-
Notifications
You must be signed in to change notification settings - Fork 5.4k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add ST_Union geospatial function #10921
Conversation
{ | ||
OGCGeometry leftGeometry = deserialize(left); | ||
OGCGeometry rightGeometry = deserialize(right); | ||
OGCGeometry ogcGeometry = leftGeometry.union(rightGeometry); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It returns null when unions GEOMETRYCOLLECTION EMPTY with GEOMETRYCOLLECTION EMPTY
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@yaoxin226 Xin, see Esri/geometry-api-java#176 and Esri/geometry-api-java#177 for limitations of the library's union
implementation. See also the implementation of ST_ConvexHull
in GeoFunctions.java
.
Until the next release of the library, let's restrict the input of ST_Union
to geometries other than geometry collection. Let's also add explicit handing of empty geometries.
if (left.isEmpty) return right;
if (right.isEmpty) return left;
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for your prompt reply.
So this function only supports POINT and LINE_STRING and POLYGON as the input of the function? Support of Multi-geometries also waits?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@yaoxin226 It supports multi-geometries, but not geometry-collection.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@yaoxin226 Xin, this is looking very nice. Thank you very much for adding lots of tests.
@@ -126,6 +126,10 @@ Operations | |||
|
|||
Returns the geometry value that represents the point set symmetric difference of two geometries. | |||
|
|||
.. function:: ST_Union(Geometry, Geometry) -> Geometry | |||
|
|||
Returns a geometry that represents the point set union of the Geometries. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
s/of the Geometries/of the input geometries
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could you mention that GEOMETRYCOLLECTION is not supported?
This function doesn't support geometry collections.
assertFunction(format("ST_ASText(ST_Union(ST_GeometryFromText('%s'), ST_GeometryFromText('%s')))", rightWkt, leftWkt), VARCHAR, expectWkt); | ||
} | ||
|
||
private void assertSTUnionInvalidFunction(String leftWkt, String rightWkt, String errorMessage) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Since all callers pass the same errorMessage
, let's remove errorMessage
argument and hard-coded the error message. Let's also rename this method to assertInvalidUnion
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hardcoded both GeometryCollection
and errorMessage
, since all callers pass the same parameters for them. Also renamed the function name to reflect that.
assertSTUnion("MULTIPOLYGON (((1 1, 3 1, 3 3, 1 3, 1 1)))", "MULTIPOLYGON (((2 2, 4 2, 4 4, 2 4, 2 2)))", "POLYGON ((1 1, 3 1, 3 2, 4 2, 4 4, 2 4, 2 3, 1 3, 1 1))"); | ||
} | ||
|
||
private void assertSTUnion(String leftWkt, String rightWkt, String expectWkt) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For clarity, let's remove ST
: assertUnion
.
private void assertSTUnion(String leftWkt, String rightWkt, String expectWkt) | ||
{ | ||
assertFunction(format("ST_ASText(ST_Union(ST_GeometryFromText('%s'), ST_GeometryFromText('%s')))", leftWkt, rightWkt), VARCHAR, expectWkt); | ||
assertFunction(format("ST_ASText(ST_Union(ST_GeometryFromText('%s'), ST_GeometryFromText('%s')))", rightWkt, leftWkt), VARCHAR, expectWkt); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for testing union(a, b)
as well as union(b, a)
.
{ | ||
// invalid type GEOMETRYCOLLECTION | ||
String invalidGeometryCollectionErrorMessage = "ST_Union only applies to POINT or MULTI_POINT or LINE_STRING or MULTI_LINE_STRING or POLYGON or MULTI_POLYGON. Input type is: GEOMETRY_COLLECTION"; | ||
assertSTUnionInvalidFunction("GEOMETRYCOLLECTION(POINT(2 3))", "POINT (1 2)", invalidGeometryCollectionErrorMessage); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
perhaps, write this as a loop over simpleWkts
@@ -331,7 +331,7 @@ public void assertInvalidFunction(String projection, StandardErrorCode errorCode | |||
catch (PrestoException e) { | |||
try { | |||
assertEquals(e.getErrorCode(), errorCode.toErrorCode()); | |||
assertTrue(e.getMessage().equals(messagePattern) || e.getMessage().matches(messagePattern)); | |||
assertTrue(e.getMessage().equals(messagePattern) || e.getMessage().matches(messagePattern), format("Exception message[%s] should either equals or matches messagePattern[%s]", e.getMessage(), messagePattern)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
To match L329, let's update to Error message [%s] doesn't match [%s]
OGCGeometry rightGeometry = deserialize(right); | ||
validateType("ST_Union", rightGeometry, EnumSet.of(POINT, MULTI_POINT, LINE_STRING, MULTI_LINE_STRING, POLYGON, MULTI_POLYGON)); | ||
|
||
if (leftGeometry.isEmpty()) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
perhaps, move this check above deserialize(right)
to avoid unnecessary deserialization
return left; | ||
} | ||
|
||
OGCGeometry ogcGeometry = leftGeometry.union(rightGeometry); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
perhaps, inline this variable
@@ -496,6 +496,31 @@ public static long stNumGeometries(@SqlType(GEOMETRY_TYPE_NAME) Slice input) | |||
return ((OGCGeometryCollection) geometry).numGeometries(); | |||
} | |||
|
|||
@SqlNullable |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this function doesn't return null
s, does it?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks @mbasmanova for the thorough review. I have addressed all the comments.
assertFunction(format("ST_ASText(ST_Union(ST_GeometryFromText('%s'), ST_GeometryFromText('%s')))", rightWkt, leftWkt), VARCHAR, expectWkt); | ||
} | ||
|
||
private void assertSTUnionInvalidFunction(String leftWkt, String rightWkt, String errorMessage) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hardcoded both GeometryCollection
and errorMessage
, since all callers pass the same parameters for them. Also renamed the function name to reflect that.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@yaoxin226 Looks great!
Please, squash commits and update commit message to remove reference to PostGIS. Geospatial functions in Presto follow SQL/MM Part 3 standard.
Add ST_Union geospatial function
ST_Union function takes two geometries and returns a new geometry that represents the point set union of the input geometries.
|
||
private void assertInvalidGeometryCollectionUnion(String validWkt) | ||
{ | ||
assertInvalidFunction(format("ST_ASText(ST_Union(ST_GeometryFromText('%s'), ST_GeometryFromText('%s')))", validWkt, "GEOMETRYCOLLECTION(POINT(2 3))"), "ST_Union only applies to POINT or MULTI_POINT or LINE_STRING or MULTI_LINE_STRING or POLYGON or MULTI_POLYGON. Input type is: GEOMETRY_COLLECTION"); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ST_Text
and placeholder for geometry collection are not necessary; let's simplify to
assertInvalidFunction(format("ST_Union(ST_GeometryFromText('%s'), ST_GeometryFromText('GEOMETRYCOLLECTION (POINT(2 3))'))", validWkt), "ST_Union only applies to POINT or MULTI_POINT or LINE_STRING or MULTI_LINE_STRING or POLYGON or MULTI_POLYGON. Input type is: GEOMETRY_COLLECTION");
Addressed all comments and squashed into one commit |
ST_Union function takes two geometries and returns a new geometry that represents the point set union of the input geometries.
@yaoxin226 Thank you, Xin. |
Thanks @mbasmanova for your prompt and thorough review! |
ST_Union function takes two geometries and returns a new geometry that represents the point set union of the input geometries.