From 791c3ff287e490351454b91c664a353586924ce2 Mon Sep 17 00:00:00 2001 From: Johannes Wolf Date: Sat, 17 Aug 2024 01:45:50 +0200 Subject: [PATCH] Fix clipper --- src/plot/axis-styles/orthorect-2d/clipper.typ | 23 +++++++++++++++---- 1 file changed, 19 insertions(+), 4 deletions(-) diff --git a/src/plot/axis-styles/orthorect-2d/clipper.typ b/src/plot/axis-styles/orthorect-2d/clipper.typ index 0cbdd33..66fbc09 100644 --- a/src/plot/axis-styles/orthorect-2d/clipper.typ +++ b/src/plot/axis-styles/orthorect-2d/clipper.typ @@ -28,15 +28,16 @@ ) let interpolated-end(a, b) = { + let pts = () for (edge-a, edge-b) in edges { let pt = cetz.intersection.line-line(a, b, edge-a, edge-b) if pt != none { - return pt + pts.push(pt) } } + return pts } - // Find lines crossing the rect bounds // by storing all crossings as tuples (, , ) let crossings = () @@ -47,15 +48,29 @@ crossings.push((0, true, points.first())) } - // Find crossings and compute interseciton points. + // Find crossings and compute intersection points. for i in range(1, points.len()) { let current-inside = in-rect(points.at(i)) if current-inside != was-inside { crossings.push(( i, current-inside, - interpolated-end(points.at(i - 1), points.at(i)))) + interpolated-end(points.at(i - 1), points.at(i)).first())) was-inside = current-inside + } else if not current-inside { + let (px, py) = points.at(i - 1) + let (cx, cy) = points.at(i) + let (lo-x, hi-x) = (calc.min(px, cx), calc.max(px, cx)) + let (lo-y, hi-y) = (calc.min(py, cy), calc.max(py, cy)) + + let x-differs = (lo-x < min-x and hi-x > max-x) or (lo-x < max-x and hi-x > max-x) + let y-differs = (lo-y < min-y and hi-y > max-y) or (lo-y < max-y and hi-y > max-y) + if x-differs or y-differs { + for pt in interpolated-end(points.at(i - 1), points.at(i)) { + crossings.push((i, not current-inside, pt)) + current-inside = not current-inside + } + } } }