32 #include "utils/lsyscache.h"
34 #include "utils/array.h"
35 #include "catalog/pg_type.h"
37 #include "../../postgis_config.h"
38 #include "lwgeom_pg.h"
42 #include "access/htup_details.h"
79 int32_t bandindex = 0;
83 bool exclude_nodata_value =
TRUE;
87 bandindex = PG_GETARG_INT32(1);
88 if ( bandindex < 1 ) {
89 elog(NOTICE,
"Invalid band index (must use 1-based). Returning NULL");
93 x = PG_GETARG_INT32(2);
95 y = PG_GETARG_INT32(3);
97 exclude_nodata_value = PG_GETARG_BOOL(4);
102 if (PG_ARGISNULL(0)) PG_RETURN_NULL();
103 pgraster = (
rt_pgraster *)PG_DETOAST_DATUM(PG_GETARG_DATUM(0));
107 PG_FREE_IF_COPY(pgraster, 0);
108 elog(ERROR,
"RASTER_getPixelValue: Could not deserialize raster");
115 elog(NOTICE,
"Could not find raster band of index %d when getting pixel "
116 "value. Returning NULL", bandindex);
118 PG_FREE_IF_COPY(pgraster, 0);
126 if (
result !=
ES_NONE || (exclude_nodata_value && isnodata)) {
128 PG_FREE_IF_COPY(pgraster, 0);
133 PG_FREE_IF_COPY(pgraster, 0);
135 PG_RETURN_FLOAT8(pixvalue);
158 elog(ERROR,
"rtpg_dumpvalues_arg_init: Could not allocate memory for arguments");
180 if (arg->
values != NULL) {
181 for (i = 0; i < arg->
numbands; i++) {
183 if (arg->
values[i] != NULL)
186 if (arg->
nodata[i] != NULL)
200 #define VALUES_LENGTH 2
205 FuncCallContext *funcctx;
222 if (SRF_IS_FIRSTCALL()) {
223 MemoryContext oldcontext;
229 bool exclude_nodata_value =
TRUE;
242 funcctx = SRF_FIRSTCALL_INIT();
245 oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);
248 if (PG_ARGISNULL(0)) {
249 MemoryContextSwitchTo(oldcontext);
250 SRF_RETURN_DONE(funcctx);
252 pgraster = (
rt_pgraster *) PG_DETOAST_DATUM(PG_GETARG_DATUM(0));
256 PG_FREE_IF_COPY(pgraster, 0);
258 errcode(ERRCODE_OUT_OF_MEMORY),
259 errmsg(
"Could not deserialize raster")
261 MemoryContextSwitchTo(oldcontext);
262 SRF_RETURN_DONE(funcctx);
279 elog(NOTICE,
"Raster provided has no bands");
281 PG_FREE_IF_COPY(pgraster, 0);
282 MemoryContextSwitchTo(oldcontext);
283 SRF_RETURN_DONE(funcctx);
290 PG_FREE_IF_COPY(pgraster, 0);
291 MemoryContextSwitchTo(oldcontext);
292 elog(ERROR,
"RASTER_dumpValues: Could not initialize argument structure");
293 SRF_RETURN_DONE(funcctx);
297 if (!PG_ARGISNULL(1)) {
298 array = PG_GETARG_ARRAYTYPE_P(1);
299 etype = ARR_ELEMTYPE(array);
300 get_typlenbyvalalign(etype, &typlen, &typbyval, &typalign);
309 PG_FREE_IF_COPY(pgraster, 0);
310 MemoryContextSwitchTo(oldcontext);
311 elog(ERROR,
"RASTER_dumpValues: Invalid data type for band indexes");
312 SRF_RETURN_DONE(funcctx);
316 deconstruct_array(array, etype, typlen, typbyval, typalign, &e, &nulls, &(arg1->
numbands));
319 if (arg1->
nbands == NULL) {
322 PG_FREE_IF_COPY(pgraster, 0);
323 MemoryContextSwitchTo(oldcontext);
324 elog(ERROR,
"RASTER_dumpValues: Could not allocate memory for band indexes");
325 SRF_RETURN_DONE(funcctx);
328 for (i = 0, j = 0; i < arg1->
numbands; i++) {
329 if (nulls[i])
continue;
333 arg1->
nbands[j] = DatumGetInt16(e[i]) - 1;
336 arg1->
nbands[j] = DatumGetInt32(e[i]) - 1;
343 if (j < arg1->numbands) {
345 if (arg1->
nbands == NULL) {
348 PG_FREE_IF_COPY(pgraster, 0);
349 MemoryContextSwitchTo(oldcontext);
350 elog(ERROR,
"RASTER_dumpValues: Could not reallocate memory for band indexes");
351 SRF_RETURN_DONE(funcctx);
358 for (i = 0; i < arg1->
numbands; i++) {
360 elog(NOTICE,
"Band at index %d not found in raster", arg1->
nbands[i] + 1);
363 PG_FREE_IF_COPY(pgraster, 0);
364 MemoryContextSwitchTo(oldcontext);
365 SRF_RETURN_DONE(funcctx);
375 if (arg1->
nbands == NULL) {
378 PG_FREE_IF_COPY(pgraster, 0);
379 MemoryContextSwitchTo(oldcontext);
380 elog(ERROR,
"RASTER_dumpValues: Could not allocate memory for band indexes");
381 SRF_RETURN_DONE(funcctx);
384 for (i = 0; i < arg1->
numbands; i++) {
394 if (!PG_ARGISNULL(2))
395 exclude_nodata_value = PG_GETARG_BOOL(2);
404 PG_FREE_IF_COPY(pgraster, 0);
405 MemoryContextSwitchTo(oldcontext);
406 elog(ERROR,
"RASTER_dumpValues: Could not allocate memory for pixel values");
407 SRF_RETURN_DONE(funcctx);
413 for (z = 0; z < arg1->
numbands; z++) {
423 PG_FREE_IF_COPY(pgraster, 0);
424 MemoryContextSwitchTo(oldcontext);
425 elog(ERROR,
"RASTER_dumpValues: Could not get band at index %d",
nband);
426 SRF_RETURN_DONE(funcctx);
432 if (arg1->
values[z] == NULL || arg1->
nodata[z] == NULL) {
435 PG_FREE_IF_COPY(pgraster, 0);
436 MemoryContextSwitchTo(oldcontext);
437 elog(ERROR,
"RASTER_dumpValues: Could not allocate memory for pixel values");
438 SRF_RETURN_DONE(funcctx);
447 for (i = (arg1->
rows * arg1->
columns) - 1; i >= 0; i--)
452 for (
y = 0;
y < arg1->
rows;
y++) {
459 PG_FREE_IF_COPY(pgraster, 0);
460 MemoryContextSwitchTo(oldcontext);
461 elog(ERROR,
"RASTER_dumpValues: Could not pixel (%d, %d) of band %d",
x,
y,
nband);
462 SRF_RETURN_DONE(funcctx);
465 arg1->
values[z][i] = Float8GetDatum(val);
469 if (exclude_nodata_value && isnodata) {
483 PG_FREE_IF_COPY(pgraster, 0);
486 funcctx->user_fctx = arg1;
489 funcctx->max_calls = arg1->
numbands;
492 if (get_call_result_type(fcinfo, NULL, &tupdesc) != TYPEFUNC_COMPOSITE) {
493 MemoryContextSwitchTo(oldcontext);
495 errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
497 "function returning record called in context "
498 "that cannot accept type record"
503 BlessTupleDesc(tupdesc);
504 funcctx->tuple_desc = tupdesc;
506 MemoryContextSwitchTo(oldcontext);
510 funcctx = SRF_PERCALL_SETUP();
512 call_cntr = funcctx->call_cntr;
513 max_calls = funcctx->max_calls;
514 tupdesc = funcctx->tuple_desc;
515 arg2 = funcctx->user_fctx;
518 if (call_cntr < max_calls) {
523 ArrayType *mdValues = NULL;
526 int lbound[2] = {1, 1};
533 values[0] = Int32GetDatum(arg2->
nbands[call_cntr] + 1);
536 get_typlenbyvalalign(FLOAT8OID, &typlen, &typbyval, &typalign);
539 if (arg2->
values[call_cntr] == NULL)
543 mdValues = construct_md_array(
547 typlen, typbyval, typalign
549 values[1] = PointerGetDatum(mdValues);
552 tuple = heap_form_tuple(tupdesc, values, nulls);
553 result = HeapTupleGetDatum(tuple);
555 SRF_RETURN_NEXT(funcctx,
result);
560 SRF_RETURN_DONE(funcctx);
575 int32_t bandindex = 0;
578 bool skipset =
FALSE;
587 bandindex = PG_GETARG_INT32(1);
590 elog(NOTICE,
"Invalid band index (must use 1-based). Value not set. Returning original raster");
595 if (PG_ARGISNULL(2)) {
596 elog(NOTICE,
"X coordinate can not be NULL when setting pixel value. Value not set. Returning original raster");
600 x = PG_GETARG_INT32(2);
602 if (PG_ARGISNULL(3)) {
603 elog(NOTICE,
"Y coordinate can not be NULL when setting pixel value. Value not set. Returning original raster");
607 y = PG_GETARG_INT32(3);
612 pgraster = (
rt_pgraster *) PG_DETOAST_DATUM_COPY(PG_GETARG_DATUM(0));
616 PG_FREE_IF_COPY(pgraster, 0);
617 elog(ERROR,
"RASTER_setPixelValue: Could not deserialize raster");
625 elog(NOTICE,
"Could not find raster band of index %d when setting "
626 "pixel value. Value not set. Returning original raster",
628 PG_RETURN_POINTER(pgraster);
632 if (PG_ARGISNULL(4)) {
634 elog(NOTICE,
"Raster do not have a nodata value defined. "
635 "Set band nodata value first. Nodata value not set. "
636 "Returning original raster");
637 PG_RETURN_POINTER(pgraster);
645 pixvalue = PG_GETARG_FLOAT8(4);
653 PG_FREE_IF_COPY(pgraster, 0);
657 SET_VARSIZE(pgrtn, pgrtn->
size);
658 PG_RETURN_POINTER(pgrtn);
697 struct pixelvalue *
pixval = NULL;
699 int dimpixval[2] = {1, 1};
700 int dimnoset[2] = {1, 1};
701 int hasnodata =
FALSE;
702 double nodataval = 0;
703 bool keepnodata =
FALSE;
704 bool hasnosetval =
FALSE;
705 bool nosetvalisnull =
FALSE;
720 pgraster = (
rt_pgraster *) PG_DETOAST_DATUM_COPY(PG_GETARG_DATUM(0));
725 PG_FREE_IF_COPY(pgraster, 0);
726 elog(ERROR,
"RASTER_setPixelValuesArray: Could not deserialize raster");
736 if (PG_ARGISNULL(1)) {
737 elog(NOTICE,
"Band index cannot be NULL. Value must be 1-based. Returning original raster");
739 PG_RETURN_POINTER(pgraster);
742 nband = PG_GETARG_INT32(1);
743 if (nband < 1 || nband > numbands) {
744 elog(NOTICE,
"Band index is invalid. Value must be 1-based. Returning original raster");
746 PG_RETURN_POINTER(pgraster);
750 for (i = 2, j = 0; i < 4; i++, j++) {
751 if (PG_ARGISNULL(i)) {
752 elog(NOTICE,
"%s cannot be NULL. Value must be 1-based. Returning original raster", j < 1 ?
"X" :
"Y");
754 PG_RETURN_POINTER(pgraster);
757 ul[j] = PG_GETARG_INT32(i);
760 (j < 1 && ul[j] > width) ||
761 (j > 0 && ul[j] > height)
764 elog(NOTICE,
"%s is invalid. Value must be 1-based. Returning original raster", j < 1 ?
"X" :
"Y");
766 PG_RETURN_POINTER(pgraster);
774 if (PG_ARGISNULL(4)) {
775 elog(NOTICE,
"No values to set. Returning original raster");
777 PG_RETURN_POINTER(pgraster);
780 array = PG_GETARG_ARRAYTYPE_P(4);
781 etype = ARR_ELEMTYPE(array);
782 get_typlenbyvalalign(etype, &typlen, &typbyval, &typalign);
790 PG_FREE_IF_COPY(pgraster, 0);
791 elog(ERROR,
"RASTER_setPixelValuesArray: Invalid data type for new values");
796 ndims = ARR_NDIM(array);
797 dims = ARR_DIMS(array);
800 if (ndims < 1 || ndims > 2) {
801 elog(NOTICE,
"New values array must be of 1 or 2 dimensions. Returning original raster");
803 PG_RETURN_POINTER(pgraster);
809 dimpixval[1] = dims[0];
811 dimpixval[0] = dims[0];
812 dimpixval[1] = dims[1];
819 typlen, typbyval, typalign,
820 &elements, &nulls, &num
824 if (num < 1 || num != (dimpixval[0] * dimpixval[1])) {
830 PG_FREE_IF_COPY(pgraster, 0);
831 elog(ERROR,
"RASTER_setPixelValuesArray: Could not deconstruct new values array");
837 pixval = palloc(
sizeof(
struct pixelvalue) * numpixval);
842 PG_FREE_IF_COPY(pgraster, 0);
843 elog(ERROR,
"RASTER_setPixelValuesArray: Could not allocate memory for new pixel values");
849 for (
y = 0;
y < dimpixval[0];
y++) {
850 for (
x = 0;
x < dimpixval[1];
x++) {
864 pixval[i].value = DatumGetFloat4(elements[i]);
867 pixval[i].value = DatumGetFloat8(elements[i]);
880 if (!PG_ARGISNULL(5)) {
881 array = PG_GETARG_ARRAYTYPE_P(5);
882 etype = ARR_ELEMTYPE(array);
883 get_typlenbyvalalign(etype, &typlen, &typbyval, &typalign);
891 PG_FREE_IF_COPY(pgraster, 0);
892 elog(ERROR,
"RASTER_setPixelValuesArray: Invalid data type for noset flags");
897 ndims = ARR_NDIM(array);
898 dims = ARR_DIMS(array);
901 if (ndims < 1 || ndims > 2) {
902 elog(NOTICE,
"Noset flags array must be of 1 or 2 dimensions. Returning original raster");
905 PG_RETURN_POINTER(pgraster);
911 dimnoset[1] = dims[0];
913 dimnoset[0] = dims[0];
914 dimnoset[1] = dims[1];
921 typlen, typbyval, typalign,
922 &elements, &nulls, &num
926 if (num < 1 || num != (dimnoset[0] * dimnoset[1])) {
933 PG_FREE_IF_COPY(pgraster, 0);
934 elog(ERROR,
"RASTER_setPixelValuesArray: Could not deconstruct noset flags array");
940 for (
y = 0;
y < dimnoset[0];
y++) {
941 if (
y >= dimpixval[0])
break;
943 for (
x = 0;
x < dimnoset[1];
x++) {
945 if (
x >= dimpixval[1]) {
946 i += (dimnoset[1] - dimpixval[1]);
950 if (!nulls[i] && DatumGetBool(elements[i]))
958 if (
x < dimpixval[1])
959 j += (dimpixval[1] - dimnoset[1]);
966 else if (!PG_ARGISNULL(6) && PG_GETARG_BOOL(6)) {
969 nosetvalisnull =
TRUE;
971 nosetval = PG_GETARG_FLOAT8(7);
974 #if POSTGIS_DEBUG_LEVEL > 0
975 for (i = 0; i < numpixval; i++) {
976 POSTGIS_RT_DEBUGF(4,
"pixval[%d](x, y, noset, nodata, value) = (%d, %d, %d, %d, %f)",
988 if (!PG_ARGISNULL(8))
989 keepnodata = PG_GETARG_BOOL(8);
994 elog(NOTICE,
"Could not find band at index %d. Returning original raster",
nband);
997 PG_RETURN_POINTER(pgraster);
1010 for (i = 0; i < numpixval; i++) {
1015 else if (hasnosetval) {
1017 if (
pixval[i].nodata && nosetvalisnull)
1029 elog(NOTICE,
"Cannot set value for pixel (%d, %d) outside raster bounds: %d x %d",
1037 if (hasnodata && keepnodata) {
1042 PG_FREE_IF_COPY(pgraster, 0);
1043 elog(ERROR,
"Cannot get value of pixel");
1064 PG_FREE_IF_COPY(pgraster, 0);
1068 SET_VARSIZE(pgrtn, pgrtn->
size);
1069 PG_RETURN_POINTER(pgrtn);
1099 elog(ERROR,
"rtpg_setvaluesgv_arg_init: Could not allocate memory for function arguments");
1113 if (arg->
gv != NULL) {
1114 for (i = 0; i < arg->
ngv; i++) {
1115 if (arg->
gv[i].
geom != NULL)
1117 if (arg->
gv[i].
mask != NULL)
1129 double *
value,
int *nodata
1147 for (i = arg->
rasters - 1, j = funcarg->
ngv - 1; i > 0; i--, j--) {
1151 if (arg->
nodata[i][0][0])
1169 if (arg->
nodata[0][0][0])
1196 double nodataval = 0;
1210 HeapTupleHeader tup;
1223 if (PG_ARGISNULL(0))
1225 pgraster = (
rt_pgraster *) PG_DETOAST_DATUM_COPY(PG_GETARG_DATUM(0));
1230 PG_FREE_IF_COPY(pgraster, 0);
1231 elog(ERROR,
"RASTER_setPixelValuesGeomval: Could not deserialize raster");
1243 if (PG_ARGISNULL(1)) {
1244 elog(NOTICE,
"Band index cannot be NULL. Value must be 1-based. Returning original raster");
1246 PG_RETURN_POINTER(pgraster);
1249 nband = PG_GETARG_INT32(1);
1250 if (nband < 1 || nband > numbands) {
1251 elog(NOTICE,
"Band index is invalid. Value must be 1-based. Returning original raster");
1253 PG_RETURN_POINTER(pgraster);
1264 if (PG_ARGISNULL(2)) {
1265 elog(NOTICE,
"No values to set. Returning original raster");
1267 PG_RETURN_POINTER(pgraster);
1270 array = PG_GETARG_ARRAYTYPE_P(2);
1271 etype = ARR_ELEMTYPE(array);
1272 get_typlenbyvalalign(etype, &typlen, &typbyval, &typalign);
1277 typlen, typbyval, typalign,
1282 elog(NOTICE,
"No values to set. Returning original raster");
1284 PG_RETURN_POINTER(pgraster);
1291 PG_FREE_IF_COPY(pgraster, 0);
1292 elog(ERROR,
"RASTER_setPixelValuesGeomval: Could not intialize argument structure");
1297 if (arg->
gv == NULL) {
1300 PG_FREE_IF_COPY(pgraster, 0);
1301 elog(ERROR,
"RASTER_setPixelValuesGeomval: Could not allocate memory for geomval array");
1307 for (i = 0; i < n; i++) {
1317 tup = (HeapTupleHeader) DatumGetPointer(e[i]);
1321 PG_FREE_IF_COPY(pgraster, 0);
1322 elog(ERROR,
"RASTER_setPixelValuesGeomval: Invalid argument for geomval at index %d", i);
1328 tupv = GetAttributeByName(tup,
"geom", &isnull);
1330 elog(NOTICE,
"First argument (geom) of geomval at index %d is NULL. Skipping", i);
1339 PG_FREE_IF_COPY(pgraster, 0);
1340 elog(ERROR,
"RASTER_setPixelValuesGeomval: Could not deserialize geometry of geomval at index %d", i);
1346 elog(NOTICE,
"First argument (geom) of geomval at index %d is an empty geometry. Skipping", i);
1352 elog(NOTICE,
"Geometry provided for geomval at index %d does not have the same SRID as the raster: %d. Returning original raster", i, srid);
1355 PG_RETURN_POINTER(pgraster);
1407 PG_FREE_IF_COPY(pgraster, 0);
1408 elog(ERROR,
"RASTER_setPixelValuesGeomval: Could not rasterize geometry of geomval at index %d", i);
1417 tupv = GetAttributeByName(tup,
"val", &isnull);
1419 elog(NOTICE,
"Second argument (val) of geomval at index %d is NULL. Treating as NODATA", i);
1431 if (arg->
gv == NULL) {
1434 PG_FREE_IF_COPY(pgraster, 0);
1435 elog(ERROR,
"RASTER_setPixelValuesGeomval: Could not reallocate memory for geomval array");
1441 if (!PG_ARGISNULL(3))
1447 POSTGIS_RT_DEBUG(3,
"keepnodata = TRUE and band is NODATA. Not doing anything");
1450 else if (allpoint == arg->
ngv) {
1451 double igt[6] = {0};
1460 POSTGIS_RT_DEBUG(3,
"all geometries are points, using direct to pixel method");
1466 for (i = 0; i < arg->
ngv; i++) {
1471 for (j = 0; j < coll->
ngeoms; j++) {
1478 PG_FREE_IF_COPY(pgraster, 0);
1479 elog(ERROR,
"RASTER_setPixelValuesGeomval: Could not process coordinates of point");
1485 (xy[0] < 0 || xy[0] >= width) ||
1486 (xy[1] < 0 || xy[1] >= height)
1488 elog(NOTICE,
"Point is outside raster extent. Skipping");
1496 PG_FREE_IF_COPY(pgraster, 0);
1497 elog(ERROR,
"RASTER_setPixelValuesGeomval: Could not get pixel value");
1514 PG_FREE_IF_COPY(pgraster, 0);
1515 elog(ERROR,
"RASTER_setPixelValuesGeomval: Could not set pixel value");
1529 if (itrset == NULL) {
1532 PG_FREE_IF_COPY(pgraster, 0);
1533 elog(ERROR,
"RASTER_setPixelValuesGeomval: Could not allocate memory for iterator arguments");
1543 for (i = 0, j = 1; i < arg->
ngv; i++, j++) {
1545 itrset[j].
nband = 0;
1551 itrset, arg->
ngv + 1,
1554 hasnodata, nodataval,
1566 PG_FREE_IF_COPY(pgraster, 0);
1567 elog(ERROR,
"RASTER_setPixelValuesGeomval: Could not run raster iterator function");
1573 if (_band == NULL) {
1577 PG_FREE_IF_COPY(pgraster, 0);
1578 elog(ERROR,
"RASTER_setPixelValuesGeomval: Could not get band from working raster");
1583 if (_band == NULL) {
1587 PG_FREE_IF_COPY(pgraster, 0);
1588 elog(ERROR,
"RASTER_setPixelValuesGeomval: Could not replace band in output raster");
1600 PG_FREE_IF_COPY(pgraster, 0);
1607 SET_VARSIZE(pgrtn, pgrtn->
size);
1608 PG_RETURN_POINTER(pgrtn);
1611 #undef VALUES_LENGTH
1612 #define VALUES_LENGTH 3
1620 FuncCallContext *funcctx;
1631 if (SRF_IS_FIRSTCALL()) {
1632 MemoryContext oldcontext;
1639 double *search = NULL;
1642 bool exclude_nodata_value =
TRUE;
1653 funcctx = SRF_FIRSTCALL_INIT();
1656 oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);
1658 if (PG_ARGISNULL(0)) {
1659 MemoryContextSwitchTo(oldcontext);
1660 SRF_RETURN_DONE(funcctx);
1662 pgraster = (
rt_pgraster *) PG_DETOAST_DATUM(PG_GETARG_DATUM(0));
1665 PG_FREE_IF_COPY(pgraster, 0);
1666 MemoryContextSwitchTo(oldcontext);
1667 elog(ERROR,
"RASTER_pixelOfValue: Could not deserialize raster");
1668 SRF_RETURN_DONE(funcctx);
1673 if (num_bands < 1) {
1674 elog(NOTICE,
"Raster provided has no bands");
1676 PG_FREE_IF_COPY(pgraster, 0);
1677 MemoryContextSwitchTo(oldcontext);
1678 SRF_RETURN_DONE(funcctx);
1682 if (!PG_ARGISNULL(1))
1683 nband = PG_GETARG_INT32(1);
1684 if (nband < 1 || nband > num_bands) {
1685 elog(NOTICE,
"Invalid band index (must use 1-based). Returning NULL");
1687 PG_FREE_IF_COPY(pgraster, 0);
1688 MemoryContextSwitchTo(oldcontext);
1689 SRF_RETURN_DONE(funcctx);
1693 array = PG_GETARG_ARRAYTYPE_P(2);
1694 etype = ARR_ELEMTYPE(array);
1695 get_typlenbyvalalign(etype, &typlen, &typbyval, &typalign);
1703 PG_FREE_IF_COPY(pgraster, 0);
1704 MemoryContextSwitchTo(oldcontext);
1705 elog(ERROR,
"RASTER_pixelOfValue: Invalid data type for pixel values");
1706 SRF_RETURN_DONE(funcctx);
1710 deconstruct_array(array, etype, typlen, typbyval, typalign, &e,
1713 search = palloc(
sizeof(
double) * n);
1714 for (i = 0, nsearch = 0; i < n; i++) {
1715 if (nulls[i])
continue;
1719 val = (double) DatumGetFloat4(e[i]);
1722 val = (double) DatumGetFloat8(e[i]);
1726 search[nsearch] = val;
1733 elog(NOTICE,
"No search values provided. Returning NULL");
1736 PG_FREE_IF_COPY(pgraster, 0);
1737 MemoryContextSwitchTo(oldcontext);
1738 SRF_RETURN_DONE(funcctx);
1740 else if (nsearch < n)
1741 search = repalloc(search,
sizeof(
double) * nsearch);
1744 if (!PG_ARGISNULL(3))
1745 exclude_nodata_value = PG_GETARG_BOOL(3);
1750 elog(NOTICE,
"Could not find band at index %d. Returning NULL",
nband);
1752 PG_FREE_IF_COPY(pgraster, 0);
1753 MemoryContextSwitchTo(oldcontext);
1754 SRF_RETURN_DONE(funcctx);
1759 band, exclude_nodata_value,
1766 PG_FREE_IF_COPY(pgraster, 0);
1770 elog(NOTICE,
"Could not get the pixels of search values for band at index %d",
nband);
1773 elog(NOTICE,
"No pixels of search values found for band at index %d",
nband);
1775 MemoryContextSwitchTo(oldcontext);
1776 SRF_RETURN_DONE(funcctx);
1780 funcctx->user_fctx = pixels;
1783 funcctx->max_calls =
count;
1786 if (get_call_result_type(fcinfo, NULL, &tupdesc) != TYPEFUNC_COMPOSITE) {
1788 errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1790 "function returning record called in context "
1791 "that cannot accept type record"
1796 BlessTupleDesc(tupdesc);
1797 funcctx->tuple_desc = tupdesc;
1799 MemoryContextSwitchTo(oldcontext);
1803 funcctx = SRF_PERCALL_SETUP();
1805 call_cntr = funcctx->call_cntr;
1806 max_calls = funcctx->max_calls;
1807 tupdesc = funcctx->tuple_desc;
1808 pixels2 = funcctx->user_fctx;
1811 if (call_cntr < max_calls) {
1820 pixels2[call_cntr].
x += 1;
1821 pixels2[call_cntr].
y += 1;
1823 values[0] = Float8GetDatum(pixels2[call_cntr].
value);
1824 values[1] = Int32GetDatum(pixels2[call_cntr].
x);
1825 values[2] = Int32GetDatum(pixels2[call_cntr].
y);
1828 tuple = heap_form_tuple(tupdesc, values, nulls);
1831 result = HeapTupleGetDatum(tuple);
1833 SRF_RETURN_NEXT(funcctx,
result);
1837 SRF_RETURN_DONE(funcctx);
1853 bool exclude_nodata_value =
TRUE;
1866 if (PG_ARGISNULL(0))
1868 pgraster = (
rt_pgraster *) PG_DETOAST_DATUM(PG_GETARG_DATUM(0));
1871 PG_FREE_IF_COPY(pgraster, 0);
1872 elog(ERROR,
"RASTER_nearestValue: Could not deserialize raster");
1877 if (!PG_ARGISNULL(1))
1878 bandindex = PG_GETARG_INT32(1);
1880 if (bandindex < 1 || bandindex > num_bands) {
1881 elog(NOTICE,
"Invalid band index (must use 1-based). Returning NULL");
1883 PG_FREE_IF_COPY(pgraster, 0);
1888 geom = PG_GETARG_GSERIALIZED_P(2);
1890 elog(NOTICE,
"Geometry provided must be a point");
1892 PG_FREE_IF_COPY(pgraster, 0);
1893 PG_FREE_IF_COPY(geom, 2);
1898 if (!PG_ARGISNULL(3))
1899 exclude_nodata_value = PG_GETARG_BOOL(3);
1903 elog(NOTICE,
"SRIDs of geometry and raster do not match");
1905 PG_FREE_IF_COPY(pgraster, 0);
1906 PG_FREE_IF_COPY(geom, 2);
1913 elog(NOTICE,
"Could not find band at index %d. Returning NULL", bandindex);
1915 PG_FREE_IF_COPY(pgraster, 0);
1916 PG_FREE_IF_COPY(geom, 2);
1924 elog(NOTICE,
"Geometry provided cannot be empty");
1926 PG_FREE_IF_COPY(pgraster, 0);
1927 PG_FREE_IF_COPY(geom, 2);
1948 PG_FREE_IF_COPY(pgraster, 0);
1950 PG_FREE_IF_COPY(geom, 2);
1951 elog(ERROR,
"RASTER_nearestValue: Could not compute pixel coordinates from spatial coordinates");
1962 PG_FREE_IF_COPY(pgraster, 0);
1964 PG_FREE_IF_COPY(geom, 2);
1965 elog(ERROR,
"RASTER_nearestValue: Could not get pixel value for band at index %d", bandindex);
1970 if (!exclude_nodata_value || !isnodata) {
1972 PG_FREE_IF_COPY(pgraster, 0);
1974 PG_FREE_IF_COPY(geom, 2);
1976 PG_RETURN_FLOAT8(
value);
1985 exclude_nodata_value,
1993 elog(NOTICE,
"Could not get the nearest value for band at index %d", bandindex);
1996 elog(NOTICE,
"No nearest value found for band at index %d", bandindex);
1999 PG_FREE_IF_COPY(geom, 2);
2001 PG_FREE_IF_COPY(pgraster, 0);
2009 double lastdist = -1;
2012 for (i = 0; i <
count; i++) {
2017 PG_FREE_IF_COPY(geom, 2);
2019 PG_FREE_IF_COPY(pgraster, 0);
2020 elog(ERROR,
"RASTER_nearestValue: Could not get polygon of neighboring pixel");
2026 if (lastdist < 0 || dist < lastdist) {
2042 PG_FREE_IF_COPY(geom, 2);
2044 PG_FREE_IF_COPY(pgraster, 0);
2047 PG_RETURN_FLOAT8(
value);
2068 bool exclude_nodata_value =
TRUE;
2074 double **value2D = NULL;
2075 int **nodata2D = NULL;
2080 Datum *value1D = NULL;
2081 bool *nodata1D = NULL;
2083 int lbound[2] = {1, 1};
2084 ArrayType *mdArray = NULL;
2091 if (PG_ARGISNULL(0))
2093 pgraster = (
rt_pgraster *) PG_DETOAST_DATUM(PG_GETARG_DATUM(0));
2097 PG_FREE_IF_COPY(pgraster, 0);
2098 elog(ERROR,
"RASTER_neighborhood: Could not deserialize raster");
2103 if (!PG_ARGISNULL(1))
2104 bandindex = PG_GETARG_INT32(1);
2106 if (bandindex < 1 || bandindex > num_bands) {
2107 elog(NOTICE,
"Invalid band index (must use 1-based). Returning NULL");
2109 PG_FREE_IF_COPY(pgraster, 0);
2114 x = PG_GETARG_INT32(2);
2118 y = PG_GETARG_INT32(3);
2124 elog(NOTICE,
"Invalid value for distancex (must be >= zero). Returning NULL");
2126 PG_FREE_IF_COPY(pgraster, 0);
2134 elog(NOTICE,
"Invalid value for distancey (must be >= zero). Returning NULL");
2136 PG_FREE_IF_COPY(pgraster, 0);
2142 if (!PG_ARGISNULL(6))
2143 exclude_nodata_value = PG_GETARG_BOOL(6);
2148 elog(NOTICE,
"Could not find band at index %d. Returning NULL", bandindex);
2150 PG_FREE_IF_COPY(pgraster, 0);
2162 exclude_nodata_value,
2167 elog(NOTICE,
"Could not get the pixel's neighborhood for band at index %d", bandindex);
2171 PG_FREE_IF_COPY(pgraster, 0);
2188 elog(NOTICE,
"Could not get the pixel of band at index %d. Returning NULL", bandindex);
2191 PG_FREE_IF_COPY(pgraster, 0);
2214 if (npixels == NULL) {
2218 PG_FREE_IF_COPY(pgraster, 0);
2220 elog(ERROR,
"RASTER_neighborhood: Could not reallocate memory for neighborhood");
2223 npixels[
count - 1].
x = _x;
2224 npixels[
count - 1].
y = _y;
2229 if (!exclude_nodata_value || !isnodata) {
2236 PG_FREE_IF_COPY(pgraster, 0);
2241 npixels,
count, NULL,
2246 &(dim[1]), &(dim[0])
2250 elog(NOTICE,
"Could not create 2D array of neighborhood");
2255 value1D = palloc(
sizeof(Datum) * dim[0] * dim[1]);
2256 nodata1D = palloc(
sizeof(
bool) * dim[0] * dim[1]);
2258 if (value1D == NULL || nodata1D == NULL) {
2260 for (i = 0; i < dim[0]; i++) {
2267 elog(ERROR,
"RASTER_neighborhood: Could not allocate memory for return 2D array");
2274 for (i = 0; i < dim[0]; i++) {
2276 for (j = 0; j < dim[1]; j++) {
2277 nodata1D[k] = (bool) nodata2D[i][j];
2279 value1D[k] = Float8GetDatum(value2D[i][j]);
2281 value1D[k] = PointerGetDatum(NULL);
2288 for (i = 0; i < dim[0]; i++) {
2296 get_typlenbyvalalign(FLOAT8OID, &typlen, &typbyval, &typalign);
2298 mdArray = construct_md_array(
2302 typlen, typbyval, typalign
2308 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.
uint32_t gserialized_get_type(const GSERIALIZED *g)
Extract the geometry type from the serialized form (it hides in the anonymous data area,...
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)
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...
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.
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_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_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.
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_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 rtpg_dumpvalues_arg rtpg_dumpvalues_arg_init()
Datum RASTER_nearestValue(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::@22 pixval