48 int *aligned,
char **reason
56 assert(NULL != rast1);
57 assert(NULL != rast2);
58 assert(NULL != aligned);
63 if (reason != NULL) *reason =
"The rasters have different SRIDs";
68 if (reason != NULL) *reason =
"The rasters have different scales on the X axis";
72 if (reason != NULL) *reason =
"The rasters have different scales on the Y axis";
77 if (reason != NULL) *reason =
"The rasters have different skews on the X axis";
81 if (reason != NULL) *reason =
"The rasters have different skews on the Y axis";
97 rterror(
"rt_raster_same_alignment: Could not get raster coordinates of second raster from first raster's spatial coordinates");
109 rterror(
"rt_raster_same_alignment: Could not get spatial coordinates of second raster from raster coordinates");
120 if (reason != NULL) *reason =
"The rasters are aligned";
126 if (reason != NULL) *reason =
"The rasters (pixel corner coordinates) are not aligned";
145 GEOSGeometry *geom1 = NULL;
146 GEOSGeometry *geom2 = NULL;
152 assert(NULL != rast1);
153 assert(NULL != rast2);
154 assert(NULL != testresult);
156 if (nband1 < 0 && nband2 < 0) {
170 rterror(
"rt_raster_geos_spatial_relationship: The two rasters provided have different SRIDs");
178 rterror(
"rt_raster_geos_spatial_relationship: Could not get surface of the specified band from the first raster");
182 rterror(
"rt_raster_geos_spatial_relationship: Could not get surface of the specified band from the second raster");
188 if (surface1 == NULL || surface2 == NULL) {
198 rterror(
"rt_raster_geos_spatial_relationship: Could not convert surface of the specified band from the first raster to a GEOSGeometry");
206 rterror(
"rt_raster_geos_spatial_relationship: Could not convert surface of the specified band from the second raster to a GEOSGeometry");
213 rtn = GEOSOverlaps(geom1, geom2);
216 rtn = GEOSTouches(geom1, geom2);
219 rtn = GEOSContains(geom1, geom2);
222 rtn = GEOSRelatePattern(geom1, geom2,
"T**FF*FF*");
225 rtn = GEOSRelatePattern(geom1, geom2,
"******FF*");
228 rtn = GEOSRelatePattern(geom1, geom2,
"**F**F***");
231 rterror(
"rt_raster_geos_spatial_relationship: Unknown or unsupported GEOS spatial relationship test");
235 GEOSGeom_destroy(geom1);
236 GEOSGeom_destroy(geom2);
240 rterror(
"rt_raster_geos_spatial_relationship: Could not run the appropriate GEOS spatial relationship test");
244 else if (flag >= 0) {
473 assert(NULL != rast1);
474 assert(NULL != rast2);
475 assert(NULL != dwithin);
477 if (nband1 < 0 && nband2 < 0) {
491 rterror(
"rt_raster_distance_within: The two rasters provided have different SRIDs");
497 rterror(
"rt_raster_distance_within: Distance cannot be less than zero");
503 rterror(
"rt_raster_distance_within: Could not get surface of the specified band from the first raster");
509 rterror(
"rt_raster_distance_within: Could not get surface of the specified band from the second raster");
516 if (surface1 == NULL || surface2 == NULL) {
529 if (
FLT_EQ(mindist, distance) || distance > mindist)
532 RASTER_DEBUGF(3,
"(mindist, distance) = (%f, %f, %d)", mindist, distance, *dwithin);
568 assert(NULL != rast1);
569 assert(NULL != rast2);
570 assert(NULL != dfwithin);
572 if (nband1 < 0 && nband2 < 0) {
586 rterror(
"rt_raster_fully_within_distance: The two rasters provided have different SRIDs");
592 rterror(
"rt_raster_fully_within_distance: Distance cannot be less than zero");
598 rterror(
"rt_raster_fully_within_distance: Could not get surface of the specified band from the first raster");
604 rterror(
"rt_raster_fully_within_distance: Could not get surface of the specified band from the second raster");
611 if (surface1 == NULL || surface2 == NULL) {
624 if (
FLT_EQ(maxdist, distance) || distance > maxdist)
627 RASTER_DEBUGF(3,
"(maxdist, distance, dfwithin) = (%f, %f, %d)", maxdist, distance, *dfwithin);
640 int hasnodata1,
int hasnodata2,
641 double nodata1,
double nodata2
652 enum line_points {X1, Y1, X2, Y2};
654 double line1[4] = {0.};
655 double line2[4] = {0.};
659 double gt1[6] = {0.};
660 double gt2[6] = {0.};
661 double igt1[6] = {0};
662 double igt2[6] = {0};
693 &(line1[X1]), &(line1[Y1]),
700 &(line1[X2]), &(line1[Y2]),
707 &(line2[X1]), &(line2[Y1]),
714 &(line2[X2]), &(line2[Y2]),
719 if (
FLT_EQ(((line1[X2] - line1[X1]) * (line2[Y2] - line2[Y1])),
720 ((line2[X2] - line2[X1]) * (line1[Y2] - line1[Y1]))))
727 RASTER_DEBUGF(4,
"byHeight: %d, dimValue: %d", byHeight, dimValue);
730 for (coloffset = 0; coloffset < 3; coloffset++) {
731 for (rowoffset = 0; rowoffset < 3; rowoffset++) {
733 for (col = coloffset; col <= width1; col += 3) {
738 &(line1[X1]), &(line1[Y1]),
745 &(line1[X2]), &(line1[Y2]),
750 for (row = rowoffset; row <= dimValue; row += 3) {
756 &(line2[X1]), &(line2[Y1]),
763 &(line2[X2]), &(line2[Y2]),
771 &(line2[X1]), &(line2[Y1]),
778 &(line2[X2]), &(line2[Y2]),
785 line1[X1], line1[Y1], line1[X2], line1[Y2]);
787 line2[X1], line2[Y1], line2[X2], line2[Y2]);
791 d = ((line1[X1] - line1[X2]) * (line2[Y1] - line2[Y2])) - ((line1[Y1] - line1[Y2]) * (line2[X1] - line2[X2]));
797 P[pX] = (((line1[X1] * line1[Y2]) - (line1[Y1] * line1[X2])) * (line2[X1] - line2[X2])) -
798 ((line1[X1] - line1[X2]) * ((line2[X1] * line2[Y2]) - (line2[Y1] * line2[X2])));
801 P[pY] = (((line1[X1] * line1[Y2]) - (line1[Y1] * line1[X2])) * (line2[Y1] - line2[Y2])) -
802 ((line1[Y1] - line1[Y2]) * ((line2[X1] * line2[Y2]) - (line2[Y1] * line2[X2])));
809 (
FLT_EQ(P[pX], line1[X1]) ||
FLT_EQ(P[pX], line1[X2])) ||
810 (P[pX] > fmin(line1[X1], line1[X2]) && (P[pX] < fmax(line1[X1], line1[X2])))
812 (
FLT_EQ(P[pY], line1[Y1]) ||
FLT_EQ(P[pY], line1[Y2])) ||
813 (P[pY] > fmin(line1[Y1], line1[Y2]) && (P[pY] < fmax(line1[Y1], line1[Y2])))
815 (
FLT_EQ(P[pX], line2[X1]) ||
FLT_EQ(P[pX], line2[X2])) ||
816 (P[pX] > fmin(line2[X1], line2[X2]) && (P[pX] < fmax(line2[X1], line2[X2])))
818 (
FLT_EQ(P[pY], line2[Y1]) ||
FLT_EQ(P[pY], line2[Y2])) ||
819 (P[pY] > fmin(line2[Y1], line2[Y2]) && (P[pY] < fmax(line2[Y1], line2[Y2])))
823 for (i = 0; i < 8; i++) adjacent[i] = 0;
826 for (i = 0; i < 8; i++) {
829 Qw[pX] = P[pX] - xscale;
830 Qw[pY] = P[pY] + yscale;
834 Qw[pX] = P[pX] - xscale;
838 Qw[pX] = P[pX] - xscale;
839 Qw[pY] = P[pY] - yscale;
844 Qw[pY] = P[pY] - yscale;
847 Qw[pX] = P[pX] + xscale;
848 Qw[pY] = P[pY] - yscale;
852 Qw[pX] = P[pX] + xscale;
857 Qw[pX] = P[pX] + xscale;
858 Qw[pY] = P[pY] + yscale;
863 Qw[pY] = P[pY] + yscale;
872 &(Qr[pX]), &(Qr[pY]),
879 (Qr[pX] < 0 || Qr[pX] > width1 ||
FLT_EQ(Qr[pX], width1)) ||
880 (Qr[pY] < 0 || Qr[pY] > height1 ||
FLT_EQ(Qr[pY], height1))
884 else if (hasnodata1 ==
FALSE)
895 &(Qr[pX]), &(Qr[pY]),
902 (Qr[pX] < 0 || Qr[pX] > width2 ||
FLT_EQ(Qr[pX], width2)) ||
903 (Qr[pY] < 0 || Qr[pY] > height2 ||
FLT_EQ(Qr[pY], height2))
907 else if (hasnodata2 ==
FALSE)
922 (hasnodata1 ==
FALSE) || !isnodata1
927 (hasnodata2 ==
FALSE) || !isnodata2
933 if (noval1 || noval2) {
934 RASTER_DEBUGF(4,
"noval1 = %d, noval2 = %d", noval1, noval2);
940 ((hasnodata1 ==
FALSE) || !isnodata1) &&
941 ((hasnodata2 ==
FALSE) || !isnodata2)
950 for (i = 0; i < 4; i++) {
952 , i, adjacent[i], i + 4, adjacent[i + 4]);
953 if (adjacent[i] == 0)
continue;
955 if (adjacent[i] + adjacent[i + 4] == 4) {
1000 GEOSGeometry *ghull[2] = {NULL};
1012 uint16_t *widthS = NULL;
1013 uint16_t *heightS = NULL;
1014 uint16_t *widthL = NULL;
1015 uint16_t *heightL = NULL;
1020 int hasnodataS =
FALSE;
1021 int hasnodataL =
FALSE;
1026 double gtS[6] = {0};
1027 double igtL[6] = {0};
1034 enum line_points {X1, Y1, X2, Y2};
1035 enum point {pX, pY};
1043 assert(NULL != rast1);
1044 assert(NULL != rast2);
1045 assert(NULL != intersects);
1047 if (nband1 < 0 && nband2 < 0) {
1058 rterror(
"rt_raster_intersects: The two rasters provided have different SRIDs");
1070 for (i = 0; i < 2; i++) {
1072 for (j = 0; j < i; j++) {
1073 GEOSGeom_destroy(ghull[j]);
1079 ghull[i] = (GEOSGeometry *)
LWGEOM2GEOS(hull[i], 0);
1080 if (NULL == ghull[i]) {
1081 for (j = 0; j < i; j++) {
1082 GEOSGeom_destroy(ghull[j]);
1094 if (GEOSWithin(ghull[0], ghull[1]) == 1)
1096 else if (GEOSWithin(ghull[1], ghull[0]) == 1)
1102 rtn = GEOSIntersects(ghull[0], ghull[1]);
1104 for (i = 0; i < 2; i++) {
1105 GEOSGeom_destroy(ghull[i]);
1110 RASTER_DEBUGF(4,
"convex hulls of rasters do %sintersect", rtn != 1 ?
"NOT " :
"");
1116 else if (nband1 < 0) {
1134 area1 = fabs(width1 * height1 * pixarea1);
1135 area2 = fabs(width2 * height2 * pixarea2);
1136 RASTER_DEBUGF(4,
"pixarea1, pixarea2, area1, area2 = %f, %f, %f, %f",
1137 pixarea1, pixarea2, area1, area2);
1142 (area1 < pixarea2) ||
1180 if (NULL == bandS) {
1181 rterror(
"rt_raster_intersects: Could not get band %d of the first raster", nbandS);
1187 if (hasnodataS !=
FALSE)
1192 if (NULL == bandL) {
1193 rterror(
"rt_raster_intersects: Could not get band %d of the first raster", nbandL);
1199 if (hasnodataL !=
FALSE)
1213 RASTER_DEBUG(3,
"One of the two raster bands is NODATA. The two rasters do not intersect");
1219 if (within != 0 && ((pixarea1 > area2) || (pixarea2 > area1))) {
1220 RASTER_DEBUG(4,
"Using special case of raster fitting into another raster's pixel");
1222 for (coloffset = 0; coloffset < 3; coloffset++) {
1223 for (rowoffset = 0; rowoffset < 3; rowoffset++) {
1224 for (col = coloffset; col < *widthS; col += 3) {
1225 for (row = rowoffset; row < *heightS; row += 3) {
1226 if (hasnodataS ==
FALSE)
1231 if ((hasnodataS ==
FALSE) || !isnodataS) {
1235 &(lineS[X1]), &(lineS[Y1]),
1241 lineS[X1], lineS[Y1],
1242 &(Qr[pX]), &(Qr[pY]),
1249 (Qr[pX] < 0 || Qr[pX] > *widthL ||
FLT_EQ(Qr[pX], *widthL)) ||
1250 (Qr[pY] < 0 || Qr[pY] > *heightL ||
FLT_EQ(Qr[pY], *heightL))
1255 if (hasnodataS ==
FALSE)
1260 if ((hasnodataL ==
FALSE) || !isnodataL) {
1270 RASTER_DEBUG(4,
"Smaller raster not in the other raster's pixel. Continuing");
1273 RASTER_DEBUG(4,
"Testing smaller raster vs larger raster");
1277 hasnodataS, hasnodataL,
1281 if (*intersects)
return ES_NONE;
1283 RASTER_DEBUG(4,
"Testing larger raster vs smaller raster");
1287 hasnodataL, hasnodataS,
1291 if (*intersects)
return ES_NONE;
Datum coveredby(PG_FUNCTION_ARGS)
int rt_raster_get_num_bands(rt_raster raster)
Datum covers(PG_FUNCTION_ARGS)
rt_errorstate rt_raster_fully_within_distance(rt_raster rast1, int nband1, rt_raster rast2, int nband2, double distance, int *dfwithin)
Return ES_ERROR if error occurred in function.
rt_errorstate rt_raster_same_alignment(rt_raster rast1, rt_raster rast2, int *aligned, char **reason)
double lwgeom_maxdistance2d_tolerance(const LWGEOM *lw1, const LWGEOM *lw2, double tolerance)
Function handling max distance calculations and dfyllywithin calculations.
double lwgeom_mindistance2d_tolerance(const LWGEOM *lw1, const LWGEOM *lw2, double tolerance)
Function handling min distance calculations and dwithin calculations.
rt_errorstate rt_raster_covers(rt_raster rast1, int nband1, rt_raster rast2, int nband2, int *covers)
Return ES_ERROR if error occurred in function.
void lwgeom_free(LWGEOM *geom)
Datum contains(PG_FUNCTION_ARGS)
static int rt_raster_intersects_algorithm(rt_raster rast1, rt_raster rast2, rt_band band1, rt_band band2, int hasnodata1, int hasnodata2, double nodata1, double nodata2)
void rterror(const char *fmt,...)
Wrappers used for reporting errors and info.
rt_errorstate
Enum definitions.
rt_errorstate rt_raster_overlaps(rt_raster rast1, int nband1, rt_raster rast2, int nband2, int *overlaps)
Return ES_ERROR if error occurred in function.
Datum overlaps(PG_FUNCTION_ARGS)
rt_errorstate rt_raster_coveredby(rt_raster rast1, int nband1, rt_raster rast2, int nband2, int *coveredby)
Return ES_ERROR if error occurred in function.
static rt_errorstate rt_raster_geos_spatial_relationship(rt_raster rast1, int nband1, rt_raster rast2, int nband2, rt_geos_spatial_test testtype, int *testresult)
Datum touches(PG_FUNCTION_ARGS)
rt_geos_spatial_test
GEOS spatial relationship tests available.
rt_errorstate rt_band_get_nodata(rt_band band, double *nodata)
Get NODATA value.
rt_errorstate rt_raster_get_convex_hull(rt_raster raster, LWGEOM **hull)
Get raster's convex hull.
rt_errorstate rt_raster_cell_to_geopoint(rt_raster raster, double xr, double yr, double *xw, double *yw, double *gt)
Convert an xr, yr raster point to an xw, yw point on map.
rt_errorstate rt_raster_surface(rt_raster raster, int nband, LWMPOLY **surface)
Get a raster as a surface (multipolygon).
void lwmpoly_free(LWMPOLY *mpoly)
rt_errorstate rt_raster_within_distance(rt_raster rast1, int nband1, rt_raster rast2, int nband2, double distance, int *dwithin)
Return ES_ERROR if error occurred in function.
rt_errorstate rt_raster_contains_properly(rt_raster rast1, int nband1, rt_raster rast2, int nband2, int *contains)
Return ES_ERROR if error occurred in function.
void lwgeom_geos_error(const char *fmt,...)
Datum intersects(PG_FUNCTION_ARGS)
rt_errorstate rt_band_get_pixel(rt_band band, int x, int y, double *value, int *nodata)
Get pixel value.
rt_band rt_raster_get_band(rt_raster raster, int bandNum)
Return Nth band, or NULL if unavailable.
void rtinfo(const char *fmt,...)
int rt_band_get_hasnodata_flag(rt_band band)
Get hasnodata flag value.
double rt_raster_get_x_scale(rt_raster raster)
Get scale X in projection units.
#define RASTER_DEBUGF(level, msg,...)
int32_t rt_raster_get_srid(rt_raster raster)
Get raster's SRID.
rt_errorstate rt_raster_geopoint_to_cell(rt_raster raster, double xw, double yw, double *xr, double *yr, double *igt)
Convert an xw, yw map point to a xr, yr raster point.
GEOSGeometry * LWGEOM2GEOS(const LWGEOM *lwgeom, int autofix)
double rt_raster_get_y_scale(rt_raster raster)
Get scale Y in projection units.
Datum distance(PG_FUNCTION_ARGS)
rt_errorstate rt_raster_touches(rt_raster rast1, int nband1, rt_raster rast2, int nband2, int *touches)
Return ES_ERROR if error occurred in function.
uint16_t rt_raster_get_width(rt_raster raster)
rt_errorstate rt_raster_intersects(rt_raster rast1, int nband1, rt_raster rast2, int nband2, int *intersects)
Return zero if error occurred in function.
#define RASTER_DEBUG(level, msg)
This library is the generic raster handling section of PostGIS.
rt_errorstate rt_raster_contains(rt_raster rast1, int nband1, rt_raster rast2, int nband2, int *contains)
Return ES_ERROR if error occurred in function.
int rt_band_get_isnodata_flag(rt_band band)
Get isnodata flag value.
uint16_t rt_raster_get_height(rt_raster raster)
LWGEOM * lwmpoly_as_lwgeom(const LWMPOLY *obj)