mirror of
https://github.com/a-b-street/abstreet.git
synced 2024-11-28 03:35:51 +03:00
splitting into two Bounds types
This commit is contained in:
parent
cc9f0289ab
commit
bb9c98b54e
@ -2,16 +2,16 @@ use aabb_quadtree::geom::Rect;
|
||||
use aabb_quadtree::QuadTree;
|
||||
use abstutil::MultiMap;
|
||||
use geo;
|
||||
use geom::{Bounds, LonLat};
|
||||
use geom::{GPSBounds, LonLat};
|
||||
use map_model::raw_data;
|
||||
use std::collections::BTreeSet;
|
||||
|
||||
// Slight cheat
|
||||
type ParcelIdx = usize;
|
||||
|
||||
pub fn group_parcels(map_bounds: &Bounds, parcels: &mut Vec<raw_data::Parcel>) {
|
||||
pub fn group_parcels(gps_bounds: &GPSBounds, parcels: &mut Vec<raw_data::Parcel>) {
|
||||
// Make a quadtree to quickly prune intersections between parcels
|
||||
let mut quadtree = QuadTree::default(map_bounds.as_bbox());
|
||||
let mut quadtree = QuadTree::default(gps_bounds.as_bbox());
|
||||
for (idx, p) in parcels.iter().enumerate() {
|
||||
quadtree.insert_with_box(idx, get_bbox(&p.points));
|
||||
}
|
||||
@ -107,9 +107,9 @@ fn polygons_intersect(pts1: &Vec<LonLat>, pts2: &Vec<LonLat>) -> bool {
|
||||
}
|
||||
|
||||
fn get_bbox(pts: &Vec<LonLat>) -> Rect {
|
||||
let mut b = Bounds::new();
|
||||
for p in pts.iter() {
|
||||
b.update(p.longitude, p.latitude);
|
||||
let mut b = GPSBounds::new();
|
||||
for pt in pts.iter() {
|
||||
b.update(*pt)
|
||||
}
|
||||
b.as_bbox()
|
||||
}
|
||||
|
@ -24,7 +24,6 @@ mod split_ways;
|
||||
mod srtm;
|
||||
mod traffic_signals;
|
||||
|
||||
use geom::LonLat;
|
||||
use map_model::raw_data;
|
||||
use ordered_float::NotNaN;
|
||||
use srtm::Elevation;
|
||||
@ -71,7 +70,7 @@ pub fn convert(flags: &Flags) -> raw_data::Map {
|
||||
let raw_map = osm::osm_to_raw_roads(&flags.osm);
|
||||
let mut map = split_ways::split_up_roads(&raw_map, &elevation);
|
||||
remove_disconnected::remove_disconnected_roads(&mut map);
|
||||
let bounds = map.get_gps_bounds();
|
||||
let gps_bounds = map.get_gps_bounds();
|
||||
|
||||
println!("Loading parcels from {}", flags.parcels);
|
||||
let parcels_map: raw_data::Map =
|
||||
@ -83,21 +82,20 @@ pub fn convert(flags: &Flags) -> raw_data::Map {
|
||||
for p in parcels_map.parcels {
|
||||
if p.points
|
||||
.iter()
|
||||
.find(|pt| !bounds.contains(pt.longitude, pt.latitude))
|
||||
.find(|pt| !gps_bounds.contains(**pt))
|
||||
.is_none()
|
||||
{
|
||||
map.parcels.push(p);
|
||||
}
|
||||
}
|
||||
group_parcels::group_parcels(&bounds, &mut map.parcels);
|
||||
group_parcels::group_parcels(&gps_bounds, &mut map.parcels);
|
||||
|
||||
for coord in
|
||||
&traffic_signals::extract(&flags.traffic_signals).expect("loading traffic signals failed")
|
||||
for pt in traffic_signals::extract(&flags.traffic_signals)
|
||||
.expect("loading traffic signals failed")
|
||||
.into_iter()
|
||||
{
|
||||
if bounds.contains(coord.longitude, coord.latitude) {
|
||||
let distance = |i: &raw_data::Intersection| {
|
||||
coord.gps_dist_meters(LonLat::new(i.point.longitude, i.point.latitude))
|
||||
};
|
||||
if gps_bounds.contains(pt) {
|
||||
let distance = |i: &raw_data::Intersection| pt.gps_dist_meters(i.point);
|
||||
|
||||
// TODO use a quadtree or some better way to match signals to the closest
|
||||
// intersection
|
||||
@ -124,7 +122,7 @@ pub fn convert(flags: &Flags) -> raw_data::Map {
|
||||
.to_os_string()
|
||||
.into_string()
|
||||
.unwrap();
|
||||
neighborhoods::convert(&flags.neighborhoods, map_name, &bounds);
|
||||
neighborhoods::convert(&flags.neighborhoods, map_name, &gps_bounds);
|
||||
|
||||
timer.done();
|
||||
|
||||
|
@ -1,9 +1,9 @@
|
||||
use abstutil;
|
||||
use geojson::{GeoJson, PolygonType, Value};
|
||||
use geom::{Bounds, LonLat, Pt2D};
|
||||
use geom::{GPSBounds, LonLat, Pt2D};
|
||||
use sim::Neighborhood;
|
||||
|
||||
pub fn convert(geojson_path: &str, map_name: String, bounds: &Bounds) {
|
||||
pub fn convert(geojson_path: &str, map_name: String, gps_bounds: &GPSBounds) {
|
||||
println!("Extracting neighborhoods from {}...", geojson_path);
|
||||
let document: GeoJson = abstutil::read_json(geojson_path).unwrap();
|
||||
match document {
|
||||
@ -11,14 +11,14 @@ pub fn convert(geojson_path: &str, map_name: String, bounds: &Bounds) {
|
||||
let name = f.properties.unwrap()["name"].as_str().unwrap().to_string();
|
||||
match f.geometry.unwrap().value {
|
||||
Value::Polygon(p) => {
|
||||
convert_polygon(p, name, map_name.clone(), bounds);
|
||||
convert_polygon(p, name, map_name.clone(), gps_bounds);
|
||||
}
|
||||
Value::MultiPolygon(polygons) => for (idx, p) in polygons.into_iter().enumerate() {
|
||||
convert_polygon(
|
||||
p,
|
||||
format!("{} portion #{}", name, idx + 1),
|
||||
map_name.clone(),
|
||||
bounds,
|
||||
gps_bounds,
|
||||
);
|
||||
},
|
||||
x => panic!("Unexpected GeoJson value {:?}", x),
|
||||
@ -28,7 +28,7 @@ pub fn convert(geojson_path: &str, map_name: String, bounds: &Bounds) {
|
||||
}
|
||||
}
|
||||
|
||||
fn convert_polygon(input: PolygonType, name: String, map_name: String, bounds: &Bounds) {
|
||||
fn convert_polygon(input: PolygonType, name: String, map_name: String, gps_bounds: &GPSBounds) {
|
||||
if input.len() > 1 {
|
||||
println!("{} has a polygon with an inner ring, skipping", name);
|
||||
return;
|
||||
@ -37,7 +37,7 @@ fn convert_polygon(input: PolygonType, name: String, map_name: String, bounds: &
|
||||
let mut points: Vec<Pt2D> = Vec::new();
|
||||
for pt in &input[0] {
|
||||
assert_eq!(pt.len(), 2);
|
||||
if let Some(pt) = Pt2D::from_gps(LonLat::new(pt[0], pt[1]), bounds) {
|
||||
if let Some(pt) = Pt2D::from_gps(LonLat::new(pt[0], pt[1]), gps_bounds) {
|
||||
points.push(pt);
|
||||
} else {
|
||||
println!(
|
||||
|
@ -1,4 +1,4 @@
|
||||
use geom::{Bounds, LonLat, PolyLine, Pt2D};
|
||||
use geom::{GPSBounds, LonLat, PolyLine, Pt2D};
|
||||
use quick_xml::events::Event;
|
||||
use quick_xml::reader::Reader;
|
||||
use std::collections::BTreeMap;
|
||||
@ -27,7 +27,7 @@ pub enum ExtraShapeGeom {
|
||||
Points(PolyLine),
|
||||
}
|
||||
|
||||
pub fn load(path: &String, gps_bounds: &Bounds) -> Result<Vec<ExtraShape>, io::Error> {
|
||||
pub fn load(path: &String, gps_bounds: &GPSBounds) -> Result<Vec<ExtraShape>, io::Error> {
|
||||
info!("Opening {}", path);
|
||||
let f = File::open(path).unwrap();
|
||||
let mut reader = Reader::from_reader(io::BufReader::new(f));
|
||||
@ -122,7 +122,7 @@ pub fn load(path: &String, gps_bounds: &Bounds) -> Result<Vec<ExtraShape>, io::E
|
||||
return Ok(shapes);
|
||||
}
|
||||
|
||||
fn parse_pt(input: &str, gps_bounds: &Bounds) -> Option<Pt2D> {
|
||||
fn parse_pt(input: &str, gps_bounds: &GPSBounds) -> Option<Pt2D> {
|
||||
let coords: Vec<&str> = input.split(",").collect();
|
||||
if coords.len() != 2 {
|
||||
return None;
|
||||
|
@ -55,8 +55,8 @@ impl Renderable for DrawBuilding {
|
||||
|
||||
fn get_bounds(&self) -> Bounds {
|
||||
let mut b = self.fill_polygon.get_bounds();
|
||||
b.update_pt(self.front_path.pt1());
|
||||
b.update_pt(self.front_path.pt2());
|
||||
b.update(self.front_path.pt1());
|
||||
b.update(self.front_path.pt2());
|
||||
b
|
||||
}
|
||||
|
||||
|
@ -171,7 +171,7 @@ impl Renderable for DrawLane {
|
||||
map.get_source_intersection(self.id).elevation,
|
||||
map.get_destination_intersection(self.id).elevation,
|
||||
),
|
||||
format!("Lane is {}m long", l.length()),
|
||||
format!("Lane is {} long", l.length()),
|
||||
];
|
||||
for (k, v) in &r.osm_tags {
|
||||
lines.push(format!("{} = {}", k, v));
|
||||
|
@ -1,60 +0,0 @@
|
||||
use aabb_quadtree::geom::{Point, Rect};
|
||||
use std::f64;
|
||||
use {LonLat, Pt2D};
|
||||
|
||||
// TODO argh, use this in kml too
|
||||
// TODO this maybe represents LonLat only?
|
||||
#[derive(Clone, Copy, Debug, Serialize, Deserialize)]
|
||||
pub struct Bounds {
|
||||
pub min_x: f64,
|
||||
pub min_y: f64,
|
||||
pub max_x: f64,
|
||||
pub max_y: f64,
|
||||
|
||||
// TODO hack to easily construct test maps
|
||||
pub represents_world_space: bool,
|
||||
}
|
||||
|
||||
impl Bounds {
|
||||
pub fn new() -> Bounds {
|
||||
Bounds {
|
||||
min_x: f64::MAX,
|
||||
min_y: f64::MAX,
|
||||
max_x: f64::MIN,
|
||||
max_y: f64::MIN,
|
||||
represents_world_space: false,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn update(&mut self, x: f64, y: f64) {
|
||||
self.min_x = self.min_x.min(x);
|
||||
self.max_x = self.max_x.max(x);
|
||||
self.min_y = self.min_y.min(y);
|
||||
self.max_y = self.max_y.max(y);
|
||||
}
|
||||
|
||||
pub fn update_pt(&mut self, pt: Pt2D) {
|
||||
self.update(pt.x(), pt.y());
|
||||
}
|
||||
|
||||
pub fn update_coord(&mut self, coord: LonLat) {
|
||||
self.update(coord.longitude, coord.latitude);
|
||||
}
|
||||
|
||||
pub fn contains(&self, x: f64, y: f64) -> bool {
|
||||
x >= self.min_x && x <= self.max_x && y >= self.min_y && y <= self.max_y
|
||||
}
|
||||
|
||||
pub fn as_bbox(&self) -> Rect {
|
||||
Rect {
|
||||
top_left: Point {
|
||||
x: self.min_x as f32,
|
||||
y: self.min_y as f32,
|
||||
},
|
||||
bottom_right: Point {
|
||||
x: self.max_x as f32,
|
||||
y: self.max_y as f32,
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
@ -24,7 +24,6 @@ impl Circle {
|
||||
max_x: self.center.x() + self.radius,
|
||||
min_y: self.center.y() - self.radius,
|
||||
max_y: self.center.y() + self.radius,
|
||||
represents_world_space: false,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,4 +1,6 @@
|
||||
use pt::HashablePt2D;
|
||||
use aabb_quadtree::geom::{Point, Rect};
|
||||
use std::f64;
|
||||
use HashablePt2D;
|
||||
|
||||
// longitude is x, latitude is y
|
||||
#[derive(Copy, Clone, PartialEq, Debug, Serialize, Deserialize)]
|
||||
@ -37,3 +39,53 @@ impl LonLat {
|
||||
HashablePt2D::new(self.longitude, self.latitude)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Serialize, Deserialize)]
|
||||
pub struct GPSBounds {
|
||||
pub min_lon: f64,
|
||||
pub min_lat: f64,
|
||||
pub max_lon: f64,
|
||||
pub max_lat: f64,
|
||||
|
||||
// TODO hack to easily construct test maps
|
||||
pub represents_world_space: bool,
|
||||
}
|
||||
|
||||
impl GPSBounds {
|
||||
pub fn new() -> GPSBounds {
|
||||
GPSBounds {
|
||||
min_lon: f64::MAX,
|
||||
min_lat: f64::MAX,
|
||||
max_lon: f64::MIN,
|
||||
max_lat: f64::MIN,
|
||||
represents_world_space: false,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn update(&mut self, pt: LonLat) {
|
||||
self.min_lon = self.min_lon.min(pt.longitude);
|
||||
self.max_lon = self.max_lon.max(pt.longitude);
|
||||
self.min_lat = self.min_lat.min(pt.latitude);
|
||||
self.max_lat = self.max_lat.max(pt.latitude);
|
||||
}
|
||||
|
||||
pub fn contains(&self, pt: LonLat) -> bool {
|
||||
pt.longitude >= self.min_lon
|
||||
&& pt.longitude <= self.max_lon
|
||||
&& pt.latitude >= self.min_lat
|
||||
&& pt.latitude <= self.max_lat
|
||||
}
|
||||
|
||||
pub fn as_bbox(&self) -> Rect {
|
||||
Rect {
|
||||
top_left: Point {
|
||||
x: self.min_lon as f32,
|
||||
y: self.min_lat as f32,
|
||||
},
|
||||
bottom_right: Point {
|
||||
x: self.max_lon as f32,
|
||||
y: self.max_lat as f32,
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -7,7 +7,6 @@ extern crate serde;
|
||||
extern crate serde_derive;
|
||||
|
||||
mod angle;
|
||||
mod bounds;
|
||||
mod circle;
|
||||
mod gps;
|
||||
mod line;
|
||||
@ -16,14 +15,13 @@ mod polyline;
|
||||
mod pt;
|
||||
|
||||
pub use angle::Angle;
|
||||
pub use bounds::Bounds;
|
||||
pub use circle::Circle;
|
||||
use dimensioned::si;
|
||||
pub use gps::LonLat;
|
||||
pub use gps::{GPSBounds, LonLat};
|
||||
pub use line::Line;
|
||||
pub use polygon::{Polygon, Triangle};
|
||||
pub use polyline::PolyLine;
|
||||
pub use pt::{HashablePt2D, Pt2D};
|
||||
pub use pt::{Bounds, HashablePt2D, Pt2D};
|
||||
use std::marker;
|
||||
|
||||
// About 0.4 inches... which is quite tiny on the scale of things. :)
|
||||
|
@ -95,9 +95,9 @@ impl Polygon {
|
||||
pub fn get_bounds(&self) -> Bounds {
|
||||
let mut b = Bounds::new();
|
||||
for tri in &self.triangles {
|
||||
b.update_pt(tri.pt1);
|
||||
b.update_pt(tri.pt2);
|
||||
b.update_pt(tri.pt3);
|
||||
b.update(tri.pt1);
|
||||
b.update(tri.pt2);
|
||||
b.update(tri.pt3);
|
||||
}
|
||||
b
|
||||
}
|
||||
|
@ -1,7 +1,8 @@
|
||||
use aabb_quadtree::geom::{Point, Rect};
|
||||
use ordered_float::NotNaN;
|
||||
use std::f64;
|
||||
use std::fmt;
|
||||
use {Angle, Bounds, LonLat};
|
||||
use {Angle, GPSBounds, LonLat};
|
||||
|
||||
// This represents world-space in meters.
|
||||
#[derive(Clone, Copy, Debug, PartialEq, Serialize, Deserialize)]
|
||||
@ -28,18 +29,18 @@ impl Pt2D {
|
||||
Pt2D { x, y }
|
||||
}
|
||||
|
||||
pub fn from_gps(gps: LonLat, b: &Bounds) -> Option<Pt2D> {
|
||||
pub fn from_gps(gps: LonLat, b: &GPSBounds) -> Option<Pt2D> {
|
||||
// TODO hack to construct test maps more easily
|
||||
if b.represents_world_space {
|
||||
return Some(Pt2D::new(gps.longitude, gps.latitude));
|
||||
}
|
||||
|
||||
if !b.contains(gps.longitude, gps.latitude) {
|
||||
if !b.contains(gps) {
|
||||
return None;
|
||||
}
|
||||
|
||||
// Invert y, so that the northernmost latitude is 0. Screen drawing order, not Cartesian grid.
|
||||
let base = LonLat::new(b.min_x, b.max_y);
|
||||
let base = LonLat::new(b.min_lon, b.max_lat);
|
||||
|
||||
// Apparently the aabb_quadtree can't handle 0, so add a bit.
|
||||
// TODO epsilon or epsilon - 1.0?
|
||||
@ -50,7 +51,7 @@ impl Pt2D {
|
||||
Some(Pt2D::new(dx, dy))
|
||||
}
|
||||
|
||||
pub fn to_gps(&self, gps_bounds: &Bounds) -> LonLat {
|
||||
pub fn to_gps(&self, _gps_bounds: &GPSBounds) -> LonLat {
|
||||
// TODO wait, this is going to be more complicated
|
||||
LonLat::new(0.0, 0.0)
|
||||
}
|
||||
@ -107,6 +108,7 @@ impl From<HashablePt2D> for Pt2D {
|
||||
}
|
||||
|
||||
// This isn't opinionated about what the (x, y) represents -- could be lat/lon or world space.
|
||||
// TODO So rename it HashablePair or something
|
||||
#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq, PartialOrd, Ord)]
|
||||
pub struct HashablePt2D {
|
||||
x_nan: NotNaN<f64>,
|
||||
@ -135,3 +137,46 @@ impl From<Pt2D> for HashablePt2D {
|
||||
HashablePt2D::new(pt.x(), pt.y())
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Serialize, Deserialize)]
|
||||
pub struct Bounds {
|
||||
pub min_x: f64,
|
||||
pub min_y: f64,
|
||||
pub max_x: f64,
|
||||
pub max_y: f64,
|
||||
}
|
||||
|
||||
impl Bounds {
|
||||
pub fn new() -> Bounds {
|
||||
Bounds {
|
||||
min_x: f64::MAX,
|
||||
min_y: f64::MAX,
|
||||
max_x: f64::MIN,
|
||||
max_y: f64::MIN,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn update(&mut self, pt: Pt2D) {
|
||||
self.min_x = self.min_x.min(pt.x);
|
||||
self.max_x = self.max_x.max(pt.x);
|
||||
self.min_y = self.min_y.min(pt.y);
|
||||
self.max_y = self.max_y.max(pt.y);
|
||||
}
|
||||
|
||||
pub fn contains(&self, pt: Pt2D) -> bool {
|
||||
pt.x >= self.min_x && pt.x <= self.max_x && pt.y >= self.min_y && pt.y <= self.max_y
|
||||
}
|
||||
|
||||
pub fn as_bbox(&self) -> Rect {
|
||||
Rect {
|
||||
top_left: Point {
|
||||
x: self.min_x as f32,
|
||||
y: self.min_y as f32,
|
||||
},
|
||||
bottom_right: Point {
|
||||
x: self.max_x as f32,
|
||||
y: self.max_y as f32,
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -141,8 +141,8 @@ impl DrawBuilding {
|
||||
fn get_bounds(&self) -> Bounds {
|
||||
// The bbox only shrinks; the original position is the worst case.
|
||||
let mut b = self.polygon.get_bounds();
|
||||
b.update_pt(self.line.pt1());
|
||||
b.update_pt(self.line.pt2());
|
||||
b.update(self.line.pt1());
|
||||
b.update(self.line.pt2());
|
||||
b
|
||||
}
|
||||
}
|
||||
|
@ -1,16 +1,13 @@
|
||||
// Copyright 2018 Google LLC, licensed under http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
use geom;
|
||||
use geom::{GPSBounds, LonLat};
|
||||
use map_model;
|
||||
use quick_xml::events::Event;
|
||||
use quick_xml::reader::Reader;
|
||||
use std::fs::File;
|
||||
use std::{f64, io};
|
||||
|
||||
pub fn load(
|
||||
path: &String,
|
||||
b: &geom::Bounds,
|
||||
) -> Result<Vec<map_model::raw_data::Parcel>, io::Error> {
|
||||
pub fn load(path: &String, b: &GPSBounds) -> Result<Vec<map_model::raw_data::Parcel>, io::Error> {
|
||||
println!("Opening {}", path);
|
||||
let f = File::open(path).unwrap();
|
||||
let mut reader = Reader::from_reader(io::BufReader::new(f));
|
||||
@ -40,10 +37,10 @@ pub fn load(
|
||||
points: Vec::new(),
|
||||
block: 0,
|
||||
};
|
||||
for pt in text.split(" ") {
|
||||
if let Some((lon, lat)) = parse_pt(pt) {
|
||||
if b.contains(lon, lat) {
|
||||
parcel.points.push(geom::LonLat::new(lon, lat));
|
||||
for raw_pt in text.split(" ") {
|
||||
if let Some(pt) = parse_pt(raw_pt) {
|
||||
if b.contains(pt) {
|
||||
parcel.points.push(pt);
|
||||
} else {
|
||||
ok = false;
|
||||
}
|
||||
@ -69,13 +66,13 @@ pub fn load(
|
||||
return Ok(parcels);
|
||||
}
|
||||
|
||||
fn parse_pt(input: &str) -> Option<(f64, f64)> {
|
||||
fn parse_pt(input: &str) -> Option<LonLat> {
|
||||
let coords: Vec<&str> = input.split(",").collect();
|
||||
if coords.len() != 2 {
|
||||
return None;
|
||||
}
|
||||
return match (coords[0].parse::<f64>(), coords[1].parse::<f64>()) {
|
||||
(Ok(lon), Ok(lat)) => Some((lon, lat)),
|
||||
(Ok(lon), Ok(lat)) => Some(LonLat::new(lon, lat)),
|
||||
_ => None,
|
||||
};
|
||||
}
|
||||
|
@ -18,11 +18,11 @@ fn main() {
|
||||
}
|
||||
|
||||
// TODO don't hardcode
|
||||
let bounds = geom::Bounds {
|
||||
min_x: -122.4416,
|
||||
max_x: -122.2421,
|
||||
min_y: 47.5793,
|
||||
max_y: 47.7155,
|
||||
let bounds = geom::GPSBounds {
|
||||
min_lon: -122.4416,
|
||||
max_lon: -122.2421,
|
||||
min_lat: 47.5793,
|
||||
max_lat: 47.7155,
|
||||
represents_world_space: false,
|
||||
};
|
||||
// TODO could use a better output format now
|
||||
|
@ -1,6 +1,6 @@
|
||||
use abstutil::Timer;
|
||||
use dimensioned::si;
|
||||
use geom::{Bounds, HashablePt2D, Line, PolyLine, Pt2D};
|
||||
use geom::{Bounds, GPSBounds, HashablePt2D, Line, PolyLine, Pt2D};
|
||||
use make::sidewalk_finder::find_sidewalk_points;
|
||||
use raw_data;
|
||||
use std::collections::HashSet;
|
||||
@ -9,7 +9,7 @@ use {Building, BuildingID, FrontPath, Lane};
|
||||
pub fn make_all_buildings(
|
||||
results: &mut Vec<Building>,
|
||||
input: &Vec<raw_data::Building>,
|
||||
gps_bounds: &Bounds,
|
||||
gps_bounds: &GPSBounds,
|
||||
bounds: &Bounds,
|
||||
lanes: &Vec<Lane>,
|
||||
timer: &mut Timer,
|
||||
|
@ -1,6 +1,6 @@
|
||||
use abstutil::Timer;
|
||||
use dimensioned::si;
|
||||
use geom::{Bounds, HashablePt2D, Pt2D};
|
||||
use geom::{Bounds, GPSBounds, HashablePt2D, Pt2D};
|
||||
use gtfs;
|
||||
use make::sidewalk_finder::find_sidewalk_points;
|
||||
use multimap::MultiMap;
|
||||
@ -13,7 +13,7 @@ pub fn make_bus_stops(
|
||||
lanes: &mut Vec<Lane>,
|
||||
roads: &Vec<Road>,
|
||||
bus_routes: &Vec<gtfs::Route>,
|
||||
gps_bounds: &Bounds,
|
||||
gps_bounds: &GPSBounds,
|
||||
bounds: &Bounds,
|
||||
timer: &mut Timer,
|
||||
) -> (BTreeMap<BusStopID, BusStop>, Vec<BusRoute>) {
|
||||
|
@ -1,6 +1,6 @@
|
||||
use abstutil::Timer;
|
||||
use dimensioned::si;
|
||||
use geom::{Bounds, HashablePt2D, Pt2D};
|
||||
use geom::{Bounds, GPSBounds, HashablePt2D, Pt2D};
|
||||
use make::sidewalk_finder::find_sidewalk_points;
|
||||
use raw_data;
|
||||
use std::collections::HashSet;
|
||||
@ -9,7 +9,7 @@ use {Lane, Parcel, ParcelID};
|
||||
pub fn make_all_parcels(
|
||||
results: &mut Vec<Parcel>,
|
||||
input: &Vec<raw_data::Parcel>,
|
||||
gps_bounds: &Bounds,
|
||||
gps_bounds: &GPSBounds,
|
||||
bounds: &Bounds,
|
||||
lanes: &Vec<Lane>,
|
||||
timer: &mut Timer,
|
||||
|
@ -88,7 +88,7 @@ fn lane_to_line_string(l: &Lane) -> geo::LineString<f64> {
|
||||
fn lane_to_rect(l: &Lane) -> Rect {
|
||||
let mut b = Bounds::new();
|
||||
for pt in l.lane_center_pts.points() {
|
||||
b.update_pt(*pt);
|
||||
b.update(*pt);
|
||||
}
|
||||
b.as_bbox()
|
||||
}
|
||||
|
@ -3,7 +3,7 @@
|
||||
use abstutil;
|
||||
use abstutil::{Error, Timer};
|
||||
use edits::RoadEdits;
|
||||
use geom::{Bounds, HashablePt2D, LonLat, PolyLine, Pt2D};
|
||||
use geom::{Bounds, GPSBounds, HashablePt2D, LonLat, PolyLine, Pt2D};
|
||||
use make;
|
||||
use raw_data;
|
||||
use std::collections::{BTreeMap, BTreeSet, HashMap};
|
||||
@ -26,8 +26,8 @@ pub struct Map {
|
||||
bus_routes: Vec<BusRoute>,
|
||||
areas: Vec<Area>,
|
||||
|
||||
// TODO maybe dont need to retain GPS stuff later
|
||||
gps_bounds: Bounds,
|
||||
gps_bounds: GPSBounds,
|
||||
bounds: Bounds,
|
||||
|
||||
name: String,
|
||||
road_edits: RoadEdits,
|
||||
@ -57,11 +57,24 @@ impl Map {
|
||||
) -> Map {
|
||||
timer.start("raw_map to Map");
|
||||
let gps_bounds = data.get_gps_bounds();
|
||||
let bounds = gps_to_map_bounds(&gps_bounds);
|
||||
|
||||
let bounds = {
|
||||
// min_y here due to the wacky y inversion
|
||||
let max_screen_pt = Pt2D::from_gps(
|
||||
LonLat::new(gps_bounds.max_lon, gps_bounds.min_lat),
|
||||
&gps_bounds,
|
||||
).unwrap();
|
||||
let mut b = Bounds::new();
|
||||
b.update(Pt2D::new(0.0, 0.0));
|
||||
b.update(max_screen_pt);
|
||||
b
|
||||
};
|
||||
|
||||
let mut m = Map {
|
||||
name,
|
||||
road_edits,
|
||||
gps_bounds,
|
||||
gps_bounds: gps_bounds.clone(),
|
||||
bounds: bounds.clone(),
|
||||
roads: Vec::new(),
|
||||
lanes: Vec::new(),
|
||||
intersections: Vec::new(),
|
||||
@ -412,12 +425,12 @@ impl Map {
|
||||
}
|
||||
|
||||
// TODO can we return a borrow?
|
||||
pub fn get_gps_bounds(&self) -> Bounds {
|
||||
pub fn get_gps_bounds(&self) -> GPSBounds {
|
||||
self.gps_bounds.clone()
|
||||
}
|
||||
|
||||
pub fn get_bounds(&self) -> Bounds {
|
||||
gps_to_map_bounds(&self.gps_bounds)
|
||||
self.bounds.clone()
|
||||
}
|
||||
|
||||
pub fn get_driving_lane_from_bldg(&self, bldg: BuildingID) -> Result<LaneID, Error> {
|
||||
@ -491,12 +504,3 @@ impl Map {
|
||||
info!("Saved {}", path);
|
||||
}
|
||||
}
|
||||
|
||||
fn gps_to_map_bounds(gps: &Bounds) -> Bounds {
|
||||
// min_y here due to the wacky y inversion
|
||||
let max_screen_pt = Pt2D::from_gps(LonLat::new(gps.max_x, gps.min_y), gps).unwrap();
|
||||
let mut b = Bounds::new();
|
||||
b.update_pt(Pt2D::new(0.0, 0.0));
|
||||
b.update_pt(max_screen_pt);
|
||||
b
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
use dimensioned::si;
|
||||
use geom::{Bounds, HashablePt2D, LonLat};
|
||||
use geom::{GPSBounds, HashablePt2D, LonLat};
|
||||
use gtfs::Route;
|
||||
use std::collections::BTreeMap;
|
||||
use AreaType;
|
||||
@ -29,30 +29,30 @@ impl Map {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_gps_bounds(&self) -> Bounds {
|
||||
let mut bounds = Bounds::new();
|
||||
pub fn get_gps_bounds(&self) -> GPSBounds {
|
||||
let mut bounds = GPSBounds::new();
|
||||
|
||||
for r in &self.roads {
|
||||
for pt in &r.points {
|
||||
bounds.update_coord(*pt);
|
||||
bounds.update(*pt);
|
||||
}
|
||||
}
|
||||
for i in &self.intersections {
|
||||
bounds.update_coord(i.point);
|
||||
bounds.update(i.point);
|
||||
}
|
||||
for b in &self.buildings {
|
||||
for pt in &b.points {
|
||||
bounds.update_coord(*pt);
|
||||
bounds.update(*pt);
|
||||
}
|
||||
}
|
||||
for a in &self.areas {
|
||||
for pt in &a.points {
|
||||
bounds.update_coord(*pt);
|
||||
bounds.update(*pt);
|
||||
}
|
||||
}
|
||||
for p in &self.parcels {
|
||||
for pt in &p.points {
|
||||
bounds.update_coord(*pt);
|
||||
bounds.update(*pt);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
use abstutil;
|
||||
use geom::{Bounds, Polygon, Pt2D};
|
||||
use geom::{GPSBounds, Polygon, Pt2D};
|
||||
use map_model::{BuildingID, Map, RoadID};
|
||||
use rand::Rng;
|
||||
use std::collections::{BTreeSet, HashMap, HashSet};
|
||||
@ -88,7 +88,7 @@ impl Neighborhood {
|
||||
}
|
||||
|
||||
// https://wiki.openstreetmap.org/wiki/Osmosis/Polygon_Filter_File_Format
|
||||
pub fn save_as_osmosis(&self, gps_bounds: &Bounds) -> Result<(), Error> {
|
||||
pub fn save_as_osmosis(&self, gps_bounds: &GPSBounds) -> Result<(), Error> {
|
||||
let path = format!("{}.poly", self.name);
|
||||
let mut f = File::create(&path)?;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user