PageRenderTime 66ms CodeModel.GetById 28ms RepoModel.GetById 1ms app.codeStats 0ms

/raster/rt_pg/rtpg_spatial_relationship.c

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