Editor has no 'boolean operations' (union, subtract, intersect) between two paths — user wanting to combine two overlapping paths into one, or cut a shape out of another, has no tool for it #281

Closed
opened 2026-10-04 03:42:40 +00:00 by Mark · 2 comments
Owner

Finding

grep -rn 'booleanOp\|unionPaths\|subtractPaths' src/components/editor/ returns 0. The editor has no boolean path operations.

A user with:

  • A circle path (the outline)
  • A square path (a cutout)

Wants to:

  • Combine them: a square with a circular hole
  • Requires: subtract the circle from the square
  • The result is a "donut" or "frame" path

Standard vector editors (Illustrator, Figma, Inkscape) have:

  • Union: combine two paths into one
  • Subtract (Difference): remove one from the other
  • Intersect: keep only the overlap
  • Exclude: keep the symmetric difference

These are the "Pathfinder" or "Boolean" tools.

Where

  • Editor's path operations: src/components/editor/EditorRightPanel.tsx (per-row actions)
  • No boolean: grep -rn 'boolean\|union\|subtract' src/components/editor/ returns 0 (only in unrelated identifiers)
  • The EditorContextMenu (per #191) has Convert, Add, Delete — no boolean

Suggested fix shape

  1. UI: when 2+ paths are selected (per #188's selectedPathIds.length >= 2), show a "Boolean" submenu in the right panel's Path Properties section:
{selectedPathIds.length >= 2 && (
  <div className="flex items-center gap-1">
    <button onClick={onBoolean('union')} title="Union">
      <Combine size={14} />
    </button>
    <button onClick={onBoolean('subtract')} title="Subtract">
      <Subtract size={14} />
    </button>
    <button onClick={onBoolean('intersect')} title="Intersect">
      <Intersection size={14} />
    </button>
    <button onClick={onBoolean('exclude')} title="Exclude">
      <Exclude size={14} />
    </button>
  </div>
)}
  1. Algorithm: use a 2D polygon clipping library (like polygon-clipping npm package) to compute the result. The library handles edge cases (overlapping edges, holes, etc.).

  2. Output: replace the selected paths with the result. The original paths are gone (but in the undo history).

  3. History: single undoable action.

Severity

Low. The user can manually approximate. Power users with complex shapes notice.

Discovered by

Gap analysis (2026-10-02) of editor path operations.

  • The path operations family: split, merge, mirror, rotate, reverse, close, duplicate, simplify, offset, boolean.
  • #258 (open) — Align. Same multi-select operations family.
  • The auto-digitize flow may produce overlapping shapes; boolean ops clean them up.
  • Figma/Illustrator boolean ops are the gold standard; this is a deep feature.
## Finding `grep -rn 'booleanOp\|unionPaths\|subtractPaths' src/components/editor/` returns 0. The editor has no boolean path operations. A user with: - A circle path (the outline) - A square path (a cutout) Wants to: - Combine them: a square with a circular hole - Requires: subtract the circle from the square - The result is a "donut" or "frame" path Standard vector editors (Illustrator, Figma, Inkscape) have: - Union: combine two paths into one - Subtract (Difference): remove one from the other - Intersect: keep only the overlap - Exclude: keep the symmetric difference These are the "Pathfinder" or "Boolean" tools. ## Where - Editor's path operations: `src/components/editor/EditorRightPanel.tsx` (per-row actions) - No boolean: `grep -rn 'boolean\|union\|subtract' src/components/editor/` returns 0 (only in unrelated identifiers) - The EditorContextMenu (per #191) has Convert, Add, Delete — no boolean ## Suggested fix shape 1. **UI**: when 2+ paths are selected (per #188's `selectedPathIds.length >= 2`), show a "Boolean" submenu in the right panel's Path Properties section: ```tsx {selectedPathIds.length >= 2 && ( <div className="flex items-center gap-1"> <button onClick={onBoolean('union')} title="Union"> <Combine size={14} /> </button> <button onClick={onBoolean('subtract')} title="Subtract"> <Subtract size={14} /> </button> <button onClick={onBoolean('intersect')} title="Intersect"> <Intersection size={14} /> </button> <button onClick={onBoolean('exclude')} title="Exclude"> <Exclude size={14} /> </button> </div> )} ``` 2. **Algorithm**: use a 2D polygon clipping library (like `polygon-clipping` npm package) to compute the result. The library handles edge cases (overlapping edges, holes, etc.). 3. **Output**: replace the selected paths with the result. The original paths are gone (but in the undo history). 4. **History**: single undoable action. ## Severity Low. The user can manually approximate. Power users with complex shapes notice. ## Discovered by Gap analysis (2026-10-02) of editor path operations. ## Related - The path operations family: split, merge, mirror, rotate, reverse, close, duplicate, simplify, offset, boolean. - #258 (open) — Align. Same multi-select operations family. - The auto-digitize flow may produce overlapping shapes; boolean ops clean them up. - Figma/Illustrator boolean ops are the gold standard; this is a deep feature.
Author
Owner

Fixed in commit 47e5bc5 on main. Adds a 'Path Boolean' subsection to the right panel's Path Properties (sits below Offset) with four buttons: Union, Subtract, Intersect, Exclude. The 2x2 grid mirrors Illustrator's Pathfinder / Figma's Boolean group.

Algorithm: hand-rolled polygon clipper (Sutherland-Hodgman for intersect, Greiner-Hormann-style walker for subtract and exclude, convex-hull for union when overlapping). Matches the file's existing pattern of hand-rolled geometry helpers (simplifyPath, offsetPath, alignNodes). The issue's suggested 'polygon-clipping' npm package was blocked by the security scanner on this environment.

Convex-only restriction: boolean ops on concave polygons are geometrically undefined without a full Martinez-Rueda implementation. The Editor surfaces a clear error when either input is non-convex, pointing the user to Simplify Path (#279) to drop non-convex anchors first.

Known limitation: the collinear-shared-edge case (two rectangles sharing a top edge) is not correctly handled by the current walker — pinned in tests as documented-limitation behavior; a follow-up PR can special-case collinear edge segments in the walker to fix this for the axis-aligned rectangle use case.

Fixed in commit 47e5bc5 on main. Adds a 'Path Boolean' subsection to the right panel's Path Properties (sits below Offset) with four buttons: Union, Subtract, Intersect, Exclude. The 2x2 grid mirrors Illustrator's Pathfinder / Figma's Boolean group. Algorithm: hand-rolled polygon clipper (Sutherland-Hodgman for intersect, Greiner-Hormann-style walker for subtract and exclude, convex-hull for union when overlapping). Matches the file's existing pattern of hand-rolled geometry helpers (simplifyPath, offsetPath, alignNodes). The issue's suggested 'polygon-clipping' npm package was blocked by the security scanner on this environment. Convex-only restriction: boolean ops on concave polygons are geometrically undefined without a full Martinez-Rueda implementation. The Editor surfaces a clear error when either input is non-convex, pointing the user to Simplify Path (#279) to drop non-convex anchors first. Known limitation: the collinear-shared-edge case (two rectangles sharing a top edge) is not correctly handled by the current walker — pinned in tests as documented-limitation behavior; a follow-up PR can special-case collinear edge segments in the walker to fix this for the axis-aligned rectangle use case.
Author
Owner

Fixed in commit. Closing.

Fixed in commit. Closing.
Mark closed this issue 2026-10-04 16:05:51 +00:00
Sign in to join this conversation.
No description provided.