ripping out other_side too

This commit is contained in:
Dustin Carlino 2018-07-24 10:13:50 -07:00
parent c04572e4c7
commit 7d187bcceb
8 changed files with 68 additions and 172 deletions

View File

@ -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

View File

@ -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();

View File

@ -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 {

View File

@ -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| lt == LaneType::Sidewalk);
let sidewalk2_idx = side2_types.iter().position(|&lt| 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)),
]
);
}

View File

@ -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;

View File

@ -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;

View File

@ -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);

View File

@ -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) {