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

View File

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

View File

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

View File

@ -14,6 +14,7 @@ use super::{
bend::{FixedBendIndex, FixedBendWeight, LooseBendIndex, LooseBendWeight},
dot::{FixedDotIndex, FixedDotWeight, LooseDotIndex, LooseDotWeight},
primitive::Primitive,
rules::RulesTrait,
seg::{
FixedSegIndex, FixedSegWeight, LoneLooseSegIndex, LoneLooseSegWeight, SeqLooseSegIndex,
SeqLooseSegWeight,
@ -40,7 +41,7 @@ pub trait GetBandIndex {
#[enum_dispatch]
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 {
@ -54,7 +55,7 @@ macro_rules! impl_weight {
pub type $index_struct = GenericIndex<$weight_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))
}
}

View File

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

View File

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

View File

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

View File

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

View File

@ -20,19 +20,11 @@ use crate::layout::{
Layout,
};
#[enum_dispatch]
pub trait GetLayout {
fn layout(&self) -> &Layout;
}
use super::rules::RulesTrait;
#[enum_dispatch]
pub trait GetConnectable: GetNet + GetLayout {
fn connectable(&self, node: GeometryIndex) -> bool {
let this = self.net();
let other = node.primitive(self.layout()).net();
(this == other) || this == -1 || other == -1
}
pub trait GetLayout<'a, R: RulesTrait> {
fn layout(&self) -> &Layout<R>;
}
#[enum_dispatch]
@ -82,7 +74,7 @@ pub trait GetJoints<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> {
self.layout()
.geometry()
@ -95,7 +87,7 @@ pub trait GetBendIndex {
fn bend_index(&self) -> BendIndex;
}
pub trait GetCore: GetLayout + GetBendIndex {
pub trait GetCore<'a, R: RulesTrait>: GetLayout<'a, R> + GetBendIndex {
fn core(&self) -> FixedDotIndex {
FixedDotIndex::new(
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> {
self.layout()
.geometry()
@ -124,7 +116,7 @@ pub trait GetInnerOuter: GetLayout + GetBendIndex {
macro_rules! impl_primitive {
($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 {
if let GeometryWeight::$primitive_struct(weight) = self.tagged_weight() {
weight
@ -140,13 +132,13 @@ macro_rules! impl_fixed_primitive {
($primitive_struct:ident, $weight_struct:ident) => {
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 {
self.weight().component()
}
}
impl<'a> GetNet for $primitive_struct<'a> {
impl<'a, R: RulesTrait> GetNet for $primitive_struct<'a, R> {
fn net(&self) -> i64 {
self.layout()
.connectivity()
@ -162,7 +154,7 @@ macro_rules! impl_loose_primitive {
($primitive_struct:ident, $weight_struct:ident) => {
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 {
self.layout()
.connectivity()
@ -174,25 +166,25 @@ macro_rules! impl_loose_primitive {
};
}
#[enum_dispatch(GetNet, GetWidth, GetLayout, GetConnectable, MakeShape, GetLimbs)]
pub enum Primitive<'a> {
FixedDot(FixedDot<'a>),
LooseDot(LooseDot<'a>),
FixedSeg(FixedSeg<'a>),
LoneLooseSeg(LoneLooseSeg<'a>),
SeqLooseSeg(SeqLooseSeg<'a>),
FixedBend(FixedBend<'a>),
LooseBend(LooseBend<'a>),
#[enum_dispatch(GetNet, GetWidth, GetLayout, MakeShape, GetLimbs)]
pub enum Primitive<'a, R: RulesTrait> {
FixedDot(FixedDot<'a, R>),
LooseDot(LooseDot<'a, R>),
FixedSeg(FixedSeg<'a, R>),
LoneLooseSeg(LoneLooseSeg<'a, R>),
SeqLooseSeg(SeqLooseSeg<'a, R>),
FixedBend(FixedBend<'a, R>),
LooseBend(LooseBend<'a, R>),
}
#[derive(Debug)]
pub struct GenericPrimitive<'a, W> {
pub struct GenericPrimitive<'a, W, R: RulesTrait> {
pub index: GenericIndex<W>,
layout: &'a Layout,
layout: &'a Layout<R>,
}
impl<'a, W> GenericPrimitive<'a, W> {
pub fn new(index: GenericIndex<W>, layout: &'a Layout) -> Self {
impl<'a, W, R: RulesTrait> GenericPrimitive<'a, W, R> {
pub fn new(index: GenericIndex<W>, layout: &'a Layout<R>) -> Self {
Self { index, layout }
}
@ -205,44 +197,42 @@ impl<'a, W> GenericPrimitive<'a, W> {
.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)
}
}
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> {
vec![self.tagged_weight().retag(self.index.node_index())]
}
}
impl<'a, W> GetLayout for GenericPrimitive<'a, W> {
fn layout(&self) -> &Layout {
impl<'a, W, R: RulesTrait> GetLayout<'a, R> for GenericPrimitive<'a, W, R> {
fn layout(&self) -> &Layout<R> {
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> {
self.index.node_index()
}
}
impl<'a, W> GetConnectable for GenericPrimitive<'a, W> where GenericPrimitive<'a, W>: GetNet {}
impl<'a, W: GetWidth> GetWidth for GenericPrimitive<'a, W>
impl<'a, W: GetWidth, R: RulesTrait> GetWidth for GenericPrimitive<'a, W, R>
where
GenericPrimitive<'a, W>: GetWeight<W>,
GenericPrimitive<'a, W, R>: GetWeight<W>,
{
fn width(&self) -> f64 {
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<'a> FixedDot<'a> {
impl<'a, R: RulesTrait> FixedDot<'a, R> {
pub fn first_loose(&self, _band: BandIndex) -> Option<LooseIndex> {
self.layout
.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 {
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> {
self.layout
.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<'a> LooseDot<'a> {
impl<'a, R: RulesTrait> LooseDot<'a, R> {
pub fn seg(&self) -> Option<SeqLooseSegIndex> {
self.layout
.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 {
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> {
if let Some(seg) = self.seg() {
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<'a> MakeShape for FixedSeg<'a> {
impl<'a, R: RulesTrait> MakeShape for FixedSeg<'a, R> {
fn shape(&self) -> Shape {
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) {
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<'a> MakeShape for LoneLooseSeg<'a> {
impl<'a, R: RulesTrait> MakeShape for LoneLooseSeg<'a, R> {
fn shape(&self) -> Shape {
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) {
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<'a> MakeShape for SeqLooseSeg<'a> {
impl<'a, R: RulesTrait> MakeShape for SeqLooseSeg<'a, R> {
fn shape(&self) -> Shape {
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) {
let joints = self.layout.geometry().seg_joints(self.index.into());
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<'a> GetBendIndex for FixedBend<'a> {
impl<'a, R: RulesTrait> GetBendIndex for FixedBend<'a, R> {
fn bend_index(&self) -> BendIndex {
self.index.into()
}
}
impl<'a> MakeShape for FixedBend<'a> {
impl<'a, R: RulesTrait> MakeShape for FixedBend<'a, R> {
fn shape(&self) -> Shape {
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) {
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> GetFirstRail for FixedBend<'a> {}
impl<'a> GetCore for FixedBend<'a> {} // TODO: Fixed bends don't have cores actually.
//impl<'a> GetInnerOuter for FixedBend<'a> {}
impl<'a, R: RulesTrait> GetOtherJoint<FixedDotIndex, FixedDotIndex> for FixedBend<'a, R> {}
impl<'a, R: RulesTrait> GetFirstRail<'a, R> for FixedBend<'a, R> {}
impl<'a, R: RulesTrait> GetCore<'a, R> for FixedBend<'a, R> {} // TODO: Fixed bends don't have cores actually.
//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<'a> GetBendIndex for LooseBend<'a> {
impl<'a, R: RulesTrait> GetBendIndex for LooseBend<'a, R> {
fn bend_index(&self) -> BendIndex {
self.index.into()
}
}
impl<'a> From<LooseBend<'a>> for BendIndex {
fn from(bend: LooseBend<'a>) -> BendIndex {
impl<'a, R: RulesTrait> From<LooseBend<'a, R>> for BendIndex {
fn from(bend: LooseBend<'a, R>) -> BendIndex {
bend.index.into()
}
}
impl<'a> MakeShape for LooseBend<'a> {
impl<'a, R: RulesTrait> MakeShape for LooseBend<'a, R> {
fn shape(&self) -> Shape {
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 {
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) {
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> GetCore for LooseBend<'a> {}
impl<'a> GetInnerOuter for LooseBend<'a> {}
impl<'a, R: RulesTrait> GetOtherJoint<LooseDotIndex, LooseDotIndex> for LooseBend<'a, R> {}
impl<'a, R: RulesTrait> GetCore<'a, R> for LooseBend<'a, R> {}
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,
},
primitive::{GenericPrimitive, Primitive},
rules::RulesTrait,
Layout,
},
};

View File

@ -7,6 +7,8 @@ use crate::layout::{
Layout,
};
use super::rules::RulesTrait;
#[derive(Debug, Clone, Copy)]
pub struct Segbend {
pub seg: SeqLooseSegIndex,
@ -15,7 +17,7 @@ pub struct 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 dot = LooseBend::new(bend, layout).other_joint(dot);
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::graph::{GeometryIndex, MakePrimitive};
use layout::primitive::MakeShape;
use layout::rules::{Conditions, LayerNetclassConditions, RulesTrait};
use layout::seg::FixedSegWeight;
use layout::{Infringement, Layout, LayoutException};
use mesh::{Mesh, MeshEdgeReference, VertexIndex};
use petgraph::visit::{EdgeRef, IntoEdgeReferences};
use router::RouterObserver;
use router::RouterObserverTrait;
use sdl2::event::Event;
use sdl2::keyboard::Keycode;
@ -57,26 +58,42 @@ use tracer::{Trace, Tracer};
use crate::math::Circle;
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.
enum RouterOrLayout<'a> {
Router(&'a mut Router),
Layout(&'a Layout),
enum RouterOrLayout<'a, R: RulesTrait> {
Router(&'a mut Router<R>),
Layout(&'a Layout<R>),
}
struct EmptyRouterObserver;
impl RouterObserver for EmptyRouterObserver {
fn on_rework(&mut self, _tracer: &Tracer, _trace: &Trace) {}
fn before_probe(&mut self, _tracer: &Tracer, _trace: &Trace, _edge: MeshEdgeReference) {}
impl<R: RulesTrait> RouterObserverTrait<R> for EmptyRouterObserver {
fn on_rework(&mut self, _tracer: &Tracer<R>, _trace: &Trace) {}
fn before_probe(&mut self, _tracer: &Tracer<R>, _trace: &Trace, _edge: MeshEdgeReference) {}
fn on_probe(
&mut self,
_tracer: &Tracer,
_tracer: &Tracer<R>,
_trace: &Trace,
_edge: MeshEdgeReference,
_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> {
@ -102,8 +119,8 @@ impl<'a> DebugRouterObserver<'a> {
}
}
impl<'a> RouterObserver for DebugRouterObserver<'a> {
fn on_rework(&mut self, tracer: &Tracer, trace: &Trace) {
impl<'a, R: RulesTrait> RouterObserverTrait<R> for DebugRouterObserver<'a> {
fn on_rework(&mut self, tracer: &Tracer<R>, trace: &Trace) {
render_times(
self.event_pump,
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();
path.push(edge.target());
render_times(
@ -139,7 +156,7 @@ impl<'a> RouterObserver for DebugRouterObserver<'a> {
fn on_probe(
&mut self,
tracer: &Tracer,
tracer: &Tracer<R>,
trace: &Trace,
_edge: MeshEdgeReference,
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> {
@ -218,7 +235,7 @@ fn main() -> Result<(), anyhow::Error> {
let mut event_pump = sdl_context.event_pump().unwrap();
let _i = 0;
let mut router = Router::new();
let mut router = Router::new(ConstantClearance {});
let component1_1 = router.layout.add_component(1);
let component1_2 = router.layout.add_component(1);
@ -321,7 +338,7 @@ fn main() -> Result<(), anyhow::Error> {
dot2_1,
FixedSegWeight {
component: component2,
width: 16.0,
width: 3.0,
},
);
@ -341,7 +358,7 @@ fn main() -> Result<(), anyhow::Error> {
dot2_2,
FixedSegWeight {
component: component2,
width: 16.0,
width: 3.0,
},
);
@ -372,7 +389,7 @@ fn main() -> Result<(), anyhow::Error> {
dot4,
FixedSegWeight {
component: component2,
width: 16.0,
width: 3.0,
},
);
@ -392,7 +409,7 @@ fn main() -> Result<(), anyhow::Error> {
dot5,
FixedSegWeight {
component: component2,
width: 16.0,
width: 3.0,
},
);
@ -412,7 +429,7 @@ fn main() -> Result<(), anyhow::Error> {
dot1_2,
FixedSegWeight {
component: component2,
width: 16.0,
width: 3.0,
},
);
@ -421,7 +438,7 @@ fn main() -> Result<(), anyhow::Error> {
dot2_2,
FixedSegWeight {
component: component2,
width: 16.0,
width: 3.0,
},
);
@ -441,7 +458,7 @@ fn main() -> Result<(), anyhow::Error> {
dot6,
FixedSegWeight {
component: component2,
width: 16.0,
width: 3.0,
},
);
@ -461,7 +478,7 @@ fn main() -> Result<(), anyhow::Error> {
dot7,
FixedSegWeight {
net: 20,
width: 16.0,
width: 3.0,
},
);*/
@ -613,7 +630,7 @@ fn render_times(
window: &Window,
renderer: &mut Renderer<GLDevice>,
font_context: &CanvasFontContext,
mut router_or_layout: RouterOrLayout,
mut router_or_layout: RouterOrLayout<impl RulesTrait>,
maybe_band: Option<BandIndex>,
mut maybe_mesh: Option<Mesh>,
path: &[VertexIndex],

View File

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

View File

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

View File

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

View File

@ -4,7 +4,10 @@ use geo::{point, Point};
use petgraph::visit::{self, NodeIndexable};
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> {
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>>
Triangulation<I, W>
{
pub fn new(layout: &Layout) -> Self {
pub fn new(layout: &Layout<impl RulesTrait>) -> Self {
let mut this = Self {
triangulation: <DelaunayTriangulation<W> as spade::Triangulation>::new(),
vertex_to_handle: Vec::new(),

View File

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