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
90 FunctionCallInfoData ufc_info;
95 char fcinfo_data[SizeForFunctionCallInfo(FUNC_MAX_ARGS)];
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;
1223 if (arg->
rasters == 1 && i > 7) {
1224 elog(ERROR,
"rtpg_nmapalgebraexpr_callback: rast2 argument specified in single-raster invocation");
1231 values[idx] = Int32GetDatum(arg->
src_pixel[0][0] + 1);
1235 values[idx] = Int32GetDatum(arg->
src_pixel[0][1] + 1);
1241 if (!arg->
nodata[0][0][0])
1242 values[idx] = Float8GetDatum(arg->
values[0][0][0]);
1249 values[idx] = Int32GetDatum(arg->
src_pixel[0][0] + 1);
1253 values[idx] = Int32GetDatum(arg->
src_pixel[0][1] + 1);
1259 if (!arg->
nodata[0][0][0])
1260 values[idx] = Float8GetDatum(arg->
values[0][0][0]);
1267 values[idx] = Int32GetDatum(arg->
src_pixel[1][0] + 1);
1271 values[idx] = Int32GetDatum(arg->
src_pixel[1][1] + 1);
1277 if (!arg->
nodata[1][0][0])
1278 values[idx] = Float8GetDatum(arg->
values[1][0][0]);
1288 err = SPI_execute_plan(plan, values, nulls,
TRUE, 1);
1289 if (err != SPI_OK_SELECT || SPI_tuptable == NULL || SPI_processed != 1) {
1290 elog(ERROR,
"rtpg_nmapalgebraexpr_callback: Unexpected error when running prepared statement %d",
id);
1295 tupdesc = SPI_tuptable->tupdesc;
1296 tuptable = SPI_tuptable;
1297 tuple = tuptable->vals[0];
1299 datum = SPI_getbinval(tuple, tupdesc, 1, &isnull);
1300 if (SPI_result == SPI_ERROR_NOATTRIBUTE) {
1301 if (SPI_tuptable) SPI_freetuptable(tuptable);
1302 elog(ERROR,
"rtpg_nmapalgebraexpr_callback: Could not get result of prepared statement %d",
id);
1307 *
value = DatumGetFloat8(datum);
1327 if (SPI_tuptable) SPI_freetuptable(tuptable);
1337 MemoryContext mainMemCtx = CurrentMemoryContext;
1340 uint16_t exprpos[3] = {1, 4, 5};
1354 SPITupleTable *tuptable = NULL;
1357 bool isnull =
FALSE;
1363 const int argkwcount = 12;
1379 if (PG_ARGISNULL(0))
1385 elog(ERROR,
"RASTER_nMapAlgebraExpr: Could not initialize argument structure");
1392 elog(ERROR,
"RASTER_nMapAlgebra: Could not process rastbandarg");
1396 POSTGIS_RT_DEBUGF(4,
"allnull, allempty, noband = %d, %d, %d", allnull, allempty, noband);
1400 elog(NOTICE,
"All input rasters are NULL. Returning NULL");
1412 if (!PG_ARGISNULL(2)) {
1413 char *pixtypename = text_to_cstring(PG_GETARG_TEXT_P(2));
1419 elog(ERROR,
"RASTER_nMapAlgebraExpr: Invalid pixel type: %s", pixtypename);
1426 if (!PG_ARGISNULL(3)) {
1432 if (numraster < 2) {
1433 elog(NOTICE,
"CUSTOM extent type not supported. Defaulting to FIRST");
1437 elog(NOTICE,
"CUSTOM extent type not supported. Defaulting to INTERSECTION");
1441 else if (numraster < 2)
1447 if (!PG_ARGISNULL(6)) {
1455 elog(NOTICE,
"All input rasters are empty. Returning empty raster");
1460 elog(NOTICE,
"All input rasters do not have bands at indicated indexes. Returning empty raster");
1468 elog(ERROR,
"RASTER_nMapAlgebraExpr: Could not create empty raster");
1474 if (!pgraster) PG_RETURN_NULL();
1476 SET_VARSIZE(pgraster, pgraster->
size);
1477 PG_RETURN_POINTER(pgraster);
1481 if (SPI_connect() != SPI_OK_CONNECT) {
1483 elog(ERROR,
"RASTER_nMapAlgebraExpr: Could not connect to the SPI manager");
1499 char place[12] =
"$1";
1501 if (PG_ARGISNULL(exprpos[i]))
1504 expr = text_to_cstring(PG_GETARG_TEXT_P(exprpos[i]));
1507 for (j = 0, k = 1; j < argkwcount; j++) {
1519 sprintf(place,
"$%d", k);
1525 len = strlen(
"SELECT (") + strlen(expr) + strlen(
")::double precision");
1526 sql = (
char *) palloc(len + 1);
1530 elog(ERROR,
"RASTER_nMapAlgebraExpr: Could not allocate memory for expression parameter %d", exprpos[i]);
1534 memcpy(
sql,
"SELECT (", strlen(
"SELECT ("));
1535 memcpy(
sql + strlen(
"SELECT ("), expr, strlen(expr));
1536 memcpy(
sql + strlen(
"SELECT (") + strlen(expr),
")::double precision", strlen(
")::double precision"));
1545 if (argtype == NULL) {
1549 elog(ERROR,
"RASTER_nMapAlgebraExpr: Could not allocate memory for prepared plan argtypes of expression parameter %d", exprpos[i]);
1554 for (j = 0, k = 0; j < argkwcount; j++) {
1559 (strstr(argkw[j],
"[rast.x]") != NULL) ||
1560 (strstr(argkw[j],
"[rast.y]") != NULL) ||
1561 (strstr(argkw[j],
"[rast1.x]") != NULL) ||
1562 (strstr(argkw[j],
"[rast1.y]") != NULL) ||
1563 (strstr(argkw[j],
"[rast2.x]") != NULL) ||
1564 (strstr(argkw[j],
"[rast2.y]") != NULL)
1566 argtype[k] = INT4OID;
1569 argtype[k] = FLOAT8OID;
1581 elog(ERROR,
"RASTER_nMapAlgebraExpr: Could not create prepared plan of expression parameter %d", exprpos[i]);
1587 POSTGIS_RT_DEBUGF(3,
"expression parameter %d has no args, simply executing", exprpos[i]);
1588 err = SPI_execute(
sql,
TRUE, 0);
1591 if (err != SPI_OK_SELECT || SPI_tuptable == NULL || SPI_processed != 1) {
1594 elog(ERROR,
"RASTER_nMapAlgebraExpr: Could not evaluate expression parameter %d", exprpos[i]);
1599 tupdesc = SPI_tuptable->tupdesc;
1600 tuptable = SPI_tuptable;
1601 tuple = tuptable->vals[0];
1603 datum = SPI_getbinval(tuple, tupdesc, 1, &isnull);
1604 if (SPI_result == SPI_ERROR_NOATTRIBUTE) {
1605 if (SPI_tuptable) SPI_freetuptable(tuptable);
1608 elog(ERROR,
"RASTER_nMapAlgebraExpr: Could not get result of expression parameter %d", exprpos[i]);
1617 if (SPI_tuptable) SPI_freetuptable(tuptable);
1637 for (i = 0; i < numraster; i++) {
1661 if (itrset == NULL) {
1664 elog(ERROR,
"RASTER_nMapAlgebra: Could not allocate memory for iterator arguments");
1669 for (i = 0; i < numraster; i++) {
1693 elog(ERROR,
"RASTER_nMapAlgebraExpr: Could not run raster iterator function");
1696 else if (
raster == NULL) {
1702 MemoryContextSwitchTo(mainMemCtx);
1713 SET_VARSIZE(pgraster, pgraster->
size);
1714 PG_RETURN_POINTER(pgraster);
1734 assert(cutype && strlen(cutype) > 0);
1736 if (strcmp(cutype,
"LAST") == 0)
1738 else if (strcmp(cutype,
"FIRST") == 0)
1740 else if (strcmp(cutype,
"MIN") == 0)
1742 else if (strcmp(cutype,
"MAX") == 0)
1744 else if (strcmp(cutype,
"COUNT") == 0)
1746 else if (strcmp(cutype,
"SUM") == 0)
1748 else if (strcmp(cutype,
"MEAN") == 0)
1750 else if (strcmp(cutype,
"RANGE") == 0)
1777 for (i = 0; i < arg->
numband; i++) {
1801 double *
value,
int *nodata
1813 elog(ERROR,
"rtpg_union_callback: Invalid arguments passed to callback");
1829 else if (!arg->
nodata[0][0][0] && arg->
nodata[1][0][0]) {
1835 else if (arg->
nodata[0][0][0] && !arg->
nodata[1][0][0]) {
1863 else if (!arg->
nodata[0][0][0] && arg->
nodata[1][0][0])
1866 else if (arg->
nodata[0][0][0] && !arg->
nodata[1][0][0])
1892 double *
value,
int *nodata
1902 elog(ERROR,
"rtpg_union_mean_callback: Invalid arguments passed to callback");
1925 double *
value,
int *nodata
1935 elog(ERROR,
"rtpg_union_range_callback: Invalid arguments passed to callback");
1968 HeapTupleHeader tup;
1974 char *utypename = NULL;
1977 etype = ARR_ELEMTYPE(array);
1978 get_typlenbyvalalign(etype, &typlen, &typbyval, &typalign);
1983 typlen, typbyval, typalign,
1988 elog(ERROR,
"rtpg_union_unionarg_process: Invalid argument for unionarg");
1996 elog(ERROR,
"rtpg_union_unionarg_process: Could not allocate memory for band information");
2001 for (i = 0; i < n; i++) {
2010 tup = (HeapTupleHeader) DatumGetPointer(e[i]);
2012 elog(ERROR,
"rtpg_union_unionarg_process: Invalid argument for unionarg");
2017 tupv = GetAttributeByName(tup,
"nband", &isnull);
2020 elog(NOTICE,
"First argument (nband) of unionarg is NULL. Assuming nband = %d",
nband);
2023 nband = DatumGetInt32(tupv);
2026 elog(ERROR,
"rtpg_union_unionarg_process: Band number must be greater than zero (1-based)");
2031 tupv = GetAttributeByName(tup,
"uniontype", &isnull);
2033 elog(NOTICE,
"Second argument (uniontype) of unionarg is NULL. Assuming uniontype = LAST");
2037 utypename = text_to_cstring((text *) DatumGetPointer(tupv));
2058 elog(ERROR,
"rtpg_union_unionarg_process: Could not reallocate memory for band information");
2075 if (numbands <= arg->numband)
2085 elog(ERROR,
"rtpg_union_noarg: Could not reallocate memory for band information");
2091 for (; i < arg->
numband; i++) {
2099 elog(ERROR,
"rtpg_union_noarg: Could not allocate memory for working rasters");
2108 elog(ERROR,
"rtpg_union_noarg: Could not create working raster");
2121 MemoryContext aggcontext;
2122 MemoryContext oldcontext;
2132 int isempty[2] = {0};
2133 int hasband[2] = {0};
2135 double _offset[4] = {0.};
2143 char *utypename = NULL;
2147 double nodataval = 0;
2153 uint16_t _dim[2] = {0};
2160 if (!AggCheckCallContext(fcinfo, &aggcontext)) {
2161 elog(ERROR,
"RASTER_union_transfn: Cannot be called in a non-aggregate context");
2166 oldcontext = MemoryContextSwitchTo(aggcontext);
2168 if (PG_ARGISNULL(0)) {
2173 MemoryContextSwitchTo(oldcontext);
2174 elog(ERROR,
"RASTER_union_transfn: Could not allocate memory for state variable");
2190 if (!PG_ARGISNULL(1)) {
2192 pgraster = (
rt_pgraster *) PG_DETOAST_DATUM(PG_GETARG_DATUM(1));
2199 PG_FREE_IF_COPY(pgraster, 1);
2201 MemoryContextSwitchTo(oldcontext);
2202 elog(ERROR,
"RASTER_union_transfn: Could not deserialize raster");
2215 if (!PG_ARGISNULL(2)) {
2216 Oid calltype = get_fn_expr_argtype(fcinfo->flinfo, 2);
2227 utypename = text_to_cstring(PG_GETARG_TEXT_P(2));
2251 if (numband > idx) {
2269 PG_FREE_IF_COPY(pgraster, 1);
2272 MemoryContextSwitchTo(oldcontext);
2273 elog(ERROR,
"RASTER_union_transfn: Could not allocate memory for band information");
2278 for (i = idx; i < iwr->
numband; i++) {
2302 nband = PG_GETARG_INT32(2);
2308 PG_FREE_IF_COPY(pgraster, 1);
2311 MemoryContextSwitchTo(oldcontext);
2312 elog(ERROR,
"RASTER_union_transfn: Band number must be greater than zero (1-based)");
2323 PG_FREE_IF_COPY(pgraster, 1);
2326 MemoryContextSwitchTo(oldcontext);
2327 elog(ERROR,
"RASTER_union_transfn: Could not allocate memory for band information");
2348 PG_FREE_IF_COPY(pgraster, 1);
2351 MemoryContextSwitchTo(oldcontext);
2352 elog(ERROR,
"RASTER_union_transfn: Could not process unionarg");
2361 if (nargs > 3 && !PG_ARGISNULL(3)) {
2362 utypename = text_to_cstring(PG_GETARG_TEXT_P(3));
2376 for (i = 0; i < iwr->
numband; i++) {
2391 PG_FREE_IF_COPY(pgraster, 1);
2394 MemoryContextSwitchTo(oldcontext);
2395 elog(ERROR,
"RASTER_union_transfn: Could not allocate memory for working raster(s)");
2410 PG_FREE_IF_COPY(pgraster, 1);
2413 MemoryContextSwitchTo(oldcontext);
2414 elog(ERROR,
"RASTER_union_transfn: Could not create working raster");
2431 PG_FREE_IF_COPY(pgraster, 1);
2434 MemoryContextSwitchTo(oldcontext);
2435 elog(ERROR,
"RASTER_union_transfn: Could not check and balance number of bands");
2442 if (itrset == NULL) {
2447 PG_FREE_IF_COPY(pgraster, 1);
2450 MemoryContextSwitchTo(oldcontext);
2451 elog(ERROR,
"RASTER_union_transfn: Could not allocate memory for iterator arguments");
2456 for (i = 0; i < iwr->
numband; i++) {
2476 if (!isempty[0] && hasband[0])
2478 else if (!isempty[1] && hasband[1])
2485 if (_band != NULL) {
2523 itrset[0].
nband = 0;
2539 if (!isempty[0] && !isempty[1] && hasband[0] && hasband[1]) {
2553 PG_FREE_IF_COPY(pgraster, 1);
2556 MemoryContextSwitchTo(oldcontext);
2557 elog(ERROR,
"RASTER_union_transfn: Could not create internal raster");
2561 _offset[0], _offset[1], _offset[2], _offset[3]);
2568 double igt[6] = {0};
2584 hasnodata, nodataval,
2593 PG_FREE_IF_COPY(pgraster, 1);
2596 MemoryContextSwitchTo(oldcontext);
2597 elog(ERROR,
"RASTER_union_transfn: Could not add new band to internal raster");
2605 for (
y = 0;
y < _dim[1];
y++) {
2606 POSTGIS_RT_DEBUGF(4,
"Getting pixel line of working raster at (x, y, length) = (0, %d, %d)",
y, _dim[0]);
2620 PG_FREE_IF_COPY(pgraster, 1);
2623 MemoryContextSwitchTo(oldcontext);
2624 elog(ERROR,
"RASTER_union_transfn: Could not get pixel line from band of working raster");
2628 POSTGIS_RT_DEBUGF(4,
"Setting pixel line at (x, y, length) = (%d, %d, %d)", (
int) _offset[0], (
int) _offset[1] +
y, nvals);
2631 (
int) _offset[0], (
int) _offset[1] +
y,
2641 PG_FREE_IF_COPY(pgraster, 1);
2644 MemoryContextSwitchTo(oldcontext);
2645 elog(ERROR,
"RASTER_union_transfn: Could not set pixel line to band of internal raster");
2661 hasnodata, nodataval,
2678 PG_FREE_IF_COPY(pgraster, 1);
2681 MemoryContextSwitchTo(oldcontext);
2682 elog(ERROR,
"RASTER_union_transfn: Could not run raster iterator function");
2690 for (
y = 0;
y < _dim[1];
y++) {
2691 POSTGIS_RT_DEBUGF(4,
"Getting pixel line of iterator raster at (x, y, length) = (0, %d, %d)",
y, _dim[0]);
2707 PG_FREE_IF_COPY(pgraster, 1);
2710 MemoryContextSwitchTo(oldcontext);
2711 elog(ERROR,
"RASTER_union_transfn: Could not get pixel line from band of working raster");
2715 POSTGIS_RT_DEBUGF(4,
"Setting pixel line at (x, y, length) = (%d, %d, %d)", (
int) _offset[2], (
int) _offset[3] +
y, nvals);
2718 (
int) _offset[2], (
int) _offset[3] +
y,
2730 PG_FREE_IF_COPY(pgraster, 1);
2733 MemoryContextSwitchTo(oldcontext);
2734 elog(ERROR,
"RASTER_union_transfn: Could not set pixel line to band of internal raster");
2754 hasnodata, nodataval,
2768 PG_FREE_IF_COPY(pgraster, 1);
2771 MemoryContextSwitchTo(oldcontext);
2772 elog(ERROR,
"RASTER_union_transfn: Could not run raster iterator function");
2791 PG_FREE_IF_COPY(pgraster, 1);
2795 MemoryContextSwitchTo(oldcontext);
2799 PG_RETURN_POINTER(iwr);
2819 double nodataval = 0;
2824 if (!AggCheckCallContext(fcinfo, NULL)) {
2825 elog(ERROR,
"RASTER_union_finalfn: Cannot be called in a non-aggregate context");
2830 if (PG_ARGISNULL(0))
2837 if (itrset == NULL) {
2839 elog(ERROR,
"RASTER_union_finalfn: Could not allocate memory for iterator arguments");
2843 for (i = 0; i < iwr->
numband; i++) {
2858 itrset[0].
nband = 0;
2860 itrset[1].
nband = 0;
2868 hasnodata, nodataval,
2881 hasnodata, nodataval,
2895 elog(ERROR,
"RASTER_union_finalfn: Could not run raster iterator function");
2901 if (_raster == NULL)
2907 uint32_t bandNums[1] = {0};
2909 status = (_rtn == NULL) ? -1 : 0;
2934 elog(ERROR,
"RASTER_union_finalfn: Could not add band to final raster");
2947 if (!_rtn) PG_RETURN_NULL();
2957 SET_VARSIZE(pgraster, pgraster->
size);
2958 PG_RETURN_POINTER(pgraster);
2987 elog(ERROR,
"rtpg_clip_arg_init: Could not allocate memory for function arguments");
3001 if (arg->
band != NULL)
3006 if (arg->
mask != NULL)
3046 double offset[4] = {0.};
3056 int mask_height = 0;
3066 if (PG_ARGISNULL(0) || PG_ARGISNULL(2))
3072 elog(ERROR,
"RASTER_clip: Could not initialize argument structure");
3077 pgraster = (
rt_pgraster *) PG_DETOAST_DATUM(PG_GETARG_DATUM(0));
3081 if (arg->
raster == NULL) {
3083 PG_FREE_IF_COPY(pgraster, 0);
3084 elog(ERROR,
"RASTER_clip: Could not deserialize raster");
3090 elog(NOTICE,
"Input raster is empty or has no bands. Returning empty raster");
3093 PG_FREE_IF_COPY(pgraster, 0);
3097 elog(ERROR,
"RASTER_clip: Could not create empty raster");
3106 SET_VARSIZE(pgrtn, pgrtn->
size);
3107 PG_RETURN_POINTER(pgrtn);
3115 gser = PG_GETARG_GSERIALIZED_P(2);
3127 elog(NOTICE,
"Geometry provided does not have the same SRID as the raster. Returning NULL");
3130 PG_FREE_IF_COPY(pgraster, 0);
3132 PG_FREE_IF_COPY(gser, 2);
3138 if (!PG_ARGISNULL(4) && !PG_GETARG_BOOL(4))
3145 PG_FREE_IF_COPY(pgraster, 0);
3147 PG_FREE_IF_COPY(gser, 2);
3149 elog(ERROR,
"RASTER_clip: Could not get convex hull of raster");
3156 PG_FREE_IF_COPY(gser, 2);
3161 elog(NOTICE,
"The input raster and input geometry do not intersect. Returning empty raster");
3164 PG_FREE_IF_COPY(pgraster, 0);
3169 elog(ERROR,
"RASTER_clip: Could not create empty raster");
3178 SET_VARSIZE(pgrtn, pgrtn->
size);
3179 PG_RETURN_POINTER(pgrtn);
3183 if (!PG_ARGISNULL(1)) {
3184 array = PG_GETARG_ARRAYTYPE_P(1);
3185 etype = ARR_ELEMTYPE(array);
3186 get_typlenbyvalalign(etype, &typlen, &typbyval, &typalign);
3194 PG_FREE_IF_COPY(pgraster, 0);
3196 elog(ERROR,
"RASTER_clip: Invalid data type for band indexes");
3203 typlen, typbyval, typalign,
3208 if (arg->
band == NULL) {
3210 PG_FREE_IF_COPY(pgraster, 0);
3212 elog(ERROR,
"RASTER_clip: Could not allocate memory for band arguments");
3216 for (i = 0, j = 0; i < arg->
numbands; i++) {
3217 if (nulls[i])
continue;
3221 arg->
band[j].
nband = DatumGetInt16(e[i]) - 1;
3224 arg->
band[j].
nband = DatumGetInt32(e[i]) - 1;
3231 if (j < arg->numbands) {
3233 if (arg->
band == NULL) {
3235 PG_FREE_IF_COPY(pgraster, 0);
3237 elog(ERROR,
"RASTER_clip: Could not reallocate memory for band arguments");
3245 for (i = 0; i < arg->
numbands; i++) {
3247 elog(NOTICE,
"Band at index %d not found in raster", arg->
band[i].
nband + 1);
3249 PG_FREE_IF_COPY(pgraster, 0);
3264 if (arg->
band == NULL) {
3267 PG_FREE_IF_COPY(pgraster, 0);
3270 elog(ERROR,
"RASTER_clip: Could not allocate memory for band arguments");
3274 for (i = 0; i < arg->
numbands; i++) {
3283 if (!PG_ARGISNULL(3)) {
3284 array = PG_GETARG_ARRAYTYPE_P(3);
3285 etype = ARR_ELEMTYPE(array);
3286 get_typlenbyvalalign(etype, &typlen, &typbyval, &typalign);
3294 PG_FREE_IF_COPY(pgraster, 0);
3296 elog(ERROR,
"RASTER_clip: Invalid data type for NODATA values");
3303 typlen, typbyval, typalign,
3308 for (i = 0, j = 0; i < arg->
numbands; i++, j++) {
3356 if (arg->
mask == NULL) {
3358 PG_FREE_IF_COPY(pgraster, 0);
3359 elog(ERROR,
"RASTER_clip: Could not rasterize intersection geometry");
3371 PG_FREE_IF_COPY(pgraster, 0);
3372 elog(ERROR,
"RASTER_clip: Could not compute extent of rasters");
3381 for (i = 0; i < arg->
numbands; i++) {
3402 PG_FREE_IF_COPY(pgraster, 0);
3403 elog(ERROR,
"RASTER_clip: Could not add new band in output raster");
3417 for (
y = 0;
y < height;
y++) {
3418 for (
x = 0;
x < width;
x++) {
3419 mask_x =
x - (int)offset[2];
3420 mask_y =
y - (int)offset[3];
3424 mask_x < mask_width &&
3426 mask_y < mask_height
3433 PG_FREE_IF_COPY(pgraster, 0);
3434 elog(ERROR,
"RASTER_clip: Could not get pixel value");
3442 input_x =
x - (int)offset[0];
3443 input_y =
y - (int)offset[1];
3447 PG_FREE_IF_COPY(pgraster, 0);
3448 elog(ERROR,
"RASTER_clip: Could not get pixel value");
3458 PG_FREE_IF_COPY(pgraster, 0);
3459 elog(ERROR,
"RASTER_clip: Could not set pixel value");
3467 PG_FREE_IF_COPY(pgraster, 0);
3477 SET_VARSIZE(pgrtn, pgrtn->
size);
3478 PG_RETURN_POINTER(pgrtn);
3491 uint32_t numBands = 0;
3511 HeapTupleHeader tup;
3516 text *exprtext = NULL;
3521 char *pixeltype = NULL;
3522 text *pixeltypetext = NULL;
3524 double nodataval = 0;
3525 bool hasnodata =
FALSE;
3527 char **comma_set = NULL;
3528 uint32_t comma_n = 0;
3529 char **colon_set = NULL;
3530 uint32_t colon_n = 0;
3531 char **dash_set = NULL;
3532 uint32_t dash_n = 0;
3537 if (PG_ARGISNULL(0))
3539 pgraster = (
rt_pgraster *) PG_DETOAST_DATUM(PG_GETARG_DATUM(0));
3544 PG_FREE_IF_COPY(pgraster, 0);
3545 elog(ERROR,
"RASTER_reclass: Could not deserialize raster");
3549 POSTGIS_RT_DEBUGF(3,
"RASTER_reclass: %d possible bands to be reclassified", numBands);
3553 array = PG_GETARG_ARRAYTYPE_P(1);
3554 etype = ARR_ELEMTYPE(array);
3555 get_typlenbyvalalign(etype, &typlen, &typbyval, &typalign);
3557 deconstruct_array(array, etype, typlen, typbyval, typalign, &e,
3561 elog(NOTICE,
"Invalid argument for reclassargset. Returning original raster");
3565 PG_FREE_IF_COPY(pgraster, 0);
3569 SET_VARSIZE(pgrtn, pgrtn->
size);
3570 PG_RETURN_POINTER(pgrtn);
3578 for (i = 0; i < n; i++) {
3579 if (nulls[i])
continue;
3582 tup = (HeapTupleHeader) DatumGetPointer(e[i]);
3584 elog(NOTICE,
"Invalid argument for reclassargset. Returning original raster");
3588 PG_FREE_IF_COPY(pgraster, 0);
3592 SET_VARSIZE(pgrtn, pgrtn->
size);
3593 PG_RETURN_POINTER(pgrtn);
3597 tupv = GetAttributeByName(tup,
"nband", &isnull);
3599 elog(NOTICE,
"Invalid argument for reclassargset. Missing value of nband for reclassarg of index %d . Returning original raster", i);
3603 PG_FREE_IF_COPY(pgraster, 0);
3607 SET_VARSIZE(pgrtn, pgrtn->
size);
3608 PG_RETURN_POINTER(pgrtn);
3610 nband = DatumGetInt32(tupv);
3614 if (nband < 1 || nband > numBands) {
3615 elog(NOTICE,
"Invalid argument for reclassargset. Invalid band index (must use 1-based) for reclassarg of index %d . Returning original raster", i);
3619 PG_FREE_IF_COPY(pgraster, 0);
3623 SET_VARSIZE(pgrtn, pgrtn->
size);
3624 PG_RETURN_POINTER(pgrtn);
3628 tupv = GetAttributeByName(tup,
"reclassexpr", &isnull);
3630 elog(NOTICE,
"Invalid argument for reclassargset. Missing value of reclassexpr for reclassarg of index %d . Returning original raster", i);
3634 PG_FREE_IF_COPY(pgraster, 0);
3638 SET_VARSIZE(pgrtn, pgrtn->
size);
3639 PG_RETURN_POINTER(pgrtn);
3641 exprtext = (text *) DatumGetPointer(tupv);
3642 if (NULL == exprtext) {
3643 elog(NOTICE,
"Invalid argument for reclassargset. Missing value of reclassexpr for reclassarg of index %d . Returning original raster", i);
3647 PG_FREE_IF_COPY(pgraster, 0);
3651 SET_VARSIZE(pgrtn, pgrtn->
size);
3652 PG_RETURN_POINTER(pgrtn);
3654 expr = text_to_cstring(exprtext);
3663 elog(NOTICE,
"Invalid argument for reclassargset. Invalid expression of reclassexpr for reclassarg of index %d . Returning original raster", i);
3667 PG_FREE_IF_COPY(pgraster, 0);
3671 SET_VARSIZE(pgrtn, pgrtn->
size);
3672 PG_RETURN_POINTER(pgrtn);
3679 for (a = 0, j = 0; a < comma_n; a++) {
3685 elog(NOTICE,
"Invalid argument for reclassargset. Invalid expression of reclassexpr for reclassarg of index %d . Returning original raster", i);
3686 for (k = 0; k < j; k++) pfree(exprset[k]);
3691 PG_FREE_IF_COPY(pgraster, 0);
3695 SET_VARSIZE(pgrtn, pgrtn->
size);
3696 PG_RETURN_POINTER(pgrtn);
3702 for (b = 0; b < colon_n; b++) {
3707 if (dash_n < 1 || dash_n > 3) {
3708 elog(NOTICE,
"Invalid argument for reclassargset. Invalid expression of reclassexpr for reclassarg of index %d . Returning original raster", i);
3709 for (k = 0; k < j; k++) pfree(exprset[k]);
3714 PG_FREE_IF_COPY(pgraster, 0);
3718 SET_VARSIZE(pgrtn, pgrtn->
size);
3719 PG_RETURN_POINTER(pgrtn);
3722 for (c = 0; c < dash_n; c++) {
3726 strlen(dash_set[c]) == 1 && (
3727 strchr(dash_set[c],
'(') != NULL ||
3728 strchr(dash_set[c],
'[') != NULL ||
3729 strchr(dash_set[c],
')') != NULL ||
3730 strchr(dash_set[c],
']') != NULL
3734 junk = palloc(
sizeof(
char) * (strlen(dash_set[c + 1]) + 2));
3736 for (k = 0; k <= j; k++) pfree(exprset[k]);
3739 PG_FREE_IF_COPY(pgraster, 0);
3741 elog(ERROR,
"RASTER_reclass: Could not allocate memory");
3745 sprintf(junk,
"%s%s", dash_set[c], dash_set[c + 1]);
3747 dash_set[c] = repalloc(dash_set[c],
sizeof(
char) * (strlen(junk) + 1));
3748 strcpy(dash_set[c], junk);
3752 for (dash_it = 1; dash_it < dash_n; dash_it++) {
3753 dash_set[dash_it - 1] = repalloc(dash_set[dash_it - 1], (strlen(dash_set[dash_it]) + 1) *
sizeof(
char));
3754 strcpy(dash_set[dash_it - 1], dash_set[dash_it]);
3758 pfree(dash_set[dash_n]);
3759 dash_set = repalloc(dash_set,
sizeof(
char *) * dash_n);
3763 if (c < 1 && dash_n > 2) {
3764 elog(NOTICE,
"Invalid argument for reclassargset. Invalid expression of reclassexpr for reclassarg of index %d . Returning original raster", i);
3765 for (k = 0; k < j; k++) pfree(exprset[k]);
3770 PG_FREE_IF_COPY(pgraster, 0);
3774 SET_VARSIZE(pgrtn, pgrtn->
size);
3775 PG_RETURN_POINTER(pgrtn);
3786 strchr(dash_set[c],
')') != NULL ||
3787 strchr(dash_set[c],
']') != NULL
3792 else if (strchr(dash_set[c],
'(') != NULL){
3802 strrchr(dash_set[c],
'(') != NULL ||
3803 strrchr(dash_set[c],
'[') != NULL
3808 else if (strrchr(dash_set[c],
']') != NULL) {
3816 POSTGIS_RT_DEBUGF(4,
"RASTER_reclass: exc_val %d inc_val %d", exc_val, inc_val);
3824 val = strtod(dash_set[c], &junk);
3825 if (errno != 0 || dash_set[c] == junk) {
3826 elog(NOTICE,
"Invalid argument for reclassargset. Invalid expression of reclassexpr for reclassarg of index %d . Returning original raster", i);
3827 for (k = 0; k < j; k++) pfree(exprset[k]);
3832 PG_FREE_IF_COPY(pgraster, 0);
3836 SET_VARSIZE(pgrtn, pgrtn->
size);
3837 PG_RETURN_POINTER(pgrtn);
3843 junk = strstr(colon_set[b], dash_set[c]);
3848 "(colon_set[%d], dash_set[%d], junk) = (%s, %s, %s)",
3849 b, c, colon_set[b], dash_set[c], junk
3852 if (junk != colon_set[b]) {
3854 if (*(junk - 1) ==
'-') {
3857 ((junk - 1) == colon_set[b]) ||
3858 (*(junk - 2) ==
'-') ||
3859 (*(junk - 2) ==
'[') ||
3860 (*(junk - 2) ==
'(')
3880 exprset[j]->
src.
min = val;
3886 exprset[j]->
src.
max = val;
3896 exprset[j]->
dst.
min = val;
3899 exprset[j]->
dst.
max = val;
3907 , exprset[j]->src.min
3917 tupv = GetAttributeByName(tup,
"pixeltype", &isnull);
3919 elog(NOTICE,
"Invalid argument for reclassargset. Missing value of pixeltype for reclassarg of index %d . Returning original raster", i);
3923 PG_FREE_IF_COPY(pgraster, 0);
3927 SET_VARSIZE(pgrtn, pgrtn->
size);
3928 PG_RETURN_POINTER(pgrtn);
3930 pixeltypetext = (text *) DatumGetPointer(tupv);
3931 if (NULL == pixeltypetext) {
3932 elog(NOTICE,
"Invalid argument for reclassargset. Missing value of pixeltype for reclassarg of index %d . Returning original raster", i);
3936 PG_FREE_IF_COPY(pgraster, 0);
3940 SET_VARSIZE(pgrtn, pgrtn->
size);
3941 PG_RETURN_POINTER(pgrtn);
3943 pixeltype = text_to_cstring(pixeltypetext);
3948 tupv = GetAttributeByName(tup,
"nodataval", &isnull);
3954 nodataval = DatumGetFloat8(tupv);
3963 elog(NOTICE,
"Could not find raster band of index %d. Returning original raster",
nband);
3964 for (k = 0; k < j; k++) pfree(exprset[k]);
3969 PG_FREE_IF_COPY(pgraster, 0);
3973 SET_VARSIZE(pgrtn, pgrtn->
size);
3974 PG_RETURN_POINTER(pgrtn);
3978 for (k = 0; k < j; k++) pfree(exprset[k]);
3982 PG_FREE_IF_COPY(pgraster, 0);
3984 elog(ERROR,
"RASTER_reclass: Could not reclassify raster band of index %d",
nband);
3990 for (k = 0; k < j; k++) pfree(exprset[k]);
3995 PG_FREE_IF_COPY(pgraster, 0);
3997 elog(ERROR,
"RASTER_reclass: Could not replace raster band of index %d with reclassified band",
nband);
4005 for (k = 0; k < j; k++) pfree(exprset[k]);
4011 PG_FREE_IF_COPY(pgraster, 0);
4017 SET_VARSIZE(pgrtn, pgrtn->
size);
4018 PG_RETURN_POINTER(pgrtn);
4047 elog(ERROR,
"rtpg_colormap_arg: Could not allocate memory for function arguments");
4058 elog(ERROR,
"rtpg_colormap_arg: Could not allocate memory for function arguments");
4091 for (i = 0; i < arg->
nentry; i++) {
4092 if (arg->
entry[i] != NULL)
4093 pfree(arg->
entry[i]);
4099 for (i = 0; i < arg->
nelement; i++)
4119 if (PG_ARGISNULL(0))
4125 elog(ERROR,
"RASTER_colorMap: Could not initialize argument structure");
4130 pgraster = (
rt_pgraster *) PG_DETOAST_DATUM(PG_GETARG_DATUM(0));
4136 PG_FREE_IF_COPY(pgraster, 0);
4137 elog(ERROR,
"RASTER_colorMap: Could not deserialize raster");
4142 if (!PG_ARGISNULL(1))
4143 arg->
nband = PG_GETARG_INT32(1);
4148 elog(NOTICE,
"Raster does not have band at index %d. Returning empty raster", arg->
nband);
4153 PG_FREE_IF_COPY(pgraster, 0);
4154 elog(ERROR,
"RASTER_colorMap: Could not create empty raster");
4159 PG_FREE_IF_COPY(pgraster, 0);
4163 if (pgraster == NULL)
4166 SET_VARSIZE(pgraster, ((
rt_pgraster*) pgraster)->size);
4167 PG_RETURN_POINTER(pgraster);
4172 if (arg->
band == NULL) {
4175 PG_FREE_IF_COPY(pgraster, 0);
4176 elog(ERROR,
"RASTER_colorMap: Could not get band at index %d",
nband);
4181 if (!PG_ARGISNULL(3)) {
4182 char *method = NULL;
4183 char *tmp = text_to_cstring(PG_GETARG_TEXT_P(3));
4190 if (strcmp(method,
"INTERPOLATE") == 0)
4192 else if (strcmp(method,
"EXACT") == 0)
4194 else if (strcmp(method,
"NEAREST") == 0)
4197 elog(NOTICE,
"Unknown value provided for method. Defaulting to INTERPOLATE");
4207 if (PG_ARGISNULL(2)) {
4209 PG_FREE_IF_COPY(pgraster, 0);
4210 elog(ERROR,
"RASTER_colorMap: Value must be provided for colormap");
4215 char *colormap = text_to_cstring(PG_GETARG_TEXT_P(2));
4224 if (!strlen(colormap)) {
4226 PG_FREE_IF_COPY(pgraster, 0);
4227 elog(ERROR,
"RASTER_colorMap: Value must be provided for colormap");
4235 PG_FREE_IF_COPY(pgraster, 0);
4236 elog(ERROR,
"RASTER_colorMap: Could not process the value provided for colormap");
4244 PG_FREE_IF_COPY(pgraster, 0);
4245 elog(ERROR,
"RASTER_colorMap: Could not allocate memory for colormap entries");
4251 for (i = 0; i < arg->
nentry; i++) {
4265 if (!strlen(_entry)) {
4275 PG_FREE_IF_COPY(pgraster, 0);
4276 elog(ERROR,
"RASTER_colorMap: Could not process colormap entry %d", i + 1);
4280 elog(NOTICE,
"More than five elements in colormap entry %d. Using at most five elements", i + 1);
4289 for (j = 0; j < arg->
nelement; j++) {
4298 char *percent = NULL;
4302 strcmp(_element,
"NV") == 0 ||
4303 strcmp(_element,
"NULL") == 0 ||
4304 strcmp(_element,
"NODATA") == 0
4309 elog(NOTICE,
"More than one NODATA entry found. Using only the first one");
4318 else if ((percent = strchr(_element,
'%')) != NULL) {
4330 PG_FREE_IF_COPY(pgraster, 0);
4331 elog(ERROR,
"RASTER_colorMap: Could not get band's summary stats to process percentages");
4337 tmp = palloc(
sizeof(
char) * (percent - _element + 1));
4341 PG_FREE_IF_COPY(pgraster, 0);
4342 elog(ERROR,
"RASTER_colorMap: Could not allocate memory for value of percentage");
4346 memcpy(tmp, _element, percent - _element);
4347 tmp[percent - _element] =
'\0';
4352 value = strtod(tmp, NULL);
4354 if (errno != 0 || _element == junk) {
4357 PG_FREE_IF_COPY(pgraster, 0);
4358 elog(ERROR,
"RASTER_colorMap: Could not process percent string to value");
4364 elog(NOTICE,
"Percentage values cannot be less than zero. Defaulting to zero");
4367 else if (
value > 100.) {
4368 elog(NOTICE,
"Percentage values cannot be greater than 100. Defaulting to 100");
4380 if (errno != 0 || _element == junk) {
4383 PG_FREE_IF_COPY(pgraster, 0);
4384 elog(ERROR,
"RASTER_colorMap: Could not process string to value");
4395 value = (int) strtod(_element, &junk);
4396 if (errno != 0 || _element == junk) {
4399 PG_FREE_IF_COPY(pgraster, 0);
4400 elog(ERROR,
"RASTER_colorMap: Could not process string to value");
4405 elog(NOTICE,
"RGBA value cannot be greater than 255. Defaulting to 255");
4408 else if (
value < 0) {
4409 elog(NOTICE,
"RGBA value cannot be less than zero. Defaulting to zero");
4418 POSTGIS_RT_DEBUGF(4,
"colormap->entry[%d] (isnodata, value, R, G, B, A) = (%d, %f, %d, %d, %d, %d)",
4439 PG_FREE_IF_COPY(pgraster, 0);
4440 elog(ERROR,
"RASTER_colorMap: Could not create new raster with applied colormap");
4445 PG_FREE_IF_COPY(pgraster, 0);
4451 if (pgraster == NULL)
4454 SET_VARSIZE(pgraster, ((
rt_pgraster*) pgraster)->size);
4455 PG_RETURN_POINTER(pgraster);
4467 int x,
y,
nband, width, height;
4469 double newnodatavalue = 0.0;
4470 double newinitialvalue = 0.0;
4471 double newval = 0.0;
4472 char *newexpr = NULL;
4473 char *initexpr = NULL;
4474 char *expression = NULL;
4475 int hasnodataval = 0;
4476 double nodataval = 0.;
4478 int skipcomputation = 0;
4480 const int argkwcount = 3;
4481 enum KEYWORDS { kVAL=0, kX=1, kY=2 };
4482 char *argkw[] = {
"[rast]",
"[rast.x]",
"[rast.y]"};
4483 Oid argkwtypes[] = { FLOAT8OID, INT4OID, INT4OID };
4485 Oid argtype[] = { FLOAT8OID, INT4OID, INT4OID };
4486 uint8_t argpos[3] = {0};
4491 SPIPlanPtr spi_plan = NULL;
4492 SPITupleTable * tuptable = NULL;
4494 char * strFromText = NULL;
4495 Datum *values = NULL;
4496 Datum datum = (Datum)NULL;
4498 bool isnull =
FALSE;
4505 if (PG_ARGISNULL(0)) {
4506 elog(NOTICE,
"Raster is NULL. Returning NULL");
4512 pgraster = (
rt_pgraster *)PG_DETOAST_DATUM(PG_GETARG_DATUM(0));
4515 PG_FREE_IF_COPY(pgraster, 0);
4516 elog(ERROR,
"RASTER_mapAlgebraExpr: Could not deserialize raster");
4522 if (PG_ARGISNULL(1))
4525 nband = PG_GETARG_INT32(1);
4531 POSTGIS_RT_DEBUG(3,
"RASTER_mapAlgebraExpr: Creating new empty raster...");
4542 if ( NULL == newrast ) {
4543 PG_FREE_IF_COPY(pgraster, 0);
4544 elog(ERROR,
"RASTER_mapAlgebraExpr: Could not create a new raster");
4569 elog(NOTICE,
"Raster is empty. Returning an empty raster");
4571 PG_FREE_IF_COPY(pgraster, 0);
4575 if (NULL == pgrtn) {
4577 elog(ERROR,
"RASTER_mapAlgebraExpr: Could not serialize raster");
4581 SET_VARSIZE(pgrtn, pgrtn->
size);
4582 PG_RETURN_POINTER(pgrtn);
4593 elog(NOTICE,
"Raster does not have the required band. Returning a raster "
4596 PG_FREE_IF_COPY(pgraster, 0);
4600 if (NULL == pgrtn) {
4601 elog(ERROR,
"RASTER_mapAlgebraExpr: Could not serialize raster");
4605 SET_VARSIZE(pgrtn, pgrtn->
size);
4606 PG_RETURN_POINTER(pgrtn);
4611 if ( NULL ==
band ) {
4612 elog(NOTICE,
"Could not get the required band. Returning a raster "
4615 PG_FREE_IF_COPY(pgraster, 0);
4619 if (NULL == pgrtn) {
4620 elog(ERROR,
"RASTER_mapAlgebraExpr: Could not serialize raster");
4624 SET_VARSIZE(pgrtn, pgrtn->
size);
4625 PG_RETURN_POINTER(pgrtn);
4631 POSTGIS_RT_DEBUG(3,
"RASTER_mapAlgebraExpr: Getting NODATA value for band...");
4649 newinitialvalue = newnodatavalue;
4656 if (PG_ARGISNULL(2)) {
4661 strFromText = text_to_cstring(PG_GETARG_TEXT_P(2));
4664 if (newpixeltype ==
PT_END)
4668 if (newpixeltype ==
PT_END) {
4669 PG_FREE_IF_COPY(pgraster, 0);
4670 elog(ERROR,
"RASTER_mapAlgebraExpr: Invalid pixeltype");
4679 if (!PG_ARGISNULL(3)) {
4680 expression = text_to_cstring(PG_GETARG_TEXT_P(3));
4681 len = strlen(
"SELECT (") + strlen(expression) + strlen(
")::double precision");
4682 initexpr = (
char *)palloc(len + 1);
4684 memcpy(initexpr,
"SELECT (", strlen(
"SELECT ("));
4685 memcpy(initexpr + strlen(
"SELECT ("), expression, strlen(expression));
4686 memcpy(initexpr + strlen(
"SELECT (") + strlen(expression),
")::double precision", strlen(
")::double precision"));
4687 initexpr[len] =
'\0';
4705 if (!PG_ARGISNULL(4)) {
4707 nodataval = PG_GETARG_FLOAT8(4);
4708 newinitialvalue = nodataval;
4725 POSTGIS_RT_DEBUG(3,
"RASTER_mapAlgebraExpr: Band is a nodata band, returning "
4726 "a raster filled with nodata");
4729 newinitialvalue,
TRUE, newnodatavalue, 0);
4735 PG_FREE_IF_COPY(pgraster, 0);
4740 if (NULL == pgrtn) {
4741 elog(ERROR,
"RASTER_mapAlgebraExpr: Could not serialize raster");
4745 SET_VARSIZE(pgrtn, pgrtn->
size);
4746 PG_RETURN_POINTER(pgrtn);
4754 if (initexpr != NULL && ( !strcmp(initexpr,
"SELECT [rast]") || !strcmp(initexpr,
"SELECT [rast.val]") ) && !hasnodataval) {
4757 "Returning raster with band %d from original raster",
nband);
4769 PG_FREE_IF_COPY(pgraster, 0);
4774 if (NULL == pgrtn) {
4775 elog(ERROR,
"RASTER_mapAlgebraExpr: Could not serialize raster");
4779 SET_VARSIZE(pgrtn, pgrtn->
size);
4780 PG_RETURN_POINTER(pgrtn);
4787 if (initexpr != NULL && strstr(initexpr,
"[rast") == NULL) {
4788 ret = SPI_connect();
4789 if (ret != SPI_OK_CONNECT) {
4790 PG_FREE_IF_COPY(pgraster, 0);
4791 elog(ERROR,
"RASTER_mapAlgebraExpr: Could not connect to the SPI manager");
4796 ret = SPI_execute(initexpr,
FALSE, 0);
4798 if (ret != SPI_OK_SELECT || SPI_tuptable == NULL || SPI_processed != 1) {
4802 SPI_freetuptable(tuptable);
4803 PG_FREE_IF_COPY(pgraster, 0);
4806 elog(ERROR,
"RASTER_mapAlgebraExpr: Invalid construction for expression");
4810 tupdesc = SPI_tuptable->tupdesc;
4811 tuptable = SPI_tuptable;
4813 tuple = tuptable->vals[0];
4814 newexpr = SPI_getvalue(tuple, tupdesc, 1);
4816 POSTGIS_RT_DEBUG(3,
"Constant expression evaluated to NULL, keeping initvalue");
4817 newval = newinitialvalue;
4819 newval = atof(newexpr);
4822 SPI_freetuptable(tuptable);
4829 skipcomputation = 1;
4835 if (!hasnodataval) {
4836 newinitialvalue = newval;
4837 skipcomputation = 2;
4841 else if (
FLT_NEQ(newval, newinitialvalue)) {
4842 skipcomputation = 2;
4851 newinitialvalue,
TRUE, newnodatavalue, 0);
4858 if (expression == NULL || skipcomputation == 2) {
4864 PG_FREE_IF_COPY(pgraster, 0);
4869 if (NULL == pgrtn) {
4870 elog(ERROR,
"RASTER_mapAlgebraExpr: Could not serialize raster");
4874 SET_VARSIZE(pgrtn, pgrtn->
size);
4875 PG_RETURN_POINTER(pgrtn);
4878 RASTER_DEBUG(3,
"RASTER_mapAlgebraExpr: Creating new raster band...");
4882 if ( NULL == newband ) {
4883 elog(NOTICE,
"Could not modify band for new raster. Returning new "
4884 "raster with the original band");
4889 PG_FREE_IF_COPY(pgraster, 0);
4894 if (NULL == pgrtn) {
4895 elog(ERROR,
"RASTER_mapAlgebraExpr: Could not serialize raster");
4899 SET_VARSIZE(pgrtn, pgrtn->
size);
4900 PG_RETURN_POINTER(pgrtn);
4906 if (initexpr != NULL) {
4909 pfree(initexpr); initexpr=newexpr;
4911 sprintf(place,
"$1");
4912 for (i = 0, j = 1; i < argkwcount; i++) {
4915 pfree(initexpr); initexpr=newexpr;
4917 argtype[argcount] = argkwtypes[i];
4921 sprintf(place,
"$%d", j);
4931 values = (Datum *) palloc(
sizeof(Datum) * argcount);
4932 if (values == NULL) {
4937 PG_FREE_IF_COPY(pgraster, 0);
4940 elog(ERROR,
"RASTER_mapAlgebraExpr: Could not allocate memory for value parameters of prepared statement");
4945 nulls = (
char *)palloc(argcount);
4946 if (nulls == NULL) {
4951 PG_FREE_IF_COPY(pgraster, 0);
4954 elog(ERROR,
"RASTER_mapAlgebraExpr: Could not allocate memory for null parameters of prepared statement");
4959 ret = SPI_connect();
4960 if (ret != SPI_OK_CONNECT) {
4965 PG_FREE_IF_COPY(pgraster, 0);
4968 elog(ERROR,
"RASTER_mapAlgebraExpr: Could not connect to the SPI manager");
4973 spi_plan = SPI_prepare(initexpr, argcount, argtype);
4975 if (spi_plan == NULL) {
4978 PG_FREE_IF_COPY(pgraster, 0);
4985 elog(ERROR,
"RASTER_mapAlgebraExpr: Could not prepare expression");
4990 for (
x = 0;
x < width;
x++) {
4991 for(
y = 0;
y < height;
y++) {
4999 if (skipcomputation == 0) {
5000 if (initexpr != NULL) {
5002 memset(nulls,
'n', argcount);
5004 for (i = 0; i < argkwcount; i++) {
5006 if (idx < 1)
continue;
5011 values[idx] = Int32GetDatum(
x+1);
5016 values[idx] = Int32GetDatum(
y+1);
5019 else if (i == kVAL ) {
5020 values[idx] = Float8GetDatum(
r);
5026 ret = SPI_execute_plan(spi_plan, values, nulls,
FALSE, 0);
5027 if (ret != SPI_OK_SELECT || SPI_tuptable == NULL ||
5028 SPI_processed != 1) {
5030 SPI_freetuptable(tuptable);
5032 SPI_freeplan(spi_plan);
5040 PG_FREE_IF_COPY(pgraster, 0);
5043 elog(ERROR,
"RASTER_mapAlgebraExpr: Error executing prepared plan");
5048 tupdesc = SPI_tuptable->tupdesc;
5049 tuptable = SPI_tuptable;
5051 tuple = tuptable->vals[0];
5052 datum = SPI_getbinval(tuple, tupdesc, 1, &isnull);
5053 if ( SPI_result == SPI_ERROR_NOATTRIBUTE ) {
5054 POSTGIS_RT_DEBUGF(3,
"Expression for pixel %d,%d (value %g) errored, skip setting",
x+1,
y+1,
r);
5055 newval = newinitialvalue;
5057 else if ( isnull ) {
5058 POSTGIS_RT_DEBUGF(3,
"Expression for pixel %d,%d (value %g) evaluated to NULL, skip setting",
x+1,
y+1,
r);
5059 newval = newinitialvalue;
5061 newval = DatumGetFloat8(datum);
5064 SPI_freetuptable(tuptable);
5068 newval = newinitialvalue;
5081 if (initexpr != NULL) {
5082 SPI_freeplan(spi_plan);
5096 POSTGIS_RT_DEBUG(3,
"RASTER_mapAlgebraExpr: raster modified, serializing it.");
5100 PG_FREE_IF_COPY(pgraster, 0);
5107 SET_VARSIZE(pgrtn, pgrtn->
size);
5115 PG_RETURN_POINTER(pgrtn);
5130 int x,
y,
nband, width, height;
5132 double newnodatavalue = 0.0;
5133 double newinitialvalue = 0.0;
5134 double newval = 0.0;
5139 #if POSTGIS_PGSQL_VERSION < 120
5140 FunctionCallInfoData cbdata;
5142 LOCAL_FCINFO(cbdata, FUNC_MAX_ARGS);
5145 char * strFromText = NULL;
5151 if (PG_ARGISNULL(0)) {
5152 elog(WARNING,
"Raster is NULL. Returning NULL");
5158 pgraster = (
rt_pgraster *)PG_DETOAST_DATUM(PG_GETARG_DATUM(0));
5161 PG_FREE_IF_COPY(pgraster, 0);
5162 elog(ERROR,
"RASTER_mapAlgebraFct: Could not deserialize raster");
5170 if (PG_ARGISNULL(1))
5173 nband = PG_GETARG_INT32(1);
5189 if ( NULL == newrast ) {
5192 PG_FREE_IF_COPY(pgraster, 0);
5194 elog(ERROR,
"RASTER_mapAlgebraFct: Could not create a new raster");
5219 elog(NOTICE,
"Raster is empty. Returning an empty raster");
5221 PG_FREE_IF_COPY(pgraster, 0);
5225 if (NULL == pgrtn) {
5226 elog(ERROR,
"RASTER_mapAlgebraFct: Could not serialize raster");
5230 SET_VARSIZE(pgrtn, pgrtn->
size);
5231 PG_RETURN_POINTER(pgrtn);
5241 elog(NOTICE,
"Raster does not have the required band. Returning a raster "
5244 PG_FREE_IF_COPY(pgraster, 0);
5248 if (NULL == pgrtn) {
5249 elog(ERROR,
"RASTER_mapAlgebraFct: Could not serialize raster");
5253 SET_VARSIZE(pgrtn, pgrtn->
size);
5254 PG_RETURN_POINTER(pgrtn);
5259 if ( NULL ==
band ) {
5260 elog(NOTICE,
"Could not get the required band. Returning a raster "
5263 PG_FREE_IF_COPY(pgraster, 0);
5267 if (NULL == pgrtn) {
5268 elog(ERROR,
"RASTER_mapAlgebraFct: Could not serialize raster");
5272 SET_VARSIZE(pgrtn, pgrtn->
size);
5273 PG_RETURN_POINTER(pgrtn);
5279 POSTGIS_RT_DEBUG(3,
"RASTER_mapAlgebraFct: Getting NODATA value for band...");
5296 newinitialvalue = newnodatavalue;
5303 if (PG_ARGISNULL(2)) {
5308 strFromText = text_to_cstring(PG_GETARG_TEXT_P(2));
5311 if (newpixeltype ==
PT_END)
5315 if (newpixeltype ==
PT_END) {
5318 PG_FREE_IF_COPY(pgraster, 0);
5321 elog(ERROR,
"RASTER_mapAlgebraFct: Invalid pixeltype");
5329 if (PG_ARGISNULL(3)) {
5332 PG_FREE_IF_COPY(pgraster, 0);
5335 elog(ERROR,
"RASTER_mapAlgebraFct: Required function is missing. Returning NULL");
5339 oid = PG_GETARG_OID(3);
5340 if (oid == InvalidOid) {
5343 PG_FREE_IF_COPY(pgraster, 0);
5346 elog(ERROR,
"RASTER_mapAlgebraFct: Got invalid function object id. Returning NULL");
5350 fmgr_info(oid, &cbinfo);
5353 if (cbinfo.fn_retset) {
5356 PG_FREE_IF_COPY(pgraster, 0);
5359 elog(ERROR,
"RASTER_mapAlgebraFct: Function provided must return double precision not resultset");
5363 else if (cbinfo.fn_nargs < 2 || cbinfo.fn_nargs > 3) {
5366 PG_FREE_IF_COPY(pgraster, 0);
5369 elog(ERROR,
"RASTER_mapAlgebraFct: Function does not have two or three input parameters");
5373 if (cbinfo.fn_nargs == 2)
5378 if (func_volatile(oid) ==
'v') {
5379 elog(NOTICE,
"Function provided is VOLATILE. Unless required and for best performance, function should be IMMUTABLE or STABLE");
5383 #if POSTGIS_PGSQL_VERSION < 120
5384 InitFunctionCallInfoData(cbdata, &cbinfo, 2, InvalidOid, NULL, NULL);
5386 cbdata.argnull[0] =
FALSE;
5387 cbdata.argnull[1] =
FALSE;
5388 cbdata.argnull[2] =
FALSE;
5390 InitFunctionCallInfoData(*cbdata, &cbinfo, 2, InvalidOid, NULL, NULL);
5392 cbdata->args[0].isnull =
FALSE;
5393 cbdata->args[1].isnull =
FALSE;
5394 cbdata->args[2].isnull =
FALSE;
5398 if (PG_ARGISNULL(4)) {
5399 if (cbinfo.fn_strict) {
5402 PG_FREE_IF_COPY(pgraster, 0);
5405 elog(ERROR,
"RASTER_mapAlgebraFct: Strict callback functions cannot have null parameters");
5409 #if POSTGIS_PGSQL_VERSION < 120
5410 cbdata.arg[k] = (Datum)NULL;
5411 cbdata.argnull[k] =
TRUE;
5413 cbdata->args[k].value = (Datum)NULL;
5414 cbdata->args[k].isnull =
TRUE;
5418 #if POSTGIS_PGSQL_VERSION < 120
5419 cbdata.arg[k] = PG_GETARG_DATUM(4);
5421 cbdata->args[k].value = PG_GETARG_DATUM(4);
5432 POSTGIS_RT_DEBUG(3,
"RASTER_mapAlgebraFct: Band is a nodata band, returning "
5433 "a raster filled with nodata");
5436 newinitialvalue,
TRUE, newnodatavalue, 0);
5439 PG_FREE_IF_COPY(pgraster, 0);
5444 if (NULL == pgrtn) {
5445 elog(ERROR,
"RASTER_mapAlgebraFct: Could not serialize raster");
5449 SET_VARSIZE(pgrtn, pgrtn->
size);
5450 PG_RETURN_POINTER(pgrtn);
5459 newinitialvalue,
TRUE, newnodatavalue, 0);
5463 if ( NULL == newband ) {
5464 elog(NOTICE,
"Could not modify band for new raster. Returning new "
5465 "raster with the original band");
5468 PG_FREE_IF_COPY(pgraster, 0);
5473 if (NULL == pgrtn) {
5474 elog(ERROR,
"RASTER_mapAlgebraFct: Could not serialize raster");
5478 SET_VARSIZE(pgrtn, pgrtn->
size);
5479 PG_RETURN_POINTER(pgrtn);
5485 for (
x = 0;
x < width;
x++) {
5486 for(
y = 0;
y < height;
y++) {
5494 if (
FLT_EQ(
r, newnodatavalue)) {
5495 if (cbinfo.fn_strict) {
5496 POSTGIS_RT_DEBUG(3,
"RASTER_mapAlgebraFct: Strict callbacks cannot accept NULL arguments, skipping NODATA cell.");
5499 #if POSTGIS_PGSQL_VERSION < 120
5500 cbdata.argnull[0] =
TRUE;
5501 cbdata.arg[0] = (Datum)NULL;
5503 cbdata->args[0].isnull =
TRUE;
5504 cbdata->args[0].value = (Datum)NULL;
5508 #if POSTGIS_PGSQL_VERSION < 120
5509 cbdata.argnull[0] =
FALSE;
5510 cbdata.arg[0] = Float8GetDatum(
r);
5512 cbdata->args[0].isnull =
FALSE;
5513 cbdata->args[0].value = Float8GetDatum(
r);
5518 if (cbinfo.fn_nargs == 3) {
5522 d[0] = Int32GetDatum(
x+1);
5523 d[1] = Int32GetDatum(
y+1);
5525 a = construct_array(d, 2, INT4OID,
sizeof(
int32),
true,
'i');
5527 #if POSTGIS_PGSQL_VERSION < 120
5528 cbdata.argnull[1] =
FALSE;
5529 cbdata.arg[1] = PointerGetDatum(a);
5531 cbdata->args[1].isnull =
FALSE;
5532 cbdata->args[1].value = PointerGetDatum(a);
5539 #if POSTGIS_PGSQL_VERSION < 120
5540 tmpnewval = FunctionCallInvoke(&cbdata);
5542 if (cbdata.isnull) {
5543 newval = newnodatavalue;
5546 tmpnewval = FunctionCallInvoke(cbdata);
5550 newval = newnodatavalue;
5554 newval = DatumGetFloat8(tmpnewval);
5568 POSTGIS_RT_DEBUG(3,
"RASTER_mapAlgebraFct: raster modified, serializing it.");
5572 PG_FREE_IF_COPY(pgraster, 0);
5583 SET_VARSIZE(pgrtn, pgrtn->
size);
5584 PG_RETURN_POINTER(pgrtn);
5599 int x,
y,
nband, width, height, ngbwidth, ngbheight, winwidth, winheight, u, v, nIndex, nNullItems;
5601 double newnodatavalue = 0.0;
5602 double newinitialvalue = 0.0;
5603 double newval = 0.0;
5608 #if POSTGIS_PGSQL_VERSION < 120
5609 FunctionCallInfoData cbdata;
5611 LOCAL_FCINFO(cbdata, FUNC_MAX_ARGS);
5614 ArrayType * neighborDatum;
5615 char * strFromText = NULL;
5616 text * txtNodataMode = NULL;
5617 text * txtCallbackParam = NULL;
5619 float fltReplace = 0;
5620 bool valuereplace =
false, pixelreplace, nNodataOnly =
true, nNullSkip =
false;
5621 Datum * neighborData = NULL;
5622 bool * neighborNulls = NULL;
5623 int neighborDims[2];
5632 if (PG_ARGISNULL(0)) {
5633 elog(WARNING,
"Raster is NULL. Returning NULL");
5639 pgraster = (
rt_pgraster *)PG_DETOAST_DATUM(PG_GETARG_DATUM(0));
5643 PG_FREE_IF_COPY(pgraster, 0);
5644 elog(ERROR,
"RASTER_mapAlgebraFctNgb: Could not deserialize raster");
5652 if (PG_ARGISNULL(1))
5655 nband = PG_GETARG_INT32(1);
5660 POSTGIS_RT_DEBUG(3,
"RASTER_mapAlgebraFctNgb: Creating new empty raster...");
5671 if ( NULL == newrast ) {
5673 PG_FREE_IF_COPY(pgraster, 0);
5674 elog(ERROR,
"RASTER_mapAlgebraFctNgb: Could not create a new raster");
5699 elog(NOTICE,
"Raster is empty. Returning an empty raster");
5701 PG_FREE_IF_COPY(pgraster, 0);
5705 if (NULL == pgrtn) {
5706 elog(ERROR,
"RASTER_mapAlgebraFctNgb: Could not serialize raster");
5710 SET_VARSIZE(pgrtn, pgrtn->
size);
5711 PG_RETURN_POINTER(pgrtn);
5721 elog(NOTICE,
"Raster does not have the required band. Returning a raster "
5724 PG_FREE_IF_COPY(pgraster, 0);
5728 if (NULL == pgrtn) {
5729 elog(ERROR,
"RASTER_mapAlgebraFctNgb: Could not serialize raster");
5733 SET_VARSIZE(pgrtn, pgrtn->
size);
5734 PG_RETURN_POINTER(pgrtn);
5739 if ( NULL ==
band ) {
5740 elog(NOTICE,
"Could not get the required band. Returning a raster "
5743 PG_FREE_IF_COPY(pgraster, 0);
5747 if (NULL == pgrtn) {
5748 elog(ERROR,
"RASTER_mapAlgebraFctNgb: Could not serialize raster");
5752 SET_VARSIZE(pgrtn, pgrtn->
size);
5753 PG_RETURN_POINTER(pgrtn);
5759 POSTGIS_RT_DEBUG(3,
"RASTER_mapAlgebraFctNgb: Getting NODATA value for band...");
5776 newinitialvalue = newnodatavalue;
5783 if (PG_ARGISNULL(2)) {
5788 strFromText = text_to_cstring(PG_GETARG_TEXT_P(2));
5789 POSTGIS_RT_DEBUGF(3,
"RASTER_mapAlgebraFctNgb: Pixeltype parameter: %s", strFromText);
5792 if (newpixeltype ==
PT_END)
5796 if (newpixeltype ==
PT_END) {
5799 PG_FREE_IF_COPY(pgraster, 0);
5802 elog(ERROR,
"RASTER_mapAlgebraFctNgb: Invalid pixeltype");
5810 if (PG_ARGISNULL(5)) {
5813 PG_FREE_IF_COPY(pgraster, 0);
5816 elog(ERROR,
"RASTER_mapAlgebraFctNgb: Required function is missing");
5820 oid = PG_GETARG_OID(5);
5821 if (oid == InvalidOid) {
5824 PG_FREE_IF_COPY(pgraster, 0);
5827 elog(ERROR,
"RASTER_mapAlgebraFctNgb: Got invalid function object id");
5831 fmgr_info(oid, &cbinfo);
5834 if (cbinfo.fn_retset) {
5837 PG_FREE_IF_COPY(pgraster, 0);
5840 elog(ERROR,
"RASTER_mapAlgebraFctNgb: Function provided must return double precision not resultset");
5844 else if (cbinfo.fn_nargs != 3) {
5847 PG_FREE_IF_COPY(pgraster, 0);
5850 elog(ERROR,
"RASTER_mapAlgebraFctNgb: Function does not have three input parameters");
5854 if (func_volatile(oid) ==
'v') {
5855 elog(NOTICE,
"Function provided is VOLATILE. Unless required and for best performance, function should be IMMUTABLE or STABLE");
5859 #if POSTGIS_PGSQL_VERSION < 120
5860 InitFunctionCallInfoData(cbdata, &cbinfo, 3, InvalidOid, NULL, NULL);
5861 memset(cbdata.argnull,
FALSE,
sizeof(
bool) * 3);
5863 InitFunctionCallInfoData(*cbdata, &cbinfo, 3, InvalidOid, NULL, NULL);
5864 cbdata->args[0].isnull =
FALSE;
5865 cbdata->args[1].isnull =
FALSE;
5866 cbdata->args[2].isnull =
FALSE;
5870 if (PG_ARGISNULL(7)) {
5871 if (cbinfo.fn_strict) {
5874 PG_FREE_IF_COPY(pgraster, 0);
5877 elog(ERROR,
"RASTER_mapAlgebraFctNgb: Strict callback functions cannot have NULL parameters");
5881 #if POSTGIS_PGSQL_VERSION < 120
5882 cbdata.arg[2] = (Datum)NULL;
5883 cbdata.argnull[2] =
TRUE;
5885 cbdata->args[2].value = (Datum)NULL;
5886 cbdata->args[2].isnull =
TRUE;
5890 #if POSTGIS_PGSQL_VERSION < 120
5891 cbdata.arg[2] = PG_GETARG_DATUM(7);
5893 cbdata->args[2].value = PG_GETARG_DATUM(7);
5904 POSTGIS_RT_DEBUG(3,
"RASTER_mapAlgebraFctNgb: Band is a nodata band, returning "
5905 "a raster filled with nodata");
5908 newinitialvalue,
TRUE, newnodatavalue, 0);
5911 PG_FREE_IF_COPY(pgraster, 0);
5916 if (NULL == pgrtn) {
5917 elog(ERROR,
"RASTER_mapAlgebraFctNgb: Could not serialize raster");
5921 SET_VARSIZE(pgrtn, pgrtn->
size);
5922 PG_RETURN_POINTER(pgrtn);
5931 newinitialvalue,
TRUE, newnodatavalue, 0);
5935 if ( NULL == newband ) {
5936 elog(NOTICE,
"Could not modify band for new raster. Returning new "
5937 "raster with the original band");
5940 PG_FREE_IF_COPY(pgraster, 0);
5945 if (NULL == pgrtn) {
5946 elog(ERROR,
"RASTER_mapAlgebraFctNgb: Could not serialize raster");
5950 SET_VARSIZE(pgrtn, pgrtn->
size);
5951 PG_RETURN_POINTER(pgrtn);
5955 if (PG_ARGISNULL(3) || PG_GETARG_INT32(3) <= 0) {
5956 elog(NOTICE,
"Neighborhood width is NULL or <= 0. Returning new "
5957 "raster with the original band");
5960 PG_FREE_IF_COPY(pgraster, 0);
5965 if (NULL == pgrtn) {
5966 elog(ERROR,
"RASTER_mapAlgebraFctNgb: Could not serialize raster");
5970 SET_VARSIZE(pgrtn, pgrtn->
size);
5971 PG_RETURN_POINTER(pgrtn);
5974 ngbwidth = PG_GETARG_INT32(3);
5975 winwidth = ngbwidth * 2 + 1;
5978 if (PG_ARGISNULL(4) || PG_GETARG_INT32(4) <= 0) {
5979 elog(NOTICE,
"Neighborhood height is NULL or <= 0. Returning new "
5980 "raster with the original band");
5983 PG_FREE_IF_COPY(pgraster, 0);
5988 if (NULL == pgrtn) {
5989 elog(ERROR,
"RASTER_mapAlgebraFctNgb: Could not serialize raster");
5993 SET_VARSIZE(pgrtn, pgrtn->
size);
5994 PG_RETURN_POINTER(pgrtn);
5997 ngbheight = PG_GETARG_INT32(4);
5998 winheight = ngbheight * 2 + 1;
6001 if (PG_ARGISNULL(6)) {
6002 elog(NOTICE,
"Neighborhood NODATA behavior defaulting to 'ignore'");
6003 txtNodataMode = cstring_to_text(
"ignore");
6006 txtNodataMode = PG_GETARG_TEXT_P(6);
6009 txtCallbackParam = (text*)palloc(VARSIZE(txtNodataMode));
6010 SET_VARSIZE(txtCallbackParam, VARSIZE(txtNodataMode));
6011 memcpy((
void *)VARDATA(txtCallbackParam), (
void *)VARDATA(txtNodataMode), VARSIZE(txtNodataMode) - VARHDRSZ);
6014 #if POSTGIS_PGSQL_VERSION < 120
6015 cbdata.arg[1] = PointerGetDatum(txtCallbackParam);
6017 cbdata->args[1].value = PointerGetDatum(txtCallbackParam);
6020 strFromText = text_to_cstring(txtNodataMode);
6023 if (strcmp(strFromText,
"VALUE") == 0)
6024 valuereplace =
true;
6025 else if (strcmp(strFromText,
"IGNORE") != 0 && strcmp(strFromText,
"NULL") != 0) {
6027 if (sscanf(strFromText,
"%d", &intReplace) <= 0 && sscanf(strFromText,
"%f", &fltReplace) <= 0) {
6029 elog(NOTICE,
"Neighborhood NODATA mode is not recognized. Must be one of 'value', 'ignore', "
6030 "'NULL', or a numeric value. Returning new raster with the original band");
6033 pfree(txtCallbackParam);
6037 PG_FREE_IF_COPY(pgraster, 0);
6042 if (NULL == pgrtn) {
6043 elog(ERROR,
"RASTER_mapAlgebraFctNgb: Could not serialize raster");
6047 SET_VARSIZE(pgrtn, pgrtn->
size);
6048 PG_RETURN_POINTER(pgrtn);
6051 else if (strcmp(strFromText,
"NULL") == 0) {
6060 neighborData = (Datum *)palloc(winwidth * winheight *
sizeof(Datum));
6061 neighborNulls = (
bool *)palloc(winwidth * winheight *
sizeof(
bool));
6064 neighborDims[0] = winwidth;
6065 neighborDims[1] = winheight;
6072 get_typlenbyvalalign(FLOAT8OID, &typlen, &typbyval, &typalign);
6074 for (
x = 0 + ngbwidth;
x < width - ngbwidth;
x++) {
6075 for(
y = 0 + ngbheight;
y < height - ngbheight;
y++) {
6080 pixelreplace =
false;
6084 pixelreplace =
true;
6087 for (u =
x - ngbwidth; u <=
x + ngbwidth; u++) {
6088 for (v =
y - ngbheight; v <=
y + ngbheight; v++) {
6093 neighborData[nIndex] = Float8GetDatum((
double)
r);
6094 neighborNulls[nIndex] =
false;
6095 nNodataOnly =
false;
6099 if (valuereplace && pixelreplace) {
6101 neighborData[nIndex] = Float8GetDatum((
double)rpix);
6102 neighborNulls[nIndex] =
false;
6107 neighborData[nIndex] = PointerGetDatum(NULL);
6108 neighborNulls[nIndex] =
true;
6115 neighborData[nIndex] = PointerGetDatum(NULL);
6116 neighborNulls[nIndex] =
true;
6128 if (!(nNodataOnly ||
6129 (nNullSkip && nNullItems > 0) ||
6130 (valuereplace && nNullItems > 0))) {
6132 x,
y, winwidth, winheight);
6134 neighborDatum = construct_md_array((
void *)neighborData, neighborNulls, 2, neighborDims, neighborLbs,
6135 FLOAT8OID, typlen, typbyval, typalign);
6137 #if POSTGIS_PGSQL_VERSION < 120
6139 cbdata.arg[0] = PointerGetDatum(neighborDatum);
6142 tmpnewval = FunctionCallInvoke(&cbdata);
6145 if (cbdata.isnull) {
6146 newval = newnodatavalue;
6150 cbdata->args[0].value = PointerGetDatum(neighborDatum);
6153 tmpnewval = FunctionCallInvoke(cbdata);
6158 newval = newnodatavalue;
6162 newval = DatumGetFloat8(tmpnewval);
6178 pfree(neighborNulls);
6179 pfree(neighborData);
6181 pfree(txtCallbackParam);
6184 PG_FREE_IF_COPY(pgraster, 0);
6188 POSTGIS_RT_DEBUG(3,
"RASTER_mapAlgebraFctNgb: raster modified, serializing it.");
6199 SET_VARSIZE(pgrtn, pgrtn->
size);
6200 PG_RETURN_POINTER(pgrtn);
6203 #define ARGKWCOUNT 8
6211 const uint32_t set_count = 2;
6213 int pgrastpos[2] = {-1, -1};
6216 int _isempty[2] = {0};
6217 uint32_t bandindex[2] = {0};
6220 int _hasnodata[2] = {0};
6221 double _nodataval[2] = {0};
6222 double _offset[4] = {0.};
6223 double _rastoffset[2][4] = {{0.}};
6224 int _haspixel[2] = {0};
6225 double _pixel[2] = {0};
6226 int _pos[2][2] = {{0}};
6227 uint16_t _dim[2][2] = {{0}};
6229 char *pixtypename = NULL;
6231 char *extenttypename = NULL;
6236 uint16_t dim[2] = {0};
6239 double nodataval = 0;
6240 double gt[6] = {0.};
6242 Oid calltype = InvalidOid;
6244 const uint32_t spi_count = 3;
6245 uint16_t spi_exprpos[3] = {4, 7, 8};
6246 uint32_t spi_argcount[3] = {0};
6249 SPIPlanPtr spi_plan[3] = {NULL};
6250 uint16_t spi_empty = 0;
6251 Oid *argtype = NULL;
6252 uint8_t argpos[3][8] = {{0}};
6253 char *argkw[] = {
"[rast1.x]",
"[rast1.y]",
"[rast1.val]",
"[rast1]",
"[rast2.x]",
"[rast2.y]",
"[rast2.val]",
"[rast2]"};
6257 SPITupleTable *tuptable = NULL;
6260 bool isnull =
FALSE;
6261 int hasargval[3] = {0};
6262 double argval[3] = {0.};
6263 int hasnodatanodataval = 0;
6264 double nodatanodataval = 0;
6267 Oid ufc_noid = InvalidOid;
6269 #if POSTGIS_PGSQL_VERSION < 120
6270 FunctionCallInfoData ufc_info;
6272 LOCAL_FCINFO(ufc_info, FUNC_MAX_ARGS);
6274 int ufc_nullcount = 0;
6290 for (i = 0, j = 0; i < set_count; i++) {
6291 if (!PG_ARGISNULL(j)) {
6292 pgrast[i] = (
rt_pgraster *) PG_DETOAST_DATUM(PG_GETARG_DATUM(j));
6299 for (k = 0; k <= i; k++) {
6300 if (k < i &&
rast[k] != NULL)
6302 if (pgrastpos[k] != -1)
6303 PG_FREE_IF_COPY(pgrast[k], pgrastpos[k]);
6305 elog(ERROR,
"RASTER_mapAlgebra2: Could not deserialize the %s raster", i < 1 ?
"first" :
"second");
6313 if (!PG_ARGISNULL(j)) {
6314 bandindex[i] = PG_GETARG_INT32(j);
6327 if (
rast[0] == NULL &&
rast[1] == NULL) {
6328 elog(NOTICE,
"The two rasters provided are NULL. Returning NULL");
6329 for (k = 0; k < set_count; k++) {
6330 if (pgrastpos[k] != -1)
6331 PG_FREE_IF_COPY(pgrast[k], pgrastpos[k]);
6337 if (_isempty[0] && _isempty[1]) {
6338 elog(NOTICE,
"The two rasters provided are empty. Returning empty raster");
6342 for (k = 0; k < set_count; k++) {
6343 if (
rast[k] != NULL)
6345 if (pgrastpos[k] != -1)
6346 PG_FREE_IF_COPY(pgrast[k], pgrastpos[k]);
6348 elog(ERROR,
"RASTER_mapAlgebra2: Could not create empty raster");
6358 SET_VARSIZE(pgrtn, pgrtn->
size);
6359 PG_RETURN_POINTER(pgrtn);
6364 (
rast[0] == NULL || _isempty[0]) ||
6365 (
rast[1] == NULL || _isempty[1])
6368 if (
rast[0] == NULL || _isempty[0]) {
6381 if (_rast[i] != NULL)
6393 if (_rast[i] == NULL) {
6395 for (k = 0; k < set_count; k++) {
6396 if (pgrastpos[k] != -1)
6397 PG_FREE_IF_COPY(pgrast[k], pgrastpos[k]);
6399 elog(ERROR,
"RASTER_mapAlgebra2: Could not create NODATA raster");
6433 for (k = 0; k < set_count; k++) {
6434 if (_rast[k] != NULL)
6436 if (pgrastpos[k] != -1)
6437 PG_FREE_IF_COPY(pgrast[k], pgrastpos[k]);
6439 elog(ERROR,
"RASTER_mapAlgebra2: Could not test for alignment on the two rasters");
6443 elog(NOTICE,
"The two rasters provided do not have the same alignment. Returning NULL");
6444 for (k = 0; k < set_count; k++) {
6445 if (_rast[k] != NULL)
6447 if (pgrastpos[k] != -1)
6448 PG_FREE_IF_COPY(pgrast[k], pgrastpos[k]);
6454 if (!PG_ARGISNULL(5)) {
6455 pixtypename = text_to_cstring(PG_GETARG_TEXT_P(5));
6458 if (pixtype ==
PT_END ) {
6459 for (k = 0; k < set_count; k++) {
6460 if (_rast[k] != NULL)
6462 if (pgrastpos[k] != -1)
6463 PG_FREE_IF_COPY(pgrast[k], pgrastpos[k]);
6465 elog(ERROR,
"RASTER_mapAlgebra2: Invalid pixel type: %s", pixtypename);
6471 if (!PG_ARGISNULL(6)) {
6484 for (k = 0; k < set_count; k++) {
6485 if (_rast[k] != NULL)
6487 if (pgrastpos[k] != -1)
6488 PG_FREE_IF_COPY(pgrast[k], pgrastpos[k]);
6490 elog(ERROR,
"RASTER_mapAlgebra2: Could not get output raster of correct extent");
6495 _rastoffset[0][0] = _offset[0];
6496 _rastoffset[0][1] = _offset[1];
6497 _rastoffset[1][0] = _offset[2];
6498 _rastoffset[1][1] = _offset[3];
6506 switch (extenttype) {
6516 (extenttype ==
ET_FIRST && i == 0) ||
6520 elog(NOTICE,
"The %s raster is NULL. Returning NULL", (i != 1 ?
"FIRST" :
"SECOND"));
6521 for (k = 0; k < set_count; k++) {
6522 if (_rast[k] != NULL)
6524 if (pgrastpos[k] != -1)
6525 PG_FREE_IF_COPY(pgrast[k], pgrastpos[k]);
6533 elog(NOTICE,
"The %s raster does not have the band at index %d. Returning no band raster of correct extent",
6534 (i != 1 ?
"FIRST" :
"SECOND"), bandindex[i]
6537 for (k = 0; k < set_count; k++) {
6538 if (_rast[k] != NULL)
6540 if (pgrastpos[k] != -1)
6541 PG_FREE_IF_COPY(pgrast[k], pgrastpos[k]);
6546 if (!pgrtn) PG_RETURN_NULL();
6548 SET_VARSIZE(pgrtn, pgrtn->
size);
6549 PG_RETURN_POINTER(pgrtn);
6557 _isempty[0] || _isempty[1] ||
6560 elog(NOTICE,
"The two rasters provided have no intersection. Returning no band raster");
6563 if (dim[0] || dim[1]) {
6568 for (k = 0; k < set_count; k++) {
6569 if (_rast[k] != NULL)
6571 if (pgrastpos[k] != -1)
6572 PG_FREE_IF_COPY(pgrast[k], pgrastpos[k]);
6574 elog(ERROR,
"RASTER_mapAlgebra2: Could not create no band raster");
6582 for (k = 0; k < set_count; k++) {
6583 if (_rast[k] != NULL)
6585 if (pgrastpos[k] != -1)
6586 PG_FREE_IF_COPY(pgrast[k], pgrastpos[k]);
6591 if (!pgrtn) PG_RETURN_NULL();
6593 SET_VARSIZE(pgrtn, pgrtn->
size);
6594 PG_RETURN_POINTER(pgrtn);
6599 for (k = 0; k < set_count; k++) {
6600 if (_rast[k] != NULL)
6602 if (pgrastpos[k] != -1)
6603 PG_FREE_IF_COPY(pgrast[k], pgrastpos[k]);
6605 elog(ERROR,
"RASTER_mapAlgebra2: ET_LAST and ET_CUSTOM are not implemented");
6615 elog(NOTICE,
"The two rasters provided do not have the respectively specified band indices. Returning no band raster of correct extent");
6617 for (k = 0; k < set_count; k++) {
6618 if (_rast[k] != NULL)
6620 if (pgrastpos[k] != -1)
6621 PG_FREE_IF_COPY(pgrast[k], pgrastpos[k]);
6626 if (!pgrtn) PG_RETURN_NULL();
6628 SET_VARSIZE(pgrtn, pgrtn->
size);
6629 PG_RETURN_POINTER(pgrtn);
6633 for (i = 0; i < set_count; i++) {
6642 if (_band[i] == NULL) {
6643 for (k = 0; k < set_count; k++) {
6644 if (_rast[k] != NULL)
6646 if (pgrastpos[k] != -1)
6647 PG_FREE_IF_COPY(pgrast[k], pgrastpos[k]);
6650 elog(ERROR,
"RASTER_mapAlgebra2: Could not get band %d of the %s raster",
6652 (i < 1 ?
"FIRST" :
"SECOND")
6664 if ((extenttype ==
ET_SECOND && !_isempty[1]) || _isempty[0])
6671 if (extenttype ==
ET_SECOND && !_isempty[1] && _hasnodata[1]) {
6672 nodataval = _nodataval[1];
6674 else if (!_isempty[0] && _hasnodata[0]) {
6675 nodataval = _nodataval[0];
6677 else if (!_isempty[1] && _hasnodata[1]) {
6678 nodataval = _nodataval[1];
6681 elog(NOTICE,
"Neither raster provided has a NODATA value for the specified band indices. NODATA value set to minimum possible for %s",
rt_pixtype_name(pixtype));
6693 for (k = 0; k < set_count; k++) {
6694 if (_rast[k] != NULL)
6696 if (pgrastpos[k] != -1)
6697 PG_FREE_IF_COPY(pgrast[k], pgrastpos[k]);
6700 elog(ERROR,
"RASTER_mapAlgebra2: Could not add new band to output raster");
6707 for (k = 0; k < set_count; k++) {
6708 if (_rast[k] != NULL)
6710 if (pgrastpos[k] != -1)
6711 PG_FREE_IF_COPY(pgrast[k], pgrastpos[k]);
6714 elog(ERROR,
"RASTER_mapAlgebra2: Could not get newly added band of output raster");
6719 (
int) _rastoffset[0][0],
6720 (
int) _rastoffset[0][1],
6721 (
int) _rastoffset[1][0],
6722 (
int) _rastoffset[1][1]
6725 POSTGIS_RT_DEBUGF(4,
"metadata = (%f, %f, %d, %d, %f, %f, %f, %f, %d)",
6742 calltype = get_fn_expr_argtype(fcinfo->flinfo, 4);
6749 if (SPI_connect() != SPI_OK_CONNECT) {
6750 for (k = 0; k < set_count; k++) {
6751 if (_rast[k] != NULL)
6753 if (pgrastpos[k] != -1)
6754 PG_FREE_IF_COPY(pgrast[k], pgrastpos[k]);
6757 elog(ERROR,
"RASTER_mapAlgebra2: Could not connect to the SPI manager");
6762 memset(hasargval, 0,
sizeof(
int) * spi_count);
6772 for (i = 0; i < spi_count; i++) {
6773 if (!PG_ARGISNULL(spi_exprpos[i])) {
6775 char place[5] =
"$1";
6776 expr = text_to_cstring(PG_GETARG_TEXT_P(spi_exprpos[i]));
6790 sprintf(place,
"$%d", k);
6796 len = strlen(
"SELECT (") + strlen(expr) + strlen(
")::double precision");
6797 sql = (
char *) palloc(len + 1);
6800 for (k = 0; k < spi_count; k++) SPI_freeplan(spi_plan[k]);
6803 for (k = 0; k < set_count; k++) {
6804 if (_rast[k] != NULL)
6806 if (pgrastpos[k] != -1)
6807 PG_FREE_IF_COPY(pgrast[k], pgrastpos[k]);
6811 elog(ERROR,
"RASTER_mapAlgebra2: Could not allocate memory for expression parameter %d", spi_exprpos[i]);
6815 memcpy(
sql,
"SELECT (", strlen(
"SELECT ("));
6816 memcpy(
sql + strlen(
"SELECT ("), expr, strlen(expr));
6817 memcpy(
sql + strlen(
"SELECT (") + strlen(expr),
")::double precision", strlen(
")::double precision"));
6823 if (spi_argcount[i]) {
6824 argtype = (Oid *) palloc(spi_argcount[i] *
sizeof(Oid));
6825 if (argtype == NULL) {
6828 for (k = 0; k < spi_count; k++) SPI_freeplan(spi_plan[k]);
6831 for (k = 0; k < set_count; k++) {
6832 if (_rast[k] != NULL)
6834 if (pgrastpos[k] != -1)
6835 PG_FREE_IF_COPY(pgrast[k], pgrastpos[k]);
6839 elog(ERROR,
"RASTER_mapAlgebra2: Could not allocate memory for prepared plan argtypes of expression parameter %d", spi_exprpos[i]);
6845 if (argpos[i][j] < 1)
continue;
6849 (strstr(argkw[j],
"[rast1.x]") != NULL) ||
6850 (strstr(argkw[j],
"[rast1.y]") != NULL) ||
6851 (strstr(argkw[j],
"[rast2.x]") != NULL) ||
6852 (strstr(argkw[j],
"[rast2.y]") != NULL)
6854 argtype[k] = INT4OID;
6858 argtype[k] = FLOAT8OID;
6864 spi_plan[i] = SPI_prepare(
sql, spi_argcount[i], argtype);
6867 if (spi_plan[i] == NULL) {
6870 for (k = 0; k < spi_count; k++) SPI_freeplan(spi_plan[k]);
6873 for (k = 0; k < set_count; k++) {
6874 if (_rast[k] != NULL)
6876 if (pgrastpos[k] != -1)
6877 PG_FREE_IF_COPY(pgrast[k], pgrastpos[k]);
6881 elog(ERROR,
"RASTER_mapAlgebra2: Could not create prepared plan of expression parameter %d", spi_exprpos[i]);
6887 err = SPI_execute(
sql,
TRUE, 0);
6888 if (err != SPI_OK_SELECT || SPI_tuptable == NULL || SPI_processed != 1) {
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 evaluate expression parameter %d", spi_exprpos[i]);
6907 tupdesc = SPI_tuptable->tupdesc;
6908 tuptable = SPI_tuptable;
6909 tuple = tuptable->vals[0];
6911 datum = SPI_getbinval(tuple, tupdesc, 1, &isnull);
6912 if (SPI_result == SPI_ERROR_NOATTRIBUTE) {
6915 if (SPI_tuptable) SPI_freetuptable(tuptable);
6916 for (k = 0; k < spi_count; k++) SPI_freeplan(spi_plan[k]);
6919 for (k = 0; k < set_count; k++) {
6920 if (_rast[k] != NULL)
6922 if (pgrastpos[k] != -1)
6923 PG_FREE_IF_COPY(pgrast[k], pgrastpos[k]);
6927 elog(ERROR,
"RASTER_mapAlgebra2: Could not get result of expression parameter %d", spi_exprpos[i]);
6933 argval[i] = DatumGetFloat8(datum);
6936 if (SPI_tuptable) SPI_freetuptable(tuptable);
6946 if (!PG_ARGISNULL(9)) {
6947 hasnodatanodataval = 1;
6948 nodatanodataval = PG_GETARG_FLOAT8(9);
6951 hasnodatanodataval = 0;
6954 case REGPROCEDUREOID: {
6956 if (!PG_ARGISNULL(4)) {
6959 ufc_noid = PG_GETARG_OID(4);
6962 fmgr_info(ufc_noid, &ufl_info);
6966 if (ufl_info.fn_retset) {
6970 else if (ufl_info.fn_nargs < 3 || ufl_info.fn_nargs > 4) {
6980 for (k = 0; k < set_count; k++) {
6981 if (_rast[k] != NULL)
6983 if (pgrastpos[k] != -1)
6984 PG_FREE_IF_COPY(pgrast[k], pgrastpos[k]);
6989 elog(ERROR,
"RASTER_mapAlgebra2: Function provided must have three or four input parameters");
6991 elog(ERROR,
"RASTER_mapAlgebra2: Function provided must return double precision not resultset");
6995 if (func_volatile(ufc_noid) ==
'v') {
6996 elog(NOTICE,
"Function provided is VOLATILE. Unless required and for best performance, function should be IMMUTABLE or STABLE");
7000 #if POSTGIS_PGSQL_VERSION < 120
7001 InitFunctionCallInfoData(ufc_info, &ufl_info, ufl_info.fn_nargs, InvalidOid, NULL, NULL);
7002 memset(ufc_info.argnull,
FALSE,
sizeof(
bool) * ufl_info.fn_nargs);
7004 InitFunctionCallInfoData(
7005 *ufc_info, &ufl_info, ufl_info.fn_nargs, InvalidOid, NULL, NULL);
7006 ufc_info->args[0].isnull =
FALSE;
7007 ufc_info->args[1].isnull =
FALSE;
7008 ufc_info->args[2].isnull =
FALSE;
7009 if (ufl_info.fn_nargs == 4)
7010 ufc_info->args[3].isnull =
FALSE;
7013 if (ufl_info.fn_nargs != 4)
7017 #if POSTGIS_PGSQL_VERSION < 120
7018 if (!PG_ARGISNULL(7)) {
7019 ufc_info.arg[k] = PG_GETARG_DATUM(7);
7022 ufc_info.arg[k] = (Datum) NULL;
7023 ufc_info.argnull[k] =
TRUE;
7027 if (!PG_ARGISNULL(7))
7029 ufc_info->args[k].value = PG_GETARG_DATUM(7);
7033 ufc_info->args[k].value = (Datum)NULL;
7034 ufc_info->args[k].isnull =
TRUE;
7042 for (k = 0; k < set_count; k++) {
7043 if (_rast[k] != NULL)
7045 if (pgrastpos[k] != -1)
7046 PG_FREE_IF_COPY(pgrast[k], pgrastpos[k]);
7049 elog(ERROR,
"RASTER_mapAlgebra2: Invalid data type for expression or userfunction");
7057 (calltype == TEXTOID) && (
7058 (spi_empty != spi_count) || hasnodatanodataval
7061 (calltype == REGPROCEDUREOID) && (ufc_noid != InvalidOid)
7063 for (
x = 0;
x < dim[0];
x++) {
7064 for (
y = 0;
y < dim[1];
y++) {
7067 for (i = 0; i < set_count; i++) {
7072 _x = (int)
x - (
int)_rastoffset[i][0];
7073 _y = (int)
y - (
int)_rastoffset[i][1];
7076 _pos[i][0] = _x + 1;
7077 _pos[i][1] = _y + 1;
7080 if (_band[i] == NULL) {
7081 if (!_hasnodata[i]) {
7083 _pixel[i] = _nodataval[i];
7088 (_x >= 0 && _x < _dim[i][0]) &&
7089 (_y >= 0 && _y < _dim[i][1])
7094 if (calltype == TEXTOID) {
7095 for (k = 0; k < spi_count; k++) SPI_freeplan(spi_plan[k]);
7099 for (k = 0; k < set_count; k++) {
7100 if (_rast[k] != NULL)
7102 if (pgrastpos[k] != -1)
7103 PG_FREE_IF_COPY(pgrast[k], pgrastpos[k]);
7107 elog(ERROR,
"RASTER_mapAlgebra2: Could not get pixel of %s raster", (i < 1 ?
"FIRST" :
"SECOND"));
7111 if (!_hasnodata[i] || !isnodata)
7130 if (!_haspixel[0] && !_haspixel[1])
7134 else if (_haspixel[0] && !_haspixel[1])
7138 else if (!_haspixel[0] && _haspixel[1])
7147 if (hasnodatanodataval) {
7149 pixel = nodatanodataval;
7153 else if (hasargval[i]) {
7158 else if (spi_plan[i] != NULL) {
7162 memset(values, (Datum) NULL,
sizeof(Datum) *
ARGKWCOUNT);
7167 if (spi_argcount[i]) {
7171 if (idx < 1)
continue;
7174 if (strstr(argkw[j],
"[rast1.x]") != NULL) {
7175 values[idx] = _pos[0][0];
7177 else if (strstr(argkw[j],
"[rast1.y]") != NULL) {
7178 values[idx] = _pos[0][1];
7181 (strstr(argkw[j],
"[rast1.val]") != NULL) ||
7182 (strstr(argkw[j],
"[rast1]") != NULL)
7184 if (_isempty[0] || !_haspixel[0])
7187 values[idx] = Float8GetDatum(_pixel[0]);
7189 else if (strstr(argkw[j],
"[rast2.x]") != NULL) {
7190 values[idx] = _pos[1][0];
7192 else if (strstr(argkw[j],
"[rast2.y]") != NULL) {
7193 values[idx] = _pos[1][1];
7196 (strstr(argkw[j],
"[rast2.val]") != NULL) ||
7197 (strstr(argkw[j],
"[rast2]") != NULL)
7199 if (_isempty[1] || !_haspixel[1])
7202 values[idx] = Float8GetDatum(_pixel[1]);
7208 err = SPI_execute_plan(spi_plan[i], values, nulls,
TRUE, 1);
7209 if (err != SPI_OK_SELECT || SPI_tuptable == NULL || SPI_processed != 1) {
7211 for (k = 0; k < spi_count; k++) SPI_freeplan(spi_plan[k]);
7214 for (k = 0; k < set_count; k++) {
7215 if (_rast[k] != NULL)
7217 if (pgrastpos[k] != -1)
7218 PG_FREE_IF_COPY(pgrast[k], pgrastpos[k]);
7222 elog(ERROR,
"RASTER_mapAlgebra2: Unexpected error when running prepared statement %d", i);
7227 tupdesc = SPI_tuptable->tupdesc;
7228 tuptable = SPI_tuptable;
7229 tuple = tuptable->vals[0];
7231 datum = SPI_getbinval(tuple, tupdesc, 1, &isnull);
7232 if (SPI_result == SPI_ERROR_NOATTRIBUTE) {
7234 if (SPI_tuptable) SPI_freetuptable(tuptable);
7235 for (k = 0; k < spi_count; k++) SPI_freeplan(spi_plan[k]);
7238 for (k = 0; k < set_count; k++) {
7239 if (_rast[k] != NULL)
7241 if (pgrastpos[k] != -1)
7242 PG_FREE_IF_COPY(pgrast[k], pgrastpos[k]);
7246 elog(ERROR,
"RASTER_mapAlgebra2: Could not get result of prepared statement %d", i);
7252 pixel = DatumGetFloat8(datum);
7255 if (SPI_tuptable) SPI_freetuptable(tuptable);
7258 case REGPROCEDUREOID: {
7263 for (i = 0; i < set_count; i++) {
7264 #if POSTGIS_PGSQL_VERSION < 120
7265 ufc_info.arg[i] = Float8GetDatum(_pixel[i]);
7267 ufc_info->args[i].value = Float8GetDatum(_pixel[i]);
7271 #if POSTGIS_PGSQL_VERSION < 120
7272 ufc_info.argnull[i] =
FALSE;
7274 ufc_info->args[i].isnull =
FALSE;
7279 #if POSTGIS_PGSQL_VERSION < 120
7280 ufc_info.argnull[i] =
TRUE;
7282 ufc_info->args[i].isnull =
TRUE;
7290 if (ufl_info.fn_strict && ufc_nullcount)
7294 if (ufl_info.fn_nargs == 4) {
7297 for (i = 0; i < set_count; i++) {
7299 d[0] = Int32GetDatum(_pos[i][0]);
7300 d[1] = Int32GetDatum(_pos[i][1]);
7303 d[2] = Int32GetDatum(_pos[i][0]);
7304 d[3] = Int32GetDatum(_pos[i][1]);
7308 a = construct_array(d, 4, INT4OID,
sizeof(
int32),
true,
'i');
7309 #if POSTGIS_PGSQL_VERSION < 120
7310 ufc_info.arg[2] = PointerGetDatum(a);
7311 ufc_info.argnull[2] =
FALSE;
7313 ufc_info->args[2].value = PointerGetDatum(a);
7314 ufc_info->args[2].isnull =
FALSE;
7318 #if POSTGIS_PGSQL_VERSION < 120
7319 datum = FunctionCallInvoke(&ufc_info);
7322 if (!ufc_info.isnull) {
7324 pixel = DatumGetFloat8(datum);
7327 datum = FunctionCallInvoke(ufc_info);
7330 if (!ufc_info->isnull)
7333 pixel = DatumGetFloat8(datum);
7343 if (calltype == TEXTOID) {
7344 for (k = 0; k < spi_count; k++) SPI_freeplan(spi_plan[k]);
7348 for (k = 0; k < set_count; k++) {
7349 if (_rast[k] != NULL)
7351 if (pgrastpos[k] != -1)
7352 PG_FREE_IF_COPY(pgrast[k], pgrastpos[k]);
7356 elog(ERROR,
"RASTER_mapAlgebra2: Could not set pixel value of output raster");
7368 if (calltype == TEXTOID) {
7369 for (i = 0; i < spi_count; i++) {
7370 if (spi_plan[i] != NULL) SPI_freeplan(spi_plan[i]);
7375 for (k = 0; k < set_count; k++) {
7376 if (_rast[k] != NULL)
7378 if (pgrastpos[k] != -1)
7379 PG_FREE_IF_COPY(pgrast[k], pgrastpos[k]);
7384 if (!pgrtn) PG_RETURN_NULL();
7388 SET_VARSIZE(pgrtn, pgrtn->
size);
7389 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_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)
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
union rtpg_nmapalgebra_callback_arg::@21 ufc_info_data
FunctionCallInfo ufc_info
FunctionCallInfoBaseData fcinfo
rtpg_nmapalgebraexpr_callback_arg callback
rtpg_nmapalgebra_arg bandarg
struct rtpg_nmapalgebraexpr_callback_arg::@24 kw
struct rtpg_nmapalgebraexpr_callback_arg::@23 nodatanodata
struct rtpg_nmapalgebraexpr_callback_arg::@22 expr[3]
rtpg_union_band_arg bandarg
rtpg_union_type uniontype