tile38/pkg/geojson/poly/poly.go

120 lines
2.4 KiB
Go
Raw Normal View History

2016-12-04 18:57:54 +03:00
// Package poly provides polygon detection methods.
2016-03-05 02:08:16 +03:00
package poly
import "fmt"
2016-12-04 18:57:54 +03:00
// Point is simple 2D point
2016-03-05 02:08:16 +03:00
type Point struct {
X, Y, Z float64
}
// InsideRect detects point is inside of another rect
func (p Point) InsideRect(rect Rect) bool {
if p.X < rect.Min.X || p.X > rect.Max.X {
return false
}
if p.Y < rect.Min.Y || p.Y > rect.Max.Y {
return false
}
return true
}
// Polygon is series of points that make up a polygon
type Polygon []Point
// InsideRect detects polygon is inside of another rect
func (p Polygon) InsideRect(rect Rect) bool {
if len(p) == 0 {
return false
}
for _, p := range p {
if !p.InsideRect(rect) {
return false
}
}
return true
}
// IntersectsRect detects polygon is inside of another rect
func (p Polygon) IntersectsRect(rect Rect) bool {
if len(p) == 0 {
return false
}
rectPoly := Polygon{rect.Min, {rect.Min.X, rect.Max.Y, 0}, rect.Max, {rect.Max.X, rect.Min.Y, 0}, rect.Min}
return p.Intersects(rectPoly, nil)
}
// String returns a string representation of the polygon.
func (p Polygon) String() string {
s := "{"
for i, p := range p {
if i > 0 {
s += ", "
}
s += fmt.Sprintf("{%v, %v}", p.X, p.Y)
}
s += "}"
return s
}
// Rect is rectangle
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
}
2016-03-05 02:08:16 +03:00
// Rect returns the bounding box rectangle for the polygon
func (p Polygon) Rect() Rect {
var bbox Rect
for i, p := range p {
if i == 0 {
bbox.Min = p
bbox.Max = p
} else {
if p.X < bbox.Min.X {
bbox.Min.X = p.X
} else if p.X > bbox.Max.X {
bbox.Max.X = p.X
}
if p.Y < bbox.Min.Y {
bbox.Min.Y = p.Y
} else if p.Y > bbox.Max.Y {
bbox.Max.Y = p.Y
}
}
}
return bbox
}
// IntersectsRect detects if two bboxes intersect.
func (r Rect) IntersectsRect(rect Rect) bool {
if r.Min.Y > rect.Max.Y || r.Max.Y < rect.Min.Y {
return false
}
if r.Min.X > rect.Max.X || r.Max.X < rect.Min.X {
return false
}
return true
}
// InsideRect detects rect is inside of another rect
func (r Rect) InsideRect(rect Rect) bool {
if r.Min.X < rect.Min.X || r.Max.X > rect.Max.X {
return false
}
if r.Min.Y < rect.Min.Y || r.Max.Y > rect.Max.Y {
return false
}
return true
}