mirror of https://codeberg.org/topola/topola.git
Introduce `Segbend`, a seg-dot-bend triple
This commit is contained in:
parent
79a26cb324
commit
47aadfcdd3
|
|
@ -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();
|
||||||
|
|
|
||||||
14
src/guide.rs
14
src/guide.rs
|
|
@ -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 {
|
||||||
|
|
|
||||||
|
|
@ -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>(
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
|
|
|
||||||
|
|
@ -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)
|
||||||
|
|
|
||||||
|
|
@ -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((
|
||||||
dot: to_index,
|
Head {
|
||||||
bend: None,
|
dot: to_index,
|
||||||
})
|
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)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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),
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue