Merge branch 'refs/heads/master' into netgis_map_client_update

# Conflicts:
#	konova/forms/geometry_form.py
#	templates/map/client/config.json
This commit is contained in:
2025-10-12 11:22:56 +02:00
24 changed files with 228 additions and 84 deletions

View File

@@ -27,7 +27,7 @@ class SimpleGeomForm(BaseForm):
"""
read_only = True
geometry_simplified = False
output = JSONField(
geom = JSONField(
label=_("Geometry"),
help_text=_(""),
label_suffix="",
@@ -55,27 +55,26 @@ class SimpleGeomForm(BaseForm):
geom = ""
self.empty = True
self.initialize_form_field("output", geom)
self.initialize_form_field("geom", geom)
def is_valid(self):
super().is_valid()
is_valid = True
# Get geojson from form
geom = self.data["output"]
geom = self.data["geom"]
if geom is None or len(geom) == 0:
# empty geometry is a valid geometry
self.cleaned_data["output"] = MultiPolygon(srid=DEFAULT_SRID_RLP).ewkt
self.cleaned_data["geom"] = MultiPolygon(srid=DEFAULT_SRID_RLP).ewkt
return is_valid
geom = json.loads(geom)
# Write submitted data back into form field to make sure invalid geometry
# will be rendered again on failed submit
self.initialize_form_field("output", self.data["output"])
self.initialize_form_field("geom", self.data["geom"])
# Read geojson into gdal geometry
# HINT: This can be simplified if the geojson format holds data in epsg:4326 (GDAL provides direct creation for
# this case)
# Initialize features list with empty MultiPolygon, so that an empty input will result in a
# proper empty MultiPolygon object
features = []
features_json = geom.get("features", [])
accepted_ogr_types = [
@@ -98,33 +97,35 @@ class SimpleGeomForm(BaseForm):
g = self.__flatten_geom_to_2D(g)
if g.geom_type not in accepted_ogr_types:
self.add_error("output", _("Only surfaces allowed. Points or lines must be buffered."))
self.add_error("geom", _("Only surfaces allowed. Points or lines must be buffered."))
is_valid &= False
return is_valid
is_valid &= self.__is_area_valid(g)
polygon = Polygon.from_ewkt(g.ewkt)
is_valid &= polygon.valid
if not polygon.valid:
self.add_error("output", polygon.valid_reason)
g = Polygon.from_ewkt(g.ewkt)
is_valid &= g.valid
if not g.valid:
self.add_error("geom", g.valid_reason)
return is_valid
features.append(polygon)
if isinstance(g, Polygon):
features.append(g)
elif isinstance(g, MultiPolygon):
features.extend(list(g))
# Unionize all geometry features into one new MultiPolygon
form_geom = MultiPolygon(srid=DEFAULT_SRID_RLP)
for feature in features:
form_geom = form_geom.union(feature)
if features:
form_geom = MultiPolygon(*features, srid=DEFAULT_SRID_RLP).unary_union
else:
form_geom = MultiPolygon(srid=DEFAULT_SRID_RLP)
# Make sure to convert into a MultiPolygon. Relevant if a single Polygon is provided.
if form_geom.geom_type != "MultiPolygon":
form_geom = MultiPolygon(form_geom, srid=DEFAULT_SRID_RLP)
form_geom = Geometry.cast_to_multipolygon(form_geom)
# Write unioned Multipolygon into cleaned data
if self.cleaned_data is None:
self.cleaned_data = {}
self.cleaned_data["output"] = form_geom.ewkt
self.cleaned_data["geom"] = form_geom.ewkt
return is_valid
@@ -134,7 +135,7 @@ class SimpleGeomForm(BaseForm):
Returns:
"""
geom = self.cleaned_data.get("output")
geom = self.cleaned_data.get("geom")
g = gdal.OGRGeometry(geom, srs=DEFAULT_SRID_RLP)
num_vertices = g.num_coords
@@ -150,7 +151,7 @@ class SimpleGeomForm(BaseForm):
if not is_area_valid:
self.add_error(
"output",
"geom",
_("Geometry must be greater than 1m². Currently is {}").format(
float(geom.area)
)
@@ -193,14 +194,14 @@ class SimpleGeomForm(BaseForm):
if self.instance is None or self.instance.geometry is None:
raise LookupError
geometry = self.instance.geometry
geometry.geom = self.cleaned_data.get("output", MultiPolygon(srid=DEFAULT_SRID_RLP))
geometry.geom = self.cleaned_data.get("geom", MultiPolygon(srid=DEFAULT_SRID_RLP))
geometry.modified = action
geometry.save()
except LookupError:
# No geometry or linked instance holding a geometry exist --> create a new one!
geometry = Geometry.objects.create(
geom=self.cleaned_data.get("output", MultiPolygon(srid=DEFAULT_SRID_RLP)),
geom=self.cleaned_data.get("geom", MultiPolygon(srid=DEFAULT_SRID_RLP)),
created=action,
)