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 testWFSPointsMultipleEdits(self): """ Adds some points, then check. Modify 2 points, then checks and clear all """ layer_name = 'test_point' layer = self._getLayer(layer_name) wfs_layer = self._getWFSLayer(layer_name) feat1 = QgsFeature(wfs_layer.pendingFields()) feat1['id'] = 11 feat1['name'] = 'name 11' feat1.setGeometry(QgsGeometry.fromPointXY(QgsPointXY(9, 45))) feat2 = QgsFeature(wfs_layer.pendingFields()) feat2.setGeometry(QgsGeometry.fromPointXY(QgsPointXY(9.5, 45.5))) feat2['id'] = 12 feat2['name'] = 'name 12' old_features = [feat1, feat2] # Change feat1 and feat2 new_feat1 = QgsFeature(wfs_layer.pendingFields()) new_feat1['id'] = 121 new_feat1['name'] = 'name 121' new_feat1.setGeometry(QgsGeometry.fromPointXY(QgsPointXY(10, 46))) new_feat2 = QgsFeature(wfs_layer.pendingFields()) new_feat2['id'] = 122 new_feat2['name'] = 'name 122' new_feat2.setGeometry(QgsGeometry.fromPointXY(QgsPointXY(10.5, 47))) new_features = [new_feat1, new_feat2] self._testLayer(wfs_layer, layer, old_features, new_features)
def testDeleteMultipleFeatures(self): # test deleting multiple features from an edit buffer # make a layer with two features layer = createEmptyLayer() self.assertTrue(layer.startEditing()) # add two features f1 = QgsFeature(layer.fields(), 1) f1.setGeometry(QgsGeometry.fromPointXY(QgsPointXY(1, 2))) f1.setAttributes(["test", 123]) self.assertTrue(layer.addFeature(f1)) f2 = QgsFeature(layer.fields(), 2) f2.setGeometry(QgsGeometry.fromPointXY(QgsPointXY(2, 4))) f2.setAttributes(["test2", 246]) self.assertTrue(layer.addFeature(f2)) layer.commitChanges() layer.startEditing() self.assertEqual(layer.editBuffer().deletedFeatureIds(), []) self.assertFalse(layer.editBuffer().isFeatureDeleted(1)) self.assertFalse(layer.editBuffer().isFeatureDeleted(2)) # delete features layer.deleteFeatures([1, 2]) # test contents of buffer self.assertEqual(set(layer.editBuffer().deletedFeatureIds()), set([1, 2])) self.assertTrue(layer.editBuffer().isFeatureDeleted(1)) self.assertTrue(layer.editBuffer().isFeatureDeleted(2))
def testAddMultipleFeatures(self): # test adding multiple features to an edit buffer layer = createEmptyLayer() self.assertTrue(layer.startEditing()) self.assertEqual(layer.editBuffer().addedFeatures(), {}) self.assertFalse(layer.editBuffer().isFeatureAdded(1)) self.assertFalse(layer.editBuffer().isFeatureAdded(3)) # add two features f1 = QgsFeature(layer.fields(), 1) f1.setGeometry(QgsGeometry.fromPointXY(QgsPointXY(1, 2))) f1.setAttributes(["test", 123]) f2 = QgsFeature(layer.fields(), 2) f2.setGeometry(QgsGeometry.fromPointXY(QgsPointXY(2, 4))) f2.setAttributes(["test2", 246]) self.assertTrue(layer.addFeatures([f1, f2])) # test contents of buffer added = layer.editBuffer().addedFeatures() new_feature_ids = list(added.keys()) self.assertEqual(added[new_feature_ids[0]]['fldtxt'], 'test2') self.assertEqual(added[new_feature_ids[0]]['fldint'], 246) self.assertEqual(added[new_feature_ids[1]]['fldtxt'], 'test') self.assertEqual(added[new_feature_ids[1]]['fldint'], 123) self.assertTrue(layer.editBuffer().isFeatureAdded(new_feature_ids[0])) self.assertTrue(layer.editBuffer().isFeatureAdded(new_feature_ids[1]))
def testProxyFeatureSink(self): fields = QgsFields() fields.append(QgsField('fldtxt', QVariant.String)) fields.append(QgsField('fldint', QVariant.Int)) store = QgsFeatureStore(fields, QgsCoordinateReferenceSystem()) proxy = QgsProxyFeatureSink(store) self.assertEqual(proxy.destinationSink(), store) self.assertEqual(len(store), 0) f = QgsFeature() f.setAttributes(["test", 123]) f.setGeometry(QgsGeometry.fromPointXY(QgsPointXY(100, 200))) proxy.addFeature(f) self.assertEqual(len(store), 1) self.assertEqual(store.features()[0]['fldtxt'], 'test') f2 = QgsFeature() f2.setAttributes(["test2", 457]) f2.setGeometry(QgsGeometry.fromPointXY(QgsPointXY(200, 200))) f3 = QgsFeature() f3.setAttributes(["test3", 888]) f3.setGeometry(QgsGeometry.fromPointXY(QgsPointXY(300, 200))) proxy.addFeatures([f2, f3]) self.assertEqual(len(store), 3) self.assertEqual(store.features()[1]['fldtxt'], 'test2') self.assertEqual(store.features()[2]['fldtxt'], 'test3')
def testCreateLayer(self): layer = QgsVectorLayer("Point?field=id:integer&field=fldtxt:string&field=fldint:integer", "addfeat", "memory") pr = layer.dataProvider() f = QgsFeature() f.setAttributes([1, "test", 1]) f.setGeometry(QgsGeometry.fromPointXY(QgsPointXY(1, 2))) f2 = QgsFeature() f2.setAttributes([2, "test2", 3]) f3 = QgsFeature() f3.setAttributes([3, "test2", NULL]) f3.setGeometry(QgsGeometry.fromPointXY(QgsPointXY(3, 2))) f4 = QgsFeature() f4.setAttributes([4, NULL, 3]) f4.setGeometry(QgsGeometry.fromPointXY(QgsPointXY(4, 3))) pr.addFeatures([f, f2, f3, f4]) uri = '{} table="qgis_test"."new_table" sql='.format(self.dbconn) error, message = QgsVectorLayerExporter.exportLayer(layer, uri, 'mssql', QgsCoordinateReferenceSystem('EPSG:4326')) self.assertEqual(error, QgsVectorLayerExporter.NoError) new_layer = QgsVectorLayer(uri, 'new', 'mssql') self.assertTrue(new_layer.isValid()) self.assertEqual(new_layer.wkbType(), QgsWkbTypes.Point) self.assertEqual([f.name() for f in new_layer.fields()], ['qgs_fid', 'id', 'fldtxt', 'fldint']) features = [f.attributes() for f in new_layer.getFeatures()] self.assertEqual(features, [[1, 1, 'test', 1], [2, 2, 'test2', 3], [3, 3, 'test2', NULL], [4, 4, NULL, 3]]) geom = [f.geometry().asWkt() for f in new_layer.getFeatures()] self.assertEqual(geom, ['Point (1 2)', '', 'Point (3 2)', 'Point (4 3)'])
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)
def test_updateFeatures(self): ol, offline_layer = self._testInit() # Edit feature 2 feat2 = self._getFeatureByAttribute(offline_layer, 'name', "'name 2'") self.assertTrue(offline_layer.startEditing()) self.assertTrue(offline_layer.changeAttributeValue(feat2.id(), offline_layer.fields().lookupField('name'), 'name 2 edited')) self.assertTrue(offline_layer.changeGeometry(feat2.id(), QgsGeometry.fromPointXY(QgsPointXY(33.0, 60.0)))) self.assertTrue(offline_layer.commitChanges()) feat2 = self._getFeatureByAttribute(offline_layer, 'name', "'name 2 edited'") self.assertTrue(ol.isOfflineProject()) # Sync ol.synchronize() sleep(2) # Does anybody know why the sleep is needed? Is that a threaded WFS consequence? online_layer = list(self.registry.mapLayers().values())[0] self.assertTrue(online_layer.isValid()) self.assertFalse(online_layer.name().find('(offline)') > -1) self.assertEqual(len([f for f in online_layer.getFeatures()]), len(TEST_FEATURES)) # Check that data have changed in the backend (raise exception if not found) feat2 = self._getFeatureByAttribute(self._getLayer('test_point'), 'name', "'name 2 edited'") feat2 = self._getFeatureByAttribute(online_layer, 'name', "'name 2 edited'") self.assertEqual(feat2.geometry().asPoint().toString(), QgsPointXY(33.0, 60.0).toString()) # Check that all other features have not changed layer = self._getLayer('test_point') self.assertTrue(self._compareFeature(layer, TEST_FEATURES[1 - 1])) self.assertTrue(self._compareFeature(layer, TEST_FEATURES[3 - 1])) self.assertTrue(self._compareFeature(layer, TEST_FEATURES[4 - 1])) # Test for regression on double sync (it was a SEGFAULT) # goes offline ol = QgsOfflineEditing() offline_layer = list(self.registry.mapLayers().values())[0] # Edit feature 2 feat2 = self._getFeatureByAttribute(offline_layer, 'name', "'name 2 edited'") self.assertTrue(offline_layer.startEditing()) self.assertTrue(offline_layer.changeAttributeValue(feat2.id(), offline_layer.fields().lookupField('name'), 'name 2')) self.assertTrue(offline_layer.changeGeometry(feat2.id(), QgsGeometry.fromPointXY(TEST_FEATURES[1][2]))) # Edit feat 4 feat4 = self._getFeatureByAttribute(offline_layer, 'name', "'name 4'") self.assertTrue(offline_layer.changeAttributeValue(feat4.id(), offline_layer.fields().lookupField('name'), 'name 4 edited')) self.assertTrue(offline_layer.commitChanges()) # Sync ol.synchronize() # Does anybody knows why the sleep is needed? Is that a threaded WFS consequence? sleep(1) online_layer = list(self.registry.mapLayers().values())[0] layer = self._getLayer('test_point') # Check that data have changed in the backend (raise exception if not found) feat4 = self._getFeatureByAttribute(layer, 'name', "'name 4 edited'") feat4 = self._getFeatureByAttribute(online_layer, 'name', "'name 4 edited'") feat2 = self._getFeatureByAttribute(layer, 'name', "'name 2'") feat2 = self._getFeatureByAttribute(online_layer, 'name', "'name 2'") # Check that all other features have not changed layer = self._getLayer('test_point') self.assertTrue(self._compareFeature(layer, TEST_FEATURES[1 - 1])) self.assertTrue(self._compareFeature(layer, TEST_FEATURES[2 - 1])) self.assertTrue(self._compareFeature(layer, TEST_FEATURES[3 - 1]))
def testAddFeatures(self): # test adding features to an edit buffer layer = createEmptyLayer() self.assertTrue(layer.startEditing()) self.assertEqual(layer.editBuffer().addedFeatures(), {}) self.assertFalse(layer.editBuffer().isFeatureAdded(1)) self.assertFalse(layer.editBuffer().isFeatureAdded(3)) # add two features f1 = QgsFeature(layer.fields(), 1) f1.setGeometry(QgsGeometry.fromPointXY(QgsPointXY(1, 2))) f1.setAttributes(["test", 123]) self.assertTrue(layer.addFeature(f1)) f2 = QgsFeature(layer.fields(), 2) f2.setGeometry(QgsGeometry.fromPointXY(QgsPointXY(2, 4))) f2.setAttributes(["test2", 246]) self.assertTrue(layer.addFeature(f2)) # test contents of buffer added = layer.editBuffer().addedFeatures() new_feature_ids = list(added.keys()) self.assertEqual(added[new_feature_ids[0]]['fldtxt'], 'test2') self.assertEqual(added[new_feature_ids[0]]['fldint'], 246) self.assertEqual(added[new_feature_ids[1]]['fldtxt'], 'test') self.assertEqual(added[new_feature_ids[1]]['fldint'], 123) self.assertTrue(layer.editBuffer().isFeatureAdded(new_feature_ids[0])) self.assertTrue(layer.editBuffer().isFeatureAdded(new_feature_ids[1])) # check if error in case adding not adaptable geometry # eg. a Multiline in a Line layer = createEmptyLinestringLayer() self.assertTrue(layer.startEditing()) self.assertEqual(layer.editBuffer().addedFeatures(), {}) self.assertFalse(layer.editBuffer().isFeatureAdded(1)) self.assertFalse(layer.editBuffer().isFeatureAdded(3)) # add a features with a multi line geometry of not touched lines => # cannot be forced to be linestring multiline = [ [QgsPointXY(1, 1), QgsPointXY(2, 2)], [QgsPointXY(3, 3), QgsPointXY(4, 4)], ] f1 = QgsFeature(layer.fields(), 1) f1.setGeometry(QgsGeometry.fromMultiPolylineXY(multiline)) f1.setAttributes(["test", 123]) self.assertTrue(layer.addFeatures([f1])) self.assertFalse(layer.commitChanges())
def createReferencingLayer(): layer = QgsVectorLayer("Point?field=fldtxt:string&field=foreignkey:integer", "referencinglayer", "memory") pr = layer.dataProvider() f1 = QgsFeature() f1.setFields(layer.fields()) f1.setAttributes(["test1", 123]) f1.setGeometry(QgsGeometry.fromPointXY(QgsPointXY(100, 200))) f2 = QgsFeature() f2.setFields(layer.fields()) f2.setAttributes(["test2", 123]) f2.setGeometry(QgsGeometry.fromPointXY(QgsPointXY(101, 201))) assert pr.addFeatures([f1, f2]) return layer
def get_utm_epsg(longitude, latitude, crs=None): """Return epsg code of the utm zone according to X, Y coordinates. By default, the CRS is EPSG:4326. If the CRS is provided, first X,Y will be reprojected from the input CRS to WGS84. The code is based on the code: http://gis.stackexchange.com/questions/34401 :param longitude: The longitude. :type longitude: float :param latitude: The latitude. :type latitude: float :param crs: The coordinate reference system of the latitude, longitude. :type crs: QgsCoordinateReferenceSystem """ if crs is None or crs.authid() == 'EPSG:4326': epsg = 32600 if latitude < 0.0: epsg += 100 epsg += get_utm_zone(longitude) return epsg else: epsg_4326 = QgsCoordinateReferenceSystem('EPSG:4326') transform = QgsCoordinateTransform( crs, epsg_4326, QgsProject.instance()) geom = QgsGeometry.fromPointXY(QgsPointXY(longitude, latitude)) geom.transform(transform) point = geom.asPoint() # The point is now in 4326, we can call the function again. return get_utm_epsg(point.x(), point.y())
def test_expressionRequiresFormScope(self): res = list(QgsValueRelationFieldFormatter.expressionFormAttributes("current_value('ONE') AND current_value('TWO')")) res = sorted(res) self.assertEqual(res, ['ONE', 'TWO']) res = list(QgsValueRelationFieldFormatter.expressionFormVariables("@current_geometry")) self.assertEqual(res, ['current_geometry']) self.assertFalse(QgsValueRelationFieldFormatter.expressionRequiresFormScope("")) self.assertTrue(QgsValueRelationFieldFormatter.expressionRequiresFormScope("current_value('TWO')")) self.assertTrue(QgsValueRelationFieldFormatter.expressionRequiresFormScope("current_value ( 'TWO' )")) self.assertTrue(QgsValueRelationFieldFormatter.expressionRequiresFormScope("@current_geometry")) self.assertTrue(QgsValueRelationFieldFormatter.expressionIsUsable("", QgsFeature())) self.assertFalse(QgsValueRelationFieldFormatter.expressionIsUsable("@current_geometry", QgsFeature())) self.assertFalse(QgsValueRelationFieldFormatter.expressionIsUsable("current_value ( 'TWO' )", QgsFeature())) layer = QgsVectorLayer("none?field=pkid:integer&field=decoded:string", "layer", "memory") self.assertTrue(layer.isValid()) QgsProject.instance().addMapLayer(layer) f = QgsFeature(layer.fields()) f.setAttributes([1, 'value']) point = QgsGeometry.fromPointXY(QgsPointXY(123, 456)) f.setGeometry(point) self.assertTrue(QgsValueRelationFieldFormatter.expressionIsUsable("current_geometry", f)) self.assertFalse(QgsValueRelationFieldFormatter.expressionIsUsable("current_value ( 'TWO' )", f)) self.assertTrue(QgsValueRelationFieldFormatter.expressionIsUsable("current_value ( 'pkid' )", f)) self.assertTrue(QgsValueRelationFieldFormatter.expressionIsUsable("@current_geometry current_value ( 'pkid' )", f)) QgsProject.instance().removeMapLayer(layer.id())
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 processAlgorithm(self, parameters, context, feedback): source = self.parameterAsSource(parameters, self.INPUT, context) pointCount = self.parameterAsDouble(parameters, self.POINTS_NUMBER, context) minDistance = self.parameterAsDouble(parameters, self.MIN_DISTANCE, context) bbox = source.sourceExtent() sourceIndex = QgsSpatialIndex(source, feedback) fields = QgsFields() fields.append(QgsField('id', QVariant.Int, '', 10, 0)) (sink, dest_id) = self.parameterAsSink(parameters, self.OUTPUT, context, fields, QgsWkbTypes.Point, source.sourceCrs()) nPoints = 0 nIterations = 0 maxIterations = pointCount * 200 total = 100.0 / pointCount if pointCount else 1 index = QgsSpatialIndex() points = dict() random.seed() while nIterations < maxIterations and nPoints < pointCount: if feedback.isCanceled(): break rx = bbox.xMinimum() + bbox.width() * random.random() ry = bbox.yMinimum() + bbox.height() * random.random() p = QgsPointXY(rx, ry) geom = QgsGeometry.fromPointXY(p) ids = sourceIndex.intersects(geom.buffer(5, 5).boundingBox()) if len(ids) > 0 and \ vector.checkMinDistance(p, index, minDistance, points): request = QgsFeatureRequest().setFilterFids(ids).setSubsetOfAttributes([]) for f in source.getFeatures(request): if feedback.isCanceled(): break tmpGeom = f.geometry() if geom.within(tmpGeom): f = QgsFeature(nPoints) f.initAttributes(1) f.setFields(fields) f.setAttribute('id', nPoints) f.setGeometry(geom) sink.addFeature(f, QgsFeatureSink.FastInsert) index.insertFeature(f) points[nPoints] = p nPoints += 1 feedback.setProgress(int(nPoints * total)) nIterations += 1 if nPoints < pointCount: feedback.pushInfo(self.tr('Could not generate requested number of random points. ' 'Maximum number of attempts exceeded.')) return {self.OUTPUT: dest_id}
def processAlgorithm(self, parameters, context, feedback): if parameters[self.INPUT] == parameters[self.HUBS]: raise QgsProcessingException( self.tr('Same layer given for both hubs and spokes')) point_source = self.parameterAsSource(parameters, self.INPUT, context) hub_source = self.parameterAsSource(parameters, self.HUBS, context) fieldName = self.parameterAsString(parameters, self.FIELD, context) units = self.UNITS[self.parameterAsEnum(parameters, self.UNIT, context)] fields = point_source.fields() fields.append(QgsField('HubName', QVariant.String)) fields.append(QgsField('HubDist', QVariant.Double)) (sink, dest_id) = self.parameterAsSink(parameters, self.OUTPUT, context, fields, QgsWkbTypes.Point, point_source.sourceCrs()) index = QgsSpatialIndex(hub_source.getFeatures(QgsFeatureRequest().setSubsetOfAttributes([]).setDestinationCrs(point_source.sourceCrs(), context.transformContext()))) distance = QgsDistanceArea() distance.setSourceCrs(point_source.sourceCrs(), context.transformContext()) distance.setEllipsoid(context.project().ellipsoid()) # Scan source points, find nearest hub, and write to output file features = point_source.getFeatures() total = 100.0 / point_source.featureCount() if point_source.featureCount() else 0 for current, f in enumerate(features): if feedback.isCanceled(): break if not f.hasGeometry(): sink.addFeature(f, QgsFeatureSink.FastInsert) continue src = f.geometry().boundingBox().center() neighbors = index.nearestNeighbor(src, 1) ft = next(hub_source.getFeatures(QgsFeatureRequest().setFilterFid(neighbors[0]).setSubsetOfAttributes([fieldName], hub_source.fields()).setDestinationCrs(point_source.sourceCrs(), context.transformContext()))) closest = ft.geometry().boundingBox().center() hubDist = distance.measureLine(src, closest) if units != self.LAYER_UNITS: hub_dist_in_desired_units = distance.convertLengthMeasurement(hubDist, units) else: hub_dist_in_desired_units = hubDist attributes = f.attributes() attributes.append(ft[fieldName]) attributes.append(hub_dist_in_desired_units) feat = QgsFeature() feat.setAttributes(attributes) feat.setGeometry(QgsGeometry.fromPointXY(src)) sink.addFeature(feat, QgsFeatureSink.FastInsert) feedback.setProgress(int(current * total)) return {self.OUTPUT: dest_id}
def test_SetGeometry(self): feat = QgsFeature() feat.setGeometry(QgsGeometry.fromPointXY(QgsPointXY(123, 456))) myGeometry = feat.geometry() myExpectedGeometry = "!None" myMessage = '\nExpected: %s\nGot: %s' % (myExpectedGeometry, myGeometry) assert myGeometry is not None, myMessage
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 testSettingFeature(self): """ test that feature is set when item moves """ a = QgsTextAnnotation() a.setFrameSizeMm(QSizeF(300 / 3.7795275, 200 / 3.7795275)) a.setFrameOffsetFromReferencePointMm(QPointF(40 / 3.7795275, 50 / 3.7795275)) a.setHasFixedMapPosition(True) a.setMapPosition(QgsPointXY(12, 34)) a.setMapPositionCrs(QgsCoordinateReferenceSystem(4326)) canvas = QgsMapCanvas() canvas.setDestinationCrs(QgsCoordinateReferenceSystem(4326)) canvas.setFrameStyle(0) canvas.resize(600, 400) canvas.setExtent(QgsRectangle(10, 30, 20, 35)) i = QgsMapCanvasAnnotationItem(a, canvas) # NOQA layer = QgsVectorLayer("Point?crs=EPSG:4326&field=station:string&field=suburb:string", 'test', "memory") canvas.setLayers([layer]) f = QgsFeature(layer.fields()) f.setGeometry(QgsGeometry.fromPointXY(QgsPointXY(14, 31))) f.setValid(True) f.setAttributes(['hurstbridge', 'somewhere']) self.assertTrue(layer.dataProvider().addFeatures([f])) a.setMapLayer(layer) self.assertFalse(a.associatedFeature().isValid()) a.setMapPosition(QgsPointXY(14, 31)) self.assertTrue(a.associatedFeature().isValid()) self.assertEqual(a.associatedFeature().attributes()[0], 'hurstbridge') a.setMapPosition(QgsPointXY(17, 31)) self.assertFalse(a.associatedFeature().isValid())
def writePoint(self, xy, gipodId, owner, description, startDateTime, endDateTime, importantHindrance, detail, cities=[], initiator=None, recurrencePattern=None): fet = QgsFeature(self.fields) fet['gipodId'] = gipodId fet['owner'] = owner fet['description'] = description if self.KML: fet['begin'] = startDateTime.split("T")[0] fet['end'] = endDateTime.split("T")[0] if importantHindrance: fet['icon'] = "http://api.gipod.vlaanderen.be/ws/v1/icon/workassignment?important=true" else: fet['icon'] = "http://api.gipod.vlaanderen.be/ws/v1/icon/workassignment?important=false" fet['beginDate'] = startDateTime fet['endDate'] = endDateTime fet['hinder'] = importantHindrance fet['link'] = detail fet['cities'] = ", ".join(cities) if initiator and self.manifestation: fet['intiatief'] = initiator if recurrencePattern and self.manifestation: fet['patroon'] = recurrencePattern prjPt = self._makeCRSpoint( xy ) fet.setGeometry(QgsGeometry.fromPointXY(prjPt)) self.gipodProvider.addFeatures([ fet ])
def testAddZ(self): """Check adding z values to non z input.""" input = QgsVectorLayer( 'Point?crs=epsg:4326&field=name:string(20)', 'test', 'memory') self.assertTrue(input.isValid(), 'Provider not initialized') ft = QgsFeature() ft.setGeometry(QgsGeometry.fromPointXY(QgsPointXY(10, 10))) myResult, myFeatures = input.dataProvider().addFeatures([ft]) self.assertTrue(myResult) self.assertTrue(myFeatures) dest_file_name = os.path.join(str(QDir.tempPath()), 'add_z.geojson') options = QgsVectorFileWriter.SaveVectorOptions() options.overrideGeometryType = QgsWkbTypes.PointZ options.driverName = 'GeoJSON' write_result, error_message = QgsVectorFileWriter.writeAsVectorFormat( input, dest_file_name, options) self.assertEqual(write_result, QgsVectorFileWriter.NoError, error_message) # Open result and check created_layer = QgsVectorLayer(dest_file_name, 'test', 'ogr') self.assertTrue(created_layer.isValid()) f = next(created_layer.getFeatures(QgsFeatureRequest())) self.assertEqual(f.geometry().asWkt(), 'PointZ (10 10 0)')
def test_CreateFeature(self): feat = QgsFeature() feat.initAttributes(1) feat.setAttribute(0, "text") feat.setGeometry(QgsGeometry.fromPointXY(QgsPointXY(123, 456))) myId = feat.id() myExpectedId = 0 myMessage = '\nExpected: %s\nGot: %s' % (myExpectedId, myId) assert myId == myExpectedId, myMessage
def testCreateFeature(self): """ test creating a feature respecting defaults and constraints """ layer = QgsVectorLayer("Point?field=fldtxt:string&field=fldint:integer&field=flddbl:double", "addfeat", "memory") # add a bunch of features f = QgsFeature() f.setAttributes(["test", 123, 1.0]) f1 = QgsFeature(2) f1.setAttributes(["test_1", 124, 1.1]) f2 = QgsFeature(3) f2.setAttributes(["test_2", 125, 2.4]) f3 = QgsFeature(4) f3.setAttributes(["test_3", 126, 1.7]) f4 = QgsFeature(5) f4.setAttributes(["superpig", 127, 0.8]) self.assertTrue(layer.dataProvider().addFeatures([f, f1, f2, f3, f4])) # no layer self.assertFalse(QgsVectorLayerUtils.createFeature(None).isValid()) # basic tests f = QgsVectorLayerUtils.createFeature(layer) self.assertTrue(f.isValid()) self.assertEqual(f.fields(), layer.fields()) self.assertFalse(f.hasGeometry()) self.assertEqual(f.attributes(), [NULL, NULL, NULL]) # set geometry g = QgsGeometry.fromPointXY(QgsPointXY(100, 200)) f = QgsVectorLayerUtils.createFeature(layer, g) self.assertTrue(f.hasGeometry()) self.assertEqual(f.geometry().asWkt(), g.asWkt()) # using attribute map f = QgsVectorLayerUtils.createFeature(layer, attributes={0: 'a', 2: 6.0}) self.assertEqual(f.attributes(), ['a', NULL, 6.0]) # layer with default value expression layer.setDefaultValueDefinition(2, QgsDefaultValue('3*4')) f = QgsVectorLayerUtils.createFeature(layer) self.assertEqual(f.attributes(), [NULL, NULL, 12.0]) # we expect the default value expression to take precedence over the attribute map f = QgsVectorLayerUtils.createFeature(layer, attributes={0: 'a', 2: 6.0}) self.assertEqual(f.attributes(), ['a', NULL, 12.0]) # layer with default value expression based on geometry layer.setDefaultValueDefinition(2, QgsDefaultValue('3*$x')) f = QgsVectorLayerUtils.createFeature(layer, g) self.assertEqual(f.attributes(), [NULL, NULL, 300.0]) layer.setDefaultValueDefinition(2, QgsDefaultValue(None)) # test with violated unique constraints layer.setFieldConstraint(1, QgsFieldConstraints.ConstraintUnique) f = QgsVectorLayerUtils.createFeature(layer, attributes={0: 'test_1', 1: 123}) self.assertEqual(f.attributes(), ['test_1', 128, NULL]) layer.setFieldConstraint(0, QgsFieldConstraints.ConstraintUnique) f = QgsVectorLayerUtils.createFeature(layer, attributes={0: 'test_1', 1: 123}) self.assertEqual(f.attributes(), ['test_4', 128, NULL])
def testAdd(self): self.layer.startEditing() f = QgsFeature() f.setAttributes(["test", 8]) f.setGeometry(QgsGeometry.fromPointXY(QgsPointXY(100, 200))) self.layer.addFeature(f) self.assertEqual(self.am.rowCount(), 11)
def createReferencedLayer(): layer = QgsVectorLayer( "Point?field=x:string&field=y:integer&field=z:integer", "referencedlayer", "memory") pr = layer.dataProvider() f1 = QgsFeature() f1.setFields(layer.fields()) f1.setAttributes(["foo", 123, 321]) f1.setGeometry(QgsGeometry.fromPointXY(QgsPointXY(1, 1))) f2 = QgsFeature() f2.setFields(layer.fields()) f2.setAttributes(["bar", 456, 654]) f2.setGeometry(QgsGeometry.fromPointXY(QgsPointXY(2, 2))) f3 = QgsFeature() f3.setFields(layer.fields()) f3.setAttributes(["foobar'bar", 789, 554]) f3.setGeometry(QgsGeometry.fromPointXY(QgsPointXY(2, 3))) assert pr.addFeatures([f1, f2, f3]) return layer
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 setUp(self): """ create a layer with one feature """ self.layer = QgsVectorLayer("Point?crs=EPSG:21781&field=fldtxt:string&field=fldint:integer", "addfeat", "memory") pr = self.layer.dataProvider() # NOQA f = QgsFeature() f.setAttributes(["Hello World", 123]) f.setGeometry(QgsGeometry.fromPointXY(QgsPointXY(600000, 200000)))
def createLayerWithOnePoint(): layer = QgsVectorLayer("Point?field=fldtxt:string&field=fldint:integer", "addfeat", "memory") pr = layer.dataProvider() f = QgsFeature() f.setAttributes(["test", 123]) f.setGeometry(QgsGeometry.fromPointXY(QgsPointXY(100, 200))) assert pr.addFeatures([f]) assert layer.featureCount() == 1 return layer
def save_sample_points(self, pointData, profileName="", layername="elevation_samples", saveToFile=None, sender=None): '' attributes = [ QgsField("name", QVariant.String), QgsField("Dist", QVariant.Double), QgsField("z_taw", QVariant.Double) ] if not QgsProject.instance().mapLayer(self.sampleslayerid) : self.sampleslayer = QgsVectorLayer("Point", layername, "memory") self.samplesProvider = self.sampleslayer.dataProvider() self.samplesProvider.addAttributes(attributes) self.sampleslayer.updateFields() fields= self.sampleslayer.fields() for point in pointData: #create the geometry pt = QgsPointXY( point[1], point[2] ) # add a feature fet = QgsFeature(fields) #set geometry fromCrs = QgsCoordinateReferenceSystem(4326) xform = QgsCoordinateTransform( fromCrs, self.sampleslayer.crs(), QgsProject.instance() ) prjPt = xform.transform( pt ) fet.setGeometry(QgsGeometry.fromPointXY(prjPt)) fet['name'] = profileName fet['dist'] = point[0] if point[3] > -9999 : fet['z_taw'] = point[3] self.samplesProvider.addFeatures([ fet ]) self.sampleslayer.updateExtents() if saveToFile and not QgsProject.instance().mapLayer(self.sampleslayerid): save = self._saveToFile( sender, os.path.join( self.startFolder, layername)) if save: fpath, flType = save error, msg = QgsVectorFileWriter.writeAsVectorFormat(layer=self.sampleslayer, fileName=fpath, fileEncoding="utf-8", driverName=flType ) if error == QgsVectorFileWriter.NoError: self.sampleslayer = QgsVectorLayer( fpath , layername, "ogr") self.samplesProvider = self.sampleslayer.dataProvider() else: del self.sampleslayer, self.samplesProvider return else: del self.sampleslayer, self.samplesProvider return # add layer if not already print( QgsProject.instance().addMapLayer(self.sampleslayer) ) # store layer id and refresh self.sampleslayerid = self.sampleslayer.id() self.iface.mapCanvas().refresh()
def testChangeAttributeValues(self): # test changing attributes values from an edit buffer # make a layer with two features layer = createEmptyLayer() self.assertTrue(layer.startEditing()) # add two features f1 = QgsFeature(layer.fields(), 1) f1.setGeometry(QgsGeometry.fromPointXY(QgsPointXY(1, 2))) f1.setAttributes(["test", 123]) self.assertTrue(layer.addFeature(f1)) f2 = QgsFeature(layer.fields(), 2) f2.setGeometry(QgsGeometry.fromPointXY(QgsPointXY(2, 4))) f2.setAttributes(["test2", 246]) self.assertTrue(layer.addFeature(f2)) layer.commitChanges() layer.startEditing() self.assertEqual(layer.editBuffer().changedAttributeValues(), {}) self.assertFalse(layer.editBuffer().isFeatureAttributesChanged(1)) self.assertFalse(layer.editBuffer().isFeatureAttributesChanged(2)) # change attribute values layer.changeAttributeValue(1, 0, 'a') # test contents of buffer self.assertEqual(list(layer.editBuffer().changedAttributeValues().keys()), [1]) self.assertEqual(layer.editBuffer().changedAttributeValues()[1], {0: 'a'}) self.assertTrue(layer.editBuffer().isFeatureAttributesChanged(1)) self.assertFalse(layer.editBuffer().isFeatureAttributesChanged(2)) layer.changeAttributeValue(2, 1, 5) # test contents of buffer self.assertEqual(set(layer.editBuffer().changedAttributeValues().keys()), set([1, 2])) self.assertEqual(layer.editBuffer().changedAttributeValues()[1], {0: 'a'}) self.assertEqual(layer.editBuffer().changedAttributeValues()[2], {1: 5}) self.assertTrue(layer.editBuffer().isFeatureAttributesChanged(1)) self.assertTrue(layer.editBuffer().isFeatureAttributesChanged(2))
def processAlgorithm(self, parameters, context, feedback): source = self.parameterAsSource(parameters, self.INPUT, context) strategy = self.parameterAsEnum(parameters, self.STRATEGY, context) minDistance = self.parameterAsDouble(parameters, self.MIN_DISTANCE, context) expression = QgsExpression( self.parameterAsString(parameters, self.EXPRESSION, context)) if expression.hasParserError(): raise ProcessingException(expression.parserErrorString()) expressionContext = self.createExpressionContext(parameters, context) if not expression.prepare(expressionContext): raise ProcessingException( self.tr('Evaluation error: {0}').format( expression.evalErrorString())) fields = QgsFields() fields.append(QgsField('id', QVariant.Int, '', 10, 0)) (sink, dest_id) = self.parameterAsSink(parameters, self.OUTPUT, context, fields, QgsWkbTypes.Point, source.sourceCrs()) da = QgsDistanceArea() da.setSourceCrs(source.sourceCrs(), context.transformContext()) da.setEllipsoid(context.project().ellipsoid()) total = 100.0 / source.featureCount() if source.featureCount() else 0 for current, f in enumerate(source.getFeatures()): if feedback.isCanceled(): break expressionContext.setFeature(f) value = expression.evaluate(expressionContext) if expression.hasEvalError(): feedback.pushInfo( self.tr('Evaluation error for feature ID {}: {}').format( f.id(), expression.evalErrorString())) continue fGeom = f.geometry() bbox = fGeom.boundingBox() if strategy == 0: pointCount = int(value) else: pointCount = int(round(value * da.measureArea(fGeom))) if pointCount == 0: feedback.pushInfo( "Skip feature {} as number of points for it is 0.") continue index = QgsSpatialIndex() points = dict() nPoints = 0 nIterations = 0 maxIterations = pointCount * 200 total = 100.0 / pointCount if pointCount else 1 random.seed() while nIterations < maxIterations and nPoints < pointCount: if feedback.isCanceled(): break rx = bbox.xMinimum() + bbox.width() * random.random() ry = bbox.yMinimum() + bbox.height() * random.random() p = QgsPointXY(rx, ry) geom = QgsGeometry.fromPointXY(p) if geom.within(fGeom) and \ vector.checkMinDistance(p, index, minDistance, points): f = QgsFeature(nPoints) f.initAttributes(1) f.setFields(fields) f.setAttribute('id', nPoints) f.setGeometry(geom) sink.addFeature(f, QgsFeatureSink.FastInsert) index.insertFeature(f) points[nPoints] = p nPoints += 1 feedback.setProgress(int(nPoints * total)) nIterations += 1 if nPoints < pointCount: feedback.pushInfo( self.tr('Could not generate requested number of random ' 'points. Maximum number of attempts exceeded.')) feedback.setProgress(0) return {self.OUTPUT: dest_id}
def add_point_to_layer(writer, point, attributes): geometry = QgsGeometry.fromPointXY(point) feature = QgsFeature() feature.setAttributes(attributes) feature.setGeometry(geometry) writer.addFeature(feature)
def processAlgorithm(self, parameters, context, feedback): uavImage = self.parameterAsRasterLayer(parameters, self.INPUT, context) feedback.pushInfo(self.tr('Processing image source: ')+self.tr(uavImage.source())) sourceCRS = self.parameterAsCrs(parameters, self.SOURCE_CRS, context) if sourceCRS is None or not sourceCRS.isValid(): sourceCRS = uavImage.crs() destinationCRS = self.parameterAsCrs(parameters, self.DESTINATION_CRS, context) if destinationCRS is None or not destinationCRS.isValid(): feedback.pushInfo(self.tr('Getting destination CRS from source image')) destinationCRS = sourceCRS feedback.pushInfo(self.tr('Source CRS is: ')+self.tr(sourceCRS.authid())) feedback.pushInfo(self.tr('Destination CRS is: ')+self.tr(destinationCRS.authid())) # set fields for footprint and nadir vectors fields = QgsFields() # fields.append(QgsField('gimball_pitch', QVariant.Double)) # fields.append(QgsField('gimball_roll', QVariant.Double)) # fields.append(QgsField('gimball_jaw', QVariant.Double)) # fields.append(QgsField('relative_altitude', QVariant.Double)) # fields.append(QgsField('image', QVariant.String)) # fields.append(QgsField('camera_model', QVariant.String)) # fields.append(QgsField('camera_vertical_FOV', QVariant.Double)) # fields.append(QgsField('camera_horizontal_FOV', QVariant.Double)) # (footprintSink, footprint_dest_id) = self.parameterAsSink( # parameters, # self.OUTPUT_FOOTPRINT, # context, # fields, # QgsWkbTypes.Polygon, # destinationCRS) # if footprintSink is None: # raise QgsProcessingException(self.invalidSinkError(parameters, self.OUTPUT_FOOTPRINT)) (nadirSink, nadir_dest_id) = self.parameterAsSink( parameters, self.OUTPUT_NADIR, context, fields, QgsWkbTypes.Point, destinationCRS) if nadirSink is None: raise QgsProcessingException(self.invalidSinkError(parameters, self.OUTPUT_NADIR)) horizontalFOV = self.parameterAsDouble(parameters, self.HORIZONTAL_FOV, context) verticalFOV = self.parameterAsDouble(parameters, self.VERTICAL_FOV, context) useImageRatio = self.parameterAsBoolean(parameters, self.USE_IMAGE_RATIO_FOR_VERTICAL_FOV, context) verticalFOV_multiplier = self.parameterAsDouble(parameters, self.VERTICAL_FOV_MULTIPLIER, context) nadirToBottomOffset = self.parameterAsDouble(parameters, self.NADIR_TO_BOTTOM_OFFSET, context) nadirToupperOffset = self.parameterAsDouble(parameters, self.NADIR_TO_UPPPER_OFFSET, context) # extract exif and XMP data try: gdal.UseExceptions() dataFrame = gdal.Open(uavImage.source(), gdal.GA_ReadOnly) domains = dataFrame.GetMetadataDomainList() # get exif metadata exifTags = dataFrame.GetMetadata() for key, value in exifTags.items(): #print(key, ':', value) pass # select metadata from XMP domain only droneMetadata = {} for domain in domains: metadata = dataFrame.GetMetadata(domain) # skip not relevant tags if isinstance(metadata, dict): for key, value in metadata.items(): #print(domain, "--", key, ":", value) pass # probably XMPs if isinstance(metadata, list): if domain == 'xml:XMP': # parse xml root = ElementTree.XML(metadata[0]) xmldict = XmlDictConfig(root) # skip first element containing only description and domain info subdict = list(xmldict.values())[0] # get XMP tags subdict = list(subdict.values())[0] # parse XMP stuffs removing head namespace in the key # e.g. # {http://www.dji.com/drone-dji/1.0/}AbsoluteAltitude # become # AbsoluteAltitude for key, value in subdict.items(): #print(domain, '--', key, value) key = key.split('}')[1] droneMetadata[key] = value except Exception as ex: raise QgsProcessingException(str(ex)) # extract all important tagged information about the image # get image lat/lon that will be the coordinates of nadir point # converted to destination CRS lat = _convert_to_degress(exifTags['EXIF_GPSLatitude']) emisphere = exifTags['EXIF_GPSLatitudeRef'] lon = _convert_to_degress(exifTags['EXIF_GPSLongitude']) lonReference = exifTags['EXIF_GPSLongitudeRef'] if emisphere == 'S': lat = -lat if lonReference == 'W': lon = -lon exifDateTime = exifTags['EXIF_DateTime'] feedback.pushInfo("EXIF_DateTime: "+exifDateTime) exifImageWidth = exifTags['EXIF_PixelXDimension'] exifImageLength = exifTags['EXIF_PixelYDimension'] imageRatio = float(exifImageWidth)/float(exifImageLength) feedback.pushInfo("EXIF_PixelXDimension: "+exifImageWidth) feedback.pushInfo("EXIF_PixelYDimension: "+exifImageLength) feedback.pushInfo("Image ratio: "+str(imageRatio)) # drone especific metadata droneMaker = exifTags['EXIF_Make'] droneModel = exifTags['EXIF_Model'] feedback.pushInfo("EXIF_Make: "+droneMaker) feedback.pushInfo("EXIF_Model: "+droneModel) # drone maker substitute XMP drone dictKey dictKey = droneMaker relativeAltitude = float(droneMetadata['RelativeAltitude']) feedback.pushInfo(self.tr("XMP {}:RelativeAltitude: ".format(dictKey))+str(relativeAltitude)) gimballRoll = float(droneMetadata['GimbalRollDegree']) gimballPitch = float(droneMetadata['GimbalPitchDegree']) gimballYaw = float(droneMetadata['GimbalYawDegree']) feedback.pushInfo("XMP {}:GimbalRollDegree: ".format(dictKey)+str(gimballRoll)) feedback.pushInfo("XMP {}:GimbalPitchDegree: ".format(dictKey)+str(gimballPitch)) feedback.pushInfo("XMP {}:GimbalYawDegree: ".format(dictKey)+str(gimballYaw)) flightRoll = float(droneMetadata['FlightRollDegree']) flightPitch = float(droneMetadata['FlightPitchDegree']) flightYaw = float(droneMetadata['FlightYawDegree']) feedback.pushInfo("XMP {}:FlightRollDegree: ".format(dictKey)+str(flightRoll)) feedback.pushInfo("XMP {}:FlightPitchDegree: ".format(dictKey)+str(flightPitch)) feedback.pushInfo("XMP {}:FlightYawDegree: ".format(dictKey)+str(flightYaw)) feedback.pushInfo(self.tr("Horizontal FOV: ")+str(horizontalFOV)) if useImageRatio: verticalFOV = (horizontalFOV/imageRatio)*verticalFOV_multiplier feedback.pushInfo(self.tr("Vertical FOV basing on image ratio: ")+str(verticalFOV)) else: feedback.pushInfo(self.tr("Vertical FOV: ")+str(verticalFOV)) # do calculation inspired by: # https://photo.stackexchange.com/questions/56596/how-do-i-calculate-the-ground-footprint-of-an-aerial-camera # distance of the nearest point to nadir (bottom distance) bottomDistance = relativeAltitude*(math.tan(math.radians(90 - gimballPitch - 0.5*verticalFOV))) # distance of the farest point to nadir (upper distance) upperDistance = relativeAltitude*(math.tan(math.radians(90 - gimballPitch + 0.5*verticalFOV))) feedback.pushInfo(self.tr("Northing (degree): ")+str(gimballYaw)) feedback.pushInfo(self.tr("Nadir to bottom distance (metre): ")+str(bottomDistance)) feedback.pushInfo(self.tr("Nadir to upper distance (metre): ")+str(upperDistance)) # populate nadir layer droneLocation = QgsPoint(lon, lat) tr = QgsCoordinateTransform(sourceCRS, destinationCRS, QgsProject.instance()) droneLocation.transform(tr) feedback.pushInfo(self.tr("Nadir coordinates (lon, lat): ")+'{}, {}'.format(droneLocation.x(), droneLocation.y())) nadirGeometry = QgsGeometry.fromPointXY(QgsPointXY(droneLocation.x(), droneLocation.y())) feature = QgsFeature() feature.setGeometry(nadirGeometry) nadirSink.addFeature(feature, QgsFeatureSink.FastInsert) # create a memory layer with nadir point to be input to "native:wedgebuffers" algorithm # it's not possible to use directly the FeatureSink becaseu can't be accepted by processing.run. # the reason is that a generic sink can be also NOT a layer but a more generic sink where features # can't be recovered. tempNadirLayer = QgsVectorLayer('Point?crs={}'.format(destinationCRS.authid()), 'tempNadirLayer', 'memory' ) provider = tempNadirLayer.dataProvider() feature = QgsFeature() feature.setGeometry(nadirGeometry) provider.addFeatures([feature]) # create polygon using wedge buffer processign algorithm parameters = { 'INPUT': tempNadirLayer, 'AZIMUTH': gimballYaw, 'WIDTH': horizontalFOV, 'OUTER_RADIUS': abs(bottomDistance) + nadirToBottomOffset, 'INNER_RADIUS': abs(upperDistance) + nadirToupperOffset, 'OUTPUT': parameters[self.OUTPUT_FOOTPRINT] } wedge_buffer_result = processing.run("native:wedgebuffers", parameters, is_child_algorithm=True, context = context, feedback = feedback) # Return the results results = { self.OUTPUT_FOOTPRINT: wedge_buffer_result['OUTPUT'], self.OUTPUT_NADIR: nadir_dest_id, } return results
def processAlgorithm(self, parameters, context, feedback): if parameters[self.INPUT] == parameters[self.HUBS]: raise QgsProcessingException( self.tr('Same layer given for both hubs and spokes')) point_source = self.parameterAsSource(parameters, self.INPUT, context) if point_source is None: raise QgsProcessingException( self.invalidSourceError(parameters, self.INPUT)) hub_source = self.parameterAsSource(parameters, self.HUBS, context) if hub_source is None: raise QgsProcessingException( self.invalidSourceError(parameters, self.HUBS)) fieldName = self.parameterAsString(parameters, self.FIELD, context) units = self.UNITS[self.parameterAsEnum(parameters, self.UNIT, context)] fields = point_source.fields() fields.append(QgsField('HubName', QVariant.String)) fields.append(QgsField('HubDist', QVariant.Double)) (sink, dest_id) = self.parameterAsSink(parameters, self.OUTPUT, context, fields, QgsWkbTypes.Point, point_source.sourceCrs()) if sink is None: raise QgsProcessingException( self.invalidSinkError(parameters, self.OUTPUT)) index = QgsSpatialIndex( hub_source.getFeatures(QgsFeatureRequest().setSubsetOfAttributes( []).setDestinationCrs(point_source.sourceCrs(), context.transformContext()))) distance = QgsDistanceArea() distance.setSourceCrs(point_source.sourceCrs(), context.transformContext()) distance.setEllipsoid(context.project().ellipsoid()) # Scan source points, find nearest hub, and write to output file features = point_source.getFeatures() total = 100.0 / point_source.featureCount( ) if point_source.featureCount() else 0 for current, f in enumerate(features): if feedback.isCanceled(): break if not f.hasGeometry(): sink.addFeature(f, QgsFeatureSink.FastInsert) continue src = f.geometry().boundingBox().center() neighbors = index.nearestNeighbor(src, 1) ft = next( hub_source.getFeatures(QgsFeatureRequest().setFilterFid( neighbors[0]).setSubsetOfAttributes( [fieldName], hub_source.fields()).setDestinationCrs( point_source.sourceCrs(), context.transformContext()))) closest = ft.geometry().boundingBox().center() hubDist = distance.measureLine(src, closest) if units != self.LAYER_UNITS: hub_dist_in_desired_units = distance.convertLengthMeasurement( hubDist, units) else: hub_dist_in_desired_units = hubDist attributes = f.attributes() attributes.append(ft[fieldName]) attributes.append(hub_dist_in_desired_units) feat = QgsFeature() feat.setAttributes(attributes) feat.setGeometry(QgsGeometry.fromPointXY(src)) sink.addFeature(feat, QgsFeatureSink.FastInsert) feedback.setProgress(int(current * total)) return {self.OUTPUT: dest_id}
def processAlgorithm(self, parameters, context, feedback): layer = self.parameterAsVectorLayer(parameters, self.Polygons, context) aMethod = parameters[self.Method] Threshold = parameters[self.T] mDict = {0: "Centerlines", 1: "All", 2: "Circles"} Method = mDict[aMethod] context.setInvalidGeometryCheck(QgsFeatureRequest.GeometryNoCheck) def densify(polyline, interval): #based on DensifyGeometriesInterval.py output = [] for i in range(len(polyline) - 1): p1 = polyline[i] p2 = polyline[i + 1] output.append(p1) # Calculate necessary number of points between p1 and p2 pointsNumber = math.sqrt(p1.sqrDist(p2)) / interval if pointsNumber > 1: multiplier = 1.0 / float(pointsNumber) else: multiplier = 1 for j in range(int(pointsNumber)): delta = multiplier * (j + 1) x = p1.x() + delta * (p2.x() - p1.x()) y = p1.y() + delta * (p2.y() - p1.y()) output.append(QgsPointXY(x, y)) if j + 1 == pointsNumber: break output.append(polyline[len(polyline) - 1]) return output field_check = layer.fields().indexFromName('ID') if field_check == -1: pr = layer.dataProvider() pr.addAttributes([QgsField("ID", QVariant.Int)]) layer.updateFields() layer.startEditing() for feature in layer.getFeatures(): feature['ID'] = feature.id() layer.updateFeature(feature) layer.commitChanges() fet = QgsFeature() fields = QgsFields() fields.append(QgsField("ID", QVariant.Int)) field_names = ['Distance', 'RDistance', 'SP_Dist', 'SP_RDist'] for name in field_names: fields.append(QgsField(name, QVariant.Double)) fet2 = QgsFeature(fields) (writer2, dest_id) = self.parameterAsSink(parameters, self.Output, context, fields, QgsWkbTypes.LineString, layer.sourceCrs()) outDir = os.path.join(tempfile.gettempdir(), 'GA') if not os.path.exists(outDir): os.mkdir(outDir) fname = ''.join( random.choice(string.ascii_lowercase) for i in range(10)) infc = os.path.join(outDir, '%s.shp' % (fname)) Densify_Interval = parameters[self.Densify] Precision, tol = 6, 1e-6 keepNodes = set([]) fields = QgsFields() fields.append(QgsField("ID", QVariant.Int)) writer = QgsVectorFileWriter( infc, "CP1250", fields, QgsWkbTypes.Point, layer.sourceCrs(), "ESRI Shapefile") #.shp requirement of SAGA feedback.pushInfo( QCoreApplication.translate('Update', 'Creating Vertices')) total = 100.0 / layer.featureCount() for enum, feature in enumerate(layer.getFeatures()): if total != -1: feedback.setProgress(int(enum * total)) geomType = feature.geometry() geom = [] if geomType.wkbType() == QgsWkbTypes.Polygon: polygon = geomType.asPolygon() if Densify_Interval == 0: geom = chain(*polygon) else: for ring in polygon: geom.extend(densify(ring, Densify_Interval)) else: polygons = geomType.asMultiPolygon() if Densify_Interval == 0: geom = chain(*chain(*polygons)) else: for poly in polygons: p = [] for ring in poly: p.extend(densify(ring, Densify_Interval)) geom.extend(p) for points in geom: if (round(points.x(), Precision), round(points.y(), Precision)) not in keepNodes: pnt = QgsGeometry.fromPointXY( QgsPointXY(points.x(), points.y())) fet.setGeometry(pnt) fet.setAttributes([feature['ID']]) writer.addFeature(fet) keepNodes.update([(round(points.x(), Precision), round(points.y(), Precision))]) feedback.pushInfo( QCoreApplication.translate('Update', 'Creating Voronoi Polygons')) del writer tempVP = os.path.join(outDir, 'VL.shp') #.shp requirement of SAGA param = {'POINTS': infc, 'POLYGONS': tempVP, 'FRAME': 10.0} Voronoi = st.run("saga:thiessenpolygons", param, context=context, feedback=feedback) del keepNodes edges = {} feedback.pushInfo( QCoreApplication.translate('Update', 'Calculating Edges')) param = {'INPUT': Voronoi['POLYGONS'], 'OUTPUT': 'memory:'} lines = st.run("qgis:polygonstolines", param, context=context, feedback=feedback) param = {'INPUT': lines['OUTPUT'], 'OUTPUT': 'memory:'} exploded = st.run("native:explodelines", param, context=context, feedback=feedback) param = { 'INPUT': exploded['OUTPUT'], 'PREDICATE': 6, 'INTERSECT': layer, 'METHOD': 0 } st.run("native:selectbylocation", param, context=context, feedback=feedback) total = 100.0 / exploded['OUTPUT'].selectedFeatureCount() for enum, feature in enumerate(exploded['OUTPUT'].selectedFeatures()): try: if total != -1: feedback.setProgress(int(enum * total)) part = feature.geometry().asPolyline() startx = None for point in part: if startx == None: startx, starty = (round(point.x(), Precision), round(point.y(), Precision)) continue endx, endy = (round(point.x(), Precision), round(point.y(), Precision)) geom = QgsGeometry.fromPolylineXY( [QgsPointXY(startx, starty), QgsPointXY(endx, endy)]) ID = feature['ID'] Length = geom.length() if Length > tol: if ID in edges: edges[ID].add_edge((startx, starty), (endx, endy), weight=Length) else: Graph = nx.Graph() Graph.add_edge((startx, starty), (endx, endy), weight=Length) edges[ID] = Graph startx, starty = endx, endy except Exception as e: feedback.reportError( QCoreApplication.translate('Error', '%s' % (e))) feedback.pushInfo( QCoreApplication.translate( 'Update', 'Calculating %s Centerlines' % (len(edges)))) if edges: total = 100.0 / len(edges) for enum, FID in enumerate(edges): feedback.setProgress(int(enum * total)) G = edges[FID] G = max(nx.connected_component_subgraphs(G), key=len) #Largest Connected Graph try: if Threshold > 0: Threshold = int(Threshold) G2 = G.copy() G3 = G.copy() for n in range(int(Threshold)): degree = G2.degree() removeNodes = [k for k, v in degree if v == 1] G2.remove_nodes_from(removeNodes) degree = G2.degree() if len(G2) < 2: feedback.reportError( QCoreApplication.translate( 'Update', 'No centerline found after trimming dangles for polygon ID %s - skipping' % (FID))) continue endPoints = [k for k, v in degree if v == 1] G3.remove_edges_from(G2.edges) for source in endPoints: length, path = nx.single_source_dijkstra( G3, source, weight='weight') Index = max(length, key=length.get) G2.add_path(path[Index]) del G3 source = list( G2.nodes())[0] #Get length along all paths for n in range(2): length, path = nx.single_source_dijkstra( G, source, weight='weight') Index = max(length, key=length.get) source = path[Index][-1] length2, path2 = nx.single_source_dijkstra( G, source, weight='weight') for p in G2.edges: points = [] points.append(QgsPointXY(p[0][0], p[0][1])) points.append(QgsPointXY(p[1][0], p[1][1])) D = max([ length[(p[0][0], p[0][1])], length[(p[1][0], p[1][1])] ]) D2 = max([ length2[(p[0][0], p[0][1])], length2[(p[1][0], p[1][1])] ]) dx = path[Index][0][0] - p[1][0] dy = path[Index][0][1] - p[1][1] dx2 = path[Index][0][0] - p[0][0] dy2 = path[Index][0][1] - p[0][1] SP = max([ math.sqrt((dx**2) + (dy**2)), math.sqrt((dx2**2) + (dy2**2)) ]) dx = path[Index][-1][0] - p[1][0] dy = path[Index][-1][1] - p[1][1] dx2 = path[Index][-1][0] - p[0][0] dy2 = path[Index][-1][1] - p[0][1] SP2 = max([ math.sqrt((dx**2) + (dy**2)), math.sqrt((dx2**2) + (dy2**2)) ]) fet2.setGeometry( QgsGeometry.fromPolylineXY(points)) fet2.setAttributes([FID, D, D2, SP, SP2]) writer2.addFeature(fet2) del G2 elif Method == 'All': curLen = 0 G2 = G.copy() while len(G2) != curLen: curLen = len(G2) degree = G2.degree() removeNodes = [k for k, v in degree if v == 1] G2.remove_nodes_from(removeNodes) source = list(G.nodes())[0] for n in range(2): length, path = nx.single_source_dijkstra( G, source, weight='weight') Index = max(length, key=length.get) source = path[Index][-1] G2.add_path(path[Index]) source = list( G2.nodes())[0] #Get length along all paths for n in range(2): length, path = nx.single_source_dijkstra( G, source, weight='weight') Index = max(length, key=length.get) source = path[Index][-1] length2, path2 = nx.single_source_dijkstra( G, source, weight='weight') for p in G2.edges: points = [] points.append(QgsPointXY(p[0][0], p[0][1])) points.append(QgsPointXY(p[1][0], p[1][1])) D = max([ length[(p[0][0], p[0][1])], length[(p[1][0], p[1][1])] ]) D2 = max([ length2[(p[0][0], p[0][1])], length2[(p[1][0], p[1][1])] ]) dx = path[Index][0][0] - p[1][0] dy = path[Index][0][1] - p[1][1] dx2 = path[Index][0][0] - p[0][0] dy2 = path[Index][0][1] - p[0][1] SP = max([ math.sqrt((dx**2) + (dy**2)), math.sqrt((dx2**2) + (dy2**2)) ]) dx = path[Index][-1][0] - p[1][0] dy = path[Index][-1][1] - p[1][1] dx2 = path[Index][-1][0] - p[0][0] dy2 = path[Index][-1][1] - p[0][1] SP2 = max([ math.sqrt((dx**2) + (dy**2)), math.sqrt((dx2**2) + (dy2**2)) ]) fet2.setGeometry( QgsGeometry.fromPolylineXY(points)) fet2.setAttributes([FID, D, D2, SP, SP2]) writer2.addFeature(fet2) del G2 elif Method == 'Circles': curLen = 0 G2 = G.copy() while len(G2) != curLen: curLen = len(G2) degree = G2.degree() removeNodes = [k for k, v in degree if v == 1] G2.remove_nodes_from(removeNodes) for p in G2.edges: points = [] points.append(QgsPointXY(p[0][0], p[0][1])) points.append(QgsPointXY(p[1][0], p[1][1])) fet2.setGeometry( QgsGeometry.fromPolylineXY(points)) fet2.setAttributes([FID]) writer2.addFeature(fet2) del G2 else: source = list(G.nodes())[0] for n in range(2): length, path = nx.single_source_dijkstra( G, source, weight='weight') Index = max(length, key=length.get) source = path[Index][-1] length2, path2 = nx.single_source_dijkstra( G, source, weight='weight') sx = None for p in path[Index]: if sx == None: sx, sy = p[0], p[1] continue ex, ey = p[0], p[1] D = max([length[(sx, sy)], length[(ex, ey)]]) D2 = max([length2[(sx, sy)], length2[(ex, ey)]]) dx = path[Index][0][0] - ex dy = path[Index][0][1] - ey dx2 = path[Index][0][0] - sx dy2 = path[Index][0][1] - sy SP = max([ math.sqrt((dx**2) + (dy**2)), math.sqrt((dx2**2) + (dy2**2)) ]) dx = path[Index][-1][0] - ex dy = path[Index][-1][1] - ey dx2 = path[Index][-1][0] - sx dy2 = path[Index][-1][1] - sy SP2 = max([ math.sqrt((dx**2) + (dy**2)), math.sqrt((dx2**2) + (dy2**2)) ]) points = [QgsPointXY(sx, sy), QgsPointXY(ex, ey)] fet2.setGeometry( QgsGeometry.fromPolylineXY(points)) fet2.setAttributes([FID, D, D2, SP, SP2]) writer2.addFeature(fet2) sx, sy = ex, ey except Exception: feedback.reportError( QCoreApplication.translate( 'Update', 'No centerline found for polygon ID %s - skipping' % (FID))) continue finally: G.clear() del writer2, edges return {self.Output: dest_id}
def run(self): global almacen #coloco el puntero arriba del todo QgsProject.instance().layerTreeRegistryBridge().setLayerInsertionPoint( QgsProject.instance().layerTreeRoot(), 0) #genero una lista con los sistemas de referencia misdatos = [["Etrs89 Zona30 (25830)", "25830"], ["Etrs89 Zona29 (25829)", "25829"], ["ED50 Zona30 (23030)", "23030"], ["ED50_Zona29 (23029)", "23029"], ["WGS84 geograficas sexagesimales(4326)", "4326"], ["WGS84 geograficas centesimales(4326)", "4258"]] self.dlg.comboBox_src.clear() for element in misdatos: self.dlg.comboBox_src.addItem(element[0]) """Run method that performs all the real work""" # Create the dialog with elements (after translation) and keep reference # Only create GUI ONCE in callback, so that it will only load when the plugin is started if self.first_start == True: self.first_start = False #leo la cache rutacache = os.path.join(QgsApplication.qgisSettingsDirPath(), r"python\plugins\zoomSigmena\cache.txt") if os.path.isfile(rutacache) == True: filecache = open(rutacache, "r") filecacheleido = filecache.readlines() try: import ast almacen = ast.literal_eval((filecacheleido[0].replace( '\n', '')).replace(" [[", "[[").replace("]] ", "]]")) #.split(',')) cache_utm = int(almacen[0]) cache_geo = int(almacen[1]) cache_escala = almacen[2] print(cache_escala) print(almacen) #miscomarcas=(filecacheleido[3].replace('\n','')).strip('][').split(',') #convierto una str en una list #mismunicipios=ast.literal_eval((filecacheleido[4].replace('\n','')).replace(" [[","[[").replace("]] ","]]"))#.split(',')) #convierto una str en una list filecache.close() except: print("esta no encuentra el file cache") self.dlg.lineEdit_escala.setText(str(cache_escala)) self.dlg.checkBox_utm.setChecked(cache_utm) self.dlg.checkBox_geo.setChecked(cache_geo) # show the dialog self.dlg.show() # Run the dialog event loop result = self.dlg.exec_() # See if OK was pressed if result: # Do something useful here - delete the line containing pass and # substitute with your code. def deg_to_dms(deg, type='lat'): decimals, number = math.modf(deg) d = int(number) m = int(decimals * 60) s = (deg - d - m / 60) * 3600.00 compass = {'lat': ('N', 'S'), 'lon': ('E', 'W')} compass_str = compass[type][0 if d >= 0 else 1] return '{}º{}\'{:.2f}"{}'.format(abs(d), abs(m), abs(s), compass_str) #saco de aqui variables que estan en las cajitas src_seleccionado = self.dlg.comboBox_src.currentIndex() # Get the coordinates and scale factor from the dialog x = self.dlg.XX.text() ##displayText() y = self.dlg.YY.text() ##displayText() escala = self.dlg.lineEdit_escala.text() x = x.replace(',', '.') y = y.replace(',', '.') escala = int(escala.replace('.', '')) src = misdatos[int(src_seleccionado)][1] if src == "4326": latext = y longtext = x lag = float(latext.split()[0]) lam = float(latext.split()[1]) las = float(latext.split()[2]) log = float(longtext.split()[0]) lom = float(longtext.split()[1]) los = float(longtext.split()[2]) lon = -1 * (log + (lom / 60) + (los / 3600)) lat = lag + (lam / 60) + (las / 3600) x = float(lon) y = float(lat) print(x) print(y) huso = 30 destinoProj = pyproj.Proj(proj="utm", zone=huso, ellps="WGS84", units="m") origenProj = pyproj.Proj(proj='longlat', ellps='WGS84', datum='WGS84') UTM_X, UTM_Y = pyproj.transform(origenProj, destinoProj, lon, lat) if src == "4258": print("por el camino adecuado") lat = float(y) lonn = float(x) lon = -1.0 * lonn print(lat) print(lon) huso = 30 destinoProj = pyproj.Proj(proj="utm", zone=huso, ellps="WGS84", units="m") origenProj = pyproj.Proj(proj='longlat', ellps='WGS84', datum='WGS84') UTM_X, UTM_Y = pyproj.transform(origenProj, destinoProj, lon, lat) print(UTM_X) print(UTM_Y) x = lon y = lat #creo una capa temporal con las coordenadas # create layer vl2 = QgsVectorLayer("Point?crs=EPSG:" + src, "Zoom", "memory") pr2 = vl2.dataProvider() vl2.startEditing() # add fields pr2.addAttributes([ QgsField("x", QVariant.Double), QgsField("y", QVariant.Double), QgsField("xx", QVariant.String), QgsField("yy", QVariant.String), QgsField("xxx", QVariant.Double), QgsField("yyy", QVariant.Double) ]) vl2.updateFields() # tell the vector layer to fetch changes from the provider #$add a feature fet = QgsFeature() print("punto") print(x) print(y) fet.setGeometry( QgsGeometry.fromPointXY(QgsPointXY(float(x), float(y)))) if src == "25830": huso = 30 origenProj = pyproj.Proj(proj="utm", zone=huso, ellps="WGS84", units="m") destinoProj = pyproj.Proj(proj='longlat', ellps='WGS84', datum='WGS84') xxx, yyy = pyproj.transform(origenProj, destinoProj, x, y) xx = (deg_to_dms(xxx, 'lon')) yy = (deg_to_dms(yyy)) if src == "25829": huso = 29 origenProj = pyproj.Proj(proj="utm", zone=huso, ellps="WGS84", units="m") destinoProj = pyproj.Proj(proj='longlat', ellps='WGS84', datum='WGS84') xxx, yyy = pyproj.transform(origenProj, destinoProj, x, y) xx = (deg_to_dms(xxx, 'lon')) yy = (deg_to_dms(yyy)) if src == "23030": huso = 30 origenProj = pyproj.Proj(proj="utm", zone=huso, ellps="intl", units="m") destinoProj = pyproj.Proj(proj='longlat', ellps='WGS84', datum='WGS84') xxx, yyy = pyproj.transform(origenProj, destinoProj, x, y) xx = (deg_to_dms(xxx, 'lon')) yy = (deg_to_dms(yyy)) if src == "23029": huso = 29 origenProj = pyproj.Proj(proj="utm", zone=huso, ellps="intl", units="m") destinoProj = pyproj.Proj(proj='longlat', ellps='WGS84', datum='WGS84') xxx, yyy = pyproj.transform(origenProj, destinoProj, x, y) xx = (deg_to_dms(xxx, 'lon')) yy = (deg_to_dms(yyy)) #para que lo pase a utms en pantalla if src == "4326": x = int(UTM_X) y = int(UTM_Y) #xx=longtext #yy=latext huso = 30 origenProj = pyproj.Proj(proj="utm", zone=huso, ellps="intl", units="m") destinoProj = pyproj.Proj(proj='longlat', ellps='WGS84', datum='WGS84') xxx, yyy = pyproj.transform(origenProj, destinoProj, x, y) xx = (deg_to_dms(xxx, 'lon')) yy = (deg_to_dms(yyy)) #para que lo pase a utms en pantalla if src == "4258": x = int(UTM_X) y = int(UTM_Y) xxx = lon yyy = lat xx = (deg_to_dms(xxx, 'lon')) yy = (deg_to_dms(yyy)) fet.setAttributes( [float(x), float(y), str(xx), str(yy), float(xxx), float(yyy)]) pr2.addFeatures([fet]) #cambio la simbologia symbol = QgsMarkerSymbol.createSimple({ 'name': 'circle', 'color': 'red', 'size': '3', }) vl2.renderer().setSymbol(symbol) # update layer's extent when new features have been added # because change of extent in provider is not propagated to the layer layer_settings = QgsPalLayerSettings() text_format = QgsTextFormat() text_format.setFont(QFont("Arial", 12)) text_format.setSize(12) text_format.setColor(QColor("Orange")) layer_settings.setFormat(text_format) layer_settings.placement = 1 layer_settings.xOffset = 0.0 layer_settings.yOffset = 10.0 mostrar = True if self.dlg.checkBox_utm.isChecked( ) and self.dlg.checkBox_geo.isChecked(): layer_settings.fieldName = '''concat('X: ',"X",' Y: ',"Y",'\n','Lon: ',"xx",' Lat: ',"yy" )''' almacen = [1, 1] else: if self.dlg.checkBox_utm.isChecked(): layer_settings.fieldName = '''concat('X: ',"X",' Y: ',"Y" )''' almacen = [1, 0] print("caso1") if self.dlg.checkBox_geo.isChecked(): layer_settings.fieldName = '''concat('Lon: ',"xx",' Lat: ',"yy" )''' almacen = [0, 1] print("caso2") if not self.dlg.checkBox_utm.isChecked( ) and not self.dlg.checkBox_geo.isChecked(): mostrar = False almacen = [0, 0] print("caso3") print("almacen despues de etiquetar", almacen) layer_settings.isExpression = True print(mostrar) layer_settings.enabled = mostrar layer_settings = QgsVectorLayerSimpleLabeling(layer_settings) vl2.setLabelsEnabled(True) vl2.setLabeling(layer_settings) vl2.triggerRepaint() # update layer's extent when new features have been added # because change of extent in provider is not propagated to the layer vl2.updateExtents() vl2.commitChanges() vl2.updateExtents() canvas = self.iface.mapCanvas() canvas.setExtent(vl2.extent()) crsSrc = QgsCoordinateReferenceSystem('EPSG:' + str(src)) crsDest = QgsProject.instance().crs() if crsSrc != crsDest: xform = QgsCoordinateTransform(crsSrc, crsDest, QgsProject.instance()) canvas.setExtent(xform.transform(vl2.extent())) self.iface.mapCanvas().zoomScale(escala) #self.limpiar_pressed() almacen.append(escala) #lo escribo en el txt, mavhacando lo que ya tenia f = open(rutacache, "w") escribir = str(almacen) f.write(escribir) f.close() print(almacen) QgsProject.instance().addMapLayer(vl2)
def accept(self): try: distance = float(self.distLineEdit.text()) azimuth = float(self.azimuthLineEdit.text()) units = self.unitsComboBox.currentIndex( ) # 0 km, 1 m, 2 nm, 3 miles, 4 yards, 5 ft, 6 inches, 7 cm start = self.checkBox.isChecked() except: self.iface.messageBar().pushMessage( "", tr("Either distance or azimuth were invalid"), level=Qgis.Warning, duration=4) return layer = self.iface.activeLayer() if layer is None: self.iface.messageBar().pushMessage( "", tr("No point or line layer selected"), level=Qgis.Warning, duration=4) return measureFactor = conversionToMeters(units) distance = distance * measureFactor pt = self.pt destCRS = layer.crs() transform = QgsCoordinateTransform(epsg4326, destCRS, QgsProject.instance()) if layer.wkbType() == QgsWkbTypes.Point: g = geod.Direct(pt.y(), pt.x(), azimuth, distance, Geodesic.LATITUDE | Geodesic.LONGITUDE) if start: ptStart = transform.transform(self.pt.x(), self.pt.y()) feat = QgsFeature(layer.fields()) feat.setGeometry(QgsGeometry.fromPointXY(ptStart)) layer.addFeature(feat) pt = transform.transform(g['lon2'], g['lat2']) feat = QgsFeature(layer.fields()) feat.setGeometry(QgsGeometry.fromPointXY(pt)) layer.addFeature(feat) else: # It will either be a LineString or MultiLineString maxseglen = settings.maxSegLength * 1000.0 # Needs to be in meters maxSegments = settings.maxSegments l = geod.Line(pt.y(), pt.x(), azimuth) n = int(math.ceil(distance / maxseglen)) if n > maxSegments: n = maxSegments seglen = distance / n pts = [] for i in range(0, n + 1): s = seglen * i g = l.Position( s, Geodesic.LATITUDE | Geodesic.LONGITUDE | Geodesic.LONG_UNROLL) ptc = transform.transform(g['lon2'], g['lat2']) pts.append(ptc) feat = QgsFeature(layer.fields()) if layer.wkbType() == QgsWkbTypes.LineString: feat.setGeometry(QgsGeometry.fromPolylineXY(pts)) else: feat.setGeometry(QgsGeometry.fromMultiPolylineXY([pts])) layer.addFeatures([feat]) layer.updateExtents() self.iface.mapCanvas().refresh() self.close()
def create_project(self): self.project = self.project_manager.create_project(self.project_name) self.project_areas = None source_crs = self.area_layer.crs() target_crs = QgsCoordinateReferenceSystem(f'epsg:{self.epsg}') self.project_areas = Teilflaechen.features(project=self.project, create=True) # remove z-values from imported areas (they might mess up the geometries # later) try: parameters = { 'INPUT': self.area_layer, 'DROP_Z_VALUES': True, 'OUTPUT': 'memory:' } area_layer = processing.run('native:dropmzvalues', parameters)['OUTPUT'] # native:dropmzvalues is not always available (e.g. in tests) except QgsProcessingException: area_layer = self.area_layer layer_features = list(area_layer.getFeatures()) self.log(f'Neues Projekt angelegt im Ordner {self.project.path}') self.set_progress(10) trans_geoms = [] self.log(f'Füge {len(layer_features)} Fläche(n) hinzu...') tr = QgsCoordinateTransform(source_crs, target_crs, QgsProject.instance()) if not layer_features: raise Exception( 'Es wurden keine Flächen im Eingangslayer gefunden') for area in layer_features: geom = area.geometry() geom.transform(tr) trans_geoms.append(geom) # gather additional information about areas basedata = self.project_manager.basedata ags_feats = get_ags(layer_features, basedata, source_crs=source_crs, use_centroid=True) ags = [f.AGS for f in ags_feats] gem_names = [f.GEN for f in ags_feats] gem_types = [f.Gemeindetyp for f in ags_feats] if len(np.unique(ags)) > 1: raise Exception("Die Teilflächen liegen nicht in " "der selben Gemeinde") project_ags = ags[0] centroids = [geom.centroid().asPoint() for geom in trans_geoms] xs = [centroid.x() for centroid in centroids] ys = [centroid.y() for centroid in centroids] project_centroid = QgsPointXY(np.mean(xs), np.mean(ys)) max_dist = getattr(settings, 'MAX_AREA_DISTANCE', None) self.set_progress(33) self.log(f'Überprüfe die Flächenlage...') if max_dist is not None and len(layer_features) > 1: distances = [] for i in range(len(layer_features)): for j in range(i): dist = np.linalg.norm( np.subtract((xs[i], ys[i]), (xs[j], ys[j]))) distances.append(dist) if distances and max(distances) > max_dist: raise Exception("Der Abstand zwischen den Schwerpunkten der " "Teilflächen darf nicht größer " "als {} m sein!".format(max_dist)) self.set_progress(50) traffic_connectors = Connectors.features(project=self.project, create=True) self.log(f'Berechne Projektrahmendaten...') # create areas and connections to roads now = datetime.now() for i, feature in enumerate(layer_features): area = self.project_areas.add( nutzungsart=Nutzungsart.UNDEFINIERT.value, name=f'Flaeche_{i+1}', validiert=0, aufsiedlungsdauer=1, beginn_nutzung=now.year, ags_bkg=ags[i], gemeinde_name=gem_names[i], gemeinde_typ=gem_types[i], geom=trans_geoms[i]) traffic_connectors.add(id_teilflaeche=area.id, name_teilflaeche=area.name, geom=centroids[i]) self.set_progress(50) # general project data project_frame = Projektrahmendaten.features(project=self.project, create=True) local_versions = self.project_manager.local_versions( settings.basedata_path) # newest local version basedata_version = local_versions[0] project_frame.add(ags=ags[0], gemeinde_name=gem_names[0], gemeinde_typ=gem_types[0], projekt_name=self.project.name, geom=project_centroid, datum=now.strftime("%d.%m.%Y"), basisdaten_version=basedata_version['version'], basisdaten_datum=basedata_version['date']) self.set_progress(60) # create selectable centers around the areas for the market competition # domain sk_radius = getattr(settings, 'PROJECT_RADIUS', 20000) self.log( f'Ermittle Gemeinden im Umkreis von {int(sk_radius/1000)} km...') workspace = basedata.get_workspace('Basisdaten_deutschland') vg_table = workspace.get_table('Verwaltungsgemeinschaften') buffer = QgsGeometry.fromPointXY(QgsPointXY(*project_centroid)).buffer( sk_radius, 20) vg_table.spatial_filter(buffer.asWkt()) centers = Centers.features(project=self.project, create=True) rs_list = [] for row in vg_table: centers.add( name=row['GEN'], rs=row['RS'], geom=row['geom'], # -1 indicates that it is a vg for selection and output only nutzerdefiniert=-1) rs_list.append(row['RS']) project_rs = None gem_table = workspace.get_table('bkg_gemeinden') for row in gem_table: cut_rs = row['RS'][:9] ags = row['AGS'] if cut_rs in rs_list: if ags == project_ags: project_rs = cut_rs centers.add( name=row['GEN'], rs=cut_rs, ags=ags, geom=row['geom'], # 0 indicates gemeinden, for calculations only nutzerdefiniert=0) # preselect the VG the project is in if project_rs: project_vg = centers.get(rs=project_rs, nutzerdefiniert=-1) project_vg.auswahl = -1 project_vg.save() self.set_progress(100) return self.project
def calculate_locally(self): if not self.sqi_setup_tab.use_custom.isChecked(): QtWidgets.QMessageBox.critical(None, self.tr("Error"), self.tr("Due to the options you have chosen, this calculation must occur offline. You MUST select a custom land cover dataset.")) return if len(self.sqi_setup_tab.use_custom_pm.layer_list) == 0: QtWidgets.QMessageBox.critical(None, self.tr("Error"), self.tr("You must add an parent material layer to your map before you can run the calculation.")) return if len(self.sqi_setup_tab.use_custom_rock_frag.layer_list) == 0: QtWidgets.QMessageBox.critical(None, self.tr("Error"), self.tr("You must add a rock fragment layer to your map before you can run the calculation.")) return if len(self.sqi_setup_tab.use_custom_texture.layer_list) == 0: QtWidgets.QMessageBox.critical(None, self.tr("Error"), self.tr("You must add a soil texture layer to your map before you can run the calculation.")) return if len(self.sqi_setup_tab.use_custom_drainage.layer_list) == 0: QtWidgets.QMessageBox.critical(None, self.tr("Error"), self.tr("You must add a drainage layer to your map before you can run the calculation.")) return # select the parent material, slope, soil texture, drainage and rock fragment datasets pm_vrt = self.sqi_setup_tab.use_custom_pm.get_vrt() drainage_vrt = self.sqi_setup_tab.use_custom_drainage.get_vrt() texture_vrt = self.sqi_setup_tab.use_custom_texture.get_vrt() rock_frag_vrt = self.sqi_setup_tab.use_custom_rock_frag.get_vrt() soil_depth = self.sqi_setup_tab.use_depth.value() if self.aoi.calc_frac_overlap(QgsGeometry.fromRect(self.sqi_setup_tab.use_custom_pm.get_layer().extent())) < .99: QtWidgets.QMessageBox.critical(None, self.tr("Error"), self.tr("Area of interest is not entirely within the parent material layer.")) return if self.aoi.calc_frac_overlap(QgsGeometry.fromRect(self.sqi_setup_tab.use_custom_drainage.get_layer().extent())) < .99: QtWidgets.QMessageBox.critical(None, self.tr("Error"), self.tr("Area of interest is not entirely within the drainage layer.")) return if self.aoi.calc_frac_overlap(QgsGeometry.fromRect(self.sqi_setup_tab.use_custom_rock_frag.get_layer().extent())) < .99: QtWidgets.QMessageBox.critical(None, self.tr("Error"), self.tr("Area of interest is not entirely within the rock fragment layer.")) return if self.aoi.calc_frac_overlap(QgsGeometry.fromRect(self.sqi_setup_tab.use_custom_texture.get_layer().extent())) < .99: QtWidgets.QMessageBox.critical(None, self.tr("Error"), self.tr("Area of interest is not entirely within the soil texture layer.")) return out_f = self.get_save_raster() if not out_f: return self.close() crosses_180th, geojsons = self.aoi.bounding_box_gee_geojson() val = [] n = 1 if self.area_tab.area_fromfile.isChecked(): for f in self.aoi.get_layer_wgs84().getFeatures(): # Get an OGR geometry from the QGIS geometry geom = f.geometry() val.append(geom) n += 1 # stringify json object val_string = '{}'.format(json.loads(val[0].asJson())) # create ogr geometry val_geom = ogr.CreateGeometryFromJson(val_string) # simplify polygon to tolerance of 0.003 val_geom_simplified = val_geom.Simplify(0.003) # fetch coordinates from json coords= json.loads(val_geom_simplified.ExportToJson())['coordinates'] geometries = { "coordinates":coords, "type":"Polygon" } elif self.area_tab.area_fromadmin.isChecked(): geometries ={ "coordinates":self.get_admin_poly_geojson()['geometry']['coordinates'][0], "type":"Polygon" } elif self.area_tab.area_frompoint.isChecked(): point = QgsPointXY(float(self.area_tab.area_frompoint_point_x.text()), float(self.area_tab.area_frompoint_point_y.text())) crs_src = QgsCoordinateReferenceSystem(self.area_tab.canvas.mapSettings().destinationCrs().authid()) point = QgsCoordinateTransform(crs_src, self.aoi.crs_dst, QgsProject.instance()).transform(point) geometries = json.loads(QgsGeometry.fromPointXY(point).asJson()) # write aoi geometry to file for masking output aoi_geom = { "type": "FeatureCollection", "features": [ { "type": "Feature", "properties": {}, "geometry": geometries } ] } aoi_file = os.path.join(os.path.dirname(os.path.realpath(__file__)), 'data', 'aoi.geojson') with open(aoi_file, 'w') as filetowrite: filetowrite.write(json.dumps(aoi_geom)) # Add the sqi layers to a VRT in case they don't match in resolution, # and set proper output bounds sqi_files = [pm_vrt, texture_vrt, drainage_vrt, rock_frag_vrt] # in_vrt = tempfile.NamedTemporaryFile(suffix='.vrt').name sqi_vrts = [] for i in range(len(sqi_files)): f = tempfile.NamedTemporaryFile(suffix='.vrt').name gdal.BuildVRT(f, sqi_files[i], bandList=[i + 1], resolution='highest', resampleAlg=gdal.GRA_NearestNeighbour, outputBounds=self.aoi.get_aligned_output_bounds_deprecated(texture_vrt), separate=True) sqi_vrts.append(f) slope_v = os.path.join(os.path.dirname(os.path.realpath(__file__)), 'data', 'slope.tif') if not os.path.exists(slope_v): slope_zip = os.path.join(os.path.dirname(os.path.realpath(__file__)), 'data', 'slope.zip') slope_unzip = ZipFile(slope_zip) slope_unzip.extractall(os.path.join(os.path.dirname(os.path.realpath(__file__)), 'data')) slope_unzip.close() log("Extracting slope file...") else: log("Slope.tif already exists") in_files = [slope_v] in_files.extend(sqi_vrts) in_vrt = tempfile.NamedTemporaryFile(suffix='.vrt').name log(u'Saving SQI input files to {}'.format(in_vrt)) gdal.BuildVRT(in_vrt, in_files, resolution='highest', resampleAlg=gdal.GRA_NearestNeighbour, outputBounds=self.aoi.get_aligned_output_bounds_deprecated(texture_vrt), separate=True) # sqi_band_nums = np.arange(len(lc_files)) + 6 sqi_worker = StartWorker(SoilQualityWorker, 'calculating soil quality index', soil_depth, in_vrt, out_f ) if not sqi_worker.success: QtWidgets.QMessageBox.critical(None, self.tr("Error"), self.tr("Error calculating soil quality index."), None) return band_info = [BandInfo("Soil Quality Index (cm deep)", add_to_map=True, metadata={'depth': soil_depth})] out_json = os.path.splitext(out_f)[0] + '.json' create_local_json_metadata(out_json, out_f, band_info) schema = BandInfoSchema() for band_number in range(len(band_info)): b = schema.dump(band_info[band_number]) if b['add_to_map']: # The +1 is because band numbers start at 1, not zero add_layer(out_f, band_number + 1, b)
def create_points_at(startpoint, endpoint, distance, geom, fid, force, fo_fila, divide): """Creating Points at coordinates along the line """ # don't allow distance to be zero and loop endlessly if fo_fila: distance = 0 if distance <= 0: distance = geom.length() length = geom.length() if length < endpoint: endpoint = length if divide > 0: length2 = length if startpoint > 0: length2 = length - startpoint if endpoint > 0: length2 = endpoint if startpoint > 0 and endpoint > 0: length2 = endpoint - startpoint distance = length2 / divide current_distance = distance else: current_distance = distance feats = [] if endpoint > 0: length = endpoint # set the first point at startpoint point = geom.interpolate(startpoint) # convert 3D geometry to 2D geometry as OGR seems to have problems with this point = QgsGeometry.fromPointXY(point.asPoint()) field_id = QgsField(name="id", type=QVariant.Int) field = QgsField(name="dist", type=QVariant.Double) fields = QgsFields() fields.append(field_id) fields.append(field) feature = QgsFeature(fields) feature['dist'] = startpoint feature['id'] = fid feature.setGeometry(point) feats.append(feature) while startpoint + current_distance <= length: # Get a point along the line at the current distance point = geom.interpolate(startpoint + current_distance) # Create a new QgsFeature and assign it the new geometry feature = QgsFeature(fields) feature['dist'] = (startpoint + current_distance) feature['id'] = fid feature.setGeometry(point) feats.append(feature) # Increase the distance current_distance = current_distance + distance # set the last point at endpoint if wanted if force is True: end = geom.length() point = geom.interpolate(end) feature = QgsFeature(fields) feature['dist'] = end feature['id'] = fid feature.setGeometry(point) feats.append(feature) return feats
def calculate_on_GEE(self, method, biomass_data): self.close() crosses_180th, geojsons = self.aoi.bounding_box_gee_geojson() val = [] n = 1 if self.area_tab.area_fromfile.isChecked(): for f in self.aoi.get_layer_wgs84().getFeatures(): # Get an OGR geometry from the QGIS geometry geom = f.geometry() val.append(geom) n += 1 # stringify json object val_string = '{}'.format(json.loads(val[0].asJson())) # create ogr geometry val_geom = ogr.CreateGeometryFromJson(val_string) # simplify polygon to tolerance of 0.003 val_geom_simplified = val_geom.Simplify(0.003) # fetch coordinates from json coords = json.loads( val_geom_simplified.ExportToJson())['coordinates'] geometries = json.dumps([{ "coordinates": coords, "type": "Polygon" }]) elif self.area_tab.area_fromadmin.isChecked(): geometries = json.dumps([{ "coordinates": self.get_admin_poly_geojson()['geometry']['coordinates'][0], "type": "Polygon" }]) elif self.area_tab.area_frompoint.isChecked(): point = QgsPointXY( float(self.area_tab.area_frompoint_point_x.text()), float(self.area_tab.area_frompoint_point_y.text())) crs_src = QgsCoordinateReferenceSystem( self.area_tab.canvas.mapSettings().destinationCrs().authid()) point = QgsCoordinateTransform( crs_src, self.aoi.crs_dst, QgsProject.instance()).transform(point) geometries = json.dumps( json.loads(QgsGeometry.fromPointXY(point).asJson())) payload = { 'year_start': self.hansen_bl_year.date().year(), 'year_end': self.hansen_tg_year.date().year(), 'fc_threshold': int(self.hansen_fc_threshold.text().replace('%', '')), 'method': method, 'biomass_data': biomass_data, # 'geojsons':json.dumps(geojsons), 'geojsons': geometries, 'crs': self.aoi.get_crs_dst_wkt(), 'crosses_180th': crosses_180th, 'task_name': self.options_tab.task_name.text(), 'task_notes': self.options_tab.task_notes.toPlainText() } resp = run_script(get_script_slug('total-carbon'), payload) if resp: mb.pushMessage( QtWidgets.QApplication.translate("MISLAND", "Submitted"), QtWidgets.QApplication.translate( "MISLAND", "Total carbon submitted to Google Earth Engine."), level=0, duration=5) else: mb.pushMessage( QtWidgets.QApplication.translate("MISLAND", "Error"), QtWidgets.QApplication.translate( "MISLAND", "Unable to submit total carbon task to Google Earth Engine." ), level=0, duration=5)
def testDateTimeWriteShapefile(self): """Check writing date and time fields to an ESRI shapefile.""" ml = QgsVectorLayer( ('Point?crs=epsg:4326&field=id:int&' 'field=date_f:date&field=time_f:time&field=dt_f:datetime'), 'test', 'memory') self.assertTrue(ml.isValid()) provider = ml.dataProvider() self.assertIsNotNone(provider) ft = QgsFeature() ft.setGeometry(QgsGeometry.fromPointXY(QgsPointXY(10, 10))) ft.setAttributes([ 1, QDate(2014, 3, 5), QTime(13, 45, 22), QDateTime(QDate(2014, 3, 5), QTime(13, 45, 22)) ]) res, features = provider.addFeatures([ft]) self.assertTrue(res) self.assertTrue(features) dest_file_name = os.path.join(str(QDir.tempPath()), 'datetime.shp') crs = QgsCoordinateReferenceSystem() crs.createFromId(4326, QgsCoordinateReferenceSystem.EpsgCrsId) write_result, error_message = QgsVectorFileWriter.writeAsVectorFormat( ml, dest_file_name, 'utf-8', crs, 'ESRI Shapefile') self.assertEqual(write_result, QgsVectorFileWriter.NoError, error_message) # Open result and check created_layer = QgsVectorLayer('{}|layerid=0'.format(dest_file_name), 'test', 'ogr') fields = created_layer.dataProvider().fields() self.assertEqual( fields.at(fields.indexFromName('date_f')).type(), QVariant.Date) # shapefiles do not support time types, result should be string self.assertEqual( fields.at(fields.indexFromName('time_f')).type(), QVariant.String) # shapefiles do not support datetime types, result should be string self.assertEqual( fields.at(fields.indexFromName('dt_f')).type(), QVariant.String) f = next(created_layer.getFeatures(QgsFeatureRequest())) date_idx = created_layer.fields().lookupField('date_f') self.assertIsInstance(f.attributes()[date_idx], QDate) self.assertEqual(f.attributes()[date_idx], QDate(2014, 3, 5)) time_idx = created_layer.fields().lookupField('time_f') # shapefiles do not support time types self.assertIsInstance(f.attributes()[time_idx], str) self.assertEqual(f.attributes()[time_idx], '13:45:22') # shapefiles do not support datetime types datetime_idx = created_layer.fields().lookupField('dt_f') self.assertIsInstance(f.attributes()[datetime_idx], str) self.assertEqual( f.attributes()[datetime_idx], QDateTime(QDate(2014, 3, 5), QTime(13, 45, 22)).toString("yyyy/MM/dd hh:mm:ss.zzz"))
def testChangeGeometry(self): # test changing geometries values from an edit buffer # make a layer with two features layer = createEmptyLayer() self.assertTrue(layer.startEditing()) # add two features f1 = QgsFeature(layer.fields(), 1) f1.setGeometry(QgsGeometry.fromPointXY(QgsPointXY(1, 2))) f1.setAttributes(["test", 123]) self.assertTrue(layer.addFeature(f1)) f2 = QgsFeature(layer.fields(), 2) f2.setGeometry(QgsGeometry.fromPointXY(QgsPointXY(2, 4))) f2.setAttributes(["test2", 246]) self.assertTrue(layer.addFeature(f2)) layer.commitChanges() layer.startEditing() self.assertEqual(layer.editBuffer().changedGeometries(), {}) self.assertFalse(layer.editBuffer().isFeatureGeometryChanged(1)) self.assertFalse(layer.editBuffer().isFeatureGeometryChanged(2)) # change geometry layer.changeGeometry(1, QgsGeometry.fromPointXY(QgsPointXY(10, 20))) # test contents of buffer self.assertEqual(list(layer.editBuffer().changedGeometries().keys()), [1]) self.assertEqual( layer.editBuffer().changedGeometries()[1].constGet().x(), 10) self.assertTrue(layer.editBuffer().isFeatureGeometryChanged(1)) self.assertFalse(layer.editBuffer().isFeatureGeometryChanged(2)) self.assertEqual(layer.undoStack().count(), 1) self.assertEqual(layer.getFeature(1).geometry().constGet().x(), 10) self.assertEqual(layer.getFeature(2).geometry().constGet().x(), 2) # apply second change to same feature layer.beginEditCommand( 'second change' ) # need to use an edit command to avoid the two geometry changes being merged layer.changeGeometry(1, QgsGeometry.fromPointXY(QgsPointXY(100, 200))) layer.endEditCommand() # test contents of buffer self.assertEqual(list(layer.editBuffer().changedGeometries().keys()), [1]) self.assertEqual( layer.editBuffer().changedGeometries()[1].constGet().x(), 100) self.assertTrue(layer.editBuffer().isFeatureGeometryChanged(1)) self.assertFalse(layer.editBuffer().isFeatureGeometryChanged(2)) self.assertEqual(layer.undoStack().count(), 2) self.assertEqual(layer.getFeature(1).geometry().constGet().x(), 100) self.assertEqual(layer.getFeature(2).geometry().constGet().x(), 2) layer.changeGeometry(2, QgsGeometry.fromPointXY(QgsPointXY(20, 40))) # test contents of buffer self.assertEqual(set(layer.editBuffer().changedGeometries().keys()), set([1, 2])) self.assertEqual( layer.editBuffer().changedGeometries()[1].constGet().x(), 100) self.assertEqual( layer.editBuffer().changedGeometries()[2].constGet().x(), 20) self.assertTrue(layer.editBuffer().isFeatureGeometryChanged(1)) self.assertTrue(layer.editBuffer().isFeatureGeometryChanged(2)) self.assertEqual(layer.undoStack().count(), 3) self.assertEqual(layer.getFeature(1).geometry().constGet().x(), 100) self.assertEqual(layer.getFeature(2).geometry().constGet().x(), 20) layer.undoStack().undo() self.assertEqual(list(layer.editBuffer().changedGeometries().keys()), [1]) self.assertEqual( layer.editBuffer().changedGeometries()[1].constGet().x(), 100) self.assertTrue(layer.editBuffer().isFeatureGeometryChanged(1)) self.assertFalse(layer.editBuffer().isFeatureGeometryChanged(2)) self.assertEqual(layer.getFeature(1).geometry().constGet().x(), 100) self.assertEqual(layer.getFeature(2).geometry().constGet().x(), 2) layer.undoStack().undo() self.assertEqual(list(layer.editBuffer().changedGeometries().keys()), [1]) self.assertTrue(layer.editBuffer().isFeatureGeometryChanged(1)) self.assertFalse(layer.editBuffer().isFeatureGeometryChanged(2)) self.assertEqual(layer.getFeature(1).geometry().constGet().x(), 10) self.assertEqual(layer.getFeature(2).geometry().constGet().x(), 2) layer.undoStack().undo() self.assertEqual(list(layer.editBuffer().changedGeometries().keys()), []) self.assertFalse(layer.editBuffer().isFeatureGeometryChanged(1)) self.assertFalse(layer.editBuffer().isFeatureGeometryChanged(2)) self.assertEqual(layer.getFeature(1).geometry().constGet().x(), 1) self.assertEqual(layer.getFeature(2).geometry().constGet().x(), 2)
def test_updateFeatures(self): ol, offline_layer = self._testInit() # Edit feature 2 feat2 = self._getFeatureByAttribute(offline_layer, 'name', "'name 2'") self.assertTrue(offline_layer.startEditing()) self.assertTrue( offline_layer.changeAttributeValue( feat2.id(), offline_layer.fields().lookupField('name'), 'name 2 edited')) self.assertTrue( offline_layer.changeGeometry( feat2.id(), QgsGeometry.fromPointXY(QgsPointXY(33.0, 60.0)))) self.assertTrue(offline_layer.commitChanges()) feat2 = self._getFeatureByAttribute(offline_layer, 'name', "'name 2 edited'") self.assertTrue(ol.isOfflineProject()) # Sync ol.synchronize() sleep(2) # Does anybody know why the sleep is needed? Is that a threaded WFS consequence? online_layer = list(self.registry.mapLayers().values())[0] self.assertTrue(online_layer.isValid()) self.assertFalse(online_layer.name().find('(offline)') > -1) self.assertEqual(len([f for f in online_layer.getFeatures()]), len(TEST_FEATURES)) # Check that data have changed in the backend (raise exception if not found) feat2 = self._getFeatureByAttribute(self._getLayer('test_point'), 'name', "'name 2 edited'") feat2 = self._getFeatureByAttribute(online_layer, 'name', "'name 2 edited'") self.assertEqual(feat2.geometry().asPoint().toString(), QgsPointXY(33.0, 60.0).toString()) # Check that all other features have not changed layer = self._getLayer('test_point') self.assertTrue(self._compareFeature(layer, TEST_FEATURES[1 - 1])) self.assertTrue(self._compareFeature(layer, TEST_FEATURES[3 - 1])) self.assertTrue(self._compareFeature(layer, TEST_FEATURES[4 - 1])) # Test for regression on double sync (it was a SEGFAULT) # goes offline ol = QgsOfflineEditing() offline_layer = list(self.registry.mapLayers().values())[0] # Edit feature 2 feat2 = self._getFeatureByAttribute(offline_layer, 'name', "'name 2 edited'") self.assertTrue(offline_layer.startEditing()) self.assertTrue( offline_layer.changeAttributeValue( feat2.id(), offline_layer.fields().lookupField('name'), 'name 2')) self.assertTrue( offline_layer.changeGeometry( feat2.id(), QgsGeometry.fromPointXY(TEST_FEATURES[1][2]))) # Edit feat 4 feat4 = self._getFeatureByAttribute(offline_layer, 'name', "'name 4'") self.assertTrue( offline_layer.changeAttributeValue( feat4.id(), offline_layer.fields().lookupField('name'), 'name 4 edited')) self.assertTrue(offline_layer.commitChanges()) # Sync ol.synchronize() # Does anybody knows why the sleep is needed? Is that a threaded WFS consequence? sleep(1) online_layer = list(self.registry.mapLayers().values())[0] layer = self._getLayer('test_point') # Check that data have changed in the backend (raise exception if not found) feat4 = self._getFeatureByAttribute(layer, 'name', "'name 4 edited'") feat4 = self._getFeatureByAttribute(online_layer, 'name', "'name 4 edited'") feat2 = self._getFeatureByAttribute(layer, 'name', "'name 2'") feat2 = self._getFeatureByAttribute(online_layer, 'name', "'name 2'") # Check that all other features have not changed layer = self._getLayer('test_point') self.assertTrue(self._compareFeature(layer, TEST_FEATURES[1 - 1])) self.assertTrue(self._compareFeature(layer, TEST_FEATURES[2 - 1])) self.assertTrue(self._compareFeature(layer, TEST_FEATURES[3 - 1]))
def testCreateFeature(self): """ test creating a feature respecting defaults and constraints """ layer = QgsVectorLayer("Point?field=fldtxt:string&field=fldint:integer&field=flddbl:double", "addfeat", "memory") # add a bunch of features f = QgsFeature() f.setAttributes(["test", 123, 1.0]) f1 = QgsFeature(2) f1.setAttributes(["test_1", 124, 1.1]) f2 = QgsFeature(3) f2.setAttributes(["test_2", 125, 2.4]) f3 = QgsFeature(4) f3.setAttributes(["test_3", 126, 1.7]) f4 = QgsFeature(5) f4.setAttributes(["superpig", 127, 0.8]) self.assertTrue(layer.dataProvider().addFeatures([f, f1, f2, f3, f4])) # no layer self.assertFalse(QgsVectorLayerUtils.createFeature(None).isValid()) # basic tests f = QgsVectorLayerUtils.createFeature(layer) self.assertTrue(f.isValid()) self.assertEqual(f.fields(), layer.fields()) self.assertFalse(f.hasGeometry()) self.assertEqual(f.attributes(), [NULL, NULL, NULL]) # set geometry g = QgsGeometry.fromPointXY(QgsPointXY(100, 200)) f = QgsVectorLayerUtils.createFeature(layer, g) self.assertTrue(f.hasGeometry()) self.assertEqual(f.geometry().asWkt(), g.asWkt()) # using attribute map f = QgsVectorLayerUtils.createFeature(layer, attributes={0: 'a', 2: 6.0}) self.assertEqual(f.attributes(), ['a', NULL, 6.0]) # layer with default value expression layer.setDefaultValueDefinition(2, QgsDefaultValue('3*4')) f = QgsVectorLayerUtils.createFeature(layer) self.assertEqual(f.attributes(), [NULL, NULL, 12]) # we do not expect the default value expression to take precedence over the attribute map f = QgsVectorLayerUtils.createFeature(layer, attributes={0: 'a', 2: 6.0}) self.assertEqual(f.attributes(), ['a', NULL, 6.0]) # layer with default value expression based on geometry layer.setDefaultValueDefinition(2, QgsDefaultValue('3*$x')) f = QgsVectorLayerUtils.createFeature(layer, g) #adjusted so that input value and output feature are the same self.assertEqual(f.attributes(), [NULL, NULL, 300.0]) layer.setDefaultValueDefinition(2, QgsDefaultValue(None)) # test with violated unique constraints layer.setFieldConstraint(1, QgsFieldConstraints.ConstraintUnique) f = QgsVectorLayerUtils.createFeature(layer, attributes={0: 'test_1', 1: 123}) # since field 1 has Unique Constraint, it ignores value 123 that already has been set and sets to 128 self.assertEqual(f.attributes(), ['test_1', 128, NULL]) layer.setFieldConstraint(0, QgsFieldConstraints.ConstraintUnique) # since field 0 and 1 already have values test_1 and 123, the output must be a new unique value f = QgsVectorLayerUtils.createFeature(layer, attributes={0: 'test_1', 1: 123}) self.assertEqual(f.attributes(), ['test_4', 128, NULL]) # test with violated unique constraints and default value expression providing unique value layer.setDefaultValueDefinition(1, QgsDefaultValue('130')) f = QgsVectorLayerUtils.createFeature(layer, attributes={0: 'test_1', 1: 123}) # since field 1 has Unique Constraint, it ignores value 123 that already has been set and adds the default value self.assertEqual(f.attributes(), ['test_4', 130, NULL]) # fallback: test with violated unique constraints and default value expression providing already existing value # add the feature with the default value: self.assertTrue(layer.dataProvider().addFeatures([f])) f = QgsVectorLayerUtils.createFeature(layer, attributes={0: 'test_1', 1: 123}) # since field 1 has Unique Constraint, it ignores value 123 that already has been set and adds the default value # and since the default value providing an already existing value (130) it generates a unique value (next int: 131) self.assertEqual(f.attributes(), ['test_5', 131, NULL]) layer.setDefaultValueDefinition(1, QgsDefaultValue(None)) # test with manually correct unique constraint f = QgsVectorLayerUtils.createFeature(layer, attributes={0: 'test_1', 1: 132}) self.assertEqual(f.attributes(), ['test_5', 132, NULL]) """ test creating a feature respecting unique values of postgres provider """ layer = QgsVectorLayer("Point?field=fldtxt:string&field=fldint:integer&field=flddbl:double", "addfeat", "memory") # init connection string dbconn = 'dbname=\'qgis_test\'' if 'QGIS_PGTEST_DB' in os.environ: dbconn = os.environ['QGIS_PGTEST_DB'] # create a vector layer pg_layer = QgsVectorLayer('{} table="qgis_test"."authors" sql='.format(dbconn), "authors", "postgres") self.assertTrue(pg_layer.isValid()) # check the default clause default_clause = 'nextval(\'qgis_test.authors_pk_seq\'::regclass)' self.assertEqual(pg_layer.dataProvider().defaultValueClause(0), default_clause) # though default_clause is after the first create not unique (until save), it should fill up all the features with it pg_layer.startEditing() f = QgsVectorLayerUtils.createFeature(pg_layer) self.assertEqual(f.attributes(), [default_clause, NULL]) self.assertTrue(pg_layer.addFeatures([f])) self.assertTrue(QgsVectorLayerUtils.valueExists(pg_layer, 0, default_clause)) f = QgsVectorLayerUtils.createFeature(pg_layer) self.assertEqual(f.attributes(), [default_clause, NULL]) self.assertTrue(pg_layer.addFeatures([f])) f = QgsVectorLayerUtils.createFeature(pg_layer) self.assertEqual(f.attributes(), [default_clause, NULL]) self.assertTrue(pg_layer.addFeatures([f])) # if a unique value is passed, use it f = QgsVectorLayerUtils.createFeature(pg_layer, attributes={0: 40, 1: NULL}) self.assertEqual(f.attributes(), [40, NULL]) # and if a default value is configured use it as well pg_layer.setDefaultValueDefinition(0, QgsDefaultValue('11*4')) f = QgsVectorLayerUtils.createFeature(pg_layer) self.assertEqual(f.attributes(), [44, NULL]) pg_layer.rollBack()
def t0_Update_Pipeline_Layer(self): nodes_file = self.dlg.lineEdit_22.text() # ogr2ogr.main(["","-f", "ESRI Shapefile", "-s_srs", "epsg:32643", "-t_srs", "epsg:4326", "newp.shp", nodes_file]) nodeLyr = QgsVectorLayer(nodes_file, "nodes", "ogr") pipes_file = self.dlg.lineEdit_21.text() # ogr2ogr.main(["","-f", "ESRI Shapefile", "-s_srs", "epsg:32643", "-t_srs", "epsg:4326", "newl.shp", pipes_file]) # pipeLyr = QgsVectorLayer(pipes_file, "updated pipes", "ogr") vl = QgsVectorLayer("Point?crs=epsg:4326", "temporary_points", "memory") pr = vl.dataProvider() #setting up reprojection for temporary points epsg4326 = QgsCoordinateReferenceSystem( 4326, QgsCoordinateReferenceSystem.EpsgCrsId) self.reprojectgeographic = QgsCoordinateTransform( self.iface.mapCanvas().mapSettings().destinationCrs(), epsg4326, QgsProject.instance()) # Enter editing mode vl.startEditing() # add fields pr.addAttributes([ QgsField("id", QVariant.Int), QgsField("Name", QVariant.String), # QgsField("Latitude", QVariant.String), # QgsField("Longuitude", QVariant.String), # QgsField("Coordinates", QVariant.String), QgsField("GL(m)", QVariant.String), # QgsField("Dem.(lps)", QVariant.Int), # QgsField("Active", QVariant.String), QgsField("Dem.(lps)", QVariant.String) ]) vl.commitChanges() pt = QgsPointXY() fields = vl.fields() feature = QgsFeature() feature.setFields(fields) feature = feature.attributes() outFeature = QgsFeature() # QgsProject.instance().addMapLayer(vl) caps = vl.dataProvider().capabilities() # attrs = vl.feature() if caps & QgsVectorDataProvider.AddFeatures: for feat in nodeLyr.getFeatures(): # feat = QgsFeature(vl.fields()) feature[0] = feat.attributes()[0] feature[1] = feat.attributes()[1] feature[2] = feat.attributes()[5].split(' ')[0] # feature[3] = NULL pt.setX(float(feat["Coordinates"].split(',')[0])) pt.setY(float(feat["Coordinates"].split(',')[1])) # pt.setX(float(feat["X"])) # pt.setY(float(feat["Y"])) outFeature.setGeometry(QgsGeometry.fromPointXY(pt)) outFeature.setAttributes(feature) # outFeature.setGeometry(float(feat["Longitude"]),float(feat["Latitude"])) pr.addFeature(outFeature) vl.updateExtents() # outLayer.addFeature(outFeature) # geom = feature.geometry() # geomSingleType = QgsWkbTypes.isSingleType(geom.wkbType()) # res, outFeats = vl.addFeature(outFeature) error_node = QgsVectorFileWriter.writeAsVectorFormat( vl, pipes_file, "UTF-8", epsg4326, "ESRI Shapefile") # QgsProject.instance().addMapLayer(vl) Lyr = QgsVectorLayer(pipes_file, "Nodes", "ogr") QgsProject.instance().addMapLayer(Lyr) QgsProject.instance().addMapLayer(vl) return
def processAlgorithm(self, parameters, context, feedback): """ Here is where the processing itself takes place. """ layer = self.parameterAsVectorLayer(parameters, self.INPUT, context) #on ajoute un nouveau champ 'Aberrant' dans la couche en sortie new_fields = layer.fields() if not parameters['BOOLEAN']: new_fields.append(QgsField('Aberrant', QVariant.Double)) (sink, dest_id) = self.parameterAsSink(parameters, self.OUTPUT, context, new_fields, layer.wkbType(), layer.sourceCrs()) method = self.parameterAsEnum(parameters, self.INPUT_METHOD, context) int_confiance = self.parameterAsEnum(parameters, self.INPUT_CONFIANCE, context) nb_sd = self.parameterAsInt(parameters, self.INPUT_SD, context) field_to_filter = self.parameterAsString(parameters, self.FIELD, context) if feedback.isCanceled(): return {} #on créer une matrice avec les coordonnées features = layer.getFeatures() coordinates_arr = np.array( [[feat.geometry().asPoint()[k] for k in range(2)] for feat in features]) #création de la matrice de distance dist_array = distance.cdist(coordinates_arr, coordinates_arr) #tri de la matrice selon les lignes sort_array = np.sort(dist_array, axis=1) if parameters['BOOLEAN_DISTANCE']: min_dist_array = np.where( sort_array > parameters['INPUT_DISTANCE'], np.nan, sort_array) #on supprime le point des données pour IDW if method == 2: min_dist_array = min_dist_array[:, 1:] #selection d'uniquement les premières "colonnes" : donc les plus proches voisins #creation d'une matrice ou chaque ligne correspond a une liste des distances des plus proches voisin pour un point (indiceligne = indice du point) else: min_dist_array = np.delete(sort_array, parameters['INPUT_VOISINS'], 1) for k in range(parameters['INPUT_VOISINS'] + 1, len(sort_array[0]) - 1): min_dist_array = np.delete(min_dist_array, parameters['INPUT_VOISINS'], 1) #on supprime le point des données pour IDW if method == 2: min_dist_array = np.delete(min_dist_array, 0, 1) if feedback.isCanceled(): return {} #nombre de points dans le shp nb_points = len(coordinates_arr) #creation d'une liste de liste : liste des index des voisins les plus proches pour chaque point neighbors = [] for k in range(nb_points): l = np.nonzero(np.in1d(dist_array[k], min_dist_array[k]))[0].tolist() neighbors.append(l) #création du dataframe de données features = layer.getFeatures() #liste contenant les noms des champs field_list = [field.name() for field in layer.fields()] #on créé une matrice ou 1 ligne = 1 feature data = np.array([[feat[field_name] for field_name in field_list] for feat in features]) #on créer le dataframe avec les données et les noms des colonnes df = pd.DataFrame(data, columns=field_list) if feedback.isCanceled(): return {} if method == 0: int_confiance += 1 mean = [] sd = [] for k in range(nb_points): mean.append(df.iloc[neighbors[k]][field_to_filter].mean()) sd.append(df.iloc[neighbors[k]][field_to_filter].std()) df['mean'] = mean df['sd'] = sd #met 1 quand c'est aberrant, 0 sinon df['Aberrant'] = np.where( (df[field_to_filter] > df['mean'] - int_confiance * df['sd']) & (df[field_to_filter] < df['mean'] + int_confiance * df['sd']), 0, 1) df = df.drop(columns='mean') df = df.drop(columns='sd') elif method == 1: mean = [] sd = [] nb_neighbors = [] for k in range(nb_points): mean.append(df.iloc[neighbors[k]][field_to_filter].mean()) sd.append(df.iloc[neighbors[k]][field_to_filter].std()) nb_neighbors.append(len(neighbors[k])) df['mean'] = mean df['sd'] = sd df['CV_neighbors'] = 100 * (df['sd'] / df['mean']) df = df.drop(columns='sd') df = df.drop(columns='mean') df['nb_neighbors'] = nb_neighbors nb_high_cv = [] for k in range(nb_points): nb_high_cv.append( len(df.iloc[neighbors[k]][ df['CV_neighbors'] > parameters['INPUT_CV_MAX']])) df['nb_high_cv'] = nb_high_cv df['Aberrant'] = np.where( (df['nb_neighbors'] - 1 <= df['nb_high_cv']), 1, 0) df = df.drop(columns='CV_neighbors') df = df.drop(columns='nb_neighbors') df = df.drop(columns='nb_high_cv') else: sd = [] denominateur = [] numerateur = [] df_distances = pd.DataFrame(min_dist_array) denom = (1 / (df_distances**2)).sum(axis=1) values = [] for k in range(nb_points): sd.append(df.iloc[neighbors[k]][field_to_filter].std()) values.append( df.iloc[neighbors[k]][field_to_filter].values.tolist()) df['sd'] = sd df_values = pd.DataFrame(values) num = (df_values * (1 / (df_distances**2))).sum(axis=1) df['interpolation'] = num / denom df['Aberrant'] = np.where( (df[field_to_filter] > df['interpolation'] - nb_sd * df['sd']) & (df[field_to_filter] < df['interpolation'] + nb_sd * df['sd']), 0, 1) df = df.drop(columns='sd') df = df.drop(columns='interpolation') if feedback.isCanceled(): return {} #on va créer un dataframe avec les coordonnées, normalement les features sont parcourrues dans le même ordre coordinates = pd.DataFrame(coordinates_arr, columns=['X', 'Y']) df['X'] = coordinates['X'] df['Y'] = coordinates['Y'] if parameters['BOOLEAN']: indexNames = df[df['Aberrant'] == 1].index df.drop(indexNames, inplace=True) df.drop(columns='Aberrant') #on transforme le dataframe en liste pour les attributs df_list = df.values.tolist() if feedback.isCanceled(): return {} featureList = [] #on va parcourrir chaque ligne, ie chaque feature for row in df_list: feat = QgsFeature() feat.setAttributes( row[0:-2] ) #row = une ligne, on exclu les deux dernières colonnes qui sont les coordonnées feat.setGeometry( QgsGeometry.fromPointXY(QgsPointXY( row[-2], row[-1]))) #on définit la position de chaque point featureList.append(feat) #on ajoute la feature à la liste if feedback.isCanceled(): return {} #on ajoute la liste des features à la couche de sortie sink.addFeatures(featureList) return {self.OUTPUT: dest_id}
def move_feature(self, feat, dx, dy): self.new_feat = feat.copy() self.geometry = feat["geometry"] if self.geometry.wkbType() == 1: # Point self.geom = self.geometry.asPoint() self.newGeom = QgsPointXY(self.geom[0] + dx, self.geom[1] + dy) self.newGeometry = QgsGeometry.fromPointXY(self.newGeom) self.new_feat["geometry"] = self.newGeometry elif self.geometry.wkbType() == 2: # LineString self.geom = self.geometry.asPolyline() self.newGeom = [ QgsPointXY(i[0] + dx, i[1] + dy) for i in self.geom ] self.newGeometry = QgsGeometry.fromPolylineXY(self.newGeom) self.new_feat["geometry"] = self.newGeometry elif self.geometry.wkbType() == 3: # Polygon self.geom = self.geometry.buffer(0, 5).asPolygon() self.newGeom = [] for g in self.geom: self.g1 = [] for gg in g: self.new_gg = QgsPointXY(gg[0] + dx, gg[1] + dy) self.g1.append(self.new_gg) self.newGeom.append(self.g1) self.newGeometry = QgsGeometry.fromPolygonXY(self.newGeom) self.new_feat["geometry"] = self.newGeometry elif self.geometry.wkbType() == 4: # MultiPoint self.geom = self.geometry.asMultiPoint() self.newGeom = [ QgsPointXY(i[0] + dx, i[1] + dy) for i in self.geom ] self.newGeometry = QgsGeometry.fromMultiPointXY(self.newGeom) self.new_feat["geometry"] = self.newGeometry elif self.geometry.wkbType() == 5: # MultiLineString self.geom = self.geometry.asMultiPolyline() self.newGeom = [] for g in self.geom: self.g1 = [] for gg in g: self.new_gg = QgsPointXY(gg[0] + dx, gg[1] + dy) self.g1.append(self.new_gg) self.newGeom.append(self.g1) self.newGeometry = QgsGeometry.fromMultiPolylineXY(self.newGeom) self.new_feat["geometry"] = self.newGeometry elif self.geometry.wkbType() == 6: # MultiPolygon self.geom = self.geometry.asMultiPolygon() self.newGeom = [] for g in self.geom: self.g1 = [] for gg in g: self.g2 = [] for ggg in gg: self.new_ggg = QgsPointXY(ggg[0] + dx, ggg[1] + dy) self.g2.append(self.new_ggg) self.g1.append(self.g2) self.newGeom.append(self.g1) self.newGeometry = QgsGeometry.fromMultiPolygonXY(self.newGeom) self.new_feat["geometry"] = self.newGeometry return self.new_feat
def testQgsGeometryRepr(self): p = QgsPointXY(123.456, 987.654) g = QgsGeometry.fromPointXY(p) self.assertTrue( g.__repr__().startswith('<QgsGeometry: Point (123.456'))
def processAlgorithm(self, parameters, context, feedback): source = self.parameterAsSource(parameters, self.INPUT, context) if source is None: raise QgsProcessingException( self.invalidSourceError(parameters, self.INPUT)) pointCount = self.parameterAsDouble(parameters, self.POINTS_NUMBER, context) minDistance = self.parameterAsDouble(parameters, self.MIN_DISTANCE, context) fields = QgsFields() fields.append(QgsField('id', QVariant.Int, '', 10, 0)) (sink, dest_id) = self.parameterAsSink(parameters, self.OUTPUT, context, fields, QgsWkbTypes.Point, source.sourceCrs()) if sink is None: raise QgsProcessingException( self.invalidSinkError(parameters, self.OUTPUT)) nPoints = 0 nIterations = 0 maxIterations = pointCount * 200 featureCount = source.featureCount() total = 100.0 / pointCount if pointCount else 1 index = QgsSpatialIndex() points = dict() da = QgsDistanceArea() da.setSourceCrs(source.sourceCrs(), context.transformContext()) da.setEllipsoid(context.project().ellipsoid()) request = QgsFeatureRequest() random.seed() while nIterations < maxIterations and nPoints < pointCount: if feedback.isCanceled(): break # pick random feature fid = random.randint(0, featureCount - 1) f = next( source.getFeatures( request.setFilterFid(fid).setSubsetOfAttributes([]))) fGeom = f.geometry() if fGeom.isMultipart(): lines = fGeom.asMultiPolyline() # pick random line lineId = random.randint(0, len(lines) - 1) vertices = lines[lineId] else: vertices = fGeom.asPolyline() # pick random segment if len(vertices) == 2: vid = 0 else: vid = random.randint(0, len(vertices) - 2) startPoint = vertices[vid] endPoint = vertices[vid + 1] length = da.measureLine(startPoint, endPoint) dist = length * random.random() if dist > minDistance: d = dist / (length - dist) rx = (startPoint.x() + d * endPoint.x()) / (1 + d) ry = (startPoint.y() + d * endPoint.y()) / (1 + d) # generate random point p = QgsPointXY(rx, ry) geom = QgsGeometry.fromPointXY(p) if vector.checkMinDistance(p, index, minDistance, points): f = QgsFeature(nPoints) f.initAttributes(1) f.setFields(fields) f.setAttribute('id', nPoints) f.setGeometry(geom) sink.addFeature(f, QgsFeatureSink.FastInsert) index.insertFeature(f) points[nPoints] = p nPoints += 1 feedback.setProgress(int(nPoints * total)) nIterations += 1 if nPoints < pointCount: feedback.pushInfo( self.tr( 'Could not generate requested number of random points. ' 'Maximum number of attempts exceeded.')) return {self.OUTPUT: dest_id}
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)
def doGeocode(self): if self.dockwidget.apiKeyEdit.text() == '': self.iface.messageBar().pushMessage("Erro", u"API key não definida!", level=Qgis.Critical, duration=5) return progressDialog = QProgressDialog() progressDialog.setMinimum(0) progressDialog.setCancelButtonText('Cancelar') progressDialog.setWindowModality(Qt.WindowModal) progressDialog.setMinimumWidth(300) progressDialog.show() inputFile = self.dockwidget.inputFileWidget.filePath() errorFile = self.dockwidget.errorOutputFileWidget.filePath() addrPartsIdxs = [] inputAddrList = [] if self.dockwidget.toolBox.currentIndex() == 0: addrPartsIdxs.append(self.dockwidget.addressCombo.currentIndex()) if self.dockwidget.neighborhoodCombo.currentIndex( ) != self.dockwidget.neighborhoodCombo.count() - 1: addrPartsIdxs.append( self.dockwidget.neighborhoodCombo.currentIndex()) if self.dockwidget.cityCombo.currentIndex( ) != self.dockwidget.cityCombo.count() - 1: addrPartsIdxs.append(self.dockwidget.cityCombo.currentIndex()) if self.dockwidget.stateCombo.currentIndex( ) != self.dockwidget.stateCombo.count() - 1: addrPartsIdxs.append(self.dockwidget.stateCombo.currentIndex()) if self.dockwidget.countryCombo.currentIndex( ) != self.dockwidget.countryCombo.count() - 1: addrPartsIdxs.append( self.dockwidget.countryCombo.currentIndex()) else: addrPartsIdxs.append( self.dockwidget.fullAddressCombo.currentIndex()) with open(inputFile, 'r') as iFile: csv_reader = csv.reader(iFile, delimiter=';') lineCount = 0 for row in csv_reader: if lineCount == 0: lineCount += 1 else: addr = ', '.join(row[i] for i in addrPartsIdxs) addr = '"' + addr + '"' inputAddrList.append(addr) # geolocator = Bing(api_key=apiKey) geolocator = self.getGeocoder() temp = QgsVectorLayer("Point?crs=epsg:4326", "Geocoding output", "memory") temp_data = temp.dataProvider() temp.startEditing() fl = open(inputFile, 'r') fo = open(errorFile, 'w') header = fl.readline() header = header.replace('\n', '') header = header.split(';') temp_data.addAttributes( [QgsField(header[i], QVariant.String) for i in range(len(header))]) temp_data.addAttributes([QgsField('addr_geocoded', QVariant.String)]) temp.updateFields() fo.writelines(';'.join(header)) totalAddresses = len(inputAddrList) progressDialog.setWindowTitle(u'Geocodificando ' + str(totalAddresses) + u' endereços...') progressDialog.setMaximum(totalAddresses) counter = 2 for a in inputAddrList: if progressDialog.wasCanceled(): self.iface.messageBar().clearWidgets() self.iface.messageBar().pushMessage( u"Geocodificação cancelada", u'Salvos ' + str(counter - 2) + u' endereços.', level=Qgis.Info, duration=5) break address, (latitude, longitude) = geolocator.reverse(a) print(counter, address, latitude, longitude) counter += 1 feat = QgsFeature() feat.setGeometry( QgsGeometry.fromPointXY(QgsPointXY(longitude, latitude))) attributes = fl.readline().replace('\n', '').split(';') attributes.append(address) feat.setAttributes(attributes) temp.addFeatures([feat]) temp.updateExtents() # progress.setValue(counter-2) progressDialog.setValue(counter - 2) self.iface.mainWindow().repaint() temp.commitChanges() QgsProject.instance().addMapLayer(temp) self.iface.messageBar().clearWidgets() self.iface.messageBar().pushMessage( u"Successo", u'Geocodificados ' + str(totalAddresses) + u' endereços!', level=Qgis.Success, duration=5)
def testCreateFeature(self): """ test creating a feature respecting defaults and constraints """ layer = QgsVectorLayer("Point?field=fldtxt:string&field=fldint:integer&field=flddbl:double", "addfeat", "memory") # add a bunch of features f = QgsFeature() f.setAttributes(["test", 123, 1.0]) f1 = QgsFeature(2) f1.setAttributes(["test_1", 124, 1.1]) f2 = QgsFeature(3) f2.setAttributes(["test_2", 125, 2.4]) f3 = QgsFeature(4) f3.setAttributes(["test_3", 126, 1.7]) f4 = QgsFeature(5) f4.setAttributes(["superpig", 127, 0.8]) self.assertTrue(layer.dataProvider().addFeatures([f, f1, f2, f3, f4])) # no layer self.assertFalse(QgsVectorLayerUtils.createFeature(None).isValid()) # basic tests f = QgsVectorLayerUtils.createFeature(layer) self.assertTrue(f.isValid()) self.assertEqual(f.fields(), layer.fields()) self.assertFalse(f.hasGeometry()) self.assertEqual(f.attributes(), [NULL, NULL, NULL]) # set geometry g = QgsGeometry.fromPointXY(QgsPointXY(100, 200)) f = QgsVectorLayerUtils.createFeature(layer, g) self.assertTrue(f.hasGeometry()) self.assertEqual(f.geometry().asWkt(), g.asWkt()) # using attribute map f = QgsVectorLayerUtils.createFeature(layer, attributes={0: 'a', 2: 6.0}) self.assertEqual(f.attributes(), ['a', NULL, 6.0]) # layer with default value expression layer.setDefaultValueDefinition(2, QgsDefaultValue('3*4')) f = QgsVectorLayerUtils.createFeature(layer) self.assertEqual(f.attributes(), [NULL, NULL, 12]) # we do not expect the default value expression to take precedence over the attribute map f = QgsVectorLayerUtils.createFeature(layer, attributes={0: 'a', 2: 6.0}) self.assertEqual(f.attributes(), ['a', NULL, 6.0]) # layer with default value expression based on geometry layer.setDefaultValueDefinition(2, QgsDefaultValue('3*$x')) f = QgsVectorLayerUtils.createFeature(layer, g) #adjusted so that input value and output feature are the same self.assertEqual(f.attributes(), [NULL, NULL, 300.0]) layer.setDefaultValueDefinition(2, QgsDefaultValue(None)) # test with violated unique constraints layer.setFieldConstraint(1, QgsFieldConstraints.ConstraintUnique) f = QgsVectorLayerUtils.createFeature(layer, attributes={0: 'test_1', 1: 123}) # since field 1 has Unique Constraint, it ignores value 123 that already has been set and sets to 128 self.assertEqual(f.attributes(), ['test_1', 128, NULL]) layer.setFieldConstraint(0, QgsFieldConstraints.ConstraintUnique) # since field 0 and 1 already have values test_1 and 123, the output must be a new unique value f = QgsVectorLayerUtils.createFeature(layer, attributes={0: 'test_1', 1: 123}) self.assertEqual(f.attributes(), ['test_4', 128, NULL]) # test with violated unique constraints and default value expression providing unique value layer.setDefaultValueDefinition(1, QgsDefaultValue('130')) f = QgsVectorLayerUtils.createFeature(layer, attributes={0: 'test_1', 1: 123}) # since field 1 has Unique Constraint, it ignores value 123 that already has been set and adds the default value self.assertEqual(f.attributes(), ['test_4', 130, NULL]) # fallback: test with violated unique constraints and default value expression providing already existing value # add the feature with the default value: self.assertTrue(layer.dataProvider().addFeatures([f])) f = QgsVectorLayerUtils.createFeature(layer, attributes={0: 'test_1', 1: 123}) # since field 1 has Unique Constraint, it ignores value 123 that already has been set and adds the default value # and since the default value providing an already existing value (130) it generates a unique value (next int: 131) self.assertEqual(f.attributes(), ['test_5', 131, NULL]) layer.setDefaultValueDefinition(1, QgsDefaultValue(None)) # test with manually correct unique constraint f = QgsVectorLayerUtils.createFeature(layer, attributes={0: 'test_1', 1: 132}) self.assertEqual(f.attributes(), ['test_5', 132, NULL])
def testCreateFeature(self): """ test creating a feature respecting defaults and constraints """ layer = QgsVectorLayer( "Point?field=fldtxt:string&field=fldint:integer&field=flddbl:double", "addfeat", "memory") # add a bunch of features f = QgsFeature() f.setAttributes(["test", 123, 1.0]) f1 = QgsFeature(2) f1.setAttributes(["test_1", 124, 1.1]) f2 = QgsFeature(3) f2.setAttributes(["test_2", 125, 2.4]) f3 = QgsFeature(4) f3.setAttributes(["test_3", 126, 1.7]) f4 = QgsFeature(5) f4.setAttributes(["superpig", 127, 0.8]) self.assertTrue(layer.dataProvider().addFeatures([f, f1, f2, f3, f4])) # no layer self.assertFalse(QgsVectorLayerUtils.createFeature(None).isValid()) # basic tests f = QgsVectorLayerUtils.createFeature(layer) self.assertTrue(f.isValid()) self.assertEqual(f.fields(), layer.fields()) self.assertFalse(f.hasGeometry()) self.assertEqual(f.attributes(), [NULL, NULL, NULL]) # set geometry g = QgsGeometry.fromPointXY(QgsPointXY(100, 200)) f = QgsVectorLayerUtils.createFeature(layer, g) self.assertTrue(f.hasGeometry()) self.assertEqual(f.geometry().asWkt(), g.asWkt()) # using attribute map f = QgsVectorLayerUtils.createFeature(layer, attributes={ 0: 'a', 2: 6.0 }) self.assertEqual(f.attributes(), ['a', NULL, 6.0]) # layer with default value expression layer.setDefaultValueDefinition(2, QgsDefaultValue('3*4')) f = QgsVectorLayerUtils.createFeature(layer) self.assertEqual(f.attributes(), [NULL, NULL, 12.0]) # we expect the default value expression to take precedence over the attribute map f = QgsVectorLayerUtils.createFeature(layer, attributes={ 0: 'a', 2: 6.0 }) self.assertEqual(f.attributes(), ['a', NULL, 12.0]) # layer with default value expression based on geometry layer.setDefaultValueDefinition(2, QgsDefaultValue('3*$x')) f = QgsVectorLayerUtils.createFeature(layer, g) self.assertEqual(f.attributes(), [NULL, NULL, 300.0]) layer.setDefaultValueDefinition(2, QgsDefaultValue(None)) # test with violated unique constraints layer.setFieldConstraint(1, QgsFieldConstraints.ConstraintUnique) f = QgsVectorLayerUtils.createFeature(layer, attributes={ 0: 'test_1', 1: 123 }) self.assertEqual(f.attributes(), ['test_1', 128, NULL]) layer.setFieldConstraint(0, QgsFieldConstraints.ConstraintUnique) f = QgsVectorLayerUtils.createFeature(layer, attributes={ 0: 'test_1', 1: 123 }) self.assertEqual(f.attributes(), ['test_4', 128, NULL])
def create_point_layer(self): """ Create an temporary point layer in the Qgis canvas """ try: QApplication.setOverrideCursor(Qt.WaitCursor) ## Start the 'wait' cursor if self.list_points: # create layer vl = QgsVectorLayer("Point?crs=" + self.selected_epsg, self.layer_name, "memory") pr = vl.dataProvider() # add fields pr.addAttributes([QgsField("id_point", QVariant.Int), QgsField("nom", QVariant.String), QgsField("pfp", QVariant.Int), QgsField("pfa", QVariant.Int), QgsField("ty", QVariant.String), QgsField("date_rep", QVariant.String), QgsField("ordre", QVariant.String), QgsField("num_carte", QVariant.String), QgsField("coordY", QVariant.Double, "double", 12, 4), QgsField("coordX", QVariant.Double, "double", 12, 4), QgsField("coord_prov", QVariant.String), QgsField("altitudeH", QVariant.Double, "double", 10, 4), QgsField("altitude_prov", QVariant.String), QgsField("coord_code", QVariant.String), QgsField("geoide_cote", QVariant.String), QgsField("geoide_prov", QVariant.String), QgsField("ellips_code", QVariant.String), QgsField("dev_vert_ETA", QVariant.String), QgsField("dev_vert_XI", QVariant.String), QgsField("dev_vert_prov", QVariant.String), QgsField("dev_vert_ETA0", QVariant.String), QgsField("dev_vert_XI0", QVariant.String), QgsField("dev_vert_prov0", QVariant.String), QgsField("code_raumtri", QVariant.String), QgsField("num_cont", QVariant.String), QgsField("flag_gps", QVariant.String), QgsField("num_sess_gps", QVariant.String), QgsField("num_zone", QVariant.String), QgsField("reserve", QVariant.String)]) vl.updateFields() # tell the vector layer to fetch changes from the provider # add features for item in self.list_points: pos_y = float(item[8]) pos_x = float(item[9]) fet = QgsFeature() fet.setGeometry(QgsGeometry.fromPointXY(QgsPointXY(pos_y,pos_x))) fet.setAttributes(list(item)) pr.addFeatures([fet]) # add preconfigured qgis.qml style file plugin_folder = os.path.dirname(os.path.dirname(__file__)) qml_file = Path(plugin_folder) / "qml" / self.qml_style_point if qml_file.is_file(): # Test if file exist, avoid error if he is missing vl.loadNamedStyle(str(qml_file)) # update layer's extent when new features have been added vl.updateExtents() # zoom to the layer extent if self.zoom: canvas = iface.mapCanvas() canvas.setExtent(vl.extent()) # Show in project self.rmv_old_qgs_point_layer() QgsProject.instance().addMapLayer(vl) except: QApplication.restoreOverrideCursor() ## Stop the 'wait' cursor print("Point -> Failed to create a new Qgis point layer (def create_point_layer)") finally: QApplication.restoreOverrideCursor() ## Stop the 'wait' cursor
def clickTool(self): self.rubberBand.reset(QgsWkbTypes.GeometryType(3)) click_point_geom = QgsGeometry.fromPointXY(self.geometry_class.geometry) buffer_geom = click_point_geom.buffer(self.settingsWidget.spinBox_searchArea.value(),20) lines_layers = self.getLayers(1) polygons_layers = self.getLayers(2) len_line_layers = 0 len_polygon_layers = 0 try: len_line_layers += len(lines_layers) except TypeError: pass try: len_polygon_layers += len(polygons_layers) except TypeError: pass if len_polygon_layers == 0 and len_line_layers == 0: QMessageBox.warning(None,'Missing restrictive layers', 'Select one of the settings') return self.target_geom = None # Polygon layers if self.settingsWidget.checkBoxPolygon.isChecked() and len_polygon_layers > 0: for l in polygons_layers: poly_layer = l[0] for f in poly_layer.getFeatures(buffer_geom.boundingBox()): f_geom = f.geometry() if f_geom.intersects(click_point_geom): QMessageBox.warning(None,'No space to fill', 'No space to fill, choose a different location') return if f_geom.intersects(buffer_geom): buffer_geom = buffer_geom.difference(f_geom) if not poly_layer.isEditable(): poly_layer.startEditing() for part in buffer_geom.parts(): part_wkt = part.asWkt() part_geom = QgsGeometry.fromWkt(part_wkt) if part_geom.intersects(click_point_geom): target_geom = part_geom break # Line layers if self.settingsWidget.checkBoxLine.isChecked(): for l in lines_layers: line_layer = l[0] features = [i.geometry() for i in line_layer.getFeatures(buffer_geom.boundingBox())] buffer_geom_linestring = self.polygon2Linestring(buffer_geom) if buffer_geom_linestring != None: features.append(buffer_geom_linestring) features_unary_geom = QgsGeometry.unaryUnion(features) features_unary_geom_parts = [QgsGeometry.fromWkt(i.asWkt()) for i in features_unary_geom.parts()] features_polygonize = QgsGeometry.polygonize(features_unary_geom_parts) for part in features_polygonize.parts(): part_geom = QgsGeometry.fromWkt(part.asWkt()) if part_geom.intersects(click_point_geom): if target_geom == None: target_geom = part_geom else: target_geom = target_geom.intersection(part_geom) break target_geom.convertGeometryCollectionToSubclass(2) for part in target_geom.parts(): if part != None: part_geom = QgsGeometry.fromWkt(part.asWkt()) if part_geom.intersects(click_point_geom): self.target_geom = part_geom if self.target_geom != None: self.rubberBand.setToGeometry(self.target_geom,None) if self.settingsWidget.checkBox_askTargetLayer.isChecked(): self.addMenu() else: t_layer = self.getTargetLayer() if t_layer == None: QMessageBox.warning(None,'Missing target layer', 'Select one of the settings') return else: self.addFeature(t_layer)
def doCheck(self, method, parameters, context, feedback): source = self.parameterAsSource(parameters, self.INPUT_LAYER, context) (valid_output_sink, valid_output_dest_id) = self.parameterAsSink(parameters, self.VALID_OUTPUT, context, source.fields(), source.wkbType(), source.sourceCrs()) valid_count = 0 invalid_fields = source.fields() invalid_fields.append( QgsField('_errors', QVariant.String, 'string', 255)) (invalid_output_sink, invalid_output_dest_id) = self.parameterAsSink( parameters, self.INVALID_OUTPUT, context, invalid_fields, source.wkbType(), source.sourceCrs()) invalid_count = 0 error_fields = QgsFields() error_fields.append(QgsField('message', QVariant.String, 'string', 255)) (error_output_sink, error_output_dest_id) = self.parameterAsSink( parameters, self.ERROR_OUTPUT, context, error_fields, QgsWkbTypes.Point, source.sourceCrs()) error_count = 0 features = source.getFeatures( QgsFeatureRequest(), QgsProcessingFeatureSource.FlagSkipGeometryValidityChecks) total = 100.0 / source.featureCount() if source.featureCount() else 0 for current, inFeat in enumerate(features): if feedback.isCanceled(): break geom = inFeat.geometry() attrs = inFeat.attributes() valid = True if not geom.isNull() and not geom.isEmpty(): errors = list(geom.validateGeometry(method)) if errors: # QGIS method return a summary at the end if method == 1: errors.pop() valid = False reasons = [] for error in errors: errFeat = QgsFeature() error_geom = QgsGeometry.fromPointXY(error.where()) errFeat.setGeometry(error_geom) errFeat.setAttributes([error.what()]) if error_output_sink: error_output_sink.addFeature( errFeat, QgsFeatureSink.FastInsert) error_count += 1 reasons.append(error.what()) reason = "\n".join(reasons) if len(reason) > 255: reason = reason[:252] + '…' attrs.append(reason) outFeat = QgsFeature() outFeat.setGeometry(geom) outFeat.setAttributes(attrs) if valid: if valid_output_sink: valid_output_sink.addFeature(outFeat, QgsFeatureSink.FastInsert) valid_count += 1 else: if invalid_output_sink: invalid_output_sink.addFeature(outFeat, QgsFeatureSink.FastInsert) invalid_count += 1 feedback.setProgress(int(current * total)) results = { self.VALID_COUNT: valid_count, self.INVALID_COUNT: invalid_count, self.ERROR_COUNT: error_count } if valid_output_sink: results[self.VALID_OUTPUT] = valid_output_dest_id if invalid_output_sink: results[self.INVALID_OUTPUT] = invalid_output_dest_id if error_output_sink: results[self.ERROR_OUTPUT] = error_output_dest_id return results
def legend_test(self): self.atlas_map.setAtlasDriven(True) self.atlas_map.setAtlasScalingMode(QgsLayoutItemMap.Auto) self.atlas_map.setAtlasMargin(0.10) # add a point layer ptLayer = QgsVectorLayer( "Point?crs=epsg:4326&field=attr:int(1)&field=label:string(20)", "points", "memory") pr = ptLayer.dataProvider() f1 = QgsFeature(1) f1.initAttributes(2) f1.setAttribute(0, 1) f1.setAttribute(1, "Test label 1") f1.setGeometry(QgsGeometry.fromPointXY(QgsPointXY(-0.638, 48.954))) f2 = QgsFeature(2) f2.initAttributes(2) f2.setAttribute(0, 2) f2.setAttribute(1, "Test label 2") f2.setGeometry(QgsGeometry.fromPointXY(QgsPointXY(-1.682, 48.550))) pr.addFeatures([f1, f2]) # categorized symbology r = QgsCategorizedSymbolRenderer("attr", [ QgsRendererCategory( 1, QgsMarkerSymbol.createSimple({ "color": "255,0,0", 'outline_color': 'black' }), "red"), QgsRendererCategory( 2, QgsMarkerSymbol.createSimple({ "color": "0,0,255", 'outline_color': 'black' }), "blue") ]) ptLayer.setRenderer(r) QgsProject.instance().addMapLayer(ptLayer) # add the point layer to the map settings layers = self.layers layers = [ptLayer] + layers self.atlas_map.setLayers(layers) self.overview.setLayers(layers) # add a legend legend = QgsLayoutItemLegend(self.layout) legend.attemptMove(QgsLayoutPoint(200, 100)) # sets the legend filter parameter legend.setLinkedMap(self.atlas_map) legend.setLegendFilterOutAtlas(True) self.layout.addLayoutItem(legend) self.atlas.beginRender() self.atlas.seekTo(0) self.mLabel1.adjustSizeToText() checker = QgsLayoutChecker('atlas_legend', self.layout) myTestResult, myMessage = checker.testLayout() self.report += checker.report() self.assertTrue(myTestResult, myMessage) self.atlas.endRender() # restore state self.atlas_map.setLayers([layers[1]]) self.layout.removeLayoutItem(legend) QgsProject.instance().removeMapLayer(ptLayer.id())
def processAlgorithm(self, parameters, context, feedback): source = self.parameterAsSource(parameters, self.INPUT, context) if source is None: raise QgsProcessingException( self.invalidSourceError(parameters, self.INPUT)) pointCount = self.parameterAsDouble(parameters, self.POINTS_NUMBER, context) minDistance = self.parameterAsDouble(parameters, self.MIN_DISTANCE, context) bbox = source.sourceExtent() sourceIndex = QgsSpatialIndex(source, feedback) fields = QgsFields() fields.append(QgsField('id', QVariant.Int, '', 10, 0)) (sink, dest_id) = self.parameterAsSink(parameters, self.OUTPUT, context, fields, QgsWkbTypes.Point, source.sourceCrs()) if sink is None: raise QgsProcessingException( self.invalidSinkError(parameters, self.OUTPUT)) nPoints = 0 nIterations = 0 maxIterations = pointCount * 200 total = 100.0 / pointCount if pointCount else 1 index = QgsSpatialIndex() points = dict() random.seed() while nIterations < maxIterations and nPoints < pointCount: if feedback.isCanceled(): break rx = bbox.xMinimum() + bbox.width() * random.random() ry = bbox.yMinimum() + bbox.height() * random.random() p = QgsPointXY(rx, ry) geom = QgsGeometry.fromPointXY(p) ids = sourceIndex.intersects(geom.buffer(5, 5).boundingBox()) if len(ids) > 0 and \ vector.checkMinDistance(p, index, minDistance, points): request = QgsFeatureRequest().setFilterFids( ids).setSubsetOfAttributes([]) for f in source.getFeatures(request): if feedback.isCanceled(): break tmpGeom = f.geometry() if geom.within(tmpGeom): f = QgsFeature(nPoints) f.initAttributes(1) f.setFields(fields) f.setAttribute('id', nPoints) f.setGeometry(geom) sink.addFeature(f, QgsFeatureSink.FastInsert) index.insertFeature(f) points[nPoints] = p nPoints += 1 feedback.setProgress(int(nPoints * total)) nIterations += 1 if nPoints < pointCount: feedback.pushInfo( self.tr( 'Could not generate requested number of random points. ' 'Maximum number of attempts exceeded.')) return {self.OUTPUT: dest_id}
def processAlgorithm(self, parameters, context, feedback): """ RUN PROCESS """ # INPUT linelayer = self.parameterAsSource(parameters, self.INPUT, context) tol = self.parameterAsDouble(parameters, self.TOLERANCE, context) nmask = self.parameterAsString(parameters, self.NODE_MASK, context) nini = self.parameterAsInt(parameters, self.NODE_INI, context) ninc = self.parameterAsInt(parameters, self.NODE_INC, context) lmask = self.parameterAsString(parameters, self.LINK_MASK, context) lini = self.parameterAsInt(parameters, self.LINK_INI, context) linc = self.parameterAsInt(parameters, self.LINK_INC, context) # SEND INFORMATION TO THE USER feedback.pushInfo('=' * 40) crsid = linelayer.sourceCrs().authid() if crsid: feedback.pushInfo('CRS is {}.'.format(crsid)) else: feedback.pushInfo('WARNING: CRS is not set!') if linelayer.wkbType() == QgsWkbTypes.MultiLineString: feedback.reportError('ERROR: Source geometry is MultiLineString!') # READ LINESTRINGS AS WKT lines = [] for feature in linelayer.getFeatures(): line = [] for point in feature.geometry().asPolyline(): line.append((point.x(), point.y())) lines.append(line) for line in lines: if tools.dist2p(line[0], line[-1]) < tol: feedback.reportError('ERROR: Looped LineString!') return {} # SHOW INFO feedback.pushInfo('Read: {} LineStrings.'.format(len(lines))) # CONFIG def n_format(index): return tools.format_id(nini + index * ninc, nmask) def l_format(index): return tools.format_id(lini + index * linc, lmask) # CALCULATE NETWORK nodes, links = tools.net_from_linestrings(lines, tol) # GENERATE NODE LAYER newfields = QgsFields() newfields.append(QgsField("id", QVariant.String)) newfields.append(QgsField("type", QVariant.String)) newfields.append(QgsField("elevation", QVariant.Double)) (node_sink, node_id) = self.parameterAsSink(parameters, self.NODE_OUTPUT, context, newfields, QgsWkbTypes.Point, linelayer.sourceCrs()) # ADD FEATURES ncnt = 0 f = QgsFeature() for x, y in nodes[:]: nodeid = n_format(ncnt) f.setGeometry(QgsGeometry.fromPointXY(QgsPointXY(x, y))) f.setAttributes([nodeid, '', 0.0]) node_sink.addFeature(f) ncnt += 1 # SHOW PROGRESS if ncnt % 100 == 0: feedback.setProgress(50 * ncnt / len(nodes)) # GENERATE LINK LAYER newfields = QgsFields() newfields.append(QgsField("id", QVariant.String)) newfields.append(QgsField("start", QVariant.String)) newfields.append(QgsField("end", QVariant.String)) newfields.append(QgsField("type", QVariant.String)) newfields.append(QgsField("length", QVariant.Double)) newfields.extend(linelayer.fields()) (link_sink, link_id) = self.parameterAsSink(parameters, self.LINK_OUTPUT, context, newfields, QgsWkbTypes.LineString, linelayer.sourceCrs()) # ADD FEATURES lcnt = 0 g = QgsFeature() for f in linelayer.getFeatures(): link = links[lcnt] linkid = l_format(lcnt) start = n_format(link[0]) end = n_format(link[1]) poly = [] for x, y in links[lcnt][2][:]: poly.append(QgsPointXY(x, y)) length = tools.length2d(poly) attr = [linkid, start, end, 'PIPE', length] attr.extend(f.attributes()) g.setGeometry(QgsGeometry.fromPolylineXY(poly)) g.setAttributes(attr) link_sink.addFeature(g) lcnt += 1 # SHOW PROGRESS if lcnt % 100 == 0: feedback.setProgress(50 + 50 * lcnt / len(links)) feedback.pushInfo('Network was generated successfully.') feedback.pushInfo('Node number: {}.'.format(ncnt)) feedback.pushInfo('Link number: {}.'.format(lcnt)) feedback.pushInfo('=' * 40) # PROCCES CANCELED if feedback.isCanceled(): return {} # OUTPUT return {self.NODE_OUTPUT: node_id, self.LINK_OUTPUT: link_id}
def legend_test(self): self.atlas_map.setAtlasDriven(True) self.atlas_map.setAtlasScalingMode(QgsLayoutItemMap.Auto) self.atlas_map.setAtlasMargin(0.10) # add a point layer ptLayer = QgsVectorLayer("Point?crs=epsg:4326&field=attr:int(1)&field=label:string(20)", "points", "memory") pr = ptLayer.dataProvider() f1 = QgsFeature(1) f1.initAttributes(2) f1.setAttribute(0, 1) f1.setAttribute(1, "Test label 1") f1.setGeometry(QgsGeometry.fromPointXY(QgsPointXY(-0.638, 48.954))) f2 = QgsFeature(2) f2.initAttributes(2) f2.setAttribute(0, 2) f2.setAttribute(1, "Test label 2") f2.setGeometry(QgsGeometry.fromPointXY(QgsPointXY(-1.682, 48.550))) pr.addFeatures([f1, f2]) # categorized symbology r = QgsCategorizedSymbolRenderer("attr", [QgsRendererCategory(1, QgsMarkerSymbol.createSimple({"color": "255,0,0", 'outline_color': 'black'}), "red"), QgsRendererCategory(2, QgsMarkerSymbol.createSimple({"color": "0,0,255", 'outline_color': 'black'}), "blue")]) ptLayer.setRenderer(r) QgsProject.instance().addMapLayer(ptLayer) # add the point layer to the map settings layers = self.layers layers = [ptLayer] + layers self.atlas_map.setLayers(layers) self.overview.setLayers(layers) # add a legend legend = QgsLayoutItemLegend(self.layout) legend.setTitle("Legend") legend.attemptMove(QgsLayoutPoint(200, 100)) # sets the legend filter parameter legend.setLinkedMap(self.atlas_map) legend.setLegendFilterOutAtlas(True) self.layout.addLayoutItem(legend) self.atlas.beginRender() self.atlas.seekTo(0) self.mLabel1.adjustSizeToText() checker = QgsLayoutChecker('atlas_legend', self.layout) myTestResult, myMessage = checker.testLayout() self.report += checker.report() self.assertTrue(myTestResult, myMessage) self.atlas.endRender() # restore state self.atlas_map.setLayers([layers[1]]) self.layout.removeLayoutItem(legend) QgsProject.instance().removeMapLayer(ptLayer.id())