This commit is contained in:
Gilles 2017-12-25 10:25:18 +01:00
parent 5ec8070228
commit 29c067466e
3 changed files with 137 additions and 137 deletions

View File

@ -644,10 +644,10 @@ public class PolygonsSet extends AbstractRegion<Euclidean2D, Euclidean1D> {
for (ConnectableSegment s = getUnprocessed(segments); s != null; s = getUnprocessed(segments)) { for (ConnectableSegment s = getUnprocessed(segments); s != null; s = getUnprocessed(segments)) {
final List<Segment> loop = followLoop(s); final List<Segment> loop = followLoop(s);
if (loop != null) { if (loop != null) {
// an open loop is one that has fewer than two segments or has a 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 // start point; the case where we have two segments in a closed loop
// (ie, an infinitely thin, degenerate loop) will result in null being // (ie, an infinitely thin, degenerate loop) will result in null being
// returned from the followLoops method // returned from the followLoops method
if (loop.size() < 2 || loop.get(0).getStart() == null) { if (loop.size() < 2 || loop.get(0).getStart() == null) {
// this is an open loop, we put it on the front // this is an open loop, we put it on the front
loops.add(0, loop); loops.add(0, loop);
@ -867,22 +867,22 @@ public class PolygonsSet extends AbstractRegion<Euclidean2D, Euclidean1D> {
* @param loop segments loop to filter (will be modified in-place) * @param loop segments loop to filter (will be modified in-place)
*/ */
private void filterSpuriousVertices(final List<Segment> loop) { private void filterSpuriousVertices(final List<Segment> loop) {
// we need at least 2 segments in order for one of the contained vertices // we need at least 2 segments in order for one of the contained vertices
// to be unnecessary // to be unnecessary
if (loop.size() > 1) { if (loop.size() > 1) {
for (int i = 0; i < loop.size(); ++i) { for (int i = 0; i < loop.size(); ++i) {
final Segment previous = loop.get(i); final Segment previous = loop.get(i);
int j = (i + 1) % loop.size(); int j = (i + 1) % loop.size();
final Segment next = loop.get(j); final Segment next = loop.get(j);
if (next != null && if (next != null &&
Precision.equals(previous.getLine().getAngle(), next.getLine().getAngle(), Precision.EPSILON)) { Precision.equals(previous.getLine().getAngle(), next.getLine().getAngle(), Precision.EPSILON)) {
// the vertex between the two edges is a spurious one // the vertex between the two edges is a spurious one
// replace the two segments by a single one // replace the two segments by a single one
loop.set(j, new Segment(previous.getStart(), next.getEnd(), previous.getLine())); loop.set(j, new Segment(previous.getStart(), next.getEnd(), previous.getLine()));
loop.remove(i--); loop.remove(i--);
} }
} }
} }
} }
/** Private extension of Segment allowing connection. */ /** Private extension of Segment allowing connection. */
@ -1078,23 +1078,23 @@ public class PolygonsSet extends AbstractRegion<Euclidean2D, Euclidean1D> {
* @return node closest to point, or null if point is null or no node is closer than tolerance * @return node closest to point, or null if point is null or no node is closer than tolerance
*/ */
private BSPTree<Euclidean2D> selectClosest(final Cartesian2D point, final Iterable<BSPTree<Euclidean2D>> candidates) { private BSPTree<Euclidean2D> selectClosest(final Cartesian2D point, final Iterable<BSPTree<Euclidean2D>> candidates) {
if (point != null) { if (point != null) {
BSPTree<Euclidean2D> selected = null; BSPTree<Euclidean2D> selected = null;
double min = Double.POSITIVE_INFINITY; double min = Double.POSITIVE_INFINITY;
for (final BSPTree<Euclidean2D> node : candidates) { for (final BSPTree<Euclidean2D> node : candidates) {
final double distance = FastMath.abs(node.getCut().getHyperplane().getOffset(point)); final double distance = FastMath.abs(node.getCut().getHyperplane().getOffset(point));
if (distance < min) { if (distance < min) {
selected = node; selected = node;
min = distance; min = distance;
} }
} }
if (min <= tolerance) { if (min <= tolerance) {
return selected; return selected;
} }
} }
return null; return null;
} }
/** Get the segments. /** Get the segments.

View File

@ -26,141 +26,141 @@ import org.junit.Test;
public class SubOrientedPointTest { public class SubOrientedPointTest {
private static final double TEST_TOLERANCE = 1e-10; private static final double TEST_TOLERANCE = 1e-10;
@Test @Test
public void testGetSize() { public void testGetSize() {
// arrange // arrange
OrientedPoint hyperplane = new OrientedPoint(new Cartesian1D(1), true, TEST_TOLERANCE); OrientedPoint hyperplane = new OrientedPoint(new Cartesian1D(1), true, TEST_TOLERANCE);
SubOrientedPoint pt = (SubOrientedPoint) hyperplane.wholeHyperplane(); SubOrientedPoint pt = (SubOrientedPoint) hyperplane.wholeHyperplane();
// act/assert // act/assert
Assert.assertEquals(0.0, pt.getSize(), TEST_TOLERANCE); Assert.assertEquals(0.0, pt.getSize(), TEST_TOLERANCE);
} }
@Test @Test
public void testIsEmpty() { public void testIsEmpty() {
// arrange // arrange
OrientedPoint hyperplane = new OrientedPoint(new Cartesian1D(1), true, TEST_TOLERANCE); OrientedPoint hyperplane = new OrientedPoint(new Cartesian1D(1), true, TEST_TOLERANCE);
SubOrientedPoint pt = (SubOrientedPoint) hyperplane.wholeHyperplane(); SubOrientedPoint pt = (SubOrientedPoint) hyperplane.wholeHyperplane();
// act/assert // act/assert
Assert.assertFalse(pt.isEmpty()); Assert.assertFalse(pt.isEmpty());
} }
@Test @Test
public void testBuildNew() { public void testBuildNew() {
// arrange // arrange
OrientedPoint originalHyperplane = new OrientedPoint(new Cartesian1D(1), true, TEST_TOLERANCE); OrientedPoint originalHyperplane = new OrientedPoint(new Cartesian1D(1), true, TEST_TOLERANCE);
SubOrientedPoint pt = (SubOrientedPoint) originalHyperplane.wholeHyperplane(); SubOrientedPoint pt = (SubOrientedPoint) originalHyperplane.wholeHyperplane();
OrientedPoint hyperplane = new OrientedPoint(new Cartesian1D(2), true, TEST_TOLERANCE); OrientedPoint hyperplane = new OrientedPoint(new Cartesian1D(2), true, TEST_TOLERANCE);
IntervalsSet intervals = new IntervalsSet(2, 3, TEST_TOLERANCE); IntervalsSet intervals = new IntervalsSet(2, 3, TEST_TOLERANCE);
// act // act
SubHyperplane<Euclidean1D> result = pt.buildNew(hyperplane, intervals); SubHyperplane<Euclidean1D> result = pt.buildNew(hyperplane, intervals);
// assert // assert
Assert.assertTrue(result instanceof SubOrientedPoint); Assert.assertTrue(result instanceof SubOrientedPoint);
Assert.assertSame(hyperplane, result.getHyperplane()); Assert.assertSame(hyperplane, result.getHyperplane());
Assert.assertSame(intervals, ((SubOrientedPoint) result).getRemainingRegion()); Assert.assertSame(intervals, ((SubOrientedPoint) result).getRemainingRegion());
} }
@Test @Test
public void testSplit_resultOnMinusSide() { public void testSplit_resultOnMinusSide() {
// arrange // arrange
OrientedPoint hyperplane = new OrientedPoint(new Cartesian1D(1), true, TEST_TOLERANCE); OrientedPoint hyperplane = new OrientedPoint(new Cartesian1D(1), true, TEST_TOLERANCE);
IntervalsSet interval = new IntervalsSet(4, 5, TEST_TOLERANCE); IntervalsSet interval = new IntervalsSet(4, 5, TEST_TOLERANCE);
SubOrientedPoint pt = new SubOrientedPoint(hyperplane, interval); SubOrientedPoint pt = new SubOrientedPoint(hyperplane, interval);
OrientedPoint splitter = new OrientedPoint(new Cartesian1D(2), true, TEST_TOLERANCE); OrientedPoint splitter = new OrientedPoint(new Cartesian1D(2), true, TEST_TOLERANCE);
// act // act
SplitSubHyperplane<Euclidean1D> split = pt.split(splitter); SplitSubHyperplane<Euclidean1D> split = pt.split(splitter);
// assert // assert
Assert.assertEquals(Side.MINUS, split.getSide()); Assert.assertEquals(Side.MINUS, split.getSide());
SubOrientedPoint minusSub = ((SubOrientedPoint) split.getMinus()); SubOrientedPoint minusSub = ((SubOrientedPoint) split.getMinus());
Assert.assertNotNull(minusSub); Assert.assertNotNull(minusSub);
OrientedPoint minusHyper = (OrientedPoint) minusSub.getHyperplane(); OrientedPoint minusHyper = (OrientedPoint) minusSub.getHyperplane();
Assert.assertEquals(1, minusHyper.getLocation().getX(), TEST_TOLERANCE); Assert.assertEquals(1, minusHyper.getLocation().getX(), TEST_TOLERANCE);
List<Interval> minusIntervals = ((IntervalsSet) minusSub.getRemainingRegion()).asList(); List<Interval> minusIntervals = ((IntervalsSet) minusSub.getRemainingRegion()).asList();
Assert.assertEquals(1, minusIntervals.size()); Assert.assertEquals(1, minusIntervals.size());
Assert.assertEquals(4, minusIntervals.get(0).getInf(), TEST_TOLERANCE); Assert.assertEquals(4, minusIntervals.get(0).getInf(), TEST_TOLERANCE);
Assert.assertEquals(5, minusIntervals.get(0).getSup(), TEST_TOLERANCE); Assert.assertEquals(5, minusIntervals.get(0).getSup(), TEST_TOLERANCE);
Assert.assertNull(split.getPlus()); Assert.assertNull(split.getPlus());
} }
@Test @Test
public void testSplit_resultOnPlusSide() { public void testSplit_resultOnPlusSide() {
// arrange // arrange
OrientedPoint hyperplane = new OrientedPoint(new Cartesian1D(1), true, TEST_TOLERANCE); OrientedPoint hyperplane = new OrientedPoint(new Cartesian1D(1), true, TEST_TOLERANCE);
IntervalsSet interval = new IntervalsSet(4, 5, TEST_TOLERANCE); IntervalsSet interval = new IntervalsSet(4, 5, TEST_TOLERANCE);
SubOrientedPoint pt = new SubOrientedPoint(hyperplane, interval); SubOrientedPoint pt = new SubOrientedPoint(hyperplane, interval);
OrientedPoint splitter = new OrientedPoint(new Cartesian1D(0), true, TEST_TOLERANCE); OrientedPoint splitter = new OrientedPoint(new Cartesian1D(0), true, TEST_TOLERANCE);
// act // act
SplitSubHyperplane<Euclidean1D> split = pt.split(splitter); SplitSubHyperplane<Euclidean1D> split = pt.split(splitter);
// assert // assert
Assert.assertEquals(Side.PLUS, split.getSide()); Assert.assertEquals(Side.PLUS, split.getSide());
Assert.assertNull(split.getMinus()); Assert.assertNull(split.getMinus());
SubOrientedPoint plusSub = ((SubOrientedPoint) split.getPlus()); SubOrientedPoint plusSub = ((SubOrientedPoint) split.getPlus());
Assert.assertNotNull(plusSub); Assert.assertNotNull(plusSub);
OrientedPoint plusHyper = (OrientedPoint) plusSub.getHyperplane(); OrientedPoint plusHyper = (OrientedPoint) plusSub.getHyperplane();
Assert.assertEquals(1, plusHyper.getLocation().getX(), TEST_TOLERANCE); Assert.assertEquals(1, plusHyper.getLocation().getX(), TEST_TOLERANCE);
List<Interval> plusIntervals = ((IntervalsSet) plusSub.getRemainingRegion()).asList(); List<Interval> plusIntervals = ((IntervalsSet) plusSub.getRemainingRegion()).asList();
Assert.assertEquals(1, plusIntervals.size()); Assert.assertEquals(1, plusIntervals.size());
Assert.assertEquals(4, plusIntervals.get(0).getInf(), TEST_TOLERANCE); Assert.assertEquals(4, plusIntervals.get(0).getInf(), TEST_TOLERANCE);
Assert.assertEquals(5, plusIntervals.get(0).getSup(), TEST_TOLERANCE); Assert.assertEquals(5, plusIntervals.get(0).getSup(), TEST_TOLERANCE);
} }
@Test @Test
public void testSplit_equivalentHyperplanes() { public void testSplit_equivalentHyperplanes() {
// arrange // arrange
OrientedPoint hyperplane = new OrientedPoint(new Cartesian1D(1), true, TEST_TOLERANCE); OrientedPoint hyperplane = new OrientedPoint(new Cartesian1D(1), true, TEST_TOLERANCE);
IntervalsSet interval = new IntervalsSet(4, 5, TEST_TOLERANCE); IntervalsSet interval = new IntervalsSet(4, 5, TEST_TOLERANCE);
SubOrientedPoint pt = new SubOrientedPoint(hyperplane, interval); SubOrientedPoint pt = new SubOrientedPoint(hyperplane, interval);
OrientedPoint splitter = new OrientedPoint(new Cartesian1D(1), true, TEST_TOLERANCE); OrientedPoint splitter = new OrientedPoint(new Cartesian1D(1), true, TEST_TOLERANCE);
// act // act
SplitSubHyperplane<Euclidean1D> split = pt.split(splitter); SplitSubHyperplane<Euclidean1D> split = pt.split(splitter);
// assert // assert
Assert.assertEquals(Side.HYPER, split.getSide()); Assert.assertEquals(Side.HYPER, split.getSide());
Assert.assertNull(split.getMinus()); Assert.assertNull(split.getMinus());
Assert.assertNull(split.getPlus()); Assert.assertNull(split.getPlus());
} }
@Test @Test
public void testSplit_usesToleranceFromParentHyperplane() { public void testSplit_usesToleranceFromParentHyperplane() {
// arrange // arrange
OrientedPoint hyperplane = new OrientedPoint(new Cartesian1D(1), true, 0.1); OrientedPoint hyperplane = new OrientedPoint(new Cartesian1D(1), true, 0.1);
SubOrientedPoint pt = (SubOrientedPoint) hyperplane.wholeHyperplane(); SubOrientedPoint pt = (SubOrientedPoint) hyperplane.wholeHyperplane();
// act/assert // act/assert
SplitSubHyperplane<Euclidean1D> plusSplit = pt.split(new OrientedPoint(new Cartesian1D(0.899), true, 1e-10)); SplitSubHyperplane<Euclidean1D> plusSplit = pt.split(new OrientedPoint(new Cartesian1D(0.899), true, 1e-10));
Assert.assertNull(plusSplit.getMinus()); Assert.assertNull(plusSplit.getMinus());
Assert.assertNotNull(plusSplit.getPlus()); Assert.assertNotNull(plusSplit.getPlus());
SplitSubHyperplane<Euclidean1D> lowWithinTolerance = pt.split(new OrientedPoint(new Cartesian1D(0.901), true, 1e-10)); SplitSubHyperplane<Euclidean1D> lowWithinTolerance = pt.split(new OrientedPoint(new Cartesian1D(0.901), true, 1e-10));
Assert.assertNull(lowWithinTolerance.getMinus()); Assert.assertNull(lowWithinTolerance.getMinus());
Assert.assertNull(lowWithinTolerance.getPlus()); Assert.assertNull(lowWithinTolerance.getPlus());
SplitSubHyperplane<Euclidean1D> highWithinTolerance = pt.split(new OrientedPoint(new Cartesian1D(1.09), true, 1e-10)); SplitSubHyperplane<Euclidean1D> highWithinTolerance = pt.split(new OrientedPoint(new Cartesian1D(1.09), true, 1e-10));
Assert.assertNull(highWithinTolerance.getMinus()); Assert.assertNull(highWithinTolerance.getMinus());
Assert.assertNull(highWithinTolerance.getPlus()); Assert.assertNull(highWithinTolerance.getPlus());
SplitSubHyperplane<Euclidean1D> minusSplit = pt.split(new OrientedPoint(new Cartesian1D(1.101), true, 1e-10)); SplitSubHyperplane<Euclidean1D> minusSplit = pt.split(new OrientedPoint(new Cartesian1D(1.101), true, 1e-10));
Assert.assertNotNull(minusSplit.getMinus()); Assert.assertNotNull(minusSplit.getMinus());
Assert.assertNull(minusSplit.getPlus()); Assert.assertNull(minusSplit.getPlus());

View File

@ -95,53 +95,53 @@ public class PolygonsSetTest {
PolygonsSet box = new PolygonsSet(new BSPTree<Euclidean2D>(Boolean.TRUE), 1.0e-10); PolygonsSet box = new PolygonsSet(new BSPTree<Euclidean2D>(Boolean.TRUE), 1.0e-10);
Assert.assertTrue(Double.isInfinite(box.getSize())); Assert.assertTrue(Double.isInfinite(box.getSize()));
} }
@Test @Test
public void testSingleInfiniteLine() { public void testSingleInfiniteLine() {
// arrange // arrange
double tolerance = 1e-10; double tolerance = 1e-10;
Line line = new Line(new Cartesian2D(0, 0), new Cartesian2D(1, 1), tolerance); Line line = new Line(new Cartesian2D(0, 0), new Cartesian2D(1, 1), tolerance);
List<SubHyperplane<Euclidean2D>> boundaries = new ArrayList<SubHyperplane<Euclidean2D>>(); List<SubHyperplane<Euclidean2D>> boundaries = new ArrayList<SubHyperplane<Euclidean2D>>();
boundaries.add(line.wholeHyperplane()); boundaries.add(line.wholeHyperplane());
// act // act
PolygonsSet polygon = new PolygonsSet(boundaries, tolerance); PolygonsSet polygon = new PolygonsSet(boundaries, tolerance);
// assert // assert
Assert.assertTrue(Double.isInfinite(polygon.getSize())); Assert.assertTrue(Double.isInfinite(polygon.getSize()));
Cartesian2D[][] vertices = polygon.getVertices(); Cartesian2D[][] vertices = polygon.getVertices();
Assert.assertEquals(1, vertices.length); Assert.assertEquals(1, vertices.length);
Cartesian2D[] loop = vertices[0]; Cartesian2D[] loop = vertices[0];
Assert.assertEquals(3, loop.length); Assert.assertEquals(3, loop.length);
Assert.assertEquals(null, loop[0]); 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[1], tolerance);
checkPointsEqual(line.toSpace(new Cartesian1D(Float.MAX_VALUE)), loop[2], tolerance); checkPointsEqual(line.toSpace(new Cartesian1D(Float.MAX_VALUE)), loop[2], tolerance);
} }
@Test @Test
public void testMixOfFiniteAndInfiniteBoundaries() { public void testMixOfFiniteAndInfiniteBoundaries() {
// arrange // arrange
double tolerance = 1e-10; double tolerance = 1e-10;
Line line = new Line(new Cartesian2D(1, 0), new Cartesian2D(1, 1), tolerance); Line line = new Line(new Cartesian2D(1, 0), new Cartesian2D(1, 1), tolerance);
List<SubHyperplane<Euclidean2D>> boundaries = new ArrayList<SubHyperplane<Euclidean2D>>(); List<SubHyperplane<Euclidean2D>> boundaries = new ArrayList<SubHyperplane<Euclidean2D>>();
boundaries.add(buildSegment(new Cartesian2D(0, 1), new Cartesian2D(0, 0))); boundaries.add(buildSegment(new Cartesian2D(0, 1), new Cartesian2D(0, 0)));
boundaries.add(buildSegment(new Cartesian2D(0, 0), new Cartesian2D(1, 0))); boundaries.add(buildSegment(new Cartesian2D(0, 0), new Cartesian2D(1, 0)));
boundaries.add(new SubLine(line, new IntervalsSet(0, Double.POSITIVE_INFINITY, tolerance))); boundaries.add(new SubLine(line, new IntervalsSet(0, Double.POSITIVE_INFINITY, tolerance)));
// act // act
PolygonsSet polygon = new PolygonsSet(boundaries, tolerance); PolygonsSet polygon = new PolygonsSet(boundaries, tolerance);
// assert // assert
Assert.assertTrue(Double.isInfinite(polygon.getSize())); Assert.assertTrue(Double.isInfinite(polygon.getSize()));
Cartesian2D[][] vertices = polygon.getVertices(); Cartesian2D[][] vertices = polygon.getVertices();
Assert.assertEquals(1, vertices.length); Assert.assertEquals(1, vertices.length);
Cartesian2D[] loop = vertices[0]; Cartesian2D[] loop = vertices[0];
Assert.assertEquals(5, loop.length); Assert.assertEquals(5, loop.length);
Assert.assertEquals(null, loop[0]); Assert.assertEquals(null, loop[0]);
@ -1327,7 +1327,7 @@ public class PolygonsSetTest {
double upper = (line.toSubSpace(end)).getX(); double upper = (line.toSubSpace(end)).getX();
return new SubLine(line, new IntervalsSet(lower, upper, 1.0e-10)); return new SubLine(line, new IntervalsSet(lower, upper, 1.0e-10));
} }
private void checkPointsEqual(Cartesian2D expected, Cartesian2D actual, double tolerance) { private void checkPointsEqual(Cartesian2D expected, Cartesian2D actual, double tolerance) {
Assert.assertEquals(expected.getX(), actual.getX(), tolerance); Assert.assertEquals(expected.getX(), actual.getX(), tolerance);
Assert.assertEquals(expected.getY(), actual.getY(), tolerance); Assert.assertEquals(expected.getY(), actual.getY(), tolerance);