Skip to content

Commit 4bad576

Browse files
committed
fix: self-intersections for charshape
1 parent c92c729 commit 4bad576

File tree

3 files changed

+42
-26
lines changed

3 files changed

+42
-26
lines changed

Cargo.lock

Lines changed: 20 additions & 20 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,4 +14,4 @@ hashbrown = "0.15.5"
1414
pyo3 = "0.25.0"
1515
rayon = "1.10.0"
1616
rstar = "0.12.2"
17-
spade = "2.14.0"
17+
spade = "2.15.0"

src/algorithms/charshape.rs

Lines changed: 21 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
use geo::{Coord, GeoFloat, LineString, Polygon};
22
use hashbrown::HashSet;
33
use spade::handles::{DirectedEdgeHandle, VertexHandle};
4-
use spade::{DelaunayTriangulation, Point2, SpadeNum, Triangulation};
4+
use spade::{CdtEdge, ConstrainedDelaunayTriangulation, Point2, SpadeNum, Triangulation};
55
use std::cmp::Ordering;
66
use std::collections::BinaryHeap;
77
use std::hash::Hash;
@@ -12,7 +12,7 @@ where
1212
T: SpadeNum,
1313
{
1414
score: T,
15-
edge: DirectedEdgeHandle<'a, Point2<T>, (), (), ()>,
15+
edge: DirectedEdgeHandle<'a, Point2<T>, (), CdtEdge<()>, ()>,
1616
}
1717

1818
// These impls give us a max-heap
@@ -37,7 +37,7 @@ impl<T: SpadeNum> PartialEq for CharScore<'_, T> {
3737
}
3838

3939
#[derive(Debug)]
40-
struct BoundaryNode<'a, T>(VertexHandle<'a, Point2<T>>);
40+
struct BoundaryNode<'a, T>(VertexHandle<'a, Point2<T>, (), CdtEdge<()>>);
4141

4242
impl<T> PartialEq for BoundaryNode<'_, T> {
4343
fn eq(&self, other: &BoundaryNode<T>) -> bool {
@@ -72,13 +72,29 @@ fn characteristic_shape<T>(orig: &Polygon<T>, eps: T, max_len: usize) -> Polygon
7272
where
7373
T: GeoFloat + SpadeNum,
7474
{
75+
// Number of unique vertices
76+
let orig_len = orig.exterior().0.len() - 1;
77+
7578
// Construct Delaunay triangulation
7679
let vertices = orig
7780
.exterior()
7881
.coords()
82+
.take(orig_len) // duplicate points are removed
7983
.map(|c| Point2::new(c.x, c.y))
8084
.collect::<Vec<_>>();
81-
let tri = DelaunayTriangulation::<Point2<T>>::bulk_load_stable(vertices).unwrap();
85+
86+
let edges = (0..orig_len - 1)
87+
.map(|i| {
88+
if i == 0 {
89+
[vertices.len() - 1, i]
90+
} else {
91+
[i, i + 1]
92+
}
93+
})
94+
.collect::<Vec<_>>();
95+
96+
let tri =
97+
ConstrainedDelaunayTriangulation::<Point2<T>>::bulk_load_cdt(vertices, edges).unwrap();
8298

8399
let boundary_edges = tri.convex_hull().map(|edge| edge.rev()).collect::<Vec<_>>();
84100
let mut boundary_nodes: HashSet<_> =
@@ -125,7 +141,7 @@ where
125141
}
126142

127143
fn recompute_boundary<'a, T>(
128-
edge: DirectedEdgeHandle<'a, Point2<T>, (), (), ()>,
144+
edge: DirectedEdgeHandle<'a, Point2<T>, (), CdtEdge<()>, ()>,
129145
pq: &mut BinaryHeap<CharScore<'a, T>>,
130146
) where
131147
T: GeoFloat + SpadeNum,

0 commit comments

Comments
 (0)