point match on interior hole, fixes #241

This commit is contained in:
Josh Baker 2017-12-18 08:37:03 -07:00
parent 02fa605dc4
commit 5b5e589be3
5 changed files with 91 additions and 2 deletions

View File

@ -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

View File

@ -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)

View File

@ -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

View File

@ -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.

View File

@ -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))
}
}