From b9de22fb1ca10edadea15a148d6388cf2ac81242 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Laura=20Kl=C3=BCnder?= Date: Sun, 6 Aug 2017 20:06:46 +0200 Subject: [PATCH] save areas in buildaltitudes --- src/c3nav/mapdata/models/geometry/level.py | 61 +++++++++++++++++++++- 1 file changed, 59 insertions(+), 2 deletions(-) diff --git a/src/c3nav/mapdata/models/geometry/level.py b/src/c3nav/mapdata/models/geometry/level.py index fcbde6e8..bb49b813 100644 --- a/src/c3nav/mapdata/models/geometry/level.py +++ b/src/c3nav/mapdata/models/geometry/level.py @@ -1,3 +1,5 @@ +from operator import attrgetter, itemgetter + from django.db import models from django.db.models import F from django.utils.translation import ugettext_lazy as _ @@ -9,7 +11,7 @@ from c3nav.mapdata.models import Level from c3nav.mapdata.models.access import AccessRestrictionMixin from c3nav.mapdata.models.geometry.base import GeometryMixin from c3nav.mapdata.models.locations import SpecificLocation -from c3nav.mapdata.utils.geometry import assert_multilinestring, assert_multipolygon +from c3nav.mapdata.utils.geometry import assert_multilinestring, assert_multipolygon, clean_geometry class LevelGeometryMixin(GeometryMixin): @@ -194,7 +196,9 @@ class AltitudeArea(LevelGeometryMixin, models.Model): all_areas.extend(areas) # give temporary ids to all areas - areas = all_areas + for area in areas: + area.geometry = clean_geometry(area.geometry) + areas = [area for area in all_areas if not area.geometry.is_empty] for i, area in enumerate(areas): area.tmpid = i for area in areas: @@ -303,3 +307,56 @@ class AltitudeArea(LevelGeometryMixin, models.Model): for tmpid in areas_without_altitude: area = areas[tmpid] area.altitude = area.level.base_altitude + + # save to database + from c3nav.mapdata.models import MapUpdate + with MapUpdate.lock(): + areas_to_save = set(range(len(areas))) + + level_areas = {} + for area in areas: + level_areas.setdefault(area.level, set()).add(area.tmpid) + + all_candidates = AltitudeArea.objects.select_related('level') + for candidate in all_candidates: + candidate.area = candidate.geometry.area + all_candidates = sorted(all_candidates, key=attrgetter('area'), reverse=True) + + num_modified = 0 + num_deleted = 0 + num_created = 0 + + for candidate in all_candidates: + new_area = None + for tmpid in level_areas.get(candidate.level, set()): + area = areas[tmpid] + if area.geometry.almost_equals(candidate.geometry, 1): + new_area = area + break + + if new_area is None: + potential_areas = [(tmpid, areas[tmpid].geometry.intersection(candidate.geometry).area) + for tmpid in level_areas.get(candidate.level, set())] + potential_areas = [(tmpid, size) for tmpid, size in potential_areas + if candidate.area and size/candidate.area > 0.9] + if potential_areas: + num_modified += 1 + new_area = areas[max(potential_areas, key=itemgetter(1))[0]] + + if new_area is None: + candidate.delete() + num_deleted += 1 + continue + + candidate.geometry = new_area.geometry + candidate.altitude = new_area.altitude + candidate.save() + areas_to_save.discard(new_area.tmpid) + level_areas[new_area.level].discard(new_area.tmpid) + + for tmpid in areas_to_save: + num_created += 1 + areas[tmpid].save() + + print(_('%d altitude areas built.') % len(areas)) + print(_('%d modified, %d deleted, %d created.') % (num_modified, num_deleted, num_created))