diff --git a/src/layout.rs b/src/layout.rs index ef57fce..0106604 100644 --- a/src/layout.rs +++ b/src/layout.rs @@ -97,12 +97,6 @@ impl Layout { let bend_to = self.add_dot(self.mesh.dot_weight(head.dot)); let net = self.mesh.dot_weight(head.dot).net; - let mut layer = around; - while let TaggedIndex::Bend(layer_bend) = layer { - layer = self.mesh.around(layer_bend) - } - let center = *layer.as_dot().unwrap(); - let bend = self.mesh.add_bend(head.dot, bend_to, around, BendWeight {net, cw}); Head {dot: bend_to, bend: Some(bend)} } @@ -132,12 +126,10 @@ impl Layout { match maybe_bend { Some(bend) => { - let head_around = self.mesh.around(bend); - - match self.mesh.weight(head_around) { - Weight::Dot(..) => self.dot_guidecircle(*head_around.as_dot().unwrap(), width + 5.0, conditions), - Weight::Seg(..) => unreachable!(), - Weight::Bend(..) => self.bend_guidecircle(*head_around.as_bend().unwrap(), width, conditions), + if let Some(inner) = self.mesh.inner(bend) { + self.bend_guidecircle(inner, width, conditions) + } else { + self.dot_guidecircle(self.mesh.core(bend), width + 5.0, conditions) } }, None => Circle { @@ -163,18 +155,18 @@ impl Layout { } fn bend_guidecircle(&self, bend: BendIndex, width: f64, conditions: Conditions) -> Circle { - let mut layer = TaggedIndex::Bend(bend); let mut r = width + self.rules.ruleset(conditions).clearance.min; + let mut layer = bend; - while let TaggedIndex::Bend(layer_bend) = layer { - layer = self.mesh.around(layer_bend); - r += 5.0 + self.mesh.primitive(layer).width(); + while let Some(inner) = self.mesh.inner(layer) { + r += 5.0 + self.mesh.primitive(inner.tag()).width(); + layer = inner; } - let circle = self.mesh.weight(layer).as_dot().unwrap().circle; + let core_circle = self.mesh.dot_weight(self.mesh.core(bend)).circle; Circle { - pos: circle.pos, - r: circle.r - 5.0 + r, + pos: core_circle.pos, + r: core_circle.r + r + 15.0 } } @@ -234,10 +226,6 @@ impl Layout { } pub fn primitive(&self, index: TaggedIndex) -> Primitive { - return self.mesh.primitive(index); + self.mesh.primitive(index) } - - /*pub fn bend(&self, index: DotIndex) -> Option { - return self.mesh.bend(index); - }*/ } diff --git a/src/mesh.rs b/src/mesh.rs index 445a9f6..fddf9c3 100644 --- a/src/mesh.rs +++ b/src/mesh.rs @@ -1,5 +1,6 @@ use std::marker::PhantomData; use enum_as_inner::EnumAsInner; +use petgraph::Direction::{Outgoing, Incoming}; use petgraph::stable_graph::{StableDiGraph, NodeIndex, EdgeIndex}; use petgraph::visit::EdgeRef; use rstar::{RTree, RTreeObject, AABB}; @@ -103,25 +104,38 @@ impl Mesh { } pub fn add_bend(&mut self, from: DotIndex, to: DotIndex, around: TaggedIndex, weight: BendWeight) -> BendIndex { + match around { + TaggedIndex::Dot(core) => + self.add_core_bend(from, to, core, weight), + TaggedIndex::Bend(around) => + self.add_noncore_bend(from, to, around, weight), + TaggedIndex::Seg(..) => unreachable!(), + } + } + + pub fn add_core_bend(&mut self, from: DotIndex, to: DotIndex, core: DotIndex, weight: BendWeight) -> BendIndex { let bend = BendIndex::new(self.graph.add_node(Weight::Bend(weight))); self.graph.add_edge(bend.index, from.index, Label::End); self.graph.add_edge(bend.index, to.index, Label::End); - - match around { - TaggedIndex::Dot(DotIndex {index: around_index, ..}) => { - self.graph.add_edge(bend.index, around_index, Label::Around); - }, - TaggedIndex::Seg(..) => unreachable!(), - TaggedIndex::Bend(BendIndex {index: around_index, ..}) => { - self.graph.add_edge(bend.index, around_index, Label::Around); - }, - } + self.graph.add_edge(bend.index, core.index, Label::Core); let index = TaggedIndex::Bend(bend); self.rtree.insert(RTreeWrapper::new(self.primitive(index), index)); bend } + pub fn add_noncore_bend(&mut self, from: DotIndex, to: DotIndex, inner: BendIndex, weight: BendWeight) -> BendIndex { + let core = *self.graph.neighbors(inner.index) + .filter(|ni| self.graph.edge_weight(self.graph.find_edge(inner.index, *ni).unwrap()).unwrap().is_core()) + .map(|ni| DotIndex::new(ni)) + .collect::>() + .first() + .unwrap(); + let bend = self.add_core_bend(from, to, core, weight); + self.graph.add_edge(inner.index, bend.index, Label::Outer); + bend + } + pub fn remove_bend(&mut self, bend: BendIndex) { self.rtree.remove(&RTreeWrapper::new(self.primitive(TaggedIndex::Bend(bend)), TaggedIndex::Bend(bend))); self.graph.remove_node(bend.index); @@ -139,45 +153,43 @@ impl Mesh { .into_iter() .map(|index| self.dot_weight(index)) .collect(), - around_weight: match index { - TaggedIndex::Bend(bend) => Some(self.weight(self.around(bend))), - _ => None, - }, - focus: match index { + core_pos: match index { TaggedIndex::Bend(bend) => { - let mut layer = index; - while let TaggedIndex::Bend(layer_bend) = layer { - layer = self.around(layer_bend) - } - Some(self.weight(layer).as_dot().unwrap().circle.pos) + Some(self.dot_weight(self.core(bend)).circle.pos) }, _ => None, }, } } - /*pub fn focus(&self, bend: BendIndex) -> DotIndex { - let mut layer = bend.tag(); - while let TaggedIndex::Bend(bend) = layer { - layer = self.around(layer).unwrap(); - } - - *layer.as_dot().unwrap() - }*/ - pub fn around(&self, bend: BendIndex) -> TaggedIndex { - for neighbor in self.graph.neighbors(bend.index) { - let edge = self.graph.find_edge(bend.index, neighbor).unwrap(); - - if self.graph.edge_weight(edge).unwrap().is_around() { - return match self.graph.node_weight(neighbor).unwrap() { - Weight::Dot(dot) => DotIndex::new(neighbor).tag(), - Weight::Bend(bend) => BendIndex::new(neighbor).tag(), - Weight::Seg(seg) => SegIndex::new(neighbor).tag(), - } - } + if let Some(inner) = self.inner(bend) { + TaggedIndex::Bend(inner) + } else { + TaggedIndex::Dot(self.core(bend)) } - unreachable!(); + } + + pub fn core(&self, bend: BendIndex) -> DotIndex { + self.graph.neighbors(bend.index) + .filter(|ni| self.graph.edge_weight(self.graph.find_edge(bend.index, *ni).unwrap()).unwrap().is_core()) + .map(|ni| DotIndex::new(ni)) + .next() + .unwrap() + } + + pub fn inner(&self, bend: BendIndex) -> Option { + self.graph.neighbors_directed(bend.index, Incoming) + .filter(|ni| self.graph.edge_weight(self.graph.find_edge(*ni, bend.index).unwrap()).unwrap().is_outer()) + .map(|ni| BendIndex::new(ni)) + .next() + } + + pub fn outer(&self, bend: BendIndex) -> Option { + self.graph.neighbors_directed(bend.index, Outgoing) + .filter(|ni| self.graph.edge_weight(self.graph.find_edge(bend.index, *ni).unwrap()).unwrap().is_outer()) + .map(|ni| BendIndex::new(ni)) + .next() } pub fn ends(&self, index: TaggedIndex) -> Vec { diff --git a/src/primitive.rs b/src/primitive.rs index 213249d..8ca7486 100644 --- a/src/primitive.rs +++ b/src/primitive.rs @@ -7,8 +7,7 @@ use crate::{weight::{Weight, DotWeight}, math::Circle}; pub struct Primitive { pub weight: Weight, pub dot_neighbor_weights: Vec, - pub around_weight: Option, - pub focus: Option, + pub core_pos: Option, } impl Primitive { @@ -36,9 +35,9 @@ impl Primitive { Weight::Dot(dot) => Some(dot.circle), Weight::Seg(seg) => None, Weight::Bend(bend) => { - let r = self.dot_neighbor_weights[0].circle.pos.euclidean_distance(&self.focus.unwrap()); + let r = self.dot_neighbor_weights[0].circle.pos.euclidean_distance(&self.core_pos.unwrap()); Some(Circle { - pos: self.focus.unwrap(), + pos: self.core_pos.unwrap(), r, }) } diff --git a/src/weight.rs b/src/weight.rs index d07f191..414470c 100644 --- a/src/weight.rs +++ b/src/weight.rs @@ -29,5 +29,6 @@ pub enum Weight { #[derive(Debug, EnumAsInner, Clone, Copy, PartialEq)] pub enum Label { End, - Around, + Outer, + Core, }