mirror of https://github.com/tidwall/tile38.git
separate bboxes for multipolygon
This commit is contained in:
parent
c8353a18b2
commit
e3a09d7469
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
||||||
},
|
},
|
||||||
|
|
|
@ -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
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue