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)
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)
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()
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)
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)
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}