Make the rat-run detector respect modal filters.

Overall results still not right, but getting closer. Some "rat-runs"
retained will only be in the neighborhood out of "necessity" -- they
should maybe be totally filtered out for the heatmap counts.
This commit is contained in:
Dustin Carlino 2021-12-19 12:27:33 +00:00
parent 83bf6953d1
commit fd852795c2
3 changed files with 36 additions and 10 deletions

View File

@ -2,7 +2,7 @@ use std::collections::{BTreeMap, BTreeSet};
use geom::{Circle, Distance, Line, Polygon};
use map_gui::tools::DrawRoadLabels;
use map_model::{IntersectionID, Map, Perimeter, RoadID};
use map_model::{IntersectionID, Map, Perimeter, RoadID, RoutingParams, TurnID};
use widgetry::mapspace::ToggleZoomed;
use widgetry::{Color, Drawable, EventCtx, GeomBatch};
@ -41,6 +41,25 @@ pub struct ModalFilters {
pub intersections: BTreeMap<IntersectionID, DiagonalFilter>,
}
impl ModalFilters {
/// Modify RoutingParams to respect these modal filters
pub fn update_routing_params(&self, params: &mut RoutingParams) {
params.avoid_roads.extend(self.roads.keys().cloned());
for filter in self.intersections.values() {
params
.avoid_movements_between
.extend(filter.avoid_movements_between_roads());
}
}
pub fn allows_turn(&self, t: TurnID) -> bool {
if let Some(filter) = self.intersections.get(&t.parent) {
return filter.allows_turn(t.src.road, t.dst.road);
}
true
}
}
/// A diagonal filter exists in an intersection. It's defined by two roads (the order is
/// arbitrary). When all of the intersection's roads are sorted in clockwise order, this pair of
/// roads splits the ordering into two groups. Turns in each group are still possible, but not

View File

@ -38,16 +38,30 @@ pub fn find_rat_runs(
}
}
let mut params = map.routing_params().clone();
modal_filters.update_routing_params(&mut params);
let cache_custom = true;
let mut paths: Vec<Path> = timer
.parallelize(
"calculate paths between entrances and exits",
requests,
|req| map.pathfind(req),
|req| map.pathfind_with_params(req, &params, cache_custom),
)
.into_iter()
.flatten()
.collect();
// update_routing_params heavily penalizes crossing modal filters, but it doesn't prevent it
// completely! So strip out paths that were forced to cross a filter.
paths.retain(|path| {
!path.get_steps().iter().any(|step| match step {
PathStep::Lane(l) => modal_filters.roads.contains_key(&l.road),
PathStep::Turn(t) => !modal_filters.allows_turn(*t),
// Car paths don't make contraflow movements
_ => unreachable!(),
})
});
// Some paths wind up partly using perimeter roads (or even things outside the neighborhood
// entirely). Sort by "worse" paths that spend more time inside.
paths.sort_by_key(|path| {

View File

@ -87,14 +87,7 @@ impl RoutePlanner {
// First the route respecting the filters
let (total_time_after, total_dist_after) = {
let mut params = map.routing_params().clone();
params
.avoid_roads
.extend(app.session.modal_filters.roads.keys().cloned());
for filter in app.session.modal_filters.intersections.values() {
params
.avoid_movements_between
.extend(filter.avoid_movements_between_roads());
}
app.session.modal_filters.update_routing_params(&mut params);
params.main_road_penalty = self.panel.spinner::<RoundedF64>("main road penalty").0;
let cache_custom = true;