mirror of
https://github.com/hannobraun/Fornjot
synced 2025-02-25 08:35:51 +00:00
Fix triangulation edge case
Triangular holes in a face were treated as part of the face.
This commit is contained in:
parent
bb61819550
commit
0b2bc8c1f8
@ -61,9 +61,13 @@ impl Polygon {
|
|||||||
|
|
||||||
pub fn contains_triangle(
|
pub fn contains_triangle(
|
||||||
&self,
|
&self,
|
||||||
[a, b, c]: [Point<2>; 3],
|
triangle: [impl Into<Point<2>>; 3],
|
||||||
debug_info: &mut DebugInfo,
|
debug_info: &mut DebugInfo,
|
||||||
) -> bool {
|
) -> bool {
|
||||||
|
let [a, b, c] = triangle.map(Into::into);
|
||||||
|
|
||||||
|
let mut might_be_hole = true;
|
||||||
|
|
||||||
for edge in [a, b, c, a].windows(2) {
|
for edge in [a, b, c, a].windows(2) {
|
||||||
// This can't panic, as we passed `2` to `windows`. It can be
|
// This can't panic, as we passed `2` to `windows`. It can be
|
||||||
// cleaned up a bit, once `array_windows` is stable.
|
// cleaned up a bit, once `array_windows` is stable.
|
||||||
@ -72,6 +76,13 @@ impl Polygon {
|
|||||||
let is_exterior_edge = self.contains_exterior_edge(edge);
|
let is_exterior_edge = self.contains_exterior_edge(edge);
|
||||||
let is_interior_edge = self.contains_interior_edge(edge);
|
let is_interior_edge = self.contains_interior_edge(edge);
|
||||||
|
|
||||||
|
// If the triangle edge is not an interior edge of the polygon, we
|
||||||
|
// can rule out that the triangle is identical with a hole in the
|
||||||
|
// polygon.
|
||||||
|
if !is_interior_edge {
|
||||||
|
might_be_hole = false;
|
||||||
|
}
|
||||||
|
|
||||||
// If the triangle edge is an edge of the face, we don't need to
|
// If the triangle edge is an edge of the face, we don't need to
|
||||||
// take a closer look.
|
// take a closer look.
|
||||||
if is_exterior_edge || is_interior_edge {
|
if is_exterior_edge || is_interior_edge {
|
||||||
@ -92,6 +103,12 @@ impl Polygon {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// We haven't rules out that the triangle is a polygon hole. Since we
|
||||||
|
// checked all its edges, this means we now know for certain that is is.
|
||||||
|
if might_be_hole {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
// If we didn't throw away the triangle up till now, this means all its
|
// If we didn't throw away the triangle up till now, this means all its
|
||||||
// edges are within the face.
|
// edges are within the face.
|
||||||
true
|
true
|
||||||
@ -208,6 +225,23 @@ mod tests {
|
|||||||
|
|
||||||
use super::Polygon;
|
use super::Polygon;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn contains_triangle_with_triangular_hole() {
|
||||||
|
let a = [0., 0.];
|
||||||
|
let b = [3., 0.];
|
||||||
|
let c = [0., 3.];
|
||||||
|
|
||||||
|
let d = [1., 1.];
|
||||||
|
let e = [2., 1.];
|
||||||
|
let f = [1., 2.];
|
||||||
|
|
||||||
|
let polygon = Polygon::new(Surface::x_y_plane())
|
||||||
|
.with_exterior(PolyChain::from([a, b, c]).close())
|
||||||
|
.with_interiors([PolyChain::from([d, e, f]).close()]);
|
||||||
|
|
||||||
|
assert!(!polygon.contains_triangle([d, e, f], &mut DebugInfo::new()));
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn contains_point_ray_hits_vertex_while_passing_outside() {
|
fn contains_point_ray_hits_vertex_while_passing_outside() {
|
||||||
let a = [0., 0.];
|
let a = [0., 0.];
|
||||||
|
Loading…
Reference in New Issue
Block a user