mirror of
https://github.com/a-b-street/abstreet.git
synced 2024-12-25 15:33:44 +03:00
using strong Distance types in many more places
This commit is contained in:
parent
3e00789960
commit
7519fdf584
@ -165,9 +165,7 @@ fn use_parking_hints(map: &mut raw_data::Map, shapes: ExtraShapes, gps_bounds: &
|
|||||||
// TODO Long blockfaces sometimes cover two roads. Should maybe find ALL matches within
|
// TODO Long blockfaces sometimes cover two roads. Should maybe find ALL matches within
|
||||||
// the threshold distance?
|
// the threshold distance?
|
||||||
let middle = PolyLine::new(pts).middle();
|
let middle = PolyLine::new(pts).middle();
|
||||||
if let Some(((r, fwds), _)) =
|
if let Some(((r, fwds), _)) = closest.closest_pt(middle, LANE_THICKNESS * 5.0) {
|
||||||
closest.closest_pt(middle, Distance::meters(5.0 * LANE_THICKNESS))
|
|
||||||
{
|
|
||||||
let category = s.attributes.get("PARKING_CATEGORY");
|
let category = s.attributes.get("PARKING_CATEGORY");
|
||||||
let has_parking = category != Some(&"None".to_string())
|
let has_parking = category != Some(&"None".to_string())
|
||||||
&& category != Some(&"No Parking Allowed".to_string());
|
&& category != Some(&"No Parking Allowed".to_string());
|
||||||
|
@ -3,9 +3,6 @@
|
|||||||
## Geometry
|
## Geometry
|
||||||
|
|
||||||
- try fixed pt again, for determinism purposes mostly
|
- try fixed pt again, for determinism purposes mostly
|
||||||
- go through and use less f64's... like LANE_THICKNESS, make_polygons, Circle::new, project_away
|
|
||||||
- audit inner_foo()'s
|
|
||||||
|
|
||||||
- change internal pt2d representation to int. JUST get that working first.
|
- change internal pt2d representation to int. JUST get that working first.
|
||||||
- clamp distances first, not points?
|
- clamp distances first, not points?
|
||||||
- note contains_pt needs to use 2 or 3 * epsilon, because of the error that may accumulate...
|
- note contains_pt needs to use 2 or 3 * epsilon, because of the error that may accumulate...
|
||||||
|
@ -1,10 +1,10 @@
|
|||||||
use crate::objects::Ctx;
|
use crate::objects::Ctx;
|
||||||
use crate::plugins::{load_neighborhood_builder, Plugin, PluginCtx};
|
use crate::plugins::{load_neighborhood_builder, Plugin, PluginCtx};
|
||||||
use ezgui::{Color, GfxCtx, Key, Wizard, WrappedWizard};
|
use ezgui::{Color, GfxCtx, Key, Wizard, WrappedWizard};
|
||||||
use geom::{Circle, Line, Polygon, Pt2D};
|
use geom::{Circle, Distance, Line, Polygon, Pt2D};
|
||||||
use map_model::{Map, NeighborhoodBuilder};
|
use map_model::{Map, NeighborhoodBuilder};
|
||||||
|
|
||||||
const POINT_RADIUS: f64 = 2.0;
|
const POINT_RADIUS: Distance = Distance::const_meters(2.0);
|
||||||
|
|
||||||
pub enum DrawNeighborhoodState {
|
pub enum DrawNeighborhoodState {
|
||||||
PickNeighborhood(Wizard),
|
PickNeighborhood(Wizard),
|
||||||
|
@ -1,10 +1,10 @@
|
|||||||
use crate::objects::{Ctx, ID};
|
use crate::objects::{Ctx, ID};
|
||||||
use crate::render::{RenderOptions, Renderable};
|
use crate::render::{RenderOptions, Renderable};
|
||||||
use ezgui::{Color, GfxCtx};
|
use ezgui::{Color, GfxCtx};
|
||||||
use geom::{Bounds, Polygon, Pt2D};
|
use geom::{Bounds, Distance, Polygon, Pt2D};
|
||||||
use sim::{CarID, CarState, DrawCarInput};
|
use sim::{CarID, CarState, DrawCarInput};
|
||||||
|
|
||||||
const BIKE_WIDTH: f64 = 0.8;
|
const BIKE_WIDTH: Distance = Distance::const_meters(0.8);
|
||||||
|
|
||||||
pub struct DrawBike {
|
pub struct DrawBike {
|
||||||
pub id: CarID,
|
pub id: CarID,
|
||||||
|
@ -19,7 +19,7 @@ impl DrawBuilding {
|
|||||||
// overlap. For now, this cleanup is visual; it doesn't belong in the map_model layer.
|
// 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 mut front_path_line = bldg.front_path.line.clone();
|
||||||
let len = front_path_line.length();
|
let len = front_path_line.length();
|
||||||
let trim_back = Distance::meters(LANE_THICKNESS / 2.0);
|
let trim_back = LANE_THICKNESS / 2.0;
|
||||||
if len > trim_back && len - trim_back > geom::EPSILON_DIST {
|
if len > trim_back && len - trim_back > geom::EPSILON_DIST {
|
||||||
front_path_line = Line::new(
|
front_path_line = Line::new(
|
||||||
front_path_line.pt1(),
|
front_path_line.pt1(),
|
||||||
@ -27,7 +27,7 @@ impl DrawBuilding {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
let fill_polygon = Polygon::new(&bldg.points);
|
let fill_polygon = Polygon::new(&bldg.points);
|
||||||
let front_path = front_path_line.make_polygons(1.0);
|
let front_path = front_path_line.make_polygons(Distance::meters(1.0));
|
||||||
|
|
||||||
let default_draw = prerender.upload_borrowed(vec![
|
let default_draw = prerender.upload_borrowed(vec![
|
||||||
(
|
(
|
||||||
|
@ -27,7 +27,7 @@ impl DrawBusStop {
|
|||||||
.map(|(pt, _)| pt)
|
.map(|(pt, _)| pt)
|
||||||
.unwrap_or_else(|| lane.last_pt()),
|
.unwrap_or_else(|| lane.last_pt()),
|
||||||
])
|
])
|
||||||
.make_polygons(0.8 * LANE_THICKNESS);
|
.make_polygons(LANE_THICKNESS * 0.8);
|
||||||
DrawBusStop {
|
DrawBusStop {
|
||||||
id: stop.id,
|
id: stop.id,
|
||||||
polygon,
|
polygon,
|
||||||
|
@ -6,7 +6,7 @@ use map_model::{Map, TurnType};
|
|||||||
use sim::{CarID, CarState, DrawCarInput, MIN_CAR_LENGTH};
|
use sim::{CarID, CarState, DrawCarInput, MIN_CAR_LENGTH};
|
||||||
use std;
|
use std;
|
||||||
|
|
||||||
const CAR_WIDTH: f64 = 2.0;
|
const CAR_WIDTH: Distance = Distance::const_meters(2.0);
|
||||||
|
|
||||||
pub struct DrawCar {
|
pub struct DrawCar {
|
||||||
pub id: CarID,
|
pub id: CarID,
|
||||||
@ -57,17 +57,17 @@ impl DrawCar {
|
|||||||
.body
|
.body
|
||||||
.dist_along(input.body.length() - Distance::meters(0.5));
|
.dist_along(input.body.length() - Distance::meters(0.5));
|
||||||
let (back_blinker_pos, back_blinker_angle) = input.body.dist_along(Distance::meters(0.5));
|
let (back_blinker_pos, back_blinker_angle) = input.body.dist_along(Distance::meters(0.5));
|
||||||
let blinker_radius = 0.3;
|
let blinker_radius = Distance::meters(0.3);
|
||||||
|
|
||||||
let window_length_gap = 0.2;
|
let window_length_gap = Distance::meters(0.2);
|
||||||
let window_thickness = 0.3;
|
let window_thickness = Distance::meters(0.3);
|
||||||
let front_window = {
|
let front_window = {
|
||||||
let (pos, angle) = input
|
let (pos, angle) = input
|
||||||
.body
|
.body
|
||||||
.dist_along(input.body.length() - Distance::meters(1.0));
|
.dist_along(input.body.length() - Distance::meters(1.0));
|
||||||
thick_line_from_angle(
|
thick_line_from_angle(
|
||||||
window_thickness,
|
window_thickness,
|
||||||
CAR_WIDTH - 2.0 * window_length_gap,
|
CAR_WIDTH - window_length_gap * 2.0,
|
||||||
pos.project_away(
|
pos.project_away(
|
||||||
CAR_WIDTH / 2.0 - window_length_gap,
|
CAR_WIDTH / 2.0 - window_length_gap,
|
||||||
angle.rotate_degs(-90.0),
|
angle.rotate_degs(-90.0),
|
||||||
@ -79,7 +79,7 @@ impl DrawCar {
|
|||||||
let (pos, angle) = input.body.dist_along(Distance::meters(1.0));
|
let (pos, angle) = input.body.dist_along(Distance::meters(1.0));
|
||||||
thick_line_from_angle(
|
thick_line_from_angle(
|
||||||
window_thickness * 0.8,
|
window_thickness * 0.8,
|
||||||
CAR_WIDTH - 2.0 * window_length_gap,
|
CAR_WIDTH - window_length_gap * 2.0,
|
||||||
pos.project_away(
|
pos.project_away(
|
||||||
CAR_WIDTH / 2.0 - window_length_gap,
|
CAR_WIDTH / 2.0 - window_length_gap,
|
||||||
angle.rotate_degs(-90.0),
|
angle.rotate_degs(-90.0),
|
||||||
@ -95,26 +95,32 @@ impl DrawCar {
|
|||||||
left_blinkers: Some((
|
left_blinkers: Some((
|
||||||
Circle::new(
|
Circle::new(
|
||||||
front_blinker_pos.project_away(
|
front_blinker_pos.project_away(
|
||||||
CAR_WIDTH / 2.0 - 0.5,
|
CAR_WIDTH / 2.0 - Distance::meters(0.5),
|
||||||
front_blinker_angle.rotate_degs(-90.0),
|
front_blinker_angle.rotate_degs(-90.0),
|
||||||
),
|
),
|
||||||
blinker_radius,
|
blinker_radius,
|
||||||
),
|
),
|
||||||
Circle::new(
|
Circle::new(
|
||||||
back_blinker_pos
|
back_blinker_pos.project_away(
|
||||||
.project_away(CAR_WIDTH / 2.0 - 0.5, back_blinker_angle.rotate_degs(-90.0)),
|
CAR_WIDTH / 2.0 - Distance::meters(0.5),
|
||||||
|
back_blinker_angle.rotate_degs(-90.0),
|
||||||
|
),
|
||||||
blinker_radius,
|
blinker_radius,
|
||||||
),
|
),
|
||||||
)),
|
)),
|
||||||
right_blinkers: Some((
|
right_blinkers: Some((
|
||||||
Circle::new(
|
Circle::new(
|
||||||
front_blinker_pos
|
front_blinker_pos.project_away(
|
||||||
.project_away(CAR_WIDTH / 2.0 - 0.5, front_blinker_angle.rotate_degs(90.0)),
|
CAR_WIDTH / 2.0 - Distance::meters(0.5),
|
||||||
|
front_blinker_angle.rotate_degs(90.0),
|
||||||
|
),
|
||||||
blinker_radius,
|
blinker_radius,
|
||||||
),
|
),
|
||||||
Circle::new(
|
Circle::new(
|
||||||
back_blinker_pos
|
back_blinker_pos.project_away(
|
||||||
.project_away(CAR_WIDTH / 2.0 - 0.5, back_blinker_angle.rotate_degs(90.0)),
|
CAR_WIDTH / 2.0 - Distance::meters(0.5),
|
||||||
|
back_blinker_angle.rotate_degs(90.0),
|
||||||
|
),
|
||||||
blinker_radius,
|
blinker_radius,
|
||||||
),
|
),
|
||||||
)),
|
)),
|
||||||
@ -216,7 +222,12 @@ impl Renderable for DrawCar {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn thick_line_from_angle(thickness: f64, line_length: f64, pt: Pt2D, angle: Angle) -> Polygon {
|
fn thick_line_from_angle(
|
||||||
|
thickness: Distance,
|
||||||
|
line_length: Distance,
|
||||||
|
pt: Pt2D,
|
||||||
|
angle: Angle,
|
||||||
|
) -> Polygon {
|
||||||
let pt2 = pt.project_away(line_length, angle);
|
let pt2 = pt.project_away(line_length, angle);
|
||||||
// Shouldn't ever fail for a single line
|
// Shouldn't ever fail for a single line
|
||||||
PolyLine::new(vec![pt, pt2]).make_polygons(thickness)
|
PolyLine::new(vec![pt, pt2]).make_polygons(thickness)
|
||||||
|
@ -50,19 +50,18 @@ impl DrawExtraShape {
|
|||||||
road: None,
|
road: None,
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
let width = get_sidewalk_width(&s.attributes)
|
let width = get_sidewalk_width(&s.attributes).unwrap_or(EXTRA_SHAPE_THICKNESS);
|
||||||
.unwrap_or_else(|| Distance::meters(EXTRA_SHAPE_THICKNESS));
|
|
||||||
let pl = PolyLine::new(pts);
|
let pl = PolyLine::new(pts);
|
||||||
// The blockface line endpoints will be close to other roads, so match based on the
|
// The blockface line endpoints will be close to other roads, so match based on the
|
||||||
// middle of the blockface.
|
// middle of the blockface.
|
||||||
// TODO Long blockfaces sometimes cover two roads. Should maybe find ALL matches within
|
// TODO Long blockfaces sometimes cover two roads. Should maybe find ALL matches within
|
||||||
// the threshold distance?
|
// the threshold distance?
|
||||||
let road = closest
|
let road = closest
|
||||||
.closest_pt(pl.middle(), Distance::meters(5.0 * LANE_THICKNESS))
|
.closest_pt(pl.middle(), LANE_THICKNESS * 5.0)
|
||||||
.map(|(r, _)| r);
|
.map(|(r, _)| r);
|
||||||
Some(DrawExtraShape {
|
Some(DrawExtraShape {
|
||||||
id,
|
id,
|
||||||
shape: Shape::Polygon(pl.make_polygons(width.inner_meters())),
|
shape: Shape::Polygon(pl.make_polygons(width)),
|
||||||
attributes: s.attributes,
|
attributes: s.attributes,
|
||||||
road,
|
road,
|
||||||
})
|
})
|
||||||
|
@ -224,7 +224,7 @@ fn draw_signal_cycle_with_icons(cycle: &Cycle, g: &mut GfxCtx, ctx: &Ctx) {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
let radius = Distance::meters(LANE_THICKNESS / 2.0);
|
let radius = LANE_THICKNESS / 2.0;
|
||||||
|
|
||||||
// TODO Ignore right_ok...
|
// TODO Ignore right_ok...
|
||||||
{
|
{
|
||||||
@ -234,7 +234,7 @@ fn draw_signal_cycle_with_icons(cycle: &Cycle, g: &mut GfxCtx, ctx: &Ctx) {
|
|||||||
} else {
|
} else {
|
||||||
ctx.cs.get_def("traffic light stop", Color::RED)
|
ctx.cs.get_def("traffic light stop", Color::RED)
|
||||||
};
|
};
|
||||||
g.draw_circle(color, &Circle::new(center1, radius.inner_meters()));
|
g.draw_circle(color, &Circle::new(center1, radius));
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(pri) = left_priority {
|
if let Some(pri) = left_priority {
|
||||||
@ -248,16 +248,14 @@ fn draw_signal_cycle_with_icons(cycle: &Cycle, g: &mut GfxCtx, ctx: &Ctx) {
|
|||||||
};
|
};
|
||||||
g.draw_circle(
|
g.draw_circle(
|
||||||
ctx.cs.get_def("traffic light box", Color::BLACK),
|
ctx.cs.get_def("traffic light box", Color::BLACK),
|
||||||
&Circle::new(center2, radius.inner_meters()),
|
&Circle::new(center2, radius),
|
||||||
);
|
);
|
||||||
g.draw_arrow(
|
g.draw_arrow(
|
||||||
color,
|
color,
|
||||||
0.1,
|
Distance::meters(0.1),
|
||||||
&Line::new(
|
&Line::new(
|
||||||
center2
|
center2.project_away(radius, lane_line.angle().rotate_degs(90.0)),
|
||||||
.project_away(radius.inner_meters(), lane_line.angle().rotate_degs(90.0)),
|
center2.project_away(radius, lane_line.angle().rotate_degs(-90.0)),
|
||||||
center2
|
|
||||||
.project_away(radius.inner_meters(), lane_line.angle().rotate_degs(-90.0)),
|
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -81,8 +81,8 @@ impl DrawLane {
|
|||||||
PARCEL_BOUNDARY_THICKNESS / 2.0,
|
PARCEL_BOUNDARY_THICKNESS / 2.0,
|
||||||
&l,
|
&l,
|
||||||
);
|
);
|
||||||
g.draw_circle(circle_color, &Circle::new(l.pt1(), 0.4));
|
g.draw_circle(circle_color, &Circle::new(l.pt1(), Distance::meters(0.4)));
|
||||||
g.draw_circle(circle_color, &Circle::new(l.pt2(), 0.8));
|
g.draw_circle(circle_color, &Circle::new(l.pt2(), Distance::meters(0.8)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -122,14 +122,14 @@ impl Renderable for DrawLane {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// TODO this always does it at pt1
|
// TODO this always does it at pt1
|
||||||
fn perp_line(l: Line, length: f64) -> Line {
|
fn perp_line(l: Line, length: Distance) -> Line {
|
||||||
let pt1 = l.shift_right(length / 2.0).pt1();
|
let pt1 = l.shift_right(length / 2.0).pt1();
|
||||||
let pt2 = l.shift_left(length / 2.0).pt1();
|
let pt2 = l.shift_left(length / 2.0).pt1();
|
||||||
Line::new(pt1, pt2)
|
Line::new(pt1, pt2)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn calculate_sidewalk_lines(lane: &Lane, cs: &ColorScheme) -> Vec<(Color, Polygon)> {
|
fn calculate_sidewalk_lines(lane: &Lane, cs: &ColorScheme) -> Vec<(Color, Polygon)> {
|
||||||
let tile_every = Distance::meters(LANE_THICKNESS);
|
let tile_every = LANE_THICKNESS;
|
||||||
let color = cs.get_def("sidewalk lines", Color::grey(0.7));
|
let color = cs.get_def("sidewalk lines", Color::grey(0.7));
|
||||||
|
|
||||||
let length = lane.length();
|
let length = lane.length();
|
||||||
@ -140,10 +140,10 @@ fn calculate_sidewalk_lines(lane: &Lane, cs: &ColorScheme) -> Vec<(Color, Polygo
|
|||||||
while dist_along < length - tile_every {
|
while dist_along < length - tile_every {
|
||||||
let (pt, angle) = lane.dist_along(dist_along);
|
let (pt, angle) = lane.dist_along(dist_along);
|
||||||
// Reuse perp_line. Project away an arbitrary amount
|
// Reuse perp_line. Project away an arbitrary amount
|
||||||
let pt2 = pt.project_away(1.0, angle);
|
let pt2 = pt.project_away(Distance::meters(1.0), angle);
|
||||||
result.push((
|
result.push((
|
||||||
color,
|
color,
|
||||||
perp_line(Line::new(pt, pt2), LANE_THICKNESS).make_polygons(0.25),
|
perp_line(Line::new(pt, pt2), LANE_THICKNESS).make_polygons(Distance::meters(0.25)),
|
||||||
));
|
));
|
||||||
dist_along += tile_every;
|
dist_along += tile_every;
|
||||||
}
|
}
|
||||||
@ -153,8 +153,7 @@ fn calculate_sidewalk_lines(lane: &Lane, cs: &ColorScheme) -> Vec<(Color, Polygo
|
|||||||
|
|
||||||
fn calculate_parking_lines(lane: &Lane, cs: &ColorScheme) -> Vec<(Color, Polygon)> {
|
fn calculate_parking_lines(lane: &Lane, cs: &ColorScheme) -> Vec<(Color, Polygon)> {
|
||||||
// meters, but the dims get annoying below to remove
|
// meters, but the dims get annoying below to remove
|
||||||
// TODO make Pt2D natively understand meters, projecting away by an angle
|
let leg_length = Distance::meters(1.0);
|
||||||
let leg_length = 1.0;
|
|
||||||
let color = cs.get_def("parking lines", Color::WHITE);
|
let color = cs.get_def("parking lines", Color::WHITE);
|
||||||
|
|
||||||
let mut result = Vec::new();
|
let mut result = Vec::new();
|
||||||
@ -168,13 +167,22 @@ fn calculate_parking_lines(lane: &Lane, cs: &ColorScheme) -> Vec<(Color, Polygon
|
|||||||
let t_pt = pt.project_away(LANE_THICKNESS * 0.4, perp_angle);
|
let t_pt = pt.project_away(LANE_THICKNESS * 0.4, perp_angle);
|
||||||
// The perp leg
|
// The perp leg
|
||||||
let p1 = t_pt.project_away(leg_length, perp_angle.opposite());
|
let p1 = t_pt.project_away(leg_length, perp_angle.opposite());
|
||||||
result.push((color, Line::new(t_pt, p1).make_polygons(0.25)));
|
result.push((
|
||||||
|
color,
|
||||||
|
Line::new(t_pt, p1).make_polygons(Distance::meters(0.25)),
|
||||||
|
));
|
||||||
// Upper leg
|
// Upper leg
|
||||||
let p2 = t_pt.project_away(leg_length, lane_angle);
|
let p2 = t_pt.project_away(leg_length, lane_angle);
|
||||||
result.push((color, Line::new(t_pt, p2).make_polygons(0.25)));
|
result.push((
|
||||||
|
color,
|
||||||
|
Line::new(t_pt, p2).make_polygons(Distance::meters(0.25)),
|
||||||
|
));
|
||||||
// Lower leg
|
// Lower leg
|
||||||
let p3 = t_pt.project_away(leg_length, lane_angle.opposite());
|
let p3 = t_pt.project_away(leg_length, lane_angle.opposite());
|
||||||
result.push((color, Line::new(t_pt, p3).make_polygons(0.25)));
|
result.push((
|
||||||
|
color,
|
||||||
|
Line::new(t_pt, p3).make_polygons(Distance::meters(0.25)),
|
||||||
|
));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -199,7 +207,7 @@ fn calculate_driving_lines(lane: &Lane, parent: &Road, cs: &ColorScheme) -> Vec<
|
|||||||
.slice(dash_separation, lane_edge_pts.length() - dash_separation)
|
.slice(dash_separation, lane_edge_pts.length() - dash_separation)
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.0
|
.0
|
||||||
.dashed_polygons(0.25, dash_len, dash_separation);
|
.dashed_polygons(Distance::meters(0.25), dash_len, dash_separation);
|
||||||
polygons
|
polygons
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.map(|p| (cs.get_def("dashed lane line", Color::WHITE), p))
|
.map(|p| (cs.get_def("dashed lane line", Color::WHITE), p))
|
||||||
@ -220,7 +228,7 @@ fn calculate_stop_sign_line(
|
|||||||
|
|
||||||
let (pt1, angle) = lane.safe_dist_along(lane.length() - Distance::meters(1.0))?;
|
let (pt1, angle) = lane.safe_dist_along(lane.length() - Distance::meters(1.0))?;
|
||||||
// Reuse perp_line. Project away an arbitrary amount
|
// Reuse perp_line. Project away an arbitrary amount
|
||||||
let pt2 = pt1.project_away(1.0, angle);
|
let pt2 = pt1.project_away(Distance::meters(1.0), angle);
|
||||||
// Don't clobber the yellow line.
|
// Don't clobber the yellow line.
|
||||||
let line = if road.is_canonical_lane(lane.id) {
|
let line = if road.is_canonical_lane(lane.id) {
|
||||||
perp_line(
|
perp_line(
|
||||||
@ -233,7 +241,7 @@ fn calculate_stop_sign_line(
|
|||||||
|
|
||||||
Some((
|
Some((
|
||||||
cs.get_def("stop line for lane", Color::RED),
|
cs.get_def("stop line for lane", Color::RED),
|
||||||
line.make_polygons(0.45),
|
line.make_polygons(Distance::meters(0.45)),
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -266,7 +274,7 @@ fn turn_markings(turn: &Turn, map: &Map, cs: &ColorScheme) -> Vec<(Color, Polygo
|
|||||||
.slice(len - Distance::meters(7.0), len - Distance::meters(5.0))
|
.slice(len - Distance::meters(7.0), len - Distance::meters(5.0))
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.0;
|
.0;
|
||||||
let base_polygon = common_base.make_polygons(0.1);
|
let base_polygon = common_base.make_polygons(Distance::meters(0.1));
|
||||||
let turn_line = Line::new(
|
let turn_line = Line::new(
|
||||||
common_base.last_pt(),
|
common_base.last_pt(),
|
||||||
common_base
|
common_base
|
||||||
@ -276,6 +284,11 @@ fn turn_markings(turn: &Turn, map: &Map, cs: &ColorScheme) -> Vec<(Color, Polygo
|
|||||||
|
|
||||||
let color = cs.get_def("turn restrictions on lane", Color::WHITE);
|
let color = cs.get_def("turn restrictions on lane", Color::WHITE);
|
||||||
let mut result = vec![(color, base_polygon)];
|
let mut result = vec![(color, base_polygon)];
|
||||||
result.extend(turn_line.make_arrow(0.05).into_iter().map(|p| (color, p)));
|
result.extend(
|
||||||
|
turn_line
|
||||||
|
.make_arrow(Distance::meters(0.05))
|
||||||
|
.into_iter()
|
||||||
|
.map(|p| (color, p)),
|
||||||
|
);
|
||||||
result
|
result
|
||||||
}
|
}
|
||||||
|
@ -22,21 +22,20 @@ pub use crate::render::map::{DrawMap, RenderOrder};
|
|||||||
pub use crate::render::pedestrian::DrawPedestrian;
|
pub use crate::render::pedestrian::DrawPedestrian;
|
||||||
pub use crate::render::turn::{DrawCrosswalk, DrawTurn};
|
pub use crate::render::turn::{DrawCrosswalk, DrawTurn};
|
||||||
use ezgui::{Color, GfxCtx};
|
use ezgui::{Color, GfxCtx};
|
||||||
use geom::{Bounds, Pt2D};
|
use geom::{Bounds, Distance, Pt2D};
|
||||||
use map_model::Map;
|
use map_model::Map;
|
||||||
use sim::{DrawCarInput, VehicleType};
|
use sim::{DrawCarInput, VehicleType};
|
||||||
use std::f64;
|
use std::f64;
|
||||||
|
|
||||||
// These are all in meters
|
const PARCEL_BOUNDARY_THICKNESS: Distance = Distance::const_meters(0.5);
|
||||||
const PARCEL_BOUNDARY_THICKNESS: f64 = 0.5;
|
const EXTRA_SHAPE_THICKNESS: Distance = Distance::const_meters(1.0);
|
||||||
const EXTRA_SHAPE_THICKNESS: f64 = 1.0;
|
const EXTRA_SHAPE_POINT_RADIUS: Distance = Distance::const_meters(1.0);
|
||||||
const EXTRA_SHAPE_POINT_RADIUS: f64 = 1.0;
|
|
||||||
|
|
||||||
const BIG_ARROW_THICKNESS: f64 = 0.5;
|
const BIG_ARROW_THICKNESS: Distance = Distance::const_meters(0.5);
|
||||||
|
|
||||||
const TURN_ICON_ARROW_THICKNESS: f64 = 0.15;
|
const TURN_ICON_ARROW_THICKNESS: Distance = Distance::const_meters(0.15);
|
||||||
const TURN_ICON_ARROW_LENGTH: f64 = 2.0;
|
const TURN_ICON_ARROW_LENGTH: Distance = Distance::const_meters(2.0);
|
||||||
pub const CROSSWALK_LINE_THICKNESS: f64 = 0.25;
|
pub const CROSSWALK_LINE_THICKNESS: Distance = Distance::const_meters(0.25);
|
||||||
|
|
||||||
pub const MIN_ZOOM_FOR_MARKINGS: f64 = 5.0;
|
pub const MIN_ZOOM_FOR_MARKINGS: f64 = 5.0;
|
||||||
|
|
||||||
|
@ -1,11 +1,11 @@
|
|||||||
use crate::objects::{Ctx, ID};
|
use crate::objects::{Ctx, ID};
|
||||||
use crate::render::{RenderOptions, Renderable};
|
use crate::render::{RenderOptions, Renderable};
|
||||||
use ezgui::{Color, GfxCtx};
|
use ezgui::{Color, GfxCtx};
|
||||||
use geom::{Bounds, Circle, Line, Pt2D};
|
use geom::{Bounds, Circle, Distance, Line, Pt2D};
|
||||||
use map_model::Map;
|
use map_model::Map;
|
||||||
use sim::{DrawPedestrianInput, PedestrianID};
|
use sim::{DrawPedestrianInput, PedestrianID};
|
||||||
|
|
||||||
const RADIUS: f64 = 1.0;
|
const RADIUS: Distance = Distance::const_meters(1.0);
|
||||||
|
|
||||||
pub struct DrawPedestrian {
|
pub struct DrawPedestrian {
|
||||||
pub id: PedestrianID,
|
pub id: PedestrianID,
|
||||||
@ -59,7 +59,7 @@ impl Renderable for DrawPedestrian {
|
|||||||
if let Some(ref a) = self.turn_arrow {
|
if let Some(ref a) = self.turn_arrow {
|
||||||
g.draw_arrow(
|
g.draw_arrow(
|
||||||
ctx.cs.get_def("pedestrian turn arrow", Color::CYAN),
|
ctx.cs.get_def("pedestrian turn arrow", Color::CYAN),
|
||||||
0.25,
|
Distance::meters(0.25),
|
||||||
a,
|
a,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -6,7 +6,6 @@ use crate::render::{
|
|||||||
use ezgui::{Color, GfxCtx};
|
use ezgui::{Color, GfxCtx};
|
||||||
use geom::{Bounds, Circle, Distance, Line, Polygon, Pt2D};
|
use geom::{Bounds, Circle, Distance, Line, Polygon, Pt2D};
|
||||||
use map_model::{Map, Turn, TurnID, LANE_THICKNESS};
|
use map_model::{Map, Turn, TurnID, LANE_THICKNESS};
|
||||||
use std::f64;
|
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct DrawTurn {
|
pub struct DrawTurn {
|
||||||
@ -22,9 +21,9 @@ impl DrawTurn {
|
|||||||
|
|
||||||
let end_line = map.get_l(turn.id.src).end_line(turn.id.parent);
|
let end_line = map.get_l(turn.id.src).end_line(turn.id.parent);
|
||||||
// Start the distance from the intersection
|
// Start the distance from the intersection
|
||||||
let icon_center = end_line.reverse().unbounded_dist_along(Distance::meters(
|
let icon_center = end_line
|
||||||
(offset_along_lane + 0.5) * TURN_ICON_ARROW_LENGTH,
|
.reverse()
|
||||||
));
|
.unbounded_dist_along(TURN_ICON_ARROW_LENGTH * (offset_along_lane + 0.5));
|
||||||
|
|
||||||
let icon_circle = Circle::new(icon_center, TURN_ICON_ARROW_LENGTH / 2.0);
|
let icon_circle = Circle::new(icon_center, TURN_ICON_ARROW_LENGTH / 2.0);
|
||||||
|
|
||||||
@ -43,10 +42,10 @@ impl DrawTurn {
|
|||||||
// TODO This is hiding a real problem... some composite turns probably need to have their
|
// TODO This is hiding a real problem... some composite turns probably need to have their
|
||||||
// geometry simplified a bit.
|
// geometry simplified a bit.
|
||||||
if let Some(pl) = t.geom.without_last_line() {
|
if let Some(pl) = t.geom.without_last_line() {
|
||||||
g.draw_polygon(color, &pl.make_polygons(2.0 * BIG_ARROW_THICKNESS));
|
g.draw_polygon(color, &pl.make_polygons(BIG_ARROW_THICKNESS * 2.0));
|
||||||
}
|
}
|
||||||
// And a cap on the arrow
|
// And a cap on the arrow
|
||||||
g.draw_arrow(color, 2.0 * BIG_ARROW_THICKNESS, &t.geom.last_line());
|
g.draw_arrow(color, BIG_ARROW_THICKNESS * 2.0, &t.geom.last_line());
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn draw_dashed(turn: &Turn, g: &mut GfxCtx, color: Color) {
|
pub fn draw_dashed(turn: &Turn, g: &mut GfxCtx, color: Color) {
|
||||||
@ -118,8 +117,8 @@ impl DrawCrosswalk {
|
|||||||
// Start at least LANE_THICKNESS out to not hit sidewalk corners. Also account for
|
// Start at least LANE_THICKNESS out to not hit sidewalk corners. Also account for
|
||||||
// the thickness of the crosswalk line itself. Center the lines inside these two
|
// the thickness of the crosswalk line itself. Center the lines inside these two
|
||||||
// boundaries.
|
// boundaries.
|
||||||
let boundary = Distance::meters(LANE_THICKNESS + CROSSWALK_LINE_THICKNESS);
|
let boundary = LANE_THICKNESS + CROSSWALK_LINE_THICKNESS;
|
||||||
let tile_every = Distance::meters(0.6 * LANE_THICKNESS);
|
let tile_every = LANE_THICKNESS * 0.6;
|
||||||
let line = {
|
let line = {
|
||||||
// The middle line in the crosswalk geometry is the main crossing line.
|
// The middle line in the crosswalk geometry is the main crossing line.
|
||||||
let pts = turn.geom.points();
|
let pts = turn.geom.points();
|
||||||
@ -136,7 +135,7 @@ impl DrawCrosswalk {
|
|||||||
for _ in 0..=num_markings {
|
for _ in 0..=num_markings {
|
||||||
let pt1 = line.dist_along(dist_along);
|
let pt1 = line.dist_along(dist_along);
|
||||||
// Reuse perp_line. Project away an arbitrary amount
|
// Reuse perp_line. Project away an arbitrary amount
|
||||||
let pt2 = pt1.project_away(1.0, turn.angle());
|
let pt2 = pt1.project_away(Distance::meters(1.0), turn.angle());
|
||||||
draw.push(
|
draw.push(
|
||||||
perp_line(Line::new(pt1, pt2), LANE_THICKNESS)
|
perp_line(Line::new(pt1, pt2), LANE_THICKNESS)
|
||||||
.make_polygons(CROSSWALK_LINE_THICKNESS),
|
.make_polygons(CROSSWALK_LINE_THICKNESS),
|
||||||
@ -154,7 +153,7 @@ impl DrawCrosswalk {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// TODO copied from DrawLane
|
// TODO copied from DrawLane
|
||||||
fn perp_line(l: Line, length: f64) -> Line {
|
fn perp_line(l: Line, length: Distance) -> Line {
|
||||||
let pt1 = l.shift_right(length / 2.0).pt1();
|
let pt1 = l.shift_right(length / 2.0).pt1();
|
||||||
let pt2 = l.shift_left(length / 2.0).pt1();
|
let pt2 = l.shift_left(length / 2.0).pt1();
|
||||||
Line::new(pt1, pt2)
|
Line::new(pt1, pt2)
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
use crate::{Canvas, Color, ScreenPt};
|
use crate::{Canvas, Color, ScreenPt};
|
||||||
use geom::{Circle, Line, Polygon, Pt2D};
|
use geom::{Circle, Distance, Line, Polygon, Pt2D};
|
||||||
use glium::{implement_vertex, uniform, Surface};
|
use glium::{implement_vertex, uniform, Surface};
|
||||||
|
|
||||||
const TRIANGLES_PER_CIRCLE: usize = 60;
|
const TRIANGLES_PER_CIRCLE: usize = 60;
|
||||||
@ -100,11 +100,11 @@ impl<'a> GfxCtx<'a> {
|
|||||||
|
|
||||||
// Use graphics::Line internally for now, but make it easy to switch to something else by
|
// Use graphics::Line internally for now, but make it easy to switch to something else by
|
||||||
// picking this API now.
|
// picking this API now.
|
||||||
pub fn draw_line(&mut self, color: Color, thickness: f64, line: &Line) {
|
pub fn draw_line(&mut self, color: Color, thickness: Distance, line: &Line) {
|
||||||
self.draw_polygon(color, &line.make_polygons(thickness));
|
self.draw_polygon(color, &line.make_polygons(thickness));
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn draw_rounded_line(&mut self, color: Color, thickness: f64, line: &Line) {
|
pub fn draw_rounded_line(&mut self, color: Color, thickness: Distance, line: &Line) {
|
||||||
self.draw_polygon_batch(vec![
|
self.draw_polygon_batch(vec![
|
||||||
(color, &line.make_polygons(thickness)),
|
(color, &line.make_polygons(thickness)),
|
||||||
(
|
(
|
||||||
@ -118,7 +118,7 @@ impl<'a> GfxCtx<'a> {
|
|||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn draw_arrow(&mut self, color: Color, thickness: f64, line: &Line) {
|
pub fn draw_arrow(&mut self, color: Color, thickness: Distance, line: &Line) {
|
||||||
let polygons = line.make_arrow(thickness);
|
let polygons = line.make_arrow(thickness);
|
||||||
self.draw_polygon_batch(polygons.iter().map(|poly| (color, poly)).collect());
|
self.draw_polygon_batch(polygons.iter().map(|poly| (color, poly)).collect());
|
||||||
}
|
}
|
||||||
|
@ -1,30 +1,30 @@
|
|||||||
use crate::{Angle, Bounds, Polygon, Pt2D};
|
use crate::{Angle, Bounds, Distance, Polygon, Pt2D};
|
||||||
use serde_derive::{Deserialize, Serialize};
|
use serde_derive::{Deserialize, Serialize};
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize, Debug)]
|
#[derive(Serialize, Deserialize, Debug)]
|
||||||
pub struct Circle {
|
pub struct Circle {
|
||||||
pub center: Pt2D,
|
pub center: Pt2D,
|
||||||
pub radius: f64,
|
pub radius: Distance,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Circle {
|
impl Circle {
|
||||||
pub fn new(center: Pt2D, radius: f64) -> Circle {
|
pub fn new(center: Pt2D, radius: Distance) -> Circle {
|
||||||
Circle { center, radius }
|
Circle { center, radius }
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn contains_pt(&self, pt: Pt2D) -> bool {
|
pub fn contains_pt(&self, pt: Pt2D) -> bool {
|
||||||
// avoid sqrt by squaring radius instead
|
// avoid sqrt by squaring radius instead
|
||||||
(pt.x() - self.center.x()).powi(2) + (pt.y() - self.center.y()).powi(2)
|
(pt.x() - self.center.x()).powi(2) + (pt.y() - self.center.y()).powi(2)
|
||||||
< self.radius.powi(2)
|
< self.radius.inner_meters().powi(2)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_bounds(&self) -> Bounds {
|
pub fn get_bounds(&self) -> Bounds {
|
||||||
Bounds {
|
Bounds {
|
||||||
min_x: self.center.x() - self.radius,
|
min_x: self.center.x() - self.radius.inner_meters(),
|
||||||
max_x: self.center.x() + self.radius,
|
max_x: self.center.x() + self.radius.inner_meters(),
|
||||||
min_y: self.center.y() - self.radius,
|
min_y: self.center.y() - self.radius.inner_meters(),
|
||||||
max_y: self.center.y() + self.radius,
|
max_y: self.center.y() + self.radius.inner_meters(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -36,15 +36,15 @@ impl Line {
|
|||||||
PolyLine::new(self.points())
|
PolyLine::new(self.points())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn make_polygons(&self, thickness: f64) -> Polygon {
|
pub fn make_polygons(&self, thickness: Distance) -> Polygon {
|
||||||
self.to_polyline().make_polygons(thickness)
|
self.to_polyline().make_polygons(thickness)
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO One polygon, please :)
|
// TODO One polygon, please :)
|
||||||
pub fn make_arrow(&self, thickness: f64) -> Vec<Polygon> {
|
pub fn make_arrow(&self, thickness: Distance) -> Vec<Polygon> {
|
||||||
let head_size = 2.0 * thickness;
|
let head_size = thickness * 2.0;
|
||||||
let angle = self.angle();
|
let angle = self.angle();
|
||||||
let triangle_height = Distance::meters((head_size / 2.0).sqrt());
|
let triangle_height = (head_size / 2.0).sqrt();
|
||||||
vec![
|
vec![
|
||||||
Polygon::new(&vec![
|
Polygon::new(&vec![
|
||||||
//self.pt2(),
|
//self.pt2(),
|
||||||
@ -107,8 +107,8 @@ impl Line {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn shift_right(&self, width: f64) -> Line {
|
pub fn shift_right(&self, width: Distance) -> Line {
|
||||||
assert!(width >= 0.0);
|
assert!(width >= Distance::ZERO);
|
||||||
let angle = self.angle().rotate_degs(90.0);
|
let angle = self.angle().rotate_degs(90.0);
|
||||||
Line(
|
Line(
|
||||||
self.pt1().project_away(width, angle),
|
self.pt1().project_away(width, angle),
|
||||||
@ -116,8 +116,8 @@ impl Line {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn shift_left(&self, width: f64) -> Line {
|
pub fn shift_left(&self, width: Distance) -> Line {
|
||||||
assert!(width >= 0.0);
|
assert!(width >= Distance::ZERO);
|
||||||
let angle = self.angle().rotate_degs(-90.0);
|
let angle = self.angle().rotate_degs(-90.0);
|
||||||
Line(
|
Line(
|
||||||
self.pt1().project_away(width, angle),
|
self.pt1().project_away(width, angle),
|
||||||
@ -125,8 +125,8 @@ impl Line {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn shift_either_direction(&self, width: f64) -> Line {
|
pub(crate) fn shift_either_direction(&self, width: Distance) -> Line {
|
||||||
if width >= 0.0 {
|
if width >= Distance::ZERO {
|
||||||
self.shift_right(width)
|
self.shift_right(width)
|
||||||
} else {
|
} else {
|
||||||
self.shift_left(-width)
|
self.shift_left(-width)
|
||||||
|
@ -3,7 +3,6 @@ use crate::{
|
|||||||
};
|
};
|
||||||
use serde_derive::{Deserialize, Serialize};
|
use serde_derive::{Deserialize, Serialize};
|
||||||
use std::collections::HashSet;
|
use std::collections::HashSet;
|
||||||
use std::f64;
|
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
|
|
||||||
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
|
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
|
||||||
@ -51,7 +50,7 @@ impl PolyLine {
|
|||||||
PolyLine { pts, length }
|
PolyLine { pts, length }
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn make_polygons_for_boundary(pts: Vec<Pt2D>, thickness: f64) -> Polygon {
|
pub fn make_polygons_for_boundary(pts: Vec<Pt2D>, thickness: Distance) -> Polygon {
|
||||||
// Points WILL repeat -- fast-path some stuff.
|
// Points WILL repeat -- fast-path some stuff.
|
||||||
let pl = PolyLine {
|
let pl = PolyLine {
|
||||||
pts,
|
pts,
|
||||||
@ -222,18 +221,18 @@ impl PolyLine {
|
|||||||
Some(PolyLine::new(self.pts[0..self.pts.len() - 1].to_vec()))
|
Some(PolyLine::new(self.pts[0..self.pts.len() - 1].to_vec()))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn shift_right(&self, width: f64) -> PolyLine {
|
pub fn shift_right(&self, width: Distance) -> PolyLine {
|
||||||
self.shift_with_corrections(width)
|
self.shift_with_corrections(width)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn shift_left(&self, width: f64) -> PolyLine {
|
pub fn shift_left(&self, width: Distance) -> PolyLine {
|
||||||
self.shift_with_corrections(-width)
|
self.shift_with_corrections(-width)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Things to remember about shifting polylines:
|
// Things to remember about shifting polylines:
|
||||||
// - the length before and after probably don't match up
|
// - the length before and after probably don't match up
|
||||||
// - the number of points will match
|
// - the number of points will match
|
||||||
fn shift_with_corrections(&self, width: f64) -> PolyLine {
|
fn shift_with_corrections(&self, width: Distance) -> PolyLine {
|
||||||
let result = PolyLine::new(Pt2D::approx_dedupe(
|
let result = PolyLine::new(Pt2D::approx_dedupe(
|
||||||
self.shift_with_sharp_angles(width),
|
self.shift_with_sharp_angles(width),
|
||||||
EPSILON_DIST,
|
EPSILON_DIST,
|
||||||
@ -247,7 +246,7 @@ impl PolyLine {
|
|||||||
fixed
|
fixed
|
||||||
}
|
}
|
||||||
|
|
||||||
fn shift_with_sharp_angles(&self, width: f64) -> Vec<Pt2D> {
|
fn shift_with_sharp_angles(&self, width: Distance) -> Vec<Pt2D> {
|
||||||
if self.pts.len() == 2 {
|
if self.pts.len() == 2 {
|
||||||
let l = Line::new(self.pts[0], self.pts[1]).shift_either_direction(width);
|
let l = Line::new(self.pts[0], self.pts[1]).shift_either_direction(width);
|
||||||
return vec![l.pt1(), l.pt2()];
|
return vec![l.pt1(), l.pt2()];
|
||||||
@ -290,7 +289,7 @@ impl PolyLine {
|
|||||||
result
|
result
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn make_polygons(&self, width: f64) -> Polygon {
|
pub fn make_polygons(&self, width: Distance) -> Polygon {
|
||||||
// TODO Don't use the angle corrections yet -- they seem to do weird things.
|
// TODO Don't use the angle corrections yet -- they seem to do weird things.
|
||||||
let side1 = self.shift_with_sharp_angles(width / 2.0);
|
let side1 = self.shift_with_sharp_angles(width / 2.0);
|
||||||
let side2 = self.shift_with_sharp_angles(-width / 2.0);
|
let side2 = self.shift_with_sharp_angles(-width / 2.0);
|
||||||
@ -315,7 +314,7 @@ impl PolyLine {
|
|||||||
|
|
||||||
pub fn dashed_polygons(
|
pub fn dashed_polygons(
|
||||||
&self,
|
&self,
|
||||||
width: f64,
|
width: Distance,
|
||||||
dash_len: Distance,
|
dash_len: Distance,
|
||||||
dash_separation: Distance,
|
dash_separation: Distance,
|
||||||
) -> Vec<Polygon> {
|
) -> Vec<Polygon> {
|
||||||
|
@ -86,12 +86,15 @@ impl Pt2D {
|
|||||||
|
|
||||||
// TODO better name
|
// TODO better name
|
||||||
// TODO Meters for dist?
|
// TODO Meters for dist?
|
||||||
pub fn project_away(self, dist: f64, theta: Angle) -> Pt2D {
|
pub fn project_away(self, dist: Distance, theta: Angle) -> Pt2D {
|
||||||
// If negative, caller should use theta.opposite()
|
// If negative, caller should use theta.opposite()
|
||||||
assert!(dist >= 0.0);
|
assert!(dist >= Distance::ZERO);
|
||||||
|
|
||||||
let (sin, cos) = theta.normalized_radians().sin_cos();
|
let (sin, cos) = theta.normalized_radians().sin_cos();
|
||||||
Pt2D::new(self.x() + dist * cos, self.y() + dist * sin)
|
Pt2D::new(
|
||||||
|
self.x() + dist.inner_meters() * cos,
|
||||||
|
self.y() + dist.inner_meters() * sin,
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO valid to do euclidean distance on world-space points that're formed from
|
// TODO valid to do euclidean distance on world-space points that're formed from
|
||||||
|
@ -35,6 +35,10 @@ impl Distance {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn sqrt(self) -> Distance {
|
||||||
|
Distance::meters(self.0.sqrt())
|
||||||
|
}
|
||||||
|
|
||||||
// TODO Remove by making Distance itself Ord.
|
// TODO Remove by making Distance itself Ord.
|
||||||
pub fn as_ordered(self) -> NotNan<f64> {
|
pub fn as_ordered(self) -> NotNan<f64> {
|
||||||
NotNan::new(self.0).unwrap()
|
NotNan::new(self.0).unwrap()
|
||||||
@ -75,6 +79,14 @@ impl ops::Sub for Distance {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl ops::Neg for Distance {
|
||||||
|
type Output = Distance;
|
||||||
|
|
||||||
|
fn neg(self) -> Distance {
|
||||||
|
Distance::meters(-self.0)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl ops::SubAssign for Distance {
|
impl ops::SubAssign for Distance {
|
||||||
fn sub_assign(&mut self, other: Distance) {
|
fn sub_assign(&mut self, other: Distance) {
|
||||||
*self = *self - other;
|
*self = *self - other;
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
use aabb_quadtree::QuadTree;
|
use aabb_quadtree::QuadTree;
|
||||||
use ezgui::{Color, GfxCtx};
|
use ezgui::{Color, GfxCtx};
|
||||||
use geom::{Bounds, Line, Polygon, Pt2D};
|
use geom::{Bounds, Distance, Line, Polygon, Pt2D};
|
||||||
use map_model::{Building, BuildingID, Map, Road, RoadID, LANE_THICKNESS};
|
use map_model::{Building, BuildingID, Map, Road, RoadID, LANE_THICKNESS};
|
||||||
|
|
||||||
// black
|
// black
|
||||||
@ -12,7 +12,7 @@ const BUILDING: Color = Color::rgb_f(136.0 / 255.0, 30.0 / 255.0, 228.0 / 255.0)
|
|||||||
// dark orange / red
|
// dark orange / red
|
||||||
const PATH: Color = Color::rgb_f(247.0 / 255.0, 95.0 / 255.0, 28.0 / 255.0);
|
const PATH: Color = Color::rgb_f(247.0 / 255.0, 95.0 / 255.0, 28.0 / 255.0);
|
||||||
|
|
||||||
const LINE_WIDTH: f64 = 1.0;
|
const LINE_WIDTH: Distance = Distance::const_meters(1.0);
|
||||||
|
|
||||||
pub struct DrawMap {
|
pub struct DrawMap {
|
||||||
roads: Vec<DrawRoad>,
|
roads: Vec<DrawRoad>,
|
||||||
|
@ -38,8 +38,9 @@ pub use crate::traffic_signals::{ControlTrafficSignal, Cycle};
|
|||||||
pub use crate::traversable::{Position, Traversable};
|
pub use crate::traversable::{Position, Traversable};
|
||||||
pub use crate::turn::{Turn, TurnID, TurnPriority, TurnType};
|
pub use crate::turn::{Turn, TurnID, TurnPriority, TurnType};
|
||||||
use abstutil::Cloneable;
|
use abstutil::Cloneable;
|
||||||
|
use geom::Distance;
|
||||||
|
|
||||||
pub const LANE_THICKNESS: f64 = 2.5;
|
pub const LANE_THICKNESS: Distance = Distance::const_meters(2.5);
|
||||||
|
|
||||||
impl Cloneable for ControlTrafficSignal {}
|
impl Cloneable for ControlTrafficSignal {}
|
||||||
impl Cloneable for IntersectionID {}
|
impl Cloneable for IntersectionID {}
|
||||||
|
@ -114,8 +114,11 @@ fn generalized_trim_back(
|
|||||||
|
|
||||||
if let Some((hit, angle)) = use_pl1.intersection(&use_pl2) {
|
if let Some((hit, angle)) = use_pl1.intersection(&use_pl2) {
|
||||||
// Find where the perpendicular hits the original road line
|
// Find where the perpendicular hits the original road line
|
||||||
let perp =
|
let perp = Line::new(
|
||||||
Line::new(hit, hit.project_away(1.0, angle.rotate_degs(90.0))).infinite();
|
hit,
|
||||||
|
hit.project_away(Distance::meters(1.0), angle.rotate_degs(90.0)),
|
||||||
|
)
|
||||||
|
.infinite();
|
||||||
// How could something perpendicular to a shifted polyline never hit the original
|
// How could something perpendicular to a shifted polyline never hit the original
|
||||||
// polyline?
|
// polyline?
|
||||||
let trim_to = road_center.intersection_infinite(&perp).unwrap();
|
let trim_to = road_center.intersection_infinite(&perp).unwrap();
|
||||||
|
@ -5,7 +5,7 @@ mod merge;
|
|||||||
use crate::raw_data::{StableIntersectionID, StableRoadID};
|
use crate::raw_data::{StableIntersectionID, StableRoadID};
|
||||||
use crate::{raw_data, MapEdits, LANE_THICKNESS};
|
use crate::{raw_data, MapEdits, LANE_THICKNESS};
|
||||||
use abstutil::Timer;
|
use abstutil::Timer;
|
||||||
use geom::{GPSBounds, PolyLine, Pt2D};
|
use geom::{Distance, GPSBounds, PolyLine, Pt2D};
|
||||||
use serde_derive::{Deserialize, Serialize};
|
use serde_derive::{Deserialize, Serialize};
|
||||||
use std::collections::{BTreeMap, BTreeSet};
|
use std::collections::{BTreeMap, BTreeSet};
|
||||||
|
|
||||||
@ -25,8 +25,8 @@ pub struct Road {
|
|||||||
pub dst_i: StableIntersectionID,
|
pub dst_i: StableIntersectionID,
|
||||||
pub original_center_pts: PolyLine,
|
pub original_center_pts: PolyLine,
|
||||||
pub trimmed_center_pts: PolyLine,
|
pub trimmed_center_pts: PolyLine,
|
||||||
pub fwd_width: f64,
|
pub fwd_width: Distance,
|
||||||
pub back_width: f64,
|
pub back_width: Distance,
|
||||||
pub lane_specs: Vec<lane_specs::LaneSpec>,
|
pub lane_specs: Vec<lane_specs::LaneSpec>,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -90,8 +90,8 @@ impl InitialMap {
|
|||||||
);
|
);
|
||||||
|
|
||||||
let lane_specs = lane_specs::get_lane_specs(r, *stable_id, edits);
|
let lane_specs = lane_specs::get_lane_specs(r, *stable_id, edits);
|
||||||
let mut fwd_width = 0.0;
|
let mut fwd_width = Distance::ZERO;
|
||||||
let mut back_width = 0.0;
|
let mut back_width = Distance::ZERO;
|
||||||
for l in &lane_specs {
|
for l in &lane_specs {
|
||||||
if l.reverse_pts {
|
if l.reverse_pts {
|
||||||
back_width += LANE_THICKNESS;
|
back_width += LANE_THICKNESS;
|
||||||
|
@ -482,5 +482,5 @@ fn validate(map: &Map, steps: &Vec<PathStep>) {
|
|||||||
|
|
||||||
// Negate since BinaryHeap is a max-heap.
|
// Negate since BinaryHeap is a max-heap.
|
||||||
fn dist_to_pri_queue(dist: Distance) -> NotNan<f64> {
|
fn dist_to_pri_queue(dist: Distance) -> NotNan<f64> {
|
||||||
(dist * -1.0).as_ordered()
|
-dist.as_ordered()
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
use ezgui::{Color, GfxCtx};
|
use ezgui::{Color, GfxCtx};
|
||||||
use geom::{Circle, PolyLine};
|
use geom::{Circle, Distance, PolyLine};
|
||||||
|
|
||||||
// TODO Don't just use ezgui constants in this crate, since we want the slight transparency by
|
// TODO Don't just use ezgui constants in this crate, since we want the slight transparency by
|
||||||
// default.
|
// default.
|
||||||
@ -11,11 +11,11 @@ pub const BLACK: Color = Color::BLACK.alpha(0.3);
|
|||||||
pub const SOLID_BLACK: Color = Color::BLACK.alpha(0.9);
|
pub const SOLID_BLACK: Color = Color::BLACK.alpha(0.9);
|
||||||
pub const YELLOW: Color = Color::YELLOW.alpha(0.8);
|
pub const YELLOW: Color = Color::YELLOW.alpha(0.8);
|
||||||
|
|
||||||
pub fn draw_polyline(g: &mut GfxCtx, pl: &PolyLine, thickness: f64, color: Color) {
|
pub fn draw_polyline(g: &mut GfxCtx, pl: &PolyLine, thickness: Distance, color: Color) {
|
||||||
for l in pl.lines() {
|
for l in pl.lines() {
|
||||||
g.draw_line(color, thickness, &l);
|
g.draw_line(color, thickness, &l);
|
||||||
}
|
}
|
||||||
let radius = 0.5;
|
let radius = Distance::meters(0.5);
|
||||||
let pts = pl.points();
|
let pts = pl.points();
|
||||||
assert!(pts.len() >= 2);
|
assert!(pts.len() >= 2);
|
||||||
for pt in pts {
|
for pt in pts {
|
||||||
|
@ -1,13 +1,13 @@
|
|||||||
use crate::common::{draw_polyline, SOLID_BLACK, YELLOW};
|
use crate::common::{draw_polyline, SOLID_BLACK, YELLOW};
|
||||||
use ezgui::{Color, GfxCtx};
|
use ezgui::{Color, GfxCtx};
|
||||||
use geom::{PolyLine, Pt2D};
|
use geom::{Distance, PolyLine, Pt2D};
|
||||||
|
|
||||||
// Copied from map_model; no need to have to rebuild that crate
|
// Copied from map_model; no need to have to rebuild that crate
|
||||||
const LANE_THICKNESS: f64 = 2.5;
|
const LANE_THICKNESS: Distance = Distance::const_meters(2.5);
|
||||||
|
|
||||||
#[allow(clippy::unreadable_literal)]
|
#[allow(clippy::unreadable_literal)]
|
||||||
pub fn run(g: &mut GfxCtx) {
|
pub fn run(g: &mut GfxCtx) {
|
||||||
let thin = 0.25;
|
let thin = Distance::meters(0.25);
|
||||||
let shift1_width = LANE_THICKNESS * 0.5;
|
let shift1_width = LANE_THICKNESS * 0.5;
|
||||||
let shift2_width = LANE_THICKNESS * 1.5;
|
let shift2_width = LANE_THICKNESS * 1.5;
|
||||||
|
|
||||||
@ -80,5 +80,5 @@ pub fn draw_lane(g: &mut GfxCtx, pl: &PolyLine, color: Color) {
|
|||||||
g.draw_polygon(color, &pl.make_polygons(LANE_THICKNESS));
|
g.draw_polygon(color, &pl.make_polygons(LANE_THICKNESS));
|
||||||
|
|
||||||
// Debug the center points
|
// Debug the center points
|
||||||
draw_polyline(g, pl, 0.25, SOLID_BLACK);
|
draw_polyline(g, pl, Distance::meters(0.25), SOLID_BLACK);
|
||||||
}
|
}
|
||||||
|
@ -1,11 +1,11 @@
|
|||||||
use crate::common::{draw_polyline, BLACK, RED};
|
use crate::common::{draw_polyline, BLACK, RED};
|
||||||
use ezgui::GfxCtx;
|
use ezgui::GfxCtx;
|
||||||
use geom::{PolyLine, Pt2D};
|
use geom::{Distance, PolyLine, Pt2D};
|
||||||
|
|
||||||
#[allow(clippy::unreadable_literal)]
|
#[allow(clippy::unreadable_literal)]
|
||||||
pub fn run(g: &mut GfxCtx, labels: &mut Vec<(Pt2D, String)>) {
|
pub fn run(g: &mut GfxCtx, labels: &mut Vec<(Pt2D, String)>) {
|
||||||
let thin = 1.0;
|
let thin = Distance::meters(1.0);
|
||||||
let width = 50.0;
|
let width = Distance::meters(50.0);
|
||||||
|
|
||||||
// TODO retain this as a regression test
|
// TODO retain this as a regression test
|
||||||
let center_pts = PolyLine::new(
|
let center_pts = PolyLine::new(
|
||||||
|
@ -7,7 +7,6 @@ mod trim_polyline;
|
|||||||
|
|
||||||
use ezgui::{Canvas, EventLoopMode, GfxCtx, Key, Prerender, Text, UserInput, GUI};
|
use ezgui::{Canvas, EventLoopMode, GfxCtx, Key, Prerender, Text, UserInput, GUI};
|
||||||
use geom::Pt2D;
|
use geom::Pt2D;
|
||||||
use std::f64;
|
|
||||||
use std::process;
|
use std::process;
|
||||||
|
|
||||||
pub struct UI {
|
pub struct UI {
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
use crate::common::{draw_polyline, BLACK, BLUE, GREEN, RED};
|
use crate::common::{draw_polyline, BLACK, BLUE, GREEN, RED};
|
||||||
use ezgui::GfxCtx;
|
use ezgui::GfxCtx;
|
||||||
use geom::{PolyLine, Pt2D};
|
use geom::{Distance, PolyLine, Pt2D};
|
||||||
|
|
||||||
pub fn run(p3_offset: (f64, f64), g: &mut GfxCtx, labels: &mut Vec<(Pt2D, String)>) {
|
pub fn run(p3_offset: (f64, f64), g: &mut GfxCtx, labels: &mut Vec<(Pt2D, String)>) {
|
||||||
macro_rules! point {
|
macro_rules! point {
|
||||||
@ -17,9 +17,9 @@ pub fn run(p3_offset: (f64, f64), g: &mut GfxCtx, labels: &mut Vec<(Pt2D, String
|
|||||||
};
|
};
|
||||||
}*/
|
}*/
|
||||||
|
|
||||||
let thin = 1.0;
|
let thin = Distance::meters(1.0);
|
||||||
let thick = 5.0;
|
let thick = Distance::meters(5.0);
|
||||||
let shift_away = 50.0;
|
let shift_away = Distance::meters(50.0);
|
||||||
|
|
||||||
point!(p1, Pt2D::new(100.0, 100.0));
|
point!(p1, Pt2D::new(100.0, 100.0));
|
||||||
point!(p2, Pt2D::new(110.0, 200.0));
|
point!(p2, Pt2D::new(110.0, 200.0));
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
use crate::common::{draw_polyline, BLUE, GREEN, RED};
|
use crate::common::{draw_polyline, BLUE, GREEN, RED};
|
||||||
use ezgui::GfxCtx;
|
use ezgui::GfxCtx;
|
||||||
use geom::{Circle, PolyLine, Pt2D};
|
use geom::{Circle, Distance, PolyLine, Pt2D};
|
||||||
|
|
||||||
#[allow(clippy::unreadable_literal)]
|
#[allow(clippy::unreadable_literal)]
|
||||||
pub fn run(g: &mut GfxCtx) {
|
pub fn run(g: &mut GfxCtx) {
|
||||||
@ -20,12 +20,12 @@ pub fn run(g: &mut GfxCtx) {
|
|||||||
|
|
||||||
let (hit, _) = vertical_pl.intersection(&horiz_pl).unwrap();
|
let (hit, _) = vertical_pl.intersection(&horiz_pl).unwrap();
|
||||||
if false {
|
if false {
|
||||||
g.draw_circle(BLUE, &Circle::new(hit, 1.0));
|
g.draw_circle(BLUE, &Circle::new(hit, Distance::meters(1.0)));
|
||||||
} else {
|
} else {
|
||||||
vertical_pl = vertical_pl.get_slice_ending_at(hit).unwrap();
|
vertical_pl = vertical_pl.get_slice_ending_at(hit).unwrap();
|
||||||
horiz_pl = horiz_pl.get_slice_ending_at(hit).unwrap();
|
horiz_pl = horiz_pl.get_slice_ending_at(hit).unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
draw_polyline(g, &vertical_pl, 0.25, RED);
|
draw_polyline(g, &vertical_pl, Distance::meters(0.25), RED);
|
||||||
draw_polyline(g, &horiz_pl, 0.25, GREEN);
|
draw_polyline(g, &horiz_pl, Distance::meters(0.25), GREEN);
|
||||||
}
|
}
|
||||||
|
@ -859,7 +859,7 @@ impl DrivingSimState {
|
|||||||
1.0 - progress
|
1.0 - progress
|
||||||
};
|
};
|
||||||
// TODO we're assuming the parking lane is to the right of us!
|
// TODO we're assuming the parking lane is to the right of us!
|
||||||
base_body.shift_right(project_away_ratio * LANE_THICKNESS)
|
base_body.shift_right(LANE_THICKNESS * project_away_ratio)
|
||||||
} else {
|
} else {
|
||||||
base_body
|
base_body
|
||||||
};
|
};
|
||||||
|
@ -142,7 +142,7 @@ impl Vehicle {
|
|||||||
speed: Speed,
|
speed: Speed,
|
||||||
dist: Distance,
|
dist: Distance,
|
||||||
) -> Result<Acceleration, Error> {
|
) -> Result<Acceleration, Error> {
|
||||||
if dist < EPSILON_DIST * -1.0 {
|
if dist < -EPSILON_DIST {
|
||||||
return Err(Error::new(format!(
|
return Err(Error::new(format!(
|
||||||
"{} called accel_to_stop_in_dist({}, {}) with negative distance",
|
"{} called accel_to_stop_in_dist({}, {}) with negative distance",
|
||||||
self.id, speed, dist
|
self.id, speed, dist
|
||||||
|
@ -3,7 +3,7 @@ mod model;
|
|||||||
use crate::model::{BuildingID, Direction, Model, ID};
|
use crate::model::{BuildingID, Direction, Model, ID};
|
||||||
use aabb_quadtree::QuadTree;
|
use aabb_quadtree::QuadTree;
|
||||||
use ezgui::{Canvas, Color, EventLoopMode, GfxCtx, Key, Prerender, Text, UserInput, Wizard, GUI};
|
use ezgui::{Canvas, Color, EventLoopMode, GfxCtx, Key, Prerender, Text, UserInput, Wizard, GUI};
|
||||||
use geom::Line;
|
use geom::{Distance, Line};
|
||||||
use map_model::raw_data::{StableIntersectionID, StableRoadID};
|
use map_model::raw_data::{StableIntersectionID, StableRoadID};
|
||||||
use std::{env, process};
|
use std::{env, process};
|
||||||
|
|
||||||
@ -210,7 +210,7 @@ impl GUI<Text> for UI {
|
|||||||
if let Some(cursor) = self.canvas.get_cursor_in_map_space() {
|
if let Some(cursor) = self.canvas.get_cursor_in_map_space() {
|
||||||
g.draw_line(
|
g.draw_line(
|
||||||
Color::GREEN,
|
Color::GREEN,
|
||||||
5.0,
|
Distance::meters(5.0),
|
||||||
&Line::new(self.model.get_i_center(i1), cursor),
|
&Line::new(self.model.get_i_center(i1), cursor),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -8,9 +8,9 @@ use serde_derive::{Deserialize, Serialize};
|
|||||||
use std::collections::BTreeMap;
|
use std::collections::BTreeMap;
|
||||||
use std::mem;
|
use std::mem;
|
||||||
|
|
||||||
const INTERSECTION_RADIUS: f64 = 5.0;
|
const INTERSECTION_RADIUS: Distance = Distance::const_meters(5.0);
|
||||||
const BUILDING_LENGTH: f64 = 30.0;
|
const BUILDING_LENGTH: f64 = 30.0;
|
||||||
const CENTER_LINE_THICKNESS: f64 = 0.5;
|
const CENTER_LINE_THICKNESS: Distance = Distance::const_meters(0.5);
|
||||||
|
|
||||||
const HIGHLIGHT_COLOR: Color = Color::CYAN;
|
const HIGHLIGHT_COLOR: Color = Color::CYAN;
|
||||||
|
|
||||||
@ -99,7 +99,7 @@ impl Road {
|
|||||||
|
|
||||||
for (idx, lt) in self.lanes.fwd.iter().enumerate() {
|
for (idx, lt) in self.lanes.fwd.iter().enumerate() {
|
||||||
let polygon = base
|
let polygon = base
|
||||||
.shift_right(((idx as f64) + 0.5) * LANE_THICKNESS)
|
.shift_right(LANE_THICKNESS * ((idx as f64) + 0.5))
|
||||||
.make_polygons(LANE_THICKNESS);
|
.make_polygons(LANE_THICKNESS);
|
||||||
g.draw_polygon(
|
g.draw_polygon(
|
||||||
if highlight_fwd {
|
if highlight_fwd {
|
||||||
@ -112,7 +112,7 @@ impl Road {
|
|||||||
}
|
}
|
||||||
for (idx, lt) in self.lanes.back.iter().enumerate() {
|
for (idx, lt) in self.lanes.back.iter().enumerate() {
|
||||||
let polygon = base
|
let polygon = base
|
||||||
.shift_left(((idx as f64) + 0.5) * LANE_THICKNESS)
|
.shift_left(LANE_THICKNESS * ((idx as f64) + 0.5))
|
||||||
.make_polygons(LANE_THICKNESS);
|
.make_polygons(LANE_THICKNESS);
|
||||||
g.draw_polygon(
|
g.draw_polygon(
|
||||||
if highlight_back {
|
if highlight_back {
|
||||||
|
@ -80,7 +80,7 @@ fn test_accel_to_stop_in_dist(vehicle: Vehicle, orig_dist_left: Distance, orig_s
|
|||||||
speed = new_speed;
|
speed = new_speed;
|
||||||
dist_left -= dist_covered;
|
dist_left -= dist_covered;
|
||||||
|
|
||||||
if dist_left < EPSILON_DIST * -1.0 {
|
if dist_left < -EPSILON_DIST {
|
||||||
println!(" Result: speed {}, dist_left {}", speed, dist_left);
|
println!(" Result: speed {}, dist_left {}", speed, dist_left);
|
||||||
panic!("We overshot too much!");
|
panic!("We overshot too much!");
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user