http://git-wip-us.apache.org/repos/asf/commons-math/blob/a7b4803f/src/main/java/org/apache/commons/math3/geometry/spherical/oned/Arc.java ---------------------------------------------------------------------- diff --git a/src/main/java/org/apache/commons/math3/geometry/spherical/oned/Arc.java b/src/main/java/org/apache/commons/math3/geometry/spherical/oned/Arc.java deleted file mode 100644 index af0388e..0000000 --- a/src/main/java/org/apache/commons/math3/geometry/spherical/oned/Arc.java +++ /dev/null @@ -1,132 +0,0 @@ -/* - * 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.math3.geometry.spherical.oned; - -import org.apache.commons.math3.exception.NumberIsTooLargeException; -import org.apache.commons.math3.exception.util.LocalizedFormats; -import org.apache.commons.math3.geometry.partitioning.Region.Location; -import org.apache.commons.math3.util.FastMath; -import org.apache.commons.math3.util.MathUtils; -import org.apache.commons.math3.util.Precision; - - -/** This class represents an arc on a circle. - * @see ArcsSet - * @since 3.3 - */ -public class Arc { - - /** The lower angular bound of the arc. */ - private final double lower; - - /** The upper angular bound of the arc. */ - private final double upper; - - /** Middle point of the arc. */ - private final double middle; - - /** Tolerance below which angles are considered identical. */ - private final double tolerance; - - /** Simple constructor. - * <p> - * If either {@code lower} is equals to {@code upper} or - * the interval exceeds \( 2 \pi \), the arc is considered - * to be the full circle and its initial defining boundaries - * will be forgotten. {@code lower} is not allowed to be - * greater than {@code upper} (an exception is thrown in this case). - * {@code lower} will be canonicalized between 0 and \( 2 \pi \), and - * upper shifted accordingly, so the {@link #getInf()} and {@link #getSup()} - * may not return the value used at instance construction. - * </p> - * @param lower lower angular bound of the arc - * @param upper upper angular bound of the arc - * @param tolerance tolerance below which angles are considered identical - * @exception NumberIsTooLargeException if lower is greater than upper - */ - public Arc(final double lower, final double upper, final double tolerance) - throws NumberIsTooLargeException { - this.tolerance = tolerance; - if (Precision.equals(lower, upper, 0) || (upper - lower) >= MathUtils.TWO_PI) { - // the arc must cover the whole circle - this.lower = 0; - this.upper = MathUtils.TWO_PI; - this.middle = FastMath.PI; - } else if (lower <= upper) { - this.lower = MathUtils.normalizeAngle(lower, FastMath.PI); - this.upper = this.lower + (upper - lower); - this.middle = 0.5 * (this.lower + this.upper); - } else { - throw new NumberIsTooLargeException(LocalizedFormats.ENDPOINTS_NOT_AN_INTERVAL, - lower, upper, true); - } - } - - /** Get the lower angular bound of the arc. - * @return lower angular bound of the arc, - * always between 0 and \( 2 \pi \) - */ - public double getInf() { - return lower; - } - - /** Get the upper angular bound of the arc. - * @return upper angular bound of the arc, - * always between {@link #getInf()} and {@link #getInf()} \( + 2 \pi \) - */ - public double getSup() { - return upper; - } - - /** Get the angular size of the arc. - * @return angular size of the arc - */ - public double getSize() { - return upper - lower; - } - - /** Get the barycenter of the arc. - * @return barycenter of the arc - */ - public double getBarycenter() { - return middle; - } - - /** Get the tolerance below which angles are considered identical. - * @return tolerance below which angles are considered identical - */ - public double getTolerance() { - return tolerance; - } - - /** Check a point with respect to the arc. - * @param point point to check - * @return a code representing the point status: either {@link - * Location#INSIDE}, {@link Location#OUTSIDE} or {@link Location#BOUNDARY} - */ - public Location checkPoint(final double point) { - final double normalizedPoint = MathUtils.normalizeAngle(point, middle); - if (normalizedPoint < lower - tolerance || normalizedPoint > upper + tolerance) { - return Location.OUTSIDE; - } else if (normalizedPoint > lower + tolerance && normalizedPoint < upper - tolerance) { - return Location.INSIDE; - } else { - return (getSize() >= MathUtils.TWO_PI - tolerance) ? Location.INSIDE : Location.BOUNDARY; - } - } - -}
http://git-wip-us.apache.org/repos/asf/commons-math/blob/a7b4803f/src/main/java/org/apache/commons/math3/geometry/spherical/oned/ArcsSet.java ---------------------------------------------------------------------- diff --git a/src/main/java/org/apache/commons/math3/geometry/spherical/oned/ArcsSet.java b/src/main/java/org/apache/commons/math3/geometry/spherical/oned/ArcsSet.java deleted file mode 100644 index 5c03150..0000000 --- a/src/main/java/org/apache/commons/math3/geometry/spherical/oned/ArcsSet.java +++ /dev/null @@ -1,962 +0,0 @@ -/* - * 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.math3.geometry.spherical.oned; - -import java.util.ArrayList; -import java.util.Collection; -import java.util.Iterator; -import java.util.List; -import java.util.NoSuchElementException; - -import org.apache.commons.math3.exception.MathIllegalArgumentException; -import org.apache.commons.math3.exception.MathInternalError; -import org.apache.commons.math3.exception.NumberIsTooLargeException; -import org.apache.commons.math3.exception.util.LocalizedFormats; -import org.apache.commons.math3.geometry.Point; -import org.apache.commons.math3.geometry.partitioning.AbstractRegion; -import org.apache.commons.math3.geometry.partitioning.BSPTree; -import org.apache.commons.math3.geometry.partitioning.BoundaryProjection; -import org.apache.commons.math3.geometry.partitioning.Side; -import org.apache.commons.math3.geometry.partitioning.SubHyperplane; -import org.apache.commons.math3.util.FastMath; -import org.apache.commons.math3.util.MathUtils; -import org.apache.commons.math3.util.Precision; - -/** This class represents a region of a circle: a set of arcs. - * <p> - * Note that due to the wrapping around \(2 \pi\), barycenter is - * ill-defined here. It was defined only in order to fulfill - * the requirements of the {@link - * org.apache.commons.math3.geometry.partitioning.Region Region} - * interface, but its use is discouraged. - * </p> - * @since 3.3 - */ -public class ArcsSet extends AbstractRegion<Sphere1D, Sphere1D> implements Iterable<double[]> { - - /** Build an arcs set representing the whole circle. - * @param tolerance tolerance below which close sub-arcs are merged together - */ - public ArcsSet(final double tolerance) { - super(tolerance); - } - - /** Build an arcs set corresponding to a single arc. - * <p> - * If either {@code lower} is equals to {@code upper} or - * the interval exceeds \( 2 \pi \), the arc is considered - * to be the full circle and its initial defining boundaries - * will be forgotten. {@code lower} is not allowed to be greater - * than {@code upper} (an exception is thrown in this case). - * </p> - * @param lower lower bound of the arc - * @param upper upper bound of the arc - * @param tolerance tolerance below which close sub-arcs are merged together - * @exception NumberIsTooLargeException if lower is greater than upper - */ - public ArcsSet(final double lower, final double upper, final double tolerance) - throws NumberIsTooLargeException { - super(buildTree(lower, upper, tolerance), tolerance); - } - - /** Build an arcs set from an inside/outside BSP tree. - * <p>The leaf nodes of the BSP tree <em>must</em> have a - * {@code Boolean} attribute representing the inside status of - * the corresponding cell (true for inside cells, false for outside - * cells). In order to avoid building too many small objects, it is - * recommended to use the predefined constants - * {@code Boolean.TRUE} and {@code Boolean.FALSE}</p> - * @param tree inside/outside BSP tree representing the arcs set - * @param tolerance tolerance below which close sub-arcs are merged together - * @exception InconsistentStateAt2PiWrapping if the tree leaf nodes are not - * consistent across the \( 0, 2 \pi \) crossing - */ - public ArcsSet(final BSPTree<Sphere1D> tree, final double tolerance) - throws InconsistentStateAt2PiWrapping { - super(tree, tolerance); - check2PiConsistency(); - } - - /** Build an arcs set from a Boundary REPresentation (B-rep). - * <p>The boundary is provided as a collection of {@link - * SubHyperplane sub-hyperplanes}. Each sub-hyperplane has the - * interior part of the region on its minus side and the exterior on - * its plus side.</p> - * <p>The boundary elements can be in any order, and can form - * several non-connected sets (like for example polygons with holes - * or a set of disjoints polyhedrons considered as a whole). In - * fact, the elements do not even need to be connected together - * (their topological connections are not used here). However, if the - * boundary does not really separate an inside open from an outside - * open (open having here its topological meaning), then subsequent - * calls to the {@link - * org.apache.commons.math3.geometry.partitioning.Region#checkPoint(org.apache.commons.math3.geometry.Point) - * checkPoint} method will not be meaningful anymore.</p> - * <p>If the boundary is empty, the region will represent the whole - * space.</p> - * @param boundary collection of boundary elements - * @param tolerance tolerance below which close sub-arcs are merged together - * @exception InconsistentStateAt2PiWrapping if the tree leaf nodes are not - * consistent across the \( 0, 2 \pi \) crossing - */ - public ArcsSet(final Collection<SubHyperplane<Sphere1D>> boundary, final double tolerance) - throws InconsistentStateAt2PiWrapping { - super(boundary, tolerance); - check2PiConsistency(); - } - - /** Build an inside/outside tree representing a single arc. - * @param lower lower angular bound of the arc - * @param upper upper angular bound of the arc - * @param tolerance tolerance below which close sub-arcs are merged together - * @return the built tree - * @exception NumberIsTooLargeException if lower is greater than upper - */ - private static BSPTree<Sphere1D> buildTree(final double lower, final double upper, - final double tolerance) - throws NumberIsTooLargeException { - - if (Precision.equals(lower, upper, 0) || (upper - lower) >= MathUtils.TWO_PI) { - // the tree must cover the whole circle - return new BSPTree<Sphere1D>(Boolean.TRUE); - } else if (lower > upper) { - throw new NumberIsTooLargeException(LocalizedFormats.ENDPOINTS_NOT_AN_INTERVAL, - lower, upper, true); - } - - // this is a regular arc, covering only part of the circle - final double normalizedLower = MathUtils.normalizeAngle(lower, FastMath.PI); - final double normalizedUpper = normalizedLower + (upper - lower); - final SubHyperplane<Sphere1D> lowerCut = - new LimitAngle(new S1Point(normalizedLower), false, tolerance).wholeHyperplane(); - - if (normalizedUpper <= MathUtils.TWO_PI) { - // simple arc starting after 0 and ending before 2 \pi - final SubHyperplane<Sphere1D> upperCut = - new LimitAngle(new S1Point(normalizedUpper), true, tolerance).wholeHyperplane(); - return new BSPTree<Sphere1D>(lowerCut, - new BSPTree<Sphere1D>(Boolean.FALSE), - new BSPTree<Sphere1D>(upperCut, - new BSPTree<Sphere1D>(Boolean.FALSE), - new BSPTree<Sphere1D>(Boolean.TRUE), - null), - null); - } else { - // arc wrapping around 2 \pi - final SubHyperplane<Sphere1D> upperCut = - new LimitAngle(new S1Point(normalizedUpper - MathUtils.TWO_PI), true, tolerance).wholeHyperplane(); - return new BSPTree<Sphere1D>(lowerCut, - new BSPTree<Sphere1D>(upperCut, - new BSPTree<Sphere1D>(Boolean.FALSE), - new BSPTree<Sphere1D>(Boolean.TRUE), - null), - new BSPTree<Sphere1D>(Boolean.TRUE), - null); - } - - } - - /** Check consistency. - * @exception InconsistentStateAt2PiWrapping if the tree leaf nodes are not - * consistent across the \( 0, 2 \pi \) crossing - */ - private void check2PiConsistency() throws InconsistentStateAt2PiWrapping { - - // start search at the tree root - BSPTree<Sphere1D> root = getTree(false); - if (root.getCut() == null) { - return; - } - - // find the inside/outside state before the smallest internal node - final Boolean stateBefore = (Boolean) getFirstLeaf(root).getAttribute(); - - // find the inside/outside state after the largest internal node - final Boolean stateAfter = (Boolean) getLastLeaf(root).getAttribute(); - - if (stateBefore ^ stateAfter) { - throw new InconsistentStateAt2PiWrapping(); - } - - } - - /** Get the first leaf node of a tree. - * @param root tree root - * @return first leaf node (i.e. node corresponding to the region just after 0.0 radians) - */ - private BSPTree<Sphere1D> getFirstLeaf(final BSPTree<Sphere1D> root) { - - if (root.getCut() == null) { - return root; - } - - // find the smallest internal node - BSPTree<Sphere1D> smallest = null; - for (BSPTree<Sphere1D> n = root; n != null; n = previousInternalNode(n)) { - smallest = n; - } - - return leafBefore(smallest); - - } - - /** Get the last leaf node of a tree. - * @param root tree root - * @return last leaf node (i.e. node corresponding to the region just before \( 2 \pi \) radians) - */ - private BSPTree<Sphere1D> getLastLeaf(final BSPTree<Sphere1D> root) { - - if (root.getCut() == null) { - return root; - } - - // find the largest internal node - BSPTree<Sphere1D> largest = null; - for (BSPTree<Sphere1D> n = root; n != null; n = nextInternalNode(n)) { - largest = n; - } - - return leafAfter(largest); - - } - - /** Get the node corresponding to the first arc start. - * @return smallest internal node (i.e. first after 0.0 radians, in trigonometric direction), - * or null if there are no internal nodes (i.e. the set is either empty or covers the full circle) - */ - private BSPTree<Sphere1D> getFirstArcStart() { - - // start search at the tree root - BSPTree<Sphere1D> node = getTree(false); - if (node.getCut() == null) { - return null; - } - - // walk tree until we find the smallest internal node - node = getFirstLeaf(node).getParent(); - - // walk tree until we find an arc start - while (node != null && !isArcStart(node)) { - node = nextInternalNode(node); - } - - return node; - - } - - /** Check if an internal node corresponds to the start angle of an arc. - * @param node internal node to check - * @return true if the node corresponds to the start angle of an arc - */ - private boolean isArcStart(final BSPTree<Sphere1D> node) { - - if ((Boolean) leafBefore(node).getAttribute()) { - // it has an inside cell before it, it may end an arc but not start it - return false; - } - - if (!(Boolean) leafAfter(node).getAttribute()) { - // it has an outside cell after it, it is a dummy cut away from real arcs - return false; - } - - // the cell has an outside before and an inside after it - // it is the start of an arc - return true; - - } - - /** Check if an internal node corresponds to the end angle of an arc. - * @param node internal node to check - * @return true if the node corresponds to the end angle of an arc - */ - private boolean isArcEnd(final BSPTree<Sphere1D> node) { - - if (!(Boolean) leafBefore(node).getAttribute()) { - // it has an outside cell before it, it may start an arc but not end it - return false; - } - - if ((Boolean) leafAfter(node).getAttribute()) { - // it has an inside cell after it, it is a dummy cut in the middle of an arc - return false; - } - - // the cell has an inside before and an outside after it - // it is the end of an arc - return true; - - } - - /** Get the next internal node. - * @param node current internal node - * @return next internal node in trigonometric order, or null - * if this is the last internal node - */ - private BSPTree<Sphere1D> nextInternalNode(BSPTree<Sphere1D> node) { - - if (childAfter(node).getCut() != null) { - // the next node is in the sub-tree - return leafAfter(node).getParent(); - } - - // there is nothing left deeper in the tree, we backtrack - while (isAfterParent(node)) { - node = node.getParent(); - } - return node.getParent(); - - } - - /** Get the previous internal node. - * @param node current internal node - * @return previous internal node in trigonometric order, or null - * if this is the first internal node - */ - private BSPTree<Sphere1D> previousInternalNode(BSPTree<Sphere1D> node) { - - if (childBefore(node).getCut() != null) { - // the next node is in the sub-tree - return leafBefore(node).getParent(); - } - - // there is nothing left deeper in the tree, we backtrack - while (isBeforeParent(node)) { - node = node.getParent(); - } - return node.getParent(); - - } - - /** Find the leaf node just before an internal node. - * @param node internal node at which the sub-tree starts - * @return leaf node just before the internal node - */ - private BSPTree<Sphere1D> leafBefore(BSPTree<Sphere1D> node) { - - node = childBefore(node); - while (node.getCut() != null) { - node = childAfter(node); - } - - return node; - - } - - /** Find the leaf node just after an internal node. - * @param node internal node at which the sub-tree starts - * @return leaf node just after the internal node - */ - private BSPTree<Sphere1D> leafAfter(BSPTree<Sphere1D> node) { - - node = childAfter(node); - while (node.getCut() != null) { - node = childBefore(node); - } - - return node; - - } - - /** Check if a node is the child before its parent in trigonometric order. - * @param node child node considered - * @return true is the node has a parent end is before it in trigonometric order - */ - private boolean isBeforeParent(final BSPTree<Sphere1D> node) { - final BSPTree<Sphere1D> parent = node.getParent(); - if (parent == null) { - return false; - } else { - return node == childBefore(parent); - } - } - - /** Check if a node is the child after its parent in trigonometric order. - * @param node child node considered - * @return true is the node has a parent end is after it in trigonometric order - */ - private boolean isAfterParent(final BSPTree<Sphere1D> node) { - final BSPTree<Sphere1D> parent = node.getParent(); - if (parent == null) { - return false; - } else { - return node == childAfter(parent); - } - } - - /** Find the child node just before an internal node. - * @param node internal node at which the sub-tree starts - * @return child node just before the internal node - */ - private BSPTree<Sphere1D> childBefore(BSPTree<Sphere1D> node) { - if (isDirect(node)) { - // smaller angles are on minus side, larger angles are on plus side - return node.getMinus(); - } else { - // smaller angles are on plus side, larger angles are on minus side - return node.getPlus(); - } - } - - /** Find the child node just after an internal node. - * @param node internal node at which the sub-tree starts - * @return child node just after the internal node - */ - private BSPTree<Sphere1D> childAfter(BSPTree<Sphere1D> node) { - if (isDirect(node)) { - // smaller angles are on minus side, larger angles are on plus side - return node.getPlus(); - } else { - // smaller angles are on plus side, larger angles are on minus side - return node.getMinus(); - } - } - - /** Check if an internal node has a direct limit angle. - * @param node internal node to check - * @return true if the limit angle is direct - */ - private boolean isDirect(final BSPTree<Sphere1D> node) { - return ((LimitAngle) node.getCut().getHyperplane()).isDirect(); - } - - /** Get the limit angle of an internal node. - * @param node internal node to check - * @return limit angle - */ - private double getAngle(final BSPTree<Sphere1D> node) { - return ((LimitAngle) node.getCut().getHyperplane()).getLocation().getAlpha(); - } - - /** {@inheritDoc} */ - @Override - public ArcsSet buildNew(final BSPTree<Sphere1D> tree) { - return new ArcsSet(tree, getTolerance()); - } - - /** {@inheritDoc} */ - @Override - protected void computeGeometricalProperties() { - if (getTree(false).getCut() == null) { - setBarycenter(S1Point.NaN); - setSize(((Boolean) getTree(false).getAttribute()) ? MathUtils.TWO_PI : 0); - } else { - double size = 0.0; - double sum = 0.0; - for (final double[] a : this) { - final double length = a[1] - a[0]; - size += length; - sum += length * (a[0] + a[1]); - } - setSize(size); - if (Precision.equals(size, MathUtils.TWO_PI, 0)) { - setBarycenter(S1Point.NaN); - } else if (size >= Precision.SAFE_MIN) { - setBarycenter(new S1Point(sum / (2 * size))); - } else { - final LimitAngle limit = (LimitAngle) getTree(false).getCut().getHyperplane(); - setBarycenter(limit.getLocation()); - } - } - } - - /** {@inheritDoc} - * @since 3.3 - */ - @Override - public BoundaryProjection<Sphere1D> projectToBoundary(final Point<Sphere1D> point) { - - // get position of test point - final double alpha = ((S1Point) point).getAlpha(); - - boolean wrapFirst = false; - double first = Double.NaN; - double previous = Double.NaN; - for (final double[] a : this) { - - if (Double.isNaN(first)) { - // remember the first angle in case we need it later - first = a[0]; - } - - if (!wrapFirst) { - if (alpha < a[0]) { - // the test point lies between the previous and the current arcs - // offset will be positive - if (Double.isNaN(previous)) { - // we need to wrap around the circle - wrapFirst = true; - } else { - final double previousOffset = alpha - previous; - final double currentOffset = a[0] - alpha; - if (previousOffset < currentOffset) { - return new BoundaryProjection<Sphere1D>(point, new S1Point(previous), previousOffset); - } else { - return new BoundaryProjection<Sphere1D>(point, new S1Point(a[0]), currentOffset); - } - } - } else if (alpha <= a[1]) { - // the test point lies within the current arc - // offset will be negative - final double offset0 = a[0] - alpha; - final double offset1 = alpha - a[1]; - if (offset0 < offset1) { - return new BoundaryProjection<Sphere1D>(point, new S1Point(a[1]), offset1); - } else { - return new BoundaryProjection<Sphere1D>(point, new S1Point(a[0]), offset0); - } - } - } - previous = a[1]; - } - - if (Double.isNaN(previous)) { - - // there are no points at all in the arcs set - return new BoundaryProjection<Sphere1D>(point, null, MathUtils.TWO_PI); - - } else { - - // the test point if before first arc and after last arc, - // somewhere around the 0/2 \pi crossing - if (wrapFirst) { - // the test point is between 0 and first - final double previousOffset = alpha - (previous - MathUtils.TWO_PI); - final double currentOffset = first - alpha; - if (previousOffset < currentOffset) { - return new BoundaryProjection<Sphere1D>(point, new S1Point(previous), previousOffset); - } else { - return new BoundaryProjection<Sphere1D>(point, new S1Point(first), currentOffset); - } - } else { - // the test point is between last and 2\pi - final double previousOffset = alpha - previous; - final double currentOffset = first + MathUtils.TWO_PI - alpha; - if (previousOffset < currentOffset) { - return new BoundaryProjection<Sphere1D>(point, new S1Point(previous), previousOffset); - } else { - return new BoundaryProjection<Sphere1D>(point, new S1Point(first), currentOffset); - } - } - - } - - } - - /** Build an ordered list of arcs representing the instance. - * <p>This method builds this arcs set as an ordered list of - * {@link Arc Arc} elements. An empty tree will build an empty list - * while a tree representing the whole circle will build a one - * element list with bounds set to \( 0 and 2 \pi \).</p> - * @return a new ordered list containing {@link Arc Arc} elements - */ - public List<Arc> asList() { - final List<Arc> list = new ArrayList<Arc>(); - for (final double[] a : this) { - list.add(new Arc(a[0], a[1], getTolerance())); - } - return list; - } - - /** {@inheritDoc} - * <p> - * The iterator returns the limit angles pairs of sub-arcs in trigonometric order. - * </p> - * <p> - * The iterator does <em>not</em> support the optional {@code remove} operation. - * </p> - */ - public Iterator<double[]> iterator() { - return new SubArcsIterator(); - } - - /** Local iterator for sub-arcs. */ - private class SubArcsIterator implements Iterator<double[]> { - - /** Start of the first arc. */ - private final BSPTree<Sphere1D> firstStart; - - /** Current node. */ - private BSPTree<Sphere1D> current; - - /** Sub-arc no yet returned. */ - private double[] pending; - - /** Simple constructor. - */ - public SubArcsIterator() { - - firstStart = getFirstArcStart(); - current = firstStart; - - if (firstStart == null) { - // all the leaf tree nodes share the same inside/outside status - if ((Boolean) getFirstLeaf(getTree(false)).getAttribute()) { - // it is an inside node, it represents the full circle - pending = new double[] { - 0, MathUtils.TWO_PI - }; - } else { - pending = null; - } - } else { - selectPending(); - } - } - - /** Walk the tree to select the pending sub-arc. - */ - private void selectPending() { - - // look for the start of the arc - BSPTree<Sphere1D> start = current; - while (start != null && !isArcStart(start)) { - start = nextInternalNode(start); - } - - if (start == null) { - // we have exhausted the iterator - current = null; - pending = null; - return; - } - - // look for the end of the arc - BSPTree<Sphere1D> end = start; - while (end != null && !isArcEnd(end)) { - end = nextInternalNode(end); - } - - if (end != null) { - - // we have identified the arc - pending = new double[] { - getAngle(start), getAngle(end) - }; - - // prepare search for next arc - current = end; - - } else { - - // the final arc wraps around 2\pi, its end is before the first start - end = firstStart; - while (end != null && !isArcEnd(end)) { - end = previousInternalNode(end); - } - if (end == null) { - // this should never happen - throw new MathInternalError(); - } - - // we have identified the last arc - pending = new double[] { - getAngle(start), getAngle(end) + MathUtils.TWO_PI - }; - - // there won't be any other arcs - current = null; - - } - - } - - /** {@inheritDoc} */ - public boolean hasNext() { - return pending != null; - } - - /** {@inheritDoc} */ - public double[] next() { - if (pending == null) { - throw new NoSuchElementException(); - } - final double[] next = pending; - selectPending(); - return next; - } - - /** {@inheritDoc} */ - public void remove() { - throw new UnsupportedOperationException(); - } - - } - - /** Compute the relative position of the instance with respect - * to an arc. - * <p> - * The {@link Side#MINUS} side of the arc is the one covered by the arc. - * </p> - * @param arc arc to check instance against - * @return one of {@link Side#PLUS}, {@link Side#MINUS}, {@link Side#BOTH} - * or {@link Side#HYPER} - */ - public Side side(final Arc arc) { - - final double reference = FastMath.PI + arc.getInf(); - final double arcLength = arc.getSup() - arc.getInf(); - - boolean inMinus = false; - boolean inPlus = false; - for (final double[] a : this) { - final double syncedStart = MathUtils.normalizeAngle(a[0], reference) - arc.getInf(); - final double arcOffset = a[0] - syncedStart; - final double syncedEnd = a[1] - arcOffset; - if (syncedStart <= arcLength - getTolerance() || syncedEnd >= MathUtils.TWO_PI + getTolerance()) { - inMinus = true; - } - if (syncedEnd >= arcLength + getTolerance()) { - inPlus = true; - } - } - - if (inMinus) { - if (inPlus) { - return Side.BOTH; - } else { - return Side.MINUS; - } - } else { - if (inPlus) { - return Side.PLUS; - } else { - return Side.HYPER; - } - } - - } - - /** Split the instance in two parts by an arc. - * @param arc splitting arc - * @return an object containing both the part of the instance - * on the plus side of the arc and the part of the - * instance on the minus side of the arc - */ - public Split split(final Arc arc) { - - final List<Double> minus = new ArrayList<Double>(); - final List<Double> plus = new ArrayList<Double>(); - - final double reference = FastMath.PI + arc.getInf(); - final double arcLength = arc.getSup() - arc.getInf(); - - for (final double[] a : this) { - final double syncedStart = MathUtils.normalizeAngle(a[0], reference) - arc.getInf(); - final double arcOffset = a[0] - syncedStart; - final double syncedEnd = a[1] - arcOffset; - if (syncedStart < arcLength) { - // the start point a[0] is in the minus part of the arc - minus.add(a[0]); - if (syncedEnd > arcLength) { - // the end point a[1] is past the end of the arc - // so we leave the minus part and enter the plus part - final double minusToPlus = arcLength + arcOffset; - minus.add(minusToPlus); - plus.add(minusToPlus); - if (syncedEnd > MathUtils.TWO_PI) { - // in fact the end point a[1] goes far enough that we - // leave the plus part of the arc and enter the minus part again - final double plusToMinus = MathUtils.TWO_PI + arcOffset; - plus.add(plusToMinus); - minus.add(plusToMinus); - minus.add(a[1]); - } else { - // the end point a[1] is in the plus part of the arc - plus.add(a[1]); - } - } else { - // the end point a[1] is in the minus part of the arc - minus.add(a[1]); - } - } else { - // the start point a[0] is in the plus part of the arc - plus.add(a[0]); - if (syncedEnd > MathUtils.TWO_PI) { - // the end point a[1] wraps around to the start of the arc - // so we leave the plus part and enter the minus part - final double plusToMinus = MathUtils.TWO_PI + arcOffset; - plus.add(plusToMinus); - minus.add(plusToMinus); - if (syncedEnd > MathUtils.TWO_PI + arcLength) { - // in fact the end point a[1] goes far enough that we - // leave the minus part of the arc and enter the plus part again - final double minusToPlus = MathUtils.TWO_PI + arcLength + arcOffset; - minus.add(minusToPlus); - plus.add(minusToPlus); - plus.add(a[1]); - } else { - // the end point a[1] is in the minus part of the arc - minus.add(a[1]); - } - } else { - // the end point a[1] is in the plus part of the arc - plus.add(a[1]); - } - } - } - - return new Split(createSplitPart(plus), createSplitPart(minus)); - - } - - /** Add an arc limit to a BSP tree under construction. - * @param tree BSP tree under construction - * @param alpha arc limit - * @param isStart if true, the limit is the start of an arc - */ - private void addArcLimit(final BSPTree<Sphere1D> tree, final double alpha, final boolean isStart) { - - final LimitAngle limit = new LimitAngle(new S1Point(alpha), !isStart, getTolerance()); - final BSPTree<Sphere1D> node = tree.getCell(limit.getLocation(), getTolerance()); - if (node.getCut() != null) { - // this should never happen - throw new MathInternalError(); - } - - node.insertCut(limit); - node.setAttribute(null); - node.getPlus().setAttribute(Boolean.FALSE); - node.getMinus().setAttribute(Boolean.TRUE); - - } - - /** Create a split part. - * <p> - * As per construction, the list of limit angles is known to have - * an even number of entries, with start angles at even indices and - * end angles at odd indices. - * </p> - * @param limits limit angles of the split part - * @return split part (may be null) - */ - private ArcsSet createSplitPart(final List<Double> limits) { - if (limits.isEmpty()) { - return null; - } else { - - // collapse close limit angles - for (int i = 0; i < limits.size(); ++i) { - final int j = (i + 1) % limits.size(); - final double lA = limits.get(i); - final double lB = MathUtils.normalizeAngle(limits.get(j), lA); - if (FastMath.abs(lB - lA) <= getTolerance()) { - // the two limits are too close to each other, we remove both of them - if (j > 0) { - // regular case, the two entries are consecutive ones - limits.remove(j); - limits.remove(i); - i = i - 1; - } else { - // special case, i the the last entry and j is the first entry - // we have wrapped around list end - final double lEnd = limits.remove(limits.size() - 1); - final double lStart = limits.remove(0); - if (limits.isEmpty()) { - // the ends were the only limits, is it a full circle or an empty circle? - if (lEnd - lStart > FastMath.PI) { - // it was full circle - return new ArcsSet(new BSPTree<Sphere1D>(Boolean.TRUE), getTolerance()); - } else { - // it was an empty circle - return null; - } - } else { - // we have removed the first interval start, so our list - // currently starts with an interval end, which is wrong - // we need to move this interval end to the end of the list - limits.add(limits.remove(0) + MathUtils.TWO_PI); - } - } - } - } - - // build the tree by adding all angular sectors - BSPTree<Sphere1D> tree = new BSPTree<Sphere1D>(Boolean.FALSE); - for (int i = 0; i < limits.size() - 1; i += 2) { - addArcLimit(tree, limits.get(i), true); - addArcLimit(tree, limits.get(i + 1), false); - } - - if (tree.getCut() == null) { - // we did not insert anything - return null; - } - - return new ArcsSet(tree, getTolerance()); - - } - } - - /** Class holding the results of the {@link #split split} method. - */ - public static class Split { - - /** Part of the arcs set on the plus side of the splitting arc. */ - private final ArcsSet plus; - - /** Part of the arcs set on the minus side of the splitting arc. */ - private final ArcsSet minus; - - /** Build a Split from its parts. - * @param plus part of the arcs set on the plus side of the - * splitting arc - * @param minus part of the arcs set on the minus side of the - * splitting arc - */ - private Split(final ArcsSet plus, final ArcsSet minus) { - this.plus = plus; - this.minus = minus; - } - - /** Get the part of the arcs set on the plus side of the splitting arc. - * @return part of the arcs set on the plus side of the splitting arc - */ - public ArcsSet getPlus() { - return plus; - } - - /** Get the part of the arcs set on the minus side of the splitting arc. - * @return part of the arcs set on the minus side of the splitting arc - */ - public ArcsSet getMinus() { - return minus; - } - - } - - /** Specialized exception for inconsistent BSP tree state inconsistency. - * <p> - * This exception is thrown at {@link ArcsSet} construction time when the - * {@link org.apache.commons.math3.geometry.partitioning.Region.Location inside/outside} - * state is not consistent at the 0, \(2 \pi \) crossing. - * </p> - */ - public static class InconsistentStateAt2PiWrapping extends MathIllegalArgumentException { - - /** Serializable UID. */ - private static final long serialVersionUID = 20140107L; - - /** Simple constructor. - */ - public InconsistentStateAt2PiWrapping() { - super(LocalizedFormats.INCONSISTENT_STATE_AT_2_PI_WRAPPING); - } - - } - -} http://git-wip-us.apache.org/repos/asf/commons-math/blob/a7b4803f/src/main/java/org/apache/commons/math3/geometry/spherical/oned/LimitAngle.java ---------------------------------------------------------------------- diff --git a/src/main/java/org/apache/commons/math3/geometry/spherical/oned/LimitAngle.java b/src/main/java/org/apache/commons/math3/geometry/spherical/oned/LimitAngle.java deleted file mode 100644 index 748a142..0000000 --- a/src/main/java/org/apache/commons/math3/geometry/spherical/oned/LimitAngle.java +++ /dev/null @@ -1,127 +0,0 @@ -/* - * 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.math3.geometry.spherical.oned; - -import org.apache.commons.math3.geometry.Point; -import org.apache.commons.math3.geometry.partitioning.Hyperplane; - -/** This class represents a 1D oriented hyperplane on the circle. - * <p>An hyperplane on the 1-sphere is an angle with an orientation.</p> - * <p>Instances of this class are guaranteed to be immutable.</p> - * @since 3.3 - */ -public class LimitAngle implements Hyperplane<Sphere1D> { - - /** Angle location. */ - private S1Point location; - - /** Orientation. */ - private boolean direct; - - /** Tolerance below which angles are considered identical. */ - private final double tolerance; - - /** Simple constructor. - * @param location location of the hyperplane - * @param direct if true, the plus side of the hyperplane is towards - * angles greater than {@code location} - * @param tolerance tolerance below which angles are considered identical - */ - public LimitAngle(final S1Point location, final boolean direct, final double tolerance) { - this.location = location; - this.direct = direct; - this.tolerance = tolerance; - } - - /** Copy the instance. - * <p>Since instances are immutable, this method directly returns - * the instance.</p> - * @return the instance itself - */ - public LimitAngle copySelf() { - return this; - } - - /** {@inheritDoc} */ - public double getOffset(final Point<Sphere1D> point) { - final double delta = ((S1Point) point).getAlpha() - location.getAlpha(); - return direct ? delta : -delta; - } - - /** Check if the hyperplane orientation is direct. - * @return true if the plus side of the hyperplane is towards - * angles greater than hyperplane location - */ - public boolean isDirect() { - return direct; - } - - /** Get the reverse of the instance. - * <p>Get a limit angle with reversed orientation with respect to the - * instance. A new object is built, the instance is untouched.</p> - * @return a new limit angle, with orientation opposite to the instance orientation - */ - public LimitAngle getReverse() { - return new LimitAngle(location, !direct, tolerance); - } - - /** Build a region covering the whole hyperplane. - * <p>Since this class represent zero dimension spaces which does - * not have lower dimension sub-spaces, this method returns a dummy - * implementation of a {@link - * org.apache.commons.math3.geometry.partitioning.SubHyperplane SubHyperplane}. - * This implementation is only used to allow the {@link - * org.apache.commons.math3.geometry.partitioning.SubHyperplane - * SubHyperplane} class implementation to work properly, it should - * <em>not</em> be used otherwise.</p> - * @return a dummy sub hyperplane - */ - public SubLimitAngle wholeHyperplane() { - return new SubLimitAngle(this, null); - } - - /** Build a region covering the whole space. - * @return a region containing the instance (really an {@link - * ArcsSet IntervalsSet} instance) - */ - public ArcsSet wholeSpace() { - return new ArcsSet(tolerance); - } - - /** {@inheritDoc} */ - public boolean sameOrientationAs(final Hyperplane<Sphere1D> other) { - return !(direct ^ ((LimitAngle) other).direct); - } - - /** Get the hyperplane location on the circle. - * @return the hyperplane location - */ - public S1Point getLocation() { - return location; - } - - /** {@inheritDoc} */ - public Point<Sphere1D> project(Point<Sphere1D> point) { - return location; - } - - /** {@inheritDoc} */ - public double getTolerance() { - return tolerance; - } - -} http://git-wip-us.apache.org/repos/asf/commons-math/blob/a7b4803f/src/main/java/org/apache/commons/math3/geometry/spherical/oned/S1Point.java ---------------------------------------------------------------------- diff --git a/src/main/java/org/apache/commons/math3/geometry/spherical/oned/S1Point.java b/src/main/java/org/apache/commons/math3/geometry/spherical/oned/S1Point.java deleted file mode 100644 index 263a559..0000000 --- a/src/main/java/org/apache/commons/math3/geometry/spherical/oned/S1Point.java +++ /dev/null @@ -1,157 +0,0 @@ -/* - * 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.math3.geometry.spherical.oned; - -import org.apache.commons.math3.geometry.Point; -import org.apache.commons.math3.geometry.Space; -import org.apache.commons.math3.geometry.euclidean.twod.Vector2D; -import org.apache.commons.math3.util.FastMath; -import org.apache.commons.math3.util.MathUtils; - -/** This class represents a point on the 1-sphere. - * <p>Instances of this class are guaranteed to be immutable.</p> - * @since 3.3 - */ -public class S1Point implements Point<Sphere1D> { - - // CHECKSTYLE: stop ConstantName - /** A vector with all coordinates set to NaN. */ - public static final S1Point NaN = new S1Point(Double.NaN, Vector2D.NaN); - // CHECKSTYLE: resume ConstantName - - /** Serializable UID. */ - private static final long serialVersionUID = 20131218L; - - /** Azimuthal angle \( \alpha \). */ - private final double alpha; - - /** Corresponding 2D normalized vector. */ - private final Vector2D vector; - - /** Simple constructor. - * Build a vector from its coordinates - * @param alpha azimuthal angle \( \alpha \) - * @see #getAlpha() - */ - public S1Point(final double alpha) { - this(MathUtils.normalizeAngle(alpha, FastMath.PI), - new Vector2D(FastMath.cos(alpha), FastMath.sin(alpha))); - } - - /** Build a point from its internal components. - * @param alpha azimuthal angle \( \alpha \) - * @param vector corresponding vector - */ - private S1Point(final double alpha, final Vector2D vector) { - this.alpha = alpha; - this.vector = vector; - } - - /** Get the azimuthal angle \( \alpha \). - * @return azimuthal angle \( \alpha \) - * @see #S1Point(double) - */ - public double getAlpha() { - return alpha; - } - - /** Get the corresponding normalized vector in the 2D euclidean space. - * @return normalized vector - */ - public Vector2D getVector() { - return vector; - } - - /** {@inheritDoc} */ - public Space getSpace() { - return Sphere1D.getInstance(); - } - - /** {@inheritDoc} */ - public boolean isNaN() { - return Double.isNaN(alpha); - } - - /** {@inheritDoc} */ - public double distance(final Point<Sphere1D> point) { - return distance(this, (S1Point) point); - } - - /** Compute the distance (angular separation) between two points. - * @param p1 first vector - * @param p2 second vector - * @return the angular separation between p1 and p2 - */ - public static double distance(S1Point p1, S1Point p2) { - return Vector2D.angle(p1.vector, p2.vector); - } - - /** - * Test for the equality of two points on the 2-sphere. - * <p> - * If all coordinates of two points are exactly the same, and none are - * <code>Double.NaN</code>, the two points are considered to be equal. - * </p> - * <p> - * <code>NaN</code> coordinates are considered to affect globally the vector - * and be equals to each other - i.e, if either (or all) coordinates of the - * 2D vector are equal to <code>Double.NaN</code>, the 2D vector is equal to - * {@link #NaN}. - * </p> - * - * @param other Object to test for equality to this - * @return true if two points on the 2-sphere objects are equal, false if - * object is null, not an instance of S2Point, or - * not equal to this S2Point instance - * - */ - @Override - public boolean equals(Object other) { - - if (this == other) { - return true; - } - - if (other instanceof S1Point) { - final S1Point rhs = (S1Point) other; - if (rhs.isNaN()) { - return this.isNaN(); - } - - return alpha == rhs.alpha; - } - - return false; - - } - - /** - * Get a hashCode for the 2D vector. - * <p> - * All NaN values have the same hash code.</p> - * - * @return a hash code value for this object - */ - @Override - public int hashCode() { - if (isNaN()) { - return 542; - } - return 1759 * MathUtils.hash(alpha); - } - -} http://git-wip-us.apache.org/repos/asf/commons-math/blob/a7b4803f/src/main/java/org/apache/commons/math3/geometry/spherical/oned/Sphere1D.java ---------------------------------------------------------------------- diff --git a/src/main/java/org/apache/commons/math3/geometry/spherical/oned/Sphere1D.java b/src/main/java/org/apache/commons/math3/geometry/spherical/oned/Sphere1D.java deleted file mode 100644 index ce5c7cd..0000000 --- a/src/main/java/org/apache/commons/math3/geometry/spherical/oned/Sphere1D.java +++ /dev/null @@ -1,106 +0,0 @@ -/* - * 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.math3.geometry.spherical.oned; - -import java.io.Serializable; - -import org.apache.commons.math3.exception.MathUnsupportedOperationException; -import org.apache.commons.math3.exception.util.LocalizedFormats; -import org.apache.commons.math3.geometry.Space; - -/** - * This class implements a one-dimensional sphere (i.e. a circle). - * <p> - * We use here the topologists definition of the 1-sphere (see - * <a href="http://mathworld.wolfram.com/Sphere.html">Sphere</a> on - * MathWorld), i.e. the 1-sphere is the one-dimensional closed curve - * defined in 2D as x<sup>2</sup>+y<sup>2</sup>=1. - * </p> - * @since 3.3 - */ -public class Sphere1D implements Serializable, Space { - - /** Serializable version identifier. */ - private static final long serialVersionUID = 20131218L; - - /** Private constructor for the singleton. - */ - private Sphere1D() { - } - - /** Get the unique instance. - * @return the unique instance - */ - public static Sphere1D getInstance() { - return LazyHolder.INSTANCE; - } - - /** {@inheritDoc} */ - public int getDimension() { - return 1; - } - - /** {@inheritDoc} - * <p> - * As the 1-dimension sphere does not have proper sub-spaces, - * this method always throws a {@link NoSubSpaceException} - * </p> - * @return nothing - * @throws NoSubSpaceException in all cases - */ - public Space getSubSpace() throws NoSubSpaceException { - throw new NoSubSpaceException(); - } - - // CHECKSTYLE: stop HideUtilityClassConstructor - /** Holder for the instance. - * <p>We use here the Initialization On Demand Holder Idiom.</p> - */ - private static class LazyHolder { - /** Cached field instance. */ - private static final Sphere1D INSTANCE = new Sphere1D(); - } - // CHECKSTYLE: resume HideUtilityClassConstructor - - /** Handle deserialization of the singleton. - * @return the singleton instance - */ - private Object readResolve() { - // return the singleton instance - return LazyHolder.INSTANCE; - } - - /** Specialized exception for inexistent sub-space. - * <p> - * This exception is thrown when attempting to get the sub-space of a one-dimensional space - * </p> - */ - public static class NoSubSpaceException extends MathUnsupportedOperationException { - - /** Serializable UID. */ - private static final long serialVersionUID = 20140225L; - - /** Simple constructor. - */ - public NoSubSpaceException() { - super(LocalizedFormats.NOT_SUPPORTED_IN_DIMENSION_N, 1); - } - - } - -} http://git-wip-us.apache.org/repos/asf/commons-math/blob/a7b4803f/src/main/java/org/apache/commons/math3/geometry/spherical/oned/SubLimitAngle.java ---------------------------------------------------------------------- diff --git a/src/main/java/org/apache/commons/math3/geometry/spherical/oned/SubLimitAngle.java b/src/main/java/org/apache/commons/math3/geometry/spherical/oned/SubLimitAngle.java deleted file mode 100644 index 880a7e8..0000000 --- a/src/main/java/org/apache/commons/math3/geometry/spherical/oned/SubLimitAngle.java +++ /dev/null @@ -1,74 +0,0 @@ -/* - * 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.math3.geometry.spherical.oned; - -import org.apache.commons.math3.geometry.partitioning.AbstractSubHyperplane; -import org.apache.commons.math3.geometry.partitioning.Hyperplane; -import org.apache.commons.math3.geometry.partitioning.Region; -import org.apache.commons.math3.geometry.partitioning.Side; - -/** This class represents sub-hyperplane for {@link LimitAngle}. - * <p>Instances of this class are guaranteed to be immutable.</p> - * @since 3.3 - */ -public class SubLimitAngle extends AbstractSubHyperplane<Sphere1D, Sphere1D> { - - /** Simple constructor. - * @param hyperplane underlying hyperplane - * @param remainingRegion remaining region of the hyperplane - */ - public SubLimitAngle(final Hyperplane<Sphere1D> hyperplane, - final Region<Sphere1D> remainingRegion) { - super(hyperplane, remainingRegion); - } - - /** {@inheritDoc} */ - @Override - public double getSize() { - return 0; - } - - /** {@inheritDoc} */ - @Override - public boolean isEmpty() { - return false; - } - - /** {@inheritDoc} */ - @Override - protected AbstractSubHyperplane<Sphere1D, Sphere1D> buildNew(final Hyperplane<Sphere1D> hyperplane, - final Region<Sphere1D> remainingRegion) { - return new SubLimitAngle(hyperplane, remainingRegion); - } - - /** {@inheritDoc} */ - @Override - public Side side(final Hyperplane<Sphere1D> hyperplane) { - final double global = hyperplane.getOffset(((LimitAngle) getHyperplane()).getLocation()); - return (global < -1.0e-10) ? Side.MINUS : ((global > 1.0e-10) ? Side.PLUS : Side.HYPER); - } - - /** {@inheritDoc} */ - @Override - public SplitSubHyperplane<Sphere1D> split(final Hyperplane<Sphere1D> hyperplane) { - final double global = hyperplane.getOffset(((LimitAngle) getHyperplane()).getLocation()); - return (global < -1.0e-10) ? - new SplitSubHyperplane<Sphere1D>(null, this) : - new SplitSubHyperplane<Sphere1D>(this, null); - } - -} http://git-wip-us.apache.org/repos/asf/commons-math/blob/a7b4803f/src/main/java/org/apache/commons/math3/geometry/spherical/oned/package-info.java ---------------------------------------------------------------------- diff --git a/src/main/java/org/apache/commons/math3/geometry/spherical/oned/package-info.java b/src/main/java/org/apache/commons/math3/geometry/spherical/oned/package-info.java deleted file mode 100644 index d54bc0b..0000000 --- a/src/main/java/org/apache/commons/math3/geometry/spherical/oned/package-info.java +++ /dev/null @@ -1,30 +0,0 @@ -/* - * 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. - */ -/** - * - * <p> - * This package provides basic geometry components on the 1-sphere. - * </p> - * <p> - * We use here the topologists definition of the 1-sphere (see - * <a href="http://mathworld.wolfram.com/Sphere.html">Sphere</a> on - * MathWorld), i.e. the 1-sphere is the one-dimensional closed curve - * defined in 2D as x<sup>2</sup>+y<sup>2</sup>=1. - * </p> - * - */ -package org.apache.commons.math3.geometry.spherical.oned; http://git-wip-us.apache.org/repos/asf/commons-math/blob/a7b4803f/src/main/java/org/apache/commons/math3/geometry/spherical/twod/Circle.java ---------------------------------------------------------------------- diff --git a/src/main/java/org/apache/commons/math3/geometry/spherical/twod/Circle.java b/src/main/java/org/apache/commons/math3/geometry/spherical/twod/Circle.java deleted file mode 100644 index d6d47de..0000000 --- a/src/main/java/org/apache/commons/math3/geometry/spherical/twod/Circle.java +++ /dev/null @@ -1,326 +0,0 @@ -/* - * 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.math3.geometry.spherical.twod; - -import org.apache.commons.math3.geometry.Point; -import org.apache.commons.math3.geometry.euclidean.threed.Rotation; -import org.apache.commons.math3.geometry.euclidean.threed.Vector3D; -import org.apache.commons.math3.geometry.partitioning.Embedding; -import org.apache.commons.math3.geometry.partitioning.Hyperplane; -import org.apache.commons.math3.geometry.partitioning.SubHyperplane; -import org.apache.commons.math3.geometry.partitioning.Transform; -import org.apache.commons.math3.geometry.spherical.oned.Arc; -import org.apache.commons.math3.geometry.spherical.oned.ArcsSet; -import org.apache.commons.math3.geometry.spherical.oned.S1Point; -import org.apache.commons.math3.geometry.spherical.oned.Sphere1D; -import org.apache.commons.math3.util.FastMath; - -/** This class represents an oriented great circle on the 2-sphere. - - * <p>An oriented circle can be defined by a center point. The circle - * is the the set of points that are in the normal plan the center.</p> - - * <p>Since it is oriented the two spherical caps at its two sides are - * unambiguously identified as a left cap and a right cap. This can be - * used to identify the interior and the exterior in a simple way by - * local properties only when part of a line is used to define part of - * a spherical polygon boundary.</p> - - * @since 3.3 - */ -public class Circle implements Hyperplane<Sphere2D>, Embedding<Sphere2D, Sphere1D> { - - /** Pole or circle center. */ - private Vector3D pole; - - /** First axis in the equator plane, origin of the phase angles. */ - private Vector3D x; - - /** Second axis in the equator plane, in quadrature with respect to x. */ - private Vector3D y; - - /** Tolerance below which close sub-arcs are merged together. */ - private final double tolerance; - - /** Build a great circle from its pole. - * <p>The circle is oriented in the trigonometric direction around pole.</p> - * @param pole circle pole - * @param tolerance tolerance below which close sub-arcs are merged together - */ - public Circle(final Vector3D pole, final double tolerance) { - reset(pole); - this.tolerance = tolerance; - } - - /** Build a great circle from two non-aligned points. - * <p>The circle is oriented from first to second point using the path smaller than \( \pi \).</p> - * @param first first point contained in the great circle - * @param second second point contained in the great circle - * @param tolerance tolerance below which close sub-arcs are merged together - */ - public Circle(final S2Point first, final S2Point second, final double tolerance) { - reset(first.getVector().crossProduct(second.getVector())); - this.tolerance = tolerance; - } - - /** Build a circle from its internal components. - * <p>The circle is oriented in the trigonometric direction around center.</p> - * @param pole circle pole - * @param x first axis in the equator plane - * @param y second axis in the equator plane - * @param tolerance tolerance below which close sub-arcs are merged together - */ - private Circle(final Vector3D pole, final Vector3D x, final Vector3D y, - final double tolerance) { - this.pole = pole; - this.x = x; - this.y = y; - this.tolerance = tolerance; - } - - /** Copy constructor. - * <p>The created instance is completely independent from the - * original instance, it is a deep copy.</p> - * @param circle circle to copy - */ - public Circle(final Circle circle) { - this(circle.pole, circle.x, circle.y, circle.tolerance); - } - - /** {@inheritDoc} */ - public Circle copySelf() { - return new Circle(this); - } - - /** Reset the instance as if built from a pole. - * <p>The circle is oriented in the trigonometric direction around pole.</p> - * @param newPole circle pole - */ - public void reset(final Vector3D newPole) { - this.pole = newPole.normalize(); - this.x = newPole.orthogonal(); - this.y = Vector3D.crossProduct(newPole, x).normalize(); - } - - /** Revert the instance. - */ - public void revertSelf() { - // x remains the same - y = y.negate(); - pole = pole.negate(); - } - - /** Get the reverse of the instance. - * <p>Get a circle with reversed orientation with respect to the - * instance. A new object is built, the instance is untouched.</p> - * @return a new circle, with orientation opposite to the instance orientation - */ - public Circle getReverse() { - return new Circle(pole.negate(), x, y.negate(), tolerance); - } - - /** {@inheritDoc} */ - public Point<Sphere2D> project(Point<Sphere2D> point) { - return toSpace(toSubSpace(point)); - } - - /** {@inheritDoc} */ - public double getTolerance() { - return tolerance; - } - - /** {@inheritDoc} - * @see #getPhase(Vector3D) - */ - public S1Point toSubSpace(final Point<Sphere2D> point) { - return new S1Point(getPhase(((S2Point) point).getVector())); - } - - /** Get the phase angle of a direction. - * <p> - * The direction may not belong to the circle as the - * phase is computed for the meridian plane between the circle - * pole and the direction. - * </p> - * @param direction direction for which phase is requested - * @return phase angle of the direction around the circle - * @see #toSubSpace(Point) - */ - public double getPhase(final Vector3D direction) { - return FastMath.PI + FastMath.atan2(-direction.dotProduct(y), -direction.dotProduct(x)); - } - - /** {@inheritDoc} - * @see #getPointAt(double) - */ - public S2Point toSpace(final Point<Sphere1D> point) { - return new S2Point(getPointAt(((S1Point) point).getAlpha())); - } - - /** Get a circle point from its phase around the circle. - * @param alpha phase around the circle - * @return circle point on the sphere - * @see #toSpace(Point) - * @see #getXAxis() - * @see #getYAxis() - */ - public Vector3D getPointAt(final double alpha) { - return new Vector3D(FastMath.cos(alpha), x, FastMath.sin(alpha), y); - } - - /** Get the X axis of the circle. - * <p> - * This method returns the same value as {@link #getPointAt(double) - * getPointAt(0.0)} but it does not do any computation and always - * return the same instance. - * </p> - * @return an arbitrary x axis on the circle - * @see #getPointAt(double) - * @see #getYAxis() - * @see #getPole() - */ - public Vector3D getXAxis() { - return x; - } - - /** Get the Y axis of the circle. - * <p> - * This method returns the same value as {@link #getPointAt(double) - * getPointAt(0.5 * FastMath.PI)} but it does not do any computation and always - * return the same instance. - * </p> - * @return an arbitrary y axis point on the circle - * @see #getPointAt(double) - * @see #getXAxis() - * @see #getPole() - */ - public Vector3D getYAxis() { - return y; - } - - /** Get the pole of the circle. - * <p> - * As the circle is a great circle, the pole does <em>not</em> - * belong to it. - * </p> - * @return pole of the circle - * @see #getXAxis() - * @see #getYAxis() - */ - public Vector3D getPole() { - return pole; - } - - /** Get the arc of the instance that lies inside the other circle. - * @param other other circle - * @return arc of the instance that lies inside the other circle - */ - public Arc getInsideArc(final Circle other) { - final double alpha = getPhase(other.pole); - final double halfPi = 0.5 * FastMath.PI; - return new Arc(alpha - halfPi, alpha + halfPi, tolerance); - } - - /** {@inheritDoc} */ - public SubCircle wholeHyperplane() { - return new SubCircle(this, new ArcsSet(tolerance)); - } - - /** Build a region covering the whole space. - * @return a region containing the instance (really a {@link - * SphericalPolygonsSet SphericalPolygonsSet} instance) - */ - public SphericalPolygonsSet wholeSpace() { - return new SphericalPolygonsSet(tolerance); - } - - /** {@inheritDoc} - * @see #getOffset(Vector3D) - */ - public double getOffset(final Point<Sphere2D> point) { - return getOffset(((S2Point) point).getVector()); - } - - /** Get the offset (oriented distance) of a direction. - * <p>The offset is defined as the angular distance between the - * circle center and the direction minus the circle radius. It - * is therefore 0 on the circle, positive for directions outside of - * the cone delimited by the circle, and negative inside the cone.</p> - * @param direction direction to check - * @return offset of the direction - * @see #getOffset(Point) - */ - public double getOffset(final Vector3D direction) { - return Vector3D.angle(pole, direction) - 0.5 * FastMath.PI; - } - - /** {@inheritDoc} */ - public boolean sameOrientationAs(final Hyperplane<Sphere2D> other) { - final Circle otherC = (Circle) other; - return Vector3D.dotProduct(pole, otherC.pole) >= 0.0; - } - - /** Get a {@link org.apache.commons.math3.geometry.partitioning.Transform - * Transform} embedding a 3D rotation. - * @param rotation rotation to use - * @return a new transform that can be applied to either {@link - * Point Point}, {@link Circle Line} or {@link - * org.apache.commons.math3.geometry.partitioning.SubHyperplane - * SubHyperplane} instances - */ - public static Transform<Sphere2D, Sphere1D> getTransform(final Rotation rotation) { - return new CircleTransform(rotation); - } - - /** Class embedding a 3D rotation. */ - private static class CircleTransform implements Transform<Sphere2D, Sphere1D> { - - /** Underlying rotation. */ - private final Rotation rotation; - - /** Build a transform from a {@code Rotation}. - * @param rotation rotation to use - */ - public CircleTransform(final Rotation rotation) { - this.rotation = rotation; - } - - /** {@inheritDoc} */ - public S2Point apply(final Point<Sphere2D> point) { - return new S2Point(rotation.applyTo(((S2Point) point).getVector())); - } - - /** {@inheritDoc} */ - public Circle apply(final Hyperplane<Sphere2D> hyperplane) { - final Circle circle = (Circle) hyperplane; - return new Circle(rotation.applyTo(circle.pole), - rotation.applyTo(circle.x), - rotation.applyTo(circle.y), - circle.tolerance); - } - - /** {@inheritDoc} */ - public SubHyperplane<Sphere1D> apply(final SubHyperplane<Sphere1D> sub, - final Hyperplane<Sphere2D> original, - final Hyperplane<Sphere2D> transformed) { - // as the circle is rotated, the limit angles are rotated too - return sub; - } - - } - -} http://git-wip-us.apache.org/repos/asf/commons-math/blob/a7b4803f/src/main/java/org/apache/commons/math3/geometry/spherical/twod/Edge.java ---------------------------------------------------------------------- diff --git a/src/main/java/org/apache/commons/math3/geometry/spherical/twod/Edge.java b/src/main/java/org/apache/commons/math3/geometry/spherical/twod/Edge.java deleted file mode 100644 index a9ccb08..0000000 --- a/src/main/java/org/apache/commons/math3/geometry/spherical/twod/Edge.java +++ /dev/null @@ -1,222 +0,0 @@ -/* - * 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.math3.geometry.spherical.twod; - -import java.util.List; - -import org.apache.commons.math3.geometry.euclidean.threed.Vector3D; -import org.apache.commons.math3.geometry.spherical.oned.Arc; -import org.apache.commons.math3.util.FastMath; -import org.apache.commons.math3.util.MathUtils; - -/** Spherical polygons boundary edge. - * @see SphericalPolygonsSet#getBoundaryLoops() - * @see Vertex - * @since 3.3 - */ -public class Edge { - - /** Start vertex. */ - private final Vertex start; - - /** End vertex. */ - private Vertex end; - - /** Length of the arc. */ - private final double length; - - /** Circle supporting the edge. */ - private final Circle circle; - - /** Build an edge not contained in any node yet. - * @param start start vertex - * @param end end vertex - * @param length length of the arc (it can be greater than \( \pi \)) - * @param circle circle supporting the edge - */ - Edge(final Vertex start, final Vertex end, final double length, final Circle circle) { - - this.start = start; - this.end = end; - this.length = length; - this.circle = circle; - - // connect the vertices back to the edge - start.setOutgoing(this); - end.setIncoming(this); - - } - - /** Get start vertex. - * @return start vertex - */ - public Vertex getStart() { - return start; - } - - /** Get end vertex. - * @return end vertex - */ - public Vertex getEnd() { - return end; - } - - /** Get the length of the arc. - * @return length of the arc (can be greater than \( \pi \)) - */ - public double getLength() { - return length; - } - - /** Get the circle supporting this edge. - * @return circle supporting this edge - */ - public Circle getCircle() { - return circle; - } - - /** Get an intermediate point. - * <p> - * The angle along the edge should normally be between 0 and {@link #getLength()} - * in order to remain within edge limits. However, there are no checks on the - * value of the angle, so user can rebuild the full circle on which an edge is - * defined if they want. - * </p> - * @param alpha angle along the edge, counted from {@link #getStart()} - * @return an intermediate point - */ - public Vector3D getPointAt(final double alpha) { - return circle.getPointAt(alpha + circle.getPhase(start.getLocation().getVector())); - } - - /** Connect the instance with a following edge. - * @param next edge following the instance - */ - void setNextEdge(final Edge next) { - end = next.getStart(); - end.setIncoming(this); - end.bindWith(getCircle()); - } - - /** Split the edge. - * <p> - * Once split, this edge is not referenced anymore by the vertices, - * it is replaced by the two or three sub-edges and intermediate splitting - * vertices are introduced to connect these sub-edges together. - * </p> - * @param splitCircle circle splitting the edge in several parts - * @param outsideList list where to put parts that are outside of the split circle - * @param insideList list where to put parts that are inside the split circle - */ - void split(final Circle splitCircle, - final List<Edge> outsideList, final List<Edge> insideList) { - - // get the inside arc, synchronizing its phase with the edge itself - final double edgeStart = circle.getPhase(start.getLocation().getVector()); - final Arc arc = circle.getInsideArc(splitCircle); - final double arcRelativeStart = MathUtils.normalizeAngle(arc.getInf(), edgeStart + FastMath.PI) - edgeStart; - final double arcRelativeEnd = arcRelativeStart + arc.getSize(); - final double unwrappedEnd = arcRelativeEnd - MathUtils.TWO_PI; - - // build the sub-edges - final double tolerance = circle.getTolerance(); - Vertex previousVertex = start; - if (unwrappedEnd >= length - tolerance) { - - // the edge is entirely contained inside the circle - // we don't split anything - insideList.add(this); - - } else { - - // there are at least some parts of the edge that should be outside - // (even is they are later be filtered out as being too small) - double alreadyManagedLength = 0; - if (unwrappedEnd >= 0) { - // the start of the edge is inside the circle - previousVertex = addSubEdge(previousVertex, - new Vertex(new S2Point(circle.getPointAt(edgeStart + unwrappedEnd))), - unwrappedEnd, insideList, splitCircle); - alreadyManagedLength = unwrappedEnd; - } - - if (arcRelativeStart >= length - tolerance) { - // the edge ends while still outside of the circle - if (unwrappedEnd >= 0) { - previousVertex = addSubEdge(previousVertex, end, - length - alreadyManagedLength, outsideList, splitCircle); - } else { - // the edge is entirely outside of the circle - // we don't split anything - outsideList.add(this); - } - } else { - // the edge is long enough to enter inside the circle - previousVertex = addSubEdge(previousVertex, - new Vertex(new S2Point(circle.getPointAt(edgeStart + arcRelativeStart))), - arcRelativeStart - alreadyManagedLength, outsideList, splitCircle); - alreadyManagedLength = arcRelativeStart; - - if (arcRelativeEnd >= length - tolerance) { - // the edge ends while still inside of the circle - previousVertex = addSubEdge(previousVertex, end, - length - alreadyManagedLength, insideList, splitCircle); - } else { - // the edge is long enough to exit outside of the circle - previousVertex = addSubEdge(previousVertex, - new Vertex(new S2Point(circle.getPointAt(edgeStart + arcRelativeStart))), - arcRelativeStart - alreadyManagedLength, insideList, splitCircle); - alreadyManagedLength = arcRelativeStart; - previousVertex = addSubEdge(previousVertex, end, - length - alreadyManagedLength, outsideList, splitCircle); - } - } - - } - - } - - /** Add a sub-edge to a list if long enough. - * <p> - * If the length of the sub-edge to add is smaller than the {@link Circle#getTolerance()} - * tolerance of the support circle, it will be ignored. - * </p> - * @param subStart start of the sub-edge - * @param subEnd end of the sub-edge - * @param subLength length of the sub-edge - * @param splitCircle circle splitting the edge in several parts - * @param list list where to put the sub-edge - * @return end vertex of the edge ({@code subEnd} if the edge was long enough and really - * added, {@code subStart} if the edge was too small and therefore ignored) - */ - private Vertex addSubEdge(final Vertex subStart, final Vertex subEnd, final double subLength, - final List<Edge> list, final Circle splitCircle) { - - if (subLength <= circle.getTolerance()) { - // the edge is too short, we ignore it - return subStart; - } - - // really add the edge - subEnd.bindWith(splitCircle); - final Edge edge = new Edge(subStart, subEnd, subLength, circle); - list.add(edge); - return subEnd; - - } - -}