add LineObstacle and various improvements
This commit is contained in:
parent
06aec21669
commit
0f81d1e49a
9 changed files with 150 additions and 5 deletions
|
@ -99,7 +99,7 @@ class MapitemFormMixin(ModelForm):
|
||||||
|
|
||||||
def create_editor_form(mapitemtype):
|
def create_editor_form(mapitemtype):
|
||||||
possible_fields = ['name', 'package', 'altitude', 'level', 'intermediate', 'levels', 'geometry',
|
possible_fields = ['name', 'package', 'altitude', 'level', 'intermediate', 'levels', 'geometry',
|
||||||
'elevator', 'button', 'crop_to_level']
|
'elevator', 'button', 'crop_to_level', 'width']
|
||||||
existing_fields = [field for field in possible_fields if hasattr(mapitemtype, field)]
|
existing_fields = [field for field in possible_fields if hasattr(mapitemtype, field)]
|
||||||
|
|
||||||
class EditorForm(MapitemFormMixin, ModelForm):
|
class EditorForm(MapitemFormMixin, ModelForm):
|
||||||
|
|
|
@ -261,6 +261,7 @@ editor = {
|
||||||
'building': '#333333',
|
'building': '#333333',
|
||||||
'room': '#FFFFFF',
|
'room': '#FFFFFF',
|
||||||
'outside': '#EEFFEE',
|
'outside': '#EEFFEE',
|
||||||
|
'lineobstacle': '#999999',
|
||||||
'obstacle': '#999999',
|
'obstacle': '#999999',
|
||||||
'door': '#FF00FF',
|
'door': '#FF00FF',
|
||||||
'hole': '#66CC66',
|
'hole': '#66CC66',
|
||||||
|
|
|
@ -10,7 +10,7 @@ from rest_framework.response import Response
|
||||||
from rest_framework.viewsets import ReadOnlyModelViewSet, ViewSet
|
from rest_framework.viewsets import ReadOnlyModelViewSet, ViewSet
|
||||||
|
|
||||||
from c3nav.mapdata.models import GEOMETRY_MAPITEM_TYPES, Level, Package, Source
|
from c3nav.mapdata.models import GEOMETRY_MAPITEM_TYPES, Level, Package, Source
|
||||||
from c3nav.mapdata.models.geometry import LineGeometryMapItemWithLevel
|
from c3nav.mapdata.models.geometry import DirectedLineGeometryMapItemWithLevel
|
||||||
from c3nav.mapdata.permissions import filter_queryset_by_package_access, get_unlocked_packages_names
|
from c3nav.mapdata.permissions import filter_queryset_by_package_access, get_unlocked_packages_names
|
||||||
from c3nav.mapdata.serializers.main import LevelSerializer, PackageSerializer, SourceSerializer
|
from c3nav.mapdata.serializers.main import LevelSerializer, PackageSerializer, SourceSerializer
|
||||||
from c3nav.mapdata.utils.cache import (CachedReadOnlyViewSetMixin, cache_mapdata_api_response, get_levels_cached,
|
from c3nav.mapdata.utils.cache import (CachedReadOnlyViewSetMixin, cache_mapdata_api_response, get_levels_cached,
|
||||||
|
@ -93,7 +93,7 @@ class GeometryViewSet(ViewSet):
|
||||||
if hasattr(mapitemtype, field_name):
|
if hasattr(mapitemtype, field_name):
|
||||||
queryset.prefetch_related(field_name)
|
queryset.prefetch_related(field_name)
|
||||||
|
|
||||||
if issubclass(mapitemtype, LineGeometryMapItemWithLevel):
|
if issubclass(mapitemtype, DirectedLineGeometryMapItemWithLevel):
|
||||||
results.extend(obj.to_shadow_geojson() for obj in queryset)
|
results.extend(obj.to_shadow_geojson() for obj in queryset)
|
||||||
|
|
||||||
results.extend(obj.to_geojson() for obj in queryset)
|
results.extend(obj.to_geojson() for obj in queryset)
|
||||||
|
|
33
src/c3nav/mapdata/migrations/0014_lineobstacle.py
Normal file
33
src/c3nav/mapdata/migrations/0014_lineobstacle.py
Normal file
|
@ -0,0 +1,33 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
# Generated by Django 1.10.4 on 2016-12-08 20:20
|
||||||
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
|
import c3nav.mapdata.fields
|
||||||
|
from django.db import migrations, models
|
||||||
|
import django.db.models.deletion
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('mapdata', '0013_auto_20161208_0937'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.CreateModel(
|
||||||
|
name='LineObstacle',
|
||||||
|
fields=[
|
||||||
|
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||||
|
('name', models.SlugField(unique=True, verbose_name='Name')),
|
||||||
|
('geometry', c3nav.mapdata.fields.GeometryField()),
|
||||||
|
('altitude', models.DecimalField(decimal_places=2, max_digits=4, verbose_name='obstacle width')),
|
||||||
|
('level', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='lineobstacles', to='mapdata.Level', verbose_name='level')),
|
||||||
|
('package', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='lineobstacles', to='mapdata.Package', verbose_name='map package')),
|
||||||
|
],
|
||||||
|
options={
|
||||||
|
'verbose_name_plural': 'Line Obstacles',
|
||||||
|
'default_related_name': 'lineobstacles',
|
||||||
|
'verbose_name': 'Line Obstacle',
|
||||||
|
},
|
||||||
|
),
|
||||||
|
]
|
20
src/c3nav/mapdata/migrations/0015_auto_20161208_2020.py
Normal file
20
src/c3nav/mapdata/migrations/0015_auto_20161208_2020.py
Normal file
|
@ -0,0 +1,20 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
# Generated by Django 1.10.4 on 2016-12-08 20:20
|
||||||
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('mapdata', '0014_lineobstacle'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name='lineobstacle',
|
||||||
|
name='altitude',
|
||||||
|
field=models.DecimalField(decimal_places=2, default=0.2, max_digits=4, verbose_name='obstacle width'),
|
||||||
|
),
|
||||||
|
]
|
20
src/c3nav/mapdata/migrations/0016_auto_20161208_2023.py
Normal file
20
src/c3nav/mapdata/migrations/0016_auto_20161208_2023.py
Normal file
|
@ -0,0 +1,20 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
# Generated by Django 1.10.4 on 2016-12-08 20:23
|
||||||
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
|
from django.db import migrations
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('mapdata', '0015_auto_20161208_2020'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.RenameField(
|
||||||
|
model_name='lineobstacle',
|
||||||
|
old_name='altitude',
|
||||||
|
new_name='width',
|
||||||
|
),
|
||||||
|
]
|
20
src/c3nav/mapdata/migrations/0017_auto_20161208_2039.py
Normal file
20
src/c3nav/mapdata/migrations/0017_auto_20161208_2039.py
Normal file
|
@ -0,0 +1,20 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
# Generated by Django 1.10.4 on 2016-12-08 20:39
|
||||||
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('mapdata', '0016_auto_20161208_2023'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name='lineobstacle',
|
||||||
|
name='width',
|
||||||
|
field=models.DecimalField(decimal_places=2, default=0.15, max_digits=4, verbose_name='obstacle width'),
|
||||||
|
),
|
||||||
|
]
|
|
@ -103,7 +103,7 @@ class GeometryMapItemWithLevel(GeometryMapItem):
|
||||||
return result
|
return result
|
||||||
|
|
||||||
|
|
||||||
class LineGeometryMapItemWithLevel(GeometryMapItemWithLevel):
|
class DirectedLineGeometryMapItemWithLevel(GeometryMapItemWithLevel):
|
||||||
geomtype = 'polyline'
|
geomtype = 'polyline'
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
|
@ -168,7 +168,7 @@ class Outside(GeometryMapItemWithLevel):
|
||||||
default_related_name = 'outsides'
|
default_related_name = 'outsides'
|
||||||
|
|
||||||
|
|
||||||
class Stair(LineGeometryMapItemWithLevel):
|
class Stair(DirectedLineGeometryMapItemWithLevel):
|
||||||
"""
|
"""
|
||||||
A stair
|
A stair
|
||||||
"""
|
"""
|
||||||
|
@ -178,6 +178,48 @@ class Stair(LineGeometryMapItemWithLevel):
|
||||||
default_related_name = 'stairs'
|
default_related_name = 'stairs'
|
||||||
|
|
||||||
|
|
||||||
|
class LineObstacle(GeometryMapItemWithLevel):
|
||||||
|
"""
|
||||||
|
An obstacle that is a line with a specific width
|
||||||
|
"""
|
||||||
|
width = models.DecimalField(_('obstacle width'), max_digits=4, decimal_places=2, default=0.15)
|
||||||
|
|
||||||
|
geomtype = 'polyline'
|
||||||
|
|
||||||
|
class Meta:
|
||||||
|
verbose_name = _('Line Obstacle')
|
||||||
|
verbose_name_plural = _('Line Obstacles')
|
||||||
|
default_related_name = 'lineobstacles'
|
||||||
|
|
||||||
|
def to_geojson(self):
|
||||||
|
result = super().to_geojson()
|
||||||
|
original_geometry = result['geometry']
|
||||||
|
draw = self.geometry.buffer(self.width/2, join_style=JOIN_STYLE.mitre, cap_style=CAP_STYLE.flat)
|
||||||
|
result['geometry'] = format_geojson(mapping(draw))
|
||||||
|
result['original_geometry'] = original_geometry
|
||||||
|
return result
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def fromfile(cls, data, file_path):
|
||||||
|
kwargs = super().fromfile(data, file_path)
|
||||||
|
|
||||||
|
if 'width' not in data:
|
||||||
|
raise ValueError('missing width.')
|
||||||
|
kwargs['width'] = data['width']
|
||||||
|
|
||||||
|
return kwargs
|
||||||
|
|
||||||
|
def get_geojson_properties(self):
|
||||||
|
result = super().get_geojson_properties()
|
||||||
|
result['width'] = float(self.width)
|
||||||
|
return result
|
||||||
|
|
||||||
|
def tofile(self):
|
||||||
|
result = super().tofile()
|
||||||
|
result['width'] = float(self.width)
|
||||||
|
return result
|
||||||
|
|
||||||
|
|
||||||
class Obstacle(GeometryMapItemWithLevel):
|
class Obstacle(GeometryMapItemWithLevel):
|
||||||
"""
|
"""
|
||||||
An obstacle
|
An obstacle
|
||||||
|
|
|
@ -104,6 +104,14 @@ class LevelGeometries():
|
||||||
def mapped(self):
|
def mapped(self):
|
||||||
return cascaded_union([self.buildings, self.outsides])
|
return cascaded_union([self.buildings, self.outsides])
|
||||||
|
|
||||||
|
@cached_property
|
||||||
|
def lineobstacles(self):
|
||||||
|
lineobstacles = []
|
||||||
|
for obstacle in self.level.lineobstacles.all():
|
||||||
|
lineobstacles.append(obstacle.geometry.buffer(obstacle.width/2,
|
||||||
|
join_style=JOIN_STYLE.mitre, cap_style=CAP_STYLE.flat))
|
||||||
|
return cascaded_union(lineobstacles)
|
||||||
|
|
||||||
@cached_property
|
@cached_property
|
||||||
def obstacles(self):
|
def obstacles(self):
|
||||||
levels_by_name = {}
|
levels_by_name = {}
|
||||||
|
@ -119,6 +127,7 @@ class LevelGeometries():
|
||||||
if level_name is not None:
|
if level_name is not None:
|
||||||
obstacles = obstacles.intersection(levels_by_name[level_name].geometries.mapped)
|
obstacles = obstacles.intersection(levels_by_name[level_name].geometries.mapped)
|
||||||
all_obstacles.append(obstacles)
|
all_obstacles.append(obstacles)
|
||||||
|
all_obstacles.extend(self.lineobstacles)
|
||||||
|
|
||||||
return cascaded_union(all_obstacles).intersection(self.mapped)
|
return cascaded_union(all_obstacles).intersection(self.mapped)
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue