mirror of
https://github.com/a-b-street/abstreet.git
synced 2024-12-01 02:33:54 +03:00
Get rid of the now redundant lanes_ltr
This commit is contained in:
parent
4c46510342
commit
112bc38e0c
@ -93,10 +93,9 @@ impl Isochrone {
|
|||||||
let mut onstreet_parking_spots = 0;
|
let mut onstreet_parking_spots = 0;
|
||||||
for r in all_roads {
|
for r in all_roads {
|
||||||
let r = app.map.get_r(r);
|
let r = app.map.get_r(r);
|
||||||
for (l, _, lt) in r.lanes_ltr() {
|
for l in &r.lanes {
|
||||||
if lt == LaneType::Parking {
|
if l.lane_type == LaneType::Parking {
|
||||||
onstreet_parking_spots +=
|
onstreet_parking_spots += l.number_parking_spots(app.map.get_config());
|
||||||
app.map.get_l(l).number_parking_spots(app.map.get_config());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -579,8 +579,10 @@ pub fn draw_unwalkable_roads(ctx: &mut EventCtx, app: &App, opts: &Options) -> D
|
|||||||
if road.is_light_rail() {
|
if road.is_light_rail() {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
for (_, _, lt) in road.lanes_ltr() {
|
for l in &road.lanes {
|
||||||
if lt == LaneType::Sidewalk || (lt == LaneType::Shoulder && allow_shoulders) {
|
if l.lane_type == LaneType::Sidewalk
|
||||||
|
|| (l.lane_type == LaneType::Shoulder && allow_shoulders)
|
||||||
|
{
|
||||||
continue 'ROADS;
|
continue 'ROADS;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -183,7 +183,7 @@ fn inner_warp_to_id(ctx: &mut EventCtx, app: &mut App, line: &str) -> Option<Tra
|
|||||||
Ok(idx) => match line.chars().next().unwrap() {
|
Ok(idx) => match line.chars().next().unwrap() {
|
||||||
'r' => {
|
'r' => {
|
||||||
let r = app.primary.map.maybe_get_r(RoadID(idx))?;
|
let r = app.primary.map.maybe_get_r(RoadID(idx))?;
|
||||||
ID::Lane(r.lanes_ltr()[0].0)
|
ID::Lane(r.lanes[0].id)
|
||||||
}
|
}
|
||||||
'R' => {
|
'R' => {
|
||||||
let r = BusRouteID(idx);
|
let r = BusRouteID(idx);
|
||||||
|
@ -784,8 +784,8 @@ impl ContextualActions for Actions {
|
|||||||
if let Some((dist, _)) = pl.dist_along_of_point(pl.project_pt(pt)) {
|
if let Some((dist, _)) = pl.dist_along_of_point(pl.project_pt(pt)) {
|
||||||
let base_pos = Position::new(l, dist);
|
let base_pos = Position::new(l, dist);
|
||||||
let mut batch = GeomBatch::new();
|
let mut batch = GeomBatch::new();
|
||||||
for (l, _, _) in map.get_parent(l).lanes_ltr() {
|
for l in &map.get_parent(l).lanes {
|
||||||
let pt = base_pos.equiv_pos(l, map).pt(map);
|
let pt = base_pos.equiv_pos(l.id, map).pt(map);
|
||||||
batch.push(
|
batch.push(
|
||||||
Color::RED,
|
Color::RED,
|
||||||
Circle::new(pt, Distance::meters(1.0)).to_polygon(),
|
Circle::new(pt, Distance::meters(1.0)).to_polygon(),
|
||||||
@ -891,14 +891,14 @@ fn find_degenerate_roads(app: &App) {
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if r1
|
if r1
|
||||||
.lanes_ltr()
|
.lanes
|
||||||
.into_iter()
|
.iter()
|
||||||
.map(|(_, dir, lt)| (dir, lt))
|
.map(|l| (l.dir, l.lane_type))
|
||||||
.collect::<Vec<_>>()
|
.collect::<Vec<_>>()
|
||||||
!= r2
|
!= r2
|
||||||
.lanes_ltr()
|
.lanes
|
||||||
.into_iter()
|
.iter()
|
||||||
.map(|(_, dir, lt)| (dir, lt))
|
.map(|l| (l.dir, l.lane_type))
|
||||||
.collect::<Vec<_>>()
|
.collect::<Vec<_>>()
|
||||||
{
|
{
|
||||||
continue;
|
continue;
|
||||||
|
@ -35,11 +35,11 @@ fn road(id: RoadID, map: &Map) -> Feature {
|
|||||||
properties.insert("sharedstreetid".to_string(), id.0.into());
|
properties.insert("sharedstreetid".to_string(), id.0.into());
|
||||||
|
|
||||||
let mut slices = Vec::new();
|
let mut slices = Vec::new();
|
||||||
for (l, dir, _) in r.lanes_ltr() {
|
for l in &r.lanes {
|
||||||
if let Some(mut slice) = lane(map.get_l(l)) {
|
if let Some(mut slice) = lane(l) {
|
||||||
slice
|
slice
|
||||||
.entry("direction".to_string())
|
.entry("direction".to_string())
|
||||||
.or_insert(if dir == Direction::Fwd {
|
.or_insert(if l.dir == Direction::Fwd {
|
||||||
"forward".into()
|
"forward".into()
|
||||||
} else {
|
} else {
|
||||||
"reverse".into()
|
"reverse".into()
|
||||||
|
@ -15,8 +15,8 @@ fn road(id: RoadID, map: &Map) -> serde_json::Map<String, serde_json::value::Val
|
|||||||
// TODO Many more fields
|
// TODO Many more fields
|
||||||
|
|
||||||
let mut segments = Vec::new();
|
let mut segments = Vec::new();
|
||||||
for (l, dir, _) in r.lanes_ltr() {
|
for l in &r.lanes {
|
||||||
segments.push(serde_json::value::Value::Object(lane(map.get_l(l), dir)));
|
segments.push(serde_json::value::Value::Object(lane(l, l.dir)));
|
||||||
}
|
}
|
||||||
street.insert(
|
street.insert(
|
||||||
"segments".to_string(),
|
"segments".to_string(),
|
||||||
|
@ -80,7 +80,7 @@ impl RoadEditor {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn lane_for_idx(&self, app: &App, idx: usize) -> LaneID {
|
fn lane_for_idx(&self, app: &App, idx: usize) -> LaneID {
|
||||||
app.primary.map.get_r(self.r).lanes_ltr()[idx].0
|
app.primary.map.get_r(self.r).lanes[idx].id
|
||||||
}
|
}
|
||||||
|
|
||||||
fn modify_current_lane<F: Fn(&mut EditRoad, usize)>(
|
fn modify_current_lane<F: Fn(&mut EditRoad, usize)>(
|
||||||
@ -316,9 +316,9 @@ impl State<App> for RoadEditor {
|
|||||||
.primary
|
.primary
|
||||||
.map
|
.map
|
||||||
.get_r(self.r)
|
.get_r(self.r)
|
||||||
.lanes_ltr()
|
.lanes
|
||||||
.into_iter()
|
.iter()
|
||||||
.all(|(_, _, lt)| lt != LaneType::Driving)
|
.all(|l| l.lane_type != LaneType::Driving)
|
||||||
{
|
{
|
||||||
return Transition::Push(PopupMsg::new_state(ctx, "Error", vec!["Add a driving lane first. Parking can't exist without a way to access it."]));
|
return Transition::Push(PopupMsg::new_state(ctx, "Error", vec!["Add a driving lane first. Parking can't exist without a way to access it."]));
|
||||||
}
|
}
|
||||||
@ -553,7 +553,7 @@ fn make_main_panel(
|
|||||||
|
|
||||||
let current_lt = selected_lane.map(|l| map.get_l(l).lane_type);
|
let current_lt = selected_lane.map(|l| map.get_l(l).lane_type);
|
||||||
|
|
||||||
let current_lts: Vec<LaneType> = road.lanes_ltr().into_iter().map(|(_, _, lt)| lt).collect();
|
let current_lts: Vec<LaneType> = road.lanes.iter().map(|l| l.lane_type).collect();
|
||||||
|
|
||||||
let lane_types = [
|
let lane_types = [
|
||||||
(LaneType::Driving, Some(Key::D)),
|
(LaneType::Driving, Some(Key::D)),
|
||||||
@ -628,10 +628,13 @@ fn make_main_panel(
|
|||||||
let mut drag_drop = DragDrop::new(ctx, "lane cards", StackAxis::Horizontal);
|
let mut drag_drop = DragDrop::new(ctx, "lane cards", StackAxis::Horizontal);
|
||||||
|
|
||||||
let road_width = road.get_width();
|
let road_width = road.get_width();
|
||||||
let lanes_ltr = road.lanes_ltr();
|
|
||||||
let lanes_len = lanes_ltr.len();
|
|
||||||
|
|
||||||
for (idx, (id, dir, lt)) in lanes_ltr.into_iter().enumerate() {
|
for l in &road.lanes {
|
||||||
|
let idx = l.id.offset;
|
||||||
|
let id = l.id;
|
||||||
|
let dir = l.dir;
|
||||||
|
let lt = l.lane_type;
|
||||||
|
|
||||||
let mut icon_stack = GeomBatchStack::vertical(vec![
|
let mut icon_stack = GeomBatchStack::vertical(vec![
|
||||||
Image::from_path(lane_type_to_icon(lt).unwrap())
|
Image::from_path(lane_type_to_icon(lt).unwrap())
|
||||||
.dims((60.0, 50.0))
|
.dims((60.0, 50.0))
|
||||||
@ -664,7 +667,7 @@ fn make_main_panel(
|
|||||||
if idx == 0 {
|
if idx == 0 {
|
||||||
rounding.top_left = DEFAULT_CORNER_RADIUS;
|
rounding.top_left = DEFAULT_CORNER_RADIUS;
|
||||||
}
|
}
|
||||||
if idx == lanes_len - 1 {
|
if idx == road.lanes.len() - 1 {
|
||||||
rounding.top_right = DEFAULT_CORNER_RADIUS;
|
rounding.top_right = DEFAULT_CORNER_RADIUS;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -786,7 +789,7 @@ fn make_main_panel(
|
|||||||
ctx.style()
|
ctx.style()
|
||||||
.btn_solid_destructive
|
.btn_solid_destructive
|
||||||
.icon("system/assets/tools/trash.svg")
|
.icon("system/assets/tools/trash.svg")
|
||||||
.disabled(road.lanes_ltr().len() == 1)
|
.disabled(road.lanes.len() == 1)
|
||||||
.hotkey(Key::Backspace)
|
.hotkey(Key::Backspace)
|
||||||
.build_widget(ctx, "delete lane")
|
.build_widget(ctx, "delete lane")
|
||||||
.centered_vert(),
|
.centered_vert(),
|
||||||
@ -1010,8 +1013,8 @@ fn draw_drop_position(app: &App, r: RoadID, from: usize, to: usize) -> GeomBatch
|
|||||||
let map = &app.primary.map;
|
let map = &app.primary.map;
|
||||||
let road = map.get_r(r);
|
let road = map.get_r(r);
|
||||||
let take_num = if from < to { to + 1 } else { to };
|
let take_num = if from < to { to + 1 } else { to };
|
||||||
for (l, _, _) in road.lanes_ltr().into_iter().take(take_num) {
|
for l in road.lanes.iter().take(take_num) {
|
||||||
width += map.get_l(l).width;
|
width += l.width;
|
||||||
}
|
}
|
||||||
if let Ok(pl) = road.get_left_side().shift_right(width) {
|
if let Ok(pl) = road.get_left_side().shift_right(width) {
|
||||||
batch.push(app.cs.selected, pl.make_polygons(OUTLINE_THICKNESS));
|
batch.push(app.cs.selected, pl.make_polygons(OUTLINE_THICKNESS));
|
||||||
|
@ -226,14 +226,14 @@ impl Snapper {
|
|||||||
let mut incoming_pts = Vec::new();
|
let mut incoming_pts = Vec::new();
|
||||||
let mut outgoing_pts = Vec::new();
|
let mut outgoing_pts = Vec::new();
|
||||||
|
|
||||||
for (l, dir, lt) in r.lanes_ltr() {
|
for l in &r.lanes {
|
||||||
if lt.is_walkable() {
|
if l.lane_type.is_walkable() {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if dir == incoming_id.dir {
|
if l.dir == incoming_id.dir {
|
||||||
incoming_pts.push(map.get_l(l).lane_center_pts.last_pt());
|
incoming_pts.push(l.lane_center_pts.last_pt());
|
||||||
} else {
|
} else {
|
||||||
outgoing_pts.push(map.get_l(l).lane_center_pts.first_pt());
|
outgoing_pts.push(l.lane_center_pts.first_pt());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -94,9 +94,9 @@ impl BikeActivity {
|
|||||||
.primary
|
.primary
|
||||||
.map
|
.map
|
||||||
.get_r(*r)
|
.get_r(*r)
|
||||||
.lanes_ltr()
|
.lanes
|
||||||
.into_iter()
|
.iter()
|
||||||
.any(|(_, _, lt)| lt == LaneType::Biking)
|
.any(|l| l.lane_type == LaneType::Biking)
|
||||||
{
|
{
|
||||||
on_bike_lanes.add(*r, *count);
|
on_bike_lanes.add(*r, *count);
|
||||||
} else {
|
} else {
|
||||||
|
@ -1062,16 +1062,16 @@ impl TutorialState {
|
|||||||
))
|
))
|
||||||
.unwrap(),
|
.unwrap(),
|
||||||
);
|
);
|
||||||
assert_eq!(r.lanes_ltr().len(), 6);
|
assert_eq!(r.lanes.len(), 6);
|
||||||
r.lanes_ltr()[2].0
|
r.lanes[2].id
|
||||||
};
|
};
|
||||||
let lane_near_bldg = {
|
let lane_near_bldg = {
|
||||||
let r = map.get_r(
|
let r = map.get_r(
|
||||||
map.find_r_by_osm_id(OriginalRoad::new(6484869, (53163501, 53069236)))
|
map.find_r_by_osm_id(OriginalRoad::new(6484869, (53163501, 53069236)))
|
||||||
.unwrap(),
|
.unwrap(),
|
||||||
);
|
);
|
||||||
assert_eq!(r.lanes_ltr().len(), 6);
|
assert_eq!(r.lanes.len(), 6);
|
||||||
r.lanes_ltr()[3].0
|
r.lanes[3].id
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut scenario = Scenario::empty(map, "prank");
|
let mut scenario = Scenario::empty(map, "prank");
|
||||||
|
@ -61,10 +61,10 @@ impl DrawNetworkLayer {
|
|||||||
for r in map.all_roads() {
|
for r in map.all_roads() {
|
||||||
let mut bike_lane = false;
|
let mut bike_lane = false;
|
||||||
let mut buffer = false;
|
let mut buffer = false;
|
||||||
for (_, _, lt) in r.lanes_ltr() {
|
for l in &r.lanes {
|
||||||
if lt == LaneType::Biking {
|
if l.lane_type == LaneType::Biking {
|
||||||
bike_lane = true;
|
bike_lane = true;
|
||||||
} else if matches!(lt, LaneType::Buffer(_)) {
|
} else if matches!(l.lane_type, LaneType::Buffer(_)) {
|
||||||
buffer = true;
|
buffer = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -356,10 +356,10 @@ impl Layers {
|
|||||||
let rank = r.get_rank();
|
let rank = r.get_rank();
|
||||||
let mut bike_lane = false;
|
let mut bike_lane = false;
|
||||||
let mut buffer = false;
|
let mut buffer = false;
|
||||||
for (_, _, lt) in r.lanes_ltr() {
|
for l in &r.lanes {
|
||||||
if lt == LaneType::Biking {
|
if l.lane_type == LaneType::Biking {
|
||||||
bike_lane = true;
|
bike_lane = true;
|
||||||
} else if matches!(lt, LaneType::Buffer(_)) {
|
} else if matches!(l.lane_type, LaneType::Buffer(_)) {
|
||||||
buffer = true;
|
buffer = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -396,11 +396,11 @@ fn calculate_border_arrows(i: &Intersection, r: &Road, map: &Map) -> Vec<Polygon
|
|||||||
|
|
||||||
let mut width_fwd = Distance::ZERO;
|
let mut width_fwd = Distance::ZERO;
|
||||||
let mut width_back = Distance::ZERO;
|
let mut width_back = Distance::ZERO;
|
||||||
for (l, dir, _) in r.lanes_ltr() {
|
for l in &r.lanes {
|
||||||
if dir == Direction::Fwd {
|
if l.dir == Direction::Fwd {
|
||||||
width_fwd += map.get_l(l).width;
|
width_fwd += l.width;
|
||||||
} else {
|
} else {
|
||||||
width_back += map.get_l(l).width;
|
width_back += l.width;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
let center = r.get_dir_change_pl(map);
|
let center = r.get_dir_change_pl(map);
|
||||||
|
@ -281,17 +281,19 @@ fn calculate_parking_lines(lane: &Lane, map: &Map) -> Vec<Polygon> {
|
|||||||
// Because the stripe straddles two lanes, it'll be partly hidden on one side. There are a bunch of
|
// Because the stripe straddles two lanes, it'll be partly hidden on one side. There are a bunch of
|
||||||
// ways to work around this z-order issue. The current approach is to rely on the fact that
|
// ways to work around this z-order issue. The current approach is to rely on the fact that
|
||||||
// quadtrees return LaneIDs in order, and lanes are always created from left->right.
|
// quadtrees return LaneIDs in order, and lanes are always created from left->right.
|
||||||
fn calculate_driving_lines(lane: &Lane, parent: &Road) -> Vec<Polygon> {
|
fn calculate_driving_lines(lane: &Lane, road: &Road) -> Vec<Polygon> {
|
||||||
let lanes = parent.lanes_ltr();
|
let idx = road.offset(lane.id);
|
||||||
let idx = parent.offset(lane.id);
|
|
||||||
|
|
||||||
// If the lane to the left of us isn't in the same direction or isn't the same type, don't
|
// If the lane to the left of us isn't in the same direction or isn't the same type, don't
|
||||||
// need dashed lines.
|
// need dashed lines.
|
||||||
if idx == 0 || lanes[idx].1 != lanes[idx - 1].1 || lanes[idx].2 != lanes[idx - 1].2 {
|
if idx == 0
|
||||||
|
|| lane.dir != road.lanes[idx - 1].dir
|
||||||
|
|| lane.lane_type != road.lanes[idx - 1].lane_type
|
||||||
|
{
|
||||||
return Vec::new();
|
return Vec::new();
|
||||||
}
|
}
|
||||||
|
|
||||||
let lane_edge_pts = if lanes[idx].1 == Direction::Fwd {
|
let lane_edge_pts = if lane.dir == Direction::Fwd {
|
||||||
lane.lane_center_pts.must_shift_left(lane.width / 2.0)
|
lane.lane_center_pts.must_shift_left(lane.width / 2.0)
|
||||||
} else {
|
} else {
|
||||||
lane.lane_center_pts.must_shift_right(lane.width / 2.0)
|
lane.lane_center_pts.must_shift_right(lane.width / 2.0)
|
||||||
@ -359,12 +361,12 @@ fn calculate_turn_markings(map: &Map, lane: &Lane) -> Vec<Polygon> {
|
|||||||
results
|
results
|
||||||
}
|
}
|
||||||
|
|
||||||
fn calculate_one_way_markings(lane: &Lane, parent: &Road) -> Vec<Polygon> {
|
fn calculate_one_way_markings(lane: &Lane, road: &Road) -> Vec<Polygon> {
|
||||||
let mut results = Vec::new();
|
let mut results = Vec::new();
|
||||||
let lanes = parent.lanes_ltr();
|
if road
|
||||||
if lanes
|
.lanes
|
||||||
.into_iter()
|
.iter()
|
||||||
.any(|(_, d, lt)| lane.dir != d && lt == LaneType::Driving)
|
.any(|l| l.dir != lane.dir && l.lane_type == LaneType::Driving)
|
||||||
{
|
{
|
||||||
// Not a one-way
|
// Not a one-way
|
||||||
return results;
|
return results;
|
||||||
|
@ -38,10 +38,12 @@ impl DrawRoad {
|
|||||||
// Draw a center line every time two driving/bike/bus lanes of opposite direction are
|
// Draw a center line every time two driving/bike/bus lanes of opposite direction are
|
||||||
// adjacent.
|
// adjacent.
|
||||||
let mut width = Distance::ZERO;
|
let mut width = Distance::ZERO;
|
||||||
for pair in r.lanes_ltr().windows(2) {
|
for pair in r.lanes.windows(2) {
|
||||||
let ((l1, dir1, lt1), (_, dir2, lt2)) = (pair[0], pair[1]);
|
width += pair[0].width;
|
||||||
width += app.map().get_l(l1).width;
|
if pair[0].dir != pair[1].dir
|
||||||
if dir1 != dir2 && lt1.is_for_moving_vehicles() && lt2.is_for_moving_vehicles() {
|
&& pair[0].lane_type.is_for_moving_vehicles()
|
||||||
|
&& pair[1].lane_type.is_for_moving_vehicles()
|
||||||
|
{
|
||||||
let pl = r.get_left_side().must_shift_right(width);
|
let pl = r.get_left_side().must_shift_right(width);
|
||||||
batch.extend(
|
batch.extend(
|
||||||
center_line_color,
|
center_line_color,
|
||||||
|
@ -119,9 +119,8 @@ pub fn all_walking_costs_from(
|
|||||||
let mut shoulder_endpoint = Vec::new();
|
let mut shoulder_endpoint = Vec::new();
|
||||||
for q in &queue {
|
for q in &queue {
|
||||||
if let WalkingNode::SidewalkEndpoint(dir_r, _) = q.node {
|
if let WalkingNode::SidewalkEndpoint(dir_r, _) = q.node {
|
||||||
let lanes = &map.get_r(dir_r.id).lanes_ltr;
|
for lane in &map.get_r(dir_r.id).lanes {
|
||||||
for (_, _, lane_type) in lanes {
|
shoulder_endpoint.push(lane.lane_type == LaneType::Shoulder);
|
||||||
shoulder_endpoint.push(lane_type == &LaneType::Shoulder)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -392,7 +392,7 @@ fn fix_lane_widths(value: &mut Value, map: &Map) -> Result<()> {
|
|||||||
dir,
|
dir,
|
||||||
// Before this commit, lane widths weren't modifiable, so this lookup works
|
// Before this commit, lane widths weren't modifiable, so this lookup works
|
||||||
// for both "old" and "new".
|
// for both "old" and "new".
|
||||||
width: map.get_l(road.lanes_ltr()[idx].0).width,
|
width: road.lanes[idx].width,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
cmd[key]["lanes_ltr"] = serde_json::to_value(lanes_ltr).unwrap();
|
cmd[key]["lanes_ltr"] = serde_json::to_value(lanes_ltr).unwrap();
|
||||||
|
@ -326,15 +326,14 @@ impl MapEdits {
|
|||||||
{
|
{
|
||||||
roads.insert(r.id);
|
roads.insert(r.id);
|
||||||
} else {
|
} else {
|
||||||
let lanes_ltr = r.lanes_ltr();
|
if r.lanes.len() != orig.lanes_ltr.len() {
|
||||||
if lanes_ltr.len() != orig.lanes_ltr.len() {
|
|
||||||
// If a lane was added or deleted, figuring out if any were modified is kind of
|
// If a lane was added or deleted, figuring out if any were modified is kind of
|
||||||
// unclear -- just mark the entire road.
|
// unclear -- just mark the entire road.
|
||||||
roads.insert(r.id);
|
roads.insert(r.id);
|
||||||
} else {
|
} else {
|
||||||
for ((l, dir, lt), spec) in lanes_ltr.into_iter().zip(orig.lanes_ltr.iter()) {
|
for (l, spec) in r.lanes.iter().zip(orig.lanes_ltr.iter()) {
|
||||||
if dir != spec.dir || lt != spec.lt || map.get_l(l).width != spec.width {
|
if l.dir != spec.dir || l.lane_type != spec.lt || l.width != spec.width {
|
||||||
lanes.insert(l);
|
lanes.insert(l.id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -93,7 +93,7 @@ impl PermanentEditCmd {
|
|||||||
match self {
|
match self {
|
||||||
PermanentEditCmd::ChangeRoad { r, new, old } => {
|
PermanentEditCmd::ChangeRoad { r, new, old } => {
|
||||||
let id = map.find_r_by_osm_id(r)?;
|
let id = map.find_r_by_osm_id(r)?;
|
||||||
let num_current = map.get_r(id).lanes_ltr().len();
|
let num_current = map.get_r(id).lanes.len();
|
||||||
// The basemap changed -- it'd be pretty hard to understand the original
|
// The basemap changed -- it'd be pretty hard to understand the original
|
||||||
// intent of the edit.
|
// intent of the edit.
|
||||||
if num_current != old.lanes_ltr.len() {
|
if num_current != old.lanes_ltr.len() {
|
||||||
|
@ -15,8 +15,7 @@ pub fn find_medians(map: &Map) -> Vec<Polygon> {
|
|||||||
for r in map.all_roads() {
|
for r in map.all_roads() {
|
||||||
if r.osm_tags.is("dual_carriageway", "yes") {
|
if r.osm_tags.is("dual_carriageway", "yes") {
|
||||||
// TODO Always to the left? Maybe driving side matters; test in southbank too
|
// TODO Always to the left? Maybe driving side matters; test in southbank too
|
||||||
let lanes_ltr = r.lanes_ltr();
|
candidates.push(r.lanes[0].id);
|
||||||
candidates.push(lanes_ltr[0].0);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -150,7 +150,6 @@ impl Map {
|
|||||||
.collect(),
|
.collect(),
|
||||||
orig_id: r.id,
|
orig_id: r.id,
|
||||||
lanes: Vec::new(),
|
lanes: Vec::new(),
|
||||||
lanes_ltr: Vec::new(),
|
|
||||||
center_pts: r.trimmed_center_pts,
|
center_pts: r.trimmed_center_pts,
|
||||||
untrimmed_center_pts: raw_road.get_geometry(r.id, map.get_config()).unwrap().0,
|
untrimmed_center_pts: raw_road.get_geometry(r.id, map.get_config()).unwrap().0,
|
||||||
src_i: i1,
|
src_i: i1,
|
||||||
|
@ -209,15 +209,15 @@ fn make_walking_turns_v2(map: &Map, i: &Intersection) -> Vec<Turn> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
for r in sorted_roads {
|
for r in sorted_roads {
|
||||||
let r = map.get_r(r);
|
let road = map.get_r(r);
|
||||||
let mut fwd = None;
|
let mut fwd = None;
|
||||||
let mut back = None;
|
let mut back = None;
|
||||||
for (l, dir, lt) in r.lanes_ltr() {
|
for l in &road.lanes {
|
||||||
if lt.is_walkable() {
|
if l.lane_type.is_walkable() {
|
||||||
if dir == Direction::Fwd {
|
if l.dir == Direction::Fwd {
|
||||||
fwd = Some(map.get_l(l));
|
fwd = Some(l);
|
||||||
} else {
|
} else {
|
||||||
back = Some(map.get_l(l));
|
back = Some(l);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -227,7 +227,7 @@ fn make_walking_turns_v2(map: &Map, i: &Intersection) -> Vec<Turn> {
|
|||||||
if back.is_some() {
|
if back.is_some() {
|
||||||
num_sidewalks += 1;
|
num_sidewalks += 1;
|
||||||
}
|
}
|
||||||
let (in_lane, out_lane) = if r.src_i == i.id {
|
let (in_lane, out_lane) = if road.src_i == i.id {
|
||||||
(back, fwd)
|
(back, fwd)
|
||||||
} else {
|
} else {
|
||||||
(fwd, back)
|
(fwd, back)
|
||||||
|
@ -23,8 +23,8 @@ const SHOULDER_THICKNESS: Distance = Distance::const_meters(0.5);
|
|||||||
/// A lane is identified by its parent road and its position, ordered from the left.
|
/// A lane is identified by its parent road and its position, ordered from the left.
|
||||||
#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq, PartialOrd, Ord)]
|
#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq, PartialOrd, Ord)]
|
||||||
pub struct LaneID {
|
pub struct LaneID {
|
||||||
pub(crate) road: RoadID,
|
pub road: RoadID,
|
||||||
pub(crate) offset: usize,
|
pub offset: usize,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl fmt::Display for LaneID {
|
impl fmt::Display for LaneID {
|
||||||
@ -445,7 +445,7 @@ impl Lane {
|
|||||||
let start = self.id;
|
let start = self.id;
|
||||||
let mut pts = Vec::new();
|
let mut pts = Vec::new();
|
||||||
let mut current = start;
|
let mut current = start;
|
||||||
let mut fwd = map.get_parent(start).lanes_ltr()[0].0 == start;
|
let mut fwd = map.get_parent(start).lanes[0].id == start;
|
||||||
let mut visited = BTreeSet::new();
|
let mut visited = BTreeSet::new();
|
||||||
loop {
|
loop {
|
||||||
let l = map.get_l(current);
|
let l = map.get_l(current);
|
||||||
@ -484,9 +484,9 @@ impl Lane {
|
|||||||
// Depending on if this road points to or from the intersection, get the left- or
|
// Depending on if this road points to or from the intersection, get the left- or
|
||||||
// right-most lane.
|
// right-most lane.
|
||||||
let next_lane = if next_road.src_i == i {
|
let next_lane = if next_road.src_i == i {
|
||||||
next_road.lanes_ltr()[0].0
|
next_road.lanes[0].id
|
||||||
} else {
|
} else {
|
||||||
next_road.lanes_ltr().last().unwrap().0
|
next_road.lanes.last().unwrap().id
|
||||||
};
|
};
|
||||||
if next_lane == start {
|
if next_lane == start {
|
||||||
break;
|
break;
|
||||||
|
@ -147,10 +147,9 @@ pub struct Road {
|
|||||||
/// positive is uphill from src_i -> dst_i, negative is downhill.
|
/// positive is uphill from src_i -> dst_i, negative is downhill.
|
||||||
pub percent_incline: f64,
|
pub percent_incline: f64,
|
||||||
|
|
||||||
/// Invariant: A road must contain at least one child. These are ordered from left-to-right.
|
/// Invariant: A road must contain at least one child. These are ordered from the left side of
|
||||||
|
/// the road to the right, with that orientation determined by the direction of `center_pts`.
|
||||||
pub lanes: Vec<Lane>,
|
pub lanes: Vec<Lane>,
|
||||||
// TODO Remove -- this becomes redundant
|
|
||||||
pub(crate) lanes_ltr: Vec<(LaneID, Direction, LaneType)>,
|
|
||||||
|
|
||||||
/// The physical center of the road, including sidewalks, after trimming to account for the
|
/// The physical center of the road, including sidewalks, after trimming to account for the
|
||||||
/// intersection geometry. The order implies road orientation.
|
/// intersection geometry. The order implies road orientation.
|
||||||
@ -163,13 +162,6 @@ pub struct Road {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl Road {
|
impl Road {
|
||||||
/// Returns all lanes from the left side of the road to right. Left/right is determined by the
|
|
||||||
/// orientation of center_pts.
|
|
||||||
pub fn lanes_ltr(&self) -> Vec<(LaneID, Direction, LaneType)> {
|
|
||||||
// TODO Change this to return &Vec
|
|
||||||
self.lanes_ltr.clone()
|
|
||||||
}
|
|
||||||
|
|
||||||
pub(crate) fn lane_specs(&self) -> Vec<LaneSpec> {
|
pub(crate) fn lane_specs(&self) -> Vec<LaneSpec> {
|
||||||
self.lanes
|
self.lanes
|
||||||
.iter()
|
.iter()
|
||||||
@ -188,13 +180,11 @@ impl Road {
|
|||||||
|
|
||||||
/// Counting from the left side of the road
|
/// Counting from the left side of the road
|
||||||
pub fn offset(&self, lane: LaneID) -> usize {
|
pub fn offset(&self, lane: LaneID) -> usize {
|
||||||
for (idx, (l, _, _)) in self.lanes_ltr().into_iter().enumerate() {
|
match self.lanes.iter().position(|l| l.id == lane) {
|
||||||
if lane == l {
|
Some(x) => x,
|
||||||
return idx;
|
None => panic!("{} doesn't contain {}", self.id, lane),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
panic!("{} doesn't contain {}", self.id, lane);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// lane must belong to this road. Offset 0 is the centermost lane on each side of a road, then
|
/// lane must belong to this road. Offset 0 is the centermost lane on each side of a road, then
|
||||||
/// it counts up from there. Note this is a different offset than `offset`!
|
/// it counts up from there. Note this is a different offset than `offset`!
|
||||||
@ -409,11 +399,11 @@ impl Road {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn is_light_rail(&self) -> bool {
|
pub fn is_light_rail(&self) -> bool {
|
||||||
self.lanes_ltr().len() == 1 && self.lanes_ltr()[0].2 == LaneType::LightRail
|
self.lanes.len() == 1 && self.lanes[0].lane_type == LaneType::LightRail
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn is_footway(&self) -> bool {
|
pub fn is_footway(&self) -> bool {
|
||||||
self.lanes_ltr().len() == 1 && self.lanes_ltr()[0].2 == LaneType::Sidewalk
|
self.lanes.len() == 1 && self.lanes[0].lane_type == LaneType::Sidewalk
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn is_service(&self) -> bool {
|
pub fn is_service(&self) -> bool {
|
||||||
@ -422,10 +412,10 @@ impl Road {
|
|||||||
|
|
||||||
pub fn is_cycleway(&self) -> bool {
|
pub fn is_cycleway(&self) -> bool {
|
||||||
let mut bike = false;
|
let mut bike = false;
|
||||||
for (_, _, lt) in self.lanes_ltr() {
|
for lane in &self.lanes {
|
||||||
if lt == LaneType::Biking {
|
if lane.lane_type == LaneType::Biking {
|
||||||
bike = true;
|
bike = true;
|
||||||
} else if lt != LaneType::Shoulder {
|
} else if lane.lane_type != LaneType::Shoulder {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -509,7 +499,6 @@ impl Road {
|
|||||||
|
|
||||||
pub(crate) fn recreate_lanes(&mut self, lane_specs_ltr: Vec<LaneSpec>) {
|
pub(crate) fn recreate_lanes(&mut self, lane_specs_ltr: Vec<LaneSpec>) {
|
||||||
self.lanes.clear();
|
self.lanes.clear();
|
||||||
self.lanes_ltr.clear();
|
|
||||||
|
|
||||||
let mut total_width = Distance::ZERO;
|
let mut total_width = Distance::ZERO;
|
||||||
for lane in &lane_specs_ltr {
|
for lane in &lane_specs_ltr {
|
||||||
@ -548,8 +537,6 @@ impl Road {
|
|||||||
};
|
};
|
||||||
width_so_far += lane.width;
|
width_so_far += lane.width;
|
||||||
|
|
||||||
// TODO Revisit
|
|
||||||
self.lanes_ltr.push((id, lane.dir, lane.lt));
|
|
||||||
self.lanes.push(Lane {
|
self.lanes.push(Lane {
|
||||||
id,
|
id,
|
||||||
lane_center_pts,
|
lane_center_pts,
|
||||||
@ -570,13 +557,13 @@ impl Road {
|
|||||||
pub fn get_lanes_between(&self, l1: LaneID, l2: LaneID) -> Vec<LaneID> {
|
pub fn get_lanes_between(&self, l1: LaneID, l2: LaneID) -> Vec<LaneID> {
|
||||||
let mut results = Vec::new();
|
let mut results = Vec::new();
|
||||||
let mut found_start = false;
|
let mut found_start = false;
|
||||||
for (l, _, _) in self.lanes_ltr() {
|
for l in &self.lanes {
|
||||||
if found_start {
|
if found_start {
|
||||||
if l == l1 || l == l2 {
|
if l.id == l1 || l.id == l2 {
|
||||||
return results;
|
return results;
|
||||||
}
|
}
|
||||||
results.push(l);
|
results.push(l.id);
|
||||||
} else if l == l1 || l == l2 {
|
} else if l.id == l1 || l.id == l2 {
|
||||||
found_start = true;
|
found_start = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -594,11 +581,11 @@ impl Road {
|
|||||||
let mut bike_lanes = false;
|
let mut bike_lanes = false;
|
||||||
let mut can_use = false;
|
let mut can_use = false;
|
||||||
// Can a bike even use it, or is it a highway?
|
// Can a bike even use it, or is it a highway?
|
||||||
for (l, _, lt) in self.lanes_ltr() {
|
for l in &self.lanes {
|
||||||
if lt == LaneType::Biking {
|
if l.lane_type == LaneType::Biking {
|
||||||
bike_lanes = true;
|
bike_lanes = true;
|
||||||
}
|
}
|
||||||
if PathConstraints::Bike.can_use(map.get_l(l), map) {
|
if PathConstraints::Bike.can_use(l, map) {
|
||||||
can_use = true;
|
can_use = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -609,26 +596,26 @@ impl Road {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO All of this is kind of deprecated? During the transiton towards lanes_ltr, some pieces
|
// TODO All of this is kind of deprecated? Some callers seem to really need to still handle lanes
|
||||||
// seemed to really need to still handle lanes going outward from the "center" line. Should keep
|
// going outward from the "center" line. Should keep whittling this down, probably. These very much
|
||||||
// whittling this down, probably. These very much don't handle multiple direction changes.
|
// don't handle multiple direction changes.
|
||||||
impl Road {
|
impl Road {
|
||||||
/// These are ordered from closest to center lane (left-most when driving on the right) to
|
/// These are ordered from closest to center lane (left-most when driving on the right) to
|
||||||
/// farthest (sidewalk)
|
/// farthest (sidewalk)
|
||||||
pub(crate) fn children_forwards(&self) -> Vec<(LaneID, LaneType)> {
|
pub(crate) fn children_forwards(&self) -> Vec<(LaneID, LaneType)> {
|
||||||
let mut result = Vec::new();
|
let mut result = Vec::new();
|
||||||
for (l, dir, lt) in self.lanes_ltr() {
|
for l in &self.lanes {
|
||||||
if dir == Direction::Fwd {
|
if l.dir == Direction::Fwd {
|
||||||
result.push((l, lt));
|
result.push((l.id, l.lane_type));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
result
|
result
|
||||||
}
|
}
|
||||||
pub(crate) fn children_backwards(&self) -> Vec<(LaneID, LaneType)> {
|
pub(crate) fn children_backwards(&self) -> Vec<(LaneID, LaneType)> {
|
||||||
let mut result = Vec::new();
|
let mut result = Vec::new();
|
||||||
for (l, dir, lt) in self.lanes_ltr() {
|
for l in &self.lanes {
|
||||||
if dir == Direction::Back {
|
if l.dir == Direction::Back {
|
||||||
result.push((l, lt));
|
result.push((l.id, l.lane_type));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
result.reverse();
|
result.reverse();
|
||||||
|
@ -65,11 +65,11 @@ impl ControlStopSign {
|
|||||||
Direction::Back
|
Direction::Back
|
||||||
};
|
};
|
||||||
let travel_lanes: Vec<LaneID> = r
|
let travel_lanes: Vec<LaneID> = r
|
||||||
.lanes_ltr()
|
.lanes
|
||||||
.into_iter()
|
.iter()
|
||||||
.filter_map(|(id, dir, lt)| {
|
.filter_map(|l| {
|
||||||
if dir == want_dir && lt.is_for_moving_vehicles() {
|
if l.dir == want_dir && l.lane_type.is_for_moving_vehicles() {
|
||||||
Some(id)
|
Some(l.id)
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
@ -364,10 +364,10 @@ impl Movement {
|
|||||||
let mut rightmost = Distance::ZERO;
|
let mut rightmost = Distance::ZERO;
|
||||||
let mut left = Distance::ZERO;
|
let mut left = Distance::ZERO;
|
||||||
|
|
||||||
for (l, _, _) in r.lanes_ltr() {
|
for l in &r.lanes {
|
||||||
let right = left + map.get_l(l).width;
|
let right = left + l.width;
|
||||||
|
|
||||||
if self.members.iter().any(|t| t.src == l) {
|
if self.members.iter().any(|t| t.src == l.id) {
|
||||||
leftmost = leftmost.min(left);
|
leftmost = leftmost.min(left);
|
||||||
rightmost = rightmost.max(right);
|
rightmost = rightmost.max(right);
|
||||||
}
|
}
|
||||||
|
@ -205,8 +205,8 @@ impl Player {
|
|||||||
On::Intersection(i) => app.map.get_i(i).roads.iter().cloned().collect(),
|
On::Intersection(i) => app.map.get_i(i).roads.iter().cloned().collect(),
|
||||||
};
|
};
|
||||||
for r in roads {
|
for r in roads {
|
||||||
for (_, _, lt) in app.map.get_r(r).lanes_ltr() {
|
for l in &app.map.get_r(r).lanes {
|
||||||
if lt == LaneType::Biking || lt == LaneType::Bus {
|
if l.lane_type == LaneType::Biking || l.lane_type == LaneType::Bus {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1083,14 +1083,13 @@ impl DrivingSimState {
|
|||||||
let current_lane = map.get_l(car.router.head().maybe_lane()?);
|
let current_lane = map.get_l(car.router.head().maybe_lane()?);
|
||||||
let road = map.get_r(current_lane.parent);
|
let road = map.get_r(current_lane.parent);
|
||||||
let idx = road.offset(current_lane.id);
|
let idx = road.offset(current_lane.id);
|
||||||
let lanes_ltr = road.lanes_ltr();
|
|
||||||
|
|
||||||
let mut candidates = Vec::new();
|
let mut candidates = Vec::new();
|
||||||
if idx != 0 {
|
if idx != 0 {
|
||||||
candidates.push(lanes_ltr[idx - 1].0);
|
candidates.push(road.lanes[idx - 1].id);
|
||||||
}
|
}
|
||||||
if idx != lanes_ltr.len() - 1 {
|
if idx != road.lanes.len() - 1 {
|
||||||
candidates.push(lanes_ltr[idx + 1].0);
|
candidates.push(road.lanes[idx + 1].id);
|
||||||
}
|
}
|
||||||
if map.get_config().driving_side == DrivingSide::Left {
|
if map.get_config().driving_side == DrivingSide::Left {
|
||||||
candidates.reverse();
|
candidates.reverse();
|
||||||
|
@ -399,27 +399,27 @@ impl Router {
|
|||||||
let mut original_cost = None;
|
let mut original_cost = None;
|
||||||
let dir = map.get_l(orig_target_lane).dir;
|
let dir = map.get_l(orig_target_lane).dir;
|
||||||
let best = parent
|
let best = parent
|
||||||
.lanes_ltr()
|
.lanes
|
||||||
.into_iter()
|
.iter()
|
||||||
.filter(|(l, d, _)| dir == *d && constraints.can_use(map.get_l(*l), map))
|
.filter(|l| l.dir == dir && constraints.can_use(l, map))
|
||||||
.filter_map(|(l, _, _)| {
|
.filter_map(|l| {
|
||||||
// Make sure we can go from this lane to next_lane.
|
// Make sure we can go from this lane to next_lane.
|
||||||
|
|
||||||
let t1 = TurnID {
|
let t1 = TurnID {
|
||||||
parent: current_turn.parent,
|
parent: current_turn.parent,
|
||||||
src: current_turn.src,
|
src: current_turn.src,
|
||||||
dst: l,
|
dst: l.id,
|
||||||
};
|
};
|
||||||
let turn1 = map.maybe_get_t(t1)?;
|
let turn1 = map.maybe_get_t(t1)?;
|
||||||
|
|
||||||
let t2 = TurnID {
|
let t2 = TurnID {
|
||||||
parent: next_parent,
|
parent: next_parent,
|
||||||
src: l,
|
src: l.id,
|
||||||
dst: next_lane,
|
dst: next_lane,
|
||||||
};
|
};
|
||||||
let turn2 = map.maybe_get_t(t2)?;
|
let turn2 = map.maybe_get_t(t2)?;
|
||||||
|
|
||||||
Some((turn1, l, turn2))
|
Some((turn1, l.id, turn2))
|
||||||
})
|
})
|
||||||
.map(|(turn1, l, turn2)| {
|
.map(|(turn1, l, turn2)| {
|
||||||
let cost = compute_cost(turn1, l);
|
let cost = compute_cost(turn1, l);
|
||||||
|
Loading…
Reference in New Issue
Block a user