1# -*- coding: utf-8 -*- 2 3""" 4*************************************************************************** 5* * 6* This program is free software; you can redistribute it and/or modify * 7* it under the terms of the GNU General Public License as published by * 8* the Free Software Foundation; either version 2 of the License, or * 9* (at your option) any later version. * 10* * 11*************************************************************************** 12""" 13 14from qgis.PyQt.QtCore import QCoreApplication 15from qgis.core import (QgsProcessing, 16 QgsFeatureSink, 17 QgsProcessingException, 18 QgsProcessingAlgorithm, 19 QgsProcessingParameterFeatureSource, 20 QgsProcessingParameterFeatureSink) 21from qgis import processing 22 23 24class ExampleProcessingAlgorithm(QgsProcessingAlgorithm): 25 """ 26 This is an example algorithm that takes a vector layer and 27 creates a new identical one. 28 29 It is meant to be used as an example of how to create your own 30 algorithms and explain methods and variables used to do it. An 31 algorithm like this will be available in all elements, and there 32 is not need for additional work. 33 34 All Processing algorithms should extend the QgsProcessingAlgorithm 35 class. 36 """ 37 38 # Constants used to refer to parameters and outputs. They will be 39 # used when calling the algorithm from another algorithm, or when 40 # calling from the QGIS console. 41 42 INPUT = 'INPUT' 43 OUTPUT = 'OUTPUT' 44 45 def tr(self, string): 46 """ 47 Returns a translatable string with the self.tr() function. 48 """ 49 return QCoreApplication.translate('Processing', string) 50 51 def createInstance(self): 52 return ExampleProcessingAlgorithm() 53 54 def name(self): 55 """ 56 Returns the algorithm name, used for identifying the algorithm. This 57 string should be fixed for the algorithm, and must not be localised. 58 The name should be unique within each provider. Names should contain 59 lowercase alphanumeric characters only and no spaces or other 60 formatting characters. 61 """ 62 return 'myscript' 63 64 def displayName(self): 65 """ 66 Returns the translated algorithm name, which should be used for any 67 user-visible display of the algorithm name. 68 """ 69 return self.tr('My Script') 70 71 def group(self): 72 """ 73 Returns the name of the group this algorithm belongs to. This string 74 should be localised. 75 """ 76 return self.tr('Example scripts') 77 78 def groupId(self): 79 """ 80 Returns the unique ID of the group this algorithm belongs to. This 81 string should be fixed for the algorithm, and must not be localised. 82 The group id should be unique within each provider. Group id should 83 contain lowercase alphanumeric characters only and no spaces or other 84 formatting characters. 85 """ 86 return 'examplescripts' 87 88 def shortHelpString(self): 89 """ 90 Returns a localised short helper string for the algorithm. This string 91 should provide a basic description about what the algorithm does and the 92 parameters and outputs associated with it.. 93 """ 94 return self.tr("Example algorithm short description") 95 96 def initAlgorithm(self, config=None): 97 """ 98 Here we define the inputs and output of the algorithm, along 99 with some other properties. 100 """ 101 102 # We add the input vector features source. It can have any kind of 103 # geometry. 104 self.addParameter( 105 QgsProcessingParameterFeatureSource( 106 self.INPUT, 107 self.tr('Input layer'), 108 [QgsProcessing.TypeVectorAnyGeometry] 109 ) 110 ) 111 112 # We add a feature sink in which to store our processed features (this 113 # usually takes the form of a newly created vector layer when the 114 # algorithm is run in QGIS). 115 self.addParameter( 116 QgsProcessingParameterFeatureSink( 117 self.OUTPUT, 118 self.tr('Output layer') 119 ) 120 ) 121 122 def processAlgorithm(self, parameters, context, feedback): 123 """ 124 Here is where the processing itself takes place. 125 """ 126 127 # Retrieve the feature source and sink. The 'dest_id' variable is used 128 # to uniquely identify the feature sink, and must be included in the 129 # dictionary returned by the processAlgorithm function. 130 source = self.parameterAsSource( 131 parameters, 132 self.INPUT, 133 context 134 ) 135 136 # If source was not found, throw an exception to indicate that the algorithm 137 # encountered a fatal error. The exception text can be any string, but in this 138 # case we use the pre-built invalidSourceError method to return a standard 139 # helper text for when a source cannot be evaluated 140 if source is None: 141 raise QgsProcessingException(self.invalidSourceError(parameters, self.INPUT)) 142 143 (sink, dest_id) = self.parameterAsSink( 144 parameters, 145 self.OUTPUT, 146 context, 147 source.fields(), 148 source.wkbType(), 149 source.sourceCrs() 150 ) 151 152 # Send some information to the user 153 feedback.pushInfo('CRS is {}'.format(source.sourceCrs().authid())) 154 155 # If sink was not created, throw an exception to indicate that the algorithm 156 # encountered a fatal error. The exception text can be any string, but in this 157 # case we use the pre-built invalidSinkError method to return a standard 158 # helper text for when a sink cannot be evaluated 159 if sink is None: 160 raise QgsProcessingException(self.invalidSinkError(parameters, self.OUTPUT)) 161 162 # Compute the number of steps to display within the progress bar and 163 # get features from source 164 total = 100.0 / source.featureCount() if source.featureCount() else 0 165 features = source.getFeatures() 166 167 for current, feature in enumerate(features): 168 # Stop the algorithm if cancel button has been clicked 169 if feedback.isCanceled(): 170 break 171 172 # Add a feature in the sink 173 sink.addFeature(feature, QgsFeatureSink.FastInsert) 174 175 # Update the progress bar 176 feedback.setProgress(int(current * total)) 177 178 # To run another Processing algorithm as part of this algorithm, you can use 179 # processing.run(...). Make sure you pass the current context and feedback 180 # to processing.run to ensure that all temporary layer outputs are available 181 # to the executed algorithm, and that the executed algorithm can send feedback 182 # reports to the user (and correctly handle cancellation and progress reports!) 183 if False: 184 buffered_layer = processing.run("native:buffer", { 185 'INPUT': dest_id, 186 'DISTANCE': 1.5, 187 'SEGMENTS': 5, 188 'END_CAP_STYLE': 0, 189 'JOIN_STYLE': 0, 190 'MITER_LIMIT': 2, 191 'DISSOLVE': False, 192 'OUTPUT': 'memory:' 193 }, context=context, feedback=feedback)['OUTPUT'] 194 195 # Return the results of the algorithm. In this case our only result is 196 # the feature sink which contains the processed features, but some 197 # algorithms may return multiple feature sinks, calculated numeric 198 # statistics, etc. These should all be included in the returned 199 # dictionary, with keys matching the feature corresponding parameter 200 # or output names. 201 return {self.OUTPUT: dest_id} 202