diff --git a/geojson/geojson_s2_util.go b/geojson/geojson_s2_util.go index 91ad975e..8afbbffb 100644 --- a/geojson/geojson_s2_util.go +++ b/geojson/geojson_s2_util.go @@ -136,44 +136,53 @@ func geometryCollectionIntersectsShape(gc *GeometryCollection, func polygonsContainsLineStrings(s2pgns []*s2.Polygon, pls []*s2.Polyline) bool { - linesWithIn := make(map[int]struct{}) checker := s2.NewCrossingEdgeQuery(s2.NewShapeIndex()) -nextLine: - for lineIndex, pl := range pls { + + // Every line segment in every linestring must be + // fully contained in atleast one of the polygons + for _, pl := range pls { for i := 0; i < len(*pl)-1; i++ { start := (*pl)[i] end := (*pl)[i+1] + contains := false for _, s2pgn := range s2pgns { containsStart := s2pgn.ContainsPoint(start) containsEnd := s2pgn.ContainsPoint(end) + // check if both end points are contained and if so, + // check if the line segment between them crosses the boundary of the polygon if containsStart && containsEnd { crossings := checker.Crossings(start, end, s2pgn, s2.CrossingTypeInterior) if len(crossings) > 0 { - continue nextLine + continue } - linesWithIn[lineIndex] = struct{}{} - continue nextLine + contains = true + break } else { + // else we check if the line segment is an edge of the polygon for _, loop := range s2pgn.Loops() { for i := 0; i < loop.NumVertices(); i++ { if !containsStart && start.ApproxEqual(loop.Vertex(i)) { containsStart = true - } else if !containsEnd && end.ApproxEqual(loop.Vertex(i)) { + } + if !containsEnd && end.ApproxEqual(loop.Vertex(i)) { containsEnd = true } if containsStart && containsEnd { - linesWithIn[lineIndex] = struct{}{} - continue nextLine + contains = true + break } } } } } + if !contains { + return false + } } } - return len(pls) == len(linesWithIn) + return true } func rectangleIntersectsWithPolygons(s2rect *s2.Rect, diff --git a/geojson/geojson_shapes_test.go b/geojson/geojson_shapes_test.go index 2c843e6d..337e638c 100644 --- a/geojson/geojson_shapes_test.go +++ b/geojson/geojson_shapes_test.go @@ -1300,7 +1300,7 @@ func TestPolygonContains(t *testing.T) { }, { // 6 - Linestring contained by polygon query: &Polygon{Typ: PolygonType, Vertices: [][][]float64{{{-1, 0}, {1, 0}, {2, 3}, {0, 3}, {-1, 0}}}}, - other: NewGeoJsonLinestring([][]float64{{2, 2}, {1, 1}, {0, 1}}), + other: NewGeoJsonLinestring([][]float64{{1, 2}, {1, 1}, {0, 1}}), output: true, }, { // 7 - Linestring with no intersection @@ -1320,7 +1320,7 @@ func TestPolygonContains(t *testing.T) { }, { // 10 - Multilinestring with both linestrings contained by polygon query: &Polygon{Typ: PolygonType, Vertices: [][][]float64{{{-1, 0}, {1, 0}, {2, 3}, {0, 3}, {-1, 0}}}}, - other: NewGeoJsonMultilinestring([][][]float64{{{2, 2}, {1, 1}, {0, 1}}, {{0.5, 0.5}, {0, 1}, {0.5, 1.5}}}), + other: NewGeoJsonMultilinestring([][][]float64{{{1, 2}, {1, 1}, {0, 1}}, {{0.5, 0.5}, {0, 1}, {0.5, 1.5}}}), output: true, }, { // 11 - Multilinestring with no intersection @@ -1465,7 +1465,7 @@ func TestMultiPolygonContains(t *testing.T) { }, { // 6 - Linestring contained by polygon query: &MultiPolygon{Typ: MultiPolygonType, Vertices: [][][][]float64{{{{100, 100}, {100, 101}, {101, 101}, {101, 100}, {100, 100}}}, {{{-1, 0}, {1, 0}, {2, 3}, {0, 3}, {-1, 0}}}}}, - other: NewGeoJsonLinestring([][]float64{{2, 2}, {1, 1}, {0, 1}}), + other: NewGeoJsonLinestring([][]float64{{1, 2}, {1, 1}, {0, 1}}), output: true, }, { // 7 - Linestring with no intersection @@ -1485,7 +1485,7 @@ func TestMultiPolygonContains(t *testing.T) { }, { // 10 - Multilinestring with both linestrings contained by polygon query: &MultiPolygon{Typ: MultiPolygonType, Vertices: [][][][]float64{{{{100, 100}, {100, 101}, {101, 101}, {101, 100}, {100, 100}}}, {{{-1, 0}, {1, 0}, {2, 3}, {0, 3}, {-1, 0}}}}}, - other: NewGeoJsonMultilinestring([][][]float64{{{2, 2}, {1, 1}, {0, 1}}, {{0.5, 0.5}, {0, 1}, {0.5, 1.5}}}), + other: NewGeoJsonMultilinestring([][][]float64{{{1, 2}, {1, 1}, {0, 1}}, {{0.5, 0.5}, {0, 1}, {0.5, 1.5}}}), output: true, }, { // 11 - Multilinestring with no intersection