diff --git a/src/bin/topola-egui/app.rs b/src/bin/topola-egui/app.rs index 08a80a3..421671b 100644 --- a/src/bin/topola-egui/app.rs +++ b/src/bin/topola-egui/app.rs @@ -33,7 +33,7 @@ use topola::{ math::Circle, router::{ draw::DrawException, - navmesh::{Navmesh, NavmeshEdgeReference, NavvertexNodeIndex}, + navmesh::{BinavvertexNodeIndex, Navmesh}, tracer::{Trace, Tracer}, }, specctra::{design::SpecctraDesign, mesadata::SpecctraMesadata}, @@ -49,7 +49,7 @@ pub struct SharedData { pub from: Option, pub to: Option, pub navmesh: Option, - pub path: Vec, + pub path: Vec, pub ghosts: Vec, pub highlighteds: Vec, } diff --git a/src/bin/topola-egui/viewport.rs b/src/bin/topola-egui/viewport.rs index 920faae..01c43e3 100644 --- a/src/bin/topola-egui/viewport.rs +++ b/src/bin/topola-egui/viewport.rs @@ -5,7 +5,10 @@ use petgraph::visit::{EdgeRef, IntoEdgeReferences}; use topola::{ autorouter::invoker::{Command, Invoker}, board::mesadata::MesadataTrait, - drawing::{graph::MakePrimitive, primitive::MakePrimitiveShape}, + drawing::{ + graph::{MakePrimitive, PrimitiveIndex}, + primitive::MakePrimitiveShape, + }, geometry::{shape::ShapeTrait, GenericNode}, layout::{via::ViaWeight, zone::MakePolyShape}, math::Circle, @@ -165,14 +168,12 @@ impl Viewport { } if let Some(navmesh) = &shared_data.navmesh { - for edge in navmesh.edge_references() { - let from = edge - .source() + for edge in navmesh.graph().edge_references() { + let from = PrimitiveIndex::from(navmesh.graph().node_weight(edge.source()).unwrap().node) .primitive(board.layout().drawing()) .shape() .center(); - let to = edge - .target() + let to = PrimitiveIndex::from(navmesh.graph().node_weight(edge.target()).unwrap().node) .primitive(board.layout().drawing()) .shape() .center(); @@ -182,11 +183,11 @@ impl Viewport { shared_data .path .iter() - .position(|node| *node == edge.source()), + .position(|node| *node == navmesh.graph().node_weight(edge.source()).unwrap().node), shared_data .path .iter() - .position(|node| *node == edge.target()), + .position(|node| *node == navmesh.graph().node_weight(edge.target()).unwrap().node), ) { if target_pos == source_pos + 1 || source_pos == target_pos + 1 diff --git a/src/router/astar.rs b/src/router/astar.rs index 559770e..167a130 100644 --- a/src/router/astar.rs +++ b/src/router/astar.rs @@ -101,9 +101,9 @@ where K: Measure + Copy, G::NodeId: Eq + Hash, { - fn is_goal(&mut self, node: G::NodeId, tracker: &PathTracker) -> Option; - fn edge_cost(&mut self, edge: G::EdgeRef) -> Option; - fn estimate_cost(&mut self, node: G::NodeId) -> K; + fn is_goal(&mut self, graph: &G, node: G::NodeId, tracker: &PathTracker) -> Option; + fn edge_cost(&mut self, graph: &G, edge: G::EdgeRef) -> Option; + fn estimate_cost(&mut self, graph: &G, node: G::NodeId) -> K; } pub struct Astar @@ -153,7 +153,7 @@ where let zero_score = K::default(); this.scores.insert(start, zero_score); this.visit_next - .push(MinScored(strategy.estimate_cost(start), start)); + .push(MinScored(strategy.estimate_cost(&&graph, start), start)); this } @@ -165,7 +165,7 @@ where return Err(AstarError::NotFound); }; - if let Some(result) = strategy.is_goal(node, &self.path_tracker) { + if let Some(result) = strategy.is_goal(&self.graph, node, &self.path_tracker) { let path = self.path_tracker.reconstruct_path_to(node); let cost = self.scores[&node]; return Ok(AstarStatus::Finished(cost, path, result)); @@ -190,7 +190,7 @@ where } for edge in self.graph.edges(node) { - if let Some(edge_cost) = strategy.edge_cost(edge) { + if let Some(edge_cost) = strategy.edge_cost(&self.graph, edge) { let next = edge.target(); let next_score = node_score + edge_cost; @@ -209,7 +209,7 @@ where } self.path_tracker.set_predecessor(next, node); - let next_estimate_score = next_score + strategy.estimate_cost(next); + let next_estimate_score = next_score + strategy.estimate_cost(&self.graph, next); self.visit_next.push(MinScored(next_estimate_score, next)); } } diff --git a/src/router/navmesh.rs b/src/router/navmesh.rs index 4a78724..76eabea 100644 --- a/src/router/navmesh.rs +++ b/src/router/navmesh.rs @@ -1,37 +1,46 @@ -use std::iter; - use enum_dispatch::enum_dispatch; use geo::Point; -use itertools::Itertools; -use petgraph::visit::{self, NodeIndexable}; -use petgraph::{stable_graph::NodeIndex, visit::EdgeRef}; +use petgraph::{ + graph::UnGraph, + stable_graph::NodeIndex, + visit::{IntoNodeIdentifiers, NodeIndexable}, +}; use spade::{HasPosition, InsertionError, Point2}; use thiserror::Error; -use crate::drawing::graph::{GetLayer, GetMaybeNet}; -use crate::geometry::shape::ShapeTrait; use crate::{ drawing::{ bend::{FixedBendIndex, LooseBendIndex}, dot::FixedDotIndex, - graph::{MakePrimitive, PrimitiveIndex}, - primitive::{GetCore, MakePrimitiveShape, Primitive}, + graph::{GetLayer, GetMaybeNet, MakePrimitive, PrimitiveIndex}, + primitive::{MakePrimitiveShape, Primitive}, rules::RulesTrait, Drawing, }, + geometry::shape::ShapeTrait, graph::GetPetgraphIndex, layout::Layout, - triangulation::{GetTrianvertexNodeIndex, Triangulation, TriangulationEdgeReference}, + triangulation::{GetTrianvertexNodeIndex, Triangulation}, }; #[enum_dispatch(GetPetgraphIndex, MakePrimitive)] #[derive(Debug, Hash, Clone, Copy, PartialEq, Eq)] -pub enum NavvertexNodeIndex { +pub enum BinavvertexNodeIndex { FixedDot(FixedDotIndex), FixedBend(FixedBendIndex), LooseBend(LooseBendIndex), } +impl From for PrimitiveIndex { + fn from(vertex: BinavvertexNodeIndex) -> Self { + match vertex { + BinavvertexNodeIndex::FixedDot(dot) => PrimitiveIndex::FixedDot(dot), + BinavvertexNodeIndex::FixedBend(bend) => PrimitiveIndex::FixedBend(bend), + BinavvertexNodeIndex::LooseBend(bend) => PrimitiveIndex::LooseBend(bend), + } + } +} + #[enum_dispatch(GetPetgraphIndex, MakePrimitive)] #[derive(Debug, Hash, Clone, Copy, PartialEq, Eq)] enum TrianvertexNodeIndex { @@ -39,30 +48,19 @@ enum TrianvertexNodeIndex { FixedBend(FixedBendIndex), } -impl From for PrimitiveIndex { - fn from(vertex: NavvertexNodeIndex) -> Self { - match vertex { - NavvertexNodeIndex::FixedDot(dot) => PrimitiveIndex::FixedDot(dot), - NavvertexNodeIndex::FixedBend(bend) => PrimitiveIndex::FixedBend(bend), - NavvertexNodeIndex::LooseBend(bend) => PrimitiveIndex::LooseBend(bend), - } - } -} - -impl From for NavvertexNodeIndex { +impl From for BinavvertexNodeIndex { fn from(vertex: TrianvertexNodeIndex) -> Self { match vertex { - TrianvertexNodeIndex::FixedDot(dot) => NavvertexNodeIndex::FixedDot(dot), - TrianvertexNodeIndex::FixedBend(bend) => NavvertexNodeIndex::FixedBend(bend), + TrianvertexNodeIndex::FixedDot(dot) => BinavvertexNodeIndex::FixedDot(dot), + TrianvertexNodeIndex::FixedBend(bend) => BinavvertexNodeIndex::FixedBend(bend), } } } #[derive(Debug, Clone)] struct TrianvertexWeight { - node: TrianvertexNodeIndex, - rails: Vec, - pos: Point, + pub node: TrianvertexNodeIndex, + pub pos: Point, } impl GetTrianvertexNodeIndex for TrianvertexWeight { @@ -79,11 +77,8 @@ impl HasPosition for TrianvertexWeight { } #[derive(Debug, Clone)] -pub struct Navmesh { - triangulation: Triangulation, - navvertex_to_trianvertex: Vec>, - source: FixedDotIndex, - target: FixedDotIndex, +pub struct NavvertexWeight { + pub node: BinavvertexNodeIndex, } #[derive(Error, Debug, Clone)] @@ -92,20 +87,23 @@ pub enum NavmeshError { Insertion(#[from] InsertionError), } +#[derive(Debug, Clone)] +pub struct Navmesh { + graph: UnGraph, + source: FixedDotIndex, + source_vertex: NodeIndex, + target: FixedDotIndex, + target_vertex: NodeIndex, +} + impl Navmesh { pub fn new( layout: &Layout, source: FixedDotIndex, target: FixedDotIndex, ) -> Result { - let mut this = Self { - triangulation: Triangulation::new(layout.drawing().geometry().graph().node_bound()), - navvertex_to_trianvertex: Vec::new(), - source, - target, - }; - this.navvertex_to_trianvertex - .resize(layout.drawing().geometry().graph().node_bound(), None); + let mut triangulation: Triangulation = + Triangulation::new(layout.drawing().geometry().graph().node_bound()); let layer = layout.drawing().primitive(source).layer(); let maybe_net = layout.drawing().primitive(source).maybe_net(); @@ -120,16 +118,14 @@ impl Navmesh { { match node { PrimitiveIndex::FixedDot(dot) => { - this.triangulation.add_vertex(TrianvertexWeight { + triangulation.add_vertex(TrianvertexWeight { node: dot.into(), - rails: vec![], pos: primitive.shape().center(), })?; } PrimitiveIndex::FixedBend(bend) => { - this.triangulation.add_vertex(TrianvertexWeight { + triangulation.add_vertex(TrianvertexWeight { node: bend.into(), - rails: vec![], pos: primitive.shape().center(), })?; } @@ -139,185 +135,48 @@ impl Navmesh { } } - for node in layout.drawing().layer_primitive_nodes(layer) { - // Add rails as vertices. This is how the navmesh differs from the triangulation. - match node { - PrimitiveIndex::LooseBend(bend) => { - this.triangulation - .weight_mut(layout.drawing().primitive(bend).core().into()) - .rails - .push(bend.into()); - this.navvertex_to_trianvertex[bend.petgraph_index().index()] = - Some(layout.drawing().primitive(bend).core().into()); - } - _ => (), + let mut graph: UnGraph = UnGraph::default(); + let mut source_vertex = None; + let mut target_vertex = None; + + for trianvertex in triangulation.node_identifiers() { + let navvertex = graph.add_node(NavvertexWeight { + node: trianvertex.into(), + }); + + if trianvertex == source.into() { + source_vertex = Some(navvertex); + } else if trianvertex == target.into() { + target_vertex = Some(navvertex); } } - Ok(this) + Ok(Self { + graph, + source, + source_vertex: source_vertex.unwrap(), + target, + target_vertex: target_vertex.unwrap(), + }) } - fn trianvertex(&self, vertex: NavvertexNodeIndex) -> TrianvertexNodeIndex { - match vertex { - NavvertexNodeIndex::FixedDot(dot) => TrianvertexNodeIndex::FixedDot(dot), - NavvertexNodeIndex::FixedBend(bend) => TrianvertexNodeIndex::FixedBend(bend), - NavvertexNodeIndex::LooseBend(bend) => { - self.navvertex_to_trianvertex[bend.petgraph_index().index()].unwrap() - } - } + pub fn graph(&self) -> &UnGraph { + &self.graph } pub fn source(&self) -> FixedDotIndex { self.source } + pub fn source_vertex(&self) -> NodeIndex { + self.source_vertex + } + pub fn target(&self) -> FixedDotIndex { self.target } -} -impl visit::GraphBase for Navmesh { - type NodeId = NavvertexNodeIndex; - type EdgeId = (NavvertexNodeIndex, NavvertexNodeIndex); -} - -impl visit::Data for Navmesh { - type NodeWeight = (); - type EdgeWeight = (); -} - -#[derive(Debug, Clone, Copy)] -pub struct NavmeshEdgeReference { - from: NavvertexNodeIndex, - to: NavvertexNodeIndex, -} - -impl visit::EdgeRef for NavmeshEdgeReference { - type NodeId = NavvertexNodeIndex; - type EdgeId = (NavvertexNodeIndex, NavvertexNodeIndex); - type Weight = (); - - fn source(&self) -> Self::NodeId { - self.from - } - - fn target(&self) -> Self::NodeId { - self.to - } - - fn weight(&self) -> &Self::Weight { - &() - } - - fn id(&self) -> Self::EdgeId { - (self.from, self.to) - } -} - -impl<'a> visit::IntoNeighbors for &'a Navmesh { - type Neighbors = Box + 'a>; - - fn neighbors(self, vertex: Self::NodeId) -> Self::Neighbors { - Box::new( - self.triangulation - .neighbors(self.trianvertex(vertex)) - .flat_map(|neighbor| { - iter::once(neighbor.into()).chain( - self.triangulation - .weight(neighbor) - .rails - .iter() - .map(|index| NavvertexNodeIndex::from(*index)), - ) - }), - ) - } -} - -fn edge_with_near_edges( - triangulation: &Triangulation, - edge: TriangulationEdgeReference, -) -> impl Iterator { - let mut from_vertices = vec![edge.source().into()]; - - // Append rails to the source. - from_vertices.extend( - triangulation - .weight(edge.source()) - .rails - .iter() - .map(|bend| NavvertexNodeIndex::from(*bend)), - ); - - let mut to_vertices = vec![edge.target().into()]; - - // Append rails to the target. - to_vertices.extend( - triangulation - .weight(edge.target()) - .rails - .iter() - .map(|bend| NavvertexNodeIndex::from(*bend)), - ); - - // Return cartesian product. - from_vertices - .into_iter() - .cartesian_product(to_vertices.into_iter()) - .map(|pair| NavmeshEdgeReference { - from: pair.0, - to: pair.1.into(), - }) -} - -impl<'a> visit::IntoEdgeReferences for &'a Navmesh { - type EdgeRef = NavmeshEdgeReference; - type EdgeReferences = Box + 'a>; - - fn edge_references(self) -> Self::EdgeReferences { - Box::new( - self.triangulation - .edge_references() - .flat_map(move |edge| edge_with_near_edges(&self.triangulation, edge)), - ) - } -} - -fn vertex_edges( - triangulation: &Triangulation, - from: NavvertexNodeIndex, - to: TrianvertexNodeIndex, -) -> impl Iterator { - let from_vertices = vec![from]; - let mut to_vertices = vec![to.into()]; - - // Append rails to the target. - to_vertices.extend( - triangulation - .weight(to) - .rails - .iter() - .map(|bend| NavvertexNodeIndex::from(*bend)), - ); - - // Return cartesian product. - from_vertices - .into_iter() - .cartesian_product(to_vertices.into_iter()) - .map(|pair| NavmeshEdgeReference { - from: pair.0, - to: pair.1, - }) -} - -impl<'a> visit::IntoEdges for &'a Navmesh { - type Edges = Box + 'a>; - - fn edges(self, vertex: Self::NodeId) -> Self::Edges { - Box::new( - self.triangulation - .edges(self.trianvertex(vertex)) - .flat_map(move |edge| vertex_edges(&self.triangulation, vertex, edge.target())), - ) + pub fn target_vertex(&self) -> NodeIndex { + self.target_vertex } } diff --git a/src/router/router.rs b/src/router/router.rs index 940e45c..4648c98 100644 --- a/src/router/router.rs +++ b/src/router/router.rs @@ -1,5 +1,8 @@ use geo::EuclideanDistance; -use petgraph::visit::EdgeRef; +use petgraph::{ + graph::{EdgeReference, NodeIndex, UnGraph}, + visit::EdgeRef, +}; use thiserror::Error; use crate::{ @@ -11,11 +14,12 @@ use crate::{ rules::RulesTrait, }, geometry::shape::ShapeTrait, + graph::GetPetgraphIndex, layout::Layout, router::{ astar::{astar, AstarError, AstarStrategy, PathTracker}, draw::DrawException, - navmesh::{Navmesh, NavmeshEdgeReference, NavmeshError, NavvertexNodeIndex}, + navmesh::{BinavvertexNodeIndex, Navmesh, NavmeshError, NavvertexWeight}, tracer::{Trace, Tracer}, }, }; @@ -35,55 +39,75 @@ pub struct Router<'a, R: RulesTrait> { struct RouterAstarStrategy<'a, R: RulesTrait> { tracer: Tracer<'a, R>, trace: Trace, - to: FixedDotIndex, + target: FixedDotIndex, } impl<'a, R: RulesTrait> RouterAstarStrategy<'a, R> { - pub fn new(tracer: Tracer<'a, R>, trace: Trace, to: FixedDotIndex) -> Self { - Self { tracer, trace, to } + pub fn new(tracer: Tracer<'a, R>, trace: Trace, target: FixedDotIndex) -> Self { + Self { + tracer, + trace, + target, + } } } -impl<'a, R: RulesTrait> AstarStrategy<&Navmesh, f64, BandFirstSegIndex> +impl<'a, R: RulesTrait> AstarStrategy<&UnGraph, f64, BandFirstSegIndex> for RouterAstarStrategy<'a, R> { fn is_goal( &mut self, - vertex: NavvertexNodeIndex, - tracker: &PathTracker<&Navmesh>, + graph: &&UnGraph, + vertex: NodeIndex, + tracker: &PathTracker<&UnGraph>, ) -> Option { let new_path = tracker.reconstruct_path_to(vertex); + /*.into_iter() + .map(|ni| graph.node_weight(ni).unwrap().node) + .collect();*/ let width = self.trace.width; self.tracer - .rework_path(&mut self.trace, &new_path, width) + .rework_path(*graph, &mut self.trace, &new_path[..], width) .unwrap(); - self.tracer.finish(&mut self.trace, self.to, width).ok() + self.tracer + .finish(*graph, &mut self.trace, self.target, width) + .ok() } - fn edge_cost(&mut self, edge: NavmeshEdgeReference) -> Option { - if edge.target() == self.to.into() { + fn edge_cost( + &mut self, + graph: &&UnGraph, + edge: EdgeReference<(), usize>, + ) -> Option { + if edge.target() == self.target.petgraph_index() { return None; } let before_probe_length = 0.0; //self.tracer.layout.band_length(self.trace.head.face()); let width = self.trace.width; - let result = self.tracer.step(&mut self.trace, edge.target(), width); + let result = self + .tracer + .step(*graph, &mut self.trace, edge.target(), width); let probe_length = 0.0; //self.tracer.layout.band_length(self.trace.head.face()); if result.is_ok() { - self.tracer.undo_step(&mut self.trace); + self.tracer.undo_step(*graph, &mut self.trace); Some(probe_length - before_probe_length) } else { None } } - fn estimate_cost(&mut self, vertex: NavvertexNodeIndex) -> f64 { - let start_point = PrimitiveIndex::from(vertex) + fn estimate_cost( + &mut self, + graph: &&UnGraph, + vertex: NodeIndex, + ) -> f64 { + let start_point = PrimitiveIndex::from(graph.node_weight(vertex).unwrap().node) .primitive(self.tracer.layout.drawing()) .shape() .center(); @@ -91,7 +115,7 @@ impl<'a, R: RulesTrait> AstarStrategy<&Navmesh, f64, BandFirstSegIndex> .tracer .layout .drawing() - .primitive(self.to) + .primitive(self.target) .shape() .center(); @@ -114,15 +138,18 @@ impl<'a, R: RulesTrait> Router<'a, R> { } pub fn route_band(&mut self, width: f64) -> Result { - let from = self.navmesh.source(); - let to = self.navmesh.target(); let mut tracer = Tracer::new(self.layout); - let trace = tracer.start(from, width); + let trace = tracer.start( + self.navmesh.graph(), + self.navmesh.source(), + self.navmesh.source_vertex(), + width, + ); let (_cost, _path, band) = astar( - &self.navmesh, - from.into(), - &mut RouterAstarStrategy::new(tracer, trace, to), + self.navmesh.graph(), + self.navmesh.source_vertex(), + &mut RouterAstarStrategy::new(tracer, trace, self.navmesh.target()), )?; Ok(band) diff --git a/src/router/tracer.rs b/src/router/tracer.rs index c5f5364..37fc532 100644 --- a/src/router/tracer.rs +++ b/src/router/tracer.rs @@ -1,23 +1,25 @@ -use contracts::debug_ensures; +use contracts::{debug_ensures, debug_requires}; +use petgraph::graph::{NodeIndex, UnGraph}; use crate::{ drawing::{ band::BandFirstSegIndex, bend::LooseBendIndex, dot::FixedDotIndex, + graph::PrimitiveIndex, guide::{BareHead, CaneHead, Head}, rules::RulesTrait, }, layout::Layout, router::{ draw::{Draw, DrawException}, - navmesh::NavvertexNodeIndex, + navmesh::{BinavvertexNodeIndex, NavvertexWeight}, }, }; #[derive(Debug)] pub struct Trace { - pub path: Vec, + pub path: Vec>, pub head: Head, pub width: f64, } @@ -32,28 +34,37 @@ impl<'a, R: RulesTrait> Tracer<'a, R> { Tracer { layout } } - pub fn start(&mut self, from: FixedDotIndex, width: f64) -> Trace { + pub fn start( + &mut self, + _graph: &UnGraph, + source: FixedDotIndex, + source_vertex: NodeIndex, + width: f64, + ) -> Trace { Trace { - path: vec![from.into()], - head: BareHead { dot: from }.into(), + path: vec![source_vertex], + head: BareHead { dot: source }.into(), width, } } pub fn finish( &mut self, + graph: &UnGraph, trace: &mut Trace, - into: FixedDotIndex, + target: FixedDotIndex, width: f64, ) -> Result { - Draw::new(self.layout).finish_in_dot(trace.head, into, width) + Draw::new(self.layout).finish_in_dot(trace.head, target, width) } + #[debug_requires(path[0] == trace.path[0])] #[debug_ensures(ret.is_ok() -> trace.path.len() == path.len())] pub fn rework_path( &mut self, + graph: &UnGraph, trace: &mut Trace, - path: &[NavvertexNodeIndex], + path: &[NodeIndex], width: f64, ) -> Result<(), DrawException> { let prefix_length = trace @@ -64,20 +75,21 @@ impl<'a, R: RulesTrait> Tracer<'a, R> { .count(); let length = trace.path.len(); - self.undo_path(trace, length - prefix_length); - self.path(trace, &path[prefix_length..], width) + self.undo_path(graph, trace, length - prefix_length); + self.path(graph, trace, &path[prefix_length..], width) } #[debug_ensures(ret.is_ok() -> trace.path.len() == old(trace.path.len() + path.len()))] pub fn path( &mut self, + graph: &UnGraph, trace: &mut Trace, - path: &[NavvertexNodeIndex], + path: &[NodeIndex], width: f64, ) -> Result<(), DrawException> { for (i, vertex) in path.iter().enumerate() { - if let Err(err) = self.step(trace, *vertex, width) { - self.undo_path(trace, i); + if let Err(err) = self.step(graph, trace, *vertex, width) { + self.undo_path(graph, trace, i); return Err(err); } } @@ -86,21 +98,28 @@ impl<'a, R: RulesTrait> Tracer<'a, R> { } #[debug_ensures(trace.path.len() == old(trace.path.len() - step_count))] - pub fn undo_path(&mut self, trace: &mut Trace, step_count: usize) { + pub fn undo_path( + &mut self, + graph: &UnGraph, + trace: &mut Trace, + step_count: usize, + ) { for _ in 0..step_count { - self.undo_step(trace); + self.undo_step(graph, trace); } } + #[debug_ensures(ret.is_ok() -> matches!(trace.head, Head::Bare(..)))] #[debug_ensures(ret.is_ok() -> trace.path.len() == old(trace.path.len() + 1))] #[debug_ensures(ret.is_err() -> trace.path.len() == old(trace.path.len()))] pub fn step( &mut self, + graph: &UnGraph, trace: &mut Trace, - to: NavvertexNodeIndex, + to: NodeIndex, width: f64, ) -> Result<(), DrawException> { - trace.head = self.wrap(trace.head, to, width)?.into(); + trace.head = self.wrap(graph, trace.head, to, width)?.into(); trace.path.push(to); Ok::<(), DrawException>(()) @@ -108,21 +127,25 @@ impl<'a, R: RulesTrait> Tracer<'a, R> { fn wrap( &mut self, + graph: &UnGraph, head: Head, - around: NavvertexNodeIndex, + around: NodeIndex, width: f64, ) -> Result { - match around { - NavvertexNodeIndex::FixedDot(dot) => self.wrap_around_fixed_dot(head, dot, width), - NavvertexNodeIndex::FixedBend(_fixed_bend) => todo!(), - NavvertexNodeIndex::LooseBend(loose_bend) => { - self.wrap_around_loose_bend(head, loose_bend, width) + match self.binavvertex(graph, around) { + BinavvertexNodeIndex::FixedDot(dot) => { + self.wrap_around_fixed_dot(graph, head, dot, width) + } + BinavvertexNodeIndex::FixedBend(_fixed_bend) => todo!(), + BinavvertexNodeIndex::LooseBend(loose_bend) => { + self.wrap_around_loose_bend(graph, head, loose_bend, width) } } } fn wrap_around_fixed_dot( &mut self, + graph: &UnGraph, head: Head, around: FixedDotIndex, width: f64, @@ -133,6 +156,7 @@ impl<'a, R: RulesTrait> Tracer<'a, R> { fn wrap_around_loose_bend( &mut self, + graph: &UnGraph, head: Head, around: LooseBendIndex, width: f64, @@ -143,8 +167,8 @@ impl<'a, R: RulesTrait> Tracer<'a, R> { } #[debug_ensures(trace.path.len() == old(trace.path.len() - 1))] - pub fn undo_step(&mut self, trace: &mut Trace) { - if let Head::Cane(head) = trace.head { + pub fn undo_step(&mut self, graph: &UnGraph, trace: &mut Trace) { + if let Head::Cane(head) = dbg!(trace.head) { trace.head = Draw::new(self.layout).undo_cane(head).unwrap(); } else { panic!(); @@ -152,4 +176,20 @@ impl<'a, R: RulesTrait> Tracer<'a, R> { trace.path.pop(); } + + fn binavvertex( + &self, + graph: &UnGraph, + vertex: NodeIndex, + ) -> BinavvertexNodeIndex { + graph.node_weight(vertex).unwrap().node + } + + fn primitive( + &self, + graph: &UnGraph, + vertex: NodeIndex, + ) -> PrimitiveIndex { + self.binavvertex(graph, vertex).into() + } }