mirror of
https://github.com/a-b-street/abstreet.git
synced 2024-11-28 12:12:00 +03:00
ripping out other_side too
This commit is contained in:
parent
c04572e4c7
commit
7d187bcceb
@ -1,24 +1,15 @@
|
||||
# TODO for Phase 1 (Basemap)
|
||||
|
||||
- turns for bike lanes
|
||||
- road with many lanes
|
||||
- make intersection know about roads, not lanes
|
||||
- make/turns can use this especially. intersections should refer to different things.
|
||||
|
||||
- trim buidings and parcels that're nowhere near roads (aka, the bbox is kinda wrong)
|
||||
|
||||
- road with many lanes
|
||||
- remove offset stuff from lanespec! \o/
|
||||
- make intersection know about roads, not lanes
|
||||
- make/turns can use this especially. intersections should refer to different things.
|
||||
- clean up all state in lane
|
||||
|
||||
|
||||
- maybe also the time to split into different lane types? what's similar/not between them?
|
||||
- graph querying?
|
||||
- rendering (and other UI/editor interactions)?
|
||||
- sim state?
|
||||
- figure out what to do about yellow center lines
|
||||
- yellow and white lines intersect cars and turn icons and such
|
||||
- who should own drawing them?
|
||||
- trim them back too (maybe to avoid hitting the intersection?)
|
||||
- maybe also the time to split into different lane types? what's similar/not between them?
|
||||
- graph querying?
|
||||
- rendering (and other UI/editor interactions)?
|
||||
- sim state?
|
||||
|
||||
- more data
|
||||
- draw water and greenery areas
|
||||
@ -40,6 +31,10 @@
|
||||
- sidewalk paths start in building centers and end in sidewalk centers
|
||||
- this is probably fine to show agents moving, but at least draw
|
||||
building layer before sidewalk layer
|
||||
- figure out what to do about yellow center lines
|
||||
- yellow and white lines intersect cars and turn icons and such
|
||||
- who should own drawing them?
|
||||
- trim them back too (maybe to avoid hitting the intersection?)
|
||||
|
||||
- code cleanup
|
||||
- make final Map serializable too
|
||||
|
@ -142,19 +142,19 @@ fn calculate_crosswalks(
|
||||
.iter()
|
||||
.chain(inter.incoming_lanes.iter())
|
||||
{
|
||||
let r1 = map.get_l(*id);
|
||||
if r1.lane_type != map_model::LaneType::Sidewalk {
|
||||
let l1 = map.get_l(*id);
|
||||
if l1.lane_type != map_model::LaneType::Sidewalk {
|
||||
continue;
|
||||
}
|
||||
if r1.other_side.unwrap().0 < r1.id.0 {
|
||||
let l2 = map.get_l(map.get_r(l1.parent).get_opposite_lane(l1.id, map).unwrap());
|
||||
if l2.id < l1.id {
|
||||
continue;
|
||||
}
|
||||
let r2 = map.get_l(r1.other_side.unwrap());
|
||||
|
||||
let line = if r1.src_i == inter.id {
|
||||
Line::new(r1.first_pt(), r2.last_pt())
|
||||
let line = if l1.src_i == inter.id {
|
||||
Line::new(l1.first_pt(), l2.last_pt())
|
||||
} else {
|
||||
Line::new(r1.last_pt(), r2.first_pt())
|
||||
Line::new(l1.last_pt(), l2.first_pt())
|
||||
};
|
||||
let angle = line.angle();
|
||||
let length = line.length();
|
||||
|
@ -42,13 +42,9 @@ pub struct Lane {
|
||||
// use this breakage to infer that a road doesn't have so many lanes.
|
||||
pub probably_broken: bool,
|
||||
|
||||
// TODO i think everything else should be moved to road, honestly.
|
||||
// This is redundant with road, but kind of annoying to compute constantly, so leave it for now
|
||||
pub src_i: IntersectionID,
|
||||
pub dst_i: IntersectionID,
|
||||
|
||||
// Need to remember this just for detecting U-turns here. Also for finding sidewalks to connect
|
||||
// with a crosswalk.
|
||||
pub other_side: Option<LaneID>,
|
||||
}
|
||||
|
||||
impl PartialEq for Lane {
|
||||
|
@ -21,8 +21,6 @@ fn get_lanes(r: &raw_data::Road) -> (Vec<LaneType>, Vec<LaneType>) {
|
||||
} else {
|
||||
1
|
||||
};
|
||||
// TODO debugging convenience
|
||||
let only_driving_lanes_for_debugging = false;
|
||||
|
||||
if junction {
|
||||
return (vec![LaneType::Driving], Vec::new());
|
||||
@ -33,7 +31,7 @@ fn get_lanes(r: &raw_data::Road) -> (Vec<LaneType>, Vec<LaneType>) {
|
||||
let driving_lanes: Vec<LaneType> = iter::repeat(LaneType::Driving)
|
||||
.take(num_driving_lanes / 2)
|
||||
.collect();
|
||||
if only_driving_lanes_for_debugging || big_highway {
|
||||
if big_highway {
|
||||
if oneway {
|
||||
let mut all_lanes = Vec::new();
|
||||
all_lanes.extend(driving_lanes.clone());
|
||||
@ -62,149 +60,27 @@ pub(crate) struct LaneSpec {
|
||||
pub lane_type: LaneType,
|
||||
pub offset: u8,
|
||||
pub reverse_pts: bool,
|
||||
pub offset_for_other_id: Option<isize>,
|
||||
}
|
||||
|
||||
impl LaneSpec {
|
||||
fn new(
|
||||
lane_type: LaneType,
|
||||
offset: u8,
|
||||
reverse_pts: bool,
|
||||
offset_for_other_id: Option<isize>,
|
||||
) -> LaneSpec {
|
||||
fn new(lane_type: LaneType, offset: u8, reverse_pts: bool) -> LaneSpec {
|
||||
LaneSpec {
|
||||
lane_type,
|
||||
offset,
|
||||
reverse_pts,
|
||||
offset_for_other_id,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn get_lane_specs(r: &raw_data::Road) -> Vec<LaneSpec> {
|
||||
lane_specs_for(get_lanes(r))
|
||||
}
|
||||
let (side1_types, side2_types) = get_lanes(r);
|
||||
|
||||
fn lane_specs_for((side1_types, side2_types): (Vec<LaneType>, Vec<LaneType>)) -> Vec<LaneSpec> {
|
||||
let mut specs: Vec<LaneSpec> = Vec::new();
|
||||
|
||||
// This seems like a messy approach. :\
|
||||
let sidewalk1_idx = side1_types.iter().position(|<| lt == LaneType::Sidewalk);
|
||||
let sidewalk2_idx = side2_types.iter().position(|<| lt == LaneType::Sidewalk);
|
||||
|
||||
for (idx, lane_type) in side1_types.iter().enumerate() {
|
||||
let offset_for_other_id = match lane_type {
|
||||
LaneType::Sidewalk => {
|
||||
sidewalk2_idx.map(|idx| (side1_types.len() - sidewalk1_idx.unwrap() + idx) as isize)
|
||||
}
|
||||
LaneType::Parking => None,
|
||||
LaneType::Biking => if !side2_types.contains(&LaneType::Biking) {
|
||||
None
|
||||
} else {
|
||||
assert!(side1_types == side2_types);
|
||||
Some(side1_types.len() as isize)
|
||||
},
|
||||
LaneType::Driving => if !side2_types.contains(&LaneType::Driving) {
|
||||
None
|
||||
} else {
|
||||
assert!(side1_types == side2_types);
|
||||
Some(side1_types.len() as isize)
|
||||
},
|
||||
};
|
||||
|
||||
specs.push(LaneSpec::new(
|
||||
*lane_type,
|
||||
idx as u8,
|
||||
false,
|
||||
offset_for_other_id,
|
||||
));
|
||||
specs.push(LaneSpec::new(*lane_type, idx as u8, false));
|
||||
}
|
||||
for (idx, lane_type) in side2_types.iter().enumerate() {
|
||||
let offset_for_other_id = match lane_type {
|
||||
LaneType::Parking => None,
|
||||
LaneType::Biking => Some(-1 * (side1_types.len() as isize)),
|
||||
LaneType::Sidewalk => sidewalk2_idx
|
||||
.map(|idx| -1 * ((side1_types.len() - sidewalk1_idx.unwrap() + idx) as isize)),
|
||||
LaneType::Driving => Some(-1 * (side1_types.len() as isize)),
|
||||
};
|
||||
|
||||
specs.push(LaneSpec::new(
|
||||
*lane_type,
|
||||
idx as u8,
|
||||
true,
|
||||
offset_for_other_id,
|
||||
));
|
||||
specs.push(LaneSpec::new(*lane_type, idx as u8, true));
|
||||
}
|
||||
|
||||
specs
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn junction() {
|
||||
let d = LaneType::Driving;
|
||||
|
||||
assert_eq!(
|
||||
lane_specs_for((vec![d], vec![])),
|
||||
vec![LaneSpec::new(d, 0, false, None)]
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn oneway() {
|
||||
let d = LaneType::Driving;
|
||||
let p = LaneType::Parking;
|
||||
let s = LaneType::Sidewalk;
|
||||
|
||||
assert_eq!(
|
||||
lane_specs_for((vec![d, p, s], vec![s])),
|
||||
vec![
|
||||
LaneSpec::new(d, 0, false, None),
|
||||
LaneSpec::new(p, 1, false, None),
|
||||
LaneSpec::new(s, 2, false, Some(1)),
|
||||
LaneSpec::new(s, 0, true, Some(-1)),
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn twoway() {
|
||||
let d = LaneType::Driving;
|
||||
let p = LaneType::Parking;
|
||||
let s = LaneType::Sidewalk;
|
||||
|
||||
assert_eq!(
|
||||
lane_specs_for((vec![d, p, s], vec![d, p, s])),
|
||||
vec![
|
||||
LaneSpec::new(d, 0, false, Some(3)),
|
||||
LaneSpec::new(p, 1, false, None),
|
||||
LaneSpec::new(s, 2, false, Some(3)),
|
||||
LaneSpec::new(d, 0, true, Some(-3)),
|
||||
LaneSpec::new(p, 1, true, None),
|
||||
LaneSpec::new(s, 2, true, Some(-3)),
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn big_twoway() {
|
||||
let d = LaneType::Driving;
|
||||
let b = LaneType::Biking;
|
||||
let p = LaneType::Parking;
|
||||
let s = LaneType::Sidewalk;
|
||||
|
||||
assert_eq!(
|
||||
lane_specs_for((vec![d, d, b, p, s], vec![d, d, b, p, s])),
|
||||
vec![
|
||||
LaneSpec::new(d, 0, false, Some(5)),
|
||||
LaneSpec::new(d, 1, false, Some(5)),
|
||||
LaneSpec::new(b, 2, false, Some(5)),
|
||||
LaneSpec::new(p, 3, false, None),
|
||||
LaneSpec::new(s, 4, false, Some(5)),
|
||||
LaneSpec::new(d, 0, true, Some(-5)),
|
||||
LaneSpec::new(d, 1, true, Some(-5)),
|
||||
LaneSpec::new(b, 2, true, Some(-5)),
|
||||
LaneSpec::new(p, 3, true, None),
|
||||
LaneSpec::new(s, 4, true, Some(-5)),
|
||||
]
|
||||
);
|
||||
}
|
||||
|
@ -6,4 +6,4 @@ mod turns;
|
||||
pub(crate) use self::buildings::make_building;
|
||||
pub(crate) use self::lanes::get_lane_specs;
|
||||
pub(crate) use self::trim_lines::trim_lines;
|
||||
pub(crate) use self::turns::{make_biking_turns, make_crosswalks, make_driving_turns};
|
||||
pub(crate) use self::turns::make_all_turns;
|
||||
|
@ -3,7 +3,17 @@ use geom::Line;
|
||||
use std::collections::HashSet;
|
||||
use {Intersection, IntersectionID, LaneID, LaneType, Map, RoadID, Turn, TurnID};
|
||||
|
||||
pub(crate) fn make_driving_turns(i: &Intersection, m: &Map, turn_id_start: usize) -> Vec<Turn> {
|
||||
pub(crate) fn make_all_turns(i: &Intersection, m: &Map, turn_id_start: usize) -> Vec<Turn> {
|
||||
let mut turns: Vec<Turn> = Vec::new();
|
||||
turns.extend(make_driving_turns(i, m, turn_id_start));
|
||||
let len = turns.len();
|
||||
turns.extend(make_biking_turns(i, m, turn_id_start + len));
|
||||
let len = turns.len();
|
||||
turns.extend(make_crosswalks(i, m, turn_id_start + len));
|
||||
turns
|
||||
}
|
||||
|
||||
fn make_driving_turns(i: &Intersection, m: &Map, turn_id_start: usize) -> Vec<Turn> {
|
||||
let incoming: Vec<LaneID> = i.incoming_lanes
|
||||
.iter()
|
||||
// TODO why's this double borrow happen?
|
||||
@ -19,7 +29,7 @@ pub(crate) fn make_driving_turns(i: &Intersection, m: &Map, turn_id_start: usize
|
||||
make_turns(m, turn_id_start, i.id, &incoming, &outgoing)
|
||||
}
|
||||
|
||||
pub(crate) fn make_biking_turns(i: &Intersection, m: &Map, turn_id_start: usize) -> Vec<Turn> {
|
||||
fn make_biking_turns(i: &Intersection, m: &Map, turn_id_start: usize) -> Vec<Turn> {
|
||||
// TODO great further evidence of needing a road/lane distinction
|
||||
let mut incoming_roads: HashSet<RoadID> = HashSet::new();
|
||||
let mut incoming_bike_lanes_per_road: MultiMap<RoadID, LaneID> = MultiMap::new();
|
||||
@ -96,10 +106,12 @@ fn make_turns(
|
||||
let mut result = Vec::new();
|
||||
for src in incoming {
|
||||
let src_l = map.get_l(*src);
|
||||
let other_side = map.get_r(src_l.parent).get_opposite_lane(src_l.id, map);
|
||||
|
||||
for dst in outgoing {
|
||||
let dst_l = map.get_l(*dst);
|
||||
// Don't create U-turns unless it's a dead-end
|
||||
if src_l.other_side == Some(dst_l.id) && !dead_end {
|
||||
if other_side == Some(dst_l.id) && !dead_end {
|
||||
continue;
|
||||
}
|
||||
|
||||
@ -117,7 +129,7 @@ fn make_turns(
|
||||
result
|
||||
}
|
||||
|
||||
pub(crate) fn make_crosswalks(i: &Intersection, m: &Map, mut turn_id_start: usize) -> Vec<Turn> {
|
||||
fn make_crosswalks(i: &Intersection, m: &Map, mut turn_id_start: usize) -> Vec<Turn> {
|
||||
let mut result = Vec::new();
|
||||
|
||||
// TODO dedupe some of this logic render/intersection
|
||||
@ -129,7 +141,7 @@ pub(crate) fn make_crosswalks(i: &Intersection, m: &Map, mut turn_id_start: usiz
|
||||
if src.lane_type != LaneType::Sidewalk {
|
||||
continue;
|
||||
}
|
||||
let dst = m.get_l(src.other_side.unwrap());
|
||||
let dst = m.get_l(m.get_r(src.parent).get_opposite_lane(src.id, m).unwrap());
|
||||
|
||||
let id = TurnID(turn_id_start);
|
||||
turn_id_start += 1;
|
||||
|
@ -82,8 +82,6 @@ impl Map {
|
||||
for lane in make::get_lane_specs(r) {
|
||||
let id = LaneID(counter);
|
||||
counter += 1;
|
||||
let other_side = lane.offset_for_other_id
|
||||
.map(|offset| LaneID(((id.0 as isize) + offset) as usize));
|
||||
|
||||
let mut unshifted_pts = road_center_pts.clone();
|
||||
if lane.reverse_pts {
|
||||
@ -109,7 +107,6 @@ impl Map {
|
||||
// lane_center_pts will get updated in the next pass
|
||||
m.lanes.push(Lane {
|
||||
id,
|
||||
other_side,
|
||||
lane_center_pts,
|
||||
probably_broken,
|
||||
src_i: i1,
|
||||
@ -133,12 +130,9 @@ impl Map {
|
||||
}
|
||||
|
||||
for i in &m.intersections {
|
||||
let turns1 = make::make_driving_turns(i, &m, m.turns.len());
|
||||
m.turns.extend(turns1);
|
||||
let turns2 = make::make_biking_turns(i, &m, m.turns.len());
|
||||
m.turns.extend(turns2);
|
||||
let crosswalks = make::make_crosswalks(i, &m, m.turns.len());
|
||||
m.turns.extend(crosswalks);
|
||||
let len = m.turns.len();
|
||||
let turns = make::make_all_turns(i, &m, len);
|
||||
m.turns.extend(turns);
|
||||
}
|
||||
for t in &m.turns {
|
||||
m.intersections[t.parent.0].turns.push(t.id);
|
||||
|
@ -23,6 +23,7 @@ pub struct Road {
|
||||
// Invariant: A road must contain at least one child
|
||||
pub children_forwards: Vec<LaneID>,
|
||||
pub children_backwards: Vec<LaneID>,
|
||||
// TODO should consider having a redundant lookup from LaneID to direction and lane type
|
||||
|
||||
// Unshifted center points. Order implies road orientation.
|
||||
pub center_pts: PolyLine,
|
||||
@ -67,6 +68,28 @@ impl Road {
|
||||
.map(|id| *id)
|
||||
}
|
||||
|
||||
pub fn get_opposite_lane(&self, lane: LaneID, map: &Map) -> Option<LaneID> {
|
||||
let lane_type = map.get_l(lane).lane_type;
|
||||
let forwards: Vec<LaneID> = self.children_forwards
|
||||
.iter()
|
||||
.filter(|&&id| map.get_l(id).lane_type == lane_type)
|
||||
.map(|id| *id)
|
||||
.collect();
|
||||
let backwards: Vec<LaneID> = self.children_backwards
|
||||
.iter()
|
||||
.filter(|&&id| map.get_l(id).lane_type == lane_type)
|
||||
.map(|id| *id)
|
||||
.collect();
|
||||
|
||||
if let Some(idx) = forwards.iter().position(|id| *id == lane) {
|
||||
return backwards.get(idx).map(|id| *id);
|
||||
}
|
||||
if let Some(idx) = backwards.iter().position(|id| *id == lane) {
|
||||
return forwards.get(idx).map(|id| *id);
|
||||
}
|
||||
panic!("{} doesn't contain {}", self.id, lane);
|
||||
}
|
||||
|
||||
fn get_siblings(&self, lane: LaneID) -> &Vec<LaneID> {
|
||||
// TODO rm lane from this list?
|
||||
if self.children_forwards.contains(&lane) {
|
||||
|
Loading…
Reference in New Issue
Block a user