Begin a radical simplification of the LTN tool's color scheme, based on

generous advice from Duncan Geere.   #911

- Remove most color from the basemap, mimicking Mapbox light
- Stop drawing cells as colored areas. Just draw the thick boundary
  between adjacent cells, showing that they're separated.

The previous behavior with colored cell areas is still available as an
advanced option, but disabled by default.
This commit is contained in:
Dustin Carlino 2022-07-10 16:48:28 +01:00
parent 602653d934
commit 624a7b0d58
7 changed files with 78 additions and 38 deletions

View File

@ -187,7 +187,7 @@ fn make_world(ctx: &mut EventCtx, app: &App, timer: &mut Timer) -> World<Neighbo
// tried greying out everything else, but then the view is too jumpy.
let neighbourhood = Neighbourhood::new(ctx, app, *id);
let render_cells = crate::draw_cells::RenderCells::new(map, &neighbourhood);
let hovered_batch = render_cells.draw();
let hovered_batch = render_cells.draw_colored_areas();
world
.add(*id)
.hitbox(info.block.polygon.clone())

View File

@ -15,6 +15,7 @@ impl About {
]),
Text::from_multiline(vec![
Line("Created by Dustin Carlino, Cindy Huang, and Jennifer Ding"),
Line("with major design advice from Duncan Geere"),
Line("Developed at the Alan Turing Institute"),
Line("Data from OpenStreetMap"),
Line("See below for full credits and more info"),

View File

@ -240,37 +240,24 @@ fn setup_editing(
let render_cells = RenderCells::new(map, neighbourhood);
if app.session.draw_cells_as_areas {
edit.world.draw_master_batch(ctx, render_cells.draw());
let mut colorer = ColorNetwork::no_fading(app);
colorer.ranked_roads(shortcuts.count_per_road.clone(), &app.cs.good_to_bad_red);
// TODO These two will be on different scales, which'll look really weird!
colorer.ranked_intersections(
shortcuts.count_per_intersection.clone(),
&app.cs.good_to_bad_red,
);
draw_top_layer.append(colorer.draw);
edit.world
.draw_master_batch(ctx, render_cells.draw_colored_areas());
} else {
for (idx, cell) in neighbourhood.cells.iter().enumerate() {
let color = render_cells.colors[idx].alpha(0.9);
for (r, interval) in &cell.roads {
let road = map.get_r(*r);
draw_top_layer = draw_top_layer.push(
color,
road.center_pts
.exact_slice(interval.start, interval.end)
.make_polygons(road.get_width()),
);
}
for i in
map_gui::tools::intersections_from_roads(&cell.roads.keys().cloned().collect(), map)
{
draw_top_layer = draw_top_layer.push(color, map.get_i(i).polygon.clone());
}
}
draw_top_layer
.unzoomed
.append(render_cells.draw_island_outlines());
}
let mut colorer = ColorNetwork::no_fading(app);
colorer.ranked_roads(shortcuts.count_per_road.clone(), &app.cs.good_to_bad_red);
// TODO These two will be on different scales, which'll look really weird!
colorer.ranked_intersections(
shortcuts.count_per_intersection.clone(),
&app.cs.good_to_bad_red,
);
draw_top_layer.append(colorer.draw);
// Draw the borders of each cell
for (idx, cell) in neighbourhood.cells.iter().enumerate() {
let color = render_cells.colors[idx];
@ -317,7 +304,11 @@ fn setup_editing(
PolyLine::must_new(vec![pt_closer, pt_farther])
.make_double_arrow(thickness, ArrowCap::Triangle)
};
draw_top_layer = draw_top_layer.push(color.alpha(1.0), arrow);
if app.session.draw_cells_as_areas {
draw_top_layer = draw_top_layer.push(color.alpha(1.0), arrow);
} else {
draw_top_layer = draw_top_layer.push(Color::BLACK, arrow);
}
}
}
}

View File

@ -1,6 +1,6 @@
use std::collections::{HashSet, VecDeque};
use geom::{Bounds, Distance, Polygon};
use geom::{Bounds, Distance, PolyLine, Polygon};
use map_gui::tools::Grid;
use map_model::Map;
use widgetry::{Color, GeomBatch};
@ -13,6 +13,8 @@ pub struct RenderCells {
pub polygons_per_cell: Vec<Vec<Polygon>>,
/// Colors per cell, such that adjacent cells are colored differently
pub colors: Vec<Color>,
boundary_polygon: Polygon,
}
struct RenderCellsBuilder {
@ -34,7 +36,9 @@ impl RenderCells {
RenderCellsBuilder::new(map, neighbourhood).finalize()
}
pub fn draw(&self) -> GeomBatch {
/// Draw cells as areas with different colors. The colors are meaningless, but the same color
/// won't be shared between adjacent cells.
pub fn draw_colored_areas(&self) -> GeomBatch {
let mut batch = GeomBatch::new();
for (color, polygons) in self.colors.iter().zip(self.polygons_per_cell.iter()) {
for poly in polygons {
@ -44,6 +48,38 @@ impl RenderCells {
batch
}
/// Draw the boundary between cells as a thick outline. It's meant to look like the
/// neighbourhood is split into disconnected islands.
pub fn draw_island_outlines(&self) -> GeomBatch {
let neighbourhood_boundary = self
.boundary_polygon
.to_outline(Distance::meters(25.0))
.ok();
let mut batch = GeomBatch::new();
for (cell_color, polygons) in self.colors.iter().zip(self.polygons_per_cell.iter()) {
for poly in polygons {
// If the cell is disconnected, keep drawing this as an area to point out the
// problem
if *cell_color == colors::DISCONNECTED_CELL {
batch.push(*cell_color, poly.clone());
continue;
}
let boundary = PolyLine::unchecked_new(poly.clone().into_points())
.make_polygons(Distance::meters(10.0));
// If possible, try to erase where the cell boundary touches the perimeter road.
if let Some(ref neighbourhood_boundary) = neighbourhood_boundary {
batch.extend(Color::BLACK, boundary.difference(neighbourhood_boundary));
} else {
batch.push(Color::BLACK, boundary);
}
}
}
batch
}
/// Per cell, convert all polygons to a `geo::MultiPolygon`. Leave the coordinate system as map-space.
pub fn to_multipolygons(&self) -> Vec<geo::MultiPolygon> {
self.polygons_per_cell
@ -156,6 +192,7 @@ impl RenderCellsBuilder {
let mut result = RenderCells {
polygons_per_cell: Vec::new(),
colors: Vec::new(),
boundary_polygon: self.boundary_polygon,
};
for (idx, color) in self.colors.into_iter().enumerate() {
@ -206,7 +243,7 @@ impl RenderCellsBuilder {
// can just clip the result.
let mut clipped = Vec::new();
for p in cell_polygons {
clipped.extend(p.intersection(&self.boundary_polygon));
clipped.extend(p.intersection(&result.boundary_polygon));
}
result.polygons_per_cell.push(clipped);

View File

@ -88,7 +88,7 @@ fn run(mut settings: Settings) {
highlight_boundary_roads: false,
draw_neighbourhood_style: browse::Style::SimpleColoring,
draw_cells_as_areas: true,
draw_cells_as_areas: false,
heuristic: filters::auto::Heuristic::SplitCells,
main_road_penalty: 1.0,

View File

@ -355,6 +355,10 @@ impl Polygon {
from_multi(self.to_geo().intersection(&other.to_geo()))
}
pub fn difference(&self, other: &Polygon) -> Vec<Polygon> {
from_multi(self.to_geo().difference(&other.to_geo()))
}
pub fn convex_hull(list: Vec<Polygon>) -> Polygon {
let mp: geo::MultiPolygon = list.into_iter().map(|p| p.to_geo()).collect();
mp.convex_hull().into()

View File

@ -360,12 +360,19 @@ impl ColorScheme {
fn ltn() -> ColorScheme {
let mut cs = ColorScheme::day_mode();
cs.scheme = ColorSchemeChoice::LTN;
cs.experiment = true;
cs.private_road = None;
cs.fade_map_dark = Color::BLACK.alpha(0.3);
// The colors of cells / neighborhoods will show through these, de-emphasizing them
cs.parking_lot = Color::BLACK.alpha(0.2);
cs.residential_building = Color::BLACK.alpha(0.3);
cs.commercial_building = Color::BLACK.alpha(0.5);
// Based on Mapbox light scheme: https://www.mapbox.com/maps/light
cs.map_background = hex("#F6F6F4").into();
cs.residential_building = hex("#E9E9E7");
cs.commercial_building = hex("#D1D1CC");
cs.water = hex("#CAD2D3").into();
cs.grass = hex("#ECEEED").into();
cs.unzoomed_highway = Color::WHITE;
cs.unzoomed_arterial = Color::WHITE;
cs.unzoomed_residential = Color::WHITE;
cs.gui_style.panel_bg = Color::WHITE;
cs.panel_bg = cs.gui_style.panel_bg;