func SymmetricDifference(a, b geom.Geometry, opts ...geom.ConstructorOption) (geom.Geometry, error) {
	result, err := binaryOpG(a, b, opts, func(ctx C.GEOSContextHandle_t, a, b *C.GEOSGeometry) *C.GEOSGeometry {
		return C.GEOSSymDifference_r(ctx, a, b)
	})
	return result, wrap(err, "executing GEOSSymDifference_r")
}
SymmetricDifference returns the geometry that represents the parts of the
input geometries that are not part of the other input geometry.
package geos
import "C"
import (
	"unsafe"
	"github.com/peterstace/simplefeatures/geom"
)
func Equals(a, b geom.Geometry) (bool, error) {
	result, err := binaryOpB(a, b, func(h C.GEOSContextHandle_t, a, b *C.GEOSGeometry) C.char {
		return C.GEOSEquals_r(h, a, b)
	})
	return result, wrap(err, "executing GEOSEquals_r")
}
func Disjoint(a, b geom.Geometry) (bool, error) {
	result, err := binaryOpB(a, b, func(h C.GEOSContextHandle_t, a, b *C.GEOSGeometry) C.char {
		return C.GEOSDisjoint_r(h, a, b)
	})
	return result, wrap(err, "executing GEOSDisjoint_r")
}
func Touches(a, b geom.Geometry) (bool, error) {
	result, err := binaryOpB(a, b, func(h C.GEOSContextHandle_t, a, b *C.GEOSGeometry) C.char {
		return C.GEOSTouches_r(h, a, b)
	})
	return result, wrap(err, "executing GEOSTouches_r")
}
func Contains(a, b geom.Geometry) (bool, error) {
	result, err := binaryOpB(a, b, func(h C.GEOSContextHandle_t, a, b *C.GEOSGeometry) C.char {
		return C.GEOSContains_r(h, a, b)
	})
	return result, wrap(err, "executing GEOSContains_r")
}
func Covers(a, b geom.Geometry) (bool, error) {
	result, err := binaryOpB(a, b, func(h C.GEOSContextHandle_t, a, b *C.GEOSGeometry) C.char {
		return C.GEOSCovers_r(h, a, b)
	})
	return result, wrap(err, "executing GEOSCovers_r")
}
func Intersects(a, b geom.Geometry) (bool, error) {
	result, err := binaryOpB(a, b, func(h C.GEOSContextHandle_t, a, b *C.GEOSGeometry) C.char {
		return C.GEOSIntersects_r(h, a, b)
	})
	return result, wrap(err, "executing GEOSIntersects_r")
}
func Within(a, b geom.Geometry) (bool, error) {
	result, err := binaryOpB(a, b, func(h C.GEOSContextHandle_t, a, b *C.GEOSGeometry) C.char {
		return C.GEOSWithin_r(h, a, b)
	})
	return result, wrap(err, "executing GEOSWithin_r")
}
func CoveredBy(a, b geom.Geometry) (bool, error) {
	result, err := binaryOpB(a, b, func(h C.GEOSContextHandle_t, a, b *C.GEOSGeometry) C.char {
		return C.GEOSCoveredBy_r(h, a, b)
	})
	return result, wrap(err, "executing GEOSCoveredBy_r")
}
func Crosses(a, b geom.Geometry) (bool, error) {
	result, err := binaryOpB(a, b, func(h C.GEOSContextHandle_t, a, b *C.GEOSGeometry) C.char {
		return C.GEOSCrosses_r(h, a, b)
	})
	return result, wrap(err, "executing GEOSCrosses_r")
}
func Relate(g1, g2 geom.Geometry) (string, error) {
	var result string
	err := binaryOpE(g1, g2, func(h *handle, gh1, gh2 *C.GEOSGeometry) error {
		cstr := C.GEOSRelate_r(h.context, gh1, gh2)
		if cstr == nil {
			return wrap(h.err(), "executing GEOSRelate_r")
		}
		defer C.GEOSFree_r(h.context, unsafe.Pointer(cstr))
		result = C.GoString(cstr)
		return nil
	})
	return result, err
}
func Overlaps(a, b geom.Geometry) (bool, error) {
	result, err := binaryOpB(a, b, func(h C.GEOSContextHandle_t, a, b *C.GEOSGeometry) C.char {
		return C.GEOSOverlaps_r(h, a, b)
	})
	return result, wrap(err, "executing GEOSOverlaps_r")
}
func Union(a, b geom.Geometry, opts ...geom.ConstructorOption) (geom.Geometry, error) {
	g, err := binaryOpG(a, b, opts, func(ctx C.GEOSContextHandle_t, a, b *C.GEOSGeometry) *C.GEOSGeometry {
		return C.GEOSUnion_r(ctx, a, b)
	})
	return g, wrap(err, "executing GEOSUnion_r")
}
func Intersection(a, b geom.Geometry, opts ...geom.ConstructorOption) (geom.Geometry, error) {
	g, err := binaryOpG(a, b, opts, func(ctx C.GEOSContextHandle_t, a, b *C.GEOSGeometry) *C.GEOSGeometry {
		return C.GEOSIntersection_r(ctx, a, b)
	})
	return g, wrap(err, "executing GEOSIntersection_r")
}
type BufferOption func(*bufferOptionSet)
type bufferOptionSet struct {
	quadSegments int
	endCapStyle  int
	joinStyle    int
	mitreLimit   float64
	ctorOpts     []geom.ConstructorOption
}
func newBufferOptionSet(opts []BufferOption) bufferOptionSet {
	bos := bufferOptionSet{
		quadSegments: 8,
		endCapStyle:  int(C.GEOSBUF_CAP_ROUND),
		joinStyle:    int(C.GEOSBUF_JOIN_ROUND),
		mitreLimit:   0.0,
	}
	for _, opt := range opts {
		opt(&bos)
	}
	return bos
}
func BufferQuadSegments(quadSegments int) BufferOption {
	return func(bos *bufferOptionSet) {
		bos.quadSegments = quadSegments
	}
}
func BufferEndCapRound() BufferOption {
	return func(bos *bufferOptionSet) {
		bos.endCapStyle = int(C.GEOSBUF_CAP_ROUND)
	}
}
func BufferEndCapFlat() BufferOption {
	return func(bos *bufferOptionSet) {
		bos.endCapStyle = int(C.GEOSBUF_CAP_FLAT)
	}
}
func BufferEndCapSquare() BufferOption {
	return func(bos *bufferOptionSet) {
		bos.endCapStyle = int(C.GEOSBUF_CAP_SQUARE)
	}
}
func BufferJoinStyleRound() BufferOption {
	return func(bos *bufferOptionSet) {
		bos.joinStyle = int(C.GEOSBUF_JOIN_ROUND)
		bos.mitreLimit = 0.0
	}
}
func BufferJoinStyleMitre(mitreLimit float64) BufferOption {
	return func(bos *bufferOptionSet) {
		bos.joinStyle = int(C.GEOSBUF_JOIN_MITRE)
		bos.mitreLimit = mitreLimit
	}
}
func BufferJoinStyleBevel() BufferOption {
	return func(bos *bufferOptionSet) {
		bos.joinStyle = int(C.GEOSBUF_JOIN_BEVEL)
		bos.mitreLimit = 0.0
	}
}
func BufferConstructorOption(opts ...geom.ConstructorOption) BufferOption {
	return func(bos *bufferOptionSet) {
		bos.ctorOpts = append(bos.ctorOpts, opts...)
	}
}
func Buffer(g geom.Geometry, radius float64, opts ...BufferOption) (geom.Geometry, error) {
	optSet := newBufferOptionSet(opts)
	result, err := unaryOpG(g, optSet.ctorOpts, func(ctx C.GEOSContextHandle_t, gh *C.GEOSGeometry) *C.GEOSGeometry {
		return C.GEOSBufferWithStyle_r(
			ctx, gh, C.double(radius),
			C.int(optSet.quadSegments),
			C.int(optSet.endCapStyle),
			C.int(optSet.joinStyle),
			C.double(optSet.mitreLimit),
		)
	})
	return result, wrap(err, "executing GEOSBufferWithStyle_r")
}
func Simplify(g geom.Geometry, tolerance float64, opts ...geom.ConstructorOption) (geom.Geometry, error) {
	result, err := unaryOpG(g, opts, func(ctx C.GEOSContextHandle_t, gh *C.GEOSGeometry) *C.GEOSGeometry {
		return C.GEOSSimplify_r(ctx, gh, C.double(tolerance))
	})
	return result, wrap(err, "executing GEOSSimplify_r")
}
func Difference(a, b geom.Geometry, opts ...geom.ConstructorOption) (geom.Geometry, error) {
	result, err := binaryOpG(a, b, opts, func(ctx C.GEOSContextHandle_t, a, b *C.GEOSGeometry) *C.GEOSGeometry {
		return C.GEOSDifference_r(ctx, a, b)
	})
	return result, wrap(err, "executing GEOSDifference_r")
}