diff --git a/src/main/java/org/apache/commons/math3/geometry/partitioning/AbstractRegion.java b/src/main/java/org/apache/commons/math3/geometry/partitioning/AbstractRegion.java
index 4454c3005..ed02f6b65 100644
--- a/src/main/java/org/apache/commons/math3/geometry/partitioning/AbstractRegion.java
+++ b/src/main/java/org/apache/commons/math3/geometry/partitioning/AbstractRegion.java
@@ -394,7 +394,7 @@ public abstract class AbstractRegion implement
*
The filtering consist in splitting the specified
* sub-hyperplane into several parts lying in inside and outside
* cells of the tree. The principle is to call this method twice for
- * each cut sub-hyperplane in the tree, once one the plus node and
+ * each cut sub-hyperplane in the tree, once on the plus node and
* once on the minus node. The parts that have the same flag
* (inside/inside or outside/outside) do not belong to the boundary
* while parts that have different flags (inside/outside or
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
index b36048d93..923d5a786 100644
--- 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
@@ -667,10 +667,8 @@ public class ArcsSet extends AbstractRegion implements Itera
final BSPTree minus = new BSPTree();
minus.setAttribute(Boolean.FALSE);
- boolean minusIgnored = false;
final BSPTree plus = new BSPTree();
plus.setAttribute(Boolean.FALSE);
- boolean plusIgnored = false;
final double reference = FastMath.PI + arc.getInf();
final double arcLength = arc.getSup() - arc.getInf();
@@ -681,146 +679,90 @@ public class ArcsSet extends AbstractRegion implements Itera
final double syncedEnd = a[1] - arcOffset;
if (syncedStart < arcLength) {
// the start point a[0] is in the minus part of the arc
- minusIgnored = addArcStart(minus, a[0], minusIgnored);
+ addArcLimit(minus, a[0], true);
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;
- minusIgnored = addArcEnd(minus, minusToPlus, minusIgnored);
- plusIgnored = addArcStart(plus, minusToPlus, plusIgnored);
+ addArcLimit(minus, minusToPlus, false);
+ addArcLimit(plus, minusToPlus, true);
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;
- plusIgnored = addArcEnd(plus, plusToMinus, plusIgnored);
- minusIgnored = addArcStart(minus, plusToMinus, minusIgnored);
- minusIgnored = addArcEnd(minus, a[1], minusIgnored);
+ addArcLimit(plus, plusToMinus, false);
+ addArcLimit(minus, plusToMinus, true);
+ addArcLimit(minus, a[1], false);
} else {
// the end point a[1] is in the plus part of the arc
- plusIgnored = addArcEnd(plus, a[1], plusIgnored);
+ addArcLimit(plus, a[1], false);
}
} else {
// the end point a[1] is in the minus part of the arc
- minusIgnored = addArcEnd(minus, a[1], minusIgnored);
+ addArcLimit(minus, a[1], false);
}
} else {
// the start point a[0] is in the plus part of the arc
- plusIgnored = addArcStart(plus, a[0], plusIgnored);
+ addArcLimit(plus, a[0], true);
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;
- plusIgnored = addArcEnd(plus, plusToMinus, plusIgnored);
- minusIgnored = addArcStart(minus, plusToMinus, minusIgnored);
+ addArcLimit(plus, plusToMinus, false);
+ addArcLimit(minus, plusToMinus, true);
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;
- minusIgnored = addArcEnd(minus, minusToPlus, minusIgnored);
- plusIgnored = addArcStart(plus, minusToPlus, plusIgnored);
- plusIgnored = addArcEnd(plus, a[1], plusIgnored);
+ addArcLimit(minus, minusToPlus, false);
+ addArcLimit(plus, minusToPlus, true);
+ addArcLimit(plus, a[1], false);
} else {
// the end point a[1] is in the minus part of the arc
- minusIgnored = addArcEnd(minus, a[1], minusIgnored);
+ addArcLimit(minus, a[1], false);
}
} else {
// the end point a[1] is in the plus part of the arc
- plusIgnored = addArcEnd(plus, a[1], plusIgnored);
+ addArcLimit(plus, a[1], false);
}
}
}
- return new Split(createSplitPart(plus, plusIgnored), createSplitPart(minus, minusIgnored));
+ return new Split(createSplitPart(plus), createSplitPart(minus));
}
- /** Add an arc start to a BSP tree under construction.
- *
- * Note that this method MUST be called in increasing angle order.
- *
+ /** Add an arc limit to a BSP tree under construction.
* @param tree BSP tree under construction
- * @param alpha arc start
- * @param ignored if true, some end points have been ignored previously
- * @return true if some points have been ignored, taking this arc end into account
+ * @param alpha arc limit
+ * @param isStart if true, the limit is the start of an arc
*/
- private boolean addArcStart(final BSPTree tree, final double alpha, final boolean ignored) {
-
- final BSPTree last = getLastLeaf(tree);
-
- if (alpha <= getTolerance()) {
- // don't add a spurious cut hyperplane at the start of the circle,
- last.setAttribute(Boolean.TRUE);
- return true;
+ private void addArcLimit(final BSPTree tree, final double alpha, final boolean isStart) {
+ final LimitAngle limit = new LimitAngle(new S1Point(alpha), !isStart, getTolerance());
+ final BSPTree node = tree.getCell(limit.getLocation(), getTolerance());
+ if (node.getCut() != null) {
+ // we find again an already added limit,
+ // this means we have done a full turn around the circle
+ leafBefore(node).setAttribute(Boolean.valueOf(!isStart));
} else {
- last.insertCut(new LimitAngle(new S1Point(alpha), false, getTolerance()));
- last.setAttribute(null);
- last.getPlus().setAttribute(Boolean.FALSE);
- last.getMinus().setAttribute(Boolean.TRUE);
- return ignored;
+ // it's a new node
+ node.insertCut(limit);
+ node.setAttribute(null);
+ node.getPlus().setAttribute(Boolean.FALSE);
+ node.getMinus().setAttribute(Boolean.TRUE);
}
-
- }
-
- /** Add an arc end to a BSP tree under construction.
- *
- * Note that this method MUST be called in increasing angle order.
- *
- * @param tree BSP tree under construction
- * @param alpha arc end
- * @param ignored if true, some end points have been ignored previously
- * @return true if some points have been ignored, taking this arc end into account
- */
- private boolean addArcEnd(final BSPTree tree, final double alpha, final boolean ignored) {
-
- final BSPTree last = getLastLeaf(tree);
-
- if (alpha >= MathUtils.TWO_PI - getTolerance()) {
-
- // don't add a spurious cut hyperplane at the end of the circle,
- last.setAttribute(Boolean.TRUE);
- return true;
-
- } else {
- last.insertCut(new LimitAngle(new S1Point(alpha), true, getTolerance()));
- last.setAttribute(null);
- last.getPlus().setAttribute(Boolean.FALSE);
- last.getMinus().setAttribute(Boolean.TRUE);
- return ignored;
- }
-
}
/** Create a split part.
* @param tree BSP tree containing the limit angles of the split part
- * @param ignored if true, some end points have been ignored previously
* @return split part (may be null)
*/
- private ArcsSet createSplitPart(final BSPTree tree, final boolean ignored) {
-
- if (ignored) {
- // ensure consistent state at 0 / 2 \pi crossing
-
- final BSPTree first = getFirstLeaf(tree);
- final boolean firstState = (Boolean) first.getAttribute();
- final BSPTree last = getLastLeaf(tree);
- final boolean lastState = (Boolean) last.getAttribute();
- if (firstState ^ lastState) {
- // there should be a real boundary at the crossing. Since it is not accurately
- // representable due to S1Point normalizing the angles between 0 (included)
- // and 2 \pi (excluded), we insert it at the *beginning* of the tree,
- // with an angle forced to 0.0
- first.insertCut(new LimitAngle(new S1Point(0.0), true, getTolerance()));
- first.getPlus().setAttribute(firstState);
- first.getMinus().setAttribute(lastState);
- }
- }
-
+ private ArcsSet createSplitPart(final BSPTree tree) {
if (tree.getCut() == null && !(Boolean) tree.getAttribute()) {
return null;
} else {
return new ArcsSet(tree, getTolerance());
}
-
}
/** Class holding the results of the {@link #split split} method.
diff --git a/src/test/java/org/apache/commons/math3/geometry/spherical/oned/ArcsSetTest.java b/src/test/java/org/apache/commons/math3/geometry/spherical/oned/ArcsSetTest.java
index 7af53fbea..300987d08 100644
--- a/src/test/java/org/apache/commons/math3/geometry/spherical/oned/ArcsSetTest.java
+++ b/src/test/java/org/apache/commons/math3/geometry/spherical/oned/ArcsSetTest.java
@@ -73,7 +73,7 @@ public class ArcsSetTest {
ArcsSet set = new ArcsSet(1.0e-10);
Arc arc = new Arc(1.5 * FastMath.PI, 2.5 * FastMath.PI, 1.0e-10);
ArcsSet.Split split = set.split(arc);
- for (double alpha = 0; alpha <= MathUtils.TWO_PI; alpha += 0.01) {
+ for (double alpha = 0.0; alpha <= MathUtils.TWO_PI; alpha += 0.01) {
S1Point p = new S1Point(alpha);
if (alpha < 0.5 * FastMath.PI || alpha > 1.5 * FastMath.PI) {
Assert.assertEquals(Location.OUTSIDE, split.getPlus().checkPoint(p));
@@ -445,8 +445,8 @@ public class ArcsSetTest {
ArcsSet s16 = new ArcsSet(1.0, 6.0, 1.0e-10);
ArcsSet.Split split1 = s16.split(new Arc(3.0, 5.0, 1.0e-10));
- ArcsSet split1Plus = (ArcsSet) split1.getPlus();
- ArcsSet split1Minus = (ArcsSet) split1.getMinus();
+ ArcsSet split1Plus = split1.getPlus();
+ ArcsSet split1Minus = split1.getMinus();
Assert.assertEquals(3.0, split1Plus.getSize(), 1.0e-10);
Assert.assertEquals(2, split1Plus.asList().size());
Assert.assertEquals(1.0, split1Plus.asList().get(0).getInf(), 1.0e-10);
@@ -459,8 +459,8 @@ public class ArcsSetTest {
Assert.assertEquals(5.0, split1Minus.asList().get(0).getSup(), 1.0e-10);
ArcsSet.Split split2 = s16.split(new Arc(5.0, 3.0 + MathUtils.TWO_PI, 1.0e-10));
- ArcsSet split2Plus = (ArcsSet) split2.getPlus();
- ArcsSet split2Minus = (ArcsSet) split2.getMinus();
+ ArcsSet split2Plus = split2.getPlus();
+ ArcsSet split2Minus = split2.getMinus();
Assert.assertEquals(2.0, split2Plus.getSize(), 1.0e-10);
Assert.assertEquals(1, split2Plus.asList().size());
Assert.assertEquals(3.0, split2Plus.asList().get(0).getInf(), 1.0e-10);
@@ -473,8 +473,8 @@ public class ArcsSetTest {
Assert.assertEquals(6.0, split2Minus.asList().get(1).getSup(), 1.0e-10);
ArcsSet.Split split3 = s35.split(new Arc(1.0, 6.0, 1.0e-10));
- ArcsSet split3Plus = (ArcsSet) split3.getPlus();
- ArcsSet split3Minus = (ArcsSet) split3.getMinus();
+ ArcsSet split3Plus = split3.getPlus();
+ ArcsSet split3Minus = split3.getMinus();
Assert.assertNull(split3Plus);
Assert.assertEquals(2.0, split3Minus.getSize(), 1.0e-10);
Assert.assertEquals(1, split3Minus.asList().size());
@@ -482,8 +482,8 @@ public class ArcsSetTest {
Assert.assertEquals(5.0, split3Minus.asList().get(0).getSup(), 1.0e-10);
ArcsSet.Split split4 = s35.split(new Arc(6.0, 1.0 + MathUtils.TWO_PI, 1.0e-10));
- ArcsSet split4Plus = (ArcsSet) split4.getPlus();
- ArcsSet split4Minus = (ArcsSet) split4.getMinus();
+ ArcsSet split4Plus = split4.getPlus();
+ ArcsSet split4Minus = split4.getMinus();
Assert.assertEquals(2.0, split4Plus.getSize(), 1.0e-10);
Assert.assertEquals(1, split4Plus.asList().size());
Assert.assertEquals(3.0, split4Plus.asList().get(0).getInf(), 1.0e-10);
@@ -499,8 +499,8 @@ public class ArcsSetTest {
ArcsSet s46 = new ArcsSet(4.0, 6.0, 1.0e-10);
ArcsSet.Split split1 = s46.split(new Arc(3.0, 5.0, 1.0e-10));
- ArcsSet split1Plus = (ArcsSet) split1.getPlus();
- ArcsSet split1Minus = (ArcsSet) split1.getMinus();
+ ArcsSet split1Plus = split1.getPlus();
+ ArcsSet split1Minus = split1.getMinus();
Assert.assertEquals(1.0, split1Plus.getSize(), 1.0e-10);
Assert.assertEquals(1, split1Plus.asList().size());
Assert.assertEquals(5.0, split1Plus.asList().get(0).getInf(), 1.0e-10);
@@ -511,8 +511,8 @@ public class ArcsSetTest {
Assert.assertEquals(5.0, split1Minus.asList().get(0).getSup(), 1.0e-10);
ArcsSet.Split split2 = s46.split(new Arc(5.0, 3.0 + MathUtils.TWO_PI, 1.0e-10));
- ArcsSet split2Plus = (ArcsSet) split2.getPlus();
- ArcsSet split2Minus = (ArcsSet) split2.getMinus();
+ ArcsSet split2Plus = split2.getPlus();
+ ArcsSet split2Minus = split2.getMinus();
Assert.assertEquals(1.0, split2Plus.getSize(), 1.0e-10);
Assert.assertEquals(1, split2Plus.asList().size());
Assert.assertEquals(4.0, split2Plus.asList().get(0).getInf(), 1.0e-10);
@@ -523,8 +523,8 @@ public class ArcsSetTest {
Assert.assertEquals(6.0, split2Minus.asList().get(0).getSup(), 1.0e-10);
ArcsSet.Split split3 = s35.split(new Arc(4.0, 6.0, 1.0e-10));
- ArcsSet split3Plus = (ArcsSet) split3.getPlus();
- ArcsSet split3Minus = (ArcsSet) split3.getMinus();
+ ArcsSet split3Plus = split3.getPlus();
+ ArcsSet split3Minus = split3.getMinus();
Assert.assertEquals(1.0, split3Plus.getSize(), 1.0e-10);
Assert.assertEquals(1, split3Plus.asList().size());
Assert.assertEquals(3.0, split3Plus.asList().get(0).getInf(), 1.0e-10);
@@ -535,8 +535,8 @@ public class ArcsSetTest {
Assert.assertEquals(5.0, split3Minus.asList().get(0).getSup(), 1.0e-10);
ArcsSet.Split split4 = s35.split(new Arc(6.0, 4.0 + MathUtils.TWO_PI, 1.0e-10));
- ArcsSet split4Plus = (ArcsSet) split4.getPlus();
- ArcsSet split4Minus = (ArcsSet) split4.getMinus();
+ ArcsSet split4Plus = split4.getPlus();
+ ArcsSet split4Minus = split4.getMinus();
Assert.assertEquals(1.0, split4Plus.getSize(), 1.0e-10);
Assert.assertEquals(1, split4Plus.asList().size());
Assert.assertEquals(4.0, split4Plus.asList().get(0).getInf(), 1.0e-10);
@@ -547,4 +547,22 @@ public class ArcsSetTest {
Assert.assertEquals(4.0, split4Minus.asList().get(0).getSup(), 1.0e-10);
}
+
+ @Test
+ public void testFarSplit() {
+ ArcsSet set = new ArcsSet(FastMath.PI, 2.5 * FastMath.PI, 1.0e-10);
+ ArcsSet.Split split = set.split(new Arc(0.5 * FastMath.PI, 1.5 * FastMath.PI, 1.0e-10));
+ ArcsSet splitPlus = split.getPlus();
+ ArcsSet splitMinus = split.getMinus();
+ Assert.assertEquals(1, splitMinus.asList().size());
+ Assert.assertEquals(1.0 * FastMath.PI, splitMinus.asList().get(0).getInf(), 1.0e-10);
+ Assert.assertEquals(1.5 * FastMath.PI, splitMinus.asList().get(0).getSup(), 1.0e-10);
+ Assert.assertEquals(0.5 * FastMath.PI, splitMinus.getSize(), 1.0e-10);
+ Assert.assertEquals(1, splitPlus.asList().size());
+ Assert.assertEquals(1.5 * FastMath.PI, splitPlus.asList().get(0).getInf(), 1.0e-10);
+ Assert.assertEquals(2.5 * FastMath.PI, splitPlus.asList().get(0).getSup(), 1.0e-10);
+ Assert.assertEquals(1.0 * FastMath.PI, splitPlus.getSize(), 1.0e-10);
+
+ }
+
}