diff --git a/geojson/poly/inside.go b/geojson/poly/inside.go index 3ba6ae33..ee6bcaab 100644 --- a/geojson/poly/inside.go +++ b/geojson/poly/inside.go @@ -17,6 +17,11 @@ func (p Point) Inside(exterior Polygon, holes []Polygon) bool { return true } +// Inside detects if a rect intersects another polygon +func (r Rect) Inside(exterior Polygon, holes []Polygon) bool { + return r.Polygon().Inside(exterior, holes) +} + // Inside returns true if shape is inside of exterior and not in a hole. func (shape Polygon) Inside(exterior Polygon, holes []Polygon) bool { var ok bool diff --git a/geojson/poly/intersects.go b/geojson/poly/intersects.go index 96a5f71b..c6017ece 100644 --- a/geojson/poly/intersects.go +++ b/geojson/poly/intersects.go @@ -5,6 +5,11 @@ func (p Point) Intersects(exterior Polygon, holes []Polygon) bool { return p.Inside(exterior, holes) } +// Intersects detects if a rect intersects another polygon +func (r Rect) Intersects(exterior Polygon, holes []Polygon) bool { + return r.Polygon().Inside(exterior, holes) +} + // Intersects detects if a polygon intersects another polygon func (shape Polygon) Intersects(exterior Polygon, holes []Polygon) bool { return shape.doesIntersects(false, exterior, holes) diff --git a/geojson/poly/poly.go b/geojson/poly/poly.go index 4ce00ced..8167a597 100644 --- a/geojson/poly/poly.go +++ b/geojson/poly/poly.go @@ -62,6 +62,17 @@ type Rect struct { Min, Max Point } +// Polygon returns a polygon for the rect +func (r Rect) Polygon() Polygon { + p := Polygon(make([]Point, 5)) + p[0] = Point{X: r.Min.X, Y: r.Max.Y} + p[1] = Point{X: r.Max.X, Y: r.Max.Y} + p[2] = Point{X: r.Max.X, Y: r.Min.Y} + p[3] = Point{X: r.Min.X, Y: r.Min.Y} + p[4] = Point{X: r.Min.X, Y: r.Max.Y} + return p +} + // Rect returns the bounding box rectangle for the polygon func (p Polygon) Rect() Rect { var bbox Rect diff --git a/geojson/polygon.go b/geojson/polygon.go index 8fc3d2fb..463e33c0 100644 --- a/geojson/polygon.go +++ b/geojson/polygon.go @@ -97,7 +97,15 @@ func (g Polygon) WithinBBox(bbox BBox) bool { if len(g.Coordinates) == 0 { return false } - return polyPositions(g.Coordinates[0]).InsideRect(rectBBox(bbox)) + rbbox := rectBBox(bbox) + ext, holes := polyExteriorHoles(g.Coordinates) + if len(holes) > 0 { + if rbbox.Max == rbbox.Min { + return rbbox.Min.Inside(ext, holes) + } + return rbbox.Inside(ext, holes) + } + return ext.InsideRect(rectBBox(bbox)) } // IntersectsBBox detects if the object intersects a bbox. @@ -108,7 +116,15 @@ func (g Polygon) IntersectsBBox(bbox BBox) bool { if len(g.Coordinates) == 0 { return false } - return polyPositions(g.Coordinates[0]).IntersectsRect(rectBBox(bbox)) + rbbox := rectBBox(bbox) + ext, holes := polyExteriorHoles(g.Coordinates) + if len(holes) > 0 { + if rbbox.Max == rbbox.Min { + return rbbox.Min.Intersects(ext, holes) + } + return rbbox.Intersects(ext, holes) + } + return ext.IntersectsRect(rectBBox(bbox)) } // Within detects if the object is fully contained inside another object. diff --git a/geojson/polygon_test.go b/geojson/polygon_test.go index 61999ecd..e4cf50d3 100644 --- a/geojson/polygon_test.go +++ b/geojson/polygon_test.go @@ -246,3 +246,55 @@ func TestPolygonIntersectsBBox(t *testing.T) { t.Fatal("!") } } + +func TestIssue241(t *testing.T) { + g, _ := ObjectJSON(`{ + "type": "Polygon", + "coordinates": [ + [ + [2.2571754455566406, 48.84472294197522], + [2.252626419067383, 48.8473212003792], + [2.2455883026123047, 48.847660093710566], + [2.2386789321899414, 48.846022088028505], + [2.2353315353393555, 48.842152792889486], + [2.235288619995117, 48.83966724854628], + [2.236189842224121, 48.836870863722986], + [2.240910530090332, 48.83461104476972], + [2.2461462020874023, 48.8343568087582], + [2.2527122497558594, 48.83540199299912], + [2.2573471069335938, 48.837746516162916], + [2.259106636047363, 48.84003443899817], + [2.259106636047363, 48.84302835299516], + [2.2571754455566406, 48.84472294197522] + ], + [ + [2.2546112537384033, 48.84285183001222], + [2.254890203475952, 48.842774159702614], + [2.255094051361084, 48.84197626682054], + [2.2551369667053223, 48.84108656596295], + [2.254589796066284, 48.8398649668164], + [2.2528302669525146, 48.83974492367404], + [2.2515535354614253, 48.839942641637556], + [2.2512423992156982, 48.84047223948045], + [2.2509634494781494, 48.841891534086436], + [2.2513389587402344, 48.84261881872204], + [2.2546112537384033, 48.84285183001222] + ] + ] +}`) + p1, _ := ObjectJSON(`{"type":"Point","coordinates":[2.253119945526123,48.841404318083505]}`) + if g.Intersects(p1) { + t.Fatalf("expected %v, got %v", false, g.Intersects(p1)) + } + if g.Within(p1) { + t.Fatalf("expected %v, got %v", false, g.Within(p1)) + } + p2, _ := ObjectJSON(`{"type":"Point","coordinates":[2.2564244270324703,48.83788774899389]}`) + if !g.Intersects(p2) { + t.Fatalf("expected %v, got %v", true, g.Intersects(p2)) + } + if !g.Within(p2) { + t.Fatalf("expected %v, got %v", false, g.Within(p2)) + } + +}