PostGIS  3.0.6dev-r@@SVN_REVISION@@

◆ RASTER_mapAlgebra2()

Datum RASTER_mapAlgebra2 ( PG_FUNCTION_ARGS  )

Definition at line 6224 of file rtpg_mapalgebra.c.

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

Here is the call graph for this function: