Ejemplo n.º 1
0
    def create_layer(self, parameters, name, is_memory, dest_crs, layer_style=None):
        save_as = parameters.file_path
        file_format = parameters.file_format
        # save paramaters
        serialized = base64.b64encode(parameters.serialize(with_style=False, with_geometry=False))

        # save geometry
        layer = QgsVectorLayer("MultiPolygon?crs=%s" % dest_crs.authid(), name, "memory")
        pr = layer.dataProvider()
        layer.startEditing()
        layer.addAttribute(QgsField("params", QVariant.String))
        fet1 = QgsFeature(0)
        fet1.setFields(layer.fields())
        fet1.setAttribute("params", str(serialized)[2:-1])
        fet1.setGeometry(parameters.geometry)
        pr.addFeatures([fet1])
        layer.commitChanges()

        # copy layer style
        if layer_style is not None:
            self.set_layer_style(layer, layer_style)

        if is_memory:
            return layer

        if os.path.isfile(save_as):
            # delete first if already exists
            if save_as.endswith(".shp"):
                QgsVectorFileWriter.deleteShapeFile(save_as)
            else:
                os.unlink(save_as)

        # create the disk layer
        QgsMessageLog.logMessage("Mask saving '{}' as {}".format(save_as, file_format),
                                 'Extensions')
        error = QgsVectorFileWriter.writeAsVectorFormat(layer, save_as, "System", dest_crs,
                                                        file_format)

        if error == 0:
            nlayer = QgsVectorLayer(save_as, name, "ogr")
            if not nlayer.dataProvider().isValid():
                return None
            if not nlayer.hasGeometryType():
                return None
            # force CRS
            nlayer.setCrs(dest_crs)

            # copy layer style
            layer_style = self.get_layer_style(layer)
            self.set_layer_style(nlayer, layer_style)
            return nlayer
        else:
            raise RuntimeError(error)

        return None
Ejemplo n.º 2
0
    def testFieldsWithSpecialCharacters(self):
        ml = QgsVectorLayer("Point?srid=EPSG:4326&field=123:int", "mem_with_nontext_fieldnames", "memory")
        self.assertEqual(ml.isValid(), True)
        QgsProject.instance().addMapLayer(ml)

        ml.startEditing()
        self.assertTrue(ml.addAttribute(QgsField('abc:123', QVariant.String)))
        self.assertTrue(ml.addAttribute(QgsField('map', QVariant.String)))  # matches QGIS expression function name
        f1 = QgsFeature(ml.fields())
        f1.setGeometry(QgsGeometry.fromWkt('POINT(0 0)'))
        f1.setAttributes([1, 'a', 'b'])
        f2 = QgsFeature(ml.fields())
        f2.setGeometry(QgsGeometry.fromWkt('POINT(1 1)'))
        f2.setAttributes([2, 'c', 'd'])
        ml.addFeatures([f1, f2])
        ml.commitChanges()

        vl = QgsVectorLayer("?query=select * from mem_with_nontext_fieldnames", "vl", "virtual")
        self.assertEqual(vl.isValid(), True)
        self.assertEqual(vl.fields().at(0).name(), '123')
        self.assertEqual(vl.fields().at(1).name(), 'abc:123')

        self.assertEqual(vl.featureCount(), 2)

        features = [f for f in vl.getFeatures(QgsFeatureRequest().setFilterExpression('"abc:123"=\'c\''))]
        self.assertEqual(len(features), 1)
        self.assertEqual(features[0].attributes(), [2, 'c', 'd'])

        features = [f for f in vl.getFeatures(QgsFeatureRequest().setFilterExpression('"map"=\'b\''))]
        self.assertEqual(len(features), 1)
        self.assertEqual(features[0].attributes(), [1, 'a', 'b'])

        vl2 = QgsVectorLayer("?query=select * from mem_with_nontext_fieldnames where \"abc:123\"='c'", "vl", "virtual")
        self.assertEqual(vl2.isValid(), True)
        self.assertEqual(vl2.fields().at(0).name(), '123')
        self.assertEqual(vl2.fields().at(1).name(), 'abc:123')

        self.assertEqual(vl2.featureCount(), 1)

        features = [f for f in vl2.getFeatures()]
        self.assertEqual(len(features), 1)
        self.assertEqual(features[0].attributes(), [2, 'c', 'd'])

        vl3 = QgsVectorLayer("?query=select * from mem_with_nontext_fieldnames where \"map\"='b'", "vl", "virtual")
        self.assertEqual(vl3.isValid(), True)
        self.assertEqual(vl3.fields().at(0).name(), '123')
        self.assertEqual(vl3.fields().at(1).name(), 'abc:123')

        self.assertEqual(vl3.featureCount(), 1)

        features = [f for f in vl3.getFeatures()]
        self.assertEqual(len(features), 1)
        self.assertEqual(features[0].attributes(), [1, 'a', 'b'])

        QgsProject.instance().removeMapLayer(ml)
Ejemplo n.º 3
0
    def add_flooded_field(self, shapefile_path):
        """Create the layer from the local shp adding the flooded field.

        .. versionadded:: 3.3

        Use this method to add a calculated field to a shapefile. The shapefile
        should have a field called 'count' containing the number of flood
        reports for the field. The field values will be set to 0 if the count
        field is < 1, otherwise it will be set to 1.

        :param shapefile_path: Path to the shapefile that will have the flooded
            field added.
        :type shapefile_path: basestring

        :return: A vector layer with the flooded field added.
        :rtype: QgsVectorLayer
        """
        layer = QgsVectorLayer(
            shapefile_path, self.tr('Jakarta Floods'), 'ogr')
        # Add a calculated field indicating if a poly is flooded or not
        # from qgis.PyQt.QtCore import QVariant
        layer.startEditing()
        # Add field with integer from 0 to 4 which represents the flood
        # class. Its the same as 'state' field except that is being treated
        # as a string.
        # This is used for cartography
        flood_class_field = QgsField('floodclass', QVariant.Int)
        layer.addAttribute(flood_class_field)
        layer.commitChanges()
        layer.startEditing()
        flood_class_idx = layer.fields().lookupField('floodclass')
        flood_class_expression = QgsExpression('to_int(state)')
        context = QgsExpressionContext()
        context.setFields(layer.fields())
        flood_class_expression.prepare(context)

        # Add field with boolean flag to say if the area is flooded
        # This is used by the impact function
        flooded_field = QgsField('flooded', QVariant.Int)
        layer.dataProvider().addAttributes([flooded_field])
        layer.commitChanges()
        layer.startEditing()
        flooded_idx = layer.fields().lookupField('flooded')
        flood_flag_expression = QgsExpression('state > 0')
        flood_flag_expression.prepare(context)
        for feature in layer.getFeatures():
            context.setFeature(feature)
            feature[flood_class_idx] = flood_class_expression.evaluate(context)
            feature[flooded_idx] = flood_flag_expression.evaluate(context)
            layer.updateFeature(feature)
        layer.commitChanges()
        return layer
Ejemplo n.º 4
0
    def testSaveFields(self):
        # Create a new memory layer with no fields
        myMemoryLayer = QgsVectorLayer(("Point?crs=epsg:4326&index=yes"), "test", "memory")

        # Add some fields to the layer
        myFields = [
            QgsField("TestInt", QVariant.Int, "integer", 2, 0),
            QgsField("TestLong", QVariant.LongLong, "long", -1, 0),
            QgsField("TestDbl", QVariant.Double, "double", 8, 6),
            QgsField("TestString", QVariant.String, "string", 50, 0),
            QgsField("TestDate", QVariant.Date, "date"),
            QgsField("TestTime", QVariant.Time, "time"),
            QgsField("TestDateTime", QVariant.DateTime, "datetime"),
        ]
        assert myMemoryLayer.startEditing()
        for f in myFields:
            assert myMemoryLayer.addAttribute(f)
        assert myMemoryLayer.commitChanges()
        myMemoryLayer.updateFields()

        # Export the layer to a layer-definition-XML
        qlr = QgsMapLayer.asLayerDefinition([myMemoryLayer])
        assert qlr is not None

        # Import the layer from the layer-definition-XML
        layers = QgsMapLayer.fromLayerDefinition(qlr)
        assert layers is not None
        myImportedLayer = layers[0]
        assert myImportedLayer is not None

        # Check for the presence of the fields
        importedFields = myImportedLayer.fields()
        assert importedFields is not None
        for f in myFields:
            assert f == importedFields.field(f.name())
Ejemplo n.º 5
0
    def testSaveFields(self):
        # Create a new memory layer with no fields
        myMemoryLayer = QgsVectorLayer(('Point?crs=epsg:4326&index=yes'),
                                       'test', 'memory')

        # Add some fields to the layer
        myFields = [
            QgsField('TestInt', QVariant.Int, 'integer', 2, 0),
            QgsField('TestDbl', QVariant.Double, 'double', 8, 6),
            QgsField('TestString', QVariant.String, 'string', 50, 0)
        ]
        assert myMemoryLayer.startEditing()
        for f in myFields:
            assert myMemoryLayer.addAttribute(f)
        assert myMemoryLayer.commitChanges()
        myMemoryLayer.updateFields()

        # Export the layer to a layer-definition-XML
        qlr = QgsMapLayer.asLayerDefinition([myMemoryLayer])
        assert qlr is not None

        # Import the layer from the layer-definition-XML
        layers = QgsMapLayer.fromLayerDefinition(qlr)
        assert layers is not None
        myImportedLayer = layers[0]
        assert myImportedLayer is not None

        # Check for the presence of the fields
        importedFields = myImportedLayer.fields()
        assert importedFields is not None
        for f in myFields:
            assert f == importedFields.field(f.name())
Ejemplo n.º 6
0
    def testEditGeoJsonAddField(self):
        """ Test bugfix of https://issues.qgis.org/issues/18596 (adding a new field)"""

        datasource = os.path.join(self.basetestpath, 'testEditGeoJsonAddField.json')
        with open(datasource, 'wt') as f:
            f.write("""{
"type": "FeatureCollection",
"features": [
{ "type": "Feature", "properties": { "x": 1 }, "geometry": { "type": "Point", "coordinates": [ 0, 0 ] } } ] }""")

        vl = QgsVectorLayer(datasource, 'test', 'ogr')
        self.assertTrue(vl.isValid())
        self.assertTrue(vl.startEditing())
        self.assertTrue(vl.addAttribute(QgsField('strfield', QVariant.String)))
        self.assertTrue(vl.commitChanges())
        self.assertEqual(len(vl.dataProvider().fields()), 1 + 1)

        f = QgsFeature()
        self.assertTrue(vl.getFeatures(QgsFeatureRequest()).nextFeature(f))
        self.assertIsNone(f['strfield'])

        # Completely reload file
        vl = QgsVectorLayer(datasource, 'test', 'ogr')
        # As we didn't set any value to the new field, it is not written at
        # all in the GeoJSON file, so it has disappeared
        self.assertEqual(len(vl.fields()), 1)
Ejemplo n.º 7
0
    def testSaveFields(self):
        # Create a new memory layer with no fields
        myMemoryLayer = QgsVectorLayer(
            ('Point?crs=epsg:4326&index=yes'),
            'test',
            'memory')

        # Add some fields to the layer
        myFields = [QgsField('TestInt', QVariant.Int, 'integer', 2, 0),
                    QgsField('TestDbl', QVariant.Double, 'double', 8, 6),
                    QgsField('TestString', QVariant.String, 'string', 50, 0),
                    QgsField('TestDate', QVariant.Date, 'date'),
                    QgsField('TestTime', QVariant.Time, 'time'),
                    QgsField('TestDateTime', QVariant.DateTime, 'datetime')]
        assert myMemoryLayer.startEditing()
        for f in myFields:
            assert myMemoryLayer.addAttribute(f)
        assert myMemoryLayer.commitChanges()
        myMemoryLayer.updateFields()

        # Export the layer to a layer-definition-XML
        qlr = QgsMapLayer.asLayerDefinition([myMemoryLayer])
        assert qlr is not None

        # Import the layer from the layer-definition-XML
        layers = QgsMapLayer.fromLayerDefinition(qlr)
        assert layers is not None
        myImportedLayer = layers[0]
        assert myImportedLayer is not None

        # Check for the presence of the fields
        importedFields = myImportedLayer.fields()
        assert importedFields is not None
        for f in myFields:
            assert f == importedFields.field(f.name())
Ejemplo n.º 8
0
    def testEditGeoJsonAddFieldAndThenAddFeatures(self):
        """ Test bugfix of https://issues.qgis.org/issues/18596 (adding a new field)"""

        datasource = os.path.join(self.basetestpath, 'testEditGeoJsonAddField.json')
        with open(datasource, 'wt') as f:
            f.write("""{
"type": "FeatureCollection",
"features": [
{ "type": "Feature", "properties": { "x": 1 }, "geometry": { "type": "Point", "coordinates": [ 0, 0 ] } } ] }""")

        vl = QgsVectorLayer(datasource, 'test', 'ogr')
        self.assertTrue(vl.isValid())
        self.assertTrue(vl.startEditing())
        self.assertTrue(vl.addAttribute(QgsField('strfield', QVariant.String)))
        self.assertTrue(vl.commitChanges())
        self.assertEqual(len(vl.dataProvider().fields()), 1 + 1)
        self.assertEqual([f.name() for f in vl.dataProvider().fields()], ['x', 'strfield'])

        f = QgsFeature()
        self.assertTrue(vl.getFeatures(QgsFeatureRequest()).nextFeature(f))
        self.assertIsNone(f['strfield'])
        self.assertEqual([field.name() for field in f.fields()], ['x', 'strfield'])

        self.assertTrue(vl.startEditing())
        vl.changeAttributeValue(f.id(), 1, 'x')
        self.assertTrue(vl.commitChanges())
        f = QgsFeature()
        self.assertTrue(vl.getFeatures(QgsFeatureRequest()).nextFeature(f))
        self.assertEqual(f['strfield'], 'x')
        self.assertEqual([field.name() for field in f.fields()], ['x', 'strfield'])

        # Completely reload file
        vl = QgsVectorLayer(datasource, 'test', 'ogr')
        self.assertEqual(len(vl.fields()), 2)
Ejemplo n.º 9
0
    def testEditGeoJsonAddField(self):
        """ Test bugfix of https://github.com/qgis/QGIS/issues/26484 (adding a new field)"""

        datasource = os.path.join(self.basetestpath, 'testEditGeoJsonAddField.json')
        with open(datasource, 'wt') as f:
            f.write("""{
"type": "FeatureCollection",
"features": [
{ "type": "Feature", "properties": { "x": 1 }, "geometry": { "type": "Point", "coordinates": [ 0, 0 ] } } ] }""")

        vl = QgsVectorLayer(datasource, 'test', 'ogr')
        self.assertTrue(vl.isValid())
        self.assertTrue(vl.startEditing())
        self.assertTrue(vl.addAttribute(QgsField('strfield', QVariant.String)))
        self.assertTrue(vl.commitChanges())
        self.assertEqual(len(vl.dataProvider().fields()), 1 + 1)

        f = QgsFeature()
        self.assertTrue(vl.getFeatures(QgsFeatureRequest()).nextFeature(f))
        self.assertIsNone(f['strfield'])

        # Completely reload file
        vl = QgsVectorLayer(datasource, 'test', 'ogr')
        # As we didn't set any value to the new field, it is not written at
        # all in the GeoJSON file, so it has disappeared
        self.assertEqual(len(vl.fields()), 1)
Ejemplo n.º 10
0
    def testEditGeoJsonAddFieldAndThenAddFeatures(self):
        """ Test bugfix of https://issues.qgis.org/issues/18596 (adding a new field)"""

        datasource = os.path.join(self.basetestpath, 'testEditGeoJsonAddField.json')
        with open(datasource, 'wt') as f:
            f.write("""{
"type": "FeatureCollection",
"features": [
{ "type": "Feature", "properties": { "x": 1 }, "geometry": { "type": "Point", "coordinates": [ 0, 0 ] } } ] }""")

        vl = QgsVectorLayer(datasource, 'test', 'ogr')
        self.assertTrue(vl.isValid())
        self.assertTrue(vl.startEditing())
        self.assertTrue(vl.addAttribute(QgsField('strfield', QVariant.String)))
        self.assertTrue(vl.commitChanges())
        self.assertEqual(len(vl.dataProvider().fields()), 1 + 1)
        self.assertEqual([f.name() for f in vl.dataProvider().fields()], ['x', 'strfield'])

        f = QgsFeature()
        self.assertTrue(vl.getFeatures(QgsFeatureRequest()).nextFeature(f))
        self.assertIsNone(f['strfield'])
        self.assertEqual([field.name() for field in f.fields()], ['x', 'strfield'])

        self.assertTrue(vl.startEditing())
        vl.changeAttributeValue(f.id(), 1, 'x')
        self.assertTrue(vl.commitChanges())
        f = QgsFeature()
        self.assertTrue(vl.getFeatures(QgsFeatureRequest()).nextFeature(f))
        self.assertEqual(f['strfield'], 'x')
        self.assertEqual([field.name() for field in f.fields()], ['x', 'strfield'])

        # Completely reload file
        vl = QgsVectorLayer(datasource, 'test', 'ogr')
        self.assertEqual(len(vl.fields()), 2)
Ejemplo n.º 11
0
    def centroid(self):
        layer = self.layerComboBox.currentData()
        uri = 'Point?crs={authid}&index=yes'.format(authid=layer.crs().authid())
        new_layer = QgsVectorLayer(uri, 'centroid', 'memory')
        QgsProject.instance().addMapLayer(new_layer)
        # segunda parte
        new_layer.startEditing()

        for field in layer.fields():
            new_layer.addAttribute(field)

        for feature in layer.getFeatures():
            geom = feature.geometry().centroid()

            feature.setGeometry(geom)
            new_layer.addFeature(feature)

        new_layer.commitChanges()
Ejemplo n.º 12
0
    def testAddingTwoIntFieldsWithWidth(self):
        """ Test buggfix for https://issues.qgis.org/issues/19009 """

        tmpfile = os.path.join(self.basetestpath, 'testRequestWithoutGeometryOnLayerMixedGeometry.gpkg')
        ds = ogr.GetDriverByName('GPKG').CreateDataSource(tmpfile)
        lyr = ds.CreateLayer('test', geom_type=ogr.wkbPoint, options=['SPATIAL_INDEX=NO'])
        lyr.CreateField(ogr.FieldDefn('a', ogr.OFTInteger))
        ds = None

        vl = QgsVectorLayer(u'{}'.format(tmpfile) + "|layername=" + "test", 'test', u'ogr')
        self.assertTrue(vl.isValid())

        vl.startEditing()
        self.assertTrue(vl.addAttribute(QgsField("b", QVariant.Int, "integer", 10)))
        self.assertTrue(vl.commitChanges())

        vl.startEditing()
        self.assertTrue(vl.addAttribute(QgsField("c", QVariant.Int, "integer", 10)))
        self.assertTrue(vl.commitChanges())
Ejemplo n.º 13
0
    def testAddingTwoIntFieldsWithWidth(self):
        """ Test buggfix for https://issues.qgis.org/issues/19009 """

        tmpfile = os.path.join(self.basetestpath, 'testRequestWithoutGeometryOnLayerMixedGeometry.gpkg')
        ds = ogr.GetDriverByName('GPKG').CreateDataSource(tmpfile)
        lyr = ds.CreateLayer('test', geom_type=ogr.wkbPoint, options=['SPATIAL_INDEX=NO'])
        lyr.CreateField(ogr.FieldDefn('a', ogr.OFTInteger))
        ds = None

        vl = QgsVectorLayer(u'{}'.format(tmpfile) + "|layername=" + "test", 'test', u'ogr')
        self.assertTrue(vl.isValid())

        vl.startEditing()
        self.assertTrue(vl.addAttribute(QgsField("b", QVariant.Int, "integer", 10)))
        self.assertTrue(vl.commitChanges())

        vl.startEditing()
        self.assertTrue(vl.addAttribute(QgsField("c", QVariant.Int, "integer", 10)))
        self.assertTrue(vl.commitChanges())
Ejemplo n.º 14
0
    def buffer(self):
        layer = self.layerComboBox.currentData()
        uri = 'Polygon?crs={authid}&index=yes'.format(authid=layer.crs().authid())
        new_layer = QgsVectorLayer(uri, 'buffer', 'memory')
        QgsProject.instance().addMapLayer(new_layer)
        # segunda parte
        buffer_size = self.spinBox.value()
        new_layer.startEditing()

        for field in layer.fields():
            new_layer.addAttribute(field)

        for feature in layer.getFeatures():
            geom = feature.geometry().buffer(buffer_size, 5)

            feature.setGeometry(geom)
            new_layer.addFeature(feature)

        new_layer.commitChanges()
Ejemplo n.º 15
0
    def testInvalidPrimaryKey(self):
        # create layer
        vl = QgsVectorLayer(
            'Point?crs=epsg:4326&field=pk:integer&key=pk',
            'test', 'memory')
        assert (vl.isValid())

        # add a field with an invalid typename
        field = QgsField(name="invalid_pk", type=QVariant.Int, typeName="xsd:int")
        vl.startEditing()
        vl.addAttribute(field)
        vl.commitChanges()

        # create auxiliary storage based on the invalid field
        s = QgsAuxiliaryStorage()
        pkf = field
        al = s.createAuxiliaryLayer(pkf, vl)

        self.assertEqual(al, None)
        self.assertTrue("CREATE TABLE IF NOT EXISTS" in s.errorString())
    def run(self):
        """
        Just show/dock Widget/Plugin
        """
        layer = QgsVectorLayer("LineString", "Examplelayer", "memory")
        layer.startEditing()

        layer.addAttribute(QgsField("id", QVariant.Int))
        layer.addAttribute(QgsField("Length", QVariant.Double))

        qfeature = QgsFeature()
        qfeature.setGeometry(
            QgsGeometry.fromPolyline([QgsPoint(0, 0),
                                      QgsPoint(1, 1)]))
        qfeature.setAttributes([1, 1.414])

        layer.addFeature(qfeature)
        layer.commitChanges()

        QgsMapLayerRegistry.instance().addMapLayer(layer)
Ejemplo n.º 17
0
    def testSaveFields(self):
        # Create a new memory layer with no fields
        myMemoryLayer = QgsVectorLayer(
            ('Point?crs=epsg:4326&index=yes'),
            'test',
            'memory')

        # Add some fields to the layer
        myFields = [QgsField('TestInt', QVariant.Int, 'integer', 2, 0),
                    QgsField('TestLong', QVariant.LongLong, 'long', -1, 0),
                    QgsField('TestDbl', QVariant.Double, 'double', 8, 6),
                    QgsField('TestString', QVariant.String, 'string', 50, 0),
                    QgsField('TestDate', QVariant.Date, 'date'),
                    QgsField('TestTime', QVariant.Time, 'time'),
                    QgsField('TestDateTime', QVariant.DateTime, 'datetime'),
                    QgsField("vallist", QVariant.List, subType=QVariant.Int),
                    QgsField("stringlist", QVariant.StringList, subType=QVariant.String),
                    QgsField("stringlist2", QVariant.List, subType=QVariant.String),
                    QgsField("reallist", QVariant.List, subType=QVariant.Double),
                    QgsField("longlist", QVariant.List, subType=QVariant.LongLong)]
        self.assertTrue(myMemoryLayer.startEditing())
        for f in myFields:
            assert myMemoryLayer.addAttribute(f)
        self.assertTrue(myMemoryLayer.commitChanges())
        myMemoryLayer.updateFields()

        for f in myFields:
            self.assertEqual(f, myMemoryLayer.fields().field(f.name()))

        # Export the layer to a layer-definition-XML
        qlr = QgsLayerDefinition.exportLayerDefinitionLayers([myMemoryLayer], QgsReadWriteContext())
        self.assertIsNotNone(qlr)

        # Import the layer from the layer-definition-XML
        layers = QgsLayerDefinition.loadLayerDefinitionLayers(qlr, QgsReadWriteContext())
        self.assertTrue(layers)
        myImportedLayer = layers[0]
        self.assertIsNotNone(myImportedLayer)

        # Check for the presence of the fields
        importedFields = myImportedLayer.fields()
        for f in myFields:
            self.assertEqual(f.name(), importedFields.field(f.name()).name())
            if f.name() != 'stringlist2':
                self.assertEqual(f.type(), importedFields.field(f.name()).type())
            else:
                # we automatically convert List with String subtype to StringList, to match other data providers
                self.assertEqual(importedFields.field(f.name()).type(), QVariant.StringList)

            self.assertEqual(f.subType(), importedFields.field(f.name()).subType())
            self.assertEqual(f.precision(), importedFields.field(f.name()).precision())
            self.assertEqual(f.length(), importedFields.field(f.name()).length())
Ejemplo n.º 18
0
            def f():
                crs = iface.mapCanvas().mapRenderer().destinationCrs()
                uri = "%s?srsname=%s&typename=geonode:%s&version=1.0.0&request=GetFeature&service=WFS" % (url, crs.authid(), name)
                qgslayer = QgsVectorLayer(uri, name, "WFS")
                if not qgslayer.isValid():
                    raise Exception ("Layer at %s is not a valid layer" % uri)

                fieldname = self._getTimeField(qgslayer)

                if fieldname is None:
                    QgsMapLayerRegistry.instance().addMapLayers([qgslayer])
                else:
                    memlayer = QgsVectorLayer("%s?crs=%s" % (GEOM_TYPE_MAP[qgslayer.wkbType()], crs.authid()), name, "memory")
                    memlayer.startEditing()
                    for field in qgslayer.pendingFields():
                        memlayer.addAttribute(field)
                    for feat in qgslayer.getFeatures():
                        memlayer.addFeatures([feat])
                    memlayer.commitChanges()
                    QgsMapLayerRegistry.instance().addMapLayers([memlayer])
                    memlayer.setSelectedFeatures([])
                    addWfsAnimation(memlayer, fieldname)
Ejemplo n.º 19
0
 def createVlayer(self, listFields,campSrc):
     '''Función para crear el vlayer con un campo de id, un campo de nom, los campos pasados por el parámetro lisFields y el parámetro campSrc para crear la geometría'''
     vlayer = QgsVectorLayer("Point?crs="+campSrc, self.dlg.txt_nomTaula.text(), "memory")
     
     vlayer.startEditing()
     vlayer.addAttribute(QgsField('id', QVariant.Int))
     vlayer.addAttribute(QgsField('Nom', QVariant.String))
     for x in range(len(listFields)):
         vlayer.addAttribute(QgsField(listFields[x], QVariant.String))
     vlayer.commitChanges()
     return vlayer
Ejemplo n.º 20
0
    def testSaveFields(self):
        # Create a new py layerwith no fields
        myPyLayer = QgsVectorLayer(('Point?crs=epsg:4326&index=yes'), 'test',
                                   'pythonprovider')

        # Add some fields to the layer
        myFields = [
            QgsField('TestInt', QVariant.Int, 'integer', 2, 0),
            QgsField('TestLong', QVariant.LongLong, 'long', -1, 0),
            QgsField('TestDbl', QVariant.Double, 'double', 8, 6),
            QgsField('TestString', QVariant.String, 'string', 50, 0),
            QgsField('TestDate', QVariant.Date, 'date'),
            QgsField('TestTime', QVariant.Time, 'time'),
            QgsField('TestDateTime', QVariant.DateTime, 'datetime')
        ]
        assert myPyLayer.startEditing()
        for f in myFields:
            assert myPyLayer.addAttribute(f)
        assert myPyLayer.commitChanges()
        myPyLayer.updateFields()

        # Export the layer to a layer-definition-XML
        qlr = QgsLayerDefinition.exportLayerDefinitionLayers(
            [myPyLayer], QgsReadWriteContext())
        assert qlr is not None

        # Import the layer from the layer-definition-XML
        layers = QgsLayerDefinition.loadLayerDefinitionLayers(
            qlr, QgsReadWriteContext())
        assert layers is not None
        myImportedLayer = layers[0]
        assert myImportedLayer is not None

        # Check for the presence of the fields
        importedFields = myImportedLayer.fields()
        assert importedFields is not None
        for f in myFields:
            assert f == importedFields.field(f.name())
Ejemplo n.º 21
0
    def testFieldsWithSpecialCharacters(self):
        ml = QgsVectorLayer("Point?srid=EPSG:4326&field=123:int",
                            "mem_with_nontext_fieldnames", "memory")
        self.assertEqual(ml.isValid(), True)
        QgsProject.instance().addMapLayer(ml)

        ml.startEditing()
        self.assertTrue(ml.addAttribute(QgsField('abc:123', QVariant.String)))
        f1 = QgsFeature(ml.fields())
        f1.setGeometry(QgsGeometry.fromWkt('POINT(0 0)'))
        f2 = QgsFeature(ml.fields())
        f2.setGeometry(QgsGeometry.fromWkt('POINT(1 1)'))
        ml.addFeatures([f1, f2])
        ml.commitChanges()

        vl = QgsVectorLayer("?query=select * from mem_with_nontext_fieldnames",
                            "vl", "virtual")
        self.assertEqual(vl.isValid(), True)
        self.assertEqual(vl.fields().at(0).name(), '123')
        self.assertEqual(vl.fields().at(1).name(), 'abc:123')

        self.assertEqual(vl.featureCount(), 2)

        QgsProject.instance().removeMapLayer(ml)
Ejemplo n.º 22
0
    def testFieldsWithSpecialCharacters(self):
        ml = QgsVectorLayer("Point?srid=EPSG:4326&field=123:int",
                            "mem_with_nontext_fieldnames", "memory")
        self.assertEqual(ml.isValid(), True)
        QgsProject.instance().addMapLayer(ml)

        ml.startEditing()
        self.assertTrue(ml.addAttribute(QgsField('abc:123', QVariant.String)))
        self.assertTrue(ml.addAttribute(QgsField(
            'map', QVariant.String)))  # matches QGIS expression function name
        f1 = QgsFeature(ml.fields())
        f1.setGeometry(QgsGeometry.fromWkt('POINT(0 0)'))
        f1.setAttributes([1, 'a', 'b'])
        f2 = QgsFeature(ml.fields())
        f2.setGeometry(QgsGeometry.fromWkt('POINT(1 1)'))
        f2.setAttributes([2, 'c', 'd'])
        ml.addFeatures([f1, f2])
        ml.commitChanges()

        vl = QgsVectorLayer("?query=select * from mem_with_nontext_fieldnames",
                            "vl", "virtual")
        self.assertEqual(vl.isValid(), True)
        self.assertEqual(vl.fields().at(0).name(), '123')
        self.assertEqual(vl.fields().at(1).name(), 'abc:123')

        self.assertEqual(vl.featureCount(), 2)

        features = [
            f for f in vl.getFeatures(QgsFeatureRequest().setFilterExpression(
                '"abc:123"=\'c\''))
        ]
        self.assertEqual(len(features), 1)
        self.assertEqual(features[0].attributes(), [2, 'c', 'd'])

        features = [
            f for f in vl.getFeatures(QgsFeatureRequest().setFilterExpression(
                '"map"=\'b\''))
        ]
        self.assertEqual(len(features), 1)
        self.assertEqual(features[0].attributes(), [1, 'a', 'b'])

        vl2 = QgsVectorLayer(
            "?query=select * from mem_with_nontext_fieldnames where \"abc:123\"='c'",
            "vl", "virtual")
        self.assertEqual(vl2.isValid(), True)
        self.assertEqual(vl2.fields().at(0).name(), '123')
        self.assertEqual(vl2.fields().at(1).name(), 'abc:123')

        self.assertEqual(vl2.featureCount(), 1)

        features = [f for f in vl2.getFeatures()]
        self.assertEqual(len(features), 1)
        self.assertEqual(features[0].attributes(), [2, 'c', 'd'])

        vl3 = QgsVectorLayer(
            "?query=select * from mem_with_nontext_fieldnames where \"map\"='b'",
            "vl", "virtual")
        self.assertEqual(vl3.isValid(), True)
        self.assertEqual(vl3.fields().at(0).name(), '123')
        self.assertEqual(vl3.fields().at(1).name(), 'abc:123')

        self.assertEqual(vl3.featureCount(), 1)

        features = [f for f in vl3.getFeatures()]
        self.assertEqual(len(features), 1)
        self.assertEqual(features[0].attributes(), [1, 'a', 'b'])

        QgsProject.instance().removeMapLayer(ml)
Ejemplo n.º 23
0
def run(settings, progress_bars):

    for key in list(progress_bars.keys()):
        bar = progress_bars[key]
        bar['bar'].setValue(0)
        bar['label'].setText('')

    CreateTempDir()

    receiver_layer_name = os.path.splitext(
        os.path.basename(settings['receivers_path']))[0]
    receiver_layer = QgsVectorLayer(settings['receivers_path'],
                                    receiver_layer_name, "ogr")

    if settings['sources_pts_path'] is not None:
        source_pts_layer_name = os.path.splitext(
            os.path.basename(settings['sources_pts_path']))[0]
        source_pts_layer = QgsVectorLayer(settings['sources_pts_path'],
                                          source_pts_layer_name, "ogr")
    else:
        source_pts_layer = None

    if settings['sources_roads_path'] is not None:
        source_roads_layer_name = os.path.splitext(
            os.path.basename(settings['sources_roads_path']))[0]
        source_roads_layer = QgsVectorLayer(settings['sources_roads_path'],
                                            source_roads_layer_name, "ogr")

    else:
        source_roads_layer = None

    if settings['buildings_path'] is not None:
        obstacles_layer_name = os.path.splitext(
            os.path.basename(settings['buildings_path']))[0]
        obstacles_layer = QgsVectorLayer(settings['buildings_path'],
                                         obstacles_layer_name, "ogr")
    else:
        obstacles_layer = None

    rays_layer_path = settings['rays_path']
    diff_rays_layer_path = settings['diff_rays_path']

    # defines rays layer
    if rays_layer_path is not None:

        rays_fields = QgsFields()
        rays_fields.append(QgsField("id_ray", QVariant.Int))
        rays_fields.append(QgsField("id_rec", QVariant.Int))
        rays_fields.append(QgsField("id_emi", QVariant.Int))
        rays_fields.append(QgsField("d_rTOe", QVariant.Double, len=10, prec=2))
        rays_fields.append(
            QgsField("d_rTOe_4m", QVariant.Double, len=10, prec=2))

        if settings['period_pts_gen'] == "True" or settings[
                'period_roads_gen'] == "True":
            rays_fields.append(
                QgsField("gen_emi", QVariant.Double, len=5, prec=1))
            rays_fields.append(QgsField("gen", QVariant.Double, len=5, prec=1))
        if settings['period_pts_day'] == "True" or settings[
                'period_roads_day'] == "True":
            rays_fields.append(
                QgsField("day_emi", QVariant.Double, len=5, prec=1))
            rays_fields.append(QgsField("day", QVariant.Double, len=5, prec=1))
        if settings['period_pts_eve'] == "True" or settings[
                'period_roads_eve'] == "True":
            rays_fields.append(
                QgsField("eve_emi", QVariant.Double, len=5, prec=1))
            rays_fields.append(QgsField("eve", QVariant.Double, len=5, prec=1))
        if settings['period_pts_nig'] == "True" or settings[
                'period_roads_nig'] == "True":
            rays_fields.append(
                QgsField("nig_emi", QVariant.Double, len=5, prec=1))
            rays_fields.append(QgsField("nig", QVariant.Double, len=5, prec=1))

        rays_writer = QgsVectorFileWriter(rays_layer_path, "System",
                                          rays_fields, QgsWkbTypes.LineString,
                                          receiver_layer.crs(),
                                          "ESRI Shapefile")

    else:
        rays_writer = None

    # defines diff rays layer
    if diff_rays_layer_path is not None:

        rays_fields = QgsFields()
        rays_fields.append(QgsField("id_ray", QVariant.Int))
        rays_fields.append(QgsField("id_rec", QVariant.Int))
        rays_fields.append(QgsField("id_dif", QVariant.Int))
        rays_fields.append(QgsField("id_emi", QVariant.Int))
        rays_fields.append(QgsField("d_rTOd", QVariant.Double, len=10, prec=2))
        rays_fields.append(QgsField("d_dTOe", QVariant.Double, len=10, prec=2))
        rays_fields.append(QgsField("d_rTOe", QVariant.Double, len=10, prec=2))

        if settings['period_pts_gen'] == "True" or settings[
                'period_roads_gen'] == "True":
            rays_fields.append(
                QgsField("gen_emi", QVariant.Double, len=5, prec=1))
            rays_fields.append(QgsField("gen", QVariant.Double, len=5, prec=1))
        if settings['period_pts_day'] == "True" or settings[
                'period_roads_day'] == "True":
            rays_fields.append(
                QgsField("day_emi", QVariant.Double, len=5, prec=1))
            rays_fields.append(QgsField("day", QVariant.Double, len=5, prec=1))
        if settings['period_pts_eve'] == "True" or settings[
                'period_roads_eve'] == "True":
            rays_fields.append(
                QgsField("eve_emi", QVariant.Double, len=5, prec=1))
            rays_fields.append(QgsField("eve", QVariant.Double, len=5, prec=1))
        if settings['period_pts_nig'] == "True" or settings[
                'period_roads_nig'] == "True":
            rays_fields.append(
                QgsField("nig_emi", QVariant.Double, len=5, prec=1))
            rays_fields.append(QgsField("nig", QVariant.Double, len=5, prec=1))

        diff_rays_writer = QgsVectorFileWriter(diff_rays_layer_path, "System",
                                               rays_fields,
                                               QgsWkbTypes.LineString,
                                               receiver_layer.crs(),
                                               "ESRI Shapefile")

    else:
        diff_rays_writer = None

    # puts the sound level in the receivers points attribute table
    # gets fields from recever point layer and initializes the final receiver_point_field_level to populate the receiver points layer attribute table
    fields_number = int(receiver_layer.fields().count())

    level_field_index = {}

    #modified version in creating fields on existing layer in qgis 3.x
    receiver_layer.startEditing()
    #level_fields = []
    if settings['period_pts_gen'] == "True" or settings[
            'period_roads_gen'] == "True":
        receiver_layer.addAttribute(
            QgsField('gen', QVariant.Double, len=5, prec=1))
        level_field_index['gen'] = fields_number
        fields_number = fields_number + 1
    if settings['period_pts_day'] == "True" or settings[
            'period_roads_day'] == "True":
        receiver_layer.addAttribute((QgsField('day',
                                              QVariant.Double,
                                              len=5,
                                              prec=1)))
        level_field_index['day'] = fields_number
        fields_number = fields_number + 1
    if settings['period_pts_eve'] == "True" or settings[
            'period_roads_eve'] == "True":
        receiver_layer.addAttribute(
            QgsField('eve', QVariant.Double, len=5, prec=1))
        level_field_index['eve'] = fields_number
        fields_number = fields_number + 1
    if settings['period_pts_nig'] == "True" or settings[
            'period_roads_nig'] == "True":
        receiver_layer.addAttribute(
            QgsField('nig', QVariant.Double, len=5, prec=1))
        level_field_index['nig'] = fields_number
        fields_number = fields_number + 1
    if settings['period_den'] == "True":
        receiver_layer.addAttribute(
            QgsField('den', QVariant.Double, len=5, prec=1))
        level_field_index['den'] = fields_number
        fields_number = fields_number + 1

    #receiver_layer.dataProvider().addAttributes( level_fields )
    receiver_layer.updateFields()

    #calculation
    receiver_feat_new_fields = calc(progress_bars, receiver_layer,
                                    source_pts_layer, source_roads_layer,
                                    settings, level_field_index,
                                    obstacles_layer, rays_writer,
                                    diff_rays_writer)

    #old way to insert data in table
    # receiver_layer.dataProvider().changeAttributeValues(receiver_feat_new_fields)

    #new way to insert data in table
    for f in receiver_layer.getFeatures():
        if 'gen' in level_field_index:
            f['gen'] = receiver_feat_new_fields[f.id()][
                level_field_index['gen']]
            #print(receiver_feat_new_fields,f.id(),f['gen'])
        if 'day' in level_field_index:
            f['day'] = receiver_feat_new_fields[f.id()][
                level_field_index['day']]
        if 'eve' in level_field_index:
            f['eve'] = receiver_feat_new_fields[f.id()][
                level_field_index['eve']]
        if 'nig' in level_field_index:
            f['nig'] = receiver_feat_new_fields[f.id()][
                level_field_index['nig']]
        if 'den' in level_field_index:
            f['den'] = receiver_feat_new_fields[f.id()][
                level_field_index['den']]
        receiver_layer.updateFeature(f)

    receiver_layer.updateExtents()

    receiver_layer.commitChanges()

    #reload all layers to see the updates of shapefile of receivers
    QgsProject.instance().reloadAllLayers()

    if rays_layer_path is not None:
        del rays_writer
        rays_layer_name = os.path.splitext(
            os.path.basename(rays_layer_path))[0]
        rays_layer = QgsVectorLayer(rays_layer_path, str(rays_layer_name),
                                    "ogr")

        QgsProject.instance().addMapLayers([rays_layer])

    if diff_rays_layer_path is not None:
        del diff_rays_writer
        diff_rays_layer_name = os.path.splitext(
            os.path.basename(diff_rays_layer_path))[0]
        diff_rays_layer = QgsVectorLayer(diff_rays_layer_path,
                                         str(diff_rays_layer_name), "ogr")

        QgsProject.instance().addMapLayers([diff_rays_layer])

        QgsProject.instance().reloadAllLayers()

    # render receivers with noise colours
    level_fields_new = list(receiver_layer.dataProvider().fields())

    if len(level_fields_new) > 0:
        receiver_layer_name = settings['receivers_name']
        layer = QgsProject.instance().mapLayersByName(receiver_layer_name)[0]
        on_ApplyNoiseSymbology.renderizeXY(
            layer, level_fields_new[len(level_fields_new) - 1].name())

    DeleteTempDir()
        def _test(autoTransaction):
            """Test buffer methods within and without transactions

            - create a feature
            - save
            - retrieve the feature
            - change geom and attrs
            - test changes are seen in the buffer
            """

            def _check_feature(wkt):

                f = next(layer_a.getFeatures())
                self.assertEqual(f.geometry().asWkt().upper(), wkt)
                f = list(buffer.addedFeatures().values())[0]
                self.assertEqual(f.geometry().asWkt().upper(), wkt)

            ml = QgsVectorLayer('Point?crs=epsg:4326&field=int:integer', 'test', 'memory')
            self.assertTrue(ml.isValid())

            d = QTemporaryDir()
            options = QgsVectorFileWriter.SaveVectorOptions()
            options.driverName = 'GPKG'
            options.layerName = 'layer_a'
            err, _ = QgsVectorFileWriter.writeAsVectorFormatV2(ml, os.path.join(d.path(), 'transaction_test.gpkg'), QgsCoordinateTransformContext(), options)

            self.assertEqual(err, QgsVectorFileWriter.NoError)
            self.assertTrue(os.path.isfile(os.path.join(d.path(), 'transaction_test.gpkg')))

            options.layerName = 'layer_b'
            options.actionOnExistingFile = QgsVectorFileWriter.CreateOrOverwriteLayer
            err, _ = QgsVectorFileWriter.writeAsVectorFormatV2(ml, os.path.join(d.path(), 'transaction_test.gpkg'), QgsCoordinateTransformContext(), options)

            layer_a = QgsVectorLayer(os.path.join(d.path(), 'transaction_test.gpkg|layername=layer_a'))

            self.assertTrue(layer_a.isValid())

            project = QgsProject()
            project.setAutoTransaction(autoTransaction)
            project.addMapLayers([layer_a])

            ###########################################
            # Tests with a new feature

            self.assertTrue(layer_a.startEditing())
            buffer = layer_a.editBuffer()

            f = QgsFeature(layer_a.fields())
            f.setAttribute('int', 123)
            f.setGeometry(QgsGeometry.fromWkt('point(7 45)'))
            self.assertTrue(layer_a.addFeatures([f]))

            _check_feature('POINT (7 45)')

            # Need to fetch the feature because its ID is NULL (-9223372036854775808)
            f = next(layer_a.getFeatures())

            self.assertEqual(len(buffer.addedFeatures()), 1)
            layer_a.undoStack().undo()
            self.assertEqual(len(buffer.addedFeatures()), 0)
            layer_a.undoStack().redo()
            self.assertEqual(len(buffer.addedFeatures()), 1)
            f = list(buffer.addedFeatures().values())[0]
            self.assertEqual(f.attribute('int'), 123)

            # Now change attribute
            self.assertEqual(buffer.changedAttributeValues(), {})
            layer_a.changeAttributeValue(f.id(), 1, 321)

            self.assertEqual(len(buffer.addedFeatures()), 1)
            # This is surprising: because it was a new feature it has been changed directly
            self.assertEqual(buffer.changedAttributeValues(), {})
            f = list(buffer.addedFeatures().values())[0]
            self.assertEqual(f.attribute('int'), 321)

            layer_a.undoStack().undo()
            self.assertEqual(buffer.changedAttributeValues(), {})
            f = list(buffer.addedFeatures().values())[0]
            self.assertEqual(f.attribute('int'), 123)
            f = next(layer_a.getFeatures())
            self.assertEqual(f.attribute('int'), 123)

            # Change geometry
            f = next(layer_a.getFeatures())
            self.assertTrue(layer_a.changeGeometry(f.id(), QgsGeometry.fromWkt('point(9 43)')))

            _check_feature('POINT (9 43)')
            self.assertEqual(buffer.changedGeometries(), {})

            layer_a.undoStack().undo()

            _check_feature('POINT (7 45)')
            self.assertEqual(buffer.changedGeometries(), {})

            self.assertTrue(layer_a.changeGeometry(f.id(), QgsGeometry.fromWkt('point(9 43)')))
            _check_feature('POINT (9 43)')

            self.assertTrue(layer_a.changeGeometry(f.id(), QgsGeometry.fromWkt('point(10 44)')))
            _check_feature('POINT (10 44)')

            # This is anothr surprise: geometry edits get collapsed into a single
            # one because they have the same hardcoded id
            layer_a.undoStack().undo()
            _check_feature('POINT (7 45)')

            self.assertTrue(layer_a.commitChanges())

            ###########################################
            # Tests with the existing feature

            # Get the feature
            f = next(layer_a.getFeatures())
            self.assertTrue(f.isValid())
            self.assertEqual(f.attribute('int'), 123)
            self.assertEqual(f.geometry().asWkt().upper(), 'POINT (7 45)')

            self.assertTrue(layer_a.startEditing())
            layer_a.changeAttributeValue(f.id(), 1, 321)
            buffer = layer_a.editBuffer()
            self.assertEqual(buffer.changedAttributeValues(), {1: {1: 321}})
            layer_a.undoStack().undo()
            self.assertEqual(buffer.changedAttributeValues(), {})

            # Change geometry
            self.assertTrue(layer_a.changeGeometry(f.id(), QgsGeometry.fromWkt('point(9 43)')))
            f = next(layer_a.getFeatures())
            self.assertEqual(f.geometry().asWkt().upper(), 'POINT (9 43)')
            self.assertEqual(buffer.changedGeometries()[1].asWkt().upper(), 'POINT (9 43)')
            layer_a.undoStack().undo()
            self.assertEqual(buffer.changedGeometries(), {})
            f = next(layer_a.getFeatures())

            self.assertEqual(f.geometry().asWkt().upper(), 'POINT (7 45)')
            self.assertEqual(buffer.changedGeometries(), {})

            # Delete an existing feature
            self.assertTrue(layer_a.deleteFeature(f.id()))
            with self.assertRaises(StopIteration):
                next(layer_a.getFeatures())
            self.assertEqual(buffer.deletedFeatureIds(), [f.id()])

            layer_a.undoStack().undo()
            self.assertTrue(layer_a.getFeature(f.id()).isValid())
            self.assertEqual(buffer.deletedFeatureIds(), [])

            ###########################################
            # Test delete

            # Delete a new feature
            f = QgsFeature(layer_a.fields())
            f.setAttribute('int', 555)
            f.setGeometry(QgsGeometry.fromWkt('point(8 46)'))
            self.assertTrue(layer_a.addFeatures([f]))
            f = [f for f in layer_a.getFeatures() if f.attribute('int') == 555][0]
            self.assertTrue(f.id() in buffer.addedFeatures())
            self.assertTrue(layer_a.deleteFeature(f.id()))
            self.assertFalse(f.id() in buffer.addedFeatures())
            self.assertFalse(f.id() in buffer.deletedFeatureIds())

            layer_a.undoStack().undo()
            self.assertTrue(f.id() in buffer.addedFeatures())

            ###########################################
            # Add attribute

            field = QgsField('attr1', QVariant.String)
            self.assertTrue(layer_a.addAttribute(field))
            self.assertNotEqual(layer_a.fields().lookupField(field.name()), -1)
            self.assertEqual(buffer.addedAttributes(), [field])

            layer_a.undoStack().undo()
            self.assertEqual(layer_a.fields().lookupField(field.name()), -1)
            self.assertEqual(buffer.addedAttributes(), [])

            layer_a.undoStack().redo()
            self.assertNotEqual(layer_a.fields().lookupField(field.name()), -1)
            self.assertEqual(buffer.addedAttributes(), [field])

            self.assertTrue(layer_a.commitChanges())

            ###########################################
            # Remove attribute

            self.assertTrue(layer_a.startEditing())
            buffer = layer_a.editBuffer()

            attr_idx = layer_a.fields().lookupField(field.name())
            self.assertNotEqual(attr_idx, -1)

            self.assertTrue(layer_a.deleteAttribute(attr_idx))
            self.assertEqual(buffer.deletedAttributeIds(), [2])
            self.assertEqual(layer_a.fields().lookupField(field.name()), -1)

            layer_a.undoStack().undo()
            self.assertEqual(buffer.deletedAttributeIds(), [])
            self.assertEqual(layer_a.fields().lookupField(field.name()), attr_idx)

            layer_a.undoStack().redo()
            self.assertEqual(buffer.deletedAttributeIds(), [2])
            self.assertEqual(layer_a.fields().lookupField(field.name()), -1)

            self.assertTrue(layer_a.rollBack())

            ###########################################
            # Rename attribute

            self.assertTrue(layer_a.startEditing())

            attr_idx = layer_a.fields().lookupField(field.name())
            self.assertNotEqual(attr_idx, -1)

            self.assertEqual(layer_a.fields().lookupField('new_name'), -1)
            self.assertTrue(layer_a.renameAttribute(attr_idx, 'new_name'))
            self.assertEqual(layer_a.fields().lookupField('new_name'), attr_idx)

            layer_a.undoStack().undo()
            self.assertEqual(layer_a.fields().lookupField(field.name()), attr_idx)
            self.assertEqual(layer_a.fields().lookupField('new_name'), -1)

            layer_a.undoStack().redo()
            self.assertEqual(layer_a.fields().lookupField('new_name'), attr_idx)
            self.assertEqual(layer_a.fields().lookupField(field.name()), -1)
Ejemplo n.º 25
0
def create_polylines(output_filename, launch_datetime, launch_locations):
    # create output feature class
    lines_layer = QgsVectorLayer(output_filename)

    lines_layer.startEditing()

    # create fields in new feature class
    lines_layer.addAttribute(QgsField("Name", QVariant.String))
    lines_layer.addAttribute(QgsField("Lnch_Time", QVariant.String))
    lines_layer.addAttribute(QgsField("Dataset", QVariant.String))
    lines_layer.addAttribute(QgsField("Lnch_Lon", QVariant.Double))
    lines_layer.addAttribute(QgsField("Lnch_Lat", QVariant.Double))
    lines_layer.addAttribute(QgsField("Lnch_Alt_m", QVariant.Double))
    lines_layer.addAttribute(QgsField("Ascnt_m_s", QVariant.Double))
    lines_layer.addAttribute(QgsField("Brst_Alt_m", QVariant.Double))
    lines_layer.addAttribute(QgsField("Dscnt_m_s", QVariant.Double))
    lines_layer.addAttribute(QgsField("Length_m", QVariant.Double))

    lines_layer.commitChanges()

    features = []

    # set predict Id
    current_predict_id = 1

    # populate fields for each launch location predict
    for name, launch_location in launch_locations.items():
        print(f'Getting prediction for {name}')
        query_json = CUSFPredictionAPI.request_prediction(
            launch_longitude=launch_location[0],
            launch_latitude=launch_location[1],
            launch_datetime=launch_datetime)

        features.append(
            json_to_polylines(query_json, output_filename, name,
                              current_predict_id))

        current_predict_id += 1

    lines_layer.startEditing()

    # insert polylines into layer
    lines_layer.dataProvider().addFeatures(features)

    # insert polyline
    lines_layer.commitChanges()
Ejemplo n.º 26
0
 def extract(self, outPath, tableName):
     # main process
     
     # open target point layer
     targetLayer = self.targetItems[str(self.TargetLayer.currentText())][0]
     targetprovider = targetLayer.dataProvider()
     allAttrs = targetprovider.attributeIndexes()
     sRs = targetLayer.crs()
     
     # create output layer: first create list of selected fields
     fieldList = QgsFields()
     for i in range(len(self.fields)):
         if self.fields[i][0] == "point":
             # copying fields from source layer
             field = targetprovider.fields()[targetprovider.fieldNameIndex(self.targetItems[self.fields[i][1]][self.fields[i][2]][0])]
             field.setName(self.targetItems[self.fields[i][1]][self.fields[i][2]][1])
             
         elif self.fields[i][0] == "polygon": 
             # copying fields from polygon layers
             polyLayer = self.polygonItems[self.fields[i][1]][0]
             polyProvider = polyLayer.dataProvider()
             field = polyProvider.fields()[polyProvider.fieldNameIndex(self.polygonItems[self.fields[i][1]][self.fields[i][2]][0])]
             field.setName(self.polygonItems[self.fields[i][1]][self.fields[i][2]][1])
         
         else: 
             # creating fields for raster layers
             field = QgsField(self.rasterItems[self.fields[i][1]][self.fields[i][2]][1], QVariant.Double, "real", 20, 5, "")
         
         fieldList.append(field)
         
     # create temporary memory layer 
     memLayer = QgsVectorLayer("Point?crs=epsg:%d" % sRs.postgisSrid(), 'temp layer', 'memory')
     memLayer.startEditing()
     for field in fieldList:
         memLayer.addAttribute(field)
     memLayer.commitChanges()
     
     self.repaint()
     # process point after point
     pointFeat = QgsFeature()
     np = 0
     snp = targetprovider.featureCount()
     for pointFeat in targetprovider.getFeatures():
         np += 1
         # convert multipoint[0] to point
         pointGeom = pointFeat.geometry()
         if pointGeom.wkbType() == QgsWkbTypes.MultiPoint:
             pointPoint = pointGeom.asMultiPoint()[0]
         else:
             pointPoint = pointGeom.asPoint()
         outFeat = QgsFeature()
         outFeat.setGeometry(pointGeom)
         
         # and next loop inside: field after field
         bBox = QgsRectangle(pointPoint.x()-0.001,pointPoint.y()-0.001,pointPoint.x()+0.001,pointPoint.y()+0.001) 
         # reusable rectangle buffer around the point feature
         previousPolyLayer = None  # reuse previous feature if it's still the same layer
         previousPolyFeat = None   # reuse previous feature if it's still the same layer
         previousRastLayer = None  # reuse previous raster multichannel sample if it's still the same layer
         previousRastSample = None # reuse previous raster multichannel sample if it's still the same layer
         attrs = []
         for i in range(len(self.fields)):
             field = self.fields[i]
             
             if field[0] == "point":
                 attr = pointFeat.attributes()[targetprovider.fieldNameIndex(self.targetItems[field[1]][field[2]][0])]
                 attrs += [attr]
                 
             elif field[0] == "polygon":
                 polyLayer = self.polygonItems[field[1]][0]
                 polyProvider = polyLayer.dataProvider()
                 
                 if polyLayer == previousPolyLayer:
                     polyFeat = previousPolyFeat
                     
                 else:
                     polyFeat = None
                     pointGeom = QgsGeometry().fromPointXY(pointPoint)
                     for iFeat in polyProvider.getFeatures(QgsFeatureRequest().setFilterRect(bBox)):
                         if pointGeom.intersects(iFeat.geometry()):
                             polyFeat = iFeat
                             
                 if polyFeat:
                     attr = polyFeat.attributes()[polyProvider.fieldNameIndex(self.polygonItems[field[1]][field[2]][0])]
                 
                 else:
                     attr = None
                 attrs += [attr] 
                 #only last one if more polygons overlaps
                 previousPolyLayer = polyLayer
                 previousPolyFeat = polyFeat
                 
             else:
                 # raster
                 rastLayer = self.rasterItems[field[1]][0]
                 if rastLayer == previousRastLayer:
                     rastSample = previousRastSample
                     
                 else:
                     rastSample = rastLayer.dataProvider().identify(pointPoint, QgsRaster.IdentifyFormatValue).results()
                 
                 try:
                     bandNo = field[2]
                     attr = float(rastSample[bandNo])
                 except: # point is out of raster extent
                     attr = None
                 
                 attrs += [attr]
                 previousRastLayer = rastLayer
                 previousRastSample = rastSample
                 
         outFeat.initAttributes(len(attrs))
         outFeat.setAttributes(attrs)
         memLayer.dataProvider().addFeature(outFeat)
     
     # write memlayer to the output file
     so = QgsVectorFileWriter.SaveVectorOptions()
     so.fileEncoding = 'UTF-8'
     
     if outPath.upper().endswith('SHP'):
         so.driverName = "ESRI Shapefile"
     elif outPath.upper().endswith('CSV'):
         so.driverName = "CSV"
     else:
         so.driverName = "GPKG"
         if tableName:
             so.actionOnExistingFile = QgsVectorFileWriter.CreateOrOverwriteLayer
             so.layerName = tableName
     result, errMsg = QgsVectorFileWriter.writeAsVectorFormat(memLayer, outPath, so)
     if result:
         QMessageBox.critical(self, self.tr("Extract tool"), errMsg)
         return False
     else:
         del memLayer
         return True
Ejemplo n.º 27
0
    def sampling(self, outPath, tableName):  # main process
        # open sampling points layer
        pointLayer = self.sampItems[str(self.inSample.currentText())][0]
        pointProvider = pointLayer.dataProvider()
        allAttrs = pointProvider.attributeIndexes()
        sRs = pointLayer.crs()
        # create destination layer: first create list of selected fields
        fieldList = QgsFields()
        for i in range(len(self.fields)):
            if self.fields[i][0] == "point":  #copying fields from source layer
                field = pointProvider.fields()[pointProvider.fieldNameIndex(
                    self.sampItems[self.fields[i][1]][self.fields[i][2]][0])]
                field.setName(
                    self.sampItems[self.fields[i][1]][self.fields[i][2]][1])
            elif self.fields[i][
                    0] == "poly":  #copying fields from polygon layers
                polyLayer = self.polyItems[self.fields[i][1]][0]
                polyProvider = polyLayer.dataProvider()
                field = polyProvider.fields()[polyProvider.fieldNameIndex(
                    self.polyItems[self.fields[i][1]][self.fields[i][2]][0])]
                field.setName(
                    self.polyItems[self.fields[i][1]][self.fields[i][2]][1])
            else:  #creating fields for raster layers
                field = QgsField(
                    self.rastItems[self.fields[i][1]][self.fields[i][2]][1],
                    QVariant.Double, "real", 20, 5, "")
                ##### Better data type fit will be implemented in next versions
            fieldList.append(field)
        # create temporary memory layer (as it's currently impossible to set GPKG table name when writting features to QgsVectorFileWriter directly)
        memLayer = QgsVectorLayer("Point?crs=epsg:%d" % sRs.postgisSrid(),
                                  'temp layer', 'memory')
        memLayer.startEditing()
        for field in fieldList:
            memLayer.addAttribute(field)
        memLayer.commitChanges()

        self.statusLabel.setText("Writing data to the new layer...")
        self.repaint()
        # process point after point...
        pointFeat = QgsFeature()
        np = 0
        snp = pointProvider.featureCount()
        for pointFeat in pointProvider.getFeatures():
            np += 1
            if snp < 100 or (snp < 5000 and (np // 10.0 == np / 10.0)) or (
                    np // 100.0 == np /
                    100.0):  # display each or every 10th or every 100th point:
                self.statusLabel.setText("Processing point %s of %s" %
                                         (np, snp))
                self.repaint()
            # convert multipoint[0] to point
            pointGeom = pointFeat.geometry()
            if pointGeom.wkbType() == QgsWkbTypes.MultiPoint:
                pointPoint = pointGeom.asMultiPoint()[0]
            else:
                pointPoint = pointGeom.asPoint()
            outFeat = QgsFeature()
            outFeat.setGeometry(pointGeom)
            # ...and next loop inside: field after field
            bBox = QgsRectangle(
                pointPoint.x() - 0.001,
                pointPoint.y() - 0.001,
                pointPoint.x() + 0.001,
                pointPoint.y() +
                0.001)  # reuseable rectangle buffer around the point feature
            previousPolyLayer = None  # reuse previous feature if it's still the same layer
            previousPolyFeat = None  # reuse previous feature if it's still the same layer
            previousRastLayer = None  # reuse previous raster multichannel sample if it's still the same layer
            previousRastSample = None  # reuse previous raster multichannel sample if it's still the same layer
            attrs = []
            for i in range(len(self.fields)):
                field = self.fields[i]
                if field[0] == "point":
                    attr = pointFeat.attributes()[pointProvider.fieldNameIndex(
                        self.sampItems[field[1]][field[2]][0])]
                    attrs += [attr]
                elif field[0] == "poly":
                    polyLayer = self.polyItems[field[1]][0]
                    polyProvider = polyLayer.dataProvider()
                    if polyLayer == previousPolyLayer:
                        polyFeat = previousPolyFeat
                    else:
                        polyFeat = None
                        pointGeom = QgsGeometry().fromPointXY(pointPoint)
                        for iFeat in polyProvider.getFeatures(
                                QgsFeatureRequest().setFilterRect(bBox)):
                            if pointGeom.intersects(iFeat.geometry()):
                                polyFeat = iFeat
                    if polyFeat:
                        attr = polyFeat.attributes()[
                            polyProvider.fieldNameIndex(
                                self.polyItems[field[1]][field[2]][0])]
                    else:
                        attr = None
                    attrs += [
                        attr
                    ]  #only last one if more polygons overlaps!! This way we avoid attribute list overflow
                    previousPolyLayer = polyLayer
                    previousPolyFeat = polyFeat
                else:  # field source is raster
                    rastLayer = self.rastItems[field[1]][0]
                    if rastLayer == previousRastLayer:
                        rastSample = previousRastSample
                    else:
                        rastSample = rastLayer.dataProvider().identify(
                            pointPoint,
                            QgsRaster.IdentifyFormatValue).results()
                    try:
                        #bandName = self.rastItems[field[1]][field[2]][0] #depreciated
                        bandNo = field[2]
                        attr = float(
                            rastSample[bandNo]
                        )  ##### !! float() - I HAVE TO IMPLEMENT RASTER TYPE HANDLING!!!!
                    except:  # point is out of raster extent
                        attr = None
                    attrs += [attr]
                    previousRastLayer = rastLayer
                    previousRastSample = rastSample
            outFeat.initAttributes(len(attrs))
            outFeat.setAttributes(attrs)
            memLayer.dataProvider().addFeature(outFeat)

        # write the memlayer to the output file
        so = QgsVectorFileWriter.SaveVectorOptions()
        so.fileEncoding = 'UTF-8'
        if outPath.upper().endswith('SHP'):
            so.driverName = "ESRI Shapefile"
        elif outPath.upper().endswith('CSV'):
            so.driverName = "CSV"
        else:
            so.driverName = "GPKG"
            if tableName:
                so.actionOnExistingFile = QgsVectorFileWriter.CreateOrOverwriteLayer
                so.layerName = tableName
        result, errMsg = QgsVectorFileWriter.writeAsVectorFormat(
            memLayer, outPath, so)
        if result:
            QMessageBox.critical(self, "Point sampling tool", errMsg)
            return False
        else:
            del memLayer
            self.statusLabel.setText("The new layer has been created.")
            return True
Ejemplo n.º 28
0
        def _test(autoTransaction):
            """Test buffer methods within and without transactions

            - create a feature
            - save
            - retrieve the feature
            - change geom and attrs
            - test changes are seen in the buffer
            """
            def _check_feature(wkt):

                f = next(layer_a.getFeatures())
                self.assertEqual(f.geometry().asWkt().upper(), wkt)
                f = list(buffer.addedFeatures().values())[0]
                self.assertEqual(f.geometry().asWkt().upper(), wkt)

            ml = QgsVectorLayer(
                'Point?crs=epsg:4326&field=int:integer&field=int2:integer',
                'test', 'memory')
            self.assertTrue(ml.isValid())

            d = QTemporaryDir()
            options = QgsVectorFileWriter.SaveVectorOptions()
            options.driverName = 'GPKG'
            options.layerName = 'layer_a'
            err, msg, newFileName, newLayer = QgsVectorFileWriter.writeAsVectorFormatV3(
                ml, os.path.join(d.path(), 'transaction_test.gpkg'),
                QgsCoordinateTransformContext(), options)

            self.assertEqual(err, QgsVectorFileWriter.NoError)
            self.assertTrue(os.path.isfile(newFileName))

            layer_a = QgsVectorLayer(newFileName + '|layername=layer_a')

            self.assertTrue(layer_a.isValid())

            project = QgsProject()
            project.setAutoTransaction(autoTransaction)
            project.addMapLayers([layer_a])

            ###########################################
            # Tests with a new feature

            self.assertTrue(layer_a.startEditing())
            buffer = layer_a.editBuffer()

            f = QgsFeature(layer_a.fields())
            f.setAttribute('int', 123)
            f.setGeometry(QgsGeometry.fromWkt('point(7 45)'))
            self.assertTrue(layer_a.addFeatures([f]))

            _check_feature('POINT (7 45)')

            # Need to fetch the feature because its ID is NULL (-9223372036854775808)
            f = next(layer_a.getFeatures())

            self.assertEqual(len(buffer.addedFeatures()), 1)
            layer_a.undoStack().undo()
            self.assertEqual(len(buffer.addedFeatures()), 0)
            layer_a.undoStack().redo()
            self.assertEqual(len(buffer.addedFeatures()), 1)
            f = list(buffer.addedFeatures().values())[0]
            self.assertEqual(f.attribute('int'), 123)

            # Now change attribute
            self.assertEqual(buffer.changedAttributeValues(), {})
            spy_attribute_changed = QSignalSpy(layer_a.attributeValueChanged)
            layer_a.changeAttributeValue(f.id(), 1, 321)
            self.assertEqual(len(spy_attribute_changed), 1)
            self.assertEqual(spy_attribute_changed[0], [f.id(), 1, 321])

            self.assertEqual(len(buffer.addedFeatures()), 1)
            # This is surprising: because it was a new feature it has been changed directly
            self.assertEqual(buffer.changedAttributeValues(), {})
            f = list(buffer.addedFeatures().values())[0]
            self.assertEqual(f.attribute('int'), 321)

            spy_attribute_changed = QSignalSpy(layer_a.attributeValueChanged)
            layer_a.undoStack().undo()
            self.assertEqual(len(spy_attribute_changed), 1)
            self.assertEqual(spy_attribute_changed[0], [f.id(), 1, 123])
            self.assertEqual(buffer.changedAttributeValues(), {})
            f = list(buffer.addedFeatures().values())[0]
            self.assertEqual(f.attribute('int'), 123)
            f = next(layer_a.getFeatures())
            self.assertEqual(f.attribute('int'), 123)

            # Change multiple attributes
            spy_attribute_changed = QSignalSpy(layer_a.attributeValueChanged)
            layer_a.changeAttributeValues(f.id(), {1: 321, 2: 456})
            self.assertEqual(len(spy_attribute_changed), 2)
            self.assertEqual(spy_attribute_changed[0], [f.id(), 1, 321])
            self.assertEqual(spy_attribute_changed[1], [f.id(), 2, 456])
            buffer = layer_a.editBuffer()
            # This is surprising: because it was a new feature it has been changed directly
            self.assertEqual(buffer.changedAttributeValues(), {})

            spy_attribute_changed = QSignalSpy(layer_a.attributeValueChanged)
            layer_a.undoStack().undo()
            # This is because QgsVectorLayerUndoCommandChangeAttribute plural
            if not autoTransaction:
                layer_a.undoStack().undo()
            f = next(layer_a.getFeatures())
            self.assertEqual(f.attribute('int'), 123)
            self.assertEqual(f.attribute('int2'), None)
            self.assertEqual(len(spy_attribute_changed), 2)
            self.assertEqual(
                spy_attribute_changed[1 if autoTransaction else 0],
                [f.id(), 2, None])
            self.assertEqual(
                spy_attribute_changed[0 if autoTransaction else 1],
                [f.id(), 1, 123])

            # Change geometry
            f = next(layer_a.getFeatures())
            spy_geometry_changed = QSignalSpy(layer_a.geometryChanged)
            self.assertTrue(
                layer_a.changeGeometry(f.id(),
                                       QgsGeometry.fromWkt('point(9 43)')))
            self.assertTrue(len(spy_geometry_changed), 1)
            self.assertEqual(spy_geometry_changed[0][0], f.id())
            self.assertEqual(spy_geometry_changed[0][1].asWkt(),
                             QgsGeometry.fromWkt('point(9 43)').asWkt())

            _check_feature('POINT (9 43)')
            self.assertEqual(buffer.changedGeometries(), {})

            layer_a.undoStack().undo()

            _check_feature('POINT (7 45)')
            self.assertEqual(buffer.changedGeometries(), {})

            self.assertTrue(
                layer_a.changeGeometry(f.id(),
                                       QgsGeometry.fromWkt('point(9 43)')))
            _check_feature('POINT (9 43)')

            self.assertTrue(
                layer_a.changeGeometry(f.id(),
                                       QgsGeometry.fromWkt('point(10 44)')))
            _check_feature('POINT (10 44)')

            # This is another surprise: geometry edits get collapsed into a single
            # one because they have the same hardcoded id
            layer_a.undoStack().undo()
            _check_feature('POINT (7 45)')

            self.assertTrue(layer_a.commitChanges())

            ###########################################
            # Tests with the existing feature

            # Get the feature
            f = next(layer_a.getFeatures())
            self.assertTrue(f.isValid())
            self.assertEqual(f.attribute('int'), 123)
            self.assertEqual(f.geometry().asWkt().upper(), 'POINT (7 45)')

            # Change single attribute
            self.assertTrue(layer_a.startEditing())
            spy_attribute_changed = QSignalSpy(layer_a.attributeValueChanged)
            layer_a.changeAttributeValue(f.id(), 1, 321)
            self.assertEqual(len(spy_attribute_changed), 1)
            self.assertEqual(spy_attribute_changed[0], [f.id(), 1, 321])
            buffer = layer_a.editBuffer()
            self.assertEqual(buffer.changedAttributeValues(), {1: {1: 321}})

            f = next(layer_a.getFeatures())
            self.assertEqual(f.attribute(1), 321)

            spy_attribute_changed = QSignalSpy(layer_a.attributeValueChanged)
            layer_a.undoStack().undo()
            f = next(layer_a.getFeatures())
            self.assertEqual(f.attribute(1), 123)
            self.assertEqual(len(spy_attribute_changed), 1)
            self.assertEqual(spy_attribute_changed[0], [f.id(), 1, 123])
            self.assertEqual(buffer.changedAttributeValues(), {})

            # Change attributes
            spy_attribute_changed = QSignalSpy(layer_a.attributeValueChanged)
            layer_a.changeAttributeValues(f.id(), {1: 111, 2: 654})
            self.assertEqual(len(spy_attribute_changed), 2)
            self.assertEqual(spy_attribute_changed[0], [1, 1, 111])
            self.assertEqual(spy_attribute_changed[1], [1, 2, 654])
            f = next(layer_a.getFeatures())
            self.assertEqual(f.attributes(), [1, 111, 654])
            self.assertEqual(buffer.changedAttributeValues(),
                             {1: {
                                 1: 111,
                                 2: 654
                             }})

            spy_attribute_changed = QSignalSpy(layer_a.attributeValueChanged)
            layer_a.undoStack().undo()
            # This is because QgsVectorLayerUndoCommandChangeAttribute plural
            if not autoTransaction:
                layer_a.undoStack().undo()
            self.assertEqual(len(spy_attribute_changed), 2)
            self.assertEqual(
                spy_attribute_changed[0 if autoTransaction else 1],
                [1, 1, 123])
            self.assertEqual(
                spy_attribute_changed[1 if autoTransaction else 0],
                [1, 2, None])
            f = next(layer_a.getFeatures())
            self.assertEqual(f.attributes(), [1, 123, None])
            self.assertEqual(buffer.changedAttributeValues(), {})

            # Change geometry
            spy_geometry_changed = QSignalSpy(layer_a.geometryChanged)
            self.assertTrue(
                layer_a.changeGeometry(f.id(),
                                       QgsGeometry.fromWkt('point(9 43)')))
            self.assertEqual(spy_geometry_changed[0][0], 1)
            self.assertEqual(spy_geometry_changed[0][1].asWkt(),
                             QgsGeometry.fromWkt('point(9 43)').asWkt())

            f = next(layer_a.getFeatures())
            self.assertEqual(f.geometry().asWkt().upper(), 'POINT (9 43)')
            self.assertEqual(buffer.changedGeometries()[1].asWkt().upper(),
                             'POINT (9 43)')

            spy_geometry_changed = QSignalSpy(layer_a.geometryChanged)
            layer_a.undoStack().undo()
            self.assertEqual(spy_geometry_changed[0][0], 1)
            self.assertEqual(spy_geometry_changed[0][1].asWkt(),
                             QgsGeometry.fromWkt('point(7 45)').asWkt())
            self.assertEqual(buffer.changedGeometries(), {})
            f = next(layer_a.getFeatures())

            self.assertEqual(f.geometry().asWkt().upper(), 'POINT (7 45)')
            self.assertEqual(buffer.changedGeometries(), {})

            # Delete an existing feature
            self.assertTrue(layer_a.deleteFeature(f.id()))
            with self.assertRaises(StopIteration):
                next(layer_a.getFeatures())
            self.assertEqual(buffer.deletedFeatureIds(), [f.id()])

            layer_a.undoStack().undo()
            self.assertTrue(layer_a.getFeature(f.id()).isValid())
            self.assertEqual(buffer.deletedFeatureIds(), [])

            ###########################################
            # Test delete

            # Delete a new feature
            f = QgsFeature(layer_a.fields())
            f.setAttribute('int', 555)
            f.setGeometry(QgsGeometry.fromWkt('point(8 46)'))
            self.assertTrue(layer_a.addFeatures([f]))
            f = [
                f for f in layer_a.getFeatures() if f.attribute('int') == 555
            ][0]
            self.assertTrue(f.id() in buffer.addedFeatures())
            self.assertTrue(layer_a.deleteFeature(f.id()))
            self.assertFalse(f.id() in buffer.addedFeatures())
            self.assertFalse(f.id() in buffer.deletedFeatureIds())

            layer_a.undoStack().undo()
            self.assertTrue(f.id() in buffer.addedFeatures())

            ###########################################
            # Add attribute

            field = QgsField('attr1', QVariant.String)
            self.assertTrue(layer_a.addAttribute(field))
            self.assertNotEqual(layer_a.fields().lookupField(field.name()), -1)
            self.assertEqual(buffer.addedAttributes(), [field])

            layer_a.undoStack().undo()
            self.assertEqual(layer_a.fields().lookupField(field.name()), -1)
            self.assertEqual(buffer.addedAttributes(), [])

            layer_a.undoStack().redo()
            self.assertNotEqual(layer_a.fields().lookupField(field.name()), -1)
            self.assertEqual(buffer.addedAttributes(), [field])

            self.assertTrue(layer_a.commitChanges())

            ###########################################
            # Remove attribute

            self.assertTrue(layer_a.startEditing())
            buffer = layer_a.editBuffer()

            attr_idx = layer_a.fields().lookupField(field.name())
            self.assertNotEqual(attr_idx, -1)

            self.assertTrue(layer_a.deleteAttribute(attr_idx))
            self.assertEqual(buffer.deletedAttributeIds(), [attr_idx])
            self.assertEqual(layer_a.fields().lookupField(field.name()), -1)

            layer_a.undoStack().undo()
            self.assertEqual(buffer.deletedAttributeIds(), [])
            self.assertEqual(layer_a.fields().lookupField(field.name()),
                             attr_idx)

            # This is totally broken at least on OGR/GPKG: the rollback
            # does not restore the original fields
            if False:

                layer_a.undoStack().redo()
                self.assertEqual(buffer.deletedAttributeIds(), [attr_idx])
                self.assertEqual(layer_a.fields().lookupField(field.name()),
                                 -1)

                # Rollback!
                self.assertTrue(layer_a.rollBack())

                self.assertIn('attr1', layer_a.dataProvider().fields().names())
                self.assertIn('attr1', layer_a.fields().names())
                self.assertEqual(layer_a.fields().names(),
                                 layer_a.dataProvider().fields().names())

                attr_idx = layer_a.fields().lookupField(field.name())
                self.assertNotEqual(attr_idx, -1)

                self.assertTrue(layer_a.startEditing())
                attr_idx = layer_a.fields().lookupField(field.name())
                self.assertNotEqual(attr_idx, -1)

            ###########################################
            # Rename attribute

            attr_idx = layer_a.fields().lookupField(field.name())
            self.assertEqual(layer_a.fields().lookupField('new_name'), -1)
            self.assertTrue(layer_a.renameAttribute(attr_idx, 'new_name'))
            self.assertEqual(layer_a.fields().lookupField('new_name'),
                             attr_idx)

            layer_a.undoStack().undo()
            self.assertEqual(layer_a.fields().lookupField(field.name()),
                             attr_idx)
            self.assertEqual(layer_a.fields().lookupField('new_name'), -1)

            layer_a.undoStack().redo()
            self.assertEqual(layer_a.fields().lookupField('new_name'),
                             attr_idx)
            self.assertEqual(layer_a.fields().lookupField(field.name()), -1)

            #############################################
            # Try hard to make this fail for transactions
            if autoTransaction:
                self.assertTrue(layer_a.commitChanges())
                self.assertTrue(layer_a.startEditing())
                f = next(layer_a.getFeatures())

                # Do
                for i in range(10):
                    spy_attribute_changed = QSignalSpy(
                        layer_a.attributeValueChanged)
                    layer_a.changeAttributeValue(f.id(), 2, i)
                    self.assertEqual(len(spy_attribute_changed), 1)
                    self.assertEqual(spy_attribute_changed[0], [f.id(), 2, i])
                    buffer = layer_a.editBuffer()
                    self.assertEqual(buffer.changedAttributeValues(),
                                     {f.id(): {
                                          2: i
                                      }})
                    f = next(layer_a.getFeatures())
                    self.assertEqual(f.attribute(2), i)

                # Undo/redo
                for i in range(9):

                    # Undo
                    spy_attribute_changed = QSignalSpy(
                        layer_a.attributeValueChanged)
                    layer_a.undoStack().undo()
                    f = next(layer_a.getFeatures())
                    self.assertEqual(f.attribute(2), 8 - i)
                    self.assertEqual(len(spy_attribute_changed), 1)
                    self.assertEqual(spy_attribute_changed[0],
                                     [f.id(), 2, 8 - i])
                    buffer = layer_a.editBuffer()
                    self.assertEqual(buffer.changedAttributeValues(),
                                     {f.id(): {
                                          2: 8 - i
                                      }})

                    # Redo
                    spy_attribute_changed = QSignalSpy(
                        layer_a.attributeValueChanged)
                    layer_a.undoStack().redo()
                    f = next(layer_a.getFeatures())
                    self.assertEqual(f.attribute(2), 9 - i)
                    self.assertEqual(len(spy_attribute_changed), 1)
                    self.assertEqual(spy_attribute_changed[0],
                                     [f.id(), 2, 9 - i])

                    # Undo again
                    spy_attribute_changed = QSignalSpy(
                        layer_a.attributeValueChanged)
                    layer_a.undoStack().undo()
                    f = next(layer_a.getFeatures())
                    self.assertEqual(f.attribute(2), 8 - i)
                    self.assertEqual(len(spy_attribute_changed), 1)
                    self.assertEqual(spy_attribute_changed[0],
                                     [f.id(), 2, 8 - i])
                    buffer = layer_a.editBuffer()
                    self.assertEqual(buffer.changedAttributeValues(),
                                     {f.id(): {
                                          2: 8 - i
                                      }})

                    # Last check
                    f = next(layer_a.getFeatures())
                    self.assertEqual(f.attribute(2), 8 - i)

                self.assertEqual(buffer.changedAttributeValues(),
                                 {f.id(): {
                                      2: 0
                                  }})
                layer_a.undoStack().undo()
                buffer = layer_a.editBuffer()
                self.assertEqual(buffer.changedAttributeValues(), {})
                f = next(layer_a.getFeatures())
                self.assertEqual(f.attribute(2), None)
 def sampling(self, outPath, tableName): # main process
    # open sampling points layer
    pointLayer = self.sampItems[str(self.inSample.currentText())][0]
    pointProvider = pointLayer.dataProvider()
    allAttrs = pointProvider.attributeIndexes()
    sRs = pointLayer.crs()
    # create destination layer: first create list of selected fields
    fieldList = QgsFields()
    for i in range(len(self.fields)):
        if self.fields[i][0] == "point": #copying fields from source layer
            field = pointProvider.fields()[pointProvider.fieldNameIndex(self.sampItems[self.fields[i][1]][self.fields[i][2]][0])]
            field.setName(self.sampItems[self.fields[i][1]][self.fields[i][2]][1])
        elif self.fields[i][0] == "poly": #copying fields from polygon layers
            polyLayer = self.polyItems[self.fields[i][1]][0]
            polyProvider = polyLayer.dataProvider()
            field = polyProvider.fields()[polyProvider.fieldNameIndex(self.polyItems[self.fields[i][1]][self.fields[i][2]][0])]
            field.setName(self.polyItems[self.fields[i][1]][self.fields[i][2]][1])
        else: #creating fields for raster layers
            field = QgsField(self.rastItems[self.fields[i][1]][self.fields[i][2]][1], QVariant.Double, "real", 20, 5, "")
            ##### Better data type fit will be implemented in next versions
        fieldList.append(field)
    # create temporary memory layer (as it's currently impossible to set GPKG table name when writting features to QgsVectorFileWriter directly)
    memLayer = QgsVectorLayer("Point?crs=epsg:%d" % sRs.postgisSrid(), 'temp layer', 'memory')
    memLayer.startEditing()
    for field in fieldList:
        memLayer.addAttribute(field)
    memLayer.commitChanges()

    self.statusLabel.setText(self.tr("Writing data to the new layer..."))
    self.repaint()
    # process point after point...
    pointFeat = QgsFeature()
    np = 0
    snp = pointProvider.featureCount()
    for pointFeat in pointProvider.getFeatures():
        np += 1
        if snp<100 or ( snp<5000 and ( np // 10.0 == np / 10.0 ) ) or ( np // 100.0 == np / 100.0 ): # display each or every 10th or every 100th point:
            self.statusLabel.setText(self.tr("Processing point %s of %s") % (np, snp))
            self.repaint()
        # convert multipoint[0] to point
        pointGeom = pointFeat.geometry()
        if pointGeom.wkbType() == QgsWkbTypes.MultiPoint:
            pointPoint = pointGeom.asMultiPoint()[0]
        else:
            pointPoint = pointGeom.asPoint()
        outFeat = QgsFeature()
        outFeat.setGeometry(pointGeom)
        # ...and next loop inside: field after field
        bBox = QgsRectangle(pointPoint.x()-0.001,pointPoint.y()-0.001,pointPoint.x()+0.001,pointPoint.y()+0.001) # reuseable rectangle buffer around the point feature
        previousPolyLayer = None  # reuse previous feature if it's still the same layer
        previousPolyFeat = None   # reuse previous feature if it's still the same layer
        previousRastLayer = None  # reuse previous raster multichannel sample if it's still the same layer
        previousRastSample = None # reuse previous raster multichannel sample if it's still the same layer
        attrs = []
        for i in range(len(self.fields)):
            field = self.fields[i]
            if field[0] == "point":
                attr = pointFeat.attributes()[pointProvider.fieldNameIndex(self.sampItems[field[1]][field[2]][0])]
                attrs += [attr]
            elif field[0] == "poly":
                polyLayer = self.polyItems[field[1]][0]
                polyProvider = polyLayer.dataProvider()
                if polyLayer == previousPolyLayer:
                    polyFeat = previousPolyFeat
                else:
                    polyFeat = None
                    pointGeom = QgsGeometry().fromPointXY(pointPoint)
                    for iFeat in polyProvider.getFeatures(QgsFeatureRequest().setFilterRect(bBox)):
                        if pointGeom.intersects(iFeat.geometry()):
                            polyFeat = iFeat
                if polyFeat:
                    attr = polyFeat.attributes()[polyProvider.fieldNameIndex(self.polyItems[field[1]][field[2]][0])]
                else:
                    attr = None
                attrs += [attr] #only last one if more polygons overlaps!! This way we avoid attribute list overflow
                previousPolyLayer = polyLayer
                previousPolyFeat = polyFeat
            else: # field source is raster
                rastLayer = self.rastItems[field[1]][0]
                if rastLayer == previousRastLayer:
                    rastSample = previousRastSample
                else:
                    rastSample = rastLayer.dataProvider().identify(pointPoint, QgsRaster.IdentifyFormatValue).results()
                try:
                    #bandName = self.rastItems[field[1]][field[2]][0] #depreciated
                    bandNo = field[2]
                    attr = float(rastSample[bandNo]) ##### !! float() - I HAVE TO IMPLEMENT RASTER TYPE HANDLING!!!!
                except: # point is out of raster extent
                    attr = None
                attrs += [attr]
                previousRastLayer = rastLayer
                previousRastSample = rastSample
        outFeat.initAttributes(len(attrs))
        outFeat.setAttributes(attrs)
        memLayer.dataProvider().addFeature(outFeat)

    # write the memlayer to the output file
    so=QgsVectorFileWriter.SaveVectorOptions()
    so.fileEncoding = 'UTF-8'
    if outPath.upper().endswith('SHP'):
        so.driverName = "ESRI Shapefile"
    elif outPath.upper().endswith('CSV'):
        so.driverName = "CSV"
    else:
        so.driverName = "GPKG"
        if tableName:
            so.actionOnExistingFile = QgsVectorFileWriter.CreateOrOverwriteLayer
            so.layerName = tableName
    result, errMsg = QgsVectorFileWriter.writeAsVectorFormat(memLayer, outPath, so)
    if result:
     QMessageBox.critical(self, self.tr("Point sampling tool"), errMsg)
     return False
    else:
     del memLayer
     self.statusLabel.setText(self.tr("The new layer has been created."))
     return True
Ejemplo n.º 30
0
    def _add_extrafields(self, request, filepath, filename):
        """
        Add extra fields to layer properties if sbp parameters are in http query parameters.
        """

        # check for fields data in GET OR POST
        if request.method == 'POST':
            request_data = request.data
        else:
            request_data = request.query_params

        if 'sbp_qgs_layer_id' in request_data and 'sbp_fid' in request_data:

            try:
                vlayer = QgsVectorLayer(filepath+'.shp', filename, "ogr")

                if not vlayer:
                    raise Exception(f'Failed to load layer {filepath}')

                # Try to add the layer feature of SearchByPolygon widget
                sbp_layer = get_qgis_layer(
                    self.layer.project.layer_set.filter(qgs_layer_id=request_data['sbp_qgs_layer_id'])[0])
                sbp_feature = sbp_layer.getFeature(
                    int(request_data['sbp_fid']))

                original_attributes_count = len(vlayer.fields())

                assert vlayer.startEditing()

                # Add prefix to field name to avoid repeated names
                # Use 'p' as polygon
                prefix = 'p_'
                for f in sbp_feature.fields():

                    f.setName(prefix + f.name())
                    vlayer.addAttribute(f)

                # Save attributes
                if not vlayer.commitChanges():

                    # OGR returns an error if fields were renamed (for example when they are too long)
                    # ignore the error in that case
                    if 'ERROR: field with index' in str(vlayer.commitErrors()):
                        vlayer.commitChanges()
                    else:
                        err_msg = f'Commit error for layer {filepath}'
                        # Check for commit errors
                        errs = vlayer.commitErrors()
                        if len(errs) > 0:
                            errs_msg = ', '.join(errs)
                            err_msg = err_msg + f': {errs_msg}'

                        raise Exception(err_msg)

                # Now add new attribute values
                assert vlayer.startEditing()

                # Add values to new fields
                features = [f for f in vlayer.getFeatures()]
                for feature in features:
                    added_fields = {}
                    field_index = original_attributes_count
                    for f in sbp_feature.fields():
                        added_fields.update(
                            {field_index: sbp_feature[f.name()]})
                        field_index += 1
                    vlayer.changeAttributeValues(feature.id(), added_fields)

                # Commit new fields and exit from editing
                if not vlayer.commitChanges():

                    err_msg = f'Commit error for layer {filepath}'
                    # Check for commit errors
                    errs = vlayer.commitErrors()
                    if len(errs) > 0:
                        errs_msg = ', '.join(errs)
                        err_msg = err_msg + f': {errs_msg}'

            except Exception as e:
                logger.error(e)
Ejemplo n.º 31
0
 def on_click_Inici(self):
     global lbl_Cost
     global data
     global listFields
     global urlToLoad
     global TEMPORARY_PATH
 
     self.dlg.setEnabled(False)
     '''Tratamiento de errores'''
     llistaErrors = self.controlErrorsInput()
     if len(llistaErrors) > 0:
         llista = "Llista d'errors:\n\n"
         for i in range (0,len(llistaErrors)):
             llista += ("- "+llistaErrors[i] + '\n')
         QMessageBox.information(None, "Error", llista)
         self.dlg.setEnabled(True)
         return
     
     
     textBox = u'INICI DEL PROCÉS\n\n'
     self.dlg.text_info.setText(textBox)
     self.MouText()
     campNom = ''
     campGeometria = ''
     campCod = ''
     campSrc = ''
     campLat = ''
     campLng = ''
     
     
     '''Obtención de Nom y Geometria'''
     if self.dlg.radio_ws.isChecked():
         campNom,campGeometria,campLat, campLng, campCod,campSrc=self.searchNomGeomCodSrcInFile()
         urlToLoad=self.dlg.combo_ws.currentText()
         #if(urlToLoad[-4:]=='.csv'):
         error = self.loadCSV(campNom, campGeometria, campCod,True)
         if (error=="Error"):
             self.dlg.setEnabled(True)
             return
 
     else:
         campNom = self.dlg.combo_nom.currentText()
         campCod=self.dlg.combo_cod.currentText()
         campSrc=self.dlg.combo_src.currentText()   
         if self.dlg.radio_geom.isChecked():
             campGeometria = self.dlg.combo_geom.currentText()
         elif self.dlg.radio_latlng.isChecked():
             campLat=self.dlg.combo_lat.currentText()
             campLng=self.dlg.combo_lng.currentText()
     
     '''Creación vector layer'''
     self.dlg.progressBar.setValue(60)
     textBox += u'Generant capa vectorial...\n'
     self.dlg.text_info.setText(textBox)
     self.MouText()
     if campGeometria != '':
         file = 'file:///'+TEMPORARY_PATH+'/WS.csv?encoding=%s&delimiter=%s&wktField=%s&crs=%s' % (campCod,",", campGeometria,campSrc)
     elif campLat != '' and campLng != '':
         file = 'file:///'+TEMPORARY_PATH+'/WS.csv?encoding=%s&delimiter=%s&xField=%s&yField=%s&crs=%s' % (campCod,",", campLng, campLat,campSrc)
     else:
         file = 'file:///'+TEMPORARY_PATH+'/WS.csv?encoding=%s&delimiter=%s' % (campCod,",")  
     vlayergeom = QgsVectorLayer(file, self.dlg.txt_nomTaula.text(),'delimitedtext')
     try:
         vlayergeom = self.comprobarValidez(vlayergeom) #Sirve tanto para comprobar la corrección del CSV como para pasar el layer a memoria
     except Exception as ex:
         missatge="La geometria seleccionada no és correcte"
         print (missatge)
         template = "An exception of type {0} occurred. Arguments:\n{1!r}"
         message = template.format(type(ex).__name__, ex.args)
         print (message)
         QMessageBox.information(None, "Error", missatge)
         self.dlg.text_info.setText('')
         self.dlg.progressBar.setValue(0)
         self.dlg.setEnabled(True)
         return "Error"
     vlayergeom.setName(self.dlg.txt_nomTaula.text())
            
     self.dlg.progressBar.setValue(80)
     textBox += u'Adaptant camps...\n'
     self.dlg.text_info.setText(textBox)
     self.MouText()
     
     '''Se renombra el campo de nombre y se añade un id'''
     vlayergeom.startEditing()
     fields = vlayergeom.fields()
     for x in range(len(fields)):
         if(campNom in fields[x].displayName()):
             vlayergeom.renameAttribute(x,'Nom')
             break;
     vlayergeom.addAttribute(QgsField('id', QVariant.Int))
     vlayergeom.commitChanges()
     
     '''Se autonumera el id'''
     features = vlayergeom.getFeatures()
     vlayergeom.startEditing()
     x=1
     for feature in features:
         vlayergeom.changeAttributeValue(feature.id(),self.getIndexOfField(vlayergeom,"id"),x)
         x=x+1
     vlayergeom.commitChanges()
        
     
     '''Se borran los campos no seleccionados''' 
     if not self.dlg.radio_ws.isChecked():
         llista_sel=[]    
         if (len(self.dlg.ListaCamps.selectedItems())>0):
             for item in self.dlg.ListaCamps.selectedItems():
                 llista_sel.append(item.text())
         
         vlayergeom.startEditing()
         for elem in listFields:
             if elem not in llista_sel:
                 vlayergeom.deleteAttribute(self.getIndexOfField(vlayergeom,elem))
         
         vlayergeom.commitChanges()
    
    
     '''Se representa en pantalla'''
     QgsProject.instance().addMapLayer(vlayergeom,False)
     root = QgsProject.instance().layerTreeRoot()
     myLayerNode=QgsLayerTreeLayer(vlayergeom)
     root.insertChildNode(0,myLayerNode)
     myLayerNode.setCustomProperty("showFeatureCount", True)
     
     
     if self.dlg.checkBox_save.isChecked():
         this_folder = os.path.dirname(os.path.abspath(__file__))   
         '''UPDATE'''
         file = open(this_folder+'/default_ws.txt') 
         cont=0
         strToWrite = ''
         for line in file:
             if (line.split('=',1)[1].replace('\n','')==self.dlg.txt_url.text()):
                 cont+=1
                 strToWrite+= line
             elif (cont==1):
                 cont+=1
                 strToWrite+= 'nom='+campNom+'\n'
             elif (cont==2):
                 cont+=1
                 if self.dlg.radio_geom.isChecked():
                     strToWrite+= 'geom='+campGeometria+'\n'
                 else:
                     strToWrite+='geom=\n'
             elif (cont==3):
                 cont+=1
                 if self.dlg.radio_latlng.isChecked():
                     strToWrite+= 'lat='+campLat+'\n'
                 else:
                     strToWrite+='lat=\n'
             elif (cont==4):
                 cont+=1
                 if self.dlg.radio_latlng.isChecked():
                     strToWrite+= 'lng='+campLng+'\n'
                 else:
                     strToWrite+='lng=\n'
             elif (cont==5):
                 cont+=1
                 strToWrite+= 'cod='+campCod+'\n'
             elif (cont==6):
                 cont+=1
                 strToWrite+= 'src='+campSrc+'\n'
             else:
                 strToWrite+=line
         file.close()
         file = open(this_folder+'/default_ws.txt', "w")
         file.write(strToWrite)
         file.close()    
         
         '''APEND'''
         if cont == 0:
             strToAppend = '\nurl='+self.dlg.txt_url.text()
             strToAppend += '\nnom='+campNom
             if self.dlg.radio_geom.isChecked():
                 strToAppend += '\ngeo='+campGeometria
             else:
                 strToAppend += '\ngeo='
             if self.dlg.radio_latlng.isChecked():
                 strToAppend += '\nlat='+campLat
                 strToAppend += '\nlng='+campLng
             else:
                 strToAppend += '\nlat='
                 strToAppend += '\nlng='
             strToAppend += '\ncod='+campCod
             strToAppend += '\nsrc='+campSrc
             file = open(this_folder+'/default_ws.txt', "a")
             file.write(strToAppend)
             file.close()
         
         
         self.file2Combo("default_ws.txt", self.dlg.combo_ws, 'Selecciona una opció')
         
     
     self.dlg.progressBar.setValue(100)
     textBox += u'\nProcés finalitzat.\n'
     self.dlg.text_info.setText(textBox)
     self.MouText()
     self.dlg.setEnabled(True)
Ejemplo n.º 32
0
def generate_od_routes(
    network_layer: QgsVectorLayer,
    origin_layer: QgsVectorLayer,
    poi_layer: QgsVectorLayer,
    size_field: str,
    class_field: str,
    work_layer: QgsVectorLayer = None,
    work_size_field: str = None,
    school_layer: QgsVectorLayer = None,
    school_size_field: str = None,
    origin_weight_field: str = None,
    socio_data=None,
    health_data=None,
    diversity_data=None,
    join_on: str = None,
    max_distance: int = 25000,
    return_layer: bool = True,
    return_raw: bool = False,
    feedback: QgsProcessingFeedback = None,
) -> QgsVectorLayer:
    """
    Shortest path algorithm based on Dijkstra's algorithm

    :param network_layer: road network
    :param points_layer: combined from to points
    :param relations_data: tabular from to id data
    :param origin_field: name of from field
    :param destination_field: name of to field
    :param max_distance: maximum distance/cost
    :param crs: output layer crs
    """

    if not network_layer.wkbType() & QgsWkbTypes.LineString:
        raise Exception('Network layer must be of type LineString')
    crs = network_layer.crs()

    ## prepare graph
    director = QgsVectorLayerDirector(
        source=network_layer,
        directionFieldId=-1,
        directDirectionValue='',
        reverseDirectionValue='',
        bothDirectionValue='',
        defaultDirection=QgsVectorLayerDirector.DirectionBoth,
    )
    # First strategy is for actual shortest distance calculation
    director.addStrategy(QgsNetworkDistanceStrategy())  # 0
    # Second strategy is a hack to be able to recover the edge id
    director.addStrategy(SaveFidStrategy())  # 1
    builder = QgsGraphBuilder(crs)

    ## spatial index

    poi_sidx = QgsSpatialIndex(poi_layer)
    work_sidx = QgsSpatialIndex(work_layer)
    school_sidx = QgsSpatialIndex(school_layer)

    ## prepare points
    orig_n = len(origin_layer)
    poi_n = len(poi_layer)
    work_n = len(work_layer) if work_layer else 0
    school_n = len(school_layer) if school_layer else 0
    dest_n = poi_n + work_n + school_n

    orig_points = [None] * orig_n
    orig_sizes = np.zeros(orig_n, dtype=float)
    if socio_data:
        orig_socio = np.zeros(orig_n, dtype=float)
    dest_points = [None] * dest_n
    dest_sizes = [None] * dest_n
    dest_fids = [None] * dest_n
    dest_cats = [None] * dest_n

    orig_id_field = 'deso'
    for i, feat in enumerate(origin_layer.getFeatures()):
        orig_points[i] = feat.geometry().asPoint()
        orig_sizes[i] = feat[size_field] * (
            feat[origin_weight_field] if origin_weight_field else 1
        )

        if socio_data:
            orig_socio[i] = socio_data[
                feat[orig_id_field]
            ]  # FIXME: check if all origins have data

    if socio_data:
        orig_socio = orig_socio / np.mean(orig_socio)
        orig_sizes *= orig_socio

    for i, feat in enumerate(poi_layer.getFeatures()):
        dest_points[i] = feat.geometry().asPoint()
        dest_fids[i] = feat.id()
        dest_sizes[i] = 1  # TODO: dest size
        dest_cats[i] = poi_class_map.get(feat[class_field])

    if work_layer:
        for i, feat in enumerate(work_layer.getFeatures(), start=poi_n):
            dest_points[i] = feat.geometry().asPoint()
            dest_fids[i] = feat.id()
            dest_sizes[i] = feat[work_size_field]  # TODO: dest size
            dest_cats[i] = 'work'

    if school_layer:
        for i, feat in enumerate(school_layer.getFeatures(), start=(poi_n + work_n)):
            dest_points[i] = feat.geometry().asPoint()
            dest_fids[i] = feat.id()
            dest_sizes[i] = feat[school_size_field]  # TODO: dest size
            dest_cats[i] = 'school'

    # points = [origin.point for origin in origins_data] + [
    #    dest.point for dest in dests_data
    # ]

    if feedback is None:
        feedback = QgsProcessingFeedback()

        def progress(p):
            if int(10 * p % 100) == 0:
                print(f'{int(p):#3d}%')

        feedback.progressChanged.connect(progress)

    with timing('build network graph'):
        tied_points = director.makeGraph(
            builder, orig_points + dest_points, feedback=feedback
        )
        graph = builder.graph()

    orig_tied_points = tied_points[:orig_n]
    dest_tied_points = tied_points[orig_n:]

    poi_tied_points = dest_tied_points[:poi_n]
    work_tied_points = dest_tied_points[poi_n : poi_n + work_n]
    school_tied_points = dest_tied_points[poi_n + work_n :]

    dest_fid_to_tied_points = dict(zip(dest_fids, enumerate(dest_tied_points)))

    poi_fid_to_tied_points = dict(zip(dest_fids[:poi_n], enumerate(poi_tied_points)))
    work_fid_to_tied_points = dict(
        zip(dest_fids[poi_n : poi_n + work_n], enumerate(work_tied_points, start=poi_n))
    )
    school_fid_to_tied_points = dict(
        zip(
            dest_fids[poi_n + work_n :],
            enumerate(school_tied_points, start=poi_n + work_n),
        )
    )

    orig_dests = [None] * orig_n
    for i, point in enumerate(orig_points):
        orig_dests[i] = (
            [
                poi_fid_to_tied_points[fid]
                for fid in poi_sidx.nearestNeighbor(
                    point, neighbors=MAX_NEIGHBORS, maxDistance=max_distance
                )
            ]
            + [
                work_fid_to_tied_points[fid]
                for fid in work_sidx.nearestNeighbor(
                    point, neighbors=MAX_NEIGHBORS, maxDistance=max_distance
                )
            ]
            + [
                school_fid_to_tied_points[fid]
                for fid in school_sidx.nearestNeighbor(
                    point, neighbors=MAX_NEIGHBORS, maxDistance=max_distance
                )
            ]
        )

    step = 100.0 / orig_n
    time_dijkstra = 0.0
    time_find = 0.0
    time_route = 0.0
    with timing('calculate connecting routes'):
        routes = []
        # for i, (origin_fid, dest_fids) in enumerate(od_data):
        for i, (orig_point, dests) in enumerate(zip(orig_tied_points, orig_dests)):
            origin_vertex_id = graph.findVertex(orig_point)

            # Calculate the tree and cost using the distance strategy (#0)
            ts = time()
            (tree, cost) = QgsGraphAnalyzer.dijkstra(graph, origin_vertex_id, 0)
            time_dijkstra += time() - ts

            for j, dest_point in dests:
                if feedback.isCanceled():
                    return
                if dest_sizes[j] <= 0:
                    continue
                category = dest_cats[j]
                if category is None:
                    continue
                ts = time()
                dest_vertex_id = graph.findVertex(dest_point)
                time_find += time() - ts
                if tree[dest_vertex_id] != -1 and (
                    cost[dest_vertex_id] <= MAX_DISTANCE_M
                    or MAX_DISTANCE_M <= 0  # TODO: enable skipping max distance
                ):
                    route_distance = cost[dest_vertex_id]
                    # route_points = [graph.vertex(dest_vertex_id).point()]
                    cur_vertex_id = dest_vertex_id
                    route_fids = []
                    # Iterate the graph from dest to origin saving the edges
                    ts = time()
                    while cur_vertex_id != origin_vertex_id:
                        cur_edge = graph.edge(tree[cur_vertex_id])
                        # Here we recover the edge id through strategy #1
                        route_fids.append(cur_edge.cost(1))
                        cur_vertex_id = cur_edge.fromVertex()
                        # route_points.append(graph.vertex(cur_vertex_id).point())
                    time_route += time() - ts

                    # route_points.reverse()
                    # route_geom = QgsGeometry.fromPolylineXY(route_points))

                    # Hack to remove duplicate fids
                    route_fids = list(
                        dict.fromkeys(route_fids)
                    )  # NOTE: requires python >= 3.7 for ordered dict FIXME: add python version check
                    route_fids.reverse()

                    # Calc
                    # TODO: Move to matrix and vectorize calculation using numpy
                    gravity_value = poi_gravity_values[category]
                    bike_params = mode_params_bike[category]
                    ebike_params = mode_params_ebike[category]

                    # NOTE: we include dest size in decay here
                    decay = dest_sizes[j] * math.exp(
                        gravity_value * route_distance / 1000.0
                    )
                    p_bike = sigmoid(*bike_params, route_distance)
                    p_ebike = sigmoid(*ebike_params, route_distance)

                    # TODO: use namedtuple or dataclass
                    routes.append(
                        Route(
                            i,
                            j,
                            category,
                            route_distance,
                            decay,
                            p_bike,
                            p_ebike,
                            route_fids,
                        )
                    )
            feedback.setProgress(i * step)

        print(f'dijkstra took: {time_dijkstra:#1.2f} sec')
        print(f'find vertex took: {time_find:#1.2f} sec')
        print(f'route took: {time_route:#1.2f} sec')

    with timing('post process routes'):
        alpha_bike = 0.8
        alpha_ebke = 0.2

        decay_sums = {cat: defaultdict(float) for cat in poi_categories}
        bike_values = {cat: defaultdict(float) for cat in poi_categories}
        ebike_values = {cat: defaultdict(float) for cat in poi_categories}

        for route in routes:
            # NOTE: dest size is included in decay
            decay_sums[route.cat][route.i] += route.decay
        for route in routes:
            decay_sum = decay_sums[route.cat][route.i]
            # TODO: add T_p and alpha_m
            T_p = trip_generation[route.cat]
            bike_value = (
                T_p
                * alpha_bike
                * orig_sizes[route.i]
                * route.p_bike
                * route.decay
                / decay_sum
            )
            ebike_value = (
                T_p
                * alpha_ebke
                * orig_sizes[route.i]
                * route.p_ebike
                * route.decay
                / decay_sum
            )
            for fid in route.net_fids:
                bike_values[route.cat][fid] += float(bike_value)
                ebike_values[route.cat][fid] += float(ebike_value)

    # FIXME: Un-kludge this
    with timing('create result features'):
        fields = get_fields()

        segments = []
        for feature in network_layer.getFeatures():
            fid = feature.id()
            segment = QgsFeature(fields)
            segment.setGeometry(QgsGeometry(feature.geometry()))

            segment['network_fid'] = fid
            flow = 0.0
            for cat in poi_categories:
                bike_field = f'{cat}_bike_value'
                ebike_field = f'{cat}_ebike_value'

                flow_bike = segment[bike_field] = bike_values[cat].get(fid)
                flow_ebke = segment[ebike_field] = ebike_values[cat].get(fid)

                if flow_bike is not None:
                    flow += flow_bike
                if flow_ebke is not None:
                    flow += flow_ebke

            segment['flow'] = flow
            segment['lts'] = feature['lts']
            segment['vgu'] = feature['vgu']
            segment['R'] = flow * feature['ratio']
            segments.append(segment)

    if not return_layer:
        if return_raw:
            return segments, bike_values, ebike_values
        return segments

    with timing('create result layer'):
        output_layer = QgsVectorLayer(
            f'LineString?crs={crs.toWkt()}', 'segments', 'memory'
        )
        with edit(output_layer):
            for field in fields:
                output_layer.addAttribute(field)
            output_layer.addFeatures(segments, flags=QgsFeatureSink.FastInsert)

    return output_layer
Ejemplo n.º 33
0
class AutoFieldsTests( unittest.TestCase ):

    @classmethod
    def setUpClass( self ):
        self.msg = MessageManager( 'debug', None ) 
        self.msg.show( "Info! SetUp started", 'info', True )
        #Initialize QGIS app
        app = QgsApplication([], True)
        QgsApplication.setPrefixPath("/usr", True)
        QgsApplication.initQgis()
        
        #Configure QSettings (organization and application name)
        self.settings = QSettings("GeoTux", "QGIS-Plugin-Test") 

        #Load layer, add field f1, and add layer to Registry
        baseDir = os.path.dirname( os.path.realpath( __file__ ) )
        self.layerPath = os.path.join( baseDir, 'test_data', 'test_points.shp' )
        self.layer = QgsVectorLayer( self.layerPath, 'puntos', 'ogr' )   
        self.layer.dataProvider().addAttributes([QgsField('f1', QVariant.Double)])
        self.layer.updateFields()
        QgsMapLayerRegistry.instance().addMapLayer( self.layer )  
        
        #Instantiate AutoFieldManager
        self.autoFieldManager = AutoFieldManager( self.msg, None, '/AutoFieldsTest', 'GeoTux', 'QGIS-Plugin-Test' )
        
            
    def readStoredSettings( self, layer, fieldName ):
        """ Helper function to get a dictionary of stored QSettings for an AutoField """
        dictTmpProperties = {}
        autoFieldId = self.autoFieldManager.buildAutoFieldId( layer, fieldName )
        self.settings.beginGroup('/AutoFieldsTest/data/' + autoFieldId)
        dictTmpProperties['layer'] = self.settings.value( "layer", "", type=str )
        dictTmpProperties['field'] = self.settings.value( "field", u"", type=unicode )
        dictTmpProperties['expression'] = self.settings.value( "expression", u"", type=unicode )
        dictTmpProperties['layer2'] = self.settings.value( "layer2", "", type=str )
        dictTmpProperties['field2'] = self.settings.value( "field2", "", type=str )            
        dictTmpProperties['enabled'] = self.settings.value( "enabled", False, type=bool )
        self.settings.endGroup()
                
        return dictTmpProperties

    def test01CreateEnabledAutoField( self ):
        """ QSettings should be properly stored, AutoField should be enabled """
        self.msg.show( "Info! Test 1 started", 'info', True )

        self.autoFieldManager.createAutoField(
            layer=self.layer, 
            fieldName=u'f1', 
            expression=u'$x'
        )

        dictTmpProperties = self.readStoredSettings( self.layer, u'f1' )      
        dictExpectedProperties = {
            'layer':self.layerPath,
            'field':u'f1',
            'expression':u'$x',
            'layer2':"",
            'field2':"",
            'enabled':True
        }
        
        self.assertEqual( dictTmpProperties, dictExpectedProperties )
        
        
    def test02AvoidTwoAutoFieldsOnSameField( self ):
        """ AutoField should not be created if another one already exists on the same field."""
        self.msg.show( "Info! Test 2 started", 'info', True )

        res = self.autoFieldManager.createAutoField(
            layer=self.layer, 
            fieldName=u'f1', 
            expression=u'$y'
        )
        
        self.assertFalse( res )
        
        
    def test03EditAutoFieldLayer( self ):
        """ AutoField value should be updated if a feature is added.
            Note: It cannot handle the case when writing directly to the provider,
              as QGIS doesn't have a SIGNAL for that.
              self.layer.dataProvider().addFeatures( [ tmpFeature ] )        
         """
        self.msg.show( "Info! Test 3 started", 'info', True )

        tmpFeature = QgsFeature( self.layer.pendingFields() )
        tmpFeature.setGeometry( QgsGeometry.fromPoint( QgsPoint(-74.4, 4.5) ) )

        # Either 1:
        self.layer.startEditing()
        self.layer.addFeature( tmpFeature )
        self.layer.commitChanges()
        
        # Or 2:
        #with edit( self.layer ):
        #    self.layer.addFeature( tmpFeature )
            
        addedFeature = self.layer.getFeatures().next()
        self.assertEquals( addedFeature['f1'], -74.4 )


    def test04ChangeAttributeValue( self ):
        """ AutoField value should be updated if another AutoField value is changed """
        self.msg.show( "Info! Test 4 started", 'info', True )

        self.autoFieldManager.createAutoField(
            layer=self.layer, 
            fieldName=u'modified', 
            expression=u'\'now: \' + to_string("f1")'
        )

        self.layer.startEditing()
        self.layer.changeAttributeValue( 0, self.layer.fieldNameIndex( u'id' ), 1 )
        self.layer.commitChanges()
            
        feature = self.layer.getFeatures().next()
        self.assertEquals( feature['modified'], 'now: -74.4' )

    
    def test05FieldRemovedThenDisableAutoField( self ):
        """ AutoField should be disabled if its base field is removed """
        self.msg.show( "Info! Test 5 started", 'info', True )

        fieldIndex = self.layer.fieldNameIndex( u'f1' )
        self.layer.startEditing()
        self.layer.deleteAttribute( fieldIndex )
        self.layer.commitChanges()
        dictTmpProperties = self.readStoredSettings( self.layer, u'f1' )    
        
        self.assertFalse( dictTmpProperties['enabled'] )        
            

    def test06MissingFieldAddedThenEnableAutoField( self ):
        """ AutoField should be enabled if missing field is added """
        self.msg.show( "Info! Test 6 started", 'info', True )    

        self.layer.startEditing()
        self.layer.addAttribute( QgsField( 'f1', QVariant.Double, len=10, prec=2 ) )
        self.layer.commitChanges()
        
        dictTmpProperties = self.readStoredSettings( self.layer, u'f1' )    
        
        self.assertTrue( dictTmpProperties['enabled'] )   

        
    def test07LayerRemovedThenDisableAutoField( self ):
        """ AutoField should be disabled if its base layer is removed """
        self.msg.show( "Info! Test 7 started", 'info', True )

        QgsMapLayerRegistry.instance().removeMapLayer( self.layer.id() )

        # removeMapLayer deletes the underlying object, so create it again
        self.layer = QgsVectorLayer( self.layerPath, 'puntos', 'ogr' )   
        dictTmpProperties = self.readStoredSettings( self.layer, u'f1' )    
        
        self.assertFalse( dictTmpProperties['enabled'] )
        
     
    def test08MissingLayerAddedThenEnableAutoField( self ):
        """ AutoField should be enabled if missing layer is added """
        self.msg.show( "Info! Test 8 started", 'info', True )

        # test07 deletes the layer object, so create it again
        self.layer = QgsVectorLayer( self.layerPath, 'puntos', 'ogr' )
        QgsMapLayerRegistry.instance().addMapLayer( self.layer )  
        dictTmpProperties = self.readStoredSettings( self.layer, u'f1' )    
        
        self.assertTrue( dictTmpProperties['enabled'] )
           
        
    def test09RemoveAutoField( self ):
        """ QSettings should be deleted for the removed AutoField """
        self.msg.show( "Info! Test 9 started", 'info', True )

        # test07 deletes the layer object, so create it again
        self.layer = QgsVectorLayer( self.layerPath, 'puntos', 'ogr' )
        autoFieldId = self.autoFieldManager.buildAutoFieldId( self.layer, u'f1')
        self.autoFieldManager.removeAutoField( autoFieldId )
        dictTmpProperties = self.readStoredSettings( self.layer, u'f1' ) 
        
        self.assertEqual( dictTmpProperties, {'layer':"",'field':"",'expression':"",'layer2':"",'field2':"",'enabled':False} )
        

    @classmethod    
    def tearDownClass( self ):   
        self.msg.show( "Info! TearDown started", 'info', True )
    
        # test07 deletes the layer object, so create it again
        self.layer = QgsVectorLayer( self.layerPath, 'puntos', 'ogr' )

        #Remove AutoField modified
        autoFieldId = self.autoFieldManager.buildAutoFieldId( self.layer, u'modified' )
        self.autoFieldManager.removeAutoField( autoFieldId )

        #Delete field f1
        fieldIndex = self.layer.fieldNameIndex('f1')
        self.layer.dataProvider().deleteAttributes( [fieldIndex] )
        self.layer.updateFields()
        
        #Delete features from test layer
        fIds = self.layer.allFeatureIds()
        self.layer.dataProvider().deleteFeatures( fIds )
        
        #Remove layer from Registry
        QgsMapLayerRegistry.instance().removeMapLayer( self.layer.id() )
        self.msg.show( "Info! TearDown finished", 'info', True )

        QgsApplication.exitQgis()
Ejemplo n.º 34
0
class mesh_canvas(QgsMapCanvas):
    def __init__(self, iface, tile_name, tile_credit, tile_url, tile_zmin,
                 tile_zmax, tile_bbox):

        QgsMapCanvas.__init__(self)
        self.iface = iface
        self.setWheelAction(QgsMapCanvas.WheelZoom, 1)
        self.setDestinationCrs(
            self.iface.mapCanvas().mapSettings().destinationCrs())
        self.setCrsTransformEnabled(True)

        self.iface.mapCanvas().destinationCrsChanged.connect(self.onCrsChanged)
        self.iface.mapCanvas().extentsChanged.connect(self.onExtentsChanged)
        self.iface.mapCanvas().scaleChanged.connect(self.onScaleChanged)

        layerdef = TileLayerDefinition(tile_name,
                                       tile_credit,
                                       tile_url,
                                       zmin=tile_zmin,
                                       zmax=tile_zmax,
                                       bbox=tile_bbox)
        creditVisibility = True

        plugin = plugins.get("TileLayerPlugin")
        self.chirin_layer = TileLayer(plugin, layerdef, creditVisibility)
        QgsMapLayerRegistry.instance().addMapLayer(self.chirin_layer, False)

        self.meshPolyLayer = QgsVectorLayer("polygon?crs=postgis:4612",
                                            u"地域メッシュインデックス", "memory")

        renderer = self.meshPolyLayer.rendererV2()
        renderer.symbols()[0].symbolLayers()[0].setFillColor(
            QtGui.QColor(0, 0, 0, 0))
        renderer.symbols()[0].symbolLayers()[0].setBorderWidth(0.1)

        self.meshPolyLayer.label().setLabelField(0, 0)

        self.meshPolyLayer.startEditing()
        self.meshPolyLayer.addAttribute(
            QgsField("meshC", QtCore.QVariant.String))
        self.meshPolyLayer.commitChanges()

        QgsMapLayerRegistry.instance().addMapLayer(self.meshPolyLayer, False)

        main_crs = self.iface.mapCanvas().mapSettings().destinationCrs()
        self.Trs_laln = QgsCoordinateTransform(
            main_crs, QgsCoordinateReferenceSystem(4612))
        self.redraw_mesh()

        layers = []
        layers.append(QgsMapCanvasLayer(self.meshPolyLayer))
        layers.append(QgsMapCanvasLayer(self.chirin_layer))

        self.setLayerSet(layers)
        self.setExtent(self.iface.mapCanvas().extent())
        self.setWindowFlags(QtCore.Qt.WindowStaysOnTopHint)
        self.resize(self.iface.mapCanvas().size() / 2)

    def onCrsChanged(self):
        main_crs = self.iface.mapCanvas().mapSettings().destinationCrs()
        self.setDestinationCrs(main_crs)

    def onExtentsChanged(self):
        self.setExtent(self.iface.mapCanvas().extent())
        self.redraw_mesh()
        self.refresh()

    def onScaleChanged(self):
        self.resize(self.iface.mapCanvas().size() / 2)

    def PPopend(self):
        self.iface.mapCanvas().extentsChanged.disconnect()
        self.iface.mapCanvas().scaleChanged.disconnect()

    def res_mesh_index(self, latitude, longitude):
        x1d = math.floor(longitude - 100)
        x2d = math.floor((longitude - x1d - 100) * 8)
        x3d = math.floor((longitude - x1d - 100 - x2d / 8.0) * 80)
        y1d = math.floor(latitude * 1.5)
        y2d = math.floor((latitude * 1.5 - y1d) * 8)
        y3d = math.floor((latitude * 1.5 - y1d - y2d / 8.0) * 80)

        return (x1d, x2d, x3d, y1d, y2d, y3d)

    def res_extent_mesh(self):
        main_crs = self.iface.mapCanvas().mapSettings().destinationCrs()
        self.Trs_laln.setSourceCrs(main_crs)

        my_rect = self.iface.mapCanvas().extent()
        laln_rect = self.Trs_laln.transform(my_rect)

        x_min = laln_rect.xMinimum()
        x_max = laln_rect.xMaximum()
        y_min = laln_rect.yMinimum()
        y_max = laln_rect.yMaximum()

        Lx1d, Lx2d, Lx3d, Ly1d, Ly2d, Ly3d = self.res_mesh_index(y_min, x_min)
        Rx1d, Rx2d, Rx3d, Uy1d, Uy2d, Uy3d = self.res_mesh_index(y_max, x_max)
        x_range = x_max - x_min
        y_range = y_max - y_min

        return {
            "Lx1d": Lx1d,
            "Lx2d": Lx2d,
            "Lx3d": Lx3d,
            "Rx1d": Rx1d,
            "Rx2d": Rx2d,
            "Rx3d": Rx3d,
            "Ly1d": Ly1d,
            "Ly2d": Ly2d,
            "Ly3d": Ly3d,
            "Uy1d": Uy1d,
            "Uy2d": Uy2d,
            "Uy3d": Uy3d,
            "xRange": x_range,
            "yRange": y_range
        }

    def draw_m1d(self):
        x = self.e_mesh["Lx1d"] - 1
        while x <= self.e_mesh["Rx1d"] + 1:

            y = self.e_mesh["Ly1d"]
            while y <= self.e_mesh["Uy1d"]:

                f = QgsFeature(self.meshPolyLayer.pendingFields())
                f.setGeometry(
                    QgsGeometry.fromPolygon([[
                        QgsPoint(x + 100, y / 1.5),
                        QgsPoint(x + 100, (y + 1) / 1.5),
                        QgsPoint(x + 101, (y + 1) / 1.5),
                        QgsPoint(x + 101, y / 1.5)
                    ]]))

                m1d_str = str(int(y)) + str(int(x))

                f.setAttribute("meshC", m1d_str)
                self.meshPolyLayer.addFeature(f)
                y += 1

            x += 1

    def draw_m2d(self):
        x = self.e_mesh["Lx1d"] + self.e_mesh["Lx2d"] / 8.0 - 1 / 8.0
        while x <= self.e_mesh["Rx1d"] + self.e_mesh["Rx2d"] / 8.0 + 1 / 8.0:

            x1d = math.floor(x)
            x2d = math.floor((x - x1d) * 8)

            y = self.e_mesh["Ly1d"] + self.e_mesh["Ly2d"] / 8.0 - 1 / 8.0
            while y <= self.e_mesh["Uy1d"] + self.e_mesh["Uy2d"] + 1 / 8.0:

                y1d = math.floor(y)
                y2d = math.floor((y - y1d) * 8)

                f = QgsFeature(self.meshPolyLayer.pendingFields())
                f.setGeometry(
                    QgsGeometry.fromPolygon([[
                        QgsPoint(x + 100, y / 1.5),
                        QgsPoint(x + 100, (y + 1 / 8.0) / 1.5),
                        QgsPoint(x + 100 + 1 / 8.0, (y + 1 / 8.0) / 1.5),
                        QgsPoint(x + 100 + 1 / 8.0, y / 1.5)
                    ]]))

                m1d_str = str(int(y1d)) + str(int(x1d))
                m2d_str = str(int(y2d)) + str(int(x2d))
                mesh_str = m1d_str + m2d_str

                f.setAttribute("meshC", mesh_str)
                self.meshPolyLayer.addFeature(f)

                y += 1 / 8.0

            x += 1 / 8.0

    def draw_m3d(self):
        x = self.e_mesh["Lx1d"] + self.e_mesh["Lx2d"] / 8.0 + self.e_mesh[
            "Lx3d"] / 80.0 - 1 / 80.0
        while x <= self.e_mesh["Rx1d"] + self.e_mesh[
                "Rx2d"] / 8.0 + self.e_mesh["Rx3d"] / 80.0 + 1 / 80.0:

            x1d = math.floor(x)
            x2d = math.floor((x - x1d) * 8)
            x3d = math.floor((x - x1d - x2d / 8.0) * 80)

            y = self.e_mesh["Ly1d"] + self.e_mesh["Ly2d"] / 8.0 + self.e_mesh[
                "Ly3d"] / 80.0 - 1 / 80.0
            while y <= self.e_mesh["Uy1d"] + self.e_mesh[
                    "Uy2d"] / 8.0 + self.e_mesh["Uy3d"] / 80.0 + 1 / 80.0:

                y1d = math.floor(y)
                y2d = math.floor((y - y1d) * 8)
                y3d = math.floor((y - y1d - y2d / 8.0) * 80)

                f = QgsFeature(self.meshPolyLayer.pendingFields())
                f.setGeometry(
                    QgsGeometry.fromPolygon([[
                        QgsPoint(x + 100, y / 1.5),
                        QgsPoint(x + 100, (y + 1 / 80.0) / 1.5),
                        QgsPoint(x + 100 + 1 / 80.0, (y + 1 / 80.0) / 1.5),
                        QgsPoint(x + 100 + 1 / 80.0, y / 1.5)
                    ]]))

                m1d_str = str(int(y1d)) + str(int(x1d))
                m2d_str = str(int(y2d)) + str(int(x2d))
                m3d_str = str(int(y3d)) + str(int(x3d))
                mesh_str = m1d_str + m2d_str + m3d_str

                f.setAttribute("meshC", mesh_str)
                self.meshPolyLayer.addFeature(f)

                y += 1 / 80.0

            x += 1 / 80.0

    def draw_m5x(self):
        x = self.e_mesh["Lx1d"] - 1
        while x <= self.e_mesh["Rx1d"] + 1:

            x1d = math.floor(x)
            x2d = math.floor((x - x1d) * 8)
            x5x = math.floor((x - x1d - x2d / 8.0) * 16)

            y = self.e_mesh["Ly1d"] - 1
            while y <= self.e_mesh["Uy1d"] + 1:

                y1d = math.floor(y)
                y2d = math.floor((y - y1d) * 8)
                y5x = math.floor((y - y1d - y2d / 8.0) * 16)

                f = QgsFeature(self.meshPolyLayer.pendingFields())
                f.setGeometry(
                    QgsGeometry.fromPolygon([[
                        QgsPoint(x + 100, y / 1.5),
                        QgsPoint(x + 100, (y + 1 / 16.0) / 1.5),
                        QgsPoint(x + 100 + 1 / 16.0, (y + 1 / 16.0) / 1.5),
                        QgsPoint(x + 100 + 1 / 16.0, y / 1.5)
                    ]]))

                m1d_str = str(int(y1d)) + str(int(x1d))
                m2d_str = str(int(y2d)) + str(int(x2d))
                m5x_str = str(int(x5x + y5x * 2 + 1))
                mesh_str = m1d_str + "-" + m2d_str + "-" + m5x_str

                f.setAttribute("meshC", mesh_str)
                self.meshPolyLayer.addFeature(f)

                y += 1 / 16.0

            x += 1 / 16.0

    def redraw_mesh(self):

        self.e_mesh = self.res_extent_mesh()
        if self.e_mesh["xRange"] < 50:

            self.meshPolyLayer.startEditing()
            self.meshPolyLayer.selectAll()
            self.meshPolyLayer.deleteSelectedFeatures()

            if self.e_mesh["xRange"] > 2.0:
                self.draw_m1d()
            elif self.e_mesh["xRange"] > 1.0 / 8.0:
                self.draw_m2d()
            else:
                self.draw_m3d()

            self.meshPolyLayer.commitChanges()

            self.meshPolyLayer.enableLabels(self.e_mesh["xRange"] <= 8.0)

    def closeEvent(self, event):
        QgsMapLayerRegistry.instance().removeMapLayers(
            [self.meshPolyLayer.id(),
             self.chirin_layer.id()])
        self.iface.mapCanvas().destinationCrsChanged.disconnect()
        self.iface.mapCanvas().extentsChanged.disconnect()
        self.iface.mapCanvas().scaleChanged.disconnect()
Ejemplo n.º 35
0
class mesh_canvas(QgsMapCanvas):
    
    def __init__(self,iface,tile_name,tile_credit,tile_url,tile_zmin,tile_zmax,tile_bbox):
    
        QgsMapCanvas.__init__(self)
        self.iface = iface
        self.setWheelAction(QgsMapCanvas.WheelZoom,1)
        self.setDestinationCrs(self.iface.mapCanvas().mapSettings().destinationCrs())
        self.setCrsTransformEnabled(True)
        
        self.iface.mapCanvas().destinationCrsChanged.connect(self.onCrsChanged)
        self.iface.mapCanvas().extentsChanged.connect(self.onExtentsChanged)
        self.iface.mapCanvas().scaleChanged.connect(self.onScaleChanged)
        
        layerdef = TileLayerDefinition(tile_name,
                                       tile_credit,
                                       tile_url,
                                       zmin=tile_zmin,
                                       zmax=tile_zmax,
                                       bbox=tile_bbox)
        creditVisibility=True

        plugin = plugins.get("TileLayerPlugin")
        self.chirin_layer = TileLayer(plugin,layerdef, creditVisibility)
        QgsMapLayerRegistry.instance().addMapLayer(self.chirin_layer,False)
        
        self.meshPolyLayer = QgsVectorLayer("polygon?crs=postgis:4612",u"地域メッシュインデックス","memory")
        
        renderer = self.meshPolyLayer.rendererV2()
        renderer.symbols()[0].symbolLayers()[0].setFillColor(QtGui.QColor(0,0,0,0))
        renderer.symbols()[0].symbolLayers()[0].setBorderWidth(0.1)
        
        self.meshPolyLayer.label().setLabelField(0,0)
        
        self.meshPolyLayer.startEditing()
        self.meshPolyLayer.addAttribute(QgsField("meshC",QtCore.QVariant.String))
        self.meshPolyLayer.commitChanges()
        
        QgsMapLayerRegistry.instance().addMapLayer(self.meshPolyLayer,False)
        
        main_crs =  self.iface.mapCanvas().mapSettings().destinationCrs()
        self.Trs_laln = QgsCoordinateTransform(main_crs,QgsCoordinateReferenceSystem(4612))
        self.redraw_mesh()
             
        layers = []
        layers.append(QgsMapCanvasLayer(self.meshPolyLayer))
        layers.append(QgsMapCanvasLayer(self.chirin_layer))
        
        self.setLayerSet(layers)
        self.setExtent( self.iface.mapCanvas().extent() )
        self.setWindowFlags(QtCore.Qt.WindowStaysOnTopHint)
        self.resize(self.iface.mapCanvas().size()/2)
        
    def onCrsChanged(self):
        main_crs =  self.iface.mapCanvas().mapSettings().destinationCrs()
        self.setDestinationCrs(main_crs)

        
    def onExtentsChanged(self):
        self.setExtent( self.iface.mapCanvas().extent() )    
        self.redraw_mesh()
        self.refresh()
        
    def onScaleChanged(self):
        self.resize(self.iface.mapCanvas().size()/2)
        
    def PPopend(self):
        self.iface.mapCanvas().extentsChanged.disconnect()
        self.iface.mapCanvas().scaleChanged.disconnect()
        
    def res_mesh_index(self,latitude,longitude):
        x1d = math.floor(longitude - 100)
        x2d = math.floor((longitude - x1d - 100 ) * 8 )
        x3d = math.floor((longitude - x1d - 100 - x2d/8.0 )*80 )
        y1d = math.floor(latitude*1.5)
        y2d = math.floor((latitude*1.5 - y1d ) * 8 )
        y3d = math.floor((latitude*1.5 - y1d - y2d/8.0 )*80 ) 
        
        return (x1d,x2d,x3d,y1d,y2d,y3d)
        
    def res_extent_mesh(self):
        main_crs =  self.iface.mapCanvas().mapSettings().destinationCrs()
        self.Trs_laln.setSourceCrs(main_crs)
        
        my_rect = self.iface.mapCanvas().extent()        
        laln_rect = self.Trs_laln.transform(my_rect)        
        
        x_min = laln_rect.xMinimum()
        x_max = laln_rect.xMaximum()
        y_min = laln_rect.yMinimum()
        y_max = laln_rect.yMaximum()

        Lx1d,Lx2d,Lx3d,Ly1d,Ly2d,Ly3d = self.res_mesh_index(y_min, x_min)
        Rx1d,Rx2d,Rx3d,Uy1d,Uy2d,Uy3d = self.res_mesh_index(y_max, x_max)
        x_range = x_max - x_min
        y_range = y_max - y_min
        
        return {"Lx1d":Lx1d,"Lx2d":Lx2d,"Lx3d":Lx3d,
                "Rx1d":Rx1d,"Rx2d":Rx2d,"Rx3d":Rx3d,
                "Ly1d":Ly1d,"Ly2d":Ly2d,"Ly3d":Ly3d,
                "Uy1d":Uy1d,"Uy2d":Uy2d,"Uy3d":Uy3d,
                "xRange":x_range,"yRange":y_range}
        
    def draw_m1d(self):
        x = self.e_mesh["Lx1d"] -1
        while x <= self.e_mesh["Rx1d"] + 1:
                 
            y = self.e_mesh["Ly1d"] 
            while y <= self.e_mesh["Uy1d"]:
                
                f = QgsFeature(self.meshPolyLayer.pendingFields())
                f.setGeometry(QgsGeometry.fromPolygon(
                        [[QgsPoint(x+100,y/1.5),QgsPoint(x+100,(y+1)/1.5),
                        QgsPoint(x+101,(y+1)/1.5),QgsPoint(x+101,y/1.5)]]))
                
                m1d_str = str(int(y)) + str(int(x))
            
                f.setAttribute("meshC",m1d_str)
                self.meshPolyLayer.addFeature(f)
                y += 1
        
            x += 1
            
    def draw_m2d(self):
        x = self.e_mesh["Lx1d"] + self.e_mesh["Lx2d"] / 8.0 - 1 / 8.0      
        while x <= self.e_mesh["Rx1d"] + self.e_mesh["Rx2d"] / 8.0 + 1 / 8.0:
            
            x1d = math.floor(x)
            x2d = math.floor((x-x1d)*8)
                 
            y = self.e_mesh["Ly1d"] + self.e_mesh["Ly2d"] / 8.0 - 1 / 8.0 
            while y <= self.e_mesh["Uy1d"] + self.e_mesh["Uy2d"] + 1 / 8.0:
                
                y1d = math.floor(y)
                y2d = math.floor((y-y1d)*8)
                
                f = QgsFeature(self.meshPolyLayer.pendingFields())
                f.setGeometry(QgsGeometry.fromPolygon(
                        [[QgsPoint(x+100,y/1.5),QgsPoint(x+100,(y+1/8.0)/1.5),
                        QgsPoint(x+100+1/8.0,(y+1/8.0)/1.5),QgsPoint(x+100+1/8.0,y/1.5)]]))
                
                m1d_str = str(int(y1d)) + str(int(x1d))
                m2d_str = str(int(y2d)) + str(int(x2d))
                mesh_str = m1d_str + m2d_str
                    
                f.setAttribute("meshC",mesh_str)                                
                self.meshPolyLayer.addFeature(f)
                
                y += 1/8.0
                
            x += 1/8.0
  
    def draw_m3d(self):
        x = self.e_mesh["Lx1d"] + self.e_mesh["Lx2d"] / 8.0 + self.e_mesh["Lx3d"] / 80.0 - 1 / 80.0
        while x <= self.e_mesh["Rx1d"] + self.e_mesh["Rx2d"] / 8.0 + self.e_mesh["Rx3d"] / 80.0 + 1 / 80.0:
            
            x1d = math.floor(x)
            x2d = math.floor((x-x1d)*8)
            x3d = math.floor((x-x1d-x2d/8.0)*80)
                 
            y = self.e_mesh["Ly1d"] + self.e_mesh["Ly2d"] / 8.0 + self.e_mesh["Ly3d"] / 80.0 - 1 / 80.0
            while y <= self.e_mesh["Uy1d"] + self.e_mesh["Uy2d"] / 8.0 + self.e_mesh["Uy3d"] / 80.0 + 1 / 80.0:
                
                y1d = math.floor(y)
                y2d = math.floor((y-y1d)*8)
                y3d = math.floor((y-y1d-y2d/8.0)*80)
                
                f = QgsFeature(self.meshPolyLayer.pendingFields())
                f.setGeometry(QgsGeometry.fromPolygon(
                        [[QgsPoint(x+100,y/1.5),QgsPoint(x+100,(y+1/80.0)/1.5),
                        QgsPoint(x+100+1/80.0,(y+1/80.0)/1.5),QgsPoint(x+100+1/80.0,y/1.5)]]))
                
                m1d_str = str(int(y1d)) + str(int(x1d))
                m2d_str = str(int(y2d)) + str(int(x2d))
                m3d_str = str(int(y3d)) + str(int(x3d))
                mesh_str = m1d_str + m2d_str + m3d_str
                    
                f.setAttribute("meshC",mesh_str)                                
                self.meshPolyLayer.addFeature(f)
                
                y += 1/80.0
                
            x += 1/80.0              
    
                
                
    def draw_m5x(self):
        x = self.e_mesh["Lx1d"] - 1
        while x <= self.e_mesh["Rx1d"]+1:
            
            x1d = math.floor(x)
            x2d = math.floor((x-x1d)*8)
            x5x = math.floor((x-x1d-x2d/8.0)*16)
                 
            y = self.e_mesh["Ly1d"] - 1 
            while y <= self.e_mesh["Uy1d"]+1:
                
                y1d = math.floor(y)
                y2d = math.floor((y-y1d)*8)
                y5x = math.floor((y-y1d-y2d/8.0)*16)
                
                f = QgsFeature(self.meshPolyLayer.pendingFields())
                f.setGeometry(QgsGeometry.fromPolygon(
                        [[QgsPoint(x+100,y/1.5),QgsPoint(x+100,(y+1/16.0)/1.5),
                        QgsPoint(x+100+1/16.0,(y+1/16.0)/1.5),QgsPoint(x+100+1/16.0,y/1.5)]]))
                
                m1d_str = str(int(y1d)) + str(int(x1d))
                m2d_str = str(int(y2d)) + str(int(x2d))
                m5x_str = str(int(x5x+y5x*2+1))
                mesh_str = m1d_str + "-" + m2d_str + "-" + m5x_str
                    
                f.setAttribute("meshC",mesh_str)                                
                self.meshPolyLayer.addFeature(f)
                
                y += 1/16.0
                
            x += 1/16.0
            
        
    def redraw_mesh(self):
        
        self.e_mesh = self.res_extent_mesh()
        if self.e_mesh["xRange"] < 50:
        
            self.meshPolyLayer.startEditing()
            self.meshPolyLayer.selectAll()
            self.meshPolyLayer.deleteSelectedFeatures()

            if self.e_mesh["xRange"]  > 2.0:
                self.draw_m1d()
            elif self.e_mesh["xRange"] > 1.0/8.0:
                self.draw_m2d()
            else:
                self.draw_m3d()
        
            self.meshPolyLayer.commitChanges()
            
            self.meshPolyLayer.enableLabels(self.e_mesh["xRange"] <= 8.0)
        
    def closeEvent(self,event):
        QgsMapLayerRegistry.instance().removeMapLayers(
            [ self.meshPolyLayer.id(), self.chirin_layer.id() ])
        self.iface.mapCanvas().destinationCrsChanged.disconnect()
        self.iface.mapCanvas().extentsChanged.disconnect()
        self.iface.mapCanvas().scaleChanged.disconnect()
    def cloneToMemory(self):
        curlayer = self.iface.mapCanvas().currentLayer()
        selectedFeatCount = curlayer.selectedFeatureCount()
        geo = QgsWkbTypes.displayString(
            curlayer.wkbType())  # wkbType string name of geometry

        targetLayer = QgsVectorLayer(geo, self.dlg.lineEdit_2.text(), "memory")
        targetLayer.setCrs(curlayer.sourceCrs())
        QgsProject.instance().addMapLayer(targetLayer, False)
        root = QgsProject.instance().layerTreeRoot()

        self.setStyleLayer(targetLayer)

        if self.dlg.checkBoxAtrib.isChecked():  #copy attributes
            curlayer_attribute_list = curlayer.fields().toList()
            targetLayer_attribute_list = []
            targetLayerpr = targetLayer.dataProvider()

            for attrib in curlayer_attribute_list:
                if targetLayer.fields().lookupField(attrib.name()) == -1:
                    targetLayer_attribute_list.append(
                        QgsField(attrib.name(), attrib.type()))
            with edit(targetLayer):
                for attr in targetLayer_attribute_list:
                    if attr.type(
                    ) == 1:  # иначе игнорируется поле с типом 1 (bool)
                        attr = QgsField(
                            attr.name(),
                            QVariant.String)  # конвертируем bool в string
                    res_add = targetLayer.addAttribute(attr)
                    if not res_add:
                        print(u'Не создано поле {}'.format(attr.name()))
            targetLayer.updateFields()

        # for feat in curlayer.selectedFeatures(): # not work more
        #     targetLayer.dataProvider().addFeatures([feat]) # not work more

        # ИЗ МОДУЛЯ Apend Features To layer -----------------------------------------------
        # В старом варианте в QGIS3 при добавлении объектов с отличающимся набором аттрибутов
        # происходила задержка с выводом сообщений в логи. Что затягивало процесс.
        mapping = dict()
        for target_idx in targetLayer.fields().allAttributesList():
            target_field = targetLayer.fields().field(target_idx)
            source_idx = curlayer.fields().indexOf(target_field.name())
            if source_idx != -1:
                mapping[target_idx] = source_idx

        features = curlayer.selectedFeatures()
        destType = targetLayer.geometryType()
        destIsMulti = QgsWkbTypes.isMultiType(targetLayer.wkbType())
        new_features = []

        for current, in_feature in enumerate(features):
            attrs = {
                target_idx: in_feature[source_idx]
                for target_idx, source_idx in mapping.items()
            }
            geom = QgsGeometry()
            if in_feature.hasGeometry() and targetLayer.isSpatial():
                # Convert geometry to match destination layer
                # Adapted from QGIS qgisapp.cpp, pasteFromClipboard()
                geom = in_feature.geometry()
                if destType != QgsWkbTypes.UnknownGeometry:
                    newGeometry = geom.convertToType(destType, destIsMulti)
                    if newGeometry.isNull():
                        continue
                    geom = newGeometry
                # Avoid intersection if enabled in digitize settings
                geom.avoidIntersections(
                    QgsProject.instance().avoidIntersectionsLayers())

            new_feature = QgsVectorLayerUtils().createFeature(
                targetLayer, geom, attrs)
            new_features.append(new_feature)

        with edit(targetLayer):
            res = targetLayer.addFeatures(new_features)
        # ИЗ МОДУЛЯ Apend Features To layer -----------------------------------------------end

        root.insertLayer(0, targetLayer)
        self.iface.messageBar().clearWidgets()
        self.iface.setActiveLayer(targetLayer)
        curlayer.selectByIds([])

        if res:
            self.iface.messageBar().pushMessage(
                u"Выполнено",
                u"Склонировано {0}/{1} объектов".format(
                    len(new_features), selectedFeatCount),
                duration=5,
                level=0)
Ejemplo n.º 37
0
    def create_layer(self,
                     parameters,
                     name,
                     is_memory,
                     dest_crs,
                     layer_style=None):
        save_as = parameters.file_path
        file_format = parameters.file_format
        # save paramaters
        serialized = base64.b64encode(
            parameters.serialize(with_style=False, with_geometry=False))

        # save geometry
        layer = QgsVectorLayer("MultiPolygon?crs=%s" % dest_crs.authid(), name,
                               "memory")
        pr = layer.dataProvider()
        layer.startEditing()
        layer.addAttribute(QgsField("params", QVariant.String))
        fet1 = QgsFeature(0)
        fet1.setFields(layer.fields())
        fet1.setAttribute("params", str(serialized)[2:-1])
        fet1.setGeometry(parameters.geometry)
        pr.addFeatures([fet1])
        layer.commitChanges()

        # copy layer style
        if layer_style is not None:
            self.set_layer_style(layer, layer_style)

        if is_memory:
            return layer

        if os.path.isfile(save_as):
            # delete first if already exists
            if save_as.endswith(".shp"):
                QgsVectorFileWriter.deleteShapeFile(save_as)
            else:
                os.unlink(save_as)

        # create the disk layer
        QgsMessageLog.logMessage(
            "Mask saving '{}' as {}".format(save_as, file_format),
            "Extensions")
        error = QgsVectorFileWriter.writeAsVectorFormat(
            layer, save_as, "System", dest_crs, file_format)

        if error[0] == 0:
            QgsMessageLog.logMessage("Error = 0", "Extensions")
            nlayer = QgsVectorLayer(save_as, name, "ogr")
            if not nlayer.dataProvider().isValid():
                QgsMessageLog.logMessage("Invalid dataProvider", "Extensions")
                return None
            if not nlayer.isSpatial():
                QgsMessageLog.logMessage("No GeometryType", "Extensions")
                return None
            # force CRS
            nlayer.setCrs(dest_crs)

            # copy layer style
            layer_style = self.get_layer_style(layer)
            self.set_layer_style(nlayer, layer_style)
            return nlayer
        else:
            raise RuntimeError(error)

        return None
Ejemplo n.º 38
0
        def runTest(crs, primaryKey, attributeNames, attributeValues):
            self.assertTrue(crs.isValid())

            layer = QgsVectorLayer(f"Point?crs={crs.authid()}", "new_table",
                                   "memory")
            pr = layer.dataProvider()

            fields = [
                QgsField("fldid", QVariant.LongLong),
                QgsField("fldtxt", QVariant.String),
                QgsField("fldint", QVariant.Int)
            ]

            if primaryKey == "fldid":
                constraints = QgsFieldConstraints()
                constraints.setConstraint(
                    QgsFieldConstraints.ConstraintNotNull,
                    QgsFieldConstraints.ConstraintOriginProvider)
                constraints.setConstraint(
                    QgsFieldConstraints.ConstraintUnique,
                    QgsFieldConstraints.ConstraintOriginProvider)
                fields[0].setConstraints(constraints)

            layer.startEditing()
            for f in fields:
                layer.addAttribute(f)
            layer.commitChanges(True)

            f1 = QgsFeature()
            f1.setAttributes([1, "test", 11])
            f1.setGeometry(QgsGeometry.fromPointXY(QgsPointXY(1, 2)))
            f2 = QgsFeature()
            f2.setAttributes([2, "test2", 13])
            f3 = QgsFeature()
            f3.setAttributes([3, "test2", NULL])
            f3.setGeometry(QgsGeometry.fromPointXY(QgsPointXY(3, 2)))
            f4 = QgsFeature()
            f4.setAttributes([4, NULL, 13])
            f4.setGeometry(QgsGeometry.fromPointXY(QgsPointXY(4, 3)))
            pr.addFeatures([f1, f2, f3, f4])
            layer.commitChanges()

            QgsHanaProviderUtils.dropTableIfExists(self.conn, self.schemaName,
                                                   'import_data')
            uri = self.uri + f' key=\'{primaryKey}\' table="{self.schemaName}"."import_data" (geom) sql='
            error, message = QgsVectorLayerExporter.exportLayer(
                layer, uri, 'hana', crs)
            self.assertEqual(error, QgsVectorLayerExporter.NoError)

            import_layer = self.createVectorLayer(
                f'key=\'{primaryKey}\' table="{self.schemaName}"."import_data" (geom) sql=',
                'testimportedlayer')
            self.assertEqual(import_layer.wkbType(), QgsWkbTypes.Point)
            self.assertEqual([f.name() for f in import_layer.fields()],
                             attributeNames)

            features = [f.attributes() for f in import_layer.getFeatures()]
            self.assertEqual(features, attributeValues)
            geom = [f.geometry().asWkt() for f in import_layer.getFeatures()]
            self.assertEqual(geom,
                             ['Point (1 2)', '', 'Point (3 2)', 'Point (4 3)'])

            QgsHanaProviderUtils.dropTableIfExists(self.conn, self.schemaName,
                                                   'import_data')