Compare commits
9 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| fa89bbba99 | |||
| 78eb711057 | |||
| 416ad8478c | |||
| 6b28c4ec15 | |||
| 46a2a4ff46 | |||
| 90e5cf5b36 | |||
| 50f46e319c | |||
| e2ea087c4e | |||
| a6e43b044b |
@@ -8,10 +8,9 @@ Created on: 04.01.22
|
||||
import datetime
|
||||
|
||||
from django.contrib.gis.db.models.functions import Area
|
||||
from django.utils.timezone import now
|
||||
|
||||
from konova.management.commands.setup import BaseKonovaCommand
|
||||
from konova.models import Geometry, Parcel, District
|
||||
from konova.models import Geometry, ParcelIntersection
|
||||
|
||||
|
||||
class Command(BaseKonovaCommand):
|
||||
@@ -35,32 +34,53 @@ class Command(BaseKonovaCommand):
|
||||
def recalculate_parcels(self, options: dict):
|
||||
force_all = options.get("force_all", False)
|
||||
|
||||
if force_all:
|
||||
geometry_objects = Geometry.objects.all()
|
||||
else:
|
||||
_today = now().date()
|
||||
_date_threshold = _today - datetime.timedelta(days=1)
|
||||
geometry_objects = Geometry.objects.filter(
|
||||
parcel_update_start__date__lte=_date_threshold,
|
||||
parcel_update_end__isnull=True
|
||||
geometry_objects = Geometry.objects.all().exclude(
|
||||
geom=None
|
||||
)
|
||||
|
||||
if not force_all:
|
||||
# Fetch all intersections
|
||||
intersection_objs = ParcelIntersection.objects.filter(
|
||||
geometry__in=geometry_objects
|
||||
)
|
||||
# Just take the geometry ids, which seem to have intersections
|
||||
geom_with_intersection_ids = intersection_objs.values_list(
|
||||
"geometry__id",
|
||||
flat=True
|
||||
)
|
||||
# ... and resolve into Geometry objects again ...
|
||||
intersected_geom_objs = Geometry.objects.filter(
|
||||
id__in=geom_with_intersection_ids
|
||||
)
|
||||
# ... to be able to use the way more efficient difference() function ...
|
||||
geometry_objects_ids = geometry_objects.difference(intersected_geom_objs).values_list("id", flat=True)
|
||||
# ... so we can resolve these into proper Geometry objects again for further annotation usage
|
||||
geometry_objects = Geometry.objects.filter(id__in=geometry_objects_ids)
|
||||
|
||||
self._write_warning("=== Update parcels and districts ===")
|
||||
# Order geometries by size to process smaller once at first
|
||||
geometries = geometry_objects.exclude(
|
||||
geom=None
|
||||
).annotate(area=Area("geom")).order_by(
|
||||
geometries = geometry_objects.annotate(
|
||||
area=Area("geom")
|
||||
).order_by(
|
||||
'area'
|
||||
)
|
||||
self._write_warning(f"Process parcels for {geometries.count()} geometry entries now ...")
|
||||
i = 0
|
||||
num_geoms = geometries.count()
|
||||
geoms_with_errors = {}
|
||||
for geometry in geometries:
|
||||
self._write_warning(f"--- {datetime.datetime.now()} Process {geometry.id} now ...")
|
||||
geometry.update_parcels()
|
||||
self._write_warning(f"--- Processed {geometry.get_underlying_parcels().count()} underlying parcels")
|
||||
try:
|
||||
geometry.update_parcels()
|
||||
self._write_warning(f"--- Processed {geometry.get_underlying_parcels().count()} underlying parcels")
|
||||
except Exception as e:
|
||||
geoms_with_errors[geometry.id] = str(e)
|
||||
i += 1
|
||||
self._write_warning(f"--- {i}/{num_geoms} processed")
|
||||
|
||||
self._write_success("Updating parcels done!")
|
||||
|
||||
for key, val in geoms_with_errors.items():
|
||||
self._write_error(f" Error on {key}: {val}")
|
||||
self._write_success(f"{num_geoms - len(geoms_with_errors)} geometries successfuly recalculated!")
|
||||
self._break_line()
|
||||
|
||||
@@ -8,7 +8,7 @@ Created on: 15.11.21
|
||||
import json
|
||||
|
||||
from django.contrib.gis.db.models import MultiPolygonField
|
||||
from django.core.exceptions import ObjectDoesNotExist
|
||||
from django.core.exceptions import ObjectDoesNotExist, MultipleObjectsReturned
|
||||
from django.db import models, transaction
|
||||
from django.utils import timezone
|
||||
|
||||
@@ -223,6 +223,17 @@ class Geometry(BaseResource):
|
||||
)
|
||||
parcel_obj.updated_on = _now
|
||||
parcels_to_update.append(parcel_obj)
|
||||
except MultipleObjectsReturned:
|
||||
parcel_obj = Parcel.make_unique(
|
||||
district=district,
|
||||
municipal=municipal,
|
||||
parcel_group=parcel_group,
|
||||
flr=flr_val,
|
||||
flrstck_nnr=flrstck_nnr,
|
||||
flrstck_zhlr=flrstck_zhlr,
|
||||
)
|
||||
parcel_obj.updated_on = _now
|
||||
parcels_to_update.append(parcel_obj)
|
||||
except ObjectDoesNotExist:
|
||||
# If not existing, create object but do not commit, yet
|
||||
parcel_obj = Parcel(
|
||||
@@ -366,11 +377,10 @@ class Geometry(BaseResource):
|
||||
diff = geom_envelope - self.geom
|
||||
|
||||
if diff.area == 0:
|
||||
ratio = 1
|
||||
complexity_factor = 1
|
||||
else:
|
||||
ratio = self.geom.area / diff.area
|
||||
complexity_factor = self.geom.area / diff.area
|
||||
|
||||
complexity_factor = 1 - ratio
|
||||
return complexity_factor
|
||||
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@ Contact: michel.peltriaux@sgdnord.rlp.de
|
||||
Created on: 16.12.21
|
||||
|
||||
"""
|
||||
from django.db import models
|
||||
from django.db import models, transaction
|
||||
|
||||
from konova.models import UuidModel
|
||||
|
||||
@@ -158,6 +158,46 @@ class Parcel(UuidModel):
|
||||
def __str__(self):
|
||||
return f"{self.parcel_group} | {self.flr} | {self.flrstck_zhlr} | {self.flrstck_nnr}"
|
||||
|
||||
@classmethod
|
||||
def make_unique(cls, **kwargs):
|
||||
""" Checks for duplicates of a Parcel, choose a (now) unique one,
|
||||
repairs relations for ParcelIntersection and removes duplicates.
|
||||
|
||||
Args:
|
||||
**kwargs ():
|
||||
|
||||
Returns:
|
||||
unique_true (Parcel): The new unique 'true one'
|
||||
"""
|
||||
parcel_objs = Parcel.objects.filter(**kwargs)
|
||||
|
||||
if not parcel_objs.exists():
|
||||
return None
|
||||
|
||||
# Get one of the found parcels and use it as new 'true one'
|
||||
unique_parcel = parcel_objs.first()
|
||||
# separate it from the rest
|
||||
parcel_objs = parcel_objs.exclude(id=unique_parcel.id)
|
||||
|
||||
if not parcel_objs.exists():
|
||||
# There are no duplicates - all good, just return
|
||||
return unique_parcel
|
||||
|
||||
# Fetch existing intersections, which still point on the duplicated parcels
|
||||
intersection_objs = ParcelIntersection.objects.filter(
|
||||
parcel__in=parcel_objs
|
||||
)
|
||||
|
||||
# Change each intersection, so they point on the 'true one' parcel from now on
|
||||
for intersection in intersection_objs:
|
||||
intersection.parcel = unique_parcel
|
||||
intersection.save()
|
||||
|
||||
# Remove the duplicated parcels
|
||||
parcel_objs.delete()
|
||||
|
||||
return unique_parcel
|
||||
|
||||
|
||||
class ParcelIntersection(UuidModel):
|
||||
"""
|
||||
|
||||
Reference in New Issue
Block a user