[postgis-tickets] [SCM] PostGIS branch master updated. 3.1.0alpha3-4-gd8fb00c

git at osgeo.org git at osgeo.org
Thu Nov 26 16:10:15 PST 2020


This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "PostGIS".

The branch, master has been updated
       via  d8fb00c553417d04860256ca5e2be2390248f7e2 (commit)
      from  1ba9345694db6de6e648c10fe7dba2028e67a201 (commit)

Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.

- Log -----------------------------------------------------------------
commit d8fb00c553417d04860256ca5e2be2390248f7e2
Author: Paul Ramsey <pramsey at cleverelephant.ca>
Date:   Thu Nov 26 16:09:15 2020 -0800

    Add ST_ReducePrecision for GEOS 3.9+.
    Uses GEOS setPrecision CAPI routine to round coordinates
    to grid while retaining a fully valid output.

diff --git a/NEWS b/NEWS
index 2c0318d..866b944 100644
--- a/NEWS
+++ b/NEWS
@@ -4,6 +4,7 @@ Only tickets not included in 3.1.0alpha3
 
  * New features*
   - #4801, ST_ClusterKMeans supports weights in POINT[Z]M geometries (Darafei Praliaskouski)
+  - #4804, ST_ReducePrecision (GEOS 3.9+) allows valid precision reduction (Paul Ramsey)
 
 
 PostGIS 3.1.0alpha3
diff --git a/doc/reference_processing.xml b/doc/reference_processing.xml
index dbd34e7..c71dc0d 100644
--- a/doc/reference_processing.xml
+++ b/doc/reference_processing.xml
@@ -2652,6 +2652,64 @@ SELECT ST_AsEWKT(ST_PointOnSurface(ST_GeomFromEWKT('LINESTRING(0 5 1, 0 0 1, 0 1
       </refsection>
     </refentry>
 
+
+    <refentry id="ST_ReducePrecision">
+      <refnamediv>
+        <refname>ST_ReducePrecision</refname>
+
+        <refpurpose>Returns a valid geometry with all points rounded to the provided grid tolerance, and features below the tolerance removed.</refpurpose>
+      </refnamediv>
+
+      <refsynopsisdiv>
+        <funcsynopsis>
+          <funcprototype>
+            <funcdef>geometry <function>ST_ReducePrecision</function></funcdef>
+
+            <paramdef><type>geometry </type>
+            <parameter>g</parameter></paramdef>
+            <paramdef><type>float8 </type>
+            <parameter>gridsize</parameter></paramdef>
+          </funcprototype>
+        </funcsynopsis>
+      </refsynopsisdiv>
+
+      <refsection>
+        <title>Description</title>
+
+        <para>Returns a valid geometry with all points rounded to the provided grid tolerance, and features below the tolerance removed.</para>
+
+        <para>Unlike <xref linkend="ST_SnapToGrid" /> the returned geometry will be valid, with no ring self-intersections or collapsed components.</para>
+
+      </refsection>
+
+      <refsection>
+        <title>Examples</title>
+
+        <programlisting>SELECT ST_AsText(ST_ReducePrecision('POINT(1.412 19.323)', 0.1));
+    st_astext
+-----------------
+ POINT(1.4 19.3)
+
+SELECT ST_AsText(ST_ReducePrecision('POINT(1.412 19.323)', 1.0));
+  st_astext
+-------------
+ POINT(1 19)
+
+ SELECT ST_AsText(ST_ReducePrecision('POINT(1.412 19.323)', 10));
+  st_astext
+-------------
+ POINT(0 20)
+</programlisting>
+      </refsection>
+
+      <refsection>
+        <title>See Also</title>
+
+        <para><xref linkend="ST_SnapToGrid" />, <xref linkend="ST_Simplify" />, <xref linkend="ST_SimplifyVW" /></para>
+      </refsection>
+    </refentry>
+
+
     <refentry id="ST_RemoveRepeatedPoints">
       <refnamediv>
         <refname>ST_RemoveRepeatedPoints</refname>
diff --git a/liblwgeom/liblwgeom.h.in b/liblwgeom/liblwgeom.h.in
index 57d7f32..a5ea431 100644
--- a/liblwgeom/liblwgeom.h.in
+++ b/liblwgeom/liblwgeom.h.in
@@ -2367,6 +2367,7 @@ LWGEOM *lwgeom_difference_prec(const LWGEOM *geom1, const LWGEOM *geom2, double
 LWGEOM *lwgeom_symdifference(const LWGEOM* geom1, const LWGEOM* geom2);
 LWGEOM *lwgeom_symdifference_prec(const LWGEOM* geom1, const LWGEOM* geom2, double gridSize);
 LWGEOM *lwgeom_pointonsurface(const LWGEOM* geom);
+LWGEOM *lwgeom_reduceprecision(const LWGEOM* geom, double gridSize);
 LWGEOM *lwgeom_centroid(const LWGEOM* geom);
 LWGEOM *lwgeom_union(const LWGEOM *geom1, const LWGEOM *geom2);
 LWGEOM *lwgeom_union_prec(const LWGEOM *geom1, const LWGEOM *geom2, double gridSize);
diff --git a/liblwgeom/lwgeom_geos.c b/liblwgeom/lwgeom_geos.c
index 1ca3f4f..c2a41ee 100644
--- a/liblwgeom/lwgeom_geos.c
+++ b/liblwgeom/lwgeom_geos.c
@@ -939,6 +939,42 @@ lwgeom_centroid(const LWGEOM* geom)
 	return result;
 }
 
+LWGEOM*
+lwgeom_reduceprecision(const LWGEOM* geom, double gridSize)
+{
+#if POSTGIS_GEOS_VERSION < 39
+	lwerror("Precision reduction requires GEOS-3.9 or higher");
+	return NULL;
+#else
+
+	LWGEOM* result;
+	int32_t srid = RESULT_SRID(geom);
+	uint8_t is3d = FLAGS_GET_Z(geom->flags);
+	GEOSGeometry *g1, *g3;
+
+	if (srid == SRID_INVALID) return NULL;
+
+	if (lwgeom_is_empty(geom))
+		return lwgeom_clone_deep(geom);
+
+	initGEOS(lwnotice, lwgeom_geos_error);
+
+	if (!(g1 = LWGEOM2GEOS(geom, AUTOFIX))) GEOS_FAIL();
+
+	g3 = GEOSGeom_setPrecision(g1, gridSize, 0);
+
+	if (!g3) GEOS_FREE_AND_FAIL(g1);
+	GEOSSetSRID(g3, srid);
+
+	if (!(result = GEOS2LWGEOM(g3, is3d)))
+		GEOS_FREE_AND_FAIL(g1);
+
+	GEOS_FREE(g1, g3);
+
+	return result;
+#endif
+}
+
 LWGEOM *
 lwgeom_pointonsurface(const LWGEOM *geom)
 {
diff --git a/liblwgeom/lwkmeans.c b/liblwgeom/lwkmeans.c
index c5c6a4e..aaac0d0 100644
--- a/liblwgeom/lwkmeans.c
+++ b/liblwgeom/lwkmeans.c
@@ -43,7 +43,7 @@ update_r(POINT4D *objs, int *clusters, uint32_t n, POINT4D *centers, uint32_t k)
 		int curr_cluster = 0;
 
 		/* Check all other cluster centers and find the nearest */
-		for (int cluster = 1; cluster < k; cluster++)
+		for (int cluster = 1; cluster < (int)k; cluster++)
 		{
 			double distance = distance3d_sqr_pt4d_pt4d(&obj, &centers[cluster]);
 			if (distance < curr_distance)
diff --git a/postgis/lwgeom_geos.c b/postgis/lwgeom_geos.c
index ed5d27e..ae5aa75 100644
--- a/postgis/lwgeom_geos.c
+++ b/postgis/lwgeom_geos.c
@@ -1513,6 +1513,27 @@ Datum centroid(PG_FUNCTION_ARGS)
 	PG_RETURN_POINTER(result);
 }
 
+Datum ST_ReducePrecision(PG_FUNCTION_ARGS);
+PG_FUNCTION_INFO_V1(ST_ReducePrecision);
+Datum ST_ReducePrecision(PG_FUNCTION_ARGS)
+{
+	GSERIALIZED *geom, *result;
+	LWGEOM *lwgeom, *lwresult;
+	double gridSize = PG_GETARG_FLOAT8(1);
+	geom = PG_GETARG_GSERIALIZED_P(0);
+
+	lwgeom = lwgeom_from_gserialized(geom);
+	lwresult = lwgeom_reduceprecision(lwgeom, gridSize);
+	lwgeom_free(lwgeom);
+	PG_FREE_IF_COPY(geom, 0);
+
+	if (!lwresult) PG_RETURN_NULL();
+
+	result = geometry_serialize(lwresult);
+	lwgeom_free(lwresult);
+	PG_RETURN_POINTER(result);
+}
+
 Datum ST_ClipByBox2d(PG_FUNCTION_ARGS);
 PG_FUNCTION_INFO_V1(ST_ClipByBox2d);
 Datum ST_ClipByBox2d(PG_FUNCTION_ARGS)
diff --git a/postgis/postgis.sql.in b/postgis/postgis.sql.in
index 45b053a..5310d48 100644
--- a/postgis/postgis.sql.in
+++ b/postgis/postgis.sql.in
@@ -3667,6 +3667,12 @@ CREATE OR REPLACE FUNCTION ST_Subdivide(geom geometry, maxvertices integer DEFAU
 	LANGUAGE 'c' IMMUTABLE STRICT PARALLEL SAFE
 	_COST_HIGH;
 
+CREATE OR REPLACE FUNCTION ST_ReducePrecision(geom geometry, gridsize float8)
+	RETURNS geometry
+	AS 'MODULE_PATHNAME', 'ST_ReducePrecision'
+	LANGUAGE 'c' IMMUTABLE STRICT PARALLEL SAFE
+	_COST_MEDIUM;
+
 --------------------------------------------------------------------------------
 -- ST_CleanGeometry / ST_MakeValid
 --------------------------------------------------------------------------------
diff --git a/regress/core/geos39.sql b/regress/core/geos39.sql
index 2d3dab4..8885fdd 100644
--- a/regress/core/geos39.sql
+++ b/regress/core/geos39.sql
@@ -37,3 +37,8 @@ WITH p AS (
 )
 SELECT 'mic-cte' AS name, ST_AsText(st_snaptogrid((ST_MaximumInscribedCircle(ply)).center,0.001))
 	FROM p;
+
+-- ST_ReducePrecision
+SELECT 'rp-1', ST_AsText(ST_ReducePrecision('POINT(1.412 19.323)', 0.1));
+SELECT 'rp-2', ST_AsText(ST_ReducePrecision('POINT(1.412 19.323)', 1.0));
+SELECT 'rp-3', ST_AsText(ST_ReducePrecision('POINT(1.412 19.323)', 10));
diff --git a/regress/core/geos39_expected b/regress/core/geos39_expected
index f538159..06ebbd4 100644
--- a/regress/core/geos39_expected
+++ b/regress/core/geos39_expected
@@ -5,3 +5,6 @@ mic-line|POINT(49.5117 49.5117)|POINT(50.5111 98.9796)|49.4779
 mic-mpoint|POINT(48.584 49.9512)|POINT(99 98)|69.6453
 mic-point|POINT(0 0)|POINT(0 0)|0.0000
 mic-cte|POINT(49.512 49.512)
+rp-1|POINT(1.4 19.3)
+rp-2|POINT(1 19)
+rp-3|POINT(0 20)

-----------------------------------------------------------------------

Summary of changes:
 NEWS                         |  1 +
 doc/reference_processing.xml | 58 ++++++++++++++++++++++++++++++++++++++++++++
 liblwgeom/liblwgeom.h.in     |  1 +
 liblwgeom/lwgeom_geos.c      | 36 +++++++++++++++++++++++++++
 liblwgeom/lwkmeans.c         |  2 +-
 postgis/lwgeom_geos.c        | 21 ++++++++++++++++
 postgis/postgis.sql.in       |  6 +++++
 regress/core/geos39.sql      |  5 ++++
 regress/core/geos39_expected |  3 +++
 9 files changed, 132 insertions(+), 1 deletion(-)


hooks/post-receive
-- 
PostGIS


More information about the postgis-tickets mailing list