Expand description
Path boolean ops (M-BOOL.0 / AUT-161 → M-BOOL.5 / AUT-166).
In-house polygon-clipping engine. The full design rationale —
algorithm choice, alternatives rejected, follow-up tickets — is
captured in _docs/adr/M-BOOL-backend.md.
§Quick API
ⓘ
use wisp::path::boolean::{combine, BooleanOp, BoolOptions};
use wisp::path::PathBuilder;
let circle_a = /* a closed Path */;
let circle_b = /* a closed Path */;
let union = combine(&circle_a, &circle_b, BooleanOp::Union, BoolOptions::default());§Algorithm (v1, polygon-only)
- Flatten each
Pathto a list of closed polylines (one perMoveTo-rooted subpath). - Build a directed-edge list per polyline, labelled
Subject(path A) orClip(path B). - Find every pair-wise edge intersection in O(n·m). Subdivide both edges at each intersection so every output fragment has integer-multiplicity endpoints.
- For each fragment, evaluate “inside A?” and “inside B?” at the fragment’s midpoint via the parity (even-odd) point-in-polygon test against the other polygon’s full edge list.
- Keep each fragment iff it lies on the boundary of the desired output region — i.e. the op rule evaluates differently on the two sides of the fragment.
- Stitch retained fragments tip-to-tail into closed contours;
emit one
MoveTo+LineTo*+Closesubpath per contour.
§Known v1 limitations
All deferred to follow-up tickets (AUT-167..179):
- Bezier curves flatten via
crate::scene::path::Path::flattenbefore processing; curvature is lost. M-BOOL.7 lands aflatten_subpathsthat preserves multi-subpath structure. - Holes +
FillRule::NonZerosemantics are stubbed:BoolOptions::fill_ruleis accepted but onlyEvenOddis honoured today. M-BOOL.8 implements winding-number tracking. - Self-intersecting inputs → undefined output. Match Clipper2 v1.
- O(n·m) intersection finding is fine for our typical path sizes (50–500 vertices). M-BOOL.17 benchmarks set the bar for a future Bentley-Ottmann sweep-line if needed.
Structs§
- Bool
Options - Tuning knobs for
combine. - Edge 🔒
Enums§
- Boolean
Op - The four primitive boolean ops on two paths.
- Edge
Label 🔒 - Fill
Rule - Fill-rule policy for self-overlapping inputs.
Functions§
- build_
edges 🔒 - combine
- Combine two paths via the given boolean op.
- combine_
n - Convenience N-ary fold (M-BOOL.6 / AUT-167).
- contours_
to_ 🔒path - flatten_
cubic 🔒 - flatten_
quad 🔒 - inside_
any 🔒 - keep_
fragment 🔒 - Decide whether a fragment is retained for the given op.
- op_rule 🔒
- perp_
distance 🔒 - ray_
crossings 🔒 - Parity / even-odd point-in-polygon. Returns the number of times a
rightward ray from
pointcrosses any edge of the polygon. - rebuild_
from_ 🔒polylines - segment_
intersection 🔒 - Robust-ish two-segment intersection. Returns
(t_along_first, t_along_second, intersection_point)when the segments cross in the interior of both. Endpoint-only touches are filtered out by the caller viat > tolerance && t < 1 - tolerance. ReturnsNonefor parallel, collinear, or near-collinear pairs. - split_
at_ 🔒intersections - Split every edge at its intersections with every other edge. Returns the (possibly larger) fragment list.
- stitch 🔒
- Walk fragments tip-to-tail, building closed loops.
- subpaths 🔒
- Decompose a
Pathinto closed polylines, one perMoveTo-rooted subpath. Open subpaths (withoutClose) are silently dropped — boolean ops are only meaningful on closed regions.