Example #1
0
    def processAlgorithm(self, parameters, context, feedback):
        """
        Here is where the processing itself takes place.
        """
        featureHandler = FeatureHandler()
        startScaleIdx = self.parameterAsEnum(parameters, self.START_SCALE,
                                             context)
        stopScaleIdx = self.parameterAsEnum(parameters, self.STOP_SCALE,
                                            context)
        stopScale = self.scales[stopScaleIdx]
        stopScale = int(stopScale.replace('k', ''))
        if startScaleIdx > stopScaleIdx:
            raise QgsProcessingException(
                self.
                tr('The desired scale denominator must not be bigger than the base scale denominator.'
                   ))
        indexTypeIdx = self.parameterAsEnum(parameters, self.INDEX_TYPE,
                                            context)
        inputIndex = self.parameterAsString(parameters, self.INDEX, context)
        if startScaleIdx in [0, 1] and indexTypeIdx == 0:
            raise QgsProcessingException(
                self.tr('{index} is only valid for scales 250k and below.').
                format(index=self.indexTypes[indexTypeIdx]))
        if inputIndex is None or inputIndex == '':
            raise QgsProcessingException(
                self.tr('Invalid {index}').format(
                    index=self.indexTypes[indexTypeIdx]))
        index = self.getIndex(inputIndex, indexTypeIdx, startScaleIdx)
        if index is None or not self.validateIndex(index):
            raise QgsProcessingException(
                self.tr('Invalid {index} format.').format(
                    index=self.indexTypes[indexTypeIdx]))
        crs = self.parameterAsCrs(parameters, self.CRS, context)
        if crs is None or not crs.isValid():
            raise QgsProcessingException(self.tr('Invalid CRS.'))
        fields = QgsFields()
        fields.append(QgsField('inom', QVariant.String))
        fields.append(QgsField('mi', QVariant.String))
        (output_sink,
         output_sink_id) = self.parameterAsSink(parameters, self.OUTPUT,
                                                context, fields,
                                                QgsWkbTypes.Polygon, crs)
        featureList = []
        coordinateTransformer = QgsCoordinateTransform(
            QgsCoordinateReferenceSystem(crs.geographicCrsAuthId()), crs,
            QgsProject.instance())
        featureHandler.getSystematicGridFeatures(featureList,
                                                 index,
                                                 stopScale,
                                                 coordinateTransformer,
                                                 fields,
                                                 feedback=feedback)
        for feat in featureList:
            output_sink.addFeature(feat, QgsFeatureSink.FastInsert)

        return {'OUTPUT': output_sink_id}
Example #2
0
    def processAlgorithm(self, parameters, context, feedback):
        """
        Here is where the processing itself takes place.
        """
        featureHandler = FeatureHandler()
        inputLyr = self.parameterAsVectorLayer(parameters, self.INPUT, context)
        if inputLyr is None:
            raise QgsProcessingException(
                self.invalidSourceError(parameters, self.INPUT))

        inputType = inputLyr.wkbType()
        isMulti = QgsWkbTypes.isMultiType(int(inputType))
        inputFields = inputLyr.fields()

        onlySelected = self.parameterAsBool(parameters, self.SELECTED, context)
        (outershell_sink,
         outershell_dest_id) = self.parameterAsSink(parameters,
                                                    self.OUTERSHELL, context,
                                                    inputFields, inputType,
                                                    inputLyr.sourceCrs())
        if outershell_sink is None:
            raise QgsProcessingException(
                self.invalidSinkError(parameters, self.OUTERSHELL))

        (donuthole_sink,
         donuthole_dest_id) = self.parameterAsSink(parameters, self.DONUTHOLE,
                                                   context, inputFields,
                                                   inputType,
                                                   inputLyr.sourceCrs())
        if outershell_sink is None:
            raise QgsProcessingException(
                self.invalidSinkError(parameters, self.DONUTHOLE))
        # Compute the number of steps to display within the progress bar and
        # get features from source
        featureList, total = self.getIteratorAndFeatureCount(
            inputLyr, onlySelected=onlySelected
        )  #only selected is not applied because we are using an inner layer, not the original ones

        for current, feat in enumerate(featureList):
            # Stop the algorithm if cancel button has been clicked
            if feedback.isCanceled():
                break
            outerShellFeatList, donutHoleFeatList = featureHandler.getFeatureOuterShellAndHoles(
                feat, isMulti)
            for feat in outerShellFeatList:
                outershell_sink.addFeature(feat, QgsFeatureSink.FastInsert)
            for feat in donutHoleFeatList:
                donuthole_sink.addFeature(feat, QgsFeatureSink.FastInsert)
            # # Update the progress bar
            feedback.setProgress(int(current * total))
        return {
            self.DONUTHOLE: outershell_dest_id,
            self.OUTERSHELL: outershell_dest_id
        }
Example #3
0
 def processAlgorithm(self, parameters, context, feedback):
     """
     Here is where the processing itself takes place.
     """
     algsOutput, dest_id = self.parameterAsSink(
         parameters, self.OUTPUT, context, self.getFields(),
         QgsWkbTypes.NoGeometry, QgsCoordinateReferenceSystem('EPSG:4326'))
     tester = Tester()
     featureHandler = FeatureHandler()
     fields = self.getFields()
     feats = set()
     algIndexes = self.parameterAsEnums(parameters, self.INPUT_ALGS,
                                        context)
     size = len(algIndexes)
     failCount = 0
     totalProgress = 100 / size if size else 0
     feedback.setProgress(0)
     for currentStep, algIdx in enumerate(algIndexes):
         if feedback.isCanceled():
             break
         alg = self.AVAILABLE_ALGS[algIdx]
         feedback.pushInfo(self.tr("Testing {alg}'s...").format(alg=alg))
         # decided not to pass feedback to not pollute this alg's log
         msg = tester.testAlg(
             alg,
             multipleOutputs=True,
             attributeBlackList=['path'],
             addControlKey=True,
             context=context)  #, feedback=feedback, context=context)
         status = self.tr("Failed") if msg else self.tr("Passed")
         pushMethod = feedback.reportError if msg else feedback.pushDebugInfo
         failCount += 1 if msg else 0
         msg = msg or self.tr("All tests for {alg} are OK.").format(alg=alg)
         pushMethod("{msg}\n".format(msg=msg))
         feats.add(
             featureHandler.createFeatureFromLayer(algsOutput,
                                                   attributes={
                                                       "algorithm": alg,
                                                       "tests_output": msg,
                                                       "status": status
                                                   },
                                                   fields=fields))
         feedback.setProgress(currentStep * totalProgress)
     algsOutput.addFeatures(feats, QgsFeatureSink.FastInsert)
     if failCount:
         feedback.reportError(
             self.tr("{0} algorithms failed their unit tests.").format(
                 failCount))
     else:
         feedback.pushDebugInfo(
             self.tr("All algorithms passed their unit tests."))
     return {self.OUTPUT: dest_id}
Example #4
0
 def setFlags(self, flagDict, ptLayer, lLayer, polLayer, ctx, feedback):
     """
     Saves each flag to its layer, accordingly to its geometry primitive.
     :param flags: (dict) a map from offended feature ID to offenders
                   feature set.
     :param ctx: (QgsProcessingContext) context in which processing was run.
     :param feedback: (QgsProcessingFeedback) QGIS progress tracking
                      component.
     :return: (tuple-of-QgsVectorLayer) filled flag layers.
     """
     fh = FeatureHandler()
     gh = GeometryHandler()
     fields = self.getFlagFields()
     layerMap = {
         QgsWkbTypes.PointGeometry: ptLayer,
         QgsWkbTypes.LineGeometry: lLayer,
         QgsWkbTypes.PolygonGeometry: polLayer
     }
     for ruleName, flags in flagDict.items():
         flagText = self.tr('Rule "{name}" broken: {{text}}').format(
             name=ruleName)
         for flagList in flags.values():
             for flag in flagList:
                 geom = flag["geom"]
                 for g in gh.multiToSinglePart(geom):
                     newFeature = QgsFeature(fields)
                     newFeature["reason"] = flagText.format(
                         text=flag["text"])
                     newFeature.setGeometry(g)
                     layerMap[geom.type()].addFeature(
                         newFeature, QgsFeatureSink.FastInsert)
     return (ptLayer, lLayer, polLayer)
Example #5
0
 def mapFeatures(self,
                 inputPreparedLayers,
                 outputLayers,
                 featureConversionMap=None,
                 feedback=None):
     """
     Maps features from a given set of layers to a different set of layers (including attributes).
     :param inputPreparedLayers: (dict) map of layers to be translated.
     :param outputLayers: (dict) map of layers to be filled.
     :param featureConversionMap: (dict) map of features based on given input.
     :param feedback: (QgsProcessingMultiStepFeedback) QGIS tool for progress tracking.
     :return: (dict) map of (list-of-QgsFeature) features to be added to a (str) layer.
     """
     if featureConversionMap is not None:
         # do the conversion in here using the map - NOT YET SUPPORTED
         pass
     else:
         featuresMap = collections.defaultdict(set)
         lh = LayerHandler()
         fh = FeatureHandler()
         if feedback is not None:
             stepSize = 100 / len(inputPreparedLayers) if len(
                 inputPreparedLayers) else 0
         for current, (layer, vl) in enumerate(inputPreparedLayers.items()):
             if feedback is not None and feedback.isCanceled():
                 break
             if vl.featureCount() == 0 or layer not in outputLayers:
                 continue
             outuputLayer = outputLayers[layer]
             k = "{0}->{1}".format(vl.crs().authid(),
                                   outuputLayer.crs().authid())
             if k not in self.coordinateTransformers:
                 self.coordinateTransformers[
                     k] = lh.getCoordinateTransformer(
                         inputLyr=vl, outputLyr=outuputLayer)
             coordinateTransformer = self.coordinateTransformers[k]
             param = lh.getDestinationParameters(vl)
             for feature in vl.getFeatures(QgsFeatureRequest()):
                 featuresMap[layer] |= fh.handleConvertedFeature(
                     feat=feature,
                     lyr=outuputLayer,
                     parameterDict=param,
                     coordinateTransformer=coordinateTransformer)
             if feedback is not None:
                 feedback.setProgress(current * stepSize)
         return featuresMap
Example #6
0
    def processAlgorithm(self, parameters, context, feedback):
        """
        Here is where the processing itself takes place.
        """
        source = self.parameterAsSource(parameters, self.INPUT, context)
        onlySelected = self.parameterAsBool(parameters, self.SELECTED, context)
        target = self.parameterAsVectorLayer(parameters, self.INPUT, context)

        target.startEditing()
        target.beginEditCommand('Updating layer')
        fields = target.fields()
        paramDict = LayerHandler().getDestinationParameters(target)
        featHandler = FeatureHandler()
        featuresToAdd = []
        if onlySelected:
            total = 100.0 / target.selectedFeatureCount() if target.selectedFeatureCount() else 0
            features = target.getSelectedFeatures()
        else:
            total = 100.0 / target.featureCount() if target.featureCount() else 0
            features = target.getFeatures()            

        for current, feature in enumerate(features):
            if feedback.isCanceled():
                break
            if not feature.geometry():
                target.deleteFeature(feature.id())
                feedback.setProgress(int(current * total))
                continue
            updtGeom, newFeatList, update = featHandler.handleFeature([feature], feature, target, paramDict)
            if not update:
                feature.setGeometry(updtGeom)
                target.updateFeature(feature)
                featuresToAdd += newFeatList
            feedback.setProgress(int(current * total))
        if featuresToAdd:
            target.addFeatures(featuresToAdd, QgsFeatureSink.FastInsert)
        target.endEditCommand()
        # Return the results of the algorithm. In this case our only result is
        # the feature sink which contains the processed features, but some
        # algorithms may return multiple feature sinks, calculated numeric
        # statistics, etc. These should all be included in the returned
        # dictionary, with keys matching the feature corresponding parameter
        # or output names.
        return {self.OUTPUT: target}
Example #7
0
    def processAlgorithm(self, parameters, context, feedback):
        """
        Here is where the processing itself takes place.
        """
        featureHandler = FeatureHandler()
        inputLyr = self.parameterAsVectorLayer(parameters, self.INPUT, context)
        if inputLyr is None:
            raise QgsProcessingException(
                self.invalidSourceError(parameters, self.INPUT))
        stopScaleIdx = self.parameterAsEnum(parameters, self.STOP_SCALE,
                                            context)
        stopScale = self.scales[stopScaleIdx]
        stopScale = int(stopScale.replace('k', ''))
        fields = QgsFields()
        fields.append(QgsField('inom', QVariant.String))
        fields.append(QgsField('mi', QVariant.String))
        crs = inputLyr.crs()
        (output_sink,
         output_sink_id) = self.parameterAsSink(parameters, self.OUTPUT,
                                                context, fields,
                                                QgsWkbTypes.Polygon, crs)
        featureList = []
        coordinateTransformer = QgsCoordinateTransform(
            QgsCoordinateReferenceSystem(crs.geographicCrsAuthId()), crs,
            QgsProject.instance())
        featureHandler.getSystematicGridFeaturesWithConstraint(
            featureList,
            inputLyr,
            stopScale,
            coordinateTransformer,
            fields,
            feedback=feedback)
        list(
            map(lambda x: output_sink.addFeature(x, QgsFeatureSink.FastInsert),
                featureList))

        return {'OUTPUT': output_sink_id}
Example #8
0
    def processAlgorithm(self, parameters, context, feedback):
        """
        Here is where the processing itself takes place.
        """
        featureHandler = FeatureHandler()
        layerHandler = LayerHandler()
        inputLyr = self.parameterAsVectorLayer(parameters, self.INPUT, context)
        if inputLyr is None:
            raise QgsProcessingException(
                self.invalidSourceError(parameters, self.INPUT))

        inputAttr = self.parameterAsFields(parameters, self.FLAG_FIELD,
                                           context)
        inputAttr = inputAttr[0]
        tableSchema = self.parameterAsString(parameters, self.TABLE_SCHEMA,
                                             context)
        if tableSchema is None or tableSchema == '':
            raise QgsProcessingException(self.tr('Invalid table schema'))

        tableName = self.parameterAsString(parameters, self.TABLE_NAME,
                                           context)
        if tableName is None or tableName == '':
            raise QgsProcessingException(self.tr('Invalid table name'))

        geometryColumn = self.parameterAsString(parameters,
                                                self.GEOMETRY_COLUMN, context)
        if geometryColumn is None or geometryColumn == '':
            raise QgsProcessingException(self.tr('Invalid geometry column'))

        flagTextAttr = self.parameterAsString(parameters,
                                              self.OUTPUT_FLAG_TEXT_FIELD,
                                              context)
        if flagTextAttr is None or flagTextAttr == '':
            raise QgsProcessingException(
                self.tr('Invalid flag attribute column'))

        crs = self.parameterAsCrs(parameters, self.CRS, context)
        if crs is None or not crs.isValid():
            raise QgsProcessingException(self.tr('Invalid CRS.'))

        outputLyr = self.getOutputFromInput(inputLyr, tableSchema, tableName,
                                            geometryColumn)
        if not outputLyr.isValid():
            raise QgsProcessingException(self.tr('Invalid output layer.'))
        coordinateTransformer = QgsCoordinateTransform(
            QgsCoordinateReferenceSystem(crs.geographicCrsAuthId()), crs,
            QgsProject.instance())
        parameterDict = layerHandler.getDestinationParameters(outputLyr)
        outputLyr.startEditing()
        outputLyr.beginEditCommand('Adding flag features')
        count = inputLyr.featureCount()
        progress_count = 100 / count if count else 0
        for current, feat in enumerate(inputLyr.getFeatures()):
            if feedback.isCanceled():
                break
            for newFeat in featureHandler.handleConvertedFeature(
                    feat,
                    outputLyr,
                    parameterDict=parameterDict,
                    coordinateTransformer=coordinateTransformer):
                newFeat[flagTextAttr] = feat[inputAttr]
                outputLyr.addFeature(newFeat)
            feedback.setProgress(current * progress_count)
        outputLyr.endEditCommand()
        outputLyr.commitChanges()
        return {}