Fixed an error introduced by a wrong fix...

git-svn-id: https://svn.apache.org/repos/asf/commons/proper/math/trunk@1557609 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Luc Maisonobe 2014-01-12 20:41:34 +00:00
parent bb2dc86de1
commit 0f13370f35
3 changed files with 69 additions and 109 deletions

View File

@ -394,7 +394,7 @@ public abstract class AbstractRegion<S extends Space, T extends Space> implement
* <p>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

View File

@ -667,10 +667,8 @@ public class ArcsSet extends AbstractRegion<Sphere1D, Sphere1D> implements Itera
final BSPTree<Sphere1D> minus = new BSPTree<Sphere1D>();
minus.setAttribute(Boolean.FALSE);
boolean minusIgnored = false;
final BSPTree<Sphere1D> plus = new BSPTree<Sphere1D>();
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<Sphere1D, Sphere1D> 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.
* <p>
* Note that this method <em>MUST</em> be called in increasing angle order.
* </p>
/** 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<Sphere1D> tree, final double alpha, final boolean ignored) {
final BSPTree<Sphere1D> 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<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) {
// 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.
* <p>
* Note that this method <em>MUST</em> be called in increasing angle order.
* </p>
* @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<Sphere1D> tree, final double alpha, final boolean ignored) {
final BSPTree<Sphere1D> 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<Sphere1D> tree, final boolean ignored) {
if (ignored) {
// ensure consistent state at 0 / 2 \pi crossing
final BSPTree<Sphere1D> first = getFirstLeaf(tree);
final boolean firstState = (Boolean) first.getAttribute();
final BSPTree<Sphere1D> 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<Sphere1D> 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.

View File

@ -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);
}
}