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::Autorouter;
|
||||
use topola::autorouter::AutorouterOptions;
|
||||
use topola::autorouter::PresortBy;
|
||||
use topola::layout::LayoutEdit;
|
||||
use topola::router::RouterOptions;
|
||||
use topola::specctra::design::SpecctraDesign;
|
||||
|
|
@ -38,7 +39,7 @@ fn main() -> Result<(), std::io::Error> {
|
|||
Command::Autoroute(
|
||||
PinSelection::new_select_layer(&board, 0),
|
||||
AutorouterOptions {
|
||||
presort_by_pairwise_detours: false,
|
||||
presort_by: PresortBy::RatlineIntersectionCountAndLength,
|
||||
router_options: RouterOptions {
|
||||
wrap_around_bands: true,
|
||||
squeeze_through_under_bends: false,
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@ use crate::{
|
|||
};
|
||||
|
||||
use egui::{Context, Ui};
|
||||
use topola::autorouter::AutorouterOptions;
|
||||
use topola::autorouter::{AutorouterOptions, PresortBy};
|
||||
|
||||
pub struct FileActions {
|
||||
pub open_design: Trigger,
|
||||
|
|
@ -330,10 +330,12 @@ impl RouteActions {
|
|||
ui.separator();
|
||||
|
||||
ui.menu_button(tr.text("tr-menu-options"), |ui| {
|
||||
ui.checkbox(
|
||||
&mut autorouter_options.presort_by_pairwise_detours,
|
||||
tr.text("tr-menu-route-options-presort-by-pairwise-detours"),
|
||||
);
|
||||
egui::ComboBox::from_label(tr.text("tr-menu-route-options-presort-by"))
|
||||
.selected_text(format!("{:?}", autorouter_options.presort_by))
|
||||
.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(
|
||||
&mut autorouter_options
|
||||
.router_options
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@ use std::{collections::BTreeSet, ops::ControlFlow, path::Path, sync::mpsc::Sende
|
|||
use topola::{
|
||||
autorouter::{
|
||||
execution::Command, invoker::InvokerError, selection::Selection, AutorouterOptions,
|
||||
PresortBy,
|
||||
},
|
||||
board::AccessMesadata,
|
||||
interactor::{interaction::InteractionStepper, route_plan::RoutePlan},
|
||||
|
|
@ -42,7 +43,7 @@ impl MenuBar {
|
|||
pub fn new() -> Self {
|
||||
Self {
|
||||
autorouter_options: AutorouterOptions {
|
||||
presort_by_pairwise_detours: false,
|
||||
presort_by: PresortBy::RatlineIntersectionCountAndLength,
|
||||
router_options: RouterOptions {
|
||||
routed_band_width: 100.0,
|
||||
wrap_around_bands: true,
|
||||
|
|
|
|||
|
|
@ -47,7 +47,9 @@ tr-menu-help-online-documentation = Online Documentation
|
|||
# Misnamed tag, TODO fix this.
|
||||
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
|
||||
## it should be "przeciskaj pod taśmami" instead of "przeciśnij pod taśmami".
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@ use thiserror::Error;
|
|||
|
||||
use crate::{
|
||||
board::{AccessMesadata, Board},
|
||||
drawing::{band::BandTermsegIndex, dot::FixedDotIndex, Infringement},
|
||||
drawing::{band::BandTermsegIndex, Infringement},
|
||||
graph::MakeRef,
|
||||
layout::{via::ViaWeight, LayoutEdit},
|
||||
router::{navmesh::NavmeshError, ng, thetastar::ThetastarError, RouterOptions},
|
||||
|
|
@ -31,9 +31,15 @@ use super::{
|
|||
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 presort_by_pairwise_detours: bool,
|
||||
pub presort_by: PresortBy,
|
||||
pub router_options: RouterOptions,
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -15,8 +15,8 @@ use thiserror::Error;
|
|||
use crate::{
|
||||
board::AccessMesadata,
|
||||
drawing::graph::PrimitiveIndex,
|
||||
geometry::{edit::ApplyGeometryEdit, primitive::PrimitiveShape},
|
||||
graph::GenericIndex,
|
||||
geometry::{edit::ApplyGeometryEdit, primitive::PrimitiveShape, shape::MeasureLength},
|
||||
graph::{GenericIndex, MakeRef},
|
||||
layout::poly::PolyWeight,
|
||||
router::{
|
||||
navcord::Navcord,
|
||||
|
|
@ -35,7 +35,7 @@ use super::{
|
|||
measure_length::MeasureLengthExecutionStepper,
|
||||
place_via::PlaceViaExecutionStepper,
|
||||
remove_bands::RemoveBandsExecutionStepper,
|
||||
Autorouter, AutorouterError,
|
||||
Autorouter, AutorouterError, PresortBy,
|
||||
};
|
||||
|
||||
/// 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) => {
|
||||
let mut ratlines = self.autorouter.selected_ratlines(selection);
|
||||
|
||||
if options.presort_by_pairwise_detours {
|
||||
match options.presort_by {
|
||||
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
|
||||
.autorouter
|
||||
.compare_detours_ratlines(*a, *b, *options)
|
||||
.unwrap();
|
||||
|
||||
if let Ok((al, bl)) = compare_detours.finish(&mut self.autorouter) {
|
||||
PartialOrd::partial_cmp(&al, &bl).unwrap()
|
||||
} else {
|
||||
Ordering::Equal
|
||||
}
|
||||
});
|
||||
}),
|
||||
}
|
||||
|
||||
ExecutionStepper::Autoroute(self.autorouter.autoroute_ratlines(ratlines, *options)?)
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
//
|
||||
// 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 specctra_core::mesadata::AccessMesadata;
|
||||
|
||||
|
|
@ -73,31 +73,51 @@ impl<'a, M: AccessMesadata> RatlineRef<'a, M> {
|
|||
|
||||
(source_dot, target_dot)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, M: AccessMesadata> MeasureLength for RatlineRef<'a, M> {
|
||||
fn length(&self) -> f64 {
|
||||
let (ratvertex0, ratvertex1) = self
|
||||
pub fn find_intersecting_ratlines(&self) -> impl Iterator<Item = RatlineIndex> + '_ {
|
||||
let self_line = self.line();
|
||||
|
||||
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
|
||||
.ratsnest
|
||||
.graph()
|
||||
.edge_endpoints(self.index)
|
||||
.unwrap();
|
||||
let ratvertex0_pos = self
|
||||
let source_pos = self
|
||||
.autorouter
|
||||
.ratsnest
|
||||
.graph()
|
||||
.node_weight(ratvertex0)
|
||||
.node_weight(source)
|
||||
.unwrap()
|
||||
.pos;
|
||||
let ratvertex1_pos = self
|
||||
let target_pos = self
|
||||
.autorouter
|
||||
.ratsnest
|
||||
.graph()
|
||||
.node_weight(ratvertex1)
|
||||
.node_weight(target)
|
||||
.unwrap()
|
||||
.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()
|
||||
.find_map(|ratline| {
|
||||
let (candidate_origin, candidate_destination) =
|
||||
autorouter.ratline_endpoint_dots(*ratline);
|
||||
ratline.ref_(autorouter).endpoint_dots();
|
||||
let candidate_origin_pin = autorouter
|
||||
.board()
|
||||
.node_pinname(&GenericNode::Primitive(candidate_origin.into()))
|
||||
|
|
|
|||
Loading…
Reference in New Issue