"""Lawn-mask → editable polygon vectorization (W4b). No network/model.""" from __future__ import annotations import numpy as np from lawn_estimator.pipeline import _mask_to_polygon_px def test_traces_rectangle_outline(): m = np.zeros((100, 100), bool) m[20:80, 30:70] = True poly = _mask_to_polygon_px(m, simplify_px=2.0) assert len(poly) >= 4 # a closed ring xs, ys = [p[0] for p in poly], [p[1] for p in poly] assert min(xs) < 35 and max(xs) > 65 # spans the rectangle in x assert min(ys) < 25 and max(ys) > 75 # spans it in y def test_empty_mask_gives_no_polygon(): assert _mask_to_polygon_px(np.zeros((50, 50), bool)) == [] def test_picks_largest_region_and_caps_vertices(): m = np.zeros((160, 160), bool) m[10:20, 10:20] = True # small blob yy, xx = np.mgrid[0:160, 0:160] m |= (xx - 100) ** 2 + (yy - 100) ** 2 < 45 ** 2 # big disc → the "lawn" poly = _mask_to_polygon_px(m, simplify_px=1.0, max_points=30) assert 4 <= len(poly) <= 31 # simplified under the cap xs = [p[0] for p in poly] assert min(xs) > 40 # it traced the big disc, not the corner blob