Пример #1
0
def create_field_from_definition(field_definition, name=None, sub_name=None):
    """Helper to create a field from definition.

    :param field_definition: The definition of the field (see:
        safe.definitions.fields).
    :type field_definition: dict

    :param name: The name is required if the field name is dynamic and need a
        string formatting.
    :type name: basestring

    :param sub_name: The name is required if the field name is dynamic and need
        a string formatting.
    :type sub_name: basestring

    :return: The new field.
    :rtype: QgsField
    """
    field = QgsField()

    if name and not sub_name:
        field.setName(field_definition['field_name'] % name)
    elif name and sub_name:
        field.setName(field_definition['field_name'] % (name, sub_name))
    else:
        field.setName(field_definition['field_name'])

    if isinstance(field_definition['type'], list):
        # Use the first element in the list of type
        field.setType(field_definition['type'][0])
    else:
        field.setType(field_definition['type'])
    field.setLength(field_definition['length'])
    field.setPrecision(field_definition['precision'])
    return field
Пример #2
0
 def addField(original, stat, type):
     """
     Adds a field to the output, with a specified type
     """
     field = QgsField(original)
     field.setName(field.name() + '_' + stat)
     field.setType(type)
     if type == QVariant.Double:
         field.setLength(20)
         field.setPrecision(6)
     fields_to_join.append(field)
Пример #3
0
 def addField(original, stat, type):
     """
     Adds a field to the output, with a specified type
     """
     field = QgsField(original)
     field.setName(field.name() + '_' + stat)
     field.setType(type)
     if type == QVariant.Double:
         field.setLength(20)
         field.setPrecision(6)
     fields_to_join.append(field)
Пример #4
0
def create_field(definition):
    """ Création d'un champ dans un table attributaire

    :param definition: Définition de nom, type, taille et précision d'un champ
    :type definition: definition
    """
    field = QgsField()
    field.setName(definition['name'])
    field.setType(definition['type'])
    field.setPrecision(definition['precision'])
    field.setLength(definition['length'])
    return field
Пример #5
0
def _add_id_column(layer):
    """Add an ID column if it's not present in the attribute table.

    :param layer: The vector layer.
    :type layer: QgsVectorLayer
    """
    layer_purpose = layer.keywords['layer_purpose']
    mapping = {
        layer_purpose_exposure['key']: exposure_id_field,
        layer_purpose_hazard['key']: hazard_id_field,
        layer_purpose_aggregation['key']: aggregation_id_field
    }

    has_id_column = False
    for layer_type, field in mapping.iteritems():
        if layer_purpose == layer_type:
            safe_id = field
            if layer.keywords.get(field['key']):
                has_id_column = True
            break

    if not has_id_column:
        LOGGER.info(
            'We add an ID column in {purpose}'.format(purpose=layer_purpose))

        layer.startEditing()

        id_field = QgsField()
        id_field.setName(safe_id['field_name'])
        if isinstance(safe_id['type'], list):
            # Use the first element in the list of type
            id_field.setType(safe_id['type'][0])
        else:
            id_field.setType(safe_id['type'][0])
        id_field.setPrecision(safe_id['precision'])
        id_field.setLength(safe_id['length'])

        layer.addAttribute(id_field)

        new_index = layer.fieldNameIndex(id_field.name())

        for feature in layer.getFeatures():
            layer.changeAttributeValue(
                feature.id(), new_index, feature.id())

        layer.commitChanges()

        layer.keywords['inasafe_fields'][safe_id['key']] = (
            safe_id['field_name'])
Пример #6
0
def _add_id_column(layer):
    """Add an ID column if it's not present in the attribute table.

    :param layer: The vector layer.
    :type layer: QgsVectorLayer
    """
    layer_purpose = layer.keywords['layer_purpose']
    mapping = {
        layer_purpose_exposure['key']: exposure_id_field,
        layer_purpose_hazard['key']: hazard_id_field,
        layer_purpose_aggregation['key']: aggregation_id_field
    }

    has_id_column = False
    for layer_type, field in mapping.iteritems():
        if layer_purpose == layer_type:
            safe_id = field
            if layer.keywords['inasafe_fields'].get(field['key']):
                has_id_column = True
            break

    if not has_id_column:
        LOGGER.info(
            'We add an ID column in {purpose}'.format(purpose=layer_purpose))

        layer.startEditing()

        id_field = QgsField()
        id_field.setName(safe_id['field_name'])
        if isinstance(safe_id['type'], list):
            # Use the first element in the list of type
            id_field.setType(safe_id['type'][0])
        else:
            id_field.setType(safe_id['type'][0])
        id_field.setPrecision(safe_id['precision'])
        id_field.setLength(safe_id['length'])

        layer.addAttribute(id_field)

        new_index = layer.fieldNameIndex(id_field.name())

        for feature in layer.getFeatures():
            layer.changeAttributeValue(
                feature.id(), new_index, feature.id())

        layer.commitChanges()

        layer.keywords['inasafe_fields'][safe_id['key']] = (
            safe_id['field_name'])
Пример #7
0
def create_field_from_definition(field_definition, name=None, sub_name=None):
    """Helper to create a field from definition.

    :param field_definition: The definition of the field (see:
        safe.definitions.fields).
    :type field_definition: dict

    :param name: The name is required if the field name is dynamic and need a
        string formatting.
    :type name: basestring

    :param sub_name: The name is required if the field name is dynamic and need
        a string formatting.
    :type sub_name: basestring

    :return: The new field.
    :rtype: QgsField
    """
    field = QgsField()

    if isinstance(name, QPyNullVariant):
        name = 'NULL'

    if isinstance(sub_name, QPyNullVariant):
        sub_name = 'NULL'

    if name and not sub_name:
        field.setName(field_definition['field_name'] % name)
    elif name and sub_name:
        field.setName(field_definition['field_name'] % (name, sub_name))
    else:
        field.setName(field_definition['field_name'])

    if isinstance(field_definition['type'], list):
        # Use the first element in the list of type
        field.setType(field_definition['type'][0])
    else:
        field.setType(field_definition['type'])
    field.setLength(field_definition['length'])
    field.setPrecision(field_definition['precision'])
    return field
Пример #8
0
    def create_fields(self, layer, record):
        """Create the attributes for the gbif response table."""
        layer.startEditing()
        id_field = QgsField()
        id_field.setName('id')
        id_field.setType(QVariant.Int)
        id_field.setPrecision(0)
        id_field.setLength(10)
        layer.addAttribute(id_field)
        # A dict to store the field offeset for each property
        field_lookups = []
        for key in record.keys():
            new_field = QgsField()
            new_field.setName(key)
            new_field.setType(QVariant.String)
            new_field.setLength(255)
            layer.addAttribute(new_field)
            field_lookups.append(key)

        layer.commitChanges()
        return field_lookups
Пример #9
0
def update_value_map(layer, exposure_key=None, callback=None):
    """Assign inasafe values according to definitions for a vector layer.

    :param layer: The vector layer.
    :type layer: QgsVectorLayer

    :param exposure_key: The exposure key.
    :type exposure_key: str

    :param callback: A function to all to indicate progress. The function
        should accept params 'current' (int), 'maximum' (int) and 'step' (str).
        Defaults to None.
    :type callback: function

    :return: The classified vector layer.
    :rtype: QgsVectorLayer

    .. versionadded:: 4.0
    """
    output_layer_name = assign_inasafe_values_steps['output_layer_name']
    processing_step = assign_inasafe_values_steps['step_name']
    output_layer_name = output_layer_name % layer.keywords['layer_purpose']

    keywords = layer.keywords
    inasafe_fields = keywords['inasafe_fields']

    classification = None
    if keywords['layer_purpose'] == layer_purpose_hazard['key']:
        if not inasafe_fields.get(hazard_value_field['key']):
            raise InvalidKeywordsForProcessingAlgorithm
        old_field = hazard_value_field
        new_field = hazard_class_field
        classification = active_classification(layer.keywords, exposure_key)

    elif keywords['layer_purpose'] == layer_purpose_exposure['key']:
        if not inasafe_fields.get(exposure_type_field['key']):
            raise InvalidKeywordsForProcessingAlgorithm
        old_field = exposure_type_field
        new_field = exposure_class_field
    else:
        raise InvalidKeywordsForProcessingAlgorithm

    # It's a hazard layer
    if exposure_key:
        if not active_thresholds_value_maps(keywords, exposure_key):
            raise InvalidKeywordsForProcessingAlgorithm
        value_map = active_thresholds_value_maps(keywords, exposure_key)
    # It's exposure layer
    else:
        if not keywords.get('value_map'):
            raise InvalidKeywordsForProcessingAlgorithm
        value_map = keywords.get('value_map')

    unclassified_column = inasafe_fields[old_field['key']]
    unclassified_index = layer.fieldNameIndex(unclassified_column)

    reversed_value_map = {}
    for inasafe_class, values in value_map.iteritems():
        for val in values:
            reversed_value_map[val] = inasafe_class

    classified_field = QgsField()
    classified_field.setType(new_field['type'])
    classified_field.setName(new_field['field_name'])
    classified_field.setLength(new_field['length'])
    classified_field.setPrecision(new_field['precision'])

    layer.startEditing()
    layer.addAttribute(classified_field)

    classified_field_index = layer.fieldNameIndex(classified_field.name())

    for feature in layer.getFeatures():
        attributes = feature.attributes()
        source_value = attributes[unclassified_index]
        classified_value = reversed_value_map.get(source_value)

        if not classified_value:
            classified_value = ''

        layer.changeAttributeValue(
            feature.id(), classified_field_index, classified_value)

    layer.commitChanges()

    remove_fields(layer, [unclassified_column])

    # We transfer keywords to the output.
    # We add new class field
    inasafe_fields[new_field['key']] = new_field['field_name']

    # and we remove hazard value field
    inasafe_fields.pop(old_field['key'])

    layer.keywords = keywords
    layer.keywords['inasafe_fields'] = inasafe_fields
    if exposure_key:
        value_map_key = 'value_maps'
    else:
        value_map_key = 'value_map'
    if value_map_key in layer.keywords.keys():
        layer.keywords.pop(value_map_key)
    layer.keywords['title'] = output_layer_name
    if classification:
        layer.keywords['classification'] = classification

    check_layer(layer)
    return layer
Пример #10
0
def reclassify(layer, exposure_key=None):
    """Reclassify a continuous vector layer.

    This function will modify the input.

    For instance if you want to reclassify like this table :
            Original Value     |   Class
            - ∞ < val <= 0     |     1
            0   < val <= 0.5   |     2
            0.5 < val <= 5     |     3
            5   < val <  + ∞   |     6

    You need a dictionary :
        ranges = OrderedDict()
        ranges[1] = [None, 0]
        ranges[2] = [0.0, 0.5]
        ranges[3] = [0.5, 5]
        ranges[6] = [5, None]

    :param layer: The raster layer.
    :type layer: QgsRasterLayer

    :param exposure_key: The exposure key.
    :type exposure_key: str

    :return: The classified vector layer.
    :rtype: QgsVectorLayer

    .. versionadded:: 4.0
    """
    output_layer_name = reclassify_vector_steps['output_layer_name']
    output_layer_name = output_layer_name % layer.keywords['title']

    # This layer should have this keyword, or it's a mistake from the dev.
    inasafe_fields = layer.keywords['inasafe_fields']
    continuous_column = inasafe_fields[hazard_value_field['key']]

    if exposure_key:
        classification_key = active_classification(
            layer.keywords, exposure_key)
        thresholds = active_thresholds_value_maps(layer.keywords, exposure_key)
        layer.keywords['thresholds'] = thresholds
        layer.keywords['classification'] = classification_key
    else:
        classification_key = layer.keywords.get('classification')
        thresholds = layer.keywords.get('thresholds')

    if not thresholds:
        raise InvalidKeywordsForProcessingAlgorithm(
            'thresholds are missing from the layer %s'
            % layer.keywords['layer_purpose'])

    continuous_index = layer.fields().lookupField(continuous_column)

    classified_field = QgsField()
    classified_field.setType(hazard_class_field['type'])
    classified_field.setName(hazard_class_field['field_name'])
    classified_field.setLength(hazard_class_field['length'])
    classified_field.setPrecision(hazard_class_field['precision'])

    layer.startEditing()
    layer.addAttribute(classified_field)

    classified_field_index = layer.fields(). \
        lookupField(classified_field.name())

    for feature in layer.getFeatures():
        attributes = feature.attributes()
        source_value = attributes[continuous_index]
        classified_value = reclassify_value(source_value, thresholds)
        if (classified_value is None
                or (hasattr(classified_value, 'isNull')
                    and classified_value.isNull())):
            layer.deleteFeature(feature.id())
        else:
            layer.changeAttributeValue(
                feature.id(), classified_field_index, classified_value)

    layer.commitChanges()
    layer.updateFields()

    # We transfer keywords to the output.
    inasafe_fields[hazard_class_field['key']] = (
        hazard_class_field['field_name'])

    value_map = {}

    hazard_classes = definition(classification_key)['classes']
    for hazard_class in reversed(hazard_classes):
        value_map[hazard_class['key']] = [hazard_class['value']]

    layer.keywords['value_map'] = value_map
    layer.keywords['title'] = output_layer_name

    check_layer(layer)
    return layer
Пример #11
0
    def processAlgorithm(self, parameters, context, feedback):
        source = self.parameterAsSource(parameters, self.INPUT, context)
        fieldName = self.parameterAsString(parameters, self.FIELD, context)
        useField = bool(fieldName)

        field_index = None
        f = QgsField('value', QVariant.String, '', 255)
        if useField:
            field_index = source.fields().lookupField(fieldName)
            fType = source.fields()[field_index].type()
            if fType in [
                    QVariant.Int, QVariant.UInt, QVariant.LongLong,
                    QVariant.ULongLong
            ]:
                f.setType(fType)
                f.setLength(20)
            elif fType == QVariant.Double:
                f.setType(QVariant.Double)
                f.setLength(20)
                f.setPrecision(6)
            else:
                f.setType(QVariant.String)
                f.setLength(255)

        fields = QgsFields()
        fields.append(QgsField('id', QVariant.Int, '', 20))
        fields.append(f)
        fields.append(QgsField('area', QVariant.Double, '', 20, 6))
        fields.append(QgsField('perim', QVariant.Double, '', 20, 6))

        (sink, dest_id) = self.parameterAsSink(parameters, self.OUTPUT,
                                               context, fields,
                                               QgsWkbTypes.Polygon,
                                               source.sourceCrs())

        outFeat = QgsFeature()
        outGeom = QgsGeometry()

        fid = 0
        val = None
        if useField:
            unique = source.uniqueValues(field_index)
            current = 0
            total = 100.0 / (source.featureCount() *
                             len(unique)) if source.featureCount() else 1
            for i in unique:
                if feedback.isCanceled():
                    break

                first = True
                hull = []
                features = source.getFeatures(
                    QgsFeatureRequest().setSubsetOfAttributes([field_index]))
                for f in features:
                    if feedback.isCanceled():
                        break

                    idVar = f.attributes()[field_index]
                    if str(idVar).strip() == str(i).strip():
                        if first:
                            val = idVar
                            first = False

                        inGeom = f.geometry()
                        points = vector.extractPoints(inGeom)
                        hull.extend(points)
                    current += 1
                    feedback.setProgress(int(current * total))

                if len(hull) >= 3:
                    tmpGeom = QgsGeometry(outGeom.fromMultiPoint(hull))
                    try:
                        outGeom = tmpGeom.convexHull()
                        if outGeom:
                            area = outGeom.geometry().area()
                            perim = outGeom.geometry().perimeter()
                        else:
                            area = NULL
                            perim = NULL
                        outFeat.setGeometry(outGeom)
                        outFeat.setAttributes([fid, val, area, perim])
                        sink.addFeature(outFeat, QgsFeatureSink.FastInsert)
                    except:
                        raise QgsProcessingException(
                            self.tr('Exception while computing convex hull'))
                fid += 1
        else:
            hull = []
            total = 100.0 / source.featureCount() if source.featureCount(
            ) else 1
            features = source.getFeatures(
                QgsFeatureRequest().setSubsetOfAttributes([]))
            for current, f in enumerate(features):
                if feedback.isCanceled():
                    break

                inGeom = f.geometry()
                points = vector.extractPoints(inGeom)
                hull.extend(points)
                feedback.setProgress(int(current * total))

            tmpGeom = QgsGeometry(outGeom.fromMultiPoint(hull))
            try:
                outGeom = tmpGeom.convexHull()
                if outGeom:
                    area = outGeom.geometry().area()
                    perim = outGeom.geometry().perimeter()
                else:
                    area = NULL
                    perim = NULL
                outFeat.setGeometry(outGeom)
                outFeat.setAttributes([0, 'all', area, perim])
                sink.addFeature(outFeat, QgsFeatureSink.FastInsert)
            except:
                raise QgsProcessingException(
                    self.tr('Exception while computing convex hull'))

        return {self.OUTPUT: dest_id}
Пример #12
0
def reclassify(layer, exposure_key=None, callback=None):
    """Reclassify a continuous vector layer.

    This function will modify the input.

    For instance if you want to reclassify like this table :
            Original Value     |   Class
            - ∞ < val <= 0     |     1
            0   < val <= 0.5   |     2
            0.5 < val <= 5     |     3
            5   < val <  + ∞   |     6

    You need a dictionary :
        ranges = OrderedDict()
        ranges[1] = [None, 0]
        ranges[2] = [0.0, 0.5]
        ranges[3] = [0.5, 5]
        ranges[6] = [5, None]

    :param layer: The raster layer.
    :type layer: QgsRasterLayer

    :param exposure_key: The exposure key.
    :type exposure_key: str

    :param callback: A function to all to indicate progress. The function
        should accept params 'current' (int), 'maximum' (int) and 'step' (str).
        Defaults to None.
    :type callback: function

    :return: The classified vector layer.
    :rtype: QgsVectorLayer

    .. versionadded:: 4.0
    """
    output_layer_name = reclassify_vector_steps['output_layer_name']
    output_layer_name = output_layer_name % layer.keywords['title']
    processing_step = reclassify_vector_steps['step_name']

    # This layer should have this keyword, or it's a mistake from the dev.
    inasafe_fields = layer.keywords['inasafe_fields']
    continuous_column = inasafe_fields[hazard_value_field['key']]

    if exposure_key:
        classification_key = active_classification(layer.keywords,
                                                   exposure_key)
        thresholds = active_thresholds_value_maps(layer.keywords, exposure_key)
        layer.keywords['thresholds'] = thresholds
        layer.keywords['classification'] = classification_key
    else:
        classification_key = layer.keywords.get('classification')
        thresholds = layer.keywords.get('thresholds')

    if not thresholds:
        raise InvalidKeywordsForProcessingAlgorithm(
            'thresholds are missing from the layer %s' %
            layer.keywords['layer_purpose'])

    continuous_index = layer.fieldNameIndex(continuous_column)

    classified_field = QgsField()
    classified_field.setType(hazard_class_field['type'])
    classified_field.setName(hazard_class_field['field_name'])
    classified_field.setLength(hazard_class_field['length'])
    classified_field.setPrecision(hazard_class_field['precision'])

    layer.startEditing()
    layer.addAttribute(classified_field)

    classified_field_index = layer.fieldNameIndex(classified_field.name())

    for feature in layer.getFeatures():
        attributes = feature.attributes()
        source_value = attributes[continuous_index]
        classified_value = _classified_value(source_value, thresholds)
        if not classified_value:
            layer.deleteFeature(feature.id())
        else:
            layer.changeAttributeValue(feature.id(), classified_field_index,
                                       classified_value)

    layer.commitChanges()
    layer.updateFields()

    # We transfer keywords to the output.
    inasafe_fields[hazard_class_field['key']] = (
        hazard_class_field['field_name'])

    value_map = {}

    hazard_classes = definition(classification_key)['classes']
    for hazard_class in reversed(hazard_classes):
        value_map[hazard_class['key']] = [hazard_class['value']]

    layer.keywords['value_map'] = value_map
    layer.keywords['title'] = output_layer_name

    check_layer(layer)
    return layer
Пример #13
0
    def on_btnRun_clicked(self):
        
        #Check for combo and list box selections
        if self.ui.cmbBaseLayer.count() < 1 or self.ui.cmbProcessLayer.count() < 1:
            QMessageBox.critical(self, 'Vector Geoprocessor', 'Invalid layer selection.')
            return
        if len(self.ui.listFields.selectedItems()) < 1:
            QMessageBox.critical(self, 'Vector Geoprocessor', 'Invalid field selection.')
            return            
      
        #Initializations
        self.ui.ProgressBar.setValue(0)
        self.setCursor(Qt.WaitCursor)
        data = []
            
        #Add new attributes to base layer
        bprovider = self.blayer.dataProvider()
        pprovider = self.player.dataProvider()
        pfields = pprovider.fields()
        for item in self.ui.listFields.selectedItems():
            fname = item.text()
            for fld in pfields.toList():
                if fname == fld.name():                                               
                    newfield = QgsField()
                    newfield.setName(fld.name())
                    newfield.setType(fld.type())
                    newfield.setTypeName(fld.typeName())
                    newfield.setLength(fld.length())
                    newfield.setPrecision(fld.precision())
                    newfield.setComment(fld.comment())
                    bprovider.addAttributes([newfield])            

        #Create a spatial index for faster processing
        spindex = QgsSpatialIndex()
        for pfeat in pprovider.getFeatures():
            spindex.insertFeature(pfeat)
        
        #Find the intersection of process layer features with base layer
        #To increase speed, intersect with a bounding box rectangle first
        #Then further process within the geometric shape
        #Add requested processed information to base layer                
        featreq = QgsFeatureRequest()
        bfields = bprovider.fields()
        ddic = {}
        len1 = len(self.ui.listFields.selectedItems())
        len2 = len(bfields)
        b1 = 0
        b2 = bprovider.featureCount()
        attr={}
        for bfeat in bprovider.getFeatures():
            b1+=1
            attr.clear()
            bgeom = bfeat.geometry()                                          
            intersect = spindex.intersects(bgeom.boundingBox())
            data[:] = []
            for fid in intersect:               
                pfeat = self.player.getFeatures(featreq.setFilterFid(fid)).next()
                if pfeat.geometry().intersects(bgeom) == False:
                    data.append(fid)           
            for fid in data:        
                intersect.pop(intersect.index(fid))
                              
            count = 0
            for item in self.ui.listFields.selectedItems():
                pfindx = pprovider.fieldNameIndex(item.text())
                if pfindx < 0:
                    self.setCursor(Qt.ArrowCursor)
                    QMessageBox.critical(self, 'Vector Geoprocessor', 'Processing error.')
                    return
                data[:] = []
                for fid in intersect:
                    pfeat = self.player.getFeatures(featreq.setFilterFid(fid)).next()
                    if self.oindex in [0,1,2,3,4]:
                        data.append(float(pfeat.attribute(item.text())))
                    elif self.oindex in [5,6]:
                        data.append(str(pfeat.attribute(item.text())))
                if len(data) == 0:
                    value = None
                elif self.oindex == 0: #Find mean value of points within polygons
                    value = sum(data)/float(len(data))
                elif self.oindex == 1: #Find median value of points within polygons
                    data = sorted(data)
                    lendata = len(data)
                    if lendata % 2:
                        value = data[(lendata+1)/2-1]
                    else:
                        d1 = data[lendata/2-1]
                        d2 = data[lendata/2]
                        value = (d1 + d2)/2.0
                elif self.oindex == 2: #Find maximum value of points within polygons
                    value = max(data)
                elif self.oindex == 3: #Find minimum value of points within polygons
                    value = min(data)
                elif self.oindex == 4: #Find mean value (area-weighted) of polygons within polygons
                    value = 0.0
                    totalarea = 0.0
                    for fid in intersect:
                        pfeat = self.player.getFeatures(featreq.setFilterFid(fid)).next()
                        pgeom = pfeat.geometry()
                        isect = bgeom.intersection(pgeom)
                        parea = isect.area()
                        value+=(float(pfeat.attribute(item.text())*parea))
                        totalarea+=parea
                    value = value / totalarea
                elif self.oindex == 5: #Find largest area polygon within polygons
                    data = list(set(data))  #Get unique items in data                          
                    ddic.clear()
                    for i in data:
                        ddic.update({i : 0.0})
                    for fid in intersect:
                        pfeat = self.player.getFeatures(featreq.setFilterFid(fid)).next()
                        pgeom = pfeat.geometry()
                        isect = bgeom.intersection(pgeom)
                        parea = isect.area()
                        key = str(pfeat.attribute(item.text()))
                        parea = parea + ddic[key]
                        ddic.update({key : parea})
                    parea = -1
                    for key in ddic.keys():
                        if ddic[key] > parea:
                            parea = ddic[key]
                            value = key
                elif self.oindex == 6: #Add polygon attribute to points
                    if len(data) != 1:
                        QMessageBox.warning(self, 'Vector Geoprocessor',
                                            'Point intersects more than one polygon.')
                    value = data[0]
                
                attr.update({(len2-len1+count):value})
                count+=1
            result = bprovider.changeAttributeValues({bfeat.id():attr})
            if not result:
                QMessageBox.critical(self, 'Vector Geoprocessor', 'Could not change attribute value.')
                return           
            self.ui.ProgressBar.setValue(float(b1)/float(b2) * 100.0)
            QApplication.processEvents()

        self.setCursor(Qt.ArrowCursor)
 def create_target_attribute():
     source_attribute_type = source_layer.dataProvider().fields().at(
         source_layer.fieldNameIndex(source_attribute_name)).type()
     target_attr = QgsField(target_attribute_name)
     target_attr.setType(source_attribute_type)
     return target_layer.addAttribute(target_attr)
Пример #15
0
    def on_btnRun_clicked(self):

        #Check for combo and list box selections
        if self.ui.cmbBaseLayer.count() < 1 or self.ui.cmbProcessLayer.count(
        ) < 1:
            QMessageBox.critical(self, 'Vector Geoprocessor',
                                 'Invalid layer selection.')
            return
        if len(self.ui.listFields.selectedItems()) < 1:
            QMessageBox.critical(self, 'Vector Geoprocessor',
                                 'Invalid field selection.')
            return

        #Initializations
        self.ui.ProgressBar.setValue(0)
        self.setCursor(Qt.WaitCursor)
        data = []

        #Add new attributes to base layer
        bprovider = self.blayer.dataProvider()
        pprovider = self.player.dataProvider()
        pfields = pprovider.fields()
        for item in self.ui.listFields.selectedItems():
            fname = item.text()
            for fld in pfields.toList():
                if fname == fld.name():
                    newfield = QgsField()
                    newfield.setName(fld.name())
                    newfield.setType(fld.type())
                    newfield.setTypeName(fld.typeName())
                    newfield.setLength(fld.length())
                    newfield.setPrecision(fld.precision())
                    newfield.setComment(fld.comment())
                    bprovider.addAttributes([newfield])

        #Create a spatial index for faster processing
        spindex = QgsSpatialIndex()
        for pfeat in pprovider.getFeatures():
            spindex.insertFeature(pfeat)

        #Find the intersection of process layer features with base layer
        #To increase speed, intersect with a bounding box rectangle first
        #Then further process within the geometric shape
        #Add requested processed information to base layer
        featreq = QgsFeatureRequest()
        bfields = bprovider.fields()
        ddic = {}
        len1 = len(self.ui.listFields.selectedItems())
        len2 = len(bfields)
        b1 = 0
        b2 = bprovider.featureCount()
        attr = {}
        for bfeat in bprovider.getFeatures():
            b1 += 1
            attr.clear()
            bgeom = bfeat.geometry()
            intersect = spindex.intersects(bgeom.boundingBox())
            data[:] = []
            for fid in intersect:
                pfeat = next(self.player.getFeatures(
                    featreq.setFilterFid(fid)))
                if pfeat.geometry().intersects(bgeom) == False:
                    data.append(fid)
            for fid in data:
                intersect.pop(intersect.index(fid))

            count = 0
            for item in self.ui.listFields.selectedItems():
                pfindx = pprovider.fieldNameIndex(item.text())
                if pfindx < 0:
                    self.setCursor(Qt.ArrowCursor)
                    QMessageBox.critical(self, 'Vector Geoprocessor',
                                         'Processing error.')
                    return
                data[:] = []
                for fid in intersect:
                    pfeat = next(
                        self.player.getFeatures(featreq.setFilterFid(fid)))
                    if self.oindex in [0, 1, 2, 3, 4]:
                        data.append(float(pfeat.attribute(item.text())))
                    elif self.oindex in [5, 6]:
                        data.append(str(pfeat.attribute(item.text())))
                if len(data) == 0:
                    value = None
                elif self.oindex == 0:  #Find mean value of points within polygons
                    value = sum(data) / float(len(data))
                elif self.oindex == 1:  #Find median value of points within polygons
                    data = sorted(data)
                    lendata = len(data)
                    if lendata % 2:
                        value = data[(lendata + 1) / 2 - 1]
                    else:
                        d1 = data[lendata / 2 - 1]
                        d2 = data[lendata / 2]
                        value = (d1 + d2) / 2.0
                elif self.oindex == 2:  #Find maximum value of points within polygons
                    value = max(data)
                elif self.oindex == 3:  #Find minimum value of points within polygons
                    value = min(data)
                elif self.oindex == 4:  #Find mean value (area-weighted) of polygons within polygons
                    value = 0.0
                    totalarea = 0.0
                    for fid in intersect:
                        pfeat = next(
                            self.player.getFeatures(featreq.setFilterFid(fid)))
                        pgeom = pfeat.geometry()
                        isect = bgeom.intersection(pgeom)
                        parea = isect.area()
                        value += (float(pfeat.attribute(item.text()) * parea))
                        totalarea += parea
                    value = value / totalarea
                elif self.oindex == 5:  #Find largest area polygon within polygons
                    data = list(set(data))  #Get unique items in data
                    ddic.clear()
                    for i in data:
                        ddic.update({i: 0.0})
                    for fid in intersect:
                        pfeat = next(
                            self.player.getFeatures(featreq.setFilterFid(fid)))
                        pgeom = pfeat.geometry()
                        isect = bgeom.intersection(pgeom)
                        parea = isect.area()
                        key = str(pfeat.attribute(item.text()))
                        parea = parea + ddic[key]
                        ddic.update({key: parea})
                    parea = -1
                    for key in list(ddic.keys()):
                        if ddic[key] > parea:
                            parea = ddic[key]
                            value = key
                elif self.oindex == 6:  #Add polygon attribute to points
                    if len(data) != 1:
                        QMessageBox.warning(
                            self, 'Vector Geoprocessor',
                            'Point intersects more than one polygon.')
                    value = data[0]

                attr.update({(len2 - len1 + count): value})
                count += 1
            result = bprovider.changeAttributeValues({bfeat.id(): attr})
            if not result:
                QMessageBox.critical(self, 'Vector Geoprocessor',
                                     'Could not change attribute value.')
                return
            self.ui.ProgressBar.setValue(float(b1) / float(b2) * 100.0)
            QApplication.processEvents()

        self.setCursor(Qt.ArrowCursor)
Пример #16
0
    def processAlgorithm(self, progress):
        layer = dataobjects.getObjectFromUri(
            self.getParameterValue(self.INPUT))
        useField = self.getParameterValue(self.METHOD) == 1
        fieldName = self.getParameterValue(self.FIELD)

        f = QgsField('value', QVariant.String, '', 255)
        if useField:
            index = layer.fieldNameIndex(fieldName)
            fType = layer.pendingFields()[index].type()
            if fType == QVariant.Int:
                f.setType(QVariant.Int)
                f.setLength(20)
            elif fType == QVariant.Double:
                f.setType(QVariant.Double)
                f.setLength(20)
                f.setPrecision(6)
            else:
                f.setType(QVariant.String)
                f.setLength(255)

        fields = [QgsField('id', QVariant.Int, '', 20),
                  f,
                  QgsField('area', QVariant.Double, '', 20, 6),
                  QgsField('perim', QVariant.Double, '', 20, 6)
                 ]

        writer = self.getOutputFromName(self.OUTPUT).getVectorWriter(
            fields, QGis.WKBPolygon, layer.dataProvider().crs())

        outFeat = QgsFeature()
        inGeom = QgsGeometry()
        outGeom = QgsGeometry()

        current = 0

        fid = 0
        val = None
        features = vector.features(layer)
        if useField:
            unique = layer.uniqueValues(index)
            total = 100.0 / (len(features) * len(unique))
            for i in unique:
                first = True
                hull = []
                features = vector.features(layer)
                for f in features:
                    idVar = f[fieldName]
                    if unicode(idVar).strip() == unicode(i).strip():
                        if first:
                            val = idVar
                            first = False

                        inGeom = QgsGeometry(f.geometry())
                        points = vector.extractPoints(inGeom)
                        hull.extend(points)
                    current += 1
                    progress.setPercentage(int(current * total))

                if len(hull) >= 3:
                    tmpGeom = QgsGeometry(outGeom.fromMultiPoint(hull))
                    try:
                        outGeom = tmpGeom.convexHull()
                        (area, perim) = vector.simpleMeasure(outGeom)
                        outFeat.setGeometry(outGeom)
                        outFeat.setAttributes([fid, val, area, perim])
                        writer.addFeature(outFeat)
                    except:
                        raise GeoAlgorithmExecutionException(
                            self.tr('Exception while computing convex hull'))
                fid += 1
        else:
            hull = []
            total = 100.0 / float(layer.featureCount())
            features = vector.features(layer)
            for f in features:
                inGeom = QgsGeometry(f.geometry())
                points = vector.extractPoints(inGeom)
                hull.extend(points)
                current += 1
                progress.setPercentage(int(current * total))

            tmpGeom = QgsGeometry(outGeom.fromMultiPoint(hull))
            try:
                outGeom = tmpGeom.convexHull()
                (area, perim) = vector.simpleMeasure(outGeom)
                outFeat.setGeometry(outGeom)
                outFeat.setAttributes([0, 'all', area, perim])
                writer.addFeature(outFeat)
            except:
                raise GeoAlgorithmExecutionException(
                    self.tr('Exception while computing convex hull'))

        del writer
Пример #17
0
    def processAlgorithm(self, parameters, context, feedback):
        """
        Here is where the processing itself takes place.
        """

        # 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.
        source = self.parameterAsSource(
            parameters,
            self.INPUT,
            context
        )

        # If source was not found, 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 invalidSourceError
        # method to return a standard helper text for when a source cannot be
        # evaluated
        if source is None:
            raise QgsProcessingException(
                self.invalidSourceError(parameters, self.INPUT))

        fields_to_transform = self.parameterAsFields(
            parameters, self.FIELDS_TO_TRANSFORM, context)
        source_fields = source.fields()
        if not fields_to_transform:
            # no fields selected, use all numeric ones
            fields_to_transform = [source_fields.at(i).name()
                                   for i in range(len(source_fields))
                                   if source_fields.at(i).isNumeric()]
        self.transformed_fields = QgsFields()

        transformation_name = self.name()

        fields_to_transform_idxs = []
        for f in fields_to_transform:
            idx = source.fields().lookupField(f)
            if idx >= 0:
                fields_to_transform_idxs.append(idx)
                field_to_transform = source.fields().at(idx)
                if field_to_transform.isNumeric():
                    transformed_field = QgsField(field_to_transform)
                    transformed_field.setName(
                        "%s_%s" % (field_to_transform.name(),
                                   transformation_name))
                    transformed_field.setType(QVariant.Double)
                    transformed_field.setLength(20)
                    transformed_field.setPrecision(6)
                    self.transformed_fields.append(transformed_field)

        out_fields = QgsProcessingUtils.combineFields(
            source_fields, self.transformed_fields)

        (sink, self.dest_id) = self.parameterAsSink(
            parameters,
            self.OUTPUT,
            context,
            out_fields,
            source.wkbType(),
            source.sourceCrs()
        )

        # Send some information to the user
        feedback.pushInfo('CRS is {}'.format(source.sourceCrs().authid()))

        # 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))

        total = 100.0 / len(fields_to_transform)
        transformed_values = {}

        for current, fieldname_to_transform in enumerate(fields_to_transform):
            original_values = vector.values(
                source, fieldname_to_transform)[fieldname_to_transform]
            transformed_values[fieldname_to_transform] = self.transform_values(
                original_values, parameters, context)
            feedback.setProgress(int(current * total))

        feedback.setProgress(0)

        # Compute the number of steps to display within the progress bar and
        # get features from source
        total = 100.0 / source.featureCount() if source.featureCount() else 0

        for current, source_feature in enumerate(source.getFeatures()):
            # Stop the algorithm if cancel button has been clicked
            if feedback.isCanceled():
                break

            sink_feature = QgsFeature(out_fields)

            # copy original fields
            for field in source.fields():
                sink_feature[field.name()] = source_feature[field.name()]

            for original_fieldname, transformed_field in zip(
                    fields_to_transform, self.transformed_fields):
                sink_feature[transformed_field.name()] = \
                    transformed_values[original_fieldname][current]
            sink_feature.setGeometry(source_feature.geometry())

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

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

        # 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.
        return {self.OUTPUT: self.dest_id}
Пример #18
0
    def processAlgorithm(self, parameters, context, feedback):
        layer = QgsProcessingUtils.mapLayerFromString(self.getParameterValue(self.INPUT), context)
        useField = self.getParameterValue(self.METHOD) == 1
        fieldName = self.getParameterValue(self.FIELD)

        f = QgsField('value', QVariant.String, '', 255)
        if useField:
            index = layer.fields().lookupField(fieldName)
            fType = layer.fields()[index].type()
            if fType in [QVariant.Int, QVariant.UInt, QVariant.LongLong, QVariant.ULongLong]:
                f.setType(fType)
                f.setLength(20)
            elif fType == QVariant.Double:
                f.setType(QVariant.Double)
                f.setLength(20)
                f.setPrecision(6)
            else:
                f.setType(QVariant.String)
                f.setLength(255)

        fields = QgsFields()
        fields.append(QgsField('id', QVariant.Int, '', 20))
        fields.append(f)
        fields.append(QgsField('area', QVariant.Double, '', 20, 6))
        fields.append(QgsField('perim', QVariant.Double, '', 20, 6))

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

        outFeat = QgsFeature()
        inGeom = QgsGeometry()
        outGeom = QgsGeometry()

        fid = 0
        val = None
        features = QgsProcessingUtils.getFeatures(layer, context)
        if useField:
            unique = layer.uniqueValues(index)
            current = 0
            total = 100.0 / (layer.featureCount() * len(unique)) if layer.featureCount() else 1
            for i in unique:
                first = True
                hull = []
                features = QgsProcessingUtils.getFeatures(layer, context)
                for f in features:
                    idVar = f[fieldName]
                    if str(idVar).strip() == str(i).strip():
                        if first:
                            val = idVar
                            first = False

                        inGeom = f.geometry()
                        points = vector.extractPoints(inGeom)
                        hull.extend(points)
                    current += 1
                    feedback.setProgress(int(current * total))

                if len(hull) >= 3:
                    tmpGeom = QgsGeometry(outGeom.fromMultiPoint(hull))
                    try:
                        outGeom = tmpGeom.convexHull()
                        (area, perim) = vector.simpleMeasure(outGeom)
                        outFeat.setGeometry(outGeom)
                        outFeat.setAttributes([fid, val, area, perim])
                        writer.addFeature(outFeat, QgsFeatureSink.FastInsert)
                    except:
                        raise GeoAlgorithmExecutionException(
                            self.tr('Exception while computing convex hull'))
                fid += 1
        else:
            hull = []
            total = 100.0 / layer.featureCount() if layer.featureCount() else 1
            features = QgsProcessingUtils.getFeatures(layer, context)
            for current, f in enumerate(features):
                inGeom = f.geometry()
                points = vector.extractPoints(inGeom)
                hull.extend(points)
                feedback.setProgress(int(current * total))

            tmpGeom = QgsGeometry(outGeom.fromMultiPoint(hull))
            try:
                outGeom = tmpGeom.convexHull()
                (area, perim) = vector.simpleMeasure(outGeom)
                outFeat.setGeometry(outGeom)
                outFeat.setAttributes([0, 'all', area, perim])
                writer.addFeature(outFeat, QgsFeatureSink.FastInsert)
            except:
                raise GeoAlgorithmExecutionException(
                    self.tr('Exception while computing convex hull'))

        del writer
Пример #19
0
    def processAlgorithm(self, progress):
        layer = dataobjects.getObjectFromUri(self.getParameterValue(self.INPUT))
        useField = self.getParameterValue(self.METHOD) == 1
        fieldName = self.getParameterValue(self.FIELD)

        f = QgsField("value", QVariant.String, "", 255)
        if useField:
            index = layer.fields().lookupField(fieldName)
            fType = layer.fields()[index].type()
            if fType in [QVariant.Int, QVariant.UInt, QVariant.LongLong, QVariant.ULongLong]:
                f.setType(fType)
                f.setLength(20)
            elif fType == QVariant.Double:
                f.setType(QVariant.Double)
                f.setLength(20)
                f.setPrecision(6)
            else:
                f.setType(QVariant.String)
                f.setLength(255)

        fields = [
            QgsField("id", QVariant.Int, "", 20),
            f,
            QgsField("area", QVariant.Double, "", 20, 6),
            QgsField("perim", QVariant.Double, "", 20, 6),
        ]

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

        outFeat = QgsFeature()
        inGeom = QgsGeometry()
        outGeom = QgsGeometry()

        fid = 0
        val = None
        features = vector.features(layer)
        if useField:
            unique = layer.uniqueValues(index)
            current = 0
            total = 100.0 / (len(features) * len(unique))
            for i in unique:
                first = True
                hull = []
                features = vector.features(layer)
                for f in features:
                    idVar = f[fieldName]
                    if str(idVar).strip() == str(i).strip():
                        if first:
                            val = idVar
                            first = False

                        inGeom = f.geometry()
                        points = vector.extractPoints(inGeom)
                        hull.extend(points)
                    current += 1
                    progress.setPercentage(int(current * total))

                if len(hull) >= 3:
                    tmpGeom = QgsGeometry(outGeom.fromMultiPoint(hull))
                    try:
                        outGeom = tmpGeom.convexHull()
                        (area, perim) = vector.simpleMeasure(outGeom)
                        outFeat.setGeometry(outGeom)
                        outFeat.setAttributes([fid, val, area, perim])
                        writer.addFeature(outFeat)
                    except:
                        raise GeoAlgorithmExecutionException(self.tr("Exception while computing convex hull"))
                fid += 1
        else:
            hull = []
            total = 100.0 / layer.featureCount()
            features = vector.features(layer)
            for current, f in enumerate(features):
                inGeom = f.geometry()
                points = vector.extractPoints(inGeom)
                hull.extend(points)
                progress.setPercentage(int(current * total))

            tmpGeom = QgsGeometry(outGeom.fromMultiPoint(hull))
            try:
                outGeom = tmpGeom.convexHull()
                (area, perim) = vector.simpleMeasure(outGeom)
                outFeat.setGeometry(outGeom)
                outFeat.setAttributes([0, "all", area, perim])
                writer.addFeature(outFeat)
            except:
                raise GeoAlgorithmExecutionException(self.tr("Exception while computing convex hull"))

        del writer
Пример #20
0
    def processAlgorithm(self, progress):
        layer = dataobjects.getObjectFromUri(
            self.getParameterValue(self.INPUT))
        useField = self.getParameterValue(self.METHOD) == 1
        fieldName = self.getParameterValue(self.FIELD)

        f = QgsField('value', QVariant.String, '', 255)
        if useField:
            index = layer.fields().lookupField(fieldName)
            fType = layer.fields()[index].type()
            if fType in [QVariant.Int, QVariant.UInt, QVariant.LongLong, QVariant.ULongLong]:
                f.setType(fType)
                f.setLength(20)
            elif fType == QVariant.Double:
                f.setType(QVariant.Double)
                f.setLength(20)
                f.setPrecision(6)
            else:
                f.setType(QVariant.String)
                f.setLength(255)

        fields = [QgsField('id', QVariant.Int, '', 20),
                  f,
                  QgsField('area', QVariant.Double, '', 20, 6),
                  QgsField('perim', QVariant.Double, '', 20, 6)
                  ]

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

        outFeat = QgsFeature()
        inGeom = QgsGeometry()
        outGeom = QgsGeometry()

        fid = 0
        val = None
        features = vector.features(layer)
        if useField:
            unique = layer.uniqueValues(index)
            current = 0
            total = 100.0 / (len(features) * len(unique))
            for i in unique:
                first = True
                hull = []
                features = vector.features(layer)
                for f in features:
                    idVar = f[fieldName]
                    if str(idVar).strip() == str(i).strip():
                        if first:
                            val = idVar
                            first = False

                        inGeom = f.geometry()
                        points = vector.extractPoints(inGeom)
                        hull.extend(points)
                    current += 1
                    progress.setPercentage(int(current * total))

                if len(hull) >= 3:
                    tmpGeom = QgsGeometry(outGeom.fromMultiPoint(hull))
                    try:
                        outGeom = tmpGeom.convexHull()
                        (area, perim) = vector.simpleMeasure(outGeom)
                        outFeat.setGeometry(outGeom)
                        outFeat.setAttributes([fid, val, area, perim])
                        writer.addFeature(outFeat)
                    except:
                        raise GeoAlgorithmExecutionException(
                            self.tr('Exception while computing convex hull'))
                fid += 1
        else:
            hull = []
            total = 100.0 / layer.featureCount()
            features = vector.features(layer)
            for current, f in enumerate(features):
                inGeom = f.geometry()
                points = vector.extractPoints(inGeom)
                hull.extend(points)
                progress.setPercentage(int(current * total))

            tmpGeom = QgsGeometry(outGeom.fromMultiPoint(hull))
            try:
                outGeom = tmpGeom.convexHull()
                (area, perim) = vector.simpleMeasure(outGeom)
                outFeat.setGeometry(outGeom)
                outFeat.setAttributes([0, 'all', area, perim])
                writer.addFeature(outFeat)
            except:
                raise GeoAlgorithmExecutionException(
                    self.tr('Exception while computing convex hull'))

        del writer
Пример #21
0
    def processAlgorithm(self, parameters, context, feedback):
        source = self.parameterAsSource(parameters, self.INPUT, context)
        fieldName = self.parameterAsString(parameters, self.FIELD, context)
        useField = bool(fieldName)

        field_index = None
        f = QgsField('value', QVariant.String, '', 255)
        if useField:
            field_index = source.fields().lookupField(fieldName)
            fType = source.fields()[field_index].type()
            if fType in [QVariant.Int, QVariant.UInt, QVariant.LongLong, QVariant.ULongLong]:
                f.setType(fType)
                f.setLength(20)
            elif fType == QVariant.Double:
                f.setType(QVariant.Double)
                f.setLength(20)
                f.setPrecision(6)
            else:
                f.setType(QVariant.String)
                f.setLength(255)

        fields = QgsFields()
        fields.append(QgsField('id', QVariant.Int, '', 20))
        fields.append(f)
        fields.append(QgsField('area', QVariant.Double, '', 20, 6))
        fields.append(QgsField('perim', QVariant.Double, '', 20, 6))

        (sink, dest_id) = self.parameterAsSink(parameters, self.OUTPUT, context,
                                               fields, QgsWkbTypes.Polygon, source.sourceCrs())

        outFeat = QgsFeature()
        outGeom = QgsGeometry()

        fid = 0
        val = None
        if useField:
            unique = source.uniqueValues(field_index)
            current = 0
            total = 100.0 / (source.featureCount() * len(unique)) if source.featureCount() else 1
            for i in unique:
                if feedback.isCanceled():
                    break

                first = True
                hull = []
                features = source.getFeatures(QgsFeatureRequest().setSubsetOfAttributes([field_index]))
                for f in features:
                    if feedback.isCanceled():
                        break

                    idVar = f.attributes()[field_index]
                    if str(idVar).strip() == str(i).strip():
                        if first:
                            val = idVar
                            first = False

                        inGeom = f.geometry()
                        points = vector.extractPoints(inGeom)
                        hull.extend(points)
                    current += 1
                    feedback.setProgress(int(current * total))

                if len(hull) >= 3:
                    tmpGeom = QgsGeometry(outGeom.fromMultiPoint(hull))
                    try:
                        outGeom = tmpGeom.convexHull()
                        if outGeom:
                            area = outGeom.geometry().area()
                            perim = outGeom.geometry().perimeter()
                        else:
                            area = NULL
                            perim = NULL
                        outFeat.setGeometry(outGeom)
                        outFeat.setAttributes([fid, val, area, perim])
                        sink.addFeature(outFeat, QgsFeatureSink.FastInsert)
                    except:
                        raise QgsProcessingException(
                            self.tr('Exception while computing convex hull'))
                fid += 1
        else:
            hull = []
            total = 100.0 / source.featureCount() if source.featureCount() else 1
            features = source.getFeatures(QgsFeatureRequest().setSubsetOfAttributes([]))
            for current, f in enumerate(features):
                if feedback.isCanceled():
                    break

                inGeom = f.geometry()
                points = vector.extractPoints(inGeom)
                hull.extend(points)
                feedback.setProgress(int(current * total))

            tmpGeom = QgsGeometry(outGeom.fromMultiPoint(hull))
            try:
                outGeom = tmpGeom.convexHull()
                if outGeom:
                    area = outGeom.geometry().area()
                    perim = outGeom.geometry().perimeter()
                else:
                    area = NULL
                    perim = NULL
                outFeat.setGeometry(outGeom)
                outFeat.setAttributes([0, 'all', area, perim])
                sink.addFeature(outFeat, QgsFeatureSink.FastInsert)
            except:
                raise QgsProcessingException(
                    self.tr('Exception while computing convex hull'))

        return {self.OUTPUT: dest_id}
Пример #22
0
def update_value_map(layer, exposure_key=None):
    """Assign inasafe values according to definitions for a vector layer.

    :param layer: The vector layer.
    :type layer: QgsVectorLayer

    :param exposure_key: The exposure key.
    :type exposure_key: str

    :return: The classified vector layer.
    :rtype: QgsVectorLayer

    .. versionadded:: 4.0
    """
    output_layer_name = assign_inasafe_values_steps['output_layer_name']
    output_layer_name = output_layer_name % layer.keywords['layer_purpose']

    keywords = layer.keywords
    inasafe_fields = keywords['inasafe_fields']

    classification = None
    if keywords['layer_purpose'] == layer_purpose_hazard['key']:
        if not inasafe_fields.get(hazard_value_field['key']):
            raise InvalidKeywordsForProcessingAlgorithm
        old_field = hazard_value_field
        new_field = hazard_class_field
        classification = active_classification(layer.keywords, exposure_key)

    elif keywords['layer_purpose'] == layer_purpose_exposure['key']:
        if not inasafe_fields.get(exposure_type_field['key']):
            raise InvalidKeywordsForProcessingAlgorithm
        old_field = exposure_type_field
        new_field = exposure_class_field
    else:
        raise InvalidKeywordsForProcessingAlgorithm

    # It's a hazard layer
    if exposure_key:
        if not active_thresholds_value_maps(keywords, exposure_key):
            raise InvalidKeywordsForProcessingAlgorithm
        value_map = active_thresholds_value_maps(keywords, exposure_key)
    # It's exposure layer
    else:
        if not keywords.get('value_map'):
            raise InvalidKeywordsForProcessingAlgorithm
        value_map = keywords.get('value_map')

    unclassified_column = inasafe_fields[old_field['key']]
    unclassified_index = layer.fields().lookupField(unclassified_column)

    reversed_value_map = {}
    for inasafe_class, values in list(value_map.items()):
        for val in values:
            reversed_value_map[val] = inasafe_class

    classified_field = QgsField()
    classified_field.setType(new_field['type'])
    classified_field.setName(new_field['field_name'])
    classified_field.setLength(new_field['length'])
    classified_field.setPrecision(new_field['precision'])

    layer.startEditing()
    layer.addAttribute(classified_field)

    classified_field_index = layer.fields(). \
        lookupField(classified_field.name())

    for feature in layer.getFeatures():
        attributes = feature.attributes()
        source_value = attributes[unclassified_index]
        classified_value = reversed_value_map.get(source_value)

        if not classified_value:
            classified_value = ''

        layer.changeAttributeValue(feature.id(), classified_field_index,
                                   classified_value)

    layer.commitChanges()

    remove_fields(layer, [unclassified_column])

    # We transfer keywords to the output.
    # We add new class field
    inasafe_fields[new_field['key']] = new_field['field_name']

    # and we remove hazard value field
    inasafe_fields.pop(old_field['key'])

    layer.keywords = keywords
    layer.keywords['inasafe_fields'] = inasafe_fields
    if exposure_key:
        value_map_key = 'value_maps'
    else:
        value_map_key = 'value_map'
    if value_map_key in list(layer.keywords.keys()):
        layer.keywords.pop(value_map_key)
    layer.keywords['title'] = output_layer_name
    if classification:
        layer.keywords['classification'] = classification

    check_layer(layer)
    return layer
Пример #23
0
    def CheckControlFile(self):

        #Open control file
        if not os.path.exists(self.cfilename):
            QMessageBox.critical(self, 'Simulation Controller',
                                 'Control file does not exist.')
            return 1
        else:
            self.cfile = ControlFile.ControlFile()
            ret = self.cfile.ReadFile(self.cfilename)
            if ret:
                QMessageBox.critical(self, 'Simulation Controller',
                                     'Error reading control file.')
                return 1

        #Set working directory
        if not os.path.exists(self.cfile.ModelDirectory):
            QMessageBox.critical(self, 'Simulation Controller',
                                 'Model directory does not exist.')
            return 1
        else:
            os.chdir(self.cfile.ModelDirectory)

        #Get base layer
        count = 0
        for i in self.layers:
            if i.name() == self.cfile.BaseLayer:
                self.blayer = i
                self.bprovider = self.blayer.dataProvider()
                count += 1
        if not count:  #Count==0
            QMessageBox.critical(self, 'Simulation Controller',
                                 'Base layer not found.')
            return 1
        if count > 1:
            QMessageBox.critical(
                self, 'Simulation Controller',
                'Found more than one layer with base layer name.')
            return 1

        #Check template files
        for key in sorted(self.cfile.TemplateInput.keys()):
            if not os.path.exists(self.cfile.TemplateInput[key][0]):
                QMessageBox.critical(
                    self, 'Simulation Controller', 'File does not exist: %s' %
                    self.cfile.TemplateInput[key][0])
                return 1
            else:
                f = open(self.cfile.TemplateInput[key][0], 'r')
                lines = f.readlines()
                f.close()
                if lines[0][
                        0:41] != 'Geospatial Simulation Template (GST) File':
                    QMessageBox.critical(self, 'Simulation Controller',
                                         'Check template file.')
                    return 1

        #Check for input attributes in base layer
        for key in sorted(self.cfile.AttributeCode.keys()):
            bfindx = self.bprovider.fieldNameIndex(
                self.cfile.AttributeCode[key][0])
            if bfindx < 0:
                QMessageBox.critical(
                    self, 'Simulation Controller',
                    'Missing attribute in base layer: %s' %
                    self.cfile.AttributeCode[key][0])
                return 1

        #Check instruction files
        for key in sorted(self.cfile.InstructionOutput.keys()):
            if not os.path.exists(self.cfile.InstructionOutput[key][0]):
                QMessageBox.critical(
                    self, 'Simulation Controller', 'File does not exist: %s' %
                    self.cfile.InstructionOutput[key][0])
                return 1
            else:
                f = open(self.cfile.InstructionOutput[key][0], 'r')
                lines = f.readlines()
                f.close()
                if lines[0][
                        0:44] != 'Geospatial Simulation Instruction (GSI) File':
                    QMessageBox.critical(self, 'Simulation Controller',
                                         'Check instruction file.')
                    return 1
                for line in lines[1:]:
                    line = line.split(',')
                    if len(line) < 2:
                        continue
                    found = 0
                    for key in sorted(self.cfile.AttributeType.keys()):
                        if self.cfile.AttributeType[key][0] == line[0]:
                            found = 1
                            break
                    if not found:
                        QMessageBox.critical(
                            self, 'Simulation Controller',
                            'Check control file for missing output attribute: '
                            + line[0])
                        return 1

        #Check for output attributes in base layer.  Add if missing.
        for key in sorted(self.cfile.AttributeType.keys()):
            typename = self.cfile.AttributeType[key][1].split('(')[0]
            length = self.cfile.AttributeType[key][1].split('(')[1]
            bfindx = self.bprovider.fieldNameIndex(
                self.cfile.AttributeType[key][0])
            if bfindx < 0:  #Field not found, must add it
                newfield = QgsField()
                newfield.setName(self.cfile.AttributeType[key][0])
                if typename in ['String', 'string', 'STRING']:
                    newfield.setType(QVariant.String)
                    newfield.setTypeName('String')
                    newfield.setLength(int(length.split(')')[0]))
                elif typename in ['Integer', 'integer', 'INTEGER']:
                    newfield.setType(QVariant.Int)
                    newfield.setTypeName('Integer')
                    newfield.setLength(int(length.split(')')[0]))
                elif typename in ['Real', 'real', 'REAL']:
                    newfield.setType(QVariant.Double)
                    newfield.setTypeName('Real')
                    newfield.setLength(int(length.split('.')[0]))
                    newfield.setPrecision(
                        int(length.split('.')[1].split(')')[0]))
                self.bprovider.addAttributes([newfield])

        #Enable Run button
        self.ui.btnRun.setEnabled(True)

        return 0