Geometry simplification

* simplifies geometries on SimpleGeomForm if threshold GEOM_MAX_VERTICES has been exceeded
    * geometry is iteratively simplified to find a proper tolerance value which satisfies the GEOM_MAX_VERTICES threshold
This commit is contained in:
2023-06-28 14:21:26 +02:00
parent dd9d10f6fc
commit e8feec851f
9 changed files with 277 additions and 177 deletions

View File

@@ -15,6 +15,7 @@ from django.utils.translation import gettext_lazy as _
from konova.forms.base_form import BaseForm
from konova.models import Geometry
from konova.settings import GEOM_MAX_VERTICES
from konova.tasks import celery_update_parcels, celery_check_for_geometry_conflicts
from konova.sub_settings.lanis_settings import DEFAULT_SRID_RLP
from user.models import UserActionLogEntry
@@ -25,6 +26,7 @@ class SimpleGeomForm(BaseForm):
"""
read_only = True
geometry_simplified = False
geom = MultiPolygonField(
srid=DEFAULT_SRID_RLP,
label=_("Geometry"),
@@ -124,6 +126,38 @@ class SimpleGeomForm(BaseForm):
return is_valid
def __is_vertices_num_valid(self):
""" Checks whether the number of vertices in the geometry is not too high
Returns:
"""
geom = self.cleaned_data.get("geom")
g = gdal.OGRGeometry(geom, srs=DEFAULT_SRID_RLP)
num_vertices = g.num_coords
return num_vertices <= GEOM_MAX_VERTICES
def __simplify_geometry(self, geom, max_vert: int):
""" Simplifies a geometry
Geometry will be simplified until a threshold of max vertices has been reached.
Args:
geom (MultiPolygon): The geometry
max_vert (int): Threshold of maximum vertices in geometry
Returns:
geom (MultiPolygon): The simplified geometry
"""
tolerance = 0.1
n = geom.num_coords
while(n > max_vert):
geom = geom.simplify(tolerance)
n = geom.num_coords
tolerance += 0.1
return geom
def save(self, action: UserActionLogEntry):
""" Saves the form's geometry
@@ -149,6 +183,13 @@ class SimpleGeomForm(BaseForm):
geom=self.cleaned_data.get("geom", MultiPolygon(srid=DEFAULT_SRID_RLP)),
created=action,
)
is_vertices_num_valid = self.__is_vertices_num_valid()
if not is_vertices_num_valid:
geometry.geom = self.__simplify_geometry(geometry.geom, max_vert=GEOM_MAX_VERTICES)
geometry.save()
self.geometry_simplified = True
# Start parcel update and geometry conflict checking procedure in a background process
celery_update_parcels.delay(geometry.id)
celery_check_for_geometry_conflicts.delay(geometry.id)