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::{
|
||||
graph::{BendIndex, DotIndex},
|
||||
layout::Head,
|
||||
layout::Layout,
|
||||
math::{self, Circle},
|
||||
mesh::Mesh,
|
||||
router::Head,
|
||||
rules::{Conditions, Rules},
|
||||
};
|
||||
|
||||
pub struct Guide<'a, 'b> {
|
||||
mesh: &'a Mesh,
|
||||
layout: &'a Layout,
|
||||
rules: &'a Rules,
|
||||
conditions: &'b Conditions,
|
||||
}
|
||||
|
||||
impl<'a, 'b> Guide<'a, 'b> {
|
||||
pub fn new(mesh: &'a Mesh, rules: &'a Rules, conditions: &'b Conditions) -> Self {
|
||||
pub fn new(layout: &'a Layout, rules: &'a Rules, conditions: &'b Conditions) -> Self {
|
||||
Self {
|
||||
mesh,
|
||||
layout,
|
||||
rules,
|
||||
conditions,
|
||||
}
|
||||
|
|
@ -26,7 +26,7 @@ impl<'a, 'b> Guide<'a, 'b> {
|
|||
pub fn head_into_dot_segment(&self, head: &Head, into: DotIndex, width: f64) -> Line {
|
||||
let from_circle = self.head_circle(&head, width);
|
||||
let to_circle = Circle {
|
||||
pos: self.mesh.primitive(into).weight().circle.pos,
|
||||
pos: self.layout.primitive(into).weight().circle.pos,
|
||||
r: 0.0,
|
||||
};
|
||||
|
||||
|
|
@ -64,7 +64,7 @@ impl<'a, 'b> Guide<'a, 'b> {
|
|||
|
||||
pub fn head_cw(&self, head: &Head) -> Option<bool> {
|
||||
match head.bend {
|
||||
Some(bend) => Some(self.mesh.primitive(bend).weight().cw),
|
||||
Some(bend) => Some(self.layout.primitive(bend).weight().cw),
|
||||
None => None,
|
||||
}
|
||||
}
|
||||
|
|
@ -81,14 +81,14 @@ impl<'a, 'b> Guide<'a, 'b> {
|
|||
|
||||
match maybe_bend {
|
||||
Some(bend) => {
|
||||
if let Some(inner) = self.mesh.primitive(bend).inner() {
|
||||
if let Some(inner) = self.layout.primitive(bend).inner() {
|
||||
self.bend_circle(inner, width)
|
||||
} else {
|
||||
self.dot_circle(self.mesh.primitive(bend).core().unwrap(), width + 5.0)
|
||||
self.dot_circle(self.layout.primitive(bend).core().unwrap(), width + 5.0)
|
||||
}
|
||||
}
|
||||
None => Circle {
|
||||
pos: self.mesh.primitive(head.dot).weight().circle.pos,
|
||||
pos: self.layout.primitive(head.dot).weight().circle.pos,
|
||||
r: 0.0,
|
||||
},
|
||||
}
|
||||
|
|
@ -96,7 +96,7 @@ impl<'a, 'b> Guide<'a, 'b> {
|
|||
|
||||
fn bend_circle(&self, bend: BendIndex, width: f64) -> Circle {
|
||||
let mut circle = self
|
||||
.mesh
|
||||
.layout
|
||||
.primitive(bend)
|
||||
.shape()
|
||||
.as_bend()
|
||||
|
|
@ -107,7 +107,7 @@ impl<'a, 'b> Guide<'a, 'b> {
|
|||
}
|
||||
|
||||
fn dot_circle(&self, dot: DotIndex, width: f64) -> Circle {
|
||||
let circle = self.mesh.primitive(dot).weight().circle;
|
||||
let circle = self.layout.primitive(dot).weight().circle;
|
||||
Circle {
|
||||
pos: circle.pos,
|
||||
r: circle.r + width + self.rules.ruleset(self.conditions).clearance.min,
|
||||
|
|
|
|||
592
src/layout.rs
592
src/layout.rs
|
|
@ -1,318 +1,338 @@
|
|||
use geo::geometry::Point;
|
||||
use std::cell::{Ref, RefCell};
|
||||
use std::rc::Rc;
|
||||
use geo::Point;
|
||||
use petgraph::stable_graph::{EdgeIndex, NodeIndex, StableDiGraph};
|
||||
use petgraph::visit::EdgeRef;
|
||||
use petgraph::Direction::Incoming;
|
||||
use rstar::primitives::GeomWithData;
|
||||
use rstar::RTree;
|
||||
use spade::{DelaunayTriangulation, HasPosition, Point2, Triangulation};
|
||||
|
||||
use crate::graph::{BendIndex, DotIndex, Path, SegIndex, TaggedIndex};
|
||||
use crate::graph::{BendWeight, DotWeight, SegWeight, TaggedWeight};
|
||||
use crate::guide::Guide;
|
||||
use crate::math;
|
||||
use crate::math::Circle;
|
||||
use crate::mesh::Mesh;
|
||||
use crate::rules::{Conditions, Rules};
|
||||
use crate::bow::Bow;
|
||||
use crate::graph::{
|
||||
BendIndex, BendWeight, DotIndex, DotWeight, Index, Label, Path, SegIndex, SegWeight, Tag,
|
||||
TaggedIndex, TaggedWeight,
|
||||
};
|
||||
use crate::primitive::Primitive;
|
||||
use crate::shape::Shape;
|
||||
|
||||
pub struct Layout {
|
||||
mesh: Mesh,
|
||||
rules: Rules,
|
||||
}
|
||||
pub type RTreeWrapper = GeomWithData<Shape, TaggedIndex>;
|
||||
|
||||
pub struct Head {
|
||||
pub dot: DotIndex,
|
||||
pub bend: Option<BendIndex>,
|
||||
pub struct Layout {
|
||||
pub rtree: RTree<RTreeWrapper>,
|
||||
pub graph: StableDiGraph<TaggedWeight, Label, usize>,
|
||||
}
|
||||
|
||||
impl Layout {
|
||||
pub fn new() -> Self {
|
||||
Layout {
|
||||
mesh: Mesh::new(),
|
||||
rules: Rules::new(),
|
||||
rtree: RTree::new(),
|
||||
graph: StableDiGraph::default(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn draw_start(&mut self, from: DotIndex) -> Head {
|
||||
Head {
|
||||
dot: from,
|
||||
bend: self.mesh.primitive(from).bend(),
|
||||
pub fn remove_open_set(&mut self, open_set: Vec<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 draw_finish(&mut self, head: Head, into: DotIndex, width: f64) -> Result<(), ()> {
|
||||
if let Some(bend) = self.mesh.primitive(into).bend() {
|
||||
self.draw_finish_in_bend(head, bend, into, width)
|
||||
} else {
|
||||
self.draw_finish_in_dot(head, into, width)
|
||||
}
|
||||
}
|
||||
pub fn remove<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();
|
||||
|
||||
fn draw_finish_in_dot(&mut self, head: Head, into: DotIndex, width: f64) -> Result<(), ()> {
|
||||
let tangent = self
|
||||
.guide(&Default::default())
|
||||
.head_into_dot_segment(&head, into, width);
|
||||
let head = self.extend_head(head, tangent.start_point())?;
|
||||
self.add_seg(head.dot, into, width)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn draw_finish_in_bend(
|
||||
&mut self,
|
||||
head: Head,
|
||||
to_bend: BendIndex,
|
||||
to: DotIndex,
|
||||
width: f64,
|
||||
) -> Result<(), ()> {
|
||||
let to_head = Head {
|
||||
bend: Some(to_bend),
|
||||
dot: to,
|
||||
};
|
||||
let to_cw = self.guide(&Default::default()).head_cw(&to_head).unwrap();
|
||||
let tangent = self
|
||||
.guide(&Default::default())
|
||||
.head_around_bend_segment(&head, to_bend, to_cw, width);
|
||||
let head = self.extend_head(head, tangent.start_point())?;
|
||||
|
||||
let to_head = self.extend_head(to_head, tangent.end_point())?;
|
||||
self.add_seg(head.dot, to, width)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn squeeze_around_dot(
|
||||
&mut self,
|
||||
head: Head,
|
||||
around: DotIndex,
|
||||
cw: bool,
|
||||
width: f64,
|
||||
) -> Result<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)
|
||||
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, ()> {
|
||||
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, ()> {
|
||||
let net = self.mesh.primitive(from).weight().net;
|
||||
self.mesh.add_seg(from, to, SegWeight { net, width })
|
||||
pub fn add_seg(
|
||||
&mut self,
|
||||
from: DotIndex,
|
||||
to: DotIndex,
|
||||
weight: SegWeight,
|
||||
) -> Result<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> + '_ {
|
||||
self.mesh
|
||||
.nodes()
|
||||
.map(|ni| untag!(ni, self.mesh.primitive(ni).shape()))
|
||||
pub fn add_bend(
|
||||
&mut self,
|
||||
from: DotIndex,
|
||||
to: DotIndex,
|
||||
around: TaggedIndex,
|
||||
weight: BendWeight,
|
||||
) -> Result<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)> + '_ {
|
||||
self.mesh.edges().map(|endpoints| {
|
||||
let index0 = endpoints.0;
|
||||
let index1 = endpoints.1;
|
||||
pub fn add_core_bend(
|
||||
&mut self,
|
||||
from: DotIndex,
|
||||
to: DotIndex,
|
||||
core: DotIndex,
|
||||
weight: BendWeight,
|
||||
) -> Result<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()),
|
||||
untag!(index1, self.mesh.primitive(index1).shape().center()),
|
||||
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()),
|
||||
)
|
||||
})
|
||||
}
|
||||
|
||||
fn guide<'a>(&'a self, conditions: &'a Conditions) -> Guide {
|
||||
Guide::new(&self.mesh, &self.rules, conditions)
|
||||
pub fn shapes(&self) -> impl Iterator<Item = Shape> + '_ {
|
||||
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 layout;
|
||||
mod math;
|
||||
mod mesh;
|
||||
mod primitive;
|
||||
mod router;
|
||||
mod rules;
|
||||
mod shape;
|
||||
|
||||
use geo::EuclideanDistance;
|
||||
use graph::{Tag, TaggedIndex};
|
||||
use graph::{SegWeight, Tag, TaggedIndex};
|
||||
use sdl2::event::Event;
|
||||
use sdl2::gfx::primitives::DrawRenderer;
|
||||
use sdl2::keyboard::Keycode;
|
||||
|
|
@ -32,8 +32,8 @@ use std::panic;
|
|||
use std::time::Duration;
|
||||
|
||||
use crate::graph::DotWeight;
|
||||
use crate::layout::Layout;
|
||||
use crate::math::Circle;
|
||||
use crate::router::Router;
|
||||
|
||||
fn main() {
|
||||
let sdl_context = sdl2::init().unwrap();
|
||||
|
|
@ -53,58 +53,59 @@ fn main() {
|
|||
|
||||
let mut event_pump = sdl_context.event_pump().unwrap();
|
||||
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}});
|
||||
//layout.draw_seg(index, Point {x: 400.5, y: 350.5}, 6.0);
|
||||
/*let index = router.layout.add_dot(DotWeight {net: 0, circle: Circle {pos: (150.5, 80.5).into(), r: 8.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 barrier1 = layout.add_dot(DotWeight {net: 0, circle: Circle {pos: (90.5, 150.5).into(), r: 8.0}});
|
||||
layout.add_seg(index2, barrier1, 16.0);
|
||||
let index2 = router.layout.add_dot(DotWeight {net: 0, circle: Circle {pos: (180.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}});
|
||||
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 barrier2 = layout.add_dot(DotWeight {net: 0, circle: Circle {pos: (190.5, 250.5).into(), r: 8.0}});
|
||||
layout.add_seg(index3, barrier2, 16.0);
|
||||
let index3 = router.layout.add_dot(DotWeight {net: 0, circle: Circle {pos: (130.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}});
|
||||
router.layout.add_seg(index3, barrier2, 16.0);
|
||||
|
||||
let index4 = layout.draw_around_dot(index, index2, true, 5.0);
|
||||
let index5 = layout.draw_around_dot(index4, index3, false, 5.0);
|
||||
let index4 = router.draw_around_dot(index, index2, true, 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 index7 = layout.draw_to(index5, index6, 5.0);*/
|
||||
let index6 = router.layout.add_dot(DotWeight {net: 0, circle: Circle {pos: (140.5, 300.5).into(), r: 8.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 dot2 = 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 dot1 = router.layout.add_dot(DotWeight {net: 0, circle: Circle {pos: (100.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 = 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_dot2 = 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);
|
||||
let obstacle_dot1 = router.layout.add_dot(DotWeight {net: 0, circle: Circle {pos: (220.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}});
|
||||
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 dot5 = 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 dot4 = router.layout.add_dot(DotWeight {net: 0, circle: Circle {pos: (180.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 = 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 = layout.draw_around_dot(head, obstacle_dot1, true, 5.0);
|
||||
let head = router.draw_start(dot3);
|
||||
let head = router.draw_around_dot(head, obstacle_dot1, true, 5.0);
|
||||
let dot3_1 = head.dot;
|
||||
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 = layout.draw_around_dot(head, dot3, true, 5.0);
|
||||
let head = router.draw_start(dot2);
|
||||
let head = router.draw_around_dot(head, dot3, true, 5.0);
|
||||
let dot2_1 = head.dot;
|
||||
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 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 = layout.draw_around_bend(head, bend2_1, true, 5.0);
|
||||
let head = layout.draw_around_bend(head, bend2_2, true, 5.0);
|
||||
layout.draw_finish(head, dot6, 5.0);*/
|
||||
let head = router.draw_start(dot1);
|
||||
let head = router.draw_around_bend(head, bend2_1, true, 5.0);
|
||||
let head = router.draw_around_bend(head, bend2_2, true, 5.0);
|
||||
router.draw_finish(head, dot6, 5.0);*/
|
||||
|
||||
let dot1_1 = layout
|
||||
let dot1_1 = router
|
||||
.layout
|
||||
.add_dot(DotWeight {
|
||||
net: 1,
|
||||
circle: Circle {
|
||||
|
|
@ -113,7 +114,8 @@ fn main() {
|
|||
},
|
||||
})
|
||||
.unwrap();
|
||||
let dot2_1 = layout
|
||||
let dot2_1 = router
|
||||
.layout
|
||||
.add_dot(DotWeight {
|
||||
net: 2,
|
||||
circle: Circle {
|
||||
|
|
@ -122,7 +124,8 @@ fn main() {
|
|||
},
|
||||
})
|
||||
.unwrap();
|
||||
let dot3_1 = layout
|
||||
let dot3_1 = router
|
||||
.layout
|
||||
.add_dot(DotWeight {
|
||||
net: 3,
|
||||
circle: Circle {
|
||||
|
|
@ -131,7 +134,8 @@ fn main() {
|
|||
},
|
||||
})
|
||||
.unwrap();
|
||||
let dot4_1 = layout
|
||||
let dot4_1 = router
|
||||
.layout
|
||||
.add_dot(DotWeight {
|
||||
net: 4,
|
||||
circle: Circle {
|
||||
|
|
@ -141,7 +145,8 @@ fn main() {
|
|||
})
|
||||
.unwrap();
|
||||
|
||||
let dot1_2 = layout
|
||||
let dot1_2 = router
|
||||
.layout
|
||||
.add_dot(DotWeight {
|
||||
net: 1,
|
||||
circle: Circle {
|
||||
|
|
@ -150,7 +155,8 @@ fn main() {
|
|||
},
|
||||
})
|
||||
.unwrap();
|
||||
let dot2_2 = layout
|
||||
let dot2_2 = router
|
||||
.layout
|
||||
.add_dot(DotWeight {
|
||||
net: 2,
|
||||
circle: Circle {
|
||||
|
|
@ -159,7 +165,8 @@ fn main() {
|
|||
},
|
||||
})
|
||||
.unwrap();
|
||||
let dot3_2 = layout
|
||||
let dot3_2 = router
|
||||
.layout
|
||||
.add_dot(DotWeight {
|
||||
net: 3,
|
||||
circle: Circle {
|
||||
|
|
@ -168,7 +175,8 @@ fn main() {
|
|||
},
|
||||
})
|
||||
.unwrap();
|
||||
let dot4_2 = layout
|
||||
let dot4_2 = router
|
||||
.layout
|
||||
.add_dot(DotWeight {
|
||||
net: 4,
|
||||
circle: Circle {
|
||||
|
|
@ -178,7 +186,8 @@ fn main() {
|
|||
})
|
||||
.unwrap();
|
||||
|
||||
let dot5 = layout
|
||||
let dot5 = router
|
||||
.layout
|
||||
.add_dot(DotWeight {
|
||||
net: 5,
|
||||
circle: Circle {
|
||||
|
|
@ -188,7 +197,8 @@ fn main() {
|
|||
})
|
||||
.unwrap();
|
||||
|
||||
let dot6 = layout
|
||||
let dot6 = router
|
||||
.layout
|
||||
.add_dot(DotWeight {
|
||||
net: 6,
|
||||
circle: Circle {
|
||||
|
|
@ -198,7 +208,8 @@ fn main() {
|
|||
})
|
||||
.unwrap();
|
||||
|
||||
let dot7 = layout
|
||||
let dot7 = router
|
||||
.layout
|
||||
.add_dot(DotWeight {
|
||||
net: 5,
|
||||
circle: Circle {
|
||||
|
|
@ -208,7 +219,8 @@ fn main() {
|
|||
})
|
||||
.unwrap();
|
||||
|
||||
let barrier1_dot1 = layout
|
||||
let barrier1_dot1 = router
|
||||
.layout
|
||||
.add_dot(DotWeight {
|
||||
net: 10,
|
||||
circle: Circle {
|
||||
|
|
@ -217,8 +229,8 @@ fn main() {
|
|||
},
|
||||
})
|
||||
.unwrap();
|
||||
/*let barrier1_dot2 = layout
|
||||
.add_dot(DotWeight {
|
||||
/*let barrier1_dot2 = router
|
||||
.layout.add_dot(DotWeight {
|
||||
net: 10,
|
||||
circle: Circle {
|
||||
pos: (250.5, 700.5).into(),
|
||||
|
|
@ -226,9 +238,10 @@ fn main() {
|
|||
},
|
||||
})
|
||||
.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 {
|
||||
net: 20,
|
||||
circle: Circle {
|
||||
|
|
@ -237,7 +250,8 @@ fn main() {
|
|||
},
|
||||
})
|
||||
.unwrap();
|
||||
let barrier2_dot2 = layout
|
||||
let barrier2_dot2 = router
|
||||
.layout
|
||||
.add_dot(DotWeight {
|
||||
net: 20,
|
||||
circle: Circle {
|
||||
|
|
@ -246,91 +260,98 @@ fn main() {
|
|||
},
|
||||
})
|
||||
.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 = layout.draw_around_dot(head, dot6, false, 5.0).unwrap();
|
||||
let _ = layout.draw_finish(head, dot7, 5.0);
|
||||
let head = router.draw_start(dot5);
|
||||
let head = router.draw_around_dot(head, dot6, false, 5.0).unwrap();
|
||||
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 = layout
|
||||
let head = router.draw_start(dot1_1);
|
||||
let head = router
|
||||
.draw_around_dot(head, barrier1_dot1, true, 5.0)
|
||||
.unwrap();
|
||||
|
||||
render_times(&mut event_pump, &mut canvas, &mut layout, None, 50);
|
||||
let head = layout
|
||||
render_times(&mut event_pump, &mut canvas, &mut router, None, 50);
|
||||
let head = router
|
||||
.draw_around_dot(head, barrier2_dot1, true, 5.0)
|
||||
.unwrap();
|
||||
|
||||
render_times(&mut event_pump, &mut canvas, &mut layout, None, 50);
|
||||
layout.draw_finish(head, dot1_2, 5.0).unwrap();
|
||||
render_times(&mut event_pump, &mut canvas, &mut router, None, 50);
|
||||
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 = layout
|
||||
let head = router.draw_start(dot2_1);
|
||||
let head = router
|
||||
.squeeze_around_dot(head, barrier1_dot1, true, 5.0)
|
||||
.unwrap();
|
||||
|
||||
render_times(&mut event_pump, &mut canvas, &mut layout, None, 50);
|
||||
let head = layout
|
||||
render_times(&mut event_pump, &mut canvas, &mut router, None, 50);
|
||||
let head = router
|
||||
.squeeze_around_dot(head, barrier2_dot1, true, 5.0)
|
||||
.unwrap();
|
||||
|
||||
render_times(&mut event_pump, &mut canvas, &mut layout, None, 50);
|
||||
let _ = layout.draw_finish(head, dot2_2, 5.0);
|
||||
render_times(&mut event_pump, &mut canvas, &mut router, None, 50);
|
||||
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);
|
||||
let head = layout
|
||||
render_times(&mut event_pump, &mut canvas, &mut router, None, 50);
|
||||
let head = router
|
||||
.squeeze_around_dot(head, barrier1_dot1, true, 5.0)
|
||||
.unwrap();
|
||||
|
||||
render_times(&mut event_pump, &mut canvas, &mut layout, None, 50);
|
||||
let head = layout
|
||||
render_times(&mut event_pump, &mut canvas, &mut router, None, 50);
|
||||
let head = router
|
||||
.squeeze_around_dot(head, barrier2_dot1, true, 5.0)
|
||||
.unwrap();
|
||||
|
||||
render_times(&mut event_pump, &mut canvas, &mut layout, None, 50);
|
||||
let _ = layout.draw_finish(head, dot3_2, 5.0);
|
||||
render_times(&mut event_pump, &mut canvas, &mut router, None, 50);
|
||||
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);
|
||||
let head = layout
|
||||
render_times(&mut event_pump, &mut canvas, &mut router, None, 50);
|
||||
let head = router
|
||||
.squeeze_around_dot(head, barrier1_dot1, true, 5.0)
|
||||
.unwrap();
|
||||
|
||||
render_times(&mut event_pump, &mut canvas, &mut layout, None, 50);
|
||||
let head = layout
|
||||
render_times(&mut event_pump, &mut canvas, &mut router, None, 50);
|
||||
let head = router
|
||||
.squeeze_around_dot(head, barrier2_dot1, true, 5.0)
|
||||
.unwrap();
|
||||
|
||||
render_times(&mut event_pump, &mut canvas, &mut layout, None, 50);
|
||||
let _ = layout.draw_finish(head, dot4_2, 5.0);*/
|
||||
render_times(&mut event_pump, &mut canvas, &mut router, None, 50);
|
||||
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(
|
||||
&mut event_pump,
|
||||
&mut canvas,
|
||||
&mut layout,
|
||||
&mut router,
|
||||
Some(barrier1_dot1.tag()),
|
||||
-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(
|
||||
event_pump: &mut EventPump,
|
||||
canvas: &mut Canvas<Window>,
|
||||
layout: &mut Layout,
|
||||
router: &mut Router,
|
||||
follower: Option<TaggedIndex>,
|
||||
times: i64,
|
||||
) {
|
||||
|
|
@ -354,14 +375,14 @@ fn render_times(
|
|||
if let Some(follower) = follower {
|
||||
let state = event_pump.mouse_state();
|
||||
|
||||
let _ = layout.move_dot(
|
||||
let _ = router.move_dot(
|
||||
*follower.as_dot().unwrap(),
|
||||
(state.x() as f64, state.y() as f64).into(),
|
||||
);
|
||||
}
|
||||
|
||||
let result = panic::catch_unwind(|| {
|
||||
for shape in layout.shapes() {
|
||||
for shape in router.layout.shapes() {
|
||||
match shape {
|
||||
Shape::Dot(dot) => {
|
||||
let _ = canvas.filled_circle(
|
||||
|
|
@ -385,8 +406,8 @@ fn render_times(
|
|||
let delta1 = bend.from - bend.c.pos;
|
||||
let delta2 = bend.to - bend.c.pos;
|
||||
|
||||
let mut angle1 = delta1.y().atan2(delta1.x());
|
||||
let mut angle2 = delta2.y().atan2(delta2.x());
|
||||
let angle1 = delta1.y().atan2(delta1.x());
|
||||
let angle2 = delta2.y().atan2(delta2.x());
|
||||
|
||||
for d in -2..3 {
|
||||
let _ = canvas.arc(
|
||||
|
|
@ -413,7 +434,7 @@ fn render_times(
|
|||
);
|
||||
}
|
||||
|
||||
for edge in layout.edges() {
|
||||
for edge in router.routeedges() {
|
||||
let _ = canvas.line(
|
||||
edge.0.x() 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