You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@commons.apache.org by lu...@apache.org on 2014/01/01 18:30:58 UTC

svn commit: r1554656 - in /commons/proper/math/trunk/src: main/java/org/apache/commons/math3/geometry/spherical/oned/ArcsSet.java test/java/org/apache/commons/math3/geometry/spherical/oned/ArcsSetTest.java

Author: luc
Date: Wed Jan  1 17:30:58 2014
New Revision: 1554656

URL: http://svn.apache.org/r1554656
Log:
Finalized 1-sphere.

Modified:
    commons/proper/math/trunk/src/main/java/org/apache/commons/math3/geometry/spherical/oned/ArcsSet.java
    commons/proper/math/trunk/src/test/java/org/apache/commons/math3/geometry/spherical/oned/ArcsSetTest.java

Modified: commons/proper/math/trunk/src/main/java/org/apache/commons/math3/geometry/spherical/oned/ArcsSet.java
URL: http://svn.apache.org/viewvc/commons/proper/math/trunk/src/main/java/org/apache/commons/math3/geometry/spherical/oned/ArcsSet.java?rev=1554656&r1=1554655&r2=1554656&view=diff
==============================================================================
--- commons/proper/math/trunk/src/main/java/org/apache/commons/math3/geometry/spherical/oned/ArcsSet.java (original)
+++ commons/proper/math/trunk/src/main/java/org/apache/commons/math3/geometry/spherical/oned/ArcsSet.java Wed Jan  1 17:30:58 2014
@@ -18,14 +18,13 @@ package org.apache.commons.math3.geometr
 
 import java.util.ArrayList;
 import java.util.Collection;
-import java.util.Collections;
 import java.util.List;
 
+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.partitioning.AbstractRegion;
 import org.apache.commons.math3.geometry.partitioning.BSPTree;
-import org.apache.commons.math3.geometry.partitioning.BSPTreeVisitor;
 import org.apache.commons.math3.geometry.partitioning.SubHyperplane;
 import org.apache.commons.math3.util.FastMath;
 import org.apache.commons.math3.util.MathUtils;
@@ -171,19 +170,6 @@ public class ArcsSet extends AbstractReg
         return tolerance;
     }
 
-    /** Get the smallest internal node.
-     * @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)
-     */
-    public LimitAngle getSmallestLimit() {
-        final BSPTree<Sphere1D> first = getFirstArcStart();
-        if (first == null) {
-            return null;
-        } else {
-            return (LimitAngle) first.getCut().getHyperplane();
-        }
-    }
-
     /** 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)
@@ -373,7 +359,7 @@ public class ArcsSet extends AbstractReg
      * @return child node just before the internal node
      */
     private BSPTree<Sphere1D> childBefore(BSPTree<Sphere1D> node) {
-        if (((LimitAngle) node.getCut().getHyperplane()).isDirect()) {
+        if (isDirect(node)) {
             // smaller angles are on minus side, larger angles are on plus side
             return node.getMinus();
         } else {
@@ -387,7 +373,7 @@ public class ArcsSet extends AbstractReg
      * @return child node just after the internal node
      */
     private BSPTree<Sphere1D> childAfter(BSPTree<Sphere1D> node) {
-        if (((LimitAngle) node.getCut().getHyperplane()).isDirect()) {
+        if (isDirect(node)) {
             // smaller angles are on minus side, larger angles are on plus side
             return node.getPlus();
         } else {
@@ -396,6 +382,22 @@ public class ArcsSet extends AbstractReg
         }
     }
 
+    /** Check if an internal node has a direct limit angle.
+     * @param node 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 a node.
+     * @param node node to check
+     * @return true if the limit angle is direct
+     */
+    private double getAngle(final BSPTree<Sphere1D> node) {
+        return ((LimitAngle) node.getCut().getHyperplane()).getLocation().getAlpha();
+    }
+
     /** {@inheritDoc} */
     @Override
     public ArcsSet buildNew(final BSPTree<Sphere1D> tree) {
@@ -437,80 +439,65 @@ public class ArcsSet extends AbstractReg
     public List<Arc> asList() {
 
         final List<Arc> list = new ArrayList<Arc>();
-        final BSPTree<Sphere1D> root = getTree(false);
+        final BSPTree<Sphere1D> firstStart = getFirstArcStart();
 
-        if (root.getCut() == null) {
-            // the tree has a single node
-            if ((Boolean) root.getAttribute()) {
-                // it is an inside node, it represents the full circle
-                list.add(new Arc(0.0, 0.0, tolerance)); // since lower == upper, the arc covers the full circle
-            }
+        if (firstStart == null) {
+                // the tree has a single node
+                if ((Boolean) getTree(false).getAttribute()) {
+                    // it is an inside node, it represents the full circle
+                    list.add(new Arc(0.0, 0.0, tolerance)); // since lower == upper, the arc covers the full circle
+                }
+        } else if (previousNode(firstStart) == null && nextNode(firstStart) == null) {
+            // the tree is a degenerate tree (probably build from a custom collection of hyperplanes) with a single cut
+            // we ignore the cut and consider the tree represents the full circle
+            list.add(new Arc(0.0, 0.0, tolerance)); // since lower == upper, the arc covers the full circle
         } else {
 
-            // find all arcs limits
-            final LimitsCollector finder = new LimitsCollector();
-            root.visit(finder);
-            final List<Double> limits = finder.getLimits();
-            if (limits.size() < 2) {
-                // the start and end angle collapsed to the same value, its the full circle again
-                list.add(new Arc(0.0, 0.0, tolerance)); // since lower == upper, the arc covers the full circle
-                return list;
-            }
+            // find all arcs
+            BSPTree<Sphere1D> start = firstStart;
+            while (start != null) {
+
+                // look for the end of the current arc
+                BSPTree<Sphere1D> end = start;
+                while (end != null && !isArcEnd(end)) {
+                    end = nextNode(end);
+                }
+
+                if (end != null) {
+
+                    // we have identified the current arc
+                    list.add(new Arc(getAngle(start), getAngle(end), tolerance));
+
+                    // prepare search for next arc
+                    start = end;
+                    while (start != null && !isArcStart(start)) {
+                        start = nextNode(start);
+                    }
+
+                } else {
+                    // the final arc wraps around 2\pi, its end is before the first start
+                    end = firstStart;
+                    while (end != null && !isArcEnd(end)) {
+                        end = previousNode(end);
+                    }
+                    if (end == null) {
+                        // this should never happen
+                        throw new MathInternalError();
+                    }
 
-            // sort them so the first angle is an arc start
-            Collections.sort(limits);
-            if (checkPoint(new S1Point(0.5 * (limits.get(0) + limits.get(1)))) == Location.OUTSIDE) {
-                // the first angle is not an arc start, its the last arc end
-                // move it properly to the end
-                limits.add(limits.remove(0) + MathUtils.TWO_PI);
-            }
+                    // we have identified the last arc
+                    list.add(new Arc(getAngle(start), getAngle(end) + MathUtils.TWO_PI, tolerance));
 
-            // we can now build the list
-            for (int i = 0; i < limits.size(); i += 2) {
-                list.add(new Arc(limits.get(i), limits.get(i + 1), tolerance));
-            }
-
-        }
-
-        return list;
-
-    }
+                    // stop the loop
+                    start = null;
 
-    /** Visitor looking for arc limits. */
-    private final class LimitsCollector implements BSPTreeVisitor<Sphere1D> {
+                }
 
-        /** Collected limits. */
-        private List<Double> limits;
-
-        /** Simple constructor. */
-        public LimitsCollector() {
-            this.limits = new ArrayList<Double>();
-        }
-
-        /** {@inheritDoc} */
-        public BSPTreeVisitor.Order visitOrder(final BSPTree<Sphere1D> node) {
-            return Order.MINUS_PLUS_SUB;
-        }
-
-        /** {@inheritDoc} */
-        public void visitInternalNode(final BSPTree<Sphere1D> node) {
-            // check if the chord end points are arc limits
-            final LimitAngle limit = (LimitAngle) node.getCut().getHyperplane();
-            if (checkPoint(limit.getLocation()) == Location.BOUNDARY) {
-                limits.add(limit.getLocation().getAlpha());
             }
-        }
 
-        /** {@inheritDoc} */
-        public void visitLeafNode(final BSPTree<Sphere1D> node) {
         }
 
-        /** Get the collected limits.
-         * @return collected limits
-         */
-        public List<Double> getLimits() {
-            return limits;
-        }
+        return list;
 
     }
 

Modified: commons/proper/math/trunk/src/test/java/org/apache/commons/math3/geometry/spherical/oned/ArcsSetTest.java
URL: http://svn.apache.org/viewvc/commons/proper/math/trunk/src/test/java/org/apache/commons/math3/geometry/spherical/oned/ArcsSetTest.java?rev=1554656&r1=1554655&r2=1554656&view=diff
==============================================================================
--- commons/proper/math/trunk/src/test/java/org/apache/commons/math3/geometry/spherical/oned/ArcsSetTest.java (original)
+++ commons/proper/math/trunk/src/test/java/org/apache/commons/math3/geometry/spherical/oned/ArcsSetTest.java Wed Jan  1 17:30:58 2014
@@ -46,8 +46,6 @@ public class ArcsSetTest {
         Assert.assertEquals(1, set.asList().size());
         Assert.assertEquals(2.3, set.asList().get(0).getInf(), 1.0e-10);
         Assert.assertEquals(5.7, set.asList().get(0).getSup(), 1.0e-10);
-        Assert.assertEquals(2.3, set.getSmallestLimit().getLocation().getAlpha(), 1.0e-10);
-        Assert.assertFalse(set.getSmallestLimit().isDirect());
     }
 
     @Test
@@ -64,8 +62,6 @@ public class ArcsSetTest {
         Assert.assertEquals(1, set.asList().size());
         Assert.assertEquals(5.7, set.asList().get(0).getInf(), 1.0e-10);
         Assert.assertEquals(2.3 + MathUtils.TWO_PI, set.asList().get(0).getSup(), 1.0e-10);
-        Assert.assertEquals(5.7, set.getSmallestLimit().getLocation().getAlpha(), 1.0e-10);
-        Assert.assertFalse(set.getSmallestLimit().isDirect());
     }
 
     @Test(expected=NumberIsTooLargeException.class)
@@ -77,7 +73,6 @@ public class ArcsSetTest {
     public void testFullEqualEndPoints() {
         ArcsSet set = new ArcsSet(1.0, 1.0, 1.0e-10);
         Assert.assertEquals(1.0e-10, set.getTolerance(), 1.0e-20);
-        Assert.assertNull(set.getSmallestLimit());
         Assert.assertEquals(Region.Location.INSIDE, set.checkPoint(new S1Point(9.0)));
         for (double alpha = -20.0; alpha <= 20.0; alpha += 0.1) {
             Assert.assertEquals(Region.Location.INSIDE, set.checkPoint(new S1Point(alpha)));
@@ -92,7 +87,6 @@ public class ArcsSetTest {
     public void testFullCircle() {
         ArcsSet set = new ArcsSet(1.0e-10);
         Assert.assertEquals(1.0e-10, set.getTolerance(), 1.0e-20);
-        Assert.assertNull(set.getSmallestLimit());
         Assert.assertEquals(Region.Location.INSIDE, set.checkPoint(new S1Point(9.0)));
         for (double alpha = -20.0; alpha <= 20.0; alpha += 0.1) {
             Assert.assertEquals(Region.Location.INSIDE, set.checkPoint(new S1Point(alpha)));
@@ -109,7 +103,6 @@ public class ArcsSetTest {
         Assert.assertEquals(1.0e-10, empty.getTolerance(), 1.0e-20);
         Assert.assertEquals(0.0, empty.getSize(), 1.0e-10);
         Assert.assertTrue(empty.asList().isEmpty());
-        Assert.assertNull(empty.getSmallestLimit());
     }
 
     @Test
@@ -120,7 +113,6 @@ public class ArcsSetTest {
         Assert.assertEquals(1, tiny.asList().size());
         Assert.assertEquals(0.0, tiny.asList().get(0).getInf(), 1.0e-10);
         Assert.assertEquals(Precision.SAFE_MIN / 2, tiny.asList().get(0).getSup(), 1.0e-10);
-        Assert.assertEquals(0.0, tiny.getSmallestLimit().getLocation().getAlpha(), 1.0e-10);
     }
 
     @Test
@@ -134,8 +126,6 @@ public class ArcsSetTest {
         Assert.assertEquals(1, set.asList().size());
         Assert.assertEquals(0.0, set.asList().get(0).getInf(), 1.0e-10);
         Assert.assertEquals(MathUtils.TWO_PI, set.asList().get(0).getSup(), 1.0e-10);
-        Assert.assertEquals(0.0, set.getSmallestLimit().getLocation().getAlpha(), 1.0e-10);
-        Assert.assertFalse(set.getSmallestLimit().isDirect());
     }
 
     @Test