Skip to content
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

Merged
merged 1 commit into from
Jun 28, 2018
Merged

Conversation

yaoxin226
Copy link
Contributor

@yaoxin226 yaoxin226 commented Jun 26, 2018

ST_Union function takes two geometries and returns a new geometry that represents the point set union of the input geometries.

{
OGCGeometry leftGeometry = deserialize(left);
OGCGeometry rightGeometry = deserialize(right);
OGCGeometry ogcGeometry = leftGeometry.union(rightGeometry);
Copy link
Contributor Author

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

Copy link
Contributor

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;

Copy link
Contributor Author

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?

Copy link
Contributor

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.

Copy link
Contributor

@mbasmanova mbasmanova left a 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.
Copy link
Contributor

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

Copy link
Contributor

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)
Copy link
Contributor

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.

Copy link
Contributor Author

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)
Copy link
Contributor

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);
Copy link
Contributor

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);
Copy link
Contributor

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));
Copy link
Contributor

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()) {
Copy link
Contributor

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);
Copy link
Contributor

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
Copy link
Contributor

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 nulls, does it?

Copy link
Contributor Author

@yaoxin226 yaoxin226 left a 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)
Copy link
Contributor Author

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.

Copy link
Contributor

@mbasmanova mbasmanova left a 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");
Copy link
Contributor

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");

@yaoxin226
Copy link
Contributor Author

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.
@mbasmanova mbasmanova changed the title Add geometry function ST_Union Add ST_Union geospatial function Jun 28, 2018
@mbasmanova mbasmanova merged commit f5f2a3b into prestodb:master Jun 28, 2018
@mbasmanova
Copy link
Contributor

@yaoxin226 Thank you, Xin.

@yaoxin226
Copy link
Contributor Author

Thanks @mbasmanova for your prompt and thorough review!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants