mirror of
https://github.com/a-b-street/abstreet.git
synced 2024-11-24 09:24:26 +03:00
slightly better border matching for buses. dont count on any ordering in
the route relation. include intersections that get copied as possibilities.
This commit is contained in:
parent
acc82b4f06
commit
b942510f67
@ -1,7 +1,8 @@
|
||||
use abstutil::{retain_btreemap, Timer};
|
||||
use geom::{PolyLine, Ring};
|
||||
use geom::{PolyLine, Pt2D, Ring};
|
||||
use map_model::raw::{OriginalIntersection, OriginalRoad, RawMap};
|
||||
use map_model::IntersectionType;
|
||||
use std::collections::BTreeMap;
|
||||
|
||||
// TODO This needs to update turn restrictions too
|
||||
pub fn clip_map(map: &mut RawMap, timer: &mut Timer) {
|
||||
@ -27,6 +28,11 @@ pub fn clip_map(map: &mut RawMap, timer: &mut Timer) {
|
||||
first_in || last_in || light_rail_ok
|
||||
});
|
||||
|
||||
// When we split an intersection out of bounds into two, one of them gets a new ID. Remember
|
||||
// that here.
|
||||
let mut extra_borders: BTreeMap<OriginalIntersection, (OriginalIntersection, Pt2D)> =
|
||||
BTreeMap::new();
|
||||
|
||||
// First pass: Clip roads beginning out of bounds
|
||||
let road_ids: Vec<OriginalRoad> = map.roads.keys().cloned().collect();
|
||||
for id in road_ids {
|
||||
@ -36,6 +42,7 @@ pub fn clip_map(map: &mut RawMap, timer: &mut Timer) {
|
||||
}
|
||||
|
||||
let mut move_i = id.i1;
|
||||
let orig_id = id.i1;
|
||||
|
||||
// The road crosses the boundary. If the intersection happens to have another connected
|
||||
// road, then we need to copy the intersection before trimming it. This effectively
|
||||
@ -53,6 +60,7 @@ pub fn clip_map(map: &mut RawMap, timer: &mut Timer) {
|
||||
move_i = OriginalIntersection {
|
||||
osm_node_id: map.new_osm_node_id(-1),
|
||||
};
|
||||
extra_borders.insert(orig_id, (move_i, copy.point));
|
||||
map.intersections.insert(move_i, copy);
|
||||
println!("Disconnecting {} from some other stuff (starting OOB)", id);
|
||||
}
|
||||
@ -94,6 +102,7 @@ pub fn clip_map(map: &mut RawMap, timer: &mut Timer) {
|
||||
}
|
||||
|
||||
let mut move_i = id.i2;
|
||||
let orig_id = id.i2;
|
||||
|
||||
// The road crosses the boundary. If the intersection happens to have another connected
|
||||
// road, then we need to copy the intersection before trimming it. This effectively
|
||||
@ -110,6 +119,7 @@ pub fn clip_map(map: &mut RawMap, timer: &mut Timer) {
|
||||
move_i = OriginalIntersection {
|
||||
osm_node_id: map.new_osm_node_id(-1),
|
||||
};
|
||||
extra_borders.insert(orig_id, (move_i, copy.point));
|
||||
map.intersections.insert(move_i, copy);
|
||||
println!("Disconnecting {} from some other stuff (ending OOB)", id);
|
||||
}
|
||||
@ -163,41 +173,48 @@ pub fn clip_map(map: &mut RawMap, timer: &mut Timer) {
|
||||
|
||||
let mut keep_routes = Vec::new();
|
||||
for mut r in map.bus_routes.drain(..) {
|
||||
let mut borders = Vec::new();
|
||||
let num_pts = r.all_pts.len();
|
||||
for (idx, pt) in r.all_pts.drain(..).enumerate() {
|
||||
if map
|
||||
.intersections
|
||||
.get(&pt)
|
||||
.map(|i| i.intersection_type == IntersectionType::Border)
|
||||
.unwrap_or(false)
|
||||
{
|
||||
borders.push((pt, idx));
|
||||
}
|
||||
}
|
||||
if borders.len() > 2 {
|
||||
timer.warn(format!(
|
||||
"Route {} matches too many borders: {:?}",
|
||||
r.osm_rel_id, borders
|
||||
));
|
||||
} else {
|
||||
// https://wiki.openstreetmap.org/w/index.php?title=Relation:route&uselang=en#Order_matters
|
||||
// Of course the ways aren't in order. :( Use distance to the first/last stop. If
|
||||
// there's just one stop, we're just gambling at this point.
|
||||
if borders.len() == 2 {
|
||||
// Presumably the borders are in order.
|
||||
r.border_start = Some(borders[0].0);
|
||||
r.border_end = Some(borders[1].0);
|
||||
} else if borders.len() == 1 {
|
||||
// Alright, which end is which? Use the original index of the point to guess.
|
||||
if borders[0].1 < num_pts / 2 {
|
||||
r.border_start = Some(borders[0].0);
|
||||
} else {
|
||||
r.border_end = Some(borders[0].0);
|
||||
let mut borders: Vec<(OriginalIntersection, Pt2D)> = Vec::new();
|
||||
for pt in r.all_pts.drain(..) {
|
||||
if let Some(i) = map.intersections.get(&pt) {
|
||||
if i.intersection_type == IntersectionType::Border {
|
||||
borders.push((pt, i.point));
|
||||
}
|
||||
}
|
||||
keep_routes.push(r);
|
||||
if let Some(pair) = extra_borders.get(&pt) {
|
||||
borders.push(*pair);
|
||||
}
|
||||
}
|
||||
|
||||
if !borders.is_empty() {
|
||||
// Guess which border is for the beginning and end of the route. This can fail if:
|
||||
// - there's just one stop
|
||||
// - the border isn't actually connected to the stop by any path (roads causing copied
|
||||
// intersections trigger this)
|
||||
let start_pt = r.stops[0].vehicle_pos;
|
||||
let closest_to_start = borders
|
||||
.iter()
|
||||
.min_by_key(|(_, pt)| start_pt.dist_to(*pt))
|
||||
.unwrap();
|
||||
let end_pt = r.stops.last().unwrap().vehicle_pos;
|
||||
let closest_to_end = borders
|
||||
.iter()
|
||||
.min_by_key(|(_, pt)| end_pt.dist_to(*pt))
|
||||
.unwrap();
|
||||
|
||||
if closest_to_start.0 != closest_to_end.0 {
|
||||
r.border_start = Some(closest_to_start.0);
|
||||
r.border_end = Some(closest_to_end.0);
|
||||
} else {
|
||||
// Break the tie...
|
||||
if closest_to_start.1.dist_to(start_pt) < closest_to_end.1.dist_to(end_pt) {
|
||||
r.border_start = Some(closest_to_start.0);
|
||||
} else {
|
||||
r.border_end = Some(closest_to_end.0);
|
||||
}
|
||||
}
|
||||
}
|
||||
// TODO Warn for some of these weird things and maybe skip
|
||||
keep_routes.push(r);
|
||||
}
|
||||
map.bus_routes = keep_routes;
|
||||
|
||||
|
@ -126,7 +126,10 @@ fn choose_polygon(wiz: &mut Wizard, ctx: &mut EventCtx, _: &mut App) -> Option<T
|
||||
let name = wiz.wrap(ctx).choose_string("Edit which polygon?", || {
|
||||
abstutil::list_all_objects(abstutil::path("input/seattle/polygons/"))
|
||||
})?;
|
||||
match LonLat::read_osmosis_polygon(format!("input/seattle/polygons/{}.poly", name)) {
|
||||
match LonLat::read_osmosis_polygon(abstutil::path(format!(
|
||||
"input/seattle/polygons/{}.poly",
|
||||
name
|
||||
))) {
|
||||
Ok(pts) => Some(Transition::Replace(polygon::PolygonEditor::new(
|
||||
ctx, name, pts,
|
||||
))),
|
||||
|
@ -146,7 +146,7 @@ impl State for PolygonEditor {
|
||||
|
||||
// https://wiki.openstreetmap.org/wiki/Osmosis/Polygon_Filter_File_Format
|
||||
fn save_as_osmosis(name: &str, pts: &Vec<LonLat>) -> Result<(), Error> {
|
||||
let path = "bounding_boy.poly";
|
||||
let path = format!("{}.poly", name);
|
||||
let mut f = File::create(&path)?;
|
||||
|
||||
writeln!(f, "{}", name)?;
|
||||
|
@ -227,14 +227,20 @@ impl ShowBusRoute {
|
||||
bus_locations.push(pt);
|
||||
}
|
||||
|
||||
let mut colorer = ColorDiscrete::new(
|
||||
app,
|
||||
vec![
|
||||
("route", app.cs.unzoomed_bus),
|
||||
("start", Color::RED),
|
||||
("end", Color::GREEN),
|
||||
],
|
||||
);
|
||||
let mut categories = vec![("route", app.cs.unzoomed_bus)];
|
||||
if route.start_border.is_some() {
|
||||
categories.push(("start", Color::RED));
|
||||
}
|
||||
if route.end_border.is_some() {
|
||||
categories.push(("end", Color::GREEN));
|
||||
}
|
||||
let mut colorer = ColorDiscrete::new(app, categories);
|
||||
if let Some(l) = route.start_border {
|
||||
colorer.add_i(map.get_l(l).src_i, "start");
|
||||
}
|
||||
if let Some(l) = route.end_border {
|
||||
colorer.add_i(map.get_l(l).dst_i, "end");
|
||||
}
|
||||
for pair in route.stops.windows(2) {
|
||||
for step in map
|
||||
.pathfind(PathRequest {
|
||||
@ -250,12 +256,6 @@ impl ShowBusRoute {
|
||||
}
|
||||
}
|
||||
}
|
||||
if let Some(l) = route.start_border {
|
||||
colorer.add_i(map.get_l(l).src_i, "start");
|
||||
}
|
||||
if let Some(l) = route.end_border {
|
||||
colorer.add_i(map.get_l(l).dst_i, "end");
|
||||
}
|
||||
|
||||
let mut labels = Vec::new();
|
||||
for (idx, bs) in route.stops.iter().enumerate() {
|
||||
|
@ -99,8 +99,9 @@ fn make_route(
|
||||
} else {
|
||||
// TODO Should panic
|
||||
println!(
|
||||
"Route {} starts at {}, but no starting lane for a {:?}?",
|
||||
"Route {} starts at {} ({}), but no starting lane for a {:?}?",
|
||||
rel_url(r.osm_rel_id),
|
||||
i.id,
|
||||
i.orig_id,
|
||||
route_type
|
||||
);
|
||||
@ -116,8 +117,9 @@ fn make_route(
|
||||
} else {
|
||||
// TODO Should panic
|
||||
println!(
|
||||
"Route {} ends at {}, but no ending lane for a {:?}?",
|
||||
"Route {} ends at {} ({}), but no ending lane for a {:?}?",
|
||||
rel_url(r.osm_rel_id),
|
||||
i.id,
|
||||
i.orig_id,
|
||||
route_type
|
||||
);
|
||||
|
@ -155,6 +155,7 @@ impl RawMap {
|
||||
}
|
||||
}
|
||||
|
||||
// TODO Almost gone...
|
||||
pub fn new_osm_way_id(&self, start: i64) -> i64 {
|
||||
assert!(start < 0);
|
||||
// Slow, but deterministic.
|
||||
|
Loading…
Reference in New Issue
Block a user