i_overlay/
lib.rs

1//! # iOverlay
2//!
3//! The `iOverlay` library provides high-performance boolean operations on polygons, including union, intersection, difference, and xor. It is designed for applications that require precise polygon operations, such as computer graphics, CAD systems, and geographical information systems (GIS). By supporting both integer (i32) and floating-point (f32, f64) APIs, iOverlay offers flexibility and precision across diverse use cases.
4//!
5//! ## Features
6//! - **Boolean Operations**: union, intersection, difference, and exclusion.
7//! - **String Line Operations**: clip and slice.
8//! - **Polygons**: with holes, self-intersections, and multiple contours.
9//! - **Simplification**: removes degenerate vertices and merges collinear edges.
10//! - **Fill Rules**: even-odd, non-zero, positive and negative.
11//! - **Data Types**: Supports i32, f32, and f64 APIs.
12//!
13//! ## Simple Example
14//! ![Simple Example](https://raw.githubusercontent.com/iShape-Rust/iOverlay/main/readme/example_union.svg)
15//! Here's an example of performing a union operation between two polygons:
16//!
17//! ```rust
18//!use i_overlay::core::fill_rule::FillRule;
19//!use i_overlay::core::overlay_rule::OverlayRule;
20//!use i_overlay::float::single::SingleFloatOverlay;
21//!
22//! // Define the subject "O"
23//!let subj = [
24//!    // main contour
25//!    vec![
26//!         [1.0, 0.0],
27//!         [1.0, 5.0],
28//!         [4.0, 5.0],
29//!         [4.0, 0.0], // the contour is auto closed!
30//!    ],
31//!    // hole contour
32//!    vec![
33//!         [2.0, 1.0],
34//!         [3.0, 1.0],
35//!         [3.0, 4.0],
36//!         [2.0, 4.0], // the contour is auto closed!
37//!    ],
38//!];
39//!
40//! // Define the clip "-"
41//!let clip = [
42//!    // main contour
43//!    [0.0, 2.0],
44//!    [5.0, 2.0],
45//!    [5.0, 3.0],
46//!    [0.0, 3.0], // the contour is auto closed!
47//!];
48//!
49//!let result = subj.overlay(&clip, OverlayRule::Union, FillRule::EvenOdd);
50//!
51//!println!("result: {:?}", result);
52//! ```
53//! The result is a vec of shapes:
54//! ```text
55//! [
56//!     // first shape
57//!     [
58//!         // main contour (clockwise order)
59//!         [
60//!             [0.0, 2.0], [0.0, 3.0], [1.0, 3.0], [1.0, 5.0], [4.0, 5.0], [4.0, 3.0], [5.0, 3.0], [5.0, 2.0], [4.0, 2.0], [4.0, 0.0], [1.0, 0.0], [1.0, 2.0]
61//!         ],
62//!         // first hole (counterclockwise order)
63//!         [
64//!             [2.0, 2.0], [2.0, 1.0], [3.0, 1.0], [3.0, 2.0]
65//!         ],
66//!         // second hole (counterclockwise order)
67//!         [
68//!             [2.0, 4.0], [2.0, 3.0], [3.0, 3.0], [3.0, 4.0]
69//!         ]
70//!     ]
71//!     // ... other shapes if present
72//! ]
73//! ```
74//! The `overlay` function returns a `Vec<Shapes>`:
75//!
76//! - `Vec<Shape>`: A collection of shapes.
77//! - `Shape`: Represents a shape made up of:
78//!   - `Vec<Contour>`: A list of contours.
79//!   - The first contour is the outer boundary (clockwise), and subsequent contours represent holes (counterclockwise).
80//! - `Contour`: A sequence of points (`Vec<P: FloatPointCompatible>`) forming a closed contour.
81//!
82//! **Note**: Outer boundary contours have a clockwise order, and holes have a counterclockwise order. [More information](https://ishape-rust.github.io/iShape-js/overlay/contours/contours.html) about contours.
83//! ## Using a Custom Point Type
84//!
85//! `iOverlay` allows users to define custom point types, as long as they implement the `FloatPointCompatible` trait.
86//!
87//! Here's an example:
88//!
89//!```rust
90//! use i_float::float::compatible::FloatPointCompatible;
91//! use i_overlay::core::fill_rule::FillRule;
92//! use i_overlay::core::overlay_rule::OverlayRule;
93//! use i_overlay::float::single::SingleFloatOverlay;
94//!
95//! #[derive(Clone, Copy, Debug)]
96//! struct CustomPoint {
97//!     x: f32,
98//!     y: f32,
99//! }
100//!
101//! // Implement the `FloatPointCompatible` trait for CustomPoint
102//! impl FloatPointCompatible<f32> for CustomPoint {
103//!     fn from_xy(x: f32, y: f32) -> Self {
104//!         Self { x, y }
105//!     }
106//!
107//!     fn x(&self) -> f32 {
108//!         self.x
109//!     }
110//!
111//!     fn y(&self) -> f32 {
112//!         self.y
113//!     }
114//! }
115//!
116//! let subj = [
117//!     CustomPoint { x: 0.0, y: 0.0 },
118//!     CustomPoint { x: 0.0, y: 3.0 },
119//!     CustomPoint { x: 3.0, y: 3.0 },
120//!     CustomPoint { x: 3.0, y: 0.0 },
121//! ];
122//!
123//! let clip = [
124//!     CustomPoint { x: 1.0, y: 1.0 },
125//!     CustomPoint { x: 1.0, y: 2.0 },
126//!     CustomPoint { x: 2.0, y: 2.0 },
127//!     CustomPoint { x: 2.0, y: 1.0 },
128//! ];
129//!
130//! let result = subj.overlay(&clip, OverlayRule::Difference, FillRule::EvenOdd);
131//!
132//! println!("result: {:?}", result);
133//! ```
134//!
135//! ## Slicing a Polygon with a Polyline
136//! ![Slicing Example](https://raw.githubusercontent.com/iShape-Rust/iOverlay/main/readme/example_slice.svg)
137//!
138//!```rust
139//! use i_overlay::core::fill_rule::FillRule;
140//! use i_overlay::float::single::SingleFloatOverlay;
141//! use i_overlay::float::slice::FloatSlice;
142//!
143//! let polygon = [
144//!     [1.0, 1.0],
145//!     [1.0, 4.0],
146//!     [4.0, 4.0],
147//!     [4.0, 1.0],
148//! ];
149//!
150//! let polyline = [
151//!     [3.0, 5.0],
152//!     [2.0, 2.0],
153//!     [3.0, 3.0],
154//!     [2.0, 0.0],
155//! ];
156//!
157//! let result = polygon.slice_by(&polyline, FillRule::NonZero);
158//!
159//! println!("result: {:?}", result);
160//! ```
161//! ## Clipping a Polyline by a Polygon
162//! ![Clip Example](https://raw.githubusercontent.com/iShape-Rust/iOverlay/main/readme/example_clip.svg)
163//!
164//!```rust
165//! use i_overlay::core::fill_rule::FillRule;
166//! use i_overlay::float::clip::FloatClip;
167//! use i_overlay::float::single::SingleFloatOverlay;
168//! use i_overlay::string::clip::ClipRule;
169//!
170//! let polyline = [
171//!     [3.0, 5.0],
172//!     [2.0, 2.0],
173//!     [3.0, 3.0],
174//!     [2.0, 0.0],
175//! ];
176//!
177//! let polygon = [
178//!     [1.0, 1.0],
179//!     [1.0, 4.0],
180//!     [4.0, 4.0],
181//!     [4.0, 1.0],
182//! ];
183//!
184//! let clip_rule = ClipRule { invert: false, boundary_included: false };
185//! let result = polyline.clip_by(&polygon, FillRule::NonZero, clip_rule);
186//!
187//! println!("result: {:?}", result);
188//! ```
189
190
191pub mod mesh;
192pub mod fill;
193pub mod core;
194pub mod vector;
195pub mod float;
196pub mod string;
197pub mod segm;
198
199pub(crate) mod split;
200pub(crate) mod bind;
201pub(crate) mod geom;
202pub(crate) mod util;
203
204
205pub use i_float;
206pub use i_shape;