mirror of https://codeberg.org/topola/topola.git
router,autorouter: stop hiding layout behind an arc-mutex
This was preventing us from creating a new abstraction layer over layout.
This commit is contained in:
parent
dcbc5be5f3
commit
b22e3dce1a
|
|
@ -54,7 +54,7 @@ pub struct Autoroute {
|
||||||
impl Autoroute {
|
impl Autoroute {
|
||||||
pub fn new(
|
pub fn new(
|
||||||
ratlines: impl IntoIterator<Item = EdgeIndex<usize>> + 'static,
|
ratlines: impl IntoIterator<Item = EdgeIndex<usize>> + 'static,
|
||||||
autorouter: &Autorouter<impl RulesTrait>,
|
autorouter: &mut Autorouter<impl RulesTrait>,
|
||||||
) -> Result<Self, AutorouterError> {
|
) -> Result<Self, AutorouterError> {
|
||||||
let mut ratlines_iter = Box::new(ratlines.into_iter());
|
let mut ratlines_iter = Box::new(ratlines.into_iter());
|
||||||
|
|
||||||
|
|
@ -63,8 +63,7 @@ impl Autoroute {
|
||||||
};
|
};
|
||||||
|
|
||||||
let (source, target) = Self::ratline_endpoints(autorouter, cur_ratline);
|
let (source, target) = Self::ratline_endpoints(autorouter, cur_ratline);
|
||||||
let layout = autorouter.layout.lock().unwrap();
|
let navmesh = Some(Navmesh::new(&autorouter.layout, source, target)?);
|
||||||
let navmesh = Some(Navmesh::new(&layout, source, target)?);
|
|
||||||
|
|
||||||
let this = Self {
|
let this = Self {
|
||||||
ratlines_iter,
|
ratlines_iter,
|
||||||
|
|
@ -83,9 +82,12 @@ impl Autoroute {
|
||||||
let (new_navmesh, new_ratline) = if let Some(cur_ratline) = self.ratlines_iter.next() {
|
let (new_navmesh, new_ratline) = if let Some(cur_ratline) = self.ratlines_iter.next() {
|
||||||
let (source, target) = Self::ratline_endpoints(autorouter, cur_ratline);
|
let (source, target) = Self::ratline_endpoints(autorouter, cur_ratline);
|
||||||
|
|
||||||
let layout = autorouter.layout.lock().unwrap();
|
|
||||||
(
|
(
|
||||||
Some(Navmesh::new(&layout, source, target).ok().unwrap()),
|
Some(
|
||||||
|
Navmesh::new(&autorouter.layout, source, target)
|
||||||
|
.ok()
|
||||||
|
.unwrap(),
|
||||||
|
),
|
||||||
Some(cur_ratline),
|
Some(cur_ratline),
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -115,10 +117,9 @@ impl Autoroute {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn ratline_endpoints<R: RulesTrait>(
|
fn ratline_endpoints<R: RulesTrait>(
|
||||||
autorouter: &Autorouter<R>,
|
autorouter: &mut Autorouter<R>,
|
||||||
ratline: EdgeIndex<usize>,
|
ratline: EdgeIndex<usize>,
|
||||||
) -> (FixedDotIndex, FixedDotIndex) {
|
) -> (FixedDotIndex, FixedDotIndex) {
|
||||||
let mut layout = autorouter.layout.lock().unwrap();
|
|
||||||
let (source, target) = autorouter.ratsnest.graph().edge_endpoints(ratline).unwrap();
|
let (source, target) = autorouter.ratsnest.graph().edge_endpoints(ratline).unwrap();
|
||||||
|
|
||||||
let source_dot = match autorouter
|
let source_dot = match autorouter
|
||||||
|
|
@ -129,7 +130,7 @@ impl Autoroute {
|
||||||
.vertex_index()
|
.vertex_index()
|
||||||
{
|
{
|
||||||
RatsnestVertexIndex::FixedDot(dot) => dot,
|
RatsnestVertexIndex::FixedDot(dot) => dot,
|
||||||
RatsnestVertexIndex::Zone(zone) => layout.zone_apex(zone),
|
RatsnestVertexIndex::Zone(zone) => autorouter.layout.zone_apex(zone),
|
||||||
};
|
};
|
||||||
|
|
||||||
let target_dot = match autorouter
|
let target_dot = match autorouter
|
||||||
|
|
@ -140,7 +141,7 @@ impl Autoroute {
|
||||||
.vertex_index()
|
.vertex_index()
|
||||||
{
|
{
|
||||||
RatsnestVertexIndex::FixedDot(dot) => dot,
|
RatsnestVertexIndex::FixedDot(dot) => dot,
|
||||||
RatsnestVertexIndex::Zone(zone) => layout.zone_apex(zone),
|
RatsnestVertexIndex::Zone(zone) => autorouter.layout.zone_apex(zone),
|
||||||
};
|
};
|
||||||
|
|
||||||
(source_dot, target_dot)
|
(source_dot, target_dot)
|
||||||
|
|
@ -152,13 +153,13 @@ impl Autoroute {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct Autorouter<R: RulesTrait> {
|
pub struct Autorouter<R: RulesTrait> {
|
||||||
layout: Arc<Mutex<Layout<R>>>,
|
layout: Layout<R>,
|
||||||
ratsnest: Ratsnest,
|
ratsnest: Ratsnest,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<R: RulesTrait> Autorouter<R> {
|
impl<R: RulesTrait> Autorouter<R> {
|
||||||
pub fn new(layout: Arc<Mutex<Layout<R>>>) -> Result<Self, InsertionError> {
|
pub fn new(layout: Layout<R>) -> Result<Self, InsertionError> {
|
||||||
let ratsnest = Ratsnest::new(&layout.lock().unwrap())?;
|
let ratsnest = Ratsnest::new(&layout)?;
|
||||||
Ok(Self { layout, ratsnest })
|
Ok(Self { layout, ratsnest })
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -181,7 +182,7 @@ impl<R: RulesTrait> Autorouter<R> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn autoroute_walk(&self, selection: &Selection) -> Result<Autoroute, AutorouterError> {
|
pub fn autoroute_walk(&mut self, selection: &Selection) -> Result<Autoroute, AutorouterError> {
|
||||||
Autoroute::new(self.selected_ratlines(selection), self)
|
Autoroute::new(self.selected_ratlines(selection), self)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -194,7 +195,7 @@ impl<R: RulesTrait> Autorouter<R> {
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.band
|
.band
|
||||||
.unwrap();
|
.unwrap();
|
||||||
self.layout.lock().unwrap().remove_band(band);
|
self.layout.remove_band(band);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -218,14 +219,13 @@ impl<R: RulesTrait> Autorouter<R> {
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.vertex_index();
|
.vertex_index();
|
||||||
|
|
||||||
let layout = self.layout.lock().unwrap();
|
selection.contains_node(&self.layout, source_vertex.into())
|
||||||
selection.contains_node(&layout, source_vertex.into())
|
&& selection.contains_node(&self.layout, to_vertex.into())
|
||||||
&& selection.contains_node(&layout, to_vertex.into())
|
|
||||||
})
|
})
|
||||||
.collect()
|
.collect()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn layout(&self) -> &Arc<Mutex<Layout<R>>> {
|
pub fn layout(&self) -> &Layout<R> {
|
||||||
&self.layout
|
&self.layout
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -26,7 +26,7 @@ pub enum InvokerStatus {
|
||||||
Finished,
|
Finished,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(serde::Serialize, serde::Deserialize)]
|
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
|
||||||
pub enum Command {
|
pub enum Command {
|
||||||
Autoroute(Selection),
|
Autoroute(Selection),
|
||||||
}
|
}
|
||||||
|
|
@ -91,7 +91,7 @@ impl<R: RulesTrait> Invoker<R> {
|
||||||
execute
|
execute
|
||||||
}
|
}
|
||||||
|
|
||||||
fn dispatch_command(&self, command: &Command) -> Execute {
|
fn dispatch_command(&mut self, command: &Command) -> Execute {
|
||||||
match command {
|
match command {
|
||||||
Command::Autoroute(ref selection) => {
|
Command::Autoroute(ref selection) => {
|
||||||
Execute::Autoroute(self.autorouter.autoroute_walk(selection).unwrap())
|
Execute::Autoroute(self.autorouter.autoroute_walk(selection).unwrap())
|
||||||
|
|
@ -110,8 +110,8 @@ impl<R: RulesTrait> Invoker<R> {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn redo(&mut self) -> Result<(), InvokerError> {
|
pub fn redo(&mut self) -> Result<(), InvokerError> {
|
||||||
let command = self.history.last_undone()?;
|
let command = self.history.last_undone()?.clone();
|
||||||
let mut execute = self.dispatch_command(command);
|
let mut execute = self.dispatch_command(&command);
|
||||||
|
|
||||||
loop {
|
loop {
|
||||||
let status = match execute.step(self, &mut EmptyRouterObserver) {
|
let status = match execute.step(self, &mut EmptyRouterObserver) {
|
||||||
|
|
|
||||||
|
|
@ -163,7 +163,7 @@ impl eframe::App for App {
|
||||||
let layout = design.make_layout();
|
let layout = design.make_layout();
|
||||||
self.overlay = Some(Overlay::new(&layout).unwrap());
|
self.overlay = Some(Overlay::new(&layout).unwrap());
|
||||||
self.invoker = Some(Arc::new(Mutex::new(Invoker::new(
|
self.invoker = Some(Arc::new(Mutex::new(Invoker::new(
|
||||||
Autorouter::new(Arc::new(Mutex::new(layout))).unwrap(),
|
Autorouter::new(layout).unwrap(),
|
||||||
))));
|
))));
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -172,7 +172,7 @@ impl eframe::App for App {
|
||||||
let layout = design.make_layout();
|
let layout = design.make_layout();
|
||||||
self.overlay = Some(Overlay::new(&layout).unwrap());
|
self.overlay = Some(Overlay::new(&layout).unwrap());
|
||||||
self.invoker = Some(Arc::new(Mutex::new(Invoker::new(
|
self.invoker = Some(Arc::new(Mutex::new(Invoker::new(
|
||||||
Autorouter::new(Arc::new(Mutex::new(layout))).unwrap(),
|
Autorouter::new(layout).unwrap(),
|
||||||
))));
|
))));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -359,7 +359,7 @@ impl eframe::App for App {
|
||||||
self.shared_data.lock().unwrap(),
|
self.shared_data.lock().unwrap(),
|
||||||
&mut self.overlay,
|
&mut self.overlay,
|
||||||
) {
|
) {
|
||||||
let layout = &invoker.autorouter().layout().lock().unwrap();
|
let layout = &invoker.autorouter().layout();
|
||||||
|
|
||||||
if ctx.input(|i| i.pointer.any_click()) {
|
if ctx.input(|i| i.pointer.any_click()) {
|
||||||
overlay.click(
|
overlay.click(
|
||||||
|
|
|
||||||
|
|
@ -28,7 +28,7 @@ use topola::layout::zone::MakePolyShape;
|
||||||
use topola::layout::Layout;
|
use topola::layout::Layout;
|
||||||
use topola::router::draw::DrawException;
|
use topola::router::draw::DrawException;
|
||||||
use topola::router::navmesh::{Navmesh, NavmeshEdgeReference, VertexIndex};
|
use topola::router::navmesh::{Navmesh, NavmeshEdgeReference, VertexIndex};
|
||||||
use topola::router::tracer::{Trace, Tracer};
|
use topola::router::trace::{Trace, Tracer};
|
||||||
use topola::router::RouterObserverTrait;
|
use topola::router::RouterObserverTrait;
|
||||||
|
|
||||||
use sdl2::event::Event;
|
use sdl2::event::Event;
|
||||||
|
|
|
||||||
|
|
@ -62,19 +62,24 @@ impl<R: RulesTrait> RouterObserverTrait<R> for EmptyRouterObserver {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct Router<'a, R: RulesTrait> {
|
pub struct Router<'a, R: RulesTrait> {
|
||||||
layout: &'a mut Arc<Mutex<Layout<R>>>,
|
layout: &'a mut Layout<R>,
|
||||||
navmesh: Navmesh,
|
navmesh: Navmesh,
|
||||||
}
|
}
|
||||||
|
|
||||||
struct RouterAstarStrategy<'a, RO: RouterObserverTrait<R>, R: RulesTrait> {
|
struct RouterAstarStrategy<'a, RO: RouterObserverTrait<R>, R: RulesTrait> {
|
||||||
tracer: Tracer<R>,
|
tracer: Tracer<'a, R>,
|
||||||
trace: Trace,
|
trace: Trace,
|
||||||
to: FixedDotIndex,
|
to: FixedDotIndex,
|
||||||
observer: &'a mut RO,
|
observer: &'a mut RO,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, RO: RouterObserverTrait<R>, R: RulesTrait> RouterAstarStrategy<'a, RO, R> {
|
impl<'a, RO: RouterObserverTrait<R>, R: RulesTrait> RouterAstarStrategy<'a, RO, R> {
|
||||||
pub fn new(tracer: Tracer<R>, trace: Trace, to: FixedDotIndex, observer: &'a mut RO) -> Self {
|
pub fn new(
|
||||||
|
tracer: Tracer<'a, R>,
|
||||||
|
trace: Trace,
|
||||||
|
to: FixedDotIndex,
|
||||||
|
observer: &'a mut RO,
|
||||||
|
) -> Self {
|
||||||
Self {
|
Self {
|
||||||
tracer,
|
tracer,
|
||||||
trace,
|
trace,
|
||||||
|
|
@ -109,24 +114,14 @@ impl<'a, RO: RouterObserverTrait<R>, R: RulesTrait> AstarStrategy<&Navmesh, f64,
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
|
|
||||||
let before_probe_length = self
|
let before_probe_length = self.tracer.layout.band_length(self.trace.head.face());
|
||||||
.tracer
|
|
||||||
.layout
|
|
||||||
.lock()
|
|
||||||
.unwrap()
|
|
||||||
.band_length(self.trace.head.face());
|
|
||||||
|
|
||||||
let width = self.trace.width;
|
let width = self.trace.width;
|
||||||
let result = self.tracer.step(&mut self.trace, edge.target(), width);
|
let result = self.tracer.step(&mut self.trace, edge.target(), width);
|
||||||
self.observer
|
self.observer
|
||||||
.on_probe(&self.tracer, &self.trace, edge, result);
|
.on_probe(&self.tracer, &self.trace, edge, result);
|
||||||
|
|
||||||
let probe_length = self
|
let probe_length = self.tracer.layout.band_length(self.trace.head.face());
|
||||||
.tracer
|
|
||||||
.layout
|
|
||||||
.lock()
|
|
||||||
.unwrap()
|
|
||||||
.band_length(self.trace.head.face());
|
|
||||||
|
|
||||||
if result.is_ok() {
|
if result.is_ok() {
|
||||||
self.tracer.undo_step(&mut self.trace);
|
self.tracer.undo_step(&mut self.trace);
|
||||||
|
|
@ -139,12 +134,17 @@ impl<'a, RO: RouterObserverTrait<R>, R: RulesTrait> AstarStrategy<&Navmesh, f64,
|
||||||
fn estimate_cost(&mut self, vertex: VertexIndex) -> f64 {
|
fn estimate_cost(&mut self, vertex: VertexIndex) -> f64 {
|
||||||
self.observer.on_estimate(&self.tracer, vertex);
|
self.observer.on_estimate(&self.tracer, vertex);
|
||||||
|
|
||||||
let layout = self.tracer.layout.lock().unwrap();
|
|
||||||
let start_point = PrimitiveIndex::from(vertex)
|
let start_point = PrimitiveIndex::from(vertex)
|
||||||
.primitive(layout.drawing())
|
.primitive(self.tracer.layout.drawing())
|
||||||
|
.shape()
|
||||||
|
.center();
|
||||||
|
let end_point = self
|
||||||
|
.tracer
|
||||||
|
.layout
|
||||||
|
.drawing()
|
||||||
|
.primitive(self.to)
|
||||||
.shape()
|
.shape()
|
||||||
.center();
|
.center();
|
||||||
let end_point = layout.drawing().primitive(self.to).shape().center();
|
|
||||||
|
|
||||||
end_point.euclidean_distance(&start_point)
|
end_point.euclidean_distance(&start_point)
|
||||||
}
|
}
|
||||||
|
|
@ -152,18 +152,15 @@ impl<'a, RO: RouterObserverTrait<R>, R: RulesTrait> AstarStrategy<&Navmesh, f64,
|
||||||
|
|
||||||
impl<'a, R: RulesTrait> Router<'a, R> {
|
impl<'a, R: RulesTrait> Router<'a, R> {
|
||||||
pub fn new(
|
pub fn new(
|
||||||
layout: &'a mut Arc<Mutex<Layout<R>>>,
|
layout: &'a mut Layout<R>,
|
||||||
from: FixedDotIndex,
|
from: FixedDotIndex,
|
||||||
to: FixedDotIndex,
|
to: FixedDotIndex,
|
||||||
) -> Result<Self, RouterError> {
|
) -> Result<Self, RouterError> {
|
||||||
let navmesh = {
|
let navmesh = { Navmesh::new(layout, from, to)? };
|
||||||
let layout = layout.lock().unwrap();
|
|
||||||
Navmesh::new(&layout, from, to)?
|
|
||||||
};
|
|
||||||
Ok(Self::new_from_navmesh(layout, navmesh))
|
Ok(Self::new_from_navmesh(layout, navmesh))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn new_from_navmesh(layout: &'a mut Arc<Mutex<Layout<R>>>, navmesh: Navmesh) -> Self {
|
pub fn new_from_navmesh(layout: &'a mut Layout<R>, navmesh: Navmesh) -> Self {
|
||||||
Self { layout, navmesh }
|
Self { layout, navmesh }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -172,13 +169,16 @@ impl<'a, R: RulesTrait> Router<'a, R> {
|
||||||
width: f64,
|
width: f64,
|
||||||
observer: &mut impl RouterObserverTrait<R>,
|
observer: &mut impl RouterObserverTrait<R>,
|
||||||
) -> Result<BandIndex, RouterError> {
|
) -> Result<BandIndex, RouterError> {
|
||||||
let mut tracer = self.tracer();
|
let from = self.navmesh.from();
|
||||||
let trace = tracer.start(self.navmesh.from(), width);
|
let to = self.navmesh.to();
|
||||||
|
//let mut tracer = self.tracer();
|
||||||
|
let mut tracer = Tracer::new(self.layout);
|
||||||
|
let trace = tracer.start(from, width);
|
||||||
|
|
||||||
let (_cost, _path, band) = astar(
|
let (_cost, _path, band) = astar(
|
||||||
&self.navmesh,
|
&self.navmesh,
|
||||||
self.navmesh.from().into(),
|
from.into(),
|
||||||
&mut RouterAstarStrategy::new(tracer, trace, self.navmesh.to(), observer),
|
&mut RouterAstarStrategy::new(tracer, trace, to, observer),
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
Ok(band)
|
Ok(band)
|
||||||
|
|
@ -201,11 +201,11 @@ impl<'a, R: RulesTrait> Router<'a, R> {
|
||||||
self.route_band(width, observer)
|
self.route_band(width, observer)
|
||||||
}*/
|
}*/
|
||||||
|
|
||||||
fn tracer(&mut self) -> Tracer<R> {
|
/*fn tracer(&mut self) -> Tracer<R> {
|
||||||
Tracer::new(self.layout.clone())
|
Tracer::new(self.layout)
|
||||||
}
|
}*/
|
||||||
|
|
||||||
pub fn layout(&self) -> Arc<Mutex<Layout<R>>> {
|
pub fn layout(&mut self) -> &mut Layout<R> {
|
||||||
self.layout.clone()
|
self.layout
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -25,12 +25,12 @@ pub struct Trace {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct Tracer<R: RulesTrait> {
|
pub struct Tracer<'a, R: RulesTrait> {
|
||||||
pub layout: Arc<Mutex<Layout<R>>>,
|
pub layout: &'a mut Layout<R>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<R: RulesTrait> Tracer<R> {
|
impl<'a, R: RulesTrait> Tracer<'a, R> {
|
||||||
pub fn new(layout: Arc<Mutex<Layout<R>>>) -> Self {
|
pub fn new(layout: &mut Layout<R>) -> Tracer<R> {
|
||||||
Tracer { layout }
|
Tracer { layout }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -48,7 +48,7 @@ impl<R: RulesTrait> Tracer<R> {
|
||||||
into: FixedDotIndex,
|
into: FixedDotIndex,
|
||||||
width: f64,
|
width: f64,
|
||||||
) -> Result<BandIndex, DrawException> {
|
) -> Result<BandIndex, DrawException> {
|
||||||
Draw::new(&mut self.layout.lock().unwrap()).finish_in_dot(trace.head, into, width)
|
Draw::new(self.layout).finish_in_dot(trace.head, into, width)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[debug_ensures(ret.is_ok() -> trace.path.len() == path.len())]
|
#[debug_ensures(ret.is_ok() -> trace.path.len() == path.len())]
|
||||||
|
|
@ -129,11 +129,7 @@ impl<R: RulesTrait> Tracer<R> {
|
||||||
around: FixedDotIndex,
|
around: FixedDotIndex,
|
||||||
width: f64,
|
width: f64,
|
||||||
) -> Result<SegbendHead, DrawException> {
|
) -> Result<SegbendHead, DrawException> {
|
||||||
let head = Draw::new(&mut self.layout.lock().unwrap()).segbend_around_dot(
|
let head = Draw::new(self.layout).segbend_around_dot(head, around.into(), width)?;
|
||||||
head,
|
|
||||||
around.into(),
|
|
||||||
width,
|
|
||||||
)?;
|
|
||||||
Ok(head)
|
Ok(head)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -143,11 +139,7 @@ impl<R: RulesTrait> Tracer<R> {
|
||||||
around: LooseBendIndex,
|
around: LooseBendIndex,
|
||||||
width: f64,
|
width: f64,
|
||||||
) -> Result<SegbendHead, DrawException> {
|
) -> Result<SegbendHead, DrawException> {
|
||||||
let head = Draw::new(&mut self.layout.lock().unwrap()).segbend_around_bend(
|
let head = Draw::new(self.layout).segbend_around_bend(head, around.into(), width)?;
|
||||||
head,
|
|
||||||
around.into(),
|
|
||||||
width,
|
|
||||||
)?;
|
|
||||||
|
|
||||||
Ok(head)
|
Ok(head)
|
||||||
}
|
}
|
||||||
|
|
@ -155,9 +147,7 @@ impl<R: RulesTrait> Tracer<R> {
|
||||||
#[debug_ensures(trace.path.len() == old(trace.path.len() - 1))]
|
#[debug_ensures(trace.path.len() == old(trace.path.len() - 1))]
|
||||||
pub fn undo_step(&mut self, trace: &mut Trace) {
|
pub fn undo_step(&mut self, trace: &mut Trace) {
|
||||||
if let Head::Segbend(head) = trace.head {
|
if let Head::Segbend(head) = trace.head {
|
||||||
trace.head = Draw::new(&mut self.layout.lock().unwrap())
|
trace.head = Draw::new(self.layout).undo_segbend(head).unwrap();
|
||||||
.undo_segbend(head)
|
|
||||||
.unwrap();
|
|
||||||
} else {
|
} else {
|
||||||
panic!();
|
panic!();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -18,16 +18,28 @@ use topola::{
|
||||||
#[test]
|
#[test]
|
||||||
fn test() {
|
fn test() {
|
||||||
let design = DsnDesign::load_from_file("tests/data/0603_breakout/0603_breakout.dsn").unwrap();
|
let design = DsnDesign::load_from_file("tests/data/0603_breakout/0603_breakout.dsn").unwrap();
|
||||||
let layout_arc_mutex = Arc::new(Mutex::new(design.make_layout()));
|
let mut invoker = Invoker::new(Autorouter::new(design.make_layout()).unwrap());
|
||||||
|
|
||||||
let mut invoker = Invoker::new(Autorouter::new(layout_arc_mutex.clone()).unwrap());
|
|
||||||
let file = File::open("tests/data/0603_breakout/autoroute_all.cmd").unwrap();
|
let file = File::open("tests/data/0603_breakout/autoroute_all.cmd").unwrap();
|
||||||
invoker.replay(serde_json::from_reader(file).unwrap());
|
invoker.replay(serde_json::from_reader(file).unwrap());
|
||||||
|
|
||||||
let layout = layout_arc_mutex.lock().unwrap();
|
let mut unionfind = UnionFind::new(
|
||||||
let mut unionfind = UnionFind::new(layout.drawing().geometry().graph().node_bound());
|
invoker
|
||||||
|
.autorouter()
|
||||||
|
.layout()
|
||||||
|
.drawing()
|
||||||
|
.geometry()
|
||||||
|
.graph()
|
||||||
|
.node_bound(),
|
||||||
|
);
|
||||||
|
|
||||||
for edge in layout.drawing().geometry().graph().edge_references() {
|
for edge in invoker
|
||||||
|
.autorouter()
|
||||||
|
.layout()
|
||||||
|
.drawing()
|
||||||
|
.geometry()
|
||||||
|
.graph()
|
||||||
|
.edge_references()
|
||||||
|
{
|
||||||
unionfind.union(edge.source(), edge.target());
|
unionfind.union(edge.source(), edge.target());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue