diff --git a/src/main/java/org/apache/commons/math4/geometry/euclidean/twod/PolygonsSet.java b/src/main/java/org/apache/commons/math4/geometry/euclidean/twod/PolygonsSet.java index 00d1f70fa..8d5c7b930 100644 --- a/src/main/java/org/apache/commons/math4/geometry/euclidean/twod/PolygonsSet.java +++ b/src/main/java/org/apache/commons/math4/geometry/euclidean/twod/PolygonsSet.java @@ -644,10 +644,10 @@ public class PolygonsSet extends AbstractRegion { for (ConnectableSegment s = getUnprocessed(segments); s != null; s = getUnprocessed(segments)) { final List loop = followLoop(s); if (loop != null) { - // an open loop is one that has fewer than two segments or has a null - // start point; the case where we have two segments in a closed loop - // (ie, an infinitely thin, degenerate loop) will result in null being - // returned from the followLoops method + // an open loop is one that has fewer than two segments or has a null + // start point; the case where we have two segments in a closed loop + // (ie, an infinitely thin, degenerate loop) will result in null being + // returned from the followLoops method if (loop.size() < 2 || loop.get(0).getStart() == null) { // this is an open loop, we put it on the front loops.add(0, loop); @@ -867,22 +867,22 @@ public class PolygonsSet extends AbstractRegion { * @param loop segments loop to filter (will be modified in-place) */ private void filterSpuriousVertices(final List loop) { - // we need at least 2 segments in order for one of the contained vertices - // to be unnecessary - if (loop.size() > 1) { - for (int i = 0; i < loop.size(); ++i) { - final Segment previous = loop.get(i); - int j = (i + 1) % loop.size(); - final Segment next = loop.get(j); - if (next != null && - Precision.equals(previous.getLine().getAngle(), next.getLine().getAngle(), Precision.EPSILON)) { - // the vertex between the two edges is a spurious one - // replace the two segments by a single one - loop.set(j, new Segment(previous.getStart(), next.getEnd(), previous.getLine())); - loop.remove(i--); - } - } - } + // we need at least 2 segments in order for one of the contained vertices + // to be unnecessary + if (loop.size() > 1) { + for (int i = 0; i < loop.size(); ++i) { + final Segment previous = loop.get(i); + int j = (i + 1) % loop.size(); + final Segment next = loop.get(j); + if (next != null && + Precision.equals(previous.getLine().getAngle(), next.getLine().getAngle(), Precision.EPSILON)) { + // the vertex between the two edges is a spurious one + // replace the two segments by a single one + loop.set(j, new Segment(previous.getStart(), next.getEnd(), previous.getLine())); + loop.remove(i--); + } + } + } } /** Private extension of Segment allowing connection. */ @@ -1078,23 +1078,23 @@ public class PolygonsSet extends AbstractRegion { * @return node closest to point, or null if point is null or no node is closer than tolerance */ private BSPTree selectClosest(final Cartesian2D point, final Iterable> candidates) { - if (point != null) { - BSPTree selected = null; - double min = Double.POSITIVE_INFINITY; - - for (final BSPTree node : candidates) { - final double distance = FastMath.abs(node.getCut().getHyperplane().getOffset(point)); - if (distance < min) { - selected = node; - min = distance; - } - } - - if (min <= tolerance) { - return selected; - } - } - return null; + if (point != null) { + BSPTree selected = null; + double min = Double.POSITIVE_INFINITY; + + for (final BSPTree node : candidates) { + final double distance = FastMath.abs(node.getCut().getHyperplane().getOffset(point)); + if (distance < min) { + selected = node; + min = distance; + } + } + + if (min <= tolerance) { + return selected; + } + } + return null; } /** Get the segments. diff --git a/src/test/java/org/apache/commons/math4/geometry/euclidean/oned/SubOrientedPointTest.java b/src/test/java/org/apache/commons/math4/geometry/euclidean/oned/SubOrientedPointTest.java index bce54e5d6..6888d519a 100644 --- a/src/test/java/org/apache/commons/math4/geometry/euclidean/oned/SubOrientedPointTest.java +++ b/src/test/java/org/apache/commons/math4/geometry/euclidean/oned/SubOrientedPointTest.java @@ -26,141 +26,141 @@ import org.junit.Test; public class SubOrientedPointTest { private static final double TEST_TOLERANCE = 1e-10; - + @Test public void testGetSize() { - // arrange + // arrange OrientedPoint hyperplane = new OrientedPoint(new Cartesian1D(1), true, TEST_TOLERANCE); SubOrientedPoint pt = (SubOrientedPoint) hyperplane.wholeHyperplane(); - + // act/assert Assert.assertEquals(0.0, pt.getSize(), TEST_TOLERANCE); } - + @Test public void testIsEmpty() { - // arrange + // arrange OrientedPoint hyperplane = new OrientedPoint(new Cartesian1D(1), true, TEST_TOLERANCE); SubOrientedPoint pt = (SubOrientedPoint) hyperplane.wholeHyperplane(); - + // act/assert Assert.assertFalse(pt.isEmpty()); } - + @Test public void testBuildNew() { - // arrange + // arrange OrientedPoint originalHyperplane = new OrientedPoint(new Cartesian1D(1), true, TEST_TOLERANCE); SubOrientedPoint pt = (SubOrientedPoint) originalHyperplane.wholeHyperplane(); - + OrientedPoint hyperplane = new OrientedPoint(new Cartesian1D(2), true, TEST_TOLERANCE); IntervalsSet intervals = new IntervalsSet(2, 3, TEST_TOLERANCE); - + // act SubHyperplane result = pt.buildNew(hyperplane, intervals); - + // assert Assert.assertTrue(result instanceof SubOrientedPoint); Assert.assertSame(hyperplane, result.getHyperplane()); Assert.assertSame(intervals, ((SubOrientedPoint) result).getRemainingRegion()); } - + @Test public void testSplit_resultOnMinusSide() { - // arrange - OrientedPoint hyperplane = new OrientedPoint(new Cartesian1D(1), true, TEST_TOLERANCE); - IntervalsSet interval = new IntervalsSet(4, 5, TEST_TOLERANCE); - SubOrientedPoint pt = new SubOrientedPoint(hyperplane, interval); - - OrientedPoint splitter = new OrientedPoint(new Cartesian1D(2), true, TEST_TOLERANCE); - - // act - SplitSubHyperplane split = pt.split(splitter); - - // assert - Assert.assertEquals(Side.MINUS, split.getSide()); - - SubOrientedPoint minusSub = ((SubOrientedPoint) split.getMinus()); - Assert.assertNotNull(minusSub); - - OrientedPoint minusHyper = (OrientedPoint) minusSub.getHyperplane(); - Assert.assertEquals(1, minusHyper.getLocation().getX(), TEST_TOLERANCE); - - List minusIntervals = ((IntervalsSet) minusSub.getRemainingRegion()).asList(); - Assert.assertEquals(1, minusIntervals.size()); - Assert.assertEquals(4, minusIntervals.get(0).getInf(), TEST_TOLERANCE); - Assert.assertEquals(5, minusIntervals.get(0).getSup(), TEST_TOLERANCE); - - Assert.assertNull(split.getPlus()); + // arrange + OrientedPoint hyperplane = new OrientedPoint(new Cartesian1D(1), true, TEST_TOLERANCE); + IntervalsSet interval = new IntervalsSet(4, 5, TEST_TOLERANCE); + SubOrientedPoint pt = new SubOrientedPoint(hyperplane, interval); + + OrientedPoint splitter = new OrientedPoint(new Cartesian1D(2), true, TEST_TOLERANCE); + + // act + SplitSubHyperplane split = pt.split(splitter); + + // assert + Assert.assertEquals(Side.MINUS, split.getSide()); + + SubOrientedPoint minusSub = ((SubOrientedPoint) split.getMinus()); + Assert.assertNotNull(minusSub); + + OrientedPoint minusHyper = (OrientedPoint) minusSub.getHyperplane(); + Assert.assertEquals(1, minusHyper.getLocation().getX(), TEST_TOLERANCE); + + List minusIntervals = ((IntervalsSet) minusSub.getRemainingRegion()).asList(); + Assert.assertEquals(1, minusIntervals.size()); + Assert.assertEquals(4, minusIntervals.get(0).getInf(), TEST_TOLERANCE); + Assert.assertEquals(5, minusIntervals.get(0).getSup(), TEST_TOLERANCE); + + Assert.assertNull(split.getPlus()); } - + @Test public void testSplit_resultOnPlusSide() { - // arrange - OrientedPoint hyperplane = new OrientedPoint(new Cartesian1D(1), true, TEST_TOLERANCE); - IntervalsSet interval = new IntervalsSet(4, 5, TEST_TOLERANCE); - SubOrientedPoint pt = new SubOrientedPoint(hyperplane, interval); - - OrientedPoint splitter = new OrientedPoint(new Cartesian1D(0), true, TEST_TOLERANCE); - - // act - SplitSubHyperplane split = pt.split(splitter); - - // assert - Assert.assertEquals(Side.PLUS, split.getSide()); - - Assert.assertNull(split.getMinus()); - - SubOrientedPoint plusSub = ((SubOrientedPoint) split.getPlus()); - Assert.assertNotNull(plusSub); - - OrientedPoint plusHyper = (OrientedPoint) plusSub.getHyperplane(); - Assert.assertEquals(1, plusHyper.getLocation().getX(), TEST_TOLERANCE); - - List plusIntervals = ((IntervalsSet) plusSub.getRemainingRegion()).asList(); - Assert.assertEquals(1, plusIntervals.size()); - Assert.assertEquals(4, plusIntervals.get(0).getInf(), TEST_TOLERANCE); - Assert.assertEquals(5, plusIntervals.get(0).getSup(), TEST_TOLERANCE); + // arrange + OrientedPoint hyperplane = new OrientedPoint(new Cartesian1D(1), true, TEST_TOLERANCE); + IntervalsSet interval = new IntervalsSet(4, 5, TEST_TOLERANCE); + SubOrientedPoint pt = new SubOrientedPoint(hyperplane, interval); + + OrientedPoint splitter = new OrientedPoint(new Cartesian1D(0), true, TEST_TOLERANCE); + + // act + SplitSubHyperplane split = pt.split(splitter); + + // assert + Assert.assertEquals(Side.PLUS, split.getSide()); + + Assert.assertNull(split.getMinus()); + + SubOrientedPoint plusSub = ((SubOrientedPoint) split.getPlus()); + Assert.assertNotNull(plusSub); + + OrientedPoint plusHyper = (OrientedPoint) plusSub.getHyperplane(); + Assert.assertEquals(1, plusHyper.getLocation().getX(), TEST_TOLERANCE); + + List plusIntervals = ((IntervalsSet) plusSub.getRemainingRegion()).asList(); + Assert.assertEquals(1, plusIntervals.size()); + Assert.assertEquals(4, plusIntervals.get(0).getInf(), TEST_TOLERANCE); + Assert.assertEquals(5, plusIntervals.get(0).getSup(), TEST_TOLERANCE); } - + @Test public void testSplit_equivalentHyperplanes() { - // arrange - OrientedPoint hyperplane = new OrientedPoint(new Cartesian1D(1), true, TEST_TOLERANCE); - IntervalsSet interval = new IntervalsSet(4, 5, TEST_TOLERANCE); - SubOrientedPoint pt = new SubOrientedPoint(hyperplane, interval); - - OrientedPoint splitter = new OrientedPoint(new Cartesian1D(1), true, TEST_TOLERANCE); - - // act - SplitSubHyperplane split = pt.split(splitter); - - // assert - Assert.assertEquals(Side.HYPER, split.getSide()); - - Assert.assertNull(split.getMinus()); - Assert.assertNull(split.getPlus()); + // arrange + OrientedPoint hyperplane = new OrientedPoint(new Cartesian1D(1), true, TEST_TOLERANCE); + IntervalsSet interval = new IntervalsSet(4, 5, TEST_TOLERANCE); + SubOrientedPoint pt = new SubOrientedPoint(hyperplane, interval); + + OrientedPoint splitter = new OrientedPoint(new Cartesian1D(1), true, TEST_TOLERANCE); + + // act + SplitSubHyperplane split = pt.split(splitter); + + // assert + Assert.assertEquals(Side.HYPER, split.getSide()); + + Assert.assertNull(split.getMinus()); + Assert.assertNull(split.getPlus()); } - + @Test public void testSplit_usesToleranceFromParentHyperplane() { - // arrange + // arrange OrientedPoint hyperplane = new OrientedPoint(new Cartesian1D(1), true, 0.1); SubOrientedPoint pt = (SubOrientedPoint) hyperplane.wholeHyperplane(); - + // act/assert SplitSubHyperplane plusSplit = pt.split(new OrientedPoint(new Cartesian1D(0.899), true, 1e-10)); Assert.assertNull(plusSplit.getMinus()); Assert.assertNotNull(plusSplit.getPlus()); - + SplitSubHyperplane lowWithinTolerance = pt.split(new OrientedPoint(new Cartesian1D(0.901), true, 1e-10)); Assert.assertNull(lowWithinTolerance.getMinus()); Assert.assertNull(lowWithinTolerance.getPlus()); - + SplitSubHyperplane highWithinTolerance = pt.split(new OrientedPoint(new Cartesian1D(1.09), true, 1e-10)); Assert.assertNull(highWithinTolerance.getMinus()); Assert.assertNull(highWithinTolerance.getPlus()); - + SplitSubHyperplane minusSplit = pt.split(new OrientedPoint(new Cartesian1D(1.101), true, 1e-10)); Assert.assertNotNull(minusSplit.getMinus()); Assert.assertNull(minusSplit.getPlus()); diff --git a/src/test/java/org/apache/commons/math4/geometry/euclidean/twod/PolygonsSetTest.java b/src/test/java/org/apache/commons/math4/geometry/euclidean/twod/PolygonsSetTest.java index cdb9d7153..1385d4abb 100644 --- a/src/test/java/org/apache/commons/math4/geometry/euclidean/twod/PolygonsSetTest.java +++ b/src/test/java/org/apache/commons/math4/geometry/euclidean/twod/PolygonsSetTest.java @@ -95,53 +95,53 @@ public class PolygonsSetTest { PolygonsSet box = new PolygonsSet(new BSPTree(Boolean.TRUE), 1.0e-10); Assert.assertTrue(Double.isInfinite(box.getSize())); } - + @Test public void testSingleInfiniteLine() { - // arrange + // arrange double tolerance = 1e-10; Line line = new Line(new Cartesian2D(0, 0), new Cartesian2D(1, 1), tolerance); - + List> boundaries = new ArrayList>(); boundaries.add(line.wholeHyperplane()); - + // act PolygonsSet polygon = new PolygonsSet(boundaries, tolerance); - + // assert Assert.assertTrue(Double.isInfinite(polygon.getSize())); - + Cartesian2D[][] vertices = polygon.getVertices(); Assert.assertEquals(1, vertices.length); - + Cartesian2D[] loop = vertices[0]; Assert.assertEquals(3, loop.length); Assert.assertEquals(null, loop[0]); checkPointsEqual(line.toSpace(new Cartesian1D(-Float.MAX_VALUE)), loop[1], tolerance); checkPointsEqual(line.toSpace(new Cartesian1D(Float.MAX_VALUE)), loop[2], tolerance); } - + @Test public void testMixOfFiniteAndInfiniteBoundaries() { - // arrange + // arrange double tolerance = 1e-10; - + Line line = new Line(new Cartesian2D(1, 0), new Cartesian2D(1, 1), tolerance); - + List> boundaries = new ArrayList>(); boundaries.add(buildSegment(new Cartesian2D(0, 1), new Cartesian2D(0, 0))); boundaries.add(buildSegment(new Cartesian2D(0, 0), new Cartesian2D(1, 0))); boundaries.add(new SubLine(line, new IntervalsSet(0, Double.POSITIVE_INFINITY, tolerance))); - + // act PolygonsSet polygon = new PolygonsSet(boundaries, tolerance); // assert Assert.assertTrue(Double.isInfinite(polygon.getSize())); - + Cartesian2D[][] vertices = polygon.getVertices(); Assert.assertEquals(1, vertices.length); - + Cartesian2D[] loop = vertices[0]; Assert.assertEquals(5, loop.length); Assert.assertEquals(null, loop[0]); @@ -1327,7 +1327,7 @@ public class PolygonsSetTest { double upper = (line.toSubSpace(end)).getX(); return new SubLine(line, new IntervalsSet(lower, upper, 1.0e-10)); } - + private void checkPointsEqual(Cartesian2D expected, Cartesian2D actual, double tolerance) { Assert.assertEquals(expected.getX(), actual.getX(), tolerance); Assert.assertEquals(expected.getY(), actual.getY(), tolerance);