PostGIS  3.3.9dev-r@@SVN_REVISION@@
rt_gdal.c
Go to the documentation of this file.
1 /*
2  *
3  * WKTRaster - Raster Types for PostGIS
4  * http://trac.osgeo.org/postgis/wiki/WKTRaster
5  *
6  * Copyright (C) 2021 Paul Ramsey <pramsey@cleverelephant.ca>
7  *
8  * This program is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU General Public License
10  * as published by the Free Software Foundation; either version 2
11  * of the License, or (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program; if not, write to the Free Software Foundation,
20  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
21  *
22  */
23 
24 #include "../../postgis_config.h"
25 /* #define POSTGIS_DEBUG_LEVEL 4 */
26 
27 #include "librtcore.h"
28 #include "librtcore_internal.h"
29 
30 /******************************************************************************
31 * rt_raster_gdal_warp()
32 ******************************************************************************/
33 
34 typedef struct
35 {
36  struct {
37  GDALDatasetH ds;
38  GDALDriverH drv;
40  } src;
41 
42  struct {
43  OGRSFDriverH drv;
44  OGRDataSourceH ds;
45  OGRLayerH lyr;
46  int srid;
47  OGRwkbGeometryType gtype;
48  } dst;
49 
51 
52 
53 static void
55 {
56  memset(arg, 0, sizeof(_rti_contour_arg));
57  return;
58 }
59 
60 
61 static int
63 {
64  if(arg->src.ds != NULL)
65  GDALClose(arg->src.ds);
66 
67  if (arg->src.drv != NULL && arg->src.destroy_drv) {
68  GDALDeregisterDriver(arg->src.drv);
69  GDALDestroyDriver(arg->src.drv);
70  }
71 
72  if (arg->dst.ds != NULL)
73  OGR_DS_Destroy(arg->dst.ds);
74 
75  return FALSE;
76 }
77 
78 
79 
90  /* input parameters */
91  rt_raster src_raster,
92  int src_band,
93  int src_srid,
94  const char* src_srs,
95  double contour_interval,
96  double contour_base,
97  int fixed_level_count,
98  double *fixed_levels,
99  int polygonize,
100  /* output parameters */
101  size_t *ncontours,
102  struct rt_contour_t **contours
103  )
104 {
105  CPLErr cplerr;
106  OGRErr ogrerr;
107  GDALRasterBandH hBand;
108  int nfeatures = 0, i = 0;
109  OGRFeatureH hFeat;
110 
111  _rti_contour_arg arg;
112  _rti_contour_arg_init(&arg);
113 
114  /* Load raster into GDAL memory */
115  arg.src.ds = rt_raster_to_gdal_mem(src_raster, src_srs, NULL, NULL, 0, &(arg.src.drv), &(arg.src.destroy_drv));
116  /* Extract the desired band */
117  hBand = GDALGetRasterBand(arg.src.ds, src_band);
118 
119  /* Set up the OGR destination data store */
120  arg.dst.srid = src_srid;
121  arg.dst.drv = OGRGetDriverByName("Memory");
122  if (!arg.dst.drv)
123  return _rti_contour_arg_destroy(&arg);
124 
125  arg.dst.ds = OGR_Dr_CreateDataSource(arg.dst.drv, "contour_ds", NULL);
126  if (!arg.dst.ds)
127  return _rti_contour_arg_destroy(&arg);
128 
129  /* Polygonize is 2.4+ only */
130 #if POSTGIS_GDAL_VERSION >= 24
131  arg.dst.gtype = polygonize ? wkbPolygon : wkbLineString;
132 #else
133  arg.dst.gtype = wkbLineString;
134 #endif
135 
136  /* Layer has geometry, elevation, id */
137  arg.dst.lyr = OGR_DS_CreateLayer(arg.dst.ds, "contours", NULL, arg.dst.gtype, NULL);
138  if (!arg.dst.lyr)
139  return _rti_contour_arg_destroy(&arg);
140 
141  /* ID field */
142  OGRFieldDefnH hFldId = OGR_Fld_Create("id", OFTInteger);
143  ogrerr = OGR_L_CreateField(arg.dst.lyr, hFldId, TRUE);
144  if (ogrerr != OGRERR_NONE)
145  return _rti_contour_arg_destroy(&arg);
146 
147  /* ELEVATION field */
148  OGRFieldDefnH hFldElevation = OGR_Fld_Create("elevation", OFTReal);
149  ogrerr = OGR_L_CreateField(arg.dst.lyr, hFldElevation, TRUE);
150  if (ogrerr != OGRERR_NONE)
151  return _rti_contour_arg_destroy(&arg);
152 
153  // GDALContourGenerate( GDALRasterBandH hBand,
154  // double dfContourInterval, double dfContourBase,
155  // int nFixedLevelCount, double *padfFixedLevels,
156  // int bUseNoData, double dfNoDataValue,
157  // void *hLayer, int iIDField, int iElevField,
158  // GDALProgressFunc pfnProgress, void *pProgressArg );
159 
160  int use_no_data = 0;
161  double no_data_value = GDALGetRasterNoDataValue(hBand, &use_no_data);;
162 
163  /* Run the contouring routine, filling up the OGR layer */
164  cplerr = GDALContourGenerate(
165  hBand,
166  contour_interval, contour_base,
167  fixed_level_count, fixed_levels,
168  use_no_data, no_data_value,
169  arg.dst.lyr, 0, 1, // OGRLayer, idFieldNum, elevFieldNum
170  NULL, // GDALProgressFunc pfnProgress
171  NULL // void *pProgressArg
172  );
173 
174  if (cplerr != CE_None)
175  return _rti_contour_arg_destroy(&arg);
176 
177  /* Convert the OGR layer into PostGIS geometries */
178  nfeatures = OGR_L_GetFeatureCount(arg.dst.lyr, TRUE);
179  if (nfeatures < 0)
180  return _rti_contour_arg_destroy(&arg);
181 
182  *contours = rtalloc(sizeof(struct rt_contour_t) * nfeatures);
183  OGR_L_ResetReading(arg.dst.lyr);
184  while ((hFeat = OGR_L_GetNextFeature(arg.dst.lyr))) {
185  size_t szWkb;
186  unsigned char *bufWkb;
187  struct rt_contour_t contour;
188  OGRGeometryH hGeom;
189  LWGEOM *geom;
190 
191  /* Somehow we're still iterating, should not happen. */
192  if(i >= nfeatures) break;
193 
194  /* Store elevation/id */
195  contour.id = OGR_F_GetFieldAsInteger(hFeat, 0);
196  contour.elevation = OGR_F_GetFieldAsDouble(hFeat, 1);
197  /* Convert OGR geometry to LWGEOM via WKB */
198  if (!(hGeom = OGR_F_GetGeometryRef(hFeat))) continue;
199  szWkb = OGR_G_WkbSize(hGeom);
200  bufWkb = rtalloc(szWkb);
201  if (OGR_G_ExportToWkb(hGeom, wkbNDR, bufWkb) != OGRERR_NONE) continue;
202  /* Reclaim feature and associated geometry memory */
203  OGR_F_Destroy(hFeat);
204  geom = lwgeom_from_wkb(bufWkb, szWkb, LW_PARSER_CHECK_NONE);
205  if (!geom) rterror("%s: invalid wkb", __func__);
207  contour.geom = gserialized_from_lwgeom(geom, NULL);
208  lwgeom_free(geom);
209  rtdealloc(bufWkb);
210  (*contours)[i++] = contour;
211  }
212 
213  /* Return total number of contours saved */
214  *ncontours = i;
215 
216  /* Free all the non-database allocated structures */
218 
219  /* Done */
220  return TRUE;
221 }
222 
#define TRUE
Definition: dbfopen.c:73
#define FALSE
Definition: dbfopen.c:72
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:2096
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 rterror(const char *fmt,...)
Wrappers used for reporting errors and info.
Definition: rt_context.c:219
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
This library is the generic raster handling section of PostGIS.
src_band
Definition: pixval.py:76
static int _rti_contour_arg_destroy(_rti_contour_arg *arg)
Definition: rt_gdal.c:62
static void _rti_contour_arg_init(_rti_contour_arg *arg)
Definition: rt_gdal.c:54
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.
Definition: rt_gdal.c:89
struct _rti_contour_arg::@12 dst
GDALDatasetH ds
Definition: rt_gdal.c:37
OGRDataSourceH ds
Definition: rt_gdal.c:44
GDALDriverH drv
Definition: rt_gdal.c:38
OGRSFDriverH drv
Definition: rt_gdal.c:43
OGRLayerH lyr
Definition: rt_gdal.c:45
OGRwkbGeometryType gtype
Definition: rt_gdal.c:47
struct _rti_contour_arg::@11 src
GSERIALIZED * geom
Definition: librtcore.h:1749
double elevation
Definition: librtcore.h:1750