mirror of
https://github.com/a-b-street/abstreet.git
synced 2024-12-24 15:02:59 +03:00
Ignore spurious changes in pathfinding for the LTN impact tool. #868
This commit is contained in:
parent
1126972fdd
commit
272408002f
@ -143,15 +143,39 @@ impl Impact {
|
|||||||
app.session.modal_filters.update_routing_params(&mut params);
|
app.session.modal_filters.update_routing_params(&mut params);
|
||||||
// Since we're making so many requests, it's worth it to rebuild a contraction hierarchy.
|
// Since we're making so many requests, it's worth it to rebuild a contraction hierarchy.
|
||||||
// This depends on the current map edits, so no need to cache
|
// This depends on the current map edits, so no need to cache
|
||||||
let pathfinder = Pathfinder::new_ch(map, params, constraints.into_iter().collect(), timer);
|
let pathfinder_after =
|
||||||
TrafficCounts::from_path_requests(
|
Pathfinder::new_ch(map, params, constraints.into_iter().collect(), timer);
|
||||||
|
|
||||||
|
// We can't simply use TrafficCounts::from_path_requests. Due to spurious diffs with paths,
|
||||||
|
// we need to skip cases where the path before and after have the same cost. It's easiest
|
||||||
|
// (code-wise) to just repeat some calculation here.
|
||||||
|
let mut counts = TrafficCounts::from_path_requests(
|
||||||
map,
|
map,
|
||||||
// Don't bother describing all the trip filtering
|
// Don't bother describing all the trip filtering
|
||||||
"after filters".to_string(),
|
"after filters".to_string(),
|
||||||
&self.filtered_trips,
|
&vec![],
|
||||||
&pathfinder,
|
&pathfinder_after,
|
||||||
timer,
|
timer,
|
||||||
)
|
);
|
||||||
|
|
||||||
|
timer.start_iter("calculate routes", self.filtered_trips.len());
|
||||||
|
for (req, count) in &self.filtered_trips {
|
||||||
|
timer.next();
|
||||||
|
if let (Some(path1), Some(path2)) = (
|
||||||
|
map.get_pathfinder().pathfind_v2(req.clone(), map),
|
||||||
|
pathfinder_after.pathfind_v2(req.clone(), map),
|
||||||
|
) {
|
||||||
|
if path1.get_cost() == path2.get_cost() {
|
||||||
|
// When the path maybe changed but the cost is the same, just count it the same
|
||||||
|
// as the original path
|
||||||
|
counts.update_with_path(path1, *count, map);
|
||||||
|
} else {
|
||||||
|
counts.update_with_path(path2, *count, map);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
counts
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns routes that start or stop crossing the given road. Returns paths (before filters,
|
/// Returns routes that start or stop crossing the given road. Returns paths (before filters,
|
||||||
@ -185,6 +209,11 @@ impl Impact {
|
|||||||
map.get_pathfinder().pathfind_v2(req.clone(), map),
|
map.get_pathfinder().pathfind_v2(req.clone(), map),
|
||||||
pathfinder_after.pathfind_v2(req.clone(), map),
|
pathfinder_after.pathfind_v2(req.clone(), map),
|
||||||
) {
|
) {
|
||||||
|
// Skip spurious changes where the cost matches.
|
||||||
|
if path1.get_cost() == path2.get_cost() {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
if path1.crosses_road(r) != path2.crosses_road(r) {
|
if path1.crosses_road(r) != path2.crosses_road(r) {
|
||||||
if let (Ok(path1), Ok(path2)) = (path1.into_v1(map), path2.into_v1(map)) {
|
if let (Ok(path1), Ok(path2)) = (path1.into_v1(map), path2.into_v1(map)) {
|
||||||
changed.push((path1, path2));
|
changed.push((path1, path2));
|
||||||
|
@ -3,7 +3,7 @@ use serde::{Deserialize, Serialize};
|
|||||||
use abstio::MapName;
|
use abstio::MapName;
|
||||||
use abstutil::{prettyprint_usize, Counter, Timer};
|
use abstutil::{prettyprint_usize, Counter, Timer};
|
||||||
use geom::Distance;
|
use geom::Distance;
|
||||||
use map_model::{IntersectionID, Map, PathRequest, PathStepV2, Pathfinder, RoadID};
|
use map_model::{IntersectionID, Map, PathRequest, PathStepV2, PathV2, Pathfinder, RoadID};
|
||||||
|
|
||||||
/// This represents the number of vehicles (or trips, or something else) crossing roads and
|
/// This represents the number of vehicles (or trips, or something else) crossing roads and
|
||||||
/// intersections over some span of time. The data could represent real observations or something
|
/// intersections over some span of time. The data could represent real observations or something
|
||||||
@ -70,36 +70,40 @@ impl TrafficCounts {
|
|||||||
for (req, count) in requests {
|
for (req, count) in requests {
|
||||||
timer.next();
|
timer.next();
|
||||||
if let Some(path) = pathfinder.pathfind_v2(req.clone(), map) {
|
if let Some(path) = pathfinder.pathfind_v2(req.clone(), map) {
|
||||||
let count = *count;
|
counts.update_with_path(path, *count, map);
|
||||||
for step in path.get_steps() {
|
|
||||||
match step {
|
|
||||||
PathStepV2::Along(dr) | PathStepV2::Contraflow(dr) => {
|
|
||||||
counts.per_road.add(dr.road, count);
|
|
||||||
}
|
|
||||||
PathStepV2::Movement(m) | PathStepV2::ContraflowMovement(m) => {
|
|
||||||
counts.per_intersection.add(m.parent, count);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// If we're starting or ending at a border, count it
|
|
||||||
if req.start.dist_along() == Distance::ZERO {
|
|
||||||
// TODO src_i and dst_i may not work for pedestrians on contraflow sidewalks
|
|
||||||
let i = map.get_l(req.start.lane()).src_i;
|
|
||||||
if map.get_i(i).is_border() {
|
|
||||||
counts.per_intersection.add(i, count);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
let i = map.get_l(req.end.lane()).dst_i;
|
|
||||||
if map.get_i(i).is_border() {
|
|
||||||
counts.per_intersection.add(i, count);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
counts
|
counts
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn update_with_path(&mut self, path: PathV2, count: usize, map: &Map) {
|
||||||
|
for step in path.get_steps() {
|
||||||
|
match step {
|
||||||
|
PathStepV2::Along(dr) | PathStepV2::Contraflow(dr) => {
|
||||||
|
self.per_road.add(dr.road, count);
|
||||||
|
}
|
||||||
|
PathStepV2::Movement(m) | PathStepV2::ContraflowMovement(m) => {
|
||||||
|
self.per_intersection.add(m.parent, count);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// If we're starting or ending at a border, count it
|
||||||
|
let req = path.get_req();
|
||||||
|
if req.start.dist_along() == Distance::ZERO {
|
||||||
|
// TODO src_i and dst_i may not work for pedestrians on contraflow sidewalks
|
||||||
|
let i = map.get_l(req.start.lane()).src_i;
|
||||||
|
if map.get_i(i).is_border() {
|
||||||
|
self.per_intersection.add(i, count);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
let i = map.get_l(req.end.lane()).dst_i;
|
||||||
|
if map.get_i(i).is_border() {
|
||||||
|
self.per_intersection.add(i, count);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Print a comparison of counts. Only look at roads/intersections in `self`.
|
/// Print a comparison of counts. Only look at roads/intersections in `self`.
|
||||||
pub fn quickly_compare(&self, other: &TrafficCounts) {
|
pub fn quickly_compare(&self, other: &TrafficCounts) {
|
||||||
// TODO Easy ASCII art table without huge dependencies?
|
// TODO Easy ASCII art table without huge dependencies?
|
||||||
|
Loading…
Reference in New Issue
Block a user