36 #include <executor/spi.h>
37 #include <utils/lsyscache.h>
38 #include <utils/array.h>
39 #include <utils/builtins.h>
40 #include <catalog/pg_type.h>
41 #include <executor/executor.h>
43 #include "../../postgis_config.h"
44 #include "lwgeom_pg.h"
80 #if defined(__clang__)
81 # pragma clang diagnostic push
82 # pragma clang diagnostic ignored "-Wgnu-variable-sized-type-not-at-end"
89 #if POSTGIS_PGSQL_VERSION < 120
94 FunctionCallInfoBaseData fcinfo;
95 char fcinfo_data[SizeForFunctionCallInfo(FUNC_MAX_ARGS)];
97 FunctionCallInfo ufc_info;
101 #if defined(__clang__)
102 # pragma clang diagnostic pop
134 elog(ERROR,
"rtpg_nmapalgebra_arg_init: Could not allocate memory for arguments");
158 #if POSTGIS_PGSQL_VERSION >= 120
170 if (arg->
raster != NULL) {
187 if( arg->
mask != NULL )
210 if (arg == NULL || array == NULL) {
211 elog(ERROR,
"rtpg_nmapalgebra_rastbandarg_process: NULL values not permitted for parameters");
215 etype = ARR_ELEMTYPE(array);
216 get_typlenbyvalalign(etype, &typlen, &typbyval, &typalign);
221 typlen, typbyval, typalign,
226 elog(ERROR,
"rtpg_nmapalgebra_rastbandarg_process: Invalid argument for rastbandarg");
244 arg->
nband == NULL ||
248 elog(ERROR,
"rtpg_nmapalgebra_rastbandarg_process: Could not allocate memory for processing rastbandarg");
257 for (i = 0; i < n; i++) {
272 tup = (HeapTupleHeader) DatumGetPointer(e[i]);
274 elog(ERROR,
"rtpg_nmapalgebra_rastbandarg_process: Invalid argument for rastbandarg at index %d", i);
280 tupv = GetAttributeByName(tup,
"rast", &isnull);
282 elog(NOTICE,
"First argument (nband) of rastbandarg at index %d is NULL. Assuming NULL raster", i);
296 for (j = 0; j < i; j++) {
308 if (arg->
raster[i] == NULL) {
309 elog(ERROR,
"rtpg_nmapalgebra_rastbandarg_process: Could not deserialize raster at index %d", i);
325 tupv = GetAttributeByName(tup,
"nband", &isnull);
328 elog(NOTICE,
"First argument (nband) of rastbandarg at index %d is NULL. Assuming nband = %d", i,
nband);
331 nband = DatumGetInt32(tupv);
334 elog(ERROR,
"rtpg_nmapalgebra_rastbandarg_process: Band number provided for rastbandarg at index %d must be greater than zero (1-based)", i);
358 arg->
nband == NULL ||
361 elog(ERROR,
"rtpg_nmapalgebra_rastbandarg_process: Could not reallocate memory for processed rastbandarg");
376 double *
value,
int *nodata
384 ArrayType *mdValues = NULL;
385 Datum *_values = NULL;
386 bool *_nodata = NULL;
388 ArrayType *mdPos = NULL;
397 int lbound[3] = {1, 1, 1};
398 Datum datum = (Datum) NULL;
412 if (_values == NULL || _nodata == NULL) {
413 elog(ERROR,
"rtpg_nmapalgebra_callback: Could not allocate memory for values array");
420 for (z = 0; z < arg->
rasters; z++) {
422 for (
y = 0;
y < arg->
rows;
y++) {
428 _nodata[i] = (bool) arg->
nodata[z][
y][
x];
430 _values[i] = Float8GetDatum(arg->
values[z][
y][
x]);
432 _values[i] = (Datum) NULL;
440 get_typlenbyvalalign(FLOAT8OID, &typlen, &typbyval, &typalign);
443 mdValues = construct_md_array(
447 typlen, typbyval, typalign
452 _pos = palloc(
sizeof(Datum) * (arg->
rasters + 1) * 2);
453 _null = palloc(
sizeof(
bool) * (arg->
rasters + 1) * 2);
454 if (_pos == NULL || _null == NULL) {
456 elog(ERROR,
"rtpg_nmapalgebra_callback: Could not allocate memory for position array");
459 memset(_null, 0,
sizeof(
bool) * (arg->
rasters + 1) * 2);
468 for (z = 0; z < arg->
rasters; z++) {
469 _pos[i] = (Datum)arg->
src_pixel[z][0] + 1;
472 _pos[i] = (Datum)arg->
src_pixel[z][1] + 1;
477 get_typlenbyvalalign(INT4OID, &typlen, &typbyval, &typalign);
485 mdPos = construct_md_array(
489 typlen, typbyval, typalign
494 #if POSTGIS_PGSQL_VERSION < 120
495 callback->
ufc_info.arg[0] = PointerGetDatum(mdValues);
496 callback->
ufc_info.arg[1] = PointerGetDatum(mdPos);
498 callback->
ufc_info->args[0].value = PointerGetDatum(mdValues);
499 callback->
ufc_info->args[1].value = PointerGetDatum(mdPos);
503 #if POSTGIS_PGSQL_VERSION < 120
504 datum = FunctionCallInvoke(&(callback->
ufc_info));
506 datum = FunctionCallInvoke(callback->
ufc_info);
512 #if POSTGIS_PGSQL_VERSION < 120
520 *
value = DatumGetFloat8(datum);
523 *
value = (double) DatumGetFloat4(datum);
526 *
value = (double) DatumGetInt32(datum);
529 *
value = (double) DatumGetInt16(datum);
547 ArrayType *maskArray;
578 elog(ERROR,
"RASTER_nMapAlgebra: Could not initialize argument structure");
585 elog(ERROR,
"RASTER_nMapAlgebra: Could not process rastbandarg");
589 POSTGIS_RT_DEBUGF(4,
"allnull, allempty, noband = %d, %d, %d", allnull, allempty, noband);
593 elog(NOTICE,
"All input rasters are NULL. Returning NULL");
599 if (!PG_ARGISNULL(2)) {
600 char *pixtypename = text_to_cstring(PG_GETARG_TEXT_P(2));
606 elog(ERROR,
"RASTER_nMapAlgebra: Invalid pixel type: %s", pixtypename);
612 if (!PG_ARGISNULL(3)){
613 arg->
distance[0] = PG_GETARG_INT32(3);
618 if (!PG_ARGISNULL(4)){
619 arg->
distance[1] = PG_GETARG_INT32(4);
625 elog(ERROR,
"RASTER_nMapAlgebra: Distance for X and Y axis must be greater than or equal to zero");
630 if (!PG_ARGISNULL(5)) {
638 if (PG_ARGISNULL(6)) {
639 elog(NOTICE,
"Custom extent is NULL. Returning NULL");
650 elog(ERROR,
"RASTER_nMapAlgebra: Could not deserialize custom extent");
654 elog(NOTICE,
"Custom extent is an empty raster. Returning empty raster");
659 elog(ERROR,
"RASTER_nMapAlgebra: Could not create empty raster");
665 if (!pgraster) PG_RETURN_NULL();
667 SET_VARSIZE(pgraster, pgraster->
size);
668 PG_RETURN_POINTER(pgraster);
674 if( PG_ARGISNULL(7) ){
679 maskArray = PG_GETARG_ARRAYTYPE_P(7);
680 etype = ARR_ELEMTYPE(maskArray);
681 get_typlenbyvalalign(etype,&typlen,&typbyval,&typalign);
689 elog(ERROR,
"RASTER_nMapAlgebra: Mask data type must be FLOAT8 or FLOAT4");
693 ndims = ARR_NDIM(maskArray);
696 elog(ERROR,
"RASTER_nMapAlgebra: Mask Must be a 2D array");
701 maskDims = ARR_DIMS(maskArray);
703 if (maskDims[0] % 2 == 0 || maskDims[1] % 2 == 0) {
704 elog(ERROR,
"RASTER_nMapAlgebra: Mask dimensions must be odd");
712 typlen, typbyval,typalign,
713 &maskElements,&maskNulls,&num
716 if (num < 1 || num != (maskDims[0] * maskDims[1])) {
721 elog(ERROR,
"RASTER_nMapAlgebra: Could not deconstruct new values array");
727 arg->
mask->
values = palloc(
sizeof(
double*)* maskDims[0]);
728 arg->
mask->
nodata = palloc(
sizeof(
int*)*maskDims[0]);
729 for (i = 0; i < maskDims[0]; i++) {
730 arg->
mask->
values[i] = (
double*) palloc(
sizeof(
double) * maskDims[1]);
731 arg->
mask->
nodata[i] = (
int*) palloc(
sizeof(
int) * maskDims[1]);
736 for (
y = 0;
y < maskDims[0];
y++) {
737 for (
x = 0;
x < maskDims[1];
x++) {
745 arg->
mask->
values[
y][
x] = (double) DatumGetFloat4(maskElements[i]);
749 arg->
mask->
values[
y][
x] = (double) DatumGetFloat8(maskElements[i]);
760 if (maskDims[0] == 1 && maskDims[1] == 1) {
771 if (PG_ARGISNULL(8) || !PG_GETARG_BOOL(8)) {
772 if (arg->
mask != NULL)
783 elog(NOTICE,
"All input rasters are empty. Returning empty raster");
788 elog(NOTICE,
"All input rasters do not have bands at indicated indexes. Returning empty raster");
796 elog(ERROR,
"RASTER_nMapAlgebra: Could not create empty raster");
802 if (!pgraster) PG_RETURN_NULL();
804 SET_VARSIZE(pgraster, pgraster->
size);
805 PG_RETURN_POINTER(pgraster);
809 if (!PG_ARGISNULL(1) || get_fn_expr_argtype(fcinfo->flinfo, 1) == REGPROCEDUREOID) {
828 get_func_result_type(
855 elog(ERROR,
"RASTER_nMapAlgebra: Function provided must return a double precision, float, int or smallint");
858 elog(ERROR,
"RASTER_nMapAlgebra: Function provided must return scalar (double precision, float, int, smallint)");
861 elog(ERROR,
"RASTER_nMapAlgebra: Function provided must have three input parameters");
864 elog(ERROR,
"RASTER_nMapAlgebra: Function provided must return double precision, not resultset");
871 elog(NOTICE,
"Function provided is VOLATILE. Unless required and for best performance, function should be IMMUTABLE or STABLE");
874 #if POSTGIS_PGSQL_VERSION < 120
892 if (!PG_ARGISNULL(9))
893 #if POSTGIS_PGSQL_VERSION < 120
902 #if POSTGIS_PGSQL_VERSION < 120
904 construct_empty_array(TEXTOID)
908 arg->
callback.
ufc_info->args[2].value = PointerGetDatum(construct_empty_array(TEXTOID));
913 #if POSTGIS_PGSQL_VERSION < 120
925 elog(ERROR,
"RASTER_nMapAlgebra: callbackfunc must be provided");
968 if (itrset == NULL) {
970 elog(ERROR,
"RASTER_nMapAlgebra: Could not allocate memory for iterator arguments");
999 elog(ERROR,
"RASTER_nMapAlgebra: Could not run raster iterator function");
1013 SET_VARSIZE(pgraster, pgraster->
size);
1014 PG_RETURN_POINTER(pgraster);
1058 elog(ERROR,
"rtpg_nmapalgebraexpr_arg_init: Could not allocate memory for arguments");
1064 elog(ERROR,
"rtpg_nmapalgebraexpr_arg_init: Could not allocate memory for arg->bandarg");
1077 elog(ERROR,
"rtpg_nmapalgebraexpr_arg_init: Could not allocate memory for spi_argpos");
1108 double *
value,
int *nodata
1111 SPIPlanPtr plan = NULL;
1131 else if (arg->
nodata[0][0][0] && !arg->
nodata[1][0][0]) {
1141 else if (!arg->
nodata[0][0][0] && arg->
nodata[1][0][0]) {
1168 if (arg->
nodata[0][0][0]) {
1204 SPITupleTable *tuptable = NULL;
1207 bool isnull =
FALSE;
1212 memset(values, (Datum) NULL,
sizeof(Datum) * callback->
kw.
count);
1213 memset(nulls,
FALSE,
sizeof(
char) * callback->
kw.
count);
1218 for (i = 0; i < callback->
kw.
count; i++) {
1220 if (idx < 1)
continue;
1226 values[idx] = Int32GetDatum(arg->
src_pixel[0][0] + 1);
1230 values[idx] = Int32GetDatum(arg->
src_pixel[0][1] + 1);
1236 if (!arg->
nodata[0][0][0])
1237 values[idx] = Float8GetDatum(arg->
values[0][0][0]);
1244 values[idx] = Int32GetDatum(arg->
src_pixel[0][0] + 1);
1248 values[idx] = Int32GetDatum(arg->
src_pixel[0][1] + 1);
1254 if (!arg->
nodata[0][0][0])
1255 values[idx] = Float8GetDatum(arg->
values[0][0][0]);
1262 values[idx] = Int32GetDatum(arg->
src_pixel[1][0] + 1);
1266 values[idx] = Int32GetDatum(arg->
src_pixel[1][1] + 1);
1272 if (!arg->
nodata[1][0][0])
1273 values[idx] = Float8GetDatum(arg->
values[1][0][0]);
1283 err = SPI_execute_plan(plan, values, nulls,
TRUE, 1);
1284 if (err != SPI_OK_SELECT || SPI_tuptable == NULL || SPI_processed != 1) {
1285 elog(ERROR,
"rtpg_nmapalgebraexpr_callback: Unexpected error when running prepared statement %d",
id);
1290 tupdesc = SPI_tuptable->tupdesc;
1291 tuptable = SPI_tuptable;
1292 tuple = tuptable->vals[0];
1294 datum = SPI_getbinval(tuple, tupdesc, 1, &isnull);
1295 if (SPI_result == SPI_ERROR_NOATTRIBUTE) {
1296 if (SPI_tuptable) SPI_freetuptable(tuptable);
1297 elog(ERROR,
"rtpg_nmapalgebraexpr_callback: Could not get result of prepared statement %d",
id);
1302 *
value = DatumGetFloat8(datum);
1322 if (SPI_tuptable) SPI_freetuptable(tuptable);
1332 MemoryContext mainMemCtx = CurrentMemoryContext;
1335 uint16_t exprpos[3] = {1, 4, 5};
1349 SPITupleTable *tuptable = NULL;
1352 bool isnull =
FALSE;
1358 const int argkwcount = 12;
1374 if (PG_ARGISNULL(0))
1380 elog(ERROR,
"RASTER_nMapAlgebraExpr: Could not initialize argument structure");
1387 elog(ERROR,
"RASTER_nMapAlgebra: Could not process rastbandarg");
1391 POSTGIS_RT_DEBUGF(4,
"allnull, allempty, noband = %d, %d, %d", allnull, allempty, noband);
1395 elog(NOTICE,
"All input rasters are NULL. Returning NULL");
1407 if (!PG_ARGISNULL(2)) {
1408 char *pixtypename = text_to_cstring(PG_GETARG_TEXT_P(2));
1414 elog(ERROR,
"RASTER_nMapAlgebraExpr: Invalid pixel type: %s", pixtypename);
1421 if (!PG_ARGISNULL(3)) {
1427 if (numraster < 2) {
1428 elog(NOTICE,
"CUSTOM extent type not supported. Defaulting to FIRST");
1432 elog(NOTICE,
"CUSTOM extent type not supported. Defaulting to INTERSECTION");
1436 else if (numraster < 2)
1442 if (!PG_ARGISNULL(6)) {
1450 elog(NOTICE,
"All input rasters are empty. Returning empty raster");
1455 elog(NOTICE,
"All input rasters do not have bands at indicated indexes. Returning empty raster");
1463 elog(ERROR,
"RASTER_nMapAlgebraExpr: Could not create empty raster");
1469 if (!pgraster) PG_RETURN_NULL();
1471 SET_VARSIZE(pgraster, pgraster->
size);
1472 PG_RETURN_POINTER(pgraster);
1476 if (SPI_connect() != SPI_OK_CONNECT) {
1478 elog(ERROR,
"RASTER_nMapAlgebraExpr: Could not connect to the SPI manager");
1494 char place[12] =
"$1";
1496 if (PG_ARGISNULL(exprpos[i]))
1499 expr = text_to_cstring(PG_GETARG_TEXT_P(exprpos[i]));
1502 for (j = 0, k = 1; j < argkwcount; j++) {
1514 sprintf(place,
"$%d", k);
1520 len = strlen(
"SELECT (") + strlen(expr) + strlen(
")::double precision");
1521 sql = (
char *) palloc(len + 1);
1525 elog(ERROR,
"RASTER_nMapAlgebraExpr: Could not allocate memory for expression parameter %d", exprpos[i]);
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"));
1540 if (argtype == NULL) {
1544 elog(ERROR,
"RASTER_nMapAlgebraExpr: Could not allocate memory for prepared plan argtypes of expression parameter %d", exprpos[i]);
1549 for (j = 0, k = 0; j < argkwcount; j++) {
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)
1561 argtype[k] = INT4OID;
1564 argtype[k] = FLOAT8OID;
1576 elog(ERROR,
"RASTER_nMapAlgebraExpr: Could not create prepared plan of expression parameter %d", exprpos[i]);
1582 POSTGIS_RT_DEBUGF(3,
"expression parameter %d has no args, simply executing", exprpos[i]);
1583 err = SPI_execute(
sql,
TRUE, 0);
1586 if (err != SPI_OK_SELECT || SPI_tuptable == NULL || SPI_processed != 1) {
1589 elog(ERROR,
"RASTER_nMapAlgebraExpr: Could not evaluate expression parameter %d", exprpos[i]);
1594 tupdesc = SPI_tuptable->tupdesc;
1595 tuptable = SPI_tuptable;
1596 tuple = tuptable->vals[0];
1598 datum = SPI_getbinval(tuple, tupdesc, 1, &isnull);
1599 if (SPI_result == SPI_ERROR_NOATTRIBUTE) {
1600 if (SPI_tuptable) SPI_freetuptable(tuptable);
1603 elog(ERROR,
"RASTER_nMapAlgebraExpr: Could not get result of expression parameter %d", exprpos[i]);
1612 if (SPI_tuptable) SPI_freetuptable(tuptable);
1632 for (i = 0; i < numraster; i++) {
1656 if (itrset == NULL) {
1659 elog(ERROR,
"RASTER_nMapAlgebra: Could not allocate memory for iterator arguments");
1664 for (i = 0; i < numraster; i++) {
1688 elog(ERROR,
"RASTER_nMapAlgebraExpr: Could not run raster iterator function");
1691 else if (
raster == NULL) {
1697 MemoryContextSwitchTo(mainMemCtx);
1708 SET_VARSIZE(pgraster, pgraster->
size);
1709 PG_RETURN_POINTER(pgraster);
1729 assert(cutype && strlen(cutype) > 0);
1731 if (strcmp(cutype,
"LAST") == 0)
1733 else if (strcmp(cutype,
"FIRST") == 0)
1735 else if (strcmp(cutype,
"MIN") == 0)
1737 else if (strcmp(cutype,
"MAX") == 0)
1739 else if (strcmp(cutype,
"COUNT") == 0)
1741 else if (strcmp(cutype,
"SUM") == 0)
1743 else if (strcmp(cutype,
"MEAN") == 0)
1745 else if (strcmp(cutype,
"RANGE") == 0)
1772 for (i = 0; i < arg->
numband; i++) {
1796 double *
value,
int *nodata
1808 elog(ERROR,
"rtpg_union_callback: Invalid arguments passed to callback");
1824 else if (!arg->
nodata[0][0][0] && arg->
nodata[1][0][0]) {
1830 else if (arg->
nodata[0][0][0] && !arg->
nodata[1][0][0]) {
1858 else if (!arg->
nodata[0][0][0] && arg->
nodata[1][0][0])
1861 else if (arg->
nodata[0][0][0] && !arg->
nodata[1][0][0])
1887 double *
value,
int *nodata
1897 elog(ERROR,
"rtpg_union_mean_callback: Invalid arguments passed to callback");
1920 double *
value,
int *nodata
1930 elog(ERROR,
"rtpg_union_range_callback: Invalid arguments passed to callback");
1963 HeapTupleHeader tup;
1969 char *utypename = NULL;
1972 etype = ARR_ELEMTYPE(array);
1973 get_typlenbyvalalign(etype, &typlen, &typbyval, &typalign);
1978 typlen, typbyval, typalign,
1983 elog(ERROR,
"rtpg_union_unionarg_process: Invalid argument for unionarg");
1991 elog(ERROR,
"rtpg_union_unionarg_process: Could not allocate memory for band information");
1996 for (i = 0; i < n; i++) {
2005 tup = (HeapTupleHeader) DatumGetPointer(e[i]);
2007 elog(ERROR,
"rtpg_union_unionarg_process: Invalid argument for unionarg");
2012 tupv = GetAttributeByName(tup,
"nband", &isnull);
2015 elog(NOTICE,
"First argument (nband) of unionarg is NULL. Assuming nband = %d",
nband);
2018 nband = DatumGetInt32(tupv);
2021 elog(ERROR,
"rtpg_union_unionarg_process: Band number must be greater than zero (1-based)");
2026 tupv = GetAttributeByName(tup,
"uniontype", &isnull);
2028 elog(NOTICE,
"Second argument (uniontype) of unionarg is NULL. Assuming uniontype = LAST");
2032 utypename = text_to_cstring((text *) DatumGetPointer(tupv));
2053 elog(ERROR,
"rtpg_union_unionarg_process: Could not reallocate memory for band information");
2070 if (numbands <= arg->numband)
2080 elog(ERROR,
"rtpg_union_noarg: Could not reallocate memory for band information");
2086 for (; i < arg->
numband; i++) {
2094 elog(ERROR,
"rtpg_union_noarg: Could not allocate memory for working rasters");
2103 elog(ERROR,
"rtpg_union_noarg: Could not create working raster");
2116 MemoryContext aggcontext;
2117 MemoryContext oldcontext;
2127 int isempty[2] = {0};
2128 int hasband[2] = {0};
2130 double _offset[4] = {0.};
2138 char *utypename = NULL;
2142 double nodataval = 0;
2148 uint16_t _dim[2] = {0};
2155 if (!AggCheckCallContext(fcinfo, &aggcontext)) {
2156 elog(ERROR,
"RASTER_union_transfn: Cannot be called in a non-aggregate context");
2161 oldcontext = MemoryContextSwitchTo(aggcontext);
2163 if (PG_ARGISNULL(0)) {
2168 MemoryContextSwitchTo(oldcontext);
2169 elog(ERROR,
"RASTER_union_transfn: Could not allocate memory for state variable");
2185 if (!PG_ARGISNULL(1)) {
2187 pgraster = (
rt_pgraster *) PG_DETOAST_DATUM(PG_GETARG_DATUM(1));
2194 PG_FREE_IF_COPY(pgraster, 1);
2196 MemoryContextSwitchTo(oldcontext);
2197 elog(ERROR,
"RASTER_union_transfn: Could not deserialize raster");
2210 if (!PG_ARGISNULL(2)) {
2211 Oid calltype = get_fn_expr_argtype(fcinfo->flinfo, 2);
2222 utypename = text_to_cstring(PG_GETARG_TEXT_P(2));
2246 if (numband > idx) {
2264 PG_FREE_IF_COPY(pgraster, 1);
2267 MemoryContextSwitchTo(oldcontext);
2268 elog(ERROR,
"RASTER_union_transfn: Could not allocate memory for band information");
2273 for (i = idx; i < iwr->
numband; i++) {
2297 nband = PG_GETARG_INT32(2);
2303 PG_FREE_IF_COPY(pgraster, 1);
2306 MemoryContextSwitchTo(oldcontext);
2307 elog(ERROR,
"RASTER_union_transfn: Band number must be greater than zero (1-based)");
2318 PG_FREE_IF_COPY(pgraster, 1);
2321 MemoryContextSwitchTo(oldcontext);
2322 elog(ERROR,
"RASTER_union_transfn: Could not allocate memory for band information");
2343 PG_FREE_IF_COPY(pgraster, 1);
2346 MemoryContextSwitchTo(oldcontext);
2347 elog(ERROR,
"RASTER_union_transfn: Could not process unionarg");
2356 if (nargs > 3 && !PG_ARGISNULL(3)) {
2357 utypename = text_to_cstring(PG_GETARG_TEXT_P(3));
2371 for (i = 0; i < iwr->
numband; i++) {
2386 PG_FREE_IF_COPY(pgraster, 1);
2389 MemoryContextSwitchTo(oldcontext);
2390 elog(ERROR,
"RASTER_union_transfn: Could not allocate memory for working raster(s)");
2405 PG_FREE_IF_COPY(pgraster, 1);
2408 MemoryContextSwitchTo(oldcontext);
2409 elog(ERROR,
"RASTER_union_transfn: Could not create working raster");
2426 PG_FREE_IF_COPY(pgraster, 1);
2429 MemoryContextSwitchTo(oldcontext);
2430 elog(ERROR,
"RASTER_union_transfn: Could not check and balance number of bands");
2437 if (itrset == NULL) {
2442 PG_FREE_IF_COPY(pgraster, 1);
2445 MemoryContextSwitchTo(oldcontext);
2446 elog(ERROR,
"RASTER_union_transfn: Could not allocate memory for iterator arguments");
2451 for (i = 0; i < iwr->
numband; i++) {
2471 if (!isempty[0] && hasband[0])
2473 else if (!isempty[1] && hasband[1])
2480 if (_band != NULL) {
2518 itrset[0].
nband = 0;
2534 if (!isempty[0] && !isempty[1] && hasband[0] && hasband[1]) {
2548 PG_FREE_IF_COPY(pgraster, 1);
2551 MemoryContextSwitchTo(oldcontext);
2552 elog(ERROR,
"RASTER_union_transfn: Could not create internal raster");
2556 _offset[0], _offset[1], _offset[2], _offset[3]);
2563 double igt[6] = {0};
2579 hasnodata, nodataval,
2588 PG_FREE_IF_COPY(pgraster, 1);
2591 MemoryContextSwitchTo(oldcontext);
2592 elog(ERROR,
"RASTER_union_transfn: Could not add new band to internal raster");
2600 for (
y = 0;
y < _dim[1];
y++) {
2601 POSTGIS_RT_DEBUGF(4,
"Getting pixel line of working raster at (x, y, length) = (0, %d, %d)",
y, _dim[0]);
2615 PG_FREE_IF_COPY(pgraster, 1);
2618 MemoryContextSwitchTo(oldcontext);
2619 elog(ERROR,
"RASTER_union_transfn: Could not get pixel line from band of working raster");
2623 POSTGIS_RT_DEBUGF(4,
"Setting pixel line at (x, y, length) = (%d, %d, %d)", (
int) _offset[0], (
int) _offset[1] +
y, nvals);
2626 (
int) _offset[0], (
int) _offset[1] +
y,
2636 PG_FREE_IF_COPY(pgraster, 1);
2639 MemoryContextSwitchTo(oldcontext);
2640 elog(ERROR,
"RASTER_union_transfn: Could not set pixel line to band of internal raster");
2656 hasnodata, nodataval,
2673 PG_FREE_IF_COPY(pgraster, 1);
2676 MemoryContextSwitchTo(oldcontext);
2677 elog(ERROR,
"RASTER_union_transfn: Could not run raster iterator function");
2685 for (
y = 0;
y < _dim[1];
y++) {
2686 POSTGIS_RT_DEBUGF(4,
"Getting pixel line of iterator raster at (x, y, length) = (0, %d, %d)",
y, _dim[0]);
2702 PG_FREE_IF_COPY(pgraster, 1);
2705 MemoryContextSwitchTo(oldcontext);
2706 elog(ERROR,
"RASTER_union_transfn: Could not get pixel line from band of working raster");
2710 POSTGIS_RT_DEBUGF(4,
"Setting pixel line at (x, y, length) = (%d, %d, %d)", (
int) _offset[2], (
int) _offset[3] +
y, nvals);
2713 (
int) _offset[2], (
int) _offset[3] +
y,
2725 PG_FREE_IF_COPY(pgraster, 1);
2728 MemoryContextSwitchTo(oldcontext);
2729 elog(ERROR,
"RASTER_union_transfn: Could not set pixel line to band of internal raster");
2749 hasnodata, nodataval,
2763 PG_FREE_IF_COPY(pgraster, 1);
2766 MemoryContextSwitchTo(oldcontext);
2767 elog(ERROR,
"RASTER_union_transfn: Could not run raster iterator function");
2786 PG_FREE_IF_COPY(pgraster, 1);
2790 MemoryContextSwitchTo(oldcontext);
2794 PG_RETURN_POINTER(iwr);
2814 double nodataval = 0;
2819 if (!AggCheckCallContext(fcinfo, NULL)) {
2820 elog(ERROR,
"RASTER_union_finalfn: Cannot be called in a non-aggregate context");
2825 if (PG_ARGISNULL(0))
2832 if (itrset == NULL) {
2834 elog(ERROR,
"RASTER_union_finalfn: Could not allocate memory for iterator arguments");
2838 for (i = 0; i < iwr->
numband; i++) {
2853 itrset[0].
nband = 0;
2855 itrset[1].
nband = 0;
2863 hasnodata, nodataval,
2876 hasnodata, nodataval,
2890 elog(ERROR,
"RASTER_union_finalfn: Could not run raster iterator function");
2896 if (_raster == NULL)
2902 uint32_t bandNums[1] = {0};
2904 status = (_rtn == NULL) ? -1 : 0;
2929 elog(ERROR,
"RASTER_union_finalfn: Could not add band to final raster");
2942 if (!_rtn) PG_RETURN_NULL();
2952 SET_VARSIZE(pgraster, pgraster->
size);
2953 PG_RETURN_POINTER(pgraster);
2982 elog(ERROR,
"rtpg_clip_arg_init: Could not allocate memory for function arguments");
2996 if (arg->
band != NULL)
3001 if (arg->
mask != NULL)
3009 double *
value,
int *nodata
3065 if (PG_ARGISNULL(0) || PG_ARGISNULL(2))
3071 elog(ERROR,
"RASTER_clip: Could not initialize argument structure");
3076 pgraster = (
rt_pgraster *) PG_DETOAST_DATUM(PG_GETARG_DATUM(0));
3080 if (arg->
raster == NULL) {
3082 PG_FREE_IF_COPY(pgraster, 0);
3083 elog(ERROR,
"RASTER_clip: Could not deserialize raster");
3089 elog(NOTICE,
"Input raster is empty or has no bands. Returning empty raster");
3092 PG_FREE_IF_COPY(pgraster, 0);
3096 elog(ERROR,
"RASTER_clip: Could not create empty raster");
3105 SET_VARSIZE(pgrtn, pgrtn->
size);
3106 PG_RETURN_POINTER(pgrtn);
3114 gser = PG_GETARG_GSERIALIZED_P(2);
3126 elog(NOTICE,
"Geometry provided does not have the same SRID as the raster. Returning NULL");
3129 PG_FREE_IF_COPY(pgraster, 0);
3131 PG_FREE_IF_COPY(gser, 2);
3137 if (!PG_ARGISNULL(4) && !PG_GETARG_BOOL(4))
3144 PG_FREE_IF_COPY(pgraster, 0);
3146 PG_FREE_IF_COPY(gser, 2);
3148 elog(ERROR,
"RASTER_clip: Could not get convex hull of raster");
3155 PG_FREE_IF_COPY(gser, 2);
3160 elog(NOTICE,
"The input raster and input geometry do not intersect. Returning empty raster");
3163 PG_FREE_IF_COPY(pgraster, 0);
3168 elog(ERROR,
"RASTER_clip: Could not create empty raster");
3177 SET_VARSIZE(pgrtn, pgrtn->
size);
3178 PG_RETURN_POINTER(pgrtn);
3182 if (!PG_ARGISNULL(1)) {
3183 array = PG_GETARG_ARRAYTYPE_P(1);
3184 etype = ARR_ELEMTYPE(array);
3185 get_typlenbyvalalign(etype, &typlen, &typbyval, &typalign);
3193 PG_FREE_IF_COPY(pgraster, 0);
3195 elog(ERROR,
"RASTER_clip: Invalid data type for band indexes");
3202 typlen, typbyval, typalign,
3207 if (arg->
band == NULL) {
3209 PG_FREE_IF_COPY(pgraster, 0);
3211 elog(ERROR,
"RASTER_clip: Could not allocate memory for band arguments");
3215 for (i = 0, j = 0; i < arg->
numbands; i++) {
3216 if (nulls[i])
continue;
3220 arg->
band[j].
nband = DatumGetInt16(e[i]) - 1;
3223 arg->
band[j].
nband = DatumGetInt32(e[i]) - 1;
3230 if (j < arg->numbands) {
3232 if (arg->
band == NULL) {
3234 PG_FREE_IF_COPY(pgraster, 0);
3236 elog(ERROR,
"RASTER_clip: Could not reallocate memory for band arguments");
3244 for (i = 0; i < arg->
numbands; i++) {
3246 elog(NOTICE,
"Band at index %d not found in raster", arg->
band[i].
nband + 1);
3248 PG_FREE_IF_COPY(pgraster, 0);
3263 if (arg->
band == NULL) {
3266 PG_FREE_IF_COPY(pgraster, 0);
3269 elog(ERROR,
"RASTER_clip: Could not allocate memory for band arguments");
3273 for (i = 0; i < arg->
numbands; i++) {
3282 if (!PG_ARGISNULL(3)) {
3283 array = PG_GETARG_ARRAYTYPE_P(3);
3284 etype = ARR_ELEMTYPE(array);
3285 get_typlenbyvalalign(etype, &typlen, &typbyval, &typalign);
3293 PG_FREE_IF_COPY(pgraster, 0);
3295 elog(ERROR,
"RASTER_clip: Invalid data type for NODATA values");
3302 typlen, typbyval, typalign,
3307 for (i = 0, j = 0; i < arg->
numbands; i++, j++) {
3355 if (arg->
mask == NULL) {
3357 PG_FREE_IF_COPY(pgraster, 0);
3358 elog(ERROR,
"RASTER_clip: Could not rasterize intersection geometry");
3369 if (itrset == NULL) {
3371 PG_FREE_IF_COPY(pgraster, 0);
3372 elog(ERROR,
"RASTER_clip: Could not allocate memory for iterator arguments");
3377 for (i = 0; i < arg->
numbands; i++) {
3378 POSTGIS_RT_DEBUGF(4,
"band arg %d (nband, hasnodata, nodataval) = (%d, %d, %f)",
3406 PG_FREE_IF_COPY(pgraster, 0);
3407 elog(ERROR,
"RASTER_clip: Could not create output raster");
3416 PG_FREE_IF_COPY(pgraster, 0);
3417 elog(ERROR,
"RASTER_clip: Could not add NODATA band to output raster");
3431 itrset[1].
nband = 0;
3439 hasnodata, nodataval,
3451 PG_FREE_IF_COPY(pgraster, 0);
3452 elog(ERROR,
"RASTER_clip: Could not run raster iterator function");
3467 PG_FREE_IF_COPY(pgraster, 0);
3468 elog(NOTICE,
"RASTER_clip: Could not get band from working raster");
3477 PG_FREE_IF_COPY(pgraster, 0);
3478 elog(ERROR,
"RASTER_clip: Could not add new band to output raster");
3488 PG_FREE_IF_COPY(pgraster, 0);
3498 SET_VARSIZE(pgrtn, pgrtn->
size);
3499 PG_RETURN_POINTER(pgrtn);
3512 uint32_t numBands = 0;
3532 HeapTupleHeader tup;
3537 text *exprtext = NULL;
3542 char *pixeltype = NULL;
3543 text *pixeltypetext = NULL;
3545 double nodataval = 0;
3546 bool hasnodata =
FALSE;
3548 char **comma_set = NULL;
3549 uint32_t comma_n = 0;
3550 char **colon_set = NULL;
3551 uint32_t colon_n = 0;
3552 char **dash_set = NULL;
3553 uint32_t dash_n = 0;
3558 if (PG_ARGISNULL(0))
3560 pgraster = (
rt_pgraster *) PG_DETOAST_DATUM(PG_GETARG_DATUM(0));
3565 PG_FREE_IF_COPY(pgraster, 0);
3566 elog(ERROR,
"RASTER_reclass: Could not deserialize raster");
3570 POSTGIS_RT_DEBUGF(3,
"RASTER_reclass: %d possible bands to be reclassified", numBands);
3574 array = PG_GETARG_ARRAYTYPE_P(1);
3575 etype = ARR_ELEMTYPE(array);
3576 get_typlenbyvalalign(etype, &typlen, &typbyval, &typalign);
3578 deconstruct_array(array, etype, typlen, typbyval, typalign, &e,
3582 elog(NOTICE,
"Invalid argument for reclassargset. Returning original raster");
3586 PG_FREE_IF_COPY(pgraster, 0);
3590 SET_VARSIZE(pgrtn, pgrtn->
size);
3591 PG_RETURN_POINTER(pgrtn);
3599 for (i = 0; i < n; i++) {
3600 if (nulls[i])
continue;
3603 tup = (HeapTupleHeader) DatumGetPointer(e[i]);
3605 elog(NOTICE,
"Invalid argument for reclassargset. Returning original raster");
3609 PG_FREE_IF_COPY(pgraster, 0);
3613 SET_VARSIZE(pgrtn, pgrtn->
size);
3614 PG_RETURN_POINTER(pgrtn);
3618 tupv = GetAttributeByName(tup,
"nband", &isnull);
3620 elog(NOTICE,
"Invalid argument for reclassargset. Missing value of nband for reclassarg of index %d . Returning original raster", i);
3624 PG_FREE_IF_COPY(pgraster, 0);
3628 SET_VARSIZE(pgrtn, pgrtn->
size);
3629 PG_RETURN_POINTER(pgrtn);
3631 nband = DatumGetInt32(tupv);
3635 if (nband < 1 || nband > numBands) {
3636 elog(NOTICE,
"Invalid argument for reclassargset. Invalid band index (must use 1-based) for reclassarg of index %d . Returning original raster", i);
3640 PG_FREE_IF_COPY(pgraster, 0);
3644 SET_VARSIZE(pgrtn, pgrtn->
size);
3645 PG_RETURN_POINTER(pgrtn);
3649 tupv = GetAttributeByName(tup,
"reclassexpr", &isnull);
3651 elog(NOTICE,
"Invalid argument for reclassargset. Missing value of reclassexpr for reclassarg of index %d . Returning original raster", i);
3655 PG_FREE_IF_COPY(pgraster, 0);
3659 SET_VARSIZE(pgrtn, pgrtn->
size);
3660 PG_RETURN_POINTER(pgrtn);
3662 exprtext = (text *) DatumGetPointer(tupv);
3663 if (NULL == exprtext) {
3664 elog(NOTICE,
"Invalid argument for reclassargset. Missing value of reclassexpr for reclassarg of index %d . Returning original raster", i);
3668 PG_FREE_IF_COPY(pgraster, 0);
3672 SET_VARSIZE(pgrtn, pgrtn->
size);
3673 PG_RETURN_POINTER(pgrtn);
3675 expr = text_to_cstring(exprtext);
3684 elog(NOTICE,
"Invalid argument for reclassargset. Invalid expression of reclassexpr for reclassarg of index %d . Returning original raster", i);
3688 PG_FREE_IF_COPY(pgraster, 0);
3692 SET_VARSIZE(pgrtn, pgrtn->
size);
3693 PG_RETURN_POINTER(pgrtn);
3700 for (a = 0, j = 0; a < comma_n; a++) {
3706 elog(NOTICE,
"Invalid argument for reclassargset. Invalid expression of reclassexpr for reclassarg of index %d . Returning original raster", i);
3707 for (k = 0; k < j; k++) pfree(exprset[k]);
3712 PG_FREE_IF_COPY(pgraster, 0);
3716 SET_VARSIZE(pgrtn, pgrtn->
size);
3717 PG_RETURN_POINTER(pgrtn);
3723 for (b = 0; b < colon_n; b++) {
3728 if (dash_n < 1 || dash_n > 3) {
3729 elog(NOTICE,
"Invalid argument for reclassargset. Invalid expression of reclassexpr for reclassarg of index %d . Returning original raster", i);
3730 for (k = 0; k < j; k++) pfree(exprset[k]);
3735 PG_FREE_IF_COPY(pgraster, 0);
3739 SET_VARSIZE(pgrtn, pgrtn->
size);
3740 PG_RETURN_POINTER(pgrtn);
3743 for (c = 0; c < dash_n; c++) {
3747 strlen(dash_set[c]) == 1 && (
3748 strchr(dash_set[c],
'(') != NULL ||
3749 strchr(dash_set[c],
'[') != NULL ||
3750 strchr(dash_set[c],
')') != NULL ||
3751 strchr(dash_set[c],
']') != NULL
3755 junk = palloc(
sizeof(
char) * (strlen(dash_set[c + 1]) + 2));
3757 for (k = 0; k <= j; k++) pfree(exprset[k]);
3760 PG_FREE_IF_COPY(pgraster, 0);
3762 elog(ERROR,
"RASTER_reclass: Could not allocate memory");
3766 sprintf(junk,
"%s%s", dash_set[c], dash_set[c + 1]);
3768 dash_set[c] = repalloc(dash_set[c],
sizeof(
char) * (strlen(junk) + 1));
3769 strcpy(dash_set[c], junk);
3773 for (dash_it = 1; dash_it < dash_n; dash_it++) {
3774 dash_set[dash_it - 1] = repalloc(dash_set[dash_it - 1], (strlen(dash_set[dash_it]) + 1) *
sizeof(
char));
3775 strcpy(dash_set[dash_it - 1], dash_set[dash_it]);
3779 pfree(dash_set[dash_n]);
3780 dash_set = repalloc(dash_set,
sizeof(
char *) * dash_n);
3784 if (c < 1 && dash_n > 2) {
3785 elog(NOTICE,
"Invalid argument for reclassargset. Invalid expression of reclassexpr for reclassarg of index %d . Returning original raster", i);
3786 for (k = 0; k < j; k++) pfree(exprset[k]);
3791 PG_FREE_IF_COPY(pgraster, 0);
3795 SET_VARSIZE(pgrtn, pgrtn->
size);
3796 PG_RETURN_POINTER(pgrtn);
3807 strchr(dash_set[c],
')') != NULL ||
3808 strchr(dash_set[c],
']') != NULL
3813 else if (strchr(dash_set[c],
'(') != NULL){
3823 strrchr(dash_set[c],
'(') != NULL ||
3824 strrchr(dash_set[c],
'[') != NULL
3829 else if (strrchr(dash_set[c],
']') != NULL) {
3837 POSTGIS_RT_DEBUGF(4,
"RASTER_reclass: exc_val %d inc_val %d", exc_val, inc_val);
3845 val = strtod(dash_set[c], &junk);
3846 if (errno != 0 || dash_set[c] == junk) {
3847 elog(NOTICE,
"Invalid argument for reclassargset. Invalid expression of reclassexpr for reclassarg of index %d . Returning original raster", i);
3848 for (k = 0; k < j; k++) pfree(exprset[k]);
3853 PG_FREE_IF_COPY(pgraster, 0);
3857 SET_VARSIZE(pgrtn, pgrtn->
size);
3858 PG_RETURN_POINTER(pgrtn);
3864 junk = strstr(colon_set[b], dash_set[c]);
3869 "(colon_set[%d], dash_set[%d], junk) = (%s, %s, %s)",
3870 b, c, colon_set[b], dash_set[c], junk
3873 if (junk != colon_set[b]) {
3875 if (*(junk - 1) ==
'-') {
3878 ((junk - 1) == colon_set[b]) ||
3879 (*(junk - 2) ==
'-') ||
3880 (*(junk - 2) ==
'[') ||
3881 (*(junk - 2) ==
'(')
3901 exprset[j]->
src.
min = val;
3907 exprset[j]->
src.
max = val;
3917 exprset[j]->
dst.
min = val;
3920 exprset[j]->
dst.
max = val;
3928 , exprset[j]->src.min
3938 tupv = GetAttributeByName(tup,
"pixeltype", &isnull);
3940 elog(NOTICE,
"Invalid argument for reclassargset. Missing value of pixeltype for reclassarg of index %d . Returning original raster", i);
3944 PG_FREE_IF_COPY(pgraster, 0);
3948 SET_VARSIZE(pgrtn, pgrtn->
size);
3949 PG_RETURN_POINTER(pgrtn);
3951 pixeltypetext = (text *) DatumGetPointer(tupv);
3952 if (NULL == pixeltypetext) {
3953 elog(NOTICE,
"Invalid argument for reclassargset. Missing value of pixeltype for reclassarg of index %d . Returning original raster", i);
3957 PG_FREE_IF_COPY(pgraster, 0);
3961 SET_VARSIZE(pgrtn, pgrtn->
size);
3962 PG_RETURN_POINTER(pgrtn);
3964 pixeltype = text_to_cstring(pixeltypetext);
3969 tupv = GetAttributeByName(tup,
"nodataval", &isnull);
3975 nodataval = DatumGetFloat8(tupv);
3984 elog(NOTICE,
"Could not find raster band of index %d. Returning original raster",
nband);
3985 for (k = 0; k < j; k++) pfree(exprset[k]);
3990 PG_FREE_IF_COPY(pgraster, 0);
3994 SET_VARSIZE(pgrtn, pgrtn->
size);
3995 PG_RETURN_POINTER(pgrtn);
3999 for (k = 0; k < j; k++) pfree(exprset[k]);
4003 PG_FREE_IF_COPY(pgraster, 0);
4005 elog(ERROR,
"RASTER_reclass: Could not reclassify raster band of index %d",
nband);
4011 for (k = 0; k < j; k++) pfree(exprset[k]);
4016 PG_FREE_IF_COPY(pgraster, 0);
4018 elog(ERROR,
"RASTER_reclass: Could not replace raster band of index %d with reclassified band",
nband);
4026 for (k = 0; k < j; k++) pfree(exprset[k]);
4032 PG_FREE_IF_COPY(pgraster, 0);
4038 SET_VARSIZE(pgrtn, pgrtn->
size);
4039 PG_RETURN_POINTER(pgrtn);
4068 elog(ERROR,
"rtpg_colormap_arg: Could not allocate memory for function arguments");
4079 elog(ERROR,
"rtpg_colormap_arg: Could not allocate memory for function arguments");
4112 for (i = 0; i < arg->
nentry; i++) {
4113 if (arg->
entry[i] != NULL)
4114 pfree(arg->
entry[i]);
4120 for (i = 0; i < arg->
nelement; i++)
4140 if (PG_ARGISNULL(0))
4146 elog(ERROR,
"RASTER_colorMap: Could not initialize argument structure");
4151 pgraster = (
rt_pgraster *) PG_DETOAST_DATUM(PG_GETARG_DATUM(0));
4157 PG_FREE_IF_COPY(pgraster, 0);
4158 elog(ERROR,
"RASTER_colorMap: Could not deserialize raster");
4163 if (!PG_ARGISNULL(1))
4164 arg->
nband = PG_GETARG_INT32(1);
4169 elog(NOTICE,
"Raster does not have band at index %d. Returning empty raster", arg->
nband);
4174 PG_FREE_IF_COPY(pgraster, 0);
4175 elog(ERROR,
"RASTER_colorMap: Could not create empty raster");
4180 PG_FREE_IF_COPY(pgraster, 0);
4184 if (pgraster == NULL)
4187 SET_VARSIZE(pgraster, ((
rt_pgraster*) pgraster)->size);
4188 PG_RETURN_POINTER(pgraster);
4193 if (arg->
band == NULL) {
4196 PG_FREE_IF_COPY(pgraster, 0);
4197 elog(ERROR,
"RASTER_colorMap: Could not get band at index %d",
nband);
4202 if (!PG_ARGISNULL(3)) {
4203 char *method = NULL;
4204 char *tmp = text_to_cstring(PG_GETARG_TEXT_P(3));
4211 if (strcmp(method,
"INTERPOLATE") == 0)
4213 else if (strcmp(method,
"EXACT") == 0)
4215 else if (strcmp(method,
"NEAREST") == 0)
4218 elog(NOTICE,
"Unknown value provided for method. Defaulting to INTERPOLATE");
4228 if (PG_ARGISNULL(2)) {
4230 PG_FREE_IF_COPY(pgraster, 0);
4231 elog(ERROR,
"RASTER_colorMap: Value must be provided for colormap");
4236 char *colormap = text_to_cstring(PG_GETARG_TEXT_P(2));
4245 if (!strlen(colormap)) {
4247 PG_FREE_IF_COPY(pgraster, 0);
4248 elog(ERROR,
"RASTER_colorMap: Value must be provided for colormap");
4256 PG_FREE_IF_COPY(pgraster, 0);
4257 elog(ERROR,
"RASTER_colorMap: Could not process the value provided for colormap");
4265 PG_FREE_IF_COPY(pgraster, 0);
4266 elog(ERROR,
"RASTER_colorMap: Could not allocate memory for colormap entries");
4272 for (i = 0; i < arg->
nentry; i++) {
4286 if (!strlen(_entry)) {
4296 PG_FREE_IF_COPY(pgraster, 0);
4297 elog(ERROR,
"RASTER_colorMap: Could not process colormap entry %d", i + 1);
4301 elog(NOTICE,
"More than five elements in colormap entry %d. Using at most five elements", i + 1);
4310 for (j = 0; j < arg->
nelement; j++) {
4319 char *percent = NULL;
4323 strcmp(_element,
"NV") == 0 ||
4324 strcmp(_element,
"NULL") == 0 ||
4325 strcmp(_element,
"NODATA") == 0
4330 elog(NOTICE,
"More than one NODATA entry found. Using only the first one");
4339 else if ((percent = strchr(_element,
'%')) != NULL) {
4351 PG_FREE_IF_COPY(pgraster, 0);
4352 elog(ERROR,
"RASTER_colorMap: Could not get band's summary stats to process percentages");
4358 tmp = palloc(
sizeof(
char) * (percent - _element + 1));
4362 PG_FREE_IF_COPY(pgraster, 0);
4363 elog(ERROR,
"RASTER_colorMap: Could not allocate memory for value of percentage");
4367 memcpy(tmp, _element, percent - _element);
4368 tmp[percent - _element] =
'\0';
4373 value = strtod(tmp, NULL);
4375 if (errno != 0 || _element == junk) {
4378 PG_FREE_IF_COPY(pgraster, 0);
4379 elog(ERROR,
"RASTER_colorMap: Could not process percent string to value");
4385 elog(NOTICE,
"Percentage values cannot be less than zero. Defaulting to zero");
4388 else if (
value > 100.) {
4389 elog(NOTICE,
"Percentage values cannot be greater than 100. Defaulting to 100");
4401 if (errno != 0 || _element == junk) {
4404 PG_FREE_IF_COPY(pgraster, 0);
4405 elog(ERROR,
"RASTER_colorMap: Could not process string to value");
4416 value = (int) strtod(_element, &junk);
4417 if (errno != 0 || _element == junk) {
4420 PG_FREE_IF_COPY(pgraster, 0);
4421 elog(ERROR,
"RASTER_colorMap: Could not process string to value");
4426 elog(NOTICE,
"RGBA value cannot be greater than 255. Defaulting to 255");
4429 else if (
value < 0) {
4430 elog(NOTICE,
"RGBA value cannot be less than zero. Defaulting to zero");
4439 POSTGIS_RT_DEBUGF(4,
"colormap->entry[%d] (isnodata, value, R, G, B, A) = (%d, %f, %d, %d, %d, %d)",
4460 PG_FREE_IF_COPY(pgraster, 0);
4461 elog(ERROR,
"RASTER_colorMap: Could not create new raster with applied colormap");
4466 PG_FREE_IF_COPY(pgraster, 0);
4472 if (pgraster == NULL)
4475 SET_VARSIZE(pgraster, ((
rt_pgraster*) pgraster)->size);
4476 PG_RETURN_POINTER(pgraster);
4488 int x,
y,
nband, width, height;
4490 double newnodatavalue = 0.0;
4491 double newinitialvalue = 0.0;
4492 double newval = 0.0;
4493 char *newexpr = NULL;
4494 char *initexpr = NULL;
4495 char *expression = NULL;
4496 int hasnodataval = 0;
4497 double nodataval = 0.;
4499 int skipcomputation = 0;
4501 const int argkwcount = 3;
4502 enum KEYWORDS { kVAL=0, kX=1, kY=2 };
4503 char *argkw[] = {
"[rast]",
"[rast.x]",
"[rast.y]"};
4504 Oid argkwtypes[] = { FLOAT8OID, INT4OID, INT4OID };
4506 Oid argtype[] = { FLOAT8OID, INT4OID, INT4OID };
4507 uint8_t argpos[3] = {0};
4512 SPIPlanPtr spi_plan = NULL;
4513 SPITupleTable * tuptable = NULL;
4515 char * strFromText = NULL;
4516 Datum *values = NULL;
4517 Datum datum = (Datum)NULL;
4519 bool isnull =
FALSE;
4526 if (PG_ARGISNULL(0)) {
4527 elog(NOTICE,
"Raster is NULL. Returning NULL");
4533 pgraster = (
rt_pgraster *)PG_DETOAST_DATUM(PG_GETARG_DATUM(0));
4536 PG_FREE_IF_COPY(pgraster, 0);
4537 elog(ERROR,
"RASTER_mapAlgebraExpr: Could not deserialize raster");
4543 if (PG_ARGISNULL(1))
4546 nband = PG_GETARG_INT32(1);
4552 POSTGIS_RT_DEBUG(3,
"RASTER_mapAlgebraExpr: Creating new empty raster...");
4563 if ( NULL == newrast ) {
4564 PG_FREE_IF_COPY(pgraster, 0);
4565 elog(ERROR,
"RASTER_mapAlgebraExpr: Could not create a new raster");
4590 elog(NOTICE,
"Raster is empty. Returning an empty raster");
4592 PG_FREE_IF_COPY(pgraster, 0);
4596 if (NULL == pgrtn) {
4598 elog(ERROR,
"RASTER_mapAlgebraExpr: Could not serialize raster");
4602 SET_VARSIZE(pgrtn, pgrtn->
size);
4603 PG_RETURN_POINTER(pgrtn);
4614 elog(NOTICE,
"Raster does not have the required band. Returning a raster "
4617 PG_FREE_IF_COPY(pgraster, 0);
4621 if (NULL == pgrtn) {
4622 elog(ERROR,
"RASTER_mapAlgebraExpr: Could not serialize raster");
4626 SET_VARSIZE(pgrtn, pgrtn->
size);
4627 PG_RETURN_POINTER(pgrtn);
4632 if ( NULL ==
band ) {
4633 elog(NOTICE,
"Could not get the required band. Returning a raster "
4636 PG_FREE_IF_COPY(pgraster, 0);
4640 if (NULL == pgrtn) {
4641 elog(ERROR,
"RASTER_mapAlgebraExpr: Could not serialize raster");
4645 SET_VARSIZE(pgrtn, pgrtn->
size);
4646 PG_RETURN_POINTER(pgrtn);
4652 POSTGIS_RT_DEBUG(3,
"RASTER_mapAlgebraExpr: Getting NODATA value for band...");
4670 newinitialvalue = newnodatavalue;
4677 if (PG_ARGISNULL(2)) {
4682 strFromText = text_to_cstring(PG_GETARG_TEXT_P(2));
4685 if (newpixeltype ==
PT_END)
4689 if (newpixeltype ==
PT_END) {
4690 PG_FREE_IF_COPY(pgraster, 0);
4691 elog(ERROR,
"RASTER_mapAlgebraExpr: Invalid pixeltype");
4700 if (!PG_ARGISNULL(3)) {
4701 expression = text_to_cstring(PG_GETARG_TEXT_P(3));
4702 len = strlen(
"SELECT (") + strlen(expression) + strlen(
")::double precision");
4703 initexpr = (
char *)palloc(len + 1);
4705 memcpy(initexpr,
"SELECT (", strlen(
"SELECT ("));
4706 memcpy(initexpr + strlen(
"SELECT ("), expression, strlen(expression));
4707 memcpy(initexpr + strlen(
"SELECT (") + strlen(expression),
")::double precision", strlen(
")::double precision"));
4708 initexpr[len] =
'\0';
4726 if (!PG_ARGISNULL(4)) {
4728 nodataval = PG_GETARG_FLOAT8(4);
4729 newinitialvalue = nodataval;
4746 POSTGIS_RT_DEBUG(3,
"RASTER_mapAlgebraExpr: Band is a nodata band, returning "
4747 "a raster filled with nodata");
4750 newinitialvalue,
TRUE, newnodatavalue, 0);
4756 PG_FREE_IF_COPY(pgraster, 0);
4761 if (NULL == pgrtn) {
4762 elog(ERROR,
"RASTER_mapAlgebraExpr: Could not serialize raster");
4766 SET_VARSIZE(pgrtn, pgrtn->
size);
4767 PG_RETURN_POINTER(pgrtn);
4775 if (initexpr != NULL && ( !strcmp(initexpr,
"SELECT [rast]") || !strcmp(initexpr,
"SELECT [rast.val]") ) && !hasnodataval) {
4778 "Returning raster with band %d from original raster",
nband);
4790 PG_FREE_IF_COPY(pgraster, 0);
4795 if (NULL == pgrtn) {
4796 elog(ERROR,
"RASTER_mapAlgebraExpr: Could not serialize raster");
4800 SET_VARSIZE(pgrtn, pgrtn->
size);
4801 PG_RETURN_POINTER(pgrtn);
4808 if (initexpr != NULL && strstr(initexpr,
"[rast") == NULL) {
4809 ret = SPI_connect();
4810 if (ret != SPI_OK_CONNECT) {
4811 PG_FREE_IF_COPY(pgraster, 0);
4812 elog(ERROR,
"RASTER_mapAlgebraExpr: Could not connect to the SPI manager");
4817 ret = SPI_execute(initexpr,
FALSE, 0);
4819 if (ret != SPI_OK_SELECT || SPI_tuptable == NULL || SPI_processed != 1) {
4823 SPI_freetuptable(tuptable);
4824 PG_FREE_IF_COPY(pgraster, 0);
4827 elog(ERROR,
"RASTER_mapAlgebraExpr: Invalid construction for expression");
4831 tupdesc = SPI_tuptable->tupdesc;
4832 tuptable = SPI_tuptable;
4834 tuple = tuptable->vals[0];
4835 newexpr = SPI_getvalue(tuple, tupdesc, 1);
4837 POSTGIS_RT_DEBUG(3,
"Constant expression evaluated to NULL, keeping initvalue");
4838 newval = newinitialvalue;
4840 newval = atof(newexpr);
4843 SPI_freetuptable(tuptable);
4850 skipcomputation = 1;
4856 if (!hasnodataval) {
4857 newinitialvalue = newval;
4858 skipcomputation = 2;
4862 else if (
FLT_NEQ(newval, newinitialvalue)) {
4863 skipcomputation = 2;
4872 newinitialvalue,
TRUE, newnodatavalue, 0);
4879 if (expression == NULL || skipcomputation == 2) {
4885 PG_FREE_IF_COPY(pgraster, 0);
4890 if (NULL == pgrtn) {
4891 elog(ERROR,
"RASTER_mapAlgebraExpr: Could not serialize raster");
4895 SET_VARSIZE(pgrtn, pgrtn->
size);
4896 PG_RETURN_POINTER(pgrtn);
4899 RASTER_DEBUG(3,
"RASTER_mapAlgebraExpr: Creating new raster band...");
4903 if ( NULL == newband ) {
4904 elog(NOTICE,
"Could not modify band for new raster. Returning new "
4905 "raster with the original band");
4910 PG_FREE_IF_COPY(pgraster, 0);
4915 if (NULL == pgrtn) {
4916 elog(ERROR,
"RASTER_mapAlgebraExpr: Could not serialize raster");
4920 SET_VARSIZE(pgrtn, pgrtn->
size);
4921 PG_RETURN_POINTER(pgrtn);
4927 if (initexpr != NULL) {
4930 pfree(initexpr); initexpr=newexpr;
4932 sprintf(place,
"$1");
4933 for (i = 0, j = 1; i < argkwcount; i++) {
4936 pfree(initexpr); initexpr=newexpr;
4938 argtype[argcount] = argkwtypes[i];
4942 sprintf(place,
"$%d", j);
4952 values = (Datum *) palloc(
sizeof(Datum) * argcount);
4953 if (values == NULL) {
4958 PG_FREE_IF_COPY(pgraster, 0);
4961 elog(ERROR,
"RASTER_mapAlgebraExpr: Could not allocate memory for value parameters of prepared statement");
4966 nulls = (
char *)palloc(argcount);
4967 if (nulls == NULL) {
4972 PG_FREE_IF_COPY(pgraster, 0);
4975 elog(ERROR,
"RASTER_mapAlgebraExpr: Could not allocate memory for null parameters of prepared statement");
4980 ret = SPI_connect();
4981 if (ret != SPI_OK_CONNECT) {
4986 PG_FREE_IF_COPY(pgraster, 0);
4989 elog(ERROR,
"RASTER_mapAlgebraExpr: Could not connect to the SPI manager");
4994 spi_plan = SPI_prepare(initexpr, argcount, argtype);
4996 if (spi_plan == NULL) {
4999 PG_FREE_IF_COPY(pgraster, 0);
5006 elog(ERROR,
"RASTER_mapAlgebraExpr: Could not prepare expression");
5011 for (
x = 0;
x < width;
x++) {
5012 for(
y = 0;
y < height;
y++) {
5020 if (skipcomputation == 0) {
5021 if (initexpr != NULL) {
5023 memset(nulls,
'n', argcount);
5025 for (i = 0; i < argkwcount; i++) {
5027 if (idx < 1)
continue;
5032 values[idx] = Int32GetDatum(
x+1);
5037 values[idx] = Int32GetDatum(
y+1);
5040 else if (i == kVAL ) {
5041 values[idx] = Float8GetDatum(
r);
5047 ret = SPI_execute_plan(spi_plan, values, nulls,
FALSE, 0);
5048 if (ret != SPI_OK_SELECT || SPI_tuptable == NULL ||
5049 SPI_processed != 1) {
5051 SPI_freetuptable(tuptable);
5053 SPI_freeplan(spi_plan);
5061 PG_FREE_IF_COPY(pgraster, 0);
5064 elog(ERROR,
"RASTER_mapAlgebraExpr: Error executing prepared plan");
5069 tupdesc = SPI_tuptable->tupdesc;
5070 tuptable = SPI_tuptable;
5072 tuple = tuptable->vals[0];
5073 datum = SPI_getbinval(tuple, tupdesc, 1, &isnull);
5074 if ( SPI_result == SPI_ERROR_NOATTRIBUTE ) {
5075 POSTGIS_RT_DEBUGF(3,
"Expression for pixel %d,%d (value %g) errored, skip setting",
x+1,
y+1,
r);
5076 newval = newinitialvalue;
5078 else if ( isnull ) {
5079 POSTGIS_RT_DEBUGF(3,
"Expression for pixel %d,%d (value %g) evaluated to NULL, skip setting",
x+1,
y+1,
r);
5080 newval = newinitialvalue;
5082 newval = DatumGetFloat8(datum);
5085 SPI_freetuptable(tuptable);
5089 newval = newinitialvalue;
5102 if (initexpr != NULL) {
5103 SPI_freeplan(spi_plan);
5117 POSTGIS_RT_DEBUG(3,
"RASTER_mapAlgebraExpr: raster modified, serializing it.");
5121 PG_FREE_IF_COPY(pgraster, 0);
5128 SET_VARSIZE(pgrtn, pgrtn->
size);
5136 PG_RETURN_POINTER(pgrtn);
5151 int x,
y,
nband, width, height;
5153 double newnodatavalue = 0.0;
5154 double newinitialvalue = 0.0;
5155 double newval = 0.0;
5160 #if POSTGIS_PGSQL_VERSION < 120
5161 FunctionCallInfoData cbdata;
5163 LOCAL_FCINFO(cbdata, FUNC_MAX_ARGS);
5166 char * strFromText = NULL;
5172 if (PG_ARGISNULL(0)) {
5173 elog(WARNING,
"Raster is NULL. Returning NULL");
5179 pgraster = (
rt_pgraster *)PG_DETOAST_DATUM(PG_GETARG_DATUM(0));
5182 PG_FREE_IF_COPY(pgraster, 0);
5183 elog(ERROR,
"RASTER_mapAlgebraFct: Could not deserialize raster");
5191 if (PG_ARGISNULL(1))
5194 nband = PG_GETARG_INT32(1);
5210 if ( NULL == newrast ) {
5213 PG_FREE_IF_COPY(pgraster, 0);
5215 elog(ERROR,
"RASTER_mapAlgebraFct: Could not create a new raster");
5240 elog(NOTICE,
"Raster is empty. Returning an empty raster");
5242 PG_FREE_IF_COPY(pgraster, 0);
5246 if (NULL == pgrtn) {
5247 elog(ERROR,
"RASTER_mapAlgebraFct: Could not serialize raster");
5251 SET_VARSIZE(pgrtn, pgrtn->
size);
5252 PG_RETURN_POINTER(pgrtn);
5262 elog(NOTICE,
"Raster does not have the required band. Returning a raster "
5265 PG_FREE_IF_COPY(pgraster, 0);
5269 if (NULL == pgrtn) {
5270 elog(ERROR,
"RASTER_mapAlgebraFct: Could not serialize raster");
5274 SET_VARSIZE(pgrtn, pgrtn->
size);
5275 PG_RETURN_POINTER(pgrtn);
5280 if ( NULL ==
band ) {
5281 elog(NOTICE,
"Could not get the required band. Returning a raster "
5284 PG_FREE_IF_COPY(pgraster, 0);
5288 if (NULL == pgrtn) {
5289 elog(ERROR,
"RASTER_mapAlgebraFct: Could not serialize raster");
5293 SET_VARSIZE(pgrtn, pgrtn->
size);
5294 PG_RETURN_POINTER(pgrtn);
5300 POSTGIS_RT_DEBUG(3,
"RASTER_mapAlgebraFct: Getting NODATA value for band...");
5317 newinitialvalue = newnodatavalue;
5324 if (PG_ARGISNULL(2)) {
5329 strFromText = text_to_cstring(PG_GETARG_TEXT_P(2));
5332 if (newpixeltype ==
PT_END)
5336 if (newpixeltype ==
PT_END) {
5339 PG_FREE_IF_COPY(pgraster, 0);
5342 elog(ERROR,
"RASTER_mapAlgebraFct: Invalid pixeltype");
5350 if (PG_ARGISNULL(3)) {
5353 PG_FREE_IF_COPY(pgraster, 0);
5356 elog(ERROR,
"RASTER_mapAlgebraFct: Required function is missing. Returning NULL");
5360 oid = PG_GETARG_OID(3);
5361 if (oid == InvalidOid) {
5364 PG_FREE_IF_COPY(pgraster, 0);
5367 elog(ERROR,
"RASTER_mapAlgebraFct: Got invalid function object id. Returning NULL");
5371 fmgr_info(oid, &cbinfo);
5374 if (cbinfo.fn_retset) {
5377 PG_FREE_IF_COPY(pgraster, 0);
5380 elog(ERROR,
"RASTER_mapAlgebraFct: Function provided must return double precision not resultset");
5384 else if (cbinfo.fn_nargs < 2 || cbinfo.fn_nargs > 3) {
5387 PG_FREE_IF_COPY(pgraster, 0);
5390 elog(ERROR,
"RASTER_mapAlgebraFct: Function does not have two or three input parameters");
5394 if (cbinfo.fn_nargs == 2)
5399 if (func_volatile(oid) ==
'v') {
5400 elog(NOTICE,
"Function provided is VOLATILE. Unless required and for best performance, function should be IMMUTABLE or STABLE");
5404 #if POSTGIS_PGSQL_VERSION < 120
5405 InitFunctionCallInfoData(cbdata, &cbinfo, 2, InvalidOid, NULL, NULL);
5407 cbdata.argnull[0] =
FALSE;
5408 cbdata.argnull[1] =
FALSE;
5409 cbdata.argnull[2] =
FALSE;
5411 InitFunctionCallInfoData(*cbdata, &cbinfo, 2, InvalidOid, NULL, NULL);
5413 cbdata->args[0].isnull =
FALSE;
5414 cbdata->args[1].isnull =
FALSE;
5415 cbdata->args[2].isnull =
FALSE;
5419 if (PG_ARGISNULL(4)) {
5420 if (cbinfo.fn_strict) {
5423 PG_FREE_IF_COPY(pgraster, 0);
5426 elog(ERROR,
"RASTER_mapAlgebraFct: Strict callback functions cannot have null parameters");
5430 #if POSTGIS_PGSQL_VERSION < 120
5431 cbdata.arg[k] = (Datum)NULL;
5432 cbdata.argnull[k] =
TRUE;
5434 cbdata->args[k].value = (Datum)NULL;
5435 cbdata->args[k].isnull =
TRUE;
5439 #if POSTGIS_PGSQL_VERSION < 120
5440 cbdata.arg[k] = PG_GETARG_DATUM(4);
5442 cbdata->args[k].value = PG_GETARG_DATUM(4);
5453 POSTGIS_RT_DEBUG(3,
"RASTER_mapAlgebraFct: Band is a nodata band, returning "
5454 "a raster filled with nodata");
5457 newinitialvalue,
TRUE, newnodatavalue, 0);
5460 PG_FREE_IF_COPY(pgraster, 0);
5465 if (NULL == pgrtn) {
5466 elog(ERROR,
"RASTER_mapAlgebraFct: Could not serialize raster");
5470 SET_VARSIZE(pgrtn, pgrtn->
size);
5471 PG_RETURN_POINTER(pgrtn);
5480 newinitialvalue,
TRUE, newnodatavalue, 0);
5484 if ( NULL == newband ) {
5485 elog(NOTICE,
"Could not modify band for new raster. Returning new "
5486 "raster with the original band");
5489 PG_FREE_IF_COPY(pgraster, 0);
5494 if (NULL == pgrtn) {
5495 elog(ERROR,
"RASTER_mapAlgebraFct: Could not serialize raster");
5499 SET_VARSIZE(pgrtn, pgrtn->
size);
5500 PG_RETURN_POINTER(pgrtn);
5506 for (
x = 0;
x < width;
x++) {
5507 for(
y = 0;
y < height;
y++) {
5515 if (
FLT_EQ(
r, newnodatavalue)) {
5516 if (cbinfo.fn_strict) {
5517 POSTGIS_RT_DEBUG(3,
"RASTER_mapAlgebraFct: Strict callbacks cannot accept NULL arguments, skipping NODATA cell.");
5520 #if POSTGIS_PGSQL_VERSION < 120
5521 cbdata.argnull[0] =
TRUE;
5522 cbdata.arg[0] = (Datum)NULL;
5524 cbdata->args[0].isnull =
TRUE;
5525 cbdata->args[0].value = (Datum)NULL;
5529 #if POSTGIS_PGSQL_VERSION < 120
5530 cbdata.argnull[0] =
FALSE;
5531 cbdata.arg[0] = Float8GetDatum(
r);
5533 cbdata->args[0].isnull =
FALSE;
5534 cbdata->args[0].value = Float8GetDatum(
r);
5539 if (cbinfo.fn_nargs == 3) {
5543 d[0] = Int32GetDatum(
x+1);
5544 d[1] = Int32GetDatum(
y+1);
5546 a = construct_array(d, 2, INT4OID,
sizeof(
int32),
true,
'i');
5548 #if POSTGIS_PGSQL_VERSION < 120
5549 cbdata.argnull[1] =
FALSE;
5550 cbdata.arg[1] = PointerGetDatum(a);
5552 cbdata->args[1].isnull =
FALSE;
5553 cbdata->args[1].value = PointerGetDatum(a);
5560 #if POSTGIS_PGSQL_VERSION < 120
5561 tmpnewval = FunctionCallInvoke(&cbdata);
5563 if (cbdata.isnull) {
5564 newval = newnodatavalue;
5567 tmpnewval = FunctionCallInvoke(cbdata);
5571 newval = newnodatavalue;
5575 newval = DatumGetFloat8(tmpnewval);
5589 POSTGIS_RT_DEBUG(3,
"RASTER_mapAlgebraFct: raster modified, serializing it.");
5593 PG_FREE_IF_COPY(pgraster, 0);
5604 SET_VARSIZE(pgrtn, pgrtn->
size);
5605 PG_RETURN_POINTER(pgrtn);
5620 int x,
y,
nband, width, height, ngbwidth, ngbheight, winwidth, winheight, u, v, nIndex, nNullItems;
5622 double newnodatavalue = 0.0;
5623 double newinitialvalue = 0.0;
5624 double newval = 0.0;
5629 #if POSTGIS_PGSQL_VERSION < 120
5630 FunctionCallInfoData cbdata;
5632 LOCAL_FCINFO(cbdata, FUNC_MAX_ARGS);
5635 ArrayType * neighborDatum;
5636 char * strFromText = NULL;
5637 text * txtNodataMode = NULL;
5638 text * txtCallbackParam = NULL;
5640 float fltReplace = 0;
5641 bool valuereplace =
false, pixelreplace, nNodataOnly =
true, nNullSkip =
false;
5642 Datum * neighborData = NULL;
5643 bool * neighborNulls = NULL;
5644 int neighborDims[2];
5653 if (PG_ARGISNULL(0)) {
5654 elog(WARNING,
"Raster is NULL. Returning NULL");
5660 pgraster = (
rt_pgraster *)PG_DETOAST_DATUM(PG_GETARG_DATUM(0));
5664 PG_FREE_IF_COPY(pgraster, 0);
5665 elog(ERROR,
"RASTER_mapAlgebraFctNgb: Could not deserialize raster");
5673 if (PG_ARGISNULL(1))
5676 nband = PG_GETARG_INT32(1);
5681 POSTGIS_RT_DEBUG(3,
"RASTER_mapAlgebraFctNgb: Creating new empty raster...");
5692 if ( NULL == newrast ) {
5694 PG_FREE_IF_COPY(pgraster, 0);
5695 elog(ERROR,
"RASTER_mapAlgebraFctNgb: Could not create a new raster");
5720 elog(NOTICE,
"Raster is empty. Returning an empty raster");
5722 PG_FREE_IF_COPY(pgraster, 0);
5726 if (NULL == pgrtn) {
5727 elog(ERROR,
"RASTER_mapAlgebraFctNgb: Could not serialize raster");
5731 SET_VARSIZE(pgrtn, pgrtn->
size);
5732 PG_RETURN_POINTER(pgrtn);
5742 elog(NOTICE,
"Raster does not have the required band. Returning a raster "
5745 PG_FREE_IF_COPY(pgraster, 0);
5749 if (NULL == pgrtn) {
5750 elog(ERROR,
"RASTER_mapAlgebraFctNgb: Could not serialize raster");
5754 SET_VARSIZE(pgrtn, pgrtn->
size);
5755 PG_RETURN_POINTER(pgrtn);
5760 if ( NULL ==
band ) {
5761 elog(NOTICE,
"Could not get the required band. Returning a raster "
5764 PG_FREE_IF_COPY(pgraster, 0);
5768 if (NULL == pgrtn) {
5769 elog(ERROR,
"RASTER_mapAlgebraFctNgb: Could not serialize raster");
5773 SET_VARSIZE(pgrtn, pgrtn->
size);
5774 PG_RETURN_POINTER(pgrtn);
5780 POSTGIS_RT_DEBUG(3,
"RASTER_mapAlgebraFctNgb: Getting NODATA value for band...");
5797 newinitialvalue = newnodatavalue;
5804 if (PG_ARGISNULL(2)) {
5809 strFromText = text_to_cstring(PG_GETARG_TEXT_P(2));
5810 POSTGIS_RT_DEBUGF(3,
"RASTER_mapAlgebraFctNgb: Pixeltype parameter: %s", strFromText);
5813 if (newpixeltype ==
PT_END)
5817 if (newpixeltype ==
PT_END) {
5820 PG_FREE_IF_COPY(pgraster, 0);
5823 elog(ERROR,
"RASTER_mapAlgebraFctNgb: Invalid pixeltype");
5831 if (PG_ARGISNULL(5)) {
5834 PG_FREE_IF_COPY(pgraster, 0);
5837 elog(ERROR,
"RASTER_mapAlgebraFctNgb: Required function is missing");
5841 oid = PG_GETARG_OID(5);
5842 if (oid == InvalidOid) {
5845 PG_FREE_IF_COPY(pgraster, 0);
5848 elog(ERROR,
"RASTER_mapAlgebraFctNgb: Got invalid function object id");
5852 fmgr_info(oid, &cbinfo);
5855 if (cbinfo.fn_retset) {
5858 PG_FREE_IF_COPY(pgraster, 0);
5861 elog(ERROR,
"RASTER_mapAlgebraFctNgb: Function provided must return double precision not resultset");
5865 else if (cbinfo.fn_nargs != 3) {
5868 PG_FREE_IF_COPY(pgraster, 0);
5871 elog(ERROR,
"RASTER_mapAlgebraFctNgb: Function does not have three input parameters");
5875 if (func_volatile(oid) ==
'v') {
5876 elog(NOTICE,
"Function provided is VOLATILE. Unless required and for best performance, function should be IMMUTABLE or STABLE");
5880 #if POSTGIS_PGSQL_VERSION < 120
5881 InitFunctionCallInfoData(cbdata, &cbinfo, 3, InvalidOid, NULL, NULL);
5882 memset(cbdata.argnull,
FALSE,
sizeof(
bool) * 3);
5884 InitFunctionCallInfoData(*cbdata, &cbinfo, 3, InvalidOid, NULL, NULL);
5885 cbdata->args[0].isnull =
FALSE;
5886 cbdata->args[1].isnull =
FALSE;
5887 cbdata->args[2].isnull =
FALSE;
5891 if (PG_ARGISNULL(7)) {
5892 if (cbinfo.fn_strict) {
5895 PG_FREE_IF_COPY(pgraster, 0);
5898 elog(ERROR,
"RASTER_mapAlgebraFctNgb: Strict callback functions cannot have NULL parameters");
5902 #if POSTGIS_PGSQL_VERSION < 120
5903 cbdata.arg[2] = (Datum)NULL;
5904 cbdata.argnull[2] =
TRUE;
5906 cbdata->args[2].value = (Datum)NULL;
5907 cbdata->args[2].isnull =
TRUE;
5911 #if POSTGIS_PGSQL_VERSION < 120
5912 cbdata.arg[2] = PG_GETARG_DATUM(7);
5914 cbdata->args[2].value = PG_GETARG_DATUM(7);
5925 POSTGIS_RT_DEBUG(3,
"RASTER_mapAlgebraFctNgb: Band is a nodata band, returning "
5926 "a raster filled with nodata");
5929 newinitialvalue,
TRUE, newnodatavalue, 0);
5932 PG_FREE_IF_COPY(pgraster, 0);
5937 if (NULL == pgrtn) {
5938 elog(ERROR,
"RASTER_mapAlgebraFctNgb: Could not serialize raster");
5942 SET_VARSIZE(pgrtn, pgrtn->
size);
5943 PG_RETURN_POINTER(pgrtn);
5952 newinitialvalue,
TRUE, newnodatavalue, 0);
5956 if ( NULL == newband ) {
5957 elog(NOTICE,
"Could not modify band for new raster. Returning new "
5958 "raster with the original band");
5961 PG_FREE_IF_COPY(pgraster, 0);
5966 if (NULL == pgrtn) {
5967 elog(ERROR,
"RASTER_mapAlgebraFctNgb: Could not serialize raster");
5971 SET_VARSIZE(pgrtn, pgrtn->
size);
5972 PG_RETURN_POINTER(pgrtn);
5976 if (PG_ARGISNULL(3) || PG_GETARG_INT32(3) <= 0) {
5977 elog(NOTICE,
"Neighborhood width is NULL or <= 0. Returning new "
5978 "raster with the original band");
5981 PG_FREE_IF_COPY(pgraster, 0);
5986 if (NULL == pgrtn) {
5987 elog(ERROR,
"RASTER_mapAlgebraFctNgb: Could not serialize raster");
5991 SET_VARSIZE(pgrtn, pgrtn->
size);
5992 PG_RETURN_POINTER(pgrtn);
5995 ngbwidth = PG_GETARG_INT32(3);
5996 winwidth = ngbwidth * 2 + 1;
5999 if (PG_ARGISNULL(4) || PG_GETARG_INT32(4) <= 0) {
6000 elog(NOTICE,
"Neighborhood height is NULL or <= 0. Returning new "
6001 "raster with the original band");
6004 PG_FREE_IF_COPY(pgraster, 0);
6009 if (NULL == pgrtn) {
6010 elog(ERROR,
"RASTER_mapAlgebraFctNgb: Could not serialize raster");
6014 SET_VARSIZE(pgrtn, pgrtn->
size);
6015 PG_RETURN_POINTER(pgrtn);
6018 ngbheight = PG_GETARG_INT32(4);
6019 winheight = ngbheight * 2 + 1;
6022 if (PG_ARGISNULL(6)) {
6023 elog(NOTICE,
"Neighborhood NODATA behavior defaulting to 'ignore'");
6024 txtNodataMode = cstring_to_text(
"ignore");
6027 txtNodataMode = PG_GETARG_TEXT_P(6);
6030 txtCallbackParam = (text*)palloc(VARSIZE(txtNodataMode));
6031 SET_VARSIZE(txtCallbackParam, VARSIZE(txtNodataMode));
6032 memcpy((
void *)VARDATA(txtCallbackParam), (
void *)VARDATA(txtNodataMode), VARSIZE(txtNodataMode) - VARHDRSZ);
6035 #if POSTGIS_PGSQL_VERSION < 120
6036 cbdata.arg[1] = CStringGetDatum(txtCallbackParam);
6038 cbdata->args[1].value = CStringGetDatum(txtCallbackParam);
6041 strFromText = text_to_cstring(txtNodataMode);
6044 if (strcmp(strFromText,
"VALUE") == 0)
6045 valuereplace =
true;
6046 else if (strcmp(strFromText,
"IGNORE") != 0 && strcmp(strFromText,
"NULL") != 0) {
6048 if (sscanf(strFromText,
"%d", &intReplace) <= 0 && sscanf(strFromText,
"%f", &fltReplace) <= 0) {
6050 elog(NOTICE,
"Neighborhood NODATA mode is not recognized. Must be one of 'value', 'ignore', "
6051 "'NULL', or a numeric value. Returning new raster with the original band");
6054 pfree(txtCallbackParam);
6058 PG_FREE_IF_COPY(pgraster, 0);
6063 if (NULL == pgrtn) {
6064 elog(ERROR,
"RASTER_mapAlgebraFctNgb: Could not serialize raster");
6068 SET_VARSIZE(pgrtn, pgrtn->
size);
6069 PG_RETURN_POINTER(pgrtn);
6072 else if (strcmp(strFromText,
"NULL") == 0) {
6081 neighborData = (Datum *)palloc(winwidth * winheight *
sizeof(Datum));
6082 neighborNulls = (
bool *)palloc(winwidth * winheight *
sizeof(
bool));
6085 neighborDims[0] = winwidth;
6086 neighborDims[1] = winheight;
6093 get_typlenbyvalalign(FLOAT8OID, &typlen, &typbyval, &typalign);
6095 for (
x = 0 + ngbwidth;
x < width - ngbwidth;
x++) {
6096 for(
y = 0 + ngbheight;
y < height - ngbheight;
y++) {
6101 pixelreplace =
false;
6105 pixelreplace =
true;
6108 for (u =
x - ngbwidth; u <=
x + ngbwidth; u++) {
6109 for (v =
y - ngbheight; v <=
y + ngbheight; v++) {
6114 neighborData[nIndex] = Float8GetDatum((
double)
r);
6115 neighborNulls[nIndex] =
false;
6116 nNodataOnly =
false;
6120 if (valuereplace && pixelreplace) {
6122 neighborData[nIndex] = Float8GetDatum((
double)rpix);
6123 neighborNulls[nIndex] =
false;
6128 neighborData[nIndex] = PointerGetDatum(NULL);
6129 neighborNulls[nIndex] =
true;
6136 neighborData[nIndex] = PointerGetDatum(NULL);
6137 neighborNulls[nIndex] =
true;
6149 if (!(nNodataOnly ||
6150 (nNullSkip && nNullItems > 0) ||
6151 (valuereplace && nNullItems > 0))) {
6153 x,
y, winwidth, winheight);
6155 neighborDatum = construct_md_array((
void *)neighborData, neighborNulls, 2, neighborDims, neighborLbs,
6156 FLOAT8OID, typlen, typbyval, typalign);
6158 #if POSTGIS_PGSQL_VERSION < 120
6160 cbdata.arg[0] = PointerGetDatum(neighborDatum);
6163 tmpnewval = FunctionCallInvoke(&cbdata);
6166 if (cbdata.isnull) {
6167 newval = newnodatavalue;
6171 cbdata->args[0].value = PointerGetDatum(neighborDatum);
6174 tmpnewval = FunctionCallInvoke(cbdata);
6179 newval = newnodatavalue;
6183 newval = DatumGetFloat8(tmpnewval);
6199 pfree(neighborNulls);
6200 pfree(neighborData);
6202 pfree(txtCallbackParam);
6205 PG_FREE_IF_COPY(pgraster, 0);
6209 POSTGIS_RT_DEBUG(3,
"RASTER_mapAlgebraFctNgb: raster modified, serializing it.");
6220 SET_VARSIZE(pgrtn, pgrtn->
size);
6221 PG_RETURN_POINTER(pgrtn);
6224 #define ARGKWCOUNT 8
6232 const uint32_t set_count = 2;
6234 int pgrastpos[2] = {-1, -1};
6237 int _isempty[2] = {0};
6238 uint32_t bandindex[2] = {0};
6241 int _hasnodata[2] = {0};
6242 double _nodataval[2] = {0};
6243 double _offset[4] = {0.};
6244 double _rastoffset[2][4] = {{0.}};
6245 int _haspixel[2] = {0};
6246 double _pixel[2] = {0};
6247 int _pos[2][2] = {{0}};
6248 uint16_t _dim[2][2] = {{0}};
6250 char *pixtypename = NULL;
6252 char *extenttypename = NULL;
6257 uint16_t dim[2] = {0};
6260 double nodataval = 0;
6261 double gt[6] = {0.};
6263 Oid calltype = InvalidOid;
6265 const uint32_t spi_count = 3;
6266 uint16_t spi_exprpos[3] = {4, 7, 8};
6267 uint32_t spi_argcount[3] = {0};
6270 SPIPlanPtr spi_plan[3] = {NULL};
6271 uint16_t spi_empty = 0;
6272 Oid *argtype = NULL;
6273 uint8_t argpos[3][8] = {{0}};
6274 char *argkw[] = {
"[rast1.x]",
"[rast1.y]",
"[rast1.val]",
"[rast1]",
"[rast2.x]",
"[rast2.y]",
"[rast2.val]",
"[rast2]"};
6278 SPITupleTable *tuptable = NULL;
6281 bool isnull =
FALSE;
6282 int hasargval[3] = {0};
6283 double argval[3] = {0.};
6284 int hasnodatanodataval = 0;
6285 double nodatanodataval = 0;
6288 Oid ufc_noid = InvalidOid;
6290 #if POSTGIS_PGSQL_VERSION < 120
6291 FunctionCallInfoData ufc_info;
6293 LOCAL_FCINFO(ufc_info, FUNC_MAX_ARGS);
6295 int ufc_nullcount = 0;
6311 for (i = 0, j = 0; i < set_count; i++) {
6312 if (!PG_ARGISNULL(j)) {
6313 pgrast[i] = (
rt_pgraster *) PG_DETOAST_DATUM(PG_GETARG_DATUM(j));
6320 for (k = 0; k <= i; k++) {
6321 if (k < i &&
rast[k] != NULL)
6323 if (pgrastpos[k] != -1)
6324 PG_FREE_IF_COPY(pgrast[k], pgrastpos[k]);
6326 elog(ERROR,
"RASTER_mapAlgebra2: Could not deserialize the %s raster", i < 1 ?
"first" :
"second");
6334 if (!PG_ARGISNULL(j)) {
6335 bandindex[i] = PG_GETARG_INT32(j);
6348 if (
rast[0] == NULL &&
rast[1] == NULL) {
6349 elog(NOTICE,
"The two rasters provided are NULL. Returning NULL");
6350 for (k = 0; k < set_count; k++) {
6351 if (pgrastpos[k] != -1)
6352 PG_FREE_IF_COPY(pgrast[k], pgrastpos[k]);
6358 if (_isempty[0] && _isempty[1]) {
6359 elog(NOTICE,
"The two rasters provided are empty. Returning empty raster");
6363 for (k = 0; k < set_count; k++) {
6364 if (
rast[k] != NULL)
6366 if (pgrastpos[k] != -1)
6367 PG_FREE_IF_COPY(pgrast[k], pgrastpos[k]);
6369 elog(ERROR,
"RASTER_mapAlgebra2: Could not create empty raster");
6379 SET_VARSIZE(pgrtn, pgrtn->
size);
6380 PG_RETURN_POINTER(pgrtn);
6385 (
rast[0] == NULL || _isempty[0]) ||
6386 (
rast[1] == NULL || _isempty[1])
6389 if (
rast[0] == NULL || _isempty[0]) {
6402 if (_rast[i] != NULL)
6414 if (_rast[i] == NULL) {
6416 for (k = 0; k < set_count; k++) {
6417 if (pgrastpos[k] != -1)
6418 PG_FREE_IF_COPY(pgrast[k], pgrastpos[k]);
6420 elog(ERROR,
"RASTER_mapAlgebra2: Could not create NODATA raster");
6454 for (k = 0; k < set_count; k++) {
6455 if (_rast[k] != NULL)
6457 if (pgrastpos[k] != -1)
6458 PG_FREE_IF_COPY(pgrast[k], pgrastpos[k]);
6460 elog(ERROR,
"RASTER_mapAlgebra2: Could not test for alignment on the two rasters");
6464 elog(NOTICE,
"The two rasters provided do not have the same alignment. Returning NULL");
6465 for (k = 0; k < set_count; k++) {
6466 if (_rast[k] != NULL)
6468 if (pgrastpos[k] != -1)
6469 PG_FREE_IF_COPY(pgrast[k], pgrastpos[k]);
6475 if (!PG_ARGISNULL(5)) {
6476 pixtypename = text_to_cstring(PG_GETARG_TEXT_P(5));
6479 if (pixtype ==
PT_END ) {
6480 for (k = 0; k < set_count; k++) {
6481 if (_rast[k] != NULL)
6483 if (pgrastpos[k] != -1)
6484 PG_FREE_IF_COPY(pgrast[k], pgrastpos[k]);
6486 elog(ERROR,
"RASTER_mapAlgebra2: Invalid pixel type: %s", pixtypename);
6492 if (!PG_ARGISNULL(6)) {
6505 for (k = 0; k < set_count; k++) {
6506 if (_rast[k] != NULL)
6508 if (pgrastpos[k] != -1)
6509 PG_FREE_IF_COPY(pgrast[k], pgrastpos[k]);
6511 elog(ERROR,
"RASTER_mapAlgebra2: Could not get output raster of correct extent");
6516 _rastoffset[0][0] = _offset[0];
6517 _rastoffset[0][1] = _offset[1];
6518 _rastoffset[1][0] = _offset[2];
6519 _rastoffset[1][1] = _offset[3];
6527 switch (extenttype) {
6537 (extenttype ==
ET_FIRST && i == 0) ||
6541 elog(NOTICE,
"The %s raster is NULL. Returning NULL", (i != 1 ?
"FIRST" :
"SECOND"));
6542 for (k = 0; k < set_count; k++) {
6543 if (_rast[k] != NULL)
6545 if (pgrastpos[k] != -1)
6546 PG_FREE_IF_COPY(pgrast[k], pgrastpos[k]);
6554 elog(NOTICE,
"The %s raster does not have the band at index %d. Returning no band raster of correct extent",
6555 (i != 1 ?
"FIRST" :
"SECOND"), bandindex[i]
6558 for (k = 0; k < set_count; k++) {
6559 if (_rast[k] != NULL)
6561 if (pgrastpos[k] != -1)
6562 PG_FREE_IF_COPY(pgrast[k], pgrastpos[k]);
6567 if (!pgrtn) PG_RETURN_NULL();
6569 SET_VARSIZE(pgrtn, pgrtn->
size);
6570 PG_RETURN_POINTER(pgrtn);
6578 _isempty[0] || _isempty[1] ||
6581 elog(NOTICE,
"The two rasters provided have no intersection. Returning no band raster");
6584 if (dim[0] || dim[1]) {
6589 for (k = 0; k < set_count; k++) {
6590 if (_rast[k] != NULL)
6592 if (pgrastpos[k] != -1)
6593 PG_FREE_IF_COPY(pgrast[k], pgrastpos[k]);
6595 elog(ERROR,
"RASTER_mapAlgebra2: Could not create no band raster");
6603 for (k = 0; k < set_count; k++) {
6604 if (_rast[k] != NULL)
6606 if (pgrastpos[k] != -1)
6607 PG_FREE_IF_COPY(pgrast[k], pgrastpos[k]);
6612 if (!pgrtn) PG_RETURN_NULL();
6614 SET_VARSIZE(pgrtn, pgrtn->
size);
6615 PG_RETURN_POINTER(pgrtn);
6620 for (k = 0; k < set_count; k++) {
6621 if (_rast[k] != NULL)
6623 if (pgrastpos[k] != -1)
6624 PG_FREE_IF_COPY(pgrast[k], pgrastpos[k]);
6626 elog(ERROR,
"RASTER_mapAlgebra2: ET_LAST and ET_CUSTOM are not implemented");
6636 elog(NOTICE,
"The two rasters provided do not have the respectively specified band indices. Returning no band raster of correct extent");
6638 for (k = 0; k < set_count; k++) {
6639 if (_rast[k] != NULL)
6641 if (pgrastpos[k] != -1)
6642 PG_FREE_IF_COPY(pgrast[k], pgrastpos[k]);
6647 if (!pgrtn) PG_RETURN_NULL();
6649 SET_VARSIZE(pgrtn, pgrtn->
size);
6650 PG_RETURN_POINTER(pgrtn);
6654 for (i = 0; i < set_count; i++) {
6663 if (_band[i] == NULL) {
6664 for (k = 0; k < set_count; k++) {
6665 if (_rast[k] != NULL)
6667 if (pgrastpos[k] != -1)
6668 PG_FREE_IF_COPY(pgrast[k], pgrastpos[k]);
6671 elog(ERROR,
"RASTER_mapAlgebra2: Could not get band %d of the %s raster",
6673 (i < 1 ?
"FIRST" :
"SECOND")
6685 if ((extenttype ==
ET_SECOND && !_isempty[1]) || _isempty[0])
6692 if (extenttype ==
ET_SECOND && !_isempty[1] && _hasnodata[1]) {
6693 nodataval = _nodataval[1];
6695 else if (!_isempty[0] && _hasnodata[0]) {
6696 nodataval = _nodataval[0];
6698 else if (!_isempty[1] && _hasnodata[1]) {
6699 nodataval = _nodataval[1];
6702 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));
6714 for (k = 0; k < set_count; k++) {
6715 if (_rast[k] != NULL)
6717 if (pgrastpos[k] != -1)
6718 PG_FREE_IF_COPY(pgrast[k], pgrastpos[k]);
6721 elog(ERROR,
"RASTER_mapAlgebra2: Could not add new band to output raster");
6728 for (k = 0; k < set_count; k++) {
6729 if (_rast[k] != NULL)
6731 if (pgrastpos[k] != -1)
6732 PG_FREE_IF_COPY(pgrast[k], pgrastpos[k]);
6735 elog(ERROR,
"RASTER_mapAlgebra2: Could not get newly added band of output raster");
6740 (
int) _rastoffset[0][0],
6741 (
int) _rastoffset[0][1],
6742 (
int) _rastoffset[1][0],
6743 (
int) _rastoffset[1][1]
6746 POSTGIS_RT_DEBUGF(4,
"metadata = (%f, %f, %d, %d, %f, %f, %f, %f, %d)",
6763 calltype = get_fn_expr_argtype(fcinfo->flinfo, 4);
6770 if (SPI_connect() != SPI_OK_CONNECT) {
6771 for (k = 0; k < set_count; k++) {
6772 if (_rast[k] != NULL)
6774 if (pgrastpos[k] != -1)
6775 PG_FREE_IF_COPY(pgrast[k], pgrastpos[k]);
6778 elog(ERROR,
"RASTER_mapAlgebra2: Could not connect to the SPI manager");
6783 memset(hasargval, 0,
sizeof(
int) * spi_count);
6793 for (i = 0; i < spi_count; i++) {
6794 if (!PG_ARGISNULL(spi_exprpos[i])) {
6796 char place[5] =
"$1";
6797 expr = text_to_cstring(PG_GETARG_TEXT_P(spi_exprpos[i]));
6811 sprintf(place,
"$%d", k);
6817 len = strlen(
"SELECT (") + strlen(expr) + strlen(
")::double precision");
6818 sql = (
char *) palloc(len + 1);
6821 for (k = 0; k < spi_count; k++) SPI_freeplan(spi_plan[k]);
6824 for (k = 0; k < set_count; k++) {
6825 if (_rast[k] != NULL)
6827 if (pgrastpos[k] != -1)
6828 PG_FREE_IF_COPY(pgrast[k], pgrastpos[k]);
6832 elog(ERROR,
"RASTER_mapAlgebra2: Could not allocate memory for expression parameter %d", spi_exprpos[i]);
6836 memcpy(
sql,
"SELECT (", strlen(
"SELECT ("));
6837 memcpy(
sql + strlen(
"SELECT ("), expr, strlen(expr));
6838 memcpy(
sql + strlen(
"SELECT (") + strlen(expr),
")::double precision", strlen(
")::double precision"));
6844 if (spi_argcount[i]) {
6845 argtype = (Oid *) palloc(spi_argcount[i] *
sizeof(Oid));
6846 if (argtype == NULL) {
6849 for (k = 0; k < spi_count; k++) SPI_freeplan(spi_plan[k]);
6852 for (k = 0; k < set_count; k++) {
6853 if (_rast[k] != NULL)
6855 if (pgrastpos[k] != -1)
6856 PG_FREE_IF_COPY(pgrast[k], pgrastpos[k]);
6860 elog(ERROR,
"RASTER_mapAlgebra2: Could not allocate memory for prepared plan argtypes of expression parameter %d", spi_exprpos[i]);
6866 if (argpos[i][j] < 1)
continue;
6870 (strstr(argkw[j],
"[rast1.x]") != NULL) ||
6871 (strstr(argkw[j],
"[rast1.y]") != NULL) ||
6872 (strstr(argkw[j],
"[rast2.x]") != NULL) ||
6873 (strstr(argkw[j],
"[rast2.y]") != NULL)
6875 argtype[k] = INT4OID;
6879 argtype[k] = FLOAT8OID;
6885 spi_plan[i] = SPI_prepare(
sql, spi_argcount[i], argtype);
6888 if (spi_plan[i] == NULL) {
6891 for (k = 0; k < spi_count; k++) SPI_freeplan(spi_plan[k]);
6894 for (k = 0; k < set_count; k++) {
6895 if (_rast[k] != NULL)
6897 if (pgrastpos[k] != -1)
6898 PG_FREE_IF_COPY(pgrast[k], pgrastpos[k]);
6902 elog(ERROR,
"RASTER_mapAlgebra2: Could not create prepared plan of expression parameter %d", spi_exprpos[i]);
6908 err = SPI_execute(
sql,
TRUE, 0);
6909 if (err != SPI_OK_SELECT || SPI_tuptable == NULL || SPI_processed != 1) {
6912 for (k = 0; k < spi_count; k++) SPI_freeplan(spi_plan[k]);
6915 for (k = 0; k < set_count; k++) {
6916 if (_rast[k] != NULL)
6918 if (pgrastpos[k] != -1)
6919 PG_FREE_IF_COPY(pgrast[k], pgrastpos[k]);
6923 elog(ERROR,
"RASTER_mapAlgebra2: Could not evaluate expression parameter %d", spi_exprpos[i]);
6928 tupdesc = SPI_tuptable->tupdesc;
6929 tuptable = SPI_tuptable;
6930 tuple = tuptable->vals[0];
6932 datum = SPI_getbinval(tuple, tupdesc, 1, &isnull);
6933 if (SPI_result == SPI_ERROR_NOATTRIBUTE) {
6936 if (SPI_tuptable) SPI_freetuptable(tuptable);
6937 for (k = 0; k < spi_count; k++) SPI_freeplan(spi_plan[k]);
6940 for (k = 0; k < set_count; k++) {
6941 if (_rast[k] != NULL)
6943 if (pgrastpos[k] != -1)
6944 PG_FREE_IF_COPY(pgrast[k], pgrastpos[k]);
6948 elog(ERROR,
"RASTER_mapAlgebra2: Could not get result of expression parameter %d", spi_exprpos[i]);
6954 argval[i] = DatumGetFloat8(datum);
6957 if (SPI_tuptable) SPI_freetuptable(tuptable);
6967 if (!PG_ARGISNULL(9)) {
6968 hasnodatanodataval = 1;
6969 nodatanodataval = PG_GETARG_FLOAT8(9);
6972 hasnodatanodataval = 0;
6975 case REGPROCEDUREOID: {
6977 if (!PG_ARGISNULL(4)) {
6980 ufc_noid = PG_GETARG_OID(4);
6983 fmgr_info(ufc_noid, &ufl_info);
6987 if (ufl_info.fn_retset) {
6991 else if (ufl_info.fn_nargs < 3 || ufl_info.fn_nargs > 4) {
7001 for (k = 0; k < set_count; k++) {
7002 if (_rast[k] != NULL)
7004 if (pgrastpos[k] != -1)
7005 PG_FREE_IF_COPY(pgrast[k], pgrastpos[k]);
7010 elog(ERROR,
"RASTER_mapAlgebra2: Function provided must have three or four input parameters");
7012 elog(ERROR,
"RASTER_mapAlgebra2: Function provided must return double precision not resultset");
7016 if (func_volatile(ufc_noid) ==
'v') {
7017 elog(NOTICE,
"Function provided is VOLATILE. Unless required and for best performance, function should be IMMUTABLE or STABLE");
7021 #if POSTGIS_PGSQL_VERSION < 120
7022 InitFunctionCallInfoData(ufc_info, &ufl_info, ufl_info.fn_nargs, InvalidOid, NULL, NULL);
7023 memset(ufc_info.argnull,
FALSE,
sizeof(
bool) * ufl_info.fn_nargs);
7025 InitFunctionCallInfoData(
7026 *ufc_info, &ufl_info, ufl_info.fn_nargs, InvalidOid, NULL, NULL);
7027 ufc_info->args[0].isnull =
FALSE;
7028 ufc_info->args[1].isnull =
FALSE;
7029 ufc_info->args[2].isnull =
FALSE;
7030 if (ufl_info.fn_nargs == 4)
7031 ufc_info->args[3].isnull =
FALSE;
7034 if (ufl_info.fn_nargs != 4)
7038 #if POSTGIS_PGSQL_VERSION < 120
7039 if (!PG_ARGISNULL(7)) {
7040 ufc_info.arg[k] = PG_GETARG_DATUM(7);
7043 ufc_info.arg[k] = (Datum) NULL;
7044 ufc_info.argnull[k] =
TRUE;
7048 if (!PG_ARGISNULL(7))
7050 ufc_info->args[k].value = PG_GETARG_DATUM(7);
7054 ufc_info->args[k].value = (Datum)NULL;
7055 ufc_info->args[k].isnull =
TRUE;
7063 for (k = 0; k < set_count; k++) {
7064 if (_rast[k] != NULL)
7066 if (pgrastpos[k] != -1)
7067 PG_FREE_IF_COPY(pgrast[k], pgrastpos[k]);
7070 elog(ERROR,
"RASTER_mapAlgebra2: Invalid data type for expression or userfunction");
7078 (calltype == TEXTOID) && (
7079 (spi_empty != spi_count) || hasnodatanodataval
7082 (calltype == REGPROCEDUREOID) && (ufc_noid != InvalidOid)
7084 for (
x = 0;
x < dim[0];
x++) {
7085 for (
y = 0;
y < dim[1];
y++) {
7088 for (i = 0; i < set_count; i++) {
7093 _x = (int)
x - (
int)_rastoffset[i][0];
7094 _y = (int)
y - (
int)_rastoffset[i][1];
7097 _pos[i][0] = _x + 1;
7098 _pos[i][1] = _y + 1;
7101 if (_band[i] == NULL) {
7102 if (!_hasnodata[i]) {
7104 _pixel[i] = _nodataval[i];
7109 (_x >= 0 && _x < _dim[i][0]) &&
7110 (_y >= 0 && _y < _dim[i][1])
7115 if (calltype == TEXTOID) {
7116 for (k = 0; k < spi_count; k++) SPI_freeplan(spi_plan[k]);
7120 for (k = 0; k < set_count; k++) {
7121 if (_rast[k] != NULL)
7123 if (pgrastpos[k] != -1)
7124 PG_FREE_IF_COPY(pgrast[k], pgrastpos[k]);
7128 elog(ERROR,
"RASTER_mapAlgebra2: Could not get pixel of %s raster", (i < 1 ?
"FIRST" :
"SECOND"));
7132 if (!_hasnodata[i] || !isnodata)
7151 if (!_haspixel[0] && !_haspixel[1])
7155 else if (_haspixel[0] && !_haspixel[1])
7159 else if (!_haspixel[0] && _haspixel[1])
7168 if (hasnodatanodataval) {
7170 pixel = nodatanodataval;
7174 else if (hasargval[i]) {
7179 else if (spi_plan[i] != NULL) {
7183 memset(values, (Datum) NULL,
sizeof(Datum) *
ARGKWCOUNT);
7188 if (spi_argcount[i]) {
7192 if (idx < 1)
continue;
7195 if (strstr(argkw[j],
"[rast1.x]") != NULL) {
7196 values[idx] = _pos[0][0];
7198 else if (strstr(argkw[j],
"[rast1.y]") != NULL) {
7199 values[idx] = _pos[0][1];
7202 (strstr(argkw[j],
"[rast1.val]") != NULL) ||
7203 (strstr(argkw[j],
"[rast1]") != NULL)
7205 if (_isempty[0] || !_haspixel[0])
7208 values[idx] = Float8GetDatum(_pixel[0]);
7210 else if (strstr(argkw[j],
"[rast2.x]") != NULL) {
7211 values[idx] = _pos[1][0];
7213 else if (strstr(argkw[j],
"[rast2.y]") != NULL) {
7214 values[idx] = _pos[1][1];
7217 (strstr(argkw[j],
"[rast2.val]") != NULL) ||
7218 (strstr(argkw[j],
"[rast2]") != NULL)
7220 if (_isempty[1] || !_haspixel[1])
7223 values[idx] = Float8GetDatum(_pixel[1]);
7229 err = SPI_execute_plan(spi_plan[i], values, nulls,
TRUE, 1);
7230 if (err != SPI_OK_SELECT || SPI_tuptable == NULL || SPI_processed != 1) {
7232 for (k = 0; k < spi_count; k++) SPI_freeplan(spi_plan[k]);
7235 for (k = 0; k < set_count; k++) {
7236 if (_rast[k] != NULL)
7238 if (pgrastpos[k] != -1)
7239 PG_FREE_IF_COPY(pgrast[k], pgrastpos[k]);
7243 elog(ERROR,
"RASTER_mapAlgebra2: Unexpected error when running prepared statement %d", i);
7248 tupdesc = SPI_tuptable->tupdesc;
7249 tuptable = SPI_tuptable;
7250 tuple = tuptable->vals[0];
7252 datum = SPI_getbinval(tuple, tupdesc, 1, &isnull);
7253 if (SPI_result == SPI_ERROR_NOATTRIBUTE) {
7255 if (SPI_tuptable) SPI_freetuptable(tuptable);
7256 for (k = 0; k < spi_count; k++) SPI_freeplan(spi_plan[k]);
7259 for (k = 0; k < set_count; k++) {
7260 if (_rast[k] != NULL)
7262 if (pgrastpos[k] != -1)
7263 PG_FREE_IF_COPY(pgrast[k], pgrastpos[k]);
7267 elog(ERROR,
"RASTER_mapAlgebra2: Could not get result of prepared statement %d", i);
7273 pixel = DatumGetFloat8(datum);
7276 if (SPI_tuptable) SPI_freetuptable(tuptable);
7279 case REGPROCEDUREOID: {
7284 for (i = 0; i < set_count; i++) {
7285 #if POSTGIS_PGSQL_VERSION < 120
7286 ufc_info.arg[i] = Float8GetDatum(_pixel[i]);
7288 ufc_info->args[i].value = Float8GetDatum(_pixel[i]);
7292 #if POSTGIS_PGSQL_VERSION < 120
7293 ufc_info.argnull[i] =
FALSE;
7295 ufc_info->args[i].isnull =
FALSE;
7300 #if POSTGIS_PGSQL_VERSION < 120
7301 ufc_info.argnull[i] =
TRUE;
7303 ufc_info->args[i].isnull =
TRUE;
7311 if (ufl_info.fn_strict && ufc_nullcount)
7315 if (ufl_info.fn_nargs == 4) {
7318 for (i = 0; i < set_count; i++) {
7320 d[0] = Int32GetDatum(_pos[i][0]);
7321 d[1] = Int32GetDatum(_pos[i][1]);
7324 d[2] = Int32GetDatum(_pos[i][0]);
7325 d[3] = Int32GetDatum(_pos[i][1]);
7329 a = construct_array(d, 4, INT4OID,
sizeof(
int32),
true,
'i');
7330 #if POSTGIS_PGSQL_VERSION < 120
7331 ufc_info.arg[2] = PointerGetDatum(a);
7332 ufc_info.argnull[2] =
FALSE;
7334 ufc_info->args[2].value = PointerGetDatum(a);
7335 ufc_info->args[2].isnull =
FALSE;
7339 #if POSTGIS_PGSQL_VERSION < 120
7340 datum = FunctionCallInvoke(&ufc_info);
7343 if (!ufc_info.isnull) {
7345 pixel = DatumGetFloat8(datum);
7348 datum = FunctionCallInvoke(ufc_info);
7351 if (!ufc_info->isnull)
7354 pixel = DatumGetFloat8(datum);
7364 if (calltype == TEXTOID) {
7365 for (k = 0; k < spi_count; k++) SPI_freeplan(spi_plan[k]);
7369 for (k = 0; k < set_count; k++) {
7370 if (_rast[k] != NULL)
7372 if (pgrastpos[k] != -1)
7373 PG_FREE_IF_COPY(pgrast[k], pgrastpos[k]);
7377 elog(ERROR,
"RASTER_mapAlgebra2: Could not set pixel value of output raster");
7389 if (calltype == TEXTOID) {
7390 for (i = 0; i < spi_count; i++) {
7391 if (spi_plan[i] != NULL) SPI_freeplan(spi_plan[i]);
7396 for (k = 0; k < set_count; k++) {
7397 if (_rast[k] != NULL)
7399 if (pgrastpos[k] != -1)
7400 PG_FREE_IF_COPY(pgrast[k], pgrastpos[k]);
7405 if (!pgrtn) PG_RETURN_NULL();
7409 SET_VARSIZE(pgrtn, pgrtn->
size);
7410 PG_RETURN_POINTER(pgrtn);
int32_t gserialized_get_srid(const GSERIALIZED *g)
Extract the SRID from the serialized form (it is packed into three bytes so this is a handy function)...
LWGEOM * lwgeom_from_gserialized(const GSERIALIZED *g)
Allocate a new LWGEOM from a GSERIALIZED.
int lwgeom_ndims(const LWGEOM *geom)
Return the number of dimensions (2, 3, 4) in a geometry.
void lwgeom_free(LWGEOM *geom)
LWGEOM * lwgeom_intersection(const LWGEOM *geom1, const LWGEOM *geom2)
#define LWSIZE_GET(varsize)
Macro for reading the size from the GSERIALIZED size attribute.
#define SRID_UNKNOWN
Unknown SRID value.
lwvarlena_t * lwgeom_to_wkb_varlena(const LWGEOM *geom, uint8_t variant)
int32_t clamp_srid(int32_t srid)
Return a valid SRID from an arbitrary integer Raises a notice if what comes out is different from wha...
LWGEOM * lwgeom_force_2d(const LWGEOM *geom)
Strip out the Z/M components of an LWGEOM.
rt_band rt_band_reclass(rt_band srcband, rt_pixtype pixtype, uint32_t hasnodata, double nodataval, rt_reclassexpr *exprset, int exprcount)
Returns new band with values reclassified.
#define RASTER_DEBUG(level, msg)
int32_t rt_raster_get_srid(rt_raster raster)
Get raster's SRID.
double rt_raster_get_x_skew(rt_raster raster)
Get skew about the X axis.
double rt_raster_get_x_offset(rt_raster raster)
Get raster x offset, in projection units.
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.
void rt_raster_set_geotransform_matrix(rt_raster raster, double *gt)
Set raster's geotransform using 6-element array.
rt_raster rt_raster_colormap(rt_raster raster, int nband, rt_colormap colormap)
Returns a new raster with up to four 8BUI bands (RGBA) from applying a colormap to the user-specified...
void rt_raster_set_scale(rt_raster raster, double scaleX, double scaleY)
Set scale in projection units.
int rt_raster_add_band(rt_raster raster, rt_band band, int index)
Add band data to a raster.
int rt_band_get_hasnodata_flag(rt_band band)
Get hasnodata flag value.
rt_pixtype rt_pixtype_index_from_name(const char *pixname)
rt_errorstate rt_band_get_pixel(rt_band band, int x, int y, double *value, int *nodata)
Get pixel value.
void rt_raster_destroy(rt_raster raster)
Release memory associated to a raster.
void rt_raster_set_skews(rt_raster raster, double skewX, double skewY)
Set skews about the X and Y axis.
int rt_band_get_isnodata_flag(rt_band band)
Get isnodata flag value.
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)
double rt_pixtype_get_min_value(rt_pixtype pixtype)
Return minimum value possible for pixel type.
int rt_raster_has_band(rt_raster raster, int nband)
Return TRUE if the raster has a band of this number.
void * rt_raster_serialize(rt_raster raster)
Return this raster in serialized form.
double rt_raster_get_x_scale(rt_raster raster)
Get scale X in projection units.
rt_band rt_raster_replace_band(rt_raster raster, rt_band band, int index)
Replace band at provided index with new band.
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_band_set_pixel(rt_band band, int x, int y, double val, int *converted)
Set single pixel's value.
rt_errorstate rt_band_set_pixel_line(rt_band band, int x, int y, void *vals, uint32_t len)
Set values of multiple pixels.
rt_raster rt_raster_gdal_rasterize(const unsigned char *wkb, uint32_t wkb_len, const char *srs, uint32_t num_bands, rt_pixtype *pixtype, double *init, double *value, double *nodata, uint8_t *hasnodata, int *width, int *height, double *scale_x, double *scale_y, double *ul_xw, double *ul_yw, double *grid_xw, double *grid_yw, double *skew_x, double *skew_y, char **options)
Return a raster of the provided geometry.
void rt_band_destroy(rt_band band)
Destroy a raster band.
uint16_t rt_raster_get_num_bands(rt_raster raster)
rt_raster rt_raster_clone(rt_raster raster, uint8_t deep)
Clone an existing raster.
rt_errorstate rt_raster_get_convex_hull(rt_raster raster, LWGEOM **hull)
Get raster's convex hull.
uint16_t rt_raster_get_height(rt_raster raster)
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.
void rt_raster_set_srid(rt_raster raster, int32_t srid)
Set raster's SRID.
rt_raster rt_raster_from_band(rt_raster raster, uint32_t *bandNums, int count)
Construct a new rt_raster from an existing rt_raster and an array of band numbers.
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.
const char * rt_pixtype_name(rt_pixtype pixtype)
uint16_t rt_raster_get_width(rt_raster raster)
rt_errorstate rt_raster_from_two_rasters(rt_raster rast1, rt_raster rast2, rt_extenttype extenttype, rt_raster *rtnraster, double *offset)
int rt_util_same_geotransform_matrix(double *gt1, double *gt2)
int rt_raster_copy_band(rt_raster torast, rt_raster fromrast, int fromindex, int toindex)
Copy one band from one raster to another.
double rt_raster_get_y_scale(rt_raster raster)
Get scale Y in projection units.
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.
void rt_raster_get_geotransform_matrix(rt_raster raster, double *gt)
Get 6-element array of raster geotransform matrix.
void rt_raster_set_offsets(rt_raster raster, double x, double y)
Set insertion points in projection units.
rt_bandstats rt_band_get_summary_stats(rt_band band, int exclude_nodata_value, double sample, int inc_vals, uint64_t *cK, double *cM, double *cQ)
Compute summary statistics for a band.
rt_raster rt_raster_deserialize(void *serialized, int header_only)
Return a raster from a serialized form.
rt_errorstate rt_band_get_pixel_line(rt_band band, int x, int y, uint16_t len, void **vals, uint16_t *nvals)
Get values of multiple pixels.
double rt_raster_get_y_offset(rt_raster raster)
Get raster y offset, in projection units.
int rt_raster_is_empty(rt_raster raster)
Return TRUE if the raster is empty.
rt_band rt_raster_get_band(rt_raster raster, int bandNum)
Return Nth band, or NULL if unavailable.
static int lwgeom_is_empty(const LWGEOM *geom)
Return true or false depending on whether a geometry is an "empty" geometry (no vertices members)
raster
Be careful!! Zeros function's input parameter can be a (height x width) array, not (width x height): ...
char * rtpg_removespaces(char *str)
char * rtpg_strtoupper(char *str)
char * rtpg_chartrim(const char *input, char *remove)
char * rtpg_strrstr(const char *s1, const char *s2)
char * rtpg_trim(const char *input)
char ** rtpg_strsplit(const char *str, const char *delimiter, uint32_t *n)
char * rtpg_strreplace(const char *str, const char *oldstr, const char *newstr, int *count)
Datum RASTER_nMapAlgebra(PG_FUNCTION_ARGS)
struct rtpg_colormap_arg_t * rtpg_colormap_arg
static rtpg_nmapalgebra_arg rtpg_nmapalgebra_arg_init()
static int rtpg_union_mean_callback(rt_iterator_arg arg, void *userarg, double *value, int *nodata)
Datum RASTER_mapAlgebraFct(PG_FUNCTION_ARGS)
static void rtpg_nmapalgebra_arg_destroy(rtpg_nmapalgebra_arg arg)
static void rtpg_nmapalgebraexpr_arg_destroy(rtpg_nmapalgebraexpr_arg arg)
static rtpg_nmapalgebraexpr_arg rtpg_nmapalgebraexpr_arg_init(int cnt, char **kw)
struct rtpg_clip_arg_t * rtpg_clip_arg
static void rtpg_colormap_arg_destroy(rtpg_colormap_arg arg)
Datum RASTER_colorMap(PG_FUNCTION_ARGS)
static rtpg_union_type rtpg_uniontype_index_from_name(const char *cutype)
struct rtpg_clip_band_t * rtpg_clip_band
static int rtpg_union_range_callback(rt_iterator_arg arg, void *userarg, double *value, int *nodata)
PG_FUNCTION_INFO_V1(RASTER_nMapAlgebra)
static int rtpg_nmapalgebra_rastbandarg_process(rtpg_nmapalgebra_arg arg, ArrayType *array, int *allnull, int *allempty, int *noband)
Datum RASTER_mapAlgebra2(PG_FUNCTION_ARGS)
static int rtpg_nmapalgebraexpr_callback(rt_iterator_arg arg, void *userarg, double *value, int *nodata)
static void rtpg_union_arg_destroy(rtpg_union_arg arg)
struct rtpg_union_arg_t * rtpg_union_arg
Datum RASTER_mapAlgebraExpr(PG_FUNCTION_ARGS)
static int rtpg_union_unionarg_process(rtpg_union_arg arg, ArrayType *array)
struct rtpg_nmapalgebra_arg_t * rtpg_nmapalgebra_arg
static rtpg_clip_arg rtpg_clip_arg_init()
Datum RASTER_mapAlgebraFctNgb(PG_FUNCTION_ARGS)
static int rtpg_union_callback(rt_iterator_arg arg, void *userarg, double *value, int *nodata)
static int rtpg_nmapalgebra_callback(rt_iterator_arg arg, void *userarg, double *value, int *nodata)
Datum RASTER_union_transfn(PG_FUNCTION_ARGS)
Datum RASTER_reclass(PG_FUNCTION_ARGS)
Datum RASTER_nMapAlgebraExpr(PG_FUNCTION_ARGS)
static void rtpg_clip_arg_destroy(rtpg_clip_arg arg)
static int rtpg_clip_callback(rt_iterator_arg arg, void *userarg, double *value, int *nodata)
struct rtpg_union_band_arg_t * rtpg_union_band_arg
struct rtpg_nmapalgebraexpr_arg_t * rtpg_nmapalgebraexpr_arg
static rtpg_colormap_arg rtpg_colormap_arg_init()
Datum RASTER_union_finalfn(PG_FUNCTION_ARGS)
Datum RASTER_clip(PG_FUNCTION_ARGS)
static int rtpg_union_noarg(rtpg_union_arg arg, rt_raster raster)
#define POSTGIS_RT_DEBUG(level, msg)
#define POSTGIS_RT_DEBUGF(level, msg,...)
enum rt_colormap_t::@10 method
struct rt_reclassexpr_t::rt_reclassrange src
struct rt_reclassexpr_t::rt_reclassrange dst
rtpg_nmapalgebra_callback_arg callback
FunctionCallInfoData ufc_info
rtpg_nmapalgebraexpr_callback_arg callback
rtpg_nmapalgebra_arg bandarg
struct rtpg_nmapalgebraexpr_callback_arg::@21 kw
struct rtpg_nmapalgebraexpr_callback_arg::@19 expr[3]
struct rtpg_nmapalgebraexpr_callback_arg::@20 nodatanodata
rtpg_union_band_arg bandarg
rtpg_union_type uniontype