diff --git a/src/c3nav/editor/api.py b/src/c3nav/editor/api.py index 0d511964..2adcc3b7 100644 --- a/src/c3nav/editor/api.py +++ b/src/c3nav/editor/api.py @@ -24,11 +24,11 @@ class EditorViewSet(ViewSet): if space is not None: raise ValidationError('Only section or space can be specified.') section = get_object_or_404(Section, pk=section) - holes = section.holes.all() - holes_geom = cascaded_union([hole.geometry for hole in holes]) buildings = section.buildings.all() buildings_geom = cascaded_union([building.geometry for building in buildings]) - spaces = {space.id: space for space in section.spaces.all().prefetch_related('groups')} + spaces = {space.id: space for space in section.spaces.all().prefetch_related('groups', 'holes')} + holes = sum((list(space.holes.all()) for space in spaces.values()), []) + holes_geom = cascaded_union([hole.geometry for hole in holes]) for space in spaces.values(): if space.outside: space.geometry = space.geometry.difference(buildings_geom) @@ -79,6 +79,7 @@ class EditorViewSet(ViewSet): spaces, [space], space.areas.all().prefetch_related('groups'), + space.holes.all(), space.stairs.all(), space.obstacles.all(), space.lineobstacles.all(), diff --git a/src/c3nav/editor/urls.py b/src/c3nav/editor/urls.py index d972ae9a..e7d5d2f7 100644 --- a/src/c3nav/editor/urls.py +++ b/src/c3nav/editor/urls.py @@ -39,7 +39,7 @@ urlpatterns.extend(add_editor_urls('Source')) urlpatterns.extend(add_editor_urls('Building', 'Section')) urlpatterns.extend(add_editor_urls('Space', 'Section', explicit_edit=True)) urlpatterns.extend(add_editor_urls('Door', 'Section')) -urlpatterns.extend(add_editor_urls('Hole', 'Section')) +urlpatterns.extend(add_editor_urls('Hole', 'Space')) urlpatterns.extend(add_editor_urls('Area', 'Space')) urlpatterns.extend(add_editor_urls('Stair', 'Space')) urlpatterns.extend(add_editor_urls('Obstacle', 'Space')) diff --git a/src/c3nav/editor/views.py b/src/c3nav/editor/views.py index 4aebee5c..8da4cd9d 100644 --- a/src/c3nav/editor/views.py +++ b/src/c3nav/editor/views.py @@ -58,7 +58,7 @@ def section_detail(request, pk): 'section_as_pk': True, 'child_models': [child_model(model_name, kwargs={'section': pk}, parent=section) - for model_name in ('Building', 'Space', 'Door', 'Hole')], + for model_name in ('Building', 'Space', 'Door')], 'geometry_url': '/api/editor/geometries/?section='+pk, }) @@ -72,7 +72,7 @@ def space_detail(request, section, pk): 'space': space, 'child_models': [child_model(model_name, kwargs={'space': pk}, parent=space) - for model_name in ('Area', 'Stair', 'Obstacle', 'LineObstacle', 'Point')], + for model_name in ('Hole', 'Area', 'Stair', 'Obstacle', 'LineObstacle', 'Point')], 'geometry_url': '/api/editor/geometries/?space='+pk, }) diff --git a/src/c3nav/mapdata/api.py b/src/c3nav/mapdata/api.py index 0cc42751..62e0dfc2 100644 --- a/src/c3nav/mapdata/api.py +++ b/src/c3nav/mapdata/api.py @@ -84,7 +84,7 @@ class DoorViewSet(MapdataViewSet): class HoleViewSet(MapdataViewSet): - """ Add ?geometry=1 to get geometries, add ?section= to filter by section. """ + """ Add ?geometry=1 to get geometries, add ?space= to filter by space. """ queryset = Hole.objects.all() diff --git a/src/c3nav/mapdata/migrations/0007_assign_hole_space.py b/src/c3nav/mapdata/migrations/0007_assign_hole_space.py new file mode 100644 index 00000000..0fcc8a0e --- /dev/null +++ b/src/c3nav/mapdata/migrations/0007_assign_hole_space.py @@ -0,0 +1,33 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.10.7 on 2017-06-08 13:01 +from __future__ import unicode_literals + +from django.db import migrations, models +import django.db.models.deletion + + +def assign_hole_to_space(apps, schema_editor): + Hole = apps.get_model('mapdata', 'Hole') + Space = apps.get_model('mapdata', 'Space') + for hole in Hole.objects.filter(): + space = max(hole.section.spaces.filter(level='normal'), + key=lambda s: s.geometry.intersection(hole.geometry).area) + hole.space = space + hole.save() + + +class Migration(migrations.Migration): + + dependencies = [ + ('mapdata', '0006_remove_section_name'), + ] + + operations = [ + migrations.AddField( + model_name='hole', + name='space', + field=models.ForeignKey(default=0, on_delete=django.db.models.deletion.CASCADE, related_name='holes', to='mapdata.Space', verbose_name='space'), + preserve_default=False, + ), + migrations.RunPython(assign_hole_to_space), + ] diff --git a/src/c3nav/mapdata/migrations/0008_auto_20170608_1317.py b/src/c3nav/mapdata/migrations/0008_auto_20170608_1317.py new file mode 100644 index 00000000..ea9cb7c9 --- /dev/null +++ b/src/c3nav/mapdata/migrations/0008_auto_20170608_1317.py @@ -0,0 +1,44 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.10.7 on 2017-06-08 13:17 +from __future__ import unicode_literals + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('mapdata', '0007_assign_hole_space'), + ] + + operations = [ + migrations.RemoveField( + model_name='hole', + name='section', + ), + migrations.AlterField( + model_name='area', + name='color', + field=models.CharField(blank=True, max_length=16, null=True, verbose_name='background color'), + ), + migrations.AlterField( + model_name='locationgroup', + name='color', + field=models.CharField(blank=True, max_length=16, null=True, verbose_name='background color'), + ), + migrations.AlterField( + model_name='point', + name='color', + field=models.CharField(blank=True, max_length=16, null=True, verbose_name='background color'), + ), + migrations.AlterField( + model_name='section', + name='color', + field=models.CharField(blank=True, max_length=16, null=True, verbose_name='background color'), + ), + migrations.AlterField( + model_name='space', + name='color', + field=models.CharField(blank=True, max_length=16, null=True, verbose_name='background color'), + ), + ] diff --git a/src/c3nav/mapdata/models/__init__.py b/src/c3nav/mapdata/models/__init__.py index e1b0d4e1..e6458bcd 100644 --- a/src/c3nav/mapdata/models/__init__.py +++ b/src/c3nav/mapdata/models/__init__.py @@ -1,5 +1,5 @@ from .section import Section # noqa from .source import Source # noqa -from c3nav.mapdata.models.geometry.section import Building, Space, Hole, Door # noqa -from c3nav.mapdata.models.geometry.space import Area, Stair, Obstacle, LineObstacle # noqa +from c3nav.mapdata.models.geometry.section import Building, Space, Door # noqa +from c3nav.mapdata.models.geometry.space import Area, Stair, Obstacle, LineObstacle, Hole # noqa from .locations import Location, LocationSlug, LocationGroup # noqa diff --git a/src/c3nav/mapdata/models/geometry/section.py b/src/c3nav/mapdata/models/geometry/section.py index 8c65ba0c..da655f58 100644 --- a/src/c3nav/mapdata/models/geometry/section.py +++ b/src/c3nav/mapdata/models/geometry/section.py @@ -96,15 +96,3 @@ class Door(SectionGeometryMixin, models.Model): verbose_name = _('Door') verbose_name_plural = _('Doors') default_related_name = 'doors' - - -class Hole(SectionGeometryMixin, models.Model): - """ - A hole in the ground of a section (all spaces with layer "normal" and buildings), e.g. for stairs. - """ - geometry = GeometryField('polygon') - - class Meta: - verbose_name = _('Hole') - verbose_name_plural = _('Holes') - default_related_name = 'holes' diff --git a/src/c3nav/mapdata/models/geometry/space.py b/src/c3nav/mapdata/models/geometry/space.py index f85d23f2..53c2d05a 100644 --- a/src/c3nav/mapdata/models/geometry/space.py +++ b/src/c3nav/mapdata/models/geometry/space.py @@ -158,3 +158,15 @@ class Point(SpecificLocation, SpaceGeometryMixin, models.Model): result['original_geometry'] = result['geometry'] result['geometry'] = format_geojson(mapping(self.buffered_geometry)) return result + + +class Hole(SpaceGeometryMixin, models.Model): + """ + A hole in the ground of a space, e.g. for stairs. + """ + geometry = GeometryField('polygon') + + class Meta: + verbose_name = _('Hole') + verbose_name_plural = _('Holes') + default_related_name = 'holes'