From 33114212e40c46250cbd011a2f92974ba729e764 Mon Sep 17 00:00:00 2001 From: Thomas Buck Date: Sat, 20 Sep 2025 00:41:34 +0100 Subject: [PATCH 1/2] Initial ST_CoverageClean() implementation. --- docs/functions.md | 295 +++++++++++---------- src/spatial/modules/geos/geos_geometry.hpp | 43 +++ src/spatial/modules/geos/geos_module.cpp | 105 ++++++++ test/sql/geos/st_coverageclean.test | 18 ++ vcpkg.json | 6 + 5 files changed, 329 insertions(+), 138 deletions(-) create mode 100644 test/sql/geos/st_coverageclean.test diff --git a/docs/functions.md b/docs/functions.md index 89583ca4..d8d065c1 100644 --- a/docs/functions.md +++ b/docs/functions.md @@ -3,144 +3,145 @@ ## Function Index **[Scalar Functions](#scalar-functions)** -| Function | Summary | -| --- | --- | -| [`DuckDB_PROJ_Compiled_Version`](#duckdb_proj_compiled_version) | Returns a text description of the PROJ library version that that this instance of DuckDB was compiled against. | -| [`DuckDB_Proj_Version`](#duckdb_proj_version) | Returns a text description of the PROJ library version that is being used by this instance of DuckDB. | -| [`ST_Affine`](#st_affine) | Applies an affine transformation to a geometry. | -| [`ST_Area`](#st_area) | Compute the area of a geometry. | -| [`ST_Area_Spheroid`](#st_area_spheroid) | Returns the area of a geometry in meters, using an ellipsoidal model of the earth | -| [`ST_AsGeoJSON`](#st_asgeojson) | Returns the geometry as a GeoJSON fragment | -| [`ST_AsHEXWKB`](#st_ashexwkb) | Returns the geometry as a HEXWKB string | -| [`ST_AsMVTGeom`](#st_asmvtgeom) | Transform and clip geometry to a tile boundary | -| [`ST_AsSVG`](#st_assvg) | Convert the geometry into a SVG fragment or path | -| [`ST_AsText`](#st_astext) | Returns the geometry as a WKT string | -| [`ST_AsWKB`](#st_aswkb) | Returns the geometry as a WKB (Well-Known-Binary) blob | -| [`ST_Azimuth`](#st_azimuth) | Returns the azimuth (a clockwise angle measured from north) of two points in radian. | -| [`ST_Boundary`](#st_boundary) | Returns the "boundary" of a geometry | -| [`ST_Buffer`](#st_buffer) | Returns a buffer around the input geometry at the target distance | -| [`ST_BuildArea`](#st_buildarea) | Creates a polygonal geometry by attemtping to "fill in" the input geometry. | -| [`ST_Centroid`](#st_centroid) | Returns the centroid of a geometry | -| [`ST_Collect`](#st_collect) | Collects a list of geometries into a collection geometry. | -| [`ST_CollectionExtract`](#st_collectionextract) | Extracts geometries from a GeometryCollection into a typed multi geometry. | -| [`ST_ConcaveHull`](#st_concavehull) | Returns the 'concave' hull of the input geometry, containing all of the source input's points, and which can be used to create polygons from points. The ratio parameter dictates the level of concavity; 1.0 returns the convex hull; and 0 indicates to return the most concave hull possible. Set allowHoles to a non-zero value to allow output containing holes. | -| [`ST_Contains`](#st_contains) | Returns true if the first geometry contains the second geometry | -| [`ST_ContainsProperly`](#st_containsproperly) | Returns true if the first geometry \"properly\" contains the second geometry | -| [`ST_ConvexHull`](#st_convexhull) | Returns the convex hull enclosing the geometry | -| [`ST_CoverageInvalidEdges`](#st_coverageinvalidedges) | Returns the invalid edges in a polygonal coverage, which are edges that are not shared by two polygons. | -| [`ST_CoverageSimplify`](#st_coveragesimplify) | Simplify the edges in a polygonal coverage, preserving the coverange by ensuring that the there are no seams between the resulting simplified polygons. | -| [`ST_CoverageUnion`](#st_coverageunion) | Union all geometries in a polygonal coverage into a single geometry. | -| [`ST_CoveredBy`](#st_coveredby) | Returns true if geom1 is "covered by" geom2 | -| [`ST_Covers`](#st_covers) | Returns true if the geom1 "covers" geom2 | -| [`ST_Crosses`](#st_crosses) | Returns true if geom1 "crosses" geom2 | -| [`ST_DWithin`](#st_dwithin) | Returns if two geometries are within a target distance of each-other | -| [`ST_DWithin_GEOS`](#st_dwithin_geos) | Returns if two geometries are within a target distance of each-other | -| [`ST_DWithin_Spheroid`](#st_dwithin_spheroid) | Returns if two POINT_2D's are within a target distance in meters, using an ellipsoidal model of the earths surface | -| [`ST_Difference`](#st_difference) | Returns the "difference" between two geometries | -| [`ST_Dimension`](#st_dimension) | Returns the "topological dimension" of a geometry. | -| [`ST_Disjoint`](#st_disjoint) | Returns true if the geometries are disjoint | -| [`ST_Distance`](#st_distance) | Returns the planar distance between two geometries | -| [`ST_Distance_GEOS`](#st_distance_geos) | Returns the planar distance between two geometries | -| [`ST_Distance_Sphere`](#st_distance_sphere) | Returns the haversine (great circle) distance between two geometries. | -| [`ST_Distance_Spheroid`](#st_distance_spheroid) | Returns the distance between two geometries in meters using an ellipsoidal model of the earths surface | -| [`ST_Dump`](#st_dump) | Dumps a geometry into a list of sub-geometries and their "path" in the original geometry. | -| [`ST_EndPoint`](#st_endpoint) | Returns the end point of a LINESTRING. | -| [`ST_Envelope`](#st_envelope) | Returns the minimum bounding rectangle of a geometry as a polygon geometry | -| [`ST_Equals`](#st_equals) | Returns true if the geometries are "equal" | -| [`ST_Extent`](#st_extent) | Returns the minimal bounding box enclosing the input geometry | -| [`ST_Extent_Approx`](#st_extent_approx) | Returns the approximate bounding box of a geometry, if available. | -| [`ST_ExteriorRing`](#st_exteriorring) | Returns the exterior ring (shell) of a polygon geometry. | -| [`ST_FlipCoordinates`](#st_flipcoordinates) | Returns a new geometry with the coordinates of the input geometry "flipped" so that x = y and y = x | -| [`ST_Force2D`](#st_force2d) | Forces the vertices of a geometry to have X and Y components | -| [`ST_Force3DM`](#st_force3dm) | Forces the vertices of a geometry to have X, Y and M components | -| [`ST_Force3DZ`](#st_force3dz) | Forces the vertices of a geometry to have X, Y and Z components | -| [`ST_Force4D`](#st_force4d) | Forces the vertices of a geometry to have X, Y, Z and M components | -| [`ST_GeomFromGeoJSON`](#st_geomfromgeojson) | Deserializes a GEOMETRY from a GeoJSON fragment. | -| [`ST_GeomFromHEXEWKB`](#st_geomfromhexewkb) | Deserialize a GEOMETRY from a HEX(E)WKB encoded string | -| [`ST_GeomFromHEXWKB`](#st_geomfromhexwkb) | Deserialize a GEOMETRY from a HEX(E)WKB encoded string | -| [`ST_GeomFromText`](#st_geomfromtext) | Deserialize a GEOMETRY from a WKT encoded string | -| [`ST_GeomFromWKB`](#st_geomfromwkb) | Deserializes a GEOMETRY from a WKB encoded blob | -| [`ST_GeometryType`](#st_geometrytype) | Returns a 'GEOMETRY_TYPE' enum identifying the input geometry type. Possible enum return types are: `POINT`, `LINESTRING`, `POLYGON`, `MULTIPOINT`, `MULTILINESTRING`, `MULTIPOLYGON`, and `GEOMETRYCOLLECTION`. | -| [`ST_HasM`](#st_hasm) | Check if the input geometry has M values. | -| [`ST_HasZ`](#st_hasz) | Check if the input geometry has Z values. | -| [`ST_Hilbert`](#st_hilbert) | Encodes the X and Y values as the hilbert curve index for a curve covering the given bounding box. | -| [`ST_InterpolatePoint`](#st_interpolatepoint) | Computes the closest point on a LINESTRING to a given POINT and returns the interpolated M value of that point. | -| [`ST_Intersection`](#st_intersection) | Returns the intersection of two geometries | -| [`ST_Intersects`](#st_intersects) | Returns true if the geometries intersect | -| [`ST_Intersects_Extent`](#st_intersects_extent) | Returns true if the extent of two geometries intersects | -| [`ST_IsClosed`](#st_isclosed) | Check if a geometry is 'closed' | -| [`ST_IsEmpty`](#st_isempty) | Returns true if the geometry is "empty". | -| [`ST_IsRing`](#st_isring) | Returns true if the geometry is a ring (both ST_IsClosed and ST_IsSimple). | -| [`ST_IsSimple`](#st_issimple) | Returns true if the geometry is simple | -| [`ST_IsValid`](#st_isvalid) | Returns true if the geometry is valid | -| [`ST_Length`](#st_length) | Returns the length of the input line geometry | -| [`ST_Length_Spheroid`](#st_length_spheroid) | Returns the length of the input geometry in meters, using an ellipsoidal model of the earth | -| [`ST_LineInterpolatePoint`](#st_lineinterpolatepoint) | Returns a point interpolated along a line at a fraction of total 2D length. | -| [`ST_LineInterpolatePoints`](#st_lineinterpolatepoints) | Returns a multi-point interpolated along a line at a fraction of total 2D length. | -| [`ST_LineLocatePoint`](#st_linelocatepoint) | Returns the location on a line closest to a point as a fraction of the total 2D length of the line. | -| [`ST_LineMerge`](#st_linemerge) | "Merges" the input line geometry, optionally taking direction into account. | -| [`ST_LineString2DFromWKB`](#st_linestring2dfromwkb) | Deserialize a LINESTRING_2D from a WKB encoded blob | -| [`ST_LineSubstring`](#st_linesubstring) | Returns a substring of a line between two fractions of total 2D length. | -| [`ST_LocateAlong`](#st_locatealong) | Returns a point or multi-point, containing the point(s) at the geometry with the given measure | -| [`ST_LocateBetween`](#st_locatebetween) | Returns a geometry or geometry collection created by filtering and interpolating vertices within a range of "M" values | -| [`ST_M`](#st_m) | Returns the M coordinate of a point geometry | -| [`ST_MMax`](#st_mmax) | Returns the maximum M coordinate of a geometry | -| [`ST_MMin`](#st_mmin) | Returns the minimum M coordinate of a geometry | -| [`ST_MakeBox2D`](#st_makebox2d) | Create a BOX2D from two POINT geometries | -| [`ST_MakeEnvelope`](#st_makeenvelope) | Create a rectangular polygon from min/max coordinates | -| [`ST_MakeLine`](#st_makeline) | Create a LINESTRING from a list of POINT geometries | -| [`ST_MakePoint`](#st_makepoint) | Creates a GEOMETRY point from an pair of floating point numbers. | -| [`ST_MakePolygon`](#st_makepolygon) | Create a POLYGON from a LINESTRING shell | -| [`ST_MakeValid`](#st_makevalid) | Returns a valid representation of the geometry | -| [`ST_MaximumInscribedCircle`](#st_maximuminscribedcircle) | Returns the maximum inscribed circle of the input geometry, optionally with a tolerance. | -| [`ST_MinimumRotatedRectangle`](#st_minimumrotatedrectangle) | Returns the minimum rotated rectangle that bounds the input geometry, finding the surrounding box that has the lowest area by using a rotated rectangle, rather than taking the lowest and highest coordinate values as per ST_Envelope(). | -| [`ST_Multi`](#st_multi) | Turns a single geometry into a multi geometry. | -| [`ST_NGeometries`](#st_ngeometries) | Returns the number of component geometries in a collection geometry. | -| [`ST_NInteriorRings`](#st_ninteriorrings) | Returns the number of interior rings of a polygon | -| [`ST_NPoints`](#st_npoints) | Returns the number of vertices within a geometry | -| [`ST_Node`](#st_node) | Returns a "noded" MultiLinestring, produced by combining a collection of input linestrings and adding additional vertices where they intersect. | -| [`ST_Normalize`](#st_normalize) | Returns the "normalized" representation of the geometry | -| [`ST_NumGeometries`](#st_numgeometries) | Returns the number of component geometries in a collection geometry. | -| [`ST_NumInteriorRings`](#st_numinteriorrings) | Returns the number of interior rings of a polygon | -| [`ST_NumPoints`](#st_numpoints) | Returns the number of vertices within a geometry | -| [`ST_Overlaps`](#st_overlaps) | Returns true if the geometries overlap | -| [`ST_Perimeter`](#st_perimeter) | Returns the length of the perimeter of the geometry | -| [`ST_Perimeter_Spheroid`](#st_perimeter_spheroid) | Returns the length of the perimeter in meters using an ellipsoidal model of the earths surface | -| [`ST_Point`](#st_point) | Creates a GEOMETRY point | -| [`ST_Point2D`](#st_point2d) | Creates a POINT_2D | -| [`ST_Point2DFromWKB`](#st_point2dfromwkb) | Deserialize a POINT_2D from a WKB encoded blob | -| [`ST_Point3D`](#st_point3d) | Creates a POINT_3D | -| [`ST_Point4D`](#st_point4d) | Creates a POINT_4D | -| [`ST_PointN`](#st_pointn) | Returns the n'th vertex from the input geometry as a point geometry | -| [`ST_PointOnSurface`](#st_pointonsurface) | Returns a point guaranteed to lie on the surface of the geometry | -| [`ST_Points`](#st_points) | Collects all the vertices in the geometry into a MULTIPOINT | -| [`ST_Polygon2DFromWKB`](#st_polygon2dfromwkb) | Deserialize a POLYGON_2D from a WKB encoded blob | -| [`ST_Polygonize`](#st_polygonize) | Returns a polygonized representation of the input geometries | -| [`ST_QuadKey`](#st_quadkey) | Compute the [quadkey](https://learn.microsoft.com/en-us/bingmaps/articles/bing-maps-tile-system) for a given lon/lat point at a given level. | -| [`ST_ReducePrecision`](#st_reduceprecision) | Returns the geometry with all vertices reduced to the given precision | -| [`ST_RemoveRepeatedPoints`](#st_removerepeatedpoints) | Remove repeated points from a LINESTRING. | -| [`ST_Reverse`](#st_reverse) | Returns the geometry with the order of its vertices reversed | -| [`ST_ShortestLine`](#st_shortestline) | Returns the shortest line between two geometries | -| [`ST_Simplify`](#st_simplify) | Returns a simplified version of the geometry | -| [`ST_SimplifyPreserveTopology`](#st_simplifypreservetopology) | Returns a simplified version of the geometry that preserves topology | -| [`ST_StartPoint`](#st_startpoint) | Returns the start point of a LINESTRING. | -| [`ST_TileEnvelope`](#st_tileenvelope) | The `ST_TileEnvelope` scalar function generates tile envelope rectangular polygons from specified zoom level and tile indices. | -| [`ST_Touches`](#st_touches) | Returns true if the geometries touch | -| [`ST_Transform`](#st_transform) | Transforms a geometry between two coordinate systems | -| [`ST_Union`](#st_union) | Returns the union of two geometries | -| [`ST_VoronoiDiagram`](#st_voronoidiagram) | Returns the Voronoi diagram of the supplied MultiPoint geometry | -| [`ST_Within`](#st_within) | Returns true if the first geometry is within the second | -| [`ST_WithinProperly`](#st_withinproperly) | Returns true if the first geometry \"properly\" is contained by the second geometry | -| [`ST_X`](#st_x) | Returns the X coordinate of a point geometry | -| [`ST_XMax`](#st_xmax) | Returns the maximum X coordinate of a geometry | -| [`ST_XMin`](#st_xmin) | Returns the minimum X coordinate of a geometry | -| [`ST_Y`](#st_y) | Returns the Y coordinate of a point geometry | -| [`ST_YMax`](#st_ymax) | Returns the maximum Y coordinate of a geometry | -| [`ST_YMin`](#st_ymin) | Returns the minimum Y coordinate of a geometry | -| [`ST_Z`](#st_z) | Returns the Z coordinate of a point geometry | -| [`ST_ZMFlag`](#st_zmflag) | Returns a flag indicating the presence of Z and M values in the input geometry. | -| [`ST_ZMax`](#st_zmax) | Returns the maximum Z coordinate of a geometry | -| [`ST_ZMin`](#st_zmin) | Returns the minimum Z coordinate of a geometry | +| Function | Summary | +|-----------------------------------------------------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| [`DuckDB_PROJ_Compiled_Version`](#duckdb_proj_compiled_version) | Returns a text description of the PROJ library version that that this instance of DuckDB was compiled against. | +| [`DuckDB_Proj_Version`](#duckdb_proj_version) | Returns a text description of the PROJ library version that is being used by this instance of DuckDB. | +| [`ST_Affine`](#st_affine) | Applies an affine transformation to a geometry. | +| [`ST_Area`](#st_area) | Compute the area of a geometry. | +| [`ST_Area_Spheroid`](#st_area_spheroid) | Returns the area of a geometry in meters, using an ellipsoidal model of the earth | +| [`ST_AsGeoJSON`](#st_asgeojson) | Returns the geometry as a GeoJSON fragment | +| [`ST_AsHEXWKB`](#st_ashexwkb) | Returns the geometry as a HEXWKB string | +| [`ST_AsMVTGeom`](#st_asmvtgeom) | Transform and clip geometry to a tile boundary | +| [`ST_AsSVG`](#st_assvg) | Convert the geometry into a SVG fragment or path | +| [`ST_AsText`](#st_astext) | Returns the geometry as a WKT string | +| [`ST_AsWKB`](#st_aswkb) | Returns the geometry as a WKB (Well-Known-Binary) blob | +| [`ST_Azimuth`](#st_azimuth) | Returns the azimuth (a clockwise angle measured from north) of two points in radian. | +| [`ST_Boundary`](#st_boundary) | Returns the "boundary" of a geometry | +| [`ST_Buffer`](#st_buffer) | Returns a buffer around the input geometry at the target distance | +| [`ST_BuildArea`](#st_buildarea) | Creates a polygonal geometry by attemtping to "fill in" the input geometry. | +| [`ST_Centroid`](#st_centroid) | Returns the centroid of a geometry | +| [`ST_Collect`](#st_collect) | Collects a list of geometries into a collection geometry. | +| [`ST_CollectionExtract`](#st_collectionextract) | Extracts geometries from a GeometryCollection into a typed multi geometry. | +| [`ST_ConcaveHull`](#st_concavehull) | Returns the 'concave' hull of the input geometry, containing all of the source input's points, and which can be used to create polygons from points. The ratio parameter dictates the level of concavity; 1.0 returns the convex hull; and 0 indicates to return the most concave hull possible. Set allowHoles to a non-zero value to allow output containing holes. | +| [`ST_Contains`](#st_contains) | Returns true if the first geometry contains the second geometry | +| [`ST_ContainsProperly`](#st_containsproperly) | Returns true if the first geometry \"properly\" contains the second geometry | +| [`ST_ConvexHull`](#st_convexhull) | Returns the convex hull enclosing the geometry | +| [`ST_CoverageClean`](#st_coverageclean) | Remove the gaps between polygon edges that should be an exact match but aren't due to the coordinate data itself. | +| [`ST_CoverageInvalidEdges`](#st_coverageinvalidedges) | Returns the invalid edges in a polygonal coverage, which are edges that are not shared by two polygons. | +| [`ST_CoverageSimplify`](#st_coveragesimplify) | Simplify the edges in a polygonal coverage, preserving the coverange by ensuring that the there are no seams between the resulting simplified polygons. | +| [`ST_CoverageUnion`](#st_coverageunion) | Union all geometries in a polygonal coverage into a single geometry. | +| [`ST_CoveredBy`](#st_coveredby) | Returns true if geom1 is "covered by" geom2 | +| [`ST_Covers`](#st_covers) | Returns true if the geom1 "covers" geom2 | +| [`ST_Crosses`](#st_crosses) | Returns true if geom1 "crosses" geom2 | +| [`ST_DWithin`](#st_dwithin) | Returns if two geometries are within a target distance of each-other | +| [`ST_DWithin_GEOS`](#st_dwithin_geos) | Returns if two geometries are within a target distance of each-other | +| [`ST_DWithin_Spheroid`](#st_dwithin_spheroid) | Returns if two POINT_2D's are within a target distance in meters, using an ellipsoidal model of the earths surface | +| [`ST_Difference`](#st_difference) | Returns the "difference" between two geometries | +| [`ST_Dimension`](#st_dimension) | Returns the "topological dimension" of a geometry. | +| [`ST_Disjoint`](#st_disjoint) | Returns true if the geometries are disjoint | +| [`ST_Distance`](#st_distance) | Returns the planar distance between two geometries | +| [`ST_Distance_GEOS`](#st_distance_geos) | Returns the planar distance between two geometries | +| [`ST_Distance_Sphere`](#st_distance_sphere) | Returns the haversine (great circle) distance between two geometries. | +| [`ST_Distance_Spheroid`](#st_distance_spheroid) | Returns the distance between two geometries in meters using an ellipsoidal model of the earths surface | +| [`ST_Dump`](#st_dump) | Dumps a geometry into a list of sub-geometries and their "path" in the original geometry. | +| [`ST_EndPoint`](#st_endpoint) | Returns the end point of a LINESTRING. | +| [`ST_Envelope`](#st_envelope) | Returns the minimum bounding rectangle of a geometry as a polygon geometry | +| [`ST_Equals`](#st_equals) | Returns true if the geometries are "equal" | +| [`ST_Extent`](#st_extent) | Returns the minimal bounding box enclosing the input geometry | +| [`ST_Extent_Approx`](#st_extent_approx) | Returns the approximate bounding box of a geometry, if available. | +| [`ST_ExteriorRing`](#st_exteriorring) | Returns the exterior ring (shell) of a polygon geometry. | +| [`ST_FlipCoordinates`](#st_flipcoordinates) | Returns a new geometry with the coordinates of the input geometry "flipped" so that x = y and y = x | +| [`ST_Force2D`](#st_force2d) | Forces the vertices of a geometry to have X and Y components | +| [`ST_Force3DM`](#st_force3dm) | Forces the vertices of a geometry to have X, Y and M components | +| [`ST_Force3DZ`](#st_force3dz) | Forces the vertices of a geometry to have X, Y and Z components | +| [`ST_Force4D`](#st_force4d) | Forces the vertices of a geometry to have X, Y, Z and M components | +| [`ST_GeomFromGeoJSON`](#st_geomfromgeojson) | Deserializes a GEOMETRY from a GeoJSON fragment. | +| [`ST_GeomFromHEXEWKB`](#st_geomfromhexewkb) | Deserialize a GEOMETRY from a HEX(E)WKB encoded string | +| [`ST_GeomFromHEXWKB`](#st_geomfromhexwkb) | Deserialize a GEOMETRY from a HEX(E)WKB encoded string | +| [`ST_GeomFromText`](#st_geomfromtext) | Deserialize a GEOMETRY from a WKT encoded string | +| [`ST_GeomFromWKB`](#st_geomfromwkb) | Deserializes a GEOMETRY from a WKB encoded blob | +| [`ST_GeometryType`](#st_geometrytype) | Returns a 'GEOMETRY_TYPE' enum identifying the input geometry type. Possible enum return types are: `POINT`, `LINESTRING`, `POLYGON`, `MULTIPOINT`, `MULTILINESTRING`, `MULTIPOLYGON`, and `GEOMETRYCOLLECTION`. | +| [`ST_HasM`](#st_hasm) | Check if the input geometry has M values. | +| [`ST_HasZ`](#st_hasz) | Check if the input geometry has Z values. | +| [`ST_Hilbert`](#st_hilbert) | Encodes the X and Y values as the hilbert curve index for a curve covering the given bounding box. | +| [`ST_InterpolatePoint`](#st_interpolatepoint) | Computes the closest point on a LINESTRING to a given POINT and returns the interpolated M value of that point. | +| [`ST_Intersection`](#st_intersection) | Returns the intersection of two geometries | +| [`ST_Intersects`](#st_intersects) | Returns true if the geometries intersect | +| [`ST_Intersects_Extent`](#st_intersects_extent) | Returns true if the extent of two geometries intersects | +| [`ST_IsClosed`](#st_isclosed) | Check if a geometry is 'closed' | +| [`ST_IsEmpty`](#st_isempty) | Returns true if the geometry is "empty". | +| [`ST_IsRing`](#st_isring) | Returns true if the geometry is a ring (both ST_IsClosed and ST_IsSimple). | +| [`ST_IsSimple`](#st_issimple) | Returns true if the geometry is simple | +| [`ST_IsValid`](#st_isvalid) | Returns true if the geometry is valid | +| [`ST_Length`](#st_length) | Returns the length of the input line geometry | +| [`ST_Length_Spheroid`](#st_length_spheroid) | Returns the length of the input geometry in meters, using an ellipsoidal model of the earth | +| [`ST_LineInterpolatePoint`](#st_lineinterpolatepoint) | Returns a point interpolated along a line at a fraction of total 2D length. | +| [`ST_LineInterpolatePoints`](#st_lineinterpolatepoints) | Returns a multi-point interpolated along a line at a fraction of total 2D length. | +| [`ST_LineLocatePoint`](#st_linelocatepoint) | Returns the location on a line closest to a point as a fraction of the total 2D length of the line. | +| [`ST_LineMerge`](#st_linemerge) | "Merges" the input line geometry, optionally taking direction into account. | +| [`ST_LineString2DFromWKB`](#st_linestring2dfromwkb) | Deserialize a LINESTRING_2D from a WKB encoded blob | +| [`ST_LineSubstring`](#st_linesubstring) | Returns a substring of a line between two fractions of total 2D length. | +| [`ST_LocateAlong`](#st_locatealong) | Returns a point or multi-point, containing the point(s) at the geometry with the given measure | +| [`ST_LocateBetween`](#st_locatebetween) | Returns a geometry or geometry collection created by filtering and interpolating vertices within a range of "M" values | +| [`ST_M`](#st_m) | Returns the M coordinate of a point geometry | +| [`ST_MMax`](#st_mmax) | Returns the maximum M coordinate of a geometry | +| [`ST_MMin`](#st_mmin) | Returns the minimum M coordinate of a geometry | +| [`ST_MakeBox2D`](#st_makebox2d) | Create a BOX2D from two POINT geometries | +| [`ST_MakeEnvelope`](#st_makeenvelope) | Create a rectangular polygon from min/max coordinates | +| [`ST_MakeLine`](#st_makeline) | Create a LINESTRING from a list of POINT geometries | +| [`ST_MakePoint`](#st_makepoint) | Creates a GEOMETRY point from an pair of floating point numbers. | +| [`ST_MakePolygon`](#st_makepolygon) | Create a POLYGON from a LINESTRING shell | +| [`ST_MakeValid`](#st_makevalid) | Returns a valid representation of the geometry | +| [`ST_MaximumInscribedCircle`](#st_maximuminscribedcircle) | Returns the maximum inscribed circle of the input geometry, optionally with a tolerance. | +| [`ST_MinimumRotatedRectangle`](#st_minimumrotatedrectangle) | Returns the minimum rotated rectangle that bounds the input geometry, finding the surrounding box that has the lowest area by using a rotated rectangle, rather than taking the lowest and highest coordinate values as per ST_Envelope(). | +| [`ST_Multi`](#st_multi) | Turns a single geometry into a multi geometry. | +| [`ST_NGeometries`](#st_ngeometries) | Returns the number of component geometries in a collection geometry. | +| [`ST_NInteriorRings`](#st_ninteriorrings) | Returns the number of interior rings of a polygon | +| [`ST_NPoints`](#st_npoints) | Returns the number of vertices within a geometry | +| [`ST_Node`](#st_node) | Returns a "noded" MultiLinestring, produced by combining a collection of input linestrings and adding additional vertices where they intersect. | +| [`ST_Normalize`](#st_normalize) | Returns the "normalized" representation of the geometry | +| [`ST_NumGeometries`](#st_numgeometries) | Returns the number of component geometries in a collection geometry. | +| [`ST_NumInteriorRings`](#st_numinteriorrings) | Returns the number of interior rings of a polygon | +| [`ST_NumPoints`](#st_numpoints) | Returns the number of vertices within a geometry | +| [`ST_Overlaps`](#st_overlaps) | Returns true if the geometries overlap | +| [`ST_Perimeter`](#st_perimeter) | Returns the length of the perimeter of the geometry | +| [`ST_Perimeter_Spheroid`](#st_perimeter_spheroid) | Returns the length of the perimeter in meters using an ellipsoidal model of the earths surface | +| [`ST_Point`](#st_point) | Creates a GEOMETRY point | +| [`ST_Point2D`](#st_point2d) | Creates a POINT_2D | +| [`ST_Point2DFromWKB`](#st_point2dfromwkb) | Deserialize a POINT_2D from a WKB encoded blob | +| [`ST_Point3D`](#st_point3d) | Creates a POINT_3D | +| [`ST_Point4D`](#st_point4d) | Creates a POINT_4D | +| [`ST_PointN`](#st_pointn) | Returns the n'th vertex from the input geometry as a point geometry | +| [`ST_PointOnSurface`](#st_pointonsurface) | Returns a point guaranteed to lie on the surface of the geometry | +| [`ST_Points`](#st_points) | Collects all the vertices in the geometry into a MULTIPOINT | +| [`ST_Polygon2DFromWKB`](#st_polygon2dfromwkb) | Deserialize a POLYGON_2D from a WKB encoded blob | +| [`ST_Polygonize`](#st_polygonize) | Returns a polygonized representation of the input geometries | +| [`ST_QuadKey`](#st_quadkey) | Compute the [quadkey](https://learn.microsoft.com/en-us/bingmaps/articles/bing-maps-tile-system) for a given lon/lat point at a given level. | +| [`ST_ReducePrecision`](#st_reduceprecision) | Returns the geometry with all vertices reduced to the given precision | +| [`ST_RemoveRepeatedPoints`](#st_removerepeatedpoints) | Remove repeated points from a LINESTRING. | +| [`ST_Reverse`](#st_reverse) | Returns the geometry with the order of its vertices reversed | +| [`ST_ShortestLine`](#st_shortestline) | Returns the shortest line between two geometries | +| [`ST_Simplify`](#st_simplify) | Returns a simplified version of the geometry | +| [`ST_SimplifyPreserveTopology`](#st_simplifypreservetopology) | Returns a simplified version of the geometry that preserves topology | +| [`ST_StartPoint`](#st_startpoint) | Returns the start point of a LINESTRING. | +| [`ST_TileEnvelope`](#st_tileenvelope) | The `ST_TileEnvelope` scalar function generates tile envelope rectangular polygons from specified zoom level and tile indices. | +| [`ST_Touches`](#st_touches) | Returns true if the geometries touch | +| [`ST_Transform`](#st_transform) | Transforms a geometry between two coordinate systems | +| [`ST_Union`](#st_union) | Returns the union of two geometries | +| [`ST_VoronoiDiagram`](#st_voronoidiagram) | Returns the Voronoi diagram of the supplied MultiPoint geometry | +| [`ST_Within`](#st_within) | Returns true if the first geometry is within the second | +| [`ST_WithinProperly`](#st_withinproperly) | Returns true if the first geometry \"properly\" is contained by the second geometry | +| [`ST_X`](#st_x) | Returns the X coordinate of a point geometry | +| [`ST_XMax`](#st_xmax) | Returns the maximum X coordinate of a geometry | +| [`ST_XMin`](#st_xmin) | Returns the minimum X coordinate of a geometry | +| [`ST_Y`](#st_y) | Returns the Y coordinate of a point geometry | +| [`ST_YMax`](#st_ymax) | Returns the maximum Y coordinate of a geometry | +| [`ST_YMin`](#st_ymin) | Returns the minimum Y coordinate of a geometry | +| [`ST_Z`](#st_z) | Returns the Z coordinate of a point geometry | +| [`ST_ZMFlag`](#st_zmflag) | Returns a flag indicating the presence of Z and M values in the input geometry. | +| [`ST_ZMax`](#st_zmax) | Returns the maximum Z coordinate of a geometry | +| [`ST_ZMin`](#st_zmin) | Returns the minimum Z coordinate of a geometry | **[Aggregate Functions](#aggregate-functions)** @@ -768,6 +769,24 @@ GEOMETRY ST_ConvexHull (geom GEOMETRY) #### Description Returns the convex hull enclosing the geometry +---- + +### ST_CoverageClean + + +#### Signatures + +```sql +GEOMETRY ST_CoverageClean (geoms GEOMETRY[], snapDistance DOUBLE, maxWidth DOUBLE) +GEOMETRY ST_CoverageClean (geoms GEOMETRY[], snapDistance DOUBLE) +GEOMETRY ST_CoverageClean (geoms GEOMETRY[]) +``` + +#### Description + +Aligns the edges of a polygon list whose edges are meant to align but are in fact not exact matches. + +Returns a collection of fixed polygons with the same size and order as the input polygons. `EMPTY` will be used in place of collapsed polygons. ---- diff --git a/src/spatial/modules/geos/geos_geometry.hpp b/src/spatial/modules/geos/geos_geometry.hpp index 6ebf063c..df0dfcb3 100644 --- a/src/spatial/modules/geos/geos_geometry.hpp +++ b/src/spatial/modules/geos/geos_geometry.hpp @@ -96,6 +96,7 @@ class GeosGeometry { GeosGeometry get_buffer_style(double distance, int quadsegs, int endcap_style, int join_style, double mitre_limit) const; + GeosGeometry get_coverage_clean(double snapping_distance, double gap_maximum_width) const; GeosGeometry get_coverage_invalid_edges(double tolerance) const; GeosGeometry get_coverage_simplified(double tolerance, bool preserve_boundary) const; GeosGeometry get_coverage_union() const; @@ -507,11 +508,53 @@ inline GeosGeometry GeosGeometry::get_buffer_style(double distance, int quadsegs return GeosGeometry(handle, buffer); } +inline GeosGeometry GeosGeometry::get_coverage_clean(double snapping_distance, double gap_maximum_width) const { + + auto *params_raw = GEOSCoverageCleanParams_create_r(handle); + if (!params_raw) { + // Failed to allocate params; return an empty/invalid geometry handle + return GeosGeometry(handle, nullptr); + } + + // ensure params tidy themselves up after use + struct ParamsDeleter { + GEOSContextHandle_t h; + void operator()(GEOSCoverageCleanParams *p) const { + if (p) { + GEOSCoverageCleanParams_destroy_r(h, p); + } + } + }; + + std::unique_ptr params(params_raw, ParamsDeleter{handle}); + + // Conditionally set optional parameters; check return codes and fail fast + if (snapping_distance >= 0) { + if (!GEOSCoverageCleanParams_setSnappingDistance_r(handle, params.get(), snapping_distance)) { + return GeosGeometry(handle, nullptr); + } + } + if (gap_maximum_width >= 0) { + if (!GEOSCoverageCleanParams_setGapMaximumWidth_r(handle, params.get(), gap_maximum_width)) { + return GeosGeometry(handle, nullptr); + } + } + + // Overlap merge strategy: using a literal to avoid a dependency on enum values when I don't know the wider impact + // 0 is MERGE_LONGEST_BORDER + if (!GEOSCoverageCleanParams_setOverlapMergeStrategy_r(handle, params.get(), 0)) { + return GeosGeometry(handle, nullptr); + } + + return GeosGeometry(handle, GEOSCoverageCleanWithParams_r(handle, geom, params.get())); +} + inline GeosGeometry GeosGeometry::get_coverage_invalid_edges(double tolerance) const { GEOSGeometry *output = nullptr; GEOSCoverageIsValid_r(handle, geom, tolerance, &output); return GeosGeometry(handle, output); } + inline GeosGeometry GeosGeometry::get_coverage_simplified(double tolerance, bool preserve_boundary) const { return GeosGeometry(handle, GEOSCoverageSimplifyVW_r(handle, geom, tolerance, preserve_boundary)); } diff --git a/src/spatial/modules/geos/geos_module.cpp b/src/spatial/modules/geos/geos_module.cpp index 87b50c67..b3bd12be 100644 --- a/src/spatial/modules/geos/geos_module.cpp +++ b/src/spatial/modules/geos/geos_module.cpp @@ -803,6 +803,110 @@ struct ST_ConvexHull { } }; +struct ST_CoverageClean { + + static unique_ptr Bind(ClientContext &context, ScalarFunction &bound_function, + vector> &arguments) { + // set default values for coverage_clean parameters + const size_t num_args = arguments.size(); + if (num_args == 2) { // gap max width + arguments.push_back(make_uniq_base(Value::DOUBLE(-1))); + } + + if (num_args == 1) { // snapping distance, gap max width + arguments.push_back(make_uniq_base(Value::DOUBLE(-1))); + arguments.push_back(make_uniq_base(Value::DOUBLE(-1))); + } + + return nullptr; + } + + static void Execute(DataChunk &args, ExpressionState &state, Vector &result) { + const auto &lstate = LocalState::ResetAndGet(state); + UnifiedVectorFormat format; + + auto &list_vec = args.data[0]; + auto &item_vec = ListVector::GetEntry(list_vec); + item_vec.ToUnifiedFormat(ListVector::GetListSize(list_vec), format); + + // Collection to hold the working set of geometries + GeosCollection collection(lstate.GetContext()); + + TernaryExecutor::Execute( + list_vec, args.data[1], args.data[2], + result, args.size(), [&](const list_entry_t &list, + double snapping_distance, double gap_maximum_width) { + // Reset the collection + collection.clear(); + collection.reserve(list.length); + + const auto offset = list.offset; + const auto length = list.length; + + // Collect all geometries in the list into the collection + for (idx_t i = offset; i < offset + length; i++) { + const auto mapped_idx = format.sel->get_index(i); + + if (!format.validity.RowIsValid(mapped_idx)) { + continue; + } + + const auto &geom_blob = UnifiedVectorFormat::GetData(format)[mapped_idx]; + + auto geom = lstate.Deserialize(geom_blob); + collection.add(std::move(geom)); + } + + // Now make a geometrycollection and simplify + const auto geometry_col = collection.get_collection(); + const auto cleaned = geometry_col.get_coverage_clean(snapping_distance, gap_maximum_width); + return lstate.Serialize(result, cleaned); + }); + } + + static void Register(ExtensionLoader &loader) { + FunctionBuilder::RegisterScalar(loader, "ST_CoverageClean", [](ScalarFunctionBuilder &func) { + func.AddVariant([](ScalarFunctionVariantBuilder &variant) { + variant.AddParameter("geoms", LogicalType::LIST(GeoTypes::GEOMETRY())); + variant.AddParameter("snapping_distance", LogicalType::DOUBLE); + variant.AddParameter("gap_maximum_width", LogicalType::DOUBLE); + variant.SetReturnType(GeoTypes::GEOMETRY()); + + variant.SetInit(LocalState::Init); + variant.SetBind(Bind); + variant.SetFunction(Execute); + }); + + func.AddVariant([](ScalarFunctionVariantBuilder &variant) { + variant.AddParameter("geoms", LogicalType::LIST(GeoTypes::GEOMETRY())); + variant.AddParameter("snapping_distance", LogicalType::DOUBLE); + variant.SetReturnType(GeoTypes::GEOMETRY()); + + variant.SetInit(LocalState::Init); + variant.SetBind(Bind); + variant.SetFunction(Execute); + }); + + func.AddVariant([](ScalarFunctionVariantBuilder &variant) { + variant.AddParameter("geoms", LogicalType::LIST(GeoTypes::GEOMETRY())); + variant.SetReturnType(GeoTypes::GEOMETRY()); + + variant.SetInit(LocalState::Init); + variant.SetBind(Bind); + variant.SetFunction(Execute); + }); + + func.SetDescription(R"( + Aligns the edges of a list of polygons whose edges are meant to align but are in fact exact matches. + + Returns a collection of fixed polygons with the same size and order as the input polygons. EMPTY will be used in place of collapsed polygons. + )"); + func.SetTag("ext", "spatial"); + func.SetTag("category", "construction"); + }); + } +}; + struct ST_CoverageInvalidEdges { static unique_ptr Bind(ClientContext &context, ScalarFunction &bound_function, @@ -2984,6 +3088,7 @@ void RegisterGEOSModule(ExtensionLoader &loader) { ST_WithinProperly::Register(loader); ST_ConcaveHull::Register(loader); ST_ConvexHull::Register(loader); + ST_CoverageClean::Register(loader); ST_CoverageInvalidEdges::Register(loader); ST_CoverageSimplify::Register(loader); ST_CoverageUnion::Register(loader); diff --git a/test/sql/geos/st_coverageclean.test b/test/sql/geos/st_coverageclean.test new file mode 100644 index 00000000..69ba834f --- /dev/null +++ b/test/sql/geos/st_coverageclean.test @@ -0,0 +1,18 @@ +require spatial + +# As per st_isvalid, we trust that GEOS knows what it's doing, so we're not interested in testing this too much + +query I +SELECT ST_CoverageClean( [ + ST_GeomFromText('POLYGON ((533135.006 124828.779, 533140.387 124828.514, 533142.884 124828.615, 533146.44 124829.532, 533150.1 124830.7, 533152.1 124831.7, 533154.2 124832.85, 533157.35 124834.65, 533160.7 124836.85, 533161.35 124837.3, 533161.75 124837.64, 533170.25 124843.55, 533173.05 124845.5, 533191.4 124860.95, 533195.3 124863.32, 533194.65 124864.55, 533193.95 124870.85, 533193.91 124871.2, 533193 124879.25, 533192.81 124881.72, 533192.5 124885.65, 533191.8 124894.05, 533191.63 124897.53, 533191.51 124899.98, 533191.4 124902.2, 533191.32 124903.77, 533191.01 124910.41, 533190.91 124912.57, 533190.589 124913.407, 533190.69 124913.52, 533191 124913.82, 533191.2 124913.99, 533191.4 124914.15, 533191.61 124914.31, 533191.82 124914.45, 533192.04 124914.58, 533192.27 124914.71, 533209.378 124922.281, 533233.851 124933.109, 533234.178 124933.251, 533241.486 124936.502, 533256.269 124943.011, 533272.689 124950.307, 533280.96 124953.37, 533310.314 124966.309, 533327.77 124974.03, 533328.15 124973.2, 533338.87 124949.39, 533344.25 124937.45, 533345.6 124934.43, 533348.18 124928.68, 533347.38 124928.19, 533347.5 124927.8, 533336.95 124921.25, 533325.54 124916.43, 533325.35 124916.35, 533319.85 124914.1, 533315.09 124912.14, 533313.55 124911.5, 533307.35 124912.45, 533306.12 124912.1, 533296.68 124909.37, 533295.9 124909.15, 533287.2 124904.1, 533288.2 124901.35, 533281.6 124898.6, 533281.501 124898.845, 533275.72 124896.47, 533275.633 124896.434, 533275.55 124896.4, 533266.949 124892.9, 533266.369 124892.709, 533265.48 124894.96, 533260.4 124892.9, 533259.42 124892.46, 533256.7 124891.25, 533254.07 124890.13, 533251.65 124889.1, 533248.06 124887.42, 533247.8 124887.3, 533242.85 124885.2, 533242.71 124885.14, 533237.95 124882.95, 533237.16 124882.57, 533233.65 124880.9, 533232.75 124880.4, 533231.62 124879.71, 533230.05 124878.75, 533226.26 124876.52, 533226.05 124876.4, 533220.8 124873.3, 533219.71 124872.62, 533215.95 124870.25, 533210.1 124866.45, 533205.18 124863.03, 533198.3 124858.25, 533197.65 124857.8, 533197.25 124858.2, 533194.15 124855.8, 533192.8 124854.75, 533189.07 124851.79, 533188.2 124851.1, 533185.49 124848.96, 533182.95 124846.95, 533178.4 124843.6, 533175.18 124841.14, 533173.9 124840.15, 533169.8 124837, 533167 124834.9, 533164.35 124833.05, 533164 124832.85, 533160.85 124830.95, 533160.4 124830.7, 533157.15 124829.05, 533153.2 124827.35, 533151.3 124826.65, 533148.15 124825.65, 533143.05 124823.95, 533136.45 124822.05, 533135.8 124826.4, 533135.302 124827.751, 533135.1 124828.3, 533135.006 124828.779))') + , ST_GeomFromText('POLYGON ((533266.369 124892.709, 533266.949 124892.9, 533275.55 124896.4, 533275.633 124896.434, 533275.79 124896.03, 533281.975 124880.06, 533286.87 124867.42, 533289.215 124860.931, 533290.691 124856.899, 533290.339 124856.77, 533284.4 124854.6, 533281.13 124853.37, 533275.1 124869.5, 533275.02 124869.71, 533273.06 124875.11, 533270.65 124881.75, 533267.5 124890.1, 533266.55 124892.25, 533266.369 124892.709))') + , ST_GeomFromText('POLYGON ((533248.06 124887.42, 533251.65 124889.1, 533254.069 124890.13, 533262.6 124867.3, 533264.05 124863.4, 533269.449 124848.95, 533263.699 124846.76, 533262.29 124850.43, 533258.1 124861.4, 533257.3 124863.5, 533248.06 124887.42))') + , ST_GeomFromText('POLYGON ((533275.72 124896.47, 533281.501 124898.845, 533281.6 124898.6, 533291.699 124873.05, 533292.9 124869.7, 533295.339 124863.19, 533296.85 124859.15, 533291.04 124857.026, 533289.524 124861.032, 533286.87 124867.42, 533275.88 124896.06, 533275.72 124896.47))') + , ST_GeomFromText('POLYGON ((533254.069 124890.13, 533256.699 124891.25, 533259.42 124892.46, 533268.949 124867.6, 533269.699 124865.7, 533273.77 124854.73, 533275.132 124851.104, 533273.4 124850.45, 533269.449 124848.95, 533264.05 124863.4, 533262.6 124867.3, 533254.069 124890.13))') + , ST_GeomFromText('POLYGON ((533273.584 124876.936, 533281.975 124880.06, 533286.87 124867.42, 533290.691 124856.899, 533290.339 124856.77, 533286.214 124855.262, 533284.247 124860.343, 533281.686 124859.392, 533280.28 124858.87, 533279.585 124860.745, 533277.06 124867.56, 533273.584 124876.936))') + , ST_GeomFromText('POLYGON ((533259.42 124892.46, 533260.4 124892.9, 533265.48 124894.96, 533266.55 124892.25, 533267.5 124890.1, 533270.65 124881.75, 533273.06 124875.11, 533275.02 124869.71, 533275.1 124869.5, 533281.13 124853.37, 533275.132 124851.104, 533273.77 124854.73, 533269.699 124865.7, 533268.949 124867.6, 533259.42 124892.46))') + ] + , 0.5 +);; +---- +GEOMETRYCOLLECTION (POLYGON ((533251.65 124889.1, 533248.06 124887.42, 533242.85 124885.2, 533237.95 124882.95, 533237.16 124882.57, 533233.65 124880.9, 533232.75 124880.4, 533231.62 124879.71, 533230.05 124878.75, 533226.26 124876.52, 533220.8 124873.3, 533219.71 124872.62, 533215.95 124870.25, 533210.1 124866.45, 533205.18 124863.03, 533198.3 124858.25, 533197.65 124857.8, 533197.25 124858.2, 533194.15 124855.8, 533192.8 124854.75, 533189.07 124851.79, 533188.2 124851.1, 533185.49 124848.96, 533182.95 124846.95, 533178.4 124843.6, 533175.18 124841.14, 533173.9 124840.15, 533169.8 124837, 533167 124834.9, 533164.35 124833.05, 533160.85 124830.95, 533160.4 124830.7, 533157.15 124829.05, 533153.2 124827.35, 533151.3 124826.65, 533148.15 124825.65, 533143.05 124823.95, 533136.45 124822.05, 533135.8 124826.4, 533135.302 124827.751, 533135.006 124828.779, 533140.387 124828.514, 533142.884 124828.615, 533146.44 124829.532, 533150.1 124830.7, 533152.1 124831.7, 533154.2 124832.85, 533157.35 124834.65, 533160.7 124836.85, 533161.35 124837.3, 533161.75 124837.64, 533170.25 124843.55, 533173.05 124845.5, 533191.4 124860.95, 533195.3 124863.32, 533194.65 124864.55, 533193.95 124870.85, 533193 124879.25, 533192.81 124881.72, 533192.5 124885.65, 533191.8 124894.05, 533191.63 124897.53, 533191.51 124899.98, 533191.4 124902.2, 533191.32 124903.77, 533191.01 124910.41, 533190.91 124912.57, 533190.589 124913.407, 533191 124913.82, 533191.4 124914.15, 533191.82 124914.45, 533192.27 124914.71, 533209.378 124922.281, 533233.851 124933.109, 533241.486 124936.502, 533256.269 124943.011, 533272.689 124950.307, 533280.96 124953.37, 533310.314 124966.309, 533327.77 124974.03, 533328.15 124973.2, 533338.87 124949.39, 533344.25 124937.45, 533345.6 124934.43, 533348.18 124928.68, 533347.38 124928.19, 533336.95 124921.25, 533325.54 124916.43, 533319.85 124914.1, 533315.09 124912.14, 533313.55 124911.5, 533307.35 124912.45, 533306.12 124912.1, 533296.68 124909.37, 533295.9 124909.15, 533287.2 124904.1, 533288.2 124901.35, 533281.6 124898.6, 533275.72 124896.47, 533266.949 124892.9, 533266.369 124892.709, 533265.48 124894.96, 533260.4 124892.9, 533259.42 124892.46, 533256.7 124891.25, 533254.07 124890.13, 533251.65 124889.1)), POLYGON ((533266.949 124892.9, 533275.72 124896.47, 533281.975 124880.06, 533286.87 124867.42, 533289.215 124860.931, 533290.691 124856.899, 533286.214 124855.262, 533284.4 124854.6, 533281.13 124853.37, 533275.1 124869.5, 533273.06 124875.11, 533270.65 124881.75, 533267.5 124890.1, 533266.369 124892.709, 533266.949 124892.9)), POLYGON ((533251.65 124889.1, 533254.07 124890.13, 533262.6 124867.3, 533264.05 124863.4, 533269.449 124848.95, 533263.699 124846.76, 533262.29 124850.43, 533258.1 124861.4, 533257.3 124863.5, 533248.06 124887.42, 533251.65 124889.1)), POLYGON ((533281.6 124898.6, 533291.699 124873.05, 533292.9 124869.7, 533295.339 124863.19, 533296.85 124859.15, 533290.691 124856.899, 533289.215 124860.931, 533286.87 124867.42, 533281.975 124880.06, 533275.72 124896.47, 533281.6 124898.6)), POLYGON ((533256.7 124891.25, 533259.42 124892.46, 533268.949 124867.6, 533269.699 124865.7, 533273.77 124854.73, 533275.132 124851.104, 533273.4 124850.45, 533269.449 124848.95, 533264.05 124863.4, 533262.6 124867.3, 533254.07 124890.13, 533256.7 124891.25)), POLYGON EMPTY, POLYGON ((533260.4 124892.9, 533265.48 124894.96, 533266.369 124892.709, 533267.5 124890.1, 533270.65 124881.75, 533273.06 124875.11, 533275.1 124869.5, 533281.13 124853.37, 533275.132 124851.104, 533273.77 124854.73, 533269.699 124865.7, 533268.949 124867.6, 533259.42 124892.46, 533260.4 124892.9))) \ No newline at end of file diff --git a/vcpkg.json b/vcpkg.json index 646ab5ca..38084a72 100644 --- a/vcpkg.json +++ b/vcpkg.json @@ -46,5 +46,11 @@ } ] }, + "overrides": [ + { + "name": "geos", + "version-string": "3.14.0" + } + ], "builtin-baseline" : "ce613c41372b23b1f51333815feb3edd87ef8a8b" } From 30e20310b9ac74bb1602ee4447d29a19e665fff9 Mon Sep 17 00:00:00 2001 From: Thomas Buck Date: Sat, 20 Sep 2025 10:27:34 +0100 Subject: [PATCH 2/2] Vcpkg baseline update to 9824d05f8d9548720ba3331f4baba3e2d6c1693b --- vcpkg.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vcpkg.json b/vcpkg.json index 38084a72..8ef53304 100644 --- a/vcpkg.json +++ b/vcpkg.json @@ -52,5 +52,5 @@ "version-string": "3.14.0" } ], - "builtin-baseline" : "ce613c41372b23b1f51333815feb3edd87ef8a8b" + "builtin-baseline" : "9824d05f8d9548720ba3331f4baba3e2d6c1693b" }