ClipRasterByGrid.py 7.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191
  1. # -*- coding: utf-8 -*-
  2. __author__ = 'wanger'
  3. __description__ = '按照掩膜范围裁剪栅格数据'
  4. __date__ = '2024-11-25'
  5. __copyright__ = '(C) 2024 by siwei'
  6. __revision__ = '1.0'
  7. import os
  8. import subprocess
  9. import math
  10. from qgis._core import QgsRasterFileWriter, QgsProcessingParameterFolderDestination
  11. from qgis.core import (
  12. QgsVectorLayer,
  13. QgsRasterLayer,
  14. QgsFeature,
  15. QgsGeometry
  16. )
  17. import processing
  18. from PyQt5.QtCore import QFileInfo
  19. from qgis.analysis import QgsRasterCalculator, QgsRasterCalculatorEntry
  20. from qgis.PyQt.QtCore import QCoreApplication
  21. from qgis._core import QgsSpatialIndex, QgsField, QgsRectangle, QgsProcessingParameterVectorDestination, \
  22. QgsVectorFileWriter, QgsWkbTypes, QgsProcessingParameterNumber, QgsProcessingParameterBoolean, QgsGeometry, \
  23. QgsFeature
  24. from qgis.core import (QgsProcessing,
  25. QgsVectorLayer,
  26. QgsFeatureSink,
  27. QgsProcessingException,
  28. QgsProcessingAlgorithm,
  29. QgsProcessingParameterFile,
  30. QgsProcessingParameterFeatureSource,
  31. QgsProcessingParameterFeatureSink)
  32. from qgis import processing
  33. class ClipRasterByMaskProcessingAlgorithm(QgsProcessingAlgorithm):
  34. INPUT_SHP = 'INPUT_SHP'
  35. INPUT_RASTER = 'INPUT_RASTER'
  36. OUTPUT = 'OUTPUT'
  37. def tr(self, string):
  38. return QCoreApplication.translate('Processing', string)
  39. def createInstance(self):
  40. return ClipRasterByMaskProcessingAlgorithm()
  41. def name(self):
  42. return 'cliprasterbymask'
  43. def displayName(self):
  44. return self.tr('按照掩膜范围裁剪栅格数据')
  45. def group(self):
  46. return self.tr('栅格裁剪')
  47. def groupId(self):
  48. return 'rasterclip'
  49. def shortHelpString(self):
  50. return self.tr("遍历输入shp数据要素裁剪输入栅格,保存到输出文件夹。")
  51. def initAlgorithm(self, config=None):
  52. self.addParameter(QgsProcessingParameterFile(
  53. self.INPUT_SHP,
  54. '网格数据',
  55. extension='shp'
  56. ))
  57. self.addParameter(QgsProcessingParameterFile(
  58. self.INPUT_RASTER,
  59. '栅格数据',
  60. extension='tif'
  61. ))
  62. # 通过 setExtensions 方法设置多个扩展名
  63. # self.parameter(self.INPUT_RASTER).setExtensions(['tif', 'img']) # 支持 .shp, .csv, .txt
  64. self.addParameter(QgsProcessingParameterFolderDestination(self.OUTPUT, '输出文件夹'))
  65. # 执行
  66. def processAlgorithm(self, parameters, context, feedback):
  67. input_shp = self.parameterAsString(parameters, self.INPUT_SHP, context)
  68. input_raster = self.parameterAsOutputLayer(parameters, self.INPUT_RASTER, context)
  69. output_raster = self.parameterAsString(parameters, self.OUTPUT, context)
  70. # 输入Shapefile路径
  71. # input_shp = "E:\\projects\\遥感技术部需求\\裁剪栅格\\data\\grid_extent.shp"
  72. # 输入栅格数据路径
  73. # input_raster = "D:\\gisdata\\tif\\unnamed_卫图_Level_12.tif"
  74. # 输出裁剪后的栅格路径
  75. # output_raster = "E:\\projects\\遥感技术部需求\\裁剪栅格\\output\\"
  76. # 加载输入Shapefile和栅格数据
  77. vector_layer = QgsVectorLayer(input_shp, "vector_layer", "ogr")
  78. raster_layer = QgsRasterLayer(input_raster, "raster_layer")
  79. fields = vector_layer.fields()
  80. # 获取分辨率(像素大小)
  81. pixel_width = raster_layer.rasterUnitsPerPixelX()
  82. pixel_height = raster_layer.rasterUnitsPerPixelY()
  83. # 遍历输入图层的所有要素,并为每个要素保存一个单独的Shapefile文件
  84. total = 0
  85. for idx, feature in enumerate(vector_layer.getFeatures()):
  86. # 获取当前要素的几何数据
  87. geometry = feature.geometry()
  88. key = feature["新图号"]
  89. extent = geometry.boundingBox()
  90. # 创建一个新的 Shapefile 文件名,可以使用索引或 ID 来命名
  91. # output_shp = os.path.join(output_raster, f"{key}.shp")
  92. #
  93. # # 创建输出shapefile
  94. # writer = QgsVectorFileWriter(output_shp, 'UTF-8', fields, QgsWkbTypes.MultiPolygon, vector_layer.crs(),
  95. # 'ESRI Shapefile')
  96. # writer.addFeature(feature)
  97. #
  98. # # 完成写入并关闭输出文件
  99. # del writer
  100. # 使用QGIS的processing模块进行栅格裁剪
  101. # params = {
  102. # 'INPUT': raster_layer, # 输入栅格
  103. # 'MASK': output_shp, # 用于裁剪的矢量图层
  104. # 'OUTPUT': f"{output_raster}\\{key}.tif", # 输出裁剪后的栅格文件
  105. # 'CROP_TO_CUTLINE': True
  106. # }
  107. # 调用 clipRasterByExtent 进行裁剪
  108. # vector_layer_cur = QgsVectorLayer(output_shp, 'Shapefile Layer')
  109. # params = {
  110. # 'INPUT': input_raster,
  111. # 'EXTENT': vector_layer_cur.extent(),
  112. # 'PROJWIN': vector_layer_cur.extent(),
  113. # 'OUTPUT': f"{output_raster}\\{key}.tif"
  114. # }
  115. # extent = vector_layer_cur.extent()
  116. # 计算裁剪范围的整数倍,确保裁剪范围对齐
  117. minX = extent.xMinimum()
  118. maxX = extent.xMaximum()
  119. minY = extent.yMinimum()
  120. maxY = extent.yMaximum()
  121. # 通过对齐最大值,确保裁剪范围完整
  122. maxX_aligned = maxX + pixel_width
  123. maxY_aligned = maxY + pixel_width
  124. minX_aligned = minX - pixel_width
  125. minY_aligned = minY - pixel_width
  126. # maxX_aligned = math.ceil(maxX / pixel_width) * pixel_width + pixel_width
  127. # maxY_aligned = math.ceil(maxY / pixel_height) * pixel_height + pixel_width
  128. # minX_aligned = math.floor(minX / pixel_width) * pixel_width - pixel_width
  129. # minY_aligned = math.floor(minY / pixel_height) * pixel_height - pixel_width
  130. # extent_cur = f'{minX},{extent.yMaximum()},{extent.xMaximum()},{minY}' # 裁剪范围:minX,maxY,maxX,minY
  131. # extent_cur = f'524101.737 3310956.7264999966 530229.7547000019 3306243.2199' # 裁剪范围:minX,maxY,maxX,minY
  132. # print(extent_cur)
  133. # 设置 gdal_translate 命令和参数
  134. gdal_translate_cmd = [
  135. 'gdal_translate', # GDAL 工具名称
  136. '-projwin', str(minX_aligned), str(maxY_aligned), str(maxX_aligned), str(minY_aligned),
  137. # 裁剪范围(minX, maxY, maxX, minY)
  138. '-of', 'GTiff', # 输出格式为 GeoTIFF
  139. input_raster, # 输入栅格文件路径
  140. f"{output_raster}\\{key}.tif" # 输出文件路径
  141. ]
  142. print(gdal_translate_cmd)
  143. # 运行命令
  144. try:
  145. subprocess.run(gdal_translate_cmd, check=True)
  146. print("gdal_translate 执行成功!")
  147. total = total + 1
  148. except subprocess.CalledProcessError as e:
  149. print(f"gdal_translate 执行失败: {e}")
  150. # 3. 调用 `gdal:translate` 进行裁剪
  151. # parameters = {
  152. # 'INPUT': input_raster, # 输入栅格
  153. # 'OUTPUT': f"{output_raster}\\{key}.tif", # 输出路径
  154. # 'PROJWIN': extent_cur, # 裁剪范围 (左下右上)
  155. # # 'TARGET_CRS': 'EPSG:4544' # 可选:指定目标坐标系统(如果需要)
  156. # }
  157. # print(parameters)
  158. # 4. 运行工具
  159. # processing.run('gdal:translate', parameters)
  160. # 执行裁剪操作
  161. # processing.run('gdal:cliprasterbyextent', params)
  162. # processing.run('gdal:cliprasterbymasklayer', params)
  163. # print(f"Cropped raster saved to {output_raster}")
  164. return {
  165. "状态": f"处理成功,共裁剪出{total}块栅格数据。"
  166. }