Files
konova/konova/models/geometry.py
T
mpeltriaux 71f88f7218 #49 Parcels and Districts
* introduces new models: Parcel and District
2021-12-16 12:21:31 +01:00

114 lines
3.6 KiB
Python

"""
Author: Michel Peltriaux
Organization: Struktur- und Genehmigungsdirektion Nord, Rhineland-Palatinate, Germany
Contact: michel.peltriaux@sgdnord.rlp.de
Created on: 15.11.21
"""
from django.contrib.gis.db.models import MultiPolygonField
from django.db import models
from konova.models import BaseResource, UuidModel
class Geometry(BaseResource):
"""
Geometry model
"""
from konova.settings import DEFAULT_SRID
geom = MultiPolygonField(null=True, blank=True, srid=DEFAULT_SRID)
def save(self, *args, **kwargs):
super().save(*args, **kwargs)
self.check_for_conflicts()
def check_for_conflicts(self):
""" Checks for new geometry overlaps
Creates a new GeometryConflict entry for each overlap to another geometry, which has already been there before
Returns:
"""
# If no geometry is given or important data is missing, we can not perform any checks
if self.geom is None or (self.created is None and self.modified is None):
return None
self.recheck_existing_conflicts()
overlapping_geoms = Geometry.objects.filter(
geom__intersects=self.geom,
).exclude(
id=self.id
).distinct()
for match in overlapping_geoms:
GeometryConflict.objects.get_or_create(conflicting_geometry=self, affected_geometry=match)
def recheck_existing_conflicts(self):
""" Rechecks GeometryConflict entries
If a conflict seems to be resolved due to no longer intersection between the two geometries, the entry
will be deleted.
Returns:
"""
all_conflicts_as_conflicting = self.conflicts_geometries.all()
still_conflicting_conflicts = all_conflicts_as_conflicting.filter(
affected_geometry__geom__intersects=self.geom
)
resolved_conflicts = all_conflicts_as_conflicting.exclude(id__in=still_conflicting_conflicts)
resolved_conflicts.delete()
all_conflicted_by_conflicts = self.conflicted_by_geometries.all()
still_conflicting_conflicts = all_conflicted_by_conflicts.filter(
conflicting_geometry__geom__intersects=self.geom
)
resolved_conflicts = all_conflicted_by_conflicts.exclude(id__in=still_conflicting_conflicts)
resolved_conflicts.delete()
def get_data_objects(self):
""" Getter for all objects which are related to this geometry
Returns:
objs (list): The list of objects
"""
objs = []
sets = [
self.intervention_set,
self.compensation_set,
self.ema_set,
self.ecoaccount_set,
]
for _set in sets:
set_objs = _set.filter(
deleted=None
)
objs += set_objs
return objs
class GeometryConflict(UuidModel):
"""
Geometry conflicts model
If a new/edited geometry overlays an existing geometry, there will be a new GeometryConflict on the db
"""
conflicting_geometry = models.ForeignKey(
Geometry,
on_delete=models.CASCADE,
help_text="The geometry which came second",
related_name="conflicts_geometries"
)
affected_geometry = models.ForeignKey(
Geometry,
on_delete=models.CASCADE,
help_text="The geometry which came first",
related_name="conflicted_by_geometries"
)
detected_on = models.DateTimeField(auto_now_add=True, null=True)
def __str__(self):
return f"{self.conflicting_geometry.id} conflicts with {self.affected_geometry.id}"