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);
154 rtpg_dumpvalues_arg arg = NULL;
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;
218 rtpg_dumpvalues_arg arg1 = NULL;
219 rtpg_dumpvalues_arg arg2 = NULL;
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++) {
453 for (x = 0; x < arg1->
columns; x++) {
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);
838 if (pixval == NULL) {
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++) {
852 pixval[i].x = ul[0] +
x;
853 pixval[i].y = ul[1] +
y;
855 pixval[i].noset =
FALSE;
856 pixval[i].nodata =
FALSE;
860 pixval[i].nodata =
TRUE;
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]))
951 pixval[j].noset =
TRUE;
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++) {
1012 if (pixval[i].noset)
1015 else if (hasnosetval) {
1017 if (pixval[i].
nodata && nosetvalisnull)
1020 else if (!pixval[i].
nodata && !nosetvalisnull &&
FLT_EQ(pixval[i].
value, nosetval))
1026 (pixval[i].x < 0 || pixval[i].x >= width) ||
1027 (pixval[i].y < 0 || pixval[i].y >= height)
1029 elog(NOTICE,
"Cannot set value for pixel (%d, %d) outside raster bounds: %d x %d",
1030 pixval[i].x + 1, pixval[i].y + 1,
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);
1081 rtpg_setvaluesgv_geomval
gv;
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)
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])
1172 *value = arg->
values[0][0][0];
1196 double nodataval = 0;
1198 rtpg_setvaluesgv_arg arg = NULL;
1210 HeapTupleHeader tup;
1216 unsigned char *wkb = NULL;
1224 if (PG_ARGISNULL(0))
1226 pgraster = (
rt_pgraster *) PG_DETOAST_DATUM_COPY(PG_GETARG_DATUM(0));
1231 PG_FREE_IF_COPY(pgraster, 0);
1232 elog(ERROR,
"RASTER_setPixelValuesGeomval: Could not deserialize raster");
1244 if (PG_ARGISNULL(1)) {
1245 elog(NOTICE,
"Band index cannot be NULL. Value must be 1-based. Returning original raster");
1247 PG_RETURN_POINTER(pgraster);
1250 nband = PG_GETARG_INT32(1);
1251 if (nband < 1 || nband > numbands) {
1252 elog(NOTICE,
"Band index is invalid. Value must be 1-based. Returning original raster");
1254 PG_RETURN_POINTER(pgraster);
1265 if (PG_ARGISNULL(2)) {
1266 elog(NOTICE,
"No values to set. Returning original raster");
1268 PG_RETURN_POINTER(pgraster);
1271 array = PG_GETARG_ARRAYTYPE_P(2);
1272 etype = ARR_ELEMTYPE(array);
1273 get_typlenbyvalalign(etype, &typlen, &typbyval, &typalign);
1278 typlen, typbyval, typalign,
1283 elog(NOTICE,
"No values to set. Returning original raster");
1285 PG_RETURN_POINTER(pgraster);
1292 PG_FREE_IF_COPY(pgraster, 0);
1293 elog(ERROR,
"RASTER_setPixelValuesGeomval: Could not intialize argument structure");
1298 if (arg->
gv == NULL) {
1301 PG_FREE_IF_COPY(pgraster, 0);
1302 elog(ERROR,
"RASTER_setPixelValuesGeomval: Could not allocate memory for geomval array");
1308 for (i = 0; i < n; i++) {
1318 tup = (HeapTupleHeader) DatumGetPointer(e[i]);
1322 PG_FREE_IF_COPY(pgraster, 0);
1323 elog(ERROR,
"RASTER_setPixelValuesGeomval: Invalid argument for geomval at index %d", i);
1329 tupv = GetAttributeByName(tup,
"geom", &isnull);
1331 elog(NOTICE,
"First argument (geom) of geomval at index %d is NULL. Skipping", i);
1340 PG_FREE_IF_COPY(pgraster, 0);
1341 elog(ERROR,
"RASTER_setPixelValuesGeomval: Could not deserialize geometry of geomval at index %d", i);
1347 elog(NOTICE,
"First argument (geom) of geomval at index %d is an empty geometry. Skipping", i);
1353 elog(NOTICE,
"Geometry provided for geomval at index %d does not have the same SRID as the raster: %d. Returning original raster", i, srid);
1356 PG_RETURN_POINTER(pgraster);
1401 PG_FREE_IF_COPY(pgraster, 0);
1402 elog(ERROR,
"RASTER_setPixelValuesGeomval: Could not rasterize geometry of geomval at index %d", i);
1411 tupv = GetAttributeByName(tup,
"val", &isnull);
1413 elog(NOTICE,
"Second argument (val) of geomval at index %d is NULL. Treating as NODATA", i);
1425 if (arg->
gv == NULL) {
1428 PG_FREE_IF_COPY(pgraster, 0);
1429 elog(ERROR,
"RASTER_setPixelValuesGeomval: Could not reallocate memory for geomval array");
1435 if (!PG_ARGISNULL(3))
1441 POSTGIS_RT_DEBUG(3,
"keepnodata = TRUE and band is NODATA. Not doing anything");
1444 else if (allpoint == arg->
ngv) {
1445 double igt[6] = {0};
1454 POSTGIS_RT_DEBUG(3,
"all geometries are points, using direct to pixel method");
1460 for (i = 0; i < arg->
ngv; i++) {
1465 for (j = 0; j < coll->
ngeoms; j++) {
1472 PG_FREE_IF_COPY(pgraster, 0);
1473 elog(ERROR,
"RASTER_setPixelValuesGeomval: Could not process coordinates of point");
1479 (xy[0] < 0 || xy[0] >= width) ||
1480 (xy[1] < 0 || xy[1] >= height)
1482 elog(NOTICE,
"Point is outside raster extent. Skipping");
1490 PG_FREE_IF_COPY(pgraster, 0);
1491 elog(ERROR,
"RASTER_setPixelValuesGeomval: Could not get pixel value");
1508 PG_FREE_IF_COPY(pgraster, 0);
1509 elog(ERROR,
"RASTER_setPixelValuesGeomval: Could not set pixel value");
1523 if (itrset == NULL) {
1526 PG_FREE_IF_COPY(pgraster, 0);
1527 elog(ERROR,
"RASTER_setPixelValuesGeomval: Could not allocate memory for iterator arguments");
1533 itrset[0].
nband = nband - 1;
1537 for (i = 0, j = 1; i < arg->
ngv; i++, j++) {
1539 itrset[j].
nband = 0;
1545 itrset, arg->
ngv + 1,
1548 hasnodata, nodataval,
1560 PG_FREE_IF_COPY(pgraster, 0);
1561 elog(ERROR,
"RASTER_setPixelValuesGeomval: Could not run raster iterator function");
1567 if (_band == NULL) {
1571 PG_FREE_IF_COPY(pgraster, 0);
1572 elog(ERROR,
"RASTER_setPixelValuesGeomval: Could not get band from working raster");
1577 if (_band == NULL) {
1581 PG_FREE_IF_COPY(pgraster, 0);
1582 elog(ERROR,
"RASTER_setPixelValuesGeomval: Could not replace band in output raster");
1594 PG_FREE_IF_COPY(pgraster, 0);
1601 SET_VARSIZE(pgrtn, pgrtn->
size);
1602 PG_RETURN_POINTER(pgrtn);
1605 #undef VALUES_LENGTH 1606 #define VALUES_LENGTH 3 1614 FuncCallContext *funcctx;
1625 if (SRF_IS_FIRSTCALL()) {
1626 MemoryContext oldcontext;
1633 double *search = NULL;
1636 bool exclude_nodata_value =
TRUE;
1647 funcctx = SRF_FIRSTCALL_INIT();
1650 oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);
1652 if (PG_ARGISNULL(0)) {
1653 MemoryContextSwitchTo(oldcontext);
1654 SRF_RETURN_DONE(funcctx);
1656 pgraster = (
rt_pgraster *) PG_DETOAST_DATUM(PG_GETARG_DATUM(0));
1659 PG_FREE_IF_COPY(pgraster, 0);
1660 MemoryContextSwitchTo(oldcontext);
1661 elog(ERROR,
"RASTER_pixelOfValue: Could not deserialize raster");
1662 SRF_RETURN_DONE(funcctx);
1667 if (num_bands < 1) {
1668 elog(NOTICE,
"Raster provided has no bands");
1670 PG_FREE_IF_COPY(pgraster, 0);
1671 MemoryContextSwitchTo(oldcontext);
1672 SRF_RETURN_DONE(funcctx);
1676 if (!PG_ARGISNULL(1))
1677 nband = PG_GETARG_INT32(1);
1678 if (nband < 1 || nband > num_bands) {
1679 elog(NOTICE,
"Invalid band index (must use 1-based). Returning NULL");
1681 PG_FREE_IF_COPY(pgraster, 0);
1682 MemoryContextSwitchTo(oldcontext);
1683 SRF_RETURN_DONE(funcctx);
1687 array = PG_GETARG_ARRAYTYPE_P(2);
1688 etype = ARR_ELEMTYPE(array);
1689 get_typlenbyvalalign(etype, &typlen, &typbyval, &typalign);
1697 PG_FREE_IF_COPY(pgraster, 0);
1698 MemoryContextSwitchTo(oldcontext);
1699 elog(ERROR,
"RASTER_pixelOfValue: Invalid data type for pixel values");
1700 SRF_RETURN_DONE(funcctx);
1704 deconstruct_array(array, etype, typlen, typbyval, typalign, &e,
1707 search = palloc(
sizeof(
double) * n);
1708 for (i = 0, nsearch = 0; i < n; i++) {
1709 if (nulls[i])
continue;
1713 val = (double) DatumGetFloat4(e[i]);
1716 val = (double) DatumGetFloat8(e[i]);
1720 search[nsearch] = val;
1727 elog(NOTICE,
"No search values provided. Returning NULL");
1730 PG_FREE_IF_COPY(pgraster, 0);
1731 MemoryContextSwitchTo(oldcontext);
1732 SRF_RETURN_DONE(funcctx);
1734 else if (nsearch < n)
1735 search = repalloc(search,
sizeof(
double) * nsearch);
1738 if (!PG_ARGISNULL(3))
1739 exclude_nodata_value = PG_GETARG_BOOL(3);
1744 elog(NOTICE,
"Could not find band at index %d. Returning NULL", nband);
1746 PG_FREE_IF_COPY(pgraster, 0);
1747 MemoryContextSwitchTo(oldcontext);
1748 SRF_RETURN_DONE(funcctx);
1753 band, exclude_nodata_value,
1760 PG_FREE_IF_COPY(pgraster, 0);
1764 elog(NOTICE,
"Could not get the pixels of search values for band at index %d", nband);
1767 elog(NOTICE,
"No pixels of search values found for band at index %d", nband);
1769 MemoryContextSwitchTo(oldcontext);
1770 SRF_RETURN_DONE(funcctx);
1774 funcctx->user_fctx = pixels;
1777 funcctx->max_calls =
count;
1780 if (get_call_result_type(fcinfo, NULL, &tupdesc) != TYPEFUNC_COMPOSITE) {
1782 errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1784 "function returning record called in context " 1785 "that cannot accept type record" 1790 BlessTupleDesc(tupdesc);
1791 funcctx->tuple_desc = tupdesc;
1793 MemoryContextSwitchTo(oldcontext);
1797 funcctx = SRF_PERCALL_SETUP();
1799 call_cntr = funcctx->call_cntr;
1800 max_calls = funcctx->max_calls;
1801 tupdesc = funcctx->tuple_desc;
1802 pixels2 = funcctx->user_fctx;
1805 if (call_cntr < max_calls) {
1814 pixels2[call_cntr].
x += 1;
1815 pixels2[call_cntr].
y += 1;
1817 values[0] = Float8GetDatum(pixels2[call_cntr].
value);
1818 values[1] = Int32GetDatum(pixels2[call_cntr].
x);
1819 values[2] = Int32GetDatum(pixels2[call_cntr].
y);
1822 tuple = heap_form_tuple(tupdesc, values, nulls);
1825 result = HeapTupleGetDatum(tuple);
1827 SRF_RETURN_NEXT(funcctx, result);
1831 SRF_RETURN_DONE(funcctx);
1847 bool exclude_nodata_value =
TRUE;
1860 if (PG_ARGISNULL(0))
1862 pgraster = (
rt_pgraster *) PG_DETOAST_DATUM(PG_GETARG_DATUM(0));
1865 PG_FREE_IF_COPY(pgraster, 0);
1866 elog(ERROR,
"RASTER_nearestValue: Could not deserialize raster");
1871 if (!PG_ARGISNULL(1))
1872 bandindex = PG_GETARG_INT32(1);
1874 if (bandindex < 1 || bandindex > num_bands) {
1875 elog(NOTICE,
"Invalid band index (must use 1-based). Returning NULL");
1877 PG_FREE_IF_COPY(pgraster, 0);
1882 geom = PG_GETARG_GSERIALIZED_P(2);
1884 elog(NOTICE,
"Geometry provided must be a point");
1886 PG_FREE_IF_COPY(pgraster, 0);
1887 PG_FREE_IF_COPY(geom, 2);
1892 if (!PG_ARGISNULL(3))
1893 exclude_nodata_value = PG_GETARG_BOOL(3);
1897 elog(NOTICE,
"SRIDs of geometry and raster do not match");
1899 PG_FREE_IF_COPY(pgraster, 0);
1900 PG_FREE_IF_COPY(geom, 2);
1907 elog(NOTICE,
"Could not find band at index %d. Returning NULL", bandindex);
1909 PG_FREE_IF_COPY(pgraster, 0);
1910 PG_FREE_IF_COPY(geom, 2);
1918 elog(NOTICE,
"Geometry provided cannot be empty");
1920 PG_FREE_IF_COPY(pgraster, 0);
1921 PG_FREE_IF_COPY(geom, 2);
1942 PG_FREE_IF_COPY(pgraster, 0);
1944 PG_FREE_IF_COPY(geom, 2);
1945 elog(ERROR,
"RASTER_nearestValue: Could not compute pixel coordinates from spatial coordinates");
1956 PG_FREE_IF_COPY(pgraster, 0);
1958 PG_FREE_IF_COPY(geom, 2);
1959 elog(ERROR,
"RASTER_nearestValue: Could not get pixel value for band at index %d", bandindex);
1964 if (!exclude_nodata_value || !isnodata) {
1966 PG_FREE_IF_COPY(pgraster, 0);
1968 PG_FREE_IF_COPY(geom, 2);
1970 PG_RETURN_FLOAT8(value);
1979 exclude_nodata_value,
1987 elog(NOTICE,
"Could not get the nearest value for band at index %d", bandindex);
1990 elog(NOTICE,
"No nearest value found for band at index %d", bandindex);
1993 PG_FREE_IF_COPY(geom, 2);
1995 PG_FREE_IF_COPY(pgraster, 0);
2003 double lastdist = -1;
2006 for (i = 0; i <
count; i++) {
2011 PG_FREE_IF_COPY(geom, 2);
2013 PG_FREE_IF_COPY(pgraster, 0);
2014 elog(ERROR,
"RASTER_nearestValue: Could not get polygon of neighboring pixel");
2020 if (lastdist < 0 || dist < lastdist) {
2021 value = npixels[i].
value;
2030 value = npixels[0].
value;
2036 PG_FREE_IF_COPY(geom, 2);
2038 PG_FREE_IF_COPY(pgraster, 0);
2041 PG_RETURN_FLOAT8(value);
2062 bool exclude_nodata_value =
TRUE;
2068 double **value2D = NULL;
2069 int **nodata2D = NULL;
2074 Datum *value1D = NULL;
2075 bool *nodata1D = NULL;
2077 int lbound[2] = {1, 1};
2078 ArrayType *mdArray = NULL;
2085 if (PG_ARGISNULL(0))
2087 pgraster = (
rt_pgraster *) PG_DETOAST_DATUM(PG_GETARG_DATUM(0));
2091 PG_FREE_IF_COPY(pgraster, 0);
2092 elog(ERROR,
"RASTER_neighborhood: Could not deserialize raster");
2097 if (!PG_ARGISNULL(1))
2098 bandindex = PG_GETARG_INT32(1);
2100 if (bandindex < 1 || bandindex > num_bands) {
2101 elog(NOTICE,
"Invalid band index (must use 1-based). Returning NULL");
2103 PG_FREE_IF_COPY(pgraster, 0);
2108 x = PG_GETARG_INT32(2);
2112 y = PG_GETARG_INT32(3);
2116 distance[0] = PG_GETARG_INT32(4);
2117 if (distance[0] < 0) {
2118 elog(NOTICE,
"Invalid value for distancex (must be >= zero). Returning NULL");
2120 PG_FREE_IF_COPY(pgraster, 0);
2123 distance[0] = (uint16_t) distance[0];
2126 distance[1] = PG_GETARG_INT32(5);
2127 if (distance[1] < 0) {
2128 elog(NOTICE,
"Invalid value for distancey (must be >= zero). Returning NULL");
2130 PG_FREE_IF_COPY(pgraster, 0);
2133 distance[1] = (uint16_t) distance[1];
2136 if (!PG_ARGISNULL(6))
2137 exclude_nodata_value = PG_GETARG_BOOL(6);
2142 elog(NOTICE,
"Could not find band at index %d. Returning NULL", bandindex);
2144 PG_FREE_IF_COPY(pgraster, 0);
2151 if (distance[0] > 0 || distance[1] > 0) {
2155 distance[0], distance[1],
2156 exclude_nodata_value,
2161 elog(NOTICE,
"Could not get the pixel's neighborhood for band at index %d", bandindex);
2165 PG_FREE_IF_COPY(pgraster, 0);
2182 elog(NOTICE,
"Could not get the pixel of band at index %d. Returning NULL", bandindex);
2185 PG_FREE_IF_COPY(pgraster, 0);
2208 if (npixels == NULL) {
2212 PG_FREE_IF_COPY(pgraster, 0);
2214 elog(ERROR,
"RASTER_neighborhood: Could not reallocate memory for neighborhood");
2217 npixels[count - 1].
x = _x;
2218 npixels[count - 1].
y = _y;
2219 npixels[count - 1].
nodata = 1;
2223 if (!exclude_nodata_value || !isnodata) {
2224 npixels[count - 1].
nodata = 0;
2230 PG_FREE_IF_COPY(pgraster, 0);
2235 npixels, count, NULL,
2237 distance[0], distance[1],
2240 &(dim[1]), &(dim[0])
2244 elog(NOTICE,
"Could not create 2D array of neighborhood");
2249 value1D = palloc(
sizeof(Datum) * dim[0] * dim[1]);
2250 nodata1D = palloc(
sizeof(
bool) * dim[0] * dim[1]);
2252 if (value1D == NULL || nodata1D == NULL) {
2254 for (i = 0; i < dim[0]; i++) {
2261 elog(ERROR,
"RASTER_neighborhood: Could not allocate memory for return 2D array");
2268 for (i = 0; i < dim[0]; i++) {
2270 for (j = 0; j < dim[1]; j++) {
2271 nodata1D[k] = (bool) nodata2D[i][j];
2273 value1D[k] = Float8GetDatum(value2D[i][j]);
2275 value1D[k] = PointerGetDatum(NULL);
2282 for (i = 0; i < dim[0]; i++) {
2290 get_typlenbyvalalign(FLOAT8OID, &typlen, &typbyval, &typalign);
2292 mdArray = construct_md_array(
2296 typlen, typbyval, typalign
2302 PG_RETURN_ARRAYTYPE_P(mdArray);
static int rtpg_setvalues_geomval_callback(rt_iterator_arg arg, void *userarg, double *value, int *nodata)
uint32_t gserialized_get_type(const GSERIALIZED *s)
Extract the geometry type from the serialized form (it hides in the anonymous data area...
int clamp_srid(int srid)
Return a valid SRID from an arbitrary integer Raises a notice if what comes out is different from wha...
void * rt_raster_serialize(rt_raster raster)
Return this raster in serialized form.
int rt_raster_get_num_bands(rt_raster raster)
LWGEOM * lwgeom_from_gserialized(const GSERIALIZED *g)
Allocate a new LWGEOM from a GSERIALIZED.
raster
Be careful!! Zeros function's input parameter can be a (height x width) array, not (width x height): ...
struct rt_pixel_t * rt_pixel
rt_errorstate rt_pixel_set_to_array(rt_pixel npixel, int count, rt_mask mask, int x, int y, uint16_t distancex, uint16_t distancey, double ***value, int ***nodata, int *dimx, int *dimy)
struct rtpg_dumpvalues_arg_t * rtpg_dumpvalues_arg
void rt_raster_get_geotransform_matrix(rt_raster raster, double *gt)
Get 6-element array of raster geotransform matrix.
void lwgeom_free(LWGEOM *geom)
rtpg_setvaluesgv_geomval gv
Datum RASTER_neighborhood(PG_FUNCTION_ARGS)
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.
Datum RASTER_setPixelValue(PG_FUNCTION_ARGS)
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.
LWGEOM * lwgeom_as_multi(const LWGEOM *lwgeom)
Create a new LWGEOM of the appropriate MULTI* type.
void rt_band_destroy(rt_band band)
Destroy a raster band.
LWPOINT * lwgeom_as_lwpoint(const LWGEOM *lwgeom)
LWGEOM * lwpoly_as_lwgeom(const LWPOLY *obj)
int lwgeom_ndims(const LWGEOM *geom)
Return the number of dimensions (2, 3, 4) in a geometry.
Datum RASTER_dumpValues(PG_FUNCTION_ARGS)
int rt_raster_is_empty(rt_raster raster)
Return TRUE if the raster is empty.
#define POSTGIS_RT_DEBUGF(level, msg,...)
rt_errorstate rt_band_get_nodata(rt_band band, double *nodata)
Get NODATA value.
Datum RASTER_getPixelValue(PG_FUNCTION_ARGS)
uint8_t * lwgeom_to_wkb(const LWGEOM *geom, uint8_t variant, size_t *size_out)
Convert LWGEOM to a char* in WKB format.
static void rtpg_dumpvalues_arg_destroy(rtpg_dumpvalues_arg arg)
static rtpg_dumpvalues_arg rtpg_dumpvalues_arg_init()
void lwpoly_free(LWPOLY *poly)
struct rtpg_setvaluesgv_arg_t * rtpg_setvaluesgv_arg
rt_errorstate rt_band_get_pixel(rt_band band, int x, int y, double *value, int *nodata)
Get pixel value.
PG_FUNCTION_INFO_V1(RASTER_getPixelValue)
Return value of a single pixel.
LWGEOM * lwgeom_force_2d(const LWGEOM *geom)
Strip out the Z/M components of an LWGEOM.
int rt_band_clamped_value_is_nodata(rt_band band, double val)
Compare clamped value to band's clamped NODATA value.
rt_band rt_raster_get_band(rt_raster raster, int bandNum)
Return Nth band, or NULL if unavailable.
int rt_band_get_hasnodata_flag(rt_band band)
Get hasnodata flag value.
LWPOLY * rt_raster_pixel_as_polygon(rt_raster raster, int x, int y)
Get a raster pixel as a polygon.
uint16_t rt_band_get_width(rt_band band)
Return width of this band.
int rt_raster_has_band(rt_raster raster, int nband)
Return TRUE if the raster has a band of this number.
uint16_t rt_band_get_height(rt_band band)
Return height of this band.
struct rtpg_setvaluesgv_geomval_t * rtpg_setvaluesgv_geomval
void rt_raster_set_srid(rt_raster raster, int32_t srid)
Set raster's SRID.
Datum RASTER_nearestValue(PG_FUNCTION_ARGS)
int32_t rt_raster_get_srid(rt_raster raster)
Get raster's SRID.
void rt_raster_destroy(rt_raster raster)
Release memory associated to a raster.
rt_band rt_raster_replace_band(rt_raster raster, rt_band band, int index)
Replace band at provided index with new band.
int getPoint2d_p(const POINTARRAY *pa, int n, POINT2D *point)
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.
Datum distance(PG_FUNCTION_ARGS)
static rtpg_setvaluesgv_arg rtpg_setvaluesgv_arg_init()
Datum RASTER_setPixelValuesArray(PG_FUNCTION_ARGS)
uint16_t rt_raster_get_width(rt_raster raster)
struct rtpg_setvaluesgv_geomval_t::@19 pixval
double rt_band_get_min_value(rt_band band)
Returns the minimal possible value for the band according to the pixel type.
rt_errorstate rt_raster_get_inverse_geotransform_matrix(rt_raster raster, double *gt, double *igt)
Get 6-element array of raster inverse geotransform matrix.
LWCOLLECTION * lwgeom_as_lwcollection(const LWGEOM *lwgeom)
static void rtpg_setvaluesgv_arg_destroy(rtpg_setvaluesgv_arg arg)
rt_errorstate rt_raster_iterator(rt_iterator itrset, uint16_t itrcount, rt_extenttype extenttype, rt_raster customextent, rt_pixtype pixtype, uint8_t hasnodata, double nodataval, uint16_t distancex, uint16_t distancey, rt_mask mask, void *userarg, int(*callback)(rt_iterator_arg arg, void *userarg, double *value, int *nodata), rt_raster *rtnraster)
n-raster iterator.
rt_pixtype rt_band_get_pixtype(rt_band band)
Return pixeltype of this band.
#define POINTTYPE
LWTYPE numbers, used internally by PostGIS.
double lwgeom_mindistance2d(const LWGEOM *lw1, const LWGEOM *lw2)
Function initialazing min distance calculation.
int rt_band_get_isnodata_flag(rt_band band)
Get isnodata flag value.
rt_errorstate rt_band_set_pixel(rt_band band, int x, int y, double val, int *converted)
Set single pixel's value.
uint16_t rt_raster_get_height(rt_raster raster)
#define POSTGIS_RT_DEBUG(level, msg)
int lwgeom_is_empty(const LWGEOM *geom)
Return true or false depending on whether a geometry is an "empty" geometry (no vertices members) ...
Datum RASTER_setPixelValuesGeomval(PG_FUNCTION_ARGS)
int 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.
rt_raster rt_raster_deserialize(void *serialized, int header_only)
Return a raster from a serialized form.
int32_t gserialized_get_srid(const GSERIALIZED *s)
Extract the SRID from the serialized form (it is packed into three bytes so this is a handy function)...
Datum RASTER_pixelOfValue(PG_FUNCTION_ARGS)