calculate heightareas and vertex_heights

This commit is contained in:
Laura Klünder 2017-11-08 22:57:34 +01:00
parent 4b94d892d7
commit 426d838b13

View file

@ -153,6 +153,12 @@ class LevelRenderData:
if new_geoms.walls.is_empty and not new_geoms.altitudeareas:
continue
new_geoms.heightareas = tuple(
(area, height) for area, height in ((crop_to.intersection(area), height)
for area, height in old_geoms.heightareas)
if not area.is_empty
)
new_geoms.affected_area = unary_union((
*(altitudearea.geometry for altitudearea in new_geoms.altitudeareas),
crop_to.intersection(new_geoms.walls.buffer(1))
@ -221,6 +227,7 @@ class LevelRenderData:
class LevelGeometries:
def __init__(self):
self.altitudeareas = []
self.heightareas = []
self.walls = None
self.doors = None
self.holes = None
@ -232,6 +239,7 @@ class LevelGeometries:
self.vertices = None
self.faces = None
self.vertex_altitudes = None
self.vertex_heights = None
@staticmethod
def build_for_level(level):
@ -261,10 +269,9 @@ class LevelGeometries:
restricted_spaces_indoors = {}
restricted_spaces_outdoors = {}
# ground colors
# go through spaces and their areas for access control, ground colors and height areas
colors = {}
# go through spaces and their areas for access control and ground colors
heightareas = {}
for space in level.spaces.all():
access_restriction = space.access_restriction_id
if access_restriction is not None:
@ -288,6 +295,8 @@ class LevelGeometries:
if access_restriction is not None:
access_restriction_affected.setdefault(access_restriction, []).append(area.geometry)
colors.setdefault(area.get_color(), {}).setdefault(access_restriction, []).append(area.geometry)
heightareas.setdefault(space.height or level.default_height, []).append(space.geometry)
colors.pop(None, None)
# merge ground colors
@ -304,6 +313,10 @@ class LevelGeometries:
altitudearea_colors = {color: areas for color, areas in altitudearea_colors.items() if areas}
geoms.altitudeareas.append(AltitudeAreaGeometries(altitudearea, altitudearea_colors))
# merge height areas
geoms.heightareas = tuple((unary_union(geoms), height)
for height, geoms in sorted(heightareas.items(), key=operator.itemgetter(0)))
# merge access restrictions
geoms.access_restriction_affected = {access_restriction: unary_union(areas)
for access_restriction, areas in access_restriction_affected.items()}
@ -317,12 +330,15 @@ class LevelGeometries:
return geoms
def get_geometries(self):
# omit heightareas as these are never drawn
return chain(chain(*(area.get_geometries() for area in self.altitudeareas)), (self.walls, self.doors,),
self.restricted_spaces_indoors.values(), self.restricted_spaces_outdoors.values())
def create_hybrid_geometries(self, face_centers):
for area in self.altitudeareas:
area.create_hybrid_geometries(face_centers)
self.heightareas = tuple((HybridGeometry.create(area, face_centers), height)
for area, height in self.heightareas)
self.walls = HybridGeometry.create(self.walls, face_centers)
self.doors = HybridGeometry.create(self.doors, face_centers)
self.restricted_spaces_indoors = {key: HybridGeometry.create(geom, face_centers)
@ -330,23 +346,34 @@ class LevelGeometries:
self.restricted_spaces_outdoors = {key: HybridGeometry.create(geom, face_centers)
for key, geom in self.restricted_spaces_outdoors.items()}
def _build_vertex_values(self, area_values):
vertex_values = np.empty(self.vertices.shape[:1], dtype=np.int32)
vertex_value_mask = np.full(self.vertices.shape[:1], fill_value=False, dtype=np.bool)
for area, value in area_values:
i_vertices = np.unique(self.faces[np.array(tuple(area.faces))].flatten())
vertex_values[i_vertices] = value
vertex_value_mask[i_vertices] = True
if not np.all(vertex_value_mask):
interpolate = NearestNDInterpolator(self.vertices[vertex_value_mask],
vertex_values[vertex_value_mask])
vertex_values[np.logical_not(vertex_value_mask)] = interpolate(
*np.transpose(self.vertices[np.logical_not(vertex_value_mask)])
)
return vertex_values
def build_mesh(self):
rings = tuple(chain(*(get_rings(geom) for geom in self.get_geometries())))
self.vertices, self.faces = triangulate_rings(rings)
self.create_hybrid_geometries(face_centers=self.vertices[self.faces].sum(axis=1) / 3)
# calculate altitudes
self.vertex_altitudes = np.empty(self.vertices.shape[:1], dtype=np.int32)
vertex_altitude_mask = np.full(self.vertices.shape[:1], fill_value=False, dtype=np.bool)
self.vertex_altitudes = self._build_vertex_values((area.geometry, int(area.altitude*100))
for area in self.altitudeareas)
self.vertex_heights = self._build_vertex_values((area, int(height*100))
for area, height in self.heightareas)
for area in self.altitudeareas:
i_vertices = np.unique(self.faces[np.array(tuple(area.geometry.faces))].flatten())
self.vertex_altitudes[i_vertices] = int(area.altitude*100)
vertex_altitude_mask[i_vertices] = True
if not np.all(vertex_altitude_mask):
interpolate = NearestNDInterpolator(self.vertices[vertex_altitude_mask],
self.vertex_altitudes[vertex_altitude_mask])
self.vertex_altitudes[np.logical_not(vertex_altitude_mask)] = interpolate(
*np.transpose(self.vertices[np.logical_not(vertex_altitude_mask)])
)
# unset heightareas, they are no loinger needed
self.heightareas = None