package geom import ( "math" ) // PointF is an X, Y coordinate pair (floating point). type PointF struct { X, Y float64 } // ZeroPtF is initialized on (0, 0). var ZeroPtF = PointF{X: 0, Y: 0} // PtF is a shorthand function to create a point. func PtF(x, y float64) PointF { return PointF{X: x, Y: y} } // To32 transforms the point p into a PointF32. func (p PointF) To32() PointF32 { return PointF32{float32(p.X), float32(p.Y)} } // Add adds q as a vector to p. func (p PointF) Add(q PointF) PointF { return PointF{p.X + q.X, p.Y + q.Y} } // Sub subtracts q as a vector from p. func (p PointF) Sub(q PointF) PointF { return PointF{p.X - q.X, p.Y - q.Y} } // AngleTo calculates the angle [0..2*Pi) from point p to point q. func (p PointF) AngleTo(q PointF) float64 { a := math.Atan((p.Y - q.Y) / (p.X - q.X)) if q.X < p.X { return a + math.Pi } if a < 0 { a += 2 * math.Pi } return a } // Distance calculates the distance between points p and q. func (p PointF) Distance(q PointF) float64 { return math.Sqrt(p.Distance2(q)) } // Distance2 calculates the squared distance between points p and q. func (p PointF) Distance2(q PointF) float64 { dx := q.X - p.X dy := q.Y - p.Y return dx*dx + dy*dy } // In tests if the point p is inside the rectangle r. 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 { return false } return true } // InPolygon tests is the point p is inside the polygon q. func (p PointF) InPolygon(q PolygonF) 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 }