feat(topola-egui): Add sliders to set autorouting timeouts (not fully translated yet)

This commit is contained in:
Mikolaj Wielgus 2025-11-04 20:02:34 +01:00
parent 9afe862edc
commit 8216d3a907
8 changed files with 72 additions and 12 deletions

View File

@ -335,6 +335,38 @@ impl RouteActions {
&mut multilayer_autorouter_options.planar.router.wrap_around_bands,
tr.text("tr-menu-route-options-wrap-around-bands"),
);
ui.label(tr.text("tr-menu-route-options-multilayer-timeout"));
ui.add(
egui::widgets::Slider::new(
&mut multilayer_autorouter_options.timeout.initial,
0.0..=1000.0,
).text("initial")
.suffix(" s"),
);
ui.add(
egui::widgets::Slider::new(
&mut multilayer_autorouter_options.timeout.progress_bonus,
0.0..=100.0,
).text("progress bonus")
.suffix(" s/ratline"),
);
ui.label(tr.text("tr-menu-route-options-planar-timeout"));
ui.add(
egui::widgets::Slider::new(
&mut multilayer_autorouter_options.planar.timeout.initial,
0.0..=1000.0,
).text("initial")
.suffix(" s"),
);
ui.add(
egui::widgets::Slider::new(
&mut multilayer_autorouter_options.planar.timeout.progress_bonus,
0.0..=100.0,
).text("progress bonus")
.suffix(" s/length units"),
);
});
})
}

View File

@ -14,6 +14,7 @@ use topola::{
interactor::{interaction::InteractionStepper, route_plan::RoutePlan},
router::RouterOptions,
specctra::{design::SpecctraDesign, ParseError, ParseErrorContext as SpecctraLoadingError},
stepper::TimeoutOptions,
};
use crate::{
@ -62,6 +63,14 @@ impl MenuBar {
wrap_around_bands: true,
squeeze_through_under_bends: true,
},
timeout: TimeoutOptions {
initial: 1.0,
progress_bonus: 0.005,
},
},
timeout: TimeoutOptions {
initial: 5.0,
progress_bonus: 0.5,
},
},
is_placing_via: false,

View File

@ -73,6 +73,9 @@ tr-menu-route-options-wrap-around-bands = Wrap around Bands
##
tr-menu-route-options-multilayer-timeout = Multilayer Timeout
tr-menu-route-options-planar-timeout = Planar Timeout
tr-menu-inspect = Inspect
tr-menu-inspect-measure-length = Measure Length

View File

@ -24,6 +24,7 @@ use crate::{
graph::MakeRef,
layout::{via::ViaWeight, LayoutEdit, LayoutException},
router::{navmesh::NavmeshError, ng, thetastar::ThetastarError, RouterOptions},
stepper::TimeoutOptions,
triangulation::GetTrianvertexNodeIndex,
};
@ -49,6 +50,7 @@ pub struct PlanarAutorouteOptions {
pub presort_by: PresortBy,
pub permutate: bool,
pub router: RouterOptions,
pub timeout: TimeoutOptions,
}
#[derive(Error, Debug, Clone)]

View File

@ -22,7 +22,10 @@ use crate::{
drawing::graph::PrimitiveIndex,
geometry::{edit::Edit, primitive::PrimitiveShape},
router::{navcord::Navcord, navmesh::Navmesh, thetastar::ThetastarStepper},
stepper::{Abort, EstimateProgress, LinearScale, ReconfiguratorStatus, Reconfigure, Step},
stepper::{
Abort, EstimateProgress, LinearScale, ReconfiguratorStatus, Reconfigure, Step,
TimeoutOptions,
},
};
#[derive(Clone, Debug)]
@ -35,6 +38,7 @@ pub struct MultilayerAutorouteConfiguration {
pub struct MultilayerAutorouteOptions {
pub anterouter: AnterouterOptions,
pub planar: PlanarAutorouteOptions,
pub timeout: TimeoutOptions,
}
#[derive(Getters)]

View File

@ -73,7 +73,7 @@ impl MultilayerAutorouteReconfigurator {
preconfiguration,
options,
)?,
timeout: TimeVsProgressAccumulatorTimeout::new(10.0, 1.0),
timeout: TimeVsProgressAccumulatorTimeout::new_from_options(options.timeout),
reconfigurer,
options,
})
@ -85,7 +85,7 @@ impl MultilayerAutorouteReconfigurator {
) -> Result<ControlFlow<Option<BoardEdit>, MultilayerReconfiguratorStatus>, AutorouterError>
{
// Reset the reconfiguration trigger.
self.timeout = TimeVsProgressAccumulatorTimeout::new(10.0, 5.0);
self.timeout = TimeVsProgressAccumulatorTimeout::new_from_options(self.options.timeout);
loop {
let Some(configuration) = self.reconfigurer.next_configuration(autorouter) else {

View File

@ -65,7 +65,7 @@ impl PlanarAutorouteReconfigurator {
Ok(Self {
stepper: PlanarAutorouteExecutionStepper::new(autorouter, preconfiguration, options)?,
timeout: TimeVsProgressAccumulatorTimeout::new(3.0, 1.0),
timeout: TimeVsProgressAccumulatorTimeout::new_from_options(options.timeout),
// Note: I assume here that the first permutation is the same as the original order.
reconfigurer,
options,
@ -77,7 +77,7 @@ impl PlanarAutorouteReconfigurator {
autorouter: &mut Autorouter<impl AccessMesadata>,
) -> Result<ControlFlow<Option<BoardEdit>, PlanarAutorouteReconfiguratorStatus>, AutorouterError>
{
self.timeout = TimeVsProgressAccumulatorTimeout::new(3.0, 1.0);
self.timeout = TimeVsProgressAccumulatorTimeout::new_from_options(self.options.timeout);
loop {
let Some(configuration) = self
@ -112,7 +112,7 @@ impl<M: AccessMesadata> Step<Autorouter<M>, Option<BoardEdit>, PlanarAutorouteRe
{
if !self
.timeout
.update(*self.estimate_progress().value() as f64)
.update(*self.estimate_progress().subscale().value() as f64)
{
return self.reconfigure(autorouter);
}
@ -134,7 +134,6 @@ impl<M: AccessMesadata> Step<Autorouter<M>, Option<BoardEdit>, PlanarAutorouteRe
impl<M: AccessMesadata> Abort<Autorouter<M>> for PlanarAutorouteReconfigurator {
fn abort(&mut self, autorouter: &mut Autorouter<M>) {
//self.permutations_iter.all(|_| true); // Why did I add this code here???
self.stepper.abort(autorouter);
}
}

View File

@ -6,6 +6,7 @@ use core::ops::ControlFlow;
use std::time::Instant;
use derive_getters::Getters;
use serde::{Deserialize, Serialize};
/// This trait represents a linearly advanceable state whose advancement may
/// break or fail with many different return values, and to which part of
@ -115,6 +116,12 @@ pub trait GetTimeoutProgress {
fn timeout_progress(&self) -> Option<LinearScale<f64, Self::Subscale>>;
}
#[derive(Clone, Copy, Debug, Deserialize, Serialize)]
pub struct TimeoutOptions {
pub initial: f64,
pub progress_bonus: f64,
}
#[derive(Clone, Debug, Getters)]
pub struct TimeVsProgressAccumulatorTimeout {
start_instant: Instant,
@ -122,22 +129,26 @@ pub struct TimeVsProgressAccumulatorTimeout {
last_max_value: f64,
progress_accumulator: f64,
#[getter(skip)]
progress_bonus_s: f64,
progress_time_bonus_s: f64,
}
impl TimeVsProgressAccumulatorTimeout {
pub fn new(initial_timeout_s: f64, progress_bonus_s: f64) -> Self {
pub fn new(initial_timeout_value_s: f64, progress_bonus_s: f64) -> Self {
Self {
start_instant: Instant::now(),
last_max_value: 0.0,
progress_accumulator: initial_timeout_s,
progress_bonus_s,
progress_accumulator: initial_timeout_value_s,
progress_time_bonus_s: progress_bonus_s,
}
}
pub fn new_from_options(options: TimeoutOptions) -> Self {
Self::new(options.initial, options.progress_bonus)
}
pub fn update(&mut self, value: f64) -> bool {
if value > self.last_max_value {
self.progress_accumulator += (value - self.last_max_value) * self.progress_bonus_s;
self.progress_accumulator += (value - self.last_max_value) * self.progress_time_bonus_s;
self.last_max_value = value;
}