Closed
Description
Hi,
I've just stumbled upon a case where RegionCoverer.InteriorCovering
results in an infinite loop.
To be fair, the s2.Polygon
in question isn't a valid polygon according to the restrictions:
- Loops may not cross, i.e. the boundary of a loop may not intersect
both the interior and exterior of any other loop. - Loops may not share edges, i.e. if a loop contains an edge AB, then
no other loop may contain AB or BA.
since it consists of the same loop two times.
I still think this might be worth looking into - since an infinite loop is pretty dangerous to trigger in any case.
And it does work (even correctly) for the RegionCoverer.Covering
variant.
Below is a fully reproducible example:
package main
import (
"fmt"
"github.com/golang/geo/s2"
)
func main() {
// a closed-polygon, an area in mexico
points := []s2.Point{
s2.PointFromLatLng(s2.LatLngFromDegrees(20.15, -97.70)),
s2.PointFromLatLng(s2.LatLngFromDegrees(19.72, -97.70)),
s2.PointFromLatLng(s2.LatLngFromDegrees(19.72, -97.19)),
s2.PointFromLatLng(s2.LatLngFromDegrees(20.15, -97.19)),
}
poly := s2.PolygonFromOrientedLoops([]*s2.Loop{s2.LoopFromPoints(points)})
coverer := s2.RegionCoverer{MinLevel: 0, MaxLevel: 30, LevelMod: 1, MaxCells: 1}
interiorCovering := coverer.InteriorCovering(poly) // works as intended
fmt.Println(interiorCovering) // [4/023231102]
// now let's try the same area again, but with two times the same loop
// this happened for us when converting a GeoJSON multipolygon to a S2 polygon and we didn't validate the
// non-overlapping constraint before
multiPoly := s2.PolygonFromOrientedLoops([]*s2.Loop{s2.LoopFromPoints(points), s2.LoopFromPoints(points)})
// the call below results in an infinite loop
interiorCovering = coverer.InteriorCovering(multiPoly)
fmt.Println(interiorCovering)
}
Metadata
Metadata
Assignees
Labels
No labels