Example #1
0
def copy_fields(layer, fields_to_copy):
    """Copy fields inside an attribute table.

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

    :param fields_to_copy: Dictionary of fields to copy.
    :type fields_to_copy: dict
    """
    for field in fields_to_copy:

        index = layer.fields().lookupField(field)
        if index != -1:

            layer.startEditing()

            source_field = layer.fields().at(index)
            new_field = QgsField(source_field)
            new_field.setName(fields_to_copy[field])

            layer.addAttribute(new_field)

            new_index = layer.fields().lookupField(fields_to_copy[field])

            for feature in layer.getFeatures():
                attributes = feature.attributes()
                source_value = attributes[index]
                layer.changeAttributeValue(
                    feature.id(), new_index, source_value)

            layer.commitChanges()
            layer.updateFields()  # Avoid crash #4729
Example #2
0
 def addField(name):
     """
     Adds a field to the output, keeping the same data type as the value_field
     """
     field = QgsField(value_field)
     field.setName(name)
     fields.append(field)
 def addFieldKeepType(original, stat):
     """
     Adds a field to the output, keeping the same data type as the original
     """
     field = QgsField(original)
     field.setName(field.name() + '_' + stat)
     fields_to_join.append(field)
 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)
Example #5
0
  def test04_EditShapefile1(self):
    """Load a file, edit and overwrite. edits: add a field, set values to the field, and then remove the field"""
    self._testAvailable() or self.skipTest("Not available")
    fieldName = u'\u6587\u5b57\u52172'
    c0 = ord(u'\u30a2')

    infile = self.testDataPath(self.layerName)
    for ignore in [True, False]:
      setSettingValue("/qgis/ignoreShapeEncoding", ignore)

      # copy a set of shapefile
      layerName = u"{}_edit{}".format(self.layerName, 1 if ignore else 2)
      workfile = self.testDataPath(layerName, output=True)
      copyFileSet(infile, workfile, [".shp", ".shx", ".dbf", ".prj", ".cpg"])

      # load the copy
      layer = self._testLayer(workfile + ".shp", output=True)

      # add a field
      layer.startEditing()
      f = QgsField(fieldName, QVariant.String, len=20)
      assert layer.addAttribute(f), "failed to add a field"
      fldIdx = layer.fieldNameIndex(fieldName)

      # set strings with Japanese characters to the field
      c = c0
      for f in layer.getFeatures():
        val = "".join([unichr(c + i) for i in range(5)])
        assert layer.changeAttributeValue(f.id(), fldIdx, val), "failed to change attribute value"
        c += 5

      # save and reload the shapefile
      assert layer.commitChanges(), "failed to commit changes"
      del layer
      layer = self._testLayer(workfile + ".shp", output=True)

      # check the values of the field
      c = c0
      for f in layer.getFeatures():
        val = "".join([unichr(c + i) for i in range(5)])
        self.assertEqual(f.attribute(fieldName), val)
        c += 5

      # remove the added field
      layer.startEditing()
      layer.deleteAttribute(fldIdx)
      assert layer.commitChanges(), "failed to commit changes"

      # compare the file set with source
      c = compareFileSet(infile, workfile, [".shp", ".shx", ".dbf", ".prj", ".cpg"])
      self.assertEqual(c, [], "input and output do not match: {}".format(str(c)))

      print 'with "ignore..." option = {}...success'.format(ignore)
 def getFields():
   atts = [
     { 'name': 'id_add', 'type': QVariant.Int },
     { 'name': 'total_imgs', 'type':QVariant.Int },
     { 'name': 'images', 'type': QVariant.String, 'len': 254 },
     { 'name': 'user', 'type': QVariant.String, 'len': 20 },
     { 'name': 'date_add', 'type': QVariant.String, 'len': 20 },
     { 'name': 'crs_map', 'type': QVariant.String, 'len': 50 },
     { 'name': 'extent_map', 'type': QVariant.String, 'len': 200 },
     { 'name': 'annotation', 'type': QVariant.String, 'len': 100 }
   ]
   fields = QgsFields()
   for att in atts:
     f = QgsField( att['name'], att['type'] )
     if 'len' in att:
       f.setLength( att['len'])
     fields.append( f )
   return fields
Example #7
0
def combineVectorFields(layerA, layerB):
    """Create single field map from two input field maps.
    """
    fields = []
    fieldsA = layerA.pendingFields()
    fields.extend(fieldsA)
    namesA = [unicode(f.name()).lower() for f in fieldsA]
    fieldsB = layerB.pendingFields()
    for field in fieldsB:
        name = unicode(field.name()).lower()
        if name in namesA:
            idx = 2
            newName = name + '_' + unicode(idx)
            while newName in namesA:
                idx += 1
                newName = name + '_' + unicode(idx)
            field = QgsField(newName, field.type(), field.typeName())
        fields.append(field)

    return fields
Example #8
0
def combineFields(fieldsA, fieldsB):
    """Create single field map from two input field maps.
    """
    fields = []
    fields.extend(fieldsA)
    namesA = [str(f.name()).lower() for f in fieldsA]
    for field in fieldsB:
        name = str(field.name()).lower()
        if name in namesA:
            idx = 2
            newName = name + '_' + str(idx)
            while newName in namesA:
                idx += 1
                newName = name + '_' + str(idx)
            field = QgsField(newName, field.type(), field.typeName())
        fields.append(field)

    real_fields = QgsFields()
    for f in fields:
        real_fields.append(f)
    return real_fields
 def testFieldTooltip(self):
     f = QgsField('my_string', QVariant.String, 'string')
     self.assertEqual(QgsFieldModel.fieldToolTip(f), '<b>my_string</b><p>string</p>')
     f.setAlias('my alias')
     self.assertEqual(QgsFieldModel.fieldToolTip(f), '<b>my alias</b> (my_string)<p>string</p>')
     f.setLength(20)
     self.assertEqual(QgsFieldModel.fieldToolTip(f), '<b>my alias</b> (my_string)<p>string (20)</p>')
     f = QgsField('my_real', QVariant.Double, 'real', 8, 3)
     self.assertEqual(QgsFieldModel.fieldToolTip(f), '<b>my_real</b><p>real (8, 3)</p>')
 def createQgsField(self):
     qgsField = None
     if self.type.attributeType == GeoCsvAttributeType.integer:
         qgsField = QgsField(self.name, QVariant.Int)
     elif self.type.attributeType == GeoCsvAttributeType.easting or self.type.attributeType == GeoCsvAttributeType.northing or self.type.attributeType == GeoCsvAttributeType.real:
         qgsField = QgsField(self.name, QVariant.Double)
     else:
         qgsField = QgsField(self.name, QVariant.String)
     if not self.type.length == 0:
         qgsField.setLength(self.type.length)
     if not self.type.precision == 0:
         qgsField.setPrecision(self.type.precision) 
     return qgsField     
 def test_find_attribute_id(self):
     field_names = ['first', 'second']
     field_one = QgsField(field_names[0], QVariant.String)
     field_one.setTypeName(STRING_FIELD_TYPE_NAME)
     field_two = QgsField(field_names[1], QVariant.Int)
     field_two.setTypeName(INT_FIELD_TYPE_NAME)
     attributes = [field_one, field_two]
     ProcessLayer(self.layer).add_attributes(attributes)
     added_field_names = [field.name() for field in self.dp.fields()]
     # Double-check that add_attributes is working properly
     assert added_field_names == field_names
     # Check that both attributes are correctly found
     for attr_name in field_names:
         try:
             ProcessLayer(self.layer).find_attribute_id(attr_name)
         except AttributeError:
             print "We would expect both attributes to be found!"
             raise
     # Check that an inexistent field doesn't get found and that the
     # AttributeError exception is correctly raised
     with self.assertRaises(AttributeError):
         ProcessLayer(self.layer).add_attributes('dummy')
Example #12
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
Example #13
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}
    def processAlgorithm(self, context, feedback):
        layer = dataobjects.getLayerFromString(
            self.getParameterValue(self.VECTOR))
        fieldName = self.getParameterValue(self.FIELD)
        minDistance = float(self.getParameterValue(self.MIN_DISTANCE))
        strategy = self.getParameterValue(self.STRATEGY)

        fields = QgsFields()
        fields.append(QgsField('id', QVariant.Int, '', 10, 0))
        writer = self.getOutputFromName(self.OUTPUT).getVectorWriter(fields, QgsWkbTypes.Point, layer.crs(), context)

        da = QgsDistanceArea()

        features = QgsProcessingUtils.getFeatures(layer, context)
        for current, f in enumerate(features):
            fGeom = f.geometry()
            bbox = fGeom.boundingBox()
            if strategy == 0:
                pointCount = int(f[fieldName])
            else:
                pointCount = int(round(f[fieldName] * da.measureArea(fGeom)))

            if pointCount == 0:
                feedback.pushInfo("Skip feature {} as number of points for it is 0.")
                continue

            index = QgsSpatialIndex()
            points = dict()

            nPoints = 0
            nIterations = 0
            maxIterations = pointCount * 200
            total = 100.0 / pointCount

            random.seed()

            while nIterations < maxIterations and nPoints < pointCount:
                rx = bbox.xMinimum() + bbox.width() * random.random()
                ry = bbox.yMinimum() + bbox.height() * random.random()

                pnt = QgsPoint(rx, ry)
                geom = QgsGeometry.fromPoint(pnt)
                if geom.within(fGeom) and \
                   vector.checkMinDistance(pnt, index, minDistance, points):
                    f = QgsFeature(nPoints)
                    f.initAttributes(1)
                    f.setFields(fields)
                    f.setAttribute('id', nPoints)
                    f.setGeometry(geom)
                    writer.addFeature(f)
                    index.insertFeature(f)
                    points[nPoints] = pnt
                    nPoints += 1
                    feedback.setProgress(int(nPoints * total))
                nIterations += 1

            if nPoints < pointCount:
                QgsMessageLog.logMessage(self.tr('Can not generate requested number of random '
                                                 'points. Maximum number of attempts exceeded.'), self.tr('Processing'), QgsMessageLog.INFO)

            feedback.setProgress(0)

        del writer
Example #15
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(), context.transformContext())
        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))

        expression.prepare(exp_context)

        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 testModel(self):
        """Test the mapping model"""

        model = QgsFieldMappingModel(self.source_fields,
                                     self.destination_fields)
        self.assertEqual(model.rowCount(QModelIndex()), 3)
        self.assertIsNone(model.data(model.index(9999, 0), Qt.DisplayRole))
        # We now have this default mapping:
        # source exp        | destination fld
        # -------------------------------------------
        # source_field2     | destination_field1
        # source_field1     | destination_field2
        # NOT SET (NULL)    | destination_field3
        self.assertEqual(model.data(model.index(0, 0), Qt.DisplayRole),
                         '"source_field2"')
        self.assertEqual(model.data(model.index(0, 1), Qt.DisplayRole),
                         'destination_field1')
        self.assertEqual(model.data(model.index(0, 3), Qt.DisplayRole), 10)
        self.assertEqual(model.data(model.index(0, 4), Qt.DisplayRole), 8)

        self.assertEqual(model.data(model.index(1, 0), Qt.DisplayRole),
                         '"source_field1"')
        self.assertEqual(model.data(model.index(1, 1), Qt.DisplayRole),
                         'destination_field2')

        self.assertEqual(model.data(model.index(2, 0), Qt.DisplayRole),
                         QVariant())
        self.assertEqual(model.data(model.index(2, 1), Qt.DisplayRole),
                         'destination_field3')

        # Test expression scope
        ctx = model.contextGenerator().createExpressionContext()
        self.assertTrue('source_field1' in ctx.fields().names())

        # Test add fields
        model.appendField(QgsField('destination_field4', QVariant.String))
        self.assertEqual(model.rowCount(QModelIndex()), 4)
        self.assertEqual(model.data(model.index(3, 1), Qt.DisplayRole),
                         'destination_field4')

        # Test remove field
        model.removeField(model.index(3, 0))
        self.assertEqual(model.rowCount(QModelIndex()), 3)
        self.assertEqual(model.data(model.index(2, 1), Qt.DisplayRole),
                         'destination_field3')

        # Test edit fields
        mapping = model.mapping()
        self.assertEqual(mapping[0].field.name(), 'destination_field1')
        self.assertEqual(mapping[1].field.name(), 'destination_field2')
        self.assertEqual(mapping[2].field.name(), 'destination_field3')
        self.assertEqual(mapping[0].originalName, 'destination_field1')
        self.assertEqual(mapping[1].originalName, 'destination_field2')
        self.assertEqual(mapping[2].originalName, 'destination_field3')

        # Test move up or down
        self.assertFalse(model.moveUp(model.index(0, 0)))
        self.assertFalse(model.moveUp(model.index(100, 0)))
        self.assertFalse(model.moveDown(model.index(2, 0)))
        self.assertFalse(model.moveDown(model.index(100, 0)))

        self.assertTrue(model.moveDown(model.index(0, 0)))
        mapping = model.mapping()
        self.assertEqual(mapping[1].field.name(), 'destination_field1')
        self.assertEqual(mapping[0].field.name(), 'destination_field2')
        self.assertEqual(mapping[2].field.name(), 'destination_field3')
        self.assertEqual(mapping[1].originalName, 'destination_field1')
        self.assertEqual(mapping[0].originalName, 'destination_field2')
        self.assertEqual(mapping[2].originalName, 'destination_field3')

        self.assertTrue(model.moveUp(model.index(1, 0)))
        mapping = model.mapping()
        self.assertEqual(mapping[0].field.name(), 'destination_field1')
        self.assertEqual(mapping[1].field.name(), 'destination_field2')
        self.assertEqual(mapping[2].field.name(), 'destination_field3')
        self.assertEqual(mapping[0].originalName, 'destination_field1')
        self.assertEqual(mapping[1].originalName, 'destination_field2')
        self.assertEqual(mapping[2].originalName, 'destination_field3')

        self.assertTrue(model.moveUp(model.index(2, 0)))
        mapping = model.mapping()
        self.assertEqual(mapping[0].field.name(), 'destination_field1')
        self.assertEqual(mapping[2].field.name(), 'destination_field2')
        self.assertEqual(mapping[1].field.name(), 'destination_field3')
        self.assertEqual(mapping[0].originalName, 'destination_field1')
        self.assertEqual(mapping[2].originalName, 'destination_field2')
        self.assertEqual(mapping[1].originalName, 'destination_field3')
Example #17
0
def calculate_svi(
    iface, current_layer, project_definition, indicators_operator=None, themes_operator=None, reuse_field=False
):
    """
    add an SVI attribute to the current layer
    """
    # set default
    if indicators_operator is None:
        indicators_operator = DEFAULT_COMBINATION
    if themes_operator is None:
        themes_operator = DEFAULT_COMBINATION

    themes = project_definition["children"][1]["children"]

    if reuse_field and "svi_field" in project_definition:
        svi_attr_name = project_definition["svi_field"]
        if DEBUG:
            print "Reusing %s" % svi_attr_name
    else:
        svi_attr_name = "SVI"
        svi_field = QgsField(svi_attr_name, QVariant.Double)
        svi_field.setTypeName(DOUBLE_FIELD_TYPE_NAME)
        attr_names = ProcessLayer(current_layer).add_attributes([svi_field])
        svi_attr_name = attr_names[svi_attr_name]

    # get the id of the new attribute
    svi_attr_id = ProcessLayer(current_layer).find_attribute_id(svi_attr_name)

    discarded_feats_ids = []
    try:
        with LayerEditingManager(current_layer, "Add SVI", DEBUG):
            for feat in current_layer.getFeatures():
                # If a feature contains any NULL value, discard_feat will
                # be set to True and the corresponding SVI will be set to
                # NULL
                discard_feat = False
                feat_id = feat.id()

                # init svi_value to the correct value depending on
                # themes_operator
                if themes_operator in SUM_BASED_COMBINATIONS:
                    svi_value = 0
                elif themes_operator in MUL_BASED_COMBINATIONS:
                    svi_value = 1

                # iterate all themes of SVI
                for theme in themes:
                    indicators = theme["children"]

                    # init theme_result to the correct value depending on
                    # indicators_operator
                    if indicators_operator in SUM_BASED_COMBINATIONS:
                        theme_result = 0
                    elif indicators_operator in MUL_BASED_COMBINATIONS:
                        theme_result = 1

                    # iterate all indicators of a theme
                    for indicator in indicators:
                        if feat[indicator["field"]] == QPyNullVariant(float):
                            discard_feat = True
                            discarded_feats_ids.append(feat_id)
                            break
                        # For "Average (equal weights)" it's equivalent to use
                        # equal weights, or to sum the indicators
                        # (all weights 1)
                        # and divide by the number of indicators (we use
                        # the latter solution)
                        if indicators_operator in (
                            "Sum (simple)",
                            "Average (equal weights)",
                            "Multiplication (simple)",
                        ):
                            indicator_weighted = feat[indicator["field"]]
                        else:
                            indicator_weighted = feat[indicator["field"]] * indicator["weight"]

                        if indicators_operator in SUM_BASED_COMBINATIONS:
                            theme_result += indicator_weighted
                        elif indicators_operator in MUL_BASED_COMBINATIONS:
                            theme_result *= indicator_weighted
                        else:
                            error_message = "invalid indicators_operator: %s" % indicators_operator
                            raise RuntimeError(error_message)
                    if discard_feat:
                        break
                    if indicators_operator == "Average (equal weights)":
                        theme_result /= len(indicators)

                    # combine the indicators of each theme
                    # For "Average (equal weights)" it's equivalent to use
                    # equal weights, or to sum the themes (all weights 1)
                    # and divide by the number of themes (we use
                    # the latter solution)
                    if themes_operator in ("Sum (simple)", "Average (equal weights)", "Multiplication (simple)"):
                        theme_weighted = theme_result
                    else:
                        theme_weighted = theme_result * theme["weight"]

                    if themes_operator in SUM_BASED_COMBINATIONS:
                        svi_value += theme_weighted
                    elif themes_operator in MUL_BASED_COMBINATIONS:
                        svi_value *= theme_weighted
                if discard_feat:
                    svi_value = QPyNullVariant(float)
                else:
                    if themes_operator == "Average (equal weights)":
                        svi_value /= len(themes)

                current_layer.changeAttributeValue(feat_id, svi_attr_id, svi_value)
        msg = (
            "The SVI has been calculated for fields containing "
            "non-NULL values and it was added to the layer as "
            "a new attribute called %s"
        ) % svi_attr_name
        iface.messageBar().pushMessage(tr("Info"), tr(msg), level=QgsMessageBar.INFO)
        if discarded_feats_ids:
            widget = toggle_select_features_widget(
                tr("Warning"),
                tr("Invalid indicators were found in some features while " "calculating SVI"),
                tr("Select invalid features"),
                current_layer,
                discarded_feats_ids,
                current_layer.selectedFeaturesIds(),
            )
            iface.messageBar().pushWidget(widget, QgsMessageBar.WARNING)

        project_definition["indicators_operator"] = indicators_operator
        project_definition["themes_operator"] = themes_operator
        project_definition["svi_field"] = svi_attr_name
        return svi_attr_id, discarded_feats_ids

    except TypeError as e:
        current_layer.dataProvider().deleteAttributes([svi_attr_id])
        msg = "Could not calculate SVI due to data problems: %s" % e
        iface.messageBar().pushMessage(tr("Error"), tr(msg), level=QgsMessageBar.CRITICAL)
Example #18
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
Example #19
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
Example #20
0
    def doCheck(self, method, parameters, context, feedback):
        source = self.parameterAsSource(parameters, self.INPUT_LAYER, context)

        (valid_output_sink,
         valid_output_dest_id) = self.parameterAsSink(parameters,
                                                      self.VALID_OUTPUT,
                                                      context, source.fields(),
                                                      source.wkbType(),
                                                      source.sourceCrs())
        valid_count = 0

        invalid_fields = source.fields()
        invalid_fields.append(
            QgsField('_errors', QVariant.String, 'string', 255))
        (invalid_output_sink, invalid_output_dest_id) = self.parameterAsSink(
            parameters, self.INVALID_OUTPUT, context, invalid_fields,
            source.wkbType(), source.sourceCrs())
        invalid_count = 0

        error_fields = QgsFields()
        error_fields.append(QgsField('message', QVariant.String, 'string',
                                     255))
        (error_output_sink, error_output_dest_id) = self.parameterAsSink(
            parameters, self.ERROR_OUTPUT, context, error_fields,
            QgsWkbTypes.Point, source.sourceCrs())
        error_count = 0

        features = source.getFeatures(
            QgsFeatureRequest(),
            QgsProcessingFeatureSource.FlagSkipGeometryValidityChecks)
        total = 100.0 / source.featureCount() if source.featureCount() else 0
        for current, inFeat in enumerate(features):
            if feedback.isCanceled():
                break
            geom = inFeat.geometry()
            attrs = inFeat.attributes()

            valid = True
            if not geom.isNull() and not geom.isEmpty():
                errors = list(geom.validateGeometry(method))
                if errors:
                    # QGIS method return a summary at the end
                    if method == 1:
                        errors.pop()
                    valid = False
                    reasons = []
                    for error in errors:
                        errFeat = QgsFeature()
                        error_geom = QgsGeometry.fromPointXY(error.where())
                        errFeat.setGeometry(error_geom)
                        errFeat.setAttributes([error.what()])
                        if error_output_sink:
                            error_output_sink.addFeature(
                                errFeat, QgsFeatureSink.FastInsert)
                        error_count += 1

                        reasons.append(error.what())

                    reason = "\n".join(reasons)
                    if len(reason) > 255:
                        reason = reason[:252] + '…'
                    attrs.append(reason)

            outFeat = QgsFeature()
            outFeat.setGeometry(geom)
            outFeat.setAttributes(attrs)

            if valid:
                if valid_output_sink:
                    valid_output_sink.addFeature(outFeat,
                                                 QgsFeatureSink.FastInsert)
                valid_count += 1

            else:
                if invalid_output_sink:
                    invalid_output_sink.addFeature(outFeat,
                                                   QgsFeatureSink.FastInsert)
                invalid_count += 1

            feedback.setProgress(int(current * total))

        results = {
            self.VALID_COUNT: valid_count,
            self.INVALID_COUNT: invalid_count,
            self.ERROR_COUNT: error_count
        }
        if valid_output_sink:
            results[self.VALID_OUTPUT] = valid_output_dest_id
        if invalid_output_sink:
            results[self.INVALID_OUTPUT] = invalid_output_dest_id
        if error_output_sink:
            results[self.ERROR_OUTPUT] = error_output_dest_id
        return results
Example #21
0
    def testCreateMemoryLayer(self):
        """
        Test QgsMemoryProviderUtils.createMemoryLayer()
        """

        # no fields
        layer = QgsMemoryProviderUtils.createMemoryLayer(
            'my name', QgsFields())
        self.assertTrue(layer.isValid())
        self.assertEqual(layer.name(), 'my name')
        self.assertTrue(layer.fields().isEmpty())

        # similar layers should have unique sources
        layer2 = QgsMemoryProviderUtils.createMemoryLayer(
            'my name', QgsFields())
        self.assertNotEqual(layer.source(), layer2.source())

        # geometry type
        layer = QgsMemoryProviderUtils.createMemoryLayer(
            'my name', QgsFields(), QgsWkbTypes.Point)
        self.assertTrue(layer.isValid())
        self.assertEqual(layer.wkbType(), QgsWkbTypes.Point)
        layer = QgsMemoryProviderUtils.createMemoryLayer(
            'my name', QgsFields(), QgsWkbTypes.PolygonZM)
        self.assertTrue(layer.isValid())
        self.assertEqual(layer.wkbType(), QgsWkbTypes.PolygonZM)

        # crs
        layer = QgsMemoryProviderUtils.createMemoryLayer(
            'my name', QgsFields(), QgsWkbTypes.PolygonZM,
            QgsCoordinateReferenceSystem.fromEpsgId(3111))
        self.assertTrue(layer.isValid())
        self.assertEqual(layer.wkbType(), QgsWkbTypes.PolygonZM)
        self.assertTrue(layer.crs().isValid())
        self.assertEqual(layer.crs().authid(), 'EPSG:3111')

        # fields
        fields = QgsFields()
        fields.append(QgsField("string", QVariant.String))
        fields.append(QgsField("long", QVariant.LongLong))
        fields.append(QgsField("double", QVariant.Double))
        fields.append(QgsField("integer", QVariant.Int))
        fields.append(QgsField("date", QVariant.Date))
        fields.append(QgsField("datetime", QVariant.DateTime))
        fields.append(QgsField("time", QVariant.Time))
        layer = QgsMemoryProviderUtils.createMemoryLayer('my name', fields)
        self.assertTrue(layer.isValid())
        self.assertFalse(layer.fields().isEmpty())
        self.assertEqual(len(layer.fields()), len(fields))
        for i in range(len(fields)):
            self.assertEqual(layer.fields()[i].name(), fields[i].name())
            self.assertEqual(layer.fields()[i].type(), fields[i].type())

        # unsupported field type
        fields = QgsFields()
        fields.append(QgsField("rect", QVariant.RectF))
        layer = QgsMemoryProviderUtils.createMemoryLayer('my name', fields)
        self.assertTrue(layer.isValid())
        self.assertFalse(layer.fields().isEmpty())
        self.assertEqual(layer.fields()[0].name(), 'rect')
        self.assertEqual(layer.fields()[0].type(),
                         QVariant.String)  # should be mapped to string
Example #22
0
    def processAlgorithm(self, parameters, context, feedback):
        if parameters[self.INPUT] == parameters[self.HUBS]:
            raise QgsProcessingException(
                self.tr('Same layer given for both hubs and spokes'))

        point_source = self.parameterAsSource(parameters, self.INPUT, context)
        if point_source is None:
            raise QgsProcessingException(
                self.invalidSourceError(parameters, self.INPUT))

        hub_source = self.parameterAsSource(parameters, self.HUBS, context)
        if hub_source is None:
            raise QgsProcessingException(
                self.invalidSourceError(parameters, self.HUBS))

        fieldName = self.parameterAsString(parameters, self.FIELD, context)

        units = self.UNITS[self.parameterAsEnum(parameters, self.UNIT,
                                                context)]

        fields = point_source.fields()
        fields.append(QgsField('HubName', QVariant.String))
        fields.append(QgsField('HubDist', QVariant.Double))

        (sink, dest_id) = self.parameterAsSink(parameters, self.OUTPUT,
                                               context, fields,
                                               QgsWkbTypes.Point,
                                               point_source.sourceCrs())
        if sink is None:
            raise QgsProcessingException(
                self.invalidSinkError(parameters, self.OUTPUT))

        index = QgsSpatialIndex(
            hub_source.getFeatures(QgsFeatureRequest().setSubsetOfAttributes(
                []).setDestinationCrs(point_source.sourceCrs(),
                                      context.transformContext())))

        distance = QgsDistanceArea()
        distance.setSourceCrs(point_source.sourceCrs(),
                              context.transformContext())
        distance.setEllipsoid(context.project().ellipsoid())

        # Scan source points, find nearest hub, and write to output file
        features = point_source.getFeatures()
        total = 100.0 / point_source.featureCount(
        ) if point_source.featureCount() else 0
        for current, f in enumerate(features):
            if feedback.isCanceled():
                break

            if not f.hasGeometry():
                sink.addFeature(f, QgsFeatureSink.FastInsert)
                continue

            src = f.geometry().boundingBox().center()

            neighbors = index.nearestNeighbor(src, 1)
            ft = next(
                hub_source.getFeatures(QgsFeatureRequest().setFilterFid(
                    neighbors[0]).setSubsetOfAttributes(
                        [fieldName], hub_source.fields()).setDestinationCrs(
                            point_source.sourceCrs(),
                            context.transformContext())))
            closest = ft.geometry().boundingBox().center()
            hubDist = distance.measureLine(src, closest)

            if units != self.LAYER_UNITS:
                hub_dist_in_desired_units = distance.convertLengthMeasurement(
                    hubDist, units)
            else:
                hub_dist_in_desired_units = hubDist

            attributes = f.attributes()
            attributes.append(ft[fieldName])
            attributes.append(hub_dist_in_desired_units)

            feat = QgsFeature()
            feat.setAttributes(attributes)

            feat.setGeometry(QgsGeometry.fromPointXY(src))

            sink.addFeature(feat, QgsFeatureSink.FastInsert)
            feedback.setProgress(int(current * total))

        return {self.OUTPUT: dest_id}
Example #23
0
    def processAlgorithm(self, parameters, context, feedback):
        source = self.parameterAsSource(parameters, self.INPUT_VECTOR, context)
        if source is None:
            raise QgsProcessingException(
                self.invalidSourceError(parameters, self.INPUT_VECTOR))

        raster_layer = self.parameterAsRasterLayer(parameters,
                                                   self.INPUT_RASTER, context)
        rasterPath = raster_layer.source()

        rasterDS = gdal.Open(rasterPath, gdal.GA_ReadOnly)
        geoTransform = rasterDS.GetGeoTransform()

        fields = QgsFields()
        fields.append(QgsField('id', QVariant.Int, '', 10, 0))
        fields.append(QgsField('poly_id', QVariant.Int, '', 10, 0))
        fields.append(QgsField('point_id', QVariant.Int, '', 10, 0))

        (sink, dest_id) = self.parameterAsSink(parameters, self.OUTPUT,
                                               context, fields,
                                               QgsWkbTypes.Point,
                                               raster_layer.crs())
        if sink is None:
            raise QgsProcessingException(
                self.invalidSinkError(parameters, self.OUTPUT))

        outFeature = QgsFeature()
        outFeature.setFields(fields)

        fid = 0
        polyId = 0
        pointId = 0

        features = source.getFeatures(QgsFeatureRequest().setDestinationCrs(
            raster_layer.crs(), context.transformContext()))
        total = 100.0 / source.featureCount() if source.featureCount() else 0
        for current, f in enumerate(features):
            if feedback.isCanceled():
                break

            if not f.hasGeometry():
                continue

            geom = f.geometry()
            bbox = geom.boundingBox()

            xMin = bbox.xMinimum()
            xMax = bbox.xMaximum()
            yMin = bbox.yMinimum()
            yMax = bbox.yMaximum()

            (startRow,
             startColumn) = raster.mapToPixel(xMin, yMax, geoTransform)
            (endRow, endColumn) = raster.mapToPixel(xMax, yMin, geoTransform)

            # use prepared geometries for faster intersection tests
            engine = QgsGeometry.createGeometryEngine(geom.constGet())
            engine.prepareGeometry()

            for row in range(startRow, endRow + 1):
                for col in range(startColumn, endColumn + 1):
                    if feedback.isCanceled():
                        break

                    (x, y) = raster.pixelToMap(row, col, geoTransform)
                    point = QgsPoint(x, y)

                    if engine.contains(point):
                        outFeature.setGeometry(QgsGeometry(point))
                        outFeature['id'] = fid
                        outFeature['poly_id'] = polyId
                        outFeature['point_id'] = pointId

                        fid += 1
                        pointId += 1

                        sink.addFeature(outFeature, QgsFeatureSink.FastInsert)

            pointId = 0
            polyId += 1

            feedback.setProgress(int(current * total))

        return {self.OUTPUT: dest_id}
Example #24
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))

        field_name = self.parameterAsString(parameters, self.FIELD, context)
        type = self.parameterAsEnum(parameters, self.TYPE, context)
        use_field = bool(field_name)

        field_index = -1

        fields = QgsFields()
        fields.append(QgsField('id', QVariant.Int, '', 20))

        if use_field:
            # keep original field type, name and parameters
            field_index = source.fields().lookupField(field_name)
            if field_index >= 0:
                fields.append(source.fields()[field_index])
        if type == 0:
            # envelope
            fields.append(QgsField('width', QVariant.Double, '', 20, 6))
            fields.append(QgsField('height', QVariant.Double, '', 20, 6))
            fields.append(QgsField('area', QVariant.Double, '', 20, 6))
            fields.append(QgsField('perimeter', QVariant.Double, '', 20, 6))
        elif type == 1:
            # oriented rect
            fields.append(QgsField('width', QVariant.Double, '', 20, 6))
            fields.append(QgsField('height', QVariant.Double, '', 20, 6))
            fields.append(QgsField('angle', QVariant.Double, '', 20, 6))
            fields.append(QgsField('area', QVariant.Double, '', 20, 6))
            fields.append(QgsField('perimeter', QVariant.Double, '', 20, 6))
        elif type == 2:
            # circle
            fields.append(QgsField('radius', QVariant.Double, '', 20, 6))
            fields.append(QgsField('area', QVariant.Double, '', 20, 6))
        elif type == 3:
            # convex hull
            fields.append(QgsField('area', QVariant.Double, '', 20, 6))
            fields.append(QgsField('perimeter', QVariant.Double, '', 20, 6))

        (sink, dest_id) = self.parameterAsSink(parameters, self.OUTPUT,
                                               context, fields,
                                               QgsWkbTypes.Polygon,
                                               source.sourceCrs())
        if sink is None:
            raise QgsProcessingException(
                self.invalidSinkError(parameters, self.OUTPUT))

        if field_index >= 0:
            geometry_dict = {}
            bounds_dict = {}
            total = 50.0 / source.featureCount() if source.featureCount(
            ) else 1
            features = source.getFeatures(
                QgsFeatureRequest().setSubsetOfAttributes([field_index]))
            for current, f in enumerate(features):
                if feedback.isCanceled():
                    break

                if not f.hasGeometry():
                    continue

                if type == 0:
                    # bounding boxes - calculate on the fly for efficiency
                    if not f.attributes()[field_index] in bounds_dict:
                        bounds_dict[f.attributes()[field_index]] = f.geometry(
                        ).boundingBox()
                    else:
                        bounds_dict[f.attributes()
                                    [field_index]].combineExtentWith(
                                        f.geometry().boundingBox())
                else:
                    if not f.attributes()[field_index] in geometry_dict:
                        geometry_dict[f.attributes()[field_index]] = [
                            f.geometry()
                        ]
                    else:
                        geometry_dict[f.attributes()[field_index]].append(
                            f.geometry())

                feedback.setProgress(int(current * total))

            if type == 0:
                # bounding boxes
                current = 0
                total = 50.0 / len(bounds_dict) if bounds_dict else 1
                for group, rect in bounds_dict.items():
                    if feedback.isCanceled():
                        break

                    # envelope
                    feature = QgsFeature()
                    feature.setGeometry(QgsGeometry.fromRect(rect))
                    feature.setAttributes([
                        current, group,
                        rect.width(),
                        rect.height(),
                        rect.area(),
                        rect.perimeter()
                    ])
                    sink.addFeature(feature, QgsFeatureSink.FastInsert)
                    geometry_dict[group] = None

                    feedback.setProgress(50 + int(current * total))
                    current += 1
            else:
                current = 0
                total = 50.0 / len(geometry_dict) if geometry_dict else 1

                for group, geometries in geometry_dict.items():
                    if feedback.isCanceled():
                        break

                    feature = self.createFeature(feedback, current, type,
                                                 geometries, group)
                    sink.addFeature(feature, QgsFeatureSink.FastInsert)
                    geometry_dict[group] = None

                    feedback.setProgress(50 + int(current * total))
                    current += 1
        else:
            total = 80.0 / source.featureCount() if source.featureCount(
            ) else 1
            features = source.getFeatures(
                QgsFeatureRequest().setSubsetOfAttributes([]))
            geometry_queue = []
            bounds = QgsRectangle()
            for current, f in enumerate(features):
                if feedback.isCanceled():
                    break

                if not f.hasGeometry():
                    continue

                if type == 0:
                    # bounding boxes, calculate on the fly for efficiency
                    bounds.combineExtentWith(f.geometry().boundingBox())
                else:
                    geometry_queue.append(f.geometry())
                feedback.setProgress(int(current * total))

            if not feedback.isCanceled():
                if type == 0:
                    feature = QgsFeature()
                    feature.setGeometry(QgsGeometry.fromRect(bounds))
                    feature.setAttributes([
                        0,
                        bounds.width(),
                        bounds.height(),
                        bounds.area(),
                        bounds.perimeter()
                    ])
                else:
                    feature = self.createFeature(feedback, 0, type,
                                                 geometry_queue)
                sink.addFeature(feature, QgsFeatureSink.FastInsert)

        return {self.OUTPUT: dest_id}
Example #25
0
    def transform_attribute(
            self, input_attr_name, algorithm_name, variant="",
            inverse=False, new_attr_name=None, simulate=False):
        """
        Use one of the available transformation algorithms to transform an
        attribute of the layer, and add a new attribute with the
        transformed data
        """
        # get the id of the attribute named input_attr_name
        input_attr_id = self.find_attribute_id(input_attr_name)

        # build the name of the output transformed attribute
        # WARNING! Shape files support max 10 chars for attribute names
        if not new_attr_name:
            if variant:
                new_attr_name = algorithm_name[:5] + '_' + variant[:4]
            else:
                new_attr_name = algorithm_name[:10]
        else:
            new_attr_name = new_attr_name[:10]
        new_attr_name = new_attr_name.replace(' ', '_')
        field = QgsField(new_attr_name, QVariant.Double)
        field.setTypeName(DOUBLE_FIELD_TYPE_NAME)
        if simulate:
            attr_names_dict = self.add_attributes([field], simulate=simulate)
            # get the name actually assigned to the new attribute
            actual_new_attr_name = attr_names_dict[new_attr_name]
            return actual_new_attr_name

        # a dict will contain all the values for the chosen input attribute,
        # keeping as key, for each value, the id of the corresponding feature
        initial_dict = dict()
        for feat in self.layer.getFeatures():
            initial_dict[feat.id()] = feat[input_attr_id]

        # get the transformation algorithm from the register
        algorithm = TRANSFORMATION_ALGS[algorithm_name]

        # transform the values in the dictionary with the chosen algorithm
        try:
            transformed_dict = transform(
                initial_dict, algorithm, variant, inverse)
        except ValueError:
            raise
        except NotImplementedError:
            raise

        attr_names_dict = self.add_attributes([field], simulate=simulate)
        # get the name actually assigned to the new attribute
        actual_new_attr_name = attr_names_dict[new_attr_name]
        # get the id of the new attribute
        new_attr_id = self.find_attribute_id(actual_new_attr_name)

        with LayerEditingManager(
                self.layer, 'Write transformed values', DEBUG):
            for feat in self.layer.getFeatures():
                feat_id = feat.id()
                value = transformed_dict[feat_id]
                if type(value) not in (QPyNullVariant, NoneType):
                    value = float(value)
                self.layer.changeAttributeValue(feat_id, new_attr_id, value)
        return actual_new_attr_name
Example #26
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))

        value_field_name = self.parameterAsString(parameters,
                                                  self.VALUES_FIELD_NAME,
                                                  context)
        category_field_names = self.parameterAsFields(
            parameters, self.CATEGORIES_FIELD_NAME, context)

        value_field_index = source.fields().lookupField(value_field_name)
        if value_field_index >= 0:
            value_field = source.fields().at(value_field_index)
        else:
            value_field = None
        category_field_indexes = [
            source.fields().lookupField(n) for n in category_field_names
        ]

        # generate output fields
        fields = QgsFields()
        for c in category_field_indexes:
            fields.append(source.fields().at(c))

        def addField(name):
            """
            Adds a field to the output, keeping the same data type as the value_field
            """
            field = QgsField(value_field)
            field.setName(name)
            fields.append(field)

        if value_field is None:
            field_type = 'none'
            fields.append(QgsField('count', QVariant.Int))
        elif value_field.isNumeric():
            field_type = 'numeric'
            fields.append(QgsField('count', QVariant.Int))
            fields.append(QgsField('unique', QVariant.Int))
            fields.append(QgsField('min', QVariant.Double))
            fields.append(QgsField('max', QVariant.Double))
            fields.append(QgsField('range', QVariant.Double))
            fields.append(QgsField('sum', QVariant.Double))
            fields.append(QgsField('mean', QVariant.Double))
            fields.append(QgsField('median', QVariant.Double))
            fields.append(QgsField('stddev', QVariant.Double))
            fields.append(QgsField('minority', QVariant.Double))
            fields.append(QgsField('majority', QVariant.Double))
            fields.append(QgsField('q1', QVariant.Double))
            fields.append(QgsField('q3', QVariant.Double))
            fields.append(QgsField('iqr', QVariant.Double))
        elif value_field.type() in (QVariant.Date, QVariant.Time,
                                    QVariant.DateTime):
            field_type = 'datetime'
            fields.append(QgsField('count', QVariant.Int))
            fields.append(QgsField('unique', QVariant.Int))
            fields.append(QgsField('empty', QVariant.Int))
            fields.append(QgsField('filled', QVariant.Int))
            # keep same data type for these fields
            addField('min')
            addField('max')
        else:
            field_type = 'string'
            fields.append(QgsField('count', QVariant.Int))
            fields.append(QgsField('unique', QVariant.Int))
            fields.append(QgsField('empty', QVariant.Int))
            fields.append(QgsField('filled', QVariant.Int))
            # keep same data type for these fields
            addField('min')
            addField('max')
            fields.append(QgsField('min_length', QVariant.Int))
            fields.append(QgsField('max_length', QVariant.Int))
            fields.append(QgsField('mean_length', QVariant.Double))

        request = QgsFeatureRequest().setFlags(QgsFeatureRequest.NoGeometry)
        if value_field is not None:
            attrs = [value_field_index]
        else:
            attrs = []
        attrs.extend(category_field_indexes)
        request.setSubsetOfAttributes(attrs)
        features = source.getFeatures(
            request, QgsProcessingFeatureSource.FlagSkipGeometryValidityChecks)
        total = 50.0 / source.featureCount() if source.featureCount() else 0
        if field_type == 'none':
            values = defaultdict(lambda: 0)
        else:
            values = defaultdict(list)
        for current, feat in enumerate(features):
            if feedback.isCanceled():
                break

            feedback.setProgress(int(current * total))
            attrs = feat.attributes()
            cat = tuple([attrs[c] for c in category_field_indexes])
            if field_type == 'none':
                values[cat] += 1
                continue
            if field_type == 'numeric':
                if attrs[value_field_index] == NULL:
                    continue
                else:
                    value = float(attrs[value_field_index])
            elif field_type == 'string':
                if attrs[value_field_index] == NULL:
                    value = ''
                else:
                    value = str(attrs[value_field_index])
            elif attrs[value_field_index] == NULL:
                value = NULL
            else:
                value = attrs[value_field_index]
            values[cat].append(value)

        (sink, dest_id) = self.parameterAsSink(parameters, self.OUTPUT,
                                               context, fields,
                                               QgsWkbTypes.NoGeometry,
                                               QgsCoordinateReferenceSystem())
        if sink is None:
            raise QgsProcessingException(
                self.invalidSinkError(parameters, self.OUTPUT))

        if field_type == 'none':
            self.saveCounts(values, sink, feedback)
        elif field_type == 'numeric':
            self.calcNumericStats(values, sink, feedback)
        elif field_type == 'datetime':
            self.calcDateTimeStats(values, sink, feedback)
        else:
            self.calcStringStats(values, sink, feedback)

        return {self.OUTPUT: dest_id}
Example #27
0
    def processAlgorithm(self, parameters, context, feedback):
        source = self.parameterAsSource(parameters, self.INPUT_VECTOR, context)
        if source is None:
            raise QgsProcessingException(
                self.invalidSourceError(parameters, self.INPUT_VECTOR))

        raster_layer = self.parameterAsRasterLayer(parameters,
                                                   self.INPUT_RASTER, context)
        rasterPath = raster_layer.source()

        rasterDS = gdal.Open(rasterPath, gdal.GA_ReadOnly)
        geoTransform = rasterDS.GetGeoTransform()
        rasterDS = None

        fields = QgsFields()
        fields.append(QgsField('id', QVariant.Int, '', 10, 0))
        fields.append(QgsField('line_id', QVariant.Int, '', 10, 0))
        fields.append(QgsField('point_id', QVariant.Int, '', 10, 0))

        (sink, dest_id) = self.parameterAsSink(parameters, self.OUTPUT,
                                               context, fields,
                                               QgsWkbTypes.Point,
                                               raster_layer.crs())
        if sink is None:
            raise QgsProcessingException(
                self.invalidSinkError(parameters, self.OUTPUT))

        outFeature = QgsFeature()
        outFeature.setFields(fields)

        self.fid = 0
        self.lineId = 0
        self.pointId = 0

        features = source.getFeatures(QgsFeatureRequest().setDestinationCrs(
            raster_layer.crs(), context.transformContext()))
        total = 100.0 / source.featureCount() if source.featureCount() else 0
        for current, f in enumerate(features):
            if feedback.isCanceled():
                break
            geom = f.geometry()
            if geom.isMultipart():
                lines = geom.asMultiPolyline()
                for line in lines:
                    for i in range(len(line) - 1):
                        p1 = line[i]
                        p2 = line[i + 1]

                        (x1, y1) = raster.mapToPixel(p1.x(), p1.y(),
                                                     geoTransform)
                        (x2, y2) = raster.mapToPixel(p2.x(), p2.y(),
                                                     geoTransform)

                        self.buildLine(x1, y1, x2, y2, geoTransform, sink,
                                       outFeature)
            else:
                points = geom.asPolyline()
                for i in range(len(points) - 1):
                    p1 = points[i]
                    p2 = points[i + 1]

                    (x1, y1) = raster.mapToPixel(p1.x(), p1.y(), geoTransform)
                    (x2, y2) = raster.mapToPixel(p2.x(), p2.y(), geoTransform)

                    self.buildLine(x1, y1, x2, y2, geoTransform, sink,
                                   outFeature)

            self.pointId = 0
            self.lineId += 1

            feedback.setProgress(int(current * total))

        return {self.OUTPUT: dest_id}
Example #28
0
 def testQgsFieldRepr(self):
     f = QgsField('field_name', QVariant.Double, 'double')
     self.assertEqual(f.__repr__(), "<QgsField: field_name (double)>")
Example #29
0
    def processAlgorithm(self, progress):
        polyLayer = dataobjects.getObjectFromUri(
            self.getParameterValue(self.POLYGONS))
        pointLayer = dataobjects.getObjectFromUri(
            self.getParameterValue(self.POINTS))
        fieldName = self.getParameterValue(self.FIELD)
        fieldIdx = pointLayer.fields().lookupField(
            self.getParameterValue(self.WEIGHT))

        fields = polyLayer.fields()
        fields.append(QgsField(fieldName, QVariant.Int))

        (idxCount,
         fieldList) = vector.findOrCreateField(polyLayer, polyLayer.fields(),
                                               fieldName)

        writer = self.getOutputFromName(self.OUTPUT).getVectorWriter(
            fields.toList(), polyLayer.wkbType(), polyLayer.crs())

        spatialIndex = vector.spatialindex(pointLayer)

        ftPoint = QgsFeature()
        outFeat = QgsFeature()
        geom = QgsGeometry()

        features = vector.features(polyLayer)
        total = 100.0 / len(features)
        for current, ftPoly in enumerate(features):
            geom = ftPoly.geometry()
            engine = QgsGeometry.createGeometryEngine(geom.geometry())
            engine.prepareGeometry()

            attrs = ftPoly.attributes()

            count = 0
            points = spatialIndex.intersects(geom.boundingBox())
            if len(points) > 0:
                progress.setText(str(len(points)))
                request = QgsFeatureRequest().setFilterFids(
                    points).setSubsetOfAttributes([fieldIdx])
                fit = pointLayer.getFeatures(request)
                ftPoint = QgsFeature()
                while fit.nextFeature(ftPoint):
                    tmpGeom = QgsGeometry(ftPoint.geometry())
                    if engine.contains(tmpGeom.geometry()):
                        weight = str(ftPoint.attributes()[fieldIdx])
                        try:
                            count += float(weight)
                        except:
                            # Ignore fields with non-numeric values
                            pass

            outFeat.setGeometry(geom)
            if idxCount == len(attrs):
                attrs.append(count)
            else:
                attrs[idxCount] = count
            outFeat.setAttributes(attrs)
            writer.addFeature(outFeat)

            progress.setPercentage(int(current * total))

        del writer
 def test_add_attributes(self):
     field_one = QgsField('first', QVariant.String)
     field_one.setTypeName(STRING_FIELD_TYPE_NAME)
     field_two = QgsField('second', QVariant.Int)
     field_two.setTypeName(INT_FIELD_TYPE_NAME)
     attributes = [field_one, field_two]
     added_attributes = ProcessLayer(self.layer).add_attributes(attributes)
     expected_dict = {'first': 'first',
                      'second': 'second'}
     assert added_attributes == expected_dict
     # Let's add 2 other fields with the same names of the previous ones
     # ==> Since the names are already taken, we expect to add fields with
     # the same names plus '_1'
     field_three = QgsField('first', QVariant.String)
     field_three.setTypeName(STRING_FIELD_TYPE_NAME)
     field_four = QgsField('second', QVariant.Int)
     field_four.setTypeName(INT_FIELD_TYPE_NAME)
     attributes = [field_three, field_four]
     added_attributes = ProcessLayer(self.layer).add_attributes(attributes)
     expected_dict = {'first': 'first_1',
                      'second': 'second_1'}
     assert added_attributes == expected_dict
     # Let's add 2 other fields with the same names of the previous ones
     # ==> Since the names are already taken, as well as the corresponding
     # '_1' versions, we expect to add fields with the same names plus '_2'
     field_five = QgsField('first', QVariant.String)
     field_five.setTypeName(STRING_FIELD_TYPE_NAME)
     field_six = QgsField('second', QVariant.Int)
     field_six.setTypeName(INT_FIELD_TYPE_NAME)
     attributes = [field_five, field_six]
     added_attributes = ProcessLayer(self.layer).add_attributes(attributes)
     expected_dict = {'first': 'first_2',
                      'second': 'second_2'}
     assert added_attributes == expected_dict
Example #31
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)
Example #32
0
def makefield(name, type, length):
    field = QgsField(name, type)
    field.setLength(length)
    return field
    def test1(self):
        d = QgsVirtualLayerDefinition()
        self.assertEqual(d.toString(), "")
        d.setFilePath("/file")
        self.assertEqual(d.toString(), "file:///file")
        self.assertEqual(
            QgsVirtualLayerDefinition.fromUrl(d.toUrl()).filePath(), "/file")
        self.assertEqual(
            QgsVirtualLayerDefinition.fromUrl(strToUrl(
                d.toString())).filePath(), "/file")
        d.setFilePath(os.path.join('C:/', 'file'))
        self.assertEqual(d.toString(), "file:///C:/file")
        # self.assertEqual(QgsVirtualLayerDefinition.fromUrl(d.toUrl()).filePath(), os.path.join('C:/', 'file'))
        d.setQuery("SELECT * FROM mytable")
        self.assertEqual(
            QgsVirtualLayerDefinition.fromUrl(d.toUrl()).query(),
            "SELECT * FROM mytable")
        self.assertEqual(
            QgsVirtualLayerDefinition.fromUrl(strToUrl(d.toString())).query(),
            "SELECT * FROM mytable")

        q = "SELECT * FROM tableéé /*:int*/"
        d.setQuery(q)
        self.assertEqual(
            QgsVirtualLayerDefinition.fromUrl(d.toUrl()).query(), q)
        self.assertEqual(
            QgsVirtualLayerDefinition.fromUrl(strToUrl(d.toString())).query(),
            q)

        s1 = "file://foo&bar=okié"
        d.addSource("name", s1, "provider", "utf8")
        self.assertEqual(
            QgsVirtualLayerDefinition.fromUrl(
                d.toUrl()).sourceLayers()[0].source(), s1)
        self.assertEqual(
            QgsVirtualLayerDefinition.fromUrl(strToUrl(
                d.toString())).sourceLayers()[0].source(), s1)

        n1 = "éé ok"
        d.addSource(n1, s1, "provider")
        self.assertEqual(
            QgsVirtualLayerDefinition.fromUrl(
                d.toUrl()).sourceLayers()[1].name(), n1)
        self.assertEqual(
            QgsVirtualLayerDefinition.fromUrl(strToUrl(
                d.toString())).sourceLayers()[1].name(), n1)

        d.addSource("ref1", "id0001")
        self.assertEqual(
            QgsVirtualLayerDefinition.fromUrl(
                d.toUrl()).sourceLayers()[2].reference(), "id0001")
        self.assertEqual(
            QgsVirtualLayerDefinition.fromUrl(strToUrl(
                d.toString())).sourceLayers()[2].reference(), "id0001")

        s = "dbname='C:\\tt' table=\"test\" (geometry) sql="
        d.addSource("nn", s, "spatialite")
        self.assertEqual(
            QgsVirtualLayerDefinition.fromUrl(
                d.toUrl()).sourceLayers()[3].source(), s)
        self.assertEqual(
            QgsVirtualLayerDefinition.fromUrl(strToUrl(
                d.toString())).sourceLayers()[3].source(), s)

        d.setGeometryField("geom")
        self.assertEqual(
            QgsVirtualLayerDefinition.fromUrl(d.toUrl()).geometryField(),
            "geom")
        self.assertEqual(
            QgsVirtualLayerDefinition.fromUrl(strToUrl(
                d.toString())).geometryField(), "geom")

        d.setGeometryWkbType(QgsWkbTypes.Point)
        self.assertEqual(
            QgsVirtualLayerDefinition.fromUrl(d.toUrl()).geometryWkbType(),
            QgsWkbTypes.Point)
        self.assertEqual(
            QgsVirtualLayerDefinition.fromUrl(strToUrl(
                d.toString())).geometryWkbType(), QgsWkbTypes.Point)

        f = QgsFields()
        f.append(QgsField("a", QVariant.Int))
        f.append(QgsField("f", QVariant.Double))
        f.append(QgsField("s", QVariant.String))
        d.setFields(f)
        f2 = QgsVirtualLayerDefinition.fromUrl(d.toUrl()).fields()
        self.assertEqual(f[0].name(), f2[0].name())
        self.assertEqual(f[0].type(), f2[0].type())
        self.assertEqual(f[1].name(), f2[1].name())
        self.assertEqual(f[1].type(), f2[1].type())
        self.assertEqual(f[2].name(), f2[2].name())
        self.assertEqual(f[2].type(), f2[2].type())
    def testUpdateMode(self):
        """ Test that on-the-fly re-opening in update/read-only mode works """

        tmpdir = tempfile.mkdtemp()
        self.dirs_to_cleanup.append(tmpdir)
        srcpath = os.path.join(TEST_DATA_DIR, 'provider')
        for file in glob.glob(os.path.join(srcpath, 'shapefile.*')):
            shutil.copy(os.path.join(srcpath, file), tmpdir)
        datasource = os.path.join(tmpdir, 'shapefile.shp')

        vl = QgsVectorLayer(u'{}|layerid=0'.format(datasource), u'test',
                            u'ogr')
        caps = vl.dataProvider().capabilities()
        self.assertTrue(caps & QgsVectorDataProvider.AddFeatures)
        self.assertTrue(caps & QgsVectorDataProvider.DeleteFeatures)
        self.assertTrue(caps & QgsVectorDataProvider.ChangeAttributeValues)
        self.assertTrue(caps & QgsVectorDataProvider.AddAttributes)
        self.assertTrue(caps & QgsVectorDataProvider.DeleteAttributes)
        self.assertTrue(caps & QgsVectorDataProvider.CreateSpatialIndex)
        self.assertTrue(caps & QgsVectorDataProvider.SelectAtId)
        self.assertTrue(caps & QgsVectorDataProvider.ChangeGeometries)
        #self.assertTrue(caps & QgsVectorDataProvider.ChangeFeatures)

        # We should be really opened in read-only mode even if write capabilities are declared
        self.assertEquals(vl.dataProvider().property("_debug_open_mode"),
                          "read-only")

        # Unbalanced call to leaveUpdateMode()
        self.assertFalse(vl.dataProvider().leaveUpdateMode())

        # Test that startEditing() / commitChanges() plays with enterUpdateMode() / leaveUpdateMode()
        self.assertTrue(vl.startEditing())
        self.assertEquals(vl.dataProvider().property("_debug_open_mode"),
                          "read-write")
        self.assertTrue(vl.dataProvider().isValid())

        self.assertTrue(vl.commitChanges())
        self.assertEquals(vl.dataProvider().property("_debug_open_mode"),
                          "read-only")
        self.assertTrue(vl.dataProvider().isValid())

        # Manual enterUpdateMode() / leaveUpdateMode() with 2 depths
        self.assertTrue(vl.dataProvider().enterUpdateMode())
        self.assertEquals(vl.dataProvider().property("_debug_open_mode"),
                          "read-write")
        caps = vl.dataProvider().capabilities()
        self.assertTrue(caps & QgsVectorDataProvider.AddFeatures)

        f = QgsFeature()
        f.setAttributes([200])
        f.setGeometry(QgsGeometry.fromWkt('Point (2 49)'))
        (ret, feature_list) = vl.dataProvider().addFeatures([f])
        self.assertTrue(ret)
        fid = feature_list[0].id()

        features = [
            f_iter
            for f_iter in vl.getFeatures(QgsFeatureRequest().setFilterFid(fid))
        ]
        values = [f_iter['pk'] for f_iter in features]
        self.assertEquals(values, [200])

        got_geom = [f_iter.geometry() for f_iter in features][0].geometry()
        self.assertEquals((got_geom.x(), got_geom.y()), (2.0, 49.0))

        self.assertTrue(vl.dataProvider().changeGeometryValues(
            {fid: QgsGeometry.fromWkt('Point (3 50)')}))
        self.assertTrue(vl.dataProvider().changeAttributeValues(
            {fid: {
                0: 100
            }}))

        features = [
            f_iter
            for f_iter in vl.getFeatures(QgsFeatureRequest().setFilterFid(fid))
        ]
        values = [f_iter['pk'] for f_iter in features]

        got_geom = [f_iter.geometry() for f_iter in features][0].geometry()
        self.assertEquals((got_geom.x(), got_geom.y()), (3.0, 50.0))

        self.assertTrue(vl.dataProvider().deleteFeatures([fid]))

        # Check that it has really disappeared
        osgeo.gdal.PushErrorHandler('CPLQuietErrorHandler')
        features = [
            f_iter
            for f_iter in vl.getFeatures(QgsFeatureRequest().setFilterFid(fid))
        ]
        osgeo.gdal.PopErrorHandler()
        self.assertEquals(features, [])

        self.assertTrue(vl.dataProvider().addAttributes(
            [QgsField("new_field", QVariant.Int, "integer")]))
        self.assertTrue(vl.dataProvider().deleteAttributes(
            [len(vl.dataProvider().fields()) - 1]))

        self.assertTrue(vl.startEditing())
        self.assertEquals(vl.dataProvider().property("_debug_open_mode"),
                          "read-write")

        self.assertTrue(vl.commitChanges())
        self.assertEquals(vl.dataProvider().property("_debug_open_mode"),
                          "read-write")

        self.assertTrue(vl.dataProvider().enterUpdateMode())
        self.assertEquals(vl.dataProvider().property("_debug_open_mode"),
                          "read-write")

        self.assertTrue(vl.dataProvider().leaveUpdateMode())
        self.assertEquals(vl.dataProvider().property("_debug_open_mode"),
                          "read-write")

        self.assertTrue(vl.dataProvider().leaveUpdateMode())
        self.assertEquals(vl.dataProvider().property("_debug_open_mode"),
                          "read-only")

        # Test that update mode will be implictly enabled if doing an action
        # that requires update mode
        (ret, _) = vl.dataProvider().addFeatures([QgsFeature()])
        self.assertTrue(ret)
        self.assertEquals(vl.dataProvider().property("_debug_open_mode"),
                          "read-write")
Example #35
0
    def run(self):
        """Specific stuff at tool activating."""

        cur_carhab_lyr = CarhabLayerRegistry.instance().getCurrentCarhabLayer()
        if not cur_carhab_lyr:
            no_carhab_lyr_msg()
            return
        csv_dir = QFileDialog.getExistingDirectory(None, "Select a folder:", None, QFileDialog.ShowDirsOnly)
        if csv_dir:
            now = time.strftime("%Y-%m-%d-%H%M%S")
            directory = os.path.join(csv_dir, cur_carhab_lyr.getName() + "_" + now)
            if not os.path.exists(directory):
                os.makedirs(directory)

            for tbl_name, desc in Config.DB_STRUCTURE:
                file_name = desc.get("std_name")
                tbl_fields = desc.get("fields")
                if file_name:
                    if not desc.get("spatial"):
                        csv_name = file_name if file_name.endswith(".csv") else file_name + ".csv"
                        csv_path = os.path.join(directory, csv_name)
                        field_names = [row[1].get("std_name") for row in tbl_fields if row[1].get("std_name")]
                        db = DbManager(cur_carhab_lyr.dbPath)
                        r = Recorder(db, tbl_name)
                        tbl_rows = r.select_all()
                        csv_rows = []
                        for tbl_row in tbl_rows:
                            csv_row = {}
                            for dbf, value in tbl_row.items():
                                for field in desc.get("fields"):
                                    if dbf == field[0] and field[1].get("std_name"):
                                        csv_row[encode(field[1].get("std_name"))] = encode(value)
                                        break
                            csv_rows.append(csv_row)

                        with open(csv_path, "wb") as csv_file:
                            writer = csv.DictWriter(csv_file, field_names)
                            writer.writeheader()
                            writer.writerows(csv_rows)
                    else:
                        for vlyr in cur_carhab_lyr.getQgisLayers():
                            vlyr_tbl = QgsDataSourceURI(vlyr.dataProvider().dataSourceUri()).table()
                            if tbl_name == vlyr_tbl:
                                shp_name = file_name if file_name.endswith(".shp") else file_name + ".shp"
                                shp_path = os.path.join(directory, shp_name)
                                QgsVectorFileWriter.writeAsVectorFormat(vlyr, shp_path, "utf-8", None)
                                shp_lyr = QgsVectorLayer(shp_path, "", "ogr")
                                shapefile = shp_lyr.dataProvider()
                                features = shapefile.getFeatures()
                                attrs_to_del = []
                                for attr, attr_desc in tbl_fields:
                                    std_attr = attr_desc.get("std_name")
                                    if not std_attr == attr:
                                        if std_attr:
                                            cur_field = shapefile.fields().field(attr)
                                            new_field = QgsField(cur_field)
                                            new_field.setName(std_attr)
                                            shapefile.addAttributes([new_field])
                                            for feat in features:
                                                idx = shapefile.fields().indexFromName(std_attr)
                                                update_map = {feat.id(): {idx: feat[attr]}}
                                                shapefile.changeAttributeValues(update_map)
                                        attrs_to_del.append(shapefile.fields().indexFromName(attr))
                                shapefile.deleteAttributes(attrs_to_del)
            popup("Export effectué")
Example #36
0
    def regularMatrix(self, parameters, context, source, inField,
                      target_source, targetField, nPoints, feedback):

        distArea = QgsDistanceArea()
        distArea.setSourceCrs(source.sourceCrs(), context.transformContext())
        distArea.setEllipsoid(context.project().ellipsoid())

        inIdx = source.fields().lookupField(inField)
        targetIdx = target_source.fields().lookupField(targetField)

        index = QgsSpatialIndex(
            target_source.getFeatures(
                QgsFeatureRequest().setSubsetOfAttributes(
                    []).setDestinationCrs(source.sourceCrs(),
                                          context.transformContext())),
            feedback)

        first = True
        sink = None
        dest_id = None
        features = source.getFeatures(
            QgsFeatureRequest().setSubsetOfAttributes([inIdx]))
        total = 100.0 / source.featureCount() if source.featureCount() else 0
        for current, inFeat in enumerate(features):
            if feedback.isCanceled():
                break

            inGeom = inFeat.geometry()
            if first:
                featList = index.nearestNeighbor(inGeom.asPoint(), nPoints)
                first = False
                fields = QgsFields()
                input_id_field = source.fields()[inIdx]
                input_id_field.setName('ID')
                fields.append(input_id_field)
                for f in target_source.getFeatures(
                        QgsFeatureRequest().setFilterFids(
                            featList).setSubsetOfAttributes([
                                targetIdx
                            ]).setDestinationCrs(source.sourceCrs(),
                                                 context.transformContext())):
                    fields.append(
                        QgsField(str(f[targetField]), QVariant.Double))

                (sink, dest_id) = self.parameterAsSink(parameters, self.OUTPUT,
                                                       context, fields,
                                                       source.wkbType(),
                                                       source.sourceCrs())
                if sink is None:
                    raise QgsProcessingException(
                        self.invalidSinkError(parameters, self.OUTPUT))

            data = [inFeat[inField]]
            for target in target_source.getFeatures(
                    QgsFeatureRequest().setSubsetOfAttributes(
                        []).setFilterFids(featList).setDestinationCrs(
                            source.sourceCrs(), context.transformContext())):
                if feedback.isCanceled():
                    break
                outGeom = target.geometry()
                dist = distArea.measureLine(inGeom.asPoint(),
                                            outGeom.asPoint())
                data.append(dist)

            out_feature = QgsFeature()
            out_feature.setGeometry(inGeom)
            out_feature.setAttributes(data)
            sink.addFeature(out_feature, QgsFeatureSink.FastInsert)
            feedback.setProgress(int(current * total))

        return {self.OUTPUT: dest_id}
Example #37
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)
Example #38
0
    def linearMatrix(self, parameters, context, source, inField, target_source, targetField, same_source_and_target,
                     matType, nPoints, feedback):

        if same_source_and_target:
            # need to fetch an extra point from the index, since the closest match will always be the same
            # as the input feature
            nPoints += 1

        inIdx = source.fields().lookupField(inField)
        outIdx = target_source.fields().lookupField(targetField)

        fields = QgsFields()
        input_id_field = source.fields()[inIdx]
        input_id_field.setName('InputID')
        fields.append(input_id_field)
        if matType == 0:
            target_id_field = target_source.fields()[outIdx]
            target_id_field.setName('TargetID')
            fields.append(target_id_field)
            fields.append(QgsField('Distance', QVariant.Double))
        else:
            fields.append(QgsField('MEAN', QVariant.Double))
            fields.append(QgsField('STDDEV', QVariant.Double))
            fields.append(QgsField('MIN', QVariant.Double))
            fields.append(QgsField('MAX', QVariant.Double))

        out_wkb = QgsWkbTypes.multiType(source.wkbType()) if matType == 0 else source.wkbType()
        (sink, dest_id) = self.parameterAsSink(parameters, self.OUTPUT, context,
                                               fields, out_wkb, source.sourceCrs())
        if sink is None:
            raise QgsProcessingException(self.invalidSinkError(parameters, self.OUTPUT))

        index = QgsSpatialIndex(target_source.getFeatures(QgsFeatureRequest().setSubsetOfAttributes([]).setDestinationCrs(source.sourceCrs(), context.transformContext())), feedback)

        distArea = QgsDistanceArea()
        distArea.setSourceCrs(source.sourceCrs(), context.transformContext())
        distArea.setEllipsoid(context.project().ellipsoid())

        features = source.getFeatures(QgsFeatureRequest().setSubsetOfAttributes([inIdx]))
        total = 100.0 / source.featureCount() if source.featureCount() else 0
        for current, inFeat in enumerate(features):
            if feedback.isCanceled():
                break

            inGeom = inFeat.geometry()
            inID = str(inFeat.attributes()[inIdx])
            featList = index.nearestNeighbor(inGeom.asPoint(), nPoints)
            distList = []
            vari = 0.0
            request = QgsFeatureRequest().setFilterFids(featList).setSubsetOfAttributes([outIdx]).setDestinationCrs(source.sourceCrs(), context.transformContext())
            for outFeat in target_source.getFeatures(request):
                if feedback.isCanceled():
                    break

                if same_source_and_target and inFeat.id() == outFeat.id():
                    continue

                outID = outFeat.attributes()[outIdx]
                outGeom = outFeat.geometry()
                dist = distArea.measureLine(inGeom.asPoint(),
                                            outGeom.asPoint())

                if matType == 0:
                    out_feature = QgsFeature()
                    out_geom = QgsGeometry.unaryUnion([inFeat.geometry(), outFeat.geometry()])
                    out_feature.setGeometry(out_geom)
                    out_feature.setAttributes([inID, outID, dist])
                    sink.addFeature(out_feature, QgsFeatureSink.FastInsert)
                else:
                    distList.append(float(dist))

            if matType != 0:
                mean = sum(distList) / len(distList)
                for i in distList:
                    vari += (i - mean) * (i - mean)
                vari = math.sqrt(vari / len(distList))

                out_feature = QgsFeature()
                out_feature.setGeometry(inFeat.geometry())
                out_feature.setAttributes([inID, mean, vari, min(distList), max(distList)])
                sink.addFeature(out_feature, QgsFeatureSink.FastInsert)

            feedback.setProgress(int(current * total))

        return {self.OUTPUT: dest_id}
Example #39
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
Example #40
0
def exportLayers(iface, layers, folder, precision, optimize, popupField, json,
                 restrictToExtent, extent, feedback):
    canvas = iface.mapCanvas()
    epsg4326 = QgsCoordinateReferenceSystem("EPSG:4326")
    layersFolder = os.path.join(folder, "layers")
    QDir().mkpath(layersFolder)
    for count, (layer, encode2json,
                popup) in enumerate(zip(layers, json, popupField)):
        if (layer.type() == layer.VectorLayer
                and (layer.providerType() != "WFS" or encode2json)):
            feedback.showFeedback("Exporting %s to JSON..." % layer.name())
            cleanLayer = writeTmpLayer(layer, popup, restrictToExtent, iface,
                                       extent)
            fields = layer.pendingFields()
            for field in fields:
                exportImages(layer, field.name(), layersFolder + "/tmp.tmp")
            if is25d(layer, canvas, restrictToExtent, extent):
                provider = cleanLayer.dataProvider()
                provider.addAttributes([
                    QgsField("height", QVariant.Double),
                    QgsField("wallColor", QVariant.String),
                    QgsField("roofColor", QVariant.String)
                ])
                cleanLayer.updateFields()
                fields = cleanLayer.pendingFields()
                renderer = layer.rendererV2()
                renderContext = QgsRenderContext.fromMapSettings(
                    canvas.mapSettings())
                feats = layer.getFeatures()
                context = QgsExpressionContext()
                context.appendScope(
                    QgsExpressionContextUtils.layerScope(layer))
                expression = QgsExpression('eval(@qgis_25d_height)')
                heightField = fields.indexFromName("height")
                wallField = fields.indexFromName("wallColor")
                roofField = fields.indexFromName("roofColor")
                renderer.startRender(renderContext, fields)
                cleanLayer.startEditing()
                for feat in feats:
                    context.setFeature(feat)
                    height = expression.evaluate(context)
                    if isinstance(renderer, QgsCategorizedSymbolRendererV2):
                        classAttribute = renderer.classAttribute()
                        attrValue = feat.attribute(classAttribute)
                        catIndex = renderer.categoryIndexForValue(attrValue)
                        categories = renderer.categories()
                        symbol = categories[catIndex].symbol()
                    elif isinstance(renderer, QgsGraduatedSymbolRendererV2):
                        classAttribute = renderer.classAttribute()
                        attrValue = feat.attribute(classAttribute)
                        ranges = renderer.ranges()
                        for range in ranges:
                            if (attrValue >= range.lowerValue()
                                    and attrValue <= range.upperValue()):
                                symbol = range.symbol().clone()
                    else:
                        symbol = renderer.symbolForFeature2(
                            feat, renderContext)
                    sl1 = symbol.symbolLayer(1)
                    sl2 = symbol.symbolLayer(2)
                    wallColor = sl1.subSymbol().color().name()
                    roofColor = sl2.subSymbol().color().name()
                    provider.changeAttributeValues({
                        feat.id() + 1: {
                            heightField: height,
                            wallField: wallColor,
                            roofField: roofColor
                        }
                    })
                cleanLayer.commitChanges()
                renderer.stopRender(renderContext)

            sln = safeName(cleanLayer.name()) + unicode(count)
            tmpPath = os.path.join(layersFolder, sln + ".json")
            path = os.path.join(layersFolder, sln + ".js")
            options = []
            if precision != "maintain":
                options.append("COORDINATE_PRECISION=" + unicode(precision))
            QgsVectorFileWriter.writeAsVectorFormat(cleanLayer,
                                                    tmpPath,
                                                    "utf-8",
                                                    epsg4326,
                                                    'GeoJson',
                                                    0,
                                                    layerOptions=options)
            with open(path, "w") as f:
                f.write("var %s = " % ("geojson_" + sln))
                with open(tmpPath, "r") as f2:
                    for line in f2:
                        if optimize:
                            line = line.strip("\n\t ")
                            line = removeSpaces(line)
                        f.write(line)
            os.remove(tmpPath)

        elif (layer.type() == layer.RasterLayer
              and layer.providerType() != "wms"):

            feedback.showFeedback("Exporting %s to PNG..." % layer.name())
            name_ts = (safeName(layer.name()) + unicode(count) +
                       unicode(int(time.time())))

            # We need to create a new file to export style
            piped_file = os.path.join(tempfile.gettempdir(),
                                      name_ts + '_piped.tif')

            piped_extent = layer.extent()
            piped_width = layer.height()
            piped_height = layer.width()
            piped_crs = layer.crs()
            piped_renderer = layer.renderer()
            piped_provider = layer.dataProvider()

            pipe = QgsRasterPipe()
            pipe.set(piped_provider.clone())
            pipe.set(piped_renderer.clone())

            file_writer = QgsRasterFileWriter(piped_file)

            file_writer.writeRaster(pipe, piped_width, piped_height,
                                    piped_extent, piped_crs)

            # Extent of the layer in EPSG:3857
            crsSrc = layer.crs()
            crsDest = QgsCoordinateReferenceSystem(3857)
            xform = QgsCoordinateTransform(crsSrc, crsDest)
            extentRep = xform.transform(layer.extent())

            extentRepNew = ','.join([
                unicode(extentRep.xMinimum()),
                unicode(extentRep.xMaximum()),
                unicode(extentRep.yMinimum()),
                unicode(extentRep.yMaximum())
            ])

            # Reproject in 3857
            piped_3857 = os.path.join(tempfile.gettempdir(),
                                      name_ts + '_piped_3857.tif')
            # Export layer as PNG
            out_raster = os.path.join(
                layersFolder,
                safeName(layer.name()) + unicode(count) + ".png")

            qgis_version = QGis.QGIS_VERSION

            if int(qgis_version.split('.')[1]) < 15:
                processing.runalg("gdalogr:warpreproject", piped_file,
                                  layer.crs().authid(), "EPSG:3857", "", 0, 1,
                                  0, -1, 75, 6, 1, False, 0, False, "",
                                  piped_3857)
                processing.runalg("gdalogr:translate", piped_3857, 100, True,
                                  "", 0, "", extentRepNew, False, 0, 0, 75, 6,
                                  1, False, 0, False, "", out_raster)
            else:
                try:
                    warpArgs = {
                        "INPUT": piped_file,
                        "SOURCE_SRS": layer.crs().authid(),
                        "DEST_SRS": "EPSG:3857",
                        "NO_DATA": "",
                        "TR": 0,
                        "METHOD": 2,
                        "RAST_EXT": extentRepNew,
                        "EXT_CRS": "EPSG:3857",
                        "RTYPE": 0,
                        "COMPRESS": 4,
                        "JPEGCOMPRESSION": 75,
                        "ZLEVEL": 6,
                        "PREDICTOR": 1,
                        "TILED": False,
                        "BIGTIFF": 0,
                        "TFW": False,
                        "EXTRA": "",
                        "OUTPUT": piped_3857
                    }
                    procRtn = processing.runalg("gdalogr:warpreproject",
                                                warpArgs)
                    # force exception on algorithm fail
                    for val in procRtn:
                        pass
                except:
                    try:
                        warpArgs = {
                            "INPUT": piped_file,
                            "SOURCE_SRS": layer.crs().authid(),
                            "DEST_SRS": "EPSG:3857",
                            "NO_DATA": "",
                            "TR": 0,
                            "METHOD": 2,
                            "RAST_EXT": extentRepNew,
                            "RTYPE": 0,
                            "COMPRESS": 4,
                            "JPEGCOMPRESSION": 75,
                            "ZLEVEL": 6,
                            "PREDICTOR": 1,
                            "TILED": False,
                            "BIGTIFF": 0,
                            "TFW": False,
                            "EXTRA": "",
                            "OUTPUT": piped_3857
                        }
                        procRtn = processing.runalg("gdalogr:warpreproject",
                                                    warpArgs)
                        # force exception on algorithm fail
                        for val in procRtn:
                            pass
                    except:
                        try:
                            warpArgs = {
                                "INPUT": piped_file,
                                "SOURCE_SRS": layer.crs().authid(),
                                "DEST_SRS": "EPSG:3857",
                                "NO_DATA": "",
                                "TR": 0,
                                "METHOD": 2,
                                "RTYPE": 0,
                                "COMPRESS": 4,
                                "JPEGCOMPRESSION": 75,
                                "ZLEVEL": 6,
                                "PREDICTOR": 1,
                                "TILED": False,
                                "BIGTIFF": 0,
                                "TFW": False,
                                "EXTRA": "",
                                "OUTPUT": piped_3857
                            }
                            procRtn = processing.runalg(
                                "gdalogr:warpreproject", warpArgs)
                            # force exception on algorithm fail
                            for val in procRtn:
                                pass
                        except:
                            shutil.copyfile(piped_file, piped_3857)

                try:
                    processing.runalg("gdalogr:translate", piped_3857, 100,
                                      True, "", 0, "", extentRepNew, False, 5,
                                      4, 75, 6, 1, False, 0, False, "",
                                      out_raster)
                except:
                    shutil.copyfile(piped_3857, out_raster)
    feedback.completeStep()
Example #41
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
Example #42
0
    def processAlgorithm(self, parameters, context, feedback):
        source = self.parameterAsSource(parameters, self.INPUT, context)

        extent = self.parameterAsExtent(parameters, self.TARGET_AREA, context)
        target_crs = self.parameterAsCrs(parameters, self.TARGET_AREA_CRS,
                                         context)

        target_geom = QgsGeometry.fromRect(extent)

        fields = QgsFields()
        fields.append(QgsField('auth_id', QVariant.String, '', 20))

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

        # make intersection tests nice and fast
        engine = QgsGeometry.createGeometryEngine(target_geom.constGet())
        engine.prepareGeometry()

        layer_bounds = QgsGeometry.fromRect(source.sourceExtent())

        crses_to_check = QgsCoordinateReferenceSystem.validSrsIds()
        total = 100.0 / len(crses_to_check)

        found_results = 0

        transform_context = QgsCoordinateTransformContext()
        for current, srs_id in enumerate(crses_to_check):
            if feedback.isCanceled():
                break

            candidate_crs = QgsCoordinateReferenceSystem.fromSrsId(srs_id)
            if not candidate_crs.isValid():
                continue

            transform_candidate = QgsCoordinateTransform(
                candidate_crs, target_crs, transform_context)
            transformed_bounds = QgsGeometry(layer_bounds)
            try:
                if not transformed_bounds.transform(transform_candidate) == 0:
                    continue
            except:
                continue

            try:
                if engine.intersects(transformed_bounds.constGet()):
                    feedback.pushInfo(
                        self.tr('Found candidate CRS: {}').format(
                            candidate_crs.authid()))
                    f = QgsFeature(fields)
                    f.setAttributes([candidate_crs.authid()])
                    sink.addFeature(f, QgsFeatureSink.FastInsert)
                    found_results += 1
            except:
                continue

            feedback.setProgress(int(current * total))

        if found_results == 0:
            feedback.reportError(self.tr('No matching projections found'))

        return {self.OUTPUT: dest_id}
Example #43
0
    def testWidget(self):
        """Test widget operations"""

        widget = QgsAggregateMappingWidget()
        for i in range(10):
            widget.appendField(QgsField(str(i)), source=str(i))
        self.assertTrue(widget.model().rowCount(QModelIndex()), 10)

        def _compare(widget, expected):
            actual = []
            for aggregate in widget.mapping():
                actual.append(int(aggregate.source))
            self.assertEqual(actual, expected)

        _compare(widget, [0, 1, 2, 3, 4, 5, 6, 7, 8, 9])

        selection_model = widget.selectionModel()
        selection_model.clear()
        for i in range(0, 10, 2):
            selection_model.select(widget.model().index(i, 0),
                                   QItemSelectionModel.Select)

        self.assertTrue(widget.moveSelectedFieldsDown())
        _compare(widget, [1, 0, 3, 2, 5, 4, 7, 6, 9, 8])

        selection_model.clear()
        for i in range(1, 10, 2):
            selection_model.select(widget.model().index(i, 0),
                                   QItemSelectionModel.Select)

        self.assertTrue(widget.moveSelectedFieldsUp())
        _compare(widget, [0, 1, 2, 3, 4, 5, 6, 7, 8, 9])

        selection_model.clear()
        for i in range(0, 10, 2):
            selection_model.select(widget.model().index(i, 0),
                                   QItemSelectionModel.Select)

        self.assertTrue(widget.removeSelectedFields())
        _compare(widget, [1, 3, 5, 7, 9])

        widget.setSourceFields(self.source_fields)
        mapping = widget.mapping()

        self.assertEqual(mapping[0].field.name(), 'source_field1')
        self.assertEqual(mapping[0].source, '"source_field1"')
        self.assertEqual(mapping[0].aggregate, 'concatenate')
        self.assertEqual(mapping[0].delimiter, ',')
        self.assertEqual(mapping[1].field.name(), 'source_field2')
        self.assertEqual(mapping[1].source, '"source_field2"')
        self.assertEqual(mapping[1].aggregate, 'sum')
        self.assertEqual(mapping[1].delimiter, ',')

        mapping[0].source = 'upper("source_field2")'
        mapping[0].aggregate = 'first_value'
        mapping[0].delimiter = '|'
        new_aggregate = QgsAggregateMappingModel.Aggregate()
        new_aggregate.field = QgsField('output_field3',
                                       QVariant.Double,
                                       len=4,
                                       prec=2)
        new_aggregate.source = 'randf(1,2)'
        new_aggregate.aggregate = 'mean'
        new_aggregate.delimiter = '*'
        mapping.append(new_aggregate)

        widget.setMapping(mapping)

        mapping = widget.mapping()

        self.assertEqual(mapping[0].field.name(), 'source_field1')
        self.assertEqual(mapping[0].source, 'upper("source_field2")')
        self.assertEqual(mapping[0].aggregate, 'first_value')
        self.assertEqual(mapping[0].delimiter, '|')
        self.assertEqual(mapping[1].field.name(), 'source_field2')
        self.assertEqual(mapping[1].source, '"source_field2"')
        self.assertEqual(mapping[1].aggregate, 'sum')
        self.assertEqual(mapping[1].delimiter, ',')
        self.assertEqual(mapping[2].field.name(), 'output_field3')
        self.assertEqual(mapping[2].source, 'randf(1,2)')
        self.assertEqual(mapping[2].aggregate, 'mean')
        self.assertEqual(mapping[2].delimiter, '*')
Example #44
0
    def testModel(self):
        """Test the mapping model"""

        model = QgsAggregateMappingModel(self.source_fields)
        self.assertEqual(model.rowCount(QModelIndex()), 2)
        self.assertIsNone(model.data(model.index(9999, 0), Qt.DisplayRole))

        self.assertEqual(model.data(model.index(0, 0), Qt.DisplayRole),
                         '"source_field1"')
        self.assertEqual(model.data(model.index(0, 1), Qt.DisplayRole),
                         'concatenate')
        self.assertEqual(model.data(model.index(0, 2), Qt.DisplayRole), ',')
        self.assertEqual(model.data(model.index(0, 3), Qt.DisplayRole),
                         'source_field1')
        self.assertEqual(model.data(model.index(0, 4), Qt.DisplayRole),
                         QVariant.String)
        self.assertEqual(model.data(model.index(0, 5), Qt.DisplayRole), 0)
        self.assertEqual(model.data(model.index(0, 6), Qt.DisplayRole), 0)

        self.assertEqual(model.data(model.index(1, 0), Qt.DisplayRole),
                         '"source_field2"')
        self.assertEqual(model.data(model.index(1, 1), Qt.DisplayRole), 'sum')
        self.assertEqual(model.data(model.index(1, 2), Qt.DisplayRole), ',')
        self.assertEqual(model.data(model.index(1, 3), Qt.DisplayRole),
                         'source_field2')
        self.assertEqual(model.data(model.index(1, 4), Qt.DisplayRole),
                         QVariant.Int)
        self.assertEqual(model.data(model.index(1, 5), Qt.DisplayRole), 10)
        self.assertEqual(model.data(model.index(1, 6), Qt.DisplayRole), 8)

        # Test expression scope
        ctx = model.contextGenerator().createExpressionContext()
        self.assertTrue('source_field1' in ctx.fields().names())

        # Test add fields
        model.appendField(QgsField('field3', QVariant.String),
                          'upper("field3")', 'first_value')
        self.assertEqual(model.rowCount(QModelIndex()), 3)
        self.assertEqual(model.data(model.index(2, 0), Qt.DisplayRole),
                         'upper("field3")')
        self.assertEqual(model.data(model.index(2, 1), Qt.DisplayRole),
                         'first_value')
        self.assertEqual(model.data(model.index(2, 2), Qt.DisplayRole), ',')
        self.assertEqual(model.data(model.index(2, 3), Qt.DisplayRole),
                         'field3')
        self.assertEqual(model.data(model.index(2, 4), Qt.DisplayRole),
                         QVariant.String)
        self.assertEqual(model.data(model.index(2, 5), Qt.DisplayRole), 0)
        self.assertEqual(model.data(model.index(2, 6), Qt.DisplayRole), 0)

        # Test remove field
        model.removeField(model.index(1, 0))
        self.assertEqual(model.rowCount(QModelIndex()), 2)
        self.assertEqual(model.data(model.index(0, 0), Qt.DisplayRole),
                         '"source_field1"')
        self.assertEqual(model.data(model.index(1, 0), Qt.DisplayRole),
                         'upper("field3")')

        # Test edit fields
        mapping = model.mapping()
        self.assertEqual(mapping[0].field.name(), 'source_field1')
        self.assertEqual(mapping[0].aggregate, 'concatenate')
        self.assertEqual(mapping[0].delimiter, ',')
        self.assertEqual(mapping[0].source, '"source_field1"')
        self.assertEqual(mapping[1].field.name(), 'field3')
        self.assertEqual(mapping[1].aggregate, 'first_value')
        self.assertEqual(mapping[1].delimiter, ',')
        self.assertEqual(mapping[1].source, 'upper("field3")')

        # Test move up or down
        self.assertFalse(model.moveUp(model.index(0, 0)))
        self.assertFalse(model.moveUp(model.index(100, 0)))
        self.assertFalse(model.moveDown(model.index(1, 0)))
        self.assertFalse(model.moveDown(model.index(100, 0)))

        self.assertTrue(model.moveDown(model.index(0, 0)))
        mapping = model.mapping()
        self.assertEqual(mapping[0].field.name(), 'field3')
        self.assertEqual(mapping[1].field.name(), 'source_field1')

        self.assertTrue(model.moveUp(model.index(1, 0)))
        mapping = model.mapping()
        self.assertEqual(mapping[0].field.name(), 'source_field1')
        self.assertEqual(mapping[1].field.name(), 'field3')
Example #45
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'])
Example #46
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
Example #47
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
Example #48
0
    def testExportFeatures(self):
        """ Test exporting feature collections """

        fields = QgsFields()
        fields.append(QgsField("name", QVariant.String))
        fields.append(QgsField("cost", QVariant.Double))
        fields.append(QgsField("population", QVariant.Int))

        feature = QgsFeature(fields, 5)
        feature.setGeometry(QgsGeometry(QgsPoint(5, 6)))
        feature.setAttributes(['Valsier Peninsula', 6.8, 198])

        exporter = QgsJsonExporter()

        # single feature
        expected = """{ "type": "FeatureCollection",
    "features":[
{
   "type":"Feature",
   "id":5,
   "geometry":
   {"type": "Point", "coordinates": [5, 6]},
   "properties":{
      "name":"Valsier Peninsula",
      "cost":6.8,
      "population":198
   }
}
]}"""
        self.assertEqual(exporter.exportFeatures([feature]), expected)

        # multiple features
        feature2 = QgsFeature(fields, 6)
        feature2.setGeometry(QgsGeometry(QgsPoint(7, 8)))
        feature2.setAttributes(['Henry Gale Island', 9.7, 38])

        expected = """{ "type": "FeatureCollection",
    "features":[
{
   "type":"Feature",
   "id":5,
   "geometry":
   {"type": "Point", "coordinates": [5, 6]},
   "properties":{
      "name":"Valsier Peninsula",
      "cost":6.8,
      "population":198
   }
},
{
   "type":"Feature",
   "id":6,
   "geometry":
   {"type": "Point", "coordinates": [7, 8]},
   "properties":{
      "name":"Henry Gale Island",
      "cost":9.7,
      "population":38
   }
}
]}"""
        self.assertEqual(exporter.exportFeatures([feature, feature2]),
                         expected)
Example #49
0
 def testQgsFieldRepr(self):
     f = QgsField('field_name', QVariant.Double, 'double')
     self.assertEqual(f.__repr__(), "<QgsField: field_name (double)>")
Example #50
0
    def testJSONExporter(self):
        """ test converting features to GeoJSON """
        fields = QgsFields()
        fields.append(QgsField("name", QVariant.String))
        fields.append(QgsField("cost", QVariant.Double))
        fields.append(QgsField("population", QVariant.Int))

        feature = QgsFeature(fields, 5)
        feature.setGeometry(QgsGeometry(QgsPoint(5, 6)))
        feature.setAttributes(['Valsier Peninsula', 6.8, 198])

        exporter = QgsJsonExporter()

        expected = """{
   "type":"Feature",
   "id":5,
   "geometry":
   {"type": "Point", "coordinates": [5, 6]},
   "properties":{
      "name":"Valsier Peninsula",
      "cost":6.8,
      "population":198
   }
}"""
        self.assertEqual(exporter.exportFeature(feature), expected)

        # test with linestring for bbox inclusion
        l = QgsLineString()
        l.setPoints([QgsPoint(5, 6), QgsPoint(15, 16)])
        feature.setGeometry(QgsGeometry(QgsLineString(l)))

        expected = """{
   "type":"Feature",
   "id":5,
   "bbox":[5, 6, 15, 16],
   "geometry":
   {"type": "LineString", "coordinates": [ [5, 6], [15, 16]]},
   "properties":{
      "name":"Valsier Peninsula",
      "cost":6.8,
      "population":198
   }
}"""
        self.assertEqual(exporter.exportFeature(feature), expected)

        # test that precision is respected
        feature.setGeometry(QgsGeometry(QgsPoint(5.444444444, 6.333333333)))
        exporter.setPrecision(3)
        self.assertEqual(exporter.precision(), 3)
        expected = """{
   "type":"Feature",
   "id":5,
   "geometry":
   {"type": "Point", "coordinates": [5.444, 6.333]},
   "properties":{
      "name":"Valsier Peninsula",
      "cost":6.8,
      "population":198
   }
}"""
        self.assertEqual(exporter.exportFeature(feature), expected)
        feature.setGeometry(QgsGeometry(QgsPoint(5, 6)))
        exporter.setPrecision(17)

        # test that attribute subset is respected
        exporter.setAttributes([0, 2])
        self.assertEqual(exporter.attributes(), [0, 2])
        expected = """{
   "type":"Feature",
   "id":5,
   "geometry":
   {"type": "Point", "coordinates": [5, 6]},
   "properties":{
      "name":"Valsier Peninsula",
      "population":198
   }
}"""
        self.assertEqual(exporter.exportFeature(feature), expected)

        exporter.setAttributes([1])
        self.assertEqual(exporter.attributes(), [1])
        expected = """{
   "type":"Feature",
   "id":5,
   "geometry":
   {"type": "Point", "coordinates": [5, 6]},
   "properties":{
      "cost":6.8
   }
}"""
        self.assertEqual(exporter.exportFeature(feature), expected)
        exporter.setAttributes([])

        # text excluding attributes

        exporter.setExcludedAttributes([1])
        self.assertEqual(exporter.excludedAttributes(), [1])
        expected = """{
   "type":"Feature",
   "id":5,
   "geometry":
   {"type": "Point", "coordinates": [5, 6]},
   "properties":{
      "name":"Valsier Peninsula",
      "population":198
   }
}"""
        self.assertEqual(exporter.exportFeature(feature), expected)

        exporter.setExcludedAttributes([1, 2])
        self.assertEqual(exporter.excludedAttributes(), [1, 2])
        expected = """{
   "type":"Feature",
   "id":5,
   "geometry":
   {"type": "Point", "coordinates": [5, 6]},
   "properties":{
      "name":"Valsier Peninsula"
   }
}"""
        self.assertEqual(exporter.exportFeature(feature), expected)

        exporter.setExcludedAttributes([0, 1, 2])
        self.assertEqual(exporter.excludedAttributes(), [0, 1, 2])
        expected = """{
   "type":"Feature",
   "id":5,
   "geometry":
   {"type": "Point", "coordinates": [5, 6]},
   "properties":null
}"""
        self.assertEqual(exporter.exportFeature(feature), expected)

        # test that excluded attributes take precedence over included

        exporter.setAttributes([1, 2])
        exporter.setExcludedAttributes([0, 1])
        expected = """{
   "type":"Feature",
   "id":5,
   "geometry":
   {"type": "Point", "coordinates": [5, 6]},
   "properties":{
      "population":198
   }
}"""
        self.assertEqual(exporter.exportFeature(feature), expected)

        exporter.setAttributes([])
        exporter.setExcludedAttributes([])

        # test excluding geometry
        exporter.setIncludeGeometry(False)
        self.assertEqual(exporter.includeGeometry(), False)
        feature.setGeometry(QgsGeometry(QgsLineString(l)))

        expected = """{
   "type":"Feature",
   "id":5,
   "geometry":null,
   "properties":{
      "name":"Valsier Peninsula",
      "cost":6.8,
      "population":198
   }
}"""
        self.assertEqual(exporter.exportFeature(feature), expected)
        exporter.setIncludeGeometry(True)

        feature.setGeometry(QgsGeometry(QgsPoint(5, 6)))

        # test excluding attributes
        exporter.setIncludeAttributes(False)
        self.assertEqual(exporter.includeAttributes(), False)
        expected = """{
   "type":"Feature",
   "id":5,
   "geometry":
   {"type": "Point", "coordinates": [5, 6]},
   "properties":null
}"""
        self.assertEqual(exporter.exportFeature(feature), expected)

        exporter.setIncludeGeometry(False)
        expected = """{
   "type":"Feature",
   "id":5,
   "geometry":null,
   "properties":null
}"""
        self.assertEqual(exporter.exportFeature(feature), expected)
        exporter.setIncludeAttributes(True)

        # test overriding ID
        expected = """{
   "type":"Feature",
   "id":29,
   "geometry":null,
   "properties":{
      "name":"Valsier Peninsula",
      "cost":6.8,
      "population":198
   }
}"""
        self.assertEqual(exporter.exportFeature(feature, id=29), expected)

        # test injecting extra attributes
        expected = """{
   "type":"Feature",
   "id":5,
   "geometry":null,
   "properties":{
      "name":"Valsier Peninsula",
      "cost":6.8,
      "population":198,
      "extra":"val1",
      "extra2":2
   }
}"""
        self.assertEqual(
            exporter.exportFeature(feature,
                                   extraProperties={
                                       "extra": "val1",
                                       "extra2": 2
                                   }), expected)

        exporter.setIncludeAttributes(False)
        expected = """{
   "type":"Feature",
   "id":5,
   "geometry":null,
   "properties":{
      "extra":"val1",
      "extra2":{"nested_map":5,
"nested_map2":"val"},
      "extra3":[1,2,3]
   }
}"""
        expected2 = """{
   "type":"Feature",
   "id":5,
   "geometry":null,
   "properties":{
      "extra":"val1",
      "extra2":{"nested_map":5,"nested_map2":"val"},
      "extra3":[1,2,3]
   }
}"""
        exp_f = exporter.exportFeature(feature,
                                       extraProperties={
                                           "extra": "val1",
                                           "extra2": {
                                               "nested_map": 5,
                                               "nested_map2": "val"
                                           },
                                           "extra3": [1, 2, 3]
                                       })
        self.assertTrue(exp_f == expected or exp_f == expected2)
        exporter.setIncludeGeometry(True)
    def saveAutoField( self ):
        """ Do some validation and then call AutoFieldManager """

        # Check layers
        if not self.tblLayers.selectedItems():
            self.msg.show( QApplication.translate( "AutoFieldsDockWidgetPy",
                "[Warning] Please first select a layer." ), 'warning' )
            return

        # Check expression
        expression = u''
        if self.optXCoord.isChecked():
            expression = u'$x'
        elif self.optYCoord.isChecked():
            expression = u'$y'
        elif self.optLength.isChecked():
            expression = u'$length'
        elif self.optPerimeter.isChecked():
            expression = u'$perimeter'
        elif self.optArea.isChecked():
            expression = u'$area'
        elif self.optDate.isChecked():
            expression = u'now()'
        elif self.optCustomExpression.isChecked():
            if self.expressionDlg:
                expression = self.expressionDlg.expression
            if not self.expressionDlg or not expression:
                self.msg.show( QApplication.translate( "AutoFieldsDockWidgetPy",
                    "[Warning] Please first set a valid custom expression." ),
                    'warning' )
                return
        else: # optSpatialValue
            pass

        # Check fields
        fieldName = ''
        if self.optNewField.isChecked():
            if self.txtFieldName.text():

                fieldName = self.txtFieldName.text().strip()
                newField = QgsField( fieldName,
                    self.cboFieldType.itemData( self.cboFieldType.currentIndex(), Qt.UserRole) )

                length = self.txtFieldLength.value()
                precision = self.txtFieldPrecision.value()
                # Ensure length and precision are valid values when dealing with Real numbers
                if self.fieldTypesDict[self.cboFieldType.currentIndex()] == 'Real':
                    if precision > length:
                        precision = length
                newField.setLength( length )
                newField.setPrecision( precision )

                for item in self.tblLayers.selectedItems():
                    if item.column() == 1: # It's the layer name item
                        layer = QgsMapLayerRegistry.instance().mapLayer( item.data( Qt.UserRole ) )
                        if layer.fieldNameIndex( fieldName ) != -1:
                            self.msg.show(
                                QApplication.translate( "AutoFieldsDockWidgetPy",
                                    "[Error] The field " ) + fieldName + \
                                QApplication.translate( "AutoFieldsDockWidgetPy",
                                    " already exists in layer " ) + layer.name() + ". " + \
                                QApplication.translate( "AutoFieldsDockWidgetPy",
                                    " If you want to create an AutoField on it, you need to choose it from 'Existing Field' list." ),
                                'warning' )
                        else:
                            res = layer.dataProvider().addAttributes( [ newField ] )
                            if res:
                                layer.updateFields()

                                # Check if fieldName is preserved by the provider after field creation.
                                if layer.fieldNameIndex( fieldName ) == -1:
                                    self.msg.show(
                                        QApplication.translate( "AutoFieldsDockWidgetPy",
                                            "[Error] The field " ) + fieldName + \
                                        QApplication.translate( "AutoFieldsDockWidgetPy",
                                            " was probably created with another name by the layer (" ) + \
                                        layer.name() + \
                                        QApplication.translate( "AutoFieldsDockWidgetPy",
                                            ") provider. " ) + \
                                        QApplication.translate( "AutoFieldsDockWidgetPy",
                                            " If you want to create an AutoField on it, you need to choose it from 'Existing Field' list." ),
                                        'warning' )
                                else:

                                    self.doSaveAutoField( layer, fieldName, expression )

                            else:
                                self.msg.show( QApplication.translate( "AutoFieldsDockWidgetPy",
                                    "[Error] Couldn't create " ) + newField.name() + \
                                    QApplication.translate( "AutoFieldsDockWidgetPy",
                                        " field in " ) + layer.name() + \
                                    QApplication.translate( "AutoFieldsDockWidgetPy", " layer." ),
                                    'warning' )

                # Some fields might have been created, update the field list once
                self.updateFieldList()

            else:
                self.msg.show( QApplication.translate( "AutoFieldsDockWidgetPy",
                    "[Warning] Please first set a name for the new field." ), 'warning' )
                return
        else:
            fieldName = self.cboField.currentText()

            for item in self.tblLayers.selectedItems():
                if item.column() == 1: # It's the layer name item
                    layer = QgsMapLayerRegistry.instance().mapLayer( item.data( Qt.UserRole ) )
                    self.doSaveAutoField( layer, fieldName, expression )
Example #52
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))

        group_field_name = self.parameterAsString(parameters, self.GROUP_FIELD, context)
        order_field_name = self.parameterAsString(parameters, self.ORDER_FIELD, context)
        date_format = self.parameterAsString(parameters, self.DATE_FORMAT, context)
        text_dir = self.parameterAsString(parameters, self.OUTPUT_TEXT_DIR, context)

        group_field_index = source.fields().lookupField(group_field_name)
        order_field_index = source.fields().lookupField(order_field_name)

        if group_field_index >= 0:
            group_field_def = source.fields().at(group_field_index)
        else:
            group_field_def = None
        order_field_def = source.fields().at(order_field_index)

        fields = QgsFields()
        if group_field_def is not None:
            fields.append(group_field_def)
        begin_field = QgsField(order_field_def)
        begin_field.setName('begin')
        fields.append(begin_field)
        end_field = QgsField(order_field_def)
        end_field.setName('end')
        fields.append(end_field)

        output_wkb = QgsWkbTypes.LineString
        if QgsWkbTypes.hasM(source.wkbType()):
            output_wkb = QgsWkbTypes.addM(output_wkb)
        if QgsWkbTypes.hasZ(source.wkbType()):
            output_wkb = QgsWkbTypes.addZ(output_wkb)

        (sink, dest_id) = self.parameterAsSink(parameters, self.OUTPUT, context,
                                               fields, output_wkb, source.sourceCrs())
        if sink is None:
            raise QgsProcessingException(self.invalidSinkError(parameters, self.OUTPUT))

        points = dict()
        features = source.getFeatures(QgsFeatureRequest().setSubsetOfAttributes([group_field_index, order_field_index]), QgsProcessingFeatureSource.FlagSkipGeometryValidityChecks)
        total = 100.0 / source.featureCount() if source.featureCount() else 0
        for current, f in enumerate(features):
            if feedback.isCanceled():
                break

            if not f.hasGeometry():
                continue

            point = f.geometry().constGet().clone()
            if group_field_index >= 0:
                group = f[group_field_index]
            else:
                group = 1
            order = f[order_field_index]
            if date_format != '':
                order = datetime.strptime(str(order), date_format)
            if group in points:
                points[group].append((order, point))
            else:
                points[group] = [(order, point)]

            feedback.setProgress(int(current * total))

        feedback.setProgress(0)

        da = QgsDistanceArea()
        da.setSourceCrs(source.sourceCrs(), context.transformContext())
        da.setEllipsoid(context.project().ellipsoid())

        current = 0
        total = 100.0 / len(points) if points else 1
        for group, vertices in points.items():
            if feedback.isCanceled():
                break

            vertices.sort(key=lambda x: (x[0] is None, x[0]))
            f = QgsFeature()
            attributes = []
            if group_field_index >= 0:
                attributes.append(group)
            attributes.extend([vertices[0][0], vertices[-1][0]])
            f.setAttributes(attributes)
            line = [node[1] for node in vertices]

            if text_dir:
                fileName = os.path.join(text_dir, '%s.txt' % group)

                with open(fileName, 'w') as fl:
                    fl.write('angle=Azimuth\n')
                    fl.write('heading=Coordinate_System\n')
                    fl.write('dist_units=Default\n')

                    for i in range(len(line)):
                        if i == 0:
                            fl.write('startAt=%f;%f;90\n' % (line[i].x(), line[i].y()))
                            fl.write('survey=Polygonal\n')
                            fl.write('[data]\n')
                        else:
                            angle = line[i - 1].azimuth(line[i])
                            distance = da.measureLine(QgsPointXY(line[i - 1]), QgsPointXY(line[i]))
                            fl.write('%f;%f;90\n' % (angle, distance))

            f.setGeometry(QgsGeometry(QgsLineString(line)))
            sink.addFeature(f, QgsFeatureSink.FastInsert)
            current += 1
            feedback.setProgress(int(current * total))

        return {self.OUTPUT: dest_id}
Example #53
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))

        fields = QgsFields()
        fields.append(QgsField('POINTA', QVariant.Double, '', 24, 15))
        fields.append(QgsField('POINTB', QVariant.Double, '', 24, 15))
        fields.append(QgsField('POINTC', QVariant.Double, '', 24, 15))

        (sink, dest_id) = self.parameterAsSink(parameters, self.OUTPUT,
                                               context, fields,
                                               QgsWkbTypes.Polygon,
                                               source.sourceCrs())
        if sink is None:
            raise QgsProcessingException(
                self.invalidSinkError(parameters, self.OUTPUT))

        pts = []
        ptDict = {}
        ptNdx = -1
        c = voronoi.Context()
        features = source.getFeatures()
        total = 100.0 / source.featureCount() if source.featureCount() else 0
        for current, inFeat in enumerate(features):
            if feedback.isCanceled():
                break

            geom = QgsGeometry(inFeat.geometry())
            if geom.isNull():
                continue
            if geom.isMultipart():
                points = geom.asMultiPoint()
            else:
                points = [geom.asPoint()]
            for n, point in enumerate(points):
                x = point.x()
                y = point.y()
                pts.append((x, y))
                ptNdx += 1
                ptDict[ptNdx] = (inFeat.id(), n)
            feedback.setProgress(int(current * total))

        if len(pts) < 3:
            raise QgsProcessingException(
                self.tr('Input file should contain at least 3 points. Choose '
                        'another file and try again.'))

        uniqueSet = set(item for item in pts)
        ids = [pts.index(item) for item in uniqueSet]
        sl = voronoi.SiteList([voronoi.Site(*i) for i in uniqueSet])
        c.triangulate = True
        voronoi.voronoi(sl, c)
        triangles = c.triangles
        feat = QgsFeature()

        total = 100.0 / len(triangles) if triangles else 1
        for current, triangle in enumerate(triangles):
            if feedback.isCanceled():
                break

            indices = list(triangle)
            indices.append(indices[0])
            polygon = []
            attrs = []
            step = 0
            for index in indices:
                fid, n = ptDict[ids[index]]
                request = QgsFeatureRequest().setFilterFid(fid)
                inFeat = next(source.getFeatures(request))
                geom = QgsGeometry(inFeat.geometry())
                if geom.isMultipart():
                    point = QgsPointXY(geom.asMultiPoint()[n])
                else:
                    point = QgsPointXY(geom.asPoint())
                polygon.append(point)
                if step <= 3:
                    attrs.append(ids[index])
                step += 1
            feat.setAttributes(attrs)
            geometry = QgsGeometry().fromPolygonXY([polygon])
            feat.setGeometry(geometry)
            sink.addFeature(feat, QgsFeatureSink.FastInsert)
            feedback.setProgress(int(current * total))

        return {self.OUTPUT: dest_id}
Example #54
0
def calculate_iri(
    iface, current_layer, project_definition, svi_attr_id, aal_field_name, discarded_feats_ids, iri_operator=None
):
    """
    Copy the AAL and calculate an IRI attribute to the current layer
    """

    # set default
    if iri_operator is None:
        iri_operator = DEFAULT_COMBINATION

    aal_weight = project_definition["children"][0]["weight"]
    svi_weight = project_definition["children"][1]["weight"]

    iri_attr_name = "IRI"
    iri_field = QgsField(iri_attr_name, QVariant.Double)
    iri_field.setTypeName(DOUBLE_FIELD_TYPE_NAME)

    attr_names = ProcessLayer(current_layer).add_attributes([iri_field])

    # get the id of the new attributes
    iri_attr_id = ProcessLayer(current_layer).find_attribute_id(attr_names[iri_attr_name])

    discarded_aal_feats_ids = []

    try:
        with LayerEditingManager(current_layer, "Add IRI", DEBUG):
            for feat in current_layer.getFeatures():
                feat_id = feat.id()
                svi_value = feat.attributes()[svi_attr_id]
                aal_value = feat[aal_field_name]
                if aal_value == QPyNullVariant(float) or feat_id in discarded_feats_ids:
                    iri_value = QPyNullVariant(float)
                    discarded_aal_feats_ids.append(feat_id)
                elif iri_operator == "Sum (simple)":
                    iri_value = svi_value + aal_value
                elif iri_operator == "Multiplication (simple)":
                    iri_value = svi_value * aal_value
                elif iri_operator == "Sum (weighted)":
                    iri_value = svi_value * svi_weight + aal_value * aal_weight
                elif iri_operator == "Multiplication (weighted)":
                    iri_value = svi_value * svi_weight * aal_value * aal_weight
                elif iri_operator == "Average (equal weights)":
                    # For "Average (equal weights)" it's equivalent to use
                    # equal weights, or to sum the indices (all weights 1)
                    # and divide by the number of indices (we use
                    # the latter solution)
                    iri_value = (svi_value + aal_value) / 2.0
                # store IRI
                current_layer.changeAttributeValue(feat_id, iri_attr_id, iri_value)
        project_definition["iri_operator"] = iri_operator
        # set the field name for the copied AAL layer
        project_definition["aal_field"] = aal_field_name
        project_definition["iri_field"] = attr_names[iri_attr_name]
        msg = (
            "The IRI has been calculated for fields containing "
            "non-NULL values and it was added to the layer as "
            "a new attribute called %s"
        ) % attr_names[iri_attr_name]
        iface.messageBar().pushMessage(tr("Info"), tr(msg), level=QgsMessageBar.INFO)
        widget = toggle_select_features_widget(
            tr("Warning"),
            tr("Invalid values were found in some features while calculating " "IRI"),
            tr("Select invalid features"),
            current_layer,
            discarded_aal_feats_ids,
            current_layer.selectedFeaturesIds(),
        )
        iface.messageBar().pushWidget(widget, QgsMessageBar.WARNING)
        return iri_attr_id

    except TypeError as e:
        current_layer.dataProvider().deleteAttributes([iri_attr_id])
        msg = "Could not calculate IRI due to data problems: %s" % e

        iface.messageBar().pushMessage(tr("Error"), tr(msg), level=QgsMessageBar.CRITICAL)
Example #55
0
    def processAlgorithm(self, parameters, context, feedback):
        line_source = self.parameterAsSource(parameters, self.LINES, context)
        poly_source = self.parameterAsSource(parameters, self.POLYGONS, context)

        length_field_name = self.parameterAsString(parameters, self.LEN_FIELD, context)
        count_field_name = self.parameterAsString(parameters, self.COUNT_FIELD, context)

        fields = poly_source.fields()
        if fields.lookupField(length_field_name) < 0:
            fields.append(QgsField(length_field_name, QVariant.Double))
        length_field_index = fields.lookupField(length_field_name)
        if fields.lookupField(count_field_name) < 0:
            fields.append(QgsField(count_field_name, QVariant.Int))
        count_field_index = fields.lookupField(count_field_name)

        (sink, dest_id) = self.parameterAsSink(parameters, self.OUTPUT, context,
                                               fields, poly_source.wkbType(), poly_source.sourceCrs())

        spatialIndex = QgsSpatialIndex(line_source.getFeatures(
            QgsFeatureRequest().setSubsetOfAttributes([]).setDestinationCrs(poly_source.sourceCrs())), feedback)

        distArea = QgsDistanceArea()
        distArea.setSourceCrs(poly_source.sourceCrs())
        distArea.setEllipsoid(context.project().ellipsoid())

        features = poly_source.getFeatures()
        total = 100.0 / poly_source.featureCount() if poly_source.featureCount() else 0
        for current, poly_feature in enumerate(features):
            if feedback.isCanceled():
                break

            output_feature = QgsFeature()
            count = 0
            length = 0
            if poly_feature.hasGeometry():
                poly_geom = poly_feature.geometry()
                has_intersections = False
                lines = spatialIndex.intersects(poly_geom.boundingBox())
                engine = None
                if len(lines) > 0:
                    has_intersections = True
                    # use prepared geometries for faster intersection tests
                    engine = QgsGeometry.createGeometryEngine(poly_geom.constGet())
                    engine.prepareGeometry()

                if has_intersections:
                    request = QgsFeatureRequest().setFilterFids(lines).setSubsetOfAttributes([]).setDestinationCrs(poly_source.sourceCrs())
                    for line_feature in line_source.getFeatures(request):
                        if feedback.isCanceled():
                            break

                        if engine.intersects(line_feature.geometry().constGet()):
                            outGeom = poly_geom.intersection(line_feature.geometry())
                            length += distArea.measureLength(outGeom)
                            count += 1

                output_feature.setGeometry(poly_geom)

            attrs = poly_feature.attributes()
            if length_field_index == len(attrs):
                attrs.append(length)
            else:
                attrs[length_field_index] = length
            if count_field_index == len(attrs):
                attrs.append(count)
            else:
                attrs[count_field_index] = count
            output_feature.setAttributes(attrs)
            sink.addFeature(output_feature, QgsFeatureSink.FastInsert)

            feedback.setProgress(int(current * total))

        return {self.OUTPUT: dest_id}
Example #56
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))

        method = self.parameterAsEnum(parameters, self.METHOD, context)

        wkb_type = source.wkbType()
        fields = source.fields()

        new_fields = QgsFields()
        if QgsWkbTypes.geometryType(wkb_type) == QgsWkbTypes.PolygonGeometry:
            new_fields.append(QgsField('area', QVariant.Double))
            new_fields.append(QgsField('perimeter', QVariant.Double))
        elif QgsWkbTypes.geometryType(wkb_type) == QgsWkbTypes.LineGeometry:
            new_fields.append(QgsField('length', QVariant.Double))
            if not QgsWkbTypes.isMultiType(source.wkbType()):
                new_fields.append(QgsField('straightdis', QVariant.Double))
                new_fields.append(QgsField('sinuosity', QVariant.Double))
        else:
            new_fields.append(QgsField('xcoord', QVariant.Double))
            new_fields.append(QgsField('ycoord', QVariant.Double))
            if QgsWkbTypes.hasZ(source.wkbType()):
                self.export_z = True
                new_fields.append(QgsField('zcoord', QVariant.Double))
            if QgsWkbTypes.hasM(source.wkbType()):
                self.export_m = True
                new_fields.append(QgsField('mvalue', QVariant.Double))

        fields = QgsProcessingUtils.combineFields(fields, new_fields)
        (sink, dest_id) = self.parameterAsSink(parameters, self.OUTPUT,
                                               context, fields, wkb_type,
                                               source.sourceCrs())
        if sink is None:
            raise QgsProcessingException(
                self.invalidSinkError(parameters, self.OUTPUT))

        coordTransform = None

        # Calculate with:
        # 0 - layer CRS
        # 1 - project CRS
        # 2 - ellipsoidal

        self.distance_area = QgsDistanceArea()
        if method == 2:
            self.distance_area.setSourceCrs(source.sourceCrs(),
                                            context.transformContext())
            self.distance_area.setEllipsoid(context.project().ellipsoid())
        elif method == 1:
            coordTransform = QgsCoordinateTransform(source.sourceCrs(),
                                                    context.project().crs(),
                                                    context.project())

        features = source.getFeatures()
        total = 100.0 / source.featureCount() if source.featureCount() else 0
        for current, f in enumerate(features):
            if feedback.isCanceled():
                break

            outFeat = f
            attrs = f.attributes()
            inGeom = f.geometry()
            if inGeom:
                if coordTransform is not None:
                    inGeom.transform(coordTransform)

                if inGeom.type() == QgsWkbTypes.PointGeometry:
                    attrs.extend(self.point_attributes(inGeom))
                elif inGeom.type() == QgsWkbTypes.PolygonGeometry:
                    attrs.extend(self.polygon_attributes(inGeom))
                else:
                    attrs.extend(self.line_attributes(inGeom))

            # ensure consistent count of attributes - otherwise null
            # geometry features will have incorrect attribute length
            # and provider may reject them
            if len(attrs) < len(fields):
                attrs += [NULL] * (len(fields) - len(attrs))

            outFeat.setAttributes(attrs)
            sink.addFeature(outFeat, QgsFeatureSink.FastInsert)

            feedback.setProgress(int(current * total))

        return {self.OUTPUT: dest_id}
Example #57
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))

        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)
        code = self.parameterAsString(parameters, self.FORMULA, context)
        globalExpression = self.parameterAsString(parameters, self.GLOBAL, context)

        fields = source.fields()
        field = QgsField(field_name, field_type, '', width, precision)
        fields.append(field)
        new_ns = {}

        (sink, dest_id) = self.parameterAsSink(parameters, self.OUTPUT, context,
                                               fields, source.wkbType(), source.sourceCrs())
        if sink is None:
            raise QgsProcessingException(self.invalidSinkError(parameters, self.OUTPUT))

        # Run global code
        if globalExpression.strip() != '':
            try:
                bytecode = compile(globalExpression, '<string>', 'exec')
                exec(bytecode, new_ns)
            except:
                raise QgsProcessingException(
                    self.tr("FieldPyculator code execute error.Global code block can't be executed!\n{0}\n{1}").format(
                        str(sys.exc_info()[0].__name__), str(sys.exc_info()[1])))

        # Replace all fields tags
        fields = source.fields()
        num = 0
        for field in fields:
            field_name = str(field.name())
            replval = '__attr[' + str(num) + ']'
            code = code.replace('<' + field_name + '>', replval)
            num += 1

        # Replace all special vars
        code = code.replace('$id', '__id')
        code = code.replace('$geom', '__geom')
        need_id = code.find('__id') != -1
        need_geom = code.find('__geom') != -1
        need_attrs = code.find('__attr') != -1

        # Compile
        try:
            bytecode = compile(code, '<string>', 'exec')
        except:
            raise QgsProcessingException(
                self.tr("FieldPyculator code execute error. Field code block can't be executed!\n{0}\n{1}").format(
                    str(sys.exc_info()[0].__name__), str(sys.exc_info()[1])))

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

        for current, feat in enumerate(features):
            if feedback.isCanceled():
                break

            feedback.setProgress(int(current * total))
            attrs = feat.attributes()
            feat_id = feat.id()

            # Add needed vars
            if need_id:
                new_ns['__id'] = feat_id

            if need_geom:
                geom = feat.geometry()
                new_ns['__geom'] = geom

            if need_attrs:
                pyattrs = [a for a in attrs]
                new_ns['__attr'] = pyattrs

            # Clear old result
            if self.RESULT_VAR_NAME in new_ns:
                del new_ns[self.RESULT_VAR_NAME]

            # Exec
            exec(bytecode, new_ns)

            # Check result
            if self.RESULT_VAR_NAME not in new_ns:
                raise QgsProcessingException(
                    self.tr("FieldPyculator code execute error\n"
                            "Field code block does not return '{0}' variable! "
                            "Please declare this variable in your code!").format(self.RESULT_VAR_NAME))

            # Write feature
            attrs.append(new_ns[self.RESULT_VAR_NAME])
            feat.setAttributes(attrs)
            sink.addFeature(feat, QgsFeatureSink.FastInsert)

        return {self.OUTPUT: dest_id}
    def testWidget(self):
        """Test widget operations"""

        widget = QgsFieldMappingWidget()
        for i in range(10):
            widget.appendField(QgsField(str(i)))
        self.assertTrue(widget.model().rowCount(QModelIndex()), 10)

        def _compare(widget, expected):
            actual = []
            for field in widget.mapping():
                actual.append(int(field.originalName))
            self.assertEqual(actual, expected)

        _compare(widget, [0, 1, 2, 3, 4, 5, 6, 7, 8, 9])

        selection_model = widget.selectionModel()
        selection_model.clear()
        for i in range(0, 10, 2):
            selection_model.select(widget.model().index(i, 0),
                                   QItemSelectionModel.Select)

        self.assertTrue(widget.moveSelectedFieldsDown())
        _compare(widget, [1, 0, 3, 2, 5, 4, 7, 6, 9, 8])

        selection_model.clear()
        for i in range(1, 10, 2):
            selection_model.select(widget.model().index(i, 0),
                                   QItemSelectionModel.Select)

        self.assertTrue(widget.moveSelectedFieldsUp())
        _compare(widget, [0, 1, 2, 3, 4, 5, 6, 7, 8, 9])

        selection_model.clear()
        for i in range(0, 10, 2):
            selection_model.select(widget.model().index(i, 0),
                                   QItemSelectionModel.Select)

        self.assertTrue(widget.removeSelectedFields())
        _compare(widget, [1, 3, 5, 7, 9])

        # Test set destination fields
        widget.setSourceFields(self.source_fields)
        widget.setDestinationFields(self.destination_fields)
        mapping = widget.mapping()
        self.assertEqual(mapping[0].field.name(), 'destination_field1')
        self.assertEqual(mapping[1].field.name(), 'destination_field2')
        self.assertEqual(mapping[2].field.name(), 'destination_field3')
        self.assertEqual(mapping[0].originalName, 'destination_field1')
        self.assertEqual(mapping[1].originalName, 'destination_field2')
        self.assertEqual(mapping[2].originalName, 'destination_field3')

        # Test constraints
        f = QgsField('constraint_field', QVariant.Int)
        constraints = QgsFieldConstraints()
        constraints.setConstraint(QgsFieldConstraints.ConstraintNotNull,
                                  QgsFieldConstraints.ConstraintOriginProvider)
        constraints.setConstraint(QgsFieldConstraints.ConstraintExpression,
                                  QgsFieldConstraints.ConstraintOriginProvider)
        constraints.setConstraint(QgsFieldConstraints.ConstraintUnique,
                                  QgsFieldConstraints.ConstraintOriginProvider)
        f.setConstraints(constraints)
        fields = QgsFields()
        fields.append(f)
        widget.setDestinationFields(fields)
        self.assertEqual(
            widget.model().data(widget.model().index(0, 5, QModelIndex()),
                                Qt.DisplayRole), "Constraints active")
        self.assertEqual(
            widget.model().data(widget.model().index(0, 5, QModelIndex()),
                                Qt.ToolTipRole),
            "Unique<br>Not null<br>Expression")
        self.assertEqual(
            widget.model().data(widget.model().index(0, 5, QModelIndex()),
                                Qt.BackgroundColorRole), QColor(255, 224, 178))
Example #59
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))

        group_field_name = self.parameterAsString(parameters, self.GROUP_FIELD, context)
        order_field_name = self.parameterAsString(parameters, self.ORDER_FIELD, context)
        date_format = self.parameterAsString(parameters, self.DATE_FORMAT, context)
        text_dir = self.parameterAsString(parameters, self.OUTPUT_TEXT_DIR, context)

        group_field_index = source.fields().lookupField(group_field_name)
        order_field_index = source.fields().lookupField(order_field_name)

        if group_field_index >= 0:
            group_field_def = source.fields().at(group_field_index)
        else:
            group_field_def = None
        order_field_def = source.fields().at(order_field_index)

        fields = QgsFields()
        if group_field_def is not None:
            fields.append(group_field_def)
        begin_field = QgsField(order_field_def)
        begin_field.setName('begin')
        fields.append(begin_field)
        end_field = QgsField(order_field_def)
        end_field.setName('end')
        fields.append(end_field)

        output_wkb = QgsWkbTypes.LineString
        if QgsWkbTypes.hasM(source.wkbType()):
            output_wkb = QgsWkbTypes.addM(output_wkb)
        if QgsWkbTypes.hasZ(source.wkbType()):
            output_wkb = QgsWkbTypes.addZ(output_wkb)

        (sink, dest_id) = self.parameterAsSink(parameters, self.OUTPUT, context,
                                               fields, output_wkb, source.sourceCrs())
        if sink is None:
            raise QgsProcessingException(self.invalidSinkError(parameters, self.OUTPUT))

        points = dict()
        features = source.getFeatures(QgsFeatureRequest().setSubsetOfAttributes([group_field_index, order_field_index]), QgsProcessingFeatureSource.FlagSkipGeometryValidityChecks)
        total = 100.0 / source.featureCount() if source.featureCount() else 0
        for current, f in enumerate(features):
            if feedback.isCanceled():
                break

            if not f.hasGeometry():
                continue

            point = f.geometry().constGet().clone()
            if group_field_index >= 0:
                group = f.attributes()[group_field_index]
            else:
                group = 1
            order = f.attributes()[order_field_index]
            if date_format != '':
                order = datetime.strptime(str(order), date_format)
            if group in points:
                points[group].append((order, point))
            else:
                points[group] = [(order, point)]

            feedback.setProgress(int(current * total))

        feedback.setProgress(0)

        da = QgsDistanceArea()
        da.setSourceCrs(source.sourceCrs(), context.transformContext())
        da.setEllipsoid(context.project().ellipsoid())

        current = 0
        total = 100.0 / len(points) if points else 1
        for group, vertices in list(points.items()):
            if feedback.isCanceled():
                break

            vertices.sort(key=lambda x: (x[0] is None, x[0]))
            f = QgsFeature()
            attributes = []
            if group_field_index >= 0:
                attributes.append(group)
            attributes.extend([vertices[0][0], vertices[-1][0]])
            f.setAttributes(attributes)
            line = [node[1] for node in vertices]

            if text_dir:
                fileName = os.path.join(text_dir, '%s.txt' % group)

                with open(fileName, 'w') as fl:
                    fl.write('angle=Azimuth\n')
                    fl.write('heading=Coordinate_System\n')
                    fl.write('dist_units=Default\n')

                    for i in range(len(line)):
                        if i == 0:
                            fl.write('startAt=%f;%f;90\n' % (line[i].x(), line[i].y()))
                            fl.write('survey=Polygonal\n')
                            fl.write('[data]\n')
                        else:
                            angle = line[i - 1].azimuth(line[i])
                            distance = da.measureLine(QgsPointXY(line[i - 1]), QgsPointXY(line[i]))
                            fl.write('%f;%f;90\n' % (angle, distance))

            f.setGeometry(QgsGeometry(QgsLineString(line)))
            sink.addFeature(f, QgsFeatureSink.FastInsert)
            current += 1
            feedback.setProgress(int(current * total))

        return {self.OUTPUT: dest_id}
Example #60
0
    def processAlgorithm(self, parameters, context, feedback):
        network = self.parameterAsSource(parameters, self.INPUT, context)
        startPoint = self.parameterAsPoint(parameters, self.START_POINT,
                                           context, network.sourceCrs())
        strategy = self.parameterAsEnum(parameters, self.STRATEGY, context)
        travelCost = self.parameterAsDouble(parameters, self.TRAVEL_COST,
                                            context)

        directionFieldName = self.parameterAsString(parameters,
                                                    self.DIRECTION_FIELD,
                                                    context)
        forwardValue = self.parameterAsString(parameters, self.VALUE_FORWARD,
                                              context)
        backwardValue = self.parameterAsString(parameters, self.VALUE_BACKWARD,
                                               context)
        bothValue = self.parameterAsString(parameters, self.VALUE_BOTH,
                                           context)
        defaultDirection = self.parameterAsEnum(parameters,
                                                self.DEFAULT_DIRECTION,
                                                context)
        speedFieldName = self.parameterAsString(parameters, self.SPEED_FIELD,
                                                context)
        defaultSpeed = self.parameterAsDouble(parameters, self.DEFAULT_SPEED,
                                              context)
        tolerance = self.parameterAsDouble(parameters, self.TOLERANCE, context)

        directionField = -1
        if directionFieldName:
            directionField = network.fields().lookupField(directionFieldName)
        speedField = -1
        if speedFieldName:
            speedField = network.fields().lookupField(speedFieldName)

        director = QgsVectorLayerDirector(network, directionField,
                                          forwardValue, backwardValue,
                                          bothValue, defaultDirection)

        distUnit = context.project().crs().mapUnits()
        multiplier = QgsUnitTypes.fromUnitToUnitFactor(
            distUnit, QgsUnitTypes.DistanceMeters)
        if strategy == 0:
            strategy = QgsNetworkDistanceStrategy()
        else:
            strategy = QgsNetworkSpeedStrategy(speedField, defaultSpeed,
                                               multiplier * 1000.0 / 3600.0)

        director.addStrategy(strategy)
        builder = QgsGraphBuilder(network.sourceCrs(), True, tolerance)
        feedback.pushInfo(
            QCoreApplication.translate('ServiceAreaFromPoint',
                                       'Building graph…'))
        snappedPoints = director.makeGraph(builder, [startPoint], feedback)

        feedback.pushInfo(
            QCoreApplication.translate('ServiceAreaFromPoint',
                                       'Calculating service area…'))
        graph = builder.graph()
        idxStart = graph.findVertex(snappedPoints[0])

        tree, cost = QgsGraphAnalyzer.dijkstra(graph, idxStart, 0)
        vertices = []
        for i, v in enumerate(cost):
            if v > travelCost and tree[i] != -1:
                vertexId = graph.edge(tree[i]).fromVertex()
                if cost[vertexId] <= travelCost:
                    vertices.append(i)

        upperBoundary = []
        lowerBoundary = []
        for i in vertices:
            upperBoundary.append(
                graph.vertex(graph.edge(tree[i]).toVertex()).point())
            lowerBoundary.append(
                graph.vertex(graph.edge(tree[i]).fromVertex()).point())

        feedback.pushInfo(
            QCoreApplication.translate('ServiceAreaFromPoint',
                                       'Writing results…'))

        fields = QgsFields()
        fields.append(QgsField('type', QVariant.String, '', 254, 0))
        fields.append(QgsField('start', QVariant.String, '', 254, 0))

        feat = QgsFeature()
        feat.setFields(fields)

        geomUpper = QgsGeometry.fromMultiPointXY(upperBoundary)
        geomLower = QgsGeometry.fromMultiPointXY(lowerBoundary)

        (sink, dest_id) = self.parameterAsSink(parameters, self.OUTPUT,
                                               context, fields,
                                               QgsWkbTypes.MultiPoint,
                                               network.sourceCrs())

        feat.setGeometry(geomUpper)
        feat['type'] = 'upper'
        feat['start'] = startPoint.toString()
        sink.addFeature(feat, QgsFeatureSink.FastInsert)

        feat.setGeometry(geomLower)
        feat['type'] = 'lower'
        feat['start'] = startPoint.toString()
        sink.addFeature(feat, QgsFeatureSink.FastInsert)

        upperBoundary.append(startPoint)
        lowerBoundary.append(startPoint)
        geomUpper = QgsGeometry.fromMultiPointXY(upperBoundary)
        geomLower = QgsGeometry.fromMultiPointXY(lowerBoundary)

        return {self.OUTPUT: dest_id}