All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.apache.commons.geometry.spherical.twod.AbstractGreatArcConnector Maven / Gradle / Ivy

The newest version!
/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.apache.commons.geometry.spherical.twod;

import java.util.ArrayList;
import java.util.List;
import java.util.Objects;

import org.apache.commons.geometry.euclidean.internal.AbstractPathConnector;
import org.apache.commons.geometry.euclidean.threed.Vector3D;

/** Abstract class for joining collections of great arcs into connected
 * paths. This class is not thread-safe.
 */
public abstract class AbstractGreatArcConnector
    extends AbstractPathConnector {
    /** Add an arc to the connector, leaving it unconnected until a later call to
     * to {@link #connect(Iterable)} or {@link #connectAll()}.
     * @param arc arc to add
     * @see #connect(Iterable)
     * @see #connectAll()
     */
    public void add(final GreatArc arc) {
        addPathElement(new ConnectableGreatArc(arc));
    }

    /** Add a collection of arcs to the connector, leaving them unconnected
     * until a later call to {@link #connect(Iterable)} or
     * {@link #connectAll()}.
     * @param arcs arcs to add
     * @see #connect(Iterable)
     * @see #connectAll()
     * @see #add(GreatArc)
     */
    public void add(final Iterable arcs) {
        for (final GreatArc segment : arcs) {
            add(segment);
        }
    }

    /** Add a collection of arcs to the connector and attempt to connect each new
     * arc with existing ones. Connections made at this time will not be
     * overwritten by subsequent calls to this or other connection methods,
     * (eg, {@link #connectAll()}).
     *
     * 

The connector is not reset by this call. Additional arc can still be added * to the current set of paths.

* @param arcs arcs to connect * @see #connectAll() */ public void connect(final Iterable arcs) { final List newEntries = new ArrayList<>(); for (final GreatArc segment : arcs) { newEntries.add(new ConnectableGreatArc(segment)); } connectPathElements(newEntries); } /** Add the given arcs to this instance and connect all current * arc into paths. This call is equivalent to *
     *      connector.add(arcs);
     *      List<GreatArcPath> result = connector.connectAll();
     * 
* *

The connector is reset after this call. Further calls to * add or connect arcs will result in new paths being generated.

* @param arcs arcs to add * @return the connected arc paths * @see #add(Iterable) * @see #connectAll() */ public List connectAll(final Iterable arcs) { add(arcs); return connectAll(); } /** Connect all current arcs into connected paths, returning the result as a * list of arc paths. * *

The connector is reset after this call. Further calls to * add or connect arcs will result in new paths being generated.

* @return the connected line segments paths */ public List connectAll() { final List roots = computePathRoots(); final List paths = new ArrayList<>(roots.size()); for (final ConnectableGreatArc root : roots) { paths.add(toPath(root)); } return paths; } /** Convert the linked list of path elements starting at the argument * into a {@link GreatArcPath}. * @param root root of a connected path linked list * @return a great arc path representing the linked list path */ private GreatArcPath toPath(final ConnectableGreatArc root) { final GreatArcPath.Builder builder = GreatArcPath.builder(null); builder.append(root.getArc()); ConnectableGreatArc current = root.getNext(); while (current != null && current != root) { builder.append(current.getArc()); current = current.getNext(); } return builder.build(); } /** Internal class for connecting {@link GreatArc}s into {@link GreatArcPath}s. */ protected static class ConnectableGreatArc extends AbstractPathConnector.ConnectableElement { /** Segment start point. This will be used to connect to other path elements. */ private final Point2S start; /** Great arc for this instance. */ private final GreatArc arc; /** Create a new instance with the given start point. This constructor is * intended only for performing searches for other path elements. * @param start start point */ public ConnectableGreatArc(final Point2S start) { this(start, null); } /** Create a new instance from the given arc. * @param arc arc for the instance */ public ConnectableGreatArc(final GreatArc arc) { this(arc.getStartPoint(), arc); } /** Create a new instance with the given start point and arc. * @param start start point * @param arc arc for the instance */ private ConnectableGreatArc(final Point2S start, final GreatArc arc) { this.start = start; this.arc = arc; } /** Get the arc for the instance. * @return the arc for the instance */ public GreatArc getArc() { return arc; } /** {@inheritDoc} */ @Override public boolean hasStart() { return start != null; } /** {@inheritDoc} */ @Override public boolean hasEnd() { return arc.getEndPoint() != null; } /** {@inheritDoc} */ @Override public boolean endPointsEq(final ConnectableGreatArc other) { if (hasEnd() && other.hasEnd()) { return arc.getEndPoint() .eq(other.arc.getEndPoint(), arc.getCircle().getPrecision()); } return false; } /** Return true if this instance has a size equivalent to zero. * @return true if this instance has a size equivalent to zero. */ public boolean hasZeroSize() { return arc != null && arc.getCircle().getPrecision().eqZero(arc.getSize()); } /** {@inheritDoc} */ @Override public boolean canConnectTo(final ConnectableGreatArc next) { final Point2S end = arc.getEndPoint(); final Point2S nextStart = next.start; return end != null && nextStart != null && end.eq(nextStart, arc.getCircle().getPrecision()); } /** {@inheritDoc} */ @Override public double getRelativeAngle(final ConnectableGreatArc other) { return arc.getCircle().angle(other.getArc().getCircle()); } /** {@inheritDoc} */ @Override public ConnectableGreatArc getConnectionSearchKey() { return new ConnectableGreatArc(arc.getEndPoint()); } /** {@inheritDoc} */ @Override public boolean shouldContinueConnectionSearch(final ConnectableGreatArc candidate, final boolean ascending) { if (candidate.hasStart()) { final double candidatePolar = candidate.getArc().getStartPoint().getPolar(); final double thisPolar = arc.getEndPoint().getPolar(); final int cmp = arc.getCircle().getPrecision().compare(candidatePolar, thisPolar); return ascending ? cmp <= 0 : cmp >= 0; } return true; } /** {@inheritDoc} */ @Override public int compareTo(final ConnectableGreatArc other) { int cmp = Point2S.POLAR_AZIMUTH_ASCENDING_ORDER.compare(start, other.start); if (cmp == 0) { // sort entries without arcs before ones with arcs final boolean thisHasArc = arc != null; final boolean otherHasArc = other.arc != null; cmp = Boolean.compare(thisHasArc, otherHasArc); if (cmp == 0 && thisHasArc) { // place point-like segments before ones with non-zero length cmp = Boolean.compare(this.hasZeroSize(), other.hasZeroSize()); if (cmp == 0) { // sort by circle pole cmp = Vector3D.COORDINATE_ASCENDING_ORDER.compare( arc.getCircle().getPole(), other.arc.getCircle().getPole()); } } } return cmp; } /** {@inheritDoc} */ @Override public int hashCode() { return Objects.hash(start, arc); } /** {@inheritDoc} */ @Override public boolean equals(final Object obj) { if (this == obj) { return true; } if (obj == null || !this.getClass().equals(obj.getClass())) { return false; } final ConnectableGreatArc other = (ConnectableGreatArc) obj; return Objects.equals(this.start, other.start) && Objects.equals(this.arc, other.arc); } /** {@inheritDoc} */ @Override protected ConnectableGreatArc getSelf() { return this; } } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy