diff --git a/src/input/triangulation.rs b/src/input/triangulation.rs index 563def0..3ed72bd 100644 --- a/src/input/triangulation.rs +++ b/src/input/triangulation.rs @@ -61,7 +61,11 @@ impl Triangulation { /// Epsilon is the minimum area a point should contribute to a polygon. #[cfg_attr(feature = "tracing", instrument(skip_all))] pub fn simplify(&mut self, epsilon: f32) { - self.inner = self.inner.simplify_vw_preserve(&epsilon); + self.inner.interiors_mut(|interiors| { + for interior in interiors { + *interior = interior.simplify_vw_preserve(&epsilon); + } + }); } #[cfg_attr(feature = "tracing", instrument(skip_all))] diff --git a/tests/triangulation.rs b/tests/triangulation.rs index 139cb23..6e9838a 100644 --- a/tests/triangulation.rs +++ b/tests/triangulation.rs @@ -161,3 +161,79 @@ fn is_in_mesh_overlapping_merged() { } } } + +#[test] +fn is_in_mesh_simplified() { + let mut triangulation = Triangulation::from_outer_edges(&[ + vec2(0.0, 0.0), + vec2(10.0, 0.0), + vec2(10.0, 10.0), + vec2(0.0, 10.0), + ]); + // adding a circle obstacle in the middle + let nb_points = 100; + let radius = 2.5; + triangulation.add_obstacle( + (0..nb_points) + .map(|i| { + let angle = i as f32 * std::f32::consts::TAU / nb_points as f32; + let (x, y) = angle.sin_cos(); + vec2(x, y) * radius + vec2(5.0, 5.0) + }) + .collect(), + ); + let polygons_before = triangulation.as_navmesh().polygons; + triangulation.simplify(0.1); + let mesh: Mesh = triangulation.as_navmesh(); + assert!(dbg!(polygons_before.len()) > dbg!(mesh.polygons.len())); + for i in 0..20 { + for j in 0..20 { + let point = vec2(i as f32 / 2.0, j as f32 / 2.0); + if point.distance(vec2(5.0, 5.0)) < radius { + assert!(!mesh.point_in_mesh(point)); + } else { + assert!(mesh.point_in_mesh(point)); + } + } + } +} + +#[test] +fn is_in_mesh_overlapping_simplified() { + let mut triangulation = Triangulation::from_outer_edges(&[ + vec2(0.0, 0.0), + vec2(10.0, 0.0), + vec2(10.0, 10.0), + vec2(0.0, 10.0), + ]); + // adding a circle obstacle in the middle + let nb_points = 1000; + let radius = 2.5; + triangulation.add_obstacle( + (0..nb_points) + .map(|i| { + let angle = i as f32 * std::f32::consts::TAU / nb_points as f32; + let (x, y) = angle.sin_cos(); + vec2(x, y) * radius + vec2(5.0, 5.0) + }) + .collect(), + ); + triangulation.add_obstacle(vec![ + vec2(2.5, 2.5), + vec2(2.5, 5.0), + vec2(5.0, 5.0), + vec2(5.0, 2.5), + ]); + + let mesh_before = triangulation.as_navmesh(); + triangulation.simplify(0.01); + let mesh: Mesh = triangulation.as_navmesh(); + assert!(dbg!(mesh_before.polygons.len()) > dbg!(mesh.polygons.len())); + let resolution = 5; + for i in 0..(10 * resolution) { + for j in 0..(10 * resolution) { + let point = vec2(i as f32 / resolution as f32, j as f32 / resolution as f32); + assert_eq!(mesh.point_in_mesh(point), mesh_before.point_in_mesh(point)); + } + } +}