51 assert(band->raster != NULL);
54 memset(
trim, 0,
sizeof(uint16_t) * 4);
60 for (y = 0; y < height; y++) {
61 for (offset = 0; offset < 3; offset++) {
63 for (x = offset; x < width; x += 3) {
65 rterror(
"_rti_raster_get_band_perimeter: Could not get band pixel");
69 RASTER_DEBUGF(4,
"top (x, y, value, nodata) = (%d, %d, %f, %d)", x, y, value, nodata);
86 for (x = width - 1; x >= 0; x--) {
87 for (offset = 0; offset < 3; offset++) {
89 for (y = offset; y < height; y += 3) {
91 rterror(
"_rti_raster_get_band_perimeter: Could not get band pixel");
95 RASTER_DEBUGF(4,
"right (x, y, value, nodata) = (%d, %d, %f, %d)", x, y, value, nodata);
97 trim[1] = width - (x + 1);
112 for (y = height - 1; y >= 0; y--) {
113 for (offset = 0; offset < 3; offset++) {
115 for (x = offset; x < width; x += 3) {
117 rterror(
"_rti_raster_get_band_perimeter: Could not get band pixel");
121 RASTER_DEBUGF(4,
"bottom (x, y, value, nodata) = (%d, %d, %f, %d)", x, y, value, nodata);
123 trim[2] = height - (y + 1);
138 for (x = 0; x < width; x++) {
139 for (offset = 0; offset < 3; offset++) {
141 for (y = offset; y < height; y += 3) {
143 rterror(
"_rti_raster_get_band_perimeter: Could not get band pixel");
147 RASTER_DEBUGF(4,
"left (x, , value, nodata) = (%d, %d, %f, %d)", x, y, value, nodata);
189 uint16_t *_nband = NULL;
192 uint16_t _trim[4] = {0};
193 uint16_t
trim[4] = {0};
195 double gt[6] = {0.0};
203 assert(perimeter != NULL);
216 RASTER_DEBUGF(3,
"rt_raster_get_perimeter: raster is %dx%d", raster->width, raster->height);
220 if (nband >= numband) {
221 rterror(
"rt_raster_get_boundary: Band %d not found for raster", nband);
230 RASTER_DEBUGF(3,
"rt_raster_get_perimeter: nband, numband = %d, %d", nband, numband);
232 _nband =
rtalloc(
sizeof(uint16_t) * numband);
233 if (_nband == NULL) {
234 rterror(
"rt_raster_get_boundary: Could not allocate memory for band indices");
239 for (i = 0; i < numband; i++)
245 for (i = 0; i < numband; i++) {
248 rterror(
"rt_raster_get_boundary: Could not get band at index %d", _nband[i]);
258 rterror(
"rt_raster_get_boundary: Could not get band perimeter");
263 for (j = 0; j < 4; j++) {
264 if (!isset[j] ||
trim[j] < _trim[j]) {
286 rterror(
"rt_raster_get_perimeter: Could not allocate memory for polygon ring");
291 rterror(
"rt_raster_get_perimeter: Could not construct point array");
309 raster->width - _trim[1], _trim[0],
318 raster->width - _trim[1], raster->height - _trim[2],
327 _trim[3], raster->height - _trim[2],
363 GEOSGeometry *gc = NULL;
364 GEOSGeometry *gunion = NULL;
365 GEOSGeometry **geoms = NULL;
369 assert(surface != NULL);
387 rterror(
"rt_raster_surface: Could not get convex hull of raster");
400 rterror(
"rt_raster_surface: The band index %d is invalid", nband);
407 rterror(
"rt_raster_surface: Error getting band %d from raster", nband);
420 rterror(
"rt_raster_surface: Could not get convex hull of raster");
441 RASTER_DEBUG(3,
"All pixels of band are NODATA. Returning NULL");
446 else if (gvcount > 1) {
448 geomscount = gvcount;
449 geoms =
rtalloc(
sizeof(GEOSGeometry *) * geomscount);
451 rterror(
"rt_raster_surface: Could not allocate memory for pixel polygons as GEOSGeometry");
452 for (i = 0; i < gvcount; i++)
lwpoly_free(gv[i].geom);
456 for (i = 0; i < gvcount; i++) {
457#if POSTGIS_DEBUG_LEVEL > 3
471 gc = GEOSGeom_createCollection(GEOS_GEOMETRYCOLLECTION, geoms, geomscount);
474 rterror(
"rt_raster_surface: Could not create GEOS GEOMETRYCOLLECTION from set of pixel polygons");
476 for (i = 0; i < geomscount; i++)
477 GEOSGeom_destroy(geoms[i]);
483 gunion = GEOSUnaryUnion(gc);
485 GEOSGeom_destroy(gc);
488 if (gunion == NULL) {
489 rterror(
"rt_raster_surface: Could not union the pixel polygons using GEOSUnaryUnion()");
501 LWGEOM *mpolyValid = NULL;
503 if (GEOSisValid(gunion))
508 if (mpolyValid == NULL) {
509 rtwarn(
"Cannot fix invalid geometry");
518 GEOSGeom_destroy(gunion);
524#if POSTGIS_DEBUG_LEVEL > 3
541#if POSTGIS_DEBUG_LEVEL > 3
565#if POSTGIS_DEBUG_LEVEL > 3
574#if POSTGIS_DEBUG_LEVEL > 3
610 double scale_x, scale_y;
611 double skew_x, skew_y;
618 assert(rast != NULL);
631 p0.
x = scale_x * x + skew_x * y + ul_x;
632 p0.
y = scale_y * y + skew_y * x + ul_y;
635 p.
x = p0.
x + scale_x;
639 p.
x = p0.
x + scale_x + skew_x;
640 p.
y = p0.
y + scale_y + skew_y;
644 p.
y = p0.
y + scale_y;
671 double scale_x, scale_y;
672 double skew_x, skew_y;
675 double center_x, center_y;
686 center_x = scale_x * x + skew_x * y + ul_x + (scale_x + skew_x) * 0.5;
687 center_y = scale_y * y + skew_y * x + ul_y + (scale_y + skew_y) * 0.5;
707 double gt[6] = {0.0};
726 "rt_raster_get_envelope: raster is %dx%d",
732 if ((!raster->width) || (!raster->height)) {
737 if (!raster->width && !raster->height) {
756 rterror(
"rt_raster_get_envelope: Could not get second point for linestring");
776 rterror(
"rt_raster_get_envelope_geom: Could not allocate memory for polygon ring");
781 rterror(
"rt_raster_get_envelope_geom: Could not construct point array");
788 rterror(
"rt_raster_get_envelope_geom: Could not get raster envelope");
840 double gt[6] = {0.0};
846 assert(hull != NULL);
857 RASTER_DEBUGF(3,
"rt_raster_get_convex_hull: raster is %dx%d", raster->width, raster->height);
860 if ((!raster->width) || (!raster->height)) {
865 if (!raster->width && !raster->height) {
884 rterror(
"rt_raster_get_convex_hull: Could not get second point for linestring");
902 rterror(
"rt_raster_get_convex_hull: Could not allocate memory for polygon ring");
909 rterror(
"rt_raster_get_convex_hull: Could not construct point array");
932 raster->width, raster->height,
978 int exclude_nodata_value,
981 CPLErr cplerr = CE_None;
984 OGRSFDriverH ogr_drv = NULL;
985 GDALDriverH gdal_drv = NULL;
986 int destroy_gdal_drv = 0;
987 GDALDatasetH memdataset = NULL;
988 GDALRasterBandH gdal_band = NULL;
989 OGRDataSourceH memdatasource = NULL;
991 OGRLayerH hLayer = NULL;
992 OGRFeatureH hFeature = NULL;
993 OGRGeometryH hGeom = NULL;
994 OGRFieldDefnH hFldDfn = NULL;
995 unsigned char *wkb = NULL;
998 int nFeatureCount = 0;
1001 double dValue = 0.0;
1002 int iBandHasNodataValue =
FALSE;
1003 double dBandNoData = 0.0;
1005 uint32_t bandNums[1] = {nband};
1006 int excludeNodataValues[1] = {exclude_nodata_value};
1009 assert(NULL != raster);
1010 assert(NULL != pnElements);
1021 rterror(
"rt_raster_gdal_polygonize: Error getting band %d from raster", nband);
1025 if (exclude_nodata_value) {
1035 if (iBandHasNodataValue)
1038 exclude_nodata_value =
FALSE;
1044 memdataset =
rt_raster_to_gdal_mem(raster, NULL, bandNums, excludeNodataValues, 1, &gdal_drv, &destroy_gdal_drv);
1045 if (NULL == memdataset) {
1046 rterror(
"rt_raster_gdal_polygonize: Couldn't convert raster to GDAL MEM dataset");
1053#ifdef GDAL_DCAP_RASTER
1065 ogr_drv = OGRGetDriverByName(
"Memory");
1066 memdatasource = OGR_Dr_CreateDataSource(ogr_drv,
"", NULL);
1067 if (NULL == memdatasource) {
1068 rterror(
"rt_raster_gdal_polygonize: Couldn't create a OGR Datasource to store pols");
1069 GDALClose(memdataset);
1070 if (destroy_gdal_drv) GDALDestroyDriver(gdal_drv);
1075 if (!OGR_DS_TestCapability(memdatasource, ODsCCreateLayer)) {
1076 rterror(
"rt_raster_gdal_polygonize: MEM driver can't create new layers, aborting");
1079 GDALClose(memdataset);
1080 if (destroy_gdal_drv) GDALDestroyDriver(gdal_drv);
1081 OGRReleaseDataSource(memdatasource);
1097 hLayer = OGR_DS_CreateLayer(memdatasource,
"PolygonizedLayer", NULL, wkbPolygon, NULL);
1099 if (NULL == hLayer) {
1100 rterror(
"rt_raster_gdal_polygonize: Couldn't create layer to store polygons");
1102 GDALClose(memdataset);
1103 if (destroy_gdal_drv) GDALDestroyDriver(gdal_drv);
1104 OGRReleaseDataSource(memdatasource);
1114 hFldDfn = OGR_Fld_Create(
"PixelValue", OFTReal);
1117 if (OGR_L_CreateField(hLayer, hFldDfn,
TRUE) != OGRERR_NONE) {
1118 rtwarn(
"Couldn't create a field in OGR Layer. The polygons generated won't be able to store the pixel value");
1127 gdal_band = GDALGetRasterBand(memdataset, 1);
1128 if (NULL == gdal_band) {
1129 rterror(
"rt_raster_gdal_polygonize: Couldn't get GDAL band to polygonize");
1131 GDALClose(memdataset);
1132 if (destroy_gdal_drv) GDALDestroyDriver(gdal_drv);
1133 OGR_Fld_Destroy(hFldDfn);
1134 OGR_DS_DeleteLayer(memdatasource, 0);
1135 OGRReleaseDataSource(memdatasource);
1144 cplerr = GDALFPolygonize(
1147 if (cplerr != CE_None) {
1148 rterror(
"rt_raster_gdal_polygonize: Could not polygonize GDAL band");
1150 GDALClose(memdataset);
1151 if (destroy_gdal_drv) GDALDestroyDriver(gdal_drv);
1152 OGR_Fld_Destroy(hFldDfn);
1153 OGR_DS_DeleteLayer(memdatasource, 0);
1154 OGRReleaseDataSource(memdatasource);
1165 if (iBandHasNodataValue) {
1166 size_t sz = 50 *
sizeof (char);
1167 pszQuery = (
char *)
rtalloc(sz);
1168 snprintf(pszQuery, sz,
"PixelValue != %f", dBandNoData );
1169 OGRErr e = OGR_L_SetAttributeFilter(hLayer, pszQuery);
1170 if (e != OGRERR_NONE) {
1171 rtwarn(
"Error filtering NODATA values for band. All values will be treated as data values");
1184 nFeatureCount = OGR_L_GetFeatureCount(hLayer,
TRUE);
1190 rterror(
"rt_raster_gdal_polygonize: Could not allocate memory for geomval set");
1192 GDALClose(memdataset);
1193 if (destroy_gdal_drv) GDALDestroyDriver(gdal_drv);
1194 OGR_Fld_Destroy(hFldDfn);
1195 OGR_DS_DeleteLayer(memdatasource, 0);
1196 if (NULL != pszQuery)
1198 OGRReleaseDataSource(memdatasource);
1209 OGR_L_ResetReading(hLayer);
1211 for (j = 0; j < nFeatureCount; j++) {
1212 hFeature = OGR_L_GetNextFeature(hLayer);
1213 dValue = OGR_F_GetFieldAsDouble(hFeature, iPixVal);
1215 hGeom = OGR_F_GetGeometryRef(hFeature);
1216 wkbsize = OGR_G_WkbSize(hGeom);
1219 wkb =
rtalloc(
sizeof(
unsigned char) * wkbsize);
1221 rterror(
"rt_raster_gdal_polygonize: Could not allocate memory for WKB buffer");
1223 OGR_F_Destroy(hFeature);
1224 GDALClose(memdataset);
1225 if (destroy_gdal_drv) GDALDestroyDriver(gdal_drv);
1226 OGR_Fld_Destroy(hFldDfn);
1227 OGR_DS_DeleteLayer(memdatasource, 0);
1228 if (NULL != pszQuery)
1230 OGRReleaseDataSource(memdatasource);
1236 OGR_G_ExportToWkb(hGeom, wkbNDR, wkb);
1240 if (!lwgeom)
rterror(
"%s: invalid wkb", __func__);
1242#if POSTGIS_DEBUG_LEVEL > 3
1245 OGR_G_ExportToWkt(hGeom, &wkt);
1249 d_print_binary_hex(
"GDAL wkb", wkb, wkbsize);
1258 OGR_F_Destroy(hFeature);
1266#if POSTGIS_DEBUG_LEVEL > 3
1275 d_print_binary_hex(
"LWGEOM wkb", (
const uint8_t *)lwwkb->
data, lwwkbsize);
1282 pols[j].
val = dValue;
1285 *pnElements = nFeatureCount;
1288 GDALClose(memdataset);
1289 if (destroy_gdal_drv) GDALDestroyDriver(gdal_drv);
1292 OGR_Fld_Destroy(hFldDfn);
1293 OGR_DS_DeleteLayer(memdatasource, 0);
1294 if (NULL != pszQuery)
rtdealloc(pszQuery);
1295 OGRReleaseDataSource(memdatasource);
GEOSGeometry * LWGEOM2GEOS(const LWGEOM *lwgeom, uint8_t autofix)
void lwgeom_geos_error(const char *fmt,...)
void(*) LWGEOM GEOS2LWGEOM)(const GEOSGeometry *geom, uint8_t want3d)
LWGEOM * lwpoint_as_lwgeom(const LWPOINT *obj)
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...
void lwgeom_free(LWGEOM *geom)
LWGEOM * lwgeom_as_multi(const LWGEOM *lwgeom)
Create a new LWGEOM of the appropriate MULTI* type.
#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)
POINTARRAY * ptarray_construct_empty(char hasz, char hasm, uint32_t maxpoints)
Create a new POINTARRAY with no points.
LWPOLY * lwgeom_as_lwpoly(const LWGEOM *lwgeom)
LWLINE * lwline_construct(int32_t srid, GBOX *bbox, POINTARRAY *points)
LWPOINT * lwpoint_make2d(int32_t srid, double x, double y)
int lwgeom_is_collection(const LWGEOM *lwgeom)
Determine whether a LWGEOM contains sub-geometries or not This basically just checks that the struct ...
LWGEOM * lwline_as_lwgeom(const LWLINE *obj)
LWMPOLY * lwgeom_as_lwmpoly(const LWGEOM *lwgeom)
LWPOLY * lwpoly_construct(int32_t srid, GBOX *bbox, uint32_t nrings, POINTARRAY **points)
int ptarray_append_point(POINTARRAY *pa, const POINT4D *pt, int allow_duplicates)
Append a point to the end of an existing POINTARRAY If allow_duplicate is LW_FALSE,...
void lwpoly_free(LWPOLY *poly)
#define LW_TRUE
Return types for functions with status returns.
#define SRID_UNKNOWN
Unknown SRID value.
void ptarray_set_point4d(POINTARRAY *pa, uint32_t n, const POINT4D *p4d)
LWGEOM * lwpoly_as_lwgeom(const LWPOLY *obj)
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...
LWGEOM * lwgeom_make_valid(LWGEOM *geom)
Attempts to make an invalid geometries valid w/out losing points.
POINTARRAY * ptarray_construct(char hasz, char hasm, uint32_t npoints)
Construct an empty pointarray, allocating storage and setting the npoints, but not filling in any inf...
LWGEOM * lwgeom_clone_deep(const LWGEOM *lwgeom)
Deep clone an LWGEOM, everything is copied.
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.
uint16_t rt_band_get_width(rt_band band)
Return width of this band.
#define RASTER_DEBUG(level, msg)
rt_errorstate rt_raster_cell_to_geopoint(rt_raster raster, double xr, double yr, double *xw, double *yw, double *gt)
Convert an xr, yr raster point to an xw, yw point on map.
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,...)
double rt_raster_get_x_skew(rt_raster raster)
Get skew about the X axis.
double rt_raster_get_x_offset(rt_raster raster)
Get raster x offset, in projection units.
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.
rt_errorstate rt_band_get_pixel(rt_band band, int x, int y, double *value, int *nodata)
Get pixel value.
int rt_band_get_isnodata_flag(rt_band band)
Get isnodata flag value.
int rt_util_gdal_progress_func(double dfComplete, const char *pszMessage, void *pProgressArg)
double rt_raster_get_x_scale(rt_raster raster)
Get scale X in projection units.
rt_errorstate
Enum definitions.
uint16_t rt_raster_get_num_bands(rt_raster raster)
uint16_t rt_raster_get_height(rt_raster raster)
struct rt_geomval_t * rt_geomval
rt_errorstate rt_band_get_nodata(rt_band band, double *nodata)
Get NODATA value.
uint16_t rt_raster_get_width(rt_raster raster)
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.
double rt_raster_get_y_scale(rt_raster raster)
Get scale Y in projection units.
rt_errorstate rt_raster_get_envelope(rt_raster raster, rt_envelope *env)
Get raster's envelope.
double rt_raster_get_y_skew(rt_raster raster)
Get skew about the Y axis.
void rt_raster_get_geotransform_matrix(rt_raster raster, double *gt)
Get 6-element array of raster geotransform matrix.
uint16_t rt_band_get_height(rt_band band)
Return height of this band.
double rt_raster_get_y_offset(rt_raster raster)
Get raster y offset, in projection units.
int rt_raster_is_empty(rt_raster raster)
Return TRUE if the raster is empty.
rt_band rt_raster_get_band(rt_raster raster, int bandNum)
Return Nth band, or NULL if unavailable.
This library is the generic raster handling section of PostGIS.
static char * trim(const char *input)
rt_errorstate rt_raster_surface(rt_raster raster, int nband, LWMPOLY **surface)
Get a raster as a surface (multipolygon).
rt_geomval rt_raster_gdal_polygonize(rt_raster raster, int nband, int exclude_nodata_value, int *pnElements)
Returns a set of "geomval" value, one for each group of pixel sharing the same value for the provided...
LWPOLY * rt_raster_pixel_as_polygon(rt_raster rast, int x, int y)
Get a raster pixel as a polygon.
rt_errorstate rt_raster_get_convex_hull(rt_raster raster, LWGEOM **hull)
Get raster's convex hull.
static rt_errorstate _rti_raster_get_band_perimeter(rt_band band, uint16_t *trim)
LWPOINT * rt_raster_pixel_as_centroid_point(rt_raster rast, int x, int y)
Get a raster pixel centroid point.
rt_errorstate rt_raster_get_envelope_geom(rt_raster raster, LWGEOM **env)
Get raster's envelope as a geometry.
rt_errorstate rt_raster_get_perimeter(rt_raster raster, int nband, LWGEOM **perimeter)
Get raster perimeter.