2017-11-01 05:51:41 +00:00
|
|
|
package geom
|
|
|
|
|
|
|
|
import (
|
2019-12-21 10:42:01 +00:00
|
|
|
"fmt"
|
2019-12-21 11:48:57 +00:00
|
|
|
|
|
|
|
"opslag.de/schobers/geom/ints"
|
2017-11-01 05:51:41 +00:00
|
|
|
)
|
|
|
|
|
2019-12-21 10:42:01 +00:00
|
|
|
// ZeroPt represents the coordinate (0, 0)
|
|
|
|
var ZeroPt = Point{0, 0}
|
|
|
|
|
|
|
|
// OnePt represents the coordinate (1, 1)
|
|
|
|
var OnePt = Point{1, 1}
|
|
|
|
|
|
|
|
// North represents the coordinate next to the ZeroPt (Y == -1)
|
|
|
|
var North = Point{0, -1}
|
|
|
|
|
|
|
|
// East represents the coordinate next to the ZeroPt (X == 1)
|
|
|
|
var East = Point{1, 0}
|
|
|
|
|
|
|
|
// South represents the coordinate next to the ZeroPt (Y == 1)
|
|
|
|
var South = Point{0, 1}
|
|
|
|
|
|
|
|
// West represents the coordinate next to the ZeroPt (X == -1)
|
|
|
|
var West = Point{-1, 0}
|
|
|
|
|
|
|
|
// Point represents a 2-dimensional point.
|
|
|
|
type Point struct {
|
|
|
|
X, Y int
|
|
|
|
}
|
2017-11-01 05:51:41 +00:00
|
|
|
|
|
|
|
// Pt is a shorthand function to create a point.
|
|
|
|
func Pt(x, y int) Point {
|
|
|
|
return Point{x, y}
|
|
|
|
}
|
2018-11-14 09:27:03 +00:00
|
|
|
|
2019-12-21 10:42:01 +00:00
|
|
|
// NewPt is a short function to create a point and return a pointer to it.
|
|
|
|
func NewPt(x, y int) *Point {
|
|
|
|
return &Point{x, y}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Abs returns a point the absolute values of X and Y.
|
|
|
|
func (p Point) Abs() Point {
|
2019-12-21 11:48:57 +00:00
|
|
|
return Pt(ints.Abs(p.X), ints.Abs(p.Y))
|
2019-12-21 10:42:01 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// Add returns the sum of p and q.
|
|
|
|
func (p Point) Add(q Point) Point {
|
|
|
|
return p.Add2D(q.X, q.Y)
|
|
|
|
}
|
|
|
|
|
|
|
|
// Add2D adds x and y to X and Y of point p and returns the sum.
|
|
|
|
func (p Point) Add2D(x, y int) Point {
|
|
|
|
return Pt(p.X+x, p.Y+y)
|
|
|
|
}
|
|
|
|
|
2019-12-23 14:09:33 +00:00
|
|
|
// Div divides the X and Y values of point p with t and returns the result.
|
|
|
|
func (p Point) Div(t int) Point {
|
|
|
|
return Pt(p.X/t, p.Y/t)
|
|
|
|
}
|
|
|
|
|
|
|
|
// DistInt returns the integer distance between the points p and q.
|
|
|
|
func (p Point) DistInt(q Point) int {
|
|
|
|
return ints.SubAbs(p.X, q.X) + ints.SubAbs(p.Y, q.Y)
|
|
|
|
}
|
|
|
|
|
2020-05-16 17:52:05 +00:00
|
|
|
// In tests if the point p is inside the rectangle r.
|
|
|
|
func (p Point) In(r Rectangle) bool {
|
|
|
|
if p.X < r.Min.X || p.X >= r.Max.X || p.Y < r.Min.Y || p.Y >= r.Max.Y {
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
return true
|
|
|
|
}
|
|
|
|
|
2019-12-21 10:42:01 +00:00
|
|
|
// Less returns true if q is above (Y is smaller) or left (X is smaller) than p. Otherwise returns false.
|
|
|
|
func (p Point) Less(q Point) bool {
|
|
|
|
if p.Y == q.Y {
|
|
|
|
return p.X < q.X
|
|
|
|
}
|
|
|
|
return p.Y < q.Y
|
|
|
|
}
|
|
|
|
|
|
|
|
// Mul multiplier the X and Y values of point p with t and returns the result.
|
|
|
|
func (p Point) Mul(t int) Point {
|
|
|
|
return Pt(p.X*t, p.Y*t)
|
|
|
|
}
|
|
|
|
|
|
|
|
// Norm returns the point with both X and Y normalized.
|
|
|
|
func (p Point) Norm() Point {
|
2019-12-21 11:48:57 +00:00
|
|
|
return Pt(ints.Norm(p.X), ints.Norm(p.Y))
|
2019-12-21 10:42:01 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// String returns a string representation of point p "X, Y".
|
2018-11-14 09:27:03 +00:00
|
|
|
func (p Point) String() string {
|
2019-12-21 10:42:01 +00:00
|
|
|
return fmt.Sprintf("%d, %d", p.X, p.Y)
|
|
|
|
}
|
|
|
|
|
|
|
|
// StringBrackets formats the point p as a string "(X, Y)".
|
|
|
|
func (p Point) StringBrackets() string {
|
|
|
|
return fmt.Sprintf("(%d, %d)", p.X, p.Y)
|
|
|
|
}
|
|
|
|
|
|
|
|
// StringCompact returns a compact string representation of point p "X,Y".
|
|
|
|
func (p Point) StringCompact() string {
|
|
|
|
return fmt.Sprintf("%d,%d", p.X, p.Y)
|
|
|
|
}
|
|
|
|
|
|
|
|
// Sub returns the difference of p and q.
|
|
|
|
func (p Point) Sub(p2 Point) Point {
|
|
|
|
return Pt(p.X-p2.X, p.Y-p2.Y)
|
|
|
|
}
|
|
|
|
|
2019-12-23 12:53:10 +00:00
|
|
|
// ToF returns the floating point representation of p.
|
|
|
|
func (p Point) ToF() PointF { return PtF(float64(p.X), float64(p.Y)) }
|
|
|
|
|
|
|
|
// ToF32 returns the floating point representation of p.
|
|
|
|
func (p Point) ToF32() PointF32 { return PtF32(float32(p.X), float32(p.Y)) }
|
|
|
|
|
2019-12-28 17:26:08 +00:00
|
|
|
// MaxPt returns the point that is at the largest X & Y position of a and b.
|
|
|
|
func MaxPt(a, b Point) Point {
|
|
|
|
return Pt(ints.Max(a.X, b.X), ints.Max(a.Y, b.Y))
|
|
|
|
}
|
|
|
|
|
2019-12-21 10:42:01 +00:00
|
|
|
// MinMaxPoints returns the extremes of all the given points.
|
|
|
|
func MinMaxPoints(p ...Point) (min Point, max Point) {
|
|
|
|
if 0 == len(p) {
|
|
|
|
return Point{}, Point{}
|
|
|
|
}
|
|
|
|
min, max = p[0], p[0]
|
|
|
|
for i := 1; i < len(p); i++ {
|
|
|
|
var pt = p[i]
|
|
|
|
if pt.X < min.X {
|
|
|
|
min.X = pt.X
|
|
|
|
} else if pt.X > max.X {
|
|
|
|
max.X = pt.X
|
|
|
|
}
|
|
|
|
if pt.Y < min.Y {
|
|
|
|
min.Y = pt.Y
|
|
|
|
} else if pt.Y > max.Y {
|
|
|
|
max.Y = pt.Y
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return min, max
|
2018-11-14 09:27:03 +00:00
|
|
|
}
|
2019-12-28 17:26:08 +00:00
|
|
|
|
|
|
|
// MinPt returns the point that is at the smallest X & Y position of a and b.
|
|
|
|
func MinPt(a, b Point) Point {
|
|
|
|
return Pt(ints.Min(a.X, b.X), ints.Min(a.Y, b.Y))
|
|
|
|
}
|