Relief.py 7.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171
  1. """
  2. ***************************************************************************
  3. Relief.py
  4. ---------------------
  5. Date : December 2016
  6. Copyright : (C) 2016 by Alexander Bruy
  7. Email : alexander dot bruy at gmail dot com
  8. ***************************************************************************
  9. * *
  10. * This program is free software; you can redistribute it and/or modify *
  11. * it under the terms of the GNU General Public License as published by *
  12. * the Free Software Foundation; either version 2 of the License, or *
  13. * (at your option) any later version. *
  14. * *
  15. ***************************************************************************
  16. """
  17. __author__ = 'Alexander Bruy'
  18. __date__ = 'December 2016'
  19. __copyright__ = '(C) 2016, Alexander Bruy'
  20. import os
  21. from qgis.PyQt.QtGui import QIcon, QColor
  22. from qgis.analysis import QgsRelief
  23. from qgis.core import (QgsProcessingParameterDefinition,
  24. QgsProcessingParameterRasterLayer,
  25. QgsProcessingParameterNumber,
  26. QgsProcessingParameterBoolean,
  27. QgsProcessingParameterRasterDestination,
  28. QgsProcessingParameterFileDestination,
  29. QgsRasterFileWriter,
  30. QgsProcessingException)
  31. from processing.algs.qgis.QgisAlgorithm import QgisAlgorithm
  32. pluginPath = os.path.split(os.path.split(os.path.dirname(__file__))[0])[0]
  33. class ParameterReliefColors(QgsProcessingParameterDefinition):
  34. def __init__(self, name='', description='', parent=None, optional=True):
  35. super().__init__(name, description, None, optional)
  36. self.parent = parent
  37. self.setMetadata({'widget_wrapper': 'processing.algs.qgis.ui.ReliefColorsWidget.ReliefColorsWidgetWrapper'})
  38. def type(self):
  39. return 'relief_colors'
  40. def clone(self):
  41. return ParameterReliefColors(self.name(), self.description(), self.parent,
  42. self.flags() & QgsProcessingParameterDefinition.FlagOptional)
  43. @staticmethod
  44. def valueToColors(value):
  45. if value is None:
  46. return None
  47. if value == '':
  48. return None
  49. if isinstance(value, str):
  50. return value.split(';')
  51. else:
  52. return ParameterReliefColors.colorsToString(value)
  53. @staticmethod
  54. def colorsToString(colors):
  55. return ';'.join('{:f}, {:f}, {:d}, {:d}, {:d}'.format(c[0],
  56. c[1],
  57. c[2],
  58. c[3],
  59. c[4])
  60. for c in colors)
  61. class Relief(QgisAlgorithm):
  62. INPUT = 'INPUT'
  63. Z_FACTOR = 'Z_FACTOR'
  64. AUTO_COLORS = 'AUTO_COLORS'
  65. COLORS = 'COLORS'
  66. OUTPUT = 'OUTPUT'
  67. FREQUENCY_DISTRIBUTION = 'FREQUENCY_DISTRIBUTION'
  68. def icon(self):
  69. return QIcon(os.path.join(pluginPath, 'images', 'dem.png'))
  70. def group(self):
  71. return self.tr('Raster terrain analysis')
  72. def groupId(self):
  73. return 'rasterterrainanalysis'
  74. def __init__(self):
  75. super().__init__()
  76. def initAlgorithm(self, config=None):
  77. self.addParameter(QgsProcessingParameterRasterLayer(self.INPUT,
  78. self.tr('Elevation layer')))
  79. self.addParameter(QgsProcessingParameterNumber(self.Z_FACTOR,
  80. self.tr('Z factor'), type=QgsProcessingParameterNumber.Double,
  81. minValue=0.00, defaultValue=1.0))
  82. self.addParameter(QgsProcessingParameterBoolean(self.AUTO_COLORS,
  83. self.tr('Generate relief classes automatically'),
  84. defaultValue=False))
  85. self.addParameter(ParameterReliefColors(self.COLORS,
  86. self.tr('Relief colors'),
  87. self.INPUT,
  88. True))
  89. self.addParameter(QgsProcessingParameterRasterDestination(self.OUTPUT,
  90. self.tr('Relief')))
  91. self.addParameter(QgsProcessingParameterFileDestination(self.FREQUENCY_DISTRIBUTION,
  92. self.tr('Frequency distribution'),
  93. 'CSV files (*.csv)',
  94. optional=True,
  95. createByDefault=False))
  96. def name(self):
  97. return 'relief'
  98. def displayName(self):
  99. return self.tr('Relief')
  100. def processAlgorithm(self, parameters, context, feedback):
  101. inputFile = self.parameterAsRasterLayer(parameters, self.INPUT, context).source()
  102. zFactor = self.parameterAsDouble(parameters, self.Z_FACTOR, context)
  103. automaticColors = self.parameterAsBoolean(parameters, self.AUTO_COLORS, context)
  104. outputFile = self.parameterAsOutputLayer(parameters, self.OUTPUT, context)
  105. frequencyDistribution = self.parameterAsFileOutput(parameters, self.FREQUENCY_DISTRIBUTION, context)
  106. outputFormat = QgsRasterFileWriter.driverForExtension(os.path.splitext(outputFile)[1])
  107. relief = QgsRelief(inputFile, outputFile, outputFormat)
  108. if automaticColors:
  109. reliefColors = relief.calculateOptimizedReliefClasses()
  110. else:
  111. colors = ParameterReliefColors.valueToColors(parameters[self.COLORS])
  112. if colors is None or len(colors) == 0:
  113. raise QgsProcessingException(
  114. self.tr('Specify relief colors or activate "Generate relief classes automatically" option.'))
  115. reliefColors = []
  116. for c in colors:
  117. v = c.split(',')
  118. color = QgsRelief.ReliefColor(QColor(int(v[2]), int(v[3]), int(v[4])),
  119. float(v[0]),
  120. float(v[1]))
  121. reliefColors.append(color)
  122. relief.setReliefColors(reliefColors)
  123. relief.setZFactor(zFactor)
  124. if frequencyDistribution:
  125. relief.exportFrequencyDistributionToCsv(frequencyDistribution)
  126. res = relief.processRaster(feedback)
  127. if res == 1:
  128. raise QgsProcessingException(self.tr('Can not open input file.'))
  129. elif res == 2:
  130. raise QgsProcessingException(self.tr('Can not get GDAL driver for output file.'))
  131. elif res == 3:
  132. raise QgsProcessingException(self.tr('Can not create output file.'))
  133. elif res == 4:
  134. raise QgsProcessingException(self.tr('Can not get input band.'))
  135. elif res == 5:
  136. raise QgsProcessingException(self.tr('Can not create output bands.'))
  137. elif res == 6:
  138. raise QgsProcessingException(self.tr('Output raster size is too small (at least 3 rows needed).'))
  139. elif res == 7:
  140. feedback.pushInfo(self.tr('Canceled.'))
  141. return {self.OUTPUT: outputFile, self.FREQUENCY_DISTRIBUTION: frequencyDistribution}