dashed white lines on big roads

This commit is contained in:
Dustin Carlino 2018-06-27 11:45:13 -07:00
parent 5e362cdfc5
commit 849a132a6a
6 changed files with 77 additions and 35 deletions

View File

@ -59,6 +59,7 @@ The polyline problem:
- https://stackoverflow.com/questions/36475254/polylines-outline-construction-drawing-thick-polylines
- Will lengths change? Is this a problem?
- Drawing cars as rectangles is funky, because if their front is aligned to a new line segment, their back juts into the center of the road
- https://hal.inria.fr/hal-00907326/document
- Seemingly: line intersection of shifted lines yields the new joint point, which looks good.
@ -102,10 +103,15 @@ wait slow down even more -- before any of this change, lanes on adjacent roads s
- osm tags and such would ideally be part of a master road
- automated regression test / quality control
- find all overlapping polygons, only some are expected
- find a way to show the problem easily
- geo rust!
- improve intersection geom?
- bad polygons when shifted lines invert points
- arguably, these could be a case when there's not enough room to shift away.
- render dashed white lines for multiple driving lanes
- render trees?
- revisit parks/water (as parcels / areas, maybe)
@ -114,6 +120,7 @@ wait slow down even more -- before any of this change, lanes on adjacent roads s
- make final Map serializable too
- useful to precompute sidewalk paths
- reorg map making
- small geometry refactorings (like shifting polyline on opposite side, reversing pts)
- MORE CLEANUP: do we really need to hash pt2d's often? Should maybe settle and use Vec2d more

View File

@ -24,6 +24,12 @@
0.0,
1.0
],
"DrivingLaneMarking": [
1.0,
1.0,
1.0,
1.0
],
"Parking": [
0.2,
0.2,

View File

@ -14,6 +14,7 @@ pub enum Colors {
Debug,
BrightDebug,
Road,
DrivingLaneMarking,
Parking,
ParkingMarking,
Sidewalk,

View File

@ -52,7 +52,7 @@ impl DrawRoad {
marking_lines: match road.lane_type {
map_model::LaneType::Sidewalk => calculate_sidewalk_lines(road),
map_model::LaneType::Parking => calculate_parking_lines(road),
map_model::LaneType::Driving => Vec::new(),
map_model::LaneType::Driving => calculate_driving_lines(road),
},
lane_type: road.lane_type,
}
@ -83,8 +83,7 @@ impl DrawRoad {
let extra_marking_color = match self.lane_type {
map_model::LaneType::Sidewalk => cs.get(Colors::SidewalkMarking),
map_model::LaneType::Parking => cs.get(Colors::ParkingMarking),
// this case doesn't matter yet, no dotted lines yet...
map_model::LaneType::Driving => cs.get(Colors::Road),
map_model::LaneType::Driving => cs.get(Colors::DrivingLaneMarking),
};
let extra_marking = graphics::Line::new(
extra_marking_color,
@ -255,3 +254,35 @@ fn calculate_parking_lines(road: &map_model::Road) -> Vec<(Vec2d, Vec2d)> {
result
}
fn calculate_driving_lines(road: &map_model::Road) -> Vec<(Vec2d, Vec2d)> {
// Only multi-lane roads have dashed white lines.
if road.offset == 0 {
return Vec::new();
}
// Project left, so reverse the points.
let mut center_pts = road.lane_center_pts.clone();
center_pts.reverse();
let lane_edge_pts = map_model::shift_polyline(geometry::LANE_THICKNESS / 2.0, &center_pts);
// This is an incredibly expensive way to compute dashed polyines, and it doesn't follow bends
// properly. Just a placeholder.
let lane_len = geometry::polyline_len(&lane_edge_pts);
let dash_separation = 2.0 * si::M;
let dash_len = 1.0 * si::M;
let mut dashes: Vec<(Vec2d, Vec2d)> = Vec::new();
let mut start = dash_separation;
loop {
if start + dash_len >= lane_len - dash_separation {
break;
}
let (pt1, _) = geometry::dist_along(&lane_edge_pts, start);
let (pt2, _) = geometry::dist_along(&lane_edge_pts, start + dash_len);
dashes.push((pt1.to_vec(), pt2.to_vec()));
start += dash_len + dash_separation;
}
dashes
}

View File

@ -83,6 +83,8 @@ pub fn point_in_circle(x: f64, y: f64, center: Vec2d, radius: f64) -> bool {
}*/
// TODO borrow or copy?
// TODO valid to do euclidean distance on screen-space points that're formed from
// Haversine?
pub(crate) fn euclid_dist((pt1, pt2): (Pt2D, Pt2D)) -> si::Meter<f64> {
return ((pt1.x() - pt2.x()).powi(2) + (pt1.y() - pt2.y()).powi(2)).sqrt() * si::M;
}
@ -200,3 +202,27 @@ pub fn angle(from: &Pt2D, to: &Pt2D) -> angles::Radian<f64> {
}
theta * angles::RAD
}
pub fn dist_along(pts: &Vec<Pt2D>, dist_along: si::Meter<f64>) -> (Pt2D, angles::Radian<f64>) {
let mut dist_left = dist_along;
for (idx, pair) in pts.windows(2).enumerate() {
let length = euclid_dist((pair[0], pair[1]));
let epsilon = if idx == pts.len() - 2 {
EPSILON_METERS
} else {
0.0 * si::M
};
if dist_left <= length + epsilon {
let vec = safe_dist_along_line((&pair[0], &pair[1]), dist_left);
return (Pt2D::new(vec[0], vec[1]), angle(&pair[0], &pair[1]));
}
dist_left -= length;
}
panic!("{} is longer than pts by {}", dist_along, dist_left);
}
pub fn polyline_len(pts: &Vec<Pt2D>) -> si::Meter<f64> {
pts.windows(2).fold(0.0 * si::M, |so_far, pair| {
so_far + euclid_dist((pair[0], pair[1]))
})
}

View File

@ -80,40 +80,11 @@ impl Road {
}
pub fn dist_along(&self, dist_along: si::Meter<f64>) -> (Pt2D, geometry::angles::Radian<f64>) {
// TODO valid to do euclidean distance on screen-space points that're formed from
// Haversine?
let mut dist_left = dist_along;
for (idx, pair) in self.lane_center_pts.windows(2).enumerate() {
let length = geometry::euclid_dist((pair[0], pair[1]));
let epsilon = if idx == self.lane_center_pts.len() - 2 {
geometry::EPSILON_METERS
} else {
0.0 * si::M
};
if dist_left <= length + epsilon {
let vec = geometry::safe_dist_along_line((&pair[0], &pair[1]), dist_left);
return (
Pt2D::new(vec[0], vec[1]),
geometry::angle(&pair[0], &pair[1]),
);
}
dist_left -= length;
}
panic!(
"{} is longer than road {:?}'s {}. dist_left is {}",
dist_along,
self.id,
self.length(),
dist_left
);
geometry::dist_along(&self.lane_center_pts, dist_along)
}
pub fn length(&self) -> si::Meter<f64> {
self.lane_center_pts
.windows(2)
.fold(0.0 * si::M, |so_far, pair| {
so_far + geometry::euclid_dist((pair[0], pair[1]))
})
geometry::polyline_len(&self.lane_center_pts)
}
pub fn dump_debug(&self) {