mirror of
https://github.com/a-b-street/abstreet.git
synced 2024-12-25 07:25:47 +03:00
select a path of roads
This commit is contained in:
parent
f3b396a7e9
commit
db7c276e91
1
Cargo.lock
generated
1
Cargo.lock
generated
@ -1006,6 +1006,7 @@ dependencies = [
|
||||
"kml 0.1.0",
|
||||
"map_model 0.1.0",
|
||||
"maplit 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"petgraph 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rand 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rand_xorshift 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"serde 1.0.106 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
|
@ -23,6 +23,7 @@ instant = "0.1.2"
|
||||
kml = { path = "../kml" }
|
||||
maplit = "1.0.2"
|
||||
map_model = { path = "../map_model" }
|
||||
petgraph = "0.5.0"
|
||||
rand = "0.7.0"
|
||||
rand_xorshift = "0.2.0"
|
||||
serde = "1.0.98"
|
||||
|
@ -1,11 +1,14 @@
|
||||
use crate::app::{App, ShowEverything};
|
||||
use crate::common::CommonState;
|
||||
use crate::game::{State, Transition};
|
||||
use crate::helpers::ID;
|
||||
use ezgui::{
|
||||
hotkey, Btn, Composite, EventCtx, GfxCtx, HorizontalAlignment, Key, Line, Outcome, TextExt,
|
||||
VerticalAlignment, Widget,
|
||||
hotkey, Btn, Color, Composite, Drawable, EventCtx, GeomBatch, GfxCtx, HorizontalAlignment, Key,
|
||||
Line, Outcome, TextExt, VerticalAlignment, Widget,
|
||||
};
|
||||
use map_model::IntersectionID;
|
||||
use geom::Distance;
|
||||
use map_model::{IntersectionID, Map, RoadID};
|
||||
use petgraph::graphmap::UnGraphMap;
|
||||
use sim::DontDrawAgents;
|
||||
|
||||
// TODO For now, individual turns can't be manipulated. Banning turns could be useful, but I'm not
|
||||
@ -13,6 +16,7 @@ use sim::DontDrawAgents;
|
||||
pub struct BulkSelect {
|
||||
composite: Composite,
|
||||
i1: Option<IntersectionID>,
|
||||
preview_path: Option<(IntersectionID, Vec<RoadID>, Drawable)>,
|
||||
}
|
||||
|
||||
impl BulkSelect {
|
||||
@ -22,7 +26,9 @@ impl BulkSelect {
|
||||
composite: Composite::new(
|
||||
Widget::col(vec![
|
||||
Line("Edit many roads").small_heading().draw(ctx),
|
||||
"Click one intersection to start".draw_text(ctx),
|
||||
"Click one intersection to start"
|
||||
.draw_text(ctx)
|
||||
.named("instructions"),
|
||||
Btn::text_fg("Quit")
|
||||
.build_def(ctx, hotkey(Key::Escape))
|
||||
.margin_above(10),
|
||||
@ -33,6 +39,7 @@ impl BulkSelect {
|
||||
.aligned(HorizontalAlignment::Center, VerticalAlignment::Top)
|
||||
.build(ctx),
|
||||
i1: None,
|
||||
preview_path: None,
|
||||
})
|
||||
}
|
||||
}
|
||||
@ -54,6 +61,58 @@ impl State for BulkSelect {
|
||||
}
|
||||
}
|
||||
|
||||
if let Some(ID::Intersection(i)) = app.primary.current_selection {
|
||||
if self.i1.is_none() && app.per_obj.left_click(ctx, "start here") {
|
||||
self.i1 = Some(i);
|
||||
self.composite.replace(
|
||||
ctx,
|
||||
"instructions",
|
||||
"Click a second intersection to edit this path".draw_text(ctx),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
if let Some(i1) = self.i1 {
|
||||
if let Some(ID::Intersection(i2)) = app.primary.current_selection {
|
||||
if self
|
||||
.preview_path
|
||||
.as_ref()
|
||||
.map(|(i, _, _)| *i != i2)
|
||||
.unwrap_or(true)
|
||||
{
|
||||
let mut batch = GeomBatch::new();
|
||||
let roads = if let Some(roads) = pathfind(&app.primary.map, i1, i2) {
|
||||
for r in &roads {
|
||||
batch.push(
|
||||
Color::RED,
|
||||
app.primary
|
||||
.map
|
||||
.get_r(*r)
|
||||
.get_thick_polygon(&app.primary.map)
|
||||
.unwrap(),
|
||||
);
|
||||
}
|
||||
roads
|
||||
} else {
|
||||
Vec::new()
|
||||
};
|
||||
self.preview_path = Some((i2, roads, ctx.upload(batch)));
|
||||
}
|
||||
|
||||
if self
|
||||
.preview_path
|
||||
.as_ref()
|
||||
.map(|(_, roads, _)| !roads.is_empty())
|
||||
.unwrap_or(false)
|
||||
&& app.per_obj.left_click(ctx, "end here")
|
||||
{
|
||||
println!("do it");
|
||||
}
|
||||
} else {
|
||||
self.preview_path = None;
|
||||
}
|
||||
}
|
||||
|
||||
match self.composite.event(ctx) {
|
||||
Some(Outcome::Clicked(x)) => match x.as_ref() {
|
||||
"Quit" => {
|
||||
@ -68,5 +127,32 @@ impl State for BulkSelect {
|
||||
|
||||
fn draw(&self, g: &mut GfxCtx, app: &App) {
|
||||
self.composite.draw(g);
|
||||
if let Some(i) = self.i1 {
|
||||
g.draw_polygon(Color::GREEN, &app.primary.map.get_i(i).polygon);
|
||||
}
|
||||
if let Some((_, _, ref p)) = self.preview_path {
|
||||
g.redraw(p);
|
||||
}
|
||||
CommonState::draw_osd(g, app, &None);
|
||||
}
|
||||
}
|
||||
|
||||
// Simple search along undirected roads
|
||||
fn pathfind(map: &Map, i1: IntersectionID, i2: IntersectionID) -> Option<Vec<RoadID>> {
|
||||
let mut graph: UnGraphMap<IntersectionID, RoadID> = UnGraphMap::new();
|
||||
for r in map.all_roads() {
|
||||
graph.add_edge(r.src_i, r.dst_i, r.id);
|
||||
}
|
||||
let (_, path) = petgraph::algo::astar(
|
||||
&graph,
|
||||
i1,
|
||||
|i| i == i2,
|
||||
|(_, _, r)| map.get_r(*r).center_pts.length(),
|
||||
|_| Distance::ZERO,
|
||||
)?;
|
||||
Some(
|
||||
path.windows(2)
|
||||
.map(|pair| *graph.edge_weight(pair[0], pair[1]).unwrap())
|
||||
.collect(),
|
||||
)
|
||||
}
|
||||
|
@ -168,3 +168,9 @@ impl std::iter::Sum for Distance {
|
||||
sum
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for Distance {
|
||||
fn default() -> Distance {
|
||||
Distance::ZERO
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user