connect levels in full_levels renderung

This commit is contained in:
Laura Klünder 2017-11-10 01:47:55 +01:00
parent 9ed381567d
commit ab4402907d
2 changed files with 40 additions and 3 deletions

View file

@ -15,7 +15,7 @@ from shapely.ops import unary_union
from c3nav.mapdata.cache import MapHistory from c3nav.mapdata.cache import MapHistory
from c3nav.mapdata.models import Level, MapUpdate from c3nav.mapdata.models import Level, MapUpdate
from c3nav.mapdata.utils.geometry import assert_multipolygon, get_rings from c3nav.mapdata.utils.geometry import assert_multipolygon, get_rings
from c3nav.mapdata.utils.mesh import triangulate_rings from c3nav.mapdata.utils.mesh import triangulate_rings, triangulate_polygon
from c3nav.mapdata.utils.mpl import shapely_to_mpl from c3nav.mapdata.utils.mpl import shapely_to_mpl
@ -133,6 +133,25 @@ class LevelRenderData:
single_level_geoms = {level.pk: LevelGeometries.build_for_level(level) for level in levels} single_level_geoms = {level.pk: LevelGeometries.build_for_level(level) for level in levels}
interpolators = {}
last_interpolator = None
for level in reversed(levels):
if level.on_top_of_id is not None:
continue
if last_interpolator is not None:
interpolators[level.pk] = last_interpolator
coords = deque()
values = deque()
for area in single_level_geoms[level.pk].altitudeareas:
new_coords = np.vstack(tuple(np.array(ring.coords) for ring in get_rings(area.geometry)))
coords.append(new_coords)
values.append(np.full((new_coords.shape[0], ), fill_value=float(area.altitude)))
last_interpolator = NearestNDInterpolator(np.hstack(coords), np.hstack(values))
for i, level in enumerate(levels): for i, level in enumerate(levels):
if level.on_top_of_id is not None: if level.on_top_of_id is not None:
continue continue
@ -184,6 +203,7 @@ 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.walls_extended = crop_to.intersection(old_geoms.walls_extended)
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)
@ -248,7 +268,7 @@ class LevelRenderData:
new_geoms.min_altitude = float(min(area.altitude for area in new_geoms.altitudeareas) new_geoms.min_altitude = float(min(area.altitude for area in new_geoms.altitudeareas)
if new_geoms.altitudeareas else new_geoms.base_altitude) if new_geoms.altitudeareas else new_geoms.base_altitude)
new_geoms.build_mesh() new_geoms.build_mesh(interpolators.get(level.pk) if sublevel.pk == level.pk else None)
render_data.levels.append(new_geoms) render_data.levels.append(new_geoms)
@ -296,6 +316,7 @@ class LevelGeometries:
self.altitudeareas = [] self.altitudeareas = []
self.heightareas = [] self.heightareas = []
self.walls = None self.walls = None
self.walls_extended = None
self.doors = None self.doors = None
self.holes = None self.holes = None
self.access_restriction_affected = None self.access_restriction_affected = None
@ -303,6 +324,9 @@ class LevelGeometries:
self.restricted_spaces_outdoors = None self.restricted_spaces_outdoors = None
self.affected_area = None self.affected_area = None
self.vertices = None
self.faces = None
self.level_base = None self.level_base = None
self.optional_base = None self.optional_base = None
@ -397,6 +421,7 @@ class LevelGeometries:
for access_restriction, spaces in restricted_spaces_outdoors.items()} for access_restriction, spaces in restricted_spaces_outdoors.items()}
geoms.walls = buildings_geom.difference(spaces_geom).difference(doors_geom) geoms.walls = buildings_geom.difference(spaces_geom).difference(doors_geom)
geoms.walls_extended = buildings_geom.difference(spaces_geom)
# general level infos # general level infos
geoms.pk = level.pk geoms.pk = level.pk
@ -419,6 +444,7 @@ 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.walls_extended = HybridGeometry.create(self.walls_extended, 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()}
@ -494,7 +520,7 @@ class LevelGeometries:
return (np.vstack(new_faces), ) return (np.vstack(new_faces), )
def build_mesh(self): def build_mesh(self, interpolator=None):
rings = tuple(chain(*(get_rings(geom) for geom in self.get_geometries()))) rings = tuple(chain(*(get_rings(geom) for geom in self.get_geometries())))
self.vertices, self.faces = triangulate_rings(rings) self.vertices, self.faces = triangulate_rings(rings)
self.create_hybrid_geometries(face_centers=self.vertices[self.faces].sum(axis=1) / 3) self.create_hybrid_geometries(face_centers=self.vertices[self.faces].sum(axis=1) / 3)
@ -509,6 +535,13 @@ class LevelGeometries:
# create polyhedrons # create polyhedrons
self.walls.build_polyhedron(self._create_polyhedron, bottom=vertex_altitudes-0.7, top=vertex_wall_heights) self.walls.build_polyhedron(self._create_polyhedron, bottom=vertex_altitudes-0.7, top=vertex_wall_heights)
if interpolator is not None:
self.walls_extended.build_polyhedron(self._create_polyhedron,
bottom=vertex_wall_heights,
top=interpolator(*np.transpose(self.vertices))-0.3)
else:
self.walls_extended = None
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():
@ -533,6 +566,7 @@ class LevelGeometries:
self.optional_base.build_polyhedron(self._create_polyhedron, bottom=0, top=1) self.optional_base.build_polyhedron(self._create_polyhedron, bottom=0, top=1)
# unset heightareas, they are no loinger needed # unset heightareas, they are no loinger needed
self.vertex_altitudes = None
self.heightareas = None self.heightareas = None
self.vertices = None self.vertices = None
self.faces = None self.faces = None

View file

@ -124,6 +124,9 @@ class MapRenderer:
if walls is not None: if walls is not None:
engine.add_geometry(walls, height=geoms.default_height, fill=FillAttribs('#aaaaaa')) engine.add_geometry(walls, height=geoms.default_height, fill=FillAttribs('#aaaaaa'))
if geoms.walls_extended and self.full_levels and engine.is_3d:
engine.add_geometry(geoms.walls_extended, height=geoms.default_height, fill=FillAttribs('#aaaaaa'))
if not geoms.doors.is_empty: if not geoms.doors.is_empty:
engine.add_geometry(geoms.doors.difference(add_walls), fill=FillAttribs('#ffffff'), engine.add_geometry(geoms.doors.difference(add_walls), fill=FillAttribs('#ffffff'),
stroke=StrokeAttribs('#ffffff', 0.05, min_px=0.2)) stroke=StrokeAttribs('#ffffff', 0.05, min_px=0.2))