func (geom Geometry) SpatialReference() SpatialReference {
	spatialRef := C.OGR_G_GetSpatialReference(geom.cval)
	return SpatialReference{spatialRef}
}
Fetch the spatial reference associated with this geometry
package gdal
import "C"
import (
	"reflect"
	"time"
	"unsafe"
)
func init() {
	C.OGRRegisterAll()
}
type GeometryType uint32
const (
	GT_Unknown               = GeometryType(C.wkbUnknown)
	GT_Point                 = GeometryType(C.wkbPoint)
	GT_LineString            = GeometryType(C.wkbLineString)
	GT_Polygon               = GeometryType(C.wkbPolygon)
	GT_MultiPoint            = GeometryType(C.wkbMultiPoint)
	GT_MultiLineString       = GeometryType(C.wkbMultiLineString)
	GT_MultiPolygon          = GeometryType(C.wkbMultiPolygon)
	GT_GeometryCollection    = GeometryType(C.wkbGeometryCollection)
	GT_None                  = GeometryType(C.wkbNone)
	GT_LinearRing            = GeometryType(C.wkbLinearRing)
	GT_Point25D              = GeometryType(C.wkbPoint25D)
	GT_LineString25D         = GeometryType(C.wkbLineString25D)
	GT_Polygon25D            = GeometryType(C.wkbPolygon25D)
	GT_MultiPoint25D         = GeometryType(C.wkbMultiPoint25D)
	GT_MultiLineString25D    = GeometryType(C.wkbMultiLineString25D)
	GT_MultiPolygon25D       = GeometryType(C.wkbMultiPolygon25D)
	GT_GeometryCollection25D = GeometryType(C.wkbGeometryCollection25D)
)
type Envelope struct {
	cval C.OGREnvelope
}
func (env Envelope) MinX() float64 {
	return float64(env.cval.MinX)
}
func (env Envelope) MaxX() float64 {
	return float64(env.cval.MaxX)
}
func (env Envelope) MinY() float64 {
	return float64(env.cval.MinY)
}
func (env Envelope) MaxY() float64 {
	return float64(env.cval.MaxY)
}
func (env *Envelope) SetMinX(val float64) {
	env.cval.MinX = C.double(val)
}
func (env *Envelope) SetMaxX(val float64) {
	env.cval.MaxX = C.double(val)
}
func (env *Envelope) SetMinY(val float64) {
	env.cval.MinY = C.double(val)
}
func (env *Envelope) SetMaxY(val float64) {
	env.cval.MaxY = C.double(val)
}
func (env Envelope) IsInit() bool {
	return env.cval.MinX != 0 || env.cval.MinY != 0 || env.cval.MaxX != 0 || env.cval.MaxY != 0
}
func min(a, b C.double) C.double {
	if a < b {
		return a
	}
	return b
}
func max(a, b C.double) C.double {
	if a > b {
		return a
	}
	return b
}
func (env Envelope) Union(other Envelope) Envelope {
	if env.IsInit() {
		env.cval.MinX = min(env.cval.MinX, other.cval.MinX)
		env.cval.MinY = min(env.cval.MinY, other.cval.MinY)
		env.cval.MaxX = max(env.cval.MaxX, other.cval.MaxX)
		env.cval.MaxY = max(env.cval.MaxY, other.cval.MaxY)
	} else {
		env.cval.MinX = other.cval.MinX
		env.cval.MinY = other.cval.MinY
		env.cval.MaxX = other.cval.MaxX
		env.cval.MaxY = other.cval.MaxY
	}
	return env
}
func (env Envelope) Intersect(other Envelope) Envelope {
	if env.Intersects(other) {
		if env.IsInit() {
			env.cval.MinX = max(env.cval.MinX, other.cval.MinX)
			env.cval.MinY = max(env.cval.MinY, other.cval.MinY)
			env.cval.MaxX = min(env.cval.MaxX, other.cval.MaxX)
			env.cval.MaxY = min(env.cval.MaxY, other.cval.MaxY)
		} else {
			env.cval.MinX = other.cval.MinX
			env.cval.MinY = other.cval.MinY
			env.cval.MaxX = other.cval.MaxX
			env.cval.MaxY = other.cval.MaxY
		}
	} else {
		env.cval.MinX = 0
		env.cval.MinY = 0
		env.cval.MaxX = 0
		env.cval.MaxY = 0
	}
	return env
}
func (env Envelope) Intersects(other Envelope) bool {
	return env.cval.MinX <= other.cval.MaxX &&
		env.cval.MaxX >= other.cval.MinX &&
		env.cval.MinY <= other.cval.MaxY &&
		env.cval.MaxY >= other.cval.MinY
}
func (env Envelope) Contains(other Envelope) bool {
	return env.cval.MinX <= other.cval.MinX &&
		env.cval.MaxX >= other.cval.MaxX &&
		env.cval.MinY <= other.cval.MinY &&
		env.cval.MaxY >= other.cval.MaxY
}
func CleanupOGR() {
	C.OGRCleanupAll()
}
func BoolToCInt(in bool) (out C.int) {
	if in {
		out = 1
	} else {
		out = 0
	}
	return
}
type Geometry struct {
	cval C.OGRGeometryH
}
func CreateFromWKB(wkb []uint8, srs SpatialReference, bytes int) (Geometry, error) {
	cString := unsafe.Pointer(&wkb[0])
	var newGeom Geometry
	return newGeom, C.go_CreateFromWkb(
		cString, srs.cval, &newGeom.cval, C.int(bytes),
	).Err()
}
func CreateFromWKT(wkt string, srs SpatialReference) (Geometry, error) {
	cString := C.CString(wkt)
	defer C.free(unsafe.Pointer(cString))
	var newGeom Geometry
	return newGeom, C.OGR_G_CreateFromWkt(
		&cString, srs.cval, &newGeom.cval,
	).Err()
}
func CreateFromJson(_json string) Geometry {
	cString := C.CString(_json)
	defer C.free(unsafe.Pointer(cString))
	var newGeom Geometry
	newGeom.cval = C.OGR_G_CreateGeometryFromJson(cString)
	return newGeom
}
func (geometry Geometry) Destroy() {
	C.OGR_G_DestroyGeometry(geometry.cval)
}
func Create(geomType GeometryType) Geometry {
	geom := C.OGR_G_CreateGeometry(C.OGRwkbGeometryType(geomType))
	return Geometry{geom}
}
func ApproximateArcAngles(
	x, y, z,
	primaryRadius,
	secondaryRadius,
	rotation,
	startAngle,
	endAngle,
	stepSizeDegrees float64,
) Geometry {
	geom := C.OGR_G_ApproximateArcAngles(
		C.double(x),
		C.double(y),
		C.double(z),
		C.double(primaryRadius),
		C.double(secondaryRadius),
		C.double(rotation),
		C.double(startAngle),
		C.double(endAngle),
		C.double(stepSizeDegrees))
	return Geometry{geom}
}
func (geom Geometry) ForceToPolygon() Geometry {
	newGeom := C.OGR_G_ForceToPolygon(geom.cval)
	return Geometry{newGeom}
}
func (geom Geometry) ForceToMultiPolygon() Geometry {
	newGeom := C.OGR_G_ForceToMultiPolygon(geom.cval)
	return Geometry{newGeom}
}
func (geom Geometry) ForceToMultiPoint() Geometry {
	newGeom := C.OGR_G_ForceToMultiPoint(geom.cval)
	return Geometry{newGeom}
}
func (geom Geometry) ForceToMultiLineString() Geometry {
	newGeom := C.OGR_G_ForceToMultiLineString(geom.cval)
	return Geometry{newGeom}
}
func (geom Geometry) Dimension() int {
	dim := C.OGR_G_GetDimension(geom.cval)
	return int(dim)
}
func (geom Geometry) CoordinateDimension() int {
	dim := C.OGR_G_GetCoordinateDimension(geom.cval)
	return int(dim)
}
func (geom Geometry) SetCoordinateDimension(dim int) {
	C.OGR_G_SetCoordinateDimension(geom.cval, C.int(dim))
}
func (geom Geometry) Clone() Geometry {
	newGeom := C.OGR_G_Clone(geom.cval)
	return Geometry{newGeom}
}
func (geom Geometry) Envelope() Envelope {
	var env Envelope
	C.OGR_G_GetEnvelope(geom.cval, &env.cval)
	return env
}
func (geom Geometry) FromWKB(wkb []uint8, bytes int) error {
	cString := unsafe.Pointer(&wkb[0])
	return C.go_ImportFromWkb(geom.cval, cString, C.int(bytes)).Err()
}
func (geom Geometry) ToWKB() ([]uint8, error) {
	b := make([]uint8, geom.WKBSize())
	cString := (*C.uchar)(unsafe.Pointer(&b[0]))
	err := C.go_ExportToWkb(geom.cval, C.OGRwkbByteOrder(C.wkbNDR), cString).Err()
	return b, err
}
func (geom Geometry) WKBSize() int {
	size := C.OGR_G_WkbSize(geom.cval)
	return int(size)
}
func (geom Geometry) FromWKT(wkt string) error {
	cString := C.CString(wkt)
	defer C.free(unsafe.Pointer(cString))
	return C.OGR_G_ImportFromWkt(geom.cval, &cString).Err()
}
func (geom Geometry) ToWKT() (string, error) {
	var p *C.char
	err := C.OGR_G_ExportToWkt(geom.cval, &p).Err()
	wkt := C.GoString(p)
	defer C.free(unsafe.Pointer(p))
	return wkt, err
}
func (geom Geometry) Type() GeometryType {
	gt := C.OGR_G_GetGeometryType(geom.cval)
	return GeometryType(gt)
}
func (geom Geometry) Name() string {
	name := C.OGR_G_GetGeometryName(geom.cval)
	return C.GoString(name)
}
func (geom Geometry) FlattenTo2D() {
	C.OGR_G_FlattenTo2D(geom.cval)
}
func (geom Geometry) CloseRings() {
	C.OGR_G_CloseRings(geom.cval)
}
func CreateFromGML(gml string) Geometry {
	cString := C.CString(gml)
	defer C.free(unsafe.Pointer(cString))
	geom := C.OGR_G_CreateFromGML(cString)
	return Geometry{geom}
}
func (geom Geometry) ToGML() string {
	val := C.OGR_G_ExportToGML(geom.cval)
	return C.GoString(val)
}
func (geom Geometry) ToGML_Ex(options []string) string {
	length := len(options)
	opts := make([]*C.char, length+1)
	for i := 0; i < length; i++ {
		opts[i] = C.CString(options[i])
		defer C.free(unsafe.Pointer(opts[i]))
	}
	opts[length] = (*C.char)(unsafe.Pointer(nil))
	val := C.OGR_G_ExportToGMLEx(geom.cval, (**C.char)(unsafe.Pointer(&opts[0])))
	return C.GoString(val)
}
func (geom Geometry) ToKML() string {
	val := C.OGR_G_ExportToKML(geom.cval, nil)
	result := C.GoString(val)
	C.free(unsafe.Pointer(val))
	return result
}
func (geom Geometry) ToJSON() string {
	val := C.OGR_G_ExportToJson(geom.cval)
	return C.GoString(val)
}
func (geom Geometry) ToJSON_ex(options []string) string {
	length := len(options)
	opts := make([]*C.char, length+1)
	for i := 0; i < length; i++ {
		opts[i] = C.CString(options[i])
		defer C.free(unsafe.Pointer(opts[i]))
	}
	opts[length] = (*C.char)(unsafe.Pointer(nil))
	val := C.OGR_G_ExportToJsonEx(geom.cval, (**C.char)(unsafe.Pointer(&opts[0])))
	return C.GoString(val)
}