From c492bd1dda9b09b0b96174ff4b34a806a3b149c0 Mon Sep 17 00:00:00 2001 From: Mikolaj Wielgus Date: Sat, 2 Sep 2023 06:05:13 +0200 Subject: [PATCH] Parametrize routing using `RouteStrategy` trait --- src/astar.rs | 4 +--- src/main.rs | 3 ++- src/router.rs | 65 ++++++++++++++++++++++++++++++++++++++++----------- 3 files changed, 55 insertions(+), 17 deletions(-) diff --git a/src/astar.rs b/src/astar.rs index 31d7b22..df0cc0c 100644 --- a/src/astar.rs +++ b/src/astar.rs @@ -1,8 +1,6 @@ /** * - * Copied from petgraph's scored.rs and algo/astar.rs. Renamed the `is_goal: IsGoal` callback to - * `reroute: Reroute` and made it pass a reference to `path_tracker` and return a value to be added - * to outgoing edge costs. + * Copied and substantially modified from petgraph's scored.rs and algo/astar.rs. * * Copyright (c) 2015 **/ diff --git a/src/main.rs b/src/main.rs index d497c21..a206fb0 100644 --- a/src/main.rs +++ b/src/main.rs @@ -24,6 +24,7 @@ mod segbend; mod shape; use graph::{Tag, TaggedIndex}; +use router::DefaultRouteStrategy; use sdl2::event::Event; use sdl2::gfx::primitives::DrawRenderer; use sdl2::keyboard::Keycode; @@ -218,7 +219,7 @@ fn main() { let head = router.draw_around_dot(head, dot6, false, 5.0).unwrap(); let _ = router.draw_finish(head, dot7, 5.0);*/ - router.enroute(dot1_1, dot1_2); + router.enroute(dot1_1, dot1_2, DefaultRouteStrategy::new()); render_times(&mut event_pump, &mut canvas, &mut router, None, -1); render_times( diff --git a/src/router.rs b/src/router.rs index 71952b3..05f8f46 100644 --- a/src/router.rs +++ b/src/router.rs @@ -21,19 +21,53 @@ pub struct Router { rules: Rules, } -pub struct DefaultAstarStrategy<'a> { - route: Route<'a>, - trace: Trace, - to: VertexIndex, +pub trait RouteStrategy { + fn route_cost(&mut self, path: &[VertexIndex]) -> u64; + fn edge_cost(&mut self, edge: MeshEdgeReference) -> u64; + fn estimate_cost(&mut self, vertex: VertexIndex) -> u64; } -impl<'a> DefaultAstarStrategy<'a> { - pub fn new(route: Route<'a>, trace: Trace, to: VertexIndex) -> Self { - Self { route, trace, to } +pub struct DefaultRouteStrategy {} + +impl DefaultRouteStrategy { + pub fn new() -> Self { + Self {} } } -impl<'a> AstarStrategy<&Mesh, u64> for DefaultAstarStrategy<'a> { +impl RouteStrategy for DefaultRouteStrategy { + fn route_cost(&mut self, path: &[VertexIndex]) -> u64 { + 0 + } + + fn edge_cost(&mut self, edge: MeshEdgeReference) -> u64 { + 1 + } + + fn estimate_cost(&mut self, vertex: VertexIndex) -> u64 { + 0 + } +} + +struct RouterAstarStrategy<'a, RS: RouteStrategy> { + route: Route<'a>, + trace: Trace, + to: VertexIndex, + route_strategy: RS, +} + +impl<'a, RS: RouteStrategy> RouterAstarStrategy<'a, RS> { + pub fn new(route: Route<'a>, trace: Trace, to: VertexIndex, route_strategy: RS) -> Self { + Self { + route, + trace, + to, + route_strategy, + } + } +} + +impl<'a, RS: RouteStrategy> AstarStrategy<&Mesh, u64> for RouterAstarStrategy<'a, RS> { fn reroute(&mut self, vertex: VertexIndex, tracker: &PathTracker<&Mesh>) -> Option { let new_path = tracker.reconstruct_path_to(vertex); @@ -47,16 +81,16 @@ impl<'a> AstarStrategy<&Mesh, u64> for DefaultAstarStrategy<'a> { None } else { self.route.rework_path(&mut self.trace, &new_path, 5.0).ok(); - Some(0) + Some(self.route_strategy.route_cost(&new_path)) } } fn edge_cost(&mut self, edge: MeshEdgeReference) -> u64 { - 1 + self.route_strategy.edge_cost(edge) } fn estimate_cost(&mut self, vertex: VertexIndex) -> u64 { - 0 + self.route_strategy.estimate_cost(vertex) } } @@ -68,7 +102,12 @@ impl Router { } } - pub fn enroute(&mut self, from: DotIndex, to: DotIndex) -> Result<(), InsertionError> { + pub fn enroute( + &mut self, + from: DotIndex, + to: DotIndex, + strategy: impl RouteStrategy, + ) -> Result<(), InsertionError> { // XXX: Should we actually store the mesh? May be useful for debugging, but doesn't look // right. //self.mesh.triangulate(&self.layout)?; @@ -81,7 +120,7 @@ impl Router { let (_cost, path) = astar( &mesh, mesh.vertex(from), - &mut DefaultAstarStrategy::new(route, trace, mesh.vertex(to)), + &mut RouterAstarStrategy::new(route, trace, mesh.vertex(to), strategy), ) .unwrap(); // TODO. Ok(())