autorouter: create new command: Remove Selected Bands

This commit is contained in:
Mikolaj Wielgus 2024-07-25 01:46:54 +02:00
parent b568f2d790
commit fcffb76de4
9 changed files with 147 additions and 7 deletions

View File

@ -14,6 +14,7 @@ use super::{
autoroute::Autoroute, autoroute::Autoroute,
place_via::PlaceVia, place_via::PlaceVia,
ratsnest::{Ratsnest, RatvertexIndex}, ratsnest::{Ratsnest, RatvertexIndex},
remove_bands::RemoveBands,
selection::{BandSelection, PinSelection}, selection::{BandSelection, PinSelection},
}; };
@ -89,7 +90,27 @@ impl<M: AccessMesadata> Autorouter<M> {
PlaceVia::new(weight) PlaceVia::new(weight)
} }
pub fn undo_place_via(&mut self, weight: ViaWeight) { pub fn undo_place_via(&mut self, _weight: ViaWeight) {
todo!();
}
pub fn remove_bands(&mut self, selection: &BandSelection) -> Result<(), AutorouterError> {
for selector in selection.selectors() {
let band = self.board.bandname_band(selector.band.clone()).unwrap().0;
self.board.layout_mut().remove_band(band);
}
Ok(())
}
pub fn remove_bands_walk(
&self,
selection: &BandSelection,
) -> Result<RemoveBands, AutorouterError> {
RemoveBands::new(selection)
}
pub fn undo_remove_bands(&mut self, _selection: &BandSelection) {
todo!(); todo!();
} }

View File

@ -15,6 +15,7 @@ use super::{
autoroute::Autoroute, autoroute::Autoroute,
history::{History, HistoryError}, history::{History, HistoryError},
place_via::PlaceVia, place_via::PlaceVia,
remove_bands::RemoveBands,
selection::{BandSelection, PinSelection}, selection::{BandSelection, PinSelection},
Autorouter, AutorouterError, AutorouterStatus, Autorouter, AutorouterError, AutorouterStatus,
}; };
@ -57,12 +58,14 @@ pub enum InvokerStatus {
pub enum Command { pub enum Command {
Autoroute(PinSelection), Autoroute(PinSelection),
PlaceVia(ViaWeight), PlaceVia(ViaWeight),
RemoveBands(BandSelection),
} }
#[enum_dispatch(GetMaybeNavmesh, GetMaybeTrace, GetGhosts, GetObstacles)] #[enum_dispatch(GetMaybeNavmesh, GetMaybeTrace, GetGhosts, GetObstacles)]
pub enum Execute { pub enum Execute {
Autoroute(Autoroute), Autoroute(Autoroute),
PlaceVia(PlaceVia), PlaceVia(PlaceVia),
RemoveBands(RemoveBands),
} }
impl Execute { impl Execute {
@ -99,6 +102,10 @@ impl Execute {
place_via.doit(&mut invoker.autorouter)?; place_via.doit(&mut invoker.autorouter)?;
Ok(InvokerStatus::Finished) Ok(InvokerStatus::Finished)
} }
Execute::RemoveBands(remove_bands) => {
remove_bands.doit(&mut invoker.autorouter)?;
Ok(InvokerStatus::Finished)
}
} }
} }
} }
@ -210,6 +217,9 @@ impl<M: AccessMesadata> Invoker<M> {
Command::PlaceVia(weight) => Ok::<Execute, InvokerError>(Execute::PlaceVia( Command::PlaceVia(weight) => Ok::<Execute, InvokerError>(Execute::PlaceVia(
self.autorouter.place_via_walk(*weight)?, self.autorouter.place_via_walk(*weight)?,
)), )),
Command::RemoveBands(selection) => Ok::<Execute, InvokerError>(Execute::RemoveBands(
self.autorouter.remove_bands_walk(selection)?,
)),
} }
} }
@ -220,6 +230,7 @@ impl<M: AccessMesadata> Invoker<M> {
match command { match command {
Command::Autoroute(ref selection) => self.autorouter.undo_autoroute(selection), Command::Autoroute(ref selection) => self.autorouter.undo_autoroute(selection),
Command::PlaceVia(weight) => self.autorouter.undo_place_via(*weight), Command::PlaceVia(weight) => self.autorouter.undo_place_via(*weight),
Command::RemoveBands(ref selection) => self.autorouter.undo_remove_bands(selection),
} }
Ok::<(), InvokerError>(self.history.undo()?) Ok::<(), InvokerError>(self.history.undo()?)

View File

@ -4,6 +4,7 @@ pub mod history;
pub mod invoker; pub mod invoker;
pub mod place_via; pub mod place_via;
pub mod ratsnest; pub mod ratsnest;
pub mod remove_bands;
pub mod selection; pub mod selection;
pub use autorouter::*; pub use autorouter::*;

View File

@ -14,18 +14,27 @@ use super::{
#[derive(Debug)] #[derive(Debug)]
pub struct PlaceVia { pub struct PlaceVia {
weight: ViaWeight, weight: ViaWeight,
done: bool,
} }
impl PlaceVia { impl PlaceVia {
pub fn new(weight: ViaWeight) -> Result<Self, AutorouterError> { pub fn new(weight: ViaWeight) -> Result<Self, AutorouterError> {
Ok(Self { weight }) Ok(Self {
weight,
done: false,
})
} }
pub fn doit( pub fn doit(
&mut self, &mut self,
autorouter: &mut Autorouter<impl AccessMesadata>, autorouter: &mut Autorouter<impl AccessMesadata>,
) -> Result<(), AutorouterError> { ) -> Result<(), AutorouterError> {
if !self.done {
self.done = true;
autorouter.place_via(self.weight) autorouter.place_via(self.weight)
} else {
Ok(())
}
} }
} }

View File

@ -0,0 +1,63 @@
use crate::{
board::mesadata::AccessMesadata,
drawing::graph::PrimitiveIndex,
geometry::primitive::PrimitiveShape,
router::{navmesh::Navmesh, trace::Trace},
};
use super::{
invoker::{GetGhosts, GetMaybeNavmesh, GetMaybeTrace, GetObstacles},
selection::BandSelection,
Autorouter, AutorouterError,
};
#[derive(Debug)]
pub struct RemoveBands {
selection: BandSelection,
done: bool,
}
impl RemoveBands {
pub fn new(selection: &BandSelection) -> Result<Self, AutorouterError> {
Ok(Self {
selection: selection.clone(),
done: false,
})
}
pub fn doit(
&mut self,
autorouter: &mut Autorouter<impl AccessMesadata>,
) -> Result<(), AutorouterError> {
if !self.done {
self.done = true;
autorouter.remove_bands(&self.selection)
} else {
Ok(())
}
}
}
impl GetMaybeNavmesh for RemoveBands {
fn maybe_navmesh(&self) -> Option<&Navmesh> {
None
}
}
impl GetMaybeTrace for RemoveBands {
fn maybe_trace(&self) -> Option<&Trace> {
None
}
}
impl GetGhosts for RemoveBands {
fn ghosts(&self) -> &[PrimitiveShape] {
&[]
}
}
impl GetObstacles for RemoveBands {
fn obstacles(&self) -> &[PrimitiveIndex] {
&[]
}
}

View File

@ -15,8 +15,8 @@ use crate::{
#[derive(Debug, Clone, Hash, Eq, PartialEq, Serialize, Deserialize)] #[derive(Debug, Clone, Hash, Eq, PartialEq, Serialize, Deserialize)]
pub struct PinSelector { pub struct PinSelector {
pin: String, pub pin: String,
layer: String, pub layer: String,
} }
#[derive(Debug, Clone, Serialize, Deserialize)] #[derive(Debug, Clone, Serialize, Deserialize)]
@ -78,11 +78,15 @@ impl PinSelection {
self.node_selector(board, node) self.node_selector(board, node)
.map_or(false, |selector| self.selectors.contains(&selector)) .map_or(false, |selector| self.selectors.contains(&selector))
} }
pub fn selectors(&self) -> impl Iterator<Item = &PinSelector> {
self.selectors.iter()
}
} }
#[derive(Debug, Clone, Hash, Eq, PartialEq, Serialize, Deserialize)] #[derive(Debug, Clone, Hash, Eq, PartialEq, Serialize, Deserialize)]
pub struct BandSelector { pub struct BandSelector {
band: BandName, pub band: BandName,
} }
#[derive(Debug, Clone, Serialize, Deserialize)] #[derive(Debug, Clone, Serialize, Deserialize)]
@ -133,6 +137,10 @@ impl BandSelection {
self.node_selector(board, node) self.node_selector(board, node)
.map_or(false, |selector| self.selectors.contains(&selector)) .map_or(false, |selector| self.selectors.contains(&selector))
} }
pub fn selectors(&self) -> impl Iterator<Item = &BandSelector> {
self.selectors.iter()
}
} }
#[derive(Debug, Clone, Serialize, Deserialize)] #[derive(Debug, Clone, Serialize, Deserialize)]

View File

@ -75,6 +75,11 @@ impl Top {
egui::Modifiers::CTRL, egui::Modifiers::CTRL,
egui::Key::P, egui::Key::P,
)); ));
let mut remove_bands = Trigger::new(Action::new(
"Remove Selected Bands",
egui::Modifiers::NONE,
egui::Key::Delete,
));
let mut undo = Trigger::new(Action::new("Undo", egui::Modifiers::CTRL, egui::Key::Z)); let mut undo = Trigger::new(Action::new("Undo", egui::Modifiers::CTRL, egui::Key::Z));
let mut redo = Trigger::new(Action::new("Redo", egui::Modifiers::CTRL, egui::Key::Y)); let mut redo = Trigger::new(Action::new("Redo", egui::Modifiers::CTRL, egui::Key::Y));
@ -104,6 +109,8 @@ impl Top {
place_via.toggle_widget(ctx, ui, &mut self.is_placing_via); place_via.toggle_widget(ctx, ui, &mut self.is_placing_via);
remove_bands.button(ctx, ui);
ui.separator(); ui.separator();
undo.button(ctx, ui); undo.button(ctx, ui);
@ -213,6 +220,22 @@ impl Top {
} }
} }
} else if place_via.consume_key_enabled(ctx, ui, &mut self.is_placing_via) { } else if place_via.consume_key_enabled(ctx, ui, &mut self.is_placing_via) {
} else if remove_bands.consume_key_triggered(ctx, ui) {
if maybe_execute.as_mut().map_or(true, |execute| {
matches!(execute.maybe_status(), Some(InvokerStatus::Finished))
}) {
if let (Some(invoker), Some(ref mut overlay)) = (
arc_mutex_maybe_invoker.lock().unwrap().as_mut(),
maybe_overlay,
) {
let selection = overlay.selection().clone();
overlay.clear_selection();
maybe_execute
.insert(ExecuteWithStatus::new(invoker.execute_walk(
Command::RemoveBands(selection.band_selection),
)?));
}
}
} else if undo.consume_key_triggered(ctx, ui) { } else if undo.consume_key_triggered(ctx, ui) {
if let Some(invoker) = arc_mutex_maybe_invoker.lock().unwrap().as_mut() { if let Some(invoker) = arc_mutex_maybe_invoker.lock().unwrap().as_mut() {
invoker.undo(); invoker.undo();

View File

@ -156,6 +156,10 @@ impl<M: AccessMesadata> Board<M> {
self.band_bandname.get_by_left(&band) self.band_bandname.get_by_left(&band)
} }
pub fn bandname_band(&self, bandname: BandName) -> Option<&BandUid> {
self.band_bandname.get_by_right(&bandname)
}
pub fn try_set_band_between_nodes( pub fn try_set_band_between_nodes(
&mut self, &mut self,
source: FixedDotIndex, source: FixedDotIndex,

View File

@ -16,7 +16,7 @@ use super::{
}; };
#[derive(Debug, Hash, Clone, Copy)] #[derive(Debug, Hash, Clone, Copy)]
pub struct BandUid(BandTermsegIndex, BandTermsegIndex); pub struct BandUid(pub BandTermsegIndex, pub BandTermsegIndex);
impl BandUid { impl BandUid {
pub fn new(first_seg1: BandTermsegIndex, first_seg2: BandTermsegIndex) -> Self { pub fn new(first_seg1: BandTermsegIndex, first_seg2: BandTermsegIndex) -> Self {