Skip to main content

Module boolean

Module boolean 

Source
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)

  1. Flatten each Path to a list of closed polylines (one per MoveTo-rooted subpath).
  2. Build a directed-edge list per polyline, labelled Subject (path A) or Clip (path B).
  3. Find every pair-wise edge intersection in O(n·m). Subdivide both edges at each intersection so every output fragment has integer-multiplicity endpoints.
  4. 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.
  5. 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.
  6. Stitch retained fragments tip-to-tail into closed contours; emit one MoveTo+LineTo*+Close subpath per contour.

§Known v1 limitations

All deferred to follow-up tickets (AUT-167..179):

  • Bezier curves flatten via crate::scene::path::Path::flatten before processing; curvature is lost. M-BOOL.7 lands a flatten_subpaths that preserves multi-subpath structure.
  • Holes + FillRule::NonZero semantics are stubbed: BoolOptions::fill_rule is accepted but only EvenOdd is 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§

BoolOptions
Tuning knobs for combine.
Edge 🔒

Enums§

BooleanOp
The four primitive boolean ops on two paths.
EdgeLabel 🔒
FillRule
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 point crosses 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 via t > tolerance && t < 1 - tolerance. Returns None for 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 Path into closed polylines, one per MoveTo-rooted subpath. Open subpaths (without Close) are silently dropped — boolean ops are only meaningful on closed regions.