PostGIS 3.0.6dev-r@@SVN_REVISION@@
Loading...
Searching...
No Matches

◆ 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);
6369 rt_raster_destroy(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 }
6542 rt_raster_destroy(raster);
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);
6560 rt_raster_destroy(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]) {
6579 rt_raster_destroy(raster);
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);
6594 rt_raster_set_srid(raster, rt_raster_get_srid(_rast[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);
6605 rt_raster_destroy(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);
6640 rt_raster_destroy(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 }
6664 rt_raster_destroy(raster);
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 }
6714 rt_raster_destroy(raster);
6715 elog(ERROR, "RASTER_mapAlgebra2: Could not add new band to output raster");
6716 PG_RETURN_NULL();
6717 }
6718
6719 /* get output band */
6720 band = rt_raster_get_band(raster, 0);
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 }
6728 rt_raster_destroy(raster);
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)",
6741 rt_raster_get_x_offset(raster),
6742 rt_raster_get_y_offset(raster),
6743 rt_raster_get_width(raster),
6744 rt_raster_get_height(raster),
6745 rt_raster_get_x_scale(raster),
6746 rt_raster_get_y_scale(raster),
6747 rt_raster_get_x_skew(raster),
6748 rt_raster_get_y_skew(raster),
6749 rt_raster_get_srid(raster)
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 }
6771 rt_raster_destroy(raster);
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 }
6824 rt_raster_destroy(raster);
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 }
6852 rt_raster_destroy(raster);
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 }
6894 rt_raster_destroy(raster);
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 }
6915 rt_raster_destroy(raster);
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 }
6940 rt_raster_destroy(raster);
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 }
7001 rt_raster_destroy(raster);
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 }
7063 rt_raster_destroy(raster);
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 }
7120 rt_raster_destroy(raster);
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 }
7235 rt_raster_destroy(raster);
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 }
7259 rt_raster_destroy(raster);
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 }
7369 rt_raster_destroy(raster);
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);
7398 rt_raster_destroy(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
double rt_raster_get_x_scale(rt_raster raster)
Get scale X in projection units.
Definition rt_raster.c:150
const char * rt_pixtype_name(rt_pixtype pixtype)
Definition rt_pixel.c:110
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
uint16_t rt_raster_get_width(rt_raster raster)
Definition rt_raster.c:121
void * rt_raster_serialize(rt_raster raster)
Return this raster in serialized form.
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.
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
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
char * text_to_cstring(const text *textptr)
char * rtpg_strreplace(const char *str, const char *oldstr, const char *newstr, int *count)
char * rtpg_trim(const char *input)
char * rtpg_strtoupper(char *str)
#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, ES_NONE, ET_CUSTOM, ET_FIRST, ET_INTERSECTION, ET_LAST, ET_SECOND, ET_UNION, FALSE, POSTGIS_RT_DEBUG, POSTGIS_RT_DEBUGF, PT_END, 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, text_to_cstring(), and TRUE.

Here is the call graph for this function: