ST_VALUE not resampling using nearest neighbor
Herzsprung, Severin (LDBV)
Severin.Herzsprung at ldbv.bayern.de
Wed Feb 19 11:12:27 PST 2025
Hi,
I have been using PostGIS to build and query a DEM, while testing I noticed that I was not getting the expected results from st_value using resample => 'nearest'. Instead of returning the value of the nearest pixel the x-coordinate is always simply rounded down, while the y-coordinate ist always rounded up.
The following query showcases this behaviour:
WITH r AS (
SELECT ST_SetValues(
ST_AddBand(
ST_MakeEmptyRaster(
width => 2, height => 2,
upperleftx => 0, upperlefty => 2,
scalex => 1.0, scaley => -1.0,
skewx => 0, skewy => 0, srid => 4326),
index => 1, pixeltype => '16BSI',
initialvalue => 0, nodataval => -999),
1,1,1, newvalueset =>ARRAY[ARRAY[10.0::float8, 50.0::float8], ARRAY[40.0::float8, 20.0::float8]]) AS rast
)
SELECT
'Test 5',
round(ST_Value(rast, 1, 'SRID=4326;POINT(0 2)'::geometry, resample => 'nearest')) as top_left,
round(ST_Value(rast, 1, 'SRID=4326;POINT(1 2)'::geometry, resample => 'nearest')) as top_right,
round(ST_Value(rast, 1, 'SRID=4326;POINT(0 1)'::geometry, resample => 'nearest')) as bottom_left,
round(ST_Value(rast, 1, 'SRID=4326;POINT(1 1)'::geometry, resample => 'nearest')) as bottom_right,
round(ST_Value(rast, 1, 'SRID=4326;POINT(0.9 1)'::geometry, resample => 'nearest')) as should_be_bottom_right_but_is_bottom_left,
round(ST_Value(rast, 1, 'SRID=4326;POINT(1 1.1)'::geometry, resample => 'nearest')) as should_be_bottom_right_but_is_top_right,
round(ST_Value(rast, 1, 'SRID=4326;POINT(0.9 1.1)'::geometry, resample => 'nearest')) as should_be_bottom_right_but_is_top_left
FROM r;
Resulting in:
?column? | top_left | top_right | bottom_left | bottom_right | should_be_bottom_right_but_is_bottom_left | should_be_bottom_right_but_is_top_right | should_be_bottom_right_but_is_top_left
----------+----------+-----------+-------------+--------------+-------------------------------------------+-----------------------------------------+----------------------------------------
Test 5 | 10 | 50 | 40 | 20 | 40 | 50 | 10
When looking through the source code on git I found that the method 'rt_band_get_pixel_resample' that is eventually called when using st_value simply rounds down the given raster coordinates instead of actually using nearest-neighbor:
else if (resample == RT_NEAREST) {
return rt_band_get_pixel(
band, floor(xr), floor(yr),
r_value, r_nodata
);
}
So my question is, is this the intended behaviour?
Is there maybe another way to get a value from a raster using actual nearest-neighbor resampling?
I'm using Postgres 17.2 and postgis 3.6.0dev if that is relevant.
Thanks in advance
-------------- next part --------------
A non-text attachment was scrubbed...
Name: smime.p7s
Type: application/pkcs7-signature
Size: 7552 bytes
Desc: not available
URL: <http://lists.osgeo.org/pipermail/postgis-users/attachments/20250219/ca87a6e3/attachment.bin>
More information about the postgis-users
mailing list