draw people inside buildings!

This commit is contained in:
Dustin Carlino 2020-03-27 16:08:38 -07:00
parent e2cc9dbb55
commit 555b793910
3 changed files with 107 additions and 42 deletions

View File

@ -1,10 +1,11 @@
use crate::app::App; use crate::app::App;
use crate::helpers::ID; use crate::helpers::{ColorScheme, ID};
use crate::info::{header_btns, make_table, make_tabs, Details, Tab}; use crate::info::{header_btns, make_table, make_tabs, Details, Tab};
use crate::render::DrawPedestrian;
use ezgui::{Btn, EventCtx, Line, Text, TextExt, Widget}; use ezgui::{Btn, EventCtx, Line, Text, TextExt, Widget};
use geom::Time; use geom::{Angle, Time};
use map_model::BuildingID; use map_model::{Building, BuildingID, LaneID, Traversable, SIDEWALK_THICKNESS};
use sim::{TripMode, TripResult}; use sim::{DrawPedestrianInput, PedestrianID, TripMode, TripResult};
pub fn info(ctx: &mut EventCtx, app: &App, details: &mut Details, id: BuildingID) -> Vec<Widget> { pub fn info(ctx: &mut EventCtx, app: &App, details: &mut Details, id: BuildingID) -> Vec<Widget> {
let mut rows = header(ctx, app, details, id, Tab::BldgInfo(id)); let mut rows = header(ctx, app, details, id, Tab::BldgInfo(id));
@ -165,5 +166,58 @@ fn header(
); );
} }
draw_occupants(
details,
&app.cs,
app.primary.map.get_b(id),
app.primary.sim.bldg_to_people(id).len(),
);
rows rows
} }
fn draw_occupants(details: &mut Details, cs: &ColorScheme, bldg: &Building, num_ppl: usize) {
// TODO Lots of fun ideas here. Have a deterministic simulation based on building ID and time
// to have people "realistically" move around. Draw little floor plans.
let num_rows_cols = (num_ppl as f64).sqrt().ceil() as usize;
let ped_len = SIDEWALK_THICKNESS.inner_meters() / 2.0;
let separation = ped_len * 1.5;
let total_width_height = (num_rows_cols as f64) * (ped_len + separation);
let top_left = bldg
.label_center
.offset(-total_width_height / 2.0, -total_width_height / 2.0);
// TODO Current thing is inefficient and can easily wind up outside the building.
let mut cnt = 0;
'OUTER: for x in 0..num_rows_cols {
for y in 0..num_rows_cols {
DrawPedestrian::geometry(
&mut details.zoomed,
cs,
&DrawPedestrianInput {
id: PedestrianID(cnt),
pos: top_left.offset(
(x as f64) * (ped_len + separation),
(y as f64) * (ped_len + separation),
),
facing: Angle::new_degs(90.0),
waiting_for_turn: None,
preparing_bike: false,
// Both hands and feet!
waiting_for_bus: true,
on: Traversable::Lane(LaneID(0)),
},
0,
);
cnt += 1;
if cnt == num_ppl {
break 'OUTER;
}
}
}
}

View File

@ -20,7 +20,7 @@ pub use crate::render::extra_shape::ExtraShapeID;
pub use crate::render::intersection::{calculate_corners, DrawIntersection}; pub use crate::render::intersection::{calculate_corners, DrawIntersection};
pub use crate::render::lane::DrawLane; pub use crate::render::lane::DrawLane;
pub use crate::render::map::{AgentCache, AgentColorScheme, DrawMap}; pub use crate::render::map::{AgentCache, AgentColorScheme, DrawMap};
use crate::render::pedestrian::{DrawPedCrowd, DrawPedestrian}; pub use crate::render::pedestrian::{DrawPedCrowd, DrawPedestrian};
pub use crate::render::road::DrawRoad; pub use crate::render::road::DrawRoad;
pub use crate::render::traffic_signal::{draw_signal_phase, make_signal_diagram}; pub use crate::render::traffic_signal::{draw_signal_phase, make_signal_diagram};
pub use crate::render::turn::{DrawTurn, DrawTurnGroup}; pub use crate::render::turn::{DrawTurn, DrawTurnGroup};

View File

@ -22,6 +22,40 @@ impl DrawPedestrian {
prerender: &Prerender, prerender: &Prerender,
cs: &ColorScheme, cs: &ColorScheme,
) -> DrawPedestrian { ) -> DrawPedestrian {
let mut draw_default = GeomBatch::new();
DrawPedestrian::geometry(&mut draw_default, cs, &input, step_count);
let radius = SIDEWALK_THICKNESS / 4.0; // TODO make const after const fn is better
let body_circle = Circle::new(input.pos, radius);
if let Some(t) = input.waiting_for_turn {
// A silly idea for peds... use hands to point at their turn?
let angle = map.get_t(t).angle();
draw_default.push(
cs.get("turn arrow"),
PolyLine::new(vec![
input.pos.project_away(radius / 2.0, angle.opposite()),
input.pos.project_away(radius / 2.0, angle),
])
.make_arrow(Distance::meters(0.15))
.unwrap(),
);
}
DrawPedestrian {
id: input.id,
body_circle,
zorder: input.on.get_zorder(map),
draw_default: prerender.upload(draw_default),
}
}
pub fn geometry(
batch: &mut GeomBatch,
cs: &ColorScheme,
input: &DrawPedestrianInput,
step_count: usize,
) {
// TODO Slight issues with rendering small pedestrians: // TODO Slight issues with rendering small pedestrians:
// - route visualization is thick // - route visualization is thick
// - there are little skips when making turns // - there are little skips when making turns
@ -29,8 +63,6 @@ impl DrawPedestrian {
let radius = SIDEWALK_THICKNESS / 4.0; // TODO make const after const fn is better let radius = SIDEWALK_THICKNESS / 4.0; // TODO make const after const fn is better
let body_circle = Circle::new(input.pos, radius); let body_circle = Circle::new(input.pos, radius);
let mut draw_default = GeomBatch::new();
let foot_radius = 0.2 * radius; let foot_radius = 0.2 * radius;
let hand_radius = 0.2 * radius; let hand_radius = 0.2 * radius;
let left_foot_angle = 30.0; let left_foot_angle = 30.0;
@ -68,13 +100,13 @@ impl DrawPedestrian {
let jitter = input.id.0 % 2 == 0; let jitter = input.id.0 % 2 == 0;
let remainder = step_count % 6; let remainder = step_count % 6;
if input.waiting_for_turn.is_some() || input.waiting_for_bus { if input.waiting_for_turn.is_some() || input.waiting_for_bus {
draw_default.push(foot_color, left_foot.to_polygon()); batch.push(foot_color, left_foot.to_polygon());
draw_default.push(foot_color, right_foot.to_polygon()); batch.push(foot_color, right_foot.to_polygon());
draw_default.push(hand_color, left_hand.to_polygon()); batch.push(hand_color, left_hand.to_polygon());
draw_default.push(hand_color, right_hand.to_polygon()); batch.push(hand_color, right_hand.to_polygon());
} else if jitter == (remainder < 3) { } else if jitter == (remainder < 3) {
draw_default.push(foot_color, left_foot.to_polygon()); batch.push(foot_color, left_foot.to_polygon());
draw_default.push( batch.push(
foot_color, foot_color,
Circle::new( Circle::new(
input input
@ -85,8 +117,8 @@ impl DrawPedestrian {
.to_polygon(), .to_polygon(),
); );
draw_default.push(hand_color, right_hand.to_polygon()); batch.push(hand_color, right_hand.to_polygon());
draw_default.push( batch.push(
hand_color, hand_color,
Circle::new( Circle::new(
input input
@ -97,8 +129,8 @@ impl DrawPedestrian {
.to_polygon(), .to_polygon(),
); );
} else { } else {
draw_default.push(foot_color, right_foot.to_polygon()); batch.push(foot_color, right_foot.to_polygon());
draw_default.push( batch.push(
foot_color, foot_color,
Circle::new( Circle::new(
input input
@ -109,8 +141,8 @@ impl DrawPedestrian {
.to_polygon(), .to_polygon(),
); );
draw_default.push(hand_color, left_hand.to_polygon()); batch.push(hand_color, left_hand.to_polygon());
draw_default.push( batch.push(
hand_color, hand_color,
Circle::new( Circle::new(
input input
@ -123,32 +155,11 @@ impl DrawPedestrian {
}; };
let head_circle = Circle::new(input.pos, 0.5 * radius); let head_circle = Circle::new(input.pos, 0.5 * radius);
draw_default.push(zoomed_color_ped(&input, cs), body_circle.to_polygon()); batch.push(zoomed_color_ped(&input, cs), body_circle.to_polygon());
draw_default.push( batch.push(
cs.get_def("pedestrian head", Color::rgb(139, 69, 19)), cs.get_def("pedestrian head", Color::rgb(139, 69, 19)),
head_circle.to_polygon(), head_circle.to_polygon(),
); );
if let Some(t) = input.waiting_for_turn {
// A silly idea for peds... use hands to point at their turn?
let angle = map.get_t(t).angle();
draw_default.push(
cs.get("turn arrow"),
PolyLine::new(vec![
input.pos.project_away(radius / 2.0, angle.opposite()),
input.pos.project_away(radius / 2.0, angle),
])
.make_arrow(Distance::meters(0.15))
.unwrap(),
);
}
DrawPedestrian {
id: input.id,
body_circle,
zorder: input.on.get_zorder(map),
draw_default: prerender.upload(draw_default),
}
} }
} }