Skip to content

[GH-3111] Fix scanline x-intercepts on rasters with non-square pixels#3113

Merged
jiayuasu merged 5 commits into
apache:masterfrom
james-willis:fix/gh-3111-scanline-intercepts
Jul 19, 2026
Merged

[GH-3111] Fix scanline x-intercepts on rasters with non-square pixels#3113
jiayuasu merged 5 commits into
apache:masterfrom
james-willis:fix/gh-3111-scanline-intercepts

Conversation

@james-willis

@james-willis james-willis commented Jul 17, 2026

Copy link
Copy Markdown
Collaborator

Did you read the Contributor Guide?

Is this PR related to a ticket?

What changes were proposed in this PR?

Rasterization.computeScanlineIntersections computed edge x-intercepts as p1X + ((p1Y - y) / slope), dividing a pixel-space Δy by a world-space slope. On square north-up pixels the missing factor -scaleY/scaleX equals 1 so the result is coincidentally correct, but on any raster whose pixels are not square in world units the intercepts land in the wrong place and pixels whose centers are inside the polygon are dropped (or near-edge pixels selected asymmetrically). This PR converts the pixel Δy to world units and the resulting world Δx back to pixels, keeping the intercept in pixel space for any pixel aspect ratio.

How was this patch tested?

  • New testAsRasterWithNonSquarePixels covering the centroid rule, allTouched, a polygon with a diagonal-edged interior ring, and a bottom-up grid, all on 2x3-world-unit pixels. Expected matrices are produced by GDAL (rasterio.features.rasterize) on the same grids. The test was written first and fails on master (the dropped center-inside pixels from Rasterization selects wrong pixels on rasters with non-square pixels (pixel/world unit mix in scanline x-intercepts) #3111).
  • Full common module suite passes (1146 tests, 0 failures): existing square-pixel expectations are bit-identical before and after the fix.
  • A 300-case fuzz comparing RasterConstructors.asRaster against rasterio.features.rasterize over random polygons on random anisotropic north-up and south-up grids: centroid-rule mismatches go from 187/214 cases before the fix to 0/214 after. (The allTouched boundary path, which rasterizes ring segments with Bresenham rather than scanlines, retains a small pre-existing divergence from GDAL — 24/86 fuzz cases by 1-2 boundary pixels, down from 32/86 — which is a separate issue.)
  • A seeded (deterministic) 100-case version of that fuzz ships with the PR as python/tests/sql/test_rasterize_parity.py, comparing RS_AsRaster against rasterio.features.rasterize in a single batched Spark job. The centroid-rule test fails against the released 1.9.0 jars and passes with this fix; the same corpus under allTouched=true is a strict xfail documenting the pre-existing sampling divergence above, and will flip to a visible failure when that is fixed.

Did this PR include necessary documentation updates?

  • No, this PR does not affect any public API so no need to change the documentation.

@james-willis
james-willis marked this pull request as ready for review July 17, 2026 08:12
@james-willis
james-willis requested a review from jiayuasu as a code owner July 17, 2026 08:12
@james-willis
james-willis requested a review from prantogg July 17, 2026 17:51
@jiayuasu jiayuasu added this to the sedona-1.9.1 milestone Jul 19, 2026
@jiayuasu
jiayuasu merged commit 6709670 into apache:master Jul 19, 2026
44 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Rasterization selects wrong pixels on rasters with non-square pixels (pixel/world unit mix in scanline x-intercepts)

2 participants