xframe/vendor/github.com/paulmach/orb/bound.go

173 lines
3.6 KiB
Go

package orb
import (
"math"
)
var emptyBound = Bound{Min: Point{1, 1}, Max: Point{-1, -1}}
// A Bound represents a closed box or rectangle.
// To create a bound with two points you can do something like:
// orb.MultiPoint{p1, p2}.Bound()
type Bound struct {
Min, Max Point
}
// GeoJSONType returns the GeoJSON type for the object.
func (b Bound) GeoJSONType() string {
return "Polygon"
}
// Dimensions returns 2 because a Bound is a 2d object.
func (b Bound) Dimensions() int {
return 2
}
// ToPolygon converts the bound into a Polygon object.
func (b Bound) ToPolygon() Polygon {
return Polygon{b.ToRing()}
}
// ToRing converts the bound into a loop defined
// by the boundary of the box.
func (b Bound) ToRing() Ring {
return Ring{
b.Min,
Point{b.Max[0], b.Min[1]},
b.Max,
Point{b.Min[0], b.Max[1]},
b.Min,
}
}
// Extend grows the bound to include the new point.
func (b Bound) Extend(point Point) Bound {
// already included, no big deal
if b.Contains(point) {
return b
}
return Bound{
Min: Point{
math.Min(b.Min[0], point[0]),
math.Min(b.Min[1], point[1]),
},
Max: Point{
math.Max(b.Max[0], point[0]),
math.Max(b.Max[1], point[1]),
},
}
}
// Union extends this bound to contain the union of this and the given bound.
func (b Bound) Union(other Bound) Bound {
if other.IsEmpty() {
return b
}
b = b.Extend(other.Min)
b = b.Extend(other.Max)
b = b.Extend(other.LeftTop())
b = b.Extend(other.RightBottom())
return b
}
// Contains determines if the point is within the bound.
// Points on the boundary are considered within.
func (b Bound) Contains(point Point) bool {
if point[1] < b.Min[1] || b.Max[1] < point[1] {
return false
}
if point[0] < b.Min[0] || b.Max[0] < point[0] {
return false
}
return true
}
// Intersects determines if two bounds intersect.
// Returns true if they are touching.
func (b Bound) Intersects(bound Bound) bool {
if (b.Max[0] < bound.Min[0]) ||
(b.Min[0] > bound.Max[0]) ||
(b.Max[1] < bound.Min[1]) ||
(b.Min[1] > bound.Max[1]) {
return false
}
return true
}
// Pad extends the bound in all directions by the given value.
func (b Bound) Pad(d float64) Bound {
b.Min[0] -= d
b.Min[1] -= d
b.Max[0] += d
b.Max[1] += d
return b
}
// Center returns the center of the bounds by "averaging" the x and y coords.
func (b Bound) Center() Point {
return Point{
(b.Min[0] + b.Max[0]) / 2.0,
(b.Min[1] + b.Max[1]) / 2.0,
}
}
// Top returns the top of the bound.
func (b Bound) Top() float64 {
return b.Max[1]
}
// Bottom returns the bottom of the bound.
func (b Bound) Bottom() float64 {
return b.Min[1]
}
// Right returns the right of the bound.
func (b Bound) Right() float64 {
return b.Max[0]
}
// Left returns the left of the bound.
func (b Bound) Left() float64 {
return b.Min[0]
}
// LeftTop returns the upper left point of the bound.
func (b Bound) LeftTop() Point {
return Point{b.Left(), b.Top()}
}
// RightBottom return the lower right point of the bound.
func (b Bound) RightBottom() Point {
return Point{b.Right(), b.Bottom()}
}
// IsEmpty returns true if it contains zero area or if
// it's in some malformed negative state where the left point is larger than the right.
// This can be caused by padding too much negative.
func (b Bound) IsEmpty() bool {
return b.Min[0] > b.Max[0] || b.Min[1] > b.Max[1]
}
// IsZero return true if the bound just includes just null island.
func (b Bound) IsZero() bool {
return b.Max == Point{} && b.Min == Point{}
}
// Bound returns the the same bound.
func (b Bound) Bound() Bound {
return b
}
// Equal returns if two bounds are equal.
func (b Bound) Equal(c Bound) bool {
return b.Min == c.Min && b.Max == c.Max
}