1 /*
2 *
3 * WKTRaster - Raster Types for PostGIS
4 * http://trac.osgeo.org/postgis/wiki/WKTRaster
5 *
6 * Copyright (C) 2011-2013 Regents of the University of California
7 * <bkpark@ucdavis.edu>
8 * Copyright (C) 2010-2011 Jorge Arevalo <jorge.arevalo@deimos-space.com>
9 * Copyright (C) 2010-2011 David Zwarg <dzwarg@azavea.com>
10 * Copyright (C) 2009-2011 Pierre Racine <pierre.racine@sbf.ulaval.ca>
11 * Copyright (C) 2009-2011 Mateusz Loskot <mateusz@loskot.net>
12 * Copyright (C) 2008-2009 Sandro Santilli <strk@kbt.io>
13 *
14 * This program is free software; you can redistribute it and/or
15 * modify it under the terms of the GNU General Public License
16 * as published by the Free Software Foundation; either version 2
17 * of the License, or (at your option) any later version.
18 *
19 * This program is distributed in the hope that it will be useful,
20 * but WITHOUT ANY WARRANTY; without even the implied warranty of
21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 * GNU General Public License for more details.
23 *
24 * You should have received a copy of the GNU General Public License
25 * along with this program; if not, write to the Free Software Foundation,
26 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
27 *
28 */
29
30 #include <postgres.h> /* for palloc */
31 #include <fmgr.h>
32 #include <utils/builtins.h>
33
34 #include "../../postgis_config.h"
35
36 #include "lwgeom_pg.h"
37 #include "rtpostgis.h"
38
39 /* determine if two rasters intersect */
40 Datum RASTER_intersects(PG_FUNCTION_ARGS);
41
42 /* determine if two rasters overlap */
43 Datum RASTER_overlaps(PG_FUNCTION_ARGS);
44
45 /* determine if two rasters touch */
46 Datum RASTER_touches(PG_FUNCTION_ARGS);
47
48 /* determine if the first raster contains the second raster */
49 Datum RASTER_contains(PG_FUNCTION_ARGS);
50
51 /* determine if the first raster contains properly the second raster */
52 Datum RASTER_containsProperly(PG_FUNCTION_ARGS);
53
54 /* determine if the first raster covers the second raster */
55 Datum RASTER_covers(PG_FUNCTION_ARGS);
56
57 /* determine if the first raster is covered by the second raster */
58 Datum RASTER_coveredby(PG_FUNCTION_ARGS);
59
60 /* determine if the two rasters are within the specified distance of each other */
61 Datum RASTER_dwithin(PG_FUNCTION_ARGS);
62
63 /* determine if the two rasters are fully within the specified distance of each other */
64 Datum RASTER_dfullywithin(PG_FUNCTION_ARGS);
65
66 /* determine if two rasters are aligned */
67 Datum RASTER_sameAlignment(PG_FUNCTION_ARGS);
68 Datum RASTER_notSameAlignmentReason(PG_FUNCTION_ARGS);
69
70 /**
71 * See if two rasters intersect
72 */
73 PG_FUNCTION_INFO_V1(RASTER_intersects);
RASTER_intersects(PG_FUNCTION_ARGS)74 Datum RASTER_intersects(PG_FUNCTION_ARGS)
75 {
76 const uint32_t set_count = 2;
77 rt_pgraster *pgrast[2];
78 int pgrastpos[2] = {-1, -1};
79 rt_raster rast[2] = {NULL};
80 uint32_t bandindex[2] = {0};
81 uint32_t hasbandindex[2] = {0};
82
83 uint32_t i;
84 uint32_t j;
85 uint32_t k;
86 uint32_t numBands;
87 int rtn;
88 int result;
89
90 for (i = 0, j = 0; i < set_count; i++) {
91 /* pgrast is null, return null */
92 if (PG_ARGISNULL(j)) {
93 for (k = 0; k < i; k++) {
94 rt_raster_destroy(rast[k]);
95 PG_FREE_IF_COPY(pgrast[k], pgrastpos[k]);
96 }
97 PG_RETURN_NULL();
98 }
99 pgrast[i] = (rt_pgraster *) PG_DETOAST_DATUM(PG_GETARG_DATUM(j));
100 pgrastpos[i] = j;
101 j++;
102
103 /* raster */
104 rast[i] = rt_raster_deserialize(pgrast[i], FALSE);
105 if (!rast[i]) {
106 for (k = 0; k <= i; k++) {
107 if (k < i)
108 rt_raster_destroy(rast[k]);
109 PG_FREE_IF_COPY(pgrast[k], pgrastpos[k]);
110 }
111 elog(ERROR, "RASTER_intersects: Could not deserialize the %s raster", i < 1 ? "first" : "second");
112 PG_RETURN_NULL();
113 }
114
115 /* numbands */
116 numBands = rt_raster_get_num_bands(rast[i]);
117 if (numBands < 1) {
118 elog(NOTICE, "The %s raster provided has no bands", i < 1 ? "first" : "second");
119 if (i > 0) i++;
120 for (k = 0; k < i; k++) {
121 rt_raster_destroy(rast[k]);
122 PG_FREE_IF_COPY(pgrast[k], pgrastpos[k]);
123 }
124 PG_RETURN_NULL();
125 }
126
127 /* band index */
128 if (!PG_ARGISNULL(j)) {
129 bandindex[i] = PG_GETARG_INT32(j);
130 if (bandindex[i] < 1 || bandindex[i] > numBands) {
131 elog(NOTICE, "Invalid band index (must use 1-based) for the %s raster. Returning NULL", i < 1 ? "first" : "second");
132 if (i > 0) i++;
133 for (k = 0; k < i; k++) {
134 rt_raster_destroy(rast[k]);
135 PG_FREE_IF_COPY(pgrast[k], pgrastpos[k]);
136 }
137 PG_RETURN_NULL();
138 }
139 hasbandindex[i] = 1;
140 }
141 else
142 hasbandindex[i] = 0;
143 POSTGIS_RT_DEBUGF(4, "hasbandindex[%d] = %d", i, hasbandindex[i]);
144 POSTGIS_RT_DEBUGF(4, "bandindex[%d] = %d", i, bandindex[i]);
145 j++;
146 }
147
148 /* hasbandindex must be balanced */
149 if (
150 (hasbandindex[0] && !hasbandindex[1]) ||
151 (!hasbandindex[0] && hasbandindex[1])
152 ) {
153 elog(NOTICE, "Missing band index. Band indices must be provided for both rasters if any one is provided");
154 for (k = 0; k < set_count; k++) {
155 rt_raster_destroy(rast[k]);
156 PG_FREE_IF_COPY(pgrast[k], pgrastpos[k]);
157 }
158 PG_RETURN_NULL();
159 }
160
161 /* SRID must match */
162 if (rt_raster_get_srid(rast[0]) != rt_raster_get_srid(rast[1])) {
163 for (k = 0; k < set_count; k++) {
164 rt_raster_destroy(rast[k]);
165 PG_FREE_IF_COPY(pgrast[k], pgrastpos[k]);
166 }
167 elog(ERROR, "The two rasters provided have different SRIDs");
168 PG_RETURN_NULL();
169 }
170
171 rtn = rt_raster_intersects(
172 rast[0], (hasbandindex[0] ? (int)bandindex[0] - 1 : -1),
173 rast[1], (hasbandindex[1] ? (int)bandindex[1] - 1 : -1),
174 &result
175 );
176 for (k = 0; k < set_count; k++) {
177 rt_raster_destroy(rast[k]);
178 PG_FREE_IF_COPY(pgrast[k], pgrastpos[k]);
179 }
180
181 if (rtn != ES_NONE) {
182 elog(ERROR, "RASTER_intersects: Could not test for intersection on the two rasters");
183 PG_RETURN_NULL();
184 }
185
186 PG_RETURN_BOOL(result);
187 }
188
189 /**
190 * See if two rasters overlap
191 */
192 PG_FUNCTION_INFO_V1(RASTER_overlaps);
RASTER_overlaps(PG_FUNCTION_ARGS)193 Datum RASTER_overlaps(PG_FUNCTION_ARGS)
194 {
195 const uint32_t set_count = 2;
196 rt_pgraster *pgrast[2];
197 int pgrastpos[2] = {-1, -1};
198 rt_raster rast[2] = {NULL};
199 uint32_t bandindex[2] = {0};
200 uint32_t hasbandindex[2] = {0};
201
202 uint32_t i;
203 uint32_t j;
204 uint32_t k;
205 uint32_t numBands;
206 int rtn;
207 int result;
208
209 for (i = 0, j = 0; i < set_count; i++) {
210 /* pgrast is null, return null */
211 if (PG_ARGISNULL(j)) {
212 for (k = 0; k < i; k++) {
213 rt_raster_destroy(rast[k]);
214 PG_FREE_IF_COPY(pgrast[k], pgrastpos[k]);
215 }
216 PG_RETURN_NULL();
217 }
218 pgrast[i] = (rt_pgraster *) PG_DETOAST_DATUM(PG_GETARG_DATUM(j));
219 pgrastpos[i] = j;
220 j++;
221
222 /* raster */
223 rast[i] = rt_raster_deserialize(pgrast[i], FALSE);
224 if (!rast[i]) {
225 for (k = 0; k <= i; k++) {
226 if (k < i)
227 rt_raster_destroy(rast[k]);
228 PG_FREE_IF_COPY(pgrast[k], pgrastpos[k]);
229 }
230 elog(ERROR, "RASTER_overlaps: Could not deserialize the %s raster", i < 1 ? "first" : "second");
231 PG_RETURN_NULL();
232 }
233
234 /* numbands */
235 numBands = rt_raster_get_num_bands(rast[i]);
236 if (numBands < 1) {
237 elog(NOTICE, "The %s raster provided has no bands", i < 1 ? "first" : "second");
238 if (i > 0) i++;
239 for (k = 0; k < i; k++) {
240 rt_raster_destroy(rast[k]);
241 PG_FREE_IF_COPY(pgrast[k], pgrastpos[k]);
242 }
243 PG_RETURN_NULL();
244 }
245
246 /* band index */
247 if (!PG_ARGISNULL(j)) {
248 bandindex[i] = PG_GETARG_INT32(j);
249 if (bandindex[i] < 1 || bandindex[i] > numBands) {
250 elog(NOTICE, "Invalid band index (must use 1-based) for the %s raster. Returning NULL", i < 1 ? "first" : "second");
251 if (i > 0) i++;
252 for (k = 0; k < i; k++) {
253 rt_raster_destroy(rast[k]);
254 PG_FREE_IF_COPY(pgrast[k], pgrastpos[k]);
255 }
256 PG_RETURN_NULL();
257 }
258 hasbandindex[i] = 1;
259 }
260 else
261 hasbandindex[i] = 0;
262 POSTGIS_RT_DEBUGF(4, "hasbandindex[%d] = %d", i, hasbandindex[i]);
263 POSTGIS_RT_DEBUGF(4, "bandindex[%d] = %d", i, bandindex[i]);
264 j++;
265 }
266
267 /* hasbandindex must be balanced */
268 if (
269 (hasbandindex[0] && !hasbandindex[1]) ||
270 (!hasbandindex[0] && hasbandindex[1])
271 ) {
272 elog(NOTICE, "Missing band index. Band indices must be provided for both rasters if any one is provided");
273 for (k = 0; k < set_count; k++) {
274 rt_raster_destroy(rast[k]);
275 PG_FREE_IF_COPY(pgrast[k], pgrastpos[k]);
276 }
277 PG_RETURN_NULL();
278 }
279
280 /* SRID must match */
281 if (rt_raster_get_srid(rast[0]) != rt_raster_get_srid(rast[1])) {
282 for (k = 0; k < set_count; k++) {
283 rt_raster_destroy(rast[k]);
284 PG_FREE_IF_COPY(pgrast[k], pgrastpos[k]);
285 }
286 elog(ERROR, "The two rasters provided have different SRIDs");
287 PG_RETURN_NULL();
288 }
289
290 rtn = rt_raster_overlaps(
291 rast[0], (hasbandindex[0] ? (int)bandindex[0] - 1 : -1),
292 rast[1], (hasbandindex[1] ? (int)bandindex[1] - 1 : -1),
293 &result
294 );
295 for (k = 0; k < set_count; k++) {
296 rt_raster_destroy(rast[k]);
297 PG_FREE_IF_COPY(pgrast[k], pgrastpos[k]);
298 }
299
300 if (rtn != ES_NONE) {
301 elog(ERROR, "RASTER_overlaps: Could not test for overlap on the two rasters");
302 PG_RETURN_NULL();
303 }
304
305 PG_RETURN_BOOL(result);
306 }
307
308 /**
309 * See if two rasters touch
310 */
311 PG_FUNCTION_INFO_V1(RASTER_touches);
RASTER_touches(PG_FUNCTION_ARGS)312 Datum RASTER_touches(PG_FUNCTION_ARGS)
313 {
314 const uint32_t set_count = 2;
315 rt_pgraster *pgrast[2];
316 int pgrastpos[2] = {-1, -1};
317 rt_raster rast[2] = {NULL};
318 uint32_t bandindex[2] = {0};
319 uint32_t hasbandindex[2] = {0};
320
321 uint32_t i;
322 uint32_t j;
323 uint32_t k;
324 uint32_t numBands;
325 int rtn;
326 int result;
327
328 for (i = 0, j = 0; i < set_count; i++) {
329 /* pgrast is null, return null */
330 if (PG_ARGISNULL(j)) {
331 for (k = 0; k < i; k++) {
332 rt_raster_destroy(rast[k]);
333 PG_FREE_IF_COPY(pgrast[k], pgrastpos[k]);
334 }
335 PG_RETURN_NULL();
336 }
337 pgrast[i] = (rt_pgraster *) PG_DETOAST_DATUM(PG_GETARG_DATUM(j));
338 pgrastpos[i] = j;
339 j++;
340
341 /* raster */
342 rast[i] = rt_raster_deserialize(pgrast[i], FALSE);
343 if (!rast[i]) {
344 for (k = 0; k <= i; k++) {
345 if (k < i)
346 rt_raster_destroy(rast[k]);
347 PG_FREE_IF_COPY(pgrast[k], pgrastpos[k]);
348 }
349 elog(ERROR, "RASTER_touches: Could not deserialize the %s raster", i < 1 ? "first" : "second");
350 PG_RETURN_NULL();
351 }
352
353 /* numbands */
354 numBands = rt_raster_get_num_bands(rast[i]);
355 if (numBands < 1) {
356 elog(NOTICE, "The %s raster provided has no bands", i < 1 ? "first" : "second");
357 if (i > 0) i++;
358 for (k = 0; k < i; k++) {
359 rt_raster_destroy(rast[k]);
360 PG_FREE_IF_COPY(pgrast[k], pgrastpos[k]);
361 }
362 PG_RETURN_NULL();
363 }
364
365 /* band index */
366 if (!PG_ARGISNULL(j)) {
367 bandindex[i] = PG_GETARG_INT32(j);
368 if (bandindex[i] < 1 || bandindex[i] > numBands) {
369 elog(NOTICE, "Invalid band index (must use 1-based) for the %s raster. Returning NULL", i < 1 ? "first" : "second");
370 if (i > 0) i++;
371 for (k = 0; k < i; k++) {
372 rt_raster_destroy(rast[k]);
373 PG_FREE_IF_COPY(pgrast[k], pgrastpos[k]);
374 }
375 PG_RETURN_NULL();
376 }
377 hasbandindex[i] = 1;
378 }
379 else
380 hasbandindex[i] = 0;
381 POSTGIS_RT_DEBUGF(4, "hasbandindex[%d] = %d", i, hasbandindex[i]);
382 POSTGIS_RT_DEBUGF(4, "bandindex[%d] = %d", i, bandindex[i]);
383 j++;
384 }
385
386 /* hasbandindex must be balanced */
387 if (
388 (hasbandindex[0] && !hasbandindex[1]) ||
389 (!hasbandindex[0] && hasbandindex[1])
390 ) {
391 elog(NOTICE, "Missing band index. Band indices must be provided for both rasters if any one is provided");
392 for (k = 0; k < set_count; k++) {
393 rt_raster_destroy(rast[k]);
394 PG_FREE_IF_COPY(pgrast[k], pgrastpos[k]);
395 }
396 PG_RETURN_NULL();
397 }
398
399 /* SRID must match */
400 if (rt_raster_get_srid(rast[0]) != rt_raster_get_srid(rast[1])) {
401 for (k = 0; k < set_count; k++) {
402 rt_raster_destroy(rast[k]);
403 PG_FREE_IF_COPY(pgrast[k], pgrastpos[k]);
404 }
405 elog(ERROR, "The two rasters provided have different SRIDs");
406 PG_RETURN_NULL();
407 }
408
409 rtn = rt_raster_touches(
410 rast[0], (hasbandindex[0] ? (int)bandindex[0] - 1 : -1),
411 rast[1], (hasbandindex[1] ? (int)bandindex[1] - 1 : -1),
412 &result
413 );
414 for (k = 0; k < set_count; k++) {
415 rt_raster_destroy(rast[k]);
416 PG_FREE_IF_COPY(pgrast[k], pgrastpos[k]);
417 }
418
419 if (rtn != ES_NONE) {
420 elog(ERROR, "RASTER_touches: Could not test for touch on the two rasters");
421 PG_RETURN_NULL();
422 }
423
424 PG_RETURN_BOOL(result);
425 }
426
427 /**
428 * See if the first raster contains the second raster
429 */
430 PG_FUNCTION_INFO_V1(RASTER_contains);
RASTER_contains(PG_FUNCTION_ARGS)431 Datum RASTER_contains(PG_FUNCTION_ARGS)
432 {
433 const uint32_t set_count = 2;
434 rt_pgraster *pgrast[2];
435 int pgrastpos[2] = {-1, -1};
436 rt_raster rast[2] = {NULL};
437 uint32_t bandindex[2] = {0};
438 uint32_t hasbandindex[2] = {0};
439
440 uint32_t i;
441 uint32_t j;
442 uint32_t k;
443 uint32_t numBands;
444 int rtn;
445 int result;
446
447 for (i = 0, j = 0; i < set_count; i++) {
448 /* pgrast is null, return null */
449 if (PG_ARGISNULL(j)) {
450 for (k = 0; k < i; k++) {
451 rt_raster_destroy(rast[k]);
452 PG_FREE_IF_COPY(pgrast[k], pgrastpos[k]);
453 }
454 PG_RETURN_NULL();
455 }
456 pgrast[i] = (rt_pgraster *) PG_DETOAST_DATUM(PG_GETARG_DATUM(j));
457 pgrastpos[i] = j;
458 j++;
459
460 /* raster */
461 rast[i] = rt_raster_deserialize(pgrast[i], FALSE);
462 if (!rast[i]) {
463 for (k = 0; k <= i; k++) {
464 if (k < i)
465 rt_raster_destroy(rast[k]);
466 PG_FREE_IF_COPY(pgrast[k], pgrastpos[k]);
467 }
468 elog(ERROR, "RASTER_contains: Could not deserialize the %s raster", i < 1 ? "first" : "second");
469 PG_RETURN_NULL();
470 }
471
472 /* numbands */
473 numBands = rt_raster_get_num_bands(rast[i]);
474 if (numBands < 1) {
475 elog(NOTICE, "The %s raster provided has no bands", i < 1 ? "first" : "second");
476 if (i > 0) i++;
477 for (k = 0; k < i; k++) {
478 rt_raster_destroy(rast[k]);
479 PG_FREE_IF_COPY(pgrast[k], pgrastpos[k]);
480 }
481 PG_RETURN_NULL();
482 }
483
484 /* band index */
485 if (!PG_ARGISNULL(j)) {
486 bandindex[i] = PG_GETARG_INT32(j);
487 if (bandindex[i] < 1 || bandindex[i] > numBands) {
488 elog(NOTICE, "Invalid band index (must use 1-based) for the %s raster. Returning NULL", i < 1 ? "first" : "second");
489 if (i > 0) i++;
490 for (k = 0; k < i; k++) {
491 rt_raster_destroy(rast[k]);
492 PG_FREE_IF_COPY(pgrast[k], pgrastpos[k]);
493 }
494 PG_RETURN_NULL();
495 }
496 hasbandindex[i] = 1;
497 }
498 else
499 hasbandindex[i] = 0;
500 POSTGIS_RT_DEBUGF(4, "hasbandindex[%d] = %d", i, hasbandindex[i]);
501 POSTGIS_RT_DEBUGF(4, "bandindex[%d] = %d", i, bandindex[i]);
502 j++;
503 }
504
505 /* hasbandindex must be balanced */
506 if (
507 (hasbandindex[0] && !hasbandindex[1]) ||
508 (!hasbandindex[0] && hasbandindex[1])
509 ) {
510 elog(NOTICE, "Missing band index. Band indices must be provided for both rasters if any one is provided");
511 for (k = 0; k < set_count; k++) {
512 rt_raster_destroy(rast[k]);
513 PG_FREE_IF_COPY(pgrast[k], pgrastpos[k]);
514 }
515 PG_RETURN_NULL();
516 }
517
518 /* SRID must match */
519 if (rt_raster_get_srid(rast[0]) != rt_raster_get_srid(rast[1])) {
520 for (k = 0; k < set_count; k++) {
521 rt_raster_destroy(rast[k]);
522 PG_FREE_IF_COPY(pgrast[k], pgrastpos[k]);
523 }
524 elog(ERROR, "The two rasters provided have different SRIDs");
525 PG_RETURN_NULL();
526 }
527
528 rtn = rt_raster_contains(
529 rast[0], (hasbandindex[0] ? (int)bandindex[0] - 1 : -1),
530 rast[1], (hasbandindex[1] ? (int)bandindex[1] - 1 : -1),
531 &result
532 );
533 for (k = 0; k < set_count; k++) {
534 rt_raster_destroy(rast[k]);
535 PG_FREE_IF_COPY(pgrast[k], pgrastpos[k]);
536 }
537
538 if (rtn != ES_NONE) {
539 elog(ERROR, "RASTER_contains: Could not test that the first raster contains the second raster");
540 PG_RETURN_NULL();
541 }
542
543 PG_RETURN_BOOL(result);
544 }
545
546 /**
547 * See if the first raster contains properly the second raster
548 */
549 PG_FUNCTION_INFO_V1(RASTER_containsProperly);
RASTER_containsProperly(PG_FUNCTION_ARGS)550 Datum RASTER_containsProperly(PG_FUNCTION_ARGS)
551 {
552 const uint32_t set_count = 2;
553 rt_pgraster *pgrast[2];
554 int pgrastpos[2] = {-1, -1};
555 rt_raster rast[2] = {NULL};
556 uint32_t bandindex[2] = {0};
557 uint32_t hasbandindex[2] = {0};
558
559 uint32_t i;
560 uint32_t j;
561 uint32_t k;
562 uint32_t numBands;
563 int rtn;
564 int result;
565
566 for (i = 0, j = 0; i < set_count; i++) {
567 /* pgrast is null, return null */
568 if (PG_ARGISNULL(j)) {
569 for (k = 0; k < i; k++) {
570 rt_raster_destroy(rast[k]);
571 PG_FREE_IF_COPY(pgrast[k], pgrastpos[k]);
572 }
573 PG_RETURN_NULL();
574 }
575 pgrast[i] = (rt_pgraster *) PG_DETOAST_DATUM(PG_GETARG_DATUM(j));
576 pgrastpos[i] = j;
577 j++;
578
579 /* raster */
580 rast[i] = rt_raster_deserialize(pgrast[i], FALSE);
581 if (!rast[i]) {
582 for (k = 0; k <= i; k++) {
583 if (k < i)
584 rt_raster_destroy(rast[k]);
585 PG_FREE_IF_COPY(pgrast[k], pgrastpos[k]);
586 }
587 elog(ERROR, "RASTER_containsProperly: Could not deserialize the %s raster", i < 1 ? "first" : "second");
588 PG_RETURN_NULL();
589 }
590
591 /* numbands */
592 numBands = rt_raster_get_num_bands(rast[i]);
593 if (numBands < 1) {
594 elog(NOTICE, "The %s raster provided has no bands", i < 1 ? "first" : "second");
595 if (i > 0) i++;
596 for (k = 0; k < i; k++) {
597 rt_raster_destroy(rast[k]);
598 PG_FREE_IF_COPY(pgrast[k], pgrastpos[k]);
599 }
600 PG_RETURN_NULL();
601 }
602
603 /* band index */
604 if (!PG_ARGISNULL(j)) {
605 bandindex[i] = PG_GETARG_INT32(j);
606 if (bandindex[i] < 1 || bandindex[i] > numBands) {
607 elog(NOTICE, "Invalid band index (must use 1-based) for the %s raster. Returning NULL", i < 1 ? "first" : "second");
608 if (i > 0) i++;
609 for (k = 0; k < i; k++) {
610 rt_raster_destroy(rast[k]);
611 PG_FREE_IF_COPY(pgrast[k], pgrastpos[k]);
612 }
613 PG_RETURN_NULL();
614 }
615 hasbandindex[i] = 1;
616 }
617 else
618 hasbandindex[i] = 0;
619 POSTGIS_RT_DEBUGF(4, "hasbandindex[%d] = %d", i, hasbandindex[i]);
620 POSTGIS_RT_DEBUGF(4, "bandindex[%d] = %d", i, bandindex[i]);
621 j++;
622 }
623
624 /* hasbandindex must be balanced */
625 if (
626 (hasbandindex[0] && !hasbandindex[1]) ||
627 (!hasbandindex[0] && hasbandindex[1])
628 ) {
629 elog(NOTICE, "Missing band index. Band indices must be provided for both rasters if any one is provided");
630 for (k = 0; k < set_count; k++) {
631 rt_raster_destroy(rast[k]);
632 PG_FREE_IF_COPY(pgrast[k], pgrastpos[k]);
633 }
634 PG_RETURN_NULL();
635 }
636
637 /* SRID must match */
638 if (rt_raster_get_srid(rast[0]) != rt_raster_get_srid(rast[1])) {
639 for (k = 0; k < set_count; k++) {
640 rt_raster_destroy(rast[k]);
641 PG_FREE_IF_COPY(pgrast[k], pgrastpos[k]);
642 }
643 elog(ERROR, "The two rasters provided have different SRIDs");
644 PG_RETURN_NULL();
645 }
646
647 rtn = rt_raster_contains_properly(
648 rast[0], (hasbandindex[0] ? (int)bandindex[0] - 1 : -1),
649 rast[1], (hasbandindex[1] ? (int)bandindex[1] - 1 : -1),
650 &result
651 );
652 for (k = 0; k < set_count; k++) {
653 rt_raster_destroy(rast[k]);
654 PG_FREE_IF_COPY(pgrast[k], pgrastpos[k]);
655 }
656
657 if (rtn != ES_NONE) {
658 elog(ERROR, "RASTER_containsProperly: Could not test that the first raster contains properly the second raster");
659 PG_RETURN_NULL();
660 }
661
662 PG_RETURN_BOOL(result);
663 }
664
665 /**
666 * See if the first raster covers the second raster
667 */
668 PG_FUNCTION_INFO_V1(RASTER_covers);
RASTER_covers(PG_FUNCTION_ARGS)669 Datum RASTER_covers(PG_FUNCTION_ARGS)
670 {
671 const uint32_t set_count = 2;
672 rt_pgraster *pgrast[2];
673 int pgrastpos[2] = {-1, -1};
674 rt_raster rast[2] = {NULL};
675 uint32_t bandindex[2] = {0};
676 uint32_t hasbandindex[2] = {0};
677
678 uint32_t i;
679 uint32_t j;
680 uint32_t k;
681 uint32_t numBands;
682 int rtn;
683 int result;
684
685 for (i = 0, j = 0; i < set_count; i++) {
686 /* pgrast is null, return null */
687 if (PG_ARGISNULL(j)) {
688 for (k = 0; k < i; k++) {
689 rt_raster_destroy(rast[k]);
690 PG_FREE_IF_COPY(pgrast[k], pgrastpos[k]);
691 }
692 PG_RETURN_NULL();
693 }
694 pgrast[i] = (rt_pgraster *) PG_DETOAST_DATUM(PG_GETARG_DATUM(j));
695 pgrastpos[i] = j;
696 j++;
697
698 /* raster */
699 rast[i] = rt_raster_deserialize(pgrast[i], FALSE);
700 if (!rast[i]) {
701 for (k = 0; k <= i; k++) {
702 if (k < i)
703 rt_raster_destroy(rast[k]);
704 PG_FREE_IF_COPY(pgrast[k], pgrastpos[k]);
705 }
706 elog(ERROR, "RASTER_covers: Could not deserialize the %s raster", i < 1 ? "first" : "second");
707 PG_RETURN_NULL();
708 }
709
710 /* numbands */
711 numBands = rt_raster_get_num_bands(rast[i]);
712 if (numBands < 1) {
713 elog(NOTICE, "The %s raster provided has no bands", i < 1 ? "first" : "second");
714 if (i > 0) i++;
715 for (k = 0; k < i; k++) {
716 rt_raster_destroy(rast[k]);
717 PG_FREE_IF_COPY(pgrast[k], pgrastpos[k]);
718 }
719 PG_RETURN_NULL();
720 }
721
722 /* band index */
723 if (!PG_ARGISNULL(j)) {
724 bandindex[i] = PG_GETARG_INT32(j);
725 if (bandindex[i] < 1 || bandindex[i] > numBands) {
726 elog(NOTICE, "Invalid band index (must use 1-based) for the %s raster. Returning NULL", i < 1 ? "first" : "second");
727 if (i > 0) i++;
728 for (k = 0; k < i; k++) {
729 rt_raster_destroy(rast[k]);
730 PG_FREE_IF_COPY(pgrast[k], pgrastpos[k]);
731 }
732 PG_RETURN_NULL();
733 }
734 hasbandindex[i] = 1;
735 }
736 else
737 hasbandindex[i] = 0;
738 POSTGIS_RT_DEBUGF(4, "hasbandindex[%d] = %d", i, hasbandindex[i]);
739 POSTGIS_RT_DEBUGF(4, "bandindex[%d] = %d", i, bandindex[i]);
740 j++;
741 }
742
743 /* hasbandindex must be balanced */
744 if (
745 (hasbandindex[0] && !hasbandindex[1]) ||
746 (!hasbandindex[0] && hasbandindex[1])
747 ) {
748 elog(NOTICE, "Missing band index. Band indices must be provided for both rasters if any one is provided");
749 for (k = 0; k < set_count; k++) {
750 rt_raster_destroy(rast[k]);
751 PG_FREE_IF_COPY(pgrast[k], pgrastpos[k]);
752 }
753 PG_RETURN_NULL();
754 }
755
756 /* SRID must match */
757 if (rt_raster_get_srid(rast[0]) != rt_raster_get_srid(rast[1])) {
758 for (k = 0; k < set_count; k++) {
759 rt_raster_destroy(rast[k]);
760 PG_FREE_IF_COPY(pgrast[k], pgrastpos[k]);
761 }
762 elog(ERROR, "The two rasters provided have different SRIDs");
763 PG_RETURN_NULL();
764 }
765
766 rtn = rt_raster_covers(
767 rast[0], (hasbandindex[0] ? (int)bandindex[0] - 1 : -1),
768 rast[1], (hasbandindex[1] ? (int)bandindex[1] - 1 : -1),
769 &result
770 );
771 for (k = 0; k < set_count; k++) {
772 rt_raster_destroy(rast[k]);
773 PG_FREE_IF_COPY(pgrast[k], pgrastpos[k]);
774 }
775
776 if (rtn != ES_NONE) {
777 elog(ERROR, "RASTER_covers: Could not test that the first raster covers the second raster");
778 PG_RETURN_NULL();
779 }
780
781 PG_RETURN_BOOL(result);
782 }
783
784 /**
785 * See if the first raster is covered by the second raster
786 */
787 PG_FUNCTION_INFO_V1(RASTER_coveredby);
RASTER_coveredby(PG_FUNCTION_ARGS)788 Datum RASTER_coveredby(PG_FUNCTION_ARGS)
789 {
790 const uint32_t set_count = 2;
791 rt_pgraster *pgrast[2];
792 int pgrastpos[2] = {-1, -1};
793 rt_raster rast[2] = {NULL};
794 uint32_t bandindex[2] = {0};
795 uint32_t hasbandindex[2] = {0};
796
797 uint32_t i;
798 uint32_t j;
799 uint32_t k;
800 uint32_t numBands;
801 int rtn;
802 int result;
803
804 for (i = 0, j = 0; i < set_count; i++) {
805 /* pgrast is null, return null */
806 if (PG_ARGISNULL(j)) {
807 for (k = 0; k < i; k++) {
808 rt_raster_destroy(rast[k]);
809 PG_FREE_IF_COPY(pgrast[k], pgrastpos[k]);
810 }
811 PG_RETURN_NULL();
812 }
813 pgrast[i] = (rt_pgraster *) PG_DETOAST_DATUM(PG_GETARG_DATUM(j));
814 pgrastpos[i] = j;
815 j++;
816
817 /* raster */
818 rast[i] = rt_raster_deserialize(pgrast[i], FALSE);
819 if (!rast[i]) {
820 for (k = 0; k <= i; k++) {
821 if (k < i)
822 rt_raster_destroy(rast[k]);
823 PG_FREE_IF_COPY(pgrast[k], pgrastpos[k]);
824 }
825 elog(ERROR, "RASTER_coveredby: Could not deserialize the %s raster", i < 1 ? "first" : "second");
826 PG_RETURN_NULL();
827 }
828
829 /* numbands */
830 numBands = rt_raster_get_num_bands(rast[i]);
831 if (numBands < 1) {
832 elog(NOTICE, "The %s raster provided has no bands", i < 1 ? "first" : "second");
833 if (i > 0) i++;
834 for (k = 0; k < i; k++) {
835 rt_raster_destroy(rast[k]);
836 PG_FREE_IF_COPY(pgrast[k], pgrastpos[k]);
837 }
838 PG_RETURN_NULL();
839 }
840
841 /* band index */
842 if (!PG_ARGISNULL(j)) {
843 bandindex[i] = PG_GETARG_INT32(j);
844 if (bandindex[i] < 1 || bandindex[i] > numBands) {
845 elog(NOTICE, "Invalid band index (must use 1-based) for the %s raster. Returning NULL", i < 1 ? "first" : "second");
846 if (i > 0) i++;
847 for (k = 0; k < i; k++) {
848 rt_raster_destroy(rast[k]);
849 PG_FREE_IF_COPY(pgrast[k], pgrastpos[k]);
850 }
851 PG_RETURN_NULL();
852 }
853 hasbandindex[i] = 1;
854 }
855 else
856 hasbandindex[i] = 0;
857 POSTGIS_RT_DEBUGF(4, "hasbandindex[%d] = %d", i, hasbandindex[i]);
858 POSTGIS_RT_DEBUGF(4, "bandindex[%d] = %d", i, bandindex[i]);
859 j++;
860 }
861
862 /* hasbandindex must be balanced */
863 if (
864 (hasbandindex[0] && !hasbandindex[1]) ||
865 (!hasbandindex[0] && hasbandindex[1])
866 ) {
867 elog(NOTICE, "Missing band index. Band indices must be provided for both rasters if any one is provided");
868 for (k = 0; k < set_count; k++) {
869 rt_raster_destroy(rast[k]);
870 PG_FREE_IF_COPY(pgrast[k], pgrastpos[k]);
871 }
872 PG_RETURN_NULL();
873 }
874
875 /* SRID must match */
876 if (rt_raster_get_srid(rast[0]) != rt_raster_get_srid(rast[1])) {
877 for (k = 0; k < set_count; k++) {
878 rt_raster_destroy(rast[k]);
879 PG_FREE_IF_COPY(pgrast[k], pgrastpos[k]);
880 }
881 elog(ERROR, "The two rasters provided have different SRIDs");
882 PG_RETURN_NULL();
883 }
884
885 rtn = rt_raster_coveredby(
886 rast[0], (hasbandindex[0] ? (int)bandindex[0] - 1 : -1),
887 rast[1], (hasbandindex[1] ? (int)bandindex[1] - 1 : -1),
888 &result
889 );
890 for (k = 0; k < set_count; k++) {
891 rt_raster_destroy(rast[k]);
892 PG_FREE_IF_COPY(pgrast[k], pgrastpos[k]);
893 }
894
895 if (rtn != ES_NONE) {
896 elog(ERROR, "RASTER_coveredby: Could not test that the first raster is covered by the second raster");
897 PG_RETURN_NULL();
898 }
899
900 PG_RETURN_BOOL(result);
901 }
902
903 /**
904 * See if the two rasters are within the specified distance of each other
905 */
906 PG_FUNCTION_INFO_V1(RASTER_dwithin);
RASTER_dwithin(PG_FUNCTION_ARGS)907 Datum RASTER_dwithin(PG_FUNCTION_ARGS)
908 {
909 const uint32_t set_count = 2;
910 rt_pgraster *pgrast[2];
911 int pgrastpos[2] = {-1, -1};
912 rt_raster rast[2] = {NULL};
913 uint32_t bandindex[2] = {0};
914 uint32_t hasbandindex[2] = {0};
915 double distance = 0;
916
917 uint32_t i;
918 uint32_t j;
919 uint32_t k;
920 uint32_t numBands;
921 int rtn;
922 int result;
923
924 for (i = 0, j = 0; i < set_count; i++) {
925 /* pgrast is null, return null */
926 if (PG_ARGISNULL(j)) {
927 for (k = 0; k < i; k++) {
928 rt_raster_destroy(rast[k]);
929 PG_FREE_IF_COPY(pgrast[k], pgrastpos[k]);
930 }
931 PG_RETURN_NULL();
932 }
933 pgrast[i] = (rt_pgraster *) PG_DETOAST_DATUM(PG_GETARG_DATUM(j));
934 pgrastpos[i] = j;
935 j++;
936
937 /* raster */
938 rast[i] = rt_raster_deserialize(pgrast[i], FALSE);
939 if (!rast[i]) {
940 for (k = 0; k <= i; k++) {
941 if (k < i)
942 rt_raster_destroy(rast[k]);
943 PG_FREE_IF_COPY(pgrast[k], pgrastpos[k]);
944 }
945 elog(ERROR, "RASTER_dwithin: Could not deserialize the %s raster", i < 1 ? "first" : "second");
946 PG_RETURN_NULL();
947 }
948
949 /* numbands */
950 numBands = rt_raster_get_num_bands(rast[i]);
951 if (numBands < 1) {
952 elog(NOTICE, "The %s raster provided has no bands", i < 1 ? "first" : "second");
953 if (i > 0) i++;
954 for (k = 0; k < i; k++) {
955 rt_raster_destroy(rast[k]);
956 PG_FREE_IF_COPY(pgrast[k], pgrastpos[k]);
957 }
958 PG_RETURN_NULL();
959 }
960
961 /* band index */
962 if (!PG_ARGISNULL(j)) {
963 bandindex[i] = PG_GETARG_INT32(j);
964 if (bandindex[i] < 1 || bandindex[i] > numBands) {
965 elog(NOTICE, "Invalid band index (must use 1-based) for the %s raster. Returning NULL", i < 1 ? "first" : "second");
966 if (i > 0) i++;
967 for (k = 0; k < i; k++) {
968 rt_raster_destroy(rast[k]);
969 PG_FREE_IF_COPY(pgrast[k], pgrastpos[k]);
970 }
971 PG_RETURN_NULL();
972 }
973 hasbandindex[i] = 1;
974 }
975 else
976 hasbandindex[i] = 0;
977 POSTGIS_RT_DEBUGF(4, "hasbandindex[%d] = %d", i, hasbandindex[i]);
978 POSTGIS_RT_DEBUGF(4, "bandindex[%d] = %d", i, bandindex[i]);
979 j++;
980 }
981
982 /* distance */
983 if (PG_ARGISNULL(4)) {
984 elog(NOTICE, "Distance cannot be NULL. Returning NULL");
985 for (k = 0; k < set_count; k++) {
986 rt_raster_destroy(rast[k]);
987 PG_FREE_IF_COPY(pgrast[k], pgrastpos[k]);
988 }
989 PG_RETURN_NULL();
990 }
991
992 distance = PG_GETARG_FLOAT8(4);
993 if (distance < 0) {
994 elog(NOTICE, "Distance cannot be less than zero. Returning NULL");
995 for (k = 0; k < set_count; k++) {
996 rt_raster_destroy(rast[k]);
997 PG_FREE_IF_COPY(pgrast[k], pgrastpos[k]);
998 }
999 PG_RETURN_NULL();
1000 }
1001
1002 /* hasbandindex must be balanced */
1003 if (
1004 (hasbandindex[0] && !hasbandindex[1]) ||
1005 (!hasbandindex[0] && hasbandindex[1])
1006 ) {
1007 elog(NOTICE, "Missing band index. Band indices must be provided for both rasters if any one is provided");
1008 for (k = 0; k < set_count; k++) {
1009 rt_raster_destroy(rast[k]);
1010 PG_FREE_IF_COPY(pgrast[k], pgrastpos[k]);
1011 }
1012 PG_RETURN_NULL();
1013 }
1014
1015 /* SRID must match */
1016 if (rt_raster_get_srid(rast[0]) != rt_raster_get_srid(rast[1])) {
1017 for (k = 0; k < set_count; k++) {
1018 rt_raster_destroy(rast[k]);
1019 PG_FREE_IF_COPY(pgrast[k], pgrastpos[k]);
1020 }
1021 elog(ERROR, "The two rasters provided have different SRIDs");
1022 PG_RETURN_NULL();
1023 }
1024
1025 rtn = rt_raster_within_distance(
1026 rast[0], (hasbandindex[0] ? (int)bandindex[0] - 1 : -1),
1027 rast[1], (hasbandindex[1] ? (int)bandindex[1] - 1 : -1),
1028 distance,
1029 &result
1030 );
1031 for (k = 0; k < set_count; k++) {
1032 rt_raster_destroy(rast[k]);
1033 PG_FREE_IF_COPY(pgrast[k], pgrastpos[k]);
1034 }
1035
1036 if (rtn != ES_NONE) {
1037 elog(ERROR, "RASTER_dwithin: Could not test that the two rasters are within the specified distance of each other");
1038 PG_RETURN_NULL();
1039 }
1040
1041 PG_RETURN_BOOL(result);
1042 }
1043
1044 /**
1045 * See if the two rasters are fully within the specified distance of each other
1046 */
1047 PG_FUNCTION_INFO_V1(RASTER_dfullywithin);
RASTER_dfullywithin(PG_FUNCTION_ARGS)1048 Datum RASTER_dfullywithin(PG_FUNCTION_ARGS)
1049 {
1050 const uint32_t set_count = 2;
1051 rt_pgraster *pgrast[2];
1052 int pgrastpos[2] = {-1, -1};
1053 rt_raster rast[2] = {NULL};
1054 uint32_t bandindex[2] = {0};
1055 uint32_t hasbandindex[2] = {0};
1056 double distance = 0;
1057
1058 uint32_t i;
1059 uint32_t j;
1060 uint32_t k;
1061 uint32_t numBands;
1062 int rtn;
1063 int result;
1064
1065 for (i = 0, j = 0; i < set_count; i++) {
1066 /* pgrast is null, return null */
1067 if (PG_ARGISNULL(j)) {
1068 for (k = 0; k < i; k++) {
1069 rt_raster_destroy(rast[k]);
1070 PG_FREE_IF_COPY(pgrast[k], pgrastpos[k]);
1071 }
1072 PG_RETURN_NULL();
1073 }
1074 pgrast[i] = (rt_pgraster *) PG_DETOAST_DATUM(PG_GETARG_DATUM(j));
1075 pgrastpos[i] = j;
1076 j++;
1077
1078 /* raster */
1079 rast[i] = rt_raster_deserialize(pgrast[i], FALSE);
1080 if (!rast[i]) {
1081 for (k = 0; k <= i; k++) {
1082 if (k < i)
1083 rt_raster_destroy(rast[k]);
1084 PG_FREE_IF_COPY(pgrast[k], pgrastpos[k]);
1085 }
1086 elog(ERROR, "RASTER_dfullywithin: Could not deserialize the %s raster", i < 1 ? "first" : "second");
1087 PG_RETURN_NULL();
1088 }
1089
1090 /* numbands */
1091 numBands = rt_raster_get_num_bands(rast[i]);
1092 if (numBands < 1) {
1093 elog(NOTICE, "The %s raster provided has no bands", i < 1 ? "first" : "second");
1094 if (i > 0) i++;
1095 for (k = 0; k < i; k++) {
1096 rt_raster_destroy(rast[k]);
1097 PG_FREE_IF_COPY(pgrast[k], pgrastpos[k]);
1098 }
1099 PG_RETURN_NULL();
1100 }
1101
1102 /* band index */
1103 if (!PG_ARGISNULL(j)) {
1104 bandindex[i] = PG_GETARG_INT32(j);
1105 if (bandindex[i] < 1 || bandindex[i] > numBands) {
1106 elog(NOTICE, "Invalid band index (must use 1-based) for the %s raster. Returning NULL", i < 1 ? "first" : "second");
1107 if (i > 0) i++;
1108 for (k = 0; k < i; k++) {
1109 rt_raster_destroy(rast[k]);
1110 PG_FREE_IF_COPY(pgrast[k], pgrastpos[k]);
1111 }
1112 PG_RETURN_NULL();
1113 }
1114 hasbandindex[i] = 1;
1115 }
1116 else
1117 hasbandindex[i] = 0;
1118 POSTGIS_RT_DEBUGF(4, "hasbandindex[%d] = %d", i, hasbandindex[i]);
1119 POSTGIS_RT_DEBUGF(4, "bandindex[%d] = %d", i, bandindex[i]);
1120 j++;
1121 }
1122
1123 /* distance */
1124 if (PG_ARGISNULL(4)) {
1125 elog(NOTICE, "Distance cannot be NULL. Returning NULL");
1126 for (k = 0; k < set_count; k++) {
1127 rt_raster_destroy(rast[k]);
1128 PG_FREE_IF_COPY(pgrast[k], pgrastpos[k]);
1129 }
1130 PG_RETURN_NULL();
1131 }
1132
1133 distance = PG_GETARG_FLOAT8(4);
1134 if (distance < 0) {
1135 elog(NOTICE, "Distance cannot be less than zero. Returning NULL");
1136 for (k = 0; k < set_count; k++) {
1137 rt_raster_destroy(rast[k]);
1138 PG_FREE_IF_COPY(pgrast[k], pgrastpos[k]);
1139 }
1140 PG_RETURN_NULL();
1141 }
1142
1143 /* hasbandindex must be balanced */
1144 if (
1145 (hasbandindex[0] && !hasbandindex[1]) ||
1146 (!hasbandindex[0] && hasbandindex[1])
1147 ) {
1148 elog(NOTICE, "Missing band index. Band indices must be provided for both rasters if any one is provided");
1149 for (k = 0; k < set_count; k++) {
1150 rt_raster_destroy(rast[k]);
1151 PG_FREE_IF_COPY(pgrast[k], pgrastpos[k]);
1152 }
1153 PG_RETURN_NULL();
1154 }
1155
1156 /* SRID must match */
1157 if (rt_raster_get_srid(rast[0]) != rt_raster_get_srid(rast[1])) {
1158 for (k = 0; k < set_count; k++) {
1159 rt_raster_destroy(rast[k]);
1160 PG_FREE_IF_COPY(pgrast[k], pgrastpos[k]);
1161 }
1162 elog(ERROR, "The two rasters provided have different SRIDs");
1163 PG_RETURN_NULL();
1164 }
1165
1166 rtn = rt_raster_fully_within_distance(
1167 rast[0], (hasbandindex[0] ? (int)bandindex[0] - 1 : -1),
1168 rast[1], (hasbandindex[1] ? (int)bandindex[1] - 1 : -1),
1169 distance,
1170 &result
1171 );
1172 for (k = 0; k < set_count; k++) {
1173 rt_raster_destroy(rast[k]);
1174 PG_FREE_IF_COPY(pgrast[k], pgrastpos[k]);
1175 }
1176
1177 if (rtn != ES_NONE) {
1178 elog(ERROR, "RASTER_dfullywithin: Could not test that the two rasters are fully within the specified distance of each other");
1179 PG_RETURN_NULL();
1180 }
1181
1182 PG_RETURN_BOOL(result);
1183 }
1184
1185 /**
1186 * See if two rasters are aligned
1187 */
1188 PG_FUNCTION_INFO_V1(RASTER_sameAlignment);
RASTER_sameAlignment(PG_FUNCTION_ARGS)1189 Datum RASTER_sameAlignment(PG_FUNCTION_ARGS)
1190 {
1191 const uint32_t set_count = 2;
1192 rt_pgraster *pgrast[2];
1193 int pgrastpos[2] = {-1, -1};
1194 rt_raster rast[2] = {NULL};
1195
1196 uint32_t i;
1197 uint32_t j;
1198 uint32_t k;
1199 int rtn;
1200 int aligned = 0;
1201 char *reason = NULL;
1202
1203 for (i = 0, j = 0; i < set_count; i++) {
1204 /* pgrast is null, return null */
1205 if (PG_ARGISNULL(j)) {
1206 for (k = 0; k < i; k++) {
1207 rt_raster_destroy(rast[k]);
1208 PG_FREE_IF_COPY(pgrast[k], pgrastpos[k]);
1209 }
1210 PG_RETURN_NULL();
1211 }
1212 pgrast[i] = (rt_pgraster *) PG_DETOAST_DATUM_SLICE(PG_GETARG_DATUM(j), 0, sizeof(struct rt_raster_serialized_t));
1213 pgrastpos[i] = j;
1214 j++;
1215
1216 /* raster */
1217 rast[i] = rt_raster_deserialize(pgrast[i], TRUE);
1218 if (!rast[i]) {
1219 for (k = 0; k <= i; k++) {
1220 if (k < i)
1221 rt_raster_destroy(rast[k]);
1222 PG_FREE_IF_COPY(pgrast[k], pgrastpos[k]);
1223 }
1224 elog(ERROR, "RASTER_sameAlignment: Could not deserialize the %s raster", i < 1 ? "first" : "second");
1225 PG_RETURN_NULL();
1226 }
1227 }
1228
1229 rtn = rt_raster_same_alignment(
1230 rast[0],
1231 rast[1],
1232 &aligned,
1233 &reason
1234 );
1235 for (k = 0; k < set_count; k++) {
1236 rt_raster_destroy(rast[k]);
1237 PG_FREE_IF_COPY(pgrast[k], pgrastpos[k]);
1238 }
1239
1240 if (rtn != ES_NONE) {
1241 elog(ERROR, "RASTER_sameAlignment: Could not test for alignment on the two rasters");
1242 PG_RETURN_NULL();
1243 }
1244
1245 /* only output reason if not aligned */
1246 if (reason != NULL && !aligned)
1247 elog(NOTICE, "%s", reason);
1248
1249 PG_RETURN_BOOL(aligned);
1250 }
1251
1252 /**
1253 * Return a reason why two rasters are not aligned
1254 */
1255 PG_FUNCTION_INFO_V1(RASTER_notSameAlignmentReason);
RASTER_notSameAlignmentReason(PG_FUNCTION_ARGS)1256 Datum RASTER_notSameAlignmentReason(PG_FUNCTION_ARGS)
1257 {
1258 const uint32_t set_count = 2;
1259 rt_pgraster *pgrast[2];
1260 int pgrastpos[2] = {-1, -1};
1261 rt_raster rast[2] = {NULL};
1262
1263 uint32_t i;
1264 uint32_t j;
1265 uint32_t k;
1266 int rtn;
1267 int aligned = 0;
1268 char *reason = NULL;
1269 text *result = NULL;
1270
1271 for (i = 0, j = 0; i < set_count; i++) {
1272 /* pgrast is null, return null */
1273 if (PG_ARGISNULL(j)) {
1274 for (k = 0; k < i; k++) {
1275 rt_raster_destroy(rast[k]);
1276 PG_FREE_IF_COPY(pgrast[k], pgrastpos[k]);
1277 }
1278 PG_RETURN_NULL();
1279 }
1280 pgrast[i] = (rt_pgraster *) PG_DETOAST_DATUM_SLICE(PG_GETARG_DATUM(j), 0, sizeof(struct rt_raster_serialized_t));
1281 pgrastpos[i] = j;
1282 j++;
1283
1284 /* raster */
1285 rast[i] = rt_raster_deserialize(pgrast[i], TRUE);
1286 if (!rast[i]) {
1287 for (k = 0; k <= i; k++) {
1288 if (k < i)
1289 rt_raster_destroy(rast[k]);
1290 PG_FREE_IF_COPY(pgrast[k], pgrastpos[k]);
1291 }
1292 elog(ERROR, "RASTER_notSameAlignmentReason: Could not deserialize the %s raster", i < 1 ? "first" : "second");
1293 PG_RETURN_NULL();
1294 }
1295 }
1296
1297 rtn = rt_raster_same_alignment(
1298 rast[0],
1299 rast[1],
1300 &aligned,
1301 &reason
1302 );
1303 for (k = 0; k < set_count; k++) {
1304 rt_raster_destroy(rast[k]);
1305 PG_FREE_IF_COPY(pgrast[k], pgrastpos[k]);
1306 }
1307
1308 if (rtn != ES_NONE) {
1309 elog(ERROR, "RASTER_notSameAlignmentReason: Could not test for alignment on the two rasters");
1310 PG_RETURN_NULL();
1311 }
1312
1313 result = cstring_to_text(reason);
1314 PG_RETURN_TEXT_P(result);
1315 }
1316