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::{
graph::{
BendIndex, DotIndex, FixedDotIndex, FixedSegWeight, GetNet, Index, LooseBendIndex,
BendIndex, DotIndex, FixedDotIndex, FixedSegWeight, GetEnds, GetNet, Index, LooseBendIndex,
LooseBendWeight, LooseDotIndex, LooseDotWeight, LooseSegWeight, MakePrimitive,
},
guide::Guide,
layout::Layout,
math::Circle,
primitive::GetOtherEnd,
primitive::{GetOtherEnd, GetWeight},
rules::{Conditions, Rules},
segbend::Segbend,
};
@ -258,6 +258,22 @@ impl<'a> Draw<'a> {
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 {
match dot {
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 {
Guide::new(self.layout, self.rules, conditions)
}

View File

@ -5,7 +5,7 @@ use crate::{
graph::{BendIndex, DotIndex, FixedDotIndex, MakePrimitive},
layout::Layout,
math::{self, Circle},
primitive::{GetCore, GetWeight, MakeShape},
primitive::{GetCore, GetInnerOuter, GetWeight, MakeShape},
rules::{Conditions, Rules},
shape::ShapeTrait,
};
@ -133,15 +133,15 @@ impl<'a, 'b> Guide<'a, 'b> {
}
}
fn bend_circle(&self, bend: BendIndex, _width: f64) -> Circle {
let mut circle = bend
.primitive(&self.layout.graph)
.shape()
.into_bend()
.unwrap()
.circle();
circle.r += self.rules.ruleset(&self.conditions).clearance.min;
circle
fn bend_circle(&self, bend: BendIndex, width: f64) -> Circle {
let shape = bend.primitive(&self.layout.graph).shape();
Circle {
pos: shape.center(),
r: shape.width() / 2.0
+ width
+ 6.0
+ self.rules.ruleset(self.conditions).clearance.min,
}
}
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.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.edge_count() == old(self.graph.edge_count()))]
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.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.edge_count() == old(self.graph.edge_count()))]
fn add_loose_bend(
&mut self,
from: LooseDotIndex,
@ -220,6 +222,7 @@ impl Layout {
match around {
Index::FixedDot(core) => self.add_core_bend(from, to, core, weight),
Index::FixedBend(around) => self.add_outer_bend(from, to, around, weight),
Index::LooseBend(around) => self.add_outer_bend(from, to, around, weight),
_ => unreachable!(),
}
}
@ -293,10 +296,14 @@ impl Layout {
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.edge_count() == old(self.graph.edge_count())
|| 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());
if let Some(old_inner_edge) = self

View File

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

View File

@ -60,6 +60,7 @@ pub trait GetFirstLayer: GetGraph + GetNodeIndex {
fn first_layer(&self) -> Option<LooseBendIndex> {
self.graph()
.neighbors_directed(self.node_index(), Incoming)
.filter(|ni| self.graph().find_edge(self.node_index(), *ni).is_some())
.filter(|ni| {
self.graph()
.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> {
self.graph()
.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>;
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 {
let mut r = 0.0;
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
todo!();
}
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> GetFirstLayer for FixedBend<'a> {}
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>;
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 {
let mut r = 0.0;
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> 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::Seg(other) => self.polygon().intersects(&other.polygon()),
Shape::Bend(other) => {
for segment in self.polygon().exterior().lines() {
/*for segment in self.polygon().exterior().lines() {
let inner_circle = other.inner_circle();
let outer_circle = other.outer_circle();
@ -132,7 +132,7 @@ impl ShapeTrait for SegShape {
return true;
}
}
}
}*/
false
}

View File

@ -2,9 +2,10 @@ use contracts::debug_ensures;
use crate::{
draw::{BareHead, Draw, Head, SegbendHead},
graph::FixedDotIndex,
graph::{FixedDotIndex, LooseBendIndex},
layout::Layout,
mesh::{Mesh, VertexIndex},
primitive::{GetFirstLayer, GetInnerOuter},
rules::Rules,
};
@ -88,35 +89,12 @@ impl<'a> Tracer<'a> {
}
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 {
VertexIndex::FixedDot(dot) => self.wrap_around_fixed_dot(head, dot, width),
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,
width: f64,
) -> Result<SegbendHead, ()> {
self.draw().segbend_around_dot(head, around.into(), width)
let head = self.draw().segbend_around_dot(head, around.into(), width)?;
if let Some(first_layer) = self.layout.primitive(around).first_layer() {
self.layout.reattach_bend(first_layer, head.segbend.bend);
self.update_outward(head.segbend.bend);
}
/*fn is_under(
&mut self,
_head: Head,
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)
}
fn tuck_around_bend(
fn wrap_around_loose_bend(
&mut self,
head: Head,
around: FixedBendIndex,
around: LooseBendIndex,
width: f64,
) -> Result<SegbendHead, ()> {
let outer = self.layout.primitive(around).outer().unwrap();
let maybe_outer = self.layout.primitive(around).outer();
let head = self
.draw()
.segbend_around_bend(Head::from(head), around.into(), width)?;
self.layout.reattach_bend(outer, head.segbend.bend);
.segbend_around_bend(head, around.into(), width)?;
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)
}
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 cur_bend = bend;

View File

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