def prepareAlgorithm(self, parameters, context, feedback): source = self.parameterAsSource(parameters, 'INPUT', context) mapping = self.parameterAsFieldsMapping(parameters, self.FIELDS_MAPPING, context) self.fields = QgsFields() self.expressions = [] da = QgsDistanceArea() da.setSourceCrs(source.sourceCrs()) da.setEllipsoid(context.project().ellipsoid()) # create an expression context using thread safe processing context self.expr_context = self.createExpressionContext(parameters, context, source) for field_def in mapping: self.fields.append(QgsField(name=field_def['name'], type=field_def['type'], typeName="", len=field_def.get('length', 0), prec=field_def.get('precision', 0))) expression = QgsExpression(field_def['expression']) expression.setGeomCalculator(da) expression.setDistanceUnits(context.project().distanceUnits()) expression.setAreaUnits(context.project().areaUnits()) if expression.hasParserError(): raise QgsProcessingException( self.tr(u'Parser error in expression "{}": {}') .format(str(expression.expression()), str(expression.parserErrorString()))) self.expressions.append(expression) return True
def get_feature_value(self, model=None): self.layer.startEditing() feature = None request = QgsFeatureRequest() if model is None: model = self.host.model() request.setFilterFid(model.id) feature_itr = self.layer.getFeatures(request) for feat in feature_itr: feature = feat break exp = QgsExpression(self.column.expression) if exp.hasParserError(): raise Exception(exp.parserErrorString()) exp.prepare(self.layer.pendingFields()) if feature is not None: value = exp.evaluate(feature) return value else: return None
def generic_zoom(self, fieldname, combo, field_index=0): ''' Get selected element from the combo, and returns a feature request expression ''' # Get selected element from combo element = combo.currentText() if element.strip() == '': print "Any record selected" return None elem = combo.itemData(combo.currentIndex()) if not elem: # that means that user has edited manually the combo but the element # does not correspond to any combo element message = 'Element {} does not exist'.format(element) self.controller.show_warning(message) return None # Select this feature in order to copy to memory layer aux = fieldname+" = '"+str(elem[field_index])+"'" expr = QgsExpression(aux) if expr.hasParserError(): message = expr.parserErrorString() + ": " + aux self.controller.show_warning(message) return return expr
def mg_flow_trace_select_features(self, layer, elem_type): sql = "SELECT * FROM "+self.schema_name+".temp_mincut_"+elem_type+" ORDER BY "+elem_type+"_id" rows = self.dao.get_rows(sql) self.dao.commit() # Build an expression to select them aux = "\""+elem_type+"_id\" IN (" for elem in rows: aux+= elem[0]+", " aux = aux[:-2]+")" # Get a featureIterator from this expression: expr = QgsExpression(aux) if expr.hasParserError(): self.showWarning("Expression Error: "+str(expr.parserErrorString())) return it = layer.getFeatures(QgsFeatureRequest(expr)) # Build a list of feature id's from the previous result id_list = [i.id() for i in it] # Select features with these id's layer.setSelectedFeatures(id_list)
def processAlgorithm(self, progress): layer = layer = dataobjects.getObjectFromUri(self.getParameterValue(self.INPUT)) expression = self.getParameterValue(self.EXPRESSION) qExp = QgsExpression(expression) if qExp.hasParserError(): raise GeoAlgorithmExecutionException(qExp.parserErrorString()) writer = self.getOutputFromName(self.OUTPUT).getVectorWriter( layer.fields(), layer.wkbType(), layer.crs()) context = QgsExpressionContext() context.appendScope(QgsExpressionContextUtils.globalScope()) context.appendScope(QgsExpressionContextUtils.projectScope()) context.appendScope(QgsExpressionContextUtils.layerScope(layer)) count = layer.featureCount() step = 100.0 / count if count else 1 request = QgsFeatureRequest(qExp, context) for current, f in enumerate(layer.getFeatures(request)): writer.addFeature(f) progress.setPercentage(int(current * step)) del writer
def mg_flow_trace_select_features(self, layer, elem_type): if self.index_action == '56': sql = "SELECT * FROM "+self.schema_name+".anl_flow_trace_"+elem_type+" ORDER BY "+elem_type+"_id" else: sql = "SELECT * FROM "+self.schema_name+".anl_flow_exit_"+elem_type+" ORDER BY "+elem_type+"_id" rows = self.controller.get_rows(sql) if rows: # Build an expression to select them aux = "\""+elem_type+"_id\" IN (" for elem in rows: aux += elem[0] + ", " aux = aux[:-2] + ")" # Get a featureIterator from this expression: expr = QgsExpression(aux) if expr.hasParserError(): message = "Expression Error: " + str(expr.parserErrorString()) self.controller.show_warning(message, context_name='ui_message') return it = layer.getFeatures(QgsFeatureRequest(expr)) # Build a list of feature id's from the previous result id_list = [i.id() for i in it] # Select features with these id's layer.setSelectedFeatures(id_list)
def processAlgorithm(self, progress): layer = dataobjects.getObjectFromUri( self.getParameterValue(self.INPUT_LAYER)) geometry_type = self.getParameterValue(self.OUTPUT_GEOMETRY) wkb_type = None if geometry_type == 0: wkb_type = QgsWkbTypes.Polygon elif geometry_type == 1: wkb_type = QgsWkbTypes.LineString else: wkb_type = QgsWkbTypes.Point if self.getParameterValue(self.WITH_Z): wkb_type = QgsWkbTypes.addZ(wkb_type) if self.getParameterValue(self.WITH_M): wkb_type = QgsWkbTypes.addM(wkb_type) writer = self.getOutputFromName( self.OUTPUT_LAYER).getVectorWriter( layer.fields(), wkb_type, layer.crs()) expression = QgsExpression(self.getParameterValue(self.EXPRESSION)) if expression.hasParserError(): raise GeoAlgorithmExecutionException(expression.parserErrorString()) exp_context = QgsExpressionContext() exp_context.appendScope(QgsExpressionContextUtils.globalScope()) exp_context.appendScope(QgsExpressionContextUtils.projectScope()) exp_context.appendScope(QgsExpressionContextUtils.layerScope(layer)) if not expression.prepare(exp_context): raise GeoAlgorithmExecutionException( self.tr('Evaluation error: %s' % expression.evalErrorString())) features = vector.features(layer) total = 100.0 / len(features) for current, input_feature in enumerate(features): output_feature = input_feature exp_context.setFeature(input_feature) value = expression.evaluate(exp_context) if expression.hasEvalError(): raise GeoAlgorithmExecutionException( self.tr('Evaluation error: %s' % expression.evalErrorString())) if not value: output_feature.setGeometry(QgsGeometry()) else: if not isinstance(value, QgsGeometry): raise GeoAlgorithmExecutionException( self.tr('{} is not a geometry').format(value)) output_feature.setGeometry(value) writer.addFeature(output_feature) progress.setPercentage(int(current * total)) del writer
def processAlgorithm(self, parameters, context, feedback): source = self.parameterAsSource(parameters, self.INPUT, context) layer = self.parameterAsVectorLayer(parameters, self.INPUT, context) field_name = self.parameterAsString(parameters, self.FIELD_NAME, context) field_type = self.TYPES[self.parameterAsEnum(parameters, self.FIELD_TYPE, context)] width = self.parameterAsInt(parameters, self.FIELD_LENGTH, context) precision = self.parameterAsInt(parameters, self.FIELD_PRECISION, context) new_field = self.parameterAsBool(parameters, self.NEW_FIELD, context) formula = self.parameterAsString(parameters, self.FORMULA, context) expression = QgsExpression(formula) da = QgsDistanceArea() da.setSourceCrs(source.sourceCrs()) da.setEllipsoid(context.project().ellipsoid()) expression.setGeomCalculator(da) expression.setDistanceUnits(context.project().distanceUnits()) expression.setAreaUnits(context.project().areaUnits()) fields = source.fields() field_index = fields.lookupField(field_name) if new_field or field_index < 0: fields.append(QgsField(field_name, field_type, '', width, precision)) (sink, dest_id) = self.parameterAsSink(parameters, self.OUTPUT, context, fields, source.wkbType(), source.sourceCrs()) exp_context = self.createExpressionContext(parameters, context) if layer is not None: exp_context.appendScope(QgsExpressionContextUtils.layerScope(layer)) if not expression.prepare(exp_context): raise QgsProcessingException( self.tr('Evaluation error: {0}').format(expression.parserErrorString())) features = source.getFeatures() total = 100.0 / source.featureCount() if source.featureCount() else 0 for current, f in enumerate(features): if feedback.isCanceled(): break rownum = current + 1 exp_context.setFeature(f) exp_context.lastScope().setVariable("row_number", rownum) value = expression.evaluate(exp_context) if expression.hasEvalError(): feedback.reportError(expression.evalErrorString()) else: attrs = f.attributes() if new_field or field_index < 0: attrs.append(value) else: attrs[field_index] = value f.setAttributes(attrs) sink.addFeature(f, QgsFeatureSink.FastInsert) feedback.setProgress(int(current * total)) return {self.OUTPUT: dest_id}
def urban_zoom(self): ''' Zoom to layer 'urban' filtering values of all combos ''' # Build expresion search aux = "" layer = self.layers['urban_propierties_layer'] fieldname = self.params['urban_propierties_field_pzone'] combo = self.dlg.urban_properties_zone text = utils_giswater.getSelectedItem(combo) if text != "null": if aux != "": aux+= " AND " aux+= fieldname+" = '"+str(text)+"'" fieldname = self.params['urban_propierties_field_block'] combo = self.dlg.urban_properties_block text = utils_giswater.getSelectedItem(combo) if text != "null": if aux != "": aux+= " AND " aux+= fieldname+" = '"+str(text)+"'" fieldname = self.params['urban_propierties_field_number'] combo = self.dlg.urban_properties_number text = utils_giswater.getSelectedItem(combo) if text != "null": if aux != "": aux+= " AND " aux+= fieldname+" = '"+str(text)+"'" # Build a list of feature id's from the expression and select them if aux != '': expr = QgsExpression(aux) if expr.hasParserError(): message = expr.parserErrorString() + ": " + aux self.controller.show_warning(message) return it = layer.getFeatures(QgsFeatureRequest(expr)) ids = [i.id() for i in it] layer.setSelectedFeatures(ids) # Select all features else: layer.selectAll() # Copy selected features to memory layer self.urbanMemLayer = self.copy_selected(layer, self.urbanMemLayer, "Polygon") # Zoom to generated memory layer self.zoom_to_scale() # Load style if self.QML_URBAN is not None: self.load_style(self.urbanMemLayer, self.QML_URBAN) # Toggles 'Show feature count' self.show_feature_count()
def address_get_numbers(self): ''' Populate civic numbers depending on selected street. Available civic numbers are linked with self.street_field_code column code in self.portal_layer and self.street_layer ''' # get selected street selected = self.dlg.adress_street.currentText() if selected == '': print "Any record selected" return # get street code elem = self.dlg.adress_street.itemData(self.dlg.adress_street.currentIndex()) code = elem[0] # to know the index see the query that populate the combo records = [[-1, '']] # Set filter expression layer = self.layers['portal_layer'] idx_field_code = layer.fieldNameIndex(self.params['portal_field_code']) idx_field_number = layer.fieldNameIndex(self.params['portal_field_number']) aux = self.params['portal_field_code']+" = '"+str(code)+"'" # Check filter and existence of fields expr = QgsExpression(aux) if expr.hasParserError(): message = expr.parserErrorString() + ": " + aux self.controller.show_warning(message) return if idx_field_code == -1: message = "Field '{}' not found in layer '{}'. Open '{}' and check parameter '{}'" \ .format(self.params['portal_field_code'], layer.name(), self.setting_file, 'portal_field_code') self.controller.show_warning(message) return if idx_field_number == -1: message = "Field '{}' not found in layer '{}'. Open '{}' and check parameter '{}'" \ .format(self.params['portal_field_number'], layer.name(), self.setting_file, 'portal_field_number') self.controller.show_warning(message) return # Get a featureIterator from an expression: # Get features from the iterator and do something it = layer.getFeatures(QgsFeatureRequest(expr)) for feature in it: attrs = feature.attributes() field_number = attrs[idx_field_number] if not type(field_number) is QPyNullVariant: elem = [code, field_number] records.append(elem) # Fill numbers combo records_sorted = sorted(records, key = operator.itemgetter(1)) self.dlg.adress_number.blockSignals(True) self.dlg.adress_number.clear() for record in records_sorted: self.dlg.adress_number.addItem(str(record[1]), record) self.dlg.adress_number.blockSignals(False)
def createExpression(self, text, da, context): expr = QgsExpression(text) expr.setGeomCalculator(da) expr.setDistanceUnits(context.project().distanceUnits()) expr.setAreaUnits(context.project().areaUnits()) if expr.hasParserError(): raise QgsProcessingException( self.tr(u'Parser error in expression "{}": {}') .format(text, expr.parserErrorString())) return expr
def where(layer, exp): exp = QgsExpression(exp) if exp.hasParserError(): raise Exception(exp.parserErrorString()) exp.prepare(layer.pendingFields()) for feature in layer.getFeatures(): value = exp.evaluate(feature) if exp.hasEvalError(): raise ValueError(exp.evalErrorString()) if bool(value): yield feature
def layer_value(feature, layer, defaultconfig): if not canvas: roam.utils.warning("No canvas set for using layer_values default function") return None layers = [] # layer name can also be a list of layers to search layername = defaultconfig['layer'] if isinstance(layername, basestring): layers.append(layername) else: layers = layername expression = defaultconfig['expression'] field = defaultconfig['field'] for searchlayer in layers: try: searchlayer = QgsMapLayerRegistry.instance().mapLayersByName(searchlayer)[0] except IndexError: RoamEvents.raisemessage("Missing layer", "Unable to find layer used in widget expression {}".format(searchlayer), level=1) roam.utils.warning("Unable to find expression layer {}".format(searchlayer)) return if feature.geometry(): rect = feature.geometry().boundingBox() if layer.geometryType() == QGis.Point: point = feature.geometry().asPoint() rect = QgsRectangle(point.x(), point.y(), point.x() + 10, point.y() + 10) rect.scale(20) rect = canvas.mapRenderer().mapToLayerCoordinates(layer, rect) rq = QgsFeatureRequest().setFilterRect(rect)\ .setFlags(QgsFeatureRequest.ExactIntersect) features = searchlayer.getFeatures(rq) else: features = searchlayer.getFeatures() exp = QgsExpression(expression) exp.prepare(searchlayer.pendingFields()) if exp.hasParserError(): error = exp.parserErrorString() roam.utils.warning(error) for f in features: value = exp.evaluate(f) if exp.hasEvalError(): error = exp.evalErrorString() roam.utils.warning(error) if value: return f[field] raise DefaultError('No features found')
def evaluateExpression(self, text): context = QgsExpressionContext() context.appendScope(QgsExpressionContextUtils.globalScope()) context.appendScope(QgsExpressionContextUtils.projectScope()) exp = QgsExpression(text) if exp.hasParserError(): raise Exception(exp.parserErrorString()) result = exp.evaluate(context) if exp.hasEvalError(): raise ValueError(exp.evalErrorString()) return result
def getStreetNumbers(self): ''' Populate civic numbers depending on selected street. Available civic numbers are linked with self.STREET_FIELD_CODE column code in self.PORTAL_LAYER and self.STREET_LAYER ''' # get selected street selected = self.dlg.cboStreet.currentText() if selected == '': return # get street code sel_street = self.dlg.cboStreet.itemData(self.dlg.cboStreet.currentIndex()) code = sel_street[2] # to know the index see the query that populate the combo records = [[-1, '']] # Set filter expression layer = self.portalLayer idx_field_code = layer.fieldNameIndex(self.PORTAL_FIELD_CODE) idx_field_number = layer.fieldNameIndex(self.PORTAL_FIELD_NUMBER) aux = self.PORTAL_FIELD_CODE+"='"+str(code)+"'" # Check filter and existence of fields expr = QgsExpression(aux) if expr.hasParserError(): self.iface.messageBar().pushMessage(expr.parserErrorString() + ": " + aux, self.app_name, QgsMessageBar.WARNING, 10) return if idx_field_code == -1: message = self.tr("Field '{}' not found in layer '{}'. Open '{}' and check parameter '{}'". format(self.PORTAL_FIELD_CODE, layer.name(), self.setting_file, 'PORTAL_FIELD_CODE')) self.iface.messageBar().pushMessage(message, '', QgsMessageBar.WARNING) return if idx_field_number == -1: message = self.tr("Field '{}' not found in layer '{}'. Open '{}' and check parameter '{}'". format(self.PORTAL_FIELD_NUMBER, layer.name(), self.setting_file, 'PORTAL_FIELD_NUMBER')) self.iface.messageBar().pushMessage(message, '', QgsMessageBar.WARNING) return # Get a featureIterator from an expression: # Get features from the iterator and do something it = layer.getFeatures(QgsFeatureRequest(expr)) for feature in it: attrs = feature.attributes() field_number = attrs[idx_field_number] if not type(field_number) is QPyNullVariant: elem = [code, field_number] records.append(elem) # Fill numbers combo records_sorted = sorted(records, key = operator.itemgetter(1)) self.dlg.cboNumber.blockSignals(True) self.dlg.cboNumber.clear() for record in records_sorted: self.dlg.cboNumber.addItem(record[1], record) self.dlg.cboNumber.blockSignals(False)
def where(self, exp): '''Request feature by QgsExpression Usage : for feat in layer.where("myfield" = 2): ... ''' exp = QgsExpression(exp) if exp.hasParserError(): raise Exception(exp.parserErrorString()) if exp.hasEvalError(): raise ValueError(exp.evalErrorString()) return self.getFeatures(QgsFeatureRequest(exp))
def processAlgorithm(self, parameters, context, feedback): layer = QgsProcessingUtils.mapLayerFromString(self.getParameterValue(self.INPUT_LAYER), context) geometry_type = self.getParameterValue(self.OUTPUT_GEOMETRY) wkb_type = None if geometry_type == 0: wkb_type = QgsWkbTypes.Polygon elif geometry_type == 1: wkb_type = QgsWkbTypes.LineString else: wkb_type = QgsWkbTypes.Point if self.getParameterValue(self.WITH_Z): wkb_type = QgsWkbTypes.addZ(wkb_type) if self.getParameterValue(self.WITH_M): wkb_type = QgsWkbTypes.addM(wkb_type) writer = self.getOutputFromName( self.OUTPUT_LAYER).getVectorWriter(layer.fields(), wkb_type, layer.crs(), context) expression = QgsExpression(self.getParameterValue(self.EXPRESSION)) if expression.hasParserError(): raise GeoAlgorithmExecutionException(expression.parserErrorString()) exp_context = QgsExpressionContext(QgsExpressionContextUtils.globalProjectLayerScopes(layer)) if not expression.prepare(exp_context): raise GeoAlgorithmExecutionException( self.tr('Evaluation error: {0}').format(expression.evalErrorString())) features = QgsProcessingUtils.getFeatures(layer, context) total = 100.0 / QgsProcessingUtils.featureCount(layer, context) for current, input_feature in enumerate(features): output_feature = input_feature exp_context.setFeature(input_feature) value = expression.evaluate(exp_context) if expression.hasEvalError(): raise GeoAlgorithmExecutionException( self.tr('Evaluation error: {0}').format(expression.evalErrorString())) if not value: output_feature.setGeometry(QgsGeometry()) else: if not isinstance(value, QgsGeometry): raise GeoAlgorithmExecutionException( self.tr('{} is not a geometry').format(value)) output_feature.setGeometry(value) writer.addFeature(output_feature) feedback.setProgress(int(current * total)) del writer
def processAlgorithm(self, parameters, context, feedback): layer = self.parameterAsVectorLayer(parameters, self.INPUT, context) fieldName = self.parameterAsString(parameters, self.FIELD, context) operator = self.OPERATORS[self.parameterAsEnum(parameters, self.OPERATOR, context)] value = self.parameterAsString(parameters, self.VALUE, context) fields = layer.fields() idx = layer.fields().lookupField(fieldName) if idx < 0: raise QgsProcessingException(self.tr("Field '{}' was not found in layer").format(fieldName)) fieldType = fields[idx].type() if fieldType != QVariant.String and operator in self.STRING_OPERATORS: op = ''.join(['"%s", ' % o for o in self.STRING_OPERATORS]) raise QgsProcessingException( self.tr('Operators {0} can be used only with string fields.').format(op)) field_ref = QgsExpression.quotedColumnRef(fieldName) quoted_val = QgsExpression.quotedValue(value) if operator == 'is null': expression_string = '{} IS NULL'.format(field_ref) elif operator == 'is not null': expression_string = '{} IS NOT NULL'.format(field_ref) elif operator == 'begins with': expression_string = "{} LIKE '{}%'".format(field_ref, value) elif operator == 'contains': expression_string = "{} LIKE '%{}%'".format(field_ref, value) elif operator == 'does not contain': expression_string = "{} NOT LIKE '%{}%'".format(field_ref, value) else: expression_string = '{} {} {}'.format(field_ref, operator, quoted_val) method = self.parameterAsEnum(parameters, self.METHOD, context) if method == 0: behavior = QgsVectorLayer.SetSelection elif method == 1: behavior = QgsVectorLayer.AddToSelection elif method == 2: behavior = QgsVectorLayer.RemoveFromSelection elif method == 3: behavior = QgsVectorLayer.IntersectSelection expression = QgsExpression(expression_string) if expression.hasParserError(): raise QgsProcessingException(expression.parserErrorString()) layer.selectByExpression(expression_string, behavior) return {self.OUTPUT: parameters[self.INPUT]}
def _buildfromlayer(self, widget, layerconfig): layername = layerconfig['layer'] keyfield = layerconfig['key'] valuefield = layerconfig['value'] filterexp = layerconfig.get('filter', None) try: layer = QgsMapLayerRegistry.instance().mapLayersByName(layername)[0] except IndexError: roam.utils.warning("Can't find layer {} in project".format(layername)) return keyfieldindex = layer.fieldNameIndex(keyfield) valuefieldindex = layer.fieldNameIndex(valuefield) if keyfieldindex == -1 or valuefieldindex == -1: roam.utils.warning("Can't find key or value column") return if not filterexp and valuefieldindex == keyfieldindex: values = layer.uniqueValues(keyfieldindex) for value in values: widget.addItem(value, value) return attributes = {keyfieldindex, valuefieldindex} flags = QgsFeatureRequest.NoGeometry expression = None if filterexp: expression = QgsExpression(filterexp) expression.prepare(layer.pendingFields()) if expression.hasParserError(): roam.utils.warning("Expression has parser error: {}".format(expression.parserErrorString())) return if expression.needsGeometry(): flags = QgsFeatureRequest.NoFlags for field in expression.referencedColumns(): index = layer.fieldNameIndex(field) attributes.add(index) values = set() request = QgsFeatureRequest().setFlags(flags).setSubsetOfAttributes(list(attributes)) for feature in layer.getFeatures(request): if expression and not expression.evaluate(feature): continue widget.addItem(feature[keyfieldindex], feature[valuefield]) if self.allownulls: widget.insertItem(0, '(no selection)', None)
def getPlots(self): # get selected urban core selected = self.dlg.cboUrbanCore.currentText() if selected == '': return # get urban core code sel_core = self.dlg.cboUrbanCore.itemData(self.dlg.cboUrbanCore.currentIndex()) code = sel_core[2] # to know the index see the query that populate the combo records = [[-1, '']] # Set filter expression layer = self.plotLayer idx_field_code = layer.fieldNameIndex(self.PLOT_FIELD_CODE) idx_field_number = layer.fieldNameIndex(self.PLOT_FIELD_ADDRESS) idx_field_id = layer.fieldNameIndex('id') aux = self.PLOT_FIELD_CODE+"='"+str(code)+"'" # Check filter and existence of fields expr = QgsExpression(aux) if expr.hasParserError(): self.iface.messageBar().pushMessage(expr.parserErrorString() + ": " + aux, self.app_name, QgsMessageBar.WARNING, 10) return if idx_field_code == -1: message = self.tr("Field '{}' not found in layer '{}'. Open '{}' and check parameter '{}'". format(self.PLOT_FIELD_CODE, layer.name(), self.setting_file, 'PLOT_FIELD_CODE')) self.iface.messageBar().pushMessage(message, '', QgsMessageBar.WARNING) return if idx_field_number == -1: message = self.tr("Field '{}' not found in layer '{}'. Open '{}' and check parameter '{}'". format(self.PLOT_FIELD_ADDRESS, layer.name(), self.setting_file, 'PLOT_FIELD_ADDRESS')) self.iface.messageBar().pushMessage(message, '', QgsMessageBar.WARNING) return # Get a featureIterator from an expression: # Get features from the iterator and do something it = layer.getFeatures(QgsFeatureRequest(expr)) for feature in it: attrs = feature.attributes() plot_id = attrs[idx_field_id] field_number = attrs[idx_field_number] if not type(field_number) is QPyNullVariant: elem = [plot_id, field_number] records.append(elem) # Fill numbers combo records_sorted = sorted(records, key = operator.itemgetter(1)) self.dlg.cboPlot.blockSignals(True) self.dlg.cboPlot.clear() for record in records_sorted: self.dlg.cboPlot.addItem(record[1], record) self.dlg.cboPlot.blockSignals(False)
def calculate( self, layer, fieldName, expression ): if ( layer.featureCount() == 0 ): self.msg.show( "[Info] * No existing features on layer " + layer.name() + " to calculate expression.", 'info', True ) return expression = QgsExpression( expression ) if expression.hasParserError(): self.msg.show( QApplication.translate( "AutoFields-FieldCalculator", "[Error] (Parsing) " ) + \ expression.parserErrorString(), 'critical' ) return context = QgsExpressionContext() context.appendScope( QgsExpressionContextUtils.globalScope() ) context.appendScope( QgsExpressionContextUtils.projectScope() ) context.appendScope( QgsExpressionContextUtils.layerScope( layer ) ) context.setFields( layer.fields() ) if expression.needsGeometry(): if self.iface: # This block was borrowed from QGIS/python/plugins/processing/algs/qgis/FieldsCalculator.py da = QgsDistanceArea() da.setSourceCrs( layer.crs().srsid() ) da.setEllipsoidalMode( self.iface.mapCanvas().mapSettings().hasCrsTransformEnabled() ) da.setEllipsoid( QgsProject.instance().readEntry( 'Measure', '/Ellipsoid', GEO_NONE )[0] ) expression.setGeomCalculator( da ) if QGis.QGIS_VERSION_INT >= 21400: # Methods added in QGIS 2.14 expression.setDistanceUnits( QgsProject.instance().distanceUnits() ) expression.setAreaUnits( QgsProject.instance().areaUnits() ) expression.prepare( context ) fieldIndex = layer.fieldNameIndex( fieldName ) if fieldIndex == -1: return field = layer.fields()[fieldIndex] dictResults = {} for feature in layer.getFeatures(): context.setFeature( feature ) result = expression.evaluate( context ) if expression.hasEvalError(): self.msg.show( QApplication.translate( "AutoFields-FieldCalculator", "[Error] (Evaluating) " ) + \ expression.evalErrorString(), 'critical' ) return dictResults[feature.id()] = { fieldIndex: field.convertCompatible( result ) } layer.dataProvider().changeAttributeValues( dictResults ) self.msg.show( "[Info] * An expression was calculated on existing features of layer " + layer.name() + ", field " + fieldName + ".", 'info', True )
def processAlgorithm(self, progress): layer = dataobjects.getObjectFromUri(self.getParameterValue(self.INPUT)) fieldName = self.getParameterValue(self.FIELD) operator = self.OPERATORS[self.getParameterValue(self.OPERATOR)] value = self.getParameterValue(self.VALUE) fields = layer.pendingFields() writer = self.getOutputFromName(self.OUTPUT).getVectorWriter(fields, layer.wkbType(), layer.crs()) idx = layer.fieldNameIndex(fieldName) fieldType = fields[idx].type() if fieldType != QVariant.String and operator in self.OPERATORS[-2:]: op = ''.join(['"%s", ' % o for o in self.OPERATORS[-2:]]) raise GeoAlgorithmExecutionException( self.tr('Operators %s can be used only with string fields.' % op)) if fieldType in [QVariant.Int, QVariant.Double]: progress.setInfo(self.tr('Numeric field')) expr = '"%s" %s %s' % (fieldName, operator, value) progress.setInfo(expr) elif fieldType == QVariant.String: progress.setInfo(self.tr('String field')) if operator not in self.OPERATORS[-2:]: expr = """"%s" %s '%s'""" % (fieldName, operator, value) elif operator == 'begins with': expr = """"%s" LIKE '%s%%'""" % (fieldName, value) elif operator == 'contains': expr = """"%s" LIKE '%%%s%%'""" % (fieldName, value) progress.setInfo(expr) elif fieldType in [QVariant.Date, QVariant.DateTime]: progress.setInfo(self.tr('Date field')) expr = """"%s" %s '%s'""" % (fieldName, operator, value) progress.setInfo(expr) else: raise GeoAlgorithmExecutionException( self.tr('Unsupported field type "%s"' % fields[idx].typeName())) expression = QgsExpression(expr) if not expression.hasParserError(): req = QgsFeatureRequest(expression) else: raise GeoAlgorithmExecutionException(expression.parserErrorString()) for f in layer.getFeatures(req): writer.addFeature(f) del writer
def processAlgorithm(self, progress): layer = dataobjects.getObjectFromUri(self.getParameterValue(self.INPUT)) expression_string = self.getParameterValue(self.EXPRESSION) writer = self.getOutputFromName(self.OUTPUT).getVectorWriter(layer.fields(), layer.wkbType(), layer.crs()) expression = QgsExpression(expression_string) if not expression.hasParserError(): req = QgsFeatureRequest().setFilterExpression(expression_string) else: raise GeoAlgorithmExecutionException(expression.parserErrorString()) for f in layer.getFeatures(req): writer.addFeature(f) del writer
def testExpression(self, row): self._errors[row] = None field = self._mapping[row] expression = QgsExpression(field['expression']) if expression.hasParserError(): self._errors[row] = expression.parserErrorString() return if self._layer is None: return dp = self._layer.dataProvider() for feature in dp.getFeatures(): expression.evaluate(feature, dp.fields()) if expression.hasEvalError(): self._errors[row] = expression.evalErrorString() return break
def _features_select(self): """ Generator function that returns features based on user-defined expression. """ exp = QgsExpression(self.expressionText()) if exp.hasParserError(): raise Exception(exp.parserErrorString()) exp.prepare(self._ref_layer.pendingFields()) for f in self._ref_layer.getFeatures(): value = exp.evaluate(f) if bool(value): yield f
def testExpression(self, row): self._errors[row] = None field = self._mapping[row] expression = QgsExpression(field['expression']) if expression.hasParserError(): self._errors[row] = expression.parserErrorString() return if self._layer is None: return context = QgsExpressionContextUtils.createFeatureBasedContext(QgsFeature(), self._layer.fields()) for feature in self._layer.getFeatures(): context.setFeature(feature) expression.evaluate(context) if expression.hasEvalError(): self._errors[row] = expression.evalErrorString() return break
def address_zoom_portal(self): ''' Show street data on the canvas when selected street and number in street tab ''' street = self.dlg.adress_street.currentText() civic = self.dlg.adress_number.currentText() if street == '' or civic == '': print "Any record selected" return # Get selected portal elem = self.dlg.adress_number.itemData(self.dlg.adress_number.currentIndex()) if not elem: # that means that user has edited manually the combo but the element # does not correspond to any combo element message = 'Element {} does not exist'.format(civic) self.controller.show_warning(message) return # select this feature in order to copy to memory layer aux = self.params['portal_field_code']+"='"+str(elem[0])+"' AND "+self.params['portal_field_number']+"='"+str(elem[1])+"'" expr = QgsExpression(aux) if expr.hasParserError(): message = expr.parserErrorString() + ": " + aux self.controller.show_warning(message) return # Get a featureIterator from an expression # Build a list of feature Ids from the previous result # Select featureswith the ids obtained layer = self.layers['portal_layer'] it = self.layers['portal_layer'].getFeatures(QgsFeatureRequest(expr)) ids = [i.id() for i in it] layer.setSelectedFeatures(ids) # Copy selected features to memory layer self.portalMemLayer = self.copy_selected(layer, self.portalMemLayer, "Point") # Zoom to generated memory layer self.zoom_to_scale() # Load style if self.QML_PORTAL is not None: self.load_style(self.portalMemLayer, self.QML_PORTAL) # Toggles 'Show feature count' self.show_feature_count()
def processAlgorithm(self, parameters, context, feedback): source = self.parameterAsSource(parameters, self.INPUT, context) expression_string = self.parameterAsExpression(parameters, self.EXPRESSION, context) (matching_sink, matching_sink_id) = self.parameterAsSink(parameters, self.OUTPUT, context, source.fields(), source.wkbType(), source.sourceCrs()) (nonmatching_sink, non_matching_sink_id) = self.parameterAsSink(parameters, self.FAIL_OUTPUT, context, source.fields(), source.wkbType(), source.sourceCrs()) expression = QgsExpression(expression_string) if expression.hasParserError(): raise GeoAlgorithmExecutionException(expression.parserErrorString()) expression_context = self.createExpressionContext(parameters, context) if not nonmatching_sink: # not saving failing features - so only fetch good features req = QgsFeatureRequest().setFilterExpression(expression_string) req.setExpressionContext(expression_context) for f in source.getFeatures(req): if feedback.isCanceled(): break matching_sink.addFeature(f) else: # saving non-matching features, so we need EVERYTHING expression_context.setFields(source.fields()) expression.prepare(expression_context) total = 100.0 / source.featureCount() for current, f in enumerate(source.getFeatures()): if feedback.isCanceled(): break expression_context.setFeature(f) if expression.evaluate(expression_context): matching_sink.addFeature(f) else: nonmatching_sink.addFeature(f) feedback.setProgress(int(current * total)) results = {self.OUTPUT: matching_sink_id} if nonmatching_sink: results[self.FAIL_OUTPUT] = non_matching_sink_id return results
def processAlgorithm(self, feedback): layer = dataobjects.getLayerFromString(self.getParameterValue(self.INPUT)) fieldName = self.getParameterValue(self.FIELD) operator = self.OPERATORS[self.getParameterValue(self.OPERATOR)] value = self.getParameterValue(self.VALUE) fields = layer.fields() writer = self.getOutputFromName(self.OUTPUT).getVectorWriter(fields, layer.wkbType(), layer.crs()) idx = layer.fields().lookupField(fieldName) fieldType = fields[idx].type() if fieldType != QVariant.String and operator in self.STRING_OPERATORS: op = ''.join(['"%s", ' % o for o in self.STRING_OPERATORS]) raise GeoAlgorithmExecutionException( self.tr('Operators {0} can be used only with string fields.').format(op)) field_ref = QgsExpression.quotedColumnRef(fieldName) quoted_val = QgsExpression.quotedValue(value) if operator == 'is null': expr = '{} IS NULL'.format(field_ref) elif operator == 'is not null': expr = '{} IS NOT NULL'.format(field_ref) elif operator == 'begins with': expr = """%s LIKE '%s%%'""" % (field_ref, value) elif operator == 'contains': expr = """%s LIKE '%%%s%%'""" % (field_ref, value) elif operator == 'does not contain': expr = """%s NOT LIKE '%%%s%%'""" % (field_ref, value) else: expr = '{} {} {}'.format(field_ref, operator, quoted_val) expression = QgsExpression(expr) if not expression.hasParserError(): req = QgsFeatureRequest(expression) else: raise GeoAlgorithmExecutionException(expression.parserErrorString()) for f in layer.getFeatures(req): writer.addFeature(f) del writer
def displayEquipment(self): ''' Show equipment data on the canvas when selected it in the relative tab ''' typ = self.dlg.cboType.currentText() equipment = self.dlg.cboEquipment.currentText() if typ == '' or equipment == '': return # get selected item elem = self.dlg.cboEquipment.itemData(self.dlg.cboEquipment.currentIndex()) if not elem: # that means that user has edited manually the combo but the element # does not correspond to any combo element message = self.tr('Element {} does not exist'.format(equipment)) self.iface.messageBar().pushMessage(message, QgsMessageBar.WARNING, 5) return # select this feature in order to copy to memory layer aux = "id = "+str(elem[0]) expr = QgsExpression(aux) if expr.hasParserError(): self.iface.messageBar().pushMessage(expr.parserErrorString() + ": " + aux, self.app_name, QgsMessageBar.WARNING, 5) return # Get a featureIterator from an expression # Build a list of feature Ids from the previous result # Select features with the ids obtained it = self.equipmentLayer.getFeatures(QgsFeatureRequest(expr)) ids = [i.id() for i in it] self.equipmentLayer.setSelectedFeatures(ids) # Copy selected features to memory layer self.equipmentMemLayer = self.copySelected(self.equipmentLayer, self.equipmentMemLayer, "Point") # Zoom to point layer self.iface.mapCanvas().zoomScale(float(self.defaultZoomScale)) # Load style self.loadStyle(self.equipmentMemLayer, self.QML_EQUIPMENT) # Zoom to scale self.iface.mapCanvas().zoomScale(float(self.defaultZoomScale))
def virtualFields(self, params: Dict[str, str], response: QgsServerResponse, project: QgsProject) -> None: """ Get virtual fields for features In parameters: LAYER=wms-layer-name VIRTUALS={"key1": "first expression", "key2": "second expression"} // optionals FILTER=An expression to filter layer FIELDS=list of requested field separated by comma WITH_GEOMETRY=False """ layername = params.get('LAYER', '') if not layername: raise ExpressionServiceError( "Bad request error", "Invalid 'VirtualFields' REQUEST: LAYER parameter is mandatory", 400) # get layer layer = findVectorLayer(layername, project) # layer not found if not layer: raise ExpressionServiceError( "Bad request error", "Invalid LAYER parameter for 'VirtualFields': {} provided". format(layername), 400) # get virtuals virtuals = params.get('VIRTUALS', '') if not virtuals: raise ExpressionServiceError( "Bad request error", "Invalid 'VirtualFields' REQUEST: VIRTUALS parameter is mandatory", 400) # try to load virtuals dict vir_json = None try: vir_json = json.loads(virtuals) except Exception: QgsMessageLog.logMessage( "JSON loads virtuals '{}' exception:\n{}".format( virtuals, traceback.format_exc()), "lizmap", Qgis.Critical) raise ExpressionServiceError( "Bad request error", "Invalid 'VirtualFields' REQUEST: VIRTUALS '{}' are not well formed" .format(virtuals), 400) if not isinstance(vir_json, dict): raise ExpressionServiceError( "Bad request error", "Invalid 'VirtualFields' REQUEST: VIRTUALS '{}' are not well formed" .format(virtuals), 400) # create expression context exp_context = QgsExpressionContext() exp_context.appendScope(QgsExpressionContextUtils.globalScope()) exp_context.appendScope( QgsExpressionContextUtils.projectScope(project)) exp_context.appendScope(QgsExpressionContextUtils.layerScope(layer)) # create distance area context da = QgsDistanceArea() da.setSourceCrs(layer.crs(), project.transformContext()) da.setEllipsoid(project.ellipsoid()) # parse virtuals exp_map = {} exp_parser_errors = [] for k, e in vir_json.items(): exp = QgsExpression(e) exp.setGeomCalculator(da) exp.setDistanceUnits(project.distanceUnits()) exp.setAreaUnits(project.areaUnits()) if exp.hasParserError(): exp_parser_errors.append('Error "{}": {}'.format( e, exp.parserErrorString())) continue if not exp.isValid(): exp_parser_errors.append('Expression not valid "{}"'.format(e)) continue exp.prepare(exp_context) exp_map[k] = exp # expression parser errors found if exp_parser_errors: raise ExpressionServiceError( "Bad request error", "Invalid VIRTUALS for 'VirtualFields':\n{}".format( '\n'.join(exp_parser_errors)), 400) req = QgsFeatureRequest() # get filter req_filter = params.get('FILTER', '') if req_filter: req_exp = QgsExpression(req_filter) req_exp.setGeomCalculator(da) req_exp.setDistanceUnits(project.distanceUnits()) req_exp.setAreaUnits(project.areaUnits()) if req_exp.hasParserError(): raise ExpressionServiceError( "Bad request error", "Invalid FILTER for 'VirtualFields' Error \"{}\": {}". format(req_filter, req_exp.parserErrorString()), 400) if not req_exp.isValid(): raise ExpressionServiceError( "Bad request error", "Invalid FILTER for 'VirtualFields' Expression not valid \"{}\"" .format(req_filter), 400) req_exp.prepare(exp_context) req = QgsFeatureRequest(req_exp, exp_context) # With geometry withGeom = params.get('WITH_GEOMETRY', '').lower() in ['true', '1', 't'] if not withGeom: req.setFlags(QgsFeatureRequest.NoGeometry) # Fields pkAttributes = layer.primaryKeyAttributes() attributeList = [i for i in pkAttributes] fields = layer.fields() r_fields = [ f.strip() for f in params.get('FIELDS', '').split(',') if f ] for f in r_fields: attributeList.append(fields.indexOf(f)) # response response.setStatusCode(200) response.setHeader("Content-Type", "application/json") response.write('{ "type": "FeatureCollection","features":[') response.flush() jsonExporter = QgsJsonExporter(layer) if attributeList: jsonExporter.setAttributes(attributeList) separator = '' for feat in layer.getFeatures(req): fid = layername + '.' + getServerFid(feat, pkAttributes) extra = {} # Update context exp_context.setFeature(feat) exp_context.setFields(feat.fields()) # Evaluate expressions for virtual fields errors = {} for k, exp in exp_map.items(): value = exp.evaluate(exp_context) if exp.hasEvalError(): extra[k] = None errors[k] = exp.evalErrorString() else: extra[k] = json.loads(QgsJsonUtils.encodeValue(value)) errors[k] = exp.expression() response.write(separator + jsonExporter.exportFeature(feat, extra, fid)) response.flush() separator = ',\n' response.write(']}') return
def processAlgorithm(self, parameters, context, feedback): source = self.parameterAsSource(parameters, self.INPUT, context) if source is None: raise QgsProcessingException( self.invalidSourceError(parameters, self.INPUT)) name_field_name = self.parameterAsString(parameters, self.NAME_FIELD, context) elevation_field_name = self.parameterAsString(parameters, self.ELEVATION_FIELD, context) name_field_index = source.fields().lookupField(name_field_name) elevation_field_index = source.fields().lookupField( elevation_field_name) request = QgsFeatureRequest() request.setDestinationCrs(QgsCoordinateReferenceSystem('EPSG:4326'), context.transformContext()) expression_string = self.parameterAsString(parameters, self.ORDERBY_EXPRESSION, context) if expression_string: expression = QgsExpression(expression_string) if expression.hasParserError(): raise QgsProcessingException(expression.parserErrorString()) request.addOrderBy(expression_string) departure_point = QgsPointXY() destination_point = QgsPointXY() user_points = '' total = 100.0 / source.featureCount() if source.featureCount() else 0 features = source.getFeatures(request) for current, feature in enumerate(features): if feedback.isCanceled(): break if not feature.hasGeometry(): continue point = feature.geometry().asPoint() if departure_point.isEmpty(): departure_point = point destination_point = point name = 'UNTITLED' if name_field_index >= 0: name = feature[name_field_index] name = re.sub('[^0-9A-Za-z_]', '', re.sub('\s+', '_', name)) elevation = 1000.0 if elevation_field_index >= 0: elevation = feature[elevation_field_index] user_points += ' <ATCWaypoint id="{}">\n <ATCWaypointType>User</ATCWaypointType>\n <WorldPosition>{}</WorldPosition>\n </ATCWaypoint>\n'.format( name, self.formattedCoordinateElevation(point, elevation)) feedback.setProgress(int(current * total)) if departure_point.isEmpty(): raise QgsProcessingException('Error: departure point is missing') if destination_point.isEmpty(): raise QgsProcessingException('Error: destination point is missing') strips = QgsVectorLayer( os.path.join(os.path.dirname(__file__), 'data', 'strips.gpkg'), 'strips') index = QgsSpatialIndex(strips.getFeatures()) icao_index = strips.fields().lookupField('icao') name_short_index = strips.fields().lookupField('nameshort') departure_airport = self.parameterAsString(parameters, self.DEPARTURE_AIRPORT, context) if departure_airport: feature = QgsFeature() expression = QgsExpression( "icao ILIKE '{}'".format(departure_airport)) strips.getFeatures( QgsFeatureRequest(expression)).nextFeature(feature) if feature: departure_point = feature.geometry().asPoint() else: raise QgsProcessingException( 'Error: custom departure airport ICAO ID not found') destination_airport = self.parameterAsString(parameters, self.DESTINATION_AIRPORT, context) if destination_airport: feature = QgsFeature() expression = QgsExpression( "icao ILIKE '{}'".format(destination_airport)) strips.getFeatures( QgsFeatureRequest(expression)).nextFeature(feature) if feature: destination_point = feature.geometry().asPoint() else: raise QgsProcessingException( 'Error: custom destination airport ICAO ID not found') departure = '' departure_header = '' destination = '' destination_header = '' if not departure_point.isEmpty(): departure_id = index.nearestNeighbor(departure_point) feature = strips.getFeature(departure_id[0]) point = feature.geometry().asPoint() elevation = 50.0 departure = ' <ATCWaypoint id="{}">\n <ATCWaypointType>Airport</ATCWaypointType>\n <WorldPosition>{}</WorldPosition>\n <RunwayNumberFP>1</RunwayNumberFP>\n <ICAO>\n <ICAOIdent>{}</ICAOIdent>\n </ICAO>\n </ATCWaypoint>\n'.format( feature[icao_index], self.formattedCoordinateElevation(point, elevation), feature[icao_index]) departure_header = ' <DepartureID>{}</DepartureID>\n <DepartureLLA>{}</DepartureLLA>\n <DepartureName>{}</DepartureName>\n'.format( feature[icao_index], self.formattedCoordinateElevation(point, elevation), feature[name_short_index]) if not destination_point.isEmpty(): destination_id = index.nearestNeighbor(destination_point) feature = strips.getFeature(destination_id[0]) point = feature.geometry().asPoint() elevation = 50.0 destination = ' <ATCWaypoint id="{}">\n <ATCWaypointType>Airport</ATCWaypointType>\n <WorldPosition>{}</WorldPosition>\n <RunwayNumberFP>1</RunwayNumberFP>\n <ICAO>\n <ICAOIdent>{}</ICAOIdent>\n </ICAO>\n </ATCWaypoint>\n'.format( feature[icao_index], self.formattedCoordinateElevation(point, elevation), feature[icao_index]) destination_header = ' <DestinationID>{}</DestinationID>\n <DestinationLLA>{}</DestinationLLA>\n <DestinationName>{}</DestinationName>\n'.format( feature[icao_index], self.formattedCoordinateElevation(point, elevation), feature[name_short_index]) title = self.parameterAsString(parameters, self.TITLE, context) plan_file_path = self.parameterAsString(parameters, self.OUTPUT, context) plan_file = open(plan_file_path, 'w') plan_file.write( '<?xml version="1.0" encoding="UTF-8"?>\n\n<SimBase.Document Type="AceXML" version="1,0">\n <Descr>AceXML Document</Descr>\n <FlightPlan.FlightPlan>\n <Title>{}</Title>\n <FPType>IFR</FPType>\n <RouteType>LowAlt</RouteType>\n <CruisingAlt>11000.000</CruisingAlt>\n' .format(title)) plan_file.write(departure_header + destination_header) plan_file.write( ' <Descr>{}</Descr>\n <AppVersion>\n <AppVersionMajor>11</AppVersionMajor>\n <AppVersionBuild>282174</AppVersionBuild>\n </AppVersion>\n' .format(title)) plan_file.write(departure + user_points + destination) plan_file.write(' </FlightPlan.FlightPlan>\n</SimBase.Document>\n') plan_file.close() return {self.OUTPUT: plan_file_path}
def processAlgorithm(self, parameters, context, feedback): """ Here is where the processing itself takes place. """ vectorLayer = self.parameterAsVectorLayer(parameters, self.INPUT, context) expression = self.parameterAsString(parameters, self.EXPRESSION, context) expr = QgsExpression(expression) if expr.hasParserError(): raise QgsProcessingException(expr.parserErrorString()) context = QgsExpressionContext() count = vectorLayer.featureCount() if vectorLayer.featureCount() else 0 total = 100.0 / count # And now we can process attributes = [] duplicates = [] index = 0 protokoll = [] #Iterating over Vector Layer feedback.pushInfo("Processing ") iter = vectorLayer.getFeatures() for current, feature in enumerate(iter): try: #create value from Expression context.setFeature(feature) value = expr.evaluate(context) except Exception as err: msg = "Error while run Expression" + str( expr.expression()) + " on feature " + str( feature.attributes()) + ": " + str( err.args) + ";" + str(repr(err)) feedback.reportError(msg) raise QgsProcessingException(msg) try: #is the attribut in the list yet index = attributes.index(value) feedback.pushInfo("Index " + str(value) + ": " + str(index)) #index=attributes.index(feature[fidx]) except ValueError as err: # value is not in the list index = -1 #feedback.reportError( str(repr(err)) ) # "ValueError: "+str( value ) + ": " + str(err.args) + ";" + except KeyError as err: # value is not in the list index = -1 #feedback.reportError( "KeyError: "+str(value) + ": " + str(err.args) + ";" + str(repr(err)) ) if index == -1: # add new attribute in the list attributes.append(value) else: # it is a duplicate duplicates.append(feature.id()) # Update the progress bar proz = int((current + 1) * total) feedback.setProgress(proz) feedback.pushInfo(str(len(duplicates)) + " duplicates were selected!") if len(duplicates) > 0: vectorLayer.select(duplicates) return {self.OUTPUT: parameters[self.INPUT]}
def layer_value(feature, layer, defaultconfig): if not canvas: roam.utils.warning( "No canvas set for using layer_values default function") return None layers = [] # layer name can also be a list of layers to search layername = defaultconfig['layer'] if isinstance(layername, basestring): layers.append(layername) else: layers = layername expression = defaultconfig['expression'] field = defaultconfig['field'] for searchlayer in layers: try: searchlayer = QgsMapLayerRegistry.instance().mapLayersByName( searchlayer)[0] except IndexError: RoamEvents.raisemessage( "Missing layer", "Unable to find layer used in widget expression {}".format( searchlayer), level=1) roam.utils.warning( "Unable to find expression layer {}".format(searchlayer)) return if feature.geometry(): rect = feature.geometry().boundingBox() if layer.geometryType() == QGis.Point: point = feature.geometry().asPoint() rect = QgsRectangle(point.x(), point.y(), point.x() + 10, point.y() + 10) rect.scale(20) rect = canvas.mapRenderer().mapToLayerCoordinates(layer, rect) rq = QgsFeatureRequest().setFilterRect(rect)\ .setFlags(QgsFeatureRequest.ExactIntersect) features = searchlayer.getFeatures(rq) else: features = searchlayer.getFeatures() exp = QgsExpression(expression) exp.prepare(searchlayer.pendingFields()) if exp.hasParserError(): error = exp.parserErrorString() roam.utils.warning(error) for f in features: value = exp.evaluate(f) if exp.hasEvalError(): error = exp.evalErrorString() roam.utils.warning(error) if value: return f[field] raise DefaultError('No features found')
def processAlgorithm(self, parameters, context, feedback): source = self.parameterAsSource(parameters, self.INPUT, context) expressionContext = self.createExpressionContext( parameters, context, source) x_expression = self.parameterAsString(parameters, self.XEXPRESSION, context) x_expression = QgsExpression(x_expression) if x_expression.hasParserError(): x_expression.prepare(expressionContext) raise QgsProcessingException(x_expression.parserErrorString()) y_expression = self.parameterAsString(parameters, self.YEXPRESSION, context) y_expression = QgsExpression(y_expression) if y_expression.hasParserError(): y_expression.prepare(expressionContext) raise QgsProcessingException(y_expression.parserErrorString()) size = self.parameterAsDouble(parameters, self.SIZE, context) size_property = None if QgsProcessingParameters.isDynamic(parameters, "SIZE"): size_property = parameters["SIZE"] color = self.parameterAsColor(parameters, self.COLOR, context) color_property = None if QgsProcessingParameters.isDynamic(parameters, "COLOR"): color_property = parameters["COLOR"] facet_row = self.parameterAsString(parameters, self.FACET_ROW, context) facet_row_expression = QgsExpression(facet_row) if facet_row and facet_row_expression.hasParserError(): facet_row_expression.prepare(expressionContext) raise QgsProcessingException( facet_row_expression.parserErrorString()) facet_col = self.parameterAsString(parameters, self.FACET_COL, context) facet_col_expression = QgsExpression(facet_col) if facet_col and facet_col_expression.hasParserError(): facet_col_expression.prepare(expressionContext) raise QgsProcessingException( facet_col_expression.parserErrorString()) offline = self.parameterAsBool(parameters, self.OFFLINE, context) if offline is not True: offline = 'cdn' output_html = self.parameterAsFileOutput(parameters, self.OUTPUT_HTML_FILE, context) output_json = self.parameterAsFileOutput(parameters, self.OUTPUT_JSON_FILE, context) colnames = ['x', 'y', 'customdata'] data = [] request = QgsFeatureRequest() request.setFlags(QgsFeatureRequest.NoGeometry) for current, f in enumerate(source.getFeatures(request)): tl = [] expressionContext.setFeature(f) x_val = x_expression.evaluate(expressionContext) y_val = y_expression.evaluate(expressionContext) ids = f.id() tl.append(x_val) tl.append(y_val) tl.append(ids) if facet_row: facet_row_val = facet_row_expression.evaluate( expressionContext) tl.append(facet_row_val) if facet_col: facet_col_val = facet_col_expression.evaluate( expressionContext) tl.append(facet_col_val) if size_property: the_size, _ = size_property.valueAsDouble( expressionContext, size) tl.append(the_size) if color_property: the_color, _ = color_property.value(expressionContext, color) tl.append(the_color) data.append(tl) if facet_row: colnames.append('facet_row') if facet_col: colnames.append('facet_col') if size_property: colnames.append('size') if color_property: colnames.append('color') df = pd.DataFrame(data=data, columns=colnames) feedback.pushDebugInfo(f'{df}') fig = px.scatter(df, x='x', y='y', size='size' if size_property else None, color='color' if color_property else None, facet_row="facet_row" if facet_row else None, facet_col="facet_col" if facet_col else None) if size_property is None: fig.update_traces(marker_size=size) if color_property is None: fig.update_traces(marker_color=color.name()) fig.update_layout(showlegend=True) results = {} fig.write_html(output_html, include_plotlyjs=offline) results[self.OUTPUT_HTML_FILE] = output_html if output_json: fig.write_json(output_json, pretty=True) results[self.OUTPUT_JSON_FILE] = output_json return results
def responseComplete(self): ''' Send new response ''' self.handler = self.serverIface.requestHandler() params = self.handler.parameterMap( ) # Check if needed params are passed # If not, do not change QGIS Server response if params['SERVICE'].lower() != 'wms': return # Check if getprintatlas request. If not, just send the response if 'REQUEST' not in params or params['REQUEST'].lower() not in ['getprintatlas', 'getcapabilitiesatlas']: return # Get capabilities if params['REQUEST'].lower() == 'getcapabilitiesatlas': body = { 'status': 'success', 'metadata': self.metadata } self.setJsonResponse( '200', body) return # Check if needed params are set if 'TEMPLATE' not in params or 'FORMAT' not in params or 'DPI' not in params or 'MAP' not in params or 'EXP_FILTER' not in params: body = { 'status': 'fail', 'message': 'Missing parameters: TEMPLATE, FORMAT, DPI, MAP, EXP_FILTER are required ' } self.setJsonResponse( '200', body) return self.project_path = self.serverInterface().configFilePath() self.composer_name = params['TEMPLATE'] self.feature_filter = params['EXP_FILTER'] # check expression qExp = QgsExpression(self.feature_filter) if not qExp.hasParserError(): qReq = QgsFeatureRequest(qExp) qReq.setLimit(1) ok = True else: body = { 'status': 'fail', 'message': 'An error occured while parsing the given expression: %s' % qExp.parserErrorString() } syslog.syslog(syslog.LOG_ERR, "ATLAS - ERROR EXPRESSION: %s" % qExp.parserErrorString()) self.setJsonResponse( '200', body) return try: pdf = self.print_atlas( project_path=self.project_path, composer_name=self.composer_name, predefined_scales=self.predefined_scales, feature_filter=self.feature_filter ) except: pdf = None if not pdf: body = { 'status': 'fail', 'message': 'ATLAS - Error while generating the PDF' } QgsMessageLog.logMessage("ATLAS - No PDF generated in %s" % pdf, 'atlasprint', Qgis.Info) self.setJsonResponse( '200', body) return # Send PDF self.handler.clear() self.handler.setResponseHeader('Content-type', 'application/pdf') self.handler.setResponseHeader('Status', '200') try: with open(pdf, 'rb') as f: loads = f.readlines() ba = QByteArray(b''.join(loads)) self.handler.appendBody(ba) except: body = { 'status': 'fail', 'message': 'Error occured while reading PDF file', } self.setJsonResponse( '200', body) finally: os.remove(pdf) return
def processAlgorithm(self, parameters, 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(context.project().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(context.project().distanceUnits()) expression.setAreaUnits(context.project().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, QgsFeatureSink.FastInsert) 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())))
def processAlgorithm(self, feedback): layer = self.getParameterValue(self.INPUT_LAYER) mapping = self.getParameterValue(self.FIELDS_MAPPING) output = self.getOutputFromName(self.OUTPUT_LAYER) layer = dataobjects.getObjectFromUri(layer) fields = [] expressions = [] da = QgsDistanceArea() da.setSourceCrs(layer.crs()) da.setEllipsoidalMode(True) da.setEllipsoid(QgsProject.instance().readEntry( 'Measure', '/Ellipsoid', GEO_NONE)[0]) exp_context = layer.createExpressionContext() 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']) 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( unicode(expression.expression()), unicode(expression.parserErrorString()))) expressions.append(expression) writer = output.getVectorWriter(fields, layer.wkbType(), layer.crs()) # Create output vector layer with new attributes error_exp = None inFeat = QgsFeature() outFeat = QgsFeature() features = vector.features(layer) total = 100.0 / len(features) 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)) del writer if error_exp is not None: raise GeoAlgorithmExecutionException( self.tr(u'Evaluation error in expression "{}": {}').format( unicode(error_exp.expression()), unicode(error_exp.parserErrorString())))
class GeometryByExpression(QgisFeatureBasedAlgorithm): OUTPUT_GEOMETRY = 'OUTPUT_GEOMETRY' WITH_Z = 'WITH_Z' WITH_M = 'WITH_M' EXPRESSION = 'EXPRESSION' def group(self): return self.tr('Vector geometry') def groupId(self): return 'vectorgeometry' def __init__(self): super().__init__() self.geometry_types = [self.tr('Polygon'), 'Line', 'Point'] def initParameters(self, config=None): self.addParameter( QgsProcessingParameterEnum(self.OUTPUT_GEOMETRY, self.tr('Output geometry type'), options=self.geometry_types, defaultValue=0)) self.addParameter( QgsProcessingParameterBoolean( self.WITH_Z, self.tr('Output geometry has z dimension'), defaultValue=False)) self.addParameter( QgsProcessingParameterBoolean( self.WITH_M, self.tr('Output geometry has m values'), defaultValue=False)) self.addParameter( QgsProcessingParameterExpression(self.EXPRESSION, self.tr("Geometry expression"), defaultValue='$geometry', parentLayerParameterName='INPUT')) def name(self): return 'geometrybyexpression' def displayName(self): return self.tr('Geometry by expression') def outputName(self): return self.tr('Modified geometry') def prepareAlgorithm(self, parameters, context, feedback): self.geometry_type = self.parameterAsEnum(parameters, self.OUTPUT_GEOMETRY, context) self.wkb_type = None if self.geometry_type == 0: self.wkb_type = QgsWkbTypes.Polygon elif self.geometry_type == 1: self.wkb_type = QgsWkbTypes.LineString else: self.wkb_type = QgsWkbTypes.Point if self.parameterAsBool(parameters, self.WITH_Z, context): self.wkb_type = QgsWkbTypes.addZ(self.wkb_type) if self.parameterAsBool(parameters, self.WITH_M, context): self.wkb_type = QgsWkbTypes.addM(self.wkb_type) self.expression = QgsExpression( self.parameterAsString(parameters, self.EXPRESSION, context)) if self.expression.hasParserError(): feedback.reportError(self.expression.parserErrorString()) return False self.expression_context = self.createExpressionContext( parameters, context) self.expression.prepare(self.expression_context) return True def outputWkbType(self, input_wkb_type): return self.wkb_type def inputLayerTypes(self): return [QgsProcessing.TypeVector] def sourceFlags(self): return QgsProcessingFeatureSource.FlagSkipGeometryValidityChecks def processFeature(self, feature, context, feedback): self.expression_context.setFeature(feature) value = self.expression.evaluate(self.expression_context) if self.expression.hasEvalError(): raise QgsProcessingException( self.tr('Evaluation error: {0}').format( self.expression.evalErrorString())) if not value: feature.setGeometry(QgsGeometry()) else: if not isinstance(value, QgsGeometry): raise QgsProcessingException( self.tr('{} is not a geometry').format(value)) feature.setGeometry(value) return [feature]
def get_print(self, params: Dict[str, str], response: QgsServerResponse, project: QgsProject) -> None: """ Get print document """ template = params.get('TEMPLATE') feature_filter = params.get('EXP_FILTER', None) scale = params.get('SCALE') scales = params.get('SCALES') output_format = parse_output_format( params.get('FORMAT', params.get('format'))) try: if not template: raise AtlasPrintException('TEMPLATE is required') if feature_filter: expression = QgsExpression(feature_filter) if expression.hasParserError(): raise AtlasPrintException( 'Expression is invalid: {}'.format( expression.parserErrorString())) if scale and scales: raise AtlasPrintException( 'SCALE and SCALES can not be used together.') if scale: try: scale = int(scale) except ValueError: raise AtlasPrintException('Invalid number in SCALE.') if scales: try: scales = [int(scale) for scale in scales.split(',')] except ValueError: raise AtlasPrintException('Invalid number in SCALES.') additional_params = { k: v for k, v in params.items() if k not in ('TEMPLATE', 'EXP_FILTER', 'SCALE', 'SCALES', 'FORMAT', 'MAP', 'REQUEST', 'SERVICE') } output_path = print_layout(project=project, layout_name=params['TEMPLATE'], output_format=output_format, scale=scale, scales=scales, feature_filter=feature_filter, **additional_params) except AtlasPrintException as e: raise AtlasPrintError( 400, 'ATLAS - Error from the user while generating the PDF: {}'. format(e)) except Exception: self.logger.critical("Unhandled exception:\n{}".format( traceback.format_exc())) raise AtlasPrintError(500, "Internal 'atlasprint' service error") path = Path(output_path) if not path.exists(): raise AtlasPrintError( 404, "ATLAS {} not found".format(output_format.name)) # Send PDF response.setHeader('Content-Type', output_format.value) response.setStatusCode(200) try: response.write(path.read_bytes()) path.unlink() except Exception: self.logger.critical("Error occurred while reading {} file".format( output_format.name)) raise
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)
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) fields = [] expressions = [] da = QgsDistanceArea() da.setSourceCrs(layer.crs().srsid()) da.setEllipsoidalMode( iface.mapCanvas().mapSettings().hasCrsTransformEnabled()) da.setEllipsoid(QgsProject.instance().readEntry( 'Measure', '/Ellipsoid', GEO_NONE)[0]) exp_context = QgsExpressionContext() exp_context.appendScope(QgsExpressionContextUtils.globalScope()) exp_context.appendScope(QgsExpressionContextUtils.projectScope()) exp_context.appendScope(QgsExpressionContextUtils.layerScope(layer)) 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']) expression.setGeomCalculator(da) expression.setDistanceUnits(QgsProject.instance().distanceUnits()) expression.setAreaUnits(QgsProject.instance().areaUnits()) if expression.hasParserError(): raise GeoAlgorithmExecutionException( self.tr(u'Parser error in expression "{}": {}').format( str(field_def['expression']), str(expression.parserErrorString()))) expression.prepare(exp_context) if expression.hasEvalError(): raise GeoAlgorithmExecutionException( self.tr(u'Evaluation error in expression "{}": {}').format( str(field_def['expression']), str(expression.evalErrorString()))) expressions.append(expression) writer = output.getVectorWriter(fields, layer.wkbType(), layer.crs()) # Create output vector layer with new attributes error = '' calculationSuccess = True inFeat = QgsFeature() outFeat = QgsFeature() features = vector.features(layer) total = 100.0 / len(features) 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(): calculationSuccess = False error = expression.evalErrorString() break attrs.append(value) outFeat.setAttributes(attrs) writer.addFeature(outFeat) progress.setPercentage(int(current * total)) del writer if not calculationSuccess: raise GeoAlgorithmExecutionException( self.tr('An error occurred while evaluating the calculation' ' string:\n') + error)
def processAlgorithm(self, parameters, context, feedback): source = self.parameterAsSource(parameters, self.INPUT, context) layer = self.parameterAsVectorLayer(parameters, self.INPUT, context) field_name = self.parameterAsString(parameters, self.FIELD_NAME, context) field_type = self.TYPES[self.parameterAsEnum(parameters, self.FIELD_TYPE, context)] width = self.parameterAsInt(parameters, self.FIELD_LENGTH, context) precision = self.parameterAsInt(parameters, self.FIELD_PRECISION, context) new_field = self.parameterAsBool(parameters, self.NEW_FIELD, context) formula = self.parameterAsString(parameters, self.FORMULA, context) expression = QgsExpression(formula) da = QgsDistanceArea() da.setSourceCrs(source.sourceCrs()) da.setEllipsoid(context.project().ellipsoid()) expression.setGeomCalculator(da) expression.setDistanceUnits(context.project().distanceUnits()) expression.setAreaUnits(context.project().areaUnits()) fields = source.fields() field_index = fields.lookupField(field_name) if new_field or field_index < 0: fields.append( QgsField(field_name, field_type, '', width, precision)) (sink, dest_id) = self.parameterAsSink(parameters, self.OUTPUT, context, fields, source.wkbType(), source.sourceCrs()) exp_context = self.createExpressionContext(parameters, context) if layer is not None: exp_context.appendScope( QgsExpressionContextUtils.layerScope(layer)) if not expression.prepare(exp_context): raise QgsProcessingException( self.tr('Evaluation error: {0}').format( expression.parserErrorString())) features = source.getFeatures() total = 100.0 / source.featureCount() if source.featureCount() else 0 for current, f in enumerate(features): if feedback.isCanceled(): break rownum = current + 1 exp_context.setFeature(f) exp_context.lastScope().setVariable("row_number", rownum) value = expression.evaluate(exp_context) if expression.hasEvalError(): feedback.reportError(expression.evalErrorString()) else: attrs = f.attributes() if new_field or field_index < 0: attrs.append(value) else: attrs[field_index] = value f.setAttributes(attrs) sink.addFeature(f, QgsFeatureSink.FastInsert) feedback.setProgress(int(current * total)) return {self.OUTPUT: dest_id}
def processAlgorithm(self, parameters, context, feedback): """ Here is where the processing itself takes place. """ ueberhoehung = self.parameterAsDouble(parameters, self.INPUTZFACTOR, context) baseLineLayer = self.parameterAsVectorLayer(parameters, self.INPUTBASELINE, context) vectorLayer = self.parameterAsVectorLayer(parameters, self.INPUTVECTORLAYER, context) baselineIDFieldName = self.parameterAsExpression( parameters, self.PROFIL_BASELINE_ID, context) offsetFieldName = self.parameterAsString(parameters, self.OFFSETFIELD, context) vectorLayerBaselineIDFieldName = self.parameterAsExpression( parameters, self.INPUTVECTORLAYER_BASLINE_ID, context) outputGeomType = vectorLayer.wkbType() #Output Geometry Type Point offsetExpr = QgsExpression(offsetFieldName) if offsetExpr.hasParserError(): feedback.reportError("Offset Expression failed: " + offsetExpr.parserErrorString()) offsetExpr = "0" # Retrieve the feature source and sink. The 'dest_id' variable is used # to uniquely identify the feature sink, and must be included in the # dictionary returned by the processAlgorithm function. fields = vectorLayer.fields() #fields.append( QgsField( "station" , QVariant.Double ) ) # will be added and filled by Subprocess (algorithm_TransformToProfil_LineIntersection.py) #.append( QgsField( "abstand" , QVariant.Double ) ) # will be added and filled by Subprocess (algorithm_TransformToProfil_LineIntersection.py) #fields.append( QgsField( "z_factor" , QVariant.Int ) ) # will be added and filled by Subprocess (algorithm_TransformToProfil_LineIntersection.py) #fields.append( QgsField( "profil_id" , QVariant.Int ) ) if vectorLayer is None: raise QgsProcessingException( self.invalidSourceError(parameters, self.INPUTVECTORLAYER)) if vectorLayer is None: raise QgsProcessingException( self.invalidSourceError(parameters, self.OUTPUT)) #check if vectorlayer has Features if vectorLayer.featureCount() == 0: msg = self.tr("Error: Layer ", vectorLayer.name(), "is emty! ") feedback.reportError(msg) raise QgsProcessingException(msg) #check if baselineLayer has Features if baseLineLayer.featureCount() == 0: msg = self.tr("Error: Layer ", baseLineLayer.name(), "is emty! ") feedback.reportError(msg) raise QgsProcessingException(msg) #take CRS from Project crsProject = QgsProject.instance().crs() (sink, dest_id) = self.parameterAsSink(parameters, self.OUTPUT, context, fields, outputGeomType, vectorLayer.sourceCrs()) # If sink was not created, throw an exception to indicate that the algorithm # encountered a fatal error. The exception text can be any string, but in this # case we use the pre-built invalidSinkError method to return a standard # helper text for when a sink cannot be evaluated if sink is None: raise QgsProcessingException( self.invalidSinkError(parameters, self.OUTPUT)) offsetExprContext = QgsExpressionContext() # Send some information to the user #feedback.pushInfo('CRS is {}'.format(vectorLayer.sourceCrs().authid())) features = [] #QgsFeatureIterator if len(vectorLayer.selectedFeatures()) > 0: features = vectorLayer.selectedFeatures() else: features = [feat for feat in vectorLayer.getFeatures()] feedback.pushInfo('Features {} used'.format(len(features))) # Compute the number of steps to display within the progress bar and # get features from source total = 100.0 / len(features) if len(features) else 0 #names = [field.name()+"; " for field in fields] #feedback.pushInfo(''.join( names ) ) #Clear Selection vectorLayer.removeSelection() i = 0 for current, feature in enumerate(features): try: # Stop the algorithm if cancel button has been clicked if feedback.isCanceled(): break # Offset abstand = 0 offsetExprContext.setFeature(feature) try: abstand = offsetExpr.evaluate(offsetExprContext) except: msg = self.tr( "Error while calculating Offset from Expression. Feature " + str(feat.attributes())) feedback.reportError(msg) raise QgsProcessingException(msg) try: #check for numeric Expression Data type a = int(abstand) b = float(abstand) except: msg = self.tr( "Feature(" + feature.id() + "): " + "Error Offset Experession result must be numeric, not " + str(type(abstand))) feedback.reportError(msg) raise QgsProcessingException(msg) # get Profile Baseline by ID #profil_id of the profile feature expr = QgsExpression(vectorLayerBaselineIDFieldName) exprContext = QgsExpressionContext() exprContext.setFeature(feature) profil_id = expr.evaluate(exprContext) # baseline ID exprBaseLineID = QgsExpression(baselineIDFieldName) # remove quotes "" if baselineIDFieldName.startswith('\"'): baselineIDFieldName = baselineIDFieldName.replace('\"', '') exprText = baselineIDFieldName + '=' + str(profil_id) #feedback.pushInfo('waehle Basislinie: ' + exprText ) exprBaseLine = QgsExpression(exprText) selection = baseLineLayer.getFeatures( QgsFeatureRequest(exprBaseLine)) baseLineFeature = next(selection) linRef = LinearReferencingMaschine(baseLineFeature.geometry(), crsProject, feedback) #feedback.pushInfo("Profil_id: " + str( profil_id ) + ' feature: ' + str( feature.attributes() ) ) geom = feature.geometry() feedback.pushInfo("srcgeom: " + str(geom.asWkt())) subFeatureList = [] layerUtils = LayerUtils(crsProject, feedback) subFeatureList = layerUtils.multiPartToSinglePartFeature( feature) feedback.pushInfo("subFeatureList: " + str(len(subFeatureList))) #preparation of profile geometrys prepSubFeatureList = [] for iP, f in enumerate(subFeatureList): if linRef.isSimpleLine or vectorLayer.geometryType( ) == 0 or vectorLayer.geometryType( ) == 1: #Point (Line nur temporär): prepSubFeatureList.append(f) #keep old feature else: # Basisline hat Knickpunkte, Profilgeometrien müssen ggf. mit zusätzlichen Stützpunkten gefüllt werden # Baseline has breakpoints, we have to fill the profile geometrys with additional vertices filledSingleGeom = None if vectorLayer.geometryType() == 2: #Polygon filledSingleGeomList = self.fillPolygonVertices( f.geometry(), linRef, crsProject, feedback) #elif vectorLayer.geometryType() == 1: #Line if len(filledSingleGeomList) > 0: for g in filledSingleGeomList: #create a feature for each filled sub geometry filledFeature = QgsFeature(f) filledFeature.setGeometry(g) filledFeature.setAttributes(f.attributes()) prepSubFeatureList.append(filledFeature) else: prepSubFeatureList.append(f) #keep old feature feedback.reportError( "Feature geometry can not be filled: " + str(f.attributes())) feedback.pushInfo("prepSubFeatureList: " + str(len(prepSubFeatureList))) #Back to Real World Transformation for each sub Feature realWorldSubFeatureList = [] for pFeat in prepSubFeatureList: #Create Real World geometry with LinearReferencingMaschine realWorldFeat = linRef.transformProfileFeatureToRealWorld( pFeat, vectorLayer.crs(), feedback, abstand, ueberhoehung) realWorldSubFeatureList.append(realWorldFeat) feedback.pushInfo(str(realWorldFeat.geometry().asWkt())) ##### ggf features könnten hier wieder gruppiert werden ###### #write real worl Features to output layer for rwFeat in realWorldSubFeatureList: sink.addFeature(rwFeat, QgsFeatureSink.FastInsert) i = i + 1 # Update the progress bar feedback.setProgress(int(i * total)) except: msg = self.tr("Error on Feature " + str(i) + " " + str(feature.attributes())) feedback.reportError(msg) raise QgsProcessingException(msg) msgInfo = self.tr( str(i) + " Features were transformed to real world coordinates") feedback.pushInfo(msgInfo) # Return the results of the algorithm. In this case our only result is return {self.OUTPUT: dest_id} # # print("ERROR:", err.args, repr( err ), "Fehler: " ) # To run another Processing algorithm as part of this algorithm, you can use # processing.run(...). Make sure you pass the current context and feedback # to processing.run to ensure that all temporary layer outputs are available # to the executed algorithm, and that the executed algorithm can send feedback # reports to the user (and correctly handle cancelation and progress reports!) # Return the results of the algorithm. In this case our only result is # the feature sink which contains the processed features, but some # algorithms may return multiple feature sinks, calculated numeric # statistics, etc. These should all be included in the returned # dictionary, with keys matching the feature corresponding parameter # or output names. feedback.pushInfo(str(counter) + " Profile Baslines processed") return {self.OUTPUT: dest_id}
def print_layout(project, layout_name, feature_filter: str = None, scales=None, scale=None, **kwargs): """Generate a PDF for an atlas or a report. :param project: The QGIS project. :type project: QgsProject :param layout_name: Name of the layout of the atlas or report. :type layout_name: basestring :param feature_filter: QGIS Expression to use to select the feature. It can return many features, a multiple pages PDF will be returned. This is required to print atlas, not report :type feature_filter: basestring :param scale: A scale to force in the atlas context. Default to None. :type scale: int :param scales: A list of predefined list of scales to force in the atlas context. Default to None. :type scales: list :return: Path to the PDF. :rtype: basestring """ canvas = QgsMapCanvas() bridge = QgsLayerTreeMapCanvasBridge(project.layerTreeRoot(), canvas) bridge.setCanvasLayers() manager = project.layoutManager() master_layout = manager.layoutByName(layout_name) settings = QgsLayoutExporter.PdfExportSettings() atlas = None atlas_layout = None report_layout = None logger = Logger() if not master_layout: raise AtlasPrintException('Layout `{}` not found'.format(layout_name)) if master_layout.layoutType() == QgsMasterLayoutInterface.PrintLayout: for _print_layout in manager.printLayouts(): if _print_layout.name() == layout_name: atlas_layout = _print_layout break atlas = atlas_layout.atlas() if not atlas.enabled(): raise AtlasPrintException('The layout is not enabled for an atlas') layer = atlas.coverageLayer() if feature_filter is None: raise AtlasPrintException( 'EXP_FILTER is mandatory to print an atlas layout') feature_filter = optimize_expression(layer, feature_filter) expression = QgsExpression(feature_filter) if expression.hasParserError(): raise AtlasPrintException( 'Expression is invalid, parser error: {}'.format( expression.parserErrorString())) context = QgsExpressionContext() context.appendScope(QgsExpressionContextUtils.globalScope()) context.appendScope(QgsExpressionContextUtils.projectScope(project)) context.appendScope( QgsExpressionContextUtils.layoutScope(atlas_layout)) context.appendScope(QgsExpressionContextUtils.atlasScope(atlas)) context.appendScope(QgsExpressionContextUtils.layerScope(layer)) expression.prepare(context) if expression.hasEvalError(): raise AtlasPrintException( 'Expression is invalid, eval error: {}'.format( expression.evalErrorString())) atlas.setFilterFeatures(True) atlas.setFilterExpression(feature_filter) if scale: atlas_layout.referenceMap().setAtlasScalingMode( QgsLayoutItemMap.Fixed) atlas_layout.referenceMap().setScale(scale) if scales: atlas_layout.referenceMap().setAtlasScalingMode( QgsLayoutItemMap.Predefined) if Qgis.QGIS_VERSION_INT >= 30900: settings.predefinedMapScales = scales else: atlas_layout.reportContext().setPredefinedScales(scales) if not scales and atlas_layout.referenceMap().atlasScalingMode( ) == QgsLayoutItemMap.Predefined: if Qgis.QGIS_VERSION_INT >= 30900: use_project = project.useProjectScales() map_scales = project.mapScales() else: map_scales = project_scales(project) use_project = len(map_scales) == 0 if not use_project or len(map_scales) == 0: logger.info( 'Map scales not found in project, fetching predefined map scales in global config' ) map_scales = global_scales() if Qgis.QGIS_VERSION_INT >= 30900: settings.predefinedMapScales = map_scales else: atlas_layout.reportContext().setPredefinedScales(map_scales) elif master_layout.layoutType() == QgsMasterLayoutInterface.Report: report_layout = master_layout else: raise AtlasPrintException('The layout is not supported by the plugin') for key, value in kwargs.items(): found = False if atlas_layout: item = atlas_layout.itemById(key.lower()) if isinstance(item, QgsLayoutItemLabel): item.setText(value) found = True logger.info( 'Additional parameters: {} found in layout {}, value {}'.format( key, found, value)) export_path = os.path.join( tempfile.gettempdir(), '{}_{}.pdf'.format(clean_string(layout_name), uuid4())) result, error = QgsLayoutExporter.exportToPdf(atlas or report_layout, export_path, settings) if result != QgsLayoutExporter.Success: raise Exception('Export not generated in QGIS exporter {} : {}'.format( export_path, error)) if not os.path.isfile(export_path): raise Exception( 'Export OK from QGIS, but file not found on the file system : {}'. format(export_path)) return export_path
def getFeatureWithFormScope(self, params: Dict[str, str], response: QgsServerResponse, project: QgsProject) -> None: """ Get filtered features with a form scope In parameters: LAYER=wms-layer-name FILTER=An expression to filter layer FORM_FEATURE={"type": "Feature", "geometry": {}, "properties": {}} // optionals FIELDS=list of requested field separated by comma WITH_GEOMETRY=False """ layername = params.get('LAYER', '') if not layername: raise ExpressionServiceError( "Bad request error", "Invalid 'GetFeatureWithFormScope' REQUEST: LAYER parameter is mandatory", 400) # get layer layer = findVectorLayer(layername, project) # layer not found if not layer: raise ExpressionServiceError( "Bad request error", "Invalid LAYER parameter for 'VirtualField': {} provided". format(layername), 400) # get filter exp_filter = params.get('FILTER', '') if not exp_filter: raise ExpressionServiceError( "Bad request error", "Invalid 'GetFeatureWithFormScope' REQUEST: FILTER parameter is mandatory", 400) # get form feature form_feature = params.get('FORM_FEATURE', '') if not form_feature: raise ExpressionServiceError( "Bad request error", "Invalid 'GetFeatureWithFormScope' REQUEST: FORM_FEATURE parameter is mandatory", 400) # Check features geojson = {} try: geojson = json.loads(form_feature) except Exception: QgsMessageLog.logMessage( "JSON loads form feature '{}' exception:\n{}".format( form_feature, traceback.format_exc()), "lizmap", Qgis.Critical) raise ExpressionServiceError( "Bad request error", "Invalid 'GetFeatureWithFormScope' REQUEST: FORM_FEATURE '{}' are not well formed" .format(form_feature), 400) if not geojson or not isinstance(geojson, dict): raise ExpressionServiceError( "Bad request error", "Invalid 'GetFeatureWithFormScope' REQUEST: FORM_FEATURE '{}' are not well formed" .format(form_feature), 400) if ('type' not in geojson) or geojson['type'] != 'Feature': raise ExpressionServiceError( "Bad request error", "Invalid 'GetFeatureWithFormScope' REQUEST: FORM_FEATURE '{}' are not well formed: type not defined or not Feature." .format(form_feature), 400) # try to load form feature # read fields form_feature_fields = QgsJsonUtils.stringToFields( form_feature, QTextCodec.codecForName("UTF-8")) # read features form_feature_list = QgsJsonUtils.stringToFeatureList( form_feature, form_feature_fields, QTextCodec.codecForName("UTF-8")) # features not well formed if not form_feature_list: raise ExpressionServiceError( "Bad request error", "Invalid FORM_FEATURE for 'GetFeatureWithFormScope': not GeoJSON feature provided\n{}" .format(form_feature), 400) if len(form_feature_list) != 1: raise ExpressionServiceError( "Bad request error", "Invalid FORM_FEATURE for 'GetFeatureWithFormScope': not GeoJSON feature provided\n{}" .format(form_feature), 400) # Get the form feature form_feat = form_feature_list[0] # create expression context exp_context = QgsExpressionContext() exp_context.appendScope(QgsExpressionContextUtils.globalScope()) exp_context.appendScope( QgsExpressionContextUtils.projectScope(project)) exp_context.appendScope(QgsExpressionContextUtils.layerScope(layer)) exp_context.appendScope(QgsExpressionContextUtils.formScope(form_feat)) # create distance area context da = QgsDistanceArea() da.setSourceCrs(layer.crs(), project.transformContext()) da.setEllipsoid(project.ellipsoid()) # Get filter expression exp_f = QgsExpression(exp_filter) exp_f.setGeomCalculator(da) exp_f.setDistanceUnits(project.distanceUnits()) exp_f.setAreaUnits(project.areaUnits()) if exp_f.hasParserError(): raise ExpressionServiceError( "Bad request error", "Invalid FILTER for 'GetFeatureWithFormScope': Error \"{}\": {}" .format(exp_filter, exp_f.parserErrorString()), 400) if not exp_f.isValid(): raise ExpressionServiceError( "Bad request error", "Invalid FILTER for 'GetFeatureWithFormScope': Expression not valid \"{}\"" .format(exp_filter), 400) exp_f.prepare(exp_context) req = QgsFeatureRequest(exp_f, exp_context) # With geometry withGeom = params.get('WITH_GEOMETRY', '').lower() in ['true', '1', 't'] if not withGeom: req.setFlags(QgsFeatureRequest.NoGeometry) # Fields pkAttributes = layer.primaryKeyAttributes() attributeList = [i for i in pkAttributes] fields = layer.fields() r_fields = [ f.strip() for f in params.get('FIELDS', '').split(',') if f ] for f in r_fields: attributeList.append(fields.indexOf(f)) # response response.setStatusCode(200) response.setHeader("Content-Type", "application/json") response.write('{ "type": "FeatureCollection","features":[') response.flush() jsonExporter = QgsJsonExporter(layer) if attributeList: jsonExporter.setAttributes(attributeList) separator = '' for feat in layer.getFeatures(req): fid = layername + '.' + getServerFid(feat, pkAttributes) response.write(separator + jsonExporter.exportFeature(feat, {}, fid)) response.flush() separator = ',\n' response.write(']}') return
def _buildfromlayer(self, widget, layerconfig): layername = layerconfig['layer'] keyfield = layerconfig['key'] valuefield = layerconfig['value'] filterexp = layerconfig.get('filter', None) try: layer = QgsMapLayerRegistry.instance().mapLayersByName( layername)[0] except IndexError: roam.utils.warning( "Can't find layer {} in project".format(layername)) return keyfieldindex = layer.fieldNameIndex(keyfield) valuefieldindex = layer.fieldNameIndex(valuefield) if keyfieldindex == -1 or valuefieldindex == -1: roam.utils.warning("Can't find key or value column") return if self.allownulls: item = QStandardItem('(no selection)') item.setData(None, Qt.UserRole) self.listmodel.appendRow(item) attributes = {keyfieldindex, valuefieldindex} iconfieldindex = layer.fieldNameIndex('icon') if iconfieldindex > -1: attributes.add(iconfieldindex) if not filterexp and valuefieldindex == keyfieldindex and iconfieldindex == -1: values = layer.uniqueValues(keyfieldindex) for value in values: value = nullconvert(value) item = QStandardItem(value) item.setData(value, Qt.UserRole) self.listmodel.appendRow(item) return flags = QgsFeatureRequest.NoGeometry expression = None if filterexp: expression = QgsExpression(filterexp) expression.prepare(layer.pendingFields()) if expression.hasParserError(): roam.utils.warning("Expression has parser error: {}".format( expression.parserErrorString())) return if expression.needsGeometry(): flags = QgsFeatureRequest.NoFlags for field in expression.referencedColumns(): index = layer.fieldNameIndex(field) attributes.add(index) request = QgsFeatureRequest().setFlags(flags).setSubsetOfAttributes( list(attributes)) for feature in layer.getFeatures(request): if expression and not expression.evaluate(feature): continue keyvalue = nullconvert(feature[keyfieldindex]) valuvalue = nullconvert(feature[valuefield]) try: path = feature[iconfieldindex] icon = QIcon(path) except KeyError: icon = QIcon() item = QStandardItem(unicode(keyvalue)) item.setData(unicode(valuvalue), Qt.UserRole) item.setIcon(icon) self.listmodel.appendRow(item)
def evaluate(self, params: Dict[str, str], response: QgsServerResponse, project: QgsProject) -> None: """ Evaluate expressions against layer or features In parameters: LAYER=wms-layer-name EXPRESSION=An expression to evaluate or EXPRESSIONS=["first expression", "second expression"] or EXPRESSIONS={"key1": "first expression", "key2": "second expression"} // optionals FEATURE={"type": "Feature", "geometry": {}, "properties": {}} or FEATURES=[{"type": "Feature", "geometry": {}, "properties": {}}, {"type": "Feature", "geometry": {}, "properties": {}}] FORM_SCOPE=boolean to add formScope based on provided features """ layername = params.get('LAYER', '') if not layername: raise ExpressionServiceError( "Bad request error", "Invalid 'Evaluate' REQUEST: LAYER parameter is mandatory", 400) # get layer layer = findVectorLayer(layername, project) # layer not found if not layer: raise ExpressionServiceError( "Bad request error", "Invalid LAYER parameter for 'Evaluate': {} provided".format( layername), 400) # get expressions expressions = params.get('EXPRESSIONS', '') if not expressions: expression = params.get('EXPRESSION', '') if not expression: raise ExpressionServiceError( "Bad request error", "Invalid 'Evaluate' REQUEST: EXPRESSION or EXPRESSIONS parameter is mandatory", 400) expressions = '["{}"]'.format(expression) # try to load expressions list or dict exp_json = None try: exp_json = json.loads(expressions) except Exception: QgsMessageLog.logMessage( "JSON loads expressions '{}' exception:\n{}".format( expressions, traceback.format_exc()), "lizmap", Qgis.Critical) raise ExpressionServiceError( "Bad request error", "Invalid 'Evaluate' REQUEST: EXPRESSIONS '{}' are not well formed" .format(expressions), 400) # create expression context exp_context = QgsExpressionContext() exp_context.appendScope(QgsExpressionContextUtils.globalScope()) exp_context.appendScope( QgsExpressionContextUtils.projectScope(project)) exp_context.appendScope(QgsExpressionContextUtils.layerScope(layer)) # create distance area context da = QgsDistanceArea() da.setSourceCrs(layer.crs(), project.transformContext()) da.setEllipsoid(project.ellipsoid()) # parse expressions exp_map = {} exp_parser_errors = [] exp_items = [] if isinstance(exp_json, list): exp_items = enumerate(exp_json) elif isinstance(exp_json, dict): exp_items = exp_json.items() for k, e in exp_items: exp = QgsExpression(e) exp.setGeomCalculator(da) exp.setDistanceUnits(project.distanceUnits()) exp.setAreaUnits(project.areaUnits()) if exp.hasParserError(): exp_parser_errors.append('Error "{}": {}'.format( e, exp.parserErrorString())) continue if not exp.isValid(): exp_parser_errors.append('Expression not valid "{}"'.format(e)) continue exp.prepare(exp_context) exp_map[k] = exp # expression parser errors found if exp_parser_errors: raise ExpressionServiceError( "Bad request error", "Invalid EXPRESSIONS for 'Evaluate':\n{}".format( '\n'.join(exp_parser_errors)), 400) # get features features = params.get('FEATURES', '') if not features: feature = params.get('FEATURE', '') if feature: features = '[' + feature + ']' # create the body body = { 'status': 'success', 'results': [], 'errors': [], 'features': 0 } # without features just evaluate expression with layer context if not features: result = {} error = {} for k, exp in exp_map.items(): value = exp.evaluate(exp_context) if exp.hasEvalError(): result[k] = None error[k] = exp.evalErrorString() else: result[k] = json.loads(QgsJsonUtils.encodeValue(value)) body['results'].append(result) body['errors'].append(error) write_json_response(body, response) return # Check features geojson = [] try: geojson = json.loads(features) except Exception: QgsMessageLog.logMessage( "JSON loads features '{}' exception:\n{}".format( features, traceback.format_exc()), "lizmap", Qgis.Critical) raise ExpressionServiceError( "Bad request error", "Invalid 'Evaluate' REQUEST: FEATURES '{}' are not well formed" .format(features), 400) if not geojson or not isinstance(geojson, list) or len(geojson) == 0: raise ExpressionServiceError( "Bad request error", "Invalid 'Evaluate' REQUEST: FEATURES '{}' are not well formed" .format(features), 400) if ('type' not in geojson[0]) or geojson[0]['type'] != 'Feature': raise ExpressionServiceError( "Bad request error", "Invalid 'Evaluate' REQUEST: FEATURES '{}' are not well formed: type not defined or not Feature." .format(features), 400) # try to load features # read fields feature_fields = QgsJsonUtils.stringToFields( '{ "type": "FeatureCollection","features":' + features + '}', QTextCodec.codecForName("UTF-8")) # read features feature_list = QgsJsonUtils.stringToFeatureList( '{ "type": "FeatureCollection","features":' + features + '}', feature_fields, QTextCodec.codecForName("UTF-8")) # features not well formed if not feature_list: raise ExpressionServiceError( "Bad request error", "Invalid FEATURES for 'Evaluate': not GeoJSON features array provided\n{}" .format(features), 400) # Extend layer fields with this provided in GeoJSON Features feat_fields = QgsFields(layer.fields()) feat_fields.extend(feature_fields) # form scope addFormScope = params.get('FORM_SCOPE', '').lower() in ['true', '1', 't'] # loop through provided features to evaluate expressions for f in feature_list: # clone the features with all attributes # those defined in layer + fields from GeoJSON Features feat = QgsFeature(feat_fields) feat.setGeometry(f.geometry()) for field in f.fields(): fname = field.name() if feat_fields.indexOf(fname) != -1: feat.setAttribute(fname, f[fname]) # Add form scope to expression context if addFormScope: exp_context.appendScope( QgsExpressionContextUtils.formScope(feat)) exp_context.setFeature(feat) exp_context.setFields(feat.fields()) # Evaluate expressions with the new feature result = {} error = {} for k, exp in exp_map.items(): if addFormScope: # need to prepare the expression because the context as been updated with a new scope exp.prepare(exp_context) value = exp.evaluate(exp_context) if exp.hasEvalError(): result[k] = None error[k] = exp.evalErrorString() else: result[k] = json.loads(QgsJsonUtils.encodeValue(value)) error[k] = exp.expression() body['results'].append(result) body['errors'].append(error) write_json_response(body, response) return
def processAlgorithm(self, parameters, context, feedback): """ Here is where the processing itself takes place. """ ueberhoehung = self.parameterAsInt(parameters, self.INPUTZFACTOR, context) vectorLayer = self.parameterAsVectorLayer(parameters, self.INPUTVECTORLAYER, context) baseLineLayer = self.parameterAsVectorLayer(parameters, self.INPUTBASELINE, context) offsetFieldName = self.parameterAsString(parameters, self.OFFSETFIELD, context) #offsetFieldIndex=-1 #if not offsetFieldName=="": #fields = vectorLayer.fields() #offsetFieldIndex = vectorLayer.fields().lookupField(offsetFieldName) offsetExpr=QgsExpression(offsetFieldName) if offsetExpr.hasParserError(): feedback.reportError("Offset Expression failed: " + offsetExpr.parserErrorString()) offsetExpr="0" offsetExprContext = QgsExpressionContext() baseLineFeature=None baseLine=None #Basline Layer must have only 1 Feature if baseLineLayer.featureCount()==1: #baseLine must be the first feature baseLineFeature=next(baseLineLayer.getFeatures(QgsFeatureRequest().setLimit(1))) baseLine=baseLineFeature.geometry() elif len(baseLineLayer.selectedFeatures())==1: selection=baseLineLayer.selectedFeatures() #baseLine must be the first feature selFeats=[f for f in selection] baseLineFeature=selFeats[0] baseLine=baseLineFeature.geometry() else: msg = self.tr("Error: BaseLine layer needs exactly one line feature! "+ str(baseLineLayer.featureCount()) + " Just select one feature!") feedback.reportError(msg) raise QgsProcessingException(msg) #check if vectorlayer has Features if vectorLayer.featureCount()==0: msg = self.tr("Error: Layer " , vectorLayer.name() , "is emty! ") feedback.reportError(msg) raise QgsProcessingException(msg) #take CRS from Project crsProject=QgsProject.instance().crs() #check if layers have the same crs if not baseLineLayer.crs().authid()==crsProject.authid(): # if not, transform to raster crs() trafo=QgsCoordinateTransform(baseLineLayer.crs(),crsProject,QgsProject.instance()) #transform BaseLine opResult=baseLine.transform(trafo,QgsCoordinateTransform.ForwardTransform, False) linRef = LinearReferencingMaschine(baseLine, crsProject, feedback) (sink, dest_id) = self.parameterAsSink(parameters, self.OUTPUT, context, vectorLayer.fields(), vectorLayer.wkbType(), crsProject) try: total = 100.0 / vectorLayer.featureCount() except: msg = self.tr("Keine Basislinie") feedback.reportError(msg) raise QgsProcessingException(msg) #check Selection of Inputlayer #if yes, use just the selection processfeatures=None if len(vectorLayer.selectedFeatures()) == 0: processfeatures = vectorLayer.getFeatures() else: processfeatures = vectorLayer.selectedFeatures() i=0 for feat in processfeatures: #vectorLayer.getFeatures(): abstand=0 offsetExprContext.setFeature( feat ) try: abstand = offsetExpr.evaluate( offsetExprContext ) except: msg = self.tr("Error while calculating Offset from Expression. Feature " + str(feat.attributes()) ) feedback.reportError(msg) raise QgsProcessingException(msg) try: #check for numeric Expression Data type a=int(abstand) b=float(abstand) except: msg = self.tr("Error Offset Experession result must be numeric, not " + str( type( abstand )) ) feedback.reportError(msg) raise QgsProcessingException(msg) subFeatureList=[] layerUtils=LayerUtils( crsProject, feedback) subFeatureList=layerUtils.multiPartToSinglePartFeature( feat ) #preparation of profile geometrys prepSubFeatureList=[] for iP, f in enumerate(subFeatureList): if linRef.isSimpleLine or vectorLayer.geometryType() == 0 or vectorLayer.geometryType() == 1: #Point (Line nur temporär): prepSubFeatureList.append( f ) #keep old feature else: # Basisline hat Knickpunkte, Profilgeometrien müssen ggf. mit zusätzlichen Stützpunkten gefüllt werden # Baseline has breakpoints, we have to fill the profile geometrys with additional vertices filledSingleGeom = None if vectorLayer.geometryType() == 2: #Polygon filledSingleGeomList = self.fillPolygonVertices( f.geometry() , linRef, crsProject, feedback) #elif vectorLayer.geometryType() == 1: #Line if len(filledSingleGeomList) > 0: for g in filledSingleGeomList: #create a feature for each filled sub geometry filledFeature=QgsFeature( f ) filledFeature.setGeometry( g ) filledFeature.setAttributes( f.attributes() ) prepSubFeatureList.append( filledFeature ) else: prepSubFeatureList.append( f ) #keep old feature feedback.reportError( "Feature geometry can not be filled: " + str( f.attributes() ) ) #Back to Real World Transformation for each sub Feature realWorldSubFeatureList=[] for pFeat in prepSubFeatureList: #Create Real World geometry with LinearReferencingMaschine realWorldFeat=linRef.transformProfileFeatureToRealWorld( pFeat, vectorLayer.crs(), feedback, abstand, ueberhoehung ) realWorldSubFeatureList.append( realWorldFeat ) ##### ggf features könnten hier wieder gruppiert werden ###### #write real worl Features to output layer for rwFeat in realWorldSubFeatureList: sink.addFeature(rwFeat, QgsFeatureSink.FastInsert) i=i+1 # Update the progress bar feedback.setProgress(int(i * total)) msgInfo=self.tr(str(i) + " Features were transformed to real world coordinates") feedback.pushInfo(msgInfo) # Return the results of the algorithm. In this case our only result is return {self.OUTPUT: dest_id}
def processAlgorithm(self, parameters, context, feedback): source = self.parameterAsSource(parameters, self.INPUT, context) if source is None: raise QgsProcessingException( self.invalidSourceError(parameters, self.INPUT)) strategy = self.parameterAsEnum(parameters, self.STRATEGY, context) minDistance = self.parameterAsDouble(parameters, self.MIN_DISTANCE, context) expression = QgsExpression( self.parameterAsString(parameters, self.EXPRESSION, context)) if expression.hasParserError(): raise QgsProcessingException(expression.parserErrorString()) expressionContext = self.createExpressionContext( parameters, context, source) expression.prepare(expressionContext) fields = QgsFields() fields.append(QgsField('id', QVariant.Int, '', 10, 0)) (sink, dest_id) = self.parameterAsSink(parameters, self.OUTPUT, context, fields, QgsWkbTypes.Point, source.sourceCrs()) if sink is None: raise QgsProcessingException( self.invalidSinkError(parameters, self.OUTPUT)) da = QgsDistanceArea() da.setSourceCrs(source.sourceCrs(), context.transformContext()) da.setEllipsoid(context.project().ellipsoid()) total = 100.0 / source.featureCount() if source.featureCount() else 0 current_progress = 0 for current, f in enumerate(source.getFeatures()): if feedback.isCanceled(): break if not f.hasGeometry(): continue current_progress = total * current feedback.setProgress(current_progress) expressionContext.setFeature(f) value = expression.evaluate(expressionContext) if expression.hasEvalError(): feedback.pushInfo( self.tr('Evaluation error for feature ID {}: {}').format( f.id(), expression.evalErrorString())) continue fGeom = f.geometry() engine = QgsGeometry.createGeometryEngine(fGeom.constGet()) engine.prepareGeometry() bbox = fGeom.boundingBox() if strategy == 0: pointCount = int(value) else: pointCount = int(round(value * da.measureArea(fGeom))) if pointCount == 0: feedback.pushInfo( "Skip feature {} as number of points for it is 0.".format( f.id())) continue index = QgsSpatialIndex() points = dict() nPoints = 0 nIterations = 0 maxIterations = pointCount * 200 feature_total = total / pointCount if pointCount else 1 random.seed() while nIterations < maxIterations and nPoints < pointCount: if feedback.isCanceled(): break rx = bbox.xMinimum() + bbox.width() * random.random() ry = bbox.yMinimum() + bbox.height() * random.random() p = QgsPointXY(rx, ry) geom = QgsGeometry.fromPointXY(p) if engine.contains(geom.constGet()) and \ vector.checkMinDistance(p, index, minDistance, points): f = QgsFeature(nPoints) f.initAttributes(1) f.setFields(fields) f.setAttribute('id', nPoints) f.setGeometry(geom) sink.addFeature(f, QgsFeatureSink.FastInsert) index.addFeature(f) points[nPoints] = p nPoints += 1 feedback.setProgress(current_progress + int(nPoints * feature_total)) nIterations += 1 if nPoints < pointCount: feedback.pushInfo( self.tr('Could not generate requested number of random ' 'points. Maximum number of attempts exceeded.')) feedback.setProgress(100) return {self.OUTPUT: dest_id}