Commit 0d695c0a authored by Rick Gruber-Riemer's avatar Rick Gruber-Riemer

Parameters for building levels and height

parent d11a086a
......@@ -57,11 +57,15 @@ def random_LOD():
if r < 0.7: return 1 # 70% rough
return 0 # 30% bare
default_height=12.
random_level_height = random_number(float, 3.1, 3.6)
random_levels = random_number(int, 2, 5)
#random_levels_skyscraper = random_number(int, 10, 60)
random_levels_skyscraper = random_number('gauss', 35, 10)
def random_level_height(place="city"):
""" Calculates the height for each level of a building based on place and random factor"""
#FIXME: other places (e.g. village)
return random.uniform(parameters.BUILDING_CITY_LEVEL_HEIGHT_MIN, parameters.BUILDING_CITY_LEVEL_HEIGHT_MAX)
def random_levels(place="city"):
""" Calculates the number of building levels based on place and random factor"""
#FIXME: other places
return random.randint(parameters.BUILDING_CITY_LEVELS_MIN, parameters.BUILDING_CITY_LEVELS_MAX)
def check_height(building_height, t):
"""check if a texture t fits the building height (h)
......@@ -279,7 +283,6 @@ def analyse(buildings, static_objects, transform, elev, facades, roofs):
tools.stats.nodes_simplified += nodes_simplified
tools.stats.nodes_ground += b.nnodes_ground
# -- fix inverted faces and compute edge length
lenX = np.zeros((b.nnodes_ground))
crossX = 0.
......@@ -300,53 +303,70 @@ def analyse(buildings, static_objects, transform, elev, facades, roofs):
lenX = np.roll(lenX, 1)
X[0] = X[-1]
level_height = random_level_height()
# ***********************
# skip buildings outside elevation raster
# ***********************
if elev(vec2d(X[0])) == -9999:
print "-9999"
continue
# -- LOWI year 2525
# ***********************
# Check for static objects nearby
# ***********************
# FIXME: which radius? Or use centroid point? make radius a parameter
radius = 5. # alternative: radius = max(lenX)
# -- query_ball_point may return funny lists [[], [], .. ]
# filter these
if static_objects:
nearby = static_tree.query_ball_point(X, radius)
nearby = [x for x in nearby if x]
if len(nearby):
for i in range(b.nnodes_ground):
tools.stats.debug2.write("%g %g\n" % (X[i,0], X[i,1]))
# print "nearby:", nearby
# for n in nearby:
# print "-->", s[n]
try:
print "Static objects nearby. Skipping ", b.name, len(nearby)
except:
print "FIXME: Encoding problem", b.name.encode('ascii', 'ignore')
#for n in nearby:
# print static_objects.objs[n].name,
#print
tools.stats.skipped_nearby += 1
continue
# *************
# Check area
# *************
if False == analyse_area(buildings, b):
tools.stats.skipped_small += 1
continue
# ***********************
# Work on height and levels
# ***********************
# -- LOWI year 2525
if False:
if b.area >= 1500:
b.levels = int(random_levels_skyscraper())
b.height = float(b.levels) * level_height
b.levels = int(random.gauss(35, 10)) # random_number(int, 10, 60)
b.height = float(b.levels) * random_level_height()
if b.area < 1500:
#if b.area < 200. or (b.area < 500. and random.uniform(0,1) < 0.5):
tools.stats.skipped_small += 1
continue
# try OSM height first
# catch exceptions, since height might be "5 m" instead of "5"
try:
height = float(b.height)
if height > 1.: b.levels = (height*1.)/level_height
except:
height = 0.
pass
# failing that, try OSM levels
if height < 1:
if float(b.levels) > 0:
pass
#print "have levels", b.levels
else:
# failing that, use random levels
b.levels = random_levels()
if b.area < 40: b.levels = min(b.levels, 2)
b.height = float(b.levels) * level_height
#print "hei", b.height, b.levels
analyse_level_height(b)
if b.height < parameters.BUILDING_MIN_HEIGHT:
print "Skipping small building with height < building_min_height parameter"
tools.stats.skipped_small += 1
continue
# -- skipping buildings smaller than min_area plus a percentage of buildings under a certain area
if b.area < parameters.BUILDING_MIN_AREA or (b.area < parameters.BUILDING_REDUCE_THRESHOLD and random.uniform(0,1) < parameters.BUILDING_REDUCE_RATE):
#if b.area < 20. : # FIXME use limits.area_min:
#print "Skipping small building (area)"
tools.stats.skipped_small += 1
continue
# ***********************
# Work on roof
# ***********************
# -- roof is controlled by two flags:
# bool b.roof_separate: whether or not to include roof as separate model
# useful for
......@@ -355,7 +375,6 @@ def analyse(buildings, static_objects, transform, elev, facades, roofs):
# replace by roof_type? flat --> no separate model
# gable --> separate model
# ACs -"-
b.roof_separate = False
b.roof_flat = True
......@@ -364,53 +383,17 @@ def analyse(buildings, static_objects, transform, elev, facades, roofs):
b.roof_separate = True
b.roof_flat = False # -- pitched roof
# -- no gable roof on tall buildings
if b.levels > 5:
b.roof_flat = True
b.roof_separate = False
# FIXME: roof_ACs = True
# b.roof_flat = True
# b.roof_separate = False
requires = []
if b.roof_separate and not b.roof_flat:
requires.append('age:old')
requires.append('compat:roof-gable')
# -- static objects nearby?
# FIXME: which radius? Or use centroid point?
#radius = max(lenX)
radius = 5.
# -- query_ball_point may return funny lists [[], [], .. ]
# filter these
if static_objects:
nearby = static_tree.query_ball_point(X, radius)
nearby = [x for x in nearby if x]
if len(nearby):
for i in range(b.nnodes_ground):
tools.stats.debug2.write("%g %g\n" % (X[i,0], X[i,1]))
# print "nearby:", nearby
# for n in nearby:
# print "-->", s[n]
try:
print "Static objects nearby. Skipping ", b.name, len(nearby)
except:
print "FIXME: Encoding problem", b.name.encode('ascii', 'ignore')
#for n in nearby:
# print static_objects.objs[n].name,
#print
tools.stats.skipped_nearby += 1
continue
# -- skip buildings outside elevation raster
if elev(vec2d(X[0])) == -9999:
print "-9999"
continue
#tools.stats.print_summary()
# if p.area < 200.:
# print "small?", p.area
......@@ -439,6 +422,48 @@ def analyse(buildings, static_objects, transform, elev, facades, roofs):
return new_buildings
def analyse_area(buildings, building):
"""Checks whether a given building's area is too small for inclusion.
FIXME: Exclusion might be skipped if the building touches another building (i.e. an annex)
Returns true if the building should be included (i.e. area is big enough etc.)
"""
if building.area < parameters.BUILDING_MIN_AREA or (building.area < parameters.BUILDING_REDUCE_THRESHOLD
and random.uniform(0,1) < parameters.BUILDING_REDUCE_RATE):
#if parameters.BUILDING_REDUCE_CHECK_TOUCH:
#for k in buildings:
#if k.touches(building): # using Shapely, but buildings have no polygon currently
#return True
return False
return True
def analyse_level_height(building):
"""Determines total height (and number of levels) of a building based on OSM values and other logic"""
level_height = random_level_height()
# try OSM height first
# catch exceptions, since height might be "5 m" instead of "5"
try:
height = float(building.height)
if height > 1.:
building.levels = (height * 1.)/level_height
except:
height = 0.
pass
# failing that, try OSM levels
if height < 1:
if float(building.levels) > 0:
pass
#print "have levels", b.levels
else:
# failing that, use random levels
building.levels = random_levels()
if building.area < parameters.BUILDING_MIN_AREA:
building.levels = min(building.levels, 2)
building.height = float(building.levels) * level_height
def make_lightmap_dict(buildings):
"""make a dictionary: map texture to objects"""
lightmap_dict = {}
......
......@@ -132,7 +132,7 @@ class Building(object):
def __init__(self, osm_id, tags, refs, name, height, levels, stg_typ = None, stg_hdg = None):
self.osm_id = osm_id
self.tags = tags
self.refs = refs
self.refs = refs # the referenced coordinate nodes
self.name = name.encode('ascii', 'ignore') # stg: name
self.stg_typ = stg_typ # stg: OBJECT_SHARED or _STATIC
self.stg_hdg = stg_hdg
......
......@@ -44,12 +44,20 @@ SKIP_LIST = ["Dresden Hauptbahnhof", "Semperoper", "Zwinger", "Hofkirche",
"Residenzschloss Dresden", "Fernsehturm", "Fernsehturm Dresden"]
# Parameters which influence the number of buildings from OSM taken to output
BUILDING_MIN_HEIGHT = 3.4 # The minimum height of a building to be included in output
BUILDING_MIN_HEIGHT = 3.4 # The minimum height of a building to be included in output (does not include roof)
BUILDING_MIN_AREA = 50.0 # The minimum area for a building to be included in output
BUILDING_REDUCE_THRESHOLD = 200.0 # The threshold area of a building below which a rate of buildings get reduced from output
BUILDING_REDUCE_RATE = 0.5 # The rate (between 0 and 1) of buildings below a threshold which get reduced randomly in output
BUILDING_REDUCE_CHECK_TOUCH = False # Before removing a building due to area check whether it is touching another building and therefore should be kept
BUILDING_SIMPLIFY_TOLERANCE = 1.0 # All points in the simplified building will be within the tolerance distance of the original geometry.
# Parameters which influence the height of buildings in info in OSM not available
BUILDING_CITY_LEVELS_MIN = 2
BUILDING_CITY_LEVELS_MAX = 5
BUILDING_CITY_LEVEL_HEIGHT_MIN = 3.1
BUILDING_CITY_LEVEL_HEIGHT_MAX = 3.6
# FIXME: same parameters for place = town, village, suburb
def setParameters(paramDict):
'''
Sets the parameter values from a dictionary read by function readFromFile.
......@@ -139,11 +147,34 @@ def setParameters(paramDict):
floatValue = parseFloat('BUILDING_REDUCE_RATE', paramDict['BUILDING_REDUCE_RATE'])
if None is not floatValue:
BUILDING_REDUCE_RATE = floatValue
global BUILDING_REDUCE_CHECK_TOUCH
if 'BUILDING_REDUCE_CHECK_TOUCH' in paramDict:
BUILDING_REDUCE_CHECK_TOUCH = parseBool(paramDict['BUILDING_REDUCE_CHECK_TOUCH'])
global BUILDING_SIMPLIFY_TOLERANCE
if 'BUILDING_SIMPLIFY_TOLERANCE' in paramDict:
floatValue = parseFloat('BUILDING_SIMPLIFY_TOLERANCE', paramDict['BUILDING_SIMPLIFY_TOLERANCE'])
if None is not floatValue:
BUILDING_SIMPLIFY_TOLERANCE = floatValue
global BUILDING_CITY_LEVELS_MIN
if 'BUILDING_CITY_LEVELS_MIN' in paramDict:
intValue = parseInt('BUILDING_CITY_LEVELS_MIN', paramDict['BUILDING_CITY_LEVELS_MIN'])
if None is not intValue:
BUILDING_CITY_LEVELS_MIN = intValue
global BUILDING_CITY_LEVELS_MAX
if 'BUILDING_CITY_LEVELS_MAX' in paramDict:
intValue = parseInt('BUILDING_CITY_LEVELS_MAX', paramDict['BUILDING_CITY_LEVELS_MAX'])
if None is not intValue:
BUILDING_CITY_LEVELS_MAX = intValue
global BUILDING_CITY_LEVEL_HEIGHT_MIN
if 'BUILDING_CITY_LEVEL_HEIGHT_MIN' in paramDict:
floatValue = parseFloat('BUILDING_CITY_LEVEL_HEIGHT_MIN', paramDict['BUILDING_CITY_LEVEL_HEIGHT_MIN'])
if None is not floatValue:
BUILDING_CITY_LEVEL_HEIGHT_MIN = floatValue
global BUILDING_CITY_LEVEL_HEIGHT_MAX
if 'BUILDING_CITY_LEVEL_HEIGHT_MAX' in paramDict:
floatValue = parseFloat('BUILDING_CITY_LEVEL_HEIGHT_MAX', paramDict['BUILDING_CITY_LEVEL_HEIGHT_MAX'])
if None is not floatValue:
BUILDING_CITY_LEVEL_HEIGHT_MAX = floatValue
def printParams():
'''
......
......@@ -19,5 +19,10 @@ BUILDING_BUILDING_MIN_AREA = 50.0
BUILDING_MIN_HEIGHT = 3.0
BUILDING_REDUCE_RATE = 0.5
BUILDING_REDUCE_THRESHOLD = 200.0
BUILDING_REDUCE_CHECK_TOUCH = False
BUILDING_SIMPLIFY_TOLERANCE = 1.0
BUILDING_CITY_LEVELS_MIN = 2
BUILDING_CITY_LEVELS_MAX = 5
BUILDING_CITY_LEVEL_HEIGHT_MIN = 3.1
BUILDING_CITY_LEVEL_HEIGHT_MAX = 3.6
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment