infer clipping polygon from entire .osm if no polygon is specified

This commit is contained in:
Dustin Carlino 2019-09-02 12:37:40 -07:00
parent 3fd59ebdb5
commit 1910d06bc7
5 changed files with 65 additions and 63 deletions

View File

@ -5,11 +5,9 @@ mod remove_disconnected;
mod split_ways;
use abstutil::Timer;
use geom::{Distance, FindClosest, GPSBounds, Line, LonLat, PolyLine, Polygon, Pt2D};
use geom::{Distance, FindClosest, Line, PolyLine, Pt2D};
use kml::ExtraShapes;
use map_model::{raw_data, LaneID, OffstreetParking, Position, LANE_THICKNESS};
use std::fs::File;
use std::io::{BufRead, BufReader};
use structopt::StructOpt;
#[derive(StructOpt, Debug)]
@ -49,13 +47,8 @@ pub struct Flags {
}
pub fn convert(flags: &Flags, timer: &mut abstutil::Timer) -> raw_data::Map {
if flags.clip.is_empty() {
panic!("You must specify an Osmosis boundary polygon with --clip");
}
let mut map = split_ways::split_up_roads(
osm::extract_osm(&flags.osm, read_osmosis_polygon(&flags.clip), timer),
timer,
);
let mut map =
split_ways::split_up_roads(osm::extract_osm(&flags.osm, &flags.clip, timer), timer);
clip::clip_map(&mut map, timer);
remove_disconnected::remove_disconnected_roads(&mut map, timer);
@ -136,36 +129,6 @@ fn use_parking_hints(map: &mut raw_data::Map, path: &str, timer: &mut Timer) {
timer.stop("apply parking hints");
}
fn read_osmosis_polygon(path: &str) -> raw_data::Map {
let mut pts: Vec<LonLat> = Vec::new();
let mut gps_bounds = GPSBounds::new();
for (idx, maybe_line) in BufReader::new(File::open(path).unwrap())
.lines()
.enumerate()
{
if idx == 0 || idx == 1 {
continue;
}
let line = maybe_line.unwrap();
if line == "END" {
break;
}
let parts: Vec<&str> = line.trim_start().split(" ").collect();
assert!(parts.len() == 2);
let pt = LonLat::new(
parts[0].parse::<f64>().unwrap(),
parts[1].parse::<f64>().unwrap(),
);
pts.push(pt);
gps_bounds.update(pt);
}
let mut map = raw_data::Map::blank();
map.boundary_polygon = Polygon::new(&gps_bounds.must_convert(&pts));
map.gps_bounds = gps_bounds;
map
}
fn use_offstreet_parking(map: &mut raw_data::Map, path: &str, timer: &mut Timer) {
timer.start("match offstreet parking points");
let shapes = kml::load(path, &map.gps_bounds, timer).expect("loading offstreet_parking failed");

View File

@ -1,12 +1,14 @@
use abstutil::{FileWithProgress, Timer};
use geom::{HashablePt2D, LonLat, Polygon, Pt2D};
use geom::{GPSBounds, HashablePt2D, LonLat, Polygon, Pt2D};
use map_model::{raw_data, AreaType};
use osm_xml;
use std::collections::{BTreeMap, HashMap, HashSet};
use std::fs::File;
use std::io::{BufRead, BufReader};
pub fn extract_osm(
osm_path: &str,
mut map: raw_data::Map,
maybe_clip_path: &str,
timer: &mut Timer,
) -> (
raw_data::Map,
@ -25,6 +27,17 @@ pub fn extract_osm(
);
done(timer);
let mut map = if maybe_clip_path.is_empty() {
let mut m = raw_data::Map::blank();
for node in doc.nodes.values() {
m.gps_bounds.update(LonLat::new(node.lon, node.lat));
}
m.boundary_polygon = m.gps_bounds.to_bounds().get_rectangle();
m
} else {
read_osmosis_polygon(maybe_clip_path)
};
let mut id_to_way: HashMap<i64, Vec<Pt2D>> = HashMap::new();
let mut roads: Vec<raw_data::Road> = Vec::new();
let mut traffic_signals: HashSet<HashablePt2D> = HashSet::new();
@ -79,13 +92,20 @@ pub fn extract_osm(
parking_lane_back: false,
});
} else if is_bldg(&tags) {
let deduped = Pt2D::approx_dedupe(pts, geom::EPSILON_DIST);
if deduped.len() < 3 {
continue;
}
map.buildings.push(raw_data::Building {
osm_way_id: way.id,
polygon: Polygon::new(&Pt2D::approx_dedupe(pts, geom::EPSILON_DIST)),
polygon: Polygon::new(&deduped),
osm_tags: tags,
parking: None,
});
} else if let Some(at) = get_area_type(&tags) {
if pts.len() < 3 {
continue;
}
map.areas.push(raw_data::Area {
area_type: at,
osm_id: way.id,
@ -291,3 +311,33 @@ fn glue_multipolygon(mut pts_per_way: Vec<Vec<Pt2D>>) -> Vec<Polygon> {
polygons.push(Polygon::new(&result));
polygons
}
fn read_osmosis_polygon(path: &str) -> raw_data::Map {
let mut pts: Vec<LonLat> = Vec::new();
let mut gps_bounds = GPSBounds::new();
for (idx, maybe_line) in BufReader::new(File::open(path).unwrap())
.lines()
.enumerate()
{
if idx == 0 || idx == 1 {
continue;
}
let line = maybe_line.unwrap();
if line == "END" {
break;
}
let parts: Vec<&str> = line.trim_start().split(" ").collect();
assert!(parts.len() == 2);
let pt = LonLat::new(
parts[0].parse::<f64>().unwrap(),
parts[1].parse::<f64>().unwrap(),
);
pts.push(pt);
gps_bounds.update(pt);
}
let mut map = raw_data::Map::blank();
map.boundary_polygon = Polygon::new(&gps_bounds.must_convert(&pts));
map.gps_bounds = gps_bounds;
map
}

View File

@ -4,26 +4,16 @@ My current priority is to make Seattle work very well, but if you want to try
out A/B Street in another place, you can follow this guide. Please file a Github
issue or email <dabreegster@gmail.com> if you hit any problems.
First you need to prepare input. Obtain a `.osm` file and create an
[Osmosis polygon filter file](https://wiki.openstreetmap.org/wiki/Osmosis/Polygon_Filter_File_Format)
for the area you want to import. You can clip a `.osm` like this:
```
osmosis \
--read-xml enableDateParsing=no file=large_area.osm \
--bounding-polygon file=clip.poly completeWays=true \
--write-xml data/input/your_city.osm
```
First obtain a `.osm` with your desired area. You can use a tool like Osmosis to
clip a specific area from a large file. Put the `.osm` in `data/input/`.
Then you'll run some tools to import the map. Make sure you can compile
everything [from source](INSTRUCTIONS.md). Keep `clip.poly` around for the next
command.
everything [from source](INSTRUCTIONS.md).
```
cd convert_osm
cargo run --release -- \
--osm=../data/input/your_city.osm \
--clip=../data/input/clip.poly \
--output=../data/raw_maps/your_city.bin
cd ../precompute
cargo run --release -- ../data/raw_maps/your_city.bin

View File

@ -1,4 +1,4 @@
use crate::{LonLat, Pt2D};
use crate::{LonLat, Polygon, Pt2D};
use aabb_quadtree::geom::{Point, Rect};
use serde_derive::{Deserialize, Serialize};
use std::f64;
@ -58,13 +58,14 @@ impl Bounds {
}
}
pub fn get_corners(&self) -> Vec<Pt2D> {
vec![
pub fn get_rectangle(&self) -> Polygon {
Polygon::new(&vec![
Pt2D::new(self.min_x, self.min_y),
Pt2D::new(self.max_x, self.min_y),
Pt2D::new(self.max_x, self.max_y),
Pt2D::new(self.min_x, self.max_y),
]
Pt2D::new(self.min_x, self.min_y),
])
}
}

View File

@ -81,12 +81,10 @@ impl Neighborhood {
}
fn make_everywhere(map: &Map) -> Neighborhood {
let mut pts = map.get_bounds().get_corners();
pts.push(pts[0]);
Neighborhood {
map_name: map.get_name().to_string(),
name: "_everywhere_".to_string(),
polygon: Polygon::new(&pts),
polygon: map.get_bounds().get_rectangle(),
}
}
}