change altitudearea model to support multiple points
This commit is contained in:
parent
02411b0181
commit
732cd8a4ea
2 changed files with 90 additions and 6 deletions
|
@ -0,0 +1,67 @@
|
||||||
|
# Generated by Django 5.0.8 on 2024-08-17 17:50
|
||||||
|
|
||||||
|
import django.core.serializers.json
|
||||||
|
import django_pydantic_field.compat.django
|
||||||
|
import django_pydantic_field.fields
|
||||||
|
import types
|
||||||
|
import typing
|
||||||
|
from django.db import migrations, models
|
||||||
|
from shapely.geometry import Point
|
||||||
|
|
||||||
|
from c3nav.mapdata.models.geometry.level import AltitudeAreaPoint
|
||||||
|
|
||||||
|
|
||||||
|
def forwards_func(apps, schema_editor):
|
||||||
|
AltitudeArea = apps.get_model('mapdata', 'AltitudeArea')
|
||||||
|
for area in AltitudeArea.objects.all():
|
||||||
|
if area.point1 is not None:
|
||||||
|
area.points = [
|
||||||
|
AltitudeAreaPoint(coordinates=[area.point1.x, area.point1.y], altitude=float(area.altitude1)),
|
||||||
|
AltitudeAreaPoint(coordinates=[area.point2.x, area.point2.y], altitude=float(area.altitude))
|
||||||
|
]
|
||||||
|
area.altitude = None
|
||||||
|
area.save()
|
||||||
|
|
||||||
|
|
||||||
|
def backwards_func(apps, schema_editor):
|
||||||
|
AltitudeArea = apps.get_model('mapdata', 'AltitudeArea')
|
||||||
|
for area in AltitudeArea.objects.all():
|
||||||
|
if area.points is not None:
|
||||||
|
area.point1 = Point(*area.points[0].coordinates)
|
||||||
|
area.point2 = Point(*area.points[-1].coordinates)
|
||||||
|
area.altitude = area.points[0].altitude
|
||||||
|
area.altitude2 = area.points[-1].altitude
|
||||||
|
area.save()
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('mapdata', '0106_rename_wifi_to_beaconmeasurement'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='altitudearea',
|
||||||
|
name='points',
|
||||||
|
field=django_pydantic_field.fields.PydanticSchemaField(config=None, encoder=django.core.serializers.json.DjangoJSONEncoder, null=True, schema=django_pydantic_field.compat.django.GenericContainer(typing.Union, (django_pydantic_field.compat.django.GenericContainer(list, (AltitudeAreaPoint,)), types.NoneType))),
|
||||||
|
),
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name='altitudearea',
|
||||||
|
name='altitude',
|
||||||
|
field=models.DecimalField(decimal_places=2, max_digits=6, null=True, verbose_name='altitude'),
|
||||||
|
),
|
||||||
|
migrations.RunPython(forwards_func, backwards_func),
|
||||||
|
migrations.RemoveField(
|
||||||
|
model_name='altitudearea',
|
||||||
|
name='altitude2',
|
||||||
|
),
|
||||||
|
migrations.RemoveField(
|
||||||
|
model_name='altitudearea',
|
||||||
|
name='point1',
|
||||||
|
),
|
||||||
|
migrations.RemoveField(
|
||||||
|
model_name='altitudearea',
|
||||||
|
name='point2',
|
||||||
|
),
|
||||||
|
]
|
|
@ -3,20 +3,26 @@ from collections import deque
|
||||||
from decimal import Decimal
|
from decimal import Decimal
|
||||||
from itertools import chain, combinations
|
from itertools import chain, combinations
|
||||||
from operator import attrgetter, itemgetter
|
from operator import attrgetter, itemgetter
|
||||||
|
from typing import Sequence, Optional
|
||||||
|
|
||||||
import numpy as np
|
import numpy as np
|
||||||
from django.core.validators import MinValueValidator
|
from django.core.validators import MinValueValidator
|
||||||
from django.db import models
|
from django.db import models
|
||||||
|
from django.db.models import CheckConstraint, Q
|
||||||
from django.urls import reverse
|
from django.urls import reverse
|
||||||
from django.utils.functional import cached_property
|
from django.utils.functional import cached_property
|
||||||
from django.utils.text import format_lazy
|
from django.utils.text import format_lazy
|
||||||
from django.utils.translation import gettext_lazy as _
|
from django.utils.translation import gettext_lazy as _
|
||||||
|
from pydantic import Field as APIField
|
||||||
|
from scipy.interpolate._rbfinterp import RBFInterpolator
|
||||||
from shapely import prepared
|
from shapely import prepared
|
||||||
from shapely.affinity import scale
|
from shapely.affinity import scale
|
||||||
from shapely.geometry import JOIN_STYLE, LineString, MultiPolygon
|
from shapely.geometry import JOIN_STYLE, LineString, MultiPolygon, Point
|
||||||
from shapely.geometry.polygon import orient
|
from shapely.geometry.polygon import orient
|
||||||
|
from django_pydantic_field import SchemaField
|
||||||
from shapely.ops import unary_union
|
from shapely.ops import unary_union
|
||||||
|
|
||||||
|
from c3nav.api.schema import BaseSchema
|
||||||
from c3nav.mapdata.fields import GeometryField, I18nField
|
from c3nav.mapdata.fields import GeometryField, I18nField
|
||||||
from c3nav.mapdata.grid import grid
|
from c3nav.mapdata.grid import grid
|
||||||
from c3nav.mapdata.models import Level
|
from c3nav.mapdata.models import Level
|
||||||
|
@ -170,15 +176,26 @@ class ItemWithValue:
|
||||||
return self._func()
|
return self._func()
|
||||||
|
|
||||||
|
|
||||||
|
class AltitudeAreaPoint(BaseSchema):
|
||||||
|
coordinates: tuple[float, float] = APIField(
|
||||||
|
example=[1, 2.5]
|
||||||
|
)
|
||||||
|
altitude: float
|
||||||
|
|
||||||
|
|
||||||
class AltitudeArea(LevelGeometryMixin, models.Model):
|
class AltitudeArea(LevelGeometryMixin, models.Model):
|
||||||
"""
|
"""
|
||||||
An altitude area
|
An altitude area
|
||||||
"""
|
"""
|
||||||
geometry = GeometryField('multipolygon')
|
geometry: MultiPolygon = GeometryField('multipolygon')
|
||||||
altitude = models.DecimalField(_('altitude'), null=False, max_digits=6, decimal_places=2)
|
altitude = models.DecimalField(_('altitude'), null=True, max_digits=6, decimal_places=2)
|
||||||
altitude2 = models.DecimalField(_('second altitude'), null=True, max_digits=6, decimal_places=2)
|
points: Sequence[AltitudeAreaPoint] = SchemaField(schema=list[AltitudeAreaPoint], null=True)
|
||||||
point1 = GeometryField('point', null=True)
|
|
||||||
point2 = GeometryField('point', null=True)
|
constraints = (
|
||||||
|
CheckConstraint(check=(Q(points__isnull=True, altitude__isnull=False) |
|
||||||
|
Q(points__isnull=False, altitude__isnull=True)),
|
||||||
|
name="altitudearea_needs_precisely_one_of_altitude_or_points"),
|
||||||
|
)
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
verbose_name = _('Altitude Area')
|
verbose_name = _('Altitude Area')
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue