PostGIS  3.4.0dev-r@@SVN_REVISION@@

◆ rt_raster_gdal_contour()

int rt_raster_gdal_contour ( rt_raster  src_raster,
int  src_band,
int  src_srid,
const char *  src_srs,
double  contour_interval,
double  contour_base,
int  fixed_level_count,
double *  fixed_levels,
int  polygonize,
size_t *  ncontours,
struct rt_contour_t **  contours 
)

Return palloc'ed list of contours.

Parameters
src_raster: raster to generate contour from
src_band: band to use as input
src_srid: srid of raster
src_srs: Coordinate reference system string for raster
options: CSList of OPTION=VALUE strings for the contour routine, see https://gdal.org/api/gdal_alg.html?highlight=contour#_CPPv419GDALContourGenerate15GDALRasterBandHddiPdidPvii16GDALProgressFuncPv
ncontours: Output parameter for length of contour list
contours: Output palloc'ed list of contours, caller to free

Definition at line 114 of file rt_gdal.c.

129 {
130  CPLErr cplerr;
131  OGRErr ogrerr;
132  GDALRasterBandH hBand;
133  int nfeatures = 0, i = 0;
134  OGRFeatureH hFeat;
135 
136  /* For building out options list */
137  stringbuffer_t sb;
138  char **papszOptList = NULL;
139 
140  _rti_contour_arg arg;
141  _rti_contour_arg_init(&arg);
142 
143  /* Load raster into GDAL memory */
144  arg.src.ds = rt_raster_to_gdal_mem(src_raster, src_srs, NULL, NULL, 0, &(arg.src.drv), &(arg.src.destroy_drv));
145  /* Extract the desired band */
146  hBand = GDALGetRasterBand(arg.src.ds, src_band);
147 
148  /* Set up the OGR destination data store */
149  arg.dst.srid = src_srid;
150  arg.dst.drv = OGRGetDriverByName("Memory");
151  if (!arg.dst.drv)
152  return _rti_contour_arg_destroy(&arg);
153 
154  arg.dst.ds = OGR_Dr_CreateDataSource(arg.dst.drv, "contour_ds", NULL);
155  if (!arg.dst.ds)
156  return _rti_contour_arg_destroy(&arg);
157 
158  /* Polygonize is 2.4+ only */
159 #if POSTGIS_GDAL_VERSION >= 24
160  arg.dst.gtype = polygonize ? wkbPolygon : wkbLineString;
161 #else
162  arg.dst.gtype = wkbLineString;
163 #endif
164 
165  /* Layer has geometry, elevation, id */
166  arg.dst.lyr = OGR_DS_CreateLayer(arg.dst.ds, "contours", NULL, arg.dst.gtype, NULL);
167  if (!arg.dst.lyr)
168  return _rti_contour_arg_destroy(&arg);
169 
170  /* ID field */
171  OGRFieldDefnH hFldId = OGR_Fld_Create("id", OFTInteger);
172  ogrerr = OGR_L_CreateField(arg.dst.lyr, hFldId, TRUE);
173  if (ogrerr != OGRERR_NONE)
174  return _rti_contour_arg_destroy(&arg);
175 
176  /* ELEVATION field */
177  OGRFieldDefnH hFldElevation = OGR_Fld_Create("elevation", OFTReal);
178  ogrerr = OGR_L_CreateField(arg.dst.lyr, hFldElevation, TRUE);
179  if (ogrerr != OGRERR_NONE)
180  return _rti_contour_arg_destroy(&arg);
181 
182  int use_no_data = 0;
183  double no_data_value = GDALGetRasterNoDataValue(hBand, &use_no_data);
184 
185  // LEVEL_INTERVAL=f
186  // The elevation interval between contours generated.
187  // LEVEL_BASE=f
188  // 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.
189  // LEVEL_EXP_BASE=f
190  // 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.
191  // FIXED_LEVELS=f[,f]*
192  // The list of fixed contour levels at which contours should be generated. This option has precedence on LEVEL_INTERVAL
193  // NODATA=f
194  // 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.
195  // ID_FIELD=d
196  // This will be used as a field index to indicate where a unique id should be written for each feature (contour) written.
197  // ELEV_FIELD=d
198  // 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.
199  // ELEV_FIELD_MIN=d
200  // 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.
201  // ELEV_FIELD_MAX=d
202  // 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.
203  // POLYGONIZE=YES|NO
204 
205  /* Options strings list */
206  stringbuffer_init(&sb);
207 
208  if (use_no_data)
209  stringbuffer_aprintf(&sb, "NODATA=%g ", no_data_value);
210 
211  if (fixed_level_count > 0) {
212  int i = 0;
213  stringbuffer_append(&sb, "FIXED_LEVELS=");
214  for (i = 0; i < fixed_level_count; i++) {
215  if (i) stringbuffer_append_char(&sb, ',');
216  stringbuffer_aprintf(&sb, "%g", fixed_levels[i]);
217  }
218  stringbuffer_append_char(&sb, ' ');
219  }
220  else {
221  stringbuffer_aprintf(&sb, "LEVEL_INTERVAL=%g ", contour_interval);
222  stringbuffer_aprintf(&sb, "LEVEL_BASE=%g ", contour_base);
223  }
224 
225  stringbuffer_aprintf(&sb, "ID_FIELD=%d ", 0);
226  stringbuffer_aprintf(&sb, "ELEV_FIELD=%d ", 1);
227  stringbuffer_aprintf(&sb, "POLYGONIZE=%s ", polygonize ? "YES" : "NO");
228 
229  papszOptList = CSLTokenizeString(stringbuffer_getstring(&sb));
230 
231  // CPLSetConfigOption("OGR_GEOMETRY_ACCEPT_UNCLOSED_RING", "NO");
232 
233  /* Run the contouring routine, filling up the OGR layer */
234  cplerr = GDALContourGenerateEx(
235  hBand,
236  arg.dst.lyr,
237  papszOptList, // Options
238  rt_util_gdal_progress_func, // GDALProgressFunc pfnProgress
239  (void*)"GDALContourGenerateEx" // void *pProgressArg
240  );
241 
242  // /* Run the contouring routine, filling up the OGR layer */
243  // cplerr = GDALContourGenerate(
244  // hBand,
245  // contour_interval, contour_base,
246  // fixed_level_count, fixed_levels,
247  // use_no_data, no_data_value,
248  // arg.dst.lyr, 0, 1, // OGRLayer, idFieldNum, elevFieldNum
249  // NULL, // GDALProgressFunc pfnProgress
250  // NULL // void *pProgressArg
251  // );
252 
253  if (cplerr >= CE_Failure) {
254  return _rti_contour_arg_destroy(&arg); // FALSE
255  }
256 
257  /* Convert the OGR layer into PostGIS geometries */
258  nfeatures = OGR_L_GetFeatureCount(arg.dst.lyr, TRUE);
259  if (nfeatures < 0)
260  return _rti_contour_arg_destroy(&arg);
261 
262  *contours = rtalloc(sizeof(struct rt_contour_t) * nfeatures);
263  OGR_L_ResetReading(arg.dst.lyr);
264  while ((hFeat = OGR_L_GetNextFeature(arg.dst.lyr))) {
265  size_t szWkb;
266  unsigned char *bufWkb;
267  struct rt_contour_t contour;
268  OGRGeometryH hGeom;
269  LWGEOM *geom;
270 
271  /* Somehow we're still iterating, should not happen. */
272  if(i >= nfeatures) break;
273 
274  /* Store elevation/id */
275  contour.id = OGR_F_GetFieldAsInteger(hFeat, 0);
276  contour.elevation = OGR_F_GetFieldAsDouble(hFeat, 1);
277  /* Convert OGR geometry to LWGEOM via WKB */
278  if (!(hGeom = OGR_F_GetGeometryRef(hFeat))) continue;
279  szWkb = OGR_G_WkbSize(hGeom);
280  bufWkb = rtalloc(szWkb);
281  if (OGR_G_ExportToWkb(hGeom, wkbNDR, bufWkb) != OGRERR_NONE) continue;
282  /* Reclaim feature and associated geometry memory */
283  OGR_F_Destroy(hFeat);
284  geom = lwgeom_from_wkb(bufWkb, szWkb, LW_PARSER_CHECK_NONE);
286  contour.geom = gserialized_from_lwgeom(geom, NULL);
287  lwgeom_free(geom);
288  rtdealloc(bufWkb);
289  (*contours)[i++] = contour;
290  }
291 
292  /* Return total number of contours saved */
293  *ncontours = i;
294 
295  /* Free all the non-database allocated structures */
298 
299  /* Done */
300  return TRUE;
301 }
#define TRUE
Definition: dbfopen.c:73
GSERIALIZED * gserialized_from_lwgeom(LWGEOM *geom, size_t *size)
Allocate a new GSERIALIZED from an LWGEOM.
Definition: gserialized.c:222
void lwgeom_set_srid(LWGEOM *geom, int32_t srid)
Set the SRID on an LWGEOM For collections, only the parent gets an SRID, all the children get SRID_UN...
Definition: lwgeom.c:1547
void lwgeom_free(LWGEOM *geom)
Definition: lwgeom.c:1155
#define LW_PARSER_CHECK_NONE
Definition: liblwgeom.h:2114
LWGEOM * lwgeom_from_wkb(const uint8_t *wkb, const size_t wkb_size, const char check)
WKB inputs must have a declared size, to prevent malformed WKB from reading off the end of the memory...
Definition: lwin_wkb.c:834
void * rtalloc(size_t size)
Wrappers used for managing memory.
Definition: rt_context.c:191
void rtdealloc(void *mem)
Definition: rt_context.c:206
GDALDatasetH rt_raster_to_gdal_mem(rt_raster raster, const char *srs, uint32_t *bandNums, int *excludeNodataValues, int count, GDALDriverH *rtn_drv, int *destroy_rtn_drv)
Return GDAL dataset using GDAL MEM driver from raster.
Definition: rt_raster.c:1935
src_band
Definition: pixval.py:76
static int _rti_contour_arg_destroy(_rti_contour_arg *arg)
Definition: rt_gdal.c:85
int rt_util_gdal_progress_func(double dfComplete, const char *pszMessage, void *pProgressArg)
Definition: rt_gdal.c:58
static void _rti_contour_arg_init(_rti_contour_arg *arg)
Definition: rt_gdal.c:77
void stringbuffer_release(stringbuffer_t *s)
Definition: stringbuffer.c:48
int stringbuffer_aprintf(stringbuffer_t *s, const char *fmt,...)
Appends a formatted string to the current string buffer, using the format and argument list provided.
Definition: stringbuffer.c:247
void stringbuffer_init(stringbuffer_t *s)
Definition: stringbuffer.c:54
const char * stringbuffer_getstring(stringbuffer_t *s)
Returns a reference to the internal string being managed by the stringbuffer.
Definition: stringbuffer.c:122
static void stringbuffer_append(stringbuffer_t *s, const char *a)
Append the specified string to the stringbuffer_t.
Definition: stringbuffer.h:105
static void stringbuffer_append_char(stringbuffer_t *s, char c)
Definition: stringbuffer.h:119
GDALDatasetH ds
Definition: rt_gdal.c:38
GDALDriverH drv
Definition: rt_gdal.c:39
struct _rti_contour_arg::@14 dst
OGRLayerH lyr
Definition: rt_gdal.c:46
OGRwkbGeometryType gtype
Definition: rt_gdal.c:48
struct _rti_contour_arg::@13 src
GSERIALIZED * geom
Definition: librtcore.h:1749

References _rti_contour_arg_destroy(), _rti_contour_arg_init(), _rti_contour_arg::destroy_drv, _rti_contour_arg::drv, _rti_contour_arg::ds, _rti_contour_arg::dst, rt_contour_t::elevation, rt_contour_t::geom, gserialized_from_lwgeom(), _rti_contour_arg::gtype, rt_contour_t::id, LW_PARSER_CHECK_NONE, lwgeom_free(), lwgeom_from_wkb(), lwgeom_set_srid(), _rti_contour_arg::lyr, rt_raster_to_gdal_mem(), rt_util_gdal_progress_func(), rtalloc(), rtdealloc(), _rti_contour_arg::src, pixval::src_band, _rti_contour_arg::srid, stringbuffer_append(), stringbuffer_append_char(), stringbuffer_aprintf(), stringbuffer_getstring(), stringbuffer_init(), stringbuffer_release(), and TRUE.

Referenced by RASTER_Contour().

Here is the call graph for this function:
Here is the caller graph for this function: