mirror of
https://github.com/a-b-street/abstreet.git
synced 2024-11-28 03:35:51 +03:00
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:
parent
d4fa67ac87
commit
d00e7f7bca
@ -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),
|
||||||
|
@ -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))
|
||||||
},
|
},
|
||||||
) {
|
) {
|
||||||
|
@ -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...
|
||||||
|
@ -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)),
|
||||||
|
@ -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)),
|
||||||
|
@ -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 {
|
||||||
|
@ -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(
|
||||||
|
@ -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);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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 {
|
||||||
|
@ -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> {
|
||||||
|
@ -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,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user