From 976c49c8abfbf0176620ad8a79d6452c083cc2f1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Laura=20Kl=C3=BCnder?= Date: Fri, 17 Nov 2017 20:07:00 +0100 Subject: [PATCH] introducing short walls, so walls stay below stairs from levels on top --- src/c3nav/mapdata/render/data.py | 47 ++++++++++++++++++++++++---- src/c3nav/mapdata/render/renderer.py | 4 +++ 2 files changed, 45 insertions(+), 6 deletions(-) diff --git a/src/c3nav/mapdata/render/data.py b/src/c3nav/mapdata/render/data.py index 4b39478b..ef7eae41 100644 --- a/src/c3nav/mapdata/render/data.py +++ b/src/c3nav/mapdata/render/data.py @@ -166,12 +166,16 @@ class LevelRenderData: 'spaces__obstacles', 'spaces__lineobstacles', 'spaces__groups')) - single_level_geoms = {level.pk: LevelGeometries.build_for_level(level) for level in levels} - + single_level_geoms = {} interpolators = {} last_interpolator = None + altitudeareas_above = [] for level in reversed(levels): + single_level_geoms[level.pk] = LevelGeometries.build_for_level(level, altitudeareas_above) + if level.on_top_of_id is not None: + altitudeareas_above.extend(single_level_geoms[level.pk].altitudeareas) + altitudeareas_above.sort(key=operator.attrgetter('altitude')) continue if last_interpolator is not None: @@ -239,6 +243,11 @@ class LevelRenderData: new_geoms = LevelGeometries() new_geoms.doors = crop_to.intersection(old_geoms.doors) new_geoms.walls = crop_to.intersection(old_geoms.walls) + new_geoms.all_walls = crop_to.intersection(old_geoms.all_walls) + new_geoms.short_walls = tuple((altitude, geom) for altitude, geom in tuple( + (altitude, crop_to.intersection(geom)) + for altitude, geom in old_geoms.short_walls + ) if not geom.is_empty) for altitudearea in old_geoms.altitudeareas: new_geometry = crop_to.intersection(altitudearea.geometry) @@ -387,6 +396,8 @@ class LevelGeometries: self.heightareas = [] self.walls = None self.walls_extended = None + self.all_walls = None + self.short_walls = [] self.doors = None self.doors_extended = None self.holes = None @@ -410,7 +421,7 @@ class LevelGeometries: self.min_altitude = None @staticmethod - def build_for_level(level): + def build_for_level(level, altitudeareas_above): geoms = LevelGeometries() buildings_geom = unary_union([b.geometry for b in level.buildings.all()]) @@ -515,6 +526,19 @@ class LevelGeometries: geoms.walls = buildings_geom.difference(spaces_geom).difference(doors_geom) + # shorten walls if there are altitudeareas above + remaining = geoms.walls + for altitudearea in altitudeareas_above: + intersection = altitudearea.geometry.intersection(remaining).buffer(0) + if intersection.is_empty: + continue + remaining = remaining.difference(altitudearea.geometry) + geoms.short_walls.append((altitudearea.altitude, intersection)) + geoms.all_walls = geoms.walls + geoms.walls = geoms.walls.difference( + unary_union(tuple(altitudearea.geometry for altitudearea in altitudeareas_above)) + ) + # general level infos geoms.pk = level.pk geoms.on_top_of_id = level.on_top_of_id @@ -530,7 +554,8 @@ class LevelGeometries: 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()) + self.restricted_spaces_indoors.values(), self.restricted_spaces_outdoors.values(), + (geom for altitude, geom in self.short_walls)) def create_hybrid_geometries(self, face_centers): for area in self.altitudeareas: @@ -538,6 +563,9 @@ class LevelGeometries: self.heightareas = tuple((HybridGeometry.create(area, face_centers), height) for area, height in self.heightareas) self.walls = HybridGeometry.create(self.walls, face_centers) + self.short_walls = tuple((altitude, HybridGeometry.create(geom, face_centers)) + for altitude, geom in self.short_walls) + self.all_walls = HybridGeometry.create(self.all_walls, face_centers) self.doors = HybridGeometry.create(self.doors, face_centers) self.restricted_spaces_indoors = {key: HybridGeometry.create(geom, face_centers) for key, geom in self.restricted_spaces_indoors.items()} @@ -654,13 +682,19 @@ class LevelGeometries: area.remove_faces(reduce(operator.or_, self.walls.faces, set())) # create polyhedrons - self.walls_base = HybridGeometry(self.walls.geom, self.walls.faces) - self.walls_bottom = HybridGeometry(self.walls.geom, self.walls.faces) + self.walls_base = HybridGeometry(self.all_walls.geom, self.all_walls.faces) + self.walls_bottom = HybridGeometry(self.all_walls.geom, self.all_walls.faces) self.walls_extended = HybridGeometry(self.walls.geom, self.walls.faces) self.walls.build_polyhedron(self._create_polyhedron, lower=vertex_altitudes - int(0.7 * 1000), upper=vertex_wall_heights) + for altitude, geom in self.short_walls: + geom.build_polyhedron(self._create_polyhedron, + lower=vertex_altitudes - int(0.7 * 1000), + upper=altitude - int(0.7 * 1000)) + self.short_walls = tuple(geom for altitude, geom in self.short_walls) + for key, geometry in self.restricted_spaces_indoors.items(): geometry.crop_ids = frozenset(('in:%s' % key, )) for key, geometry in self.restricted_spaces_outdoors.items(): @@ -706,6 +740,7 @@ class LevelGeometries: self.walls_bottom.build_polyhedron(self._create_polyhedron, lower=0, upper=1, top=False) # unset heightareas, they are no loinger needed + self.all_walls = None self.heightareas = None self.vertices = None self.faces = None diff --git a/src/c3nav/mapdata/render/renderer.py b/src/c3nav/mapdata/render/renderer.py index 073c1e06..f64da664 100644 --- a/src/c3nav/mapdata/render/renderer.py +++ b/src/c3nav/mapdata/render/renderer.py @@ -147,6 +147,10 @@ class MapRenderer: top=not walls_extended), height=geoms.default_height, fill=FillAttribs('#aaaaaa'), category='walls') + for short_wall in geoms.short_walls: + engine.add_geometry(short_wall.filter(bottom=not not_full_levels), + height=geoms.default_height, fill=FillAttribs('#aaaaaa'), category='walls') + if walls_extended: engine.add_geometry(geoms.walls_extended, fill=FillAttribs('#aaaaaa'), category='walls')