From ce5634ee6ab0287d8d5a0abb6df6f8c26a1eb33c Mon Sep 17 00:00:00 2001 From: Mikolaj Wielgus Date: Fri, 13 Mar 2026 23:23:14 +0100 Subject: [PATCH] Revert "Keep track of primitive id associated with navpolygon" This reverts commit 965080b8dba0d3f752f17bcaae4ea0cc1547082e. --- topola-egui/src/displayer.rs | 4 - topola/Cargo.toml | 2 +- topola/src/lib.rs | 1 - topola/src/navmesh.rs | 74 -------------- topola/src/navmesher.rs | 180 +++++++++++++++++++++-------------- 5 files changed, 107 insertions(+), 154 deletions(-) delete mode 100644 topola/src/navmesh.rs diff --git a/topola-egui/src/displayer.rs b/topola-egui/src/displayer.rs index e4d8fa0..de8d437 100644 --- a/topola-egui/src/displayer.rs +++ b/topola-egui/src/displayer.rs @@ -187,7 +187,6 @@ impl Displayer { if workspace.appearance_panel.visible[layer] { for navmesh in workspace.navmesher_board.navmesher().layers()[layer].navmeshes() { for edge_geom in navmesh - .triangulator() .triangulation() .rtreed_dcel() .edges_rtree() @@ -195,20 +194,17 @@ impl Displayer { .iter() { let (from_vertex, to_vertex) = navmesh - .triangulator() .triangulation() .rtreed_dcel() .dcel() .edge_endpoints(edge_geom.data); let from = navmesh - .triangulator() .triangulation() .rtreed_dcel() .dcel() .vertex_weight(from_vertex) .position(); let to = navmesh - .triangulator() .triangulation() .rtreed_dcel() .dcel() diff --git a/topola/Cargo.toml b/topola/Cargo.toml index dac59b6..d330eb8 100644 --- a/topola/Cargo.toml +++ b/topola/Cargo.toml @@ -10,7 +10,7 @@ edition = "2024" [dependencies] bimap = "0.6" -dearcut = { version = "0.2", features = ["undoredo"] } +dearcut = { version = "0.1", features = ["undoredo"] } derive-getters.workspace = true derive_more.workspace = true serde.workspace = true diff --git a/topola/src/lib.rs b/topola/src/lib.rs index f9b3c38..f4a5caf 100644 --- a/topola/src/lib.rs +++ b/topola/src/lib.rs @@ -5,7 +5,6 @@ mod board; mod layout; mod math; -mod navmesh; mod navmesher; mod primitives; mod selection; diff --git a/topola/src/navmesh.rs b/topola/src/navmesh.rs deleted file mode 100644 index c18945c..0000000 --- a/topola/src/navmesh.rs +++ /dev/null @@ -1,74 +0,0 @@ -// SPDX-FileCopyrightText: 2026 Topola contributors -// -// SPDX-License-Identifier: MIT OR Apache-2.0 - -use dearcut::RecordingTriangulator; -use derive_getters::Getters; - -use crate::primitives::PrimitiveId; - -#[derive(Clone, Debug, Getters)] -pub struct Navmesh { - boundary: Vec<[i64; 2]>, - triangulator: RecordingTriangulator, - navpolygon_primitives: Vec, - inflation_factor: f64, -} - -impl Navmesh { - pub fn new(boundary: impl IntoIterator) -> Self { - Self { - boundary: boundary.into_iter().collect(), - triangulator: RecordingTriangulator::new(), - navpolygon_primitives: Vec::new(), - inflation_factor: 0.0, - } - } - - pub fn insert_polygon( - &mut self, - primitive_id: PrimitiveId, - polygon: impl IntoIterator, - ) { - let navpolygon_index = self.triangulator.insert_polygon_and_rebuild( - Self::inflate_polygon(polygon, self.inflation_factor), - self.boundary.clone(), - ); - - self.navpolygon_primitives - .resize(navpolygon_index + 1, primitive_id); - self.navpolygon_primitives[navpolygon_index] = primitive_id; - } - - fn inflate_polygon( - polygon: impl IntoIterator, - inflation_factor: f64, - ) -> impl IntoIterator { - let polygon: Vec<[i64; 2]> = polygon.into_iter().collect(); - - // Centroid. - let cx = polygon.iter().map(|p| p[0] as f64).sum::() / polygon.len() as f64; - let cy = polygon.iter().map(|p| p[1] as f64).sum::() / polygon.len() as f64; - - polygon.into_iter().map(move |[px, py]| { - // Delta. - let dx = px as f64 - cx; - let dy = py as f64 - cy; - let d = (dx * dx + dy * dy).sqrt(); - - // Normalize delta. - let nx = dx / d; - let ny = dy / d; - - // Shift away from centroid. - let fx = px as f64 + nx * inflation_factor; - let fy = py as f64 + ny * inflation_factor; - - // Round away from centroid. - let rx = if fx >= cx { fx.ceil() } else { fx.floor() }; - let ry = if fy >= cy { fy.ceil() } else { fy.floor() }; - - [rx as i64, ry as i64] - }) - } -} diff --git a/topola/src/navmesher.rs b/topola/src/navmesher.rs index 795fc96..eb7ba32 100644 --- a/topola/src/navmesher.rs +++ b/topola/src/navmesher.rs @@ -2,41 +2,72 @@ // // SPDX-License-Identifier: MIT OR Apache-2.0 +use dearcut::RecordingTriangulator; use derive_getters::Getters; use crate::{ Board, - navmesh::Navmesh, - primitives::{Joint, JointId, Polygon, PolygonId, PrimitiveId, Segment, SegmentId, Via, ViaId}, + primitives::{Joint, JointId, Polygon, PolygonId, Segment, SegmentId, Via, ViaId}, }; #[derive(Clone, Debug, Getters)] pub struct LayerNavmesher { boundary: Vec<[i64; 2]>, - navmeshes: Vec, + navmeshes: Vec>, + inflation_factors: Vec, } impl LayerNavmesher { - fn new(boundary: impl IntoIterator) -> Self { - let boundary: Vec<[i64; 2]> = boundary.into_iter().collect(); - + pub fn new(boundary: impl IntoIterator) -> Self { Self { - boundary: boundary.clone(), - navmeshes: vec![Navmesh::new(boundary)], + boundary: boundary.into_iter().collect(), + navmeshes: vec![RecordingTriangulator::new()], + inflation_factors: vec![0.0], } } - fn insert_primitive_in_polygon( - &mut self, - primitive_id: PrimitiveId, - polygon: impl IntoIterator, - ) { + pub fn insert_polygon(&mut self, polygon: impl IntoIterator) { let polygon: Vec<[i64; 2]> = polygon.into_iter().collect(); for i in 0..self.navmeshes.len() { - self.navmeshes[i].insert_polygon(primitive_id, polygon.clone()); + self.navmeshes[i].insert_polygon_and_rebuild( + Self::inflate_polygon(polygon.clone(), self.inflation_factors[i]), + self.boundary.clone(), + ); } } + + fn inflate_polygon( + polygon: impl IntoIterator, + inflation_factor: f64, + ) -> impl IntoIterator { + let polygon: Vec<[i64; 2]> = polygon.into_iter().collect(); + + // Centroid. + let cx = polygon.iter().map(|p| p[0] as f64).sum::() / polygon.len() as f64; + let cy = polygon.iter().map(|p| p[1] as f64).sum::() / polygon.len() as f64; + + polygon.into_iter().map(move |[px, py]| { + // Delta. + let dx = px as f64 - cx; + let dy = py as f64 - cy; + let d = (dx * dx + dy * dy).sqrt(); + + // Normalize delta. + let nx = dx / d; + let ny = dy / d; + + // Shift away from centroid. + let fx = px as f64 + nx * inflation_factor; + let fy = py as f64 + ny * inflation_factor; + + // Round away from centroid. + let rx = if fx >= cx { fx.ceil() } else { fx.floor() }; + let ry = if fy >= cy { fy.ceil() } else { fy.floor() }; + + [rx as i64, ry as i64] + }) + } } #[derive(Clone, Debug, Getters)] @@ -45,7 +76,7 @@ pub struct Navmesher { } impl Navmesher { - fn new(boundary: impl IntoIterator, layer_count: usize) -> Self { + pub fn new(boundary: impl IntoIterator, layer_count: usize) -> Self { let boundary: Vec<[i64; 2]> = boundary.into_iter().collect(); Self { @@ -55,9 +86,46 @@ impl Navmesher { } } - fn insert_joint(&mut self, joint_id: JointId, joint: Joint) { - self.layers[joint.layer] - .insert_primitive_in_polygon(joint_id.into(), Self::joint_circumscribed_octagon(joint)); + pub fn insert_polygon(&mut self, layer: usize, polygon: impl IntoIterator) { + self.layers[layer].insert_polygon(polygon); + } +} + +#[derive(Clone, Debug, Getters)] +pub struct NavmesherBoard { + navmesher: Navmesher, + board: Board, +} + +impl NavmesherBoard { + pub fn with_board(board: Board) -> Self { + let mut navmesher = Navmesher::new( + board.layout().boundary().clone(), + *board.layout().layer_count(), + ); + + for (_, joint) in board.layout().joints().collection() { + Self::insert_joint_in_navmesher(&mut navmesher, *joint); + } + + for (i, segment) in board.layout().segments().collection() { + Self::insert_segment_in_navmesher(&mut navmesher, &board, SegmentId::new(i), *segment); + } + + for (_, polygon) in board.layout().polygons().collection() { + Self::insert_polygon_in_navmesher(&mut navmesher, polygon.clone()); + } + + Self { navmesher, board } + } + + pub fn insert_joint(&mut self, joint: Joint) -> JointId { + Self::insert_joint_in_navmesher(&mut self.navmesher, joint); + self.board.add_joint(joint) + } + + fn insert_joint_in_navmesher(navmesher: &mut Navmesher, joint: Joint) { + navmesher.insert_polygon(joint.layer, Self::joint_circumscribed_octagon(joint)); } fn joint_circumscribed_octagon(joint: Joint) -> [[i64; 2]; 8] { @@ -77,11 +145,23 @@ impl Navmesher { ] } - fn insert_segment(&mut self, board: &Board, segment_id: SegmentId, segment: Segment) { + pub fn insert_segment(&mut self, segment: Segment) -> SegmentId { + let segment_id = self.board.add_segment(segment); + Self::insert_segment_in_navmesher(&mut self.navmesher, &self.board, segment_id, segment); + + segment_id + } + + fn insert_segment_in_navmesher( + navmesher: &mut Navmesher, + board: &Board, + segment_id: SegmentId, + segment: Segment, + ) { let endpoints = board.layout().segment_endpoints(segment_id); - self.layers[segment.layer].insert_primitive_in_polygon( - segment_id.into(), + navmesher.insert_polygon( + segment.layer, Self::inflated_segment( endpoints[0][0], endpoints[0][1], @@ -111,65 +191,17 @@ impl Navmesher { ] } - fn insert_polygon(&mut self, polygon_id: PolygonId, polygon: Polygon) { - self.layers[polygon.layer].insert_primitive_in_polygon(polygon_id.into(), polygon.vertices); - } -} - -#[derive(Clone, Debug, Getters)] -pub struct NavmesherBoard { - navmesher: Navmesher, - board: Board, -} - -impl NavmesherBoard { - pub fn with_board(board: Board) -> Self { - let mut navmesher = Navmesher::new( - board.layout().boundary().clone(), - *board.layout().layer_count(), - ); - - for (i, joint) in board.layout().joints().collection() { - navmesher.insert_joint(JointId::new(i).into(), *joint); - } - - for (i, segment) in board.layout().segments().collection() { - navmesher.insert_segment(&board, SegmentId::new(i), *segment); - } - - // TODO: Vias. - - for (i, polygon) in board.layout().polygons().collection() { - navmesher.insert_polygon(PolygonId::new(i), polygon.clone()); - } - - Self { navmesher, board } - } - - pub fn insert_joint(&mut self, joint: Joint) -> JointId { - let joint_id = self.board.add_joint(joint); - self.navmesher.insert_joint(joint_id, joint); - - joint_id - } - - pub fn insert_segment(&mut self, segment: Segment) -> SegmentId { - let segment_id = self.board.add_segment(segment); - self.navmesher - .insert_segment(&self.board, segment_id, segment); - - segment_id - } - pub fn insert_via(&mut self, via: Via) -> ViaId { // TODO: Insert into navmesh. self.board.add_via(via) } pub fn insert_polygon(&mut self, polygon: Polygon) -> PolygonId { - let polygon_id = self.board.add_polygon(polygon.clone()); - self.navmesher.insert_polygon(polygon_id, polygon); + Self::insert_polygon_in_navmesher(&mut self.navmesher, polygon.clone()); + self.board.add_polygon(polygon) + } - polygon_id + fn insert_polygon_in_navmesher(navmesher: &mut Navmesher, polygon: Polygon) { + navmesher.insert_polygon(polygon.layer, polygon.vertices); } }