mirror of
				https://github.com/qgis/QGIS.git
				synced 2025-10-31 00:06:02 -04:00 
			
		
		
		
	Prevent changes to files that weren't changed between releases. This eases review of the changes between releases significantly.
		
			
				
	
	
		
			198 lines
		
	
	
		
			6.4 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
			
		
		
	
	
			198 lines
		
	
	
		
			6.4 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
| # -*- coding: utf-8 -*-
 | |
| 
 | |
| """
 | |
| ***************************************************************************
 | |
|     RasterSampling.py
 | |
|     -----------------------
 | |
|     Date                 : July 2018
 | |
|     Copyright            : (C) 2018 by Matteo Ghetta
 | |
|     Email                : matteo dot ghetta at gmail dot com
 | |
| ***************************************************************************
 | |
| *                                                                         *
 | |
| *   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.                                   *
 | |
| *                                                                         *
 | |
| ***************************************************************************
 | |
| """
 | |
| 
 | |
| __author__ = 'Matteo Ghetta'
 | |
| __date__ = 'July 2018'
 | |
| __copyright__ = '(C) 2018, Matteo Ghetta'
 | |
| 
 | |
| 
 | |
| import os
 | |
| 
 | |
| from qgis.PyQt.QtGui import QIcon
 | |
| from qgis.PyQt.QtCore import QVariant
 | |
| 
 | |
| from qgis.core import (NULL,
 | |
|                        QgsApplication,
 | |
|                        QgsField,
 | |
|                        QgsFeatureSink,
 | |
|                        QgsRaster,
 | |
|                        QgsPointXY,
 | |
|                        QgsProcessing,
 | |
|                        QgsProcessingParameterRasterLayer,
 | |
|                        QgsProcessingParameterString,
 | |
|                        QgsProcessingParameterDefinition,
 | |
|                        QgsCoordinateTransform,
 | |
|                        QgsFields,
 | |
|                        QgsProcessingUtils,
 | |
|                        QgsProcessingException,
 | |
|                        QgsProcessingParameterFeatureSource,
 | |
|                        QgsProcessingParameterFeatureSink)
 | |
| 
 | |
| from processing.algs.qgis.QgisAlgorithm import QgisAlgorithm
 | |
| 
 | |
| 
 | |
| class RasterSampling(QgisAlgorithm):
 | |
| 
 | |
|     INPUT = 'INPUT'
 | |
|     RASTERCOPY = 'RASTERCOPY'
 | |
|     COLUMN_PREFIX = 'COLUMN_PREFIX'
 | |
|     OUTPUT = 'OUTPUT'
 | |
| 
 | |
|     def name(self):
 | |
|         return 'rastersampling'
 | |
| 
 | |
|     def displayName(self):
 | |
|         return self.tr('Sample raster values')
 | |
| 
 | |
|     def group(self):
 | |
|         return self.tr('Raster analysis')
 | |
| 
 | |
|     def groupId(self):
 | |
|         return 'rasteranalysis'
 | |
| 
 | |
|     def __init__(self):
 | |
|         super().__init__()
 | |
| 
 | |
|     def initAlgorithm(self, config=None):
 | |
|         self.addParameter(
 | |
|             QgsProcessingParameterFeatureSource(
 | |
|                 self.INPUT,
 | |
|                 self.tr('Input Point Layer'),
 | |
|                 [QgsProcessing.TypeVectorPoint]
 | |
|             )
 | |
|         )
 | |
| 
 | |
|         self.addParameter(
 | |
|             QgsProcessingParameterRasterLayer(
 | |
|                 self.RASTERCOPY,
 | |
|                 self.tr('Raster Layer to sample'),
 | |
|             )
 | |
|         )
 | |
| 
 | |
|         columnPrefix = QgsProcessingParameterString(
 | |
|             self.COLUMN_PREFIX,
 | |
|             self.tr('Output column prefix'), 'rvalue'
 | |
|         )
 | |
|         columnPrefix.setFlags(columnPrefix.flags() | QgsProcessingParameterDefinition.FlagAdvanced)
 | |
|         self.addParameter(columnPrefix)
 | |
| 
 | |
|         self.addParameter(
 | |
|             QgsProcessingParameterFeatureSink(
 | |
|                 self.OUTPUT,
 | |
|                 self.tr('Sampled Points')
 | |
|             )
 | |
|         )
 | |
| 
 | |
|     def processAlgorithm(self, parameters, context, feedback):
 | |
| 
 | |
|         source = self.parameterAsSource(
 | |
|             parameters,
 | |
|             self.INPUT,
 | |
|             context
 | |
|         )
 | |
| 
 | |
|         sampled_raster = self.parameterAsRasterLayer(
 | |
|             parameters,
 | |
|             self.RASTERCOPY,
 | |
|             context
 | |
|         )
 | |
| 
 | |
|         columnPrefix = self.parameterAsString(
 | |
|             parameters,
 | |
|             self.COLUMN_PREFIX,
 | |
|             context
 | |
|         )
 | |
| 
 | |
|         if source is None:
 | |
|             raise QgsProcessingException(self.invalidSourceError(parameters, self.INPUT))
 | |
| 
 | |
|         source_fields = source.fields()
 | |
|         raster_fields = QgsFields()
 | |
| 
 | |
|         # append field to vector as columnPrefix_bandCount
 | |
|         for b in range(sampled_raster.bandCount()):
 | |
|             raster_fields.append(QgsField(
 | |
|                 columnPrefix + str('_{}'.format(b + 1)), QVariant.Double
 | |
|             )
 | |
|             )
 | |
| 
 | |
|         # combine all the vector fields
 | |
|         out_fields = QgsProcessingUtils.combineFields(source_fields, raster_fields)
 | |
| 
 | |
|         (sink, dest_id) = self.parameterAsSink(
 | |
|             parameters,
 | |
|             self.OUTPUT,
 | |
|             context,
 | |
|             out_fields,
 | |
|             source.wkbType(),
 | |
|             source.sourceCrs()
 | |
|         )
 | |
| 
 | |
|         if sink is None:
 | |
|             raise QgsProcessingException(self.invalidSinkError(parameters, self.OUTPUT))
 | |
| 
 | |
|         total = 100.0 / source.featureCount() if source.featureCount() else 0
 | |
|         features = source.getFeatures()
 | |
| 
 | |
|         # create the coordinates transformation context
 | |
|         ct = QgsCoordinateTransform(source.sourceCrs(), sampled_raster.crs(), context.transformContext())
 | |
| 
 | |
|         for n, i in enumerate(source.getFeatures()):
 | |
| 
 | |
|             attrs = i.attributes()
 | |
| 
 | |
|             if i.geometry().isMultipart() and i.geometry().constGet().partCount() > 1:
 | |
|                 sink.addFeature(i, QgsFeatureSink.FastInsert)
 | |
|                 feedback.setProgress(int(n * total))
 | |
|                 feedback.reportError(self.tr('Impossible to sample data of multipart feature {}.').format(i.id()))
 | |
|                 continue
 | |
| 
 | |
|             # get the feature geometry as point
 | |
|             point = QgsPointXY()
 | |
|             if i.geometry().isMultipart():
 | |
|                 point = i.geometry().asMultiPoint()[0]
 | |
|             else:
 | |
|                 point = i.geometry().asPoint()
 | |
| 
 | |
|             # reproject to raster crs
 | |
|             try:
 | |
|                 point = ct.transform(point)
 | |
|             except QgsCsException:
 | |
|                 for b in range(sampled_raster.bandCount()):
 | |
|                     attrs.append(None)
 | |
|                 i.setAttributes(attrs)
 | |
|                 sink.addFeature(i, QgsFeatureSink.FastInsert)
 | |
|                 feedback.setProgress(int(n * total))
 | |
|                 feedback.reportError(self.tr('Could not reproject feature {} to raster CRS').format(i.id()))
 | |
|                 continue
 | |
| 
 | |
|             for b in range(sampled_raster.bandCount()):
 | |
|                 value, ok = sampled_raster.dataProvider().sample(point, b + 1)
 | |
|                 if ok:
 | |
|                     attrs.append(value)
 | |
|                 else:
 | |
|                     attrs.append(NULL)
 | |
| 
 | |
|             i.setAttributes(attrs)
 | |
| 
 | |
|             sink.addFeature(i, QgsFeatureSink.FastInsert)
 | |
|             feedback.setProgress(int(n * total))
 | |
| 
 | |
|         return {self.OUTPUT: dest_id}
 |