Ejemplo n.º 1
0
    def testUpdatedFields(self):
        """Test when referenced layer update its fields
        https://issues.qgis.org/issues/20893
        """

        ml = QgsVectorLayer("Point?srid=EPSG:4326&field=a:int", "mem", "memory")
        self.assertEqual(ml.isValid(), True)
        QgsProject.instance().addMapLayer(ml)

        ml.startEditing()
        f1 = QgsFeature(ml.fields())
        f1.setGeometry(QgsGeometry.fromWkt('POINT(2 3)'))
        ml.addFeatures([f1])
        ml.commitChanges()

        vl = QgsVectorLayer("?query=select a, geometry from mem", "vl", "virtual")
        self.assertEqual(vl.isValid(), True)

        # add one more field
        ml.dataProvider().addAttributes([QgsField('newfield', QVariant.Int)])
        ml.updateFields()

        self.assertEqual(ml.featureCount(), vl.featureCount())
        self.assertEqual(vl.fields().count(), 1)

        geometry = next(vl.getFeatures()).geometry()
        self.assertTrue(geometry)

        point = geometry.asPoint()
        self.assertEqual(point.x(), 2)
        self.assertEqual(point.y(), 3)

        QgsProject.instance().removeMapLayer(ml)
Ejemplo n.º 2
0
    def test_SplitFeature(self):
        """Test sqlite feature can be split"""
        tmpfile = os.path.join(self.basetestpath, 'testGeopackageSplitFeatures.sqlite')
        ds = ogr.GetDriverByName('SQlite').CreateDataSource(tmpfile)
        lyr = ds.CreateLayer('test', geom_type=ogr.wkbPolygon)
        lyr.CreateField(ogr.FieldDefn('str_field', ogr.OFTString))
        f = ogr.Feature(lyr.GetLayerDefn())
        f.SetGeometry(ogr.CreateGeometryFromWkt('POLYGON ((0 0,0 1,1 1,1 0,0 0))'))
        lyr.CreateFeature(f)
        f = None
        ds = None

        layer = QgsVectorLayer(u'{}'.format(tmpfile) + "|layername=" + "test", 'test', u'ogr')

        # Check that pk field has unique constraint
        fields = layer.fields()
        pkfield = fields.at(0)
        self.assertTrue(pkfield.constraints().constraints() & QgsFieldConstraints.ConstraintUnique)

        self.assertTrue(layer.isValid())
        self.assertTrue(layer.isSpatial())
        self.assertEqual([f for f in layer.getFeatures()][0].geometry().asWkt(), 'Polygon ((0 0, 0 1, 1 1, 1 0, 0 0))')
        layer.startEditing()
        self.assertEqual(layer.splitFeatures([QgsPointXY(0.5, 0), QgsPointXY(0.5, 1)], 0), 0)
        self.assertTrue(layer.commitChanges())
        self.assertEqual(layer.featureCount(), 2)

        layer = QgsVectorLayer(u'{}'.format(tmpfile) + "|layername=" + "test", 'test', u'ogr')
        self.assertEqual(layer.featureCount(), 2)
        self.assertEqual([f for f in layer.getFeatures()][0].geometry().asWkt(), 'Polygon ((0.5 0, 0.5 1, 1 1, 1 0, 0.5 0))')
        self.assertEqual([f for f in layer.getFeatures()][1].geometry().asWkt(), 'Polygon ((0.5 1, 0.5 0, 0 0, 0 1, 0.5 1))')
Ejemplo n.º 3
0
    def testFeatureSourceInput(self):
        # create a memory layer and add to project and context
        layer = QgsVectorLayer("Point?crs=epsg:3857&field=fldtxt:string&field=fldint:integer",
                               "testmem", "memory")
        self.assertTrue(layer.isValid())
        pr = layer.dataProvider()
        f = QgsFeature()
        f.setAttributes(["test", 123])
        f.setGeometry(QgsGeometry.fromPointXY(QgsPointXY(100, 200)))
        f2 = QgsFeature()
        f2.setAttributes(["test2", 457])
        f2.setGeometry(QgsGeometry.fromPointXY(QgsPointXY(110, 200)))
        self.assertTrue(pr.addFeatures([f, f2]))
        self.assertEqual(layer.featureCount(), 2)

        # select first feature
        layer.selectByIds([next(layer.getFeatures()).id()])
        self.assertEqual(len(layer.selectedFeatureIds()), 1)

        QgsProject.instance().addMapLayer(layer)
        context = QgsProcessingContext()
        context.setProject(QgsProject.instance())

        alg = QgsApplication.processingRegistry().createAlgorithmById('grass7:v.buffer')
        self.assertIsNotNone(alg)
        temp_file = os.path.join(self.temp_dir, 'grass_output_sel.shp')
        parameters = {'input': QgsProcessingFeatureSourceDefinition('testmem', True),
                      'cats': '',
                      'where': '',
                      'type': [0, 1, 4],
                      'distance': 1,
                      'minordistance': None,
                      'angle': 0,
                      'column': None,
                      'scale': 1,
                      'tolerance': 0.01,
                      '-s': False,
                      '-c': False,
                      '-t': False,
                      'output': temp_file,
                      'GRASS_REGION_PARAMETER': None,
                      'GRASS_SNAP_TOLERANCE_PARAMETER': -1,
                      'GRASS_MIN_AREA_PARAMETER': 0.0001,
                      'GRASS_OUTPUT_TYPE_PARAMETER': 0,
                      'GRASS_VECTOR_DSCO': '',
                      'GRASS_VECTOR_LCO': ''}
        feedback = QgsProcessingFeedback()

        results, ok = alg.run(parameters, context, feedback)
        self.assertTrue(ok)
        self.assertTrue(os.path.exists(temp_file))

        # make sure that layer has correct features
        res = QgsVectorLayer(temp_file, 'res')
        self.assertTrue(res.isValid())
        self.assertEqual(res.featureCount(), 1)

        QgsProject.instance().removeMapLayer(layer)
Ejemplo n.º 4
0
    def processAlgorithm(self, parameters, context, feedback):
        layers = self.getParameterValue(self.INPUT_DATASOURCES)
        query = self.getParameterValue(self.INPUT_QUERY)
        uid_field = self.getParameterValue(self.INPUT_UID_FIELD)
        geometry_field = self.getParameterValue(self.INPUT_GEOMETRY_FIELD)
        geometry_type = self.getParameterValue(self.INPUT_GEOMETRY_TYPE)
        geometry_crs = self.getParameterValue(self.INPUT_GEOMETRY_CRS)

        df = QgsVirtualLayerDefinition()
        layerIdx = 1
        if layers:
            for layerSource in layers.split(';'):
                layer = QgsProcessingUtils.mapLayerFromString(layerSource, context)
                if layer:
                    df.addSource('input{}'.format(layerIdx), layer.id())
                layerIdx += 1

        if query == '':
            raise GeoAlgorithmExecutionException(
                self.tr('Empty SQL. Please enter valid SQL expression and try again.'))
        else:
            df.setQuery(query)

        if uid_field:
            df.setUid(uid_field)

        if geometry_type == 1:  # no geometry
            df.setGeometryWkbType(QgsWkbTypes.NullGeometry)
        else:
            if geometry_field:
                df.setGeometryField(geometry_field)
            if geometry_type > 1:
                df.setGeometryWkbType(geometry_type - 1)
            if geometry_crs:
                crs = QgsCoordinateReferenceSystem(geometry_crs)
                if crs.isValid():
                    df.setGeometrySrid(crs.postgisSrid())

        vLayer = QgsVectorLayer(df.toString(), "temp_vlayer", "virtual")
        if not vLayer.isValid():
            raise GeoAlgorithmExecutionException(vLayer.dataProvider().error().message())

        writer = self.getOutputFromName(self.OUTPUT_LAYER).getVectorWriter(vLayer.fields(),
                                                                           vLayer.wkbType() if geometry_type != 1 else 1,
                                                                           vLayer.crs(), context)

        features = QgsProcessingUtils.getFeatures(vLayer, context)
        total = 100.0 / vLayer.featureCount() if vLayer.featureCount() else 0
        outFeat = QgsFeature()
        for current, inFeat in enumerate(features):
            outFeat.setAttributes(inFeat.attributes())
            if geometry_type != 1:
                outFeat.setGeometry(inFeat.geometry())
            writer.addFeature(outFeat, QgsFeatureSink.FastInsert)
            feedback.setProgress(int(current * total))
        del writer
Ejemplo n.º 5
0
 def test_SplitTruToCreateCutEdge(self):
     """Try to creat a cut edge"""
     layer = QgsVectorLayer("dbname=test.sqlite table=test_pg (geometry)", "test_pg", "spatialite")
     assert(layer.isValid())
     assert(layer.hasGeometryType())
     layer.featureCount() == 1 or die("wrong number of features")
     layer.startEditing()
     layer.splitFeatures([QgsPoint(1.5, -0.5), QgsPoint(1.5, 1.5)], 0) == 0 or die("error when trying to create an invalid polygon in split")
     layer.commitChanges() or die("this commit should work")
     layer.featureCount() == 1 or die("wrong number of features, polygon should be unafected by cut")
Ejemplo n.º 6
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.º 7
0
 def test_SplitMultipolygon(self):
     """Split multipolygon"""
     layer = QgsVectorLayer("dbname=test.sqlite table=test_mpg (geometry)", "test_mpg", "spatialite")
     assert(layer.isValid())
     assert(layer.hasGeometryType())
     layer.featureCount() == 1 or die("wrong number of features")
     layer.startEditing()
     layer.splitFeatures([QgsPoint(0.5, -0.5), QgsPoint(0.5, 1.5)], 0) == 0 or die("error in split of one polygon of multipolygon")
     layer.splitFeatures([QgsPoint(2.5, -0.5), QgsPoint(2.5, 4)], 0) == 0 or die("error in split of two polygons of multipolygon at a time")
     layer.commitChanges() or die("this commit should work")
     layer.featureCount() == 7 or die("wrong number of features after 2 split")
Ejemplo n.º 8
0
 def test_SplitFeature(self):
     """Create spatialite database"""
     layer = QgsVectorLayer("dbname=%s table=test_pg (geometry)" % self.dbname, "test_pg", "spatialite")
     assert(layer.isValid())
     assert(layer.hasGeometryType())
     layer.startEditing()
     layer.splitFeatures([QgsPoint(0.5, -0.5), QgsPoint(0.5, 1.5)], 0) == 0 or die("error in split")
     layer.splitFeatures([QgsPoint(-0.5, 0.5), QgsPoint(1.5, 0.5)], 0) == 0 or die("error in split")
     if not layer.commitChanges():
         die("this commit should work")
     layer.featureCount() == 4 or die("we should have 4 features after 2 split")
Ejemplo n.º 9
0
    def processAlgorithm(self, parameters, context, feedback):
        layers = self.parameterAsLayerList(parameters, self.INPUT_DATASOURCES, context)
        query = self.parameterAsString(parameters, self.INPUT_QUERY, context)
        uid_field = self.parameterAsString(parameters, self.INPUT_UID_FIELD, context)
        geometry_field = self.parameterAsString(parameters, self.INPUT_GEOMETRY_FIELD, context)
        geometry_type = self.parameterAsEnum(parameters, self.INPUT_GEOMETRY_TYPE, context)
        geometry_crs = self.parameterAsCrs(parameters, self.INPUT_GEOMETRY_CRS, context)

        df = QgsVirtualLayerDefinition()
        for layerIdx, layer in enumerate(layers):
            df.addSource('input{}'.format(layerIdx + 1), layer.id())

        if query == '':
            raise QgsProcessingException(
                self.tr('Empty SQL. Please enter valid SQL expression and try again.'))
        else:
            localContext = self.createExpressionContext(parameters, context)
            expandedQuery = QgsExpression.replaceExpressionText(query, localContext)
            df.setQuery(expandedQuery)

        if uid_field:
            df.setUid(uid_field)

        if geometry_type == 1:  # no geometry
            df.setGeometryWkbType(QgsWkbTypes.NoGeometry)
        else:
            if geometry_field:
                df.setGeometryField(geometry_field)
            if geometry_type > 1:
                df.setGeometryWkbType(geometry_type - 1)
            if geometry_crs.isValid():
                df.setGeometrySrid(geometry_crs.postgisSrid())

        vLayer = QgsVectorLayer(df.toString(), "temp_vlayer", "virtual")
        if not vLayer.isValid():
            raise QgsProcessingException(vLayer.dataProvider().error().message())

        (sink, dest_id) = self.parameterAsSink(parameters, self.OUTPUT, context,
                                               vLayer.fields(), vLayer.wkbType() if geometry_type != 1 else 1, vLayer.crs())
        if sink is None:
            raise QgsProcessingException(self.invalidSinkError(parameters, self.OUTPUT))

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

            sink.addFeature(inFeat, QgsFeatureSink.FastInsert)
            feedback.setProgress(int(current * total))
        return {self.OUTPUT: dest_id}
Ejemplo n.º 10
0
def create_grid(size):
    """Create a polygonal grid using Processing.

    :param size: The cell size.
    :type size: int

    :return: The grid layer in memory.
    :rtype: QgsVectorLayer
    """
    output_filename = unique_filename(prefix='grid', suffix='.shp')

    result = processing.runalg(
        'qgis:vectorgrid',
        '336199.970553,352338.397991,7636164.67975,7648562.41208',
        size,  # X spacing
        size,  # Y spacing
        0,  # Output as polygons
        output_filename)

    layer = QgsVectorLayer(output_filename, 'grid', 'ogr')
    layer.setCrs(QgsCoordinateReferenceSystem(32740))

    remove_fields(layer, ['xmin', 'xmax', 'ymin', 'ymax'])

    # Make a copy in memory
    memory = create_memory_layer(
        'grid', layer.geometryType(), layer.crs(), layer.fields())
    copy_layer(layer, memory)

    print "NB cells : %s" % layer.featureCount()

    return memory
Ejemplo n.º 11
0
    def testApproxFeatureCountAndExtent(self):
        """ Test perf improvement for for https://issues.qgis.org/issues/18402 """

        tmpfile = os.path.join(self.basetestpath, 'testApproxFeatureCountAndExtent.gpkg')
        ds = ogr.GetDriverByName('GPKG').CreateDataSource(tmpfile)
        lyr = ds.CreateLayer('test', geom_type=ogr.wkbPoint)
        f = ogr.Feature(lyr.GetLayerDefn())
        f.SetGeometry(ogr.CreateGeometryFromWkt('POINT(0 1)'))
        lyr.CreateFeature(f)
        f = ogr.Feature(lyr.GetLayerDefn())
        f.SetGeometry(ogr.CreateGeometryFromWkt('POINT(2 3)'))
        lyr.CreateFeature(f)
        fid = f.GetFID()
        f = ogr.Feature(lyr.GetLayerDefn())
        f.SetGeometry(ogr.CreateGeometryFromWkt('POINT(4 5)'))
        lyr.CreateFeature(f)
        lyr.DeleteFeature(fid)
        ds = None
        ds = ogr.Open(tmpfile, update=1)
        ds.ExecuteSQL('DROP TABLE gpkg_ogr_contents')
        ds = None

        os.environ['QGIS_GPKG_FC_THRESHOLD'] = '1'
        vl = QgsVectorLayer(u'{}'.format(tmpfile) + "|layername=" + "test", 'test', u'ogr')
        self.assertTrue(vl.isValid())
        fc = vl.featureCount()
        del os.environ['QGIS_GPKG_FC_THRESHOLD']
        self.assertEqual(fc, 3) # didn't notice the hole

        reference = QgsGeometry.fromRect(QgsRectangle(0, 1, 4, 5))
        provider_extent = QgsGeometry.fromRect(vl.extent())
        self.assertTrue(QgsGeometry.compare(provider_extent.asPolygon()[0], reference.asPolygon()[0], 0.00001),
                        provider_extent.asPolygon()[0])
Ejemplo n.º 12
0
    def testDontRepackOnReload(self):
        ''' Test fix for #18421 '''

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

        vl = QgsVectorLayer('{}|layerid=0'.format(datasource), 'test', 'ogr')
        feature_count = vl.featureCount()
        # Start an iterator that will open a new connection
        iterator = vl.getFeatures()
        next(iterator)

        # Delete another feature while in update mode
        vl.dataProvider().enterUpdateMode()
        vl.dataProvider().reloadData()
        vl.dataProvider().deleteFeatures([0])

        # Test that repacking has not been done (since in update mode)
        ds = osgeo.ogr.Open(datasource)
        self.assertTrue(ds.GetLayer(0).GetFeatureCount() == feature_count)
        ds = None

        vl = None
Ejemplo n.º 13
0
 def test_FeatureCount(self):
     myPath = os.path.join(unitTestDataPath(), 'lines.shp')
     myLayer = QgsVectorLayer(myPath, 'Lines', 'ogr')
     myCount = myLayer.featureCount()
     myExpectedCount = 6
     myMessage = '\nExpected: %s\nGot: %s' % (myCount, myExpectedCount)
     assert myCount == myExpectedCount, myMessage
Ejemplo n.º 14
0
    def testDeleteShapes(self):
        ''' Test fix for #11007 '''

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

        vl = QgsVectorLayer('{}|layerid=0'.format(datasource), 'test', 'ogr')
        feature_count = vl.featureCount()
        # Start an iterator that will open a new connection
        iterator = vl.getFeatures()
        f = next(iterator)

        # Delete a feature
        self.assertTrue(vl.startEditing())
        self.assertTrue(vl.deleteFeature(1))
        self.assertTrue(vl.commitChanges())

        # Test the content of the shapefile while it is still opened
        ds = osgeo.ogr.Open(datasource)
        # Test repacking has been done
        self.assertTrue(ds.GetLayer(0).GetFeatureCount(), feature_count - 1)
        ds = None

        vl = None
Ejemplo n.º 15
0
 def _aliased_sql_helper(self, dbname):
     queries = (
         '(SELECT * FROM (SELECT * from \\"some view\\"))',
         '(SELECT * FROM \\"some view\\")',
         '(select sd.* from somedata as sd left join somedata as sd2 on ( sd2.name = sd.name ))',
         '(select sd.* from \\"somedata\\" as sd left join \\"somedata\\" as sd2 on ( sd2.name = sd.name ))',
         "(SELECT * FROM somedata as my_alias1\n)",
         "(SELECT * FROM somedata as my_alias2)",
         "(SELECT * FROM somedata AS my_alias3)",
         '(SELECT * FROM \\"somedata\\" as my_alias4\n)',
         '(SELECT * FROM (SELECT * FROM \\"somedata\\"))',
         '(SELECT my_alias5.* FROM (SELECT * FROM \\"somedata\\") AS my_alias5)',
         '(SELECT my_alias6.* FROM (SELECT * FROM \\"somedata\\" as my_alias\n) AS my_alias6)',
         '(SELECT my_alias7.* FROM (SELECT * FROM \\"somedata\\" as my_alias\n) AS my_alias7\n)',
         '(SELECT my_alias8.* FROM (SELECT * FROM \\"some data\\") AS my_alias8)',
         '(SELECT my_alias9.* FROM (SELECT * FROM \\"some data\\" as my_alias\n) AS my_alias9)',
         '(SELECT my_alias10.* FROM (SELECT * FROM \\"some data\\" as my_alias\n) AS my_alias10\n)',
         '(select sd.* from \\"some data\\" as sd left join \\"some data\\" as sd2 on ( sd2.name = sd.name ))',
         '(SELECT * FROM \\"some data\\" as my_alias11\n)',
         '(SELECT * FROM \\"some data\\" as my_alias12)',
         '(SELECT * FROM \\"some data\\" AS my_alias13)',
         '(SELECT * from \\"some data\\" AS my_alias14\n)',
         '(SELECT * FROM (SELECT * from \\"some data\\"))',
     )
     for sql in queries:
         vl = QgsVectorLayer('dbname=\'{}\' table="{}" (geom) sql='.format(dbname, sql), 'test', 'spatialite')
         self.assertTrue(vl.isValid(), 'dbname: {} - sql: {}'.format(dbname, sql))
         self.assertTrue(vl.featureCount() > 1)
         self.assertTrue(vl.isSpatial())
Ejemplo n.º 16
0
    def test_split_by_polygon(self):
        """Test split_by_polygon work"""
        line_before = QgsVectorLayer(
            self.line_before + '.shp', 'test', 'ogr')
        expected_lines = QgsVectorLayer(
            self.line_after + '.shp', 'test', 'ogr')
        polygon_layer = QgsVectorLayer(
            self.polygon_base + '.shp', 'test', 'ogr')

        # Only one polygon is stored in the layer
        for feature in polygon_layer.getFeatures():
            polygon = feature.geometry()

        split_lines = split_by_polygon(
            line_before,
            polygon,
            mark_value=('flooded', 1))

        # Test the lines is not multipart
        for feature in split_lines.getFeatures():
            self.assertFalse(feature.geometry().isMultipart())

        self.assertEqual(expected_lines.featureCount(),
                         split_lines.featureCount())
        # Assert for every line from split_lines
        # we can find the same line
        for feature in split_lines.getFeatures():
            found = False
            for expected in expected_lines.getFeatures():
                if (feature.attributes() == expected.attributes()) and \
                   (feature.geometry().isGeosEqual(expected.geometry())):
                    found = True
                    break
            self.assertTrue(found)

        # Split by the extent (The result is the copy of the layer)
        line_before.updateExtents()
        # Expand extent to cover the lines (add epsilon to bounds)
        epsilon = 0.0001    # A small number
        extent = line_before.extent()
        new_extent = QgsRectangle(
            extent.xMinimum() - epsilon,
            extent.yMinimum() - epsilon,
            extent.xMaximum() + epsilon,
            extent.yMaximum() + epsilon
        )
        new_extent = QgsGeometry().fromRect(new_extent)
        split_lines = split_by_polygon(
            line_before,
            new_extent)
        for feature in split_lines.getFeatures():
            found = False
            for expected in line_before.getFeatures():
                if (feature.attributes() == expected.attributes()) and \
                   (feature.geometry().isGeosEqual(expected.geometry())):
                    found = True
                    break
            self.assertTrue(found)
    def testSubsetStringExtent_bug17863(self):
        """Check that the extent is correct when applied in the ctor and when
        modified after a subset string is set """

        def _lessdigits(s):
            return re.sub(r'(\d+\.\d{3})\d+', r'\1', s)

        testPath = "dbname=%s table='test_filter' (geometry) key='id'" % self.dbname

        subSetString = '"name" = \'int\''
        subSet = ' sql=%s' % subSetString

        # unfiltered
        vl = QgsVectorLayer(testPath, 'test', 'spatialite')
        self.assertTrue(vl.isValid())
        self.assertEqual(vl.featureCount(), 8)
        unfiltered_extent = _lessdigits(vl.extent().toString())
        self.assertNotEqual('Empty', unfiltered_extent)
        del(vl)

        # filter after construction ...
        subSet_vl2 = QgsVectorLayer(testPath, 'test', 'spatialite')
        self.assertEqual(_lessdigits(subSet_vl2.extent().toString()), unfiltered_extent)
        self.assertEqual(subSet_vl2.featureCount(), 8)
        # ... apply filter now!
        subSet_vl2.setSubsetString(subSetString)
        self.assertEqual(subSet_vl2.featureCount(), 4)
        self.assertEqual(subSet_vl2.subsetString(), subSetString)
        self.assertNotEqual(_lessdigits(subSet_vl2.extent().toString()), unfiltered_extent)
        filtered_extent = _lessdigits(subSet_vl2.extent().toString())
        del(subSet_vl2)

        # filtered in constructor
        subSet_vl = QgsVectorLayer(testPath + subSet, 'subset_test', 'spatialite')
        self.assertEqual(subSet_vl.subsetString(), subSetString)
        self.assertTrue(subSet_vl.isValid())

        # This was failing in bug 17863
        self.assertEqual(subSet_vl.featureCount(), 4)
        self.assertEqual(_lessdigits(subSet_vl.extent().toString()), filtered_extent)
        self.assertNotEqual(_lessdigits(subSet_vl.extent().toString()), unfiltered_extent)

        self.assertTrue(subSet_vl.setSubsetString(''))
        self.assertEqual(subSet_vl.featureCount(), 8)
        self.assertEqual(_lessdigits(subSet_vl.extent().toString()), unfiltered_extent)
Ejemplo n.º 18
0
    def testSubsetStringRegexp(self):
        """Check that the provider supports the REGEXP syntax"""

        testPath = "dbname=%s table='test_filter' (geometry) key='id'" % self.dbname
        vl = QgsVectorLayer(testPath, 'test', 'spatialite')
        self.assertTrue(vl.isValid())
        vl.setSubsetString('"name" REGEXP \'[txe]\'')
        self.assertEqual(vl.featureCount(), 4)
        del(vl)
Ejemplo n.º 19
0
 def testBboxRestriction(self):
     """
     Test limiting provider to features within a preset bounding box
     """
     endpoint = self.basetestpath + '/fake_qgis_http_endpoint'
     vl = QgsVectorLayer("url='http://" + endpoint + "' crs='epsg:4326' bbox='-70.000000,67.000000,-60.000000,80.000000'", 'test', 'arcgisfeatureserver')
     self.assertTrue(vl.isValid())
     self.assertEqual(vl.featureCount(), 2)
     self.assertEqual([f['pk'] for f in vl.getFeatures()], [2, 4])
Ejemplo n.º 20
0
def createLayerWithOnePoint():
    layer = QgsVectorLayer("Point?field=fldtxt:string&field=fldint:integer",
                           "addfeat", "memory")
    pr = layer.dataProvider()
    f = QgsFeature()
    f.setAttributes(["test", 123])
    assert pr.addFeatures([f])
    assert layer.featureCount() == 1
    return layer
 def test_SplitFeature(self):
     """Create SpatiaLite database"""
     layer = QgsVectorLayer("dbname=%s table=test_pg (geometry)" % self.dbname, "test_pg", "spatialite")
     self.assertTrue(layer.isValid())
     self.assertTrue(layer.isSpatial())
     layer.startEditing()
     self.assertEqual(layer.splitFeatures([QgsPointXY(0.75, -0.5), QgsPointXY(0.75, 1.5)], 0), 0)
     self.assertEqual(layer.splitFeatures([QgsPointXY(-0.5, 0.25), QgsPointXY(1.5, 0.25)], 0), 0)
     self.assertTrue(layer.commitChanges())
     self.assertEqual(layer.featureCount(), 4)
Ejemplo n.º 22
0
    def testRepackAtFirstSave(self):
        ''' Test fix for #15407 '''

        # This requires a GDAL fix done per https://trac.osgeo.org/gdal/ticket/6672
        # but on non-Windows version the test would succeed
        if int(osgeo.gdal.VersionInfo('VERSION_NUM')) < GDAL_COMPUTE_VERSION(2, 1, 2):
            return

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

        ds = osgeo.ogr.Open(datasource)
        lyr = ds.GetLayer(0)
        original_feature_count = lyr.GetFeatureCount()
        lyr.DeleteFeature(2)
        ds = None

        vl = QgsVectorLayer('{}|layerid=0'.format(datasource), 'test', 'ogr')

        self.assertTrue(vl.featureCount(), original_feature_count)

        # Edit a feature (attribute change only)
        self.assertTrue(vl.startEditing())
        self.assertTrue(vl.dataProvider().changeAttributeValues({0: {0: 100}}))

        # Commit changes and check no error is emitted
        cbk = ErrorReceiver()
        vl.dataProvider().raiseError.connect(cbk.receiveError)
        self.assertTrue(vl.commitChanges())
        self.assertIsNone(cbk.msg)

        self.assertTrue(vl.featureCount(), original_feature_count - 1)

        vl = None

        # Test repacking has been done
        ds = osgeo.ogr.Open(datasource)
        self.assertTrue(ds.GetLayer(0).GetFeatureCount(), original_feature_count - 1)
        ds = None
Ejemplo n.º 23
0
    def testRepack(self):
        vl = QgsVectorLayer('{}|layerid=0'.format(self.repackfile), 'test', 'ogr')

        ids = [f.id() for f in vl.getFeatures(QgsFeatureRequest().setFilterExpression('pk=1'))]
        vl.selectByIds(ids)
        self.assertEqual(vl.selectedFeatureIds(), ids)
        self.assertEqual(vl.featureCount(), 5)
        self.assertTrue(vl.startEditing())
        self.assertTrue(vl.deleteFeature(3))
        self.assertTrue(vl.commitChanges())
        self.assertTrue(vl.selectedFeatureCount() == 0 or vl.selectedFeatures()[0]['pk'] == 1)
Ejemplo n.º 24
0
def _modifyAndLoadWfs():
    valid = {}
    urls = os.getenv(TEST_URLS).split(",")
    for url in urls:
        try:
            url = url.strip() + "/wfs"
            uri = "%s?typename=union&version=1.0.0&request=GetFeature&service=WFS" % url
            layer = QgsVectorLayer(uri, "testlayer", "WFS")
            featureCount = layer.featureCount()
            featureid = list(layer.getFeatures())[0].id()
            layer.startEditing()
            layer.deleteFeature(featureid)
            layer.commitChanges()
            layer = QgsVectorLayer(uri, "testlayer", "WFS")
            valid[url] =  layer.featureCount() == featureCount - 1
        except:
            valid[url] = False
    failed = [k for k,v in valid.items() if not v]
    if failed:
        raise AssertionError("Test failed for the following URLs: " + str(failed))
Ejemplo n.º 25
0
 def testIntersection(self):
     myLine = QgsGeometry.fromPolyline([QgsPoint(0, 0),QgsPoint(1, 1),QgsPoint(2, 2)])
     myPoint = QgsGeometry.fromPoint(QgsPoint(1, 1))
     intersectionGeom = QgsGeometry.intersection(myLine, myPoint)
     myMessage = ('Expected:\n%s\nGot:\n%s\n' %
                   (QGis.Point, intersectionGeom.type()))
     assert intersectionGeom.wkbType() == QGis.WKBPoint, myMessage
     
     layer = QgsVectorLayer("Point", "intersection", "memory")
     assert layer.isValid(), "Failed to create valid point memory layer"
     
     provider = layer.dataProvider()
             
     ft = QgsFeature()
     ft.setGeometry(intersectionGeom)
     provider.addFeatures([ft])
     
     myMessage = ('Expected:\n%s\nGot:\n%s\n' %
                   (1, layer.featureCount()))
     assert layer.featureCount() == 1, myMessage
Ejemplo n.º 26
0
    def test_non_ascii_output(self):
        # create a memory layer and add to project and context
        layer = QgsVectorLayer("Point?crs=epsg:3857&field=fldtxt:string&field=fldint:integer",
                               "testmem", "memory")
        self.assertTrue(layer.isValid())
        pr = layer.dataProvider()
        f = QgsFeature()
        f.setAttributes(["test", 123])
        f.setGeometry(QgsGeometry.fromPointXY(QgsPointXY(100, 200)))
        f2 = QgsFeature()
        f2.setAttributes(["test2", 457])
        f2.setGeometry(QgsGeometry.fromPointXY(QgsPointXY(110, 200)))
        self.assertTrue(pr.addFeatures([f, f2]))
        self.assertEqual(layer.featureCount(), 2)
        QgsProject.instance().addMapLayer(layer)
        context = QgsProcessingContext()
        context.setProject(QgsProject.instance())

        alg = QgsApplication.processingRegistry().createAlgorithmById('saga:fixeddistancebuffer')
        self.assertIsNotNone(alg)

        temp_file = os.path.join(self.temp_dir, 'non_ascii_ñññ.shp')
        parameters = {'SHAPES': 'testmem',
                      'DIST_FIELD_DEFAULT': 5,
                      'NZONES': 1,
                      'DARC': 5,
                      'DISSOLVE': False,
                      'POLY_INNER': False,
                      'BUFFER': temp_file}
        feedback = QgsProcessingFeedback()

        results, ok = alg.run(parameters, context, feedback)
        self.assertTrue(ok)
        self.assertTrue(os.path.exists(temp_file))

        # make sure that layer has correct features
        res = QgsVectorLayer(temp_file, 'res')
        self.assertTrue(res.isValid())
        self.assertEqual(res.featureCount(), 2)

        QgsProject.instance().removeMapLayer(layer)
Ejemplo n.º 27
0
    def test_filterfid_crossjoin(self):
        l0 = QgsVectorLayer(os.path.join(self.testDataDir, "france_parts.shp"), "france_parts", "ogr")
        self.assertTrue(l0.isValid())
        QgsProject.instance().addMapLayer(l0)

        l1 = QgsVectorLayer(os.path.join(self.testDataDir, "points.shp"), "points", "ogr")
        self.assertTrue(l1.isValid())
        QgsProject.instance().addMapLayer(l1)

        # cross join
        query = toPercent("SELECT * FROM france_parts,points")
        vl = QgsVectorLayer("?query=%s" % query, "tt", "virtual")

        self.assertEqual(vl.featureCount(), l0.featureCount() * l1.featureCount())

        # test with FilterFid requests
        f = next(vl.getFeatures(QgsFeatureRequest().setFilterFid(0)))
        idx = f.fields().indexOf('Class')
        self.assertEqual(f.id(), 0)
        self.assertEqual(f.attributes()[idx], 'Jet')

        f = next(vl.getFeatures(QgsFeatureRequest().setFilterFid(5)))
        self.assertEqual(f.id(), 5)
        self.assertEqual(f.attributes()[idx], 'Biplane')

        # test with FilterFid requests
        fit = vl.getFeatures(QgsFeatureRequest().setFilterFids([0, 3, 5]))

        f = next(fit)
        self.assertEqual(f.id(), 0)
        self.assertEqual(f.attributes()[idx], 'Jet')

        f = next(fit)
        self.assertEqual(f.id(), 3)
        self.assertEqual(f.attributes()[idx], 'Jet')

        f = next(fit)
        self.assertEqual(f.id(), 5)
        self.assertEqual(f.attributes()[idx], 'Biplane')
Ejemplo n.º 28
0
    def testGetOgrCompatibleSourceFromFeatureSource(self):
        # create a memory layer and add to project and context
        layer = QgsVectorLayer("Point?field=fldtxt:string&field=fldint:integer",
                               "testmem", "memory")
        self.assertTrue(layer.isValid())
        pr = layer.dataProvider()
        f = QgsFeature()
        f.setAttributes(["test", 123])
        f.setGeometry(QgsGeometry.fromPointXY(QgsPointXY(100, 200)))
        f2 = QgsFeature()
        f2.setAttributes(["test2", 457])
        f2.setGeometry(QgsGeometry.fromPointXY(QgsPointXY(100, 200)))
        self.assertTrue(pr.addFeatures([f, f2]))
        self.assertEqual(layer.featureCount(), 2)
        # select first feature
        layer.selectByIds([next(layer.getFeatures()).id()])
        self.assertEqual(len(layer.selectedFeatureIds()), 1)
        QgsProject.instance().addMapLayer(layer)
        context = QgsProcessingContext()
        context.setProject(QgsProject.instance())

        alg = QgsApplication.processingRegistry().createAlgorithmById('gdal:buffervectors')
        self.assertIsNotNone(alg)
        parameters = {'INPUT': QgsProcessingFeatureSourceDefinition('testmem', True)}
        feedback = QgsProcessingFeedback()
        # check that memory layer is automatically saved out to shape when required by GDAL algorithms
        ogr_data_path, ogr_layer_name = alg.getOgrCompatibleSource('INPUT', parameters, context, feedback,
                                                                   executing=True)
        self.assertTrue(ogr_data_path)
        self.assertTrue(ogr_data_path.endswith('.shp'))
        self.assertTrue(os.path.exists(ogr_data_path))
        self.assertTrue(ogr_layer_name)

        # make sure that layer has only selected feature
        res = QgsVectorLayer(ogr_data_path, 'res')
        self.assertTrue(res.isValid())
        self.assertEqual(res.featureCount(), 1)

        QgsProject.instance().removeMapLayer(layer)
Ejemplo n.º 29
0
def polygonize_gdal(
        raster,
        threshold_min=0.0,
        threshold_max=float('inf')):
    """
    Function to polygonize raster. Areas (pixels) with threshold_min <
    pixel_values < threshold_max will be converted to polygons.

    :param raster:  Raster layer
    :type raster: QgsRasterLayer

    :param threshold_min: Value that splits raster to flooded or not flooded.
    :type threshold_min: float

    :param threshold_max: Value that splits raster to flooded or not flooded.
    :type threshold_max: float

    :returns: Polygonal geometry
    :rtype: QgsGeometry
    """

    # save qgis raster to disk
    base_name = unique_filename()
    file_name = base_name + '.tif'
    file_writer = QgsRasterFileWriter(file_name)
    pipe = QgsRasterPipe()
    provider = raster.dataProvider()
    if not pipe.set(provider.clone()):
        msg = "Cannot set pipe provider"
        raise GetDataError(msg)
    file_writer.writeRaster(
        pipe,
        provider.xSize(),
        provider.ySize(),
        provider.extent(),
        provider.crs())

    (
        inside_file_name,
        inside_layer_name,
        outside_file_name,
        outside_layer_name
    ) = polygonize_thresholds(file_name, threshold_min, threshold_max)
    inside_layer = \
        QgsVectorLayer(inside_file_name, inside_layer_name, 'ogr')
    outside_layer = \
        QgsVectorLayer(outside_file_name, outside_layer_name, 'ogr')
    if inside_layer.featureCount() == 0:
        return None, None
    else:
        return inside_layer, outside_layer
Ejemplo n.º 30
0
    def testPKNotInt(self):
        """ Check when primary key is not an integer """
        # create test db
        dbname = os.path.join(tempfile.mkdtemp(), "test_pknotint.sqlite")
        con = spatialite_connect(dbname, isolation_level=None)
        cur = con.cursor()

        # try the two different types of index creation
        for index_creation_method in ['CreateSpatialIndex', 'CreateMbrCache']:

            table_name = "pk_is_string_{}".format(index_creation_method)

            cur.execute("BEGIN")
            sql = "SELECT InitSpatialMetadata()"
            cur.execute(sql)

            # create table with spatial index and pk is string
            sql = "CREATE TABLE {}(id VARCHAR PRIMARY KEY NOT NULL, name TEXT NOT NULL);"
            cur.execute(sql.format(table_name))

            sql = "SELECT AddGeometryColumn('{}', 'geometry',  4326, 'POINT', 'XY')"
            cur.execute(sql.format(table_name))

            sql = "SELECT {}('{}', 'geometry')"
            cur.execute(sql.format(index_creation_method, table_name))

            sql = "insert into {} ('id', 'name', 'geometry') values( 'test_id', 'test_name', st_geomfromtext('POINT(1 2)', 4326))"
            cur.execute(sql.format(table_name))

            cur.execute("COMMIT")

            testPath = "dbname={} table='{}' (geometry)".format(dbname, table_name)
            vl = QgsVectorLayer(testPath, 'test', 'spatialite')
            self.assertTrue(vl.isValid())
            self.assertEqual(vl.featureCount(), 1)

            # make spatial request to force the index use
            request = QgsFeatureRequest(QgsRectangle(0, 0, 2, 3))
            feature = next(vl.getFeatures(request), None)
            self.assertTrue(feature)

            self.assertEqual(feature.id(), 1)
            point = feature.geometry().asPoint()
            self.assertTrue(point)
            self.assertEqual(point.x(), 1)
            self.assertEqual(point.y(), 2)

        con.close()

        basepath, filename = os.path.split(dbname)
        shutil.rmtree(basepath)
Ejemplo n.º 31
0
    def testApproxFeatureCountAndExtent(self):
        """ Test perf improvement for for https://issues.qgis.org/issues/18402 """

        tmpfile = os.path.join(self.basetestpath,
                               'testApproxFeatureCountAndExtent.gpkg')
        ds = ogr.GetDriverByName('GPKG').CreateDataSource(tmpfile)
        lyr = ds.CreateLayer('test', geom_type=ogr.wkbPoint)
        f = ogr.Feature(lyr.GetLayerDefn())
        f.SetGeometry(ogr.CreateGeometryFromWkt('POINT(0 1)'))
        lyr.CreateFeature(f)
        f = ogr.Feature(lyr.GetLayerDefn())
        f.SetGeometry(ogr.CreateGeometryFromWkt('POINT(2 3)'))
        lyr.CreateFeature(f)
        fid = f.GetFID()
        f = ogr.Feature(lyr.GetLayerDefn())
        f.SetGeometry(ogr.CreateGeometryFromWkt('POINT(4 5)'))
        lyr.CreateFeature(f)
        lyr.DeleteFeature(fid)
        ds = None
        ds = ogr.Open(tmpfile, update=1)
        ds.ExecuteSQL('DROP TABLE gpkg_ogr_contents')
        ds = None

        os.environ['QGIS_GPKG_FC_THRESHOLD'] = '1'
        vl = QgsVectorLayer(u'{}'.format(tmpfile) + "|layername=" + "test",
                            'test', u'ogr')
        self.assertTrue(vl.isValid())
        fc = vl.featureCount()
        del os.environ['QGIS_GPKG_FC_THRESHOLD']
        self.assertEqual(fc, 3)  # didn't notice the hole

        reference = QgsGeometry.fromRect(QgsRectangle(0, 1, 4, 5))
        provider_extent = QgsGeometry.fromRect(vl.extent())
        self.assertTrue(
            QgsGeometry.compare(provider_extent.asPolygon()[0],
                                reference.asPolygon()[0], 0.00001),
            provider_extent.asPolygon()[0])
Ejemplo n.º 32
0
def addIrrepResults(setupObject, irrepDict, irrepFieldName, statusSet):
    puLayer = QgsVectorLayer(setupObject.puPath, 'Planning units', 'ogr')
    provider = puLayer.dataProvider()
    idFieldIndex = puLayer.fields().indexFromName("Unit_ID")
    statusFieldIndex = puLayer.fields().indexFromName("Status")

    provider.addAttributes([QgsField(irrepFieldName, QVariant.Double)])
    puLayer.updateFields()
    irrepFieldOrder = provider.fieldNameIndex(irrepFieldName)

    progressBar = makeProgressBar('Adding summed irreplaceability values to planning unit shapefile')
    polyCount = 1
    polyTotalCount = puLayer.featureCount()

    puFeatures = puLayer.getFeatures()
    puLayer.startEditing()
    for puFeature in puFeatures:
        progressBar.setValue((polyCount/polyTotalCount) * 100)
        polyCount += 1

        puRow = puFeature.id()
        puAttributes = puFeature.attributes()
        puID = puAttributes[idFieldIndex]
        puStatus = puAttributes[statusFieldIndex]
        if puStatus in statusSet:
            summedIrrepValue = 0
            try:
                puIrrepDict = irrepDict[puID]
                for featID in puIrrepDict:
                    summedIrrepValue += puIrrepDict[featID]
            except KeyError:
                pass
        else:
            summedIrrepValue = -99
        puLayer.changeAttributeValue(puRow, irrepFieldOrder, summedIrrepValue, True)
    puLayer.commitChanges()
    clearProgressBar()
Ejemplo n.º 33
0
    def testOverwriteGPKG(self):
        """Test that overwriting the same origin GPKG file works only if the layername is different"""

        # Prepare test data
        ml = QgsVectorLayer('Point?field=firstfield:int&field=secondfield:int',
                            'test', 'memory')
        provider = ml.dataProvider()
        ft = QgsFeature()
        ft.setAttributes([4, -10])
        provider.addFeatures([ft])
        filehandle, filename = tempfile.mkstemp('.gpkg')

        options = QgsVectorFileWriter.SaveVectorOptions()
        options.driverName = 'GPKG'
        options.layerName = 'test'
        write_result, error_message = QgsVectorFileWriter.writeAsVectorFormat(
            ml, filename, options)
        self.assertEqual(write_result, QgsVectorFileWriter.NoError,
                         error_message)

        # Real test
        vl = QgsVectorLayer("%s|layername=test" % filename, 'src_test', 'ogr')
        self.assertTrue(vl.isValid())
        self.assertEqual(vl.featureCount(), 1)

        # This must fail
        write_result, error_message = QgsVectorFileWriter.writeAsVectorFormat(
            vl, filename, options)
        self.assertEqual(write_result, QgsVectorFileWriter.ErrCreateDataSource)
        self.assertEqual(error_message,
                         'Cannot overwrite a OGR layer in place')

        options.layerName = 'test2'
        write_result, error_message = QgsVectorFileWriter.writeAsVectorFormat(
            vl, filename, options)
        self.assertEqual(write_result, QgsVectorFileWriter.NoError,
                         error_message)
    def testNoSliverPolygons(self):

        # create a layer with some polygons that will be used as a source for "avoid intersections"
        l = QgsVectorLayer('MultiPolygon', 'test_layer', 'memory')
        assert l.isValid()

        features = []
        for i, wkt in enumerate(feat_wkt):
            f = QgsFeature(i + 1)
            f.setGeometry(QgsGeometry.fromWkt(wkt))
            features.append(f)

        l.dataProvider().addFeatures(features)
        assert l.featureCount() == 7

        # create a geometry and remove its intersections with other geometries

        g = QgsGeometry.fromWkt(newg_wkt)
        assert g.avoidIntersections([l]) == 0

        # the resulting multi-polygon must have exactly three parts
        # (in QGIS 2.0 it has one more tiny part that appears at the border between two of the original polygons)
        mpg = g.asMultiPolygon()
        assert len(mpg) == 3
Ejemplo n.º 35
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.º 36
0
    def testLoadStyle(self):
        """Check that we can store and load a style"""

        # create test db
        dbname = os.path.join(tempfile.gettempdir(), "test_loadstyle.sqlite")
        if os.path.exists(dbname):
            os.remove(dbname)
        con = spatialite_connect(dbname, isolation_level=None)
        cur = con.cursor()
        cur.execute("BEGIN")
        sql = "SELECT InitSpatialMetadata()"
        cur.execute(sql)

        # simple table with primary key
        sql = "CREATE TABLE test_pg (id INTEGER NOT NULL PRIMARY KEY, name TEXT NOT NULL)"
        cur.execute(sql)

        sql = "SELECT AddGeometryColumn('test_pg', 'geometry', 4326, 'POLYGON', 'XY')"
        cur.execute(sql)

        sql = "INSERT INTO test_pg (id, name, geometry) "
        sql += "VALUES (1, 'toto', GeomFromText('POLYGON((0 0,1 0,1 1,0 1,0 0))', 4326))"
        cur.execute(sql)

        cur.execute("COMMIT")
        con.close()

        testPath = "dbname=%s table='test_pg' (geometry) key='id'" % dbname
        vl = QgsVectorLayer(testPath, 'test', 'spatialite')
        self.assertTrue(vl.isValid())
        self.assertEqual(vl.featureCount(), 1)
        err, ok = vl.loadDefaultStyle()
        self.assertFalse(ok)
        vl.saveStyleToDatabase('my_style', 'My description', True, '')
        err, ok = vl.loadDefaultStyle()
        self.assertTrue(ok)
Ejemplo n.º 37
0
    def test_AddFeatureNullFid(self):
        """Test gpkg feature with NULL fid can be added"""
        tmpfile = os.path.join(self.basetestpath, 'testGeopackageSplitFeatures.gpkg')
        ds = ogr.GetDriverByName('GPKG').CreateDataSource(tmpfile)
        lyr = ds.CreateLayer('test', geom_type=ogr.wkbPolygon)
        lyr.CreateField(ogr.FieldDefn('str_field', ogr.OFTString))
        ds = None

        layer = QgsVectorLayer(u'{}'.format(tmpfile) + "|layername=" + "test", 'test', u'ogr')

        # Check that pk field has unique constraint
        fields = layer.fields()
        pkfield = fields.at(0)
        self.assertTrue(pkfield.constraints().constraints() & QgsFieldConstraints.ConstraintUnique)

        # Test add feature with default Fid (NULL)
        layer.startEditing()
        f = QgsFeature()
        feat = QgsFeature(layer.fields())
        feat.setGeometry(QgsGeometry.fromWkt('Polygon ((0 0, 0 1, 1 1, 1 0, 0 0))'))
        feat.setAttribute(1, 'test_value')
        layer.addFeature(feat)
        self.assertTrue(layer.commitChanges())
        self.assertEqual(layer.featureCount(), 1)
Ejemplo n.º 38
0
    def test_create_geometries(self):

        layer = QgsVectorLayer('Polygon?crs=epsg:2056&field=value:double(1,0)',
                               'polygons', "memory")

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

        pos_x = 2600000
        pos_y = 1200000
        for value in range(10):
            points = []
            points.append(QgsPointXY(pos_x, pos_y))
            points.append(QgsPointXY(pos_x + 200, pos_y))
            points.append(QgsPointXY(pos_x + 200, pos_y + 10))
            points.append(QgsPointXY(pos_x, pos_y + 10))
            points.append(QgsPointXY(pos_x, pos_y))
            geometry = QgsGeometry.fromPolygonXY([points])

            feature = QgsFeature(layer.fields())
            feature.setFields(layer.fields())
            feature.setGeometry(geometry)
            layer.dataProvider().addFeatures([feature])
            pos_y += 20
        self.assertEqual(10, layer.featureCount())
Ejemplo n.º 39
0
    def testCloneFeatures(self):
        """
        Test that cloning a memory layer also clones features
        """
        vl = QgsVectorLayer(
            'Point?crs=epsg:4326&field=f1:integer&field=f2:integer', 'test',
            'memory')
        self.assertTrue(vl.isValid())

        f1 = QgsFeature()
        f1.setAttributes([5, -200])
        f2 = QgsFeature()
        f2.setAttributes([3, 300])
        f3 = QgsFeature()
        f3.setAttributes([1, 100])
        res, [f1, f2, f3] = vl.dataProvider().addFeatures([f1, f2, f3])
        self.assertEqual(vl.featureCount(), 3)

        vl2 = vl.clone()
        self.assertEqual(vl2.featureCount(), 3)
        features = [f for f in vl2.getFeatures()]
        self.assertTrue([f for f in features if f['f1'] == 5])
        self.assertTrue([f for f in features if f['f1'] == 3])
        self.assertTrue([f for f in features if f['f1'] == 1])
Ejemplo n.º 40
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)
    def check_overlaps_in_boundaries(self, db, layer_dict):
        rule = self.quality_rules_manager.get_quality_rule(EnumQualityRule.Line.OVERLAPS_IN_BOUNDARIES)
        boundary_layer = list(layer_dict[QUALITY_RULE_LAYERS].values())[0] if layer_dict[QUALITY_RULE_LAYERS] else None

        if not boundary_layer:
            return QCoreApplication.translate("LineQualityRules", "'Boundary' layer not found!"), Qgis.Critical

        # Create error layers structure
        error_point_layer = QgsVectorLayer("MultiPoint?crs={}".format(boundary_layer.sourceCrs().authid()), "{} (puntos)".format(rule.error_table_name), "memory")
        data_provider = error_point_layer.dataProvider()
        data_provider.addAttributes(rule.error_table_fields)
        error_point_layer.updateFields()

        error_line_layer = QgsVectorLayer("MultiLineString?crs={}".format(boundary_layer.sourceCrs().authid()), "{} (líneas)".format(rule.error_table_name), "memory")
        data_provider = error_line_layer.dataProvider()
        data_provider.addAttributes(rule.error_table_fields)
        error_line_layer.updateFields()

        if boundary_layer:
            overlapping = self.geometry.get_overlapping_lines(boundary_layer)
            if overlapping is None:
                return (QCoreApplication.translate("LineQualityRules",
                                 "There are no boundaries to check for overlaps!"), Qgis.Warning)

            else:
                points_intersected = overlapping['native:saveselectedfeatures_3:Intersected_Points']
                lines_intersected = overlapping['native:saveselectedfeatures_2:Intersected_Lines']

                if isinstance(points_intersected, QgsVectorLayer):
                    point_features = list()
                    if points_intersected.featureCount() > 0:
                        for feature in points_intersected.getFeatures():
                            new_feature = QgsVectorLayerUtils().createFeature(
                                error_point_layer,
                                feature.geometry(),
                                {0: feature[db.names.T_ILI_TID_F],
                                 1: feature["{}_2".format(db.names.T_ILI_TID_F)],
                                 2: self.quality_rules_manager.get_error_message(QUALITY_RULE_ERROR_CODE_E200101),
                                 3: QUALITY_RULE_ERROR_CODE_E200101})
                            point_features.append(new_feature)
                    error_point_layer.dataProvider().addFeatures(point_features)

                if isinstance(lines_intersected, QgsVectorLayer):
                    line_features = list()
                    if lines_intersected.featureCount() > 0:
                        for feature in lines_intersected.getFeatures():
                            new_feature = QgsVectorLayerUtils().createFeature(
                                error_line_layer,
                                feature.geometry(),
                                {0: feature[db.names.T_ILI_TID_F],
                                 1: feature["{}_2".format(db.names.T_ILI_TID_F)],
                                 2: self.quality_rules_manager.get_error_message(QUALITY_RULE_ERROR_CODE_E200101),
                                 3: QUALITY_RULE_ERROR_CODE_E200101})
                            line_features.append(new_feature)

                    error_line_layer.dataProvider().addFeatures(line_features)

                if error_point_layer.featureCount() == 0 and error_line_layer.featureCount() == 0:
                    return QCoreApplication.translate("LineQualityRules", "There are no overlapping boundaries."), Qgis.Success
                else:
                    msg = ""
                    if error_point_layer.featureCount() and error_line_layer.featureCount():
                        self.app.gui.add_error_layer(db, error_point_layer)
                        self.app.gui.add_error_layer(db, error_line_layer)
                        msg = QCoreApplication.translate("LineQualityRules",
                                                         "Two memory layers with overlapping boundaries ({} point intersections and {} line intersections) have been added to the map.").format(error_point_layer.featureCount(), error_line_layer.featureCount())
                    elif error_point_layer.featureCount():
                        self.app.gui.add_error_layer(db, error_point_layer)
                        msg = QCoreApplication.translate("LineQualityRules",
                                                         "A memory layer with {} overlapping boundaries (point intersections) has been added to the map.").format(error_point_layer.featureCount())
                    elif error_line_layer.featureCount():
                        self.app.gui.add_error_layer(db, error_line_layer)
                        msg = QCoreApplication.translate("LineQualityRules",
                                                         "A memory layer with {} overlapping boundaries (line intersections) has been added to the map.").format(error_line_layer.featureCount())
                    return msg, Qgis.Critical
class GpxFeatureBuilder:
    """ Builds gpx layers and features """

    def __init__(self, layer_name, attribute_definitions, attribute_select='Last', crs=None):
        self.error_message = ''

        layer_definition: str = 'LineString'
        if crs is not None:
            layer_definition = layer_definition + "?crs=epsg:" + str(crs.postgisSrid())

        self.vector_layer = QgsVectorLayer(layer_definition, layer_name, "memory")
        self.data_provider = self.vector_layer.dataProvider()

        # Enter editing mode
        self.vector_layer.startEditing()
        attributes = list()
        for attribute in attribute_definitions:
            if attribute.selected:  # select attribute [boolean]
                for attribute_select_option in ['First', 'Last']:
                    if attribute_select_option != attribute_select and attribute_select != 'Both':
                        continue

                    key = str(attribute.attribute_key_modified)
                    if attribute_select == 'Both' and attribute.attribute_key_modified != '_distance' \
                            and attribute.attribute_key_modified != '_duration' \
                            and attribute.attribute_key_modified != '_speed':
                        if attribute_select_option == 'First':
                            key = 'a_' + key
                        elif attribute_select_option == 'Last':
                            key = 'b_' + key

                    if attribute.datatype == DataTypes.Integer:  # data type [Integer|Double|String]
                        attributes.append(QgsField(key, QVariant.Int, 'Integer'))
                    elif attribute.datatype == DataTypes.Double:
                        attributes.append(QgsField(key, QVariant.Double, 'Real'))
                    elif attribute.datatype == DataTypes.Boolean:
                        # QVariant.Bool is not available for QgsField
                        # attributes.append(QgsField(key, QVariant.Bool, 'Boolean'))
                        attributes.append(QgsField(key, QVariant.String, 'String'))
                    # elif attribute.datatype == DataTypes.Date:
                    #     attributes.append(QgsField(key, QVariant.DateTime, 'String'))
                    elif attribute.datatype == DataTypes.String:
                        attributes.append(QgsField(key, QVariant.String, 'String'))
        self.data_provider.addAttributes(attributes)
        self.vector_layer.updateFields()

    def add_feature(self, line_coordinates, attributes):
        feature = QgsFeature()
        feature.setGeometry(QgsGeometry.fromPolyline(line_coordinates))
        feature.setFields(self.vector_layer.fields(), True)
        for attribute_key in list(attributes.keys()):
            try:
                feature.setAttribute(attribute_key, attributes[attribute_key])
            except KeyError:
                pass
        self.data_provider.addFeatures([feature])

    def save_layer(self, output_directory, overwrite):
        self.vector_layer.commitChanges()

        self.error_message = ''

        if self.vector_layer.featureCount() > 0:
            self.vector_layer.updateExtents()

            # Write vector layer to file
            if output_directory is not None:
                if os.path.isdir(output_directory):
                    vector_layer_writer = VectorFileWriter(output_directory)
                    output_file_path = vector_layer_writer.write(self.vector_layer, overwrite)

                    if output_file_path is not None:
                        return QgsVectorLayer(output_file_path, os.path.basename(output_file_path), 'ogr')
                    else:
                        self.error_message = 'Writing vector layer failed...'
                        return None
                else:
                    self.error_message = 'Cannot find output directory'
                    return None

        return self.vector_layer
Ejemplo n.º 43
0
    def run(self):
        """Run the impact function.

        :returns: A new line layer with inundated roads marked.
        :type: safe_layer
        """
        self.validate()
        self.prepare()

        self.provenance.append_step(
            'Calculating Step', 'Impact function is calculating the impact.')

        # Thresholds for tsunami hazard zone breakdown.
        low_max = self.parameters['low_threshold'].value
        medium_max = self.parameters['medium_threshold'].value
        high_max = self.parameters['high_threshold'].value

        target_field = self.target_field
        # Get parameters from layer's keywords
        road_class_field = self.exposure.keyword('road_class_field')

        # reproject self.extent to the hazard projection
        hazard_crs = self.hazard.layer.crs()
        hazard_authid = hazard_crs.authid()

        if hazard_authid == 'EPSG:4326':
            viewport_extent = self.requested_extent
        else:
            geo_crs = QgsCoordinateReferenceSystem()
            geo_crs.createFromSrid(4326)
            viewport_extent = extent_to_geo_array(
                QgsRectangle(*self.requested_extent), geo_crs, hazard_crs)

        # Align raster extent and viewport
        # assuming they are both in the same projection
        raster_extent = self.hazard.layer.dataProvider().extent()
        clip_xmin = raster_extent.xMinimum()
        # clip_xmax = raster_extent.xMaximum()
        clip_ymin = raster_extent.yMinimum()
        # clip_ymax = raster_extent.yMaximum()
        if viewport_extent[0] > clip_xmin:
            clip_xmin = viewport_extent[0]
        if viewport_extent[1] > clip_ymin:
            clip_ymin = viewport_extent[1]

        height = ((viewport_extent[3] - viewport_extent[1]) /
                  self.hazard.layer.rasterUnitsPerPixelY())
        height = int(height)
        width = ((viewport_extent[2] - viewport_extent[0]) /
                 self.hazard.layer.rasterUnitsPerPixelX())
        width = int(width)

        raster_extent = self.hazard.layer.dataProvider().extent()
        xmin = raster_extent.xMinimum()
        xmax = raster_extent.xMaximum()
        ymin = raster_extent.yMinimum()
        ymax = raster_extent.yMaximum()

        x_delta = (xmax - xmin) / self.hazard.layer.width()
        x = xmin
        for i in range(self.hazard.layer.width()):
            if abs(x - clip_xmin) < x_delta:
                # We have found the aligned raster boundary
                break
            x += x_delta
            _ = i

        y_delta = (ymax - ymin) / self.hazard.layer.height()
        y = ymin
        for i in range(self.hazard.layer.width()):
            if abs(y - clip_ymin) < y_delta:
                # We have found the aligned raster boundary
                break
            y += y_delta
        clip_extent = [x, y, x + width * x_delta, y + height * y_delta]

        # Clip hazard raster
        small_raster = clip_raster(self.hazard.layer, width, height,
                                   QgsRectangle(*clip_extent))

        # Create vector features from the flood raster
        # For each raster cell there is one rectangular polygon
        # Data also get spatially indexed for faster operation
        ranges = OrderedDict()
        ranges[0] = [0.0, 0.0]
        ranges[1] = [0.0, low_max]
        ranges[2] = [low_max, medium_max]
        ranges[3] = [medium_max, high_max]
        ranges[4] = [high_max, None]

        index, flood_cells_map = _raster_to_vector_cells(
            small_raster, ranges, self.exposure.layer.crs())

        # Filter geometry and data using the extent
        ct = QgsCoordinateTransform(QgsCoordinateReferenceSystem("EPSG:4326"),
                                    self.exposure.layer.crs())
        extent = ct.transformBoundingBox(QgsRectangle(*self.requested_extent))
        request = QgsFeatureRequest()
        request.setFilterRect(extent)
        """
        if len(low_max_flood_cells_map) == 0 and \
            len(medium_max_flood_cells_map) == 0 and \
            len(high_max_flood_cells_map) == 0 and \
            len(high_min_flood_cells_map) == 0:
            message = tr(
                'There are no objects in the hazard layer with "value" > 0. '
                'Please check the value or use other extent.' % (
                    threshold_min, ))
            raise GetDataError(message)
        """

        # create template for the output layer
        line_layer_tmp = create_layer(self.exposure.layer)
        new_field = QgsField(target_field, QVariant.Int)
        line_layer_tmp.dataProvider().addAttributes([new_field])
        line_layer_tmp.updateFields()

        # create empty output layer and load it
        filename = unique_filename(suffix='.shp')
        QgsVectorFileWriter.writeAsVectorFormat(line_layer_tmp, filename,
                                                "utf-8", None,
                                                "ESRI Shapefile")
        line_layer = QgsVectorLayer(filename, "flooded roads", "ogr")

        # Do the heavy work - for each road get flood polygon for that area and
        # do the intersection/difference to find out which parts are flooded
        _intersect_lines_with_vector_cells(self.exposure.layer, request, index,
                                           flood_cells_map, line_layer,
                                           target_field)

        target_field_index = line_layer.dataProvider().\
            fieldNameIndex(target_field)

        # Generate simple impact report
        epsg = get_utm_epsg(self.requested_extent[0], self.requested_extent[1])
        output_crs = QgsCoordinateReferenceSystem(epsg)
        transform = QgsCoordinateTransform(self.exposure.layer.crs(),
                                           output_crs)

        # Roads breakdown
        self.road_lengths = OrderedDict()
        self.affected_road_categories = self.hazard_classes
        # Impacted roads breakdown
        self.affected_road_lengths = OrderedDict([
            (self.hazard_classes[0], {}),
            (self.hazard_classes[1], {}),
            (self.hazard_classes[2], {}),
            (self.hazard_classes[3], {}),
            (self.hazard_classes[4], {}),
        ])

        if line_layer.featureCount() < 1:
            raise ZeroImpactException()

        roads_data = line_layer.getFeatures()
        road_type_field_index = line_layer.fieldNameIndex(road_class_field)
        for road in roads_data:
            attributes = road.attributes()
            affected = attributes[target_field_index]
            hazard_zone = self.hazard_classes[affected]
            road_type = attributes[road_type_field_index]
            if road_type.__class__.__name__ == 'QPyNullVariant':
                road_type = tr('Other')
            geom = road.geometry()
            geom.transform(transform)
            length = geom.length()

            if road_type not in self.road_lengths:
                self.road_lengths[road_type] = 0

            if hazard_zone not in self.affected_road_lengths:
                self.affected_road_lengths[hazard_zone] = {}

            if road_type not in self.affected_road_lengths[hazard_zone]:
                self.affected_road_lengths[hazard_zone][road_type] = 0

            self.road_lengths[road_type] += length
            num_classes = len(self.hazard_classes)
            if attributes[target_field_index] in range(num_classes):
                self.affected_road_lengths[hazard_zone][road_type] += length

        impact_summary = self.html_report()

        # For printing map purpose
        map_title = tr('Roads inundated')
        legend_title = tr('Road inundated status')

        style_classes = [
            # FIXME 0 - 0.1
            dict(label=self.hazard_classes[0] + ': 0m',
                 value=0,
                 colour='#00FF00',
                 transparency=0,
                 size=1),
            dict(label=self.hazard_classes[1] + ': <0 - %.1f m' % low_max,
                 value=1,
                 colour='#FFFF00',
                 transparency=0,
                 size=1),
            dict(label=self.hazard_classes[2] + ': %.1f - %.1f m' %
                 (low_max + 0.1, medium_max),
                 value=2,
                 colour='#FFB700',
                 transparency=0,
                 size=1),
            dict(label=self.hazard_classes[3] + ': %.1f - %.1f m' %
                 (medium_max + 0.1, high_max),
                 value=3,
                 colour='#FF6F00',
                 transparency=0,
                 size=1),
            dict(label=self.hazard_classes[4] + ' > %.1f m' % high_max,
                 value=4,
                 colour='#FF0000',
                 transparency=0,
                 size=1),
        ]
        style_info = dict(target_field=target_field,
                          style_classes=style_classes,
                          style_type='categorizedSymbol')

        extra_keywords = {
            'impact_summary': impact_summary,
            'map_title': map_title,
            'legend_title': legend_title,
            'target_field': target_field
        }

        self.set_if_provenance()

        impact_layer_keywords = self.generate_impact_keywords(extra_keywords)

        # Convert QgsVectorLayer to inasafe layer and return it
        line_layer = Vector(data=line_layer,
                            name=tr('Flooded roads'),
                            keywords=impact_layer_keywords,
                            style_info=style_info)
        self._impact = line_layer
        return line_layer
Ejemplo n.º 44
0
    def testStartEditingCommitRollBack(self):

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

        # Layer A geopackage A
        d = QTemporaryDir()
        options = QgsVectorFileWriter.SaveVectorOptions()
        options.driverName = 'GPKG'
        options.layerName = 'layer_a'
        err, msg, newFileName, newLayer = QgsVectorFileWriter.writeAsVectorFormatV3(
            ml, os.path.join(d.path(), 'test_EditBufferGroup_A.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())

        # Layer B geopackage B
        options.layerName = 'layer_b'
        err, msg, newFileName, newLayer = QgsVectorFileWriter.writeAsVectorFormatV3(
            ml, os.path.join(d.path(), 'test_EditBufferGroup_B.gpkg'),
            QgsCoordinateTransformContext(), options)

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

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

        self.assertTrue(layer_b.isValid())

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

        project = QgsProject()
        project.addMapLayers([layer_a, layer_b, layer_c])
        project.setTransactionMode(Qgis.TransactionMode.BufferedGroups)

        editBufferGroup = project.editBufferGroup()

        # Check layers in group
        self.assertIn(layer_a, editBufferGroup.layers())
        self.assertIn(layer_b, editBufferGroup.layers())
        self.assertIn(layer_c, editBufferGroup.layers())

        self.assertFalse(editBufferGroup.isEditing())

        self.assertTrue(editBufferGroup.startEditing())
        self.assertTrue(editBufferGroup.isEditing())
        self.assertTrue(layer_a.editBuffer())
        self.assertTrue(layer_b.editBuffer())
        self.assertTrue(layer_c.editBuffer())
        self.assertEqual(len(editBufferGroup.modifiedLayers()), 0)

        commitErrors = []
        self.assertTrue(editBufferGroup.commitChanges(commitErrors, False))
        self.assertTrue(editBufferGroup.isEditing())
        self.assertTrue(editBufferGroup.commitChanges(commitErrors, True))
        self.assertFalse(editBufferGroup.isEditing())

        self.assertTrue(editBufferGroup.startEditing())
        self.assertTrue(editBufferGroup.isEditing())

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

        # Check feature in layer edit buffer but not in provider till commit
        self.assertEqual(layer_a.featureCount(), 1)
        self.assertEqual(layer_a.dataProvider().featureCount(), 0)

        rollbackErrors = []
        self.assertTrue(editBufferGroup.rollBack(rollbackErrors, False))
        self.assertTrue(editBufferGroup.isEditing())
        self.assertEqual(layer_a.featureCount(), 0)

        self.assertTrue(layer_a.addFeatures([f]))
        self.assertEqual(layer_a.featureCount(), 1)
        self.assertEqual(layer_a.dataProvider().featureCount(), 0)

        self.assertTrue(editBufferGroup.commitChanges(commitErrors, True))
        self.assertFalse(editBufferGroup.isEditing())
        self.assertEqual(layer_a.featureCount(), 1)
        self.assertEqual(layer_a.dataProvider().featureCount(), 1)
Ejemplo n.º 45
0
    def __createCtrlLayers(self, requete):
        """
        Création des couches de contrôles
        - selon une requête SQL dans la base de données (choix  ou des contrôle par l'utilisateur)
        - selon une zone géographique définie par l'utilisateur
        :param requete: liste des requêtes
        """

        self.__iface.messageBar().clearWidgets()
        progressMessageBar = self.__iface.messageBar()
        # ajout d'une barre de progression pour voir le chargement progressif des couches
        progress = QProgressBar()
        progress.setMaximum(100)
        progressMessageBar.pushWidget(progress)

        # récupérer la géométrie définie par l'utilisateur pour l'utiliser dans les requêtes SQL
        # conversion en géométrie binaire et dans le bon système de coordonnée)
        self.__crs = self.__iface.mapCanvas().mapSettings().destinationCrs(
        ).postgisSrid()
        # défintion du système de coordonnées en sortie (par défaut 21781), récupérer des paramètres du projets
        bbox = "(SELECT ST_GeomFromText('" + self.geom.exportToWkt(
        ) + "'," + str(self.__crs) + "))"

        # paramètres de la source des couches à ajouter au projet
        uri = QgsDataSourceURI()
        uri.setConnection(self.__db.hostName(), str(self.__db.port()),
                          self.__db.databaseName(), self.__db.userName(),
                          self.__db.password())
        uri.setSrid(str(self.__crs))
        outputLayers = [
        ]  # listes des couches de résultats à charger dans le projet
        styleLayers = []  # listes des styles de couches (fichier qml)
        i = 0
        totalError = 0  # décompte des erreurs détectées (nombre d'objets dans chaque couche)
        for name in requete:
            for q in self.__layerCfgControl.getFeatures(
                    QgsFeatureRequest(int(name))):
                query_fct = q["sql_function"]
                query_fct = query_fct.replace("bbox", bbox)
                geom_type = QgsWKBTypes.parseType(q["geom_type"])
                # récupérer le type de géométrie QGIS "QgsWKBTypes" depuis un type de géométrie WKT Postgis
                uri.setWkbType(geom_type)
                uri.setDataSource('', query_fct, q["geom_name"], "",
                                  q["key_attribute"])
                layer = QgsVectorLayer(uri.uri(), q["layer_name"], "postgres")

                totalError = totalError + layer.featureCount()
                if layer.featureCount() > 0:
                    outputLayers.append(layer)
                    styleLayers.append(str(q["layer_style"]))
            percent = (
                float(i + 1.0) / float(len(requete))
            ) * 100  # Faire évoluer la barre de progression du traitement
            progress.setValue(percent)
            i += 1
        if len(outputLayers) > 0:
            self.__addCtrlLayers(outputLayers, styleLayers)
            self.__iface.messageBar().clearWidgets()
            self.__iface.messageBar().pushMessage(
                "Info",
                QCoreApplication.translate(
                    "VDLTools",
                    "All layers have been charged with success in the projet. |"
                ) + QCoreApplication.translate("VDLTools", "Total errors : ") +
                str(totalError),
                level=QgsMessageBar.INFO,
                duration=10)
        else:
            self.__iface.messageBar().clearWidgets()
            self.__iface.messageBar().pushMessage(
                "Info",
                QCoreApplication.translate(
                    "VDLTools",
                    "Good !! No error detected on the defined area"),
                level=QgsMessageBar.INFO,
                duration=5)
Ejemplo n.º 46
0
    def testWFSGetOnlyFeaturesInViewExtent(self):
        """Test 'get only features in view extent' """

        endpoint = self.__class__.basetestpath + '/fake_qgis_http_endpoint_only_features_in_view_extent'

        with open(
                sanitize(
                    endpoint,
                    '?SERVICE=WFS?REQUEST=GetCapabilities?ACCEPTVERSIONS=2.0.0,1.1.0,1.0.0'
                ), 'wb') as f:
            f.write("""
<wfs:WFS_Capabilities version="1.1.0" xmlns="http://www.opengis.net/wfs" xmlns:wfs="http://www.opengis.net/wfs" xmlns:ogc="http://www.opengis.net/ogc" xmlns:ows="http://www.opengis.net/ows" xmlns:gml="http://schemas.opengis.net/gml">
  <ows:OperationsMetadata>
    <ows:Operation name="GetFeature">
      <ows:Parameter name="resultType">
        <ows:Value>results</ows:Value>
        <ows:Value>hits</ows:Value>
      </ows:Parameter>
    </ows:Operation>
    <ows:Constraint name="DefaultMaxFeatures">
      <ows:Value>2</ows:Value>
    </ows:Constraint>
  </ows:OperationsMetadata>
  <FeatureTypeList>
    <FeatureType>
      <Name>my:typename</Name>
      <Title>Title</Title>
      <Abstract>Abstract</Abstract>
      <DefaultCRS>urn:ogc:def:crs:EPSG::4326</DefaultCRS>
      <ows:WGS84BoundingBox>
        <ows:LowerCorner>-80 60</ows:LowerCorner>
        <ows:UpperCorner>-50 80</ows:UpperCorner>
      </ows:WGS84BoundingBox>
    </FeatureType>
  </FeatureTypeList>
</wfs:WFS_Capabilities>""")

        with open(
                sanitize(
                    endpoint,
                    '?SERVICE=WFS&REQUEST=DescribeFeatureType&VERSION=1.1.0&TYPENAME=my:typename'
                ), 'wb') as f:
            f.write("""
<xsd:schema xmlns:my="http://my" xmlns:gml="http://www.opengis.net/gml" xmlns:xsd="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified" targetNamespace="http://my">
  <xsd:import namespace="http://www.opengis.net/gml"/>
  <xsd:complexType name="my:typenameType">
    <xsd:complexContent>
      <xsd:extension base="gml:AbstractFeatureType">
        <xsd:sequence>
          <xsd:element maxOccurs="1" minOccurs="0" name="id" nillable="true" type="xsd:int"/>
          <xsd:element maxOccurs="1" minOccurs="0" name="geometryProperty" nillable="true" type="gml:PointPropertyType"/>
        </xsd:sequence>
      </xsd:extension>
    </xsd:complexContent>
  </xsd:complexType>
  <xsd:element name="typename" substitutionGroup="gml:_Feature" type="my:typenameType"/>
</xsd:schema>
""")

        # Create test layer
        vl = QgsVectorLayer(
            u"url='http://" + endpoint +
            u"' typename='my:typename' retrictToRequestBBOX=1", u'test',
            u'WFS')
        assert vl.isValid()
        self.assertEquals(vl.wkbType(), QgsWKBTypes.Point)

        last_url = sanitize(
            endpoint,
            '?SERVICE=WFS&REQUEST=GetFeature&VERSION=1.1.0&TYPENAME=my:typename&MAXFEATURES=2&SRSNAME=urn:ogc:def:crs:EPSG::4326&BBOX=60,-70,80,-60'
        )
        with open(last_url, 'wb') as f:
            f.write("""
<wfs:FeatureCollection xmlns:wfs="http://www.opengis.net/wfs"
                       xmlns:gml="http://www.opengis.net/gml"
                       xmlns:my="http://my"
                       numberOfFeatures="1" timeStamp="2016-03-25T14:51:48.998Z">
  <gml:featureMembers>
    <my:typename gml:id="typename.200">
      <my:geometryProperty><gml:Point srsName="urn:ogc:def:crs:EPSG::4326"><gml:pos>70 -65</gml:pos></gml:Point></my:geometryProperty>
      <my:id>2</my:id>
    </my:typename>
  </gml:featureMembers>
</wfs:FeatureCollection>""")

        extent = QgsRectangle(-70, 60, -60, 80)
        request = QgsFeatureRequest().setFilterRect(extent)
        values = [f['id'] for f in vl.getFeatures(request)]
        self.assertEquals(values, [2])

        # To show that if we zoom-in, we won't issue a new request
        with open(last_url, 'wb') as f:
            f.write("""
<wfs:FeatureCollection xmlns:wfs="http://www.opengis.net/wfs"
                       xmlns:gml="http://www.opengis.net/gml"
                       xmlns:my="http://my"
                       numberOfFeatures="1" timeStamp="2016-03-25T14:51:48.998Z">
  <gml:featureMembers>
    <my:typename gml:id="typename.20000">
      <my:geometryProperty><gml:Point srsName="urn:ogc:def:crs:EPSG::4326"><gml:pos>70 -65</gml:pos></gml:Point></my:geometryProperty>
      <my:id>200</my:id>
    </my:typename>
  </gml:featureMembers>
</wfs:FeatureCollection>""")

        extent = QgsRectangle(-66, 62, -62, 78)
        request = QgsFeatureRequest().setFilterRect(extent)
        values = [f['id'] for f in vl.getFeatures(request)]
        self.assertEquals(values, [2])

        # Move to a neighbouring area, and reach the download limit
        last_url = sanitize(
            endpoint,
            '?SERVICE=WFS&REQUEST=GetFeature&VERSION=1.1.0&TYPENAME=my:typename&MAXFEATURES=2&SRSNAME=urn:ogc:def:crs:EPSG::4326&BBOX=65,-70,90,-60'
        )
        with open(last_url, 'wb') as f:
            f.write("""
<wfs:FeatureCollection xmlns:wfs="http://www.opengis.net/wfs"
                       xmlns:gml="http://www.opengis.net/gml"
                       xmlns:my="http://my"
                       numberOfFeatures="1" timeStamp="2016-03-25T14:51:48.998Z">
  <gml:featureMembers>
    <my:typename gml:id="typename.200">
      <my:geometryProperty><gml:Point srsName="urn:ogc:def:crs:EPSG::4326"><gml:pos>70 -65</gml:pos></gml:Point></my:geometryProperty>
      <my:id>2</my:id>
    </my:typename>
    <my:typename gml:id="typename.300">
      <my:geometryProperty><gml:Point srsName="urn:ogc:def:crs:EPSG::4326"><gml:pos>85 -65</gml:pos></gml:Point></my:geometryProperty>
      <my:id>3</my:id>
    </my:typename>
  </gml:featureMembers>
</wfs:FeatureCollection>""")

        extent = QgsRectangle(-70, 65, -60, 90)
        request = QgsFeatureRequest().setFilterRect(extent)
        values = [f['id'] for f in vl.getFeatures(request)]
        self.assertEquals(values, [2, 3])

        # Zoom-in again, and bring more features
        last_url = sanitize(
            endpoint,
            '?SERVICE=WFS&REQUEST=GetFeature&VERSION=1.1.0&TYPENAME=my:typename&MAXFEATURES=2&SRSNAME=urn:ogc:def:crs:EPSG::4326&BBOX=66,-69,89,-61'
        )
        with open(last_url, 'wb') as f:
            f.write("""
<wfs:FeatureCollection xmlns:wfs="http://www.opengis.net/wfs"
                       xmlns:gml="http://www.opengis.net/gml"
                       xmlns:my="http://my"
                       numberOfFeatures="1" timeStamp="2016-03-25T14:51:48.998Z">
  <gml:featureMembers>
    <my:typename gml:id="typename.200">
      <my:geometryProperty><gml:Point srsName="urn:ogc:def:crs:EPSG::4326"><gml:pos>70 -65</gml:pos></gml:Point></my:geometryProperty>
      <my:id>2</my:id>
    </my:typename>
    <my:typename gml:id="typename.400">
      <my:geometryProperty><gml:Point srsName="urn:ogc:def:crs:EPSG::4326"><gml:pos>84 -64</gml:pos></gml:Point></my:geometryProperty>
      <my:id>4</my:id>
    </my:typename>
  </gml:featureMembers>
</wfs:FeatureCollection>""")

        extent = QgsRectangle(-69, 66, -61, 89)
        request = QgsFeatureRequest().setFilterRect(extent)
        values = [f['id'] for f in vl.getFeatures(request)]
        self.assertEquals(values, [2, 3, 4])

        # Test RESULTTYPE=hits
        last_url = sanitize(
            endpoint,
            '?SERVICE=WFS&REQUEST=GetFeature&VERSION=1.1.0&TYPENAME=my:typename&RESULTTYPE=hits'
        )
        with open(last_url, 'wb') as f:
            f.write("""
<wfs:FeatureCollection xmlns:wfs="http://www.opengis.net/wfs"
                       numberOfFeatures="10" timeStamp="2016-03-25T14:51:48.998Z"/>"""
                    )

        self.assertEquals(vl.featureCount(), 10)

        # Combine BBOX and FILTER
        last_url = sanitize(
            endpoint,
            """?SERVICE=WFS&REQUEST=GetFeature&VERSION=1.1.0&TYPENAME=my:typename&MAXFEATURES=2&SRSNAME=urn:ogc:def:crs:EPSG::4326&FILTER=<ogc:Filter xmlns:ogc="http://www.opengis.net/ogc" xmlns:gml="http://www.opengis.net/gml">
 <ogc:And>
  <ogc:BBOX>
   <ogc:PropertyName>geometryProperty</ogc:PropertyName>
   <gml:Envelope srsName="urn:ogc:def:crs:EPSG::4326">
    <gml:lowerCorner>66 -69</gml:lowerCorner>
    <gml:upperCorner>89 -61</gml:upperCorner>
   </gml:Envelope>
  </ogc:BBOX>
  <ogc:PropertyIsEqualTo xmlns:ogc="http://www.opengis.net/ogc">
   <ogc:PropertyName xmlns:ogc="http://www.opengis.net/ogc">id</ogc:PropertyName>
   <ogc:Literal xmlns:ogc="http://www.opengis.net/ogc">101</ogc:Literal>
  </ogc:PropertyIsEqualTo>
 </ogc:And>
</ogc:Filter>
""")
        with open(last_url, 'wb') as f:
            f.write("""
<wfs:FeatureCollection xmlns:wfs="http://www.opengis.net/wfs"
                       xmlns:gml="http://www.opengis.net/gml"
                       xmlns:my="http://my"
                       numberOfFeatures="1" timeStamp="2016-03-25T14:51:48.998Z">
  <gml:featureMembers>
    <my:typename gml:id="typename.101">
      <my:geometryProperty><gml:Point srsName="urn:ogc:def:crs:EPSG::4326"><gml:pos>70 -65</gml:pos></gml:Point></my:geometryProperty>
      <my:id>101</my:id>
    </my:typename>
  </gml:featureMembers>
</wfs:FeatureCollection>""")

        vl.dataProvider().setSubsetString('id = 101')
        extent = QgsRectangle(-69, 66, -61, 89)
        request = QgsFeatureRequest().setFilterRect(extent)
        values = [f['id'] for f in vl.getFeatures(request)]
        self.assertEquals(values, [101])
Ejemplo n.º 47
0
    def accept(self):
        """Do PetaBencana download and display it in QGIS.

        .. versionadded: 3.3
        """

        self.save_state()
        try:
            self.require_directory()
        except CanceledImportDialogError:
            return

        QtGui.qApp.setOverrideCursor(QtGui.QCursor(QtCore.Qt.WaitCursor))

        source = self.define_url()
        # save the file as json first
        name = 'jakarta_flood.json'
        output_directory = self.output_directory.text()
        output_prefix = self.filename_prefix.text()
        overwrite = self.overwrite_flag.isChecked()
        date_stamp_flag = self.include_date_flag.isChecked()
        output_base_file_path = self.get_output_base_path(
            output_directory, output_prefix, date_stamp_flag, name, overwrite)

        title = self.tr("Can't access API")

        try:
            self.download(source, output_base_file_path)

            # Open downloaded file as QgsMapLayer
            layer = QgsVectorLayer(output_base_file_path, 'flood', 'ogr',
                                   False)
        except Exception as e:
            disable_busy_cursor()
            QMessageBox.critical(self, title, str(e))
            return

        self.time_stamp = time.strftime('%d-%b-%Y %H:%M:%S')
        # Now save as shp
        name = 'jakarta_flood.shp'
        output_base_file_path = self.get_output_base_path(
            output_directory, output_prefix, date_stamp_flag, name, overwrite)
        QgsVectorFileWriter.writeAsVectorFormat(layer, output_base_file_path,
                                                'CP1250', None,
                                                'ESRI Shapefile')
        # Get rid of the GeoJSON layer and rather use local shp
        del layer

        self.copy_style(output_base_file_path)

        self.copy_keywords(output_base_file_path)
        layer = self.add_flooded_field(output_base_file_path)

        # check if the layer has feature or not
        if layer.featureCount() <= 0:
            city = self.city_combo_box.currentText()
            message = self.tr('There are no floods data available on {city} '
                              'at this time.').format(city=city)
            display_warning_message_box(self, self.tr('No data'), message)
            disable_busy_cursor()
        else:
            # add the layer to the map
            registry = QgsMapLayerRegistry.instance()
            registry.addMapLayer(layer)
            disable_busy_cursor()
            self.done(QDialog.Accepted)
Ejemplo n.º 48
0
    def processAlgorithm(self, progress):
        inLayers = self.getParameterValue(self.LAYERS)
        paths = inLayers.split(';')

        layers = []
        fields = QgsFields()
        totalFeatureCount = 0
        for x in range(len(paths)):
            layer = QgsVectorLayer(paths[x], str(x), 'ogr')

            if (len(layers) > 0):
                if (layer.wkbType() != layers[0].wkbType()):
                    raise GeoAlgorithmExecutionException(
                        self.tr('All layers must have same geometry type!'))

            layers.append(layer)
            totalFeatureCount += layer.featureCount()

            for sindex, sfield in enumerate(layer.fields()):
                found = None
                for dfield in fields:
                    if (dfield.name().upper() == sfield.name().upper()):
                        found = dfield
                        if (dfield.type() != sfield.type()):
                            raise GeoAlgorithmExecutionException(
                                self.tr('{} field in layer {} has different '
                                        'data type than in other layers.'))

                if not found:
                    fields.append(sfield)

        total = 100.0 / totalFeatureCount
        writer = self.getOutputFromName(self.OUTPUT).getVectorWriter(
            fields.toList(), layers[0].wkbType(), layers[0].crs())

        featureCount = 0
        for layer in layers:
            for feature in layer.getFeatures():
                sattributes = feature.attributes()
                dattributes = []
                for dindex, dfield in enumerate(fields):
                    if (dfield.type() == QVariant.Int, QVariant.UInt,
                            QVariant.LongLong, QVariant.ULongLong):
                        dattribute = 0
                    elif (dfield.type() == QVariant.Double):
                        dattribute = 0.0
                    else:
                        dattribute = ''

                    for sindex, sfield in enumerate(layer.fields()):
                        if (sfield.name().upper() == dfield.name().upper()):
                            if (sfield.type() != dfield.type()):
                                raise GeoAlgorithmExecutionException(
                                    self.tr('Attribute type mismatch'))
                            dattribute = sattributes[sindex]
                            break

                    dattributes.append(dattribute)

                feature.setAttributes(dattributes)
                writer.addFeature(feature)
                featureCount += 1
                progress.setPercentage(int(featureCount * total))

        del writer
Ejemplo n.º 49
0
    def run(self):
        """Run the impact function.

        :returns: A new line layer with inundated roads marked.
        :type: safe_layer
        """
        self.validate()
        self.prepare()

        target_field = self.target_field
        # Get parameters from layer's keywords
        road_class_field = self.exposure.keyword('road_class_field')
        # Get parameters from IF parameter
        threshold_min = self.parameters['min threshold'].value
        threshold_max = self.parameters['max threshold'].value

        if threshold_min > threshold_max:
            message = tr(
                'The minimal threshold is greater than the maximal specified '
                'threshold. Please check the values.')
            raise GetDataError(message)

        # reproject self.extent to the hazard projection
        hazard_crs = self.hazard.layer.crs()
        hazard_authid = hazard_crs.authid()

        if hazard_authid == 'EPSG:4326':
            viewport_extent = self.requested_extent
        else:
            geo_crs = QgsCoordinateReferenceSystem()
            geo_crs.createFromSrid(4326)
            viewport_extent = extent_to_geo_array(
                QgsRectangle(*self.requested_extent), geo_crs, hazard_crs)

        # Align raster extent and viewport
        # assuming they are both in the same projection
        raster_extent = self.hazard.layer.dataProvider().extent()
        clip_xmin = raster_extent.xMinimum()
        # clip_xmax = raster_extent.xMaximum()
        clip_ymin = raster_extent.yMinimum()
        # clip_ymax = raster_extent.yMaximum()
        if viewport_extent[0] > clip_xmin:
            clip_xmin = viewport_extent[0]
        if viewport_extent[1] > clip_ymin:
            clip_ymin = viewport_extent[1]
        # TODO: Why have these two clauses when they are not used?
        # Commenting out for now.
        # if viewport_extent[2] < clip_xmax:
        #     clip_xmax = viewport_extent[2]
        # if viewport_extent[3] < clip_ymax:
        #     clip_ymax = viewport_extent[3]

        height = ((viewport_extent[3] - viewport_extent[1]) /
                  self.hazard.layer.rasterUnitsPerPixelY())
        height = int(height)
        width = ((viewport_extent[2] - viewport_extent[0]) /
                 self.hazard.layer.rasterUnitsPerPixelX())
        width = int(width)

        raster_extent = self.hazard.layer.dataProvider().extent()
        xmin = raster_extent.xMinimum()
        xmax = raster_extent.xMaximum()
        ymin = raster_extent.yMinimum()
        ymax = raster_extent.yMaximum()

        x_delta = (xmax - xmin) / self.hazard.layer.width()
        x = xmin
        for i in range(self.hazard.layer.width()):
            if abs(x - clip_xmin) < x_delta:
                # We have found the aligned raster boundary
                break
            x += x_delta
            _ = i

        y_delta = (ymax - ymin) / self.hazard.layer.height()
        y = ymin
        for i in range(self.hazard.layer.width()):
            if abs(y - clip_ymin) < y_delta:
                # We have found the aligned raster boundary
                break
            y += y_delta
        clip_extent = [x, y, x + width * x_delta, y + height * y_delta]

        # Clip hazard raster
        small_raster = clip_raster(self.hazard.layer, width, height,
                                   QgsRectangle(*clip_extent))

        # Create vector features from the flood raster
        # For each raster cell there is one rectangular polygon
        # Data also get spatially indexed for faster operation
        index, flood_cells_map = _raster_to_vector_cells(
            small_raster, threshold_min, threshold_max,
            self.exposure.layer.crs())

        # Filter geometry and data using the extent
        ct = QgsCoordinateTransform(QgsCoordinateReferenceSystem("EPSG:4326"),
                                    self.exposure.layer.crs())
        extent = ct.transformBoundingBox(QgsRectangle(*self.requested_extent))
        request = QgsFeatureRequest()
        request.setFilterRect(extent)

        if len(flood_cells_map) == 0:
            message = tr(
                'There are no objects in the hazard layer with "value" > %s. '
                'Please check the value or use other extent.' %
                (threshold_min, ))
            raise GetDataError(message)

        # create template for the output layer
        line_layer_tmp = create_layer(self.exposure.layer)
        new_field = QgsField(target_field, QVariant.Int)
        line_layer_tmp.dataProvider().addAttributes([new_field])
        line_layer_tmp.updateFields()

        # create empty output layer and load it
        filename = unique_filename(suffix='.shp')
        QgsVectorFileWriter.writeAsVectorFormat(line_layer_tmp, filename,
                                                "utf-8", None,
                                                "ESRI Shapefile")
        line_layer = QgsVectorLayer(filename, "flooded roads", "ogr")

        # Do the heavy work - for each road get flood polygon for that area and
        # do the intersection/difference to find out which parts are flooded
        _intersect_lines_with_vector_cells(self.exposure.layer, request, index,
                                           flood_cells_map, line_layer,
                                           target_field)

        target_field_index = line_layer.dataProvider().\
            fieldNameIndex(target_field)

        # Generate simple impact report
        epsg = get_utm_epsg(self.requested_extent[0], self.requested_extent[1])
        output_crs = QgsCoordinateReferenceSystem(epsg)
        transform = QgsCoordinateTransform(self.exposure.layer.crs(),
                                           output_crs)
        flooded_keyword = tr('Flooded in the threshold (m)')
        self.affected_road_categories = [flooded_keyword]
        self.affected_road_lengths = OrderedDict([(flooded_keyword, {})])
        self.road_lengths = OrderedDict()

        if line_layer.featureCount() < 1:
            raise ZeroImpactException()

        roads_data = line_layer.getFeatures()
        road_type_field_index = line_layer.fieldNameIndex(road_class_field)
        for road in roads_data:
            attributes = road.attributes()
            road_type = attributes[road_type_field_index]
            if road_type.__class__.__name__ == 'QPyNullVariant':
                road_type = tr('Other')
            geom = road.geometry()
            geom.transform(transform)
            length = geom.length()

            if road_type not in self.road_lengths:
                self.affected_road_lengths[flooded_keyword][road_type] = 0
                self.road_lengths[road_type] = 0

            self.road_lengths[road_type] += length
            if attributes[target_field_index] == 1:
                self.affected_road_lengths[flooded_keyword][
                    road_type] += length

        impact_summary = self.html_report()

        # For printing map purpose
        map_title = tr('Roads inundated')
        legend_title = tr('Road inundated status')

        style_classes = [
            dict(label=tr('Not Inundated'),
                 value=0,
                 colour='#1EFC7C',
                 transparency=0,
                 size=0.5),
            dict(label=tr('Inundated'),
                 value=1,
                 colour='#F31A1C',
                 transparency=0,
                 size=0.5)
        ]
        style_info = dict(target_field=target_field,
                          style_classes=style_classes,
                          style_type='categorizedSymbol')

        # Convert QgsVectorLayer to inasafe layer and return it
        line_layer = Vector(data=line_layer,
                            name=tr('Flooded roads'),
                            keywords={
                                'impact_summary': impact_summary,
                                'map_title': map_title,
                                'legend_title': legend_title,
                                'target_field': target_field
                            },
                            style_info=style_info)
        self._impact = line_layer
        return line_layer
class TestQgsVectorLayerFeatureCounter(unittest.TestCase):
    def setUp(self):

        self.vl = QgsVectorLayer(
            'Point?crs=epsg:4326&field=pk:integer&field=cnt:integer&field=name:string(0)&field=name2:string(0)&field=num_char:string&field=dt:datetime&field=date:date&field=time:time&key=pk',
            'test', 'memory')
        assert (self.vl.isValid())

        f1 = QgsFeature(5)
        f1.setAttributes([
            5, -200, NULL, 'NuLl', '5',
            QDateTime(QDate(2020, 5, 4), QTime(12, 13, 14)),
            QDate(2020, 5, 2),
            QTime(12, 13, 1)
        ])
        f1.setGeometry(QgsGeometry.fromWkt('Point (-71.123 78.23)'))

        f2 = QgsFeature(3)
        f2.setAttributes([3, 300, 'Pear', 'PEaR', '3', NULL, NULL, NULL])

        f3 = QgsFeature(1)
        f3.setAttributes([
            1, 100, 'Orange', 'oranGe', '1',
            QDateTime(QDate(2020, 5, 3), QTime(12, 13, 14)),
            QDate(2020, 5, 3),
            QTime(12, 13, 14)
        ])
        f3.setGeometry(QgsGeometry.fromWkt('Point (-70.332 66.33)'))

        f4 = QgsFeature(2)
        f4.setAttributes([
            2, 200, 'Apple', 'Apple', '2',
            QDateTime(QDate(2020, 5, 4), QTime(12, 14, 14)),
            QDate(2020, 5, 4),
            QTime(12, 14, 14)
        ])
        f4.setGeometry(QgsGeometry.fromWkt('Point (-68.2 70.8)'))

        f5 = QgsFeature(4)
        f5.setAttributes([
            4, 400, 'Honey', 'Honey', '4',
            QDateTime(QDate(2021, 5, 4), QTime(13, 13, 14)),
            QDate(2021, 5, 4),
            QTime(13, 13, 14)
        ])
        f5.setGeometry(QgsGeometry.fromWkt('Point (-65.32 78.3)'))

        assert self.vl.dataProvider().addFeatures([f1, f2, f3, f4, f5])

        self.vl2 = QgsVectorLayer(
            'Point?crs=epsg:4326&field=pk:integer&field=cnt:integer&field=name:string(0)&field=name2:string(0)&field=num_char:string&field=dt:datetime&field=date:date&field=time:time&key=pk',
            'test', 'memory')
        assert (self.vl2.isValid())

    def tearDown(self):
        del self.vl
        del self.vl2

    def testFeaturesCount(self):

        self.assertTrue(self.vl.renderer().legendSymbolItems())

        signal_spy = QSignalSpy(self.vl.symbolFeatureCountMapChanged)
        self.vl.countSymbolFeatures()
        signal_spy.wait()

        self.assertEqual(len(signal_spy), 1)
        self.assertEqual(
            self.vl.featureCount(
                self.vl.renderer().legendSymbolItems()[0].ruleKey()), 5)

    def testFeaturesCountOnEmptyLayer(self):

        self.assertTrue(self.vl2.renderer().legendSymbolItems())

        signal_spy = QSignalSpy(self.vl2.symbolFeatureCountMapChanged)
        self.vl2.countSymbolFeatures()
        signal_spy.wait()

        self.assertEqual(len(signal_spy), 1)
        self.assertEqual(
            self.vl2.featureCount(
                self.vl2.renderer().legendSymbolItems()[0].ruleKey()), 0)
Ejemplo n.º 51
0
    def processAlgorithm(self, parameters, context, feedback):
        layers = self.parameterAsLayerList(parameters, self.INPUT_DATASOURCES,
                                           context)
        query = self.parameterAsString(parameters, self.INPUT_QUERY, context)
        uid_field = self.parameterAsString(parameters, self.INPUT_UID_FIELD,
                                           context)
        geometry_field = self.parameterAsString(parameters,
                                                self.INPUT_GEOMETRY_FIELD,
                                                context)
        geometry_type = self.parameterAsEnum(parameters,
                                             self.INPUT_GEOMETRY_TYPE, context)
        geometry_crs = self.parameterAsCrs(parameters, self.INPUT_GEOMETRY_CRS,
                                           context)

        df = QgsVirtualLayerDefinition()
        for layerIdx, layer in enumerate(layers):
            df.addSource('input{}'.format(layerIdx + 1), layer.id())

        if query == '':
            raise QgsProcessingException(
                self.
                tr('Empty SQL. Please enter valid SQL expression and try again.'
                   ))
        else:
            localContext = self.createExpressionContext(parameters, context)
            expandedQuery = QgsExpression.replaceExpressionText(
                query, localContext)
            df.setQuery(expandedQuery)

        if uid_field:
            df.setUid(uid_field)

        if geometry_type == 1:  # no geometry
            df.setGeometryWkbType(QgsWkbTypes.NoGeometry)
        else:
            if geometry_field:
                df.setGeometryField(geometry_field)
            if geometry_type > 1:
                df.setGeometryWkbType(geometry_type - 1)
            if geometry_crs.isValid():
                df.setGeometrySrid(geometry_crs.postgisSrid())

        vLayer = QgsVectorLayer(df.toString(), "temp_vlayer", "virtual")
        if not vLayer.isValid():
            raise QgsProcessingException(
                vLayer.dataProvider().error().message())

        (sink, dest_id) = self.parameterAsSink(
            parameters, self.OUTPUT, context, vLayer.fields(),
            vLayer.wkbType() if geometry_type != 1 else 1, vLayer.crs())
        if sink is None:
            raise QgsProcessingException(
                self.invalidSinkError(parameters, self.OUTPUT))

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

            sink.addFeature(inFeat, QgsFeatureSink.FastInsert)
            feedback.setProgress(int(current * total))
        return {self.OUTPUT: dest_id}
Ejemplo n.º 52
0
    def testWFS10(self):
        """Test WFS 1.0 read-only"""

        endpoint = self.__class__.basetestpath + '/fake_qgis_http_endpoint_WFS1.0'

        with open(
                sanitize(endpoint,
                         '?SERVICE=WFS?REQUEST=GetCapabilities?VERSION=1.0.0'),
                'wb') as f:
            f.write("""
<WFS_Capabilities version="1.0.0" xmlns="http://www.opengis.net/wfs" xmlns:ogc="http://www.opengis.net/ogc">
  <FeatureTypeList>
    <FeatureType>
      <Name>my:typename</Name>
      <Title>Title</Title>
      <Abstract>Abstract</Abstract>
      <SRS>EPSG:4326</SRS>
      <LatLongBoundingBox minx="-71.123" miny="66.33" maxx="-65.32" maxy="78.3"/>
    </FeatureType>
  </FeatureTypeList>
</WFS_Capabilities>""")

        with open(
                sanitize(
                    endpoint,
                    '?SERVICE=WFS&REQUEST=DescribeFeatureType&VERSION=1.0.0&TYPENAME=my:typename'
                ), 'wb') as f:
            f.write("""
<xsd:schema xmlns:my="http://my" xmlns:gml="http://www.opengis.net/gml" xmlns:xsd="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified" targetNamespace="http://my">
  <xsd:import namespace="http://www.opengis.net/gml"/>
  <xsd:complexType name="my:typenameType">
    <xsd:complexContent>
      <xsd:extension base="gml:AbstractFeatureType">
        <xsd:sequence>
          <xsd:element maxOccurs="1" minOccurs="0" name="INTFIELD" nillable="true" type="xsd:int"/>
          <xsd:element maxOccurs="1" minOccurs="0" name="GEOMETRY" nillable="true" type="xsd:int"/>
          <xsd:element maxOccurs="1" minOccurs="0" name="longfield" nillable="true" type="xsd:long"/>
          <xsd:element maxOccurs="1" minOccurs="0" name="stringfield" nillable="true" type="xsd:string"/>
          <xsd:element maxOccurs="1" minOccurs="0" name="geometryProperty" nillable="true" type="gml:PointPropertyType"/>
        </xsd:sequence>
      </xsd:extension>
    </xsd:complexContent>
  </xsd:complexType>
  <xsd:element name="typename" substitutionGroup="gml:_Feature" type="my:typenameType"/>
</xsd:schema>
""")

        vl = QgsVectorLayer(
            u"url='http://" + endpoint +
            u"' typename='my:typename' version='1.0.0'", u'test', u'WFS')
        assert vl.isValid()
        self.assertEquals(vl.wkbType(), QgsWKBTypes.Point)
        self.assertEquals(len(vl.fields()), 4)
        self.assertEquals(vl.featureCount(), 0)
        reference = QgsGeometry.fromRect(
            QgsRectangle(-71.123, 66.33, -65.32, 78.3))
        vl_extent = QgsGeometry.fromRect(vl.extent())
        assert QgsGeometry.compare(vl_extent.asPolygon(),
                                   reference.asPolygon(),
                                   0.00001), 'Expected {}, got {}'.format(
                                       reference.exportToWkt(),
                                       vl_extent.exportToWkt())

        with open(
                sanitize(
                    endpoint,
                    '?SERVICE=WFS&REQUEST=GetFeature&VERSION=1.0.0&TYPENAME=my:typename&SRSNAME=EPSG:4326'
                ), 'wb') as f:
            f.write("""
<wfs:FeatureCollection
                       xmlns:wfs="http://www.opengis.net/wfs"
                       xmlns:gml="http://www.opengis.net/gml"
                       xmlns:my="http://my">
  <gml:boundedBy><gml:null>unknown</gml:null></gml:boundedBy>
  <gml:featureMember>
    <my:typename fid="typename.0">
      <my:geometryProperty>
          <gml:Point srsName="http://www.opengis.net/gml/srs/epsg.xml#4326"><gml:coordinates decimal="." cs="," ts=" ">2,49</gml:coordinates></gml:Point></my:geometryProperty>
      <my:INTFIELD>1</my:INTFIELD>
      <my:GEOMETRY>2</my:GEOMETRY>
      <my:longfield>1234567890123</my:longfield>
      <my:stringfield>foo</my:stringfield>
    </my:typename>
  </gml:featureMember>
</wfs:FeatureCollection>""")

        values = [f['INTFIELD'] for f in vl.getFeatures()]
        self.assertEquals(values, [1])

        values = [f['GEOMETRY'] for f in vl.getFeatures()]
        self.assertEquals(values, [2])

        values = [f['longfield'] for f in vl.getFeatures()]
        self.assertEquals(values, [1234567890123])

        values = [f['stringfield'] for f in vl.getFeatures()]
        self.assertEquals(values, ['foo'])

        got = [f.geometry() for f in vl.getFeatures()][0].geometry()
        self.assertEquals((got.x(), got.y()), (2.0, 49.0))

        self.assertEquals(vl.featureCount(), 1)

        self.assertEquals(vl.dataProvider().capabilities(), 0)

        (ret, _) = vl.dataProvider().addFeatures([QgsFeature()])
        assert not ret

        assert not vl.dataProvider().deleteFeatures([0])
Ejemplo n.º 53
0
    def performRequestParcel(self, region, parcel):
        objectType = self.checkedFeatureType()
        self.crs = QgsProject.instance().crs().authid().split(":")[1]

        name = region + ' ' + parcel

        result = uldk_parcel.getParcelById(name, self.crs)
        if result is None:
            self.iface.messageBar().pushMessage(
                "Nie udało się pobrać obiektu:",
                'API nie zwróciło obiektu dla id %s' % name,
                level=Qgis.Critical,
                duration=10)
            return

        res = result.split("|")
        if res[0] == '':
            self.iface.messageBar().pushMessage(
                "Nie udało się pobrać obiektu:",
                'API nie zwróciło geometrii dla id %s' % name,
                level=Qgis.Critical,
                duration=10)
            return
        wkt = res[0]
        teryt = res[1]
        parcel = res[2]
        region = res[3]
        commune = res[4]
        county = res[5]
        voivodeship = res[6]
        # print(teryt, parcel, region, commune, county, voivodeship)

        # layer
        nazwa = self.nazwy_warstw[objectType]

        layers = QgsProject.instance().mapLayersByName(nazwa)
        geom = QgsGeometry().fromWkt(wkt)
        feat = QgsFeature()
        feat.setGeometry(geom)
        canvas = self.iface.mapCanvas()

        if layers:
            # jezeli istnieje to dodaj obiekt do warstwy
            layer = layers[0]
        else:
            # jezeli nie istnieje to stworz warstwe
            epsg = "Polygon?crs=EPSG:" + self.crs
            layer = QgsVectorLayer(epsg, nazwa, "memory")
            QgsProject.instance().addMapLayer(layer)

        box = feat.geometry().boundingBox()

        canvas.setExtent(box)
        provider = layer.dataProvider()
        provider.addFeature(feat)
        layer.updateExtents()
        canvas.refresh()

        counter = layer.featureCount()
        # add attributes
        if not layers:
            identyfikatorField = QgsField('identyfikator',
                                          QVariant.String,
                                          len=30)
            provider.addAttributes([identyfikatorField])

            voivField = QgsField('województwo', QVariant.String, len=30)
            provider.addAttributes([voivField])

            conField = QgsField('powiat', QVariant.String, len=30)
            provider.addAttributes([conField])

            comField = QgsField('gmina', QVariant.String, len=30)
            provider.addAttributes([comField])

            regField = QgsField('obręb', QVariant.String, len=30)
            provider.addAttributes([regField])
            layer.updateFields()

            parField = QgsField('numer', QVariant.String, len=30)
            provider.addAttributes([parField])
            layer.updateFields()

            layer.updateFields()
            counter = 1

        idx = layer.fields().indexFromName('identyfikator')
        attrMap = {counter: {idx: teryt}}
        provider.changeAttributeValues(attrMap)

        voiv = layer.fields().indexFromName('województwo')
        attrMap = {counter: {voiv: voivodeship}}
        provider.changeAttributeValues(attrMap)

        if parcel is not None:
            par = layer.fields().indexFromName('numer')
            attrMap = {counter: {par: parcel}}
            provider.changeAttributeValues(attrMap)

        if region is not None:
            reg = layer.fields().indexFromName('obręb')
            attrMap = {counter: {reg: region}}
            provider.changeAttributeValues(attrMap)
        if commune is not None:
            com = layer.fields().indexFromName('gmina')
            attrMap = {counter: {com: commune}}
            provider.changeAttributeValues(attrMap)

        if county is not None:
            con = layer.fields().indexFromName('powiat')
            attrMap = {counter: {con: county}}
            provider.changeAttributeValues(attrMap)

        self.iface.messageBar().pushMessage("Sukces:",
                                            'pobrano obrys obiektu %s' %
                                            (name),
                                            level=Qgis.Success,
                                            duration=10)
Ejemplo n.º 54
0
    def testTypeValidation(self):
        """Test that incompatible types in attributes raise errors"""

        vl = QgsVectorLayer('Point?crs=epsg:4326&field=int:integer', 'test',
                            'memory')
        self.assertTrue(vl.isValid())
        invalid = QgsFeature(vl.fields())
        invalid.setAttribute('int', 'A string')
        invalid.setGeometry(QgsGeometry.fromWkt('point(9 45)'))
        self.assertTrue(vl.startEditing())
        # Validation happens on commit
        self.assertTrue(vl.addFeatures([invalid]))
        self.assertFalse(vl.commitChanges())
        self.assertTrue(vl.rollBack())
        self.assertFalse(vl.hasFeatures())

        # Add a valid feature
        valid = QgsFeature(vl.fields())
        valid.setAttribute('int', 123)
        self.assertTrue(vl.startEditing())
        self.assertTrue(vl.addFeatures([valid]))
        self.assertTrue(vl.commitChanges())
        self.assertEqual(vl.featureCount(), 1)

        f = vl.getFeature(1)
        self.assertEqual(f.attribute('int'), 123)

        # Add both
        vl = QgsVectorLayer('Point?crs=epsg:4326&field=int:integer', 'test',
                            'memory')
        self.assertEqual(vl.featureCount(), 0)
        self.assertTrue(vl.startEditing())
        self.assertTrue(vl.addFeatures([valid, invalid]))
        self.assertFalse(vl.commitChanges())
        self.assertEqual(vl.featureCount(), 2)
        self.assertTrue(vl.rollBack())
        self.assertEqual(vl.featureCount(), 0)

        # Add both swapped
        vl = QgsVectorLayer('Point?crs=epsg:4326&field=int:integer', 'test',
                            'memory')
        self.assertTrue(vl.startEditing())
        self.assertTrue(vl.addFeatures([invalid, valid]))
        self.assertFalse(vl.commitChanges())
        self.assertEqual(vl.featureCount(), 2)
        self.assertTrue(vl.rollBack())
        self.assertEqual(vl.featureCount(), 0)

        # Change attribute value
        vl = QgsVectorLayer('Point?crs=epsg:4326&field=int:integer', 'test',
                            'memory')
        self.assertTrue(vl.startEditing())
        self.assertTrue(vl.addFeatures([valid]))
        self.assertTrue(vl.commitChanges())
        self.assertTrue(vl.startEditing())
        self.assertTrue(vl.changeAttributeValue(1, 0, 'A string'))
        self.assertFalse(vl.commitChanges())
        f = vl.getFeature(1)
        self.assertEqual(f.attribute('int'), 'A string')
        self.assertTrue(vl.rollBack())

        f = vl.getFeature(1)
        self.assertEqual(f.attribute('int'), 123)

        # Change attribute values
        vl = QgsVectorLayer('Point?crs=epsg:4326&field=int:integer', 'test',
                            'memory')
        self.assertTrue(vl.startEditing())
        self.assertTrue(vl.addFeatures([valid]))
        self.assertTrue(vl.commitChanges())
        self.assertTrue(vl.startEditing())
        self.assertTrue(vl.changeAttributeValues(1, {0: 'A string'}))
        self.assertFalse(vl.commitChanges())
        f = vl.getFeature(1)
        self.assertEqual(f.attribute('int'), 'A string')
        self.assertTrue(vl.rollBack())

        f = vl.getFeature(1)
        self.assertEqual(f.attribute('int'), 123)

        ##############################################
        # Test direct data provider calls

        # No rollback (old behavior)
        vl = QgsVectorLayer('Point?crs=epsg:4326&field=int:integer', 'test',
                            'memory')
        dp = vl.dataProvider()
        self.assertFalse(dp.addFeatures([valid, invalid])[0])
        self.assertEqual([f.attributes() for f in dp.getFeatures()], [[123]])
        f = vl.getFeature(1)
        self.assertEqual(f.attribute('int'), 123)

        # Roll back
        vl = QgsVectorLayer('Point?crs=epsg:4326&field=int:integer', 'test',
                            'memory')
        dp = vl.dataProvider()
        self.assertFalse(
            dp.addFeatures([valid, invalid],
                           QgsFeatureSink.RollBackOnErrors)[0])
        self.assertFalse(dp.hasFeatures())

        # Expected behavior for changeAttributeValues is to always roll back
        self.assertTrue(dp.addFeatures([valid])[0])
        self.assertFalse(dp.changeAttributeValues({1: {0: 'A string'}}))
        f = vl.getFeature(1)
        self.assertEqual(f.attribute('int'), 123)
Ejemplo n.º 55
0
    def testWFS20Paging(self):
        """Test WFS 2.0 paging"""

        endpoint = self.__class__.basetestpath + '/fake_qgis_http_endpoint_WFS_2.0_paging'

        with open(
                sanitize(
                    endpoint,
                    '?SERVICE=WFS?REQUEST=GetCapabilities?ACCEPTVERSIONS=2.0.0,1.1.0,1.0.0'
                ), 'wb') as f:
            f.write("""
<wfs:WFS_Capabilities version="2.0.0" xmlns="http://www.opengis.net/wfs/2.0" xmlns:wfs="http://www.opengis.net/wfs/2.0" xmlns:ows="http://www.opengis.net/ows/1.1" xmlns:gml="http://schemas.opengis.net/gml/3.2" xmlns:fes="http://www.opengis.net/fes/2.0" xmlns:xlink="http://www.w3.org/1999/xlink">
  <ows:OperationsMetadata>
    <ows:Operation name="GetFeature">
      <ows:Constraint name="CountDefault">
        <ows:NoValues/>
        <ows:DefaultValue>1</ows:DefaultValue>
      </ows:Constraint>
    </ows:Operation>
    <ows:Constraint name="ImplementsResultPaging">
      <ows:NoValues/>
      <ows:DefaultValue>TRUE</ows:DefaultValue>
    </ows:Constraint>
  </ows:OperationsMetadata>
  <FeatureTypeList>
    <FeatureType>
      <Name>my:typename</Name>
      <Title>Title</Title>
      <Abstract>Abstract</Abstract>
      <DefaultCRS>urn:ogc:def:crs:EPSG::4326</DefaultCRS>
      <ows:WGS84BoundingBox>
        <ows:LowerCorner>-71.123 66.33</ows:LowerCorner>
        <ows:UpperCorner>-65.32 78.3</ows:UpperCorner>
      </ows:WGS84BoundingBox>
    </FeatureType>
  </FeatureTypeList>
</wfs:WFS_Capabilities>""")

        with open(
                sanitize(
                    endpoint,
                    '?SERVICE=WFS&REQUEST=DescribeFeatureType&VERSION=2.0.0&TYPENAME=my:typename'
                ), 'wb') as f:
            f.write("""
<xsd:schema xmlns:my="http://my" xmlns:gml="http://www.opengis.net/gml/3.2" xmlns:xsd="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified" targetNamespace="http://my">
  <xsd:import namespace="http://www.opengis.net/gml/3.2"/>
  <xsd:complexType name="my:typenameType">
    <xsd:complexContent>
      <xsd:extension base="gml:AbstractFeatureType">
        <xsd:sequence>
          <xsd:element maxOccurs="1" minOccurs="0" name="id" nillable="true" type="xsd:int"/>
          <xsd:element maxOccurs="1" minOccurs="0" name="geometryProperty" nillable="true" type="gml:GeometryPropertyType"/>
        </xsd:sequence>
      </xsd:extension>
    </xsd:complexContent>
  </xsd:complexType>
  <xsd:element name="typename" substitutionGroup="gml:_Feature" type="my:typenameType"/>
</xsd:schema>
""")

        with open(
                sanitize(
                    endpoint,
                    '?SERVICE=WFS&REQUEST=GetFeature&VERSION=2.0.0&TYPENAMES=my:typename&STARTINDEX=0&COUNT=1&SRSNAME=urn:ogc:def:crs:EPSG::4326'
                ), 'wb') as f:
            f.write("""
<wfs:FeatureCollection xmlns:wfs="http://www.opengis.net/wfs/2.0"
                       xmlns:gml="http://www.opengis.net/gml/3.2"
                       xmlns:my="http://my"
                       numberMatched="2" numberReturned="1" timeStamp="2016-03-25T14:51:48.998Z">
  <wfs:member>
    <my:typename gml:id="typename.100">
      <my:geometryProperty><gml:Point srsName="urn:ogc:def:crs:EPSG::4326" gml:id="typename.geom.0"><gml:pos>66.33 -70.332</gml:pos></gml:Point></my:geometryProperty>
      <my:id>1</my:id>
    </my:typename>
  </wfs:member>
</wfs:FeatureCollection>""")

        # Create test layer
        vl = QgsVectorLayer(
            u"url='http://" + endpoint + u"' typename='my:typename'", u'test',
            u'WFS')
        assert vl.isValid()
        self.assertEquals(vl.wkbType(), QgsWKBTypes.Point)

        with open(
                sanitize(
                    endpoint,
                    '?SERVICE=WFS&REQUEST=GetFeature&VERSION=2.0.0&TYPENAMES=my:typename&STARTINDEX=1&COUNT=1&SRSNAME=urn:ogc:def:crs:EPSG::4326'
                ), 'wb') as f:
            f.write("""
<wfs:FeatureCollection xmlns:wfs="http://www.opengis.net/wfs/2.0"
                       xmlns:gml="http://www.opengis.net/gml/3.2"
                       xmlns:my="http://my"
                       numberMatched="2" numberReturned="1" timeStamp="2016-03-25T14:51:48.998Z">
  <wfs:member>
    <my:typename gml:id="typename.200">
      <my:geometryProperty><gml:Point srsName="urn:ogc:def:crs:EPSG::4326" gml:id="typename.geom.0"><gml:pos>66.33 -70.332</gml:pos></gml:Point></my:geometryProperty>
      <my:id>2</my:id>
    </my:typename>
  </wfs:member>
</wfs:FeatureCollection>""")

        with open(
                sanitize(
                    endpoint,
                    '?SERVICE=WFS&REQUEST=GetFeature&VERSION=2.0.0&TYPENAMES=my:typename&STARTINDEX=2&COUNT=1&SRSNAME=urn:ogc:def:crs:EPSG::4326'
                ), 'wb') as f:
            f.write("""
<wfs:FeatureCollection xmlns:wfs="http://www.opengis.net/wfs/2.0"
                       xmlns:gml="http://www.opengis.net/gml/3.2"
                       xmlns:my="http://my"
                       numberMatched="2" numberReturned="0" timeStamp="2016-03-25T14:51:48.998Z">
</wfs:FeatureCollection>""")

        values = [f['id'] for f in vl.getFeatures()]
        self.assertEquals(values, [1, 2])

        # Suppress GetFeature responses to demonstrate that the cache is used
        os.unlink(
            sanitize(
                endpoint,
                '?SERVICE=WFS&REQUEST=GetFeature&VERSION=2.0.0&TYPENAMES=my:typename&STARTINDEX=0&COUNT=1&SRSNAME=urn:ogc:def:crs:EPSG::4326'
            ))
        os.unlink(
            sanitize(
                endpoint,
                '?SERVICE=WFS&REQUEST=GetFeature&VERSION=2.0.0&TYPENAMES=my:typename&STARTINDEX=1&COUNT=1&SRSNAME=urn:ogc:def:crs:EPSG::4326'
            ))
        os.unlink(
            sanitize(
                endpoint,
                '?SERVICE=WFS&REQUEST=GetFeature&VERSION=2.0.0&TYPENAMES=my:typename&STARTINDEX=2&COUNT=1&SRSNAME=urn:ogc:def:crs:EPSG::4326'
            ))

        values = [f['id'] for f in vl.getFeatures()]
        self.assertEquals(values, [1, 2])

        # No need for hits since the download went to its end
        self.assertEquals(vl.featureCount(), 2)

        vl.dataProvider().reloadData()

        # Hits not working
        self.assertEquals(vl.featureCount(), 0)

        vl.dataProvider().reloadData()

        # Hits working
        with open(
                sanitize(
                    endpoint,
                    '?SERVICE=WFS&REQUEST=GetFeature&VERSION=2.0.0&TYPENAMES=my:typename&RESULTTYPE=hits'
                ), 'wb') as f:
            f.write("""
<wfs:FeatureCollection xmlns:wfs="http://www.opengis.net/wfs/2.0"
                       xmlns:gml="http://www.opengis.net/gml/3.2"
                       xmlns:my="http://my"
                       numberMatched="2" numberReturned="0" timeStamp="2016-03-25T14:51:48.998Z">
</wfs:FeatureCollection>""")
        self.assertEquals(vl.featureCount(), 2)
Ejemplo n.º 56
0
    # QGIS_PREFIX_PATH should be set if not run from install dir
    qgs = QgsApplication([], False)
    qgs.initQgis()

    django.setup(set_prefix=False)

    from djangoprovider import DjangoProvider, register_django_provider
    register_django_provider()

    from basic.models import *  # after django setup

    model = Point
    uri = '%s.%s' % (model._meta.app_label, model._meta.model_name)
    layer = QgsVectorLayer(uri, 'test', 'django')
    print('layer valid: %s' % layer.isValid())
    print('feature count: %s' % layer.featureCount())
    print('crs authid: %s' % layer.crs().authid())
    print('extent: %s' % layer.sourceExtent().toString())
    QgsProject.instance().addMapLayer(layer)

    image = QImage(QSize(600, 400), QImage.Format_ARGB32_Premultiplied)

    image.fill(QColor(255, 255, 128).rgb())

    painter = QPainter(image)

    settings = QgsMapSettings()
    settings.setOutputDpi(image.logicalDpiX())
    settings.setOutputImageFormat(QImage.Format_ARGB32)
    settings.setDestinationCrs(layer.crs())
    settings.setOutputSize(image.size())
Ejemplo n.º 57
0
class MissionTrack(QObject):
    mission_changed = pyqtSignal(int)
    step_removed = pyqtSignal(int)

    def __init__(self,
                 mission_name="Mission",
                 mission_filename=None,
                 mission_layer=None,
                 mission_renderer=None,
                 canvas=None):
        super(MissionTrack, self).__init__()
        self.mission_filename = mission_filename
        self.mission_name = mission_name
        self.mission_layer = mission_layer
        self.mission_renderer = mission_renderer
        self.mission = Mission()
        self.canvas = canvas
        self.start_end_marker = StartEndMarker(
            canvas, self.find_waypoints_in_mission(), QColor(200, 0, 0))

        self.saved = False
        self.modified = False

    def is_saved(self):
        """
        :return: return True if mission is saved,  otherwise False
        """
        return self.saved

    def is_modified(self):
        """
        :return: return True if mission is modified,  otherwise False
        """
        return self.modified

    def set_modified(self, modified):
        """ Set modified state"""
        self.modified = modified

    def load_mission(self, filename):
        """ Load mission with name 'filename'"""
        try:
            self.mission.load_mission(filename)
            self.mission_filename = filename
            self.update_start_end_markers()
            self.saved = True
            self.modifed = False
        except:
            logger.error("Invalid mission file")
            raise Exception("Invalid mission file")

    def set_mission(self, mission):
        """ Set Mission."""
        self.mission = mission

    def set_mission_filename(self, filename):
        """ Set Mission Filename"""
        self.mission_filename = filename

    def set_mission_name(self, name):
        """ Set Mission name."""
        self.mission_name = name

    def set_mission_layer(self, layer):
        """ Set mission layer."""
        self.mission_layer.name = self.mission_name
        self.mission_layer = layer

    def set_mission_renderer(self, renderer):
        """ Set mission renderer."""
        self.mission_renderer = renderer
        self.mission_layer.setRenderer(self.mission_renderer)

    def get_mission(self):
        """ Returns the mission"""
        return self.mission

    def get_step(self, step):
        """ Returns the step 'step' of the mission"""
        return self.mission.get_step(step)

    def get_mission_length(self):
        """ Returns mission length"""
        return self.mission.num_steps

    def get_mission_layer(self):
        """ Returns mission layer"""
        return self.mission_layer

    def get_mission_name(self):
        """ Returns mission name"""
        return self.mission_name

    def get_mission_filename(self):
        """ Returns mission filename"""
        return self.mission_filename

    def copy_mission(self):
        """ Returns a copy of the current mission"""
        return copy.deepcopy(self.mission)

    def change_position(self, wp_id, point):
        """
        Changes a position of the waypoint 'wp_id' with a new position 'point'
        :param wp_id: Current step
        :param point: Point position
        """
        position = self.mission.get_step(wp_id).get_maneuver().get_position()
        position.set_lat_lon(point.y(), point.x())
        if wp_id != self.mission.get_length() - 1:  # not last point
            if self.mission.get_step(
                    wp_id +
                    1).get_maneuver().get_maneuver_type() == SECTION_MANEUVER:
                logger.debug("Next step is a section")
                # if next step is a section change its initial position
                position_next = self.mission.get_step(
                    wp_id + 1).get_maneuver().get_initial_position()
                position_next.set_lat_lon(point.y(), point.x())
        self.mission_changed.emit(wp_id)
        self.update_start_end_markers()
        self.modified = True

    def remove_step(self, wp_id):
        """
        Remove step 'wp_id'
        :param wp_id: the step number to delete
        """
        initial_num_steps = self.mission.num_steps
        # if is first point and next waypoint is a Section, show warning message
        if (wp_id == 0 and initial_num_steps > 1 and
                self.mission.get_step(wp_id +
                                      1).get_maneuver().get_maneuver_type()
                == SECTION_MANEUVER):
            reply = QMessageBox.warning(
                None, "Mission Error",
                "Impossible to remove the point because the next point is a section"
            )

        else:

            if (initial_num_steps - 1 != wp_id
                    and self.mission.get_step(wp_id + 1).get_maneuver(
                    ).get_maneuver_type() == SECTION_MANEUVER):
                logger.debug("Next step is a section")
                # if it's not the last step
                # if next step is a section change its initial position to the one of the point before
                position_previous = self.mission.get_step(
                    wp_id - 1).get_maneuver().get_position()
                position_next = self.mission.get_step(
                    wp_id + 1).get_maneuver().get_initial_position()
                position_next.set_lat_lon(position_previous.latitude,
                                          position_previous.longitude)

            self.mission.remove_step(wp_id)
            self.step_removed.emit(wp_id)

            # When point is deleted, layer may need a geometry type change
            if initial_num_steps <= 2:
                self.update_layer_geometry()

            if wp_id == initial_num_steps - 1:
                # if last waypoint is removed show previous
                self.mission_changed.emit(wp_id - 1)
            else:
                self.mission_changed.emit(wp_id)

            self.update_start_end_markers()

            self.modified = True

    def update_steps(self, id_list, mission_step_list):
        """
        Update the number of the step 'wp_id' with new number 'step'
        :param id_list: list of step ids to update
        :param mission_step_list: list of mission steps to update
        :return:
        """
        if len(id_list) > 0:
            for i in range(0, len(id_list)):
                self.mission.update_step(id_list[i], mission_step_list[i])
            self.mission_changed.emit(id_list[0])
            self.update_start_end_markers()
            self.modified = True

    def add_step(self, wp_id, point):
        """ Add new step"""
        initial_num_steps = self.mission.num_steps
        logger.debug("Add step: Mission has {} steps and wp_id is {}".format(
            initial_num_steps, wp_id))
        step = MissionStep()
        position = MissionPosition()
        tolerance = MissionTolerance()
        # If more than one point, get maneuver from surrounding waypoint and copy data
        if initial_num_steps > 0:
            if wp_id != 0:

                # if point is at the end or in the middle copy from the previous
                manv_to_copy = self.mission.get_step(wp_id - 1).get_maneuver()

                if manv_to_copy.get_maneuver_type() == SECTION_MANEUVER:
                    # if section, initial pos will be the final pos of the previous
                    manv = MissionSection()
                    position.copy(manv_to_copy.get_position())
                    tolerance.copy(manv_to_copy.get_tolerance())
                    manv.set(manv_to_copy.get_final_position(), position,
                             manv_to_copy.get_speed(), tolerance)
                    manv.get_final_position().set_lat_lon(point.y(), point.x())

                if wp_id != initial_num_steps:
                    # if point in the middle check if next is also section, we need to modify it
                    manv_next = self.mission.get_step(wp_id).get_maneuver()
                    if manv_next.get_maneuver_type() == SECTION_MANEUVER:
                        manv_next.get_initial_position().set_lat_lon(
                            point.y(), point.x())

            else:  # wp_id == 0
                # copy from the next wp, next cannot be a section if was first waypoint until now, so no need to check
                manv_to_copy = self.mission.get_step(wp_id).get_maneuver()

            if manv_to_copy.get_maneuver_type() == WAYPOINT_MANEUVER:
                manv = MissionWaypoint()
                position.copy(manv_to_copy.get_position())
                tolerance.copy(manv_to_copy.get_tolerance())
                manv.set(position, manv_to_copy.get_speed(), tolerance)
                manv.get_position().set_lat_lon(point.y(), point.x())

            elif manv_to_copy.get_maneuver_type() == PARK_MANEUVER:
                manv = MissionPark()
                position.copy(manv_to_copy.get_position())
                tolerance.copy(manv_to_copy.get_tolerance())
                manv.set(position, manv_to_copy.get_speed(),
                         manv_to_copy.get_time(), tolerance)
                manv.get_position().set_lat_lon(point.y(), point.x())

        else:
            # is first point of the mission, fill maneuver by default type waypoint with clicked position
            manv = MissionWaypoint(
                MissionPosition(point.y(), point.x(), 0.0, False), 0.5,
                MissionTolerance(
                    2.0, 2.0,
                    1.0))  # todo: define default z, mode, speed and tolerance

        step.add_maneuver(manv)

        self.mission.insert_step(wp_id, step)
        logger.debug("Mission has now {} steps".format(self.mission.num_steps))

        # When point is added, layer may need a geometry type change
        if initial_num_steps <= 1:
            self.update_layer_geometry()

        self.mission_changed.emit(wp_id)
        self.update_start_end_markers()
        self.modified = True

    def save_mission(self):
        """ Saves a mission"""
        if self.mission.num_steps == 0:
            reply = QMessageBox.question(
                None, "Save Mission",
                "You are about to save an empty mission. Do you want to proceed?",
                QMessageBox.Yes | QMessageBox.No, QMessageBox.Yes)
            if reply == QMessageBox.No:
                return False
        elif float(
                self.mission.get_step(self.mission.get_length() - 1).
                get_maneuver().get_position().get_z()) != 0.0:
            # vehicle last waypoint is not at zero depth.
            reply = QMessageBox.question(
                None, "Save Mission",
                "You are about to save and the last waypoint is not at zero depth. "
                "Do you want to proceed?", QMessageBox.Yes | QMessageBox.No,
                QMessageBox.Yes)
            if reply == QMessageBox.No:
                return False

        logger.info("Saving mission to {}".format(self.mission_filename))
        self.mission.write_mission(self.mission_filename)
        self.mission_layer.setCustomProperty("mission_xml",
                                             self.mission_filename)
        self.saved = True
        self.modified = False
        return True

    def saveas_mission(self):
        """ Save a mission with new name"""
        if self.mission.num_steps == 0:
            reply = QMessageBox.question(
                None, "Save Mission",
                "You are about to save an empty mission. Do you want to proceed?",
                QMessageBox.Yes | QMessageBox.No, QMessageBox.Yes)
            if reply == QMessageBox.No:
                return False, None
        elif float(
                self.mission.get_step(self.mission.get_length() - 1).
                get_maneuver().get_position().get_z()) != 0.0:
            # vehicle last waypoint is not at zero depth.
            reply = QMessageBox.question(
                None, "Save Mission",
                "You are about to save and the last waypoint is not at zero depth. "
                "Do you want to proceed?", QMessageBox.Yes | QMessageBox.No,
                QMessageBox.Yes)
            if reply == QMessageBox.No:
                return False, None

        mission_filename, selected_filter = QFileDialog.getSaveFileName(
            None, 'Save mission', self.mission_filename, 'XML (*.xml)')

        if mission_filename != '':
            if selected_filter == "XML (*.xml)":
                file_info = QFileInfo(mission_filename)

                self.mission.write_mission(mission_filename)

                logger.debug(file_info.fileName())
                self.set_mission_name(file_info.fileName())
                self.set_mission_filename(mission_filename)
                self.mission_layer.setName(file_info.baseName())
                self.mission_layer.setCustomProperty("mission_xml",
                                                     self.mission_filename)

                self.saved = True
                self.modified = False

            return True, mission_filename

        else:
            return False, None

    def render_mission(self):
        """
        Render the mission, it will render the mission layer with Point geometry if it has only 1 point
        oterwise it will be with LineString geometry.
        """
        waypoints = self.find_waypoints_in_mission()
        if self.mission_layer is None:
            if len(waypoints) == 1:
                self.mission_layer = QgsVectorLayer("Point?crs=epsg:4326",
                                                    self.mission_name,
                                                    "memory")
                self.mission_layer.setCustomProperty("mission_xml",
                                                     self.mission_filename)
                feature = QgsFeature()
                feature.setGeometry(QgsGeometry(waypoints[0]))
                self.mission_layer.dataProvider().addFeatures([feature])
            else:
                self.mission_layer = QgsVectorLayer("LineString?crs=epsg:4326",
                                                    self.mission_name,
                                                    "memory")
                self.mission_layer.setCustomProperty("mission_xml",
                                                     self.mission_filename)
                feature = QgsFeature()
                feature.setGeometry(QgsGeometry.fromPolyline(waypoints))
                self.mission_layer.dataProvider().addFeatures([feature])

        else:
            # mission layer exists, now check if it has already a feature or not
            feats = self.mission_layer.getFeatures()
            logger.debug("layer feature count {}".format(
                self.mission_layer.featureCount()))
            if self.mission_layer.featureCount() == 0:
                feature = QgsFeature()
                if len(waypoints) == 1:
                    feature.setGeometry(QgsGeometry(waypoints[0]))
                else:
                    feature.setGeometry(QgsGeometry.fromPolyline(waypoints))
                self.mission_layer.dataProvider().addFeatures([feature])
            else:
                logger.debug("layer has feature mission already, updating...")
                for f in feats:
                    self.mission_layer.dataProvider().deleteFeatures([f.id()])
                    feature = QgsFeature()
                    if len(waypoints) == 1:
                        feature.setGeometry(QgsGeometry(waypoints[0]))
                    else:
                        feature.setGeometry(
                            QgsGeometry.fromPolyline(waypoints))
                    self.mission_layer.dataProvider().addFeatures([feature])

        self.set_mission_renderer(self.get_default_track_renderer())

    def find_waypoints_in_mission(self, indexes=None):
        """
        Gets all waypoints from a mission structure
        """
        waypoints = []
        if indexes is None:
            step_indexes = range(0, self.mission.size())
        else:
            step_indexes = indexes

        for stepindex in step_indexes:
            step = self.mission.get_step(stepindex)
            maneuver = step.get_maneuver()

            if maneuver.get_maneuver_type(
            ) == SECTION_MANEUVER:  # for a Section
                position = maneuver.get_final_position()
            else:
                position = maneuver.get_position()  # for Waypoint and Park

            waypoints.append(
                QgsPoint(float(position.longitude), float(position.latitude)))
        return waypoints

    def get_default_track_renderer(self):
        # Renderer for track lines
        registry = QgsSymbolLayerRegistry()
        line_meta = registry.symbolLayerMetadata("SimpleLine")
        marker_meta = registry.symbolLayerMetadata("MarkerLine")

        symbol = QgsSymbol.defaultSymbol(self.mission_layer.geometryType())

        # Line layer
        line_layer = line_meta.createSymbolLayer({
            'width': '0.5',
            'color': '255,0,0',
            'offset': '0.0',
            'penstyle': 'solid',
            'use_custom_dash': '0',
            'joinstyle': 'bevel',
            'capstyle': 'square'
        })

        # Marker layer
        marker_layer = marker_meta.createSymbolLayer({
            'width': '1.5',
            'color': '255,0,0',
            'placement': 'vertex',
            'offset': '0.0'
        })
        sub_symbol = marker_layer.subSymbol()

        # Replace the default layer with our own SimpleMarker
        sub_symbol.deleteSymbolLayer(0)
        cross = registry.symbolLayerMetadata("SimpleMarker").createSymbolLayer(
            {
                'name': 'circle',
                'color': '255,0,0',
                'color_border': '0,0,0',
                'offset': '0,0',
                'size': '2.5',
                'angle': '0'
            })
        sub_symbol.appendSymbolLayer(cross)

        # Replace the default layer with our two custom layers
        symbol.deleteSymbolLayer(0)
        symbol.appendSymbolLayer(line_layer)
        symbol.appendSymbolLayer(marker_layer)

        # Replace the renderer of the current layer
        renderer = QgsSingleSymbolRenderer(symbol)
        return renderer

    def update_start_end_markers(self):
        """ Updates start_end_markers"""
        self.start_end_marker.update_markers(self.find_waypoints_in_mission())

    def hide_start_end_markers(self):
        """ Hide start_end_markers"""
        self.start_end_marker.hide_markers()

    def remove_start_end_markers(self):
        """ Removes start end markers"""
        self.start_end_marker.close_markers()

    def update_layer_geometry(self):
        """
        This function needs to be called every time a point is added or deleted from the layer
        If needed, a new layer is created with the apropiate geometry
        Point if only one point, LineString otherwise
        """
        options = QgsDataProvider.ProviderOptions()
        waypoints = self.find_waypoints_in_mission()
        if (len(waypoints) != 1) and self.mission_layer.geometryType(
        ) == QgsWkbTypes.PointGeometry:
            self.mission_layer.setDataSource("LineString?crs=epsg:4326",
                                             self.mission_name, "memory",
                                             options)
            self.set_mission_renderer(self.get_default_track_renderer())
        elif len(waypoints) == 1 and self.mission_layer.geometryType(
        ) == QgsWkbTypes.LineGeometry:
            self.mission_layer.setDataSource("Point?crs=epsg:4326",
                                             self.mission_name, "memory",
                                             options)
            self.set_mission_renderer(self.get_default_track_renderer())
Ejemplo n.º 58
0
    def testWFST10(self):
        """Test WFS-T 1.0 (read-write)"""

        endpoint = self.__class__.basetestpath + '/fake_qgis_http_endpoint_WFS_T_1.0'

        with open(
                sanitize(endpoint,
                         '?SERVICE=WFS?REQUEST=GetCapabilities?VERSION=1.0.0'),
                'wb') as f:
            f.write("""
<WFS_Capabilities version="1.0.0" xmlns="http://www.opengis.net/wfs" xmlns:ogc="http://www.opengis.net/ogc">
  <FeatureTypeList>
    <Operations>
      <Query/>
      <Insert/>
      <Update/>
      <Delete/>
    </Operations>
    <FeatureType>
      <Name>my:typename</Name>
      <Title>Title</Title>
      <Abstract>Abstract</Abstract>
      <SRS>EPSG:4326</SRS>
      <LatLongBoundingBox minx="-71.123" miny="66.33" maxx="-65.32" maxy="78.3"/>
    </FeatureType>
  </FeatureTypeList>
</WFS_Capabilities>""")

        with open(
                sanitize(
                    endpoint,
                    '?SERVICE=WFS&REQUEST=DescribeFeatureType&VERSION=1.0.0&TYPENAME=my:typename'
                ), 'wb') as f:
            f.write("""
<xsd:schema xmlns:my="http://my" xmlns:gml="http://www.opengis.net/gml" xmlns:xsd="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified" targetNamespace="http://my">
  <xsd:import namespace="http://www.opengis.net/gml"/>
  <xsd:complexType name="my:typenameType">
    <xsd:complexContent>
      <xsd:extension base="gml:AbstractFeatureType">
        <xsd:sequence>
          <xsd:element maxOccurs="1" minOccurs="0" name="intfield" nillable="true" type="xsd:int"/>
          <xsd:element maxOccurs="1" minOccurs="0" name="longfield" nillable="true" type="xsd:long"/>
          <xsd:element maxOccurs="1" minOccurs="0" name="stringfield" nillable="true" type="xsd:string"/>
          <xsd:element maxOccurs="1" minOccurs="0" name="geometryProperty" nillable="true" type="gml:PointPropertyType"/>
        </xsd:sequence>
      </xsd:extension>
    </xsd:complexContent>
  </xsd:complexType>
  <xsd:element name="typename" substitutionGroup="gml:_Feature" type="my:typenameType"/>
</xsd:schema>
""")

        vl = QgsVectorLayer(
            u"url='http://" + endpoint +
            u"' typename='my:typename' version='1.0.0'", u'test', u'WFS')
        assert vl.isValid()

        self.assertEquals(
            vl.dataProvider().capabilities(),
            QgsVectorDataProvider.AddFeatures +
            QgsVectorDataProvider.ChangeAttributeValues +
            QgsVectorDataProvider.ChangeGeometries +
            QgsVectorDataProvider.DeleteFeatures)

        (ret, _) = vl.dataProvider().addFeatures([QgsFeature()])
        assert not ret

        self.assertEquals(vl.featureCount(), 0)

        assert not vl.dataProvider().deleteFeatures([0])

        self.assertEquals(vl.featureCount(), 0)

        assert not vl.dataProvider().changeGeometryValues(
            {0: QgsGeometry.fromWkt('Point (3 50)')})

        assert not vl.dataProvider().changeAttributeValues({0: {0: 0}})

        # Test addFeatures
        with open(
                sanitize(
                    endpoint,
                    '?SERVICE=WFS&POSTDATA=<Transaction xmlns="http://www.opengis.net/wfs" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="1.0.0" service="WFS" xsi:schemaLocation="http://my http://fake_qgis_http_endpoint?REQUEST=DescribeFeatureType&amp;VERSION=1.0.0&amp;TYPENAME=my:typename" xmlns:my="http://my" xmlns:gml="http://www.opengis.net/gml"><Insert xmlns="http://www.opengis.net/wfs"><typename xmlns="http://my"><intfield xmlns="http://my">1</intfield><longfield xmlns="http://my">1234567890123</longfield><stringfield xmlns="http://my">foo</stringfield><geometryProperty xmlns="http://my"><gml:Point srsName="EPSG:4326"><gml:coordinates cs="," ts=" ">2,49</gml:coordinates></gml:Point></geometryProperty></typename></Insert></Transaction>'
                ), 'wb') as f:
            f.write("""
<wfs:WFS_TransactionResponse version="1.0.0" xmlns:wfs="http://www.opengis.net/wfs" xmlns:ogc="http://www.opengis.net/ogc">
  <wfs:InsertResult>
    <ogc:FeatureId fid="typename.1" />
  </wfs:InsertResult>
  <wfs:TransactionResult>
    <wfs:Status>
        <wfs:SUCCESS/>
    </wfs:Status>
  </wfs:TransactionResult>
</wfs:WFS_TransactionResponse>
""")

        f = QgsFeature()
        f.setAttributes([1, 1234567890123, 'foo'])
        f.setGeometry(QgsGeometry.fromWkt('Point (2 49)'))
        (ret, fl) = vl.dataProvider().addFeatures([f])
        assert ret
        self.assertEquals(fl[0].id(), 1)

        self.assertEquals(vl.featureCount(), 1)

        values = [f['intfield'] for f in vl.getFeatures()]
        self.assertEquals(values, [1])

        values = [f['longfield'] for f in vl.getFeatures()]
        self.assertEquals(values, [1234567890123])

        values = [f['stringfield'] for f in vl.getFeatures()]
        self.assertEquals(values, ['foo'])

        got = [f.geometry() for f in vl.getFeatures()][0].geometry()
        self.assertEquals((got.x(), got.y()), (2.0, 49.0))

        # Test changeGeometryValues
        with open(
                sanitize(
                    endpoint,
                    '?SERVICE=WFS&POSTDATA=<Transaction xmlns="http://www.opengis.net/wfs" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="1.0.0" service="WFS" xsi:schemaLocation="http://my http://fake_qgis_http_endpoint?REQUEST=DescribeFeatureType&amp;VERSION=1.0.0&amp;TYPENAME=my:typename" xmlns:my="http://my" xmlns:gml="http://www.opengis.net/gml"><Update xmlns="http://www.opengis.net/wfs" typeName="my:typename"><Property xmlns="http://www.opengis.net/wfs"><Name xmlns="http://www.opengis.net/wfs">geometryProperty</Name><Value xmlns="http://www.opengis.net/wfs"><gml:Point srsName="EPSG:4326"><gml:coordinates cs="," ts=" ">3,50</gml:coordinates></gml:Point></Value></Property><Filter xmlns="http://www.opengis.net/ogc"><FeatureId xmlns="http://www.opengis.net/ogc" fid="typename.1"/></Filter></Update></Transaction>'
                ), 'wb') as f:
            f.write("""
<wfs:WFS_TransactionResponse version="1.0.0" xmlns:wfs="http://www.opengis.net/wfs" xmlns:ogc="http://www.opengis.net/ogc">
  <wfs:TransactionResult>
    <wfs:Status>
        <wfs:SUCCESS/>
    </wfs:Status>
  </wfs:TransactionResult>
</wfs:WFS_TransactionResponse>
""")

        ret = vl.dataProvider().changeGeometryValues(
            {1: QgsGeometry.fromWkt('Point (3 50)')})
        assert ret

        got = [f.geometry() for f in vl.getFeatures()][0].geometry()
        self.assertEquals((got.x(), got.y()), (3.0, 50.0))

        values = [f['intfield'] for f in vl.getFeatures()]
        self.assertEquals(values, [1])

        values = [f['longfield'] for f in vl.getFeatures()]
        self.assertEquals(values, [1234567890123])

        values = [f['stringfield'] for f in vl.getFeatures()]
        self.assertEquals(values, ['foo'])

        # Test changeAttributeValues
        with open(
                sanitize(
                    endpoint,
                    '?SERVICE=WFS&POSTDATA=<Transaction xmlns="http://www.opengis.net/wfs" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="1.0.0" service="WFS" xsi:schemaLocation="http://my http://fake_qgis_http_endpoint?REQUEST=DescribeFeatureType&amp;VERSION=1.0.0&amp;TYPENAME=my:typename" xmlns:my="http://my" xmlns:gml="http://www.opengis.net/gml"><Update xmlns="http://www.opengis.net/wfs" typeName="my:typename"><Property xmlns="http://www.opengis.net/wfs"><Name xmlns="http://www.opengis.net/wfs">intfield</Name><Value xmlns="http://www.opengis.net/wfs">2</Value></Property><Property xmlns="http://www.opengis.net/wfs"><Name xmlns="http://www.opengis.net/wfs">longfield</Name><Value xmlns="http://www.opengis.net/wfs">3</Value></Property><Property xmlns="http://www.opengis.net/wfs"><Name xmlns="http://www.opengis.net/wfs">stringfield</Name><Value xmlns="http://www.opengis.net/wfs">bar</Value></Property><Filter xmlns="http://www.opengis.net/ogc"><FeatureId xmlns="http://www.opengis.net/ogc" fid="typename.1"/></Filter></Update></Transaction>'
                ), 'wb') as f:
            f.write("""
<wfs:WFS_TransactionResponse version="1.0.0" xmlns:wfs="http://www.opengis.net/wfs" xmlns:ogc="http://www.opengis.net/ogc">
  <wfs:TransactionResult>
    <wfs:Status>
        <wfs:SUCCESS/>
    </wfs:Status>
  </wfs:TransactionResult>
</wfs:WFS_TransactionResponse>
""")
        assert vl.dataProvider().changeAttributeValues(
            {1: {
                0: 2,
                1: 3,
                2: "bar"
            }})

        values = [f['intfield'] for f in vl.getFeatures()]
        self.assertEquals(values, [2])

        values = [f['longfield'] for f in vl.getFeatures()]
        self.assertEquals(values, [3])

        values = [f['stringfield'] for f in vl.getFeatures()]
        self.assertEquals(values, ['bar'])

        got = [f.geometry() for f in vl.getFeatures()][0].geometry()
        self.assertEquals((got.x(), got.y()), (3.0, 50.0))

        # Test deleteFeatures
        with open(
                sanitize(
                    endpoint,
                    '?SERVICE=WFS&POSTDATA=<Transaction xmlns="http://www.opengis.net/wfs" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="1.0.0" service="WFS" xsi:schemaLocation="http://my http://fake_qgis_http_endpoint?REQUEST=DescribeFeatureType&amp;VERSION=1.0.0&amp;TYPENAME=my:typename" xmlns:my="http://my" xmlns:gml="http://www.opengis.net/gml"><Delete xmlns="http://www.opengis.net/wfs" typeName="my:typename"><Filter xmlns="http://www.opengis.net/ogc"><FeatureId xmlns="http://www.opengis.net/ogc" fid="typename.1"/></Filter></Delete></Transaction>'
                ), 'wb') as f:
            f.write("""
<wfs:WFS_TransactionResponse version="1.0.0" xmlns:wfs="http://www.opengis.net/wfs" xmlns:ogc="http://www.opengis.net/ogc">
  <wfs:TransactionResult>
    <wfs:Status>
        <wfs:SUCCESS/>
    </wfs:Status>
  </wfs:TransactionResult>
</wfs:WFS_TransactionResponse>
""")
        assert vl.dataProvider().deleteFeatures([1])

        self.assertEquals(vl.featureCount(), 0)
Ejemplo n.º 59
0
class TestQgsTextEditWidget(unittest.TestCase):

    @classmethod
    def setUpClass(cls):
        QgsGui.editorWidgetRegistry().initEditors()

    def createLayerWithOnePoint(self):
        self.layer = QgsVectorLayer("Point?field=fldtxt:string&field=fldint:integer",
                                    "addfeat", "memory")
        pr = self.layer.dataProvider()
        f = QgsFeature()
        f.setAttributes(["test", 123])
        f.setGeometry(QgsGeometry.fromPointXY(QgsPointXY(100, 200)))
        self.assertTrue(pr.addFeatures([f]))
        self.assertEqual(self.layer.featureCount(), 1)
        return self.layer

    def doAttributeTest(self, idx, expected):
        reg = QgsGui.editorWidgetRegistry()
        configWdg = reg.createConfigWidget('TextEdit', self.layer, idx, None)
        config = configWdg.config()
        editwidget = reg.create('TextEdit', self.layer, idx, config, None, None)

        editwidget.setValue('value')
        self.assertEqual(editwidget.value(), expected[0])

        editwidget.setValue(123)
        self.assertEqual(editwidget.value(), expected[1])

        editwidget.setValue(None)
        self.assertEqual(editwidget.value(), expected[2])

        editwidget.setValue(NULL)
        self.assertEqual(editwidget.value(), expected[3])

    def test_SetValue(self):
        self.createLayerWithOnePoint()

        self.doAttributeTest(0, ['value', '123', NULL, NULL])
        self.doAttributeTest(1, [NULL, 123, NULL, NULL])

    def testStringWithMaxLen(self):
        """ tests that text edit wrappers correctly handle string fields with a maximum length """
        layer = QgsVectorLayer("none?field=fldint:integer", "layer", "memory")
        self.assertTrue(layer.isValid())
        layer.dataProvider().addAttributes([QgsField('max', QVariant.String, 'string', 10),
                                            QgsField('nomax', QVariant.String, 'string', 0)])
        layer.updateFields()
        QgsProject.instance().addMapLayer(layer)

        reg = QgsGui.editorWidgetRegistry()
        config = {'IsMultiline': 'True'}

        # first test for field without character limit
        editor = QTextEdit()
        editor.setPlainText('this_is_a_long_string')
        w = reg.create('TextEdit', layer, 2, config, editor, None)
        self.assertEqual(w.value(), 'this_is_a_long_string')

        # next test for field with character limit
        editor = QTextEdit()
        editor.setPlainText('this_is_a_long_string')
        w = reg.create('TextEdit', layer, 1, config, editor, None)

        self.assertEqual(w.value(), 'this_is_a_')

        QgsProject.instance().removeAllMapLayers()
Ejemplo n.º 60
0
    def test_add_feature_geometry(self):
        """
        Test to add a feature with a geometry
        """
        vl_pipes = QgsVectorLayer(
            self.dbconn +
            ' sslmode=disable key=\'pk\' table="qgis_test"."pipes" (geom) sql=',
            'pipes', 'postgres')
        vl_leaks = QgsVectorLayer(
            self.dbconn +
            ' sslmode=disable key=\'pk\' table="qgis_test"."leaks" (geom) sql=',
            'leaks', 'postgres')
        vl_leaks.startEditing()

        QgsProject.instance().addMapLayer(vl_pipes)
        QgsProject.instance().addMapLayer(vl_leaks)

        self.assertEqual(vl_pipes.featureCount(), 2)
        self.assertEqual(vl_leaks.featureCount(), 3)

        rel = QgsRelation()
        rel.setReferencingLayer(vl_leaks.id())
        rel.setReferencedLayer(vl_pipes.id())
        rel.addFieldPair('pipe', 'id')
        rel.setId('rel_pipe_leak')
        self.assertTrue(rel.isValid())
        self.relMgr.addRelation(rel)

        # Mock vector layer tool to just set default value on created feature
        class DummyVlTools(QgsVectorLayerTools):
            def addFeature(self, layer, defaultValues, defaultGeometry):
                f = QgsFeature(layer.fields())
                for idx, value in defaultValues.items():
                    f.setAttribute(idx, value)
                f.setGeometry(defaultGeometry)
                ok = layer.addFeature(f)

                return ok, f

        wrapper = QgsRelationWidgetWrapper(vl_leaks, rel)
        context = QgsAttributeEditorContext()
        vltool = DummyVlTools()
        context.setVectorLayerTools(vltool)
        context.setMapCanvas(self.mapCanvas)
        cadDockWidget = QgsAdvancedDigitizingDockWidget(self.mapCanvas)
        context.setCadDockWidget(cadDockWidget)
        wrapper.setContext(context)
        widget = wrapper.widget()
        widget.show()
        pipe = next(vl_pipes.getFeatures())
        self.assertEqual(pipe.id(), 1)
        wrapper.setFeature(pipe)
        table_view = widget.findChild(QTableView)
        self.assertEqual(table_view.model().rowCount(), 1)

        btn = widget.findChild(QToolButton, 'mAddFeatureGeometryButton')
        self.assertTrue(btn.isVisible())
        self.assertTrue(btn.isEnabled())
        btn.click()
        self.assertTrue(self.mapCanvas.mapTool())
        feature = QgsFeature(vl_leaks.fields())
        feature.setGeometry(QgsGeometry.fromWkt('POINT(0 0.8)'))
        self.mapCanvas.mapTool().digitizingCompleted.emit(feature)
        self.assertEqual(table_view.model().rowCount(), 2)
        self.assertEqual(vl_leaks.featureCount(), 4)
        request = QgsFeatureRequest()
        request.addOrderBy("id", False)

        # get new created feature
        feat = next(vl_leaks.getFeatures('"id" is NULL'))
        self.assertTrue(feat.isValid())
        self.assertTrue(feat.geometry().equals(
            QgsGeometry.fromWkt('POINT(0 0.8)')))

        vl_leaks.rollBack()