separate bboxes for multipolygon

This commit is contained in:
Josh Baker 2018-03-07 13:18:25 -07:00
parent c8353a18b2
commit e3a09d7469
3 changed files with 39 additions and 44 deletions

View File

@ -363,20 +363,6 @@ func fillLevel4Map(json string) (
return return
} }
func level4CalculatedBBox(coordinates [][][]Position, bbox *BBox) BBox {
if bbox != nil {
return *bbox
}
var bbox2 BBox
var i = 0
for _, ps := range coordinates {
for _, ps := range ps {
i, bbox2 = positionBBox(i, bbox2, ps)
}
}
return bbox2
}
func level4Weight(coordinates [][][]Position, bbox *BBox) int { func level4Weight(coordinates [][][]Position, bbox *BBox) int {
return level4PositionCount(coordinates, bbox) * sizeofPosition return level4PositionCount(coordinates, bbox) * sizeofPosition
} }

View File

@ -7,27 +7,22 @@ type MultiPolygon struct {
Coordinates [][][]Position Coordinates [][][]Position
BBox *BBox BBox *BBox
bboxDefined bool bboxDefined bool
polygons []Polygon
} }
func fillMultiPolygon(coordinates [][][]Position, bbox *BBox, err error) (MultiPolygon, error) { func fillMultiPolygon(coordinates [][][]Position, bbox *BBox, err error) (MultiPolygon, error) {
polygons := make([]Polygon, len(coordinates))
if err == nil { if err == nil {
outer: for i, ps := range coordinates {
for _, ps := range coordinates { polygons[i], err = fillPolygon(ps, nil, nil)
if len(ps) == 0 { if err != nil {
err = errMustBeALinearRing
break break
} }
for _, ps := range ps {
if !isLinearRing(ps) {
err = errMustBeALinearRing
break outer
}
}
} }
} }
bboxDefined := bbox != nil bboxDefined := bbox != nil
if !bboxDefined { if !bboxDefined {
cbbox := level4CalculatedBBox(coordinates, nil) cbbox := calculatedBBox(polygons, nil)
bbox = &cbbox bbox = &cbbox
} }
return MultiPolygon{ return MultiPolygon{
@ -37,9 +32,24 @@ func fillMultiPolygon(coordinates [][][]Position, bbox *BBox, err error) (MultiP
}, err }, err
} }
func calculatedBBox(polygons []Polygon, bbox *BBox) BBox {
if bbox != nil {
return *bbox
}
var cbbox BBox
for i, p := range polygons {
if i == 0 {
cbbox = p.CalculatedBBox()
} else {
cbbox = cbbox.union(p.CalculatedBBox())
}
}
return cbbox
}
// CalculatedBBox is exterior bbox containing the object. // CalculatedBBox is exterior bbox containing the object.
func (g MultiPolygon) CalculatedBBox() BBox { func (g MultiPolygon) CalculatedBBox() BBox {
return level4CalculatedBBox(g.Coordinates, g.BBox) return calculatedBBox(g.polygons, g.BBox)
} }
// CalculatedPoint is a point representation of the object. // CalculatedPoint is a point representation of the object.
@ -99,6 +109,13 @@ func (g MultiPolygon) hasPositions() bool {
return false return false
} }
func (g MultiPolygon) getPolygon(index int) Polygon {
if index < len(g.polygons) {
return g.polygons[index]
}
return Polygon{Coordinates: g.Coordinates[index]}
}
// WithinBBox detects if the object is fully contained inside a bbox. // WithinBBox detects if the object is fully contained inside a bbox.
func (g MultiPolygon) WithinBBox(bbox BBox) bool { func (g MultiPolygon) WithinBBox(bbox BBox) bool {
if g.bboxDefined { if g.bboxDefined {
@ -107,8 +124,8 @@ func (g MultiPolygon) WithinBBox(bbox BBox) bool {
if len(g.Coordinates) == 0 { if len(g.Coordinates) == 0 {
return false return false
} }
for _, p := range g.Coordinates { for i := range g.Coordinates {
if !(Polygon{Coordinates: p}).WithinBBox(bbox) { if !g.getPolygon(i).WithinBBox(bbox) {
return false return false
} }
} }
@ -120,8 +137,8 @@ func (g MultiPolygon) IntersectsBBox(bbox BBox) bool {
if g.bboxDefined { if g.bboxDefined {
return rectBBox(g.CalculatedBBox()).IntersectsRect(rectBBox(bbox)) return rectBBox(g.CalculatedBBox()).IntersectsRect(rectBBox(bbox))
} }
for _, p := range g.Coordinates { for i := range g.Coordinates {
if (Polygon{Coordinates: p}).IntersectsBBox(bbox) { if g.getPolygon(i).IntersectsBBox(bbox) {
return true return true
} }
} }
@ -135,12 +152,8 @@ func (g MultiPolygon) Within(o Object) bool {
if len(g.Coordinates) == 0 { if len(g.Coordinates) == 0 {
return false return false
} }
for _, p := range g.Coordinates { if !v.Within(o) {
if len(p) > 0 { return false
if !polyPositions(p[0]).Inside(polyExteriorHoles(v.Coordinates)) {
return false
}
}
} }
return true return true
}, },
@ -154,12 +167,8 @@ func (g MultiPolygon) Intersects(o Object) bool {
if len(g.Coordinates) == 0 { if len(g.Coordinates) == 0 {
return false return false
} }
for _, p := range g.Coordinates { if v.Intersects(o) {
if len(p) > 0 { return true
if polyPositions(p[0]).Intersects(polyExteriorHoles(v.Coordinates)) {
return true
}
}
} }
return false return false
}, },

View File

@ -205,8 +205,8 @@ func withinObjectShared(g Object, o Object, pin func(v Polygon) bool) bool {
} }
return pin(v) return pin(v)
case MultiPolygon: case MultiPolygon:
for _, coords := range v.Coordinates { for i := range v.Coordinates {
if pin(Polygon{Coordinates: coords}) { if pin(v.getPolygon(i)) {
return true return true
} }
} }