tracer: Implement rudimentary wrapping around loose bends

Temporarily disabled bend-seg intersection to make it rudimentarily
work.
This commit is contained in:
Mikolaj Wielgus 2023-11-15 02:52:37 +00:00
parent 60c494a171
commit 36710b7a51
8 changed files with 99 additions and 143 deletions

View File

@ -4,13 +4,13 @@ use geo::{EuclideanLength, Point};
use crate::{ use crate::{
graph::{ graph::{
BendIndex, DotIndex, FixedDotIndex, FixedSegWeight, GetNet, Index, LooseBendIndex, BendIndex, DotIndex, FixedDotIndex, FixedSegWeight, GetEnds, GetNet, Index, LooseBendIndex,
LooseBendWeight, LooseDotIndex, LooseDotWeight, LooseSegWeight, MakePrimitive, LooseBendWeight, LooseDotIndex, LooseDotWeight, LooseSegWeight, MakePrimitive,
}, },
guide::Guide, guide::Guide,
layout::Layout, layout::Layout,
math::Circle, math::Circle,
primitive::GetOtherEnd, primitive::{GetOtherEnd, GetWeight},
rules::{Conditions, Rules}, rules::{Conditions, Rules},
segbend::Segbend, segbend::Segbend,
}; };
@ -258,6 +258,22 @@ impl<'a> Draw<'a> {
Some(self.head(prev_dot)) Some(self.head(prev_dot))
} }
#[debug_ensures(self.layout.node_count() == old(self.layout.node_count()))]
pub fn update_bow(&mut self, bend: LooseBendIndex) {
/*let cw = self.layout.primitive(bend).weight().cw;
let ends = self.layout.primitive(bend).ends();
let from_head = self.rear_head(ends.0);
let to_head = self.rear_head(ends.1);
let from = self
.guide(&Default::default())
.head_around_bend_segment(&from_head, inner, cw, 3.0);
let to = self
.guide(&Default::default())
.head_around_bend_segment(&from_head, inner, cw, 3.0);
self.layout.reposition_bend(bend, from, to);*/
}
fn head(&self, dot: DotIndex) -> Head { fn head(&self, dot: DotIndex) -> Head {
match dot { match dot {
DotIndex::Fixed(loose) => BareHead { dot: loose }.into(), DotIndex::Fixed(loose) => BareHead { dot: loose }.into(),
@ -272,6 +288,16 @@ impl<'a> Draw<'a> {
} }
} }
fn rear_head(&self, dot: LooseDotIndex) -> Head {
self.head(self.rear(self.segbend_head(dot)))
}
fn rear(&self, head: SegbendHead) -> DotIndex {
self.layout
.primitive(head.segbend.seg)
.other_end(head.segbend.dot.into())
}
fn guide(&'a self, conditions: &'a Conditions) -> Guide { fn guide(&'a self, conditions: &'a Conditions) -> Guide {
Guide::new(self.layout, self.rules, conditions) Guide::new(self.layout, self.rules, conditions)
} }

View File

@ -5,7 +5,7 @@ use crate::{
graph::{BendIndex, DotIndex, FixedDotIndex, MakePrimitive}, graph::{BendIndex, DotIndex, FixedDotIndex, MakePrimitive},
layout::Layout, layout::Layout,
math::{self, Circle}, math::{self, Circle},
primitive::{GetCore, GetWeight, MakeShape}, primitive::{GetCore, GetInnerOuter, GetWeight, MakeShape},
rules::{Conditions, Rules}, rules::{Conditions, Rules},
shape::ShapeTrait, shape::ShapeTrait,
}; };
@ -133,15 +133,15 @@ impl<'a, 'b> Guide<'a, 'b> {
} }
} }
fn bend_circle(&self, bend: BendIndex, _width: f64) -> Circle { fn bend_circle(&self, bend: BendIndex, width: f64) -> Circle {
let mut circle = bend let shape = bend.primitive(&self.layout.graph).shape();
.primitive(&self.layout.graph) Circle {
.shape() pos: shape.center(),
.into_bend() r: shape.width() / 2.0
.unwrap() + width
.circle(); + 6.0
circle.r += self.rules.ruleset(&self.conditions).clearance.min; + self.rules.ruleset(self.conditions).clearance.min,
circle }
} }
fn dot_circle(&self, dot: DotIndex, width: f64) -> Circle { fn dot_circle(&self, dot: DotIndex, width: f64) -> Circle {

View File

@ -107,7 +107,7 @@ impl Layout {
} }
#[debug_ensures(ret.is_ok() -> self.graph.node_count() == old(self.graph.node_count() + 4))] #[debug_ensures(ret.is_ok() -> self.graph.node_count() == old(self.graph.node_count() + 4))]
#[debug_ensures(ret.is_ok() -> self.graph.edge_count() == old(self.graph.edge_count() + 5))] #[debug_ensures(ret.is_ok() -> self.graph.edge_count() >= old(self.graph.edge_count() + 5))]
#[debug_ensures(ret.is_err() -> self.graph.node_count() == old(self.graph.node_count()))] #[debug_ensures(ret.is_err() -> self.graph.node_count() == old(self.graph.node_count()))]
#[debug_ensures(ret.is_err() -> self.graph.edge_count() == old(self.graph.edge_count()))] #[debug_ensures(ret.is_err() -> self.graph.edge_count() == old(self.graph.edge_count()))]
pub fn add_segbend( pub fn add_segbend(
@ -209,7 +209,9 @@ impl Layout {
}*/ }*/
#[debug_ensures(ret.is_ok() -> self.graph.node_count() == old(self.graph.node_count() + 1))] #[debug_ensures(ret.is_ok() -> self.graph.node_count() == old(self.graph.node_count() + 1))]
#[debug_ensures(ret.is_ok() -> self.graph.edge_count() == old(self.graph.edge_count() + 3) || self.graph.edge_count() == old(self.graph.edge_count() + 4))]
#[debug_ensures(ret.is_err() -> self.graph.node_count() == old(self.graph.node_count()))] #[debug_ensures(ret.is_err() -> self.graph.node_count() == old(self.graph.node_count()))]
#[debug_ensures(ret.is_err() -> self.graph.edge_count() == old(self.graph.edge_count()))]
fn add_loose_bend( fn add_loose_bend(
&mut self, &mut self,
from: LooseDotIndex, from: LooseDotIndex,
@ -220,6 +222,7 @@ impl Layout {
match around { match around {
Index::FixedDot(core) => self.add_core_bend(from, to, core, weight), Index::FixedDot(core) => self.add_core_bend(from, to, core, weight),
Index::FixedBend(around) => self.add_outer_bend(from, to, around, weight), Index::FixedBend(around) => self.add_outer_bend(from, to, around, weight),
Index::LooseBend(around) => self.add_outer_bend(from, to, around, weight),
_ => unreachable!(), _ => unreachable!(),
} }
} }
@ -293,10 +296,14 @@ impl Layout {
Ok(bend) Ok(bend)
} }
pub fn reposition_bend(&mut self, bend: LooseBendIndex, from: Point, to: Point) {
// TODO.
}
#[debug_ensures(self.graph.node_count() == old(self.graph.node_count()))] #[debug_ensures(self.graph.node_count() == old(self.graph.node_count()))]
#[debug_ensures(self.graph.edge_count() == old(self.graph.edge_count()) #[debug_ensures(self.graph.edge_count() == old(self.graph.edge_count())
|| self.graph.edge_count() == old(self.graph.edge_count() + 1))] || self.graph.edge_count() == old(self.graph.edge_count() + 1))]
pub fn reattach_bend(&mut self, bend: FixedBendIndex, inner: FixedBendIndex) { pub fn reattach_bend(&mut self, bend: LooseBendIndex, inner: LooseBendIndex) {
self.remove_from_rtree(bend.into()); self.remove_from_rtree(bend.into());
if let Some(old_inner_edge) = self if let Some(old_inner_edge) = self

View File

@ -148,7 +148,7 @@ fn main() {
let dot2 = router let dot2 = router
.layout .layout
.add_fixed_dot(FixedDotWeight { .add_fixed_dot(FixedDotWeight {
net: 1, net: 5,
circle: Circle { circle: Circle {
pos: (100.5, 500.5).into(), pos: (100.5, 500.5).into(),
r: 8.0, r: 8.0,
@ -170,7 +170,7 @@ fn main() {
let dot_end2 = router let dot_end2 = router
.layout .layout
.add_fixed_dot(FixedDotWeight { .add_fixed_dot(FixedDotWeight {
net: 1, net: 5,
circle: Circle { circle: Circle {
pos: (500.5, 150.5).into(), pos: (500.5, 150.5).into(),
r: 8.0, r: 8.0,

View File

@ -60,6 +60,7 @@ pub trait GetFirstLayer: GetGraph + GetNodeIndex {
fn first_layer(&self) -> Option<LooseBendIndex> { fn first_layer(&self) -> Option<LooseBendIndex> {
self.graph() self.graph()
.neighbors_directed(self.node_index(), Incoming) .neighbors_directed(self.node_index(), Incoming)
.filter(|ni| self.graph().find_edge(self.node_index(), *ni).is_some())
.filter(|ni| { .filter(|ni| {
self.graph() self.graph()
.edge_weight(self.graph().find_edge(self.node_index(), *ni).unwrap()) .edge_weight(self.graph().find_edge(self.node_index(), *ni).unwrap())
@ -87,7 +88,20 @@ pub trait GetCore: GetGraph + GetNodeIndex {
} }
} }
pub trait GetOuter: GetGraph + GetNodeIndex { pub trait GetInnerOuter: GetGraph + GetNodeIndex {
fn inner(&self) -> Option<LooseBendIndex> {
self.graph()
.neighbors_directed(self.node_index(), Incoming)
.filter(|ni| {
self.graph()
.edge_weight(self.graph().find_edge(*ni, self.node_index()).unwrap())
.unwrap()
.is_outer()
})
.map(|ni| LooseBendIndex::new(ni))
.next()
}
fn outer(&self) -> Option<LooseBendIndex> { fn outer(&self) -> Option<LooseBendIndex> {
self.graph() self.graph()
.neighbors_directed(self.node_index(), Outgoing) .neighbors_directed(self.node_index(), Outgoing)
@ -340,45 +354,8 @@ impl<'a> GetOtherEnd<DotIndex, LooseDotIndex> for LooseSeg<'a> {}
pub type FixedBend<'a> = GenericPrimitive<'a, FixedBendWeight>; pub type FixedBend<'a> = GenericPrimitive<'a, FixedBendWeight>;
impl<'a> FixedBend<'a> { impl<'a> FixedBend<'a> {
pub fn around(&self) -> Index {
if let Some(inner) = self.inner() {
inner.into()
} else {
self.core().into()
}
}
pub fn inner(&self) -> Option<FixedBendIndex> {
self.graph
.neighbors_directed(self.index.node_index(), Incoming)
.filter(|ni| {
self.graph
.edge_weight(self.graph.find_edge(*ni, self.index.node_index()).unwrap())
.unwrap()
.is_outer()
})
.map(|ni| FixedBendIndex::new(ni))
.next()
}
fn inner_radius(&self) -> f64 { fn inner_radius(&self) -> f64 {
let mut r = 0.0; todo!();
let mut layer = FixedBendIndex::new(self.index.node_index());
while let Some(inner) = self.primitive(layer).inner() {
r += self.primitive(inner).width();
layer = inner;
}
let core_circle = self
.primitive(
self.primitive(FixedBendIndex::new(self.index.node_index()))
.core(),
)
.weight()
.circle;
core_circle.r + r + 3.0
} }
pub fn cross_product(&self) -> f64 { pub fn cross_product(&self) -> f64 {
@ -428,24 +405,11 @@ impl<'a> GetOtherEnd<FixedDotIndex, FixedDotIndex> for FixedBend<'a> {}
impl<'a> TraverseOutward for FixedBend<'a> {} impl<'a> TraverseOutward for FixedBend<'a> {}
impl<'a> GetFirstLayer for FixedBend<'a> {} impl<'a> GetFirstLayer for FixedBend<'a> {}
impl<'a> GetCore for FixedBend<'a> {} // TODO: Fixed bends don't have cores actually. impl<'a> GetCore for FixedBend<'a> {} // TODO: Fixed bends don't have cores actually.
impl<'a> GetOuter for FixedBend<'a> {} //impl<'a> GetInnerOuter for FixedBend<'a> {}
pub type LooseBend<'a> = GenericPrimitive<'a, LooseBendWeight>; pub type LooseBend<'a> = GenericPrimitive<'a, LooseBendWeight>;
impl<'a> LooseBend<'a> { impl<'a> LooseBend<'a> {
pub fn inner(&self) -> Option<LooseBendIndex> {
self.graph
.neighbors_directed(self.index.node_index(), Incoming)
.filter(|ni| {
self.graph
.edge_weight(self.graph.find_edge(*ni, self.index.node_index()).unwrap())
.unwrap()
.is_outer()
})
.map(|ni| LooseBendIndex::new(ni))
.next()
}
fn inner_radius(&self) -> f64 { fn inner_radius(&self) -> f64 {
let mut r = 0.0; let mut r = 0.0;
let mut layer = LooseBendIndex::new(self.index.node_index()); let mut layer = LooseBendIndex::new(self.index.node_index());
@ -509,4 +473,4 @@ impl<'a> GetEnds<LooseDotIndex, LooseDotIndex> for LooseBend<'a> {
impl<'a> GetOtherEnd<LooseDotIndex, LooseDotIndex> for LooseBend<'a> {} impl<'a> GetOtherEnd<LooseDotIndex, LooseDotIndex> for LooseBend<'a> {}
impl<'a> GetCore for LooseBend<'a> {} impl<'a> GetCore for LooseBend<'a> {}
impl<'a> GetOuter for LooseBend<'a> {} impl<'a> GetInnerOuter for LooseBend<'a> {}

View File

@ -117,7 +117,7 @@ impl ShapeTrait for SegShape {
Shape::Dot(..) => unreachable!(), Shape::Dot(..) => unreachable!(),
Shape::Seg(other) => self.polygon().intersects(&other.polygon()), Shape::Seg(other) => self.polygon().intersects(&other.polygon()),
Shape::Bend(other) => { Shape::Bend(other) => {
for segment in self.polygon().exterior().lines() { /*for segment in self.polygon().exterior().lines() {
let inner_circle = other.inner_circle(); let inner_circle = other.inner_circle();
let outer_circle = other.outer_circle(); let outer_circle = other.outer_circle();
@ -132,7 +132,7 @@ impl ShapeTrait for SegShape {
return true; return true;
} }
} }
} }*/
false false
} }

View File

@ -2,9 +2,10 @@ use contracts::debug_ensures;
use crate::{ use crate::{
draw::{BareHead, Draw, Head, SegbendHead}, draw::{BareHead, Draw, Head, SegbendHead},
graph::FixedDotIndex, graph::{FixedDotIndex, LooseBendIndex},
layout::Layout, layout::Layout,
mesh::{Mesh, VertexIndex}, mesh::{Mesh, VertexIndex},
primitive::{GetFirstLayer, GetInnerOuter},
rules::Rules, rules::Rules,
}; };
@ -88,35 +89,12 @@ impl<'a> Tracer<'a> {
} }
fn wrap(&mut self, head: Head, around: VertexIndex, width: f64) -> Result<SegbendHead, ()> { fn wrap(&mut self, head: Head, around: VertexIndex, width: f64) -> Result<SegbendHead, ()> {
/*let _around_pos = self.layout.primitive(around).weight().circle.pos;
let _around_primitive = self.layout.primitive(around);
'blk: {
if let Some(mut layer) = self.layout.primitive(around).outer() {
match self.is_under(head, around, layer) {
Some(true) => return self.tuck_around_dot(head, around, width),
Some(false) => (),
None => break 'blk,
}
while let Some(outer) = self.layout.primitive(layer).outer() {
match self.is_under(head, around, outer) {
Some(true) => return self.tuck_around_bend(head, layer, width),
Some(false) => (),
None => break 'blk,
}
layer = outer;
}
return self.draw().segbend_around_bend(head, layer.into(), width);
}
}*/
match around { match around {
VertexIndex::FixedDot(dot) => self.wrap_around_fixed_dot(head, dot, width), VertexIndex::FixedDot(dot) => self.wrap_around_fixed_dot(head, dot, width),
VertexIndex::FixedBend(_fixed_bend) => todo!(), VertexIndex::FixedBend(_fixed_bend) => todo!(),
VertexIndex::LooseBend(_loose_bend) => todo!(), VertexIndex::LooseBend(loose_bend) => {
self.wrap_around_loose_bend(head, loose_bend, width)
}
} }
} }
@ -126,64 +104,45 @@ impl<'a> Tracer<'a> {
around: FixedDotIndex, around: FixedDotIndex,
width: f64, width: f64,
) -> Result<SegbendHead, ()> { ) -> Result<SegbendHead, ()> {
self.draw().segbend_around_dot(head, around.into(), width) let head = self.draw().segbend_around_dot(head, around.into(), width)?;
}
/*fn is_under( if let Some(first_layer) = self.layout.primitive(around).first_layer() {
&mut self, self.layout.reattach_bend(first_layer, head.segbend.bend);
_head: Head, self.update_outward(head.segbend.bend);
around: FixedDotIndex, }
_layer: FixedBendIndex,
) -> Option<bool> {
let _around_pos = self.layout.primitive(around).weight().circle.pos;
/*if Some(layer) != self.layout.primitive(head.dot()).prev_bend() {
Some(
self.layout
.primitive(layer)
.shape()
.into_bend()
.unwrap()
.between_ends(around_pos),
)
} else {*/
None
//}
}*/
/*fn tuck_around_dot(
&mut self,
head: Head,
around: FixedDotIndex,
width: f64,
) -> Result<SegbendHead, ()> {
let outer = self.layout.primitive(around).outer().unwrap();
let head = self
.draw()
.segbend_around_dot(Head::from(head), around.into(), width)?;
self.layout.reattach_bend(outer, head.segbend.bend);
self.redraw_outward(outer)?;
Ok(head) Ok(head)
} }
fn tuck_around_bend( fn wrap_around_loose_bend(
&mut self, &mut self,
head: Head, head: Head,
around: FixedBendIndex, around: LooseBendIndex,
width: f64, width: f64,
) -> Result<SegbendHead, ()> { ) -> Result<SegbendHead, ()> {
let outer = self.layout.primitive(around).outer().unwrap(); let maybe_outer = self.layout.primitive(around).outer();
let head = self let head = self
.draw() .draw()
.segbend_around_bend(Head::from(head), around.into(), width)?; .segbend_around_bend(head, around.into(), width)?;
self.layout.reattach_bend(outer, head.segbend.bend);
if let Some(outer) = maybe_outer {
self.layout.reattach_bend(outer, head.segbend.bend);
self.update_outward(head.segbend.bend);
}
self.redraw_outward(outer)?;
Ok(head) Ok(head)
} }
fn redraw_outward(&mut self, bend: FixedBendIndex) -> Result<(), ()> { fn update_outward(&mut self, bend: LooseBendIndex) {
let mut layer = bend;
while let Some(outer) = self.layout.primitive(layer).outer() {
self.draw().update_bow(bend);
layer = outer;
}
}
/*fn redraw_outward(&mut self, bend: FixedBendIndex) -> Result<(), ()> {
let mut bows: Vec<Bow> = vec![]; let mut bows: Vec<Bow> = vec![];
let mut cur_bend = bend; let mut cur_bend = bend;

View File

@ -2,7 +2,7 @@ use petgraph::stable_graph::StableDiGraph;
use crate::{ use crate::{
graph::{Label, LooseBendIndex, Weight}, graph::{Label, LooseBendIndex, Weight},
primitive::{GenericPrimitive, GetOuter}, primitive::{GenericPrimitive, GetInnerOuter},
}; };
pub struct OutwardLayerTraverser<'a> { pub struct OutwardLayerTraverser<'a> {