mirror of https://github.com/tidwall/tile38.git
295 lines
6.3 KiB
Go
295 lines
6.3 KiB
Go
|
package geojson
|
||
|
|
||
|
import (
|
||
|
"github.com/tidwall/tile38/geojson/poly"
|
||
|
)
|
||
|
|
||
|
// withinObjectShared returns true if g is within o
|
||
|
func withinObjectShared(g, o Object) bool {
|
||
|
bbp := o.bboxPtr()
|
||
|
if bbp != nil {
|
||
|
if !g.WithinBBox(*bbp) {
|
||
|
return false
|
||
|
}
|
||
|
if o.IsBBoxDefined() {
|
||
|
return true
|
||
|
}
|
||
|
}
|
||
|
switch o := o.(type) {
|
||
|
default:
|
||
|
return false
|
||
|
case SimplePoint:
|
||
|
return g.WithinBBox(o.CalculatedBBox())
|
||
|
case Point:
|
||
|
return g.WithinBBox(o.CalculatedBBox())
|
||
|
case MultiPoint:
|
||
|
for i := range o.Coordinates {
|
||
|
if g.Within(o.getPoint(i)) {
|
||
|
return true
|
||
|
}
|
||
|
}
|
||
|
return false
|
||
|
case LineString:
|
||
|
if len(o.Coordinates) == 0 {
|
||
|
return false
|
||
|
}
|
||
|
switch g := g.(type) {
|
||
|
default:
|
||
|
return false
|
||
|
case SimplePoint:
|
||
|
return poly.Point(Position{X: g.X, Y: g.Y, Z: 0}).IntersectsLineString(polyPositions(o.Coordinates))
|
||
|
case Point:
|
||
|
return poly.Point(g.Coordinates).IntersectsLineString(polyPositions(o.Coordinates))
|
||
|
case MultiPoint:
|
||
|
if len(o.Coordinates) == 0 {
|
||
|
return false
|
||
|
}
|
||
|
for _, p := range o.Coordinates {
|
||
|
if !poly.Point(p).IntersectsLineString(polyPositions(o.Coordinates)) {
|
||
|
return false
|
||
|
}
|
||
|
}
|
||
|
return true
|
||
|
}
|
||
|
case MultiLineString:
|
||
|
for i := range o.Coordinates {
|
||
|
if g.Within(o.getLineString(i)) {
|
||
|
return true
|
||
|
}
|
||
|
}
|
||
|
return false
|
||
|
case MultiPolygon:
|
||
|
for i := range o.Coordinates {
|
||
|
if g.Within(o.getPolygon(i)) {
|
||
|
return true
|
||
|
}
|
||
|
}
|
||
|
return false
|
||
|
case Feature:
|
||
|
return g.Within(o.Geometry)
|
||
|
case FeatureCollection:
|
||
|
for _, o := range o.Features {
|
||
|
if g.Within(o) {
|
||
|
return true
|
||
|
}
|
||
|
}
|
||
|
return false
|
||
|
case GeometryCollection:
|
||
|
for _, o := range o.Geometries {
|
||
|
if g.Within(o) {
|
||
|
return true
|
||
|
}
|
||
|
}
|
||
|
return false
|
||
|
case Polygon:
|
||
|
if len(o.Coordinates) == 0 {
|
||
|
return false
|
||
|
}
|
||
|
exterior, holes := polyExteriorHoles(o.Coordinates)
|
||
|
switch g := g.(type) {
|
||
|
default:
|
||
|
return false
|
||
|
case SimplePoint:
|
||
|
return poly.Point(Position{X: g.X, Y: g.Y, Z: 0}).Inside(exterior, holes)
|
||
|
case Point:
|
||
|
return poly.Point(g.Coordinates).Inside(exterior, holes)
|
||
|
case MultiPoint:
|
||
|
if len(g.Coordinates) == 0 {
|
||
|
return false
|
||
|
}
|
||
|
for i := range g.Coordinates {
|
||
|
if !g.getPoint(i).Within(o) {
|
||
|
return false
|
||
|
}
|
||
|
}
|
||
|
return true
|
||
|
case LineString:
|
||
|
return polyPositions(g.Coordinates).Inside(exterior, holes)
|
||
|
case MultiLineString:
|
||
|
if len(g.Coordinates) == 0 {
|
||
|
return false
|
||
|
}
|
||
|
for i := range g.Coordinates {
|
||
|
if !g.getLineString(i).Within(o) {
|
||
|
return false
|
||
|
}
|
||
|
}
|
||
|
return true
|
||
|
case Polygon:
|
||
|
if len(g.Coordinates) == 0 {
|
||
|
return false
|
||
|
}
|
||
|
return polyPositions(g.Coordinates[0]).Inside(exterior, holes)
|
||
|
case MultiPolygon:
|
||
|
if len(g.Coordinates) == 0 {
|
||
|
return false
|
||
|
}
|
||
|
for i := range g.Coordinates {
|
||
|
if !g.getPolygon(i).Within(o) {
|
||
|
return false
|
||
|
}
|
||
|
}
|
||
|
return true
|
||
|
case GeometryCollection:
|
||
|
if len(g.Geometries) == 0 {
|
||
|
return false
|
||
|
}
|
||
|
for _, g := range g.Geometries {
|
||
|
if !g.Within(o) {
|
||
|
return false
|
||
|
}
|
||
|
}
|
||
|
return true
|
||
|
case Feature:
|
||
|
return g.Geometry.Within(o)
|
||
|
case FeatureCollection:
|
||
|
if len(g.Features) == 0 {
|
||
|
return false
|
||
|
}
|
||
|
for _, g := range g.Features {
|
||
|
if !g.Within(o) {
|
||
|
return false
|
||
|
}
|
||
|
}
|
||
|
return true
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// intersectsObjectShared detects if g intersects with o
|
||
|
func intersectsObjectShared(g, o Object) bool {
|
||
|
bbp := o.bboxPtr()
|
||
|
if bbp != nil {
|
||
|
if !g.IntersectsBBox(*bbp) {
|
||
|
return false
|
||
|
}
|
||
|
if o.IsBBoxDefined() {
|
||
|
return true
|
||
|
}
|
||
|
}
|
||
|
switch o := o.(type) {
|
||
|
default:
|
||
|
return false
|
||
|
case SimplePoint:
|
||
|
return g.IntersectsBBox(o.CalculatedBBox())
|
||
|
case Point:
|
||
|
return g.IntersectsBBox(o.CalculatedBBox())
|
||
|
case MultiPoint:
|
||
|
for i := range o.Coordinates {
|
||
|
if o.getPoint(i).Intersects(g) {
|
||
|
return true
|
||
|
}
|
||
|
}
|
||
|
return false
|
||
|
case LineString:
|
||
|
if g, ok := g.(LineString); ok {
|
||
|
a := polyPositions(g.Coordinates)
|
||
|
b := polyPositions(o.Coordinates)
|
||
|
return a.LineStringIntersectsLineString(b)
|
||
|
}
|
||
|
return o.Intersects(g)
|
||
|
case MultiLineString:
|
||
|
for i := range o.Coordinates {
|
||
|
if g.Intersects(o.getLineString(i)) {
|
||
|
return true
|
||
|
}
|
||
|
}
|
||
|
return false
|
||
|
case MultiPolygon:
|
||
|
for i := range o.Coordinates {
|
||
|
if g.Intersects(o.getPolygon(i)) {
|
||
|
return true
|
||
|
}
|
||
|
}
|
||
|
return false
|
||
|
case Feature:
|
||
|
return g.Intersects(o.Geometry)
|
||
|
case FeatureCollection:
|
||
|
for _, f := range o.Features {
|
||
|
if g.Intersects(f) {
|
||
|
return true
|
||
|
}
|
||
|
}
|
||
|
return false
|
||
|
case GeometryCollection:
|
||
|
for _, f := range o.Geometries {
|
||
|
if g.Intersects(f) {
|
||
|
return true
|
||
|
}
|
||
|
}
|
||
|
return false
|
||
|
case Polygon:
|
||
|
if len(o.Coordinates) == 0 {
|
||
|
return false
|
||
|
}
|
||
|
exterior, holes := polyExteriorHoles(o.Coordinates)
|
||
|
switch g := g.(type) {
|
||
|
default:
|
||
|
return false
|
||
|
case SimplePoint:
|
||
|
return poly.Point(Position{X: g.X, Y: g.Y, Z: 0}).Intersects(exterior, holes)
|
||
|
case Point:
|
||
|
return poly.Point(g.Coordinates).Intersects(exterior, holes)
|
||
|
case MultiPoint:
|
||
|
for i := range g.Coordinates {
|
||
|
if g.getPoint(i).Intersects(o) {
|
||
|
return true
|
||
|
}
|
||
|
}
|
||
|
return false
|
||
|
case LineString:
|
||
|
return polyPositions(g.Coordinates).LineStringIntersects(exterior, holes)
|
||
|
case MultiLineString:
|
||
|
for i := range g.Coordinates {
|
||
|
if g.getLineString(i).Intersects(o) {
|
||
|
return true
|
||
|
}
|
||
|
}
|
||
|
return false
|
||
|
case Polygon:
|
||
|
if len(g.Coordinates) == 0 {
|
||
|
return false
|
||
|
}
|
||
|
return polyPositions(g.Coordinates[0]).Intersects(exterior, holes)
|
||
|
case MultiPolygon:
|
||
|
for i := range g.Coordinates {
|
||
|
if g.getPolygon(i).Intersects(o) {
|
||
|
return true
|
||
|
}
|
||
|
}
|
||
|
return false
|
||
|
case GeometryCollection:
|
||
|
for _, g := range g.Geometries {
|
||
|
if g.Intersects(o) {
|
||
|
return true
|
||
|
}
|
||
|
}
|
||
|
return false
|
||
|
case Feature:
|
||
|
return g.Geometry.Intersects(o)
|
||
|
case FeatureCollection:
|
||
|
for _, g := range g.Features {
|
||
|
if g.Intersects(o) {
|
||
|
return true
|
||
|
}
|
||
|
}
|
||
|
return false
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// The object's calculated bounding box must intersect the radius of the circle to pass.
|
||
|
func nearbyObjectShared(g Object, x, y float64, meters float64) bool {
|
||
|
if !g.hasPositions() {
|
||
|
return false
|
||
|
}
|
||
|
center := Position{X: x, Y: y, Z: 0}
|
||
|
bbox := g.CalculatedBBox()
|
||
|
if bbox.Min.X == bbox.Max.X && bbox.Min.Y == bbox.Max.Y {
|
||
|
// just a point, return is point is inside of the circle
|
||
|
return center.DistanceTo(bbox.Min) <= meters
|
||
|
}
|
||
|
circlePoly := CirclePolygon(x, y, meters, 12)
|
||
|
return g.Intersects(circlePoly)
|
||
|
}
|