refactor(drawing::guide): turn Guide into a trait

This commit is contained in:
Ellen Emilia Anna Zscheile 2025-02-01 23:54:45 +01:00 committed by mikolaj
parent bcb0c4ad5c
commit 2087e76dfe
4 changed files with 118 additions and 77 deletions

View File

@ -540,12 +540,11 @@ impl<CW: Copy, R: AccessRules> Drawing<CW, R> {
let rail_primitive = self.primitive(rail); let rail_primitive = self.primitive(rail);
let joints = rail_primitive.joints(); let joints = rail_primitive.joints();
let guide = Guide::new(self); let from_head = self.rear_head(joints.1);
let from_head = guide.rear_head(joints.1); let to_head = self.rear_head(joints.0);
let to_head = guide.rear_head(joints.0);
if let Some(inner) = rail_primitive.inner() { if let Some(inner) = rail_primitive.inner() {
let from = guide let from = self
.head_around_bend_segment( .head_around_bend_segment(
&from_head, &from_head,
inner.into(), inner.into(),
@ -553,7 +552,7 @@ impl<CW: Copy, R: AccessRules> Drawing<CW, R> {
self.primitive(rail).width(), self.primitive(rail).width(),
)? )?
.end_point(); .end_point();
let to = guide let to = self
.head_around_bend_segment( .head_around_bend_segment(
&to_head, &to_head,
inner.into(), inner.into(),
@ -561,7 +560,7 @@ impl<CW: Copy, R: AccessRules> Drawing<CW, R> {
self.primitive(rail).width(), self.primitive(rail).width(),
)? )?
.end_point(); .end_point();
let offset = guide.head_around_bend_offset( let offset = self.head_around_bend_offset(
&from_head, &from_head,
inner.into(), inner.into(),
self.primitive(rail).width(), self.primitive(rail).width(),
@ -590,7 +589,7 @@ impl<CW: Copy, R: AccessRules> Drawing<CW, R> {
// Update offsets in case the rule conditions changed. // Update offsets in case the rule conditions changed.
} else { } else {
let core = rail_primitive.core(); let core = rail_primitive.core();
let from = guide let from = self
.head_around_dot_segment( .head_around_dot_segment(
&from_head, &from_head,
core.into(), core.into(),
@ -598,7 +597,7 @@ impl<CW: Copy, R: AccessRules> Drawing<CW, R> {
self.primitive(rail).width(), self.primitive(rail).width(),
)? )?
.end_point(); .end_point();
let to = guide let to = self
.head_around_dot_segment( .head_around_dot_segment(
&to_head, &to_head,
core.into(), core.into(),
@ -606,7 +605,7 @@ impl<CW: Copy, R: AccessRules> Drawing<CW, R> {
self.primitive(rail).width(), self.primitive(rail).width(),
)? )?
.end_point(); .end_point();
let offset = guide.head_around_dot_offset( let offset = self.head_around_dot_offset(
&from_head, &from_head,
core.into(), core.into(),
self.primitive(rail).width(), self.primitive(rail).width(),
@ -1105,10 +1104,6 @@ impl<CW: Copy, R: AccessRules> Drawing<CW, R> {
&mut self.rules &mut self.rules
} }
pub fn guide(&self) -> Guide<CW, R> {
Guide::new(self)
}
pub fn primitive<W>(&self, index: GenericIndex<W>) -> GenericPrimitive<W, CW, R> { pub fn primitive<W>(&self, index: GenericIndex<W>) -> GenericPrimitive<W, CW, R> {
GenericPrimitive::new(index, self) GenericPrimitive::new(index, self)
} }

View File

@ -22,18 +22,59 @@ use super::{
Drawing, Drawing,
}; };
pub struct Guide<'a, CW, R> { pub trait Guide {
drawing: &'a Drawing<CW, R>, fn head_into_dot_segment(
&self,
head: &Head,
into: FixedDotIndex,
width: f64,
) -> Result<Line, NoTangents>;
fn head_around_dot_segments(
&self,
head: &Head,
around: DotIndex,
width: f64,
) -> Result<(Line, Line), NoTangents>;
fn head_around_dot_segment(
&self,
head: &Head,
around: DotIndex,
cw: bool,
width: f64,
) -> Result<Line, NoTangents>;
fn head_around_dot_offset(&self, head: &Head, around: DotIndex, _width: f64) -> f64;
fn head_around_bend_segments(
&self,
head: &Head,
around: BendIndex,
width: f64,
) -> Result<(Line, Line), NoTangents>;
fn head_around_bend_segment(
&self,
head: &Head,
around: BendIndex,
cw: bool,
width: f64,
) -> Result<Line, NoTangents>;
fn head_around_bend_offset(&self, head: &Head, around: BendIndex, _width: f64) -> f64;
fn head_cw(&self, head: &Head) -> Option<bool>;
fn cane_head(&self, face: LooseDotIndex) -> CaneHead;
fn rear_head(&self, face: LooseDotIndex) -> Head;
fn head(&self, face: DotIndex) -> Head;
} }
impl<'a, CW, R> Guide<'a, CW, R> { impl<CW: Copy, R: AccessRules> Guide for Drawing<CW, R> {
pub fn new(drawing: &'a Drawing<CW, R>) -> Self { fn head_into_dot_segment(
Self { drawing }
}
}
impl<'a, CW: Copy, R: AccessRules> Guide<'a, CW, R> {
pub fn head_into_dot_segment(
&self, &self,
head: &Head, head: &Head,
into: FixedDotIndex, into: FixedDotIndex,
@ -41,7 +82,7 @@ impl<'a, CW: Copy, R: AccessRules> Guide<'a, CW, R> {
) -> 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 = Circle { let to_circle = Circle {
pos: self.drawing.primitive(into).weight().circle.pos, pos: self.primitive(into).weight().circle.pos,
r: 0.0, r: 0.0,
}; };
@ -49,7 +90,7 @@ impl<'a, CW: Copy, R: AccessRules> Guide<'a, CW, R> {
math::tangent_segment(from_circle, from_cw, to_circle, None) math::tangent_segment(from_circle, from_cw, to_circle, None)
} }
pub fn head_around_dot_segments( fn head_around_dot_segments(
&self, &self,
head: &Head, head: &Head,
around: DotIndex, around: DotIndex,
@ -64,7 +105,7 @@ impl<'a, CW: Copy, R: AccessRules> Guide<'a, CW, R> {
Ok((tangents[0], tangents[1])) Ok((tangents[0], tangents[1]))
} }
pub fn head_around_dot_segment( fn head_around_dot_segment(
&self, &self,
head: &Head, head: &Head,
around: DotIndex, around: DotIndex,
@ -78,14 +119,14 @@ impl<'a, CW: Copy, R: AccessRules> Guide<'a, CW, 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 { fn head_around_dot_offset(&self, head: &Head, around: DotIndex, _width: f64) -> f64 {
self.drawing.rules().clearance( self.rules().clearance(
&self.conditions(around.into()), &self.conditions(around.into()),
&self.conditions(head.face().into()), &self.conditions(head.face().into()),
) )
} }
pub fn head_around_bend_segments( fn head_around_bend_segments(
&self, &self,
head: &Head, head: &Head,
around: BendIndex, around: BendIndex,
@ -100,7 +141,7 @@ impl<'a, CW: Copy, R: AccessRules> Guide<'a, CW, R> {
Ok((tangents[0], tangents[1])) Ok((tangents[0], tangents[1]))
} }
pub fn head_around_bend_segment( fn head_around_bend_segment(
&self, &self,
head: &Head, head: &Head,
around: BendIndex, around: BendIndex,
@ -114,16 +155,16 @@ impl<'a, CW: Copy, R: AccessRules> Guide<'a, CW, 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 { fn head_around_bend_offset(&self, head: &Head, around: BendIndex, _width: f64) -> f64 {
self.drawing.rules().clearance( self.rules().clearance(
&self.conditions(head.face().into()), &self.conditions(head.face().into()),
&self.conditions(around.into()), &self.conditions(around.into()),
) )
} }
pub fn head_cw(&self, head: &Head) -> Option<bool> { fn head_cw(&self, head: &Head) -> Option<bool> {
if let Head::Cane(head) = head { if let Head::Cane(head) = head {
let joints = self.drawing.primitive(head.cane.bend).joints(); let joints = self.primitive(head.cane.bend).joints();
if head.face() == joints.0.into() { if head.face() == joints.0.into() {
Some(false) Some(false)
@ -135,18 +176,50 @@ impl<'a, CW: Copy, R: AccessRules> Guide<'a, CW, R> {
} }
} }
fn cane_head(&self, face: LooseDotIndex) -> CaneHead {
CaneHead {
face,
cane: self.cane(face),
}
}
fn rear_head(&self, face: LooseDotIndex) -> Head {
self.head(self.rear(self.cane_head(face)))
}
fn head(&self, face: DotIndex) -> Head {
match face {
DotIndex::Fixed(dot) => BareHead { face: dot }.into(),
DotIndex::Loose(dot) => self.cane_head(dot).into(),
}
}
}
trait GuidePrivate {
fn head_circle(&self, head: &Head, width: f64) -> Circle;
fn bend_circle(&self, bend: BendIndex, width: f64, guide_conditions: &Conditions) -> Circle;
fn dot_circle(&self, dot: DotIndex, width: f64, guide_conditions: &Conditions) -> Circle;
fn rear(&self, head: CaneHead) -> DotIndex;
fn conditions(&self, node: PrimitiveIndex) -> Conditions;
}
impl<CW: Copy, R: AccessRules> GuidePrivate for Drawing<CW, R> {
fn head_circle(&self, head: &Head, width: f64) -> Circle { fn head_circle(&self, head: &Head, width: f64) -> Circle {
match *head { match *head {
Head::Bare(head) => Circle { Head::Bare(head) => Circle {
pos: head.face().primitive(self.drawing).shape().center(), // TODO. pos: head.face().primitive(self).shape().center(), // TODO.
r: 0.0, r: 0.0,
}, },
Head::Cane(head) => { Head::Cane(head) => {
if let Some(inner) = self.drawing.primitive(head.cane.bend).inner() { if let Some(inner) = self.primitive(head.cane.bend).inner() {
self.bend_circle(inner.into(), width, &self.conditions(head.face().into())) self.bend_circle(inner.into(), width, &self.conditions(head.face().into()))
} else { } else {
self.dot_circle( self.dot_circle(
self.drawing.primitive(head.cane.bend).core().into(), self.primitive(head.cane.bend).core().into(),
width, width,
&self.conditions(head.face().into()), &self.conditions(head.face().into()),
) )
@ -156,7 +229,7 @@ impl<'a, CW: Copy, R: AccessRules> Guide<'a, CW, R> {
} }
fn bend_circle(&self, bend: BendIndex, width: f64, guide_conditions: &Conditions) -> Circle { fn bend_circle(&self, bend: BendIndex, width: f64, guide_conditions: &Conditions) -> Circle {
let outer_circle = match bend.primitive(self.drawing).shape() { let outer_circle = match bend.primitive(self).shape() {
PrimitiveShape::Bend(shape) => shape.outer_circle(), PrimitiveShape::Bend(shape) => shape.outer_circle(),
_ => unreachable!(), _ => unreachable!(),
}; };
@ -166,50 +239,29 @@ impl<'a, CW: Copy, R: AccessRules> Guide<'a, CW, R> {
r: outer_circle.r r: outer_circle.r
+ width / 2.0 + width / 2.0
+ self + self
.drawing
.rules() .rules()
.clearance(&self.conditions(bend.into()), guide_conditions), .clearance(&self.conditions(bend.into()), guide_conditions),
} }
} }
fn dot_circle(&self, dot: DotIndex, width: f64, guide_conditions: &Conditions) -> Circle { fn dot_circle(&self, dot: DotIndex, width: f64, guide_conditions: &Conditions) -> Circle {
let shape = dot.primitive(self.drawing).shape(); let shape = dot.primitive(self).shape();
Circle { Circle {
pos: shape.center(), pos: shape.center(),
r: shape.width() / 2.0 r: shape.width() / 2.0
+ width / 2.0 + width / 2.0
+ self + self
.drawing
.rules() .rules()
.clearance(&self.conditions(dot.into()), guide_conditions), .clearance(&self.conditions(dot.into()), guide_conditions),
} }
} }
pub fn cane_head(&self, face: LooseDotIndex) -> CaneHead {
CaneHead {
face,
cane: self.drawing.cane(face),
}
}
pub fn rear_head(&self, face: LooseDotIndex) -> Head {
self.head(self.rear(self.cane_head(face)))
}
pub fn head(&self, face: DotIndex) -> Head {
match face {
DotIndex::Fixed(dot) => BareHead { face: dot }.into(),
DotIndex::Loose(dot) => self.cane_head(dot).into(),
}
}
fn rear(&self, head: CaneHead) -> DotIndex { fn rear(&self, head: CaneHead) -> DotIndex {
self.drawing self.primitive(head.cane.seg)
.primitive(head.cane.seg)
.other_joint(head.cane.dot.into()) .other_joint(head.cane.dot.into())
} }
fn conditions(&self, node: PrimitiveIndex) -> Conditions { fn conditions(&self, node: PrimitiveIndex) -> Conditions {
node.primitive(self.drawing).conditions() node.primitive(self).conditions()
} }
} }

View File

@ -22,7 +22,7 @@ use crate::{
seg::{LoneLooseSegWeight, SeqLooseSegWeight}, seg::{LoneLooseSegWeight, SeqLooseSegWeight},
DrawingException, Infringement, DrawingException, Infringement,
}, },
layout::{CompoundWeight, Layout, LayoutEdit}, layout::{Layout, LayoutEdit},
math::{Circle, NoTangents}, math::{Circle, NoTangents},
}; };
@ -71,7 +71,7 @@ pub trait Draw {
impl<R: AccessRules> Draw for Layout<R> { impl<R: AccessRules> Draw for Layout<R> {
fn start(&mut self, from: LooseDotIndex) -> Head { fn start(&mut self, from: LooseDotIndex) -> Head {
self.guide().cane_head(from).into() self.drawing().cane_head(from).into()
} }
#[debug_ensures(ret.is_ok() -> self.drawing().node_count() == old(self.drawing().node_count() + 1))] #[debug_ensures(ret.is_ok() -> self.drawing().node_count() == old(self.drawing().node_count() + 1))]
@ -84,7 +84,7 @@ impl<R: AccessRules> Draw for Layout<R> {
width: f64, width: f64,
) -> Result<BandTermsegIndex, DrawException> { ) -> Result<BandTermsegIndex, DrawException> {
let tangent = self let tangent = self
.guide() .drawing()
.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
@ -134,10 +134,10 @@ impl<R: AccessRules> Draw for Layout<R> {
width: f64, width: f64,
) -> Result<CaneHead, DrawException> { ) -> Result<CaneHead, DrawException> {
let tangent = self let tangent = self
.guide() .drawing()
.head_around_dot_segment(&head, around.into(), cw, width)?; .head_around_dot_segment(&head, around.into(), cw, width)?;
let offset = self let offset = self
.guide() .drawing()
.head_around_dot_offset(&head, around.into(), width); .head_around_dot_offset(&head, around.into(), width);
self.cane_around( self.cane_around(
recorder, recorder,
@ -163,9 +163,9 @@ impl<R: AccessRules> Draw for Layout<R> {
width: f64, width: f64,
) -> Result<CaneHead, DrawException> { ) -> Result<CaneHead, DrawException> {
let tangent = self let tangent = self
.guide() .drawing()
.head_around_bend_segment(&head, around, cw, width)?; .head_around_bend_segment(&head, around, cw, width)?;
let offset = self.guide().head_around_bend_offset(&head, around, width); let offset = self.drawing().head_around_bend_offset(&head, around, width);
self.cane_around( self.cane_around(
recorder, recorder,
@ -189,7 +189,7 @@ impl<R: AccessRules> Draw for Layout<R> {
.other_joint(head.cane.dot.into()); .other_joint(head.cane.dot.into());
self.remove_cane(recorder, &head.cane, head.face); self.remove_cane(recorder, &head.cane, head.face);
Some(self.guide().head(prev_dot)) Some(self.drawing().head(prev_dot))
} }
} }
@ -225,8 +225,6 @@ trait DrawPrivate {
width: f64, width: f64,
offset: f64, offset: f64,
) -> Result<CaneHead, DrawingException>; ) -> Result<CaneHead, DrawingException>;
fn guide(&self) -> Guide<CompoundWeight, Self::R>;
} }
impl<R: AccessRules> DrawPrivate for Layout<R> { impl<R: AccessRules> DrawPrivate for Layout<R> {
@ -308,8 +306,4 @@ impl<R: AccessRules> DrawPrivate for Layout<R> {
cane, cane,
}) })
} }
fn guide(&self) -> Guide<CompoundWeight, R> {
Guide::new(self.drawing())
}
} }

View File

@ -12,6 +12,7 @@ use crate::{
band::BandTermsegIndex, band::BandTermsegIndex,
dot::{DotIndex, FixedDotIndex}, dot::{DotIndex, FixedDotIndex},
graph::{MakePrimitive, PrimitiveIndex}, graph::{MakePrimitive, PrimitiveIndex},
guide::Guide,
head::GetFace, head::GetFace,
primitive::MakePrimitiveShape, primitive::MakePrimitiveShape,
rules::AccessRules, rules::AccessRules,
@ -74,7 +75,6 @@ impl<'a, R: AccessRules> RouterAstarStrategy<'a, R> {
DotIndex::Loose(face) => self DotIndex::Loose(face) => self
.layout .layout
.drawing() .drawing()
.guide()
.rear_head(face) .rear_head(face)
.ref_(self.layout.drawing()) .ref_(self.layout.drawing())
.length(), .length(),