# Zusammenfassung Wir haben innerhalb kürzester Zeit eine sehr einfache Verwaltungssoftware für Bebauungspläne erstellt. Die exportierbaren GML-Dateien lassen sich mit Hilfe des Validators prüfen und sind valide. Einen praktischen Nutzwert hat die Software in diesem Stadium aber noch nicht. ```{image} img/bplan_list_1.png :alt: Liste der Bebauungspläne :class: bg-primary :width: 800px :align: center ``` # Metadatenexport Um zeigen zu können, wie schnell man das System anpassen kann, werden wir schnell noch ISO19193-konforme Metadaten generieren. ## Neuer Endpunkt Den View für XPlan GML können wir einfach beibehalten und später etwas anpassen ;-) komserv2/xplanung_light/urls.py ```python urlpatterns = [ # ... # iso metadata generator for each bplan path("bplan//iso19139/", BPlanDetailXmlRasterView.as_view(template_name="xplanung_light/bplan_template_iso19139.xml"), name="bplan-export-iso19139"), ] ``` ## Anpassung des Views Wir brauchen die Geometrien jetzt auch im EPSG:4326 - dazu schreiben wir auch eine kleine Funktion zum Qualifizieren des GMLs aus der DB. komserv2/xplanung_light/views.py ```python # ... from django.urls import reverse_lazy, reverse # ... def qualify_gml_geometry(gml_from_db:str): ET.register_namespace('gml','http://www.opengis.net/gml/3.2') root = ET.fromstring("" + gml_from_db + "") ns = { 'gml': 'http://www.opengis.net/gml/3.2', } # print("" + context['bplan'].geltungsbereich_gml_25832 + "") # Test ob ein Polygon zurück kommt - damit wäre nur ein einziges Polygon im geometry Field polygons = root.findall('gml:Polygon', ns) # print(len(polygons)) if len(polygons) == 0: # print("Kein Polygon auf oberer Ebene gefunden - es sind wahrscheinlich mehrere!") multi_polygon_element = root.find('gml:MultiSurface', ns) uuid_multisurface = uuid.uuid4() multi_polygon_element.set("gml:id", "GML_" + str(uuid_multisurface)) # Füge gml_id Attribute hinzu - besser diese als Hash aus den Geometrien zu rechnen, oder in Zukunft generic_ids der Bereiche zu verwenden polygons = root.findall('gml:MultiSurface/gml:surfaceMember/gml:Polygon', ns) for polygon in polygons: uuid_polygon = uuid.uuid4() polygon.set("gml:id", "GML_" + str(uuid_polygon)) return ET.tostring(multi_polygon_element, encoding="utf-8", method="xml").decode('utf8') else: polygon_element = root.find('gml:Polygon', ns) #polygon_element.set("xmlns:gml", "http://www.opengis.net/gml/3.2") uuid_polygon = uuid.uuid4() polygon_element.set("gml:id", "GML_" + str(uuid_polygon)) # Ausgabe der Geometrie in ein XML-Snippet - erweitert um den MultiSurface/surfaceMember Rahmen ET.dump(polygon_element) return '' + ET.tostring(polygon_element, encoding="utf-8", method="xml").decode('utf8') + '' # ... class BPlanDetailXmlRasterView(BPlanDetailView): def get_queryset(self): # Erweiterung der auszulesenden Objekte um eine transformierte Geomtrie im Format GML 3 queryset = super().get_queryset().annotate(geltungsbereich_gml_25832=AsGML(Transform("geltungsbereich", 25832), version=3)).annotate(geltungsbereich_gml_4326=AsGML("geltungsbereich", version=3)) return queryset def get_context_data(self, **kwargs): context = super().get_context_data(**kwargs) # Um einen XPlanung-konformen Auszug zu bekommen, werden gml_id(s) verwendet. # Es handelt sich um uuids, die noch das Prefix "GML_" bekommen. Grundsätzlich sollten die # aus den Daten in der DB stammen und dort vergeben werden. # Im ersten Schritt synthetisieren wir sie einfach ;-) context['auszug_uuid'] = "GML_" + str(uuid.uuid4()) context['bplan_uuid'] = "GML_" + str(uuid.uuid4()) # Irgendwie gibt es keine django model function um direkt den Extent der Geometrie zu erhalten. Daher nutzen wir hier gdal # und Transformieren die Daten erneut im RAM # Definition der Transformation (Daten sind immer in WGS 84 - 4326) ct = CoordTransform(SpatialReference(4326, srs_type='epsg'), SpatialReference(25832, srs_type='epsg')) # OGRGeoemtry Objekt erstellen ogr_geom = OGRGeometry(str(context['bplan'].geltungsbereich), srs=4326) context['wgs84_extent'] = ogr_geom.extent # Transformation nach EPSG:25832 ogr_geom.transform(ct) # Speichern des Extents in den Context context['extent'] = ogr_geom.extent # Ausgabe der GML Variante zu Testzwecken # print(context['bplan'].geltungsbereich_gml_25832) # Da die GML Daten nicht alle Attribute beinhalten, die XPlanung fordert, müssen wir sie anpassen, bzw. umschreiben # Hierzu nutzen wir die Funktion qualify_gml_geometry context['multisurface_geometry_25832'] = qualify_gml_geometry(context['bplan'].geltungsbereich_gml_25832) context['multisurface_geometry_4326'] = qualify_gml_geometry(context['bplan'].geltungsbereich_gml_4326) relative_url = reverse('bplan-export-xplan-raster-6', kwargs={'pk': context['bplan'].id}) context['iso19139_url']= self.request.build_absolute_uri(relative_url) return context def dispatch(self, *args, **kwargs): response = super().dispatch(*args, **kwargs) response['Content-type'] = "application/xml" # set header return response # ... ``` ## Erstellen des XML-Templates komserv2/xplanung_light/templates/xplanung_light/bplan_template_iso19139.xml ```jinja {{ bplan.generic_id }} Deutsch dataset {{ bplan.gemeinde.name }} Rheinland-Pfalz DE {{ bplan.gemeinde.address_email }} pointOfContact {% if bplan.history.date %} {{ bplan.history.date }} {% else %} 2025-05-07 {% endif %} ISO19115 2003/Cor.1:2006 European Petroleum Survey Group (EPSG) Geodetic Parameter Registry 2008-11-12 publication European Petroleum Survey Group http://www.epsg-registry.org/ http://www.opengis.net/def/crs/EPSG/0/4326 6.18.3 Bebauungsplan {{ bplan.name }} von {{ bplan.gemeinde.name }} {% if bplan.history.date %} {{ bplan.history.date }} {% else %} 2025-05-07 {% endif %} revision https://komserv4gdi.service24.rlp.de/{{ bplan.generic_id }} Bebauungsplan {{ bplan.name }} von {{ bplan.gemeinde.name }} {{ bplan.gemeinde.address_street }} Rheinland-Pfalz DE {{ bplan.gemeinde.address_email }} publisher Regional Spatial scope 2019-05-22 publication Es gelten keine Zugriffsbeschränkungen Lizenz: cc-by-3.0 - Creative Commons: Namensnennung 3.0 Deutschland - http://creativecommons.org/licenses/by/3.0/de/ - Quellenvermerk: Source note required by license, but not given! {"id":"cc-by-3.0","name":"Creative Commons: Namensnennung 3.0 Deutschland","url":"http:\/\/creativecommons.org\/licenses\/by\/3.0\/de\/","quelle":"Source note required by license, but not given!"} vector 1000 Deutsch location {{ wgs84_extent.0 }} {{ wgs84_extent.1 }} {{ wgs84_extent.2 }} {{ wgs84_extent.3 }} {% if multisurface_geometry_4326 %} {% autoescape off %} {{ multisurface_geometry_4326 }} {% endautoescape %} {% endif %} GML 3.2 {% if responsible_party_address %} {{ responsible_party_address }} {% else %} Musterstraße 10 {% endif %} Rheinland-Pfalz DE {% if responsible_party_email %} {{ responsible_party_email }} {% else %} test@example.com {% endif %} pointOfContact {{ iso19139_url }} download dataset VERORDNUNG (EG) Nr. 1205/2008 DER KOMMISSION vom 3. Dezember 2008 zur Durchführung der Richtlinie 2007/2/EG des Europäischen Parlaments und des Rates hinsichtlich Metadaten 2008-12-04 publication 1.0 No explanation available true VERORDNUNG (EU) Nr. 1253/2013 DER KOMMISSION vom 21. Oktober 2013 zur Änderung der Verordnung (EU) Nr. 1089/2010 zur Durchführung der Richtlinie 2007/2/EG hinsichtlich der Interoperabilität von Geodatensätzen und -diensten 2013-12-10 publication 1.0 No explanation available false VERORDNUNG (EU) Nr. 102/2011 DER KOMMISSION vom 4. Februar 2011 zur Änderung der Verordnung (EU) Nr. 1089/2010 zur Durchführung der Richtlinie 2007/2/EG des Europäischen Parlaments und des Rates hinsichtlich der Interoperabilität von Geodatensätzen und -diensten 2011-02-05 publication 1.0 No explanation available false VERORDNUNG (EG) Nr. 1089/2010 DER KOMMISSION vom 23. November 2010 zur Durchführung der Richtlinie 2007/2/EG des Europäischen Parlaments und des Rates hinsichtlich der Interoperabilität von Geodatensätzen und -diensten 2010-12-08 publication 1.0 No explanation available false Geodaten basieren auf den generalisierten amtlichen Grenzen der Gebietskörperschaften. ``` ## Anpassung der Tabelle komserv2/xplanung_light/tables.py ```python import django_tables2 as tables from .models import BPlan from django_tables2 import Column from django_tables2.utils import A class BPlanTable(tables.Table): #download = tables.LinkColumn('gedis-document-pdf', text='Download', args=[A('pk')], \ # orderable=False, empty_values=()) xplan_gml = tables.LinkColumn('bplan-export-xplan-raster-6', text='Exportieren', args=[A('pk')], \ orderable=False, empty_values=()) iso_metadata = tables.LinkColumn('bplan-export-iso19139', text='Exportieren', args=[A('pk')], \ orderable=False, empty_values=()) edit = tables.LinkColumn('bplan-update', text='Bearbeiten', args=[A('pk')], \ orderable=False, empty_values=()) delete = tables.LinkColumn('bplan-delete', text='Löschen', args=[A('pk')], \ orderable=False, empty_values=()) """ geojson = Column( accessor=A('geojson'), orderable=False, # ... ) """ class Meta: model = BPlan template_name = "django_tables2/bootstrap5.html" fields = ("name", "gemeinde", "planart", "xplan_gml", "iso_metadata", "edit", "delete") ``` # Ergebnis des ISO-Metadaten Exports Die Bebauungsplantabelle hat jetzt eine Spalte mit dem jeweiligen Link zu einem konformen **ISO-19139 dataset Metadatensatz**. Den können wir später verwenden um die Serverkomponenten damit anzureichen - **GDI very easy ;-)** . ## Neue Spalte für Export in Tabelle [http://127.0.0.1:8000/bplan/](http://127.0.0.1:8000/bplan/) ```{image} img/bplan_list_tables2_iso_export.png :alt: Neue Spalte für Export in Tabelle :class: bg-primary :width: 800px :align: center ``` ## ISO19139 Export [http://127.0.0.1:8000/bplan/1/iso19139/](http://127.0.0.1:8000/bplan/1/iso19139/) ```{image} img/iso19139_export_1.png :alt: ISO19139 Export :class: bg-primary :width: 800px :align: center ``` # TODOs Um die Software zur Produktionsreife zu bringen, müssen noch ein paar Dinge entwickelt werden. * Ersetzen des Felds **geltungsbereich** durch eine m2m Relation zu einem neuen Modell **bereich** * Aktivieren der Pflichtfelder entprechend der Vorgaben in RLP * Entwickeln notwendiger Validierungsfunktionen * Erstellung eines Mapfile-Generators zur Publikation von WMS- und WFS-Interfaces * Schaffung der Ablagemöglichkeit für Dokumente * Importmöglichkeit für BPlan-GML Dokumente * ... ```{note} Auf geht's ;-) ... ```