PostGIS 3.7.0dev-r@@SVN_REVISION@@
Loading...
Searching...
No Matches

◆ RASTER_nearestValue()

Datum RASTER_nearestValue ( PG_FUNCTION_ARGS  )

Definition at line 2044 of file rtpg_pixel.c.

2045{
2046 rt_pgraster *pgraster = NULL;
2047 rt_raster raster = NULL;
2048 rt_band band = NULL;
2049 int bandindex = 1;
2050 int num_bands = 0;
2051 GSERIALIZED *geom;
2052 bool exclude_nodata_value = TRUE;
2053 LWGEOM *lwgeom;
2054 LWPOINT *point = NULL;
2055 POINT2D p;
2056
2057 double x;
2058 double y;
2059 int count;
2060 rt_pixel npixels = NULL;
2061 double value = 0;
2062 int hasvalue = 0;
2063 int isnodata = 0;
2064
2065 if (PG_ARGISNULL(0))
2066 PG_RETURN_NULL();
2067 pgraster = (rt_pgraster *) PG_DETOAST_DATUM(PG_GETARG_DATUM(0));
2068 raster = rt_raster_deserialize(pgraster, FALSE);
2069 if (!raster) {
2070 PG_FREE_IF_COPY(pgraster, 0);
2071 elog(ERROR, "RASTER_nearestValue: Could not deserialize raster");
2072 PG_RETURN_NULL();
2073 }
2074
2075 /* band index is 1-based */
2076 if (!PG_ARGISNULL(1))
2077 bandindex = PG_GETARG_INT32(1);
2078 num_bands = rt_raster_get_num_bands(raster);
2079 if (bandindex < 1 || bandindex > num_bands) {
2080 elog(NOTICE, "Invalid band index (must use 1-based). Returning NULL");
2081 rt_raster_destroy(raster);
2082 PG_FREE_IF_COPY(pgraster, 0);
2083 PG_RETURN_NULL();
2084 }
2085
2086 /* point */
2087 geom = PG_GETARG_GSERIALIZED_P(2);
2088 if (gserialized_get_type(geom) != POINTTYPE) {
2089 elog(NOTICE, "Geometry provided must be a point");
2090 rt_raster_destroy(raster);
2091 PG_FREE_IF_COPY(pgraster, 0);
2092 PG_FREE_IF_COPY(geom, 2);
2093 PG_RETURN_NULL();
2094 }
2095
2096 /* exclude_nodata_value flag */
2097 if (!PG_ARGISNULL(3))
2098 exclude_nodata_value = PG_GETARG_BOOL(3);
2099
2100 /* SRIDs of raster and geometry must match */
2102 elog(NOTICE, "SRIDs of geometry and raster do not match");
2103 rt_raster_destroy(raster);
2104 PG_FREE_IF_COPY(pgraster, 0);
2105 PG_FREE_IF_COPY(geom, 2);
2106 PG_RETURN_NULL();
2107 }
2108
2109 /* get band */
2110 band = rt_raster_get_band(raster, bandindex - 1);
2111 if (!band) {
2112 elog(NOTICE, "Could not find band at index %d. Returning NULL", bandindex);
2113 rt_raster_destroy(raster);
2114 PG_FREE_IF_COPY(pgraster, 0);
2115 PG_FREE_IF_COPY(geom, 2);
2116 PG_RETURN_NULL();
2117 }
2118
2119 /* process geometry */
2120 lwgeom = lwgeom_from_gserialized(geom);
2121
2122 if (lwgeom_is_empty(lwgeom)) {
2123 elog(NOTICE, "Geometry provided cannot be empty");
2124 rt_raster_destroy(raster);
2125 PG_FREE_IF_COPY(pgraster, 0);
2126 PG_FREE_IF_COPY(geom, 2);
2127 PG_RETURN_NULL();
2128 }
2129
2130 /* Get a 2D version of the geometry if necessary */
2131 if (lwgeom_ndims(lwgeom) > 2) {
2132 LWGEOM *lwgeom2d = lwgeom_force_2d(lwgeom);
2133 lwgeom_free(lwgeom);
2134 lwgeom = lwgeom2d;
2135 }
2136
2137 point = lwgeom_as_lwpoint(lwgeom);
2138 getPoint2d_p(point->point, 0, &p);
2139
2141 raster,
2142 p.x, p.y,
2143 &x, &y,
2144 NULL
2145 ) != ES_NONE) {
2146 rt_raster_destroy(raster);
2147 PG_FREE_IF_COPY(pgraster, 0);
2148 lwgeom_free(lwgeom);
2149 PG_FREE_IF_COPY(geom, 2);
2150 elog(ERROR, "RASTER_nearestValue: Could not compute pixel coordinates from spatial coordinates");
2151 PG_RETURN_NULL();
2152 }
2153
2154 /* get value at point */
2155 if (
2156 (x >= 0 && x < rt_raster_get_width(raster)) &&
2157 (y >= 0 && y < rt_raster_get_height(raster))
2158 ) {
2159 if (rt_band_get_pixel(band, x, y, &value, &isnodata) != ES_NONE) {
2160 rt_raster_destroy(raster);
2161 PG_FREE_IF_COPY(pgraster, 0);
2162 lwgeom_free(lwgeom);
2163 PG_FREE_IF_COPY(geom, 2);
2164 elog(ERROR, "RASTER_nearestValue: Could not get pixel value for band at index %d", bandindex);
2165 PG_RETURN_NULL();
2166 }
2167
2168 /* value at point, return value */
2169 if (!exclude_nodata_value || !isnodata) {
2170 rt_raster_destroy(raster);
2171 PG_FREE_IF_COPY(pgraster, 0);
2172 lwgeom_free(lwgeom);
2173 PG_FREE_IF_COPY(geom, 2);
2174
2175 PG_RETURN_FLOAT8(value);
2176 }
2177 }
2178
2179 /* get neighborhood */
2181 band,
2182 x, y,
2183 0, 0,
2184 exclude_nodata_value,
2185 &npixels
2186 );
2187 rt_band_destroy(band);
2188 /* error or no neighbors */
2189 if (count < 1) {
2190 /* error */
2191 if (count < 0)
2192 elog(NOTICE, "Could not get the nearest value for band at index %d", bandindex);
2193 /* no nearest pixel */
2194 else
2195 elog(NOTICE, "No nearest value found for band at index %d", bandindex);
2196
2197 lwgeom_free(lwgeom);
2198 PG_FREE_IF_COPY(geom, 2);
2199 rt_raster_destroy(raster);
2200 PG_FREE_IF_COPY(pgraster, 0);
2201 PG_RETURN_NULL();
2202 }
2203
2204 /* more than one nearest value, see which one is closest */
2205 if (count > 1) {
2206 int i = 0;
2207 LWPOLY *poly = NULL;
2208 double lastdist = -1;
2209 double dist;
2210
2211 for (i = 0; i < count; i++) {
2212 /* convex-hull of pixel */
2213 poly = rt_raster_pixel_as_polygon(raster, npixels[i].x, npixels[i].y);
2214 if (!poly) {
2215 lwgeom_free(lwgeom);
2216 PG_FREE_IF_COPY(geom, 2);
2217 rt_raster_destroy(raster);
2218 PG_FREE_IF_COPY(pgraster, 0);
2219 elog(ERROR, "RASTER_nearestValue: Could not get polygon of neighboring pixel");
2220 PG_RETURN_NULL();
2221 }
2222
2223 /* distance between convex-hull and point */
2224 dist = lwgeom_mindistance2d(lwpoly_as_lwgeom(poly), lwgeom);
2225 if (lastdist < 0 || dist < lastdist) {
2226 value = npixels[i].value;
2227 hasvalue = 1;
2228 }
2229 lastdist = dist;
2230
2231 lwpoly_free(poly);
2232 }
2233 }
2234 else {
2235 value = npixels[0].value;
2236 hasvalue = 1;
2237 }
2238
2239 pfree(npixels);
2240 lwgeom_free(lwgeom);
2241 PG_FREE_IF_COPY(geom, 2);
2242 rt_raster_destroy(raster);
2243 PG_FREE_IF_COPY(pgraster, 0);
2244
2245 if (hasvalue)
2246 PG_RETURN_FLOAT8(value);
2247 else
2248 PG_RETURN_NULL();
2249}
#define TRUE
Definition dbfopen.c:73
#define FALSE
Definition dbfopen.c:72
int32_t gserialized_get_srid(const GSERIALIZED *g)
Extract the SRID from the serialized form (it is packed into three bytes so this is a handy function)...
LWGEOM * lwgeom_from_gserialized(const GSERIALIZED *g)
Allocate a new LWGEOM from a GSERIALIZED.
uint32_t gserialized_get_type(const GSERIALIZED *g)
Extract the geometry type from the serialized form (it hides in the anonymous data area,...
int lwgeom_ndims(const LWGEOM *geom)
Return the number of dimensions (2, 3, 4) in a geometry.
Definition lwgeom.c:983
void lwgeom_free(LWGEOM *geom)
Definition lwgeom.c:1246
int getPoint2d_p(const POINTARRAY *pa, uint32_t n, POINT2D *point)
Definition lwgeom_api.c:342
LWGEOM * lwgeom_force_2d(const LWGEOM *geom)
Strip out the Z/M components of an LWGEOM.
Definition lwgeom.c:821
#define POINTTYPE
LWTYPE numbers, used internally by PostGIS.
Definition liblwgeom.h:102
double lwgeom_mindistance2d(const LWGEOM *lw1, const LWGEOM *lw2)
Function initializing min distance calculation.
Definition measures.c:212
void lwpoly_free(LWPOLY *poly)
Definition lwpoly.c:175
LWGEOM * lwpoly_as_lwgeom(const LWPOLY *obj)
Definition lwgeom.c:357
int32_t clamp_srid(int32_t srid)
Return a valid SRID from an arbitrary integer Raises a notice if what comes out is different from wha...
Definition lwutil.c:339
int32_t rt_raster_get_srid(rt_raster raster)
Get raster's SRID.
Definition rt_raster.c:360
LWPOLY * rt_raster_pixel_as_polygon(rt_raster raster, int x, int y)
Get a raster pixel as a polygon.
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.
Definition rt_raster.c:686
rt_errorstate rt_band_get_pixel(rt_band band, int x, int y, double *value, int *nodata)
Get pixel value.
Definition rt_band.c:1551
void rt_raster_destroy(rt_raster raster)
Release memory associated to a raster.
Definition rt_raster.c:86
@ ES_NONE
Definition librtcore.h:182
void rt_band_destroy(rt_band band)
Destroy a raster band.
Definition rt_band.c:499
uint16_t rt_raster_get_num_bands(rt_raster raster)
Definition rt_raster.c:376
uint16_t rt_raster_get_height(rt_raster raster)
Definition rt_raster.c:133
uint16_t rt_raster_get_width(rt_raster raster)
Definition rt_raster.c:125
uint32_t rt_band_get_nearest_pixel(rt_band band, int x, int y, uint16_t distancex, uint16_t distancey, int exclude_nodata_value, rt_pixel *npixels)
Get nearest pixel(s) with value (not NODATA) to specified pixel.
Definition rt_band.c:1709
rt_raster rt_raster_deserialize(void *serialized, int header_only)
Return a raster from a serialized form.
rt_band rt_raster_get_band(rt_raster raster, int bandNum)
Return Nth band, or NULL if unavailable.
Definition rt_raster.c:385
static LWPOINT * lwgeom_as_lwpoint(const LWGEOM *lwgeom)
Definition lwinline.h:127
static int lwgeom_is_empty(const LWGEOM *geom)
Return true or false depending on whether a geometry is an "empty" geometry (no vertices members)
Definition lwinline.h:199
int value
Definition genraster.py:62
int count
Definition genraster.py:57
raster
Be careful!! Zeros function's input parameter can be a (height x width) array, not (width x height): ...
Definition rtrowdump.py:125
POINTARRAY * point
Definition liblwgeom.h:471
double y
Definition liblwgeom.h:390
double x
Definition liblwgeom.h:390
double value
Definition librtcore.h:2540
Struct definitions.
Definition librtcore.h:2452

References clamp_srid(), ES_NONE, FALSE, getPoint2d_p(), gserialized_get_srid(), gserialized_get_type(), lwgeom_as_lwpoint(), lwgeom_force_2d(), lwgeom_free(), lwgeom_from_gserialized(), lwgeom_is_empty(), lwgeom_mindistance2d(), lwgeom_ndims(), lwpoly_as_lwgeom(), lwpoly_free(), LWPOINT::point, POINTTYPE, rt_band_destroy(), rt_band_get_nearest_pixel(), rt_band_get_pixel(), rt_raster_deserialize(), rt_raster_destroy(), rt_raster_geopoint_to_cell(), rt_raster_get_band(), rt_raster_get_height(), rt_raster_get_num_bands(), rt_raster_get_srid(), rt_raster_get_width(), rt_raster_pixel_as_polygon(), TRUE, rt_pixel_t::value, POINT2D::x, and POINT2D::y.

Here is the call graph for this function: