mirror of
https://github.com/a-b-street/abstreet.git
synced 2024-11-24 09:24:26 +03:00
center pedestrians on bldg front paths, and group them into crowds when
appropriate
This commit is contained in:
parent
d40002bb17
commit
f39bb7c6cb
@ -2,9 +2,6 @@
|
||||
|
||||
## Boundary clipping
|
||||
|
||||
- lakes missing from huge_seattle
|
||||
- just connecting the ends of ways doesnt always work well
|
||||
- maybe increase the Bounds for areas, and let clipping clean up later?
|
||||
- some border intersections have weird OOBish geometry, or the arrows look weird
|
||||
- simplify border node detection, only do it in convert_osm?
|
||||
|
||||
@ -69,17 +66,12 @@
|
||||
- iterative process... have to redo affected roads and intersections
|
||||
- we havent filtered buildings by proximity to sidewalk yet
|
||||
- if we dont filter at all, we pick up some houseboats! :) should draw water...
|
||||
- undo disabled traffic signal assertion
|
||||
|
||||
## Map edits
|
||||
|
||||
- lane type can affect border intersections
|
||||
- lane type can affect turn idx
|
||||
- assert turns are the same
|
||||
- crash when loading some edits (priori->bikelanez)
|
||||
- edit an intersection first, then change lanes to destroy turns. need to recalculate the policy, preserving edits!
|
||||
- just revert intersection and warn
|
||||
- or store overrides more granularly and warn or do something reasonable
|
||||
|
||||
## Sim bugs/tests needed
|
||||
|
||||
|
@ -20,7 +20,6 @@
|
||||
|
||||
- optionally limit canvas scrolling/zooming to some map bounds
|
||||
- start context menu when left click releases and we're not dragging
|
||||
- distinguish hints from status of modal menus, for hiding purposes
|
||||
- move context menus out of ezgui
|
||||
- simplify/remove UserInput.
|
||||
- maybe separate impls for context, wizard, modal menu make sense.
|
||||
|
@ -3,7 +3,7 @@ use crate::render::{AgentColorScheme, DrawCtx, DrawOptions, Renderable, OUTLINE_
|
||||
use ezgui::{Canvas, Color, Drawable, GeomBatch, GfxCtx, Line, Prerender, Text};
|
||||
use geom::{Circle, Distance, PolyLine, Polygon};
|
||||
use map_model::{Map, LANE_THICKNESS};
|
||||
use sim::{DrawPedCrowdInput, DrawPedestrianInput, PedestrianID};
|
||||
use sim::{DrawPedCrowdInput, DrawPedestrianInput, PedCrowdLocation, PedestrianID};
|
||||
|
||||
pub struct DrawPedestrian {
|
||||
pub id: PedestrianID,
|
||||
@ -201,12 +201,21 @@ impl DrawPedCrowd {
|
||||
prerender: &Prerender,
|
||||
cs: &ColorScheme,
|
||||
) -> DrawPedCrowd {
|
||||
// TODO front path
|
||||
let pl_slice = input.on.exact_slice(input.low, input.high, map);
|
||||
let pl_shifted = if input.contraflow {
|
||||
pl_slice.shift_left(LANE_THICKNESS / 4.0).unwrap()
|
||||
} else {
|
||||
pl_slice.shift_right(LANE_THICKNESS / 4.0).unwrap()
|
||||
let pl_shifted = match input.location {
|
||||
PedCrowdLocation::Sidewalk(on, contraflow) => {
|
||||
let pl_slice = on.exact_slice(input.low, input.high, map);
|
||||
if contraflow {
|
||||
pl_slice.shift_left(LANE_THICKNESS / 4.0).unwrap()
|
||||
} else {
|
||||
pl_slice.shift_right(LANE_THICKNESS / 4.0).unwrap()
|
||||
}
|
||||
}
|
||||
PedCrowdLocation::FrontPath(b) => map
|
||||
.get_b(b)
|
||||
.front_path
|
||||
.line
|
||||
.to_polyline()
|
||||
.exact_slice(input.low, input.high),
|
||||
};
|
||||
let blob = pl_shifted.make_polygons(LANE_THICKNESS / 2.0);
|
||||
let draw_default = prerender.upload_borrowed(vec![(cs.get("pedestrian"), &blob)]);
|
||||
@ -223,7 +232,10 @@ impl DrawPedCrowd {
|
||||
members: input.members,
|
||||
blob_pl: pl_shifted,
|
||||
blob,
|
||||
zorder: input.on.get_zorder(map),
|
||||
zorder: match input.location {
|
||||
PedCrowdLocation::Sidewalk(on, _) => on.get_zorder(map),
|
||||
PedCrowdLocation::FrontPath(_) => 0,
|
||||
},
|
||||
draw_default,
|
||||
label,
|
||||
}
|
||||
|
@ -27,7 +27,7 @@ pub use self::trips::{TripCount, TripResult};
|
||||
pub(crate) use self::trips::{TripLeg, TripManager};
|
||||
pub use crate::render::{
|
||||
AgentMetadata, CarStatus, DontDrawAgents, DrawCarInput, DrawPedCrowdInput, DrawPedestrianInput,
|
||||
GetDrawAgents, UnzoomedAgent,
|
||||
GetDrawAgents, PedCrowdLocation, UnzoomedAgent,
|
||||
};
|
||||
use abstutil::Cloneable;
|
||||
use geom::{Distance, Duration, Pt2D, Speed};
|
||||
|
@ -1,8 +1,8 @@
|
||||
use crate::{
|
||||
AgentID, AgentMetadata, Command, CreatePedestrian, DistanceInterval, DrawPedCrowdInput,
|
||||
DrawPedestrianInput, Event, IntersectionSimState, ParkingSimState, ParkingSpot, PedestrianID,
|
||||
Scheduler, SidewalkPOI, SidewalkSpot, TimeInterval, TransitSimState, TripID, TripManager,
|
||||
TripPositions, UnzoomedAgent,
|
||||
DrawPedestrianInput, Event, IntersectionSimState, ParkingSimState, ParkingSpot,
|
||||
PedCrowdLocation, PedestrianID, Scheduler, SidewalkPOI, SidewalkSpot, TimeInterval,
|
||||
TransitSimState, TripID, TripManager, TripPositions, UnzoomedAgent,
|
||||
};
|
||||
use abstutil::{deserialize_multimap, serialize_multimap, MultiMap};
|
||||
use geom::{Distance, Duration, Line, PolyLine, Speed};
|
||||
@ -329,8 +329,6 @@ impl WalkingSimState {
|
||||
let mut backwards: Vec<(PedestrianID, Distance)> = Vec::new();
|
||||
let mut front_path: MultiMap<BuildingID, (PedestrianID, Distance)> = MultiMap::new();
|
||||
|
||||
let mut loners: Vec<DrawPedestrianInput> = Vec::new();
|
||||
|
||||
for id in self.peds_per_traversable.get(on) {
|
||||
let ped = &self.peds[id];
|
||||
let dist = ped.get_dist_along(now, map);
|
||||
@ -350,14 +348,13 @@ impl WalkingSimState {
|
||||
forwards.push((*id, dist));
|
||||
}
|
||||
}
|
||||
PedState::LeavingBuilding(b, _) | PedState::EnteringBuilding(b, _) => {
|
||||
// TODO Group on front paths too.
|
||||
if false {
|
||||
// TODO Distance along the front path
|
||||
front_path.insert(b, (*id, dist));
|
||||
} else {
|
||||
loners.push(ped.get_draw_ped(now, map));
|
||||
}
|
||||
PedState::LeavingBuilding(b, ref int) => {
|
||||
let len = map.get_b(b).front_path.line.length();
|
||||
front_path.insert(b, (*id, int.percent(now) * len));
|
||||
}
|
||||
PedState::EnteringBuilding(b, ref int) => {
|
||||
let len = map.get_b(b).front_path.line.length();
|
||||
front_path.insert(b, (*id, (1.0 - int.percent(now)) * len));
|
||||
}
|
||||
PedState::StartingToBike(_, _, _)
|
||||
| PedState::FinishingBiking(_, _, _)
|
||||
@ -369,29 +366,38 @@ impl WalkingSimState {
|
||||
}
|
||||
|
||||
let mut crowds: Vec<DrawPedCrowdInput> = Vec::new();
|
||||
let on_len = on.length(map);
|
||||
let mut loners: Vec<DrawPedestrianInput> = Vec::new();
|
||||
|
||||
// For each group, sort by distance along. Attempt to bundle into intervals.
|
||||
for (idx, mut group) in vec![forwards, backwards]
|
||||
.into_iter()
|
||||
.chain(
|
||||
front_path
|
||||
.consume()
|
||||
.values()
|
||||
.map(|set| set.iter().cloned().collect::<Vec<_>>()),
|
||||
for (mut group, location, on_len) in vec![
|
||||
(
|
||||
forwards,
|
||||
PedCrowdLocation::Sidewalk(on, false),
|
||||
on.length(map),
|
||||
),
|
||||
(
|
||||
backwards,
|
||||
PedCrowdLocation::Sidewalk(on, true),
|
||||
on.length(map),
|
||||
),
|
||||
]
|
||||
.into_iter()
|
||||
.chain(front_path.consume().into_iter().map(|(b, set)| {
|
||||
(
|
||||
set.into_iter().collect::<Vec<_>>(),
|
||||
PedCrowdLocation::FrontPath(b),
|
||||
map.get_b(b).front_path.line.length(),
|
||||
)
|
||||
.enumerate()
|
||||
{
|
||||
})) {
|
||||
if group.is_empty() {
|
||||
continue;
|
||||
}
|
||||
group.sort_by_key(|(_, dist)| *dist);
|
||||
let (individs, these_crowds) = find_crowds(group, on);
|
||||
let (individs, these_crowds) = find_crowds(group, location);
|
||||
for id in individs {
|
||||
loners.push(self.peds[&id].get_draw_ped(now, map));
|
||||
}
|
||||
for mut crowd in these_crowds {
|
||||
crowd.contraflow = idx == 1;
|
||||
// Clamp the distance intervals.
|
||||
if crowd.low < Distance::ZERO {
|
||||
crowd.low = Distance::ZERO;
|
||||
@ -491,11 +497,7 @@ impl Pedestrian {
|
||||
(
|
||||
front_path
|
||||
.line
|
||||
.dist_along(time_int.percent(now) * front_path.line.length())
|
||||
.project_away(
|
||||
LANE_THICKNESS / 4.0,
|
||||
front_path.line.angle().rotate_degs(90.0),
|
||||
),
|
||||
.dist_along(time_int.percent(now) * front_path.line.length()),
|
||||
front_path.line.angle(),
|
||||
)
|
||||
}
|
||||
@ -505,11 +507,7 @@ impl Pedestrian {
|
||||
front_path
|
||||
.line
|
||||
.reverse()
|
||||
.dist_along(time_int.percent(now) * front_path.line.length())
|
||||
.project_away(
|
||||
LANE_THICKNESS / 4.0,
|
||||
front_path.line.angle().rotate_degs(-90.0),
|
||||
),
|
||||
.dist_along(time_int.percent(now) * front_path.line.length()),
|
||||
front_path.line.angle().opposite(),
|
||||
)
|
||||
}
|
||||
@ -628,7 +626,7 @@ impl PedState {
|
||||
// The crowds returned here may have low/high values extending up to radius past the real geometry.
|
||||
fn find_crowds(
|
||||
input: Vec<(PedestrianID, Distance)>,
|
||||
on: Traversable,
|
||||
location: PedCrowdLocation,
|
||||
) -> (Vec<PedestrianID>, Vec<DrawPedCrowdInput>) {
|
||||
let mut loners = Vec::new();
|
||||
let mut crowds = Vec::new();
|
||||
@ -637,9 +635,8 @@ fn find_crowds(
|
||||
let mut current_crowd = DrawPedCrowdInput {
|
||||
low: input[0].1 - radius,
|
||||
high: input[0].1 + radius,
|
||||
contraflow: false,
|
||||
members: vec![input[0].0],
|
||||
on,
|
||||
location: location.clone(),
|
||||
};
|
||||
for (id, dist) in input.into_iter().skip(1) {
|
||||
// If the pedestrian circles would overlap at all,
|
||||
@ -656,9 +653,8 @@ fn find_crowds(
|
||||
current_crowd = DrawPedCrowdInput {
|
||||
low: dist - radius,
|
||||
high: dist + radius,
|
||||
contraflow: false,
|
||||
members: vec![id],
|
||||
on,
|
||||
location: location.clone(),
|
||||
};
|
||||
}
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
use crate::{CarID, PedestrianID, VehicleType};
|
||||
use geom::{Angle, Distance, Duration, PolyLine, Pt2D};
|
||||
use map_model::{Map, Traversable, TurnID};
|
||||
use map_model::{BuildingID, Map, Traversable, TurnID};
|
||||
|
||||
// Intermediate structures so that sim and game crates don't have a cyclic dependency.
|
||||
#[derive(Clone)]
|
||||
@ -25,9 +25,15 @@ pub struct AgentMetadata {
|
||||
pub struct DrawPedCrowdInput {
|
||||
pub low: Distance,
|
||||
pub high: Distance,
|
||||
pub contraflow: bool,
|
||||
pub members: Vec<PedestrianID>,
|
||||
pub on: Traversable,
|
||||
pub location: PedCrowdLocation,
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
pub enum PedCrowdLocation {
|
||||
// bool is contraflow
|
||||
Sidewalk(Traversable, bool),
|
||||
FrontPath(BuildingID),
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
|
Loading…
Reference in New Issue
Block a user