egui: draw the navmesh

This required some considerable rearrangements in `Router`.
This commit is contained in:
Mikolaj Wielgus 2024-05-06 02:35:43 +02:00
parent 63561e6a4a
commit eaecb99146
7 changed files with 82 additions and 56 deletions

View File

@ -11,12 +11,13 @@ use crate::{
autorouter::ratsnest::{Ratsnest, RatsnestVertexIndex}, autorouter::ratsnest::{Ratsnest, RatsnestVertexIndex},
drawing::{dot::FixedDotIndex, rules::RulesTrait}, drawing::{dot::FixedDotIndex, rules::RulesTrait},
layout::{connectivity::BandIndex, Layout}, layout::{connectivity::BandIndex, Layout},
router::{Router, RouterObserverTrait, RoutingError}, router::{navmesh::Navmesh, Router, RouterObserverTrait, RoutingError},
triangulation::GetVertexIndex, triangulation::GetVertexIndex,
}; };
pub struct Autoroute { pub struct Autoroute {
edge_indices: EdgeIndices<usize>, edge_indices: EdgeIndices<usize>,
navmesh: Navmesh, // Useful for debugging.
} }
impl Autoroute { impl Autoroute {
@ -30,9 +31,9 @@ impl Autoroute {
}; };
let (from, to) = autorouter.ratsnest.graph().edge_endpoints(ratline).unwrap(); let (from, to) = autorouter.ratsnest.graph().edge_endpoints(ratline).unwrap();
let (from_dot, to_dot) = { let (navmesh, from_dot, to_dot) = {
let layout = autorouter.router.layout(); let mut layout = autorouter.layout.lock().unwrap();
let mut layout = layout.lock().unwrap(); let navmesh = Navmesh::new(&layout).unwrap();
let from_dot = match autorouter let from_dot = match autorouter
.ratsnest .ratsnest
@ -56,28 +57,33 @@ impl Autoroute {
RatsnestVertexIndex::Zone(zone) => layout.zone_apex(zone), RatsnestVertexIndex::Zone(zone) => layout.zone_apex(zone),
}; };
(from_dot, to_dot) (navmesh, from_dot, to_dot)
}; };
autorouter let router = Router::new_with_navmesh(
.router &mut autorouter.layout,
std::mem::replace(&mut self.navmesh, navmesh),
);
router
.unwrap()
.route_band(from_dot, to_dot, 100.0, observer); .route_band(from_dot, to_dot, 100.0, observer);
Some(()) Some(())
} }
pub fn navmesh(&self) -> &Navmesh {
&self.navmesh
}
} }
pub struct Autorouter<R: RulesTrait> { pub struct Autorouter<R: RulesTrait> {
ratsnest: Ratsnest, ratsnest: Ratsnest,
router: Router<R>, layout: Arc<Mutex<Layout<R>>>,
} }
impl<R: RulesTrait> Autorouter<R> { impl<R: RulesTrait> Autorouter<R> {
pub fn new(layout: Arc<Mutex<Layout<R>>>) -> Result<Self, InsertionError> { pub fn new(layout: Arc<Mutex<Layout<R>>>) -> Result<Self, InsertionError> {
let ratsnest = Ratsnest::new(&layout.lock().unwrap())?; let ratsnest = Ratsnest::new(&layout.lock().unwrap())?;
Ok(Self { Ok(Self { ratsnest, layout })
ratsnest,
router: Router::new(layout),
})
} }
pub fn autoroute(&mut self, observer: &mut impl RouterObserverTrait<R>) { pub fn autoroute(&mut self, observer: &mut impl RouterObserverTrait<R>) {
@ -90,10 +96,11 @@ impl<R: RulesTrait> Autorouter<R> {
pub fn autoroute_iter(&mut self) -> Autoroute { pub fn autoroute_iter(&mut self) -> Autoroute {
Autoroute { Autoroute {
edge_indices: self.ratsnest.graph().edge_indices(), edge_indices: self.ratsnest.graph().edge_indices(),
navmesh: Navmesh::new(&self.layout.lock().unwrap()).unwrap(),
} }
} }
pub fn router(&self) -> &Router<R> { pub fn layout(&self) -> &Arc<Mutex<Layout<R>>> {
&self.router &self.layout
} }
} }

View File

@ -21,13 +21,14 @@ use topola::{
geometry::{ geometry::{
compound::CompoundManagerTrait, compound::CompoundManagerTrait,
primitive::{BendShape, DotShape, PrimitiveShape, PrimitiveShapeTrait, SegShape}, primitive::{BendShape, DotShape, PrimitiveShape, PrimitiveShapeTrait, SegShape},
shape::ShapeTrait,
GenericNode, GenericNode,
}, },
layout::{zone::MakePolyShape, Layout}, layout::{zone::MakePolyShape, Layout},
math::Circle, math::Circle,
router::{ router::{
draw::DrawException, draw::DrawException,
navmesh::{NavmeshEdgeReference, VertexIndex}, navmesh::{Navmesh, NavmeshEdgeReference, VertexIndex},
tracer::{Trace, Tracer}, tracer::{Trace, Tracer},
RouterObserverTrait, RouterObserverTrait,
}, },
@ -37,6 +38,7 @@ use crate::{overlay::Overlay, painter::Painter};
#[derive(Debug, Default)] #[derive(Debug, Default)]
struct SharedData { struct SharedData {
pub navmesh: Option<Navmesh>,
pub path: Vec<VertexIndex>, pub path: Vec<VertexIndex>,
pub ghosts: Vec<PrimitiveShape>, pub ghosts: Vec<PrimitiveShape>,
pub highlighteds: Vec<PrimitiveIndex>, pub highlighteds: Vec<PrimitiveIndex>,
@ -197,7 +199,17 @@ impl eframe::App for App {
execute(async move { execute(async move {
let mut autorouter = Autorouter::new(layout).unwrap(); let mut autorouter = Autorouter::new(layout).unwrap();
autorouter.autoroute(&mut DebugRouterObserver { shared_data }); let mut it = autorouter.autoroute_iter();
shared_data.lock().unwrap().navmesh = Some(it.navmesh().clone());
while let Some(()) = it.next(
&mut autorouter,
&mut DebugRouterObserver {
shared_data: shared_data.clone(),
},
) {
shared_data.lock().unwrap().navmesh = Some(it.navmesh().clone());
}
}); });
} }
} }
@ -264,7 +276,7 @@ impl eframe::App for App {
} else { } else {
egui::Color32::from_rgb(52, 52, 200) egui::Color32::from_rgb(52, 52, 200)
}; };
painter.paint_shape(&shape, color); painter.paint_primitive(&shape, color);
} }
for zone in layout.layer_zone_nodes(1) { for zone in layout.layer_zone_nodes(1) {
@ -289,7 +301,7 @@ impl eframe::App for App {
} else { } else {
egui::Color32::from_rgb(200, 52, 52) egui::Color32::from_rgb(200, 52, 52)
}; };
painter.paint_shape(&shape, color); painter.paint_primitive(&shape, color);
} }
for zone in layout.layer_zone_nodes(0) { for zone in layout.layer_zone_nodes(0) {
@ -319,8 +331,21 @@ impl eframe::App for App {
painter.paint_edge(from, to, egui::Color32::from_rgb(90, 90, 200)); painter.paint_edge(from, to, egui::Color32::from_rgb(90, 90, 200));
} }
if let Some(navmesh) = &shared_data.navmesh {
for edge in navmesh.edge_references() {
let from =
edge.source().primitive(layout.drawing()).shape().center();
let to = edge.target().primitive(layout.drawing()).shape().center();
painter.paint_edge(
from,
to,
egui::Color32::from_rgb(125, 125, 125),
);
}
}
for ghost in shared_data.ghosts.iter() { for ghost in shared_data.ghosts.iter() {
painter.paint_shape(&ghost, egui::Color32::from_rgb(75, 75, 150)); painter.paint_primitive(&ghost, egui::Color32::from_rgb(75, 75, 150));
} }
//unreachable!(); //unreachable!();
} }

View File

@ -11,7 +11,7 @@ impl<'a> Painter<'a> {
Self { ui, transform } Self { ui, transform }
} }
pub fn paint_shape(&mut self, shape: &PrimitiveShape, color: egui::epaint::Color32) { pub fn paint_primitive(&mut self, shape: &PrimitiveShape, color: egui::epaint::Color32) {
let epaint_shape = match shape { let epaint_shape = match shape {
PrimitiveShape::Dot(dot) => egui::Shape::circle_filled( PrimitiveShape::Dot(dot) => egui::Shape::circle_filled(
self.transform self.transform

View File

@ -406,7 +406,7 @@ fn render_times(
}; };
let shape = node.primitive(drawing).shape(); let shape = node.primitive(drawing).shape();
painter.paint_shape(&shape, color, view.zoom); painter.paint_primitive(&shape, color, view.zoom);
} }
for zone in drawing.layer_zones(1) { for zone in drawing.layer_zones(1) {
@ -425,7 +425,7 @@ fn render_times(
}; };
let shape = node.primitive(drawing).shape(); let shape = node.primitive(drawing).shape();
painter.paint_shape(&shape, color, view.zoom); painter.paint_primitive(&shape, color, view.zoom);
} }
for zone in drawing.layer_zones(0) { for zone in drawing.layer_zones(0) {
@ -437,13 +437,13 @@ fn render_times(
} }
for ghost in ghosts { for ghost in ghosts {
painter.paint_shape(&ghost, ColorU::new(75, 75, 150, 255), view.zoom); painter.paint_primitive(&ghost, ColorU::new(75, 75, 150, 255), view.zoom);
} }
if let Some(ref navmesh) = maybe_navmesh { if let Some(ref navmesh) = maybe_navmesh {
for edge in navmesh.edge_references() { for edge in navmesh.edge_references() {
let to = edge.source().primitive(drawing).shape().center(); let from = edge.source().primitive(drawing).shape().center();
let from = edge.target().primitive(drawing).shape().center(); let to = edge.target().primitive(drawing).shape().center();
let color = 'blk: { let color = 'blk: {
if let (Some(source_pos), Some(target_pos)) = ( if let (Some(source_pos), Some(target_pos)) = (

View File

@ -13,7 +13,7 @@ impl<'a> Painter<'a> {
Self { canvas } Self { canvas }
} }
pub fn paint_shape(&mut self, shape: &PrimitiveShape, color: ColorU, zoom: f32) { pub fn paint_primitive(&mut self, shape: &PrimitiveShape, color: ColorU, zoom: f32) {
self.canvas.set_stroke_style(color); self.canvas.set_stroke_style(color);
self.canvas.set_fill_style(color); self.canvas.set_fill_style(color);

View File

@ -57,24 +57,20 @@ pub trait RouterObserverTrait<R: RulesTrait> {
fn on_estimate(&mut self, tracer: &Tracer<R>, vertex: VertexIndex); fn on_estimate(&mut self, tracer: &Tracer<R>, vertex: VertexIndex);
} }
pub struct Router<R: RulesTrait> { pub struct Router<'a, R: RulesTrait> {
layout: Arc<Mutex<Layout<R>>>, layout: &'a mut Arc<Mutex<Layout<R>>>,
navmesh: Navmesh,
} }
struct RouterAstarStrategy<'a, RO: RouterObserverTrait<R>, R: RulesTrait> { struct RouterAstarStrategy<'a, RO: RouterObserverTrait<R>, R: RulesTrait> {
tracer: Tracer<'a, R>, tracer: Tracer<R>,
trace: Trace, trace: Trace,
to: FixedDotIndex, to: FixedDotIndex,
observer: &'a mut RO, observer: &'a mut RO,
} }
impl<'a, RO: RouterObserverTrait<R>, R: RulesTrait> RouterAstarStrategy<'a, RO, R> { impl<'a, RO: RouterObserverTrait<R>, R: RulesTrait> RouterAstarStrategy<'a, RO, R> {
pub fn new( pub fn new(tracer: Tracer<R>, trace: Trace, to: FixedDotIndex, observer: &'a mut RO) -> Self {
tracer: Tracer<'a, R>,
trace: Trace,
to: FixedDotIndex,
observer: &'a mut RO,
) -> Self {
Self { Self {
tracer, tracer,
trace, trace,
@ -146,9 +142,17 @@ impl<'a, RO: RouterObserverTrait<R>, R: RulesTrait> AstarStrategy<&Navmesh, f64>
} }
} }
impl<R: RulesTrait> Router<R> { impl<'a, R: RulesTrait> Router<'a, R> {
pub fn new(layout: Arc<Mutex<Layout<R>>>) -> Self { pub fn new(layout: &'a mut Arc<Mutex<Layout<R>>>) -> Result<Self, InsertionError> {
Router { layout } let navmesh = Navmesh::new(&layout.lock().unwrap())?;
Self::new_with_navmesh(layout, navmesh)
}
pub fn new_with_navmesh(
layout: &'a mut Arc<Mutex<Layout<R>>>,
navmesh: Navmesh,
) -> Result<Self, InsertionError> {
Ok(Self { layout, navmesh })
} }
pub fn route_band( pub fn route_band(
@ -158,22 +162,13 @@ impl<R: RulesTrait> Router<R> {
width: f64, width: f64,
observer: &mut impl RouterObserverTrait<R>, observer: &mut impl RouterObserverTrait<R>,
) -> Result<BandIndex, RoutingError> { ) -> Result<BandIndex, RoutingError> {
// XXX: Should we actually store the mesh? May be useful for debugging, but doesn't look let mut tracer = self.tracer();
// right.
//self.mesh.triangulate(&self.layout)?;
let mesh = Navmesh::new(&self.layout.lock().unwrap()).map_err(|err| RoutingError {
from,
to,
source: err.into(),
})?;
let mut tracer = self.tracer(&mesh);
let trace = tracer.start(from, width); let trace = tracer.start(from, width);
let band = trace.band; let band = trace.band;
let (_cost, _path) = astar( let (_cost, _path) = astar(
&mesh, &self.navmesh,
from.into(), from.into(),
&mut RouterAstarStrategy::new(tracer, trace, to.into(), observer), &mut RouterAstarStrategy::new(tracer, trace, to.into(), observer),
) )
@ -206,8 +201,8 @@ impl<R: RulesTrait> Router<R> {
self.route_band(from_dot, to_dot, width, observer) self.route_band(from_dot, to_dot, width, observer)
} }
pub fn tracer<'a>(&'a mut self, mesh: &'a Navmesh) -> Tracer<R> { fn tracer(&mut self) -> Tracer<R> {
Tracer::new(self.layout.clone(), mesh) Tracer::new(self.layout.clone())
} }
pub fn layout(&self) -> Arc<Mutex<Layout<R>>> { pub fn layout(&self) -> Arc<Mutex<Layout<R>>> {

View File

@ -25,14 +25,13 @@ pub struct Trace {
} }
#[derive(Debug)] #[derive(Debug)]
pub struct Tracer<'a, R: RulesTrait> { pub struct Tracer<R: RulesTrait> {
pub layout: Arc<Mutex<Layout<R>>>, pub layout: Arc<Mutex<Layout<R>>>,
pub navmesh: &'a Navmesh,
} }
impl<'a, R: RulesTrait> Tracer<'a, R> { impl<R: RulesTrait> Tracer<R> {
pub fn new(layout: Arc<Mutex<Layout<R>>>, navmesh: &'a Navmesh) -> Self { pub fn new(layout: Arc<Mutex<Layout<R>>>) -> Self {
Tracer { layout, navmesh } Tracer { layout }
} }
pub fn start(&mut self, from: FixedDotIndex, width: f64) -> Trace { pub fn start(&mut self, from: FixedDotIndex, width: f64) -> Trace {