Skip to content

contours() emits degenerate and duplicate lines for exact-level plateaus #2790

@brendancol

Description

@brendancol

Describe the bug

contours() returns zero-length and duplicate lines when raster cells exactly equal the contour level. In xrspatial/contour.py, the >= level corner test (around line 76) plus the interpolation fallback t = (level - a) / (b - a) if b != a else 0.5 (around lines 172-204) collapse a segment to a point when a corner sits exactly on the level. The interpolation parameter resolves to an endpoint, so the segment has identical start and end coordinates, or it repeats a vertex already in the line.

A 4x4 raster with a flat interior plateau contoured at level=1.0 shows it: the call returns three lines, two of which are single-point "lines" (a 2-row array whose rows are identical). The GeoPandas path (around line 547) only checks len(coords) >= 2, so these pass straight through into the GeoDataFrame.

Reproduce

import numpy as np
import xarray as xr
from xrspatial.contour import contours

data = np.array([
    [0, 0, 0, 0],
    [0, 1, 1, 0],
    [0, 1, 1, 0],
    [0, 0, 0, 0],
], dtype=float)
res = contours(xr.DataArray(data, dims=['y', 'x']), levels=[1.0])
for lvl, coords in res:
    print(coords.shape, coords)

Prints one valid ring plus two (2, 2) arrays whose two points are the same.

Expected behavior

Exact-level plateaus should produce only valid lines. Drop zero-length and single-point segments, and drop duplicate geometries, before results are returned or converted to a GeoDataFrame.

Additional context

All backends route through the same stitching and output code, so the fix should cover numpy, cupy, dask+numpy, and dask+cupy. Needs a regression test for the 4x4 plateau at level=1.0 plus a few other exact-level cases.

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't workingseverity:mediumSweep finding: MEDIUM

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions