Expected behavior
RS_PixelAsPoint, RS_PixelAsCentroid and RS_PixelAsPolygon are one family — the same grid coordinate interpreted as a corner, a centre and a footprint — so they should agree on what an out-of-grid coordinate means.
Actual behavior
Only RS_PixelAsPoint rejects one. On a 2×3-pixel raster at (100, 500) with Sedona 1.9.1:
RS_PixelAsPoint(rast, 1, 1) -> POINT (100 500)
RS_PixelAsPoint(rast, 0, 0) -> IndexOutOfBoundsException:
Specified pixel coordinates (0, 0) do not lie in the raster
RS_PixelAsCentroid(rast, 0, 0) -> POINT (99 501.5)
RS_PixelAsPolygon(rast, 0, 0) -> POLYGON ((98 503, 100 503, 100 500, 98 500, 98 503))
The two siblings extrapolate along the geotransform without complaint. Note the polygon's first corner, (98 503): that is exactly the point RS_PixelAsPoint(0, 0) refuses to return. The value is already computed and returned by a sibling function on the same input — only this one entry point declines to hand it over.
This is documented, so it reads as deliberate rather than accidental, but the docs state the inconsistency plainly:
RS_PixelAsPoint: "If the pixel coordinates specified do not exist in the raster (out of bounds), RS_PixelAsPoint throws an IndexOutOfBoundsException."
RS_PixelAsPolygon and RS_PixelAsCentroid: "If colX and rowY are out of bounds for the raster, they are interpolated assuming the same skew and translate values."
Cause
One call site in common/src/main/java/org/apache/sedona/common/raster/PixelFunctions.java. getPixelAsPoint uses the range-checking helper:
Point2D point2D = RasterUtils.getWorldCornerCoordinatesWithRangeCheck(raster, colX, rowY);
while getPixelAsPolygon uses the unchecked one:
Point2D point2D1 = RasterUtils.getWorldCornerCoordinates(raster, colX, rowY);
and getPixelAsCentroid delegates to getPixelAsPolygon, inheriting the unchecked behaviour. getWorldCornerCoordinatesWithRangeCheck (common/src/main/java/org/apache/sedona/common/utils/RasterUtils.java) has exactly one caller — getPixelAsPoint.
Proposed fix
Drop the range check so getPixelAsPoint matches its siblings, extrapolating along the geotransform. That direction is the non-breaking one: it turns an exception into a value, where the reverse would break existing RS_PixelAsCentroid/RS_PixelAsPolygon callers who rely on extrapolation today.
That would mean:
getPixelAsPoint calls RasterUtils.getWorldCornerCoordinates, leaving getWorldCornerCoordinatesWithRangeCheck unused (remove it, or keep it if another caller is planned).
testPixelAsPointOutOfBounds in common/src/test/java/org/apache/sedona/common/raster/FunctionsTest.java currently pins the exception, and would assert the extrapolated point instead.
- The
RS_PixelAsPoint doc line changes to match the wording already used by the other two.
I am happy to open the PR if the direction sounds right. The alternative — making all three raise — is defensible on the grounds that an out-of-grid coordinate is usually a caller error, but it is a breaking change for two functions rather than a widening of one, and it would leave RS_PixelAsPolygon unable to return a footprint it can compute perfectly well.
For cross-implementation context: SedonaDB extrapolates for all three, so aligning this way would also close a divergence between the two engines.
Expected behavior
RS_PixelAsPoint,RS_PixelAsCentroidandRS_PixelAsPolygonare one family — the same grid coordinate interpreted as a corner, a centre and a footprint — so they should agree on what an out-of-grid coordinate means.Actual behavior
Only
RS_PixelAsPointrejects one. On a 2×3-pixel raster at(100, 500)with Sedona 1.9.1:The two siblings extrapolate along the geotransform without complaint. Note the polygon's first corner,
(98 503): that is exactly the pointRS_PixelAsPoint(0, 0)refuses to return. The value is already computed and returned by a sibling function on the same input — only this one entry point declines to hand it over.This is documented, so it reads as deliberate rather than accidental, but the docs state the inconsistency plainly:
RS_PixelAsPoint: "If the pixel coordinates specified do not exist in the raster (out of bounds), RS_PixelAsPoint throws an IndexOutOfBoundsException."RS_PixelAsPolygonandRS_PixelAsCentroid: "IfcolXandrowYare out of bounds for the raster, they are interpolated assuming the same skew and translate values."Cause
One call site in
common/src/main/java/org/apache/sedona/common/raster/PixelFunctions.java.getPixelAsPointuses the range-checking helper:while
getPixelAsPolygonuses the unchecked one:and
getPixelAsCentroiddelegates togetPixelAsPolygon, inheriting the unchecked behaviour.getWorldCornerCoordinatesWithRangeCheck(common/src/main/java/org/apache/sedona/common/utils/RasterUtils.java) has exactly one caller —getPixelAsPoint.Proposed fix
Drop the range check so
getPixelAsPointmatches its siblings, extrapolating along the geotransform. That direction is the non-breaking one: it turns an exception into a value, where the reverse would break existingRS_PixelAsCentroid/RS_PixelAsPolygoncallers who rely on extrapolation today.That would mean:
getPixelAsPointcallsRasterUtils.getWorldCornerCoordinates, leavinggetWorldCornerCoordinatesWithRangeCheckunused (remove it, or keep it if another caller is planned).testPixelAsPointOutOfBoundsincommon/src/test/java/org/apache/sedona/common/raster/FunctionsTest.javacurrently pins the exception, and would assert the extrapolated point instead.RS_PixelAsPointdoc line changes to match the wording already used by the other two.I am happy to open the PR if the direction sounds right. The alternative — making all three raise — is defensible on the grounds that an out-of-grid coordinate is usually a caller error, but it is a breaking change for two functions rather than a widening of one, and it would leave
RS_PixelAsPolygonunable to return a footprint it can compute perfectly well.For cross-implementation context: SedonaDB extrapolates for all three, so aligning this way would also close a divergence between the two engines.