From bbbd2f57fec23954b65342195a17d2e9b07b2bbb Mon Sep 17 00:00:00 2001 From: Mikolaj Wielgus Date: Wed, 23 Aug 2023 05:15:16 +0200 Subject: [PATCH] Add `Guide` struct to generate guide curves --- src/guide.rs | 116 +++++++++++++++++++++++++++++++ src/layout.rs | 184 ++++++++++++-------------------------------------- src/main.rs | 1 + src/math.rs | 8 +-- src/mesh.rs | 9 --- src/rules.rs | 4 +- src/shape.rs | 3 +- 7 files changed, 168 insertions(+), 157 deletions(-) create mode 100644 src/guide.rs diff --git a/src/guide.rs b/src/guide.rs new file mode 100644 index 0000000..8ce6810 --- /dev/null +++ b/src/guide.rs @@ -0,0 +1,116 @@ +use geo::Line; + +use crate::{ + graph::{BendIndex, DotIndex}, + layout::Head, + math::{self, Circle}, + mesh::Mesh, + rules::{Conditions, Rules}, +}; + +pub struct Guide<'a, 'b> { + mesh: &'a Mesh, + rules: &'a Rules, + conditions: &'b Conditions, +} + +impl<'a, 'b> Guide<'a, 'b> { + pub fn new(mesh: &'a Mesh, rules: &'a Rules, conditions: &'b Conditions) -> Self { + Self { + mesh, + rules, + conditions, + } + } + + pub fn head_into_dot_segment(&self, head: &Head, into: DotIndex, width: f64) -> Line { + let from_circle = self.head_circle(&head, width); + let to_circle = Circle { + pos: self.mesh.primitive(into).weight().circle.pos, + r: 0.0, + }; + + let from_cw = self.head_cw(&head); + 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_segment( + &self, + head: &Head, + around: DotIndex, + cw: bool, + width: f64, + ) -> Line { + let from_circle = self.head_circle(&head, width); + let to_circle = self.dot_circle(around, width + 5.0); + + 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 { + match head.bend { + Some(bend) => Some(self.mesh.primitive(bend).weight().cw), + None => None, + } + } + + fn head_circle(&self, head: &Head, width: f64) -> Circle { + let maybe_bend = head.bend; + + let conditions = Conditions { + lower_net: None, + higher_net: None, + layer: None, + zone: None, + }; + + match maybe_bend { + Some(bend) => { + if let Some(inner) = self.mesh.primitive(bend).inner() { + self.bend_circle(inner, width) + } else { + self.dot_circle(self.mesh.primitive(bend).core().unwrap(), width + 5.0) + } + } + None => Circle { + pos: self.mesh.primitive(head.dot).weight().circle.pos, + r: 0.0, + }, + } + } + + fn bend_circle(&self, bend: BendIndex, width: f64) -> Circle { + let mut circle = self + .mesh + .primitive(bend) + .shape() + .as_bend() + .unwrap() + .circle(); + circle.r += self.rules.ruleset(&self.conditions).clearance.min + 10.0; + circle + } + + fn dot_circle(&self, dot: DotIndex, width: f64) -> Circle { + let circle = self.mesh.primitive(dot).weight().circle; + Circle { + pos: circle.pos, + r: circle.r + width + self.rules.ruleset(self.conditions).clearance.min, + } + } +} diff --git a/src/layout.rs b/src/layout.rs index bbcc3c8..b7f353e 100644 --- a/src/layout.rs +++ b/src/layout.rs @@ -4,6 +4,7 @@ use std::rc::Rc; use crate::graph::{BendIndex, DotIndex, Path, SegIndex, TaggedIndex}; use crate::graph::{BendWeight, DotWeight, SegWeight, TaggedWeight}; +use crate::guide::Guide; use crate::math; use crate::math::Circle; use crate::mesh::Mesh; @@ -35,34 +36,20 @@ impl Layout { } } - pub fn route_finish(&mut self, head: Head, to: DotIndex, width: f64) -> Result<(), ()> { - if let Some(bend) = self.mesh.primitive(to).bend() { - self.route_finish_in_bend(head, bend, to, width) + pub fn route_finish(&mut self, head: Head, into: DotIndex, width: f64) -> Result<(), ()> { + if let Some(bend) = self.mesh.primitive(into).bend() { + self.route_finish_in_bend(head, bend, into, width) } else { - self.route_finish_in_dot(head, to, width) + self.route_finish_in_dot(head, into, width) } } - fn route_finish_in_dot(&mut self, head: Head, to: DotIndex, width: f64) -> Result<(), ()> { - let from_circle = self.head_guidecircle(&head, width); - - let conditions = Conditions { - lower_net: None, - higher_net: None, - layer: None, - zone: None, - }; - - let to_circle = Circle { - pos: self.mesh.primitive(to).weight().circle.pos, - r: 0.0, - }; - - let from_cw = self.head_cw(&head); - let tangent_points = math::tangent_point_pair(from_circle, from_cw, to_circle, None); - - let head = self.extend_head(head, tangent_points.0)?; - self.add_seg(head.dot, to, width)?; + fn route_finish_in_dot(&mut self, head: Head, into: DotIndex, width: f64) -> Result<(), ()> { + let tangent = self + .guide(&Default::default()) + .head_into_dot_segment(&head, into, width); + let head = self.extend_head(head, tangent.start_point())?; + self.add_seg(head.dot, into, width)?; Ok(()) } @@ -73,28 +60,17 @@ impl Layout { to: DotIndex, width: f64, ) -> Result<(), ()> { - let from_circle = self.head_guidecircle(&head, width); - - let conditions = Conditions { - lower_net: None, - higher_net: None, - layer: None, - zone: None, - }; - - 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, }; - let to_cw = self.head_cw(&to_head); + let to_cw = self.guide(&Default::default()).head_cw(&to_head).unwrap(); + let tangent = self + .guide(&Default::default()) + .head_around_bend_segment(&head, to_bend, to_cw, width); + let head = self.extend_head(head, tangent.start_point())?; - let tangent_points = math::tangent_point_pair(from_circle, from_cw, to_circle, to_cw); - let head = self.extend_head(head, tangent_points.0)?; - - let to_head = self.extend_head(to_head, tangent_points.1)?; + let to_head = self.extend_head(to_head, tangent.end_point())?; self.add_seg(head.dot, to, width)?; Ok(()) } @@ -121,22 +97,18 @@ impl Layout { cw: bool, width: f64, ) -> Result { - let from_circle = self.head_guidecircle(&head, width); + let tangent = self + .guide(&Default::default()) + .head_around_dot_segment(&head, around, cw, width); - let conditions = Conditions { - lower_net: None, - higher_net: None, - layer: None, - zone: None, - }; - - let to_circle = self.dot_guidecircle(around, width + 5.0, conditions); - - let from_cw = self.head_cw(&head); - let tangent_points = math::tangent_point_pair(from_circle, from_cw, to_circle, Some(cw)); - - let head = self.extend_head(head, tangent_points.0)?; - self.route_seg_bend(head, TaggedIndex::Dot(around), tangent_points.1, cw, width) + let head = self.extend_head(head, tangent.start_point())?; + self.route_seg_bend( + head, + TaggedIndex::Dot(around), + tangent.end_point(), + cw, + width, + ) } pub fn shove_around_bend( @@ -161,22 +133,18 @@ impl Layout { cw: bool, width: f64, ) -> Result { - let from_circle = self.head_guidecircle(&head, width); + let tangent = self + .guide(&Default::default()) + .head_around_bend_segment(&head, around, cw, width); - let conditions = Conditions { - lower_net: None, - higher_net: None, - layer: None, - zone: None, - }; - - let to_circle = self.bend_guidecircle(around, width, conditions); - - let from_cw = self.head_cw(&head); - let tangent_points = math::tangent_point_pair(from_circle, from_cw, to_circle, Some(cw)); - - let head = self.extend_head(head, tangent_points.0)?; - self.route_seg_bend(head, TaggedIndex::Bend(around), tangent_points.1, cw, width) + let head = self.extend_head(head, tangent.start_point())?; + self.route_seg_bend( + head, + TaggedIndex::Bend(around), + tangent.end_point(), + cw, + width, + ) } fn route_seg_bend( @@ -301,76 +269,6 @@ impl Layout { Ok(()) } - fn head_guidecircle(&self, head: &Head, width: f64) -> Circle { - let maybe_bend = head.bend; - - let conditions = Conditions { - lower_net: None, - higher_net: None, - layer: None, - zone: None, - }; - - match maybe_bend { - Some(bend) => { - if let Some(inner) = self.mesh.primitive(bend).inner() { - self.bend_guidecircle(inner, width, conditions) - } else { - self.dot_guidecircle( - self.mesh.primitive(bend).core().unwrap(), - width + 5.0, - conditions, - ) - } - } - None => Circle { - pos: self.mesh.primitive(head.dot).weight().circle.pos, - r: 0.0, - }, - } - } - - fn head_cw(&self, head: &Head) -> Option { - match head.bend { - Some(bend) => Some(self.mesh.primitive(bend).weight().cw), - None => None, - } - } - - fn dot_guidecircle(&self, dot: DotIndex, width: f64, conditions: Conditions) -> Circle { - let circle = self.mesh.primitive(dot).weight().circle; - Circle { - pos: circle.pos, - r: circle.r + width + self.rules.ruleset(conditions).clearance.min, - } - } - - fn bend_circle(&self, bend: BendIndex, width: f64) -> Circle { - let mut r = 0.0; - let mut layer = bend; - - while let Some(inner) = self.mesh.primitive(layer).inner() { - r += 5.0 + self.mesh.primitive(inner).shape().width(); - layer = inner; - } - - let core_circle = self - .mesh - .primitive(self.mesh.primitive(bend).core().unwrap()) - .weight() - .circle; - Circle { - pos: core_circle.pos, - 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, width); - circle.r += self.rules.ruleset(conditions).clearance.min + 10.0; - circle - } - fn extend_head(&mut self, head: Head, to: Point) -> Result { if let Some(..) = head.bend { self.extend_head_bend(head, to) @@ -413,4 +311,8 @@ impl Layout { ) }) } + + fn guide<'a>(&'a self, conditions: &'a Conditions) -> Guide { + Guide::new(&self.mesh, &self.rules, conditions) + } } diff --git a/src/main.rs b/src/main.rs index df62f29..af39b4f 100644 --- a/src/main.rs +++ b/src/main.rs @@ -10,6 +10,7 @@ macro_rules! dbg_dot { #[macro_use] mod graph; mod bow; +mod guide; mod layout; mod math; mod mesh; diff --git a/src/math.rs b/src/math.rs index 3891e47..44dd971 100644 --- a/src/math.rs +++ b/src/math.rs @@ -69,7 +69,7 @@ fn cast_point_to_canonical_line(pt: Point, line: CanonicalLine) -> Point { .into(); } -pub fn tangent_point_pairs(circle1: Circle, circle2: Circle) -> [(Point, Point); 4] { +fn tangent_point_pairs(circle1: Circle, circle2: Circle) -> [(Point, Point); 4] { let tgs = _tangents(circle1, circle2); [ @@ -92,12 +92,12 @@ pub fn tangent_point_pairs(circle1: Circle, circle2: Circle) -> [(Point, Point); ] } -pub fn tangent_point_pair( +pub fn tangent_segment( circle1: Circle, cw1: Option, circle2: Circle, cw2: Option, -) -> (Point, Point) { +) -> Line { let tangent_point_pairs = tangent_point_pairs(circle1, circle2); for tangent_point_pair in tangent_point_pairs { @@ -117,7 +117,7 @@ pub fn tangent_point_pair( } } - return tangent_point_pair; + return Line::new(tangent_point_pair.0, tangent_point_pair.1); } unreachable!(); diff --git a/src/mesh.rs b/src/mesh.rs index 1602af9..3edf995 100644 --- a/src/mesh.rs +++ b/src/mesh.rs @@ -239,15 +239,6 @@ impl Mesh { } fn triangulate(&mut self) { - /*for edge_index in self.graph.edge_indices() { - if *self.graph.edge_weight(edge_index).unwrap() == Label::Peer { - self.graph.remove_edge(edge_index); - } - }*/ - /*for (edge_index, edge) in self.graph.raw_edges().iter().enumerate() { - self.graph.remove_edge(edge_index); - }*/ - let peer_edge_indices: Vec> = self .graph .edge_indices() diff --git a/src/rules.rs b/src/rules.rs index ccec0ec..de05878 100644 --- a/src/rules.rs +++ b/src/rules.rs @@ -1,6 +1,6 @@ use std::collections::HashMap; -#[derive(Debug, Clone, Copy, Hash, PartialEq, Eq)] +#[derive(Debug, Default, Clone, Copy, Hash, PartialEq, Eq)] pub struct Conditions { pub lower_net: Option, pub higher_net: Option, @@ -40,7 +40,7 @@ impl Rules { me } - pub fn ruleset(&self, conditions: Conditions) -> &Ruleset { + pub fn ruleset(&self, conditions: &Conditions) -> &Ruleset { let priority = conditions.priority(); for index in (1..(priority + 1)).rev() { diff --git a/src/shape.rs b/src/shape.rs index 05ff20b..09632a5 100644 --- a/src/shape.rs +++ b/src/shape.rs @@ -1,3 +1,4 @@ +use enum_as_inner::EnumAsInner; use geo::{point, polygon, EuclideanDistance, Intersects, Point, Polygon, Rotate}; use rstar::{RTreeObject, AABB}; @@ -69,7 +70,7 @@ impl BendShape { } } -#[derive(Debug, PartialEq)] +#[derive(Debug, EnumAsInner, PartialEq)] pub enum Shape { // Intentionally in different order to reorder `self.intersects(...)` properly. Dot(DotShape),