feat(autorouter): add pointroute execution, which routes to a point

Not available as a command (for now?). Hasn't been tested yet.
This commit is contained in:
Mikolaj Wielgus 2024-10-21 23:20:00 +02:00
parent dc11b5d8ff
commit 7d75f918e7
4 changed files with 125 additions and 11 deletions

View File

@ -55,17 +55,19 @@ impl AutorouteExecutionStepper {
return Err(AutorouterError::NothingToRoute);
};
let (source, target) = autorouter.ratline_endpoints(curr_ratline);
let (origin, destination) = autorouter.ratline_endpoints(curr_ratline);
let mut router = Router::new(autorouter.board.layout_mut(), options.router_options);
let this = Self {
Ok(Self {
ratlines_iter,
options,
route: Some(router.route(source, target, options.router_options.routed_band_width)?),
route: Some(router.route(
origin,
destination,
options.router_options.routed_band_width,
)?),
curr_ratline: Some(curr_ratline),
};
Ok(this)
})
}
}

View File

@ -1,5 +1,6 @@
use derive_getters::Getters;
use petgraph::graph::EdgeIndex;
use geo::Point;
use petgraph::graph::{EdgeIndex, NodeIndex};
use serde::{Deserialize, Serialize};
use spade::InsertionError;
use thiserror::Error;
@ -17,6 +18,7 @@ use super::{
compare_detours::CompareDetoursExecutionStepper,
measure_length::MeasureLengthExecutionStepper,
place_via::PlaceViaExecutionStepper,
pointroute::PointrouteExecutionStepper,
ratsnest::{Ratsnest, RatvertexIndex},
remove_bands::RemoveBandsExecutionStepper,
selection::{BandSelection, PinSelection},
@ -56,6 +58,34 @@ impl<M: AccessMesadata> Autorouter<M> {
Ok(Self { board, ratsnest })
}
pub fn pointroute(
&mut self,
selection: &PinSelection,
point: Point,
options: AutorouterOptions,
) -> Result<PointrouteExecutionStepper, AutorouterError> {
let ratvertex = self.find_selected_ratvertex(selection).unwrap();
let origin_dot = match self
.ratsnest
.graph()
.node_weight(ratvertex)
.unwrap()
.node_index()
{
RatvertexIndex::FixedDot(dot) => dot,
RatvertexIndex::Poly(poly) => self.board.poly_apex(poly),
};
PointrouteExecutionStepper::new(self, origin_dot, point, options)
}
pub fn undo_pointroute(&mut self, band: BandTermsegIndex) -> Result<(), AutorouterError> {
self.board
.layout_mut()
.remove_band(band)
.map_err(|_| AutorouterError::CouldNotRemoveBand(band))
}
pub fn autoroute(
&mut self,
selection: &PinSelection,
@ -185,22 +215,36 @@ impl<M: AccessMesadata> Autorouter<M> {
.filter(|ratline| {
let (source, target) = self.ratsnest.graph().edge_endpoints(*ratline).unwrap();
let source_navvertex = self
let source_ratvertex = self
.ratsnest
.graph()
.node_weight(source)
.unwrap()
.node_index();
let to_navvertex = self
let to_ratvertex = self
.ratsnest
.graph()
.node_weight(target)
.unwrap()
.node_index();
selection.contains_node(&self.board, source_navvertex.into())
&& selection.contains_node(&self.board, to_navvertex.into())
selection.contains_node(&self.board, source_ratvertex.into())
&& selection.contains_node(&self.board, to_ratvertex.into())
})
.collect()
}
fn find_selected_ratvertex(&self, selection: &PinSelection) -> Option<NodeIndex<usize>> {
self.ratsnest.graph().node_indices().find(|ratvertex| {
selection.contains_node(
&self.board,
self.ratsnest
.graph()
.node_weight(*ratvertex)
.unwrap()
.node_index()
.into(),
)
})
}
}

View File

@ -8,6 +8,7 @@ pub mod history;
pub mod invoker;
pub mod measure_length;
pub mod place_via;
pub mod pointroute;
pub mod ratsnest;
pub mod remove_bands;
pub mod selection;

View File

@ -0,0 +1,67 @@
use std::ops::ControlFlow;
use geo::Point;
use crate::{
board::mesadata::AccessMesadata,
drawing::{
band::BandTermsegIndex,
dot::{FixedDotIndex, FixedDotWeight},
},
math::Circle,
router::{route::RouteStepper, Router},
stepper::Step,
};
use super::{Autorouter, AutorouterError, AutorouterOptions};
pub struct PointrouteExecutionStepper {
point: Point,
route: RouteStepper,
options: AutorouterOptions,
}
impl PointrouteExecutionStepper {
pub fn new(
autorouter: &mut Autorouter<impl AccessMesadata>,
origin: FixedDotIndex,
point: Point,
options: AutorouterOptions,
) -> Result<Self, AutorouterError> {
let destination = autorouter.board.add_fixed_dot_infringably(
FixedDotWeight {
circle: Circle {
pos: point,
r: options.router_options.routed_band_width / 2.0,
},
layer: 0,
maybe_net: None,
},
None,
);
let mut router = Router::new(autorouter.board.layout_mut(), options.router_options);
Ok(Self {
point,
route: router.route(
origin,
destination,
options.router_options.routed_band_width,
)?,
options,
})
}
}
impl<M: AccessMesadata> Step<Autorouter<M>, BandTermsegIndex> for PointrouteExecutionStepper {
type Error = AutorouterError;
fn step(
&mut self,
autorouter: &mut Autorouter<M>,
) -> Result<ControlFlow<BandTermsegIndex>, AutorouterError> {
let mut router = Router::new(autorouter.board.layout_mut(), self.options.router_options);
Ok(self.route.step(&mut router)?)
}
}