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" 41 #if POSTGIS_PGSQL_VERSION > 92 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)
203 FuncCallContext *funcctx;
216 rtpg_dumpvalues_arg arg1 = NULL;
217 rtpg_dumpvalues_arg arg2 = NULL;
220 if (SRF_IS_FIRSTCALL()) {
221 MemoryContext oldcontext;
227 bool exclude_nodata_value =
TRUE;
240 funcctx = SRF_FIRSTCALL_INIT();
243 oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);
246 if (PG_ARGISNULL(0)) {
247 MemoryContextSwitchTo(oldcontext);
248 SRF_RETURN_DONE(funcctx);
250 pgraster = (
rt_pgraster *) PG_DETOAST_DATUM(PG_GETARG_DATUM(0));
254 PG_FREE_IF_COPY(pgraster, 0);
256 errcode(ERRCODE_OUT_OF_MEMORY),
257 errmsg(
"Could not deserialize raster")
259 MemoryContextSwitchTo(oldcontext);
260 SRF_RETURN_DONE(funcctx);
277 elog(NOTICE,
"Raster provided has no bands");
279 PG_FREE_IF_COPY(pgraster, 0);
280 MemoryContextSwitchTo(oldcontext);
281 SRF_RETURN_DONE(funcctx);
288 PG_FREE_IF_COPY(pgraster, 0);
289 MemoryContextSwitchTo(oldcontext);
290 elog(ERROR,
"RASTER_dumpValues: Could not initialize argument structure");
291 SRF_RETURN_DONE(funcctx);
295 if (!PG_ARGISNULL(1)) {
296 array = PG_GETARG_ARRAYTYPE_P(1);
297 etype = ARR_ELEMTYPE(array);
298 get_typlenbyvalalign(etype, &typlen, &typbyval, &typalign);
307 PG_FREE_IF_COPY(pgraster, 0);
308 MemoryContextSwitchTo(oldcontext);
309 elog(ERROR,
"RASTER_dumpValues: Invalid data type for band indexes");
310 SRF_RETURN_DONE(funcctx);
314 deconstruct_array(array, etype, typlen, typbyval, typalign, &e, &nulls, &(arg1->
numbands));
317 if (arg1->
nbands == NULL) {
320 PG_FREE_IF_COPY(pgraster, 0);
321 MemoryContextSwitchTo(oldcontext);
322 elog(ERROR,
"RASTER_dumpValues: Could not allocate memory for band indexes");
323 SRF_RETURN_DONE(funcctx);
326 for (i = 0, j = 0; i < arg1->
numbands; i++) {
327 if (nulls[i])
continue;
331 arg1->
nbands[j] = DatumGetInt16(e[i]) - 1;
334 arg1->
nbands[j] = DatumGetInt32(e[i]) - 1;
341 if (j < arg1->numbands) {
343 if (arg1->
nbands == NULL) {
346 PG_FREE_IF_COPY(pgraster, 0);
347 MemoryContextSwitchTo(oldcontext);
348 elog(ERROR,
"RASTER_dumpValues: Could not reallocate memory for band indexes");
349 SRF_RETURN_DONE(funcctx);
356 for (i = 0; i < arg1->
numbands; i++) {
358 elog(NOTICE,
"Band at index %d not found in raster", arg1->
nbands[i] + 1);
361 PG_FREE_IF_COPY(pgraster, 0);
362 MemoryContextSwitchTo(oldcontext);
363 SRF_RETURN_DONE(funcctx);
373 if (arg1->
nbands == NULL) {
376 PG_FREE_IF_COPY(pgraster, 0);
377 MemoryContextSwitchTo(oldcontext);
378 elog(ERROR,
"RASTER_dumpValues: Could not allocate memory for band indexes");
379 SRF_RETURN_DONE(funcctx);
382 for (i = 0; i < arg1->
numbands; i++) {
392 if (!PG_ARGISNULL(2))
393 exclude_nodata_value = PG_GETARG_BOOL(2);
402 PG_FREE_IF_COPY(pgraster, 0);
403 MemoryContextSwitchTo(oldcontext);
404 elog(ERROR,
"RASTER_dumpValues: Could not allocate memory for pixel values");
405 SRF_RETURN_DONE(funcctx);
411 for (z = 0; z < arg1->
numbands; z++) {
421 PG_FREE_IF_COPY(pgraster, 0);
422 MemoryContextSwitchTo(oldcontext);
423 elog(ERROR,
"RASTER_dumpValues: Could not get band at index %d", nband);
424 SRF_RETURN_DONE(funcctx);
430 if (arg1->
values[z] == NULL || arg1->
nodata[z] == NULL) {
433 PG_FREE_IF_COPY(pgraster, 0);
434 MemoryContextSwitchTo(oldcontext);
435 elog(ERROR,
"RASTER_dumpValues: Could not allocate memory for pixel values");
436 SRF_RETURN_DONE(funcctx);
445 for (i = (arg1->
rows * arg1->
columns) - 1; i >= 0; i--)
450 for (y = 0; y < arg1->
rows; y++) {
451 for (x = 0; x < arg1->
columns; x++) {
457 PG_FREE_IF_COPY(pgraster, 0);
458 MemoryContextSwitchTo(oldcontext);
459 elog(ERROR,
"RASTER_dumpValues: Could not pixel (%d, %d) of band %d", x, y, nband);
460 SRF_RETURN_DONE(funcctx);
463 arg1->
values[z][i] = Float8GetDatum(val);
467 if (exclude_nodata_value && isnodata) {
481 PG_FREE_IF_COPY(pgraster, 0);
484 funcctx->user_fctx = arg1;
487 funcctx->max_calls = arg1->
numbands;
490 if (get_call_result_type(fcinfo, NULL, &tupdesc) != TYPEFUNC_COMPOSITE) {
491 MemoryContextSwitchTo(oldcontext);
493 errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
495 "function returning record called in context " 496 "that cannot accept type record" 501 BlessTupleDesc(tupdesc);
502 funcctx->tuple_desc = tupdesc;
504 MemoryContextSwitchTo(oldcontext);
508 funcctx = SRF_PERCALL_SETUP();
510 call_cntr = funcctx->call_cntr;
511 max_calls = funcctx->max_calls;
512 tupdesc = funcctx->tuple_desc;
513 arg2 = funcctx->user_fctx;
516 if (call_cntr < max_calls) {
517 int values_length = 2;
518 Datum
values[values_length];
519 bool nulls[values_length];
522 ArrayType *mdValues = NULL;
525 int lbound[2] = {1, 1};
530 memset(nulls,
FALSE,
sizeof(
bool) * values_length);
532 values[0] = Int32GetDatum(arg2->
nbands[call_cntr] + 1);
535 get_typlenbyvalalign(FLOAT8OID, &typlen, &typbyval, &typalign);
538 if (arg2->
values[call_cntr] == NULL)
542 mdValues = construct_md_array(
546 typlen, typbyval, typalign
548 values[1] = PointerGetDatum(mdValues);
551 tuple = heap_form_tuple(tupdesc, values, nulls);
552 result = HeapTupleGetDatum(tuple);
554 SRF_RETURN_NEXT(funcctx, result);
559 SRF_RETURN_DONE(funcctx);
574 int32_t bandindex = 0;
577 bool skipset =
FALSE;
586 bandindex = PG_GETARG_INT32(1);
589 elog(NOTICE,
"Invalid band index (must use 1-based). Value not set. Returning original raster");
594 if (PG_ARGISNULL(2)) {
595 elog(NOTICE,
"X coordinate can not be NULL when setting pixel value. Value not set. Returning original raster");
599 x = PG_GETARG_INT32(2);
601 if (PG_ARGISNULL(3)) {
602 elog(NOTICE,
"Y coordinate can not be NULL when setting pixel value. Value not set. Returning original raster");
606 y = PG_GETARG_INT32(3);
611 pgraster = (
rt_pgraster *) PG_DETOAST_DATUM_COPY(PG_GETARG_DATUM(0));
615 PG_FREE_IF_COPY(pgraster, 0);
616 elog(ERROR,
"RASTER_setPixelValue: Could not deserialize raster");
624 elog(NOTICE,
"Could not find raster band of index %d when setting " 625 "pixel value. Value not set. Returning original raster",
627 PG_RETURN_POINTER(pgraster);
631 if (PG_ARGISNULL(4)) {
633 elog(NOTICE,
"Raster do not have a nodata value defined. " 634 "Set band nodata value first. Nodata value not set. " 635 "Returning original raster");
636 PG_RETURN_POINTER(pgraster);
644 pixvalue = PG_GETARG_FLOAT8(4);
652 PG_FREE_IF_COPY(pgraster, 0);
656 SET_VARSIZE(pgrtn, pgrtn->
size);
657 PG_RETURN_POINTER(pgrtn);
696 struct pixelvalue *
pixval = NULL;
698 int dimpixval[2] = {1, 1};
699 int dimnoset[2] = {1, 1};
700 int hasnodata =
FALSE;
701 double nodataval = 0;
702 bool keepnodata =
FALSE;
703 bool hasnosetval =
FALSE;
704 bool nosetvalisnull =
FALSE;
719 pgraster = (
rt_pgraster *) PG_DETOAST_DATUM_COPY(PG_GETARG_DATUM(0));
724 PG_FREE_IF_COPY(pgraster, 0);
725 elog(ERROR,
"RASTER_setPixelValuesArray: Could not deserialize raster");
735 if (PG_ARGISNULL(1)) {
736 elog(NOTICE,
"Band index cannot be NULL. Value must be 1-based. Returning original raster");
738 PG_RETURN_POINTER(pgraster);
741 nband = PG_GETARG_INT32(1);
742 if (nband < 1 || nband > numbands) {
743 elog(NOTICE,
"Band index is invalid. Value must be 1-based. Returning original raster");
745 PG_RETURN_POINTER(pgraster);
749 for (i = 2, j = 0; i < 4; i++, j++) {
750 if (PG_ARGISNULL(i)) {
751 elog(NOTICE,
"%s cannot be NULL. Value must be 1-based. Returning original raster", j < 1 ?
"X" :
"Y");
753 PG_RETURN_POINTER(pgraster);
756 ul[j] = PG_GETARG_INT32(i);
759 (j < 1 && ul[j] > width) ||
760 (j > 0 && ul[j] > height)
763 elog(NOTICE,
"%s is invalid. Value must be 1-based. Returning original raster", j < 1 ?
"X" :
"Y");
765 PG_RETURN_POINTER(pgraster);
773 if (PG_ARGISNULL(4)) {
774 elog(NOTICE,
"No values to set. Returning original raster");
776 PG_RETURN_POINTER(pgraster);
779 array = PG_GETARG_ARRAYTYPE_P(4);
780 etype = ARR_ELEMTYPE(array);
781 get_typlenbyvalalign(etype, &typlen, &typbyval, &typalign);
789 PG_FREE_IF_COPY(pgraster, 0);
790 elog(ERROR,
"RASTER_setPixelValuesArray: Invalid data type for new values");
795 ndims = ARR_NDIM(array);
796 dims = ARR_DIMS(array);
799 if (ndims < 1 || ndims > 2) {
800 elog(NOTICE,
"New values array must be of 1 or 2 dimensions. Returning original raster");
802 PG_RETURN_POINTER(pgraster);
808 dimpixval[1] = dims[0];
810 dimpixval[0] = dims[0];
811 dimpixval[1] = dims[1];
818 typlen, typbyval, typalign,
819 &elements, &nulls, &num
823 if (num < 1 || num != (dimpixval[0] * dimpixval[1])) {
829 PG_FREE_IF_COPY(pgraster, 0);
830 elog(ERROR,
"RASTER_setPixelValuesArray: Could not deconstruct new values array");
836 pixval = palloc(
sizeof(
struct pixelvalue) * numpixval);
837 if (pixval == NULL) {
841 PG_FREE_IF_COPY(pgraster, 0);
842 elog(ERROR,
"RASTER_setPixelValuesArray: Could not allocate memory for new pixel values");
848 for (y = 0; y < dimpixval[0]; y++) {
849 for (x = 0; x < dimpixval[1]; x++) {
851 pixval[i].x = ul[0] +
x;
852 pixval[i].y = ul[1] +
y;
854 pixval[i].noset =
FALSE;
855 pixval[i].nodata =
FALSE;
859 pixval[i].nodata =
TRUE;
863 pixval[i].value = DatumGetFloat4(elements[i]);
866 pixval[i].value = DatumGetFloat8(elements[i]);
879 if (!PG_ARGISNULL(5)) {
880 array = PG_GETARG_ARRAYTYPE_P(5);
881 etype = ARR_ELEMTYPE(array);
882 get_typlenbyvalalign(etype, &typlen, &typbyval, &typalign);
890 PG_FREE_IF_COPY(pgraster, 0);
891 elog(ERROR,
"RASTER_setPixelValuesArray: Invalid data type for noset flags");
896 ndims = ARR_NDIM(array);
897 dims = ARR_DIMS(array);
900 if (ndims < 1 || ndims > 2) {
901 elog(NOTICE,
"Noset flags array must be of 1 or 2 dimensions. Returning original raster");
904 PG_RETURN_POINTER(pgraster);
910 dimnoset[1] = dims[0];
912 dimnoset[0] = dims[0];
913 dimnoset[1] = dims[1];
920 typlen, typbyval, typalign,
921 &elements, &nulls, &num
925 if (num < 1 || num != (dimnoset[0] * dimnoset[1])) {
932 PG_FREE_IF_COPY(pgraster, 0);
933 elog(ERROR,
"RASTER_setPixelValuesArray: Could not deconstruct noset flags array");
939 for (y = 0; y < dimnoset[0]; y++) {
940 if (y >= dimpixval[0])
break;
942 for (x = 0; x < dimnoset[1]; x++) {
944 if (x >= dimpixval[1]) {
945 i += (dimnoset[1] - dimpixval[1]);
949 if (!nulls[i] && DatumGetBool(elements[i]))
950 pixval[j].noset =
TRUE;
957 if (x < dimpixval[1])
958 j += (dimpixval[1] - dimnoset[1]);
965 else if (!PG_ARGISNULL(6) && PG_GETARG_BOOL(6)) {
968 nosetvalisnull =
TRUE;
970 nosetval = PG_GETARG_FLOAT8(7);
973 #if POSTGIS_DEBUG_LEVEL > 0 974 for (i = 0; i < numpixval; i++) {
975 POSTGIS_RT_DEBUGF(4,
"pixval[%d](x, y, noset, nodata, value) = (%d, %d, %d, %d, %f)",
987 if (!PG_ARGISNULL(8))
988 keepnodata = PG_GETARG_BOOL(8);
993 elog(NOTICE,
"Could not find band at index %d. Returning original raster", nband);
996 PG_RETURN_POINTER(pgraster);
1009 for (i = 0; i < numpixval; i++) {
1011 if (pixval[i].noset)
1014 else if (hasnosetval) {
1016 if (pixval[i].
nodata && nosetvalisnull)
1019 else if (!pixval[i].
nodata && !nosetvalisnull &&
FLT_EQ(pixval[i].
value, nosetval))
1025 (pixval[i].x < 0 || pixval[i].x >= width) ||
1026 (pixval[i].y < 0 || pixval[i].y >= height)
1028 elog(NOTICE,
"Cannot set value for pixel (%d, %d) outside raster bounds: %d x %d",
1029 pixval[i].x + 1, pixval[i].y + 1,
1036 if (hasnodata && keepnodata) {
1041 PG_FREE_IF_COPY(pgraster, 0);
1042 elog(ERROR,
"Cannot get value of pixel");
1063 PG_FREE_IF_COPY(pgraster, 0);
1067 SET_VARSIZE(pgrtn, pgrtn->
size);
1068 PG_RETURN_POINTER(pgrtn);
1080 rtpg_setvaluesgv_geomval
gv;
1098 elog(ERROR,
"rtpg_setvaluesgv_arg_init: Could not allocate memory for function arguments");
1112 if (arg->
gv != NULL) {
1113 for (i = 0; i < arg->
ngv; i++) {
1114 if (arg->
gv[i].
geom != NULL)
1116 if (arg->
gv[i].
mask != NULL)
1146 for (i = arg->
rasters - 1, j = funcarg->
ngv - 1; i > 0; i--, j--) {
1150 if (arg->
nodata[i][0][0])
1168 if (arg->
nodata[0][0][0])
1171 *value = arg->
values[0][0][0];
1195 double nodataval = 0;
1197 rtpg_setvaluesgv_arg arg = NULL;
1209 HeapTupleHeader tup;
1215 unsigned char *wkb = NULL;
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);
1400 PG_FREE_IF_COPY(pgraster, 0);
1401 elog(ERROR,
"RASTER_setPixelValuesGeomval: Could not rasterize geometry of geomval at index %d", i);
1410 tupv = GetAttributeByName(tup,
"val", &isnull);
1412 elog(NOTICE,
"Second argument (val) of geomval at index %d is NULL. Treating as NODATA", i);
1424 if (arg->
gv == NULL) {
1427 PG_FREE_IF_COPY(pgraster, 0);
1428 elog(ERROR,
"RASTER_setPixelValuesGeomval: Could not reallocate memory for geomval array");
1434 if (!PG_ARGISNULL(3))
1440 POSTGIS_RT_DEBUG(3,
"keepnodata = TRUE and band is NODATA. Not doing anything");
1443 else if (allpoint == arg->
ngv) {
1444 double igt[6] = {0};
1453 POSTGIS_RT_DEBUG(3,
"all geometries are points, using direct to pixel method");
1459 for (i = 0; i < arg->
ngv; i++) {
1464 for (j = 0; j < coll->
ngeoms; j++) {
1471 PG_FREE_IF_COPY(pgraster, 0);
1472 elog(ERROR,
"RASTER_setPixelValuesGeomval: Could not process coordinates of point");
1478 (xy[0] < 0 || xy[0] >= width) ||
1479 (xy[1] < 0 || xy[1] >= height)
1481 elog(NOTICE,
"Point is outside raster extent. Skipping");
1489 PG_FREE_IF_COPY(pgraster, 0);
1490 elog(ERROR,
"RASTER_setPixelValuesGeomval: Could not get pixel value");
1507 PG_FREE_IF_COPY(pgraster, 0);
1508 elog(ERROR,
"RASTER_setPixelValuesGeomval: Could not set pixel value");
1522 if (itrset == NULL) {
1525 PG_FREE_IF_COPY(pgraster, 0);
1526 elog(ERROR,
"RASTER_setPixelValuesGeomval: Could not allocate memory for iterator arguments");
1532 itrset[0].
nband = nband - 1;
1536 for (i = 0, j = 1; i < arg->
ngv; i++, j++) {
1538 itrset[j].
nband = 0;
1544 itrset, arg->
ngv + 1,
1547 hasnodata, nodataval,
1559 PG_FREE_IF_COPY(pgraster, 0);
1560 elog(ERROR,
"RASTER_setPixelValuesGeomval: Could not run raster iterator function");
1566 if (_band == NULL) {
1570 PG_FREE_IF_COPY(pgraster, 0);
1571 elog(ERROR,
"RASTER_setPixelValuesGeomval: Could not get band from working raster");
1576 if (_band == NULL) {
1580 PG_FREE_IF_COPY(pgraster, 0);
1581 elog(ERROR,
"RASTER_setPixelValuesGeomval: Could not replace band in output raster");
1593 PG_FREE_IF_COPY(pgraster, 0);
1600 SET_VARSIZE(pgrtn, pgrtn->
size);
1601 PG_RETURN_POINTER(pgrtn);
1610 FuncCallContext *funcctx;
1621 if (SRF_IS_FIRSTCALL()) {
1622 MemoryContext oldcontext;
1629 double *search = NULL;
1632 bool exclude_nodata_value =
TRUE;
1643 funcctx = SRF_FIRSTCALL_INIT();
1646 oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);
1648 if (PG_ARGISNULL(0)) {
1649 MemoryContextSwitchTo(oldcontext);
1650 SRF_RETURN_DONE(funcctx);
1652 pgraster = (
rt_pgraster *) PG_DETOAST_DATUM(PG_GETARG_DATUM(0));
1655 PG_FREE_IF_COPY(pgraster, 0);
1656 MemoryContextSwitchTo(oldcontext);
1657 elog(ERROR,
"RASTER_pixelOfValue: Could not deserialize raster");
1658 SRF_RETURN_DONE(funcctx);
1663 if (num_bands < 1) {
1664 elog(NOTICE,
"Raster provided has no bands");
1666 PG_FREE_IF_COPY(pgraster, 0);
1667 MemoryContextSwitchTo(oldcontext);
1668 SRF_RETURN_DONE(funcctx);
1672 if (!PG_ARGISNULL(1))
1673 nband = PG_GETARG_INT32(1);
1674 if (nband < 1 || nband > num_bands) {
1675 elog(NOTICE,
"Invalid band index (must use 1-based). Returning NULL");
1677 PG_FREE_IF_COPY(pgraster, 0);
1678 MemoryContextSwitchTo(oldcontext);
1679 SRF_RETURN_DONE(funcctx);
1683 array = PG_GETARG_ARRAYTYPE_P(2);
1684 etype = ARR_ELEMTYPE(array);
1685 get_typlenbyvalalign(etype, &typlen, &typbyval, &typalign);
1693 PG_FREE_IF_COPY(pgraster, 0);
1694 MemoryContextSwitchTo(oldcontext);
1695 elog(ERROR,
"RASTER_pixelOfValue: Invalid data type for pixel values");
1696 SRF_RETURN_DONE(funcctx);
1700 deconstruct_array(array, etype, typlen, typbyval, typalign, &e,
1703 search = palloc(
sizeof(
double) * n);
1704 for (i = 0, nsearch = 0; i < n; i++) {
1705 if (nulls[i])
continue;
1709 val = (double) DatumGetFloat4(e[i]);
1712 val = (double) DatumGetFloat8(e[i]);
1716 search[nsearch] = val;
1723 elog(NOTICE,
"No search values provided. Returning NULL");
1726 PG_FREE_IF_COPY(pgraster, 0);
1727 MemoryContextSwitchTo(oldcontext);
1728 SRF_RETURN_DONE(funcctx);
1730 else if (nsearch < n)
1731 search = repalloc(search,
sizeof(
double) * nsearch);
1734 if (!PG_ARGISNULL(3))
1735 exclude_nodata_value = PG_GETARG_BOOL(3);
1740 elog(NOTICE,
"Could not find band at index %d. Returning NULL", nband);
1742 PG_FREE_IF_COPY(pgraster, 0);
1743 MemoryContextSwitchTo(oldcontext);
1744 SRF_RETURN_DONE(funcctx);
1749 band, exclude_nodata_value,
1756 PG_FREE_IF_COPY(pgraster, 0);
1760 elog(NOTICE,
"Could not get the pixels of search values for band at index %d", nband);
1763 elog(NOTICE,
"No pixels of search values found for band at index %d", nband);
1765 MemoryContextSwitchTo(oldcontext);
1766 SRF_RETURN_DONE(funcctx);
1770 funcctx->user_fctx = pixels;
1773 funcctx->max_calls =
count;
1776 if (get_call_result_type(fcinfo, NULL, &tupdesc) != TYPEFUNC_COMPOSITE) {
1778 errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1780 "function returning record called in context " 1781 "that cannot accept type record" 1786 BlessTupleDesc(tupdesc);
1787 funcctx->tuple_desc = tupdesc;
1789 MemoryContextSwitchTo(oldcontext);
1793 funcctx = SRF_PERCALL_SETUP();
1795 call_cntr = funcctx->call_cntr;
1796 max_calls = funcctx->max_calls;
1797 tupdesc = funcctx->tuple_desc;
1798 pixels2 = funcctx->user_fctx;
1801 if (call_cntr < max_calls) {
1802 int values_length = 3;
1803 Datum
values[values_length];
1804 bool nulls[values_length];
1808 memset(nulls,
FALSE,
sizeof(
bool) * values_length);
1811 pixels2[call_cntr].
x += 1;
1812 pixels2[call_cntr].
y += 1;
1814 values[0] = Float8GetDatum(pixels2[call_cntr].
value);
1815 values[1] = Int32GetDatum(pixels2[call_cntr].
x);
1816 values[2] = Int32GetDatum(pixels2[call_cntr].
y);
1819 tuple = heap_form_tuple(tupdesc, values, nulls);
1822 result = HeapTupleGetDatum(tuple);
1824 SRF_RETURN_NEXT(funcctx, result);
1828 SRF_RETURN_DONE(funcctx);
1844 bool exclude_nodata_value =
TRUE;
1857 if (PG_ARGISNULL(0))
1859 pgraster = (
rt_pgraster *) PG_DETOAST_DATUM(PG_GETARG_DATUM(0));
1862 PG_FREE_IF_COPY(pgraster, 0);
1863 elog(ERROR,
"RASTER_nearestValue: Could not deserialize raster");
1868 if (!PG_ARGISNULL(1))
1869 bandindex = PG_GETARG_INT32(1);
1871 if (bandindex < 1 || bandindex > num_bands) {
1872 elog(NOTICE,
"Invalid band index (must use 1-based). Returning NULL");
1874 PG_FREE_IF_COPY(pgraster, 0);
1879 geom = PG_GETARG_GSERIALIZED_P(2);
1881 elog(NOTICE,
"Geometry provided must be a point");
1883 PG_FREE_IF_COPY(pgraster, 0);
1884 PG_FREE_IF_COPY(geom, 2);
1889 if (!PG_ARGISNULL(3))
1890 exclude_nodata_value = PG_GETARG_BOOL(3);
1894 elog(NOTICE,
"SRIDs of geometry and raster do not match");
1896 PG_FREE_IF_COPY(pgraster, 0);
1897 PG_FREE_IF_COPY(geom, 2);
1904 elog(NOTICE,
"Could not find band at index %d. Returning NULL", bandindex);
1906 PG_FREE_IF_COPY(pgraster, 0);
1907 PG_FREE_IF_COPY(geom, 2);
1915 elog(NOTICE,
"Geometry provided cannot be empty");
1917 PG_FREE_IF_COPY(pgraster, 0);
1918 PG_FREE_IF_COPY(geom, 2);
1939 PG_FREE_IF_COPY(pgraster, 0);
1941 PG_FREE_IF_COPY(geom, 2);
1942 elog(ERROR,
"RASTER_nearestValue: Could not compute pixel coordinates from spatial coordinates");
1953 PG_FREE_IF_COPY(pgraster, 0);
1955 PG_FREE_IF_COPY(geom, 2);
1956 elog(ERROR,
"RASTER_nearestValue: Could not get pixel value for band at index %d", bandindex);
1961 if (!exclude_nodata_value || !isnodata) {
1963 PG_FREE_IF_COPY(pgraster, 0);
1965 PG_FREE_IF_COPY(geom, 2);
1967 PG_RETURN_FLOAT8(value);
1976 exclude_nodata_value,
1984 elog(NOTICE,
"Could not get the nearest value for band at index %d", bandindex);
1987 elog(NOTICE,
"No nearest value found for band at index %d", bandindex);
1990 PG_FREE_IF_COPY(geom, 2);
1992 PG_FREE_IF_COPY(pgraster, 0);
2000 double lastdist = -1;
2003 for (i = 0; i <
count; i++) {
2008 PG_FREE_IF_COPY(geom, 2);
2010 PG_FREE_IF_COPY(pgraster, 0);
2011 elog(ERROR,
"RASTER_nearestValue: Could not get polygon of neighboring pixel");
2017 if (lastdist < 0 || dist < lastdist) {
2018 value = npixels[i].
value;
2027 value = npixels[0].
value;
2033 PG_FREE_IF_COPY(geom, 2);
2035 PG_FREE_IF_COPY(pgraster, 0);
2038 PG_RETURN_FLOAT8(value);
2059 bool exclude_nodata_value =
TRUE;
2065 double **value2D = NULL;
2066 int **nodata2D = NULL;
2071 Datum *value1D = NULL;
2072 bool *nodata1D = NULL;
2074 int lbound[2] = {1, 1};
2075 ArrayType *mdArray = NULL;
2082 if (PG_ARGISNULL(0))
2084 pgraster = (
rt_pgraster *) PG_DETOAST_DATUM(PG_GETARG_DATUM(0));
2088 PG_FREE_IF_COPY(pgraster, 0);
2089 elog(ERROR,
"RASTER_neighborhood: Could not deserialize raster");
2094 if (!PG_ARGISNULL(1))
2095 bandindex = PG_GETARG_INT32(1);
2097 if (bandindex < 1 || bandindex > num_bands) {
2098 elog(NOTICE,
"Invalid band index (must use 1-based). Returning NULL");
2100 PG_FREE_IF_COPY(pgraster, 0);
2105 x = PG_GETARG_INT32(2);
2109 y = PG_GETARG_INT32(3);
2113 distance[0] = PG_GETARG_INT32(4);
2114 if (distance[0] < 0) {
2115 elog(NOTICE,
"Invalid value for distancex (must be >= zero). Returning NULL");
2117 PG_FREE_IF_COPY(pgraster, 0);
2120 distance[0] = (uint16_t) distance[0];
2123 distance[1] = PG_GETARG_INT32(5);
2124 if (distance[1] < 0) {
2125 elog(NOTICE,
"Invalid value for distancey (must be >= zero). Returning NULL");
2127 PG_FREE_IF_COPY(pgraster, 0);
2130 distance[1] = (uint16_t) distance[1];
2133 if (!PG_ARGISNULL(6))
2134 exclude_nodata_value = PG_GETARG_BOOL(6);
2139 elog(NOTICE,
"Could not find band at index %d. Returning NULL", bandindex);
2141 PG_FREE_IF_COPY(pgraster, 0);
2148 if (distance[0] > 0 || distance[1] > 0) {
2152 distance[0], distance[1],
2153 exclude_nodata_value,
2158 elog(NOTICE,
"Could not get the pixel's neighborhood for band at index %d", bandindex);
2162 PG_FREE_IF_COPY(pgraster, 0);
2179 elog(NOTICE,
"Could not get the pixel of band at index %d. Returning NULL", bandindex);
2182 PG_FREE_IF_COPY(pgraster, 0);
2205 if (npixels == NULL) {
2209 PG_FREE_IF_COPY(pgraster, 0);
2211 elog(ERROR,
"RASTER_neighborhood: Could not reallocate memory for neighborhood");
2214 npixels[count - 1].
x = _x;
2215 npixels[count - 1].
y = _y;
2216 npixels[count - 1].
nodata = 1;
2220 if (!exclude_nodata_value || !isnodata) {
2221 npixels[count - 1].
nodata = 0;
2227 PG_FREE_IF_COPY(pgraster, 0);
2232 npixels, count, NULL,
2234 distance[0], distance[1],
2237 &(dim[1]), &(dim[0])
2241 elog(NOTICE,
"Could not create 2D array of neighborhood");
2246 value1D = palloc(
sizeof(Datum) * dim[0] * dim[1]);
2247 nodata1D = palloc(
sizeof(
bool) * dim[0] * dim[1]);
2249 if (value1D == NULL || nodata1D == NULL) {
2251 for (i = 0; i < dim[0]; i++) {
2258 elog(ERROR,
"RASTER_neighborhood: Could not allocate memory for return 2D array");
2265 for (i = 0; i < dim[0]; i++) {
2267 for (j = 0; j < dim[1]; j++) {
2268 nodata1D[k] = (bool) nodata2D[i][j];
2270 value1D[k] = Float8GetDatum(value2D[i][j]);
2272 value1D[k] = PointerGetDatum(NULL);
2279 for (i = 0; i < dim[0]; i++) {
2287 get_typlenbyvalalign(FLOAT8OID, &typlen, &typbyval, &typalign);
2289 mdArray = construct_md_array(
2293 typlen, typbyval, typalign
2299 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)