1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651
|
----------------------------------------------------------------------
--
--
-- Copyright (c) 2009-2010 Pierre Racine <pierre.racine@sbf.ulaval.ca>
--
----------------------------------------------------------------------
-- Note: The functions provided in this script are in developement. Do not use.
-- Note: this script is dependent on
-- _MapAlgebraParts(r1x int, r1y int, r1w int, r1h int, r2x int, r2y int, r2w int, r2h int)
-- ST_SameAlignment(rast1ulx float8, rast1uly float8, rast1scalex float8, rast1scaley float8, rast1skewx float8, rast1skewy float8, rast2ulx float8, rast2uly float8, rast2scalex float8, rast2scaley float8, rast2skewx float8, rast2skewy float8)
-- ST_IsEmpty(raster)
-- ST_HasNoBand(raster, int)
-- ST_BandIsNoData(raster, int)
-- to be found in the script/plpgsql folder
--------------------------------------------------------------------
-- ST_MapAlgebra - (two rasters version) Return a raster which
-- values are the result of an SQL expression involving
-- pixel values from input rasters bands.
-- Arguments
-- rast1 raster - First raster referred by rast1 in the expression.
-- band1 integer - Band number of the first raster. Default to 1.
-- rast2 raster - Second raster referred by rast2 in the expression.
-- band2 integer - Band number of the second raster. Default to 1.
-- expression text - SQL expression. Ex.: "rast1 + 2 * rast2"
-- pixeltype text - Pixeltype assigned to the resulting raster. Expression
-- results are truncated to this type. Default to the
-- pixeltype of the first raster.
-- extentexpr text - Raster extent of the result. Can be:
-- -FIRST: Same extent as the first raster. Default.
-- -SECOND: Same extent as the second) raster. Default.
-- -INTERSECTION: Intersection of extent of the two rasters.
-- -UNION: Union oof extent of the two rasters.
-- nodata1expr text - Expression used when only rast1 pixel value are nodata or absent, i.e. rast2 pixel value is with data.
-- nodata2expr text - Expression used when only rast2 pixel value are nodata or absent, i.e. rast1 pixel value is with data.
-- nodatanodataexpr text - Expression used when both pixel values are nodata values or absent.
-- Further enhancements:
-- -Move the expression parameter in seventh position just before other expression parameters.
-- -Optimization for UNION & FIRST. We might not have to iterate over all the new raster. See st_mapalgebra_optimized.sql
-- -Add the possibility to assign the x or y coordinate of the pixel to the pixel (do the same to the one raster version).
-- -Resample the second raster when necessary (Require ST_Resample)
-- -More test with rotated images
--------------------------------------------------------------------
CREATE OR REPLACE FUNCTION ST_MapAlgebra2(rast1 raster,
band1 integer,
rast2 raster,
band2 integer,
expression text,
pixeltype text,
extentexpr text,
nodata1expr text,
nodata2expr text,
nodatanodataexpr text)
RETURNS raster AS
$$
DECLARE
x integer;
y integer;
r1 float;
r2 float;
rast1ulx float8;
rast1uly float8;
rast1width int;
rast1height int;
rast1scalex float8;
rast1scaley float8;
rast1skewx float8;
rast1skewy float8;
rast1nodataval float8;
rast1srid int;
rast1offsetx int;
rast1offsety int;
rast2ulx float8;
rast2uly float8;
rast2width int;
rast2height int;
rast2scalex float8;
rast2scaley float8;
rast2skewx float8;
rast2skewy float8;
rast2nodataval float8;
rast2srid int;
r1x int;
r1y int;
r1w int;
r1h int;
r2x int;
r2y int;
r2w int;
r2h int;
newrx int;
newry int;
newrast raster;
tmprast raster;
newsrid int;
newscalex float8;
newscaley float8;
newskewx float8;
newskewy float8;
newnodatavalue float8;
newpixeltype text;
newulx float8;
newuly float8;
newwidth int;
newheight int;
newoffsetx1 int;
newoffsety1 int;
newoffsetx2 int;
newoffsety2 int;
newval float;
newexpr text;
upnodatanodataexpr text;
upnodata1expr text;
upnodata2expr text;
upexpression text;
nodatanodataval float;
skipcomputation int;
zones int[];
z11x int;
z11y int;
z11w int;
z11h int;
z12x int;
z12y int;
z12w int;
z12h int;
z13x int;
z13y int;
z13w int;
z13h int;
z14x int;
z14y int;
z14w int;
z14h int;
z21x int;
z21y int;
z21w int;
z21h int;
z22x int;
z22y int;
z22w int;
z22h int;
z23x int;
z23y int;
z23w int;
z23h int;
z24x int;
z24y int;
z24w int;
z24h int;
zcx int;
zcy int;
zcw int;
zch int;
BEGIN
-- We have to deal with NULL, empty, hasnoband and hasnodatavalue band rasters...
-- These are respectively tested by "IS NULL", "ST_IsEmpty()", "ST_HasNoBand()" and "ST_BandIsNodata()"
-- If both raster are null, we return NULL. ok
-- If both raster do not have extent (are empty), we return an empty raster. ok
-- If both raster do not have the specified band,
-- we return a no band raster with the correct extent (according to the extent expression). ok
-- If both raster bands are nodatavalue and there is no replacement value, we return a nodata value band. ok
-- If only one raster is null or empty or has no band or hasnodata band we treat it as a nodata band raster.
-- If there is a replacement value we replace the missing raster values with this replacement value. ok
-- If there is no replacement value, we return a nodata value band. ok
-- What to do when only one raster is NULL or empty
-- If the extent expression is FIRST and the first raster is null we return NULL. ok
-- If the extent expression is FIRST and the first raster do not have extent (is empty), we return an empty raster. ok
-- If the extent expression is SECOND and the second raster is null we return NULL. ok
-- If the extent expression is SECOND and the second raster do not have extent (is empty), we return an empty raster. ok
-- If the extent expression is INTERSECTION and one raster is null or do not have extent (is empty), we return an empty raster. ok
-- If the extent expression is UNION and one raster is null or do not have extent (is empty),
-- we return a raster having the extent and the band characteristics of the other raster. ok
-- What to do when only one raster do not have the required band.
-- If the extent expression is FIRST and the first raster do not have the specified band,
-- we return a no band raster with the correct extent (according to the extent expression). ok
-- If the extent expression is SECOND and the second raster do not have the specified band,
-- we return a no band raster with the correct extent (according to the extent expression). ok
-- If the extent expression is INTERSECTION and one raster do not have the specified band,
-- we treat it as a nodata raster band. ok
-- If the extent expression is UNION and one raster do not have the specified band,
-- we treat it as a nodata raster band. ok
-- In all those cases, we make a warning.
-- Check if both rasters are NULL
RAISE NOTICE 'ST_MapAlgebra2 000';
IF rast1 IS NULL AND rast2 IS NULL THEN
RAISE NOTICE 'ST_MapAlgebra: Both raster are NULL. Returning NULL';
RETURN NULL;
END IF;
-- Check if both rasters are empty (width or height = 0)
IF ST_IsEmpty(rast1) AND ST_IsEmpty(rast2) THEN
RAISE NOTICE 'ST_MapAlgebra: Both raster are empty. Returning an empty raster';
RETURN ST_MakeEmptyRaster(0, 0, 0, 0, 0, 0, 0, 0, -1);
END IF;
rast1ulx := ST_UpperLeftX(rast1);
rast1uly := ST_UpperLeftY(rast1);
rast1width := ST_Width(rast1);
rast1height := ST_Height(rast1);
rast1scalex := ST_ScaleX(rast1);
rast1scaley := ST_ScaleY(rast1);
rast1skewx := ST_SkewX(rast1);
rast1skewy := ST_SkewY(rast1);
rast1srid := ST_SRID(rast1);
rast2ulx := ST_UpperLeftX(rast2);
rast2uly := ST_UpperLeftY(rast2);
rast2width := ST_Width(rast2);
rast2height := ST_Height(rast2);
rast2scalex := ST_ScaleX(rast2);
rast2scaley := ST_ScaleY(rast2);
rast2skewx := ST_SkewX(rast2);
rast2skewy := ST_SkewY(rast2);
rast2srid := ST_SRID(rast2);
-- Check if the first raster is NULL or empty
IF rast1 IS NULL OR ST_IsEmpty(rast1) THEN
rast1ulx := rast2ulx;
rast1uly := rast2uly;
rast1width := rast2width;
rast1height := rast2height;
rast1scalex := rast2scalex;
rast1scaley := rast2scaley;
rast1skewx := rast2skewx;
rast1skewy := rast2skewy;
rast1srid := rast2srid;
END IF;
-- Check if the second raster is NULL or empty
IF rast2 IS NULL OR ST_IsEmpty(rast2) THEN
rast2ulx := rast1ulx;
rast2uly := rast1uly;
rast2width := rast1width;
rast2height := rast1height;
rast2scalex := rast1scalex;
rast2scaley := rast1scaley;
rast2skewx := rast1skewx;
rast2skewy := rast1skewy;
rast2srid := rast1srid;
END IF;
-- Check for SRID
IF rast1srid != rast2srid THEN
RAISE EXCEPTION 'ST_MapAlgebra: Provided raster with different SRID. Aborting';
END IF;
newsrid := rast1srid;
-- Check for alignment. (Rotation problem here)
IF NOT ST_SameAlignment(rast1ulx, rast1uly, rast1scalex, rast1scaley, rast1skewx, rast1skewy, rast2ulx, rast2uly, rast2scalex, rast2scaley, rast2skewx, rast2skewy) THEN
-- For now print an error message, but a more robust implementation should resample the second raster to the alignment of the first raster.
RAISE EXCEPTION 'ST_MapAlgebra: Provided raster do not have the same alignment. Aborting';
END IF;
-- Set new pixel size and skew. We set it to the rast1 scale and skew
-- since both rasters are aligned and thus have the same scale and skew
newscalex := rast1scalex;
newscaley := rast1scaley;
newskewx := rast1skewx;
newskewy := rast1skewy;
--r1x & r2x are the offset of each rasters relatively to global extent
r1x := 0;
r2x := -st_world2rastercoordx(rast2, rast1ulx, rast1uly) + 1;
IF r2x < 0 THEN
r1x := -r2x;
r2x := 0;
END IF;
r1y := 0;
r2y := -st_world2rastercoordy(rast2, rast1ulx, rast1uly) + 1;
IF r2y < 0 THEN
r1y := -r2y;
r2y := 0;
END IF;
r1w := rast1width;
r1h := rast1height;
r2w := rast2width;
r2h := rast2height;
zones := _MapAlgebraParts(r1x + 1, r1y + 1, r1w, r1h, r2x + 1, r2y + 1, r2w, r2h);
z11x := zones[1];
z11y := zones[2];
z11w := zones[3];
z11h := zones[4];
z12x := zones[5];
z12y := zones[6];
z12w := zones[7];
z12h := zones[8];
z13x := zones[9];
z13y := zones[10];
z13w := zones[11];
z13h := zones[12];
z14x := zones[13];
z14y := zones[14];
z14w := zones[15];
z14h := zones[16];
z21x := zones[17];
z21y := zones[18];
z21w := zones[19];
z21h := zones[20];
z22x := zones[21];
z22y := zones[22];
z22w := zones[23];
z22h := zones[24];
z23x := zones[25];
z23y := zones[26];
z23w := zones[27];
z23h := zones[28];
z24x := zones[29];
z24y := zones[30];
z24w := zones[31];
z24h := zones[32];
zcx := zones[33];
zcy := zones[34];
zcw := zones[35];
zch := zones[36];
-- Compute x and y relative index of master and slave according to the extent expression (FIRST, SECOND, INTERSECTION or UNION)
IF extentexpr IS NULL OR upper(extentexpr) = 'FIRST' THEN
-- Check if rast1 is NULL
IF rast1 IS NULL THEN
RAISE NOTICE 'ST_MapAlgebra: FIRST raster is NULL. Returning NULL';
RETURN NULL;
END IF;
-- Check if rast1 is empty
IF ST_IsEmpty(rast1) THEN
RAISE NOTICE 'ST_MapAlgebra: FIRST raster is empty. Returning an empty raster';
RETURN ST_MakeEmptyRaster(0, 0, 0, 0, 0, 0, 0, 0, newsrid);
END IF;
-- Check if rast1 has the required band
IF ST_HasNoBand(rast1, band1) THEN
RAISE NOTICE 'ST_MapAlgebra: FIRST raster has no band. Returning a raster without band';
RETURN ST_MakeEmptyRaster(rast1width, rast1height, rast1ulx, rast1uly, rast1scalex, rast1scaley, rast1skewx, rast1skewy, rast1srid);
END IF;
newulx := rast1ulx;
newuly := rast1uly;
newwidth := rast1width;
newheight := rast1height;
newrx := r1x;
newry := r1y;
z21w := 0;
z22w := 0;
z23w := 0;
z24w := 0;
ELSIF upper(extentexpr) = 'SECOND' THEN
-- Check if rast2 is NULL
IF rast2 IS NULL THEN
RAISE NOTICE 'ST_MapAlgebra: SECOND raster is NULL. Returning NULL';
RETURN NULL;
END IF;
-- Check if rast2 is empty
IF ST_IsEmpty(rast2) THEN
RAISE NOTICE 'ST_MapAlgebra: SECOND raster is empty. Returning an empty raster';
RETURN ST_MakeEmptyRaster(0, 0, 0, 0, 0, 0, 0, 0, newsrid);
END IF;
-- Check if rast2 has the required band
IF ST_HasNoBand(rast2, band2) THEN
RAISE NOTICE 'ST_MapAlgebra: SECOND raster has no band. Returning an empty raster';
RETURN ST_MakeEmptyRaster(rast2width, rast2height, rast2ulx, rast2uly, rast2scalex, rast2scaley, rast2skewx, rast2skewy, rast2srid);
END IF;
newulx := rast2ulx;
newuly := rast2uly;
newwidth := rast2width;
newheight := rast2height;
newrx := r2x;
newry := r2y;
z11w := 0;
z12w := 0;
z13w := 0;
z14w := 0;
ELSIF upper(extentexpr) = 'INTERSECTION' THEN
-- Check if the intersection is empty.
IF zcw = 0 OR zch = 0 OR
rast1 IS NULL OR ST_IsEmpty(rast1) OR
rast2 IS NULL OR ST_IsEmpty(rast2) THEN
RAISE NOTICE 'ST_MapAlgebra: INTERSECTION of provided rasters is empty. Returning an empty raster';
RETURN ST_MakeEmptyRaster(0, 0, 0, 0, 0, 0, 0, 0, newsrid);
END IF;
-- Compute the new ulx and uly
newulx := st_raster2worldcoordx(rast1, zcx - r1x + 1, zcy - r1y + 1);
newuly := st_raster2worldcoordy(rast1, zcx - r1x + 1, zcy - r1y + 1);
newwidth := zcw;
newheight := zch;
newrx := zcx;
newry := zcy;
z11w := 0;
z12w := 0;
z13w := 0;
z14w := 0;
z21w := 0;
z22w := 0;
z23w := 0;
z24w := 0;
ELSIF upper(extentexpr) = 'UNION' THEN
IF rast1 IS NULL OR ST_IsEmpty(rast1) THEN
newulx := rast2ulx;
newuly := rast2uly;
newwidth := rast2width;
newheight := rast2height;
newrx := r2x;
newry := r2y;
z21w := 0;
z22w := 0;
z23w := 0;
z24w := 0;
ELSIF rast2 IS NULL OR ST_IsEmpty(rast2) THEN
newulx := rast1ulx;
newuly := rast1uly;
newwidth := rast1width;
newheight := rast1height;
newrx := r1x;
newry := r1y;
z11w := 0;
z12w := 0;
z13w := 0;
z14w := 0;
ELSE
newrx := 0;
newry := 0;
newulx := st_raster2worldcoordx(rast1, r1x + 1, r1y + 1);
newuly := st_raster2worldcoordy(rast1, r1x + 1, r1y + 1);
newwidth := max(r1x + r1w, r2x + r2w);
newheight := max(r1y + r1h, r2y + r2h);
END IF;
ELSE
RAISE EXCEPTION 'ST_MapAlgebra: Unhandled extent expression "%". Only MASTER, INTERSECTION and UNION are accepted. Aborting.', upper(extentexpr);
END IF;
-- Check if both rasters do not have the specified band.
IF ST_HasNoband(rast1, band1) AND ST_HasNoband(rast2, band2) THEN
RAISE NOTICE 'ST_MapAlgebra: Both raster do not have the specified band. Returning a no band raster with the correct extent';
RETURN ST_MakeEmptyRaster(newwidth, newheight, newulx, newuly, newscalex, newscaley, newskewx, newskewy, newsrid);
END IF;
-- Check newpixeltype
newpixeltype := pixeltype;
IF newpixeltype NOTNULL AND newpixeltype != '1BB' AND newpixeltype != '2BUI' AND newpixeltype != '4BUI' AND newpixeltype != '8BSI' AND newpixeltype != '8BUI' AND
newpixeltype != '16BSI' AND newpixeltype != '16BUI' AND newpixeltype != '32BSI' AND newpixeltype != '32BUI' AND newpixeltype != '32BF' AND newpixeltype != '64BF' THEN
RAISE EXCEPTION 'ST_MapAlgebra: Invalid pixeltype "%". Aborting.', newpixeltype;
END IF;
-- If no newpixeltype was provided, get it from the provided rasters.
IF newpixeltype IS NULL THEN
IF (upper(extentexpr) = 'SECOND' AND NOT ST_HasNoBand(rast2, band2)) OR ST_HasNoBand(rast1, band1) THEN
newpixeltype := ST_BandPixelType(rast2, band2);
ELSE
newpixeltype := ST_BandPixelType(rast1, band1);
END IF;
END IF;
-- Get the nodata value for first raster
IF NOT ST_HasNoBand(rast1, band1) AND ST_BandHasNodataValue(rast1, band1) THEN
rast1nodataval := ST_BandNodatavalue(rast1, band1);
ELSE
rast1nodataval := NULL;
END IF;
-- Get the nodata value for second raster
IF NOT ST_HasNoBand(rast2, band2) AND ST_BandHasNodatavalue(rast2, band2) THEN
rast2nodataval := ST_BandNodatavalue(rast2, band2);
ELSE
rast2nodataval := NULL;
END IF;
-- Determine new notadavalue
IF (upper(extentexpr) = 'SECOND' AND NOT rast2nodataval IS NULL) THEN
newnodatavalue := rast2nodataval;
ELSEIF NOT rast1nodataval IS NULL THEN
newnodatavalue := rast1nodataval;
ELSE
RAISE NOTICE 'ST_MapAlgebra: Both source rasters do not have a nodata value, nodata value for new raster set to the minimum value possible';
newnodatavalue := ST_MinPossibleValue(newrast);
END IF;
upnodatanodataexpr := upper(nodatanodataexpr);
upnodata1expr := upper(nodata1expr);
upnodata2expr := upper(nodata2expr);
upexpression := upper(expression);
-- Initialise newrast with nodata-nodata values. Then we don't have anymore to set values for nodata-nodata pixels.
IF upnodatanodataexpr IS NULL THEN
nodatanodataval := newnodatavalue;
ELSE
EXECUTE 'SELECT ' || upnodatanodataexpr INTO nodatanodataval;
IF nodatanodataval IS NULL THEN
nodatanodataval := newnodatavalue;
ELSE
newnodatavalue := nodatanodataval;
END IF;
END IF;
-------------------------------------------------------------------
--Create the raster receiving all the computed values. Initialize it to the new nodatavalue.
newrast := ST_AddBand(ST_MakeEmptyRaster(newwidth, newheight, newulx, newuly, newscalex, newscaley, newskewx, newskewy, newsrid), newpixeltype, newnodatavalue, newnodatavalue);
-------------------------------------------------------------------
RAISE NOTICE 'ST_MapAlgebra2 111 z11x=%, z11y=%, z11w=%, z11h=%', z11x, z11y, z11w, z11h;
-- First zone with only rast1 (z11)
IF z11w > 0 AND z11h > 0 AND NOT ST_BandIsNodata(rast1, band1) AND NOT nodata2expr IS NULL THEN
IF upnodata2expr = 'RAST' THEN
-- IF rast1nodataval != nodatanodataval THEN
RAISE NOTICE 'ST_MapAlgebra2 222';
-- newrast := ST_SetValues(newrast, 1, z11x, z11y, z11w, z11h, nodatanodataval);
-- END IF;
RAISE NOTICE 'ST_MapAlgebra2 333 z11x=%, z11y=%, z11w=%, z11h=%', z11x, z11y, z11w, z11h;
newrast := ST_SetValues(newrast, 1, z11x, z11y, z11w, z11h, rast1, band1, NULL, TRUE);
ELSE
RAISE NOTICE 'ST_MapAlgebra2 444';
tmprast := ST_Clip(rast1, z11x - r1x + 1, z11y - r1y + 1, z11w, z11h);
newrast := ST_Mapalgebra2(newrast, 1, tmprast, 1, replace(upnodata2expr, 'RAST', 'RAST2'), NULL, 'FIRST', NULL, 'RAST', NULL);
END IF;
END IF;
RAISE NOTICE 'ST_MapAlgebra2 555';
-- Common zone (zc)
skipcomputation = 0;
IF zcw > 0 AND zch > 0 AND (NOT ST_BandIsNodata(rast1, band1) OR NOT ST_BandIsNodata(rast2, band2)) THEN
RAISE NOTICE 'ST_MapAlgebra2 666';
-- Initialize the zone with nodatavalue. We will not further compute nodata nodata pixels
-- newrast := ST_SetValues(newrast, 1, zcx + 1, zcy + 1, zcw, zch, newnodatavalue);
-- If rast1 is only nodata values, apply nodata1expr
IF ST_BandIsNodata(rast1, band1) THEN
IF nodata1expr IS NULL THEN
-- Do nothing
skipcomputation = 0;
ELSEIF upnodata1expr = 'RAST' THEN
-- Copy rast2 into newrast
newrast := ST_SetValues(newrast, 1, zcx, zcy, zcw, zch, , rast2, band2, NULL, 'KEEP');
ELSE
-- If nodata1expr resume to a constant
IF position('RAST' in upnodata1expr) = 0 THEN
EXECUTE 'SELECT ' || upnodata1expr INTO newval;
IF newval IS NULL OR newval = newnodatavalue THEN
-- The constant is equal to nodata. We have nothing to compute since newrast was already initialized to nodata
skipcomputation := 2;
ELSEIF newnodatavalue IS NULL THEN
-- We can globally initialize to the constant only if there was no newnodatavalue.
newrast := ST_SetValues(newrast, 1, zcx, zcy, zcw, zch, newval);
skipcomputation := 2;
ELSE
-- We will assign the constant pixel by pixel.
skipcomputation := 1;
END IF;
END IF;
IF skipcomputation < 2 THEN
FOR x IN 1..zcw LOOP
FOR y IN 1..zch LOOP
r2 := ST_Value(rast2, band2, x + r2x, y + r2y);
IF (r2 IS NULL OR r2 = rast2nodataval) THEN
-- Do nothing since the raster have already been all set to this value
ELSE
IF skipcomputation < 1 THEN
newexpr := replace('SELECT ' || upnodata1expr, 'RAST', r2);
EXECUTE newexpr INTO newval;
IF newval IS NULL THEN
newval := newnodatavalue;
END IF;
END IF;
newrast = ST_SetValue(newrast, 1, x + zcx, y + zcy, newval);
END IF;
END LOOP;
END LOOP;
END IF;
END IF;
ELSEIF ST_BandIsNodata(rast2, band2) THEN
ELSE
END IF;
END IF;
RETURN newrast;
END;
$$
LANGUAGE 'plpgsql';
CREATE OR REPLACE FUNCTION ST_TestRaster(ulx float8, uly float8, val float8)
RETURNS raster AS
$$
DECLARE
BEGIN
RETURN ST_AddBand(ST_MakeEmptyRaster(5, 5, ulx, uly, 1, -1, 0, 0, -1), '32BF', val, -1);
END;
$$
LANGUAGE 'plpgsql';
SELECT asbinary((gv).geom), (gv).val
FROM st_pixelaspolygons(ST_TestRaster(-10, 2, 1)) gv;
SELECT asbinary(_MapAlgebraAllPartsGeom(0, 0, 2, 1, 1, 0, 2, 1))
SELECT asbinary(pix.geom) as geom, pix.val
FROM st_pixelaspolygons(ST_MapAlgebra2(ST_TestRaster(0, 1, 1), 1, ST_TestRaster(1, 0, 1), 1, '(rast1 + rast2) / 2', NULL, 'union', '2*rast', 'rast', NULL), 1) as pix
|