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:
Mikolaj Wielgus 2023-07-31 05:00:21 +02:00
parent f9ec5a0ef7
commit 0c32ea7e41
4 changed files with 135 additions and 26 deletions

View File

@ -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
} }

View File

@ -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);
} }

View File

@ -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()
} }

View File

@ -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)
}
} }