use osm data for actual building height (#340)

This commit is contained in:
Michael Kirk 2020-09-22 11:59:50 -07:00 committed by GitHub
parent 59fec852a8
commit 848251fca4
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 25 additions and 14 deletions

View File

@ -5,8 +5,6 @@ use crate::options::{CameraAngle, Options};
use crate::render::{DrawOptions, Renderable, OUTLINE_THICKNESS};
use geom::{Angle, Distance, Line, Polygon, Pt2D, Ring};
use map_model::{Building, BuildingID, Map, OffstreetParking, NORMAL_LANE_THICKNESS};
use rand::{Rng, SeedableRng};
use rand_xorshift::XorShiftRng;
use std::cell::RefCell;
use widgetry::{Color, Drawable, EventCtx, GeomBatch, GfxCtx, Line, Text};
@ -73,10 +71,11 @@ impl DrawBuilding {
_ => unreachable!(),
};
// TODO For now, blindly guess the building height
let max_height = 15.0;
let mut rng = XorShiftRng::seed_from_u64(bldg.id.0 as u64);
let height = Distance::meters(rng.gen_range(1.0, max_height));
let bldg_height_per_level = 3.5;
// In downtown areas, really tall buildings look kind of ridculous next to
// everything else. So we artifically compress the number of levels a bit.
let bldg_rendered_meters = bldg_height_per_level * bldg.levels.powf(0.8);
let height = Distance::meters(bldg_rendered_meters);
let map_bounds = map.get_gps_bounds().to_bounds();
let (map_width, map_height) = (map_bounds.width(), map_bounds.height());
@ -122,8 +121,8 @@ impl DrawBuilding {
.unwrap_or(0.0);
// smaller z renders above larger
let scale_factor = map_length + max_height;
let groundfloor_z = (distance_from_projection_axis) / scale_factor - 1.0;
let scale_factor = map_length;
let groundfloor_z = distance_from_projection_axis / scale_factor - 1.0;
let roof_z = groundfloor_z - height.inner_meters() / scale_factor;
// TODO Some buildings have holes in them

View File

@ -57,16 +57,31 @@ pub fn make_all_buildings(
};
let id = BuildingID(results.len());
let mut rng = XorShiftRng::seed_from_u64(orig_id.inner() as u64);
// TODO is it worth using height or building:height as an alternative if not tagged?
let levels = b
.osm_tags
.get("building:levels")
.and_then(|x| x.parse::<f64>().ok())
.unwrap_or(1.0);
results.push(Building {
id,
polygon: b.polygon.clone(),
levels,
address: get_address(&b.osm_tags, sidewalk_pos.lane(), map),
name: NamePerLanguage::new(&b.osm_tags),
orig_id,
label_center: b.polygon.polylabel(),
amenities: b.amenities.clone(),
bldg_type: classify_bldg(&b.osm_tags, &b.amenities, b.polygon.area(), &mut rng),
bldg_type: classify_bldg(
&b.osm_tags,
&b.amenities,
levels,
b.polygon.area(),
&mut rng,
),
parking: if let Some(n) = b.public_garage_name.clone() {
OffstreetParking::PublicGarage(n, b.num_parking_spots)
} else {
@ -117,6 +132,7 @@ fn get_address(tags: &Tags, sidewalk: LaneID, map: &Map) -> String {
fn classify_bldg(
tags: &Tags,
amenities: &BTreeSet<(NamePerLanguage, String)>,
levels: f64,
ground_area_sq_meters: f64,
rng: &mut XorShiftRng,
) -> BuildingType {
@ -124,11 +140,6 @@ fn classify_bldg(
let mut commercial = false;
// TODO is it worth using height or building:height as an alternative if not tagged?
let levels = tags
.get("building:levels")
.and_then(|x| x.parse::<f64>().ok())
.unwrap_or(1.0);
let area_sq_meters = levels * ground_area_sq_meters;
// These are (name, amenity type) pairs, produced by get_bldg_amenities in

View File

@ -26,6 +26,7 @@ impl fmt::Display for BuildingID {
pub struct Building {
pub id: BuildingID,
pub polygon: Polygon,
pub levels: f64,
pub address: String,
pub name: Option<NamePerLanguage>,
pub orig_id: osm::OsmID,