Add methods to add multivertices to navmesher

This commit is contained in:
Mikolaj Wielgus 2026-03-19 11:20:54 +01:00
parent 1b84eea06b
commit f9e6c1bdda
3 changed files with 82 additions and 31 deletions

View File

@ -287,7 +287,9 @@ impl Display {
) { ) {
for layer in 0..*workspace.navmesher_board.board().layout().layer_count() { for layer in 0..*workspace.navmesher_board.board().layout().layer_count() {
if workspace.appearance_panel.visible[layer] { 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 for edge_geom in navmesh
.triangulation() .triangulation()
.rtreed_dcel() .rtreed_dcel()

View File

@ -10,7 +10,7 @@ edition = "2024"
[dependencies] [dependencies]
bimap = "0.6" bimap = "0.6"
dearcut = { version = "0.3", features = ["undoredo"] } dearcut = { version = "0.3", features = ["serde", "undoredo"] }
derive-getters.workspace = true derive-getters.workspace = true
derive_more.workspace = true derive_more.workspace = true
rstar = "0.12" rstar = "0.12"

View File

@ -2,7 +2,7 @@
// //
// SPDX-License-Identifier: MIT OR Apache-2.0 // SPDX-License-Identifier: MIT OR Apache-2.0
use dearcut::RecordingTriangulator; use dearcut::{RecordingTriangulator, VertexId};
use derive_getters::Getters; use derive_getters::Getters;
use derive_more::Constructor; use derive_more::Constructor;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
@ -16,12 +16,12 @@ use crate::{
#[derive( #[derive(
Clone, Constructor, Copy, Debug, Deserialize, Eq, Ord, PartialEq, PartialOrd, Serialize, Clone, Constructor, Copy, Debug, Deserialize, Eq, Ord, PartialEq, PartialOrd, Serialize,
)] )]
pub struct ObstacleId { pub struct MultiObstacleId {
layer: usize, layer: usize,
index: usize, index: usize,
} }
impl ObstacleId { impl MultiObstacleId {
/// Layer of the obstacle. /// Layer of the obstacle.
#[inline] #[inline]
pub fn layer(self) -> usize { 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<VertexId>,
}
impl MultiVertexId {
/// Layer of the obstacle.
#[inline]
pub fn layer(self) -> usize {
self.layer
}
}
#[derive(Clone, Debug, Getters)] #[derive(Clone, Debug, Getters)]
pub struct LayerNavmesher { pub struct LayerNavmesher {
boundary: Vec<Vector2<i64>>, boundary: Vec<Vector2<i64>>,
@ -51,12 +65,15 @@ impl LayerNavmesher {
} }
} }
pub fn insert_obstacle(&mut self, polygon: impl IntoIterator<Item = Vector2<i64>>) -> usize { pub fn insert_multiobstacle(
&mut self,
polygon: impl IntoIterator<Item = Vector2<i64>>,
) -> usize {
let polygon: Vec<Vector2<i64>> = polygon.into_iter().collect(); let polygon: Vec<Vector2<i64>> = polygon.into_iter().collect();
let mut index = 0; let mut index = 0;
for i in 0..self.navmeshes.len() { 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]) Self::inflate_polygon(polygon.clone(), self.inflation_factors[i])
.into_iter() .into_iter()
.map(Into::into), .map(Into::into),
@ -98,11 +115,28 @@ impl LayerNavmesher {
Vector2::new(rx as i64, ry as i64) Vector2::new(rx as i64, ry as i64)
}) })
} }
pub fn insert_free_multivertex_in_multiobstacle(
&mut self,
multiobstacle_index: usize,
position: Vector2<i64>,
) -> Vec<VertexId> {
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)] #[derive(Clone, Debug, Getters)]
pub struct Navmesher { pub struct Navmesher {
layers: Vec<LayerNavmesher>, layer_navmeshers: Vec<LayerNavmesher>,
} }
impl Navmesher { impl Navmesher {
@ -110,18 +144,33 @@ impl Navmesher {
let boundary: Vec<Vector2<i64>> = boundary.into_iter().collect(); let boundary: Vec<Vector2<i64>> = boundary.into_iter().collect();
Self { Self {
layers: std::iter::repeat_with(|| LayerNavmesher::new(boundary.clone())) layer_navmeshers: std::iter::repeat_with(|| LayerNavmesher::new(boundary.clone()))
.take(layer_count) .take(layer_count)
.collect(), .collect(),
} }
} }
pub fn insert_obstacle( pub fn insert_multiobstacle(
&mut self, &mut self,
layer: usize, layer: usize,
polygon: impl IntoIterator<Item = Vector2<i64>>, multiobstacle: impl IntoIterator<Item = Vector2<i64>>,
) -> ObstacleId { ) -> MultiObstacleId {
ObstacleId::new(layer, self.layers[layer].insert_obstacle(polygon)) MultiObstacleId::new(
layer,
self.layer_navmeshers[layer].insert_multiobstacle(multiobstacle),
)
}
pub fn insert_free_multivertex_in_multiobstacle(
&mut self,
multiobstacle_id: MultiObstacleId,
position: Vector2<i64>,
) -> 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, navmesher: Navmesher,
board: Board, board: Board,
joint_obstacles: Recorder<Vec<ObstacleId>>, joint_multiobstacles: Recorder<Vec<MultiObstacleId>>,
segment_obstacles: Recorder<Vec<ObstacleId>>, segment_multiobstacles: Recorder<Vec<MultiObstacleId>>,
polygon_obstacles: Recorder<Vec<ObstacleId>>, polygon_multiobstacles: Recorder<Vec<MultiObstacleId>>,
} }
impl NavmesherBoard { impl NavmesherBoard {
@ -148,23 +197,23 @@ impl NavmesherBoard {
), ),
board, board,
joint_obstacles: Recorder::new(Vec::new()), joint_multiobstacles: Recorder::new(Vec::new()),
segment_obstacles: Recorder::new(Vec::new()), segment_multiobstacles: Recorder::new(Vec::new()),
polygon_obstacles: Recorder::new(Vec::new()), polygon_multiobstacles: Recorder::new(Vec::new()),
}; };
for (i, joint) in this.board.layout().joints().collection() { for (i, joint) in this.board.layout().joints().collection() {
this.joint_obstacles.insert( this.joint_multiobstacles.insert(
i, i,
this.navmesher 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() { for (i, segment) in this.board.layout().segments().collection() {
this.segment_obstacles.insert( this.segment_multiobstacles.insert(
i, i,
this.navmesher.insert_obstacle( this.navmesher.insert_multiobstacle(
segment.layer, segment.layer,
this.segment_bounding_rectangle(SegmentId::new(i), *segment), this.segment_bounding_rectangle(SegmentId::new(i), *segment),
), ),
@ -172,10 +221,10 @@ impl NavmesherBoard {
} }
for (i, polygon) in this.board.layout().polygons().collection() { for (i, polygon) in this.board.layout().polygons().collection() {
this.polygon_obstacles.insert( this.polygon_multiobstacles.insert(
i, i,
this.navmesher 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 { pub fn insert_joint(&mut self, joint: Joint) -> JointId {
let joint_id = self.board.add_joint(joint); let joint_id = self.board.add_joint(joint);
self.joint_obstacles.insert( self.joint_multiobstacles.insert(
joint_id.id(), joint_id.id(),
self.navmesher self.navmesher
.insert_obstacle(joint.layer, Self::joint_bounding_octagon(joint)), .insert_multiobstacle(joint.layer, Self::joint_bounding_octagon(joint)),
); );
joint_id joint_id
@ -212,9 +261,9 @@ impl NavmesherBoard {
pub fn insert_segment(&mut self, segment: Segment) -> SegmentId { pub fn insert_segment(&mut self, segment: Segment) -> SegmentId {
let segment_id = self.board.add_segment(segment); let segment_id = self.board.add_segment(segment);
self.segment_obstacles.insert( self.segment_multiobstacles.insert(
segment_id.id(), segment_id.id(),
self.navmesher.insert_obstacle( self.navmesher.insert_multiobstacle(
segment.layer, segment.layer,
self.segment_bounding_rectangle(segment_id, segment), self.segment_bounding_rectangle(segment_id, segment),
), ),
@ -245,10 +294,10 @@ impl NavmesherBoard {
pub fn insert_polygon(&mut self, polygon: Polygon) -> PolygonId { pub fn insert_polygon(&mut self, polygon: Polygon) -> PolygonId {
let polygon_id = self.board.add_polygon(polygon.clone()); let polygon_id = self.board.add_polygon(polygon.clone());
self.polygon_obstacles.insert( self.polygon_multiobstacles.insert(
polygon_id.id(), polygon_id.id(),
self.navmesher self.navmesher
.insert_obstacle(polygon.layer, polygon.vertices), .insert_multiobstacle(polygon.layer, polygon.vertices),
); );
polygon_id polygon_id