feat(drawing/query): Don't infringe or collide primitives on different layers

This commit is contained in:
Mikolaj Wielgus 2025-09-22 01:27:08 +02:00
parent f4b78749b1
commit 00aa79ff31
5 changed files with 25 additions and 20 deletions

View File

@ -162,13 +162,7 @@ impl SpecctraMesadata {
} }
} }
/// Retrieves the Specctra routing rule associated with a specified net ID. pub fn rule(&self, net: usize) -> &SpecctraRule {
///
/// This function looks up the routing rule for a given net ID. It first checks if the net is
/// 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 self.net_netclass
.get(&net) .get(&net)
.and_then(|netclass| self.class_rules.get(netclass)) .and_then(|netclass| self.class_rules.get(netclass))
@ -177,11 +171,15 @@ impl SpecctraMesadata {
} }
impl AccessRules for SpecctraMesadata { impl AccessRules for SpecctraMesadata {
fn clearance(&self, conditions1: &Conditions<'_>, conditions2: &Conditions<'_>) -> f64 { fn clearance(&self, conditions1: &Conditions<'_>, conditions2: &Conditions<'_>) -> Option<f64> {
let clearance1 = self.get_rule(conditions1.net).clearance; if conditions1.maybe_layer != conditions2.maybe_layer {
let clearance2 = self.get_rule(conditions2.net).clearance; return None;
}
f64::max(clearance1, clearance2) let clearance1 = self.rule(conditions1.net).clearance;
let clearance2 = self.rule(conditions2.net).clearance;
Some(f64::max(clearance1, clearance2))
} }
fn largest_clearance(&self, _maybe_net: Option<usize>) -> f64 { fn largest_clearance(&self, _maybe_net: Option<usize>) -> f64 {

View File

@ -26,11 +26,10 @@ pub struct Conditions<'a> {
#[serde(borrow)] #[serde(borrow)]
pub maybe_region: Option<Cow<'a, str>>, pub maybe_region: Option<Cow<'a, str>>,
#[serde(borrow)] pub maybe_layer: Option<usize>,
pub maybe_layer: Option<Cow<'a, str>>,
} }
pub trait AccessRules { pub trait AccessRules {
fn clearance(&self, conditions1: &Conditions<'_>, conditions2: &Conditions<'_>) -> f64; fn clearance(&self, conditions1: &Conditions<'_>, conditions2: &Conditions<'_>) -> Option<f64>;
fn largest_clearance(&self, net: Option<usize>) -> f64; fn largest_clearance(&self, net: Option<usize>) -> f64;
} }

View File

@ -195,7 +195,7 @@ impl<CW: Clone, Cel: Copy, R: AccessRules> Drawing<CW, Cel, R> {
fn clearance(&self, lhs: Option<&Conditions<'_>>, rhs: Option<&Conditions<'_>>) -> f64 { fn clearance(&self, lhs: Option<&Conditions<'_>>, rhs: Option<&Conditions<'_>>) -> f64 {
match (lhs, rhs) { match (lhs, rhs) {
(None, _) | (_, None) => 0.0, (None, _) | (_, None) => 0.0,
(Some(lhs), Some(rhs)) => self.rules().clearance(lhs, rhs), (Some(lhs), Some(rhs)) => self.rules().clearance(lhs, rhs).unwrap_or(0.0),
} }
} }

View File

@ -219,13 +219,13 @@ where
impl<'a, W, CW, Cel, R> GetConditions<'a> for &GenericPrimitive<'a, W, CW, Cel, R> impl<'a, W, CW, Cel, R> GetConditions<'a> for &GenericPrimitive<'a, W, CW, Cel, R>
where where
GenericPrimitive<'a, W, CW, Cel, R>: GetMaybeNet, GenericPrimitive<'a, W, CW, Cel, R>: GetMaybeNet + GetLayer,
{ {
fn conditions(self) -> Option<Conditions<'a>> { fn conditions(self) -> Option<Conditions<'a>> {
self.maybe_net().map(|net| Conditions { self.maybe_net().map(|net| Conditions {
net, net,
maybe_region: Some("A".into()), maybe_region: Some("A".into()), // TODO.
maybe_layer: Some("F.Cu".into()), maybe_layer: Some(self.layer()),
}) })
} }
} }

View File

@ -228,12 +228,16 @@ impl<CW: Clone, Cel: Copy, R: AccessRules> Drawing<CW, Cel, R> {
&conditions, &conditions,
infringee_conditions, infringee_conditions,
) { ) {
(None, _) | (_, None) => 0.0, (None, _) | (_, None) => return None,
(Some(lhs), Some(rhs)) => { (Some(lhs), Some(rhs)) => {
let Some(clearance) = self.rules().clearance(lhs, &rhs) else {
return None;
};
// Note the epsilon comparison. // Note the epsilon comparison.
// XXX: Epsilon is probably too large. But what should // XXX: Epsilon is probably too large. But what should
// it be exactly then? // it be exactly then?
(self.rules().clearance(lhs, &rhs) - epsilon).clamp(0.0, f64::INFINITY) (clearance - epsilon).clamp(0.0, f64::INFINITY)
} }
}); });
@ -298,6 +302,10 @@ impl<CW: Clone, Cel: Copy, R: AccessRules> Drawing<CW, Cel, R> {
}) })
.filter(|collidee| predicate(&self, collider, *collidee)) .filter(|collidee| predicate(&self, collider, *collidee))
.find_map(|collidee| { .find_map(|collidee| {
if collider.primitive_ref(self).layer() != collidee.primitive_ref(self).layer() {
return None;
}
let collidee_shape = collidee.primitive_ref(self).shape(); let collidee_shape = collidee.primitive_ref(self).shape();
if collider_shape.intersects(&collidee_shape) { if collider_shape.intersects(&collidee_shape) {