ditch quadtrees in synthetic crate. if anything, switch later to

viewer's World
This commit is contained in:
Dustin Carlino 2019-09-11 13:34:41 -07:00
parent 97361317ed
commit c3ae6bf8f8
4 changed files with 26 additions and 108 deletions

View File

@ -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,

View File

@ -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" }

View File

@ -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
} }
} }

View File

@ -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) => {