diff --git a/crates/topola-cli/src/main.rs b/crates/topola-cli/src/main.rs index 83b1c66..2107666 100644 --- a/crates/topola-cli/src/main.rs +++ b/crates/topola-cli/src/main.rs @@ -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 { diff --git a/crates/topola-egui/src/actions.rs b/crates/topola-egui/src/actions.rs index 1c333a5..2852d3b 100644 --- a/crates/topola-egui/src/actions.rs +++ b/crates/topola-egui/src/actions.rs @@ -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| { diff --git a/crates/topola-egui/src/app.rs b/crates/topola-egui/src/app.rs index 3d53d10..b3577c0 100644 --- a/crates/topola-egui/src/app.rs +++ b/crates/topola-egui/src/app.rs @@ -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); } } diff --git a/crates/topola-egui/src/appearance_panel.rs b/crates/topola-egui/src/appearance_panel.rs index 326e466..7b3355a 100644 --- a/crates/topola-egui/src/appearance_panel.rs +++ b/crates/topola-egui/src/appearance_panel.rs @@ -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, } impl AppearancePanel { @@ -20,13 +21,15 @@ impl AppearancePanel { let visible = core::iter::repeat(true) .take(layer_count) .collect::>(); - Self { - visible, - active_layer: Some(0), - } + Self { visible } } - pub fn update(&mut self, ctx: &Context, board: &Board) { + pub fn update( + &mut self, + ctx: &Context, + board: &Board, + 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 { diff --git a/crates/topola-egui/src/displayer.rs b/crates/topola-egui/src/displayer.rs index 6e7661c..3c71061 100644 --- a/crates/topola-egui/src/displayer.rs +++ b/crates/topola-egui/src/displayer.rs @@ -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,34 +571,35 @@ 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) { - let pos = primitive - .primitive_ref(board.layout().drawing()) - .shape() - .center(); + 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() - { - if activity.obstacles().contains(&primitive) { - egui::Color32::from_rgb(255, 255, 255) - } else { - egui::Color32::from_rgb(150, 150, 150) - } - } else { + 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 { + egui::Color32::from_rgb(150, 150, 150) + } + } else { + egui::Color32::from_rgb(255, 255, 255) + }; - self.painter.paint_text( - pos, - egui::Align2::CENTER_CENTER, - &format!("{}", primitive.index()), - color, - ); - } + self.painter.paint_text( + pos, + egui::Align2::CENTER_CENTER, + &format!("{}", primitive.index()), + color, + ); } } } diff --git a/crates/topola-egui/src/menu_bar.rs b/crates/topola-egui/src/menu_bar.rs index ccd78b4..be47271 100644 --- a/crates/topola-egui/src/menu_bar.rs +++ b/crates/topola-egui/src/menu_bar.rs @@ -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, - ); - } + workspace.overlay.recalculate_topo_navmesh( + workspace.interactor.invoker().autorouter(), + 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 - .interactor - .invoker() - .autorouter() - .board() - .layout() - .rules() - .layer_layername(active_layer) - .expect("unknown active layer") - .to_string(); - schedule(error_dialog, workspace, |selection| { - Command::TopoAutoroute { - selection: selection.pin_selection, - allowed_edges: BTreeSet::new(), - active_layer, - routed_band_width: self - .multilayer_autorouter_options - .planar - .router - .routed_band_width, - } - }); - } + let active_layer_name = workspace + .interactor + .invoker() + .autorouter() + .board() + .layout() + .rules() + .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_name, + routed_band_width: self + .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,12 +387,12 @@ 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), - )); - } + self.is_placing_via = false; + workspace.interactor.interact(InteractionStepper::RoutePlan( + RoutePlan::new( + self.multilayer_autoroute_options.planar.principal_layer, + ), + )); } } } diff --git a/crates/topola-egui/src/viewport.rs b/crates/topola-egui/src/viewport.rs index 1aa11a8..253d495 100644 --- a/crates/topola-egui/src/viewport.rs +++ b/crates/topola-egui/src/viewport.rs @@ -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), }; diff --git a/crates/topola-egui/src/workspace.rs b/crates/topola-egui/src/workspace.rs index 43d1770..cb6fd9b 100644 --- a/crates/topola-egui/src/workspace.rs +++ b/crates/topola-egui/src/workspace.rs @@ -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); } } diff --git a/src/autorouter/autorouter.rs b/src/autorouter/autorouter.rs index 71f4544..b99fc0b 100644 --- a/src/autorouter/autorouter.rs +++ b/src/autorouter/autorouter.rs @@ -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 Autorouter { &mut self, selection: &PinSelection, point: Point, - options: AutorouterOptions, + options: PlanarAutorouteOptions, ) -> Result { let ratvertex = self.find_selected_ratvertex(selection).unwrap(); let origin_dot = match self @@ -114,7 +115,7 @@ impl Autorouter { pub fn multilayer_autoroute( &mut self, selection: &PinSelection, - options: MultilayerAutorouterOptions, + options: MultilayerAutorouteOptions, ) -> Result { let planner = Planner::new(self, &self.selected_ratlines(selection)); @@ -129,7 +130,7 @@ impl Autorouter { pub fn planar_autoroute( &mut self, selection: &PinSelection, - options: AutorouterOptions, + options: PlanarAutorouteOptions, ) -> Result { PlanarAutorouteExecutionPermutator::new(self, self.selected_ratlines(selection), options) } @@ -137,7 +138,7 @@ impl Autorouter { pub(super) fn planar_autoroute_ratlines( &mut self, ratlines: Vec, - options: AutorouterOptions, + options: PlanarAutorouteOptions, ) -> Result { PlanarAutorouteExecutionStepper::new(self, ratlines, options) } @@ -278,7 +279,7 @@ impl Autorouter { pub fn compare_detours( &mut self, selection: &PinSelection, - options: AutorouterOptions, + options: PlanarAutorouteOptions, ) -> Result { let ratlines = self.selected_ratlines(selection); if ratlines.len() < 2 { @@ -291,7 +292,7 @@ impl Autorouter { &mut self, ratline1: RatlineIndex, ratline2: RatlineIndex, - options: AutorouterOptions, + options: PlanarAutorouteOptions, ) -> Result { CompareDetoursExecutionStepper::new(self, ratline1, ratline2, options) } diff --git a/src/autorouter/compare_detours.rs b/src/autorouter/compare_detours.rs index ee65a2d..e479b54 100644 --- a/src/autorouter/compare_detours.rs +++ b/src/autorouter/compare_detours.rs @@ -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, ratline1: RatlineIndex, ratline2: RatlineIndex, - options: AutorouterOptions, + options: PlanarAutorouteOptions, ) -> Result { Ok(Self { autoroute: autorouter.planar_autoroute_ratlines(vec![ratline1, ratline2], options)?, diff --git a/src/autorouter/execution.rs b/src/autorouter/execution.rs index 55d6324..528ae58 100644 --- a/src/autorouter/execution.rs +++ b/src/autorouter/execution.rs @@ -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), } diff --git a/src/autorouter/multilayer_autoroute.rs b/src/autorouter/multilayer_autoroute.rs index 6564874..62e8e33 100644 --- a/src/autorouter/multilayer_autoroute.rs +++ b/src/autorouter/multilayer_autoroute.rs @@ -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, ratlines: Vec, plan: AnterouterPlan, - options: MultilayerAutorouterOptions, + options: MultilayerAutorouteOptions, ) -> Result { let mut assigner = Anterouter::new(plan); assigner.anteroute(autorouter, &options.anterouter); diff --git a/src/autorouter/permutator.rs b/src/autorouter/permutator.rs index f73ebbc..bf00d2f 100644 --- a/src/autorouter/permutator.rs +++ b/src/autorouter/permutator.rs @@ -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, ratlines: Vec, - options: AutorouterOptions, + options: PlanarAutorouteOptions, ) -> Result { let presorter = SccIntersectionsAndLengthPresorter::new( autorouter, diff --git a/src/autorouter/permuter.rs b/src/autorouter/permuter.rs index 70497d0..6ae6075 100644 --- a/src/autorouter/permuter.rs +++ b/src/autorouter/permuter.rs @@ -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, ratlines: Vec, presorter: SccIntersectionsAndLengthPresorter, - options: &AutorouterOptions, + options: &PlanarAutorouteOptions, ) -> Self { RatlinesPermuter::SccPermutations(SccPermutationsRatlinePermuter::new( autorouter, ratlines, presorter, options, @@ -60,7 +60,7 @@ impl SccPermutationsRatlinePermuter { _autorouter: &mut Autorouter, ratlines: Vec, 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, _ratlines: Vec, _presorter: SccIntersectionsAndLengthPresorter, - _options: &AutorouterOptions, + _options: &PlanarAutorouteOptions, ) -> Self { /*Self { sccs: presorter.dissolve(), diff --git a/src/autorouter/planar_autoroute.rs b/src/autorouter/planar_autoroute.rs index 82575ac..66899dd 100644 --- a/src/autorouter/planar_autoroute.rs +++ b/src/autorouter/planar_autoroute.rs @@ -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, /// 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, ratlines: Vec, - options: AutorouterOptions, + options: PlanarAutorouteOptions, ) -> Result { if ratlines.is_empty() { return Err(AutorouterError::NothingToRoute); diff --git a/src/autorouter/pointroute.rs b/src/autorouter/pointroute.rs index 0e33ebe..1cf0801 100644 --- a/src/autorouter/pointroute.rs +++ b/src/autorouter/pointroute.rs @@ -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, origin: FixedDotIndex, point: Point, - options: AutorouterOptions, + options: PlanarAutorouteOptions, ) -> Result { let destination = autorouter.board.add_fixed_dot_infringably( &mut BoardEdit::new(), // TODO?