Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update to mapbox/earcut v3.0.1 #19

Merged
merged 1 commit into from
Feb 18, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "earcut"
version = "0.4.2"
version = "0.4.3"
edition = "2021"
description = "A Rust port of the Earcut polygon triangulation library"
authors = ["Taku Fukada <[email protected]>", "MIERUNE Inc. <[email protected]>"]
Expand Down
46 changes: 39 additions & 7 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -287,8 +287,28 @@
}
}

self.queue
.sort_by(|(_a, ax), (_b, bx)| ax.partial_cmp(bx).unwrap_or(Ordering::Equal));
self.queue.sort_by(|(ai, ax), (bi, bx)| {
// compareXYSlope
match ax.partial_cmp(bx) {
Some(Ordering::Equal) => {}
Some(ordering) => return ordering,
None => return Ordering::Equal,

Check warning on line 295 in src/lib.rs

View check run for this annotation

Codecov / codecov/patch

src/lib.rs#L295

Added line #L295 was not covered by tests
}
// when the left-most point of 2 holes meet at a vertex, sort the holes counterclockwise so that when we find
// the bridge to the outer shell is always the point that they meet at.
let a = node!(self.nodes, ai);
let b = node!(self.nodes, bi);
match a.xy[1].partial_cmp(&b.xy[1]) {
Some(Ordering::Equal) => {}
Some(ordering) => return ordering,
None => return Ordering::Equal,

Check warning on line 304 in src/lib.rs

View check run for this annotation

Codecov / codecov/patch

src/lib.rs#L304

Added line #L304 was not covered by tests
};
let a_slope = (node!(self.nodes, a.next_i).xy[1] - a.xy[1])
/ (node!(self.nodes, a.next_i).xy[0] - a.xy[0]);
let b_slope = (node!(self.nodes, b.next_i).xy[1] - b.xy[1])
/ (node!(self.nodes, b.next_i).xy[0] - b.xy[0]);
a_slope.partial_cmp(&b_slope).unwrap_or(Ordering::Equal)
});

// process holes from left to right
for &(q, _) in &self.queue {
Expand Down Expand Up @@ -406,7 +426,7 @@
while !ptr::eq(p, a) {
let p_next = node!(nodes, p.next_i);
if (p.xy[0] >= x0 && p.xy[0] <= x1 && p.xy[1] >= y0 && p.xy[1] <= y1)
&& point_in_triangle(a.xy, b.xy, c.xy, p.xy)
&& point_in_triangle_except_first(a.xy, b.xy, c.xy, p.xy)
&& area(p_prev, p, p_next) >= T::zero()
{
return (false, a, c);
Expand Down Expand Up @@ -465,7 +485,7 @@
& (p.xy[1] >= xy_min[1])
& (p.xy[1] <= xy_max[1]))
&& (!ptr::eq(p, a) && !ptr::eq(p, c))
&& point_in_triangle(a.xy, b.xy, c.xy, p.xy)
&& point_in_triangle_except_first(a.xy, b.xy, c.xy, p.xy)
&& area(node!(nodes, p.prev_i), p, node!(nodes, p.next_i)) >= T::zero()
{
return (false, a, c);
Expand All @@ -477,7 +497,7 @@
& (n.xy[1] >= xy_min[1])
& (n.xy[1] <= xy_max[1]))
&& (!ptr::eq(n, a) && !ptr::eq(n, c))
&& point_in_triangle(a.xy, b.xy, c.xy, n.xy)
&& point_in_triangle_except_first(a.xy, b.xy, c.xy, n.xy)
&& area(node!(nodes, n.prev_i), n, node!(nodes, n.next_i)) >= T::zero()
{
return (false, a, c);
Expand All @@ -495,7 +515,7 @@
& (p.xy[1] >= xy_min[1])
& (p.xy[1] <= xy_max[1]))
&& (!ptr::eq(p, a) && !ptr::eq(p, c))
&& point_in_triangle(a.xy, b.xy, c.xy, p.xy)
&& point_in_triangle_except_first(a.xy, b.xy, c.xy, p.xy)
&& area(node!(nodes, p.prev_i), p, node!(nodes, p.next_i)) >= T::zero()
{
return (false, a, c);
Expand All @@ -513,7 +533,7 @@
& (n.xy[1] >= xy_min[1])
& (n.xy[1] <= xy_max[1]))
&& (!ptr::eq(n, a) && !ptr::eq(n, c))
&& point_in_triangle(a.xy, b.xy, c.xy, n.xy)
&& point_in_triangle_except_first(a.xy, b.xy, c.xy, n.xy)
&& area(node!(nodes, n.prev_i), n, node!(nodes, n.next_i)) >= T::zero()
{
return (false, a, c);
Expand Down Expand Up @@ -862,9 +882,16 @@

// find a segment intersected by a ray from the hole's leftmost point to the left;
// segment's endpoint with lesser x will be potential connection point
// unless they intersect at a vertex, then choose the vertex
let mut p = node!(nodes, p_i);
if equals(hole, p) {
return Some(p_i);
}
loop {
let p_next = node!(nodes, p.next_i);
if equals(hole, p_next) {
return Some(p.next_i);
}
if hole.xy[1] <= p.xy[1] && hole.xy[1] >= p_next.xy[1] && p_next.xy[1] != p.xy[1] {
let x = p.xy[0]
+ (hole.xy[1] - p.xy[1]) * (p_next.xy[0] - p.xy[0]) / (p_next.xy[1] - p.xy[1]);
Expand Down Expand Up @@ -1135,6 +1162,11 @@
&& ((b[0] - p[0]) * (c[1] - p[1]) >= (c[0] - p[0]) * (b[1] - p[1]))
}

#[allow(clippy::too_many_arguments)]
fn point_in_triangle_except_first<T: Float>(a: [T; 2], b: [T; 2], c: [T; 2], p: [T; 2]) -> bool {
!(a[0] == p[0] && a[1] == p[1]) && point_in_triangle(a, b, c, p)
}

/// signed area of a triangle
fn area<T: Float>(p: &Node<T>, q: &Node<T>, r: &Node<T>) -> T {
(q.xy[1] - p.xy[1]) * (r.xy[0] - q.xy[0]) - (q.xy[0] - p.xy[0]) * (r.xy[1] - q.xy[1])
Expand Down
35 changes: 30 additions & 5 deletions tests/fixture.rs
Original file line number Diff line number Diff line change
Expand Up @@ -75,12 +75,12 @@ fn fixture_water4() {

#[test]
fn fixture_water_huge1() {
test_fixture("water-huge", 5177, 0.0011);
test_fixture("water-huge", 5176, 0.0011);
}

#[test]
fn fixture_water_huge2() {
test_fixture("water-huge2", 4462, 0.0028);
test_fixture("water-huge2", 4462, 0.004);
}

#[test]
Expand Down Expand Up @@ -148,6 +148,31 @@ fn fixture_touching_holes() {
test_fixture("touching-holes", 57, 0.0);
}

#[test]
fn fixture_touching_holes2() {
test_fixture("touching-holes2", 10, 0.0);
}

#[test]
fn fixture_touching_holes3() {
test_fixture("touching-holes3", 82, 0.0);
}

#[test]
fn fixture_touching_holes4() {
test_fixture("touching-holes4", 55, 0.0);
}

#[test]
fn fixture_touching_holes5() {
test_fixture("touching-holes5", 133, 0.0);
}

#[test]
fn fixture_touching_holes6() {
test_fixture("touching-holes6", 3098, 0.0);
}

#[test]
fn fixture_hole_touching_outer() {
test_fixture("hole-touching-outer", 77, 0.0);
Expand Down Expand Up @@ -200,12 +225,12 @@ fn fixture_issue107() {

#[test]
fn fixture_issue111() {
test_fixture("issue111", 19, 0.0);
test_fixture("issue111", 18, 0.0);
}

#[test]
fn fixture_collinear_boxy() {
test_fixture("boxy", 57, 0.0);
test_fixture("boxy", 58, 0.0);
}

#[test]
Expand Down Expand Up @@ -235,7 +260,7 @@ fn fixture_touching3() {

#[test]
fn fixture_touching4() {
test_fixture("touching4", 20, 0.0);
test_fixture("touching4", 19, 0.0);
}

#[test]
Expand Down
1 change: 1 addition & 0 deletions tests/fixtures/touching-holes2.json
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
[[[0,0],[20,0],[20,25],[0,25],[0,0]],[[3,3],[2,12],[9,15],[3,3]],[[9,21],[2,12],[7,22],[9,21]]]
1 change: 1 addition & 0 deletions tests/fixtures/touching-holes3.json
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
[[[0,0],[20,0],[20,25],[0,25],[0,0]],[[2,12],[4,23],[5,23],[2,12]],[[2,12],[6,23],[7,23],[2,12]],[[2,12],[8,23],[9,23],[2,12]],[[2,12],[10,23],[11,23],[2,12]],[[2,12],[12,23],[13,23],[2,12]],[[2,12],[14,23],[15,23],[2,12]],[[2,12],[16,23],[17,23],[2,12]],[[2,12],[18,23],[18,22],[2,12]],[[2,12],[18,21],[18,20],[2,12]],[[2,12],[18,19],[18,18],[2,12]],[[2,12],[18,17],[18,16],[2,12]],[[2,12],[18,15],[18,14],[2,12]],[[2,12],[18,13],[18,12],[2,12]],[[2,12],[18,11],[18,10],[2,12]],[[2,12],[18,9],[18,8],[2,12]],[[2,12],[18,7],[18,6],[2,12]],[[2,12],[18,5],[18,4],[2,12]],[[2,12],[18,3],[18,2],[2,12]],[[2,12],[18,1],[17,1],[2,12]],[[2,12],[16,1],[15,1],[2,12]],[[2,12],[14,1],[13,1],[2,12]],[[2,12],[12,1],[11,1],[2,12]],[[2,12],[10,1],[9,1],[2,12]],[[2,12],[8,1],[7,1],[2,12]],[[2,12],[6,1],[5,1],[2,12]],[[2,12],[4,1],[3,1],[2,12]]]
1 change: 1 addition & 0 deletions tests/fixtures/touching-holes4.json
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
[[[-20,0],[20,0],[20,25],[-20,25],[-20,0]],[[2,12],[-1,23],[0,23],[2,12]],[[2,12],[-3,23],[-2,23],[2,12]],[[2,12],[-5,23],[-4,23],[2,12]],[[2,12],[-7,23],[-6,23],[2,12]],[[2,12],[-9,23],[-8,23],[2,12]],[[2,12],[-11,23],[-10,23],[2,12]],[[2,12],[-13,23],[-12,23],[2,12]],[[2,12],[-14,22],[-14,23],[2,12]],[[2,12],[-14,20],[-14,21],[2,12]],[[2,12],[-14,18],[-14,19],[2,12]],[[2,12],[-14,16],[-14,17],[2,12]],[[2,12],[-14,14],[-14,15],[2,12]],[[2,12],[-14,12],[-14,13],[2,12]],[[2,12],[-14,10],[-14,11],[2,12]],[[2,12],[-14,8],[-14,9],[2,12]],[[2,12],[-14,6],[-14,7],[2,12]],[[2,12],[-14,4],[-14,5],[2,12]],[[2,12],[-14,2],[-14,3],[2,12]],[[2,12],[-13,1],[-14,1],[2,12]],[[2,12],[-11,1],[-12,1],[2,12]],[[2,12],[-9,1],[-10,1],[2,12]],[[2,12],[-7,1],[-8,1],[2,12]],[[2,12],[-5,1],[-6,1],[2,12]],[[2,12],[-3,1],[-4,1],[2,12]],[[2,12],[-1,1],[-2,1],[2,12]],[[2,12],[1,1],[0,1],[2,12]]]
1 change: 1 addition & 0 deletions tests/fixtures/touching-holes5.json
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
[[[-20,0],[20,0],[20,25],[-20,25],[-20,0]],[[2,12],[4,23],[5,23],[2,12]],[[2,12],[6,23],[7,23],[2,12]],[[2,12],[8,23],[9,23],[2,12]],[[2,12],[10,23],[11,23],[2,12]],[[2,12],[12,23],[13,23],[2,12]],[[2,12],[14,23],[15,23],[2,12]],[[2,12],[16,23],[17,23],[2,12]],[[2,12],[18,23],[18,22],[2,12]],[[2,12],[18,21],[18,20],[2,12]],[[2,12],[18,19],[18,18],[2,12]],[[2,12],[18,17],[18,16],[2,12]],[[2,12],[18,15],[18,14],[2,12]],[[2,12],[18,13],[18,12],[2,12]],[[2,12],[18,11],[18,10],[2,12]],[[2,12],[18,9],[18,8],[2,12]],[[2,12],[18,7],[18,6],[2,12]],[[2,12],[18,5],[18,4],[2,12]],[[2,12],[18,3],[18,2],[2,12]],[[2,12],[18,1],[17,1],[2,12]],[[2,12],[16,1],[15,1],[2,12]],[[2,12],[14,1],[13,1],[2,12]],[[2,12],[12,1],[11,1],[2,12]],[[2,12],[10,1],[9,1],[2,12]],[[2,12],[8,1],[7,1],[2,12]],[[2,12],[6,1],[5,1],[2,12]],[[2,12],[4,1],[3,1],[2,12]],[[2,12],[-1,23],[0,23],[2,12]],[[2,12],[-3,23],[-2,23],[2,12]],[[2,12],[-5,23],[-4,23],[2,12]],[[2,12],[-7,23],[-6,23],[2,12]],[[2,12],[-9,23],[-8,23],[2,12]],[[2,12],[-11,23],[-10,23],[2,12]],[[2,12],[-13,23],[-12,23],[2,12]],[[2,12],[-14,22],[-14,23],[2,12]],[[2,12],[-14,20],[-14,21],[2,12]],[[2,12],[-14,18],[-14,19],[2,12]],[[2,12],[-14,16],[-14,17],[2,12]],[[2,12],[-14,14],[-14,15],[2,12]],[[2,12],[-14,12],[-14,13],[2,12]],[[2,12],[-14,10],[-14,11],[2,12]],[[2,12],[-14,8],[-14,9],[2,12]],[[2,12],[-14,6],[-14,7],[2,12]],[[2,12],[-14,4],[-14,5],[2,12]],[[2,12],[-14,2],[-14,3],[2,12]],[[2,12],[-13,1],[-14,1],[2,12]],[[2,12],[-11,1],[-12,1],[2,12]],[[2,12],[-9,1],[-10,1],[2,12]],[[2,12],[-7,1],[-8,1],[2,12]],[[2,12],[-5,1],[-6,1],[2,12]],[[2,12],[-3,1],[-4,1],[2,12]],[[2,12],[-1,1],[-2,1],[2,12]],[[2,12],[1,1],[0,1],[2,12]]]
1 change: 1 addition & 0 deletions tests/fixtures/touching-holes6.json

Large diffs are not rendered by default.