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,
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::<DrawException>::into)?;
let head = self
@ -100,10 +95,10 @@ impl<'a, R: RulesTrait> Draw<'a, R> {
width: f64,
) -> Result<SegbendHead, DrawException> {
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<SegbendHead, DrawException> {
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<R> {
Guide::new(self.layout, ref_conditions, guide_conditions)
fn guide(&self) -> Guide<R> {
Guide::new(self.layout)
}
}

View File

@ -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<R>,
ref_conditions: &'b Conditions,
guide_conditions: &'b Conditions,
}
impl<'a, 'b, R: RulesTrait> Guide<'a, 'b, R> {
pub fn new(
layout: &'a Layout<R>,
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<R>) -> 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<Line> =
@ -123,16 +115,17 @@ impl<'a, 'b, R: RulesTrait> Guide<'a, 'b, R> {
width: f64,
) -> Result<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);
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<Line> =
@ -158,16 +151,17 @@ impl<'a, 'b, R: RulesTrait> Guide<'a, 'b, R> {
width: f64,
) -> Result<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);
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<bool> {
@ -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()
}
}

View File

@ -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<R: RulesTrait> Layout<R> {
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<R: RulesTrait> Layout<R> {
)?;
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();

View File

@ -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);

View File

@ -1,21 +1,25 @@
#[derive(Debug, Default)]
pub struct Conditions {
layer: Option<String>,
region: Option<String>,
netclass: Option<String>,
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<String>,
pub struct Conditions {
pub netclass: Option<String>,
pub region: Option<String>,
pub layer: Option<String>,
}
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;*/
}

View File

@ -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 {}
impl RulesTrait for ConstantClearance {
fn clearance(&self, _conditions1: &Conditions, _conditions2: &Conditions) -> f64 {
10.0
struct SimpleRules {
netclass_clearances: HashMap<(String, String), f64>,
}
fn clearance_limit(
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(
&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);