Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,14 @@

## Unreleased

- Fix `reflect.DeepEqual` returning false for some pairs of geometries that
`ExactEquals` reports as equal. Some operations gave an empty geometry (or
an empty member of a geometry) an empty slice where it should have a nil
one. These included `Reverse`, `Densify`, `ForceCW`, `ForceCCW`,
`TransformXY`, `Transform` and `ForceCoordinatesType`, and parsing an empty
Z, M or ZM `GeometryCollection` from WKT or WKB. `Sequence.Slice` had the
same problem when given equal indices.

- Fix quadratic time and memory (in the nesting depth) when building nested
`GeometryCollection`s, including when parsing them from WKB, WKT, GeoJSON
and TWKB.
Expand Down
16 changes: 16 additions & 0 deletions geom/type_geometry_collection.go
Original file line number Diff line number Diff line change
Expand Up @@ -242,6 +242,10 @@ func (c *GeometryCollection) UnmarshalJSON(buf []byte) error {
// [GeometryCollection] according to fn. See [Geometry.TransformXY] for more
// details.
func (c GeometryCollection) TransformXY(fn func(XY) XY) GeometryCollection {
if len(c.geoms) == 0 {
// Use nil rather than an empty slice so that reflect.DeepEqual works correctly.
return GeometryCollection{nil, c.ctype}
}
transformed := make([]Geometry, len(c.geoms))
for i := range c.geoms {
transformed[i] = c.geoms[i].TransformXY(fn)
Expand All @@ -252,6 +256,10 @@ func (c GeometryCollection) TransformXY(fn func(XY) XY) GeometryCollection {
// Transform transforms this [GeometryCollection] into another [GeometryCollection]
// according to fn. See [Geometry.Transform] for more details.
func (c GeometryCollection) Transform(fn func(CoordinatesType, []float64) error) (GeometryCollection, error) {
if len(c.geoms) == 0 {
// Use nil rather than an empty slice so that reflect.DeepEqual works correctly.
return GeometryCollection{nil, c.ctype}, nil
}
transformed := make([]Geometry, len(c.geoms))
for i := range c.geoms {
var err error
Expand Down Expand Up @@ -427,6 +435,10 @@ func (c GeometryCollection) ForceCoordinatesType(newCType CoordinatesType) Geome
if c.ctype == newCType {
return c
}
if len(c.geoms) == 0 {
// Use nil rather than an empty slice so that reflect.DeepEqual works correctly.
return GeometryCollection{nil, newCType}
}
gs := make([]Geometry, len(c.geoms))
for i := range c.geoms {
gs[i] = c.geoms[i].ForceCoordinatesType(newCType)
Expand Down Expand Up @@ -584,6 +596,10 @@ func (c GeometryCollection) Simplify(threshold float64, nv ...NoValidate) (Geome
//
// Panics if maxDistance is zero or negative.
func (c GeometryCollection) Densify(maxDistance float64) GeometryCollection {
if len(c.geoms) == 0 {
// Use nil rather than an empty slice so that reflect.DeepEqual works correctly.
return GeometryCollection{nil, c.ctype}
}
gs := make([]Geometry, len(c.geoms))
for i, g := range c.geoms {
gs[i] = g.Densify(maxDistance)
Expand Down
Loading
Loading