draw,guide: construct guides from rules

This commit is contained in:
Mikolaj Wielgus 2024-02-03 23:19:47 +00:00
parent d2ff1826a0
commit e5ddf47eb3
8 changed files with 102 additions and 156 deletions

View File

@ -11,9 +11,11 @@ use crate::{
primitive::GetOtherJoint, primitive::GetOtherJoint,
seg::{LoneLooseSegWeight, SeqLooseSegWeight}, seg::{LoneLooseSegWeight, SeqLooseSegWeight},
}, },
layout::{rules::RulesTrait, Infringement, Layout, LayoutException}, layout::{
rules::{Conditions, RulesTrait},
Infringement, Layout, LayoutException,
},
math::{Circle, NoTangents}, math::{Circle, NoTangents},
rules::{Conditions, Rules},
wraparoundable::WraparoundableIndex, wraparoundable::WraparoundableIndex,
}; };
@ -31,16 +33,17 @@ pub enum DrawException {
pub struct Draw<'a, R: RulesTrait> { pub struct Draw<'a, R: RulesTrait> {
layout: &'a mut Layout<R>, layout: &'a mut Layout<R>,
rules: &'a Rules,
} }
impl<'a, R: RulesTrait> Draw<'a, R> { impl<'a, R: RulesTrait> Draw<'a, R> {
pub fn new(layout: &'a mut Layout<R>, rules: &'a Rules) -> Self { pub fn new(layout: &'a mut Layout<R>) -> Self {
Self { layout, rules } Self { layout }
} }
pub fn start(&mut self, from: LooseDotIndex) -> Head { 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))] #[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, width: f64,
) -> Result<(), DrawException> { ) -> Result<(), DrawException> {
let tangent = self let tangent = self
.guide(&Default::default()) .guide(&Default::default(), &Default::default())
.head_into_dot_segment(&head, into, width) .head_into_dot_segment(&head, into, width)
.map_err(Into::<DrawException>::into)?; .map_err(Into::<DrawException>::into)?;
let head = self let head = self
@ -95,13 +98,13 @@ impl<'a, R: RulesTrait> Draw<'a, R> {
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
&head, .guide(&Default::default(), &Default::default())
around.into(), .head_around_dot_segments(&head, around.into(), width)?;
width, let offset = self
)?; .guide(&Default::default(), &Default::default())
.head_around_dot_offset(&head, around.into(), width);
let mut dirs = [true, false]; let mut dirs = [true, false];
if tangents.1.euclidean_length() < tangents.0.euclidean_length() { if tangents.1.euclidean_length() < tangents.0.euclidean_length() {
@ -118,8 +121,8 @@ impl<'a, R: RulesTrait> Draw<'a, R> {
tangent.start_point(), tangent.start_point(),
tangent.end_point(), tangent.end_point(),
dirs[i], dirs[i],
offset,
width, width,
offset,
) { ) {
Ok(ok) => return Ok(ok), Ok(ok) => return Ok(ok),
Err(err) => errs.push(err), Err(err) => errs.push(err),
@ -140,13 +143,13 @@ impl<'a, R: RulesTrait> Draw<'a, R> {
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
&head, .guide(&Default::default(), &Default::default())
around.into(), .head_around_bend_segments(&head, around.into(), width)?;
width, let offset = self
)?; .guide(&Default::default(), &Default::default())
.head_around_bend_offset(&head, around.into(), width);
let mut dirs = [true, false]; let mut dirs = [true, false];
if tangents.1.euclidean_length() < tangents.0.euclidean_length() { if tangents.1.euclidean_length() < tangents.0.euclidean_length() {
@ -163,8 +166,8 @@ impl<'a, R: RulesTrait> Draw<'a, R> {
tangent.start_point(), tangent.start_point(),
tangent.end_point(), tangent.end_point(),
dirs[i], dirs[i],
offset,
width, width,
offset,
) { ) {
Ok(ok) => return Ok(ok), Ok(ok) => return Ok(ok),
Err(err) => errs.push(err), Err(err) => errs.push(err),
@ -191,7 +194,7 @@ impl<'a, R: RulesTrait> Draw<'a, R> {
offset: 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, offset, width) self.segbend(head, around, to, cw, width, offset)
} }
#[debug_ensures(self.layout.node_count() == old(self.layout.node_count()))] #[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; let band = head.band;
self.layout.remove_segbend(&head.segbend, head.face); 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<R> { fn guide(
Guide::new(self.layout, conditions) &'a self,
ref_conditions: &'a Conditions,
guide_conditions: &'a Conditions,
) -> Guide<R> {
Guide::new(self.layout, ref_conditions, guide_conditions)
} }
} }

View File

@ -12,10 +12,12 @@ use crate::{
Layout, Layout,
}, },
math::{self, Circle, NoTangents}, math::{self, Circle, NoTangents},
rules::{Conditions, Rules},
}; };
use super::{rules::RulesTrait, segbend::Segbend}; use super::{
rules::{Conditions, RulesTrait},
segbend::Segbend,
};
#[enum_dispatch] #[enum_dispatch]
pub trait HeadTrait { pub trait HeadTrait {
@ -65,12 +67,21 @@ impl HeadTrait for SegbendHead {
pub struct Guide<'a, 'b, R: RulesTrait> { pub struct Guide<'a, 'b, R: RulesTrait> {
layout: &'a Layout<R>, layout: &'a Layout<R>,
conditions: &'b Conditions, ref_conditions: &'b Conditions,
guide_conditions: &'b Conditions,
} }
impl<'a, 'b, R: RulesTrait> Guide<'a, 'b, R> { impl<'a, 'b, R: RulesTrait> Guide<'a, 'b, R> {
pub fn new(layout: &'a Layout<R>, conditions: &'b Conditions) -> Self { pub fn new(
Self { layout, conditions } layout: &'a Layout<R>,
ref_conditions: &'b Conditions,
guide_conditions: &'b Conditions,
) -> Self {
Self {
layout,
ref_conditions,
guide_conditions,
}
} }
pub fn head_into_dot_segment( 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)) 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( pub fn head_around_bend_segments(
&self, &self,
head: &Head, 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)) 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<bool> { pub fn head_cw(&self, head: &Head) -> Option<bool> {
if let Head::Segbend(head) = head { if let Head::Segbend(head) = head {
Some(self.layout.primitive(head.segbend.bend).weight().cw) 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 { fn head_circle(&self, head: &Head, width: f64) -> Circle {
let _conditions = Conditions {
lower_net: None,
higher_net: None,
layer: None,
zone: None,
};
match *head { match *head {
Head::Bare(head) => Circle { Head::Bare(head) => Circle {
pos: head.face().primitive(self.layout).shape().center(), // TODO. pos: head.face().primitive(self.layout).shape().center(), // TODO.
@ -189,7 +205,12 @@ impl<'a, 'b, R: RulesTrait> Guide<'a, 'b, R> {
Circle { Circle {
pos: outer_circle.pos, 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(); let shape = dot.primitive(self.layout).shape();
Circle { Circle {
pos: shape.center(), 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),
} }
} }

View File

@ -413,8 +413,9 @@ impl<R: RulesTrait> Layout<R> {
let cw = primitive.weight().cw; let cw = primitive.weight().cw;
let ends = primitive.joints(); let ends = primitive.joints();
let conditions = Default::default(); let default1 = Default::default();
let guide = Guide::new(self, &conditions); let default2 = Default::default();
let guide = Guide::new(self, &default1, &default2);
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);

View File

@ -1,16 +1,19 @@
#[derive(Debug, Default)]
pub struct Conditions { pub struct Conditions {
layer: Option<String>, layer: Option<String>,
region: Option<String>, region: Option<String>,
netclass: Option<String>, netclass: Option<String>,
} }
#[derive(Debug, Default)]
pub struct LayerNetclassConditions { pub struct LayerNetclassConditions {
region: Option<String>, region: Option<String>,
} }
pub trait RulesTrait { pub trait RulesTrait {
fn clearance(conditions1: &Conditions, conditions2: &Conditions) -> f64; fn clearance(&self, conditions1: &Conditions, conditions2: &Conditions) -> f64;
fn clearance_limit( fn clearance_limit(
&self,
layer: String, layer: String,
netclass: String, netclass: String,
conditions: &LayerNetclassConditions, conditions: &LayerNetclassConditions,

View File

@ -16,7 +16,6 @@ mod layout;
mod math; mod math;
mod mesh; mod mesh;
mod router; mod router;
mod rules;
mod tracer; mod tracer;
mod triangulation; mod triangulation;
mod wraparoundable; mod wraparoundable;
@ -61,14 +60,15 @@ use crate::router::Router;
struct ConstantClearance {} struct ConstantClearance {}
impl RulesTrait for ConstantClearance { impl RulesTrait for ConstantClearance {
fn clearance(conditions1: &Conditions, conditions2: &Conditions) -> f64 { fn clearance(&self, _conditions1: &Conditions, _conditions2: &Conditions) -> f64 {
3.0 10.0
} }
fn clearance_limit( fn clearance_limit(
layer: String, &self,
netclass: String, _layer: String,
conditions: &LayerNetclassConditions, _netclass: String,
_conditions: &LayerNetclassConditions,
) -> f64 { ) -> f64 {
3.0 3.0
} }
@ -507,6 +507,7 @@ fn main() -> Result<(), anyhow::Error> {
let _ = router.route_band( let _ = router.route_band(
dot_start, dot_start,
dot_end, dot_end,
3.0,
//&mut EmptyRouterObserver, //&mut EmptyRouterObserver,
&mut DebugRouterObserver::new(&mut event_pump, &window, &mut renderer, &font_context), &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( let band2 = router.route_band(
dot_start2, dot_start2,
dot_end2, dot_end2,
3.0,
//&mut EmptyRouterObserver, //&mut EmptyRouterObserver,
&mut DebugRouterObserver::new(&mut event_pump, &window, &mut renderer, &font_context), &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( let band3 = router.route_band(
dot_start3, dot_start3,
dot_end3, dot_end3,
3.0,
//&mut EmptyRouterObserver, //&mut EmptyRouterObserver,
&mut DebugRouterObserver::new(&mut event_pump, &window, &mut renderer, &font_context), &mut DebugRouterObserver::new(&mut event_pump, &window, &mut renderer, &font_context),
)?; )?;
@ -667,6 +670,7 @@ fn render_times(
.reroute_band( .reroute_band(
band, band,
point! {x: state.x() as f64, y: state.y() as f64}, point! {x: state.x() as f64, y: state.y() as f64},
3.0,
&mut DebugRouterObserver::new( &mut DebugRouterObserver::new(
event_pump, event_pump,
window, window,

View File

@ -19,7 +19,6 @@ use crate::layout::{
use crate::mesh::{Mesh, MeshEdgeReference, VertexIndex}; use crate::mesh::{Mesh, MeshEdgeReference, VertexIndex};
use crate::rules::Rules;
use crate::tracer::{Trace, Tracer}; use crate::tracer::{Trace, Tracer};
#[derive(Error, Debug, Clone, Copy)] #[derive(Error, Debug, Clone, Copy)]
@ -55,7 +54,6 @@ pub trait RouterObserverTrait<R: RulesTrait> {
pub struct Router<R: RulesTrait> { pub struct Router<R: RulesTrait> {
pub layout: Layout<R>, pub layout: Layout<R>,
rules: Rules,
} }
struct RouterAstarStrategy<'a, RO: RouterObserverTrait<R>, R: RulesTrait> { struct RouterAstarStrategy<'a, RO: RouterObserverTrait<R>, R: RulesTrait> {
@ -132,7 +130,6 @@ impl<R: RulesTrait> Router<R> {
pub fn new(rules: R) -> Self { pub fn new(rules: R) -> Self {
Router { Router {
layout: Layout::new(rules), layout: Layout::new(rules),
rules: Rules::new(),
} }
} }
@ -140,6 +137,7 @@ impl<R: RulesTrait> Router<R> {
&mut self, &mut self,
from: FixedDotIndex, from: FixedDotIndex,
to: FixedDotIndex, to: FixedDotIndex,
width: f64,
observer: &mut impl RouterObserverTrait<R>, 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
@ -153,7 +151,7 @@ impl<R: RulesTrait> Router<R> {
})?; })?;
let mut tracer = self.tracer(&mesh); 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 band = trace.head.band();
let (_cost, _path) = astar( let (_cost, _path) = astar(
@ -174,16 +172,17 @@ impl<R: RulesTrait> Router<R> {
&mut self, &mut self,
band: BandIndex, band: BandIndex,
to: Point, to: Point,
width: f64,
observer: &mut impl RouterObserverTrait<R>, 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();
self.layout.remove_band(band); self.layout.remove_band(band);
self.layout.move_dot(to_dot.into(), to).unwrap(); // TODO: Remove `.unwrap()`. 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<R> { 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, mesh)
} }
} }

View File

@ -1,89 +0,0 @@
use std::collections::HashMap;
#[derive(Debug, Default, Clone, Copy, Hash, PartialEq, Eq)]
pub struct Conditions {
pub lower_net: Option<i64>,
pub higher_net: Option<i64>,
pub layer: Option<i64>,
pub zone: Option<i64>,
}
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<HashMap<Conditions, Ruleset>>; 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<f64>,
pub max: f64,
}
impl Rule {
pub fn new() -> Self {
Self {
min: 0.0,
opt: None,
max: f64::INFINITY,
}
}
}

View File

@ -10,7 +10,6 @@ use crate::{
Layout, Layout,
}, },
mesh::{Mesh, VertexIndex}, mesh::{Mesh, VertexIndex},
rules::Rules,
}; };
#[derive(Debug)] #[derive(Debug)]
@ -21,17 +20,12 @@ pub struct Trace {
pub struct Tracer<'a, R: RulesTrait> { pub struct Tracer<'a, R: RulesTrait> {
pub layout: &'a mut Layout<R>, pub layout: &'a mut Layout<R>,
pub rules: &'a Rules,
pub mesh: &'a Mesh, pub mesh: &'a Mesh,
} }
impl<'a, R: RulesTrait> Tracer<'a, R> { impl<'a, R: RulesTrait> Tracer<'a, R> {
pub fn new(layout: &'a mut Layout<R>, rules: &'a Rules, mesh: &'a Mesh) -> Self { pub fn new(layout: &'a mut Layout<R>, mesh: &'a Mesh) -> Self {
Tracer { Tracer { layout, mesh }
layout,
rules,
mesh,
}
} }
pub fn start(&mut self, from: FixedDotIndex, width: f64) -> Trace { pub fn start(&mut self, from: FixedDotIndex, width: f64) -> Trace {
@ -129,9 +123,7 @@ impl<'a, R: RulesTrait> Tracer<'a, R> {
around: FixedDotIndex, around: FixedDotIndex,
width: f64, width: f64,
) -> Result<SegbendHead, DrawException> { ) -> Result<SegbendHead, DrawException> {
let head = self let head = self.draw().segbend_around_dot(head, around.into(), width)?;
.draw()
.segbend_around_dot(head, around.into(), width, 3.0)?;
Ok(head) Ok(head)
} }
@ -143,7 +135,7 @@ impl<'a, R: RulesTrait> Tracer<'a, R> {
) -> Result<SegbendHead, DrawException> { ) -> Result<SegbendHead, DrawException> {
let head = self let head = self
.draw() .draw()
.segbend_around_bend(head, around.into(), width, 3.0)?; .segbend_around_bend(head, around.into(), width)?;
Ok(head) Ok(head)
} }
@ -160,6 +152,6 @@ impl<'a, R: RulesTrait> Tracer<'a, R> {
} }
fn draw(&mut self) -> Draw<R> { fn draw(&mut self) -> Draw<R> {
Draw::new(&mut self.layout, &self.rules) Draw::new(&mut self.layout)
} }
} }