refactor: replace multiple custom Recording* structures with single generic Recording<'a, T> struct

This commit is contained in:
Alain Emilia Anna Zscheile 2025-01-03 05:17:16 +01:00
parent 26631ed6cd
commit a911c0cddf
12 changed files with 379 additions and 283 deletions

View File

@ -12,6 +12,7 @@ use thiserror::Error;
use crate::{ use crate::{
board::{mesadata::AccessMesadata, Board}, board::{mesadata::AccessMesadata, Board},
drawing::{band::BandTermsegIndex, dot::FixedDotIndex, Infringement}, drawing::{band::BandTermsegIndex, dot::FixedDotIndex, Infringement},
geometry::edit::Recordable,
layout::{via::ViaWeight, LayoutEdit}, layout::{via::ViaWeight, LayoutEdit},
router::{astar::AstarError, navmesh::NavmeshError, RouterOptions}, router::{astar::AstarError, navmesh::NavmeshError, RouterOptions},
triangulation::GetTrianvertexNodeIndex, triangulation::GetTrianvertexNodeIndex,

View File

@ -9,7 +9,7 @@
use crate::{ use crate::{
board::mesadata::AccessMesadata, board::mesadata::AccessMesadata,
drawing::graph::PrimitiveIndex, drawing::graph::PrimitiveIndex,
geometry::primitive::PrimitiveShape, geometry::{edit::Recordable, primitive::PrimitiveShape},
layout::{via::ViaWeight, LayoutEdit}, layout::{via::ViaWeight, LayoutEdit},
router::{navcord::NavcordStepper, navmesh::Navmesh}, router::{navcord::NavcordStepper, navmesh::Navmesh},
}; };

View File

@ -7,7 +7,7 @@
use crate::{ use crate::{
board::mesadata::AccessMesadata, board::mesadata::AccessMesadata,
drawing::graph::PrimitiveIndex, drawing::graph::PrimitiveIndex,
geometry::primitive::PrimitiveShape, geometry::{edit::Recordable, primitive::PrimitiveShape},
layout::LayoutEdit, layout::LayoutEdit,
router::{navcord::NavcordStepper, navmesh::Navmesh}, router::{navcord::NavcordStepper, navmesh::Navmesh},
}; };

View File

@ -25,7 +25,11 @@ use crate::{
graph::{GetLayer, GetMaybeNet, PrimitiveIndex, PrimitiveWeight}, graph::{GetLayer, GetMaybeNet, PrimitiveIndex, PrimitiveWeight},
seg::{FixedSegIndex, FixedSegWeight, SegIndex, SegWeight}, seg::{FixedSegIndex, FixedSegWeight, SegIndex, SegWeight},
}, },
geometry::{edit::ApplyGeometryEdit, shape::AccessShape, GenericNode}, geometry::{
edit::{ApplyGeometryEdit, Recordable},
shape::AccessShape,
GenericNode,
},
graph::GenericIndex, graph::GenericIndex,
layout::{ layout::{
poly::{GetMaybeApex, MakePolyShape, PolyWeight}, poly::{GetMaybeApex, MakePolyShape, PolyWeight},

View File

@ -12,11 +12,9 @@ use thiserror::Error;
use crate::geometry::{ use crate::geometry::{
compound::ManageCompounds, compound::ManageCompounds,
edit::{ApplyGeometryEdit, GeometryEdit}, edit::{ApplyGeometryEdit, GeometryEdit, Recordable, Recording},
primitive::{AccessPrimitiveShape, PrimitiveShape}, primitive::{AccessPrimitiveShape, PrimitiveShape},
recording_with_rtree::RecordingGeometryWithRtree, with_rtree::{BboxedIndex, GeometryWithRtree},
with_rtree::BboxedIndex,
with_rtree::GeometryWithRtree,
AccessBendWeight, AccessDotWeight, AccessSegWeight, GenericNode, Geometry, GeometryLabel, AccessBendWeight, AccessDotWeight, AccessSegWeight, GenericNode, Geometry, GeometryLabel,
GetOffset, GetPos, GetWidth, GetOffset, GetPos, GetWidth,
}; };
@ -100,12 +98,18 @@ pub struct Drawing<CW, R> {
rules: R, rules: R,
} }
pub struct RecordingDrawing<'a, CW, R> { impl<CW: Copy, R> Recordable for Drawing<CW, R> {
pub drawing: &'a mut Drawing<CW, R>, type PW = PrimitiveWeight;
pub recorder: &'a mut DrawingEdit<CW>, type DW = DotWeight;
type SW = SegWeight;
type BW = BendWeight;
type CW = CW;
type PI = PrimitiveIndex;
type DI = DotIndex;
type SI = SegIndex;
type BI = BendIndex;
} }
#[debug_invariant(self.test_if_looses_dont_infringe_each_other())]
impl<CW: Copy, R: AccessRules> Drawing<CW, R> { impl<CW: Copy, R: AccessRules> Drawing<CW, R> {
pub fn new(rules: R, layer_count: usize) -> Self { pub fn new(rules: R, layer_count: usize) -> Self {
Self { Self {
@ -114,17 +118,6 @@ impl<CW: Copy, R: AccessRules> Drawing<CW, R> {
} }
} }
#[inline(always)]
pub fn recording<'a>(
&'a mut self,
recorder: &'a mut DrawingEdit<CW>,
) -> RecordingDrawing<'a, CW, R> {
RecordingDrawing {
drawing: self,
recorder,
}
}
#[inline(always)] #[inline(always)]
fn graph( fn graph(
&self, &self,
@ -317,6 +310,8 @@ impl<CW: Copy, R: AccessRules> Drawing<CW, R> {
self.geometry_with_rtree.graph().node_count() self.geometry_with_rtree.graph().node_count()
} }
// used for constraints checking on nightly Rust
#[allow(unused)]
fn test_if_looses_dont_infringe_each_other(&self) -> bool { fn test_if_looses_dont_infringe_each_other(&self) -> bool {
!self !self
.primitive_nodes() .primitive_nodes()
@ -359,24 +354,33 @@ impl<CW: Copy, R: AccessRules> Drawing<CW, R> {
} }
} }
impl<CW: Copy, R: AccessRules> RecordingDrawing<'_, CW, R> { impl<CW: Copy, R: AccessRules> Recording<'_, Drawing<CW, R>> {
fn recording_geometry_with_rtree( fn recording_geometry_with_rtree(
&mut self, &mut self,
) -> RecordingGeometryWithRtree< ) -> Recording<
'_, '_,
PrimitiveWeight, GeometryWithRtree<
DotWeight, PrimitiveWeight,
SegWeight, DotWeight,
BendWeight, SegWeight,
CW, BendWeight,
PrimitiveIndex, CW,
DotIndex, PrimitiveIndex,
SegIndex, DotIndex,
BendIndex, SegIndex,
BendIndex,
>,
> { > {
self.drawing.geometry_with_rtree.recording(self.recorder) self.inner.geometry_with_rtree.recording(self.recorder)
} }
pub fn rules_mut(&mut self) -> &mut R {
&mut self.inner.rules
}
}
#[debug_invariant(self.inner.test_if_looses_dont_infringe_each_other())]
impl<CW: Copy, R: AccessRules> Recording<'_, Drawing<CW, R>> {
pub fn remove_band(&mut self, band: BandTermsegIndex) -> Result<(), DrawingException> { pub fn remove_band(&mut self, band: BandTermsegIndex) -> Result<(), DrawingException> {
match band { match band {
BandTermsegIndex::Straight(seg) => { BandTermsegIndex::Straight(seg) => {
@ -406,16 +410,16 @@ impl<CW: Copy, R: AccessRules> RecordingDrawing<'_, CW, R> {
LooseIndex::Bend(bend) => { LooseIndex::Bend(bend) => {
bends.push(bend); bends.push(bend);
if let Some(outer) = self.drawing.primitive(bend).outer() { if let Some(outer) = self.inner.primitive(bend).outer() {
outers.push(outer); outers.push(outer);
self.reattach_bend(outer, self.drawing.primitive(bend).inner()); self.reattach_bend(outer, self.inner.primitive(bend).inner());
} }
} }
} }
let prev_prev = prev; let prev_prev = prev;
prev = maybe_loose; prev = maybe_loose;
maybe_loose = self.drawing.loose(loose).next_loose(prev_prev); maybe_loose = self.inner.loose(loose).next_loose(prev_prev);
} }
for bend in bends { for bend in bends {
@ -443,27 +447,27 @@ impl<CW: Copy, R: AccessRules> RecordingDrawing<'_, CW, R> {
Ok(()) Ok(())
} }
#[debug_ensures(ret.is_ok() -> self.drawing.graph().node_count() == old(self.drawing.graph().node_count() + 1))] #[debug_ensures(ret.is_ok() -> self.inner.graph().node_count() == old(self.inner.graph().node_count() + 1))]
#[debug_ensures(ret.is_err() -> self.drawing.graph().node_count() == old(self.drawing.graph().node_count()))] #[debug_ensures(ret.is_err() -> self.inner.graph().node_count() == old(self.inner.graph().node_count()))]
#[debug_ensures(self.drawing.graph().edge_count() == old(self.drawing.graph().edge_count()))] #[debug_ensures(self.inner.graph().edge_count() == old(self.inner.graph().edge_count()))]
pub fn add_fixed_dot(&mut self, weight: FixedDotWeight) -> Result<FixedDotIndex, Infringement> { pub fn add_fixed_dot(&mut self, weight: FixedDotWeight) -> Result<FixedDotIndex, Infringement> {
self.add_dot_with_infringables(weight, Some(&[])) self.add_dot_with_infringables(weight, Some(&[]))
} }
#[debug_ensures(self.drawing.graph().node_count() == old(self.drawing.graph().node_count() - 1))] #[debug_ensures(self.inner.graph().node_count() == old(self.inner.graph().node_count() - 1))]
#[debug_ensures(self.drawing.graph().edge_count() == old(self.drawing.graph().edge_count()))] #[debug_ensures(self.inner.graph().edge_count() == old(self.inner.graph().edge_count()))]
pub fn remove_fixed_dot(&mut self, dot: FixedDotIndex) { pub fn remove_fixed_dot(&mut self, dot: FixedDotIndex) {
self.recording_geometry_with_rtree().remove_dot(dot.into()); self.recording_geometry_with_rtree().remove_dot(dot.into());
} }
#[debug_ensures(self.drawing.graph().node_count() == old(self.drawing.graph().node_count() + 1))] #[debug_ensures(self.inner.graph().node_count() == old(self.inner.graph().node_count() + 1))]
#[debug_ensures(self.drawing.graph().edge_count() == old(self.drawing.graph().edge_count()))] #[debug_ensures(self.inner.graph().edge_count() == old(self.inner.graph().edge_count()))]
pub fn add_fixed_dot_infringably(&mut self, weight: FixedDotWeight) -> FixedDotIndex { pub fn add_fixed_dot_infringably(&mut self, weight: FixedDotWeight) -> FixedDotIndex {
self.add_dot_infringably(weight) self.add_dot_infringably(weight)
} }
#[debug_ensures(ret.is_ok() -> self.drawing.graph().node_count() == old(self.drawing.graph().node_count() + 1))] #[debug_ensures(ret.is_ok() -> self.inner.graph().node_count() == old(self.inner.graph().node_count() + 1))]
#[debug_ensures(ret.is_err() -> self.drawing.graph().node_count() == old(self.drawing.graph().node_count()))] #[debug_ensures(ret.is_err() -> self.inner.graph().node_count() == old(self.inner.graph().node_count()))]
fn add_dot_with_infringables<W: AccessDotWeight<PrimitiveWeight> + GetLayer>( fn add_dot_with_infringables<W: AccessDotWeight<PrimitiveWeight> + GetLayer>(
&mut self, &mut self,
weight: W, weight: W,
@ -478,9 +482,9 @@ impl<CW: Copy, R: AccessRules> RecordingDrawing<'_, CW, R> {
Ok(dot) Ok(dot)
} }
#[debug_ensures(ret.is_ok() -> self.drawing.graph().node_count() == old(self.drawing.graph().node_count() + 1))] #[debug_ensures(ret.is_ok() -> self.inner.graph().node_count() == old(self.inner.graph().node_count() + 1))]
#[debug_ensures(ret.is_err() -> self.drawing.graph().node_count() == old(self.drawing.graph().node_count()))] #[debug_ensures(ret.is_err() -> self.inner.graph().node_count() == old(self.inner.graph().node_count()))]
#[debug_ensures(self.drawing.graph().edge_count() == old(self.drawing.graph().edge_count()))] #[debug_ensures(self.inner.graph().edge_count() == old(self.inner.graph().edge_count()))]
pub fn add_fixed_seg( pub fn add_fixed_seg(
&mut self, &mut self,
from: FixedDotIndex, from: FixedDotIndex,
@ -490,8 +494,8 @@ impl<CW: Copy, R: AccessRules> RecordingDrawing<'_, CW, R> {
self.add_seg_with_infringables(from.into(), to.into(), weight, Some(&[])) self.add_seg_with_infringables(from.into(), to.into(), weight, Some(&[]))
} }
#[debug_ensures(self.drawing.graph().node_count() == old(self.drawing.graph().node_count() + 1))] #[debug_ensures(self.inner.graph().node_count() == old(self.inner.graph().node_count() + 1))]
#[debug_ensures(self.drawing.graph().edge_count() == old(self.drawing.graph().edge_count() + 2))] #[debug_ensures(self.inner.graph().edge_count() == old(self.inner.graph().edge_count() + 2))]
pub fn add_fixed_seg_infringably( pub fn add_fixed_seg_infringably(
&mut self, &mut self,
from: FixedDotIndex, from: FixedDotIndex,
@ -501,10 +505,10 @@ impl<CW: Copy, R: AccessRules> RecordingDrawing<'_, CW, R> {
self.add_seg_infringably(from.into(), to.into(), weight) self.add_seg_infringably(from.into(), to.into(), weight)
} }
#[debug_ensures(ret.is_ok() -> self.drawing.graph().node_count() == old(self.drawing.graph().node_count() + 1))] #[debug_ensures(ret.is_ok() -> self.inner.graph().node_count() == old(self.inner.graph().node_count() + 1))]
#[debug_ensures(ret.is_ok() -> self.drawing.graph().edge_count() == old(self.drawing.graph().edge_count() + 2))] #[debug_ensures(ret.is_ok() -> self.inner.graph().edge_count() == old(self.inner.graph().edge_count() + 2))]
#[debug_ensures(ret.is_err() -> self.drawing.graph().node_count() == old(self.drawing.graph().node_count()))] #[debug_ensures(ret.is_err() -> self.inner.graph().node_count() == old(self.inner.graph().node_count()))]
#[debug_ensures(ret.is_err() -> self.drawing.graph().edge_count() == old(self.drawing.graph().edge_count()))] #[debug_ensures(ret.is_err() -> self.inner.graph().edge_count() == old(self.inner.graph().edge_count()))]
pub fn add_lone_loose_seg( pub fn add_lone_loose_seg(
&mut self, &mut self,
from: FixedDotIndex, from: FixedDotIndex,
@ -515,10 +519,10 @@ impl<CW: Copy, R: AccessRules> RecordingDrawing<'_, CW, R> {
Ok(seg) Ok(seg)
} }
#[debug_ensures(ret.is_ok() -> self.drawing.graph().node_count() == old(self.drawing.graph().node_count() + 1))] #[debug_ensures(ret.is_ok() -> self.inner.graph().node_count() == old(self.inner.graph().node_count() + 1))]
#[debug_ensures(ret.is_ok() -> self.drawing.graph().edge_count() == old(self.drawing.graph().edge_count() + 2))] #[debug_ensures(ret.is_ok() -> self.inner.graph().edge_count() == old(self.inner.graph().edge_count() + 2))]
#[debug_ensures(ret.is_err() -> self.drawing.graph().node_count() == old(self.drawing.graph().node_count()))] #[debug_ensures(ret.is_err() -> self.inner.graph().node_count() == old(self.inner.graph().node_count()))]
#[debug_ensures(ret.is_err() -> self.drawing.graph().edge_count() == old(self.drawing.graph().edge_count()))] #[debug_ensures(ret.is_err() -> self.inner.graph().edge_count() == old(self.inner.graph().edge_count()))]
pub fn add_seq_loose_seg( pub fn add_seq_loose_seg(
&mut self, &mut self,
from: DotIndex, from: DotIndex,
@ -529,10 +533,10 @@ impl<CW: Copy, R: AccessRules> RecordingDrawing<'_, CW, R> {
Ok(seg) Ok(seg)
} }
#[debug_ensures(ret.is_ok() -> self.drawing.graph().node_count() == old(self.drawing.graph().node_count() + 1))] #[debug_ensures(ret.is_ok() -> self.inner.graph().node_count() == old(self.inner.graph().node_count() + 1))]
#[debug_ensures(ret.is_ok() -> self.drawing.graph().edge_count() >= old(self.drawing.graph().edge_count() + 2))] #[debug_ensures(ret.is_ok() -> self.inner.graph().edge_count() >= old(self.inner.graph().edge_count() + 2))]
#[debug_ensures(ret.is_err() -> self.drawing.graph().node_count() == old(self.drawing.graph().node_count()))] #[debug_ensures(ret.is_err() -> self.inner.graph().node_count() == old(self.inner.graph().node_count()))]
#[debug_ensures(ret.is_err() -> self.drawing.graph().edge_count() == old(self.drawing.graph().edge_count()))] #[debug_ensures(ret.is_err() -> self.inner.graph().edge_count() == old(self.inner.graph().edge_count()))]
fn add_seg_with_infringables<W: AccessSegWeight<PrimitiveWeight> + GetLayer>( fn add_seg_with_infringables<W: AccessSegWeight<PrimitiveWeight> + GetLayer>(
&mut self, &mut self,
from: DotIndex, from: DotIndex,
@ -549,11 +553,11 @@ impl<CW: Copy, R: AccessRules> RecordingDrawing<'_, CW, R> {
Ok(seg) Ok(seg)
} }
#[debug_ensures(ret.is_ok() -> self.drawing.graph().node_count() == old(self.drawing.graph().node_count() + 1))] #[debug_ensures(ret.is_ok() -> self.inner.graph().node_count() == old(self.inner.graph().node_count() + 1))]
#[debug_ensures(ret.is_ok() -> self.drawing.graph().edge_count() == old(self.drawing.graph().edge_count() + 3) #[debug_ensures(ret.is_ok() -> self.inner.graph().edge_count() == old(self.inner.graph().edge_count() + 3)
|| self.drawing.graph().edge_count() == old(self.drawing.graph().edge_count() + 4))] || self.inner.graph().edge_count() == old(self.inner.graph().edge_count() + 4))]
#[debug_ensures(ret.is_err() -> self.drawing.graph().node_count() == old(self.drawing.graph().node_count()))] #[debug_ensures(ret.is_err() -> self.inner.graph().node_count() == old(self.inner.graph().node_count()))]
#[debug_ensures(ret.is_err() -> self.drawing.graph().edge_count() == old(self.drawing.graph().edge_count()))] #[debug_ensures(ret.is_err() -> self.inner.graph().edge_count() == old(self.inner.graph().edge_count()))]
fn add_loose_bend_with_infringables( fn add_loose_bend_with_infringables(
&mut self, &mut self,
from: LooseDotIndex, from: LooseDotIndex,
@ -565,14 +569,14 @@ impl<CW: Copy, R: AccessRules> RecordingDrawing<'_, CW, R> {
// It makes no sense to wrap something around or under one of its connectables. // It makes no sense to wrap something around or under one of its connectables.
// //
if let Some(net) = weight.maybe_net { if let Some(net) = weight.maybe_net {
if let Some(around_net) = around.primitive(self.drawing).maybe_net() { if let Some(around_net) = around.primitive(self.inner).maybe_net() {
if net == around_net { if net == around_net {
return Err(AlreadyConnected(net, around.into()).into()); return Err(AlreadyConnected(net, around.into()).into());
} }
} }
// //
if let Some(next_gear) = around.ref_(self.drawing).next_gear() { if let Some(next_gear) = around.ref_(self.inner).next_gear() {
if let Some(next_gear_net) = next_gear.primitive(self.drawing).maybe_net() { if let Some(next_gear_net) = next_gear.primitive(self.inner).maybe_net() {
if net == next_gear_net { if net == next_gear_net {
return Err(AlreadyConnected(net, next_gear.into()).into()); return Err(AlreadyConnected(net, next_gear.into()).into());
} }
@ -593,10 +597,10 @@ impl<CW: Copy, R: AccessRules> RecordingDrawing<'_, CW, R> {
} }
} }
#[debug_ensures(ret.is_ok() -> self.drawing.graph().node_count() == old(self.drawing.graph().node_count() + 1))] #[debug_ensures(ret.is_ok() -> self.inner.graph().node_count() == old(self.inner.graph().node_count() + 1))]
#[debug_ensures(ret.is_err() -> self.drawing.graph().node_count() == old(self.drawing.graph().node_count()))] #[debug_ensures(ret.is_err() -> self.inner.graph().node_count() == old(self.inner.graph().node_count()))]
#[debug_ensures(ret.is_ok() -> self.drawing.graph().edge_count() == old(self.drawing.graph().edge_count() + 3))] #[debug_ensures(ret.is_ok() -> self.inner.graph().edge_count() == old(self.inner.graph().edge_count() + 3))]
#[debug_ensures(ret.is_err() -> self.drawing.graph().edge_count() == old(self.drawing.graph().edge_count()))] #[debug_ensures(ret.is_err() -> self.inner.graph().edge_count() == old(self.inner.graph().edge_count()))]
fn add_core_bend_with_infringables<W: AccessBendWeight<PrimitiveWeight> + GetLayer>( fn add_core_bend_with_infringables<W: AccessBendWeight<PrimitiveWeight> + GetLayer>(
&mut self, &mut self,
from: DotIndex, from: DotIndex,
@ -616,10 +620,10 @@ impl<CW: Copy, R: AccessRules> RecordingDrawing<'_, CW, R> {
Ok(bend) Ok(bend)
} }
#[debug_ensures(ret.is_ok() -> self.drawing.graph().node_count() == old(self.drawing.graph().node_count() + 1))] #[debug_ensures(ret.is_ok() -> self.inner.graph().node_count() == old(self.inner.graph().node_count() + 1))]
#[debug_ensures(ret.is_err() -> self.drawing.graph().node_count() == old(self.drawing.graph().node_count()))] #[debug_ensures(ret.is_err() -> self.inner.graph().node_count() == old(self.inner.graph().node_count()))]
#[debug_ensures(ret.is_ok() -> self.drawing.graph().edge_count() == old(self.drawing.graph().edge_count() + 4))] #[debug_ensures(ret.is_ok() -> self.inner.graph().edge_count() == old(self.inner.graph().edge_count() + 4))]
#[debug_ensures(ret.is_err() -> self.drawing.graph().edge_count() == old(self.drawing.graph().edge_count()))] #[debug_ensures(ret.is_err() -> self.inner.graph().edge_count() == old(self.inner.graph().edge_count()))]
fn add_outer_bend_with_infringables( fn add_outer_bend_with_infringables(
&mut self, &mut self,
from: LooseDotIndex, from: LooseDotIndex,
@ -629,15 +633,15 @@ impl<CW: Copy, R: AccessRules> RecordingDrawing<'_, CW, R> {
infringables: Option<&[PrimitiveIndex]>, infringables: Option<&[PrimitiveIndex]>,
) -> Result<GenericIndex<LooseBendWeight>, Infringement> { ) -> Result<GenericIndex<LooseBendWeight>, Infringement> {
let core = *self let core = *self
.drawing .inner
.graph() .graph()
.neighbors(inner.petgraph_index()) .neighbors(inner.petgraph_index())
.filter(|ni| { .filter(|ni| {
matches!( matches!(
self.drawing self.inner
.graph() .graph()
.edge_weight( .edge_weight(
self.drawing self.inner
.graph() .graph()
.find_edge(inner.petgraph_index(), *ni) .find_edge(inner.petgraph_index(), *ni)
.unwrap() .unwrap()
@ -664,25 +668,25 @@ impl<CW: Copy, R: AccessRules> RecordingDrawing<'_, CW, R> {
Ok(bend) Ok(bend)
} }
#[debug_ensures(self.drawing.graph().node_count() == old(self.drawing.graph().node_count()))] #[debug_ensures(self.inner.graph().node_count() == old(self.inner.graph().node_count()))]
#[debug_ensures(self.drawing.graph().edge_count() == old(self.drawing.graph().edge_count()))] #[debug_ensures(self.inner.graph().edge_count() == old(self.inner.graph().edge_count()))]
pub fn flip_bend(&mut self, bend: FixedBendIndex) { pub fn flip_bend(&mut self, bend: FixedBendIndex) {
self.recording_geometry_with_rtree().flip_bend(bend.into()); self.recording_geometry_with_rtree().flip_bend(bend.into());
} }
#[debug_ensures(self.drawing.graph().node_count() == old(self.drawing.graph().node_count()))] #[debug_ensures(self.inner.graph().node_count() == old(self.inner.graph().node_count()))]
#[debug_ensures(self.drawing.graph().edge_count() == old(self.drawing.graph().edge_count()) #[debug_ensures(self.inner.graph().edge_count() == old(self.inner.graph().edge_count())
|| self.drawing.graph().edge_count() == old(self.drawing.graph().edge_count() - 1) || self.inner.graph().edge_count() == old(self.inner.graph().edge_count() - 1)
|| self.drawing.graph().edge_count() == old(self.drawing.graph().edge_count() + 1))] || self.inner.graph().edge_count() == old(self.inner.graph().edge_count() + 1))]
fn reattach_bend(&mut self, bend: LooseBendIndex, maybe_new_inner: Option<LooseBendIndex>) { fn reattach_bend(&mut self, bend: LooseBendIndex, maybe_new_inner: Option<LooseBendIndex>) {
self.recording_geometry_with_rtree() self.recording_geometry_with_rtree()
.reattach_bend(bend.into(), maybe_new_inner.map(Into::into)); .reattach_bend(bend.into(), maybe_new_inner.map(Into::into));
} }
#[debug_ensures(ret.is_ok() -> self.drawing.graph().node_count() == old(self.drawing.graph().node_count() + 4))] #[debug_ensures(ret.is_ok() -> self.inner.graph().node_count() == old(self.inner.graph().node_count() + 4))]
#[debug_ensures(ret.is_ok() -> self.drawing.graph().edge_count() >= old(self.drawing.graph().edge_count() + 5))] #[debug_ensures(ret.is_ok() -> self.inner.graph().edge_count() >= old(self.inner.graph().edge_count() + 5))]
#[debug_ensures(ret.is_err() -> self.drawing.graph().node_count() == old(self.drawing.graph().node_count()))] #[debug_ensures(ret.is_err() -> self.inner.graph().node_count() == old(self.inner.graph().node_count()))]
#[debug_ensures(ret.is_err() -> self.drawing.graph().edge_count() == old(self.drawing.graph().edge_count()))] #[debug_ensures(ret.is_err() -> self.inner.graph().edge_count() == old(self.inner.graph().edge_count()))]
pub fn insert_cane( pub fn insert_cane(
&mut self, &mut self,
from: DotIndex, from: DotIndex,
@ -692,7 +696,7 @@ impl<CW: Copy, R: AccessRules> RecordingDrawing<'_, CW, R> {
bend_weight: LooseBendWeight, bend_weight: LooseBendWeight,
cw: bool, cw: bool,
) -> Result<Cane, DrawingException> { ) -> Result<Cane, DrawingException> {
let maybe_next_gear = around.ref_(self.drawing).next_gear(); let maybe_next_gear = around.ref_(self.inner).next_gear();
let cane = self.add_cane_with_infringables( let cane = self.add_cane_with_infringables(
from, from,
around, around,
@ -707,16 +711,16 @@ impl<CW: Copy, R: AccessRules> RecordingDrawing<'_, CW, R> {
self.reattach_bend(next_gear, Some(cane.bend)); self.reattach_bend(next_gear, Some(cane.bend));
} }
if let Some(outer) = self.drawing.primitive(cane.bend).outer() { if let Some(outer) = self.inner.primitive(cane.bend).outer() {
self.update_this_and_outward_bows(outer).inspect_err(|_| { self.update_this_and_outward_bows(outer).inspect_err(|_| {
let joint = self.drawing.primitive(cane.bend).other_joint(cane.dot); let joint = self.inner.primitive(cane.bend).other_joint(cane.dot);
self.remove_cane(&cane, joint); self.remove_cane(&cane, joint);
})?; })?;
} }
// Segs must not cross. // Segs must not cross.
if let Some(collision) = self.drawing.detect_collision(cane.seg.into()) { if let Some(collision) = self.inner.detect_collision(cane.seg.into()) {
let joint = self.drawing.primitive(cane.bend).other_joint(cane.dot); let joint = self.inner.primitive(cane.bend).other_joint(cane.dot);
self.remove_cane(&cane, joint); self.remove_cane(&cane, joint);
Err(collision.into()) Err(collision.into())
} else { } else {
@ -724,8 +728,8 @@ impl<CW: Copy, R: AccessRules> RecordingDrawing<'_, CW, R> {
} }
} }
#[debug_ensures(self.drawing.graph().node_count() == old(self.drawing.graph().node_count()))] #[debug_ensures(self.inner.graph().node_count() == old(self.inner.graph().node_count()))]
#[debug_ensures(self.drawing.graph().edge_count() == old(self.drawing.graph().edge_count()))] #[debug_ensures(self.inner.graph().edge_count() == old(self.inner.graph().edge_count()))]
fn update_this_and_outward_bows( fn update_this_and_outward_bows(
&mut self, &mut self,
around: LooseBendIndex, around: LooseBendIndex,
@ -734,10 +738,10 @@ impl<CW: Copy, R: AccessRules> RecordingDrawing<'_, CW, R> {
let mut maybe_rail = Some(around); let mut maybe_rail = Some(around);
while let Some(rail) = maybe_rail { while let Some(rail) = maybe_rail {
let rail_primitive = self.drawing.primitive(rail); let rail_primitive = self.inner.primitive(rail);
let joints = rail_primitive.joints(); let joints = rail_primitive.joints();
let guide = Guide::new(self.drawing); let guide = Guide::new(self.inner);
let from_head = guide.rear_head(joints.1); let from_head = guide.rear_head(joints.1);
let to_head = guide.rear_head(joints.0); let to_head = guide.rear_head(joints.0);
@ -747,7 +751,7 @@ impl<CW: Copy, R: AccessRules> RecordingDrawing<'_, CW, R> {
&from_head, &from_head,
inner.into(), inner.into(),
true, true,
self.drawing.primitive(rail).width(), self.inner.primitive(rail).width(),
)? )?
.end_point(); .end_point();
let to = guide let to = guide
@ -755,30 +759,30 @@ impl<CW: Copy, R: AccessRules> RecordingDrawing<'_, CW, R> {
&to_head, &to_head,
inner.into(), inner.into(),
false, false,
self.drawing.primitive(rail).width(), self.inner.primitive(rail).width(),
)? )?
.end_point(); .end_point();
let offset = guide.head_around_bend_offset( let offset = guide.head_around_bend_offset(
&from_head, &from_head,
inner.into(), inner.into(),
self.drawing.primitive(rail).width(), self.inner.primitive(rail).width(),
); );
self.move_dot_with_infringables( self.move_dot_with_infringables(
joints.0.into(), joints.0.into(),
from, from,
Some(&self.drawing.collect().bend_outer_bows(rail)), Some(&self.inner.collect().bend_outer_bows(rail)),
)?; )?;
self.move_dot_with_infringables( self.move_dot_with_infringables(
joints.1.into(), joints.1.into(),
to, to,
Some(&self.drawing.collect().bend_outer_bows(rail)), Some(&self.inner.collect().bend_outer_bows(rail)),
)?; )?;
self.shift_bend_with_infringables( self.shift_bend_with_infringables(
rail.into(), rail.into(),
offset, offset,
Some(&self.drawing.collect().bend_outer_bows(rail)), Some(&self.inner.collect().bend_outer_bows(rail)),
)?; )?;
// Update offsets in case the rule conditions changed. // Update offsets in case the rule conditions changed.
@ -789,7 +793,7 @@ impl<CW: Copy, R: AccessRules> RecordingDrawing<'_, CW, R> {
&from_head, &from_head,
core.into(), core.into(),
true, true,
self.drawing.primitive(rail).width(), self.inner.primitive(rail).width(),
)? )?
.end_point(); .end_point();
let to = guide let to = guide
@ -797,43 +801,43 @@ impl<CW: Copy, R: AccessRules> RecordingDrawing<'_, CW, R> {
&to_head, &to_head,
core.into(), core.into(),
false, false,
self.drawing.primitive(rail).width(), self.inner.primitive(rail).width(),
)? )?
.end_point(); .end_point();
let offset = guide.head_around_dot_offset( let offset = guide.head_around_dot_offset(
&from_head, &from_head,
core.into(), core.into(),
self.drawing.primitive(rail).width(), self.inner.primitive(rail).width(),
); );
self.move_dot_with_infringables( self.move_dot_with_infringables(
joints.0.into(), joints.0.into(),
from, from,
Some(&self.drawing.collect().bend_outer_bows(rail)), Some(&self.inner.collect().bend_outer_bows(rail)),
)?; )?;
self.move_dot_with_infringables( self.move_dot_with_infringables(
joints.1.into(), joints.1.into(),
to, to,
Some(&self.drawing.collect().bend_outer_bows(rail)), Some(&self.inner.collect().bend_outer_bows(rail)),
)?; )?;
self.shift_bend_with_infringables( self.shift_bend_with_infringables(
rail.into(), rail.into(),
offset, offset,
Some(&self.drawing.collect().bend_outer_bows(rail)), Some(&self.inner.collect().bend_outer_bows(rail)),
)?; )?;
} }
maybe_rail = self.drawing.primitive(rail).outer(); maybe_rail = self.inner.primitive(rail).outer();
} }
Ok(()) Ok(())
} }
#[debug_ensures(ret.is_ok() -> self.drawing.graph().node_count() == old(self.drawing.graph().node_count() + 4))] #[debug_ensures(ret.is_ok() -> self.inner.graph().node_count() == old(self.inner.graph().node_count() + 4))]
#[debug_ensures(ret.is_ok() -> self.drawing.graph().edge_count() >= old(self.drawing.graph().edge_count() + 5))] #[debug_ensures(ret.is_ok() -> self.inner.graph().edge_count() >= old(self.inner.graph().edge_count() + 5))]
#[debug_ensures(ret.is_err() -> self.drawing.graph().node_count() == old(self.drawing.graph().node_count()))] #[debug_ensures(ret.is_err() -> self.inner.graph().node_count() == old(self.inner.graph().node_count()))]
#[debug_ensures(ret.is_err() -> self.drawing.graph().edge_count() == old(self.drawing.graph().edge_count()))] #[debug_ensures(ret.is_err() -> self.inner.graph().edge_count() == old(self.inner.graph().edge_count()))]
pub fn add_cane( pub fn add_cane(
&mut self, &mut self,
from: DotIndex, from: DotIndex,
@ -854,10 +858,10 @@ impl<CW: Copy, R: AccessRules> RecordingDrawing<'_, CW, R> {
) )
} }
#[debug_ensures(ret.is_ok() -> self.drawing.graph().node_count() == old(self.drawing.graph().node_count() + 4))] #[debug_ensures(ret.is_ok() -> self.inner.graph().node_count() == old(self.inner.graph().node_count() + 4))]
#[debug_ensures(ret.is_ok() -> self.drawing.graph().edge_count() >= old(self.drawing.graph().edge_count() + 5))] #[debug_ensures(ret.is_ok() -> self.inner.graph().edge_count() >= old(self.inner.graph().edge_count() + 5))]
#[debug_ensures(ret.is_err() -> self.drawing.graph().node_count() == old(self.drawing.graph().node_count()))] #[debug_ensures(ret.is_err() -> self.inner.graph().node_count() == old(self.inner.graph().node_count()))]
#[debug_ensures(ret.is_err() -> self.drawing.graph().edge_count() == old(self.drawing.graph().edge_count()))] #[debug_ensures(ret.is_err() -> self.inner.graph().edge_count() == old(self.inner.graph().edge_count()))]
fn add_cane_with_infringables( fn add_cane_with_infringables(
&mut self, &mut self,
from: DotIndex, from: DotIndex,
@ -902,13 +906,13 @@ impl<CW: Copy, R: AccessRules> RecordingDrawing<'_, CW, R> {
}) })
} }
#[debug_ensures(self.drawing.graph().node_count() == old(self.drawing.graph().node_count() - 4))] #[debug_ensures(self.inner.graph().node_count() == old(self.inner.graph().node_count() - 4))]
pub fn remove_cane(&mut self, cane: &Cane, face: LooseDotIndex) { pub fn remove_cane(&mut self, cane: &Cane, face: LooseDotIndex) {
let maybe_outer = self.drawing.primitive(cane.bend).outer(); let maybe_outer = self.inner.primitive(cane.bend).outer();
// Removing a loose bend affects its outer bends. // Removing a loose bend affects its outer bends.
if let Some(outer) = maybe_outer { if let Some(outer) = maybe_outer {
self.reattach_bend(outer, self.drawing.primitive(cane.bend).inner()); self.reattach_bend(outer, self.inner.primitive(cane.bend).inner());
} }
self.recording_geometry_with_rtree() self.recording_geometry_with_rtree()
@ -928,8 +932,8 @@ impl<CW: Copy, R: AccessRules> RecordingDrawing<'_, CW, R> {
} }
} }
#[debug_ensures(self.drawing.graph().node_count() == old(self.drawing.graph().node_count()))] #[debug_ensures(self.inner.graph().node_count() == old(self.inner.graph().node_count()))]
#[debug_ensures(self.drawing.graph().edge_count() == old(self.drawing.graph().edge_count()))] #[debug_ensures(self.inner.graph().edge_count() == old(self.inner.graph().edge_count()))]
pub fn move_dot(&mut self, dot: DotIndex, to: Point) -> Result<(), Infringement> { pub fn move_dot(&mut self, dot: DotIndex, to: Point) -> Result<(), Infringement> {
match dot { match dot {
DotIndex::Fixed(..) => self.move_dot_with_infringables(dot, to, Some(&[])), DotIndex::Fixed(..) => self.move_dot_with_infringables(dot, to, Some(&[])),
@ -937,20 +941,19 @@ impl<CW: Copy, R: AccessRules> RecordingDrawing<'_, CW, R> {
} }
} }
#[debug_ensures(self.drawing.graph().node_count() == old(self.drawing.graph().node_count()))] #[debug_ensures(self.inner.graph().node_count() == old(self.inner.graph().node_count()))]
#[debug_ensures(self.drawing.graph().edge_count() == old(self.drawing.graph().edge_count()))] #[debug_ensures(self.inner.graph().edge_count() == old(self.inner.graph().edge_count()))]
fn move_dot_with_infringables( fn move_dot_with_infringables(
&mut self, &mut self,
dot: DotIndex, dot: DotIndex,
to: Point, to: Point,
infringables: Option<&[PrimitiveIndex]>, infringables: Option<&[PrimitiveIndex]>,
) -> Result<(), Infringement> { ) -> Result<(), Infringement> {
let old_pos = self.drawing.geometry().dot_weight(dot).pos(); let old_pos = self.inner.geometry().dot_weight(dot).pos();
self.recording_geometry_with_rtree().move_dot(dot, to); self.recording_geometry_with_rtree().move_dot(dot, to);
for limb in dot.primitive(self.drawing).limbs() { for limb in dot.primitive(self.inner).limbs() {
if let Some(infringement) = self.drawing.detect_infringement_except(limb, infringables) if let Some(infringement) = self.inner.detect_infringement_except(limb, infringables) {
{
// Restore original state. // Restore original state.
self.recording_geometry_with_rtree().move_dot(dot, old_pos); self.recording_geometry_with_rtree().move_dot(dot, old_pos);
return Err(infringement); return Err(infringement);
@ -958,7 +961,7 @@ impl<CW: Copy, R: AccessRules> RecordingDrawing<'_, CW, R> {
} }
if let Some(infringement) = self if let Some(infringement) = self
.drawing .inner
.detect_infringement_except(dot.into(), infringables) .detect_infringement_except(dot.into(), infringables)
{ {
// Restore original state. // Restore original state.
@ -969,20 +972,20 @@ impl<CW: Copy, R: AccessRules> RecordingDrawing<'_, CW, R> {
Ok(()) Ok(())
} }
#[debug_ensures(self.drawing.graph().node_count() == old(self.drawing.graph().node_count()))] #[debug_ensures(self.inner.graph().node_count() == old(self.inner.graph().node_count()))]
#[debug_ensures(self.drawing.graph().edge_count() == old(self.drawing.graph().edge_count()))] #[debug_ensures(self.inner.graph().edge_count() == old(self.inner.graph().edge_count()))]
fn shift_bend_with_infringables( fn shift_bend_with_infringables(
&mut self, &mut self,
bend: BendIndex, bend: BendIndex,
offset: f64, offset: f64,
infringables: Option<&[PrimitiveIndex]>, infringables: Option<&[PrimitiveIndex]>,
) -> Result<(), Infringement> { ) -> Result<(), Infringement> {
let old_offset = self.drawing.geometry().bend_weight(bend).offset(); let old_offset = self.inner.geometry().bend_weight(bend).offset();
self.recording_geometry_with_rtree() self.recording_geometry_with_rtree()
.shift_bend(bend, offset); .shift_bend(bend, offset);
if let Some(infringement) = self if let Some(infringement) = self
.drawing .inner
.detect_infringement_except(bend.into(), infringables) .detect_infringement_except(bend.into(), infringables)
{ {
// Restore original state. // Restore original state.
@ -994,8 +997,8 @@ impl<CW: Copy, R: AccessRules> RecordingDrawing<'_, CW, R> {
Ok(()) Ok(())
} }
#[debug_ensures(self.drawing.graph().node_count() == old(self.drawing.graph().node_count() + 1))] #[debug_ensures(self.inner.graph().node_count() == old(self.inner.graph().node_count() + 1))]
#[debug_ensures(self.drawing.graph().edge_count() == old(self.drawing.graph().edge_count()))] #[debug_ensures(self.inner.graph().edge_count() == old(self.inner.graph().edge_count()))]
fn add_dot_infringably<W: AccessDotWeight<PrimitiveWeight> + GetLayer>( fn add_dot_infringably<W: AccessDotWeight<PrimitiveWeight> + GetLayer>(
&mut self, &mut self,
weight: W, weight: W,
@ -1006,8 +1009,8 @@ impl<CW: Copy, R: AccessRules> RecordingDrawing<'_, CW, R> {
self.recording_geometry_with_rtree().add_dot(weight) self.recording_geometry_with_rtree().add_dot(weight)
} }
#[debug_ensures(self.drawing.graph().node_count() == old(self.drawing.graph().node_count() + 1))] #[debug_ensures(self.inner.graph().node_count() == old(self.inner.graph().node_count() + 1))]
#[debug_ensures(self.drawing.graph().edge_count() == old(self.drawing.graph().edge_count() + 2))] #[debug_ensures(self.inner.graph().edge_count() == old(self.inner.graph().edge_count() + 2))]
fn add_seg_infringably<W: AccessSegWeight<PrimitiveWeight> + GetLayer>( fn add_seg_infringably<W: AccessSegWeight<PrimitiveWeight> + GetLayer>(
&mut self, &mut self,
from: DotIndex, from: DotIndex,
@ -1035,15 +1038,15 @@ impl<CW: Copy, R: AccessRules> RecordingDrawing<'_, CW, R> {
.add_to_compound(primitive, compound); .add_to_compound(primitive, compound);
} }
#[debug_ensures(ret.is_ok() -> self.drawing.graph().node_count() == old(self.drawing.graph().node_count()))] #[debug_ensures(ret.is_ok() -> self.inner.graph().node_count() == old(self.inner.graph().node_count()))]
#[debug_ensures(ret.is_ok() -> self.drawing.graph().edge_count() == old(self.drawing.graph().edge_count()))] #[debug_ensures(ret.is_ok() -> self.inner.graph().edge_count() == old(self.inner.graph().edge_count()))]
#[debug_ensures(ret.is_err() -> self.drawing.graph().node_count() == old(self.drawing.graph().node_count() - 1))] #[debug_ensures(ret.is_err() -> self.inner.graph().node_count() == old(self.inner.graph().node_count() - 1))]
fn fail_and_remove_if_infringes_except( fn fail_and_remove_if_infringes_except(
&mut self, &mut self,
node: PrimitiveIndex, node: PrimitiveIndex,
maybe_except: Option<&[PrimitiveIndex]>, maybe_except: Option<&[PrimitiveIndex]>,
) -> Result<(), Infringement> { ) -> Result<(), Infringement> {
if let Some(infringement) = self.drawing.detect_infringement_except(node, maybe_except) { if let Some(infringement) = self.inner.detect_infringement_except(node, maybe_except) {
let mut recording_geometry_with_rtree = self.recording_geometry_with_rtree(); let mut recording_geometry_with_rtree = self.recording_geometry_with_rtree();
if let Ok(dot) = node.try_into() { if let Ok(dot) = node.try_into() {
recording_geometry_with_rtree.remove_dot(dot); recording_geometry_with_rtree.remove_dot(dot);
@ -1056,10 +1059,6 @@ impl<CW: Copy, R: AccessRules> RecordingDrawing<'_, CW, R> {
} }
Ok(()) Ok(())
} }
pub fn rules_mut(&mut self) -> &mut R {
&mut self.drawing.rules
}
} }
impl<CW: Copy, R: AccessRules> impl<CW: Copy, R: AccessRules>
@ -1075,27 +1074,8 @@ impl<CW: Copy, R: AccessRules>
BendIndex, BendIndex,
> for Drawing<CW, R> > for Drawing<CW, R>
{ {
#[inline] #[inline(always)]
fn apply(&mut self, edit: &DrawingEdit<CW>) { fn apply(&mut self, edit: &DrawingEdit<CW>) {
self.geometry_with_rtree.apply(edit); self.geometry_with_rtree.apply(edit);
} }
} }
impl<CW: Copy, R: AccessRules>
ApplyGeometryEdit<
PrimitiveWeight,
DotWeight,
SegWeight,
BendWeight,
CW,
PrimitiveIndex,
DotIndex,
SegIndex,
BendIndex,
> for RecordingDrawing<'_, CW, R>
{
#[inline]
fn apply(&mut self, edit: &DrawingEdit<CW>) {
self.drawing.geometry_with_rtree.apply(edit);
}
}

View File

@ -2,6 +2,7 @@
// //
// SPDX-License-Identifier: MIT // SPDX-License-Identifier: MIT
use core::fmt;
use std::{collections::HashMap, hash::Hash, marker::PhantomData}; use std::{collections::HashMap, hash::Hash, marker::PhantomData};
use crate::{ use crate::{
@ -87,3 +88,142 @@ impl<
} }
} }
} }
pub trait Recordable {
type PW: GetWidth
+ GetLayer
+ TryInto<Self::DW>
+ TryInto<Self::SW>
+ TryInto<Self::BW>
+ Retag<Self::PI>
+ Copy;
type DW: AccessDotWeight<Self::PW> + GetLayer;
type SW: AccessSegWeight<Self::PW> + GetLayer;
type BW: AccessBendWeight<Self::PW> + GetLayer;
type CW: Copy;
type PI: GetPetgraphIndex
+ TryInto<Self::DI>
+ TryInto<Self::SI>
+ TryInto<Self::BI>
+ Copy
+ Eq
+ Hash;
type DI: GetPetgraphIndex + Into<Self::PI> + Copy + Eq + Hash;
type SI: GetPetgraphIndex + Into<Self::PI> + Copy + Eq + Hash;
type BI: GetPetgraphIndex + Into<Self::PI> + Copy + Eq + Hash;
#[inline(always)]
fn recording<'a>(
&'a mut self,
recorder: &'a mut GeometryEdit<
Self::PW,
Self::DW,
Self::SW,
Self::BW,
Self::CW,
Self::PI,
Self::DI,
Self::SI,
Self::BI,
>,
) -> Recording<'a, Self> {
Recording {
inner: self,
recorder,
}
}
}
pub type RecordingEdit<T: Recordable + ?Sized> = GeometryEdit<
<T as Recordable>::PW,
<T as Recordable>::DW,
<T as Recordable>::SW,
<T as Recordable>::BW,
<T as Recordable>::CW,
<T as Recordable>::PI,
<T as Recordable>::DI,
<T as Recordable>::SI,
<T as Recordable>::BI,
>;
pub struct Recording<'a, T: Recordable + ?Sized> {
pub inner: &'a mut T,
pub recorder: &'a mut RecordingEdit<T>,
}
impl<'a, T> fmt::Debug for Recording<'a, T>
where
T: Recordable + fmt::Debug + ?Sized,
<T as Recordable>::PW: fmt::Debug,
<T as Recordable>::DW: fmt::Debug,
<T as Recordable>::SW: fmt::Debug,
<T as Recordable>::BW: fmt::Debug,
<T as Recordable>::CW: fmt::Debug,
<T as Recordable>::PI: fmt::Debug,
<T as Recordable>::DI: fmt::Debug,
<T as Recordable>::SI: fmt::Debug,
<T as Recordable>::BI: fmt::Debug,
{
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("Recording")
.field("inner", &self.inner)
.field("recorder", &self.recorder)
.finish()
}
}
// this is a hack, but it allows us to not needing as much boilerplate for delegations
impl<'a, T: Recordable + ?Sized> core::ops::Deref for Recording<'a, T> {
type Target = T;
#[inline(always)]
fn deref(&self) -> &T {
self.inner
}
}
impl<'a, T>
ApplyGeometryEdit<
<T as Recordable>::PW,
<T as Recordable>::DW,
<T as Recordable>::SW,
<T as Recordable>::BW,
<T as Recordable>::CW,
<T as Recordable>::PI,
<T as Recordable>::DI,
<T as Recordable>::SI,
<T as Recordable>::BI,
> for Recording<'a, T>
where
T: Recordable
+ ?Sized
+ ApplyGeometryEdit<
<T as Recordable>::PW,
<T as Recordable>::DW,
<T as Recordable>::SW,
<T as Recordable>::BW,
<T as Recordable>::CW,
<T as Recordable>::PI,
<T as Recordable>::DI,
<T as Recordable>::SI,
<T as Recordable>::BI,
>,
{
#[inline(always)]
fn apply(
&mut self,
edit: &GeometryEdit<
<T as Recordable>::PW,
<T as Recordable>::DW,
<T as Recordable>::SW,
<T as Recordable>::BW,
<T as Recordable>::CW,
<T as Recordable>::PI,
<T as Recordable>::DI,
<T as Recordable>::SI,
<T as Recordable>::BI,
>,
) {
self.inner.apply(edit)
}
}

View File

@ -16,18 +16,12 @@ use crate::{
use super::{ use super::{
compound::ManageCompounds, compound::ManageCompounds,
edit::{ApplyGeometryEdit, GeometryEdit}, edit::{GeometryEdit, Recording},
with_rtree::{BboxedIndex, GeometryWithRtree}, with_rtree::{BboxedIndex, GeometryWithRtree},
AccessBendWeight, AccessDotWeight, AccessSegWeight, GenericNode, Geometry, GeometryLabel, AccessBendWeight, AccessDotWeight, AccessSegWeight, GenericNode, Geometry, GeometryLabel,
GetWidth, GetWidth,
}; };
#[derive(Debug)]
pub struct RecordingGeometryWithRtree<'a, PW, DW, SW, BW, CW, PI, DI, SI, BI> {
pub geometry_with_rtree: &'a mut GeometryWithRtree<PW, DW, SW, BW, CW, PI, DI, SI, BI>,
pub recorder: &'a mut GeometryEdit<PW, DW, SW, BW, CW, PI, DI, SI, BI>,
}
impl< impl<
PW: GetWidth + GetLayer + TryInto<DW> + TryInto<SW> + TryInto<BW> + Retag<PI> + Copy, PW: GetWidth + GetLayer + TryInto<DW> + TryInto<SW> + TryInto<BW> + Retag<PI> + Copy,
DW: AccessDotWeight<PW> + GetLayer, DW: AccessDotWeight<PW> + GetLayer,
@ -38,13 +32,13 @@ impl<
DI: GetPetgraphIndex + Into<PI> + Eq + Hash + Copy, DI: GetPetgraphIndex + Into<PI> + Eq + Hash + Copy,
SI: GetPetgraphIndex + Into<PI> + Eq + Hash + Copy, SI: GetPetgraphIndex + Into<PI> + Eq + Hash + Copy,
BI: GetPetgraphIndex + Into<PI> + Eq + Hash + Copy, BI: GetPetgraphIndex + Into<PI> + Eq + Hash + Copy,
> RecordingGeometryWithRtree<'_, PW, DW, SW, BW, CW, PI, DI, SI, BI> > Recording<'_, GeometryWithRtree<PW, DW, SW, BW, CW, PI, DI, SI, BI>>
{ {
pub fn add_dot<W: AccessDotWeight<PW> + GetLayer>(&mut self, weight: W) -> GenericIndex<W> pub fn add_dot<W: AccessDotWeight<PW> + GetLayer>(&mut self, weight: W) -> GenericIndex<W>
where where
GenericIndex<W>: Into<PI>, GenericIndex<W>: Into<PI>,
{ {
let dot = self.geometry_with_rtree.add_dot(weight); let dot = self.inner.add_dot(weight);
self.recorder.dots.insert( self.recorder.dots.insert(
Into::<PI>::into(dot) Into::<PI>::into(dot)
.try_into() .try_into()
@ -66,7 +60,7 @@ impl<
where where
GenericIndex<W>: Into<PI>, GenericIndex<W>: Into<PI>,
{ {
let seg = self.geometry_with_rtree.add_seg(from, to, weight); let seg = self.inner.add_seg(from, to, weight);
self.recorder.segs.insert( self.recorder.segs.insert(
Into::<PI>::into(seg) Into::<PI>::into(seg)
.try_into() .try_into()
@ -92,7 +86,7 @@ impl<
where where
GenericIndex<W>: Into<PI>, GenericIndex<W>: Into<PI>,
{ {
let bend = self.geometry_with_rtree.add_bend(from, to, core, weight); let bend = self.inner.add_bend(from, to, core, weight);
self.recorder.bends.insert( self.recorder.bends.insert(
Into::<PI>::into(bend) Into::<PI>::into(bend)
.try_into() .try_into()
@ -109,7 +103,7 @@ impl<
} }
pub fn add_compound(&mut self, weight: CW) -> GenericIndex<CW> { pub fn add_compound(&mut self, weight: CW) -> GenericIndex<CW> {
let compound = self.geometry_with_rtree.add_compound(weight); let compound = self.inner.add_compound(weight);
self.recorder self.recorder
.compounds .compounds
.insert(compound, (None, Some((vec![], weight)))); .insert(compound, (None, Some((vec![], weight))));
@ -117,14 +111,13 @@ impl<
} }
pub fn add_to_compound<W>(&mut self, primitive: GenericIndex<W>, compound: GenericIndex<CW>) { pub fn add_to_compound<W>(&mut self, primitive: GenericIndex<W>, compound: GenericIndex<CW>) {
let geometry = self.geometry_with_rtree.geometry(); let geometry = self.inner.geometry();
let old_members = geometry.compound_members(compound).collect(); let old_members = geometry.compound_members(compound).collect();
let old_weight = geometry.compound_weight(compound); let old_weight = geometry.compound_weight(compound);
self.geometry_with_rtree self.inner.add_to_compound(primitive, compound);
.add_to_compound(primitive, compound);
let geometry = self.geometry_with_rtree.geometry(); let geometry = self.inner.geometry();
let new_members = geometry.compound_members(compound).collect(); let new_members = geometry.compound_members(compound).collect();
let new_weight = geometry.compound_weight(compound); let new_weight = geometry.compound_weight(compound);
@ -136,26 +129,26 @@ impl<
} }
pub fn remove_dot(&mut self, dot: DI) -> Result<(), ()> { pub fn remove_dot(&mut self, dot: DI) -> Result<(), ()> {
let weight = self.geometry_with_rtree.geometry().dot_weight(dot); let weight = self.inner.geometry().dot_weight(dot);
self.geometry_with_rtree.remove_dot(dot)?; self.inner.remove_dot(dot)?;
edit_remove_from_map(&mut self.recorder.dots, dot, weight); edit_remove_from_map(&mut self.recorder.dots, dot, weight);
Ok(()) Ok(())
} }
pub fn remove_seg(&mut self, seg: SI) { pub fn remove_seg(&mut self, seg: SI) {
let geometry = self.geometry_with_rtree.geometry(); let geometry = self.inner.geometry();
let weight = geometry.seg_weight(seg); let weight = geometry.seg_weight(seg);
let joints = geometry.seg_joints(seg); let joints = geometry.seg_joints(seg);
self.geometry_with_rtree.remove_seg(seg); self.inner.remove_seg(seg);
edit_remove_from_map(&mut self.recorder.segs, seg, (joints, weight)); edit_remove_from_map(&mut self.recorder.segs, seg, (joints, weight));
} }
pub fn remove_bend(&mut self, bend: BI) { pub fn remove_bend(&mut self, bend: BI) {
let geometry = self.geometry_with_rtree.geometry(); let geometry = self.inner.geometry();
let weight = geometry.bend_weight(bend); let weight = geometry.bend_weight(bend);
let joints = geometry.bend_joints(bend); let joints = geometry.bend_joints(bend);
let core = geometry.core(bend); let core = geometry.core(bend);
self.geometry_with_rtree.remove_bend(bend); self.inner.remove_bend(bend);
edit_remove_from_map( edit_remove_from_map(
&mut self.recorder.bends, &mut self.recorder.bends,
bend, bend,
@ -164,17 +157,17 @@ impl<
} }
pub fn remove_compound(&mut self, compound: GenericIndex<CW>) { pub fn remove_compound(&mut self, compound: GenericIndex<CW>) {
let geometry = self.geometry_with_rtree.geometry(); let geometry = self.inner.geometry();
let weight = geometry.compound_weight(compound); let weight = geometry.compound_weight(compound);
let members = geometry.compound_members(compound).collect(); let members = geometry.compound_members(compound).collect();
self.geometry_with_rtree.remove_compound(compound); self.inner.remove_compound(compound);
edit_remove_from_map(&mut self.recorder.compounds, compound, (members, weight)); edit_remove_from_map(&mut self.recorder.compounds, compound, (members, weight));
} }
pub fn move_dot(&mut self, dot: DI, to: Point) { pub fn move_dot(&mut self, dot: DI, to: Point) {
let old_weight = self.geometry_with_rtree.geometry().dot_weight(dot); let old_weight = self.inner.geometry().dot_weight(dot);
self.geometry_with_rtree.move_dot(dot, to); self.inner.move_dot(dot, to);
let new_weight = self.geometry_with_rtree.geometry().dot_weight(dot); let new_weight = self.inner.geometry().dot_weight(dot);
self.recorder self.recorder
.dots .dots
@ -187,14 +180,14 @@ impl<
where where
F: FnOnce(&mut GeometryWithRtree<PW, DW, SW, BW, CW, PI, DI, SI, BI>, BI), F: FnOnce(&mut GeometryWithRtree<PW, DW, SW, BW, CW, PI, DI, SI, BI>, BI),
{ {
let geometry = self.geometry_with_rtree.geometry(); let geometry = self.inner.geometry();
let old_joints = geometry.bend_joints(bend); let old_joints = geometry.bend_joints(bend);
let old_core = geometry.core(bend); let old_core = geometry.core(bend);
let old_weight = geometry.bend_weight(bend); let old_weight = geometry.bend_weight(bend);
f(&mut self.geometry_with_rtree, bend); f(&mut self.inner, bend);
let geometry = self.geometry_with_rtree.geometry(); let geometry = self.inner.geometry();
let new_joints = geometry.bend_joints(bend); let new_joints = geometry.bend_joints(bend);
let new_core = geometry.core(bend); let new_core = geometry.core(bend);
let new_weight = geometry.bend_weight(bend); let new_weight = geometry.bend_weight(bend);
@ -228,14 +221,14 @@ impl<
} }
pub fn compound_weight(&self, compound: GenericIndex<CW>) -> CW { pub fn compound_weight(&self, compound: GenericIndex<CW>) -> CW {
self.geometry_with_rtree.compound_weight(compound) self.inner.compound_weight(compound)
} }
pub fn compounds<'a, W: 'a>( pub fn compounds<'a, W: 'a>(
&'a self, &'a self,
node: GenericIndex<W>, node: GenericIndex<W>,
) -> impl Iterator<Item = GenericIndex<CW>> + 'a { ) -> impl Iterator<Item = GenericIndex<CW>> + 'a {
self.geometry_with_rtree.compounds(node) self.inner.compounds(node)
} }
pub fn recorder(&self) -> &GeometryEdit<PW, DW, SW, BW, CW, PI, DI, SI, BI> { pub fn recorder(&self) -> &GeometryEdit<PW, DW, SW, BW, CW, PI, DI, SI, BI> {
@ -243,19 +236,19 @@ impl<
} }
pub fn geometry(&self) -> &Geometry<PW, DW, SW, BW, CW, PI, DI, SI, BI> { pub fn geometry(&self) -> &Geometry<PW, DW, SW, BW, CW, PI, DI, SI, BI> {
self.geometry_with_rtree.geometry() self.inner.geometry()
} }
pub fn rtree(&self) -> &RTree<BboxedIndex<GenericNode<PI, GenericIndex<CW>>>> { pub fn rtree(&self) -> &RTree<BboxedIndex<GenericNode<PI, GenericIndex<CW>>>> {
self.geometry_with_rtree.rtree() self.inner.rtree()
} }
pub fn layer_count(&self) -> usize { pub fn layer_count(&self) -> usize {
*self.geometry_with_rtree.layer_count() *self.inner.layer_count()
} }
pub fn graph(&self) -> &StableDiGraph<GenericNode<PW, CW>, GeometryLabel, usize> { pub fn graph(&self) -> &StableDiGraph<GenericNode<PW, CW>, GeometryLabel, usize> {
self.geometry_with_rtree.graph() self.inner.graph()
} }
} }
@ -280,22 +273,3 @@ fn edit_remove_from_map<I, T>(
} }
} }
} }
impl<
PW: GetWidth + GetLayer + TryInto<DW> + TryInto<SW> + TryInto<BW> + Retag<PI> + Copy,
DW: AccessDotWeight<PW> + GetLayer,
SW: AccessSegWeight<PW> + GetLayer,
BW: AccessBendWeight<PW> + GetLayer,
CW: Copy,
PI: GetPetgraphIndex + TryInto<DI> + TryInto<SI> + TryInto<BI> + Eq + Hash + Copy,
DI: GetPetgraphIndex + Into<PI> + Eq + Hash + Copy,
SI: GetPetgraphIndex + Into<PI> + Eq + Hash + Copy,
BI: GetPetgraphIndex + Into<PI> + Eq + Hash + Copy,
> ApplyGeometryEdit<PW, DW, SW, BW, CW, PI, DI, SI, BI>
for RecordingGeometryWithRtree<'_, PW, DW, SW, BW, CW, PI, DI, SI, BI>
{
#[inline(always)]
fn apply(&mut self, edit: &GeometryEdit<PW, DW, SW, BW, CW, PI, DI, SI, BI>) {
self.geometry_with_rtree.apply(edit)
}
}

View File

@ -3,7 +3,7 @@
// SPDX-License-Identifier: MIT // SPDX-License-Identifier: MIT
use contracts_try::debug_invariant; use contracts_try::debug_invariant;
use core::hash::Hash; use core::{cmp::Eq, hash::Hash};
use derive_getters::Getters; use derive_getters::Getters;
use geo::Point; use geo::Point;
use petgraph::stable_graph::StableDiGraph; use petgraph::stable_graph::StableDiGraph;
@ -13,7 +13,7 @@ use crate::{
drawing::graph::{GetLayer, Retag}, drawing::graph::{GetLayer, Retag},
geometry::{ geometry::{
compound::ManageCompounds, compound::ManageCompounds,
edit::{ApplyGeometryEdit, GeometryEdit}, edit::{ApplyGeometryEdit, GeometryEdit, Recordable},
primitive::{AccessPrimitiveShape, PrimitiveShape}, primitive::{AccessPrimitiveShape, PrimitiveShape},
AccessBendWeight, AccessDotWeight, AccessSegWeight, GenericNode, Geometry, GeometryLabel, AccessBendWeight, AccessDotWeight, AccessSegWeight, GenericNode, Geometry, GeometryLabel,
GetWidth, GetWidth,
@ -48,6 +48,29 @@ pub struct GeometryWithRtree<PW, DW, SW, BW, CW, PI, DI, SI, BI> {
layer_count: usize, layer_count: usize,
} }
impl<
PW: GetWidth + GetLayer + TryInto<DW> + TryInto<SW> + TryInto<BW> + Retag<PI> + Copy,
DW: AccessDotWeight<PW> + GetLayer,
SW: AccessSegWeight<PW> + GetLayer,
BW: AccessBendWeight<PW> + GetLayer,
CW: Copy,
PI: GetPetgraphIndex + TryInto<DI> + TryInto<SI> + TryInto<BI> + Copy + Eq + Hash,
DI: GetPetgraphIndex + Into<PI> + Copy + Eq + Hash,
SI: GetPetgraphIndex + Into<PI> + Copy + Eq + Hash,
BI: GetPetgraphIndex + Into<PI> + Copy + Eq + Hash,
> Recordable for GeometryWithRtree<PW, DW, SW, BW, CW, PI, DI, SI, BI>
{
type PW = PW;
type DW = DW;
type SW = SW;
type BW = BW;
type CW = CW;
type PI = PI;
type DI = DI;
type SI = SI;
type BI = BI;
}
#[debug_invariant(self.test_envelopes())] #[debug_invariant(self.test_envelopes())]
#[debug_invariant(self.geometry.graph().node_count() == self.rtree.size())] #[debug_invariant(self.geometry.graph().node_count() == self.rtree.size())]
impl< impl<
@ -70,28 +93,6 @@ impl<
} }
} }
#[inline(always)]
pub fn recording<'a>(
&'a mut self,
recorder: &'a mut super::edit::GeometryEdit<PW, DW, SW, BW, CW, PI, DI, SI, BI>,
) -> super::recording_with_rtree::RecordingGeometryWithRtree<
'a,
PW,
DW,
SW,
BW,
CW,
PI,
DI,
SI,
BI,
> {
super::recording_with_rtree::RecordingGeometryWithRtree {
geometry_with_rtree: self,
recorder,
}
}
pub fn add_dot<W: AccessDotWeight<PW> + GetLayer>(&mut self, weight: W) -> GenericIndex<W> pub fn add_dot<W: AccessDotWeight<PW> + GetLayer>(&mut self, weight: W) -> GenericIndex<W>
where where
GenericIndex<W>: Into<PI>, GenericIndex<W>: Into<PI>,

View File

@ -23,9 +23,13 @@ use crate::{
FixedSegIndex, FixedSegWeight, LoneLooseSegIndex, LoneLooseSegWeight, SegIndex, FixedSegIndex, FixedSegWeight, LoneLooseSegIndex, LoneLooseSegWeight, SegIndex,
SegWeight, SeqLooseSegIndex, SeqLooseSegWeight, SegWeight, SeqLooseSegIndex, SeqLooseSegWeight,
}, },
Drawing, DrawingEdit, DrawingException, Infringement, RecordingDrawing, Drawing, DrawingEdit, DrawingException, Infringement,
},
geometry::{
edit::{ApplyGeometryEdit, Recordable, Recording},
shape::Shape,
GenericNode,
}, },
geometry::{edit::ApplyGeometryEdit, shape::Shape, GenericNode},
graph::{GenericIndex, GetPetgraphIndex}, graph::{GenericIndex, GetPetgraphIndex},
layout::{ layout::{
poly::{MakePolyShape, Poly, PolyWeight}, poly::{MakePolyShape, Poly, PolyWeight},
@ -53,24 +57,23 @@ pub struct Layout<R> {
drawing: Drawing<CompoundWeight, R>, drawing: Drawing<CompoundWeight, R>,
} }
pub struct RecordingLayout<'a, R> {
pub layout: &'a mut Layout<R>,
pub recorder: &'a mut LayoutEdit,
}
impl<R> Layout<R> { impl<R> Layout<R> {
#[inline(always)] #[inline(always)]
pub fn new(drawing: Drawing<CompoundWeight, R>) -> Self { pub fn new(drawing: Drawing<CompoundWeight, R>) -> Self {
Self { drawing } Self { drawing }
} }
}
#[inline(always)] impl<R> Recordable for Layout<R> {
pub fn recording<'a>(&'a mut self, recorder: &'a mut LayoutEdit) -> RecordingLayout<'a, R> { type PW = PrimitiveWeight;
RecordingLayout { type DW = DotWeight;
layout: self, type SW = SegWeight;
recorder, type BW = BendWeight;
} type CW = CompoundWeight;
} type PI = PrimitiveIndex;
type DI = DotIndex;
type SI = SegIndex;
type BI = BendIndex;
} }
impl<R: AccessRules> Layout<R> { impl<R: AccessRules> Layout<R> {
@ -205,22 +208,13 @@ impl<R: AccessRules> Layout<R> {
} }
} }
// this is a hack, but it allows us to not needing as much boilerplate for delegations impl<R: AccessRules> Recording<'_, Layout<R>> {
impl<R> core::ops::Deref for RecordingLayout<'_, R> { fn recording_drawing(&mut self) -> Recording<'_, Drawing<CompoundWeight, R>> {
type Target = Layout<R>; self.inner.drawing.recording(self.recorder)
fn deref(&self) -> &Layout<R> {
self.layout
}
}
impl<R: AccessRules> RecordingLayout<'_, R> {
fn recording_drawing(&mut self) -> RecordingDrawing<'_, CompoundWeight, R> {
self.layout.drawing.recording(self.recorder)
} }
pub fn rules_mut(&mut self) -> &mut R { pub fn rules_mut(&mut self) -> &mut R {
self.layout.drawing.rules_mut() self.inner.drawing.rules_mut()
} }
/// Insert [`Cane`] object into the [`Layout`] /// Insert [`Cane`] object into the [`Layout`]

View File

@ -13,14 +13,14 @@ use crate::{
dot::{DotIndex, FixedDotIndex, LooseDotIndex, LooseDotWeight}, dot::{DotIndex, FixedDotIndex, LooseDotIndex, LooseDotWeight},
gear::GearIndex, gear::GearIndex,
graph::{GetLayer, GetMaybeNet, MakePrimitive}, graph::{GetLayer, GetMaybeNet, MakePrimitive},
guide::Guide,
head::{CaneHead, GetFace, Head}, head::{CaneHead, GetFace, Head},
primitive::GetOtherJoint, primitive::GetOtherJoint,
rules::AccessRules, rules::AccessRules,
seg::{LoneLooseSegWeight, SeqLooseSegWeight}, seg::{LoneLooseSegWeight, SeqLooseSegWeight},
Drawing, DrawingException, Infringement, DrawingException, Infringement,
}, },
layout::{CompoundWeight, Layout, LayoutEdit, RecordingLayout}, geometry::edit::Recording,
layout::Layout,
math::{Circle, NoTangents}, math::{Circle, NoTangents},
}; };
@ -67,7 +67,7 @@ pub trait Draw {
fn undo_cane(&mut self, head: CaneHead) -> Option<Head>; fn undo_cane(&mut self, head: CaneHead) -> Option<Head>;
} }
impl<'a, R: AccessRules> Draw for RecordingLayout<'a, R> { impl<'a, R: AccessRules> Draw for Recording<'a, Layout<R>> {
fn start(&mut self, from: LooseDotIndex) -> Head { fn start(&mut self, from: LooseDotIndex) -> Head {
self.guide().cane_head(from).into() self.guide().cane_head(from).into()
} }
@ -188,7 +188,7 @@ impl<'a, R: AccessRules> Draw for RecordingLayout<'a, R> {
#[debug_ensures(ret.is_ok() -> this.drawing().node_count() == old(this.drawing().node_count() + 4))] #[debug_ensures(ret.is_ok() -> this.drawing().node_count() == old(this.drawing().node_count() + 4))]
#[debug_ensures(ret.is_err() -> this.drawing().node_count() == old(this.drawing().node_count()))] #[debug_ensures(ret.is_err() -> this.drawing().node_count() == old(this.drawing().node_count()))]
fn cane_around<R: AccessRules>( fn cane_around<R: AccessRules>(
this: &mut RecordingLayout<'_, R>, this: &mut Recording<'_, Layout<R>>,
head: Head, head: Head,
around: GearIndex, around: GearIndex,
from: Point, from: Point,
@ -203,7 +203,7 @@ fn cane_around<R: AccessRules>(
#[debug_ensures(this.drawing().node_count() == old(this.drawing().node_count()))] #[debug_ensures(this.drawing().node_count() == old(this.drawing().node_count()))]
fn extend_head<R: AccessRules>( fn extend_head<R: AccessRules>(
this: &mut RecordingLayout<'_, R>, this: &mut Recording<'_, Layout<R>>,
head: Head, head: Head,
to: Point, to: Point,
) -> Result<Head, Infringement> { ) -> Result<Head, Infringement> {
@ -218,7 +218,7 @@ fn extend_head<R: AccessRules>(
#[debug_ensures(ret.is_ok() -> this.drawing().node_count() == old(this.drawing().node_count() + 4))] #[debug_ensures(ret.is_ok() -> this.drawing().node_count() == old(this.drawing().node_count() + 4))]
#[debug_ensures(ret.is_err() -> this.drawing().node_count() == old(this.drawing().node_count()))] #[debug_ensures(ret.is_err() -> this.drawing().node_count() == old(this.drawing().node_count()))]
fn cane<R: AccessRules>( fn cane<R: AccessRules>(
this: &mut RecordingLayout<'_, R>, this: &mut Recording<'_, Layout<R>>,
head: Head, head: Head,
around: GearIndex, around: GearIndex,
to: Point, to: Point,

View File

@ -13,6 +13,7 @@ use crate::{
head::{BareHead, CaneHead, Head}, head::{BareHead, CaneHead, Head},
rules::AccessRules, rules::AccessRules,
}, },
geometry::edit::Recordable,
layout::LayoutEdit, layout::LayoutEdit,
}; };

View File

@ -7,6 +7,7 @@ use thiserror::Error;
use crate::{ use crate::{
drawing::{band::BandTermsegIndex, dot::FixedDotIndex, rules::AccessRules}, drawing::{band::BandTermsegIndex, dot::FixedDotIndex, rules::AccessRules},
geometry::edit::Recordable,
layout::{Layout, LayoutEdit}, layout::{Layout, LayoutEdit},
}; };