func (c GeometryCollection) TransformXY(fn func(XY) XY, opts ...ConstructorOption) (GeometryCollection, error) {
	transformed := make([]Geometry, len(c.geoms))
	for i := range c.geoms {
		var err error
		transformed[i], err = c.geoms[i].TransformXY(fn, opts...)
		if err != nil {
			return GeometryCollection{}, wrapTransformed(err)
		}
	}
	return GeometryCollection{transformed, c.ctype}, nil
}
TransformXY transforms this GeometryCollection into another GeometryCollection according to fn.
package geom
import (
	"database/sql/driver"
	"encoding/json"
	"fmt"
	"unsafe"
)
type GeometryCollection struct {
	geoms []Geometry
	ctype CoordinatesType
}
func NewGeometryCollection(geoms []Geometry, opts ...ConstructorOption) GeometryCollection {
	if len(geoms) == 0 {
		return GeometryCollection{}
	}
	ctype := DimXYZM
	for _, g := range geoms {
		ctype &= g.CoordinatesType()
	}
	geoms = append([]Geometry(nil), geoms...)
	for i := range geoms {
		geoms[i] = geoms[i].ForceCoordinatesType(ctype)
	}
	return GeometryCollection{geoms, ctype}
}
func (c GeometryCollection) Type() GeometryType {
	return TypeGeometryCollection
}
func (c GeometryCollection) AsGeometry() Geometry {
	return Geometry{TypeGeometryCollection, unsafe.Pointer(&c)}
}
func (c GeometryCollection) NumGeometries() int {
	return len(c.geoms)
}
func (c GeometryCollection) NumTotalGeometries() int {
	var n int
	for _, geom := range c.geoms {
		if geom.IsGeometryCollection() {
			n += geom.AsGeometryCollection().NumTotalGeometries()
		}
	}
	return n + c.NumGeometries()
}
func (c GeometryCollection) GeometryN(n int) Geometry {
	return c.geoms[n]
}
func (c GeometryCollection) AsText() string {
	return string(c.AppendWKT(nil))
}
func (c GeometryCollection) AppendWKT(dst []byte) []byte {
	dst = appendWKTHeader(dst, "GEOMETRYCOLLECTION", c.ctype)
	if len(c.geoms) == 0 {
		return appendWKTEmpty(dst)
	}
	dst = append(dst, '(')
	for i, g := range c.geoms {
		if i > 0 {
			dst = append(dst, ',')
		}
		dst = g.AppendWKT(dst)
	}
	return append(dst, ')')
}
func (c GeometryCollection) IsEmpty() bool {
	for _, g := range c.geoms {
		if !g.IsEmpty() {
			return false
		}
	}
	return true
}
func (c GeometryCollection) Dimension() int {
	dim := 0
	for _, g := range c.geoms {
		dim = max(dim, g.Dimension())
	}
	return dim
}
func (c GeometryCollection) walk(fn func(Geometry)) {
	for _, g := range c.geoms {
		if g.IsGeometryCollection() {
			g.AsGeometryCollection().walk(fn)
		} else {
			fn(g)
		}
	}
}
func (c GeometryCollection) Envelope() Envelope {
	var env Envelope
	for _, g := range c.geoms {
		env = env.ExpandToIncludeEnvelope(g.Envelope())
	}
	return env
}
func (c GeometryCollection) Boundary() GeometryCollection {
	if c.IsEmpty() {
		return c
	}
	var bounds []Geometry
	for _, g := range c.geoms {
		bound := g.Boundary().Force2D()
		if !bound.IsEmpty() {
			bounds = append(bounds, bound)
		}
	}
	return GeometryCollection{bounds, DimXY}
}
func (c GeometryCollection) Value() (driver.Value, error) {
	return c.AsBinary(), nil
}
func (c *GeometryCollection) Scan(src interface{}) error {
	return scanAsType(src, c, TypeGeometryCollection)
}
func (c GeometryCollection) AsBinary() []byte {
	return c.AppendWKB(nil)
}
func (c GeometryCollection) AppendWKB(dst []byte) []byte {
	marsh := newWKBMarshaller(dst)
	marsh.writeByteOrder()
	marsh.writeGeomType(TypeGeometryCollection, c.ctype)
	n := c.NumGeometries()
	marsh.writeCount(n)
	for i := 0; i < n; i++ {
		g := c.GeometryN(i)
		marsh.buf = g.AppendWKB(marsh.buf)
	}
	return marsh.buf
}
func (c GeometryCollection) ConvexHull() Geometry {
	return convexHull(c.AsGeometry())
}
func (c GeometryCollection) MarshalJSON() ([]byte, error) {
	buf := []byte(`{"type":"GeometryCollection","geometries":`)
	var geoms = c.geoms
	if geoms == nil {
		geoms = []Geometry{}
	}
	geomsJSON, err := json.Marshal(geoms)
	if err != nil {
		return nil, err
	}
	buf = append(buf, geomsJSON...)
	buf = append(buf, '}')
	return buf, nil
}