diff --git a/src/draw.rs b/src/draw.rs index 865430f..bf5d7ad 100644 --- a/src/draw.rs +++ b/src/draw.rs @@ -8,7 +8,7 @@ use crate::{ LooseBendWeight, LooseDotIndex, LooseDotWeight, LooseSegWeight, MakePrimitive, WraparoundableIndex, }, - guide::Guide, + guide::{Guide, Head, HeadTrait, SegbendHead}, layout::Layout, math::Circle, primitive::{GetOtherEnd, GetWeight}, @@ -16,52 +16,6 @@ use crate::{ segbend::Segbend, }; -#[enum_dispatch] -pub trait HeadTrait { - fn dot(&self) -> DotIndex; - fn band(&self) -> usize; -} - -#[enum_dispatch(HeadTrait)] -#[derive(Debug, Clone, Copy)] -pub enum Head { - Bare(BareHead), - Segbend(SegbendHead), -} - -#[derive(Debug, Clone, Copy)] -pub struct BareHead { - pub dot: FixedDotIndex, - pub band: usize, -} - -impl HeadTrait for BareHead { - fn dot(&self) -> DotIndex { - self.dot.into() - } - - fn band(&self) -> usize { - self.band - } -} - -#[derive(Debug, Clone, Copy)] -pub struct SegbendHead { - pub dot: LooseDotIndex, - pub segbend: Segbend, - pub band: usize, -} - -impl HeadTrait for SegbendHead { - fn dot(&self) -> DotIndex { - self.dot.into() - } - - fn band(&self) -> usize { - self.band - } -} - pub struct Draw<'a> { layout: &'a mut Layout, rules: &'a Rules, @@ -73,7 +27,7 @@ impl<'a> Draw<'a> { } pub fn start(&mut self, from: LooseDotIndex) -> Head { - self.segbend_head(from).into() + self.guide(&Default::default()).segbend_head(from).into() } #[debug_ensures(ret.is_ok() -> self.layout.node_count() == old(self.layout.node_count() + 1))] @@ -111,7 +65,7 @@ impl<'a> Draw<'a> { into: LooseDotIndex, width: f64, ) -> Result<(), ()> { - let to_head = self.segbend_head(into); + let to_head = self.guide(&Default::default()).segbend_head(into); let to_cw = self .guide(&Default::default()) .head_cw(&to_head.into()) @@ -244,7 +198,7 @@ impl<'a> Draw<'a> { cw: bool, width: f64, ) -> Result { - let segbend = self.layout.add_segbend( + let segbend = self.layout.insert_segbend( head.dot(), around, LooseDotWeight { @@ -280,51 +234,7 @@ impl<'a> Draw<'a> { self.layout.remove_interior(&head.segbend); self.layout.remove(head.dot().into()); - Some(self.head(prev_dot, band)) - } - - #[debug_ensures(self.layout.node_count() == old(self.layout.node_count()))] - pub fn update_bow(&mut self, _bend: LooseBendIndex) { - /*let cw = self.layout.primitive(bend).weight().cw; - let ends = self.layout.primitive(bend).ends(); - let from_head = self.rear_head(ends.0); - let to_head = self.rear_head(ends.1); - - let from = self - .guide(&Default::default()) - .head_around_bend_segment(&from_head, inner, cw, 3.0); - let to = self - .guide(&Default::default()) - .head_around_bend_segment(&from_head, inner, cw, 3.0); - self.layout.reposition_bend(bend, from, to);*/ - } - - fn head(&self, dot: DotIndex, band: usize) -> Head { - match dot { - DotIndex::Fixed(loose) => BareHead { dot: loose, band }.into(), - DotIndex::Loose(fixed) => self.segbend_head(fixed).into(), - } - } - - fn segbend_head(&self, dot: LooseDotIndex) -> SegbendHead { - SegbendHead { - dot, - segbend: self.layout.segbend(dot), - band: self.layout.primitive(dot).weight().band(), - } - } - - fn rear_head(&self, dot: LooseDotIndex) -> Head { - self.head( - self.rear(self.segbend_head(dot)), - self.layout.primitive(dot).weight().band(), - ) - } - - fn rear(&self, head: SegbendHead) -> DotIndex { - self.layout - .primitive(head.segbend.seg) - .other_end(head.segbend.dot.into()) + Some(self.guide(&Default::default()).head(prev_dot, band)) } fn guide(&'a self, conditions: &'a Conditions) -> Guide { diff --git a/src/graph.rs b/src/graph.rs index 2f9839c..53ff905 100644 --- a/src/graph.rs +++ b/src/graph.rs @@ -11,14 +11,6 @@ use crate::{ primitive::{GenericPrimitive, Primitive}, }; -pub trait Interior { - fn interior(&self) -> Vec; -} - -pub trait GetEnds { - fn ends(&self) -> (F, T); -} - #[enum_dispatch] pub trait Retag { fn retag(&self, index: NodeIndex) -> Index; @@ -176,14 +168,23 @@ impl From for WraparoundableIndex { } } -#[enum_dispatch(GetNodeIndex, MakePrimitive, GetWraparound)] +#[enum_dispatch(GetNodeIndex, MakePrimitive)] #[derive(Debug, Clone, Copy, PartialEq)] pub enum WraparoundableIndex { + FixedDot(FixedDotIndex), FixedBend(FixedBendIndex), LooseBend(LooseBendIndex), - FixedDot(FixedDotIndex), } +impl From for Index { + fn from(wraparoundable: WraparoundableIndex) -> Self { + match wraparoundable { + WraparoundableIndex::FixedDot(dot) => Index::FixedDot(dot), + WraparoundableIndex::FixedBend(bend) => Index::FixedBend(bend), + WraparoundableIndex::LooseBend(bend) => Index::LooseBend(bend), + } + } +} pub trait DotWeight: GetWidth + Into + Copy {} #[derive(Debug, Clone, Copy, PartialEq)] diff --git a/src/guide.rs b/src/guide.rs index dbb77dd..5aed548 100644 --- a/src/guide.rs +++ b/src/guide.rs @@ -1,15 +1,62 @@ +use enum_dispatch::enum_dispatch; use geo::Line; use crate::{ - draw::{Head, HeadTrait}, - graph::{BendIndex, DotIndex, FixedDotIndex, MakePrimitive}, + graph::{BendIndex, DotIndex, FixedDotIndex, GetBand, LooseDotIndex, MakePrimitive}, layout::Layout, math::{self, Circle}, - primitive::{GetCore, GetInnerOuter, GetWeight, MakeShape}, + primitive::{GetCore, GetInnerOuter, GetOtherEnd, GetWeight, MakeShape}, rules::{Conditions, Rules}, + segbend::Segbend, shape::{Shape, ShapeTrait}, }; +#[enum_dispatch] +pub trait HeadTrait { + fn dot(&self) -> DotIndex; + fn band(&self) -> usize; +} + +#[enum_dispatch(HeadTrait)] +#[derive(Debug, Clone, Copy)] +pub enum Head { + Bare(BareHead), + Segbend(SegbendHead), +} + +#[derive(Debug, Clone, Copy)] +pub struct BareHead { + pub dot: FixedDotIndex, + pub band: usize, +} + +impl HeadTrait for BareHead { + fn dot(&self) -> DotIndex { + self.dot.into() + } + + fn band(&self) -> usize { + self.band + } +} + +#[derive(Debug, Clone, Copy)] +pub struct SegbendHead { + pub dot: LooseDotIndex, + pub segbend: Segbend, + pub band: usize, +} + +impl HeadTrait for SegbendHead { + fn dot(&self) -> DotIndex { + self.dot.into() + } + + fn band(&self) -> usize { + self.band + } +} + pub struct Guide<'a, 'b> { layout: &'a Layout, rules: &'a Rules, @@ -149,7 +196,35 @@ impl<'a, 'b> Guide<'a, 'b> { let shape = dot.primitive(self.layout).shape(); Circle { pos: shape.center(), - r: shape.width() / 2.0 + width + self.rules.ruleset(self.conditions).clearance.min, + r: shape.width() / 2.0 + width + 0.0, } } + + pub fn segbend_head(&self, dot: LooseDotIndex) -> SegbendHead { + SegbendHead { + dot, + segbend: self.layout.segbend(dot), + band: self.layout.primitive(dot).weight().band(), + } + } + + pub fn rear_head(&self, dot: LooseDotIndex) -> Head { + self.head( + self.rear(self.segbend_head(dot)), + self.layout.primitive(dot).weight().band(), + ) + } + + pub fn head(&self, dot: DotIndex, band: usize) -> Head { + match dot { + DotIndex::Fixed(fixed) => BareHead { dot: fixed, band }.into(), + DotIndex::Loose(loose) => self.segbend_head(loose).into(), + } + } + + fn rear(&self, head: SegbendHead) -> DotIndex { + self.layout + .primitive(head.segbend.seg) + .other_end(head.segbend.dot.into()) + } } diff --git a/src/layout.rs b/src/layout.rs index 3aa05b1..864dea0 100644 --- a/src/layout.rs +++ b/src/layout.rs @@ -9,11 +9,15 @@ use slab::Slab; use crate::graph::{ BendWeight, DotIndex, DotWeight, FixedBendIndex, FixedDotIndex, FixedDotWeight, FixedSegIndex, - FixedSegWeight, GenericIndex, GetNodeIndex, Index, Interior, Label, LooseBendIndex, + FixedSegWeight, GenericIndex, GetNet, GetNodeIndex, Index, Label, LooseBendIndex, LooseBendWeight, LooseDotIndex, LooseDotWeight, LooseSegIndex, LooseSegWeight, MakePrimitive, Retag, SegWeight, Weight, WraparoundableIndex, }; -use crate::primitive::{GenericPrimitive, GetConnectable, GetWeight, MakeShape}; +use crate::guide::Guide; +use crate::primitive::{ + GenericPrimitive, GetConnectable, GetCore, GetEnds, GetFirstRail, GetInnerOuter, GetInterior, + GetOtherEnd, GetWeight, GetWraparound, MakeShape, +}; use crate::segbend::Segbend; use crate::shape::{Shape, ShapeTrait}; @@ -44,7 +48,7 @@ impl Layout { } #[debug_ensures(self.graph.node_count() == old(self.graph.node_count() - path.interior().len()))] - pub fn remove_interior(&mut self, path: &impl Interior) { + pub fn remove_interior(&mut self, path: &impl GetInterior) { for index in path .interior() .into_iter() @@ -67,6 +71,14 @@ impl Layout { #[debug_ensures(self.graph.node_count() == old(self.graph.node_count() - 1))] pub fn remove(&mut self, index: Index) { + // Removing a loose bend affects its outer bends. + if let Index::LooseBend(bend) = index { + if let Some(outer) = self.primitive(bend).outer() { + self.reattach_bend(outer, self.primitive(bend).inner()); + self.update_this_and_outward_bows(outer).unwrap(); // Must never fail. + } + } + // Unnecessary retag. It should be possible to elide it. let weight = *self.graph.node_weight(index.node_index()).unwrap(); @@ -78,27 +90,30 @@ impl Layout { #[debug_ensures(ret.is_err() -> self.graph.node_count() == old(self.graph.node_count()))] #[debug_ensures(self.graph.edge_count() == old(self.graph.edge_count()))] pub fn add_fixed_dot(&mut self, weight: FixedDotWeight) -> Result { - self.add_dot(weight) + self.add_dot_infringably(weight, &[]) } - // TODO: Remove. - #[debug_ensures(ret.is_ok() -> self.graph.node_count() == old(self.graph.node_count() + 1))] + /*#[debug_ensures(ret.is_ok() -> self.graph.node_count() == old(self.graph.node_count() + 1))] #[debug_ensures(ret.is_err() -> self.graph.node_count() == old(self.graph.node_count()))] #[debug_ensures(self.graph.edge_count() == old(self.graph.edge_count()))] fn add_loose_dot(&mut self, weight: LooseDotWeight) -> Result { - self.add_dot(weight) - } + self.add_dot_infringably(weight, &[]) + }*/ #[debug_ensures(ret.is_ok() -> self.graph.node_count() == old(self.graph.node_count() + 1))] #[debug_ensures(ret.is_err() -> self.graph.node_count() == old(self.graph.node_count()))] - fn add_dot(&mut self, weight: W) -> Result, ()> + fn add_dot_infringably( + &mut self, + weight: W, + infringables: &[Index], + ) -> Result, ()> where GenericIndex: Into + Copy, { let dot = GenericIndex::::new(self.graph.add_node(weight.into())); self.insert_into_rtree(dot.into()); - self.fail_and_remove_if_collides_except(dot.into(), &[])?; + self.fail_and_remove_if_infringes_except(dot.into(), infringables)?; Ok(dot) } @@ -113,7 +128,253 @@ impl Layout { to: FixedDotIndex, weight: FixedSegWeight, ) -> Result { - self.add_seg(from, to, weight) + self.add_seg_infringably(from, to, weight, &[]) + } + + #[debug_ensures(ret.is_ok() -> self.graph.node_count() == old(self.graph.node_count() + 4))] + #[debug_ensures(ret.is_ok() -> self.graph.edge_count() >= old(self.graph.edge_count() + 5))] + #[debug_ensures(ret.is_err() -> self.graph.node_count() == old(self.graph.node_count()))] + #[debug_ensures(ret.is_err() -> self.graph.edge_count() == old(self.graph.edge_count()))] + pub fn insert_segbend( + &mut self, + from: DotIndex, + around: WraparoundableIndex, + dot_weight: LooseDotWeight, + seg_weight: LooseSegWeight, + bend_weight: LooseBendWeight, + ) -> Result { + let maybe_wraparound = match around { + WraparoundableIndex::FixedDot(around) => self.primitive(around).wraparound(), + WraparoundableIndex::FixedBend(around) => self.primitive(around).wraparound(), + WraparoundableIndex::LooseBend(around) => self.primitive(around).wraparound(), + }; + + let mut infringables = self.this_and_wraparound_bow(around); + + if let Some(wraparound) = maybe_wraparound { + infringables.append(&mut self.outer_bows(wraparound)); + } + + let segbend = self.add_segbend_infringably( + from, + around, + dot_weight, + seg_weight, + bend_weight, + &infringables, + )?; + + if let Some(wraparound) = maybe_wraparound { + self.reattach_bend(wraparound, Some(segbend.bend)); + } + + if let Some(outer) = self.primitive(segbend.bend).outer() { + self.update_this_and_outward_bows(outer); + } + + // Segs must not cross. + if let Some(..) = self.detect_collision(segbend.seg.into()) { + let end = self.primitive(segbend.bend).other_end(segbend.dot); + self.remove_interior(&segbend); + self.remove(end.into()); + return Err(()); + } + + Ok(segbend) + } + + #[debug_ensures(self.graph.node_count() == old(self.graph.node_count()))] + #[debug_ensures(self.graph.edge_count() == old(self.graph.edge_count()))] + fn inner_and_outer_bows(&self, bend: LooseBendIndex) -> Vec { + let bend_primitive = self.primitive(bend); + let mut v = vec![]; + + if let Some(inner) = bend_primitive.inner() { + v.append(&mut self.bow(inner.into())); + } else { + let core = bend_primitive.core(); + v.push(core.into()); + } + + if let Some(outer) = bend_primitive.outer() { + v.append(&mut self.bow(outer.into())); + } + + v + } + + #[debug_ensures(self.graph.node_count() == old(self.graph.node_count()))] + #[debug_ensures(self.graph.edge_count() == old(self.graph.edge_count()))] + fn this_and_wraparound_bow(&self, around: WraparoundableIndex) -> Vec { + match around { + WraparoundableIndex::FixedDot(dot) => { + let mut v = vec![around.into()]; + if let Some(first_rail) = self.primitive(dot).first_rail() { + v.append(&mut self.bow(first_rail)); + } + v + } + WraparoundableIndex::FixedBend(bend) => { + let mut v = vec![around.into()]; + if let Some(first_rail) = self.primitive(bend).first_rail() { + v.append(&mut self.bow(first_rail)); + } + v + } + WraparoundableIndex::LooseBend(bend) => { + let mut v = self.bow(bend); + if let Some(outer) = self.primitive(bend).outer() { + v.append(&mut self.bow(outer)); + } + v + } + } + } + + // XXX: Move this to primitives? + #[debug_ensures(self.graph.node_count() == old(self.graph.node_count()))] + #[debug_ensures(self.graph.edge_count() == old(self.graph.edge_count()))] + fn bow(&self, bend: LooseBendIndex) -> Vec { + let mut bow: Vec = vec![]; + bow.push(bend.into()); + + let ends = self.primitive(bend).ends(); + bow.push(ends.0.into()); + bow.push(ends.1.into()); + + if let Some(seg0) = self.primitive(ends.0).seg() { + bow.push(seg0.into()); + } + + if let Some(seg1) = self.primitive(ends.1).seg() { + bow.push(seg1.into()); + } + + bow + } + + #[debug_ensures(self.graph.node_count() == old(self.graph.node_count()))] + #[debug_ensures(self.graph.edge_count() == old(self.graph.edge_count()))] + fn outer_bows(&self, bend: LooseBendIndex) -> Vec { + let mut outer_bows = vec![]; + let mut rail = bend; + + while let Some(outer) = self.primitive(rail).outer() { + let primitive = self.primitive(outer); + + outer_bows.push(outer.into()); + + let ends = primitive.ends(); + outer_bows.push(ends.0.into()); + outer_bows.push(ends.1.into()); + + outer_bows.push(self.primitive(ends.0).seg().unwrap().into()); + outer_bows.push(self.primitive(ends.1).seg().unwrap().into()); + + rail = outer; + } + + outer_bows + + /*let mut outer_bows = vec![]; + + // XXX: Ugly all-same match. + let mut maybe_rail = match around { + WraparoundableIndex::FixedDot(around) => self.primitive(around).wraparound(), + WraparoundableIndex::FixedBend(around) => self.primitive(around).wraparound(), + WraparoundableIndex::LooseBend(around) => self.primitive(around).wraparound(), + }; + + while let Some(rail) = maybe_rail { + let primitive = self.primitive(rail); + outer_bows.push(rail.into()); + + let ends = primitive.ends(); + outer_bows.push(ends.0.into()); + outer_bows.push(ends.1.into()); + + outer_bows.push(self.primitive(ends.0).seg().unwrap().into()); + maybe_rail = primitive.outer(); + } + + outer_bows*/ + } + + #[debug_ensures(self.graph.node_count() == old(self.graph.node_count()))] + #[debug_ensures(self.graph.edge_count() == old(self.graph.edge_count()) + || self.graph.edge_count() == old(self.graph.edge_count() - 1) + || self.graph.edge_count() == old(self.graph.edge_count() + 1))] + fn reattach_bend(&mut self, bend: LooseBendIndex, maybe_new_inner: Option) { + self.remove_from_rtree(bend.into()); + + if let Some(old_inner_edge) = self + .graph + .edges_directed(bend.node_index(), Incoming) + .filter(|edge| *edge.weight() == Label::Outer) + .next() + { + self.graph.remove_edge(old_inner_edge.id()); + } + + if let Some(new_inner) = maybe_new_inner { + self.graph + .add_edge(new_inner.node_index(), bend.node_index(), Label::Outer); + } + + self.insert_into_rtree(bend.into()); + } + + #[debug_ensures(self.graph.node_count() == old(self.graph.node_count()))] + #[debug_ensures(self.graph.edge_count() == old(self.graph.edge_count()))] + fn update_this_and_outward_bows(&mut self, around: LooseBendIndex) -> Result<(), ()> { + let mut maybe_rail = Some(around); + + while let Some(rail) = maybe_rail { + let primitive = self.primitive(rail); + let cw = primitive.weight().cw; + let ends = primitive.ends(); + + let rules = Default::default(); + let conditions = Default::default(); + let guide = Guide::new(self, &rules, &conditions); + + let from_head = guide.rear_head(ends.1); + let to_head = guide.rear_head(ends.0); + + if let Some(inner) = primitive.inner() { + let from = guide + .head_around_bend_segment(&from_head.into(), inner.into(), !cw, 6.0)? + .end_point(); + let to = guide + .head_around_bend_segment(&to_head.into(), inner.into(), cw, 6.0)? + .end_point(); + self.move_dot(ends.0, from)?; + self.move_dot(ends.1, to)?; + } else { + let core = primitive.core(); + let from = guide + .head_around_dot_segment(&from_head.into(), core.into(), !cw, 6.0)? + .end_point(); + let to = guide + .head_around_dot_segment(&to_head.into(), core.into(), cw, 6.0)? + .end_point(); + self.move_dot(ends.0, from)?; + self.move_dot(ends.1, to)?; + } + + /*let from = guide + .head_around_bend_segment(&from_head.into(), rail.into(), !cw, 0.0)? + .end_point(); + let to = guide + .head_around_bend_segment(&to_head.into(), rail.into(), cw, 0.0)? + .end_point(); + self.move_dot(ends.0, from)?; + self.move_dot(ends.1, to)?;*/ + + maybe_rail = self.primitive(rail).outer(); + } + + Ok(()) } #[debug_ensures(ret.is_ok() -> self.graph.node_count() == old(self.graph.node_count() + 4))] @@ -128,17 +389,44 @@ impl Layout { seg_weight: LooseSegWeight, bend_weight: LooseBendWeight, ) -> Result { - let seg_to = self.add_loose_dot(dot_weight)?; - let seg = self.add_loose_seg(from, seg_to, seg_weight).map_err(|_| { - self.remove(seg_to.into()); - })?; + self.add_segbend_infringably( + from, + around, + dot_weight, + seg_weight, + bend_weight, + &self.this_and_wraparound_bow(around), + ) + } - let bend_to = self.add_loose_dot(dot_weight).map_err(|_| { - self.remove(seg.into()); - self.remove(seg_to.into()); - })?; + #[debug_ensures(ret.is_ok() -> self.graph.node_count() == old(self.graph.node_count() + 4))] + #[debug_ensures(ret.is_ok() -> self.graph.edge_count() >= old(self.graph.edge_count() + 5))] + #[debug_ensures(ret.is_err() -> self.graph.node_count() == old(self.graph.node_count()))] + #[debug_ensures(ret.is_err() -> self.graph.edge_count() == old(self.graph.edge_count()))] + fn add_segbend_infringably( + &mut self, + from: DotIndex, + around: WraparoundableIndex, + dot_weight: LooseDotWeight, + seg_weight: LooseSegWeight, + bend_weight: LooseBendWeight, + infringables: &[Index], + ) -> Result { + let seg_to = self.add_dot_infringably(dot_weight, infringables)?; + let seg = self + .add_seg_infringably(from, seg_to, seg_weight, infringables) + .map_err(|_| { + self.remove(seg_to.into()); + })?; + + let bend_to = self + .add_dot_infringably(dot_weight, infringables) + .map_err(|_| { + self.remove(seg.into()); + self.remove(seg_to.into()); + })?; let bend = self - .add_loose_bend(seg_to, bend_to, around, bend_weight) + .add_loose_bend_infringably(seg_to, bend_to, around, bend_weight, infringables) .map_err(|_| { self.remove(bend_to.into()); self.remove(seg.into()); @@ -162,18 +450,19 @@ impl Layout { to: LooseDotIndex, weight: LooseSegWeight, ) -> Result { - self.add_seg(from, to, weight) + self.add_seg_infringably(from, to, weight, &[]) } #[debug_ensures(ret.is_ok() -> self.graph.node_count() == old(self.graph.node_count() + 1))] #[debug_ensures(ret.is_ok() -> self.graph.edge_count() == old(self.graph.edge_count() + 2))] #[debug_ensures(ret.is_err() -> self.graph.node_count() == old(self.graph.node_count()))] #[debug_ensures(ret.is_err() -> self.graph.edge_count() == old(self.graph.edge_count()))] - fn add_seg( + fn add_seg_infringably( &mut self, from: impl GetNodeIndex, to: impl GetNodeIndex, weight: W, + infringables: &[Index], ) -> Result, ()> where GenericIndex: Into + Copy, @@ -186,7 +475,7 @@ impl Layout { .add_edge(seg.node_index(), to.node_index(), Label::Adjacent); self.insert_into_rtree(seg.into()); - self.fail_and_remove_if_collides_except(seg.into(), &[])?; + self.fail_and_remove_if_infringes_except(seg.into(), infringables)?; Ok(seg) } @@ -208,21 +497,43 @@ impl Layout { }*/ #[debug_ensures(ret.is_ok() -> self.graph.node_count() == old(self.graph.node_count() + 1))] - #[debug_ensures(ret.is_ok() -> self.graph.edge_count() == old(self.graph.edge_count() + 3) || self.graph.edge_count() == old(self.graph.edge_count() + 4))] + #[debug_ensures(ret.is_ok() -> self.graph.edge_count() == old(self.graph.edge_count() + 3) + || self.graph.edge_count() == old(self.graph.edge_count() + 4))] #[debug_ensures(ret.is_err() -> self.graph.node_count() == old(self.graph.node_count()))] #[debug_ensures(ret.is_err() -> self.graph.edge_count() == old(self.graph.edge_count()))] - fn add_loose_bend( + fn add_loose_bend_infringably( &mut self, from: LooseDotIndex, to: LooseDotIndex, around: WraparoundableIndex, weight: LooseBendWeight, + infringables: &[Index], ) -> Result { + // It makes no sense to wrap something around or under one of its connectables. + if self.bands[weight.band].net == around.primitive(self).net() { + return Err(()); + } + // + if let Some(wraparound) = match around { + WraparoundableIndex::FixedDot(around) => self.primitive(around).wraparound(), + WraparoundableIndex::FixedBend(around) => self.primitive(around).wraparound(), + WraparoundableIndex::LooseBend(around) => self.primitive(around).wraparound(), + } { + if self.bands[weight.band].net == wraparound.primitive(self).net() { + return Err(()); + } + } + match around { - WraparoundableIndex::FixedDot(core) => self.add_core_bend(from, to, core, weight), - WraparoundableIndex::FixedBend(around) => self.add_outer_bend(from, to, around, weight), - WraparoundableIndex::LooseBend(around) => self.add_outer_bend(from, to, around, weight), - _ => unreachable!(), + WraparoundableIndex::FixedDot(core) => { + self.add_core_bend_infringably(from, to, core, weight, infringables) + } + WraparoundableIndex::FixedBend(around) => { + self.add_outer_bend_infringably(from, to, around, weight, infringables) + } + WraparoundableIndex::LooseBend(around) => { + self.add_outer_bend_infringably(from, to, around, weight, infringables) + } } } @@ -230,12 +541,13 @@ impl Layout { #[debug_ensures(ret.is_err() -> self.graph.node_count() == old(self.graph.node_count()))] #[debug_ensures(ret.is_ok() -> self.graph.edge_count() == old(self.graph.edge_count() + 3))] #[debug_ensures(ret.is_err() -> self.graph.edge_count() == old(self.graph.edge_count()))] - fn add_core_bend( + fn add_core_bend_infringably( &mut self, from: impl GetNodeIndex, to: impl GetNodeIndex, core: FixedDotIndex, weight: W, + infringables: &[Index], ) -> Result where GenericIndex: Into + Copy, @@ -250,7 +562,7 @@ impl Layout { .add_edge(bend.node_index(), core.node_index(), Label::Core); self.insert_into_rtree(bend.into()); - self.fail_and_remove_if_collides_except(bend.into(), &[core.into()])?; + self.fail_and_remove_if_infringes_except(bend.into(), infringables)?; Ok(bend) } @@ -258,12 +570,13 @@ impl Layout { #[debug_ensures(ret.is_err() -> self.graph.node_count() == old(self.graph.node_count()))] #[debug_ensures(ret.is_ok() -> self.graph.edge_count() == old(self.graph.edge_count() + 4))] #[debug_ensures(ret.is_err() -> self.graph.edge_count() == old(self.graph.edge_count()))] - fn add_outer_bend( + fn add_outer_bend_infringably( &mut self, from: impl GetNodeIndex, to: impl GetNodeIndex, inner: impl GetNodeIndex, weight: W, + infringables: &[Index], ) -> Result { let core = *self .graph @@ -293,34 +606,10 @@ impl Layout { .add_edge(inner.node_index(), bend.node_index(), Label::Outer); self.insert_into_rtree(bend.into()); - self.fail_and_remove_if_collides_except(bend.into(), &[core.into()])?; + self.fail_and_remove_if_infringes_except(bend.into(), infringables)?; Ok(bend) } - pub fn reposition_bend(&mut self, _bend: LooseBendIndex, _from: Point, _to: Point) { - // TODO. - } - - #[debug_ensures(self.graph.node_count() == old(self.graph.node_count()))] - #[debug_ensures(self.graph.edge_count() == old(self.graph.edge_count()) - || self.graph.edge_count() == old(self.graph.edge_count() + 1))] - pub fn reattach_bend(&mut self, bend: LooseBendIndex, inner: LooseBendIndex) { - self.remove_from_rtree(bend.into()); - - if let Some(old_inner_edge) = self - .graph - .edges_directed(bend.node_index(), Incoming) - .filter(|edge| *edge.weight() == Label::Outer) - .next() - { - self.graph.remove_edge(old_inner_edge.id()); - } - - self.graph - .add_edge(inner.node_index(), bend.node_index(), Label::Outer); - self.insert_into_rtree(bend.into()); - } - #[debug_ensures(self.graph.node_count() == old(self.graph.node_count()))] #[debug_ensures(self.graph.edge_count() == old(self.graph.edge_count()))] pub fn flip_bend(&mut self, bend: FixedBendIndex) { @@ -346,12 +635,12 @@ impl Layout { #[debug_ensures(ret.is_ok() -> self.graph.node_count() == old(self.graph.node_count()))] #[debug_ensures(ret.is_ok() -> self.graph.edge_count() == old(self.graph.edge_count()))] #[debug_ensures(ret.is_err() -> self.graph.node_count() == old(self.graph.node_count() - 1))] - fn fail_and_remove_if_collides_except( + fn fail_and_remove_if_infringes_except( &mut self, index: Index, except: &[Index], ) -> Result<(), ()> { - if let Some(..) = self.detect_collision_except(index, except) { + if let Some(..) = self.detect_infringement_except(index, except) { self.remove(index); return Err(()); } @@ -382,9 +671,31 @@ impl Layout { #[debug_invariant(self.test_envelopes())] impl Layout { + pub fn move_dot(&mut self, dot: LooseDotIndex, to: Point) -> Result<(), ()> { + self.move_dot_infringably( + dot, + to, + &self.inner_and_outer_bows(self.primitive(dot).bend()), + ) + + //let bend_primitive = self.primitive(self.primitive(dot).bend()); + + /*if let Some(inner) = bend_primitive.inner() { + } else { + let core = bend_primitive.core(); + //let v = vec![]; + //self.move_dot_infringably(dot, to, &self.this_and_wraparound_bow(core.into())) + }*/ + } + #[debug_ensures(self.graph.node_count() == old(self.graph.node_count()))] #[debug_ensures(self.graph.edge_count() == old(self.graph.edge_count()))] - pub fn move_dot(&mut self, dot: LooseDotIndex, to: Point) -> Result<(), ()> { + pub fn move_dot_infringably( + &mut self, + dot: LooseDotIndex, + to: Point, + infringables: &[Index], + ) -> Result<(), ()> { self.primitive(dot) .seg() .map(|seg| self.remove_from_rtree(seg.into())); @@ -397,23 +708,23 @@ impl Layout { dot_weight.circle.pos = to; *self.graph.node_weight_mut(dot.node_index()).unwrap() = Weight::LooseDot(dot_weight); - if let Some(..) = self.detect_collision_except(dot.into(), &[]) { + /*if let Some(..) = dbg!(self.detect_infringement_except(dot.into(), infringables)) { // Restore original state. *self.graph.node_weight_mut(dot.node_index()).unwrap() = Weight::LooseDot(old_weight); self.insert_into_rtree(dot.into()); + self.insert_into_rtree(self.primitive(dot).bend().into()); self.primitive(dot) .seg() - .map(|seg| self.remove_from_rtree(seg.into())); - self.insert_into_rtree(self.primitive(dot).bend().into()); + .map(|seg| self.insert_into_rtree(seg.into())); return Err(()); - } + }*/ self.insert_into_rtree(dot.into()); + self.insert_into_rtree(self.primitive(dot).bend().into()); self.primitive(dot) .seg() - .map(|seg| self.remove_from_rtree(seg.into())); - self.insert_into_rtree(self.primitive(dot).bend().into()); + .map(|seg| self.insert_into_rtree(seg.into())); Ok(()) } @@ -422,7 +733,7 @@ impl Layout { GenericPrimitive::new(index, self) } - fn detect_collision_except(&self, index: Index, except: &[Index]) -> Option { + fn detect_infringement_except(&self, index: Index, except: &[Index]) -> Option { let shape = index.primitive(self).shape(); self.rtree @@ -437,6 +748,21 @@ impl Layout { .next() } + // TODO: Collision and infringement are the same for now. Change this. + fn detect_collision(&self, index: Index) -> Option { + let shape = index.primitive(self).shape(); + + self.rtree + .locate_in_envelope_intersecting(&RTreeObject::envelope(&shape)) + .filter(|wrapper| { + let other_index = wrapper.data; + !index.primitive(self).connectable(other_index) + }) + .filter(|wrapper| shape.intersects(wrapper.geom())) + .map(|wrapper| wrapper.data) + .next() + } + #[debug_ensures(self.graph.node_count() == old(self.graph.node_count()))] #[debug_ensures(self.graph.edge_count() == old(self.graph.edge_count()))] fn insert_into_rtree(&mut self, index: Index) { diff --git a/src/main.rs b/src/main.rs index 91d63e8..1693ccb 100644 --- a/src/main.rs +++ b/src/main.rs @@ -34,12 +34,12 @@ use router::RouterObserver; use sdl2::event::Event; use sdl2::keyboard::Keycode; -use sdl2::video::{Window, GLProfile}; +use sdl2::video::{GLProfile, Window}; use sdl2::EventPump; use shape::{Shape, ShapeTrait}; +use pathfinder_canvas::{ArcDirection, ColorU, FillRule}; use pathfinder_canvas::{Canvas, CanvasFontContext, Path2D}; -use pathfinder_canvas::{ColorU, FillRule, ArcDirection}; use pathfinder_geometry::rect::RectF; use pathfinder_geometry::vector::{vec2f, vec2i}; use pathfinder_gl::{GLDevice, GLVersion}; @@ -63,6 +63,15 @@ enum RouterOrLayout<'a> { Layout(&'a Layout), } +struct EmptyRouterObserver; + +impl RouterObserver for EmptyRouterObserver { + fn on_rework(&mut self, tracer: &Tracer, trace: &Trace) {} + fn before_probe(&mut self, tracer: &Tracer, trace: &Trace, edge: MeshEdgeReference) {} + fn on_probe(&mut self, tracer: &Tracer, trace: &Trace, _edge: MeshEdgeReference) {} + fn on_estimate(&mut self, _tracer: &Tracer, _vertex: VertexIndex) {} +} + struct DebugRouterObserver<'a> { event_pump: &'a mut sdl2::EventPump, window: &'a Window, @@ -74,10 +83,15 @@ impl<'a> DebugRouterObserver<'a> { pub fn new( event_pump: &'a mut sdl2::EventPump, window: &'a Window, - renderer: &'a mut Renderer, + renderer: &'a mut Renderer, font_context: &'a CanvasFontContext, ) -> Self { - Self { event_pump, window, renderer, font_context } + Self { + event_pump, + window, + renderer, + font_context, + } } } @@ -93,7 +107,7 @@ impl<'a> RouterObserver for DebugRouterObserver<'a> { None, Some(tracer.mesh.clone()), &trace.path, - 20, + 40, ); } @@ -110,7 +124,7 @@ impl<'a> RouterObserver for DebugRouterObserver<'a> { None, Some(tracer.mesh.clone()), &path, - 5, + 10, ); } @@ -125,7 +139,7 @@ impl<'a> RouterObserver for DebugRouterObserver<'a> { None, Some(tracer.mesh.clone()), &trace.path, - 5, + 10, ); } @@ -181,7 +195,7 @@ fn main() { let _i = 0; let mut router = Router::new(); - let dot1 = router + let dot_start = router .layout .add_fixed_dot(FixedDotWeight { net: 1, @@ -192,10 +206,10 @@ fn main() { }) .unwrap(); - let dot2 = router + let dot_start2 = router .layout .add_fixed_dot(FixedDotWeight { - net: 5, + net: 3, circle: Circle { pos: (100.5, 500.5).into(), r: 8.0, @@ -203,6 +217,17 @@ fn main() { }) .unwrap(); + let dot_start3 = router + .layout + .add_fixed_dot(FixedDotWeight { + net: 4, + circle: Circle { + pos: (160.5, 430.5).into(), + r: 8.0, + }, + }) + .unwrap(); + let dot_end = router .layout .add_fixed_dot(FixedDotWeight { @@ -217,7 +242,7 @@ fn main() { let dot_end2 = router .layout .add_fixed_dot(FixedDotWeight { - net: 5, + net: 3, circle: Circle { pos: (500.5, 150.5).into(), r: 8.0, @@ -225,6 +250,17 @@ fn main() { }) .unwrap(); + let dot_end3 = router + .layout + .add_fixed_dot(FixedDotWeight { + net: 4, + circle: Circle { + pos: (350.5, 200.5).into(), + r: 8.0, + }, + }) + .unwrap(); + let dot1_1 = router .layout .add_fixed_dot(FixedDotWeight { @@ -411,7 +447,7 @@ fn main() { &mut event_pump, &mut canvas, RouterOrLayout::Router(&mut router), - Some(dot1), + Some(dot_start), Some(dot_end), None, &[], @@ -419,9 +455,10 @@ fn main() { );*/ let _ = router.enroute( - dot1, + dot_start, dot_end, - &mut DebugRouterObserver::new(&mut event_pump, &window, &mut renderer, &font_context), + &mut EmptyRouterObserver, + //&mut DebugRouterObserver::new(&mut event_pump, &window, &mut renderer, &font_context), ); render_times( @@ -441,7 +478,7 @@ fn main() { &mut event_pump, &mut canvas, RouterOrLayout::Router(&mut router), - Some(dot2), + Some(dot_start2), Some(dot_end), None, &[], @@ -449,8 +486,28 @@ fn main() { );*/ let _ = router.enroute( - dot2, + dot_start2, dot_end2, + &mut EmptyRouterObserver, + //&mut DebugRouterObserver::new(&mut event_pump, &window, &mut renderer, &font_context), + ); + + render_times( + &mut event_pump, + &window, + &mut renderer, + &font_context, + RouterOrLayout::Layout(&router.layout), + None, + None, + None, + &[], + -1, + ); + + let _ = router.enroute( + dot_start3, + dot_end3, &mut DebugRouterObserver::new(&mut event_pump, &window, &mut renderer, &font_context), ); @@ -510,7 +567,12 @@ fn render_times( .reroute( from, point! {x: state.x() as f64, y: state.y() as f64}, - &mut DebugRouterObserver::new(event_pump, window, renderer, font_context), + &mut DebugRouterObserver::new( + event_pump, + window, + renderer, + font_context, + ), ) .ok(); } else { @@ -534,25 +596,18 @@ fn render_times( Shape::Dot(dot) => { let mut path = Path2D::new(); path.ellipse( - vec2f( - dot.c.pos.x() as f32, - dot.c.pos.y() as f32 - ), + vec2f(dot.c.pos.x() as f32, dot.c.pos.y() as f32), dot.c.r as f32, - 0.0, 0.0, std::f32::consts::TAU + 0.0, + 0.0, + std::f32::consts::TAU, ); canvas.fill_path(path, FillRule::Winding); } Shape::Seg(seg) => { let mut path = Path2D::new(); - path.move_to(vec2f( - seg.from.x() as f32, - seg.from.y() as f32 - )); - path.line_to(vec2f( - seg.to.x() as f32, - seg.to.y() as f32 - )); + path.move_to(vec2f(seg.from.x() as f32, seg.from.y() as f32)); + path.line_to(vec2f(seg.to.x() as f32, seg.to.y() as f32)); canvas.set_line_width(seg.width as f32); canvas.stroke_path(path); } @@ -565,14 +620,11 @@ fn render_times( let mut path = Path2D::new(); path.arc( - vec2f( - bend.c.pos.x() as f32, - bend.c.pos.y() as f32 - ), + vec2f(bend.c.pos.x() as f32, bend.c.pos.y() as f32), bend.circle().r as f32, angle1 as f32, angle2 as f32, - ArcDirection::CW + ArcDirection::CW, ); canvas.set_line_width(bend.width as f32); canvas.stroke_path(path); @@ -584,7 +636,7 @@ fn render_times( let bottomright = vec2f(envelope.upper()[0] as f32, envelope.upper()[1] as f32); canvas.set_line_width(1.0); canvas.set_stroke_style(ColorU::new(100, 100, 100, 255)); - canvas.stroke_rect(RectF::new(topleft, bottomright-topleft)); + canvas.stroke_rect(RectF::new(topleft, bottomright - topleft)); } if let Some(ref mesh) = mesh { @@ -599,14 +651,8 @@ fn render_times( }; let mut path = Path2D::new(); - path.move_to(vec2f( - start_point.x() as f32, - start_point.y() as f32 - )); - path.line_to(vec2f( - end_point.x() as f32, - end_point.y() as f32 - )); + path.move_to(vec2f(start_point.x() as f32, start_point.y() as f32)); + path.line_to(vec2f(end_point.x() as f32, end_point.y() as f32)); canvas.set_stroke_style(color); canvas.set_line_width(1.0); canvas.stroke_path(path); @@ -614,9 +660,11 @@ fn render_times( } //}); - let mut scene = SceneProxy::from_scene(canvas.into_canvas().into_scene(), - renderer.mode().level, - RayonExecutor); + let mut scene = SceneProxy::from_scene( + canvas.into_canvas().into_scene(), + renderer.mode().level, + RayonExecutor, + ); scene.build_and_render(renderer, BuildOptions::default()); window.gl_swap_window(); diff --git a/src/mesh.rs b/src/mesh.rs index 6a4fe22..bd09134 100644 --- a/src/mesh.rs +++ b/src/mesh.rs @@ -200,6 +200,7 @@ impl<'a> visit::IntoEdges for &'a Mesh { fn edges(self, node: Self::NodeId) -> Self::Edges { Box::new( self.triangulation + // FIXME: node has to be converted to triangulation vertex (?) .edges(node) .flat_map(move |edge| edges(&self.triangulation, edge)), ) diff --git a/src/primitive.rs b/src/primitive.rs index c662497..4c560ca 100644 --- a/src/primitive.rs +++ b/src/primitive.rs @@ -6,9 +6,9 @@ use petgraph::Direction::{Incoming, Outgoing}; use crate::graph::{ DotIndex, FixedBendWeight, FixedDotIndex, FixedDotWeight, FixedSegWeight, GenericIndex, - GetBand, GetEnds, GetNet, GetNodeIndex, GetOffset, GetWidth, Index, Interior, Label, - LooseBendIndex, LooseBendWeight, LooseDotIndex, LooseDotWeight, LooseSegIndex, LooseSegWeight, - MakePrimitive, Retag, Weight, + GetBand, GetNet, GetNodeIndex, GetOffset, GetWidth, Index, Label, LooseBendIndex, + LooseBendWeight, LooseDotIndex, LooseDotWeight, LooseSegIndex, LooseSegWeight, MakePrimitive, + Retag, Weight, }; use crate::layout::Layout; use crate::math::{self, Circle}; @@ -39,6 +39,10 @@ pub trait MakeShape { fn shape(&self) -> Shape; } +pub trait GetInterior { + fn interior(&self) -> Vec; +} + pub trait GetOtherEnd>: GetEnds { fn other_end(&self, end: F) -> F { let ends = self.ends(); @@ -50,6 +54,10 @@ pub trait GetOtherEnd>: GetEnds } } +pub trait GetEnds { + fn ends(&self) -> (F, T); +} + pub trait GetWraparound: GetLayout + GetNodeIndex { fn wraparound(&self) -> Option; } @@ -59,12 +67,6 @@ pub trait GetFirstRail: GetLayout + GetNodeIndex { self.layout() .graph .neighbors_directed(self.node_index(), Incoming) - .filter(|ni| { - self.layout() - .graph - .find_edge(self.node_index(), *ni) - .is_some() - }) .filter(|ni| { matches!( self.layout() @@ -72,7 +74,7 @@ pub trait GetFirstRail: GetLayout + GetNodeIndex { .edge_weight( self.layout() .graph - .find_edge(self.node_index(), *ni) + .find_edge(*ni, self.node_index()) .unwrap() ) .unwrap(), @@ -249,7 +251,7 @@ impl<'a, W> GenericPrimitive<'a, W> { } } -impl<'a, W> Interior for GenericPrimitive<'a, W> { +impl<'a, W> GetInterior for GenericPrimitive<'a, W> { fn interior(&self) -> Vec { vec![self.tagged_weight().retag(self.index.node_index())] } @@ -288,9 +290,7 @@ impl<'a> MakeShape for FixedDot<'a> { }) } } - impl<'a> GetFirstRail for FixedDot<'a> {} - impl<'a> GetWraparound for FixedDot<'a> { fn wraparound(&self) -> Option { self.first_rail() @@ -557,5 +557,6 @@ impl<'a> GetWraparound for LooseBend<'a> { self.outer() } } + impl<'a> GetCore for LooseBend<'a> {} impl<'a> GetInnerOuter for LooseBend<'a> {} diff --git a/src/router.rs b/src/router.rs index aea3023..5927990 100644 --- a/src/router.rs +++ b/src/router.rs @@ -112,148 +112,10 @@ impl Router { _to: Point, _observer: &mut impl RouterObserver, ) -> Result { - /*let to_dot = if let Some(band) = self.layout.next_band(from) { - let to_dot = band.ends().1; - - self.layout.remove_interior(&band); - self.layout.move_dot(to_dot, to); - to_dot - } else { - let from_weight = self.layout.primitive(from).weight(); - self.layout - .add_fixed_dot(FixedDotWeight { - net: from_weight.net, - circle: Circle { pos: to, r: 2.0 }, - }) - .unwrap() // TODO. - }; - - self.enroute(from, to_dot, observer)*/ Ok(Mesh::new(&self.layout)) } - /*pub fn squeeze_around_dot( - &mut self, - head: Head, - around: FixedDotIndex, - cw: bool, - width: f64, - ) -> Result { - let outer = self.layout.primitive(around).outer().unwrap(); - let head = self.draw().segbend_around_dot(head, around, cw, width)?; - self.layout - .reattach_bend(outer, head.segbend.as_ref().unwrap().bend); - - self.reroute_outward(outer)?; - Ok(head) - } - - pub fn squeeze_around_bend( - &mut self, - head: Head, - around: FixedBendIndex, - cw: bool, - width: f64, - ) -> Result { - let outer = self.layout.primitive(around).outer().unwrap(); - let head = self.draw().segbend_around_bend(head, around, cw, width)?; - self.layout - .reattach_bend(outer, head.segbend.as_ref().unwrap().bend); - - self.reroute_outward(outer)?; - Ok(head) - } - - fn reroute_outward(&mut self, bend: FixedBendIndex) -> Result<(), ()> { - let mut bows: Vec = vec![]; - let cw = self.layout.primitive(bend).weight().cw; - - let mut cur_bend = bend; - loop { - bows.push(self.layout.bow(cur_bend)); - - cur_bend = match self.layout.primitive(cur_bend).outer() { - Some(new_bend) => new_bend, - None => break, - } - } - - let core = self.layout.primitive(bend).core().unwrap(); - let mut maybe_inner = self.layout.primitive(bend).inner(); - - for bow in &bows { - self.layout.remove_interior(bow); - } - - for bow in &bows { - let ends = bow.ends(); - let mut head = self.draw().start(ends.0); - let width = 5.0; - - if let Some(inner) = maybe_inner { - head = self.draw().segbend_around_bend(head, inner, cw, width)?; - } else { - head = self.draw().segbend_around_dot(head, core, cw, width)?; - } - - maybe_inner = head.segbend.as_ref().map(|segbend| segbend.bend); - self.draw().finish(head, ends.1, width)?; - self.relax_band(maybe_inner.unwrap()); - } - - Ok(()) - } - - fn relax_band(&mut self, bend: FixedBendIndex) { - let mut prev_bend = bend; - while let Some(cur_bend) = self.layout.primitive(prev_bend).find_prev_akin() { - if self.layout.primitive(cur_bend).cross_product() >= 0. { - self.release_bow(cur_bend); - } - - prev_bend = cur_bend; - } - - let mut prev_bend = bend; - while let Some(cur_bend) = self.layout.primitive(prev_bend).find_next_akin() { - if self.layout.primitive(cur_bend).cross_product() >= 0. { - self.release_bow(cur_bend); - } - - prev_bend = cur_bend; - } - } - - fn release_bow(&mut self, bend: FixedBendIndex) { - let bow = self.layout.bow(bend); - let ends = bow.ends(); - - self.layout.remove_interior(&bow); - - let head = self.draw().start(ends.0); - let _ = self.draw().finish(head, ends.1, 5.0); - } - - pub fn move_dot(&mut self, dot: FixedDotIndex, to: Point) -> Result<(), ()> { - self.layout.move_dot(dot, to)?; - - if let Some(outer) = self.layout.primitive(dot).outer() { - self.reroute_outward(outer)?; - } - - Ok(()) - }*/ - pub fn tracer<'a>(&'a mut self, mesh: &'a Mesh) -> Tracer { Tracer::new(&mut self.layout, &self.rules, mesh) } - - /*pub fn routeedges(&self) -> impl Iterator + '_ { - self.mesh.edge_references().map(|edge| { - ( - self.mesh.position(edge.source()), - self.mesh.position(edge.target()), - ) - }) - }*/ } diff --git a/src/rules.rs b/src/rules.rs index 718a6b3..8cf2d50 100644 --- a/src/rules.rs +++ b/src/rules.rs @@ -19,6 +19,7 @@ impl Conditions { } } +#[derive(Debug, Default, Clone)] pub struct Rules { rulesets: [Option>; 16], } @@ -55,6 +56,7 @@ impl Rules { } } +#[derive(Debug, Default, Clone)] pub struct Ruleset { pub length: Rule, pub clearance: Rule, @@ -69,6 +71,7 @@ impl Ruleset { } } +#[derive(Debug, Default, Clone)] pub struct Rule { pub min: f64, pub opt: Option, diff --git a/src/segbend.rs b/src/segbend.rs index 895bdf1..db44c48 100644 --- a/src/segbend.rs +++ b/src/segbend.rs @@ -1,7 +1,7 @@ use crate::{ - graph::{GetEnds, Index, Interior, LooseBendIndex, LooseDotIndex, LooseSegIndex}, + graph::{Index, LooseBendIndex, LooseDotIndex, LooseSegIndex}, layout::Layout, - primitive::{GetOtherEnd, LooseBend, LooseDot}, + primitive::{GetEnds, GetInterior, GetOtherEnd, LooseBend, LooseDot}, }; #[derive(Debug, Clone, Copy)] @@ -20,7 +20,7 @@ impl Segbend { } } -impl Interior for Segbend { +impl GetInterior for Segbend { fn interior(&self) -> Vec { vec![self.bend.into(), self.dot.into(), self.seg.into()] } diff --git a/src/tracer.rs b/src/tracer.rs index ce4a7a0..956be5e 100644 --- a/src/tracer.rs +++ b/src/tracer.rs @@ -1,11 +1,12 @@ use contracts::debug_ensures; use crate::{ - draw::{BareHead, Draw, Head, SegbendHead}, + draw::Draw, graph::{FixedDotIndex, GetNet, LooseBendIndex}, + guide::{BareHead, Head, SegbendHead}, layout::{Band, Layout}, mesh::{Mesh, VertexIndex}, - primitive::{GetFirstRail, GetInnerOuter}, + primitive::{GetInnerOuter, GetWraparound}, rules::Rules, }; @@ -109,12 +110,6 @@ impl<'a> Tracer<'a> { width: f64, ) -> Result { let head = self.draw().segbend_around_dot(head, around.into(), width)?; - - if let Some(first_rail) = self.layout.primitive(around).first_rail() { - self.layout.reattach_bend(first_rail, head.segbend.bend); - self.update_outward(head.segbend.bend); - } - Ok(head) } @@ -124,98 +119,13 @@ impl<'a> Tracer<'a> { around: LooseBendIndex, width: f64, ) -> Result { - let maybe_outer = self.layout.primitive(around).outer(); let head = self .draw() .segbend_around_bend(head, around.into(), width)?; - if let Some(outer) = maybe_outer { - self.layout.reattach_bend(outer, head.segbend.bend); - self.update_outward(head.segbend.bend); - } - Ok(head) } - fn update_outward(&mut self, bend: LooseBendIndex) { - let mut rail = bend; - - while let Some(outer) = self.layout.primitive(rail).outer() { - self.draw().update_bow(bend); - rail = outer; - } - } - - /*fn redraw_outward(&mut self, bend: FixedBendIndex) -> Result<(), ()> { - let mut bows: Vec = vec![]; - - let mut cur_bend = bend; - loop { - bows.push(self.layout.bow(cur_bend)); - - cur_bend = match self.layout.primitive(cur_bend).outer() { - Some(new_bend) => new_bend, - None => break, - } - } - - let core = self.layout.primitive(bend).core().unwrap(); - let mut maybe_inner = self.layout.primitive(bend).inner(); - - for bow in &bows { - self.layout.remove_interior(bow); - } - - for bow in &bows { - let ends = bow.ends(); - let head = self.draw().start(ends.0); - let width = 5.0; - - let segbend_head = if let Some(inner) = maybe_inner { - self.draw().segbend_around_bend(head, inner.into(), width)? - } else { - self.draw().segbend_around_dot(head, core.into(), width)? - }; - - maybe_inner = Some(segbend_head.segbend.bend); - self.draw().finish(head, ends.1, width)?; - //self.relax_band(maybe_inner.unwrap()); - } - - Ok(()) - }*/ - - /*fn relax_band(&mut self, bend: FixedBendIndex) { - let mut prev_bend = bend; - while let Some(cur_bend) = self.layout.primitive(prev_bend).prev_bend() { - if self.layout.primitive(cur_bend).cross_product() >= 0. { - self.release_bow(cur_bend); - } - - prev_bend = cur_bend; - } - - let mut prev_bend = bend; - while let Some(cur_bend) = self.layout.primitive(prev_bend).next_bend() { - if self.layout.primitive(cur_bend).cross_product() >= 0. { - self.release_bow(cur_bend); - } - - prev_bend = cur_bend; - } - }*/ - - /*fn release_bow(&mut self, bend: FixedBendIndex) { - let bow = self.layout.bow(bend); - let ends = bow.ends(); - - self.layout.remove_interior(&bow); - - let head = self.draw().start(ends.0); - - let _ = self.draw().finish(head, ends.1, 5.0); - }*/ - #[debug_ensures(ret.is_ok() -> trace.path.len() == old(trace.path.len() - 1))] #[debug_ensures(ret.is_err() -> trace.path.len() == old(trace.path.len()))] pub fn undo_step(&mut self, trace: &mut Trace) -> Result<(), ()> { diff --git a/src/triangulation.rs b/src/triangulation.rs index 98536e1..08eed16 100644 --- a/src/triangulation.rs +++ b/src/triangulation.rs @@ -143,8 +143,11 @@ impl<'a, I: Copy + PartialEq + GetNodeIndex, W: GetVertexIndex + HasPosition< } } -impl<'a, I: Copy + PartialEq + GetNodeIndex, W: GetVertexIndex + HasPosition> - visit::IntoEdges for &'a Triangulation +impl< + 'a, + I: Copy + PartialEq + GetNodeIndex + std::fmt::Debug, + W: GetVertexIndex + HasPosition, + > visit::IntoEdges for &'a Triangulation { type Edges = Box> + 'a>;