Exemple #1
0
    def processAlgorithm(self, progress):
        fieldName = self.getParameterValue(self.FIELD_NAME)
        fieldType = self.getParameterValue(self.FIELD_TYPE)
        fieldLength = self.getParameterValue(self.FIELD_LENGTH)
        fieldPrecision = self.getParameterValue(self.FIELD_PRECISION)
        code = self.getParameterValue(self.FORMULA)
        globalExpression = self.getParameterValue(self.GLOBAL)
        output = self.getOutputFromName(self.OUTPUT_LAYER)

        layer = dataobjects.getObjectFromUri(
            self.getParameterValue(self.INPUT_LAYER))
        provider = layer.dataProvider()
        fields = provider.fields()
        fields.append(
            QgsField(fieldName, self.TYPES[fieldType], '', fieldLength,
                     fieldPrecision))
        writer = output.getVectorWriter(fields, provider.geometryType(),
                                        layer.crs())
        outFeat = QgsFeature()
        new_ns = {}

        # Run global code
        if globalExpression.strip() != '':
            try:
                bytecode = compile(globalExpression, '<string>', 'exec')
                exec(bytecode, new_ns)
            except:
                raise GeoAlgorithmExecutionException(
                    self.
                    tr("FieldPyculator code execute error.Global code block can't be executed!\n%s\n%s"
                       % (unicode(sys.exc_info()[0].__name__),
                          unicode(sys.exc_info()[1]))))

        # Replace all fields tags
        fields = provider.fields()
        num = 0
        for field in fields:
            field_name = unicode(field.name())
            replval = '__attr[' + unicode(num) + ']'
            code = code.replace('<' + field_name + '>', replval)
            num += 1

        # Replace all special vars
        code = code.replace('$id', '__id')
        code = code.replace('$geom', '__geom')
        need_id = code.find('__id') != -1
        need_geom = code.find('__geom') != -1
        need_attrs = code.find('__attr') != -1

        # Compile
        try:
            bytecode = compile(code, '<string>', 'exec')
        except:
            raise GeoAlgorithmExecutionException(
                self.
                tr("FieldPyculator code execute error.Field code block can't be executed!\n%s\n%s"
                   % (unicode(sys.exc_info()[0].__name__),
                      unicode(sys.exc_info()[1]))))

        # Run
        features = vector.features(layer)
        total = 100.0 / len(features)
        for current, feat in enumerate(features):
            progress.setPercentage(int(current * total))
            attrs = feat.attributes()
            feat_id = feat.id()

            # Add needed vars
            if need_id:
                new_ns['__id'] = feat_id

            if need_geom:
                geom = feat.geometry()
                new_ns['__geom'] = geom

            if need_attrs:
                pyattrs = [a for a in attrs]
                new_ns['__attr'] = pyattrs

            # Clear old result
            if self.RESULT_VAR_NAME in new_ns:
                del new_ns[self.RESULT_VAR_NAME]

            # Exec
            exec(bytecode, new_ns)

            # Check result
            if self.RESULT_VAR_NAME not in new_ns:
                raise GeoAlgorithmExecutionException(
                    self.tr("FieldPyculator code execute error\n"
                            "Field code block does not return '%s1' variable! "
                            "Please declare this variable in your code!" %
                            self.RESULT_VAR_NAME))

            # Write feature
            outFeat.setGeometry(feat.geometry())
            attrs.append(new_ns[self.RESULT_VAR_NAME])
            outFeat.setAttributes(attrs)
            writer.addFeature(outFeat)

        del writer
Exemple #2
0
    def processAlgorithm(self, context, feedback):
        layer = QgsProcessingUtils.mapLayerFromString(
            self.getParameterValue(self.INPUT), context)
        index = self.getParameterValue(self.TYPE)

        splitNodes = False
        if index == 0:
            newType = QgsWkbTypes.Point
        elif index == 1:
            newType = QgsWkbTypes.Point
            splitNodes = True
        elif index == 2:
            newType = QgsWkbTypes.LineString
        elif index == 3:
            newType = QgsWkbTypes.MultiLineString
        elif index == 4:
            newType = QgsWkbTypes.Polygon
        else:
            newType = QgsWkbTypes.Point

        writer = self.getOutputFromName(self.OUTPUT).getVectorWriter(
            layer.fields(), newType, layer.crs(), context)

        features = QgsProcessingUtils.getFeatures(layer, context)
        total = 100.0 / QgsProcessingUtils.featureCount(layer, context)

        for current, f in enumerate(features):
            geom = f.geometry()
            geomType = geom.wkbType()

            if geomType in [QgsWkbTypes.Point, QgsWkbTypes.Point25D]:
                if newType == QgsWkbTypes.Point:
                    writer.addFeature(f)
                else:
                    raise GeoAlgorithmExecutionException(
                        self.tr('Cannot convert from {0} to {1}').format(
                            geomType, newType))
            elif geomType in [
                    QgsWkbTypes.MultiPoint, QgsWkbTypes.MultiPoint25D
            ]:
                if newType == QgsWkbTypes.Point and splitNodes:
                    points = geom.asMultiPoint()
                    for p in points:
                        feat = QgsFeature()
                        feat.setAttributes(f.attributes())
                        feat.setGeometry(QgsGeometry.fromPoint(p))
                        writer.addFeature(feat)
                elif newType == QgsWkbTypes.Point:
                    feat = QgsFeature()
                    feat.setAttributes(f.attributes())
                    feat.setGeometry(geom.centroid())
                    writer.addFeature(feat)
                else:
                    raise GeoAlgorithmExecutionException(
                        self.tr('Cannot convert from {0} to {1}').format(
                            geomType, newType))
            elif geomType in [
                    QgsWkbTypes.LineString, QgsWkbTypes.LineString25D
            ]:
                if newType == QgsWkbTypes.Point and splitNodes:
                    points = geom.asPolyline()
                    for p in points:
                        feat = QgsFeature()
                        feat.setAttributes(f.attributes())
                        feat.setGeometry(QgsGeometry.fromPoint(p))
                        writer.addFeature(feat)
                elif newType == QgsWkbTypes.Point:
                    feat = QgsFeature()
                    feat.setAttributes(f.attributes())
                    feat.setGeometry(geom.centroid())
                    writer.addFeature(feat)
                elif newType == QgsWkbTypes.LineString:
                    writer.addFeature(f)
                else:
                    raise GeoAlgorithmExecutionException(
                        self.tr('Cannot convert from {0} to {1}').format(
                            geomType, newType))
            elif geomType in [
                    QgsWkbTypes.MultiLineString, QgsWkbTypes.MultiLineString25D
            ]:
                if newType == QgsWkbTypes.Point and splitNodes:
                    lines = geom.asMultiPolyline()
                    for line in lines:
                        for p in line:
                            feat = QgsFeature()
                            feat.setAttributes(f.attributes())
                            feat.setGeometry(QgsGeometry.fromPoint(p))
                            writer.addFeature(feat)
                elif newType == QgsWkbTypes.Point:
                    feat = QgsFeature()
                    feat.setAttributes(f.attributes())
                    feat.setGeometry(geom.centroid())
                    writer.addFeature(feat)
                elif newType == QgsWkbTypes.LineString:
                    lines = geom.asMultiPolyline()
                    for line in lines:
                        feat = QgsFeature()
                        feat.setAttributes(f.attributes())
                        feat.setGeometry(QgsGeometry.fromPolyline(line))
                        writer.addFeature(feat)
                elif newType == QgsWkbTypes.MultiLineString:
                    writer.addFeature(f)
                else:
                    raise GeoAlgorithmExecutionException(
                        self.tr('Cannot convert from {0} to {1}').format(
                            geomType, newType))
            elif geomType in [QgsWkbTypes.Polygon, QgsWkbTypes.Polygon25D]:
                if newType == QgsWkbTypes.Point and splitNodes:
                    rings = geom.asPolygon()
                    for ring in rings:
                        for p in ring:
                            feat = QgsFeature()
                            feat.setAttributes(f.attributes())
                            feat.setGeometry(QgsGeometry.fromPoint(p))
                            writer.addFeature(feat)
                elif newType == QgsWkbTypes.Point:
                    feat = QgsFeature()
                    feat.setAttributes(f.attributes())
                    feat.setGeometry(geom.centroid())
                    writer.addFeature(feat)
                elif newType == QgsWkbTypes.MultiLineString:
                    rings = geom.asPolygon()
                    feat = QgsFeature()
                    feat.setAttributes(f.attributes())
                    feat.setGeometry(QgsGeometry.fromMultiPolyline(rings))
                    writer.addFeature(feat)
                elif newType == QgsWkbTypes.Polygon:
                    writer.addFeature(f)
                else:
                    raise GeoAlgorithmExecutionException(
                        self.tr('Cannot convert from {0} to {1}').format(
                            geomType, newType))
            elif geomType in [
                    QgsWkbTypes.MultiPolygon, QgsWkbTypes.MultiPolygon25D
            ]:
                if newType == QgsWkbTypes.Point and splitNodes:
                    polygons = geom.asMultiPolygon()
                    for polygon in polygons:
                        for line in polygon:
                            for p in line:
                                feat = QgsFeature()
                                feat.setAttributes(f.attributes())
                                feat.setGeometry(QgsGeometry.fromPoint(p))
                                writer.addFeature(feat)
                elif newType == QgsWkbTypes.Point:
                    feat = QgsFeature()
                    feat.setAttributes(f.attributes())
                    feat.setGeometry(geom.centroid())
                    writer.addFeature(feat)
                elif newType == QgsWkbTypes.LineString:
                    polygons = geom.asMultiPolygon()
                    for polygons in polygons:
                        feat = QgsFeature()
                        feat.setAttributes(f.attributes())
                        feat.setGeometry(QgsGeometry.fromPolyline(polygon))
                        writer.addFeature(feat)
                elif newType == QgsWkbTypes.Polygon:
                    polygons = geom.asMultiPolygon()
                    for polygon in polygons:
                        feat = QgsFeature()
                        feat.setAttributes(f.attributes())
                        feat.setGeometry(QgsGeometry.fromPolygon(polygon))
                        writer.addFeature(feat)
                elif newType in [
                        QgsWkbTypes.MultiLineString, QgsWkbTypes.MultiPolygon
                ]:
                    writer.addFeature(f)
                else:
                    raise GeoAlgorithmExecutionException(
                        self.tr('Cannot convert from {0} to {1}').format(
                            geomType, newType))

            feedback.setProgress(int(current * total))

        del writer
Exemple #3
0
class GeoAlgorithm:

    _icon = QtGui.QIcon(os.path.dirname(__file__) + '/../images/alg.png')

    def __init__(self):
        # Parameters needed by the algorithm
        self.parameters = list()

        # Outputs generated by the algorithm
        self.outputs = list()

        # Name and group for normal toolbox display
        self.name = ''
        self.group = ''

        # The crs taken from input layers (if possible), and used when
        # loading output layers
        self.crs = None

        # Change any of the following if your algorithm should not
        # appear in the toolbox or modeler
        self.showInToolbox = True
        self.showInModeler = True
        #if true, will show only loaded layers in parameters dialog.
        #Also, if True, the algorithm does not run on the modeler
        #or batch ptocessing interface
        self.allowOnlyOpenedLayers = False

        # False if it should not be run a a batch process
        self.canRunInBatchMode = True

        # To be set by the provider when it loads the algorithm
        self.provider = None

        # If the algorithm is run as part of a model, the parent model
        # can be set in this variable, to allow for customized
        # behaviour, in case some operations should be run differently
        # when running as part of a model
        self.model = None

        self.defineCharacteristics()

    def getCopy(self):
        """Returns a new instance of this algorithm, ready to be used
        for being executed.
        """
        newone = copy.copy(self)
        newone.parameters = copy.deepcopy(self.parameters)
        newone.outputs = copy.deepcopy(self.outputs)
        return newone

    # methods to overwrite when creating a custom geoalgorithm

    def getIcon(self):
        return self._icon

    @staticmethod
    def getDefaultIcon():
        return GeoAlgorithm._icon

    def help(self):
        """Returns the help with the description of this algorithm.
        It returns a tuple boolean, string. IF the boolean value is true, it means that
        the string contains the actual description. If false, it is an url or path to a file
        where the description is stored.

        Returns None if there is no help file available.

        The default implementation looks for an rst file in a help folder under the folder
        where the algorithm is located.
        The name of the file is the name console name of the algorithm, without the namespace part
        """
        name = self.commandLineName().split(':')[1].lower()
        filename = os.path.join(
            os.path.dirname(inspect.getfile(self.__class__)), 'help',
            name + '.rst')
        print filename
        try:
            html = getHtmlFromRstFile(filename)
            return True, html
        except:
            return False, None

    def processAlgorithm(self):
        """Here goes the algorithm itself.

        There is no return value from this method.
        A GeoAlgorithmExecutionException should be raised in case
        something goes wrong.
        """
        pass

    def defineCharacteristics(self):
        """Here is where the parameters and outputs should be defined.
        """
        pass

    def getCustomParametersDialog(self):
        """If the algorithm has a custom parameters dialog, it should
        be returned here, ready to be executed.
        """
        return None

    def getCustomModelerParametersDialog(self, modelAlg, algIndex=None):
        """If the algorithm has a custom parameters dialog when called
        from the modeler, it should be returned here, ready to be
        executed.
        """
        return None

    def getParameterDescriptions(self):
        """Returns a dict with param names as keys and detailed
        descriptions of each param as value. These descriptions are
        used as tool tips in the parameters dialog.

        If a description does not exist, the parameter's
        human-readable name is used.
        """
        descs = {}
        return descs

    def checkBeforeOpeningParametersDialog(self):
        """If there is any check to perform before the parameters
        dialog is opened, it should be done here.

        This method returns an error message string if there is any
        problem (for instance, an external app not configured yet),
        or None if the parameters dialog can be opened.

        Note that this check should also be done in the
        processAlgorithm method, since algorithms can be called without
        opening the parameters dialog.
        """
        return None

    def checkParameterValuesBeforeExecuting(self):
        """If there is any check to do before launching the execution
        of the algorithm, it should be done here.

        If values are not correct, a message should be returned
        explaining the problem.

        This check is called from the parameters dialog, and also when
        calling from the console.
        """
        return None

    # =========================================================

    def execute(self, progress=None, model=None):
        """The method to use to call a processing algorithm.

        Although the body of the algorithm is in processAlgorithm(),
        it should be called using this method, since it performs
        some additional operations.

        Raises a GeoAlgorithmExecutionException in case anything goes
        wrong.
        """
        self.model = model
        try:
            self.setOutputCRS()
            self.resolveTemporaryOutputs()
            self.checkOutputFileExtensions()
            self.runPreExecutionScript(progress)
            self.processAlgorithm(progress)
            progress.setPercentage(100)
            self.convertUnsupportedFormats(progress)
            self.runPostExecutionScript(progress)
        except GeoAlgorithmExecutionException, gaee:
            ProcessingLog.addToLog(ProcessingLog.LOG_ERROR, gaee.msg)
            raise gaee
        except Exception, e:
            # If something goes wrong and is not caught in the
            # algorithm, we catch it here and wrap it
            lines = ['Uncaught error while executing algorithm']
            errstring = traceback.format_exc()
            newline = errstring.find('\n')
            if newline != -1:
                lines.append(errstring[:newline])
            else:
                lines.append(errstring)
            lines.append(errstring.replace('\n', '|'))
            ProcessingLog.addToLog(ProcessingLog.LOG_ERROR, lines)
            raise GeoAlgorithmExecutionException(
                str(e) + '\nSee log for more details')
Exemple #4
0
    def processAlgorithm(self, parameters, context, feedback):
        expression = self.getParameterValue(self.EXPRESSION)
        layersValue = self.getParameterValue(self.LAYERS)
        layersDict = {}
        if layersValue:
            layers = [
                QgsProcessingUtils.mapLayerFromString(f, context)
                for f in layersValue.split(";")
            ]
            layersDict = {
                os.path.basename(lyr.source().split(".")[0]): lyr
                for lyr in layers
            }

        for lyr in QgsProcessingUtils.compatibleRasterLayers(
                QgsProject.instance()):
            name = lyr.name()
            if (name + "@") in expression:
                layersDict[name] = lyr

        entries = []
        for name, lyr in layersDict.items():
            for n in range(lyr.bandCount()):
                entry = QgsRasterCalculatorEntry()
                entry.ref = '{:s}@{:d}'.format(name, n + 1)
                entry.raster = lyr
                entry.bandNumber = n + 1
                entries.append(entry)

        output = self.getOutputValue(self.OUTPUT)
        extentValue = self.getParameterValue(self.EXTENT)
        if not extentValue:
            extentValue = QgsProcessingUtils.combineLayerExtents(layersValue)

        if extentValue:
            extent = extentValue.split(',')
            bbox = QgsRectangle(float(extent[0]), float(extent[2]),
                                float(extent[1]), float(extent[3]))
        else:
            if layersDict:
                bbox = list(layersDict.values())[0].extent()
                for lyr in layersDict.values():
                    bbox.combineExtentWith(lyr.extent())
            else:
                raise GeoAlgorithmExecutionException(
                    self.tr("No layers selected"))

        def _cellsize(layer):
            return (layer.extent().xMaximum() -
                    layer.extent().xMinimum()) / layer.width()

        cellsize = self.getParameterValue(self.CELLSIZE) or min(
            [_cellsize(lyr) for lyr in layersDict.values()])
        width = math.floor((bbox.xMaximum() - bbox.xMinimum()) / cellsize)
        height = math.floor((bbox.yMaximum() - bbox.yMinimum()) / cellsize)
        driverName = GdalUtils.getFormatShortNameFromFilename(output)
        calc = QgsRasterCalculator(expression, output, driverName, bbox, width,
                                   height, entries)

        res = calc.processCalculation()
        if res == QgsRasterCalculator.ParserError:
            raise GeoAlgorithmExecutionException(
                self.tr("Error parsing formula"))
Exemple #5
0
    def processAlgorithm(self, context, feedback):
        layer = self.getParameterValue(self.INPUT_LAYER)
        mapping = self.getParameterValue(self.FIELDS_MAPPING)
        output = self.getOutputFromName(self.OUTPUT_LAYER)

        layer = QgsProcessingUtils.mapLayerFromString(layer, context)
        fields = QgsFields()
        expressions = []

        da = QgsDistanceArea()
        da.setSourceCrs(layer.crs())
        da.setEllipsoid(QgsProject.instance().ellipsoid())

        exp_context = layer.createExpressionContext()

        for field_def in mapping:
            fields.append(
                QgsField(field_def['name'], field_def['type'],
                         field_def['length'], field_def['precision']))

            expression = QgsExpression(field_def['expression'])
            expression.setGeomCalculator(da)
            expression.setDistanceUnits(QgsProject.instance().distanceUnits())
            expression.setAreaUnits(QgsProject.instance().areaUnits())
            expression.prepare(exp_context)
            if expression.hasParserError():
                raise GeoAlgorithmExecutionException(
                    self.tr(u'Parser error in expression "{}": {}').format(
                        str(expression.expression()),
                        str(expression.parserErrorString())))
            expressions.append(expression)

        writer = output.getVectorWriter(fields, layer.wkbType(), layer.crs(),
                                        context)

        # Create output vector layer with new attributes
        error_exp = None
        inFeat = QgsFeature()
        outFeat = QgsFeature()
        features = QgsProcessingUtils.getFeatures(layer, context)
        count = QgsProcessingUtils.featureCount(layer, context)
        if count > 0:
            total = 100.0 / count
            for current, inFeat in enumerate(features):
                rownum = current + 1

                geometry = inFeat.geometry()
                outFeat.setGeometry(geometry)

                attrs = []
                for i in range(0, len(mapping)):
                    field_def = mapping[i]
                    expression = expressions[i]
                    exp_context.setFeature(inFeat)
                    exp_context.lastScope().setVariable("row_number", rownum)
                    value = expression.evaluate(exp_context)
                    if expression.hasEvalError():
                        error_exp = expression
                        break

                    attrs.append(value)
                outFeat.setAttributes(attrs)

                writer.addFeature(outFeat)

                feedback.setProgress(int(current * total))
        else:
            feedback.setProgress(100)

        del writer

        if error_exp is not None:
            raise GeoAlgorithmExecutionException(
                self.tr(u'Evaluation error in expression "{}": {}').format(
                    str(error_exp.expression()),
                    str(error_exp.parserErrorString())))
Exemple #6
0
    def getImportCommands(self):
        commands = []

        # Just use main mirror
        commands.append('options("repos"="http://cran.at.r-project.org/")')

        # Try to install packages if needed
        packages = RUtils.getRequiredPackages(self.script)
        packages.extend(['rgdal', 'raster'])
        for p in packages:
            commands.append('tryCatch(find.package("' + p +
                            '"), error=function(e) install.packages("' + p +
                            '", dependencies=TRUE))')
        commands.append('library("raster")')
        commands.append('library("rgdal")')

        for param in self.parameters:
            if isinstance(param, ParameterRaster):
                value = param.value
                value = value.replace('\\', '/')
                if self.passFileNames:
                    commands.append(param.name + ' = "' + value + '"')
                elif self.useRasterPackage:
                    commands.append(param.name + ' = ' + 'brick("' + value +
                                    '")')
                else:
                    commands.append(param.name + ' = ' + 'readGDAL("' + value +
                                    '")')
            if isinstance(param, ParameterVector):
                value = param.getSafeExportedLayer()
                value = value.replace('\\', '/')
                filename = os.path.basename(value)
                filename = filename[:-4]
                folder = os.path.dirname(value)
                if self.passFileNames:
                    commands.append(param.name + ' = "' + value + '"')
                else:
                    commands.append(param.name + ' = readOGR("' + folder +
                                    '",layer="' + filename + '")')
            if isinstance(param, ParameterTable):
                value = param.value
                if not value.lower().endswith('csv'):
                    raise GeoAlgorithmExecutionException(
                        'Unsupported input file format.\n' + value)
                if self.passFileNames:
                    commands.append(param.name + ' = "' + value + '"')
                else:
                    commands.append(param.name + ' <- read.csv("' + value +
                                    '", head=TRUE, sep=",")')
            elif isinstance(
                    param,
                (ParameterTableField, ParameterString, ParameterFile)):
                commands.append(param.name + '="' + param.value + '"')
            elif isinstance(param, (ParameterNumber, ParameterSelection)):
                commands.append(param.name + '=' + str(param.value))
            elif isinstance(param, ParameterBoolean):
                if param.value:
                    commands.append(param.name + '=TRUE')
                else:
                    commands.append(param.name + '=FALSE')
            elif isinstance(param, ParameterMultipleInput):
                iLayer = 0
                if param.datatype == ParameterMultipleInput.TYPE_RASTER:
                    layers = param.value.split(';')
                    for layer in layers:
                        layer = layer.replace('\\', '/')
                        if self.passFileNames:
                            commands.append('tempvar' + str(iLayer) + ' <- "' +
                                            layer + '"')
                        elif self.useRasterPackage:
                            commands.append('tempvar' + str(iLayer) + ' <- ' +
                                            'brick("' + layer + '")')
                        else:
                            commands.append('tempvar' + str(iLayer) + ' <- ' +
                                            'readGDAL("' + layer + '")')
                        iLayer += 1
                else:
                    exported = param.getSafeExportedLayers()
                    layers = exported.split(';')
                    for layer in layers:
                        if not layer.lower().endswith('shp') \
                            and not self.passFileNames:
                            raise GeoAlgorithmExecutionException(
                                'Unsupported input file format.\n' + layer)
                        layer = layer.replace('\\', '/')
                        filename = os.path.basename(layer)
                        filename = filename[:-4]
                        if self.passFileNames:
                            commands.append('tempvar' + str(iLayer) + ' <- "' +
                                            layer + '"')
                        else:
                            commands.append('tempvar' + str(iLayer) + ' <- ' +
                                            'readOGR("' + layer + '",layer="' +
                                            filename + '")')
                        iLayer += 1
                s = ''
                s += param.name
                s += ' = c('
                iLayer = 0
                for layer in layers:
                    if iLayer != 0:
                        s += ','
                    s += 'tempvar' + str(iLayer)
                    iLayer += 1
                s += ')\n'
                commands.append(s)

        if self.showPlots:
            htmlfilename = self.getOutputValue(RAlgorithm.RPLOTS)
            self.plotsFilename = htmlfilename + '.png'
            self.plotsFilename = self.plotsFilename.replace('\\', '/')
            commands.append('png("' + self.plotsFilename + '")')

        return commands
Exemple #7
0
    def processAlgorithm(self, progress):
        currentOs = os.name

        path = OTBUtils.otbPath()
        libpath = OTBUtils.otbLibPath()
        if path == "" or libpath == "":
            raise GeoAlgorithmExecutionException(
                "OTB folder is not configured.\nPlease configure it before running OTB algorithms."
            )

        commands = []
        commands.append(path + os.sep + self.cliName)

        self.roiVectors = {}
        self.roiRasters = {}
        for param in self.parameters:
            # get the given input(s)
            if param.name in ["-il", "-in"]:
                newparams = ""
                listeParameters = param.value.split(";")
                for inputParameter in listeParameters:
                    # if HDF5 file
                    if "HDF5" in inputParameter:
                        if currentOs == "posix":
                            data = inputParameter[6:]
                        else:
                            data = inputParameter[5:]
                        dataset = data

                        #on windows, there isn't "
                        #if data[-1] == '"':
                        if currentOs == "posix":
                            data = data[:data.index('"')]
                        else:
                            data = data[:data.index('://')]
                        #try :
                        if currentOs == "posix":
                            dataset.index('"')
                            dataset = os.path.basename(
                                data) + dataset[dataset.index('"'):]
                        #except ValueError :
                        else:
                            #dataset = os.path.basename( data ) + '"' + dataset[dataset.index('://'):]
                            dataset = dataset[dataset.index('://'):]

                        #get index of the subdataset with gdal
                        if currentOs == "posix":
                            commandgdal = "gdalinfo " + data + " | grep '" + dataset + "$'"
                        else:
                            commandgdal = "gdalinfo " + data + " | findstr \"" + dataset + "$\""
                        resultGDAL = os.popen(commandgdal).readlines()
                        indexSubdataset = -1
                        if resultGDAL:
                            indexSubdatasetString = re.search(
                                "SUBDATASET_(\d+)_", resultGDAL[0])
                            if indexSubdatasetString:
                                #match between ()
                                indexSubdataset = indexSubdatasetString.group(
                                    1)
                            else:
                                indexSubdataset = -1
                        else:
                            #print "Error : no match of ", dataset, "$ in gdalinfo " + data
                            indexSubdataset = -1

                        if not indexSubdataset == -1:
                            indexSubdataset = int(indexSubdataset) - 1
                            newParam = "\'" + data + "?&sdataidx=" + str(
                                indexSubdataset) + "\'"

                        else:
                            newParam = inputParameter

                        newparams += newParam
                    # no hdf5
                    else:
                        newparams += inputParameter
                    newparams += ";"
                if newparams[-1] == ";":
                    newparams = newparams[:-1]
                param.value = newparams

            if param.value == None or param.value == "":
                continue
            if isinstance(param, ParameterVector):
                commands.append(param.name)
                if self.hasROI:
                    roiFile = getTempFilename('shp')
                    commands.append(roiFile)
                    self.roiVectors[param.value] = roiFile
                else:
                    commands.append("\"" + param.value + "\"")
            elif isinstance(param, ParameterRaster):
                commands.append(param.name)
                if self.hasROI:
                    roiFile = getTempFilename('tif')
                    commands.append(roiFile)
                    self.roiRasters[param.value] = roiFile
                else:
                    commands.append("\"" + param.value + "\"")
            elif isinstance(param, ParameterMultipleInput):
                commands.append(param.name)
                files = str(param.value).split(";")
                paramvalue = " ".join(["\"" + f + "\"" for f in files])
                commands.append(paramvalue)
            elif isinstance(param, ParameterSelection):
                commands.append(param.name)
                idx = int(param.value)
                commands.append(str(param.options[idx]))
            elif isinstance(param, ParameterBoolean):
                if param.value:
                    commands.append(param.name)
                    commands.append(str(param.value).lower())
            elif isinstance(param, ParameterExtent):
                self.roiValues = param.value.split(",")
            else:
                commands.append(param.name)
                commands.append(str(param.value))

        for out in self.outputs:
            commands.append(out.name)
            commands.append('"' + out.value + '"')
        for roiInput, roiFile in self.roiRasters.items():
            startX, startY = float(self.roiValues[0]), float(self.roiValues[1])
            sizeX = float(self.roiValues[2]) - startX
            sizeY = float(self.roiValues[3]) - startY
            helperCommands = [
                "otbcli_ExtractROI", "-in", roiInput, "-out", roiFile,
                "-startx",
                str(startX), "-starty",
                str(startY), "-sizex",
                str(sizeX), "-sizey",
                str(sizeY)
            ]
            ProcessingLog.addToLog(ProcessingLog.LOG_INFO, helperCommands)
            progress.setCommand(helperCommands)
            OTBUtils.executeOtb(helperCommands, progress)

        if self.roiRasters:
            supportRaster = self.roiRasters.itervalues().next()
            for roiInput, roiFile in self.roiVectors.items():
                helperCommands = [
                    "otbcli_VectorDataExtractROIApplication", "-vd.in",
                    roiInput, "-io.in", supportRaster, "-io.out", roiFile,
                    "-elev.dem.path",
                    OTBUtils.otbSRTMPath()
                ]
                ProcessingLog.addToLog(ProcessingLog.LOG_INFO, helperCommands)
                progress.setCommand(helperCommands)
                OTBUtils.executeOtb(helperCommands, progress)

        loglines = []
        loglines.append("OTB execution command")
        for line in commands:
            loglines.append(line)
            progress.setCommand(line)

        ProcessingLog.addToLog(ProcessingLog.LOG_INFO, loglines)
        import processing.algs.otb.OTBSpecific_XMLLoading
        module = processing.algs.otb.OTBSpecific_XMLLoading

        found = False
        if 'adapt%s' % self.appkey in dir(module):
            found = True
            commands = getattr(module, 'adapt%s' % self.appkey)(commands)
        else:
            the_key = 'adapt%s' % self.appkey
            if '-' in the_key:
                base_key = the_key.split("-")[0]
                if base_key in dir(module):
                    found = True
                    commands = getattr(module, base_key)(commands)

        if not found:
            ProcessingLog.addToLog(ProcessingLog.LOG_INFO,
                                   "Adapter for %s not found" % the_key)

        #frames = inspect.getouterframes(inspect.currentframe())[1:]
        #for a_frame in frames:
        #    frame,filename,line_number,function_name,lines,index = a_frame
        #    ProcessingLog.addToLog(ProcessingLog.LOG_INFO, "%s %s %s %s %s %s" % (frame,filename,line_number,function_name,lines,index))

        OTBUtils.executeOtb(commands, progress)
Exemple #8
0
    def processAlgorithm(self, progress):
        layer = self.getParameterValue(self.INPUT_LAYER)
        mapping = self.getParameterValue(self.FIELDS_MAPPING)
        output = self.getOutputFromName(self.OUTPUT_LAYER)

        layer = dataobjects.getObjectFromUri(layer)
        provider = layer.dataProvider()
        fields = []
        expressions = []
        for field_def in mapping:
            fields.append(QgsField(name=field_def['name'],
                                   type=field_def['type'],
                                   len=field_def['length'],
                                   prec=field_def['precision']))

            expression = QgsExpression(field_def['expression'])
            if expression.hasParserError():
                raise GeoAlgorithmExecutionException(
                    self.tr(u'Parser error in expression "{}": {}')
                    .format(unicode(field_def['expression']),
                            unicode(expression.parserErrorString())))
            expression.prepare(provider.fields())
            if expression.hasEvalError():
                raise GeoAlgorithmExecutionException(
                    self.tr(u'Evaluation error in expression "{}": {}')
                    .format(unicode(field_def['expression']),
                            unicode(expression.evalErrorString())))
            expressions.append(expression)

        writer = output.getVectorWriter(fields,
                                        provider.geometryType(),
                                        layer.crs())

        # Create output vector layer with new attributes
        error = ''
        calculationSuccess = True
        inFeat = QgsFeature()
        outFeat = QgsFeature()
        features = vector.features(layer)
        count = len(features)
        for current, inFeat in enumerate(features):
            rownum = current + 1

            outFeat.setGeometry(inFeat.geometry())

            attrs = []
            for i in xrange(0, len(mapping)):
                field_def = mapping[i]
                expression = expressions[i]
                expression.setCurrentRowNumber(rownum)
                value = expression.evaluate(inFeat)
                if expression.hasEvalError():
                    calculationSuccess = False
                    error = expression.evalErrorString()
                    break

                attrs.append(value)
            outFeat.setAttributes(attrs)

            writer.addFeature(outFeat)

            current += 1
            progress.setPercentage(100 * current / float(count))

        del writer

        if not calculationSuccess:
            raise GeoAlgorithmExecutionException(
                self.tr('An error occurred while evaluating the calculation'
                        ' string:\n') + error)
Exemple #9
0
        if primaryKeyField:
            uri.setDataSource(schema, table, geomColumn, '', primaryKeyField)
        else:
            uri.setDataSource(schema, table, geomColumn, '')

        (ret, errMsg) = QgsVectorLayerImport.importLayer(
            layer,
            uri.uri(),
            providerName,
            self.crs,
            False,
            False,
            options,
        )
        if ret != 0:
            raise GeoAlgorithmExecutionException(
                self.tr('Error importing to PostGIS\n%s' % errMsg))

        if geomColumn and createIndex:
            db.create_spatial_index(table, schema, geomColumn)

        db.vacuum_analyze(table, schema)

    def dbConnectionNames(self):
        settings = QSettings()
        settings.beginGroup('/PostgreSQL/connections/')
        return settings.childGroups()

    def defineCharacteristics(self):
        self.name = 'Import into PostGIS'
        self.group = 'Database'
        self.addParameter(
    def processAlgorithm(self, feedback):
        layer = dataobjects.getLayerFromString(
            self.getParameterValue(self.INPUT_LAYER))

        fields = layer.fields()
        fields.append(QgsField('node_pos', QVariant.Int))
        fields.append(QgsField('node_index', QVariant.Int))
        fields.append(QgsField('distance', QVariant.Double))
        fields.append(QgsField('angle', QVariant.Double))

        writer = self.getOutputFromName(
            self.OUTPUT_LAYER).getVectorWriter(
                fields,
                QgsWkbTypes.Point,
                layer.crs())

        node_indices_string = self.getParameterValue(self.NODES)
        indices = []
        for node in node_indices_string.split(','):
            try:
                indices.append(int(node))
            except:
                raise GeoAlgorithmExecutionException(
                    self.tr('\'{}\' is not a valid node index').format(node))

        features = vector.features(layer)
        total = 100.0 / len(features)

        for current, f in enumerate(features):

            input_geometry = f.geometry()
            if not input_geometry:
                writer.addFeature(f)
            else:
                total_nodes = input_geometry.geometry().nCoordinates()

                for node in indices:
                    if node < 0:
                        node_index = total_nodes + node
                    else:
                        node_index = node

                    if node_index < 0 or node_index >= total_nodes:
                        continue

                    distance = input_geometry.distanceToVertex(node_index)
                    angle = math.degrees(input_geometry.angleAtVertex(node_index))

                    output_feature = QgsFeature()
                    attrs = f.attributes()
                    attrs.append(node)
                    attrs.append(node_index)
                    attrs.append(distance)
                    attrs.append(angle)
                    output_feature.setAttributes(attrs)

                    point = input_geometry.vertexAt(node_index)
                    output_feature.setGeometry(QgsGeometry.fromPoint(point))

                    writer.addFeature(output_feature)

            feedback.setProgress(int(current * total))

        del writer
Exemple #11
0
 def _runSQL(sql):
     try:
         db._exec_sql_and_commit(str(sql))
     except spatialite.DbError as e:
         raise GeoAlgorithmExecutionException(
             'Error creating output Spatialite table:\n%s' % str(e))
Exemple #12
0
 def _runSQL(sql):
     try:
         db._exec_sql_and_commit(str(sql))
     except postgis.DbError as e:
         raise GeoAlgorithmExecutionException(
             'Error creating output PostGIS table:\n%s' % e.message)
Exemple #13
0
    def __init__(self, destination, encoding, fields, geometryType,
                 crs, options=None):
        self.destination = destination
        self.isNotFileBased = False
        self.layer = None
        self.writer = None

        if encoding is None:
            settings = QgsSettings()
            encoding = settings.value('/Processing/encoding', 'System', str)

        if self.destination.startswith(self.MEMORY_LAYER_PREFIX):
            self.isNotFileBased = True

            uri = QgsWkbTypes.displayString(geometryType) + "?uuid=" + str(uuid.uuid4())
            if crs.isValid():
                uri += '&crs=' + crs.authid()
            fieldsdesc = []
            for f in fields:
                qgsfield = _toQgsField(f)
                fieldsdesc.append('field=%s:%s' % (qgsfield.name(),
                                                   TYPE_MAP_MEMORY_LAYER.get(qgsfield.type(), "string")))
            if fieldsdesc:
                uri += '&' + '&'.join(fieldsdesc)

            self.layer = QgsVectorLayer(uri, self.destination, 'memory')
            self.writer = self.layer.dataProvider()
        elif self.destination.startswith(self.POSTGIS_LAYER_PREFIX):
            self.isNotFileBased = True
            uri = QgsDataSourceUri(self.destination[len(self.POSTGIS_LAYER_PREFIX):])
            connInfo = uri.connectionInfo()
            (success, user, passwd) = QgsCredentials.instance().get(connInfo, None, None)
            if success:
                QgsCredentials.instance().put(connInfo, user, passwd)
            else:
                raise GeoAlgorithmExecutionException("Couldn't connect to database")
            try:
                db = postgis.GeoDB(host=uri.host(), port=int(uri.port()),
                                   dbname=uri.database(), user=user, passwd=passwd)
            except postgis.DbError as e:
                raise GeoAlgorithmExecutionException(
                    "Couldn't connect to database:\n%s" % e.message)

            def _runSQL(sql):
                try:
                    db._exec_sql_and_commit(str(sql))
                except postgis.DbError as e:
                    raise GeoAlgorithmExecutionException(
                        'Error creating output PostGIS table:\n%s' % e.message)

            fields = [_toQgsField(f) for f in fields]
            fieldsdesc = ",".join('%s %s' % (f.name(),
                                             TYPE_MAP_POSTGIS_LAYER.get(f.type(), "VARCHAR"))
                                  for f in fields)

            _runSQL("CREATE TABLE %s.%s (%s)" % (uri.schema(), uri.table().lower(), fieldsdesc))
            if geometryType != QgsWkbTypes.NullGeometry:
                _runSQL("SELECT AddGeometryColumn('{schema}', '{table}', 'the_geom', {srid}, '{typmod}', 2)".format(
                    table=uri.table().lower(), schema=uri.schema(), srid=crs.authid().split(":")[-1],
                    typmod=QgsWkbTypes.displayString(geometryType).upper()))

            self.layer = QgsVectorLayer(uri.uri(), uri.table(), "postgres")
            self.writer = self.layer.dataProvider()
        elif self.destination.startswith(self.SPATIALITE_LAYER_PREFIX):
            self.isNotFileBased = True
            uri = QgsDataSourceUri(self.destination[len(self.SPATIALITE_LAYER_PREFIX):])
            try:
                db = spatialite.GeoDB(uri=uri)
            except spatialite.DbError as e:
                raise GeoAlgorithmExecutionException(
                    "Couldn't connect to database:\n%s" % e.message)

            def _runSQL(sql):
                try:
                    db._exec_sql_and_commit(str(sql))
                except spatialite.DbError as e:
                    raise GeoAlgorithmExecutionException(
                        'Error creating output Spatialite table:\n%s' % str(e))

            fields = [_toQgsField(f) for f in fields]
            fieldsdesc = ",".join('%s %s' % (f.name(),
                                             TYPE_MAP_SPATIALITE_LAYER.get(f.type(), "VARCHAR"))
                                  for f in fields)

            _runSQL("DROP TABLE IF EXISTS %s" % uri.table().lower())
            _runSQL("CREATE TABLE %s (%s)" % (uri.table().lower(), fieldsdesc))
            if geometryType != QgsWkbTypes.NullGeometry:
                _runSQL("SELECT AddGeometryColumn('{table}', 'the_geom', {srid}, '{typmod}', 2)".format(
                    table=uri.table().lower(), srid=crs.authid().split(":")[-1],
                    typmod=QgsWkbTypes.displayString(geometryType).upper()))

            self.layer = QgsVectorLayer(uri.uri(), uri.table(), "spatialite")
            self.writer = self.layer.dataProvider()
        else:
            formats = QgsVectorFileWriter.supportedFiltersAndFormats()
            OGRCodes = {}
            for (key, value) in list(formats.items()):
                extension = str(key)
                extension = extension[extension.find('*.') + 2:]
                extension = extension[:extension.find(' ')]
                OGRCodes[extension] = value
            OGRCodes['dbf'] = "DBF file"

            extension = self.destination[self.destination.rfind('.') + 1:]

            if extension not in OGRCodes:
                extension = 'shp'
                self.destination = self.destination + '.shp'

            if geometryType == QgsWkbTypes.NoGeometry:
                if extension == 'shp':
                    extension = 'dbf'
                    self.destination = self.destination[:self.destination.rfind('.')] + '.dbf'
                if extension not in self.nogeometry_extensions:
                    raise GeoAlgorithmExecutionException(
                        "Unsupported format for tables with no geometry")

            qgsfields = QgsFields()
            for field in fields:
                qgsfields.append(_toQgsField(field))

            # use default dataset/layer options
            dataset_options = QgsVectorFileWriter.defaultDatasetOptions(OGRCodes[extension])
            layer_options = QgsVectorFileWriter.defaultLayerOptions(OGRCodes[extension])

            self.writer = QgsVectorFileWriter(self.destination, encoding,
                                              qgsfields, geometryType, crs, OGRCodes[extension],
                                              dataset_options, layer_options)
Exemple #14
0
    def processAlgorithm(self, parameters, context, feedback):
        vlayerA = QgsProcessingUtils.mapLayerFromString(
            self.getParameterValue(self.INPUT), context)
        vlayerB = QgsProcessingUtils.mapLayerFromString(
            self.getParameterValue(self.INPUT2), context)

        geomType = QgsWkbTypes.multiType(vlayerA.wkbType())
        fields = vector.combineVectorFields(vlayerA, vlayerB)
        writer = self.getOutputFromName(self.OUTPUT).getVectorWriter(
            fields, geomType, vlayerA.crs(), context)
        outFeat = QgsFeature()
        index = QgsProcessingUtils.createSpatialIndex(vlayerB, context)
        selectionA = QgsProcessingUtils.getFeatures(vlayerA, context)
        total = 100.0 / vlayerA.featureCount() if vlayerA.featureCount() else 0
        for current, inFeatA in enumerate(selectionA):
            feedback.setProgress(int(current * total))
            geom = inFeatA.geometry()
            atMapA = inFeatA.attributes()
            intersects = index.intersects(geom.boundingBox())
            request = QgsFeatureRequest().setFilterFids(intersects)

            engine = None
            if len(intersects) > 0:
                # use prepared geometries for faster intersection tests
                engine = QgsGeometry.createGeometryEngine(geom.geometry())
                engine.prepareGeometry()

            for inFeatB in vlayerB.getFeatures(request):
                tmpGeom = inFeatB.geometry()
                if engine.intersects(tmpGeom.geometry()):
                    atMapB = inFeatB.attributes()
                    int_geom = QgsGeometry(geom.intersection(tmpGeom))
                    if int_geom.wkbType(
                    ) == QgsWkbTypes.Unknown or QgsWkbTypes.flatType(
                            int_geom.geometry().wkbType(
                            )) == QgsWkbTypes.GeometryCollection:
                        int_com = geom.combine(tmpGeom)
                        int_geom = QgsGeometry()
                        if int_com:
                            int_sym = geom.symDifference(tmpGeom)
                            int_geom = QgsGeometry(int_com.difference(int_sym))
                    if int_geom.isEmpty() or not int_geom.isGeosValid():
                        raise GeoAlgorithmExecutionException(
                            self.tr('GEOS geoprocessing error: One or '
                                    'more input features have invalid '
                                    'geometry.'))
                    try:
                        if int_geom.wkbType() in wkbTypeGroups[wkbTypeGroups[
                                int_geom.wkbType()]]:
                            outFeat.setGeometry(int_geom)
                            attrs = []
                            attrs.extend(atMapA)
                            attrs.extend(atMapB)
                            outFeat.setAttributes(attrs)
                            writer.addFeature(outFeat,
                                              QgsFeatureSink.FastInsert)
                    except:
                        raise GeoAlgorithmExecutionException(
                            self.tr('Feature geometry error: One or more '
                                    'output features ignored due to invalid '
                                    'geometry.'))

        del writer
Exemple #15
0
    def processAlgorithm(self, parameters, context, feedback):
        layer = QgsProcessingUtils.mapLayerFromString(self.getParameterValue(self.INPUT), context)

        buf = self.getParameterValue(self.BUFFER)

        writer = self.getOutputFromName(self.OUTPUT).getVectorWriter(layer.fields(), QgsWkbTypes.Polygon,
                                                                     layer.crs(), context)

        outFeat = QgsFeature()
        extent = layer.extent()
        extraX = extent.height() * (buf / 100.0)
        extraY = extent.width() * (buf / 100.0)
        height = extent.height()
        width = extent.width()
        c = voronoi.Context()
        pts = []
        ptDict = {}
        ptNdx = -1

        features = QgsProcessingUtils.getFeatures(layer, context)
        total = 100.0 / QgsProcessingUtils.featureCount(layer, context)
        for current, inFeat in enumerate(features):
            geom = inFeat.geometry()
            point = geom.asPoint()
            x = point.x() - extent.xMinimum()
            y = point.y() - extent.yMinimum()
            pts.append((x, y))
            ptNdx += 1
            ptDict[ptNdx] = inFeat.id()
            feedback.setProgress(int(current * total))

        if len(pts) < 3:
            raise GeoAlgorithmExecutionException(
                self.tr('Input file should contain at least 3 points. Choose '
                        'another file and try again.'))

        uniqueSet = set(item for item in pts)
        ids = [pts.index(item) for item in uniqueSet]
        sl = voronoi.SiteList([voronoi.Site(i[0], i[1], sitenum=j) for (j,
                                                                        i) in enumerate(uniqueSet)])
        voronoi.voronoi(sl, c)
        inFeat = QgsFeature()

        current = 0
        if len(c.polygons) == 0:
            raise GeoAlgorithmExecutionException(
                self.tr('There were no polygons created.'))

        total = 100.0 / len(c.polygons)

        for (site, edges) in list(c.polygons.items()):
            request = QgsFeatureRequest().setFilterFid(ptDict[ids[site]])
            inFeat = next(layer.getFeatures(request))
            lines = self.clip_voronoi(edges, c, width, height, extent, extraX, extraY)

            geom = QgsGeometry.fromMultiPoint(lines)
            geom = QgsGeometry(geom.convexHull())
            outFeat.setGeometry(geom)
            outFeat.setAttributes(inFeat.attributes())
            writer.addFeature(outFeat)

            current += 1
            feedback.setProgress(int(current * total))

        del writer
    def processAlgorithm(self, parameters, context, feedback):
        inLayer = QgsProcessingUtils.mapLayerFromString(
            self.getParameterValue(self.INPUT), context)
        boundary = self.getParameterValue(self.MODE) == self.MODE_BOUNDARY
        smallestArea = self.getParameterValue(
            self.MODE) == self.MODE_SMALLEST_AREA

        if inLayer.selectedFeatureCount() == 0:
            QgsMessageLog.logMessage(
                self.tr('{0}: (No selection in input layer "{1}")').format(
                    self.displayName(), self.getParameterValue(self.INPUT)),
                self.tr('Processing'), QgsMessageLog.WARNING)

        featToEliminate = []
        selFeatIds = inLayer.selectedFeatureIds()
        output = self.getOutputFromName(self.OUTPUT)
        writer = output.getVectorWriter(inLayer.fields(), inLayer.wkbType(),
                                        inLayer.crs(), context)

        for aFeat in inLayer.getFeatures():
            if aFeat.id() in selFeatIds:
                # Keep references to the features to eliminate
                featToEliminate.append(aFeat)
            else:
                # write the others to output
                writer.addFeature(aFeat, QgsFeatureSink.FastInsert)

        # Delete all features to eliminate in processLayer
        processLayer = output.layer
        processLayer.startEditing()

        # ANALYZE
        if len(featToEliminate) > 0:  # Prevent zero division
            start = 20.00
            add = 80.00 / len(featToEliminate)
        else:
            start = 100

        feedback.setProgress(start)
        madeProgress = True

        # We go through the list and see if we find any polygons we can
        # merge the selected with. If we have no success with some we
        # merge and then restart the whole story.
        while madeProgress:  # Check if we made any progress
            madeProgress = False
            featNotEliminated = []

            # Iterate over the polygons to eliminate
            for i in range(len(featToEliminate)):
                feat = featToEliminate.pop()
                geom2Eliminate = feat.geometry()
                bbox = geom2Eliminate.boundingBox()
                fit = processLayer.getFeatures(
                    QgsFeatureRequest().setFilterRect(
                        bbox).setSubsetOfAttributes([]))
                mergeWithFid = None
                mergeWithGeom = None
                max = 0
                min = -1
                selFeat = QgsFeature()

                # use prepared geometries for faster intersection tests
                engine = QgsGeometry.createGeometryEngine(
                    geom2Eliminate.geometry())
                engine.prepareGeometry()

                while fit.nextFeature(selFeat):
                    selGeom = selFeat.geometry()

                    if engine.intersects(selGeom.geometry()):
                        # We have a candidate
                        iGeom = geom2Eliminate.intersection(selGeom)

                        if not iGeom:
                            continue

                        if boundary:
                            selValue = iGeom.length()
                        else:
                            # area. We need a common boundary in
                            # order to merge
                            if 0 < iGeom.length():
                                selValue = selGeom.area()
                            else:
                                selValue = -1

                        if -1 != selValue:
                            useThis = True

                            if smallestArea:
                                if -1 == min:
                                    min = selValue
                                else:
                                    if selValue < min:
                                        min = selValue
                                    else:
                                        useThis = False
                            else:
                                if selValue > max:
                                    max = selValue
                                else:
                                    useThis = False

                            if useThis:
                                mergeWithFid = selFeat.id()
                                mergeWithGeom = QgsGeometry(selGeom)
                # End while fit

                if mergeWithFid is not None:
                    # A successful candidate
                    newGeom = mergeWithGeom.combine(geom2Eliminate)

                    if processLayer.changeGeometry(mergeWithFid, newGeom):
                        madeProgress = True
                    else:
                        raise GeoAlgorithmExecutionException(
                            self.
                            tr('Could not replace geometry of feature with id {0}'
                               ).format(mergeWithFid))

                    start = start + add
                    feedback.setProgress(start)
                else:
                    featNotEliminated.append(feat)

            # End for featToEliminate

            featToEliminate = featNotEliminated

        # End while
        if not processLayer.commitChanges():
            raise GeoAlgorithmExecutionException(
                self.tr('Could not commit changes'))

        for feature in featNotEliminated:
            writer.addFeature(feature, QgsFeatureSink.FastInsert)
Exemple #17
0
    def processAlgorithm(self, context, feedback):
        layer = QgsProcessingUtils.mapLayerFromString(
            self.getParameterValue(self.INPUT_VECTOR), context)
        startPoint = self.getParameterValue(self.START_POINT)
        endPoint = self.getParameterValue(self.END_POINT)
        strategy = self.getParameterValue(self.STRATEGY)

        directionFieldName = self.getParameterValue(self.DIRECTION_FIELD)
        forwardValue = self.getParameterValue(self.VALUE_FORWARD)
        backwardValue = self.getParameterValue(self.VALUE_BACKWARD)
        bothValue = self.getParameterValue(self.VALUE_BOTH)
        defaultDirection = self.getParameterValue(self.DEFAULT_DIRECTION)
        bothValue = self.getParameterValue(self.VALUE_BOTH)
        defaultDirection = self.getParameterValue(self.DEFAULT_DIRECTION)
        speedFieldName = self.getParameterValue(self.SPEED_FIELD)
        defaultSpeed = self.getParameterValue(self.DEFAULT_SPEED)
        tolerance = self.getParameterValue(self.TOLERANCE)

        fields = QgsFields()
        fields.append(QgsField('start', QVariant.String, '', 254, 0))
        fields.append(QgsField('end', QVariant.String, '', 254, 0))
        fields.append(QgsField('cost', QVariant.Double, '', 20, 7))

        writer = self.getOutputFromName(self.OUTPUT_LAYER).getVectorWriter(
            fields, QgsWkbTypes.LineString, layer.crs(), context)

        tmp = startPoint.split(',')
        startPoint = QgsPoint(float(tmp[0]), float(tmp[1]))
        tmp = endPoint.split(',')
        endPoint = QgsPoint(float(tmp[0]), float(tmp[1]))

        directionField = -1
        if directionFieldName is not None:
            directionField = layer.fields().lookupField(directionFieldName)
        speedField = -1
        if speedFieldName is not None:
            speedField = layer.fields().lookupField(speedFieldName)

        director = QgsVectorLayerDirector(layer, directionField, forwardValue,
                                          backwardValue, bothValue,
                                          defaultDirection)

        distUnit = iface.mapCanvas().mapSettings().destinationCrs().mapUnits()
        multiplier = QgsUnitTypes.fromUnitToUnitFactor(
            distUnit, QgsUnitTypes.DistanceMeters)
        if strategy == 0:
            strategy = QgsNetworkDistanceStrategy()
        else:
            strategy = QgsNetworkSpeedStrategy(speedField, defaultSpeed,
                                               multiplier * 1000.0 / 3600.0)
            multiplier = 3600

        director.addStrategy(strategy)
        builder = QgsGraphBuilder(
            iface.mapCanvas().mapSettings().destinationCrs(), True, tolerance)
        feedback.pushInfo(self.tr('Building graph...'))
        snappedPoints = director.makeGraph(builder, [startPoint, endPoint])

        feedback.pushInfo(self.tr('Calculating shortest path...'))
        graph = builder.graph()
        idxStart = graph.findVertex(snappedPoints[0])
        idxEnd = graph.findVertex(snappedPoints[1])

        tree, cost = QgsGraphAnalyzer.dijkstra(graph, idxStart, 0)
        if tree[idxEnd] == -1:
            raise GeoAlgorithmExecutionException(
                self.tr('There is no route from start point to end point.'))

        route = []
        cost = 0.0
        current = idxEnd
        while current != idxStart:
            cost += graph.edge(tree[current]).cost(0)
            route.append(
                graph.vertex(graph.edge(tree[current]).inVertex()).point())
            current = graph.edge(tree[current]).outVertex()

        route.append(snappedPoints[0])
        route.reverse()

        self.setOutputValue(self.TRAVEL_COST, cost / multiplier)

        feedback.pushInfo(self.tr('Writing results...'))
        geom = QgsGeometry.fromPolyline(route)
        feat = QgsFeature()
        feat.setFields(fields)
        feat['start'] = startPoint.toString()
        feat['end'] = endPoint.toString()
        feat['cost'] = cost / multiplier
        feat.setGeometry(geom)
        writer.addFeature(feat)
        del writer
Exemple #18
0
    def processAlgorithm(self, feedback):
        layer = dataobjects.getLayerFromString(self.getParameterValue(self.POINTS))
        weightField = self.getParameterValue(self.WEIGHT)
        uniqueField = self.getParameterValue(self.UID)

        if weightField is None:
            weightIndex = -1
        else:
            weightIndex = layer.fields().lookupField(weightField)

        if uniqueField is None:
            uniqueIndex = -1
        else:
            uniqueIndex = layer.fields().lookupField(uniqueField)

        fieldList = [QgsField('MEAN_X', QVariant.Double, '', 24, 15),
                     QgsField('MEAN_Y', QVariant.Double, '', 24, 15),
                     QgsField('UID', QVariant.String, '', 255)]

        writer = self.getOutputFromName(self.OUTPUT).getVectorWriter(
            fieldList, QgsWkbTypes.Point, layer.crs()
        )

        features = vector.features(layer)
        total = 100.0 / len(features)
        means = {}
        for current, feat in enumerate(features):
            feedback.setProgress(int(current * total))
            if uniqueIndex == -1:
                clazz = "Single class"
            else:
                clazz = str(feat.attributes()[uniqueIndex]).strip()
            if weightIndex == -1:
                weight = 1.00
            else:
                try:
                    weight = float(feat.attributes()[weightIndex])
                except:
                    weight = 1.00

            if weight < 0:
                raise GeoAlgorithmExecutionException(self.tr('Negative weight value found. Please fix your data and try again.'))

            if clazz not in means:
                means[clazz] = (0, 0, 0)

            (cx, cy, totalweight) = means[clazz]
            geom = QgsGeometry(feat.geometry())
            geom = vector.extractPoints(geom)
            for i in geom:
                cx += i.x() * weight
                cy += i.y() * weight
                totalweight += weight
            means[clazz] = (cx, cy, totalweight)

        current = 0
        total = 100.0 / len(means)
        for (clazz, values) in list(means.items()):
            outFeat = QgsFeature()
            cx = values[0] / values[2]
            cy = values[1] / values[2]
            meanPoint = QgsPoint(cx, cy)

            outFeat.setGeometry(QgsGeometry.fromPoint(meanPoint))
            outFeat.setAttributes([cx, cy, clazz])
            writer.addFeature(outFeat)
            current += 1
            feedback.setProgress(int(current * total))

        del writer
Exemple #19
0
    def processAlgorithm(self, parameters, context, feedback):
        layer = QgsProcessingUtils.mapLayerFromString(self.getParameterValue(self.INPUT), context)

        fields = QgsFields()
        fields.append(QgsField('POINTA', QVariant.Double, '', 24, 15))
        fields.append(QgsField('POINTB', QVariant.Double, '', 24, 15))
        fields.append(QgsField('POINTC', QVariant.Double, '', 24, 15))

        writer = self.getOutputFromName(self.OUTPUT).getVectorWriter(fields, QgsWkbTypes.Polygon, layer.crs(), context)

        pts = []
        ptDict = {}
        ptNdx = -1
        c = voronoi.Context()
        features = QgsProcessingUtils.getFeatures(layer, context)
        total = 100.0 / layer.featureCount() if layer.featureCount() else 0
        for current, inFeat in enumerate(features):
            geom = QgsGeometry(inFeat.geometry())
            if geom.isNull():
                continue
            if geom.isMultipart():
                points = geom.asMultiPoint()
            else:
                points = [geom.asPoint()]
            for n, point in enumerate(points):
                x = point.x()
                y = point.y()
                pts.append((x, y))
                ptNdx += 1
                ptDict[ptNdx] = (inFeat.id(), n)
            feedback.setProgress(int(current * total))

        if len(pts) < 3:
            raise GeoAlgorithmExecutionException(
                self.tr('Input file should contain at least 3 points. Choose '
                        'another file and try again.'))

        uniqueSet = set(item for item in pts)
        ids = [pts.index(item) for item in uniqueSet]
        sl = voronoi.SiteList([voronoi.Site(*i) for i in uniqueSet])
        c.triangulate = True
        voronoi.voronoi(sl, c)
        triangles = c.triangles
        feat = QgsFeature()

        total = 100.0 / len(triangles) if triangles else 1
        for current, triangle in enumerate(triangles):
            indices = list(triangle)
            indices.append(indices[0])
            polygon = []
            attrs = []
            step = 0
            for index in indices:
                fid, n = ptDict[ids[index]]
                request = QgsFeatureRequest().setFilterFid(fid)
                inFeat = next(layer.getFeatures(request))
                geom = QgsGeometry(inFeat.geometry())
                if geom.isMultipart():
                    point = QgsPointXY(geom.asMultiPoint()[n])
                else:
                    point = QgsPointXY(geom.asPoint())
                polygon.append(point)
                if step <= 3:
                    attrs.append(ids[index])
                step += 1
            feat.setAttributes(attrs)
            geometry = QgsGeometry().fromPolygon([polygon])
            feat.setGeometry(geometry)
            writer.addFeature(feat, QgsFeatureSink.FastInsert)
            feedback.setProgress(int(current * total))

        del writer
Exemple #20
0
    def processAlgorithm(self, feedback):
        layer = dataobjects.getLayerFromString(self.getParameterValue(self.INPUT_LAYER))
        fieldName = self.getParameterValue(self.FIELD_NAME)
        fieldType = self.TYPES[self.getParameterValue(self.FIELD_TYPE)]
        width = self.getParameterValue(self.FIELD_LENGTH)
        precision = self.getParameterValue(self.FIELD_PRECISION)
        newField = self.getParameterValue(self.NEW_FIELD)
        formula = self.getParameterValue(self.FORMULA)

        output = self.getOutputFromName(self.OUTPUT_LAYER)

        fields = layer.fields()
        if newField:
            fields.append(QgsField(fieldName, fieldType, '', width, precision))

        writer = output.getVectorWriter(fields, layer.wkbType(),
                                        layer.crs())

        exp = QgsExpression(formula)

        da = QgsDistanceArea()
        da.setSourceCrs(layer.crs())
        da.setEllipsoidalMode(True)
        da.setEllipsoid(QgsProject.instance().ellipsoid())
        exp.setGeomCalculator(da)
        exp.setDistanceUnits(QgsProject.instance().distanceUnits())
        exp.setAreaUnits(QgsProject.instance().areaUnits())

        exp_context = QgsExpressionContext(QgsExpressionContextUtils.globalProjectLayerScopes(layer))

        if not exp.prepare(exp_context):
            raise GeoAlgorithmExecutionException(
                self.tr('Evaluation error: {0}').format(exp.evalErrorString()))

        outFeature = QgsFeature()
        outFeature.initAttributes(len(fields))
        outFeature.setFields(fields)

        error = ''
        calculationSuccess = True

        features = vector.features(layer)
        total = 100.0 / len(features)

        rownum = 1
        for current, f in enumerate(features):
            rownum = current + 1
            exp_context.setFeature(f)
            exp_context.lastScope().setVariable("row_number", rownum)
            value = exp.evaluate(exp_context)
            if exp.hasEvalError():
                calculationSuccess = False
                error = exp.evalErrorString()
                break
            else:
                outFeature.setGeometry(f.geometry())
                for fld in f.fields():
                    outFeature[fld.name()] = f[fld.name()]
                outFeature[fieldName] = value
                writer.addFeature(outFeature)

            feedback.setProgress(int(current * total))
        del writer

        if not calculationSuccess:
            raise GeoAlgorithmExecutionException(
                self.tr('An error occurred while evaluating the calculation '
                        'string:\n{0}').format(error))
Exemple #21
0
    def processAlgorithm(self, context, feedback):
        if system.isWindows():
            path = Grass7Utils.grassPath()
            if path == '':
                raise GeoAlgorithmExecutionException(
                    self.tr(
                        'GRASS GIS 7 folder is not configured. Please '
                        'configure it before running GRASS GIS 7 algorithms.'))

        # Create brand new commands lists
        self.commands = []
        self.outputCommands = []
        self.exportedLayers = {}

        # If GRASS session has been created outside of this algorithm then
        # get the list of layers loaded in GRASS otherwise start a new
        # session
        existingSession = Grass7Utils.sessionRunning
        if existingSession:
            self.exportedLayers = Grass7Utils.getSessionLayers()
        else:
            Grass7Utils.startGrass7Session()

        # Handle ext functions for inputs/command/outputs
        if self.module:
            if hasattr(self.module, 'processInputs'):
                func = getattr(self.module, 'processInputs')
                func(self)
            else:
                self.processInputs()

            if hasattr(self.module, 'processCommand'):
                func = getattr(self.module, 'processCommand')
                func(self)
            else:
                self.processCommand()

            if hasattr(self.module, 'processOutputs'):
                func = getattr(self.module, 'processOutputs')
                func(self)
            else:
                self.processOutputs()
        else:
            self.processInputs()
            self.processCommand()
            self.processOutputs()

        # Run GRASS
        loglines = []
        loglines.append(self.tr('GRASS GIS 7 execution commands'))
        for line in self.commands:
            feedback.pushCommandInfo(line)
            loglines.append(line)
        if ProcessingConfig.getSetting(Grass7Utils.GRASS_LOG_COMMANDS):
            QgsMessageLog.logMessage("\n".join(loglines),
                                     self.tr('Processing'), QgsMessageLog.INFO)

        Grass7Utils.executeGrass7(self.commands, feedback, self.outputCommands)

        for out in self.outputs:
            if isinstance(out, OutputHTML):
                with open(self.getOutputFromName("rawoutput").value) as f:
                    rawOutput = "".join(f.readlines())
                with open(out.value, "w") as f:
                    f.write("<pre>%s</pre>" % rawOutput)

        # If the session has been created outside of this algorithm, add
        # the new GRASS GIS 7 layers to it otherwise finish the session
        if existingSession:
            Grass7Utils.addSessionLayers(self.exportedLayers)
        else:
            Grass7Utils.endGrass7Session()
Exemple #22
0
    def processAlgorithm(self, parameters, context, feedback):
        database = self.parameterAsVectorLayer(parameters, self.DATABASE,
                                               context)
        databaseuri = database.dataProvider().dataSourceUri()
        uri = QgsDataSourceUri(databaseuri)
        if uri.database() is '':
            if '|layerid' in databaseuri:
                databaseuri = databaseuri[:databaseuri.find('|layerid')]
            uri = QgsDataSourceUri('dbname=\'%s\'' % (databaseuri))
        db = spatialite.GeoDB(uri)

        overwrite = self.parameterAsBool(parameters, self.OVERWRITE, context)
        createIndex = self.parameterAsBool(parameters, self.CREATEINDEX,
                                           context)
        convertLowerCase = self.parameterAsBool(parameters,
                                                self.LOWERCASE_NAMES, context)
        dropStringLength = self.parameterAsBool(parameters,
                                                self.DROP_STRING_LENGTH,
                                                context)
        forceSinglePart = self.parameterAsBool(parameters,
                                               self.FORCE_SINGLEPART, context)
        primaryKeyField = self.parameterAsString(parameters, self.PRIMARY_KEY,
                                                 context) or 'id'
        encoding = self.parameterAsString(parameters, self.ENCODING, context)

        source = self.parameterAsSource(parameters, self.INPUT, context)

        table = self.parameterAsString(parameters, self.TABLENAME, context)
        if table:
            table.strip()
        if not table or table == '':
            table = source.sourceName()
            table = table.replace('.', '_')
        table = table.replace(' ', '').lower()
        providerName = 'spatialite'

        geomColumn = self.parameterAsString(parameters, self.GEOMETRY_COLUMN,
                                            context)
        if not geomColumn:
            geomColumn = 'geom'

        options = {}
        if overwrite:
            options['overwrite'] = True
        if convertLowerCase:
            options['lowercaseFieldNames'] = True
            geomColumn = geomColumn.lower()
        if dropStringLength:
            options['dropStringConstraints'] = True
        if forceSinglePart:
            options['forceSinglePartGeometryType'] = True

        # Clear geometry column for non-geometry tables
        if source.wkbType() == QgsWkbTypes.NoGeometry:
            geomColumn = None

        uri = db.uri
        uri.setDataSource('', table, geomColumn, '', primaryKeyField)

        if encoding:
            options['fileEncoding'] = encoding

        exporter = QgsVectorLayerExporter(uri.uri(), providerName,
                                          source.fields(), source.wkbType(),
                                          source.sourceCrs(), overwrite,
                                          options)

        if exporter.errorCode() != QgsVectorLayerExporter.NoError:
            raise GeoAlgorithmExecutionException(
                self.tr('Error importing to Spatialite\n{0}').format(
                    exporter.errorMessage()))

        features = source.getFeatures()
        total = 100.0 / source.featureCount() if source.featureCount() else 0
        for current, f in enumerate(features):
            if feedback.isCanceled():
                break

            if not exporter.addFeature(f, QgsFeatureSink.FastInsert):
                feedback.reportError(exporter.errorMessage())

            feedback.setProgress(int(current * total))

        exporter.flushBuffer()
        if exporter.errorCode() != QgsVectorLayerExporter.NoError:
            raise GeoAlgorithmExecutionException(
                self.tr('Error importing to Spatialite\n{0}').format(
                    exporter.errorMessage()))

        if geomColumn and createIndex:
            db.create_spatial_index(table, geomColumn)

        return {}
Exemple #23
0
    def processAlgorithm(self, progress):
        # Do GFS processing here
        progress.setConsoleInfo("Reached first function")
        for var in ['APCP', 'TMAX', 'TMIN']:
            # Set destination folder and level
            if var == 'APCP':
                progress.setConsoleInfo(
                    "Downloading GFS precipitation data...")
                progress.setPercentage(0)
                dst_folder = self.getParameterValue(
                    GetGfsClimateDataDaily.PCP_DST_FOLDER)
                level = 'surface'
            elif var == 'TMAX':
                progress.setConsoleInfo(
                    "Downloading GFS maximum temperature data...")
                progress.setPercentage(0)
                dst_folder = self.getParameterValue(
                    GetGfsClimateDataDaily.TMAX_DST_FOLDER)
                level = '2_m_above_ground'
            elif var == 'TMIN':
                progress.setConsoleInfo(
                    "Downloading GFS minimum temperature data...")
                progress.setPercentage(0)
                dst_folder = self.getParameterValue(
                    GetGfsClimateDataDaily.TMIN_DST_FOLDER)
                level = '2_m_above_ground'

            # Setting coordinates
            left_long = math.floor(
                self.getParameterValue(GetGfsClimateDataDaily.LEFT_LONG))
            right_long = math.ceil(
                self.getParameterValue(GetGfsClimateDataDaily.RIGHT_LONG))
            top_lat = math.ceil(
                self.getParameterValue(GetGfsClimateDataDaily.TOP_LAT))
            bottom_lat = math.ceil(
                self.getParameterValue(GetGfsClimateDataDaily.BOTTOM_LAT))

            if (left_long >= right_long) or (bottom_lat >= top_lat):
                raise GeoAlgorithmExecutionException('Error in coordinates: \"Left :' + str(left_long) + \
                '< Right: ' + str(right_long) + ', Top :' + str(top_lat) + '> Bottom :' + str(bottom_lat) + '\"')

            if os.path.isdir(dst_folder):
                # Create and set Forecast folder
                forecast_folder = dst_folder + os.sep + 'Forecasts'
                if not os.path.isdir(forecast_folder):
                    os.mkdir(forecast_folder)

                # Creating log file
                log_file = open(dst_folder + os.sep + "Download_log.txt", "w")
                # Write current date to log file
                now = date.today()
                log_file.write(self.name + ' run: ' + now.strftime('%Y%m%d') +
                               '\n')
                log_file.write('Data source: NOAA-GFS\n')

                # Finding newest file date and move old forecasted files to forecast folder
                dates = []
                dirs = os.listdir(dst_folder + os.sep + 'Temporary')
                for f in dirs:
                    if (os.path.isfile(os.path.join(dst_folder, f))):
                        if (var + '.tif') in f:
                            dates.append(
                                date(int(f[0:4]), int(f[4:6]), int(f[6:8])))

                # Newest file date +1 or today-60days (if no files) as start date
                if dates == []:
                    first_date = date(2015, 01, 01)
                else:
                    first_date = max(dates) + timedelta(days=1)
                log_file.write(var + ' downloading start date: ' +
                               first_date.strftime('%Y%m%d') + '\n')

                # Downloading data
                forecast_date = GfsForecastImport(first_date, var, level,
                                                  dst_folder, left_long,
                                                  right_long, top_lat,
                                                  bottom_lat, log_file,
                                                  progress)
                log_file.write('Forecast date ' + var + ': ' +
                               forecast_date.strftime('%Y%m%d') + '\n')

                log_file.close()
Exemple #24
0
    def processAlgorithm(self, parameters, context, feedback):
        input_layers = self.parameterAsLayerList(parameters, self.LAYERS, context)

        layers = []
        fields = QgsFields()
        totalFeatureCount = 0
        for layer in input_layers:
            if layer.type() != QgsMapLayer.VectorLayer:
                raise GeoAlgorithmExecutionException(
                    self.tr('All layers must be vector layers!'))

            if (len(layers) > 0):
                if (layer.wkbType() != layers[0].wkbType()):
                    raise GeoAlgorithmExecutionException(
                        self.tr('All layers must have same geometry type!'))

            layers.append(layer)
            totalFeatureCount += layer.featureCount()

            for sindex, sfield in enumerate(layer.fields()):
                found = None
                for dfield in fields:
                    if (dfield.name().upper() == sfield.name().upper()):
                        found = dfield
                        if (dfield.type() != sfield.type()):
                            raise GeoAlgorithmExecutionException(
                                self.tr('{} field in layer {} has different '
                                        'data type than in other layers.'.format(sfield.name(), layerSource)))

                if not found:
                    fields.append(sfield)

        total = 100.0 / totalFeatureCount
        dest_crs = layers[0].crs()
        (sink, dest_id) = self.parameterAsSink(parameters, self.OUTPUT, context,
                                               fields, layers[0].wkbType(), dest_crs)

        featureCount = 0
        for layer in layers:
            for feature in layer.getFeatures(QgsFeatureRequest().setDestinationCrs(dest_crs)):
                if feedback.isCanceled():
                    break

                sattributes = feature.attributes()
                dattributes = []
                for dindex, dfield in enumerate(fields):
                    if (dfield.type() == QVariant.Int, QVariant.UInt, QVariant.LongLong, QVariant.ULongLong):
                        dattribute = 0
                    elif (dfield.type() == QVariant.Double):
                        dattribute = 0.0
                    else:
                        dattribute = ''

                    for sindex, sfield in enumerate(layer.fields()):
                        if (sfield.name().upper() == dfield.name().upper()):
                            if (sfield.type() != dfield.type()):
                                raise GeoAlgorithmExecutionException(
                                    self.tr('Attribute type mismatch'))
                            dattribute = sattributes[sindex]
                            break

                    dattributes.append(dattribute)

                feature.setAttributes(dattributes)
                sink.addFeature(feature)
                featureCount += 1
                feedback.setProgress(int(featureCount * total))

        return {self.OUTPUT: dest_id}
Exemple #25
0
    def processAlgorithm(self, parameters, context, feedback):
        layers = self.getParameterValue(self.INPUT_DATASOURCES)
        query = self.getParameterValue(self.INPUT_QUERY)
        uid_field = self.getParameterValue(self.INPUT_UID_FIELD)
        geometry_field = self.getParameterValue(self.INPUT_GEOMETRY_FIELD)
        geometry_type = self.getParameterValue(self.INPUT_GEOMETRY_TYPE)
        geometry_crs = self.getParameterValue(self.INPUT_GEOMETRY_CRS)

        df = QgsVirtualLayerDefinition()
        layerIdx = 1
        if layers:
            for layerSource in layers.split(';'):
                layer = QgsProcessingUtils.mapLayerFromString(
                    layerSource, context)
                if layer:
                    df.addSource('input{}'.format(layerIdx), layer.id())
                layerIdx += 1

        if query == '':
            raise GeoAlgorithmExecutionException(
                self.
                tr('Empty SQL. Please enter valid SQL expression and try again.'
                   ))
        else:
            df.setQuery(query)

        if uid_field:
            df.setUid(uid_field)

        if geometry_type == 1:  # no geometry
            df.setGeometryWkbType(QgsWkbTypes.NullGeometry)
        else:
            if geometry_field:
                df.setGeometryField(geometry_field)
            if geometry_type > 1:
                df.setGeometryWkbType(geometry_type - 1)
            if geometry_crs:
                crs = QgsCoordinateReferenceSystem(geometry_crs)
                if crs.isValid():
                    df.setGeometrySrid(crs.postgisSrid())

        vLayer = QgsVectorLayer(df.toString(), "temp_vlayer", "virtual")
        if not vLayer.isValid():
            raise GeoAlgorithmExecutionException(
                vLayer.dataProvider().error().message())

        writer = self.getOutputFromName(self.OUTPUT_LAYER).getVectorWriter(
            vLayer.fields(),
            vLayer.wkbType() if geometry_type != 1 else 1, vLayer.crs(),
            context)

        features = QgsProcessingUtils.getFeatures(vLayer, context)
        total = 100.0 / QgsProcessingUtils.featureCount(vLayer, context)
        outFeat = QgsFeature()
        for current, inFeat in enumerate(features):
            outFeat.setAttributes(inFeat.attributes())
            if geometry_type != 1:
                outFeat.setGeometry(inFeat.geometry())
            writer.addFeature(outFeat)
            feedback.setProgress(int(current * total))
        del writer
Exemple #26
0
    def processAlgorithm(self, parameters, context, feedback):
        commands = list()
        self.exportedLayers = {}

        self.preProcessInputs()

        # 1: Export rasters to sgrd and vectors to shp
        # Tables must be in dbf format. We check that.
        for param in self.parameterDefinitions():
            if isinstance(param, ParameterRaster):
                if param.name(
                ) not in parameters or parameters[param.name()] is None:
                    continue
                if parameters[param.name()].endswith('sdat'):
                    parameters[
                        param.name()] = parameters[param.name()][:-4] + "sgrd"
                elif not parameters[param.name()].endswith('sgrd'):
                    exportCommand = self.exportRasterLayer(
                        parameters[param.name()])
                    if exportCommand is not None:
                        commands.append(exportCommand)
            if isinstance(param, ParameterVector):
                if param.name(
                ) not in parameters or parameters[param.name()] is None:
                    continue
                layer = QgsProcessingUtils.mapLayerFromString(
                    parameters[param.name()], context, False)
                if layer:
                    filename = dataobjects.exportVectorLayer(layer)
                    self.exportedLayers[param.value] = filename
                elif not parameteres[param.name()].endswith('shp'):
                    raise GeoAlgorithmExecutionException(
                        self.tr('Unsupported file format'))
            if isinstance(param, ParameterTable):
                if param.name(
                ) not in parameters or parameters[param.name()] is None:
                    continue
                table = QgsProcessingUtils.mapLayerFromString(
                    parameters[param.name()], context, False)
                if table:
                    filename = dataobjects.exportTable(table)
                    self.exportedLayers[parameters[param.name()]] = filename
                elif not parameters[param.name()].endswith('shp'):
                    raise GeoAlgorithmExecutionException(
                        self.tr('Unsupported file format'))
            if isinstance(param, ParameterMultipleInput):
                if param.name(
                ) not in parameters or parameters[param.name()] is None:
                    continue
                layers = param.value.split(';')
                if layers is None or len(layers) == 0:
                    continue
                if param.datatype == ParameterMultipleInput.TYPE_RASTER:
                    for i, layerfile in enumerate(layers):
                        if layerfile.endswith('sdat'):
                            layerfile = param.value[:-4] + "sgrd"
                            layers[i] = layerfile
                        elif not layerfile.endswith('sgrd'):
                            exportCommand = self.exportRasterLayer(layerfile)
                            if exportCommand is not None:
                                commands.append(exportCommand)
                        param.value = ";".join(layers)
                elif param.datatype in [
                        dataobjects.TYPE_VECTOR_ANY,
                        dataobjects.TYPE_VECTOR_LINE,
                        dataobjects.TYPE_VECTOR_POLYGON,
                        dataobjects.TYPE_VECTOR_POINT
                ]:
                    for layerfile in layers:
                        layer = QgsProcessingUtils.mapLayerFromString(
                            layerfile, context, False)
                        if layer:
                            filename = dataobjects.exportVectorLayer(layer)
                            self.exportedLayers[layerfile] = filename
                        elif not layerfile.endswith('shp'):
                            raise GeoAlgorithmExecutionException(
                                self.tr('Unsupported file format'))

        # TODO - set minimum extent
        if not extent:
            extent = QgsProcessingUtils.combineLayerExtents([layer])

        # 2: Set parameters and outputs
        command = self.undecoratedGroup + ' "' + self.cmdname + '"'
        command += ' ' + ' '.join(self.hardcodedStrings)

        for param in self.parameterDefinitions():
            if not param.name() in parameters or parameters[
                    param.name()] is None:
                continue
            if isinstance(param,
                          (ParameterRaster, ParameterVector, ParameterTable)):
                value = parameters[param.name()]
                if value in list(self.exportedLayers.keys()):
                    command += ' -' + param.name() + ' "' \
                        + self.exportedLayers[value] + '"'
                else:
                    command += ' -' + param.name() + ' "' + value + '"'
            elif isinstance(param, ParameterMultipleInput):
                s = parameters[param.name()]
                for layer in list(self.exportedLayers.keys()):
                    s = s.replace(layer, self.exportedLayers[layer])
                command += ' -' + param.name() + ' "' + s + '"'
            elif isinstance(param, ParameterBoolean):
                if parameters[param.name()]:
                    command += ' -' + param.name().strip() + " true"
                else:
                    command += ' -' + param.name().strip() + " false"
            elif isinstance(param, ParameterFixedTable):
                tempTableFile = getTempFilename('txt')
                with open(tempTableFile, 'w') as f:
                    f.write('\t'.join([col for col in param.cols]) + '\n')
                    values = parameters[param.name()].split(',')
                    for i in range(0, len(values), 3):
                        s = values[i] + '\t' + values[i + 1] + '\t' + values[
                            i + 2] + '\n'
                        f.write(s)
                command += ' -' + param.name() + ' "' + tempTableFile + '"'
            elif isinstance(param, ParameterExtent):
                # 'We have to substract/add half cell size, since SAGA is
                # center based, not corner based
                halfcell = self.getOutputCellsize(parameters) / 2
                offset = [halfcell, -halfcell, halfcell, -halfcell]
                values = parameters[param.name()].split(',')
                for i in range(4):
                    command += ' -' + self.extentParamNames[i] + ' ' \
                        + str(float(values[i]) + offset[i])
            elif isinstance(param, (ParameterNumber, ParameterSelection)):
                command += ' -' + param.name() + ' ' + str(param.value)
            else:
                command += ' -' + param.name() + ' "' + str(param.value) + '"'

        for out in self.outputs:
            command += ' -' + out.name + ' "' + out.getCompatibleFileName(
                self) + '"'

        commands.append(command)

        # special treatment for RGB algorithm
        # TODO: improve this and put this code somewhere else
        for out in self.outputs:
            if isinstance(out, OutputRaster):
                filename = out.getCompatibleFileName(self)
                filename2 = filename + '.sgrd'
                if self.cmdname == 'RGB Composite':
                    commands.append('io_grid_image 0 -IS_RGB -GRID:"' +
                                    filename2 + '" -FILE:"' + filename + '"')

        # 3: Run SAGA
        commands = self.editCommands(commands)
        SagaUtils.createSagaBatchJobFileFromSagaCommands(commands)
        loglines = []
        loglines.append(self.tr('SAGA execution commands'))
        for line in commands:
            feedback.pushCommandInfo(line)
            loglines.append(line)
        if ProcessingConfig.getSetting(SagaUtils.SAGA_LOG_COMMANDS):
            QgsMessageLog.logMessage('\n'.join(loglines),
                                     self.tr('Processing'), QgsMessageLog.INFO)
        SagaUtils.executeSaga(feedback)

        if self.crs is not None:
            for out in self.outputs:
                if isinstance(out, (OutputVector, OutputRaster)):
                    prjFile = os.path.splitext(
                        out.getCompatibleFileName(self))[0] + ".prj"
                    with open(prjFile, "w") as f:
                        f.write(self.crs.toWkt())
Exemple #27
0
    def processAlgorithm(self, context, feedback):
        layerPoints = QgsProcessingUtils.mapLayerFromString(
            self.getParameterValue(self.POINTS), context)
        layerHubs = QgsProcessingUtils.mapLayerFromString(
            self.getParameterValue(self.HUBS), context)
        fieldName = self.getParameterValue(self.FIELD)

        units = self.UNITS[self.getParameterValue(self.UNIT)]

        if layerPoints.source() == layerHubs.source():
            raise GeoAlgorithmExecutionException(
                self.tr('Same layer given for both hubs and spokes'))

        fields = layerPoints.fields()
        fields.append(QgsField('HubName', QVariant.String))
        fields.append(QgsField('HubDist', QVariant.Double))

        writer = self.getOutputFromName(self.OUTPUT).getVectorWriter(
            fields, QgsWkbTypes.Point, layerPoints.crs(), context)

        index = QgsProcessingUtils.createSpatialIndex(layerHubs, context)

        distance = QgsDistanceArea()
        distance.setSourceCrs(layerPoints.crs())
        distance.setEllipsoid(QgsProject.instance().ellipsoid())

        # Scan source points, find nearest hub, and write to output file
        features = QgsProcessingUtils.getFeatures(layerPoints, context)
        total = 100.0 / QgsProcessingUtils.featureCount(layerPoints, context)
        for current, f in enumerate(features):
            src = f.geometry().boundingBox().center()

            neighbors = index.nearestNeighbor(src, 1)
            ft = next(
                layerHubs.getFeatures(QgsFeatureRequest().setFilterFid(
                    neighbors[0]).setSubsetOfAttributes([fieldName],
                                                        layerHubs.fields())))
            closest = ft.geometry().boundingBox().center()
            hubDist = distance.measureLine(src, closest)

            attributes = f.attributes()
            attributes.append(ft[fieldName])
            if units == 'Feet':
                attributes.append(hubDist * 3.2808399)
            elif units == 'Miles':
                attributes.append(hubDist * 0.000621371192)
            elif units == 'Kilometers':
                attributes.append(hubDist / 1000.0)
            elif units != 'Meters':
                attributes.append(
                    sqrt(
                        pow(src.x() - closest.x(), 2.0) +
                        pow(src.y() - closest.y(), 2.0)))
            else:
                attributes.append(hubDist)

            feat = QgsFeature()
            feat.setAttributes(attributes)

            feat.setGeometry(QgsGeometry.fromPoint(src))

            writer.addFeature(feat)
            feedback.setProgress(int(current * total))

        del writer
Exemple #28
0
    def mergeDataSources2Vrt(self, dataSources, outFile, union=False, relative=False,
                             schema=False, feedback=None):
        '''Function to do the work of merging datasources in a single vrt format

        @param data_sources: Array of path strings
        @param outfile: the output vrt file to generate
        @param relative: Write relative flag. DOES NOT relativise paths. They have to be already relative
        @param schema: Schema flag
        @return: vrt in string format
        '''
        if feedback is None:
            feedback = QgsProcessingFeedback()

        vrt = '<OGRVRTDataSource>'
        if union:
            vrt += '<OGRVRTUnionLayer name="UnionedLayer">'

        total = 100.0 / len(dataSources)
        for current, inFile in enumerate(dataSources):
            feedback.setProgress(int(current * total))

            srcDS = ogr.Open(inFile, 0)
            if srcDS is None:
                raise GeoAlgorithmExecutionException(
                    self.tr('Invalid datasource: {}'.format(inFile)))

            if schema:
                inFile = '@dummy@'

            for layer in srcDS:
                layerDef = layer.GetLayerDefn()
                layerName = layerDef.GetName()

                vrt += '<OGRVRTLayer name="{}">'.format(self.XmlEsc(layerName))
                vrt += '<SrcDataSource relativeToVRT="{}" shared="{}">{}</SrcDataSource>'.format(1 if relative else 0, not schema, self.XmlEsc(inFile))
                if schema:
                    vrt += '<SrcLayer>@dummy@</SrcLayer>'
                else:
                    vrt += '<SrcLayer>{}</SrcLayer>'.format(self.XmlEsc(layerName))

                vrt += '<GeometryType>{}</GeometryType>'.format(self.GeomType2Name(layerDef.GetGeomType()))

                crs = layer.GetSpatialRef()
                if crs is not None:
                    vrt += '<LayerSRS>{}</LayerSRS>'.format(self.XmlEsc(crs.ExportToWkt()))

                # Process all the fields.
                for fieldIdx in range(layerDef.GetFieldCount()):
                    fieldDef = layerDef.GetFieldDefn(fieldIdx)
                    vrt += '<Field name="{}" type="{}"'.format(self.XmlEsc(fieldDef.GetName()), self.fieldType2Name(fieldDef.GetType()))
                    if not schema:
                        vrt += ' src="{}"'.format(self.XmlEsc(fieldDef.GetName()))
                    if fieldDef.GetWidth() > 0:
                        vrt += ' width="{}"'.format(fieldDef.GetWidth())
                    if fieldDef.GetPrecision() > 0:
                        vrt += ' precision="{}"'.format(fieldDef.GetPrecision())
                    vrt += '/>'

                vrt += '</OGRVRTLayer>'

            srcDS.Destroy()

        if union:
            vrt += '</OGRVRTUnionLayer>'

        vrt += '</OGRVRTDataSource>'

        #TODO: pretty-print XML

        if outFile is not None:
            with codecs.open(outFile, 'w') as f:
                f.write(vrt)

        return vrt
Exemple #29
0
    def processAlgorithm(self, parameters, context, feedback):
        inLayers = self.getParameterValue(self.LAYERS)

        layers = []
        fields = QgsFields()
        totalFeatureCount = 0
        for layerSource in inLayers.split(';'):
            layer = QgsProcessingUtils.mapLayerFromString(layerSource, context)

            if (len(layers) > 0):
                if (layer.wkbType() != layers[0].wkbType()):
                    raise GeoAlgorithmExecutionException(
                        self.tr('All layers must have same geometry type!'))

            layers.append(layer)
            totalFeatureCount += layer.featureCount()

            for sindex, sfield in enumerate(layer.fields()):
                found = None
                for dfield in fields:
                    if (dfield.name().upper() == sfield.name().upper()):
                        found = dfield
                        if (dfield.type() != sfield.type()):
                            raise GeoAlgorithmExecutionException(
                                self.tr(
                                    '{} field in layer {} has different '
                                    'data type than in other layers.'.format(
                                        sfield.name(), layerSource)))

                if not found:
                    fields.append(sfield)

        total = 100.0 / totalFeatureCount
        writer = self.getOutputFromName(self.OUTPUT).getVectorWriter(
            fields, layers[0].wkbType(), layers[0].crs(), context)

        featureCount = 0
        for layer in layers:
            for feature in layer.getFeatures():
                sattributes = feature.attributes()
                dattributes = []
                for dindex, dfield in enumerate(fields):
                    if (dfield.type() == QVariant.Int, QVariant.UInt,
                            QVariant.LongLong, QVariant.ULongLong):
                        dattribute = 0
                    elif (dfield.type() == QVariant.Double):
                        dattribute = 0.0
                    else:
                        dattribute = ''

                    for sindex, sfield in enumerate(layer.fields()):
                        if (sfield.name().upper() == dfield.name().upper()):
                            if (sfield.type() != dfield.type()):
                                raise GeoAlgorithmExecutionException(
                                    self.tr('Attribute type mismatch'))
                            dattribute = sattributes[sindex]
                            break

                    dattributes.append(dattribute)

                feature.setAttributes(dattributes)
                writer.addFeature(feature)
                featureCount += 1
                feedback.setProgress(int(featureCount * total))

        del writer
Exemple #30
0
 def __init__(self, msg=None):
     GeoAlgorithmExecutionException.__init__(self, msg)
     self.level = QgsMessageBar.CRITICAL
     self.duration = 7
Exemple #31
0
    def processAlgorithm(self, feedback):
        useField = not self.getParameterValue(Dissolve.DISSOLVE_ALL)
        field_names = self.getParameterValue(Dissolve.FIELD)
        vlayerA = dataobjects.getObjectFromUri(
            self.getParameterValue(Dissolve.INPUT))

        writer = self.getOutputFromName(Dissolve.OUTPUT).getVectorWriter(
            vlayerA.fields().toList(), vlayerA.wkbType(), vlayerA.crs())

        outFeat = QgsFeature()
        features = vector.features(vlayerA)
        total = 100.0 / len(features)

        if not useField:
            first = True
            # we dissolve geometries in blocks using unaryUnion
            geom_queue = []
            for current, inFeat in enumerate(features):
                feedback.setProgress(int(current * total))
                if first:
                    outFeat.setAttributes(inFeat.attributes())
                    first = False

                tmpInGeom = inFeat.geometry()
                if tmpInGeom.isNull() or tmpInGeom.isEmpty():
                    continue

                errors = tmpInGeom.validateGeometry()
                if len(errors) != 0:
                    for error in errors:
                        ProcessingLog.addToLog(
                            ProcessingLog.LOG_ERROR,
                            self.tr('ValidateGeometry()'
                                    'error: One or more '
                                    'input features have '
                                    'invalid geometry: ') + error.what())
                    continue

                geom_queue.append(tmpInGeom)

                if len(geom_queue) > 10000:
                    # queue too long, combine it
                    try:
                        temp_output_geometry = QgsGeometry.unaryUnion(
                            geom_queue)
                        geom_queue = [temp_output_geometry]
                    except:
                        raise GeoAlgorithmExecutionException(
                            self.tr('Geometry exception while dissolving'))

            try:
                outFeat.setGeometry(QgsGeometry.unaryUnion(geom_queue))
            except:
                raise GeoAlgorithmExecutionException(
                    self.tr('Geometry exception while dissolving'))

            writer.addFeature(outFeat)
        else:
            field_indexes = [
                vlayerA.fields().lookupField(f) for f in field_names.split(';')
            ]

            attribute_dict = {}
            geometry_dict = defaultdict(lambda: [])

            for inFeat in features:
                attrs = inFeat.attributes()

                index_attrs = tuple([attrs[i] for i in field_indexes])

                tmpInGeom = QgsGeometry(inFeat.geometry())
                if tmpInGeom and tmpInGeom.isEmpty():
                    continue
                errors = tmpInGeom.validateGeometry()
                if len(errors) != 0:
                    for error in errors:
                        ProcessingLog.addToLog(
                            ProcessingLog.LOG_ERROR,
                            self.tr('ValidateGeometry() '
                                    'error: One or more input'
                                    'features have invalid '
                                    'geometry: ') + error.what())

                if not index_attrs in attribute_dict:
                    # keep attributes of first feature
                    attribute_dict[index_attrs] = attrs

                geometry_dict[index_attrs].append(tmpInGeom)

            nFeat = len(attribute_dict)

            nElement = 0
            for key, value in list(geometry_dict.items()):
                outFeat = QgsFeature()
                nElement += 1
                feedback.setProgress(int(nElement * 100 / nFeat))
                try:
                    tmpOutGeom = QgsGeometry.unaryUnion(value)
                except:
                    raise GeoAlgorithmExecutionException(
                        self.tr('Geometry exception while dissolving'))
                outFeat.setGeometry(tmpOutGeom)
                outFeat.setAttributes(attribute_dict[key])
                writer.addFeature(outFeat)

        del writer