mirror of https://codeberg.org/topola/topola.git
feat(autorouter/autorouter): Add presorting by ratline intersection count and length
Sadly, this does not work well for the DE-9 to DE-9 test, but it is a step forward.
This commit is contained in:
parent
0752817538
commit
43005eb864
|
|
@ -11,6 +11,7 @@ use topola::autorouter::invoker::Invoker;
|
||||||
use topola::autorouter::selection::PinSelection;
|
use topola::autorouter::selection::PinSelection;
|
||||||
use topola::autorouter::Autorouter;
|
use topola::autorouter::Autorouter;
|
||||||
use topola::autorouter::AutorouterOptions;
|
use topola::autorouter::AutorouterOptions;
|
||||||
|
use topola::autorouter::PresortBy;
|
||||||
use topola::layout::LayoutEdit;
|
use topola::layout::LayoutEdit;
|
||||||
use topola::router::RouterOptions;
|
use topola::router::RouterOptions;
|
||||||
use topola::specctra::design::SpecctraDesign;
|
use topola::specctra::design::SpecctraDesign;
|
||||||
|
|
@ -38,7 +39,7 @@ fn main() -> Result<(), std::io::Error> {
|
||||||
Command::Autoroute(
|
Command::Autoroute(
|
||||||
PinSelection::new_select_layer(&board, 0),
|
PinSelection::new_select_layer(&board, 0),
|
||||||
AutorouterOptions {
|
AutorouterOptions {
|
||||||
presort_by_pairwise_detours: false,
|
presort_by: PresortBy::RatlineIntersectionCountAndLength,
|
||||||
router_options: RouterOptions {
|
router_options: RouterOptions {
|
||||||
wrap_around_bands: true,
|
wrap_around_bands: true,
|
||||||
squeeze_through_under_bends: false,
|
squeeze_through_under_bends: false,
|
||||||
|
|
|
||||||
|
|
@ -10,7 +10,7 @@ use crate::{
|
||||||
};
|
};
|
||||||
|
|
||||||
use egui::{Context, Ui};
|
use egui::{Context, Ui};
|
||||||
use topola::autorouter::AutorouterOptions;
|
use topola::autorouter::{AutorouterOptions, PresortBy};
|
||||||
|
|
||||||
pub struct FileActions {
|
pub struct FileActions {
|
||||||
pub open_design: Trigger,
|
pub open_design: Trigger,
|
||||||
|
|
@ -330,10 +330,12 @@ impl RouteActions {
|
||||||
ui.separator();
|
ui.separator();
|
||||||
|
|
||||||
ui.menu_button(tr.text("tr-menu-options"), |ui| {
|
ui.menu_button(tr.text("tr-menu-options"), |ui| {
|
||||||
ui.checkbox(
|
egui::ComboBox::from_label(tr.text("tr-menu-route-options-presort-by"))
|
||||||
&mut autorouter_options.presort_by_pairwise_detours,
|
.selected_text(format!("{:?}", autorouter_options.presort_by))
|
||||||
tr.text("tr-menu-route-options-presort-by-pairwise-detours"),
|
.show_ui(ui, |ui| {
|
||||||
);
|
ui.selectable_value(&mut autorouter_options.presort_by, PresortBy::RatlineIntersectionCountAndLength, tr.text("tr-menu-route-options-presort-by-ratline-intersection-count-and-length"));
|
||||||
|
ui.selectable_value(&mut autorouter_options.presort_by, PresortBy::PairwiseDetours, tr.text("tr-menu-route-options-presort-by-pairwise-detours"));
|
||||||
|
});
|
||||||
ui.checkbox(
|
ui.checkbox(
|
||||||
&mut autorouter_options
|
&mut autorouter_options
|
||||||
.router_options
|
.router_options
|
||||||
|
|
|
||||||
|
|
@ -7,6 +7,7 @@ use std::{collections::BTreeSet, ops::ControlFlow, path::Path, sync::mpsc::Sende
|
||||||
use topola::{
|
use topola::{
|
||||||
autorouter::{
|
autorouter::{
|
||||||
execution::Command, invoker::InvokerError, selection::Selection, AutorouterOptions,
|
execution::Command, invoker::InvokerError, selection::Selection, AutorouterOptions,
|
||||||
|
PresortBy,
|
||||||
},
|
},
|
||||||
board::AccessMesadata,
|
board::AccessMesadata,
|
||||||
interactor::{interaction::InteractionStepper, route_plan::RoutePlan},
|
interactor::{interaction::InteractionStepper, route_plan::RoutePlan},
|
||||||
|
|
@ -42,7 +43,7 @@ impl MenuBar {
|
||||||
pub fn new() -> Self {
|
pub fn new() -> Self {
|
||||||
Self {
|
Self {
|
||||||
autorouter_options: AutorouterOptions {
|
autorouter_options: AutorouterOptions {
|
||||||
presort_by_pairwise_detours: false,
|
presort_by: PresortBy::RatlineIntersectionCountAndLength,
|
||||||
router_options: RouterOptions {
|
router_options: RouterOptions {
|
||||||
routed_band_width: 100.0,
|
routed_band_width: 100.0,
|
||||||
wrap_around_bands: true,
|
wrap_around_bands: true,
|
||||||
|
|
|
||||||
|
|
@ -47,7 +47,9 @@ tr-menu-help-online-documentation = Online Documentation
|
||||||
# Misnamed tag, TODO fix this.
|
# Misnamed tag, TODO fix this.
|
||||||
tr-menu-options = Options
|
tr-menu-options = Options
|
||||||
|
|
||||||
tr-menu-route-options-presort-by-pairwise-detours = Presort by Pairwise Detours
|
tr-menu-route-options-presort-by = Presort by
|
||||||
|
tr-menu-route-options-presort-by-ratline-intersection-count-and-length = Intersection Count and Length
|
||||||
|
tr-menu-route-options-presort-by-pairwise-detours = Pairwise Detours
|
||||||
|
|
||||||
## Continuously applied, so use imperfective aspect if possible, e.g. in Polish
|
## Continuously applied, so use imperfective aspect if possible, e.g. in Polish
|
||||||
## it should be "przeciskaj pod taśmami" instead of "przeciśnij pod taśmami".
|
## it should be "przeciskaj pod taśmami" instead of "przeciśnij pod taśmami".
|
||||||
|
|
|
||||||
|
|
@ -12,7 +12,7 @@ use thiserror::Error;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
board::{AccessMesadata, Board},
|
board::{AccessMesadata, Board},
|
||||||
drawing::{band::BandTermsegIndex, dot::FixedDotIndex, Infringement},
|
drawing::{band::BandTermsegIndex, Infringement},
|
||||||
graph::MakeRef,
|
graph::MakeRef,
|
||||||
layout::{via::ViaWeight, LayoutEdit},
|
layout::{via::ViaWeight, LayoutEdit},
|
||||||
router::{navmesh::NavmeshError, ng, thetastar::ThetastarError, RouterOptions},
|
router::{navmesh::NavmeshError, ng, thetastar::ThetastarError, RouterOptions},
|
||||||
|
|
@ -31,9 +31,15 @@ use super::{
|
||||||
selection::{BandSelection, PinSelection},
|
selection::{BandSelection, PinSelection},
|
||||||
};
|
};
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy, Serialize, Deserialize)]
|
#[derive(Clone, Copy, Debug, Deserialize, Eq, PartialEq, Serialize)]
|
||||||
|
pub enum PresortBy {
|
||||||
|
RatlineIntersectionCountAndLength,
|
||||||
|
PairwiseDetours,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Copy, Debug, Deserialize, Serialize)]
|
||||||
pub struct AutorouterOptions {
|
pub struct AutorouterOptions {
|
||||||
pub presort_by_pairwise_detours: bool,
|
pub presort_by: PresortBy,
|
||||||
pub router_options: RouterOptions,
|
pub router_options: RouterOptions,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -15,8 +15,8 @@ use thiserror::Error;
|
||||||
use crate::{
|
use crate::{
|
||||||
board::AccessMesadata,
|
board::AccessMesadata,
|
||||||
drawing::graph::PrimitiveIndex,
|
drawing::graph::PrimitiveIndex,
|
||||||
geometry::{edit::ApplyGeometryEdit, primitive::PrimitiveShape},
|
geometry::{edit::ApplyGeometryEdit, primitive::PrimitiveShape, shape::MeasureLength},
|
||||||
graph::GenericIndex,
|
graph::{GenericIndex, MakeRef},
|
||||||
layout::poly::PolyWeight,
|
layout::poly::PolyWeight,
|
||||||
router::{
|
router::{
|
||||||
navcord::Navcord,
|
navcord::Navcord,
|
||||||
|
|
@ -35,7 +35,7 @@ use super::{
|
||||||
measure_length::MeasureLengthExecutionStepper,
|
measure_length::MeasureLengthExecutionStepper,
|
||||||
place_via::PlaceViaExecutionStepper,
|
place_via::PlaceViaExecutionStepper,
|
||||||
remove_bands::RemoveBandsExecutionStepper,
|
remove_bands::RemoveBandsExecutionStepper,
|
||||||
Autorouter, AutorouterError,
|
Autorouter, AutorouterError, PresortBy,
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Trait for getting the information to display on the debug overlay,
|
/// Trait for getting the information to display on the debug overlay,
|
||||||
|
|
@ -169,18 +169,43 @@ impl<M: AccessMesadata + Clone> Invoker<M> {
|
||||||
Command::Autoroute(selection, options) => {
|
Command::Autoroute(selection, options) => {
|
||||||
let mut ratlines = self.autorouter.selected_ratlines(selection);
|
let mut ratlines = self.autorouter.selected_ratlines(selection);
|
||||||
|
|
||||||
if options.presort_by_pairwise_detours {
|
match options.presort_by {
|
||||||
ratlines.sort_unstable_by(|a, b| {
|
PresortBy::RatlineIntersectionCountAndLength => {
|
||||||
|
ratlines.sort_unstable_by(|a, b| {
|
||||||
|
let a_intersector_count = a
|
||||||
|
.ref_(self.autorouter())
|
||||||
|
.find_intersecting_ratlines()
|
||||||
|
.count();
|
||||||
|
let b_intersector_count = b
|
||||||
|
.ref_(self.autorouter())
|
||||||
|
.find_intersecting_ratlines()
|
||||||
|
.count();
|
||||||
|
|
||||||
|
let primary_ordering = a_intersector_count.cmp(&b_intersector_count);
|
||||||
|
|
||||||
|
if primary_ordering != Ordering::Equal {
|
||||||
|
primary_ordering
|
||||||
|
} else {
|
||||||
|
let a_length = a.ref_(self.autorouter()).length();
|
||||||
|
let b_length = b.ref_(self.autorouter()).length();
|
||||||
|
let secondary_ordering = a_length.total_cmp(&b_length);
|
||||||
|
|
||||||
|
secondary_ordering
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
PresortBy::PairwiseDetours => ratlines.sort_unstable_by(|a, b| {
|
||||||
let mut compare_detours = self
|
let mut compare_detours = self
|
||||||
.autorouter
|
.autorouter
|
||||||
.compare_detours_ratlines(*a, *b, *options)
|
.compare_detours_ratlines(*a, *b, *options)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
if let Ok((al, bl)) = compare_detours.finish(&mut self.autorouter) {
|
if let Ok((al, bl)) = compare_detours.finish(&mut self.autorouter) {
|
||||||
PartialOrd::partial_cmp(&al, &bl).unwrap()
|
PartialOrd::partial_cmp(&al, &bl).unwrap()
|
||||||
} else {
|
} else {
|
||||||
Ordering::Equal
|
Ordering::Equal
|
||||||
}
|
}
|
||||||
});
|
}),
|
||||||
}
|
}
|
||||||
|
|
||||||
ExecutionStepper::Autoroute(self.autorouter.autoroute_ratlines(ratlines, *options)?)
|
ExecutionStepper::Autoroute(self.autorouter.autoroute_ratlines(ratlines, *options)?)
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
//
|
//
|
||||||
// SPDX-License-Identifier: MIT OR Apache-2.0
|
// SPDX-License-Identifier: MIT OR Apache-2.0
|
||||||
|
|
||||||
use geo::{Distance, Euclidean};
|
use geo::{line_intersection::line_intersection, Distance, Euclidean, Line};
|
||||||
use petgraph::graph::EdgeIndex;
|
use petgraph::graph::EdgeIndex;
|
||||||
use specctra_core::mesadata::AccessMesadata;
|
use specctra_core::mesadata::AccessMesadata;
|
||||||
|
|
||||||
|
|
@ -73,31 +73,51 @@ impl<'a, M: AccessMesadata> RatlineRef<'a, M> {
|
||||||
|
|
||||||
(source_dot, target_dot)
|
(source_dot, target_dot)
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
impl<'a, M: AccessMesadata> MeasureLength for RatlineRef<'a, M> {
|
pub fn find_intersecting_ratlines(&self) -> impl Iterator<Item = RatlineIndex> + '_ {
|
||||||
fn length(&self) -> f64 {
|
let self_line = self.line();
|
||||||
let (ratvertex0, ratvertex1) = self
|
|
||||||
|
self.autorouter
|
||||||
|
.ratsnest()
|
||||||
|
.graph()
|
||||||
|
.edge_indices()
|
||||||
|
.filter(move |other| {
|
||||||
|
let other_line = other.ref_(self.autorouter).line();
|
||||||
|
|
||||||
|
line_intersection(self_line, other_line).is_some()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn line(&self) -> Line {
|
||||||
|
let (source, target) = self
|
||||||
.autorouter
|
.autorouter
|
||||||
.ratsnest
|
.ratsnest
|
||||||
.graph()
|
.graph()
|
||||||
.edge_endpoints(self.index)
|
.edge_endpoints(self.index)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
let ratvertex0_pos = self
|
let source_pos = self
|
||||||
.autorouter
|
.autorouter
|
||||||
.ratsnest
|
.ratsnest
|
||||||
.graph()
|
.graph()
|
||||||
.node_weight(ratvertex0)
|
.node_weight(source)
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.pos;
|
.pos;
|
||||||
let ratvertex1_pos = self
|
let target_pos = self
|
||||||
.autorouter
|
.autorouter
|
||||||
.ratsnest
|
.ratsnest
|
||||||
.graph()
|
.graph()
|
||||||
.node_weight(ratvertex1)
|
.node_weight(target)
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.pos;
|
.pos;
|
||||||
|
|
||||||
Euclidean::distance(&ratvertex0_pos, &ratvertex1_pos)
|
Line::new(source_pos, target_pos)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a, M: AccessMesadata> MeasureLength for RatlineRef<'a, M> {
|
||||||
|
fn length(&self) -> f64 {
|
||||||
|
let line = self.line();
|
||||||
|
|
||||||
|
Euclidean::distance(&line.start_point(), &line.end_point())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -84,7 +84,7 @@ pub fn assert_navnode_count(
|
||||||
.iter()
|
.iter()
|
||||||
.find_map(|ratline| {
|
.find_map(|ratline| {
|
||||||
let (candidate_origin, candidate_destination) =
|
let (candidate_origin, candidate_destination) =
|
||||||
autorouter.ratline_endpoint_dots(*ratline);
|
ratline.ref_(autorouter).endpoint_dots();
|
||||||
let candidate_origin_pin = autorouter
|
let candidate_origin_pin = autorouter
|
||||||
.board()
|
.board()
|
||||||
.node_pinname(&GenericNode::Primitive(candidate_origin.into()))
|
.node_pinname(&GenericNode::Primitive(candidate_origin.into()))
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue