Get a raster as a surface (multipolygon).
If a band is specified, those pixels with value (not NODATA) contribute to the area of the output multipolygon.
355 {
361 int gvcount = 0;
362 GEOSGeometry *gc = NULL;
363 GEOSGeometry *gunion = NULL;
364 GEOSGeometry **geoms = NULL;
365 int geomscount = 0;
366 int i = 0;
367
368 assert(surface != NULL);
369
370
371 *surface = NULL;
372
373
376
377
378 if (nband < 0) {
379
380
381
382
383
384
386 rterror(
"rt_raster_surface: Could not get convex hull of raster");
388 }
393
396 }
397
399 rterror(
"rt_raster_surface: The band index %d is invalid", nband);
401 }
402
403
405 if (band == NULL) {
406 rterror(
"rt_raster_surface: Error getting band %d from raster", nband);
408 }
409
410
412
413
414
415
416
417
419 rterror(
"rt_raster_surface: Could not get convex hull of raster");
421 }
426
429 }
430
434 }
435
436
438
439
441
442 if (gvcount < 1) {
443 RASTER_DEBUG(3,
"All pixels of band are NODATA. Returning NULL");
446 }
447
448 else if (gvcount > 1) {
449
450 geomscount = gvcount;
451 geoms =
rtalloc(
sizeof(GEOSGeometry *) * geomscount);
452 if (geoms == NULL) {
453 rterror(
"rt_raster_surface: Could not allocate memory for pixel polygons as GEOSGeometry");
454 for (i = 0; i < gvcount; i++)
lwpoly_free(gv[i].geom);
457 }
458 for (i = 0; i < gvcount; i++) {
459#if POSTGIS_DEBUG_LEVEL > 3
460 {
464 }
465#endif
466
469 }
471
472
473 gc = GEOSGeom_createCollection(GEOS_GEOMETRYCOLLECTION, geoms, geomscount);
474
475 if (gc == NULL) {
476 rterror(
"rt_raster_surface: Could not create GEOS GEOMETRYCOLLECTION from set of pixel polygons");
477
478 for (i = 0; i < geomscount; i++)
479 GEOSGeom_destroy(geoms[i]);
482 }
483
484
485 gunion = GEOSUnaryUnion(gc);
486
487 GEOSGeom_destroy(gc);
489
490 if (gunion == NULL) {
491 rterror(
"rt_raster_surface: Could not union the pixel polygons using GEOSUnaryUnion()");
493 }
494
495
497
498
499
500
501
502 do {
503 LWGEOM *mpolyValid = NULL;
504
505 if (GEOSisValid(gunion))
506 break;
507
508
510 if (mpolyValid == NULL) {
511 rtwarn(
"Cannot fix invalid geometry");
512 break;
513 }
514
516 mpoly = mpolyValid;
517 }
518 while (0);
519
520 GEOSGeom_destroy(gunion);
521 }
522 else {
525
526#if POSTGIS_DEBUG_LEVEL > 3
527 {
531 }
532#endif
533 }
534
535
537
538 if (mpoly != NULL) {
539
541 tmp = mpoly;
542
543#if POSTGIS_DEBUG_LEVEL > 3
544 {
548 }
549#endif
550
552
553
554
555
556
557
558
563 mpoly = clone;
564
566
567#if POSTGIS_DEBUG_LEVEL > 3
568 {
572 }
573#endif
574 }
575
576#if POSTGIS_DEBUG_LEVEL > 3
577 {
581 }
582#endif
583
586 }
587
589}
GEOSGeometry * LWGEOM2GEOS(const LWGEOM *lwgeom, uint8_t autofix)
LWGEOM * GEOS2LWGEOM(const GEOSGeometry *geom, uint8_t want3d)
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...
void lwgeom_free(LWGEOM *geom)
LWGEOM * lwgeom_as_multi(const LWGEOM *lwgeom)
Create a new LWGEOM of the appropriate MULTI* type.
char * lwgeom_to_wkt(const LWGEOM *geom, uint8_t variant, int precision, size_t *size_out)
WKT emitter function.
int lwgeom_is_collection(const LWGEOM *lwgeom)
Determine whether a LWGEOM can contain sub-geometries or not.
LWMPOLY * lwgeom_as_lwmpoly(const LWGEOM *lwgeom)
void lwpoly_free(LWPOLY *poly)
LWGEOM * lwpoly_as_lwgeom(const LWPOLY *obj)
LWGEOM * lwgeom_make_valid(LWGEOM *geom)
Attempts to make an invalid geometries valid w/out losing points.
LWGEOM * lwgeom_clone_deep(const LWGEOM *lwgeom)
Deep clone an LWGEOM, everything is copied.
void rterror(const char *fmt,...)
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.
#define RASTER_DEBUGF(level, msg,...)
void rtinfo(const char *fmt,...)
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.
void rtwarn(const char *fmt,...)
uint16_t rt_raster_get_num_bands(rt_raster raster)
void rtdealloc(void *mem)
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.
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...
rt_errorstate rt_raster_get_convex_hull(rt_raster raster, LWGEOM **hull)
Get raster's convex hull.