From fe7b8d51e38ea691968de6a5863534978f836ad7 Mon Sep 17 00:00:00 2001 From: Erik Grinaker Date: Sat, 12 Sep 2020 15:56:22 +0200 Subject: [PATCH] builtins: implement ST_Boundary, ST_Difference, and ST_Relate with BNR Release note (sql change): Implement the geometry builtins `ST_Boundary`, `ST_Difference`, and `ST_Relate` (BNR variant). --- docs/generated/sql/functions.md | 9 + pkg/geo/geomfn/de9im.go | 9 + pkg/geo/geomfn/de9im_test.go | 34 ++ pkg/geo/geomfn/topology_operations.go | 29 ++ pkg/geo/geomfn/topology_operations_test.go | 63 +++ pkg/geo/geos/geos.cc | 81 +++ pkg/geo/geos/geos.go | 42 ++ pkg/geo/geos/geos.h | 5 + .../logictest/testdata/logic_test/geospatial | 463 ++++++++++++------ pkg/sql/sem/builtins/geo_builtins.go | 62 ++- 10 files changed, 650 insertions(+), 147 deletions(-) diff --git a/docs/generated/sql/functions.md b/docs/generated/sql/functions.md index fda6c5445730..94414c42a364 100644 --- a/docs/generated/sql/functions.md +++ b/docs/generated/sql/functions.md @@ -1377,6 +1377,9 @@ has no relationship with the commit order of concurrent transactions.

st_azimuth(geometry_a: geometry, geometry_b: geometry) → float

Returns the azimuth in radians of the segment defined by the given point geometries, or NULL if the two points are coincident.

The azimuth is angle is referenced from north, and is positive clockwise: North = 0; East = π/2; South = π; West = 3π/2.

+st_boundary(geometry: geometry) → geometry

Returns the closure of the combinatorial boundary of this Geometry.

+

This function utilizes the GEOS module.

+
st_box2dfromgeohash(geohash: string) → box2d

Return a Box2D from a GeoHash string with max precision.

st_box2dfromgeohash(geohash: string, precision: int) → box2d

Return a Box2D from a GeoHash string with supplied precision.

@@ -1549,6 +1552,9 @@ from the given Geometry.

st_dfullywithinexclusive(geometry_a: geometry, geometry_b: geometry, distance: float) → bool

Returns true if every pair of points comprising geometry_a and geometry_b are within distance units, exclusive. In other words, the ST_MaxDistance between geometry_a and geometry_b is less than distance units.

This function variant will attempt to utilize any available spatial index.

+st_difference(geometry_a: geometry, geometry_b: geometry) → geometry

Returns the difference of two Geometries.

+

This function utilizes the GEOS module.

+
st_dimension(geometry: geometry) → int

Returns the number of topological dimensions of a given Geometry.

st_disjoint(geometry_a: geometry, geometry_b: geometry) → bool

Returns true if geometry_a does not overlap, touch or is within geometry_b.

@@ -1987,6 +1993,9 @@ Negative azimuth values and values greater than 2π (360 degrees) are supported. st_relate(geometry_a: geometry, geometry_b: geometry) → string

Returns the DE-9IM spatial relation between geometry_a and geometry_b.

This function utilizes the GEOS module.

+st_relate(geometry_a: geometry, geometry_b: geometry, bnr: int) → string

Returns the DE-9IM spatial relation between geometry_a and geometry_b using the given boundary node rule (1:OGC/MOD2, 2:Endpoint, 3:MultivalentEndpoint, 4:MonovalentEndpoint).

+

This function utilizes the GEOS module.

+
st_relate(geometry_a: geometry, geometry_b: geometry, pattern: string) → bool

Returns whether the DE-9IM spatial relation between geometry_a and geometry_b matches the DE-9IM pattern.

This function utilizes the GEOS module.

diff --git a/pkg/geo/geomfn/de9im.go b/pkg/geo/geomfn/de9im.go index e3aa1d0ad094..40b4318d5e71 100644 --- a/pkg/geo/geomfn/de9im.go +++ b/pkg/geo/geomfn/de9im.go @@ -25,6 +25,15 @@ func Relate(a geo.Geometry, b geo.Geometry) (string, error) { return geos.Relate(a.EWKB(), b.EWKB()) } +// RelateBoundaryNodeRule returns the DE-9IM relation between A and B using +// the given boundary node rule (as specified by GEOS). +func RelateBoundaryNodeRule(a, b geo.Geometry, bnr int) (string, error) { + if a.SRID() != b.SRID() { + return "", geo.NewMismatchingSRIDsError(a.SpatialObject(), b.SpatialObject()) + } + return geos.RelateBoundaryNodeRule(a.EWKB(), b.EWKB(), bnr) +} + // RelatePattern returns whether the DE-9IM relation between A and B matches. func RelatePattern(a geo.Geometry, b geo.Geometry, pattern string) (bool, error) { if a.SRID() != b.SRID() { diff --git a/pkg/geo/geomfn/de9im_test.go b/pkg/geo/geomfn/de9im_test.go index 6849b900dec1..9203899a10c3 100644 --- a/pkg/geo/geomfn/de9im_test.go +++ b/pkg/geo/geomfn/de9im_test.go @@ -36,6 +36,40 @@ func TestRelate(t *testing.T) { } } +func TestRelateBoundaryNodeRule(t *testing.T) { + testCases := []struct { + a geo.Geometry + b geo.Geometry + bnr int + expected string + }{ + {leftRect, rightRect, 1, "FF2F11212"}, + {leftRect, rightRect, 2, "FF2F11212"}, + {leftRect, rightRect, 3, "1F2F002F2"}, + {leftRect, rightRect, 4, "FF2F11212"}, + } + + for i, tc := range testCases { + t.Run(fmt.Sprintf("tc:%d", i), func(t *testing.T) { + ret, err := RelateBoundaryNodeRule(tc.a, tc.b, tc.bnr) + require.NoError(t, err) + require.Equal(t, tc.expected, ret) + }) + } + + t.Run("errors on invalid BNR", func(t *testing.T) { + _, err := RelateBoundaryNodeRule(leftRect, rightRect, 0) + require.Error(t, err) + _, err = RelateBoundaryNodeRule(leftRect, rightRect, 5) + require.Error(t, err) + }) + + t.Run("errors if SRIDs mismatch", func(t *testing.T) { + _, err := RelateBoundaryNodeRule(mismatchingSRIDGeometryA, mismatchingSRIDGeometryB, 1) + requireMismatchingSRIDError(t, err) + }) +} + func TestMatchesDE9IM(t *testing.T) { testCases := []struct { str string diff --git a/pkg/geo/geomfn/topology_operations.go b/pkg/geo/geomfn/topology_operations.go index 6254da502169..b7f20ad23a61 100644 --- a/pkg/geo/geomfn/topology_operations.go +++ b/pkg/geo/geomfn/topology_operations.go @@ -15,6 +15,19 @@ import ( "github.com/cockroachdb/cockroach/pkg/geo/geos" ) +// Boundary returns the boundary of a given Geometry. +func Boundary(g geo.Geometry) (geo.Geometry, error) { + // follow PostGIS behavior + if g.Empty() { + return g, nil + } + boundaryEWKB, err := geos.Boundary(g.EWKB()) + if err != nil { + return geo.Geometry{}, err + } + return geo.ParseGeometryFromEWKB(boundaryEWKB) +} + // Centroid returns the Centroid of a given Geometry. func Centroid(g geo.Geometry) (geo.Geometry, error) { centroidEWKB, err := geos.Centroid(g.EWKB()) @@ -45,6 +58,22 @@ func ConvexHull(g geo.Geometry) (geo.Geometry, error) { return geo.ParseGeometryFromEWKB(convexHullEWKB) } +// Difference returns the difference between two given Geometries. +func Difference(a, b geo.Geometry) (geo.Geometry, error) { + // follow PostGIS behavior + if a.Empty() || b.Empty() { + return a, nil + } + if a.SRID() != b.SRID() { + return geo.Geometry{}, geo.NewMismatchingSRIDsError(a.SpatialObject(), b.SpatialObject()) + } + diffEWKB, err := geos.Difference(a.EWKB(), b.EWKB()) + if err != nil { + return geo.Geometry{}, err + } + return geo.ParseGeometryFromEWKB(diffEWKB) +} + // Simplify returns a simplified Geometry. func Simplify(g geo.Geometry, tolerance float64) (geo.Geometry, error) { simplifiedEWKB, err := geos.Simplify(g.EWKB(), tolerance) diff --git a/pkg/geo/geomfn/topology_operations_test.go b/pkg/geo/geomfn/topology_operations_test.go index 0c250ab0672e..53a4da5d1f86 100644 --- a/pkg/geo/geomfn/topology_operations_test.go +++ b/pkg/geo/geomfn/topology_operations_test.go @@ -20,6 +20,36 @@ import ( "github.com/twpayne/go-geom" ) +func TestBoundary(t *testing.T) { + testCases := []struct { + wkt string + expected string + }{ + {"POINT EMPTY", "POINT EMPTY"}, + {"POINT (1 1)", "GEOMETRYCOLLECTION EMPTY"}, + {"LINESTRING EMPTY", "LINESTRING EMPTY"}, + {"LINESTRING (100 150, 50 60, 70 80, 160 170)", "MULTIPOINT (100 150, 160 170)"}, + {"SRID=4000;LINESTRING (100 150, 50 60, 70 80, 160 170)", "SRID=4000;MULTIPOINT (100 150, 160 170)"}, + { + "POLYGON ((10 130, 50 190, 110 190, 140 150, 150 80, 100 10, 20 40, 10 130), (70 40, 100 50, 120 80, 80 110, 50 90, 70 40))", + "MULTILINESTRING ((10 130, 50 190, 110 190, 140 150, 150 80, 100 10, 20 40, 10 130), (70 40, 100 50, 120 80, 80 110, 50 90, 70 40))", + }, + } + + for _, tc := range testCases { + t.Run(tc.wkt, func(t *testing.T) { + g, err := geo.ParseGeometry(tc.wkt) + require.NoError(t, err) + ret, err := Boundary(g) + require.NoError(t, err) + + wkt, err := geo.SpatialObjectToEWKT(ret.SpatialObject(), 0) + require.NoError(t, err) + require.EqualValues(t, tc.expected, wkt) + }) + } +} + func TestCentroid(t *testing.T) { testCases := []struct { wkt string @@ -93,6 +123,39 @@ func TestConvexHull(t *testing.T) { } } +func TestDifference(t *testing.T) { + testCases := []struct { + wkt1 string + wkt2 string + expected string + }{ + {"POINT EMPTY", "LINESTRING EMPTY", "POINT EMPTY"}, + {"LINESTRING EMPTY", "POINT EMPTY", "LINESTRING EMPTY"}, + {"LINESTRING (50 100, 50 200)", "LINESTRING(50 50, 50 150)", "LINESTRING (50 150, 50 200)"}, + {"SRID=4000;LINESTRING (50 100, 50 200)", "SRID=4000;LINESTRING(50 50, 50 150)", "SRID=4000;LINESTRING (50 150, 50 200)"}, + } + + for _, tc := range testCases { + t.Run(fmt.Sprintf("%v - %v", tc.wkt2, tc.wkt1), func(t *testing.T) { + g1, err := geo.ParseGeometry(tc.wkt1) + require.NoError(t, err) + g2, err := geo.ParseGeometry(tc.wkt2) + require.NoError(t, err) + ret, err := Difference(g1, g2) + require.NoError(t, err) + + wkt, err := geo.SpatialObjectToEWKT(ret.SpatialObject(), 0) + require.NoError(t, err) + require.EqualValues(t, tc.expected, wkt) + }) + } + + t.Run("errors if SRIDs mismatch", func(t *testing.T) { + _, err := Difference(mismatchingSRIDGeometryA, mismatchingSRIDGeometryB) + requireMismatchingSRIDError(t, err) + }) +} + func TestSimplify(t *testing.T) { testCases := []struct { wkt string diff --git a/pkg/geo/geos/geos.cc b/pkg/geo/geos/geos.cc index d5918342c9a9..31d5595e11da 100644 --- a/pkg/geo/geos/geos.cc +++ b/pkg/geo/geos/geos.cc @@ -97,8 +97,11 @@ typedef int (*CR_GEOS_Length_r)(CR_GEOS_Handle, CR_GEOS_Geometry, double*); typedef int (*CR_GEOS_Normalize_r)(CR_GEOS_Handle, CR_GEOS_Geometry); typedef CR_GEOS_Geometry (*CR_GEOS_LineMerge_r)(CR_GEOS_Handle, CR_GEOS_Geometry); +typedef CR_GEOS_Geometry (*CR_GEOS_Boundary_r)(CR_GEOS_Handle, CR_GEOS_Geometry); typedef CR_GEOS_Geometry (*CR_GEOS_Centroid_r)(CR_GEOS_Handle, CR_GEOS_Geometry); typedef CR_GEOS_Geometry (*CR_GEOS_ConvexHull_r)(CR_GEOS_Handle, CR_GEOS_Geometry); +typedef CR_GEOS_Geometry (*CR_GEOS_Difference_r)(CR_GEOS_Handle, CR_GEOS_Geometry, + CR_GEOS_Geometry); typedef CR_GEOS_Geometry (*CR_GEOS_Simplify_r)(CR_GEOS_Handle, CR_GEOS_Geometry, double); typedef CR_GEOS_Geometry (*CR_GEOS_TopologyPreserveSimplify_r)(CR_GEOS_Handle, CR_GEOS_Geometry, double); @@ -125,6 +128,8 @@ typedef char (*CR_GEOS_Touches_r)(CR_GEOS_Handle, CR_GEOS_Geometry, CR_GEOS_Geom typedef char (*CR_GEOS_Within_r)(CR_GEOS_Handle, CR_GEOS_Geometry, CR_GEOS_Geometry); typedef char* (*CR_GEOS_Relate_r)(CR_GEOS_Handle, CR_GEOS_Geometry, CR_GEOS_Geometry); +typedef char* (*CR_GEOS_RelateBoundaryNodeRule_r)(CR_GEOS_Handle, CR_GEOS_Geometry, + CR_GEOS_Geometry, int); typedef char (*CR_GEOS_RelatePattern_r)(CR_GEOS_Handle, CR_GEOS_Geometry, CR_GEOS_Geometry, const char*); @@ -190,8 +195,10 @@ struct CR_GEOS { CR_GEOS_Normalize_r GEOSNormalize_r; CR_GEOS_LineMerge_r GEOSLineMerge_r; + CR_GEOS_Boundary_r GEOSBoundary_r; CR_GEOS_Centroid_r GEOSGetCentroid_r; CR_GEOS_ConvexHull_r GEOSConvexHull_r; + CR_GEOS_Difference_r GEOSDifference_r; CR_GEOS_Simplify_r GEOSSimplify_r; CR_GEOS_TopologyPreserveSimplify_r GEOSTopologyPreserveSimplify_r; CR_GEOS_Union_r GEOSUnion_r; @@ -215,6 +222,7 @@ struct CR_GEOS { CR_GEOS_Within_r GEOSWithin_r; CR_GEOS_Relate_r GEOSRelate_r; + CR_GEOS_RelateBoundaryNodeRule_r GEOSRelateBoundaryNodeRule_r; CR_GEOS_RelatePattern_r GEOSRelatePattern_r; CR_GEOS_WKBWriter_create_r GEOSWKBWriter_create_r; @@ -276,6 +284,8 @@ struct CR_GEOS { INIT(GEOSNormalize_r); INIT(GEOSLineMerge_r); INIT(GEOSisSimple_r); + INIT(GEOSBoundary_r); + INIT(GEOSDifference_r); INIT(GEOSGetCentroid_r); INIT(GEOSConvexHull_r); INIT(GEOSSimplify_r); @@ -297,6 +307,7 @@ struct CR_GEOS { INIT(GEOSTouches_r); INIT(GEOSWithin_r); INIT(GEOSRelate_r); + INIT(GEOSRelateBoundaryNodeRule_r); INIT(GEOSRelatePattern_r); INIT(GEOSSharedPaths_r); INIT(GEOSWKTReader_create_r); @@ -705,6 +716,24 @@ CR_GEOS_Status CR_GEOS_MakeValid(CR_GEOS* lib, CR_GEOS_Slice g, CR_GEOS_String* // Topology operators. // +CR_GEOS_Status CR_GEOS_Boundary(CR_GEOS* lib, CR_GEOS_Slice a, CR_GEOS_String* boundaryEWKB) { + std::string error; + auto handle = initHandleWithErrorBuffer(lib, &error); + auto geom = CR_GEOS_GeometryFromSlice(lib, handle, a); + *boundaryEWKB = {.data = NULL, .len = 0}; + if (geom != nullptr) { + auto boundaryGeom = lib->GEOSBoundary_r(handle, geom); + if (boundaryGeom != nullptr) { + auto srid = lib->GEOSGetSRID_r(handle, geom); + CR_GEOS_writeGeomToEWKB(lib, handle, boundaryGeom, boundaryEWKB, srid); + lib->GEOSGeom_destroy_r(handle, boundaryGeom); + } + lib->GEOSGeom_destroy_r(handle, geom); + } + lib->GEOS_finish_r(handle); + return toGEOSString(error.data(), error.length()); +} + CR_GEOS_Status CR_GEOS_Centroid(CR_GEOS* lib, CR_GEOS_Slice a, CR_GEOS_String* centroidEWKB) { std::string error; auto handle = initHandleWithErrorBuffer(lib, &error); @@ -741,6 +770,31 @@ CR_GEOS_Status CR_GEOS_ConvexHull(CR_GEOS* lib, CR_GEOS_Slice a, CR_GEOS_String* return toGEOSString(error.data(), error.length()); } +CR_GEOS_Status CR_GEOS_Difference(CR_GEOS* lib, CR_GEOS_Slice a, CR_GEOS_Slice b, + CR_GEOS_String* diffEWKB) { + std::string error; + auto handle = initHandleWithErrorBuffer(lib, &error); + auto geomA = CR_GEOS_GeometryFromSlice(lib, handle, a); + auto geomB = CR_GEOS_GeometryFromSlice(lib, handle, b); + *diffEWKB = {.data = NULL, .len = 0}; + if (geomA != nullptr && geomB != nullptr) { + auto diffGeom = lib->GEOSDifference_r(handle, geomA, geomB); + if (diffGeom != nullptr) { + auto srid = lib->GEOSGetSRID_r(handle, geomA); + CR_GEOS_writeGeomToEWKB(lib, handle, diffGeom, diffEWKB, srid); + lib->GEOSGeom_destroy_r(handle, diffGeom); + } + } + if (geomA != nullptr) { + lib->GEOSGeom_destroy_r(handle, geomA); + } + if (geomB != nullptr) { + lib->GEOSGeom_destroy_r(handle, geomB); + } + lib->GEOS_finish_r(handle); + return toGEOSString(error.data(), error.length()); +} + CR_GEOS_Status CR_GEOS_Simplify(CR_GEOS* lib, CR_GEOS_Slice a, CR_GEOS_String* simplifyEWKB, double tolerance) { std::string error; @@ -1017,6 +1071,33 @@ CR_GEOS_Status CR_GEOS_Relate(CR_GEOS* lib, CR_GEOS_Slice a, CR_GEOS_Slice b, CR return toGEOSString(error.data(), error.length()); } +CR_GEOS_Status CR_GEOS_RelateBoundaryNodeRule(CR_GEOS* lib, CR_GEOS_Slice a, CR_GEOS_Slice b, + int bnr, CR_GEOS_String* ret) { + std::string error; + auto handle = initHandleWithErrorBuffer(lib, &error); + + auto wkbReader = lib->GEOSWKBReader_create_r(handle); + auto geomA = lib->GEOSWKBReader_read_r(handle, wkbReader, a.data, a.len); + auto geomB = lib->GEOSWKBReader_read_r(handle, wkbReader, b.data, b.len); + lib->GEOSWKBReader_destroy_r(handle, wkbReader); + + if (geomA != nullptr && geomB != nullptr) { + auto r = lib->GEOSRelateBoundaryNodeRule_r(handle, geomA, geomB, bnr); + if (r != NULL) { + *ret = toGEOSString(r, strlen(r)); + lib->GEOSFree_r(handle, r); + } + } + if (geomA != nullptr) { + lib->GEOSGeom_destroy_r(handle, geomA); + } + if (geomB != nullptr) { + lib->GEOSGeom_destroy_r(handle, geomB); + } + lib->GEOS_finish_r(handle); + return toGEOSString(error.data(), error.length()); +} + CR_GEOS_Status CR_GEOS_RelatePattern(CR_GEOS* lib, CR_GEOS_Slice a, CR_GEOS_Slice b, CR_GEOS_Slice pattern, char* ret) { std::string error; diff --git a/pkg/geo/geos/geos.go b/pkg/geo/geos/geos.go index dc3a79412818..fff842ea63a4 100644 --- a/pkg/geo/geos/geos.go +++ b/pkg/geo/geos/geos.go @@ -326,6 +326,32 @@ func Area(ewkb geopb.EWKB) (float64, error) { return float64(area), nil } +// Boundary returns the boundary of an EWKB. +func Boundary(ewkb geopb.EWKB) (geopb.EWKB, error) { + g, err := ensureInitInternal() + if err != nil { + return nil, err + } + var cEWKB C.CR_GEOS_String + if err := statusToError(C.CR_GEOS_Boundary(g, goToCSlice(ewkb), &cEWKB)); err != nil { + return nil, err + } + return cStringToSafeGoBytes(cEWKB), nil +} + +// Difference returns the difference between two EWKB. +func Difference(ewkb1 geopb.EWKB, ewkb2 geopb.EWKB) (geopb.EWKB, error) { + g, err := ensureInitInternal() + if err != nil { + return nil, err + } + var diffEWKB C.CR_GEOS_String + if err := statusToError(C.CR_GEOS_Difference(g, goToCSlice(ewkb1), goToCSlice(ewkb2), &diffEWKB)); err != nil { + return nil, err + } + return cStringToSafeGoBytes(diffEWKB), nil +} + // Length returns the length of an EWKB. func Length(ewkb geopb.EWKB) (float64, error) { g, err := ensureInitInternal() @@ -685,6 +711,22 @@ func Relate(a geopb.EWKB, b geopb.EWKB) (string, error) { return string(cStringToSafeGoBytes(ret)), nil } +// RelateBoundaryNodeRule returns the DE-9IM relation between A and B given a boundary node rule. +func RelateBoundaryNodeRule(a geopb.EWKB, b geopb.EWKB, bnr int) (string, error) { + g, err := ensureInitInternal() + if err != nil { + return "", err + } + var ret C.CR_GEOS_String + if err := statusToError(C.CR_GEOS_RelateBoundaryNodeRule(g, goToCSlice(a), goToCSlice(b), C.int(bnr), &ret)); err != nil { + return "", err + } + if ret.data == nil { + return "", errors.Newf("expected DE-9IM string but found nothing") + } + return string(cStringToSafeGoBytes(ret)), nil +} + // RelatePattern whether A and B have a DE-9IM relation matching the given pattern. func RelatePattern(a geopb.EWKB, b geopb.EWKB, pattern string) (bool, error) { g, err := ensureInitInternal() diff --git a/pkg/geo/geos/geos.h b/pkg/geo/geos/geos.h index 80369af9ba65..d5035ddf76a2 100644 --- a/pkg/geo/geos/geos.h +++ b/pkg/geo/geos/geos.h @@ -97,8 +97,11 @@ CR_GEOS_Status CR_GEOS_IsSimple(CR_GEOS* lib, CR_GEOS_Slice a, char* ret); // Topology operators. // +CR_GEOS_Status CR_GEOS_Boundary(CR_GEOS* lib, CR_GEOS_Slice a, CR_GEOS_String* boundaryEWKB); CR_GEOS_Status CR_GEOS_Centroid(CR_GEOS* lib, CR_GEOS_Slice a, CR_GEOS_String* centroidEWKB); CR_GEOS_Status CR_GEOS_ConvexHull(CR_GEOS* lib, CR_GEOS_Slice a, CR_GEOS_String* convexHullEWKB); +CR_GEOS_Status CR_GEOS_Difference(CR_GEOS* lib, CR_GEOS_Slice a, CR_GEOS_Slice b, + CR_GEOS_String* diffEWKB); CR_GEOS_Status CR_GEOS_Simplify(CR_GEOS* lib, CR_GEOS_Slice a, CR_GEOS_String* simplifyEWKB, double tolerance); CR_GEOS_Status CR_GEOS_TopologyPreserveSimplify(CR_GEOS* lib, CR_GEOS_Slice a, @@ -146,6 +149,8 @@ CR_GEOS_Status CR_GEOS_Within(CR_GEOS* lib, CR_GEOS_Slice a, CR_GEOS_Slice b, ch // CR_GEOS_Status CR_GEOS_Relate(CR_GEOS* lib, CR_GEOS_Slice a, CR_GEOS_Slice b, CR_GEOS_String* ret); +CR_GEOS_Status CR_GEOS_RelateBoundaryNodeRule(CR_GEOS* lib, CR_GEOS_Slice a, CR_GEOS_Slice b, + int bnr, CR_GEOS_String* ret); CR_GEOS_Status CR_GEOS_RelatePattern(CR_GEOS* lib, CR_GEOS_Slice a, CR_GEOS_Slice b, CR_GEOS_Slice pattern, char* ret); diff --git a/pkg/sql/logictest/testdata/logic_test/geospatial b/pkg/sql/logictest/testdata/logic_test/geospatial index 8feeb4b63667..884489b51836 100644 --- a/pkg/sql/logictest/testdata/logic_test/geospatial +++ b/pkg/sql/logictest/testdata/logic_test/geospatial @@ -1190,6 +1190,24 @@ Square (left) POINT (-0.5 0.5) POINT (-0.5 0.5) PO Square (right) POINT (0.5 0.5) POINT (0.5 0.5) POLYGON ((0 0, 0 1, 1 1, 1 0, 0 0)) Square overlapping left and right square POINT (0.45 0.5) POINT (0.45 0.5) POLYGON ((-0.1 0, -0.1 1, 1 1, 1 0, -0.1 0)) +query TT +SELECT + a.dsc, + ST_AsEWKT(ST_Boundary(a.geom)) +FROM geom_operators_test a +WHERE NOT ST_IsCollection(a.geom) +ORDER BY a.dsc +---- +Empty LineString LINESTRING EMPTY +Empty Point POINT EMPTY +Faraway point GEOMETRYCOLLECTION EMPTY +Line going through left and right square MULTIPOINT (-0.5 0.5, 0.5 0.5) +Point middle of Left Square GEOMETRYCOLLECTION EMPTY +Point middle of Right Square GEOMETRYCOLLECTION EMPTY +Square (left) LINESTRING (-1 0, 0 0, 0 1, -1 1, -1 0) +Square (right) LINESTRING (0 0, 1 0, 1 1, 0 1, 0 0) +Square overlapping left and right square LINESTRING (-0.1 0, 1 0, 1 1, -0.1 1, -0.1 0) + query TTT SELECT a.dsc, @@ -1945,6 +1963,160 @@ Square overlapping left and right square Square (left) Square overlapping left and right square Square (right) LINESTRING (-0.1 0, 1 1) LINESTRING (0 0, 0 0) Square overlapping left and right square Square overlapping left and right square LINESTRING (-0.1 0, 1 1) LINESTRING (-0.1 0, -0.1 0) +# ST_Difference +query TTT +SELECT + a.dsc, + b.dsc, + ST_AsText(ST_Difference(a.geom, b.geom)) +FROM geom_operators_test a, geom_operators_test b +ORDER BY a.dsc, b.dsc +---- +Empty GeometryCollection Empty GeometryCollection GEOMETRYCOLLECTION EMPTY +Empty GeometryCollection Empty LineString GEOMETRYCOLLECTION EMPTY +Empty GeometryCollection Empty Point GEOMETRYCOLLECTION EMPTY +Empty GeometryCollection Faraway point GEOMETRYCOLLECTION EMPTY +Empty GeometryCollection Line going through left and right square GEOMETRYCOLLECTION EMPTY +Empty GeometryCollection NULL NULL +Empty GeometryCollection Nested Geometry Collection GEOMETRYCOLLECTION EMPTY +Empty GeometryCollection Point middle of Left Square GEOMETRYCOLLECTION EMPTY +Empty GeometryCollection Point middle of Right Square GEOMETRYCOLLECTION EMPTY +Empty GeometryCollection Square (left) GEOMETRYCOLLECTION EMPTY +Empty GeometryCollection Square (right) GEOMETRYCOLLECTION EMPTY +Empty GeometryCollection Square overlapping left and right square GEOMETRYCOLLECTION EMPTY +Empty LineString Empty GeometryCollection LINESTRING EMPTY +Empty LineString Empty LineString LINESTRING EMPTY +Empty LineString Empty Point LINESTRING EMPTY +Empty LineString Faraway point LINESTRING EMPTY +Empty LineString Line going through left and right square LINESTRING EMPTY +Empty LineString NULL NULL +Empty LineString Nested Geometry Collection LINESTRING EMPTY +Empty LineString Point middle of Left Square LINESTRING EMPTY +Empty LineString Point middle of Right Square LINESTRING EMPTY +Empty LineString Square (left) LINESTRING EMPTY +Empty LineString Square (right) LINESTRING EMPTY +Empty LineString Square overlapping left and right square LINESTRING EMPTY +Empty Point Empty GeometryCollection POINT EMPTY +Empty Point Empty LineString POINT EMPTY +Empty Point Empty Point POINT EMPTY +Empty Point Faraway point POINT EMPTY +Empty Point Line going through left and right square POINT EMPTY +Empty Point NULL NULL +Empty Point Nested Geometry Collection POINT EMPTY +Empty Point Point middle of Left Square POINT EMPTY +Empty Point Point middle of Right Square POINT EMPTY +Empty Point Square (left) POINT EMPTY +Empty Point Square (right) POINT EMPTY +Empty Point Square overlapping left and right square POINT EMPTY +Faraway point Empty GeometryCollection POINT (5 5) +Faraway point Empty LineString POINT (5 5) +Faraway point Empty Point POINT (5 5) +Faraway point Faraway point POINT EMPTY +Faraway point Line going through left and right square POINT (5 5) +Faraway point NULL NULL +Faraway point Nested Geometry Collection POINT (5 5) +Faraway point Point middle of Left Square POINT (5 5) +Faraway point Point middle of Right Square POINT (5 5) +Faraway point Square (left) POINT (5 5) +Faraway point Square (right) POINT (5 5) +Faraway point Square overlapping left and right square POINT (5 5) +Line going through left and right square Empty GeometryCollection LINESTRING (-0.5 0.5, 0.5 0.5) +Line going through left and right square Empty LineString LINESTRING (-0.5 0.5, 0.5 0.5) +Line going through left and right square Empty Point LINESTRING (-0.5 0.5, 0.5 0.5) +Line going through left and right square Faraway point LINESTRING (-0.5 0.5, 0.5 0.5) +Line going through left and right square Line going through left and right square LINESTRING EMPTY +Line going through left and right square NULL NULL +Line going through left and right square Nested Geometry Collection LINESTRING (-0.5 0.5, 0.5 0.5) +Line going through left and right square Point middle of Left Square LINESTRING (-0.5 0.5, 0.5 0.5) +Line going through left and right square Point middle of Right Square LINESTRING (-0.5 0.5, 0.5 0.5) +Line going through left and right square Square (left) LINESTRING (0 0.5, 0.5 0.5) +Line going through left and right square Square (right) LINESTRING (-0.5 0.5, 0 0.5) +Line going through left and right square Square overlapping left and right square LINESTRING (-0.5 0.5, -0.1 0.5) +NULL Empty GeometryCollection NULL +NULL Empty LineString NULL +NULL Empty Point NULL +NULL Faraway point NULL +NULL Line going through left and right square NULL +NULL NULL NULL +NULL Nested Geometry Collection NULL +NULL Point middle of Left Square NULL +NULL Point middle of Right Square NULL +NULL Square (left) NULL +NULL Square (right) NULL +NULL Square overlapping left and right square NULL +Nested Geometry Collection Empty GeometryCollection GEOMETRYCOLLECTION (GEOMETRYCOLLECTION (POINT (0 0))) +Nested Geometry Collection Empty LineString GEOMETRYCOLLECTION (GEOMETRYCOLLECTION (POINT (0 0))) +Nested Geometry Collection Empty Point GEOMETRYCOLLECTION (GEOMETRYCOLLECTION (POINT (0 0))) +Nested Geometry Collection Faraway point POINT (0 0) +Nested Geometry Collection Line going through left and right square POINT (0 0) +Nested Geometry Collection NULL NULL +Nested Geometry Collection Nested Geometry Collection POINT EMPTY +Nested Geometry Collection Point middle of Left Square POINT (0 0) +Nested Geometry Collection Point middle of Right Square POINT (0 0) +Nested Geometry Collection Square (left) POINT EMPTY +Nested Geometry Collection Square (right) POINT EMPTY +Nested Geometry Collection Square overlapping left and right square POINT EMPTY +Point middle of Left Square Empty GeometryCollection POINT (-0.5 0.5) +Point middle of Left Square Empty LineString POINT (-0.5 0.5) +Point middle of Left Square Empty Point POINT (-0.5 0.5) +Point middle of Left Square Faraway point POINT (-0.5 0.5) +Point middle of Left Square Line going through left and right square POINT EMPTY +Point middle of Left Square NULL NULL +Point middle of Left Square Nested Geometry Collection POINT (-0.5 0.5) +Point middle of Left Square Point middle of Left Square POINT EMPTY +Point middle of Left Square Point middle of Right Square POINT (-0.5 0.5) +Point middle of Left Square Square (left) POINT EMPTY +Point middle of Left Square Square (right) POINT (-0.5 0.5) +Point middle of Left Square Square overlapping left and right square POINT (-0.5 0.5) +Point middle of Right Square Empty GeometryCollection POINT (0.5 0.5) +Point middle of Right Square Empty LineString POINT (0.5 0.5) +Point middle of Right Square Empty Point POINT (0.5 0.5) +Point middle of Right Square Faraway point POINT (0.5 0.5) +Point middle of Right Square Line going through left and right square POINT EMPTY +Point middle of Right Square NULL NULL +Point middle of Right Square Nested Geometry Collection POINT (0.5 0.5) +Point middle of Right Square Point middle of Left Square POINT (0.5 0.5) +Point middle of Right Square Point middle of Right Square POINT EMPTY +Point middle of Right Square Square (left) POINT (0.5 0.5) +Point middle of Right Square Square (right) POINT EMPTY +Point middle of Right Square Square overlapping left and right square POINT EMPTY +Square (left) Empty GeometryCollection POLYGON ((-1 0, 0 0, 0 1, -1 1, -1 0)) +Square (left) Empty LineString POLYGON ((-1 0, 0 0, 0 1, -1 1, -1 0)) +Square (left) Empty Point POLYGON ((-1 0, 0 0, 0 1, -1 1, -1 0)) +Square (left) Faraway point POLYGON ((-1 0, -1 1, 0 1, 0 0, -1 0)) +Square (left) Line going through left and right square POLYGON ((0 0.5, 0 0, -1 0, -1 1, 0 1, 0 0.5)) +Square (left) NULL NULL +Square (left) Nested Geometry Collection POLYGON ((-1 0, -1 1, 0 1, 0 0, -1 0)) +Square (left) Point middle of Left Square POLYGON ((-1 0, -1 1, 0 1, 0 0, -1 0)) +Square (left) Point middle of Right Square POLYGON ((-1 0, -1 1, 0 1, 0 0, -1 0)) +Square (left) Square (left) POLYGON EMPTY +Square (left) Square (right) POLYGON ((0 0, -1 0, -1 1, 0 1, 0 0)) +Square (left) Square overlapping left and right square POLYGON ((-0.1 0, -1 0, -1 1, -0.1 1, -0.1 0)) +Square (right) Empty GeometryCollection POLYGON ((0 0, 1 0, 1 1, 0 1, 0 0)) +Square (right) Empty LineString POLYGON ((0 0, 1 0, 1 1, 0 1, 0 0)) +Square (right) Empty Point POLYGON ((0 0, 1 0, 1 1, 0 1, 0 0)) +Square (right) Faraway point POLYGON ((0 0, 0 1, 1 1, 1 0, 0 0)) +Square (right) Line going through left and right square POLYGON ((0 0.5, 0 1, 1 1, 1 0, 0 0, 0 0.5)) +Square (right) NULL NULL +Square (right) Nested Geometry Collection POLYGON ((0 0, 0 1, 1 1, 1 0, 0 0)) +Square (right) Point middle of Left Square POLYGON ((0 0, 0 1, 1 1, 1 0, 0 0)) +Square (right) Point middle of Right Square POLYGON ((0 0, 0 1, 1 1, 1 0, 0 0)) +Square (right) Square (left) POLYGON ((0 1, 1 1, 1 0, 0 0, 0 1)) +Square (right) Square (right) POLYGON EMPTY +Square (right) Square overlapping left and right square POLYGON EMPTY +Square overlapping left and right square Empty GeometryCollection POLYGON ((-0.1 0, 1 0, 1 1, -0.1 1, -0.1 0)) +Square overlapping left and right square Empty LineString POLYGON ((-0.1 0, 1 0, 1 1, -0.1 1, -0.1 0)) +Square overlapping left and right square Empty Point POLYGON ((-0.1 0, 1 0, 1 1, -0.1 1, -0.1 0)) +Square overlapping left and right square Faraway point POLYGON ((-0.1 0, -0.1 1, 1 1, 1 0, -0.1 0)) +Square overlapping left and right square Line going through left and right square POLYGON ((-0.1 0.5, -0.1 1, 1 1, 1 0, -0.1 0, -0.1 0.5)) +Square overlapping left and right square NULL NULL +Square overlapping left and right square Nested Geometry Collection POLYGON ((-0.1 0, -0.1 1, 1 1, 1 0, -0.1 0)) +Square overlapping left and right square Point middle of Left Square POLYGON ((-0.1 0, -0.1 1, 1 1, 1 0, -0.1 0)) +Square overlapping left and right square Point middle of Right Square POLYGON ((-0.1 0, -0.1 1, 1 1, 1 0, -0.1 0)) +Square overlapping left and right square Square (left) POLYGON ((0 1, 1 1, 1 0, 0 0, 0 1)) +Square overlapping left and right square Square (right) POLYGON ((0 0, -0.1 0, -0.1 1, 0 1, 0 0)) +Square overlapping left and right square Square overlapping left and right square POLYGON EMPTY + # Binary predicates query TTBBBBBBBBBBB SELECT @@ -2625,160 +2797,161 @@ FROM ( VALUES true false -query TTTB +query TTTTB SELECT a.dsc, b.dsc, ST_Relate(a.geom, b.geom), + ST_Relate(a.geom, b.geom, 3), ST_Relate(a.geom, b.geom, 'T**FF*FF*') FROM geom_operators_test a JOIN geom_operators_test b ON (1=1) ORDER BY a.dsc, b.dsc ---- -Empty GeometryCollection Empty GeometryCollection FFFFFFFF2 false -Empty GeometryCollection Empty LineString FFFFFFFF2 false -Empty GeometryCollection Empty Point FFFFFFFF2 false -Empty GeometryCollection Faraway point FFFFFF0F2 false -Empty GeometryCollection Line going through left and right square FFFFFF102 false -Empty GeometryCollection NULL NULL NULL -Empty GeometryCollection Nested Geometry Collection FFFFFF0F2 false -Empty GeometryCollection Point middle of Left Square FFFFFF0F2 false -Empty GeometryCollection Point middle of Right Square FFFFFF0F2 false -Empty GeometryCollection Square (left) FFFFFF212 false -Empty GeometryCollection Square (right) FFFFFF212 false -Empty GeometryCollection Square overlapping left and right square FFFFFF212 false -Empty LineString Empty GeometryCollection FFFFFFFF2 false -Empty LineString Empty LineString FFFFFFFF2 false -Empty LineString Empty Point FFFFFFFF2 false -Empty LineString Faraway point FFFFFF0F2 false -Empty LineString Line going through left and right square FFFFFF102 false -Empty LineString NULL NULL NULL -Empty LineString Nested Geometry Collection FFFFFF0F2 false -Empty LineString Point middle of Left Square FFFFFF0F2 false -Empty LineString Point middle of Right Square FFFFFF0F2 false -Empty LineString Square (left) FFFFFF212 false -Empty LineString Square (right) FFFFFF212 false -Empty LineString Square overlapping left and right square FFFFFF212 false -Empty Point Empty GeometryCollection FFFFFFFF2 false -Empty Point Empty LineString FFFFFFFF2 false -Empty Point Empty Point FFFFFFFF2 false -Empty Point Faraway point FFFFFF0F2 false -Empty Point Line going through left and right square FFFFFF102 false -Empty Point NULL NULL NULL -Empty Point Nested Geometry Collection FFFFFF0F2 false -Empty Point Point middle of Left Square FFFFFF0F2 false -Empty Point Point middle of Right Square FFFFFF0F2 false -Empty Point Square (left) FFFFFF212 false -Empty Point Square (right) FFFFFF212 false -Empty Point Square overlapping left and right square FFFFFF212 false -Faraway point Empty GeometryCollection FF0FFFFF2 false -Faraway point Empty LineString FF0FFFFF2 false -Faraway point Empty Point FF0FFFFF2 false -Faraway point Faraway point 0FFFFFFF2 true -Faraway point Line going through left and right square FF0FFF102 false -Faraway point NULL NULL NULL -Faraway point Nested Geometry Collection FF0FFF0F2 false -Faraway point Point middle of Left Square FF0FFF0F2 false -Faraway point Point middle of Right Square FF0FFF0F2 false -Faraway point Square (left) FF0FFF212 false -Faraway point Square (right) FF0FFF212 false -Faraway point Square overlapping left and right square FF0FFF212 false -Line going through left and right square Empty GeometryCollection FF1FF0FF2 false -Line going through left and right square Empty LineString FF1FF0FF2 false -Line going through left and right square Empty Point FF1FF0FF2 false -Line going through left and right square Faraway point FF1FF00F2 false -Line going through left and right square Line going through left and right square 1FFF0FFF2 false -Line going through left and right square NULL NULL NULL -Line going through left and right square Nested Geometry Collection FF1FF00F2 false -Line going through left and right square Point middle of Left Square FF10F0FF2 false -Line going through left and right square Point middle of Right Square FF10F0FF2 false -Line going through left and right square Square (left) 1010F0212 false -Line going through left and right square Square (right) 1010F0212 false -Line going through left and right square Square overlapping left and right square 1010F0212 false -NULL Empty GeometryCollection NULL NULL -NULL Empty LineString NULL NULL -NULL Empty Point NULL NULL -NULL Faraway point NULL NULL -NULL Line going through left and right square NULL NULL -NULL NULL NULL NULL -NULL Nested Geometry Collection NULL NULL -NULL Point middle of Left Square NULL NULL -NULL Point middle of Right Square NULL NULL -NULL Square (left) NULL NULL -NULL Square (right) NULL NULL -NULL Square overlapping left and right square NULL NULL -Nested Geometry Collection Empty GeometryCollection FF0FFFFF2 false -Nested Geometry Collection Empty LineString FF0FFFFF2 false -Nested Geometry Collection Empty Point FF0FFFFF2 false -Nested Geometry Collection Faraway point FF0FFF0F2 false -Nested Geometry Collection Line going through left and right square FF0FFF102 false -Nested Geometry Collection NULL NULL NULL -Nested Geometry Collection Nested Geometry Collection 0FFFFFFF2 true -Nested Geometry Collection Point middle of Left Square FF0FFF0F2 false -Nested Geometry Collection Point middle of Right Square FF0FFF0F2 false -Nested Geometry Collection Square (left) F0FFFF212 false -Nested Geometry Collection Square (right) F0FFFF212 false -Nested Geometry Collection Square overlapping left and right square F0FFFF212 false -Point middle of Left Square Empty GeometryCollection FF0FFFFF2 false -Point middle of Left Square Empty LineString FF0FFFFF2 false -Point middle of Left Square Empty Point FF0FFFFF2 false -Point middle of Left Square Faraway point FF0FFF0F2 false -Point middle of Left Square Line going through left and right square F0FFFF102 false -Point middle of Left Square NULL NULL NULL -Point middle of Left Square Nested Geometry Collection FF0FFF0F2 false -Point middle of Left Square Point middle of Left Square 0FFFFFFF2 true -Point middle of Left Square Point middle of Right Square FF0FFF0F2 false -Point middle of Left Square Square (left) 0FFFFF212 false -Point middle of Left Square Square (right) FF0FFF212 false -Point middle of Left Square Square overlapping left and right square FF0FFF212 false -Point middle of Right Square Empty GeometryCollection FF0FFFFF2 false -Point middle of Right Square Empty LineString FF0FFFFF2 false -Point middle of Right Square Empty Point FF0FFFFF2 false -Point middle of Right Square Faraway point FF0FFF0F2 false -Point middle of Right Square Line going through left and right square F0FFFF102 false -Point middle of Right Square NULL NULL NULL -Point middle of Right Square Nested Geometry Collection FF0FFF0F2 false -Point middle of Right Square Point middle of Left Square FF0FFF0F2 false -Point middle of Right Square Point middle of Right Square 0FFFFFFF2 true -Point middle of Right Square Square (left) FF0FFF212 false -Point middle of Right Square Square (right) 0FFFFF212 false -Point middle of Right Square Square overlapping left and right square 0FFFFF212 false -Square (left) Empty GeometryCollection FF2FF1FF2 false -Square (left) Empty LineString FF2FF1FF2 false -Square (left) Empty Point FF2FF1FF2 false -Square (left) Faraway point FF2FF10F2 false -Square (left) Line going through left and right square 1020F1102 false -Square (left) NULL NULL NULL -Square (left) Nested Geometry Collection FF20F1FF2 false -Square (left) Point middle of Left Square 0F2FF1FF2 true -Square (left) Point middle of Right Square FF2FF10F2 false -Square (left) Square (left) 2FFF1FFF2 false -Square (left) Square (right) FF2F11212 false -Square (left) Square overlapping left and right square 212111212 false -Square (right) Empty GeometryCollection FF2FF1FF2 false -Square (right) Empty LineString FF2FF1FF2 false -Square (right) Empty Point FF2FF1FF2 false -Square (right) Faraway point FF2FF10F2 false -Square (right) Line going through left and right square 1020F1102 false -Square (right) NULL NULL NULL -Square (right) Nested Geometry Collection FF20F1FF2 false -Square (right) Point middle of Left Square FF2FF10F2 false -Square (right) Point middle of Right Square 0F2FF1FF2 true -Square (right) Square (left) FF2F11212 false -Square (right) Square (right) 2FFF1FFF2 false -Square (right) Square overlapping left and right square 2FF11F212 false -Square overlapping left and right square Empty GeometryCollection FF2FF1FF2 false -Square overlapping left and right square Empty LineString FF2FF1FF2 false -Square overlapping left and right square Empty Point FF2FF1FF2 false -Square overlapping left and right square Faraway point FF2FF10F2 false -Square overlapping left and right square Line going through left and right square 1020F1102 false -Square overlapping left and right square NULL NULL NULL -Square overlapping left and right square Nested Geometry Collection FF20F1FF2 false -Square overlapping left and right square Point middle of Left Square FF2FF10F2 false -Square overlapping left and right square Point middle of Right Square 0F2FF1FF2 true -Square overlapping left and right square Square (left) 212111212 false -Square overlapping left and right square Square (right) 212F11FF2 false -Square overlapping left and right square Square overlapping left and right square 2FFF1FFF2 false +Empty GeometryCollection Empty GeometryCollection FFFFFFFF2 FFFFFFFF2 false +Empty GeometryCollection Empty LineString FFFFFFFF2 FFFFFFFF2 false +Empty GeometryCollection Empty Point FFFFFFFF2 FFFFFFFF2 false +Empty GeometryCollection Faraway point FFFFFF0F2 FFFFFF0F2 false +Empty GeometryCollection Line going through left and right square FFFFFF102 FFFFFF102 false +Empty GeometryCollection NULL NULL NULL NULL +Empty GeometryCollection Nested Geometry Collection FFFFFF0F2 FFFFFF0F2 false +Empty GeometryCollection Point middle of Left Square FFFFFF0F2 FFFFFF0F2 false +Empty GeometryCollection Point middle of Right Square FFFFFF0F2 FFFFFF0F2 false +Empty GeometryCollection Square (left) FFFFFF212 FFFFFF212 false +Empty GeometryCollection Square (right) FFFFFF212 FFFFFF212 false +Empty GeometryCollection Square overlapping left and right square FFFFFF212 FFFFFF212 false +Empty LineString Empty GeometryCollection FFFFFFFF2 FFFFFFFF2 false +Empty LineString Empty LineString FFFFFFFF2 FFFFFFFF2 false +Empty LineString Empty Point FFFFFFFF2 FFFFFFFF2 false +Empty LineString Faraway point FFFFFF0F2 FFFFFF0F2 false +Empty LineString Line going through left and right square FFFFFF102 FFFFFF102 false +Empty LineString NULL NULL NULL NULL +Empty LineString Nested Geometry Collection FFFFFF0F2 FFFFFF0F2 false +Empty LineString Point middle of Left Square FFFFFF0F2 FFFFFF0F2 false +Empty LineString Point middle of Right Square FFFFFF0F2 FFFFFF0F2 false +Empty LineString Square (left) FFFFFF212 FFFFFF212 false +Empty LineString Square (right) FFFFFF212 FFFFFF212 false +Empty LineString Square overlapping left and right square FFFFFF212 FFFFFF212 false +Empty Point Empty GeometryCollection FFFFFFFF2 FFFFFFFF2 false +Empty Point Empty LineString FFFFFFFF2 FFFFFFFF2 false +Empty Point Empty Point FFFFFFFF2 FFFFFFFF2 false +Empty Point Faraway point FFFFFF0F2 FFFFFF0F2 false +Empty Point Line going through left and right square FFFFFF102 FFFFFF102 false +Empty Point NULL NULL NULL NULL +Empty Point Nested Geometry Collection FFFFFF0F2 FFFFFF0F2 false +Empty Point Point middle of Left Square FFFFFF0F2 FFFFFF0F2 false +Empty Point Point middle of Right Square FFFFFF0F2 FFFFFF0F2 false +Empty Point Square (left) FFFFFF212 FFFFFF212 false +Empty Point Square (right) FFFFFF212 FFFFFF212 false +Empty Point Square overlapping left and right square FFFFFF212 FFFFFF212 false +Faraway point Empty GeometryCollection FF0FFFFF2 FF0FFFFF2 false +Faraway point Empty LineString FF0FFFFF2 FF0FFFFF2 false +Faraway point Empty Point FF0FFFFF2 FF0FFFFF2 false +Faraway point Faraway point 0FFFFFFF2 0FFFFFFF2 true +Faraway point Line going through left and right square FF0FFF102 FF0FFF102 false +Faraway point NULL NULL NULL NULL +Faraway point Nested Geometry Collection FF0FFF0F2 FF0FFF0F2 false +Faraway point Point middle of Left Square FF0FFF0F2 FF0FFF0F2 false +Faraway point Point middle of Right Square FF0FFF0F2 FF0FFF0F2 false +Faraway point Square (left) FF0FFF212 FF0FFF212 false +Faraway point Square (right) FF0FFF212 FF0FFF212 false +Faraway point Square overlapping left and right square FF0FFF212 FF0FFF212 false +Line going through left and right square Empty GeometryCollection FF1FF0FF2 FF1FF0FF2 false +Line going through left and right square Empty LineString FF1FF0FF2 FF1FF0FF2 false +Line going through left and right square Empty Point FF1FF0FF2 FF1FF0FF2 false +Line going through left and right square Faraway point FF1FF00F2 FF1FF00F2 false +Line going through left and right square Line going through left and right square 1FFF0FFF2 1FFFFFFF2 false +Line going through left and right square NULL NULL NULL NULL +Line going through left and right square Nested Geometry Collection FF1FF00F2 FF1FF00F2 false +Line going through left and right square Point middle of Left Square FF10F0FF2 0F1FFFFF2 false +Line going through left and right square Point middle of Right Square FF10F0FF2 0F1FFFFF2 false +Line going through left and right square Square (left) 1010F0212 101FFF202 false +Line going through left and right square Square (right) 1010F0212 101FFF202 false +Line going through left and right square Square overlapping left and right square 1010F0212 101FFF202 false +NULL Empty GeometryCollection NULL NULL NULL +NULL Empty LineString NULL NULL NULL +NULL Empty Point NULL NULL NULL +NULL Faraway point NULL NULL NULL +NULL Line going through left and right square NULL NULL NULL +NULL NULL NULL NULL NULL +NULL Nested Geometry Collection NULL NULL NULL +NULL Point middle of Left Square NULL NULL NULL +NULL Point middle of Right Square NULL NULL NULL +NULL Square (left) NULL NULL NULL +NULL Square (right) NULL NULL NULL +NULL Square overlapping left and right square NULL NULL NULL +Nested Geometry Collection Empty GeometryCollection FF0FFFFF2 FF0FFFFF2 false +Nested Geometry Collection Empty LineString FF0FFFFF2 FF0FFFFF2 false +Nested Geometry Collection Empty Point FF0FFFFF2 FF0FFFFF2 false +Nested Geometry Collection Faraway point FF0FFF0F2 FF0FFF0F2 false +Nested Geometry Collection Line going through left and right square FF0FFF102 FF0FFF102 false +Nested Geometry Collection NULL NULL NULL NULL +Nested Geometry Collection Nested Geometry Collection 0FFFFFFF2 0FFFFFFF2 true +Nested Geometry Collection Point middle of Left Square FF0FFF0F2 FF0FFF0F2 false +Nested Geometry Collection Point middle of Right Square FF0FFF0F2 FF0FFF0F2 false +Nested Geometry Collection Square (left) F0FFFF212 F0FFFF212 false +Nested Geometry Collection Square (right) F0FFFF212 F0FFFF212 false +Nested Geometry Collection Square overlapping left and right square F0FFFF212 F0FFFF212 false +Point middle of Left Square Empty GeometryCollection FF0FFFFF2 FF0FFFFF2 false +Point middle of Left Square Empty LineString FF0FFFFF2 FF0FFFFF2 false +Point middle of Left Square Empty Point FF0FFFFF2 FF0FFFFF2 false +Point middle of Left Square Faraway point FF0FFF0F2 FF0FFF0F2 false +Point middle of Left Square Line going through left and right square F0FFFF102 0FFFFF1F2 false +Point middle of Left Square NULL NULL NULL NULL +Point middle of Left Square Nested Geometry Collection FF0FFF0F2 FF0FFF0F2 false +Point middle of Left Square Point middle of Left Square 0FFFFFFF2 0FFFFFFF2 true +Point middle of Left Square Point middle of Right Square FF0FFF0F2 FF0FFF0F2 false +Point middle of Left Square Square (left) 0FFFFF212 0FFFFF212 false +Point middle of Left Square Square (right) FF0FFF212 FF0FFF212 false +Point middle of Left Square Square overlapping left and right square FF0FFF212 FF0FFF212 false +Point middle of Right Square Empty GeometryCollection FF0FFFFF2 FF0FFFFF2 false +Point middle of Right Square Empty LineString FF0FFFFF2 FF0FFFFF2 false +Point middle of Right Square Empty Point FF0FFFFF2 FF0FFFFF2 false +Point middle of Right Square Faraway point FF0FFF0F2 FF0FFF0F2 false +Point middle of Right Square Line going through left and right square F0FFFF102 0FFFFF1F2 false +Point middle of Right Square NULL NULL NULL NULL +Point middle of Right Square Nested Geometry Collection FF0FFF0F2 FF0FFF0F2 false +Point middle of Right Square Point middle of Left Square FF0FFF0F2 FF0FFF0F2 false +Point middle of Right Square Point middle of Right Square 0FFFFFFF2 0FFFFFFF2 true +Point middle of Right Square Square (left) FF0FFF212 FF0FFF212 false +Point middle of Right Square Square (right) 0FFFFF212 0FFFFF212 false +Point middle of Right Square Square overlapping left and right square 0FFFFF212 0FFFFF212 false +Square (left) Empty GeometryCollection FF2FF1FF2 FF2FF1FF2 false +Square (left) Empty LineString FF2FF1FF2 FF2FF1FF2 false +Square (left) Empty Point FF2FF1FF2 FF2FF1FF2 false +Square (left) Faraway point FF2FF10F2 FF2FF10F2 false +Square (left) Line going through left and right square 1020F1102 1F20F01F2 false +Square (left) NULL NULL NULL NULL +Square (left) Nested Geometry Collection FF20F1FF2 FF20F1FF2 false +Square (left) Point middle of Left Square 0F2FF1FF2 0F2FF1FF2 true +Square (left) Point middle of Right Square FF2FF10F2 FF2FF10F2 false +Square (left) Square (left) 2FFF1FFF2 2FFF0FFF2 false +Square (left) Square (right) FF2F11212 1F2F002F2 false +Square (left) Square overlapping left and right square 212111212 2F2F002F2 false +Square (right) Empty GeometryCollection FF2FF1FF2 FF2FF1FF2 false +Square (right) Empty LineString FF2FF1FF2 FF2FF1FF2 false +Square (right) Empty Point FF2FF1FF2 FF2FF1FF2 false +Square (right) Faraway point FF2FF10F2 FF2FF10F2 false +Square (right) Line going through left and right square 1020F1102 1F20F01F2 false +Square (right) NULL NULL NULL NULL +Square (right) Nested Geometry Collection FF20F1FF2 FF20F1FF2 false +Square (right) Point middle of Left Square FF2FF10F2 FF2FF10F2 false +Square (right) Point middle of Right Square 0F2FF1FF2 0F2FF1FF2 true +Square (right) Square (left) FF2F11212 1F2F0F202 false +Square (right) Square (right) 2FFF1FFF2 2FFF0FFF2 false +Square (right) Square overlapping left and right square 2FF11F212 2FFF0F202 false +Square overlapping left and right square Empty GeometryCollection FF2FF1FF2 FF2FF1FF2 false +Square overlapping left and right square Empty LineString FF2FF1FF2 FF2FF1FF2 false +Square overlapping left and right square Empty Point FF2FF1FF2 FF2FF1FF2 false +Square overlapping left and right square Faraway point FF2FF10F2 FF2FF10F2 false +Square overlapping left and right square Line going through left and right square 1020F1102 1F20F01F2 false +Square overlapping left and right square NULL NULL NULL NULL +Square overlapping left and right square Nested Geometry Collection FF20F1FF2 FF20F1FF2 false +Square overlapping left and right square Point middle of Left Square FF2FF10F2 FF2FF10F2 false +Square overlapping left and right square Point middle of Right Square 0F2FF1FF2 0F2FF1FF2 true +Square overlapping left and right square Square (left) 212111212 2F2F0F202 false +Square overlapping left and right square Square (right) 212F11FF2 2F2F00FF2 false +Square overlapping left and right square Square overlapping left and right square 2FFF1FFF2 2FFF0FFF2 false # ST_Envelope query TT diff --git a/pkg/sql/sem/builtins/geo_builtins.go b/pkg/sql/sem/builtins/geo_builtins.go index 4cca86775c30..9c2afc0ee36b 100644 --- a/pkg/sql/sem/builtins/geo_builtins.go +++ b/pkg/sql/sem/builtins/geo_builtins.go @@ -3001,6 +3001,30 @@ Note if geometries are the same, it will return the LineString with the minimum }.String(), Volatility: tree.VolatilityImmutable, }, + tree.Overload{ + Types: tree.ArgTypes{ + {"geometry_a", types.Geometry}, + {"geometry_b", types.Geometry}, + {"bnr", types.Int}, + }, + ReturnType: tree.FixedReturnType(types.String), + Fn: func(ctx *tree.EvalContext, args tree.Datums) (tree.Datum, error) { + a := tree.MustBeDGeometry(args[0]) + b := tree.MustBeDGeometry(args[1]) + bnr := tree.MustBeDInt(args[2]) + ret, err := geomfn.RelateBoundaryNodeRule(a.Geometry, b.Geometry, int(bnr)) + if err != nil { + return nil, err + } + return tree.NewDString(ret), nil + }, + Info: infoBuilder{ + info: `Returns the DE-9IM spatial relation between geometry_a and geometry_b using the given ` + + `boundary node rule (1:OGC/MOD2, 2:Endpoint, 3:MultivalentEndpoint, 4:MonovalentEndpoint).`, + libraryUsage: usesGEOS, + }.String(), + Volatility: tree.VolatilityImmutable, + }, ), "st_relatematch": makeBuiltin( defProps(), @@ -3143,6 +3167,24 @@ For flags=1, validity considers self-intersecting rings forming holes as valid a // Topology operations // + "st_boundary": makeBuiltin( + defProps(), + geometryOverload1( + func(ctx *tree.EvalContext, g *tree.DGeometry) (tree.Datum, error) { + centroid, err := geomfn.Boundary(g.Geometry) + if err != nil { + return nil, err + } + return tree.NewDGeometry(centroid), err + }, + types.Geometry, + infoBuilder{ + info: "Returns the closure of the combinatorial boundary of this Geometry.", + libraryUsage: usesGEOS, + }, + tree.VolatilityImmutable, + ), + ), "st_centroid": makeBuiltin( defProps(), append( @@ -3215,6 +3257,24 @@ For flags=1, validity considers self-intersecting rings forming holes as valid a tree.VolatilityImmutable, ), ), + "st_difference": makeBuiltin( + defProps(), + geometryOverload2( + func(ctx *tree.EvalContext, a, b *tree.DGeometry) (tree.Datum, error) { + diff, err := geomfn.Difference(a.Geometry, b.Geometry) + if err != nil { + return nil, err + } + return tree.NewDGeometry(diff), err + }, + types.Geometry, + infoBuilder{ + info: "Returns the difference of two Geometries.", + libraryUsage: usesGEOS, + }, + tree.VolatilityImmutable, + ), + ), "st_pointonsurface": makeBuiltin( defProps(), geometryOverload1( @@ -4826,7 +4886,6 @@ The swap_ordinate_string parameter is a 2-character string naming the ordinates "st_aslatlontext": makeBuiltin(tree.FunctionProperties{UnsupportedWithIssue: 48882}), "st_assvg": makeBuiltin(tree.FunctionProperties{UnsupportedWithIssue: 48883}), "st_astwkb": makeBuiltin(tree.FunctionProperties{UnsupportedWithIssue: 48886}), - "st_boundary": makeBuiltin(tree.FunctionProperties{UnsupportedWithIssue: 48888}), "st_boundingdiagonal": makeBuiltin(tree.FunctionProperties{UnsupportedWithIssue: 48889}), "st_buildarea": makeBuiltin(tree.FunctionProperties{UnsupportedWithIssue: 48892}), "st_chaikinsmoothing": makeBuiltin(tree.FunctionProperties{UnsupportedWithIssue: 48894}), @@ -4838,7 +4897,6 @@ The swap_ordinate_string parameter is a 2-character string naming the ordinates "st_clusterwithin": makeBuiltin(tree.FunctionProperties{UnsupportedWithIssue: 48901}), "st_concavehull": makeBuiltin(tree.FunctionProperties{UnsupportedWithIssue: 48906}), "st_delaunaytriangles": makeBuiltin(tree.FunctionProperties{UnsupportedWithIssue: 48915}), - "st_difference": makeBuiltin(tree.FunctionProperties{UnsupportedWithIssue: 48917}), "st_dump": makeBuiltin(tree.FunctionProperties{UnsupportedWithIssue: 49785}), "st_dumppoints": makeBuiltin(tree.FunctionProperties{UnsupportedWithIssue: 49786}), "st_dumprings": makeBuiltin(tree.FunctionProperties{UnsupportedWithIssue: 49787}),