94 lines
3.5 KiB
Python
94 lines
3.5 KiB
Python
import os
|
|
from collections import OrderedDict, namedtuple
|
|
|
|
from django.db import models
|
|
from django.utils.translation import ugettext_lazy as _
|
|
from django.utils.translation import get_language
|
|
from shapely.geometry import mapping, shape
|
|
|
|
from c3nav.mapdata.fields import GeometryField, JSONField
|
|
from c3nav.mapdata.utils import sort_geojson
|
|
|
|
|
|
class FeatureType(namedtuple('FeatureType', ('name', 'title', 'title_plural', 'geomtype', 'color'))):
|
|
# noinspection PyUnusedLocal
|
|
def __init__(self, *args, **kwargs):
|
|
super().__init__()
|
|
FEATURE_TYPES[self.name] = self
|
|
|
|
|
|
FEATURE_TYPES = OrderedDict()
|
|
FeatureType('building', _('Building'), _('Buildings'), 'polygon', '#333333')
|
|
FeatureType('room', _('Room'), _('Rooms'), 'polygon', '#CCCCCC')
|
|
FeatureType('outside', _('Outside Area'), _('Outside Areas'), 'polygon', '#EEEEEE')
|
|
FeatureType('obstacle', _('Obstacle'), _('Obstacles'), 'polygon', '#999999')
|
|
|
|
|
|
# FeatureType('door', _('Door'), 'polygon', '#FF00FF')
|
|
# FeatureType('step', _('Step'), 'polyline', '#FF0000')
|
|
# FeatureType('elevator', _('Elevator'), 'polygon', '#99CC00')
|
|
|
|
|
|
class Feature(models.Model):
|
|
"""
|
|
A map feature
|
|
"""
|
|
TYPES = tuple((name, t.title) for name, t in FEATURE_TYPES.items())
|
|
|
|
name = models.SlugField(_('feature identifier'), primary_key=True, max_length=50)
|
|
package = models.ForeignKey('mapdata.Package', on_delete=models.CASCADE, related_name='features',
|
|
verbose_name=_('map package'))
|
|
feature_type = models.CharField(max_length=50, choices=TYPES)
|
|
level = models.ForeignKey('mapdata.Level', on_delete=models.CASCADE, related_name='features',
|
|
verbose_name=_('level'))
|
|
titles = JSONField()
|
|
geometry = GeometryField()
|
|
|
|
path_regex = r'^features/('+'|'.join(name for name, title in TYPES)+')/'
|
|
|
|
@property
|
|
def title(self):
|
|
lang = get_language()
|
|
if lang in self.titles:
|
|
return self.titles[lang]
|
|
return next(iter(self.titles.values())) if self.titles else self.name
|
|
|
|
def tofilename(self):
|
|
return 'features/%s/%s.json' % (self.feature_type, self.name)
|
|
|
|
@classmethod
|
|
def fromfile(cls, data, file_path):
|
|
kwargs = {}
|
|
kwargs['feature_type'] = file_path.split(os.path.sep)[1]
|
|
|
|
if 'geometry' not in data:
|
|
raise ValueError('missing geometry.')
|
|
try:
|
|
kwargs['geometry'] = shape(data['geometry'])
|
|
except:
|
|
raise ValueError(_('Invalid GeoJSON.'))
|
|
|
|
if 'level' not in data:
|
|
raise ValueError('missing level.')
|
|
kwargs['level'] = data['level']
|
|
|
|
if 'titles' not in data:
|
|
raise ValueError('missing titles.')
|
|
titles = data['titles']
|
|
if not isinstance(titles, dict):
|
|
raise ValueError('Invalid titles format.')
|
|
if any(not isinstance(lang, str) for lang in titles.keys()):
|
|
raise ValueError('titles: All languages have to be strings.')
|
|
if any(not isinstance(title, str) for title in titles.values()):
|
|
raise ValueError('titles: All titles have to be strings.')
|
|
if any(not title for title in titles.values()):
|
|
raise ValueError('titles: Titles must not be empty strings.')
|
|
kwargs['titles'] = titles
|
|
return kwargs
|
|
|
|
def tofile(self):
|
|
return OrderedDict((
|
|
('titles', OrderedDict(sorted(self.titles.items()))),
|
|
('level', self.level.name),
|
|
('geometry', sort_geojson(mapping(self.geometry)))
|
|
))
|