mirror of
https://github.com/a-b-street/abstreet.git
synced 2024-11-28 12:12:00 +03:00
dashed white lines on big roads
This commit is contained in:
parent
5e362cdfc5
commit
849a132a6a
@ -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
|
||||
|
@ -24,6 +24,12 @@
|
||||
0.0,
|
||||
1.0
|
||||
],
|
||||
"DrivingLaneMarking": [
|
||||
1.0,
|
||||
1.0,
|
||||
1.0,
|
||||
1.0
|
||||
],
|
||||
"Parking": [
|
||||
0.2,
|
||||
0.2,
|
||||
|
@ -14,6 +14,7 @@ pub enum Colors {
|
||||
Debug,
|
||||
BrightDebug,
|
||||
Road,
|
||||
DrivingLaneMarking,
|
||||
Parking,
|
||||
ParkingMarking,
|
||||
Sidewalk,
|
||||
|
@ -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, ¢er_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
|
||||
}
|
||||
|
@ -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]))
|
||||
})
|
||||
}
|
||||
|
@ -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) {
|
||||
|
Loading…
Reference in New Issue
Block a user