mirror of https://codeberg.org/topola/topola.git
Implement basic shoving
This commit is contained in:
parent
7c86b902aa
commit
68c2863784
|
|
@ -4,10 +4,10 @@ use petgraph::stable_graph::NodeIndex;
|
|||
|
||||
use crate::math::Circle;
|
||||
|
||||
pub trait Set {
|
||||
pub trait Path {
|
||||
fn interior(&self) -> Vec<TaggedIndex>;
|
||||
fn closure(&self) -> Vec<TaggedIndex>;
|
||||
fn boundary(&self) -> Vec<DotIndex>;
|
||||
fn ends(&self) -> [DotIndex; 2];
|
||||
}
|
||||
|
||||
#[derive(Debug, EnumAsInner, Clone, Copy, PartialEq)]
|
||||
|
|
|
|||
101
src/layout.rs
101
src/layout.rs
|
|
@ -4,7 +4,7 @@ use geo::geometry::Point;
|
|||
|
||||
use crate::math::Circle;
|
||||
use crate::mesh::Mesh;
|
||||
use crate::graph::{TaggedIndex, DotIndex, SegIndex, BendIndex};
|
||||
use crate::graph::{TaggedIndex, DotIndex, SegIndex, BendIndex, Path};
|
||||
use crate::rules::{Rules, Conditions};
|
||||
use crate::shape::Shape;
|
||||
use crate::graph::{TaggedWeight, DotWeight, SegWeight, BendWeight};
|
||||
|
|
@ -29,10 +29,18 @@ impl Layout {
|
|||
}
|
||||
|
||||
pub fn route_start(&mut self, from: DotIndex) -> Head {
|
||||
Head {dot: from, bend: None}
|
||||
Head {dot: from, bend: self.mesh.primitive(from).bend()}
|
||||
}
|
||||
|
||||
pub fn route_stop(&mut self, head: Head, to: DotIndex, width: f64) {
|
||||
pub fn route_finish(&mut self, head: Head, to: DotIndex, width: f64) {
|
||||
if let Some(bend) = self.mesh.primitive(to).bend() {
|
||||
self.route_finish_in_bend(head, bend, to, width);
|
||||
} else {
|
||||
self.route_finish_in_dot(head, to, width);
|
||||
}
|
||||
}
|
||||
|
||||
fn route_finish_in_dot(&mut self, head: Head, to: DotIndex, width: f64) {
|
||||
let from_circle = self.head_guidecircle(&head, width);
|
||||
|
||||
let conditions = Conditions {
|
||||
|
|
@ -54,6 +62,37 @@ impl Layout {
|
|||
self.add_seg(head.dot, to, width);
|
||||
}
|
||||
|
||||
fn route_finish_in_bend(&mut self, head: Head, to_bend: BendIndex, to: DotIndex, width: f64) {
|
||||
let from_circle = self.head_guidecircle(&head, width);
|
||||
|
||||
let conditions = Conditions {
|
||||
lower_net: None,
|
||||
higher_net: None,
|
||||
layer: None,
|
||||
zone: None,
|
||||
};
|
||||
|
||||
let to_circle = self.bend_circle(to_bend);
|
||||
let from_cw = self.head_cw(&head);
|
||||
|
||||
let to_head = Head {bend: Some(to_bend), dot: to};
|
||||
let to_cw = self.head_cw(&to_head);
|
||||
|
||||
let tangent_points = math::tangent_point_pair(from_circle, from_cw, to_circle, to_cw);
|
||||
let head = self.extend_head(head, tangent_points.0);
|
||||
|
||||
let to_head = self.extend_head(to_head, tangent_points.1);
|
||||
self.add_seg(head.dot, to, width);
|
||||
}
|
||||
|
||||
pub fn shove_around_dot(&mut self, head: Head, around: DotIndex, cw: bool, width: f64) -> Head {
|
||||
let outer = self.mesh.primitive(around).outer().unwrap();
|
||||
let head = self.route_around_dot(head, around, cw, width);
|
||||
self.mesh.reattach_bend(outer, head.bend.unwrap());
|
||||
self.displace_outers(head.bend.unwrap());
|
||||
head
|
||||
}
|
||||
|
||||
pub fn route_around_dot(&mut self, head: Head, around: DotIndex, cw: bool, width: f64) -> Head {
|
||||
let from_circle = self.head_guidecircle(&head, width);
|
||||
|
||||
|
|
@ -73,6 +112,14 @@ impl Layout {
|
|||
self.route_seg_bend(head, TaggedIndex::Dot(around), tangent_points.1, cw, width)
|
||||
}
|
||||
|
||||
pub fn shove_around_bend(&mut self, head: Head, around: BendIndex, cw: bool, width: f64) -> Head {
|
||||
let outer = self.mesh.primitive(around).outer().unwrap();
|
||||
let head = self.route_around_bend(head, around, cw, width);
|
||||
self.mesh.reattach_bend(outer, head.bend.unwrap());
|
||||
self.displace_outers(head.bend.unwrap());
|
||||
head
|
||||
}
|
||||
|
||||
pub fn route_around_bend(&mut self, head: Head, around: BendIndex, cw: bool, width: f64) -> Head {
|
||||
let from_circle = self.head_guidecircle(&head, width);
|
||||
|
||||
|
|
@ -101,6 +148,36 @@ impl Layout {
|
|||
Head {dot: bend_to, bend: Some(bend)}
|
||||
}
|
||||
|
||||
fn displace_outers(&mut self, bend: BendIndex) {
|
||||
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;
|
||||
while let Some(outer) = self.mesh.primitive(cur_bend).outer() {
|
||||
let stretch = self.mesh.stretch(outer);
|
||||
endss.push(stretch.ends());
|
||||
interiors.push(stretch.interior());
|
||||
cur_bend = outer;
|
||||
}
|
||||
|
||||
for interior in interiors {
|
||||
self.mesh.remove_open_set(interior);
|
||||
}
|
||||
|
||||
let mut cur_bend = bend;
|
||||
for ends in endss {
|
||||
let head = self.route_start(ends[0]);
|
||||
//let width = self.mesh.primitive(head.dot).weight().circle.r * 2.0;
|
||||
let width = 5.0;
|
||||
|
||||
let head = self.route_around_bend(head, cur_bend, cw, width);
|
||||
cur_bend = head.bend.unwrap();
|
||||
|
||||
self.route_finish(head, ends[1], width);
|
||||
}
|
||||
}
|
||||
|
||||
fn route_seg(&mut self, head: Head, to: Point, width: f64) -> Head {
|
||||
let net = self.mesh.primitive(head.dot).weight().net;
|
||||
|
||||
|
|
@ -110,7 +187,7 @@ impl Layout {
|
|||
net,
|
||||
circle: Circle {pos: to, r: width / 2.0},
|
||||
});
|
||||
self.mesh.add_seg(head.dot, to_index, SegWeight {net, width});
|
||||
self.add_seg(head.dot, to_index, width);
|
||||
Head {dot: to_index, bend: None}
|
||||
}
|
||||
|
||||
|
|
@ -154,8 +231,8 @@ impl Layout {
|
|||
}
|
||||
}
|
||||
|
||||
fn bend_guidecircle(&self, bend: BendIndex, width: f64, conditions: Conditions) -> Circle {
|
||||
let mut r = width + self.rules.ruleset(conditions).clearance.min;
|
||||
fn bend_circle(&self, bend: BendIndex) -> Circle {
|
||||
let mut r = 0.0;
|
||||
let mut layer = bend;
|
||||
|
||||
while let Some(inner) = self.mesh.primitive(layer).inner() {
|
||||
|
|
@ -166,10 +243,16 @@ impl Layout {
|
|||
let core_circle = self.mesh.primitive(self.mesh.primitive(bend).core().unwrap()).weight().circle;
|
||||
Circle {
|
||||
pos: core_circle.pos,
|
||||
r: core_circle.r + r + 15.0
|
||||
r: core_circle.r + r
|
||||
}
|
||||
}
|
||||
|
||||
fn bend_guidecircle(&self, bend: BendIndex, width: f64, conditions: Conditions) -> Circle {
|
||||
let mut circle = self.bend_circle(bend);
|
||||
circle.r += width + self.rules.ruleset(conditions).clearance.min + 15.0;
|
||||
circle
|
||||
}
|
||||
|
||||
fn extend_head(&mut self, head: Head, to: Point) -> Head {
|
||||
if let Some(..) = head.bend {
|
||||
self.extend_head_bend(head, to)
|
||||
|
|
@ -191,10 +274,6 @@ impl Layout {
|
|||
self.mesh.add_dot(weight)
|
||||
}
|
||||
|
||||
pub fn remove_dot(&mut self, index: DotIndex) {
|
||||
self.mesh.remove_dot(index);
|
||||
}
|
||||
|
||||
pub fn add_seg(&mut self, from: DotIndex, to: DotIndex, width: f64) -> SegIndex {
|
||||
let net = self.mesh.primitive(from).weight().net;
|
||||
self.mesh.add_seg(from, to, SegWeight {net, width})
|
||||
|
|
|
|||
39
src/main.rs
39
src/main.rs
|
|
@ -7,7 +7,6 @@ mod mesh;
|
|||
mod stretch;
|
||||
mod primitive;
|
||||
mod shape;
|
||||
mod weight;
|
||||
mod math;
|
||||
|
||||
use std::time::Duration;
|
||||
|
|
@ -39,6 +38,7 @@ fn main() {
|
|||
let mut i = 0;
|
||||
let mut layout = Layout::new();
|
||||
|
||||
|
||||
/*let index = layout.add_dot(DotWeight {net: 0, circle: Circle {pos: (150.5, 80.5).into(), r: 8.0}});
|
||||
//layout.route_seg(index, Point {x: 400.5, y: 350.5}, 6.0);
|
||||
|
||||
|
|
@ -56,7 +56,8 @@ fn main() {
|
|||
let index6 = layout.add_dot(DotWeight {net: 0, circle: Circle {pos: (140.5, 300.5).into(), r: 8.0}});
|
||||
let index7 = layout.route_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 = 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}});
|
||||
|
||||
|
|
@ -72,7 +73,7 @@ fn main() {
|
|||
let head = layout.route_around_dot(head, obstacle_dot1, true, 5.0);
|
||||
let dot3_1 = head.dot;
|
||||
let bend3_1 = head.bend.unwrap();
|
||||
layout.route_stop(head, dot4, 5.0);
|
||||
layout.route_finish(head, dot4, 5.0);
|
||||
|
||||
let head = layout.route_start(dot2);
|
||||
let head = layout.route_around_dot(head, dot3, true, 5.0);
|
||||
|
|
@ -81,12 +82,40 @@ fn main() {
|
|||
let head = layout.route_around_bend(head, bend3_1, true, 5.0);
|
||||
let dot2_2 = head.dot;
|
||||
let bend2_2 = head.bend.unwrap();
|
||||
layout.route_stop(head, dot5, 5.0);
|
||||
layout.route_finish(head, dot5, 5.0);
|
||||
|
||||
let head = layout.route_start(dot1);
|
||||
let head = layout.route_around_bend(head, bend2_1, true, 5.0);
|
||||
let head = layout.route_around_bend(head, bend2_2, true, 5.0);
|
||||
layout.route_stop(head, dot6, 5.0);
|
||||
layout.route_finish(head, dot6, 5.0);*/
|
||||
|
||||
|
||||
let dot1_1 = layout.add_dot(DotWeight {net: 0, circle: Circle {pos: (200.5, 200.5).into(), r: 8.0}});
|
||||
let dot2_1 = layout.add_dot(DotWeight {net: 0, circle: Circle {pos: (230.5, 230.5).into(), r: 8.0}});
|
||||
let dot3_1 = layout.add_dot(DotWeight {net: 0, circle: Circle {pos: (260.5, 260.5).into(), r: 8.0}});
|
||||
|
||||
let dot1_2 = layout.add_dot(DotWeight {net: 0, circle: Circle {pos: (500.5, 200.5).into(), r: 8.0}});
|
||||
let dot2_2 = layout.add_dot(DotWeight {net: 0, circle: Circle {pos: (470.5, 230.5).into(), r: 8.0}});
|
||||
let dot3_2 = layout.add_dot(DotWeight {net: 0, circle: Circle {pos: (440.5, 260.5).into(), r: 8.0}});
|
||||
|
||||
let barrier_dot1 = layout.add_dot(DotWeight {net: 0, circle: Circle {pos: (350.5, 150.5).into(), r: 8.0}});
|
||||
let barrier_dot2 = layout.add_dot(DotWeight {net: 0, circle: Circle {pos: (350.5, 500.5).into(), r: 8.0}});
|
||||
layout.add_seg(barrier_dot1, barrier_dot2, 16.0);
|
||||
|
||||
let head = layout.route_start(dot1_1);
|
||||
let head = layout.route_around_dot(head, barrier_dot1, true, 5.0);
|
||||
layout.route_finish(head, dot1_2, 5.0);
|
||||
|
||||
let head = layout.route_start(dot2_1);
|
||||
//let head = layout.route_around_dot(head, barrier_dot1, true, 5.0);
|
||||
let head = layout.shove_around_dot(head, barrier_dot1, true, 5.0);
|
||||
layout.route_finish(head, dot2_2, 5.0);
|
||||
|
||||
let head = layout.route_start(dot3_1);
|
||||
//let head = layout.route_around_dot(head, barrier_dot1, true, 5.0);
|
||||
let head = layout.shove_around_dot(head, barrier_dot1, true, 5.0);
|
||||
layout.route_finish(head, dot3_2, 5.0);
|
||||
|
||||
|
||||
'running: loop {
|
||||
i = (i + 1) % 255;
|
||||
|
|
|
|||
55
src/mesh.rs
55
src/mesh.rs
|
|
@ -1,11 +1,14 @@
|
|||
use geo::Point;
|
||||
use petgraph::Direction::Incoming;
|
||||
use petgraph::stable_graph::StableDiGraph;
|
||||
use petgraph::visit::EdgeRef;
|
||||
use rstar::RTree;
|
||||
use rstar::primitives::GeomWithData;
|
||||
|
||||
use crate::primitive::Primitive;
|
||||
use crate::shape::Shape;
|
||||
use crate::graph::{Tag, TaggedIndex, DotIndex, SegIndex, BendIndex, Index, TaggedWeight, DotWeight, SegWeight, BendWeight, Label};
|
||||
use crate::graph::{Tag, TaggedIndex, DotIndex, SegIndex, BendIndex, Index, TaggedWeight, DotWeight, SegWeight, BendWeight, Label, Path};
|
||||
use crate::stretch::Stretch;
|
||||
|
||||
pub type RTreeWrapper = GeomWithData<Shape, TaggedIndex>;
|
||||
|
||||
|
|
@ -22,17 +25,33 @@ impl Mesh {
|
|||
}
|
||||
}
|
||||
|
||||
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();
|
||||
self.rtree.remove(&RTreeWrapper::new(self.primitive(index).shape(), index.retag(weight)));
|
||||
|
||||
self.graph.remove_node(index.index);
|
||||
}
|
||||
|
||||
pub fn add_dot(&mut self, weight: DotWeight) -> DotIndex {
|
||||
let dot = DotIndex::new(self.graph.add_node(TaggedWeight::Dot(weight)));
|
||||
self.rtree.insert(RTreeWrapper::new(self.primitive(dot).shape(), TaggedIndex::Dot(dot)));
|
||||
dot
|
||||
}
|
||||
|
||||
pub fn remove_dot(&mut self, dot: DotIndex) {
|
||||
self.rtree.remove(&RTreeWrapper::new(self.primitive(dot).shape(), TaggedIndex::Dot(dot)));
|
||||
self.graph.remove_node(dot.index);
|
||||
}
|
||||
|
||||
pub fn add_seg(&mut self, from: DotIndex, to: DotIndex, weight: SegWeight) -> SegIndex {
|
||||
let seg = SegIndex::new(self.graph.add_node(TaggedWeight::Seg(weight)));
|
||||
self.graph.add_edge(from.index, seg.index, Label::End);
|
||||
|
|
@ -42,11 +61,6 @@ impl Mesh {
|
|||
seg
|
||||
}
|
||||
|
||||
pub fn remove_seg(&mut self, seg: SegIndex) {
|
||||
self.rtree.remove(&RTreeWrapper::new(self.primitive(seg).shape(), TaggedIndex::Seg(seg)));
|
||||
self.graph.remove_node(seg.index);
|
||||
}
|
||||
|
||||
pub fn add_bend(&mut self, from: DotIndex, to: DotIndex, around: TaggedIndex, weight: BendWeight) -> BendIndex {
|
||||
match around {
|
||||
TaggedIndex::Dot(core) =>
|
||||
|
|
@ -79,9 +93,14 @@ impl Mesh {
|
|||
bend
|
||||
}
|
||||
|
||||
pub fn remove_bend(&mut self, bend: BendIndex) {
|
||||
self.rtree.remove(&RTreeWrapper::new(self.primitive(bend).shape(), TaggedIndex::Bend(bend)));
|
||||
self.graph.remove_node(bend.index);
|
||||
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) {
|
||||
|
|
@ -96,10 +115,6 @@ impl Mesh {
|
|||
self.insert_into_rtree(bend.tag());
|
||||
}
|
||||
|
||||
pub fn reoffset_bend(&mut self, bend: BendIndex, offset: f64) {
|
||||
|
||||
}
|
||||
|
||||
pub fn nodes(&self) -> impl Iterator<Item=TaggedIndex> + '_ {
|
||||
self.rtree.iter().map(|wrapper| wrapper.data)
|
||||
}
|
||||
|
|
@ -108,6 +123,10 @@ impl Mesh {
|
|||
Primitive::new(index, &self.graph)
|
||||
}
|
||||
|
||||
pub fn stretch(&self, bend: BendIndex) -> Stretch {
|
||||
Stretch::new(bend, &self.graph)
|
||||
}
|
||||
|
||||
fn insert_into_rtree(&mut self, index: TaggedIndex) {
|
||||
let shape = untag!(index, self.primitive(index).shape());
|
||||
self.rtree.insert(RTreeWrapper::new(shape, index));
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ use std::mem::swap;
|
|||
use petgraph::Direction::{Outgoing, Incoming};
|
||||
use petgraph::stable_graph::StableDiGraph;
|
||||
|
||||
use crate::graph::{Set, DotIndex, SegIndex, BendIndex, TaggedIndex, Tag, Index, DotWeight, SegWeight, BendWeight, TaggedWeight, Label};
|
||||
use crate::graph::{Path, DotIndex, SegIndex, BendIndex, TaggedIndex, Tag, Index, DotWeight, SegWeight, BendWeight, TaggedWeight, Label};
|
||||
use crate::shape::Shape;
|
||||
|
||||
pub struct Primitive<'a, Weight> {
|
||||
|
|
@ -17,7 +17,6 @@ impl<'a, Weight> Primitive<'a, Weight> {
|
|||
}
|
||||
|
||||
pub fn shape(&self) -> Shape {
|
||||
let ends = self.ends();
|
||||
match self.tagged_weight() {
|
||||
TaggedWeight::Dot(dot) => Shape {
|
||||
width: dot.circle.r * 2.0,
|
||||
|
|
@ -26,6 +25,7 @@ impl<'a, Weight> Primitive<'a, Weight> {
|
|||
center: None,
|
||||
},
|
||||
TaggedWeight::Seg(seg) => {
|
||||
let ends = self.ends();
|
||||
Shape {
|
||||
width: seg.width,
|
||||
from: self.primitive(ends[0]).weight().circle.pos,
|
||||
|
|
@ -34,6 +34,7 @@ impl<'a, Weight> Primitive<'a, Weight> {
|
|||
}
|
||||
}
|
||||
TaggedWeight::Bend(bend) => {
|
||||
let ends = self.ends();
|
||||
let mut shape = Shape {
|
||||
width: self.primitive(ends[0]).weight().circle.r * 2.0,
|
||||
from: self.primitive(ends[0]).weight().circle.pos,
|
||||
|
|
@ -51,26 +52,18 @@ impl<'a, Weight> Primitive<'a, Weight> {
|
|||
|
||||
pub fn next(&self) -> Option<TaggedIndex> {
|
||||
self.graph.neighbors_directed(self.index.index, Outgoing)
|
||||
.filter(|ni| self.graph.edge_weight(self.graph.find_edge(*ni, self.index.index).unwrap()).unwrap().is_end())
|
||||
.filter(|ni| self.graph.edge_weight(self.graph.find_edge(self.index.index, *ni).unwrap()).unwrap().is_end())
|
||||
.map(|ni| Index::<Label>::new(ni).retag(*self.graph.node_weight(ni).unwrap()))
|
||||
.next()
|
||||
}
|
||||
|
||||
pub fn prev(&self) -> Option<TaggedIndex> {
|
||||
self.graph.neighbors_directed(self.index.index, Incoming)
|
||||
.filter(|ni| self.graph.edge_weight(self.graph.find_edge(self.index.index, *ni).unwrap()).unwrap().is_end())
|
||||
.filter(|ni| self.graph.edge_weight(self.graph.find_edge(*ni, self.index.index).unwrap()).unwrap().is_end())
|
||||
.map(|ni| Index::<Label>::new(ni).retag(*self.graph.node_weight(ni).unwrap()))
|
||||
.next()
|
||||
}
|
||||
|
||||
pub fn ends(&self) -> Vec<DotIndex> {
|
||||
self.graph.neighbors_undirected(self.index.index)
|
||||
.filter(|ni| self.graph.edge_weight(self.graph.find_edge_undirected(self.index.index, *ni).unwrap().0).unwrap().is_end())
|
||||
.filter(|ni| self.graph.node_weight(*ni).unwrap().is_dot())
|
||||
.map(|ni| DotIndex::new(ni))
|
||||
.collect()
|
||||
}
|
||||
|
||||
pub fn core(&self) -> Option<DotIndex> {
|
||||
self.graph.neighbors(self.index.index)
|
||||
.filter(|ni| self.graph.edge_weight(self.graph.find_edge(self.index.index, *ni).unwrap()).unwrap().is_core())
|
||||
|
|
@ -91,7 +84,7 @@ impl<'a, Weight> Primitive<'a, Weight> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<'a, Weight> Set for Primitive<'a, Weight> {
|
||||
impl<'a, Weight> Path for Primitive<'a, Weight> {
|
||||
fn interior(&self) -> Vec<TaggedIndex> {
|
||||
vec![self.tagged_index()]
|
||||
}
|
||||
|
|
@ -104,8 +97,14 @@ impl<'a, Weight> Set for Primitive<'a, Weight> {
|
|||
[[self.tagged_index()].as_slice(), ends.as_slice()].concat()
|
||||
}
|
||||
|
||||
fn boundary(&self) -> Vec<DotIndex> {
|
||||
self.ends()
|
||||
fn ends(&self) -> [DotIndex; 2] {
|
||||
self.graph.neighbors_undirected(self.index.index)
|
||||
.filter(|ni| self.graph.edge_weight(self.graph.find_edge_undirected(self.index.index, *ni).unwrap().0).unwrap().is_end())
|
||||
.filter(|ni| self.graph.node_weight(*ni).unwrap().is_dot())
|
||||
.map(|ni| DotIndex::new(ni))
|
||||
.collect::<Vec<DotIndex>>()
|
||||
.try_into()
|
||||
.unwrap()
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -114,6 +113,22 @@ pub type Seg<'a> = Primitive<'a, SegWeight>;
|
|||
pub type Bend<'a> = Primitive<'a, BendWeight>;
|
||||
|
||||
impl<'a> Dot<'a> {
|
||||
pub fn bend(&self) -> Option<BendIndex> {
|
||||
self.graph.neighbors_undirected(self.index.index)
|
||||
.filter(|ni| self.graph.edge_weight(self.graph.find_edge_undirected(self.index.index, *ni).unwrap().0).unwrap().is_end())
|
||||
.filter(|ni| self.graph.node_weight(*ni).unwrap().is_bend())
|
||||
.map(|ni| BendIndex::new(ni))
|
||||
.next()
|
||||
}
|
||||
|
||||
pub fn outer(&self) -> Option<BendIndex> {
|
||||
self.graph.neighbors_directed(self.index.index, Incoming)
|
||||
.filter(|ni| self.graph.edge_weight(self.graph.find_edge(*ni, self.index.index).unwrap()).unwrap().is_core())
|
||||
.map(|ni| BendIndex::new(ni))
|
||||
.filter(|bend| self.primitive(*bend).inner().is_none())
|
||||
.next()
|
||||
}
|
||||
|
||||
pub fn weight(&self) -> DotWeight {
|
||||
*self.tagged_weight().as_dot().unwrap()
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,99 +1,72 @@
|
|||
use petgraph::stable_graph::StableDiGraph;
|
||||
|
||||
use crate::primitive::{Dot, Seg, Bend};
|
||||
use crate::graph::{TaggedIndex, DotIndex, SegIndex, BendIndex, TaggedWeight, Label, Set};
|
||||
use crate::graph::{TaggedIndex, DotIndex, SegIndex, BendIndex, TaggedWeight, Label, Path};
|
||||
|
||||
pub struct Stretch<'a> {
|
||||
bend1_dot1: DotIndex,
|
||||
bend1: BendIndex,
|
||||
bend1_dot2: DotIndex,
|
||||
seg1_dot1: DotIndex,
|
||||
seg1: SegIndex,
|
||||
bend2_dot1: DotIndex,
|
||||
bend2: BendIndex,
|
||||
bend2_dot2: DotIndex,
|
||||
seg1_dot2: DotIndex,
|
||||
bend: BendIndex,
|
||||
seg2_dot1: DotIndex,
|
||||
seg2: SegIndex,
|
||||
bend3_dot1: DotIndex,
|
||||
bend3: BendIndex,
|
||||
bend3_dot2: DotIndex,
|
||||
seg2_dot2: DotIndex,
|
||||
graph: &'a StableDiGraph<TaggedWeight, Label, usize>,
|
||||
}
|
||||
|
||||
impl<'a> Stretch<'a> {
|
||||
pub fn new(index: BendIndex, graph: &'a StableDiGraph<TaggedWeight, Label, usize>) -> Self {
|
||||
let bend2 = index;
|
||||
let bend = index;
|
||||
|
||||
let bend2_dot1 = *Bend::new(bend2, graph).prev().unwrap().as_dot().unwrap();
|
||||
let seg1 = *Dot::new(bend2_dot1, graph).prev().unwrap().as_seg().unwrap();
|
||||
let bend1_dot2 = *Seg::new(seg1, graph).prev().unwrap().as_dot().unwrap();
|
||||
let bend1 = *Dot::new(bend1_dot2, graph).prev().unwrap().as_bend().unwrap();
|
||||
let bend1_dot1 = *Bend::new(bend1, graph).prev().unwrap().as_dot().unwrap();
|
||||
let seg1_dot2 = *Bend::new(bend, graph).prev().unwrap().as_dot().unwrap();
|
||||
let seg1 = *Dot::new(seg1_dot2, graph).prev().unwrap().as_seg().unwrap();
|
||||
let seg1_dot1 = *Seg::new(seg1, graph).prev().unwrap().as_dot().unwrap();
|
||||
|
||||
let bend2_dot2 = *Bend::new(bend2, graph).next().unwrap().as_dot().unwrap();
|
||||
let seg2 = *Dot::new(bend2_dot1, graph).next().unwrap().as_seg().unwrap();
|
||||
let bend3_dot1 = *Seg::new(seg1, graph).next().unwrap().as_dot().unwrap();
|
||||
let bend3 = *Dot::new(bend1_dot2, graph).next().unwrap().as_bend().unwrap();
|
||||
let bend3_dot2 = *Bend::new(bend1, graph).next().unwrap().as_dot().unwrap();
|
||||
let seg2_dot1 = *Bend::new(bend, graph).next().unwrap().as_dot().unwrap();
|
||||
let seg2 = *Dot::new(seg2_dot1, graph).next().unwrap().as_seg().unwrap();
|
||||
let seg2_dot2 = *Seg::new(seg2, graph).next().unwrap().as_dot().unwrap();
|
||||
|
||||
Self {
|
||||
bend1_dot1,
|
||||
bend1,
|
||||
bend1_dot2,
|
||||
seg1_dot1,
|
||||
seg1,
|
||||
bend2_dot1,
|
||||
bend2,
|
||||
bend2_dot2,
|
||||
seg1_dot2,
|
||||
bend,
|
||||
seg2_dot1,
|
||||
seg2,
|
||||
bend3_dot1,
|
||||
bend3,
|
||||
bend3_dot2,
|
||||
seg2_dot2,
|
||||
graph,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Set for Stretch<'a> {
|
||||
impl<'a> Path for Stretch<'a> {
|
||||
fn interior(&self) -> Vec<TaggedIndex> {
|
||||
vec![
|
||||
TaggedIndex::Bend(self.bend1),
|
||||
TaggedIndex::Dot(self.bend1_dot2),
|
||||
|
||||
TaggedIndex::Seg(self.seg1),
|
||||
|
||||
TaggedIndex::Dot(self.bend2_dot1),
|
||||
TaggedIndex::Bend(self.bend2),
|
||||
TaggedIndex::Dot(self.bend2_dot2),
|
||||
TaggedIndex::Dot(self.seg1_dot2),
|
||||
TaggedIndex::Bend(self.bend),
|
||||
TaggedIndex::Dot(self.seg2_dot1),
|
||||
|
||||
TaggedIndex::Seg(self.seg2),
|
||||
|
||||
TaggedIndex::Dot(self.bend3_dot1),
|
||||
TaggedIndex::Bend(self.bend3),
|
||||
]
|
||||
}
|
||||
|
||||
fn closure(&self) -> Vec<TaggedIndex> {
|
||||
vec![
|
||||
TaggedIndex::Dot(self.bend1_dot1),
|
||||
TaggedIndex::Bend(self.bend1),
|
||||
TaggedIndex::Dot(self.bend1_dot2),
|
||||
|
||||
TaggedIndex::Dot(self.seg1_dot1),
|
||||
TaggedIndex::Seg(self.seg1),
|
||||
|
||||
TaggedIndex::Dot(self.bend2_dot1),
|
||||
TaggedIndex::Bend(self.bend2),
|
||||
TaggedIndex::Dot(self.bend2_dot2),
|
||||
TaggedIndex::Dot(self.seg1_dot2),
|
||||
TaggedIndex::Bend(self.bend),
|
||||
TaggedIndex::Dot(self.seg2_dot1),
|
||||
|
||||
TaggedIndex::Seg(self.seg2),
|
||||
|
||||
TaggedIndex::Dot(self.bend3_dot1),
|
||||
TaggedIndex::Bend(self.bend3),
|
||||
TaggedIndex::Dot(self.bend3_dot2),
|
||||
TaggedIndex::Dot(self.seg2_dot2),
|
||||
]
|
||||
}
|
||||
|
||||
fn boundary(&self) -> Vec<DotIndex> {
|
||||
vec![
|
||||
self.bend1_dot1,
|
||||
self.bend3_dot2,
|
||||
]
|
||||
fn ends(&self) -> [DotIndex; 2] {
|
||||
[self.seg1_dot1, self.seg2_dot2]
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,2 +0,0 @@
|
|||
use enum_as_inner::EnumAsInner;
|
||||
use crate::math::Circle;
|
||||
Loading…
Reference in New Issue