mirror of
https://github.com/a-b-street/abstreet.git
synced 2024-11-28 12:12:00 +03:00
ditch quadtrees in synthetic crate. if anything, switch later to
viewer's World
This commit is contained in:
parent
97361317ed
commit
c3ae6bf8f8
@ -37,7 +37,7 @@ pub struct Flags {
|
|||||||
#[structopt(long = "neighborhoods", default_value = "")]
|
#[structopt(long = "neighborhoods", default_value = "")]
|
||||||
pub neighborhoods: String,
|
pub neighborhoods: String,
|
||||||
|
|
||||||
/// Osmosis clipping polgon. Required.
|
/// Osmosis clipping polgon. Optional.
|
||||||
#[structopt(long = "clip", default_value = "")]
|
#[structopt(long = "clip", default_value = "")]
|
||||||
pub clip: String,
|
pub clip: String,
|
||||||
|
|
||||||
|
@ -5,7 +5,6 @@ authors = ["Dustin Carlino <dabreegster@gmail.com>"]
|
|||||||
edition = "2018"
|
edition = "2018"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
aabb-quadtree = "0.1.0"
|
|
||||||
abstutil = { path = "../abstutil" }
|
abstutil = { path = "../abstutil" }
|
||||||
ezgui = { path = "../ezgui" }
|
ezgui = { path = "../ezgui" }
|
||||||
geom = { path = "../geom" }
|
geom = { path = "../geom" }
|
||||||
|
@ -1,4 +1,3 @@
|
|||||||
use aabb_quadtree::QuadTree;
|
|
||||||
use abstutil::{deserialize_btreemap, read_binary, serialize_btreemap, write_json, Timer};
|
use abstutil::{deserialize_btreemap, read_binary, serialize_btreemap, write_json, Timer};
|
||||||
use ezgui::{Canvas, Color, GfxCtx, Line, Text};
|
use ezgui::{Canvas, Color, GfxCtx, Line, Text};
|
||||||
use geom::{Circle, Distance, LonLat, PolyLine, Polygon, Pt2D};
|
use geom::{Circle, Distance, LonLat, PolyLine, Polygon, Pt2D};
|
||||||
@ -169,52 +168,26 @@ impl Model {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn draw(&self, g: &mut GfxCtx, quadtree: Option<&QuadTree<ID>>) {
|
pub fn draw(&self, g: &mut GfxCtx) {
|
||||||
g.clear(Color::WHITE);
|
g.clear(Color::WHITE);
|
||||||
|
|
||||||
let mut roads: Vec<StableRoadID> = Vec::new();
|
let selected = self.mouseover_something(g.canvas);
|
||||||
let mut buildings: Vec<BuildingID> = Vec::new();
|
|
||||||
let mut intersections: Vec<StableIntersectionID> = Vec::new();
|
|
||||||
if let Some(ref qt) = quadtree {
|
|
||||||
let bbox = g.get_screen_bounds().as_bbox();
|
|
||||||
for &(id, _, _) in &qt.query(bbox) {
|
|
||||||
match *id {
|
|
||||||
ID::Road(id) => {
|
|
||||||
roads.push(id);
|
|
||||||
}
|
|
||||||
ID::Building(id) => {
|
|
||||||
buildings.push(id);
|
|
||||||
}
|
|
||||||
ID::Intersection(id) => {
|
|
||||||
intersections.push(id);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
roads.extend(self.roads.keys());
|
|
||||||
buildings.extend(self.buildings.keys());
|
|
||||||
intersections.extend(self.intersections.keys());
|
|
||||||
}
|
|
||||||
|
|
||||||
let selected = self.mouseover_something(g.canvas, quadtree);
|
|
||||||
let current_r = match selected {
|
let current_r = match selected {
|
||||||
Some(ID::Road(r)) => self.mouseover_road(r, g.get_cursor_in_map_space().unwrap()),
|
Some(ID::Road(r)) => self.mouseover_road(r, g.get_cursor_in_map_space().unwrap()),
|
||||||
_ => None,
|
_ => None,
|
||||||
};
|
};
|
||||||
|
|
||||||
for id in roads {
|
for (id, r) in &self.roads {
|
||||||
let r = &self.roads[&id];
|
|
||||||
r.draw(
|
r.draw(
|
||||||
self,
|
self,
|
||||||
g,
|
g,
|
||||||
Some((id, FORWARDS)) == current_r,
|
Some((*id, FORWARDS)) == current_r,
|
||||||
Some((id, BACKWARDS)) == current_r,
|
Some((*id, BACKWARDS)) == current_r,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
for id in intersections {
|
for (id, i) in &self.intersections {
|
||||||
let i = &self.intersections[&id];
|
let color = if Some(ID::Intersection(*id)) == selected {
|
||||||
let color = if Some(ID::Intersection(id)) == selected {
|
|
||||||
HIGHLIGHT_COLOR
|
HIGHLIGHT_COLOR
|
||||||
} else {
|
} else {
|
||||||
match i.intersection_type {
|
match i.intersection_type {
|
||||||
@ -230,9 +203,8 @@ impl Model {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for id in buildings {
|
for (id, b) in &self.buildings {
|
||||||
let b = &self.buildings[&id];
|
let color = if Some(ID::Building(*id)) == selected {
|
||||||
let color = if Some(ID::Building(id)) == selected {
|
|
||||||
HIGHLIGHT_COLOR
|
HIGHLIGHT_COLOR
|
||||||
} else {
|
} else {
|
||||||
Color::BLUE
|
Color::BLUE
|
||||||
@ -245,55 +217,24 @@ impl Model {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn mouseover_something(
|
pub fn mouseover_something(&self, canvas: &Canvas) -> Option<ID> {
|
||||||
&self,
|
|
||||||
canvas: &Canvas,
|
|
||||||
quadtree: Option<&QuadTree<ID>>,
|
|
||||||
) -> Option<ID> {
|
|
||||||
let cursor = canvas.get_cursor_in_map_space()?;
|
let cursor = canvas.get_cursor_in_map_space()?;
|
||||||
|
|
||||||
// TODO Duplicated with draw
|
for (id, i) in &self.intersections {
|
||||||
let mut roads: Vec<StableRoadID> = Vec::new();
|
|
||||||
let mut buildings: Vec<BuildingID> = Vec::new();
|
|
||||||
let mut intersections: Vec<StableIntersectionID> = Vec::new();
|
|
||||||
if let Some(ref qt) = quadtree {
|
|
||||||
let bbox = canvas.get_screen_bounds().as_bbox();
|
|
||||||
for &(id, _, _) in &qt.query(bbox) {
|
|
||||||
match *id {
|
|
||||||
ID::Road(id) => {
|
|
||||||
roads.push(id);
|
|
||||||
}
|
|
||||||
ID::Building(id) => {
|
|
||||||
buildings.push(id);
|
|
||||||
}
|
|
||||||
ID::Intersection(id) => {
|
|
||||||
intersections.push(id);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
roads.extend(self.roads.keys());
|
|
||||||
buildings.extend(self.buildings.keys());
|
|
||||||
intersections.extend(self.intersections.keys());
|
|
||||||
}
|
|
||||||
|
|
||||||
for id in intersections {
|
|
||||||
let i = &self.intersections[&id];
|
|
||||||
if i.circle().contains_pt(cursor) {
|
if i.circle().contains_pt(cursor) {
|
||||||
return Some(ID::Intersection(id));
|
return Some(ID::Intersection(*id));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for id in buildings {
|
for (id, b) in &self.buildings {
|
||||||
let b = &self.buildings[&id];
|
|
||||||
if b.polygon().contains_pt(cursor) {
|
if b.polygon().contains_pt(cursor) {
|
||||||
return Some(ID::Building(id));
|
return Some(ID::Building(*id));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for id in roads {
|
for id in self.roads.keys() {
|
||||||
if self.mouseover_road(id, cursor).is_some() {
|
if self.mouseover_road(*id, cursor).is_some() {
|
||||||
return Some(ID::Road(id));
|
return Some(ID::Road(*id));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -412,11 +353,10 @@ impl Model {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// TODO Directly use raw_data and get rid of Model? Might be more maintainable long-term.
|
// TODO Directly use raw_data and get rid of Model? Might be more maintainable long-term.
|
||||||
pub fn import(path: &str) -> (Model, QuadTree<ID>) {
|
pub fn import(path: &str) -> Model {
|
||||||
let data: raw_data::Map = read_binary(path, &mut Timer::new("load map")).unwrap();
|
let data: raw_data::Map = read_binary(path, &mut Timer::new("load map")).unwrap();
|
||||||
|
|
||||||
let mut m = Model::new();
|
let mut m = Model::new();
|
||||||
let mut quadtree = QuadTree::default(data.gps_bounds.to_bounds().as_bbox());
|
|
||||||
|
|
||||||
for (id, raw_i) in &data.intersections {
|
for (id, raw_i) in &data.intersections {
|
||||||
let i = Intersection {
|
let i = Intersection {
|
||||||
@ -424,7 +364,6 @@ impl Model {
|
|||||||
intersection_type: raw_i.intersection_type,
|
intersection_type: raw_i.intersection_type,
|
||||||
label: raw_i.label.clone(),
|
label: raw_i.label.clone(),
|
||||||
};
|
};
|
||||||
quadtree.insert_with_box(ID::Intersection(*id), i.circle().get_bounds().as_bbox());
|
|
||||||
m.intersections.insert(*id, i);
|
m.intersections.insert(*id, i);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -440,16 +379,6 @@ impl Model {
|
|||||||
back_label: r.osm_tags.get("back_label").cloned(),
|
back_label: r.osm_tags.get("back_label").cloned(),
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
let pl = PolyLine::new(vec![
|
|
||||||
m.intersections[&i1].center,
|
|
||||||
m.intersections[&i2].center,
|
|
||||||
]);
|
|
||||||
quadtree.insert_with_box(
|
|
||||||
ID::Road(*id),
|
|
||||||
pl.make_polygons(LANE_THICKNESS * 6.0)
|
|
||||||
.get_bounds()
|
|
||||||
.as_bbox(),
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO Too slow!
|
// TODO Too slow!
|
||||||
@ -458,11 +387,10 @@ impl Model {
|
|||||||
label: None,
|
label: None,
|
||||||
center: Pt2D::center(&data.gps_bounds.must_convert(&b.points)),
|
center: Pt2D::center(&data.gps_bounds.must_convert(&b.points)),
|
||||||
};
|
};
|
||||||
quadtree.insert_with_box(ID::Building(idx), b.polygon().get_bounds().as_bbox());
|
|
||||||
m.buildings.insert(idx, b);
|
m.buildings.insert(idx, b);
|
||||||
}*/
|
}*/
|
||||||
|
|
||||||
(m, quadtree)
|
m
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,4 +1,3 @@
|
|||||||
use aabb_quadtree::QuadTree;
|
|
||||||
use ezgui::{Color, EventCtx, EventLoopMode, GfxCtx, Key, Text, Wizard, GUI};
|
use ezgui::{Color, EventCtx, EventLoopMode, GfxCtx, Key, Text, Wizard, GUI};
|
||||||
use geom::{Distance, Line};
|
use geom::{Distance, Line};
|
||||||
use map_model::raw_data::{StableIntersectionID, StableRoadID};
|
use map_model::raw_data::{StableIntersectionID, StableRoadID};
|
||||||
@ -7,7 +6,6 @@ use synthetic::{BuildingID, Direction, Model, ID};
|
|||||||
|
|
||||||
struct UI {
|
struct UI {
|
||||||
model: Model,
|
model: Model,
|
||||||
quadtree: Option<QuadTree<ID>>,
|
|
||||||
state: State,
|
state: State,
|
||||||
osd: Text,
|
osd: Text,
|
||||||
}
|
}
|
||||||
@ -26,22 +24,17 @@ enum State {
|
|||||||
|
|
||||||
impl UI {
|
impl UI {
|
||||||
fn new(load: Option<&String>) -> UI {
|
fn new(load: Option<&String>) -> UI {
|
||||||
let (model, quadtree): (Model, Option<QuadTree<ID>>) = if let Some(path) = load {
|
let model = if let Some(path) = load {
|
||||||
if path.contains("raw_maps/") {
|
if path.contains("raw_maps/") {
|
||||||
let (m, q) = Model::import(path);
|
Model::import(path)
|
||||||
(m, Some(q))
|
|
||||||
} else {
|
} else {
|
||||||
(
|
abstutil::read_json(path).expect(&format!("Couldn't load {}", path))
|
||||||
abstutil::read_json(path).expect(&format!("Couldn't load {}", path)),
|
|
||||||
None,
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
(Model::new(), None)
|
Model::new()
|
||||||
};
|
};
|
||||||
UI {
|
UI {
|
||||||
model,
|
model,
|
||||||
quadtree,
|
|
||||||
state: State::Viewing,
|
state: State::Viewing,
|
||||||
osd: Text::new(),
|
osd: Text::new(),
|
||||||
}
|
}
|
||||||
@ -58,9 +51,7 @@ impl GUI for UI {
|
|||||||
return EventLoopMode::InputOnly;
|
return EventLoopMode::InputOnly;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
let selected = self
|
let selected = self.model.mouseover_something(ctx.canvas);
|
||||||
.model
|
|
||||||
.mouseover_something(ctx.canvas, self.quadtree.as_ref());
|
|
||||||
|
|
||||||
match self.state {
|
match self.state {
|
||||||
State::MovingIntersection(id) => {
|
State::MovingIntersection(id) => {
|
||||||
@ -197,7 +188,7 @@ impl GUI for UI {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn draw(&self, g: &mut GfxCtx) {
|
fn draw(&self, g: &mut GfxCtx) {
|
||||||
self.model.draw(g, self.quadtree.as_ref());
|
self.model.draw(g);
|
||||||
|
|
||||||
match self.state {
|
match self.state {
|
||||||
State::CreatingRoad(i1) => {
|
State::CreatingRoad(i1) => {
|
||||||
|
Loading…
Reference in New Issue
Block a user