draw,layout: create an interface for accessing conditions

This commit is contained in:
Mikolaj Wielgus 2024-02-05 02:53:31 +00:00
parent e5ddf47eb3
commit 17209c2a65
6 changed files with 113 additions and 80 deletions

View File

@ -11,10 +11,7 @@ use crate::{
primitive::GetOtherJoint, primitive::GetOtherJoint,
seg::{LoneLooseSegWeight, SeqLooseSegWeight}, seg::{LoneLooseSegWeight, SeqLooseSegWeight},
}, },
layout::{ layout::{rules::RulesTrait, Infringement, Layout, LayoutException},
rules::{Conditions, RulesTrait},
Infringement, Layout, LayoutException,
},
math::{Circle, NoTangents}, math::{Circle, NoTangents},
wraparoundable::WraparoundableIndex, wraparoundable::WraparoundableIndex,
}; };
@ -41,9 +38,7 @@ impl<'a, R: RulesTrait> Draw<'a, R> {
} }
pub fn start(&mut self, from: LooseDotIndex) -> Head { pub fn start(&mut self, from: LooseDotIndex) -> Head {
self.guide(&Default::default(), &Default::default()) self.guide().segbend_head(from).into()
.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))]
@ -55,7 +50,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(), &Default::default()) .guide()
.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
@ -100,10 +95,10 @@ impl<'a, R: RulesTrait> Draw<'a, R> {
width: f64, width: f64,
) -> Result<SegbendHead, DrawException> { ) -> Result<SegbendHead, DrawException> {
let mut tangents = self let mut tangents = self
.guide(&Default::default(), &Default::default()) .guide()
.head_around_dot_segments(&head, around.into(), width)?; .head_around_dot_segments(&head, around.into(), width)?;
let offset = self let offset = self
.guide(&Default::default(), &Default::default()) .guide()
.head_around_dot_offset(&head, around.into(), width); .head_around_dot_offset(&head, around.into(), width);
let mut dirs = [true, false]; let mut dirs = [true, false];
@ -145,10 +140,10 @@ impl<'a, R: RulesTrait> Draw<'a, R> {
width: f64, width: f64,
) -> Result<SegbendHead, DrawException> { ) -> Result<SegbendHead, DrawException> {
let mut tangents = self let mut tangents = self
.guide(&Default::default(), &Default::default()) .guide()
.head_around_bend_segments(&head, around.into(), width)?; .head_around_bend_segments(&head, around.into(), width)?;
let offset = self let offset = self
.guide(&Default::default(), &Default::default()) .guide()
.head_around_bend_offset(&head, around.into(), width); .head_around_bend_offset(&head, around.into(), width);
let mut dirs = [true, false]; let mut dirs = [true, false];
@ -256,17 +251,10 @@ 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( Some(self.guide().head(prev_dot, band))
self.guide(&Default::default(), &Default::default())
.head(prev_dot, band),
)
} }
fn guide( fn guide(&self) -> Guide<R> {
&'a self, Guide::new(self.layout)
ref_conditions: &'a Conditions,
guide_conditions: &'a Conditions,
) -> Guide<R> {
Guide::new(self.layout, ref_conditions, guide_conditions)
} }
} }

View File

@ -9,12 +9,14 @@ use crate::{
geometry::shape::{Shape, ShapeTrait}, geometry::shape::{Shape, ShapeTrait},
graph::{GetBandIndex, MakePrimitive}, graph::{GetBandIndex, MakePrimitive},
primitive::{GetCore, GetInnerOuter, GetOtherJoint, GetWeight, MakeShape}, primitive::{GetCore, GetInnerOuter, GetOtherJoint, GetWeight, MakeShape},
rules::GetConditions,
Layout, Layout,
}, },
math::{self, Circle, NoTangents}, math::{self, Circle, NoTangents},
}; };
use super::{ use super::{
graph::GeometryIndex,
rules::{Conditions, RulesTrait}, rules::{Conditions, RulesTrait},
segbend::Segbend, 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<R>, layout: &'a Layout<R>,
ref_conditions: &'b Conditions,
guide_conditions: &'b Conditions,
} }
impl<'a, 'b, R: RulesTrait> Guide<'a, 'b, R> { impl<'a, R: RulesTrait> Guide<'a, R> {
pub fn new( pub fn new(layout: &'a Layout<R>) -> Self {
layout: &'a Layout<R>, Self { layout }
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(
@ -107,7 +99,7 @@ impl<'a, 'b, R: RulesTrait> Guide<'a, 'b, R> {
width: f64, width: f64,
) -> Result<(Line, Line), NoTangents> { ) -> Result<(Line, Line), NoTangents> {
let from_circle = self.head_circle(head, width); 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 from_cw = self.head_cw(head);
let tangents: Vec<Line> = let tangents: Vec<Line> =
@ -123,16 +115,17 @@ impl<'a, 'b, R: RulesTrait> Guide<'a, 'b, R> {
width: f64, width: f64,
) -> Result<Line, NoTangents> { ) -> Result<Line, NoTangents> {
let from_circle = self.head_circle(head, width); 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 from_cw = self.head_cw(head);
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 { pub fn head_around_dot_offset(&self, head: &Head, around: DotIndex, width: f64) -> f64 {
self.layout self.layout.rules().clearance(
.rules() &self.conditions(around.into()),
.clearance(self.ref_conditions, self.guide_conditions) &self.conditions(head.face().into()),
)
} }
pub fn head_around_bend_segments( pub fn head_around_bend_segments(
@ -142,7 +135,7 @@ impl<'a, 'b, R: RulesTrait> Guide<'a, 'b, R> {
width: f64, width: f64,
) -> Result<(Line, Line), NoTangents> { ) -> Result<(Line, Line), NoTangents> {
let from_circle = self.head_circle(head, width); 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 from_cw = self.head_cw(head);
let tangents: Vec<Line> = let tangents: Vec<Line> =
@ -158,16 +151,17 @@ impl<'a, 'b, R: RulesTrait> Guide<'a, 'b, R> {
width: f64, width: f64,
) -> Result<Line, NoTangents> { ) -> Result<Line, NoTangents> {
let from_circle = self.head_circle(head, width); 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 from_cw = self.head_cw(head);
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 { pub fn head_around_bend_offset(&self, head: &Head, around: BendIndex, width: f64) -> f64 {
self.layout self.layout.rules().clearance(
.rules() &self.conditions(head.face().into()),
.clearance(self.ref_conditions, self.guide_conditions) &self.conditions(around.into()),
)
} }
pub fn head_cw(&self, head: &Head) -> Option<bool> { pub fn head_cw(&self, head: &Head) -> Option<bool> {
@ -186,18 +180,19 @@ impl<'a, 'b, R: RulesTrait> Guide<'a, 'b, R> {
}, },
Head::Segbend(head) => { Head::Segbend(head) => {
if let Some(inner) = self.layout.primitive(head.segbend.bend).inner() { 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 { } else {
self.dot_circle( self.dot_circle(
self.layout.primitive(head.segbend.bend).core().into(), self.layout.primitive(head.segbend.bend).core().into(),
width, 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() { let outer_circle = match bend.primitive(self.layout).shape() {
Shape::Bend(shape) => shape.outer_circle(), Shape::Bend(shape) => shape.outer_circle(),
_ => unreachable!(), _ => unreachable!(),
@ -210,11 +205,11 @@ impl<'a, 'b, R: RulesTrait> Guide<'a, 'b, R> {
+ self + self
.layout .layout
.rules() .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(); let shape = dot.primitive(self.layout).shape();
Circle { Circle {
pos: shape.center(), pos: shape.center(),
@ -223,7 +218,7 @@ impl<'a, 'b, R: RulesTrait> Guide<'a, 'b, R> {
+ self + self
.layout .layout
.rules() .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) .primitive(head.segbend.seg)
.other_joint(head.segbend.dot.into()) .other_joint(head.segbend.dot.into())
} }
fn conditions(&self, node: GeometryIndex) -> Conditions {
node.primitive(self.layout).conditions()
}
} }

View File

@ -23,6 +23,7 @@ use crate::layout::geometry::{
BendWeightTrait, DotWeightTrait, Geometry, GeometryLabel, GetPos, SegWeightTrait, BendWeightTrait, DotWeightTrait, Geometry, GeometryLabel, GetPos, SegWeightTrait,
}; };
use crate::layout::guide::Guide; use crate::layout::guide::Guide;
use crate::layout::rules::{Conditions, GetConditions};
use crate::layout::{ use crate::layout::{
bend::{FixedBendIndex, LooseBendIndex, LooseBendWeight}, bend::{FixedBendIndex, LooseBendIndex, LooseBendWeight},
dot::{DotIndex, FixedDotIndex, FixedDotWeight, LooseDotIndex, LooseDotWeight}, dot::{DotIndex, FixedDotIndex, FixedDotWeight, LooseDotIndex, LooseDotWeight},
@ -409,18 +410,22 @@ impl<R: RulesTrait> Layout<R> {
let mut maybe_rail = Some(around); let mut maybe_rail = Some(around);
while let Some(rail) = maybe_rail { while let Some(rail) = maybe_rail {
let primitive = self.primitive(rail); let rail_primitive = self.primitive(rail);
let cw = primitive.weight().cw; let cw = rail_primitive.weight().cw;
let ends = primitive.joints(); let ends = rail_primitive.joints();
let default1 = Default::default(); let inner_conditions = Conditions::from(if let Some(inner) = rail_primitive.inner() {
let default2 = Default::default(); self.primitive(inner).conditions()
let guide = Guide::new(self, &default1, &default2); } 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 from_head = guide.rear_head(ends.1);
let to_head = guide.rear_head(ends.0); let to_head = guide.rear_head(ends.0);
if let Some(inner) = primitive.inner() { if let Some(inner) = rail_primitive.inner() {
let from = guide let from = guide
.head_around_bend_segment(&from_head.into(), inner.into(), !cw, 6.0)? .head_around_bend_segment(&from_head.into(), inner.into(), !cw, 6.0)?
.end_point(); .end_point();
@ -434,7 +439,7 @@ impl<R: RulesTrait> Layout<R> {
)?; )?;
self.move_dot_infringably(ends.1.into(), to, &self.inner_bow_and_outer_bows(rail))?; self.move_dot_infringably(ends.1.into(), to, &self.inner_bow_and_outer_bows(rail))?;
} else { } else {
let core = primitive.core(); let core = rail_primitive.core();
let from = guide let from = guide
.head_around_dot_segment(&from_head.into(), core.into(), !cw, 6.0)? .head_around_dot_segment(&from_head.into(), core.into(), !cw, 6.0)?
.end_point(); .end_point();

View File

@ -20,7 +20,7 @@ use crate::layout::{
Layout, Layout,
}; };
use super::rules::RulesTrait; use super::rules::{Conditions, GetConditions, RulesTrait};
#[enum_dispatch] #[enum_dispatch]
pub trait GetLayout<'a, R: RulesTrait> { 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> { pub enum Primitive<'a, R: RulesTrait> {
FixedDot(FixedDot<'a, R>), FixedDot(FixedDot<'a, R>),
LooseDot(LooseDot<'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>; pub type FixedDot<'a, R> = GenericPrimitive<'a, FixedDotWeight, R>;
impl_fixed_primitive!(FixedDot, FixedDotWeight); impl_fixed_primitive!(FixedDot, FixedDotWeight);

View File

@ -1,21 +1,25 @@
#[derive(Debug, Default)] use enum_dispatch::enum_dispatch;
pub struct Conditions {
layer: Option<String>, use crate::layout::primitive::Primitive;
region: Option<String>,
netclass: Option<String>, #[enum_dispatch]
pub trait GetConditions {
fn conditions(&self) -> Conditions;
} }
#[derive(Debug, Default)] #[derive(Debug, Default)]
pub struct LayerNetclassConditions { pub struct Conditions {
region: Option<String>, pub netclass: Option<String>,
pub region: Option<String>,
pub layer: Option<String>,
} }
pub trait RulesTrait { pub trait RulesTrait {
fn clearance(&self, conditions1: &Conditions, conditions2: &Conditions) -> f64; fn clearance(&self, conditions1: &Conditions, conditions2: &Conditions) -> f64;
fn clearance_limit( /*fn clearance_limit(
&self, &self,
layer: String, layer: String,
netclass: String, netclass: String,
conditions: &LayerNetclassConditions, conditions: &PrimitiveConditions,
) -> f64; ) -> f64;*/
} }

View File

@ -27,7 +27,7 @@ use layout::dot::FixedDotWeight;
use layout::geometry::shape::{Shape, ShapeTrait}; use layout::geometry::shape::{Shape, ShapeTrait};
use layout::graph::{GeometryIndex, MakePrimitive}; use layout::graph::{GeometryIndex, MakePrimitive};
use layout::primitive::MakeShape; use layout::primitive::MakeShape;
use layout::rules::{Conditions, LayerNetclassConditions, RulesTrait}; use layout::rules::{Conditions, RulesTrait};
use layout::seg::FixedSegWeight; use layout::seg::FixedSegWeight;
use layout::{Infringement, Layout, LayoutException}; use layout::{Infringement, Layout, LayoutException};
use mesh::{Mesh, MeshEdgeReference, VertexIndex}; use mesh::{Mesh, MeshEdgeReference, VertexIndex};
@ -51,27 +51,39 @@ use pathfinder_renderer::gpu::renderer::Renderer;
use pathfinder_renderer::options::BuildOptions; use pathfinder_renderer::options::BuildOptions;
use pathfinder_resources::embedded::EmbeddedResourceLoader; use pathfinder_resources::embedded::EmbeddedResourceLoader;
use std::collections::HashMap;
use std::time::Duration; use std::time::Duration;
use tracer::{Trace, Tracer}; use tracer::{Trace, Tracer};
use crate::math::Circle; use crate::math::Circle;
use crate::router::Router; use crate::router::Router;
struct ConstantClearance {} struct SimpleRules {
netclass_clearances: HashMap<(String, String), f64>,
}
impl RulesTrait for ConstantClearance { impl RulesTrait for SimpleRules {
fn clearance(&self, _conditions1: &Conditions, _conditions2: &Conditions) -> f64 { fn clearance(&self, conditions1: &Conditions, conditions2: &Conditions) -> f64 {
10.0 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, &self,
_layer: String, _layer: String,
_netclass: String, _netclass: String,
_conditions: &LayerNetclassConditions, _conditions: &PrimitiveConditions,
) -> f64 { ) -> f64 {
3.0 3.0
} }*/
} }
// Clunky enum to work around borrow checker. // 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 mut event_pump = sdl_context.event_pump().unwrap();
let _i = 0; 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_1 = router.layout.add_component(1);
let component1_2 = router.layout.add_component(1); let component1_2 = router.layout.add_component(1);