func (p *Polyline) NumChains() int {
	return minInt(1, p.NumEdges())
}
NumChains reports the number of contiguous edge chains in this Polyline.
package s2
import (
	"fmt"
	"io"
	"math"
	"github.com/golang/geo/s1"
)
type Polyline []Point
func PolylineFromLatLngs(points []LatLng) *Polyline {
	p := make(Polyline, len(points))
	for k, v := range points {
		p[k] = PointFromLatLng(v)
	}
	return &p
}
func (p *Polyline) Reverse() {
	for i := 0; i < len(*p)/2; i++ {
		(*p)[i], (*p)[len(*p)-i-1] = (*p)[len(*p)-i-1], (*p)[i]
	}
}
func (p *Polyline) Length() s1.Angle {
	var length s1.Angle
	for i := 1; i < len(*p); i++ {
		length += (*p)[i-1].Distance((*p)[i])
	}
	return length
}
func (p *Polyline) Centroid() Point {
	var centroid Point
	for i := 1; i < len(*p); i++ {
		vSum := (*p)[i-1].Add((*p)[i].Vector)   
		vDiff := (*p)[i-1].Sub((*p)[i].Vector)  
		centroid = Point{centroid.Add(vSum.Mul(math.Sqrt(vDiff.Norm2() / vSum.Norm2())))}
	}
	return centroid
}
func (p *Polyline) Equal(b *Polyline) bool {
	if len(*p) != len(*b) {
		return false
	}
	for i, v := range *p {
		if v != (*b)[i] {
			return false
		}
	}
	return true
}
func (p *Polyline) ApproxEqual(o *Polyline) bool {
	return p.approxEqual(o, s1.Angle(epsilon))
}
func (p *Polyline) approxEqual(o *Polyline, maxError s1.Angle) bool {
	if len(*p) != len(*o) {
		return false
	}
	for offset, val := range *p {
		if !val.approxEqual((*o)[offset], maxError) {
			return false
		}
	}
	return true
}
func (p *Polyline) CapBound() Cap {
	return p.RectBound().CapBound()
}
func (p *Polyline) RectBound() Rect {
	rb := NewRectBounder()
	for _, v := range *p {
		rb.AddPoint(v)
	}
	return rb.RectBound()
}
func (p *Polyline) ContainsCell(cell Cell) bool {
	return false
}
func (p *Polyline) IntersectsCell(cell Cell) bool {
	if len(*p) == 0 {
		return false
	}
	for _, v := range *p {
		if cell.ContainsPoint(v) {
			return true
		}
	}
	cellVertices := []Point{
		cell.Vertex(0),
		cell.Vertex(1),
		cell.Vertex(2),
		cell.Vertex(3),
	}
	for j := 0; j < 4; j++ {
		crosser := NewChainEdgeCrosser(cellVertices[j], cellVertices[(j+1)&3], (*p)[0])
		for i := 1; i < len(*p); i++ {
			if crosser.ChainCrossingSign((*p)[i]) != DoNotCross {
				return true
			}
		}
	}
	return false
}
func (p *Polyline) ContainsPoint(point Point) bool {
	return false
}
func (p *Polyline) CellUnionBound() []CellID {
	return p.CapBound().CellUnionBound()
}
func (p *Polyline) NumEdges() int {
	if len(*p) == 0 {
		return 0
	}
	return len(*p) - 1
}
func (p *Polyline) Edge(i int) Edge {
	return Edge{(*p)[i], (*p)[i+1]}
}
func (p *Polyline) ReferencePoint() ReferencePoint {
	return OriginReferencePoint(false)
}