Returns a set of "geomval" value, one for each group of pixel sharing the same value for the provided band.
From GDALPolygonize function header: "Polygon features will be
created on the output layer, with polygon geometries representing
the polygons". So,the WKB geometry type should be "wkbPolygon"
Optimization: Apply a OGR SQL filter to the layer to select the features different from NODATA value.
Thanks to David Zwarg.
979 {
980 CPLErr cplerr = CE_None;
981 char *pszQuery;
982 long j;
983 OGRSFDriverH ogr_drv = NULL;
984 GDALDriverH gdal_drv = NULL;
985 int destroy_gdal_drv = 0;
986 GDALDatasetH memdataset = NULL;
987 GDALRasterBandH gdal_band = NULL;
988 OGRDataSourceH memdatasource = NULL;
990 OGRLayerH hLayer = NULL;
991 OGRFeatureH hFeature = NULL;
992 OGRGeometryH hGeom = NULL;
993 OGRFieldDefnH hFldDfn = NULL;
994 unsigned char *wkb = NULL;
995 int wkbsize = 0;
997 int nFeatureCount = 0;
999 int iPixVal = -1;
1000 double dValue = 0.0;
1001 int iBandHasNodataValue =
FALSE;
1002 double dBandNoData = 0.0;
1003
1004 uint32_t bandNums[1] = {
nband};
1005 int excludeNodataValues[1] = {exclude_nodata_value};
1006
1007
1008 assert(NULL != raster);
1009 assert(NULL != pnElements);
1010
1012
1013 *pnElements = 0;
1014
1015
1016
1017
1019 if (NULL == band) {
1020 rterror(
"rt_raster_gdal_polygonize: Error getting band %d from raster", nband);
1021 return NULL;
1022 }
1023
1024 if (exclude_nodata_value) {
1025
1026
1029 *pnElements = 0;
1030 return NULL;
1031 }
1032
1034 if (iBandHasNodataValue)
1036 else
1037 exclude_nodata_value =
FALSE;
1038 }
1039
1040
1041
1042
1043 memdataset =
rt_raster_to_gdal_mem(raster, NULL, bandNums, excludeNodataValues, 1, &gdal_drv, &destroy_gdal_drv);
1044 if (NULL == memdataset) {
1045 rterror(
"rt_raster_gdal_polygonize: Couldn't convert raster to GDAL MEM dataset");
1046 return NULL;
1047 }
1048
1049
1050
1051
1052#ifdef GDAL_DCAP_RASTER
1053
1055#else
1056 OGRRegisterAll();
1057#endif
1058
1060
1061
1062
1063
1064 ogr_drv = OGRGetDriverByName("Memory");
1065 memdatasource = OGR_Dr_CreateDataSource(ogr_drv, "", NULL);
1066 if (NULL == memdatasource) {
1067 rterror(
"rt_raster_gdal_polygonize: Couldn't create a OGR Datasource to store pols");
1068 GDALClose(memdataset);
1069 if (destroy_gdal_drv) GDALDestroyDriver(gdal_drv);
1070 return NULL;
1071 }
1072
1073
1074 if (!OGR_DS_TestCapability(memdatasource, ODsCCreateLayer)) {
1075 rterror(
"rt_raster_gdal_polygonize: MEM driver can't create new layers, aborting");
1076
1077
1078 GDALClose(memdataset);
1079 if (destroy_gdal_drv) GDALDestroyDriver(gdal_drv);
1080 OGRReleaseDataSource(memdatasource);
1081
1082 return NULL;
1083 }
1084
1086
1087
1088
1089
1090
1096 hLayer = OGR_DS_CreateLayer(memdatasource, "PolygonizedLayer", NULL, wkbPolygon, NULL);
1097
1098 if (NULL == hLayer) {
1099 rterror(
"rt_raster_gdal_polygonize: Couldn't create layer to store polygons");
1100
1101 GDALClose(memdataset);
1102 if (destroy_gdal_drv) GDALDestroyDriver(gdal_drv);
1103 OGRReleaseDataSource(memdatasource);
1104
1105 return NULL;
1106 }
1107
1112
1113 hFldDfn = OGR_Fld_Create("PixelValue", OFTReal);
1114
1115
1116 if (OGR_L_CreateField(hLayer, hFldDfn,
TRUE) != OGRERR_NONE) {
1117 rtwarn(
"Couldn't create a field in OGR Layer. The polygons generated won't be able to store the pixel value");
1118 iPixVal = -1;
1119 }
1120 else {
1121
1122 iPixVal = 0;
1123 }
1124
1125
1126 gdal_band = GDALGetRasterBand(memdataset, 1);
1127 if (NULL == gdal_band) {
1128 rterror(
"rt_raster_gdal_polygonize: Couldn't get GDAL band to polygonize");
1129
1130 GDALClose(memdataset);
1131 if (destroy_gdal_drv) GDALDestroyDriver(gdal_drv);
1132 OGR_Fld_Destroy(hFldDfn);
1133 OGR_DS_DeleteLayer(memdatasource, 0);
1134 OGRReleaseDataSource(memdatasource);
1135
1136 return NULL;
1137 }
1138
1139
1140 cplerr = GDALFPolygonize(gdal_band, NULL, hLayer, iPixVal, NULL, NULL, NULL);
1141
1142 if (cplerr != CE_None) {
1143 rterror(
"rt_raster_gdal_polygonize: Could not polygonize GDAL band");
1144
1145 GDALClose(memdataset);
1146 if (destroy_gdal_drv) GDALDestroyDriver(gdal_drv);
1147 OGR_Fld_Destroy(hFldDfn);
1148 OGR_DS_DeleteLayer(memdatasource, 0);
1149 OGRReleaseDataSource(memdatasource);
1150
1151 return NULL;
1152 }
1153
1160 if (iBandHasNodataValue) {
1161 size_t sz = 50 * sizeof (char);
1162 pszQuery = (
char *)
rtalloc(sz);
1163 snprintf(pszQuery, sz, "PixelValue != %f", dBandNoData );
1164 OGRErr e = OGR_L_SetAttributeFilter(hLayer, pszQuery);
1165 if (e != OGRERR_NONE) {
1166 rtwarn(
"Error filtering NODATA values for band. All values will be treated as data values");
1167 }
1168 }
1169 else {
1170 pszQuery = NULL;
1171 }
1172
1173
1174
1175
1176
1177
1178
1179 nFeatureCount = OGR_L_GetFeatureCount(hLayer,
TRUE);
1180
1181
1183
1184 if (NULL == pols) {
1185 rterror(
"rt_raster_gdal_polygonize: Could not allocate memory for geomval set");
1186
1187 GDALClose(memdataset);
1188 if (destroy_gdal_drv) GDALDestroyDriver(gdal_drv);
1189 OGR_Fld_Destroy(hFldDfn);
1190 OGR_DS_DeleteLayer(memdatasource, 0);
1191 if (NULL != pszQuery)
1193 OGRReleaseDataSource(memdatasource);
1194
1195 return NULL;
1196 }
1197
1198
1200
1202
1203
1204 OGR_L_ResetReading(hLayer);
1205
1206 for (j = 0; j < nFeatureCount; j++) {
1207 hFeature = OGR_L_GetNextFeature(hLayer);
1208 dValue = OGR_F_GetFieldAsDouble(hFeature, iPixVal);
1209
1210 hGeom = OGR_F_GetGeometryRef(hFeature);
1211 wkbsize = OGR_G_WkbSize(hGeom);
1212
1213
1214 wkb =
rtalloc(
sizeof(
unsigned char) * wkbsize);
1215 if (wkb == NULL) {
1216 rterror(
"rt_raster_gdal_polygonize: Could not allocate memory for WKB buffer");
1217
1218 OGR_F_Destroy(hFeature);
1219 GDALClose(memdataset);
1220 if (destroy_gdal_drv) GDALDestroyDriver(gdal_drv);
1221 OGR_Fld_Destroy(hFldDfn);
1222 OGR_DS_DeleteLayer(memdatasource, 0);
1223 if (NULL != pszQuery)
1225 OGRReleaseDataSource(memdatasource);
1226
1227 return NULL;
1228 }
1229
1230
1231 OGR_G_ExportToWkb(hGeom, wkbNDR, wkb);
1232
1233
1235 if (!lwgeom)
rterror(
"%s: invalid wkb", __func__);
1236
1237#if POSTGIS_DEBUG_LEVEL > 3
1238 {
1239 char *wkt = NULL;
1240 OGR_G_ExportToWkt(hGeom, &wkt);
1242 CPLFree(wkt);
1243
1244 d_print_binary_hex("GDAL wkb", wkb, wkbsize);
1245 }
1246#endif
1247
1248
1250 wkb = NULL;
1251 wkbsize = 0;
1252
1253 OGR_F_Destroy(hFeature);
1254
1255
1257
1258
1260
1261#if POSTGIS_DEBUG_LEVEL > 3
1262 {
1266
1269 if (lwwkbsize) {
1270 d_print_binary_hex(
"LWGEOM wkb", (
const uint8_t *)lwwkb->
data, lwwkbsize);
1272 }
1273 }
1274#endif
1275
1276
1277 pols[j].
val = dValue;
1278 }
1279
1280 *pnElements = nFeatureCount;
1281
1283 GDALClose(memdataset);
1284 if (destroy_gdal_drv) GDALDestroyDriver(gdal_drv);
1285
1287 OGR_Fld_Destroy(hFldDfn);
1288 OGR_DS_DeleteLayer(memdatasource, 0);
1289 if (NULL != pszQuery)
rtdealloc(pszQuery);
1290 OGRReleaseDataSource(memdatasource);
1291
1292 return pols;
1293}
void lwgeom_geos_error(const char *fmt,...)
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...
#define LW_PARSER_CHECK_NONE
#define LWSIZE_GET(varsize)
Macro for reading the size from the GSERIALIZED size attribute.
char * lwgeom_to_wkt(const LWGEOM *geom, uint8_t variant, int precision, size_t *size_out)
WKT emitter function.
lwvarlena_t * lwgeom_to_wkb_varlena(const LWGEOM *geom, uint8_t variant)
LWPOLY * lwgeom_as_lwpoly(const LWGEOM *lwgeom)
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...
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.
#define RASTER_DEBUG(level, msg)
int32_t rt_raster_get_srid(rt_raster raster)
Get raster's SRID.
int rt_util_gdal_register_all(int force_register_all)
#define RASTER_DEBUGF(level, msg,...)
void void rtinfo(const char *fmt,...) __attribute__((format(printf
void void void rtwarn(const char *fmt,...) __attribute__((format(printf
int rt_band_get_hasnodata_flag(rt_band band)
Get hasnodata flag value.
int rt_band_get_isnodata_flag(rt_band band)
Get isnodata flag value.
struct rt_geomval_t * rt_geomval
rt_errorstate rt_band_get_nodata(rt_band band, double *nodata)
Get NODATA value.
void rtdealloc(void *mem)
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.
rt_band rt_raster_get_band(rt_raster raster, int bandNum)
Return Nth band, or NULL if unavailable.