mirror of https://codeberg.org/topola/topola.git
draw,layout: create an interface for accessing conditions
This commit is contained in:
parent
e5ddf47eb3
commit
17209c2a65
32
src/draw.rs
32
src/draw.rs
|
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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()
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
||||
|
|
|
|||
|
|
@ -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;*/
|
||||
}
|
||||
|
|
|
|||
45
src/main.rs
45
src/main.rs
|
|
@ -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 {}
|
||||
struct SimpleRules {
|
||||
netclass_clearances: HashMap<(String, String), f64>,
|
||||
}
|
||||
|
||||
impl RulesTrait for ConstantClearance {
|
||||
fn clearance(&self, _conditions1: &Conditions, _conditions2: &Conditions) -> f64 {
|
||||
10.0
|
||||
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(
|
||||
/*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);
|
||||
|
|
|
|||
Loading…
Reference in New Issue