mirror of https://codeberg.org/topola/topola.git
feat: use topola-rules / put 'AccessRules' into separate crate
This commit is contained in:
parent
67c4933b09
commit
910ab5b76a
|
|
@ -28,6 +28,7 @@ fp-info-cache
|
|||
|
||||
# Lockfiles
|
||||
*.lck
|
||||
.#*
|
||||
|
||||
# ---> Topola
|
||||
*.ses
|
||||
|
|
|
|||
|
|
@ -13,6 +13,7 @@ geo-types.workspace = true
|
|||
serde.workspace = true
|
||||
specctra_derive.path = "../specctra_derive"
|
||||
thiserror.workspace = true
|
||||
topola-rules.path = "../topola-rules"
|
||||
utf8-chars = "3.0"
|
||||
|
||||
[dependencies.rstar]
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ pub mod error;
|
|||
pub mod math;
|
||||
pub mod mesadata;
|
||||
pub mod read;
|
||||
pub mod rules;
|
||||
pub use topola_rules as rules;
|
||||
pub mod structure;
|
||||
pub mod write;
|
||||
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ use bimap::BiBTreeMap;
|
|||
use std::collections::BTreeMap;
|
||||
|
||||
use crate::{
|
||||
rules::{AccessRules, Conditions},
|
||||
rules::{AccessRules, Conditions, OrderedPair},
|
||||
structure::Pcb,
|
||||
};
|
||||
|
||||
|
|
@ -17,7 +17,7 @@ use crate::{
|
|||
///
|
||||
/// This trait implements generic function for accessing or modifying different
|
||||
/// compounds of board parts like nets or layers
|
||||
pub trait AccessMesadata: AccessRules {
|
||||
pub trait AccessMesadata: AccessRules<Scalar = f64, ObjectKind = ()> {
|
||||
/// Renames a layer based on its index.
|
||||
fn bename_layer(&mut self, layer: usize, layername: String);
|
||||
|
||||
|
|
@ -178,19 +178,16 @@ impl SpecctraMesadata {
|
|||
}
|
||||
|
||||
impl AccessRules for SpecctraMesadata {
|
||||
fn clearance(&self, conditions1: &Conditions, conditions2: &Conditions) -> f64 {
|
||||
let (Some(net1), Some(net2)) = (conditions1.maybe_net, conditions2.maybe_net) else {
|
||||
return 0.0;
|
||||
};
|
||||
type Scalar = f64;
|
||||
type ObjectKind = ();
|
||||
|
||||
let clr1 = self.get_rule(net1).clearance;
|
||||
let clr2 = self.get_rule(net2).clearance;
|
||||
fn clearance(&self, conditions: OrderedPair<&Conditions<'_, ()>>) -> f64 {
|
||||
let (conditions1, conditions2) = conditions.into();
|
||||
|
||||
if clr1 > clr2 {
|
||||
clr1
|
||||
} else {
|
||||
clr2
|
||||
}
|
||||
let clr1 = self.get_rule(conditions1.net).clearance;
|
||||
let clr2 = self.get_rule(conditions2.net).clearance;
|
||||
|
||||
f64::max(clr1, clr2)
|
||||
}
|
||||
|
||||
fn largest_clearance(&self, _maybe_net: Option<usize>) -> f64 {
|
||||
|
|
|
|||
|
|
@ -1,19 +0,0 @@
|
|||
// SPDX-FileCopyrightText: 2024 Topola contributors
|
||||
//
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
pub trait GetConditions {
|
||||
fn conditions(&self) -> Conditions;
|
||||
}
|
||||
|
||||
#[derive(Debug, Default)]
|
||||
pub struct Conditions {
|
||||
pub maybe_net: Option<usize>,
|
||||
pub maybe_region: Option<String>,
|
||||
pub maybe_layer: Option<String>,
|
||||
}
|
||||
|
||||
pub trait AccessRules {
|
||||
fn clearance(&self, conditions1: &Conditions, conditions2: &Conditions) -> f64;
|
||||
fn largest_clearance(&self, net: Option<usize>) -> f64;
|
||||
}
|
||||
|
|
@ -0,0 +1,21 @@
|
|||
# SPDX-FileCopyrightText: 2024 Topola contributors
|
||||
#
|
||||
# SPDX-License-Identifier: MIT OR Apache-2.0
|
||||
|
||||
[package]
|
||||
name = "topola-rules"
|
||||
version = "0.1.1"
|
||||
edition = "2021"
|
||||
license = "MIT OR Apache-2.0"
|
||||
repository = "https://codeberg.org/topola/topola"
|
||||
|
||||
[package.metadata.docs.rs]
|
||||
features = ["serde"]
|
||||
|
||||
[dependencies]
|
||||
|
||||
[dependencies.serde]
|
||||
version = "1.0"
|
||||
features = ["derive", "alloc"]
|
||||
default-features = false
|
||||
optional = true
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
# topola-rules
|
||||
|
||||
Generic design rules/clearance handling.
|
||||
|
|
@ -0,0 +1,163 @@
|
|||
// SPDX-FileCopyrightText: 2025 Topola contributors
|
||||
//
|
||||
// SPDX-License-Identifier: MIT OR Apache-2.0
|
||||
//
|
||||
//! Generic design rules/clearance handling.
|
||||
|
||||
#![no_std]
|
||||
|
||||
extern crate alloc;
|
||||
|
||||
use alloc::borrow::Cow;
|
||||
use core::ops;
|
||||
|
||||
#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
||||
#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
|
||||
#[cfg_attr(feature = "serde", serde(from = "(T, T)", into = "(T, T)"))]
|
||||
#[cfg_attr(
|
||||
feature = "serde",
|
||||
serde(bound(
|
||||
deserialize = "T: serde::Deserialize<'de> + Ord",
|
||||
serialize = "T: serde::Serialize + Clone"
|
||||
))
|
||||
)]
|
||||
pub struct OrderedPair<T>(T, T);
|
||||
|
||||
impl<T> ops::Index<bool> for OrderedPair<T> {
|
||||
type Output = T;
|
||||
|
||||
#[inline]
|
||||
fn index(&self, index: bool) -> &T {
|
||||
if index { &self.1 } else { &self.0 }
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Ord> From<(T, T)> for OrderedPair<T> {
|
||||
fn from(mut x: (T, T)) -> Self {
|
||||
if x.0 > x.1 {
|
||||
core::mem::swap(&mut x.0, &mut x.1);
|
||||
}
|
||||
let (a, b) = x;
|
||||
Self(a, b)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> From<OrderedPair<T>> for (T, T) {
|
||||
#[inline(always)]
|
||||
fn from(OrderedPair(a, b): OrderedPair<T>) -> (T, T) {
|
||||
(a, b)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
||||
#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
|
||||
pub struct Conditions<'a, K> {
|
||||
pub net: usize,
|
||||
|
||||
#[cfg_attr(feature = "serde", serde(borrow))]
|
||||
pub maybe_region: Option<Cow<'a, str>>,
|
||||
|
||||
#[cfg_attr(feature = "serde", serde(borrow))]
|
||||
pub maybe_layer: Option<Cow<'a, str>>,
|
||||
|
||||
pub kind: K,
|
||||
}
|
||||
|
||||
impl<K: Copy> Conditions<'_, K> {
|
||||
#[inline]
|
||||
pub fn ref_(&self) -> Conditions<'_, K> {
|
||||
Conditions {
|
||||
net: self.net,
|
||||
maybe_region: self.maybe_region.as_ref().map(|i| Cow::Borrowed(&**i)),
|
||||
maybe_layer: self.maybe_layer.as_ref().map(|i| Cow::Borrowed(&**i)),
|
||||
kind: self.kind,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub trait GetConditions<'a>: Sized {
|
||||
type ObjectKind: Copy + Eq;
|
||||
|
||||
#[inline(always)]
|
||||
fn conditions(self) -> Option<Conditions<'a, Self::ObjectKind>> {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, K: Copy + Eq> GetConditions<'a> for &'a Conditions<'_, K> {
|
||||
type ObjectKind = K;
|
||||
|
||||
#[inline]
|
||||
fn conditions(self) -> Option<Conditions<'a, K>> {
|
||||
Some(self.ref_())
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, T: Copy + GetConditions<'a>> GetConditions<'a> for &T {
|
||||
type ObjectKind = <T as GetConditions<'a>>::ObjectKind;
|
||||
|
||||
#[inline(always)]
|
||||
fn conditions(self) -> Option<Conditions<'a, <T as GetConditions<'a>>::ObjectKind>> {
|
||||
T::conditions(*self)
|
||||
}
|
||||
}
|
||||
|
||||
pub trait GetWidth {
|
||||
type Scalar: Copy;
|
||||
|
||||
fn width(&self) -> Self::Scalar;
|
||||
}
|
||||
|
||||
impl<T: GetWidth> GetWidth for &T {
|
||||
type Scalar = <T as GetWidth>::Scalar;
|
||||
|
||||
#[inline(always)]
|
||||
fn width(&self) -> <T as GetWidth>::Scalar {
|
||||
T::width(*self)
|
||||
}
|
||||
}
|
||||
|
||||
pub trait AccessRules {
|
||||
type Scalar: Copy + core::ops::Add<Output = Self::Scalar> + core::iter::Sum;
|
||||
type ObjectKind: Copy + Eq;
|
||||
|
||||
fn clearance(&self, conditions: OrderedPair<&Conditions<'_, Self::ObjectKind>>)
|
||||
-> Self::Scalar;
|
||||
fn largest_clearance(&self, maybe_net: Option<usize>) -> Self::Scalar;
|
||||
}
|
||||
|
||||
impl<T: AccessRules + Copy> AccessRules for &T {
|
||||
type Scalar = <T as AccessRules>::Scalar;
|
||||
type ObjectKind = <T as AccessRules>::ObjectKind;
|
||||
|
||||
#[inline(always)]
|
||||
fn clearance(
|
||||
&self,
|
||||
conditions: OrderedPair<&Conditions<'_, <T as AccessRules>::ObjectKind>>,
|
||||
) -> <T as AccessRules>::Scalar {
|
||||
T::clearance(*self, conditions)
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
fn largest_clearance(&self, maybe_net: Option<usize>) -> <T as AccessRules>::Scalar {
|
||||
T::largest_clearance(*self, maybe_net)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: AccessRules + ?Sized> AccessRules for alloc::sync::Arc<T> {
|
||||
type Scalar = <T as AccessRules>::Scalar;
|
||||
type ObjectKind = <T as AccessRules>::ObjectKind;
|
||||
|
||||
#[inline(always)]
|
||||
fn clearance(
|
||||
&self,
|
||||
conditions: OrderedPair<&Conditions<'_, <T as AccessRules>::ObjectKind>>,
|
||||
) -> <T as AccessRules>::Scalar {
|
||||
T::clearance(self, conditions)
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
fn largest_clearance(&self, maybe_net: Option<usize>) -> <T as AccessRules>::Scalar {
|
||||
T::largest_clearance(self, maybe_net)
|
||||
}
|
||||
}
|
||||
|
|
@ -25,7 +25,7 @@ use crate::{
|
|||
dot::FixedDotIndex,
|
||||
graph::{GetMaybeNet, MakePrimitive, PrimitiveIndex},
|
||||
primitive::MakePrimitiveShape,
|
||||
rules::AccessRules,
|
||||
AccessRules,
|
||||
},
|
||||
geometry::shape::AccessShape,
|
||||
graph::{GenericIndex, GetPetgraphIndex},
|
||||
|
|
|
|||
|
|
@ -15,9 +15,8 @@ use super::{
|
|||
graph::MakePrimitive,
|
||||
loose::{GetPrevNextLoose, LooseIndex},
|
||||
primitive::MakePrimitiveShape,
|
||||
rules::AccessRules,
|
||||
seg::{LoneLooseSegIndex, SeqLooseSegIndex},
|
||||
Drawing,
|
||||
AccessRules, Drawing,
|
||||
};
|
||||
|
||||
#[derive(Clone, Copy, Debug)]
|
||||
|
|
|
|||
|
|
@ -8,8 +8,7 @@ use crate::{
|
|||
drawing::{
|
||||
graph::{GetLayer, GetMaybeNet, MakePrimitive, PrimitiveIndex, PrimitiveWeight, Retag},
|
||||
primitive::{GenericPrimitive, Primitive},
|
||||
rules::AccessRules,
|
||||
Drawing,
|
||||
AccessRules, Drawing,
|
||||
},
|
||||
geometry::{GetOffset, GetWidth, SetOffset},
|
||||
graph::{GenericIndex, GetPetgraphIndex},
|
||||
|
|
|
|||
|
|
@ -7,9 +7,8 @@ use super::{
|
|||
dot::LooseDotIndex,
|
||||
graph::PrimitiveIndex,
|
||||
primitive::{GetInterior, GetJoints, GetOtherJoint, LooseBend, LooseDot},
|
||||
rules::AccessRules,
|
||||
seg::SeqLooseSegIndex,
|
||||
Drawing,
|
||||
AccessRules, Drawing,
|
||||
};
|
||||
|
||||
/// A cane is a sequence consisting of a seg followed by a dot followed by a
|
||||
|
|
|
|||
|
|
@ -11,8 +11,7 @@ use super::{
|
|||
graph::PrimitiveIndex,
|
||||
loose::{GetPrevNextLoose, LooseIndex},
|
||||
primitive::{GetInnerOuter, GetJoints},
|
||||
rules::AccessRules,
|
||||
Drawing,
|
||||
AccessRules, Drawing,
|
||||
};
|
||||
|
||||
pub trait Collect {
|
||||
|
|
|
|||
|
|
@ -11,8 +11,7 @@ use crate::{
|
|||
drawing::{
|
||||
graph::{GetLayer, GetMaybeNet, MakePrimitive, PrimitiveIndex, PrimitiveWeight, Retag},
|
||||
primitive::{GenericPrimitive, Primitive},
|
||||
rules::AccessRules,
|
||||
Drawing,
|
||||
AccessRules, Drawing,
|
||||
},
|
||||
geometry::{GetSetPos, GetWidth},
|
||||
graph::{GenericIndex, GetPetgraphIndex},
|
||||
|
|
|
|||
|
|
@ -36,11 +36,12 @@ use crate::{
|
|||
GenericPrimitive, GetCore, GetInnerOuter, GetJoints, GetLimbs, GetOtherJoint,
|
||||
MakePrimitiveShape,
|
||||
},
|
||||
rules::{AccessRules, GetConditions},
|
||||
rules::GetConditions,
|
||||
seg::{
|
||||
FixedSegIndex, FixedSegWeight, LoneLooseSegIndex, LoneLooseSegWeight, SegIndex,
|
||||
SegWeight, SeqLooseSegIndex, SeqLooseSegWeight,
|
||||
},
|
||||
AccessRules,
|
||||
},
|
||||
graph::MakeRef,
|
||||
};
|
||||
|
|
@ -982,8 +983,12 @@ impl<CW: Copy, R: AccessRules> Drawing<CW, R> {
|
|||
|
||||
let epsilon = 1.0;
|
||||
inflated_shape = node.primitive(self).shape().inflate(
|
||||
(self.rules.clearance(&conditions, &infringee_conditions) - epsilon)
|
||||
.clamp(0.0, f64::INFINITY),
|
||||
match (&conditions, infringee_conditions) {
|
||||
(None, _) | (_, None) => 0.0,
|
||||
(Some(lhs), Some(rhs)) => (self.rules.clearance((lhs, &rhs).into())
|
||||
- epsilon)
|
||||
.clamp(0.0, f64::INFINITY),
|
||||
},
|
||||
);
|
||||
|
||||
inflated_shape
|
||||
|
|
|
|||
|
|
@ -11,8 +11,7 @@ use crate::{
|
|||
dot::FixedDotIndex,
|
||||
graph::{MakePrimitive, PrimitiveIndex},
|
||||
primitive::{FixedBend, FixedDot, GetFirstGear, GetInnerOuter, LooseBend, Primitive},
|
||||
rules::AccessRules,
|
||||
Drawing,
|
||||
AccessRules, Drawing,
|
||||
},
|
||||
graph::{GetPetgraphIndex, MakeRef},
|
||||
};
|
||||
|
|
|
|||
|
|
@ -11,11 +11,11 @@ use super::{
|
|||
bend::{FixedBendIndex, FixedBendWeight, LooseBendIndex, LooseBendWeight},
|
||||
dot::{FixedDotIndex, FixedDotWeight, LooseDotIndex, LooseDotWeight},
|
||||
primitive::Primitive,
|
||||
rules::AccessRules,
|
||||
seg::{
|
||||
FixedSegIndex, FixedSegWeight, LoneLooseSegIndex, LoneLooseSegWeight, SeqLooseSegIndex,
|
||||
SeqLooseSegWeight,
|
||||
},
|
||||
AccessRules,
|
||||
};
|
||||
|
||||
#[enum_dispatch]
|
||||
|
|
|
|||
|
|
@ -18,8 +18,8 @@ use super::{
|
|||
graph::{MakePrimitive, PrimitiveIndex},
|
||||
head::{BareHead, CaneHead, GetFace, Head},
|
||||
primitive::{GetCore, GetInnerOuter, GetJoints, GetOtherJoint, GetWeight, MakePrimitiveShape},
|
||||
rules::{AccessRules, Conditions, GetConditions},
|
||||
Drawing,
|
||||
rules::{Conditions, GetConditions},
|
||||
AccessRules, Drawing,
|
||||
};
|
||||
|
||||
pub trait Guide {
|
||||
|
|
@ -97,7 +97,8 @@ impl<CW: Copy, R: AccessRules> Guide for Drawing<CW, R> {
|
|||
width: f64,
|
||||
) -> Result<(Line, Line), NoTangents> {
|
||||
let from_circle = self.head_circle(head, width);
|
||||
let to_circle = self.dot_circle(around, width, &self.conditions(head.face().into()));
|
||||
let to_circle =
|
||||
self.dot_circle(around, width, self.conditions(head.face().into()).as_ref());
|
||||
|
||||
let from_cw = self.head_cw(head);
|
||||
let tangents: Vec<Line> =
|
||||
|
|
@ -113,16 +114,17 @@ impl<CW: Copy, R: AccessRules> Guide for Drawing<CW, R> {
|
|||
width: f64,
|
||||
) -> Result<Line, NoTangents> {
|
||||
let from_circle = self.head_circle(head, width);
|
||||
let to_circle = self.dot_circle(around, width, &self.conditions(head.face().into()));
|
||||
let to_circle =
|
||||
self.dot_circle(around, width, self.conditions(head.face().into()).as_ref());
|
||||
|
||||
let from_cw = self.head_cw(head);
|
||||
math::tangent_segment(from_circle, from_cw, to_circle, Some(cw))
|
||||
}
|
||||
|
||||
fn head_around_dot_offset(&self, head: &Head, around: DotIndex, _width: f64) -> f64 {
|
||||
self.rules().clearance(
|
||||
&self.conditions(around.into()),
|
||||
&self.conditions(head.face().into()),
|
||||
self.clearance(
|
||||
self.conditions(around.into()).as_ref(),
|
||||
self.conditions(head.face().into()).as_ref(),
|
||||
)
|
||||
}
|
||||
|
||||
|
|
@ -133,7 +135,8 @@ impl<CW: Copy, R: AccessRules> Guide for Drawing<CW, R> {
|
|||
width: f64,
|
||||
) -> Result<(Line, Line), NoTangents> {
|
||||
let from_circle = self.head_circle(head, width);
|
||||
let to_circle = self.bend_circle(around, width, &self.conditions(head.face().into()));
|
||||
let to_circle =
|
||||
self.bend_circle(around, width, self.conditions(head.face().into()).as_ref());
|
||||
|
||||
let from_cw = self.head_cw(head);
|
||||
let tangents: Vec<Line> =
|
||||
|
|
@ -149,16 +152,17 @@ impl<CW: Copy, R: AccessRules> Guide for Drawing<CW, R> {
|
|||
width: f64,
|
||||
) -> Result<Line, NoTangents> {
|
||||
let from_circle = self.head_circle(head, width);
|
||||
let to_circle = self.bend_circle(around, width, &self.conditions(head.face().into()));
|
||||
let to_circle =
|
||||
self.bend_circle(around, width, self.conditions(head.face().into()).as_ref());
|
||||
|
||||
let from_cw = self.head_cw(head);
|
||||
math::tangent_segment(from_circle, from_cw, to_circle, Some(cw))
|
||||
}
|
||||
|
||||
fn head_around_bend_offset(&self, head: &Head, around: BendIndex, _width: f64) -> f64 {
|
||||
self.rules().clearance(
|
||||
&self.conditions(head.face().into()),
|
||||
&self.conditions(around.into()),
|
||||
self.clearance(
|
||||
self.conditions(head.face().into()).as_ref(),
|
||||
self.conditions(around.into()).as_ref(),
|
||||
)
|
||||
}
|
||||
|
||||
|
|
@ -196,18 +200,37 @@ impl<CW: Copy, R: AccessRules> Guide for Drawing<CW, R> {
|
|||
}
|
||||
|
||||
trait GuidePrivate {
|
||||
fn clearance(&self, lhs: Option<&Conditions<'_, ()>>, rhs: Option<&Conditions<'_, ()>>) -> f64;
|
||||
|
||||
fn head_circle(&self, head: &Head, width: f64) -> Circle;
|
||||
|
||||
fn bend_circle(&self, bend: BendIndex, width: f64, guide_conditions: &Conditions) -> Circle;
|
||||
fn bend_circle(
|
||||
&self,
|
||||
bend: BendIndex,
|
||||
width: f64,
|
||||
guide_conditions: Option<&Conditions<'_, ()>>,
|
||||
) -> Circle;
|
||||
|
||||
fn dot_circle(&self, dot: DotIndex, width: f64, guide_conditions: &Conditions) -> Circle;
|
||||
fn dot_circle(
|
||||
&self,
|
||||
dot: DotIndex,
|
||||
width: f64,
|
||||
guide_conditions: Option<&Conditions<'_, ()>>,
|
||||
) -> Circle;
|
||||
|
||||
fn rear(&self, head: CaneHead) -> DotIndex;
|
||||
|
||||
fn conditions(&self, node: PrimitiveIndex) -> Conditions;
|
||||
fn conditions(&self, node: PrimitiveIndex) -> Option<Conditions<'_, ()>>;
|
||||
}
|
||||
|
||||
impl<CW: Copy, R: AccessRules> GuidePrivate for Drawing<CW, R> {
|
||||
fn clearance(&self, lhs: Option<&Conditions<'_, ()>>, rhs: Option<&Conditions<'_, ()>>) -> f64 {
|
||||
match (lhs, rhs) {
|
||||
(None, _) | (_, None) => 0.0,
|
||||
(Some(lhs), Some(rhs)) => self.rules().clearance((lhs, rhs).into()),
|
||||
}
|
||||
}
|
||||
|
||||
fn head_circle(&self, head: &Head, width: f64) -> Circle {
|
||||
match *head {
|
||||
Head::Bare(head) => Circle {
|
||||
|
|
@ -216,19 +239,28 @@ impl<CW: Copy, R: AccessRules> GuidePrivate for Drawing<CW, R> {
|
|||
},
|
||||
Head::Cane(head) => {
|
||||
if let Some(inner) = self.primitive(head.cane.bend).inner() {
|
||||
self.bend_circle(inner.into(), width, &self.conditions(head.face().into()))
|
||||
self.bend_circle(
|
||||
inner.into(),
|
||||
width,
|
||||
self.conditions(head.face().into()).as_ref(),
|
||||
)
|
||||
} else {
|
||||
self.dot_circle(
|
||||
self.primitive(head.cane.bend).core().into(),
|
||||
width,
|
||||
&self.conditions(head.face().into()),
|
||||
self.conditions(head.face().into()).as_ref(),
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn bend_circle(&self, bend: BendIndex, width: f64, guide_conditions: &Conditions) -> Circle {
|
||||
fn bend_circle(
|
||||
&self,
|
||||
bend: BendIndex,
|
||||
width: f64,
|
||||
guide_conditions: Option<&Conditions<'_, ()>>,
|
||||
) -> Circle {
|
||||
let outer_circle = match bend.primitive(self).shape() {
|
||||
PrimitiveShape::Bend(shape) => shape.outer_circle(),
|
||||
_ => unreachable!(),
|
||||
|
|
@ -238,21 +270,22 @@ impl<CW: Copy, R: AccessRules> GuidePrivate for Drawing<CW, R> {
|
|||
pos: outer_circle.pos,
|
||||
r: outer_circle.r
|
||||
+ width / 2.0
|
||||
+ self
|
||||
.rules()
|
||||
.clearance(&self.conditions(bend.into()), guide_conditions),
|
||||
+ self.clearance(self.conditions(bend.into()).as_ref(), guide_conditions),
|
||||
}
|
||||
}
|
||||
|
||||
fn dot_circle(&self, dot: DotIndex, width: f64, guide_conditions: &Conditions) -> Circle {
|
||||
fn dot_circle(
|
||||
&self,
|
||||
dot: DotIndex,
|
||||
width: f64,
|
||||
guide_conditions: Option<&Conditions<'_, ()>>,
|
||||
) -> Circle {
|
||||
let shape = dot.primitive(self).shape();
|
||||
Circle {
|
||||
pos: shape.center(),
|
||||
r: shape.width() / 2.0
|
||||
+ width / 2.0
|
||||
+ self
|
||||
.rules()
|
||||
.clearance(&self.conditions(dot.into()), guide_conditions),
|
||||
+ self.clearance(self.conditions(dot.into()).as_ref(), guide_conditions),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -261,7 +294,7 @@ impl<CW: Copy, R: AccessRules> GuidePrivate for Drawing<CW, R> {
|
|||
.other_joint(head.cane.dot.into())
|
||||
}
|
||||
|
||||
fn conditions(&self, node: PrimitiveIndex) -> Conditions {
|
||||
fn conditions(&self, node: PrimitiveIndex) -> Option<Conditions<'_, ()>> {
|
||||
node.primitive(self).conditions()
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -10,8 +10,7 @@ use super::{
|
|||
cane::Cane,
|
||||
dot::{DotIndex, FixedDotIndex, LooseDotIndex},
|
||||
primitive::MakePrimitiveShape,
|
||||
rules::AccessRules,
|
||||
Drawing,
|
||||
AccessRules, Drawing,
|
||||
};
|
||||
|
||||
#[enum_dispatch]
|
||||
|
|
|
|||
|
|
@ -13,12 +13,11 @@ use crate::{
|
|||
graph::{MakePrimitive, PrimitiveIndex},
|
||||
primitive::{GetJoints, LoneLooseSeg, LooseBend, LooseDot, Primitive, SeqLooseSeg},
|
||||
seg::{LoneLooseSegIndex, SeqLooseSegIndex},
|
||||
AccessRules,
|
||||
},
|
||||
graph::GetPetgraphIndex,
|
||||
};
|
||||
|
||||
use super::rules::AccessRules;
|
||||
|
||||
#[enum_dispatch]
|
||||
pub trait GetPrevNextLoose {
|
||||
fn next_loose(&self, maybe_prev: Option<LooseIndex>) -> Option<LooseIndex>;
|
||||
|
|
|
|||
|
|
@ -15,6 +15,7 @@ mod guide;
|
|||
pub mod head;
|
||||
pub mod loose;
|
||||
pub mod primitive;
|
||||
pub use crate::specctra::AccessRules;
|
||||
pub use specctra_core::rules;
|
||||
pub mod seg;
|
||||
|
||||
|
|
|
|||
|
|
@ -11,13 +11,13 @@ use crate::{
|
|||
dot::{DotIndex, DotWeight, FixedDotIndex, FixedDotWeight, LooseDotIndex, LooseDotWeight},
|
||||
graph::{GetLayer, GetMaybeNet, PrimitiveIndex, PrimitiveWeight, Retag},
|
||||
seg::{FixedSegWeight, LoneLooseSegWeight, SegIndex, SeqLooseSegIndex, SeqLooseSegWeight},
|
||||
Drawing,
|
||||
AccessRules, Drawing,
|
||||
},
|
||||
geometry::{primitive::PrimitiveShape, GenericNode, GetOffset, GetWidth},
|
||||
graph::{GenericIndex, GetPetgraphIndex},
|
||||
};
|
||||
|
||||
use specctra_core::rules::{AccessRules, Conditions, GetConditions};
|
||||
use specctra_core::rules::{Conditions, GetConditions};
|
||||
|
||||
#[enum_dispatch]
|
||||
pub trait GetDrawing<'a, R: AccessRules> {
|
||||
|
|
@ -171,16 +171,20 @@ pub enum Primitive<'a, CW: Copy, R: AccessRules> {
|
|||
LooseBend(LooseBend<'a, CW, R>),
|
||||
}
|
||||
|
||||
impl<'a, CW: Copy, R: AccessRules> specctra_core::rules::GetConditions for Primitive<'a, CW, R> {
|
||||
fn conditions(&self) -> specctra_core::rules::Conditions {
|
||||
impl<'a, CW: Copy, R: AccessRules> specctra_core::rules::GetConditions<'a>
|
||||
for &Primitive<'a, CW, R>
|
||||
{
|
||||
type ObjectKind = ();
|
||||
|
||||
fn conditions(self) -> Option<specctra_core::rules::Conditions<'a, ()>> {
|
||||
match self {
|
||||
Self::FixedDot(x) => x.conditions(),
|
||||
Self::LooseDot(x) => x.conditions(),
|
||||
Self::FixedSeg(x) => x.conditions(),
|
||||
Self::LoneLooseSeg(x) => x.conditions(),
|
||||
Self::SeqLooseSeg(x) => x.conditions(),
|
||||
Self::FixedBend(x) => x.conditions(),
|
||||
Self::LooseBend(x) => x.conditions(),
|
||||
Primitive::FixedDot(x) => x.conditions(),
|
||||
Primitive::LooseDot(x) => x.conditions(),
|
||||
Primitive::FixedSeg(x) => x.conditions(),
|
||||
Primitive::LoneLooseSeg(x) => x.conditions(),
|
||||
Primitive::SeqLooseSeg(x) => x.conditions(),
|
||||
Primitive::FixedBend(x) => x.conditions(),
|
||||
Primitive::LooseBend(x) => x.conditions(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -244,16 +248,19 @@ where
|
|||
}
|
||||
}
|
||||
|
||||
impl<'a, W, CW: Copy, R: AccessRules> GetConditions for GenericPrimitive<'a, W, CW, R>
|
||||
impl<'a, W, CW: Copy, R: AccessRules> GetConditions<'a> for &GenericPrimitive<'a, W, CW, R>
|
||||
where
|
||||
GenericPrimitive<'a, W, CW, R>: GetMaybeNet,
|
||||
{
|
||||
fn conditions(&self) -> Conditions {
|
||||
Conditions {
|
||||
maybe_net: self.maybe_net(),
|
||||
maybe_region: Some("A".to_string()),
|
||||
maybe_layer: Some("F.Cu".to_string()),
|
||||
}
|
||||
type ObjectKind = ();
|
||||
|
||||
fn conditions(self) -> Option<Conditions<'a, ()>> {
|
||||
self.maybe_net().map(|net| Conditions {
|
||||
net,
|
||||
maybe_region: Some("A".into()),
|
||||
maybe_layer: Some("F.Cu".into()),
|
||||
kind: (),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -8,8 +8,7 @@ use crate::{
|
|||
drawing::{
|
||||
graph::{GetLayer, GetMaybeNet, MakePrimitive, PrimitiveIndex, PrimitiveWeight, Retag},
|
||||
primitive::{GenericPrimitive, Primitive},
|
||||
rules::AccessRules,
|
||||
Drawing,
|
||||
AccessRules, Drawing,
|
||||
},
|
||||
geometry::GetWidth,
|
||||
graph::{GenericIndex, GetPetgraphIndex},
|
||||
|
|
|
|||
|
|
@ -18,8 +18,8 @@ use crate::{
|
|||
dot::DotWeight,
|
||||
graph::{PrimitiveWeight, Retag},
|
||||
primitive::Primitive,
|
||||
rules::AccessRules,
|
||||
seg::SegWeight,
|
||||
AccessRules,
|
||||
},
|
||||
geometry::{
|
||||
compound::ManageCompounds,
|
||||
|
|
|
|||
|
|
@ -16,12 +16,11 @@ use crate::{
|
|||
gear::GearIndex,
|
||||
graph::{GetMaybeNet, IsInLayer, MakePrimitive, PrimitiveIndex, PrimitiveWeight},
|
||||
primitive::MakePrimitiveShape,
|
||||
rules::AccessRules,
|
||||
seg::{
|
||||
FixedSegIndex, FixedSegWeight, LoneLooseSegIndex, LoneLooseSegWeight, SegIndex,
|
||||
SegWeight, SeqLooseSegIndex, SeqLooseSegWeight,
|
||||
},
|
||||
Cane, Drawing, DrawingEdit, DrawingException, Infringement,
|
||||
AccessRules, Cane, Drawing, DrawingEdit, DrawingException, Infringement,
|
||||
},
|
||||
geometry::{edit::ApplyGeometryEdit, shape::Shape, GenericNode},
|
||||
graph::{GenericIndex, GetPetgraphIndex},
|
||||
|
|
|
|||
|
|
@ -13,9 +13,8 @@ use crate::{
|
|||
dot::FixedDotIndex,
|
||||
graph::{GetLayer, GetMaybeNet, PrimitiveIndex},
|
||||
primitive::GetLimbs,
|
||||
rules::AccessRules,
|
||||
seg::SegIndex,
|
||||
Drawing,
|
||||
AccessRules, Drawing,
|
||||
},
|
||||
geometry::GetSetPos,
|
||||
graph::{GenericIndex, GetPetgraphIndex},
|
||||
|
|
|
|||
|
|
@ -10,8 +10,7 @@ use crate::{
|
|||
drawing::{
|
||||
graph::{GetMaybeNet, IsInLayer},
|
||||
primitive::MakePrimitiveShape,
|
||||
rules::AccessRules,
|
||||
Drawing,
|
||||
AccessRules, Drawing,
|
||||
},
|
||||
geometry::primitive::{DotShape, PrimitiveShape},
|
||||
graph::{GenericIndex, GetPetgraphIndex},
|
||||
|
|
|
|||
|
|
@ -17,9 +17,8 @@ use crate::{
|
|||
graph::{GetLayer, GetMaybeNet, MakePrimitive},
|
||||
head::{CaneHead, GetFace, Head},
|
||||
primitive::GetOtherJoint,
|
||||
rules::AccessRules,
|
||||
seg::{LoneLooseSegWeight, SeqLooseSegWeight},
|
||||
DrawingException, Guide, Infringement,
|
||||
AccessRules, DrawingException, Guide, Infringement,
|
||||
},
|
||||
layout::{Layout, LayoutEdit},
|
||||
math::{Circle, NoTangents},
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@ use crate::{
|
|||
dot::FixedDotIndex,
|
||||
graph::PrimitiveIndex,
|
||||
head::{BareHead, CaneHead, Head},
|
||||
rules::AccessRules,
|
||||
AccessRules,
|
||||
},
|
||||
layout::{Layout, LayoutEdit},
|
||||
};
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ use contracts_try::{debug_ensures, debug_requires};
|
|||
use thiserror::Error;
|
||||
|
||||
use crate::{
|
||||
drawing::{band::BandTermsegIndex, dot::FixedDotIndex, rules::AccessRules},
|
||||
drawing::{band::BandTermsegIndex, dot::FixedDotIndex, AccessRules},
|
||||
layout::{Layout, LayoutEdit},
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -25,8 +25,7 @@ use crate::{
|
|||
gear::{GearIndex, GetNextGear},
|
||||
graph::{GetLayer, GetMaybeNet, MakePrimitive, PrimitiveIndex},
|
||||
primitive::{MakePrimitiveShape, Primitive},
|
||||
rules::AccessRules,
|
||||
Drawing,
|
||||
AccessRules, Drawing,
|
||||
},
|
||||
geometry::shape::AccessShape,
|
||||
graph::{GetPetgraphIndex, MakeRef},
|
||||
|
|
|
|||
|
|
@ -7,9 +7,7 @@ use std::ops::ControlFlow;
|
|||
use derive_getters::{Dissolve, Getters};
|
||||
|
||||
use crate::{
|
||||
drawing::{
|
||||
band::BandTermsegIndex, dot::FixedDotIndex, graph::PrimitiveIndex, rules::AccessRules,
|
||||
},
|
||||
drawing::{band::BandTermsegIndex, dot::FixedDotIndex, graph::PrimitiveIndex, AccessRules},
|
||||
geometry::primitive::PrimitiveShape,
|
||||
layout::LayoutEdit,
|
||||
router::{
|
||||
|
|
|
|||
|
|
@ -14,8 +14,7 @@ use crate::{
|
|||
graph::{MakePrimitive, PrimitiveIndex},
|
||||
head::GetFace,
|
||||
primitive::MakePrimitiveShape,
|
||||
rules::AccessRules,
|
||||
Collision, DrawingException, Guide, Infringement,
|
||||
AccessRules, Collision, DrawingException, Guide, Infringement,
|
||||
},
|
||||
geometry::{
|
||||
primitive::PrimitiveShape,
|
||||
|
|
|
|||
|
|
@ -11,4 +11,7 @@ pub use specctra_core::error::{ParseError, ParseErrorContext};
|
|||
pub use specctra_core::mesadata;
|
||||
use specctra_core::*;
|
||||
|
||||
pub trait AccessRules: specctra_core::rules::AccessRules<Scalar = f64, ObjectKind = ()> {}
|
||||
impl<T> AccessRules for T where T: specctra_core::rules::AccessRules<Scalar = f64, ObjectKind = ()> {}
|
||||
|
||||
pub mod design;
|
||||
|
|
|
|||
Loading…
Reference in New Issue