Merge commit 'refs/pull/73/head' of https://github.com/apache/commons-math into fix-MATH-1436

This commit is contained in:
Gilles 2017-12-25 10:02:17 +01:00
commit 5ec8070228
2 changed files with 99 additions and 28 deletions

View File

@ -644,7 +644,11 @@ 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) {
if (loop.get(0).getStart() == 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
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);
} else { } else {
@ -863,6 +867,9 @@ 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
// to be unnecessary
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();
@ -876,6 +883,7 @@ public class PolygonsSet extends AbstractRegion<Euclidean2D, Euclidean1D> {
} }
} }
} }
}
/** Private extension of Segment allowing connection. */ /** Private extension of Segment allowing connection. */
private static class ConnectableSegment extends Segment { private static class ConnectableSegment extends Segment {
@ -1067,10 +1075,10 @@ public class PolygonsSet extends AbstractRegion<Euclidean2D, Euclidean1D> {
/** Select the node whose cut sub-hyperplane is closest to specified point. /** Select the node whose cut sub-hyperplane is closest to specified point.
* @param point reference point * @param point reference point
* @param candidates candidate nodes * @param candidates candidate nodes
* @return node closest to point, or null if 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) {
BSPTree<Euclidean2D> selected = null; BSPTree<Euclidean2D> selected = null;
double min = Double.POSITIVE_INFINITY; double min = Double.POSITIVE_INFINITY;
@ -1082,8 +1090,11 @@ public class PolygonsSet extends AbstractRegion<Euclidean2D, Euclidean1D> {
} }
} }
return min <= tolerance ? selected : null; if (min <= tolerance) {
return selected;
}
}
return null;
} }
/** Get the segments. /** Get the segments.

View File

@ -96,6 +96,61 @@ public class PolygonsSetTest {
Assert.assertTrue(Double.isInfinite(box.getSize())); Assert.assertTrue(Double.isInfinite(box.getSize()));
} }
@Test
public void testSingleInfiniteLine() {
// arrange
double tolerance = 1e-10;
Line line = new Line(new Cartesian2D(0, 0), new Cartesian2D(1, 1), tolerance);
List<SubHyperplane<Euclidean2D>> boundaries = new ArrayList<SubHyperplane<Euclidean2D>>();
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
double tolerance = 1e-10;
Line line = new Line(new Cartesian2D(1, 0), new Cartesian2D(1, 1), tolerance);
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, 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]);
checkPointsEqual(new Cartesian2D(0, 1), loop[1], tolerance);
checkPointsEqual(new Cartesian2D(0, 0), loop[2], tolerance);
checkPointsEqual(new Cartesian2D(1, 0), loop[3], tolerance);
checkPointsEqual(new Cartesian2D(1, 0), loop[4], tolerance);
}
@Test @Test
public void testStair() { public void testStair() {
Cartesian2D[][] vertices = new Cartesian2D[][] { Cartesian2D[][] vertices = new Cartesian2D[][] {
@ -1273,6 +1328,11 @@ public class PolygonsSetTest {
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) {
Assert.assertEquals(expected.getX(), actual.getX(), tolerance);
Assert.assertEquals(expected.getY(), actual.getY(), tolerance);
}
private void checkPoints(Region.Location expected, PolygonsSet set, private void checkPoints(Region.Location expected, PolygonsSet set,
Cartesian2D[] points) { Cartesian2D[] points) {
for (int i = 0; i < points.length; ++i) { for (int i = 0; i < points.length; ++i) {