refactor(topola-egui): Move storing principal layer to planar autoroute options

I've done some struct renaming while at it.
This commit is contained in:
Mikolaj Wielgus 2025-10-13 21:38:47 +02:00
parent 4c1a72dc1d
commit cd73c766a5
16 changed files with 134 additions and 123 deletions

View File

@ -11,7 +11,7 @@ use topola::autorouter::history::History;
use topola::autorouter::invoker::Invoker;
use topola::autorouter::selection::PinSelection;
use topola::autorouter::Autorouter;
use topola::autorouter::AutorouterOptions;
use topola::autorouter::PlanarAutorouteOptions;
use topola::autorouter::PresortBy;
use topola::board::edit::BoardEdit;
use topola::router::RouterOptions;
@ -39,7 +39,7 @@ fn main() -> Result<(), std::io::Error> {
history.do_(
Command::Autoroute(
PinSelection::new_select_layer(&board, 0),
AutorouterOptions {
PlanarAutorouteOptions {
presort_by: PresortBy::RatlineIntersectionCountAndLength,
permutate: true,
router: RouterOptions {

View File

@ -10,9 +10,7 @@ use crate::{
};
use egui::{Context, Ui};
use topola::autorouter::{
multilayer_autoroute::MultilayerAutorouterOptions, AutorouterOptions, PresortBy,
};
use topola::autorouter::{multilayer_autoroute::MultilayerAutorouteOptions, PresortBy};
pub struct FileActions {
pub open_design: Trigger,
@ -336,7 +334,7 @@ impl RouteActions {
tr: &Translator,
have_workspace: bool,
workspace_activities_enabled: bool,
multilayer_autorouter_options: &mut MultilayerAutorouterOptions,
multilayer_autorouter_options: &mut MultilayerAutorouteOptions,
) -> egui::InnerResponse<()> {
ui.add_enabled_ui(have_workspace, |ui| {
ui.add_enabled_ui(workspace_activities_enabled, |ui| {

View File

@ -185,7 +185,8 @@ impl eframe::App for App {
if self.menu_bar.show_appearance_panel {
if let Some(workspace) = &mut self.maybe_workspace {
workspace.update_appearance_panel(ctx);
workspace
.update_appearance_panel(ctx, &mut self.menu_bar.multilayer_autoroute_options);
}
}

View File

@ -3,15 +3,16 @@
// SPDX-License-Identifier: MIT
use egui::{widget_text::WidgetText, Context, Grid, ScrollArea, SidePanel};
use topola::board::{AccessMesadata, Board};
use topola::{
autorouter::multilayer_autoroute::MultilayerAutorouteOptions,
board::{AccessMesadata, Board},
};
pub struct AppearancePanel {
// TODO:
// In1.Cu shall be #7fc87f (#d5ecd5 when selected).
// In2.Cu shall be #ce7d2c (#e8c39e when selected).
pub visible: Box<[bool]>,
pub active_layer: Option<usize>,
}
impl AppearancePanel {
@ -20,13 +21,15 @@ impl AppearancePanel {
let visible = core::iter::repeat(true)
.take(layer_count)
.collect::<Box<[_]>>();
Self {
visible,
active_layer: Some(0),
}
Self { visible }
}
pub fn update(&mut self, ctx: &Context, board: &Board<impl AccessMesadata>) {
pub fn update(
&mut self,
ctx: &Context,
board: &Board<impl AccessMesadata>,
options: &mut MultilayerAutorouteOptions,
) {
SidePanel::right("appearance_panel").show(ctx, |ui| {
ui.label("Layers");
let row_height = ui.spacing().interact_size.y;
@ -49,8 +52,8 @@ impl AppearancePanel {
// unnamed layers can't be used for routing
if layername.is_some() {
ui.radio_value(
&mut self.active_layer,
Some(layer),
&mut options.planar.principal_layer,
layer,
WidgetText::default(),
);
} else {

View File

@ -78,7 +78,7 @@ impl<'a> Displayer<'a> {
self.display_activity(menu_bar);
if menu_bar.show_primitive_indices {
self.display_primitive_indices();
self.display_primitive_indices(menu_bar);
}
}
@ -571,18 +571,20 @@ impl<'a> Displayer<'a> {
}
}
fn display_primitive_indices(&mut self) {
fn display_primitive_indices(&mut self, menu_bar: &MenuBar) {
let board = self.workspace.interactor.invoker().autorouter().board();
if let Some(active_layer) = self.workspace.appearance_panel.active_layer {
for primitive in board.layout().drawing().layer_primitive_nodes(active_layer) {
for primitive in board
.layout()
.drawing()
.layer_primitive_nodes(menu_bar.multilayer_autoroute_options.planar.principal_layer)
{
let pos = primitive
.primitive_ref(board.layout().drawing())
.shape()
.center();
let color = if let Some(activity) = &mut self.workspace.interactor.maybe_activity()
{
let color = if let Some(activity) = &mut self.workspace.interactor.maybe_activity() {
if activity.obstacles().contains(&primitive) {
egui::Color32::from_rgb(255, 255, 255)
} else {
@ -600,5 +602,4 @@ impl<'a> Displayer<'a> {
);
}
}
}
}

View File

@ -7,8 +7,8 @@ use std::{collections::BTreeSet, ops::ControlFlow, path::Path, sync::mpsc::Sende
use topola::{
autorouter::{
anterouter::AnterouterOptions, execution::Command, invoker::InvokerError,
multilayer_autoroute::MultilayerAutorouterOptions, selection::Selection, AutorouterOptions,
PresortBy,
multilayer_autoroute::MultilayerAutorouteOptions, selection::Selection,
PlanarAutorouteOptions, PresortBy,
},
board::AccessMesadata,
interactor::{interaction::InteractionStepper, route_plan::RoutePlan},
@ -26,7 +26,7 @@ use crate::{
};
pub struct MenuBar {
pub multilayer_autorouter_options: MultilayerAutorouterOptions,
pub multilayer_autoroute_options: MultilayerAutorouteOptions,
pub is_placing_via: bool,
pub show_ratsnest: bool,
pub show_navmesh: bool,
@ -46,11 +46,12 @@ pub struct MenuBar {
impl MenuBar {
pub fn new() -> Self {
Self {
multilayer_autorouter_options: MultilayerAutorouterOptions {
multilayer_autoroute_options: MultilayerAutorouteOptions {
anterouter: AnterouterOptions {
fanout_clearance: 200.0,
},
planar: AutorouterOptions {
planar: PlanarAutorouteOptions {
principal_layer: 0,
presort_by: PresortBy::RatlineIntersectionCountAndLength,
permutate: true,
router: RouterOptions {
@ -166,7 +167,7 @@ impl MenuBar {
tr,
maybe_workspace.is_some(),
workspace_activities_enabled,
&mut self.multilayer_autorouter_options,
&mut self.multilayer_autoroute_options,
)
});
@ -294,12 +295,10 @@ impl MenuBar {
.recalculate_topo_navmesh
.consume_key_triggered(ctx, ui)
{
if let Some(active_layer) = workspace.appearance_panel.active_layer {
workspace.overlay.recalculate_topo_navmesh(
workspace.interactor.invoker().autorouter(),
active_layer,
self.multilayer_autoroute_options.planar.principal_layer,
);
}
} else if actions.place.place_via.consume_key_enabled(
ctx,
ui,
@ -322,35 +321,35 @@ impl MenuBar {
Command::RemoveBands(selection.band_selection)
})
} else if actions.route.topo_autoroute.consume_key_triggered(ctx, ui) {
if let Some(active_layer) = workspace.appearance_panel.active_layer {
let active_layer = workspace
let active_layer_name = workspace
.interactor
.invoker()
.autorouter()
.board()
.layout()
.rules()
.layer_layername(active_layer)
.layer_layername(
self.multilayer_autoroute_options.planar.principal_layer,
)
.expect("unknown active layer")
.to_string();
schedule(error_dialog, workspace, |selection| {
Command::TopoAutoroute {
selection: selection.pin_selection,
allowed_edges: BTreeSet::new(),
active_layer,
active_layer: active_layer_name,
routed_band_width: self
.multilayer_autorouter_options
.multilayer_autoroute_options
.planar
.router
.routed_band_width,
}
});
}
} else if actions.route.autoroute.consume_key_triggered(ctx, ui) {
schedule(error_dialog, workspace, |selection| {
Command::MultilayerAutoroute(
selection.pin_selection,
self.multilayer_autorouter_options,
self.multilayer_autoroute_options,
)
});
} else if actions
@ -361,7 +360,7 @@ impl MenuBar {
schedule(error_dialog, workspace, |selection| {
Command::Autoroute(
selection.pin_selection,
self.multilayer_autorouter_options.planar,
self.multilayer_autoroute_options.planar,
)
});
} else if actions
@ -372,7 +371,7 @@ impl MenuBar {
schedule(error_dialog, workspace, |selection| {
Command::CompareDetours(
selection.pin_selection,
self.multilayer_autorouter_options.planar,
self.multilayer_autoroute_options.planar,
)
});
} else if actions
@ -388,15 +387,15 @@ impl MenuBar {
.place_route_plan
.consume_key_triggered(ctx, ui)
{
if let Some(active_layer) = workspace.appearance_panel.active_layer {
self.is_placing_via = false;
workspace.interactor.interact(InteractionStepper::RoutePlan(
RoutePlan::new(active_layer),
RoutePlan::new(
self.multilayer_autoroute_options.planar.principal_layer,
),
));
}
}
}
}
Ok::<(), InvokerError>(())
})
.inner

View File

@ -51,7 +51,9 @@ impl Viewport {
let latest_point = point! {x: latest_pos.x as f64, y: -latest_pos.y as f64};
let interactive_input = InteractiveInput {
active_layer: workspace.appearance_panel.active_layer,
active_layer: Some(
menu_bar.multilayer_autoroute_options.planar.principal_layer,
),
pointer_pos: latest_point,
dt: ctx.input(|i| i.stable_dt),
};

View File

@ -8,7 +8,9 @@ use std::{
};
use topola::{
autorouter::{execution::Command, history::History},
autorouter::{
execution::Command, history::History, multilayer_autoroute::MultilayerAutorouteOptions,
},
board::edit::BoardEdit,
interactor::{
activity::{InteractiveEvent, InteractiveEventKind, InteractiveInput},
@ -120,7 +122,7 @@ impl Workspace {
circle: Circle {
pos: interactive_input.pointer_pos,
r: menu_bar
.multilayer_autorouter_options
.multilayer_autoroute_options
.planar
.router
.routed_band_width
@ -197,8 +199,12 @@ impl Workspace {
}
}
pub fn update_appearance_panel(&mut self, ctx: &egui::Context) {
pub fn update_appearance_panel(
&mut self,
ctx: &egui::Context,
options: &mut MultilayerAutorouteOptions,
) {
self.appearance_panel
.update(ctx, self.interactor.invoker().autorouter().board());
.update(ctx, self.interactor.invoker().autorouter().board(), options);
}
}

View File

@ -12,7 +12,7 @@ use thiserror::Error;
use crate::{
autorouter::{
multilayer_autoroute::{MultilayerAutorouteExecutionStepper, MultilayerAutorouterOptions},
multilayer_autoroute::{MultilayerAutorouteExecutionStepper, MultilayerAutorouteOptions},
permutator::PlanarAutorouteExecutionPermutator,
planner::Planner,
ratsnests::Ratsnests,
@ -44,7 +44,8 @@ pub enum PresortBy {
}
#[derive(Clone, Copy, Debug, Deserialize, Serialize)]
pub struct AutorouterOptions {
pub struct PlanarAutorouteOptions {
pub principal_layer: usize,
pub presort_by: PresortBy,
pub permutate: bool,
pub router: RouterOptions,
@ -86,7 +87,7 @@ impl<M: AccessMesadata> Autorouter<M> {
&mut self,
selection: &PinSelection,
point: Point,
options: AutorouterOptions,
options: PlanarAutorouteOptions,
) -> Result<PointrouteExecutionStepper, AutorouterError> {
let ratvertex = self.find_selected_ratvertex(selection).unwrap();
let origin_dot = match self
@ -114,7 +115,7 @@ impl<M: AccessMesadata> Autorouter<M> {
pub fn multilayer_autoroute(
&mut self,
selection: &PinSelection,
options: MultilayerAutorouterOptions,
options: MultilayerAutorouteOptions,
) -> Result<MultilayerAutorouteExecutionStepper, AutorouterError> {
let planner = Planner::new(self, &self.selected_ratlines(selection));
@ -129,7 +130,7 @@ impl<M: AccessMesadata> Autorouter<M> {
pub fn planar_autoroute(
&mut self,
selection: &PinSelection,
options: AutorouterOptions,
options: PlanarAutorouteOptions,
) -> Result<PlanarAutorouteExecutionPermutator, AutorouterError> {
PlanarAutorouteExecutionPermutator::new(self, self.selected_ratlines(selection), options)
}
@ -137,7 +138,7 @@ impl<M: AccessMesadata> Autorouter<M> {
pub(super) fn planar_autoroute_ratlines(
&mut self,
ratlines: Vec<RatlineIndex>,
options: AutorouterOptions,
options: PlanarAutorouteOptions,
) -> Result<PlanarAutorouteExecutionStepper, AutorouterError> {
PlanarAutorouteExecutionStepper::new(self, ratlines, options)
}
@ -278,7 +279,7 @@ impl<M: AccessMesadata> Autorouter<M> {
pub fn compare_detours(
&mut self,
selection: &PinSelection,
options: AutorouterOptions,
options: PlanarAutorouteOptions,
) -> Result<CompareDetoursExecutionStepper, AutorouterError> {
let ratlines = self.selected_ratlines(selection);
if ratlines.len() < 2 {
@ -291,7 +292,7 @@ impl<M: AccessMesadata> Autorouter<M> {
&mut self,
ratline1: RatlineIndex,
ratline2: RatlineIndex,
options: AutorouterOptions,
options: PlanarAutorouteOptions,
) -> Result<CompareDetoursExecutionStepper, AutorouterError> {
CompareDetoursExecutionStepper::new(self, ratline1, ratline2, options)
}

View File

@ -20,7 +20,7 @@ use super::{
invoker::GetDebugOverlayData,
planar_autoroute::{PlanarAutorouteContinueStatus, PlanarAutorouteExecutionStepper},
ratline::RatlineIndex,
Autorouter, AutorouterError, AutorouterOptions,
Autorouter, AutorouterError, PlanarAutorouteOptions,
};
pub struct CompareDetoursExecutionStepper {
@ -38,7 +38,7 @@ impl CompareDetoursExecutionStepper {
autorouter: &mut Autorouter<impl AccessMesadata>,
ratline1: RatlineIndex,
ratline2: RatlineIndex,
options: AutorouterOptions,
options: PlanarAutorouteOptions,
) -> Result<Self, AutorouterError> {
Ok(Self {
autoroute: autorouter.planar_autoroute_ratlines(vec![ratline1, ratline2], options)?,

View File

@ -9,7 +9,7 @@ use serde::{Deserialize, Serialize};
use crate::{
autorouter::{
multilayer_autoroute::{MultilayerAutorouteExecutionStepper, MultilayerAutorouterOptions},
multilayer_autoroute::{MultilayerAutorouteExecutionStepper, MultilayerAutorouteOptions},
permutator::PlanarAutorouteExecutionPermutator,
},
board::{edit::BoardEdit, AccessMesadata},
@ -25,15 +25,15 @@ use super::{
place_via::PlaceViaExecutionStepper,
remove_bands::RemoveBandsExecutionStepper,
selection::{BandSelection, PinSelection},
Autorouter, AutorouterOptions,
Autorouter, PlanarAutorouteOptions,
};
type Type = PinSelection;
#[derive(Debug, Clone, Serialize, Deserialize)]
pub enum Command {
Autoroute(PinSelection, AutorouterOptions), // TODO: Rename to PlanarAutoroute.
MultilayerAutoroute(PinSelection, MultilayerAutorouterOptions),
Autoroute(PinSelection, PlanarAutorouteOptions), // TODO: Rename to PlanarAutoroute.
MultilayerAutoroute(PinSelection, MultilayerAutorouteOptions),
TopoAutoroute {
selection: PinSelection,
#[serde(default, skip_serializing_if = "BTreeSet::is_empty")]
@ -43,7 +43,7 @@ pub enum Command {
},
PlaceVia(ViaWeight),
RemoveBands(BandSelection),
CompareDetours(Type, AutorouterOptions),
CompareDetours(Type, PlanarAutorouteOptions),
MeasureLength(BandSelection),
}

View File

@ -14,7 +14,7 @@ use crate::{
permutator::PlanarAutorouteExecutionPermutator,
planar_autoroute::PlanarAutorouteContinueStatus,
ratline::RatlineIndex,
Autorouter, AutorouterError, AutorouterOptions,
Autorouter, AutorouterError, PlanarAutorouteOptions,
},
board::edit::BoardEdit,
drawing::graph::PrimitiveIndex,
@ -24,9 +24,9 @@ use crate::{
};
#[derive(Clone, Copy, Debug, Deserialize, Serialize)]
pub struct MultilayerAutorouterOptions {
pub struct MultilayerAutorouteOptions {
pub anterouter: AnterouterOptions,
pub planar: AutorouterOptions,
pub planar: PlanarAutorouteOptions,
}
pub struct MultilayerAutorouteExecutionStepper {
@ -38,7 +38,7 @@ impl MultilayerAutorouteExecutionStepper {
autorouter: &mut Autorouter<impl AccessMesadata>,
ratlines: Vec<RatlineIndex>,
plan: AnterouterPlan,
options: MultilayerAutorouterOptions,
options: MultilayerAutorouteOptions,
) -> Result<Self, AutorouterError> {
let mut assigner = Anterouter::new(plan);
assigner.anteroute(autorouter, &options.anterouter);

View File

@ -13,7 +13,7 @@ use crate::{
planar_autoroute::{PlanarAutorouteContinueStatus, PlanarAutorouteExecutionStepper},
presorter::{PresortParams, PresortRatlines, SccIntersectionsAndLengthPresorter},
ratline::RatlineIndex,
Autorouter, AutorouterError, AutorouterOptions,
Autorouter, AutorouterError, PlanarAutorouteOptions,
},
board::edit::BoardEdit,
drawing::graph::PrimitiveIndex,
@ -25,14 +25,14 @@ use crate::{
pub struct PlanarAutorouteExecutionPermutator {
stepper: PlanarAutorouteExecutionStepper,
permuter: RatlinesPermuter,
options: AutorouterOptions,
options: PlanarAutorouteOptions,
}
impl PlanarAutorouteExecutionPermutator {
pub fn new(
autorouter: &mut Autorouter<impl AccessMesadata>,
ratlines: Vec<RatlineIndex>,
options: AutorouterOptions,
options: PlanarAutorouteOptions,
) -> Result<Self, AutorouterError> {
let presorter = SccIntersectionsAndLengthPresorter::new(
autorouter,

View File

@ -12,7 +12,7 @@ use crate::{
autorouter::{
planar_autoroute::PlanarAutorouteExecutionStepper,
presorter::SccIntersectionsAndLengthPresorter, ratline::RatlineIndex, scc::Scc, Autorouter,
AutorouterOptions,
PlanarAutorouteOptions,
},
drawing::graph::MakePrimitiveRef,
geometry::{GenericNode, GetLayer},
@ -39,7 +39,7 @@ impl RatlinesPermuter {
autorouter: &mut Autorouter<impl AccessMesadata>,
ratlines: Vec<RatlineIndex>,
presorter: SccIntersectionsAndLengthPresorter,
options: &AutorouterOptions,
options: &PlanarAutorouteOptions,
) -> Self {
RatlinesPermuter::SccPermutations(SccPermutationsRatlinePermuter::new(
autorouter, ratlines, presorter, options,
@ -60,7 +60,7 @@ impl SccPermutationsRatlinePermuter {
_autorouter: &mut Autorouter<impl AccessMesadata>,
ratlines: Vec<RatlineIndex>,
presorter: SccIntersectionsAndLengthPresorter,
_options: &AutorouterOptions,
_options: &PlanarAutorouteOptions,
) -> Self {
// TODO: Instead of instantiating presorter again here, get it from
// an argument.
@ -120,7 +120,7 @@ impl RatlineCutsRatlinePermuter {
_autorouter: &mut Autorouter<impl AccessMesadata>,
_ratlines: Vec<RatlineIndex>,
_presorter: SccIntersectionsAndLengthPresorter,
_options: &AutorouterOptions,
_options: &PlanarAutorouteOptions,
) -> Self {
/*Self {
sccs: presorter.dissolve(),

View File

@ -26,7 +26,7 @@ use crate::{
use super::{
invoker::GetDebugOverlayData, ratline::RatlineIndex, Autorouter, AutorouterError,
AutorouterOptions,
PlanarAutorouteOptions,
};
/// Represents the current status of the autoroute operation.
@ -53,7 +53,7 @@ pub struct PlanarAutorouteExecutionStepper {
/// Records the changes to the board data, one routed band per item.
board_data_edits: Vec<BoardDataEdit>,
/// The options for the autorouting process, defining how routing should be carried out.
options: AutorouterOptions,
options: PlanarAutorouteOptions,
}
impl PlanarAutorouteExecutionStepper {
@ -65,7 +65,7 @@ impl PlanarAutorouteExecutionStepper {
pub fn new(
autorouter: &mut Autorouter<impl AccessMesadata>,
ratlines: Vec<RatlineIndex>,
options: AutorouterOptions,
options: PlanarAutorouteOptions,
) -> Result<Self, AutorouterError> {
if ratlines.is_empty() {
return Err(AutorouterError::NothingToRoute);

View File

@ -18,11 +18,11 @@ use crate::{
stepper::Step,
};
use super::{Autorouter, AutorouterError, AutorouterOptions};
use super::{Autorouter, AutorouterError, PlanarAutorouteOptions};
pub struct PointrouteExecutionStepper {
route: RouteStepper,
options: AutorouterOptions,
options: PlanarAutorouteOptions,
}
impl PointrouteExecutionStepper {
@ -30,7 +30,7 @@ impl PointrouteExecutionStepper {
autorouter: &mut Autorouter<impl AccessMesadata>,
origin: FixedDotIndex,
point: Point,
options: AutorouterOptions,
options: PlanarAutorouteOptions,
) -> Result<Self, AutorouterError> {
let destination = autorouter.board.add_fixed_dot_infringably(
&mut BoardEdit::new(), // TODO?