PostGIS 3.7.0dev-r@@SVN_REVISION@@
Loading...
Searching...
No Matches

◆ 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 119 of file rt_gdal.c.

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

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, _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: