PostGIS  2.4.9dev-r@@SVN_REVISION@@

◆ RASTER_mapAlgebra2()

Datum RASTER_mapAlgebra2 ( PG_FUNCTION_ARGS  )

Definition at line 6213 of file rtpg_mapalgebra.c.

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, and TRUE.

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