package geom import "log" // 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). type PolygonF struct { Points PointsF } // Add adds q as a vector to all points in p. func (p PolygonF) Add(q PointF) PolygonF { var r = p.copy() for i, pt := range r.Points { r.Points[i] = pt.Add(q) } return r } func (p PolygonF) copy() PolygonF { var q = PolygonF{make(PointsF, len(p.Points))} copy(q.Points, p.Points) return q } // Extend creates a new polygon based on p with one or more extra points q. func (p PolygonF) Extend(q ...PointF) PolygonF { var t = PolygonF{make(PointsF, len(p.Points)+len(q))} copy(t.Points, p.Points) copy(t.Points[len(p.Points):], q) return t } // Mul multiplies the points of polygon p with t and returns the result. func (p PolygonF) Mul(t float64) PolygonF { var q = p.copy() for i, pt := range q.Points { q.Points[i] = pt.Mul(t) } return q } // Triangulate triangulates the polygon p. func (p PolygonF) Triangulate() []TriangleF { var triangles []TriangleF points := p.copy().Points[:] n := len(points) if n > 0 && points[0] == points[n-1] { // remove first point if polygon is closed points = points[1:] n-- } triangle := func(i int) TriangleF { return TrF(points[(i+n-1)%n], points[i], points[(i+1)%n]) } ear := func(i int) (TriangleF, bool) { t := triangle(i) if t.Winding() == WindingCounterClockwise { return TriangleF{}, false } for j := 0; j < n-3; j++ { p := points[(i+2+j)%n] if t.Contains(p) { return TriangleF{}, false } } return t, true } for n >= 3 { leastSharp := -1 var leastSharpAngle float64 for i := range points { if t, ok := ear(i); ok { sharpAngle := t.SmallestAngle() if leastSharp < 0 || sharpAngle > leastSharpAngle { leastSharp = i leastSharpAngle = sharpAngle } } } if leastSharp < 0 { if n >= 3 { log.Println("not fully triangulated") } break } triangles = append(triangles, triangle(leastSharp)) points = append(points[:leastSharp], points[leastSharp+1:]...) n = len(points) } return triangles } // Reverse reverses the order of the points of polygon p. func (p PolygonF) Reverse() PolygonF { n := len(p.Points) var q = PolygonF{make(PointsF, n)} for i := 0; i < n/2; i++ { q.Points[i], q.Points[n-i-1] = p.Points[n-i-1], p.Points[i] } return q }