mirror of https://codeberg.org/topola/topola.git
refactor(router::draw): turn Draw into a trait
This commit is contained in:
parent
869d63f7c0
commit
1d11011133
|
|
@ -1,6 +1,8 @@
|
||||||
// SPDX-FileCopyrightText: 2024 Topola contributors
|
// SPDX-FileCopyrightText: 2024 Topola contributors
|
||||||
//
|
//
|
||||||
// SPDX-License-Identifier: MIT
|
// SPDX-License-Identifier: MIT
|
||||||
|
//! router module's routines for drawing and erasing the primitives
|
||||||
|
//! to pull out or contract the currently routed band.
|
||||||
|
|
||||||
use contracts_try::debug_ensures;
|
use contracts_try::debug_ensures;
|
||||||
use geo::Point;
|
use geo::Point;
|
||||||
|
|
@ -20,7 +22,7 @@ use crate::{
|
||||||
seg::{LoneLooseSegWeight, SeqLooseSegWeight},
|
seg::{LoneLooseSegWeight, SeqLooseSegWeight},
|
||||||
DrawingException, Infringement,
|
DrawingException, Infringement,
|
||||||
},
|
},
|
||||||
layout::{Layout, LayoutEdit},
|
layout::{CompoundWeight, Layout, LayoutEdit},
|
||||||
math::{Circle, NoTangents},
|
math::{Circle, NoTangents},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -35,25 +37,46 @@ pub enum DrawException {
|
||||||
CannotWrapAround(GearIndex, #[source] DrawingException),
|
CannotWrapAround(GearIndex, #[source] DrawingException),
|
||||||
}
|
}
|
||||||
|
|
||||||
/// This struct is a simple wrapper whose sole purpose is to have a separate
|
pub trait Draw {
|
||||||
/// file for the router module's routines for drawing and erasing the primitives
|
fn start(&mut self, from: LooseDotIndex) -> Head;
|
||||||
/// to pull out or contract the currently routed band.
|
|
||||||
pub struct Draw<'a, R> {
|
fn finish_in_dot(
|
||||||
layout: &'a mut Layout<R>,
|
&mut self,
|
||||||
|
recorder: &mut LayoutEdit,
|
||||||
|
head: Head,
|
||||||
|
into: FixedDotIndex,
|
||||||
|
width: f64,
|
||||||
|
) -> Result<BandTermsegIndex, DrawException>;
|
||||||
|
|
||||||
|
fn cane_around_dot(
|
||||||
|
&mut self,
|
||||||
|
recorder: &mut LayoutEdit,
|
||||||
|
head: Head,
|
||||||
|
around: FixedDotIndex,
|
||||||
|
cw: bool,
|
||||||
|
width: f64,
|
||||||
|
) -> Result<CaneHead, DrawException>;
|
||||||
|
|
||||||
|
fn cane_around_bend(
|
||||||
|
&mut self,
|
||||||
|
recorder: &mut LayoutEdit,
|
||||||
|
head: Head,
|
||||||
|
around: BendIndex,
|
||||||
|
cw: bool,
|
||||||
|
width: f64,
|
||||||
|
) -> Result<CaneHead, DrawException>;
|
||||||
|
|
||||||
|
fn undo_cane(&mut self, recorder: &mut LayoutEdit, head: CaneHead) -> Option<Head>;
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, R: AccessRules> Draw<'a, R> {
|
impl<R: AccessRules> Draw for Layout<R> {
|
||||||
pub fn new(layout: &'a mut Layout<R>) -> Self {
|
fn start(&mut self, from: LooseDotIndex) -> Head {
|
||||||
Self { layout }
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn start(&mut self, from: LooseDotIndex) -> Head {
|
|
||||||
self.guide().cane_head(from).into()
|
self.guide().cane_head(from).into()
|
||||||
}
|
}
|
||||||
|
|
||||||
#[debug_ensures(ret.is_ok() -> self.layout.drawing().node_count() == old(self.layout.drawing().node_count() + 1))]
|
#[debug_ensures(ret.is_ok() -> self.drawing().node_count() == old(self.drawing().node_count() + 1))]
|
||||||
#[debug_ensures(ret.is_err() -> self.layout.drawing().node_count() == old(self.layout.drawing().node_count()))]
|
#[debug_ensures(ret.is_err() -> self.drawing().node_count() == old(self.drawing().node_count()))]
|
||||||
pub fn finish_in_dot(
|
fn finish_in_dot(
|
||||||
&mut self,
|
&mut self,
|
||||||
recorder: &mut LayoutEdit,
|
recorder: &mut LayoutEdit,
|
||||||
head: Head,
|
head: Head,
|
||||||
|
|
@ -67,13 +90,12 @@ impl<'a, R: AccessRules> Draw<'a, R> {
|
||||||
let head = self
|
let head = self
|
||||||
.extend_head(recorder, head, tangent.start_point())
|
.extend_head(recorder, head, tangent.start_point())
|
||||||
.map_err(|err| DrawException::CannotFinishIn(into, err.into()))?;
|
.map_err(|err| DrawException::CannotFinishIn(into, err.into()))?;
|
||||||
let layer = head.face().primitive(self.layout.drawing()).layer();
|
let layer = head.face().primitive(self.drawing()).layer();
|
||||||
let maybe_net = head.face().primitive(self.layout.drawing()).maybe_net();
|
let maybe_net = head.face().primitive(self.drawing()).maybe_net();
|
||||||
|
|
||||||
Ok(match head.face() {
|
Ok(match head.face() {
|
||||||
DotIndex::Fixed(dot) => BandTermsegIndex::Straight(
|
DotIndex::Fixed(dot) => BandTermsegIndex::Straight(
|
||||||
self.layout
|
self.add_lone_loose_seg(
|
||||||
.add_lone_loose_seg(
|
|
||||||
recorder,
|
recorder,
|
||||||
dot,
|
dot,
|
||||||
into,
|
into,
|
||||||
|
|
@ -86,8 +108,7 @@ impl<'a, R: AccessRules> Draw<'a, R> {
|
||||||
.map_err(|err| DrawException::CannotFinishIn(into, err.into()))?,
|
.map_err(|err| DrawException::CannotFinishIn(into, err.into()))?,
|
||||||
),
|
),
|
||||||
DotIndex::Loose(dot) => BandTermsegIndex::Bended(
|
DotIndex::Loose(dot) => BandTermsegIndex::Bended(
|
||||||
self.layout
|
self.add_seq_loose_seg(
|
||||||
.add_seq_loose_seg(
|
|
||||||
recorder,
|
recorder,
|
||||||
into.into(),
|
into.into(),
|
||||||
dot,
|
dot,
|
||||||
|
|
@ -102,9 +123,9 @@ impl<'a, R: AccessRules> Draw<'a, R> {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
#[debug_ensures(ret.is_ok() -> self.layout.drawing().node_count() == old(self.layout.drawing().node_count() + 4))]
|
#[debug_ensures(ret.is_ok() -> self.drawing().node_count() == old(self.drawing().node_count() + 4))]
|
||||||
#[debug_ensures(ret.is_err() -> self.layout.drawing().node_count() == old(self.layout.drawing().node_count()))]
|
#[debug_ensures(ret.is_err() -> self.drawing().node_count() == old(self.drawing().node_count()))]
|
||||||
pub fn cane_around_dot(
|
fn cane_around_dot(
|
||||||
&mut self,
|
&mut self,
|
||||||
recorder: &mut LayoutEdit,
|
recorder: &mut LayoutEdit,
|
||||||
head: Head,
|
head: Head,
|
||||||
|
|
@ -131,9 +152,9 @@ impl<'a, R: AccessRules> Draw<'a, R> {
|
||||||
.map_err(|err| DrawException::CannotWrapAround(around.into(), err))
|
.map_err(|err| DrawException::CannotWrapAround(around.into(), err))
|
||||||
}
|
}
|
||||||
|
|
||||||
#[debug_ensures(ret.is_ok() -> self.layout.drawing().node_count() == old(self.layout.drawing().node_count() + 4))]
|
#[debug_ensures(ret.is_ok() -> self.drawing().node_count() == old(self.drawing().node_count() + 4))]
|
||||||
#[debug_ensures(ret.is_err() -> self.layout.drawing().node_count() == old(self.layout.drawing().node_count()))]
|
#[debug_ensures(ret.is_err() -> self.drawing().node_count() == old(self.drawing().node_count()))]
|
||||||
pub fn cane_around_bend(
|
fn cane_around_bend(
|
||||||
&mut self,
|
&mut self,
|
||||||
recorder: &mut LayoutEdit,
|
recorder: &mut LayoutEdit,
|
||||||
head: Head,
|
head: Head,
|
||||||
|
|
@ -159,8 +180,60 @@ impl<'a, R: AccessRules> Draw<'a, R> {
|
||||||
.map_err(|err| DrawException::CannotWrapAround(around.into(), err))
|
.map_err(|err| DrawException::CannotWrapAround(around.into(), err))
|
||||||
}
|
}
|
||||||
|
|
||||||
#[debug_ensures(ret.is_ok() -> self.layout.drawing().node_count() == old(self.layout.drawing().node_count() + 4))]
|
#[debug_ensures(ret.is_some() -> self.drawing().node_count() == old(self.drawing().node_count() - 4))]
|
||||||
#[debug_ensures(ret.is_err() -> self.layout.drawing().node_count() == old(self.layout.drawing().node_count()))]
|
#[debug_ensures(ret.is_none() -> self.drawing().node_count() == old(self.drawing().node_count()))]
|
||||||
|
fn undo_cane(&mut self, recorder: &mut LayoutEdit, head: CaneHead) -> Option<Head> {
|
||||||
|
let prev_dot = self
|
||||||
|
.drawing()
|
||||||
|
.primitive(head.cane.seg)
|
||||||
|
.other_joint(head.cane.dot.into());
|
||||||
|
|
||||||
|
self.remove_cane(recorder, &head.cane, head.face);
|
||||||
|
Some(self.guide().head(prev_dot))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
trait DrawPrivate {
|
||||||
|
type R;
|
||||||
|
|
||||||
|
fn cane_around(
|
||||||
|
&mut self,
|
||||||
|
recorder: &mut LayoutEdit,
|
||||||
|
head: Head,
|
||||||
|
around: GearIndex,
|
||||||
|
from: Point,
|
||||||
|
to: Point,
|
||||||
|
cw: bool,
|
||||||
|
width: f64,
|
||||||
|
offset: f64,
|
||||||
|
) -> Result<CaneHead, DrawingException>;
|
||||||
|
|
||||||
|
fn extend_head(
|
||||||
|
&mut self,
|
||||||
|
recorder: &mut LayoutEdit,
|
||||||
|
head: Head,
|
||||||
|
to: Point,
|
||||||
|
) -> Result<Head, Infringement>;
|
||||||
|
|
||||||
|
fn cane(
|
||||||
|
&mut self,
|
||||||
|
recorder: &mut LayoutEdit,
|
||||||
|
head: Head,
|
||||||
|
around: GearIndex,
|
||||||
|
to: Point,
|
||||||
|
cw: bool,
|
||||||
|
width: f64,
|
||||||
|
offset: f64,
|
||||||
|
) -> Result<CaneHead, DrawingException>;
|
||||||
|
|
||||||
|
fn guide(&self) -> Guide<CompoundWeight, Self::R>;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<R: AccessRules> DrawPrivate for Layout<R> {
|
||||||
|
type R = R;
|
||||||
|
|
||||||
|
#[debug_ensures(ret.is_ok() -> self.drawing().node_count() == old(self.drawing().node_count() + 4))]
|
||||||
|
#[debug_ensures(ret.is_err() -> self.drawing().node_count() == old(self.drawing().node_count()))]
|
||||||
fn cane_around(
|
fn cane_around(
|
||||||
&mut self,
|
&mut self,
|
||||||
recorder: &mut LayoutEdit,
|
recorder: &mut LayoutEdit,
|
||||||
|
|
@ -176,7 +249,7 @@ impl<'a, R: AccessRules> Draw<'a, R> {
|
||||||
self.cane(recorder, head, around, to, cw, width, offset)
|
self.cane(recorder, head, around, to, cw, width, offset)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[debug_ensures(self.layout.drawing().node_count() == old(self.layout.drawing().node_count()))]
|
#[debug_ensures(self.drawing().node_count() == old(self.drawing().node_count()))]
|
||||||
fn extend_head(
|
fn extend_head(
|
||||||
&mut self,
|
&mut self,
|
||||||
recorder: &mut LayoutEdit,
|
recorder: &mut LayoutEdit,
|
||||||
|
|
@ -184,15 +257,15 @@ impl<'a, R: AccessRules> Draw<'a, R> {
|
||||||
to: Point,
|
to: Point,
|
||||||
) -> Result<Head, Infringement> {
|
) -> Result<Head, Infringement> {
|
||||||
if let Head::Cane(head) = head {
|
if let Head::Cane(head) = head {
|
||||||
self.layout.move_dot(recorder, head.face.into(), to)?;
|
self.move_dot(recorder, head.face.into(), to)?;
|
||||||
Ok(Head::Cane(head))
|
Ok(Head::Cane(head))
|
||||||
} else {
|
} else {
|
||||||
Ok(head)
|
Ok(head)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[debug_ensures(ret.is_ok() -> self.layout.drawing().node_count() == old(self.layout.drawing().node_count() + 4))]
|
#[debug_ensures(ret.is_ok() -> self.drawing().node_count() == old(self.drawing().node_count() + 4))]
|
||||||
#[debug_ensures(ret.is_err() -> self.layout.drawing().node_count() == old(self.layout.drawing().node_count()))]
|
#[debug_ensures(ret.is_err() -> self.drawing().node_count() == old(self.drawing().node_count()))]
|
||||||
fn cane(
|
fn cane(
|
||||||
&mut self,
|
&mut self,
|
||||||
recorder: &mut LayoutEdit,
|
recorder: &mut LayoutEdit,
|
||||||
|
|
@ -203,9 +276,9 @@ impl<'a, R: AccessRules> Draw<'a, R> {
|
||||||
width: f64,
|
width: f64,
|
||||||
offset: f64,
|
offset: f64,
|
||||||
) -> Result<CaneHead, DrawingException> {
|
) -> Result<CaneHead, DrawingException> {
|
||||||
let layer = head.face().primitive(self.layout.drawing()).layer();
|
let layer = head.face().primitive(self.drawing()).layer();
|
||||||
let maybe_net = head.face().primitive(self.layout.drawing()).maybe_net();
|
let maybe_net = head.face().primitive(self.drawing()).maybe_net();
|
||||||
let cane = self.layout.insert_cane(
|
let cane = self.insert_cane(
|
||||||
recorder,
|
recorder,
|
||||||
head.face(),
|
head.face(),
|
||||||
around,
|
around,
|
||||||
|
|
@ -231,29 +304,12 @@ impl<'a, R: AccessRules> Draw<'a, R> {
|
||||||
cw,
|
cw,
|
||||||
)?;
|
)?;
|
||||||
Ok(CaneHead {
|
Ok(CaneHead {
|
||||||
face: self
|
face: self.drawing().primitive(cane.bend).other_joint(cane.dot),
|
||||||
.layout
|
|
||||||
.drawing()
|
|
||||||
.primitive(cane.bend)
|
|
||||||
.other_joint(cane.dot),
|
|
||||||
cane,
|
cane,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
#[debug_ensures(ret.is_some() -> self.layout.drawing().node_count() == old(self.layout.drawing().node_count() - 4))]
|
fn guide(&self) -> Guide<CompoundWeight, R> {
|
||||||
#[debug_ensures(ret.is_none() -> self.layout.drawing().node_count() == old(self.layout.drawing().node_count()))]
|
Guide::new(self.drawing())
|
||||||
pub fn undo_cane(&mut self, recorder: &mut LayoutEdit, head: CaneHead) -> Option<Head> {
|
|
||||||
let prev_dot = self
|
|
||||||
.layout
|
|
||||||
.drawing()
|
|
||||||
.primitive(head.cane.seg)
|
|
||||||
.other_joint(head.cane.dot.into());
|
|
||||||
|
|
||||||
self.layout.remove_cane(recorder, &head.cane, head.face);
|
|
||||||
Some(self.guide().head(prev_dot))
|
|
||||||
}
|
|
||||||
|
|
||||||
fn guide(&self) -> Guide<impl Copy, R> {
|
|
||||||
Guide::new(self.layout.drawing())
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -85,13 +85,9 @@ impl NavcordStepper {
|
||||||
cw: bool,
|
cw: bool,
|
||||||
width: f64,
|
width: f64,
|
||||||
) -> Result<CaneHead, NavcorderException> {
|
) -> Result<CaneHead, NavcorderException> {
|
||||||
Ok(Draw::new(navcorder.layout).cane_around_dot(
|
Ok(navcorder
|
||||||
&mut self.recorder,
|
.layout
|
||||||
head,
|
.cane_around_dot(&mut self.recorder, head, around, cw, width)?)
|
||||||
around,
|
|
||||||
cw,
|
|
||||||
width,
|
|
||||||
)?)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn wrap_around_loose_bend(
|
fn wrap_around_loose_bend(
|
||||||
|
|
@ -102,13 +98,9 @@ impl NavcordStepper {
|
||||||
cw: bool,
|
cw: bool,
|
||||||
width: f64,
|
width: f64,
|
||||||
) -> Result<CaneHead, NavcorderException> {
|
) -> Result<CaneHead, NavcorderException> {
|
||||||
Ok(Draw::new(navcorder.layout).cane_around_bend(
|
Ok(navcorder
|
||||||
&mut self.recorder,
|
.layout
|
||||||
head,
|
.cane_around_bend(&mut self.recorder, head, around.into(), cw, width)?)
|
||||||
around.into(),
|
|
||||||
cw,
|
|
||||||
width,
|
|
||||||
)?)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn binavvertex(&self, navmesh: &Navmesh, navvertex: NavvertexIndex) -> BinavvertexNodeIndex {
|
fn binavvertex(&self, navmesh: &Navmesh, navvertex: NavvertexIndex) -> BinavvertexNodeIndex {
|
||||||
|
|
@ -159,7 +151,8 @@ impl NavcordStepper {
|
||||||
navcorder: &mut Navcorder<'a, R>,
|
navcorder: &mut Navcorder<'a, R>,
|
||||||
) -> Result<(), NavcorderException> {
|
) -> Result<(), NavcorderException> {
|
||||||
if let Head::Cane(head) = self.head {
|
if let Head::Cane(head) = self.head {
|
||||||
self.head = Draw::new(navcorder.layout)
|
self.head = navcorder
|
||||||
|
.layout
|
||||||
.undo_cane(&mut self.recorder, head)
|
.undo_cane(&mut self.recorder, head)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
} else {
|
} else {
|
||||||
|
|
|
||||||
|
|
@ -53,12 +53,9 @@ impl<'a, R: AccessRules> Navcorder<'a, R> {
|
||||||
target: FixedDotIndex,
|
target: FixedDotIndex,
|
||||||
width: f64,
|
width: f64,
|
||||||
) -> Result<BandTermsegIndex, NavcorderException> {
|
) -> Result<BandTermsegIndex, NavcorderException> {
|
||||||
Ok(Draw::new(self.layout).finish_in_dot(
|
Ok(self
|
||||||
&mut navcord.recorder,
|
.layout
|
||||||
navcord.head,
|
.finish_in_dot(&mut navcord.recorder, navcord.head, target, width)?)
|
||||||
target,
|
|
||||||
width,
|
|
||||||
)?)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[debug_requires(path[0] == navcord.path[0])]
|
#[debug_requires(path[0] == navcord.path[0])]
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue