Skip to content

Shape Boolean ​

Geometric boolean operations between two shapes — Union, Intersect, Subtract, InverseSubtract, Xor. Outputs a new shape with fresh PointIds.

Category: Shape Ops Menu path: Shape Ops > Shape Boolean

Ports ​

PortTypeDirectionDescription
shape_ashapeinputSubject shape (the "A" in A op B)
shape_bshapeinputClip shape (the "B" in A op B)
outshapeoutputResult of the boolean operation

Parameters ​

ParamTypeDefaultDescription
operationenumUnionBoolean mode: Union (A ∪ B), Intersect (A ∩ B), Subtract (A − B), InverseSubtract (B − A), Xor (A ⊕ B)
precisionscalar1.0Polyline sampling resolution in pixels. Lower = smoother (more vertices), slower. Only affects bezier input.
outputenumBezierBezier fits Catmull-Rom cubic beziers through the result polyline for smooth curves. Polyline emits straight-line segments (faceted, fastest).

How It Works ​

Draw Shape Local fill/stroke mapping retains a common source frame when inputs agree. Synthesizing geometry from differing frames resets the mapping to comp-centered identity; this is not a deforming-UV or image-fit operation. Passthroughs retain their source frame.

Shape Boolean takes two closed shapes, runs them through a polygon clipping algorithm (via the i_overlay crate — the industry-standard approach for robust boolean operations on polygons), and emits a new shape representing the geometric result.

Operations ​

OperationResult
UnionA ∪ B — outer boundary of both shapes combined. Disjoint inputs → multiple output paths.
IntersectA ∩ B — only the region where both overlap. Disjoint inputs → empty output.
SubtractA − B — everything in A that isn't in B. Classic "punch a hole" operation.
InverseSubtractB − A — the reverse of Subtract (often useful when you have the wrong order).
XorA ⊕ B — regions unique to each shape, excluding the overlap.

Precision and bezier output ​

Boolean operations require polygons, not beziers. Shape Boolean subdivides bezier segments into polyline steps of roughly precision pixels so curved input makes it through the clipper. With output = Bezier (the default), the result is re-fit to cubic bezier segments via Catmull-Rom interpolation — circles round-trip as circles within a visible fidelity budget.

Pick Polyline output when you want explicit flat edges (retro pixel-art look) or when a downstream node will replace the segments anyway (e.g. feeding the result directly into a ResampleShape).

Hole handling ​

Subtract producing a donut emits two paths: the outer boundary and the opposite-winding inner hole. The output shape's fillRule is forced to NonZero, and all contours belonging to one result region (outer boundary + its holes) are tagged with a shared fill group (glyphIndex path attribute — the same mechanism TextToShape uses for letter counters). DrawShape tessellates a fill group as a single unit, so the hole is cut out correctly — including the full-containment case where the shapes' outlines never cross (a star fully inside a circle subtracts into a coin). Regions without holes are left untagged.

Attributes and PointIds ​

Point IDs are regenerated every evaluation. Boolean ops invent entirely new vertices where input edges intersect — there's no correspondence between input and output PointIds. Downstream nodes that key on specific PointIds (e.g. PointAttributes with a Custom attribute referencing a named vertex) will need to be set up after the Boolean node in the chain.

Path attributes are inherited from shape_a. Each output path gets the same color, strokeWidth, opacity, etc. as shape_a's first path. Attributes on shape_b are dropped (documented v1 policy — the result is treated as a new object). The one exception is glyphIndex: the boolean assigns its own fill-group tags (see Hole handling) rather than inheriting a stale per-glyph index from a text-derived input.

For per-glyph / per-path styling post-boolean, feed the output into ShapeAttributes downstream.

Usage Examples ​

Donut (animated) ​

Circle (outer, radius: 100) ─┐
                              ├─► ShapeBoolean (Subtract) ─► DrawShape ─► Output
Circle (inner, radius: 50) ──┘  (animate position/radius)

Classic donut — punch an animated hole through a fixed outer shape.

Shape union with color ​

Circle ────┐
            ├─► ShapeBoolean (Union) ─► ShapeAttributes (color: red) ─► DrawShape
Rectangle ─┘

Merge two primitives into one solid silhouette.

Intersect for masking ​

Text → TextToShape ──┐
                      ├─► ShapeBoolean (Intersect) ─► DrawShape
Circle ──────────────┘

The letters only render inside the circle — text clipped to shape, as pure vector geometry.

Logo composition ​

Polygon (star) ────┐
                    ├─► ShapeBoolean (Subtract) ─► OffsetPath (-5) ─► DrawShape
Polygon (star)  ──┘ (scaled smaller)

Star outline with an inset border, built from two booleans.

Text counter-cut ​

Use Subtract with a text shape as B to cut letter-shaped holes out of another shape.

Animated combine ​

Keyframe operation between Union / Intersect / Xor for a morph-between-modes transition (the change is instant per frame; results are stable so easing via InterpolationType::Hold gives a hard cut, Linear is meaningless for enums).

Tips ​

  • Precision tradeoff: 1.0px is sub-pixel at 1080p — usually invisible. Drop to 0.25 for extreme zoom; raise to 2.0+ for faster interactive editing on complex paths.
  • Self-intersecting input: i_overlay respects the input's fillRule (NonZero / EvenOdd), so a self-intersecting path upstream is interpreted according to that rule. If you see unexpected results on star shapes with crossing edges, check the upstream shape's fill rule.
  • Open paths are skipped. A Boolean is only defined on closed regions — feeding an open path does nothing useful. Close the path upstream (e.g. set closed: true on EditableShape) or use OffsetPath to thicken it into a region first.
  • Disjoint inputs survive. Union of two non-overlapping circles is two separate paths in the output, not one path with a gap.
  • Precision is animation-stable. Changing precision does not jitter the output shape — the same inputs at the same precision always produce identical geometry. Animate operation or the inputs themselves, not precision.
  • For smooth curves: keep output = Bezier (default). The Catmull-Rom fit is visually close to the intent even when the internal polyline was coarse.
  • MergeShapes — concatenates shapes without geometric intersection (cheaper, but doesn't resolve overlaps)
  • OffsetPath — expand/contract a single shape (often useful before/after boolean)
  • RoundCorners — smooth the corners produced by a polyline-output boolean
  • ResampleShape — re-smooth the output of a Polyline-mode boolean into beziers
  • ShapeAttributes — re-apply per-path color/stroke after boolean (since attributes only inherit from shape_a)