Bläddra i källkod

栅格数据裁剪

wanger 7 månader sedan
förälder
incheckning
b64d3c9c30

+ 1 - 1
processing/algs/gdal/ClipRasterByExtent.py

@@ -110,7 +110,7 @@ class ClipRasterByExtent(GdalAlgorithm):
         return 'rasterextraction'
 
     def icon(self):
-        return QIcon(os.path.join(pluginPath, 'images', 'gdaltools', 'raster-clip.png'))
+        return QIcon(os.path.join(pluginPath, 'images', 'gdaltools', 'raster-clip.py.png'))
 
     def commandName(self):
         return "gdal_translate"

+ 1 - 1
processing/algs/gdal/ClipRasterByMask.py

@@ -151,7 +151,7 @@ class ClipRasterByMask(GdalAlgorithm):
         return self.tr('Clip raster by mask layer')
 
     def icon(self):
-        return QIcon(os.path.join(pluginPath, 'images', 'gdaltools', 'raster-clip.png'))
+        return QIcon(os.path.join(pluginPath, 'images', 'gdaltools', 'raster-clip.py.png'))
 
     def group(self):
         return self.tr('Raster extraction')

+ 1 - 1
processing/gui/menus.py

@@ -75,7 +75,7 @@ def initMenusAndToolbars():
                                'native:intersection': geoprocessingToolsMenu,
                                'native:union': geoprocessingToolsMenu,
                                'native:symmetricaldifference': geoprocessingToolsMenu,
-                               'native:clip': geoprocessingToolsMenu,
+                               'native:clip.py': geoprocessingToolsMenu,
                                'native:difference': geoprocessingToolsMenu,
                                'native:dissolve': geoprocessingToolsMenu,
                                'qgis:eliminateselectedpolygons': geoprocessingToolsMenu})

+ 125 - 0
processing/tools/Raster/ClipRasterByGrid.py

@@ -0,0 +1,125 @@
+# -*- coding: utf-8 -*-
+
+__author__ = 'wanger'
+__description__ = '按照掩膜范围裁剪栅格数据'
+__date__ = '2024-11-25'
+__copyright__ = '(C) 2024 by siwei'
+__revision__ = '1.0'
+
+import os
+
+from qgis._core import QgsRasterFileWriter, QgsProcessingParameterFolderDestination
+from qgis.core import (
+    QgsVectorLayer,
+    QgsRasterLayer,
+    QgsFeature,
+    QgsGeometry
+)
+import processing
+from PyQt5.QtCore import QFileInfo
+from qgis.analysis import QgsRasterCalculator, QgsRasterCalculatorEntry
+
+from qgis.PyQt.QtCore import QCoreApplication
+from qgis._core import QgsSpatialIndex, QgsField, QgsRectangle, QgsProcessingParameterVectorDestination, \
+    QgsVectorFileWriter, QgsWkbTypes, QgsProcessingParameterNumber, QgsProcessingParameterBoolean, QgsGeometry, \
+    QgsFeature
+from qgis.core import (QgsProcessing,
+                       QgsVectorLayer,
+                       QgsFeatureSink,
+                       QgsProcessingException,
+                       QgsProcessingAlgorithm,
+                       QgsProcessingParameterFile,
+                       QgsProcessingParameterFeatureSource,
+                       QgsProcessingParameterFeatureSink)
+from qgis import processing
+
+
+class ClipRasterByMaskProcessingAlgorithm(QgsProcessingAlgorithm):
+    INPUT_SHP = 'INPUT_SHP'
+    INPUT_RASTER = 'INPUT_RASTER'
+    OUTPUT = 'OUTPUT'
+
+    def tr(self, string):
+        return QCoreApplication.translate('Processing', string)
+
+    def createInstance(self):
+        return ClipRasterByMaskProcessingAlgorithm()
+
+    def name(self):
+        return 'cliprasterbymask'
+
+    def displayName(self):
+        return self.tr('按照掩膜范围裁剪栅格数据')
+
+    def group(self):
+        return self.tr('栅格裁剪')
+
+    def groupId(self):
+        return 'rasterclip'
+
+    def shortHelpString(self):
+        return self.tr("遍历输入shp数据要素裁剪输入栅格,保存到输出文件夹。")
+
+    def initAlgorithm(self, config=None):
+        self.addParameter(QgsProcessingParameterFile(
+            self.INPUT_SHP,
+            '网格数据',
+            extension='shp'
+        ))
+        self.addParameter(QgsProcessingParameterFile(
+            self.INPUT_RASTER,
+            '栅格数据',
+            extension='tif'
+        ))
+        # 通过 setExtensions 方法设置多个扩展名
+        # self.parameter(self.INPUT_RASTER).setExtensions(['tif', 'img'])  # 支持 .shp, .csv, .txt
+        self.addParameter(QgsProcessingParameterFolderDestination(self.OUTPUT, '输出文件夹'))
+
+    # 执行
+    def processAlgorithm(self, parameters, context, feedback):
+        input_shp = self.parameterAsString(parameters, self.INPUT_SHP, context)
+        input_raster = self.parameterAsOutputLayer(parameters, self.INPUT_RASTER, context)
+        output_raster = self.parameterAsString(parameters, self.OUTPUT, context)
+        # 输入Shapefile路径
+        # input_shp = "E:\\projects\\遥感技术部需求\\裁剪栅格\\data\\grid_extent.shp"
+        # 输入栅格数据路径
+        # input_raster = "D:\\gisdata\\tif\\unnamed_卫图_Level_12.tif"
+        # 输出裁剪后的栅格路径
+        # output_raster = "E:\\projects\\遥感技术部需求\\裁剪栅格\\output\\"
+        # 加载输入Shapefile和栅格数据
+        vector_layer = QgsVectorLayer(input_shp, "vector_layer", "ogr")
+        raster_layer = QgsRasterLayer(input_raster, "raster_layer")
+        fields = vector_layer.fields()
+        # 遍历输入图层的所有要素,并为每个要素保存一个单独的Shapefile文件
+        total = 0
+        for idx, feature in enumerate(vector_layer.getFeatures()):
+            # 获取当前要素的几何数据
+            geometry = feature.geometry()
+            key = feature["新图号"]
+
+            # 创建一个新的 Shapefile 文件名,可以使用索引或 ID 来命名
+            output_shp = os.path.join(output_raster, f"{key}.shp")
+
+            # 创建输出shapefile
+            writer = QgsVectorFileWriter(output_shp, 'UTF-8', fields, QgsWkbTypes.MultiPolygon, vector_layer.crs(),
+                                         'ESRI Shapefile')
+            writer.addFeature(feature)
+
+            # 完成写入并关闭输出文件
+            del writer
+
+            # 使用QGIS的processing模块进行栅格裁剪
+            params = {
+                'INPUT': raster_layer,  # 输入栅格
+                'MASK': output_shp,  # 用于裁剪的矢量图层
+                'OUTPUT': f"{output_raster}\\{key}.tif",  # 输出裁剪后的栅格文件
+                'CROP_TO_CUTLINE': True
+            }
+
+            # 执行裁剪操作
+            processing.run('gdal:cliprasterbymasklayer', params)
+            print(f"Cropped raster saved to {output_raster}")
+            total = total + 1
+        return {
+            "状态": f"处理成功,共裁剪出{total}块栅格数据。"
+        }

+ 141 - 0
processing/tools/Raster/Expand_Grid.py

@@ -0,0 +1,141 @@
+# -*- coding: utf-8 -*-
+
+__author__ = 'wanger'
+__description__ = '处理网格数据  遍历要素获取四至坐标点  按照指定距离外扩数据框'
+__date__ = '2024-11-25'
+__copyright__ = '(C) 2024 by siwei'
+__revision__ = '1.0'
+import processing
+import os
+
+from PyQt5.QtCore import QVariant
+
+from qgis.PyQt.QtCore import QCoreApplication
+from qgis._core import QgsSpatialIndex, QgsField, QgsRectangle, QgsProcessingParameterVectorDestination, \
+    QgsVectorFileWriter, QgsWkbTypes, QgsProcessingParameterNumber, QgsProcessingParameterBoolean, QgsGeometry, \
+    QgsFeature
+from qgis.core import (QgsProcessing,
+                       QgsVectorLayer,
+                       QgsFeatureSink,
+                       QgsProcessingException,
+                       QgsProcessingAlgorithm,
+                       QgsProcessingParameterFile,
+                       QgsProcessingParameterFeatureSource,
+                       QgsProcessingParameterFeatureSink)
+from qgis import processing
+
+
+class ExpandGridProcessingAlgorithm(QgsProcessingAlgorithm):
+    INPUT = 'INPUT'
+    OUTPUT = 'OUTPUT'
+    tolerance = 'tolerance'
+    expanded = 'expanded'
+
+    def tr(self, string):
+        return QCoreApplication.translate('Processing', string)
+
+    def createInstance(self):
+        return ExpandGridProcessingAlgorithm()
+
+    def name(self):
+        return 'expandGrid'
+
+    def displayName(self):
+        return self.tr('外扩网格数据')
+
+    def group(self):
+        return self.tr('栅格裁剪')
+
+    def groupId(self):
+        return 'rasterclip'
+
+    def shortHelpString(self):
+        return self.tr("遍历输入shp数据要素获取四至坐标点并按照指定距离外扩数据框,保存到输出文件夹。")
+
+    def initAlgorithm(self, config=None):
+        self.addParameter(QgsProcessingParameterFile(
+            self.INPUT,
+            '网格数据',
+            extension='shp'
+        ))
+        # 创建一个参数,提示用户输入一个小数值
+        self.addParameter(QgsProcessingParameterNumber(self.tolerance,
+                                                       self.tr('外扩距离(米)'),
+                                                       QgsProcessingParameterNumber.Double
+                                                       ))
+        self.addParameter(QgsProcessingParameterBoolean(self.expanded,
+                                                        self.tr('是否外扩'),
+                                                        defaultValue=True))
+        self.addParameter(QgsProcessingParameterVectorDestination(self.OUTPUT,
+                                                                  self.tr('输出位置')))
+
+    # 执行
+    def processAlgorithm(self, parameters, context, feedback):
+        input_shp = self.parameterAsString(parameters, self.INPUT, context)
+        output_shp = self.parameterAsOutputLayer(parameters, self.OUTPUT, context)
+        expand_distance = self.parameterAsDouble(parameters, self.tolerance, context)
+        print(f"expand_distance:{expand_distance}")
+        expanded = self.parameterAsBoolean(parameters, self.expanded, context)
+        print(f"expanded:{expanded}")
+        if expanded == False:
+            expand_distance = 0
+        print(f"expanded:{expanded}")
+        # 加载输入shapefile
+        input_layer = QgsVectorLayer(input_shp, "input_layer", "ogr")
+        if not input_layer.isValid():
+            print(f"Failed to load input shapefile: {input_shp}")
+            return {
+                "状态": "处理失败!",
+                "原因": f"Failed to load input shapefile: {input_shp}"
+            }
+        else:
+            # 获取输入图层的字段信息
+            fields = input_layer.fields()
+            # 创建输出shapefile
+            writer = QgsVectorFileWriter(output_shp, 'UTF-8', fields, QgsWkbTypes.MultiPolygon, input_layer.crs(),
+                                         'ESRI Shapefile')
+            # 检查文件是否成功创建
+            if writer.hasError() != QgsVectorFileWriter.NoError:
+                print(f"Error creating output shapefile: {output_shp}")
+                return {
+                    "状态": "处理失败!",
+                    "原因": f"Error creating output shapefile: {output_shp}"
+                }
+            else:
+                # 遍历输入shapefile中的要素
+                for feature in input_layer.getFeatures():
+                    # 获取要素的geometry和extent
+                    geometry = feature.geometry()
+                    extent = geometry.boundingBox()  # 获取要素的extent(bounding box)
+                    # 对extent进行外扩
+                    # 使用 grow 方法来将bounding box外扩100米
+                    # if expanded == False:
+                    #     extent.grow(expand_distance)  # 扩展100米
+                    # print(f"Feature ID: {feature.id()}, Extent: {extent}")
+                    # 获取四至坐标
+                    minX = extent.xMinimum()
+                    maxX = extent.xMaximum()
+                    minY = extent.yMinimum()
+                    maxY = extent.yMaximum()
+                    # 手动扩展extent,向四个方向扩展100米
+                    expanded_minX = minX - expand_distance  # 向左扩展
+                    expanded_maxX = maxX + expand_distance  # 向右扩展
+                    expanded_minY = minY - expand_distance  # 向下扩展
+                    expanded_maxY = maxY + expand_distance  # 向上扩展
+                    # 创建新的扩展后的QgsRectangle
+                    expanded_extent = QgsRectangle(expanded_minX, expanded_minY, expanded_maxX, expanded_maxY)
+                    # 使用extent创建一个新的几何(矩形geometry)
+                    new_geometry = QgsGeometry.fromRect(expanded_extent)
+                    # 创建一个新的要素,并将新几何设置到要素中
+                    new_feature = QgsFeature(fields)  # 创建新的空要素,使用相同的字段定义
+                    new_feature.setGeometry(new_geometry)  # 设置新的几何(extent)
+                    # 复制原始要素的属性到新的要素
+                    new_feature.setAttributes(feature.attributes())  # 将原要素的属性复制到新要素
+                    # 将修改后的要素添加到输出shapefile
+                    writer.addFeature(new_feature)
+                # 完成写入并关闭输出文件
+                del writer
+                print(f"Features copied from {input_shp} to {output_shp} with modified extent.")
+        return {
+            "状态": "处理成功"
+        }

+ 60 - 0
processing/tools/Raster/clip.py

@@ -0,0 +1,60 @@
+from qgis._core import QgsWkbTypes
+from qgis.core import (
+    QgsVectorLayer,
+    QgsFeature,
+    QgsField,
+    QgsVectorFileWriter
+)
+import os
+
+# 输入Shapefile路径
+input_shp = "E:\\projects\\遥感技术部需求\\裁剪栅格\\data\\grid0.shp"
+
+# 加载输入Shapefile图层
+input_layer = QgsVectorLayer(input_shp, "input_layer", "ogr")
+
+# 检查图层是否有效
+if not input_layer.isValid():
+    print("Failed to load input layer")
+else:
+    print("Input layer loaded successfully")
+
+# 获取输入图层的字段信息
+fields = input_layer.fields()
+
+# 输出目录路径(所有新的Shapefile文件会保存在这个目录下)
+output_dir = "E:\\projects\\遥感技术部需求\\裁剪栅格\\output\\"
+
+# 遍历输入图层的所有要素,并为每个要素保存一个单独的Shapefile文件
+for idx, feature in enumerate(input_layer.getFeatures()):
+    # 获取当前要素的几何数据
+    geometry = feature.geometry()
+
+    # 创建一个新的 Shapefile 文件名,可以使用索引或 ID 来命名
+    output_shp = os.path.join(output_dir, f"output_{idx + 1}.shp")
+
+    # 创建一个新的Shapefile图层来保存单个几何
+    # 我们假设输入图层是多边形类型,若输入为其他类型,需修改
+    output_layer = QgsVectorLayer(f"{input_layer.geometryType()}?crs={input_layer.crs().authid()}", f"output_{idx + 1}",
+                                  "memory")
+    output_layer_data_provider = output_layer.dataProvider()
+
+    # 将输入图层的字段添加到新图层中
+    output_layer_data_provider.addAttributes(fields)  # 添加字段到数据提供者
+    output_layer.updateFields()  # 更新字段信息
+
+    # 创建一个新的要素并设置其几何和属性
+    new_feature = QgsFeature()
+    new_feature.setGeometry(geometry)
+    new_feature.setAttributes(feature.attributes())
+
+    # 将新的要素添加到新图层
+    output_layer_data_provider.addFeature(new_feature)
+
+    # 创建输出shapefile
+    writer = QgsVectorFileWriter(output_shp, 'UTF-8', fields, QgsWkbTypes.MultiPolygon, input_layer.crs(),
+                                 'ESRI Shapefile')
+    writer.addFeature(feature)
+
+    # 完成写入并关闭输出文件
+    del writer

+ 69 - 0
processing/tools/Raster/extent.py

@@ -0,0 +1,69 @@
+from qgis._core import QgsRectangle
+from qgis.core import QgsVectorLayer, QgsFeature, QgsGeometry, QgsVectorFileWriter, QgsField, QgsWkbTypes
+from PyQt5.QtCore import QVariant
+
+# 输入shapefile路径
+input_shp = "E:\\projects\\遥感技术部需求\\裁剪栅格\\data\\grid.shp"
+
+# 输出shapefile路径
+output_shp = "E:\\projects\\遥感技术部需求\\裁剪栅格\\data\\grid_extent.shp"
+
+expand_distance = 50
+
+# 加载输入shapefile
+input_layer = QgsVectorLayer(input_shp, "input_layer", "ogr")
+
+if not input_layer.isValid():
+    print(f"Failed to load input shapefile: {input_shp}")
+else:
+    # 获取输入图层的字段信息
+    fields = input_layer.fields()
+
+    # 创建输出shapefile
+    writer = QgsVectorFileWriter(output_shp, 'UTF-8', fields, QgsWkbTypes.MultiPolygon, input_layer.crs(),
+                                 'ESRI Shapefile')
+
+    output_layer = QgsVectorLayer(output_shp, "output_shp", "ogr")
+
+    # 检查文件是否成功创建
+    if writer.hasError() != QgsVectorFileWriter.NoError:
+        print(f"Error creating output shapefile: {output_shp}")
+    else:
+        # 遍历输入shapefile中的要素
+        for feature in input_layer.getFeatures():
+            # 获取要素的geometry和extent
+            geometry = feature.geometry()
+            extent = geometry.boundingBox()  # 获取要素的extent(bounding box)
+            # 对extent进行外扩
+            # 使用 grow 方法来将bounding box外扩100米
+            # extent.grow(expand_distance)  # 扩展100米
+            # print(f"Feature ID: {feature.id()}, Extent: {extent}")
+            # 获取四至坐标
+            minX = extent.xMinimum()
+            maxX = extent.xMaximum()
+            minY = extent.yMinimum()
+            maxY = extent.yMaximum()
+
+            # 手动扩展extent,向四个方向扩展100米
+            expanded_minX = minX - expand_distance  # 向左扩展
+            expanded_maxX = maxX + expand_distance  # 向右扩展
+            expanded_minY = minY - expand_distance  # 向下扩展
+            expanded_maxY = maxY + expand_distance  # 向上扩展
+
+            # 创建新的扩展后的QgsRectangle
+            expanded_extent = QgsRectangle(expanded_minX, expanded_minY, expanded_maxX, expanded_maxY)
+
+            # 使用extent创建一个新的几何(矩形geometry)
+            new_geometry = QgsGeometry.fromRect(expanded_extent)
+
+            # 创建一个新的要素,并将新几何设置到要素中
+            new_feature = QgsFeature(fields)  # 创建新的空要素,使用相同的字段定义
+            new_feature.setGeometry(new_geometry)  # 设置新的几何(extent)
+            # 复制原始要素的属性到新的要素
+            new_feature.setAttributes(feature.attributes())  # 将原要素的属性复制到新要素
+            # 将修改后的要素添加到输出shapefile
+            writer.addFeature(new_feature)
+
+        # 完成写入并关闭输出文件
+        del writer
+        print(f"Features copied from {input_shp} to {output_shp} with modified extent.")

+ 57 - 0
processing/tools/Raster/rasterbuffer.py

@@ -0,0 +1,57 @@
+from qgis.core import (
+    QgsProject,
+    QgsVectorLayer,
+    QgsProcessingFeatureSourceDefinition,
+    QgsProcessing,
+    QgsApplication
+)
+from qgis.analysis import QgsNativeAlgorithms
+
+# 初始化 QGIS(适用于独立脚本)
+# 如果你在 QGIS 自带的 Python 控制台中运行,跳过这部分
+QgsApplication.setPrefixPath("/usr", True)
+qgs = QgsApplication([], False)
+qgs.initQgis()
+
+# 注册原生算法(若未启用)
+QgsApplication.processingRegistry().addProvider(QgsNativeAlgorithms())
+
+# 加载矢量图层
+layer_path = "/path/to/your/input_layer.shp"  # 替换为你的输入图层路径
+input_layer = QgsVectorLayer(layer_path, "Input Layer", "ogr")
+
+if not input_layer.isValid():
+    print("Failed to load the input layer!")
+else:
+    print("Input layer loaded successfully!")
+
+# 设置缓冲区参数
+buffer_distance = 10  # 缓冲区距离(单位取决于图层 CRS)
+output_path = "/path/to/your/output_buffer.shp"  # 替换为输出文件路径
+
+# 调用缓冲区工具
+params = {
+    'INPUT': QgsProcessingFeatureSourceDefinition(input_layer.source(), selectedFeaturesOnly=False),
+    'DISTANCE': buffer_distance,  # 缓冲区距离
+    'SEGMENTS': 4,  # 缓冲区边界平滑度(更多段数更平滑)
+    'END_CAP_STYLE': 2,  # 端点样式:0=圆角,1=平端,2=尖角
+    'JOIN_STYLE': 2,  # 节点连接样式:0=圆角,1=斜接,2=尖角
+    'MITER_LIMIT': 2,  # 斜接限值(仅当 JOIN_STYLE 为斜接时有效)
+    'DISSOLVE': False,  # 是否溶解结果
+    'OUTPUT': output_path  # 输出文件路径
+}
+
+# 运行缓冲区分析
+processing_output = QgsApplication.processingRegistry().algorithmById("native:buffer").run(params)
+
+if processing_output['OUTPUT']:
+    print(f"Buffer created successfully: {output_path}")
+else:
+    print("Buffer creation failed!")
+
+# 在 QGIS 中加载输出图层
+output_layer = QgsVectorLayer(output_path, "Buffered Layer", "ogr")
+QgsProject.instance().addMapLayer(output_layer)
+
+# 清理(适用于独立脚本)
+qgs.exitQgis()