mirror of
https://github.com/a-b-street/abstreet.git
synced 2024-11-28 03:35:51 +03:00
more polyline work... get rid of Warn<>. extremely spammy and hasn't
been helpful in ages.
This commit is contained in:
parent
f8b8c501ae
commit
07ed1fec95
@ -2,7 +2,6 @@ mod cli;
|
||||
mod clone;
|
||||
mod collections;
|
||||
mod io;
|
||||
mod logs;
|
||||
mod random;
|
||||
mod time;
|
||||
|
||||
@ -19,7 +18,6 @@ pub use crate::io::{
|
||||
serialize_multimap, serialize_usize, serialized_size_bytes, slurp_file, to_json, write_binary,
|
||||
write_json, FileWithProgress,
|
||||
};
|
||||
pub use crate::logs::Warn;
|
||||
pub use crate::random::{fork_rng, WeightedUsizeChoice};
|
||||
pub use crate::time::{
|
||||
elapsed_seconds, prettyprint_usize, start_profiler, stop_profiler, MeasureMemory, Profiler,
|
||||
|
@ -1,81 +0,0 @@
|
||||
use crate::Timer;
|
||||
|
||||
//
|
||||
// - If it doesn't make sense to plumb Timer to a library call, return Warn<T>.
|
||||
// - If there's no Timer, plumb the Warn<T>.
|
||||
// - If a Timer is available and there's a Warn<T>, use get() or with_context().
|
||||
// - If a Timer is available and something goes wrong, directly call warn().
|
||||
// - DO NOT prefer plumbing the Warn<T> and accumulating context. It's usually too tedious. Check
|
||||
// out DrawIntersection for an example.
|
||||
pub struct Warn<T> {
|
||||
value: T,
|
||||
warnings: Vec<String>,
|
||||
}
|
||||
|
||||
impl<T> Warn<T> {
|
||||
pub fn ok(value: T) -> Warn<T> {
|
||||
Warn {
|
||||
value,
|
||||
warnings: Vec::new(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn warn(value: T, warning: String) -> Warn<T> {
|
||||
Warn {
|
||||
value,
|
||||
warnings: vec![warning],
|
||||
}
|
||||
}
|
||||
|
||||
pub fn warnings(value: T, warnings: Vec<String>) -> Warn<T> {
|
||||
Warn { value, warnings }
|
||||
}
|
||||
|
||||
pub fn unwrap(self) -> T {
|
||||
if !self.warnings.is_empty() {
|
||||
println!("{} warnings:", self.warnings.len());
|
||||
for line in self.warnings {
|
||||
println!("{}", line);
|
||||
}
|
||||
}
|
||||
self.value
|
||||
}
|
||||
|
||||
pub fn expect(self, context: String) -> T {
|
||||
if !self.warnings.is_empty() {
|
||||
println!("{} warnings ({}):", self.warnings.len(), context);
|
||||
for line in self.warnings {
|
||||
println!("{}", line);
|
||||
}
|
||||
}
|
||||
self.value
|
||||
}
|
||||
|
||||
pub fn get(self, timer: &mut Timer) -> T {
|
||||
// TODO Context from the current Timer phase, caller
|
||||
for line in self.warnings {
|
||||
timer.warn(line);
|
||||
}
|
||||
self.value
|
||||
}
|
||||
|
||||
pub fn with_context(self, timer: &mut Timer, context: String) -> T {
|
||||
for line in self.warnings {
|
||||
timer.warn(format!("{}: {}", context, line));
|
||||
}
|
||||
self.value
|
||||
}
|
||||
|
||||
pub fn map<O, F: Fn(T) -> O>(self, f: F) -> Warn<O> {
|
||||
Warn {
|
||||
value: f(self.value),
|
||||
warnings: self.warnings,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Warn<()> {
|
||||
pub fn empty_warnings(warnings: Vec<String>) -> Warn<()> {
|
||||
Warn::warnings((), warnings)
|
||||
}
|
||||
}
|
@ -136,7 +136,6 @@ fn use_parking_hints(map: &mut RawMap, path: String, timer: &mut Timer) {
|
||||
map.config
|
||||
.driving_side
|
||||
.right_shift(center.clone(), DIRECTED_ROAD_THICKNESS)
|
||||
.get(timer)
|
||||
.points(),
|
||||
);
|
||||
closest.add(
|
||||
@ -144,7 +143,6 @@ fn use_parking_hints(map: &mut RawMap, path: String, timer: &mut Timer) {
|
||||
map.config
|
||||
.driving_side
|
||||
.left_shift(center, DIRECTED_ROAD_THICKNESS)
|
||||
.get(timer)
|
||||
.points(),
|
||||
);
|
||||
}
|
||||
|
@ -133,10 +133,7 @@ impl<'a> GfxCtx<'a> {
|
||||
pub fn draw_arrow(&mut self, color: Color, thickness: Distance, line: &Line) {
|
||||
self.draw_polygon(
|
||||
color,
|
||||
&line
|
||||
.to_polyline()
|
||||
.make_arrow(thickness, ArrowCap::Triangle)
|
||||
.unwrap(),
|
||||
&line.to_polyline().make_arrow(thickness, ArrowCap::Triangle),
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -163,8 +163,7 @@ impl State for BlockMap {
|
||||
pl.make_arrow(
|
||||
Distance::meters(15.0) * pct,
|
||||
ArrowCap::Triangle,
|
||||
)
|
||||
.unwrap(),
|
||||
),
|
||||
);
|
||||
}
|
||||
} else {
|
||||
|
@ -239,13 +239,11 @@ impl ParkingMapper {
|
||||
batch.push(
|
||||
Color::GREEN,
|
||||
map.right_shift(r.center_pts.clone(), r.get_half_width(map))
|
||||
.unwrap()
|
||||
.make_polygons(thickness),
|
||||
);
|
||||
batch.push(
|
||||
Color::BLUE,
|
||||
map.left_shift(r.center_pts.clone(), r.get_half_width(map))
|
||||
.unwrap()
|
||||
.make_polygons(thickness),
|
||||
);
|
||||
}
|
||||
|
@ -81,8 +81,7 @@ impl State for ClusterTrafficSignalEditor {
|
||||
app.cs.selected,
|
||||
g.group
|
||||
.geom
|
||||
.make_arrow(BIG_ARROW_THICKNESS, ArrowCap::Triangle)
|
||||
.unwrap(),
|
||||
.make_arrow(BIG_ARROW_THICKNESS, ArrowCap::Triangle),
|
||||
);
|
||||
} else {
|
||||
batch.push(app.cs.signal_turn_block_bg, g.block.clone());
|
||||
|
@ -488,7 +488,6 @@ pub fn apply_map_edits(ctx: &mut EventCtx, app: &mut App, edits: MapEdits) {
|
||||
&app.primary.map,
|
||||
&app.cs,
|
||||
ctx.prerender,
|
||||
&mut timer,
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -318,15 +318,13 @@ impl State for TrafficSignalEditor {
|
||||
green.alpha(0.5),
|
||||
signal.turn_groups[&g.id]
|
||||
.geom
|
||||
.make_arrow(BIG_ARROW_THICKNESS, ArrowCap::Triangle)
|
||||
.unwrap(),
|
||||
.make_arrow(BIG_ARROW_THICKNESS, ArrowCap::Triangle),
|
||||
);
|
||||
batch.extend(
|
||||
green,
|
||||
signal.turn_groups[&g.id]
|
||||
.geom
|
||||
.make_arrow_outline(BIG_ARROW_THICKNESS, Distance::meters(0.1))
|
||||
.unwrap(),
|
||||
.make_arrow_outline(BIG_ARROW_THICKNESS, Distance::meters(0.1)),
|
||||
);
|
||||
green
|
||||
}
|
||||
@ -366,15 +364,13 @@ impl State for TrafficSignalEditor {
|
||||
red.alpha(0.5),
|
||||
signal.turn_groups[&g.id]
|
||||
.geom
|
||||
.make_arrow(BIG_ARROW_THICKNESS, ArrowCap::Triangle)
|
||||
.unwrap(),
|
||||
.make_arrow(BIG_ARROW_THICKNESS, ArrowCap::Triangle),
|
||||
);
|
||||
batch.extend(
|
||||
red,
|
||||
signal.turn_groups[&g.id]
|
||||
.geom
|
||||
.make_arrow_outline(BIG_ARROW_THICKNESS, Distance::meters(0.1))
|
||||
.unwrap(),
|
||||
.make_arrow_outline(BIG_ARROW_THICKNESS, Distance::meters(0.1)),
|
||||
);
|
||||
red
|
||||
}
|
||||
|
@ -153,8 +153,7 @@ pub fn current_demand(
|
||||
let percent = (demand as f64) / (total_demand as f64);
|
||||
batch.push(
|
||||
Color::hex("#A3A3A3"),
|
||||
pl.make_arrow(percent * Distance::meters(3.0), ArrowCap::Triangle)
|
||||
.unwrap(),
|
||||
pl.make_arrow(percent * Distance::meters(3.0), ArrowCap::Triangle),
|
||||
);
|
||||
txt_batch.append(
|
||||
Text::from(Line(prettyprint_usize(demand)).fg(Color::RED))
|
||||
|
@ -349,9 +349,7 @@ fn make_timeline(
|
||||
if let Ok(pl) =
|
||||
PolyLine::new(vec![Pt2D::from_gps(loc.gps, map.get_gps_bounds()), center])
|
||||
{
|
||||
let arrow = pl
|
||||
.make_arrow(Distance::meters(5.0), ArrowCap::Triangle)
|
||||
.unwrap();
|
||||
let arrow = pl.make_arrow(Distance::meters(5.0), ArrowCap::Triangle);
|
||||
details.unzoomed.push(Color::GREEN, arrow.clone());
|
||||
details.zoomed.push(Color::GREEN, arrow.clone());
|
||||
}
|
||||
@ -396,9 +394,7 @@ fn make_timeline(
|
||||
if let Ok(pl) =
|
||||
PolyLine::new(vec![center, Pt2D::from_gps(loc.gps, map.get_gps_bounds())])
|
||||
{
|
||||
let arrow = pl
|
||||
.make_arrow(Distance::meters(5.0), ArrowCap::Triangle)
|
||||
.unwrap();
|
||||
let arrow = pl.make_arrow(Distance::meters(5.0), ArrowCap::Triangle);
|
||||
details.unzoomed.push(Color::GREEN, arrow.clone());
|
||||
details.zoomed.push(Color::GREEN, arrow.clone());
|
||||
}
|
||||
|
@ -84,8 +84,7 @@ impl Elevation {
|
||||
pt.project_away(arrow_len / 2.0, angle.opposite()),
|
||||
pt.project_away(arrow_len / 2.0, angle),
|
||||
])
|
||||
.make_arrow(thickness, ArrowCap::Triangle)
|
||||
.unwrap(),
|
||||
.make_arrow(thickness, ArrowCap::Triangle),
|
||||
);
|
||||
dist += btwn;
|
||||
}
|
||||
|
@ -90,8 +90,7 @@ impl DrawBike {
|
||||
body_pos.project_away(body_radius / 2.0, angle.opposite()),
|
||||
body_pos.project_away(body_radius / 2.0, angle),
|
||||
])
|
||||
.make_arrow(Distance::meters(0.15), ArrowCap::Triangle)
|
||||
.unwrap(),
|
||||
.make_arrow(Distance::meters(0.15), ArrowCap::Triangle),
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -24,8 +24,8 @@ impl DrawCar {
|
||||
|
||||
// Wheels
|
||||
for side in vec![
|
||||
input.body.shift_right(CAR_WIDTH / 2.0).unwrap(),
|
||||
input.body.shift_left(CAR_WIDTH / 2.0).unwrap(),
|
||||
input.body.shift_right(CAR_WIDTH / 2.0),
|
||||
input.body.shift_left(CAR_WIDTH / 2.0),
|
||||
] {
|
||||
let len = side.length();
|
||||
if len <= Distance::meters(2.0) {
|
||||
@ -93,8 +93,7 @@ impl DrawCar {
|
||||
pos.project_away(arrow_len / 2.0, angle.rotate_degs(90.0)),
|
||||
pos.project_away(arrow_len / 2.0, angle.rotate_degs(-90.0)),
|
||||
])
|
||||
.make_arrow(arrow_thickness, ArrowCap::Triangle)
|
||||
.unwrap(),
|
||||
.make_arrow(arrow_thickness, ArrowCap::Triangle),
|
||||
);
|
||||
}
|
||||
TurnType::Right => {
|
||||
@ -109,8 +108,7 @@ impl DrawCar {
|
||||
pos.project_away(arrow_len / 2.0, angle.rotate_degs(-90.0)),
|
||||
pos.project_away(arrow_len / 2.0, angle.rotate_degs(90.0)),
|
||||
])
|
||||
.make_arrow(arrow_thickness, ArrowCap::Triangle)
|
||||
.unwrap(),
|
||||
.make_arrow(arrow_thickness, ArrowCap::Triangle),
|
||||
);
|
||||
}
|
||||
TurnType::Straight | TurnType::LaneChangeLeft | TurnType::LaneChangeRight => {}
|
||||
|
@ -5,7 +5,6 @@ use crate::options::TrafficSignalStyle;
|
||||
use crate::render::{
|
||||
draw_signal_phase, DrawOptions, Renderable, CROSSWALK_LINE_THICKNESS, OUTLINE_THICKNESS,
|
||||
};
|
||||
use abstutil::Timer;
|
||||
use ezgui::{Color, Drawable, GeomBatch, GfxCtx, Line, Prerender, RewriteColor, Text};
|
||||
use geom::{Angle, ArrowCap, Distance, Line, PolyLine, Polygon, Pt2D, Time, EPSILON_DIST};
|
||||
use map_model::{
|
||||
@ -28,7 +27,6 @@ impl DrawIntersection {
|
||||
map: &Map,
|
||||
cs: &ColorScheme,
|
||||
prerender: &Prerender,
|
||||
timer: &mut Timer,
|
||||
) -> DrawIntersection {
|
||||
// Order matters... main polygon first, then sidewalk corners.
|
||||
let mut default_geom = GeomBatch::new();
|
||||
@ -51,10 +49,7 @@ impl DrawIntersection {
|
||||
match i.intersection_type {
|
||||
IntersectionType::Border => {
|
||||
let r = map.get_r(*i.roads.iter().next().unwrap());
|
||||
default_geom.extend(
|
||||
cs.road_center_line,
|
||||
calculate_border_arrows(i, r, map, timer),
|
||||
);
|
||||
default_geom.extend(cs.road_center_line, calculate_border_arrows(i, r, map));
|
||||
}
|
||||
IntersectionType::StopSign => {
|
||||
for ss in map.get_stop_sign(i.id).roads.values() {
|
||||
@ -201,15 +196,11 @@ pub fn calculate_corners(i: &Intersection, map: &Map) -> Vec<Polygon> {
|
||||
let l1 = map.get_l(turn.id.src);
|
||||
let l2 = map.get_l(turn.id.dst);
|
||||
|
||||
let mut pts = map
|
||||
.left_shift(turn.geom.clone(), width / 2.0)
|
||||
.unwrap()
|
||||
.into_points();
|
||||
let mut pts = map.left_shift(turn.geom.clone(), width / 2.0).into_points();
|
||||
pts.push(map.left_shift_line(l2.first_line(), width / 2.0).pt1());
|
||||
pts.push(map.right_shift_line(l2.first_line(), width / 2.0).pt1());
|
||||
pts.extend(
|
||||
map.right_shift(turn.geom.clone(), width / 2.0)
|
||||
.unwrap()
|
||||
.reversed()
|
||||
.into_points(),
|
||||
);
|
||||
@ -223,12 +214,7 @@ pub fn calculate_corners(i: &Intersection, map: &Map) -> Vec<Polygon> {
|
||||
corners
|
||||
}
|
||||
|
||||
fn calculate_border_arrows(
|
||||
i: &Intersection,
|
||||
r: &Road,
|
||||
map: &Map,
|
||||
timer: &mut Timer,
|
||||
) -> Vec<Polygon> {
|
||||
fn calculate_border_arrows(i: &Intersection, r: &Road, map: &Map) -> Vec<Polygon> {
|
||||
let mut result = Vec::new();
|
||||
|
||||
let mut width_fwd = Distance::ZERO;
|
||||
@ -261,8 +247,7 @@ fn calculate_border_arrows(
|
||||
line.unbounded_dist_along(Distance::meters(-9.5)),
|
||||
line.unbounded_dist_along(Distance::meters(-0.5)),
|
||||
])
|
||||
.make_arrow(width / 3.0, ArrowCap::Triangle)
|
||||
.with_context(timer, format!("outgoing border arrows for {}", r.id)),
|
||||
.make_arrow(width / 3.0, ArrowCap::Triangle),
|
||||
);
|
||||
}
|
||||
|
||||
@ -285,8 +270,7 @@ fn calculate_border_arrows(
|
||||
line.unbounded_dist_along(Distance::meters(-0.5)),
|
||||
line.unbounded_dist_along(Distance::meters(-9.5)),
|
||||
])
|
||||
.make_arrow(width / 3.0, ArrowCap::Triangle)
|
||||
.with_context(timer, format!("incoming border arrows for {}", r.id)),
|
||||
.make_arrow(width / 3.0, ArrowCap::Triangle),
|
||||
);
|
||||
}
|
||||
|
||||
@ -399,14 +383,12 @@ fn make_rainbow_crosswalk(batch: &mut GeomBatch, turn: &Turn, map: &Map) -> bool
|
||||
let slice = turn
|
||||
.geom
|
||||
.exact_slice(total_width, turn.geom.length() - total_width)
|
||||
.shift_left(total_width / 2.0 - band_width / 2.0)
|
||||
.unwrap();
|
||||
.shift_left(total_width / 2.0 - band_width / 2.0);
|
||||
for (idx, color) in colors.into_iter().enumerate() {
|
||||
batch.push(
|
||||
color,
|
||||
slice
|
||||
.shift_right(band_width * (idx as f64))
|
||||
.unwrap()
|
||||
.make_polygons(band_width),
|
||||
);
|
||||
}
|
||||
|
@ -1,7 +1,6 @@
|
||||
use crate::app::App;
|
||||
use crate::helpers::ID;
|
||||
use crate::render::{DrawOptions, Renderable, OUTLINE_THICKNESS};
|
||||
use abstutil::Timer;
|
||||
use ezgui::{Drawable, GeomBatch, GfxCtx, RewriteColor};
|
||||
use geom::{Angle, ArrowCap, Distance, Line, PolyLine, Polygon, Pt2D};
|
||||
use map_model::{Lane, LaneID, LaneType, Map, Road, TurnType, PARKING_SPOT_LENGTH};
|
||||
@ -35,7 +34,6 @@ impl DrawLane {
|
||||
let road = map.get_r(lane.parent);
|
||||
|
||||
let mut draw = GeomBatch::new();
|
||||
let mut timer = Timer::throwaway();
|
||||
if !lane.is_light_rail() {
|
||||
draw.push(
|
||||
match lane.lane_type {
|
||||
@ -64,11 +62,11 @@ impl DrawLane {
|
||||
LaneType::Driving | LaneType::Bus => {
|
||||
draw.extend(
|
||||
app.cs.general_road_marking,
|
||||
calculate_driving_lines(map, lane, road, &mut timer),
|
||||
calculate_driving_lines(map, lane, road),
|
||||
);
|
||||
draw.extend(
|
||||
app.cs.general_road_marking,
|
||||
calculate_turn_markings(map, lane, &mut timer),
|
||||
calculate_turn_markings(map, lane),
|
||||
);
|
||||
draw.extend(
|
||||
app.cs.general_road_marking,
|
||||
@ -81,14 +79,12 @@ impl DrawLane {
|
||||
app.cs.road_center_line,
|
||||
lane.lane_center_pts
|
||||
.shift_right(lane.width / 2.0)
|
||||
.get(&mut timer)
|
||||
.make_polygons(Distance::meters(0.25)),
|
||||
);
|
||||
draw.push(
|
||||
app.cs.road_center_line,
|
||||
lane.lane_center_pts
|
||||
.shift_left(lane.width / 2.0)
|
||||
.get(&mut timer)
|
||||
.make_polygons(Distance::meters(0.25)),
|
||||
);
|
||||
}
|
||||
@ -99,14 +95,12 @@ impl DrawLane {
|
||||
app.cs.light_rail_track,
|
||||
lane.lane_center_pts
|
||||
.shift_right((lane.width - track_width) / 2.5)
|
||||
.get(&mut timer)
|
||||
.make_polygons(track_width),
|
||||
);
|
||||
draw.push(
|
||||
app.cs.light_rail_track,
|
||||
lane.lane_center_pts
|
||||
.shift_left((lane.width - track_width) / 2.5)
|
||||
.get(&mut timer)
|
||||
.make_polygons(track_width),
|
||||
);
|
||||
|
||||
@ -269,20 +263,13 @@ fn calculate_parking_lines(map: &Map, lane: &Lane) -> Vec<Polygon> {
|
||||
result
|
||||
}
|
||||
|
||||
fn calculate_driving_lines(
|
||||
map: &Map,
|
||||
lane: &Lane,
|
||||
parent: &Road,
|
||||
timer: &mut Timer,
|
||||
) -> Vec<Polygon> {
|
||||
fn calculate_driving_lines(map: &Map, lane: &Lane, parent: &Road) -> Vec<Polygon> {
|
||||
// The leftmost lanes don't have dashed lines.
|
||||
let (dir, idx) = parent.dir_and_offset(lane.id);
|
||||
if idx == 0 || (dir && parent.children_forwards[idx - 1].1 == LaneType::SharedLeftTurn) {
|
||||
return Vec::new();
|
||||
}
|
||||
let lane_edge_pts = map
|
||||
.left_shift(lane.lane_center_pts.clone(), lane.width / 2.0)
|
||||
.get(timer);
|
||||
let lane_edge_pts = map.left_shift(lane.lane_center_pts.clone(), lane.width / 2.0);
|
||||
lane_edge_pts.dashed_lines(
|
||||
Distance::meters(0.25),
|
||||
Distance::meters(1.0),
|
||||
@ -290,7 +277,7 @@ fn calculate_driving_lines(
|
||||
)
|
||||
}
|
||||
|
||||
fn calculate_turn_markings(map: &Map, lane: &Lane, timer: &mut Timer) -> Vec<Polygon> {
|
||||
fn calculate_turn_markings(map: &Map, lane: &Lane) -> Vec<Polygon> {
|
||||
let mut results = Vec::new();
|
||||
|
||||
// Are there multiple driving lanes on this side of the road?
|
||||
@ -325,8 +312,7 @@ fn calculate_turn_markings(map: &Map, lane: &Lane, timer: &mut Timer) -> Vec<Pol
|
||||
.last_pt()
|
||||
.project_away(lane.width / 2.0, turn.angle()),
|
||||
])
|
||||
.make_arrow(thickness, ArrowCap::Triangle)
|
||||
.with_context(timer, format!("turn_markings for {}", turn.id)),
|
||||
.make_arrow(thickness, ArrowCap::Triangle),
|
||||
);
|
||||
}
|
||||
|
||||
@ -361,8 +347,7 @@ fn calculate_one_way_markings(lane: &Lane, parent: &Road) -> Vec<Polygon> {
|
||||
pt.project_away(arrow_len / 2.0, angle.opposite()),
|
||||
pt.project_away(arrow_len / 2.0, angle),
|
||||
])
|
||||
.make_arrow(thickness, ArrowCap::Triangle)
|
||||
.unwrap(),
|
||||
.make_arrow(thickness, ArrowCap::Triangle),
|
||||
);
|
||||
dist += btwn;
|
||||
}
|
||||
|
@ -90,7 +90,7 @@ impl DrawMap {
|
||||
timer.start_iter("make DrawIntersections", map.all_intersections().len());
|
||||
for i in map.all_intersections() {
|
||||
timer.next();
|
||||
intersections.push(DrawIntersection::new(i, map, cs, ctx.prerender, timer));
|
||||
intersections.push(DrawIntersection::new(i, map, cs, ctx.prerender));
|
||||
}
|
||||
|
||||
timer.start("generate unzoomed intersections");
|
||||
|
@ -38,8 +38,7 @@ impl DrawPedestrian {
|
||||
input.pos.project_away(radius / 2.0, angle.opposite()),
|
||||
input.pos.project_away(radius / 2.0, angle),
|
||||
])
|
||||
.make_arrow(Distance::meters(0.15), ArrowCap::Triangle)
|
||||
.unwrap(),
|
||||
.make_arrow(Distance::meters(0.15), ArrowCap::Triangle),
|
||||
);
|
||||
}
|
||||
|
||||
@ -207,9 +206,9 @@ impl DrawPedCrowd {
|
||||
PedCrowdLocation::Sidewalk(on, contraflow) => {
|
||||
let pl_slice = on.exact_slice(input.low, input.high, map);
|
||||
if contraflow {
|
||||
map.left_shift(pl_slice, SIDEWALK_THICKNESS / 4.0).unwrap()
|
||||
map.left_shift(pl_slice, SIDEWALK_THICKNESS / 4.0)
|
||||
} else {
|
||||
map.right_shift(pl_slice, SIDEWALK_THICKNESS / 4.0).unwrap()
|
||||
map.right_shift(pl_slice, SIDEWALK_THICKNESS / 4.0)
|
||||
}
|
||||
}
|
||||
PedCrowdLocation::BldgFrontPath(b) => map
|
||||
|
@ -66,8 +66,7 @@ pub fn draw_signal_phase(
|
||||
app.cs.signal_protected_turn.alpha(percent)
|
||||
},
|
||||
pl.exact_slice(slice_start, pl.length() - slice_end)
|
||||
.make_arrow(BIG_ARROW_THICKNESS, ArrowCap::Triangle)
|
||||
.unwrap(),
|
||||
.make_arrow(BIG_ARROW_THICKNESS, ArrowCap::Triangle),
|
||||
);
|
||||
} else {
|
||||
let (center, angle) = crosswalk_icon(&signal.turn_groups[g].geom);
|
||||
@ -132,15 +131,13 @@ pub fn draw_signal_phase(
|
||||
app.cs.signal_permitted_turn.alpha(0.3),
|
||||
signal.turn_groups[g]
|
||||
.geom
|
||||
.make_arrow(BIG_ARROW_THICKNESS * 2.0, ArrowCap::Triangle)
|
||||
.unwrap(),
|
||||
.make_arrow(BIG_ARROW_THICKNESS * 2.0, ArrowCap::Triangle),
|
||||
);
|
||||
batch.extend(
|
||||
app.cs.signal_permitted_turn,
|
||||
signal.turn_groups[g]
|
||||
.geom
|
||||
.make_arrow_outline(BIG_ARROW_THICKNESS * 2.0, BIG_ARROW_THICKNESS / 2.0)
|
||||
.unwrap(),
|
||||
.make_arrow_outline(BIG_ARROW_THICKNESS * 2.0, BIG_ARROW_THICKNESS / 2.0),
|
||||
);
|
||||
}
|
||||
let mut dont_walk = BTreeSet::new();
|
||||
@ -155,8 +152,7 @@ pub fn draw_signal_phase(
|
||||
app.cs.signal_protected_turn,
|
||||
signal.turn_groups[g]
|
||||
.geom
|
||||
.make_arrow(BIG_ARROW_THICKNESS * 2.0, ArrowCap::Triangle)
|
||||
.unwrap(),
|
||||
.make_arrow(BIG_ARROW_THICKNESS * 2.0, ArrowCap::Triangle),
|
||||
);
|
||||
} else {
|
||||
let (center, angle) = crosswalk_icon(&signal.turn_groups[g].geom);
|
||||
@ -186,15 +182,13 @@ pub fn draw_signal_phase(
|
||||
app.cs.signal_permitted_turn.alpha(0.3),
|
||||
signal.turn_groups[g]
|
||||
.geom
|
||||
.make_arrow(BIG_ARROW_THICKNESS * 2.0, ArrowCap::Triangle)
|
||||
.unwrap(),
|
||||
.make_arrow(BIG_ARROW_THICKNESS * 2.0, ArrowCap::Triangle),
|
||||
);
|
||||
batch.extend(
|
||||
app.cs.signal_permitted_turn,
|
||||
signal.turn_groups[g]
|
||||
.geom
|
||||
.make_arrow_outline(BIG_ARROW_THICKNESS * 2.0, BIG_ARROW_THICKNESS / 2.0)
|
||||
.unwrap(),
|
||||
.make_arrow_outline(BIG_ARROW_THICKNESS * 2.0, BIG_ARROW_THICKNESS / 2.0),
|
||||
);
|
||||
}
|
||||
for g in &phase.protected_groups {
|
||||
@ -210,8 +204,7 @@ pub fn draw_signal_phase(
|
||||
app.cs.signal_protected_turn,
|
||||
signal.turn_groups[g]
|
||||
.geom
|
||||
.make_arrow(BIG_ARROW_THICKNESS * 2.0, ArrowCap::Triangle)
|
||||
.unwrap(),
|
||||
.make_arrow(BIG_ARROW_THICKNESS * 2.0, ArrowCap::Triangle),
|
||||
);
|
||||
}
|
||||
}
|
||||
@ -237,19 +230,16 @@ pub fn draw_signal_phase(
|
||||
batch.push(
|
||||
app.cs.signal_protected_turn,
|
||||
turn.geom
|
||||
.make_arrow(BIG_ARROW_THICKNESS * 2.0, ArrowCap::Triangle)
|
||||
.unwrap(),
|
||||
.make_arrow(BIG_ARROW_THICKNESS * 2.0, ArrowCap::Triangle),
|
||||
);
|
||||
}
|
||||
TurnPriority::Yield => {
|
||||
batch.extend(
|
||||
app.cs.signal_permitted_turn,
|
||||
turn.geom
|
||||
.make_arrow_outline(
|
||||
BIG_ARROW_THICKNESS * 2.0,
|
||||
BIG_ARROW_THICKNESS / 2.0,
|
||||
)
|
||||
.unwrap(),
|
||||
turn.geom.make_arrow_outline(
|
||||
BIG_ARROW_THICKNESS * 2.0,
|
||||
BIG_ARROW_THICKNESS / 2.0,
|
||||
),
|
||||
);
|
||||
}
|
||||
TurnPriority::Banned => {}
|
||||
|
@ -99,7 +99,6 @@ fn make_geom(offset: f64, pl: PolyLine, width: Distance, angle: Angle) -> (Polyg
|
||||
center.project_away(TURN_ICON_ARROW_LENGTH / 2.0, angle),
|
||||
])
|
||||
.make_arrow(Distance::meters(0.5), ArrowCap::Triangle)
|
||||
.unwrap()
|
||||
};
|
||||
|
||||
(block, arrow)
|
||||
|
@ -370,8 +370,7 @@ impl GameplayState for Tutorial {
|
||||
]) {
|
||||
g.draw_polygon(
|
||||
Color::RED,
|
||||
&pl.make_arrow(Distance::meters(20.0), ArrowCap::Triangle)
|
||||
.unwrap(),
|
||||
&pl.make_arrow(Distance::meters(20.0), ArrowCap::Triangle),
|
||||
);
|
||||
}
|
||||
g.unfork();
|
||||
|
@ -203,8 +203,7 @@ impl State for TurnExplorer {
|
||||
color_turn_type(turn.turn_type).alpha(0.5),
|
||||
&turn
|
||||
.geom
|
||||
.make_arrow(BIG_ARROW_THICKNESS, ArrowCap::Triangle)
|
||||
.unwrap(),
|
||||
.make_arrow(BIG_ARROW_THICKNESS, ArrowCap::Triangle),
|
||||
);
|
||||
}
|
||||
} else {
|
||||
@ -228,8 +227,7 @@ impl State for TurnExplorer {
|
||||
CURRENT_TURN,
|
||||
current
|
||||
.geom
|
||||
.make_arrow(BIG_ARROW_THICKNESS, ArrowCap::Triangle)
|
||||
.unwrap(),
|
||||
.make_arrow(BIG_ARROW_THICKNESS, ArrowCap::Triangle),
|
||||
);
|
||||
batch.draw(g);
|
||||
}
|
||||
|
@ -160,8 +160,7 @@ impl UberTurnViewer {
|
||||
Color::RED,
|
||||
ic.uber_turns[idx]
|
||||
.geom(&app.primary.map)
|
||||
.make_arrow(BIG_ARROW_THICKNESS, ArrowCap::Triangle)
|
||||
.unwrap(),
|
||||
.make_arrow(BIG_ARROW_THICKNESS, ArrowCap::Triangle),
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -1,7 +1,6 @@
|
||||
use crate::{
|
||||
Angle, Bounds, Distance, HashablePt2D, InfiniteLine, Line, Polygon, Pt2D, Ring, EPSILON_DIST,
|
||||
};
|
||||
use abstutil::Warn;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::collections::HashSet;
|
||||
use std::error::Error;
|
||||
@ -24,40 +23,6 @@ pub struct PolyLine {
|
||||
}
|
||||
|
||||
impl PolyLine {
|
||||
fn old_new(pts: Vec<Pt2D>) -> PolyLine {
|
||||
assert!(pts.len() >= 2);
|
||||
let length = pts.windows(2).fold(Distance::ZERO, |so_far, pair| {
|
||||
so_far + pair[0].dist_to(pair[1])
|
||||
});
|
||||
|
||||
// This checks no lines are too small. Could take the other approach and automatically
|
||||
// squish down points here and make sure the final result is at least EPSILON_DIST.
|
||||
// But probably better for the callers to do this -- they have better understanding of what
|
||||
// needs to be squished down, why, and how.
|
||||
if pts.windows(2).any(|pair| pair[0] == pair[1]) {
|
||||
panic!(
|
||||
"PL with total length {} and {} pts has ~dupe adjacent pts: {:?}",
|
||||
length,
|
||||
pts.len(),
|
||||
pts
|
||||
);
|
||||
}
|
||||
|
||||
let result = PolyLine { pts, length };
|
||||
|
||||
// Can't have duplicates! If the polyline ever crosses back on itself, all sorts of things
|
||||
// are broken.
|
||||
let (_, dupes) = to_set(result.points());
|
||||
if !dupes.is_empty() {
|
||||
panic!(
|
||||
"PolyLine has non-adjacent repeat points: {}\nRepeated points: {:?}",
|
||||
result, dupes
|
||||
);
|
||||
}
|
||||
|
||||
result
|
||||
}
|
||||
|
||||
pub fn new(pts: Vec<Pt2D>) -> Result<PolyLine, Box<dyn Error>> {
|
||||
if pts.len() < 2 {
|
||||
return Err(format!("Need at least two points for a PolyLine").into());
|
||||
@ -370,7 +335,6 @@ impl PolyLine {
|
||||
|
||||
pub fn middle(&self) -> Pt2D {
|
||||
// If this fails, must be some super tiny line. Just return the first point in that case.
|
||||
// TODO Use Warn<Pt2D>
|
||||
match self.dist_along(self.length() / 2.0) {
|
||||
Ok((pt, _)) => pt,
|
||||
Err(err) => {
|
||||
@ -397,29 +361,31 @@ impl PolyLine {
|
||||
Line::must_new(self.pts[self.pts.len() - 2], self.pts[self.pts.len() - 1])
|
||||
}
|
||||
|
||||
///////////////////////// TODO Keep cleaning up below
|
||||
|
||||
pub fn shift_right(&self, width: Distance) -> Warn<PolyLine> {
|
||||
pub fn shift_right(&self, width: Distance) -> PolyLine {
|
||||
self.shift_with_corrections(width)
|
||||
}
|
||||
|
||||
pub fn shift_left(&self, width: Distance) -> Warn<PolyLine> {
|
||||
pub fn shift_left(&self, width: Distance) -> 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 will match
|
||||
fn shift_with_corrections(&self, width: Distance) -> Warn<PolyLine> {
|
||||
let mut raw = self.shift_with_sharp_angles(width, MITER_THRESHOLD);
|
||||
raw.dedup();
|
||||
let result = PolyLine::old_new(raw);
|
||||
let fixed = if result.pts.len() == self.pts.len() {
|
||||
fix_angles(self, result)
|
||||
// - the number of points may not match
|
||||
fn shift_with_corrections(&self, width: Distance) -> PolyLine {
|
||||
let raw = self.shift_with_sharp_angles(width, MITER_THRESHOLD);
|
||||
let result = match PolyLine::deduping_new(raw) {
|
||||
Ok(pl) => pl,
|
||||
Err(err) => panic!("shifting by {} broke {}: {}", width, self, err),
|
||||
};
|
||||
if result.pts.len() == self.pts.len() {
|
||||
match fix_angles(self, result) {
|
||||
Ok(pl) => pl,
|
||||
Err(err) => panic!("shifting by {} broke {}: {}", width, self, err),
|
||||
}
|
||||
} else {
|
||||
result
|
||||
};
|
||||
check_angles(self, fixed)
|
||||
}
|
||||
}
|
||||
|
||||
fn shift_with_sharp_angles(&self, width: Distance, miter_threshold: f64) -> Vec<Pt2D> {
|
||||
@ -543,15 +509,13 @@ impl PolyLine {
|
||||
.exact_dashed_polygons(width, dash_len, dash_separation)
|
||||
}
|
||||
|
||||
pub fn make_arrow(&self, thickness: Distance, cap: ArrowCap) -> Warn<Polygon> {
|
||||
pub fn make_arrow(&self, thickness: Distance, cap: ArrowCap) -> Polygon {
|
||||
let head_size = thickness * 2.0;
|
||||
let triangle_height = head_size / 2.0_f64.sqrt();
|
||||
|
||||
if self.length() < triangle_height + EPSILON_DIST {
|
||||
return Warn::warn(
|
||||
self.make_polygons(thickness),
|
||||
format!("Can't make_arrow of thickness {} for {}", thickness, self),
|
||||
);
|
||||
// Just give up and make the thick line.
|
||||
return self.make_polygons(thickness);
|
||||
}
|
||||
let slice = self.exact_slice(Distance::ZERO, self.length() - triangle_height);
|
||||
let angle = slice.last_pt().angle_to(self.last_pt());
|
||||
@ -563,16 +527,14 @@ impl PolyLine {
|
||||
.project_away(head_size, angle.rotate_degs(135.0));
|
||||
|
||||
match cap {
|
||||
ArrowCap::Triangle => {
|
||||
Warn::ok(slice.make_polygons(thickness).union(Polygon::new(&vec![
|
||||
self.last_pt(),
|
||||
corner1,
|
||||
corner2,
|
||||
])))
|
||||
}
|
||||
ArrowCap::Lines => Warn::ok(self.make_polygons(thickness).union(
|
||||
PolyLine::old_new(vec![corner1, self.last_pt(), corner2]).make_polygons(thickness),
|
||||
)),
|
||||
ArrowCap::Triangle => slice.make_polygons(thickness).union(Polygon::new(&vec![
|
||||
self.last_pt(),
|
||||
corner1,
|
||||
corner2,
|
||||
])),
|
||||
ArrowCap::Lines => self.make_polygons(thickness).union(
|
||||
PolyLine::must_new(vec![corner1, self.last_pt(), corner2]).make_polygons(thickness),
|
||||
),
|
||||
}
|
||||
}
|
||||
|
||||
@ -581,24 +543,18 @@ impl PolyLine {
|
||||
&self,
|
||||
arrow_thickness: Distance,
|
||||
outline_thickness: Distance,
|
||||
) -> Warn<Vec<Polygon>> {
|
||||
) -> Vec<Polygon> {
|
||||
let head_size = arrow_thickness * 2.0;
|
||||
let triangle_height = head_size / 2.0_f64.sqrt();
|
||||
|
||||
if self.length() < triangle_height {
|
||||
return Warn::warn(
|
||||
vec![self.make_polygons(arrow_thickness)],
|
||||
format!(
|
||||
"Can't make_arrow of thickness {} for {}",
|
||||
arrow_thickness, self
|
||||
),
|
||||
);
|
||||
return vec![self.make_polygons(arrow_thickness)];
|
||||
}
|
||||
let slice = self.exact_slice(Distance::ZERO, self.length() - triangle_height);
|
||||
|
||||
if let Some(p) = slice.to_thick_boundary(arrow_thickness, outline_thickness) {
|
||||
let angle = slice.last_pt().angle_to(self.last_pt());
|
||||
Warn::ok(vec![
|
||||
vec![
|
||||
p,
|
||||
Ring::new(vec![
|
||||
self.last_pt(),
|
||||
@ -609,15 +565,9 @@ impl PolyLine {
|
||||
self.last_pt(),
|
||||
])
|
||||
.make_polygons(outline_thickness),
|
||||
])
|
||||
]
|
||||
} else {
|
||||
Warn::warn(
|
||||
vec![self.make_polygons(arrow_thickness)],
|
||||
format!(
|
||||
"Can't make_arrow_outline of outline_thickness {} for {}",
|
||||
outline_thickness, self
|
||||
),
|
||||
)
|
||||
vec![self.make_polygons(arrow_thickness)]
|
||||
}
|
||||
}
|
||||
|
||||
@ -641,7 +591,7 @@ impl PolyLine {
|
||||
last_line.pt2(),
|
||||
)
|
||||
};
|
||||
polygons.push(arrow_line.to_polyline().make_arrow(width, cap).unwrap());
|
||||
polygons.push(arrow_line.to_polyline().make_arrow(width, cap));
|
||||
polygons
|
||||
}
|
||||
|
||||
@ -698,7 +648,7 @@ impl PolyLine {
|
||||
if pts.len() == 1 {
|
||||
return None;
|
||||
}
|
||||
Some(PolyLine::old_new(pts))
|
||||
Some(PolyLine::must_new(pts))
|
||||
} else {
|
||||
panic!("Can't get_slice_ending_at: {} doesn't contain {}", self, pt);
|
||||
}
|
||||
@ -716,7 +666,7 @@ impl PolyLine {
|
||||
if pt != pts[0] {
|
||||
pts.insert(0, pt);
|
||||
}
|
||||
Some(PolyLine::old_new(pts))
|
||||
Some(PolyLine::must_new(pts))
|
||||
} else {
|
||||
panic!(
|
||||
"Can't get_slice_starting_at: {} doesn't contain {}",
|
||||
@ -754,7 +704,7 @@ impl PolyLine {
|
||||
|
||||
impl fmt::Display for PolyLine {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
writeln!(f, "PolyLine::new(vec![")?;
|
||||
writeln!(f, "PolyLine::new(vec![ // length {}", self.length)?;
|
||||
for (idx, pt) in self.pts.iter().enumerate() {
|
||||
write!(f, " Pt2D::new({}, {}),", pt.x(), pt.y())?;
|
||||
if idx > 0 {
|
||||
@ -774,7 +724,7 @@ impl fmt::Display for PolyLine {
|
||||
}
|
||||
}
|
||||
|
||||
fn fix_angles(orig: &PolyLine, result: PolyLine) -> PolyLine {
|
||||
fn fix_angles(orig: &PolyLine, result: PolyLine) -> Result<PolyLine, Box<dyn Error>> {
|
||||
let mut pts = result.pts.clone();
|
||||
|
||||
// Check that the angles roughly match up between the original and shifted line
|
||||
@ -796,23 +746,7 @@ fn fix_angles(orig: &PolyLine, result: PolyLine) -> PolyLine {
|
||||
}
|
||||
|
||||
// When we swap points, length of the entire PolyLine may change! Recalculating is vital.
|
||||
PolyLine::old_new(pts)
|
||||
}
|
||||
|
||||
fn check_angles(orig: &PolyLine, fixed: PolyLine) -> Warn<PolyLine> {
|
||||
let mut warnings = Vec::new();
|
||||
for (orig_l, shifted_l) in orig.lines().iter().zip(fixed.lines().iter()) {
|
||||
let orig_angle = orig_l.angle();
|
||||
let shifted_angle = shifted_l.angle();
|
||||
|
||||
if !orig_angle.approx_eq(shifted_angle, 1.0) {
|
||||
warnings.push(format!(
|
||||
"Points changed angles from {} to {} during polyline shifting",
|
||||
orig_angle, shifted_angle
|
||||
));
|
||||
}
|
||||
}
|
||||
Warn::warnings(fixed, warnings)
|
||||
PolyLine::new(pts)
|
||||
}
|
||||
|
||||
// Also returns the duplicates.
|
||||
|
@ -516,7 +516,6 @@ impl Model {
|
||||
.config
|
||||
.driving_side
|
||||
.right_shift(center_pts.clone(), offset + width / 2.0)
|
||||
.unwrap()
|
||||
.make_polygons(width),
|
||||
);
|
||||
offset += width;
|
||||
@ -540,7 +539,6 @@ impl Model {
|
||||
.config
|
||||
.driving_side
|
||||
.right_shift(center_pts.reversed(), offset + width / 2.0)
|
||||
.unwrap()
|
||||
.make_polygons(width),
|
||||
);
|
||||
offset += width;
|
||||
@ -563,7 +561,6 @@ impl Model {
|
||||
}
|
||||
PolyLine::must_new(vec![self.get_r_center(id), self.get_r_center(*to)])
|
||||
.make_arrow(NORMAL_LANE_THICKNESS, ArrowCap::Triangle)
|
||||
.unwrap()
|
||||
};
|
||||
|
||||
result.push(Object::new(
|
||||
|
@ -40,12 +40,8 @@ pub fn intersection_polygon(
|
||||
};
|
||||
road_endpts.push(pl.last_pt());
|
||||
|
||||
let pl_normal = driving_side
|
||||
.right_shift(pl.clone(), r.half_width)
|
||||
.with_context(timer, format!("pl_normal {}", r.id));
|
||||
let pl_reverse = driving_side
|
||||
.left_shift(pl.clone(), r.half_width)
|
||||
.with_context(timer, format!("pl_reverse {}", r.id));
|
||||
let pl_normal = driving_side.right_shift(pl.clone(), r.half_width);
|
||||
let pl_reverse = driving_side.left_shift(pl.clone(), r.half_width);
|
||||
(*id, pl.last_line(), pl_normal, pl_reverse)
|
||||
})
|
||||
.collect();
|
||||
@ -262,26 +258,22 @@ fn generalized_trim_back(
|
||||
endpoints.push(
|
||||
driving_side
|
||||
.right_shift(r.trimmed_center_pts.clone(), r.half_width)
|
||||
.with_context(timer, format!("main polygon endpoints from {}", r.id))
|
||||
.last_pt(),
|
||||
);
|
||||
endpoints.push(
|
||||
driving_side
|
||||
.left_shift(r.trimmed_center_pts.clone(), r.half_width)
|
||||
.with_context(timer, format!("main polygon endpoints from {}", r.id))
|
||||
.last_pt(),
|
||||
);
|
||||
} else {
|
||||
endpoints.push(
|
||||
driving_side
|
||||
.left_shift(r.trimmed_center_pts.clone(), r.half_width)
|
||||
.with_context(timer, format!("main polygon endpoints from {}", r.id))
|
||||
.first_pt(),
|
||||
);
|
||||
endpoints.push(
|
||||
driving_side
|
||||
.right_shift(r.trimmed_center_pts.clone(), r.half_width)
|
||||
.with_context(timer, format!("main polygon endpoints from {}", r.id))
|
||||
.first_pt(),
|
||||
);
|
||||
}
|
||||
@ -388,26 +380,22 @@ fn deadend(
|
||||
endpts.push(
|
||||
driving_side
|
||||
.right_shift(r.trimmed_center_pts.clone(), r.half_width)
|
||||
.with_context(timer, format!("main polygon endpoints from {}", r.id))
|
||||
.last_pt(),
|
||||
);
|
||||
endpts.push(
|
||||
driving_side
|
||||
.left_shift(r.trimmed_center_pts.clone(), r.half_width)
|
||||
.with_context(timer, format!("main polygon endpoints from {}", r.id))
|
||||
.last_pt(),
|
||||
);
|
||||
} else {
|
||||
endpts.push(
|
||||
driving_side
|
||||
.left_shift(r.trimmed_center_pts.clone(), r.half_width)
|
||||
.with_context(timer, format!("main polygon endpoints from {}", r.id))
|
||||
.first_pt(),
|
||||
);
|
||||
endpts.push(
|
||||
driving_side
|
||||
.right_shift(r.trimmed_center_pts.clone(), r.half_width)
|
||||
.with_context(timer, format!("main polygon endpoints from {}", r.id))
|
||||
.first_pt(),
|
||||
);
|
||||
}
|
||||
|
@ -46,13 +46,11 @@ impl Road {
|
||||
// If there's a sidewalk on only one side, adjust the true center of the road.
|
||||
let mut trimmed_center_pts = PolyLine::must_new(r.center_points.clone());
|
||||
if sidewalk_right && !sidewalk_left {
|
||||
trimmed_center_pts = driving_side
|
||||
.right_shift(trimmed_center_pts, SIDEWALK_THICKNESS / 2.0)
|
||||
.unwrap();
|
||||
trimmed_center_pts =
|
||||
driving_side.right_shift(trimmed_center_pts, SIDEWALK_THICKNESS / 2.0);
|
||||
} else if sidewalk_left && !sidewalk_right {
|
||||
trimmed_center_pts = driving_side
|
||||
.left_shift(trimmed_center_pts, SIDEWALK_THICKNESS / 2.0)
|
||||
.unwrap();
|
||||
trimmed_center_pts =
|
||||
driving_side.left_shift(trimmed_center_pts, SIDEWALK_THICKNESS / 2.0);
|
||||
}
|
||||
|
||||
Road {
|
||||
|
@ -149,9 +149,7 @@ impl Map {
|
||||
}
|
||||
// TODO Maybe easier to use the road's "yellow center line" and shift left/right from
|
||||
// there.
|
||||
let road_left_pts = map
|
||||
.left_shift(road.center_pts.clone(), r.half_width)
|
||||
.with_context(timer, format!("shift for {}", road.id));
|
||||
let road_left_pts = map.left_shift(road.center_pts.clone(), r.half_width);
|
||||
|
||||
let mut fwd_width_so_far = Distance::ZERO;
|
||||
let mut back_width_so_far = Distance::ZERO;
|
||||
@ -173,15 +171,14 @@ impl Map {
|
||||
total_back_width + fwd_width_so_far + (lane.width() / 2.0),
|
||||
);
|
||||
fwd_width_so_far += lane.width();
|
||||
pl.with_context(timer, format!("shift for {}", id))
|
||||
pl
|
||||
} else {
|
||||
let pl = map.right_shift(
|
||||
road_left_pts.clone(),
|
||||
total_back_width - back_width_so_far - (lane.width() / 2.0),
|
||||
);
|
||||
back_width_so_far += lane.width();
|
||||
pl.with_context(timer, format!("shift for {}", id))
|
||||
.reversed()
|
||||
pl.reversed()
|
||||
};
|
||||
|
||||
map.lanes.push(Lane {
|
||||
|
@ -2,7 +2,7 @@ use crate::raw::{DrivingSide, RestrictionType};
|
||||
use crate::{
|
||||
Intersection, IntersectionID, Lane, LaneID, LaneType, Road, RoadID, Turn, TurnID, TurnType,
|
||||
};
|
||||
use abstutil::{wraparound_get, Timer, Warn};
|
||||
use abstutil::{wraparound_get, Timer};
|
||||
use geom::{Distance, Line, PolyLine, Pt2D, Ring};
|
||||
use nbez::{Bez3o, BezCurve, Point2d};
|
||||
use std::collections::{BTreeSet, HashMap, HashSet};
|
||||
@ -19,7 +19,7 @@ pub fn make_all_turns(
|
||||
assert!(!i.is_border());
|
||||
|
||||
let mut raw_turns: Vec<Turn> = Vec::new();
|
||||
raw_turns.extend(make_vehicle_turns(i, roads, lanes, timer));
|
||||
raw_turns.extend(make_vehicle_turns(i, roads, lanes));
|
||||
raw_turns.extend(make_walking_turns(driving_side, i, roads, lanes, timer));
|
||||
let unique_turns = ensure_unique(raw_turns);
|
||||
|
||||
@ -104,7 +104,6 @@ fn make_vehicle_turns(
|
||||
i: &Intersection,
|
||||
all_roads: &Vec<Road>,
|
||||
lanes: &Vec<Lane>,
|
||||
timer: &mut Timer,
|
||||
) -> impl Iterator<Item = Turn> {
|
||||
let sorted_roads: Vec<&Road> = i
|
||||
.get_roads_sorted_by_incoming_angle(all_roads)
|
||||
@ -127,8 +126,9 @@ fn make_vehicle_turns(
|
||||
|
||||
for lane_type in lane_types.into_iter() {
|
||||
if i.roads.len() == 1 {
|
||||
result
|
||||
.extend(make_vehicle_turns_for_dead_end(i, all_roads, lanes, lane_type).get(timer));
|
||||
result.extend(make_vehicle_turns_for_dead_end(
|
||||
i, all_roads, lanes, lane_type,
|
||||
));
|
||||
continue;
|
||||
}
|
||||
|
||||
@ -266,12 +266,13 @@ fn make_vehicle_turns_for_dead_end(
|
||||
roads: &Vec<Road>,
|
||||
lanes: &Vec<Lane>,
|
||||
lane_type: LaneType,
|
||||
) -> Warn<Vec<Option<Turn>>> {
|
||||
) -> Vec<Option<Turn>> {
|
||||
let road = &roads[i.roads.iter().next().unwrap().0];
|
||||
let incoming = filter_vehicle_lanes(road.incoming_lanes(i.id), lane_type);
|
||||
let outgoing = filter_vehicle_lanes(road.outgoing_lanes(i.id), lane_type);
|
||||
if incoming.is_empty() || outgoing.is_empty() {
|
||||
return Warn::warn(Vec::new(), format!("{} needs to be a border node!", i.id));
|
||||
println!("{} needs to be a border node!", i.id);
|
||||
return Vec::new();
|
||||
}
|
||||
|
||||
let mut result = Vec::new();
|
||||
@ -290,7 +291,7 @@ fn make_vehicle_turns_for_dead_end(
|
||||
}
|
||||
}
|
||||
|
||||
Warn::ok(result)
|
||||
result
|
||||
}
|
||||
|
||||
fn make_walking_turns(
|
||||
@ -575,10 +576,6 @@ fn make_shared_sidewalk_corner(
|
||||
pts_between.extend(
|
||||
driving_side
|
||||
.right_shift(PolyLine::must_new(deduped), l1.width / 2.0)
|
||||
.with_context(
|
||||
timer,
|
||||
format!("SharedSidewalkCorner between {} and {}", l1.id, l2.id),
|
||||
)
|
||||
.points(),
|
||||
);
|
||||
}
|
||||
|
@ -5,7 +5,7 @@ use crate::{
|
||||
ParkingLot, ParkingLotID, Path, PathConstraints, PathRequest, Position, Road, RoadID, Turn,
|
||||
TurnGroupID, TurnID, TurnType,
|
||||
};
|
||||
use abstutil::{Timer, Warn};
|
||||
use abstutil::Timer;
|
||||
use geom::{Angle, Bounds, Distance, GPSBounds, Line, PolyLine, Polygon, Pt2D};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::collections::{BTreeMap, BTreeSet, HashSet, VecDeque};
|
||||
@ -628,10 +628,10 @@ impl Map {
|
||||
None
|
||||
}
|
||||
|
||||
pub fn right_shift(&self, pl: PolyLine, width: Distance) -> Warn<PolyLine> {
|
||||
pub fn right_shift(&self, pl: PolyLine, width: Distance) -> PolyLine {
|
||||
self.config.driving_side.right_shift(pl, width)
|
||||
}
|
||||
pub fn left_shift(&self, pl: PolyLine, width: Distance) -> Warn<PolyLine> {
|
||||
pub fn left_shift(&self, pl: PolyLine, width: Distance) -> PolyLine {
|
||||
self.config.driving_side.left_shift(pl, width)
|
||||
}
|
||||
pub fn right_shift_line(&self, line: Line, width: Distance) -> Line {
|
||||
|
@ -281,7 +281,6 @@ impl Road {
|
||||
self.children_backwards[0].0
|
||||
});
|
||||
map.left_shift(lane.lane_center_pts.clone(), lane.width / 2.0)
|
||||
.unwrap()
|
||||
}
|
||||
|
||||
pub fn any_on_other_side(&self, l: LaneID, lt: LaneType) -> Option<LaneID> {
|
||||
|
@ -240,7 +240,7 @@ impl TurnGroup {
|
||||
left += map.get_l(l).width;
|
||||
}
|
||||
|
||||
let pl = map.right_shift(pl, (leftmost + rightmost) / 2.0).unwrap();
|
||||
let pl = map.right_shift(pl, (leftmost + rightmost) / 2.0);
|
||||
// Flip direction, so we point away from the intersection
|
||||
let pl = if self.id.crosswalk
|
||||
&& map.get_l(self.members[0].src).src_i == self.members[0].parent
|
||||
|
@ -319,7 +319,7 @@ impl UberTurnGroup {
|
||||
left += map.get_l(l).width;
|
||||
}
|
||||
|
||||
let pl = map.right_shift(pl, (leftmost + rightmost) / 2.0).unwrap();
|
||||
let pl = map.right_shift(pl, (leftmost + rightmost) / 2.0);
|
||||
// Flip direction, so we point away from the intersection
|
||||
(pl.reversed(), rightmost - leftmost)
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
use crate::make::initial::lane_specs::get_lane_types;
|
||||
use crate::{osm, AreaType, IntersectionType, MapConfig, RoadSpec};
|
||||
use abstutil::{deserialize_btreemap, serialize_btreemap, Timer, Warn};
|
||||
use abstutil::{deserialize_btreemap, serialize_btreemap, Timer};
|
||||
use geom::{Angle, Distance, GPSBounds, Line, PolyLine, Polygon, Pt2D};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::collections::{BTreeMap, BTreeSet};
|
||||
@ -388,14 +388,14 @@ pub enum DrivingSide {
|
||||
impl DrivingSide {
|
||||
// "right" and "left" here are in terms of DrivingSide::Right, what I'm used to reasoning about
|
||||
// in the USA. They invert appropriately for DrivingSide::Left.
|
||||
pub fn right_shift(self, pl: PolyLine, width: Distance) -> Warn<PolyLine> {
|
||||
pub fn right_shift(self, pl: PolyLine, width: Distance) -> PolyLine {
|
||||
match self {
|
||||
DrivingSide::Right => pl.shift_right(width),
|
||||
DrivingSide::Left => pl.shift_left(width),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn left_shift(self, pl: PolyLine, width: Distance) -> Warn<PolyLine> {
|
||||
pub fn left_shift(self, pl: PolyLine, width: Distance) -> PolyLine {
|
||||
match self {
|
||||
DrivingSide::Right => pl.shift_left(width),
|
||||
DrivingSide::Left => pl.shift_right(width),
|
||||
|
@ -134,7 +134,7 @@ impl Car {
|
||||
} else {
|
||||
-width
|
||||
};
|
||||
raw_body.shift_right(shift).unwrap()
|
||||
raw_body.shift_right(shift)
|
||||
}
|
||||
_ => {
|
||||
let driveway = match spot {
|
||||
|
Loading…
Reference in New Issue
Block a user