Skip to content

Commit

Permalink
Handle diagonal and perpendicular parking
Browse files Browse the repository at this point in the history
  • Loading branch information
dabreegster committed Apr 1, 2024
1 parent c25be02 commit eba8b28
Show file tree
Hide file tree
Showing 14 changed files with 1,674 additions and 1,491 deletions.
20 changes: 2 additions & 18 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 2 additions & 1 deletion osm2lanes-js/example.html
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,8 @@
bikes_can_use_bus_lanes: true,
inferred_sidewalks: false,
inferred_kerbs: true,
street_parking_spot_length: 8.0,
parallel_street_parking_spot_length: 8.0,
vehicle_width_for_parking_spots: 3.0,
turn_on_red: true,
include_railroads: true,
},
Expand Down
29 changes: 23 additions & 6 deletions osm2lanes/src/algorithm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,19 @@ use enumset::EnumSet;
use geom::Distance;
use muv_osm::{
conditional::MatchSituation,
lanes::{lanes, travel::TravelLane, Lane, LaneIndex, LaneVariant},
lanes::{
lanes,
parking::{ParkingLane, ParkingOrientation},
travel::TravelLane,
Lane, LaneIndex, LaneVariant,
},
units::{self, Quantity},
AccessLevel, Conditional, Lifecycle, Location, TMode, TModes, Tag, Vehicle,
AccessLevel, Conditional, Lifecycle, Location, TMode, TModes, Tag, Taglike, Vehicle,
};

use crate::{
osm::{self, HIGHWAY},
BufferType, Direction, DrivingSide, LaneSpec, LaneType, MapConfig, TurnDirection,
BufferType, Direction, DrivingSide, LaneSpec, LaneType, MapConfig, ParkingType, TurnDirection,
};

/// Purely from OSM tags, determine the lanes that a road segment has.
Expand Down Expand Up @@ -114,7 +119,7 @@ fn from_lane(
) -> LaneSpec {
let (lt, dir, turns) = match &lane.variant {
LaneVariant::Travel(t) => travel_lane(t, lane.is_sidepath, traffic_direction, date_time),
LaneVariant::Parking(_) => parking_lane(traffic_direction),
LaneVariant::Parking(p) => parking_lane(p, traffic_direction),
};

let width = lane.width.map_or_else(
Expand Down Expand Up @@ -296,8 +301,20 @@ fn travel_lane(
(LaneType::Construction, Direction::Forward, EnumSet::new())
}

fn parking_lane(traffic_direction: Direction) -> (LaneType, Direction, EnumSet<TurnDirection>) {
(LaneType::Parking, traffic_direction, EnumSet::new())
fn parking_lane(
p: &ParkingLane,
traffic_direction: Direction,
) -> (LaneType, Direction, EnumSet<TurnDirection>) {
let parking_type = match p.orientation {
Some(ParkingOrientation::Parallel) | None => ParkingType::Parallel,
Some(ParkingOrientation::Diagonal) => ParkingType::Diagonal,
Some(ParkingOrientation::Perpendicular) => ParkingType::Perpendicular,
};
(
LaneType::Parking(parking_type),
traffic_direction,
EnumSet::new(),
)
}

fn distance_from_muv(qty: Quantity<units::Distance>) -> Distance {
Expand Down
2 changes: 1 addition & 1 deletion osm2lanes/src/edit/add_bike_lanes.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ impl LaneSpec {
let mut num_driving_lanes = 0;
let mut already_has_bike_lane = false;
for (idx, spec) in side.iter().enumerate() {
if spec.lt == LaneType::Parking && parking_lane.is_none() {
if matches!(spec.lt, LaneType::Parking(_)) && parking_lane.is_none() {
parking_lane = Some(idx);
}
if spec.lt == LaneType::Driving && first_driving_lane.is_none() {
Expand Down
2 changes: 1 addition & 1 deletion osm2lanes/src/edit/add_new_lane.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ impl LaneSpec {
.map(|x| x + 1)
.unwrap_or(lanes_ltr.len());
}
LaneType::Biking | LaneType::Bus | LaneType::Parking | LaneType::Construction => {
LaneType::Biking | LaneType::Bus | LaneType::Parking(_) | LaneType::Construction => {
let relevant_lanes: Vec<&LaneSpec> =
lanes_ltr.iter().filter(|x| x.lt == lt).collect();
dir = if !relevant_lanes.is_empty() {
Expand Down
51 changes: 32 additions & 19 deletions osm2lanes/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ const SHOULDER_THICKNESS: Distance = Distance::const_meters(0.5);
#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq, PartialOrd, Ord, Serialize, Deserialize)]
pub enum LaneType {
Driving,
Parking,
Parking(ParkingType),
Sidewalk,
// Walkable like a Sidewalk, but very narrow. Used to model pedestrians walking on roads
// without sidewalks.
Expand Down Expand Up @@ -62,13 +62,20 @@ pub enum BufferType {
Verge,
}

#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq, PartialOrd, Ord, Serialize, Deserialize)]
pub enum ParkingType {
Parallel,
Diagonal,
Perpendicular,
}

impl LaneType {
pub fn is_for_moving_vehicles(self) -> bool {
match self {
LaneType::Driving => true,
LaneType::Biking => true,
LaneType::Bus => true,
LaneType::Parking => false,
LaneType::Parking(_) => false,
LaneType::Sidewalk => false,
LaneType::Shoulder => false,
LaneType::SharedLeftTurn => false,
Expand All @@ -85,7 +92,7 @@ impl LaneType {
LaneType::Driving => true,
LaneType::Biking => true,
LaneType::Bus => true,
LaneType::Parking => false,
LaneType::Parking(_) => false,
LaneType::Sidewalk => true,
LaneType::Shoulder => true,
LaneType::SharedLeftTurn => false,
Expand All @@ -107,7 +114,7 @@ impl LaneType {
LaneType::Driving => true,
LaneType::Biking => true, // FIXME depends on lane vs track
LaneType::Bus => true,
LaneType::Parking => false,
LaneType::Parking(_) => false,
LaneType::Sidewalk => false,
LaneType::Shoulder => false,
LaneType::SharedLeftTurn => true,
Expand All @@ -126,7 +133,7 @@ impl LaneType {
LaneType::Driving => true,
LaneType::Biking => true, // FIXME depends on lane vs track
LaneType::Bus => true,
LaneType::Parking => true, // FIXME depends on on-street vs street-side
LaneType::Parking(_) => true, // FIXME depends on on-street vs street-side
LaneType::Sidewalk => false,
LaneType::Shoulder => true,
LaneType::SharedLeftTurn => true,
Expand Down Expand Up @@ -156,7 +163,7 @@ impl LaneType {
SharedUse | Biking => Some(TrafficClass::Bicycle),
Bus | SharedLeftTurn | Driving => Some(TrafficClass::Motor),
LightRail => Some(TrafficClass::Rail),
Buffer(_) | Shoulder | Construction | Parking => None,
Buffer(_) | Shoulder | Construction | Parking(_) => None,
}
}

Expand All @@ -165,7 +172,7 @@ impl LaneType {
LaneType::Driving => "a general-purpose driving lane",
LaneType::Biking => "a bike lane",
LaneType::Bus => "a bus-only lane",
LaneType::Parking => "an on-street parking lane",
LaneType::Parking(_) => "an on-street parking lane",
LaneType::Sidewalk => "a sidewalk",
LaneType::Shoulder => "a shoulder",
LaneType::SharedLeftTurn => "a shared left-turn lane",
Expand All @@ -187,7 +194,9 @@ impl LaneType {
LaneType::Driving => "driving lane",
LaneType::Biking => "bike lane",
LaneType::Bus => "bus lane",
LaneType::Parking => "parking lane",
LaneType::Parking(ParkingType::Parallel) => "parallel parking lane",
LaneType::Parking(ParkingType::Diagonal) => "diagonal parking lane",
LaneType::Parking(ParkingType::Perpendicular) => "perpendicular parking lane",
LaneType::Sidewalk => "sidewalk",
LaneType::Shoulder => "shoulder",
LaneType::SharedLeftTurn => "left-turn lane",
Expand All @@ -209,7 +218,9 @@ impl LaneType {
"driving lane" => Some(LaneType::Driving),
"bike lane" => Some(LaneType::Biking),
"bus lane" => Some(LaneType::Bus),
"parking lane" => Some(LaneType::Parking),
"parallel parking lane" => Some(LaneType::Parking(ParkingType::Parallel)),
"diagonal parking lane" => Some(LaneType::Parking(ParkingType::Diagonal)),
"perpendicular parking lane" => Some(LaneType::Parking(ParkingType::Perpendicular)),
"sidewalk" => Some(LaneType::Sidewalk),
"shoulder" => Some(LaneType::Shoulder),
"left-turn lane" => Some(LaneType::SharedLeftTurn),
Expand All @@ -233,7 +244,7 @@ impl LaneType {
LaneType::Driving => 'd',
LaneType::Biking => 'b',
LaneType::Bus => 'B',
LaneType::Parking => 'p',
LaneType::Parking(_) => 'p',
LaneType::Sidewalk => 's',
LaneType::Shoulder => 'S',
LaneType::SharedLeftTurn => 'C',
Expand All @@ -245,13 +256,13 @@ impl LaneType {
}
}

/// The inverse of `to_char`. Always picks one buffer type. Panics on invalid input.
/// The inverse of `to_char`. Always picks one buffer and parking type. Panics on invalid input.
pub fn from_char(x: char) -> LaneType {
match x {
'd' => LaneType::Driving,
'b' => LaneType::Biking,
'B' => LaneType::Bus,
'p' => LaneType::Parking,
'p' => LaneType::Parking(ParkingType::Parallel),
's' => LaneType::Sidewalk,
'S' => LaneType::Shoulder,
'C' => LaneType::SharedLeftTurn,
Expand Down Expand Up @@ -309,7 +320,7 @@ impl LaneSpec {
(Distance::feet(12.0), "normal"),
],
// https://nacto.org/publication/urban-street-design-guide/street-design-elements/lane-width/
LaneType::Parking => {
LaneType::Parking(_) => {
let mut choices = vec![
(NORMAL_LANE_THICKNESS, "full lane"),
(SERVICE_ROAD_LANE_THICKNESS, "alley"),
Expand Down Expand Up @@ -550,11 +561,12 @@ pub struct MapConfig {
/// If true, roads without explicitly tagged sidewalks may be assigned sidewalks or shoulders.
/// If false, no inference will occur and separate sidewalks and crossings will be included.
pub inferred_sidewalks: bool,
/// Street parking is divided into spots of this length. 8 meters is a reasonable default, but
/// people in some regions might be more accustomed to squeezing into smaller spaces. This
/// value can be smaller than the hardcoded maximum car length; cars may render on top of each
/// other, but otherwise the simulation doesn't care.
pub street_parking_spot_length: Distance,
/// Parallel street parking is divided into spots of this length. 8 meters is a reasonable
/// default, but people in some regions might be more accustomed to squeezing into smaller
/// spaces.
pub parallel_street_parking_spot_length: Distance,
/// For diagonal and perpendicular parking spots
pub vehicle_width_for_parking_spots: Distance,
/// If true, turns on red which do not conflict crossing traffic ('right on red') are allowed
pub turn_on_red: bool,
/// OSM railway=rail will be included as light rail if so. Cosmetic only.
Expand All @@ -571,7 +583,8 @@ impl MapConfig {
country_code: String::new(),
bikes_can_use_bus_lanes: true,
inferred_sidewalks: false,
street_parking_spot_length: Distance::meters(8.0),
parallel_street_parking_spot_length: Distance::meters(8.0),
vehicle_width_for_parking_spots: Distance::meters(3.0),
turn_on_red: true,
include_railroads: true,
inferred_kerbs: true,
Expand Down
2 changes: 1 addition & 1 deletion osm2streets/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ pub use self::types::NamePerLanguage;
// Re-export osm2lanes types for an easier refactor. TODO Stop doing this.
pub use osm2lanes::{
get_lane_specs_ltr, osm, BufferType, Direction, DrivingSide, LaneSpec, LaneType, MapConfig,
Placement, NORMAL_LANE_THICKNESS, SIDEWALK_THICKNESS,
ParkingType, Placement, NORMAL_LANE_THICKNESS, SIDEWALK_THICKNESS,
};

mod block;
Expand Down
Loading

0 comments on commit eba8b28

Please sign in to comment.