diff --git a/src/guide.rs b/src/guide.rs index c8d524a..ddd0641 100644 --- a/src/guide.rs +++ b/src/guide.rs @@ -5,6 +5,7 @@ use crate::{ graph::{BendIndex, DotIndex}, layout::Layout, math::{self, Circle}, + primitive::MakeShape, rules::{Conditions, Rules}, }; diff --git a/src/layout.rs b/src/layout.rs index c1eaff2..f3e77fc 100644 --- a/src/layout.rs +++ b/src/layout.rs @@ -13,7 +13,7 @@ use crate::graph::{ BendIndex, BendWeight, DotIndex, DotWeight, Index, Interior, Label, Retag, SegIndex, SegWeight, Tag, TaggedIndex, Weight, }; -use crate::primitive::Primitive; +use crate::primitive::{MakeShape, Primitive}; use crate::segbend::Segbend; use crate::shape::{Shape, ShapeTrait}; @@ -49,7 +49,7 @@ impl Layout { } #[debug_ensures(self.graph.node_count() == old(self.graph.node_count() - 1))] - pub fn remove(&mut self, index: Index) { + pub fn remove(&mut self, index: Index) { // Unnecessary retag. It should be possible to elide it. let weight = *self.graph.node_weight(index.index).unwrap(); @@ -236,11 +236,14 @@ 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_collides_except( &mut self, - index: Index, + index: Index, except: &[TaggedIndex], - ) -> Result<(), ()> { + ) -> Result<(), ()> + where + for<'a> Primitive<'a, W>: MakeShape, + { if let Some(..) = self.detect_collision_except(index, except) { self.remove(index); return Err(()); @@ -310,15 +313,18 @@ impl Layout { Ok(()) } - pub fn primitive(&self, index: Index) -> Primitive { + pub fn primitive(&self, index: Index) -> Primitive { Primitive::new(index, &self.graph) } - fn detect_collision_except( + fn detect_collision_except( &self, - index: Index, + index: Index, except: &[TaggedIndex], - ) -> Option { + ) -> Option + where + for<'a> Primitive<'a, W>: MakeShape, + { let primitive = self.primitive(index); let shape = primitive.shape(); diff --git a/src/mesh.rs b/src/mesh.rs index 1244915..6325d94 100644 --- a/src/mesh.rs +++ b/src/mesh.rs @@ -7,8 +7,8 @@ use spade::{ DelaunayTriangulation, HasPosition, InsertionError, Point2, Triangulation, }; -use crate::shape::ShapeTrait; use crate::{graph::DotIndex, layout::Layout}; +use crate::{primitive::MakeShape, shape::ShapeTrait}; #[derive(Debug, Clone)] struct Vertex { diff --git a/src/primitive.rs b/src/primitive.rs index 8097f03..69383d8 100644 --- a/src/primitive.rs +++ b/src/primitive.rs @@ -1,5 +1,6 @@ use std::mem::{self, swap}; +use enum_dispatch::enum_dispatch; use petgraph::stable_graph::{NodeIndex, StableDiGraph}; use petgraph::Direction::{Incoming, Outgoing}; @@ -10,6 +11,10 @@ use crate::graph::{ use crate::math::{self, Circle}; use crate::shape::{BendShape, DotShape, SegShape, Shape, ShapeTrait}; +pub trait MakeShape { + fn shape(&self) -> Shape; +} + #[derive(Debug)] pub struct Primitive<'a, W> { pub index: Index, @@ -21,38 +26,6 @@ impl<'a, W> Primitive<'a, W> { Self { index, graph } } - pub fn shape(&self) -> Shape { - match self.tagged_weight() { - Weight::Dot(dot) => Shape::Dot(DotShape { c: dot.circle }), - Weight::Seg(seg) => { - let ends = self.ends(); - Shape::Seg(SegShape { - from: self.primitive(ends.0).weight().circle.pos, - to: self.primitive(ends.1).weight().circle.pos, - width: seg.width, - }) - } - Weight::Bend(bend) => { - let ends = self.ends(); - - let mut bend_shape = BendShape { - from: self.primitive(ends.0).weight().circle.pos, - to: self.primitive(ends.1).weight().circle.pos, - c: Circle { - pos: self.primitive(self.core().unwrap()).weight().circle.pos, - r: self.inner_radius(), - }, - width: self.primitive(ends.0).weight().circle.r * 2.0, - }; - - if bend.cw { - swap(&mut bend_shape.from, &mut bend_shape.to); - } - Shape::Bend(bend_shape) - } - } - } - fn inner_radius(&self) -> f64 { let mut r = 0.0; let mut layer = BendIndex::new(self.index.index); @@ -224,13 +197,13 @@ impl<'a, W> Primitive<'a, W> { } } -impl<'a, Weight> Interior for Primitive<'a, Weight> { +impl<'a, W> Interior for Primitive<'a, W> { fn interior(&self) -> Vec { vec![self.tagged_index()] } } -impl<'a, Weight> Ends for Primitive<'a, Weight> { +impl<'a, W> Ends for Primitive<'a, W> { fn ends(&self) -> (DotIndex, DotIndex) { let v = self .graph @@ -254,8 +227,6 @@ impl<'a, Weight> Ends for Primitive<'a, Weight> { } pub type Dot<'a> = Primitive<'a, DotWeight>; -pub type Seg<'a> = Primitive<'a, SegWeight>; -pub type Bend<'a> = Primitive<'a, BendWeight>; impl<'a> Dot<'a> { pub fn bend(&self) -> Option { @@ -296,6 +267,16 @@ impl<'a> Dot<'a> { } } +impl<'a> MakeShape for Dot<'a> { + fn shape(&self) -> Shape { + Shape::Dot(DotShape { + c: self.weight().circle, + }) + } +} + +pub type Seg<'a> = Primitive<'a, SegWeight>; + impl<'a> Seg<'a> { pub fn next(&self) -> Option { self.next_node().map(|ni| DotIndex::new(ni)) @@ -310,6 +291,19 @@ impl<'a> Seg<'a> { } } +impl<'a> MakeShape for Seg<'a> { + fn shape(&self) -> Shape { + let ends = self.ends(); + Shape::Seg(SegShape { + from: self.primitive(ends.0).weight().circle.pos, + to: self.primitive(ends.1).weight().circle.pos, + width: self.weight().width, + }) + } +} + +pub type Bend<'a> = Primitive<'a, BendWeight>; + impl<'a> Bend<'a> { pub fn around(&self) -> TaggedIndex { if let Some(inner) = self.inner() { @@ -365,3 +359,24 @@ impl<'a> Bend<'a> { math::cross_product(end1 - center, end2 - center) } } + +impl<'a> MakeShape for Bend<'a> { + fn shape(&self) -> Shape { + let ends = self.ends(); + + let mut bend_shape = BendShape { + from: self.primitive(ends.0).weight().circle.pos, + to: self.primitive(ends.1).weight().circle.pos, + c: Circle { + pos: self.primitive(self.core().unwrap()).weight().circle.pos, + r: self.inner_radius(), + }, + width: self.primitive(ends.0).weight().circle.r * 2.0, + }; + + if self.weight().cw { + swap(&mut bend_shape.from, &mut bend_shape.to); + } + Shape::Bend(bend_shape) + } +} diff --git a/src/tracer.rs b/src/tracer.rs index 429c6e7..ecc5004 100644 --- a/src/tracer.rs +++ b/src/tracer.rs @@ -6,6 +6,7 @@ use crate::{ graph::{BendIndex, DotIndex, Ends}, layout::Layout, mesh::{Mesh, MeshEdgeReference, VertexIndex}, + primitive::MakeShape, rules::Rules, };