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,
|
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,54 +125,51 @@ 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
|
|
||||||
// necessarily scored before adding it to `visit_next`.
|
|
||||||
let node_score = scores[&node];
|
|
||||||
|
|
||||||
match estimate_scores.entry(node) {
|
// This lookup can be unwrapped without fear of panic since the node was
|
||||||
Occupied(mut entry) => {
|
// necessarily scored before adding it to `visit_next`.
|
||||||
// If the node has already been visited with an equal or lower score than
|
let node_score = scores[&node];
|
||||||
// now, then we do not need to re-visit it.
|
|
||||||
if *entry.get() <= estimate_score {
|
match estimate_scores.entry(node) {
|
||||||
continue;
|
Occupied(mut entry) => {
|
||||||
}
|
// If the node has already been visited with an equal or lower score than
|
||||||
entry.insert(estimate_score);
|
// now, then we do not need to re-visit it.
|
||||||
}
|
if *entry.get() <= estimate_score {
|
||||||
Vacant(entry) => {
|
continue;
|
||||||
entry.insert(estimate_score);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
entry.insert(estimate_score);
|
||||||
|
}
|
||||||
|
Vacant(entry) => {
|
||||||
|
entry.insert(estimate_score);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
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) => {
|
||||||
// No need to add neighbors that we have already reached through a
|
// No need to add neighbors that we have already reached through a
|
||||||
// shorter path than now.
|
// shorter path than now.
|
||||||
if *entry.get() <= next_score {
|
if *entry.get() <= next_score {
|
||||||
continue;
|
continue;
|
||||||
}
|
|
||||||
entry.insert(next_score);
|
|
||||||
}
|
|
||||||
Vacant(entry) => {
|
|
||||||
entry.insert(next_score);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
entry.insert(next_score);
|
||||||
path_tracker.set_predecessor(next, node);
|
}
|
||||||
let next_estimate_score = next_score + strategy.estimate_cost(next);
|
Vacant(entry) => {
|
||||||
visit_next.push(MinScored(next_estimate_score, next));
|
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 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();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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)> + '_ {
|
||||||
|
|
|
||||||
|
|
@ -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,
|
||||||
Loading…
Reference in New Issue