introducing short walls, so walls stay below stairs from levels on top

This commit is contained in:
Laura Klünder 2017-11-17 20:07:00 +01:00
parent fdce9a9ab1
commit 976c49c8ab
2 changed files with 45 additions and 6 deletions

View file

@ -166,12 +166,16 @@ class LevelRenderData:
'spaces__obstacles', 'spaces__lineobstacles', 'spaces__obstacles', 'spaces__lineobstacles',
'spaces__groups')) 'spaces__groups'))
single_level_geoms = {level.pk: LevelGeometries.build_for_level(level) for level in levels} single_level_geoms = {}
interpolators = {} interpolators = {}
last_interpolator = None last_interpolator = None
altitudeareas_above = []
for level in reversed(levels): 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: 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 continue
if last_interpolator is not None: if last_interpolator is not None:
@ -239,6 +243,11 @@ class LevelRenderData:
new_geoms = LevelGeometries() new_geoms = LevelGeometries()
new_geoms.doors = crop_to.intersection(old_geoms.doors) new_geoms.doors = crop_to.intersection(old_geoms.doors)
new_geoms.walls = crop_to.intersection(old_geoms.walls) 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: for altitudearea in old_geoms.altitudeareas:
new_geometry = crop_to.intersection(altitudearea.geometry) new_geometry = crop_to.intersection(altitudearea.geometry)
@ -387,6 +396,8 @@ class LevelGeometries:
self.heightareas = [] self.heightareas = []
self.walls = None self.walls = None
self.walls_extended = None self.walls_extended = None
self.all_walls = None
self.short_walls = []
self.doors = None self.doors = None
self.doors_extended = None self.doors_extended = None
self.holes = None self.holes = None
@ -410,7 +421,7 @@ class LevelGeometries:
self.min_altitude = None self.min_altitude = None
@staticmethod @staticmethod
def build_for_level(level): def build_for_level(level, altitudeareas_above):
geoms = LevelGeometries() geoms = LevelGeometries()
buildings_geom = unary_union([b.geometry for b in level.buildings.all()]) 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) 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 # general level infos
geoms.pk = level.pk geoms.pk = level.pk
geoms.on_top_of_id = level.on_top_of_id geoms.on_top_of_id = level.on_top_of_id
@ -530,7 +554,8 @@ class LevelGeometries:
def get_geometries(self): def get_geometries(self):
# omit heightareas as these are never drawn # omit heightareas as these are never drawn
return chain(chain(*(area.get_geometries() for area in self.altitudeareas)), (self.walls, self.doors,), 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): def create_hybrid_geometries(self, face_centers):
for area in self.altitudeareas: for area in self.altitudeareas:
@ -538,6 +563,9 @@ class LevelGeometries:
self.heightareas = tuple((HybridGeometry.create(area, face_centers), height) self.heightareas = tuple((HybridGeometry.create(area, face_centers), height)
for area, height in self.heightareas) for area, height in self.heightareas)
self.walls = HybridGeometry.create(self.walls, face_centers) 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.doors = HybridGeometry.create(self.doors, face_centers)
self.restricted_spaces_indoors = {key: HybridGeometry.create(geom, face_centers) self.restricted_spaces_indoors = {key: HybridGeometry.create(geom, face_centers)
for key, geom in self.restricted_spaces_indoors.items()} 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())) area.remove_faces(reduce(operator.or_, self.walls.faces, set()))
# create polyhedrons # create polyhedrons
self.walls_base = HybridGeometry(self.walls.geom, self.walls.faces) self.walls_base = HybridGeometry(self.all_walls.geom, self.all_walls.faces)
self.walls_bottom = HybridGeometry(self.walls.geom, self.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_extended = HybridGeometry(self.walls.geom, self.walls.faces)
self.walls.build_polyhedron(self._create_polyhedron, self.walls.build_polyhedron(self._create_polyhedron,
lower=vertex_altitudes - int(0.7 * 1000), lower=vertex_altitudes - int(0.7 * 1000),
upper=vertex_wall_heights) 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(): for key, geometry in self.restricted_spaces_indoors.items():
geometry.crop_ids = frozenset(('in:%s' % key, )) geometry.crop_ids = frozenset(('in:%s' % key, ))
for key, geometry in self.restricted_spaces_outdoors.items(): 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) self.walls_bottom.build_polyhedron(self._create_polyhedron, lower=0, upper=1, top=False)
# unset heightareas, they are no loinger needed # unset heightareas, they are no loinger needed
self.all_walls = None
self.heightareas = None self.heightareas = None
self.vertices = None self.vertices = None
self.faces = None self.faces = None

View file

@ -147,6 +147,10 @@ class MapRenderer:
top=not walls_extended), top=not walls_extended),
height=geoms.default_height, fill=FillAttribs('#aaaaaa'), category='walls') 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: if walls_extended:
engine.add_geometry(geoms.walls_extended, fill=FillAttribs('#aaaaaa'), category='walls') engine.add_geometry(geoms.walls_extended, fill=FillAttribs('#aaaaaa'), category='walls')