diff --git a/src/autorouter/anterouter.rs b/src/autorouter/anterouter.rs index c05a697..fe7a22a 100644 --- a/src/autorouter/anterouter.rs +++ b/src/autorouter/anterouter.rs @@ -11,7 +11,11 @@ use serde::{Deserialize, Serialize}; use specctra_core::mesadata::AccessMesadata; use crate::{ - autorouter::{compass_direction::CardinalDirection, ratline::RatlineIndex, Autorouter}, + autorouter::{ + compass_direction::{CardinalDirection, CompassDirection, OrdinalDirection}, + ratline::RatlineIndex, + Autorouter, + }, board::edit::BoardEdit, drawing::{ dot::FixedDotIndex, @@ -157,7 +161,7 @@ impl Anterouter { source_dot, small_bbox, target_layer, - CardinalDirection::nearest_to_vector(ratline_delta), + CardinalDirection::nearest_from_vector(ratline_delta), options, ) .is_ok() @@ -190,7 +194,37 @@ impl Anterouter { source_dot, large_bbox, target_layer, - CardinalDirection::nearest_to_vector(ratline_delta), + CardinalDirection::nearest_from_vector(ratline_delta), + options, + ) + .is_ok() + { + return; + } + + if self + .anteroute_fanout_on_bbox( + autorouter, + ratvertex, + source_dot, + small_bbox, + target_layer, + OrdinalDirection::nearest_from_vector(ratline_delta), + options, + ) + .is_ok() + { + return; + } + + if self + .anteroute_fanout_on_bbox( + autorouter, + ratvertex, + source_dot, + large_bbox, + target_layer, + OrdinalDirection::nearest_from_vector(ratline_delta), options, ) .is_ok() @@ -208,17 +242,17 @@ impl Anterouter { source_dot: FixedDotIndex, bbox: AABB<[f64; 2]>, target_layer: usize, - preferred_cardinal_direction: CardinalDirection, + preferred_compass_direction: impl CompassDirection, options: &AnterouterOptions, ) -> Result<(), ()> { if self - .anteroute_fanout_on_bbox_in_cardinal_direction( + .anteroute_fanout_on_bbox_in_direction( autorouter, ratvertex, source_dot, bbox, target_layer, - preferred_cardinal_direction, + preferred_compass_direction, options, ) .is_ok() @@ -226,15 +260,15 @@ impl Anterouter { return Ok(()); } - let mut counterclockwise_turning_cardinal_direction = preferred_cardinal_direction; - let mut clockwise_turning_cardinal_direction = preferred_cardinal_direction; + let mut counterclockwise_turning_cardinal_direction = preferred_compass_direction; + let mut clockwise_turning_cardinal_direction = preferred_compass_direction; loop { counterclockwise_turning_cardinal_direction = counterclockwise_turning_cardinal_direction.turn_counterclockwise(); if self - .anteroute_fanout_on_bbox_in_cardinal_direction( + .anteroute_fanout_on_bbox_in_direction( autorouter, ratvertex, source_dot, @@ -252,7 +286,7 @@ impl Anterouter { clockwise_turning_cardinal_direction.turn_clockwise(); if self - .anteroute_fanout_on_bbox_in_cardinal_direction( + .anteroute_fanout_on_bbox_in_direction( autorouter, ratvertex, source_dot, @@ -266,31 +300,31 @@ impl Anterouter { return Ok(()); } - if counterclockwise_turning_cardinal_direction == preferred_cardinal_direction - || clockwise_turning_cardinal_direction == preferred_cardinal_direction + if counterclockwise_turning_cardinal_direction == preferred_compass_direction + || clockwise_turning_cardinal_direction == preferred_compass_direction { return Err(()); } } } - fn anteroute_fanout_on_bbox_in_cardinal_direction( + fn anteroute_fanout_on_bbox_in_direction( &mut self, autorouter: &mut Autorouter, ratvertex: NodeIndex, source_dot: FixedDotIndex, bbox: AABB<[f64; 2]>, target_layer: usize, - cardinal_direction: CardinalDirection, + direction: impl Into, options: &AnterouterOptions, ) -> Result<(), ()> { - let (_, dots) = self.place_fanout_via_on_bbox_in_cardinal_direction( + let (_, dots) = self.place_fanout_via_on_bbox_in_direction( autorouter, ratvertex, source_dot, bbox, target_layer, - cardinal_direction, + direction, options, )?; @@ -326,14 +360,14 @@ impl Anterouter { Ok(()) } - fn place_fanout_via_on_bbox_in_cardinal_direction( + fn place_fanout_via_on_bbox_in_direction( &mut self, autorouter: &mut Autorouter, ratvertex: NodeIndex, source_dot: FixedDotIndex, bbox: AABB<[f64; 2]>, target_layer: usize, - cardinal_direction: CardinalDirection, + direction: impl Into, options: &AnterouterOptions, ) -> Result<(GenericIndex, Vec), ()> { let source_layer = autorouter @@ -357,7 +391,7 @@ impl Anterouter { .shape() .center(); - let cardinal_direction_vector = Point::from(cardinal_direction); + let cardinal_direction_vector = direction.into(); let bbox_anchor = point! { x: (bbox.upper()[0] - bbox.lower()[0]) / 2.0 * cardinal_direction_vector.x(), diff --git a/src/autorouter/compass_direction.rs b/src/autorouter/compass_direction.rs index 21e3445..0356258 100644 --- a/src/autorouter/compass_direction.rs +++ b/src/autorouter/compass_direction.rs @@ -4,6 +4,12 @@ use geo::Point; +pub trait CompassDirection: Copy + PartialEq + Into { + fn nearest_from_vector(vector: Point) -> Self; + fn turn_clockwise(self) -> Self; + fn turn_counterclockwise(self) -> Self; +} + #[derive(Clone, Copy, Debug, Eq, PartialEq)] pub enum CardinalDirection { North, @@ -13,8 +19,8 @@ pub enum CardinalDirection { } impl From for Point { - fn from(compass_direction: CardinalDirection) -> Point { - match compass_direction { + fn from(cardinal_direction: CardinalDirection) -> Point { + match cardinal_direction { CardinalDirection::North => [0.0, -1.0].into(), CardinalDirection::West => [-1.0, 0.0].into(), CardinalDirection::South => [0.0, 1.0].into(), @@ -23,8 +29,8 @@ impl From for Point { } } -impl CardinalDirection { - pub fn nearest_to_vector(vector: Point) -> Self { +impl CompassDirection for CardinalDirection { + fn nearest_from_vector(vector: Point) -> Self { if vector.x().abs() > vector.y().abs() { if vector.x() > 0.0 { Self::East @@ -40,7 +46,16 @@ impl CardinalDirection { } } - pub fn turn_counterclockwise(self) -> Self { + fn turn_clockwise(self) -> Self { + match self { + Self::North => Self::East, + Self::East => Self::South, + Self::South => Self::West, + Self::West => Self::North, + } + } + + fn turn_counterclockwise(self) -> Self { match self { Self::North => Self::West, Self::West => Self::South, @@ -48,13 +63,55 @@ impl CardinalDirection { Self::East => Self::North, } } +} - pub fn turn_clockwise(self) -> Self { +#[derive(Clone, Copy, Debug, Eq, PartialEq)] +pub enum OrdinalDirection { + NorthWest, + SouthWest, + SouthEast, + NorthEast, +} + +impl From for Point { + fn from(ordinal_direction: OrdinalDirection) -> Point { + match ordinal_direction { + OrdinalDirection::NorthWest => [-1.0, -1.0].into(), + OrdinalDirection::SouthWest => [-1.0, 1.0].into(), + OrdinalDirection::SouthEast => [1.0, 1.0].into(), + OrdinalDirection::NorthEast => [1.0, -1.0].into(), + } + } +} + +impl CompassDirection for OrdinalDirection { + fn nearest_from_vector(vector: Point) -> Self { + if vector.x() > 0.0 && vector.y() > 0.0 { + Self::SouthEast + } else if vector.x() > 0.0 && vector.y() < 0.0 { + Self::NorthEast + } else if vector.x() < 0.0 && vector.y() < 0.0 { + Self::NorthWest + } else { + Self::NorthEast + } + } + + fn turn_clockwise(self) -> Self { match self { - Self::North => Self::East, - Self::East => Self::South, - Self::South => Self::West, - Self::West => Self::North, + Self::NorthWest => Self::SouthWest, + Self::SouthWest => Self::SouthEast, + Self::SouthEast => Self::SouthWest, + Self::NorthEast => Self::NorthWest, + } + } + + fn turn_counterclockwise(self) -> Self { + match self { + Self::NorthWest => Self::SouthWest, + Self::SouthWest => Self::SouthEast, + Self::SouthEast => Self::NorthEast, + Self::NorthEast => Self::NorthWest, } } } @@ -86,8 +143,8 @@ impl From for Point { } } -impl PrincipalWind { - pub fn nearest_to_vector(vector: Point) -> Self { +impl CompassDirection for PrincipalWind { + fn nearest_from_vector(vector: Point) -> Self { if vector.x() == 0.0 && vector.y() == 0.0 { panic!("Zero vector has no direction"); } @@ -110,20 +167,7 @@ impl PrincipalWind { } } - pub fn turn_counterclockwise(self) -> Self { - match self { - Self::North => Self::NorthWest, - Self::NorthWest => Self::West, - Self::West => Self::SouthWest, - Self::SouthWest => Self::South, - Self::South => Self::SouthEast, - Self::SouthEast => Self::East, - Self::East => Self::NorthEast, - Self::NorthEast => Self::North, - } - } - - pub fn turn_clockwise(self) -> Self { + fn turn_clockwise(self) -> Self { match self { Self::North => Self::NorthEast, Self::NorthEast => Self::East, @@ -135,4 +179,17 @@ impl PrincipalWind { Self::NorthWest => Self::North, } } + + fn turn_counterclockwise(self) -> Self { + match self { + Self::North => Self::NorthWest, + Self::NorthWest => Self::West, + Self::West => Self::SouthWest, + Self::SouthWest => Self::South, + Self::South => Self::SouthEast, + Self::SouthEast => Self::East, + Self::East => Self::NorthEast, + Self::NorthEast => Self::North, + } + } }