1331{
1332 MemoryContext mainMemCtx = CurrentMemoryContext;
1335 uint16_t exprpos[3] = {1, 4, 5};
1336
1337 int i = 0;
1338 int j = 0;
1339 int k = 0;
1340
1341 int numraster = 0;
1342 int err = 0;
1343 int allnull = 0;
1344 int allempty = 0;
1345 int noband = 0;
1346 int len = 0;
1347
1348 TupleDesc tupdesc;
1349 SPITupleTable *tuptable = NULL;
1350 HeapTuple tuple;
1351 Datum datum;
1352 bool isnull =
FALSE;
1353
1357
1358 const int argkwcount = 12;
1359 char *argkw[] = {
1360 "[rast.x]",
1361 "[rast.y]",
1362 "[rast.val]",
1363 "[rast]",
1364 "[rast1.x]",
1365 "[rast1.y]",
1366 "[rast1.val]",
1367 "[rast1]",
1368 "[rast2.x]",
1369 "[rast2.y]",
1370 "[rast2.val]",
1371 "[rast2]"
1372 };
1373
1374 if (PG_ARGISNULL(0))
1375 PG_RETURN_NULL();
1376
1377
1379 if (arg == NULL) {
1380 elog(ERROR, "RASTER_nMapAlgebraExpr: Could not initialize argument structure");
1381 PG_RETURN_NULL();
1382 }
1383
1384
1387 elog(ERROR, "RASTER_nMapAlgebra: Could not process rastbandarg");
1388 PG_RETURN_NULL();
1389 }
1390
1391 POSTGIS_RT_DEBUGF(4,
"allnull, allempty, noband = %d, %d, %d", allnull, allempty, noband);
1392
1393
1395 elog(NOTICE, "All input rasters are NULL. Returning NULL");
1397 PG_RETURN_NULL();
1398 }
1399
1400
1402 numraster = 2;
1403 else
1404 numraster = 1;
1405
1406
1407 if (!PG_ARGISNULL(2)) {
1409
1410
1414 elog(ERROR, "RASTER_nMapAlgebraExpr: Invalid pixel type: %s", pixtypename);
1415 PG_RETURN_NULL();
1416 }
1417 }
1419
1420
1421 if (!PG_ARGISNULL(3)) {
1424 }
1425
1427 if (numraster < 2) {
1428 elog(NOTICE, "CUSTOM extent type not supported. Defaulting to FIRST");
1430 }
1431 else {
1432 elog(NOTICE, "CUSTOM extent type not supported. Defaulting to INTERSECTION");
1434 }
1435 }
1436 else if (numraster < 2)
1438
1440
1441
1442 if (!PG_ARGISNULL(6)) {
1445 }
1446
1447 err = 0;
1448
1450 elog(NOTICE, "All input rasters are empty. Returning empty raster");
1451 err = 1;
1452 }
1453
1455 elog(NOTICE, "All input rasters do not have bands at indicated indexes. Returning empty raster");
1456 err = 1;
1457 }
1458 if (err) {
1460
1462 if (raster == NULL) {
1463 elog(ERROR, "RASTER_nMapAlgebraExpr: Could not create empty raster");
1464 PG_RETURN_NULL();
1465 }
1466
1469 if (!pgraster) PG_RETURN_NULL();
1470
1471 SET_VARSIZE(pgraster, pgraster->
size);
1472 PG_RETURN_POINTER(pgraster);
1473 }
1474
1475
1476 if (SPI_connect() != SPI_OK_CONNECT) {
1478 elog(ERROR, "RASTER_nMapAlgebraExpr: Could not connect to the SPI manager");
1479 PG_RETURN_NULL();
1480 }
1481
1482
1483
1484
1485
1486
1487
1488
1489
1491 char *expr = NULL;
1492 char *tmp = NULL;
1494 char place[12] = "$1";
1495
1496 if (PG_ARGISNULL(exprpos[i]))
1497 continue;
1498
1501
1502 for (j = 0, k = 1; j < argkwcount; j++) {
1503
1504 len = 0;
1506 pfree(expr);
1507 expr = tmp;
1508
1509 if (len) {
1513
1514 sprintf(place, "$%d", k);
1515 }
1516 else
1518 }
1519
1520 len = strlen("SELECT (") + strlen(expr) + strlen(")::double precision");
1521 sql = (
char *) palloc(len + 1);
1522 if (sql == NULL) {
1524 SPI_finish();
1525 elog(ERROR, "RASTER_nMapAlgebraExpr: Could not allocate memory for expression parameter %d", exprpos[i]);
1526 PG_RETURN_NULL();
1527 }
1528
1529 memcpy(sql, "SELECT (", strlen("SELECT ("));
1530 memcpy(sql + strlen("SELECT ("), expr, strlen(expr));
1531 memcpy(sql + strlen("SELECT (") + strlen(expr), ")::double precision", strlen(")::double precision"));
1533
1535
1536
1540 if (argtype == NULL) {
1541 pfree(sql);
1543 SPI_finish();
1544 elog(ERROR, "RASTER_nMapAlgebraExpr: Could not allocate memory for prepared plan argtypes of expression parameter %d", exprpos[i]);
1545 PG_RETURN_NULL();
1546 }
1547
1548
1549 for (j = 0, k = 0; j < argkwcount; j++) {
1551
1552
1553 if (
1554 (strstr(argkw[j], "[rast.x]") != NULL) ||
1555 (strstr(argkw[j], "[rast.y]") != NULL) ||
1556 (strstr(argkw[j], "[rast1.x]") != NULL) ||
1557 (strstr(argkw[j], "[rast1.y]") != NULL) ||
1558 (strstr(argkw[j], "[rast2.x]") != NULL) ||
1559 (strstr(argkw[j], "[rast2.y]") != NULL)
1560 )
1561 argtype[k] = INT4OID;
1562
1563 else
1564 argtype[k] = FLOAT8OID;
1565
1566 k++;
1567 }
1568
1570 pfree(argtype);
1571 pfree(sql);
1572
1575 SPI_finish();
1576 elog(ERROR, "RASTER_nMapAlgebraExpr: Could not create prepared plan of expression parameter %d", exprpos[i]);
1577 PG_RETURN_NULL();
1578 }
1579 }
1580
1581 else {
1582 POSTGIS_RT_DEBUGF(3,
"expression parameter %d has no args, simply executing", exprpos[i]);
1583 err = SPI_execute(sql,
TRUE, 0);
1584 pfree(sql);
1585
1586 if (err != SPI_OK_SELECT || SPI_tuptable == NULL || SPI_processed != 1) {
1588 SPI_finish();
1589 elog(ERROR, "RASTER_nMapAlgebraExpr: Could not evaluate expression parameter %d", exprpos[i]);
1590 PG_RETURN_NULL();
1591 }
1592
1593
1594 tupdesc = SPI_tuptable->tupdesc;
1595 tuptable = SPI_tuptable;
1596 tuple = tuptable->vals[0];
1597
1598 datum = SPI_getbinval(tuple, tupdesc, 1, &isnull);
1599 if (SPI_result == SPI_ERROR_NOATTRIBUTE) {
1600 if (SPI_tuptable) SPI_freetuptable(tuptable);
1602 SPI_finish();
1603 elog(ERROR, "RASTER_nMapAlgebraExpr: Could not get result of expression parameter %d", exprpos[i]);
1604 PG_RETURN_NULL();
1605 }
1606
1607 if (!isnull) {
1610 }
1611
1612 if (SPI_tuptable) SPI_freetuptable(tuptable);
1613 }
1614 }
1615
1616
1617
1621 if (numraster > 1)
1622 i = 1;
1623 else
1624 i = 0;
1625 break;
1626 default:
1627 i = 0;
1628 break;
1629 }
1630
1632 for (i = 0; i < numraster; i++) {
1634 break;
1635 }
1636 if (i >= numraster)
1637 i = numraster - 1;
1638 }
1640
1641
1644
1645
1649 else
1651
1653
1654
1656 if (itrset == NULL) {
1658 SPI_finish();
1659 elog(ERROR, "RASTER_nMapAlgebra: Could not allocate memory for iterator arguments");
1660 PG_RETURN_NULL();
1661 }
1662
1663
1664 for (i = 0; i < numraster; i++) {
1668 }
1669
1670
1672 itrset, numraster,
1676 0, 0,
1677 NULL,
1680 &raster
1681 );
1682
1683 pfree(itrset);
1685
1687 SPI_finish();
1688 elog(ERROR, "RASTER_nMapAlgebraExpr: Could not run raster iterator function");
1689 PG_RETURN_NULL();
1690 }
1691 else if (raster == NULL) {
1692 SPI_finish();
1693 PG_RETURN_NULL();
1694 }
1695
1696
1697 MemoryContextSwitchTo(mainMemCtx);
1698
1701
1702
1703 SPI_finish();
1704
1705 if (!pgraster)
1706 PG_RETURN_NULL();
1707
1708 SET_VARSIZE(pgraster, pgraster->
size);
1709 PG_RETURN_POINTER(pgraster);
1710}
int rt_band_get_hasnodata_flag(rt_band band)
Get hasnodata flag value.
rt_pixtype rt_pixtype_index_from_name(const char *pixname)
void rt_raster_destroy(rt_raster raster)
Release memory associated to a raster.
rt_raster rt_raster_new(uint32_t width, uint32_t height)
Construct a raster with given dimensions.
rt_extenttype rt_util_extent_type(const char *name)
const char * rt_pixtype_name(rt_pixtype pixtype)
double rt_band_get_min_value(rt_band band)
Returns the minimal possible value for the band according to the pixel type.
rt_errorstate rt_raster_iterator(rt_iterator itrset, uint16_t itrcount, rt_extenttype extenttype, rt_raster customextent, rt_pixtype pixtype, uint8_t hasnodata, double nodataval, uint16_t distancex, uint16_t distancey, rt_mask mask, void *userarg, int(*callback)(rt_iterator_arg arg, void *userarg, double *value, int *nodata), rt_raster *rtnraster)
n-raster iterator.
rt_errorstate rt_band_get_nodata(rt_band band, double *nodata)
Get NODATA value.
rt_pixtype rt_band_get_pixtype(rt_band band)
Return pixeltype of this band.
void * rt_raster_serialize(rt_raster raster)
Return this raster in serialized form.
rt_band rt_raster_get_band(rt_raster raster, int bandNum)
Return Nth band, or NULL if unavailable.
raster
Be careful!! Zeros function's input parameter can be a (height x width) array, not (width x height): ...
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)
static void rtpg_nmapalgebraexpr_arg_destroy(rtpg_nmapalgebraexpr_arg arg)
static rtpg_nmapalgebraexpr_arg rtpg_nmapalgebraexpr_arg_init(int cnt, char **kw)
static int rtpg_nmapalgebra_rastbandarg_process(rtpg_nmapalgebra_arg arg, ArrayType *array, int *allnull, int *allempty, int *noband)
static int rtpg_nmapalgebraexpr_callback(rt_iterator_arg arg, void *userarg, double *value, int *nodata)
#define POSTGIS_RT_DEBUGF(level, msg,...)
rtpg_nmapalgebraexpr_callback_arg callback
rtpg_nmapalgebra_arg bandarg
struct rtpg_nmapalgebraexpr_callback_arg::@18 expr[3]
struct rtpg_nmapalgebraexpr_callback_arg::@19 nodatanodata