mirror of https://codeberg.org/topola/topola.git
router: Implement basic cursor following
This commit is contained in:
parent
0e8a6d6e42
commit
7a06a9b02d
105
src/band.rs
105
src/band.rs
|
|
@ -12,25 +12,52 @@ pub struct Band {
|
|||
}
|
||||
|
||||
impl Band {
|
||||
pub fn new(
|
||||
from: DotIndex,
|
||||
to: DotIndex,
|
||||
pub fn from_dot_prev(
|
||||
dot: DotIndex,
|
||||
graph: &StableDiGraph<TaggedWeight, Label, usize>,
|
||||
) -> Self {
|
||||
let mut this = Self {
|
||||
from,
|
||||
to,
|
||||
interior: vec![],
|
||||
};
|
||||
let mut prev_index = from.tag();
|
||||
) -> Option<Self> {
|
||||
let mut next_index = dot.tag();
|
||||
let mut interior = vec![];
|
||||
|
||||
while let Some(index) = untag!(next_index, Primitive::new(next_index, graph).tagged_next())
|
||||
{
|
||||
interior.push(index);
|
||||
next_index = index;
|
||||
}
|
||||
|
||||
if interior.is_empty() {
|
||||
None
|
||||
} else {
|
||||
Some(Self {
|
||||
from: *interior.pop().unwrap().as_dot().unwrap(),
|
||||
to: dot,
|
||||
interior,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
pub fn from_dot_next(
|
||||
dot: DotIndex,
|
||||
graph: &StableDiGraph<TaggedWeight, Label, usize>,
|
||||
) -> Option<Self> {
|
||||
let mut prev_index = dot.tag();
|
||||
let mut interior = vec![];
|
||||
|
||||
while let Some(index) = untag!(prev_index, Primitive::new(prev_index, graph).tagged_next())
|
||||
{
|
||||
this.interior.push(index);
|
||||
interior.push(index);
|
||||
prev_index = index;
|
||||
}
|
||||
|
||||
this
|
||||
if interior.is_empty() {
|
||||
None
|
||||
} else {
|
||||
Some(Self {
|
||||
from: dot,
|
||||
to: *interior.pop().unwrap().as_dot().unwrap(),
|
||||
interior,
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -46,57 +73,3 @@ impl Ends<DotIndex, DotIndex> for Band {
|
|||
(self.from, self.to)
|
||||
}
|
||||
}
|
||||
/*use petgraph::stable_graph::StableDiGraph;
|
||||
|
||||
use crate::{
|
||||
graph::{DotIndex, Ends, Interior, Label, Tag, TaggedIndex, TaggedWeight},
|
||||
primitive::Primitive,
|
||||
};
|
||||
|
||||
pub struct Band {
|
||||
from: DotIndex,
|
||||
to: DotIndex,
|
||||
}
|
||||
|
||||
impl Band {
|
||||
pub fn new(from: DotIndex, to: DotIndex) -> Self {
|
||||
Self { from, to }
|
||||
}
|
||||
}
|
||||
|
||||
struct BandIterator<'a> {
|
||||
graph: &'a StableDiGraph<TaggedWeight, Label, usize>,
|
||||
index: TaggedIndex,
|
||||
}
|
||||
|
||||
impl<'a> Iterator for BandIterator<'a> {
|
||||
type Item = TaggedIndex;
|
||||
|
||||
fn next(&mut self) -> Option<Self::Item> {
|
||||
let index = self.index;
|
||||
let next_index = untag!(index, Primitive::new(index, self.graph).tagged_next());
|
||||
|
||||
if let Some(next_index) = next_index {
|
||||
self.index = next_index;
|
||||
}
|
||||
|
||||
next_index
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Interior<'a, TaggedIndex> for Band {
|
||||
type Iter = BandIterator<'a>;
|
||||
|
||||
fn interior(&self, graph: &'a StableDiGraph<TaggedWeight, Label, usize>) -> Self::Iter {
|
||||
BandIterator {
|
||||
graph,
|
||||
index: self.from.tag(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Ends<DotIndex, DotIndex> for Band {
|
||||
fn ends(&self) -> (DotIndex, DotIndex) {
|
||||
(self.from, self.to)
|
||||
}
|
||||
}*/
|
||||
|
|
|
|||
|
|
@ -207,8 +207,12 @@ impl Layout {
|
|||
Segbend::from_dot_next(dot, &self.graph)
|
||||
}
|
||||
|
||||
pub fn band(&self, from: DotIndex, to: DotIndex) -> Band {
|
||||
Band::new(from, to, &self.graph)
|
||||
pub fn prev_band(&self, to: DotIndex) -> Option<Band> {
|
||||
Band::from_dot_prev(to, &self.graph)
|
||||
}
|
||||
|
||||
pub fn next_band(&self, from: DotIndex) -> Option<Band> {
|
||||
Band::from_dot_next(from, &self.graph)
|
||||
}
|
||||
|
||||
#[debug_ensures(ret.is_ok() -> self.graph.node_count() == old(self.graph.node_count()))]
|
||||
|
|
|
|||
58
src/main.rs
58
src/main.rs
|
|
@ -24,7 +24,8 @@ mod rules;
|
|||
mod segbend;
|
||||
mod shape;
|
||||
|
||||
use graph::{SegWeight, Tag, TaggedIndex};
|
||||
use geo::point;
|
||||
use graph::{DotIndex, SegWeight, Tag, TaggedIndex};
|
||||
use layout::Layout;
|
||||
use mesh::{MeshEdgeReference, VertexIndex};
|
||||
use route::Route;
|
||||
|
|
@ -44,6 +45,12 @@ use crate::graph::DotWeight;
|
|||
use crate::math::Circle;
|
||||
use crate::router::Router;
|
||||
|
||||
// Clunky enum to work around borrow checker.
|
||||
enum RouterOrLayout<'a> {
|
||||
Router(&'a mut Router),
|
||||
Layout(&'a Layout),
|
||||
}
|
||||
|
||||
struct DebugRouteStrategy<'a, RS: RouteStrategy> {
|
||||
strategy: RS,
|
||||
event_pump: &'a mut sdl2::EventPump,
|
||||
|
|
@ -66,7 +73,14 @@ impl<'a, RS: RouteStrategy> DebugRouteStrategy<'a, RS> {
|
|||
|
||||
impl<'a, RS: RouteStrategy> RouteStrategy for DebugRouteStrategy<'a, RS> {
|
||||
fn route_cost(&mut self, route: &Route, path: &[VertexIndex]) -> u64 {
|
||||
render_times(self.event_pump, self.canvas, route.layout, None, 25);
|
||||
render_times(
|
||||
self.event_pump,
|
||||
self.canvas,
|
||||
RouterOrLayout::Layout(route.layout),
|
||||
None,
|
||||
None,
|
||||
25,
|
||||
);
|
||||
self.strategy.route_cost(route, path)
|
||||
}
|
||||
|
||||
|
|
@ -258,28 +272,37 @@ fn main() {
|
|||
let head = router.draw_around_dot(head, dot6, false, 5.0).unwrap();
|
||||
let _ = router.draw_finish(head, dot7, 5.0);*/
|
||||
|
||||
let _ = router.enroute(
|
||||
/*let _ = router.enroute(
|
||||
dot1_1,
|
||||
dot1_2,
|
||||
DebugRouteStrategy::new(DefaultRouteStrategy::new(), &mut event_pump, &mut canvas),
|
||||
);
|
||||
|
||||
render_times(&mut event_pump, &mut canvas, &router.layout, None, -1);
|
||||
render_times(&mut event_pump, &mut canvas, &router.layout, None, -1);*/
|
||||
render_times(
|
||||
&mut event_pump,
|
||||
&mut canvas,
|
||||
&router.layout,
|
||||
Some(barrier1_dot1.tag()),
|
||||
RouterOrLayout::Router(&mut router),
|
||||
Some(dot1_1),
|
||||
Some(dot1_2),
|
||||
-1,
|
||||
);
|
||||
render_times(
|
||||
&mut event_pump,
|
||||
&mut canvas,
|
||||
RouterOrLayout::Layout(&router.layout),
|
||||
None,
|
||||
None,
|
||||
-1,
|
||||
);
|
||||
render_times(&mut event_pump, &mut canvas, &router.layout, None, -1);
|
||||
}
|
||||
|
||||
fn render_times(
|
||||
event_pump: &mut EventPump,
|
||||
canvas: &mut Canvas<Window>,
|
||||
layout: &Layout,
|
||||
follower: Option<TaggedIndex>,
|
||||
mut router_or_layout: RouterOrLayout,
|
||||
from: Option<DotIndex>,
|
||||
follower: Option<DotIndex>,
|
||||
times: i64,
|
||||
) {
|
||||
let mut i = 0;
|
||||
|
|
@ -299,14 +322,29 @@ fn render_times(
|
|||
}
|
||||
}
|
||||
|
||||
let layout = match router_or_layout {
|
||||
RouterOrLayout::Router(ref mut router) => {
|
||||
if let Some(follower) = follower {
|
||||
let state = event_pump.mouse_state();
|
||||
|
||||
/*let _ = router.move_dot(
|
||||
/*let _ = router.layout.move_dot(
|
||||
*follower.as_dot().unwrap(),
|
||||
(state.x() as f64, state.y() as f64).into(),
|
||||
);*/
|
||||
|
||||
if let Some(from) = from {
|
||||
router.reroute(
|
||||
from,
|
||||
point! {x: state.x() as f64, y: state.y() as f64},
|
||||
&mut DefaultRouteStrategy::new(),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
&router.layout
|
||||
}
|
||||
RouterOrLayout::Layout(layout) => layout,
|
||||
};
|
||||
|
||||
let result = panic::catch_unwind(|| {
|
||||
for shape in layout.shapes() {
|
||||
|
|
|
|||
|
|
@ -53,11 +53,11 @@ struct RouterAstarStrategy<'a, RS: RouteStrategy> {
|
|||
route: Route<'a>,
|
||||
trace: Trace,
|
||||
to: VertexIndex,
|
||||
strategy: RS,
|
||||
strategy: &'a mut RS,
|
||||
}
|
||||
|
||||
impl<'a, RS: RouteStrategy> RouterAstarStrategy<'a, RS> {
|
||||
pub fn new(route: Route<'a>, trace: Trace, to: VertexIndex, strategy: RS) -> Self {
|
||||
pub fn new(route: Route<'a>, trace: Trace, to: VertexIndex, strategy: &'a mut RS) -> Self {
|
||||
Self {
|
||||
route,
|
||||
trace,
|
||||
|
|
@ -101,7 +101,7 @@ impl Router {
|
|||
&mut self,
|
||||
from: DotIndex,
|
||||
to: DotIndex,
|
||||
strategy: impl RouteStrategy,
|
||||
strategy: &mut impl RouteStrategy,
|
||||
) -> Result<(), InsertionError> {
|
||||
// XXX: Should we actually store the mesh? May be useful for debugging, but doesn't look
|
||||
// right.
|
||||
|
|
@ -121,6 +121,31 @@ impl Router {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
pub fn reroute(
|
||||
&mut self,
|
||||
from: DotIndex,
|
||||
to: Point,
|
||||
strategy: &mut impl RouteStrategy,
|
||||
) -> Result<(), InsertionError> {
|
||||
let to_dot = if let Some(band) = self.layout.next_band(from) {
|
||||
let to_dot = band.ends().1;
|
||||
|
||||
self.layout.remove_interior(&band);
|
||||
self.layout.move_dot(to_dot, to);
|
||||
to_dot
|
||||
} else {
|
||||
let from_weight = self.layout.primitive(from).weight();
|
||||
self.layout
|
||||
.add_dot(DotWeight {
|
||||
net: from_weight.net,
|
||||
circle: Circle { pos: to, r: 2.0 },
|
||||
})
|
||||
.unwrap() // TODO.
|
||||
};
|
||||
|
||||
self.enroute(from, to_dot, strategy)
|
||||
}
|
||||
|
||||
/*pub fn squeeze_around_dot(
|
||||
&mut self,
|
||||
head: Head,
|
||||
|
|
|
|||
Loading…
Reference in New Issue