team-3/src/c3nav/mapdata/models/geometry/space.py

144 lines
4.4 KiB
Python
Raw Normal View History

2016-11-27 14:03:39 +01:00
from collections import OrderedDict
2017-05-08 21:55:45 +02:00
from django.db import models
from django.utils.translation import ugettext_lazy as _
2017-05-07 12:06:13 +02:00
from shapely.geometry import CAP_STYLE, JOIN_STYLE, mapping
from c3nav.mapdata.fields import GeometryField
2017-05-08 16:40:22 +02:00
from c3nav.mapdata.models.geometry.base import GeometryMixin
2017-05-10 18:03:57 +02:00
from c3nav.mapdata.models.locations import SpecificLocation
2016-12-07 16:11:33 +01:00
from c3nav.mapdata.utils.json import format_geojson
2017-05-11 19:36:49 +02:00
SPACE_MODELS = []
2016-12-01 12:25:02 +01:00
2017-05-08 16:40:22 +02:00
class SpaceGeometryMixin(GeometryMixin):
space = models.ForeignKey('mapdata.Space', on_delete=models.CASCADE, verbose_name=_('space'))
class Meta:
abstract = True
2017-05-11 19:36:49 +02:00
def _serialize(self, space=True, **kwargs):
result = super()._serialize(**kwargs)
if space:
result['space'] = self.space.id
2017-05-04 15:44:32 +02:00
return result
2017-05-10 18:03:57 +02:00
class Area(SpecificLocation, SpaceGeometryMixin, models.Model):
"""
An area in a space.
"""
geometry = GeometryField('polygon')
stuffed = models.BooleanField(verbose_name=_('stuffed area'), default=False)
class Meta:
verbose_name = _('Area')
verbose_name_plural = _('Areas')
2017-05-10 15:27:37 +02:00
default_related_name = 'areas'
2017-05-11 19:36:49 +02:00
def _serialize(self, **kwargs):
result = super()._serialize(**kwargs)
result['stuffed'] = self.stuffed
return result
2017-05-13 21:32:13 +02:00
def get_color(self):
color = super().get_color()
if not color and self.stuffed:
color = 'rgba(0, 0, 0, 0.04)'
return color
2017-05-08 16:40:22 +02:00
class Stair(SpaceGeometryMixin, models.Model):
2016-12-08 18:12:07 +01:00
"""
A stair
"""
geometry = GeometryField('linestring')
2016-12-08 18:12:07 +01:00
class Meta:
verbose_name = _('Stair')
verbose_name_plural = _('Stairs')
default_related_name = 'stairs'
def to_geojson(self):
result = super().to_geojson()
original_geometry = result['geometry']
draw = self.geometry.buffer(0.05, join_style=JOIN_STYLE.mitre, cap_style=CAP_STYLE.flat)
result['geometry'] = format_geojson(mapping(draw))
result['original_geometry'] = original_geometry
return result
def to_shadow_geojson(self):
shadow = self.geometry.parallel_offset(0.03, 'right', join_style=JOIN_STYLE.mitre)
shadow = shadow.buffer(0.019, join_style=JOIN_STYLE.mitre, cap_style=CAP_STYLE.flat)
return OrderedDict((
('type', 'Feature'),
('properties', OrderedDict((
('type', 'shadow'),
('original_type', self.__class__.__name__.lower()),
('original_id', self.id),
))),
('geometry', format_geojson(mapping(shadow), round=False)),
))
2016-12-08 18:12:07 +01:00
2017-05-08 16:40:22 +02:00
class Obstacle(SpaceGeometryMixin, models.Model):
"""
2016-12-09 14:49:20 +01:00
An obstacle
"""
geometry = GeometryField('polygon')
class Meta:
2016-12-09 14:49:20 +01:00
verbose_name = _('Obstacle')
verbose_name_plural = _('Obstacles')
default_related_name = 'obstacles'
2017-05-08 16:40:22 +02:00
class LineObstacle(SpaceGeometryMixin, models.Model):
2016-12-01 12:25:02 +01:00
"""
2016-12-09 14:49:20 +01:00
An obstacle that is a line with a specific width
2016-12-01 12:25:02 +01:00
"""
geometry = GeometryField('linestring')
2016-12-09 14:49:20 +01:00
width = models.DecimalField(_('obstacle width'), max_digits=4, decimal_places=2, default=0.15)
2016-12-04 20:01:37 +01:00
2016-12-01 12:25:02 +01:00
class Meta:
2016-12-09 14:49:20 +01:00
verbose_name = _('Line Obstacle')
verbose_name_plural = _('Line Obstacles')
default_related_name = 'lineobstacles'
2017-05-11 19:36:49 +02:00
def serialize(self, geometry=True, **kwargs):
result = super().serialize(geometry=geometry, **kwargs)
if geometry:
result.move_to_end('buffered_geometry')
return result
def _serialize(self, geometry=True, **kwargs):
result = super()._serialize(geometry=geometry, **kwargs)
result['width'] = float(str(self.width))
if geometry:
result['buffered_geometry'] = format_geojson(mapping(self.buffered_geometry))
return result
2017-05-04 15:44:32 +02:00
@property
def buffered_geometry(self):
return self.geometry.buffer(self.width / 2, join_style=JOIN_STYLE.mitre, cap_style=CAP_STYLE.flat)
2016-12-09 14:49:20 +01:00
def to_geojson(self):
result = super().to_geojson()
original_geometry = result['geometry']
2017-05-04 15:44:32 +02:00
result['geometry'] = format_geojson(mapping(self.buffered_geometry))
2016-12-09 14:49:20 +01:00
result['original_geometry'] = original_geometry
return result
2016-12-01 12:25:02 +01:00
2017-05-10 15:30:54 +02:00
2017-05-10 18:03:57 +02:00
class Point(SpecificLocation, SpaceGeometryMixin, models.Model):
2017-05-10 15:30:54 +02:00
"""
An point in a space.
"""
geometry = GeometryField('point')
class Meta:
verbose_name = _('Point')
verbose_name_plural = _('Points')
default_related_name = 'points'