Skip to content

Commit 36f261e

Browse files
committed
Shamos-Hoey simple polygon detection bug fix
1 parent 16c770a commit 36f261e

File tree

2 files changed

+45
-11
lines changed

2 files changed

+45
-11
lines changed

src/main/java/mil/nga/sf/util/sweep/ShamosHoey.java

Lines changed: 23 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,11 @@
11
package mil.nga.sf.util.sweep;
22

33
import java.util.ArrayList;
4+
import java.util.HashMap;
5+
import java.util.HashSet;
46
import java.util.List;
7+
import java.util.Map;
8+
import java.util.Set;
59

610
import mil.nga.sf.LineString;
711
import mil.nga.sf.Point;
@@ -115,22 +119,31 @@ public static boolean simplePolygon(List<LineString> rings) {
115119
}
116120
}
117121

118-
// Remove duplicate consecutive points
119-
for (int j = 0; j < ringCopyPoints.size() - 1; j++) {
120-
Point point = ringCopyPoints.get(j);
121-
Point next = ringCopyPoints.get(j + 1);
122-
if (point.equalsXY(next)) {
123-
ringCopyPoints.remove(j + 1);
124-
j--;
125-
}
126-
}
127-
128122
// Verify enough ring points
129123
if (ringCopyPoints.size() < 3) {
130124
simple = false;
131125
break;
132126
}
133127

128+
// Check for duplicate points (thus connecting more than two edges
129+
// and not simple)
130+
Map<Double, Set<Double>> pointValues = new HashMap<>();
131+
for (Point point : ringCopyPoints) {
132+
double x = point.getX();
133+
double y = point.getY();
134+
Set<Double> xValues = pointValues.get(x);
135+
if (xValues == null) {
136+
xValues = new HashSet<>();
137+
xValues.add(y);
138+
pointValues.put(x, xValues);
139+
} else if (!xValues.contains(y)) {
140+
xValues.add(y);
141+
} else {
142+
simple = false;
143+
break;
144+
}
145+
}
146+
134147
// Check holes to make sure the first point is in the polygon
135148
if (i > 0) {
136149
Point firstPoint = ringCopyPoints.get(0);

src/test/java/mil/nga/sf/util/sweep/ShamosHoeyTest.java

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -179,7 +179,22 @@ public void testNonSimple() throws IOException {
179179
TestCase.assertFalse(
180180
ShamosHoey.simplePolygon(new Polygon(new LineString(points))));
181181
TestCase.assertFalse((new LineString(points)).isSimple());
182-
TestCase.assertFalse((new Polygon(new LineString(points))).isSimple());
182+
complex(new Polygon(new LineString(points)));
183+
TestCase.assertEquals(4, points.size());
184+
185+
points.clear();
186+
187+
addPoint(points, 1, 0);
188+
addPoint(points, 0, 1);
189+
addPoint(points, 1, 0);
190+
addPoint(points, 2, 2);
191+
192+
TestCase.assertFalse(ShamosHoey.simplePolygonPoints(points));
193+
TestCase.assertFalse(ShamosHoey.simplePolygon(new LineString(points)));
194+
TestCase.assertFalse(
195+
ShamosHoey.simplePolygon(new Polygon(new LineString(points))));
196+
TestCase.assertFalse((new LineString(points)).isSimple());
197+
complex(new Polygon(new LineString(points)));
183198
TestCase.assertEquals(4, points.size());
184199

185200
}
@@ -828,6 +843,12 @@ private void validate(Polygon polygon, boolean simple) {
828843
Polygon copy = new Polygon(polygon);
829844
List<Point> points = copy.getRing(0).getPoints();
830845

846+
Point first = points.get(0);
847+
Point last = points.get(points.size() - 1);
848+
if (first.equalsXY(last)) {
849+
points.remove(points.size() - 1);
850+
}
851+
831852
for (int i = 1; i < points.size(); i++) {
832853

833854
points.add(points.remove(0));

0 commit comments

Comments
 (0)