Skip to content

Commit

Permalink
Use [T; 2] as a vertex + some optimizations (#11)
Browse files Browse the repository at this point in the history
* perf

* no_std

* more

* improve

* improments

* benchmarks on readme
  • Loading branch information
ciscorn committed Apr 15, 2024
1 parent c782a9a commit e51bb5a
Show file tree
Hide file tree
Showing 7 changed files with 304 additions and 235 deletions.
4 changes: 2 additions & 2 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "earcut"
version = "0.3.6"
version = "0.4.0"
edition = "2021"
description = "A Rust port of the Earcut polygon triangulation library"
authors = ["Taku Fukada <naninunenor@gmail.com>", "MIERUNE Inc. <info@mierune.co.jp>"]
Expand All @@ -9,7 +9,7 @@ repository = "https://github.com/MIERUNE/earcut-rs"
categories = ["graphics", "science", "no-std"]

[dependencies]
num-traits = "0.2"
num-traits = { version = "0.2", no-default-features = true }

[dev-dependencies]
serde_json = { version = "1.0", features = ["float_roundtrip"] }
Expand Down
26 changes: 24 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,32 @@
A Rust port of the [mapbox/earcut](https://github.com/mapbox/earcut) polygon triangulation library, implemented from scratch with some reference to [donbright/earcutr](https://github.com/donbright/earcutr).

- Based on the latest earcut 2.2.4 release.
- Designed to avoid unnecessary memory allocations. You can reuse the internal buffer and the output index vector.
- (Experimental) An additional module, `utils3d`, can rotate polygons from 3D to 2D space before triangulation.
- Designed to avoid unnecessary memory allocations. You can reuse the internal buffer and the output index vector for multiple triangulations.
- (Experimental) An additional module, `utils3d`, can rotate 3D coplanar polygons into the 2D plane before triangulation.
- License: ISC

<p align="center">
<img src="./docs/image.png" width="300">
</p>


## Benchmarks

on Macbook Pro (M1 Pro)

| Polygon | earcut.hpp | earcut-rs (0.4.0) | earcutr (0.4.3) |
|----------------|-------------:|--------------:|-------------:|
| bad_hole | 3.574 µs/i | 4.630 µs/i | 4.415 µs/i |
| building | 397 ns/i | 197 ns/i | 604 ns/i |
| degenerate | 142 ns/i | 46 ns/i | 206 ns/i |
| dude | 5.061 µs/i | 6.516 µs/i | 8.096 µs/i |
| empty_square | 195 ns/i | 88 ns/i | 331 ns/i |
| water | 459.6 µs/i | 623.5 µs/i | 801.3 µs/i |
| water2 | 334.1 µs/i | 409.5 µs/i | 450.3 µs/i |
| water3 | 13.12 µs/i | 19.12 µs/i | 23.46 µs/i |
| water3b | 1.340 µs/i | 1.368 µs/i | 2.165 µs/i |
| water4 | 81.48 µs/i | 122.0 µs/i | 154.1 µs/i |
| water_huge | 6.906 ms/i | 11.01 ms/i | 10.90 ms/i |
| water_huge2 | 15.38 ms/i | 23.40 ms/i | 22.35 ms/i |

(Earcutr is not besed on the latest earcut.)
10 changes: 2 additions & 8 deletions benches/benchmark.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,20 +4,15 @@ use criterion::{criterion_group, criterion_main, Criterion};

use earcut::Earcut;

fn load_fixture(name: &str) -> (Vec<f64>, Vec<usize>) {
fn load_fixture(name: &str) -> (Vec<[f64; 2]>, Vec<usize>) {
// load JSON
type Coords = Vec<Vec<[f64; 2]>>;
let s = fs::read_to_string("./tests/fixtures/".to_string() + name + ".json").unwrap();
let expected = serde_json::from_str::<Coords>(&s).unwrap();

// prepare input
let num_holes = expected.len();
let data = expected
.clone()
.into_iter()
.flatten()
.flatten()
.collect::<Vec<_>>();
let data = expected.clone().into_iter().flatten().collect::<Vec<_>>();
let hole_indices: Vec<_> = expected
.iter()
.map(|x| x.len())
Expand Down Expand Up @@ -109,7 +104,6 @@ fn bench(c: &mut Criterion) {
let (data, hole_indices) = load_fixture("water-huge");
b.iter(|| {
earcut.earcut(data.iter().copied(), &hole_indices, &mut triangles);
assert_eq!(triangles.len(), 5177 * 3)
})
});

Expand Down
7 changes: 1 addition & 6 deletions examples/example.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,7 @@ fn load_fixture(name: &str, num_triangles: usize, expected_deviation: f64) {

// prepare input
let num_holes = expected.len();
let vertices = expected
.clone()
.into_iter()
.flatten()
.flatten()
.collect::<Vec<_>>();
let vertices = expected.clone().into_iter().flatten().collect::<Vec<_>>();
let hole_indices: Vec<_> = expected
.into_iter()
.map(|x| x.len() as u32)
Expand Down
Loading

0 comments on commit e51bb5a

Please sign in to comment.