diff --git a/src/draw.rs b/src/draw.rs index 45157f1..047f1f7 100644 --- a/src/draw.rs +++ b/src/draw.rs @@ -11,10 +11,7 @@ use crate::{ primitive::GetOtherJoint, seg::{LoneLooseSegWeight, SeqLooseSegWeight}, }, - layout::{ - rules::{Conditions, RulesTrait}, - Infringement, Layout, LayoutException, - }, + layout::{rules::RulesTrait, Infringement, Layout, LayoutException}, math::{Circle, NoTangents}, wraparoundable::WraparoundableIndex, }; @@ -41,9 +38,7 @@ impl<'a, R: RulesTrait> Draw<'a, R> { } pub fn start(&mut self, from: LooseDotIndex) -> Head { - self.guide(&Default::default(), &Default::default()) - .segbend_head(from) - .into() + self.guide().segbend_head(from).into() } #[debug_ensures(ret.is_ok() -> self.layout.node_count() == old(self.layout.node_count() + 1))] @@ -55,7 +50,7 @@ impl<'a, R: RulesTrait> Draw<'a, R> { width: f64, ) -> Result<(), DrawException> { let tangent = self - .guide(&Default::default(), &Default::default()) + .guide() .head_into_dot_segment(&head, into, width) .map_err(Into::::into)?; let head = self @@ -100,10 +95,10 @@ impl<'a, R: RulesTrait> Draw<'a, R> { width: f64, ) -> Result { let mut tangents = self - .guide(&Default::default(), &Default::default()) + .guide() .head_around_dot_segments(&head, around.into(), width)?; let offset = self - .guide(&Default::default(), &Default::default()) + .guide() .head_around_dot_offset(&head, around.into(), width); let mut dirs = [true, false]; @@ -145,10 +140,10 @@ impl<'a, R: RulesTrait> Draw<'a, R> { width: f64, ) -> Result { let mut tangents = self - .guide(&Default::default(), &Default::default()) + .guide() .head_around_bend_segments(&head, around.into(), width)?; let offset = self - .guide(&Default::default(), &Default::default()) + .guide() .head_around_bend_offset(&head, around.into(), width); let mut dirs = [true, false]; @@ -256,17 +251,10 @@ impl<'a, R: RulesTrait> Draw<'a, R> { let band = head.band; self.layout.remove_segbend(&head.segbend, head.face); - Some( - self.guide(&Default::default(), &Default::default()) - .head(prev_dot, band), - ) + Some(self.guide().head(prev_dot, band)) } - fn guide( - &'a self, - ref_conditions: &'a Conditions, - guide_conditions: &'a Conditions, - ) -> Guide { - Guide::new(self.layout, ref_conditions, guide_conditions) + fn guide(&self) -> Guide { + Guide::new(self.layout) } } diff --git a/src/layout/guide.rs b/src/layout/guide.rs index a65b3da..a4e4ce4 100644 --- a/src/layout/guide.rs +++ b/src/layout/guide.rs @@ -9,12 +9,14 @@ use crate::{ geometry::shape::{Shape, ShapeTrait}, graph::{GetBandIndex, MakePrimitive}, primitive::{GetCore, GetInnerOuter, GetOtherJoint, GetWeight, MakeShape}, + rules::GetConditions, Layout, }, math::{self, Circle, NoTangents}, }; use super::{ + graph::GeometryIndex, rules::{Conditions, RulesTrait}, segbend::Segbend, }; @@ -65,23 +67,13 @@ impl HeadTrait for SegbendHead { } } -pub struct Guide<'a, 'b, R: RulesTrait> { +pub struct Guide<'a, R: RulesTrait> { layout: &'a Layout, - ref_conditions: &'b Conditions, - guide_conditions: &'b Conditions, } -impl<'a, 'b, R: RulesTrait> Guide<'a, 'b, R> { - pub fn new( - layout: &'a Layout, - ref_conditions: &'b Conditions, - guide_conditions: &'b Conditions, - ) -> Self { - Self { - layout, - ref_conditions, - guide_conditions, - } +impl<'a, R: RulesTrait> Guide<'a, R> { + pub fn new(layout: &'a Layout) -> Self { + Self { layout } } pub fn head_into_dot_segment( @@ -107,7 +99,7 @@ impl<'a, 'b, R: RulesTrait> Guide<'a, 'b, R> { width: f64, ) -> Result<(Line, Line), NoTangents> { let from_circle = self.head_circle(head, width); - let to_circle = self.dot_circle(around, width); + let to_circle = self.dot_circle(around, width, &self.conditions(head.face().into())); let from_cw = self.head_cw(head); let tangents: Vec = @@ -123,16 +115,17 @@ impl<'a, 'b, R: RulesTrait> Guide<'a, 'b, R> { width: f64, ) -> Result { let from_circle = self.head_circle(head, width); - let to_circle = self.dot_circle(around, width); + let to_circle = self.dot_circle(around, width, &self.conditions(head.face().into())); let from_cw = self.head_cw(head); math::tangent_segment(from_circle, from_cw, to_circle, Some(cw)) } pub fn head_around_dot_offset(&self, head: &Head, around: DotIndex, width: f64) -> f64 { - self.layout - .rules() - .clearance(self.ref_conditions, self.guide_conditions) + self.layout.rules().clearance( + &self.conditions(around.into()), + &self.conditions(head.face().into()), + ) } pub fn head_around_bend_segments( @@ -142,7 +135,7 @@ impl<'a, 'b, R: RulesTrait> Guide<'a, 'b, R> { width: f64, ) -> Result<(Line, Line), NoTangents> { let from_circle = self.head_circle(head, width); - let to_circle = self.bend_circle(around, width); + let to_circle = self.bend_circle(around, width, &self.conditions(head.face().into())); let from_cw = self.head_cw(head); let tangents: Vec = @@ -158,16 +151,17 @@ impl<'a, 'b, R: RulesTrait> Guide<'a, 'b, R> { width: f64, ) -> Result { let from_circle = self.head_circle(head, width); - let to_circle = self.bend_circle(around, width); + let to_circle = self.bend_circle(around, width, &self.conditions(head.face().into())); let from_cw = self.head_cw(head); math::tangent_segment(from_circle, from_cw, to_circle, Some(cw)) } pub fn head_around_bend_offset(&self, head: &Head, around: BendIndex, width: f64) -> f64 { - self.layout - .rules() - .clearance(self.ref_conditions, self.guide_conditions) + self.layout.rules().clearance( + &self.conditions(head.face().into()), + &self.conditions(around.into()), + ) } pub fn head_cw(&self, head: &Head) -> Option { @@ -186,18 +180,19 @@ impl<'a, 'b, R: RulesTrait> Guide<'a, 'b, R> { }, Head::Segbend(head) => { if let Some(inner) = self.layout.primitive(head.segbend.bend).inner() { - self.bend_circle(inner.into(), width) + self.bend_circle(inner.into(), width, &self.conditions(head.face().into())) } else { self.dot_circle( self.layout.primitive(head.segbend.bend).core().into(), width, + &self.conditions(head.face().into()), ) } } } } - fn bend_circle(&self, bend: BendIndex, width: f64) -> Circle { + fn bend_circle(&self, bend: BendIndex, width: f64, guide_conditions: &Conditions) -> Circle { let outer_circle = match bend.primitive(self.layout).shape() { Shape::Bend(shape) => shape.outer_circle(), _ => unreachable!(), @@ -210,11 +205,11 @@ impl<'a, 'b, R: RulesTrait> Guide<'a, 'b, R> { + self .layout .rules() - .clearance(self.ref_conditions, self.guide_conditions), + .clearance(&self.conditions(bend.into()), guide_conditions), } } - fn dot_circle(&self, dot: DotIndex, width: f64) -> Circle { + fn dot_circle(&self, dot: DotIndex, width: f64, guide_conditions: &Conditions) -> Circle { let shape = dot.primitive(self.layout).shape(); Circle { pos: shape.center(), @@ -223,7 +218,7 @@ impl<'a, 'b, R: RulesTrait> Guide<'a, 'b, R> { + self .layout .rules() - .clearance(self.ref_conditions, self.guide_conditions), + .clearance(&self.conditions(dot.into()), guide_conditions), } } @@ -254,4 +249,8 @@ impl<'a, 'b, R: RulesTrait> Guide<'a, 'b, R> { .primitive(head.segbend.seg) .other_joint(head.segbend.dot.into()) } + + fn conditions(&self, node: GeometryIndex) -> Conditions { + node.primitive(self.layout).conditions() + } } diff --git a/src/layout/layout.rs b/src/layout/layout.rs index 74cfc8f..c253602 100644 --- a/src/layout/layout.rs +++ b/src/layout/layout.rs @@ -23,6 +23,7 @@ use crate::layout::geometry::{ BendWeightTrait, DotWeightTrait, Geometry, GeometryLabel, GetPos, SegWeightTrait, }; use crate::layout::guide::Guide; +use crate::layout::rules::{Conditions, GetConditions}; use crate::layout::{ bend::{FixedBendIndex, LooseBendIndex, LooseBendWeight}, dot::{DotIndex, FixedDotIndex, FixedDotWeight, LooseDotIndex, LooseDotWeight}, @@ -409,18 +410,22 @@ impl Layout { let mut maybe_rail = Some(around); while let Some(rail) = maybe_rail { - let primitive = self.primitive(rail); - let cw = primitive.weight().cw; - let ends = primitive.joints(); + let rail_primitive = self.primitive(rail); + let cw = rail_primitive.weight().cw; + let ends = rail_primitive.joints(); - let default1 = Default::default(); - let default2 = Default::default(); - let guide = Guide::new(self, &default1, &default2); + let inner_conditions = Conditions::from(if let Some(inner) = rail_primitive.inner() { + self.primitive(inner).conditions() + } else { + self.primitive(rail_primitive.core()).conditions() + }); + let rail_conditions = Conditions::from(rail_primitive.conditions()); + let guide = Guide::new(self); let from_head = guide.rear_head(ends.1); let to_head = guide.rear_head(ends.0); - if let Some(inner) = primitive.inner() { + if let Some(inner) = rail_primitive.inner() { let from = guide .head_around_bend_segment(&from_head.into(), inner.into(), !cw, 6.0)? .end_point(); @@ -434,7 +439,7 @@ impl Layout { )?; self.move_dot_infringably(ends.1.into(), to, &self.inner_bow_and_outer_bows(rail))?; } else { - let core = primitive.core(); + let core = rail_primitive.core(); let from = guide .head_around_dot_segment(&from_head.into(), core.into(), !cw, 6.0)? .end_point(); diff --git a/src/layout/primitive.rs b/src/layout/primitive.rs index 347a70a..45ab70d 100644 --- a/src/layout/primitive.rs +++ b/src/layout/primitive.rs @@ -20,7 +20,7 @@ use crate::layout::{ Layout, }; -use super::rules::RulesTrait; +use super::rules::{Conditions, GetConditions, RulesTrait}; #[enum_dispatch] pub trait GetLayout<'a, R: RulesTrait> { @@ -166,7 +166,7 @@ macro_rules! impl_loose_primitive { }; } -#[enum_dispatch(GetNet, GetWidth, GetLayout, MakeShape, GetLimbs)] +#[enum_dispatch(GetNet, GetWidth, GetLayout, MakeShape, GetLimbs, GetConditions)] pub enum Primitive<'a, R: RulesTrait> { FixedDot(FixedDot<'a, R>), LooseDot(LooseDot<'a, R>), @@ -229,6 +229,16 @@ where } } +impl<'a, W, R: RulesTrait> GetConditions for GenericPrimitive<'a, W, R> { + fn conditions(&self) -> Conditions { + Conditions { + netclass: Some("NETCLASS_A".to_string()), + region: Some("A".to_string()), + layer: Some("F.Cu".to_string()), + } + } +} + pub type FixedDot<'a, R> = GenericPrimitive<'a, FixedDotWeight, R>; impl_fixed_primitive!(FixedDot, FixedDotWeight); diff --git a/src/layout/rules.rs b/src/layout/rules.rs index 2ea9b8a..fab75f5 100644 --- a/src/layout/rules.rs +++ b/src/layout/rules.rs @@ -1,21 +1,25 @@ -#[derive(Debug, Default)] -pub struct Conditions { - layer: Option, - region: Option, - netclass: Option, +use enum_dispatch::enum_dispatch; + +use crate::layout::primitive::Primitive; + +#[enum_dispatch] +pub trait GetConditions { + fn conditions(&self) -> Conditions; } #[derive(Debug, Default)] -pub struct LayerNetclassConditions { - region: Option, +pub struct Conditions { + pub netclass: Option, + pub region: Option, + pub layer: Option, } pub trait RulesTrait { fn clearance(&self, conditions1: &Conditions, conditions2: &Conditions) -> f64; - fn clearance_limit( + /*fn clearance_limit( &self, layer: String, netclass: String, - conditions: &LayerNetclassConditions, - ) -> f64; + conditions: &PrimitiveConditions, + ) -> f64;*/ } diff --git a/src/main.rs b/src/main.rs index 9bc35d9..c8c9801 100644 --- a/src/main.rs +++ b/src/main.rs @@ -27,7 +27,7 @@ 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::rules::{Conditions, RulesTrait}; use layout::seg::FixedSegWeight; use layout::{Infringement, Layout, LayoutException}; use mesh::{Mesh, MeshEdgeReference, VertexIndex}; @@ -51,27 +51,39 @@ use pathfinder_renderer::gpu::renderer::Renderer; use pathfinder_renderer::options::BuildOptions; use pathfinder_resources::embedded::EmbeddedResourceLoader; +use std::collections::HashMap; use std::time::Duration; use tracer::{Trace, Tracer}; use crate::math::Circle; use crate::router::Router; -struct ConstantClearance {} +struct SimpleRules { + netclass_clearances: HashMap<(String, String), f64>, +} -impl RulesTrait for ConstantClearance { - fn clearance(&self, _conditions1: &Conditions, _conditions2: &Conditions) -> f64 { - 10.0 +impl RulesTrait for SimpleRules { + fn clearance(&self, conditions1: &Conditions, conditions2: &Conditions) -> f64 { + if let (Some(ref netclass1), Some(ref netclass2)) = + (conditions1.netclass.clone(), conditions2.netclass.clone()) + { + *self + .netclass_clearances + .get(&(netclass1.to_string(), netclass2.to_string())) + .unwrap_or(&10.0) + } else { + 5.0 + } } - fn clearance_limit( + /*fn clearance_limit( &self, _layer: String, _netclass: String, - _conditions: &LayerNetclassConditions, + _conditions: &PrimitiveConditions, ) -> f64 { 3.0 - } + }*/ } // Clunky enum to work around borrow checker. @@ -235,7 +247,22 @@ fn main() -> Result<(), anyhow::Error> { let mut event_pump = sdl_context.event_pump().unwrap(); let _i = 0; - let mut router = Router::new(ConstantClearance {}); + let mut router = Router::new(SimpleRules { + netclass_clearances: HashMap::from([ + ( + (String::from("NETCLASS_A"), String::from("NETCLASS_A")), + 5.0, + ), + ( + (String::from("NETCLASS_A"), String::from("NETCLASS_B")), + 10.0, + ), + ( + (String::from("NETCLASS_B"), String::from("NETCLASS_A")), + 10.0, + ), + ]), + }); let component1_1 = router.layout.add_component(1); let component1_2 = router.layout.add_component(1);