mirror of https://codeberg.org/topola/topola.git
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:
parent
dc11b5d8ff
commit
7d75f918e7
|
|
@ -55,17 +55,19 @@ impl AutorouteExecutionStepper {
|
||||||
return Err(AutorouterError::NothingToRoute);
|
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 mut router = Router::new(autorouter.board.layout_mut(), options.router_options);
|
||||||
|
|
||||||
let this = Self {
|
Ok(Self {
|
||||||
ratlines_iter,
|
ratlines_iter,
|
||||||
options,
|
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),
|
curr_ratline: Some(curr_ratline),
|
||||||
};
|
})
|
||||||
|
|
||||||
Ok(this)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
use derive_getters::Getters;
|
use derive_getters::Getters;
|
||||||
use petgraph::graph::EdgeIndex;
|
use geo::Point;
|
||||||
|
use petgraph::graph::{EdgeIndex, NodeIndex};
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use spade::InsertionError;
|
use spade::InsertionError;
|
||||||
use thiserror::Error;
|
use thiserror::Error;
|
||||||
|
|
@ -17,6 +18,7 @@ use super::{
|
||||||
compare_detours::CompareDetoursExecutionStepper,
|
compare_detours::CompareDetoursExecutionStepper,
|
||||||
measure_length::MeasureLengthExecutionStepper,
|
measure_length::MeasureLengthExecutionStepper,
|
||||||
place_via::PlaceViaExecutionStepper,
|
place_via::PlaceViaExecutionStepper,
|
||||||
|
pointroute::PointrouteExecutionStepper,
|
||||||
ratsnest::{Ratsnest, RatvertexIndex},
|
ratsnest::{Ratsnest, RatvertexIndex},
|
||||||
remove_bands::RemoveBandsExecutionStepper,
|
remove_bands::RemoveBandsExecutionStepper,
|
||||||
selection::{BandSelection, PinSelection},
|
selection::{BandSelection, PinSelection},
|
||||||
|
|
@ -56,6 +58,34 @@ impl<M: AccessMesadata> Autorouter<M> {
|
||||||
Ok(Self { board, ratsnest })
|
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(
|
pub fn autoroute(
|
||||||
&mut self,
|
&mut self,
|
||||||
selection: &PinSelection,
|
selection: &PinSelection,
|
||||||
|
|
@ -185,22 +215,36 @@ impl<M: AccessMesadata> Autorouter<M> {
|
||||||
.filter(|ratline| {
|
.filter(|ratline| {
|
||||||
let (source, target) = self.ratsnest.graph().edge_endpoints(*ratline).unwrap();
|
let (source, target) = self.ratsnest.graph().edge_endpoints(*ratline).unwrap();
|
||||||
|
|
||||||
let source_navvertex = self
|
let source_ratvertex = self
|
||||||
.ratsnest
|
.ratsnest
|
||||||
.graph()
|
.graph()
|
||||||
.node_weight(source)
|
.node_weight(source)
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.node_index();
|
.node_index();
|
||||||
let to_navvertex = self
|
let to_ratvertex = self
|
||||||
.ratsnest
|
.ratsnest
|
||||||
.graph()
|
.graph()
|
||||||
.node_weight(target)
|
.node_weight(target)
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.node_index();
|
.node_index();
|
||||||
|
|
||||||
selection.contains_node(&self.board, source_navvertex.into())
|
selection.contains_node(&self.board, source_ratvertex.into())
|
||||||
&& selection.contains_node(&self.board, to_navvertex.into())
|
&& selection.contains_node(&self.board, to_ratvertex.into())
|
||||||
})
|
})
|
||||||
.collect()
|
.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(),
|
||||||
|
)
|
||||||
|
})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -8,6 +8,7 @@ pub mod history;
|
||||||
pub mod invoker;
|
pub mod invoker;
|
||||||
pub mod measure_length;
|
pub mod measure_length;
|
||||||
pub mod place_via;
|
pub mod place_via;
|
||||||
|
pub mod pointroute;
|
||||||
pub mod ratsnest;
|
pub mod ratsnest;
|
||||||
pub mod remove_bands;
|
pub mod remove_bands;
|
||||||
pub mod selection;
|
pub mod selection;
|
||||||
|
|
|
||||||
|
|
@ -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)?)
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue