[SCM] PostGIS branch master updated. 3.5.0-41-ge8d47bb44

git at osgeo.org git at osgeo.org
Wed Oct 30 12:14:16 PDT 2024


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  e8d47bb440139d9f6c90acfd234e2fe6a668ba3d (commit)
      from  b32c5c120d7ba40801b27b947337d9da509ca799 (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 e8d47bb440139d9f6c90acfd234e2fe6a668ba3d
Author: Paul Ramsey <pramsey at cleverelephant.ca>
Date:   Wed Oct 30 12:13:55 2024 -0700

    Round even grid/scale factors more precisely.
    Closes #5424

diff --git a/liblwgeom/liblwgeom.h.in b/liblwgeom/liblwgeom.h.in
index f8c11405c..9f7cc3b01 100644
--- a/liblwgeom/liblwgeom.h.in
+++ b/liblwgeom/liblwgeom.h.in
@@ -1398,11 +1398,15 @@ typedef struct gridspec_t
 	double ysize;
 	double zsize;
 	double msize;
+    double xscale;
+    double yscale;
+    double zscale;
+    double mscale;
 }
 gridspec;
 
-extern LWGEOM* lwgeom_grid(const LWGEOM *lwgeom, const gridspec *grid);
-extern void lwgeom_grid_in_place(LWGEOM *lwgeom, const gridspec *grid);
+extern LWGEOM* lwgeom_grid(const LWGEOM *lwgeom, gridspec *grid);
+extern void lwgeom_grid_in_place(LWGEOM *lwgeom, gridspec *grid);
 
 
 /****************************************************************
diff --git a/liblwgeom/liblwgeom_internal.h b/liblwgeom/liblwgeom_internal.h
index f1e28eac0..e51062b00 100644
--- a/liblwgeom/liblwgeom_internal.h
+++ b/liblwgeom/liblwgeom_internal.h
@@ -432,7 +432,7 @@ int lwtin_is_closed(const LWTIN *tin);
 /**
 * Snap to grid
 */
-void ptarray_grid_in_place(POINTARRAY *pa, const gridspec *grid);
+void ptarray_grid_in_place(POINTARRAY *pa, gridspec *grid);
 
 /*
 * What side of the line formed by p1 and p2 does q fall?
diff --git a/liblwgeom/lwgeom.c b/liblwgeom/lwgeom.c
index 86bd54143..c22fb621e 100644
--- a/liblwgeom/lwgeom.c
+++ b/liblwgeom/lwgeom.c
@@ -2226,11 +2226,51 @@ lwgeom_startpoint(const LWGEOM *lwgeom, POINT4D *pt)
 	}
 }
 
+static inline double
+snap_to_int(double val)
+{
+	const double tolerance = 1e-6;
+    double rintval = rint(val);
+    if (fabs(val - rintval) < tolerance)
+    {
+        return rintval;
+    }
+    return val;
+}
+
+/*
+ * See https://github.com/libgeos/geos/pull/956
+ * We use scale for rounding when gridsize is < 1 and
+ * gridsize for rounding when scale < 1.
+ */
+static inline void
+condition_gridspec_scale(gridspec *grid)
+{
+	if(grid->xsize > 0)
+	{
+		if(grid->xsize < 1)
+			grid->xscale = snap_to_int(1/grid->xsize);
+		else
+			grid->xsize = snap_to_int(grid->xsize);
+	}
+	if(grid->ysize > 0)
+	{
+		if(grid->ysize < 1)
+			grid->yscale = snap_to_int(1/grid->ysize);
+		else
+			grid->ysize = snap_to_int(grid->ysize);
+	}
+}
+
+
 void
-lwgeom_grid_in_place(LWGEOM *geom, const gridspec *grid)
+lwgeom_grid_in_place(LWGEOM *geom, gridspec *grid)
 {
 	if (!geom) return;
 	if (lwgeom_is_empty(geom)) return;
+
+	condition_gridspec_scale(grid);
+
 	switch ( geom->type )
 	{
 		case POINTTYPE:
@@ -2328,7 +2368,7 @@ lwgeom_grid_in_place(LWGEOM *geom, const gridspec *grid)
 
 
 LWGEOM *
-lwgeom_grid(const LWGEOM *lwgeom, const gridspec *grid)
+lwgeom_grid(const LWGEOM *lwgeom, gridspec *grid)
 {
 	LWGEOM *lwgeom_out = lwgeom_clone_deep(lwgeom);
 	lwgeom_grid_in_place(lwgeom_out, grid);
diff --git a/liblwgeom/ptarray.c b/liblwgeom/ptarray.c
index cabf679a9..307888488 100644
--- a/liblwgeom/ptarray.c
+++ b/liblwgeom/ptarray.c
@@ -2088,7 +2088,7 @@ ptarray_startpoint(const POINTARRAY *pa, POINT4D *pt)
  *
  */
 void
-ptarray_grid_in_place(POINTARRAY *pa, const gridspec *grid)
+ptarray_grid_in_place(POINTARRAY *pa, gridspec *grid)
 {
 	uint32_t j = 0;
 	POINT4D *p, *p_out = NULL;
@@ -2108,11 +2108,24 @@ ptarray_grid_in_place(POINTARRAY *pa, const gridspec *grid)
 		if (ndims > 3)
 			m = p->m;
 
-		if (grid->xsize > 0)
-			x = rint((x - grid->ipx) / grid->xsize) * grid->xsize + grid->ipx;
+		/*
+		 * See https://github.com/libgeos/geos/pull/956
+		 * We use scale for rounding when gridsize is < 1 and
+		 * gridsize for rounding when scale < 1.
+		 */
+		if (grid->xsize > 0) {
+			if (grid->xsize < 1)
+				x = rint((x - grid->ipx) * grid->xscale) / grid->xscale + grid->ipx;
+			else
+				x = rint((x - grid->ipx) / grid->xsize) * grid->xsize + grid->ipx;
+		}
 
-		if (grid->ysize > 0)
-			y = rint((y - grid->ipy) / grid->ysize) * grid->ysize + grid->ipy;
+		if (grid->ysize > 0) {
+			if (grid->ysize < 1)
+				y = rint((y - grid->ipy) * grid->yscale) / grid->yscale + grid->ipy;
+			else
+				y = rint((y - grid->ipy) / grid->ysize) * grid->ysize + grid->ipy;
+		}
 
 		/* Read and round this point */
 		/* Z is always in third position */
diff --git a/postgis/mvt.c b/postgis/mvt.c
index 14691b551..da9318c69 100644
--- a/postgis/mvt.c
+++ b/postgis/mvt.c
@@ -144,7 +144,7 @@ static inline uint32_t c_int(enum mvt_cmd_id id, uint32_t count)
 
 static inline uint32_t p_int(int32_t value)
 {
-	return (value << 1) ^ ((int64_t)value >> 31);
+	return (value << 1) ^ (value >> 31);
 }
 
 static uint32_t encode_ptarray(enum mvt_type type, POINTARRAY *pa, uint32_t *buffer, int32_t *px, int32_t *py)
@@ -877,7 +877,7 @@ mvt_clip_and_validate_geos(LWGEOM *lwgeom, uint8_t basic_type, uint32_t extent,
 
 	if (clip_geom)
 	{
-		gridspec grid = {0, 0, 0, 0, 1, 1, 0, 0};
+		gridspec grid = {0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0};
 		GBOX bgbox;
 		bgbox.xmax = bgbox.ymax = (double)extent + (double)buffer;
 		bgbox.xmin = bgbox.ymin = -(double)buffer;
@@ -933,7 +933,7 @@ LWGEOM *mvt_geom(LWGEOM *lwgeom, const GBOX *gbox, uint32_t extent, uint32_t buf
 	bool clip_geom)
 {
 	AFFINE affine = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
-	gridspec grid = {0, 0, 0, 0, 1, 1, 0, 0};
+	gridspec grid = {0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0};
 	double width = gbox->xmax - gbox->xmin;
 	double height = gbox->ymax - gbox->ymin;
 	double fx, fy;
diff --git a/regress/core/regress_proj_pipeline.sql b/regress/core/regress_proj_pipeline.sql
index 2b5b98998..a72c3eed3 100644
--- a/regress/core/regress_proj_pipeline.sql
+++ b/regress/core/regress_proj_pipeline.sql
@@ -15,9 +15,9 @@ SELECT '5', ST_SRID(ST_TransformPipeline('SRID=4326;POINT(174 -37)'::geometry, '
 SELECT '6', ST_SRID(ST_TransformPipeline('SRID=4326;POINT(174 -37)'::geometry, '+proj=pipeline +step +proj=unitconvert +xy_in=deg +xy_out=rad +step +proj=tmerc +lat_0=0 +lon_0=173 +k=0.9996 +x_0=1600000 +y_0=10000000 +ellps=GRS80', 12345));
 
 -- GDA2020 is complicated, check it works
-SELECT '7', ST_AsText(ST_SnapToGrid(ST_TransformPipeline('SRID=4283;POINT(151.2 -33.8)'::geometry, 'urn:ogc:def:coordinateOperation:EPSG::8048'), 0.1));
+SELECT '7', ST_AsText(ST_TransformPipeline('SRID=4283;POINT(151.2 -33.8)'::geometry, 'urn:ogc:def:coordinateOperation:EPSG::8048'),1);
 
 -- testing inverse pipelines; also checks rad->deg on results
-SELECT '8', ST_AsText(ST_SnapToGrid(ST_InverseTransformPipeline('SRID=32631;POINT(426857 5427937)'::geometry, 'urn:ogc:def:coordinateOperation:EPSG::16031'), 0.1));
+SELECT '8', ST_AsText(ST_InverseTransformPipeline('SRID=32631;POINT(426857 5427937)'::geometry, 'urn:ogc:def:coordinateOperation:EPSG::16031'), 1);
 SELECT '9', ST_SRID(ST_InverseTransformPipeline('SRID=32631;POINT(426857 5427937)'::geometry, 'urn:ogc:def:coordinateOperation:EPSG::16031', 12345));
 
diff --git a/regress/core/regress_proj_pipeline_expected b/regress/core/regress_proj_pipeline_expected
index 43834cbd0..8d7891a72 100644
--- a/regress/core/regress_proj_pipeline_expected
+++ b/regress/core/regress_proj_pipeline_expected
@@ -4,6 +4,6 @@ ERROR:  could not parse coordinate operation 'bad coordinate transform pipeline'
 ERROR:  lwgeom_transform_pipeline: Failed to transform
 5|0
 6|12345
-7|POINT(151.20000000000002 -33.800000000000004)
+7|POINT(151.2 -33.8)
 8|POINT(2 49)
 9|12345
diff --git a/regress/core/tickets.sql b/regress/core/tickets.sql
index 40df77830..8228e59ca 100644
--- a/regress/core/tickets.sql
+++ b/regress/core/tickets.sql
@@ -1510,6 +1510,10 @@ SELECT '#5320', ST_SimplifyPreserveTopology('0106000020E864000001000000010300000
 DROP PROCEDURE IF EXISTS p_force_parellel_mode(text);
 SELECT '#5378', ST_SRID( ST_Buffer(ST_GeomFromText('POINT(-94 29.53)', 4269)::geography, 12)::geometry );
 
+SELECT '#5425', ST_AsText(ST_SnapToGrid(
+  ST_SnapToGrid('POINT(1.23456789 9.87654321)'::geometry, 0.001),
+  0.000001) );
+
 SELECT '#5627' AS ticket, bool_and(ST_Intersects(
     'MULTIPOINT(EMPTY,(-378 574))'::geometry,
     geom))
diff --git a/regress/core/tickets_expected b/regress/core/tickets_expected
index f2ebc6e25..e81b530ef 100644
--- a/regress/core/tickets_expected
+++ b/regress/core/tickets_expected
@@ -468,6 +468,7 @@ ERROR:  Line has no points
 ERROR:  Geometry contains invalid coordinates
 ERROR:  Geometry contains invalid coordinates
 #5378|4269
+#5425|POINT(1.235 9.877)
 #5627|t
 #5604|2|POINT(0 0)|2|POINT(-2 0)
 #5639|fullywithin1|t

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

Summary of changes:
 liblwgeom/liblwgeom.h.in                    |  8 ++++--
 liblwgeom/liblwgeom_internal.h              |  2 +-
 liblwgeom/lwgeom.c                          | 44 +++++++++++++++++++++++++++--
 liblwgeom/ptarray.c                         | 23 +++++++++++----
 postgis/mvt.c                               |  6 ++--
 regress/core/regress_proj_pipeline.sql      |  4 +--
 regress/core/regress_proj_pipeline_expected |  2 +-
 regress/core/tickets.sql                    |  4 +++
 regress/core/tickets_expected               |  1 +
 9 files changed, 78 insertions(+), 16 deletions(-)


hooks/post-receive
-- 
PostGIS


More information about the postgis-tickets mailing list