예제 #1
0
 def expressionIterator(self, layer, expression, geometryStorage):
     featReq = QgsFeatureRequest()
     qgsExpression = QgsExpression(expression)
     self.stopLoop = False
     i = 0
     for f in layer.getFeatures(featReq):
         QCoreApplication.processEvents()
         if self.stopLoop:
             break
         self.recordingSearchProgress.emit(i)
         i += 1
         context = QgsExpressionContext()
         scope = QgsExpressionContextScope()
         scope.setFeature(f)
         context.appendScope(scope)
         evaluated = unicode(qgsExpression.evaluate(context))
         if qgsExpression.hasEvalError():
             continue
         if f.geometry() is None or f.geometry().centroid() is None:
             continue
         centroid = f.geometry().centroid().asPoint()
         if geometryStorage == 'wkb':
             geom = binascii.b2a_hex(f.geometry().asWkb())
         elif geometryStorage == 'wkt':
             geom = f.geometry().exportToWkt()
         else:
             geom = f.geometry().boundingBox().asWktPolygon()
         yield( evaluated, centroid.x(), centroid.y(), geom)
예제 #2
0
    def selectionChanged(self):
        self.cleanBrowserFields()
        self.rubber.reset()
        nItems = self.layer.selectedFeatureCount()
        if nItems < 2:
            self.close()
            #self.layer.emit(SIGNAL("browserNoItem()"))
            return
        self.browseFrame.setEnabled(True)
        subset = self.layer.selectedFeatureIds()
        if self.settings.value("saveSelectionInProject"):
            self.layer.setCustomProperty("itemBrowserSelection", repr(subset))

        f = QgsFeature()
        title = QgsExpression(self.layer.displayExpression())
        # fix_print_with_import
        #print(self.layer.displayExpression())
        context = QgsExpressionContext()
        scope = QgsExpressionContextScope()
        context.appendScope(scope)
        title.prepare(context)
        #title.prepare(self.layer.fields())
        iterator = self.layer.getFeatures(QgsFeatureRequest().setFilterFids(subset))
        while iterator.nextFeature(f):
            scope.setFeature(f)
            result = title.evaluate(context)
            if title.hasEvalError():
                self.listCombo.addItem("%u" % f.id(), f.id())
            else:
                self.listCombo.addItem("%s" % result, f.id())
    def _get_eval_expr_value(layer, feature, expression):
        eval_feature = layer.getFeature(
            feature.id()
        )  # this is necessary because the feature is filtered and may not have all the necessary fields
        context = QgsExpressionContext()
        scope = QgsExpressionContextScope()
        scope.setFeature(eval_feature)
        context.appendScope(scope)
        expression.prepare(context)

        return expression.evaluate(context)
예제 #4
0
        def calcField(lyr, field_name, expres):
            lyr.dataProvider().addAttributes([ QgsField(field_name, QVariant.Double)])
            expression = QgsExpression(expres)
            context = QgsExpressionContext()
            scope = QgsExpressionContextScope()
            context.appendScope(scope)
            lyr.startEditing()
            for feature in lyr.getFeatures():
                scope.setFeature(feature)
                feature[field_name] = expression.evaluate(context)
                lyr.updateFeature(feature)

            lyr.commitChanges()
예제 #5
0
    def set_feature(self, feature, canvas_extent=CanvasExtent.Fixed):
        self.line_edit.clear()
        self.feature = feature

        if self.feature is None or not self.feature.isValid(
        ) or self.layer is None:
            return

        expression = QgsExpression(self.layer.displayExpression())
        context = QgsExpressionContext()
        scope = QgsExpressionContextScope()
        context.appendScope(scope)
        scope.setFeature(feature)
        feature_title = expression.evaluate(context)
        if feature_title == "":
            feature_title = feature.id()
        self.line_edit.setText(str(feature_title))
        self.highlight_feature(canvas_extent)
예제 #6
0
    def calc_join(self, orig_tab, link_tab, temp_field, link_field,
                  orig_field):

        path_db = self.proj_abs_path + os.sep + "db" + os.sep + "indagini.sqlite"

        joinObject = QgsVectorJoinInfo()
        joinObject.joinLayerId = link_tab.id()
        joinObject.joinFieldName = 'pkuid'
        joinObject.targetFieldName = temp_field
        joinObject.memoryCache = True
        orig_tab.addJoin(joinObject)

        context = QgsExpressionContext()
        scope = QgsExpressionContextScope()
        context.appendScope(scope)

        expression = QgsExpression(link_field)
        expression.prepare(orig_tab.pendingFields())

        try:
            conn = sqlite3.connect(path_db)
            conn.text_factory = lambda x: str(x, 'utf-8', 'ignore')
            cur = conn.cursor()

            for feature in orig_tab.getFeatures():
                scope.setFeature(feature)
                value = expression.evaluate(context)
                if value is None:
                    pass
                else:
                    nome_tab = LAYER_DB_TAB[orig_tab.name()]
                    #                     cur.execute("UPDATE %s SET %s  = %s WHERE pkuid = %s;" % nome_tab, orig_field, value, str(feature['pkuid']))
                    cur.execute(
                        "UPDATE ? SET ?  = ? WHERE pkuid = ?",
                        (nome_tab, orig_field, value, str(feature['pkuid'])))

            conn.commit()
        except Exception as ex:
            # error will be forwarded upstream
            raise ex
        finally:
            conn.close()

        orig_tab.removeJoin(link_tab.id())
 def EvalExpr(self, layername, expr):
     try:
         layer = self.prj.mapLayersByName(layername)[0]
         context = QgsExpressionContext()
         scope = QgsExpressionContextScope()
         context.appendScope(scope)
         listOfResults = []
         features = [feat for feat in layer.getFeatures()]
         for feat in features:
             scope.setFeature(feat)
             exp = QgsExpression(expr)
             if exp.evaluate(context):
                 listOfResults.append(feat.id())
         if len(listOfResults) == 0:
             self.info.msg('Kein Ergebnis!')
         else:
             layer.selectByIds(listOfResults)
             self.iface.setActiveLayer(layer)
             self.gtomain.runcmd(self.tools)
     except Exception as e:
         self.info.err(e)
def get_features_not_matching_expression(qgsvectorlayer, qgs_expression):
    """
    Returns the QgsFeature objects of the features that do not match the input QgsExpression.

    Args:
        qgsvectorlayer (QgsVectorLayer): the QgsVectorLayer object to evaluate.
        qgs_expression (QgsExpression): the QgsExpression object to filter the QgsVectorLayer's features.

    Returns:
        A list of QgsFeature objects of features that do not match the input qgs_expression.
        Return an empty list if all features match the input expression.
    """

    # A list to hold the QgsFeature objects that do not match the QgsExpression.
    non_matching_features = []

    # These variables are used to increase the speed that the evaluation takes to run when evaluating multiple features
    # of a QgsVectorLayer.
    # REF: https://docs.qgis.org/testing/en/docs/pyqgis_developer_cookbook/expressions.html
    # REF: https://gis.stackexchange.com/questions/244068/pyqgis-gives-typeerror-qgsexpression-prepare-argument-1-
    #      has-unexpected-type/244088#244088
    context = QgsExpressionContext()
    scope = QgsExpressionContextScope()

    # Iterate over the features of the QgsVectorLayer
    for feature in qgsvectorlayer.getFeatures():

        # Set the scope to the current feature.
        scope.setFeature(feature)
        context.appendScope(scope)

        # If the evaluation of the feature is FALSE, append the feature to the non_matching_features list.
        if qgs_expression.evaluate(context) == 0:
            non_matching_features.append(feature)

    # Return the list of QgsFeatures that do not match the input QgsExpression.
    return non_matching_features
def addRowInLayer(row, errTable, table_codif):
    """
    Rows will be converted in a geometry thanks to codification.
    All attributes will be added thanks to QgsExpressionContext.

    Parameters
    ----------
    row: list of list
        A row contains one or many list of points.
    errTable: list of list
        Contains points in error.
        Some points can be added after the end of this function.
    table_codif: dictionnary
        The codification file. See the information about qlsc format.
    """

    #  TODO: assert?
    code = row[CODE_POSITION][0]
    parameters = row[PARAM_POSITION]

    codif = table_codif['Codification'][code]
    layerName = codif['Layer']

    layer = QgsVectorLayer(layerName)

    dim = 4 if QgsWkbTypes.hasZ(layer.dataProvider().wkbType()) else 3
    geom = geomFromType(list(zip(*row[1:dim])), parameters,
                        codif['GeometryType'], layer.geometryType())

    if geom:
        layer.startEditing()

        fields = layer.fields()
        newFeature = QgsFeature(fields)

        newFeature.setGeometry(geom)

        for e in codif['Attributes']:
            # print(e, e[1], e[1].startswith('_att'))
            if e[1].startswith('_att'):
                # len('_att') == 4
                try:
                    nb = int(e[1][4:]) - 1
                    assert(nb >= 0)
                    val = row[ATTRS_POSITION + nb][0]
                    newFeature[e[0]] = val
                except:
                    # print("attributes error")
                    pass
            else:
                context = QgsExpressionContext()
                scope = QgsExpressionContextScope()
                try:
                    exp = QgsExpression(e[1])
                    scope.setFeature(newFeature)
                    context.appendScope(scope)
                    newFeature[e[0]] = exp.evaluate(context)
                except:
                    # print('key error')
                    pass

        ret = layer.addFeature(newFeature)
        # if not ret:
         #   print(ret)

        layer.commitChanges()
        layer.updateExtents()
    else:
        # can it happen?
        errTable.append(row)
예제 #10
0
    def processAlgorithm(self, parameters, context, feedback):

        source = self.parameterAsSource(parameters, self.INPUT, context)
        insee_com = self.parameterAsExpression(parameters, self.INSEE_COM,
                                               context)
        adresse = self.parameterAsExpression(parameters, self.ADRESSE, context)

        if source is None:
            raise QgsProcessingException(
                self.invalidSourceError(parameters, self.INPUT))

        fields = source.fields()
        fields.append(QgsField(
            'ban_label', QVariant.String, len=6)) or feedback.reportError(
                'Le champs ban_label existe deja, son contenu sera remplacé')
        fields.append(QgsField(
            'ban_citycode', QVariant.String, len=100)) or feedback.reportError(
                'Le champs ban_citycode existe deja, son contenu sera remplacé'
            )
        fields.append(QgsField(
            'ban_score', QVariant.Double, len=10,
            prec=5)) or feedback.reportError(
                'Le champs ban_score existe deja, son contenu sera remplacé')
        fields.append(QgsField(
            'ban_type', QVariant.String, len=20)) or feedback.reportError(
                'Le champs ban_type existe deja, son contenu sera remplacé')

        (sink,
         dest_id) = self.parameterAsSink(parameters, self.OUTPUT, context,
                                         fields, QgsWkbTypes.Point,
                                         QgsCoordinateReferenceSystem(2154))

        if sink is None:
            raise QgsProcessingException(
                self.invalidSinkError(parameters, self.OUTPUT))

        total = 100.0 / source.featureCount() if source.featureCount() else 0
        features = source.getFeatures()

        citycode_expr = QgsExpression(insee_com)
        adresse_expr = QgsExpression(adresse)
        context = self.createExpressionContext(parameters, context, source)
        scope = QgsExpressionContextScope()
        citycode_expr.prepare(context)
        adresse_expr.prepare(context)
        for current, feature in enumerate(features):
            if feedback.isCanceled():
                break

            scope.setFeature(feature)
            context.appendScope(scope)
            citycode = citycode_expr.evaluate(context)
            adresse = adresse_expr.evaluate(context)

            response = geocode(adresse, citycode=citycode)
            if response:
                #feedback.pushDebugInfo(str(response['properties'].get('score')))
                attr = feature.attributes()
                for i in range(fields.count() - len(attr)):
                    attr.append(None)
                feature.setFields(fields)
                feature.setAttributes(attr)
                feature.setAttribute('ban_label',
                                     response['properties'].get('label', ''))
                feature.setAttribute(
                    'ban_citycode', response['properties'].get('citycode', ''))
                feature.setAttribute('ban_score',
                                     response['properties'].get('score', ''))
                feature.setAttribute('ban_type',
                                     response['properties'].get('type', ''))

                x = response['properties'].get('x')
                y = response['properties'].get('y')
                #feature.setAttributes(attr)
                geom = QgsGeometry().fromPointXY(QgsPointXY(x, y))
                #t=QgsCoordinateTransform(QgsCoordinateReferenceSystem(2154),source.sourceCrs(),QgsProject.instance())
                #geom.transform(t)
                feature.setGeometry(geom)

            # Add a feature in the sink
            sink.addFeature(feature, QgsFeatureSink.FastInsert)

            # Update the progress bar
            feedback.setProgress(int(current * total))
            sleep(0.11)

        return {self.OUTPUT: dest_id}
    def processAlgorithm(self, parameters, context, feedback):
        source = self.parameterAsRasterLayer(parameters, self.INPUT, context)
        if source is None:
            raise QgsProcessingException(self.invalidSourceError(parameters, self.INPUT))
            
        band = self.parameterAsInt(parameters, self.BAND, context)
        expression = self.parameterAsString(parameters, self.EXPRESSION, context).replace('\n', '')
        feedback.pushInfo('Expression = {}'.format(expression))
        if len(expression.strip()) == 0:
            raise QgsProcessingException('Expression values required!')
        
        output_raster = self.parameterAsOutputLayer(parameters, self.OUTPUT, context)
        
        # create raster dataset
        inputDs = gdal.Open(unicode(source.source()), GA_ReadOnly)
        inputBand = inputDs.GetRasterBand(band)
        dataType = inputBand.DataType;
        nodata = int(inputBand.GetNoDataValue()) if dataType < 6 else inputBand.GetNoDataValue()
        
        feedback.pushInfo('NoData Value = {0}'.format(nodata))
        feedback.pushInfo('DataType = {0}'.format(dataType))
        feedback.pushInfo('DataType = {0}'.format(self.RASTER_TYPES[gdal.GetDataTypeName(dataType)]))

        driver = gdal.GetDriverByName('GTiff')
        outputDs = driver.Create(output_raster, inputDs.RasterXSize, inputDs.RasterYSize, 1, dataType)
        outputDs.SetProjection(inputDs.GetProjection())
        outputDs.SetGeoTransform(inputDs.GetGeoTransform())
        outputBand = outputDs.GetRasterBand(1)
        outputBand.SetNoDataValue(nodata)

        # prepare feature for expression
        fields = QgsFields()
        fields.append(QgsField('value', QVariant.Double))
        fields.append(QgsField(source.name(), QVariant.Double))

        exp = QgsExpression(expression)
        context = QgsExpressionContext()
        scope = QgsExpressionContextScope()
        context.appendScope(scope)

        feature = QgsFeature(fields)

        # extrace by attributes
        data_type  = self.RASTER_TYPES[gdal.GetDataTypeName(dataType)]
        for y in range(inputBand.YSize):
            if feedback.isCanceled():
                break
            feedback.setProgress(int(y / float(inputBand.YSize) * 100))
            
            scanline = inputBand.ReadRaster(0, y, inputBand.XSize, 1, inputBand.XSize, 1, dataType)
            values = struct.unpack(data_type * inputBand.XSize, scanline)
            
            output = ''.encode()
            for value in values:
                raster_value = nodata
                if value != nodata:
                    feature.setAttribute(0, value)
                    feature.setAttribute(1, value)
                    scope.setFeature(feature)
                    if bool(exp.evaluate(context)):
                      raster_value = value
                    else:
                      raster_value = nodata
                output = output + struct.pack(data_type, raster_value)
                    
            # write line
            outputBand.WriteRaster(0, y, inputBand.XSize, 1, output, buf_xsize=inputBand.XSize, buf_ysize=1, buf_type=dataType)
            del output

        outputDs.FlushCache()
        outputDs = None
        inputDs = None

        return {self.OUTPUT: output_raster}
    def processAlgorithm(self, parameters, context, feedback):
        source = self.parameterAsRasterLayer(parameters, self.INPUT, context)
        if source is None:
            raise QgsProcessingException(self.invalidSourceError(parameters, self.INPUT))
            
        band = self.parameterAsInt(parameters, self.BAND, context)
        expression = self.parameterAsString(parameters, self.EXPRESSION, context).replace('\n', '')
        feedback.pushInfo('Expression = {}'.format(expression))
        if len(expression.strip()) == 0:
            raise QgsProcessingException('Expression values required!')
        
        output_raster = self.parameterAsOutputLayer(parameters, self.OUTPUT, context)
        
        # create raster dataset
        inputDs = gdal.Open(unicode(source.source()), GA_ReadOnly)
        inputBand = inputDs.GetRasterBand(band)
        dataType = inputBand.DataType;
        nodata = int(inputBand.GetNoDataValue()) if dataType < 6 else inputBand.GetNoDataValue()
        
        feedback.pushInfo('NoData Value = {0}'.format(nodata))
        feedback.pushInfo('DataType = {0}'.format(dataType))
        feedback.pushInfo('DataType = {0}'.format(self.RASTER_TYPES[gdal.GetDataTypeName(dataType)]))

        driver = gdal.GetDriverByName('GTiff')
        outputDs = driver.Create(output_raster, inputDs.RasterXSize, inputDs.RasterYSize, 1, dataType)
        outputDs.SetProjection(inputDs.GetProjection())
        outputDs.SetGeoTransform(inputDs.GetGeoTransform())
        outputBand = outputDs.GetRasterBand(1)
        outputBand.SetNoDataValue(nodata)

        # prepare feature for expression
        fields = QgsFields()
        fields.append(QgsField('value', QVariant.Double))
        fields.append(QgsField(source.name(), QVariant.Double))

        exp = QgsExpression(expression)
        context = QgsExpressionContext()
        scope = QgsExpressionContextScope()
        context.appendScope(scope)

        feature = QgsFeature(fields)

        # extrace by attributes
        data_type  = self.RASTER_TYPES[gdal.GetDataTypeName(dataType)]
        for y in range(inputBand.YSize):
            if feedback.isCanceled():
                break
            feedback.setProgress(int(y / float(inputBand.YSize) * 100))
            
            scanline = inputBand.ReadRaster(0, y, inputBand.XSize, 1, inputBand.XSize, 1, dataType)
            values = struct.unpack(data_type * inputBand.XSize, scanline)
            
            output = ''.encode()
            for value in values:
                raster_value = nodata
                if value != nodata:
                    feature.setAttribute(0, value)
                    feature.setAttribute(1, value)
                    scope.setFeature(feature)
                    if bool(exp.evaluate(context)):
                      raster_value = value
                    else:
                      raster_value = nodata
                output = output + struct.pack(data_type, raster_value)
                    
            # write line
            outputBand.WriteRaster(0, y, inputBand.XSize, 1, output, buf_xsize=inputBand.XSize, buf_ysize=1, buf_type=dataType)
            del output

        outputDs.FlushCache()
        outputDs = None
        inputDs = None

        return {self.OUTPUT: output_raster}