Skip to content

RS_PixelAsPoint raises out of grid where RS_PixelAsCentroid and RS_PixelAsPolygon extrapolate #3395

Description

@james-willis

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.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions