router: Rename `Route` to `Tracer` and simplify related code

This commit is contained in:
Mikolaj Wielgus 2023-10-11 22:23:18 +00:00
parent cc3b537b5c
commit af61a6b120
4 changed files with 91 additions and 138 deletions

View File

@ -100,7 +100,7 @@ where
K: Measure + Copy, K: Measure + Copy,
G::NodeId: Eq + Hash, G::NodeId: Eq + Hash,
{ {
fn reroute(&mut self, node: G::NodeId, tracker: &PathTracker<G>) -> Option<K>; fn is_goal(&mut self, node: G::NodeId, tracker: &PathTracker<G>) -> bool;
fn edge_cost(&mut self, edge: G::EdgeRef) -> K; fn edge_cost(&mut self, edge: G::EdgeRef) -> K;
fn estimate_cost(&mut self, node: G::NodeId) -> K; fn estimate_cost(&mut self, node: G::NodeId) -> K;
} }
@ -125,13 +125,12 @@ where
visit_next.push(MinScored(strategy.estimate_cost(start), start)); visit_next.push(MinScored(strategy.estimate_cost(start), start));
while let Some(MinScored(estimate_score, node)) = visit_next.pop() { while let Some(MinScored(estimate_score, node)) = visit_next.pop() {
match strategy.reroute(node, &path_tracker) { if strategy.is_goal(node, &path_tracker) {
None => {
let path = path_tracker.reconstruct_path_to(node); let path = path_tracker.reconstruct_path_to(node);
let cost = scores[&node]; let cost = scores[&node];
return Some((cost, path)); return Some((cost, path));
} }
Some(route_cost) => {
// This lookup can be unwrapped without fear of panic since the node was // This lookup can be unwrapped without fear of panic since the node was
// necessarily scored before adding it to `visit_next`. // necessarily scored before adding it to `visit_next`.
let node_score = scores[&node]; let node_score = scores[&node];
@ -152,7 +151,7 @@ where
for edge in graph.edges(node) { for edge in graph.edges(node) {
let next = edge.target(); let next = edge.target();
let next_score = node_score + route_cost + strategy.edge_cost(edge); let next_score = node_score + strategy.edge_cost(edge);
match scores.entry(next) { match scores.entry(next) {
Occupied(mut entry) => { Occupied(mut entry) => {
@ -173,8 +172,6 @@ where
visit_next.push(MinScored(next_estimate_score, next)); visit_next.push(MinScored(next_estimate_score, next));
} }
} }
}
}
None None
} }

View File

@ -18,19 +18,18 @@ mod layout;
mod math; mod math;
mod mesh; mod mesh;
mod primitive; mod primitive;
mod route;
mod router; mod router;
mod rules; mod rules;
mod segbend; mod segbend;
mod shape; mod shape;
mod tracer;
use geo::point; use geo::point;
use graph::{DotIndex, SegWeight, Tag, TaggedIndex}; use graph::{DotIndex, SegWeight};
use layout::Layout; use layout::Layout;
use mesh::{Mesh, MeshEdgeReference, VertexIndex}; use mesh::{Mesh, MeshEdgeReference, VertexIndex};
use petgraph::visit::{EdgeRef, IntoEdgeReferences}; use petgraph::visit::{EdgeRef, IntoEdgeReferences};
use route::Route; use router::RouterObserver;
use router::{DefaultRouteStrategy, RouteStrategy};
use sdl2::event::Event; use sdl2::event::Event;
use sdl2::gfx::primitives::DrawRenderer; use sdl2::gfx::primitives::DrawRenderer;
use sdl2::keyboard::Keycode; use sdl2::keyboard::Keycode;
@ -41,6 +40,7 @@ use sdl2::EventPump;
use shape::Shape; use shape::Shape;
use std::panic; use std::panic;
use std::time::Duration; use std::time::Duration;
use tracer::Tracer;
use crate::graph::DotWeight; use crate::graph::DotWeight;
use crate::math::Circle; use crate::math::Circle;
@ -52,48 +52,36 @@ enum RouterOrLayout<'a> {
Layout(&'a Layout), Layout(&'a Layout),
} }
struct DebugRouteStrategy<'a, RS: RouteStrategy> { struct DebugRouterObserver<'a> {
strategy: RS,
event_pump: &'a mut sdl2::EventPump, event_pump: &'a mut sdl2::EventPump,
canvas: &'a mut sdl2::render::Canvas<Window>, canvas: &'a mut sdl2::render::Canvas<Window>,
} }
impl<'a, RS: RouteStrategy> DebugRouteStrategy<'a, RS> { impl<'a> DebugRouterObserver<'a> {
pub fn new( pub fn new(
strategy: RS,
event_pump: &'a mut sdl2::EventPump, event_pump: &'a mut sdl2::EventPump,
canvas: &'a mut sdl2::render::Canvas<Window>, canvas: &'a mut sdl2::render::Canvas<Window>,
) -> Self { ) -> Self {
Self { Self { event_pump, canvas }
strategy,
event_pump,
canvas,
}
} }
} }
impl<'a, RS: RouteStrategy> RouteStrategy for DebugRouteStrategy<'a, RS> { impl<'a> RouterObserver for DebugRouterObserver<'a> {
fn route_cost(&mut self, route: &Route, path: &[VertexIndex]) -> u64 { fn on_rework(&mut self, tracer: &Tracer, path: &[VertexIndex]) {
render_times( render_times(
self.event_pump, self.event_pump,
self.canvas, self.canvas,
RouterOrLayout::Layout(route.layout), RouterOrLayout::Layout(tracer.layout),
None, None,
None, None,
Some(route.mesh.clone()), Some(tracer.mesh.clone()),
path, path,
10, 10,
); );
self.strategy.route_cost(route, path)
} }
fn edge_cost(&mut self, route: &Route, edge: MeshEdgeReference) -> u64 { fn on_probe(&mut self, _tracer: &Tracer, _edge: MeshEdgeReference) {}
self.strategy.edge_cost(route, edge) fn on_estimate(&mut self, _tracer: &Tracer, _vertex: VertexIndex) {}
}
fn estimate_cost(&mut self, route: &Route, vertex: VertexIndex) -> u64 {
self.strategy.estimate_cost(route, vertex)
}
} }
fn main() { fn main() {
@ -304,11 +292,7 @@ fn render_times(
.reroute( .reroute(
from, from,
point! {x: state.x() as f64, y: state.y() as f64}, point! {x: state.x() as f64, y: state.y() as f64},
&mut DebugRouteStrategy::new( &mut DebugRouterObserver::new(event_pump, canvas),
DefaultRouteStrategy::new(),
event_pump,
canvas,
),
) )
.ok(); .ok();
} }

View File

@ -1,91 +1,63 @@
use geo::geometry::Point; use geo::geometry::Point;
use petgraph::visit::{EdgeRef, IntoEdgeReferences}; use petgraph::visit::EdgeRef;
use spade::InsertionError; use spade::InsertionError;
use crate::astar::{astar, AstarStrategy, PathTracker}; use crate::astar::{astar, AstarStrategy, PathTracker};
use crate::bow::Bow; use crate::graph::{DotIndex, DotWeight, Ends};
use crate::draw::{Draw, Head};
use crate::graph::{BendIndex, DotIndex, Ends, SegIndex, TaggedIndex};
use crate::graph::{BendWeight, DotWeight, SegWeight};
use crate::guide::Guide;
use crate::layout::Layout; use crate::layout::Layout;
use crate::math::Circle; use crate::math::Circle;
use crate::mesh::{Mesh, MeshEdgeReference, VertexIndex}; use crate::mesh::{Mesh, MeshEdgeReference, VertexIndex};
use crate::route::{Route, Trace}; use crate::rules::Rules;
use crate::rules::{Conditions, Rules}; use crate::tracer::{Trace, Tracer};
use crate::segbend::Segbend;
pub trait RouterObserver {
fn on_rework(&mut self, tracer: &Tracer, path: &[VertexIndex]);
fn on_probe(&mut self, tracer: &Tracer, edge: MeshEdgeReference);
fn on_estimate(&mut self, tracer: &Tracer, vertex: VertexIndex);
}
pub struct Router { pub struct Router {
pub layout: Layout, pub layout: Layout,
rules: Rules, rules: Rules,
} }
pub trait RouteStrategy { struct RouterAstarStrategy<'a, RO: RouterObserver> {
fn route_cost(&mut self, route: &Route, path: &[VertexIndex]) -> u64; tracer: Tracer<'a>,
fn edge_cost(&mut self, route: &Route, edge: MeshEdgeReference) -> u64;
fn estimate_cost(&mut self, route: &Route, vertex: VertexIndex) -> u64;
}
pub struct DefaultRouteStrategy {}
impl DefaultRouteStrategy {
pub fn new() -> Self {
Self {}
}
}
impl RouteStrategy for DefaultRouteStrategy {
fn route_cost(&mut self, route: &Route, path: &[VertexIndex]) -> u64 {
0
}
fn edge_cost(&mut self, route: &Route, edge: MeshEdgeReference) -> u64 {
1
}
fn estimate_cost(&mut self, route: &Route, vertex: VertexIndex) -> u64 {
0
}
}
struct RouterAstarStrategy<'a, RS: RouteStrategy> {
route: Route<'a>,
trace: Trace, trace: Trace,
to: VertexIndex, to: VertexIndex,
strategy: &'a mut RS, observer: &'a mut RO,
} }
impl<'a, RS: RouteStrategy> RouterAstarStrategy<'a, RS> { impl<'a, RO: RouterObserver> RouterAstarStrategy<'a, RO> {
pub fn new(route: Route<'a>, trace: Trace, to: VertexIndex, strategy: &'a mut RS) -> Self { pub fn new(tracer: Tracer<'a>, trace: Trace, to: VertexIndex, observer: &'a mut RO) -> Self {
Self { Self {
route, tracer,
trace, trace,
to, to,
strategy, observer,
} }
} }
} }
impl<'a, RS: RouteStrategy> AstarStrategy<&Mesh, u64> for RouterAstarStrategy<'a, RS> { impl<'a, RO: RouterObserver> AstarStrategy<&Mesh, u64> for RouterAstarStrategy<'a, RO> {
fn reroute(&mut self, vertex: VertexIndex, tracker: &PathTracker<&Mesh>) -> Option<u64> { fn is_goal(&mut self, vertex: VertexIndex, tracker: &PathTracker<&Mesh>) -> bool {
let new_path = tracker.reconstruct_path_to(vertex); let new_path = tracker.reconstruct_path_to(vertex);
self.route.rework_path(&mut self.trace, &new_path, 5.0); self.tracer.rework_path(&mut self.trace, &new_path, 5.0);
self.observer.on_rework(&self.tracer, &new_path);
if self.route.finish(&mut self.trace, self.to, 5.0).is_ok() { self.tracer.finish(&mut self.trace, self.to, 5.0).is_ok()
return None;
}
Some(self.strategy.route_cost(&self.route, &new_path))
} }
fn edge_cost(&mut self, edge: MeshEdgeReference) -> u64 { fn edge_cost(&mut self, edge: MeshEdgeReference) -> u64 {
self.strategy.edge_cost(&self.route, edge) self.observer.on_probe(&self.tracer, edge);
1
} }
fn estimate_cost(&mut self, vertex: VertexIndex) -> u64 { fn estimate_cost(&mut self, vertex: VertexIndex) -> u64 {
self.strategy.estimate_cost(&self.route, vertex) self.observer.on_estimate(&self.tracer, vertex);
0
} }
} }
@ -101,7 +73,7 @@ impl Router {
&mut self, &mut self,
from: DotIndex, from: DotIndex,
to: DotIndex, to: DotIndex,
strategy: &mut impl RouteStrategy, observer: &mut impl RouterObserver,
) -> Result<Mesh, InsertionError> { ) -> Result<Mesh, InsertionError> {
// XXX: Should we actually store the mesh? May be useful for debugging, but doesn't look // XXX: Should we actually store the mesh? May be useful for debugging, but doesn't look
// right. // right.
@ -109,13 +81,13 @@ impl Router {
let mut mesh = Mesh::new(); let mut mesh = Mesh::new();
mesh.triangulate(&self.layout)?; mesh.triangulate(&self.layout)?;
let mut route = self.route(&mesh); let mut tracer = self.tracer(&mesh);
let trace = route.start(mesh.vertex(from)); let trace = tracer.start(mesh.vertex(from));
let (_cost, path) = astar( let (_cost, path) = astar(
&mesh, &mesh,
mesh.vertex(from), mesh.vertex(from),
&mut RouterAstarStrategy::new(route, trace, mesh.vertex(to), strategy), &mut RouterAstarStrategy::new(tracer, trace, mesh.vertex(to), observer),
) )
.unwrap(); // TODO. .unwrap(); // TODO.
@ -126,7 +98,7 @@ impl Router {
&mut self, &mut self,
from: DotIndex, from: DotIndex,
to: Point, to: Point,
strategy: &mut impl RouteStrategy, observer: &mut impl RouterObserver,
) -> Result<Mesh, InsertionError> { ) -> Result<Mesh, InsertionError> {
let to_dot = if let Some(band) = self.layout.next_band(from) { let to_dot = if let Some(band) = self.layout.next_band(from) {
let to_dot = band.ends().1; let to_dot = band.ends().1;
@ -144,7 +116,7 @@ impl Router {
.unwrap() // TODO. .unwrap() // TODO.
}; };
self.enroute(from, to_dot, strategy) self.enroute(from, to_dot, observer)
} }
/*pub fn squeeze_around_dot( /*pub fn squeeze_around_dot(
@ -259,8 +231,8 @@ impl Router {
Ok(()) Ok(())
}*/ }*/
pub fn route<'a>(&'a mut self, mesh: &'a Mesh) -> Route { pub fn tracer<'a>(&'a mut self, mesh: &'a Mesh) -> Tracer {
Route::new(&mut self.layout, &self.rules, mesh) Tracer::new(&mut self.layout, &self.rules, mesh)
} }
/*pub fn routeedges(&self) -> impl Iterator<Item = (Point, Point)> + '_ { /*pub fn routeedges(&self) -> impl Iterator<Item = (Point, Point)> + '_ {

View File

@ -3,7 +3,7 @@ use contracts::debug_ensures;
use crate::{ use crate::{
draw::{BareHead, Draw, Head}, draw::{BareHead, Draw, Head},
layout::Layout, layout::Layout,
mesh::{Mesh, VertexIndex}, mesh::{Mesh, MeshEdgeReference, VertexIndex},
rules::Rules, rules::Rules,
}; };
@ -13,15 +13,15 @@ pub struct Trace {
head: Head, head: Head,
} }
pub struct Route<'a> { pub struct Tracer<'a> {
pub layout: &'a mut Layout, pub layout: &'a mut Layout,
pub rules: &'a Rules, pub rules: &'a Rules,
pub mesh: &'a Mesh, pub mesh: &'a Mesh,
} }
impl<'a> Route<'a> { impl<'a> Tracer<'a> {
pub fn new(layout: &'a mut Layout, rules: &'a Rules, mesh: &'a Mesh) -> Self { pub fn new(layout: &'a mut Layout, rules: &'a Rules, mesh: &'a Mesh) -> Self {
Route { Tracer {
layout, layout,
rules, rules,
mesh, mesh,