1use std::collections::BTreeSet;
2use std::fmt;
3
4use serde::{Deserialize, Deserializer, Serialize, Serializer};
5
6use geom::{Distance, Line, PolyLine, Polygon, Pt2D};
7
8use crate::{
9 DirectedRoadID, Direction, DrivingSide, IntersectionID, LaneType, Map, MapConfig, Road, RoadID,
10 RoadSideID, SideOfRoad, TurnType,
11};
12
13pub const PARKING_LOT_SPOT_LENGTH: Distance = Distance::const_meters(6.4);
16
17#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq, PartialOrd, Ord)]
19pub struct LaneID {
20 pub road: RoadID,
21 pub offset: usize,
22}
23
24impl fmt::Display for LaneID {
25 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
26 write!(f, "Lane #{}", self.encode_u32())
27 }
28}
29
30impl LaneID {
31 pub fn encode_u32(self) -> u32 {
33 let road = self.road.0 << 5;
38 (road | self.offset) as u32
39 }
40
41 pub fn decode_u32(x: u32) -> LaneID {
42 let road = RoadID((x >> 5) as usize);
43 let offset = (x & (1 + 2 + 4 + 8 + 16)) as usize;
45 LaneID { road, offset }
46 }
47
48 pub fn dummy() -> LaneID {
49 LaneID {
50 road: RoadID(0),
51 offset: 0,
52 }
53 }
54}
55
56impl Serialize for LaneID {
57 fn serialize<S>(&self, s: S) -> Result<S::Ok, S::Error>
58 where
59 S: Serializer,
60 {
61 self.encode_u32().serialize(s)
62 }
63}
64
65impl<'de> Deserialize<'de> for LaneID {
66 fn deserialize<D>(d: D) -> Result<LaneID, D::Error>
67 where
68 D: Deserializer<'de>,
69 {
70 let x = <u32>::deserialize(d)?;
71 Ok(LaneID::decode_u32(x))
72 }
73}
74
75#[derive(Serialize, Deserialize, Clone, Debug)]
77pub struct Lane {
78 pub id: LaneID,
79 pub lane_type: LaneType,
80 pub lane_center_pts: PolyLine,
81 pub width: Distance,
82 pub dir: Direction,
83
84 pub src_i: IntersectionID,
85 pub dst_i: IntersectionID,
86
87 pub driving_blackhole: bool,
90 pub biking_blackhole: bool,
91}
92
93impl Lane {
94 pub fn first_pt(&self) -> Pt2D {
96 self.lane_center_pts.first_pt()
97 }
98 pub fn last_pt(&self) -> Pt2D {
99 self.lane_center_pts.last_pt()
100 }
101 pub fn first_line(&self) -> Line {
102 self.lane_center_pts.first_line()
103 }
104 pub fn last_line(&self) -> Line {
105 self.lane_center_pts.last_line()
106 }
107
108 pub fn endpoint(&self, i: IntersectionID) -> Pt2D {
109 if i == self.src_i {
110 self.first_pt()
111 } else if i == self.dst_i {
112 self.last_pt()
113 } else {
114 panic!("{} isn't an endpoint of {}", i, self.id);
115 }
116 }
117
118 pub fn end_line(&self, i: IntersectionID) -> Line {
120 if i == self.src_i {
121 self.first_line().reversed()
122 } else if i == self.dst_i {
123 self.last_line()
124 } else {
125 panic!("{} isn't an endpoint of {}", i, self.id);
126 }
127 }
128
129 pub fn dist_along_of_point(&self, pt: Pt2D) -> Option<Distance> {
130 self.lane_center_pts
131 .dist_along_of_point(pt)
132 .map(|(dist, _)| dist)
133 }
134
135 pub fn length(&self) -> Distance {
136 self.lane_center_pts.length()
137 }
138
139 pub fn intersections(&self) -> Vec<IntersectionID> {
140 vec![self.src_i, self.dst_i]
142 }
143
144 pub fn number_parking_spots(&self, cfg: &MapConfig) -> usize {
147 assert_eq!(self.lane_type, LaneType::Parking);
148 let spots = (self.length() / cfg.street_parking_spot_length).floor() - 2.0;
150 if spots >= 1.0 {
151 spots as usize
152 } else {
153 0
154 }
155 }
156
157 pub fn is_driving(&self) -> bool {
158 self.lane_type == LaneType::Driving
159 }
160
161 pub fn is_biking(&self) -> bool {
162 self.lane_type == LaneType::Biking
163 }
164
165 pub fn is_bus(&self) -> bool {
166 self.lane_type == LaneType::Bus
167 }
168
169 pub fn is_walkable(&self) -> bool {
170 self.lane_type.is_walkable()
171 }
172
173 pub fn is_sidewalk(&self) -> bool {
174 self.lane_type == LaneType::Sidewalk
175 }
176
177 pub fn is_shoulder(&self) -> bool {
178 self.lane_type == LaneType::Shoulder
179 }
180
181 pub fn is_parking(&self) -> bool {
182 self.lane_type == LaneType::Parking
183 }
184
185 pub fn is_light_rail(&self) -> bool {
186 self.lane_type == LaneType::LightRail
187 }
188
189 pub fn is_footway(&self) -> bool {
191 self.lane_type == LaneType::Footway || self.lane_type == LaneType::SharedUse
192 }
193
194 pub fn get_directed_parent(&self) -> DirectedRoadID {
195 DirectedRoadID {
196 road: self.id.road,
197 dir: self.dir,
198 }
199 }
200
201 pub fn get_nearest_side_of_road(&self, map: &Map) -> RoadSideID {
206 if self.id.offset == 0 {
207 return RoadSideID {
208 road: self.id.road,
209 side: SideOfRoad::Left,
210 };
211 }
212 let parent = map.get_r(self.id.road);
213 if parent.lanes.last().as_ref().unwrap().id == self.id {
214 return RoadSideID {
215 road: self.id.road,
216 side: SideOfRoad::Right,
217 };
218 }
219
220 let side = match (self.dir, map.get_config().driving_side) {
221 (Direction::Fwd, DrivingSide::Right) => SideOfRoad::Right,
222 (Direction::Back, DrivingSide::Right) => SideOfRoad::Left,
223 (Direction::Fwd, DrivingSide::Left) => SideOfRoad::Left,
224 (Direction::Back, DrivingSide::Left) => SideOfRoad::Right,
225 };
226 RoadSideID {
227 road: self.id.road,
228 side,
229 }
230 }
231
232 pub fn get_lane_level_turn_restrictions(
239 &self,
240 road: &Road,
241 force_bus: bool,
242 ) -> Option<BTreeSet<TurnType>> {
243 if !self.is_driving() && (!force_bus || !self.is_bus()) {
244 return None;
245 }
246
247 let all = if self.dir == Direction::Fwd {
252 road.osm_tags
253 .get("turn:lanes:forward")
254 .or_else(|| road.osm_tags.get("turn:lanes"))?
255 } else if self.dir == Direction::Back {
256 road.osm_tags.get("turn:lanes:backward")?
257 } else {
258 return None;
259 };
260 let parts: Vec<&str> = all.split('|').collect();
261 let lanes: Vec<LaneID> = road
263 .children(self.dir)
264 .into_iter()
265 .filter(|(_, lt)| *lt == LaneType::Driving || *lt == LaneType::Bus)
266 .map(|(id, _)| id)
267 .collect();
268 if parts.len() != lanes.len() {
269 warn!("{}'s turn restrictions don't match the lanes", road.orig_id);
270 return None;
271 }
272 let part = parts[lanes.iter().position(|l| *l == self.id)?];
274
275 if part == "yes" || part == "psv" || part == "bus" {
277 return None;
278 }
279
280 if part.is_empty() || part == "none" {
288 let all_explicit_types: BTreeSet<TurnType> = parts
289 .iter()
290 .flat_map(|part| part.split(';').flat_map(parse_turn_type_from_osm))
291 .collect();
292 let mut implied = BTreeSet::new();
293 implied.insert(TurnType::Straight);
294 for tt in [TurnType::Left, TurnType::Right] {
295 if !all_explicit_types.contains(&tt) {
296 implied.insert(tt);
297 }
298 }
299 return Some(implied);
300 }
301
302 Some(part.split(';').flat_map(parse_turn_type_from_osm).collect())
303 }
304
305 pub fn common_endpoint(&self, other: &Lane) -> CommonEndpoint {
306 CommonEndpoint::new((self.src_i, self.dst_i), (other.src_i, other.dst_i))
307 }
308
309 pub fn get_thick_polygon(&self) -> Polygon {
310 self.lane_center_pts.make_polygons(self.width)
311 }
312}
313
314#[derive(PartialEq)]
315pub enum CommonEndpoint {
316 One(IntersectionID),
318 Both,
321 None,
323}
324
325impl CommonEndpoint {
326 pub fn new(
327 obj1: (IntersectionID, IntersectionID),
328 obj2: (IntersectionID, IntersectionID),
329 ) -> CommonEndpoint {
330 #![allow(clippy::suspicious_operation_groupings)]
331 let src = obj1.0 == obj2.0 || obj1.0 == obj2.1;
332 let dst = obj1.1 == obj2.0 || obj1.1 == obj2.1;
333 if src && dst {
334 return CommonEndpoint::Both;
335 }
336 if src {
337 return CommonEndpoint::One(obj1.0);
338 }
339 if dst {
340 return CommonEndpoint::One(obj1.1);
341 }
342 CommonEndpoint::None
343 }
344}
345
346fn parse_turn_type_from_osm(x: &str) -> Vec<TurnType> {
348 match x {
349 "left" => vec![TurnType::Left],
350 "right" => vec![TurnType::Right],
351 "through" => vec![TurnType::Straight],
352 "slight_right" | "slight right" | "merge_to_right" | "sharp_right" => {
353 vec![TurnType::Straight, TurnType::Right]
354 }
355 "slight_left" | "slight left" | "merge_to_left" | "sharp_left" => {
356 vec![TurnType::Straight, TurnType::Left]
357 }
358 "reverse" => vec![TurnType::UTurn],
359 "none" | "" => vec![],
360 _ => {
361 warn!("Unknown turn restriction {}", x);
362 vec![]
363 }
364 }
365}
366
367#[cfg(test)]
368mod tests {
369 use super::*;
370
371 #[test]
372 fn test_lane_id_encoding() {
373 let l = LaneID {
374 road: RoadID(42),
375 offset: 3,
376 };
377 assert_eq!(l, LaneID::decode_u32(l.encode_u32()));
378 }
379}