team-3/src/c3nav/mapdata/render/geometry/altitudearea.py
2024-08-18 21:48:17 +02:00

98 lines
4.4 KiB
Python

from collections import deque
from itertools import chain
import numpy as np
from c3nav.mapdata.models import AltitudeArea
from c3nav.mapdata.render.geometry.hybrid import HybridGeometry
class AltitudeAreaGeometries:
def __init__(self, altitudearea=None, colors=None, obstacles=None):
if altitudearea is not None:
self.geometry = altitudearea.geometry
self.altitude = int(altitudearea.altitude * 1000)
self.points = altitudearea.points
else:
self.geometry = None
self.altitude = None
self.points = None
self.base = None
self.bottom = None
self.colors = colors
self.obstacles = obstacles
def get_altitudes(self, points):
# noinspection PyCallByClass,PyTypeChecker
return AltitudeArea.get_altitudes(self, points/1000).astype(np.int32)
def create_hybrid_geometries(self, face_centers, vertices_offset, faces_offset):
self.geometry = HybridGeometry.create(self.geometry, face_centers)
vertices = deque()
faces = deque()
for color, areas in self.colors.items():
for height in tuple(areas.keys()):
faces_offset, vertices_offset = self._call_create_full(areas, height, faces, vertices,
faces_offset, vertices_offset)
for height_obstacles in self.obstacles.values():
for color_obstacles in height_obstacles.values():
for i in range(len(color_obstacles)):
faces_offset, vertices_offset = self._call_create_full(color_obstacles, i, faces, vertices,
faces_offset, vertices_offset)
if not vertices:
return np.empty((0, 2), dtype=np.int32), np.empty((0, 3), dtype=np.uint32)
return np.vstack(vertices), np.vstack(faces)
def _call_create_full(self, mapping, key, faces, vertices, faces_offset, vertices_offset):
geom = mapping[key]
new_geom, new_vertices, new_faces = HybridGeometry.create_full(geom, vertices_offset, faces_offset)
mapping[key] = new_geom
vertices_offset += new_vertices.shape[0]
faces_offset += new_faces.shape[0]
vertices.append(new_vertices)
faces.append(new_faces)
return faces_offset, vertices_offset
def remove_faces(self, faces):
self.geometry.remove_faces(faces)
for areas in self.colors.values():
for area in areas.values():
area.remove_faces(faces)
def create_polyhedrons(self, create_polyhedron, altitudes, min_altitude, crops):
if self.points is None:
altitudes = self.altitude
self.base = HybridGeometry(self.geometry.geom, self.geometry.faces)
self.bottom = HybridGeometry(self.geometry.geom, self.geometry.faces)
self.geometry.build_polyhedron(create_polyhedron,
lower=altitudes - int(0.7 * 1000),
upper=altitudes,
crops=crops)
self.base.build_polyhedron(create_polyhedron,
lower=min_altitude - int(0.7 * 1000),
upper=altitudes - int(0.7 * 1000),
crops=crops,
top=False, bottom=False)
self.bottom.build_polyhedron(create_polyhedron,
lower=0, upper=1,
crops=crops,
top=False)
for geometry in chain(*(areas.values() for areas in self.colors.values())):
geometry.build_polyhedron(create_polyhedron,
lower=altitudes,
upper=altitudes + int(0.001 * 1000),
crops=crops)
# todo: treat altitude properly
for height, height_geometries in self.obstacles.items():
for color, color_geometries in height_geometries.items():
for geometry in color_geometries:
geometry.build_polyhedron(create_polyhedron,
lower=altitudes,
upper=altitudes + height,
crops=crops)