示例#1
0
    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
示例#2
0
    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
示例#4
0
 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)
示例#7
0
    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
示例#8
0
    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)  
示例#11
0
 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
示例#12
0
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
示例#13
0
文件: defaults.py 项目: nicklv/Roam
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')
示例#14
0
 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
示例#15
0
 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) 
示例#16
0
 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))
示例#17
0
    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
示例#18
0
    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]}
示例#19
0
    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)
示例#20
0
 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) 
示例#21
0
    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 )
示例#22
0
    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
示例#23
0
    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
示例#24
0
 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
示例#25
0
    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
示例#26
0
 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()                  
示例#28
0
    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
示例#29
0
    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
示例#30
0
    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))        
示例#31
0
    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
示例#32
0
    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]}
示例#34
0
文件: defaults.py 项目: FSAS-NUS/Roam
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')
示例#35
0
    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
示例#36
0
    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
示例#37
0
    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())))
示例#38
0
    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())))
示例#39
0
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]
示例#40
0
    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
示例#41
0
    def processAlgorithm(self, progress):
        layer = self.getParameterValue(self.INPUT_LAYER)
        mapping = self.getParameterValue(self.FIELDS_MAPPING)
        output = self.getOutputFromName(self.OUTPUT_LAYER)

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

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

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

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

            outFeat.setGeometry(inFeat.geometry())

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

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

            writer.addFeature(outFeat)

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

        del writer

        if not calculationSuccess:
            raise GeoAlgorithmExecutionException(
                self.tr('An error occurred while evaluating the calculation'
                        ' string:\n') + error)
示例#42
0
    def processAlgorithm(self, progress):
        layer = self.getParameterValue(self.INPUT_LAYER)
        mapping = self.getParameterValue(self.FIELDS_MAPPING)
        output = self.getOutputFromName(self.OUTPUT_LAYER)

        layer = dataobjects.getObjectFromUri(layer)
        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)
示例#43
0
    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}
示例#45
0
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
示例#46
0
    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
示例#47
0
    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)
示例#48
0
    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
示例#49
0
    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}
示例#50
0
    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}