Skip to content

Commit

Permalink
geos: update GEOS to 3.11
Browse files Browse the repository at this point in the history
All test changes are due to a change in Polygon output ordering.

Epic: None

Release note (general change): Spatial libraries from Cockroach
now rely on GEOS 3.11 instead of GEOS 3.8.
  • Loading branch information
otan committed Jul 12, 2023
1 parent d7bfdec commit cdc50cd
Show file tree
Hide file tree
Showing 15 changed files with 520 additions and 439 deletions.
17 changes: 10 additions & 7 deletions c-deps/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -122,17 +122,20 @@ cmake(
"CMAKE_C_FLAGS": "-fPIC",
"CMAKE_CXX_FLAGS": "-fPIC",
"CMAKE_SYSTEM_NAME": "Windows",
"BUILD_GEOSOP": "OFF",
},
"@io_bazel_rules_go//go/platform:darwin": {
"CMAKE_BUILD_TYPE": "Release",
"CMAKE_C_FLAGS": "-fPIC",
"CMAKE_CXX_FLAGS": "-fPIC",
"CMAKE_SYSTEM_NAME": "Darwin",
"BUILD_GEOSOP": "OFF",
},
"//conditions:default": {
"CMAKE_BUILD_TYPE": "Release",
"CMAKE_C_FLAGS": "-fPIC",
"CMAKE_CXX_FLAGS": "-fPIC",
"BUILD_GEOSOP": "OFF",
},
}),
data = select({
Expand Down Expand Up @@ -181,21 +184,21 @@ cmake(
}),
postfix_script = "mkdir -p libgeos/lib\n" + select({
"//build/toolchains:is_cross_macos": (
"cp -L lib/libgeos.3.8.1.dylib $INSTALLDIR/lib/libgeos.dylib\n" +
"cp -L lib/libgeos.3.11.2.dylib $INSTALLDIR/lib/libgeos.dylib\n" +
"PREFIX=$($OTOOL -D $INSTALLDIR/lib/libgeos_c.dylib | tail -n1 | rev | cut -d/ -f2- | rev)\n" +
"$CMAKE_INSTALL_NAME_TOOL -id @rpath/libgeos.3.8.1.dylib $INSTALLDIR/lib/libgeos.dylib\n" +
"$CMAKE_INSTALL_NAME_TOOL -id @rpath/libgeos.3.11.2.dylib $INSTALLDIR/lib/libgeos.dylib\n" +
"$CMAKE_INSTALL_NAME_TOOL -id @rpath/libgeos_c.1.dylib $INSTALLDIR/lib/libgeos_c.dylib\n" +
"$CMAKE_INSTALL_NAME_TOOL -change $PREFIX/libgeos.3.8.1.dylib @rpath/libgeos.3.8.1.dylib $INSTALLDIR/lib/libgeos_c.dylib\n"
"$CMAKE_INSTALL_NAME_TOOL -change $PREFIX/libgeos.3.11.2.dylib @rpath/libgeos.3.11.2.dylib $INSTALLDIR/lib/libgeos_c.dylib\n"
),
"@io_bazel_rules_go//go/platform:darwin": "cp -L lib/libgeos.3.8.1.dylib $INSTALLDIR/lib/libgeos.dylib",
"@io_bazel_rules_go//go/platform:darwin": "cp -L lib/libgeos.3.11.2.dylib $INSTALLDIR/lib/libgeos.dylib",
"@io_bazel_rules_go//go/platform:windows": "",
"//build/toolchains:is_cross_linux": (
"cp -L lib/libgeos.so.3.8.1 $INSTALLDIR/lib/libgeos.so\n" +
"cp -L lib/libgeos.so.3.11.2 $INSTALLDIR/lib/libgeos.so\n" +
"patchelf --set-rpath /usr/local/lib/cockroach/ $INSTALLDIR/lib/libgeos_c.so\n" +
"patchelf --set-soname libgeos.so $INSTALLDIR/lib/libgeos.so\n" +
"patchelf --replace-needed libgeos.so.3.8.1 libgeos.so $INSTALLDIR/lib/libgeos_c.so\n"
"patchelf --replace-needed libgeos.so.3.11.2 libgeos.so $INSTALLDIR/lib/libgeos_c.so\n"
),
"//conditions:default": "cp -L lib/libgeos.so.3.8.1 $INSTALLDIR/lib/libgeos.so",
"//conditions:default": "cp -L lib/libgeos.so.3.11.2 $INSTALLDIR/lib/libgeos.so",
}),
targets = ["geos_c"],
visibility = ["//visibility:public"],
Expand Down
2 changes: 1 addition & 1 deletion c-deps/geos
Submodule geos updated 1480 files
6 changes: 2 additions & 4 deletions pkg/geo/geoindex/testdata/s2_geometry
Original file line number Diff line number Diff line change
Expand Up @@ -275,8 +275,7 @@ F0/L0/, spilled

d-within distance=2 name=point1
----
[F0/L30/000000000000000000000000000000, F0/L30/033333333333333333333333333333],
F0/L0/, F0/L1/2, F0/L2/22, [F0/L30/222000000000000000000000000000, F0/L30/222333333333333333333333333333],
[F0/L30/000000000000000000000000000000, F0/L30/333333333333333333333333333333],
spilled

# Since s2GeometryIndex.{Covers,Intersects} currently have the same implementation,
Expand All @@ -289,8 +288,7 @@ F0/L0/, spilled

d-fully-within distance=2 name=point1
----
[F0/L30/000000000000000000000000000000, F0/L30/033333333333333333333333333333],
F0/L0/, F0/L1/2, F0/L2/22, [F0/L30/222000000000000000000000000000, F0/L30/222333333333333333333333333333],
[F0/L30/000000000000000000000000000000, F0/L30/333333333333333333333333333333],
spilled

# Empty shapes
Expand Down
18 changes: 18 additions & 0 deletions pkg/geo/geomfn/geomfn_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,11 @@
package geomfn

import (
"fmt"
"testing"

"github.com/cockroachdb/cockroach/pkg/geo"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"github.com/twpayne/go-geom"
)
Expand Down Expand Up @@ -134,3 +136,19 @@ func requireGeometryFromGeomT(t *testing.T, g geom.T) geo.Geometry {
require.NoError(t, err)
return ret
}

func mustConvertToEWKT(g geo.Geometry) string {
w, err := geo.SpatialObjectToEWKT(g.SpatialObject(), -1)
if err != nil {
return fmt.Sprintf("error: %s", err.Error())
}
return string(w)
}

func requireGeomEqual(t *testing.T, expected, got geo.Geometry) {
require.Equalf(t, expected, got, "expected %s, got %s", mustConvertToEWKT(expected), mustConvertToEWKT(got))
}

func assertGeomEqual(t *testing.T, expected, got geo.Geometry) {
assert.Equalf(t, expected, got, "expected %s, got %s", mustConvertToEWKT(expected), mustConvertToEWKT(got))
}
9 changes: 4 additions & 5 deletions pkg/geo/geomfn/mvtgeom_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@ import (
"testing"

"github.com/cockroachdb/cockroach/pkg/geo"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"github.com/twpayne/go-geom"
)
Expand Down Expand Up @@ -294,7 +293,7 @@ func TestAsMVTGeometry(t *testing.T) {
buffer: 0,
clipGeometry: false,
},
want: geo.MustParseGeometry("MULTIPOLYGON(((20 -20, 30 -10, 20 0, 20 -20)),((30 -10, 40 -20, 40 0, 30 -10)))"),
want: geo.MustParseGeometry("MULTIPOLYGON (((30 -10, 20 0, 20 -20, 30 -10)), ((40 -20, 40 0, 30 -10, 40 -20)))"),
},
{
name: "clipping invalid Polygon (self intersection)",
Expand All @@ -311,7 +310,7 @@ func TestAsMVTGeometry(t *testing.T) {
buffer: 0,
clipGeometry: true,
},
want: geo.MustParseGeometry("MULTIPOLYGON(((17 3, 20 0, 20 6, 17 3)), ((10 0, 14 0, 17 3, 10 10, 10 0)))"),
want: geo.MustParseGeometry("POLYGON ((17 3, 14 0, 20 0, 20 6, 20 20, 0 20, 0 0, 10 0, 10 10, 17 3))"),
},
{
name: "clipping valid MultiLinestring",
Expand Down Expand Up @@ -427,7 +426,7 @@ func TestAsMVTGeometry(t *testing.T) {
buffer: 0,
clipGeometry: false,
},
want: geo.MustParseGeometry(`POLYGON((11 10, 24 10, 20 20, 8 20, 0 20, -4 10, 12 8, 11 10))`),
want: geo.MustParseGeometry(`POLYGON ((-4 10, 12 8, 11 10, 24 10, 20 20, 8 20, 0 20, -4 10))`),
},
{
name: "snapping to grid after clipping",
Expand Down Expand Up @@ -455,7 +454,7 @@ func TestAsMVTGeometry(t *testing.T) {
return
}
require.NoError(t, err)
assert.Equal(t, tt.want, got)
assertGeomEqual(t, tt.want, got)
})
}
}
68 changes: 36 additions & 32 deletions pkg/geo/geomfn/subdivide_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -47,58 +47,58 @@ func TestSubdivide(t *testing.T) {
"Polygon, width > height",
args{geo.MustParseGeometry("POLYGON((-1 -1,-1 -0.5, -1 0, 1 0.5, 1 -1,-1 -1))"), 5},
[]geo.Geometry{
geo.MustParseGeometry("POLYGON((-1 -1,-1 0,0 0.25,0 -1,-1 -1))"),
geo.MustParseGeometry("POLYGON((0 0.25, 1 0.5, 1 -1, 0 -1, 0 0.25))"),
geo.MustParseGeometry("POLYGON ((0 -1, -1 -1, -1 -0.5, 0 -0.5, 0 -1))"),
geo.MustParseGeometry("POLYGON ((-1 0, 0 0.25, 0 -0.5, -1 -0.5, -1 0))"),
},
},
{
"invalid (bow-tie) Polygon, width > height",
args{geo.MustParseGeometry("POLYGON((0 0, -2 -1, -2 1, 0 0, 2 1, 2 -1, 0 0))"), 5},
[]geo.Geometry{
geo.MustParseGeometry("POLYGON((0 0, -2 -1, -2 1, 0 0))"),
geo.MustParseGeometry("POLYGON((0 0, 2 1, 2 -1, 0 0))"),
geo.MustParseGeometry("POLYGON ((-2 -1, -2 1, 0 0, -2 -1))"),
geo.MustParseGeometry("POLYGON ((2 1, 2 -1, 0 0, 2 1))"),
},
},
{
"invalid (bow-tie) Polygon, height > width",
args{geo.MustParseGeometry("POLYGON((0 0, -1 -2, -1 2, 0 0, 1 2, 1 -2, 0 0))"), 5},
[]geo.Geometry{
geo.MustParseGeometry("POLYGON((0 0, 1 0, 1 -2, 0 0))"),
geo.MustParseGeometry("POLYGON((0 0,-1 -2,-1 0,0 0))"),
geo.MustParseGeometry("POLYGON((-1 0,-1 2,0 0,-1 0))"),
geo.MustParseGeometry("POLYGON((0 0,1 2,1 0,0 0))"),
geo.MustParseGeometry("POLYGON ((-1 -2, -1 0, 0 0, -1 -2))"),
geo.MustParseGeometry("POLYGON ((1 -2, 0 0, 1 0, 1 -2))"),
geo.MustParseGeometry("POLYGON ((-1 2, 0 0, -1 0, -1 2))"),
geo.MustParseGeometry("POLYGON ((1 2, 1 0, 0 0, 1 2))"),
},
},
{
"Polygon, 12 decimal points precision",
args{geo.MustParseGeometry("POLYGON((-0.1 -0.1,-0.1 -0.000000000005, -0.1 0, 0.1 0.000000000005, 0.1 -0.1,-0.1 -0.1))"), 5},
[]geo.Geometry{
geo.MustParseGeometry("POLYGON((-0.1 -0.1,-0.1 0,0 0.0000000000025,0 -0.1,-0.1 -0.1))"),
geo.MustParseGeometry("POLYGON((0 0.0000000000025, 0.1 0.000000000005, 0.1 -0.1, 0 -0.1, 0 0.0000000000025))"),
geo.MustParseGeometry("POLYGON ((0 -0.1, -0.1 -0.1, -0.1 -0.000000000005, 0 -0.000000000005, 0 -0.1))"),
geo.MustParseGeometry("POLYGON ((-0.1 0, 0 0.0000000000025, 0 -0.000000000005, -0.1 -0.000000000005, -0.1 0))"),
},
},
{
"Polygon, trapezoid+rectangle",
args{geo.MustParseGeometry("POLYGON((-1 0, -1 1, 0 2, 3 2, 3 0, -1 0))"), 5},
[]geo.Geometry{
geo.MustParseGeometry("POLYGON((-1 0,-1 1,0 2,0 0,-1 0))"),
geo.MustParseGeometry("POLYGON((0 2,3 2,3 0,0 0,0 2))"),
geo.MustParseGeometry("POLYGON ((-1 1, 0 2, 0 0, -1 0, -1 1))"),
geo.MustParseGeometry("POLYGON ((3 2, 3 0, 0 0, 0 2, 3 2))"),
},
},
{
"Polygon with a hole inside",
args{geo.MustParseGeometry("POLYGON((-1 -1, -1 1, 0 2, 1 1, 1 -1, 0 -2, -1 -1),(-0.5 -0.5, -0.5 0.5, 0.5 0.5, 0.5 -0.5, 0 -0.5, -0.5 -0.5))"), 5},
[]geo.Geometry{
geo.MustParseGeometry("POLYGON((1 -1,0 -2,-1 -1,1 -1))"),
geo.MustParseGeometry("POLYGON((-1 -1,-1 -0.5,1 -0.5,1 -1,-1 -1))"),
geo.MustParseGeometry("POLYGON((-1 -0.5,-1 0.5,-0.5 0.5,-0.5 -0.5,-1 -0.5))"),
geo.MustParseGeometry("POLYGON((-1 0.5,-1 1,0.5 1,0.5 0.5,-1 0.5))"),
geo.MustParseGeometry("POLYGON((0.5 1,1 1,1 -0.5,0.5 -0.5,0.5 1))"),
geo.MustParseGeometry("POLYGON((-1 1,0 2,1 1,-1 1))"),
geo.MustParseGeometry("POLYGON ((0 -2, -1 -1, 1 -1, 0 -2))"),
geo.MustParseGeometry("POLYGON ((-1 -1, -1 0.5, -0.5 0.5, -0.5 -1, -1 -1))"),
geo.MustParseGeometry("POLYGON ((-0.5 -0.5, 1 -0.5, 1 -1, -0.5 -1, -0.5 -0.5))"),
geo.MustParseGeometry("POLYGON ((0.5 0.5, 1 0.5, 1 -0.5, 0.5 -0.5, 0.5 0.5))"),
geo.MustParseGeometry("POLYGON ((-1 0.5, -1 1, 0 2, 0 0.5, -1 0.5))"),
geo.MustParseGeometry("POLYGON ((1 1, 1 0.5, 0 0.5, 0 2, 1 1))"),
},
},
{
"LineString, width < height ",
"LineString, width < height",
args{geo.MustParseGeometry("LINESTRING(0 0, 10 15, 0 0, 10 15, 10 0, 10 15)"), 5},
[]geo.Geometry{
geo.MustParseGeometry("LINESTRING(0 0,5 7.5)"),
Expand Down Expand Up @@ -148,8 +148,8 @@ func TestSubdivide(t *testing.T) {
"GeometryCollection, types with different dimensions",
args{geo.MustParseGeometry("GEOMETRYCOLLECTION(LINESTRING(0 0, 10 10, 0 10, 10 0), POLYGON((0 0, -2 -1, -2 1, 0 0, 2 1, 2 -1, 0 0)))"), 5},
[]geo.Geometry{
geo.MustParseGeometry("POLYGON((0 0,-2 -1,-2 1,0 0))"),
geo.MustParseGeometry("POLYGON((0 0,2 1,2 -1,0 0))"),
geo.MustParseGeometry("POLYGON ((-2 -1, -2 1, 0 0, -2 -1))"),
geo.MustParseGeometry("POLYGON ((2 1, 2 -1, 0 0, 2 1))"),
},
},
{
Expand All @@ -163,18 +163,20 @@ func TestSubdivide(t *testing.T) {
"GeometryCollection, same types, one invalid",
args{geo.MustParseGeometry("GEOMETRYCOLLECTION(POLYGON((0 0, -2 -1, -2 1, 0 0, 2 1, 2 -1, 0 0)),POLYGON((-1 -1,-1 -0.5, -1 0, 1 0.5, 1 -1,-1 -1)))"), 5},
[]geo.Geometry{
geo.MustParseGeometry("POLYGON((0 0,-2 -1,-2 1,0 0))"),
geo.MustParseGeometry("POLYGON((0 0,2 1,2 -1,0 0))"),
geo.MustParseGeometry("POLYGON((-1 -1,-1 0,0 0.25,0 -1,-1 -1))"),
geo.MustParseGeometry("POLYGON((0 0.25, 1 0.5, 1 -1, 0 -1, 0 0.25))"),
geo.MustParseGeometry("POLYGON ((-2 -1, -2 1, 0 0, -2 -1))"),
geo.MustParseGeometry("POLYGON ((2 1, 2 -1, 0 0, 2 1))"),
geo.MustParseGeometry("POLYGON ((0 -1, -1 -1, -1 -0.5, 0 -0.5, 0 -1))"),
geo.MustParseGeometry("POLYGON ((-1 0, 0 0.25, 0 -0.5, -1 -0.5, -1 0))"),
},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
got, err := Subdivide(tt.args.g, tt.args.maxVertices)
require.NoError(t, err)
require.Equal(t, tt.want, got)
for i := range tt.want {
assertGeomEqual(t, tt.want[i], got[i])
}
})
}

Expand All @@ -195,7 +197,7 @@ func TestSubdivide(t *testing.T) {
const maxVertices = 5
geomTs, err := subdivideRecursive(gt, maxVertices, startDepth, dim, maxDepth)
require.NoError(t, err)
got := []geo.Geometry{}
var got []geo.Geometry
for _, cg := range geomTs {
g, err := geo.MakeGeometryFromGeomT(cg)
require.NoError(t, err)
Expand All @@ -204,11 +206,13 @@ func TestSubdivide(t *testing.T) {
got = append(got, g)
}
want := []geo.Geometry{
geo.MustParseGeometry("POLYGON((1 -1, 0 -2, -1 -1, 1 -1))"),
geo.MustParseGeometry("POLYGON((-1 -1, -1 -0.5, 1 -0.5, 1 -1, -1 -1))"),
geo.MustParseGeometry("POLYGON((-1 -0.5, -1 1, 1 1, 1 -0.5, 0.5 -0.5, 0.5 0.5, -0.5 0.5, -0.5 -0.5, -1 -0.5))"),
geo.MustParseGeometry("POLYGON((-1 1, 0 2, 1 1, -1 1))"),
geo.MustParseGeometry("POLYGON ((0 -2, -1 -1, 1 -1, 0 -2))"),
geo.MustParseGeometry("POLYGON ((-1 -1, -1 0.5, -0.5 0.5, -0.5 -1, -1 -1))"),
geo.MustParseGeometry("POLYGON ((-0.5 -1, -0.5 -0.5, 0.5 -0.5, 0.5 0.5, 1 0.5, 1 -1, -0.5 -1))"),
geo.MustParseGeometry("POLYGON ((-1 0.5, -1 1, 0 2, 0 0.5, -1 0.5))"),
}
for i := range want {
assertGeomEqual(t, want[i], got[i])
}
require.Equal(t, want, got)
})
}
30 changes: 15 additions & 15 deletions pkg/geo/geomfn/topology_operations_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -215,7 +215,7 @@ func TestSimplifyGEOS(t *testing.T) {
{
wkt: "POLYGON ((5 7, 2 5, 5 4, 13 4, 18 7, 16 11, 7 9, 11 7, 5 7), (13 8, 13 6, 14 6, 15 9, 13 8))",
tolerance: 3,
expected: "POLYGON ((5 7, 16 11, 18 7, 2 5, 5 7))",
expected: "POLYGON ((5 7, 2 5, 18 7, 16 11, 5 7))",
},
{
wkt: "POLYGON ((5 7, 2 5, 5 4, 13 4, 18 7, 16 11, 7 9, 11 7, 5 7), (13 8, 13 6, 14 6, 15 9, 13 8))",
Expand Down Expand Up @@ -244,7 +244,7 @@ func TestSimplifyGEOS(t *testing.T) {
expected, err := geo.ParseGeometry(tc.expected)
require.NoError(t, err)

require.Equal(t, expected, ret)
requireGeomEqual(t, expected, ret)
})
}
}
Expand Down Expand Up @@ -312,7 +312,7 @@ func TestIntersection(t *testing.T) {
b geo.Geometry
expected geo.Geometry
}{
{rightRect, rightRect, geo.MustParseGeometry("POLYGON ((1 0, 0 0, 0 1, 1 1, 1 0))")},
{rightRect, rightRect, geo.MustParseGeometry("POLYGON ((0 0, 0 1, 1 1, 1 0, 0 0))")},
{geo.MustParseGeometry("LINESTRING EMPTY"), geo.MustParseGeometry("POINT(5 5)"), geo.MustParseGeometry("LINESTRING EMPTY")},
{geo.MustParseGeometry("POINT(5 5)"), geo.MustParseGeometry("LINESTRING EMPTY"), geo.MustParseGeometry("LINESTRING EMPTY")},
{rightRect, rightRectPoint, rightRectPoint},
Expand All @@ -323,7 +323,7 @@ func TestIntersection(t *testing.T) {
t.Run(fmt.Sprintf("tc:%d", i), func(t *testing.T) {
g, err := Intersection(tc.a, tc.b)
require.NoError(t, err)
require.Equal(t, tc.expected, g)
requireGeomEqual(t, tc.expected, g)
})
}

Expand All @@ -339,17 +339,17 @@ func TestUnion(t *testing.T) {
b geo.Geometry
expected geo.Geometry
}{
{rightRect, rightRect, geo.MustParseGeometry("POLYGON ((1 0, 0 0, 0 1, 1 1, 1 0))")},
{rightRect, rightRectPoint, geo.MustParseGeometry("POLYGON ((0 0, 0 1, 1 1, 1 0, 0 0))")},
{rightRect, rightRect, geo.MustParseGeometry("POLYGON ((0 0, 0 1, 1 1, 1 0, 0 0))")},
{rightRect, rightRectPoint, geo.MustParseGeometry("POLYGON ((0 1, 1 1, 1 0, 0 0, 0 1))")},
{rightRectPoint, rightRectPoint, rightRectPoint},
{leftRect, rightRect, geo.MustParseGeometry("POLYGON ((0 0, -1 0, -1 1, 0 1, 1 1, 1 0, 0 0))")},
{leftRect, rightRect, geo.MustParseGeometry("POLYGON ((-1 0, -1 1, 0 1, 1 1, 1 0, 0 0, -1 0))")},
}

for i, tc := range testCases {
t.Run(fmt.Sprintf("tc:%d", i), func(t *testing.T) {
g, err := Union(tc.a, tc.b)
require.NoError(t, err)
require.Equal(t, tc.expected, g)
requireGeomEqual(t, tc.expected, g)
})
}

Expand All @@ -366,16 +366,16 @@ func TestSymDifference(t *testing.T) {
expected geo.Geometry
}{
{rightRect, rightRect, emptyRect},
{leftRect, rightRect, geo.MustParseGeometry("POLYGON((0 0, -1 0, -1 1, 0 1, 1 1, 1 0, 0 0))")},
{leftRect, overlappingRightRect, geo.MustParseGeometry("MULTIPOLYGON(((-0.1 0, -1 0, -1 1, -0.1 1, -0.1 0)), ((0 0, 0 1, 1 1, 1 0, 0 0)))")},
{rightRect, rightRectPoint, geo.MustParseGeometry("POLYGON((0 0, 0 1, 1 1, 1 0, 0 0))")},
{leftRect, rightRect, geo.MustParseGeometry("POLYGON ((-1 0, -1 1, 0 1, 1 1, 1 0, 0 0, -1 0))")},
{leftRect, overlappingRightRect, geo.MustParseGeometry("MULTIPOLYGON (((-1 0, -1 1, -0.1 1, -0.1 0, -1 0)), ((0 1, 1 1, 1 0, 0 0, 0 1)))")},
{rightRect, rightRectPoint, geo.MustParseGeometry("POLYGON ((0 1, 1 1, 1 0, 0 0, 0 1))")},
}

for i, tc := range testCases {
t.Run(fmt.Sprintf("tc:%d", i), func(t *testing.T) {
g, err := SymDifference(tc.a, tc.b)
require.NoError(t, err)
require.Equal(t, tc.expected, g)
requireGeomEqual(t, tc.expected, g)
})
}

Expand Down Expand Up @@ -465,7 +465,7 @@ func TestUnaryUnion(t *testing.T) {
{
"multipolygon to dissolve",
geo.MustParseGeometry("MULTIPOLYGON(((0 0,4 0,4 4,0 4,0 0),(1 1,2 1,2 2,1 2,1 1)), ((-1 -1,-1 -2,-2 -2,-2 -1,-1 -1)))"),
geo.MustParseGeometry("MULTIPOLYGON(((-1 -1,-1 -2,-2 -2,-2 -1,-1 -1)),((0 0,4 0,4 4,0 4,0 0),(1 1,2 1,2 2,1 2,1 1)))"),
geo.MustParseGeometry("MULTIPOLYGON (((-1 -2, -2 -2, -2 -1, -1 -1, -1 -2)), ((0 4, 4 4, 4 0, 0 0, 0 4), (2 1, 2 2, 1 2, 1 1, 2 1)))"),
},
{
"geometry collection of different types",
Expand All @@ -475,14 +475,14 @@ func TestUnaryUnion(t *testing.T) {
{
"geometry collection with duplicates",
geo.MustParseGeometry("GEOMETRYCOLLECTION(POLYGON((0 0, 1 0, 1 1, 0 1, 0 0)),POLYGON((0 0, 1 0, 1 1, 0 1, 0 0)))"),
geo.MustParseGeometry("POLYGON((1 0,0 0,0 1,1 1,1 0))"),
geo.MustParseGeometry("POLYGON ((0 0, 0 1, 1 1, 1 0, 0 0))"),
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
got, err := UnaryUnion(tt.arg)
require.NoError(t, err)
require.Equal(t, tt.want, got)
requireGeomEqual(t, tt.want, got)
})
}
}
Expand Down
Loading

0 comments on commit cdc50cd

Please sign in to comment.