Added DistanceTo{Line,Lines,Polygon} methods for PointF and PointF32.
Added Sq{,rt}{,32} methods.
This commit is contained in:
parent
afb30dc1e6
commit
a024db06c0
40
math.go
40
math.go
@ -22,16 +22,6 @@ func IsNaN32(f float32) bool {
|
|||||||
return f != f
|
return f != f
|
||||||
}
|
}
|
||||||
|
|
||||||
// NaN returns not a floating point number.
|
|
||||||
func NaN() float64 {
|
|
||||||
return math.NaN()
|
|
||||||
}
|
|
||||||
|
|
||||||
// NaN32 returns not a floating point number.
|
|
||||||
func NaN32() float32 {
|
|
||||||
return float32(NaN())
|
|
||||||
}
|
|
||||||
|
|
||||||
// Max the maximum of the two values.
|
// Max the maximum of the two values.
|
||||||
func Max(a, b float64) float64 {
|
func Max(a, b float64) float64 {
|
||||||
return math.Max(a, b)
|
return math.Max(a, b)
|
||||||
@ -51,3 +41,33 @@ func Min(a, b float64) float64 {
|
|||||||
func Min32(a, b float32) float32 {
|
func Min32(a, b float32) float32 {
|
||||||
return float32(math.Min(float64(a), float64(b)))
|
return float32(math.Min(float64(a), float64(b)))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// NaN returns not a floating point number.
|
||||||
|
func NaN() float64 {
|
||||||
|
return math.NaN()
|
||||||
|
}
|
||||||
|
|
||||||
|
// NaN32 returns not a floating point number.
|
||||||
|
func NaN32() float32 {
|
||||||
|
return float32(NaN())
|
||||||
|
}
|
||||||
|
|
||||||
|
// Sq the square root of the value
|
||||||
|
func Sq(f float64) float64 {
|
||||||
|
return f * f
|
||||||
|
}
|
||||||
|
|
||||||
|
// Sq32 the square root of the value
|
||||||
|
func Sq32(f float32) float32 {
|
||||||
|
return f * f
|
||||||
|
}
|
||||||
|
|
||||||
|
// Sqrt the square root of the value
|
||||||
|
func Sqrt(f float64) float64 {
|
||||||
|
return math.Sqrt(f)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Sqrt32 the square root of the value
|
||||||
|
func Sqrt32(f float32) float32 {
|
||||||
|
return float32(Sqrt(float64(f)))
|
||||||
|
}
|
||||||
|
45
pointf.go
45
pointf.go
@ -46,6 +46,51 @@ func (p PointF) Distance2(q PointF) float64 {
|
|||||||
return dx*dx + dy*dy
|
return dx*dx + dy*dy
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// DistanceToLine calculates the distance to the line segment a, b.
|
||||||
|
func (p PointF) DistanceToLine(a, b PointF) float64 {
|
||||||
|
dx1, dy1 := (a.X - p.X), (a.Y - p.Y)
|
||||||
|
dx2, dy2 := (b.X - a.X), (b.Y - a.Y)
|
||||||
|
t := -((dx1*dx2 + dy1*dy2) / (dx2*dx2 + dy2*dy2))
|
||||||
|
if 0 <= t && t <= 1 {
|
||||||
|
return Abs(dx2*dy1-dy2*dx1) / Sqrt(dx2*dx2+dy2*dy2)
|
||||||
|
}
|
||||||
|
d1, d2 := Sqrt(Sq(b.X-p.X)+Sq(b.Y-p.Y)), Sqrt(dx1*dx1+dy1*dy1)
|
||||||
|
if d1 < d2 {
|
||||||
|
return d1
|
||||||
|
}
|
||||||
|
return d2
|
||||||
|
}
|
||||||
|
|
||||||
|
// DistanceToLines calculates the smallest distance to the line segments of q.
|
||||||
|
func (p PointF) DistanceToLines(q PointsF) float64 {
|
||||||
|
n := len(q)
|
||||||
|
if n == 0 {
|
||||||
|
return NaN()
|
||||||
|
}
|
||||||
|
if n == 1 {
|
||||||
|
return p.Distance(q[0])
|
||||||
|
}
|
||||||
|
min := p.DistanceToLine(q[0], q[1])
|
||||||
|
for i := range q {
|
||||||
|
if i < 2 {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
d := p.DistanceToLine(q[i-1], q[i])
|
||||||
|
if d < min {
|
||||||
|
min = d
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return min
|
||||||
|
}
|
||||||
|
|
||||||
|
// DistanceToPolygon calculates the smallest distance to the polygon q.
|
||||||
|
func (p PointF) DistanceToPolygon(q PolygonF) float64 {
|
||||||
|
if len(q.Points) == 0 {
|
||||||
|
return NaN()
|
||||||
|
}
|
||||||
|
return p.DistanceToLines(append(q.Points, q.Points[0]))
|
||||||
|
}
|
||||||
|
|
||||||
// In tests if the point p is inside the rectangle r.
|
// In tests if the point p is inside the rectangle r.
|
||||||
func (p PointF) In(r RectangleF) bool {
|
func (p PointF) In(r RectangleF) bool {
|
||||||
if p.X < r.Min.X || p.X >= r.Max.X || p.Y < r.Min.Y || p.Y >= r.Max.Y {
|
if p.X < r.Min.X || p.X >= r.Max.X || p.Y < r.Min.Y || p.Y >= r.Max.Y {
|
||||||
|
63
pointf32.go
63
pointf32.go
@ -46,6 +46,51 @@ func (p PointF32) Distance2(q PointF32) float32 {
|
|||||||
return dx*dx + dy*dy
|
return dx*dx + dy*dy
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// DistanceToLine calculates the distance to the line segment a, b.
|
||||||
|
func (p PointF32) DistanceToLine(a, b PointF32) float32 {
|
||||||
|
dx1, dy1 := (a.X - p.X), (a.Y - p.Y)
|
||||||
|
dx2, dy2 := (b.X - a.X), (b.Y - a.Y)
|
||||||
|
t := -((dx1*dx2 + dy1*dy2) / (dx2*dx2 + dy2*dy2))
|
||||||
|
if 0 <= t && t <= 1 {
|
||||||
|
return Abs32(dx2*dy1-dy2*dx1) / Sqrt32(dx2*dx2+dy2*dy2)
|
||||||
|
}
|
||||||
|
d1, d2 := Sqrt32(Sq32(b.X-p.X)+Sq32(b.Y-p.Y)), Sqrt32(dx1*dx1+dy1*dy1)
|
||||||
|
if d1 < d2 {
|
||||||
|
return d1
|
||||||
|
}
|
||||||
|
return d2
|
||||||
|
}
|
||||||
|
|
||||||
|
// DistanceToLines calculates the smallest distance to the line segments of q.
|
||||||
|
func (p PointF32) DistanceToLines(q PointsF32) float32 {
|
||||||
|
n := len(q)
|
||||||
|
if n == 0 {
|
||||||
|
return NaN32()
|
||||||
|
}
|
||||||
|
if n == 1 {
|
||||||
|
return p.Distance(q[0])
|
||||||
|
}
|
||||||
|
min := p.DistanceToLine(q[0], q[1])
|
||||||
|
for i := range q {
|
||||||
|
if i < 2 {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
d := p.DistanceToLine(q[i-1], q[i])
|
||||||
|
if d < min {
|
||||||
|
min = d
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return min
|
||||||
|
}
|
||||||
|
|
||||||
|
// DistanceToPolygon calculates the smallest distance to the polygon q.
|
||||||
|
func (p PointF32) DistanceToPolygon(q PolygonF32) float32 {
|
||||||
|
if len(q.Points) == 0 {
|
||||||
|
return NaN32()
|
||||||
|
}
|
||||||
|
return p.DistanceToLines(append(q.Points, q.Points[0]))
|
||||||
|
}
|
||||||
|
|
||||||
// In tests if the point p is inside the rectangle r.
|
// In tests if the point p is inside the rectangle r.
|
||||||
func (p PointF32) In(r RectangleF32) bool {
|
func (p PointF32) In(r RectangleF32) bool {
|
||||||
if p.X < r.Min.X || p.X >= r.Max.X || p.Y < r.Min.Y || p.Y >= r.Max.Y {
|
if p.X < r.Min.X || p.X >= r.Max.X || p.Y < r.Min.Y || p.Y >= r.Max.Y {
|
||||||
@ -54,6 +99,24 @@ func (p PointF32) In(r RectangleF32) bool {
|
|||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// InPolygon tests is the point p is inside the polygon q.
|
||||||
|
func (p PointF32) InPolygon(q PolygonF32) bool {
|
||||||
|
var n = len(q.Points)
|
||||||
|
var c = false
|
||||||
|
|
||||||
|
var i = 0
|
||||||
|
var j = n - 1
|
||||||
|
for i < n {
|
||||||
|
if ((q.Points[i].Y >= p.Y) != (q.Points[j].Y >= p.Y)) &&
|
||||||
|
(p.X <= (q.Points[j].X-q.Points[i].X)*(p.Y-q.Points[i].Y)/(q.Points[j].Y-q.Points[i].Y)+q.Points[i].X) {
|
||||||
|
c = !c
|
||||||
|
}
|
||||||
|
j = i
|
||||||
|
i++
|
||||||
|
}
|
||||||
|
return c
|
||||||
|
}
|
||||||
|
|
||||||
// Invert changes the sign of the components.
|
// Invert changes the sign of the components.
|
||||||
func (p PointF32) Invert() PointF32 {
|
func (p PointF32) Invert() PointF32 {
|
||||||
return PointF32{-p.X, -p.Y}
|
return PointF32{-p.X, -p.Y}
|
||||||
|
10
polygonf.go
10
polygonf.go
@ -1,13 +1,19 @@
|
|||||||
package geom
|
package geom
|
||||||
|
|
||||||
|
// PointsF is a set of points.
|
||||||
|
type PointsF []PointF
|
||||||
|
|
||||||
|
// PolF creates a polygon of points q.
|
||||||
|
func PolF(q ...PointF) PolygonF { return PolygonF{Points: q} }
|
||||||
|
|
||||||
// PolygonF is defined by a set of points (floating point).
|
// PolygonF is defined by a set of points (floating point).
|
||||||
type PolygonF struct {
|
type PolygonF struct {
|
||||||
Points []PointF
|
Points PointsF
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add creates a new polyqon based on p with one or more extra points q.
|
// Add creates a new polyqon based on p with one or more extra points q.
|
||||||
func (p PolygonF) Add(q ...PointF) PolygonF {
|
func (p PolygonF) Add(q ...PointF) PolygonF {
|
||||||
var t = PolygonF{make([]PointF, len(p.Points)+len(q))}
|
var t = PolygonF{make(PointsF, len(p.Points)+len(q))}
|
||||||
copy(t.Points, p.Points)
|
copy(t.Points, p.Points)
|
||||||
copy(t.Points[len(p.Points):], q)
|
copy(t.Points[len(p.Points):], q)
|
||||||
return t
|
return t
|
||||||
|
20
polygonf32.go
Normal file
20
polygonf32.go
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
package geom
|
||||||
|
|
||||||
|
// PointsF32 is a set of points.
|
||||||
|
type PointsF32 []PointF32
|
||||||
|
|
||||||
|
// PolF32 creates a polygon of points q.
|
||||||
|
func PolF32(q ...PointF32) PolygonF32 { return PolygonF32{Points: q} }
|
||||||
|
|
||||||
|
// PolygonF32 is defined by a set of points (floating point).
|
||||||
|
type PolygonF32 struct {
|
||||||
|
Points PointsF32
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add creates a new polyqon based on p with one or more extra points q.
|
||||||
|
func (p PolygonF32) Add(q ...PointF32) PolygonF32 {
|
||||||
|
var t = PolygonF32{make(PointsF32, len(p.Points)+len(q))}
|
||||||
|
copy(t.Points, p.Points)
|
||||||
|
copy(t.Points[len(p.Points):], q)
|
||||||
|
return t
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user