mirror of
https://github.com/a-b-street/abstreet.git
synced 2024-11-25 11:44:25 +03:00
the first real big change: Line::new always returns Option
This commit is contained in:
parent
0dd3199f7a
commit
98c6f46c78
@ -112,7 +112,7 @@ pub struct LinearGradient {
|
||||
|
||||
impl LinearGradient {
|
||||
pub(crate) fn new(lg: &usvg::LinearGradient) -> FancyColor {
|
||||
let line = Line::new(Pt2D::new(lg.x1, lg.y1), Pt2D::new(lg.x2, lg.y2));
|
||||
let line = Line::must_new(Pt2D::new(lg.x1, lg.y1), Pt2D::new(lg.x2, lg.y2));
|
||||
let mut stops = Vec::new();
|
||||
for stop in &lg.stops {
|
||||
let color = Color::rgba(
|
||||
|
@ -13,7 +13,7 @@ impl Warper {
|
||||
let z = ctx.canvas.cam_zoom;
|
||||
Warper {
|
||||
started: Instant::now(),
|
||||
line: Line::maybe_new(ctx.canvas.center_to_map_pt(), pt),
|
||||
line: Line::new(ctx.canvas.center_to_map_pt(), pt),
|
||||
cam_zoom: (z, target_cam_zoom.unwrap_or(z)),
|
||||
}
|
||||
}
|
||||
|
@ -51,18 +51,24 @@ impl CompareTimes {
|
||||
// Horizontal
|
||||
batch.push(
|
||||
Color::grey(0.5),
|
||||
geom::Line::new(Pt2D::new(0.0, y), Pt2D::new(width, y)).make_polygons(thickness),
|
||||
geom::Line::new(Pt2D::new(0.0, y), Pt2D::new(width, y))
|
||||
.unwrap()
|
||||
.make_polygons(thickness),
|
||||
);
|
||||
// Vertical
|
||||
batch.push(
|
||||
Color::grey(0.5),
|
||||
geom::Line::new(Pt2D::new(x, 0.0), Pt2D::new(x, height)).make_polygons(thickness),
|
||||
geom::Line::new(Pt2D::new(x, 0.0), Pt2D::new(x, height))
|
||||
.unwrap()
|
||||
.make_polygons(thickness),
|
||||
);
|
||||
}
|
||||
// Draw the diagonal, since we're comparing things on the same scale
|
||||
batch.push(
|
||||
Color::grey(0.5),
|
||||
geom::Line::new(Pt2D::new(0.0, height), Pt2D::new(width, 0.0)).make_polygons(thickness),
|
||||
geom::Line::new(Pt2D::new(0.0, height), Pt2D::new(width, 0.0))
|
||||
.unwrap()
|
||||
.make_polygons(thickness),
|
||||
);
|
||||
|
||||
let circle = Circle::new(Pt2D::new(0.0, 0.0), Distance::meters(4.0)).to_polygon();
|
||||
@ -145,13 +151,11 @@ impl WidgetImpl for CompareTimes {
|
||||
let thickness = Distance::meters(2.0);
|
||||
let mut batch = GeomBatch::new();
|
||||
// Horizontal
|
||||
if let Some(l) = geom::Line::maybe_new(Pt2D::new(rect.x1, cursor.y), cursor.to_pt())
|
||||
{
|
||||
if let Some(l) = geom::Line::new(Pt2D::new(rect.x1, cursor.y), cursor.to_pt()) {
|
||||
batch.push(Color::WHITE, l.make_polygons(thickness));
|
||||
}
|
||||
// Vertical
|
||||
if let Some(l) = geom::Line::maybe_new(Pt2D::new(cursor.x, rect.y2), cursor.to_pt())
|
||||
{
|
||||
if let Some(l) = geom::Line::new(Pt2D::new(cursor.x, rect.y2), cursor.to_pt()) {
|
||||
batch.push(Color::WHITE, l.make_polygons(thickness));
|
||||
}
|
||||
|
||||
|
@ -120,7 +120,7 @@ impl ColorLegend {
|
||||
let width_each = width / ((n - 1) as f64);
|
||||
batch.fancy_push(
|
||||
FancyColor::LinearGradient(LinearGradient {
|
||||
line: Line::new(Pt2D::new(0.0, 0.0), Pt2D::new(width, 0.0)),
|
||||
line: Line::must_new(Pt2D::new(0.0, 0.0), Pt2D::new(width, 0.0)),
|
||||
stops: scale
|
||||
.0
|
||||
.iter()
|
||||
|
@ -114,7 +114,7 @@ impl State for PolygonEditor {
|
||||
g.draw_line(
|
||||
POINT_COLOR,
|
||||
POINT_RADIUS / 2.0,
|
||||
&geom::Line::new(pts[0], pts[1]),
|
||||
&geom::Line::must_new(pts[0], pts[1]),
|
||||
);
|
||||
}
|
||||
if pts.len() >= 3 {
|
||||
|
@ -488,16 +488,19 @@ impl Screensaver {
|
||||
fn bounce(ctx: &mut EventCtx, app: &mut App, rng: &mut XorShiftRng) -> Screensaver {
|
||||
let at = ctx.canvas.center_to_map_pt();
|
||||
let bounds = app.primary.map.get_bounds();
|
||||
// TODO Ideally bounce off the edge of the map
|
||||
let goto = Pt2D::new(
|
||||
rng.gen_range(0.0, bounds.max_x),
|
||||
rng.gen_range(0.0, bounds.max_y),
|
||||
);
|
||||
let line = loop {
|
||||
let goto = Pt2D::new(
|
||||
rng.gen_range(0.0, bounds.max_x),
|
||||
rng.gen_range(0.0, bounds.max_y),
|
||||
);
|
||||
if let Some(l) = Line::new(at, goto) {
|
||||
break l;
|
||||
}
|
||||
};
|
||||
ctx.canvas.cam_zoom = 10.0;
|
||||
ctx.canvas.center_on_map_pt(at);
|
||||
|
||||
Screensaver {
|
||||
line: Line::new(at, goto),
|
||||
line,
|
||||
started: Instant::now(),
|
||||
}
|
||||
}
|
||||
|
@ -50,6 +50,7 @@ impl DrawBike {
|
||||
hand_pos.project_away(body_radius, hand_angle.rotate_degs(90.0)),
|
||||
hand_pos.project_away(body_radius, hand_angle.rotate_degs(-90.0)),
|
||||
)
|
||||
.unwrap()
|
||||
.make_polygons(Distance::meters(0.1)),
|
||||
);
|
||||
|
||||
@ -60,6 +61,7 @@ impl DrawBike {
|
||||
body_pos.project_away(0.9 * body_radius, facing.rotate_degs(-30.0)),
|
||||
hand_pos.project_away(0.4 * body_radius, hand_angle.rotate_degs(-90.0)),
|
||||
)
|
||||
.unwrap()
|
||||
.make_polygons(Distance::meters(0.08)),
|
||||
);
|
||||
draw_default.push(
|
||||
@ -68,6 +70,7 @@ impl DrawBike {
|
||||
body_pos.project_away(0.9 * body_radius, facing.rotate_degs(30.0)),
|
||||
hand_pos.project_away(0.4 * body_radius, hand_angle.rotate_degs(90.0)),
|
||||
)
|
||||
.unwrap()
|
||||
.make_polygons(Distance::meters(0.08)),
|
||||
);
|
||||
}
|
||||
|
@ -3,7 +3,7 @@ use crate::colors::ColorScheme;
|
||||
use crate::helpers::ID;
|
||||
use crate::render::{DrawOptions, Renderable, OUTLINE_THICKNESS};
|
||||
use ezgui::{Color, Drawable, GeomBatch, GfxCtx, Line, Prerender, Text};
|
||||
use geom::{Distance, Line, Polygon, Pt2D};
|
||||
use geom::{Distance, Polygon, Pt2D};
|
||||
use map_model::{Building, BuildingID, Map, NORMAL_LANE_THICKNESS, SIDEWALK_THICKNESS};
|
||||
use std::cell::RefCell;
|
||||
|
||||
@ -23,15 +23,13 @@ impl DrawBuilding {
|
||||
) -> DrawBuilding {
|
||||
// Trim the front path line away from the sidewalk's center line, so that it doesn't
|
||||
// overlap. For now, this cleanup is visual; it doesn't belong in the map_model layer.
|
||||
let mut front_path_line = bldg.front_path.line.clone();
|
||||
let len = front_path_line.length();
|
||||
let trim_back = SIDEWALK_THICKNESS / 2.0;
|
||||
if len > trim_back && len - trim_back > geom::EPSILON_DIST {
|
||||
front_path_line = Line::new(
|
||||
front_path_line.pt1(),
|
||||
front_path_line.dist_along(len - trim_back),
|
||||
);
|
||||
}
|
||||
let orig_line = &bldg.front_path.line;
|
||||
let front_path_line = orig_line
|
||||
.slice(
|
||||
Distance::ZERO,
|
||||
orig_line.length() - SIDEWALK_THICKNESS / 2.0,
|
||||
)
|
||||
.unwrap_or_else(|| orig_line.clone());
|
||||
|
||||
if bldg.amenities.is_empty() {
|
||||
bldg_batch.push(cs.residential_building, bldg.polygon.clone());
|
||||
|
@ -49,6 +49,7 @@ impl DrawBusStop {
|
||||
center.project_away(RADIUS, Angle::new_degs(90.0)),
|
||||
center.project_away(1.5 * RADIUS, Angle::new_degs(90.0)),
|
||||
)
|
||||
.unwrap()
|
||||
.make_polygons(Distance::meters(0.3)),
|
||||
);
|
||||
|
||||
|
@ -109,7 +109,7 @@ impl DrawIntersection {
|
||||
);
|
||||
|
||||
let octagon = make_octagon(last_line.pt2(), Distance::meters(1.0), last_line.angle());
|
||||
let pole = Line::new(
|
||||
let pole = Line::must_new(
|
||||
last_line
|
||||
.pt2()
|
||||
.project_away(Distance::meters(1.5), last_line.angle().opposite()),
|
||||
@ -322,7 +322,12 @@ pub fn make_crosswalk(batch: &mut GeomBatch, turn: &Turn, map: &Map, cs: &ColorS
|
||||
);
|
||||
return;
|
||||
}
|
||||
Line::new(pts[1], pts[2])
|
||||
match Line::new(pts[1], pts[2]) {
|
||||
Some(l) => l,
|
||||
None => {
|
||||
return;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
let available_length = line.length() - (boundary * 2.0);
|
||||
@ -337,7 +342,7 @@ pub fn make_crosswalk(batch: &mut GeomBatch, turn: &Turn, map: &Map, cs: &ColorS
|
||||
let pt2 = pt1.project_away(Distance::meters(1.0), turn.angle());
|
||||
batch.push(
|
||||
cs.general_road_marking,
|
||||
perp_line(Line::new(pt1, pt2), width).make_polygons(CROSSWALK_LINE_THICKNESS),
|
||||
perp_line(Line::must_new(pt1, pt2), width).make_polygons(CROSSWALK_LINE_THICKNESS),
|
||||
);
|
||||
|
||||
// Actually every line is a double
|
||||
@ -345,7 +350,7 @@ pub fn make_crosswalk(batch: &mut GeomBatch, turn: &Turn, map: &Map, cs: &ColorS
|
||||
let pt4 = pt3.project_away(Distance::meters(1.0), turn.angle());
|
||||
batch.push(
|
||||
cs.general_road_marking,
|
||||
perp_line(Line::new(pt3, pt4), width).make_polygons(CROSSWALK_LINE_THICKNESS),
|
||||
perp_line(Line::must_new(pt3, pt4), width).make_polygons(CROSSWALK_LINE_THICKNESS),
|
||||
);
|
||||
|
||||
dist_along += tile_every;
|
||||
@ -409,5 +414,5 @@ fn make_rainbow_crosswalk(batch: &mut GeomBatch, turn: &Turn, map: &Map) -> bool
|
||||
fn perp_line(l: Line, length: Distance) -> Line {
|
||||
let pt1 = l.shift_right(length / 2.0).pt1();
|
||||
let pt2 = l.shift_left(length / 2.0).pt1();
|
||||
Line::new(pt1, pt2)
|
||||
Line::must_new(pt1, pt2)
|
||||
}
|
||||
|
@ -119,7 +119,7 @@ impl DrawLane {
|
||||
let pt2 = pt.project_away(Distance::meters(1.0), angle);
|
||||
draw.push(
|
||||
app.cs.light_rail_track,
|
||||
perp_line(Line::new(pt, pt2), lane.width).make_polygons(track_width),
|
||||
perp_line(Line::must_new(pt, pt2), lane.width).make_polygons(track_width),
|
||||
);
|
||||
dist_along += tile_every;
|
||||
}
|
||||
@ -214,7 +214,7 @@ impl Renderable for DrawLane {
|
||||
fn perp_line(l: Line, length: Distance) -> Line {
|
||||
let pt1 = l.shift_right(length / 2.0).pt1();
|
||||
let pt2 = l.shift_left(length / 2.0).pt1();
|
||||
Line::new(pt1, pt2)
|
||||
Line::must_new(pt1, pt2)
|
||||
}
|
||||
|
||||
fn calculate_sidewalk_lines(lane: &Lane) -> Vec<Polygon> {
|
||||
@ -229,8 +229,9 @@ fn calculate_sidewalk_lines(lane: &Lane) -> Vec<Polygon> {
|
||||
let (pt, angle) = lane.dist_along(dist_along);
|
||||
// Reuse perp_line. Project away an arbitrary amount
|
||||
let pt2 = pt.project_away(Distance::meters(1.0), angle);
|
||||
result
|
||||
.push(perp_line(Line::new(pt, pt2), lane.width).make_polygons(Distance::meters(0.25)));
|
||||
result.push(
|
||||
perp_line(Line::must_new(pt, pt2), lane.width).make_polygons(Distance::meters(0.25)),
|
||||
);
|
||||
dist_along += tile_every;
|
||||
}
|
||||
|
||||
@ -253,13 +254,13 @@ fn calculate_parking_lines(map: &Map, lane: &Lane) -> Vec<Polygon> {
|
||||
let t_pt = pt.project_away(lane.width * 0.4, perp_angle);
|
||||
// The perp leg
|
||||
let p1 = t_pt.project_away(leg_length, perp_angle.opposite());
|
||||
result.push(Line::new(t_pt, p1).make_polygons(Distance::meters(0.25)));
|
||||
result.push(Line::must_new(t_pt, p1).make_polygons(Distance::meters(0.25)));
|
||||
// Upper leg
|
||||
let p2 = t_pt.project_away(leg_length, lane_angle);
|
||||
result.push(Line::new(t_pt, p2).make_polygons(Distance::meters(0.25)));
|
||||
result.push(Line::must_new(t_pt, p2).make_polygons(Distance::meters(0.25)));
|
||||
// Lower leg
|
||||
let p3 = t_pt.project_away(leg_length, lane_angle.opposite());
|
||||
result.push(Line::new(t_pt, p3).make_polygons(Distance::meters(0.25)));
|
||||
result.push(Line::must_new(t_pt, p3).make_polygons(Distance::meters(0.25)));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -3,7 +3,7 @@ use crate::colors::ColorScheme;
|
||||
use crate::helpers::ID;
|
||||
use crate::render::{DrawOptions, Renderable, OUTLINE_THICKNESS};
|
||||
use ezgui::{Drawable, GeomBatch, GfxCtx, Prerender};
|
||||
use geom::{Distance, Line, PolyLine, Polygon, Pt2D};
|
||||
use geom::{Distance, PolyLine, Polygon, Pt2D};
|
||||
use map_model::{
|
||||
Map, ParkingLot, ParkingLotID, NORMAL_LANE_THICKNESS, PARKING_LOT_SPOT_LENGTH,
|
||||
SIDEWALK_THICKNESS,
|
||||
@ -37,15 +37,13 @@ impl DrawParkingLot {
|
||||
|
||||
// Trim the front path line away from the sidewalk's center line, so that it doesn't
|
||||
// overlap. For now, this cleanup is visual; it doesn't belong in the map_model layer.
|
||||
let mut front_path_line = lot.sidewalk_line.clone();
|
||||
let len = front_path_line.length();
|
||||
let trim_back = SIDEWALK_THICKNESS / 2.0;
|
||||
if len > trim_back && len - trim_back > geom::EPSILON_DIST {
|
||||
front_path_line = Line::new(
|
||||
front_path_line.pt1(),
|
||||
front_path_line.dist_along(len - trim_back),
|
||||
);
|
||||
}
|
||||
let orig_line = &lot.sidewalk_line;
|
||||
let front_path_line = orig_line
|
||||
.slice(
|
||||
Distance::ZERO,
|
||||
orig_line.length() - SIDEWALK_THICKNESS / 2.0,
|
||||
)
|
||||
.unwrap_or_else(|| orig_line.clone());
|
||||
|
||||
let mut batch = GeomBatch::new();
|
||||
// TODO This isn't getting clipped to the parking lot boundary properly, so just stick this
|
||||
|
@ -282,7 +282,7 @@ pub fn draw_signal_phase(
|
||||
// TODO Kind of a hack to know that the second point is a better center.
|
||||
// Returns (center, angle)
|
||||
fn crosswalk_icon(geom: &PolyLine) -> (Pt2D, Angle) {
|
||||
let l = Line::new(geom.points()[1], geom.points()[2]);
|
||||
let l = Line::must_new(geom.points()[1], geom.points()[2]);
|
||||
(
|
||||
l.safe_dist_along(Distance::meters(1.0)).unwrap_or(l.pt1()),
|
||||
l.angle().shortest_rotation_towards(Angle::new_degs(90.0)),
|
||||
|
@ -8,26 +8,21 @@ use std::fmt;
|
||||
pub struct Line(Pt2D, Pt2D);
|
||||
|
||||
impl Line {
|
||||
pub fn new(pt1: Pt2D, pt2: Pt2D) -> Line {
|
||||
let len = pt1.dist_to(pt2);
|
||||
if len < EPSILON_DIST {
|
||||
panic!("Tiny line with length {}", len);
|
||||
}
|
||||
Line(pt1, pt2)
|
||||
}
|
||||
|
||||
pub fn maybe_new(pt1: Pt2D, pt2: Pt2D) -> Option<Line> {
|
||||
if pt1 == pt2 {
|
||||
pub fn new(pt1: Pt2D, pt2: Pt2D) -> Option<Line> {
|
||||
if pt1.dist_to(pt2) < EPSILON_DIST {
|
||||
return None;
|
||||
}
|
||||
Some(Line::new(pt1, pt2))
|
||||
Some(Line(pt1, pt2))
|
||||
}
|
||||
// Just to be more clear at the call-site
|
||||
pub fn must_new(pt1: Pt2D, pt2: Pt2D) -> Line {
|
||||
Line::new(pt1, pt2).unwrap()
|
||||
}
|
||||
|
||||
pub fn infinite(&self) -> InfiniteLine {
|
||||
InfiniteLine(self.0, self.1)
|
||||
}
|
||||
|
||||
// TODO we call these frequently here; unnecessary copies?
|
||||
pub fn pt1(&self) -> Pt2D {
|
||||
self.0
|
||||
}
|
||||
@ -173,6 +168,13 @@ impl Line {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn slice(&self, from: Distance, to: Distance) -> Option<Line> {
|
||||
if from < Distance::ZERO || to < Distance::ZERO || from >= to {
|
||||
return None;
|
||||
}
|
||||
Line::new(self.safe_dist_along(from)?, self.safe_dist_along(to)?)
|
||||
}
|
||||
|
||||
pub fn middle(&self) -> Pt2D {
|
||||
self.dist_along(self.length() / 2.0)
|
||||
}
|
||||
|
@ -196,7 +196,7 @@ impl PolyLine {
|
||||
pub fn lines(&self) -> Vec<Line> {
|
||||
self.pts
|
||||
.windows(2)
|
||||
.map(|pair| Line::new(pair[0], pair[1]))
|
||||
.map(|pair| Line::must_new(pair[0], pair[1]))
|
||||
.collect()
|
||||
}
|
||||
|
||||
@ -348,10 +348,10 @@ impl PolyLine {
|
||||
*self.pts.last().unwrap()
|
||||
}
|
||||
pub fn first_line(&self) -> Line {
|
||||
Line::new(self.pts[0], self.pts[1])
|
||||
Line::must_new(self.pts[0], self.pts[1])
|
||||
}
|
||||
pub fn last_line(&self) -> Line {
|
||||
Line::new(self.pts[self.pts.len() - 2], self.pts[self.pts.len() - 1])
|
||||
Line::must_new(self.pts[self.pts.len() - 2], self.pts[self.pts.len() - 1])
|
||||
}
|
||||
|
||||
pub fn shift_right(&self, width: Distance) -> Warn<PolyLine> {
|
||||
@ -379,7 +379,7 @@ impl PolyLine {
|
||||
|
||||
fn shift_with_sharp_angles(&self, width: Distance, miter_threshold: f64) -> Vec<Pt2D> {
|
||||
if self.pts.len() == 2 {
|
||||
let l = Line::new(self.pts[0], self.pts[1]).shift_either_direction(width);
|
||||
let l = Line::must_new(self.pts[0], self.pts[1]).shift_either_direction(width);
|
||||
return vec![l.pt1(), l.pt2()];
|
||||
}
|
||||
|
||||
@ -392,8 +392,8 @@ impl PolyLine {
|
||||
loop {
|
||||
let pt3_raw = self.pts[pt3_idx];
|
||||
|
||||
let l1 = Line::new(pt1_raw, pt2_raw).shift_either_direction(width);
|
||||
let l2 = Line::new(pt2_raw, pt3_raw).shift_either_direction(width);
|
||||
let l1 = Line::must_new(pt1_raw, pt2_raw).shift_either_direction(width);
|
||||
let l2 = Line::must_new(pt2_raw, pt3_raw).shift_either_direction(width);
|
||||
|
||||
if pt3_idx == 2 {
|
||||
result.push(l1.pt1());
|
||||
@ -591,7 +591,7 @@ impl PolyLine {
|
||||
let arrow_line = if last_len <= dash_len {
|
||||
last_line
|
||||
} else {
|
||||
Line::new(last_line.dist_along(last_len - dash_len), last_line.pt2())
|
||||
Line::must_new(last_line.dist_along(last_len - dash_len), last_line.pt2())
|
||||
};
|
||||
polygons.push(arrow_line.to_polyline().make_arrow(width, cap).unwrap());
|
||||
polygons
|
||||
@ -710,7 +710,7 @@ impl fmt::Display for PolyLine {
|
||||
for (idx, pt) in self.pts.iter().enumerate() {
|
||||
write!(f, " Pt2D::new({}, {}),", pt.x(), pt.y())?;
|
||||
if idx > 0 {
|
||||
let line = Line::new(self.pts[idx - 1], *pt);
|
||||
let line = Line::must_new(self.pts[idx - 1], *pt);
|
||||
write!(
|
||||
f,
|
||||
" // {}, {} (+ {} @ {})",
|
||||
|
@ -77,7 +77,11 @@ impl Ring {
|
||||
let mut hits = Vec::new();
|
||||
let mut seen = HashSet::new();
|
||||
for l1 in other.lines() {
|
||||
for l2 in self.pts.windows(2).map(|pair| Line::new(pair[0], pair[1])) {
|
||||
for l2 in self
|
||||
.pts
|
||||
.windows(2)
|
||||
.map(|pair| Line::must_new(pair[0], pair[1]))
|
||||
{
|
||||
if let Some(pt) = l1.intersection(&l2) {
|
||||
if !seen.contains(&pt.to_hashable()) {
|
||||
hits.push(pt);
|
||||
|
@ -564,9 +564,7 @@ impl GUI for UI {
|
||||
match self.state {
|
||||
State::CreatingRoad(i1) => {
|
||||
if let Some(cursor) = g.get_cursor_in_map_space() {
|
||||
if let Some(l) =
|
||||
Line::maybe_new(self.model.map.intersections[&i1].point, cursor)
|
||||
{
|
||||
if let Some(l) = Line::new(self.model.map.intersections[&i1].point, cursor) {
|
||||
g.draw_line(Color::GREEN, Distance::meters(5.0), &l);
|
||||
}
|
||||
}
|
||||
@ -595,14 +593,14 @@ impl GUI for UI {
|
||||
}
|
||||
State::CreatingTurnRestrictionPt1(from) => {
|
||||
if let Some(cursor) = g.get_cursor_in_map_space() {
|
||||
if let Some(l) = Line::maybe_new(self.model.get_r_center(from), cursor) {
|
||||
if let Some(l) = Line::new(self.model.get_r_center(from), cursor) {
|
||||
g.draw_arrow(Color::PURPLE, NORMAL_LANE_THICKNESS, &l);
|
||||
}
|
||||
}
|
||||
}
|
||||
State::CreatingTurnRestrictionPt2(from, to, ref wizard) => {
|
||||
if let Some(l) =
|
||||
Line::maybe_new(self.model.get_r_center(from), self.model.get_r_center(to))
|
||||
Line::new(self.model.get_r_center(from), self.model.get_r_center(to))
|
||||
{
|
||||
g.draw_arrow(Color::PURPLE, NORMAL_LANE_THICKNESS, &l);
|
||||
}
|
||||
|
@ -44,17 +44,17 @@ pub fn make_all_buildings(
|
||||
for (orig_id, bldg_center) in center_per_bldg {
|
||||
timer.next();
|
||||
if let Some(sidewalk_pos) = sidewalk_pts.get(&bldg_center) {
|
||||
let sidewalk_pt = sidewalk_pos.pt(map);
|
||||
if sidewalk_pt == bldg_center.to_pt2d() {
|
||||
timer.warn(format!(
|
||||
"Skipping building {} because front path has 0 length",
|
||||
orig_id
|
||||
));
|
||||
continue;
|
||||
}
|
||||
let b = &input[&orig_id];
|
||||
let sidewalk_line =
|
||||
trim_path(&b.polygon, Line::new(bldg_center.to_pt2d(), sidewalk_pt));
|
||||
let sidewalk_line = match Line::new(bldg_center.to_pt2d(), sidewalk_pos.pt(map)) {
|
||||
Some(l) => trim_path(&b.polygon, l),
|
||||
None => {
|
||||
timer.warn(format!(
|
||||
"Skipping building {} because front path has 0 length",
|
||||
orig_id
|
||||
));
|
||||
continue;
|
||||
}
|
||||
};
|
||||
|
||||
let id = BuildingID(results.len());
|
||||
let mut bldg = Building {
|
||||
@ -151,16 +151,16 @@ pub fn make_all_parking_lots(
|
||||
timer.next();
|
||||
// TODO Refactor this
|
||||
if let Some(sidewalk_pos) = sidewalk_pts.get(&lot_center) {
|
||||
let sidewalk_pt = sidewalk_pos.pt(map);
|
||||
if sidewalk_pt == lot_center.to_pt2d() {
|
||||
timer.warn(format!(
|
||||
"Skipping parking lot {} because driveway has 0 length",
|
||||
orig.osm_id
|
||||
));
|
||||
continue;
|
||||
}
|
||||
let sidewalk_line =
|
||||
trim_path(&orig.polygon, Line::new(lot_center.to_pt2d(), sidewalk_pt));
|
||||
let sidewalk_line = match Line::new(lot_center.to_pt2d(), sidewalk_pos.pt(map)) {
|
||||
Some(l) => trim_path(&orig.polygon, l),
|
||||
None => {
|
||||
timer.warn(format!(
|
||||
"Skipping parking lot {} because front path has 0 length",
|
||||
orig.osm_id
|
||||
));
|
||||
continue;
|
||||
}
|
||||
};
|
||||
|
||||
// Can this lot have a driveway? If it's not next to a driving lane, then no.
|
||||
let mut driveway: Option<(PolyLine, Position)> = None;
|
||||
@ -260,9 +260,9 @@ pub fn make_all_parking_lots(
|
||||
// Adjust the path to start on the building's border, not center
|
||||
fn trim_path(poly: &Polygon, path: Line) -> Line {
|
||||
for bldg_line in poly.points().windows(2) {
|
||||
let l = Line::new(bldg_line[0], bldg_line[1]);
|
||||
let l = Line::must_new(bldg_line[0], bldg_line[1]);
|
||||
if let Some(hit) = l.intersection(&path) {
|
||||
if let Some(l) = Line::maybe_new(hit, path.pt2()) {
|
||||
if let Some(l) = Line::new(hit, path.pt2()) {
|
||||
return l;
|
||||
}
|
||||
}
|
||||
@ -296,7 +296,7 @@ fn infer_spots(lot_polygon: &Polygon, aisles: &Vec<Vec<Pt2D>>) -> Vec<(Pt2D, Ang
|
||||
let (pt, angle) = pl.dist_along(start);
|
||||
start += NORMAL_LANE_THICKNESS;
|
||||
let theta = angle.rotate_degs(rotate);
|
||||
lines.push(Line::new(
|
||||
lines.push(Line::must_new(
|
||||
pt.project_away(aisle_thickness / 2.0, theta),
|
||||
pt.project_away(aisle_thickness / 2.0 + PARKING_LOT_SPOT_LENGTH, theta),
|
||||
));
|
||||
@ -307,7 +307,7 @@ fn infer_spots(lot_polygon: &Polygon, aisles: &Vec<Vec<Pt2D>>) -> Vec<(Pt2D, Ang
|
||||
for pair in lines.windows(2) {
|
||||
let l1 = &pair[0];
|
||||
let l2 = &pair[1];
|
||||
let back = Line::new(l1.pt2(), l2.pt2());
|
||||
let back = Line::must_new(l1.pt2(), l2.pt2());
|
||||
if l1.intersection(&l2).is_none()
|
||||
&& l1.angle().approx_eq(l2.angle(), 5.0)
|
||||
&& line_valid(lot_polygon, aisles, l1, &finalized_lines)
|
||||
|
@ -150,7 +150,7 @@ fn generalized_trim_back(
|
||||
|
||||
if let Some((hit, angle)) = use_pl1.intersection(&use_pl2) {
|
||||
// Find where the perpendicular hits the original road line
|
||||
let perp = Line::new(
|
||||
let perp = Line::must_new(
|
||||
hit,
|
||||
hit.project_away(Distance::meters(1.0), angle.rotate_degs(90.0)),
|
||||
)
|
||||
@ -181,9 +181,9 @@ fn generalized_trim_back(
|
||||
// road.
|
||||
// TODO Reduce DEGENERATE_INTERSECTION_HALF_LENGTH to play with this.
|
||||
if false {
|
||||
let perp = Line::new(pl1.last_pt(), other_pl1.last_pt());
|
||||
let perp = Line::must_new(pl1.last_pt(), other_pl1.last_pt());
|
||||
if perp.intersection(&pl2.last_line()).is_some() {
|
||||
let new_perp = Line::new(
|
||||
let new_perp = Line::must_new(
|
||||
pl2.last_pt(),
|
||||
pl2.last_pt()
|
||||
.project_away(Distance::meters(1.0), perp.angle()),
|
||||
|
@ -372,7 +372,7 @@ fn make_walking_turns(
|
||||
if let Some(l1) = get_sidewalk(lanes, roads[idx1].incoming_lanes(i.id)) {
|
||||
// Make the crosswalk to the other side
|
||||
if let Some(l2) = get_sidewalk(lanes, roads[idx1].outgoing_lanes(i.id)) {
|
||||
result.extend(make_crosswalks(i.id, l1, l2));
|
||||
result.extend(make_crosswalks(i.id, l1, l2).into_iter().flatten());
|
||||
}
|
||||
|
||||
// Find the shared corner
|
||||
@ -401,7 +401,7 @@ fn make_walking_turns(
|
||||
) {
|
||||
// Adjacent road is missing a sidewalk on the near side, but has one on the far
|
||||
// side
|
||||
result.extend(make_crosswalks(i.id, l1, l2));
|
||||
result.extend(make_crosswalks(i.id, l1, l2).into_iter().flatten());
|
||||
} else {
|
||||
// We may need to add a crosswalk over this intermediate road that has no
|
||||
// sidewalks at all. There might be a few in the way -- think highway onramps.
|
||||
@ -411,20 +411,20 @@ fn make_walking_turns(
|
||||
abstutil::wraparound_get(&roads, (idx1 as isize) + 2 * idx_offset)
|
||||
.outgoing_lanes(i.id),
|
||||
) {
|
||||
result.extend(make_crosswalks(i.id, l1, l2));
|
||||
result.extend(make_crosswalks(i.id, l1, l2).into_iter().flatten());
|
||||
} else if let Some(l2) = get_sidewalk(
|
||||
lanes,
|
||||
abstutil::wraparound_get(&roads, (idx1 as isize) + 2 * idx_offset)
|
||||
.incoming_lanes(i.id),
|
||||
) {
|
||||
result.extend(make_crosswalks(i.id, l1, l2));
|
||||
result.extend(make_crosswalks(i.id, l1, l2).into_iter().flatten());
|
||||
} else if roads.len() > 3 {
|
||||
if let Some(l2) = get_sidewalk(
|
||||
lanes,
|
||||
abstutil::wraparound_get(&roads, (idx1 as isize) + 3 * idx_offset)
|
||||
.outgoing_lanes(i.id),
|
||||
) {
|
||||
result.extend(make_crosswalks(i.id, l1, l2));
|
||||
result.extend(make_crosswalks(i.id, l1, l2).into_iter().flatten());
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -434,12 +434,9 @@ fn make_walking_turns(
|
||||
result
|
||||
}
|
||||
|
||||
fn make_crosswalks(i: IntersectionID, l1: &Lane, l2: &Lane) -> Vec<Turn> {
|
||||
fn make_crosswalks(i: IntersectionID, l1: &Lane, l2: &Lane) -> Option<Vec<Turn>> {
|
||||
let l1_pt = l1.endpoint(i);
|
||||
let l2_pt = l2.endpoint(i);
|
||||
if l1_pt == l2_pt {
|
||||
return Vec::new();
|
||||
}
|
||||
// TODO Not sure this is always right.
|
||||
let direction = if (l1.dst_i == i) == (l2.dst_i == i) {
|
||||
-1.0
|
||||
@ -448,10 +445,10 @@ fn make_crosswalks(i: IntersectionID, l1: &Lane, l2: &Lane) -> Vec<Turn> {
|
||||
};
|
||||
// Jut out a bit into the intersection, cross over, then jut back in. Assumes sidewalks are the
|
||||
// same width.
|
||||
let line = Line::new(l1_pt, l2_pt).shift_either_direction(direction * l1.width / 2.0);
|
||||
let line = Line::new(l1_pt, l2_pt)?.shift_either_direction(direction * l1.width / 2.0);
|
||||
let geom_fwds = PolyLine::deduping_new(vec![l1_pt, line.pt1(), line.pt2(), l2_pt]);
|
||||
|
||||
vec![
|
||||
Some(vec![
|
||||
Turn {
|
||||
id: turn_id(i, l1.id, l2.id),
|
||||
turn_type: TurnType::Crosswalk,
|
||||
@ -464,7 +461,7 @@ fn make_crosswalks(i: IntersectionID, l1: &Lane, l2: &Lane) -> Vec<Turn> {
|
||||
other_crosswalk_ids: vec![turn_id(i, l1.id, l2.id)].into_iter().collect(),
|
||||
geom: geom_fwds.reversed(),
|
||||
},
|
||||
]
|
||||
])
|
||||
}
|
||||
|
||||
// Only one physical crosswalk for degenerate intersections, right in the middle.
|
||||
@ -479,8 +476,8 @@ fn make_degenerate_crosswalks(
|
||||
let l2_in = get_sidewalk(lanes, r2.incoming_lanes(i))?;
|
||||
let l2_out = get_sidewalk(lanes, r2.outgoing_lanes(i))?;
|
||||
|
||||
let pt1 = Line::maybe_new(l1_in.last_pt(), l2_out.first_pt())?.percent_along(0.5);
|
||||
let pt2 = Line::maybe_new(l1_out.first_pt(), l2_in.last_pt())?.percent_along(0.5);
|
||||
let pt1 = Line::new(l1_in.last_pt(), l2_out.first_pt())?.percent_along(0.5);
|
||||
let pt2 = Line::new(l1_out.first_pt(), l2_in.last_pt())?.percent_along(0.5);
|
||||
|
||||
if pt1 == pt2 {
|
||||
return None;
|
||||
|
@ -81,7 +81,7 @@ impl WalkingSimState {
|
||||
),
|
||||
SidewalkPOI::BikeRack(driving_pos) => PedState::FinishingBiking(
|
||||
params.start.clone(),
|
||||
Line::new(driving_pos.pt(map), params.start.sidewalk_pos.pt(map)),
|
||||
Line::must_new(driving_pos.pt(map), params.start.sidewalk_pos.pt(map)),
|
||||
TimeInterval::new(now, now + TIME_TO_FINISH_BIKING),
|
||||
),
|
||||
_ => ped.crossing_state(params.start.sidewalk_pos.dist_along(), now, map),
|
||||
@ -198,7 +198,7 @@ impl WalkingSimState {
|
||||
let pt2 = driving_pos.pt(map);
|
||||
ped.state = PedState::StartingToBike(
|
||||
ped.goal.clone(),
|
||||
Line::new(pt1, pt2),
|
||||
Line::must_new(pt1, pt2),
|
||||
TimeInterval::new(now, now + TIME_TO_START_BIKING),
|
||||
);
|
||||
scheduler.push(ped.state.get_end_time(), Command::UpdatePed(ped.id));
|
||||
|
Loading…
Reference in New Issue
Block a user