func (geom Geometry) Distance3D(other Geometry) float64 {
	dist := C.OGR_G_Distance3D(geom.cval, other.cval)
	return float64(dist)
}
Compute 3D distance between thie geometry and the other.
This method is built on the SFCGAL library,
check it for the definition of the geometry operation.
If OGR is built without the SFCGAL library, this method will always return -1.0
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)
}
func (geom Geometry) SpatialReference() SpatialReference {
	spatialRef := C.OGR_G_GetSpatialReference(geom.cval)
	return SpatialReference{spatialRef}
}
func (geom Geometry) SetSpatialReference(spatialRef SpatialReference) {
	C.OGR_G_AssignSpatialReference(geom.cval, spatialRef.cval)
}
func (geom Geometry) Transform(ct CoordinateTransform) error {
	return C.OGR_G_Transform(geom.cval, ct.cval).Err()
}
func (geom Geometry) TransformTo(sr SpatialReference) error {
	return C.OGR_G_TransformTo(geom.cval, sr.cval).Err()
}
func (geom Geometry) Simplify(tolerance float64) Geometry {
	newGeom := C.OGR_G_Simplify(geom.cval, C.double(tolerance))
	return Geometry{newGeom}
}
func (geom Geometry) SimplifyPreservingTopology(tolerance float64) Geometry {
	newGeom := C.OGR_G_SimplifyPreserveTopology(geom.cval, C.double(tolerance))
	return Geometry{newGeom}
}
func (geom Geometry) Segmentize(distance float64) {
	C.OGR_G_Segmentize(geom.cval, C.double(distance))
}
func (geom Geometry) Intersects(other Geometry) bool {
	val := C.OGR_G_Intersects(geom.cval, other.cval)
	return val != 0
}
func (geom Geometry) Equals(other Geometry) bool {
	val := C.OGR_G_Equals(geom.cval, other.cval)
	return val != 0
}
func (geom Geometry) Disjoint(other Geometry) bool {
	val := C.OGR_G_Disjoint(geom.cval, other.cval)
	return val != 0
}
func (geom Geometry) Touches(other Geometry) bool {
	val := C.OGR_G_Touches(geom.cval, other.cval)
	return val != 0
}
func (geom Geometry) Crosses(other Geometry) bool {
	val := C.OGR_G_Crosses(geom.cval, other.cval)
	return val != 0
}
func (geom Geometry) Within(other Geometry) bool {
	val := C.OGR_G_Within(geom.cval, other.cval)
	return val != 0
}
func (geom Geometry) Contains(other Geometry) bool {
	val := C.OGR_G_Contains(geom.cval, other.cval)
	return val != 0
}
func (geom Geometry) Overlaps(other Geometry) bool {
	val := C.OGR_G_Overlaps(geom.cval, other.cval)
	return val != 0
}
func (geom Geometry) Boundary() Geometry {
	newGeom := C.OGR_G_Boundary(geom.cval)
	return Geometry{newGeom}
}
func (geom Geometry) ConvexHull() Geometry {
	newGeom := C.OGR_G_ConvexHull(geom.cval)
	return Geometry{newGeom}
}
func (geom Geometry) Buffer(distance float64, segments int) Geometry {
	newGeom := C.OGR_G_Buffer(geom.cval, C.double(distance), C.int(segments))
	return Geometry{newGeom}
}
func (geom Geometry) Intersection(other Geometry) Geometry {
	newGeom := C.OGR_G_Intersection(geom.cval, other.cval)
	return Geometry{newGeom}
}
func (geom Geometry) Union(other Geometry) Geometry {
	newGeom := C.OGR_G_Union(geom.cval, other.cval)
	return Geometry{newGeom}
}
func (geom Geometry) UnionCascaded() Geometry {
	newGeom := C.OGR_G_UnionCascaded(geom.cval)
	return Geometry{newGeom}
}
func (geom Geometry) Difference(other Geometry) Geometry {
	newGeom := C.OGR_G_Difference(geom.cval, other.cval)
	return Geometry{newGeom}
}
func (geom Geometry) SymmetricDifference(other Geometry) Geometry {
	newGeom := C.OGR_G_SymDifference(geom.cval, other.cval)
	return Geometry{newGeom}
}
func (geom Geometry) Distance(other Geometry) float64 {
	dist := C.OGR_G_Distance(geom.cval, other.cval)
	return float64(dist)
}