mirror of
https://github.com/a-b-street/abstreet.git
synced 2024-12-24 06:55:40 +03:00
Generate city picker maps from a bunch of small maps, instead of one huge map. Use for Paris. One giant map covering everything there is going to be too large.
This commit is contained in:
parent
d43bf2c869
commit
b6be9c81d5
@ -408,6 +408,10 @@
|
||||
"checksum": "69df8b1a1f93c5d52f872ef18eb5cde2",
|
||||
"size_bytes": 8485994
|
||||
},
|
||||
"data/system/paris/city.bin": {
|
||||
"checksum": "0fd1914ef16ad3797ccfaf14c36c3a17",
|
||||
"size_bytes": 2279409
|
||||
},
|
||||
"data/system/paris/maps/center.bin": {
|
||||
"checksum": "5ed145aee161a464011fb4bc16d3110a",
|
||||
"size_bytes": 37829561
|
||||
|
@ -8,6 +8,7 @@ rm -fv data/system/seattle/maps/huge_seattle.bin data/input/raw_maps/huge_seattl
|
||||
./import.sh --raw --map --city=berlin
|
||||
./import.sh --raw --map --city=krakow
|
||||
./import.sh --raw --map --city=london
|
||||
./import.sh --raw --map --city_overview --city=paris
|
||||
./import.sh --raw --map --city=tel_aviv
|
||||
./import.sh --raw --map --city=xian
|
||||
|
||||
|
@ -25,6 +25,7 @@ struct Job {
|
||||
raw_to_map: bool,
|
||||
scenario: bool,
|
||||
scenario_everyone: bool,
|
||||
city_overview: bool,
|
||||
|
||||
skip_ch: bool,
|
||||
keep_bldg_tags: bool,
|
||||
@ -49,6 +50,8 @@ fn main() {
|
||||
scenario: args.enabled("--scenario"),
|
||||
// Produce a variation of the weekday scenario including off-map trips.
|
||||
scenario_everyone: args.enabled("--scenario_everyone"),
|
||||
// Produce a city overview from all of the individual maps in a city.
|
||||
city_overview: args.enabled("--city_overview"),
|
||||
// Skip the most expensive step of --map, building contraction hierarchies. The simulation
|
||||
// will use a slower method to pathfind.
|
||||
skip_ch: args.enabled("--skip_ch"),
|
||||
@ -70,11 +73,12 @@ fn main() {
|
||||
&& !job.raw_to_map
|
||||
&& !job.scenario
|
||||
&& !job.scenario_everyone
|
||||
&& !job.city_overview
|
||||
&& job.oneshot.is_none()
|
||||
{
|
||||
println!(
|
||||
"Nothing to do! Pass some combination of --raw, --map, --scenario, \
|
||||
--scenario_everyone or --oneshot"
|
||||
--scenario_everyone, --city_overview, or --oneshot"
|
||||
);
|
||||
std::process::exit(1);
|
||||
}
|
||||
@ -221,6 +225,15 @@ fn main() {
|
||||
timer.stop(format!("scenario_everyone for {}", name.describe()));
|
||||
}
|
||||
}
|
||||
|
||||
if job.city_overview {
|
||||
timer.start(format!("generate city overview for {}", job.city));
|
||||
abstutil::write_binary(
|
||||
abstutil::path(format!("system/{}/city.bin", job.city)),
|
||||
&map_model::City::from_individual_maps(&job.city, &mut timer),
|
||||
);
|
||||
timer.stop(format!("generate city overview for {}", job.city));
|
||||
}
|
||||
}
|
||||
|
||||
fn oneshot(
|
||||
|
@ -142,7 +142,7 @@ pub fn raw_to_map(
|
||||
timer.start("generating city manifest");
|
||||
abstutil::write_binary(
|
||||
abstutil::path(format!("system/{}/city.bin", map.get_city_name())),
|
||||
&map_model::City::new(&map),
|
||||
&map_model::City::from_huge_map(&map),
|
||||
);
|
||||
timer.stop("generating city manifest");
|
||||
}
|
||||
|
@ -1,7 +1,7 @@
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use abstutil::MapName;
|
||||
use geom::{LonLat, Polygon, Ring};
|
||||
use abstutil::{MapName, Timer};
|
||||
use geom::{GPSBounds, LonLat, Polygon, Ring};
|
||||
|
||||
use crate::{AreaType, Map};
|
||||
|
||||
@ -12,13 +12,14 @@ pub struct City {
|
||||
pub name: String,
|
||||
pub boundary: Polygon,
|
||||
pub areas: Vec<(AreaType, Polygon)>,
|
||||
// The individual maps
|
||||
/// The individual maps
|
||||
pub regions: Vec<(MapName, Polygon)>,
|
||||
// TODO Move nice_map_name from game into here?
|
||||
}
|
||||
|
||||
impl City {
|
||||
pub fn new(huge_map: &Map) -> City {
|
||||
/// If there's a single map covering all the smaller maps, use this.
|
||||
pub fn from_huge_map(huge_map: &Map) -> City {
|
||||
let city_name = huge_map.get_city_name().clone();
|
||||
let mut regions = abstutil::list_dir(format!("importer/config/{}", city_name))
|
||||
.into_iter()
|
||||
@ -46,4 +47,53 @@ impl City {
|
||||
regions,
|
||||
}
|
||||
}
|
||||
|
||||
/// Generate a city from a bunch of smaller, individual maps. The boundaries of those maps
|
||||
/// may overlap and may have gaps between them.
|
||||
pub fn from_individual_maps(city_name: &str, timer: &mut Timer) -> City {
|
||||
let boundary_per_region: Vec<(MapName, Vec<LonLat>)> =
|
||||
abstutil::list_dir(format!("importer/config/{}", city_name))
|
||||
.into_iter()
|
||||
.filter(|path| path.ends_with(".poly"))
|
||||
.map(|path| {
|
||||
(
|
||||
MapName::new(&city_name, &abstutil::basename(&path)),
|
||||
LonLat::read_osmosis_polygon(&path).unwrap(),
|
||||
)
|
||||
})
|
||||
.collect();
|
||||
// Figure out the total bounds for all the maps
|
||||
let mut gps_bounds = GPSBounds::new();
|
||||
for (_, pts) in &boundary_per_region {
|
||||
for pt in pts {
|
||||
gps_bounds.update(*pt);
|
||||
}
|
||||
}
|
||||
let boundary = gps_bounds.to_bounds().get_rectangle();
|
||||
|
||||
let mut regions = Vec::new();
|
||||
for (name, pts) in boundary_per_region {
|
||||
regions.push((name, Ring::must_new(gps_bounds.convert(&pts)).to_polygon()));
|
||||
}
|
||||
|
||||
// Add areas from every map. It's fine if they partly overlap.
|
||||
let mut areas = Vec::new();
|
||||
for path in abstutil::list_dir(abstutil::path(format!("system/{}/maps", city_name))) {
|
||||
let map = Map::new(path, timer);
|
||||
for area in map.all_areas() {
|
||||
let pts = map.gps_bounds.convert_back(area.polygon.points());
|
||||
// TODO Holes in the polygons get lost
|
||||
if let Ok(ring) = Ring::new(gps_bounds.convert(&pts)) {
|
||||
areas.push((area.area_type, ring.to_polygon()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
City {
|
||||
name: city_name.to_string(),
|
||||
boundary,
|
||||
areas,
|
||||
regions,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user