mirror of https://codeberg.org/topola/topola.git
feat(autorouter/anterouter): As second choice, anteroute fanouts in ordinal directions
This commit is contained in:
parent
43f8d69281
commit
60cf00e014
|
|
@ -11,7 +11,11 @@ use serde::{Deserialize, Serialize};
|
||||||
use specctra_core::mesadata::AccessMesadata;
|
use specctra_core::mesadata::AccessMesadata;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
autorouter::{compass_direction::CardinalDirection, ratline::RatlineIndex, Autorouter},
|
autorouter::{
|
||||||
|
compass_direction::{CardinalDirection, CompassDirection, OrdinalDirection},
|
||||||
|
ratline::RatlineIndex,
|
||||||
|
Autorouter,
|
||||||
|
},
|
||||||
board::edit::BoardEdit,
|
board::edit::BoardEdit,
|
||||||
drawing::{
|
drawing::{
|
||||||
dot::FixedDotIndex,
|
dot::FixedDotIndex,
|
||||||
|
|
@ -157,7 +161,7 @@ impl Anterouter {
|
||||||
source_dot,
|
source_dot,
|
||||||
small_bbox,
|
small_bbox,
|
||||||
target_layer,
|
target_layer,
|
||||||
CardinalDirection::nearest_to_vector(ratline_delta),
|
CardinalDirection::nearest_from_vector(ratline_delta),
|
||||||
options,
|
options,
|
||||||
)
|
)
|
||||||
.is_ok()
|
.is_ok()
|
||||||
|
|
@ -190,7 +194,37 @@ impl Anterouter {
|
||||||
source_dot,
|
source_dot,
|
||||||
large_bbox,
|
large_bbox,
|
||||||
target_layer,
|
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,
|
options,
|
||||||
)
|
)
|
||||||
.is_ok()
|
.is_ok()
|
||||||
|
|
@ -208,17 +242,17 @@ impl Anterouter {
|
||||||
source_dot: FixedDotIndex,
|
source_dot: FixedDotIndex,
|
||||||
bbox: AABB<[f64; 2]>,
|
bbox: AABB<[f64; 2]>,
|
||||||
target_layer: usize,
|
target_layer: usize,
|
||||||
preferred_cardinal_direction: CardinalDirection,
|
preferred_compass_direction: impl CompassDirection,
|
||||||
options: &AnterouterOptions,
|
options: &AnterouterOptions,
|
||||||
) -> Result<(), ()> {
|
) -> Result<(), ()> {
|
||||||
if self
|
if self
|
||||||
.anteroute_fanout_on_bbox_in_cardinal_direction(
|
.anteroute_fanout_on_bbox_in_direction(
|
||||||
autorouter,
|
autorouter,
|
||||||
ratvertex,
|
ratvertex,
|
||||||
source_dot,
|
source_dot,
|
||||||
bbox,
|
bbox,
|
||||||
target_layer,
|
target_layer,
|
||||||
preferred_cardinal_direction,
|
preferred_compass_direction,
|
||||||
options,
|
options,
|
||||||
)
|
)
|
||||||
.is_ok()
|
.is_ok()
|
||||||
|
|
@ -226,15 +260,15 @@ impl Anterouter {
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut counterclockwise_turning_cardinal_direction = preferred_cardinal_direction;
|
let mut counterclockwise_turning_cardinal_direction = preferred_compass_direction;
|
||||||
let mut clockwise_turning_cardinal_direction = preferred_cardinal_direction;
|
let mut clockwise_turning_cardinal_direction = preferred_compass_direction;
|
||||||
|
|
||||||
loop {
|
loop {
|
||||||
counterclockwise_turning_cardinal_direction =
|
counterclockwise_turning_cardinal_direction =
|
||||||
counterclockwise_turning_cardinal_direction.turn_counterclockwise();
|
counterclockwise_turning_cardinal_direction.turn_counterclockwise();
|
||||||
|
|
||||||
if self
|
if self
|
||||||
.anteroute_fanout_on_bbox_in_cardinal_direction(
|
.anteroute_fanout_on_bbox_in_direction(
|
||||||
autorouter,
|
autorouter,
|
||||||
ratvertex,
|
ratvertex,
|
||||||
source_dot,
|
source_dot,
|
||||||
|
|
@ -252,7 +286,7 @@ impl Anterouter {
|
||||||
clockwise_turning_cardinal_direction.turn_clockwise();
|
clockwise_turning_cardinal_direction.turn_clockwise();
|
||||||
|
|
||||||
if self
|
if self
|
||||||
.anteroute_fanout_on_bbox_in_cardinal_direction(
|
.anteroute_fanout_on_bbox_in_direction(
|
||||||
autorouter,
|
autorouter,
|
||||||
ratvertex,
|
ratvertex,
|
||||||
source_dot,
|
source_dot,
|
||||||
|
|
@ -266,31 +300,31 @@ impl Anterouter {
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
|
|
||||||
if counterclockwise_turning_cardinal_direction == preferred_cardinal_direction
|
if counterclockwise_turning_cardinal_direction == preferred_compass_direction
|
||||||
|| clockwise_turning_cardinal_direction == preferred_cardinal_direction
|
|| clockwise_turning_cardinal_direction == preferred_compass_direction
|
||||||
{
|
{
|
||||||
return Err(());
|
return Err(());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn anteroute_fanout_on_bbox_in_cardinal_direction(
|
fn anteroute_fanout_on_bbox_in_direction(
|
||||||
&mut self,
|
&mut self,
|
||||||
autorouter: &mut Autorouter<impl AccessMesadata>,
|
autorouter: &mut Autorouter<impl AccessMesadata>,
|
||||||
ratvertex: NodeIndex<usize>,
|
ratvertex: NodeIndex<usize>,
|
||||||
source_dot: FixedDotIndex,
|
source_dot: FixedDotIndex,
|
||||||
bbox: AABB<[f64; 2]>,
|
bbox: AABB<[f64; 2]>,
|
||||||
target_layer: usize,
|
target_layer: usize,
|
||||||
cardinal_direction: CardinalDirection,
|
direction: impl Into<Point>,
|
||||||
options: &AnterouterOptions,
|
options: &AnterouterOptions,
|
||||||
) -> Result<(), ()> {
|
) -> Result<(), ()> {
|
||||||
let (_, dots) = self.place_fanout_via_on_bbox_in_cardinal_direction(
|
let (_, dots) = self.place_fanout_via_on_bbox_in_direction(
|
||||||
autorouter,
|
autorouter,
|
||||||
ratvertex,
|
ratvertex,
|
||||||
source_dot,
|
source_dot,
|
||||||
bbox,
|
bbox,
|
||||||
target_layer,
|
target_layer,
|
||||||
cardinal_direction,
|
direction,
|
||||||
options,
|
options,
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
|
|
@ -326,14 +360,14 @@ impl Anterouter {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn place_fanout_via_on_bbox_in_cardinal_direction(
|
fn place_fanout_via_on_bbox_in_direction(
|
||||||
&mut self,
|
&mut self,
|
||||||
autorouter: &mut Autorouter<impl AccessMesadata>,
|
autorouter: &mut Autorouter<impl AccessMesadata>,
|
||||||
ratvertex: NodeIndex<usize>,
|
ratvertex: NodeIndex<usize>,
|
||||||
source_dot: FixedDotIndex,
|
source_dot: FixedDotIndex,
|
||||||
bbox: AABB<[f64; 2]>,
|
bbox: AABB<[f64; 2]>,
|
||||||
target_layer: usize,
|
target_layer: usize,
|
||||||
cardinal_direction: CardinalDirection,
|
direction: impl Into<Point>,
|
||||||
options: &AnterouterOptions,
|
options: &AnterouterOptions,
|
||||||
) -> Result<(GenericIndex<ViaWeight>, Vec<FixedDotIndex>), ()> {
|
) -> Result<(GenericIndex<ViaWeight>, Vec<FixedDotIndex>), ()> {
|
||||||
let source_layer = autorouter
|
let source_layer = autorouter
|
||||||
|
|
@ -357,7 +391,7 @@ impl Anterouter {
|
||||||
.shape()
|
.shape()
|
||||||
.center();
|
.center();
|
||||||
|
|
||||||
let cardinal_direction_vector = Point::from(cardinal_direction);
|
let cardinal_direction_vector = direction.into();
|
||||||
|
|
||||||
let bbox_anchor = point! {
|
let bbox_anchor = point! {
|
||||||
x: (bbox.upper()[0] - bbox.lower()[0]) / 2.0 * cardinal_direction_vector.x(),
|
x: (bbox.upper()[0] - bbox.lower()[0]) / 2.0 * cardinal_direction_vector.x(),
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,12 @@
|
||||||
|
|
||||||
use geo::Point;
|
use geo::Point;
|
||||||
|
|
||||||
|
pub trait CompassDirection: Copy + PartialEq + Into<Point> {
|
||||||
|
fn nearest_from_vector(vector: Point) -> Self;
|
||||||
|
fn turn_clockwise(self) -> Self;
|
||||||
|
fn turn_counterclockwise(self) -> Self;
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
|
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
|
||||||
pub enum CardinalDirection {
|
pub enum CardinalDirection {
|
||||||
North,
|
North,
|
||||||
|
|
@ -13,8 +19,8 @@ pub enum CardinalDirection {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<CardinalDirection> for Point {
|
impl From<CardinalDirection> for Point {
|
||||||
fn from(compass_direction: CardinalDirection) -> Point {
|
fn from(cardinal_direction: CardinalDirection) -> Point {
|
||||||
match compass_direction {
|
match cardinal_direction {
|
||||||
CardinalDirection::North => [0.0, -1.0].into(),
|
CardinalDirection::North => [0.0, -1.0].into(),
|
||||||
CardinalDirection::West => [-1.0, 0.0].into(),
|
CardinalDirection::West => [-1.0, 0.0].into(),
|
||||||
CardinalDirection::South => [0.0, 1.0].into(),
|
CardinalDirection::South => [0.0, 1.0].into(),
|
||||||
|
|
@ -23,8 +29,8 @@ impl From<CardinalDirection> for Point {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl CardinalDirection {
|
impl CompassDirection for CardinalDirection {
|
||||||
pub fn nearest_to_vector(vector: Point) -> Self {
|
fn nearest_from_vector(vector: Point) -> Self {
|
||||||
if vector.x().abs() > vector.y().abs() {
|
if vector.x().abs() > vector.y().abs() {
|
||||||
if vector.x() > 0.0 {
|
if vector.x() > 0.0 {
|
||||||
Self::East
|
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 {
|
match self {
|
||||||
Self::North => Self::West,
|
Self::North => Self::West,
|
||||||
Self::West => Self::South,
|
Self::West => Self::South,
|
||||||
|
|
@ -48,13 +63,55 @@ impl CardinalDirection {
|
||||||
Self::East => Self::North,
|
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<OrdinalDirection> 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 {
|
match self {
|
||||||
Self::North => Self::East,
|
Self::NorthWest => Self::SouthWest,
|
||||||
Self::East => Self::South,
|
Self::SouthWest => Self::SouthEast,
|
||||||
Self::South => Self::West,
|
Self::SouthEast => Self::SouthWest,
|
||||||
Self::West => Self::North,
|
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<PrincipalWind> for Point {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl PrincipalWind {
|
impl CompassDirection for PrincipalWind {
|
||||||
pub fn nearest_to_vector(vector: Point) -> Self {
|
fn nearest_from_vector(vector: Point) -> Self {
|
||||||
if vector.x() == 0.0 && vector.y() == 0.0 {
|
if vector.x() == 0.0 && vector.y() == 0.0 {
|
||||||
panic!("Zero vector has no direction");
|
panic!("Zero vector has no direction");
|
||||||
}
|
}
|
||||||
|
|
@ -110,20 +167,7 @@ impl PrincipalWind {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn turn_counterclockwise(self) -> Self {
|
fn turn_clockwise(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 {
|
|
||||||
match self {
|
match self {
|
||||||
Self::North => Self::NorthEast,
|
Self::North => Self::NorthEast,
|
||||||
Self::NorthEast => Self::East,
|
Self::NorthEast => Self::East,
|
||||||
|
|
@ -135,4 +179,17 @@ impl PrincipalWind {
|
||||||
Self::NorthWest => Self::North,
|
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,
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue