// Geometry will do a smart more involved clipping and wrapping of the geometry.
// It will return simple OGC geometries. Rings that are NOT closed AND have an
// endpoint in the bound will be implicitly closed.
189597
func Geometry(box orb.Bound, g orb.Geometry, o orb.Orientation) orb.Geometry {
	if g == nil {
		return nil
	}

	if g.Dimensions() != 2 {
		return clip.Geometry(box, g)
	}

	var mp orb.MultiPolygon
	switch g := g.(type) {
	case orb.Ring:
		mp = Ring(box, g, o)
	case orb.Polygon:
		mp = Polygon(box, g, o)
	case orb.MultiPolygon:
		mp = MultiPolygon(box, g, o)
	case orb.Bound:
		return clip.Geometry(box, g)
	case orb.Collection:
		var result orb.Collection
		for _, c := range g {
			c := Geometry(box, c, o)
			if c != nil {
				result = append(result, c)
			}
		}

		if len(result) == 1 {
			return result[0]
		}

		return result
	default:
		panic(fmt.Sprintf("geometry type not supported: %T", g))
	}

	if mp == nil {
		return nil
	}

	if len(mp) == 1 {
		return mp[0]
	}

	return mp
}
1039730
func (grng GeometricGenerator) Geometric(p float64) int64 {
	if !(0.0 <= p && p <= 1.0) {
		panic(fmt.Sprintf("Invalid probability p: %.2f", p))
	}
	return grng.geometric(p)
}
419923
func (p *Path) Intersection(geometry interface{}) ([]*Point, [][2]int) {
	var points []*Point
	var segments [][2]int

	switch g := geometry.(type) {
	case Line:
		points, segments = p.IntersectionLine(&g)
	case *Line:
		points, segments = p.IntersectionLine(g)
	case Path:
		points, segments = p.IntersectionPath(&g)
	case *Path:
		points, segments = p.IntersectionPath(g)
	default:
		panic("can only determine intersection with lines and paths")
	}

	return points, segments
}
287878
func (gc GeometryCollection) String() string {
	var result string
	if bytes, err := json.Marshal(gc); err == nil {
		result = string(bytes)
	} else {
		result = err.Error()
	}
	return result
}
599213
func (g *Geometry) Snap(other *Geometry, tolerance float64) (*Geometry, error) {
	return geomFromC("Snap", cGEOSSnap(g.g, other.g, C.double(tolerance)))
}
824875
func (p *PGeometry) Crosses(other *Geometry) (bool, error) {
	return p.predicate("crosses", cGEOSPreparedCrosses, other)
}
1087783
func (s *GeometryScanner) Scan(d interface{}) error {
	s.Geometry = nil
	s.Valid = false

	if d == nil {
		return nil
	}

	data, ok := d.([]byte)
	if !ok {
		return ErrUnsupportedDataType
	}

	if data == nil {
		return nil
	}

	switch g := s.g.(type) {
	case nil:
		m, err := Unmarshal(data)
		if err != nil {
			return err
		}

		s.Geometry = m
		s.Valid = true
		return nil
	case *orb.Point:
		p, err := scanPoint(data)
		if err != nil {
			return err
		}

		*g = p
		s.Geometry = p
		s.Valid = true
		return nil
	case *orb.MultiPoint:
		p, err := scanMultiPoint(data)
		if err != nil {
			return err
		}

		*g = p
		s.Geometry = p
		s.Valid = true
		return nil
	case *orb.LineString:
		p, err := scanLineString(data)
		if err != nil {
			return err
		}

		*g = p
		s.Geometry = p
		s.Valid = true
		return nil
	case *orb.MultiLineString:
		p, err := scanMultiLineString(data)
		if err != nil {
			return err
		}

		*g = p
		s.Geometry = p
		s.Valid = true
		return nil
	case *orb.Ring:
		m, err := Unmarshal(data)
		if err != nil {
			return err
		}

		if p, ok := m.(orb.Polygon); ok && len(p) == 1 {
			*g = p[0]
			s.Geometry = p[0]
			s.Valid = true
			return nil
		}

		return ErrIncorrectGeometry
	case *orb.Polygon:
		m, err := scanPolygon(data)
		if err != nil {
			return err
		}

		*g = m
		s.Geometry = m
		s.Valid = true
		return nil
	case *orb.MultiPolygon:
		m, err := scanMultiPolygon(data)
		if err != nil {
			return err
		}

		*g = m
		s.Geometry = m
		s.Valid = true
		return nil
	case *orb.Collection:
		m, err := scanCollection(data)
		if err != nil {
			return err
		}

		*g = m
		s.Geometry = m
		s.Valid = true
		return nil
	case *orb.Bound:
		m, err := Unmarshal(data)
		if err != nil {
			return err
		}

		b := m.Bound()
		*g = b
		s.Geometry = b
		s.Valid = true
		return nil
	}

	return ErrIncorrectGeometry
}
682265
func (s *RadialSimplifier) Ring(r orb.Ring) orb.Ring {
	return ring(s, r)
}
486116
func Ring(box orb.Bound, r orb.Ring, o orb.Orientation) orb.MultiPolygon {
	if len(r) == 0 {
		return nil
	}

	open, closed := clipRings(box, []orb.Ring{r})
	if len(open) == 0 {
		// nothing was clipped
		if len(closed) == 0 {
			return nil // everything outside bound
		}

		return orb.MultiPolygon{{r}} // everything inside bound
	}

	// in a well defined ring there will be no closed sections
	return smartWrap(box, open, o)
}
939403
func Clone(g Geometry) Geometry {
	if g == nil {
		return nil
	}

	switch g := g.(type) {
	case Point:
		return g
	case MultiPoint:
		if g == nil {
			return nil
		}
		return g.Clone()
	case LineString:
		if g == nil {
			return nil
		}
		return g.Clone()
	case MultiLineString:
		if g == nil {
			return nil
		}
		return g.Clone()
	case Ring:
		if g == nil {
			return nil
		}
		return g.Clone()
	case Polygon:
		if g == nil {
			return nil
		}
		return g.Clone()
	case MultiPolygon:
		if g == nil {
			return nil
		}
		return g.Clone()
	case Collection:
		if g == nil {
			return nil
		}
		return g.Clone()
	case Bound:
		return g
	}

	panic(fmt.Sprintf("geometry type not supported: %T", g))
}
1199587
func (g Geometry) MarshalJSON() ([]byte, error) {
	// defining a struct here lets us define the order of the JSON elements.
	type geometry struct {
		Type        GeometryType           `json:"type"`
		BoundingBox []float64              `json:"bbox,omitempty"`
		Coordinates interface{}            `json:"coordinates,omitempty"`
		Geometries  interface{}            `json:"geometries,omitempty"`
		CRS         map[string]interface{} `json:"crs,omitempty"`
	}

	geo := &geometry{
		Type: g.Type,
	}

	if g.BoundingBox != nil && len(g.BoundingBox) != 0 {
		geo.BoundingBox = g.BoundingBox
	}

	switch g.Type {
	case GeometryPoint:
		geo.Coordinates = g.Point
	case GeometryMultiPoint:
		geo.Coordinates = g.MultiPoint
	case GeometryLineString:
		geo.Coordinates = g.LineString
	case GeometryMultiLineString:
		geo.Coordinates = g.MultiLineString
	case GeometryPolygon:
		geo.Coordinates = g.Polygon
	case GeometryMultiPolygon:
		geo.Coordinates = g.MultiPolygon
	case GeometryCollection:
		geo.Geometries = g.Geometries
	}

	return json.Marshal(geo)
}
622687
func (g *Geometry) Holes() ([]*Geometry, error) {
	n, err := intFromC("NInteriorRing", cGEOSGetNumInteriorRings(g.g), -1)
	if err != nil {
		return nil, err
	}
	holes := make([]*Geometry, n)
	for i := 0; i < n; i++ {
		// According to the GEOS C API, GEOSGetInteriorRingN returns a pointer
		// to internal storage and must not be destroyed directly, so we bypass
		// the usual constructor to avoid the finalizer.
		ring, err := geomFromPtrUnowned(cGEOSGetInteriorRingN(g.g, C.int(i)))
		if err != nil {
			return nil, err
		}
		holes[i] = ring
	}
	return holes, nil
}
670718
func (b *Bounds) Polygon() *Polygon {
	if b.IsEmpty() {
		return NewPolygonFlat(XY, nil, nil)
	}
	x1, y1 := b.min[0], b.min[1]
	x2, y2 := b.max[0], b.max[1]
	flatCoords := []float64{
		x1, y1,
		x1, y2,
		x2, y2,
		x2, y1,
		x1, y1,
	}
	return NewPolygonFlat(XY, flatCoords, []int{len(flatCoords)})
}
1029361
func Collection(b orb.Bound, c orb.Collection) orb.Collection {
	var result orb.Collection
	for _, g := range c {
		clipped := Geometry(b, g)
		if clipped != nil {
			result = append(result, clipped)
		}
	}

	return result
}
744489
func (g *Geometry) SimplifyP(tolerance float64) (*Geometry, error) {
	return g.simplify("simplify", cGEOSTopologyPreserveSimplify, tolerance)
}
780367
func (g *Geometry) Overlaps(other *Geometry) (bool, error) {
	return g.binaryPred("Overlaps", cGEOSOverlaps, other)
}
35280
func (t *Polygon) AddGeometry(g interface{}) error {
	switch c := g.(type) {
	case MultiLine:
		t.AddCoordinates(c...)
		break
	case Coordinates:
		t.AddCoordinates(c)
		break
	default:
		return errors.New(fmt.Sprintf("AssertionError %v", g))
	}
	return nil
}