| Crates.io | i_triangle |
| lib.rs | i_triangle |
| version | 0.39.1 |
| created_at | 2023-10-29 17:49:09.416777+00 |
| updated_at | 2026-01-19 18:57:02.530678+00 |
| description | Polygon Triangulation Library: Efficient Delaunay Triangulation for Complex Shapes. |
| homepage | |
| repository | https://github.com/iShape-Rust/iTriangle |
| max_upload_size | |
| id | 1017654 |
| size | 2,153,613 |
iTriangle is a high-performance 2D polygon triangulation library for Rust. It solves robust triangulation for real-world, messy input (holes, self-intersections, mixed winding) and is built for GIS/CAD, simulation, and rendering pipelines that need deterministic results.
For detailed performance benchmarks, check out the Performance Comparison
flowchart TD
A[Input contours] --> B[Normalize and fix self-intersections]
B --> C[Sweep-line triangulation]
C --> D[Raw triangulation]
D -->|Delaunay| E[Delaunay triangulation]
D --> I[Triangles and indices]
E -->|Tessellation| F[Adaptive refinement]
F --> E
E --> G[Convex decomposition]
E --> H[Centroid net]
E --> I
Add to your Cargo.toml:
[dependencies]
i_triangle = "0.36"
Minimal example:
use i_triangle::float::triangulatable::Triangulatable;
let contour = vec![
[0.0, 0.0],
[10.0, 0.0],
[10.0, 10.0],
[0.0, 10.0],
];
let triangulation = vec![contour].triangulate().to_triangulation::<u16>();
println!("triangles: {}", triangulation.indices.len() / 3);
use i_triangle::float::triangulatable::Triangulatable;
use i_triangle::float::triangulation::Triangulation;
let shape = vec![
vec![
// body
[0.0, 20.0], // 0
[-10.0, 8.0], // 1
[-7.0, 6.0], // 2
[-6.0, 2.0], // 3
[-8.0, -2.0], // 4
[-13.0, -4.0], // 5
[-16.0, -3.0], // 6
[-18.0, 0.0], // 7
[-25.0, -7.0], // 8
[-14.0, -15.0], // 9
[0.0, -18.0], // 10
[14.0, -15.0], // 11
[26.0, -7.0], // 12
[17.0, 1.0], // 13
[13.0, -1.0], // 14
[9.0, 1.0], // 15
[7.0, 6.0], // 16
[8.0, 10.0], // 17
],
vec![
// hole
[2.0, 0.0], // 0
[5.0, -2.0], // 1
[7.0, -5.0], // 2
[5.0, -9.0], // 3
[2.0, -11.0], // 4
[-2.0, -9.0], // 5
[-4.0, -5.0], // 6
[-2.0, -2.0], // 7
],
];
let triangulation = shape.triangulate().to_triangulation::<u16>();
println!("points: {:?}", triangulation.points);
println!("indices: {:?}", triangulation.indices);
let delaunay_triangulation: Triangulation<[f64; 2], u16> =
shape.triangulate().into_delaunay().to_triangulation();
println!("points: {:?}", delaunay_triangulation.points);
println!("indices: {:?}", delaunay_triangulation.indices);
let convex_polygons = shape.triangulate().into_delaunay().to_convex_polygons();
println!("convex polygons: {:?}", convex_polygons);
let tessellation: Triangulation<[f64; 2], u16> = shape
.triangulate()
.into_delaunay()
.refine_with_circumcenters_by_obtuse_angle(0.0)
.to_triangulation();
println!("points: {:?}", tessellation.points);
println!("indices: {:?}", tessellation.indices);
let centroids = shape
.triangulate()
.into_delaunay()
.refine_with_circumcenters_by_obtuse_angle(0.0)
.to_centroid_net(0.0);
println!("centroids: {:?}", centroids);
💡 Output: Triangle indices and vertices, where all triangles oriented in a counter-clockwise direction.
If you need to triangulate many shapes, it is more efficient to use Triangulator.
let contours = random_contours(100);
let mut triangulator = Triangulator::<u32>::default();
// Enable Delaunay refinement
triangulator.delaunay(true);
// Use fast Earcut solver for contours with ≤ 64 points
triangulator.earcut(true);
let mut triangulation = Triangulation::with_capacity(100);
for contour in contours.iter() {
// Triangulate using self-intersection resolver
triangulator.triangulate_into(contour, &mut triangulation);
println!("points: {:?}", triangulation.points);
println!("indices: {:?}", triangulation.indices);
}
Benchmarks and interactive demos are available here:
| Delaunay | Convex Polygons | Steiner Points |
|---|---|---|
| Tessellation | Centroid Net | |
|---|---|---|
See CONTRIBUTING.md for development setup, tests, and PR guidelines.
Licensed under either of: