mirror of https://codeberg.org/topola/topola.git
Partial implementation of releasing bends
There's a panic when releasing (unbending) any of the inner bends in the demo (the outer one works for some reason).
This commit is contained in:
parent
f9ec5a0ef7
commit
0c32ea7e41
|
|
@ -72,7 +72,7 @@ impl Layout {
|
||||||
zone: None,
|
zone: None,
|
||||||
};
|
};
|
||||||
|
|
||||||
let to_circle = self.bend_circle(to_bend);
|
let to_circle = self.bend_circle(to_bend, width);
|
||||||
let from_cw = self.head_cw(&head);
|
let from_cw = self.head_cw(&head);
|
||||||
|
|
||||||
let to_head = Head {bend: Some(to_bend), dot: to};
|
let to_head = Head {bend: Some(to_bend), dot: to};
|
||||||
|
|
@ -186,6 +186,7 @@ impl Layout {
|
||||||
|
|
||||||
maybe_inner = head.bend;
|
maybe_inner = head.bend;
|
||||||
self.route_finish(head, ends[1], width);
|
self.route_finish(head, ends[1], width);
|
||||||
|
self.relax_band(maybe_inner.unwrap());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -202,6 +203,38 @@ impl Layout {
|
||||||
Head {dot: to_index, bend: None}
|
Head {dot: to_index, bend: None}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn relax_band(&mut self, bend: BendIndex) {
|
||||||
|
let mut prev_bend = bend;
|
||||||
|
while let Some(cur_bend) = self.mesh.primitive(prev_bend).prev_akin() {
|
||||||
|
dbg!(cur_bend);
|
||||||
|
if self.mesh.primitive(cur_bend).cross_product() >= 0.0 {
|
||||||
|
self.release_bow(cur_bend);
|
||||||
|
}
|
||||||
|
|
||||||
|
prev_bend = cur_bend;
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut prev_bend = bend;
|
||||||
|
while let Some(cur_bend) = self.mesh.primitive(prev_bend).next_akin() {
|
||||||
|
dbg!(cur_bend);
|
||||||
|
if self.mesh.primitive(cur_bend).cross_product() >= 0.0 {
|
||||||
|
self.release_bow(cur_bend);
|
||||||
|
}
|
||||||
|
|
||||||
|
prev_bend = cur_bend;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn release_bow(&mut self, bend: BendIndex) {
|
||||||
|
let bow = self.mesh.bow(bend);
|
||||||
|
let ends = bow.ends();
|
||||||
|
|
||||||
|
self.mesh.remove_open_set(bow.interior());
|
||||||
|
|
||||||
|
let head = self.route_start(ends[0]);
|
||||||
|
self.route_finish(head, ends[1], 5.0);
|
||||||
|
}
|
||||||
|
|
||||||
pub fn move_dot(&mut self, dot: DotIndex, to: Point) {
|
pub fn move_dot(&mut self, dot: DotIndex, to: Point) {
|
||||||
self.mesh.move_dot(dot, to);
|
self.mesh.move_dot(dot, to);
|
||||||
|
|
||||||
|
|
@ -250,7 +283,7 @@ impl Layout {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn bend_circle(&self, bend: BendIndex) -> Circle {
|
fn bend_circle(&self, bend: BendIndex, width: f64) -> Circle {
|
||||||
let mut r = 0.0;
|
let mut r = 0.0;
|
||||||
let mut layer = bend;
|
let mut layer = bend;
|
||||||
|
|
||||||
|
|
@ -262,13 +295,13 @@ impl Layout {
|
||||||
let core_circle = self.mesh.primitive(self.mesh.primitive(bend).core().unwrap()).weight().circle;
|
let core_circle = self.mesh.primitive(self.mesh.primitive(bend).core().unwrap()).weight().circle;
|
||||||
Circle {
|
Circle {
|
||||||
pos: core_circle.pos,
|
pos: core_circle.pos,
|
||||||
r: core_circle.r + r
|
r: core_circle.r + r + width + 5.0,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn bend_guidecircle(&self, bend: BendIndex, width: f64, conditions: Conditions) -> Circle {
|
fn bend_guidecircle(&self, bend: BendIndex, width: f64, conditions: Conditions) -> Circle {
|
||||||
let mut circle = self.bend_circle(bend);
|
let mut circle = self.bend_circle(bend, width);
|
||||||
circle.r += width + self.rules.ruleset(conditions).clearance.min + 15.0;
|
circle.r += self.rules.ruleset(conditions).clearance.min + 10.0;
|
||||||
circle
|
circle
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
51
src/main.rs
51
src/main.rs
|
|
@ -94,60 +94,79 @@ fn main() {
|
||||||
layout.route_finish(head, dot6, 5.0);*/
|
layout.route_finish(head, dot6, 5.0);*/
|
||||||
|
|
||||||
|
|
||||||
let dot1_1 = layout.add_dot(DotWeight {net: 0, circle: Circle {pos: (200.5, 200.5).into(), r: 8.0}});
|
let dot1_1 = layout.add_dot(DotWeight {net: 0, circle: Circle {pos: (100.5, 400.5).into(), r: 8.0}});
|
||||||
let dot2_1 = layout.add_dot(DotWeight {net: 0, circle: Circle {pos: (230.5, 230.5).into(), r: 8.0}});
|
let dot2_1 = layout.add_dot(DotWeight {net: 0, circle: Circle {pos: (130.5, 430.5).into(), r: 8.0}});
|
||||||
let dot3_1 = layout.add_dot(DotWeight {net: 0, circle: Circle {pos: (260.5, 260.5).into(), r: 8.0}});
|
let dot3_1 = layout.add_dot(DotWeight {net: 0, circle: Circle {pos: (160.5, 460.5).into(), r: 8.0}});
|
||||||
let dot4_1 = layout.add_dot(DotWeight {net: 0, circle: Circle {pos: (290.5, 290.5).into(), r: 8.0}});
|
let dot4_1 = layout.add_dot(DotWeight {net: 0, circle: Circle {pos: (190.5, 490.5).into(), r: 8.0}});
|
||||||
|
|
||||||
let dot1_2 = layout.add_dot(DotWeight {net: 0, circle: Circle {pos: (600.5, 200.5).into(), r: 8.0}});
|
let dot1_2 = layout.add_dot(DotWeight {net: 0, circle: Circle {pos: (700.5, 400.5).into(), r: 8.0}});
|
||||||
let dot2_2 = layout.add_dot(DotWeight {net: 0, circle: Circle {pos: (570.5, 230.5).into(), r: 8.0}});
|
let dot2_2 = layout.add_dot(DotWeight {net: 0, circle: Circle {pos: (670.5, 430.5).into(), r: 8.0}});
|
||||||
let dot3_2 = layout.add_dot(DotWeight {net: 0, circle: Circle {pos: (540.5, 260.5).into(), r: 8.0}});
|
let dot3_2 = layout.add_dot(DotWeight {net: 0, circle: Circle {pos: (640.5, 460.5).into(), r: 8.0}});
|
||||||
let dot4_2 = layout.add_dot(DotWeight {net: 0, circle: Circle {pos: (510.5, 290.5).into(), r: 8.0}});
|
let dot4_2 = layout.add_dot(DotWeight {net: 0, circle: Circle {pos: (610.5, 490.5).into(), r: 8.0}});
|
||||||
|
|
||||||
let barrier_dot1 = layout.add_dot(DotWeight {net: 0, circle: Circle {pos: (400.5, 150.5).into(), r: 8.0}});
|
let barrier1_dot1 = layout.add_dot(DotWeight {net: 0, circle: Circle {pos: (250.5, 150.5).into(), r: 8.0}});
|
||||||
let barrier_dot2 = layout.add_dot(DotWeight {net: 0, circle: Circle {pos: (400.5, 500.5).into(), r: 8.0}});
|
let barrier1_dot2 = layout.add_dot(DotWeight {net: 0, circle: Circle {pos: (250.5, 700.5).into(), r: 8.0}});
|
||||||
layout.add_seg(barrier_dot1, barrier_dot2, 16.0);
|
layout.add_seg(barrier1_dot1, barrier1_dot2, 16.0);
|
||||||
|
|
||||||
|
let barrier2_dot1 = layout.add_dot(DotWeight {net: 0, circle: Circle {pos: (450.5, 200.5).into(), r: 8.0}});
|
||||||
|
let barrier2_dot2 = layout.add_dot(DotWeight {net: 0, circle: Circle {pos: (450.5, 700.5).into(), r: 8.0}});
|
||||||
|
layout.add_seg(barrier2_dot1, barrier2_dot2, 16.0);
|
||||||
|
|
||||||
render_times(&mut event_pump, &mut canvas, &mut layout, None, -1);
|
render_times(&mut event_pump, &mut canvas, &mut layout, None, -1);
|
||||||
|
|
||||||
|
|
||||||
let head = layout.route_start(dot1_1);
|
let head = layout.route_start(dot1_1);
|
||||||
let head = layout.route_around_dot(head, barrier_dot1, true, 5.0);
|
let head = layout.route_around_dot(head, barrier1_dot1, true, 5.0);
|
||||||
|
|
||||||
render_times(&mut event_pump, &mut canvas, &mut layout, None, 50);
|
render_times(&mut event_pump, &mut canvas, &mut layout, None, 50);
|
||||||
|
let head = layout.route_around_dot(head, barrier2_dot1, true, 5.0);
|
||||||
|
|
||||||
|
render_times(&mut event_pump, &mut canvas, &mut layout, None, 50);
|
||||||
layout.route_finish(head, dot1_2, 5.0);
|
layout.route_finish(head, dot1_2, 5.0);
|
||||||
|
|
||||||
render_times(&mut event_pump, &mut canvas, &mut layout, None, 50);
|
render_times(&mut event_pump, &mut canvas, &mut layout, None, 50);
|
||||||
|
|
||||||
|
|
||||||
let head = layout.route_start(dot2_1);
|
let head = layout.route_start(dot2_1);
|
||||||
let head = layout.shove_around_dot(head, barrier_dot1, true, 5.0);
|
let head = layout.shove_around_dot(head, barrier1_dot1, true, 5.0);
|
||||||
|
|
||||||
render_times(&mut event_pump, &mut canvas, &mut layout, None, 50);
|
render_times(&mut event_pump, &mut canvas, &mut layout, None, 50);
|
||||||
|
let head = layout.shove_around_dot(head, barrier2_dot1, true, 5.0);
|
||||||
|
|
||||||
|
render_times(&mut event_pump, &mut canvas, &mut layout, None, 50);
|
||||||
layout.route_finish(head, dot2_2, 5.0);
|
layout.route_finish(head, dot2_2, 5.0);
|
||||||
|
|
||||||
render_times(&mut event_pump, &mut canvas, &mut layout, None, 50);
|
render_times(&mut event_pump, &mut canvas, &mut layout, None, 50);
|
||||||
|
|
||||||
|
|
||||||
let head = layout.route_start(dot3_1);
|
let head = layout.route_start(dot3_1);
|
||||||
let head = layout.shove_around_dot(head, barrier_dot1, true, 5.0);
|
|
||||||
|
|
||||||
render_times(&mut event_pump, &mut canvas, &mut layout, None, 50);
|
render_times(&mut event_pump, &mut canvas, &mut layout, None, 50);
|
||||||
|
let head = layout.shove_around_dot(head, barrier1_dot1, true, 5.0);
|
||||||
|
|
||||||
|
render_times(&mut event_pump, &mut canvas, &mut layout, None, 50);
|
||||||
|
let head = layout.shove_around_dot(head, barrier2_dot1, true, 5.0);
|
||||||
|
|
||||||
|
render_times(&mut event_pump, &mut canvas, &mut layout, None, 50);
|
||||||
layout.route_finish(head, dot3_2, 5.0);
|
layout.route_finish(head, dot3_2, 5.0);
|
||||||
|
|
||||||
render_times(&mut event_pump, &mut canvas, &mut layout, None, 50);
|
render_times(&mut event_pump, &mut canvas, &mut layout, None, 50);
|
||||||
|
|
||||||
|
|
||||||
let head = layout.route_start(dot4_1);
|
let head = layout.route_start(dot4_1);
|
||||||
let head = layout.shove_around_dot(head, barrier_dot1, true, 5.0);
|
|
||||||
|
|
||||||
render_times(&mut event_pump, &mut canvas, &mut layout, None, 50);
|
render_times(&mut event_pump, &mut canvas, &mut layout, None, 50);
|
||||||
|
let head = layout.shove_around_dot(head, barrier1_dot1, true, 5.0);
|
||||||
|
|
||||||
|
render_times(&mut event_pump, &mut canvas, &mut layout, None, 50);
|
||||||
|
let head = layout.shove_around_dot(head, barrier2_dot1, true, 5.0);
|
||||||
|
|
||||||
|
render_times(&mut event_pump, &mut canvas, &mut layout, None, 50);
|
||||||
layout.route_finish(head, dot4_2, 5.0);
|
layout.route_finish(head, dot4_2, 5.0);
|
||||||
|
|
||||||
|
|
||||||
render_times(&mut event_pump, &mut canvas, &mut layout, None, -1);
|
render_times(&mut event_pump, &mut canvas, &mut layout, None, -1);
|
||||||
render_times(&mut event_pump, &mut canvas, &mut layout, Some(barrier_dot1.tag()), -1);
|
render_times(&mut event_pump, &mut canvas, &mut layout, Some(barrier1_dot1.tag()), -1);
|
||||||
render_times(&mut event_pump, &mut canvas, &mut layout, None, -1);
|
render_times(&mut event_pump, &mut canvas, &mut layout, None, -1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
12
src/math.rs
12
src/math.rs
|
|
@ -80,7 +80,7 @@ pub fn tangent_point_pair(circle1: Circle, cw1: Option<bool>, circle2: Circle, c
|
||||||
|
|
||||||
for tangent_point_pair in tangent_point_pairs {
|
for tangent_point_pair in tangent_point_pairs {
|
||||||
if let Some(cw1) = cw1 {
|
if let Some(cw1) = cw1 {
|
||||||
let cross1 = cross_product(tangent_point_pair.0, tangent_point_pair.1, circle1.pos);
|
let cross1 = seq_cross_product(tangent_point_pair.0, tangent_point_pair.1, circle1.pos);
|
||||||
|
|
||||||
if (cw1 && cross1 <= 0.0) || (!cw1 && cross1 >= 0.0) {
|
if (cw1 && cross1 <= 0.0) || (!cw1 && cross1 >= 0.0) {
|
||||||
continue;
|
continue;
|
||||||
|
|
@ -88,7 +88,7 @@ pub fn tangent_point_pair(circle1: Circle, cw1: Option<bool>, circle2: Circle, c
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(cw2) = cw2 {
|
if let Some(cw2) = cw2 {
|
||||||
let cross2 = cross_product(tangent_point_pair.0, tangent_point_pair.1, circle2.pos);
|
let cross2 = seq_cross_product(tangent_point_pair.0, tangent_point_pair.1, circle2.pos);
|
||||||
|
|
||||||
if (cw2 && cross2 <= 0.0) || (!cw2 && cross2 >= 0.0) {
|
if (cw2 && cross2 <= 0.0) || (!cw2 && cross2 >= 0.0) {
|
||||||
continue;
|
continue;
|
||||||
|
|
@ -101,10 +101,14 @@ pub fn tangent_point_pair(circle1: Circle, cw1: Option<bool>, circle2: Circle, c
|
||||||
unreachable!();
|
unreachable!();
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn cross_product(start: Point, stop: Point, reference: Point) -> f64 {
|
pub fn seq_cross_product(start: Point, stop: Point, reference: Point) -> f64 {
|
||||||
let dx1 = stop.x() - start.x();
|
let dx1 = stop.x() - start.x();
|
||||||
let dy1 = stop.y() - start.y();
|
let dy1 = stop.y() - start.y();
|
||||||
let dx2 = reference.x() - stop.x();
|
let dx2 = reference.x() - stop.x();
|
||||||
let dy2 = reference.y() - stop.y();
|
let dy2 = reference.y() - stop.y();
|
||||||
dx1 * dy2 - dy1 * dx2
|
cross_product((dx1, dy1).into(), (dx2, dy2).into())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn cross_product(v1: Point, v2: Point) -> f64 {
|
||||||
|
v1.x() * v2.y() - v1.y() * v2.x()
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,10 @@
|
||||||
use std::mem::swap;
|
use std::mem::{swap, self};
|
||||||
|
|
||||||
use petgraph::Direction::{Outgoing, Incoming};
|
use petgraph::Direction::{Outgoing, Incoming};
|
||||||
use petgraph::stable_graph::StableDiGraph;
|
use petgraph::stable_graph::StableDiGraph;
|
||||||
|
|
||||||
use crate::graph::{Path, DotIndex, SegIndex, BendIndex, TaggedIndex, Tag, Index, DotWeight, SegWeight, BendWeight, TaggedWeight, Label};
|
use crate::graph::{Path, DotIndex, SegIndex, BendIndex, TaggedIndex, Tag, Index, DotWeight, SegWeight, BendWeight, TaggedWeight, Label};
|
||||||
|
use crate::math;
|
||||||
use crate::shape::Shape;
|
use crate::shape::Shape;
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
|
|
@ -58,6 +59,28 @@ impl<'a, Weight> Primitive<'a, Weight> {
|
||||||
.next()
|
.next()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn 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| dbg!(self.graph.find_edge(prev_index, *ni).is_some()))
|
||||||
|
.filter(|ni| dbg!(self.graph.edge_weight(self.graph.find_edge(prev_index, *ni).unwrap()).unwrap().is_end()))
|
||||||
|
.next()
|
||||||
|
{
|
||||||
|
let weight = *self.graph.node_weight(index).unwrap();
|
||||||
|
dbg!(weight);
|
||||||
|
dbg!(index);
|
||||||
|
|
||||||
|
if mem::discriminant(&self.tagged_weight()) == mem::discriminant(&weight) {
|
||||||
|
return Some(Index::<Weight>::new(index));
|
||||||
|
}
|
||||||
|
|
||||||
|
prev_index = index;
|
||||||
|
}
|
||||||
|
|
||||||
|
None
|
||||||
|
}
|
||||||
|
|
||||||
pub fn prev(&self) -> Option<TaggedIndex> {
|
pub fn prev(&self) -> Option<TaggedIndex> {
|
||||||
self.graph.neighbors_directed(self.index.index, Incoming)
|
self.graph.neighbors_directed(self.index.index, Incoming)
|
||||||
.filter(|ni| self.graph.edge_weight(self.graph.find_edge(*ni, self.index.index).unwrap()).unwrap().is_end())
|
.filter(|ni| self.graph.edge_weight(self.graph.find_edge(*ni, self.index.index).unwrap()).unwrap().is_end())
|
||||||
|
|
@ -65,6 +88,28 @@ impl<'a, Weight> Primitive<'a, Weight> {
|
||||||
.next()
|
.next()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn prev_akin(&self) -> Option<Index<Weight>> {
|
||||||
|
let mut prev_index = self.index.index;
|
||||||
|
|
||||||
|
while let Some(index) = self.graph.neighbors_directed(prev_index, Incoming)
|
||||||
|
.filter(|ni| dbg!(self.graph.find_edge(*ni, prev_index).is_some()))
|
||||||
|
.filter(|ni| dbg!(self.graph.edge_weight(self.graph.find_edge(*ni, prev_index).unwrap()).unwrap().is_end()))
|
||||||
|
.next()
|
||||||
|
{
|
||||||
|
let weight = *self.graph.node_weight(index).unwrap();
|
||||||
|
dbg!(weight);
|
||||||
|
dbg!(index);
|
||||||
|
|
||||||
|
if mem::discriminant(&self.tagged_weight()) == mem::discriminant(&weight) {
|
||||||
|
return Some(Index::<Weight>::new(index));
|
||||||
|
}
|
||||||
|
|
||||||
|
prev_index = index;
|
||||||
|
}
|
||||||
|
|
||||||
|
None
|
||||||
|
}
|
||||||
|
|
||||||
pub fn core(&self) -> Option<DotIndex> {
|
pub fn core(&self) -> Option<DotIndex> {
|
||||||
self.graph.neighbors(self.index.index)
|
self.graph.neighbors(self.index.index)
|
||||||
.filter(|ni| self.graph.edge_weight(self.graph.find_edge(self.index.index, *ni).unwrap()).unwrap().is_core())
|
.filter(|ni| self.graph.edge_weight(self.graph.find_edge(self.index.index, *ni).unwrap()).unwrap().is_core())
|
||||||
|
|
@ -167,4 +212,12 @@ impl<'a> Bend<'a> {
|
||||||
pub fn weight(&self) -> BendWeight {
|
pub fn weight(&self) -> BendWeight {
|
||||||
*self.tagged_weight().as_bend().unwrap()
|
*self.tagged_weight().as_bend().unwrap()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn cross_product(&self) -> f64 {
|
||||||
|
let center = self.primitive(self.core().unwrap()).weight().circle.pos;
|
||||||
|
let ends = self.ends();
|
||||||
|
let end1 = self.primitive(ends[0]).weight().circle.pos;
|
||||||
|
let end2 = self.primitive(ends[1]).weight().circle.pos;
|
||||||
|
math::cross_product(end1 - center, end2 - center)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue