diff --git a/src/c3nav/mapdata/api.py b/src/c3nav/mapdata/api.py index 51ab22b0..3a8fe401 100644 --- a/src/c3nav/mapdata/api.py +++ b/src/c3nav/mapdata/api.py @@ -17,6 +17,7 @@ from rest_framework.viewsets import GenericViewSet, ReadOnlyModelViewSet, ViewSe from c3nav.mapdata.models import AccessRestriction, Building, Door, Hole, LocationGroup, MapUpdate, Source, Space from c3nav.mapdata.models.access import AccessPermission +from c3nav.mapdata.models.geometry.base import GeometryMixin from c3nav.mapdata.models.geometry.level import LevelGeometryMixin from c3nav.mapdata.models.geometry.space import POI, Area, Column, LineObstacle, Obstacle, SpaceGeometryMixin, Stair from c3nav.mapdata.models.level import Level @@ -300,10 +301,14 @@ class LocationViewSet(RetrieveModelMixin, GenericViewSet): for obj in queryset: # noinspection PyStatementEffect obj.subtitle, obj.order + if isinstance(obj, GeometryMixin): + # noinspection PyStatementEffect + obj.centroid cache.set(queryset_cache_key, queryset, 300) - result = tuple(obj.serialize(include_type=True, detailed=detailed, geometry=geometry) for obj in queryset) + result = tuple(obj.serialize(include_type=True, detailed=detailed, geometry=geometry, simple_geometry=True) + for obj in queryset) cache.set(cache_key, result, 300) return Response(result) diff --git a/src/c3nav/mapdata/models/geometry/base.py b/src/c3nav/mapdata/models/geometry/base.py index 0b182d9b..5ff700c5 100644 --- a/src/c3nav/mapdata/models/geometry/base.py +++ b/src/c3nav/mapdata/models/geometry/base.py @@ -1,6 +1,8 @@ +import math from collections import OrderedDict from django.db import models +from django.utils.functional import cached_property from django.utils.translation import ugettext_lazy as _ from shapely.geometry import Point, mapping @@ -59,16 +61,25 @@ class GeometryMixin(SerializableMixin): result['geomtype'] = cls._meta.get_field('geometry').geomtype return result + @cached_property + def centroid(self): + return self.geometry.centroid + def serialize(self, geometry=True, **kwargs): result = super().serialize(geometry=geometry, **kwargs) if geometry: result.move_to_end('geometry') return result - def _serialize(self, geometry=True, **kwargs): - result = super()._serialize(**kwargs) + def _serialize(self, geometry=True, simple_geometry=False, **kwargs): + result = super()._serialize(simple_geometry=simple_geometry, **kwargs) if geometry: result['geometry'] = format_geojson(mapping(self.geometry), round=False) + if simple_geometry: + result['point'] = (self.level_id, ) + tuple(round(i, 2) for i in self.centroid.coords[0]) + if not isinstance(self.geometry, Point): + result['bounds'] = ((int(math.floor(self.miny)), int(math.floor(self.minx))), + (int(math.ceil(self.maxy)), int(math.ceil(self.maxx)))) return result def get_shadow_geojson(self): diff --git a/src/c3nav/mapdata/models/geometry/space.py b/src/c3nav/mapdata/models/geometry/space.py index 30855049..d96dfa8f 100644 --- a/src/c3nav/mapdata/models/geometry/space.py +++ b/src/c3nav/mapdata/models/geometry/space.py @@ -1,4 +1,5 @@ from django.db import models +from django.utils.functional import cached_property from django.utils.text import format_lazy from django.utils.translation import ugettext_lazy as _ from shapely.geometry import CAP_STYLE, JOIN_STYLE, mapping @@ -16,11 +17,9 @@ class SpaceGeometryMixin(GeometryMixin): class Meta: abstract = True - def _serialize(self, space=True, **kwargs): - result = super()._serialize(**kwargs) - if space: - result['space'] = self.space_id - return result + @cached_property + def level_id(self): + return self.space.level_id def get_geojson_properties(self, *args, **kwargs) -> dict: result = super().get_geojson_properties(*args, **kwargs) diff --git a/src/c3nav/mapdata/models/locations.py b/src/c3nav/mapdata/models/locations.py index 548b677c..2bd67a80 100644 --- a/src/c3nav/mapdata/models/locations.py +++ b/src/c3nav/mapdata/models/locations.py @@ -83,7 +83,8 @@ class Location(LocationSlug, AccessRestrictionMixin, TitledMixin, models.Model): result = super().serialize(detailed=detailed, **kwargs) if not detailed: result = OrderedDict(( - (name, result[name]) for name in ('slug', 'title', 'subtitle') + (name, result[name]) for name in ('id', 'slug', 'title', 'subtitle', 'point', 'bounds', 'locations') + if name in result )) return result @@ -246,10 +247,12 @@ class LocationGroup(Location, models.Model): self.orig_category_id = self.category_id self.orig_color = self.color - def _serialize(self, **kwargs): - result = super()._serialize(**kwargs) + def _serialize(self, simple_geometry=False, **kwargs): + result = super()._serialize(simple_geometry=simple_geometry, **kwargs) result['category'] = self.category_id result['color'] = self.color + if simple_geometry: + result['locations'] = tuple(obj.pk for obj in getattr(self, 'locations', ())) return result @property diff --git a/src/c3nav/mapdata/utils/json.py b/src/c3nav/mapdata/utils/json.py index ebcc810c..302390de 100644 --- a/src/c3nav/mapdata/utils/json.py +++ b/src/c3nav/mapdata/utils/json.py @@ -6,7 +6,7 @@ def _preencode(data, magic_marker, in_coords=False, in_groups=False): if isinstance(data, dict): data = data.copy() for name, value in tuple(data.items()): - if name == 'bounds' and isinstance(value, (tuple, list)): + if name in ('bounds', 'point', 'locations') and isinstance(value, (tuple, list)): data[name] = magic_marker+json.dumps(value)+magic_marker else: data[name] = _preencode(value, magic_marker,