mirror of https://codeberg.org/topola/topola.git
Rename `Layout` to `Router`, `Mesh` to `Layout`
This commit is contained in:
parent
234a52f9e8
commit
8456259b38
24
src/guide.rs
24
src/guide.rs
|
|
@ -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,
|
||||||
|
|
|
||||||
592
src/layout.rs
592
src/layout.rs
|
|
@ -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));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
213
src/main.rs
213
src/main.rs
|
|
@ -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,
|
||||||
|
|
|
||||||
333
src/mesh.rs
333
src/mesh.rs
|
|
@ -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));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -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()),
|
||||||
|
)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue