`polygonize` result depends on coordinate magnitude
`polygonize`'s ring tracing produces a different result for the **same** boolean mask depending on the coordinate values it is given. It should only depend on the pattern (up to the coordinate transform).
## Reproducer
```julia
using GeometryOps
import GeoInterface as GI
A = fill(false, 5, 5); A[2:4, 2:4] .= true # one solid 3×3 block
only(GI.coordinates(polygonize(1:5, 1:5, A)))
# → [[[1.5, 1.5], [4.5, 1.5], [4.5, 4.5], [1.5, 4.5], [1.5, 1.5]]] # clean 5-point rectangle
only(GI.coordinates(polygonize(101:105, 101:105, A)))
# → [[[102.5, 101.5], [104.5, 101.5], [104.5, 104.5], [101.5, 104.5], [101.5, 101.5], [102.5, 101.5]]]
# same rectangle, +100, but 6 points: the ring starts mid-edge and leaves a redundant collinear vertex
```
The two rings are not translations of each other (5 vs 6 vertices).
## Worse manifestations
On larger / sparser masks the decomposition itself changes — different **polygon counts** for the same pattern:
```julia
using Random; Random.seed!(42)
data = rand(1:4, 100, 100) .== 1
GI.ngeom(polygonize(1:100, 1:100, data)) # 1138
GI.ngeom(polygonize(1001:1100, 1:100, data)) # 1116
GI.ngeom(polygonize(-100:-1, -100:-1, data)) # 1142
```
Some coordinate ranges also throw `KeyError: key (Inf, Inf) not found` from the ring tracer.
## Cause
Ring tracing in `_pixel_edges` / `_polygonize` (`src/methods/polygonize.jl`) starts from an arbitrary edge (`Dict` iteration order) and uses coordinate tuples as `Dict` keys, so the traversal — and hence vertex ordering, collinear-vertex emission, and ambiguous corner resolution — depends on the coordinate values rather than only the mask.
Surfaced while wiring the `polygonize` tests into CI in #429; two assertions there are marked `@test_broken` pointing here.
0 条评论