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;
1296 #if POSTGIS_GEOS_VERSION >= 31400
1299 rt_raster_intersection_fractions(
1307 unsigned int width, height;
1308 GEOSGeometry *geos_geom = NULL;
1312 if (!rast_in || !geom)
1314 rterror(
"%s: NULL input raster or geometry provided", __func__);
1322 if (width == 0 || height == 0)
1324 rterror(
"%s: Input raster has zero width or height", __func__);
1331 rterror(
"%s: Could not determine raster envelope", __func__);
1350 rterror(
"%s: Failed to create output band", __func__);
1364 rterror(
"%s: Could not convert LWGEOM to GEOSGeometry", __func__);
1369 geos_result = GEOSGridIntersectionFractions(
1378 GEOSGeom_destroy(geos_geom);
1381 if (geos_result != 1)
1384 rterror(
"%s: GEOSGridIntersectionFractions call failed", __func__);
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,...) __attribute__((format(printf
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,...)
int rt_raster_generate_new_band(rt_raster raster, rt_pixtype pixtype, double initialvalue, uint32_t hasnodata, double nodatavalue, int index)
Generate a new inline band and add it to a raster.
void void rtinfo(const char *fmt,...) __attribute__((format(printf
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.
void rt_raster_destroy(rt_raster raster)
Release memory associated to a raster.
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_raster rt_raster_clone(rt_raster raster, uint8_t deep)
Clone an existing 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)
void * rt_band_get_data(rt_band band)
Get pointer to raster band data.
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_errorstate rt_raster_get_envelope(rt_raster raster, rt_envelope *env)
Get raster's envelope.
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.
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)
static double distance(double x1, double y1, double x2, double y2)
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.