router: Implement basic cursor following

This commit is contained in:
Mikolaj Wielgus 2023-10-06 22:41:59 +00:00
parent 0e8a6d6e42
commit 7a06a9b02d
4 changed files with 127 additions and 87 deletions

View File

@ -12,25 +12,52 @@ pub struct Band {
} }
impl Band { impl Band {
pub fn new( pub fn from_dot_prev(
from: DotIndex, dot: DotIndex,
to: DotIndex,
graph: &StableDiGraph<TaggedWeight, Label, usize>, graph: &StableDiGraph<TaggedWeight, Label, usize>,
) -> Self { ) -> Option<Self> {
let mut this = Self { let mut next_index = dot.tag();
from, let mut interior = vec![];
to,
interior: vec![], while let Some(index) = untag!(next_index, Primitive::new(next_index, graph).tagged_next())
}; {
let mut prev_index = from.tag(); interior.push(index);
next_index = index;
}
if interior.is_empty() {
None
} else {
Some(Self {
from: *interior.pop().unwrap().as_dot().unwrap(),
to: dot,
interior,
})
}
}
pub fn from_dot_next(
dot: DotIndex,
graph: &StableDiGraph<TaggedWeight, Label, usize>,
) -> Option<Self> {
let mut prev_index = dot.tag();
let mut interior = vec![];
while let Some(index) = untag!(prev_index, Primitive::new(prev_index, graph).tagged_next()) while let Some(index) = untag!(prev_index, Primitive::new(prev_index, graph).tagged_next())
{ {
this.interior.push(index); interior.push(index);
prev_index = index; prev_index = index;
} }
this if interior.is_empty() {
None
} else {
Some(Self {
from: dot,
to: *interior.pop().unwrap().as_dot().unwrap(),
interior,
})
}
} }
} }
@ -46,57 +73,3 @@ impl Ends<DotIndex, DotIndex> for Band {
(self.from, self.to) (self.from, self.to)
} }
} }
/*use petgraph::stable_graph::StableDiGraph;
use crate::{
graph::{DotIndex, Ends, Interior, Label, Tag, TaggedIndex, TaggedWeight},
primitive::Primitive,
};
pub struct Band {
from: DotIndex,
to: DotIndex,
}
impl Band {
pub fn new(from: DotIndex, to: DotIndex) -> Self {
Self { from, to }
}
}
struct BandIterator<'a> {
graph: &'a StableDiGraph<TaggedWeight, Label, usize>,
index: TaggedIndex,
}
impl<'a> Iterator for BandIterator<'a> {
type Item = TaggedIndex;
fn next(&mut self) -> Option<Self::Item> {
let index = self.index;
let next_index = untag!(index, Primitive::new(index, self.graph).tagged_next());
if let Some(next_index) = next_index {
self.index = next_index;
}
next_index
}
}
impl<'a> Interior<'a, TaggedIndex> for Band {
type Iter = BandIterator<'a>;
fn interior(&self, graph: &'a StableDiGraph<TaggedWeight, Label, usize>) -> Self::Iter {
BandIterator {
graph,
index: self.from.tag(),
}
}
}
impl Ends<DotIndex, DotIndex> for Band {
fn ends(&self) -> (DotIndex, DotIndex) {
(self.from, self.to)
}
}*/

View File

@ -207,8 +207,12 @@ impl Layout {
Segbend::from_dot_next(dot, &self.graph) Segbend::from_dot_next(dot, &self.graph)
} }
pub fn band(&self, from: DotIndex, to: DotIndex) -> Band { pub fn prev_band(&self, to: DotIndex) -> Option<Band> {
Band::new(from, to, &self.graph) Band::from_dot_prev(to, &self.graph)
}
pub fn next_band(&self, from: DotIndex) -> Option<Band> {
Band::from_dot_next(from, &self.graph)
} }
#[debug_ensures(ret.is_ok() -> self.graph.node_count() == old(self.graph.node_count()))] #[debug_ensures(ret.is_ok() -> self.graph.node_count() == old(self.graph.node_count()))]

View File

@ -24,7 +24,8 @@ mod rules;
mod segbend; mod segbend;
mod shape; mod shape;
use graph::{SegWeight, Tag, TaggedIndex}; use geo::point;
use graph::{DotIndex, SegWeight, Tag, TaggedIndex};
use layout::Layout; use layout::Layout;
use mesh::{MeshEdgeReference, VertexIndex}; use mesh::{MeshEdgeReference, VertexIndex};
use route::Route; use route::Route;
@ -44,6 +45,12 @@ use crate::graph::DotWeight;
use crate::math::Circle; use crate::math::Circle;
use crate::router::Router; use crate::router::Router;
// Clunky enum to work around borrow checker.
enum RouterOrLayout<'a> {
Router(&'a mut Router),
Layout(&'a Layout),
}
struct DebugRouteStrategy<'a, RS: RouteStrategy> { struct DebugRouteStrategy<'a, RS: RouteStrategy> {
strategy: RS, strategy: RS,
event_pump: &'a mut sdl2::EventPump, event_pump: &'a mut sdl2::EventPump,
@ -66,7 +73,14 @@ impl<'a, RS: RouteStrategy> DebugRouteStrategy<'a, RS> {
impl<'a, RS: RouteStrategy> RouteStrategy for DebugRouteStrategy<'a, RS> { impl<'a, RS: RouteStrategy> RouteStrategy for DebugRouteStrategy<'a, RS> {
fn route_cost(&mut self, route: &Route, path: &[VertexIndex]) -> u64 { fn route_cost(&mut self, route: &Route, path: &[VertexIndex]) -> u64 {
render_times(self.event_pump, self.canvas, route.layout, None, 25); render_times(
self.event_pump,
self.canvas,
RouterOrLayout::Layout(route.layout),
None,
None,
25,
);
self.strategy.route_cost(route, path) self.strategy.route_cost(route, path)
} }
@ -258,28 +272,37 @@ fn main() {
let head = router.draw_around_dot(head, dot6, false, 5.0).unwrap(); let head = router.draw_around_dot(head, dot6, false, 5.0).unwrap();
let _ = router.draw_finish(head, dot7, 5.0);*/ let _ = router.draw_finish(head, dot7, 5.0);*/
let _ = router.enroute( /*let _ = router.enroute(
dot1_1, dot1_1,
dot1_2, dot1_2,
DebugRouteStrategy::new(DefaultRouteStrategy::new(), &mut event_pump, &mut canvas), DebugRouteStrategy::new(DefaultRouteStrategy::new(), &mut event_pump, &mut canvas),
); );
render_times(&mut event_pump, &mut canvas, &router.layout, None, -1); render_times(&mut event_pump, &mut canvas, &router.layout, None, -1);*/
render_times( render_times(
&mut event_pump, &mut event_pump,
&mut canvas, &mut canvas,
&router.layout, RouterOrLayout::Router(&mut router),
Some(barrier1_dot1.tag()), Some(dot1_1),
Some(dot1_2),
-1,
);
render_times(
&mut event_pump,
&mut canvas,
RouterOrLayout::Layout(&router.layout),
None,
None,
-1, -1,
); );
render_times(&mut event_pump, &mut canvas, &router.layout, None, -1);
} }
fn render_times( fn render_times(
event_pump: &mut EventPump, event_pump: &mut EventPump,
canvas: &mut Canvas<Window>, canvas: &mut Canvas<Window>,
layout: &Layout, mut router_or_layout: RouterOrLayout,
follower: Option<TaggedIndex>, from: Option<DotIndex>,
follower: Option<DotIndex>,
times: i64, times: i64,
) { ) {
let mut i = 0; let mut i = 0;
@ -299,14 +322,29 @@ fn render_times(
} }
} }
if let Some(follower) = follower { let layout = match router_or_layout {
let state = event_pump.mouse_state(); RouterOrLayout::Router(ref mut router) => {
if let Some(follower) = follower {
let state = event_pump.mouse_state();
/*let _ = router.move_dot( /*let _ = router.layout.move_dot(
*follower.as_dot().unwrap(), *follower.as_dot().unwrap(),
(state.x() as f64, state.y() as f64).into(), (state.x() as f64, state.y() as f64).into(),
);*/ );*/
}
if let Some(from) = from {
router.reroute(
from,
point! {x: state.x() as f64, y: state.y() as f64},
&mut DefaultRouteStrategy::new(),
);
}
}
&router.layout
}
RouterOrLayout::Layout(layout) => layout,
};
let result = panic::catch_unwind(|| { let result = panic::catch_unwind(|| {
for shape in layout.shapes() { for shape in layout.shapes() {

View File

@ -53,11 +53,11 @@ struct RouterAstarStrategy<'a, RS: RouteStrategy> {
route: Route<'a>, route: Route<'a>,
trace: Trace, trace: Trace,
to: VertexIndex, to: VertexIndex,
strategy: RS, strategy: &'a mut RS,
} }
impl<'a, RS: RouteStrategy> RouterAstarStrategy<'a, RS> { impl<'a, RS: RouteStrategy> RouterAstarStrategy<'a, RS> {
pub fn new(route: Route<'a>, trace: Trace, to: VertexIndex, strategy: RS) -> Self { pub fn new(route: Route<'a>, trace: Trace, to: VertexIndex, strategy: &'a mut RS) -> Self {
Self { Self {
route, route,
trace, trace,
@ -101,7 +101,7 @@ impl Router {
&mut self, &mut self,
from: DotIndex, from: DotIndex,
to: DotIndex, to: DotIndex,
strategy: impl RouteStrategy, strategy: &mut impl RouteStrategy,
) -> Result<(), InsertionError> { ) -> Result<(), 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.
@ -121,6 +121,31 @@ impl Router {
Ok(()) Ok(())
} }
pub fn reroute(
&mut self,
from: DotIndex,
to: Point,
strategy: &mut impl RouteStrategy,
) -> Result<(), InsertionError> {
let to_dot = if let Some(band) = self.layout.next_band(from) {
let to_dot = band.ends().1;
self.layout.remove_interior(&band);
self.layout.move_dot(to_dot, to);
to_dot
} else {
let from_weight = self.layout.primitive(from).weight();
self.layout
.add_dot(DotWeight {
net: from_weight.net,
circle: Circle { pos: to, r: 2.0 },
})
.unwrap() // TODO.
};
self.enroute(from, to_dot, strategy)
}
/*pub fn squeeze_around_dot( /*pub fn squeeze_around_dot(
&mut self, &mut self,
head: Head, head: Head,