From 8456259b38cbc2719739717852d604e6091aa5ab Mon Sep 17 00:00:00 2001 From: Mikolaj Wielgus Date: Thu, 24 Aug 2023 03:32:50 +0200 Subject: [PATCH] Rename `Layout` to `Router`, `Mesh` to `Layout` --- src/guide.rs | 24 +- src/layout.rs | 592 ++++++++++++++++++++++++++------------------------ src/main.rs | 213 ++++++++++-------- src/mesh.rs | 333 ---------------------------- src/router.rs | 312 ++++++++++++++++++++++++++ 5 files changed, 747 insertions(+), 727 deletions(-) delete mode 100644 src/mesh.rs create mode 100644 src/router.rs diff --git a/src/guide.rs b/src/guide.rs index 8ce6810..2887dc3 100644 --- a/src/guide.rs +++ b/src/guide.rs @@ -2,22 +2,22 @@ use geo::Line; use crate::{ graph::{BendIndex, DotIndex}, - layout::Head, + layout::Layout, math::{self, Circle}, - mesh::Mesh, + router::Head, rules::{Conditions, Rules}, }; pub struct Guide<'a, 'b> { - mesh: &'a Mesh, + layout: &'a Layout, rules: &'a Rules, conditions: &'b Conditions, } impl<'a, 'b> Guide<'a, 'b> { - pub fn new(mesh: &'a Mesh, rules: &'a Rules, conditions: &'b Conditions) -> Self { + pub fn new(layout: &'a Layout, rules: &'a Rules, conditions: &'b Conditions) -> Self { Self { - mesh, + layout, rules, conditions, } @@ -26,7 +26,7 @@ impl<'a, 'b> Guide<'a, 'b> { pub fn head_into_dot_segment(&self, head: &Head, into: DotIndex, width: f64) -> Line { let from_circle = self.head_circle(&head, width); let to_circle = Circle { - pos: self.mesh.primitive(into).weight().circle.pos, + pos: self.layout.primitive(into).weight().circle.pos, r: 0.0, }; @@ -64,7 +64,7 @@ impl<'a, 'b> Guide<'a, 'b> { pub fn head_cw(&self, head: &Head) -> Option { match head.bend { - Some(bend) => Some(self.mesh.primitive(bend).weight().cw), + Some(bend) => Some(self.layout.primitive(bend).weight().cw), None => None, } } @@ -81,14 +81,14 @@ impl<'a, 'b> Guide<'a, 'b> { match maybe_bend { Some(bend) => { - if let Some(inner) = self.mesh.primitive(bend).inner() { + if let Some(inner) = self.layout.primitive(bend).inner() { self.bend_circle(inner, width) } else { - self.dot_circle(self.mesh.primitive(bend).core().unwrap(), width + 5.0) + self.dot_circle(self.layout.primitive(bend).core().unwrap(), width + 5.0) } } None => Circle { - pos: self.mesh.primitive(head.dot).weight().circle.pos, + pos: self.layout.primitive(head.dot).weight().circle.pos, r: 0.0, }, } @@ -96,7 +96,7 @@ impl<'a, 'b> Guide<'a, 'b> { fn bend_circle(&self, bend: BendIndex, width: f64) -> Circle { let mut circle = self - .mesh + .layout .primitive(bend) .shape() .as_bend() @@ -107,7 +107,7 @@ impl<'a, 'b> Guide<'a, 'b> { } fn dot_circle(&self, dot: DotIndex, width: f64) -> Circle { - let circle = self.mesh.primitive(dot).weight().circle; + let circle = self.layout.primitive(dot).weight().circle; Circle { pos: circle.pos, r: circle.r + width + self.rules.ruleset(self.conditions).clearance.min, diff --git a/src/layout.rs b/src/layout.rs index 0a5ebfa..73e1301 100644 --- a/src/layout.rs +++ b/src/layout.rs @@ -1,318 +1,338 @@ -use geo::geometry::Point; -use std::cell::{Ref, RefCell}; -use std::rc::Rc; +use geo::Point; +use petgraph::stable_graph::{EdgeIndex, NodeIndex, StableDiGraph}; +use petgraph::visit::EdgeRef; +use petgraph::Direction::Incoming; +use rstar::primitives::GeomWithData; +use rstar::RTree; +use spade::{DelaunayTriangulation, HasPosition, Point2, Triangulation}; -use crate::graph::{BendIndex, DotIndex, Path, SegIndex, TaggedIndex}; -use crate::graph::{BendWeight, DotWeight, SegWeight, TaggedWeight}; -use crate::guide::Guide; -use crate::math; -use crate::math::Circle; -use crate::mesh::Mesh; -use crate::rules::{Conditions, Rules}; +use crate::bow::Bow; +use crate::graph::{ + BendIndex, BendWeight, DotIndex, DotWeight, Index, Label, Path, SegIndex, SegWeight, Tag, + TaggedIndex, TaggedWeight, +}; +use crate::primitive::Primitive; use crate::shape::Shape; -pub struct Layout { - mesh: Mesh, - rules: Rules, -} +pub type RTreeWrapper = GeomWithData; -pub struct Head { - pub dot: DotIndex, - pub bend: Option, +pub struct Layout { + pub rtree: RTree, + pub graph: StableDiGraph, } impl Layout { pub fn new() -> Self { Layout { - mesh: Mesh::new(), - rules: Rules::new(), + rtree: RTree::new(), + graph: StableDiGraph::default(), } } - pub fn draw_start(&mut self, from: DotIndex) -> Head { - Head { - dot: from, - bend: self.mesh.primitive(from).bend(), + pub fn remove_open_set(&mut self, open_set: Vec) { + for index in open_set.iter().filter(|index| !index.is_dot()) { + untag!(index, self.remove(*index)); + } + + // We must remove the dots only after the segs and bends because we need dots to calculate + // the shapes, which we need to remove the segs and bends from the R-tree. + + for index in open_set.iter().filter(|index| index.is_dot()) { + untag!(index, self.remove(*index)); } } - pub fn draw_finish(&mut self, head: Head, into: DotIndex, width: f64) -> Result<(), ()> { - if let Some(bend) = self.mesh.primitive(into).bend() { - self.draw_finish_in_bend(head, bend, into, width) - } else { - self.draw_finish_in_dot(head, into, width) - } - } + 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(); - fn draw_finish_in_dot(&mut self, head: Head, into: DotIndex, width: f64) -> Result<(), ()> { - let tangent = self - .guide(&Default::default()) - .head_into_dot_segment(&head, into, width); - let head = self.extend_head(head, tangent.start_point())?; - self.add_seg(head.dot, into, width)?; - Ok(()) - } - - fn draw_finish_in_bend( - &mut self, - head: Head, - to_bend: BendIndex, - to: DotIndex, - width: f64, - ) -> Result<(), ()> { - let to_head = Head { - bend: Some(to_bend), - dot: to, - }; - let to_cw = self.guide(&Default::default()).head_cw(&to_head).unwrap(); - let tangent = self - .guide(&Default::default()) - .head_around_bend_segment(&head, to_bend, to_cw, width); - let head = self.extend_head(head, tangent.start_point())?; - - let to_head = self.extend_head(to_head, tangent.end_point())?; - self.add_seg(head.dot, to, width)?; - Ok(()) - } - - pub fn squeeze_around_dot( - &mut self, - head: Head, - around: DotIndex, - cw: bool, - width: f64, - ) -> Result { - let outer = self.mesh.primitive(around).outer().unwrap(); - let head = self.draw_around_dot(head, around, cw, width)?; - self.mesh.reattach_bend(outer, head.bend.unwrap()); - - self.reroute_outward(outer)?; - Ok(head) - } - - pub fn draw_around_dot( - &mut self, - head: Head, - around: DotIndex, - cw: bool, - width: f64, - ) -> Result { - let tangent = self - .guide(&Default::default()) - .head_around_dot_segment(&head, around, cw, width); - - let head = self.extend_head(head, tangent.start_point())?; - self.draw_seg_bend( - head, - TaggedIndex::Dot(around), - tangent.end_point(), - cw, - width, - ) - } - - pub fn squeeze_around_bend( - &mut self, - head: Head, - around: BendIndex, - cw: bool, - width: f64, - ) -> Result { - let outer = self.mesh.primitive(around).outer().unwrap(); - let head = self.draw_around_bend(head, around, cw, width)?; - self.mesh.reattach_bend(outer, head.bend.unwrap()); - - self.reroute_outward(outer)?; - Ok(head) - } - - pub fn draw_around_bend( - &mut self, - head: Head, - around: BendIndex, - cw: bool, - width: f64, - ) -> Result { - let tangent = self - .guide(&Default::default()) - .head_around_bend_segment(&head, around, cw, width); - - let head = self.extend_head(head, tangent.start_point())?; - self.draw_seg_bend( - head, - TaggedIndex::Bend(around), - tangent.end_point(), - cw, - width, - ) - } - - fn draw_seg_bend( - &mut self, - head: Head, - around: TaggedIndex, - to: Point, - cw: bool, - width: f64, - ) -> Result { - let head = self.draw_seg(head, to, width)?; - let bend_to = self.add_dot(self.mesh.primitive(head.dot).weight())?; - let net = self.mesh.primitive(head.dot).weight().net; - - let bend = self - .mesh - .add_bend(head.dot, bend_to, around, BendWeight { net, cw })?; - Ok(Head { - dot: bend_to, - bend: Some(bend), - }) - } - - fn reroute_outward(&mut self, bend: BendIndex) -> Result<(), ()> { - let mut endss: Vec<[DotIndex; 2]> = vec![]; - let mut interiors: Vec> = vec![]; - let cw = self.mesh.primitive(bend).weight().cw; - - let mut cur_bend = bend; - loop { - let bow = self.mesh.bow(cur_bend); - endss.push(bow.ends()); - interiors.push(bow.interior()); - - cur_bend = match self.mesh.primitive(cur_bend).outer() { - Some(new_bend) => new_bend, - None => break, - } - } - - let core = self.mesh.primitive(bend).core().unwrap(); - let mut maybe_inner = self.mesh.primitive(bend).inner(); - - for interior in interiors { - self.mesh.remove_open_set(interior); - } - - for ends in endss { - let mut head = self.draw_start(ends[0]); - let width = 5.0; - - if let Some(inner) = maybe_inner { - head = self.draw_around_bend(head, inner, cw, width)?; - } else { - head = self.draw_around_dot(head, core, cw, width)?; - } - - maybe_inner = head.bend; - self.draw_finish(head, ends[1], width)?; - self.relax_band(maybe_inner.unwrap()); - } - - Ok(()) - } - - fn draw_seg(&mut self, head: Head, to: Point, width: f64) -> Result { - let net = self.mesh.primitive(head.dot).weight().net; - - assert!(width <= self.mesh.primitive(head.dot).weight().circle.r * 2.); - - let to_index = self.mesh.add_dot(DotWeight { - net, - circle: Circle { - pos: to, - r: width / 2.0, - }, - })?; - self.add_seg(head.dot, to_index, width)?; - Ok(Head { - dot: to_index, - bend: None, - }) - } - - fn relax_band(&mut self, bend: BendIndex) { - let mut prev_bend = bend; - while let Some(cur_bend) = self.mesh.primitive(prev_bend).prev_akin() { - if self.mesh.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.mesh.primitive(prev_bend).next_akin() { - if self.mesh.primitive(cur_bend).cross_product() >= 0. { - self.release_bow(cur_bend); - } - - prev_bend = cur_bend; - } - } - - fn release_bow(&mut self, bend: BendIndex) { - let bow = self.mesh.bow(bend); - let ends = bow.ends(); - - self.mesh.remove_open_set(bow.interior()); - - let head = self.draw_start(ends[0]); - let _ = self.draw_finish(head, ends[1], 5.); - } - - pub fn move_dot(&mut self, dot: DotIndex, to: Point) -> Result<(), ()> { - self.mesh.move_dot(dot, to)?; - - if let Some(outer) = self.mesh.primitive(dot).outer() { - self.reroute_outward(outer)?; - } - - Ok(()) - } - - fn extend_head(&mut self, head: Head, to: Point) -> Result { - if let Some(..) = head.bend { - self.extend_head_bend(head, to) - } else { - Ok(head) - // No assertion for now because we temporarily use floats. - - //println!("{:?} {:?}", self.mesh.weight(TaggedIndex::Dot(from)).as_dot().unwrap().circle.pos, to); - //assert!(self.mesh.weight(TaggedIndex::Dot(from)).as_dot().unwrap().circle.pos == to); - } - } - - fn extend_head_bend(&mut self, head: Head, to: Point) -> Result { - self.mesh.extend_bend(head.bend.unwrap(), head.dot, to)?; - Ok(head) + let wrapper = RTreeWrapper::new(self.primitive(index).shape(), index.retag(&weight)); + assert!(self.rtree.remove(&wrapper).is_some()); + self.graph.remove_node(index.index); } pub fn add_dot(&mut self, weight: DotWeight) -> Result { - self.mesh.add_dot(weight) + let dot = DotIndex::new(self.graph.add_node(TaggedWeight::Dot(weight))); + + self.fail_and_remove_if_collides_except(dot, &[])?; + self.insert_into_rtree(dot.tag()); + self.triangulate(); + + Ok(dot) } - pub fn add_seg(&mut self, from: DotIndex, to: DotIndex, width: f64) -> Result { - let net = self.mesh.primitive(from).weight().net; - self.mesh.add_seg(from, to, SegWeight { net, width }) + pub fn add_seg( + &mut self, + from: DotIndex, + to: DotIndex, + weight: SegWeight, + ) -> Result { + let seg = SegIndex::new(self.graph.add_node(TaggedWeight::Seg(weight))); + + self.graph.add_edge(from.index, seg.index, Label::End); + self.graph.add_edge(seg.index, to.index, Label::End); + + self.fail_and_remove_if_collides_except(seg, &[from.tag(), to.tag()])?; + self.insert_into_rtree(seg.tag()); + + self.graph + .node_weight_mut(from.index) + .unwrap() + .as_dot_mut() + .unwrap() + .net = weight.net; + self.graph + .node_weight_mut(to.index) + .unwrap() + .as_dot_mut() + .unwrap() + .net = weight.net; + + Ok(seg) } - pub fn shapes(&self) -> impl Iterator + '_ { - self.mesh - .nodes() - .map(|ni| untag!(ni, self.mesh.primitive(ni).shape())) + pub fn add_bend( + &mut self, + from: DotIndex, + to: DotIndex, + around: TaggedIndex, + weight: BendWeight, + ) -> Result { + match around { + TaggedIndex::Dot(core) => self.add_core_bend(from, to, core, weight), + TaggedIndex::Bend(around) => self.add_outer_bend(from, to, around, weight), + TaggedIndex::Seg(..) => unreachable!(), + } } - pub fn edges(&self) -> impl Iterator + '_ { - self.mesh.edges().map(|endpoints| { - let index0 = endpoints.0; - let index1 = endpoints.1; + pub fn add_core_bend( + &mut self, + from: DotIndex, + to: DotIndex, + core: DotIndex, + weight: BendWeight, + ) -> Result { + let bend = BendIndex::new(self.graph.add_node(TaggedWeight::Bend(weight))); + + self.graph.add_edge(from.index, bend.index, Label::End); + self.graph.add_edge(bend.index, to.index, Label::End); + self.graph.add_edge(bend.index, core.index, Label::Core); + + self.fail_and_remove_if_collides_except(bend, &[from.tag(), to.tag(), core.tag()])?; + self.insert_into_rtree(bend.tag()); + self.triangulate(); + Ok(bend) + } + + pub fn add_outer_bend( + &mut self, + from: DotIndex, + to: DotIndex, + inner: BendIndex, + weight: BendWeight, + ) -> Result { + 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); + Ok(bend) + } + + pub fn reattach_bend(&mut self, bend: BendIndex, inner: BendIndex) { + if let Some(old_inner_edge) = self + .graph + .edges_directed(bend.index, Incoming) + .filter(|edge| *edge.weight() == Label::Outer) + .next() + { + self.graph.remove_edge(old_inner_edge.id()); + } + self.graph.add_edge(inner.index, bend.index, Label::Outer); + } + + pub fn extend_bend(&mut self, bend: BendIndex, dot: DotIndex, to: Point) -> Result<(), ()> { + self.remove_from_rtree(bend.tag()); + self.move_dot(dot, to)?; + self.insert_into_rtree(bend.tag()); + self.triangulate(); + Ok(()) + } + + pub fn move_dot(&mut self, dot: DotIndex, to: Point) -> Result<(), ()> { + let mut cur_bend = self.primitive(dot).outer(); + loop { + match cur_bend { + Some(..) => (), + None => break, + } + + self.remove_from_rtree(cur_bend.unwrap().tag()); + cur_bend = self.primitive(cur_bend.unwrap()).outer(); + } + + self.remove_from_rtree(dot.tag()); + + let mut dot_weight = self.primitive(dot).weight(); + let old_weight = dot_weight; + + dot_weight.circle.pos = to; + *self.graph.node_weight_mut(dot.index).unwrap() = TaggedWeight::Dot(dot_weight); + + if let Some(..) = self.detect_collision_except(dot, &[]) { + // Restore original state. + *self.graph.node_weight_mut(dot.index).unwrap() = TaggedWeight::Dot(old_weight); + self.insert_into_rtree(dot.tag()); + + return Err(()); + } + + self.insert_into_rtree(dot.tag()); + self.triangulate(); + + let mut cur_bend = self.primitive(dot).outer(); + loop { + match cur_bend { + Some(..) => (), + None => break, + } + + self.insert_into_rtree(cur_bend.unwrap().tag()); + cur_bend = self.primitive(cur_bend.unwrap()).outer(); + } + + Ok(()) + } + + pub fn nodes(&self) -> impl Iterator + '_ { + self.rtree.iter().map(|wrapper| wrapper.data) + } + + pub fn edges(&self) -> impl Iterator + '_ { + self.graph.edge_indices().map(|edge| { + let endpoints = self.graph.edge_endpoints(edge).unwrap(); ( - untag!(index0, self.mesh.primitive(index0).shape().center()), - untag!(index1, self.mesh.primitive(index1).shape().center()), + Index::