From 0aa87f177f15a1c8ebed1dc82f158ab563d64f12 Mon Sep 17 00:00:00 2001 From: pathmapper Date: Wed, 10 Apr 2024 09:35:47 +0200 Subject: [PATCH] New tool: Clip raster by polygon --- xplan_umring.py | 3 + xplan_umring.ui | 197 +++++++++++++++----------- xplan_umring_algorithm_clip_raster.py | 195 +++++++++++++++++++++++++ xplan_umring_provider.py | 2 + 4 files changed, 311 insertions(+), 86 deletions(-) create mode 100644 xplan_umring_algorithm_clip_raster.py diff --git a/xplan_umring.py b/xplan_umring.py index 5cecb96..7ffd534 100644 --- a/xplan_umring.py +++ b/xplan_umring.py @@ -183,6 +183,7 @@ def saveTool(tool): self.dlg.rb_fp_60.toggled.connect(lambda: saveTool("flaechennutzungsplan60")) self.dlg.rb_lp_60.toggled.connect(lambda: saveTool("landschaftsplan60")) self.dlg.rb_replace.toggled.connect(lambda: saveTool("replacegeometry")) + self.dlg.rb_clip.toggled.connect(lambda: saveTool("clipraster")) if self.selectedTool == "bebauungsplan54": self.dlg.rb_bp_54.setChecked(True) @@ -194,6 +195,8 @@ def saveTool(tool): self.dlg.rb_lp_60.setChecked(True) elif self.selectedTool == "replacegeometry": self.dlg.rb_replace.setChecked(True) + elif self.selectedTool == "clipraster": + self.dlg.rb_clip.setChecked(True) result = self.dlg.exec_() diff --git a/xplan_umring.ui b/xplan_umring.ui index 23d2bb4..f249a32 100644 --- a/xplan_umring.ui +++ b/xplan_umring.ui @@ -7,7 +7,7 @@ 0 0 651 - 455 + 538 @@ -17,89 +17,98 @@ XPlan-Umring - - - - Qt::Vertical + + + + + 10 + - - - 20 - 20 - + + v6.0 - + - - + + 10 - - v6.0 + + Qt::StrongFocus - - + + Qt::Vertical 20 - 40 + 20 - - + + + + Qt::Horizontal + + + QDialogButtonBox::Cancel|QDialogButtonBox::Ok + + + + + 10 - 50 - false - Bitte gewünschtes Umring-Werkzeug auswählen: + Hilfswerkzeuge - - + + 10 - Bebauungsplan + v6.0 - - + + 10 - - Qt::StrongFocus + + Geltungsbereich Umringszenario ersetzen (Geometrie-Update) - - - - Qt::Horizontal + + + + + 10 + - - QDialogButtonBox::Cancel|QDialogButtonBox::Ok + + v6.0 @@ -115,69 +124,58 @@ - - + + 10 - v6.0 + Rasterplan mit Polygon zuschneiden - - - - Qt::Vertical - - - - 20 - 20 - - - - - - + + 10 + 50 + false - v5.4 + Bitte gewünschtes Umring-Werkzeug auswählen: - - + + 10 - Landschaftsplan + v5.4 - - + + 10 - Hilfswerkzeug + Bebauungsplan - - + + Qt::Vertical @@ -189,41 +187,43 @@ - - - - - 10 - + + + + Qt::Vertical - - Kommune für Voreinstellungen auswählen oder selbst eintragen (optional): + + + 20 + 20 + - + - - + + 10 - Geltungsbereich Umringszenario ersetzen (Geometrie-Update) + Landschaftsplan - - - - - 10 - + + + + Qt::Vertical - - v6.0 + + + 20 + 40 + - + @@ -238,8 +238,8 @@ - - + + Qt::Vertical @@ -251,6 +251,31 @@ + + + + + 10 + + + + Kommune für Voreinstellungen auswählen oder selbst eintragen (optional): + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + diff --git a/xplan_umring_algorithm_clip_raster.py b/xplan_umring_algorithm_clip_raster.py new file mode 100644 index 0000000..61b05a7 --- /dev/null +++ b/xplan_umring_algorithm_clip_raster.py @@ -0,0 +1,195 @@ +""" +*************************************************************************** +XPlan-Umring - Clip Raster + + begin : April 2024 + Copyright : (C) 2024 by Kreis Viersen + Email : open@kreis-viersen.de + +*************************************************************************** + +*************************************************************************** +* * +* This program is free software; you can redistribute it and/or modify * +* it under the terms of the GNU General Public License as published by * +* the Free Software Foundation; either version 2 of the License, or * +* (at your option) any later version. * +* * +*************************************************************************** +""" + +import processing +import uuid + +from lxml import etree + +from qgis.core import ( + QgsProcessing, + QgsProcessingAlgorithm, + QgsProcessingFeedback, + QgsProcessingMultiStepFeedback, + QgsProcessingParameterVectorLayer, + QgsProcessingParameterRasterLayer, + QgsProcessingParameterRasterDestination, +) + + +class XPlanUmringAlgorithmClipRaster(QgsProcessingAlgorithm): + def createInstance(self): + return XPlanUmringAlgorithmClipRaster() + + def flags(self): + return super().flags() | QgsProcessingAlgorithm.FlagNoThreading + + def name(self): + return "clipraster" + + def displayName(self): + return "Rasterplan mit Polygon zuschneiden" + + def group(self): + return self.groupId() + + def groupId(self): + return "" + + def shortHelpString(self): + return ( + "Rasterplan mit Polygon zuschneiden" + + "\n\n" + + "Eingabelayer für das Skript sind:" + + "\n" + + "1. Rasterlayer mit dem Plan, welcher zugeschnitten werden soll." + + "\n" + + "2. Vektorlayer mit dem Polygon, welches zum Zuschneiden verwendet werden soll." + + "\n\n" + + "Wichtig: Der Eingabelayer muss ein Polygonlayer sein." + + "\n\n" + + "Dazu den Speicherort und Name für den erzeugten Rasterplan festlegen." + + "\n\n" + + "Autor: Kreis Viersen" + + "\n\n" + + "Kontakt: open@kreis-viersen.de" + + "\n\n" + + "GitHub: https://github.com/kreis-viersen/xplan-umring" + ) + + def shortDescription(self): + return "Rasterplan mit Polygon zuschneiden" + + def initAlgorithm(self, config=None): + self.addParameter( + QgsProcessingParameterRasterLayer( + "alter_plan_raster", "Alter Plan (Raster)", defaultValue=None + ) + ) + self.addParameter( + QgsProcessingParameterVectorLayer( + "polygon_zum_zuschneiden", + "Polygon zum Zuschneiden (Vektor)", + optional=False, + types=[QgsProcessing.TypeVectorPolygon], + defaultValue=None, + ) + ) + self.addParameter( + QgsProcessingParameterRasterDestination( + "ZugeschnittenerRasterplan", + "Zugeschnittener Rasterplan", + createByDefault=True, + defaultValue=None, + ) + ) + + feedback = QgsProcessingFeedback() + + def processAlgorithm(self, parameters, context, feedback): + feedback = QgsProcessingMultiStepFeedback(4, feedback) + results = {} + outputs = {} + + # Layer aus Ausdehnung erzeugen + alg_params = { + "INPUT": parameters["alter_plan_raster"], + "OUTPUT": QgsProcessing.TEMPORARY_OUTPUT, + } + outputs["LayerAusAusdehnungErzeugen"] = processing.run( + "native:extenttolayer", + alg_params, + context=context, + feedback=feedback, + is_child_algorithm=True, + ) + + feedback.setCurrentStep(1) + if feedback.isCanceled(): + return {} + + # Durch maximalen Abstand segmentieren + alg_params = { + "DISTANCE": 0.01, + "INPUT": parameters["polygon_zum_zuschneiden"], + "OUTPUT": QgsProcessing.TEMPORARY_OUTPUT, + } + outputs["DurchMaximalenAbstandSegmentieren"] = processing.run( + "native:segmentizebymaxdistance", + alg_params, + context=context, + feedback=feedback, + is_child_algorithm=True, + ) + + feedback.setCurrentStep(2) + if feedback.isCanceled(): + return {} + + # Differenz + alg_params = { + "GRID_SIZE": None, + "INPUT": outputs["LayerAusAusdehnungErzeugen"]["OUTPUT"], + "OVERLAY": outputs["DurchMaximalenAbstandSegmentieren"]["OUTPUT"], + "OUTPUT": QgsProcessing.TEMPORARY_OUTPUT, + } + outputs["Differenz"] = processing.run( + "native:difference", + alg_params, + context=context, + feedback=feedback, + is_child_algorithm=True, + ) + + feedback.setCurrentStep(3) + if feedback.isCanceled(): + return {} + + # Raster auf Layermaske zuschneiden + alg_params = { + "ALPHA_BAND": False, + "CROP_TO_CUTLINE": True, + "DATA_TYPE": 0, # Eingabelayerdatentyp verwenden + "EXTRA": "", + "INPUT": parameters["alter_plan_raster"], + "KEEP_RESOLUTION": False, + "MASK": outputs["Differenz"]["OUTPUT"], + "MULTITHREADING": False, + "NODATA": None, + "OPTIONS": "", + "SET_RESOLUTION": False, + "SOURCE_CRS": None, + "TARGET_CRS": None, + "TARGET_EXTENT": None, + "X_RESOLUTION": None, + "Y_RESOLUTION": None, + "OUTPUT": parameters["ZugeschnittenerRasterplan"], + } + outputs["RasterAufLayermaskeZuschneiden"] = processing.run( + "gdal:cliprasterbymasklayer", + alg_params, + context=context, + feedback=feedback, + is_child_algorithm=True, + ) + results["ZugeschnittenerRasterplan"] = outputs[ + "RasterAufLayermaskeZuschneiden" + ]["OUTPUT"] + return results diff --git a/xplan_umring_provider.py b/xplan_umring_provider.py index 4d32e89..53222d1 100644 --- a/xplan_umring_provider.py +++ b/xplan_umring_provider.py @@ -34,6 +34,7 @@ from .xplan_umring_algorithm_fp_6_0 import XPlanUmringAlgorithmFP60 from .xplan_umring_algorithm_lp_6_0 import XPlanUmringAlgorithmLP60 from .xplan_umring_algorithm_replace_geometry import XPlanUmringAlgorithmReplaceGeometry +from .xplan_umring_algorithm_clip_raster import XPlanUmringAlgorithmClipRaster class XPlanUmringProvider(QgsProcessingProvider): @@ -60,6 +61,7 @@ def loadAlgorithms(self): self.addAlgorithm(XPlanUmringAlgorithmFP60()) self.addAlgorithm(XPlanUmringAlgorithmLP60()) self.addAlgorithm(XPlanUmringAlgorithmReplaceGeometry()) + self.addAlgorithm(XPlanUmringAlgorithmClipRaster()) def id(self): """