1use anyhow::Result;
6use serde::{Deserialize, Serialize};
7
8use geom::{Duration, Polygon, Ring, Speed};
9
10use crate::pathfind::uber_turns::UberTurnV2;
11use crate::{
12 osm, DirectedRoadID, Direction, IntersectionID, LaneID, Map, MovementID, Path, PathConstraints,
13 PathRequest, PathStep, RoadID, TurnID, UberTurn,
14};
15
16#[derive(Clone, Debug, Serialize, Deserialize)]
18pub enum PathStepV2 {
19 Along(DirectedRoadID),
21 Contraflow(DirectedRoadID),
23 Movement(MovementID),
24 ContraflowMovement(MovementID),
25}
26
27#[derive(Clone, Debug, Serialize, Deserialize)]
30pub struct PathV2 {
31 steps: Vec<PathStepV2>,
32 req: PathRequest,
34 cost: Duration,
35 uber_turns: Vec<UberTurnV2>,
38
39 orig_start_lane: LaneID,
41}
42
43impl PathV2 {
44 pub(crate) fn new(
45 map: &Map,
46 steps: Vec<PathStepV2>,
47 mut req: PathRequest,
48 cost: Duration,
49 uber_turns: Vec<UberTurnV2>,
50 ) -> PathV2 {
51 let orig_start_lane = req.start.lane();
52
53 if req.constraints != PathConstraints::Pedestrian {
56 if let Some((pos, _)) = req.alt_start {
57 if let PathStepV2::Along(dr) = steps[0] {
58 if map.get_l(req.start.lane()).get_directed_parent() == dr {
59 } else {
61 assert_eq!(map.get_l(pos.lane()).get_directed_parent(), dr);
62 req.start = pos;
63 }
64 req.alt_start = None;
65 } else {
66 unreachable!()
67 }
68 }
69 }
70
71 PathV2 {
73 steps,
74 req,
75 cost,
76 uber_turns,
77 orig_start_lane,
78 }
79 }
80
81 pub fn from_roads(
84 mut roads: Vec<DirectedRoadID>,
85 req: PathRequest,
86 cost: Duration,
87 uber_turns: Vec<UberTurnV2>,
88 map: &Map,
89 ) -> PathV2 {
90 let mut steps = Vec::new();
91 for pair in roads.windows(2) {
92 steps.push(PathStepV2::Along(pair[0]));
93 steps.push(PathStepV2::Movement(MovementID {
94 from: pair[0],
95 to: pair[1],
96 parent: pair[0].dst_i(map),
97 crosswalk: false,
98 }));
99 }
100 steps.push(PathStepV2::Along(roads.pop().unwrap()));
101 PathV2::new(map, steps, req, cost, uber_turns)
102 }
103
104 pub fn get_req(&self) -> &PathRequest {
106 &self.req
107 }
108
109 pub fn get_steps(&self) -> &Vec<PathStepV2> {
111 &self.steps
112 }
113
114 pub fn get_cost(&self) -> Duration {
118 self.cost
119 }
120
121 pub fn estimate_duration(
128 &self,
129 map: &Map,
130 max_speed: Option<Speed>,
131 main_road_penalty: Option<f64>,
132 ) -> Duration {
133 let mut total = Duration::ZERO;
134 for step in &self.steps {
135 let (dist, mut speed);
136 let mut multiplier = 1.0;
137 match step {
138 PathStepV2::Along(dr) | PathStepV2::Contraflow(dr) => {
139 let road = map.get_r(dr.road);
140 dist = road.length();
141 speed = road.speed_limit;
142
143 if let Some(penalty) = main_road_penalty {
144 if road.get_rank() != osm::RoadRank::Local {
145 multiplier = penalty;
146 }
147 }
148 }
149 PathStepV2::Movement(m) | PathStepV2::ContraflowMovement(m) => {
150 if let Some(movement) = map.get_movement(*m) {
151 dist = movement.geom.length();
152 speed = map
153 .get_r(m.from.road)
154 .speed_limit
155 .min(map.get_r(m.to.road).speed_limit);
156 } else {
157 continue;
159 }
160 }
161 }
162 if let Some(max) = max_speed {
163 speed = speed.min(max);
164 }
165
166 total += multiplier * (dist / speed);
167 }
168 total
169 }
170
171 pub fn into_v1(mut self, map: &Map) -> Result<Path> {
174 if self.req.constraints == PathConstraints::Pedestrian {
175 return self.into_v1_walking(map);
176 }
177
178 let mut graph = petgraph::graphmap::DiGraphMap::new();
182 for step in &self.steps {
183 if let PathStepV2::Movement(mvmnt) = step {
184 for src in mvmnt.from.lanes(self.req.constraints, map) {
185 for dst in mvmnt.to.lanes(self.req.constraints, map) {
186 let turn = TurnID {
187 parent: map.get_l(src).dst_i,
188 src,
189 dst,
190 };
191 if map.maybe_get_t(turn).is_some() {
192 graph.add_edge(src, dst, turn);
193 }
194 }
195 }
196 }
197 }
198
199 let virtual_start_node = LaneID {
205 road: RoadID(map.all_roads().len()),
206 offset: 0,
207 };
208 let start_lane = self.req.start.lane();
209 let start_road = map.get_parent(start_lane);
210 let start_lane_idx = start_lane.offset as isize;
211 for l in map
212 .get_l(start_lane)
213 .get_directed_parent()
214 .lanes(self.req.constraints, map)
215 {
216 let idx_dist = (start_lane_idx - (l.offset as isize)).abs();
224 let cost = 100 * idx_dist as usize;
225 let fake_turn = TurnID {
226 parent: IntersectionID(cost),
228 src: virtual_start_node,
229 dst: virtual_start_node,
230 };
231 graph.add_edge(virtual_start_node, l, fake_turn);
232 }
233
234 match petgraph::algo::astar(
235 &graph,
236 virtual_start_node,
237 |l| l == self.req.end.lane(),
238 |(_, _, t)| {
239 if t.src == virtual_start_node {
240 return t.parent.0;
241 }
242
243 let (lt, lc, slow_lane) = map.get_t(*t).penalty(self.req.constraints, map);
246 let mut extra_penalty = lt + lc;
247 if self.req.constraints == PathConstraints::Bike {
248 extra_penalty += slow_lane;
249 }
250 let base = 1;
256 base + extra_penalty
257 },
258 |_| 0,
259 ) {
260 Some((_, path)) => {
261 let mut steps = Vec::new();
262 assert_eq!(path[0], virtual_start_node);
264 for pair in path.windows(2) {
265 if pair[0] == virtual_start_node {
266 continue;
267 }
268
269 steps.push(PathStep::Lane(pair[0]));
270 steps.push(PathStep::Turn(TurnID {
272 parent: map.get_l(pair[0]).dst_i,
273 src: pair[0],
274 dst: pair[1],
275 }));
276 }
277 steps.push(PathStep::Lane(self.req.end.lane()));
278 let mut blocked_starts = Vec::new();
279 if steps[0] != PathStep::Lane(self.orig_start_lane) {
280 let actual_start = match steps[0] {
281 PathStep::Lane(l) => l,
282 _ => unreachable!(),
283 };
284 blocked_starts.push(self.orig_start_lane);
285 blocked_starts
286 .extend(start_road.get_lanes_between(self.orig_start_lane, actual_start));
287 self.req.start = self.req.start.equiv_pos(actual_start, map);
289 }
290 let uber_turns = find_uber_turns(&steps, map, self.uber_turns);
291 Ok(Path::new(map, steps, self.req, uber_turns, blocked_starts))
292 }
293 None => bail!(
294 "Can't transform a road-based path to a lane-based path for {}",
295 self.req
296 ),
297 }
298 }
299
300 fn into_v1_walking(self, map: &Map) -> Result<Path> {
301 let mut steps = Vec::new();
302 for step in self.steps {
303 steps.push(match step {
304 PathStepV2::Along(r) => PathStep::Lane(r.must_get_sidewalk(map)),
305 PathStepV2::Contraflow(r) => PathStep::ContraflowLane(r.must_get_sidewalk(map)),
306 PathStepV2::Movement(mvmnt) => PathStep::Turn(TurnID {
307 src: mvmnt.from.must_get_sidewalk(map),
308 dst: mvmnt.to.must_get_sidewalk(map),
309 parent: mvmnt.parent,
310 }),
311 PathStepV2::ContraflowMovement(mvmnt) => PathStep::ContraflowTurn(TurnID {
312 src: mvmnt.from.must_get_sidewalk(map),
313 dst: mvmnt.to.must_get_sidewalk(map),
314 parent: mvmnt.parent,
315 }),
316 });
317 }
318 Ok(Path::new(map, steps, self.req, Vec::new(), Vec::new()))
319 }
320
321 pub fn crosses_road(&self, r: RoadID) -> bool {
322 self.steps.iter().any(|step| match step {
323 PathStepV2::Along(dr) => dr.road == r,
324 _ => false,
325 })
326 }
327
328 pub fn trace_v2(&self, map: &Map) -> Result<Polygon> {
331 let mut left_pts = Vec::new();
332 let mut right_pts = Vec::new();
333 for step in &self.steps {
334 match step {
335 PathStepV2::Along(dr) => {
336 let road = map.get_r(dr.road);
337 let width = road.get_half_width();
338 if dr.dir == Direction::Fwd {
339 left_pts.extend(road.center_pts.shift_left(width)?.into_points());
340 right_pts.extend(road.center_pts.shift_right(width)?.into_points());
341 } else {
342 left_pts
343 .extend(road.center_pts.shift_right(width)?.reversed().into_points());
344 right_pts
345 .extend(road.center_pts.shift_left(width)?.reversed().into_points());
346 }
347 }
348 PathStepV2::Contraflow(_) => todo!(),
349 PathStepV2::Movement(_) | PathStepV2::ContraflowMovement(_) => {}
352 }
353 }
354 right_pts.reverse();
355 left_pts.extend(right_pts);
356 left_pts.push(left_pts[0]);
357 Ok(Ring::deduping_new(left_pts)?.into_polygon())
358 }
359
360 pub fn trace_all_polygons(&self, map: &Map) -> Vec<Polygon> {
363 let mut polygons = Vec::new();
364 for step in &self.steps {
365 match step {
366 PathStepV2::Along(dr) | PathStepV2::Contraflow(dr) => {
367 polygons.push(map.get_r(dr.road).get_thick_polygon());
368 }
369 PathStepV2::Movement(m) | PathStepV2::ContraflowMovement(m) => {
370 polygons.push(map.get_i(m.parent).polygon.clone());
371 }
372 }
373 }
374 polygons
375 }
376}
377
378fn find_uber_turns(
379 steps: &[PathStep],
380 map: &Map,
381 mut uber_turns_v2: Vec<UberTurnV2>,
382) -> Vec<UberTurn> {
383 let num_uts = uber_turns_v2.len();
388 let mut result = Vec::new();
389 let mut current_ut = Vec::new();
390 for step in steps {
391 if uber_turns_v2.is_empty() {
393 break;
394 }
395
396 if let PathStep::Turn(t) = step {
397 if current_ut.is_empty()
398 && uber_turns_v2[0].path[0].from == map.get_l(t.src).get_directed_parent()
399 {
400 current_ut.push(*t);
401 }
402
403 if !current_ut.is_empty() {
404 if current_ut.last() != Some(t) {
405 current_ut.push(*t);
406 }
407 if uber_turns_v2[0].path[0].to == map.get_l(t.dst).get_directed_parent() {
408 result.push(UberTurn {
409 path: current_ut.drain(..).collect(),
410 });
411 uber_turns_v2.remove(0);
412 }
413 }
414 }
415 }
416 assert!(current_ut.is_empty());
417 assert_eq!(num_uts, result.len());
418 result
419}