Skip to content

Commit 3595d3b

Browse files
jagillfacebook-github-bot
authored andcommitted
feat: Geometry overlay operations (facebookincubator#13332)
Summary: Pull Request resolved: facebookincubator#13332 This implements the four core overlay operations: Union, Intersection, Difference, and Symmetric Difference. For Union, this only implements the binary operation, leaving `geometry_union(array<geometry>)` for a later PR. Reviewed By: bikramSingh91 Differential Revision: D74671626 fbshipit-source-id: cb26bbaf05a9756adc94278ed2fcb7681b638c5c
1 parent 7029e54 commit 3595d3b

File tree

5 files changed

+433
-0
lines changed

5 files changed

+433
-0
lines changed

velox/docs/functions/presto/geospatial.rst

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,31 @@ function you are using.
126126

127127
.. _DE-9IM: https://en.wikipedia.org/wiki/DE-9IM
128128

129+
Spatial Operations
130+
------------------
131+
132+
.. function:: ST_Difference(geometry1: Geometry, geometry2: Geometry) -> difference: Geometry
133+
134+
Returns the geometry that represents the portion of ``geometry1`` that is
135+
not contained in ``geometry2``.
136+
137+
.. function:: ST_Intersection(geometry1: Geometry, geometry2: Geometry) -> intersection: Geometry
138+
139+
Returns the geometry that represents the portion of ``geometry1`` that is
140+
also contained in ``geometry2``.
141+
142+
.. function:: ST_SymDifference(geometry1: Geometry, geometry2: Geometry) -> symdifference: Geometry
143+
144+
Returns the geometry that represents the portion of ``geometry1`` that is
145+
not contained in ``geometry2`` as well as the portion of ``geometry1`` that
146+
is not congtained in ``geometry1``.
147+
148+
.. function:: ST_Union(geometry1: Geometry, geometry2: Geometry) -> intersection: Geometry
149+
150+
Returns the geometry that represents the all points in either ``geometry1``
151+
or ``geometry2``.
152+
153+
129154
Bing Tile Functions
130155
-------------------
131156

velox/expression/fuzzer/ExpressionFuzzerTest.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -142,6 +142,10 @@ int main(int argc, char** argv) {
142142
"st_overlaps",
143143
"st_touches",
144144
"st_within",
145+
"st_difference",
146+
"st_intersection",
147+
"st_symdifference",
148+
"st_union",
145149
};
146150
size_t initialSeed = FLAGS_seed == 0 ? std::time(nullptr) : FLAGS_seed;
147151

velox/functions/prestosql/GeometryFunctions.h

Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -291,4 +291,104 @@ struct StWithinFunction {
291291
}
292292
};
293293

294+
// Overlay operations
295+
296+
template <typename T>
297+
struct StDifferenceFunction {
298+
VELOX_DEFINE_FUNCTION_TYPES(T);
299+
300+
FOLLY_ALWAYS_INLINE Status call(
301+
out_type<Geometry>& result,
302+
const arg_type<Geometry>& leftGeometry,
303+
const arg_type<Geometry>& rightGeometry) {
304+
// TODO: When #12771 is merged, check envelopes and short-circuit
305+
// if envelopes are disjoint
306+
std::unique_ptr<geos::geom::Geometry> leftGeosGeometry =
307+
geospatial::deserializeGeometry(leftGeometry);
308+
std::unique_ptr<geos::geom::Geometry> rightGeosGeometry =
309+
geospatial::deserializeGeometry(rightGeometry);
310+
311+
std::unique_ptr<geos::geom::Geometry> outputGeometry;
312+
GEOS_TRY(outputGeometry = leftGeosGeometry->difference(&*rightGeosGeometry);
313+
, "Failed to compute geometry difference");
314+
315+
result = geospatial::serializeGeometry(*outputGeometry);
316+
return Status::OK();
317+
}
318+
};
319+
320+
template <typename T>
321+
struct StIntersectionFunction {
322+
VELOX_DEFINE_FUNCTION_TYPES(T);
323+
324+
FOLLY_ALWAYS_INLINE Status call(
325+
out_type<Geometry>& result,
326+
const arg_type<Geometry>& leftGeometry,
327+
const arg_type<Geometry>& rightGeometry) {
328+
// TODO: When #12771 is merged, check envelopes and short-circuit
329+
// if envelopes are disjoint
330+
std::unique_ptr<geos::geom::Geometry> leftGeosGeometry =
331+
geospatial::deserializeGeometry(leftGeometry);
332+
std::unique_ptr<geos::geom::Geometry> rightGeosGeometry =
333+
geospatial::deserializeGeometry(rightGeometry);
334+
335+
std::unique_ptr<geos::geom::Geometry> outputGeometry;
336+
GEOS_TRY(
337+
outputGeometry = leftGeosGeometry->intersection(&*rightGeosGeometry);
338+
, "Failed to compute geometry intersection");
339+
340+
result = geospatial::serializeGeometry(*outputGeometry);
341+
return Status::OK();
342+
}
343+
};
344+
345+
template <typename T>
346+
struct StSymDifferenceFunction {
347+
VELOX_DEFINE_FUNCTION_TYPES(T);
348+
349+
FOLLY_ALWAYS_INLINE Status call(
350+
out_type<Geometry>& result,
351+
const arg_type<Geometry>& leftGeometry,
352+
const arg_type<Geometry>& rightGeometry) {
353+
// TODO: When #12771 is merged, check envelopes and short-circuit
354+
// if envelopes are disjoint
355+
std::unique_ptr<geos::geom::Geometry> leftGeosGeometry =
356+
geospatial::deserializeGeometry(leftGeometry);
357+
std::unique_ptr<geos::geom::Geometry> rightGeosGeometry =
358+
geospatial::deserializeGeometry(rightGeometry);
359+
360+
std::unique_ptr<geos::geom::Geometry> outputGeometry;
361+
GEOS_TRY(
362+
outputGeometry = leftGeosGeometry->symDifference(&*rightGeosGeometry);
363+
, "Failed to compute geometry symdifference");
364+
365+
result = geospatial::serializeGeometry(*outputGeometry);
366+
return Status::OK();
367+
}
368+
};
369+
370+
template <typename T>
371+
struct StUnionFunction {
372+
VELOX_DEFINE_FUNCTION_TYPES(T);
373+
374+
FOLLY_ALWAYS_INLINE Status call(
375+
out_type<Geometry>& result,
376+
const arg_type<Geometry>& leftGeometry,
377+
const arg_type<Geometry>& rightGeometry) {
378+
// TODO: When #12771 is merged, check envelopes and short-circuit if
379+
// one/both are empty
380+
std::unique_ptr<geos::geom::Geometry> leftGeosGeometry =
381+
geospatial::deserializeGeometry(leftGeometry);
382+
std::unique_ptr<geos::geom::Geometry> rightGeosGeometry =
383+
geospatial::deserializeGeometry(rightGeometry);
384+
385+
std::unique_ptr<geos::geom::Geometry> outputGeometry;
386+
GEOS_TRY(outputGeometry = leftGeosGeometry->Union(&*rightGeosGeometry);
387+
, "Failed to compute geometry union");
388+
389+
result = geospatial::serializeGeometry(*outputGeometry);
390+
return Status::OK();
391+
}
392+
};
393+
294394
} // namespace facebook::velox::functions

velox/functions/prestosql/registration/GeometryFunctionsRegistration.cpp

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,17 @@ void registerRelationPredicates(const std::string& prefix) {
4444
{{prefix + "ST_Within"}});
4545
}
4646

47+
void registerOverlayOperations(const std::string& prefix) {
48+
registerFunction<StDifferenceFunction, Geometry, Geometry, Geometry>(
49+
{{prefix + "ST_Difference"}});
50+
registerFunction<StIntersectionFunction, Geometry, Geometry, Geometry>(
51+
{{prefix + "ST_Intersection"}});
52+
registerFunction<StSymDifferenceFunction, Geometry, Geometry, Geometry>(
53+
{{prefix + "ST_SymDifference"}});
54+
registerFunction<StUnionFunction, Geometry, Geometry, Geometry>(
55+
{{prefix + "ST_Union"}});
56+
}
57+
4758
} // namespace
4859

4960
void registerGeometryFunctions(const std::string& prefix) {
@@ -61,6 +72,7 @@ void registerGeometryFunctions(const std::string& prefix) {
6172
{{prefix + "ST_AsBinary"}});
6273

6374
registerRelationPredicates(prefix);
75+
registerOverlayOperations(prefix);
6476
}
6577

6678
} // namespace facebook::velox::functions

0 commit comments

Comments
 (0)