Skip to content

Commit

Permalink
Try merging intersections with concave hull instead. #114
Browse files Browse the repository at this point in the history
  • Loading branch information
dabreegster committed Dec 29, 2020
1 parent 17665a3 commit 172dbf3
Show file tree
Hide file tree
Showing 3 changed files with 32 additions and 5 deletions.
26 changes: 22 additions & 4 deletions game/src/sandbox/uber_turns.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ use geom::{ArrowCap, Polygon};
use map_gui::render::{DrawOptions, BIG_ARROW_THICKNESS};
use map_gui::tools::PopupMsg;
use map_gui::ID;
use map_model::{IntersectionCluster, IntersectionID, PathConstraints};
use map_model::{IntersectionCluster, IntersectionID, Map, PathConstraints, RoadID};
use widgetry::{
Btn, Checkbox, Color, DrawBaselayer, Drawable, EventCtx, GeomBatch, GfxCtx,
HorizontalAlignment, Key, Line, Panel, SimpleState, State, Text, TextExt, VerticalAlignment,
Expand Down Expand Up @@ -282,12 +282,17 @@ impl MergeIntersections {
.aligned(HorizontalAlignment::Center, VerticalAlignment::TopInset)
.build(ctx);

// Just take the convex hull of all the original intersection polygons
// Just take the concave hull of all the original intersection polygons and the interior
// roads
let map = &app.primary.map;
let mut polygons = Vec::new();
for r in find_interior_roads(map, &merge) {
polygons.push(map.get_r(r).get_thick_polygon(map));
}
for i in merge {
polygons.push(app.primary.map.get_i(i).polygon.clone());
polygons.push(map.get_i(i).polygon.clone());
}
let merged = Polygon::convex_hull(polygons);
let merged = Polygon::concave_hull(polygons, 0.1);
let batch = GeomBatch::from(vec![(Color::RED.alpha(0.8), merged)]);

SimpleState::new(
Expand Down Expand Up @@ -316,3 +321,16 @@ impl SimpleState<App> for MergeIntersections {
g.redraw(&self.draw);
}
}

fn find_interior_roads(map: &Map, intersections: &BTreeSet<IntersectionID>) -> BTreeSet<RoadID> {
let mut roads = BTreeSet::new();
for i in intersections {
for r in &map.get_i(*i).roads {
let road = map.get_r(*r);
if intersections.contains(&road.src_i) && intersections.contains(&road.dst_i) {
roads.insert(road.id);
}
}
}
roads
}
6 changes: 6 additions & 0 deletions geom/src/polygon.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ use std::convert::TryFrom;
use std::fmt;

use geo::algorithm::area::Area;
use geo::algorithm::concave_hull::ConcaveHull;
use geo::algorithm::convex_hull::ConvexHull;
use geo_booleanop::boolean::BooleanOp;
use serde::{Deserialize, Serialize};
Expand Down Expand Up @@ -307,6 +308,11 @@ impl Polygon {
mp.convex_hull().into()
}

pub fn concave_hull(list: Vec<Polygon>, concavity: f64) -> Polygon {
let mp: geo::MultiPolygon<f64> = list.into_iter().map(|p| to_geo(p.points())).collect();
mp.concave_hull(concavity).into()
}

pub fn polylabel(&self) -> Pt2D {
let pt = polylabel::polylabel(&to_geo(&self.points()), &1.0).unwrap();
Pt2D::new(pt.x(), pt.y())
Expand Down
5 changes: 4 additions & 1 deletion geom/src/ring.rs
Original file line number Diff line number Diff line change
Expand Up @@ -202,6 +202,9 @@ impl From<Ring> for geo::LineString<f64> {

impl From<geo::LineString<f64>> for Ring {
fn from(line_string: geo::LineString<f64>) -> Self {
Self::must_new(line_string.0.into_iter().map(Pt2D::from).collect())
// Dedupe adjacent points. Only needed for results from concave hull.
let mut pts: Vec<Pt2D> = line_string.0.into_iter().map(Pt2D::from).collect();
pts.dedup();
Self::must_new(pts)
}
}

0 comments on commit 172dbf3

Please sign in to comment.