98 lines
4.4 KiB
Python
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)
|