egui,autorouter,router: add option to toggle wrapping around bands

This commit is contained in:
Mikolaj Wielgus 2024-08-31 14:12:38 +02:00
parent 4d0c38664e
commit 0b7e5f1b9b
7 changed files with 53 additions and 22 deletions

View File

@ -18,6 +18,7 @@ action-undo = Undo
action-redo = Redo action-redo = Redo
presort-by-pairwise-detours = Presort by pairwise detours presort-by-pairwise-detours = Presort by pairwise detours
wrap-around-bands = Wrap around bands
show-ratsnest = Show Ratsnest show-ratsnest = Show Ratsnest
show-navmesh = Show Navmesh show-navmesh = Show Navmesh

View File

@ -50,7 +50,7 @@ impl Autoroute {
}; };
let (source, target) = autorouter.ratline_endpoints(curr_ratline); let (source, target) = autorouter.ratline_endpoints(curr_ratline);
let mut router = Router::new(autorouter.board.layout_mut()); let mut router = Router::new(autorouter.board.layout_mut(), options.router_options);
let this = Self { let this = Self {
ratlines_iter, ratlines_iter,
@ -77,7 +77,8 @@ impl<M: AccessMesadata> Step<Autorouter<M>, AutorouteStatus, AutorouterError, ()
let (source, target) = autorouter.ratline_endpoints(curr_ratline); let (source, target) = autorouter.ratline_endpoints(curr_ratline);
let band_termseg = { let band_termseg = {
let mut router = Router::new(autorouter.board.layout_mut()); let mut router =
Router::new(autorouter.board.layout_mut(), self.options.router_options);
let RouterStatus::Finished(band_termseg) = route.step(&mut router)? else { let RouterStatus::Finished(band_termseg) = route.step(&mut router)? else {
return Ok(AutorouteStatus::Running); return Ok(AutorouteStatus::Running);
@ -102,7 +103,8 @@ impl<M: AccessMesadata> Step<Autorouter<M>, AutorouteStatus, AutorouterError, ()
if let Some(new_ratline) = self.ratlines_iter.next() { if let Some(new_ratline) = self.ratlines_iter.next() {
let (source, target) = autorouter.ratline_endpoints(new_ratline); let (source, target) = autorouter.ratline_endpoints(new_ratline);
let mut router = Router::new(autorouter.board.layout_mut()); let mut router =
Router::new(autorouter.board.layout_mut(), self.options.router_options);
self.curr_ratline = Some(new_ratline); self.curr_ratline = Some(new_ratline);
self.route = Some(router.route(source, target, 100.0)?); self.route = Some(router.route(source, target, 100.0)?);

View File

@ -11,7 +11,7 @@ use crate::{
Infringement, Infringement,
}, },
layout::via::ViaWeight, layout::via::ViaWeight,
router::{navmesh::NavmeshError, RouterError}, router::{navmesh::NavmeshError, RouterError, RouterOptions},
triangulation::GetTrianvertexNodeIndex, triangulation::GetTrianvertexNodeIndex,
}; };
@ -28,16 +28,14 @@ use super::{
#[derive(Debug, Clone, Copy, Serialize, Deserialize)] #[derive(Debug, Clone, Copy, Serialize, Deserialize)]
pub struct AutorouterOptions { pub struct AutorouterOptions {
pub presort_by_pairwise_detours: bool, pub presort_by_pairwise_detours: bool,
//pub wrap_around_bands: bool, pub router_options: RouterOptions,
//pub squeeze_under_bands: bool,
} }
impl AutorouterOptions { impl AutorouterOptions {
pub fn new() -> Self { pub fn new() -> Self {
Self { Self {
presort_by_pairwise_detours: false, presort_by_pairwise_detours: false,
//wrap_around_bands: true, router_options: RouterOptions::new(),
//squeeze_under_bands: true,
} }
} }
} }

View File

@ -142,6 +142,10 @@ impl Top {
&mut self.autorouter_options.presort_by_pairwise_detours, &mut self.autorouter_options.presort_by_pairwise_detours,
tr.text("presort-by-pairwise-detours"), tr.text("presort-by-pairwise-detours"),
); );
ui.checkbox(
&mut self.autorouter_options.router_options.wrap_around_bands,
tr.text("wrap-around-bands"),
);
}); });
ui.separator(); ui.separator();

View File

@ -31,6 +31,8 @@ use crate::{
triangulation::{GetTrianvertexNodeIndex, Triangulation}, triangulation::{GetTrianvertexNodeIndex, Triangulation},
}; };
use super::RouterOptions;
#[derive(Debug, Hash, Clone, Copy, PartialEq, Eq)] #[derive(Debug, Hash, Clone, Copy, PartialEq, Eq)]
pub struct NavvertexIndex(NodeIndex<usize>); pub struct NavvertexIndex(NodeIndex<usize>);
@ -129,6 +131,7 @@ impl Navmesh {
layout: &Layout<impl AccessRules>, layout: &Layout<impl AccessRules>,
origin: FixedDotIndex, origin: FixedDotIndex,
destination: FixedDotIndex, destination: FixedDotIndex,
options: RouterOptions,
) -> Result<Self, NavmeshError> { ) -> Result<Self, NavmeshError> {
let mut triangulation: Triangulation<TrianvertexNodeIndex, TrianvertexWeight, ()> = let mut triangulation: Triangulation<TrianvertexNodeIndex, TrianvertexWeight, ()> =
Triangulation::new(layout.drawing().geometry().graph().node_bound()); Triangulation::new(layout.drawing().geometry().graph().node_bound());
@ -163,7 +166,7 @@ impl Navmesh {
} }
} }
Self::new_from_triangulation(layout, triangulation, origin, destination) Self::new_from_triangulation(layout, triangulation, origin, destination, options)
} }
fn new_from_triangulation( fn new_from_triangulation(
@ -171,6 +174,7 @@ impl Navmesh {
triangulation: Triangulation<TrianvertexNodeIndex, TrianvertexWeight, ()>, triangulation: Triangulation<TrianvertexNodeIndex, TrianvertexWeight, ()>,
origin: FixedDotIndex, origin: FixedDotIndex,
destination: FixedDotIndex, destination: FixedDotIndex,
options: RouterOptions,
) -> Result<Self, NavmeshError> { ) -> Result<Self, NavmeshError> {
let mut graph: UnGraph<NavvertexWeight, (), usize> = UnGraph::default(); let mut graph: UnGraph<NavvertexWeight, (), usize> = UnGraph::default();
let mut origin_navvertex = None; let mut origin_navvertex = None;
@ -205,17 +209,19 @@ impl Navmesh {
trianvertex.into(), trianvertex.into(),
); );
let mut gear = if options.wrap_around_bands {
Into::<GearIndex>::into(Into::<BinavvertexNodeIndex>::into(trianvertex)); let mut gear =
Into::<GearIndex>::into(Into::<BinavvertexNodeIndex>::into(trianvertex));
while let Some(bend) = gear.ref_(layout.drawing()).next_gear() { while let Some(bend) = gear.ref_(layout.drawing()).next_gear() {
Self::add_node_to_graph_and_map_as_binavvertex( Self::add_node_to_graph_and_map_as_binavvertex(
&mut graph, &mut graph,
&mut map, &mut map,
trianvertex, trianvertex,
bend.into(), bend.into(),
); );
gear = bend.into(); gear = bend.into();
}
} }
}; };
} }

View File

@ -27,7 +27,7 @@ impl Route {
to: FixedDotIndex, to: FixedDotIndex,
width: f64, width: f64,
) -> Result<Self, RouterError> { ) -> Result<Self, RouterError> {
let navmesh = Navmesh::new(router.layout(), from, to)?; let navmesh = Navmesh::new(router.layout(), from, to, router.options())?;
Ok(Self::new_from_navmesh(router, navmesh, width)) Ok(Self::new_from_navmesh(router, navmesh, width))
} }

View File

@ -2,6 +2,7 @@ use std::convert::Infallible;
use geo::EuclideanDistance; use geo::EuclideanDistance;
use petgraph::{data::DataMap, visit::EdgeRef}; use petgraph::{data::DataMap, visit::EdgeRef};
use serde::{Deserialize, Serialize};
use thiserror::Error; use thiserror::Error;
use crate::{ use crate::{
@ -32,6 +33,20 @@ use super::{
tracer::{Tracer, TracerException}, tracer::{Tracer, TracerException},
}; };
#[derive(Debug, Clone, Copy, Serialize, Deserialize)]
pub struct RouterOptions {
pub wrap_around_bands: bool,
//pub squeeze_under_bands: bool,
}
impl RouterOptions {
pub fn new() -> Self {
Self {
wrap_around_bands: true,
}
}
}
#[derive(Error, Debug, Clone)] #[derive(Error, Debug, Clone)]
#[error("routing failed")] #[error("routing failed")]
pub enum RouterError { pub enum RouterError {
@ -182,11 +197,12 @@ impl<'a, R: AccessRules> AstarStrategy<Navmesh, f64, BandTermsegIndex>
#[derive(Debug)] #[derive(Debug)]
pub struct Router<'a, R: AccessRules> { pub struct Router<'a, R: AccessRules> {
layout: &'a mut Layout<R>, layout: &'a mut Layout<R>,
options: RouterOptions,
} }
impl<'a, R: AccessRules> Router<'a, R> { impl<'a, R: AccessRules> Router<'a, R> {
pub fn new(layout: &'a mut Layout<R>) -> Self { pub fn new(layout: &'a mut Layout<R>, options: RouterOptions) -> Self {
Self { layout } Self { layout, options }
} }
pub fn route( pub fn route(
@ -205,4 +221,8 @@ impl<'a, R: AccessRules> Router<'a, R> {
pub fn layout(&self) -> &Layout<R> { pub fn layout(&self) -> &Layout<R> {
&self.layout &self.layout
} }
pub fn options(&self) -> RouterOptions {
self.options
}
} }