Introduce `Segbend`, a seg-dot-bend triple

This commit is contained in:
Mikolaj Wielgus 2023-08-29 01:49:37 +02:00
parent 79a26cb324
commit 47aadfcdd3
7 changed files with 156 additions and 73 deletions

View File

@ -16,7 +16,7 @@ pub struct Bow {
} }
impl Bow { impl Bow {
pub fn new(index: BendIndex, graph: &StableDiGraph<TaggedWeight, Label, usize>) -> Self { pub fn from_bend(index: BendIndex, graph: &StableDiGraph<TaggedWeight, Label, usize>) -> Self {
let bend = index; let bend = index;
let seg1_dot2 = Bend::new(bend, graph).prev().unwrap(); let seg1_dot2 = Bend::new(bend, graph).prev().unwrap();

View File

@ -63,15 +63,13 @@ impl<'a, 'b> Guide<'a, 'b> {
} }
pub fn head_cw(&self, head: &Head) -> Option<bool> { pub fn head_cw(&self, head: &Head) -> Option<bool> {
match head.bend { match &head.segbend {
Some(bend) => Some(self.layout.primitive(bend).weight().cw), Some(segbend) => Some(self.layout.primitive(segbend.bend).weight().cw),
None => None, None => None,
} }
} }
fn head_circle(&self, head: &Head, width: f64) -> Circle { fn head_circle(&self, head: &Head, width: f64) -> Circle {
let maybe_bend = head.bend;
let conditions = Conditions { let conditions = Conditions {
lower_net: None, lower_net: None,
higher_net: None, higher_net: None,
@ -79,12 +77,12 @@ impl<'a, 'b> Guide<'a, 'b> {
zone: None, zone: None,
}; };
match maybe_bend { match &head.segbend {
Some(bend) => { Some(segbend) => {
if let Some(inner) = self.layout.primitive(bend).inner() { if let Some(inner) = self.layout.primitive(segbend.bend).inner() {
self.bend_circle(inner, width) self.bend_circle(inner, width)
} else { } else {
self.dot_circle(self.layout.primitive(bend).core().unwrap(), width) self.dot_circle(self.layout.primitive(segbend.bend).core().unwrap(), width)
} }
} }
None => Circle { None => Circle {

View File

@ -12,6 +12,7 @@ use crate::graph::{
TaggedIndex, TaggedWeight, TaggedIndex, TaggedWeight,
}; };
use crate::primitive::Primitive; use crate::primitive::Primitive;
use crate::segbend::Segbend;
use crate::shape::Shape; use crate::shape::Shape;
pub type RTreeWrapper = GeomWithData<Shape, TaggedIndex>; pub type RTreeWrapper = GeomWithData<Shape, TaggedIndex>;
@ -215,7 +216,15 @@ impl Layout {
} }
pub fn bow(&self, bend: BendIndex) -> Bow { pub fn bow(&self, bend: BendIndex) -> Bow {
Bow::new(bend, &self.graph) Bow::from_bend(bend, &self.graph)
}
pub fn prev_segbend(&self, dot: DotIndex) -> Option<Segbend> {
Segbend::from_dot_prev(dot, &self.graph)
}
pub fn next_segbend(&self, dot: DotIndex) -> Option<Segbend> {
Segbend::from_dot_next(dot, &self.graph)
} }
fn fail_and_remove_if_collides_except<Weight: std::marker::Copy>( fn fail_and_remove_if_collides_except<Weight: std::marker::Copy>(

View File

@ -18,6 +18,7 @@ mod mesh;
mod primitive; mod primitive;
mod router; mod router;
mod rules; mod rules;
mod segbend;
mod shape; mod shape;
use geo::EuclideanDistance; use geo::EuclideanDistance;

View File

@ -80,50 +80,6 @@ impl<'a, Weight> Primitive<'a, Weight> {
.map(|index| Index::<Label>::new(index).retag(self.graph.node_weight(index).unwrap())) .map(|index| Index::<Label>::new(index).retag(self.graph.node_weight(index).unwrap()))
} }
pub fn find_next_akin(&self) -> Option<Index<Weight>> {
let mut prev_index = self.index.index;
while let Some(index) = self
.graph
.neighbors_directed(prev_index, Outgoing)
.filter(|ni| self.graph.find_edge(prev_index, *ni).is_some())
.filter(|ni| {
self.graph
.edge_weight(self.graph.find_edge(prev_index, *ni).unwrap())
.unwrap()
.is_end()
})
.next()
{
let weight = *self.graph.node_weight(index).unwrap();
if mem::discriminant(&self.tagged_weight()) == mem::discriminant(&weight) {
return Some(Index::<Weight>::new(index));
}
prev_index = index;
}
None
}
pub fn tagged_next(&self) -> Option<TaggedIndex> {
self.next_node()
.map(|ni| Index::<Label>::new(ni).retag(self.graph.node_weight(ni).unwrap()))
}
fn next_node(&self) -> Option<NodeIndex<usize>> {
self.graph
.neighbors_directed(self.index.index, Outgoing)
.filter(|ni| {
self.graph
.edge_weight(self.graph.find_edge(self.index.index, *ni).unwrap())
.unwrap()
.is_end()
})
.next()
}
pub fn find_prev_akin(&self) -> Option<Index<Weight>> { pub fn find_prev_akin(&self) -> Option<Index<Weight>> {
let mut prev_index = self.index.index; let mut prev_index = self.index.index;
@ -168,6 +124,50 @@ impl<'a, Weight> Primitive<'a, Weight> {
.next() .next()
} }
pub fn find_next_akin(&self) -> Option<Index<Weight>> {
let mut prev_index = self.index.index;
while let Some(index) = self
.graph
.neighbors_directed(prev_index, Outgoing)
.filter(|ni| self.graph.find_edge(prev_index, *ni).is_some())
.filter(|ni| {
self.graph
.edge_weight(self.graph.find_edge(prev_index, *ni).unwrap())
.unwrap()
.is_end()
})
.next()
{
let weight = *self.graph.node_weight(index).unwrap();
if mem::discriminant(&self.tagged_weight()) == mem::discriminant(&weight) {
return Some(Index::<Weight>::new(index));
}
prev_index = index;
}
None
}
pub fn tagged_next(&self) -> Option<TaggedIndex> {
self.next_node()
.map(|ni| Index::<Label>::new(ni).retag(self.graph.node_weight(ni).unwrap()))
}
fn next_node(&self) -> Option<NodeIndex<usize>> {
self.graph
.neighbors_directed(self.index.index, Outgoing)
.filter(|ni| {
self.graph
.edge_weight(self.graph.find_edge(self.index.index, *ni).unwrap())
.unwrap()
.is_end()
})
.next()
}
pub fn core(&self) -> Option<DotIndex> { pub fn core(&self) -> Option<DotIndex> {
self.graph self.graph
.neighbors(self.index.index) .neighbors(self.index.index)

View File

@ -13,6 +13,7 @@ use crate::math;
use crate::math::Circle; use crate::math::Circle;
use crate::mesh::{Mesh, VertexIndex}; use crate::mesh::{Mesh, VertexIndex};
use crate::rules::{Conditions, Rules}; use crate::rules::{Conditions, Rules};
use crate::segbend::Segbend;
use crate::shape::Shape; use crate::shape::Shape;
pub struct Router { pub struct Router {
@ -29,7 +30,7 @@ struct Route {
pub struct Head { pub struct Head {
pub dot: DotIndex, pub dot: DotIndex,
pub bend: Option<BendIndex>, pub segbend: Option<Segbend>,
} }
impl Router { impl Router {
@ -97,7 +98,7 @@ impl Router {
pub fn draw_start(&mut self, from: DotIndex) -> Head { pub fn draw_start(&mut self, from: DotIndex) -> Head {
Head { Head {
dot: from, dot: from,
bend: self.layout.primitive(from).bend(), segbend: self.layout.prev_segbend(from),
} }
} }
@ -131,8 +132,8 @@ impl Router {
width: f64, width: f64,
) -> Result<(), ()> { ) -> Result<(), ()> {
let to_head = Head { let to_head = Head {
bend: Some(into_bend),
dot: into, dot: into,
segbend: self.layout.next_segbend(into),
}; };
let to_cw = self.guide(&Default::default()).head_cw(&to_head).unwrap(); let to_cw = self.guide(&Default::default()).head_cw(&to_head).unwrap();
let tangent = self let tangent = self
@ -157,7 +158,8 @@ impl Router {
) -> Result<Head, ()> { ) -> Result<Head, ()> {
let outer = self.layout.primitive(around).outer().unwrap(); let outer = self.layout.primitive(around).outer().unwrap();
let head = self.draw_around_dot(head, around, cw, width)?; let head = self.draw_around_dot(head, around, cw, width)?;
self.layout.reattach_bend(outer, head.bend.unwrap()); self.layout
.reattach_bend(outer, head.segbend.as_ref().unwrap().bend);
self.reroute_outward(outer)?; self.reroute_outward(outer)?;
Ok(head) Ok(head)
@ -175,7 +177,7 @@ impl Router {
.head_around_dot_segment(&head, around, cw, width); .head_around_dot_segment(&head, around, cw, width);
let head = self.extend_head(head, tangent.start_point())?; let head = self.extend_head(head, tangent.start_point())?;
self.draw_seg_bend( self.draw_segbend(
head, head,
TaggedIndex::Dot(around), TaggedIndex::Dot(around),
tangent.end_point(), tangent.end_point(),
@ -193,7 +195,8 @@ impl Router {
) -> Result<Head, ()> { ) -> Result<Head, ()> {
let outer = self.layout.primitive(around).outer().unwrap(); let outer = self.layout.primitive(around).outer().unwrap();
let head = self.draw_around_bend(head, around, cw, width)?; let head = self.draw_around_bend(head, around, cw, width)?;
self.layout.reattach_bend(outer, head.bend.unwrap()); self.layout
.reattach_bend(outer, head.segbend.as_ref().unwrap().bend);
self.reroute_outward(outer)?; self.reroute_outward(outer)?;
Ok(head) Ok(head)
@ -211,7 +214,7 @@ impl Router {
.head_around_bend_segment(&head, around, cw, width); .head_around_bend_segment(&head, around, cw, width);
let head = self.extend_head(head, tangent.start_point())?; let head = self.extend_head(head, tangent.start_point())?;
self.draw_seg_bend( self.draw_segbend(
head, head,
TaggedIndex::Bend(around), TaggedIndex::Bend(around),
tangent.end_point(), tangent.end_point(),
@ -220,7 +223,7 @@ impl Router {
) )
} }
fn draw_seg_bend( fn draw_segbend(
&mut self, &mut self,
head: Head, head: Head,
around: TaggedIndex, around: TaggedIndex,
@ -228,7 +231,8 @@ impl Router {
cw: bool, cw: bool,
width: f64, width: f64,
) -> Result<Head, ()> { ) -> Result<Head, ()> {
let head = self.draw_seg(head, to, width)?; let (head, seg) = self.draw_seg(head, to, width)?;
let dot = head.dot;
let bend_to = self let bend_to = self
.layout .layout
.add_dot(self.layout.primitive(head.dot).weight())?; .add_dot(self.layout.primitive(head.dot).weight())?;
@ -239,7 +243,7 @@ impl Router {
.add_bend(head.dot, bend_to, around, BendWeight { net, cw })?; .add_bend(head.dot, bend_to, around, BendWeight { net, cw })?;
Ok(Head { Ok(Head {
dot: bend_to, dot: bend_to,
bend: Some(bend), segbend: Some(Segbend { bend, dot, seg }),
}) })
} }
@ -277,7 +281,7 @@ impl Router {
head = self.draw_around_dot(head, core, cw, width)?; head = self.draw_around_dot(head, core, cw, width)?;
} }
maybe_inner = head.bend; maybe_inner = head.segbend.as_ref().map(|segbend| segbend.bend);
self.draw_finish(head, ends.1, width)?; self.draw_finish(head, ends.1, width)?;
self.relax_band(maybe_inner.unwrap()); self.relax_band(maybe_inner.unwrap());
} }
@ -285,7 +289,7 @@ impl Router {
Ok(()) Ok(())
} }
fn draw_seg(&mut self, head: Head, to: Point, width: f64) -> Result<Head, ()> { fn draw_seg(&mut self, head: Head, to: Point, width: f64) -> Result<(Head, SegIndex), ()> {
let net = self.layout.primitive(head.dot).weight().net; let net = self.layout.primitive(head.dot).weight().net;
assert!(width <= self.layout.primitive(head.dot).weight().circle.r * 2.); assert!(width <= self.layout.primitive(head.dot).weight().circle.r * 2.);
@ -297,12 +301,16 @@ impl Router {
r: width / 2.0, r: width / 2.0,
}, },
})?; })?;
self.layout let seg = self
.layout
.add_seg(head.dot, to_index, SegWeight { net, width })?; .add_seg(head.dot, to_index, SegWeight { net, width })?;
Ok(Head { Ok((
Head {
dot: to_index, dot: to_index,
bend: None, segbend: None,
}) },
seg,
))
} }
fn relax_band(&mut self, bend: BendIndex) { fn relax_band(&mut self, bend: BendIndex) {
@ -346,7 +354,7 @@ impl Router {
} }
fn extend_head(&mut self, head: Head, to: Point) -> Result<Head, ()> { fn extend_head(&mut self, head: Head, to: Point) -> Result<Head, ()> {
if let Some(..) = head.bend { if let Some(..) = head.segbend {
self.extend_head_bend(head, to) self.extend_head_bend(head, to)
} else { } else {
Ok(head) Ok(head)
@ -358,7 +366,8 @@ impl Router {
} }
fn extend_head_bend(&mut self, head: Head, to: Point) -> Result<Head, ()> { fn extend_head_bend(&mut self, head: Head, to: Point) -> Result<Head, ()> {
self.layout.extend_bend(head.bend.unwrap(), head.dot, to)?; self.layout
.extend_bend(head.segbend.as_ref().unwrap().bend, head.dot, to)?;
Ok(head) Ok(head)
} }

66
src/segbend.rs Normal file
View File

@ -0,0 +1,66 @@
use petgraph::stable_graph::StableDiGraph;
use crate::{
graph::{BendIndex, DotIndex, Interior, Label, SegIndex, TaggedIndex, TaggedWeight},
primitive::{Bend, Dot},
};
pub struct Segbend {
pub seg: SegIndex,
pub dot: DotIndex,
pub bend: BendIndex,
}
impl Segbend {
pub fn new(bend: BendIndex, dot: DotIndex, seg: SegIndex) -> Self {
Self { seg, dot, bend }
}
pub fn from_dot_prev(
dot: DotIndex,
graph: &StableDiGraph<TaggedWeight, Label, usize>,
) -> Option<Self> {
if let Some(tagged_prev) = Dot::new(dot, graph).tagged_prev() {
let bend = *tagged_prev.as_bend().unwrap();
let dot = Bend::new(bend, graph).prev().unwrap();
let seg = *Dot::new(dot, graph)
.tagged_prev()
.unwrap()
.as_seg()
.unwrap();
Some(Self { bend, dot, seg })
} else {
None
}
}
pub fn from_dot_next(
dot: DotIndex,
graph: &StableDiGraph<TaggedWeight, Label, usize>,
) -> Option<Self> {
if let Some(tagged_prev) = Dot::new(dot, graph).tagged_next() {
let bend = *tagged_prev.as_bend().unwrap();
let dot = Bend::new(bend, graph).next().unwrap();
let seg = *Dot::new(dot, graph)
.tagged_next()
.unwrap()
.as_seg()
.unwrap();
Some(Self { bend, dot, seg })
} else {
None
}
}
}
impl Interior<TaggedIndex> for Segbend {
fn interior(&self) -> Vec<TaggedIndex> {
vec![
TaggedIndex::Bend(self.bend),
TaggedIndex::Dot(self.dot),
TaggedIndex::Seg(self.seg),
]
}
}