random fixes in the map importer to try to import a bunch of new cities.

not too successful, but made progress.
This commit is contained in:
Dustin Carlino 2020-08-07 10:24:58 -07:00
parent 128e649236
commit 62ed91925a
7 changed files with 87 additions and 75 deletions

View File

@ -266,7 +266,7 @@ pub fn extract_osm(map: &mut RawMap, opts: &Options, timer: &mut Timer) -> OsmEx
},
);
}
Err(err) => println!("Skipping building: {}", err),
Err(err) => println!("Skipping building {}: {}", id, err),
}
} else if rel.tags.is("type", "route") {
map.bus_routes
@ -423,7 +423,7 @@ fn is_road(tags: &mut Tags, opts: &Options) -> bool {
// Service roads can represent lots of things, most of which we don't want to keep yet. What's
// allowed here is just based on what's been encountered so far in Seattle and Kraków.
if highway == "service" && !tags.is("psv", "yes") && !tags.is("bus", "yes") {
if highway == "service" && !tags.is_any("psv", vec!["yes", "bus"]) && !tags.is("bus", "yes") {
return false;
}
@ -602,6 +602,9 @@ fn glue_multipolygon(
polygons.push(ring.to_polygon());
return polygons;
}
if result.len() < 2 {
return Vec::new();
}
if let Some(poly) = glue_to_boundary(PolyLine::must_new(result.clone()), boundary) {
polygons.push(poly);
} else {
@ -802,9 +805,13 @@ fn multipoly_geometry(
Ok(Polygon::buggy_new(outer.remove(0)))
}
} else {
let mut inner_rings = Vec::new();
for pts in inner {
inner_rings.push(Ring::new(pts)?);
}
Ok(Polygon::with_holes(
Ring::must_new(outer.pop().unwrap()),
inner.into_iter().map(Ring::must_new).collect(),
Ring::new(outer.pop().unwrap())?,
inner_rings,
))
}
}

View File

@ -2,7 +2,7 @@ use crate::make::initial::{Intersection, Road};
use crate::osm;
use crate::raw::{DrivingSide, OriginalIntersection, OriginalRoad};
use abstutil::{wraparound_get, Timer};
use geom::{Distance, Line, PolyLine, Polygon, Pt2D};
use geom::{Distance, Line, PolyLine, Polygon, Pt2D, Ring, EPSILON_DIST};
use std::collections::BTreeMap;
const DEGENERATE_INTERSECTION_HALF_LENGTH: Distance = Distance::const_meters(2.5);
@ -15,7 +15,7 @@ pub fn intersection_polygon(
i: &Intersection,
roads: &mut BTreeMap<OriginalRoad, Road>,
timer: &mut Timer,
) -> (Vec<Pt2D>, Vec<(String, Polygon)>) {
) -> (Polygon, Vec<(String, Polygon)>) {
if i.roads.is_empty() {
panic!("{} has no roads", i.id);
}
@ -72,7 +72,7 @@ fn generalized_trim_back(
i: OriginalIntersection,
lines: &Vec<(OriginalRoad, Line, PolyLine, PolyLine)>,
timer: &mut Timer,
) -> (Vec<Pt2D>, Vec<(String, Polygon)>) {
) -> (Polygon, Vec<(String, Polygon)>) {
let mut debug = Vec::new();
let mut road_lines: Vec<(OriginalRoad, PolyLine)> = Vec::new();
@ -104,16 +104,15 @@ fn generalized_trim_back(
};
// Always trim back a minimum amount, if possible.
let mut shortest_center = if road_center.length()
>= DEGENERATE_INTERSECTION_HALF_LENGTH + 3.0 * geom::EPSILON_DIST
{
road_center.exact_slice(
Distance::ZERO,
road_center.length() - DEGENERATE_INTERSECTION_HALF_LENGTH,
)
} else {
road_center.clone()
};
let mut shortest_center =
if road_center.length() >= DEGENERATE_INTERSECTION_HALF_LENGTH + 3.0 * EPSILON_DIST {
road_center.exact_slice(
Distance::ZERO,
road_center.length() - DEGENERATE_INTERSECTION_HALF_LENGTH,
)
} else {
road_center.clone()
};
for (r2, pl2) in &road_lines {
if r1 == r2 {
@ -204,9 +203,7 @@ 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 fwd_pl.length() >= EPSILON_DIST * 3.0 && adj_fwd_pl.length() >= EPSILON_DIST * 3.0 {
if let Some((hit, _)) = fwd_pl.second_half().intersection(&adj_fwd_pl.second_half()) {
endpoints.push(hit);
}
@ -243,9 +240,7 @@ fn generalized_trim_back(
);
}
if back_pl.length() >= geom::EPSILON_DIST * 3.0
&& adj_back_pl.length() >= geom::EPSILON_DIST * 3.0
{
if back_pl.length() >= EPSILON_DIST * 3.0 && adj_back_pl.length() >= EPSILON_DIST * 3.0 {
if let Some((hit, _)) = back_pl
.second_half()
.intersection(&adj_back_pl.second_half())
@ -274,13 +269,13 @@ fn generalized_trim_back(
deduped = Pt2D::approx_dedupe(deduped, Distance::meters(0.1));
deduped = close_off_polygon(deduped);
if main_result.len() == deduped.len() {
(main_result, debug)
(Ring::must_new(main_result).to_polygon(), debug)
} else {
timer.warn(format!(
"{}'s polygon has weird repeats, forcibly removing points",
i
));
(deduped, debug)
(Ring::must_new(deduped).to_polygon(), debug)
}
// TODO Or always sort points? Helps some cases, hurts other for downtown Seattle.
@ -296,7 +291,7 @@ fn deadend(
roads: &mut BTreeMap<OriginalRoad, Road>,
i: OriginalIntersection,
lines: &Vec<(OriginalRoad, Line, PolyLine, PolyLine)>,
) -> (Vec<Pt2D>, Vec<(String, Polygon)>) {
) -> (Polygon, Vec<(String, Polygon)>) {
let len = DEGENERATE_INTERSECTION_HALF_LENGTH * 4.0;
let (id, _, mut pl_a, mut pl_b) = lines[0].clone();
@ -308,7 +303,7 @@ fn deadend(
pl_b = pl_b.extend_to_length(len + 1.5 * DEGENERATE_INTERSECTION_HALF_LENGTH);
let r = roads.get_mut(&id).unwrap();
let len_with_buffer = len + 3.0 * geom::EPSILON_DIST;
let len_with_buffer = len + 3.0 * EPSILON_DIST;
let trimmed = if r.trimmed_center_pts.length() >= len_with_buffer {
if r.src_i == i {
r.trimmed_center_pts = r
@ -356,7 +351,10 @@ fn deadend(
}
endpts.dedup();
(close_off_polygon(endpts), Vec::new())
(
Ring::must_new(close_off_polygon(endpts)).to_polygon(),
Vec::new(),
)
}
fn close_off_polygon(mut pts: Vec<Pt2D>) -> Vec<Pt2D> {
@ -381,7 +379,7 @@ fn on_off_ramp(
roads: &mut BTreeMap<OriginalRoad, Road>,
i: OriginalIntersection,
lines: Vec<(OriginalRoad, Line, PolyLine, PolyLine)>,
) -> Option<(Vec<Pt2D>, Vec<(String, Polygon)>)> {
) -> Option<(Polygon, Vec<(String, Polygon)>)> {
if lines.len() != 3 {
return None;
}
@ -520,7 +518,7 @@ fn on_off_ramp(
};
roads.get_mut(&thick_id).unwrap().trimmed_center_pts = trimmed_thick;
// Give the merge point some length
if extra.length() <= 2.0 * DEGENERATE_INTERSECTION_HALF_LENGTH {
if extra.length() <= 2.0 * DEGENERATE_INTERSECTION_HALF_LENGTH + 3.0 * EPSILON_DIST {
return None;
}
let extra = extra.exact_slice(2.0 * DEGENERATE_INTERSECTION_HALF_LENGTH, extra.length());
@ -577,7 +575,11 @@ fn on_off_ramp(
endpoints.dedup();
let center = Pt2D::center(&endpoints);
endpoints.sort_by_key(|pt| pt.angle_to(center).normalized_degrees() as i64);
Some((close_off_polygon(endpoints), debug))
endpoints.dedup();
Some((
Ring::must_new(close_off_polygon(endpoints)).to_polygon(),
debug,
))
//let dummy = geom::Circle::new(orig_lines[0].3.last_pt(), Distance::meters(3.0)).to_polygon();
//Some((close_off_polygon(dummy.into_points()), debug))

View File

@ -5,7 +5,7 @@ pub use self::geometry::intersection_polygon;
use crate::raw::{DrivingSide, OriginalIntersection, OriginalRoad, RawMap, RawRoad};
use crate::IntersectionType;
use abstutil::{Tags, Timer};
use geom::{Bounds, Circle, Distance, PolyLine, Pt2D};
use geom::{Bounds, Circle, Distance, PolyLine, Polygon, Pt2D};
use lane_specs::LaneSpec;
use std::collections::{BTreeMap, BTreeSet};
@ -48,7 +48,7 @@ impl Road {
pub struct Intersection {
// Redundant but useful to embed
pub id: OriginalIntersection,
pub polygon: Vec<Pt2D>,
pub polygon: Polygon,
pub roads: BTreeSet<OriginalRoad>,
pub intersection_type: IntersectionType,
pub elevation: Distance,
@ -67,7 +67,8 @@ impl InitialMap {
*id,
Intersection {
id: *id,
polygon: Vec::new(),
// Dummy thing to start with
polygon: Circle::new(Pt2D::new(0.0, 0.0), Distance::meters(1.0)).to_polygon(),
roads: BTreeSet::new(),
intersection_type: i.intersection_type,
elevation: i.elevation,
@ -142,11 +143,7 @@ impl InitialMap {
} else {
r.trimmed_center_pts.last_pt()
};
let mut pts = Circle::new(pt, Distance::meters(3.0))
.to_polygon()
.into_points();
pts.push(pts[0]);
i.polygon = pts;
i.polygon = Circle::new(pt, Distance::meters(3.0)).to_polygon();
// Also don't attempt to make TurnGroups later!
i.intersection_type = IntersectionType::StopSign;

View File

@ -17,7 +17,7 @@ use crate::{
};
use abstutil::{Parallelism, Timer};
use enumset::EnumSet;
use geom::{Bounds, Distance, FindClosest, HashablePt2D, Ring, Speed, EPSILON_DIST};
use geom::{Bounds, Distance, FindClosest, HashablePt2D, Speed, EPSILON_DIST};
use std::collections::{BTreeMap, BTreeSet, HashMap, HashSet};
impl Map {
@ -67,7 +67,7 @@ impl Map {
let id = IntersectionID(idx);
map.intersections.push(Intersection {
id,
polygon: Ring::must_new(i.polygon.clone()).to_polygon(),
polygon: i.polygon.clone(),
turns: BTreeSet::new(),
elevation: i.elevation,
// Might change later

View File

@ -117,25 +117,27 @@ pub fn make_all_parking_lots(
.map(|(id, _, _)| id)
.collect();
let (polylines, rings) = Ring::split_points(pts).unwrap();
'PL: for pl in polylines {
for id in &candidates {
let lot = &mut results[id.0];
for segment in lot.polygon.clip_polyline(&pl) {
lot.aisles.push(segment);
continue 'PL;
}
}
}
'RING: for ring in rings {
for id in &candidates {
let lot = &mut results[id.0];
for segment in lot.polygon.clip_ring(&ring) {
lot.aisles.push(segment);
continue 'RING;
if let Ok((polylines, rings)) = Ring::split_points(pts) {
'PL: for pl in polylines {
for id in &candidates {
let lot = &mut results[id.0];
for segment in lot.polygon.clip_polyline(&pl) {
lot.aisles.push(segment);
continue 'PL;
}
}
}
'RING: for ring in rings {
for id in &candidates {
let lot = &mut results[id.0];
for segment in lot.polygon.clip_ring(&ring) {
lot.aisles.push(segment);
continue 'RING;
}
}
}
}
// TODO Should plumb along the OSM ID too and warn here
}
timer.start_iter("generate parking lot spots", results.len());
@ -192,18 +194,19 @@ 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::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)
&& line_valid(lot_polygon, aisles, l2, &finalized_lines)
&& line_valid(lot_polygon, aisles, &back, &finalized_lines)
{
let avg_angle = (l1.angle() + l2.angle()) / 2.0;
spots.push((back.middle().unwrap(), avg_angle.opposite()));
finalized_lines.push(l1.clone());
finalized_lines.push(l2.clone());
finalized_lines.push(back);
if let Some(back) = Line::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)
&& line_valid(lot_polygon, aisles, l2, &finalized_lines)
&& line_valid(lot_polygon, aisles, &back, &finalized_lines)
{
let avg_angle = (l1.angle() + l2.angle()) / 2.0;
spots.push((back.middle().unwrap(), avg_angle.opposite()));
finalized_lines.push(l1.clone());
finalized_lines.push(l2.clone());
finalized_lines.push(back);
}
}
}
}

View File

@ -68,10 +68,13 @@ impl IntersectionCluster {
continue;
}
panic!(
// TODO Saw this is New Orleans
println!(
"Need a cluster containing {:?} for turn restrictions, but there's more than one \
existing cluster that partly covers it. Union them?"
existing cluster that partly covers it. Union them?",
members
);
return Vec::new();
}
clusters

View File

@ -1,7 +1,7 @@
use crate::make::initial::lane_specs::get_lane_specs;
use crate::{osm, AreaType, IntersectionType, LaneType, MapConfig};
use abstutil::{deserialize_btreemap, serialize_btreemap, Tags, Timer};
use geom::{Angle, Distance, GPSBounds, Line, PolyLine, Polygon, Pt2D, Ring};
use geom::{Angle, Circle, Distance, GPSBounds, Line, PolyLine, Polygon, Pt2D};
use petgraph::graphmap::DiGraphMap;
use serde::{Deserialize, Serialize};
use std::collections::{BTreeMap, BTreeSet};
@ -189,7 +189,7 @@ impl RawMap {
let i = initial::Intersection {
id,
polygon: Vec::new(),
polygon: Circle::new(Pt2D::new(0.0, 0.0), Distance::meters(1.0)).to_polygon(),
roads: self.roads_per_intersection(id).into_iter().collect(),
intersection_type: self.intersections[&id].intersection_type,
elevation: self.intersections[&id].elevation,
@ -202,10 +202,10 @@ impl RawMap {
);
}
let (i_pts, debug) =
let (poly, debug) =
initial::intersection_polygon(self.config.driving_side, &i, &mut roads, timer);
(
Ring::must_new(i_pts).to_polygon(),
poly,
roads
.values()
.map(|r| r.trimmed_center_pts.make_polygons(2.0 * r.half_width))