Implement basic shoving

This commit is contained in:
Mikolaj Wielgus 2023-07-25 04:08:06 +02:00
parent 7c86b902aa
commit 68c2863784
7 changed files with 223 additions and 110 deletions

View File

@ -4,10 +4,10 @@ use petgraph::stable_graph::NodeIndex;
use crate::math::Circle; use crate::math::Circle;
pub trait Set { pub trait Path {
fn interior(&self) -> Vec<TaggedIndex>; fn interior(&self) -> Vec<TaggedIndex>;
fn closure(&self) -> Vec<TaggedIndex>; fn closure(&self) -> Vec<TaggedIndex>;
fn boundary(&self) -> Vec<DotIndex>; fn ends(&self) -> [DotIndex; 2];
} }
#[derive(Debug, EnumAsInner, Clone, Copy, PartialEq)] #[derive(Debug, EnumAsInner, Clone, Copy, PartialEq)]

View File

@ -4,7 +4,7 @@ use geo::geometry::Point;
use crate::math::Circle; use crate::math::Circle;
use crate::mesh::Mesh; 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::rules::{Rules, Conditions};
use crate::shape::Shape; use crate::shape::Shape;
use crate::graph::{TaggedWeight, DotWeight, SegWeight, BendWeight}; use crate::graph::{TaggedWeight, DotWeight, SegWeight, BendWeight};
@ -29,10 +29,18 @@ impl Layout {
} }
pub fn route_start(&mut self, from: DotIndex) -> Head { 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 from_circle = self.head_guidecircle(&head, width);
let conditions = Conditions { let conditions = Conditions {
@ -54,6 +62,37 @@ impl Layout {
self.add_seg(head.dot, to, width); 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 { pub fn route_around_dot(&mut self, head: Head, around: DotIndex, cw: bool, width: f64) -> Head {
let from_circle = self.head_guidecircle(&head, width); 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) 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 { pub fn route_around_bend(&mut self, head: Head, around: BendIndex, cw: bool, width: f64) -> Head {
let from_circle = self.head_guidecircle(&head, width); let from_circle = self.head_guidecircle(&head, width);
@ -101,6 +148,36 @@ impl Layout {
Head {dot: bend_to, bend: Some(bend)} 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 { fn route_seg(&mut self, head: Head, to: Point, width: f64) -> Head {
let net = self.mesh.primitive(head.dot).weight().net; let net = self.mesh.primitive(head.dot).weight().net;
@ -110,7 +187,7 @@ impl Layout {
net, net,
circle: Circle {pos: to, r: width / 2.0}, 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} Head {dot: to_index, bend: None}
} }
@ -154,8 +231,8 @@ impl Layout {
} }
} }
fn bend_guidecircle(&self, bend: BendIndex, width: f64, conditions: Conditions) -> Circle { fn bend_circle(&self, bend: BendIndex) -> Circle {
let mut r = width + self.rules.ruleset(conditions).clearance.min; let mut r = 0.0;
let mut layer = bend; let mut layer = bend;
while let Some(inner) = self.mesh.primitive(layer).inner() { 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; let core_circle = self.mesh.primitive(self.mesh.primitive(bend).core().unwrap()).weight().circle;
Circle { Circle {
pos: core_circle.pos, 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 { fn extend_head(&mut self, head: Head, to: Point) -> Head {
if let Some(..) = head.bend { if let Some(..) = head.bend {
self.extend_head_bend(head, to) self.extend_head_bend(head, to)
@ -191,10 +274,6 @@ impl Layout {
self.mesh.add_dot(weight) 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 { pub fn add_seg(&mut self, from: DotIndex, to: DotIndex, width: f64) -> SegIndex {
let net = self.mesh.primitive(from).weight().net; let net = self.mesh.primitive(from).weight().net;
self.mesh.add_seg(from, to, SegWeight {net, width}) self.mesh.add_seg(from, to, SegWeight {net, width})

View File

@ -7,7 +7,6 @@ mod mesh;
mod stretch; mod stretch;
mod primitive; mod primitive;
mod shape; mod shape;
mod weight;
mod math; mod math;
use std::time::Duration; use std::time::Duration;
@ -38,7 +37,8 @@ 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 layout = Layout::new();
/*let index = layout.add_dot(DotWeight {net: 0, circle: Circle {pos: (150.5, 80.5).into(), r: 8.0}}); /*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); //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 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 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 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 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 head = layout.route_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.route_stop(head, dot4, 5.0); layout.route_finish(head, dot4, 5.0);
let head = layout.route_start(dot2); let head = layout.route_start(dot2);
let head = layout.route_around_dot(head, dot3, true, 5.0); 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 head = layout.route_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.route_stop(head, dot5, 5.0); layout.route_finish(head, dot5, 5.0);
let head = layout.route_start(dot1); 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_1, true, 5.0);
let head = layout.route_around_bend(head, bend2_2, 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 { 'running: loop {
i = (i + 1) % 255; i = (i + 1) % 255;

View File

@ -1,11 +1,14 @@
use geo::Point; use geo::Point;
use petgraph::Direction::Incoming;
use petgraph::stable_graph::StableDiGraph; use petgraph::stable_graph::StableDiGraph;
use petgraph::visit::EdgeRef;
use rstar::RTree; use rstar::RTree;
use rstar::primitives::GeomWithData; use rstar::primitives::GeomWithData;
use crate::primitive::Primitive; use crate::primitive::Primitive;
use crate::shape::Shape; 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>; 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 { pub fn add_dot(&mut self, weight: DotWeight) -> DotIndex {
let dot = DotIndex::new(self.graph.add_node(TaggedWeight::Dot(weight))); let dot = DotIndex::new(self.graph.add_node(TaggedWeight::Dot(weight)));
self.rtree.insert(RTreeWrapper::new(self.primitive(dot).shape(), TaggedIndex::Dot(dot))); self.rtree.insert(RTreeWrapper::new(self.primitive(dot).shape(), TaggedIndex::Dot(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 { pub fn add_seg(&mut self, from: DotIndex, to: DotIndex, weight: SegWeight) -> SegIndex {
let seg = SegIndex::new(self.graph.add_node(TaggedWeight::Seg(weight))); 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(from.index, seg.index, Label::End);
@ -42,11 +61,6 @@ impl Mesh {
seg 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 { pub fn add_bend(&mut self, from: DotIndex, to: DotIndex, around: TaggedIndex, weight: BendWeight) -> BendIndex {
match around { match around {
TaggedIndex::Dot(core) => TaggedIndex::Dot(core) =>
@ -79,9 +93,14 @@ impl Mesh {
bend bend
} }
pub fn remove_bend(&mut self, bend: BendIndex) { pub fn reattach_bend(&mut self, bend: BendIndex, inner: BendIndex) {
self.rtree.remove(&RTreeWrapper::new(self.primitive(bend).shape(), TaggedIndex::Bend(bend))); if let Some(old_inner_edge) = self.graph.edges_directed(bend.index, Incoming)
self.graph.remove_node(bend.index); .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) { pub fn extend_bend(&mut self, bend: BendIndex, dot: DotIndex, to: Point) {
@ -95,10 +114,6 @@ impl Mesh {
self.insert_into_rtree(dot.tag()); self.insert_into_rtree(dot.tag());
self.insert_into_rtree(bend.tag()); self.insert_into_rtree(bend.tag());
} }
pub fn reoffset_bend(&mut self, bend: BendIndex, offset: f64) {
}
pub fn nodes(&self) -> impl Iterator<Item=TaggedIndex> + '_ { pub fn nodes(&self) -> impl Iterator<Item=TaggedIndex> + '_ {
self.rtree.iter().map(|wrapper| wrapper.data) self.rtree.iter().map(|wrapper| wrapper.data)
@ -108,6 +123,10 @@ impl Mesh {
Primitive::new(index, &self.graph) 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) { fn insert_into_rtree(&mut self, index: TaggedIndex) {
let shape = untag!(index, self.primitive(index).shape()); let shape = untag!(index, self.primitive(index).shape());
self.rtree.insert(RTreeWrapper::new(shape, index)); self.rtree.insert(RTreeWrapper::new(shape, index));

View File

@ -3,7 +3,7 @@ use std::mem::swap;
use petgraph::Direction::{Outgoing, Incoming}; use petgraph::Direction::{Outgoing, Incoming};
use petgraph::stable_graph::StableDiGraph; 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; use crate::shape::Shape;
pub struct Primitive<'a, Weight> { pub struct Primitive<'a, Weight> {
@ -17,7 +17,6 @@ impl<'a, Weight> Primitive<'a, Weight> {
} }
pub fn shape(&self) -> Shape { pub fn shape(&self) -> Shape {
let ends = self.ends();
match self.tagged_weight() { match self.tagged_weight() {
TaggedWeight::Dot(dot) => Shape { TaggedWeight::Dot(dot) => Shape {
width: dot.circle.r * 2.0, width: dot.circle.r * 2.0,
@ -26,6 +25,7 @@ impl<'a, Weight> Primitive<'a, Weight> {
center: None, center: None,
}, },
TaggedWeight::Seg(seg) => { TaggedWeight::Seg(seg) => {
let ends = self.ends();
Shape { Shape {
width: seg.width, width: seg.width,
from: self.primitive(ends[0]).weight().circle.pos, from: self.primitive(ends[0]).weight().circle.pos,
@ -34,6 +34,7 @@ impl<'a, Weight> Primitive<'a, Weight> {
} }
} }
TaggedWeight::Bend(bend) => { TaggedWeight::Bend(bend) => {
let ends = self.ends();
let mut shape = Shape { let mut shape = Shape {
width: self.primitive(ends[0]).weight().circle.r * 2.0, width: self.primitive(ends[0]).weight().circle.r * 2.0,
from: self.primitive(ends[0]).weight().circle.pos, from: self.primitive(ends[0]).weight().circle.pos,
@ -51,26 +52,18 @@ impl<'a, Weight> Primitive<'a, Weight> {
pub fn next(&self) -> Option<TaggedIndex> { pub fn next(&self) -> Option<TaggedIndex> {
self.graph.neighbors_directed(self.index.index, Outgoing) 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())) .map(|ni| Index::<Label>::new(ni).retag(*self.graph.node_weight(ni).unwrap()))
.next() .next()
} }
pub fn prev(&self) -> Option<TaggedIndex> { pub fn prev(&self) -> Option<TaggedIndex> {
self.graph.neighbors_directed(self.index.index, Incoming) 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())) .map(|ni| Index::<Label>::new(ni).retag(*self.graph.node_weight(ni).unwrap()))
.next() .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> { pub fn core(&self) -> Option<DotIndex> {
self.graph.neighbors(self.index.index) self.graph.neighbors(self.index.index)
.filter(|ni| self.graph.edge_weight(self.graph.find_edge(self.index.index, *ni).unwrap()).unwrap().is_core()) .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> { fn interior(&self) -> Vec<TaggedIndex> {
vec![self.tagged_index()] 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() [[self.tagged_index()].as_slice(), ends.as_slice()].concat()
} }
fn boundary(&self) -> Vec<DotIndex> { fn ends(&self) -> [DotIndex; 2] {
self.ends() 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>; pub type Bend<'a> = Primitive<'a, BendWeight>;
impl<'a> Dot<'a> { 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 { pub fn weight(&self) -> DotWeight {
*self.tagged_weight().as_dot().unwrap() *self.tagged_weight().as_dot().unwrap()
} }

View File

@ -1,99 +1,72 @@
use petgraph::stable_graph::StableDiGraph; use petgraph::stable_graph::StableDiGraph;
use crate::primitive::{Dot, Seg, Bend}; 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> { pub struct Stretch<'a> {
bend1_dot1: DotIndex, seg1_dot1: DotIndex,
bend1: BendIndex,
bend1_dot2: DotIndex,
seg1: SegIndex, seg1: SegIndex,
bend2_dot1: DotIndex, seg1_dot2: DotIndex,
bend2: BendIndex, bend: BendIndex,
bend2_dot2: DotIndex, seg2_dot1: DotIndex,
seg2: SegIndex, seg2: SegIndex,
bend3_dot1: DotIndex, seg2_dot2: DotIndex,
bend3: BendIndex,
bend3_dot2: DotIndex,
graph: &'a StableDiGraph<TaggedWeight, Label, usize>, graph: &'a StableDiGraph<TaggedWeight, Label, usize>,
} }
impl<'a> Stretch<'a> { impl<'a> Stretch<'a> {
pub fn new(index: BendIndex, graph: &'a StableDiGraph<TaggedWeight, Label, usize>) -> Self { 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_dot2 = *Bend::new(bend, graph).prev().unwrap().as_dot().unwrap();
let seg1 = *Dot::new(bend2_dot1, graph).prev().unwrap().as_seg().unwrap(); let seg1 = *Dot::new(seg1_dot2, graph).prev().unwrap().as_seg().unwrap();
let bend1_dot2 = *Seg::new(seg1, graph).prev().unwrap().as_dot().unwrap(); let seg1_dot1 = *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 bend2_dot2 = *Bend::new(bend2, graph).next().unwrap().as_dot().unwrap(); let seg2_dot1 = *Bend::new(bend, graph).next().unwrap().as_dot().unwrap();
let seg2 = *Dot::new(bend2_dot1, graph).next().unwrap().as_seg().unwrap(); let seg2 = *Dot::new(seg2_dot1, graph).next().unwrap().as_seg().unwrap();
let bend3_dot1 = *Seg::new(seg1, graph).next().unwrap().as_dot().unwrap(); let seg2_dot2 = *Seg::new(seg2, 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();
Self { Self {
bend1_dot1, seg1_dot1,
bend1,
bend1_dot2,
seg1, seg1,
bend2_dot1, seg1_dot2,
bend2, bend,
bend2_dot2, seg2_dot1,
seg2, seg2,
bend3_dot1, seg2_dot2,
bend3,
bend3_dot2,
graph, graph,
} }
} }
} }
impl<'a> Set for Stretch<'a> { impl<'a> Path for Stretch<'a> {
fn interior(&self) -> Vec<TaggedIndex> { fn interior(&self) -> Vec<TaggedIndex> {
vec![ vec![
TaggedIndex::Bend(self.bend1),
TaggedIndex::Dot(self.bend1_dot2),
TaggedIndex::Seg(self.seg1), TaggedIndex::Seg(self.seg1),
TaggedIndex::Dot(self.bend2_dot1), TaggedIndex::Dot(self.seg1_dot2),
TaggedIndex::Bend(self.bend2), TaggedIndex::Bend(self.bend),
TaggedIndex::Dot(self.bend2_dot2), TaggedIndex::Dot(self.seg2_dot1),
TaggedIndex::Seg(self.seg2), TaggedIndex::Seg(self.seg2),
TaggedIndex::Dot(self.bend3_dot1),
TaggedIndex::Bend(self.bend3),
] ]
} }
fn closure(&self) -> Vec<TaggedIndex> { fn closure(&self) -> Vec<TaggedIndex> {
vec![ vec![
TaggedIndex::Dot(self.bend1_dot1), TaggedIndex::Dot(self.seg1_dot1),
TaggedIndex::Bend(self.bend1),
TaggedIndex::Dot(self.bend1_dot2),
TaggedIndex::Seg(self.seg1), TaggedIndex::Seg(self.seg1),
TaggedIndex::Dot(self.bend2_dot1), TaggedIndex::Dot(self.seg1_dot2),
TaggedIndex::Bend(self.bend2), TaggedIndex::Bend(self.bend),
TaggedIndex::Dot(self.bend2_dot2), TaggedIndex::Dot(self.seg2_dot1),
TaggedIndex::Seg(self.seg2), TaggedIndex::Seg(self.seg2),
TaggedIndex::Dot(self.seg2_dot2),
TaggedIndex::Dot(self.bend3_dot1),
TaggedIndex::Bend(self.bend3),
TaggedIndex::Dot(self.bend3_dot2),
] ]
} }
fn boundary(&self) -> Vec<DotIndex> { fn ends(&self) -> [DotIndex; 2] {
vec![ [self.seg1_dot1, self.seg2_dot2]
self.bend1_dot1,
self.bend3_dot2,
]
} }
} }

View File

@ -1,2 +0,0 @@
use enum_as_inner::EnumAsInner;
use crate::math::Circle;