From 983784d9ec028ee1d0451791d1afcdf212897438 Mon Sep 17 00:00:00 2001 From: Arti Zirk Date: Sun, 1 Nov 2026 11:15:57 +0200 Subject: [PATCH] fix(badapple): flip potrace y-up polygons to the framebuffer --- bad-apple/data/manifest.json | 4 ++-- bad-apple/pipeline/vectorize.py | 10 ++++++++++ bad-apple/tests/test_vectorize.py | 10 +++++++++- 3 files changed, 21 insertions(+), 3 deletions(-) diff --git a/bad-apple/data/manifest.json b/bad-apple/data/manifest.json index f04d837..3b8b15b 100644 --- a/bad-apple/data/manifest.json +++ b/bad-apple/data/manifest.json @@ -1,7 +1,7 @@ { "cost_us": { - "max": 37991, - "mean": 7472.0695503699535, + "max": 37992, + "mean": 7472.069550369951, "p50": 7948, "p95": 12011 }, diff --git a/bad-apple/pipeline/vectorize.py b/bad-apple/pipeline/vectorize.py index 99dd87e..1e5c74f 100644 --- a/bad-apple/pipeline/vectorize.py +++ b/bad-apple/pipeline/vectorize.py @@ -113,6 +113,16 @@ def trace(mask: np.ndarray, params: dict) -> list[Polygon]: with open(json_path, "r", encoding="utf-8") as handle: polygons = parse_potrace_geojson(handle.read()) + # potrace's GeoJSON uses a y-up coordinate system; the framebuffer is + # y-down. Without this the whole movie is vertically mirrored. + flipped: list[Polygon] = [] + for poly in polygons: + rings: Polygon = [] + for ring in poly: + rings.append([(x, float(height) - y) for x, y in ring]) + flipped.append(rings) + polygons = flipped + simplified: list[Polygon] = [] for poly in polygons: rings: Polygon = [] diff --git a/bad-apple/tests/test_vectorize.py b/bad-apple/tests/test_vectorize.py index cb63146..673d73d 100644 --- a/bad-apple/tests/test_vectorize.py +++ b/bad-apple/tests/test_vectorize.py @@ -1,6 +1,6 @@ import numpy as np -from pipeline.vectorize import rdp, rasterize, trace +from pipeline.vectorize import rdp, rasterize, trace, vectorize_frame def test_rdp_drops_collinear_point(): @@ -23,6 +23,14 @@ def test_rasterize_square_with_hole(): assert not out[3, 3] +def test_trace_preserves_vertical_position(): + mask = np.zeros((32, 32), dtype=bool) + mask[2:6, 4:12] = True + out = vectorize_frame(mask, {"rdp_epsilon": 1.0, "min_segment": 2}) + assert out[3, 5] + assert not out[28, 5] + + def test_trace_simple_shape_and_roundtrip(): mask = np.zeros((16, 16), dtype=bool) mask[4:12, 4:12] = True