1 use crate::{LaneID, Map, TurnID}; 2 use geom::{Angle, Distance, PolyLine, Pt2D, Speed}; 3 use serde::{Deserialize, Serialize}; 4 use std::fmt; 5 6 #[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize)] 7 pub struct Position { 8 // Don't let callers construct a Position directly, so it's easy to find callers of new(). 9 lane: LaneID, 10 dist_along: Distance, 11 } 12 13 impl fmt::Display for Position { fmt(&self, f: &mut fmt::Formatter) -> fmt::Result14 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { 15 write!(f, "Position({}, {})", self.lane, self.dist_along) 16 } 17 } 18 19 impl Position { new(lane: LaneID, dist_along: Distance) -> Position20 pub fn new(lane: LaneID, dist_along: Distance) -> Position { 21 Position { lane, dist_along } 22 } 23 start(lane: LaneID) -> Position24 pub fn start(lane: LaneID) -> Position { 25 Position { 26 lane, 27 dist_along: Distance::ZERO, 28 } 29 } 30 end(lane: LaneID, map: &Map) -> Position31 pub fn end(lane: LaneID, map: &Map) -> Position { 32 Position { 33 lane, 34 dist_along: map.get_l(lane).length(), 35 } 36 } 37 lane(&self) -> LaneID38 pub fn lane(&self) -> LaneID { 39 self.lane 40 } 41 dist_along(&self) -> Distance42 pub fn dist_along(&self) -> Distance { 43 self.dist_along 44 } 45 pt(&self, map: &Map) -> Pt2D46 pub fn pt(&self, map: &Map) -> Pt2D { 47 match map 48 .get_l(self.lane) 49 .lane_center_pts 50 .dist_along(self.dist_along) 51 { 52 Ok((pt, _)) => pt, 53 Err(err) => panic!("{} invalid: {}", self, err), 54 } 55 } 56 pt_and_angle(&self, map: &Map) -> (Pt2D, Angle)57 pub fn pt_and_angle(&self, map: &Map) -> (Pt2D, Angle) { 58 match map 59 .get_l(self.lane) 60 .lane_center_pts 61 .dist_along(self.dist_along) 62 { 63 Ok(pair) => pair, 64 Err(err) => panic!("{} invalid: {}", self, err), 65 } 66 } 67 equiv_pos(&self, lane: LaneID, map: &Map) -> Position68 pub fn equiv_pos(&self, lane: LaneID, map: &Map) -> Position { 69 self.equiv_pos_for_long_object(lane, Distance::ZERO, map) 70 } equiv_pos_for_long_object( &self, lane: LaneID, our_len: Distance, map: &Map, ) -> Position71 pub fn equiv_pos_for_long_object( 72 &self, 73 lane: LaneID, 74 our_len: Distance, 75 map: &Map, 76 ) -> Position { 77 let r = map.get_parent(lane); 78 assert_eq!(map.get_l(self.lane).parent, r.id); 79 80 // TODO Project perpendicular 81 let len = map.get_l(lane).length(); 82 // The two lanes may be on opposite sides of the road; this often happens on one-ways with 83 // sidewalks on both sides. 84 if r.dir(lane) == r.dir(self.lane) { 85 Position::new(lane, self.dist_along.min(len)) 86 } else { 87 Position::new( 88 lane, 89 // TODO I don't understand what this is doing anymore in the one case, revisit 90 (len - self.dist_along + our_len) 91 .max(Distance::ZERO) 92 .min(len), 93 ) 94 } 95 } min_dist(mut self, dist_along: Distance, map: &Map) -> Option<Position>96 pub fn min_dist(mut self, dist_along: Distance, map: &Map) -> Option<Position> { 97 if self.dist_along >= dist_along { 98 return Some(self); 99 } 100 if map.get_l(self.lane).length() < dist_along { 101 return None; 102 } 103 self.dist_along = dist_along; 104 Some(self) 105 } buffer_dist(mut self, buffer: Distance, map: &Map) -> Option<Position>106 pub fn buffer_dist(mut self, buffer: Distance, map: &Map) -> Option<Position> { 107 let len = map.get_l(self.lane).length(); 108 if len <= buffer * 2.0 { 109 return None; 110 } 111 self.dist_along = self.dist_along.max(buffer).min(len - buffer); 112 Some(self) 113 } 114 } 115 116 // TODO also building paths? 117 #[derive(Clone, Copy, Debug, Eq, Hash, PartialEq, PartialOrd, Ord, Serialize, Deserialize)] 118 pub enum Traversable { 119 Lane(LaneID), 120 Turn(TurnID), 121 } 122 123 impl fmt::Display for Traversable { fmt(&self, f: &mut fmt::Formatter) -> fmt::Result124 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { 125 match self { 126 Traversable::Lane(id) => write!(f, "Traversable::Lane({})", id.0), 127 Traversable::Turn(id) => write!( 128 f, 129 "Traversable::Turn({}, {}, {})", 130 id.src, id.dst, id.parent 131 ), 132 } 133 } 134 } 135 136 impl Traversable { as_lane(&self) -> LaneID137 pub fn as_lane(&self) -> LaneID { 138 match *self { 139 Traversable::Lane(id) => id, 140 Traversable::Turn(_) => panic!("not a lane"), 141 } 142 } 143 as_turn(&self) -> TurnID144 pub fn as_turn(&self) -> TurnID { 145 match *self { 146 Traversable::Turn(id) => id, 147 Traversable::Lane(_) => panic!("not a turn"), 148 } 149 } 150 maybe_turn(&self) -> Option<TurnID>151 pub fn maybe_turn(&self) -> Option<TurnID> { 152 match *self { 153 Traversable::Turn(id) => Some(id), 154 Traversable::Lane(_) => None, 155 } 156 } 157 maybe_lane(&self) -> Option<LaneID>158 pub fn maybe_lane(&self) -> Option<LaneID> { 159 match *self { 160 Traversable::Turn(_) => None, 161 Traversable::Lane(id) => Some(id), 162 } 163 } 164 165 // TODO Just expose the PolyLine instead of all these layers of helpers length(&self, map: &Map) -> Distance166 pub fn length(&self, map: &Map) -> Distance { 167 match *self { 168 Traversable::Lane(id) => map.get_l(id).length(), 169 Traversable::Turn(id) => map.get_t(id).geom.length(), 170 } 171 } 172 dist_along(&self, dist: Distance, map: &Map) -> Result<(Pt2D, Angle), String>173 pub fn dist_along(&self, dist: Distance, map: &Map) -> Result<(Pt2D, Angle), String> { 174 match *self { 175 Traversable::Lane(id) => map.get_l(id).lane_center_pts.dist_along(dist), 176 Traversable::Turn(id) => map.get_t(id).geom.dist_along(dist), 177 } 178 } 179 slice( &self, start: Distance, end: Distance, map: &Map, ) -> Result<(PolyLine, Distance), String>180 pub fn slice( 181 &self, 182 start: Distance, 183 end: Distance, 184 map: &Map, 185 ) -> Result<(PolyLine, Distance), String> { 186 match *self { 187 Traversable::Lane(id) => map.get_l(id).lane_center_pts.slice(start, end), 188 Traversable::Turn(id) => map.get_t(id).geom.slice(start, end), 189 } 190 } 191 exact_slice(&self, start: Distance, end: Distance, map: &Map) -> PolyLine192 pub fn exact_slice(&self, start: Distance, end: Distance, map: &Map) -> PolyLine { 193 match *self { 194 Traversable::Lane(id) => map.get_l(id).lane_center_pts.exact_slice(start, end), 195 Traversable::Turn(id) => map.get_t(id).geom.exact_slice(start, end), 196 } 197 } 198 speed_limit(&self, map: &Map) -> Speed199 pub fn speed_limit(&self, map: &Map) -> Speed { 200 match *self { 201 Traversable::Lane(id) => map.get_parent(id).speed_limit, 202 Traversable::Turn(id) => map.get_parent(id.dst).speed_limit, 203 } 204 } 205 get_zorder(&self, map: &Map) -> isize206 pub fn get_zorder(&self, map: &Map) -> isize { 207 match *self { 208 Traversable::Lane(id) => map.get_parent(id).zorder, 209 Traversable::Turn(id) => map.get_i(id.parent).get_zorder(map), 210 } 211 } 212 } 213