diff --git a/src/autorouter/ratsnest.rs b/src/autorouter/ratsnest.rs index b5016ff..b393a9c 100644 --- a/src/autorouter/ratsnest.rs +++ b/src/autorouter/ratsnest.rs @@ -2,12 +2,15 @@ // // SPDX-License-Identifier: MIT -use std::collections::BTreeMap; +use std::{ + collections::BTreeMap, + ops::{Index, IndexMut}, +}; use enum_dispatch::enum_dispatch; use geo::Point; use petgraph::{data::Element, prelude::StableUnGraph, visit::NodeIndexable}; -use spade::{HasPosition, InsertionError, Point2}; +use spade::{handles::FixedVertexHandle, HasPosition, InsertionError, Point2}; use crate::{ autorouter::conncomps::Conncomps, @@ -64,6 +67,41 @@ impl HasPosition for RatvertexWeight { } } +#[derive(Clone)] +struct RatvertexToHandleMap { + fixed_dot_to_handle: Box<[Option]>, + poly_to_handle: Box<[Option]>, +} + +impl RatvertexToHandleMap { + pub fn new(fixed_dot_bound: usize, poly_bound: usize) -> Self { + Self { + fixed_dot_to_handle: vec![None; fixed_dot_bound].into_boxed_slice(), + poly_to_handle: vec![None; poly_bound].into_boxed_slice(), + } + } +} + +impl Index for RatvertexToHandleMap { + type Output = Option; + + fn index(&self, ratvertex: RatvertexIndex) -> &Self::Output { + match ratvertex { + RatvertexIndex::FixedDot(dot) => &self.fixed_dot_to_handle[dot.index()], + RatvertexIndex::Poly(bend) => &self.poly_to_handle[bend.index()], + } + } +} + +impl IndexMut for RatvertexToHandleMap { + fn index_mut(&mut self, ratvertex: RatvertexIndex) -> &mut Self::Output { + match ratvertex { + RatvertexIndex::FixedDot(dot) => &mut self.fixed_dot_to_handle[dot.index()], + RatvertexIndex::Poly(bend) => &mut self.poly_to_handle[bend.index()], + } + } +} + pub struct Ratsnest { graph: StableUnGraph, } @@ -77,7 +115,6 @@ impl Ratsnest { }; let mut triangulations = BTreeMap::new(); - let node_bound = layout.drawing().geometry().graph().node_bound(); for layer in 0..layout.drawing().layer_count() { let mut handle_ratvertex_weight = @@ -85,7 +122,12 @@ impl Ratsnest { if let Some(net) = maybe_net { triangulations .entry((layer, net)) - .or_insert_with(|| Triangulation::new(node_bound)) + .or_insert_with(|| { + Triangulation::new(RatvertexToHandleMap::new( + layout.drawing().geometry().dot_index_bound(), + layout.drawing().geometry().compound_index_bound(), + )) + }) .add_vertex(RatvertexWeight { vertex, pos })?; } Ok(()) diff --git a/src/geometry/geometry.rs b/src/geometry/geometry.rs index 74556a4..2e1dae8 100644 --- a/src/geometry/geometry.rs +++ b/src/geometry/geometry.rs @@ -530,6 +530,10 @@ impl< pub fn bend_index_bound(&self) -> usize { self.graph.node_bound() } + + pub fn compound_index_bound(&self) -> usize { + self.graph.node_bound() + } } impl, DW, SW, BW, CW, Cel, PI, DI, SI, BI> diff --git a/src/router/navmesh.rs b/src/router/navmesh.rs index 4e4f3f4..dd3a8e8 100644 --- a/src/router/navmesh.rs +++ b/src/router/navmesh.rs @@ -13,7 +13,7 @@ use petgraph::{ unionfind::UnionFind, visit::{ Data, EdgeRef, GraphBase, IntoEdgeReferences, IntoEdges, IntoNeighbors, - IntoNodeIdentifiers, NodeIndexable, Walker, + IntoNodeIdentifiers, Walker, }, }; use spade::InsertionError; @@ -163,7 +163,8 @@ impl Navmesh { let mut prenavnode_to_navnodes = BTreeMap::new(); let mut overlapping_prenavnodes_unions = - UnionFind::new(prenavmesh.triangulation().node_bound()); + // FIXME: This bound is incorrect. You can't actually unionize dots with bends. + UnionFind::new(layout.drawing().geometry().dot_index_bound()); for prenavnode in prenavmesh.triangulation().node_identifiers() { if prenavnode == origin.into() { diff --git a/src/router/prenavmesh.rs b/src/router/prenavmesh.rs index 83956b5..0cbfd1a 100644 --- a/src/router/prenavmesh.rs +++ b/src/router/prenavmesh.rs @@ -2,11 +2,13 @@ // // SPDX-License-Identifier: MIT OR Apache-2.0 +use std::ops::{Index, IndexMut}; + use derive_getters::Getters; use enum_dispatch::enum_dispatch; use geo::Point; use petgraph::visit::NodeIndexable; -use spade::{HasPosition, InsertionError, Point2}; +use spade::{handles::FixedVertexHandle, HasPosition, InsertionError, Point2}; use crate::{ drawing::{ @@ -128,9 +130,44 @@ impl PrenavmeshConstraint { } } +#[derive(Clone)] +pub struct PrenavnodeToHandleMap { + fixed_dot_to_handle: Box<[Option]>, + fixed_bend_to_handle: Box<[Option]>, +} + +impl PrenavnodeToHandleMap { + pub fn new(fixed_dot_bound: usize, fixed_bend_bound: usize) -> Self { + Self { + fixed_dot_to_handle: vec![None; fixed_dot_bound].into_boxed_slice(), + fixed_bend_to_handle: vec![None; fixed_bend_bound].into_boxed_slice(), + } + } +} + +impl Index for PrenavnodeToHandleMap { + type Output = Option; + + fn index(&self, prenavnode: PrenavmeshNodeIndex) -> &Self::Output { + match prenavnode { + PrenavmeshNodeIndex::FixedDot(dot) => &self.fixed_dot_to_handle[dot.index()], + PrenavmeshNodeIndex::FixedBend(bend) => &self.fixed_bend_to_handle[bend.index()], + } + } +} + +impl IndexMut for PrenavnodeToHandleMap { + fn index_mut(&mut self, prenavnode: PrenavmeshNodeIndex) -> &mut Self::Output { + match prenavnode { + PrenavmeshNodeIndex::FixedDot(dot) => &mut self.fixed_dot_to_handle[dot.index()], + PrenavmeshNodeIndex::FixedBend(bend) => &mut self.fixed_bend_to_handle[bend.index()], + } + } +} + #[derive(Clone, Getters)] pub struct Prenavmesh { - triangulation: Triangulation, + triangulation: Triangulation, constraints: Vec, } @@ -142,7 +179,10 @@ impl Prenavmesh { _options: RouterOptions, ) -> Result { let mut this = Self { - triangulation: Triangulation::new(layout.drawing().geometry().graph().node_bound()), + triangulation: Triangulation::new(PrenavnodeToHandleMap::new( + layout.drawing().geometry().dot_index_bound(), + layout.drawing().geometry().bend_index_bound(), + )), constraints: vec![], }; diff --git a/src/triangulation.rs b/src/triangulation.rs index d13196f..f7dae5b 100644 --- a/src/triangulation.rs +++ b/src/triangulation.rs @@ -2,6 +2,7 @@ // // SPDX-License-Identifier: MIT +use std::ops::IndexMut; use std::{cmp::Ordering, marker::PhantomData}; use geo::algorithm::line_measures::{Distance, Euclidean}; @@ -21,33 +22,37 @@ pub trait GetTrianvertexNodeIndex { // not implement `Debug`, though it could (and `spade::DelaunayTriangulation` // actually does). #[derive(Clone)] -pub struct Triangulation + HasPosition, EW: Default> { +pub struct Triangulation + HasPosition, EW: Default> { cdt: ConstrainedDelaunayTriangulation, - trianvertex_to_handle: Box<[Option]>, + trianvertex_to_handle: M, index_marker: PhantomData, } -impl + HasPosition, EW: Default> - Triangulation +impl< + I: GetIndex, + M: IndexMut>, + VW: GetTrianvertexNodeIndex + HasPosition, + EW: Default, + > Triangulation { - pub fn new(node_bound: usize) -> Self { + pub fn new(trianvertex_to_handle: M) -> Self { Self { cdt: as spade::Triangulation>::new(), - trianvertex_to_handle: vec![None; node_bound].into_boxed_slice(), + trianvertex_to_handle, index_marker: PhantomData, } } pub fn add_vertex(&mut self, weight: VW) -> Result<(), InsertionError> { - let index = weight.node_index().index(); + let index = weight.node_index(); self.trianvertex_to_handle[index] = Some(spade::Triangulation::insert(&mut self.cdt, weight)?); Ok(()) } pub fn add_constraint_edge(&mut self, from: VW, to: VW) -> Result { - let from_index = from.node_index().index(); - let to_index = to.node_index().index(); + let from_index = from.node_index(); + let to_index = to.node_index(); // It is possible for one or both constraint edge endpoint vertices to // not exist in the triangulation even after everything has been added. @@ -74,14 +79,13 @@ impl + HasPosition, EW: Default> } pub fn weight(&self, vertex: I) -> &VW { - spade::Triangulation::s(&self.cdt) - .vertex_data(self.trianvertex_to_handle[vertex.index()].unwrap()) + spade::Triangulation::s(&self.cdt).vertex_data(self.trianvertex_to_handle[vertex].unwrap()) } pub fn weight_mut(&mut self, vertex: I) -> &mut VW { spade::Triangulation::vertex_data_mut( &mut self.cdt, - self.trianvertex_to_handle[vertex.index()].unwrap(), + self.trianvertex_to_handle[vertex].unwrap(), ) } @@ -92,7 +96,7 @@ impl + HasPosition, EW: Default> } fn handle(&self, vertex: I) -> FixedVertexHandle { - self.trianvertex_to_handle[vertex.index()].unwrap() + self.trianvertex_to_handle[vertex].unwrap() } pub fn position(&self, vertex: I) -> Point<::Scalar> @@ -104,8 +108,12 @@ impl + HasPosition, EW: Default> } } -impl + HasPosition, EW: Default> - visit::GraphBase for Triangulation +impl< + I: Copy + PartialEq + GetIndex, + M: IndexMut>, + VW: GetTrianvertexNodeIndex + HasPosition, + EW: Default, + > visit::GraphBase for Triangulation { type NodeId = I; type EdgeId = (I, I); @@ -131,9 +139,10 @@ impl PartialOrd for TriangulationEdgeWeightWrapper { impl< I: Copy + PartialEq + GetIndex, + M: IndexMut>, VW: GetTrianvertexNodeIndex + HasPosition, EW: Copy + Default, - > visit::Data for Triangulation + > visit::Data for Triangulation { type NodeWeight = VW; type EdgeWeight = TriangulationEdgeWeightWrapper; @@ -171,9 +180,10 @@ impl visit::EdgeRef for TriangulationEdgeReference { impl< 'a, I: Copy + PartialEq + GetIndex, + M: IndexMut>, VW: GetTrianvertexNodeIndex + HasPosition, EW: Default, - > visit::IntoNeighbors for &'a Triangulation + > visit::IntoNeighbors for &'a Triangulation { type Neighbors = Box + 'a>; @@ -189,9 +199,10 @@ impl< impl< 'a, I: Copy + PartialEq + GetIndex, + M: IndexMut>, VW: GetTrianvertexNodeIndex + HasPosition, EW: Copy + Default, - > visit::IntoEdgeReferences for &'a Triangulation + > visit::IntoEdgeReferences for &'a Triangulation { type EdgeRef = TriangulationEdgeReference; type EdgeReferences = Box> + 'a>; @@ -216,9 +227,10 @@ impl< impl< 'a, I: Copy + PartialEq + GetIndex, + M: IndexMut>, VW: GetTrianvertexNodeIndex + HasPosition, EW: Copy + Default, - > visit::IntoEdges for &'a Triangulation + > visit::IntoEdges for &'a Triangulation { type Edges = Box> + 'a>; @@ -246,9 +258,10 @@ impl< impl< 'a, I: Copy + PartialEq + GetIndex, + M: IndexMut>, VW: GetTrianvertexNodeIndex + HasPosition, EW: Default, - > visit::IntoNodeIdentifiers for &'a Triangulation + > visit::IntoNodeIdentifiers for &'a Triangulation { type NodeIdentifiers = Box + 'a>; @@ -296,9 +309,10 @@ impl visit::NodeRef for TriangulationVertexReference<'_, I, VW> { impl< 'a, I: Copy + PartialEq + GetIndex, + M: IndexMut>, VW: GetTrianvertexNodeIndex + HasPosition, EW: Copy + Default, - > visit::IntoNodeReferences for &'a Triangulation + > visit::IntoNodeReferences for &'a Triangulation { type NodeRef = TriangulationVertexReference<'a, I, VW>; type NodeReferences = Box> + 'a>; @@ -318,22 +332,25 @@ impl< impl< I: Copy + PartialEq + GetIndex + std::fmt::Debug, + M: IndexMut>, VW: GetTrianvertexNodeIndex + HasPosition, EW: Default, - > visit::NodeIndexable for &Triangulation + > visit::NodeIndexable for &Triangulation { fn node_bound(&self) -> usize { - //spade::Triangulation::num_vertices(&self.triangulation) - self.trianvertex_to_handle.len() + //self.cdt.num_vertices() + spade::Triangulation::num_vertices(&self.cdt) + //FixedVertexHandle::max() + //Self::new_internal(u32::MAX) } fn to_index(&self, node: I) -> usize { - node.index() + self.trianvertex_to_handle[node].unwrap().index() } fn from_index(&self, index: usize) -> I { spade::Triangulation::s(&self.cdt) - .vertex_data(self.trianvertex_to_handle[index].unwrap()) + .vertex_data(FixedVertexHandle::from_index(index)) .node_index() } }