diff --git a/topola-egui/src/display.rs b/topola-egui/src/display.rs index 9ebd53d..437ef1c 100644 --- a/topola-egui/src/display.rs +++ b/topola-egui/src/display.rs @@ -287,7 +287,9 @@ impl Display { ) { for layer in 0..*workspace.navmesher_board.board().layout().layer_count() { if workspace.appearance_panel.visible[layer] { - for navmesh in workspace.navmesher_board.navmesher().layers()[layer].navmeshes() { + for navmesh in + workspace.navmesher_board.navmesher().layer_navmeshers()[layer].navmeshes() + { for edge_geom in navmesh .triangulation() .rtreed_dcel() diff --git a/topola/Cargo.toml b/topola/Cargo.toml index 5dfe80f..690cf97 100644 --- a/topola/Cargo.toml +++ b/topola/Cargo.toml @@ -10,7 +10,7 @@ edition = "2024" [dependencies] bimap = "0.6" -dearcut = { version = "0.3", features = ["undoredo"] } +dearcut = { version = "0.3", features = ["serde", "undoredo"] } derive-getters.workspace = true derive_more.workspace = true rstar = "0.12" diff --git a/topola/src/navmesher.rs b/topola/src/navmesher.rs index 48aa325..af56580 100644 --- a/topola/src/navmesher.rs +++ b/topola/src/navmesher.rs @@ -2,7 +2,7 @@ // // SPDX-License-Identifier: MIT OR Apache-2.0 -use dearcut::RecordingTriangulator; +use dearcut::{RecordingTriangulator, VertexId}; use derive_getters::Getters; use derive_more::Constructor; use serde::{Deserialize, Serialize}; @@ -16,12 +16,12 @@ use crate::{ #[derive( Clone, Constructor, Copy, Debug, Deserialize, Eq, Ord, PartialEq, PartialOrd, Serialize, )] -pub struct ObstacleId { +pub struct MultiObstacleId { layer: usize, index: usize, } -impl ObstacleId { +impl MultiObstacleId { /// Layer of the obstacle. #[inline] pub fn layer(self) -> usize { @@ -35,6 +35,20 @@ impl ObstacleId { } } +#[derive(Clone, Constructor, Debug, Deserialize, Eq, Ord, PartialEq, PartialOrd, Serialize)] +pub struct MultiVertexId { + layer: usize, + indices: Vec, +} + +impl MultiVertexId { + /// Layer of the obstacle. + #[inline] + pub fn layer(self) -> usize { + self.layer + } +} + #[derive(Clone, Debug, Getters)] pub struct LayerNavmesher { boundary: Vec>, @@ -51,12 +65,15 @@ impl LayerNavmesher { } } - pub fn insert_obstacle(&mut self, polygon: impl IntoIterator>) -> usize { + pub fn insert_multiobstacle( + &mut self, + polygon: impl IntoIterator>, + ) -> usize { let polygon: Vec> = polygon.into_iter().collect(); let mut index = 0; for i in 0..self.navmeshes.len() { - index = self.navmeshes[i].insert_polygon_and_rebuild( + index = self.navmeshes[i].insert_obstacle_and_rebuild( Self::inflate_polygon(polygon.clone(), self.inflation_factors[i]) .into_iter() .map(Into::into), @@ -98,11 +115,28 @@ impl LayerNavmesher { Vector2::new(rx as i64, ry as i64) }) } + + pub fn insert_free_multivertex_in_multiobstacle( + &mut self, + multiobstacle_index: usize, + position: Vector2, + ) -> Vec { + let mut vertices = Vec::new(); + + for navmesh in &mut self.navmeshes { + vertices.push( + navmesh + .insert_free_vertex_in_obstacle(multiobstacle_index, [position.x, position.y]), + ); + } + + vertices + } } #[derive(Clone, Debug, Getters)] pub struct Navmesher { - layers: Vec, + layer_navmeshers: Vec, } impl Navmesher { @@ -110,18 +144,33 @@ impl Navmesher { let boundary: Vec> = boundary.into_iter().collect(); Self { - layers: std::iter::repeat_with(|| LayerNavmesher::new(boundary.clone())) + layer_navmeshers: std::iter::repeat_with(|| LayerNavmesher::new(boundary.clone())) .take(layer_count) .collect(), } } - pub fn insert_obstacle( + pub fn insert_multiobstacle( &mut self, layer: usize, - polygon: impl IntoIterator>, - ) -> ObstacleId { - ObstacleId::new(layer, self.layers[layer].insert_obstacle(polygon)) + multiobstacle: impl IntoIterator>, + ) -> MultiObstacleId { + MultiObstacleId::new( + layer, + self.layer_navmeshers[layer].insert_multiobstacle(multiobstacle), + ) + } + + pub fn insert_free_multivertex_in_multiobstacle( + &mut self, + multiobstacle_id: MultiObstacleId, + position: Vector2, + ) -> MultiVertexId { + MultiVertexId { + layer: multiobstacle_id.layer, + indices: self.layer_navmeshers[multiobstacle_id.layer] + .insert_free_multivertex_in_multiobstacle(multiobstacle_id.index, position), + } } } @@ -130,9 +179,9 @@ pub struct NavmesherBoard { navmesher: Navmesher, board: Board, - joint_obstacles: Recorder>, - segment_obstacles: Recorder>, - polygon_obstacles: Recorder>, + joint_multiobstacles: Recorder>, + segment_multiobstacles: Recorder>, + polygon_multiobstacles: Recorder>, } impl NavmesherBoard { @@ -148,23 +197,23 @@ impl NavmesherBoard { ), board, - joint_obstacles: Recorder::new(Vec::new()), - segment_obstacles: Recorder::new(Vec::new()), - polygon_obstacles: Recorder::new(Vec::new()), + joint_multiobstacles: Recorder::new(Vec::new()), + segment_multiobstacles: Recorder::new(Vec::new()), + polygon_multiobstacles: Recorder::new(Vec::new()), }; for (i, joint) in this.board.layout().joints().collection() { - this.joint_obstacles.insert( + this.joint_multiobstacles.insert( i, this.navmesher - .insert_obstacle(joint.layer, Self::joint_bounding_octagon(*joint)), + .insert_multiobstacle(joint.layer, Self::joint_bounding_octagon(*joint)), ); } for (i, segment) in this.board.layout().segments().collection() { - this.segment_obstacles.insert( + this.segment_multiobstacles.insert( i, - this.navmesher.insert_obstacle( + this.navmesher.insert_multiobstacle( segment.layer, this.segment_bounding_rectangle(SegmentId::new(i), *segment), ), @@ -172,10 +221,10 @@ impl NavmesherBoard { } for (i, polygon) in this.board.layout().polygons().collection() { - this.polygon_obstacles.insert( + this.polygon_multiobstacles.insert( i, this.navmesher - .insert_obstacle(polygon.layer, polygon.vertices.clone()), + .insert_multiobstacle(polygon.layer, polygon.vertices.clone()), ); } @@ -184,10 +233,10 @@ impl NavmesherBoard { pub fn insert_joint(&mut self, joint: Joint) -> JointId { let joint_id = self.board.add_joint(joint); - self.joint_obstacles.insert( + self.joint_multiobstacles.insert( joint_id.id(), self.navmesher - .insert_obstacle(joint.layer, Self::joint_bounding_octagon(joint)), + .insert_multiobstacle(joint.layer, Self::joint_bounding_octagon(joint)), ); joint_id @@ -212,9 +261,9 @@ impl NavmesherBoard { pub fn insert_segment(&mut self, segment: Segment) -> SegmentId { let segment_id = self.board.add_segment(segment); - self.segment_obstacles.insert( + self.segment_multiobstacles.insert( segment_id.id(), - self.navmesher.insert_obstacle( + self.navmesher.insert_multiobstacle( segment.layer, self.segment_bounding_rectangle(segment_id, segment), ), @@ -245,10 +294,10 @@ impl NavmesherBoard { pub fn insert_polygon(&mut self, polygon: Polygon) -> PolygonId { let polygon_id = self.board.add_polygon(polygon.clone()); - self.polygon_obstacles.insert( + self.polygon_multiobstacles.insert( polygon_id.id(), self.navmesher - .insert_obstacle(polygon.layer, polygon.vertices), + .insert_multiobstacle(polygon.layer, polygon.vertices), ); polygon_id