diff --git a/src/band.rs b/src/band.rs index 500960e..b2a604c 100644 --- a/src/band.rs +++ b/src/band.rs @@ -12,25 +12,52 @@ pub struct Band { } impl Band { - pub fn new( - from: DotIndex, - to: DotIndex, + pub fn from_dot_prev( + dot: DotIndex, graph: &StableDiGraph, - ) -> Self { - let mut this = Self { - from, - to, - interior: vec![], - }; - let mut prev_index = from.tag(); + ) -> Option { + let mut next_index = dot.tag(); + let mut interior = vec![]; + + while let Some(index) = untag!(next_index, Primitive::new(next_index, graph).tagged_next()) + { + 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, + ) -> Option { + let mut prev_index = dot.tag(); + let mut interior = vec![]; while let Some(index) = untag!(prev_index, Primitive::new(prev_index, graph).tagged_next()) { - this.interior.push(index); + interior.push(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 for Band { (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, - index: TaggedIndex, -} - -impl<'a> Iterator for BandIterator<'a> { - type Item = TaggedIndex; - - fn next(&mut self) -> Option { - 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) -> Self::Iter { - BandIterator { - graph, - index: self.from.tag(), - } - } -} - -impl Ends for Band { - fn ends(&self) -> (DotIndex, DotIndex) { - (self.from, self.to) - } -}*/ diff --git a/src/layout.rs b/src/layout.rs index 1582a78..fe2851e 100644 --- a/src/layout.rs +++ b/src/layout.rs @@ -207,8 +207,12 @@ impl Layout { Segbend::from_dot_next(dot, &self.graph) } - pub fn band(&self, from: DotIndex, to: DotIndex) -> Band { - Band::new(from, to, &self.graph) + pub fn prev_band(&self, to: DotIndex) -> Option { + Band::from_dot_prev(to, &self.graph) + } + + pub fn next_band(&self, from: DotIndex) -> Option { + Band::from_dot_next(from, &self.graph) } #[debug_ensures(ret.is_ok() -> self.graph.node_count() == old(self.graph.node_count()))] diff --git a/src/main.rs b/src/main.rs index 2dc3dbe..f4698ba 100644 --- a/src/main.rs +++ b/src/main.rs @@ -24,7 +24,8 @@ mod rules; mod segbend; mod shape; -use graph::{SegWeight, Tag, TaggedIndex}; +use geo::point; +use graph::{DotIndex, SegWeight, Tag, TaggedIndex}; use layout::Layout; use mesh::{MeshEdgeReference, VertexIndex}; use route::Route; @@ -44,6 +45,12 @@ use crate::graph::DotWeight; use crate::math::Circle; 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> { strategy: RS, 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> { 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) } @@ -258,28 +272,37 @@ fn main() { let head = router.draw_around_dot(head, dot6, false, 5.0).unwrap(); let _ = router.draw_finish(head, dot7, 5.0);*/ - let _ = router.enroute( + /*let _ = router.enroute( dot1_1, dot1_2, 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( &mut event_pump, &mut canvas, - &router.layout, - Some(barrier1_dot1.tag()), + RouterOrLayout::Router(&mut router), + Some(dot1_1), + Some(dot1_2), + -1, + ); + render_times( + &mut event_pump, + &mut canvas, + RouterOrLayout::Layout(&router.layout), + None, + None, -1, ); - render_times(&mut event_pump, &mut canvas, &router.layout, None, -1); } fn render_times( event_pump: &mut EventPump, canvas: &mut Canvas, - layout: &Layout, - follower: Option, + mut router_or_layout: RouterOrLayout, + from: Option, + follower: Option, times: i64, ) { let mut i = 0; @@ -299,14 +322,29 @@ fn render_times( } } - if let Some(follower) = follower { - let state = event_pump.mouse_state(); + let layout = match router_or_layout { + RouterOrLayout::Router(ref mut router) => { + if let Some(follower) = follower { + let state = event_pump.mouse_state(); - /*let _ = router.move_dot( - *follower.as_dot().unwrap(), - (state.x() as f64, state.y() as f64).into(), - );*/ - } + /*let _ = router.layout.move_dot( + *follower.as_dot().unwrap(), + (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(|| { for shape in layout.shapes() { diff --git a/src/router.rs b/src/router.rs index 05852ad..9b58214 100644 --- a/src/router.rs +++ b/src/router.rs @@ -53,11 +53,11 @@ struct RouterAstarStrategy<'a, RS: RouteStrategy> { route: Route<'a>, trace: Trace, to: VertexIndex, - strategy: RS, + strategy: &'a mut 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 { route, trace, @@ -101,7 +101,7 @@ impl Router { &mut self, from: DotIndex, to: DotIndex, - strategy: impl RouteStrategy, + strategy: &mut impl RouteStrategy, ) -> Result<(), InsertionError> { // XXX: Should we actually store the mesh? May be useful for debugging, but doesn't look // right. @@ -121,6 +121,31 @@ impl Router { 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( &mut self, head: Head,