From 0c32ea7e41120529890bc4cacdb44bd0b49832b4 Mon Sep 17 00:00:00 2001 From: Mikolaj Wielgus Date: Mon, 31 Jul 2023 05:00:21 +0200 Subject: [PATCH] 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). --- src/layout.rs | 43 ++++++++++++++++++++++++++++++++----- src/main.rs | 51 ++++++++++++++++++++++++++++++-------------- src/math.rs | 12 +++++++---- src/primitive.rs | 55 +++++++++++++++++++++++++++++++++++++++++++++++- 4 files changed, 135 insertions(+), 26 deletions(-) diff --git a/src/layout.rs b/src/layout.rs index e2eedbd..ecb2906 100644 --- a/src/layout.rs +++ b/src/layout.rs @@ -72,7 +72,7 @@ impl Layout { 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 to_head = Head {bend: Some(to_bend), dot: to}; @@ -186,6 +186,7 @@ impl Layout { maybe_inner = head.bend; 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} } + 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) { 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 layer = bend; @@ -262,13 +295,13 @@ impl Layout { let core_circle = self.mesh.primitive(self.mesh.primitive(bend).core().unwrap()).weight().circle; Circle { 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 { - let mut circle = self.bend_circle(bend); - circle.r += width + self.rules.ruleset(conditions).clearance.min + 15.0; + let mut circle = self.bend_circle(bend, width); + circle.r += self.rules.ruleset(conditions).clearance.min + 10.0; circle } diff --git a/src/main.rs b/src/main.rs index 61619fb..09810a7 100644 --- a/src/main.rs +++ b/src/main.rs @@ -94,60 +94,79 @@ fn main() { 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 dot2_1 = layout.add_dot(DotWeight {net: 0, circle: Circle {pos: (230.5, 230.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 dot4_1 = layout.add_dot(DotWeight {net: 0, circle: Circle {pos: (290.5, 290.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: (130.5, 430.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: (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 dot2_2 = layout.add_dot(DotWeight {net: 0, circle: Circle {pos: (570.5, 230.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 dot4_2 = layout.add_dot(DotWeight {net: 0, circle: Circle {pos: (510.5, 290.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: (670.5, 430.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: (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 barrier_dot2 = layout.add_dot(DotWeight {net: 0, circle: Circle {pos: (400.5, 500.5).into(), r: 8.0}}); - layout.add_seg(barrier_dot1, barrier_dot2, 16.0); + let barrier1_dot1 = layout.add_dot(DotWeight {net: 0, circle: Circle {pos: (250.5, 150.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(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); 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); + 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); render_times(&mut event_pump, &mut canvas, &mut layout, None, 50); 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); + 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); render_times(&mut event_pump, &mut canvas, &mut layout, None, 50); + 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); + 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); render_times(&mut event_pump, &mut canvas, &mut layout, None, 50); + 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); + 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); + 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); } diff --git a/src/math.rs b/src/math.rs index e34b9c8..b73c629 100644 --- a/src/math.rs +++ b/src/math.rs @@ -80,7 +80,7 @@ pub fn tangent_point_pair(circle1: Circle, cw1: Option, circle2: Circle, c for tangent_point_pair in tangent_point_pairs { 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) { continue; @@ -88,7 +88,7 @@ pub fn tangent_point_pair(circle1: Circle, cw1: Option, circle2: Circle, c } 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) { continue; @@ -101,10 +101,14 @@ pub fn tangent_point_pair(circle1: Circle, cw1: Option, circle2: Circle, c 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 dy1 = stop.y() - start.y(); let dx2 = reference.x() - stop.x(); 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() } diff --git a/src/primitive.rs b/src/primitive.rs index 478edd2..48952c4 100644 --- a/src/primitive.rs +++ b/src/primitive.rs @@ -1,9 +1,10 @@ -use std::mem::swap; +use std::mem::{swap, self}; use petgraph::Direction::{Outgoing, Incoming}; use petgraph::stable_graph::StableDiGraph; use crate::graph::{Path, DotIndex, SegIndex, BendIndex, TaggedIndex, Tag, Index, DotWeight, SegWeight, BendWeight, TaggedWeight, Label}; +use crate::math; use crate::shape::Shape; #[derive(Debug)] @@ -58,6 +59,28 @@ impl<'a, Weight> Primitive<'a, Weight> { .next() } + pub fn next_akin(&self) -> Option> { + 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::::new(index)); + } + + prev_index = index; + } + + None + } + pub fn prev(&self) -> Option { 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()) @@ -65,6 +88,28 @@ impl<'a, Weight> Primitive<'a, Weight> { .next() } + pub fn prev_akin(&self) -> Option> { + 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::::new(index)); + } + + prev_index = index; + } + + None + } + pub fn core(&self) -> Option { self.graph.neighbors(self.index.index) .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 { *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) + } }