def loadData(self, resultFile, chunkId): """ Load data to the map """ if isMimeTypeVector(self.mimeType, True) != None: # Memory layer: geometryTypes = ["Point","LineString","Polygon","Unknown", "NoGeometry"] vlayer = QgsVectorLayer(resultFile, "chunk", "ogr") if self.__bFirstChunk: self.__bFirstChunk = False self.__geometryType = geometryTypes[vlayer.geometryType()] self.__bGeomMulti = vlayer.wkbType() in [4,5,6,11,12,13] self.__memoryLayer = QgsVectorLayer(self.__geometryType,"Streamed data","memory") self.__memoryLayer.dataProvider().addAttributes(vlayer.pendingFields().values()) self.__memoryLayer.updateFieldMap() provider = vlayer.dataProvider() allAttrs = provider.attributeIndexes() vlayer.select(allAttrs) # Visualize temporal geometries during the downloading process # Don't add temporal geometries if last chunk if self.DEBUG: print "Loaded chunkId:",chunkId res = self.__memoryLayer.dataProvider().addFeatures( [feat for feat in vlayer] ) self.__deliveredChunks += 1 if not self.allChunksDelivered(): inFeat = QgsFeature() inGeom = QgsGeometry() self.createTempGeometry(chunkId, self.__geometryType) while provider.nextFeature( inFeat ): inGeom = inFeat.geometry() featList = self.extractAsSingle(self.__geometryType, inGeom) if self.__bGeomMulti else [inGeom] for geom in featList: self.addTempGeometry(chunkId, self.__geometryType, geom) else: self.finishLoading() # Raster data elif isMimeTypeRaster(self.mimeType, True) != None: # We can directly attach the new layer if self.__bFirstChunk: self.__bFirstChunk = False self.__groupIndex = self.__legend.addGroup("Streamed-raster") rLayer = QgsRasterLayer(resultFile, "raster_"+str(chunkId)) bLoaded = QgsMapLayerRegistry.instance().addMapLayer(rLayer) self.stretchRaster(rLayer) self.__legend.moveLayer(rLayer, self.__groupIndex + 1) self.__deliveredChunks += 1 if self.allChunksDelivered(): self.finishLoading()
def test_ValidFeature(self): myPath = os.path.join(unitTestDataPath(), 'points.shp') myLayer = QgsVectorLayer(myPath, 'Points', 'ogr') provider = myLayer.dataProvider() allAttrs = provider.attributeIndexes() myLayer.select(allAttrs) feat = QgsFeature() myLayer.nextFeature(feat) myValidValue = feat.isValid() myMessage = '\nExpected: %s\nGot: %s' % ("True", myValidValue) assert myValidValue == True, myMessage
def main(): QgsApplication.setPrefixPath('/usr/local', True) QgsApplication.initQgis() layer = QgsVectorLayer('/path/to/layer.shp', 'layer', 'ogr') provider = layer.dataProvider() layer.select(provider.attributeIndexes()) values = [] for feat in layer: values.append(feat.attributeMap()[1].toDouble()[0]) print "Quantile: ", quantile(values, 5) print "Equal Interval: ", equal(values, 5) print "R's Pretty: ", pretty(values, 5) print "Standard Deviation: ", std_dev(values, 5) print "Natural Breaks (Jenks): ", jenks(values, classes=5) print "Sampled Jenks: ", jenks_sample(values, classes=5)
def test_Attributes(self): myPath = os.path.join(unitTestDataPath(), 'lines.shp') myLayer = QgsVectorLayer(myPath, 'Lines', 'ogr') provider = myLayer.dataProvider() allAttrs = provider.attributeIndexes() myLayer.select(allAttrs) feat = QgsFeature() myLayer.nextFeature(feat) myAttributes = feat.attributes() myExpectedAttributes = [ QVariant("Highway"), QVariant(1) ] # Only for printing purposes myAttributeDict = [ str(myAttributes[0].toString()), int(myAttributes[1].toString()) ] myExpectedAttributes = [ "Highway", 1 ] myMessage = '\nExpected: %s\nGot: %s' % (myExpectedAttributes, myAttributes) assert myAttributes == myExpectedAttributes, myMessage
class TestQgsNullSymbolRenderer(unittest.TestCase): def setUp(self): self.iface = get_iface() myShpFile = os.path.join(TEST_DATA_DIR, 'polys.shp') self.layer = QgsVectorLayer(myShpFile, 'Polys', 'ogr') QgsProject.instance().addMapLayer(self.layer) self.renderer = QgsNullSymbolRenderer() self.layer.setRenderer(self.renderer) rendered_layers = [self.layer] self.mapsettings = self.iface.mapCanvas().mapSettings() self.mapsettings.setOutputSize(QSize(400, 400)) self.mapsettings.setOutputDpi(96) self.mapsettings.setExtent(QgsRectangle(-163, 22, -70, 52)) self.mapsettings.setLayers(rendered_layers) def tearDown(self): QgsProject.instance().removeAllMapLayers() def testRender(self): # test no features are rendered renderchecker = QgsMultiRenderChecker() renderchecker.setMapSettings(self.mapsettings) renderchecker.setControlPathPrefix('null_renderer') renderchecker.setControlName('expected_nullrenderer_render') result = renderchecker.runTest('nullrenderer_render') assert result def testSelected(self): # select a feature and render self.layer.select([1, 2, 3]) renderchecker = QgsMultiRenderChecker() renderchecker.setMapSettings(self.mapsettings) renderchecker.setControlPathPrefix('null_renderer') renderchecker.setControlName('expected_nullrenderer_selected') result = renderchecker.runTest('nullrenderer_selected') assert result
def _test_copy_selected(self, input_layer_name, output_layer_name, select_id=1): print("### ", input_layer_name, output_layer_name) gpkg = get_test_file_copy_path('insert_features_to_layer_test.gpkg') input_layer_path = "{}|layername={}".format(gpkg, input_layer_name) output_layer_path = "{}|layername={}".format(gpkg, output_layer_name) input_layer = QgsVectorLayer(input_layer_path, 'layer name', 'ogr') self.assertTrue(input_layer.isValid()) output_layer = QgsVectorLayer(output_layer_path, 'layer name', 'ogr') self.assertTrue(output_layer.isValid()) QgsProject.instance().addMapLayers([input_layer, output_layer]) input_layer.select(select_id) # fid=1 res = processing.run( "etl_load:appendfeaturestolayer", { 'SOURCE_LAYER': QgsProcessingFeatureSourceDefinition(input_layer_path, True), 'SOURCE_FIELD': None, 'TARGET_LAYER': output_layer, 'TARGET_FIELD': None, 'ACTION_ON_DUPLICATE': 0 }) # No action self.assertIsNone( res[UPDATED_COUNT] ) # These are None because ACTION_ON_DUPLICATE is None self.assertIsNone(res[SKIPPED_COUNT]) return res
def testClipping(self): """Test that we can clip geometries using other geometries.""" myMemoryLayer = QgsVectorLayer( ('LineString?crs=epsg:4326&field=name:string(20)&index=yes'), 'clip-in', 'memory') assert myMemoryLayer is not None, 'Provider not initialised' myProvider = myMemoryLayer.dataProvider() assert myProvider is not None myFeature1 = QgsFeature() myFeature1.setGeometry(QgsGeometry.fromPolyline([ QgsPoint(10,10), QgsPoint(20,10), QgsPoint(30,10), QgsPoint(40,10), ] )) myFeature1.setAttributes([QVariant('Johny')]) myFeature2 = QgsFeature() myFeature2.setGeometry(QgsGeometry.fromPolyline([ QgsPoint(10,10), QgsPoint(20,20), QgsPoint(30,30), QgsPoint(40,40), ] )) myFeature2.setAttributes([QVariant('Be')]) myFeature3 = QgsFeature() myFeature3.setGeometry(QgsGeometry.fromPolyline([ QgsPoint(10,10), QgsPoint(10,20), QgsPoint(10,30), QgsPoint(10,40), ] )) myFeature3.setAttributes([QVariant('Good')]) myResult, myFeatures = myProvider.addFeatures( [myFeature1, myFeature2, myFeature3]) assert myResult == True assert len(myFeatures) == 3 myClipPolygon = QgsGeometry.fromPolygon([[ QgsPoint(20,20), QgsPoint(20,30), QgsPoint(30,30), QgsPoint(30,20), QgsPoint(20,20), ]] ) print 'Clip: %s' % myClipPolygon.exportToWkt() writeShape(myMemoryLayer, 'clipGeometryBefore.shp') myMemoryLayer.select(myProvider.attributeIndexes()) myFeatures = [] myFeature = QgsFeature() while myMemoryLayer.nextFeature(myFeature): myGeometry = myFeature.geometry() if myGeometry.intersects(myClipPolygon): # Adds nodes where the clip and the line intersec myCombinedGeometry = myGeometry.combine(myClipPolygon) # Gives you the areas inside the clip mySymmetricalGeometry = myGeometry.symDifference( myCombinedGeometry) # Gives you areas outside the clip area # myDifferenceGeometry = myCombinedGeometry.difference( # myClipPolygon) #print 'Original: %s' % myGeometry.exportToWkt() #print 'Combined: %s' % myCombinedGeometry.exportToWkt() #print 'Difference: %s' % myDifferenceGeometry.exportToWkt() print 'Symmetrical: %s' % mySymmetricalGeometry.exportToWkt() myExpectedWkt = 'LINESTRING(20.0 20.0, 30.0 30.0)' # There should only be one feature that intersects this clip # poly so this assertion should work. self.assertEqual(myExpectedWkt, mySymmetricalGeometry.exportToWkt()) myNewFeature = QgsFeature() myNewFeature.setAttributes(myFeature.attributes()) myNewFeature.setGeometry(mySymmetricalGeometry) myFeatures.append(myNewFeature) myNewMemoryLayer = QgsVectorLayer( ('LineString?crs=epsg:4326&field=name:string(20)&index=yes'), 'clip-out', 'memory') myNewProvider = myNewMemoryLayer.dataProvider() myResult, myFeatures = myNewProvider.addFeatures(myFeatures) self.assertTrue(myResult) self.assertEqual(len(myFeatures), 1) writeShape(myNewMemoryLayer, 'clipGeometryAfter.shp')
def route(self): try: import urllib.request import json origin_dest = [] featurelist = [] if self.dlg.inputpoint.isChecked(): vp_layer = self.dlg.point.currentLayer() countfeat = vp_layer.featureCount() else: vp_layer = iface.activeLayer() vp_layer.commitChanges() countfeat = vp_layer.featureCount() result = processing.run( "native:addautoincrementalfield", { 'INPUT': vp_layer, 'FIELD_NAME': 'id', 'START': 1, 'GROUP_FIELDS': [], 'SORT_EXPRESSION': '\"id\"', 'SORT_ASCENDING': True, 'SORT_NULLS_FIRST': False, 'OUTPUT': 'memory:{0}'.format(self.dlg.route_id.text()) }) QgsProject.instance().removeMapLayer(vp_layer) vp_layer = result['OUTPUT'] QgsProject.instance().addMapLayer(vp_layer) features = vp_layer.getFeatures() points = [] pointdist = [] waypoints = [] # if vp_layer.featureCount() == 2: for feature in vp_layer.getFeatures(): point = feature.geometry().asPoint() xpoint = point.x() ypoint = point.y() Qpoint = QgsPointXY(xpoint, ypoint) points.append(Qpoint) distcheck = 0 if self.dlg.direction.currentText() == 'Start->End': # for i in points: # distance = QgsDistanceArea() # Qpoint1 = i # for j in points: # Qpoint2 = j # dist = distance.measureLine(Qpoint1, Qpoint2) # pointdist.append(dist) # if dist > distcheck: # distcheck = dist self.origin = points[0] self.destination = points[countfeat - 1] # print('End->Start', self.origin, self.destination) elif self.dlg.direction.currentText() == 'End->Start': # for i in points: # distance = QgsDistanceArea() # Qpoint1 = i # for j in points: # Qpoint2 = j # dist = distance.measureLine(Qpoint1, Qpoint2) # pointdist.append(dist) # if dist > distcheck: # distcheck = dist self.origin = points[countfeat - 1] self.destination = points[0] # print('Start->End', self.origin, self.destination) # print(vp_layer.featureCount()) if vp_layer.featureCount() > 3: for i in range(countfeat - 1): if i != 0 and i != countfeat - 1: if self.dlg.direction.currentText() == 'Start->End': if len(waypoints) < 1: waypoints.append('optimize:true|via:' + str(points[i].y()) + ',' + str(points[i].x())) else: waypoints.append('via:' + str(points[i].y()) + ',' + str(points[i].x())) elif self.dlg.direction.currentText() == 'End->Start': if len(waypoints) < 1: waypoints.append( 'optimize:true|via:' + str(points[countfeat - i].y()) + ',' + str(points[countfeat - i].x())) else: waypoints.append( 'via:' + str(points[countfeat - i].y()) + ',' + str(points[countfeat - i].x())) print('|'.join(waypoints)) elif vp_layer.featureCount() == 3: for i in points: if i != self.origin and i != self.destination: waypoints.append('optimize:true|via:' + str(i.y()) + ',' + str(i.x())) else: pass # print(waypoints[0], 'waypoints') # print(distcheck, 'dist') # print(pointdist, 'pointdist') # print(origin.x(),origin.y(), destination.x(),destination.y(), 'origin_dest') # vp_layer.select(origin) # vp_layer.select(destination) for feature in vp_layer.getFeatures(): geometry = feature.geometry() origin_dest.append( {geometry.asPoint().y(), geometry.asPoint().x()}) # print(origin_dest) endpoint = 'https://maps.googleapis.com/maps/api/directions/json?' APIkey = self.dlg.api.text() # mode = 'driving' origin_str = self.origin.y(), self.origin.x() destination_str = self.destination.y(), self.destination.x() # departure_time = (self.dlg.timeEdit.time().hour()*3600 + self.dlg.timeEdit.time().minute()*60+ self.dlg.timeEdit.time().second()) # print(departure_time) import time import datetime # departure = self.totimestamp(self.dlg.timeEdit.dateTime()) if self.dlg.nowtime.isChecked(): departure = 'now' else: departure = self.dlg.timeEdit.dateTime().toSecsSinceEpoch() print(departure) if vp_layer.featureCount() > 3: if self.dlg.avoid.currentText() == 'None': nav_request = 'origin={0},{1}&destination={2},{3}&waypoints={4}&departure_time={5}&mode={6}&model={7}&key={8}'.format( self.origin.y(), self.origin.x(), self.destination.y(), self.destination.x(), '|'.join(waypoints), departure, self.dlg.mode.currentText(), self.dlg.model.currentText(), api_key) else: nav_request = 'origin={0},{1}&destination={2},{3}&waypoints={4}&departure_time={5}&avoid={6}&mode={7}&model={8}&key={9}'.format( self.origin.y(), self.origin.x(), self.destination.y(), self.destination.x(), '|'.join(waypoints), departure, self.dlg.avoid.currentText(), self.dlg.mode.currentText(), self.dlg.model.currentText(), api_key) elif vp_layer.featureCount() == 3: if self.dlg.avoid.currentText() == 'None': nav_request = 'origin={0},{1}&destination={2},{3}&waypoints={4}&departure_time={5}&mode={6}&model={7}&key={8}'.format( self.origin.y(), self.origin.x(), self.destination.y(), self.destination.x(), waypoints[0], departure, self.dlg.mode.currentText(), self.dlg.model.currentText(), api_key) else: nav_request = 'origin={0},{1}&destination={2},{3}&waypoints={4}&departure_time={5}&avoid={6}&mode={7}&model={8}&key={9}'.format( self.origin.y(), self.origin.x(), self.destination.y(), self.destination.x(), waypoints[0], departure, self.dlg.avoid.currentText(), self.dlg.mode.currentText(), self.dlg.model.currentText(), api_key) else: if self.dlg.avoid.currentText() == 'None': nav_request = 'origin={0},{1}&destination={2},{3}&departure_time={4}&mode={5}&model={6}&key={7}'.format( self.origin.y(), self.origin.x(), self.destination.y(), self.destination.x(), departure, self.dlg.mode.currentText(), self.dlg.model.currentText(), api_key) # print(nav_request) else: nav_request = 'origin={0},{1}&destination={2},{3}&departure_time{4}&avoid={5}&mode={6}&model={7}&key={8}'.format( self.origin.y(), self.origin.x(), self.destination.y(), self.destination.x(), departure, self.dlg.avoid.currentText(), self.dlg.mode.currentText(), self.dlg.model.currentText(), api_key) request = endpoint + nav_request print(request) response = urllib.request.urlopen(request).read() directions = json.loads(response) keys = directions.keys() # print(keys) # print(directions['error_message'], directions['routes']) routes = directions['routes'] legs = routes[0]['legs'] line = routes[0]['overview_polyline'] # print(routes) points = polyline.decode(line['points']) self.route_layer = QgsVectorLayer( "Point?crs=EPSG:4326&field=route_id:String(100)&field=distance:String(100)&field=time:String(100)&field=ascending/descending:String(100)&field=departure_time:String(100)&field=roads_to_avoid:String(100)&field=traffic_model:String(100)", "route_points", "memory") provider = self.route_layer.dataProvider() # QgsProject.instance().addMapLayer(self.route_layer) if len(legs[0]['duration']['text'].split(' ')) == 2: duration1 = legs[0]['duration']['text'].split(' ') print(duration1, 'dur') duration = duration1[0] else: duration1 = legs[0]['duration']['text'].split(' ') print(duration1, 'dur1') duration = str((int(duration1[0]) * 60) + int(duration1[2])) self.route_layer.startEditing() route_attrib = [ self.dlg.route_id.text(), legs[0]['distance']['text'].split(' ')[0], duration, self.dlg.direction.currentText(), (self.dlg.timeEdit.dateTime()), self.dlg.avoid.currentText(), self.dlg.model.currentText() ] # print((self.dlg.timeEdit.time())) # print(route_attrib) for i in points: outelem = QgsFeature(self.route_layer.fields()) outelem.setGeometry( QgsGeometry.fromPointXY(QgsPointXY(i[1], i[0]))) outelem.setFields(self.route_layer.fields()) outelem.setAttributes(route_attrib) featurelist.append(outelem) # print(outelem) self.route_layer.dataProvider().addFeatures(featurelist) self.route_layer.commitChanges() result = processing.run( "qgis:pointstopath", { 'INPUT': self.route_layer, 'ORDER_FIELD': 'route_id', 'GROUP_FIELD': None, 'DATE_FORMAT': '', 'OUTPUT': 'memory:' }) if not self.dlg.checkBox.isChecked(): route = QgsVectorLayer( "Linestring?crs=EPSG:4326&field=route_id:String(100)&field=distance(km):String(100)&field=time(min):String(100)&field=ascending/descending:String(100)&field=departure_time:String(100)&field=duration_in_traffic(min):String(100)&field=roads_to_avoid:String(100)&field=traffic_model:String(100)&field=no_of_nodes:String(100)", "route", "memory") else: # print(self.dlg.route_id.text(), route_attrib2) route = self.dlg.layer.currentLayer() fields = route.dataProvider().fields() field_name = [field.name() for field in fields] # line_layer = QgsVectorLayer(result['OUTPUT'], 'route') featurelist2 = [] # if self.dlg.mode.currentText() not in ['walking', 'bicycling', 'transit']: if 'duration_in_traffic' in legs[0].keys(): if len(legs[0]['duration']['text'].split(' ')) == 2: duration1 = legs[0]['duration_in_traffic']['text'].split( ' ') print(duration1, 'dur12') duration_in_traffic = duration1[0] else: duration1 = legs[0]['duration_in_traffic']['text'].split( ' ') print(duration1, 'dur13') duration_in_traffic = str((int(duration1[0]) * 60) + int(duration1[2])) if 'fid' in field_name: route_attrib2 = [ route.featureCount(), self.dlg.route_id.text(), legs[0]['distance']['text'].split(' ')[0], duration, self.dlg.direction.currentText(), (self.dlg.timeEdit.dateTime()), duration_in_traffic, self.dlg.avoid.currentText(), self.dlg.model.currentText(), str(self.route_layer.featureCount()) ] else: route_attrib2 = [ self.dlg.route_id.text(), legs[0]['distance']['text'].split(' ')[0], duration, self.dlg.direction.currentText(), (self.dlg.timeEdit.dateTime()), duration_in_traffic, self.dlg.avoid.currentText(), self.dlg.model.currentText(), str(self.route_layer.featureCount()) ] else: if 'fid' in field_name: route_attrib2 = [ route.featureCount(), self.dlg.route_id.text(), legs[0]['distance']['text'].split(' ')[0], duration, self.dlg.direction.currentText(), (self.dlg.timeEdit.dateTime()), 'None', self.dlg.avoid.currentText(), self.dlg.model.currentText(), str(self.route_layer.featureCount()) ] else: route_attrib2 = [ self.dlg.route_id.text(), legs[0]['distance']['text'].split(' ')[0], duration, self.dlg.direction.currentText(), (self.dlg.timeEdit.dateTime()), duration_in_traffic, self.dlg.avoid.currentText(), self.dlg.model.currentText(), str(self.route_layer.featureCount()) ] # print(field_name) # if 'fid' in field_name: # # route.startEditing() # # print(route.dataProvider().fieldNameIndex('fid')) # # route.dataProvider().deleteAttributes([route.dataProvider().fieldNameIndex('fid')]) # # route.updateFields() # # field_name = [field.name() for field in fields] # # print(field_name) # # route_attrib2 = [route.featureCount(), self.dlg.route_id.text(), legs[0]['distance']['text'].split(' ')[0], duration, self.dlg.direction.currentText(),(self.dlg.timeEdit.dateTime()),'None',self.dlg.avoid.currentText(), self.dlg.model.currentText(), str(self.route_layer.featureCount())] # else: # pass provider = route.dataProvider() route.startEditing() request = QgsFeatureRequest() # set order by field clause = QgsFeatureRequest.OrderByClause('route_id', ascending=False) orderby = QgsFeatureRequest.OrderBy([clause]) request.setOrderBy(orderby) fields = route.dataProvider().fields() field_name = [field.name() for field in fields] for feature in result['OUTPUT'].getFeatures(): outelem = QgsFeature(route.fields()) outelem.setGeometry(feature.geometry()) outelem.setFields(route.fields()) if 'fid' not in field_name: outelem.setAttributes(route_attrib2) else: for index, field in enumerate(field_name): if field != 'fid': print(field, route_attrib2[index]) outelem[field] = route_attrib2[index] featurelist2.append(outelem) route.dataProvider().addFeatures(featurelist2) # route.updateFeature(feature) route.commitChanges() # QgsProject.instance().addMapLayer(route) if route.featureCount() == 1: file_path = os.path.abspath( os.path.join(os.path.dirname(__file__), "route_style.qml")) route.loadNamedStyle(file_path) else: # result_del = processing.run("qgis:deletecolumn", { # 'INPUT': route, # 'COLUMN': ['gid'], 'OUTPUT': 'memory:'}) # QgsProject.instance().addMapLayer(result_del['OUTPUT']) # result = processing.run("native:addautoincrementalfield", # {'INPUT': result_del['OUTPUT'], # 'FIELD_NAME': 'gid', 'START': 1, 'GROUP_FIELDS': [], # 'SORT_EXPRESSION': '', # 'SORT_ASCENDING': False, 'SORT_NULLS_FIRST': False, 'OUTPUT': 'memory:route'}) # # QgsProject.instance().removeMapLayer(route) # route = result['OUTPUT'] QgsProject.instance().addMapLayer(route) # provide file name index and field's unique values # fni = route.dataProvider().fieldNameIndex('route_id') # unique_values = route.uniqueValues(fni) # fni2 = route.dataProvider().fieldNameIndex('route_id') # unique_values2 = route.uniqueValues(fni2) # unique_values2 = sorted(unique_values2) unique_values2 = [] unique_values = [] request = QgsFeatureRequest() # set order by field clause = QgsFeatureRequest.OrderByClause('route_id', ascending=False) orderby = QgsFeatureRequest.OrderBy([clause]) request.setOrderBy(orderby) for feature in route.getFeatures(): attrib = feature.attributes() unique_values2.append(attrib[ route.dataProvider().fieldNameIndex('route_id')]) unique_values.append(attrib[ route.dataProvider().fieldNameIndex('route_id')]) from random import randrange # fill categories categories = [] # print(unique_values) # unique_values = sorted(unique_values) print(unique_values, unique_values2) for index, unique_value in enumerate(unique_values): # initialize the default symbol for this geometry type # symbol = QgsSymbol.defaultSymbol(route.geometryType()) # symbol = QgsSymbol.Symbol().setShape(QgsSimpleMarkerSymbolLayerBase.Star # symbol.appendSymbolLayer(symbol_layer) # configure a symbol layer # sym = route.renderer().symbol() # double headed symbol = QgsSymbol.defaultSymbol(route.geometryType()) # double headed sym_layer = QgsArrowSymbolLayer.create({ "arrow_width": "1", "arrow_start_width": "1", "head_length": "1.5", "head_thickness": "1.5", "head_type": "0", "arrow_type": "0", "is_curved": "0", }) fill_sym = QgsFillSymbol.createSimple({ "color": '%d, %d, %d' % (randrange(0, 256), randrange( 0, 256), randrange(0, 256)) }) sym_layer.setSubSymbol(fill_sym) symbol.changeSymbolLayer(0, sym_layer) # layer_style = {} # layer_style['color'] = '%d, %d, %d' % (randrange(0, 256), randrange(0, 256), randrange(0, 256)) # layer_style['outline'] = '#FF0000' # # layer_style['width'] = '7.6' # symbol_layer = QgsSimpleFillSymbolLayer.create(layer_style) # replace default symbol layer with the configured one # if symbol_layer is not None: # symbol.changeSymbolLayer(0, symbol_layer) # symbol.setWidth(0.66) # create renderer object category = QgsRendererCategory(unique_value, symbol, str(unique_values2[index])) # entry for the list of category items categories.append(category) # create renderer object renderer = QgsCategorizedSymbolRenderer('route_id', categories) # assign the created renderer to the layer if renderer is not None: route.setRenderer(renderer) route.triggerRepaint() ltl = QgsProject.instance().layerTreeRoot().findLayer( route.id()) ltm = iface.layerTreeView() # ltm.sortItems(0, Qt.AscendingOrder) # view = iface.layerTreeView() # ltm.model().AllowNodeReorder() index_newfeat = ltm.model().index(0, 0) node = ltm.model().index2node(index_newfeat) nodes = ltm.model().layerLegendNodes(node) legendNodes = ltm.model().layerLegendNodes(ltl) legend_dict = {} legend_dict[node.name()] = legendNodes # print(legend_dict) ltm.setSortingEnabled(True) ltm.sortByColumn(0, Qt.DescendingOrder) for index, ln in enumerate(legendNodes): if index + 1 != route.featureCount(): ln.setData(Qt.Unchecked, Qt.CheckStateRole) # index_newfeat = ltm.model().index(route.featureCount()-1, 0) # print(index_newfeat) # node = ltm.model().index2node(index_newfeat) # print(node) # nodes = ltm.model().layerLegendNodes(node) # # layer_and_nodes[n.name()] = nodes # # print(layer_and_nodes) # # legend_get = ltm.model().index2legendNode(nodes) # print(nodes) # print(index, ln) # print(index, ltm.model().legendRootIndex(ln), ltm.model().legendNode2index(ln), ln, index_newfeat) # if index+1 != int(self.dlg.route_id.text()): # ln.setData(Qt.Checked, Qt.CheckStateRole) if not self.dlg.checkBox.isChecked(): if self.dlg.output.text() != '': path = self.dlg.output.text() QgsVectorFileWriter.writeAsVectorFormat( route, path, 'UTF-8', route.crs(), 'ESRI Shapefile') # layer = QgsProject.instance().layerTreeRoot().findLayer(route.id()) # print(layer.name()) output = self.dlg.output.text().split('/') route_path = QgsVectorLayer( path, output[len(output) - 1].split('.')[0]) QgsProject.instance().addMapLayer(route_path) else: QgsProject.instance().addMapLayer(route) listselect = [] for index, feature in enumerate(route.getFeatures()): if index + 1 == route.featureCount(): listselect.append(feature.id()) route.select(listselect) iface.actionZoomToSelected().trigger() except Exception as e: alert = QMessageBox() alert.setWindowTitle('Alert') if self.dlg.mode.currentText() in [ 'walking', 'bicycling', 'transit' ]: alert.setText( str(e) + '\nRoute not available for selected mode.') else: alert.setText(str(e)) result = alert.exec_() print(e)
class Geonet: """QGIS Plugin Implementation.""" def __init__(self, iface): """Constructor. :param iface: An interface instance that will be passed to this class which provides the hook by which you can manipulate the QGIS application at run time. :type iface: QgsInterface """ # Save reference to the QGIS interface self.iface = iface # initialize plugin directory self.plugin_dir = os.path.dirname(__file__) # initialize locale locale = QSettings().value('locale/userLocale')[0:2] locale_path = os.path.join(self.plugin_dir, 'i18n', 'Geonet_{}.qm'.format(locale)) if os.path.exists(locale_path): self.translator = QTranslator() self.translator.load(locale_path) if qVersion() > '4.3.3': QCoreApplication.installTranslator(self.translator) # Declare instance attributes self.actions = [] self.menu = self.tr(u'&Geonet') # Check if plugin was started the first time in current QGIS session # Must be set in initGui() to survive plugin reloads self.first_start = None # noinspection PyMethodMayBeStatic def tr(self, message): """Get the translation for a string using Qt translation API. We implement this ourselves since we do not inherit QObject. :param message: String for translation. :type message: str, QString :returns: Translated version of message. :rtype: QString """ # noinspection PyTypeChecker,PyArgumentList,PyCallByClass return QCoreApplication.translate('Geonet', message) def add_action(self, icon_path, text, callback, enabled_flag=True, add_to_menu=True, add_to_toolbar=True, status_tip=None, whats_this=None, parent=None): """Add a toolbar icon to the toolbar. :param icon_path: Path to the icon for this action. Can be a resource path (e.g. ':/plugins/foo/bar.png') or a normal file system path. :type icon_path: str :param text: Text that should be shown in menu items for this action. :type text: str :param callback: Function to be called when the action is triggered. :type callback: function :param enabled_flag: A flag indicating if the action should be enabled by default. Defaults to True. :type enabled_flag: bool :param add_to_menu: Flag indicating whether the action should also be added to the menu. Defaults to True. :type add_to_menu: bool :param add_to_toolbar: Flag indicating whether the action should also be added to the toolbar. Defaults to True. :type add_to_toolbar: bool :param status_tip: Optional text to show in a popup when mouse pointer hovers over the action. :type status_tip: str :param parent: Parent widget for the new action. Defaults None. :type parent: QWidget :param whats_this: Optional text to show in the status bar when the mouse pointer hovers over the action. :returns: The action that was created. Note that the action is also added to self.actions list. :rtype: QAction """ icon = QIcon(icon_path) action = QAction(icon, text, parent) action.triggered.connect(callback) action.setEnabled(enabled_flag) if status_tip is not None: action.setStatusTip(status_tip) if whats_this is not None: action.setWhatsThis(whats_this) if add_to_toolbar: # Adds plugin icon to Plugins toolbar self.iface.addToolBarIcon(action) if add_to_menu: self.iface.addPluginToMenu(self.menu, action) self.actions.append(action) return action def initGui(self): """Create the menu entries and toolbar icons inside the QGIS GUI.""" self.add_action('D:/Code/QGIS_Plugin/geonet/feature.png', text=self.tr(u'Import feaure'), callback=self.import_feature, parent=self.iface.mainWindow()) self.add_action('D:/Code/QGIS_Plugin/geonet/dangle.png', text=self.tr(u'Clean dangle nodes'), callback=self.dangle_clean, parent=self.iface.mainWindow()) self.add_action('D:/Code/QGIS_Plugin/geonet/pseudo.png', text=self.tr(u'Clean pseudo nodes'), callback=self.pseudo_clean, parent=self.iface.mainWindow()) self.add_action('D:/Code/QGIS_Plugin/geonet/graph.png', text=self.tr(u'Build graph'), callback=self.graph_build, parent=self.iface.mainWindow()) self.add_action('D:/Code/QGIS_Plugin/geonet/shortpath.png', text=self.tr(u'Shortest Path'), callback=self.shortest_path, parent=self.iface.mainWindow()) # init params self.resDlg = GeonetTableView() self.model = QStandardItemModel() self.resDlg.tView.verticalHeader().hide() self.resDlg.tView.setSelectionBehavior(QAbstractItemView.SelectRows) self.resDlg.tView.setSelectionMode(QAbstractItemView.SingleSelection) self.resDlg.tView.setEditTriggers(QAbstractItemView.NoEditTriggers) self.resDlg.tView.clicked.connect(self._zoom_to_feat) self.canvas = self.iface.mapCanvas() self.corrSet = set() self.errSet = set() self.errFeatMap = defaultdict(set) self.errPointList = [] self.newFeatMap = {} self._id = 0 self.iNode = [] self.featLayer = None self.g = None self.tool = PointTool(self.iface.mapCanvas()) self.tool.trigger.connect(self._add_node_selected) self.iface.mapCanvas().setMapTool(self.tool) # will be set False in run() self.first_start = True def unload(self): """Removes the plugin menu item and icon from QGIS GUI.""" for action in self.actions: self.iface.removePluginMenu(self.tr(u'&Geonet'), action) self.iface.removeToolBarIcon(action) def import_feature(self): """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 self.dlg = FeatInputDialog() self.dlg.mLayerComboBox.clear() self.errFeatMap.clear() self.newFeatMap.clear() layers = list(QgsProject.instance().mapLayers().values()) for layer in layers: if layer.type() == layer.VectorLayer: self.dlg.mLayerComboBox.addItem(layer.name()) # show the dialog self.dlg.show() # Run the dialog event loop result = self.dlg.exec_() # See if OK was pressed if result: self.featLayer = layers[self.dlg.mLayerComboBox.currentIndex()] lineFeatIter = self.featLayer.getFeatures() # Find pseudo points list(map(self._map_point_to_feat, lineFeatIter)) self.tool.activate() def dangle_clean(self): if self.featLayer is None: QMessageBox.warning(None, "Warning", "Please choose a feature first!") return self.model.setHorizontalHeaderLabels( ["Point_X", "Point_Y", "Feature ID"]) self.dangleList = [] for (point, feat_ids) in self.errFeatMap.items(): if len(feat_ids) == 1: # Pseudo node self.dangleList.extend(map(lambda x: (point, x), feat_ids)) self._render_table(self.dangleList) self._render_err_layer("dangle", [x for (x, _) in self.dangleList]) self.resDlg.show() result = self.resDlg.exec_() if result: pass self.model.clear() def pseudo_clean(self): if self.featLayer is None: QMessageBox.warning(None, "Warning", "Please choose a feature first!") return self.model.setHorizontalHeaderLabels( ["Point_X", "Point_Y", "Feature ID"]) self.pseduoList = [] for (point, feat_ids) in self.errFeatMap.items(): if len(feat_ids) == 2: # Pseudo node self.pseduoList.extend(map(lambda x: (point, x), feat_ids)) self._render_table(self.pseduoList) self._render_err_layer("pseudo", [x for (x, _) in self.pseduoList]) self.resDlg.show() result = self.resDlg.exec_() if result: self.pBar = WaitProgressDialog() self.thread = WorkThread(net=self) cancelButton = QPushButton("Cancel") self.pBar.setCancelButton(cancelButton) cancelButton.clicked.connect(self.thread.terminate) cancelButton.setGeometry(100, 100, 100, 100) self.pBar.show() self.thread.start() # self._render_corr_layer("pseudo", feat_set.values()) self.model.clear() def graph_build(self): if self.featLayer is None: QMessageBox.warning(None, "Warning", "Please choose a feature first!") return self.g = nx.Graph() featIter = self.featLayer.getFeatures() self.node_map = {} self.node_set = set() self.weighted_edges = [] self.node_id = 0 list(map(self._map_point_to_edge, featIter)) self.g.add_weighted_edges_from(self.weighted_edges) self._render_node_layer(self.g.nodes()) # self.tool.activate() def shortest_path(self): if self.g is None: QMessageBox.warning(None, "Warning", "Please build the graph first!") return if len(self.iNode) > 1: startNode, endNode = self.iNode[0].geometry().asPoint( ), self.iNode[1].geometry().asPoint() _route = nx.shortest_path(self.g, startNode, endNode) self.iNode.clear() self.featLayer.removeSelection() self.canvas.refresh() self._render_route_layer(_route) # self.tool.deactivate() def _clean_work_by_thread(self): print("----- Clean work start -----") # Union find feature set featCount = len(self.newFeatMap) _father = [i for i in range(0, featCount)] _rank = [0] * featCount def _find(x): if _father[x] != x: _father[x] = _find(_father[x]) return _father[x] def _union(x, y): _x = _find(x) _y = _find(y) if _x == _y: return if _rank[_x] < _rank[_y]: _father[_x] = _y elif _rank[_x] > _rank[_y]: _father[_y] = _x else: _father[_y] = _x _rank[x] += 1 for (_, feat_ids) in self.errFeatMap.items(): feat_ids = list(feat_ids) for feat_id in feat_ids[1:]: _union(feat_id, feat_ids[0]) feat_set = defaultdict(list) for idx, feat in enumerate(_father): feat_set[feat].append(idx) print('----- Render work start -----') self._render_corr_layer("pseudo", feat_set.values()) def _map_point_to_feat(self, feat): geom = feat.geometry() # Map features as point to id if geom.isMultipart(): for line in geom.asGeometryCollection(): new_feat = QgsFeature(self._id) new_feat.setGeometry(line) self._id += 1 startPoint, endPoint = line.asPolyline()[0], line.asPolyline( )[-1] self.newFeatMap[new_feat.id()] = new_feat self.errFeatMap[startPoint].add(new_feat.id()) self.errFeatMap[endPoint].add(new_feat.id()) else: new_feat = QgsFeature(self._id) new_feat.setGeometry(geom) self._id += 1 startPoint, endPoint = geom.asPolyline()[0], geom.asPolyline()[-1] self.newFeatMap[new_feat.id()] = new_feat self.errFeatMap[startPoint].add(new_feat.id()) self.errFeatMap[endPoint].add(new_feat.id()) def _map_point_to_edge(self, feat): geom = feat.geometry() weighted_edges = [] if geom.isMultipart(): for line in geom.asGeometryCollection(): startPoint, endPoint = line.asPolyline()[0], line.asPolyline( )[-1] startNode = QgsFeature() startNode.setGeometry(QgsGeometry.fromPointXY(startPoint)) # self.node_id += 1 endNode = QgsFeature() endNode.setGeometry(QgsGeometry.fromPointXY(endPoint)) # self.node_id += 1 self.weighted_edges.append( (startPoint, endPoint, line.length())) else: startPoint, endPoint = geom.asPolyline()[0], geom.asPolyline()[-1] startNode = QgsFeature(self.node_id) startNode.setGeometry(QgsGeometry.fromPointXY(startPoint)) self.node_id += 1 endNode = QgsFeature(self.node_id) endNode.setGeometry(QgsGeometry.fromPointXY(endPoint)) self.node_id += 1 self.weighted_edges.append((startNode, endNode, geom.length())) def _zoom_to_feat(self, item): # Clear previous selection for layer in self.canvas.layers(): if layer.type() == layer.VectorLayer: layer.removeSelection() self.canvas.refresh() # Get id of feature selected feat_id = self.model.item(item.row(), 2).data(0) self.featLayer.select(int(feat_id)) # Zoom canvas self.canvas.zoomToSelected(self.featLayer) self.canvas.refresh() def _render_table(self, list): for (idx, err) in enumerate(list): self.model.setItem(idx, 0, QStandardItem(str(err[0].x()))) self.model.setItem(idx, 1, QStandardItem(str(err[0].y()))) self.model.setItem(idx, 2, QStandardItem(str(err[1]))) self.resDlg.tView.setModel(self.model) # self.resDlg.tView.selectionModel().currentRowChanged.connect(self.zoom_to_feature) w = self.resDlg.tView.width() self.resDlg.tView.setColumnWidth(0, w / 3 - 1) self.resDlg.tView.setColumnWidth(1, w / 3 - 1) self.resDlg.tView.setColumnWidth(2, w - 2 * w / 3 - 2) def _render_err_layer(self, name, _list): self.errLayer = QgsVectorLayer( "Point?crs=" + self.featLayer.crs().authid(), self.featLayer.name() + "_" + name + "_Nodes", "memory") errPr = self.errLayer.dataProvider() self.errLayer.startEditing() feats = map(self._gen_point_feats, _list) errPr.addFeatures(feats) self.errLayer.commitChanges() self._add_layer(self.errLayer) def _render_corr_layer(self, name, _list): # Init correct layer self.corrLayer = QgsVectorLayer( "LineString?crs=" + self.featLayer.crs().authid(), self.featLayer.name() + "_" + name + "_Correct", "memory") corrPr = self.corrLayer.dataProvider() self.corrLayer.startEditing() # Generate new features feats = map(self._gen_corr_feats, _list) corrPr.addFeatures(feats) self.corrLayer.commitChanges() # self._add_layer(self.corrLayer) def _render_route_layer(self, _list): self.routeLayer = QgsVectorLayer( "LineString?crs=" + self.featLayer.crs().authid(), self.featLayer.name() + "_Route", "memory") routePr = self.routeLayer.dataProvider() self.routeLayer.startEditing() _symbol = QgsLineSymbol() _symbol.appendSymbolLayer(QgsArrowSymbolLayer()) self.routeLayer.renderer().setSymbol(_symbol) for idx in range(len(_list) - 1): route_seg = [_list[idx], _list[idx + 1]] feat = QgsFeature() feat.setGeometry(QgsGeometry.fromPolylineXY(route_seg)) routePr.addFeatures([feat]) self.routeLayer.commitChanges() self._add_layer(self.routeLayer) # self.canvas.refresh() def _render_node_layer(self, _list): self.nodeLayer = QgsVectorLayer( "Point?crs=" + self.featLayer.crs().authid(), self.featLayer.name() + "_Graph_Vertex", "memory") nodePr = self.nodeLayer.dataProvider() self.nodeLayer.startEditing() # Generate new features feats = map(self._gen_point_feats, _list) # feats = _list nodePr.addFeatures(feats) self.nodeLayer.commitChanges() self._add_layer(self.nodeLayer) def _add_layer(self, layer): QgsProject.instance().addMapLayer(layer) def _add_node_selected(self, node): self.iNode.append(node) self.nodeLayer.select([x.id() for x in self.iNode]) def _gen_point_feats(self, p): feat = QgsFeature() feat.setGeometry(QgsGeometry.fromPointXY(p)) return feat def _gen_corr_feats(self, feat_ids): new_feat = QgsFeature() geom = new_feat.geometry() # Combine features for idx, feat_id in enumerate(feat_ids): feat = self.newFeatMap[feat_id] if idx == 0: new_feat.setGeometry(feat.geometry()) geom = new_feat.geometry() else: geom = geom.combine(feat.geometry()) new_feat.setGeometry(geom) return new_feat def _add_corr_layer(self): QgsProject.instance().addMapLayer(self.corrLayer)