Allow colorschemes to optionally color zoomed-in lanes based on OSM road rank. Most schemes don't do this, but one needs to, and maintaining a separate git branch has become annoying.

Should have no behavioral change to existing color schemes.
This commit is contained in:
Dustin Carlino 2020-10-02 08:06:35 -07:00
parent f73d9da080
commit 5aee85f19d
9 changed files with 107 additions and 48 deletions

View File

@ -1,5 +1,7 @@
use crate::common::ColorScale;
use crate::helpers::loading_tips;
use map_model::osm::RoadRank;
use map_model::LaneType;
use widgetry::{Choice, Color, Fill, Style, Texture};
// I've gone back and forth how to organize color scheme code. I was previously against having one
@ -25,6 +27,7 @@ pub enum ColorSchemeChoice {
Textured,
MapboxLight,
MapboxDark,
FadedZoom,
}
impl ColorSchemeChoice {
@ -40,11 +43,14 @@ impl ColorSchemeChoice {
Choice::new("textured", ColorSchemeChoice::Textured),
Choice::new("mapbox light", ColorSchemeChoice::MapboxLight),
Choice::new("mapbox dark", ColorSchemeChoice::MapboxDark),
Choice::new("faded zoom", ColorSchemeChoice::FadedZoom),
]
}
}
pub struct ColorScheme {
scheme: ColorSchemeChoice,
// UI
pub hovering: Color,
pub panel_bg: Color,
@ -62,19 +68,19 @@ pub struct ColorScheme {
pub dialog_bg: Color,
// Roads
pub driving_lane: Color,
pub bus_lane: Color,
pub parking_lane: Color,
pub bike_lane: Color,
pub sidewalk: Color,
driving_lane: Color,
bus_lane: Color,
parking_lane: Color,
bike_lane: Color,
sidewalk: Color,
pub sidewalk_lines: Color,
pub general_road_marking: Color,
pub road_center_line: Color,
pub light_rail_track: Color,
pub private_road: Color,
pub unzoomed_highway: Color,
pub unzoomed_arterial: Color,
pub unzoomed_residential: Color,
unzoomed_highway: Color,
unzoomed_arterial: Color,
unzoomed_residential: Color,
// Intersections
pub normal_intersection: Color,
@ -127,13 +133,15 @@ pub struct ColorScheme {
// Misc
pub parking_trip: Color,
pub bike_trip: Color,
pub bus_trip: Color,
pub before_changes: Color,
pub after_changes: Color,
}
impl ColorScheme {
pub fn new(scheme: ColorSchemeChoice) -> ColorScheme {
match scheme {
let mut cs = match scheme {
ColorSchemeChoice::Standard => ColorScheme::standard(),
ColorSchemeChoice::NightMode => ColorScheme::night_mode(),
ColorSchemeChoice::SAMGreenDay => ColorScheme::sam_green_day(),
@ -144,13 +152,18 @@ impl ColorScheme {
ColorSchemeChoice::Textured => ColorScheme::textured(),
ColorSchemeChoice::MapboxLight => ColorScheme::mapbox_light(),
ColorSchemeChoice::MapboxDark => ColorScheme::mapbox_dark(),
}
ColorSchemeChoice::FadedZoom => ColorScheme::faded_zoom(),
};
cs.scheme = scheme;
cs
}
fn standard() -> ColorScheme {
let mut gui_style = Style::standard();
gui_style.loading_tips = loading_tips();
ColorScheme {
scheme: ColorSchemeChoice::Standard,
// UI
hovering: gui_style.hovering_color,
panel_bg: gui_style.panel_bg,
@ -239,6 +252,8 @@ impl ColorScheme {
// Misc
parking_trip: hex("#4E30A6"),
bike_trip: Color::rgb(15, 125, 75),
bus_trip: Color::rgb(190, 74, 76),
before_changes: Color::BLUE,
after_changes: Color::RED,
}
@ -260,6 +275,40 @@ impl ColorScheme {
pub fn rotating_color_agents(&self, idx: usize) -> Color {
modulo_color(&self.agent_colors, idx)
}
pub fn unzoomed_road_surface(&self, rank: RoadRank) -> Color {
match rank {
RoadRank::Highway => self.unzoomed_highway,
RoadRank::Arterial => self.unzoomed_arterial,
RoadRank::Local => self.unzoomed_residential,
}
}
pub fn zoomed_road_surface(&self, lane: LaneType, rank: RoadRank) -> Color {
match self.scheme {
ColorSchemeChoice::FadedZoom => match rank {
RoadRank::Highway => hex("#BEB2C0"),
RoadRank::Arterial => hex("#B6BDC5"),
RoadRank::Local => hex("#C6CDD5"),
},
_ => match lane {
LaneType::Driving => self.driving_lane,
LaneType::Bus => self.bus_lane,
LaneType::Parking => self.parking_lane,
LaneType::Sidewalk | LaneType::Shoulder => self.sidewalk,
LaneType::Biking => self.bike_lane,
LaneType::SharedLeftTurn => self.driving_lane,
LaneType::Construction => self.parking_lane,
LaneType::LightRail => unreachable!(),
},
}
}
pub fn zoomed_intersection_surface(&self, rank: RoadRank) -> Color {
match self.scheme {
ColorSchemeChoice::FadedZoom => self.zoomed_road_surface(LaneType::Driving, rank),
_ => self.normal_intersection,
}
}
}
fn modulo_color(colors: &Vec<Color>, idx: usize) -> Color {
@ -395,6 +444,7 @@ impl ColorScheme {
cs.residential_building = hex("#2C2C2B").into();
cs.commerical_building = hex("#2C2C2B").into();
// TODO Things like this could be refactored in zoomed_road_surface
cs.driving_lane = road;
cs.parking_lane = road;
cs.bike_lane = road;
@ -408,4 +458,9 @@ impl ColorScheme {
cs
}
fn faded_zoom() -> ColorScheme {
let cs = ColorScheme::standard();
cs
}
}

View File

@ -135,7 +135,7 @@ pub fn color_for_agent_type(app: &App, a: AgentType) -> Color {
AgentType::Pedestrian => app.cs.unzoomed_pedestrian,
AgentType::Bike => app.cs.unzoomed_bike,
AgentType::Bus | AgentType::Train => app.cs.unzoomed_bus,
AgentType::TransitRider => app.cs.bus_lane,
AgentType::TransitRider => app.cs.bus_trip,
AgentType::Car => app.cs.unzoomed_car,
}
}
@ -144,10 +144,10 @@ pub fn color_for_trip_phase(app: &App, tpt: TripPhaseType) -> Color {
match tpt {
TripPhaseType::Driving => app.cs.unzoomed_car,
TripPhaseType::Walking => app.cs.unzoomed_pedestrian,
TripPhaseType::Biking => app.cs.bike_lane,
TripPhaseType::Biking => app.cs.bike_trip,
TripPhaseType::Parking => app.cs.parking_trip,
TripPhaseType::WaitingForBus(_, _) => app.cs.bus_layer,
TripPhaseType::RidingBus(_, _, _) => app.cs.bus_lane,
TripPhaseType::RidingBus(_, _, _) => app.cs.bus_trip,
TripPhaseType::Aborted | TripPhaseType::Finished => unreachable!(),
TripPhaseType::DelayedStart => Color::YELLOW,
TripPhaseType::Remote => Color::PINK,

View File

@ -4,7 +4,7 @@ use crate::helpers::ID;
use crate::options::{CameraAngle, Options};
use crate::render::{DrawOptions, Renderable, OUTLINE_THICKNESS};
use geom::{Angle, Distance, Line, Polygon, Pt2D, Ring};
use map_model::{Building, BuildingID, Map, OffstreetParking, NORMAL_LANE_THICKNESS};
use map_model::{Building, BuildingID, LaneType, Map, OffstreetParking, NORMAL_LANE_THICKNESS};
use std::cell::RefCell;
use widgetry::{Color, Drawable, EventCtx, GeomBatch, GfxCtx, Line, Text};
@ -188,7 +188,13 @@ impl DrawBuilding {
}
}
}
paths_batch.push(cs.sidewalk, driveway.make_polygons(NORMAL_LANE_THICKNESS));
paths_batch.push(
cs.zoomed_road_surface(
LaneType::Sidewalk,
map.get_parent(bldg.sidewalk()).get_rank(),
),
driveway.make_polygons(NORMAL_LANE_THICKNESS),
);
DrawBuilding {
id: bldg.id,

View File

@ -6,7 +6,7 @@ use crate::render::{
};
use geom::{Angle, ArrowCap, Distance, Line, PolyLine, Polygon, Pt2D, Ring, Time, EPSILON_DIST};
use map_model::{
Direction, DrivingSide, Intersection, IntersectionID, IntersectionType, Map, Road,
Direction, DrivingSide, Intersection, IntersectionID, IntersectionType, LaneType, Map, Road,
RoadWithStopSign, Turn, TurnType, SIDEWALK_THICKNESS,
};
use std::cell::RefCell;
@ -41,8 +41,12 @@ impl DrawIntersection {
// Order matters... main polygon first, then sidewalk corners.
let mut default_geom = GeomBatch::new();
default_geom.push(app.cs.normal_intersection, i.polygon.clone());
default_geom.extend(app.cs.sidewalk, calculate_corners(i, map));
let rank = i.get_rank(map);
default_geom.push(app.cs.zoomed_intersection_surface(rank), i.polygon.clone());
default_geom.extend(
app.cs.zoomed_road_surface(LaneType::Sidewalk, rank),
calculate_corners(i, map),
);
for turn in map.get_turns_in_intersection(i.id) {
// Avoid double-rendering

View File

@ -39,16 +39,7 @@ impl DrawLane {
let mut draw = GeomBatch::new();
if !lane.is_light_rail() {
draw.push(
match lane.lane_type {
LaneType::Driving => app.cs.driving_lane,
LaneType::Bus => app.cs.bus_lane,
LaneType::Parking => app.cs.parking_lane,
LaneType::Sidewalk | LaneType::Shoulder => app.cs.sidewalk,
LaneType::Biking => app.cs.bike_lane,
LaneType::SharedLeftTurn => app.cs.driving_lane,
LaneType::Construction => app.cs.parking_lane,
LaneType::LightRail => unreachable!(),
},
app.cs.zoomed_road_surface(lane.lane_type, road.get_rank()),
self.polygon.clone(),
);
}

View File

@ -13,8 +13,8 @@ use aabb_quadtree::QuadTree;
use abstutil::Timer;
use geom::{Bounds, Circle, Distance, Polygon, Pt2D, Time};
use map_model::{
osm, AreaID, BuildingID, BusStopID, IntersectionID, LaneID, Map, ParkingLotID, RoadID,
Traversable, NORMAL_LANE_THICKNESS, SIDEWALK_THICKNESS,
AreaID, BuildingID, BusStopID, IntersectionID, LaneID, Map, ParkingLotID, RoadID, Traversable,
NORMAL_LANE_THICKNESS, SIDEWALK_THICKNESS,
};
use sim::{GetDrawAgents, UnzoomedAgent, VehicleType};
use std::borrow::Borrow;
@ -210,7 +210,7 @@ impl DrawMap {
} else if r.is_private() {
cs.private_road
} else {
rank_to_color(cs, r.get_rank())
cs.unzoomed_road_surface(r.get_rank())
},
));
}
@ -224,7 +224,7 @@ impl DrawMap {
} else if i.is_private(map) {
cs.private_road
} else {
rank_to_color(cs, i.get_rank(map))
cs.unzoomed_road_surface(i.get_rank(map))
}
} else {
cs.unzoomed_interesting_intersection
@ -522,11 +522,3 @@ impl UnzoomedAgents {
}
}
}
fn rank_to_color(cs: &ColorScheme, rank: osm::RoadRank) -> Color {
match rank {
osm::RoadRank::Highway => cs.unzoomed_highway,
osm::RoadRank::Arterial => cs.unzoomed_arterial,
osm::RoadRank::Local => cs.unzoomed_residential,
}
}

View File

@ -3,7 +3,9 @@ use crate::colors::ColorScheme;
use crate::helpers::ID;
use crate::render::{DrawOptions, Renderable, OUTLINE_THICKNESS};
use geom::{Distance, PolyLine, Polygon, Pt2D};
use map_model::{Map, ParkingLot, ParkingLotID, NORMAL_LANE_THICKNESS, PARKING_LOT_SPOT_LENGTH};
use map_model::{
osm, LaneType, Map, ParkingLot, ParkingLotID, NORMAL_LANE_THICKNESS, PARKING_LOT_SPOT_LENGTH,
};
use std::cell::RefCell;
use widgetry::{Drawable, EventCtx, GeomBatch, GfxCtx};
@ -23,7 +25,7 @@ impl DrawParkingLot {
for aisle in &lot.aisles {
let aisle_thickness = NORMAL_LANE_THICKNESS / 2.0;
unzoomed_batch.push(
cs.unzoomed_residential,
cs.unzoomed_road_surface(osm::RoadRank::Local),
PolyLine::unchecked_new(aisle.clone()).make_polygons(aisle_thickness),
);
}
@ -64,14 +66,21 @@ impl Renderable for DrawParkingLot {
// TODO This isn't getting clipped to the parking lot boundary properly, so just stick
// this on the lowest order for now.
batch.push(
app.cs.sidewalk,
app.cs.zoomed_road_surface(
LaneType::Sidewalk,
app.primary
.map
.get_parent(lot.sidewalk_pos.lane())
.get_rank(),
),
front_path_line.make_polygons(NORMAL_LANE_THICKNESS),
);
batch.push(app.cs.parking_lot, lot.polygon.clone());
for aisle in &lot.aisles {
let aisle_thickness = NORMAL_LANE_THICKNESS / 2.0;
batch.push(
app.cs.driving_lane,
app.cs
.zoomed_road_surface(LaneType::Driving, osm::RoadRank::Local),
PolyLine::unchecked_new(aisle.clone()).make_polygons(aisle_thickness),
);
}

View File

@ -2,7 +2,7 @@ use crate::app::App;
use crate::helpers::ID;
use crate::render::{DrawOptions, Renderable};
use geom::{Distance, Polygon, Pt2D};
use map_model::{Map, Road, RoadID};
use map_model::{LaneType, Map, Road, RoadID};
use std::cell::RefCell;
use widgetry::{Drawable, GeomBatch, GfxCtx, Line, Text};
@ -86,9 +86,11 @@ impl Renderable for DrawRoad {
app.cs.road_center_line
};
let bg = if r.is_private() {
app.cs.driving_lane.lerp(app.cs.private_road, 0.5)
app.cs
.zoomed_road_surface(LaneType::Driving, r.get_rank())
.lerp(app.cs.private_road, 0.5)
} else {
app.cs.driving_lane
app.cs.zoomed_road_surface(LaneType::Driving, r.get_rank())
};
if false {

View File

@ -30,7 +30,7 @@ pub const ENDPT_BACK: &str = "abst:endpt_back";
pub const INFERRED_PARKING: &str = "abst:parking_inferred";
pub const INFERRED_SIDEWALKS: &str = "abst:sidewalks_inferred";
#[derive(PartialEq, Eq, PartialOrd, Ord, Clone)]
#[derive(PartialEq, Eq, PartialOrd, Ord, Clone, Copy)]
pub enum RoadRank {
Local,
Arterial,