mirror of
https://github.com/a-b-street/abstreet.git
synced 2024-11-28 12:12:00 +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 abstutil::{retain_btreemap, Timer};
|
||||||
use geom::{PolyLine, Ring};
|
use geom::{PolyLine, Pt2D, Ring};
|
||||||
use map_model::raw::{OriginalIntersection, OriginalRoad, RawMap};
|
use map_model::raw::{OriginalIntersection, OriginalRoad, RawMap};
|
||||||
use map_model::IntersectionType;
|
use map_model::IntersectionType;
|
||||||
|
use std::collections::BTreeMap;
|
||||||
|
|
||||||
// TODO This needs to update turn restrictions too
|
// TODO This needs to update turn restrictions too
|
||||||
pub fn clip_map(map: &mut RawMap, timer: &mut Timer) {
|
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
|
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
|
// First pass: Clip roads beginning out of bounds
|
||||||
let road_ids: Vec<OriginalRoad> = map.roads.keys().cloned().collect();
|
let road_ids: Vec<OriginalRoad> = map.roads.keys().cloned().collect();
|
||||||
for id in road_ids {
|
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 mut move_i = id.i1;
|
||||||
|
let orig_id = id.i1;
|
||||||
|
|
||||||
// The road crosses the boundary. If the intersection happens to have another connected
|
// 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
|
// 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 {
|
move_i = OriginalIntersection {
|
||||||
osm_node_id: map.new_osm_node_id(-1),
|
osm_node_id: map.new_osm_node_id(-1),
|
||||||
};
|
};
|
||||||
|
extra_borders.insert(orig_id, (move_i, copy.point));
|
||||||
map.intersections.insert(move_i, copy);
|
map.intersections.insert(move_i, copy);
|
||||||
println!("Disconnecting {} from some other stuff (starting OOB)", id);
|
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 mut move_i = id.i2;
|
||||||
|
let orig_id = id.i2;
|
||||||
|
|
||||||
// The road crosses the boundary. If the intersection happens to have another connected
|
// 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
|
// 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 {
|
move_i = OriginalIntersection {
|
||||||
osm_node_id: map.new_osm_node_id(-1),
|
osm_node_id: map.new_osm_node_id(-1),
|
||||||
};
|
};
|
||||||
|
extra_borders.insert(orig_id, (move_i, copy.point));
|
||||||
map.intersections.insert(move_i, copy);
|
map.intersections.insert(move_i, copy);
|
||||||
println!("Disconnecting {} from some other stuff (ending OOB)", id);
|
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();
|
let mut keep_routes = Vec::new();
|
||||||
for mut r in map.bus_routes.drain(..) {
|
for mut r in map.bus_routes.drain(..) {
|
||||||
let mut borders = Vec::new();
|
let mut borders: Vec<(OriginalIntersection, Pt2D)> = Vec::new();
|
||||||
let num_pts = r.all_pts.len();
|
for pt in r.all_pts.drain(..) {
|
||||||
for (idx, pt) in r.all_pts.drain(..).enumerate() {
|
if let Some(i) = map.intersections.get(&pt) {
|
||||||
if map
|
if i.intersection_type == IntersectionType::Border {
|
||||||
.intersections
|
borders.push((pt, i.point));
|
||||||
.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);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
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;
|
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?", || {
|
let name = wiz.wrap(ctx).choose_string("Edit which polygon?", || {
|
||||||
abstutil::list_all_objects(abstutil::path("input/seattle/polygons/"))
|
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(
|
Ok(pts) => Some(Transition::Replace(polygon::PolygonEditor::new(
|
||||||
ctx, name, pts,
|
ctx, name, pts,
|
||||||
))),
|
))),
|
||||||
|
@ -146,7 +146,7 @@ impl State for PolygonEditor {
|
|||||||
|
|
||||||
// https://wiki.openstreetmap.org/wiki/Osmosis/Polygon_Filter_File_Format
|
// https://wiki.openstreetmap.org/wiki/Osmosis/Polygon_Filter_File_Format
|
||||||
fn save_as_osmosis(name: &str, pts: &Vec<LonLat>) -> Result<(), Error> {
|
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)?;
|
let mut f = File::create(&path)?;
|
||||||
|
|
||||||
writeln!(f, "{}", name)?;
|
writeln!(f, "{}", name)?;
|
||||||
|
@ -227,14 +227,20 @@ impl ShowBusRoute {
|
|||||||
bus_locations.push(pt);
|
bus_locations.push(pt);
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut colorer = ColorDiscrete::new(
|
let mut categories = vec![("route", app.cs.unzoomed_bus)];
|
||||||
app,
|
if route.start_border.is_some() {
|
||||||
vec![
|
categories.push(("start", Color::RED));
|
||||||
("route", app.cs.unzoomed_bus),
|
}
|
||||||
("start", Color::RED),
|
if route.end_border.is_some() {
|
||||||
("end", Color::GREEN),
|
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 pair in route.stops.windows(2) {
|
||||||
for step in map
|
for step in map
|
||||||
.pathfind(PathRequest {
|
.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();
|
let mut labels = Vec::new();
|
||||||
for (idx, bs) in route.stops.iter().enumerate() {
|
for (idx, bs) in route.stops.iter().enumerate() {
|
||||||
|
@ -99,8 +99,9 @@ fn make_route(
|
|||||||
} else {
|
} else {
|
||||||
// TODO Should panic
|
// TODO Should panic
|
||||||
println!(
|
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),
|
rel_url(r.osm_rel_id),
|
||||||
|
i.id,
|
||||||
i.orig_id,
|
i.orig_id,
|
||||||
route_type
|
route_type
|
||||||
);
|
);
|
||||||
@ -116,8 +117,9 @@ fn make_route(
|
|||||||
} else {
|
} else {
|
||||||
// TODO Should panic
|
// TODO Should panic
|
||||||
println!(
|
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),
|
rel_url(r.osm_rel_id),
|
||||||
|
i.id,
|
||||||
i.orig_id,
|
i.orig_id,
|
||||||
route_type
|
route_type
|
||||||
);
|
);
|
||||||
|
@ -155,6 +155,7 @@ impl RawMap {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO Almost gone...
|
||||||
pub fn new_osm_way_id(&self, start: i64) -> i64 {
|
pub fn new_osm_way_id(&self, start: i64) -> i64 {
|
||||||
assert!(start < 0);
|
assert!(start < 0);
|
||||||
// Slow, but deterministic.
|
// Slow, but deterministic.
|
||||||
|
Loading…
Reference in New Issue
Block a user