PostGIS  3.1.6dev-r@@SVN_REVISION@@

◆ RASTER_mapAlgebra2()

Datum RASTER_mapAlgebra2 ( PG_FUNCTION_ARGS  )

Definition at line 6230 of file rtpg_mapalgebra.c.

6231 {
6232  const uint32_t set_count = 2;
6233  rt_pgraster *pgrast[2] = { NULL, NULL };
6234  int pgrastpos[2] = {-1, -1};
6235  rt_pgraster *pgrtn;
6236  rt_raster rast[2] = {NULL};
6237  int _isempty[2] = {0};
6238  uint32_t bandindex[2] = {0};
6239  rt_raster _rast[2] = {NULL};
6240  rt_band _band[2] = {NULL};
6241  int _hasnodata[2] = {0};
6242  double _nodataval[2] = {0};
6243  double _offset[4] = {0.};
6244  double _rastoffset[2][4] = {{0.}};
6245  int _haspixel[2] = {0};
6246  double _pixel[2] = {0};
6247  int _pos[2][2] = {{0}};
6248  uint16_t _dim[2][2] = {{0}};
6249 
6250  char *pixtypename = NULL;
6251  rt_pixtype pixtype = PT_END;
6252  char *extenttypename = NULL;
6253  rt_extenttype extenttype = ET_INTERSECTION;
6254 
6255  rt_raster raster = NULL;
6256  rt_band band = NULL;
6257  uint16_t dim[2] = {0};
6258  int haspixel = 0;
6259  double pixel = 0.;
6260  double nodataval = 0;
6261  double gt[6] = {0.};
6262 
6263  Oid calltype = InvalidOid;
6264 
6265  const uint32_t spi_count = 3;
6266  uint16_t spi_exprpos[3] = {4, 7, 8};
6267  uint32_t spi_argcount[3] = {0};
6268  char *expr = NULL;
6269  char *sql = NULL;
6270  SPIPlanPtr spi_plan[3] = {NULL};
6271  uint16_t spi_empty = 0;
6272  Oid *argtype = NULL;
6273  uint8_t argpos[3][8] = {{0}};
6274  char *argkw[] = {"[rast1.x]", "[rast1.y]", "[rast1.val]", "[rast1]", "[rast2.x]", "[rast2.y]", "[rast2.val]", "[rast2]"};
6275  Datum values[ARGKWCOUNT];
6276  char nulls[ARGKWCOUNT];
6277  TupleDesc tupdesc;
6278  SPITupleTable *tuptable = NULL;
6279  HeapTuple tuple;
6280  Datum datum;
6281  bool isnull = FALSE;
6282  int hasargval[3] = {0};
6283  double argval[3] = {0.};
6284  int hasnodatanodataval = 0;
6285  double nodatanodataval = 0;
6286  int isnodata = 0;
6287 
6288  Oid ufc_noid = InvalidOid;
6289  FmgrInfo ufl_info;
6290 #if POSTGIS_PGSQL_VERSION < 120
6291  FunctionCallInfoData ufc_info;
6292 #else
6293  LOCAL_FCINFO(ufc_info, FUNC_MAX_ARGS); /* Could be optimized */
6294 #endif
6295  int ufc_nullcount = 0;
6296 
6297  int idx = 0;
6298  uint32_t i = 0;
6299  uint32_t j = 0;
6300  uint32_t k = 0;
6301  uint32_t x = 0;
6302  uint32_t y = 0;
6303  int _x = 0;
6304  int _y = 0;
6305  int err;
6306  int aligned = 0;
6307  int len = 0;
6308 
6309  POSTGIS_RT_DEBUG(3, "Starting RASTER_mapAlgebra2");
6310 
6311  for (i = 0, j = 0; i < set_count; i++) {
6312  if (!PG_ARGISNULL(j)) {
6313  pgrast[i] = (rt_pgraster *) PG_DETOAST_DATUM(PG_GETARG_DATUM(j));
6314  pgrastpos[i] = j;
6315  j++;
6316 
6317  /* raster */
6318  rast[i] = rt_raster_deserialize(pgrast[i], FALSE);
6319  if (!rast[i]) {
6320  for (k = 0; k <= i; k++) {
6321  if (k < i && rast[k] != NULL)
6322  rt_raster_destroy(rast[k]);
6323  if (pgrastpos[k] != -1)
6324  PG_FREE_IF_COPY(pgrast[k], pgrastpos[k]);
6325  }
6326  elog(ERROR, "RASTER_mapAlgebra2: Could not deserialize the %s raster", i < 1 ? "first" : "second");
6327  PG_RETURN_NULL();
6328  }
6329 
6330  /* empty */
6331  _isempty[i] = rt_raster_is_empty(rast[i]);
6332 
6333  /* band index */
6334  if (!PG_ARGISNULL(j)) {
6335  bandindex[i] = PG_GETARG_INT32(j);
6336  }
6337  j++;
6338  }
6339  else {
6340  _isempty[i] = 1;
6341  j += 2;
6342  }
6343 
6344  POSTGIS_RT_DEBUGF(3, "_isempty[%d] = %d", i, _isempty[i]);
6345  }
6346 
6347  /* both rasters are NULL */
6348  if (rast[0] == NULL && rast[1] == NULL) {
6349  elog(NOTICE, "The two rasters provided are NULL. Returning NULL");
6350  for (k = 0; k < set_count; k++) {
6351  if (pgrastpos[k] != -1)
6352  PG_FREE_IF_COPY(pgrast[k], pgrastpos[k]);
6353  }
6354  PG_RETURN_NULL();
6355  }
6356 
6357  /* both rasters are empty */
6358  if (_isempty[0] && _isempty[1]) {
6359  elog(NOTICE, "The two rasters provided are empty. Returning empty raster");
6360 
6361  raster = rt_raster_new(0, 0);
6362  if (raster == NULL) {
6363  for (k = 0; k < set_count; k++) {
6364  if (rast[k] != NULL)
6365  rt_raster_destroy(rast[k]);
6366  if (pgrastpos[k] != -1)
6367  PG_FREE_IF_COPY(pgrast[k], pgrastpos[k]);
6368  }
6369  elog(ERROR, "RASTER_mapAlgebra2: Could not create empty raster");
6370  PG_RETURN_NULL();
6371  }
6372  rt_raster_set_scale(raster, 0, 0);
6373 
6374  pgrtn = rt_raster_serialize(raster);
6376  if (!pgrtn)
6377  PG_RETURN_NULL();
6378 
6379  SET_VARSIZE(pgrtn, pgrtn->size);
6380  PG_RETURN_POINTER(pgrtn);
6381  }
6382 
6383  /* replace the empty or NULL raster with one matching the other */
6384  if (
6385  (rast[0] == NULL || _isempty[0]) ||
6386  (rast[1] == NULL || _isempty[1])
6387  ) {
6388  /* first raster is empty */
6389  if (rast[0] == NULL || _isempty[0]) {
6390  i = 0;
6391  j = 1;
6392  }
6393  /* second raster is empty */
6394  else {
6395  i = 1;
6396  j = 0;
6397  }
6398 
6399  _rast[j] = rast[j];
6400 
6401  /* raster is empty, destroy it */
6402  if (_rast[i] != NULL)
6403  rt_raster_destroy(_rast[i]);
6404 
6405  _dim[i][0] = rt_raster_get_width(_rast[j]);
6406  _dim[i][1] = rt_raster_get_height(_rast[j]);
6407  _dim[j][0] = rt_raster_get_width(_rast[j]);
6408  _dim[j][1] = rt_raster_get_height(_rast[j]);
6409 
6410  _rast[i] = rt_raster_new(
6411  _dim[j][0],
6412  _dim[j][1]
6413  );
6414  if (_rast[i] == NULL) {
6415  rt_raster_destroy(_rast[j]);
6416  for (k = 0; k < set_count; k++) {
6417  if (pgrastpos[k] != -1)
6418  PG_FREE_IF_COPY(pgrast[k], pgrastpos[k]);
6419  }
6420  elog(ERROR, "RASTER_mapAlgebra2: Could not create NODATA raster");
6421  PG_RETURN_NULL();
6422  }
6423  rt_raster_set_srid(_rast[i], rt_raster_get_srid(_rast[j]));
6424 
6427  }
6428  else {
6429  _rast[0] = rast[0];
6430  _dim[0][0] = rt_raster_get_width(_rast[0]);
6431  _dim[0][1] = rt_raster_get_height(_rast[0]);
6432 
6433  _rast[1] = rast[1];
6434  _dim[1][0] = rt_raster_get_width(_rast[1]);
6435  _dim[1][1] = rt_raster_get_height(_rast[1]);
6436  }
6437 
6438  /* SRID must match */
6439  /*
6440  if (rt_raster_get_srid(_rast[0]) != rt_raster_get_srid(_rast[1])) {
6441  elog(NOTICE, "The two rasters provided have different SRIDs. Returning NULL");
6442  for (k = 0; k < set_count; k++) {
6443  if (_rast[k] != NULL)
6444  rt_raster_destroy(_rast[k]);
6445  if (pgrastpos[k] != -1)
6446  PG_FREE_IF_COPY(pgrast[k], pgrastpos[k]);
6447  }
6448  PG_RETURN_NULL();
6449  }
6450  */
6451 
6452  /* same alignment */
6453  if (rt_raster_same_alignment(_rast[0], _rast[1], &aligned, NULL) != ES_NONE) {
6454  for (k = 0; k < set_count; k++) {
6455  if (_rast[k] != NULL)
6456  rt_raster_destroy(_rast[k]);
6457  if (pgrastpos[k] != -1)
6458  PG_FREE_IF_COPY(pgrast[k], pgrastpos[k]);
6459  }
6460  elog(ERROR, "RASTER_mapAlgebra2: Could not test for alignment on the two rasters");
6461  PG_RETURN_NULL();
6462  }
6463  if (!aligned) {
6464  elog(NOTICE, "The two rasters provided do not have the same alignment. Returning NULL");
6465  for (k = 0; k < set_count; k++) {
6466  if (_rast[k] != NULL)
6467  rt_raster_destroy(_rast[k]);
6468  if (pgrastpos[k] != -1)
6469  PG_FREE_IF_COPY(pgrast[k], pgrastpos[k]);
6470  }
6471  PG_RETURN_NULL();
6472  }
6473 
6474  /* pixel type */
6475  if (!PG_ARGISNULL(5)) {
6476  pixtypename = text_to_cstring(PG_GETARG_TEXT_P(5));
6477  /* Get the pixel type index */
6478  pixtype = rt_pixtype_index_from_name(pixtypename);
6479  if (pixtype == PT_END ) {
6480  for (k = 0; k < set_count; k++) {
6481  if (_rast[k] != NULL)
6482  rt_raster_destroy(_rast[k]);
6483  if (pgrastpos[k] != -1)
6484  PG_FREE_IF_COPY(pgrast[k], pgrastpos[k]);
6485  }
6486  elog(ERROR, "RASTER_mapAlgebra2: Invalid pixel type: %s", pixtypename);
6487  PG_RETURN_NULL();
6488  }
6489  }
6490 
6491  /* extent type */
6492  if (!PG_ARGISNULL(6)) {
6493  extenttypename = rtpg_strtoupper(rtpg_trim(text_to_cstring(PG_GETARG_TEXT_P(6))));
6494  extenttype = rt_util_extent_type(extenttypename);
6495  }
6496  POSTGIS_RT_DEBUGF(3, "extenttype: %d %s", extenttype, extenttypename);
6497 
6498  /* computed raster from extent type */
6500  _rast[0], _rast[1],
6501  extenttype,
6502  &raster, _offset
6503  );
6504  if (err != ES_NONE) {
6505  for (k = 0; k < set_count; k++) {
6506  if (_rast[k] != NULL)
6507  rt_raster_destroy(_rast[k]);
6508  if (pgrastpos[k] != -1)
6509  PG_FREE_IF_COPY(pgrast[k], pgrastpos[k]);
6510  }
6511  elog(ERROR, "RASTER_mapAlgebra2: Could not get output raster of correct extent");
6512  PG_RETURN_NULL();
6513  }
6514 
6515  /* copy offsets */
6516  _rastoffset[0][0] = _offset[0];
6517  _rastoffset[0][1] = _offset[1];
6518  _rastoffset[1][0] = _offset[2];
6519  _rastoffset[1][1] = _offset[3];
6520 
6521  /* get output raster dimensions */
6522  dim[0] = rt_raster_get_width(raster);
6523  dim[1] = rt_raster_get_height(raster);
6524 
6525  i = 2;
6526  /* handle special cases for extent */
6527  switch (extenttype) {
6528  case ET_FIRST:
6529  i = 0;
6530  /* fall through */
6531  case ET_SECOND:
6532  if (i > 1)
6533  i = 1;
6534 
6535  if (
6536  _isempty[i] && (
6537  (extenttype == ET_FIRST && i == 0) ||
6538  (extenttype == ET_SECOND && i == 1)
6539  )
6540  ) {
6541  elog(NOTICE, "The %s raster is NULL. Returning NULL", (i != 1 ? "FIRST" : "SECOND"));
6542  for (k = 0; k < set_count; k++) {
6543  if (_rast[k] != NULL)
6544  rt_raster_destroy(_rast[k]);
6545  if (pgrastpos[k] != -1)
6546  PG_FREE_IF_COPY(pgrast[k], pgrastpos[k]);
6547  }
6549  PG_RETURN_NULL();
6550  }
6551 
6552  /* specified band not found */
6553  if (!rt_raster_has_band(_rast[i], bandindex[i] - 1)) {
6554  elog(NOTICE, "The %s raster does not have the band at index %d. Returning no band raster of correct extent",
6555  (i != 1 ? "FIRST" : "SECOND"), bandindex[i]
6556  );
6557 
6558  for (k = 0; k < set_count; k++) {
6559  if (_rast[k] != NULL)
6560  rt_raster_destroy(_rast[k]);
6561  if (pgrastpos[k] != -1)
6562  PG_FREE_IF_COPY(pgrast[k], pgrastpos[k]);
6563  }
6564 
6565  pgrtn = rt_raster_serialize(raster);
6567  if (!pgrtn) PG_RETURN_NULL();
6568 
6569  SET_VARSIZE(pgrtn, pgrtn->size);
6570  PG_RETURN_POINTER(pgrtn);
6571  }
6572  break;
6573  case ET_UNION:
6574  break;
6575  case ET_INTERSECTION:
6576  /* no intersection */
6577  if (
6578  _isempty[0] || _isempty[1] ||
6579  !dim[0] || !dim[1]
6580  ) {
6581  elog(NOTICE, "The two rasters provided have no intersection. Returning no band raster");
6582 
6583  /* raster has dimension, replace with no band raster */
6584  if (dim[0] || dim[1]) {
6586 
6587  raster = rt_raster_new(0, 0);
6588  if (raster == NULL) {
6589  for (k = 0; k < set_count; k++) {
6590  if (_rast[k] != NULL)
6591  rt_raster_destroy(_rast[k]);
6592  if (pgrastpos[k] != -1)
6593  PG_FREE_IF_COPY(pgrast[k], pgrastpos[k]);
6594  }
6595  elog(ERROR, "RASTER_mapAlgebra2: Could not create no band raster");
6596  PG_RETURN_NULL();
6597  }
6598 
6599  rt_raster_set_scale(raster, 0, 0);
6601  }
6602 
6603  for (k = 0; k < set_count; k++) {
6604  if (_rast[k] != NULL)
6605  rt_raster_destroy(_rast[k]);
6606  if (pgrastpos[k] != -1)
6607  PG_FREE_IF_COPY(pgrast[k], pgrastpos[k]);
6608  }
6609 
6610  pgrtn = rt_raster_serialize(raster);
6612  if (!pgrtn) PG_RETURN_NULL();
6613 
6614  SET_VARSIZE(pgrtn, pgrtn->size);
6615  PG_RETURN_POINTER(pgrtn);
6616  }
6617  break;
6618  case ET_LAST:
6619  case ET_CUSTOM:
6620  for (k = 0; k < set_count; k++) {
6621  if (_rast[k] != NULL)
6622  rt_raster_destroy(_rast[k]);
6623  if (pgrastpos[k] != -1)
6624  PG_FREE_IF_COPY(pgrast[k], pgrastpos[k]);
6625  }
6626  elog(ERROR, "RASTER_mapAlgebra2: ET_LAST and ET_CUSTOM are not implemented");
6627  PG_RETURN_NULL();
6628  break;
6629  }
6630 
6631  /* both rasters do not have specified bands */
6632  if (
6633  (!_isempty[0] && !rt_raster_has_band(_rast[0], bandindex[0] - 1)) &&
6634  (!_isempty[1] && !rt_raster_has_band(_rast[1], bandindex[1] - 1))
6635  ) {
6636  elog(NOTICE, "The two rasters provided do not have the respectively specified band indices. Returning no band raster of correct extent");
6637 
6638  for (k = 0; k < set_count; k++) {
6639  if (_rast[k] != NULL)
6640  rt_raster_destroy(_rast[k]);
6641  if (pgrastpos[k] != -1)
6642  PG_FREE_IF_COPY(pgrast[k], pgrastpos[k]);
6643  }
6644 
6645  pgrtn = rt_raster_serialize(raster);
6647  if (!pgrtn) PG_RETURN_NULL();
6648 
6649  SET_VARSIZE(pgrtn, pgrtn->size);
6650  PG_RETURN_POINTER(pgrtn);
6651  }
6652 
6653  /* get bands */
6654  for (i = 0; i < set_count; i++) {
6655  if (_isempty[i] || !rt_raster_has_band(_rast[i], bandindex[i] - 1)) {
6656  _hasnodata[i] = 1;
6657  _nodataval[i] = 0;
6658 
6659  continue;
6660  }
6661 
6662  _band[i] = rt_raster_get_band(_rast[i], bandindex[i] - 1);
6663  if (_band[i] == NULL) {
6664  for (k = 0; k < set_count; k++) {
6665  if (_rast[k] != NULL)
6666  rt_raster_destroy(_rast[k]);
6667  if (pgrastpos[k] != -1)
6668  PG_FREE_IF_COPY(pgrast[k], pgrastpos[k]);
6669  }
6671  elog(ERROR, "RASTER_mapAlgebra2: Could not get band %d of the %s raster",
6672  bandindex[i],
6673  (i < 1 ? "FIRST" : "SECOND")
6674  );
6675  PG_RETURN_NULL();
6676  }
6677 
6678  _hasnodata[i] = rt_band_get_hasnodata_flag(_band[i]);
6679  if (_hasnodata[i])
6680  rt_band_get_nodata(_band[i], &(_nodataval[i]));
6681  }
6682 
6683  /* pixtype is PT_END, get pixtype based upon extent */
6684  if (pixtype == PT_END) {
6685  if ((extenttype == ET_SECOND && !_isempty[1]) || _isempty[0])
6686  pixtype = rt_band_get_pixtype(_band[1]);
6687  else
6688  pixtype = rt_band_get_pixtype(_band[0]);
6689  }
6690 
6691  /* nodata value for new band */
6692  if (extenttype == ET_SECOND && !_isempty[1] && _hasnodata[1]) {
6693  nodataval = _nodataval[1];
6694  }
6695  else if (!_isempty[0] && _hasnodata[0]) {
6696  nodataval = _nodataval[0];
6697  }
6698  else if (!_isempty[1] && _hasnodata[1]) {
6699  nodataval = _nodataval[1];
6700  }
6701  else {
6702  elog(NOTICE, "Neither raster provided has a NODATA value for the specified band indices. NODATA value set to minimum possible for %s", rt_pixtype_name(pixtype));
6703  nodataval = rt_pixtype_get_min_value(pixtype);
6704  }
6705 
6706  /* add band to output raster */
6708  raster,
6709  pixtype,
6710  nodataval,
6711  1, nodataval,
6712  0
6713  ) < 0) {
6714  for (k = 0; k < set_count; k++) {
6715  if (_rast[k] != NULL)
6716  rt_raster_destroy(_rast[k]);
6717  if (pgrastpos[k] != -1)
6718  PG_FREE_IF_COPY(pgrast[k], pgrastpos[k]);
6719  }
6721  elog(ERROR, "RASTER_mapAlgebra2: Could not add new band to output raster");
6722  PG_RETURN_NULL();
6723  }
6724 
6725  /* get output band */
6727  if (band == NULL) {
6728  for (k = 0; k < set_count; k++) {
6729  if (_rast[k] != NULL)
6730  rt_raster_destroy(_rast[k]);
6731  if (pgrastpos[k] != -1)
6732  PG_FREE_IF_COPY(pgrast[k], pgrastpos[k]);
6733  }
6735  elog(ERROR, "RASTER_mapAlgebra2: Could not get newly added band of output raster");
6736  PG_RETURN_NULL();
6737  }
6738 
6739  POSTGIS_RT_DEBUGF(4, "offsets = (%d, %d, %d, %d)",
6740  (int) _rastoffset[0][0],
6741  (int) _rastoffset[0][1],
6742  (int) _rastoffset[1][0],
6743  (int) _rastoffset[1][1]
6744  );
6745 
6746  POSTGIS_RT_DEBUGF(4, "metadata = (%f, %f, %d, %d, %f, %f, %f, %f, %d)",
6756  );
6757 
6758  /*
6759  determine who called this function
6760  Arg 4 will either be text or regprocedure
6761  */
6762  POSTGIS_RT_DEBUG(3, "checking parameter type for arg 4");
6763  calltype = get_fn_expr_argtype(fcinfo->flinfo, 4);
6764 
6765  switch(calltype) {
6766  case TEXTOID: {
6767  POSTGIS_RT_DEBUG(3, "arg 4 is \"expression\"!");
6768 
6769  /* connect SPI */
6770  if (SPI_connect() != SPI_OK_CONNECT) {
6771  for (k = 0; k < set_count; k++) {
6772  if (_rast[k] != NULL)
6773  rt_raster_destroy(_rast[k]);
6774  if (pgrastpos[k] != -1)
6775  PG_FREE_IF_COPY(pgrast[k], pgrastpos[k]);
6776  }
6778  elog(ERROR, "RASTER_mapAlgebra2: Could not connect to the SPI manager");
6779  PG_RETURN_NULL();
6780  }
6781 
6782  /* reset hasargval */
6783  memset(hasargval, 0, sizeof(int) * spi_count);
6784 
6785  /*
6786  process expressions
6787 
6788  spi_exprpos elements are:
6789  4 - expression => spi_plan[0]
6790  7 - nodata1expr => spi_plan[1]
6791  8 - nodata2expr => spi_plan[2]
6792  */
6793  for (i = 0; i < spi_count; i++) {
6794  if (!PG_ARGISNULL(spi_exprpos[i])) {
6795  char *tmp = NULL;
6796  char place[5] = "$1";
6797  expr = text_to_cstring(PG_GETARG_TEXT_P(spi_exprpos[i]));
6798  POSTGIS_RT_DEBUGF(3, "raw expr #%d: %s", i, expr);
6799 
6800  for (j = 0, k = 1; j < ARGKWCOUNT; j++) {
6801  /* attempt to replace keyword with placeholder */
6802  len = 0;
6803  tmp = rtpg_strreplace(expr, argkw[j], place, &len);
6804  pfree(expr);
6805  expr = tmp;
6806 
6807  if (len) {
6808  spi_argcount[i]++;
6809  argpos[i][j] = k++;
6810 
6811  sprintf(place, "$%d", k);
6812  }
6813  else
6814  argpos[i][j] = 0;
6815  }
6816 
6817  len = strlen("SELECT (") + strlen(expr) + strlen(")::double precision");
6818  sql = (char *) palloc(len + 1);
6819  if (sql == NULL) {
6820 
6821  for (k = 0; k < spi_count; k++) SPI_freeplan(spi_plan[k]);
6822  SPI_finish();
6823 
6824  for (k = 0; k < set_count; k++) {
6825  if (_rast[k] != NULL)
6826  rt_raster_destroy(_rast[k]);
6827  if (pgrastpos[k] != -1)
6828  PG_FREE_IF_COPY(pgrast[k], pgrastpos[k]);
6829  }
6831 
6832  elog(ERROR, "RASTER_mapAlgebra2: Could not allocate memory for expression parameter %d", spi_exprpos[i]);
6833  PG_RETURN_NULL();
6834  }
6835 
6836  memcpy(sql, "SELECT (", strlen("SELECT ("));
6837  memcpy(sql + strlen("SELECT ("), expr, strlen(expr));
6838  memcpy(sql + strlen("SELECT (") + strlen(expr), ")::double precision", strlen(")::double precision"));
6839  sql[len] = '\0';
6840 
6841  POSTGIS_RT_DEBUGF(3, "sql #%d: %s", i, sql);
6842 
6843  /* create prepared plan */
6844  if (spi_argcount[i]) {
6845  argtype = (Oid *) palloc(spi_argcount[i] * sizeof(Oid));
6846  if (argtype == NULL) {
6847 
6848  pfree(sql);
6849  for (k = 0; k < spi_count; k++) SPI_freeplan(spi_plan[k]);
6850  SPI_finish();
6851 
6852  for (k = 0; k < set_count; k++) {
6853  if (_rast[k] != NULL)
6854  rt_raster_destroy(_rast[k]);
6855  if (pgrastpos[k] != -1)
6856  PG_FREE_IF_COPY(pgrast[k], pgrastpos[k]);
6857  }
6859 
6860  elog(ERROR, "RASTER_mapAlgebra2: Could not allocate memory for prepared plan argtypes of expression parameter %d", spi_exprpos[i]);
6861  PG_RETURN_NULL();
6862  }
6863 
6864  /* specify datatypes of parameters */
6865  for (j = 0, k = 0; j < ARGKWCOUNT; j++) {
6866  if (argpos[i][j] < 1) continue;
6867 
6868  /* positions are INT4 */
6869  if (
6870  (strstr(argkw[j], "[rast1.x]") != NULL) ||
6871  (strstr(argkw[j], "[rast1.y]") != NULL) ||
6872  (strstr(argkw[j], "[rast2.x]") != NULL) ||
6873  (strstr(argkw[j], "[rast2.y]") != NULL)
6874  ) {
6875  argtype[k] = INT4OID;
6876  }
6877  /* everything else is FLOAT8 */
6878  else {
6879  argtype[k] = FLOAT8OID;
6880  }
6881 
6882  k++;
6883  }
6884 
6885  spi_plan[i] = SPI_prepare(sql, spi_argcount[i], argtype);
6886  pfree(argtype);
6887 
6888  if (spi_plan[i] == NULL) {
6889 
6890  pfree(sql);
6891  for (k = 0; k < spi_count; k++) SPI_freeplan(spi_plan[k]);
6892  SPI_finish();
6893 
6894  for (k = 0; k < set_count; k++) {
6895  if (_rast[k] != NULL)
6896  rt_raster_destroy(_rast[k]);
6897  if (pgrastpos[k] != -1)
6898  PG_FREE_IF_COPY(pgrast[k], pgrastpos[k]);
6899  }
6901 
6902  elog(ERROR, "RASTER_mapAlgebra2: Could not create prepared plan of expression parameter %d", spi_exprpos[i]);
6903  PG_RETURN_NULL();
6904  }
6905  }
6906  /* no args, just execute query */
6907  else {
6908  err = SPI_execute(sql, TRUE, 0);
6909  if (err != SPI_OK_SELECT || SPI_tuptable == NULL || SPI_processed != 1) {
6910 
6911  pfree(sql);
6912  for (k = 0; k < spi_count; k++) SPI_freeplan(spi_plan[k]);
6913  SPI_finish();
6914 
6915  for (k = 0; k < set_count; k++) {
6916  if (_rast[k] != NULL)
6917  rt_raster_destroy(_rast[k]);
6918  if (pgrastpos[k] != -1)
6919  PG_FREE_IF_COPY(pgrast[k], pgrastpos[k]);
6920  }
6922 
6923  elog(ERROR, "RASTER_mapAlgebra2: Could not evaluate expression parameter %d", spi_exprpos[i]);
6924  PG_RETURN_NULL();
6925  }
6926 
6927  /* get output of prepared plan */
6928  tupdesc = SPI_tuptable->tupdesc;
6929  tuptable = SPI_tuptable;
6930  tuple = tuptable->vals[0];
6931 
6932  datum = SPI_getbinval(tuple, tupdesc, 1, &isnull);
6933  if (SPI_result == SPI_ERROR_NOATTRIBUTE) {
6934 
6935  pfree(sql);
6936  if (SPI_tuptable) SPI_freetuptable(tuptable);
6937  for (k = 0; k < spi_count; k++) SPI_freeplan(spi_plan[k]);
6938  SPI_finish();
6939 
6940  for (k = 0; k < set_count; k++) {
6941  if (_rast[k] != NULL)
6942  rt_raster_destroy(_rast[k]);
6943  if (pgrastpos[k] != -1)
6944  PG_FREE_IF_COPY(pgrast[k], pgrastpos[k]);
6945  }
6947 
6948  elog(ERROR, "RASTER_mapAlgebra2: Could not get result of expression parameter %d", spi_exprpos[i]);
6949  PG_RETURN_NULL();
6950  }
6951 
6952  if (!isnull) {
6953  hasargval[i] = 1;
6954  argval[i] = DatumGetFloat8(datum);
6955  }
6956 
6957  if (SPI_tuptable) SPI_freetuptable(tuptable);
6958  }
6959 
6960  pfree(sql);
6961  }
6962  else
6963  spi_empty++;
6964  }
6965 
6966  /* nodatanodataval */
6967  if (!PG_ARGISNULL(9)) {
6968  hasnodatanodataval = 1;
6969  nodatanodataval = PG_GETARG_FLOAT8(9);
6970  }
6971  else
6972  hasnodatanodataval = 0;
6973  break;
6974  }
6975  case REGPROCEDUREOID: {
6976  POSTGIS_RT_DEBUG(3, "arg 4 is \"userfunction\"!");
6977  if (!PG_ARGISNULL(4)) {
6978 
6979  ufc_nullcount = 0;
6980  ufc_noid = PG_GETARG_OID(4);
6981 
6982  /* get function info */
6983  fmgr_info(ufc_noid, &ufl_info);
6984 
6985  /* function cannot return set */
6986  err = 0;
6987  if (ufl_info.fn_retset) {
6988  err = 1;
6989  }
6990  /* function should have correct # of args */
6991  else if (ufl_info.fn_nargs < 3 || ufl_info.fn_nargs > 4) {
6992  err = 2;
6993  }
6994 
6995  /*
6996  TODO: consider adding checks of the userfunction parameters
6997  should be able to use get_fn_expr_argtype() of fmgr.c
6998  */
6999 
7000  if (err > 0) {
7001  for (k = 0; k < set_count; k++) {
7002  if (_rast[k] != NULL)
7003  rt_raster_destroy(_rast[k]);
7004  if (pgrastpos[k] != -1)
7005  PG_FREE_IF_COPY(pgrast[k], pgrastpos[k]);
7006  }
7008 
7009  if (err > 1)
7010  elog(ERROR, "RASTER_mapAlgebra2: Function provided must have three or four input parameters");
7011  else
7012  elog(ERROR, "RASTER_mapAlgebra2: Function provided must return double precision not resultset");
7013  PG_RETURN_NULL();
7014  }
7015 
7016  if (func_volatile(ufc_noid) == 'v') {
7017  elog(NOTICE, "Function provided is VOLATILE. Unless required and for best performance, function should be IMMUTABLE or STABLE");
7018  }
7019 
7020  /* prep function call data */
7021 #if POSTGIS_PGSQL_VERSION < 120
7022  InitFunctionCallInfoData(ufc_info, &ufl_info, ufl_info.fn_nargs, InvalidOid, NULL, NULL);
7023  memset(ufc_info.argnull, FALSE, sizeof(bool) * ufl_info.fn_nargs);
7024 #else
7025  InitFunctionCallInfoData(
7026  *ufc_info, &ufl_info, ufl_info.fn_nargs, InvalidOid, NULL, NULL);
7027  ufc_info->args[0].isnull = FALSE;
7028  ufc_info->args[1].isnull = FALSE;
7029  ufc_info->args[2].isnull = FALSE;
7030  if (ufl_info.fn_nargs == 4)
7031  ufc_info->args[3].isnull = FALSE;
7032 #endif
7033 
7034  if (ufl_info.fn_nargs != 4)
7035  k = 2;
7036  else
7037  k = 3;
7038 #if POSTGIS_PGSQL_VERSION < 120
7039  if (!PG_ARGISNULL(7)) {
7040  ufc_info.arg[k] = PG_GETARG_DATUM(7);
7041  }
7042  else {
7043  ufc_info.arg[k] = (Datum) NULL;
7044  ufc_info.argnull[k] = TRUE;
7045  ufc_nullcount++;
7046  }
7047 #else
7048  if (!PG_ARGISNULL(7))
7049  {
7050  ufc_info->args[k].value = PG_GETARG_DATUM(7);
7051  }
7052  else
7053  {
7054  ufc_info->args[k].value = (Datum)NULL;
7055  ufc_info->args[k].isnull = TRUE;
7056  ufc_nullcount++;
7057  }
7058 #endif
7059  }
7060  break;
7061  }
7062  default:
7063  for (k = 0; k < set_count; k++) {
7064  if (_rast[k] != NULL)
7065  rt_raster_destroy(_rast[k]);
7066  if (pgrastpos[k] != -1)
7067  PG_FREE_IF_COPY(pgrast[k], pgrastpos[k]);
7068  }
7070  elog(ERROR, "RASTER_mapAlgebra2: Invalid data type for expression or userfunction");
7071  PG_RETURN_NULL();
7072  break;
7073  }
7074 
7075  /* loop over pixels */
7076  /* if any expression present, run */
7077  if ((
7078  (calltype == TEXTOID) && (
7079  (spi_empty != spi_count) || hasnodatanodataval
7080  )
7081  ) || (
7082  (calltype == REGPROCEDUREOID) && (ufc_noid != InvalidOid)
7083  )) {
7084  for (x = 0; x < dim[0]; x++) {
7085  for (y = 0; y < dim[1]; y++) {
7086 
7087  /* get pixel from each raster */
7088  for (i = 0; i < set_count; i++) {
7089  _haspixel[i] = 0;
7090  _pixel[i] = 0;
7091 
7092  /* row/column */
7093  _x = (int)x - (int)_rastoffset[i][0];
7094  _y = (int)y - (int)_rastoffset[i][1];
7095 
7096  /* store _x and _y in 1-based */
7097  _pos[i][0] = _x + 1;
7098  _pos[i][1] = _y + 1;
7099 
7100  /* get pixel value */
7101  if (_band[i] == NULL) {
7102  if (!_hasnodata[i]) {
7103  _haspixel[i] = 1;
7104  _pixel[i] = _nodataval[i];
7105  }
7106  }
7107  else if (
7108  !_isempty[i] &&
7109  (_x >= 0 && _x < _dim[i][0]) &&
7110  (_y >= 0 && _y < _dim[i][1])
7111  ) {
7112  err = rt_band_get_pixel(_band[i], _x, _y, &(_pixel[i]), &isnodata);
7113  if (err != ES_NONE) {
7114 
7115  if (calltype == TEXTOID) {
7116  for (k = 0; k < spi_count; k++) SPI_freeplan(spi_plan[k]);
7117  SPI_finish();
7118  }
7119 
7120  for (k = 0; k < set_count; k++) {
7121  if (_rast[k] != NULL)
7122  rt_raster_destroy(_rast[k]);
7123  if (pgrastpos[k] != -1)
7124  PG_FREE_IF_COPY(pgrast[k], pgrastpos[k]);
7125  }
7127 
7128  elog(ERROR, "RASTER_mapAlgebra2: Could not get pixel of %s raster", (i < 1 ? "FIRST" : "SECOND"));
7129  PG_RETURN_NULL();
7130  }
7131 
7132  if (!_hasnodata[i] || !isnodata)
7133  _haspixel[i] = 1;
7134  }
7135 
7136  POSTGIS_RT_DEBUGF(5, "pixel r%d(%d, %d) = %d, %f",
7137  i,
7138  _x, _y,
7139  _haspixel[i],
7140  _pixel[i]
7141  );
7142  }
7143 
7144  haspixel = 0;
7145 
7146  switch (calltype) {
7147  case TEXTOID: {
7148  /* which prepared plan to use? */
7149  /* !pixel0 && !pixel1 */
7150  /* use nodatanodataval */
7151  if (!_haspixel[0] && !_haspixel[1])
7152  i = 3;
7153  /* pixel0 && !pixel1 */
7154  /* run spi_plan[2] (nodata2expr) */
7155  else if (_haspixel[0] && !_haspixel[1])
7156  i = 2;
7157  /* !pixel0 && pixel1 */
7158  /* run spi_plan[1] (nodata1expr) */
7159  else if (!_haspixel[0] && _haspixel[1])
7160  i = 1;
7161  /* pixel0 && pixel1 */
7162  /* run spi_plan[0] (expression) */
7163  else
7164  i = 0;
7165 
7166  /* process values */
7167  if (i == 3) {
7168  if (hasnodatanodataval) {
7169  haspixel = 1;
7170  pixel = nodatanodataval;
7171  }
7172  }
7173  /* has an evaluated value */
7174  else if (hasargval[i]) {
7175  haspixel = 1;
7176  pixel = argval[i];
7177  }
7178  /* prepared plan exists */
7179  else if (spi_plan[i] != NULL) {
7180  POSTGIS_RT_DEBUGF(4, "Using prepared plan: %d", i);
7181 
7182  /* reset values to (Datum) NULL */
7183  memset(values, (Datum) NULL, sizeof(Datum) * ARGKWCOUNT);
7184  /* reset nulls to FALSE */
7185  memset(nulls, FALSE, sizeof(char) * ARGKWCOUNT);
7186 
7187  /* expression has argument(s) */
7188  if (spi_argcount[i]) {
7189  /* set values and nulls */
7190  for (j = 0; j < ARGKWCOUNT; j++) {
7191  idx = argpos[i][j];
7192  if (idx < 1) continue;
7193  idx--; /* 1-based becomes 0-based */
7194 
7195  if (strstr(argkw[j], "[rast1.x]") != NULL) {
7196  values[idx] = _pos[0][0];
7197  }
7198  else if (strstr(argkw[j], "[rast1.y]") != NULL) {
7199  values[idx] = _pos[0][1];
7200  }
7201  else if (
7202  (strstr(argkw[j], "[rast1.val]") != NULL) ||
7203  (strstr(argkw[j], "[rast1]") != NULL)
7204  ) {
7205  if (_isempty[0] || !_haspixel[0])
7206  nulls[idx] = TRUE;
7207  else
7208  values[idx] = Float8GetDatum(_pixel[0]);
7209  }
7210  else if (strstr(argkw[j], "[rast2.x]") != NULL) {
7211  values[idx] = _pos[1][0];
7212  }
7213  else if (strstr(argkw[j], "[rast2.y]") != NULL) {
7214  values[idx] = _pos[1][1];
7215  }
7216  else if (
7217  (strstr(argkw[j], "[rast2.val]") != NULL) ||
7218  (strstr(argkw[j], "[rast2]") != NULL)
7219  ) {
7220  if (_isempty[1] || !_haspixel[1])
7221  nulls[idx] = TRUE;
7222  else
7223  values[idx] = Float8GetDatum(_pixel[1]);
7224  }
7225  }
7226  }
7227 
7228  /* run prepared plan */
7229  err = SPI_execute_plan(spi_plan[i], values, nulls, TRUE, 1);
7230  if (err != SPI_OK_SELECT || SPI_tuptable == NULL || SPI_processed != 1) {
7231 
7232  for (k = 0; k < spi_count; k++) SPI_freeplan(spi_plan[k]);
7233  SPI_finish();
7234 
7235  for (k = 0; k < set_count; k++) {
7236  if (_rast[k] != NULL)
7237  rt_raster_destroy(_rast[k]);
7238  if (pgrastpos[k] != -1)
7239  PG_FREE_IF_COPY(pgrast[k], pgrastpos[k]);
7240  }
7242 
7243  elog(ERROR, "RASTER_mapAlgebra2: Unexpected error when running prepared statement %d", i);
7244  PG_RETURN_NULL();
7245  }
7246 
7247  /* get output of prepared plan */
7248  tupdesc = SPI_tuptable->tupdesc;
7249  tuptable = SPI_tuptable;
7250  tuple = tuptable->vals[0];
7251 
7252  datum = SPI_getbinval(tuple, tupdesc, 1, &isnull);
7253  if (SPI_result == SPI_ERROR_NOATTRIBUTE) {
7254 
7255  if (SPI_tuptable) SPI_freetuptable(tuptable);
7256  for (k = 0; k < spi_count; k++) SPI_freeplan(spi_plan[k]);
7257  SPI_finish();
7258 
7259  for (k = 0; k < set_count; k++) {
7260  if (_rast[k] != NULL)
7261  rt_raster_destroy(_rast[k]);
7262  if (pgrastpos[k] != -1)
7263  PG_FREE_IF_COPY(pgrast[k], pgrastpos[k]);
7264  }
7266 
7267  elog(ERROR, "RASTER_mapAlgebra2: Could not get result of prepared statement %d", i);
7268  PG_RETURN_NULL();
7269  }
7270 
7271  if (!isnull) {
7272  haspixel = 1;
7273  pixel = DatumGetFloat8(datum);
7274  }
7275 
7276  if (SPI_tuptable) SPI_freetuptable(tuptable);
7277  }
7278  } break;
7279  case REGPROCEDUREOID: {
7280  Datum d[4];
7281  ArrayType *a;
7282 
7283  /* build fcnarg */
7284  for (i = 0; i < set_count; i++) {
7285 #if POSTGIS_PGSQL_VERSION < 120
7286  ufc_info.arg[i] = Float8GetDatum(_pixel[i]);
7287 #else
7288  ufc_info->args[i].value = Float8GetDatum(_pixel[i]);
7289 #endif
7290 
7291  if (_haspixel[i]) {
7292 #if POSTGIS_PGSQL_VERSION < 120
7293  ufc_info.argnull[i] = FALSE;
7294 #else
7295  ufc_info->args[i].isnull = FALSE;
7296 #endif
7297  ufc_nullcount--;
7298  }
7299  else {
7300 #if POSTGIS_PGSQL_VERSION < 120
7301  ufc_info.argnull[i] = TRUE;
7302 #else
7303  ufc_info->args[i].isnull = TRUE;
7304 #endif
7305  ufc_nullcount++;
7306  }
7307  }
7308 
7309  /* function is strict and null parameter is passed */
7310  /* http://archives.postgresql.org/pgsql-general/2011-11/msg00424.php */
7311  if (ufl_info.fn_strict && ufc_nullcount)
7312  break;
7313 
7314  /* 4 parameters, add position */
7315  if (ufl_info.fn_nargs == 4) {
7316  /* Datum of 4 element array */
7317  /* array is (x1, y1, x2, y2) */
7318  for (i = 0; i < set_count; i++) {
7319  if (i < 1) {
7320  d[0] = Int32GetDatum(_pos[i][0]);
7321  d[1] = Int32GetDatum(_pos[i][1]);
7322  }
7323  else {
7324  d[2] = Int32GetDatum(_pos[i][0]);
7325  d[3] = Int32GetDatum(_pos[i][1]);
7326  }
7327  }
7328 
7329  a = construct_array(d, 4, INT4OID, sizeof(int32), true, 'i');
7330 #if POSTGIS_PGSQL_VERSION < 120
7331  ufc_info.arg[2] = PointerGetDatum(a);
7332  ufc_info.argnull[2] = FALSE;
7333 #else
7334  ufc_info->args[2].value = PointerGetDatum(a);
7335  ufc_info->args[2].isnull = FALSE;
7336 #endif
7337  }
7338 
7339 #if POSTGIS_PGSQL_VERSION < 120
7340  datum = FunctionCallInvoke(&ufc_info);
7341 
7342  /* result is not null*/
7343  if (!ufc_info.isnull) {
7344  haspixel = 1;
7345  pixel = DatumGetFloat8(datum);
7346  }
7347 #else
7348  datum = FunctionCallInvoke(ufc_info);
7349 
7350  /* result is not null*/
7351  if (!ufc_info->isnull)
7352  {
7353  haspixel = 1;
7354  pixel = DatumGetFloat8(datum);
7355  }
7356 #endif
7357  } break;
7358  }
7359 
7360  /* burn pixel if haspixel != 0 */
7361  if (haspixel) {
7362  if (rt_band_set_pixel(band, x, y, pixel, NULL) != ES_NONE) {
7363 
7364  if (calltype == TEXTOID) {
7365  for (k = 0; k < spi_count; k++) SPI_freeplan(spi_plan[k]);
7366  SPI_finish();
7367  }
7368 
7369  for (k = 0; k < set_count; k++) {
7370  if (_rast[k] != NULL)
7371  rt_raster_destroy(_rast[k]);
7372  if (pgrastpos[k] != -1)
7373  PG_FREE_IF_COPY(pgrast[k], pgrastpos[k]);
7374  }
7376 
7377  elog(ERROR, "RASTER_mapAlgebra2: Could not set pixel value of output raster");
7378  PG_RETURN_NULL();
7379  }
7380  }
7381 
7382  POSTGIS_RT_DEBUGF(5, "(x, y, val) = (%d, %d, %f)", x, y, haspixel ? pixel : nodataval);
7383 
7384  } /* y: height */
7385  } /* x: width */
7386  }
7387 
7388  /* CLEANUP */
7389  if (calltype == TEXTOID) {
7390  for (i = 0; i < spi_count; i++) {
7391  if (spi_plan[i] != NULL) SPI_freeplan(spi_plan[i]);
7392  }
7393  SPI_finish();
7394  }
7395 
7396  for (k = 0; k < set_count; k++) {
7397  if (_rast[k] != NULL)
7398  rt_raster_destroy(_rast[k]);
7399  if (pgrastpos[k] != -1)
7400  PG_FREE_IF_COPY(pgrast[k], pgrastpos[k]);
7401  }
7402 
7403  pgrtn = rt_raster_serialize(raster);
7405  if (!pgrtn) PG_RETURN_NULL();
7406 
7407  POSTGIS_RT_DEBUG(3, "Finished RASTER_mapAlgebra2");
7408 
7409  SET_VARSIZE(pgrtn, pgrtn->size);
7410  PG_RETURN_POINTER(pgrtn);
7411 }
#define TRUE
Definition: dbfopen.c:73
#define FALSE
Definition: dbfopen.c:72
int32_t rt_raster_get_srid(rt_raster raster)
Get raster's SRID.
Definition: rt_raster.c:356
double rt_raster_get_x_skew(rt_raster raster)
Get skew about the X axis.
Definition: rt_raster.c:181
double rt_raster_get_x_offset(rt_raster raster)
Get raster x offset, in projection units.
Definition: rt_raster.c:213
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_raster.c:485
void rt_raster_set_geotransform_matrix(rt_raster raster, double *gt)
Set raster's geotransform using 6-element array.
Definition: rt_raster.c:727
void rt_raster_set_scale(rt_raster raster, double scaleX, double scaleY)
Set scale in projection units.
Definition: rt_raster.c:137
int rt_band_get_hasnodata_flag(rt_band band)
Get hasnodata flag value.
Definition: rt_band.c:674
rt_pixtype rt_pixtype_index_from_name(const char *pixname)
Definition: rt_pixel.c:80
rt_errorstate rt_band_get_pixel(rt_band band, int x, int y, double *value, int *nodata)
Get pixel value.
Definition: rt_band.c:1221
void rt_raster_destroy(rt_raster raster)
Release memory associated to a raster.
Definition: rt_raster.c:82
rt_pixtype
Definition: librtcore.h:185
@ PT_END
Definition: librtcore.h:197
rt_raster rt_raster_new(uint32_t width, uint32_t height)
Construct a raster with given dimensions.
Definition: rt_raster.c:48
rt_extenttype rt_util_extent_type(const char *name)
Definition: rt_util.c:193
double rt_pixtype_get_min_value(rt_pixtype pixtype)
Return minimum value possible for pixel type.
Definition: rt_pixel.c:148
int rt_raster_has_band(rt_raster raster, int nband)
Return TRUE if the raster has a band of this number.
Definition: rt_raster.c:1342
void * rt_raster_serialize(rt_raster raster)
Return this raster in serialized form.
Definition: rt_serialize.c:521
double rt_raster_get_x_scale(rt_raster raster)
Get scale X in projection units.
Definition: rt_raster.c:150
rt_errorstate rt_band_set_pixel(rt_band band, int x, int y, double val, int *converted)
Set single pixel's value.
Definition: rt_band.c:974
@ ES_NONE
Definition: librtcore.h:180
uint16_t rt_raster_get_height(rt_raster raster)
Definition: rt_raster.c:129
void rt_raster_set_srid(rt_raster raster, int32_t srid)
Set raster's SRID.
Definition: rt_raster.c:363
rt_extenttype
Definition: librtcore.h:200
@ ET_CUSTOM
Definition: librtcore.h:206
@ ET_LAST
Definition: librtcore.h:205
@ ET_INTERSECTION
Definition: librtcore.h:201
@ ET_UNION
Definition: librtcore.h:202
@ ET_SECOND
Definition: librtcore.h:204
@ ET_FIRST
Definition: librtcore.h:203
rt_errorstate rt_band_get_nodata(rt_band band, double *nodata)
Get NODATA value.
Definition: rt_band.c:1730
rt_pixtype rt_band_get_pixtype(rt_band band)
Return pixeltype of this band.
Definition: rt_band.c:631
const char * rt_pixtype_name(rt_pixtype pixtype)
Definition: rt_pixel.c:110
uint16_t rt_raster_get_width(rt_raster raster)
Definition: rt_raster.c:121
rt_errorstate rt_raster_from_two_rasters(rt_raster rast1, rt_raster rast2, rt_extenttype extenttype, rt_raster *rtnraster, double *offset)
Definition: rt_raster.c:3337
double rt_raster_get_y_scale(rt_raster raster)
Get scale Y in projection units.
Definition: rt_raster.c:159
rt_errorstate rt_raster_same_alignment(rt_raster rast1, rt_raster rast2, int *aligned, char **reason)
double rt_raster_get_y_skew(rt_raster raster)
Get skew about the Y axis.
Definition: rt_raster.c:190
void rt_raster_get_geotransform_matrix(rt_raster raster, double *gt)
Get 6-element array of raster geotransform matrix.
Definition: rt_raster.c:706
rt_raster rt_raster_deserialize(void *serialized, int header_only)
Return a raster from a serialized form.
Definition: rt_serialize.c:725
double rt_raster_get_y_offset(rt_raster raster)
Get raster y offset, in projection units.
Definition: rt_raster.c:222
int rt_raster_is_empty(rt_raster raster)
Return TRUE if the raster is empty.
Definition: rt_raster.c:1329
rt_band rt_raster_get_band(rt_raster raster, int bandNum)
Return Nth band, or NULL if unavailable.
Definition: rt_raster.c:381
band
Definition: ovdump.py:58
pixel
Definition: pixval.py:91
raster
Be careful!! Zeros function's input parameter can be a (height x width) array, not (width x height): ...
Definition: rtrowdump.py:121
gt
Definition: window.py:78
char * rtpg_strtoupper(char *str)
char * rtpg_trim(const char *input)
char * rtpg_strreplace(const char *str, const char *oldstr, const char *newstr, int *count)
Definition: rtpg_internal.c:55
#define ARGKWCOUNT
#define POSTGIS_RT_DEBUG(level, msg)
Definition: rtpostgis.h:61
#define POSTGIS_RT_DEBUGF(level, msg,...)
Definition: rtpostgis.h:65
unsigned int int32
Definition: shpopen.c:54
Struct definitions.
Definition: librtcore.h:2251

References ARGKWCOUNT, ovdump::band, ES_NONE, ET_CUSTOM, ET_FIRST, ET_INTERSECTION, ET_LAST, ET_SECOND, ET_UNION, FALSE, window::gt, pixval::pixel, POSTGIS_RT_DEBUG, POSTGIS_RT_DEBUGF, PT_END, rtpixdump::rast, rtrowdump::raster, rt_band_get_hasnodata_flag(), rt_band_get_nodata(), rt_band_get_pixel(), rt_band_get_pixtype(), rt_band_set_pixel(), rt_pixtype_get_min_value(), rt_pixtype_index_from_name(), rt_pixtype_name(), rt_raster_deserialize(), rt_raster_destroy(), rt_raster_from_two_rasters(), rt_raster_generate_new_band(), rt_raster_get_band(), rt_raster_get_geotransform_matrix(), rt_raster_get_height(), rt_raster_get_srid(), rt_raster_get_width(), rt_raster_get_x_offset(), rt_raster_get_x_scale(), rt_raster_get_x_skew(), rt_raster_get_y_offset(), rt_raster_get_y_scale(), rt_raster_get_y_skew(), rt_raster_has_band(), rt_raster_is_empty(), rt_raster_new(), rt_raster_same_alignment(), rt_raster_serialize(), rt_raster_set_geotransform_matrix(), rt_raster_set_scale(), rt_raster_set_srid(), rt_util_extent_type(), rtpg_strreplace(), rtpg_strtoupper(), rtpg_trim(), rt_raster_serialized_t::size, rtgdalraster::sql, TRUE, pixval::x, and pixval::y.

Here is the call graph for this function: