def save2PointShape(shapePath, geodata, attribName, attribData, label, spatialRef): """ :param label: :param shapePath: Pfad wo Shapefile agespeichert wird :param geodata: Koordinaten der Punkte :param attribName: Attributname (Feldname) von zusätzlichen Werten :param attribData: Werte für Attribute :param spatialRef: Räumliche Referenz """ # define fields for feature attributes. A QgsFields object is needed fields = QgsFields() fields.append(QgsField("StuetzenNr", QVariant.String)) fields.append(QgsField(attribName, QVariant.Int)) writer = QgsVectorFileWriter(shapePath, "UTF8", fields, QgsWkbTypes.PointZ, spatialRef, "ESRI Shapefile") if writer.hasError() != QgsVectorFileWriter.NoError: # TODO raise Exception("Vector Writer") for idx, (coords, attrib) in enumerate(zip(geodata, attribData)): feature = QgsFeature() feature.setFields(fields) # TODO: Nicht 3D weil Methode fromPoint() nicht existiert. Wird evtl. in der Zukunft implementiert feature.setGeometry(QgsGeometry.fromPointXY(QgsPointXY(coords[0], coords[1]))) feature.setId(idx) feature.setAttribute("StuetzenNr", label[idx]) feature.setAttribute(attribName, attrib) writer.addFeature(feature) del feature # delete the writer to flush features to disk del writer
def testAddFeatureMissingAttributes(self): if not getattr(self, 'getEditableLayer', None): return l = self.getEditableLayer() self.assertTrue(l.isValid()) if not l.dataProvider().capabilities() & QgsVectorDataProvider.AddFeatures: return # test that adding features with missing attributes pads out these # attributes with NULL values to the correct length f1 = QgsFeature() f1.setAttributes([6, -220, NULL, 'String']) f2 = QgsFeature() f2.setAttributes([7, 330]) result, added = l.dataProvider().addFeatures([f1, f2]) self.assertTrue(result, 'Provider returned False to addFeatures with missing attributes. Providers should accept these features but add NULL attributes to the end of the existing attributes to the required field length.') f1.setId(added[0].id()) f2.setId(added[1].id()) # check result - feature attributes MUST be padded out to required number of fields f1.setAttributes([6, -220, NULL, 'String', 'NULL']) f2.setAttributes([7, 330, NULL, NULL, 'NULL']) self.testGetFeatures(l.dataProvider(), [f1, f2])
def testAddFeature(self): if not getattr(self, 'getEditableLayer', None): return l = self.getEditableLayer() self.assertTrue(l.isValid()) f1 = QgsFeature() f1.setAttributes([6, -220, NULL, 'String', '15']) f1.setGeometry(QgsGeometry.fromWkt('Point (-72.345 71.987)')) f2 = QgsFeature() f2.setAttributes([7, 330, 'Coconut', 'CoCoNut', '13']) if l.dataProvider().capabilities() & QgsVectorDataProvider.AddFeatures: # expect success result, added = l.dataProvider().addFeatures([f1, f2]) self.assertTrue(result, 'Provider reported AddFeatures capability, but returned False to addFeatures') f1.setId(added[0].id()) f2.setId(added[1].id()) # check result self.testGetFeatures(l.dataProvider(), [f1, f2]) # add empty list, should return true for consistency self.assertTrue(l.dataProvider().addFeatures([])) else: # expect fail self.assertFalse(l.dataProvider().addFeatures([f1, f2]), 'Provider reported no AddFeatures capability, but returned true to addFeatures')
def addFeatures(self, flist, flags=None): added = False f_added = [] for f in flist: if f.hasGeometry() and (f.geometry().wkbType() != self.wkbType()): return added, f_added for f in flist: _f = QgsFeature(self.fields()) _f.setGeometry(f.geometry()) attrs = [None for i in range(_f.fields().count())] for i in range(min(len(attrs), len(f.attributes()))): attrs[i] = f.attributes()[i] _f.setAttributes(attrs) _f.setId(self.next_feature_id) self._features[self.next_feature_id] = _f self.next_feature_id += 1 added = True f_added.append(_f) if self._spatialindex is not None: self._spatialindex.insertFeature(_f) if len(f_added): self.clearMinMaxCache() self.updateExtents() return added, f_added
def testIndex(self): idx = QgsSpatialIndex() fid = 0 for y in range(5, 15, 5): for x in range(5, 25, 5): ft = QgsFeature() ft.setId(fid) ft.setGeometry(QgsGeometry.fromPointXY(QgsPointXY(x, y))) idx.insertFeature(ft) fid += 1 # intersection test rect = QgsRectangle(7.0, 3.0, 17.0, 13.0) fids = idx.intersects(rect) myExpectedValue = 4 myValue = len(fids) myMessage = 'Expected: %s Got: %s' % (myExpectedValue, myValue) self.assertEqual(myValue, myExpectedValue, myMessage) fids.sort() myMessage = ('Expected: %s\nGot: %s\n' % ([1, 2, 5, 6], fids)) assert fids == [1, 2, 5, 6], myMessage # nearest neighbor test fids = idx.nearestNeighbor(QgsPointXY(8.75, 6.25), 3) myExpectedValue = 0 myValue = len(fids) myMessage = 'Expected: %s Got: %s' % (myExpectedValue, myValue) fids.sort() myMessage = ('Expected: %s\nGot: %s\n' % ([0, 1, 5], fids)) assert fids == [0, 1, 5], myMessage
def testGetGeometry(self): idx = QgsSpatialIndex() idx2 = QgsSpatialIndex(QgsSpatialIndex.FlagStoreFeatureGeometries) fid = 0 for y in range(5): for x in range(10, 15): ft = QgsFeature() ft.setId(fid) ft.setGeometry(QgsGeometry.fromPointXY(QgsPointXY(x, y))) idx.insertFeature(ft) idx2.insertFeature(ft) fid += 1 # not storing geometries, a keyerror should be raised with self.assertRaises(KeyError): idx.geometry(-100) with self.assertRaises(KeyError): idx.geometry(1) with self.assertRaises(KeyError): idx.geometry(2) with self.assertRaises(KeyError): idx.geometry(1000) self.assertEqual(idx2.geometry(1).asWkt(1), 'Point (11 0)') self.assertEqual(idx2.geometry(2).asWkt(1), 'Point (12 0)') with self.assertRaises(KeyError): idx2.geometry(-100) with self.assertRaises(KeyError): idx2.geometry(1000)
def test_signalConnection(self): # remove all layers QgsProject.instance().removeAllMapLayers() # set dependencies and add back layers self.pointsLayer = QgsVectorLayer("dbname='%s' table=\"node\" (geom) sql=" % self.fn, "points", "spatialite") assert (self.pointsLayer.isValid()) self.linesLayer = QgsVectorLayer("dbname='%s' table=\"section\" (geom) sql=" % self.fn, "lines", "spatialite") assert (self.linesLayer.isValid()) self.pointsLayer2 = QgsVectorLayer("dbname='%s' table=\"node2\" (geom) sql=" % self.fn, "_points2", "spatialite") assert (self.pointsLayer2.isValid()) self.pointsLayer.setDependencies([QgsMapLayerDependency(self.linesLayer.id())]) self.pointsLayer2.setDependencies([QgsMapLayerDependency(self.pointsLayer.id())]) # this should update connections between layers QgsProject.instance().addMapLayers([self.pointsLayer]) QgsProject.instance().addMapLayers([self.linesLayer]) QgsProject.instance().addMapLayers([self.pointsLayer2]) ms = QgsMapSettings() ms.setOutputSize(QSize(100, 100)) ms.setExtent(QgsRectangle(0, 0, 1, 1)) self.assertTrue(ms.hasValidSettings()) u = QgsSnappingUtils() u.setMapSettings(ms) cfg = u.config() cfg.setEnabled(True) cfg.setMode(QgsSnappingConfig.AdvancedConfiguration) cfg.setIndividualLayerSettings(self.pointsLayer, QgsSnappingConfig.IndividualLayerSettings(True, QgsSnappingConfig.Vertex, 20, QgsTolerance.Pixels)) cfg.setIndividualLayerSettings(self.pointsLayer2, QgsSnappingConfig.IndividualLayerSettings(True, QgsSnappingConfig.Vertex, 20, QgsTolerance.Pixels)) u.setConfig(cfg) # add another line f = QgsFeature(self.linesLayer.fields()) f.setId(4) geom = QgsGeometry.fromWkt("LINESTRING(0.5 0.2,0.6 0)") f.setGeometry(geom) self.linesLayer.startEditing() self.linesLayer.addFeatures([f]) self.linesLayer.commitChanges() # check the second snapped point is ok m = u.snapToMap(QPoint(75, 100 - 0)) self.assertTrue(m.isValid()) self.assertTrue(m.hasVertex()) self.assertEqual(m.point(), QgsPointXY(0.8, 0.0)) self.pointsLayer.setDependencies([]) self.pointsLayer2.setDependencies([])
def create_spatial_index(self, layer): spatial_index = QgsSpatialIndex() # features dictionary centroid_features = {} features = layer.getFeatures() for feature in features: # convert to point feature point_feature = QgsFeature(layer.fields()) point_feature.setId(feature.id()) point_feature.setAttributes(feature.attributes()) point_feature.setGeometry(feature.geometry().centroid()) centroid_features[point_feature.id()] = point_feature spatial_index.insertFeature(point_feature) return (spatial_index, centroid_features)
def test_Validity(self): f = QgsFeature() self.assertFalse(f.isValid()) f.setGeometry(QgsGeometry()) self.assertTrue(f.isValid()) f.setValid(False) self.assertFalse(f.isValid()) fields = QgsFields() field1 = QgsField('my_field') fields.append(field1) field2 = QgsField('my_field2') fields.append(field2) f.setFields(fields) f.setAttribute(0, 0) self.assertTrue(f.isValid()) f.setValid(False) self.assertFalse(f.isValid()) f.setId(27) self.assertTrue(f.isValid())
def save2LineShape(shapePath, geodata, spatialRef): # define fields for feature attributes. A QgsFields object is needed fields = QgsFields() writer = QgsVectorFileWriter(shapePath, "UTF8", fields, QgsWkbTypes.LineStringZ, spatialRef, "ESRI Shapefile") if writer.hasError() != QgsVectorFileWriter.NoError: # TODO raise Exception("Vector Writer") lineVertices = [] for idx, coords in enumerate(geodata): lineVertices.append(QgsPoint(coords[0], coords[1], coords[2])) feature = QgsFeature() feature.setGeometry(QgsGeometry.fromPolyline(lineVertices)) feature.setId(1) writer.addFeature(feature) del feature # delete the writer to flush features to disk del writer
def test_resetSnappingIndex(self): self.pointsLayer.setDependencies([]) self.linesLayer.setDependencies([]) self.pointsLayer2.setDependencies([]) ms = QgsMapSettings() ms.setOutputSize(QSize(100, 100)) ms.setExtent(QgsRectangle(0, 0, 1, 1)) self.assertTrue(ms.hasValidSettings()) u = QgsSnappingUtils() u.setMapSettings(ms) cfg = u.config() cfg.setEnabled(True) cfg.setMode(QgsSnappingConfig.AdvancedConfiguration) cfg.setIndividualLayerSettings(self.pointsLayer, QgsSnappingConfig.IndividualLayerSettings(True, QgsSnappingConfig.Vertex, 20, QgsTolerance.Pixels)) u.setConfig(cfg) m = u.snapToMap(QPoint(95, 100)) self.assertTrue(m.isValid()) self.assertTrue(m.hasVertex()) self.assertEqual(m.point(), QgsPointXY(1, 0)) f = QgsFeature(self.linesLayer.fields()) f.setId(1) geom = QgsGeometry.fromWkt("LINESTRING(0 0,1 1)") f.setGeometry(geom) self.linesLayer.startEditing() self.linesLayer.addFeatures([f]) self.linesLayer.commitChanges() l1 = len([f for f in self.pointsLayer.getFeatures()]) self.assertEqual(l1, 4) m = u.snapToMap(QPoint(95, 0)) # snapping not updated self.pointsLayer.setDependencies([]) self.assertEqual(m.isValid(), False) # set layer dependencies self.pointsLayer.setDependencies([QgsMapLayerDependency(self.linesLayer.id())]) # add another line f = QgsFeature(self.linesLayer.fields()) f.setId(2) geom = QgsGeometry.fromWkt("LINESTRING(0 0,0.5 0.5)") f.setGeometry(geom) self.linesLayer.startEditing() self.linesLayer.addFeatures([f]) self.linesLayer.commitChanges() # check the snapped point is ok m = u.snapToMap(QPoint(45, 50)) self.assertTrue(m.isValid()) self.assertTrue(m.hasVertex()) self.assertEqual(m.point(), QgsPointXY(0.5, 0.5)) self.pointsLayer.setDependencies([]) # test chained layer dependencies A -> B -> C cfg.setIndividualLayerSettings(self.pointsLayer2, QgsSnappingConfig.IndividualLayerSettings(True, QgsSnappingConfig.Vertex, 20, QgsTolerance.Pixels)) u.setConfig(cfg) self.pointsLayer.setDependencies([QgsMapLayerDependency(self.linesLayer.id())]) self.pointsLayer2.setDependencies([QgsMapLayerDependency(self.pointsLayer.id())]) # add another line f = QgsFeature(self.linesLayer.fields()) f.setId(3) geom = QgsGeometry.fromWkt("LINESTRING(0 0.2,0.5 0.8)") f.setGeometry(geom) self.linesLayer.startEditing() self.linesLayer.addFeatures([f]) self.linesLayer.commitChanges() # check the second snapped point is ok m = u.snapToMap(QPoint(75, 100 - 80)) self.assertTrue(m.isValid()) self.assertTrue(m.hasVertex()) self.assertEqual(m.point(), QgsPointXY(0.7, 0.8)) self.pointsLayer.setDependencies([]) self.pointsLayer2.setDependencies([])
def test_resetSnappingIndex(self): self.pointsLayer.setDependencies([]) self.linesLayer.setDependencies([]) self.pointsLayer2.setDependencies([]) ms = QgsMapSettings() ms.setOutputSize(QSize(100, 100)) ms.setExtent(QgsRectangle(0, 0, 1, 1)) self.assertTrue(ms.hasValidSettings()) u = QgsSnappingUtils() u.setMapSettings(ms) cfg = u.config() cfg.setEnabled(True) cfg.setMode(QgsSnappingConfig.AdvancedConfiguration) cfg.setIndividualLayerSettings( self.pointsLayer, QgsSnappingConfig.IndividualLayerSettings(True, QgsSnappingConfig.Vertex, 20, QgsTolerance.Pixels)) u.setConfig(cfg) m = u.snapToMap(QPoint(95, 100)) self.assertTrue(m.isValid()) self.assertTrue(m.hasVertex()) self.assertEqual(m.point(), QgsPointXY(1, 0)) f = QgsFeature(self.linesLayer.fields()) f.setId(1) geom = QgsGeometry.fromWkt("LINESTRING(0 0,1 1)") f.setGeometry(geom) self.linesLayer.startEditing() self.linesLayer.addFeatures([f]) self.linesLayer.commitChanges() l1 = len([f for f in self.pointsLayer.getFeatures()]) self.assertEqual(l1, 4) m = u.snapToMap(QPoint(95, 0)) # snapping not updated self.pointsLayer.setDependencies([]) self.assertEqual(m.isValid(), False) # set layer dependencies self.pointsLayer.setDependencies( [QgsMapLayerDependency(self.linesLayer.id())]) # add another line f = QgsFeature(self.linesLayer.fields()) f.setId(2) geom = QgsGeometry.fromWkt("LINESTRING(0 0,0.5 0.5)") f.setGeometry(geom) self.linesLayer.startEditing() self.linesLayer.addFeatures([f]) self.linesLayer.commitChanges() # check the snapped point is OK m = u.snapToMap(QPoint(45, 50)) self.assertTrue(m.isValid()) self.assertTrue(m.hasVertex()) self.assertEqual(m.point(), QgsPointXY(0.5, 0.5)) self.pointsLayer.setDependencies([]) # test chained layer dependencies A -> B -> C cfg.setIndividualLayerSettings( self.pointsLayer2, QgsSnappingConfig.IndividualLayerSettings(True, QgsSnappingConfig.Vertex, 20, QgsTolerance.Pixels)) u.setConfig(cfg) self.pointsLayer.setDependencies( [QgsMapLayerDependency(self.linesLayer.id())]) self.pointsLayer2.setDependencies( [QgsMapLayerDependency(self.pointsLayer.id())]) # add another line f = QgsFeature(self.linesLayer.fields()) f.setId(3) geom = QgsGeometry.fromWkt("LINESTRING(0 0.2,0.5 0.8)") f.setGeometry(geom) self.linesLayer.startEditing() self.linesLayer.addFeatures([f]) self.linesLayer.commitChanges() # check the second snapped point is OK m = u.snapToMap(QPoint(75, 100 - 80)) self.assertTrue(m.isValid()) self.assertTrue(m.hasVertex()) self.assertEqual(m.point(), QgsPointXY(0.7, 0.8)) self.pointsLayer.setDependencies([]) self.pointsLayer2.setDependencies([])
def test_signalConnection(self): # remove all layers QgsProject.instance().removeAllMapLayers() # set dependencies and add back layers self.pointsLayer = QgsVectorLayer( "dbname='%s' table=\"node\" (geom) sql=" % self.fn, "points", "spatialite") assert (self.pointsLayer.isValid()) self.linesLayer = QgsVectorLayer( "dbname='%s' table=\"section\" (geom) sql=" % self.fn, "lines", "spatialite") assert (self.linesLayer.isValid()) self.pointsLayer2 = QgsVectorLayer( "dbname='%s' table=\"node2\" (geom) sql=" % self.fn, "_points2", "spatialite") assert (self.pointsLayer2.isValid()) self.pointsLayer.setDependencies( [QgsMapLayerDependency(self.linesLayer.id())]) self.pointsLayer2.setDependencies( [QgsMapLayerDependency(self.pointsLayer.id())]) # this should update connections between layers QgsProject.instance().addMapLayers([self.pointsLayer]) QgsProject.instance().addMapLayers([self.linesLayer]) QgsProject.instance().addMapLayers([self.pointsLayer2]) ms = QgsMapSettings() ms.setOutputSize(QSize(100, 100)) ms.setExtent(QgsRectangle(0, 0, 1, 1)) self.assertTrue(ms.hasValidSettings()) u = QgsSnappingUtils() u.setMapSettings(ms) cfg = u.config() cfg.setEnabled(True) cfg.setMode(QgsSnappingConfig.AdvancedConfiguration) cfg.setIndividualLayerSettings( self.pointsLayer, QgsSnappingConfig.IndividualLayerSettings(True, QgsSnappingConfig.Vertex, 20, QgsTolerance.Pixels)) cfg.setIndividualLayerSettings( self.pointsLayer2, QgsSnappingConfig.IndividualLayerSettings(True, QgsSnappingConfig.Vertex, 20, QgsTolerance.Pixels)) u.setConfig(cfg) # add another line f = QgsFeature(self.linesLayer.fields()) f.setId(4) geom = QgsGeometry.fromWkt("LINESTRING(0.5 0.2,0.6 0)") f.setGeometry(geom) self.linesLayer.startEditing() self.linesLayer.addFeatures([f]) self.linesLayer.commitChanges() # check the second snapped point is OK m = u.snapToMap(QPoint(75, 100 - 0)) self.assertTrue(m.isValid()) self.assertTrue(m.hasVertex()) self.assertEqual(m.point(), QgsPointXY(0.8, 0.0)) self.pointsLayer.setDependencies([]) self.pointsLayer2.setDependencies([])