Skip to content

Commit 24e7754

Browse files
committed
Shamos-Hoey simple polygon detection bug fix
1 parent be7b2c6 commit 24e7754

3 files changed

Lines changed: 230 additions & 7 deletions

File tree

CHANGELOG.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ Adheres to [Semantic Versioning](http://semver.org/).
66

77
## 2.2.1 (TBD)
88

9-
* TBD
9+
* Shamos-Hoey simple polygon detection bug fix
1010

1111
## [2.2.0](https://github.com/ngageoint/simple-features-java/releases/tag/2.2.0) (09-21-2022)
1212

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

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -116,12 +116,18 @@ public Segment add(Event event) {
116116

117117
// Update the above and below pointers
118118
Segment next = tree.higher(segment);
119+
if (next == null) {
120+
next = tree.first();
121+
}
119122
Segment previous = tree.lower(segment);
120-
if (next != null) {
123+
if (previous == null) {
124+
previous = tree.last();
125+
}
126+
if (next != segment) {
121127
segment.setAbove(next);
122128
next.setBelow(segment);
123129
}
124-
if (previous != null) {
130+
if (previous != segment) {
125131
segment.setBelow(previous);
126132
previous.setAbove(segment);
127133
}
@@ -194,7 +200,7 @@ public boolean intersect(Segment segment1, Segment segment2) {
194200

195201
boolean intersect = false;
196202

197-
if (segment1 != null && segment2 != null) {
203+
if (segment1 != null && segment2 != null && segment1 != segment2) {
198204

199205
int ring1 = segment1.getRing();
200206
int ring2 = segment2.getRing();
@@ -329,10 +335,9 @@ private static double isLeft(Segment segment, Point point) {
329335
* @return > 0 if left, 0 if on, < 0 if right
330336
*/
331337
private static double isLeft(Point point0, Point point1, Point point2) {
332-
return (point1.getX() - point0.getX())
333-
* (point2.getY() - point0.getY())
338+
return (point1.getX() - point0.getX()) * (point2.getY() - point0.getY())
334339
- (point2.getX() - point0.getX())
335-
* (point1.getY() - point0.getY());
340+
* (point1.getY() - point0.getY());
336341
}
337342

338343
}

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

Lines changed: 218 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -568,6 +568,224 @@ public void testLargeNonSimple() throws IOException {
568568
points.size());
569569
}
570570

571+
@Test
572+
public void testPolygons1() {
573+
574+
LineString ring = new LineString();
575+
ring.addPoint(new Point(0, 0));
576+
ring.addPoint(new Point(4, 4));
577+
ring.addPoint(new Point(0, 4));
578+
ring.addPoint(new Point(4, 0));
579+
Polygon polygon = new Polygon(ring);
580+
581+
TestCase.assertFalse(polygon.isSimple());
582+
583+
ring = new LineString();
584+
ring.addPoint(new Point(0, 0));
585+
ring.addPoint(new Point(4, 0));
586+
ring.addPoint(new Point(4, 4));
587+
ring.addPoint(new Point(0, 4));
588+
polygon = new Polygon(ring);
589+
590+
TestCase.assertTrue(polygon.isSimple());
591+
592+
ring = new LineString();
593+
ring.addPoint(new Point(0, 4));
594+
ring.addPoint(new Point(4, 0));
595+
ring.addPoint(new Point(0, 0));
596+
ring.addPoint(new Point(4, 4));
597+
polygon = new Polygon(ring);
598+
599+
TestCase.assertFalse(polygon.isSimple());
600+
601+
ring = new LineString();
602+
ring.addPoint(new Point(0, 4));
603+
ring.addPoint(new Point(4, 4));
604+
ring.addPoint(new Point(4, 0));
605+
ring.addPoint(new Point(0, 0));
606+
polygon = new Polygon(ring);
607+
608+
TestCase.assertTrue(polygon.isSimple());
609+
610+
ring = new LineString();
611+
ring.addPoint(new Point(0, 0));
612+
ring.addPoint(new Point(4, 4));
613+
ring.addPoint(new Point(1, 3));
614+
ring.addPoint(new Point(3, 1));
615+
polygon = new Polygon(ring);
616+
617+
TestCase.assertFalse(polygon.isSimple());
618+
619+
ring = new LineString();
620+
ring.addPoint(new Point(0, 0));
621+
ring.addPoint(new Point(3, 1));
622+
ring.addPoint(new Point(4, 4));
623+
ring.addPoint(new Point(1, 3));
624+
polygon = new Polygon(ring);
625+
626+
TestCase.assertTrue(polygon.isSimple());
627+
628+
ring = new LineString();
629+
ring.addPoint(new Point(1, 3));
630+
ring.addPoint(new Point(3, 1));
631+
ring.addPoint(new Point(0, 0));
632+
ring.addPoint(new Point(4, 4));
633+
polygon = new Polygon(ring);
634+
635+
TestCase.assertFalse(polygon.isSimple());
636+
637+
ring = new LineString();
638+
ring.addPoint(new Point(1, 3));
639+
ring.addPoint(new Point(4, 4));
640+
ring.addPoint(new Point(3, 1));
641+
ring.addPoint(new Point(0, 0));
642+
polygon = new Polygon(ring);
643+
644+
TestCase.assertTrue(polygon.isSimple());
645+
646+
}
647+
648+
@Test
649+
public void testPolygons2() {
650+
651+
LineString ring = new LineString();
652+
ring.addPoint(new Point(119.65450502825215, 234.97190110269844));
653+
ring.addPoint(new Point(120.94208471603682, 241.47274889005215));
654+
ring.addPoint(new Point(120.57389187028015, 240.42380619065557));
655+
ring.addPoint(new Point(120.40553233952696, 239.3249423106921));
656+
ring.addPoint(new Point(120.44278575100797, 238.2138802324909));
657+
ring.addPoint(new Point(120.68437322950616, 237.12876169126298));
658+
ring.addPoint(new Point(121.12200129996195, 236.1068378045508));
659+
ring.addPoint(new Point(121.74064659481407, 235.18319027576013));
660+
ring.addPoint(new Point(122.51907159233552, 234.38952707167576));
661+
Polygon polygon = new Polygon(ring);
662+
663+
TestCase.assertFalse(polygon.isSimple());
664+
665+
ring = new LineString();
666+
ring.addPoint(new Point(119.65450502825215, 234.97190110269844));
667+
ring.addPoint(new Point(120.94208471603682, 241.47274889005215));
668+
// ring.addPoint(new Point(120.57389187028015, 240.42380619065557));
669+
// ring.addPoint(new Point(120.40553233952696, 239.3249423106921));
670+
ring.addPoint(new Point(120.44278575100797, 238.2138802324909));
671+
ring.addPoint(new Point(120.68437322950616, 237.12876169126298));
672+
ring.addPoint(new Point(121.12200129996195, 236.1068378045508));
673+
ring.addPoint(new Point(121.74064659481407, 235.18319027576013));
674+
ring.addPoint(new Point(122.51907159233552, 234.38952707167576));
675+
polygon = new Polygon(ring);
676+
677+
TestCase.assertTrue(polygon.isSimple());
678+
679+
ring = new LineString();
680+
ring.addPoint(new Point(119.65450502825215, 234.97190110269844));
681+
ring.addPoint(new Point(120.94208471603682, 241.47274889005215));
682+
// ring.addPoint(new Point(120.57389187028015, 240.42380619065557));
683+
// ring.addPoint(new Point(120.40553233952696, 239.3249423106921));
684+
ring.addPoint(new Point(120.44278575100797, 238.2138802324909));
685+
ring.addPoint(new Point(120.68437322950616, 237.12876169126298));
686+
ring.addPoint(new Point(121.12200129996195, 236.1068378045508));
687+
ring.addPoint(new Point(121.74064659481407, 235.18319027576013));
688+
ring.addPoint(new Point(122.51907159233552, 234.38952707167576));
689+
ring.addPoint(new Point(119.65450502825215, 234.97190110269844));
690+
polygon = new Polygon(ring);
691+
692+
TestCase.assertTrue(polygon.isSimple());
693+
694+
ring = new LineString();
695+
ring.addPoint(new Point(119.65450502825215, 234.97190110269844));
696+
ring.addPoint(new Point(120.94208471603682, 241.47274889005215));
697+
ring.addPoint(new Point(120.57389187028015, 240.42380619065557));
698+
// ring.addPoint(new Point(120.40553233952696, 239.3249423106921));
699+
ring.addPoint(new Point(120.44278575100797, 238.2138802324909));
700+
ring.addPoint(new Point(120.68437322950616, 237.12876169126298));
701+
ring.addPoint(new Point(121.12200129996195, 236.1068378045508));
702+
ring.addPoint(new Point(121.74064659481407, 235.18319027576013));
703+
ring.addPoint(new Point(122.51907159233552, 234.38952707167576));
704+
polygon = new Polygon(ring);
705+
706+
TestCase.assertFalse(polygon.isSimple());
707+
708+
ring = new LineString();
709+
ring.addPoint(new Point(119.65450502825215, 234.97190110269844));
710+
ring.addPoint(new Point(120.94208471603682, 241.47274889005215));
711+
// ring.addPoint(new Point(120.57389187028015, 240.42380619065557));
712+
ring.addPoint(new Point(120.40553233952696, 239.3249423106921));
713+
ring.addPoint(new Point(120.44278575100797, 238.2138802324909));
714+
ring.addPoint(new Point(120.68437322950616, 237.12876169126298));
715+
ring.addPoint(new Point(121.12200129996195, 236.1068378045508));
716+
ring.addPoint(new Point(121.74064659481407, 235.18319027576013));
717+
ring.addPoint(new Point(122.51907159233552, 234.38952707167576));
718+
polygon = new Polygon(ring);
719+
720+
TestCase.assertFalse(polygon.isSimple());
721+
722+
}
723+
724+
@Test
725+
public void testPolygons3() {
726+
727+
LineString ring = new LineString();
728+
ring.addPoint(new Point(2.48, 1.38));
729+
ring.addPoint(new Point(2.642, 4.22));
730+
ring.addPoint(new Point(4.41, 2.91));
731+
ring.addPoint(new Point(4.69, 4.42));
732+
ring.addPoint(new Point(2.68, 4.90));
733+
Polygon polygon = new Polygon(ring);
734+
735+
TestCase.assertTrue(polygon.isSimple());
736+
737+
ring = new LineString();
738+
ring.addPoint(new Point(2.48, 1.38));
739+
ring.addPoint(new Point(2.641, 4.22));
740+
ring.addPoint(new Point(4.41, 2.91));
741+
ring.addPoint(new Point(4.69, 4.42));
742+
ring.addPoint(new Point(2.68, 4.90));
743+
polygon = new Polygon(ring);
744+
745+
TestCase.assertFalse(polygon.isSimple());
746+
747+
ring = new LineString();
748+
ring.addPoint(new Point(2.48, 1.38));
749+
ring.addPoint(new Point(2.642, 4.22));
750+
ring.addPoint(new Point(3.60, 4.68));
751+
ring.addPoint(new Point(4.69, 4.42));
752+
ring.addPoint(new Point(2.68, 4.90));
753+
polygon = new Polygon(ring);
754+
755+
TestCase.assertTrue(polygon.isSimple());
756+
757+
ring = new LineString();
758+
ring.addPoint(new Point(2.48, 1.38));
759+
ring.addPoint(new Point(2.642, 4.22));
760+
ring.addPoint(new Point(3.60, 4.681));
761+
ring.addPoint(new Point(4.69, 4.42));
762+
ring.addPoint(new Point(2.68, 4.90));
763+
polygon = new Polygon(ring);
764+
765+
TestCase.assertFalse(polygon.isSimple());
766+
767+
ring = new LineString();
768+
ring.addPoint(new Point(2.48, 1.38));
769+
ring.addPoint(new Point(6.34, 2.15));
770+
ring.addPoint(new Point(5.85, 3.34));
771+
ring.addPoint(new Point(5.98, 3.07));
772+
ring.addPoint(new Point(5.09, 4.98));
773+
polygon = new Polygon(ring);
774+
775+
TestCase.assertTrue(polygon.isSimple());
776+
777+
ring = new LineString();
778+
ring.addPoint(new Point(2.48, 1.38));
779+
ring.addPoint(new Point(6.34, 2.15));
780+
ring.addPoint(new Point(5.855, 3.34));
781+
ring.addPoint(new Point(5.98, 3.07));
782+
ring.addPoint(new Point(5.09, 4.98));
783+
polygon = new Polygon(ring);
784+
785+
TestCase.assertFalse(polygon.isSimple());
786+
787+
}
788+
571789
private void addPoint(List<Point> points, double x, double y) {
572790
points.add(new Point(x, y));
573791
}

0 commit comments

Comments
 (0)