PostGIS  2.1.10dev-r@@SVN_REVISION@@
Datum RASTER_clip ( PG_FUNCTION_ARGS  )

Definition at line 19018 of file rt_pg.c.

References ovdump::band, rtpg_clip_arg_t::band, clamp_srid(), ES_NONE, ET_FIRST, ET_INTERSECTION, rtpg_clip_arg_t::extenttype, FALSE, gserialized_get_srid(), window::gt, rtpg_clip_band_t::hasnodata, lwgeom_force_2d(), lwgeom_free(), lwgeom_from_gserialized(), lwgeom_intersection(), lwgeom_is_empty(), lwgeom_ndims(), lwgeom_to_wkb(), rtpg_clip_arg_t::mask, rt_iterator_t::nband, rtpg_clip_band_t::nband, rt_iterator_t::nbnodata, rtpg_clip_band_t::nodataval, rtpg_clip_arg_t::numbands, POSTGIS_RT_DEBUG, POSTGIS_RT_DEBUGF, rt_iterator_t::raster, rtpg_clip_arg_t::raster, rt_band_get_hasnodata_flag(), rt_band_get_isnodata_flag(), rt_band_get_min_value(), rt_band_get_nodata(), rt_band_get_pixtype(), rt_raster_add_band(), rt_raster_deserialize(), rt_raster_destroy(), rt_raster_from_two_rasters(), rt_raster_gdal_rasterize(), rt_raster_generate_new_band(), rt_raster_get_band(), rt_raster_get_convex_hull(), rt_raster_get_geotransform_matrix(), rt_raster_get_num_bands(), rt_raster_get_srid(), rt_raster_has_band(), rt_raster_is_empty(), rt_raster_iterator(), rt_raster_new(), rt_raster_serialize(), rt_raster_set_srid(), rtpg_clip_arg_destroy(), rtpg_clip_arg_init(), rtpg_clip_callback(), rt_raster_serialized_t::size, SRID_UNKNOWN, and WKB_SFSQL.

19019 {
19020  rt_pgraster *pgraster = NULL;
19021  LWGEOM *rastgeom = NULL;
19022  double gt[6] = {0};
19023  int srid = SRID_UNKNOWN;
19024 
19025  rt_pgraster *pgrtn = NULL;
19026  rt_raster rtn = NULL;
19027 
19028  GSERIALIZED *gser = NULL;
19029  LWGEOM *geom = NULL;
19030  unsigned char *wkb = NULL;
19031  size_t wkb_len;
19032 
19033  ArrayType *array;
19034  Oid etype;
19035  Datum *e;
19036  bool *nulls;
19037 
19038  int16 typlen;
19039  bool typbyval;
19040  char typalign;
19041 
19042  int i = 0;
19043  int j = 0;
19044  int k = 0;
19045  rtpg_clip_arg arg = NULL;
19046  LWGEOM *tmpgeom = NULL;
19047  rt_iterator itrset;
19048 
19049  rt_raster _raster = NULL;
19050  rt_band band = NULL;
19051  rt_pixtype pixtype;
19052  int hasnodata;
19053  double nodataval;
19054  int noerr = 0;
19055 
19056  POSTGIS_RT_DEBUG(3, "Starting...");
19057 
19058  /* raster or geometry is NULL, return NULL */
19059  if (PG_ARGISNULL(0) || PG_ARGISNULL(2))
19060  PG_RETURN_NULL();
19061 
19062  /* init arg */
19063  arg = rtpg_clip_arg_init();
19064  if (arg == NULL) {
19065  elog(ERROR, "RASTER_clip: Could not initialize argument structure");
19066  PG_RETURN_NULL();
19067  }
19068 
19069  /* raster (0) */
19070  pgraster = (rt_pgraster *) PG_DETOAST_DATUM(PG_GETARG_DATUM(0));
19071 
19072  /* Get raster object */
19073  arg->raster = rt_raster_deserialize(pgraster, FALSE);
19074  if (arg->raster == NULL) {
19075  rtpg_clip_arg_destroy(arg);
19076  PG_FREE_IF_COPY(pgraster, 0);
19077  elog(ERROR, "RASTER_clip: Could not deserialize raster");
19078  PG_RETURN_NULL();
19079  }
19080 
19081  /* raster is empty, return empty raster */
19082  if (rt_raster_is_empty(arg->raster)) {
19083  elog(NOTICE, "Input raster is empty. Returning empty raster");
19084 
19085  rtpg_clip_arg_destroy(arg);
19086  PG_FREE_IF_COPY(pgraster, 0);
19087 
19088  rtn = rt_raster_new(0, 0);
19089  if (rtn == NULL) {
19090  elog(ERROR, "RASTER_clip: Could not create empty raster");
19091  PG_RETURN_NULL();
19092  }
19093 
19094  pgrtn = rt_raster_serialize(rtn);
19095  rt_raster_destroy(rtn);
19096  if (NULL == pgrtn)
19097  PG_RETURN_NULL();
19098 
19099  SET_VARSIZE(pgrtn, pgrtn->size);
19100  PG_RETURN_POINTER(pgrtn);
19101  }
19102 
19103  /* metadata */
19105  srid = clamp_srid(rt_raster_get_srid(arg->raster));
19106 
19107  /* geometry (2) */
19108  gser = (GSERIALIZED *) PG_DETOAST_DATUM(PG_GETARG_DATUM(2));
19109  geom = lwgeom_from_gserialized(gser);
19110 
19111  /* Get a 2D version of the geometry if necessary */
19112  if (lwgeom_ndims(geom) > 2) {
19113  LWGEOM *geom2d = lwgeom_force_2d(geom);
19114  lwgeom_free(geom);
19115  geom = geom2d;
19116  }
19117 
19118  /* check that SRIDs match */
19119  if (srid != clamp_srid(gserialized_get_srid(gser))) {
19120  elog(NOTICE, "Geometry provided does not have the same SRID as the raster. Returning NULL");
19121 
19122  rtpg_clip_arg_destroy(arg);
19123  PG_FREE_IF_COPY(pgraster, 0);
19124  lwgeom_free(geom);
19125  PG_FREE_IF_COPY(gser, 2);
19126 
19127  PG_RETURN_NULL();
19128  }
19129 
19130  /* crop (4) */
19131  if (!PG_ARGISNULL(4) && !PG_GETARG_BOOL(4))
19132  arg->extenttype = ET_FIRST;
19133 
19134  /* get intersection geometry of input raster and input geometry */
19135  if (rt_raster_get_convex_hull(arg->raster, &rastgeom) != ES_NONE) {
19136 
19137  rtpg_clip_arg_destroy(arg);
19138  PG_FREE_IF_COPY(pgraster, 0);
19139  lwgeom_free(geom);
19140  PG_FREE_IF_COPY(gser, 2);
19141 
19142  elog(ERROR, "RASTER_clip: Could not get convex hull of raster");
19143  PG_RETURN_NULL();
19144  }
19145 
19146  tmpgeom = lwgeom_intersection(rastgeom, geom);
19147  lwgeom_free(rastgeom);
19148  lwgeom_free(geom);
19149  PG_FREE_IF_COPY(gser, 2);
19150  geom = tmpgeom;
19151 
19152  /* intersection is empty AND extent type is INTERSECTION, return empty */
19153  if (lwgeom_is_empty(geom) && arg->extenttype == ET_INTERSECTION) {
19154  elog(NOTICE, "The input raster and input geometry do not intersect. Returning empty raster");
19155 
19156  rtpg_clip_arg_destroy(arg);
19157  PG_FREE_IF_COPY(pgraster, 0);
19158  lwgeom_free(geom);
19159 
19160  rtn = rt_raster_new(0, 0);
19161  if (rtn == NULL) {
19162  elog(ERROR, "RASTER_clip: Could not create empty raster");
19163  PG_RETURN_NULL();
19164  }
19165 
19166  pgrtn = rt_raster_serialize(rtn);
19167  rt_raster_destroy(rtn);
19168  if (NULL == pgrtn)
19169  PG_RETURN_NULL();
19170 
19171  SET_VARSIZE(pgrtn, pgrtn->size);
19172  PG_RETURN_POINTER(pgrtn);
19173  }
19174 
19175  /* nband (1) */
19176  if (!PG_ARGISNULL(1)) {
19177  array = PG_GETARG_ARRAYTYPE_P(1);
19178  etype = ARR_ELEMTYPE(array);
19179  get_typlenbyvalalign(etype, &typlen, &typbyval, &typalign);
19180 
19181  switch (etype) {
19182  case INT2OID:
19183  case INT4OID:
19184  break;
19185  default:
19186  rtpg_clip_arg_destroy(arg);
19187  PG_FREE_IF_COPY(pgraster, 0);
19188  lwgeom_free(geom);
19189  elog(ERROR, "RASTER_clip: Invalid data type for band indexes");
19190  PG_RETURN_NULL();
19191  break;
19192  }
19193 
19194  deconstruct_array(
19195  array, etype,
19196  typlen, typbyval, typalign,
19197  &e, &nulls, &(arg->numbands)
19198  );
19199 
19200  arg->band = palloc(sizeof(struct rtpg_clip_band_t) * arg->numbands);
19201  if (arg->band == NULL) {
19202  rtpg_clip_arg_destroy(arg);
19203  PG_FREE_IF_COPY(pgraster, 0);
19204  lwgeom_free(geom);
19205  elog(ERROR, "RASTER_clip: Could not allocate memory for band arguments");
19206  PG_RETURN_NULL();
19207  }
19208 
19209  for (i = 0, j = 0; i < arg->numbands; i++) {
19210  if (nulls[i]) continue;
19211 
19212  switch (etype) {
19213  case INT2OID:
19214  arg->band[j].nband = DatumGetInt16(e[i]) - 1;
19215  break;
19216  case INT4OID:
19217  arg->band[j].nband = DatumGetInt32(e[i]) - 1;
19218  break;
19219  }
19220 
19221  j++;
19222  }
19223 
19224  if (j < arg->numbands) {
19225  arg->band = repalloc(arg->band, sizeof(struct rtpg_clip_band_t) * j);
19226  if (arg->band == NULL) {
19227  rtpg_clip_arg_destroy(arg);
19228  PG_FREE_IF_COPY(pgraster, 0);
19229  lwgeom_free(geom);
19230  elog(ERROR, "RASTER_clip: Could not reallocate memory for band arguments");
19231  PG_RETURN_NULL();
19232  }
19233 
19234  arg->numbands = j;
19235  }
19236 
19237  /* validate band */
19238  for (i = 0; i < arg->numbands; i++) {
19239  if (!rt_raster_has_band(arg->raster, arg->band[i].nband)) {
19240  elog(NOTICE, "Band at index %d not found in raster", arg->band[i].nband + 1);
19241  rtpg_clip_arg_destroy(arg);
19242  PG_FREE_IF_COPY(pgraster, 0);
19243  lwgeom_free(geom);
19244  PG_RETURN_NULL();
19245  }
19246 
19247  arg->band[i].hasnodata = 0;
19248  arg->band[i].nodataval = 0;
19249  }
19250  }
19251  else {
19253 
19254  /* raster may have no bands */
19255  if (arg->numbands) {
19256  arg->band = palloc(sizeof(struct rtpg_clip_band_t) * arg->numbands);
19257  if (arg->band == NULL) {
19258 
19259  rtpg_clip_arg_destroy(arg);
19260  PG_FREE_IF_COPY(pgraster, 0);
19261  lwgeom_free(geom);
19262 
19263  elog(ERROR, "RASTER_clip: Could not allocate memory for band arguments");
19264  PG_RETURN_NULL();
19265  }
19266 
19267  for (i = 0; i < arg->numbands; i++) {
19268  arg->band[i].nband = i;
19269  arg->band[i].hasnodata = 0;
19270  arg->band[i].nodataval = 0;
19271  }
19272  }
19273  }
19274 
19275  /* nodataval (3) */
19276  if (!PG_ARGISNULL(3)) {
19277  array = PG_GETARG_ARRAYTYPE_P(3);
19278  etype = ARR_ELEMTYPE(array);
19279  get_typlenbyvalalign(etype, &typlen, &typbyval, &typalign);
19280 
19281  switch (etype) {
19282  case FLOAT4OID:
19283  case FLOAT8OID:
19284  break;
19285  default:
19286  rtpg_clip_arg_destroy(arg);
19287  PG_FREE_IF_COPY(pgraster, 0);
19288  lwgeom_free(geom);
19289  elog(ERROR, "RASTER_clip: Invalid data type for NODATA values");
19290  PG_RETURN_NULL();
19291  break;
19292  }
19293 
19294  deconstruct_array(
19295  array, etype,
19296  typlen, typbyval, typalign,
19297  &e, &nulls, &k
19298  );
19299 
19300  /* it doesn't matter if there are more nodataval */
19301  for (i = 0, j = 0; i < arg->numbands; i++, j++) {
19302  /* cap j to the last nodataval element */
19303  if (j >= k)
19304  j = k - 1;
19305 
19306  if (nulls[j])
19307  continue;
19308 
19309  arg->band[i].hasnodata = 1;
19310  switch (etype) {
19311  case FLOAT4OID:
19312  arg->band[i].nodataval = DatumGetFloat4(e[j]);
19313  break;
19314  case FLOAT8OID:
19315  arg->band[i].nodataval = DatumGetFloat8(e[j]);
19316  break;
19317  }
19318  }
19319  }
19320 
19321  /* get wkb of geometry */
19322  POSTGIS_RT_DEBUG(3, "getting wkb of geometry");
19323  wkb = lwgeom_to_wkb(geom, WKB_SFSQL, &wkb_len);
19324  lwgeom_free(geom);
19325 
19326  /* rasterize geometry */
19328  wkb, wkb_len,
19329  NULL,
19330  0, NULL,
19331  NULL, NULL,
19332  NULL, NULL,
19333  NULL, NULL,
19334  &(gt[1]), &(gt[5]),
19335  NULL, NULL,
19336  &(gt[0]), &(gt[3]),
19337  &(gt[2]), &(gt[4]),
19338  NULL
19339  );
19340 
19341  pfree(wkb);
19342  if (arg->mask == NULL) {
19343  rtpg_clip_arg_destroy(arg);
19344  PG_FREE_IF_COPY(pgraster, 0);
19345  elog(ERROR, "RASTER_clip: Could not rasterize intersection geometry");
19346  PG_RETURN_NULL();
19347  }
19348 
19349  /* set SRID */
19350  rt_raster_set_srid(arg->mask, srid);
19351 
19352  /* run iterator */
19353 
19354  /* init itrset */
19355  itrset = palloc(sizeof(struct rt_iterator_t) * 2);
19356  if (itrset == NULL) {
19357  rtpg_clip_arg_destroy(arg);
19358  PG_FREE_IF_COPY(pgraster, 0);
19359  elog(ERROR, "RASTER_clip: Could not allocate memory for iterator arguments");
19360  PG_RETURN_NULL();
19361  }
19362 
19363  /* one band at a time */
19364  for (i = 0; i < arg->numbands; i++) {
19365  POSTGIS_RT_DEBUGF(4, "band arg %d (nband, hasnodata, nodataval) = (%d, %d, %f)",
19366  i, arg->band[i].nband, arg->band[i].hasnodata, arg->band[i].nodataval);
19367 
19368  band = rt_raster_get_band(arg->raster, arg->band[i].nband);
19369 
19370  /* band metadata */
19371  pixtype = rt_band_get_pixtype(band);
19372 
19373  if (arg->band[i].hasnodata) {
19374  hasnodata = 1;
19375  nodataval = arg->band[i].nodataval;
19376  }
19377  else if (rt_band_get_hasnodata_flag(band)) {
19378  hasnodata = 1;
19379  rt_band_get_nodata(band, &nodataval);
19380  }
19381  else {
19382  hasnodata = 0;
19383  nodataval = rt_band_get_min_value(band);
19384  }
19385 
19386  /* band is NODATA, create NODATA band and continue */
19387  if (rt_band_get_isnodata_flag(band)) {
19388  /* create raster */
19389  if (rtn == NULL) {
19390  noerr = rt_raster_from_two_rasters(arg->raster, arg->mask, arg->extenttype, &rtn, NULL);
19391  if (noerr != ES_NONE) {
19392  rtpg_clip_arg_destroy(arg);
19393  PG_FREE_IF_COPY(pgraster, 0);
19394  elog(ERROR, "RASTER_clip: Could not create output raster");
19395  PG_RETURN_NULL();
19396  }
19397  }
19398 
19399  /* create NODATA band */
19400  if (rt_raster_generate_new_band(rtn, pixtype, nodataval, hasnodata, nodataval, i) < 0) {
19401  rt_raster_destroy(rtn);
19402  rtpg_clip_arg_destroy(arg);
19403  PG_FREE_IF_COPY(pgraster, 0);
19404  elog(ERROR, "RASTER_clip: Could not add NODATA band to output raster");
19405  PG_RETURN_NULL();
19406  }
19407 
19408  continue;
19409  }
19410 
19411  /* raster */
19412  itrset[0].raster = arg->raster;
19413  itrset[0].nband = arg->band[i].nband;
19414  itrset[0].nbnodata = 1;
19415 
19416  /* mask */
19417  itrset[1].raster = arg->mask;
19418  itrset[1].nband = 0;
19419  itrset[1].nbnodata = 1;
19420 
19421  /* pass to iterator */
19422  noerr = rt_raster_iterator(
19423  itrset, 2,
19424  arg->extenttype, NULL,
19425  pixtype,
19426  hasnodata, nodataval,
19427  0, 0,
19428  NULL,
19430  &_raster
19431  );
19432 
19433  if (noerr != ES_NONE) {
19434  pfree(itrset);
19435  rtpg_clip_arg_destroy(arg);
19436  if (rtn != NULL) rt_raster_destroy(rtn);
19437  PG_FREE_IF_COPY(pgraster, 0);
19438  elog(ERROR, "RASTER_clip: Could not run raster iterator function");
19439  PG_RETURN_NULL();
19440  }
19441 
19442  /* new raster */
19443  if (rtn == NULL)
19444  rtn = _raster;
19445  /* copy band */
19446  else {
19447  band = rt_raster_get_band(_raster, 0);
19448  if (band == NULL) {
19449  pfree(itrset);
19450  rtpg_clip_arg_destroy(arg);
19451  rt_raster_destroy(_raster);
19452  rt_raster_destroy(rtn);
19453  PG_FREE_IF_COPY(pgraster, 0);
19454  elog(ERROR, "RASTER_clip: Could not get band from working raster");
19455  PG_RETURN_NULL();
19456  }
19457 
19458  if (rt_raster_add_band(rtn, band, i) < 0) {
19459  pfree(itrset);
19460  rtpg_clip_arg_destroy(arg);
19461  rt_raster_destroy(_raster);
19462  rt_raster_destroy(rtn);
19463  PG_FREE_IF_COPY(pgraster, 0);
19464  elog(ERROR, "RASTER_clip: Could not add new band to output raster");
19465  PG_RETURN_NULL();
19466  }
19467 
19468  rt_raster_destroy(_raster);
19469  }
19470  }
19471 
19472  pfree(itrset);
19473  rtpg_clip_arg_destroy(arg);
19474  PG_FREE_IF_COPY(pgraster, 0);
19475 
19476  pgrtn = rt_raster_serialize(rtn);
19477  rt_raster_destroy(rtn);
19478 
19479  POSTGIS_RT_DEBUG(3, "Finished");
19480 
19481  if (!pgrtn)
19482  PG_RETURN_NULL();
19483 
19484  SET_VARSIZE(pgrtn, pgrtn->size);
19485  PG_RETURN_POINTER(pgrtn);
19486 }
int rt_raster_get_num_bands(rt_raster raster)
Definition: rt_api.c:5677
int clamp_srid(int srid)
Return a valid SRID from an arbitrary integer Raises a notice if what comes out is different from wha...
Definition: lwutil.c:326
void * rt_raster_serialize(rt_raster raster)
Return this raster in serialized form.
Definition: rt_api.c:8158
void rt_raster_destroy(rt_raster raster)
Release memory associated to a raster.
Definition: rt_api.c:5387
LWGEOM * lwgeom_from_gserialized(const GSERIALIZED *g)
Allocate a new LWGEOM from a GSERIALIZED.
rt_raster mask
Definition: rt_pg.c:18964
void lwgeom_free(LWGEOM *geom)
Definition: lwgeom.c:1006
tuple gt
Definition: window.py:79
rt_pixtype rt_band_get_pixtype(rt_band band)
Return pixeltype of this band.
Definition: rt_api.c:1900
tuple band
Definition: ovdump.py:57
int rt_raster_has_band(rt_raster raster, int nband)
Return TRUE if the raster has a band of this number.
Definition: rt_api.c:8563
rt_errorstate rt_raster_from_two_rasters(rt_raster rast1, rt_raster rast2, rt_extenttype extenttype, rt_raster *rtnraster, double *offset)
Definition: rt_api.c:12876
void rt_raster_set_srid(rt_raster raster, int32_t srid)
Set raster's SRID.
Definition: rt_api.c:5668
int32_t rt_raster_get_srid(rt_raster raster)
Get raster's SRID.
Definition: rt_api.c:5661
int rt_band_get_isnodata_flag(rt_band band)
Get isnodata flag value.
Definition: rt_api.c:2042
int lwgeom_ndims(const LWGEOM *geom)
Return the number of dimensions (2, 3, 4) in a geometry.
Definition: lwgeom.c:806
#define WKB_SFSQL
Definition: liblwgeom.h:1768
void rt_raster_get_geotransform_matrix(rt_raster raster, double *gt)
Get 6-element array of raster geotransform matrix.
Definition: rt_api.c:6005
int rt_raster_add_band(rt_raster raster, rt_band band, int index)
Add band data to a raster.
Definition: rt_api.c:5706
rt_extenttype extenttype
Definition: rt_pg.c:18962
uint8_t * lwgeom_to_wkb(const LWGEOM *geom, uint8_t variant, size_t *size_out)
Convert LWGEOM to a char* in WKB format.
Definition: lwout_wkb.c:692
rt_pixtype
Definition: rt_api.h:172
#define POSTGIS_RT_DEBUG(level, msg)
Definition: rt_pg.h:58
static int rtpg_clip_callback(rt_iterator_arg arg, void *userarg, double *value, int *nodata)
Definition: rt_pg.c:19000
double rt_band_get_min_value(rt_band band)
Returns the minimal possible value for the band according to the pixel type.
Definition: rt_api.c:3073
static rtpg_clip_arg rtpg_clip_arg_init()
Definition: rt_pg.c:18970
rt_raster rt_raster_gdal_rasterize(const unsigned char *wkb, uint32_t wkb_len, const char *srs, uint32_t num_bands, rt_pixtype *pixtype, double *init, double *value, double *nodata, uint8_t *hasnodata, int *width, int *height, double *scale_x, double *scale_y, double *ul_xw, double *ul_yw, double *grid_xw, double *grid_yw, double *skew_x, double *skew_y, char **options)
Return a raster of the provided geometry.
Definition: rt_api.c:10620
#define SRID_UNKNOWN
Unknown SRID value.
Definition: liblwgeom.h:154
rt_errorstate rt_band_get_nodata(rt_band band, double *nodata)
Get NODATA value.
Definition: rt_api.c:3058
LWGEOM * lwgeom_intersection(const LWGEOM *geom1, const LWGEOM *geom2)
LWGEOM * lwgeom_force_2d(const LWGEOM *geom)
Strip out the Z/M components of an LWGEOM.
Definition: lwgeom.c:646
double nodataval
Definition: rt_pg.c:18957
rt_raster raster
Definition: rt_pg.c:18963
rt_raster raster
Definition: rt_api.h:2360
static void rtpg_clip_arg_destroy(rtpg_clip_arg arg)
Definition: rt_pg.c:18988
uint16_t nband
Definition: rt_api.h:2361
rtpg_clip_band band
Definition: rt_pg.c:18967
rt_band rt_raster_get_band(rt_raster raster, int n)
Return Nth band, or NULL if unavailable.
Definition: rt_api.c:5686
#define FALSE
Definition: dbfopen.c:169
uint8_t nbnodata
Definition: rt_api.h:2362
Struct definitions.
Definition: rt_api.h:2175
#define POSTGIS_RT_DEBUGF(level, msg,...)
Definition: rt_pg.h:62
int rt_raster_is_empty(rt_raster raster)
Return TRUE if the raster is empty.
Definition: rt_api.c:8550
rt_errorstate rt_raster_iterator(rt_iterator itrset, uint16_t itrcount, rt_extenttype extenttype, rt_raster customextent, rt_pixtype pixtype, uint8_t hasnodata, double nodataval, uint16_t distancex, uint16_t distancey, void *userarg, int(*callback)(rt_iterator_arg arg, void *userarg, double *value, int *nodata), rt_raster *rtnraster)
n-raster iterator.
Definition: rt_api.c:13927
rt_raster rt_raster_deserialize(void *serialized, int header_only)
Return a raster from a serialized form.
Definition: rt_api.c:8350
rt_errorstate rt_raster_get_convex_hull(rt_raster raster, LWGEOM **hull)
Get raster's convex hull.
Definition: rt_api.c:6556
int lwgeom_is_empty(const LWGEOM *geom)
Return true or false depending on whether a geometry is an "empty" geometry (no vertices members) ...
Definition: lwgeom.c:1229
rt_raster rt_raster_new(uint32_t width, uint32_t height)
Construct a raster with given dimensions.
Definition: rt_api.c:5353
int rt_band_get_hasnodata_flag(rt_band band)
Get hasnodata flag value.
Definition: rt_api.c:2002
int32_t gserialized_get_srid(const GSERIALIZED *s)
Extract the SRID from the serialized form (it is packed into three bytes so this is a handy function)...
Definition: g_serialized.c:70
int rt_raster_generate_new_band(rt_raster raster, rt_pixtype pixtype, double initialvalue, uint32_t hasnodata, double nodatavalue, int index)
Generate a new inline band and add it to a raster.
Definition: rt_api.c:5784

Here is the call graph for this function: