diff --git a/src/draw.rs b/src/draw.rs index a26de36..45157f1 100644 --- a/src/draw.rs +++ b/src/draw.rs @@ -11,9 +11,11 @@ use crate::{ primitive::GetOtherJoint, seg::{LoneLooseSegWeight, SeqLooseSegWeight}, }, - layout::{rules::RulesTrait, Infringement, Layout, LayoutException}, + layout::{ + rules::{Conditions, RulesTrait}, + Infringement, Layout, LayoutException, + }, math::{Circle, NoTangents}, - rules::{Conditions, Rules}, wraparoundable::WraparoundableIndex, }; @@ -31,16 +33,17 @@ pub enum DrawException { pub struct Draw<'a, R: RulesTrait> { layout: &'a mut Layout, - rules: &'a Rules, } impl<'a, R: RulesTrait> Draw<'a, R> { - pub fn new(layout: &'a mut Layout, rules: &'a Rules) -> Self { - Self { layout, rules } + pub fn new(layout: &'a mut Layout) -> Self { + Self { layout } } pub fn start(&mut self, from: LooseDotIndex) -> Head { - self.guide(&Default::default()).segbend_head(from).into() + self.guide(&Default::default(), &Default::default()) + .segbend_head(from) + .into() } #[debug_ensures(ret.is_ok() -> self.layout.node_count() == old(self.layout.node_count() + 1))] @@ -52,7 +55,7 @@ impl<'a, R: RulesTrait> Draw<'a, R> { width: f64, ) -> Result<(), DrawException> { let tangent = self - .guide(&Default::default()) + .guide(&Default::default(), &Default::default()) .head_into_dot_segment(&head, into, width) .map_err(Into::::into)?; let head = self @@ -95,13 +98,13 @@ impl<'a, R: RulesTrait> Draw<'a, R> { head: Head, around: FixedDotIndex, width: f64, - offset: f64, ) -> Result { - let mut tangents = self.guide(&Default::default()).head_around_dot_segments( - &head, - around.into(), - width, - )?; + let mut tangents = self + .guide(&Default::default(), &Default::default()) + .head_around_dot_segments(&head, around.into(), width)?; + let offset = self + .guide(&Default::default(), &Default::default()) + .head_around_dot_offset(&head, around.into(), width); let mut dirs = [true, false]; if tangents.1.euclidean_length() < tangents.0.euclidean_length() { @@ -118,8 +121,8 @@ impl<'a, R: RulesTrait> Draw<'a, R> { tangent.start_point(), tangent.end_point(), dirs[i], - offset, width, + offset, ) { Ok(ok) => return Ok(ok), Err(err) => errs.push(err), @@ -140,13 +143,13 @@ impl<'a, R: RulesTrait> Draw<'a, R> { head: Head, around: BendIndex, width: f64, - offset: f64, ) -> Result { - let mut tangents = self.guide(&Default::default()).head_around_bend_segments( - &head, - around.into(), - width, - )?; + let mut tangents = self + .guide(&Default::default(), &Default::default()) + .head_around_bend_segments(&head, around.into(), width)?; + let offset = self + .guide(&Default::default(), &Default::default()) + .head_around_bend_offset(&head, around.into(), width); let mut dirs = [true, false]; if tangents.1.euclidean_length() < tangents.0.euclidean_length() { @@ -163,8 +166,8 @@ impl<'a, R: RulesTrait> Draw<'a, R> { tangent.start_point(), tangent.end_point(), dirs[i], - offset, width, + offset, ) { Ok(ok) => return Ok(ok), Err(err) => errs.push(err), @@ -191,7 +194,7 @@ impl<'a, R: RulesTrait> Draw<'a, R> { offset: f64, ) -> Result { let head = self.extend_head(head, from)?; - self.segbend(head, around, to, cw, offset, width) + self.segbend(head, around, to, cw, width, offset) } #[debug_ensures(self.layout.node_count() == old(self.layout.node_count()))] @@ -253,10 +256,17 @@ impl<'a, R: RulesTrait> Draw<'a, R> { let band = head.band; self.layout.remove_segbend(&head.segbend, head.face); - Some(self.guide(&Default::default()).head(prev_dot, band)) + Some( + self.guide(&Default::default(), &Default::default()) + .head(prev_dot, band), + ) } - fn guide(&'a self, conditions: &'a Conditions) -> Guide { - Guide::new(self.layout, conditions) + fn guide( + &'a self, + ref_conditions: &'a Conditions, + guide_conditions: &'a Conditions, + ) -> Guide { + Guide::new(self.layout, ref_conditions, guide_conditions) } } diff --git a/src/layout/guide.rs b/src/layout/guide.rs index b57708b..a65b3da 100644 --- a/src/layout/guide.rs +++ b/src/layout/guide.rs @@ -12,10 +12,12 @@ use crate::{ Layout, }, math::{self, Circle, NoTangents}, - rules::{Conditions, Rules}, }; -use super::{rules::RulesTrait, segbend::Segbend}; +use super::{ + rules::{Conditions, RulesTrait}, + segbend::Segbend, +}; #[enum_dispatch] pub trait HeadTrait { @@ -65,12 +67,21 @@ impl HeadTrait for SegbendHead { pub struct Guide<'a, 'b, R: RulesTrait> { layout: &'a Layout, - conditions: &'b Conditions, + ref_conditions: &'b Conditions, + guide_conditions: &'b Conditions, } impl<'a, 'b, R: RulesTrait> Guide<'a, 'b, R> { - pub fn new(layout: &'a Layout, conditions: &'b Conditions) -> Self { - Self { layout, conditions } + pub fn new( + layout: &'a Layout, + ref_conditions: &'b Conditions, + guide_conditions: &'b Conditions, + ) -> Self { + Self { + layout, + ref_conditions, + guide_conditions, + } } pub fn head_into_dot_segment( @@ -118,6 +129,12 @@ impl<'a, 'b, R: RulesTrait> Guide<'a, 'b, R> { 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) + } + pub fn head_around_bend_segments( &self, head: &Head, @@ -147,6 +164,12 @@ impl<'a, 'b, R: RulesTrait> Guide<'a, 'b, R> { 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) + } + pub fn head_cw(&self, head: &Head) -> Option { if let Head::Segbend(head) = head { Some(self.layout.primitive(head.segbend.bend).weight().cw) @@ -156,13 +179,6 @@ impl<'a, 'b, R: RulesTrait> Guide<'a, 'b, R> { } fn head_circle(&self, head: &Head, width: f64) -> Circle { - let _conditions = Conditions { - lower_net: None, - higher_net: None, - layer: None, - zone: None, - }; - match *head { Head::Bare(head) => Circle { pos: head.face().primitive(self.layout).shape().center(), // TODO. @@ -189,7 +205,12 @@ impl<'a, 'b, R: RulesTrait> Guide<'a, 'b, R> { Circle { pos: outer_circle.pos, - r: outer_circle.r + width, + r: outer_circle.r + + width / 2.0 + + self + .layout + .rules() + .clearance(self.ref_conditions, self.guide_conditions), } } @@ -197,7 +218,12 @@ impl<'a, 'b, R: RulesTrait> Guide<'a, 'b, R> { let shape = dot.primitive(self.layout).shape(); Circle { pos: shape.center(), - r: shape.width() / 2.0 + width + 0.0, + r: shape.width() / 2.0 + + width / 2.0 + + self + .layout + .rules() + .clearance(self.ref_conditions, self.guide_conditions), } } diff --git a/src/layout/layout.rs b/src/layout/layout.rs index 5b4d8e9..74cfc8f 100644 --- a/src/layout/layout.rs +++ b/src/layout/layout.rs @@ -413,8 +413,9 @@ impl Layout { let cw = primitive.weight().cw; let ends = primitive.joints(); - let conditions = Default::default(); - let guide = Guide::new(self, &conditions); + let default1 = Default::default(); + let default2 = Default::default(); + let guide = Guide::new(self, &default1, &default2); let from_head = guide.rear_head(ends.1); let to_head = guide.rear_head(ends.0); diff --git a/src/layout/rules.rs b/src/layout/rules.rs index 0f27f97..2ea9b8a 100644 --- a/src/layout/rules.rs +++ b/src/layout/rules.rs @@ -1,16 +1,19 @@ +#[derive(Debug, Default)] pub struct Conditions { layer: Option, region: Option, netclass: Option, } +#[derive(Debug, Default)] pub struct LayerNetclassConditions { region: Option, } pub trait RulesTrait { - fn clearance(conditions1: &Conditions, conditions2: &Conditions) -> f64; + fn clearance(&self, conditions1: &Conditions, conditions2: &Conditions) -> f64; fn clearance_limit( + &self, layer: String, netclass: String, conditions: &LayerNetclassConditions, diff --git a/src/main.rs b/src/main.rs index 69f3f1a..9bc35d9 100644 --- a/src/main.rs +++ b/src/main.rs @@ -16,7 +16,6 @@ mod layout; mod math; mod mesh; mod router; -mod rules; mod tracer; mod triangulation; mod wraparoundable; @@ -61,14 +60,15 @@ use crate::router::Router; struct ConstantClearance {} impl RulesTrait for ConstantClearance { - fn clearance(conditions1: &Conditions, conditions2: &Conditions) -> f64 { - 3.0 + fn clearance(&self, _conditions1: &Conditions, _conditions2: &Conditions) -> f64 { + 10.0 } fn clearance_limit( - layer: String, - netclass: String, - conditions: &LayerNetclassConditions, + &self, + _layer: String, + _netclass: String, + _conditions: &LayerNetclassConditions, ) -> f64 { 3.0 } @@ -507,6 +507,7 @@ fn main() -> Result<(), anyhow::Error> { let _ = router.route_band( dot_start, dot_end, + 3.0, //&mut EmptyRouterObserver, &mut DebugRouterObserver::new(&mut event_pump, &window, &mut renderer, &font_context), )?; @@ -539,6 +540,7 @@ fn main() -> Result<(), anyhow::Error> { let band2 = router.route_band( dot_start2, dot_end2, + 3.0, //&mut EmptyRouterObserver, &mut DebugRouterObserver::new(&mut event_pump, &window, &mut renderer, &font_context), )?; @@ -560,6 +562,7 @@ fn main() -> Result<(), anyhow::Error> { let band3 = router.route_band( dot_start3, dot_end3, + 3.0, //&mut EmptyRouterObserver, &mut DebugRouterObserver::new(&mut event_pump, &window, &mut renderer, &font_context), )?; @@ -667,6 +670,7 @@ fn render_times( .reroute_band( band, point! {x: state.x() as f64, y: state.y() as f64}, + 3.0, &mut DebugRouterObserver::new( event_pump, window, diff --git a/src/router.rs b/src/router.rs index 42d901e..20d0919 100644 --- a/src/router.rs +++ b/src/router.rs @@ -19,7 +19,6 @@ use crate::layout::{ use crate::mesh::{Mesh, MeshEdgeReference, VertexIndex}; -use crate::rules::Rules; use crate::tracer::{Trace, Tracer}; #[derive(Error, Debug, Clone, Copy)] @@ -55,7 +54,6 @@ pub trait RouterObserverTrait { pub struct Router { pub layout: Layout, - rules: Rules, } struct RouterAstarStrategy<'a, RO: RouterObserverTrait, R: RulesTrait> { @@ -132,7 +130,6 @@ impl Router { pub fn new(rules: R) -> Self { Router { layout: Layout::new(rules), - rules: Rules::new(), } } @@ -140,6 +137,7 @@ impl Router { &mut self, from: FixedDotIndex, to: FixedDotIndex, + width: f64, observer: &mut impl RouterObserverTrait, ) -> Result { // XXX: Should we actually store the mesh? May be useful for debugging, but doesn't look @@ -153,7 +151,7 @@ impl Router { })?; let mut tracer = self.tracer(&mesh); - let trace = tracer.start(from, 3.0); + let trace = tracer.start(from, width); let band = trace.head.band(); let (_cost, _path) = astar( @@ -174,16 +172,17 @@ impl Router { &mut self, band: BandIndex, to: Point, + width: f64, observer: &mut impl RouterObserverTrait, ) -> Result { let from_dot = self.layout.band(band).from(); let to_dot = self.layout.band(band).to().unwrap(); self.layout.remove_band(band); self.layout.move_dot(to_dot.into(), to).unwrap(); // TODO: Remove `.unwrap()`. - self.route_band(from_dot, to_dot, observer) + self.route_band(from_dot, to_dot, width, observer) } pub fn tracer<'a>(&'a mut self, mesh: &'a Mesh) -> Tracer { - Tracer::new(&mut self.layout, &self.rules, mesh) + Tracer::new(&mut self.layout, mesh) } } diff --git a/src/rules.rs b/src/rules.rs deleted file mode 100644 index 8cf2d50..0000000 --- a/src/rules.rs +++ /dev/null @@ -1,89 +0,0 @@ -use std::collections::HashMap; - -#[derive(Debug, Default, Clone, Copy, Hash, PartialEq, Eq)] -pub struct Conditions { - pub lower_net: Option, - pub higher_net: Option, - pub layer: Option, - pub zone: Option, -} - -impl Conditions { - pub fn priority(&self) -> i64 { - let mut priority = 0; - priority += (self.lower_net.is_some() as i64) * 1; - priority += (self.higher_net.is_some() as i64) * 2; - priority += (self.layer.is_some() as i64) * 4; - priority += (self.zone.is_some() as i64) * 8; - priority - } -} - -#[derive(Debug, Default, Clone)] -pub struct Rules { - rulesets: [Option>; 16], -} - -impl Rules { - pub fn new() -> Self { - let mut this = Self { - rulesets: Default::default(), - }; - this.rulesets[0] = Some(HashMap::from([( - Conditions { - lower_net: None, - higher_net: None, - layer: None, - zone: None, - }, - Ruleset::new(), - )])); - this - } - - pub fn ruleset(&self, conditions: &Conditions) -> &Ruleset { - let priority = conditions.priority(); - - for index in (1..(priority + 1)).rev() { - if let Some(ruleset_hashmap) = &self.rulesets[index as usize] { - if let Some(ruleset) = ruleset_hashmap.get(&conditions) { - return ruleset; - } - } - } - - &self.rulesets[0].as_ref().unwrap()[&conditions] - } -} - -#[derive(Debug, Default, Clone)] -pub struct Ruleset { - pub length: Rule, - pub clearance: Rule, -} - -impl Ruleset { - pub fn new() -> Self { - Self { - length: Rule::new(), - clearance: Rule::new(), - } - } -} - -#[derive(Debug, Default, Clone)] -pub struct Rule { - pub min: f64, - pub opt: Option, - pub max: f64, -} - -impl Rule { - pub fn new() -> Self { - Self { - min: 0.0, - opt: None, - max: f64::INFINITY, - } - } -} diff --git a/src/tracer.rs b/src/tracer.rs index e0ba5d4..72d9d03 100644 --- a/src/tracer.rs +++ b/src/tracer.rs @@ -10,7 +10,6 @@ use crate::{ Layout, }, mesh::{Mesh, VertexIndex}, - rules::Rules, }; #[derive(Debug)] @@ -21,17 +20,12 @@ pub struct Trace { pub struct Tracer<'a, R: RulesTrait> { pub layout: &'a mut Layout, - pub rules: &'a Rules, pub mesh: &'a Mesh, } impl<'a, R: RulesTrait> Tracer<'a, R> { - pub fn new(layout: &'a mut Layout, rules: &'a Rules, mesh: &'a Mesh) -> Self { - Tracer { - layout, - rules, - mesh, - } + pub fn new(layout: &'a mut Layout, mesh: &'a Mesh) -> Self { + Tracer { layout, mesh } } pub fn start(&mut self, from: FixedDotIndex, width: f64) -> Trace { @@ -129,9 +123,7 @@ impl<'a, R: RulesTrait> Tracer<'a, R> { around: FixedDotIndex, width: f64, ) -> Result { - let head = self - .draw() - .segbend_around_dot(head, around.into(), width, 3.0)?; + let head = self.draw().segbend_around_dot(head, around.into(), width)?; Ok(head) } @@ -143,7 +135,7 @@ impl<'a, R: RulesTrait> Tracer<'a, R> { ) -> Result { let head = self .draw() - .segbend_around_bend(head, around.into(), width, 3.0)?; + .segbend_around_bend(head, around.into(), width)?; Ok(head) } @@ -160,6 +152,6 @@ impl<'a, R: RulesTrait> Tracer<'a, R> { } fn draw(&mut self) -> Draw { - Draw::new(&mut self.layout, &self.rules) + Draw::new(&mut self.layout) } }