PostGIS  3.7.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
options: CSList of OPTION=VALUE strings for the contour routine, see https://gdal.org/api/gdal_alg.html?highlight=contour#_CPPv419GDALContourGenerate15GDALRasterBandHddiPdidPvii16GDALProgressFuncPv
src_srs: Coordinate reference system string for raster
ncontours: Output parameter for length of contour list
contours: palloc'ed list of contours, caller to free
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  const char* elev_field = polygonize ? "ELEV_FIELD_MIN" : "ELEV_FIELD";
140 
141  _rti_contour_arg arg;
142  _rti_contour_arg_init(&arg);
143 
144  /* Load raster into GDAL memory */
145  arg.src.ds = rt_raster_to_gdal_mem(src_raster, src_srs, NULL, NULL, 0, &(arg.src.drv), &(arg.src.destroy_drv));
146  /* Extract the desired band */
147  hBand = GDALGetRasterBand(arg.src.ds, src_band);
148 
149  /* Set up the OGR destination data store */
150  arg.dst.srid = src_srid;
151  arg.dst.drv = OGRGetDriverByName("Memory");
152  if (!arg.dst.drv)
153  return _rti_contour_arg_destroy(&arg);
154 
155  arg.dst.ds = OGR_Dr_CreateDataSource(arg.dst.drv, "contour_ds", NULL);
156  if (!arg.dst.ds)
157  return _rti_contour_arg_destroy(&arg);
158 
159  /* Polygonize is 2.4+ only */
160 #if POSTGIS_GDAL_VERSION >= 20400
161  arg.dst.gtype = polygonize ? wkbPolygon : wkbLineString;
162 #else
163  arg.dst.gtype = wkbLineString;
164 #endif
165 
166  /* Layer has geometry, elevation, id */
167  arg.dst.lyr = OGR_DS_CreateLayer(arg.dst.ds, "contours", NULL, arg.dst.gtype, NULL);
168  if (!arg.dst.lyr)
169  return _rti_contour_arg_destroy(&arg);
170 
171  /* ID field */
172  OGRFieldDefnH hFldId = OGR_Fld_Create("id", OFTInteger);
173  ogrerr = OGR_L_CreateField(arg.dst.lyr, hFldId, TRUE);
174  if (ogrerr != OGRERR_NONE)
175  return _rti_contour_arg_destroy(&arg);
176 
177  /* ELEVATION field */
178  OGRFieldDefnH hFldElevation = OGR_Fld_Create("elevation", OFTReal);
179  ogrerr = OGR_L_CreateField(arg.dst.lyr, hFldElevation, TRUE);
180  if (ogrerr != OGRERR_NONE)
181  return _rti_contour_arg_destroy(&arg);
182 
183  int use_no_data = 0;
184  double no_data_value = GDALGetRasterNoDataValue(hBand, &use_no_data);
185 
186  // LEVEL_INTERVAL=f
187  // The elevation interval between contours generated.
188  // LEVEL_BASE=f
189  // 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.
190  // LEVEL_EXP_BASE=f
191  // 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.
192  // FIXED_LEVELS=f[,f]*
193  // The list of fixed contour levels at which contours should be generated. This option has precedence on LEVEL_INTERVAL
194  // NODATA=f
195  // 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.
196  // ID_FIELD=d
197  // This will be used as a field index to indicate where a unique id should be written for each feature (contour) written.
198  // ELEV_FIELD=d
199  // 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.
200  // ELEV_FIELD_MIN=d
201  // 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.
202  // ELEV_FIELD_MAX=d
203  // 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.
204  // POLYGONIZE=YES|NO
205 
206  /* Options strings list */
207  stringbuffer_init(&sb);
208 
209  if (use_no_data)
210  stringbuffer_aprintf(&sb, "NODATA=%g ", no_data_value);
211 
212  if (fixed_level_count > 0) {
213  int i = 0;
214  stringbuffer_append(&sb, "FIXED_LEVELS=");
215  for (i = 0; i < fixed_level_count; i++) {
216  if (i) stringbuffer_append_char(&sb, ',');
217  stringbuffer_aprintf(&sb, "%g", fixed_levels[i]);
218  }
219  stringbuffer_append_char(&sb, ' ');
220  }
221  else {
222  stringbuffer_aprintf(&sb, "LEVEL_INTERVAL=%g ", contour_interval);
223  stringbuffer_aprintf(&sb, "LEVEL_BASE=%g ", contour_base);
224  }
225 
226  stringbuffer_aprintf(&sb, "ID_FIELD=%d ", 0);
227  stringbuffer_aprintf(&sb, "%s=%d ", elev_field, 1);
228 
229  stringbuffer_aprintf(&sb, "POLYGONIZE=%s ", polygonize ? "YES" : "NO");
230 
231  papszOptList = CSLTokenizeString(stringbuffer_getstring(&sb));
232 
233  // CPLSetConfigOption("OGR_GEOMETRY_ACCEPT_UNCLOSED_RING", "NO");
234 
235  /* Run the contouring routine, filling up the OGR layer */
236  cplerr = GDALContourGenerateEx(
237  hBand,
238  arg.dst.lyr,
239  papszOptList, // Options
240  rt_util_gdal_progress_func, // GDALProgressFunc pfnProgress
241  (void*)"GDALContourGenerateEx" // void *pProgressArg
242  );
243 
244  // /* Run the contouring routine, filling up the OGR layer */
245  // cplerr = GDALContourGenerate(
246  // hBand,
247  // contour_interval, contour_base,
248  // fixed_level_count, fixed_levels,
249  // use_no_data, no_data_value,
250  // arg.dst.lyr, 0, 1, // OGRLayer, idFieldNum, elevFieldNum
251  // NULL, // GDALProgressFunc pfnProgress
252  // NULL // void *pProgressArg
253  // );
254 
255  if (cplerr >= CE_Failure) {
256  return _rti_contour_arg_destroy(&arg); // FALSE
257  }
258 
259  /* Convert the OGR layer into PostGIS geometries */
260  nfeatures = OGR_L_GetFeatureCount(arg.dst.lyr, TRUE);
261  if (nfeatures < 0)
262  return _rti_contour_arg_destroy(&arg);
263 
264  *contours = rtalloc(sizeof(struct rt_contour_t) * nfeatures);
265  OGR_L_ResetReading(arg.dst.lyr);
266  while ((hFeat = OGR_L_GetNextFeature(arg.dst.lyr))) {
267  size_t szWkb;
268  unsigned char *bufWkb;
269  struct rt_contour_t contour;
270  OGRGeometryH hGeom;
271  LWGEOM *geom;
272 
273  /* Somehow we're still iterating, should not happen. */
274  if(i >= nfeatures) break;
275 
276  /* Store elevation/id */
277  contour.id = OGR_F_GetFieldAsInteger(hFeat, 0);
278  contour.elevation = OGR_F_GetFieldAsDouble(hFeat, 1);
279  /* Convert OGR geometry to LWGEOM via WKB */
280  if (!(hGeom = OGR_F_GetGeometryRef(hFeat))) continue;
281  szWkb = OGR_G_WkbSize(hGeom);
282  bufWkb = rtalloc(szWkb);
283  if (OGR_G_ExportToWkb(hGeom, wkbNDR, bufWkb) != OGRERR_NONE) continue;
284  /* Reclaim feature and associated geometry memory */
285  OGR_F_Destroy(hFeat);
286  geom = lwgeom_from_wkb(bufWkb, szWkb, LW_PARSER_CHECK_NONE);
287  if (!geom) rterror("%s: invalid wkb", __func__);
289  contour.geom = gserialized_from_lwgeom(geom, NULL);
290  lwgeom_free(geom);
291  rtdealloc(bufWkb);
292  (*contours)[i++] = contour;
293  }
294 
295  /* Return total number of contours saved */
296  *ncontours = i;
297 
298  /* Free all the non-database allocated structures */
301 
302  /* Done */
303  return TRUE;
304 }
#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:251
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:1610
void lwgeom_free(LWGEOM *geom)
Definition: lwgeom.c:1218
#define LW_PARSER_CHECK_NONE
Definition: liblwgeom.h:2146
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:842
void rterror(const char *fmt,...) __attribute__((format(printf
Wrappers used for reporting errors and info.
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:1813
src_band
Definition: pixval.py:77
static int _rti_contour_arg_destroy(_rti_contour_arg *arg)
Definition: rt_gdal.c:85
static 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:254
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:125
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
struct _rti_contour_arg::@14 src
GDALDatasetH ds
Definition: rt_gdal.c:38
GDALDriverH drv
Definition: rt_gdal.c:39
OGRLayerH lyr
Definition: rt_gdal.c:46
OGRwkbGeometryType gtype
Definition: rt_gdal.c:48
struct _rti_contour_arg::@15 dst
GSERIALIZED * geom
Definition: librtcore.h:1775

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(), rterror(), _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: