mirror of
https://github.com/a-b-street/abstreet.git
synced 2024-12-24 15:02:59 +03:00
Iterate on the curb rendering for #715. A simple start to it already happens to exist for an old color scheme experiment.
Still some issues with shoulders, but improved in many cases.
This commit is contained in:
parent
8eeee4cb8e
commit
835e4bf7a7
@ -195,6 +195,12 @@ impl ops::Mul<Distance> for f64 {
|
||||
}
|
||||
}
|
||||
|
||||
impl ops::MulAssign<f64> for Distance {
|
||||
fn mul_assign(&mut self, other: f64) {
|
||||
*self = *self * other;
|
||||
}
|
||||
}
|
||||
|
||||
impl ops::Div<Distance> for Distance {
|
||||
type Output = f64;
|
||||
|
||||
|
@ -408,6 +408,11 @@ impl PolyLine {
|
||||
self.shift_left(width).unwrap()
|
||||
}
|
||||
|
||||
/// Perpendicularly shifts the polyline to the right if positive or left if negative.
|
||||
pub fn shift_either_direction(&self, width: Distance) -> Result<PolyLine> {
|
||||
self.shift_with_corrections(width)
|
||||
}
|
||||
|
||||
// Things to remember about shifting polylines:
|
||||
// - the length before and after probably don't match up
|
||||
// - the number of points may not match
|
||||
|
@ -71,6 +71,7 @@ pub struct ColorScheme {
|
||||
pub sidewalk_lines: Option<Color>,
|
||||
general_road_marking: Color,
|
||||
road_center_line: Color,
|
||||
pub curb: Color,
|
||||
pub light_rail_track: Color,
|
||||
pub private_road: Color,
|
||||
unzoomed_highway: Color,
|
||||
@ -197,6 +198,7 @@ impl ColorScheme {
|
||||
sidewalk_lines: Some(Color::grey(0.7)),
|
||||
general_road_marking: Color::WHITE,
|
||||
road_center_line: Color::YELLOW,
|
||||
curb: hex("#666666"),
|
||||
light_rail_track: hex("#844204"),
|
||||
private_road: hex("#F0B0C0"),
|
||||
unzoomed_highway: hex("#E892A2"),
|
||||
|
@ -112,6 +112,7 @@ impl Options {
|
||||
options.push(c.label.clone());
|
||||
if c.label == x {
|
||||
self.color_scheme = c.data;
|
||||
self.toggle_day_night_colors = false;
|
||||
ok = true;
|
||||
break;
|
||||
}
|
||||
|
@ -46,13 +46,12 @@ impl DrawIntersection {
|
||||
},
|
||||
i.polygon.clone(),
|
||||
);
|
||||
if app.cs().sidewalk_lines.is_some() {
|
||||
default_geom.extend(
|
||||
app.cs().zoomed_road_surface(LaneType::Sidewalk, rank),
|
||||
calculate_corners(i, map),
|
||||
);
|
||||
} else {
|
||||
calculate_corners_with_borders(&mut default_geom, app, i);
|
||||
default_geom.extend(
|
||||
app.cs().zoomed_road_surface(LaneType::Sidewalk, rank),
|
||||
calculate_corners(i, map),
|
||||
);
|
||||
if app.cs().sidewalk_lines.is_none() {
|
||||
default_geom.extend(app.cs().curb, calculate_corner_curbs(i, map));
|
||||
}
|
||||
|
||||
for turn in map.get_turns_in_intersection(i.id) {
|
||||
@ -279,40 +278,73 @@ pub fn calculate_corners(i: &Intersection, map: &Map) -> Vec<Polygon> {
|
||||
corners
|
||||
}
|
||||
|
||||
// calculate_corners smooths edges, but we don't want to do that when drawing explicit borders.
|
||||
fn calculate_corners_with_borders(batch: &mut GeomBatch, app: &dyn AppLike, i: &Intersection) {
|
||||
let map = app.map();
|
||||
let rank = i.get_rank(map);
|
||||
let surface_color = app.cs().zoomed_road_surface(LaneType::Sidewalk, rank);
|
||||
let border_color = app.cs().general_road_marking(rank);
|
||||
fn calculate_corner_curbs(i: &Intersection, map: &Map) -> Vec<Polygon> {
|
||||
if i.is_footway(map) {
|
||||
return Vec::new();
|
||||
}
|
||||
|
||||
let mut curbs = Vec::new();
|
||||
|
||||
let thickness = Distance::meters(0.2);
|
||||
let shift = |width| (width - thickness) / 2.0;
|
||||
|
||||
for turn in map.get_turns_in_intersection(i.id) {
|
||||
if turn.turn_type != TurnType::SharedSidewalkCorner {
|
||||
continue;
|
||||
}
|
||||
// Avoid double-rendering
|
||||
if map.get_l(turn.id.src).dst_i != i.id {
|
||||
continue;
|
||||
}
|
||||
let width = map
|
||||
.get_l(turn.id.src)
|
||||
.width
|
||||
.min(map.get_l(turn.id.dst).width);
|
||||
if turn.turn_type == TurnType::SharedSidewalkCorner {
|
||||
// Avoid double-rendering
|
||||
if map.get_l(turn.id.src).dst_i != i.id {
|
||||
continue;
|
||||
}
|
||||
let l1 = map.get_l(turn.id.src);
|
||||
let l2 = map.get_l(turn.id.dst);
|
||||
|
||||
// TODO This leaves gaps.
|
||||
batch.push(surface_color, turn.geom.make_polygons(width));
|
||||
// Special case for dead-ends: just thicken the geometry.
|
||||
/*if i.roads.len() == 1 {
|
||||
corners.push(turn.geom.make_polygons(l1.width.min(l2.width)));
|
||||
continue;
|
||||
}*/
|
||||
|
||||
let thickness = Distance::meters(0.2);
|
||||
let shift = (width - thickness) / 2.0;
|
||||
batch.push(
|
||||
border_color,
|
||||
turn.geom.must_shift_right(shift).make_polygons(thickness),
|
||||
);
|
||||
batch.push(
|
||||
border_color,
|
||||
turn.geom.must_shift_left(shift).make_polygons(thickness),
|
||||
);
|
||||
if l1.width == l2.width {
|
||||
// When two sidewalks or two shoulders meet, use the turn geometry to create some
|
||||
// nice rounding.
|
||||
let mut width = shift(l1.width);
|
||||
if map.get_config().driving_side == DrivingSide::Right {
|
||||
width *= -1.0;
|
||||
}
|
||||
|
||||
if let Some(pl) = (|| {
|
||||
let mut pts = turn.geom.shift_either_direction(width).ok()?.into_points();
|
||||
let first_line = l2.first_line().shift_either_direction(width);
|
||||
pts.push(first_line.pt1());
|
||||
pts.push(first_line.unbounded_dist_along(thickness));
|
||||
let last_line = l1.last_line().shift_either_direction(width).reverse();
|
||||
pts.insert(0, last_line.pt1());
|
||||
pts.insert(0, last_line.unbounded_dist_along(thickness));
|
||||
PolyLine::deduping_new(pts).ok()
|
||||
})() {
|
||||
curbs.push(pl.make_polygons(thickness));
|
||||
}
|
||||
} else {
|
||||
// When a sidewalk and a shoulder meet, use a simpler shape to connect them.
|
||||
let direction = if map.get_config().driving_side == DrivingSide::Right {
|
||||
-1.0
|
||||
} else {
|
||||
1.0
|
||||
};
|
||||
if let Ok(pl) = PolyLine::new(vec![
|
||||
l1.last_line()
|
||||
.shift_either_direction(direction * shift(l1.width))
|
||||
.pt2(),
|
||||
l2.first_line()
|
||||
.shift_either_direction(direction * shift(l2.width))
|
||||
.pt1(),
|
||||
]) {
|
||||
curbs.push(pl.make_polygons(thickness));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
curbs
|
||||
}
|
||||
|
||||
// TODO This assumes the lanes change direction only at one point. A two-way cycletrack right at
|
||||
|
@ -48,19 +48,17 @@ impl DrawLane {
|
||||
if let Some(c) = app.cs().sidewalk_lines {
|
||||
batch.extend(c, calculate_sidewalk_lines(lane));
|
||||
} else {
|
||||
// Otherwise, draw a border at both edges
|
||||
// Create a sense of depth at the curb
|
||||
let width = Distance::meters(0.2);
|
||||
let shift = (lane.width - width) / 2.0;
|
||||
let mut shift = (lane.width - width) / 2.0;
|
||||
if map.get_config().driving_side == DrivingSide::Right {
|
||||
shift *= -1.0;
|
||||
}
|
||||
batch.push(
|
||||
general_road_marking,
|
||||
app.cs().curb,
|
||||
lane.lane_center_pts
|
||||
.must_shift_right(shift)
|
||||
.make_polygons(width),
|
||||
);
|
||||
batch.push(
|
||||
general_road_marking,
|
||||
lane.lane_center_pts
|
||||
.must_shift_left(shift)
|
||||
.shift_either_direction(shift)
|
||||
.unwrap()
|
||||
.make_polygons(width),
|
||||
);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user