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

View File

@ -22,18 +22,59 @@ use super::{
Drawing,
};
pub struct Guide<'a, CW, R> {
drawing: &'a Drawing<CW, R>,
pub trait Guide {
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> {
pub fn new(drawing: &'a Drawing<CW, R>) -> Self {
Self { drawing }
}
}
impl<'a, CW: Copy, R: AccessRules> Guide<'a, CW, R> {
pub fn head_into_dot_segment(
impl<CW: Copy, R: AccessRules> Guide for Drawing<CW, R> {
fn head_into_dot_segment(
&self,
head: &Head,
into: FixedDotIndex,
@ -41,7 +82,7 @@ impl<'a, CW: Copy, R: AccessRules> Guide<'a, CW, R> {
) -> Result<Line, NoTangents> {
let from_circle = self.head_circle(head, width);
let to_circle = Circle {
pos: self.drawing.primitive(into).weight().circle.pos,
pos: self.primitive(into).weight().circle.pos,
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)
}
pub fn head_around_dot_segments(
fn head_around_dot_segments(
&self,
head: &Head,
around: DotIndex,
@ -64,7 +105,7 @@ impl<'a, CW: Copy, R: AccessRules> Guide<'a, CW, R> {
Ok((tangents[0], tangents[1]))
}
pub fn head_around_dot_segment(
fn head_around_dot_segment(
&self,
head: &Head,
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))
}
pub fn head_around_dot_offset(&self, head: &Head, around: DotIndex, _width: f64) -> f64 {
self.drawing.rules().clearance(
fn head_around_dot_offset(&self, head: &Head, around: DotIndex, _width: f64) -> f64 {
self.rules().clearance(
&self.conditions(around.into()),
&self.conditions(head.face().into()),
)
}
pub fn head_around_bend_segments(
fn head_around_bend_segments(
&self,
head: &Head,
around: BendIndex,
@ -100,7 +141,7 @@ impl<'a, CW: Copy, R: AccessRules> Guide<'a, CW, R> {
Ok((tangents[0], tangents[1]))
}
pub fn head_around_bend_segment(
fn head_around_bend_segment(
&self,
head: &Head,
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))
}
pub fn head_around_bend_offset(&self, head: &Head, around: BendIndex, _width: f64) -> f64 {
self.drawing.rules().clearance(
fn head_around_bend_offset(&self, head: &Head, around: BendIndex, _width: f64) -> f64 {
self.rules().clearance(
&self.conditions(head.face().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 {
let joints = self.drawing.primitive(head.cane.bend).joints();
let joints = self.primitive(head.cane.bend).joints();
if head.face() == joints.0.into() {
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 {
match *head {
Head::Bare(head) => Circle {
pos: head.face().primitive(self.drawing).shape().center(), // TODO.
pos: head.face().primitive(self).shape().center(), // TODO.
r: 0.0,
},
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()))
} else {
self.dot_circle(
self.drawing.primitive(head.cane.bend).core().into(),
self.primitive(head.cane.bend).core().into(),
width,
&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 {
let outer_circle = match bend.primitive(self.drawing).shape() {
let outer_circle = match bend.primitive(self).shape() {
PrimitiveShape::Bend(shape) => shape.outer_circle(),
_ => unreachable!(),
};
@ -166,50 +239,29 @@ impl<'a, CW: Copy, R: AccessRules> Guide<'a, CW, R> {
r: outer_circle.r
+ width / 2.0
+ self
.drawing
.rules()
.clearance(&self.conditions(bend.into()), guide_conditions),
}
}
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 {
pos: shape.center(),
r: shape.width() / 2.0
+ width / 2.0
+ self
.drawing
.rules()
.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 {
self.drawing
.primitive(head.cane.seg)
self.primitive(head.cane.seg)
.other_joint(head.cane.dot.into())
}
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},
DrawingException, Infringement,
},
layout::{CompoundWeight, Layout, LayoutEdit},
layout::{Layout, LayoutEdit},
math::{Circle, NoTangents},
};
@ -71,7 +71,7 @@ pub trait Draw {
impl<R: AccessRules> Draw for Layout<R> {
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))]
@ -84,7 +84,7 @@ impl<R: AccessRules> Draw for Layout<R> {
width: f64,
) -> Result<BandTermsegIndex, DrawException> {
let tangent = self
.guide()
.drawing()
.head_into_dot_segment(&head, into, width)
.map_err(Into::<DrawException>::into)?;
let head = self
@ -134,10 +134,10 @@ impl<R: AccessRules> Draw for Layout<R> {
width: f64,
) -> Result<CaneHead, DrawException> {
let tangent = self
.guide()
.drawing()
.head_around_dot_segment(&head, around.into(), cw, width)?;
let offset = self
.guide()
.drawing()
.head_around_dot_offset(&head, around.into(), width);
self.cane_around(
recorder,
@ -163,9 +163,9 @@ impl<R: AccessRules> Draw for Layout<R> {
width: f64,
) -> Result<CaneHead, DrawException> {
let tangent = self
.guide()
.drawing()
.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(
recorder,
@ -189,7 +189,7 @@ impl<R: AccessRules> Draw for Layout<R> {
.other_joint(head.cane.dot.into());
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,
offset: f64,
) -> Result<CaneHead, DrawingException>;
fn guide(&self) -> Guide<CompoundWeight, Self::R>;
}
impl<R: AccessRules> DrawPrivate for Layout<R> {
@ -308,8 +306,4 @@ impl<R: AccessRules> DrawPrivate for Layout<R> {
cane,
})
}
fn guide(&self) -> Guide<CompoundWeight, R> {
Guide::new(self.drawing())
}
}

View File

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