making small_seattle fully convert, with some less messy hacks. added it

as a test!
This commit is contained in:
Dustin Carlino 2019-02-11 15:59:36 -08:00
parent a3b03952cf
commit 6da48c28c1
6 changed files with 98 additions and 51 deletions

View File

@ -43,6 +43,10 @@ pub fn make_all_buildings(
let sidewalk_pt = lanes[sidewalk_pos.lane().0]
.dist_along(sidewalk_pos.dist_along())
.0;
if sidewalk_pt.epsilon_eq(bldg_center.into()) {
warn!("Skipping a building because front path has 0 length");
continue;
}
let line = trim_front_path(&points, Line::new(bldg_center.into(), sidewalk_pt));
let id = BuildingID(results.len());

View File

@ -4,6 +4,11 @@ use abstutil::Timer;
use std::collections::{BTreeSet, HashSet};
pub fn fix_ramps(m: &mut InitialMap, timer: &mut Timer) {
if m.roads.len() > 15_000 {
error!("Skipping fix_ramps because map is too big! TODO: Optimize me!");
return;
}
// Look for road center lines that hit an intersection polygon that isn't one of their
// endpoints.
timer.start_iter(

View File

@ -139,11 +139,17 @@ fn generalized_trim_back(
// How could something perpendicular to a shifted polyline never hit the original
// polyline? Also, find the hit closest to the intersection -- this matters for
// very curvy roads, like highway ramps.
let trim_to = road_center.reversed().intersection_infinite(&perp).unwrap();
let trimmed = road_center.get_slice_ending_at(trim_to).unwrap();
if let Some(trimmed) = road_center
.reversed()
.intersection_infinite(&perp)
.and_then(|trim_to| road_center.get_slice_ending_at(trim_to))
{
if trimmed.length() < shortest_center.length() {
shortest_center = trimmed;
}
} else {
warn!("{} and {} hit, but the perpendicular never hit the original center line, or the trimmed thing is empty", r1, r2);
}
// We could also do the update for r2, but we'll just get to it later.
}
@ -199,6 +205,9 @@ fn generalized_trim_back(
// Include collisions between polylines of adjacent roads, so the polygon doesn't cover area
// not originally covered by the thick road bands.
// It's apparently safe to always take the second_half here.
if fwd_pl.length() >= geom::EPSILON_DIST * 3.0
&& adj_fwd_pl.length() >= geom::EPSILON_DIST * 3.0
{
if let Some((hit, _)) = fwd_pl.second_half().intersection(&adj_fwd_pl.second_half()) {
endpoints.push(hit);
} else if r.original_endpoint(i) != roads[&adj_fwd_id].original_endpoint(i) {
@ -206,12 +215,16 @@ fn generalized_trim_back(
// TODO This cuts some corners nicely, but also causes lots of problems.
// If the original roads didn't end at the same intersection (due to intersection
// merging), then use infinite lines.
if let Some((hit, _)) = fwd_pl.second_half().intersection(&adj_fwd_pl.second_half())
if let Some((hit, _)) =
fwd_pl.second_half().intersection(&adj_fwd_pl.second_half())
{
endpoints.push(hit);
}
}
}
} else {
warn!("Excluding collision between original polylines of {} and something, because stuff's too short", id);
}
// Shift those final centers out again to find the main endpoints for the polygon.
if r.dst_i == i {
@ -222,6 +235,9 @@ fn generalized_trim_back(
endpoints.push(r.trimmed_center_pts.shift_right(r.fwd_width).first_pt());
}
if back_pl.length() >= geom::EPSILON_DIST * 3.0
&& adj_back_pl.length() >= geom::EPSILON_DIST * 3.0
{
if let Some((hit, _)) = back_pl
.second_half()
.intersection(&adj_back_pl.second_half())
@ -238,6 +254,9 @@ fn generalized_trim_back(
}
}
}
} else {
warn!("Excluding collision between original polylines of {} and something, because stuff's too short", id);
}
}
// TODO Caller will close off the polygon. Does that affect our dedupe?
Pt2D::approx_dedupe(endpoints, Distance::meters(0.1))

View File

@ -8,6 +8,8 @@ use nbez::{Bez3o, BezCurve, Point2d};
use std::collections::{BTreeSet, HashSet};
use std::iter;
// TODO Add proper warnings when the geometry is too small to handle.
pub fn make_all_turns(i: &Intersection, roads: &Vec<Road>, lanes: &Vec<Lane>) -> Vec<Turn> {
if i.intersection_type == IntersectionType::Border {
return Vec::new();
@ -73,7 +75,7 @@ fn make_vehicle_turns(i: &Intersection, all_roads: &Vec<Road>, lanes: &Vec<Lane>
lane_types.remove(&LaneType::Parking);
lane_types.remove(&LaneType::Sidewalk);
let mut result = Vec::new();
let mut result: Vec<Option<Turn>> = Vec::new();
for lane_type in lane_types.into_iter() {
if i.is_dead_end() {
@ -139,7 +141,7 @@ fn make_vehicle_turns(i: &Intersection, all_roads: &Vec<Road>, lanes: &Vec<Lane>
}
}
result
result.into_iter().filter_map(|x| x).collect()
}
fn match_up_lanes(
@ -147,7 +149,7 @@ fn match_up_lanes(
i: IntersectionID,
incoming: &Vec<LaneID>,
outgoing: &Vec<LaneID>,
) -> Vec<Turn> {
) -> Vec<Option<Turn>> {
let mut result = Vec::new();
if incoming.len() < outgoing.len() {
// Arbitrarily use the leftmost incoming lane to handle the excess.
@ -185,7 +187,7 @@ fn make_vehicle_turns_for_dead_end(
roads: &Vec<Road>,
lanes: &Vec<Lane>,
lane_type: LaneType,
) -> Vec<Turn> {
) -> Vec<Option<Turn>> {
let road = &roads[i.roads.iter().next().unwrap().0];
let incoming = filter_vehicle_lanes(road.incoming_lanes(i.id), lane_type);
let outgoing = filter_vehicle_lanes(road.outgoing_lanes(i.id), lane_type);
@ -219,18 +221,22 @@ fn make_walking_turns(i: &Intersection, all_roads: &Vec<Road>, lanes: &Vec<Lane>
lanes,
wraparound_get(&roads, (idx1 as isize) - 1).outgoing_lanes(i.id),
) {
if !l1.last_pt().epsilon_eq(l2.first_pt()) {
result.push(Turn {
id: turn_id(i.id, l1.id, l2.id),
turn_type: TurnType::SharedSidewalkCorner,
geom: PolyLine::new(vec![l1.last_pt(), l2.first_pt()]),
lookup_idx: 0,
});
}
if !l2.first_pt().epsilon_eq(l1.last_pt()) {
result.push(Turn {
id: turn_id(i.id, l2.id, l1.id),
turn_type: TurnType::SharedSidewalkCorner,
geom: PolyLine::new(vec![l2.first_pt(), l1.last_pt()]),
lookup_idx: 0,
});
}
} else if roads.len() > 2 {
// See if we need to add a crosswalk over this adjacent road.
// TODO This is brittle; I could imagine having to cross two adjacent highway
@ -249,6 +255,10 @@ fn make_walking_turns(i: &Intersection, all_roads: &Vec<Road>, lanes: &Vec<Lane>
}
fn make_crosswalks(i: IntersectionID, l1: &Lane, l2: &Lane) -> Vec<Turn> {
if l1.last_pt().epsilon_eq(l2.first_pt()) {
return Vec::new();
}
// Jut out a bit into the intersection, cross over, then jut back in.
let line = Line::new(l1.last_pt(), l2.first_pt()).shift_right(LANE_THICKNESS / 2.0);
let geom_fwds = PolyLine::new(vec![l1.last_pt(), line.pt1(), line.pt2(), l2.first_pt()]);
@ -297,11 +307,15 @@ fn filter_lanes(lanes: &Vec<(LaneID, LaneType)>, filter: LaneType) -> Vec<LaneID
.collect()
}
fn make_vehicle_turn(lanes: &Vec<Lane>, i: IntersectionID, l1: LaneID, l2: LaneID) -> Turn {
fn make_vehicle_turn(lanes: &Vec<Lane>, i: IntersectionID, l1: LaneID, l2: LaneID) -> Option<Turn> {
let src = &lanes[l1.0];
let dst = &lanes[l2.0];
let turn_type = TurnType::from_angles(src.last_line().angle(), dst.first_line().angle());
if src.last_pt().epsilon_eq(dst.first_pt()) {
return None;
}
let geom = if turn_type == TurnType::Straight {
PolyLine::new(vec![src.last_pt(), dst.first_pt()])
} else {
@ -332,12 +346,12 @@ fn make_vehicle_turn(lanes: &Vec<Lane>, i: IntersectionID, l1: LaneID, l2: LaneI
))
};
Turn {
Some(Turn {
id: turn_id(i, l1, l2),
turn_type,
geom,
lookup_idx: 0,
}
})
}
fn to_pt(pt: Pt2D) -> Point2d<f64> {

View File

@ -85,7 +85,12 @@ impl ControlTrafficSignal {
intersection: IntersectionID,
) -> Option<ControlTrafficSignal> {
if map.get_turns_in_intersection(intersection).is_empty() {
panic!("{} has no turns", intersection);
error!("{} has no turns", intersection);
return Some(ControlTrafficSignal {
id: intersection,
cycles: Vec::new(),
changed: false,
});
}
let mut cycles = Vec::new();

View File

@ -51,21 +51,21 @@ pub fn run(t: &mut TestRunner) {
}
});
t.run_slow("bigger_maps", |_| {
t.run_slow("bigger_map_loads", |_| {
map_model::Map::new(
"../data/raw_maps/23rd.abst",
map_model::MapEdits::new("23rd"),
&mut abstutil::Timer::new("raw to map"),
)
.expect("23rd broke");
});
// TODO This one has lots more problems (turns with no geometry) and even when the map is
// made successfully, can't load it in the UI without OOMing.
/*map_model::Map::new(
t.run_slow("biggest_map_loads", |_| {
map_model::Map::new(
"../data/raw_maps/small_seattle.abst",
map_model::MapEdits::new("small_seattle"),
&mut abstutil::Timer::new("raw to map"),
)
.expect("small_seattle broke");*/
.expect("small_seattle broke");
});
}