From 09e1e35151db2ad897b6c037faa840d472de0ff6 Mon Sep 17 00:00:00 2001 From: Mikolaj Wielgus Date: Wed, 11 Mar 2026 10:26:23 +0100 Subject: [PATCH] Wrap `Board` in `NavmesherBoard` --- topola-egui/src/displayer.rs | 36 ++++++++++++++++++++++++++++-------- topola-egui/src/viewport.rs | 4 ++-- topola-egui/src/workspace.rs | 9 +++++---- topola/src/lib.rs | 1 + topola/src/navmesher.rs | 32 ++++++++++++++++++++++++++++++-- 5 files changed, 66 insertions(+), 16 deletions(-) diff --git a/topola-egui/src/displayer.rs b/topola-egui/src/displayer.rs index ae79dbe..bb1edf7 100644 --- a/topola-egui/src/displayer.rs +++ b/topola-egui/src/displayer.rs @@ -33,7 +33,8 @@ impl Displayer { ) { ui.painter().line( workspace - .board + .navmesher_board + .board() .layout() .boundary() .iter() @@ -45,7 +46,13 @@ impl Displayer { egui::Stroke::new(5.0 / viewport.scale_factor(), egui::Color32::WHITE), ); - for (_, joint) in workspace.board.layout().joints().collection() { + for (_, joint) in workspace + .navmesher_board + .board() + .layout() + .joints() + .collection() + { if workspace.appearance_panel.visible[joint.layer] { self.paint_joint( ctx, @@ -56,13 +63,19 @@ impl Displayer { .appearance_panel .colors(ctx) .layers - .color(workspace.board.layer_name(joint.layer)) + .color(workspace.navmesher_board.board().layer_name(joint.layer)) .normal, ); } } - for (i, segment) in workspace.board.layout().segments().collection() { + for (i, segment) in workspace + .navmesher_board + .board() + .layout() + .segments() + .collection() + { if workspace.appearance_panel.visible[segment.layer] { self.paint_segment( ctx, @@ -70,20 +83,27 @@ impl Displayer { viewport, segment, workspace - .board + .navmesher_board + .board() .layout() .segment_endpoints(SegmentId::new(i)), workspace .appearance_panel .colors(ctx) .layers - .color(workspace.board.layer_name(segment.layer)) + .color(workspace.navmesher_board.board().layer_name(segment.layer)) .normal, ); } } - for (_, polygon) in workspace.board.layout().polygons().collection() { + for (_, polygon) in workspace + .navmesher_board + .board() + .layout() + .polygons() + .collection() + { if workspace.appearance_panel.visible[polygon.layer] { self.paint_polygon( ctx, @@ -94,7 +114,7 @@ impl Displayer { .appearance_panel .colors(ctx) .layers - .color(workspace.board.layer_name(polygon.layer)) + .color(workspace.navmesher_board.board().layer_name(polygon.layer)) .normal, ); } diff --git a/topola-egui/src/viewport.rs b/topola-egui/src/viewport.rs index a7f1088..37f1aab 100644 --- a/topola-egui/src/viewport.rs +++ b/topola-egui/src/viewport.rs @@ -52,14 +52,14 @@ impl Viewport { } fn boundary_bounding_box(workspace: &Workspace) -> egui::Rect { - let first = workspace.board.layout().boundary()[0]; + let first = workspace.navmesher_board.board().layout().boundary()[0]; let mut min_x = first[0]; let mut max_x = first[0]; let mut min_y = first[1]; let mut max_y = first[1]; - for point in workspace.board.layout().boundary()[1..].iter() { + for point in workspace.navmesher_board.board().layout().boundary()[1..].iter() { if point[0] < min_x { min_x = point[0]; } diff --git a/topola-egui/src/workspace.rs b/topola-egui/src/workspace.rs index b0714f8..9f320c0 100644 --- a/topola-egui/src/workspace.rs +++ b/topola-egui/src/workspace.rs @@ -2,12 +2,12 @@ // // SPDX-License-Identifier: MIT OR Apache-2.0 -use topola::Board; +use topola::{Board, NavmesherBoard}; use crate::{appearance_panel::AppearancePanel, translator::Translator}; pub struct Workspace { - pub board: Board, + pub navmesher_board: NavmesherBoard, pub appearance_panel: AppearancePanel, } @@ -16,12 +16,13 @@ impl Workspace { let appearance_panel = AppearancePanel::new(&board); Self { - board, + navmesher_board: NavmesherBoard::with_board(board), appearance_panel, } } pub fn update_appearance_panel(&mut self, ctx: &egui::Context) { - self.appearance_panel.update(ctx, &self.board); + self.appearance_panel + .update(ctx, &self.navmesher_board.board()); } } diff --git a/topola/src/lib.rs b/topola/src/lib.rs index 0fc6f4b..5638fdf 100644 --- a/topola/src/lib.rs +++ b/topola/src/lib.rs @@ -12,3 +12,4 @@ pub use crate::board::Board; pub use crate::layout::{ Joint, JointId, Layout, Polygon, PolygonId, Segment, SegmentId, Via, ViaId, }; +pub use crate::navmesher::NavmesherBoard; diff --git a/topola/src/navmesher.rs b/topola/src/navmesher.rs index fddb772..d181e18 100644 --- a/topola/src/navmesher.rs +++ b/topola/src/navmesher.rs @@ -17,6 +17,13 @@ pub struct LayerNavmesher { } impl LayerNavmesher { + pub fn new() -> Self { + Self { + navmeshes: Vec::new(), + inflation_factors: Vec::new(), + } + } + pub fn insert_polygon(&mut self, polygon: impl IntoIterator) { let polygon: Vec<[i64; 2]> = polygon.into_iter().collect(); @@ -67,6 +74,14 @@ pub struct Navmesher { } impl Navmesher { + pub fn new(layer_count: usize) -> Self { + Self { + layers: std::iter::repeat_with(LayerNavmesher::new) + .take(layer_count) + .collect(), + } + } + pub fn insert_polygon(&mut self, layer: usize, polygon: impl IntoIterator) { self.layers[layer].insert_polygon(polygon); } @@ -79,12 +94,25 @@ pub struct NavmesherBoard { } impl NavmesherBoard { + pub fn with_board(board: Board) -> Self { + let mut navmesher = Navmesher::new(*board.layout().layer_count()); + + for (_, joint) in board.layout().joints().collection() { + Self::insert_joint_in_navmesher(&mut navmesher, *joint); + } + + Self { navmesher, board } + } + pub fn insert_joint(&mut self, joint: Joint) -> JointId { - self.navmesher - .insert_polygon(joint.layer, Self::joint_circumscribed_octagon(joint)); + 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] { let cx = joint.position[0]; let cy = joint.position[1];