start modernizing renderdata code somewhat

This commit is contained in:
Laura Klünder 2023-12-07 19:13:42 +01:00
parent 0150851808
commit 551cb1e086
2 changed files with 25 additions and 16 deletions

View file

@ -1,14 +1,17 @@
import operator import operator
import pickle import pickle
from collections import deque from collections import deque
from dataclasses import dataclass, field
from itertools import chain from itertools import chain
from typing import Optional
import numpy as np import numpy as np
from django.conf import settings from django.conf import settings
from scipy.interpolate import NearestNDInterpolator from scipy.interpolate import NearestNDInterpolator
from shapely import prepared from shapely import prepared, Geometry, MultiPolygon
from shapely.geometry import GeometryCollection from shapely.geometry import GeometryCollection
from shapely.ops import unary_union from shapely.ops import unary_union
from shapely.prepared import PreparedGeometry
from c3nav.mapdata.models import Level, MapUpdate, Source from c3nav.mapdata.models import Level, MapUpdate, Source
from c3nav.mapdata.render.geometry import AltitudeAreaGeometries, LevelGeometries from c3nav.mapdata.render.geometry import AltitudeAreaGeometries, LevelGeometries
@ -24,10 +27,13 @@ except ImportError:
empty_geometry_collection = GeometryCollection() empty_geometry_collection = GeometryCollection()
@dataclass
class Cropper: class Cropper:
def __init__(self, geometry=None): geometry: Optional[Geometry]
self.geometry = geometry geometry_prep: Optional[PreparedGeometry] = field(init=False, repr=False)
self.geometry_prep = None if geometry is None else prepared.prep(unwrap_geom(geometry))
def __post_init__(self):
self.geometry_prep = None if self.geometry is None else prepared.prep(unwrap_geom(self.geometry))
def intersection(self, other): def intersection(self, other):
if self.geometry is None: if self.geometry is None:
@ -37,19 +43,20 @@ class Cropper:
return empty_geometry_collection return empty_geometry_collection
@dataclass
class LevelRenderData: class LevelRenderData:
""" """
Renderdata for a level to display. Renderdata for a level to display.
This contains multiple LevelGeometries instances because you might to look through holes onto lower levels. This contains multiple LevelGeometries instances because you might to look through holes onto lower levels.
""" """
def __init__(self): base_altitude: float
self.levels = [] lowest_important_level: int
self.base_altitude = None levels: list[LevelGeometries] = field(default_factory=list)
self.lowest_important_level = None darken_area: MultiPolygon | None = None
self.darken_area = None
@staticmethod @staticmethod
def rebuild(): def rebuild():
# Levels are automatically sorted by base_altitude, ascending
levels = tuple(Level.objects.prefetch_related('altitudeareas', 'buildings', 'doors', 'spaces', levels = tuple(Level.objects.prefetch_related('altitudeareas', 'buildings', 'doors', 'spaces',
'spaces__holes', 'spaces__areas', 'spaces__columns', 'spaces__holes', 'spaces__areas', 'spaces__columns',
'spaces__obstacles', 'spaces__lineobstacles', 'spaces__obstacles', 'spaces__lineobstacles',
@ -58,11 +65,12 @@ class LevelRenderData:
package = CachePackage(bounds=tuple(chain(*Source.max_bounds()))) package = CachePackage(bounds=tuple(chain(*Source.max_bounds())))
# first pass in reverse to collect some data that we need later # first pass in reverse to collect some data that we need later
single_level_geoms = {} single_level_geoms: dict[int, LevelGeometries] = {}
interpolators = {} interpolators = {}
last_interpolator = None last_interpolator: NearestNDInterpolator | None = None
altitudeareas_above = [] altitudeareas_above = [] # todo: typing
for level in reversed(levels): for level in reversed(levels):
# build level geometry for every single level
single_level_geoms[level.pk] = LevelGeometries.build_for_level(level, altitudeareas_above) single_level_geoms[level.pk] = LevelGeometries.build_for_level(level, altitudeareas_above)
# ignore intermediate levels in this pass # ignore intermediate levels in this pass
@ -143,9 +151,10 @@ class LevelRenderData:
if crop_to.is_empty: if crop_to.is_empty:
break break
render_data = LevelRenderData() render_data = LevelRenderData(
render_data.base_altitude = level.base_altitude base_altitude=level.base_altitude,
render_data.lowest_important_level = lowest_important_level.pk lowest_important_level=lowest_important_level.pk,
)
access_restriction_affected = {} access_restriction_affected = {}
# go through sublevels, get their level geometries and crop them # go through sublevels, get their level geometries and crop them

View file

@ -1,5 +1,5 @@
from enum import StrEnum from enum import StrEnum
from typing import Annotated, Union, Optional from typing import Annotated, Optional, Union
from django.core.exceptions import ValidationError from django.core.exceptions import ValidationError
from django.urls import reverse from django.urls import reverse