From c14f2d2e374b614f8991f2637d63c4af50c5c264 Mon Sep 17 00:00:00 2001 From: Mikolaj Wielgus Date: Wed, 24 Sep 2025 01:50:55 +0200 Subject: [PATCH] fix(autorouter/ratsnest): Prioritize principal layer ratlines over others --- src/autorouter/ratsnest.rs | 113 +++++++++++++++++++++++-------------- src/triangulation.rs | 11 ++++ 2 files changed, 81 insertions(+), 43 deletions(-) diff --git a/src/autorouter/ratsnest.rs b/src/autorouter/ratsnest.rs index 079e9e6..3b56a00 100644 --- a/src/autorouter/ratsnest.rs +++ b/src/autorouter/ratsnest.rs @@ -106,7 +106,8 @@ pub struct Ratsnest { impl Ratsnest { pub fn new(board: &Board) -> Result { - let conncomps = ConncompsWithPrincipalLayer::new(board, 0); + let principal_layer = 0; + let conncomps = ConncompsWithPrincipalLayer::new(board, principal_layer); let mut this = Self { graph: StableUnGraph::default(), @@ -114,49 +115,11 @@ impl Ratsnest { let mut triangulations = BTreeMap::new(); + this.add_layer_to_ratsnest(board, &mut triangulations, principal_layer); + for layer in 0..board.layout().drawing().layer_count() { - let mut handle_ratvertex_weight = - |maybe_net: Option, vertex: RatvertexIndex, pos: Point| { - if let Some(net) = maybe_net { - triangulations - .entry(net) - .or_insert_with(|| { - Triangulation::new(RatvertexToHandleMap::new( - board.layout().drawing().geometry().dot_index_bound(), - board.layout().drawing().geometry().compound_index_bound(), - )) - }) - .add_vertex(RatvertexWeight { vertex, pos })?; - } - Ok(()) - }; - - for node in board.layout().drawing().layer_primitive_nodes(layer) { - if let PrimitiveIndex::FixedDot(dot) = node { - // Dots that are parts of polys are ignored because ratlines - // should only go to their centerpoints. - if board.layout().drawing().compounds(dot).next().is_none() { - handle_ratvertex_weight( - board.layout().drawing().primitive(dot).maybe_net(), - RatvertexIndex::FixedDot(dot), - node.primitive_ref(board.layout().drawing()) - .shape() - .center(), - )?; - } - } - } - - for poly in board.layout().layer_poly_nodes(layer) { - handle_ratvertex_weight( - board - .layout() - .drawing() - .compound_weight(poly.into()) - .maybe_net(), - RatvertexIndex::Poly(poly), - poly.ref_(board.layout()).shape().center(), - )?; + if layer != principal_layer { + this.add_layer_to_ratsnest(board, &mut triangulations, layer); } } @@ -192,6 +155,70 @@ impl Ratsnest { Ok(this) } + fn add_layer_to_ratsnest( + &mut self, + board: &Board, + triangulations: &mut BTreeMap< + usize, + Triangulation, + >, + layer: usize, + ) -> Result<(), InsertionError> { + let mut handle_ratvertex_weight = + |maybe_net: Option, vertex: RatvertexIndex, pos: Point| { + let Some(net) = maybe_net else { + return Ok(()); + }; + + let triangulation = triangulations.entry(net).or_insert_with(|| { + Triangulation::new(RatvertexToHandleMap::new( + board.layout().drawing().geometry().dot_index_bound(), + board.layout().drawing().geometry().compound_index_bound(), + )) + }); + + // If a vertex already exists at `pos` for this net, skip. + // This should prevent overwriting principal layer vertices + // with ones from non-principal layers. + if triangulation.find_vertex_at_position(pos).is_some() { + return Ok(()); + } + + triangulation.add_vertex(RatvertexWeight { vertex, pos })?; + Ok(()) + }; + + for node in board.layout().drawing().layer_primitive_nodes(layer) { + if let PrimitiveIndex::FixedDot(dot) = node { + // Dots that are parts of polys are ignored because ratlines + // should only go to their centerpoints. + if board.layout().drawing().compounds(dot).next().is_none() { + handle_ratvertex_weight( + board.layout().drawing().primitive(dot).maybe_net(), + RatvertexIndex::FixedDot(dot), + node.primitive_ref(board.layout().drawing()) + .shape() + .center(), + )?; + } + } + } + + for poly in board.layout().layer_poly_nodes(layer) { + handle_ratvertex_weight( + board + .layout() + .drawing() + .compound_weight(poly.into()) + .maybe_net(), + RatvertexIndex::Poly(poly), + poly.ref_(board.layout()).shape().center(), + )?; + } + + Ok(()) + } + pub fn assign_band_termseg_to_ratline( &mut self, ratline: RatlineIndex, diff --git a/src/triangulation.rs b/src/triangulation.rs index f7dae5b..078b817 100644 --- a/src/triangulation.rs +++ b/src/triangulation.rs @@ -78,6 +78,17 @@ impl< .intersects_constraint(from.position(), to.position()) } + pub fn find_vertex_at_position(&self, position: Point<::Scalar>) -> Option + where + ::Scalar: geo::CoordNum, + { + spade::Triangulation::locate_vertex( + &self.cdt, + spade::Point2::new(position.x(), position.y()), + ) + .map(|handle| self.vertex(handle.fix())) + } + pub fn weight(&self, vertex: I) -> &VW { spade::Triangulation::s(&self.cdt).vertex_data(self.trianvertex_to_handle[vertex].unwrap()) }