mirror of https://codeberg.org/topola/topola.git
router: Rename `Route` to `Tracer` and simplify related code
This commit is contained in:
parent
cc3b537b5c
commit
af61a6b120
81
src/astar.rs
81
src/astar.rs
|
|
@ -100,7 +100,7 @@ where
|
|||
K: Measure + Copy,
|
||||
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 estimate_cost(&mut self, node: G::NodeId) -> K;
|
||||
}
|
||||
|
|
@ -125,54 +125,51 @@ where
|
|||
visit_next.push(MinScored(strategy.estimate_cost(start), start));
|
||||
|
||||
while let Some(MinScored(estimate_score, node)) = visit_next.pop() {
|
||||
match strategy.reroute(node, &path_tracker) {
|
||||
None => {
|
||||
let path = path_tracker.reconstruct_path_to(node);
|
||||
let cost = scores[&node];
|
||||
return Some((cost, path));
|
||||
}
|
||||
Some(route_cost) => {
|
||||
// This lookup can be unwrapped without fear of panic since the node was
|
||||
// necessarily scored before adding it to `visit_next`.
|
||||
let node_score = scores[&node];
|
||||
if strategy.is_goal(node, &path_tracker) {
|
||||
let path = path_tracker.reconstruct_path_to(node);
|
||||
let cost = scores[&node];
|
||||
return Some((cost, path));
|
||||
}
|
||||
|
||||
match estimate_scores.entry(node) {
|
||||
Occupied(mut entry) => {
|
||||
// If the node has already been visited with an equal or lower score than
|
||||
// now, then we do not need to re-visit it.
|
||||
if *entry.get() <= estimate_score {
|
||||
continue;
|
||||
}
|
||||
entry.insert(estimate_score);
|
||||
}
|
||||
Vacant(entry) => {
|
||||
entry.insert(estimate_score);
|
||||
}
|
||||
// This lookup can be unwrapped without fear of panic since the node was
|
||||
// necessarily scored before adding it to `visit_next`.
|
||||
let node_score = scores[&node];
|
||||
|
||||
match estimate_scores.entry(node) {
|
||||
Occupied(mut entry) => {
|
||||
// If the node has already been visited with an equal or lower score than
|
||||
// now, then we do not need to re-visit it.
|
||||
if *entry.get() <= estimate_score {
|
||||
continue;
|
||||
}
|
||||
entry.insert(estimate_score);
|
||||
}
|
||||
Vacant(entry) => {
|
||||
entry.insert(estimate_score);
|
||||
}
|
||||
}
|
||||
|
||||
for edge in graph.edges(node) {
|
||||
let next = edge.target();
|
||||
let next_score = node_score + route_cost + strategy.edge_cost(edge);
|
||||
for edge in graph.edges(node) {
|
||||
let next = edge.target();
|
||||
let next_score = node_score + strategy.edge_cost(edge);
|
||||
|
||||
match scores.entry(next) {
|
||||
Occupied(mut entry) => {
|
||||
// No need to add neighbors that we have already reached through a
|
||||
// shorter path than now.
|
||||
if *entry.get() <= next_score {
|
||||
continue;
|
||||
}
|
||||
entry.insert(next_score);
|
||||
}
|
||||
Vacant(entry) => {
|
||||
entry.insert(next_score);
|
||||
}
|
||||
match scores.entry(next) {
|
||||
Occupied(mut entry) => {
|
||||
// No need to add neighbors that we have already reached through a
|
||||
// shorter path than now.
|
||||
if *entry.get() <= next_score {
|
||||
continue;
|
||||
}
|
||||
|
||||
path_tracker.set_predecessor(next, node);
|
||||
let next_estimate_score = next_score + strategy.estimate_cost(next);
|
||||
visit_next.push(MinScored(next_estimate_score, next));
|
||||
entry.insert(next_score);
|
||||
}
|
||||
Vacant(entry) => {
|
||||
entry.insert(next_score);
|
||||
}
|
||||
}
|
||||
|
||||
path_tracker.set_predecessor(next, node);
|
||||
let next_estimate_score = next_score + strategy.estimate_cost(next);
|
||||
visit_next.push(MinScored(next_estimate_score, next));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
44
src/main.rs
44
src/main.rs
|
|
@ -18,19 +18,18 @@ mod layout;
|
|||
mod math;
|
||||
mod mesh;
|
||||
mod primitive;
|
||||
mod route;
|
||||
mod router;
|
||||
mod rules;
|
||||
mod segbend;
|
||||
mod shape;
|
||||
mod tracer;
|
||||
|
||||
use geo::point;
|
||||
use graph::{DotIndex, SegWeight, Tag, TaggedIndex};
|
||||
use graph::{DotIndex, SegWeight};
|
||||
use layout::Layout;
|
||||
use mesh::{Mesh, MeshEdgeReference, VertexIndex};
|
||||
use petgraph::visit::{EdgeRef, IntoEdgeReferences};
|
||||
use route::Route;
|
||||
use router::{DefaultRouteStrategy, RouteStrategy};
|
||||
use router::RouterObserver;
|
||||
use sdl2::event::Event;
|
||||
use sdl2::gfx::primitives::DrawRenderer;
|
||||
use sdl2::keyboard::Keycode;
|
||||
|
|
@ -41,6 +40,7 @@ use sdl2::EventPump;
|
|||
use shape::Shape;
|
||||
use std::panic;
|
||||
use std::time::Duration;
|
||||
use tracer::Tracer;
|
||||
|
||||
use crate::graph::DotWeight;
|
||||
use crate::math::Circle;
|
||||
|
|
@ -52,48 +52,36 @@ enum RouterOrLayout<'a> {
|
|||
Layout(&'a Layout),
|
||||
}
|
||||
|
||||
struct DebugRouteStrategy<'a, RS: RouteStrategy> {
|
||||
strategy: RS,
|
||||
struct DebugRouterObserver<'a> {
|
||||
event_pump: &'a mut sdl2::EventPump,
|
||||
canvas: &'a mut sdl2::render::Canvas<Window>,
|
||||
}
|
||||
|
||||
impl<'a, RS: RouteStrategy> DebugRouteStrategy<'a, RS> {
|
||||
impl<'a> DebugRouterObserver<'a> {
|
||||
pub fn new(
|
||||
strategy: RS,
|
||||
event_pump: &'a mut sdl2::EventPump,
|
||||
canvas: &'a mut sdl2::render::Canvas<Window>,
|
||||
) -> Self {
|
||||
Self {
|
||||
strategy,
|
||||
event_pump,
|
||||
canvas,
|
||||
}
|
||||
Self { event_pump, canvas }
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, RS: RouteStrategy> RouteStrategy for DebugRouteStrategy<'a, RS> {
|
||||
fn route_cost(&mut self, route: &Route, path: &[VertexIndex]) -> u64 {
|
||||
impl<'a> RouterObserver for DebugRouterObserver<'a> {
|
||||
fn on_rework(&mut self, tracer: &Tracer, path: &[VertexIndex]) {
|
||||
render_times(
|
||||
self.event_pump,
|
||||
self.canvas,
|
||||
RouterOrLayout::Layout(route.layout),
|
||||
RouterOrLayout::Layout(tracer.layout),
|
||||
None,
|
||||
None,
|
||||
Some(route.mesh.clone()),
|
||||
Some(tracer.mesh.clone()),
|
||||
path,
|
||||
10,
|
||||
);
|
||||
self.strategy.route_cost(route, path)
|
||||
}
|
||||
|
||||
fn edge_cost(&mut self, route: &Route, edge: MeshEdgeReference) -> u64 {
|
||||
self.strategy.edge_cost(route, edge)
|
||||
}
|
||||
|
||||
fn estimate_cost(&mut self, route: &Route, vertex: VertexIndex) -> u64 {
|
||||
self.strategy.estimate_cost(route, vertex)
|
||||
}
|
||||
fn on_probe(&mut self, _tracer: &Tracer, _edge: MeshEdgeReference) {}
|
||||
fn on_estimate(&mut self, _tracer: &Tracer, _vertex: VertexIndex) {}
|
||||
}
|
||||
|
||||
fn main() {
|
||||
|
|
@ -304,11 +292,7 @@ fn render_times(
|
|||
.reroute(
|
||||
from,
|
||||
point! {x: state.x() as f64, y: state.y() as f64},
|
||||
&mut DebugRouteStrategy::new(
|
||||
DefaultRouteStrategy::new(),
|
||||
event_pump,
|
||||
canvas,
|
||||
),
|
||||
&mut DebugRouterObserver::new(event_pump, canvas),
|
||||
)
|
||||
.ok();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,91 +1,63 @@
|
|||
use geo::geometry::Point;
|
||||
use petgraph::visit::{EdgeRef, IntoEdgeReferences};
|
||||
use petgraph::visit::EdgeRef;
|
||||
use spade::InsertionError;
|
||||
|
||||
use crate::astar::{astar, AstarStrategy, PathTracker};
|
||||
use crate::bow::Bow;
|
||||
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::graph::{DotIndex, DotWeight, Ends};
|
||||
use crate::layout::Layout;
|
||||
|
||||
use crate::math::Circle;
|
||||
use crate::mesh::{Mesh, MeshEdgeReference, VertexIndex};
|
||||
use crate::route::{Route, Trace};
|
||||
use crate::rules::{Conditions, Rules};
|
||||
use crate::segbend::Segbend;
|
||||
use crate::rules::Rules;
|
||||
use crate::tracer::{Trace, Tracer};
|
||||
|
||||
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 layout: Layout,
|
||||
rules: Rules,
|
||||
}
|
||||
|
||||
pub trait RouteStrategy {
|
||||
fn route_cost(&mut self, route: &Route, path: &[VertexIndex]) -> u64;
|
||||
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>,
|
||||
struct RouterAstarStrategy<'a, RO: RouterObserver> {
|
||||
tracer: Tracer<'a>,
|
||||
trace: Trace,
|
||||
to: VertexIndex,
|
||||
strategy: &'a mut RS,
|
||||
observer: &'a mut RO,
|
||||
}
|
||||
|
||||
impl<'a, RS: RouteStrategy> RouterAstarStrategy<'a, RS> {
|
||||
pub fn new(route: Route<'a>, trace: Trace, to: VertexIndex, strategy: &'a mut RS) -> Self {
|
||||
impl<'a, RO: RouterObserver> RouterAstarStrategy<'a, RO> {
|
||||
pub fn new(tracer: Tracer<'a>, trace: Trace, to: VertexIndex, observer: &'a mut RO) -> Self {
|
||||
Self {
|
||||
route,
|
||||
tracer,
|
||||
trace,
|
||||
to,
|
||||
strategy,
|
||||
observer,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, RS: RouteStrategy> AstarStrategy<&Mesh, u64> for RouterAstarStrategy<'a, RS> {
|
||||
fn reroute(&mut self, vertex: VertexIndex, tracker: &PathTracker<&Mesh>) -> Option<u64> {
|
||||
impl<'a, RO: RouterObserver> AstarStrategy<&Mesh, u64> for RouterAstarStrategy<'a, RO> {
|
||||
fn is_goal(&mut self, vertex: VertexIndex, tracker: &PathTracker<&Mesh>) -> bool {
|
||||
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() {
|
||||
return None;
|
||||
}
|
||||
|
||||
Some(self.strategy.route_cost(&self.route, &new_path))
|
||||
self.tracer.finish(&mut self.trace, self.to, 5.0).is_ok()
|
||||
}
|
||||
|
||||
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 {
|
||||
self.strategy.estimate_cost(&self.route, vertex)
|
||||
self.observer.on_estimate(&self.tracer, vertex);
|
||||
0
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -101,7 +73,7 @@ impl Router {
|
|||
&mut self,
|
||||
from: DotIndex,
|
||||
to: DotIndex,
|
||||
strategy: &mut impl RouteStrategy,
|
||||
observer: &mut impl RouterObserver,
|
||||
) -> Result<Mesh, InsertionError> {
|
||||
// XXX: Should we actually store the mesh? May be useful for debugging, but doesn't look
|
||||
// right.
|
||||
|
|
@ -109,13 +81,13 @@ impl Router {
|
|||
let mut mesh = Mesh::new();
|
||||
mesh.triangulate(&self.layout)?;
|
||||
|
||||
let mut route = self.route(&mesh);
|
||||
let trace = route.start(mesh.vertex(from));
|
||||
let mut tracer = self.tracer(&mesh);
|
||||
let trace = tracer.start(mesh.vertex(from));
|
||||
|
||||
let (_cost, path) = astar(
|
||||
&mesh,
|
||||
mesh.vertex(from),
|
||||
&mut RouterAstarStrategy::new(route, trace, mesh.vertex(to), strategy),
|
||||
&mut RouterAstarStrategy::new(tracer, trace, mesh.vertex(to), observer),
|
||||
)
|
||||
.unwrap(); // TODO.
|
||||
|
||||
|
|
@ -126,7 +98,7 @@ impl Router {
|
|||
&mut self,
|
||||
from: DotIndex,
|
||||
to: Point,
|
||||
strategy: &mut impl RouteStrategy,
|
||||
observer: &mut impl RouterObserver,
|
||||
) -> Result<Mesh, InsertionError> {
|
||||
let to_dot = if let Some(band) = self.layout.next_band(from) {
|
||||
let to_dot = band.ends().1;
|
||||
|
|
@ -144,7 +116,7 @@ impl Router {
|
|||
.unwrap() // TODO.
|
||||
};
|
||||
|
||||
self.enroute(from, to_dot, strategy)
|
||||
self.enroute(from, to_dot, observer)
|
||||
}
|
||||
|
||||
/*pub fn squeeze_around_dot(
|
||||
|
|
@ -259,8 +231,8 @@ impl Router {
|
|||
Ok(())
|
||||
}*/
|
||||
|
||||
pub fn route<'a>(&'a mut self, mesh: &'a Mesh) -> Route {
|
||||
Route::new(&mut self.layout, &self.rules, mesh)
|
||||
pub fn tracer<'a>(&'a mut self, mesh: &'a Mesh) -> Tracer {
|
||||
Tracer::new(&mut self.layout, &self.rules, mesh)
|
||||
}
|
||||
|
||||
/*pub fn routeedges(&self) -> impl Iterator<Item = (Point, Point)> + '_ {
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ use contracts::debug_ensures;
|
|||
use crate::{
|
||||
draw::{BareHead, Draw, Head},
|
||||
layout::Layout,
|
||||
mesh::{Mesh, VertexIndex},
|
||||
mesh::{Mesh, MeshEdgeReference, VertexIndex},
|
||||
rules::Rules,
|
||||
};
|
||||
|
||||
|
|
@ -13,15 +13,15 @@ pub struct Trace {
|
|||
head: Head,
|
||||
}
|
||||
|
||||
pub struct Route<'a> {
|
||||
pub struct Tracer<'a> {
|
||||
pub layout: &'a mut Layout,
|
||||
pub rules: &'a Rules,
|
||||
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 {
|
||||
Route {
|
||||
Tracer {
|
||||
layout,
|
||||
rules,
|
||||
mesh,
|
||||
Loading…
Reference in New Issue