Graphite/libraries/path-bool
Dennis Kobert a4ec50d8ba
Some checks are pending
Editor: Dev & CI / build (push) Waiting to run
Editor: Dev & CI / cargo-deny (push) Waiting to run
Improve robustness and performance of the boolean operation algorithm (#2191)
* Improve perf of path bool lib

* Use swap remove

* Use outer/inner bounding box for inclusion testing

* Reuse allocations for hit testing

* Use direct root finding for inclusion testing

* Reuse bounding box

* Use faster hash and specify capacities

* Use hashmap based approach for find vertices

* Unroll find_vertecies loop and use 32 bit positions

* Tune initial vec capacities

* Remove unused bounding boxes

* Use smallvec for storing outgoing edges

* Improve allocations for compute_minor

* Use approximate bounding box for edge finding

* Transition aabb to use glam vecs

* Make find vertecies use 64 bit again this is slower but less likely to cause issues

* Improve intersection candidate finding

* Remove loop check in bit vec iter

* Special case cubic line intersections

* Optimize grid rounding and add debug output

* Remove file write

* Remove faulty line intersection

* Fix grid rounding

* Improve robustness and cleanaup code

* Make elided lifetime explicit

* Fix tests

* Fix a boolean ops crash

* Add comment

---------

Co-authored-by: Keavon Chambers <keavon@keavon.com>
2025-08-21 23:15:36 +00:00
..
benches Upgrade to the Rust 2024 edition (#2367) 2025-03-12 17:29:12 -07:00
src Improve robustness and performance of the boolean operation algorithm (#2191) 2025-08-21 23:15:36 +00:00
visual-tests Path Bool library code cleanup (#2000) 2024-09-23 12:16:31 +02:00
.gitignore Path Bool library code cleanup (#2000) 2024-09-23 12:16:31 +02:00
Cargo.toml Improve robustness and performance of the boolean operation algorithm (#2191) 2025-08-21 23:15:36 +00:00
flake.nix Path Bool library code cleanup (#2000) 2024-09-23 12:16:31 +02:00
LICENSE-APACHE Add path-bool library (#1952) 2024-09-21 02:06:43 -07:00
LICENSE-MIT Add path-bool library (#1952) 2024-09-21 02:06:43 -07:00
NOTICE Path Bool library code cleanup (#2000) 2024-09-23 12:16:31 +02:00
README.md Path Bool library code cleanup (#2000) 2024-09-23 12:16:31 +02:00
shell.nix Update references to the latest tech stack plans 2025-07-29 15:17:41 -07:00

Path Bool

A Rust library for performing boolean operations on SVG paths.

Path Bool is a port of PathBool.js, providing low-level functionality for boolean operations on complex 2D paths. It handles paths with multiple subpaths, self-intersections, and different fill rules.

Features

  • Supports multiple boolean operations: Union, Intersection, Difference, Exclusion, Division, and Fracture.
  • Handles both NonZero and EvenOdd fill rules.
  • Works with paths containing lines, cubic Bézier curves, quadratic Bézier curves, and elliptical arcs.
  • Provides utilities for parsing and generating SVG path data.

Installation

Add this to your Cargo.toml:

[dependencies]
path-bool = "0.1.0"

Usage

Here's a basic example of performing an intersection operation on two paths:

use path_bool::{path_boolean, FillRule, PathBooleanOperation, path_from_path_data, path_to_path_data};

fn main() {
    let path_a = path_from_path_data("M 10 10 L 50 10 L 30 40 Z").unwrap();
    let path_b = path_from_path_data("M 20 30 L 60 30 L 60 50 L 20 50 Z").unwrap();

    let result = path_boolean(
        &path_a,
        FillRule::NonZero,
        &path_b,
        FillRule::NonZero,
        PathBooleanOperation::Intersection
    ).unwrap();

    let result_data = path_to_path_data(&result[0], 0.001);
    println!("Result: {}", result_data);
}

Algorithm

The boolean operations are implemented using a graph-based approach. After the parsing the input, self-intersecting cubic beziers curves are simplified. Then the intersection points between all edges are calculated. These are then turned into a graph representation where every intersection becomes a new vertex. We then apply edge contractions to remove vertices with a degree of 2 to compute the graph minor. At this stage, identical edges are deduplicated. Because we are ultimately interested in the faces of the graph to decide if they should be included in the final output, we then compute the dual graph in which the faces become vertices and vertices become the new faces. That dual structure is then used to determine which faces (dual vertices) should be included in the final output.

Development status

This project is a port of PathBool.js which is still in early stages of development. Contributions, bug reports, and feedback are welcome.

Future work includes:

  • Comprehensive test suite
  • Performance optimizations
  • Additional examples and documentation
  • Support for path builder tool features

License and acknowledgements

This library is a Rust port of PathBool.js by Adam Platkevič.

It is dual-licensed under the MIT License or Apache-2.0 License. You may opt to comply with either license.

Copyright © 2024 Adam Platkevič Copyright © 2024 Graphite Authors