Commit 7466ae93 authored by Rick Gruber-Riemer's avatar Rick Gruber-Riemer

* more consistency in use of 'height' -> min_height, body_height, roof_height

* new parameters to determine roof shape if no shape is specified in OSM
* new enumeration for RoofShape
parent 48e3a2e9
This diff is collapsed.
......@@ -520,7 +520,7 @@ def _write_xml(path: str, file_name: str, the_buildings: List[building_lib.Build
for i in np.arange(0, b.nnodes_outer, b.nnodes_outer/4.):
xo = Xo[int(i+0.5), 0] - cluster_offset.x
yo = Xo[int(i+0.5), 1] - cluster_offset.y
zo = b.top_of_roof + 1.5
zo = b.top_of_roof_above_sea_level + 1.5
# <path>cursor.ac</path>
xml.write(textwrap.dedent("""
<model>
......@@ -671,7 +671,7 @@ def process(coords_transform: coordinates.Transformation, fg_elev: utilities.FGE
stg_manager.add_object_static('lightmap-switch.xml', center_global, cluster_elev, 0, once=True)
# -- write .ac and .xml
building_lib.write(os.path.join(path_to_stg, file_name + ".ac"), cl.objects, fg_elev,
building_lib.write(os.path.join(path_to_stg, file_name + ".ac"), cl.objects,
cluster_elev, cluster_offset, prepare_textures.roofs, stats)
if not parameters.FLAG_2017_2:
_write_xml(path_to_stg, file_name, cl.objects, cluster_offset)
......
......@@ -113,16 +113,24 @@ BUILDING_REDUCE_CHECK_TOUCH = False # -- before removing a building due to area,
BUILDING_SIMPLIFY_TOLERANCE = 1.0 # -- all points in the simplified building will be within the tolerance distance of the original geometry.
BUILDING_NEVER_SKIP_LEVELS = 6 # -- buildings that tall will never be skipped
BUILDING_UNKNOWN_ROOF_TYPE = "flat" # -- If the roof type isn't given use this type
BUILDING_COMPLEX_ROOFS = True # -- generate complex roofs on buildings?
BUILDING_COMPLEX_ROOFS = True # -- generate complex roofs on buildings? I.e. other shpaes than horizontal and flat
BUILDING_COMPLEX_ROOFS_MIN_LEVELS = 1 # don't put complex roof on buildings smaller than the specified value unless there is an explicit roof:shape flag
BUILDING_COMPLEX_ROOFS_MAX_LEVELS = 20 # don't put complex roofs on buildings taller the specified value unless there is an explicit roof:shape flag
BUILDING_COMPLEX_ROOFS_MAX_AREA = 2000 # -- don't put complex roofs on buildings larger than this
BUILDING_COMPLEX_ROOFS_MAX_LEVELS = 5 # don't put complex roofs on buildings taller the specified value unless there is an explicit roof:shape flag
BUILDING_COMPLEX_ROOFS_MAX_AREA = 800 # -- don't put complex roofs on buildings larger than this
BUILDING_SKEL_ROOFS = True # -- generate complex roofs with pySkeleton?
BUILDING_SKEL_ROOFS_MIN_ANGLE = 10 # -- pySkeleton based complex roofs will
BUILDING_SKEL_ROOFS_MAX_ANGLE = 50 # have a random angle between MIN and MAX
BUILDING_SKEL_MAX_NODES = 10 # -- max number of nodes for which we generate pySkeleton roofs
BUILDING_SKEL_MAX_HEIGHT_RATIO = 0.7 # -- skip skel roofs if ratio of roof height to base building height is larger than this
BUILDING_SKILLION_ROOF_MAX_HEIGHT = 2.
BUILDING_SKEL_ROOF_MAX_HEIGHT = 6. # -- skip skeleton roofs (gabled, pyramidal, ..) if the roof height is larger than this
BUILDING_SKEL_ROOF_DEFAULT_HEIGHT = 2.5 # if the roof_height is not given what we use to calculate real building heihgt temporarily
# If the roof_type is missing, what shall be the distribution of roof_types (must sum up to 1.0)
BUILDING_ROOF_FLAT_RATIO = 0.2
BUILDING_ROOF_SKILLION_RATIO = 0.1
BUILDING_ROOF_GABLED_RATIO = 0.55
BUILDING_ROOF_HIPPED_RATIO = 0.1
BUILDING_ROOF_PYRAMIDAL_RATIO = 0.05
BUILDING_FAKE_AMBIENT_OCCLUSION = True # -- fake AO by darkening facade textures towards the ground, using
BUILDING_FAKE_AMBIENT_OCCLUSION_HEIGHT = 6. # 1 - VALUE * exp(- AGL / HEIGHT )
......
......@@ -112,7 +112,7 @@ def separate_gable(ac_object, b, inward_meters=0.) -> None:
# -- 4 corners
o = ac_object.next_node_index()
for i in range(0, 4):
ac_object.node(-b.X[ind_X[i]][1], b.ground_elev + b.height - roof_height, -b.X[ind_X[i]][0])
ac_object.node(-b.X[ind_X[i]][1], b.beginning_of_roof_above_sea_level, -b.X[ind_X[i]][0])
# We don't want the hipped part to be greater than the height, which is 45 deg
inward_meters = min(roof_height, inward_meters)
......@@ -121,9 +121,9 @@ def separate_gable(ac_object, b, inward_meters=0.) -> None:
len_roof_bottom = 1.*b.edge_length_x[ind_X[0]]
ac_object.node(-(0.5 * (b.X[ind_X[3]][1] + b.X[ind_X[0]][1]) + tang[1]), b.ground_elev + b.height,
ac_object.node(-(0.5 * (b.X[ind_X[3]][1] + b.X[ind_X[0]][1]) + tang[1]), b.top_of_roof_above_sea_level,
-(0.5*(b.X[ind_X[3]][0] + b.X[ind_X[0]][0]) + tang[0]))
ac_object.node(-(0.5 * (b.X[ind_X[1]][1] + b.X[ind_X[2]][1]) - tang[1]), b.ground_elev + b.height,
ac_object.node(-(0.5 * (b.X[ind_X[1]][1] + b.X[ind_X[2]][1]) - tang[1]), b.top_of_roof_above_sea_level,
-(0.5*(b.X[ind_X[1]][0] + b.X[ind_X[2]][0]) - tang[0]))
roof_texture_size_x = t.h_size_meters # size of roof texture in meters
......@@ -169,7 +169,7 @@ def separate_pyramidal(ac_object: ac.Object, b, inward_meters=0.0) -> None:
# -- ? corners
o = ac_object.next_node_index()
for x in b.X:
ac_object.node(-x[1], b.ground_elev + b.height - roof_height, -x[0])
ac_object.node(-x[1], b.beginning_of_roof_above_sea_level, -x[0])
# We don't want the hipped part to be greater than the height, which is 45 deg
inward_meters = min(roof_height, inward_meters)
......@@ -177,7 +177,7 @@ def separate_pyramidal(ac_object: ac.Object, b, inward_meters=0.0) -> None:
# get middle node of the "tower"
out_1 = -sum([xi[1] for xi in b.X])/len(b.X)
out_2 = -sum([xi[0] for xi in b.X])/len(b.X)
ac_object.node(out_1, b.ground_elev + b.height, out_2)
ac_object.node(out_1, b.top_of_roof_above_sea_level, out_2)
# texture it
roof_texture_size_x = t.h_size_meters # size of roof texture in meters
......@@ -200,14 +200,14 @@ def separate_skillion(ac_object: ac.Object, b):
# -- 4 corners
o = ac_object.next_node_index()
for x in b.X:
ac_object.node(-x[1], b.ground_elev + b.height - b.roof_height, -x[0])
ac_object.node(-x[1], b.beginning_of_roof_above_sea_level, -x[0])
# We don't want the hipped part to be greater than the height, which is 45 deg
# FLAT PART
i = 0
for x in b.X:
ac_object.node(-x[1], b.ground_elev + b.height - b.roof_height + b.roof_height_x[i], -x[0])
ac_object.node(-x[1], b.beginning_of_roof_above_sea_level + b.roof_height_x[i], -x[0])
i += 1
if b.polygon.interiors:
......@@ -242,7 +242,7 @@ def separate_skillion(ac_object: ac.Object, b):
# create nodes for/ and roof
for i, node in enumerate(nodes):
# new nodes
ac_object.node(-b.X[node][1], b.ground_elev + b.height - b.roof_height + b.roof_height_x[node], -b.X[node][0])
ac_object.node(-b.X[node][1], b.beginning_of_roof_above_sea_level + b.roof_height_x[node], -b.X[node][0])
l.append((o + node, uv[i][0], uv[i][1]))
ac_object.face(l)
return
......
......@@ -188,7 +188,7 @@ class Stats(object):
self.area_above = np.zeros_like(self.area_levels)
self.vertices = 0
self.surfaces = 0
self.roof_types = {}
self.roof_shapes = {}
self.have_complex_roof = 0
self.roof_errors = 0
self.out = None
......@@ -201,10 +201,10 @@ class Stats(object):
def count(self, b):
"""update stats (vertices, surfaces, area, corners) with given building's data
"""
if b.roof_type in self.roof_types:
self.roof_types[b.roof_type] += 1
if b.roof_shape.name in self.roof_shapes:
self.roof_shapes[b.roof_shape.name] += 1
else:
self.roof_types[b.roof_type] = 1
self.roof_shapes[b.roof_shape.name] = 1
# -- stats on number of ground nodes.
# Complex buildings counted in corners[0]
......@@ -251,8 +251,8 @@ class Stats(object):
""" % (self.objects, self.parse_errors, total_written, self.corners[4],
self.skipped_small, self.skipped_nearby, self.skipped_no_elev, self.skipped_texture)))
roof_line = " roof-types"
for roof_type in self.roof_types:
roof_line += """\n %s\t%i""" % (roof_type, self.roof_types[roof_type])
for roof_shape in self.roof_shapes:
roof_line += """\n %s\t%i""" % (roof_shape, self.roof_shapes[roof_shape])
out.write(textwrap.dedent(roof_line))
textures_used = {k: v for k, v in self.textures_total.items() if v > 0}
......
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