map_model/objects/
lane.rs

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
13/// From some manually audited cases in Seattle, the length of parallel street parking spots is a
14/// bit different than the length in parking lots, so set a different value here.
15pub const PARKING_LOT_SPOT_LENGTH: Distance = Distance::const_meters(6.4);
16
17/// A lane is identified by its parent road and its position, ordered from the left.
18#[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    // TODO Do we have an endianness problem, or does serde take care of us?
32    pub fn encode_u32(self) -> u32 {
33        // The first 27 bits encode the RoadID, the last 5 the offset.
34        //
35        // (In some Houston area dystopia, we might want 2^5 = 32 lanes on one road. That leaves 27
36        // bits for roads -- 134 million roads should be plenty.)
37        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        // My bit twiddling is weak. Easier way to get a binary mask starting with 11111?
44        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/// A road segment is broken down into individual lanes, which have a LaneType.
76#[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    /// {Cars, bikes} trying to start or end here might not be able to reach most lanes in the
88    /// graph, because this is near a border.
89    pub driving_blackhole: bool,
90    pub biking_blackhole: bool,
91}
92
93impl Lane {
94    // TODO most of these are wrappers; stop doing this?
95    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    /// pt2 will be endpoint
119    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        // TODO I think we're assuming there are no loop lanes
141        vec![self.src_i, self.dst_i]
142    }
143
144    // TODO different types for each lane type might be reasonable
145
146    pub fn number_parking_spots(&self, cfg: &MapConfig) -> usize {
147        assert_eq!(self.lane_type, LaneType::Parking);
148        // No spots next to intersections
149        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    // TODO Misleading?
190    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    /// This does the reasonable thing for the leftmost and rightmost lane on a road -- except for
202    /// roads with exactly one lane. For lanes in the middle of a road, it uses the direction of
203    /// the lane -- so bidirectional/contraflow cycletracks will produce weird results.
204    // TODO This is such a weird API; make blockfinding not depend on this
205    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    /// Returns the set of allowed turn types, based on individual turn lane restrictions. `None`
233    /// means all turn types are allowed.
234    ///
235    /// This will return `None` for bus lanes, unless `force_bus` is true. OSM turn restrictions on
236    /// bus lanes usually apply to regular vehicles, not the buses. When generating the turns for
237    /// buses, we probably don't want to use the restrictions.
238    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        // TODO This'll interpret turn restrictions along every segment of an OSM way. They maybe
248        // only make sense for the first or last segment.
249        // TODO We could plumb forward LaneSpec.turn_restrictions instead of redoing some work here
250
251        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        // Verify the number of parts matches the road's lanes
262        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        // TODO More warnings if this fails
273        let part = parts[lanes.iter().position(|l| *l == self.id)?];
274
275        // TODO Probably the target lane should get marked as LaneType::Bus
276        if part == "yes" || part == "psv" || part == "bus" {
277            return None;
278        }
279
280        // These both mean that physically, there's no marking saying what turn is valid. In
281        // practice, this seems to imply straight is always fine, and right/left are fine unless
282        // covered by an explicit turn lane.
283        //
284        // If a multi-lane road lacks markings, just listening to this function will mean that the
285        // rightmost lanes could turn left, which probably isn't great for people in the middle
286        // lanes going straight. Further filtering (in remove_merging_turns) will prune this out.
287        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    /// Two lanes/roads share one endpoint
317    One(IntersectionID),
318    /// Two lanes/roads share both endpoints, because they both belong to the same road, or there
319    /// are two different roads connecting the same pair of intersections
320    Both,
321    /// Two lanes/roads don't have any common endpoints
322    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
346// See https://wiki.openstreetmap.org/wiki/Key:turn
347fn 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}