func (p Polygon) IsSimple() bool {
	return true
}
IsSimple returns true if this geometry contains no anomalous geometry
points, such as self intersection or self tangency. Because Polygons are
always simple, this method always returns true.
package geom
import (
	"database/sql/driver"
	"fmt"
	"math"
	"unsafe"
	"github.com/peterstace/simplefeatures/rtree"
)
type Polygon struct {
	rings []LineString
	ctype CoordinatesType
}
func NewPolygon(rings []LineString, opts ...ConstructorOption) (Polygon, error) {
	if len(rings) == 0 {
		return Polygon{}, nil
	}
	ctype := DimXYZM
	for _, r := range rings {
		ctype &= r.CoordinatesType()
	}
	rings = append([]LineString(nil), rings...)
	for i := range rings {
		rings[i] = rings[i].ForceCoordinatesType(ctype)
	}
	ctorOpts := newOptionSet(opts)
	if err := validatePolygon(rings, ctorOpts); err != nil {
		if ctorOpts.omitInvalid {
			return Polygon{}, nil
		}
		return Polygon{}, err
	}
	return Polygon{rings, ctype}, nil
}
func validatePolygon(rings []LineString, opts ctorOptionSet) error {
	if len(rings) == 0 || opts.skipValidations {
		return nil
	}
	for _, r := range rings {
		if !r.IsClosed() {
			return validationError{"polygon ring not closed"}
		}
		if !r.IsSimple() {
			return validationError{"polygon ring not simple"}
		}
	}
	nextInterVert := len(rings)
	interVerts := make(map[XY]int)
	graph := newGraph()
	boxes := make([]rtree.Box, len(rings))
	items := make([]rtree.BulkItem, len(rings))
	for i, r := range rings {
		box, ok := r.Envelope().box()
		if !ok {
			panic("unexpected empty ring")
		}
		boxes[i] = box
		items[i] = rtree.BulkItem{Box: boxes[i], RecordID: i}
	}
	tree := rtree.BulkLoad(items)
	for i := range rings {
		if err := tree.RangeSearch(boxes[i], func(j int) error {
			if i <= j {
				return nil
			}
			if i > 0 && j > 0 {  
				iStart := rings[i].Coordinates().GetXY(0)
				jStart := rings[j].Coordinates().GetXY(0)
				nestedFwd := relatePointToRing(iStart, rings[j]) == interior
				nestedRev := relatePointToRing(jStart, rings[i]) == interior
				if nestedFwd || nestedRev {
					return validationError{"polygon has nested rings"}
				}
			}
			intersects, ext := hasIntersectionLineStringWithLineString(rings[i], rings[j], true)
			if !intersects {
				return nil
			}
			if ext.multiplePoints {
				return validationError{"polygon rings intersect at multiple points"}
			}
			interVert, ok := interVerts[ext.singlePoint]
			if !ok {
				interVert = nextInterVert
				nextInterVert++
				interVerts[ext.singlePoint] = interVert
			}
			graph.addEdge(interVert, i)
			graph.addEdge(interVert, j)
			return nil
		}); err != nil {
			return err
		}
	}
	for _, hole := range rings[1:] {
		xy, ok := hole.StartPoint().XY()
		if !ok {
			continue
		}
		if relatePointToRing(xy, rings[0]) == exterior {
			return validationError{"polygon interior ring outside of exterior ring"}
		}
	}
	if graph.hasCycle() {
		return validationError{"polygon has disconnected interior"}
	}
	return nil
}
func (p Polygon) Type() GeometryType {
	return TypePolygon
}
func (p Polygon) AsGeometry() Geometry {
	return Geometry{TypePolygon, unsafe.Pointer(&p)}
}
func (p Polygon) ExteriorRing() LineString {
	if p.IsEmpty() {
		return LineString{}.ForceCoordinatesType(p.ctype)
	}
	return p.rings[0]
}
func (p Polygon) NumInteriorRings() int {
	return max(0, len(p.rings)-1)
}
func (p Polygon) NumRings() int {
	if p.IsEmpty() {
		return 0
	}
	return 1 + p.NumInteriorRings()
}
func (p Polygon) InteriorRingN(n int) LineString {
	if n == -1 {
		panic("n out of range")
	}
	return p.rings[n+1]
}
func (p Polygon) AsText() string {
	return string(p.AppendWKT(nil))
}
func (p Polygon) AppendWKT(dst []byte) []byte {
	dst = appendWKTHeader(dst, "POLYGON", p.ctype)
	return p.appendWKTBody(dst)
}
func (p Polygon) appendWKTBody(dst []byte) []byte {
	if p.IsEmpty() {
		return appendWKTEmpty(dst)
	}
	dst = append(dst, '(')
	for i, r := range p.rings {
		dst = r.appendWKTBody(dst)
		if i+1 < len(p.rings) {
			dst = append(dst, ',')
		}
	}
	return append(dst, ')')
}