Simplify path trace API -- nobody needs dist_ahead. I think that was originally meant to be a performance trick to only draw the next little bit of a route

This commit is contained in:
Dustin Carlino 2020-12-16 16:09:11 -08:00
parent d4fa67ac87
commit d00e7f7bca
11 changed files with 47 additions and 100 deletions

View File

@ -267,7 +267,7 @@ impl HoverOnBuilding {
let mut batch = GeomBatch::new(); let mut batch = GeomBatch::new();
if let Some(polyline) = isochrone if let Some(polyline) = isochrone
.path_to(&app.map, hover_id) .path_to(&app.map, hover_id)
.and_then(|path| path.trace(&app.map, Distance::ZERO, None)) .and_then(|path| path.trace(&app.map, Distance::ZERO))
{ {
let dashed_lines = polyline.dashed_lines( let dashed_lines = polyline.dashed_lines(
Distance::meters(0.75 * scale_factor), Distance::meters(0.75 * scale_factor),

View File

@ -430,7 +430,7 @@ fn calc_all_routes(ctx: &EventCtx, app: &mut App) -> (usize, Drawable) {
Parallelism::Fastest, Parallelism::Fastest,
agents, agents,
|id| { |id| {
sim.trace_route(id, map, None) sim.trace_route(id, map)
.map(|trace| trace.make_polygons(NORMAL_LANE_THICKNESS)) .map(|trace| trace.make_polygons(NORMAL_LANE_THICKNESS))
}, },
) { ) {

View File

@ -74,7 +74,7 @@ pub fn info(ctx: &mut EventCtx, app: &App, details: &mut Details, id: BuildingID
.primary .primary
.sim .sim
.walking_path_to_nearest_parking_spot(&app.primary.map, id) .walking_path_to_nearest_parking_spot(&app.primary.map, id)
.and_then(|path| path.trace(&app.primary.map, path.get_req().start.dist_along(), None)) .and_then(|path| path.trace(&app.primary.map, path.get_req().start.dist_along()))
{ {
let color = app.cs.parking_trip; let color = app.cs.parking_trip;
// TODO But this color doesn't show up well against the info panel... // TODO But this color doesn't show up well against the info panel...

View File

@ -746,7 +746,7 @@ fn make_trip_details(
// This is expensive, so cache please // This is expensive, so cache please
if idx == open_trip.cached_routes.len() { if idx == open_trip.cached_routes.len() {
if let Some(trace) = if let Some(trace) =
path.trace(map_for_pathfinding, path.get_req().start.dist_along(), None) path.trace(map_for_pathfinding, path.get_req().start.dist_along())
{ {
open_trip.cached_routes.push(Some(( open_trip.cached_routes.push(Some((
trace.make_polygons(Distance::meters(10.0)), trace.make_polygons(Distance::meters(10.0)),

View File

@ -147,9 +147,7 @@ fn preview_route(g: &mut GfxCtx, app: &App, id: TripID) -> GeomBatch {
.get_trip_phases(id, &app.primary.map) .get_trip_phases(id, &app.primary.map)
{ {
if let Some(path) = &p.path { if let Some(path) = &p.path {
if let Some(trace) = if let Some(trace) = path.trace(&app.primary.map, path.get_req().start.dist_along()) {
path.trace(&app.primary.map, path.get_req().start.dist_along(), None)
{
batch.push( batch.push(
color_for_trip_phase(app, p.phase_type), color_for_trip_phase(app, p.phase_type),
trace.make_polygons(Distance::meters(20.0)), trace.make_polygons(Distance::meters(20.0)),

View File

@ -322,7 +322,7 @@ impl State<App> for AgentSpawner {
{ {
self.goal = Some(( self.goal = Some((
to, to,
path.trace(&app.primary.map, path.get_req().start.dist_along(), None) path.trace(&app.primary.map, path.get_req().start.dist_along())
.map(|pl| pl.make_polygons(NORMAL_LANE_THICKNESS)), .map(|pl| pl.make_polygons(NORMAL_LANE_THICKNESS)),
)); ));
} else { } else {
@ -387,7 +387,7 @@ impl State<App> for AgentSpawner {
{ {
self.goal = Some(( self.goal = Some((
hovering, hovering,
path.trace(&app.primary.map, path.get_req().start.dist_along(), None) path.trace(&app.primary.map, path.get_req().start.dist_along())
.map(|pl| pl.make_polygons(NORMAL_LANE_THICKNESS)), .map(|pl| pl.make_polygons(NORMAL_LANE_THICKNESS)),
)); ));
} else { } else {

View File

@ -44,8 +44,7 @@ impl RoutePreview {
// Only draw the preview when zoomed in. If we wanted to do this unzoomed, we'd // Only draw the preview when zoomed in. If we wanted to do this unzoomed, we'd
// want a different style; the dashed lines don't show up well. // want a different style; the dashed lines don't show up well.
if zoomed { if zoomed {
if let Some(trace) = app.primary.sim.trace_route(agent, &app.primary.map, None) if let Some(trace) = app.primary.sim.trace_route(agent, &app.primary.map) {
{
batch.extend( batch.extend(
app.cs.route, app.cs.route,
trace.dashed_lines( trace.dashed_lines(

View File

@ -52,14 +52,14 @@ impl PathStep {
self.as_traversable().as_turn() self.as_traversable().as_turn()
} }
// Returns dist_remaining. start is relative to the start of the actual geometry -- so from the // start is relative to the start of the actual geometry -- so from the lane's real start for
// lane's real start for ContraflowLane. // ContraflowLane.
fn slice( fn exact_slice(
&self, &self,
map: &Map, map: &Map,
start: Distance, start: Distance,
dist_ahead: Option<Distance>, dist_ahead: Option<Distance>,
) -> Result<(PolyLine, Distance), String> { ) -> Result<PolyLine, String> {
if let Some(d) = dist_ahead { if let Some(d) = dist_ahead {
if d < Distance::ZERO { if d < Distance::ZERO {
panic!("Negative dist_ahead?! {}", d); panic!("Negative dist_ahead?! {}", d);
@ -73,26 +73,26 @@ impl PathStep {
PathStep::Lane(id) => { PathStep::Lane(id) => {
let pts = &map.get_l(*id).lane_center_pts; let pts = &map.get_l(*id).lane_center_pts;
if let Some(d) = dist_ahead { if let Some(d) = dist_ahead {
pts.slice(start, start + d) pts.maybe_exact_slice(start, start + d)
} else { } else {
pts.slice(start, pts.length()) pts.maybe_exact_slice(start, pts.length())
} }
} }
PathStep::ContraflowLane(id) => { PathStep::ContraflowLane(id) => {
let pts = map.get_l(*id).lane_center_pts.reversed(); let pts = map.get_l(*id).lane_center_pts.reversed();
let reversed_start = pts.length() - start; let reversed_start = pts.length() - start;
if let Some(d) = dist_ahead { if let Some(d) = dist_ahead {
pts.slice(reversed_start, reversed_start + d) pts.maybe_exact_slice(reversed_start, reversed_start + d)
} else { } else {
pts.slice(reversed_start, pts.length()) pts.maybe_exact_slice(reversed_start, pts.length())
} }
} }
PathStep::Turn(id) => { PathStep::Turn(id) => {
let pts = &map.get_t(*id).geom; let pts = &map.get_t(*id).geom;
if let Some(d) = dist_ahead { if let Some(d) = dist_ahead {
pts.slice(start, start + d) pts.maybe_exact_slice(start, start + d)
} else { } else {
pts.slice(start, pts.length()) pts.maybe_exact_slice(start, pts.length())
} }
} }
} }
@ -321,73 +321,45 @@ impl Path {
self.steps[self.steps.len() - 1] self.steps[self.steps.len() - 1]
} }
/// dist_ahead is unlimited when None. Note this starts at the beginning (or end, for some /// Traces along the path from a specified distance along the first step until the end.
/// walking paths) of the first lane, not accounting for the original request's start distance. pub fn trace(&self, map: &Map, start_dist: Distance) -> Option<PolyLine> {
pub fn trace(
&self,
map: &Map,
start_dist: Distance,
dist_ahead: Option<Distance>,
) -> Option<PolyLine> {
let mut pts_so_far: Option<PolyLine> = None;
let mut dist_remaining = dist_ahead;
let orig_end_dist = self.orig_req.end.dist_along(); let orig_end_dist = self.orig_req.end.dist_along();
if self.steps.len() == 1 { if self.steps.len() == 1 {
let dist = if start_dist < orig_end_dist { let dist_ahead = if start_dist < orig_end_dist {
orig_end_dist - start_dist orig_end_dist - start_dist
} else { } else {
start_dist - orig_end_dist start_dist - orig_end_dist
}; };
if let Some(d) = dist_remaining {
if dist < d { // Why might this fail? It's possible there are paths on their last step that're
dist_remaining = Some(dist); // effectively empty, because they're a 0-length turn, or something like a pedestrian
} // crossing a front path and immediately getting on a bike.
} else { return self.steps[0]
dist_remaining = Some(dist); .exact_slice(map, start_dist, Some(dist_ahead))
} .ok();
} }
// Special case the first step. let mut pts_so_far: Option<PolyLine> = None;
if let Ok((pts, dist)) = self.steps[0].slice(map, start_dist, dist_remaining) {
// Special case the first step with start_dist.
if let Ok(pts) = self.steps[0].exact_slice(map, start_dist, None) {
pts_so_far = Some(pts); pts_so_far = Some(pts);
if dist_remaining.is_some() {
dist_remaining = Some(dist);
}
}
if self.steps.len() == 1 {
// It's possible there are paths on their last step that're effectively empty, because
// they're a 0-length turn, or something like a pedestrian crossing a front path and
// immediately getting on a bike.
return pts_so_far;
} }
// Crunch through the intermediate steps, as long as we can. // Crunch through the intermediate steps, as long as we can.
for i in 1..self.steps.len() { for i in 1..self.steps.len() {
if let Some(d) = dist_remaining { // Restrict the last step's slice
if d <= Distance::ZERO { let dist_ahead = if i == self.steps.len() - 1 {
// We know there's at least some geometry if we made it here, so unwrap to Some(match self.steps[i] {
// verify that understanding.
return Some(pts_so_far.unwrap());
}
}
// If we made it to the last step, maybe use the end_dist.
if i == self.steps.len() - 1 {
let end_dist = match self.steps[i] {
PathStep::ContraflowLane(l) => { PathStep::ContraflowLane(l) => {
map.get_l(l).lane_center_pts.reversed().length() - orig_end_dist map.get_l(l).lane_center_pts.reversed().length() - orig_end_dist
} }
_ => orig_end_dist, _ => orig_end_dist,
}; })
if let Some(d) = dist_remaining { } else {
if end_dist < d { None
dist_remaining = Some(end_dist); };
}
} else {
dist_remaining = Some(end_dist);
}
}
let start_dist_this_step = match self.steps[i] { let start_dist_this_step = match self.steps[i] {
// TODO Length of a PolyLine can slightly change when points are reversed! That // TODO Length of a PolyLine can slightly change when points are reversed! That
@ -395,9 +367,7 @@ impl Path {
PathStep::ContraflowLane(l) => map.get_l(l).lane_center_pts.reversed().length(), PathStep::ContraflowLane(l) => map.get_l(l).lane_center_pts.reversed().length(),
_ => Distance::ZERO, _ => Distance::ZERO,
}; };
if let Ok((new_pts, dist)) = if let Ok(new_pts) = self.steps[i].exact_slice(map, start_dist_this_step, dist_ahead) {
self.steps[i].slice(map, start_dist_this_step, dist_remaining)
{
if pts_so_far.is_some() { if pts_so_far.is_some() {
match pts_so_far.unwrap().extend(new_pts) { match pts_so_far.unwrap().extend(new_pts) {
Ok(new) => { Ok(new) => {
@ -411,9 +381,6 @@ impl Path {
} else { } else {
pts_so_far = Some(new_pts); pts_so_far = Some(new_pts);
} }
if dist_remaining.is_some() {
dist_remaining = Some(dist);
}
} }
} }

View File

@ -1047,16 +1047,10 @@ impl DrivingSimState {
.collect() .collect()
} }
pub fn trace_route( pub fn trace_route(&self, now: Time, id: CarID, map: &Map) -> Option<PolyLine> {
&self,
now: Time,
id: CarID,
map: &Map,
dist_ahead: Option<Distance>,
) -> Option<PolyLine> {
let car = self.cars.get(&id)?; let car = self.cars.get(&id)?;
let front = self.get_car_front(now, car); let front = self.get_car_front(now, car);
car.router.get_path().trace(map, front, dist_ahead) car.router.get_path().trace(map, front)
} }
pub fn percent_along_route(&self, id: CarID) -> f64 { pub fn percent_along_route(&self, id: CarID) -> f64 {

View File

@ -398,18 +398,12 @@ impl WalkingSimState {
} }
} }
pub fn trace_route( pub fn trace_route(&self, now: Time, id: PedestrianID, map: &Map) -> Option<PolyLine> {
&self,
now: Time,
id: PedestrianID,
map: &Map,
dist_ahead: Option<Distance>,
) -> Option<PolyLine> {
let p = self.peds.get(&id)?; let p = self.peds.get(&id)?;
let body_radius = SIDEWALK_THICKNESS / 4.0; let body_radius = SIDEWALK_THICKNESS / 4.0;
let dist = (p.get_dist_along(now, map) + body_radius) let dist = (p.get_dist_along(now, map) + body_radius)
.min(p.path.current_step().as_traversable().length(map)); .min(p.path.current_step().as_traversable().length(map));
p.path.trace(map, dist, dist_ahead) p.path.trace(map, dist)
} }
pub fn get_path(&self, id: PedestrianID) -> Option<&Path> { pub fn get_path(&self, id: PedestrianID) -> Option<&Path> {

View File

@ -215,15 +215,10 @@ impl Sim {
self.driving.get_all_driving_paths() self.driving.get_all_driving_paths()
} }
pub fn trace_route( pub fn trace_route(&self, id: AgentID, map: &Map) -> Option<PolyLine> {
&self,
id: AgentID,
map: &Map,
dist_ahead: Option<Distance>,
) -> Option<PolyLine> {
match id { match id {
AgentID::Car(car) => self.driving.trace_route(self.time, car, map, dist_ahead), AgentID::Car(car) => self.driving.trace_route(self.time, car, map),
AgentID::Pedestrian(ped) => self.walking.trace_route(self.time, ped, map, dist_ahead), AgentID::Pedestrian(ped) => self.walking.trace_route(self.time, ped, map),
AgentID::BusPassenger(_, _) => None, AgentID::BusPassenger(_, _) => None,
} }
} }