mirror of https://codeberg.org/topola/topola.git
feat(autorouter/presorter): Take into account ratline-pad intersections
This commit is contained in:
parent
1b485e81a6
commit
aee8c42720
|
|
@ -168,7 +168,6 @@ impl SpecctraMesadata {
|
|||
/// associated with a net class. If a net class is found, it retrieves the corresponding rule
|
||||
/// from the class rules. If no class is associated, or if the class does not have a defined rule,
|
||||
/// it defaults to the general structure rule.
|
||||
///
|
||||
pub fn get_rule(&self, net: usize) -> &SpecctraRule {
|
||||
self.net_netclass
|
||||
.get(&net)
|
||||
|
|
@ -179,10 +178,10 @@ impl SpecctraMesadata {
|
|||
|
||||
impl AccessRules for SpecctraMesadata {
|
||||
fn clearance(&self, conditions1: &Conditions<'_>, conditions2: &Conditions<'_>) -> f64 {
|
||||
let clr1 = self.get_rule(conditions1.net).clearance;
|
||||
let clr2 = self.get_rule(conditions2.net).clearance;
|
||||
let clearance1 = self.get_rule(conditions1.net).clearance;
|
||||
let clearance2 = self.get_rule(conditions2.net).clearance;
|
||||
|
||||
f64::max(clr1, clr2)
|
||||
f64::max(clearance1, clearance2)
|
||||
}
|
||||
|
||||
fn largest_clearance(&self, _maybe_net: Option<usize>) -> f64 {
|
||||
|
|
|
|||
|
|
@ -63,10 +63,10 @@ impl SccIntersectionsAndLengthPresorter {
|
|||
&& a.contains(&filtered_ratsnest.edge_endpoints(*ratline).unwrap().1)
|
||||
{
|
||||
a_length += ratline.ref_(autorouter).length();
|
||||
a_intersector_count += ratline
|
||||
.ref_(autorouter)
|
||||
.interior_obstacle_ratlines()
|
||||
.count();
|
||||
a_intersector_count +=
|
||||
ratline.ref_(autorouter).interiorly_cut_ratlines().count();
|
||||
a_intersector_count +=
|
||||
ratline.ref_(autorouter).cut_other_net_primitives().count();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -75,10 +75,10 @@ impl SccIntersectionsAndLengthPresorter {
|
|||
&& b.contains(&filtered_ratsnest.edge_endpoints(*ratline).unwrap().1)
|
||||
{
|
||||
b_length += ratline.ref_(autorouter).length();
|
||||
b_intersector_count += ratline
|
||||
.ref_(autorouter)
|
||||
.interior_obstacle_ratlines()
|
||||
.count();
|
||||
b_intersector_count +=
|
||||
ratline.ref_(autorouter).interiorly_cut_ratlines().count();
|
||||
b_intersector_count +=
|
||||
ratline.ref_(autorouter).cut_other_net_primitives().count();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -7,8 +7,12 @@ use petgraph::graph::{EdgeIndex, NodeIndex};
|
|||
use specctra_core::mesadata::AccessMesadata;
|
||||
|
||||
use crate::{
|
||||
drawing::{band::BandTermsegIndex, dot::FixedDotIndex},
|
||||
geometry::shape::MeasureLength,
|
||||
drawing::{
|
||||
band::BandTermsegIndex,
|
||||
dot::FixedDotIndex,
|
||||
graph::{GetMaybeNet, MakePrimitive, PrimitiveIndex},
|
||||
},
|
||||
geometry::{shape::MeasureLength, GetLayer},
|
||||
graph::MakeRef,
|
||||
triangulation::GetTrianvertexNodeIndex,
|
||||
};
|
||||
|
|
@ -84,16 +88,40 @@ impl<'a, M: AccessMesadata> RatlineRef<'a, M> {
|
|||
(source_dot, target_dot)
|
||||
}
|
||||
|
||||
pub fn closure_obstacle_ratlines(&self) -> impl Iterator<Item = RatlineIndex> + '_ {
|
||||
self.intersecting_ratlines()
|
||||
pub fn layer(&self) -> usize {
|
||||
self.endpoint_dots()
|
||||
.0
|
||||
.primitive(self.autorouter.board().layout().drawing())
|
||||
.layer()
|
||||
}
|
||||
|
||||
pub fn interior_obstacle_ratlines(&self) -> impl Iterator<Item = RatlineIndex> + '_ {
|
||||
self.intersecting_ratlines()
|
||||
.filter(|index| !self.is_pin_cutter(*index))
|
||||
pub fn net(&self) -> usize {
|
||||
self.endpoint_dots()
|
||||
.0
|
||||
.primitive(self.autorouter.board().layout().drawing())
|
||||
.maybe_net()
|
||||
.unwrap()
|
||||
}
|
||||
|
||||
fn intersecting_ratlines(&self) -> impl Iterator<Item = RatlineIndex> + '_ {
|
||||
fn cut_primitives(&self) -> impl Iterator<Item = PrimitiveIndex> + '_ {
|
||||
self.autorouter
|
||||
.board()
|
||||
.layout()
|
||||
.drawing()
|
||||
.cut(self.line_segment(), 0.0, self.layer())
|
||||
}
|
||||
|
||||
pub fn cut_other_net_primitives(&self) -> impl Iterator<Item = PrimitiveIndex> + '_ {
|
||||
self.cut_primitives().filter(|primitive_node| {
|
||||
primitive_node
|
||||
.primitive(self.autorouter.board().layout().drawing())
|
||||
.maybe_net()
|
||||
.map(|net| net != self.net())
|
||||
.unwrap_or(true)
|
||||
})
|
||||
}
|
||||
|
||||
pub fn interiorly_cut_ratlines(&self) -> impl Iterator<Item = RatlineIndex> + '_ {
|
||||
let self_line_segment = self.line_segment();
|
||||
|
||||
self.autorouter
|
||||
|
|
@ -112,29 +140,18 @@ impl<'a, M: AccessMesadata> RatlineRef<'a, M> {
|
|||
.filter(move |other| {
|
||||
let other_line_segment = other.ref_(self.autorouter).line_segment();
|
||||
|
||||
line_intersection(self_line_segment, other_line_segment).is_some()
|
||||
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
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
fn is_pin_cutter(&self, other: RatlineIndex) -> bool {
|
||||
// TODO: For now, instead of detecting whether endpoint ratvertex pins
|
||||
// are cut, we only check if the intersection between self and the
|
||||
// supposed cutter is not internal.
|
||||
|
||||
let self_line_segment = self.line_segment();
|
||||
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
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@
|
|||
//
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
use geo::Line;
|
||||
use petgraph::visit::Walker;
|
||||
use specctra_core::rules::GetConditions;
|
||||
|
||||
|
|
@ -11,7 +12,10 @@ use crate::{
|
|||
primitive::MakePrimitiveShape,
|
||||
Collision, Infringement,
|
||||
},
|
||||
geometry::{primitive::AccessPrimitiveShape, GenericNode, GetLayer},
|
||||
geometry::{
|
||||
primitive::{AccessPrimitiveShape, PrimitiveShape, SegShape},
|
||||
GenericNode, GetLayer,
|
||||
},
|
||||
graph::GenericIndex,
|
||||
};
|
||||
|
||||
|
|
@ -112,6 +116,36 @@ impl<CW: Clone, Cel: Copy, R: AccessRules> Drawing<CW, Cel, R> {
|
|||
v
|
||||
}
|
||||
|
||||
pub fn cut(
|
||||
&self,
|
||||
line: Line,
|
||||
width: f64,
|
||||
layer: usize,
|
||||
) -> impl Iterator<Item = PrimitiveIndex> + '_ {
|
||||
let limiting_shape = PrimitiveShape::Seg(SegShape {
|
||||
from: line.start_point(),
|
||||
to: line.end_point(),
|
||||
width,
|
||||
})
|
||||
.inflate(self.rules().largest_clearance(None));
|
||||
|
||||
self.recording_geometry_with_rtree()
|
||||
.rtree()
|
||||
.locate_in_envelope_intersecting(&limiting_shape.envelope_3d(width, layer))
|
||||
.filter_map(|wrapper| {
|
||||
if let GenericNode::Primitive(primitive_node) = wrapper.data {
|
||||
Some(primitive_node)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
})
|
||||
.filter_map(move |primitive_node| {
|
||||
limiting_shape
|
||||
.intersects(&primitive_node.primitive(self).shape())
|
||||
.then_some(primitive_node)
|
||||
})
|
||||
}
|
||||
|
||||
pub(super) fn find_infringement_except<'a>(
|
||||
&'a self,
|
||||
infringer: PrimitiveIndex,
|
||||
|
|
|
|||
|
|
@ -38,6 +38,7 @@ pub trait AccessPrimitiveShape: AccessShape + GetWidth {
|
|||
[
|
||||
envelope.upper()[0],
|
||||
envelope.upper()[1],
|
||||
// XXX: Why isn't floating point infinity used here?
|
||||
(layer_count - 1) as f64,
|
||||
],
|
||||
)
|
||||
|
|
|
|||
Loading…
Reference in New Issue