mirror of https://codeberg.org/topola/topola.git
draw,guide: construct guides from rules
This commit is contained in:
parent
d2ff1826a0
commit
e5ddf47eb3
60
src/draw.rs
60
src/draw.rs
|
|
@ -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)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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);
|
||||||
|
|
|
||||||
|
|
@ -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,
|
||||||
|
|
|
||||||
16
src/main.rs
16
src/main.rs
|
|
@ -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,
|
||||||
|
|
|
||||||
|
|
@ -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)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
89
src/rules.rs
89
src/rules.rs
|
|
@ -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,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -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)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue