more performance optimization in altitudearea building and more comments

This commit is contained in:
Laura Klünder 2019-12-20 20:05:14 +01:00
parent 1e2119fb80
commit 484f725aa6
2 changed files with 27 additions and 7 deletions

View file

@ -8,6 +8,7 @@ import numpy as np
from django.core.validators import MinValueValidator from django.core.validators import MinValueValidator
from django.db import models from django.db import models
from django.urls import reverse from django.urls import reverse
from django.utils.functional import cached_property
from django.utils.text import format_lazy from django.utils.text import format_lazy
from django.utils.translation import ugettext_lazy as _ from django.utils.translation import ugettext_lazy as _
from scipy.sparse.csgraph._shortest_path import dijkstra from scipy.sparse.csgraph._shortest_path import dijkstra
@ -157,6 +158,16 @@ class Door(LevelGeometryMixin, AccessRestrictionMixin, models.Model):
default_related_name = 'doors' default_related_name = 'doors'
class ItemWithValue:
def __init__(self, obj, func):
self.obj = obj
self._func = func
@cached_property
def value(self):
return self._func()
class AltitudeArea(LevelGeometryMixin, models.Model): class AltitudeArea(LevelGeometryMixin, models.Model):
""" """
An altitude area An altitude area
@ -529,15 +540,17 @@ class AltitudeArea(LevelGeometryMixin, models.Model):
buffered = polygon.buffer(0.001) buffered = polygon.buffer(0.001)
center = polygon.centroid center = polygon.centroid
touches = tuple((area, buffered.intersection(area.orig_geometry).area) touches = tuple(ItemWithValue(area, lambda: buffered.intersection(area.orig_geometry).area)
for area in our_areas for area in our_areas
if area.orig_geometry_prep.intersects(buffered)) if area.orig_geometry_prep.intersects(buffered))
if touches: if len(touches) == 1:
min_touches = sum((t[1] for t in touches), 0)/4 area = touches[0].obj
area = max(touches, key=lambda item: (item[1] > min_touches, elif touches:
item[0].altitude2 is not None, min_touches = sum((t.value for t in touches), 0)/4
item[0].altitude, area = max(touches, key=lambda item: (item.value > min_touches,
item[1]))[0] item.obj.altitude2 is not None,
item.obj.altitude,
item.value)).obj
else: else:
area = min(our_areas, area = min(our_areas,
key=lambda a: a.orig_geometry.distance(center)-(0 if a.altitude2 is None else 0.6)) key=lambda a: a.orig_geometry.distance(center)-(0 if a.altitude2 is None else 0.6))

View file

@ -361,16 +361,23 @@ def clean_cut_polygon(polygon: Polygon) -> Polygon:
def cut_ring(ring: LinearRing) -> List[LinearRing]: def cut_ring(ring: LinearRing) -> List[LinearRing]:
"""
Cuts a Linearring into multiple linearrings. Useful if the ring intersects with itself.
An 8-ring would be split into it's two circles for example.
"""
rings = [] rings = []
new_ring = [] new_ring = []
# noinspection PyPropertyAccess # noinspection PyPropertyAccess
for point in ring.coords: for point in ring.coords:
try: try:
# check if this point is already part of the ring
index = new_ring.index(point) index = new_ring.index(point)
except ValueError: except ValueError:
# if not, append it
new_ring.append(point) new_ring.append(point)
continue continue
# if yes, we got a loop, add it to the result and remove it from new_ring.
if len(new_ring) > 2+index: if len(new_ring) > 2+index:
rings.append(LinearRing(new_ring[index:]+[point])) rings.append(LinearRing(new_ring[index:]+[point]))
new_ring = new_ring[:index+1] new_ring = new_ring[:index+1]