mirror of https://codeberg.org/topola/topola.git
tracer: Add some initial code for squeezing/tucking
Not functional yet.
This commit is contained in:
parent
ce72a2ba4b
commit
c9d0b2178e
69
src/draw.rs
69
src/draw.rs
|
|
@ -127,26 +127,21 @@ impl<'a> Draw<'a> {
|
|||
dirs = [false, true];
|
||||
}
|
||||
|
||||
for (i, tangent) in [tangents.0, tangents.1].iter().enumerate() {
|
||||
match self.segbend_around(
|
||||
head,
|
||||
TaggedIndex::Dot(around),
|
||||
tangent.start_point(),
|
||||
tangent.end_point(),
|
||||
dirs[i],
|
||||
width,
|
||||
) {
|
||||
Ok(head) => {
|
||||
return Ok(head);
|
||||
}
|
||||
Err(err) => {
|
||||
if i >= 1 {
|
||||
return Err(err);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
unreachable!();
|
||||
[tangents.0, tangents.1]
|
||||
.iter()
|
||||
.enumerate()
|
||||
.find_map(|(i, tangent)| {
|
||||
self.segbend_around(
|
||||
head,
|
||||
TaggedIndex::Dot(around),
|
||||
tangent.start_point(),
|
||||
tangent.end_point(),
|
||||
dirs[i],
|
||||
width,
|
||||
)
|
||||
.ok()
|
||||
})
|
||||
.ok_or(())
|
||||
}
|
||||
|
||||
#[debug_ensures(ret.is_ok() -> self.layout.node_count() == old(self.layout.node_count() + 4))]
|
||||
|
|
@ -155,21 +150,33 @@ impl<'a> Draw<'a> {
|
|||
&mut self,
|
||||
mut head: Head,
|
||||
around: BendIndex,
|
||||
cw: bool,
|
||||
width: f64,
|
||||
) -> Result<SegbendHead, ()> {
|
||||
let tangent = self
|
||||
let mut tangents = self
|
||||
.guide(&Default::default())
|
||||
.head_around_bend_segment(&head, around, cw, width);
|
||||
.head_around_bend_segments(&head, around, width);
|
||||
let mut dirs = [true, false];
|
||||
|
||||
head = self.extend_head(head, tangent.start_point())?;
|
||||
self.segbend(
|
||||
head,
|
||||
TaggedIndex::Bend(around),
|
||||
tangent.end_point(),
|
||||
cw,
|
||||
width,
|
||||
)
|
||||
if tangents.1.euclidean_length() < tangents.0.euclidean_length() {
|
||||
tangents = (tangents.1, tangents.0);
|
||||
dirs = [false, true];
|
||||
}
|
||||
|
||||
[tangents.0, tangents.1]
|
||||
.iter()
|
||||
.enumerate()
|
||||
.find_map(|(i, tangent)| {
|
||||
self.segbend_around(
|
||||
head,
|
||||
TaggedIndex::Bend(around),
|
||||
tangent.start_point(),
|
||||
tangent.end_point(),
|
||||
dirs[i],
|
||||
width,
|
||||
)
|
||||
.ok()
|
||||
})
|
||||
.ok_or(())
|
||||
}
|
||||
|
||||
#[debug_ensures(ret.is_ok() -> self.layout.node_count() == old(self.layout.node_count() + 4))]
|
||||
|
|
|
|||
43
src/guide.rs
43
src/guide.rs
|
|
@ -34,20 +34,6 @@ impl<'a, 'b> Guide<'a, 'b> {
|
|||
math::tangent_segment(from_circle, from_cw, to_circle, None)
|
||||
}
|
||||
|
||||
pub fn head_around_bend_segment(
|
||||
&self,
|
||||
head: &Head,
|
||||
around: BendIndex,
|
||||
cw: bool,
|
||||
width: f64,
|
||||
) -> Line {
|
||||
let from_circle = self.head_circle(head, width);
|
||||
let to_circle = self.bend_circle(around, width);
|
||||
|
||||
let from_cw = self.head_cw(head);
|
||||
math::tangent_segment(from_circle, from_cw, to_circle, Some(cw))
|
||||
}
|
||||
|
||||
pub fn head_around_dot_segments(
|
||||
&self,
|
||||
head: &Head,
|
||||
|
|
@ -77,6 +63,35 @@ impl<'a, 'b> Guide<'a, 'b> {
|
|||
math::tangent_segment(from_circle, from_cw, to_circle, Some(cw))
|
||||
}
|
||||
|
||||
pub fn head_around_bend_segments(
|
||||
&self,
|
||||
head: &Head,
|
||||
around: BendIndex,
|
||||
width: f64,
|
||||
) -> (Line, Line) {
|
||||
let from_circle = self.head_circle(head, width);
|
||||
let to_circle = self.bend_circle(around, width);
|
||||
|
||||
let from_cw = self.head_cw(head);
|
||||
let tangents: Vec<Line> =
|
||||
math::tangent_segments(from_circle, from_cw, to_circle, None).collect();
|
||||
(tangents[0], tangents[1])
|
||||
}
|
||||
|
||||
pub fn head_around_bend_segment(
|
||||
&self,
|
||||
head: &Head,
|
||||
around: BendIndex,
|
||||
cw: bool,
|
||||
width: f64,
|
||||
) -> Line {
|
||||
let from_circle = self.head_circle(head, width);
|
||||
let to_circle = self.bend_circle(around, width);
|
||||
|
||||
let from_cw = self.head_cw(head);
|
||||
math::tangent_segment(from_circle, from_cw, to_circle, Some(cw))
|
||||
}
|
||||
|
||||
pub fn head_cw(&self, head: &Head) -> Option<bool> {
|
||||
if let Head::Segbend(head) = head {
|
||||
Some(self.layout.primitive(head.segbend.bend).weight().cw)
|
||||
|
|
|
|||
114
src/main.rs
114
src/main.rs
|
|
@ -68,7 +68,7 @@ impl<'a> DebugRouterObserver<'a> {
|
|||
|
||||
impl<'a> RouterObserver for DebugRouterObserver<'a> {
|
||||
fn on_rework(&mut self, tracer: &Tracer, trace: &Trace) {
|
||||
render_times(
|
||||
/*render_times(
|
||||
self.event_pump,
|
||||
self.canvas,
|
||||
RouterOrLayout::Layout(tracer.layout),
|
||||
|
|
@ -77,13 +77,13 @@ impl<'a> RouterObserver for DebugRouterObserver<'a> {
|
|||
Some(tracer.mesh.clone()),
|
||||
&trace.path,
|
||||
20,
|
||||
);
|
||||
);*/
|
||||
}
|
||||
|
||||
fn before_probe(&mut self, tracer: &Tracer, trace: &Trace, edge: MeshEdgeReference) {
|
||||
let mut path = trace.path.clone();
|
||||
path.push(edge.target());
|
||||
render_times(
|
||||
/*render_times(
|
||||
self.event_pump,
|
||||
self.canvas,
|
||||
RouterOrLayout::Layout(tracer.layout),
|
||||
|
|
@ -92,11 +92,11 @@ impl<'a> RouterObserver for DebugRouterObserver<'a> {
|
|||
Some(tracer.mesh.clone()),
|
||||
&path,
|
||||
5,
|
||||
);
|
||||
);*/
|
||||
}
|
||||
|
||||
fn on_probe(&mut self, tracer: &Tracer, trace: &Trace, edge: MeshEdgeReference) {
|
||||
render_times(
|
||||
/*render_times(
|
||||
self.event_pump,
|
||||
self.canvas,
|
||||
RouterOrLayout::Layout(tracer.layout),
|
||||
|
|
@ -105,7 +105,7 @@ impl<'a> RouterObserver for DebugRouterObserver<'a> {
|
|||
Some(tracer.mesh.clone()),
|
||||
&trace.path,
|
||||
5,
|
||||
);
|
||||
);*/
|
||||
}
|
||||
|
||||
fn on_estimate(&mut self, _tracer: &Tracer, _vertex: VertexIndex) {}
|
||||
|
|
@ -145,7 +145,18 @@ fn main() {
|
|||
let dot2 = router
|
||||
.layout
|
||||
.add_dot(DotWeight {
|
||||
net: 1,
|
||||
net: 15,
|
||||
circle: Circle {
|
||||
pos: (100.5, 500.5).into(),
|
||||
r: 8.0,
|
||||
},
|
||||
})
|
||||
.unwrap();
|
||||
|
||||
let dot_end = router
|
||||
.layout
|
||||
.add_dot(DotWeight {
|
||||
net: 10,
|
||||
circle: Circle {
|
||||
pos: (470.5, 350.5).into(),
|
||||
r: 8.0,
|
||||
|
|
@ -284,16 +295,90 @@ fn main() {
|
|||
},
|
||||
);
|
||||
|
||||
let dot6 = router
|
||||
.layout
|
||||
.add_dot(DotWeight {
|
||||
net: 2,
|
||||
circle: Circle {
|
||||
pos: (530.5, 300.5).into(),
|
||||
r: 8.0,
|
||||
},
|
||||
})
|
||||
.unwrap();
|
||||
|
||||
let _ = router.layout.add_seg(
|
||||
dot5,
|
||||
dot6,
|
||||
SegWeight {
|
||||
net: 20,
|
||||
width: 16.0,
|
||||
},
|
||||
);
|
||||
|
||||
/*let dot7 = router
|
||||
.layout
|
||||
.add_dot(DotWeight {
|
||||
net: 2,
|
||||
circle: Circle {
|
||||
pos: (400.5, 440.5).into(),
|
||||
r: 8.0,
|
||||
},
|
||||
})
|
||||
.unwrap();
|
||||
|
||||
let _ = router.layout.add_seg(
|
||||
dot4,
|
||||
dot7,
|
||||
SegWeight {
|
||||
net: 20,
|
||||
width: 16.0,
|
||||
},
|
||||
);*/
|
||||
|
||||
render_times(
|
||||
&mut event_pump,
|
||||
&mut canvas,
|
||||
RouterOrLayout::Layout(&router.layout),
|
||||
None,
|
||||
None,
|
||||
None,
|
||||
&[],
|
||||
-1,
|
||||
);
|
||||
|
||||
render_times(
|
||||
&mut event_pump,
|
||||
&mut canvas,
|
||||
RouterOrLayout::Router(&mut router),
|
||||
Some(dot1),
|
||||
Some(dot2),
|
||||
Some(dot_end),
|
||||
None,
|
||||
&[],
|
||||
-1,
|
||||
);
|
||||
|
||||
render_times(
|
||||
&mut event_pump,
|
||||
&mut canvas,
|
||||
RouterOrLayout::Layout(&router.layout),
|
||||
None,
|
||||
None,
|
||||
None,
|
||||
&[],
|
||||
-1,
|
||||
);
|
||||
|
||||
render_times(
|
||||
&mut event_pump,
|
||||
&mut canvas,
|
||||
RouterOrLayout::Router(&mut router),
|
||||
Some(dot2),
|
||||
Some(dot_end),
|
||||
None,
|
||||
&[],
|
||||
-1,
|
||||
);
|
||||
|
||||
render_times(
|
||||
&mut event_pump,
|
||||
&mut canvas,
|
||||
|
|
@ -338,11 +423,6 @@ fn render_times(
|
|||
if let Some(follower) = follower {
|
||||
let state = event_pump.mouse_state();
|
||||
|
||||
/*let _ = router.layout.move_dot(
|
||||
follower.into_dot().unwrap(),
|
||||
(state.x() as f64, state.y() as f64).into(),
|
||||
);*/
|
||||
|
||||
if let Some(from) = from {
|
||||
mesh = router
|
||||
.reroute(
|
||||
|
|
@ -351,6 +431,10 @@ fn render_times(
|
|||
&mut DebugRouterObserver::new(event_pump, canvas),
|
||||
)
|
||||
.ok();
|
||||
} else {
|
||||
let _ = router
|
||||
.layout
|
||||
.move_dot(follower, (state.x() as f64, state.y() as f64).into());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -412,7 +496,7 @@ fn render_times(
|
|||
);*/
|
||||
}
|
||||
|
||||
if let Some(ref mesh) = mesh {
|
||||
/*if let Some(ref mesh) = mesh {
|
||||
for edge in mesh.edge_references() {
|
||||
let endpoints = (mesh.position(edge.source()), mesh.position(edge.target()));
|
||||
|
||||
|
|
@ -430,7 +514,7 @@ fn render_times(
|
|||
color,
|
||||
);
|
||||
}
|
||||
}
|
||||
}*/
|
||||
//});
|
||||
|
||||
canvas.present();
|
||||
|
|
|
|||
|
|
@ -153,7 +153,7 @@ pub fn intersect_circles(circle1: &Circle, circle2: &Circle) -> Vec<Point> {
|
|||
let p = circle1.pos + delta * (a / d);
|
||||
let h = (circle1.r * circle1.r - a * a).sqrt();
|
||||
|
||||
if h == 0. {
|
||||
if h == 0.0 {
|
||||
return [p].into();
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -71,7 +71,7 @@ impl<'a, Weight> Primitive<'a, Weight> {
|
|||
.weight()
|
||||
.circle;
|
||||
|
||||
core_circle.r + r + 5.0
|
||||
core_circle.r + r + 3.0
|
||||
}
|
||||
|
||||
pub fn neighbors(&self) -> impl Iterator<Item = TaggedIndex> + '_ {
|
||||
|
|
@ -80,13 +80,15 @@ impl<'a, Weight> Primitive<'a, Weight> {
|
|||
.map(|index| Index::<Label>::new(index).retag(self.graph.node_weight(index).unwrap()))
|
||||
}
|
||||
|
||||
pub fn find_prev_akin(&self) -> Option<Index<Weight>> {
|
||||
pub fn prev_bend(&self) -> Option<BendIndex> {
|
||||
let mut prev_index = self.index.index;
|
||||
|
||||
while let Some(index) = self
|
||||
.graph
|
||||
.neighbors_directed(prev_index, Incoming)
|
||||
// Ensure subsequent unwrap doesn't panic.
|
||||
.filter(|ni| self.graph.find_edge(*ni, prev_index).is_some())
|
||||
// Filter out non-End edges.
|
||||
.filter(|ni| {
|
||||
self.graph
|
||||
.edge_weight(self.graph.find_edge(*ni, prev_index).unwrap())
|
||||
|
|
@ -97,8 +99,8 @@ impl<'a, Weight> Primitive<'a, Weight> {
|
|||
{
|
||||
let weight = *self.graph.node_weight(index).unwrap();
|
||||
|
||||
if mem::discriminant(&self.tagged_weight()) == mem::discriminant(&weight) {
|
||||
return Some(Index::<Weight>::new(index));
|
||||
if let Some(TaggedWeight::Bend(..)) = self.graph.node_weight(index) {
|
||||
return Some(BendIndex::new(index));
|
||||
}
|
||||
|
||||
prev_index = index;
|
||||
|
|
@ -124,13 +126,15 @@ impl<'a, Weight> Primitive<'a, Weight> {
|
|||
.next()
|
||||
}
|
||||
|
||||
pub fn find_next_akin(&self) -> Option<Index<Weight>> {
|
||||
pub fn next_bend(&self) -> Option<BendIndex> {
|
||||
let mut prev_index = self.index.index;
|
||||
|
||||
while let Some(index) = self
|
||||
.graph
|
||||
.neighbors_directed(prev_index, Outgoing)
|
||||
// Ensure subsequent unwrap doesn't panic.
|
||||
.filter(|ni| self.graph.find_edge(prev_index, *ni).is_some())
|
||||
// Filter out non-End edges.
|
||||
.filter(|ni| {
|
||||
self.graph
|
||||
.edge_weight(self.graph.find_edge(prev_index, *ni).unwrap())
|
||||
|
|
@ -141,8 +145,8 @@ impl<'a, Weight> Primitive<'a, Weight> {
|
|||
{
|
||||
let weight = *self.graph.node_weight(index).unwrap();
|
||||
|
||||
if mem::discriminant(&self.tagged_weight()) == mem::discriminant(&weight) {
|
||||
return Some(Index::<Weight>::new(index));
|
||||
if let Some(TaggedWeight::Bend(..)) = self.graph.node_weight(index) {
|
||||
return Some(BendIndex::new(index));
|
||||
}
|
||||
|
||||
prev_index = index;
|
||||
|
|
|
|||
|
|
@ -60,7 +60,7 @@ impl BendShape {
|
|||
}
|
||||
}
|
||||
|
||||
fn between_ends(&self, point: Point) -> bool {
|
||||
pub fn between_ends(&self, point: Point) -> bool {
|
||||
math::between_vectors(
|
||||
point - self.c.pos,
|
||||
self.from - self.c.pos,
|
||||
|
|
@ -69,6 +69,7 @@ impl BendShape {
|
|||
}
|
||||
}
|
||||
|
||||
// TODO: Use enum_dispatch.
|
||||
#[derive(Debug, Clone, Copy, EnumAsInner, PartialEq)]
|
||||
pub enum Shape {
|
||||
// Intentionally in different order to reorder `self.intersects(...)` properly.
|
||||
|
|
|
|||
154
src/tracer.rs
154
src/tracer.rs
|
|
@ -1,7 +1,9 @@
|
|||
use contracts::debug_ensures;
|
||||
|
||||
use crate::{
|
||||
draw::{BareHead, Draw, Head},
|
||||
bow::Bow,
|
||||
draw::{BareHead, Draw, Head, HeadDot, SegbendHead},
|
||||
graph::{BendIndex, DotIndex, Ends},
|
||||
layout::Layout,
|
||||
mesh::{Mesh, MeshEdgeReference, VertexIndex},
|
||||
rules::Rules,
|
||||
|
|
@ -84,11 +86,159 @@ impl<'a> Tracer<'a> {
|
|||
#[debug_ensures(ret.is_err() -> trace.path.len() == old(trace.path.len()))]
|
||||
pub fn step(&mut self, trace: &mut Trace, to: VertexIndex, width: f64) -> Result<(), ()> {
|
||||
let to_dot = self.mesh.dot(to);
|
||||
trace.head = Head::from(self.draw().segbend_around_dot(trace.head, to_dot, width)?);
|
||||
trace.head = Head::from(self.wrap(trace.head, to_dot, width)?);
|
||||
|
||||
trace.path.push(to);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn wrap(&mut self, head: Head, around: DotIndex, 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.tuck_around_bend(head, layer, width);
|
||||
}
|
||||
}
|
||||
|
||||
self.draw().segbend_around_dot(head, around, width)
|
||||
}
|
||||
|
||||
fn is_under(&mut self, head: Head, around: DotIndex, layer: BendIndex) -> 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: DotIndex,
|
||||
width: f64,
|
||||
) -> Result<SegbendHead, ()> {
|
||||
let outer = self.layout.primitive(around).outer().unwrap();
|
||||
let head = self
|
||||
.draw()
|
||||
.segbend_around_dot(Head::from(head), around, width)?;
|
||||
self.layout.reattach_bend(outer, head.segbend.bend);
|
||||
|
||||
self.redraw_outward(outer)?;
|
||||
Ok(head)
|
||||
}
|
||||
|
||||
fn tuck_around_bend(
|
||||
&mut self,
|
||||
head: Head,
|
||||
around: BendIndex,
|
||||
width: f64,
|
||||
) -> Result<SegbendHead, ()> {
|
||||
let outer = self.layout.primitive(around).outer().unwrap();
|
||||
let head = self
|
||||
.draw()
|
||||
.segbend_around_bend(Head::from(head), around, width)?;
|
||||
self.layout.reattach_bend(outer, head.segbend.bend);
|
||||
|
||||
self.redraw_outward(outer)?;
|
||||
Ok(head)
|
||||
}
|
||||
|
||||
fn redraw_outward(&mut self, bend: BendIndex) -> Result<(), ()> {
|
||||
let mut bows: Vec<Bow> = vec![];
|
||||
|
||||
let mut cur_bend = bend;
|
||||
loop {
|
||||
bows.push(self.layout.bow(cur_bend));
|
||||
|
||||
cur_bend = match self.layout.primitive(cur_bend).outer() {
|
||||
Some(new_bend) => new_bend,
|
||||
None => break,
|
||||
}
|
||||
}
|
||||
|
||||
let core = self.layout.primitive(bend).core().unwrap();
|
||||
let mut maybe_inner = self.layout.primitive(bend).inner();
|
||||
|
||||
for bow in &bows {
|
||||
self.layout.remove_interior(bow);
|
||||
}
|
||||
|
||||
for bow in &bows {
|
||||
let ends = bow.ends();
|
||||
let head = self.draw().start(ends.0);
|
||||
let width = 5.0;
|
||||
|
||||
let segbend_head = if let Some(inner) = maybe_inner {
|
||||
self.draw().segbend_around_bend(head, inner, width)?
|
||||
} else {
|
||||
self.draw().segbend_around_dot(head, core, width)?
|
||||
};
|
||||
|
||||
maybe_inner = Some(segbend_head.segbend.bend);
|
||||
self.draw().finish(head, ends.1, width)?;
|
||||
self.relax_band(maybe_inner.unwrap());
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn relax_band(&mut self, bend: BendIndex) {
|
||||
let mut prev_bend = bend;
|
||||
while let Some(cur_bend) = self.layout.primitive(prev_bend).prev_bend() {
|
||||
if self.layout.primitive(cur_bend).cross_product() >= 0. {
|
||||
self.release_bow(cur_bend);
|
||||
}
|
||||
|
||||
prev_bend = cur_bend;
|
||||
}
|
||||
|
||||
let mut prev_bend = bend;
|
||||
while let Some(cur_bend) = self.layout.primitive(prev_bend).next_bend() {
|
||||
if self.layout.primitive(cur_bend).cross_product() >= 0. {
|
||||
self.release_bow(cur_bend);
|
||||
}
|
||||
|
||||
prev_bend = cur_bend;
|
||||
}
|
||||
}
|
||||
|
||||
fn release_bow(&mut self, bend: BendIndex) {
|
||||
let bow = self.layout.bow(bend);
|
||||
let ends = bow.ends();
|
||||
|
||||
self.layout.remove_interior(&bow);
|
||||
|
||||
let head = self.draw().start(ends.0);
|
||||
let _ = self.draw().finish(head, ends.1, 5.0);
|
||||
}
|
||||
|
||||
#[debug_ensures(ret.is_ok() -> trace.path.len() == old(trace.path.len() - 1))]
|
||||
#[debug_ensures(ret.is_err() -> trace.path.len() == old(trace.path.len()))]
|
||||
pub fn undo_step(&mut self, trace: &mut Trace) -> Result<(), ()> {
|
||||
|
|
|
|||
Loading…
Reference in New Issue