32 #include "utils/lsyscache.h"
34 #include "utils/array.h"
35 #include "utils/builtins.h"
36 #include "utils/formatting.h"
37 #include "catalog/pg_type.h"
39 #include "../../postgis_config.h"
40 #include "lwgeom_pg.h"
44 #include "access/htup_details.h"
83 int32_t bandindex = 0;
87 bool exclude_nodata_value =
TRUE;
91 bandindex = PG_GETARG_INT32(1);
92 if ( bandindex < 1 ) {
93 elog(NOTICE,
"Invalid band index (must use 1-based). Returning NULL");
97 x = PG_GETARG_INT32(2);
99 y = PG_GETARG_INT32(3);
101 exclude_nodata_value = PG_GETARG_BOOL(4);
106 if (PG_ARGISNULL(0)) PG_RETURN_NULL();
107 pgraster = (
rt_pgraster *)PG_DETOAST_DATUM(PG_GETARG_DATUM(0));
111 PG_FREE_IF_COPY(pgraster, 0);
112 elog(ERROR,
"RASTER_getPixelValue: Could not deserialize raster");
119 elog(NOTICE,
"Could not find raster band of index %d when getting pixel "
120 "value. Returning NULL", bandindex);
122 PG_FREE_IF_COPY(pgraster, 0);
130 if (
result !=
ES_NONE || (exclude_nodata_value && isnodata)) {
132 PG_FREE_IF_COPY(pgraster, 0);
137 PG_FREE_IF_COPY(pgraster, 0);
139 PG_RETURN_FLOAT8(pixvalue);
144 char *resample = asc_tolower(VARDATA(txt), VARSIZE_ANY_EXHDR(txt));
145 if (strncmp(resample,
"bilinear", 8) == 0)
147 else if (strncmp(resample,
"nearest", 7) == 0)
150 elog(ERROR,
"Unknown resample type '%s' requested", resample);
170 int32_t bandnum = PG_GETARG_INT32(1);
174 bool exclude_nodata_value = PG_GETARG_BOOL(3);
177 double pixvalue = 0.0;
183 elog(NOTICE,
"Invalid band index (must use 1-based). Returning NULL");
187 gser = (
GSERIALIZED*)PG_DETOAST_DATUM(PG_GETARG_DATUM(2));
189 elog(ERROR,
"Attempting to get the value of a pixel with a non-point geometry");
195 elog(ERROR,
"RASTER_getPixelValue: Could not deserialize raster");
200 elog(ERROR,
"Raster and geometry do not have the same SRID");
204 if (PG_NARGS() > 4) {
205 text *resample_text = PG_GETARG_TEXT_P(4);
212 elog(ERROR,
"Could not find raster band of index %d when getting pixel "
213 "value. Returning NULL", bandnum);
226 elog(ERROR,
"Could not convert world coordinate to raster coordinate");
242 if (err !=
ES_NONE || (exclude_nodata_value && isnodata)) {
245 PG_RETURN_FLOAT8(pixvalue);
263 LWGEOM *lwgeom_in, *lwgeom_out;
267 const char *func_name;
271 text *resample_text = PG_GETARG_TEXT_P(2);
275 func_name = get_func_name(fcinfo->flinfo->fn_oid);
276 if (strcmp(func_name,
"st_setz") == 0)
278 else if (strcmp(func_name,
"st_setm") == 0)
281 elog(ERROR,
"%s called from unexpected SQL signature", __func__);
284 gser = (
GSERIALIZED*)PG_DETOAST_DATUM(PG_GETARG_DATUM(1));
286 elog(ERROR,
"Cannot copy value into an empty geometry");
291 pgraster = (
rt_pgraster *)PG_DETOAST_DATUM(PG_GETARG_DATUM(0));
295 elog(ERROR,
"Could not deserialize raster");
300 band = PG_GETARG_INT32(3);
301 if (band < 1 || band > num_bands) {
302 elog(NOTICE,
"Invalid band index %d. Must be between 1 and %u",
band, num_bands);
308 elog(ERROR,
"Raster and geometry do not have the same SRID");
330 if (err !=
ES_NONE || !lwgeom_out) {
357 elog(ERROR,
"rtpg_dumpvalues_arg_init: Could not allocate memory for arguments");
379 if (arg->
values != NULL) {
380 for (i = 0; i < arg->
numbands; i++) {
382 if (arg->
values[i] != NULL)
385 if (arg->
nodata[i] != NULL)
399 #define VALUES_LENGTH 2
404 FuncCallContext *funcctx;
421 if (SRF_IS_FIRSTCALL()) {
422 MemoryContext oldcontext;
428 bool exclude_nodata_value =
TRUE;
441 funcctx = SRF_FIRSTCALL_INIT();
444 oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);
447 if (PG_ARGISNULL(0)) {
448 MemoryContextSwitchTo(oldcontext);
449 SRF_RETURN_DONE(funcctx);
451 pgraster = (
rt_pgraster *) PG_DETOAST_DATUM(PG_GETARG_DATUM(0));
455 PG_FREE_IF_COPY(pgraster, 0);
457 errcode(ERRCODE_OUT_OF_MEMORY),
458 errmsg(
"Could not deserialize raster")
460 MemoryContextSwitchTo(oldcontext);
461 SRF_RETURN_DONE(funcctx);
478 elog(NOTICE,
"Raster provided has no bands");
480 PG_FREE_IF_COPY(pgraster, 0);
481 MemoryContextSwitchTo(oldcontext);
482 SRF_RETURN_DONE(funcctx);
489 PG_FREE_IF_COPY(pgraster, 0);
490 MemoryContextSwitchTo(oldcontext);
491 elog(ERROR,
"RASTER_dumpValues: Could not initialize argument structure");
492 SRF_RETURN_DONE(funcctx);
496 if (!PG_ARGISNULL(1)) {
497 array = PG_GETARG_ARRAYTYPE_P(1);
498 etype = ARR_ELEMTYPE(array);
499 get_typlenbyvalalign(etype, &typlen, &typbyval, &typalign);
508 PG_FREE_IF_COPY(pgraster, 0);
509 MemoryContextSwitchTo(oldcontext);
510 elog(ERROR,
"RASTER_dumpValues: Invalid data type for band indexes");
511 SRF_RETURN_DONE(funcctx);
515 deconstruct_array(array, etype, typlen, typbyval, typalign, &e, &nulls, &(arg1->
numbands));
518 if (arg1->
nbands == NULL) {
521 PG_FREE_IF_COPY(pgraster, 0);
522 MemoryContextSwitchTo(oldcontext);
523 elog(ERROR,
"RASTER_dumpValues: Could not allocate memory for band indexes");
524 SRF_RETURN_DONE(funcctx);
527 for (i = 0, j = 0; i < arg1->
numbands; i++) {
528 if (nulls[i])
continue;
532 arg1->
nbands[j] = DatumGetInt16(e[i]) - 1;
535 arg1->
nbands[j] = DatumGetInt32(e[i]) - 1;
542 if (j < arg1->numbands) {
544 if (arg1->
nbands == NULL) {
547 PG_FREE_IF_COPY(pgraster, 0);
548 MemoryContextSwitchTo(oldcontext);
549 elog(ERROR,
"RASTER_dumpValues: Could not reallocate memory for band indexes");
550 SRF_RETURN_DONE(funcctx);
557 for (i = 0; i < arg1->
numbands; i++) {
559 elog(NOTICE,
"Band at index %d not found in raster", arg1->
nbands[i] + 1);
562 PG_FREE_IF_COPY(pgraster, 0);
563 MemoryContextSwitchTo(oldcontext);
564 SRF_RETURN_DONE(funcctx);
574 if (arg1->
nbands == NULL) {
577 PG_FREE_IF_COPY(pgraster, 0);
578 MemoryContextSwitchTo(oldcontext);
579 elog(ERROR,
"RASTER_dumpValues: Could not allocate memory for band indexes");
580 SRF_RETURN_DONE(funcctx);
583 for (i = 0; i < arg1->
numbands; i++) {
593 if (!PG_ARGISNULL(2))
594 exclude_nodata_value = PG_GETARG_BOOL(2);
603 PG_FREE_IF_COPY(pgraster, 0);
604 MemoryContextSwitchTo(oldcontext);
605 elog(ERROR,
"RASTER_dumpValues: Could not allocate memory for pixel values");
606 SRF_RETURN_DONE(funcctx);
612 for (z = 0; z < arg1->
numbands; z++) {
622 PG_FREE_IF_COPY(pgraster, 0);
623 MemoryContextSwitchTo(oldcontext);
624 elog(ERROR,
"RASTER_dumpValues: Could not get band at index %d",
nband);
625 SRF_RETURN_DONE(funcctx);
631 if (arg1->
values[z] == NULL || arg1->
nodata[z] == NULL) {
634 PG_FREE_IF_COPY(pgraster, 0);
635 MemoryContextSwitchTo(oldcontext);
636 elog(ERROR,
"RASTER_dumpValues: Could not allocate memory for pixel values");
637 SRF_RETURN_DONE(funcctx);
646 for (i = (arg1->
rows * arg1->
columns) - 1; i >= 0; i--)
651 for (
y = 0;
y < arg1->
rows;
y++) {
658 PG_FREE_IF_COPY(pgraster, 0);
659 MemoryContextSwitchTo(oldcontext);
660 elog(ERROR,
"RASTER_dumpValues: Could not pixel (%d, %d) of band %d",
x,
y,
nband);
661 SRF_RETURN_DONE(funcctx);
664 arg1->
values[z][i] = Float8GetDatum(val);
668 if (exclude_nodata_value && isnodata) {
682 PG_FREE_IF_COPY(pgraster, 0);
685 funcctx->user_fctx = arg1;
688 funcctx->max_calls = arg1->
numbands;
691 if (get_call_result_type(fcinfo, NULL, &tupdesc) != TYPEFUNC_COMPOSITE) {
692 MemoryContextSwitchTo(oldcontext);
694 errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
696 "function returning record called in context "
697 "that cannot accept type record"
702 BlessTupleDesc(tupdesc);
703 funcctx->tuple_desc = tupdesc;
705 MemoryContextSwitchTo(oldcontext);
709 funcctx = SRF_PERCALL_SETUP();
711 call_cntr = funcctx->call_cntr;
712 max_calls = funcctx->max_calls;
713 tupdesc = funcctx->tuple_desc;
714 arg2 = funcctx->user_fctx;
717 if (call_cntr < max_calls) {
722 ArrayType *mdValues = NULL;
725 int lbound[2] = {1, 1};
732 values[0] = Int32GetDatum(arg2->
nbands[call_cntr] + 1);
735 get_typlenbyvalalign(FLOAT8OID, &typlen, &typbyval, &typalign);
738 if (arg2->
values[call_cntr] == NULL)
742 mdValues = construct_md_array(
746 typlen, typbyval, typalign
748 values[1] = PointerGetDatum(mdValues);
751 tuple = heap_form_tuple(tupdesc, values, nulls);
752 result = HeapTupleGetDatum(tuple);
754 SRF_RETURN_NEXT(funcctx,
result);
759 SRF_RETURN_DONE(funcctx);
774 int32_t bandindex = 0;
777 bool skipset =
FALSE;
786 bandindex = PG_GETARG_INT32(1);
789 elog(NOTICE,
"Invalid band index (must use 1-based). Value not set. Returning original raster");
794 if (PG_ARGISNULL(2)) {
795 elog(NOTICE,
"X coordinate can not be NULL when setting pixel value. Value not set. Returning original raster");
799 x = PG_GETARG_INT32(2);
801 if (PG_ARGISNULL(3)) {
802 elog(NOTICE,
"Y coordinate can not be NULL when setting pixel value. Value not set. Returning original raster");
806 y = PG_GETARG_INT32(3);
811 pgraster = (
rt_pgraster *) PG_DETOAST_DATUM_COPY(PG_GETARG_DATUM(0));
815 PG_FREE_IF_COPY(pgraster, 0);
816 elog(ERROR,
"RASTER_setPixelValue: Could not deserialize raster");
824 elog(NOTICE,
"Could not find raster band of index %d when setting "
825 "pixel value. Value not set. Returning original raster",
827 PG_RETURN_POINTER(pgraster);
831 if (PG_ARGISNULL(4)) {
833 elog(NOTICE,
"Raster do not have a nodata value defined. "
834 "Set band nodata value first. Nodata value not set. "
835 "Returning original raster");
836 PG_RETURN_POINTER(pgraster);
844 pixvalue = PG_GETARG_FLOAT8(4);
852 PG_FREE_IF_COPY(pgraster, 0);
856 SET_VARSIZE(pgrtn, pgrtn->
size);
857 PG_RETURN_POINTER(pgrtn);
896 struct pixelvalue *
pixval = NULL;
898 int dimpixval[2] = {1, 1};
899 int dimnoset[2] = {1, 1};
900 int hasnodata =
FALSE;
901 double nodataval = 0;
902 bool keepnodata =
FALSE;
903 bool hasnosetval =
FALSE;
904 bool nosetvalisnull =
FALSE;
919 pgraster = (
rt_pgraster *) PG_DETOAST_DATUM_COPY(PG_GETARG_DATUM(0));
924 PG_FREE_IF_COPY(pgraster, 0);
925 elog(ERROR,
"RASTER_setPixelValuesArray: Could not deserialize raster");
935 if (PG_ARGISNULL(1)) {
936 elog(NOTICE,
"Band index cannot be NULL. Value must be 1-based. Returning original raster");
938 PG_RETURN_POINTER(pgraster);
941 nband = PG_GETARG_INT32(1);
942 if (nband < 1 || nband > numbands) {
943 elog(NOTICE,
"Band index is invalid. Value must be 1-based. Returning original raster");
945 PG_RETURN_POINTER(pgraster);
949 for (i = 2, j = 0; i < 4; i++, j++) {
950 if (PG_ARGISNULL(i)) {
951 elog(NOTICE,
"%s cannot be NULL. Value must be 1-based. Returning original raster", j < 1 ?
"X" :
"Y");
953 PG_RETURN_POINTER(pgraster);
956 ul[j] = PG_GETARG_INT32(i);
959 (j < 1 && ul[j] > width) ||
960 (j > 0 && ul[j] > height)
963 elog(NOTICE,
"%s is invalid. Value must be 1-based. Returning original raster", j < 1 ?
"X" :
"Y");
965 PG_RETURN_POINTER(pgraster);
973 if (PG_ARGISNULL(4)) {
974 elog(NOTICE,
"No values to set. Returning original raster");
976 PG_RETURN_POINTER(pgraster);
979 array = PG_GETARG_ARRAYTYPE_P(4);
980 etype = ARR_ELEMTYPE(array);
981 get_typlenbyvalalign(etype, &typlen, &typbyval, &typalign);
989 PG_FREE_IF_COPY(pgraster, 0);
990 elog(ERROR,
"RASTER_setPixelValuesArray: Invalid data type for new values");
995 ndims = ARR_NDIM(array);
996 dims = ARR_DIMS(array);
999 if (ndims < 1 || ndims > 2) {
1000 elog(NOTICE,
"New values array must be of 1 or 2 dimensions. Returning original raster");
1002 PG_RETURN_POINTER(pgraster);
1008 dimpixval[1] = dims[0];
1010 dimpixval[0] = dims[0];
1011 dimpixval[1] = dims[1];
1018 typlen, typbyval, typalign,
1019 &elements, &nulls, &num
1023 if (num < 1 || num != (dimpixval[0] * dimpixval[1])) {
1029 PG_FREE_IF_COPY(pgraster, 0);
1030 elog(ERROR,
"RASTER_setPixelValuesArray: Could not deconstruct new values array");
1036 pixval = palloc(
sizeof(
struct pixelvalue) * numpixval);
1041 PG_FREE_IF_COPY(pgraster, 0);
1042 elog(ERROR,
"RASTER_setPixelValuesArray: Could not allocate memory for new pixel values");
1048 for (
y = 0;
y < dimpixval[0];
y++) {
1049 for (
x = 0;
x < dimpixval[1];
x++) {
1063 pixval[i].value = DatumGetFloat4(elements[i]);
1066 pixval[i].value = DatumGetFloat8(elements[i]);
1079 if (!PG_ARGISNULL(5)) {
1080 array = PG_GETARG_ARRAYTYPE_P(5);
1081 etype = ARR_ELEMTYPE(array);
1082 get_typlenbyvalalign(etype, &typlen, &typbyval, &typalign);
1090 PG_FREE_IF_COPY(pgraster, 0);
1091 elog(ERROR,
"RASTER_setPixelValuesArray: Invalid data type for noset flags");
1096 ndims = ARR_NDIM(array);
1097 dims = ARR_DIMS(array);
1100 if (ndims < 1 || ndims > 2) {
1101 elog(NOTICE,
"Noset flags array must be of 1 or 2 dimensions. Returning original raster");
1104 PG_RETURN_POINTER(pgraster);
1110 dimnoset[1] = dims[0];
1112 dimnoset[0] = dims[0];
1113 dimnoset[1] = dims[1];
1120 typlen, typbyval, typalign,
1121 &elements, &nulls, &num
1125 if (num < 1 || num != (dimnoset[0] * dimnoset[1])) {
1132 PG_FREE_IF_COPY(pgraster, 0);
1133 elog(ERROR,
"RASTER_setPixelValuesArray: Could not deconstruct noset flags array");
1139 for (
y = 0;
y < dimnoset[0];
y++) {
1140 if (
y >= dimpixval[0])
break;
1142 for (
x = 0;
x < dimnoset[1];
x++) {
1144 if (
x >= dimpixval[1]) {
1145 i += (dimnoset[1] - dimpixval[1]);
1149 if (!nulls[i] && DatumGetBool(elements[i]))
1157 if (
x < dimpixval[1])
1158 j += (dimpixval[1] - dimnoset[1]);
1165 else if (!PG_ARGISNULL(6) && PG_GETARG_BOOL(6)) {
1167 if (PG_ARGISNULL(7))
1168 nosetvalisnull =
TRUE;
1170 nosetval = PG_GETARG_FLOAT8(7);
1173 #if POSTGIS_DEBUG_LEVEL > 0
1174 for (i = 0; i < numpixval; i++) {
1175 POSTGIS_RT_DEBUGF(4,
"pixval[%d](x, y, noset, nodata, value) = (%d, %d, %d, %d, %f)",
1187 if (!PG_ARGISNULL(8))
1188 keepnodata = PG_GETARG_BOOL(8);
1193 elog(NOTICE,
"Could not find band at index %d. Returning original raster",
nband);
1196 PG_RETURN_POINTER(pgraster);
1209 for (i = 0; i < numpixval; i++) {
1214 else if (hasnosetval) {
1216 if (
pixval[i].nodata && nosetvalisnull)
1228 elog(NOTICE,
"Cannot set value for pixel (%d, %d) outside raster bounds: %d x %d",
1236 if (hasnodata && keepnodata) {
1241 PG_FREE_IF_COPY(pgraster, 0);
1242 elog(ERROR,
"Cannot get value of pixel");
1263 PG_FREE_IF_COPY(pgraster, 0);
1267 SET_VARSIZE(pgrtn, pgrtn->
size);
1268 PG_RETURN_POINTER(pgrtn);
1298 elog(ERROR,
"rtpg_setvaluesgv_arg_init: Could not allocate memory for function arguments");
1312 if (arg->
gv != NULL) {
1313 for (i = 0; i < arg->
ngv; i++) {
1314 if (arg->
gv[i].
geom != NULL)
1316 if (arg->
gv[i].
mask != NULL)
1328 double *
value,
int *nodata
1346 for (i = arg->
rasters - 1, j = funcarg->
ngv - 1; i > 0; i--, j--) {
1350 if (arg->
nodata[i][0][0])
1368 if (arg->
nodata[0][0][0])
1395 double nodataval = 0;
1409 HeapTupleHeader tup;
1422 if (PG_ARGISNULL(0))
1424 pgraster = (
rt_pgraster *) PG_DETOAST_DATUM_COPY(PG_GETARG_DATUM(0));
1429 PG_FREE_IF_COPY(pgraster, 0);
1430 elog(ERROR,
"RASTER_setPixelValuesGeomval: Could not deserialize raster");
1442 if (PG_ARGISNULL(1)) {
1443 elog(NOTICE,
"Band index cannot be NULL. Value must be 1-based. Returning original raster");
1445 PG_RETURN_POINTER(pgraster);
1448 nband = PG_GETARG_INT32(1);
1449 if (nband < 1 || nband > numbands) {
1450 elog(NOTICE,
"Band index is invalid. Value must be 1-based. Returning original raster");
1452 PG_RETURN_POINTER(pgraster);
1463 if (PG_ARGISNULL(2)) {
1464 elog(NOTICE,
"No values to set. Returning original raster");
1466 PG_RETURN_POINTER(pgraster);
1469 array = PG_GETARG_ARRAYTYPE_P(2);
1470 etype = ARR_ELEMTYPE(array);
1471 get_typlenbyvalalign(etype, &typlen, &typbyval, &typalign);
1476 typlen, typbyval, typalign,
1481 elog(NOTICE,
"No values to set. Returning original raster");
1483 PG_RETURN_POINTER(pgraster);
1490 PG_FREE_IF_COPY(pgraster, 0);
1491 elog(ERROR,
"RASTER_setPixelValuesGeomval: Could not intialize argument structure");
1496 if (arg->
gv == NULL) {
1499 PG_FREE_IF_COPY(pgraster, 0);
1500 elog(ERROR,
"RASTER_setPixelValuesGeomval: Could not allocate memory for geomval array");
1506 for (i = 0; i < n; i++) {
1516 tup = (HeapTupleHeader) DatumGetPointer(e[i]);
1520 PG_FREE_IF_COPY(pgraster, 0);
1521 elog(ERROR,
"RASTER_setPixelValuesGeomval: Invalid argument for geomval at index %d", i);
1527 tupv = GetAttributeByName(tup,
"geom", &isnull);
1529 elog(NOTICE,
"First argument (geom) of geomval at index %d is NULL. Skipping", i);
1538 PG_FREE_IF_COPY(pgraster, 0);
1539 elog(ERROR,
"RASTER_setPixelValuesGeomval: Could not deserialize geometry of geomval at index %d", i);
1545 elog(NOTICE,
"First argument (geom) of geomval at index %d is an empty geometry. Skipping", i);
1551 elog(NOTICE,
"Geometry provided for geomval at index %d does not have the same SRID as the raster: %d. Returning original raster", i, srid);
1554 PG_RETURN_POINTER(pgraster);
1606 PG_FREE_IF_COPY(pgraster, 0);
1607 elog(ERROR,
"RASTER_setPixelValuesGeomval: Could not rasterize geometry of geomval at index %d", i);
1616 tupv = GetAttributeByName(tup,
"val", &isnull);
1618 elog(NOTICE,
"Second argument (val) of geomval at index %d is NULL. Treating as NODATA", i);
1630 if (arg->
gv == NULL) {
1633 PG_FREE_IF_COPY(pgraster, 0);
1634 elog(ERROR,
"RASTER_setPixelValuesGeomval: Could not reallocate memory for geomval array");
1640 if (!PG_ARGISNULL(3))
1646 POSTGIS_RT_DEBUG(3,
"keepnodata = TRUE and band is NODATA. Not doing anything");
1649 else if (allpoint == arg->
ngv) {
1650 double igt[6] = {0};
1659 POSTGIS_RT_DEBUG(3,
"all geometries are points, using direct to pixel method");
1665 for (i = 0; i < arg->
ngv; i++) {
1670 for (j = 0; j < coll->
ngeoms; j++) {
1677 PG_FREE_IF_COPY(pgraster, 0);
1678 elog(ERROR,
"RASTER_setPixelValuesGeomval: Could not process coordinates of point");
1684 (xy[0] < 0 || xy[0] >= width) ||
1685 (xy[1] < 0 || xy[1] >= height)
1687 elog(NOTICE,
"Point is outside raster extent. Skipping");
1695 PG_FREE_IF_COPY(pgraster, 0);
1696 elog(ERROR,
"RASTER_setPixelValuesGeomval: Could not get pixel value");
1713 PG_FREE_IF_COPY(pgraster, 0);
1714 elog(ERROR,
"RASTER_setPixelValuesGeomval: Could not set pixel value");
1728 if (itrset == NULL) {
1731 PG_FREE_IF_COPY(pgraster, 0);
1732 elog(ERROR,
"RASTER_setPixelValuesGeomval: Could not allocate memory for iterator arguments");
1742 for (i = 0, j = 1; i < arg->
ngv; i++, j++) {
1744 itrset[j].
nband = 0;
1750 itrset, arg->
ngv + 1,
1753 hasnodata, nodataval,
1765 PG_FREE_IF_COPY(pgraster, 0);
1766 elog(ERROR,
"RASTER_setPixelValuesGeomval: Could not run raster iterator function");
1772 if (_band == NULL) {
1776 PG_FREE_IF_COPY(pgraster, 0);
1777 elog(ERROR,
"RASTER_setPixelValuesGeomval: Could not get band from working raster");
1782 if (_band == NULL) {
1786 PG_FREE_IF_COPY(pgraster, 0);
1787 elog(ERROR,
"RASTER_setPixelValuesGeomval: Could not replace band in output raster");
1799 PG_FREE_IF_COPY(pgraster, 0);
1806 SET_VARSIZE(pgrtn, pgrtn->
size);
1807 PG_RETURN_POINTER(pgrtn);
1810 #undef VALUES_LENGTH
1811 #define VALUES_LENGTH 3
1819 FuncCallContext *funcctx;
1830 if (SRF_IS_FIRSTCALL()) {
1831 MemoryContext oldcontext;
1838 double *search = NULL;
1841 bool exclude_nodata_value =
TRUE;
1852 funcctx = SRF_FIRSTCALL_INIT();
1855 oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);
1857 if (PG_ARGISNULL(0)) {
1858 MemoryContextSwitchTo(oldcontext);
1859 SRF_RETURN_DONE(funcctx);
1861 pgraster = (
rt_pgraster *) PG_DETOAST_DATUM(PG_GETARG_DATUM(0));
1864 PG_FREE_IF_COPY(pgraster, 0);
1865 MemoryContextSwitchTo(oldcontext);
1866 elog(ERROR,
"RASTER_pixelOfValue: Could not deserialize raster");
1867 SRF_RETURN_DONE(funcctx);
1872 if (num_bands < 1) {
1873 elog(NOTICE,
"Raster provided has no bands");
1875 PG_FREE_IF_COPY(pgraster, 0);
1876 MemoryContextSwitchTo(oldcontext);
1877 SRF_RETURN_DONE(funcctx);
1881 if (!PG_ARGISNULL(1))
1882 nband = PG_GETARG_INT32(1);
1883 if (nband < 1 || nband > num_bands) {
1884 elog(NOTICE,
"Invalid band index (must use 1-based). Returning NULL");
1886 PG_FREE_IF_COPY(pgraster, 0);
1887 MemoryContextSwitchTo(oldcontext);
1888 SRF_RETURN_DONE(funcctx);
1892 array = PG_GETARG_ARRAYTYPE_P(2);
1893 etype = ARR_ELEMTYPE(array);
1894 get_typlenbyvalalign(etype, &typlen, &typbyval, &typalign);
1902 PG_FREE_IF_COPY(pgraster, 0);
1903 MemoryContextSwitchTo(oldcontext);
1904 elog(ERROR,
"RASTER_pixelOfValue: Invalid data type for pixel values");
1905 SRF_RETURN_DONE(funcctx);
1909 deconstruct_array(array, etype, typlen, typbyval, typalign, &e,
1912 search = palloc(
sizeof(
double) * n);
1913 for (i = 0, nsearch = 0; i < n; i++) {
1914 if (nulls[i])
continue;
1918 val = (double) DatumGetFloat4(e[i]);
1921 val = (double) DatumGetFloat8(e[i]);
1925 search[nsearch] = val;
1932 elog(NOTICE,
"No search values provided. Returning NULL");
1935 PG_FREE_IF_COPY(pgraster, 0);
1936 MemoryContextSwitchTo(oldcontext);
1937 SRF_RETURN_DONE(funcctx);
1939 else if (nsearch < n)
1940 search = repalloc(search,
sizeof(
double) * nsearch);
1943 if (!PG_ARGISNULL(3))
1944 exclude_nodata_value = PG_GETARG_BOOL(3);
1949 elog(NOTICE,
"Could not find band at index %d. Returning NULL",
nband);
1951 PG_FREE_IF_COPY(pgraster, 0);
1952 MemoryContextSwitchTo(oldcontext);
1953 SRF_RETURN_DONE(funcctx);
1958 band, exclude_nodata_value,
1965 PG_FREE_IF_COPY(pgraster, 0);
1969 elog(NOTICE,
"Could not get the pixels of search values for band at index %d",
nband);
1972 elog(NOTICE,
"No pixels of search values found for band at index %d",
nband);
1974 MemoryContextSwitchTo(oldcontext);
1975 SRF_RETURN_DONE(funcctx);
1979 funcctx->user_fctx = pixels;
1982 funcctx->max_calls =
count;
1985 if (get_call_result_type(fcinfo, NULL, &tupdesc) != TYPEFUNC_COMPOSITE) {
1987 errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1989 "function returning record called in context "
1990 "that cannot accept type record"
1995 BlessTupleDesc(tupdesc);
1996 funcctx->tuple_desc = tupdesc;
1998 MemoryContextSwitchTo(oldcontext);
2002 funcctx = SRF_PERCALL_SETUP();
2004 call_cntr = funcctx->call_cntr;
2005 max_calls = funcctx->max_calls;
2006 tupdesc = funcctx->tuple_desc;
2007 pixels2 = funcctx->user_fctx;
2010 if (call_cntr < max_calls) {
2019 pixels2[call_cntr].
x += 1;
2020 pixels2[call_cntr].
y += 1;
2022 values[0] = Float8GetDatum(pixels2[call_cntr].
value);
2023 values[1] = Int32GetDatum(pixels2[call_cntr].
x);
2024 values[2] = Int32GetDatum(pixels2[call_cntr].
y);
2027 tuple = heap_form_tuple(tupdesc, values, nulls);
2030 result = HeapTupleGetDatum(tuple);
2032 SRF_RETURN_NEXT(funcctx,
result);
2036 SRF_RETURN_DONE(funcctx);
2052 bool exclude_nodata_value =
TRUE;
2065 if (PG_ARGISNULL(0))
2067 pgraster = (
rt_pgraster *) PG_DETOAST_DATUM(PG_GETARG_DATUM(0));
2070 PG_FREE_IF_COPY(pgraster, 0);
2071 elog(ERROR,
"RASTER_nearestValue: Could not deserialize raster");
2076 if (!PG_ARGISNULL(1))
2077 bandindex = PG_GETARG_INT32(1);
2079 if (bandindex < 1 || bandindex > num_bands) {
2080 elog(NOTICE,
"Invalid band index (must use 1-based). Returning NULL");
2082 PG_FREE_IF_COPY(pgraster, 0);
2087 geom = PG_GETARG_GSERIALIZED_P(2);
2089 elog(NOTICE,
"Geometry provided must be a point");
2091 PG_FREE_IF_COPY(pgraster, 0);
2092 PG_FREE_IF_COPY(geom, 2);
2097 if (!PG_ARGISNULL(3))
2098 exclude_nodata_value = PG_GETARG_BOOL(3);
2102 elog(NOTICE,
"SRIDs of geometry and raster do not match");
2104 PG_FREE_IF_COPY(pgraster, 0);
2105 PG_FREE_IF_COPY(geom, 2);
2112 elog(NOTICE,
"Could not find band at index %d. Returning NULL", bandindex);
2114 PG_FREE_IF_COPY(pgraster, 0);
2115 PG_FREE_IF_COPY(geom, 2);
2123 elog(NOTICE,
"Geometry provided cannot be empty");
2125 PG_FREE_IF_COPY(pgraster, 0);
2126 PG_FREE_IF_COPY(geom, 2);
2147 PG_FREE_IF_COPY(pgraster, 0);
2149 PG_FREE_IF_COPY(geom, 2);
2150 elog(ERROR,
"RASTER_nearestValue: Could not compute pixel coordinates from spatial coordinates");
2161 PG_FREE_IF_COPY(pgraster, 0);
2163 PG_FREE_IF_COPY(geom, 2);
2164 elog(ERROR,
"RASTER_nearestValue: Could not get pixel value for band at index %d", bandindex);
2169 if (!exclude_nodata_value || !isnodata) {
2171 PG_FREE_IF_COPY(pgraster, 0);
2173 PG_FREE_IF_COPY(geom, 2);
2175 PG_RETURN_FLOAT8(
value);
2184 exclude_nodata_value,
2192 elog(NOTICE,
"Could not get the nearest value for band at index %d", bandindex);
2195 elog(NOTICE,
"No nearest value found for band at index %d", bandindex);
2198 PG_FREE_IF_COPY(geom, 2);
2200 PG_FREE_IF_COPY(pgraster, 0);
2208 double lastdist = -1;
2211 for (i = 0; i <
count; i++) {
2216 PG_FREE_IF_COPY(geom, 2);
2218 PG_FREE_IF_COPY(pgraster, 0);
2219 elog(ERROR,
"RASTER_nearestValue: Could not get polygon of neighboring pixel");
2225 if (lastdist < 0 || dist < lastdist) {
2241 PG_FREE_IF_COPY(geom, 2);
2243 PG_FREE_IF_COPY(pgraster, 0);
2246 PG_RETURN_FLOAT8(
value);
2267 bool exclude_nodata_value =
TRUE;
2273 double **value2D = NULL;
2274 int **nodata2D = NULL;
2279 Datum *value1D = NULL;
2280 bool *nodata1D = NULL;
2282 int lbound[2] = {1, 1};
2283 ArrayType *mdArray = NULL;
2290 if (PG_ARGISNULL(0))
2292 pgraster = (
rt_pgraster *) PG_DETOAST_DATUM(PG_GETARG_DATUM(0));
2296 PG_FREE_IF_COPY(pgraster, 0);
2297 elog(ERROR,
"RASTER_neighborhood: Could not deserialize raster");
2302 if (!PG_ARGISNULL(1))
2303 bandindex = PG_GETARG_INT32(1);
2305 if (bandindex < 1 || bandindex > num_bands) {
2306 elog(NOTICE,
"Invalid band index (must use 1-based). Returning NULL");
2308 PG_FREE_IF_COPY(pgraster, 0);
2313 x = PG_GETARG_INT32(2);
2317 y = PG_GETARG_INT32(3);
2323 elog(NOTICE,
"Invalid value for distancex (must be >= zero). Returning NULL");
2325 PG_FREE_IF_COPY(pgraster, 0);
2333 elog(NOTICE,
"Invalid value for distancey (must be >= zero). Returning NULL");
2335 PG_FREE_IF_COPY(pgraster, 0);
2341 if (!PG_ARGISNULL(6))
2342 exclude_nodata_value = PG_GETARG_BOOL(6);
2347 elog(NOTICE,
"Could not find band at index %d. Returning NULL", bandindex);
2349 PG_FREE_IF_COPY(pgraster, 0);
2361 exclude_nodata_value,
2366 elog(NOTICE,
"Could not get the pixel's neighborhood for band at index %d", bandindex);
2370 PG_FREE_IF_COPY(pgraster, 0);
2387 elog(NOTICE,
"Could not get the pixel of band at index %d. Returning NULL", bandindex);
2390 PG_FREE_IF_COPY(pgraster, 0);
2413 if (npixels == NULL) {
2417 PG_FREE_IF_COPY(pgraster, 0);
2419 elog(ERROR,
"RASTER_neighborhood: Could not reallocate memory for neighborhood");
2422 npixels[
count - 1].
x = _x;
2423 npixels[
count - 1].
y = _y;
2428 if (!exclude_nodata_value || !isnodata) {
2435 PG_FREE_IF_COPY(pgraster, 0);
2440 npixels,
count, NULL,
2445 &(dim[1]), &(dim[0])
2449 elog(NOTICE,
"Could not create 2D array of neighborhood");
2454 value1D = palloc(
sizeof(Datum) * dim[0] * dim[1]);
2455 nodata1D = palloc(
sizeof(
bool) * dim[0] * dim[1]);
2457 if (value1D == NULL || nodata1D == NULL) {
2459 for (i = 0; i < dim[0]; i++) {
2466 elog(ERROR,
"RASTER_neighborhood: Could not allocate memory for return 2D array");
2473 for (i = 0; i < dim[0]; i++) {
2475 for (j = 0; j < dim[1]; j++) {
2476 nodata1D[k] = (bool) nodata2D[i][j];
2478 value1D[k] = Float8GetDatum(value2D[i][j]);
2480 value1D[k] = PointerGetDatum(NULL);
2487 for (i = 0; i < dim[0]; i++) {
2495 get_typlenbyvalalign(FLOAT8OID, &typlen, &typbyval, &typalign);
2497 mdArray = construct_md_array(
2501 typlen, typbyval, typalign
2507 PG_RETURN_ARRAYTYPE_P(mdArray);
char result[OUT_DOUBLE_BUFFER_SIZE]
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 gserialized_is_empty(const GSERIALIZED *g)
Check if a GSERIALIZED is empty without deserializing first.
uint32_t gserialized_get_type(const GSERIALIZED *g)
Extract the geometry type from the serialized form (it hides in the anonymous data area,...
GSERIALIZED * gserialized_from_lwgeom(LWGEOM *geom, size_t *size)
Allocate a new GSERIALIZED from an LWGEOM.
int lwgeom_ndims(const LWGEOM *geom)
Return the number of dimensions (2, 3, 4) in a geometry.
void lwgeom_free(LWGEOM *geom)
LWGEOM * lwgeom_as_multi(const LWGEOM *lwgeom)
Create a new LWGEOM of the appropriate MULTI* type.
#define LWSIZE_GET(varsize)
Macro for reading the size from the GSERIALIZED size attribute.
LWGEOM * lwpoly_as_lwgeom(const LWPOLY *obj)
double lwpoint_get_x(const LWPOINT *point)
int getPoint2d_p(const POINTARRAY *pa, uint32_t n, POINT2D *point)
#define POINTTYPE
LWTYPE numbers, used internally by PostGIS.
double lwgeom_mindistance2d(const LWGEOM *lw1, const LWGEOM *lw2)
Function initializing min distance calculation.
LWCOLLECTION * lwgeom_as_lwcollection(const LWGEOM *lwgeom)
void lwpoly_free(LWPOLY *poly)
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...
double lwpoint_get_y(const LWPOINT *point)
LWGEOM * lwgeom_force_2d(const LWGEOM *geom)
Strip out the Z/M components of an LWGEOM.
int rt_band_get_pixel_of_value(rt_band band, int exclude_nodata_value, double *searchset, int searchcount, rt_pixel *pixels)
Search band for pixel(s) with search values.
uint16_t rt_band_get_width(rt_band band)
Return width of this band.
int32_t rt_raster_get_srid(rt_raster raster)
Get raster's SRID.
rt_errorstate rt_raster_get_inverse_geotransform_matrix(rt_raster raster, double *gt, double *igt)
Get 6-element array of raster inverse geotransform matrix.
int rt_band_get_hasnodata_flag(rt_band band)
Get hasnodata flag value.
rt_errorstate rt_raster_geopoint_to_cell(rt_raster raster, double xw, double yw, double *xr, double *yr, double *igt)
Convert an xw, yw map point to a xr, yr raster point.
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.
LWPOLY * rt_raster_pixel_as_polygon(rt_raster raster, int x, int y)
Get a raster pixel as a polygon.
int rt_band_get_isnodata_flag(rt_band band)
Get isnodata flag value.
rt_errorstate rt_raster_geopoint_to_rasterpoint(rt_raster raster, double xw, double yw, double *xr, double *yr, double *igt)
Convert an xw,yw map point to a xr,yr raster point.
int rt_raster_has_band(rt_raster raster, int nband)
Return TRUE if the raster has a band of this number.
struct rt_pixel_t * rt_pixel
void * rt_raster_serialize(rt_raster raster)
Return this raster in serialized form.
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
Enum definitions.
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)
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_errorstate rt_band_get_pixel_resample(rt_band band, double xr, double yr, rt_resample_type resample, double *r_value, int *r_nodata)
Retrieve a point value from the raster using a world coordinate and selected resampling method.
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.
rt_errorstate rt_pixel_set_to_array(rt_pixel npixel, uint32_t count, rt_mask mask, int x, int y, uint16_t distancex, uint16_t distancey, double ***value, int ***nodata, int *dimx, int *dimy)
uint16_t rt_raster_get_width(rt_raster raster)
uint32_t rt_band_get_nearest_pixel(rt_band band, int x, int y, uint16_t distancex, uint16_t distancey, int exclude_nodata_value, rt_pixel *npixels)
Get nearest pixel(s) with value (not NODATA) to specified pixel.
int rt_band_clamped_value_is_nodata(rt_band band, double val)
Compare clamped value to band's clamped NODATA value.
void rt_raster_get_geotransform_matrix(rt_raster raster, double *gt)
Get 6-element array of raster geotransform matrix.
rt_errorstate rt_raster_copy_to_geometry(rt_raster raster, uint32_t bandnum, char dim, rt_resample_type resample, const LWGEOM *lwgeom_in, LWGEOM **lwgeom_out)
Copy values from a raster to the points on a geometry using the requested interpolation type.
uint16_t rt_band_get_height(rt_band band)
Return height of this band.
rt_raster rt_raster_deserialize(void *serialized, int header_only)
Return a raster from a serialized form.
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)
static LWPOINT * lwgeom_as_lwpoint(const LWGEOM *lwgeom)
static double distance(double x1, double y1, double x2, double y2)
raster
Be careful!! Zeros function's input parameter can be a (height x width) array, not (width x height): ...
struct rtpg_dumpvalues_arg_t * rtpg_dumpvalues_arg
Datum RASTER_getPixelValueResample(PG_FUNCTION_ARGS)
Datum RASTER_setPixelValuesArray(PG_FUNCTION_ARGS)
static void rtpg_dumpvalues_arg_destroy(rtpg_dumpvalues_arg arg)
static void rtpg_setvaluesgv_arg_destroy(rtpg_setvaluesgv_arg arg)
Datum RASTER_dumpValues(PG_FUNCTION_ARGS)
Datum RASTER_getPixelValue(PG_FUNCTION_ARGS)
static rt_resample_type resample_text_to_type(text *txt)
static rtpg_dumpvalues_arg rtpg_dumpvalues_arg_init()
Datum RASTER_nearestValue(PG_FUNCTION_ARGS)
Datum RASTER_getGeometryValues(PG_FUNCTION_ARGS)
Datum RASTER_pixelOfValue(PG_FUNCTION_ARGS)
Datum RASTER_neighborhood(PG_FUNCTION_ARGS)
struct rtpg_setvaluesgv_geomval_t * rtpg_setvaluesgv_geomval
static int rtpg_setvalues_geomval_callback(rt_iterator_arg arg, void *userarg, double *value, int *nodata)
static rtpg_setvaluesgv_arg rtpg_setvaluesgv_arg_init()
struct rtpg_setvaluesgv_arg_t * rtpg_setvaluesgv_arg
PG_FUNCTION_INFO_V1(RASTER_getPixelValue)
Return value of a single pixel.
Datum RASTER_setPixelValuesGeomval(PG_FUNCTION_ARGS)
Datum RASTER_setPixelValue(PG_FUNCTION_ARGS)
#define POSTGIS_RT_DEBUG(level, msg)
#define POSTGIS_RT_DEBUGF(level, msg,...)
rtpg_setvaluesgv_geomval gv
struct rtpg_setvaluesgv_geomval_t::@27 pixval