feat(autorouter/ratline): Only count interior ratline intersections

This hardly makes a difference for now, but may become useful later.
This commit is contained in:
Mikolaj Wielgus 2025-09-04 17:00:22 +02:00
parent b49aa9e1b7
commit e5e5f9513e
2 changed files with 49 additions and 28 deletions

View File

@ -115,8 +115,8 @@ impl<M: AccessMesadata> Autorouter<M> {
match options.presort_by { match options.presort_by {
PresortBy::RatlineIntersectionCountAndLength => ratlines.sort_unstable_by(|a, b| { PresortBy::RatlineIntersectionCountAndLength => ratlines.sort_unstable_by(|a, b| {
let a_intersector_count = a.ref_(self).find_intersecting_ratlines().count(); let a_intersector_count = a.ref_(self).interior_obstacle_ratlines().count();
let b_intersector_count = b.ref_(self).find_intersecting_ratlines().count(); let b_intersector_count = b.ref_(self).interior_obstacle_ratlines().count();
let primary_ordering = a_intersector_count.cmp(&b_intersector_count); let primary_ordering = a_intersector_count.cmp(&b_intersector_count);

View File

@ -2,8 +2,8 @@
// //
// SPDX-License-Identifier: MIT OR Apache-2.0 // SPDX-License-Identifier: MIT OR Apache-2.0
use geo::{line_intersection::line_intersection, Distance, Euclidean, Line}; use geo::{line_intersection::line_intersection, Distance, Euclidean, Line, LineIntersection};
use petgraph::graph::EdgeIndex; use petgraph::graph::{EdgeIndex, NodeIndex};
use specctra_core::mesadata::AccessMesadata; use specctra_core::mesadata::AccessMesadata;
use crate::{ use crate::{
@ -74,26 +74,25 @@ impl<'a, M: AccessMesadata> RatlineRef<'a, M> {
(source_dot, target_dot) (source_dot, target_dot)
} }
pub fn find_intersecting_ratlines(&self) -> impl Iterator<Item = RatlineIndex> + '_ { pub fn closure_obstacle_ratlines(&self) -> impl Iterator<Item = RatlineIndex> + '_ {
let self_line = self.line(); self.intersecting_ratlines()
}
pub fn interior_obstacle_ratlines(&self) -> impl Iterator<Item = RatlineIndex> + '_ {
self.intersecting_ratlines()
.filter(|index| !self.is_pin_cutter(*index))
}
fn intersecting_ratlines(&self) -> impl Iterator<Item = RatlineIndex> + '_ {
let self_line_segment = self.line_segment();
self.autorouter self.autorouter
.ratsnest() .ratsnest()
.graph() .graph()
.edge_indices() .edge_indices()
.filter(move |other| { .filter(move |other| {
let (self_source, self_target) = self let (self_source, self_target) = self.endpoint_indices();
.autorouter let (other_source, other_target) = other.ref_(self.autorouter).endpoint_indices();
.ratsnest
.graph()
.edge_endpoints(self.index)
.unwrap();
let (other_source, other_target) = self
.autorouter
.ratsnest
.graph()
.edge_endpoints(*other)
.unwrap();
self_source != other_source self_source != other_source
&& self_source != other_target && self_source != other_target
@ -101,19 +100,33 @@ impl<'a, M: AccessMesadata> RatlineRef<'a, M> {
&& self_target != other_target && self_target != other_target
}) })
.filter(move |other| { .filter(move |other| {
let other_line = other.ref_(self.autorouter).line(); let other_line_segment = other.ref_(self.autorouter).line_segment();
line_intersection(self_line, other_line).is_some() line_intersection(self_line_segment, other_line_segment).is_some()
}) })
} }
pub fn line(&self) -> Line { fn is_pin_cutter(&self, other: RatlineIndex) -> bool {
let (source, target) = self // TODO: For now, instead of detecting whether endpoint ratvertex pins
.autorouter // are cut, we only check if the intersection between self and the
.ratsnest // supposed cutter is not internal.
.graph()
.edge_endpoints(self.index) let self_line_segment = self.line_segment();
.unwrap(); let other_line_segment = other.ref_(self.autorouter).line_segment();
if let Some(LineIntersection::SinglePoint { is_proper, .. }) =
line_intersection(self_line_segment, other_line_segment)
{
// It would make more sense to check for non-internality only in
// self, but this gives me the result I want too for now.
!is_proper
} else {
false
}
}
pub fn line_segment(&self) -> Line {
let (source, target) = self.endpoint_indices();
let source_pos = self let source_pos = self
.autorouter .autorouter
.ratsnest .ratsnest
@ -131,11 +144,19 @@ impl<'a, M: AccessMesadata> RatlineRef<'a, M> {
Line::new(source_pos, target_pos) Line::new(source_pos, target_pos)
} }
fn endpoint_indices(&self) -> (NodeIndex<usize>, NodeIndex<usize>) {
self.autorouter
.ratsnest
.graph()
.edge_endpoints(self.index)
.unwrap()
}
} }
impl<'a, M: AccessMesadata> MeasureLength for RatlineRef<'a, M> { impl<'a, M: AccessMesadata> MeasureLength for RatlineRef<'a, M> {
fn length(&self) -> f64 { fn length(&self) -> f64 {
let line = self.line(); let line = self.line_segment();
Euclidean::distance(&line.start_point(), &line.end_point()) Euclidean::distance(&line.start_point(), &line.end_point())
} }