1use geom::{LonLat, Pt2D};
2use map_model::osm::RoadRank;
3use map_model::{Intersection, IntersectionID, Map, PathConstraints};
4
5use crate::TripMode;
6
7#[derive(Clone)]
10pub struct MapBorders {
11 pub incoming_walking: Vec<MapBorder>,
12 pub incoming_driving: Vec<MapBorder>,
13 pub incoming_biking: Vec<MapBorder>,
14 pub outgoing_walking: Vec<MapBorder>,
15 pub outgoing_driving: Vec<MapBorder>,
16 pub outgoing_biking: Vec<MapBorder>,
17}
18
19#[derive(Clone)]
20pub struct MapBorder {
21 pub i: IntersectionID,
22 pub pos: Pt2D,
23 pub gps_pos: LonLat,
24 pub weight: usize,
27}
28
29impl MapBorders {
30 pub fn new(map: &Map) -> MapBorders {
31 let incoming_walking = map
32 .all_incoming_borders()
33 .into_iter()
34 .filter(|i| {
35 !i.get_outgoing_lanes(map, PathConstraints::Pedestrian)
36 .is_empty()
37 })
38 .map(|i| MapBorder::new(map, i))
39 .collect::<Vec<_>>();
40 let incoming_driving = map
41 .all_incoming_borders()
42 .into_iter()
43 .filter(|i| !i.get_outgoing_lanes(map, PathConstraints::Car).is_empty())
44 .map(|i| MapBorder::new(map, i))
45 .collect::<Vec<_>>();
46 let incoming_biking = map
47 .all_incoming_borders()
48 .into_iter()
49 .filter(|i| !i.get_outgoing_lanes(map, PathConstraints::Bike).is_empty())
50 .map(|i| MapBorder::new(map, i))
51 .collect::<Vec<_>>();
52 let outgoing_walking = map
53 .all_outgoing_borders()
54 .into_iter()
55 .filter(|i| {
56 !i.get_incoming_lanes(map, PathConstraints::Pedestrian)
57 .is_empty()
58 })
59 .map(|i| MapBorder::new(map, i))
60 .collect::<Vec<_>>();
61 let outgoing_driving = map
62 .all_outgoing_borders()
63 .into_iter()
64 .filter(|i| !i.get_incoming_lanes(map, PathConstraints::Car).is_empty())
65 .map(|i| MapBorder::new(map, i))
66 .collect::<Vec<_>>();
67 let outgoing_biking = map
68 .all_outgoing_borders()
69 .into_iter()
70 .filter(|i| !i.get_incoming_lanes(map, PathConstraints::Bike).is_empty())
71 .map(|i| MapBorder::new(map, i))
72 .collect::<Vec<_>>();
73 MapBorders {
74 incoming_walking,
75 incoming_driving,
76 incoming_biking,
77 outgoing_walking,
78 outgoing_driving,
79 outgoing_biking,
80 }
81 }
82
83 pub fn for_mode(&self, mode: TripMode) -> (&Vec<MapBorder>, &Vec<MapBorder>) {
85 match mode {
86 TripMode::Walk | TripMode::Transit => (&self.incoming_walking, &self.outgoing_walking),
87 TripMode::Drive => (&self.incoming_driving, &self.outgoing_driving),
88 TripMode::Bike => (&self.incoming_biking, &self.outgoing_biking),
89 }
90 }
91}
92
93impl MapBorder {
94 fn new(map: &Map, i: &Intersection) -> Self {
95 let road = map.get_r(*i.roads.iter().next().unwrap());
97 let mut weight = match road.get_rank() {
98 RoadRank::Local => 3,
99 RoadRank::Arterial => 5,
100 RoadRank::Highway => 8,
101 };
102 if road.is_service() {
104 weight = 1;
105 }
106
107 let pos = i.polygon.center();
108 Self {
109 i: i.id,
110 pos,
111 gps_pos: pos.to_gps(map.get_gps_bounds()),
112 weight,
113 }
114 }
115}