From 1d5b428bf9f0e542c4e6a167cb5841d7fc8d44b7 Mon Sep 17 00:00:00 2001 From: Mikolaj Wielgus Date: Wed, 30 Aug 2023 06:32:01 +0200 Subject: [PATCH] Split out drawing routines from `Router` into `Draw` --- src/astar.rs | 2 +- src/draw.rs | 204 +++++++++++++++++++++++++++++++++++++++ src/main.rs | 2 +- src/router.rs | 257 +++++++++++--------------------------------------- 4 files changed, 260 insertions(+), 205 deletions(-) create mode 100644 src/draw.rs diff --git a/src/astar.rs b/src/astar.rs index 6dc0254..f344771 100644 --- a/src/astar.rs +++ b/src/astar.rs @@ -81,7 +81,7 @@ where self.came_from.insert(node, previous); } - fn reconstruct_path_to(&self, last: G::NodeId) -> Vec { + pub fn reconstruct_path_to(&self, last: G::NodeId) -> Vec { let mut path = vec![last]; let mut current = last; diff --git a/src/draw.rs b/src/draw.rs new file mode 100644 index 0000000..4d4f321 --- /dev/null +++ b/src/draw.rs @@ -0,0 +1,204 @@ +use geo::Point; + +use crate::{ + graph::{BendIndex, BendWeight, DotIndex, DotWeight, Ends, SegIndex, SegWeight, TaggedIndex}, + guide::Guide, + layout::Layout, + math::Circle, + router::Head, + rules::{Conditions, Rules}, + segbend::Segbend, +}; + +pub struct Draw<'a> { + layout: &'a mut Layout, + rules: &'a Rules, +} + +impl<'a> Draw<'a> { + pub fn new(layout: &'a mut Layout, rules: &'a Rules) -> Self { + Self { layout, rules } + } + + pub fn start(&mut self, from: DotIndex) -> Head { + Head { + dot: from, + segbend: self.layout.prev_segbend(from), + } + } + + pub fn finish(&mut self, head: Head, into: DotIndex, width: f64) -> Result<(), ()> { + if let Some(bend) = self.layout.primitive(into).bend() { + self.finish_in_bend(head, bend, into, width)?; + } else { + self.finish_in_dot(head, into, width)?; + } + + Ok(()) + } + + fn finish_in_dot(&mut self, head: Head, into: DotIndex, width: f64) -> Result<(), ()> { + let tangent = self + .guide(&Default::default()) + .head_into_dot_segment(&head, into, width); + let head = self.extend_head(head, tangent.start_point())?; + + let net = self.layout.primitive(head.dot).weight().net; + self.layout + .add_seg(head.dot, into, SegWeight { net, width })?; + Ok(()) + } + + fn finish_in_bend( + &mut self, + head: Head, + into_bend: BendIndex, + into: DotIndex, + width: f64, + ) -> Result<(), ()> { + let to_head = Head { + dot: into, + segbend: self.layout.next_segbend(into), + }; + let to_cw = self.guide(&Default::default()).head_cw(&to_head).unwrap(); + let tangent = self + .guide(&Default::default()) + .head_around_bend_segment(&head, into_bend, to_cw, width); + + let head = self.extend_head(head, tangent.start_point())?; + let _to_head = self.extend_head(to_head, tangent.end_point())?; + + let net = self.layout.primitive(head.dot).weight().net; + self.layout + .add_seg(head.dot, into, SegWeight { net, width })?; + Ok(()) + } + + pub fn segbend_around_dot( + &mut self, + mut head: Head, + around: DotIndex, + cw: bool, + width: f64, + ) -> Result { + let tangent = self + .guide(&Default::default()) + .head_around_dot_segment(&head, around, cw, width); + + head = self.extend_head(head, tangent.start_point())?; + self.segbend( + head, + TaggedIndex::Dot(around), + tangent.end_point(), + cw, + width, + ) + } + + pub fn segbend_around_bend( + &mut self, + mut head: Head, + around: BendIndex, + cw: bool, + width: f64, + ) -> Result { + let tangent = self + .guide(&Default::default()) + .head_around_bend_segment(&head, around, cw, width); + + head = self.extend_head(head, tangent.start_point())?; + self.segbend( + head, + TaggedIndex::Bend(around), + tangent.end_point(), + cw, + width, + ) + } + + fn extend_head(&mut self, head: Head, to: Point) -> Result { + if let Some(..) = head.segbend { + self.extend_head_bend(head, to) + } else { + Ok(head) + // No assertion for now because we temporarily use floats. + + //println!("{:?} {:?}", self.layout.weight(TaggedIndex::Dot(from)).as_dot().unwrap().circle.pos, to); + //assert!(self.layout.weight(TaggedIndex::Dot(from)).as_dot().unwrap().circle.pos == to); + } + } + + fn extend_head_bend(&mut self, head: Head, to: Point) -> Result { + self.layout + .extend_bend(head.segbend.as_ref().unwrap().bend, head.dot, to)?; + Ok(head) + } + + fn segbend( + &mut self, + head: Head, + around: TaggedIndex, + to: Point, + cw: bool, + width: f64, + ) -> Result { + let (head, seg) = self.seg(head, to, width)?; + let dot = head.dot; + let bend_to = self + .layout + .add_dot(self.layout.primitive(head.dot).weight())?; + let net = self.layout.primitive(head.dot).weight().net; + + let bend = self + .layout + .add_bend(head.dot, bend_to, around, BendWeight { net, cw })?; + Ok(Head { + dot: bend_to, + segbend: Some(Segbend { bend, dot, seg }), + }) + } + + pub fn undo_segbend(&mut self, head: Head) -> Option { + let segbend = head.segbend.unwrap(); + + self.layout + .primitive(segbend.ends().0) + .prev() + .map(|prev_dot| { + self.layout.remove_interior(&segbend); + + Head { + dot: prev_dot, + segbend: self.layout.prev_segbend(prev_dot), + } + }) + } + + fn seg(&mut self, head: Head, to: Point, width: f64) -> Result<(Head, SegIndex), ()> { + let net = self.layout.primitive(head.dot).weight().net; + + assert!(width <= self.layout.primitive(head.dot).weight().circle.r * 2.0); + + let to_index = self.layout.add_dot(DotWeight { + net, + circle: Circle { + pos: to, + r: width / 2.0, + }, + })?; + let seg = self + .layout + .add_seg(head.dot, to_index, SegWeight { net, width })?; + Ok(( + Head { + dot: to_index, + segbend: None, + }, + seg, + )) + } + + fn guide(&'a self, conditions: &'a Conditions) -> Guide { + Guide::new(self.layout, self.rules, conditions) + } +} diff --git a/src/main.rs b/src/main.rs index a103847..6074a3f 100644 --- a/src/main.rs +++ b/src/main.rs @@ -11,6 +11,7 @@ macro_rules! dbg_dot { mod graph; mod astar; mod bow; +mod draw; mod guide; mod layout; mod math; @@ -21,7 +22,6 @@ mod rules; mod segbend; mod shape; - use graph::{Tag, TaggedIndex}; use sdl2::event::Event; use sdl2::gfx::primitives::DrawRenderer; diff --git a/src/router.rs b/src/router.rs index 6b2c242..6d18e03 100644 --- a/src/router.rs +++ b/src/router.rs @@ -4,6 +4,7 @@ use spade::InsertionError; use crate::astar::astar; use crate::bow::Bow; +use crate::draw::Draw; use crate::graph::{BendIndex, DotIndex, Ends, SegIndex, TaggedIndex}; use crate::graph::{BendWeight, DotWeight, SegWeight}; use crate::guide::Guide; @@ -48,7 +49,11 @@ impl Router { let (_cost, mesh_path) = astar( &self.mesh, self.mesh.vertex(from), - |node, _tracker| (node != self.mesh.vertex(to)).then_some(0), + |node, tracker| { + let new_path = tracker.reconstruct_path_to(node); + + (node != self.mesh.vertex(to)).then_some(0) + }, |_edge| 1, |_| 0, ) @@ -59,113 +64,67 @@ impl Router { .map(|vertex| self.mesh.dot(*vertex)) .collect(); - self.route_path(&path[..], 5.0).unwrap(); // TODO. + let mut route = self.route_start(path[0], 5.0); + route = self.route_path(route, &path[1..(path.len() - 1)]).unwrap(); // TODO. + let _ = self.route_finish(route, path[path.len() - 1]); Ok(()) } - fn route_path(&mut self, path: &[DotIndex], width: f64) -> Result<(), ()> { - let mut route = self.route_start(path[0], width); - - for dot in &path[1..(path.len() - 1)] { - route = self.route_step(route, *dot)?; - } - - self.route_finish(route, path[path.len() - 1]) - } - fn route_start(&mut self, from: DotIndex, width: f64) -> Route { Route { path: vec![], - head: self.draw_start(from), + head: self.draw().start(from), width, } } fn route_finish(&mut self, route: Route, into: DotIndex) -> Result<(), ()> { - self.draw_finish(route.head, into, route.width)?; + self.draw().finish(route.head, into, route.width)?; Ok(()) } + fn route_path(&mut self, mut route: Route, path: &[DotIndex]) -> Result { + for dot in path { + route = self.route_step(route, *dot)?; + } + + Ok(route) + } + + fn reroute_path(&mut self, mut route: Route, path: &[DotIndex]) -> Result { + let prefix_length = route + .path + .iter() + .zip(path) + .take_while(|(vertex, dot)| **vertex == self.mesh.vertex(**dot)) + .count(); + + let length = route.path.len(); + route = self.unroute_steps(route, length - prefix_length)?; + route = self.route_path(route, &path[prefix_length..])?; + Ok(route) + } + fn unroute_step(&mut self, mut route: Route) -> Result { - route.head = self.undraw_segbend(route.head).unwrap(); + route.head = self.draw().undo_segbend(route.head).unwrap(); route.path.pop(); Ok(route) } - fn route_step(&mut self, mut route: Route, to: DotIndex) -> Result { - route.head = self.draw_around_dot(route.head, to, true, route.width)?; - route.path.push(self.mesh.vertex(to)); + fn unroute_steps(&mut self, mut route: Route, step_count: usize) -> Result { + for _ in 0..step_count { + route = self.unroute_step(route)?; + } Ok(route) } - pub fn undraw_segbend(&mut self, head: Head) -> Option { - let segbend = head.segbend.unwrap(); - - if let Some(prev_dot) = self.layout.primitive(segbend.ends().0).prev() { - self.layout.remove_interior(&segbend); - - Some(Head { - dot: prev_dot, - segbend: self.layout.prev_segbend(prev_dot), - }) - } else { - None - } - } - - pub fn draw_start(&mut self, from: DotIndex) -> Head { - Head { - dot: from, - segbend: self.layout.prev_segbend(from), - } - } - - pub fn draw_finish(&mut self, head: Head, into: DotIndex, width: f64) -> Result<(), ()> { - if let Some(bend) = self.layout.primitive(into).bend() { - self.draw_finish_in_bend(head, bend, into, width)?; - } else { - self.draw_finish_in_dot(head, into, width)?; - } - - Ok(()) - } - - fn draw_finish_in_dot(&mut self, head: Head, into: DotIndex, width: f64) -> Result<(), ()> { - let tangent = self - .guide(&Default::default()) - .head_into_dot_segment(&head, into, width); - let head = self.extend_head(head, tangent.start_point())?; - - let net = self.layout.primitive(head.dot).weight().net; - self.layout - .add_seg(head.dot, into, SegWeight { net, width })?; - Ok(()) - } - - fn draw_finish_in_bend( - &mut self, - head: Head, - into_bend: BendIndex, - into: DotIndex, - width: f64, - ) -> Result<(), ()> { - let to_head = Head { - dot: into, - segbend: self.layout.next_segbend(into), - }; - let to_cw = self.guide(&Default::default()).head_cw(&to_head).unwrap(); - let tangent = self - .guide(&Default::default()) - .head_around_bend_segment(&head, into_bend, to_cw, width); - - let head = self.extend_head(head, tangent.start_point())?; - let _to_head = self.extend_head(to_head, tangent.end_point())?; - - let net = self.layout.primitive(head.dot).weight().net; - self.layout - .add_seg(head.dot, into, SegWeight { net, width })?; - Ok(()) + fn route_step(&mut self, mut route: Route, to: DotIndex) -> Result { + route.head = self + .draw() + .segbend_around_dot(route.head, to, true, route.width)?; + route.path.push(self.mesh.vertex(to)); + Ok(route) } pub fn squeeze_around_dot( @@ -176,7 +135,7 @@ impl Router { width: f64, ) -> Result { let outer = self.layout.primitive(around).outer().unwrap(); - let head = self.draw_around_dot(head, around, cw, width)?; + let head = self.draw().segbend_around_dot(head, around, cw, width)?; self.layout .reattach_bend(outer, head.segbend.as_ref().unwrap().bend); @@ -184,27 +143,6 @@ impl Router { Ok(head) } - pub fn draw_around_dot( - &mut self, - head: Head, - around: DotIndex, - cw: bool, - width: f64, - ) -> Result { - let tangent = self - .guide(&Default::default()) - .head_around_dot_segment(&head, around, cw, width); - - let head = self.extend_head(head, tangent.start_point())?; - self.draw_segbend( - head, - TaggedIndex::Dot(around), - tangent.end_point(), - cw, - width, - ) - } - pub fn squeeze_around_bend( &mut self, head: Head, @@ -213,7 +151,7 @@ impl Router { width: f64, ) -> Result { let outer = self.layout.primitive(around).outer().unwrap(); - let head = self.draw_around_bend(head, around, cw, width)?; + let head = self.draw().segbend_around_bend(head, around, cw, width)?; self.layout .reattach_bend(outer, head.segbend.as_ref().unwrap().bend); @@ -221,51 +159,6 @@ impl Router { Ok(head) } - pub fn draw_around_bend( - &mut self, - head: Head, - around: BendIndex, - cw: bool, - width: f64, - ) -> Result { - let tangent = self - .guide(&Default::default()) - .head_around_bend_segment(&head, around, cw, width); - - let head = self.extend_head(head, tangent.start_point())?; - self.draw_segbend( - head, - TaggedIndex::Bend(around), - tangent.end_point(), - cw, - width, - ) - } - - fn draw_segbend( - &mut self, - head: Head, - around: TaggedIndex, - to: Point, - cw: bool, - width: f64, - ) -> Result { - let (head, seg) = self.draw_seg(head, to, width)?; - let dot = head.dot; - let bend_to = self - .layout - .add_dot(self.layout.primitive(head.dot).weight())?; - let net = self.layout.primitive(head.dot).weight().net; - - let bend = self - .layout - .add_bend(head.dot, bend_to, around, BendWeight { net, cw })?; - Ok(Head { - dot: bend_to, - segbend: Some(Segbend { bend, dot, seg }), - }) - } - fn reroute_outward(&mut self, bend: BendIndex) -> Result<(), ()> { let mut bows: Vec = vec![]; let cw = self.layout.primitive(bend).weight().cw; @@ -289,47 +182,23 @@ impl Router { for bow in &bows { let ends = bow.ends(); - let mut head = self.draw_start(ends.0); + let mut head = self.draw().start(ends.0); let width = 5.0; if let Some(inner) = maybe_inner { - head = self.draw_around_bend(head, inner, cw, width)?; + head = self.draw().segbend_around_bend(head, inner, cw, width)?; } else { - head = self.draw_around_dot(head, core, cw, width)?; + head = self.draw().segbend_around_dot(head, core, cw, width)?; } maybe_inner = head.segbend.as_ref().map(|segbend| segbend.bend); - self.draw_finish(head, ends.1, width)?; + self.draw().finish(head, ends.1, width)?; self.relax_band(maybe_inner.unwrap()); } Ok(()) } - fn draw_seg(&mut self, head: Head, to: Point, width: f64) -> Result<(Head, SegIndex), ()> { - let net = self.layout.primitive(head.dot).weight().net; - - assert!(width <= self.layout.primitive(head.dot).weight().circle.r * 2.); - - let to_index = self.layout.add_dot(DotWeight { - net, - circle: Circle { - pos: to, - r: width / 2.0, - }, - })?; - let seg = self - .layout - .add_seg(head.dot, to_index, SegWeight { net, width })?; - Ok(( - Head { - dot: to_index, - segbend: None, - }, - seg, - )) - } - fn relax_band(&mut self, bend: BendIndex) { let mut prev_bend = bend; while let Some(cur_bend) = self.layout.primitive(prev_bend).find_prev_akin() { @@ -356,8 +225,8 @@ impl Router { self.layout.remove_interior(&bow); - let head = self.draw_start(ends.0); - let _ = self.draw_finish(head, ends.1, 5.0); + let head = self.draw().start(ends.0); + let _ = self.draw().finish(head, ends.1, 5.0); } pub fn move_dot(&mut self, dot: DotIndex, to: Point) -> Result<(), ()> { @@ -370,26 +239,8 @@ impl Router { Ok(()) } - fn extend_head(&mut self, head: Head, to: Point) -> Result { - if let Some(..) = head.segbend { - self.extend_head_bend(head, to) - } else { - Ok(head) - // No assertion for now because we temporarily use floats. - - //println!("{:?} {:?}", self.layout.weight(TaggedIndex::Dot(from)).as_dot().unwrap().circle.pos, to); - //assert!(self.layout.weight(TaggedIndex::Dot(from)).as_dot().unwrap().circle.pos == to); - } - } - - fn extend_head_bend(&mut self, head: Head, to: Point) -> Result { - self.layout - .extend_bend(head.segbend.as_ref().unwrap().bend, head.dot, to)?; - Ok(head) - } - - fn guide<'a>(&'a self, conditions: &'a Conditions) -> Guide { - Guide::new(&self.layout, &self.rules, conditions) + pub fn draw(&mut self) -> Draw { + Draw::new(&mut self.layout, &self.rules) } pub fn routeedges(&self) -> impl Iterator + '_ {