[postgis-tickets] [SCM] PostGIS branch master updated. 3.3.0rc2-1177-g43880f9ab

git at osgeo.org git at osgeo.org
Fri Jul 7 08:10:18 PDT 2023


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  43880f9abf66d9d5c17f8374a4c6de781fe76a72 (commit)
      from  c2542df35da0fb088dff14b629823e9a793d9f58 (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 43880f9abf66d9d5c17f8374a4c6de781fe76a72
Author: Paul Ramsey <pramsey at cleverelephant.ca>
Date:   Fri Jul 7 08:09:29 2023 -0700

    Upgrade ST_Contour to respect the polygonize parameter,
    passing it on to the GDAL contouring routine. Add support
    for user interruption of contouring, since with polygonization
    the process can run quite a long time.

diff --git a/doc/reference_raster.xml b/doc/reference_raster.xml
index c5f3f94d9..6912089ee 100644
--- a/doc/reference_raster.xml
+++ b/doc/reference_raster.xml
@@ -1353,11 +1353,6 @@ WHERE short_name = 'GTiff') As g;
             When the <varname>fixed_levels</varname> parameter is a non-empty
             array, the <varname>level_interval</varname> and <varname>level_base</varname> parameters are ignored.
         </para>
-        <para>
-            The <varname>polygonize</varname> parameter currently has no effect.
-            Use the <link linkend="ST_Polygonize">ST_Polygonize</link> function
-            to convert contours into polygons.
-        </para>
         <para>
             Return values are a set of records with the following attributes:
         </para>
diff --git a/liblwgeom/gserialized2.c b/liblwgeom/gserialized2.c
index 353c107c1..e9dc77bb5 100644
--- a/liblwgeom/gserialized2.c
+++ b/liblwgeom/gserialized2.c
@@ -1201,8 +1201,6 @@ GSERIALIZED* gserialized2_from_lwgeom(LWGEOM *geom, size_t *size)
 	return g;
 }
 
-// xxxx continue reviewing extended flags content from here
-
 /***********************************************************************
 * De-serialize GSERIALIZED into an LWGEOM.
 */
diff --git a/raster/rt_core/librtcore.h b/raster/rt_core/librtcore.h
index 7014e4f53..8f4cd82b1 100644
--- a/raster/rt_core/librtcore.h
+++ b/raster/rt_core/librtcore.h
@@ -121,7 +121,7 @@
 #include <float.h> /* for FLT_EPSILON, DBL_EPSILON and float type limits */
 #include <limits.h> /* for integer type limits */
 
-#include "liblwgeom.h"
+#include "liblwgeom_internal.h"
 
 #include "gdal.h"
 #include "gdalgrid.h" /* for ParseAlgorithmAndOptions */
@@ -2335,6 +2335,13 @@ GDALDatasetH
 rt_util_gdal_open(const char *fn, GDALAccess fn_access, int shared);
 
 
+/*
+    Callback for GDAL functions to hook into interrupt system
+*/
+int
+rt_util_gdal_progress_func(double dfComplete, const char *pszMessage, void *pProgressArg);
+
+
 void
 rt_util_from_ogr_envelope(
 	OGREnvelope	env,
diff --git a/raster/rt_core/rt_gdal.c b/raster/rt_core/rt_gdal.c
index 2b5fbe9c3..1d12d7dcc 100644
--- a/raster/rt_core/rt_gdal.c
+++ b/raster/rt_core/rt_gdal.c
@@ -26,9 +26,10 @@
 
 #include "librtcore.h"
 #include "librtcore_internal.h"
+#include "stringbuffer.h"
 
 /******************************************************************************
-* rt_raster_gdal_warp()
+* rt_raster_gdal_contour()
 ******************************************************************************/
 
 typedef struct
@@ -50,6 +51,28 @@ typedef struct
 } _rti_contour_arg;
 
 
+/* ---------------------------------------------------------------- */
+/*  GDAL progress callback for interrupt handling */
+/* ---------------------------------------------------------------- */
+
+int rt_util_gdal_progress_func(
+	double dfComplete,
+	const char *pszMessage,
+	void *pProgressArg)
+{
+	(void)dfComplete;
+	(void)pszMessage;
+
+	if (_lwgeom_interrupt_requested)
+	{
+		// rtwarn("%s interrupted at %g", (const char*)pProgressArg, dfComplete);
+		_lwgeom_interrupt_requested = 0;
+		return FALSE;
+	}
+	else
+		return TRUE;
+}
+
 static void
 _rti_contour_arg_init(_rti_contour_arg* arg)
 {
@@ -80,9 +103,11 @@ _rti_contour_arg_destroy(_rti_contour_arg* arg)
 /**
  * Return palloc'ed list of contours.
  * @param src_raster : raster to generate contour from
+ * @param src_band : band to use as input
+ * @param src_srid : srid of raster
+ * @param src_srs : Coordinate reference system string for raster
  * @param options : CSList of OPTION=VALUE strings for the
  *   contour routine, see https://gdal.org/api/gdal_alg.html?highlight=contour#_CPPv419GDALContourGenerate15GDALRasterBandHddiPdidPvii16GDALProgressFuncPv
- * @param src_srs : Coordinate reference system string for raster
  * @param ncontours : Output parameter for length of contour list
  * @param contours : Output palloc'ed list of contours, caller to free
  */
@@ -108,6 +133,10 @@ int rt_raster_gdal_contour(
 	int nfeatures = 0, i = 0;
 	OGRFeatureH hFeat;
 
+	/* For building out options list */
+	stringbuffer_t sb;
+	char **papszOptList = NULL;
+
 	_rti_contour_arg arg;
 	_rti_contour_arg_init(&arg);
 
@@ -150,29 +179,80 @@ int rt_raster_gdal_contour(
 	if (ogrerr != OGRERR_NONE)
 		return _rti_contour_arg_destroy(&arg);
 
-	// GDALContourGenerate( GDALRasterBandH hBand,
-	//   double dfContourInterval, double dfContourBase,
-	//   int nFixedLevelCount, double *padfFixedLevels,
-	//   int bUseNoData, double dfNoDataValue,
-	//   void *hLayer, int iIDField, int iElevField,
-	//   GDALProgressFunc pfnProgress, void *pProgressArg );
-
 	int use_no_data = 0;
-	double no_data_value = GDALGetRasterNoDataValue(hBand, &use_no_data);;
+	double no_data_value = GDALGetRasterNoDataValue(hBand, &use_no_data);
+
+	// LEVEL_INTERVAL=f
+	//   The elevation interval between contours generated.
+	// LEVEL_BASE=f
+	//   The "base" relative to which contour intervals are applied. This is normally zero, but could be different. To generate 10m contours at 5, 15, 25, ... the LEVEL_BASE would be 5.
+	// LEVEL_EXP_BASE=f
+	//   If greater than 0, contour levels are generated on an exponential scale. Levels will then be generated by LEVEL_EXP_BASE^k where k is a positive integer.
+	// FIXED_LEVELS=f[,f]*
+	//   The list of fixed contour levels at which contours should be generated. This option has precedence on LEVEL_INTERVAL
+	// NODATA=f
+	//   The value to use as a "nodata" value. That is, a pixel value which should be ignored in generating contours as if the value of the pixel were not known.
+	// ID_FIELD=d
+	//   This will be used as a field index to indicate where a unique id should be written for each feature (contour) written.
+	// ELEV_FIELD=d
+	//   This will be used as a field index to indicate where the elevation value of the contour should be written. Only used in line contouring mode.
+	// ELEV_FIELD_MIN=d
+	//   This will be used as a field index to indicate where the minimum elevation value of the polygon contour should be written. Only used in polygonal contouring mode.
+	// ELEV_FIELD_MAX=d
+	//   This will be used as a field index to indicate where the maximum elevation value of the polygon contour should be written. Only used in polygonal contouring mode.
+	// POLYGONIZE=YES|NO
+
+	/* Options strings list */
+	stringbuffer_init(&sb);
+
+	if (use_no_data)
+		stringbuffer_aprintf(&sb, "NODATA=%g ", no_data_value);
+
+	if (fixed_level_count > 0) {
+		int i = 0;
+		stringbuffer_append(&sb, "FIXED_LEVELS=");
+		for (i = 0; i < fixed_level_count; i++) {
+			if (i) stringbuffer_append_char(&sb, ',');
+			stringbuffer_aprintf(&sb, "%g", fixed_levels[i]);
+		}
+		stringbuffer_append_char(&sb, ' ');
+	}
+	else {
+		stringbuffer_aprintf(&sb, "LEVEL_INTERVAL=%g ", contour_interval);
+		stringbuffer_aprintf(&sb, "LEVEL_BASE=%g ", contour_base);
+	}
+
+	stringbuffer_aprintf(&sb, "ID_FIELD=%d ", 0);
+	stringbuffer_aprintf(&sb, "ELEV_FIELD=%d ", 1);
+	stringbuffer_aprintf(&sb, "POLYGONIZE=%s ", polygonize ? "YES" : "NO");
+
+	papszOptList = CSLTokenizeString(stringbuffer_getstring(&sb));
+
+	// CPLSetConfigOption("OGR_GEOMETRY_ACCEPT_UNCLOSED_RING", "NO");
 
 	/* Run the contouring routine, filling up the OGR layer */
-	cplerr = GDALContourGenerate(
+	cplerr = GDALContourGenerateEx(
 		hBand,
-		contour_interval, contour_base,
-		fixed_level_count, fixed_levels,
-		use_no_data, no_data_value,
-		arg.dst.lyr, 0, 1, // OGRLayer, idFieldNum, elevFieldNum
-		NULL,              // GDALProgressFunc pfnProgress
-		NULL               // void *pProgressArg
+		arg.dst.lyr,
+		papszOptList,      // Options
+		rt_util_gdal_progress_func,  // GDALProgressFunc pfnProgress
+		(void*)"GDALContourGenerateEx" // void *pProgressArg
 		);
 
-	if (cplerr != CE_None)
-		return _rti_contour_arg_destroy(&arg);
+	// /* Run the contouring routine, filling up the OGR layer */
+	// cplerr = GDALContourGenerate(
+	// 	hBand,
+	// 	contour_interval, contour_base,
+	// 	fixed_level_count, fixed_levels,
+	// 	use_no_data, no_data_value,
+	// 	arg.dst.lyr, 0, 1, // OGRLayer, idFieldNum, elevFieldNum
+	// 	NULL,              // GDALProgressFunc pfnProgress
+	// 	NULL               // void *pProgressArg
+	// 	);
+
+	if (cplerr >= CE_Failure) {
+		return _rti_contour_arg_destroy(&arg); // FALSE
+	}
 
 	/* Convert the OGR layer into PostGIS geometries */
 	nfeatures = OGR_L_GetFeatureCount(arg.dst.lyr, TRUE);
@@ -214,6 +294,7 @@ int rt_raster_gdal_contour(
 
 	/* Free all the non-database allocated structures */
 	_rti_contour_arg_destroy(&arg);
+	stringbuffer_release(&sb);
 
 	/* Done */
 	return TRUE;
diff --git a/raster/rt_pg/rtpg_gdal.c b/raster/rt_pg/rtpg_gdal.c
index 9a982f36e..039ea61d5 100644
--- a/raster/rt_pg/rtpg_gdal.c
+++ b/raster/rt_pg/rtpg_gdal.c
@@ -582,8 +582,7 @@ Datum RASTER_Contour(PG_FUNCTION_ARGS)
 
 		/* No-op on bad return */
 		if (rv == FALSE) {
-			funcctx = SRF_PERCALL_SETUP();
-			SRF_RETURN_DONE(funcctx);
+			PG_RETURN_NULL();
 		}
 
 		funcctx->user_fctx = result;
diff --git a/raster/rt_pg/rtpostgis.c b/raster/rt_pg/rtpostgis.c
index d591f2c7d..7ae30b93e 100644
--- a/raster/rt_pg/rtpostgis.c
+++ b/raster/rt_pg/rtpostgis.c
@@ -129,18 +129,26 @@
  *   datum is copied for use.
  *****************************************************************************/
 
-#include <postgres.h> /* for palloc */
-#include <fmgr.h> /* for PG_MODULE_MAGIC */
+/* PostgreSQL */
+#include "postgres.h" /* for palloc */
+#include "fmgr.h" /* for PG_MODULE_MAGIC */
+#include "libpq/pqsignal.h"
 #include "utils/guc.h"
+#include "utils/builtins.h"
 #include "utils/memutils.h"
+#include "utils/elog.h"
 
-#include "../../postgis_config.h"
+/* PostGIS */
+#include "postgis_config.h"
+#include "liblwgeom.h"
 #include "lwgeom_pg.h"
+#include "stringlist.h"
+#include "optionlist.h"
 
+/* PostGIS Raster */
 #include "rtpostgis.h"
 #include "rtpg_internal.h"
-#include "stringlist.h"
-#include "optionlist.h"
+
 
 #ifndef __GNUC__
 # define __attribute__ (x)
@@ -638,6 +646,48 @@ rtpg_assignHookEnableOutDBRasters(bool enable, void *extra) {
 }
 
 
+
+/*
+* Machinery for intercepting the system SIGINT
+* handler so we can cancel long-running GDAL operations
+* via the progress handlers.
+*/
+static pqsigfunc coreIntHandler = 0;
+
+#ifdef WIN32
+static void interruptCallback() {
+  if (UNBLOCKED_SIGNAL_QUEUE())
+    pgwin32_dispatch_queued_signals();
+}
+#endif
+
+
+/*
+* This is the interrupt capture for this module.
+* Before handing off the signal to the core, it
+* sets the interrupt flag for currently running
+* functions.
+*/
+static void
+handleInterrupt(int sig)
+{
+	/*
+	* NOTE: printf here would be dangerous, see
+	* https://trac.osgeo.org/postgis/ticket/3644
+	*/
+	// printf("postgis_raster interrupt requested\n"); fflush(stdout);
+
+	/* Request interruption of liblwgeom as well */
+	lwgeom_request_interrupt();
+
+	/* Pass control into the usual core handler */
+	if (coreIntHandler) {
+		(*coreIntHandler)(sig);
+	}
+}
+
+
+
 /* Module load callback */
 void
 _PG_init(void) {
@@ -645,6 +695,15 @@ _PG_init(void) {
 	bool boot_postgis_enable_outdb_rasters = false;
 	MemoryContext old_context;
 
+	/* Set up interrupt capture */
+	coreIntHandler = pqsignal(SIGINT, handleInterrupt);
+
+#ifdef WIN32
+ 	GEOS_interruptRegisterCallback(interruptCallback);
+ 	lwgeom_register_interrupt_callback(interruptCallback);
+#endif
+
+
 	/*
 	 * Change to context for memory allocation calls like palloc() in the
 	 * extension initialization routine
@@ -804,9 +863,12 @@ _PG_init(void) {
 void
 _PG_fini(void) {
 
-	MemoryContext old_context;
+	MemoryContext old_context = MemoryContextSwitchTo(TopMemoryContext);
 
-	old_context = MemoryContextSwitchTo(TopMemoryContext);
+	elog(NOTICE, "Goodbye from PostGIS Raster %s", POSTGIS_VERSION);
+
+	/* Return SIGINT handling to core */
+	pqsignal(SIGINT, coreIntHandler);
 
 	/* Clean up */
 	pfree(env_postgis_gdal_enabled_drivers);
diff --git a/sfcgal/lwgeom_sfcgal.c b/sfcgal/lwgeom_sfcgal.c
index 041f9d034..e85e7ee9a 100644
--- a/sfcgal/lwgeom_sfcgal.c
+++ b/sfcgal/lwgeom_sfcgal.c
@@ -21,18 +21,19 @@
  * Copyright 2012-2020 Oslandia <infos at oslandia.com>
  *
  **********************************************************************/
+
 #include "SFCGAL/capi/sfcgal_c.h"
+
 #include "postgres.h"
 #include "fmgr.h"
+#include "libpq/pqsignal.h"
 #include "utils/builtins.h"
+#include "utils/elog.h"
+#include "utils/guc.h"
+
 #include "lwgeom_pg.h"
 #include "lwgeom_sfcgal.h"
 #include "../postgis_config.h"
-
-
-#include "utils/elog.h"
-#include "utils/guc.h"
-#include "libpq/pqsignal.h"
 #include "../liblwgeom/liblwgeom.h"
 
 /*

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

Summary of changes:
 doc/reference_raster.xml   |   5 --
 liblwgeom/gserialized2.c   |   2 -
 raster/rt_core/librtcore.h |   9 +++-
 raster/rt_core/rt_gdal.c   | 119 +++++++++++++++++++++++++++++++++++++--------
 raster/rt_pg/rtpg_gdal.c   |   3 +-
 raster/rt_pg/rtpostgis.c   |  76 ++++++++++++++++++++++++++---
 sfcgal/lwgeom_sfcgal.c     |  11 +++--
 7 files changed, 184 insertions(+), 41 deletions(-)


hooks/post-receive
-- 
PostGIS


More information about the postgis-tickets mailing list