From abb6a6b266935a0681f13b25f6807c6c00666a56 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fran=C3=A7ois=20Mockers?= Date: Sat, 16 Nov 2024 22:26:39 +0100 Subject: [PATCH 1/3] update glam --- Cargo.toml | 4 ++-- examples/traced/Cargo.toml | 2 +- src/mesh_cleanup.rs | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index b41b946..e939ba2 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -23,9 +23,9 @@ serde = ["glam/serde", "bvh2d/serde", "dep:serde"] [dependencies] tracing = { version = "0.1", optional = true } hashbrown = { version = "0.14" } -glam = { version = "0.27", features = ["approx"] } +glam = { version = "0.29", features = ["approx"] } smallvec = { version = "1.13", features = ["union", "const_generics"] } -bvh2d = { version = "0.5", git = "https://github.com/mockersf/bvh2d" } +bvh2d = { version = "0.6", git = "https://github.com/mockersf/bvh2d" } serde = { version = "1.0", features = ["derive"], optional = true } spade = "=2.10" geo = "0.28.0" diff --git a/examples/traced/Cargo.toml b/examples/traced/Cargo.toml index 6ffbbd9..0c60bae 100644 --- a/examples/traced/Cargo.toml +++ b/examples/traced/Cargo.toml @@ -8,7 +8,7 @@ publish = false [dependencies] polyanya = { path = "../../", features = ["tracing"] } -glam = "0.27" +glam = "0.29" tracing-subscriber = "0.3" tracing-tracy = "0.10" tracing = "0.1" diff --git a/src/mesh_cleanup.rs b/src/mesh_cleanup.rs index b1869cf..3d7a5ed 100644 --- a/src/mesh_cleanup.rs +++ b/src/mesh_cleanup.rs @@ -30,7 +30,7 @@ impl Mesh { / vertices.len() as f32 + self.layers[p.layer() as usize].offset; let direction = center - vertex_coords; - let angle = Vec2::Y.angle_between(direction); + let angle = Vec2::Y.angle_to(direction); (angle * 100000.0) as i32 }); polygons.dedup_by_key(|p| *p); From b921f0535ad3eb3ad6cf8e8a5ccb42a4e54c715d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fran=C3=A7ois=20Mockers?= Date: Sat, 16 Nov 2024 22:27:03 +0100 Subject: [PATCH 2/3] update geo --- Cargo.toml | 3 +- benches/triangulation.rs | 31 ++++++++ src/input/triangulation.rs | 159 +++++++++++++------------------------ 3 files changed, 88 insertions(+), 105 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index e939ba2..ce9444b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -28,10 +28,9 @@ smallvec = { version = "1.13", features = ["union", "const_generics"] } bvh2d = { version = "0.6", git = "https://github.com/mockersf/bvh2d" } serde = { version = "1.0", features = ["derive"], optional = true } spade = "=2.10" -geo = "0.28.0" +geo = "0.29.0" log = "0.4" thiserror = "1" -i_overlay = "1.6" [dev-dependencies] criterion = "0.5" diff --git a/benches/triangulation.rs b/benches/triangulation.rs index 2e3aac1..ad7e9fe 100644 --- a/benches/triangulation.rs +++ b/benches/triangulation.rs @@ -2105,6 +2105,35 @@ fn triangulation_many_overlapping_simplified(c: &mut Criterion) { ); } +fn triangulation_many_overlapping_inflated(c: &mut Criterion) { + c.bench_function( + &"triangulation many overlapping (inflated)".to_string(), + |b| { + b.iter(|| { + let mut triangulation = random_with_many_obstacles(); + triangulation.set_agent_radius(0.1); + let mesh: Mesh = triangulation.as_navmesh(); + black_box(mesh); + }) + }, + ); +} + +fn triangulation_many_overlapping_simplified_inflated(c: &mut Criterion) { + c.bench_function( + &"triangulation many overlapping (simplified + inflated)".to_string(), + |b| { + b.iter(|| { + let mut triangulation = random_with_many_obstacles(); + triangulation.simplify(0.005); + triangulation.set_agent_radius(0.1); + let mesh: Mesh = triangulation.as_navmesh(); + black_box(mesh); + }) + }, + ); +} + criterion_group!( benches, triangulation, @@ -2114,5 +2143,7 @@ criterion_group!( triangulation_square_overlapping, triangulation_many_overlapping, triangulation_many_overlapping_simplified, + triangulation_many_overlapping_inflated, + triangulation_many_overlapping_simplified_inflated, ); criterion_main!(benches); diff --git a/src/input/triangulation.rs b/src/input/triangulation.rs index 8d89c43..ba59be0 100644 --- a/src/input/triangulation.rs +++ b/src/input/triangulation.rs @@ -600,14 +600,12 @@ mod inflate { use std::f32::consts::TAU; - use geo::{Coord, EuclideanDistance, Line, LineString, Polygon, SimplifyVwPreserve}; - use i_overlay::{ - core::{overlay_rule::OverlayRule, solver::Solver}, - i_float::f32_point::F32Point, + use geo::{ + BooleanOps, Coord, Distance, Euclidean, Line, LineString, Polygon, SimplifyVwPreserve, }; - fn segment_normal(start: &Coord, end: &Coord) -> Option { - let edge_length = end.euclidean_distance(start); + fn segment_normal(start: &Coord, end: &Coord) -> Option> { + let edge_length = Euclidean::distance(*end, *start); if edge_length == 0.0 { return None; } @@ -616,7 +614,7 @@ mod inflate { let x = -dy / edge_length; let y = dx / edge_length; - Some(F32Point::new(x, y)) + Some(Coord { x, y }) } pub trait Inflate { @@ -665,21 +663,22 @@ mod inflate { for line in lines { let rounded_line = round_line(&line, distance, arc_segments); - inflated_linestring = basic_union(inflated_linestring, rounded_line); + let from = Polygon::new(inflated_linestring, vec![]); + let with = Polygon::new(rounded_line, vec![]); + let union = from.union(&with); + inflated_linestring = union.0.into_iter().next().unwrap().into_inner().0; last = line.end; } if !linestring.is_closed() { let line = Line::new(last, linestring.0[0]); let rounded_line = round_line(&line, distance, arc_segments); - inflated_linestring = basic_union(inflated_linestring, rounded_line); + let from = Polygon::new(inflated_linestring, vec![]); + let with = Polygon::new(rounded_line, vec![]); + let union = from.union(&with); + inflated_linestring = union.0.into_iter().next().unwrap().into_inner().0; } - LineString( - inflated_linestring - .iter() - .map(|v| (v.x, v.y).into()) - .collect(), - ) + inflated_linestring } fn inflate_as_polygon( @@ -696,81 +695,81 @@ mod inflate { last = line.end; for line in lines { let rounded_line = round_line(&line, distance, arc_segments); + let from = Polygon::new(inflated_linestring, vec![]); + let with = Polygon::new(rounded_line, vec![]); + let union = from.union(&with); let hole; - (inflated_linestring, hole) = union(inflated_linestring, rounded_line); + (inflated_linestring, hole) = union.0.into_iter().next().unwrap().into_inner(); + if !hole.is_empty() { - holes.push(LineString(hole.iter().map(|v| (v.x, v.y).into()).collect())); + holes.extend(hole.into_iter()); } last = line.end; } if !linestring.is_closed() { let line = Line::new(last, linestring.0[0]); let rounded_line = round_line(&line, distance, arc_segments); + + let from = Polygon::new(inflated_linestring, vec![]); + let with = Polygon::new(rounded_line, vec![]); + let union = from.union(&with); + let hole; - (inflated_linestring, hole) = union(inflated_linestring, rounded_line); + (inflated_linestring, hole) = union.0.into_iter().next().unwrap().into_inner(); + if !hole.is_empty() { - holes.push(LineString(hole.iter().map(|v| (v.x, v.y).into()).collect())); + holes.extend(hole.into_iter()); } } - Polygon::new( - LineString( - inflated_linestring - .iter() - .map(|v| (v.x, v.y).into()) - .collect(), - ), - holes, - ) + Polygon::new(inflated_linestring, holes) } - fn round_line(line: &Line, distance: f32, arc_segments: u32) -> Vec { - let start = F32Point::new(line.start.x, line.start.y); - let end = F32Point::new(line.end.x, line.end.y); + fn round_line(line: &Line, distance: f32, arc_segments: u32) -> LineString { let Some(normal) = segment_normal(&line.start, &line.end) else { - return (0..(arc_segments * 2)) - .map(|i| { - let angle = i as f32 * TAU / (arc_segments * 2) as f32; - F32Point::new( - start.x + angle.cos() * distance, - start.y + angle.sin() * distance, - ) - }) - .collect(); + return LineString::new( + (0..(arc_segments * 2)) + .map(|i| { + let angle = i as f32 * TAU / (arc_segments * 2) as f32; + Coord { + x: line.start.x + angle.cos() * distance, + y: line.start.y + angle.sin() * distance, + } + }) + .collect(), + ); }; - let mut vertices = Vec::with_capacity((arc_segments as usize + 2) * 2); create_arc( &mut vertices, - &start, + &line.start, distance, - &(start - (normal * distance)), - &(start + (normal * distance)), + &(line.start - (normal * distance)), + &(line.start + (normal * distance)), arc_segments, true, ); create_arc( &mut vertices, - &end, + &line.end, distance, - &(end + (normal * distance)), - &(end - (normal * distance)), + &(line.end + (normal * distance)), + &(line.end - (normal * distance)), arc_segments, true, ); - vertices + LineString::new(vertices) } - // from https://github.com/w8r/polygon-offset/blob/77382ec02a4a505fe6c2c900fb67345b206961ed/src/offset.js#L139 fn create_arc( - vertices: &mut Vec, - center: &F32Point, + vertices: &mut Vec>, + center: &Coord, radius: f32, - start_vertex: &F32Point, - end_vertex: &F32Point, + start_vertex: &Coord, + end_vertex: &Coord, segment_count: u32, outwards: bool, ) { @@ -806,57 +805,11 @@ mod inflate { vertices.push(*start_vertex); for i in 1..segment_count { let angle = start_angle + segment_angle * (i as f32); - vertices.push(F32Point::new( - center.x + angle.cos() * radius, - center.y + angle.sin() * radius, - )); + vertices.push(Coord { + x: center.x + angle.cos() * radius, + y: center.y + angle.sin() * radius, + }); } vertices.push(*end_vertex); } - - fn basic_union(subj: Vec, clip: Vec) -> Vec { - let mut overlay = i_overlay::f32::overlay::F32Overlay::new(); - - overlay.add_path(subj, i_overlay::core::overlay::ShapeType::Subject); - overlay.add_path(clip, i_overlay::core::overlay::ShapeType::Clip); - - let graph = overlay.into_graph_with_solver( - i_overlay::core::fill_rule::FillRule::NonZero, - Solver { - strategy: i_overlay::core::solver::Strategy::List, - precision: i_overlay::core::solver::Precision::Auto, - multithreading: None, - }, - ); - let mut shapes = graph.extract_shapes(OverlayRule::Union); - - shapes.swap_remove(0).swap_remove(0) - } - - fn union(subj: Vec, clip: Vec) -> (Vec, Vec) { - let mut overlay = i_overlay::f32::overlay::F32Overlay::new(); - - overlay.add_path(subj, i_overlay::core::overlay::ShapeType::Subject); - overlay.add_path(clip, i_overlay::core::overlay::ShapeType::Clip); - - let graph = overlay.into_graph_with_solver( - i_overlay::core::fill_rule::FillRule::NonZero, - Solver { - strategy: i_overlay::core::solver::Strategy::List, - precision: i_overlay::core::solver::Precision::Auto, - multithreading: None, - }, - ); - let mut shapes = graph.extract_shapes(OverlayRule::Union); - - let mut res = shapes.swap_remove(0); - ( - res.swap_remove(0), - if res.is_empty() { - vec![] - } else { - res.swap_remove(0) - }, - ) - } } From c1016b82ab1c9c468c87f7e4c4fbe229be05cb82 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fran=C3=A7ois=20Mockers?= Date: Sat, 16 Nov 2024 22:29:56 +0100 Subject: [PATCH 3/3] clippy --- src/input/triangulation.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/input/triangulation.rs b/src/input/triangulation.rs index ba59be0..75d7921 100644 --- a/src/input/triangulation.rs +++ b/src/input/triangulation.rs @@ -719,7 +719,7 @@ mod inflate { (inflated_linestring, hole) = union.0.into_iter().next().unwrap().into_inner(); if !hole.is_empty() { - holes.extend(hole.into_iter()); + holes.extend(hole); } }