layout: attach `Rules` storing design rules to `Layout`

This commit is contained in:
Mikolaj Wielgus 2024-02-02 23:58:23 +00:00
parent 01d285efb0
commit d2ff1826a0
19 changed files with 275 additions and 216 deletions

View File

@ -11,7 +11,7 @@ use crate::{
primitive::GetOtherJoint, primitive::GetOtherJoint,
seg::{LoneLooseSegWeight, SeqLooseSegWeight}, seg::{LoneLooseSegWeight, SeqLooseSegWeight},
}, },
layout::{Infringement, Layout, LayoutException}, layout::{rules::RulesTrait, Infringement, Layout, LayoutException},
math::{Circle, NoTangents}, math::{Circle, NoTangents},
rules::{Conditions, Rules}, rules::{Conditions, Rules},
wraparoundable::WraparoundableIndex, wraparoundable::WraparoundableIndex,
@ -29,13 +29,13 @@ pub enum DrawException {
CannotWrapAround(WraparoundableIndex, LayoutException, LayoutException), CannotWrapAround(WraparoundableIndex, LayoutException, LayoutException),
} }
pub struct Draw<'a> { pub struct Draw<'a, R: RulesTrait> {
layout: &'a mut Layout, layout: &'a mut Layout<R>,
rules: &'a Rules, rules: &'a Rules,
} }
impl<'a> Draw<'a> { impl<'a, R: RulesTrait> Draw<'a, R> {
pub fn new(layout: &'a mut Layout, rules: &'a Rules) -> Self { pub fn new(layout: &'a mut Layout<R>, rules: &'a Rules) -> Self {
Self { layout, rules } Self { layout, rules }
} }
@ -95,6 +95,7 @@ impl<'a> Draw<'a> {
head: Head, head: Head,
around: FixedDotIndex, around: FixedDotIndex,
width: f64, width: f64,
offset: f64,
) -> Result<SegbendHead, DrawException> { ) -> Result<SegbendHead, DrawException> {
let mut tangents = self.guide(&Default::default()).head_around_dot_segments( let mut tangents = self.guide(&Default::default()).head_around_dot_segments(
&head, &head,
@ -117,6 +118,7 @@ impl<'a> Draw<'a> {
tangent.start_point(), tangent.start_point(),
tangent.end_point(), tangent.end_point(),
dirs[i], dirs[i],
offset,
width, width,
) { ) {
Ok(ok) => return Ok(ok), Ok(ok) => return Ok(ok),
@ -138,6 +140,7 @@ impl<'a> Draw<'a> {
head: Head, head: Head,
around: BendIndex, around: BendIndex,
width: f64, width: f64,
offset: f64,
) -> Result<SegbendHead, DrawException> { ) -> Result<SegbendHead, DrawException> {
let mut tangents = self.guide(&Default::default()).head_around_bend_segments( let mut tangents = self.guide(&Default::default()).head_around_bend_segments(
&head, &head,
@ -160,6 +163,7 @@ impl<'a> Draw<'a> {
tangent.start_point(), tangent.start_point(),
tangent.end_point(), tangent.end_point(),
dirs[i], dirs[i],
offset,
width, width,
) { ) {
Ok(ok) => return Ok(ok), Ok(ok) => return Ok(ok),
@ -184,9 +188,10 @@ impl<'a> Draw<'a> {
to: Point, to: Point,
cw: bool, cw: bool,
width: f64, width: f64,
offset: f64,
) -> Result<SegbendHead, LayoutException> { ) -> Result<SegbendHead, LayoutException> {
let head = self.extend_head(head, from)?; let head = self.extend_head(head, from)?;
self.segbend(head, around, to, cw, width) self.segbend(head, around, to, cw, offset, width)
} }
#[debug_ensures(self.layout.node_count() == old(self.layout.node_count()))] #[debug_ensures(self.layout.node_count() == old(self.layout.node_count()))]
@ -208,6 +213,7 @@ impl<'a> Draw<'a> {
to: Point, to: Point,
cw: bool, cw: bool,
width: f64, width: f64,
offset: f64,
) -> Result<SegbendHead, LayoutException> { ) -> Result<SegbendHead, LayoutException> {
let segbend = self.layout.insert_segbend( let segbend = self.layout.insert_segbend(
head.face(), head.face(),
@ -221,12 +227,12 @@ impl<'a> Draw<'a> {
}, },
SeqLooseSegWeight { SeqLooseSegWeight {
band: head.band(), band: head.band(),
width: 3.0, width,
}, },
LooseBendWeight { LooseBendWeight {
band: head.band(), band: head.band(),
width: 3.0, width,
offset: 3.0, offset,
cw, cw,
}, },
)?; )?;
@ -250,7 +256,7 @@ impl<'a> Draw<'a> {
Some(self.guide(&Default::default()).head(prev_dot, band)) Some(self.guide(&Default::default()).head(prev_dot, band))
} }
fn guide(&'a self, conditions: &'a Conditions) -> Guide { fn guide(&'a self, conditions: &'a Conditions) -> Guide<R> {
Guide::new(self.layout, self.rules, conditions) Guide::new(self.layout, conditions)
} }
} }

View File

@ -11,13 +11,15 @@ use crate::{
}, },
}; };
pub struct Band<'a> { use super::rules::RulesTrait;
pub struct Band<'a, R: RulesTrait> {
pub index: BandIndex, pub index: BandIndex,
layout: &'a Layout, layout: &'a Layout<R>,
} }
impl<'a> Band<'a> { impl<'a, R: RulesTrait> Band<'a, R> {
pub fn new(index: BandIndex, layout: &'a Layout) -> Self { pub fn new(index: BandIndex, layout: &'a Layout<R>) -> Self {
Self { index, layout } Self { index, layout }
} }
@ -85,7 +87,7 @@ impl<'a> Band<'a> {
} }
} }
impl<'a> GetNet for Band<'a> { impl<'a, R: RulesTrait> GetNet for Band<'a, R> {
fn net(&self) -> i64 { fn net(&self) -> i64 {
self.weight().net self.weight().net
} }

View File

@ -10,6 +10,7 @@ use crate::{
MakePrimitive, Retag, MakePrimitive, Retag,
}, },
primitive::{GenericPrimitive, Primitive}, primitive::{GenericPrimitive, Primitive},
rules::RulesTrait,
Layout, Layout,
}, },
}; };

View File

@ -13,6 +13,7 @@ use crate::{
MakePrimitive, Retag, MakePrimitive, Retag,
}, },
primitive::{GenericPrimitive, Primitive}, primitive::{GenericPrimitive, Primitive},
rules::RulesTrait,
Layout, Layout,
}, },
math::Circle, math::Circle,

View File

@ -14,6 +14,7 @@ use super::{
bend::{FixedBendIndex, FixedBendWeight, LooseBendIndex, LooseBendWeight}, bend::{FixedBendIndex, FixedBendWeight, LooseBendIndex, LooseBendWeight},
dot::{FixedDotIndex, FixedDotWeight, LooseDotIndex, LooseDotWeight}, dot::{FixedDotIndex, FixedDotWeight, LooseDotIndex, LooseDotWeight},
primitive::Primitive, primitive::Primitive,
rules::RulesTrait,
seg::{ seg::{
FixedSegIndex, FixedSegWeight, LoneLooseSegIndex, LoneLooseSegWeight, SeqLooseSegIndex, FixedSegIndex, FixedSegWeight, LoneLooseSegIndex, LoneLooseSegWeight, SeqLooseSegIndex,
SeqLooseSegWeight, SeqLooseSegWeight,
@ -40,7 +41,7 @@ pub trait GetBandIndex {
#[enum_dispatch] #[enum_dispatch]
pub trait MakePrimitive { pub trait MakePrimitive {
fn primitive<'a>(&self, layout: &'a Layout) -> Primitive<'a>; fn primitive<'a, R: RulesTrait>(&self, layout: &'a Layout<R>) -> Primitive<'a, R>;
} }
macro_rules! impl_weight { macro_rules! impl_weight {
@ -54,7 +55,7 @@ macro_rules! impl_weight {
pub type $index_struct = GenericIndex<$weight_struct>; pub type $index_struct = GenericIndex<$weight_struct>;
impl MakePrimitive for $index_struct { impl MakePrimitive for $index_struct {
fn primitive<'a>(&self, layout: &'a Layout) -> Primitive<'a> { fn primitive<'a, R: RulesTrait>(&self, layout: &'a Layout<R>) -> Primitive<'a, R> {
Primitive::$weight_variant(GenericPrimitive::new(*self, layout)) Primitive::$weight_variant(GenericPrimitive::new(*self, layout))
} }
} }

View File

@ -15,7 +15,7 @@ use crate::{
rules::{Conditions, Rules}, rules::{Conditions, Rules},
}; };
use super::segbend::Segbend; use super::{rules::RulesTrait, segbend::Segbend};
#[enum_dispatch] #[enum_dispatch]
pub trait HeadTrait { pub trait HeadTrait {
@ -63,19 +63,14 @@ impl HeadTrait for SegbendHead {
} }
} }
pub struct Guide<'a, 'b> { pub struct Guide<'a, 'b, R: RulesTrait> {
layout: &'a Layout, layout: &'a Layout<R>,
rules: &'a Rules,
conditions: &'b Conditions, conditions: &'b Conditions,
} }
impl<'a, 'b> Guide<'a, 'b> { impl<'a, 'b, R: RulesTrait> Guide<'a, 'b, R> {
pub fn new(layout: &'a Layout, rules: &'a Rules, conditions: &'b Conditions) -> Self { pub fn new(layout: &'a Layout<R>, conditions: &'b Conditions) -> Self {
Self { Self { layout, conditions }
layout,
rules,
conditions,
}
} }
pub fn head_into_dot_segment( pub fn head_into_dot_segment(

View File

@ -14,6 +14,7 @@ use super::connectivity::{
}; };
use super::geometry::with_rtree::GeometryWithRtree; use super::geometry::with_rtree::GeometryWithRtree;
use super::loose::{GetNextLoose, Loose, LooseIndex}; use super::loose::{GetNextLoose, Loose, LooseIndex};
use super::rules::RulesTrait;
use super::segbend::Segbend; use super::segbend::Segbend;
use crate::graph::{GenericIndex, GetNodeIndex}; use crate::graph::{GenericIndex, GetNodeIndex};
use crate::layout::bend::BendIndex; use crate::layout::bend::BendIndex;
@ -28,8 +29,7 @@ use crate::layout::{
geometry::shape::{Shape, ShapeTrait}, geometry::shape::{Shape, ShapeTrait},
graph::{GeometryIndex, GeometryWeight, GetComponentIndex, MakePrimitive}, graph::{GeometryIndex, GeometryWeight, GetComponentIndex, MakePrimitive},
primitive::{ primitive::{
GenericPrimitive, GetConnectable, GetCore, GetInnerOuter, GetJoints, GetOtherJoint, GenericPrimitive, GetCore, GetInnerOuter, GetJoints, GetOtherJoint, GetWeight, MakeShape,
GetWeight, MakeShape,
}, },
seg::{ seg::{
FixedSegIndex, FixedSegWeight, LoneLooseSegIndex, LoneLooseSegWeight, SegIndex, FixedSegIndex, FixedSegWeight, LoneLooseSegIndex, LoneLooseSegWeight, SegIndex,
@ -69,8 +69,7 @@ pub struct Collision(pub Shape, pub GeometryIndex);
pub struct AlreadyConnected(pub i64, pub GeometryIndex); pub struct AlreadyConnected(pub i64, pub GeometryIndex);
#[derive(Debug)] #[derive(Debug)]
pub struct Layout { pub struct Layout<R: RulesTrait> {
connectivity: ConnectivityGraph,
geometry_with_rtree: GeometryWithRtree< geometry_with_rtree: GeometryWithRtree<
GeometryWeight, GeometryWeight,
DotWeight, DotWeight,
@ -81,13 +80,16 @@ pub struct Layout {
SegIndex, SegIndex,
BendIndex, BendIndex,
>, >,
connectivity: ConnectivityGraph,
rules: R,
} }
impl Layout { impl<R: RulesTrait> Layout<R> {
pub fn new() -> Self { pub fn new(rules: R) -> Self {
Layout { Self {
connectivity: StableDiGraph::default(),
geometry_with_rtree: GeometryWithRtree::new(), geometry_with_rtree: GeometryWithRtree::new(),
connectivity: StableDiGraph::default(),
rules,
} }
} }
@ -411,9 +413,8 @@ impl Layout {
let cw = primitive.weight().cw; let cw = primitive.weight().cw;
let ends = primitive.joints(); let ends = primitive.joints();
let rules = Default::default();
let conditions = Default::default(); let conditions = Default::default();
let guide = Guide::new(self, &rules, &conditions); let guide = Guide::new(self, &conditions);
let from_head = guide.rear_head(ends.1); let from_head = guide.rear_head(ends.1);
let to_head = guide.rear_head(ends.0); let to_head = guide.rear_head(ends.0);
@ -717,10 +718,6 @@ impl Layout {
self.geometry_with_rtree.flip_bend(bend.into()); self.geometry_with_rtree.flip_bend(bend.into());
} }
/*pub fn bow(&self, bend: LooseBendIndex) -> Bow {
Bow::from_bend(bend, &self.graph)
}*/
pub fn segbend(&self, dot: LooseDotIndex) -> Segbend { pub fn segbend(&self, dot: LooseDotIndex) -> Segbend {
Segbend::from_dot(dot, self) Segbend::from_dot(dot, self)
} }
@ -769,7 +766,7 @@ impl Layout {
} }
} }
impl Layout { impl<R: RulesTrait> Layout<R> {
#[debug_ensures(self.geometry_with_rtree.graph().node_count() == old(self.geometry_with_rtree.graph().node_count()))] #[debug_ensures(self.geometry_with_rtree.graph().node_count() == old(self.geometry_with_rtree.graph().node_count()))]
#[debug_ensures(self.geometry_with_rtree.graph().edge_count() == old(self.geometry_with_rtree.graph().edge_count()))] #[debug_ensures(self.geometry_with_rtree.graph().edge_count() == old(self.geometry_with_rtree.graph().edge_count()))]
pub fn move_dot(&mut self, dot: DotIndex, to: Point) -> Result<(), Infringement> { pub fn move_dot(&mut self, dot: DotIndex, to: Point) -> Result<(), Infringement> {
@ -815,10 +812,7 @@ impl Layout {
self.geometry_with_rtree self.geometry_with_rtree
.rtree() .rtree()
.locate_in_envelope_intersecting(&RTreeObject::envelope(&shape)) .locate_in_envelope_intersecting(&RTreeObject::envelope(&shape))
.filter(|wrapper| { .filter(|wrapper| !self.are_connectable(node, wrapper.data))
let other_index = wrapper.data;
!node.primitive(self).connectable(other_index)
})
.filter(|wrapper| !except.contains(&wrapper.data)) .filter(|wrapper| !except.contains(&wrapper.data))
.filter(|wrapper| shape.intersects(wrapper.geom())) .filter(|wrapper| shape.intersects(wrapper.geom()))
.map(|wrapper| wrapper.data) .map(|wrapper| wrapper.data)
@ -835,18 +829,24 @@ impl Layout {
self.geometry_with_rtree self.geometry_with_rtree
.rtree() .rtree()
.locate_in_envelope_intersecting(&RTreeObject::envelope(&shape)) .locate_in_envelope_intersecting(&RTreeObject::envelope(&shape))
.filter(|wrapper| { .filter(|wrapper| !self.are_connectable(node, wrapper.data))
let other_index = wrapper.data;
!node.primitive(self).connectable(other_index)
})
.filter(|wrapper| shape.intersects(wrapper.geom())) .filter(|wrapper| shape.intersects(wrapper.geom()))
.map(|wrapper| wrapper.data) .map(|wrapper| wrapper.data)
.next() .next()
.and_then(|collidee| Some(Collision(shape, collidee))) .and_then(|collidee| Some(Collision(shape, collidee)))
} }
#[debug_ensures(self.geometry_with_rtree.graph().node_count() == old(self.geometry_with_rtree.graph().node_count()))]
#[debug_ensures(self.geometry_with_rtree.graph().edge_count() == old(self.geometry_with_rtree.graph().edge_count()))]
fn are_connectable(&self, node1: GeometryIndex, node2: GeometryIndex) -> bool {
let node1_net = node1.primitive(self).net();
let node2_net = node2.primitive(self).net();
(node1_net == node2_net) || node1_net == -1 || node2_net == -2
}
} }
impl Layout { impl<R: RulesTrait> Layout<R> {
#[debug_ensures(self.geometry_with_rtree.graph().node_count() == old(self.geometry_with_rtree.graph().node_count()))] #[debug_ensures(self.geometry_with_rtree.graph().node_count() == old(self.geometry_with_rtree.graph().node_count()))]
#[debug_ensures(self.geometry_with_rtree.graph().edge_count() == old(self.geometry_with_rtree.graph().edge_count()))] #[debug_ensures(self.geometry_with_rtree.graph().edge_count() == old(self.geometry_with_rtree.graph().edge_count()))]
pub fn connectivity(&self) -> &ConnectivityGraph { pub fn connectivity(&self) -> &ConnectivityGraph {
@ -872,25 +872,31 @@ impl Layout {
#[debug_ensures(self.geometry_with_rtree.graph().node_count() == old(self.geometry_with_rtree.graph().node_count()))] #[debug_ensures(self.geometry_with_rtree.graph().node_count() == old(self.geometry_with_rtree.graph().node_count()))]
#[debug_ensures(self.geometry_with_rtree.graph().edge_count() == old(self.geometry_with_rtree.graph().edge_count()))] #[debug_ensures(self.geometry_with_rtree.graph().edge_count() == old(self.geometry_with_rtree.graph().edge_count()))]
pub fn primitive<W>(&self, index: GenericIndex<W>) -> GenericPrimitive<W> { pub fn rules(&self) -> &R {
&self.rules
}
#[debug_ensures(self.geometry_with_rtree.graph().node_count() == old(self.geometry_with_rtree.graph().node_count()))]
#[debug_ensures(self.geometry_with_rtree.graph().edge_count() == old(self.geometry_with_rtree.graph().edge_count()))]
pub fn primitive<W>(&self, index: GenericIndex<W>) -> GenericPrimitive<W, R> {
GenericPrimitive::new(index, self) GenericPrimitive::new(index, self)
} }
#[debug_ensures(self.geometry_with_rtree.graph().node_count() == old(self.geometry_with_rtree.graph().node_count()))] #[debug_ensures(self.geometry_with_rtree.graph().node_count() == old(self.geometry_with_rtree.graph().node_count()))]
#[debug_ensures(self.geometry_with_rtree.graph().edge_count() == old(self.geometry_with_rtree.graph().edge_count()))] #[debug_ensures(self.geometry_with_rtree.graph().edge_count() == old(self.geometry_with_rtree.graph().edge_count()))]
pub fn wraparoundable(&self, index: WraparoundableIndex) -> Wraparoundable { pub fn wraparoundable(&self, index: WraparoundableIndex) -> Wraparoundable<R> {
Wraparoundable::new(index, self) Wraparoundable::new(index, self)
} }
#[debug_ensures(self.geometry_with_rtree.graph().node_count() == old(self.geometry_with_rtree.graph().node_count()))] #[debug_ensures(self.geometry_with_rtree.graph().node_count() == old(self.geometry_with_rtree.graph().node_count()))]
#[debug_ensures(self.geometry_with_rtree.graph().edge_count() == old(self.geometry_with_rtree.graph().edge_count()))] #[debug_ensures(self.geometry_with_rtree.graph().edge_count() == old(self.geometry_with_rtree.graph().edge_count()))]
pub fn loose(&self, index: LooseIndex) -> Loose { pub fn loose(&self, index: LooseIndex) -> Loose<R> {
Loose::new(index, self) Loose::new(index, self)
} }
#[debug_ensures(self.geometry_with_rtree.graph().node_count() == old(self.geometry_with_rtree.graph().node_count()))] #[debug_ensures(self.geometry_with_rtree.graph().node_count() == old(self.geometry_with_rtree.graph().node_count()))]
#[debug_ensures(self.geometry_with_rtree.graph().edge_count() == old(self.geometry_with_rtree.graph().edge_count()))] #[debug_ensures(self.geometry_with_rtree.graph().edge_count() == old(self.geometry_with_rtree.graph().edge_count()))]
pub fn band(&self, index: BandIndex) -> Band { pub fn band(&self, index: BandIndex) -> Band<R> {
Band::new(index, self) Band::new(index, self)
} }
} }

View File

@ -13,6 +13,8 @@ use crate::{
}, },
}; };
use super::rules::RulesTrait;
#[enum_dispatch] #[enum_dispatch]
pub trait GetNextLoose { pub trait GetNextLoose {
fn next_loose(&self, maybe_prev: Option<LooseIndex>) -> Option<LooseIndex>; fn next_loose(&self, maybe_prev: Option<LooseIndex>) -> Option<LooseIndex>;
@ -39,15 +41,15 @@ impl From<LooseIndex> for GeometryIndex {
} }
#[enum_dispatch(GetNextLoose, GetLayout, GetNodeIndex)] #[enum_dispatch(GetNextLoose, GetLayout, GetNodeIndex)]
pub enum Loose<'a> { pub enum Loose<'a, R: RulesTrait> {
Dot(LooseDot<'a>), Dot(LooseDot<'a, R>),
LoneSeg(LoneLooseSeg<'a>), LoneSeg(LoneLooseSeg<'a, R>),
SeqSeg(SeqLooseSeg<'a>), SeqSeg(SeqLooseSeg<'a, R>),
Bend(LooseBend<'a>), Bend(LooseBend<'a, R>),
} }
impl<'a> Loose<'a> { impl<'a, R: RulesTrait> Loose<'a, R> {
pub fn new(index: LooseIndex, layout: &'a Layout) -> Self { pub fn new(index: LooseIndex, layout: &'a Layout<R>) -> Self {
match index { match index {
LooseIndex::Dot(dot) => layout.primitive(dot).into(), LooseIndex::Dot(dot) => layout.primitive(dot).into(),
LooseIndex::LoneSeg(seg) => layout.primitive(seg).into(), LooseIndex::LoneSeg(seg) => layout.primitive(seg).into(),
@ -57,7 +59,7 @@ impl<'a> Loose<'a> {
} }
} }
impl<'a> GetNextLoose for LooseDot<'a> { impl<'a, R: RulesTrait> GetNextLoose for LooseDot<'a, R> {
fn next_loose(&self, maybe_prev: Option<LooseIndex>) -> Option<LooseIndex> { fn next_loose(&self, maybe_prev: Option<LooseIndex>) -> Option<LooseIndex> {
let bend = self.bend(); let bend = self.bend();
let Some(prev) = maybe_prev else { let Some(prev) = maybe_prev else {
@ -72,13 +74,13 @@ impl<'a> GetNextLoose for LooseDot<'a> {
} }
} }
impl<'a> GetNextLoose for LoneLooseSeg<'a> { impl<'a, R: RulesTrait> GetNextLoose for LoneLooseSeg<'a, R> {
fn next_loose(&self, _maybe_prev: Option<LooseIndex>) -> Option<LooseIndex> { fn next_loose(&self, _maybe_prev: Option<LooseIndex>) -> Option<LooseIndex> {
None None
} }
} }
impl<'a> GetNextLoose for SeqLooseSeg<'a> { impl<'a, R: RulesTrait> GetNextLoose for SeqLooseSeg<'a, R> {
fn next_loose(&self, maybe_prev: Option<LooseIndex>) -> Option<LooseIndex> { fn next_loose(&self, maybe_prev: Option<LooseIndex>) -> Option<LooseIndex> {
let ends = self.joints(); let ends = self.joints();
let Some(prev) = maybe_prev else { let Some(prev) = maybe_prev else {
@ -96,7 +98,7 @@ impl<'a> GetNextLoose for SeqLooseSeg<'a> {
} }
} }
impl<'a> GetNextLoose for LooseBend<'a> { impl<'a, R: RulesTrait> GetNextLoose for LooseBend<'a, R> {
fn next_loose(&self, maybe_prev: Option<LooseIndex>) -> Option<LooseIndex> { fn next_loose(&self, maybe_prev: Option<LooseIndex>) -> Option<LooseIndex> {
let ends = self.joints(); let ends = self.joints();
let Some(prev) = maybe_prev else { let Some(prev) = maybe_prev else {

View File

@ -9,6 +9,7 @@ pub mod guide;
mod layout; mod layout;
pub mod loose; pub mod loose;
pub mod primitive; pub mod primitive;
pub mod rules;
pub mod seg; pub mod seg;
pub mod segbend; pub mod segbend;

View File

@ -20,19 +20,11 @@ use crate::layout::{
Layout, Layout,
}; };
#[enum_dispatch] use super::rules::RulesTrait;
pub trait GetLayout {
fn layout(&self) -> &Layout;
}
#[enum_dispatch] #[enum_dispatch]
pub trait GetConnectable: GetNet + GetLayout { pub trait GetLayout<'a, R: RulesTrait> {
fn connectable(&self, node: GeometryIndex) -> bool { fn layout(&self) -> &Layout<R>;
let this = self.net();
let other = node.primitive(self.layout()).net();
(this == other) || this == -1 || other == -1
}
} }
#[enum_dispatch] #[enum_dispatch]
@ -82,7 +74,7 @@ pub trait GetJoints<F, T> {
fn joints(&self) -> (F, T); fn joints(&self) -> (F, T);
} }
pub trait GetFirstRail: GetLayout + GetNodeIndex { pub trait GetFirstRail<'a, R: RulesTrait>: GetLayout<'a, R> + GetNodeIndex {
fn first_rail(&self) -> Option<LooseBendIndex> { fn first_rail(&self) -> Option<LooseBendIndex> {
self.layout() self.layout()
.geometry() .geometry()
@ -95,7 +87,7 @@ pub trait GetBendIndex {
fn bend_index(&self) -> BendIndex; fn bend_index(&self) -> BendIndex;
} }
pub trait GetCore: GetLayout + GetBendIndex { pub trait GetCore<'a, R: RulesTrait>: GetLayout<'a, R> + GetBendIndex {
fn core(&self) -> FixedDotIndex { fn core(&self) -> FixedDotIndex {
FixedDotIndex::new( FixedDotIndex::new(
self.layout() self.layout()
@ -106,7 +98,7 @@ pub trait GetCore: GetLayout + GetBendIndex {
} }
} }
pub trait GetInnerOuter: GetLayout + GetBendIndex { pub trait GetInnerOuter<'a, R: RulesTrait>: GetLayout<'a, R> + GetBendIndex {
fn inner(&self) -> Option<LooseBendIndex> { fn inner(&self) -> Option<LooseBendIndex> {
self.layout() self.layout()
.geometry() .geometry()
@ -124,7 +116,7 @@ pub trait GetInnerOuter: GetLayout + GetBendIndex {
macro_rules! impl_primitive { macro_rules! impl_primitive {
($primitive_struct:ident, $weight_struct:ident) => { ($primitive_struct:ident, $weight_struct:ident) => {
impl<'a> GetWeight<$weight_struct> for $primitive_struct<'a> { impl<'a, R: RulesTrait> GetWeight<$weight_struct> for $primitive_struct<'a, R> {
fn weight(&self) -> $weight_struct { fn weight(&self) -> $weight_struct {
if let GeometryWeight::$primitive_struct(weight) = self.tagged_weight() { if let GeometryWeight::$primitive_struct(weight) = self.tagged_weight() {
weight weight
@ -140,13 +132,13 @@ macro_rules! impl_fixed_primitive {
($primitive_struct:ident, $weight_struct:ident) => { ($primitive_struct:ident, $weight_struct:ident) => {
impl_primitive!($primitive_struct, $weight_struct); impl_primitive!($primitive_struct, $weight_struct);
impl<'a> GetComponentIndex for $primitive_struct<'a> { impl<'a, R: RulesTrait> GetComponentIndex for $primitive_struct<'a, R> {
fn component(&self) -> ComponentIndex { fn component(&self) -> ComponentIndex {
self.weight().component() self.weight().component()
} }
} }
impl<'a> GetNet for $primitive_struct<'a> { impl<'a, R: RulesTrait> GetNet for $primitive_struct<'a, R> {
fn net(&self) -> i64 { fn net(&self) -> i64 {
self.layout() self.layout()
.connectivity() .connectivity()
@ -162,7 +154,7 @@ macro_rules! impl_loose_primitive {
($primitive_struct:ident, $weight_struct:ident) => { ($primitive_struct:ident, $weight_struct:ident) => {
impl_primitive!($primitive_struct, $weight_struct); impl_primitive!($primitive_struct, $weight_struct);
impl<'a> GetNet for $primitive_struct<'a> { impl<'a, R: RulesTrait> GetNet for $primitive_struct<'a, R> {
fn net(&self) -> i64 { fn net(&self) -> i64 {
self.layout() self.layout()
.connectivity() .connectivity()
@ -174,25 +166,25 @@ macro_rules! impl_loose_primitive {
}; };
} }
#[enum_dispatch(GetNet, GetWidth, GetLayout, GetConnectable, MakeShape, GetLimbs)] #[enum_dispatch(GetNet, GetWidth, GetLayout, MakeShape, GetLimbs)]
pub enum Primitive<'a> { pub enum Primitive<'a, R: RulesTrait> {
FixedDot(FixedDot<'a>), FixedDot(FixedDot<'a, R>),
LooseDot(LooseDot<'a>), LooseDot(LooseDot<'a, R>),
FixedSeg(FixedSeg<'a>), FixedSeg(FixedSeg<'a, R>),
LoneLooseSeg(LoneLooseSeg<'a>), LoneLooseSeg(LoneLooseSeg<'a, R>),
SeqLooseSeg(SeqLooseSeg<'a>), SeqLooseSeg(SeqLooseSeg<'a, R>),
FixedBend(FixedBend<'a>), FixedBend(FixedBend<'a, R>),
LooseBend(LooseBend<'a>), LooseBend(LooseBend<'a, R>),
} }
#[derive(Debug)] #[derive(Debug)]
pub struct GenericPrimitive<'a, W> { pub struct GenericPrimitive<'a, W, R: RulesTrait> {
pub index: GenericIndex<W>, pub index: GenericIndex<W>,
layout: &'a Layout, layout: &'a Layout<R>,
} }
impl<'a, W> GenericPrimitive<'a, W> { impl<'a, W, R: RulesTrait> GenericPrimitive<'a, W, R> {
pub fn new(index: GenericIndex<W>, layout: &'a Layout) -> Self { pub fn new(index: GenericIndex<W>, layout: &'a Layout<R>) -> Self {
Self { index, layout } Self { index, layout }
} }
@ -205,44 +197,42 @@ impl<'a, W> GenericPrimitive<'a, W> {
.unwrap() .unwrap()
} }
fn primitive<WW>(&self, index: GenericIndex<WW>) -> GenericPrimitive<WW> { fn primitive<WW>(&self, index: GenericIndex<WW>) -> GenericPrimitive<WW, R> {
GenericPrimitive::new(index, &self.layout) GenericPrimitive::new(index, &self.layout)
} }
} }
impl<'a, W> GetInterior<GeometryIndex> for GenericPrimitive<'a, W> { impl<'a, W, R: RulesTrait> GetInterior<GeometryIndex> for GenericPrimitive<'a, W, R> {
fn interior(&self) -> Vec<GeometryIndex> { fn interior(&self) -> Vec<GeometryIndex> {
vec![self.tagged_weight().retag(self.index.node_index())] vec![self.tagged_weight().retag(self.index.node_index())]
} }
} }
impl<'a, W> GetLayout for GenericPrimitive<'a, W> { impl<'a, W, R: RulesTrait> GetLayout<'a, R> for GenericPrimitive<'a, W, R> {
fn layout(&self) -> &Layout { fn layout(&self) -> &Layout<R> {
self.layout self.layout
} }
} }
impl<'a, W> GetNodeIndex for GenericPrimitive<'a, W> { impl<'a, W, R: RulesTrait> GetNodeIndex for GenericPrimitive<'a, W, R> {
fn node_index(&self) -> NodeIndex<usize> { fn node_index(&self) -> NodeIndex<usize> {
self.index.node_index() self.index.node_index()
} }
} }
impl<'a, W> GetConnectable for GenericPrimitive<'a, W> where GenericPrimitive<'a, W>: GetNet {} impl<'a, W: GetWidth, R: RulesTrait> GetWidth for GenericPrimitive<'a, W, R>
impl<'a, W: GetWidth> GetWidth for GenericPrimitive<'a, W>
where where
GenericPrimitive<'a, W>: GetWeight<W>, GenericPrimitive<'a, W, R>: GetWeight<W>,
{ {
fn width(&self) -> f64 { fn width(&self) -> f64 {
self.weight().width() self.weight().width()
} }
} }
pub type FixedDot<'a> = GenericPrimitive<'a, FixedDotWeight>; pub type FixedDot<'a, R> = GenericPrimitive<'a, FixedDotWeight, R>;
impl_fixed_primitive!(FixedDot, FixedDotWeight); impl_fixed_primitive!(FixedDot, FixedDotWeight);
impl<'a> FixedDot<'a> { impl<'a, R: RulesTrait> FixedDot<'a, R> {
pub fn first_loose(&self, _band: BandIndex) -> Option<LooseIndex> { pub fn first_loose(&self, _band: BandIndex) -> Option<LooseIndex> {
self.layout self.layout
.geometry() .geometry()
@ -266,13 +256,13 @@ impl<'a> FixedDot<'a> {
} }
} }
impl<'a> MakeShape for FixedDot<'a> { impl<'a, R: RulesTrait> MakeShape for FixedDot<'a, R> {
fn shape(&self) -> Shape { fn shape(&self) -> Shape {
self.layout.geometry().dot_shape(self.index.into()) self.layout.geometry().dot_shape(self.index.into())
} }
} }
impl<'a> GetLimbs for FixedDot<'a> { impl<'a, R: RulesTrait> GetLimbs for FixedDot<'a, R> {
fn segs(&self) -> Vec<SegIndex> { fn segs(&self) -> Vec<SegIndex> {
self.layout self.layout
.geometry() .geometry()
@ -288,12 +278,12 @@ impl<'a> GetLimbs for FixedDot<'a> {
} }
} }
impl<'a> GetFirstRail for FixedDot<'a> {} impl<'a, R: RulesTrait> GetFirstRail<'a, R> for FixedDot<'a, R> {}
pub type LooseDot<'a> = GenericPrimitive<'a, LooseDotWeight>; pub type LooseDot<'a, R> = GenericPrimitive<'a, LooseDotWeight, R>;
impl_loose_primitive!(LooseDot, LooseDotWeight); impl_loose_primitive!(LooseDot, LooseDotWeight);
impl<'a> LooseDot<'a> { impl<'a, R: RulesTrait> LooseDot<'a, R> {
pub fn seg(&self) -> Option<SeqLooseSegIndex> { pub fn seg(&self) -> Option<SeqLooseSegIndex> {
self.layout self.layout
.geometry() .geometry()
@ -312,13 +302,13 @@ impl<'a> LooseDot<'a> {
} }
} }
impl<'a> MakeShape for LooseDot<'a> { impl<'a, R: RulesTrait> MakeShape for LooseDot<'a, R> {
fn shape(&self) -> Shape { fn shape(&self) -> Shape {
self.layout.geometry().dot_shape(self.index.into()) self.layout.geometry().dot_shape(self.index.into())
} }
} }
impl<'a> GetLimbs for LooseDot<'a> { impl<'a, R: RulesTrait> GetLimbs for LooseDot<'a, R> {
fn segs(&self) -> Vec<SegIndex> { fn segs(&self) -> Vec<SegIndex> {
if let Some(seg) = self.seg() { if let Some(seg) = self.seg() {
vec![seg.into()] vec![seg.into()]
@ -332,18 +322,18 @@ impl<'a> GetLimbs for LooseDot<'a> {
} }
} }
pub type FixedSeg<'a> = GenericPrimitive<'a, FixedSegWeight>; pub type FixedSeg<'a, R> = GenericPrimitive<'a, FixedSegWeight, R>;
impl_fixed_primitive!(FixedSeg, FixedSegWeight); impl_fixed_primitive!(FixedSeg, FixedSegWeight);
impl<'a> MakeShape for FixedSeg<'a> { impl<'a, R: RulesTrait> MakeShape for FixedSeg<'a, R> {
fn shape(&self) -> Shape { fn shape(&self) -> Shape {
self.layout.geometry().seg_shape(self.index.into()) self.layout.geometry().seg_shape(self.index.into())
} }
} }
impl<'a> GetLimbs for FixedSeg<'a> {} impl<'a, R: RulesTrait> GetLimbs for FixedSeg<'a, R> {}
impl<'a> GetJoints<FixedDotIndex, FixedDotIndex> for FixedSeg<'a> { impl<'a, R: RulesTrait> GetJoints<FixedDotIndex, FixedDotIndex> for FixedSeg<'a, R> {
fn joints(&self) -> (FixedDotIndex, FixedDotIndex) { fn joints(&self) -> (FixedDotIndex, FixedDotIndex) {
let (from, to) = self.layout.geometry().seg_joints(self.index.into()); let (from, to) = self.layout.geometry().seg_joints(self.index.into());
( (
@ -353,20 +343,20 @@ impl<'a> GetJoints<FixedDotIndex, FixedDotIndex> for FixedSeg<'a> {
} }
} }
impl<'a> GetOtherJoint<FixedDotIndex, FixedDotIndex> for FixedSeg<'a> {} impl<'a, R: RulesTrait> GetOtherJoint<FixedDotIndex, FixedDotIndex> for FixedSeg<'a, R> {}
pub type LoneLooseSeg<'a> = GenericPrimitive<'a, LoneLooseSegWeight>; pub type LoneLooseSeg<'a, R> = GenericPrimitive<'a, LoneLooseSegWeight, R>;
impl_loose_primitive!(LoneLooseSeg, LoneLooseSegWeight); impl_loose_primitive!(LoneLooseSeg, LoneLooseSegWeight);
impl<'a> MakeShape for LoneLooseSeg<'a> { impl<'a, R: RulesTrait> MakeShape for LoneLooseSeg<'a, R> {
fn shape(&self) -> Shape { fn shape(&self) -> Shape {
self.layout.geometry().seg_shape(self.index.into()) self.layout.geometry().seg_shape(self.index.into())
} }
} }
impl<'a> GetLimbs for LoneLooseSeg<'a> {} impl<'a, R: RulesTrait> GetLimbs for LoneLooseSeg<'a, R> {}
impl<'a> GetJoints<FixedDotIndex, FixedDotIndex> for LoneLooseSeg<'a> { impl<'a, R: RulesTrait> GetJoints<FixedDotIndex, FixedDotIndex> for LoneLooseSeg<'a, R> {
fn joints(&self) -> (FixedDotIndex, FixedDotIndex) { fn joints(&self) -> (FixedDotIndex, FixedDotIndex) {
let (from, to) = self.layout.geometry().seg_joints(self.index.into()); let (from, to) = self.layout.geometry().seg_joints(self.index.into());
( (
@ -376,20 +366,20 @@ impl<'a> GetJoints<FixedDotIndex, FixedDotIndex> for LoneLooseSeg<'a> {
} }
} }
impl<'a> GetOtherJoint<FixedDotIndex, FixedDotIndex> for LoneLooseSeg<'a> {} impl<'a, R: RulesTrait> GetOtherJoint<FixedDotIndex, FixedDotIndex> for LoneLooseSeg<'a, R> {}
pub type SeqLooseSeg<'a> = GenericPrimitive<'a, SeqLooseSegWeight>; pub type SeqLooseSeg<'a, R> = GenericPrimitive<'a, SeqLooseSegWeight, R>;
impl_loose_primitive!(SeqLooseSeg, SeqLooseSegWeight); impl_loose_primitive!(SeqLooseSeg, SeqLooseSegWeight);
impl<'a> MakeShape for SeqLooseSeg<'a> { impl<'a, R: RulesTrait> MakeShape for SeqLooseSeg<'a, R> {
fn shape(&self) -> Shape { fn shape(&self) -> Shape {
self.layout.geometry().seg_shape(self.index.into()) self.layout.geometry().seg_shape(self.index.into())
} }
} }
impl<'a> GetLimbs for SeqLooseSeg<'a> {} impl<'a, R: RulesTrait> GetLimbs for SeqLooseSeg<'a, R> {}
impl<'a> GetJoints<DotIndex, LooseDotIndex> for SeqLooseSeg<'a> { impl<'a, R: RulesTrait> GetJoints<DotIndex, LooseDotIndex> for SeqLooseSeg<'a, R> {
fn joints(&self) -> (DotIndex, LooseDotIndex) { fn joints(&self) -> (DotIndex, LooseDotIndex) {
let joints = self.layout.geometry().seg_joints(self.index.into()); let joints = self.layout.geometry().seg_joints(self.index.into());
if let DotWeight::Fixed(..) = self.layout.geometry().dot_weight(joints.0) { if let DotWeight::Fixed(..) = self.layout.geometry().dot_weight(joints.0) {
@ -411,26 +401,26 @@ impl<'a> GetJoints<DotIndex, LooseDotIndex> for SeqLooseSeg<'a> {
} }
} }
impl<'a> GetOtherJoint<DotIndex, LooseDotIndex> for SeqLooseSeg<'a> {} impl<'a, R: RulesTrait> GetOtherJoint<DotIndex, LooseDotIndex> for SeqLooseSeg<'a, R> {}
pub type FixedBend<'a> = GenericPrimitive<'a, FixedBendWeight>; pub type FixedBend<'a, R> = GenericPrimitive<'a, FixedBendWeight, R>;
impl_fixed_primitive!(FixedBend, FixedBendWeight); impl_fixed_primitive!(FixedBend, FixedBendWeight);
impl<'a> GetBendIndex for FixedBend<'a> { impl<'a, R: RulesTrait> GetBendIndex for FixedBend<'a, R> {
fn bend_index(&self) -> BendIndex { fn bend_index(&self) -> BendIndex {
self.index.into() self.index.into()
} }
} }
impl<'a> MakeShape for FixedBend<'a> { impl<'a, R: RulesTrait> MakeShape for FixedBend<'a, R> {
fn shape(&self) -> Shape { fn shape(&self) -> Shape {
self.layout.geometry().bend_shape(self.index.into()) self.layout.geometry().bend_shape(self.index.into())
} }
} }
impl<'a> GetLimbs for FixedBend<'a> {} impl<'a, R: RulesTrait> GetLimbs for FixedBend<'a, R> {}
impl<'a> GetJoints<FixedDotIndex, FixedDotIndex> for FixedBend<'a> { impl<'a, R: RulesTrait> GetJoints<FixedDotIndex, FixedDotIndex> for FixedBend<'a, R> {
fn joints(&self) -> (FixedDotIndex, FixedDotIndex) { fn joints(&self) -> (FixedDotIndex, FixedDotIndex) {
let (from, to) = self.layout.geometry().bend_joints(self.index.into()); let (from, to) = self.layout.geometry().bend_joints(self.index.into());
( (
@ -440,41 +430,41 @@ impl<'a> GetJoints<FixedDotIndex, FixedDotIndex> for FixedBend<'a> {
} }
} }
impl<'a> GetOtherJoint<FixedDotIndex, FixedDotIndex> for FixedBend<'a> {} impl<'a, R: RulesTrait> GetOtherJoint<FixedDotIndex, FixedDotIndex> for FixedBend<'a, R> {}
impl<'a> GetFirstRail for FixedBend<'a> {} impl<'a, R: RulesTrait> GetFirstRail<'a, R> for FixedBend<'a, R> {}
impl<'a> GetCore for FixedBend<'a> {} // TODO: Fixed bends don't have cores actually. impl<'a, R: RulesTrait> GetCore<'a, R> for FixedBend<'a, R> {} // TODO: Fixed bends don't have cores actually.
//impl<'a> GetInnerOuter for FixedBend<'a> {} //impl<'a, R: QueryRules> GetInnerOuter for FixedBend<'a, R> {}
pub type LooseBend<'a> = GenericPrimitive<'a, LooseBendWeight>; pub type LooseBend<'a, R> = GenericPrimitive<'a, LooseBendWeight, R>;
impl_loose_primitive!(LooseBend, LooseBendWeight); impl_loose_primitive!(LooseBend, LooseBendWeight);
impl<'a> GetBendIndex for LooseBend<'a> { impl<'a, R: RulesTrait> GetBendIndex for LooseBend<'a, R> {
fn bend_index(&self) -> BendIndex { fn bend_index(&self) -> BendIndex {
self.index.into() self.index.into()
} }
} }
impl<'a> From<LooseBend<'a>> for BendIndex { impl<'a, R: RulesTrait> From<LooseBend<'a, R>> for BendIndex {
fn from(bend: LooseBend<'a>) -> BendIndex { fn from(bend: LooseBend<'a, R>) -> BendIndex {
bend.index.into() bend.index.into()
} }
} }
impl<'a> MakeShape for LooseBend<'a> { impl<'a, R: RulesTrait> MakeShape for LooseBend<'a, R> {
fn shape(&self) -> Shape { fn shape(&self) -> Shape {
self.layout.geometry().bend_shape(self.index.into()) self.layout.geometry().bend_shape(self.index.into())
} }
} }
impl<'a> GetLimbs for LooseBend<'a> {} impl<'a, R: RulesTrait> GetLimbs for LooseBend<'a, R> {}
impl<'a> GetOffset for LooseBend<'a> { impl<'a, R: RulesTrait> GetOffset for LooseBend<'a, R> {
fn offset(&self) -> f64 { fn offset(&self) -> f64 {
self.weight().offset self.weight().offset
} }
} }
impl<'a> GetJoints<LooseDotIndex, LooseDotIndex> for LooseBend<'a> { impl<'a, R: RulesTrait> GetJoints<LooseDotIndex, LooseDotIndex> for LooseBend<'a, R> {
fn joints(&self) -> (LooseDotIndex, LooseDotIndex) { fn joints(&self) -> (LooseDotIndex, LooseDotIndex) {
let (from, to) = self.layout.geometry().bend_joints(self.index.into()); let (from, to) = self.layout.geometry().bend_joints(self.index.into());
( (
@ -484,6 +474,6 @@ impl<'a> GetJoints<LooseDotIndex, LooseDotIndex> for LooseBend<'a> {
} }
} }
impl<'a> GetOtherJoint<LooseDotIndex, LooseDotIndex> for LooseBend<'a> {} impl<'a, R: RulesTrait> GetOtherJoint<LooseDotIndex, LooseDotIndex> for LooseBend<'a, R> {}
impl<'a> GetCore for LooseBend<'a> {} impl<'a, R: RulesTrait> GetCore<'a, R> for LooseBend<'a, R> {}
impl<'a> GetInnerOuter for LooseBend<'a> {} impl<'a, R: RulesTrait> GetInnerOuter<'a, R> for LooseBend<'a, R> {}

18
src/layout/rules.rs Normal file
View File

@ -0,0 +1,18 @@
pub struct Conditions {
layer: Option<String>,
region: Option<String>,
netclass: Option<String>,
}
pub struct LayerNetclassConditions {
region: Option<String>,
}
pub trait RulesTrait {
fn clearance(conditions1: &Conditions, conditions2: &Conditions) -> f64;
fn clearance_limit(
layer: String,
netclass: String,
conditions: &LayerNetclassConditions,
) -> f64;
}

View File

@ -10,6 +10,7 @@ use crate::{
MakePrimitive, Retag, MakePrimitive, Retag,
}, },
primitive::{GenericPrimitive, Primitive}, primitive::{GenericPrimitive, Primitive},
rules::RulesTrait,
Layout, Layout,
}, },
}; };

View File

@ -7,6 +7,8 @@ use crate::layout::{
Layout, Layout,
}; };
use super::rules::RulesTrait;
#[derive(Debug, Clone, Copy)] #[derive(Debug, Clone, Copy)]
pub struct Segbend { pub struct Segbend {
pub seg: SeqLooseSegIndex, pub seg: SeqLooseSegIndex,
@ -15,7 +17,7 @@ pub struct Segbend {
} }
impl Segbend { impl Segbend {
pub fn from_dot(dot: LooseDotIndex, layout: &Layout) -> Self { pub fn from_dot(dot: LooseDotIndex, layout: &Layout<impl RulesTrait>) -> Self {
let bend = LooseDot::new(dot, layout).bend(); let bend = LooseDot::new(dot, layout).bend();
let dot = LooseBend::new(bend, layout).other_joint(dot); let dot = LooseBend::new(bend, layout).other_joint(dot);
let seg = LooseDot::new(dot, layout).seg().unwrap(); let seg = LooseDot::new(dot, layout).seg().unwrap();

View File

@ -28,11 +28,12 @@ use layout::dot::FixedDotWeight;
use layout::geometry::shape::{Shape, ShapeTrait}; use layout::geometry::shape::{Shape, ShapeTrait};
use layout::graph::{GeometryIndex, MakePrimitive}; use layout::graph::{GeometryIndex, MakePrimitive};
use layout::primitive::MakeShape; use layout::primitive::MakeShape;
use layout::rules::{Conditions, LayerNetclassConditions, RulesTrait};
use layout::seg::FixedSegWeight; use layout::seg::FixedSegWeight;
use layout::{Infringement, Layout, LayoutException}; use layout::{Infringement, Layout, LayoutException};
use mesh::{Mesh, MeshEdgeReference, VertexIndex}; use mesh::{Mesh, MeshEdgeReference, VertexIndex};
use petgraph::visit::{EdgeRef, IntoEdgeReferences}; use petgraph::visit::{EdgeRef, IntoEdgeReferences};
use router::RouterObserver; use router::RouterObserverTrait;
use sdl2::event::Event; use sdl2::event::Event;
use sdl2::keyboard::Keycode; use sdl2::keyboard::Keycode;
@ -57,26 +58,42 @@ use tracer::{Trace, Tracer};
use crate::math::Circle; use crate::math::Circle;
use crate::router::Router; use crate::router::Router;
struct ConstantClearance {}
impl RulesTrait for ConstantClearance {
fn clearance(conditions1: &Conditions, conditions2: &Conditions) -> f64 {
3.0
}
fn clearance_limit(
layer: String,
netclass: String,
conditions: &LayerNetclassConditions,
) -> f64 {
3.0
}
}
// Clunky enum to work around borrow checker. // Clunky enum to work around borrow checker.
enum RouterOrLayout<'a> { enum RouterOrLayout<'a, R: RulesTrait> {
Router(&'a mut Router), Router(&'a mut Router<R>),
Layout(&'a Layout), Layout(&'a Layout<R>),
} }
struct EmptyRouterObserver; struct EmptyRouterObserver;
impl RouterObserver for EmptyRouterObserver { impl<R: RulesTrait> RouterObserverTrait<R> for EmptyRouterObserver {
fn on_rework(&mut self, _tracer: &Tracer, _trace: &Trace) {} fn on_rework(&mut self, _tracer: &Tracer<R>, _trace: &Trace) {}
fn before_probe(&mut self, _tracer: &Tracer, _trace: &Trace, _edge: MeshEdgeReference) {} fn before_probe(&mut self, _tracer: &Tracer<R>, _trace: &Trace, _edge: MeshEdgeReference) {}
fn on_probe( fn on_probe(
&mut self, &mut self,
_tracer: &Tracer, _tracer: &Tracer<R>,
_trace: &Trace, _trace: &Trace,
_edge: MeshEdgeReference, _edge: MeshEdgeReference,
_result: Result<(), DrawException>, _result: Result<(), DrawException>,
) { ) {
} }
fn on_estimate(&mut self, _tracer: &Tracer, _vertex: VertexIndex) {} fn on_estimate(&mut self, _tracer: &Tracer<R>, _vertex: VertexIndex) {}
} }
struct DebugRouterObserver<'a> { struct DebugRouterObserver<'a> {
@ -102,8 +119,8 @@ impl<'a> DebugRouterObserver<'a> {
} }
} }
impl<'a> RouterObserver for DebugRouterObserver<'a> { impl<'a, R: RulesTrait> RouterObserverTrait<R> for DebugRouterObserver<'a> {
fn on_rework(&mut self, tracer: &Tracer, trace: &Trace) { fn on_rework(&mut self, tracer: &Tracer<R>, trace: &Trace) {
render_times( render_times(
self.event_pump, self.event_pump,
self.window, self.window,
@ -119,7 +136,7 @@ impl<'a> RouterObserver for DebugRouterObserver<'a> {
); );
} }
fn before_probe(&mut self, tracer: &Tracer, trace: &Trace, edge: MeshEdgeReference) { fn before_probe(&mut self, tracer: &Tracer<R>, trace: &Trace, edge: MeshEdgeReference) {
let mut path = trace.path.clone(); let mut path = trace.path.clone();
path.push(edge.target()); path.push(edge.target());
render_times( render_times(
@ -139,7 +156,7 @@ impl<'a> RouterObserver for DebugRouterObserver<'a> {
fn on_probe( fn on_probe(
&mut self, &mut self,
tracer: &Tracer, tracer: &Tracer<R>,
trace: &Trace, trace: &Trace,
_edge: MeshEdgeReference, _edge: MeshEdgeReference,
result: Result<(), DrawException>, result: Result<(), DrawException>,
@ -168,7 +185,7 @@ impl<'a> RouterObserver for DebugRouterObserver<'a> {
); );
} }
fn on_estimate(&mut self, _tracer: &Tracer, _vertex: VertexIndex) {} fn on_estimate(&mut self, _tracer: &Tracer<R>, _vertex: VertexIndex) {}
} }
fn main() -> Result<(), anyhow::Error> { fn main() -> Result<(), anyhow::Error> {
@ -218,7 +235,7 @@ fn main() -> Result<(), anyhow::Error> {
let mut event_pump = sdl_context.event_pump().unwrap(); let mut event_pump = sdl_context.event_pump().unwrap();
let _i = 0; let _i = 0;
let mut router = Router::new(); let mut router = Router::new(ConstantClearance {});
let component1_1 = router.layout.add_component(1); let component1_1 = router.layout.add_component(1);
let component1_2 = router.layout.add_component(1); let component1_2 = router.layout.add_component(1);
@ -321,7 +338,7 @@ fn main() -> Result<(), anyhow::Error> {
dot2_1, dot2_1,
FixedSegWeight { FixedSegWeight {
component: component2, component: component2,
width: 16.0, width: 3.0,
}, },
); );
@ -341,7 +358,7 @@ fn main() -> Result<(), anyhow::Error> {
dot2_2, dot2_2,
FixedSegWeight { FixedSegWeight {
component: component2, component: component2,
width: 16.0, width: 3.0,
}, },
); );
@ -372,7 +389,7 @@ fn main() -> Result<(), anyhow::Error> {
dot4, dot4,
FixedSegWeight { FixedSegWeight {
component: component2, component: component2,
width: 16.0, width: 3.0,
}, },
); );
@ -392,7 +409,7 @@ fn main() -> Result<(), anyhow::Error> {
dot5, dot5,
FixedSegWeight { FixedSegWeight {
component: component2, component: component2,
width: 16.0, width: 3.0,
}, },
); );
@ -412,7 +429,7 @@ fn main() -> Result<(), anyhow::Error> {
dot1_2, dot1_2,
FixedSegWeight { FixedSegWeight {
component: component2, component: component2,
width: 16.0, width: 3.0,
}, },
); );
@ -421,7 +438,7 @@ fn main() -> Result<(), anyhow::Error> {
dot2_2, dot2_2,
FixedSegWeight { FixedSegWeight {
component: component2, component: component2,
width: 16.0, width: 3.0,
}, },
); );
@ -441,7 +458,7 @@ fn main() -> Result<(), anyhow::Error> {
dot6, dot6,
FixedSegWeight { FixedSegWeight {
component: component2, component: component2,
width: 16.0, width: 3.0,
}, },
); );
@ -461,7 +478,7 @@ fn main() -> Result<(), anyhow::Error> {
dot7, dot7,
FixedSegWeight { FixedSegWeight {
net: 20, net: 20,
width: 16.0, width: 3.0,
}, },
);*/ );*/
@ -613,7 +630,7 @@ fn render_times(
window: &Window, window: &Window,
renderer: &mut Renderer<GLDevice>, renderer: &mut Renderer<GLDevice>,
font_context: &CanvasFontContext, font_context: &CanvasFontContext,
mut router_or_layout: RouterOrLayout, mut router_or_layout: RouterOrLayout<impl RulesTrait>,
maybe_band: Option<BandIndex>, maybe_band: Option<BandIndex>,
mut maybe_mesh: Option<Mesh>, mut maybe_mesh: Option<Mesh>,
path: &[VertexIndex], path: &[VertexIndex],

View File

@ -7,6 +7,7 @@ use petgraph::visit::{self, NodeIndexable};
use petgraph::{stable_graph::NodeIndex, visit::EdgeRef}; use petgraph::{stable_graph::NodeIndex, visit::EdgeRef};
use spade::{HasPosition, InsertionError, Point2}; use spade::{HasPosition, InsertionError, Point2};
use crate::layout::rules::RulesTrait;
use crate::triangulation::TriangulationEdgeReference; use crate::triangulation::TriangulationEdgeReference;
use crate::{ use crate::{
graph::GetNodeIndex, graph::GetNodeIndex,
@ -82,7 +83,7 @@ pub struct Mesh {
} }
impl Mesh { impl Mesh {
pub fn new(layout: &Layout) -> Self { pub fn new(layout: &Layout<impl RulesTrait>) -> Self {
let mut this = Self { let mut this = Self {
triangulation: Triangulation::new(layout), triangulation: Triangulation::new(layout),
vertex_to_triangulation_vertex: Vec::new(), vertex_to_triangulation_vertex: Vec::new(),
@ -92,7 +93,7 @@ impl Mesh {
this this
} }
pub fn generate(&mut self, layout: &Layout) -> Result<(), InsertionError> { pub fn generate(&mut self, layout: &Layout<impl RulesTrait>) -> Result<(), InsertionError> {
for node in layout.nodes() { for node in layout.nodes() {
let center = node.primitive(layout).shape().center(); let center = node.primitive(layout).shape().center();

View File

@ -7,6 +7,7 @@ use thiserror::Error;
use crate::astar::{astar, AstarStrategy, PathTracker}; use crate::astar::{astar, AstarStrategy, PathTracker};
use crate::draw::DrawException; use crate::draw::DrawException;
use crate::layout::guide::HeadTrait; use crate::layout::guide::HeadTrait;
use crate::layout::rules::RulesTrait;
use crate::layout::Layout; use crate::layout::Layout;
use crate::layout::{ use crate::layout::{
connectivity::BandIndex, connectivity::BandIndex,
@ -39,33 +40,38 @@ pub enum RoutingErrorKind {
AStar, AStar,
} }
pub trait RouterObserver { pub trait RouterObserverTrait<R: RulesTrait> {
fn on_rework(&mut self, tracer: &Tracer, trace: &Trace); fn on_rework(&mut self, tracer: &Tracer<R>, trace: &Trace);
fn before_probe(&mut self, tracer: &Tracer, trace: &Trace, edge: MeshEdgeReference); fn before_probe(&mut self, tracer: &Tracer<R>, trace: &Trace, edge: MeshEdgeReference);
fn on_probe( fn on_probe(
&mut self, &mut self,
tracer: &Tracer, tracer: &Tracer<R>,
trace: &Trace, trace: &Trace,
edge: MeshEdgeReference, edge: MeshEdgeReference,
result: Result<(), DrawException>, result: Result<(), DrawException>,
); );
fn on_estimate(&mut self, tracer: &Tracer, vertex: VertexIndex); fn on_estimate(&mut self, tracer: &Tracer<R>, vertex: VertexIndex);
} }
pub struct Router { pub struct Router<R: RulesTrait> {
pub layout: Layout, pub layout: Layout<R>,
rules: Rules, rules: Rules,
} }
struct RouterAstarStrategy<'a, RO: RouterObserver> { struct RouterAstarStrategy<'a, RO: RouterObserverTrait<R>, R: RulesTrait> {
tracer: Tracer<'a>, tracer: Tracer<'a, R>,
trace: Trace, trace: Trace,
to: FixedDotIndex, to: FixedDotIndex,
observer: &'a mut RO, observer: &'a mut RO,
} }
impl<'a, RO: RouterObserver> RouterAstarStrategy<'a, RO> { impl<'a, RO: RouterObserverTrait<R>, R: RulesTrait> RouterAstarStrategy<'a, RO, R> {
pub fn new(tracer: Tracer<'a>, trace: Trace, to: FixedDotIndex, observer: &'a mut RO) -> Self { pub fn new(
tracer: Tracer<'a, R>,
trace: Trace,
to: FixedDotIndex,
observer: &'a mut RO,
) -> Self {
Self { Self {
tracer, tracer,
trace, trace,
@ -75,7 +81,9 @@ impl<'a, RO: RouterObserver> RouterAstarStrategy<'a, RO> {
} }
} }
impl<'a, RO: RouterObserver> AstarStrategy<&Mesh, f64> for RouterAstarStrategy<'a, RO> { impl<'a, RO: RouterObserverTrait<R>, R: RulesTrait> AstarStrategy<&Mesh, f64>
for RouterAstarStrategy<'a, RO, R>
{
fn is_goal(&mut self, vertex: VertexIndex, tracker: &PathTracker<&Mesh>) -> bool { fn is_goal(&mut self, vertex: VertexIndex, tracker: &PathTracker<&Mesh>) -> bool {
let new_path = tracker.reconstruct_path_to(vertex); let new_path = tracker.reconstruct_path_to(vertex);
@ -120,10 +128,10 @@ impl<'a, RO: RouterObserver> AstarStrategy<&Mesh, f64> for RouterAstarStrategy<'
} }
} }
impl Router { impl<R: RulesTrait> Router<R> {
pub fn new() -> Self { pub fn new(rules: R) -> Self {
Router { Router {
layout: Layout::new(), layout: Layout::new(rules),
rules: Rules::new(), rules: Rules::new(),
} }
} }
@ -132,7 +140,7 @@ impl Router {
&mut self, &mut self,
from: FixedDotIndex, from: FixedDotIndex,
to: FixedDotIndex, to: FixedDotIndex,
observer: &mut impl RouterObserver, observer: &mut impl RouterObserverTrait<R>,
) -> Result<BandIndex, RoutingError> { ) -> Result<BandIndex, RoutingError> {
// XXX: Should we actually store the mesh? May be useful for debugging, but doesn't look // XXX: Should we actually store the mesh? May be useful for debugging, but doesn't look
// right. // right.
@ -166,7 +174,7 @@ impl Router {
&mut self, &mut self,
band: BandIndex, band: BandIndex,
to: Point, to: Point,
observer: &mut impl RouterObserver, observer: &mut impl RouterObserverTrait<R>,
) -> Result<BandIndex, RoutingError> { ) -> Result<BandIndex, RoutingError> {
let from_dot = self.layout.band(band).from(); let from_dot = self.layout.band(band).from();
let to_dot = self.layout.band(band).to().unwrap(); let to_dot = self.layout.band(band).to().unwrap();
@ -175,7 +183,7 @@ impl Router {
self.route_band(from_dot, to_dot, observer) self.route_band(from_dot, to_dot, observer)
} }
pub fn tracer<'a>(&'a mut self, mesh: &'a Mesh) -> Tracer { pub fn tracer<'a>(&'a mut self, mesh: &'a Mesh) -> Tracer<R> {
Tracer::new(&mut self.layout, &self.rules, mesh) Tracer::new(&mut self.layout, &self.rules, mesh)
} }
} }

View File

@ -6,6 +6,7 @@ use crate::{
bend::LooseBendIndex, bend::LooseBendIndex,
dot::FixedDotIndex, dot::FixedDotIndex,
guide::{BareHead, Head, SegbendHead}, guide::{BareHead, Head, SegbendHead},
rules::RulesTrait,
Layout, Layout,
}, },
mesh::{Mesh, VertexIndex}, mesh::{Mesh, VertexIndex},
@ -18,14 +19,14 @@ pub struct Trace {
pub head: Head, pub head: Head,
} }
pub struct Tracer<'a> { pub struct Tracer<'a, R: RulesTrait> {
pub layout: &'a mut Layout, pub layout: &'a mut Layout<R>,
pub rules: &'a Rules, pub rules: &'a Rules,
pub mesh: &'a Mesh, pub mesh: &'a Mesh,
} }
impl<'a> Tracer<'a> { impl<'a, R: RulesTrait> Tracer<'a, R> {
pub fn new(layout: &'a mut Layout, rules: &'a Rules, mesh: &'a Mesh) -> Self { pub fn new(layout: &'a mut Layout<R>, rules: &'a Rules, mesh: &'a Mesh) -> Self {
Tracer { Tracer {
layout, layout,
rules, rules,
@ -128,7 +129,9 @@ impl<'a> Tracer<'a> {
around: FixedDotIndex, around: FixedDotIndex,
width: f64, width: f64,
) -> Result<SegbendHead, DrawException> { ) -> Result<SegbendHead, DrawException> {
let head = self.draw().segbend_around_dot(head, around.into(), width)?; let head = self
.draw()
.segbend_around_dot(head, around.into(), width, 3.0)?;
Ok(head) Ok(head)
} }
@ -140,7 +143,7 @@ impl<'a> Tracer<'a> {
) -> Result<SegbendHead, DrawException> { ) -> Result<SegbendHead, DrawException> {
let head = self let head = self
.draw() .draw()
.segbend_around_bend(head, around.into(), width)?; .segbend_around_bend(head, around.into(), width, 3.0)?;
Ok(head) Ok(head)
} }
@ -156,7 +159,7 @@ impl<'a> Tracer<'a> {
trace.path.pop(); trace.path.pop();
} }
fn draw(&mut self) -> Draw { fn draw(&mut self) -> Draw<R> {
Draw::new(&mut self.layout, &self.rules) Draw::new(&mut self.layout, &self.rules)
} }
} }

View File

@ -4,7 +4,10 @@ use geo::{point, Point};
use petgraph::visit::{self, NodeIndexable}; use petgraph::visit::{self, NodeIndexable};
use spade::{handles::FixedVertexHandle, DelaunayTriangulation, HasPosition, InsertionError}; use spade::{handles::FixedVertexHandle, DelaunayTriangulation, HasPosition, InsertionError};
use crate::{graph::GetNodeIndex, layout::Layout}; use crate::{
graph::GetNodeIndex,
layout::{rules::RulesTrait, Layout},
};
pub trait GetVertexIndex<I> { pub trait GetVertexIndex<I> {
fn vertex(&self) -> I; fn vertex(&self) -> I;
@ -20,7 +23,7 @@ pub struct Triangulation<I: Copy + PartialEq + GetNodeIndex, W: GetVertexIndex<I
impl<I: Copy + PartialEq + GetNodeIndex, W: GetVertexIndex<I> + HasPosition<Scalar = f64>> impl<I: Copy + PartialEq + GetNodeIndex, W: GetVertexIndex<I> + HasPosition<Scalar = f64>>
Triangulation<I, W> Triangulation<I, W>
{ {
pub fn new(layout: &Layout) -> Self { pub fn new(layout: &Layout<impl RulesTrait>) -> Self {
let mut this = Self { let mut this = Self {
triangulation: <DelaunayTriangulation<W> as spade::Triangulation>::new(), triangulation: <DelaunayTriangulation<W> as spade::Triangulation>::new(),
vertex_to_handle: Vec::new(), vertex_to_handle: Vec::new(),

View File

@ -10,12 +10,13 @@ use crate::{
primitive::{ primitive::{
FixedBend, FixedDot, GetFirstRail, GetInnerOuter, GetLayout, LooseBend, Primitive, FixedBend, FixedDot, GetFirstRail, GetInnerOuter, GetLayout, LooseBend, Primitive,
}, },
rules::RulesTrait,
Layout, Layout,
}, },
}; };
#[enum_dispatch] #[enum_dispatch]
pub trait GetWraparound: GetLayout + GetNodeIndex { pub trait GetWraparound: GetNodeIndex {
fn wraparound(&self) -> Option<LooseBendIndex>; fn wraparound(&self) -> Option<LooseBendIndex>;
} }
@ -47,14 +48,14 @@ impl From<BendIndex> for WraparoundableIndex {
} }
#[enum_dispatch(GetWraparound, GetLayout, GetNodeIndex)] #[enum_dispatch(GetWraparound, GetLayout, GetNodeIndex)]
pub enum Wraparoundable<'a> { pub enum Wraparoundable<'a, R: RulesTrait> {
FixedDot(FixedDot<'a>), FixedDot(FixedDot<'a, R>),
FixedBend(FixedBend<'a>), FixedBend(FixedBend<'a, R>),
LooseBend(LooseBend<'a>), LooseBend(LooseBend<'a, R>),
} }
impl<'a> Wraparoundable<'a> { impl<'a, R: RulesTrait> Wraparoundable<'a, R> {
pub fn new(index: WraparoundableIndex, layout: &'a Layout) -> Self { pub fn new(index: WraparoundableIndex, layout: &'a Layout<R>) -> Self {
match index { match index {
WraparoundableIndex::FixedDot(dot) => layout.primitive(dot).into(), WraparoundableIndex::FixedDot(dot) => layout.primitive(dot).into(),
WraparoundableIndex::FixedBend(bend) => layout.primitive(bend).into(), WraparoundableIndex::FixedBend(bend) => layout.primitive(bend).into(),
@ -63,19 +64,19 @@ impl<'a> Wraparoundable<'a> {
} }
} }
impl<'a> GetWraparound for FixedDot<'a> { impl<'a, R: RulesTrait> GetWraparound for FixedDot<'a, R> {
fn wraparound(&self) -> Option<LooseBendIndex> { fn wraparound(&self) -> Option<LooseBendIndex> {
self.first_rail() self.first_rail()
} }
} }
impl<'a> GetWraparound for LooseBend<'a> { impl<'a, R: RulesTrait> GetWraparound for LooseBend<'a, R> {
fn wraparound(&self) -> Option<LooseBendIndex> { fn wraparound(&self) -> Option<LooseBendIndex> {
self.outer() self.outer()
} }
} }
impl<'a> GetWraparound for FixedBend<'a> { impl<'a, R: RulesTrait> GetWraparound for FixedBend<'a, R> {
fn wraparound(&self) -> Option<LooseBendIndex> { fn wraparound(&self) -> Option<LooseBendIndex> {
self.first_rail() self.first_rail()
} }