From 4d34513a559d216d5ee0767d2787519e5aaaadf7 Mon Sep 17 00:00:00 2001 From: Andrew Date: Sun, 31 Mar 2024 01:07:45 +0000 Subject: [PATCH 1/2] Add NearestPoints scalar function. --- README.md | 1 + docs/docs.md | 15 +++++++ docs/src/scalar_functions.json | 1 + .../include/spatial/geos/functions/scalar.hpp | 2 + .../geos/functions/scalar/CMakeLists.txt | 1 + .../functions/scalar/st_nearestpoints.cpp | 45 +++++++++++++++++++ 6 files changed, 65 insertions(+) create mode 100644 spatial/src/spatial/geos/functions/scalar/st_nearestpoints.cpp diff --git a/README.md b/README.md index 7c453863..03b90d9c 100644 --- a/README.md +++ b/README.md @@ -388,6 +388,7 @@ Again, please feel free to open an issue if there is a particular function you w | ST_IsValid | 🧭 | 🔄 | 🔄 | 🔄 | 🔄 (as POLYGON) | | ST_Length | 🦆 | 🦆 | 🦆 | 🦆 | 🔄 (as POLYGON) | | ST_LineMerge | 🧭 | 🔄 | 🔄 | 🔄 | 🔄 (as POLYGON) | +| ST_NearestPoints | 🧭 | 🔄 | 🔄 | 🔄 | 🔄 (as POLYGON) | | ST_Normalize | 🧭 | 🔄 | 🔄 | 🔄 | 🔄 (as POLYGON) | | ST_NumPoints/ST_NPoints | 🦆 | 🦆 | 🦆 | 🦆 | 🦆 | | ST_Overlaps | 🧭 | 🔄 | 🔄 | 🔄 | 🔄 (as POLYGON) | diff --git a/docs/docs.md b/docs/docs.md index 2db464ec..9d3e5cb7 100644 --- a/docs/docs.md +++ b/docs/docs.md @@ -84,6 +84,7 @@ Note that this will overwrite any existing `spatial` extension installed for the | [ST_MakeEnvelope](##st_makeenvelope) | Returns a minimal bounding box polygon enclosing the input geometry | | [ST_MakeLine](##st_makeline) | Creates a LINESTRING geometry from a pair or list of input points | | [ST_MakePolygon](##st_makepolygon) | Creates a polygon from a shell geometry and an optional set of holes | +| [ST_NearestPoints](##st_neasrestpoints) | Returns the two closest points on geom1 and geom2 to each other | | [ST_Normalize](##st_normalize) | Returns a "normalized" version of the input geometry. | | [ST_NumGeometries](##st_numgeometries) | Returns the number of component geometries in a collection geometry | | [ST_NumInteriorRings](##st_numinteriorrings) | Returns the number if interior rings of a polygon | @@ -980,6 +981,20 @@ TODO TODO +## ST_NearestPoints + +_Returns the two closest points on geom1 and geom2 to each other_ + +- __GEOMETRY__ ST_NearestPoints(geom1 __GEOMETRY__, geom2 __GEOMETRY__) + +### Description + +TODO + +### Examples + +TODO + ## ST_Normalize _Returns a "normalized" version of the input geometry._ diff --git a/docs/src/scalar_functions.json b/docs/src/scalar_functions.json index bcee1b15..d200ac2f 100644 --- a/docs/src/scalar_functions.json +++ b/docs/src/scalar_functions.json @@ -68,6 +68,7 @@ {"type":"scalar_function","id":"st_geomfromgeojson","title":"ST_GeomFromGeoJSON","signatures":[{"returns":"GEOMETRY","parameters":["VARCHAR"]}]} {"type":"scalar_function","id":"st_asgeojson","title":"ST_AsGeoJSON","signatures":[{"returns":"VARCHAR","parameters":["GEOMETRY"]}]} {"type":"scalar_function","id":"st_intersection","title":"ST_Intersection","signatures":[{"returns":"GEOMETRY","parameters":["GEOMETRY","GEOMETRY"]}]} +{"type":"scalar_function","id":"st_nearestpoints","title":"ST_NearestPoints","signatures":[{"returns":"GEOMETRY","parameters":["GEOMETRY","GEOMETRY"]}]} {"type":"scalar_function","id":"st_boundary","title":"ST_Boundary","signatures":[{"returns":"GEOMETRY","parameters":["GEOMETRY"]}]} {"type":"scalar_function","id":"st_polygon2dfromwkb","title":"ST_Polygon2DFromWKB","signatures":[{"returns":"POLYGON_2D","parameters":["WKB_BLOB"]}]} {"type":"scalar_function","id":"st_exteriorring","title":"ST_ExteriorRing","signatures":[{"returns":"LINESTRING_2D","parameters":["POLYGON_2D"]},{"returns":"GEOMETRY","parameters":["GEOMETRY"]}]} diff --git a/spatial/include/spatial/geos/functions/scalar.hpp b/spatial/include/spatial/geos/functions/scalar.hpp index a3ee94bb..3f98012e 100644 --- a/spatial/include/spatial/geos/functions/scalar.hpp +++ b/spatial/include/spatial/geos/functions/scalar.hpp @@ -32,6 +32,7 @@ struct GEOSScalarFunctions { RegisterStLineMerge(db); RegisterStMakeValid(db); RegisterStNormalize(db); + RegisterStNearestPoints(db); RegisterStOverlaps(db); RegisterStPointOnSurface(db); RegisterStReducePrecision(db); @@ -67,6 +68,7 @@ struct GEOSScalarFunctions { static void RegisterStIsSimple(DatabaseInstance &db); static void RegisterStIsValid(DatabaseInstance &db); static void RegisterStNormalize(DatabaseInstance &db); + static void RegisterStNearestPoints(DatabaseInstance &db); static void RegisterStOverlaps(DatabaseInstance &db); static void RegisterStPointOnSurface(DatabaseInstance &db); static void RegisterStReducePrecision(DatabaseInstance &db); diff --git a/spatial/src/spatial/geos/functions/scalar/CMakeLists.txt b/spatial/src/spatial/geos/functions/scalar/CMakeLists.txt index 51b6222d..7151a897 100644 --- a/spatial/src/spatial/geos/functions/scalar/CMakeLists.txt +++ b/spatial/src/spatial/geos/functions/scalar/CMakeLists.txt @@ -24,6 +24,7 @@ set(EXTENSION_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/st_linemerge.cpp ${CMAKE_CURRENT_SOURCE_DIR}/st_makevalid.cpp ${CMAKE_CURRENT_SOURCE_DIR}/st_normalize.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/st_nearestpoints.cpp ${CMAKE_CURRENT_SOURCE_DIR}/st_overlaps.cpp ${CMAKE_CURRENT_SOURCE_DIR}/st_pointonsurface.cpp ${CMAKE_CURRENT_SOURCE_DIR}/st_reduceprecision.cpp diff --git a/spatial/src/spatial/geos/functions/scalar/st_nearestpoints.cpp b/spatial/src/spatial/geos/functions/scalar/st_nearestpoints.cpp new file mode 100644 index 00000000..96321621 --- /dev/null +++ b/spatial/src/spatial/geos/functions/scalar/st_nearestpoints.cpp @@ -0,0 +1,45 @@ +#include "spatial/common.hpp" +#include "spatial/core/types.hpp" +#include "spatial/geos/functions/scalar.hpp" +#include "spatial/geos/functions/common.hpp" +#include "spatial/geos/geos_wrappers.hpp" + +#include "duckdb/parser/parsed_data/create_scalar_function_info.hpp" +#include "duckdb/common/vector_operations/unary_executor.hpp" +#include "duckdb/common/vector_operations/binary_executor.hpp" + +namespace spatial { + +namespace geos { + +using namespace spatial::core; + +static void NearestPointsFunction(DataChunk &args, ExpressionState &state, Vector &result) { + auto &lstate = GEOSFunctionLocalState::ResetAndGet(state); + auto &ctx = lstate.ctx.GetCtx(); + BinaryExecutor::Execute( + args.data[0], args.data[1], result, args.size(), [&](geometry_t left, geometry_t right) { + auto left_geom = lstate.ctx.Deserialize(left); + auto right_geom = lstate.ctx.Deserialize(right); + + // Returned as a line string given the C++ API doesn't provide create_MultiPoint + auto coord_seq = GEOSNearestPoints_r(ctx, left_geom.get(), right_geom.get()); + auto result_geom = make_uniq_geos(ctx, GEOSGeom_createLineString_r(ctx, coord_seq)); + + return lstate.ctx.Serialize(result, result_geom); + }); +} + +void GEOSScalarFunctions::RegisterStNearestPoints(DatabaseInstance &db) { + + ScalarFunctionSet set("ST_NearestPoints"); + + set.AddFunction(ScalarFunction({GeoTypes::GEOMETRY(), GeoTypes::GEOMETRY()}, GeoTypes::GEOMETRY(), + NearestPointsFunction, nullptr, nullptr, nullptr, GEOSFunctionLocalState::Init)); + + ExtensionUtil::RegisterFunction(db, set); +} + +} // namespace geos + +} // namespace spatial From 0d3d1c5f02dd7b2461bde85d6c73e571b77156a4 Mon Sep 17 00:00:00 2001 From: Max Gabrielsson Date: Mon, 1 Apr 2024 14:58:00 +0200 Subject: [PATCH 2/2] format --- spatial/include/spatial/geos/functions/scalar.hpp | 6 +++--- .../src/spatial/geos/functions/scalar/st_shortestline.cpp | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/spatial/include/spatial/geos/functions/scalar.hpp b/spatial/include/spatial/geos/functions/scalar.hpp index 2fbc5f1b..0f2d2826 100644 --- a/spatial/include/spatial/geos/functions/scalar.hpp +++ b/spatial/include/spatial/geos/functions/scalar.hpp @@ -37,7 +37,7 @@ struct GEOSScalarFunctions { RegisterStReducePrecision(db); RegisterStRemoveRepeatedPoints(db); RegisterStReverse(db); - RegisterStShortestLine(db); + RegisterStShortestLine(db); RegisterStSimplifyPreserveTopology(db); RegisterStSimplify(db); RegisterStTouches(db); @@ -75,8 +75,8 @@ struct GEOSScalarFunctions { static void RegisterStReverse(DatabaseInstance &db); static void RegisterStLineMerge(DatabaseInstance &db); static void RegisterStMakeValid(DatabaseInstance &db); - static void RegisterStShortestLine(DatabaseInstance &db); - static void RegisterStSimplifyPreserveTopology(DatabaseInstance &db); + static void RegisterStShortestLine(DatabaseInstance &db); + static void RegisterStSimplifyPreserveTopology(DatabaseInstance &db); static void RegisterStSimplify(DatabaseInstance &db); static void RegisterStTouches(DatabaseInstance &db); static void RegisterStUnion(DatabaseInstance &db); diff --git a/spatial/src/spatial/geos/functions/scalar/st_shortestline.cpp b/spatial/src/spatial/geos/functions/scalar/st_shortestline.cpp index 4b932c7a..e6deedfc 100644 --- a/spatial/src/spatial/geos/functions/scalar/st_shortestline.cpp +++ b/spatial/src/spatial/geos/functions/scalar/st_shortestline.cpp @@ -21,7 +21,7 @@ static void ShortestLineFunction(DataChunk &args, ExpressionState &state, Vector auto left_geom = lstate.ctx.Deserialize(left); auto right_geom = lstate.ctx.Deserialize(right); - auto coord_seq = GEOSNearestPoints_r(ctx, left_geom.get(), right_geom.get()); + auto coord_seq = GEOSNearestPoints_r(ctx, left_geom.get(), right_geom.get()); auto result_geom = make_uniq_geos(ctx, GEOSGeom_createLineString_r(ctx, coord_seq)); return lstate.ctx.Serialize(result, result_geom); @@ -51,7 +51,7 @@ void GEOSScalarFunctions::RegisterStShortestLine(DatabaseInstance &db) { ShortestLineFunction, nullptr, nullptr, nullptr, GEOSFunctionLocalState::Init)); ExtensionUtil::RegisterFunction(db, set); - DocUtil::AddDocumentation(db, "ST_ShortestLine", DOC_DESCRIPTION, DOC_EXAMPLE, DOC_TAGS); + DocUtil::AddDocumentation(db, "ST_ShortestLine", DOC_DESCRIPTION, DOC_EXAMPLE, DOC_TAGS); } } // namespace geos