PostGIS  3.3.9dev-r@@SVN_REVISION@@

◆ RASTER_mapAlgebra2()

Datum RASTER_mapAlgebra2 ( PG_FUNCTION_ARGS  )

Definition at line 6209 of file rtpg_mapalgebra.c.

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

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: