diff --git a/src/autorouter/autorouter.rs b/src/autorouter/autorouter.rs index 1fcf119..f7830b9 100644 --- a/src/autorouter/autorouter.rs +++ b/src/autorouter/autorouter.rs @@ -134,35 +134,45 @@ impl Autorouter { } pub fn autoroute_walk(&mut self, selection: &Selection) -> Option { - Autoroute::new( - self.ratsnest - .graph() - .edge_indices() - .filter(|edge| { - let (from, to) = self.ratsnest.graph().edge_endpoints(*edge).unwrap(); - - let from_vertex = self - .ratsnest - .graph() - .node_weight(from) - .unwrap() - .vertex_index(); - let to_vertex = self - .ratsnest - .graph() - .node_weight(to) - .unwrap() - .vertex_index(); - - selection.contains(&from_vertex.into()) && selection.contains(&to_vertex.into()) - }) - .collect::>(), - self, - ) + Autoroute::new(self.selected_ratlines(selection), self) } pub fn undo_autoroute(&mut self, selection: &Selection) { - todo!(); + for ratline in self.selected_ratlines(selection).iter() { + let band = self + .ratsnest + .graph() + .edge_weight(*ratline) + .unwrap() + .band + .unwrap(); + self.layout.lock().unwrap().remove_band(band); + } + } + + fn selected_ratlines(&self, selection: &Selection) -> Vec> { + self.ratsnest + .graph() + .edge_indices() + .filter(|ratline| { + let (from, to) = self.ratsnest.graph().edge_endpoints(*ratline).unwrap(); + + let from_vertex = self + .ratsnest + .graph() + .node_weight(from) + .unwrap() + .vertex_index(); + let to_vertex = self + .ratsnest + .graph() + .node_weight(to) + .unwrap() + .vertex_index(); + + selection.contains(&from_vertex.into()) && selection.contains(&to_vertex.into()) + }) + .collect() } pub fn layout(&self) -> &Arc>> { diff --git a/src/autorouter/ratsnest.rs b/src/autorouter/ratsnest.rs index 8d2b8c2..7a67b88 100644 --- a/src/autorouter/ratsnest.rs +++ b/src/autorouter/ratsnest.rs @@ -12,6 +12,7 @@ use spade::{HasPosition, InsertionError, Point2}; use crate::{ drawing::{ + band::BandIndex, dot::FixedDotIndex, graph::{GetMaybeNet, MakePrimitive, PrimitiveIndex}, primitive::MakePrimitiveShape, @@ -23,7 +24,7 @@ use crate::{ zone::{MakePolyShape, ZoneWeight}, Layout, }, - triangulation::{GetVertexIndex, Triangulation, TriangulationEdgeWeight}, + triangulation::{GetVertexIndex, Triangulation}, }; #[enum_dispatch(GetNodeIndex)] @@ -61,8 +62,13 @@ impl HasPosition for VertexWeight { } } +#[derive(Debug, Default, Clone, Copy)] +pub struct EdgeWeight { + pub band: Option, +} + pub struct Ratsnest { - graph: UnGraph, + graph: UnGraph, } impl Ratsnest { @@ -140,7 +146,7 @@ impl Ratsnest { target, weight, } => { - this.graph.add_edge(map[source], map[target], weight); + this.graph.add_edge(map[source], map[target], weight.weight); } } } @@ -159,7 +165,7 @@ impl Ratsnest { Ok(this) } - pub fn graph(&self) -> &UnGraph { + pub fn graph(&self) -> &UnGraph { &self.graph } } diff --git a/src/drawing/band.rs b/src/drawing/band.rs index cf51487..52104db 100644 --- a/src/drawing/band.rs +++ b/src/drawing/band.rs @@ -1,5 +1,6 @@ use crate::drawing::seg::{LoneLooseSegIndex, SeqLooseSegIndex}; +#[derive(Debug, Clone, Copy)] pub enum BandIndex { Straight(LoneLooseSegIndex), Bended(SeqLooseSegIndex), diff --git a/src/layout/layout.rs b/src/layout/layout.rs index 74db707..0ddbcb0 100644 --- a/src/layout/layout.rs +++ b/src/layout/layout.rs @@ -4,6 +4,7 @@ use rstar::AABB; use crate::{ drawing::{ + band::BandIndex, bend::LooseBendWeight, dot::{DotIndex, FixedDotIndex, FixedDotWeight, LooseDotIndex, LooseDotWeight}, graph::{GetLayer, GetMaybeNet, PrimitiveIndex, PrimitiveWeight, Retag}, @@ -37,6 +38,10 @@ impl Layout { Self { drawing } } + pub fn remove_band(&mut self, band: BandIndex) { + self.drawing.remove_band(band); + } + pub fn remove_segbend(&mut self, segbend: &Segbend, face: LooseDotIndex) { self.drawing.remove_segbend(segbend, face) } diff --git a/src/router/navmesh.rs b/src/router/navmesh.rs index 5ae47e5..d782d71 100644 --- a/src/router/navmesh.rs +++ b/src/router/navmesh.rs @@ -58,19 +58,19 @@ impl From for VertexIndex { } #[derive(Debug, Clone)] -struct TriangulationWeight { +struct TriangulationVertexWeight { vertex: TriangulationVertexIndex, rails: Vec, pos: Point, } -impl GetVertexIndex for TriangulationWeight { +impl GetVertexIndex for TriangulationVertexWeight { fn vertex_index(&self) -> TriangulationVertexIndex { self.vertex } } -impl HasPosition for TriangulationWeight { +impl HasPosition for TriangulationVertexWeight { type Scalar = f64; fn position(&self) -> Point2 { Point2::new(self.pos.x(), self.pos.y()) @@ -79,7 +79,7 @@ impl HasPosition for TriangulationWeight { #[derive(Debug, Clone)] pub struct Navmesh { - triangulation: Triangulation, + triangulation: Triangulation, vertex_to_triangulation_vertex: Vec>, from: FixedDotIndex, to: FixedDotIndex, @@ -110,14 +110,14 @@ impl Navmesh { if node == from.into() || node == to.into() || primitive_net != net { match node { PrimitiveIndex::FixedDot(dot) => { - this.triangulation.add_vertex(TriangulationWeight { + this.triangulation.add_vertex(TriangulationVertexWeight { vertex: dot.into(), rails: vec![], pos: primitive.shape().center(), })?; } PrimitiveIndex::FixedBend(bend) => { - this.triangulation.add_vertex(TriangulationWeight { + this.triangulation.add_vertex(TriangulationVertexWeight { vertex: bend.into(), rails: vec![], pos: primitive.shape().center(), @@ -225,8 +225,8 @@ impl<'a> visit::IntoNeighbors for &'a Navmesh { } fn edge_with_near_edges( - triangulation: &Triangulation, - edge: TriangulationEdgeReference, + triangulation: &Triangulation, + edge: TriangulationEdgeReference, ) -> impl Iterator { let mut from_vertices = vec![edge.source().into()]; @@ -274,7 +274,7 @@ impl<'a> visit::IntoEdgeReferences for &'a Navmesh { } fn vertex_edges( - triangulation: &Triangulation, + triangulation: &Triangulation, from: VertexIndex, to: TriangulationVertexIndex, ) -> impl Iterator { diff --git a/src/triangulation.rs b/src/triangulation.rs index 94343ef..d355526 100644 --- a/src/triangulation.rs +++ b/src/triangulation.rs @@ -1,4 +1,4 @@ -use std::marker::PhantomData; +use std::{cmp::Ordering, marker::PhantomData}; use geo::{point, EuclideanDistance, Point}; use petgraph::visit; @@ -11,18 +11,25 @@ pub trait GetVertexIndex { } #[derive(Debug, Clone)] -pub struct Triangulation + HasPosition> { - triangulation: DelaunayTriangulation, +pub struct Triangulation< + I: Copy + PartialEq + GetNodeIndex, + VW: GetVertexIndex + HasPosition, + EW: Copy + Default, +> { + triangulation: DelaunayTriangulation, vertex_to_handle: Vec>, index_marker: PhantomData, } -impl + HasPosition> - Triangulation +impl< + I: Copy + PartialEq + GetNodeIndex, + VW: GetVertexIndex + HasPosition, + EW: Copy + Default, + > Triangulation { pub fn new(node_bound: usize) -> Self { let mut this = Self { - triangulation: as spade::Triangulation>::new(), + triangulation: as spade::Triangulation>::new(), vertex_to_handle: Vec::new(), index_marker: PhantomData, }; @@ -30,7 +37,7 @@ impl + HasPosition Result<(), InsertionError> { + pub fn add_vertex(&mut self, weight: VW) -> Result<(), InsertionError> { let index = weight.vertex_index().node_index().index(); self.vertex_to_handle[index] = Some(spade::Triangulation::insert( &mut self.triangulation, @@ -39,12 +46,12 @@ impl + HasPosition &W { + pub fn weight(&self, vertex: I) -> &VW { spade::Triangulation::s(&self.triangulation) .vertex_data(self.vertex_to_handle[vertex.node_index().index()].unwrap()) } - pub fn weight_mut(&mut self, vertex: I) -> &mut W { + pub fn weight_mut(&mut self, vertex: I) -> &mut VW { spade::Triangulation::vertex_data_mut( &mut self.triangulation, self.vertex_to_handle[vertex.node_index().index()].unwrap(), @@ -68,36 +75,55 @@ impl + HasPosition + HasPosition> - visit::GraphBase for Triangulation +impl< + I: Copy + PartialEq + GetNodeIndex, + VW: GetVertexIndex + HasPosition, + EW: Copy + Default, + > visit::GraphBase for Triangulation { type NodeId = I; type EdgeId = (I, I); } -#[derive(Debug, Clone, Copy, PartialEq, PartialOrd)] -pub struct TriangulationEdgeWeight { +#[derive(Debug, Clone, Copy)] +pub struct TriangulationEdgeWeightWrapper { length: f64, + pub weight: EW, } -impl + HasPosition> - visit::Data for Triangulation +impl PartialEq for TriangulationEdgeWeightWrapper { + fn eq(&self, other: &Self) -> bool { + self.length.eq(&other.length) + } +} + +impl PartialOrd for TriangulationEdgeWeightWrapper { + fn partial_cmp(&self, other: &Self) -> Option { + self.length.partial_cmp(&other.length) + } +} + +impl< + I: Copy + PartialEq + GetNodeIndex, + VW: GetVertexIndex + HasPosition, + EW: Copy + Default, + > visit::Data for Triangulation { - type NodeWeight = W; - type EdgeWeight = TriangulationEdgeWeight; + type NodeWeight = VW; + type EdgeWeight = TriangulationEdgeWeightWrapper; } #[derive(Debug, Clone, Copy, PartialEq)] -pub struct TriangulationEdgeReference { +pub struct TriangulationEdgeReference { from: I, to: I, - weight: TriangulationEdgeWeight, + weight: TriangulationEdgeWeightWrapper, } -impl visit::EdgeRef for TriangulationEdgeReference { +impl visit::EdgeRef for TriangulationEdgeReference { type NodeId = I; type EdgeId = (I, I); - type Weight = TriangulationEdgeWeight; + type Weight = TriangulationEdgeWeightWrapper; fn source(&self) -> Self::NodeId { self.from @@ -116,8 +142,12 @@ impl visit::EdgeRef for TriangulationEdgeReference { } } -impl<'a, I: Copy + PartialEq + GetNodeIndex, W: GetVertexIndex + HasPosition> - visit::IntoNeighbors for &'a Triangulation +impl< + 'a, + I: Copy + PartialEq + GetNodeIndex, + VW: GetVertexIndex + HasPosition, + EW: Copy + Default, + > visit::IntoNeighbors for &'a Triangulation { type Neighbors = Box + 'a>; @@ -130,22 +160,28 @@ impl<'a, I: Copy + PartialEq + GetNodeIndex, W: GetVertexIndex + HasPosition< } } -impl<'a, I: Copy + PartialEq + GetNodeIndex, W: GetVertexIndex + HasPosition> - visit::IntoEdgeReferences for &'a Triangulation +impl< + 'a, + I: Copy + PartialEq + GetNodeIndex, + VW: GetVertexIndex + HasPosition, + EW: Copy + Default, + > visit::IntoEdgeReferences for &'a Triangulation { - type EdgeRef = TriangulationEdgeReference; - type EdgeReferences = Box> + 'a>; + type EdgeRef = TriangulationEdgeReference; + type EdgeReferences = Box> + 'a>; fn edge_references(self) -> Self::EdgeReferences { Box::new( spade::Triangulation::directed_edges(&self.triangulation).map(|edge| { let from = self.vertex(edge.from().fix()); let to = self.vertex(edge.to().fix()); + TriangulationEdgeReference { from, to, - weight: TriangulationEdgeWeight { + weight: TriangulationEdgeWeightWrapper { length: self.position(from).euclidean_distance(&self.position(to)), + weight: *edge.data(), }, } }), @@ -153,10 +189,14 @@ impl<'a, I: Copy + PartialEq + GetNodeIndex, W: GetVertexIndex + HasPosition< } } -impl<'a, I: Copy + PartialEq + GetNodeIndex, W: GetVertexIndex + HasPosition> - visit::IntoEdges for &'a Triangulation +impl< + 'a, + I: Copy + PartialEq + GetNodeIndex, + VW: GetVertexIndex + HasPosition, + EW: Copy + Default, + > visit::IntoEdges for &'a Triangulation { - type Edges = Box> + 'a>; + type Edges = Box> + 'a>; fn edges(self, node: Self::NodeId) -> Self::Edges { Box::new( @@ -165,11 +205,13 @@ impl<'a, I: Copy + PartialEq + GetNodeIndex, W: GetVertexIndex + HasPosition< .map(|edge| { let from = self.vertex(edge.from().fix()); let to = self.vertex(edge.to().fix()); + TriangulationEdgeReference { from, to, - weight: TriangulationEdgeWeight { + weight: TriangulationEdgeWeightWrapper { length: self.position(from).euclidean_distance(&self.position(to)), + weight: *edge.data(), }, } }), @@ -177,8 +219,12 @@ impl<'a, I: Copy + PartialEq + GetNodeIndex, W: GetVertexIndex + HasPosition< } } -impl<'a, I: Copy + PartialEq + GetNodeIndex, W: GetVertexIndex + HasPosition> - visit::IntoNodeIdentifiers for &'a Triangulation +impl< + 'a, + I: Copy + PartialEq + GetNodeIndex, + VW: GetVertexIndex + HasPosition, + EW: Copy + Default, + > visit::IntoNodeIdentifiers for &'a Triangulation { type NodeIdentifiers = Box + 'a>; @@ -194,14 +240,14 @@ impl<'a, I: Copy + PartialEq + GetNodeIndex, W: GetVertexIndex + HasPosition< } #[derive(Debug, Clone, Copy, PartialEq)] -pub struct TriangulationVertexReference<'a, I: Copy, W> { +pub struct TriangulationVertexReference<'a, I: Copy, VW> { index: I, - weight: &'a W, + weight: &'a VW, } -impl<'a, I: Copy, W: Copy> visit::NodeRef for TriangulationVertexReference<'a, I, W> { +impl<'a, I: Copy, VW: Copy> visit::NodeRef for TriangulationVertexReference<'a, I, VW> { type NodeId = I; - type Weight = W; + type Weight = VW; fn id(&self) -> Self::NodeId { self.index @@ -215,11 +261,12 @@ impl<'a, I: Copy, W: Copy> visit::NodeRef for TriangulationVertexReference<'a, I impl< 'a, I: Copy + PartialEq + GetNodeIndex, - W: Copy + GetVertexIndex + HasPosition, - > visit::IntoNodeReferences for &'a Triangulation + VW: Copy + GetVertexIndex + HasPosition, + EW: Copy + Default, + > visit::IntoNodeReferences for &'a Triangulation { - type NodeRef = TriangulationVertexReference<'a, I, W>; - type NodeReferences = Box> + 'a>; + type NodeRef = TriangulationVertexReference<'a, I, VW>; + type NodeReferences = Box> + 'a>; fn node_references(self) -> Self::NodeReferences { Box::new( @@ -237,8 +284,9 @@ impl< impl< 'a, I: Copy + PartialEq + GetNodeIndex + std::fmt::Debug, - W: GetVertexIndex + HasPosition, - > visit::NodeIndexable for &'a Triangulation + VW: GetVertexIndex + HasPosition, + EW: Copy + Default, + > visit::NodeIndexable for &'a Triangulation { fn node_bound(&self) -> usize { //spade::Triangulation::num_vertices(&self.triangulation)