Rename `Layout` to `Router`, `Mesh` to `Layout`

This commit is contained in:
Mikolaj Wielgus 2023-08-24 03:32:50 +02:00
parent 234a52f9e8
commit 8456259b38
5 changed files with 747 additions and 727 deletions

View File

@ -2,22 +2,22 @@ use geo::Line;
use crate::{ use crate::{
graph::{BendIndex, DotIndex}, graph::{BendIndex, DotIndex},
layout::Head, layout::Layout,
math::{self, Circle}, math::{self, Circle},
mesh::Mesh, router::Head,
rules::{Conditions, Rules}, rules::{Conditions, Rules},
}; };
pub struct Guide<'a, 'b> { pub struct Guide<'a, 'b> {
mesh: &'a Mesh, layout: &'a Layout,
rules: &'a Rules, rules: &'a Rules,
conditions: &'b Conditions, conditions: &'b Conditions,
} }
impl<'a, 'b> Guide<'a, 'b> { 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 { Self {
mesh, layout,
rules, rules,
conditions, 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 { pub fn head_into_dot_segment(&self, head: &Head, into: DotIndex, width: f64) -> Line {
let from_circle = self.head_circle(&head, width); let from_circle = self.head_circle(&head, width);
let to_circle = Circle { let to_circle = Circle {
pos: self.mesh.primitive(into).weight().circle.pos, pos: self.layout.primitive(into).weight().circle.pos,
r: 0.0, r: 0.0,
}; };
@ -64,7 +64,7 @@ impl<'a, 'b> Guide<'a, 'b> {
pub fn head_cw(&self, head: &Head) -> Option<bool> { pub fn head_cw(&self, head: &Head) -> Option<bool> {
match head.bend { match head.bend {
Some(bend) => Some(self.mesh.primitive(bend).weight().cw), Some(bend) => Some(self.layout.primitive(bend).weight().cw),
None => None, None => None,
} }
} }
@ -81,14 +81,14 @@ impl<'a, 'b> Guide<'a, 'b> {
match maybe_bend { match maybe_bend {
Some(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) self.bend_circle(inner, width)
} else { } 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 { None => Circle {
pos: self.mesh.primitive(head.dot).weight().circle.pos, pos: self.layout.primitive(head.dot).weight().circle.pos,
r: 0.0, r: 0.0,
}, },
} }
@ -96,7 +96,7 @@ impl<'a, 'b> Guide<'a, 'b> {
fn bend_circle(&self, bend: BendIndex, width: f64) -> Circle { fn bend_circle(&self, bend: BendIndex, width: f64) -> Circle {
let mut circle = self let mut circle = self
.mesh .layout
.primitive(bend) .primitive(bend)
.shape() .shape()
.as_bend() .as_bend()
@ -107,7 +107,7 @@ impl<'a, 'b> Guide<'a, 'b> {
} }
fn dot_circle(&self, dot: DotIndex, width: f64) -> Circle { 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 { Circle {
pos: circle.pos, pos: circle.pos,
r: circle.r + width + self.rules.ruleset(self.conditions).clearance.min, r: circle.r + width + self.rules.ruleset(self.conditions).clearance.min,

View File

@ -1,318 +1,338 @@
use geo::geometry::Point; use geo::Point;
use std::cell::{Ref, RefCell}; use petgraph::stable_graph::{EdgeIndex, NodeIndex, StableDiGraph};
use std::rc::Rc; 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::bow::Bow;
use crate::graph::{BendWeight, DotWeight, SegWeight, TaggedWeight}; use crate::graph::{
use crate::guide::Guide; BendIndex, BendWeight, DotIndex, DotWeight, Index, Label, Path, SegIndex, SegWeight, Tag,
use crate::math; TaggedIndex, TaggedWeight,
use crate::math::Circle; };
use crate::mesh::Mesh; use crate::primitive::Primitive;
use crate::rules::{Conditions, Rules};
use crate::shape::Shape; use crate::shape::Shape;
pub struct Layout { pub type RTreeWrapper = GeomWithData<Shape, TaggedIndex>;
mesh: Mesh,
rules: Rules,
}
pub struct Head { pub struct Layout {
pub dot: DotIndex, pub rtree: RTree<RTreeWrapper>,
pub bend: Option<BendIndex>, pub graph: StableDiGraph<TaggedWeight, Label, usize>,
} }
impl Layout { impl Layout {
pub fn new() -> Self { pub fn new() -> Self {
Layout { Layout {
mesh: Mesh::new(), rtree: RTree::new(),
rules: Rules::new(), graph: StableDiGraph::default(),
} }
} }
pub fn draw_start(&mut self, from: DotIndex) -> Head { pub fn remove_open_set(&mut self, open_set: Vec<TaggedIndex>) {
Head { for index in open_set.iter().filter(|index| !index.is_dot()) {
dot: from, untag!(index, self.remove(*index));
bend: self.mesh.primitive(from).bend(), }
// 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<(), ()> { pub fn remove<Weight: std::marker::Copy>(&mut self, index: Index<Weight>) {
if let Some(bend) = self.mesh.primitive(into).bend() { // Unnecessary retag. It should be possible to elide it.
self.draw_finish_in_bend(head, bend, into, width) let weight = *self.graph.node_weight(index.index).unwrap();
} else {
self.draw_finish_in_dot(head, into, width)
}
}
fn draw_finish_in_dot(&mut self, head: Head, into: DotIndex, width: f64) -> Result<(), ()> { let wrapper = RTreeWrapper::new(self.primitive(index).shape(), index.retag(&weight));
let tangent = self assert!(self.rtree.remove(&wrapper).is_some());
.guide(&Default::default()) self.graph.remove_node(index.index);
.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<Head, ()> {
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<Head, ()> {
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<Head, ()> {
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<Head, ()> {
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<Head, ()> {
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<TaggedIndex>> = 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<Head, ()> {
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<Head, ()> {
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<Head, ()> {
self.mesh.extend_bend(head.bend.unwrap(), head.dot, to)?;
Ok(head)
} }
pub fn add_dot(&mut self, weight: DotWeight) -> Result<DotIndex, ()> { pub fn add_dot(&mut self, weight: DotWeight) -> Result<DotIndex, ()> {
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<SegIndex, ()> { pub fn add_seg(
let net = self.mesh.primitive(from).weight().net; &mut self,
self.mesh.add_seg(from, to, SegWeight { net, width }) from: DotIndex,
to: DotIndex,
weight: SegWeight,
) -> Result<SegIndex, ()> {
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<Item = Shape> + '_ { pub fn add_bend(
self.mesh &mut self,
.nodes() from: DotIndex,
.map(|ni| untag!(ni, self.mesh.primitive(ni).shape())) to: DotIndex,
around: TaggedIndex,
weight: BendWeight,
) -> Result<BendIndex, ()> {
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<Item = (Point, Point)> + '_ { pub fn add_core_bend(
self.mesh.edges().map(|endpoints| { &mut self,
let index0 = endpoints.0; from: DotIndex,
let index1 = endpoints.1; to: DotIndex,
core: DotIndex,
weight: BendWeight,
) -> Result<BendIndex, ()> {
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<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::<Vec<DotIndex>>()
.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<Item = TaggedIndex> + '_ {
self.rtree.iter().map(|wrapper| wrapper.data)
}
pub fn edges(&self) -> impl Iterator<Item = (TaggedIndex, TaggedIndex)> + '_ {
self.graph.edge_indices().map(|edge| {
let endpoints = self.graph.edge_endpoints(edge).unwrap();
( (
untag!(index0, self.mesh.primitive(index0).shape().center()), Index::<Label>::new(endpoints.0)
untag!(index1, self.mesh.primitive(index1).shape().center()), .retag(self.graph.node_weight(endpoints.0).unwrap()),
Index::<Label>::new(endpoints.1)
.retag(self.graph.node_weight(endpoints.1).unwrap()),
) )
}) })
} }
fn guide<'a>(&'a self, conditions: &'a Conditions) -> Guide { pub fn shapes(&self) -> impl Iterator<Item = Shape> + '_ {
Guide::new(&self.mesh, &self.rules, conditions) self.nodes()
.map(|ni| untag!(ni, self.primitive(ni).shape()))
}
pub fn primitive<Weight>(&self, index: Index<Weight>) -> Primitive<Weight> {
Primitive::new(index, &self.graph)
}
pub fn bow(&self, bend: BendIndex) -> Bow {
Bow::new(bend, &self.graph)
}
fn triangulate(&mut self) {
let peer_edge_indices: Vec<EdgeIndex<usize>> = self
.graph
.edge_indices()
.filter(|index| *self.graph.edge_weight(*index).unwrap() == Label::Peer)
.collect();
for edge_index in peer_edge_indices {
self.graph.remove_edge(edge_index);
}
struct TriangulationVertex {
pub index: NodeIndex<usize>,
x: f64,
y: f64,
}
impl HasPosition for TriangulationVertex {
type Scalar = f64;
fn position(&self) -> Point2<Self::Scalar> {
Point2::new(self.x, self.y)
}
}
let mut triangulation: DelaunayTriangulation<_> = DelaunayTriangulation::new();
for node_index in self
.graph
.node_indices()
.filter(|index| self.graph.node_weight(*index).unwrap().is_dot())
{
let center = self
.primitive(Index::<Label>::new(node_index))
.shape()
.center();
triangulation
.insert(TriangulationVertex {
index: node_index,
x: center.x(),
y: center.y(),
})
.unwrap();
}
for edge in triangulation.directed_edges() {
let from = edge.from().as_ref().index;
let to = edge.to().as_ref().index;
self.graph.add_edge(from, to, Label::Peer);
}
}
fn fail_and_remove_if_collides_except<Weight: std::marker::Copy>(
&mut self,
index: Index<Weight>,
except: &[TaggedIndex],
) -> Result<(), ()> {
if let Some(..) = self.detect_collision_except(index, except) {
self.remove(index);
return Err(());
}
Ok(())
}
fn detect_collision_except<Weight: std::marker::Copy>(
&self,
index: Index<Weight>,
except: &[TaggedIndex],
) -> Option<TaggedIndex> {
let primitive = self.primitive(index);
let shape = primitive.shape();
self.rtree
.locate_in_envelope_intersecting(&shape.envelope())
.filter(|wrapper| {
let index = wrapper.data;
!untag!(index, primitive.connectable(index))
})
.filter(|wrapper| !except.contains(&wrapper.data))
.filter(|wrapper| shape.intersects(wrapper.geom()))
.map(|wrapper| wrapper.data)
.next()
}
fn insert_into_rtree(&mut self, index: TaggedIndex) {
let shape = untag!(index, self.primitive(index).shape());
self.rtree.insert(RTreeWrapper::new(shape, index));
}
fn remove_from_rtree(&mut self, index: TaggedIndex) {
let shape = untag!(index, self.primitive(index).shape());
self.rtree.remove(&RTreeWrapper::new(shape, index));
} }
} }

View File

@ -13,13 +13,13 @@ mod bow;
mod guide; mod guide;
mod layout; mod layout;
mod math; mod math;
mod mesh;
mod primitive; mod primitive;
mod router;
mod rules; mod rules;
mod shape; mod shape;
use geo::EuclideanDistance; use geo::EuclideanDistance;
use graph::{Tag, TaggedIndex}; use graph::{SegWeight, Tag, TaggedIndex};
use sdl2::event::Event; use sdl2::event::Event;
use sdl2::gfx::primitives::DrawRenderer; use sdl2::gfx::primitives::DrawRenderer;
use sdl2::keyboard::Keycode; use sdl2::keyboard::Keycode;
@ -32,8 +32,8 @@ use std::panic;
use std::time::Duration; use std::time::Duration;
use crate::graph::DotWeight; use crate::graph::DotWeight;
use crate::layout::Layout;
use crate::math::Circle; use crate::math::Circle;
use crate::router::Router;
fn main() { fn main() {
let sdl_context = sdl2::init().unwrap(); let sdl_context = sdl2::init().unwrap();
@ -53,58 +53,59 @@ fn main() {
let mut event_pump = sdl_context.event_pump().unwrap(); let mut event_pump = sdl_context.event_pump().unwrap();
let mut i = 0; let mut i = 0;
let mut layout = Layout::new(); let mut router = Router::new();
/*let index = layout.add_dot(DotWeight {net: 0, circle: Circle {pos: (150.5, 80.5).into(), r: 8.0}}); /*let index = router.layout.add_dot(DotWeight {net: 0, circle: Circle {pos: (150.5, 80.5).into(), r: 8.0}});
//layout.draw_seg(index, Point {x: 400.5, y: 350.5}, 6.0); //router.draw_seg(index, Point {x: 400.5, y: 350.5}, 6.0);
let index2 = layout.add_dot(DotWeight {net: 0, circle: Circle {pos: (180.5, 150.5).into(), r: 8.0}}); let index2 = router.layout.add_dot(DotWeight {net: 0, circle: Circle {pos: (180.5, 150.5).into(), r: 8.0}});
let barrier1 = layout.add_dot(DotWeight {net: 0, circle: Circle {pos: (90.5, 150.5).into(), r: 8.0}}); let barrier1 = router.layout.add_dot(DotWeight {net: 0, circle: Circle {pos: (90.5, 150.5).into(), r: 8.0}});
layout.add_seg(index2, barrier1, 16.0); router.layout.add_seg(index2, barrier1, 16.0);
let index3 = layout.add_dot(DotWeight {net: 0, circle: Circle {pos: (130.5, 250.5).into(), r: 8.0}}); let index3 = router.layout.add_dot(DotWeight {net: 0, circle: Circle {pos: (130.5, 250.5).into(), r: 8.0}});
let barrier2 = layout.add_dot(DotWeight {net: 0, circle: Circle {pos: (190.5, 250.5).into(), r: 8.0}}); let barrier2 = router.layout.add_dot(DotWeight {net: 0, circle: Circle {pos: (190.5, 250.5).into(), r: 8.0}});
layout.add_seg(index3, barrier2, 16.0); router.layout.add_seg(index3, barrier2, 16.0);
let index4 = layout.draw_around_dot(index, index2, true, 5.0); let index4 = router.draw_around_dot(index, index2, true, 5.0);
let index5 = layout.draw_around_dot(index4, index3, false, 5.0); let index5 = router.draw_around_dot(index4, index3, false, 5.0);
let index6 = layout.add_dot(DotWeight {net: 0, circle: Circle {pos: (140.5, 300.5).into(), r: 8.0}}); let index6 = router.layout.add_dot(DotWeight {net: 0, circle: Circle {pos: (140.5, 300.5).into(), r: 8.0}});
let index7 = layout.draw_to(index5, index6, 5.0);*/ let index7 = router.draw_to(index5, index6, 5.0);*/
/*let dot1 = layout.add_dot(DotWeight {net: 0, circle: Circle {pos: (100.5, 150.5).into(), r: 8.0}}); /*let dot1 = router.layout.add_dot(DotWeight {net: 0, circle: Circle {pos: (100.5, 150.5).into(), r: 8.0}});
let dot2 = layout.add_dot(DotWeight {net: 0, circle: Circle {pos: (130.5, 150.5).into(), r: 8.0}}); let dot2 = router.layout.add_dot(DotWeight {net: 0, circle: Circle {pos: (130.5, 150.5).into(), r: 8.0}});
let dot3 = layout.add_dot(DotWeight {net: 0, circle: Circle {pos: (160.5, 150.5).into(), r: 8.0}}); let dot3 = router.layout.add_dot(DotWeight {net: 0, circle: Circle {pos: (160.5, 150.5).into(), r: 8.0}});
let obstacle_dot1 = layout.add_dot(DotWeight {net: 0, circle: Circle {pos: (220.5, 250.5).into(), r: 8.0}}); let obstacle_dot1 = router.layout.add_dot(DotWeight {net: 0, circle: Circle {pos: (220.5, 250.5).into(), r: 8.0}});
let obstacle_dot2 = layout.add_dot(DotWeight {net: 0, circle: Circle {pos: (70.5, 250.5).into(), r: 8.0}}); let obstacle_dot2 = router.layout.add_dot(DotWeight {net: 0, circle: Circle {pos: (70.5, 250.5).into(), r: 8.0}});
layout.add_seg(obstacle_dot1, obstacle_dot2, 16.0); router.layout.add_seg(obstacle_dot1, obstacle_dot2, 16.0);
let dot4 = layout.add_dot(DotWeight {net: 0, circle: Circle {pos: (180.5, 380.5).into(), r: 8.0}}); let dot4 = router.layout.add_dot(DotWeight {net: 0, circle: Circle {pos: (180.5, 380.5).into(), r: 8.0}});
let dot5 = layout.add_dot(DotWeight {net: 0, circle: Circle {pos: (220.5, 380.5).into(), r: 8.0}}); let dot5 = router.layout.add_dot(DotWeight {net: 0, circle: Circle {pos: (220.5, 380.5).into(), r: 8.0}});
let dot6 = layout.add_dot(DotWeight {net: 0, circle: Circle {pos: (290.5, 380.5).into(), r: 8.0}}); let dot6 = router.layout.add_dot(DotWeight {net: 0, circle: Circle {pos: (290.5, 380.5).into(), r: 8.0}});
let head = layout.draw_start(dot3); let head = router.draw_start(dot3);
let head = layout.draw_around_dot(head, obstacle_dot1, true, 5.0); let head = router.draw_around_dot(head, obstacle_dot1, true, 5.0);
let dot3_1 = head.dot; let dot3_1 = head.dot;
let bend3_1 = head.bend.unwrap(); let bend3_1 = head.bend.unwrap();
layout.draw_finish(head, dot4, 5.0); router.draw_finish(head, dot4, 5.0);
let head = layout.draw_start(dot2); let head = router.draw_start(dot2);
let head = layout.draw_around_dot(head, dot3, true, 5.0); let head = router.draw_around_dot(head, dot3, true, 5.0);
let dot2_1 = head.dot; let dot2_1 = head.dot;
let bend2_1 = head.bend.unwrap(); let bend2_1 = head.bend.unwrap();
let head = layout.draw_around_bend(head, bend3_1, true, 5.0); let head = router.draw_around_bend(head, bend3_1, true, 5.0);
let dot2_2 = head.dot; let dot2_2 = head.dot;
let bend2_2 = head.bend.unwrap(); let bend2_2 = head.bend.unwrap();
layout.draw_finish(head, dot5, 5.0); router.draw_finish(head, dot5, 5.0);
let head = layout.draw_start(dot1); let head = router.draw_start(dot1);
let head = layout.draw_around_bend(head, bend2_1, true, 5.0); let head = router.draw_around_bend(head, bend2_1, true, 5.0);
let head = layout.draw_around_bend(head, bend2_2, true, 5.0); let head = router.draw_around_bend(head, bend2_2, true, 5.0);
layout.draw_finish(head, dot6, 5.0);*/ router.draw_finish(head, dot6, 5.0);*/
let dot1_1 = layout let dot1_1 = router
.layout
.add_dot(DotWeight { .add_dot(DotWeight {
net: 1, net: 1,
circle: Circle { circle: Circle {
@ -113,7 +114,8 @@ fn main() {
}, },
}) })
.unwrap(); .unwrap();
let dot2_1 = layout let dot2_1 = router
.layout
.add_dot(DotWeight { .add_dot(DotWeight {
net: 2, net: 2,
circle: Circle { circle: Circle {
@ -122,7 +124,8 @@ fn main() {
}, },
}) })
.unwrap(); .unwrap();
let dot3_1 = layout let dot3_1 = router
.layout
.add_dot(DotWeight { .add_dot(DotWeight {
net: 3, net: 3,
circle: Circle { circle: Circle {
@ -131,7 +134,8 @@ fn main() {
}, },
}) })
.unwrap(); .unwrap();
let dot4_1 = layout let dot4_1 = router
.layout
.add_dot(DotWeight { .add_dot(DotWeight {
net: 4, net: 4,
circle: Circle { circle: Circle {
@ -141,7 +145,8 @@ fn main() {
}) })
.unwrap(); .unwrap();
let dot1_2 = layout let dot1_2 = router
.layout
.add_dot(DotWeight { .add_dot(DotWeight {
net: 1, net: 1,
circle: Circle { circle: Circle {
@ -150,7 +155,8 @@ fn main() {
}, },
}) })
.unwrap(); .unwrap();
let dot2_2 = layout let dot2_2 = router
.layout
.add_dot(DotWeight { .add_dot(DotWeight {
net: 2, net: 2,
circle: Circle { circle: Circle {
@ -159,7 +165,8 @@ fn main() {
}, },
}) })
.unwrap(); .unwrap();
let dot3_2 = layout let dot3_2 = router
.layout
.add_dot(DotWeight { .add_dot(DotWeight {
net: 3, net: 3,
circle: Circle { circle: Circle {
@ -168,7 +175,8 @@ fn main() {
}, },
}) })
.unwrap(); .unwrap();
let dot4_2 = layout let dot4_2 = router
.layout
.add_dot(DotWeight { .add_dot(DotWeight {
net: 4, net: 4,
circle: Circle { circle: Circle {
@ -178,7 +186,8 @@ fn main() {
}) })
.unwrap(); .unwrap();
let dot5 = layout let dot5 = router
.layout
.add_dot(DotWeight { .add_dot(DotWeight {
net: 5, net: 5,
circle: Circle { circle: Circle {
@ -188,7 +197,8 @@ fn main() {
}) })
.unwrap(); .unwrap();
let dot6 = layout let dot6 = router
.layout
.add_dot(DotWeight { .add_dot(DotWeight {
net: 6, net: 6,
circle: Circle { circle: Circle {
@ -198,7 +208,8 @@ fn main() {
}) })
.unwrap(); .unwrap();
let dot7 = layout let dot7 = router
.layout
.add_dot(DotWeight { .add_dot(DotWeight {
net: 5, net: 5,
circle: Circle { circle: Circle {
@ -208,7 +219,8 @@ fn main() {
}) })
.unwrap(); .unwrap();
let barrier1_dot1 = layout let barrier1_dot1 = router
.layout
.add_dot(DotWeight { .add_dot(DotWeight {
net: 10, net: 10,
circle: Circle { circle: Circle {
@ -217,8 +229,8 @@ fn main() {
}, },
}) })
.unwrap(); .unwrap();
/*let barrier1_dot2 = layout /*let barrier1_dot2 = router
.add_dot(DotWeight { .layout.add_dot(DotWeight {
net: 10, net: 10,
circle: Circle { circle: Circle {
pos: (250.5, 700.5).into(), pos: (250.5, 700.5).into(),
@ -226,9 +238,10 @@ fn main() {
}, },
}) })
.unwrap(); .unwrap();
let _ = layout.add_seg(barrier1_dot1, barrier1_dot2, 16.0);*/ let _ = router.layout.add_seg(barrier1_dot1, barrier1_dot2, 16.0);*/
let barrier2_dot1 = layout let barrier2_dot1 = router
.layout
.add_dot(DotWeight { .add_dot(DotWeight {
net: 20, net: 20,
circle: Circle { circle: Circle {
@ -237,7 +250,8 @@ fn main() {
}, },
}) })
.unwrap(); .unwrap();
let barrier2_dot2 = layout let barrier2_dot2 = router
.layout
.add_dot(DotWeight { .add_dot(DotWeight {
net: 20, net: 20,
circle: Circle { circle: Circle {
@ -246,91 +260,98 @@ fn main() {
}, },
}) })
.unwrap(); .unwrap();
let _ = layout.add_seg(barrier2_dot1, barrier2_dot2, 16.0); let _ = router.layout.add_seg(
barrier2_dot1,
barrier2_dot2,
SegWeight {
net: 20,
width: 16.0,
},
);
let head = layout.draw_start(dot5); let head = router.draw_start(dot5);
let head = layout.draw_around_dot(head, dot6, false, 5.0).unwrap(); let head = router.draw_around_dot(head, dot6, false, 5.0).unwrap();
let _ = layout.draw_finish(head, dot7, 5.0); let _ = router.draw_finish(head, dot7, 5.0);
/*render_times(&mut event_pump, &mut canvas, &mut layout, None, -1); /*render_times(&mut event_pump, &mut canvas, &mut router, None, -1);
let head = layout.draw_start(dot1_1); let head = router.draw_start(dot1_1);
let head = layout let head = router
.draw_around_dot(head, barrier1_dot1, true, 5.0) .draw_around_dot(head, barrier1_dot1, true, 5.0)
.unwrap(); .unwrap();
render_times(&mut event_pump, &mut canvas, &mut layout, None, 50); render_times(&mut event_pump, &mut canvas, &mut router, None, 50);
let head = layout let head = router
.draw_around_dot(head, barrier2_dot1, true, 5.0) .draw_around_dot(head, barrier2_dot1, true, 5.0)
.unwrap(); .unwrap();
render_times(&mut event_pump, &mut canvas, &mut layout, None, 50); render_times(&mut event_pump, &mut canvas, &mut router, None, 50);
layout.draw_finish(head, dot1_2, 5.0).unwrap(); router.draw_finish(head, dot1_2, 5.0).unwrap();
render_times(&mut event_pump, &mut canvas, &mut layout, None, 50); render_times(&mut event_pump, &mut canvas, &mut router, None, 50);
let head = layout.draw_start(dot2_1); let head = router.draw_start(dot2_1);
let head = layout let head = router
.squeeze_around_dot(head, barrier1_dot1, true, 5.0) .squeeze_around_dot(head, barrier1_dot1, true, 5.0)
.unwrap(); .unwrap();
render_times(&mut event_pump, &mut canvas, &mut layout, None, 50); render_times(&mut event_pump, &mut canvas, &mut router, None, 50);
let head = layout let head = router
.squeeze_around_dot(head, barrier2_dot1, true, 5.0) .squeeze_around_dot(head, barrier2_dot1, true, 5.0)
.unwrap(); .unwrap();
render_times(&mut event_pump, &mut canvas, &mut layout, None, 50); render_times(&mut event_pump, &mut canvas, &mut router, None, 50);
let _ = layout.draw_finish(head, dot2_2, 5.0); let _ = router.draw_finish(head, dot2_2, 5.0);
render_times(&mut event_pump, &mut canvas, &mut layout, None, 50); render_times(&mut event_pump, &mut canvas, &mut router, None, 50);
let head = layout.draw_start(dot3_1); let head = router.draw_start(dot3_1);
render_times(&mut event_pump, &mut canvas, &mut layout, None, 50); render_times(&mut event_pump, &mut canvas, &mut router, None, 50);
let head = layout let head = router
.squeeze_around_dot(head, barrier1_dot1, true, 5.0) .squeeze_around_dot(head, barrier1_dot1, true, 5.0)
.unwrap(); .unwrap();
render_times(&mut event_pump, &mut canvas, &mut layout, None, 50); render_times(&mut event_pump, &mut canvas, &mut router, None, 50);
let head = layout let head = router
.squeeze_around_dot(head, barrier2_dot1, true, 5.0) .squeeze_around_dot(head, barrier2_dot1, true, 5.0)
.unwrap(); .unwrap();
render_times(&mut event_pump, &mut canvas, &mut layout, None, 50); render_times(&mut event_pump, &mut canvas, &mut router, None, 50);
let _ = layout.draw_finish(head, dot3_2, 5.0); let _ = router.draw_finish(head, dot3_2, 5.0);
render_times(&mut event_pump, &mut canvas, &mut layout, None, 50); render_times(&mut event_pump, &mut canvas, &mut router, None, 50);
let head = layout.draw_start(dot4_1); let head = router.draw_start(dot4_1);
render_times(&mut event_pump, &mut canvas, &mut layout, None, 50); render_times(&mut event_pump, &mut canvas, &mut router, None, 50);
let head = layout let head = router
.squeeze_around_dot(head, barrier1_dot1, true, 5.0) .squeeze_around_dot(head, barrier1_dot1, true, 5.0)
.unwrap(); .unwrap();
render_times(&mut event_pump, &mut canvas, &mut layout, None, 50); render_times(&mut event_pump, &mut canvas, &mut router, None, 50);
let head = layout let head = router
.squeeze_around_dot(head, barrier2_dot1, true, 5.0) .squeeze_around_dot(head, barrier2_dot1, true, 5.0)
.unwrap(); .unwrap();
render_times(&mut event_pump, &mut canvas, &mut layout, None, 50); render_times(&mut event_pump, &mut canvas, &mut router, None, 50);
let _ = layout.draw_finish(head, dot4_2, 5.0);*/ let _ = router.draw_finish(head, dot4_2, 5.0);*/
render_times(&mut event_pump, &mut canvas, &mut layout, None, -1); render_times(&mut event_pump, &mut canvas, &mut router, None, -1);
render_times( render_times(
&mut event_pump, &mut event_pump,
&mut canvas, &mut canvas,
&mut layout, &mut router,
Some(barrier1_dot1.tag()), Some(barrier1_dot1.tag()),
-1, -1,
); );
render_times(&mut event_pump, &mut canvas, &mut layout, None, -1); render_times(&mut event_pump, &mut canvas, &mut router, None, -1);
} }
fn render_times( fn render_times(
event_pump: &mut EventPump, event_pump: &mut EventPump,
canvas: &mut Canvas<Window>, canvas: &mut Canvas<Window>,
layout: &mut Layout, router: &mut Router,
follower: Option<TaggedIndex>, follower: Option<TaggedIndex>,
times: i64, times: i64,
) { ) {
@ -354,14 +375,14 @@ fn render_times(
if let Some(follower) = follower { if let Some(follower) = follower {
let state = event_pump.mouse_state(); let state = event_pump.mouse_state();
let _ = layout.move_dot( let _ = router.move_dot(
*follower.as_dot().unwrap(), *follower.as_dot().unwrap(),
(state.x() as f64, state.y() as f64).into(), (state.x() as f64, state.y() as f64).into(),
); );
} }
let result = panic::catch_unwind(|| { let result = panic::catch_unwind(|| {
for shape in layout.shapes() { for shape in router.layout.shapes() {
match shape { match shape {
Shape::Dot(dot) => { Shape::Dot(dot) => {
let _ = canvas.filled_circle( let _ = canvas.filled_circle(
@ -385,8 +406,8 @@ fn render_times(
let delta1 = bend.from - bend.c.pos; let delta1 = bend.from - bend.c.pos;
let delta2 = bend.to - bend.c.pos; let delta2 = bend.to - bend.c.pos;
let mut angle1 = delta1.y().atan2(delta1.x()); let angle1 = delta1.y().atan2(delta1.x());
let mut angle2 = delta2.y().atan2(delta2.x()); let angle2 = delta2.y().atan2(delta2.x());
for d in -2..3 { for d in -2..3 {
let _ = canvas.arc( let _ = canvas.arc(
@ -413,7 +434,7 @@ fn render_times(
); );
} }
for edge in layout.edges() { for edge in router.routeedges() {
let _ = canvas.line( let _ = canvas.line(
edge.0.x() as i16, edge.0.x() as i16,
edge.0.y() as i16, edge.0.y() as i16,

View File

@ -1,333 +0,0 @@
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::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 type RTreeWrapper = GeomWithData<Shape, TaggedIndex>;
pub struct Mesh {
pub rtree: RTree<RTreeWrapper>,
pub graph: StableDiGraph<TaggedWeight, Label, usize>,
}
impl Mesh {
pub fn new() -> Self {
Mesh {
rtree: RTree::new(),
graph: StableDiGraph::default(),
}
}
pub fn remove_open_set(&mut self, open_set: Vec<TaggedIndex>) {
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 remove<Weight: std::marker::Copy>(&mut self, index: Index<Weight>) {
// Unnecessary retag. It should be possible to elide it.
let weight = *self.graph.node_weight(index.index).unwrap();
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<DotIndex, ()> {
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,
weight: SegWeight,
) -> Result<SegIndex, ()> {
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 add_bend(
&mut self,
from: DotIndex,
to: DotIndex,
around: TaggedIndex,
weight: BendWeight,
) -> Result<BendIndex, ()> {
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 add_core_bend(
&mut self,
from: DotIndex,
to: DotIndex,
core: DotIndex,
weight: BendWeight,
) -> Result<BendIndex, ()> {
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<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::<Vec<DotIndex>>()
.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<Item = TaggedIndex> + '_ {
self.rtree.iter().map(|wrapper| wrapper.data)
}
pub fn edges(&self) -> impl Iterator<Item = (TaggedIndex, TaggedIndex)> + '_ {
self.graph.edge_indices().map(|edge| {
let endpoints = self.graph.edge_endpoints(edge).unwrap();
(
Index::<Label>::new(endpoints.0)
.retag(self.graph.node_weight(endpoints.0).unwrap()),
Index::<Label>::new(endpoints.1)
.retag(self.graph.node_weight(endpoints.1).unwrap()),
)
})
}
pub fn primitive<Weight>(&self, index: Index<Weight>) -> Primitive<Weight> {
Primitive::new(index, &self.graph)
}
pub fn bow(&self, bend: BendIndex) -> Bow {
Bow::new(bend, &self.graph)
}
fn triangulate(&mut self) {
let peer_edge_indices: Vec<EdgeIndex<usize>> = self
.graph
.edge_indices()
.filter(|index| *self.graph.edge_weight(*index).unwrap() == Label::Peer)
.collect();
for edge_index in peer_edge_indices {
self.graph.remove_edge(edge_index);
}
struct TriangulationVertex {
pub index: NodeIndex<usize>,
x: f64,
y: f64,
}
impl HasPosition for TriangulationVertex {
type Scalar = f64;
fn position(&self) -> Point2<Self::Scalar> {
Point2::new(self.x, self.y)
}
}
let mut triangulation: DelaunayTriangulation<_> = DelaunayTriangulation::new();
for node_index in self
.graph
.node_indices()
.filter(|index| self.graph.node_weight(*index).unwrap().is_dot())
{
let center = self
.primitive(Index::<Label>::new(node_index))
.shape()
.center();
triangulation
.insert(TriangulationVertex {
index: node_index,
x: center.x(),
y: center.y(),
})
.unwrap();
}
for edge in triangulation.directed_edges() {
let from = edge.from().as_ref().index;
let to = edge.to().as_ref().index;
self.graph.add_edge(from, to, Label::Peer);
}
}
fn fail_and_remove_if_collides_except<Weight: std::marker::Copy>(
&mut self,
index: Index<Weight>,
except: &[TaggedIndex],
) -> Result<(), ()> {
if let Some(..) = self.detect_collision_except(index, except) {
self.remove(index);
return Err(());
}
Ok(())
}
fn detect_collision_except<Weight: std::marker::Copy>(
&self,
index: Index<Weight>,
except: &[TaggedIndex],
) -> Option<TaggedIndex> {
let primitive = self.primitive(index);
let shape = primitive.shape();
self.rtree
.locate_in_envelope_intersecting(&shape.envelope())
.filter(|wrapper| {
let index = wrapper.data;
!untag!(index, primitive.connectable(index))
})
.filter(|wrapper| !except.contains(&wrapper.data))
.filter(|wrapper| shape.intersects(wrapper.geom()))
.map(|wrapper| wrapper.data)
.next()
}
fn insert_into_rtree(&mut self, index: TaggedIndex) {
let shape = untag!(index, self.primitive(index).shape());
self.rtree.insert(RTreeWrapper::new(shape, index));
}
fn remove_from_rtree(&mut self, index: TaggedIndex) {
let shape = untag!(index, self.primitive(index).shape());
self.rtree.remove(&RTreeWrapper::new(shape, index));
}
}

312
src/router.rs Normal file
View File

@ -0,0 +1,312 @@
use geo::geometry::Point;
use std::cell::{Ref, RefCell};
use std::rc::Rc;
use crate::graph::{BendIndex, DotIndex, Path, SegIndex, TaggedIndex};
use crate::graph::{BendWeight, DotWeight, SegWeight, TaggedWeight};
use crate::guide::Guide;
use crate::layout::Layout;
use crate::math;
use crate::math::Circle;
use crate::rules::{Conditions, Rules};
use crate::shape::Shape;
pub struct Router {
pub layout: Layout,
rules: Rules,
}
pub struct Head {
pub dot: DotIndex,
pub bend: Option<BendIndex>,
}
impl Router {
pub fn new() -> Self {
Router {
layout: Layout::new(),
rules: Rules::new(),
}
}
pub fn draw_start(&mut self, from: DotIndex) -> Head {
Head {
dot: from,
bend: self.layout.primitive(from).bend(),
}
}
pub fn draw_finish(&mut self, head: Head, into: DotIndex, width: f64) -> Result<(), ()> {
if let Some(bend) = self.layout.primitive(into).bend() {
self.draw_finish_in_bend(head, bend, into, width)
} else {
self.draw_finish_in_dot(head, into, width)
}
}
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())?;
let net = self.layout.primitive(head.dot).weight().net;
self.layout
.add_seg(head.dot, into, SegWeight { net, width })?;
Ok(())
}
fn draw_finish_in_bend(
&mut self,
head: Head,
into_bend: BendIndex,
into: DotIndex,
width: f64,
) -> Result<(), ()> {
let to_head = Head {
bend: Some(into_bend),
dot: into,
};
let to_cw = self.guide(&Default::default()).head_cw(&to_head).unwrap();
let tangent = self
.guide(&Default::default())
.head_around_bend_segment(&head, into_bend, to_cw, width);
let head = self.extend_head(head, tangent.start_point())?;
let to_head = self.extend_head(to_head, tangent.end_point())?;
let net = self.layout.primitive(head.dot).weight().net;
self.layout
.add_seg(head.dot, into, SegWeight { net, width })?;
Ok(())
}
pub fn squeeze_around_dot(
&mut self,
head: Head,
around: DotIndex,
cw: bool,
width: f64,
) -> Result<Head, ()> {
let outer = self.layout.primitive(around).outer().unwrap();
let head = self.draw_around_dot(head, around, cw, width)?;
self.layout.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<Head, ()> {
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<Head, ()> {
let outer = self.layout.primitive(around).outer().unwrap();
let head = self.draw_around_bend(head, around, cw, width)?;
self.layout.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<Head, ()> {
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<Head, ()> {
let head = self.draw_seg(head, to, width)?;
let bend_to = self
.layout
.add_dot(self.layout.primitive(head.dot).weight())?;
let net = self.layout.primitive(head.dot).weight().net;
let bend = self
.layout
.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<TaggedIndex>> = vec![];
let cw = self.layout.primitive(bend).weight().cw;
let mut cur_bend = bend;
loop {
let bow = self.layout.bow(cur_bend);
endss.push(bow.ends());
interiors.push(bow.interior());
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 interior in interiors {
self.layout.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<Head, ()> {
let net = self.layout.primitive(head.dot).weight().net;
assert!(width <= self.layout.primitive(head.dot).weight().circle.r * 2.);
let to_index = self.layout.add_dot(DotWeight {
net,
circle: Circle {
pos: to,
r: width / 2.0,
},
})?;
self.layout
.add_seg(head.dot, to_index, SegWeight { net, 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.layout.primitive(prev_bend).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).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: BendIndex) {
let bow = self.layout.bow(bend);
let ends = bow.ends();
self.layout.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.layout.move_dot(dot, to)?;
if let Some(outer) = self.layout.primitive(dot).outer() {
self.reroute_outward(outer)?;
}
Ok(())
}
fn extend_head(&mut self, head: Head, to: Point) -> Result<Head, ()> {
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.layout.weight(TaggedIndex::Dot(from)).as_dot().unwrap().circle.pos, to);
//assert!(self.layout.weight(TaggedIndex::Dot(from)).as_dot().unwrap().circle.pos == to);
}
}
fn extend_head_bend(&mut self, head: Head, to: Point) -> Result<Head, ()> {
self.layout.extend_bend(head.bend.unwrap(), head.dot, to)?;
Ok(head)
}
fn guide<'a>(&'a self, conditions: &'a Conditions) -> Guide {
Guide::new(&self.layout, &self.rules, conditions)
}
pub fn routeedges(&self) -> impl Iterator<Item = (Point, Point)> + '_ {
self.layout.edges().map(|endpoints| {
let index0 = endpoints.0;
let index1 = endpoints.1;
(
untag!(index0, self.layout.primitive(index0).shape().center()),
untag!(index1, self.layout.primitive(index1).shape().center()),
)
})
}
}