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) {
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) {
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};
670 uint32_t adjacent[8] = {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]),
878 else if ((Qr[pX] < 0 || Qr[pX] >= width1) ||
879 (Qr[pY] < 0 || Qr[pY] >= height1))
883 else if (hasnodata1 ==
FALSE)
894 &(Qr[pX]), &(Qr[pY]),
900 else if ((Qr[pX] < 0 || Qr[pX] >= width2) ||
901 (Qr[pY] < 0 || Qr[pY] >= height2))
905 else if (hasnodata2 ==
FALSE)
920 (hasnodata1 ==
FALSE) || !isnodata1
925 (hasnodata2 ==
FALSE) || !isnodata2
931 if (noval1 || noval2) {
932 RASTER_DEBUGF(4,
"noval1 = %d, noval2 = %d", noval1, noval2);
938 ((hasnodata1 ==
FALSE) || !isnodata1) &&
939 ((hasnodata2 ==
FALSE) || !isnodata2)
948 for (i = 0; i < 4; i++) {
950 , i, adjacent[i], i + 4, adjacent[i + 4]);
951 if (adjacent[i] == 0)
continue;
953 if (adjacent[i] + adjacent[i + 4] == 4) {
997 GEOSGeometry *ghull[2] = {NULL};
1009 uint16_t *widthS = NULL;
1010 uint16_t *heightS = NULL;
1011 uint16_t *widthL = NULL;
1012 uint16_t *heightL = NULL;
1017 int hasnodataS =
FALSE;
1018 int hasnodataL =
FALSE;
1023 double gtS[6] = {0};
1024 double igtL[6] = {0};
1031 enum line_points {X1, Y1, X2, Y2};
1032 enum point {pX, pY};
1040 assert(NULL != rast1);
1041 assert(NULL != rast2);
1042 assert(NULL != intersects);
1044 if (nband1 < 0 && nband2 < 0) {
1055 rterror(
"rt_raster_intersects: The two rasters provided have different SRIDs");
1071 ghull[0] = (GEOSGeometry *)
LWGEOM2GEOS(hull[0], 0);
1078 GEOSGeom_destroy(ghull[0]);
1082 ghull[1] = (GEOSGeometry *)
LWGEOM2GEOS(hull[1], 0);
1084 GEOSGeom_destroy(ghull[0]);
1092 if (GEOSWithin(ghull[0], ghull[1]) == 1)
1094 else if (GEOSWithin(ghull[1], ghull[0]) == 1)
1100 rtn = GEOSIntersects(ghull[0], ghull[1]);
1102 for (i = 0; i < 2; i++) {
1103 GEOSGeom_destroy(ghull[i]);
1108 RASTER_DEBUGF(4,
"convex hulls of rasters do %sintersect", rtn != 1 ?
"NOT " :
"");
1114 else if (nband1 < 0) {
1132 area1 = fabs(width1 * height1 * pixarea1);
1133 area2 = fabs(width2 * height2 * pixarea2);
1134 RASTER_DEBUGF(4,
"pixarea1, pixarea2, area1, area2 = %f, %f, %f, %f",
1135 pixarea1, pixarea2, area1, area2);
1140 (area1 < pixarea2) ||
1178 if (NULL == bandS) {
1179 rterror(
"rt_raster_intersects: Could not get band %d of the first raster", nbandS);
1185 if (hasnodataS !=
FALSE)
1190 if (NULL == bandL) {
1191 rterror(
"rt_raster_intersects: Could not get band %d of the first raster", nbandL);
1197 if (hasnodataL !=
FALSE)
1211 RASTER_DEBUG(3,
"One of the two raster bands is NODATA. The two rasters do not intersect");
1217 if (
within != 0 && ((pixarea1 > area2) || (pixarea2 > area1))) {
1218 RASTER_DEBUG(4,
"Using special case of raster fitting into another raster's pixel");
1220 for (coloffset = 0; coloffset < 3; coloffset++) {
1221 for (rowoffset = 0; rowoffset < 3; rowoffset++) {
1222 for (col = coloffset; col < *widthS; col += 3) {
1223 for (row = rowoffset; row < *heightS; row += 3) {
1224 if (hasnodataS ==
FALSE)
1229 if ((hasnodataS ==
FALSE) || !isnodataS) {
1233 &(lineS[X1]), &(lineS[Y1]),
1239 lineS[X1], lineS[Y1],
1240 &(Qr[pX]), &(Qr[pY]),
1246 if ((Qr[pX] < 0 || Qr[pX] >= *widthL) ||
1247 (Qr[pY] < 0 || Qr[pY] >= *heightL))
1252 if (hasnodataS ==
FALSE)
1257 if ((hasnodataL ==
FALSE) || !isnodataL) {
1267 RASTER_DEBUG(4,
"Smaller raster not in the other raster's pixel. Continuing");
1270 RASTER_DEBUG(4,
"Testing smaller raster vs larger raster");
1274 hasnodataS, hasnodataL,
1278 if (*intersects)
return ES_NONE;
1280 RASTER_DEBUG(4,
"Testing larger raster vs smaller raster");
1284 hasnodataL, hasnodataS,
1288 if (*intersects)
return ES_NONE;
GEOSGeometry * LWGEOM2GEOS(const LWGEOM *lwgeom, uint8_t autofix)
void lwgeom_geos_error(const char *fmt,...)
void lwgeom_free(LWGEOM *geom)
void lwmpoly_free(LWMPOLY *mpoly)
LWGEOM * lwmpoly_as_lwgeom(const LWMPOLY *obj)
double lwgeom_mindistance2d_tolerance(const LWGEOM *lw1, const LWGEOM *lw2, double tolerance)
Function handling min distance calculations and dwithin calculations.
double lwgeom_maxdistance2d_tolerance(const LWGEOM *lw1, const LWGEOM *lw2, double tolerance)
Function handling max distance calculations and dfullywithin calculations.
void rterror(const char *fmt,...)
Wrappers used for reporting errors and info.
#define RASTER_DEBUG(level, msg)
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.
int32_t rt_raster_get_srid(rt_raster raster)
Get raster's SRID.
#define RASTER_DEBUGF(level, msg,...)
void rtinfo(const char *fmt,...)
int rt_band_get_hasnodata_flag(rt_band band)
Get hasnodata flag value.
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.
rt_errorstate rt_band_get_pixel(rt_band band, int x, int y, double *value, int *nodata)
Get pixel value.
int rt_band_get_isnodata_flag(rt_band band)
Get isnodata flag value.
rt_errorstate rt_raster_surface(rt_raster raster, int nband, LWMPOLY **surface)
Get a raster as a surface (multipolygon).
double rt_raster_get_x_scale(rt_raster raster)
Get scale X in projection units.
rt_errorstate
Enum definitions.
uint16_t rt_raster_get_num_bands(rt_raster raster)
rt_errorstate rt_raster_get_convex_hull(rt_raster raster, LWGEOM **hull)
Get raster's convex hull.
uint16_t rt_raster_get_height(rt_raster raster)
rt_errorstate rt_band_get_nodata(rt_band band, double *nodata)
Get NODATA value.
uint16_t rt_raster_get_width(rt_raster raster)
rt_geos_spatial_test
GEOS spatial relationship tests available.
double rt_raster_get_y_scale(rt_raster raster)
Get scale Y in projection units.
rt_band rt_raster_get_band(rt_raster raster, int bandNum)
Return Nth band, or NULL if unavailable.
This library is the generic raster handling section of PostGIS.
static double distance(double x1, double y1, double x2, double y2)
Datum contains(PG_FUNCTION_ARGS)
Datum coveredby(PG_FUNCTION_ARGS)
Datum covers(PG_FUNCTION_ARGS)
Datum touches(PG_FUNCTION_ARGS)
Datum overlaps(PG_FUNCTION_ARGS)
Datum within(PG_FUNCTION_ARGS)
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.
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_contains_properly(rt_raster rast1, int nband1, rt_raster rast2, int nband2, int *contains)
Return ES_ERROR if error occurred in function.
rt_errorstate rt_raster_intersects(rt_raster rast1, int nband1, rt_raster rast2, int nband2, int *intersects)
Return zero if error occurred in function.
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.
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.
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)
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.
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)
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_same_alignment(rt_raster rast1, rt_raster rast2, int *aligned, char **reason)
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.