def setUp(self): myShpFile = os.path.join(TEST_DATA_DIR, 'rectangles.shp') layer = QgsVectorLayer(myShpFile, 'Points', 'ogr') QgsMapLayerRegistry.instance().addMapLayer(layer) # Create rulebased style sym1 = QgsFillSymbolV2.createSimple({'color': '#fdbf6f'}) sym2 = QgsFillSymbolV2.createSimple({'color': '#71bd6c'}) sym3 = QgsFillSymbolV2.createSimple({'color': '#1f78b4'}) self.r1 = QgsRuleBasedRendererV2.Rule(sym1, 0, 0, '"id" = 1') self.r2 = QgsRuleBasedRendererV2.Rule(sym2, 0, 0, '"id" = 2') self.r3 = QgsRuleBasedRendererV2.Rule(sym3, 0, 0, 'ELSE') self.rootrule = QgsRuleBasedRendererV2.Rule(None) self.rootrule.appendChild(self.r1) self.rootrule.appendChild(self.r2) self.rootrule.appendChild(self.r3) self.renderer = QgsRuleBasedRendererV2(self.rootrule) layer.setRendererV2(self.renderer) self.mapsettings = CANVAS.mapSettings() self.mapsettings.setOutputSize(QSize(400, 400)) self.mapsettings.setOutputDpi(96) self.mapsettings.setExtent(QgsRectangle(-163, 22, -70, 52)) rendered_layers = [layer.id()] self.mapsettings.setLayers(rendered_layers)
def setUp(self): self.iface = get_iface() myShpFile = os.path.join(TEST_DATA_DIR, 'rectangles.shp') layer = QgsVectorLayer(myShpFile, 'Points', 'ogr') QgsMapLayerRegistry.instance().addMapLayer(layer) # Create rulebased style sym1 = QgsFillSymbolV2.createSimple({'color': '#fdbf6f'}) sym2 = QgsFillSymbolV2.createSimple({'color': '#71bd6c'}) sym3 = QgsFillSymbolV2.createSimple({'color': '#1f78b4'}) self.r1 = QgsRuleBasedRendererV2.Rule(sym1, 0, 0, '"id" = 1') self.r2 = QgsRuleBasedRendererV2.Rule(sym2, 0, 0, '"id" = 2') self.r3 = QgsRuleBasedRendererV2.Rule(sym3, 0, 0, 'ELSE') self.rootrule = QgsRuleBasedRendererV2.Rule(None) self.rootrule.appendChild(self.r1) self.rootrule.appendChild(self.r2) self.rootrule.appendChild(self.r3) self.renderer = QgsRuleBasedRendererV2(self.rootrule) layer.setRendererV2(self.renderer) self.mapsettings = self.iface.mapCanvas().mapSettings() self.mapsettings.setOutputSize(QSize(400, 400)) self.mapsettings.setOutputDpi(96) self.mapsettings.setExtent(QgsRectangle(-163, 22, -70, 52)) rendered_layers = [layer.id()] self.mapsettings.setLayers(rendered_layers)
def render_and_save_pointwise_output_layer( self, pointwise_output_csv_filepath, output_layer_name, on_values_of_attribute, graduated_rendering_interval_points, shapefile_path=''): uri = 'file:///' + pointwise_output_csv_filepath + \ '?delimiter=%s&crs=epsg:32643&xField=%s&yField=%s' % (',', 'X', 'Y') output_layer = QgsVectorLayer(uri, output_layer_name, 'delimitedtext') if 'Crop' in on_values_of_attribute: ET_D_max = max([ point.budget.PET_minus_AET_crop_end for point in model_calculator.output_grid_points ]) elif 'Monsoon' in on_values_of_attribute: ET_D_max = max([ point.budget.PET_minus_AET_monsoon_end for point in model_calculator.output_grid_points ]) graduated_symbol_renderer_range_list = [] opacity = 1 intervals_count = len(graduated_rendering_interval_points) for i in range(intervals_count): interval_min = 0 if graduated_rendering_interval_points[ i] == 0 else ( graduated_rendering_interval_points[i] * ET_D_max / 100.0 + 0.01) interval_max = (graduated_rendering_interval_points * ET_D_max / 100.0) label = "{0:.2f} - {1:.2f}".format(interval_min, interval_max) colour = QColor( int(255 * (1 - (i + 1.0) / (intervals_count + 1.0))), 0, 0) # +1 done to tackle boundary cases symbol = QgsSymbolV2.defaultSymbol(output_layer.geometryType()) symbol.setColor(colour) symbol.setAlpha(opacity) interval_range = QgsRendererRangeV2(interval_min, interval_max, symbol, label) graduated_symbol_renderer_range_list.append(interval_range) renderer = QgsGraduatedSymbolRendererV2( '', graduated_symbol_renderer_range_list) renderer.setMode(QgsGraduatedSymbolRendererV2.EqualInterval) renderer.setClassAttribute(on_values_of_attribute) output_layer.setRendererV2(renderer) QgsMapLayerRegistry.instance().addMapLayer(output_layer) if shapefile_path != '': QgsVectorFileWriter.writeAsVectorFormat(output_layer, shapefile_path, "utf-8", None, "ESRI Shapefile") return output_layer
class TestQgsArrowSymbolLayer(unittest.TestCase): def setUp(self): self.iface = get_iface() lines_shp = os.path.join(TEST_DATA_DIR, 'lines.shp') self.lines_layer = QgsVectorLayer(lines_shp, 'Lines', 'ogr') QgsMapLayerRegistry.instance().addMapLayer(self.lines_layer) # Create style sym2 = QgsLineSymbolV2.createSimple({'color': '#fdbf6f'}) self.lines_layer.setRendererV2(QgsSingleSymbolRendererV2(sym2)) self.mapsettings = self.iface.mapCanvas().mapSettings() self.mapsettings.setOutputSize(QSize(400, 400)) self.mapsettings.setOutputDpi(96) self.mapsettings.setExtent(QgsRectangle(-113, 28, -91, 40)) self.mapsettings.setBackgroundColor(QColor("white")) def tearDown(self): QgsMapLayerRegistry.instance().removeAllMapLayers() def test_1(self): sym = self.lines_layer.rendererV2().symbol() sym_layer = QgsArrowSymbolLayer.create({'head_size': '6.5'}) dd = QgsDataDefined("(@geometry_point_num % 4) * 2") sym_layer.setDataDefinedProperty("arrow_width", dd) dd2 = QgsDataDefined("(@geometry_point_num % 4) * 2") sym_layer.setDataDefinedProperty("head_size", dd2) fill_sym = QgsFillSymbolV2.createSimple({'color': '#8bcfff', 'outline_color': '#000000', 'outline_style': 'solid', 'outline_width': '1'}) sym_layer.setSubSymbol(fill_sym) sym.changeSymbolLayer(0, sym_layer) rendered_layers = [self.lines_layer.id()] self.mapsettings.setLayers(rendered_layers) renderchecker = QgsMultiRenderChecker() renderchecker.setMapSettings(self.mapsettings) renderchecker.setControlName('expected_arrowsymbollayer_1') self.assertTrue(renderchecker.runTest('arrowsymbollayer_1')) def test_2(self): sym = self.lines_layer.rendererV2().symbol() # double headed sym_layer = QgsArrowSymbolLayer.create({'arrow_width': '5', 'head_size': '6.5', 'head_type': '2'}) fill_sym = QgsFillSymbolV2.createSimple({'color': '#8bcfff', 'outline_color': '#000000', 'outline_style': 'solid', 'outline_width': '1'}) sym_layer.setSubSymbol(fill_sym) sym.changeSymbolLayer(0, sym_layer) rendered_layers = [self.lines_layer.id()] self.mapsettings.setLayers(rendered_layers) renderchecker = QgsMultiRenderChecker() renderchecker.setMapSettings(self.mapsettings) renderchecker.setControlName('expected_arrowsymbollayer_2') self.assertTrue(renderchecker.runTest('arrowsymbollayer_2'))
def legend_test(self): self.mAtlasMap.setAtlasDriven(True) self.mAtlasMap.setAtlasScalingMode(QgsComposerMap.Auto) self.mAtlasMap.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.fromPoint(QgsPoint(-0.638, 48.954))) f2 = QgsFeature(2) f2.initAttributes(2) f2.setAttribute(0, 2) f2.setAttribute(1, "Test label 2") f2.setGeometry(QgsGeometry.fromPoint(QgsPoint(-1.682, 48.550))) pr.addFeatures([f1, f2]) # categorized symbology r = QgsCategorizedSymbolRendererV2("attr", [QgsRendererCategoryV2(1, QgsMarkerSymbolV2.createSimple({"color": "255,0,0"}), "red"), QgsRendererCategoryV2(2, QgsMarkerSymbolV2.createSimple({"color": "0,0,255"}), "blue")]) ptLayer.setRendererV2(r) QgsMapLayerRegistry.instance().addMapLayer(ptLayer) # add the point layer to the map settings layers = self.mapSettings.layers() layers = [ptLayer.id()] + layers self.mapSettings.setLayers(layers) # add a legend legend = QgsComposerLegend(self.mComposition) legend.moveBy(200, 100) # sets the legend filter parameter legend.setComposerMap(self.mAtlasMap) legend.setLegendFilterOutAtlas(True) self.mComposition.addComposerLegend(legend) self.mAtlas.beginRender() self.mAtlas.prepareForFeature(0) self.mLabel1.adjustSizeToText() checker = QgsCompositionChecker('atlas_legend', self.mComposition) myTestResult, myMessage = checker.testComposition() assert myTestResult self.mAtlas.endRender() # restore state self.mapSettings.setLayers([layers[1]]) self.mComposition.removeComposerItem(legend) QgsMapLayerRegistry.instance().removeMapLayer(ptLayer.id())
class TestQgsSymbolExpressionVariables(TestCase): def setUp(self): myShpFile = os.path.join(TEST_DATA_DIR, 'polys.shp') self.layer = QgsVectorLayer(myShpFile, 'Polys', 'ogr') QgsMapLayerRegistry.instance().addMapLayer(self.layer) rendered_layers = [self.layer.id()] self.mapsettings = CANVAS.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): QgsMapLayerRegistry.instance().removeAllMapLayers() def testPartNum(self): # Create rulebased style sym1 = QgsFillSymbolV2.createSimple({'color': '#fdbf6f'}) renderer = QgsSingleSymbolRendererV2(sym1) renderer.symbols()[0].symbolLayers()[0].setDataDefinedProperty( 'color', 'color_rgb( (@geometry_part_num - 1) * 200, 0, 0 )') self.layer.setRendererV2(renderer) # Setup rendering check renderchecker = QgsMultiRenderChecker() renderchecker.setMapSettings(self.mapsettings) renderchecker.setControlName('expected_geometry_part_num') result = renderchecker.runTest('part_geometry_part_num') self.assertTrue(result) def testPartCount(self): # Create rulebased style sym1 = QgsFillSymbolV2.createSimple({'color': '#fdbf6f'}) renderer = QgsSingleSymbolRendererV2(sym1) renderer.symbols()[0].symbolLayers()[0].setDataDefinedProperty( 'color', 'color_rgb( (@geometry_part_count - 1) * 200, 0, 0 )') self.layer.setRendererV2(renderer) # Setup rendering check renderchecker = QgsMultiRenderChecker() renderchecker.setMapSettings(self.mapsettings) renderchecker.setControlName('expected_geometry_part_count') result = renderchecker.runTest('part_geometry_part_count') self.assertTrue(result)
class TestQgsSymbolExpressionVariables(TestCase): def setUp(self): myShpFile = os.path.join(TEST_DATA_DIR, 'polys.shp') self.layer = QgsVectorLayer(myShpFile, 'Polys', 'ogr') QgsMapLayerRegistry.instance().addMapLayer(self.layer) rendered_layers = [self.layer.id()] self.mapsettings = CANVAS.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): QgsMapLayerRegistry.instance().removeAllMapLayers() def testPartNum(self): # Create rulebased style sym1 = QgsFillSymbolV2.createSimple({'color': '#fdbf6f'}) renderer = QgsSingleSymbolRendererV2(sym1) renderer.symbols()[0].symbolLayers()[0].setDataDefinedProperty('color', 'color_rgb( (@geometry_part_num - 1) * 200, 0, 0 )') self.layer.setRendererV2(renderer) # Setup rendering check renderchecker = QgsMultiRenderChecker() renderchecker.setMapSettings(self.mapsettings) renderchecker.setControlName('expected_geometry_part_num') result = renderchecker.runTest('part_geometry_part_num') self.assertTrue(result) def testPartCount(self): # Create rulebased style sym1 = QgsFillSymbolV2.createSimple({'color': '#fdbf6f'}) renderer = QgsSingleSymbolRendererV2(sym1) renderer.symbols()[0].symbolLayers()[0].setDataDefinedProperty('color', 'color_rgb( (@geometry_part_count - 1) * 200, 0, 0 )') self.layer.setRendererV2(renderer) # Setup rendering check renderchecker = QgsMultiRenderChecker() renderchecker.setMapSettings(self.mapsettings) renderchecker.setControlName('expected_geometry_part_count') result = renderchecker.runTest('part_geometry_part_count') self.assertTrue(result)
def make_OD_markers(nb, xo, yo, xd, yd, list_coords=None): """ Prepare the Origin (green), Destination (red) and Intalternative_geometriesermediates (grey) markers. """ OD_layer = QgsVectorLayer( "Point?crs=epsg:4326&field=id_route:integer&field=role:string(80)", "markers_osrm{}".format(nb), "memory") features = [] fet = QgsFeature() fet.setGeometry(QgsGeometry.fromPoint(QgsPoint(float(xo), float(yo)))) fet.setAttributes([nb, 'Origin']) features.append(fet) fet = QgsFeature() fet.setGeometry(QgsGeometry.fromPoint(QgsPoint(float(xd), float(yd)))) fet.setAttributes([nb, 'Destination']) features.append(fet) marker_rules = [ ('Origin', '"role" LIKE \'Origin\'', '#50b56d', 4), ('Destination', '"role" LIKE \'Destination\'', '#d31115', 4), ] if list_coords: for i, pt in enumerate(list_coords): fet = QgsFeature() fet.setGeometry( QgsGeometry.fromPoint(QgsPoint(float(pt[0]), float(pt[1]))) ) fet.setAttributes([nb, 'Via point n°{}'.format(i)]) features.append(fet) marker_rules.insert( 1, ('Intermediate', '"role" LIKE \'Via point%\'', 'grey', 2)) OD_layer.dataProvider().addFeatures(features) symbol = QgsSymbolV2.defaultSymbol(OD_layer.geometryType()) renderer = QgsRuleBasedRendererV2(symbol) root_rule = renderer.rootRule() for label, expression, color_name, size in marker_rules: rule = root_rule.children()[0].clone() rule.setLabel(label) rule.setFilterExpression(expression) rule.symbol().setColor(QtGui.QColor(color_name)) rule.symbol().setSize(size) root_rule.appendChild(rule) root_rule.removeChildAt(0) OD_layer.setRendererV2(renderer) return OD_layer
def make_OD_markers(nb, xo, yo, xd, yd, list_coords=None): """ Prepare the Origin (green), Destination (red) and Intermediates (grey) markers. """ OD_layer = QgsVectorLayer( "Point?crs=epsg:4326&field=id_route:integer&field=role:string(80)", "markers_osrm{}".format(nb), "memory") features = [] fet = QgsFeature() fet.setGeometry(QgsGeometry.fromPoint(QgsPoint(float(xo), float(yo)))) fet.setAttributes([nb, 'Origin']) features.append(fet) fet = QgsFeature() fet.setGeometry(QgsGeometry.fromPoint(QgsPoint(float(xd), float(yd)))) fet.setAttributes([nb, 'Destination']) features.append(fet) marker_rules = [ ('Origin', '"role" LIKE \'Origin\'', '#50b56d', 4), ('Destination', '"role" LIKE \'Destination\'', '#d31115', 4), ] if list_coords: for i, pt in enumerate(list_coords): fet = QgsFeature() fet.setGeometry( QgsGeometry.fromPoint(QgsPoint(float(pt[0]), float(pt[1])))) fet.setAttributes([nb, 'Via point n°{}'.format(i)]) features.append(fet) marker_rules.insert( 1, ('Intermediate', '"role" LIKE \'Via point%\'', 'grey', 2)) OD_layer.dataProvider().addFeatures(features) symbol = QgsSymbolV2.defaultSymbol(OD_layer.geometryType()) renderer = QgsRuleBasedRendererV2(symbol) root_rule = renderer.rootRule() for label, expression, color_name, size in marker_rules: rule = root_rule.children()[0].clone() rule.setLabel(label) rule.setFilterExpression(expression) rule.symbol().setColor(QtGui.QColor(color_name)) rule.symbol().setSize(size) root_rule.appendChild(rule) root_rule.removeChildAt(0) OD_layer.setRendererV2(renderer) return OD_layer
def setUp(self): myShpFile = os.path.join(TEST_DATA_DIR, 'polys_overlapping.shp') layer = QgsVectorLayer(myShpFile, 'Polygons', 'ogr') QgsMapLayerRegistry.instance().addMapLayer(layer) # Create style sym1 = QgsFillSymbolV2.createSimple({'color': '#fdbf6f'}) self.renderer = QgsSingleSymbolRendererV2(sym1) layer.setRendererV2(self.renderer) self.mapsettings = CANVAS.mapSettings() self.mapsettings.setOutputSize(QSize(400, 400)) self.mapsettings.setOutputDpi(96) self.mapsettings.setExtent(QgsRectangle(-133, 22, -70, 52)) rendered_layers = [layer.id()] self.mapsettings.setLayers(rendered_layers)
def add_final_pts(self, pts): center_pt_layer = QgsVectorLayer( "Point?crs=epsg:4326&field=id_center:integer&field=role:string(80)", "center_{}".format(self.nb_isocr), "memory") my_symb = QgsSymbolV2.defaultSymbol(0) my_symb.setColor(QtGui.QColor("#e31a1c")) my_symb.setSize(1.2) center_pt_layer.setRendererV2(QgsSingleSymbolRendererV2(my_symb)) features = [] for nb, pt in enumerate(pts): xo, yo = pt["point"] fet = QgsFeature() fet.setGeometry(QgsGeometry.fromPoint(QgsPoint(float(xo), float(yo)))) fet.setAttributes([nb, 'Origin']) features.append(fet) center_pt_layer.dataProvider().addFeatures(features) QgsMapLayerRegistry.instance().addMapLayer(center_pt_layer)
def setUp(self): myShpFile = os.path.join(TEST_DATA_DIR, 'polys_overlapping.shp') layer = QgsVectorLayer(myShpFile, 'Polys', 'ogr') QgsMapLayerRegistry.instance().addMapLayer(layer) # Create rulebased style sym1 = QgsFillSymbolV2.createSimple({'color': '#fdbf6f'}) self.renderer = QgsSingleSymbolRendererV2(sym1) layer.setRendererV2(self.renderer) rendered_layers = [layer.id()] self.mapsettings = CANVAS.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 createLayerGrille(uriGrille): layerGrille = QgsVectorLayer(uriGrille, CONST_NOM_LAYER_GRILLE, "ogr") fieldIndex = getFieldIndex(layerGrille) if fieldIndex < 0: caps = layerGrille.dataProvider().capabilities() if caps & QgsVectorDataProvider.AddAttributes: layerGrille.dataProvider().addAttributes( [QgsField(CONST_ATTRIBUT_ID, QVariant.Int)]) layerGrille.updateFields() # Style props = {'color': '241,241,241,0', 'size': '1', 'color_border': '255,0,0'} s = QgsFillSymbolV2.createSimple(props) layerGrille.setRendererV2(QgsSingleSymbolRendererV2(s)) return layerGrille
def add_final_pts(self, pts): center_pt_layer = QgsVectorLayer( "Point?crs=epsg:4326&field=id_center:integer&field=role:string(80)", "isochrone_center_{}".format(self.nb_isocr), "memory") my_symb = QgsSymbolV2.defaultSymbol(0) my_symb.setColor(QtGui.QColor("#e31a1c")) my_symb.setSize(1.2) center_pt_layer.setRendererV2(QgsSingleSymbolRendererV2(my_symb)) features = [] for nb, pt in enumerate(pts): xo, yo = pt["point"] fet = QgsFeature() fet.setGeometry( QgsGeometry.fromPoint(QgsPoint(float(xo), float(yo)))) fet.setAttributes([nb, 'Origin']) features.append(fet) center_pt_layer.dataProvider().addFeatures(features) QgsMapLayerRegistry.instance().addMapLayer(center_pt_layer)
def testInitialSizeSymbolMapUnits(self): """Test initial size of legend with a symbol size in map units""" point_path = os.path.join(TEST_DATA_DIR, 'points.shp') point_layer = QgsVectorLayer(point_path, 'points', 'ogr') QgsMapLayerRegistry.instance().addMapLayers([point_layer]) marker_symbol = QgsMarkerSymbolV2.createSimple({ 'color': '#ff0000', 'outline_style': 'no', 'size': '5', 'size_unit': 'MapUnit' }) point_layer.setRendererV2(QgsSingleSymbolRendererV2(marker_symbol)) s = QgsMapSettings() s.setLayers([point_layer.id()]) s.setCrsTransformEnabled(False) composition = QgsComposition(s) composition.setPaperSize(297, 210) composer_map = QgsComposerMap(composition, 20, 20, 80, 80) composer_map.setFrameEnabled(True) composition.addComposerMap(composer_map) composer_map.setNewExtent(point_layer.extent()) legend = QgsComposerLegend(composition) legend.setSceneRect(QRectF(120, 20, 80, 80)) legend.setFrameEnabled(True) legend.setFrameOutlineWidth(2) legend.setBackgroundColor(QColor(200, 200, 200)) legend.setTitle('') composition.addComposerLegend(legend) legend.setComposerMap(composer_map) checker = QgsCompositionChecker('composer_legend_mapunits', composition) checker.setControlPathPrefix("composer_legend") result, message = checker.testComposition() self.assertTrue(result, message) QgsMapLayerRegistry.instance().removeMapLayers([point_layer.id()])
def create_virtual_layer(self, virtual_layer_name): sql = ("SELECT value FROM " + self.controller.schema_name + ".config_param_user" " WHERE cur_user = current_user AND parameter = 'virtual_layer_polygon'") row = self.controller.get_row(sql) if not row: sql = ("INSERT INTO "+self.schema_name + ".config_param_user (parameter, value, cur_user) " " VALUES ('virtual_layer_polygon', '"+virtual_layer_name+"', current_user)") self.controller.execute_sql(sql) srid = self.controller.plugin_settings_value('srid') uri = "Polygon?crs=epsg:" + str(srid) virtual_layer = QgsVectorLayer(uri, virtual_layer_name, "memory") props = {'color': '0, 0, 0', 'style': 'no', 'style_border': 'solid', 'color_border': '255, 0, 0'} s = QgsFillSymbolV2.createSimple(props) virtual_layer.setRendererV2(QgsSingleSymbolRendererV2(s)) virtual_layer.updateExtents() QgsProject.instance().setSnapSettingsForLayer(virtual_layer.id(), True, 2, 0, 1.0, False) QgsMapLayerRegistry.instance().addMapLayer(virtual_layer) self.iface.mapCanvas().refresh()
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') QgsMapLayerRegistry.instance().addMapLayer(self.layer) self.renderer = QgsNullSymbolRenderer() self.layer.setRendererV2(self.renderer) rendered_layers = [self.layer.id()] 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): QgsMapLayerRegistry.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 testInitialSizeSymbolMapUnits(self): """Test initial size of legend with a symbol size in map units""" point_path = os.path.join(TEST_DATA_DIR, 'points.shp') point_layer = QgsVectorLayer(point_path, 'points', 'ogr') QgsMapLayerRegistry.instance().addMapLayers([point_layer]) marker_symbol = QgsMarkerSymbolV2.createSimple({'color': '#ff0000', 'outline_style': 'no', 'size': '5', 'size_unit': 'MapUnit'}) point_layer.setRendererV2(QgsSingleSymbolRendererV2(marker_symbol)) s = QgsMapSettings() s.setLayers([point_layer.id()]) s.setCrsTransformEnabled(False) composition = QgsComposition(s) composition.setPaperSize(297, 210) composer_map = QgsComposerMap(composition, 20, 20, 80, 80) composer_map.setFrameEnabled(True) composition.addComposerMap(composer_map) composer_map.setNewExtent(point_layer.extent()) legend = QgsComposerLegend(composition) legend.setSceneRect(QRectF(120, 20, 80, 80)) legend.setFrameEnabled(True) legend.setFrameOutlineWidth(2) legend.setBackgroundColor(QColor(200, 200, 200)) legend.setTitle('') composition.addComposerLegend(legend) legend.setComposerMap(composer_map) checker = QgsCompositionChecker( 'composer_legend_mapunits', composition) checker.setControlPathPrefix("composer_legend") result, message = checker.testComposition() self.assertTrue(result, message) QgsMapLayerRegistry.instance().removeMapLayers([point_layer.id()])
class RFUDockWidget(QDockWidget, gui_dckwdgt_rfu_connector): closed = pyqtSignal() downloaded = pyqtSignal() uploaded = pyqtSignal() def __init__(self, iface, canvas, map_layer_registry, conn=None, parent=None): super(RFUDockWidget, self).__init__(parent) self.setupUi(self) self.iface = iface self.canvas = canvas self.map_layer_registry = map_layer_registry self.conn = conn self.zone = None self.precision_class = [] self.ellips_acronym = [] self.dflt_ellips_acronym = None self.selected_ellips_acronym = None self.nature = [] self.auth_creator = [] self.url = None self.l_vertex = None self.l_edge = None self.layers = [self.l_vertex, self.l_edge] # Initialize dicts which contains changed datasets self.edges_added = {} self.vertices_added = {} self.edges_removed = {} self.vertices_removed = {} self.edges_modified = {} self.vertices_modified = {} self.downloadPushButton.clicked.connect(self.on_downloaded) self.permalinkLineEdit.returnPressed.connect(self.on_downloaded) self.projComboBox.currentIndexChanged.connect(self.set_destination_crs) def closeEvent(self, event): self.closed.emit() def on_downloaded(self): widget = self.iface.messageBar().createMessage(u"Géofoncier", u"Téléchargement du RFU.") progress_bar = QProgressBar() progress_bar.setMinimum(0) progress_bar.setMaximum(2) widget.layout().addWidget(progress_bar) self.iface.messageBar().pushWidget(widget, QgsMessageBar.WARNING) progress_bar.setValue(1) # https://pro.geofoncier.fr/index.php?¢re=-196406,5983255&context=metropole url = self.permalinkLineEdit.text() if not url: return self.abort_action(msg=u"Veuillez renseigner le permalien.") self.url = url try: self.download(self.url) except Exception as e: return self.abort_action(msg=e.message) progress_bar.setValue(2) self.iface.messageBar().clearWidgets() return def on_reset(self): # Ensure that the action is intentional msg = (u"Cette action est irreversible. " u"Toute modification sera perdue. " u"Êtes-vous sûr de vouloir réinitialiser l'outil ?") resp = QMessageBox.question(self, r"Question", msg, QMessageBox.Yes, QMessageBox.No) if resp == QMessageBox.Yes: self.reset() return def on_uploaded(self): self.uploaded.emit() # Create message widget = self.iface.messageBar().createMessage(u"Géofoncier", u"Envoi des modifications.") progress_bar = QProgressBar() progress_bar.setMinimum(0) progress_bar.setMaximum(3) widget.layout().addWidget(progress_bar) self.iface.messageBar().pushWidget(widget, QgsMessageBar.WARNING) progress_bar.setValue(1) enr_ref_dossier, ok = QInputDialog.getText( self, u"Référence de dossier", u"Vous êtes sur le point de soumettre\n" u"les modifications au serveur Géofoncier.\n" u"Veuillez renseigner la référence du dossier.") if not ok: return self.abort_action() if not enr_ref_dossier: return self.abort_action(msg=u"Merci de renseigner une référence de dossier.") commentaire = u"Dossier %s" % enr_ref_dossier dossiers = self.conn.dossiersoge_dossiers(self.zone, enr_ref_dossier) if dossiers.code != 200: return self.abort_action(msg=dossiers.read()) tree = EltTree.fromstring(dossiers.read()) # Check if exception err = tree.find(r"./erreur") if err: return self.abort_action(msg=err.text) nb_dossiers = int(tree.find(r"./dossiers").attrib[r"total"]) if nb_dossiers == 0: return self.abort_action(msg=u"Le dossier \'%s\' n'existe pas." % enr_ref_dossier) if nb_dossiers >= 1: # Prendre par défaut le dernier dossier dans la liste dossier_uri = tree.getiterator(tag=r"dossier")[nb_dossiers-1].find( r"{http://www.w3.org/2005/Atom}link") enr_api_dossier = dossier_uri.attrib[r"href"].split(r"/")[-1][1:] progress_bar.setValue(2) # Stop editing mode for layer in self.layers: if layer.isEditable(): layer.commitChanges() # Check if dataset changes if (self.edges_added or self.vertices_added or self.edges_removed or self.vertices_removed or self.edges_modified or self.vertices_modified): pass else: return self.abort_action(msg=u"Aucune modification des données n'est détecté.") # Upload, reset and re-download datasets try: log = self.upload(enr_api_dossier=enr_api_dossier, commentaire=commentaire) self.reset() self.download(self.url) except Exception as e: return self.abort_action(msg=e.message) self.canvas.zoomToFullExtent() self.iface.messageBar().clearWidgets() return QMessageBox.information(self, r"Information", u"\r".join(log)) def download(self, url): # Test if permalink is valid pattern = r"^(https?:\/\/(\w+[\w\-\.\:\/])+)\?((\&+)?(\w+)\=?([\w\-\.\:\,]+?)?)+(\&+)?$" if not re.match(pattern, self.url): raise Exception(u"Le permalien n'est pas valide.") # Extract params from url params = parse_qs(urlparse(self.url).query) # Check mandatory parameters try: context = str(params[r"context"][0]) center = params[r"centre"][0] except: raise Exception(u"Les paramètres \'Context\' et \'Centre\' sont obligatoires.") auth_contexts = [r"metropole", r"guadeloupe", r"stmartin", r"stbarthelemy", r"guyane", r"reunion", r"mayotte"] # Check if context is valid if context not in auth_contexts: raise Exception(u"La valeur \'%s\' est incorrecte.\n\n" u"\'Context\' doit prentre une des %s valeurs suivantes: " u"%s" % (context, len(auth_contexts), ", ".join(auth_contexts))) self.zone = context if self.zone in [r"guadeloupe", r"stmartin", r"stbarthelemy"]: self.zone = r"antilles" # Check if XY are valid if not re.match(r"^\-?\d+,\-?\d+$", center): raise Exception(u"Les coordonnées XY du centre sont incorrectes.") # Extract XY (¢re) xcenter = int(center.split(r",")[0]) ycenter = int(center.split(r",")[1]) # Compute the bbox xmin = xcenter - self.conn.extract_lim / 2 xmax = xcenter + self.conn.extract_lim / 2 ymin = ycenter - self.conn.extract_lim / 2 ymax = ycenter + self.conn.extract_lim / 2 # Transform coordinates in WGS84 bbox = tools.reproj(QgsRectangle(xmin, ymin, xmax, ymax), 3857, 4326) # Extract RFU (Send the request) resp = self.conn.extraction(bbox.xMinimum(), bbox.yMinimum(), bbox.xMaximum(), bbox.yMaximum()) if resp.code != 200: raise Exception(resp.read()) tree = EltTree.fromstring(resp.read()) # Check if error err = tree.find(r"./erreur") if err: raise Exception(err.text) # Create the layer: "Masque d'extraction" self.l_bbox = QgsVectorLayer(r"Polygon?crs=epsg:4326&index=yes", u"Zone de travail", r"memory") p_bbox = self.l_bbox.dataProvider() simple_symbol = QgsFillSymbolV2.createSimple({ r"color": r"116,97,87,255", r"style": r"b_diagonal", r"outline_style": r"no"}) renderer_bbox = QgsInvertedPolygonRenderer(QgsSingleSymbolRendererV2(simple_symbol)) self.l_bbox.setRendererV2(renderer_bbox) ft_bbox = QgsFeature() ft_bbox.setGeometry(QgsGeometry.fromRect(QgsRectangle(bbox.xMinimum(), bbox.yMinimum(), bbox.xMaximum(), bbox.yMaximum()))) p_bbox.addFeatures([ft_bbox]) self.l_bbox.updateFields() self.l_bbox.updateExtents() # Create layers.. self.layers = self.extract_layers(tree) self.l_vertex = self.layers[0] self.l_edge = self.layers[1] # Add layer to the registry self.map_layer_registry.addMapLayers([self.l_vertex, self.l_edge, self.l_bbox]) # Set the map canvas layer set self.canvas.setLayerSet([QgsMapCanvasLayer(self.l_vertex), QgsMapCanvasLayer(self.l_edge), QgsMapCanvasLayer(self.l_bbox)]) # Set extent self.canvas.setExtent(QgsRectangle(bbox.xMinimum(), bbox.yMinimum(), bbox.xMaximum(), bbox.yMaximum())) self.features_vertex_backed_up = \ dict((ft[r"fid"], ft) for ft in self.get_features(self.l_vertex)) self.features_edge_backed_up = \ dict((ft[r"fid"], ft) for ft in self.get_features(self.l_edge)) # Get Capabitilies resp = self.conn.get_capabilities(self.zone) if resp.code != 200: raise Exception(resp.read()) tree = EltTree.fromstring(resp.read()) err = tree.find(r"./erreur") if err: raise Exception(err.text) for entry in tree.findall(r"./classe_rattachement/classe"): t = (entry.attrib[r"som_precision_rattachement"], entry.text) self.precision_class.append(t) for entry in tree.findall(r"./representation_plane_sommet_autorise/representation_plane_sommet"): t = (entry.attrib[r"som_representation_plane"], entry.attrib[r"epsg_crs_id"], entry.text) self.ellips_acronym.append(t) for entry in tree.findall(r"./nature_sommet_conseille/nature"): self.nature.append(entry.text) for entry in tree.findall(r"./som_ge_createur_autorise/som_ge_createur"): t = (entry.attrib[r"num_ge"], entry.text) self.auth_creator.append(t) try: ft = next(ft for ft in self.l_vertex.getFeatures()) ft_attrib = tools.attrib_as_kv(ft.fields(), ft.attributes()) self.dflt_ellips_acronym = ft_attrib[r"som_representation_plane"] except: self.dflt_ellips_acronym = None for i, e in enumerate(self.ellips_acronym): self.projComboBox.addItem(e[2]) if not self.dflt_ellips_acronym: continue if self.dflt_ellips_acronym == e[0]: # Check projection in combobox self.projComboBox.setCurrentIndex(i) # Activate 'On The Fly' self.canvas.setCrsTransformEnabled(True) # Then change the CRS in canvas crs = QgsCoordinateReferenceSystem(int(e[1]), QgsCoordinateReferenceSystem.EpsgCrsId) self.canvas.setDestinationCrs(crs) # Then, start editing mode.. for layer in self.layers: if not layer.isEditable(): layer.startEditing() self.projComboBox.setDisabled(False) self.permalinkLineEdit.setDisabled(True) self.downloadPushButton.setDisabled(True) self.resetPushButton.setDisabled(False) self.uploadPushButton.setDisabled(False) self.downloadPushButton.clicked.disconnect(self.on_downloaded) self.permalinkLineEdit.returnPressed.disconnect(self.on_downloaded) self.resetPushButton.clicked.connect(self.on_reset) self.uploadPushButton.clicked.connect(self.on_uploaded) self.downloaded.emit() return True def reset(self): """Remove RFU layers.""" # Remove RFU layers try: self.map_layer_registry.removeMapLayers([ self.l_vertex.id(), self.l_edge.id(), self.l_bbox.id()]) except: return # Reset variable self.precision_class = [] self.ellips_acronym = [] self.dflt_ellips_acronym = None self.nature = [] self.auth_creator = [] self.l_vertex = None self.l_edge = None self.layers = [self.l_vertex, self.l_edge] self.edges_added = {} self.vertices_added = {} self.edges_removed = {} self.vertices_removed = {} self.edges_modified = {} self.vertices_modified = {} # Reset ComboBox which contains projections authorized self.projComboBox.clear() self.projComboBox.setDisabled(True) self.permalinkLineEdit.clear() self.permalinkLineEdit.setDisabled(False) self.permalinkLineEdit.returnPressed.connect(self.on_downloaded) self.downloadPushButton.setDisabled(False) self.downloadPushButton.clicked.connect(self.on_downloaded) self.resetPushButton.setDisabled(True) self.resetPushButton.clicked.disconnect(self.on_reset) self.uploadPushButton.setDisabled(True) self.uploadPushButton.clicked.disconnect(self.on_uploaded) return True def upload(self, enr_api_dossier=None, commentaire=None): """Upload data to Géofoncier REST API. On success returns the log messages (Array). """ # Set XML document root = EltTree.Element(r"rfu") # Add to our XML document datasets which have been changed if self.vertices_added: for fid in self.vertices_added: tools.xml_subelt_creator(root, u"sommet", data=self.vertices_added[fid], action=r"create") if self.edges_added: for fid in self.edges_added: tools.xml_subelt_creator(root, u"limite", data=self.edges_added[fid], action=r"create") if self.vertices_removed: for fid in self.vertices_removed: tools.xml_subelt_creator(root, u"sommet", data=self.vertices_removed[fid], action=r"delete") if self.edges_removed: for fid in self.edges_removed: tools.xml_subelt_creator(root, u"limite", data=self.edges_removed[fid], action=r"delete") if self.vertices_modified: for fid in self.vertices_modified: tools.xml_subelt_creator(root, u"sommet", data=self.vertices_modified[fid], action=r"update") if self.edges_modified: for fid in self.edges_modified: tools.xml_subelt_creator(root, u"limite", data=self.edges_modified[fid], action=r"update") # Create a new changeset Id changeset_id = self.create_changeset(enr_api_dossier=enr_api_dossier, commentaire=commentaire) # Add changeset value in our XML document root.attrib[r"changeset"] = changeset_id # Send data edit = self.conn.edit(self.zone, EltTree.tostring(root)) if edit.code != 200: raise Exception(edit.read()) tree = EltTree.fromstring(edit.read()) err = tree.find(r"./erreur") if err: raise Exception(err.text) # Returns log info msgs_log = [] for log in tree.iter(r"log"): msgs_log.append(u"%s: %s" % (log.attrib[u"type"], log.text)) # Close the changeset self.destroy_changeset(changeset_id) # Reset all self.edges_added = {} self.vertices_added = {} self.edges_removed = {} self.vertices_removed = {} self.edges_modified = {} self.vertices_modified = {} return msgs_log def create_changeset(self, enr_api_dossier=None, commentaire=None): """Open a new changeset from Géofoncier API. On success, returns the new changeset id. """ opencs = self.conn.open_changeset(self.zone, enr_api_dossier=enr_api_dossier, commentaire=commentaire) if opencs.code != 200: raise Exception(opencs.read()) tree = EltTree.fromstring(opencs.read()) err = tree.find(r"./erreur") if err: raise Exception(err.text) treeterator = tree.getiterator(tag=r"changeset") # We should get only one changeset if len(treeterator) != 1: raise Exception(u"Le nombre de \'changeset\' est incohérent.\n" u"Merci de contacter l'administrateur Géofoncier.") return treeterator[0].attrib[r"id"] def destroy_changeset(self, id): """Close a changeset.""" closecs = self.conn.close_changeset(self.zone, id) if closecs.code != 200: raise Exception(closecs.read()) tree = EltTree.fromstring(closecs.read()) err = tree.find(r"./erreur") if err: raise Exception(err.text) return True def abort_action(self, msg=None): for layer in self.layers: if layer and not layer.isEditable(): layer.startEditing() # Clear message bar self.iface.messageBar().clearWidgets() if msg: return QMessageBox.warning(self, r"Warning", msg) return def extract_layers(self, tree): """Return a list of RFU layers.""" # Create vector layers.. l_vertex = QgsVectorLayer(r"Point?crs=epsg:4326&index=yes", u"Sommet RFU", r"memory") l_edge = QgsVectorLayer(r"LineString?crs=epsg:4326&index=yes", u"Limite RFU", r"memory") p_vertex = l_vertex.dataProvider() p_edge = l_edge.dataProvider() # Define default style renderer.. renderer_vertex = QgsRuleBasedRendererV2(QgsMarkerSymbolV2()) vertex_root_rule = renderer_vertex.rootRule() vertex_rules = ( ( (u"Borne, borne à puce, pierre, piquet, clou ou broche"), (u"$id >= 0 AND \"som_nature\" IN ('Borne'," u"'Borne à puce', 'Pierre', 'Piquet', 'Clou ou broche')"), r"#EC0000", 2.2 ), ( (u"Axe cours d'eau, axe fossé, haut de talus, pied de talus"), (u"$id >= 0 AND \"som_nature\" IN ('Axe cours d\'\'eau'," u"'Axe fossé', 'Haut de talus', 'Pied de talus')"), r"#EE8012", 2.2 ), ( (u"Angle de bâtiment, axe de mur, angle de mur, " u"angle de clôture, pylône et toute autre valeur"), (u"$id >= 0 AND \"som_nature\" NOT IN ('Borne'," u"'Borne à puce', 'Pierre', 'Piquet', 'Clou ou broche'," u"'Axe cours d\'\'eau', 'Axe fossé', 'Haut de talus'," u"'Pied de talus')"), r"#9784EC", 2.2 ), ( u"Temporaire", r"$id < 0", "cyan", 2.4 )) for label, expression, color, size in vertex_rules: rule = vertex_root_rule.children()[0].clone() rule.setLabel(label) rule.setFilterExpression(expression) rule.symbol().setColor(QColor(color)) rule.symbol().setSize(size) vertex_root_rule.appendChild(rule) vertex_root_rule.removeChildAt(0) l_vertex.setRendererV2(renderer_vertex) renderer_edge = QgsRuleBasedRendererV2(QgsLineSymbolV2()) edge_root_rule = renderer_edge.rootRule() edge_rules = ((r"Limite", r"$id >= 0", "#0A0AFF", 0.5), (r"Temporaire", r"$id < 0", "cyan", 1)) for label, expression, color, width in edge_rules: rule = edge_root_rule.children()[0].clone() rule.setLabel(label) rule.setFilterExpression(expression) rule.symbol().setColor(QColor(color)) rule.symbol().setWidth(width) edge_root_rule.appendChild(rule) edge_root_rule.removeChildAt(0) l_edge.setRendererV2(renderer_edge) # Add fields.. p_vertex.addAttributes([ QgsField(r"@id_noeud", QVariant.Int), # QgsField(r"@changeset", QVariant.Int), # QgsField(r"@timestamp", QVariant.Date), QgsField(r"@version", QVariant.Int), QgsField(r"som_ge_createur", QVariant.String), QgsField(r"som_nature", QVariant.String), QgsField(r"som_precision_rattachement", QVariant.Int), QgsField(r"som_coord_est", QVariant.Double), QgsField(r"som_coord_nord", QVariant.Double), QgsField(r"som_representation_plane", QVariant.String), # QgsField(r"date_creation", QVariant.Date) ]) p_edge.addAttributes([ QgsField(r"@id_arc", QVariant.Int), # QgsField(r"@id_noeud_debut", QVariant.Int), # QgsField(r"@id_noeud_fin", QVariant.Int), # QgsField(r"@changeset", QVariant.Int), # QgsField(r"@timestamp", QVariant.Date), QgsField(r"@version", QVariant.Int), QgsField(r"lim_ge_createur", QVariant.String), # QgsField(r"lim_date_creation", QVariant.Date) ]) # Add features from xml tree.. # ..to vertex layer.. fts_vertex = [] for e in tree.findall(r"sommet"): ft_vertex = QgsFeature() ft_vertex.setGeometry(QgsGeometry.fromWkt(e.attrib[r"geometrie"])) _id_noeud = int(e.attrib[r"id_noeud"]) # _changeset = int(e.attrib[r"changeset"]) # _timestamp = QDateTime(datetime.strptime( # e.attrib[r"timestamp"], r"%Y-%m-%d %H:%M:%S.%f")) _version = int(e.attrib[r"version"]) som_ge_createur = unicode(e.find(r"./som_ge_createur").text) som_nature = unicode(e.find(r"./som_nature").text) som_prec_rattcht = int(e.find(r"./som_precision_rattachement").text) som_coord_est = float(e.find(r"./som_coord_est").text) som_coord_nord = float(e.find(r"./som_coord_nord").text) som_repres_plane = unicode(e.find(r"./som_representation_plane").text) # som_date_creation = QDate(datetime.strptime( # e.find(r"./som_date_creation").text, r"%Y-%m-%d").date()) ft_vertex.setAttributes([ _id_noeud, # _changeset, # _timestamp, _version, som_ge_createur, som_nature, som_prec_rattcht, som_coord_est, som_coord_nord, som_repres_plane, # som_date_creation ]) fts_vertex.append(ft_vertex) # ..to edge layer.. fts_edge = [] for e in tree.findall(r"limite"): ft_edge = QgsFeature() ft_edge.setGeometry(QgsGeometry.fromWkt(e.attrib[r"geometrie"])) _id_arc = int(e.attrib[r"id_arc"]) # _id_noeud_debut = int(e.attrib[r"id_noeud_debut"]) # _id_noeud_fin = int(e.attrib[r"id_noeud_fin"]) # _changeset = int(e.attrib[r"changeset"]) # _timestamp = QDateTime(datetime.strptime( # e.attrib[r"timestamp"], r"%Y-%m-%d %H:%M:%S.%f")) _version = int(e.attrib[r"version"]) lim_ge_createur = unicode(e.find(r"./lim_ge_createur").text) # lim_date_creation = QDate(datetime.strptime( # e.find(r"./lim_date_creation").text, r"%Y-%m-%d").date()) ft_edge.setAttributes([ _id_arc, # _id_noeud_debut, # _id_noeud_fin, # _changeset, # _timestamp, _version, lim_ge_createur, # lim_date_creation ]) fts_edge.append(ft_edge) # Add features to layers.. p_vertex.addFeatures(fts_vertex) p_edge.addFeatures(fts_edge) # Update fields.. l_vertex.updateFields() l_edge.updateFields() # Update layer's extent.. l_vertex.updateExtents() l_edge.updateExtents() # Check if valid.. if not l_vertex.isValid() or not l_edge.isValid(): raise Exception(u"Une erreur est survenue lors du chargement de la couche.") # Set labelling... palyr = QgsPalLayerSettings() palyr.enabled = True # palyr.readFromLayer(l_vertex) palyr.fieldName = r"$id" # Expression $id palyr.placement = 1 # ::OverPoint palyr.quadOffset = 2 # ::QuadrantAboveRight palyr.setDataDefinedProperty(80, True, True, r"1", "") # ::OffsetUnits -> ::MM palyr.xOffset = 2.0 palyr.yOffset = -1.0 palyr.writeToLayer(l_vertex) # Then return layers.. return [l_vertex, l_edge] def get_features(self, layer): features = [] for ft in layer.getFeatures(): attributes = tools.attrib_as_kv(ft.fields(), ft.attributes()) attributes[r"fid"] = ft.id() features.append(attributes) return features def remove_features(self, layer_id, fids): for fid in fids: if layer_id == self.l_edge.id() and fid in self.features_edge_backed_up: self.edges_removed[fid] = self.features_edge_backed_up[fid] if layer_id == self.l_vertex.id() and fid in self.features_vertex_backed_up: self.vertices_removed[fid] = self.features_vertex_backed_up[fid] def add_features(self, layer_id, features): for ft in features: attrib = tools.attrib_as_kv( ft.fields(), ft.attributes(), qgsgeom=ft.geometry()) if layer_id == self.l_vertex.id(): self.vertices_added[ft.id()] = attrib if layer_id == self.l_edge.id(): self.edges_added[ft.id()] = attrib def modify_feature(self, layer_id, feature, qgsgeom=None): if qgsgeom: f = tools.attrib_as_kv( feature.fields(), feature.attributes(), qgsgeom=qgsgeom) else: f = tools.attrib_as_kv(feature.fields(), feature.attributes()) if self.l_edge.id() == layer_id: if feature.id() not in self.features_edge_backed_up: return self.edges_modified[feature.id()] = f if self.l_vertex.id() == layer_id: if feature.id() not in self.features_vertex_backed_up: return self.vertices_modified[feature.id()] = f def set_destination_crs(self, j): epsg = 4326 # by default for i, e in enumerate(self.ellips_acronym): if i == j: self.selected_ellips_acronym = e[0] epsg = int(e[1]) continue crs = QgsCoordinateReferenceSystem(epsg, QgsCoordinateReferenceSystem.EpsgCrsId) self.canvas.setDestinationCrs(crs) self.canvas.zoomToFullExtent()
def run(self): """Run method that performs all the real work""" self.dlg.layerComboBox.clear() self.dlg.sheetTypeComboBox.clear() self.dlg.scaleComboBox.clear() #self.dlg.label_2.setText('') Alllayers = self.iface.legendInterface().layers() #layer_list = [] lcount=0 for layer in Alllayers: xyCrs = layer.crs() if xyCrs.projectionAcronym()=='longlat': lcount=lcount+1 self.dlg.layerComboBox.addItem(layer.name(),layer) self.dlg.sheetTypeComboBox.addItem('Indian and Adjoining Countries Series Maps') self.dlg.sheetTypeComboBox.addItem('Open Series Maps') scale_list=['1:1M','1:250,000','1:125,000','1:50,000','1:25,000'] self.dlg.scaleComboBox.addItems(scale_list) # show the dialog self.dlg.show() # Run the dialog event loop result = self.dlg.exec_() # See if OK was pressed if result: global scaleID global sheetw global sheeth if lcount>0: scaleID=self.dlg.scaleComboBox.currentIndex()+1 maptype= self.dlg.sheetTypeComboBox.currentIndex()+1 if maptype==1: sheetw,sheeth=setFactor1(scaleID) if maptype==2: sheetw,sheeth=setFactor2(scaleID) index = self.dlg.layerComboBox.currentIndex() clayer = self.dlg.layerComboBox.itemData(index) e=clayer.extent() a,b,c=degDec2dms(e.xMinimum()) slongs=dmstosec(a,b,c) a,b,c=degDec2dms(e.xMaximum()) elongs=dmstosec(a,b,c) a,b,c=degDec2dms(e.yMinimum()) slats=dmstosec(a,b,c) a,b,c=degDec2dms(e.yMaximum()) elats=dmstosec(a,b,c) slongs,elongs,slats,elats=CalculateExtentInTermsOfSheet(slongs,elongs,slats,elats) Xgrids=int(elongs-slongs)//sheetw # // is used for modular division Ygrids=int(elats-slats)//sheeth layer = QgsVectorLayer("Polygon?crs=EPSG:4326", "TopoSheets", "memory") global poly global pr pr = layer.dataProvider() pr.addAttributes([QgsField("id",QVariant.Int),QgsField("SheetNo",QVariant.String),QgsField("Inside",QVariant.String)]) layer.updateFields() poly = QgsFeature() CalculateSheet(maptype,slats,slongs,Xgrids,Ygrids) n=0 # check intersection of selected layer feature with sheets fieldIdx = pr.fields().indexFromName('Inside' ) updateMap = {} for f in clayer.getFeatures(): for a in layer.getFeatures(): if a.geometry().intersects(f.geometry()): n=n+1 updateMap[a.id()] = { fieldIdx:1 } pr.changeAttributeValues(updateMap) # set the layer symbology values = ( ('In', True,True,QColor.fromRgb(95,254,99)), ('Out', False,False,'yellow'), ) # create a category for each item in values ranges=[] for label, lower, upper, color in values: symbol = QgsSymbolV2.defaultSymbol(layer.geometryType()) symbol.setColor(QColor(color)) rng = QgsRendererRangeV2(lower, upper, symbol, label) ranges.append(rng) expression = 'Inside' # field name renderer = QgsGraduatedSymbolRendererV2(expression, ranges) layer.setRendererV2(renderer) # set layer transparence and dolabelling layer.setLayerTransparency(65) layer.updateExtents() QgsMapLayerRegistry.instance().addMapLayers([layer]) layer.setCustomProperty("labeling", "pal") layer.setCustomProperty("labeling/enabled", "true") layer.setCustomProperty("labeling/fontFamily", "Arial") layer.setCustomProperty("labeling/fontSize", "10") layer.setCustomProperty("labeling/fieldName", "SheetNo") layer.setCustomProperty("labeling/placement", "1") iface.mapCanvas().refresh() else: iface.messageBar().pushMessage("Error", "No layers loaded, Load layer with Geographic Corrdinates", level=QgsMessageBar.CRITICAL) pass
def WPT2Layer(self): mapUnits = define._canvas.mapUnits() if define._mapCrs == None: if mapUnits == QGis.Meters: resultLayer = QgsVectorLayer( "Point?crs=EPSG:32633", "WPT_" + self.surfaceType.replace(" ", "_").replace("-", "_"), "memory") else: resultLayer = QgsVectorLayer( "Point?crs=EPSG:4326", "WPT_" + self.surfaceType.replace(" ", "_").replace("-", "_"), "memory") else: resultLayer = QgsVectorLayer( "Point?crs=%s" % define._mapCrs.authid(), "WPT_" + self.surfaceType.replace(" ", "_").replace("-", "_"), "memory") shpPath = "" if define.obstaclePath != None: shpPath = define.obstaclePath elif define.xmlPath != None: shpPath = define.xmlPath else: shpPath = define.appPath er = QgsVectorFileWriter.writeAsVectorFormat( resultLayer, shpPath + "/" + "RnavTurningSegmentAnalyserWpt" + ".shp", "utf-8", resultLayer.crs()) resultLayer = QgsVectorLayer( shpPath + "/" + "RnavTurningSegmentAnalyserWpt" + ".shp", "WPT_RnavTurningSegmentAnalyser", "ogr") fieldName = "CATEGORY" resultLayer.dataProvider().addAttributes( [QgsField(fieldName, QVariant.String)]) resultLayer.startEditing() fields = resultLayer.pendingFields() i = 1 feature = QgsFeature() feature.setFields(fields) feature.setGeometry( QgsGeometry.fromPoint(self.parametersPanel.pnlWaypoint1.Point3d)) feature.setAttribute(fieldName, "Waypoint1") pr = resultLayer.dataProvider() pr.addFeatures([feature]) # resultLayer.addFeature(feature) feature.setGeometry( QgsGeometry.fromPoint(self.parametersPanel.pnlWaypoint2.Point3d)) feature.setAttribute(fieldName, "Waypoint2") pr = resultLayer.dataProvider() pr.addFeatures([feature]) # resultLayer.addFeature(feature) resultLayer.commitChanges() renderCatFly = None if self.parametersPanel.cmbType1.SelectedIndex == 1: '''FlyOver''' symbolFlyOver = QgsSymbolV2.defaultSymbol( resultLayer.geometryType()) symbolFlyOver.deleteSymbolLayer(0) svgSymLayer = QgsSvgMarkerSymbolLayerV2("Resource/flyover.svg", 10.0, 0.0) symbolFlyOver.appendSymbolLayer(svgSymLayer) renderCatFly = QgsRendererCategoryV2(0, symbolFlyOver, "Fly Over") elif self.parametersPanel.cmbType1.SelectedIndex == 0: '''FlyBy''' symbolFlyBy = QgsSymbolV2.defaultSymbol(resultLayer.geometryType()) symbolFlyBy.deleteSymbolLayer(0) svgSymLayer = QgsSvgMarkerSymbolLayerV2("Resource/flyby.svg", 10.0, 0.0) symbolFlyBy.appendSymbolLayer(svgSymLayer) renderCatFly = QgsRendererCategoryV2(0, symbolFlyBy, "Fly By") else: return None WPT_EXPRESION = "CASE WHEN \"CATEGORY\" = 'Waypoint1' THEN 0 " + \ "END" symRenderer = QgsCategorizedSymbolRendererV2(WPT_EXPRESION, [renderCatFly]) resultLayer.setRendererV2(symRenderer) return resultLayer
def testCase(self): self.TEST_DATA_DIR = unitTestDataPath() vectorFileInfo = QFileInfo( self.TEST_DATA_DIR + "/france_parts.shp") mVectorLayer = QgsVectorLayer( vectorFileInfo.filePath(), vectorFileInfo.completeBaseName(), "ogr" ) QgsMapLayerRegistry.instance().addMapLayers( [mVectorLayer] ) # create composition with composer map mMapRenderer = QgsMapRenderer() layerStringList = [] layerStringList.append( mVectorLayer.id() ) mMapRenderer.setLayerSet( layerStringList ) mMapRenderer.setProjectionsEnabled( True ) mMapRenderer.setMapUnits( QGis.Meters ) # select epsg:2154 crs = QgsCoordinateReferenceSystem() crs.createFromSrid( 2154 ) mMapRenderer.setDestinationCrs( crs ) self.mComposition = QgsComposition( mMapRenderer ) self.mComposition.setPaperSize( 297, 210 ) # fix the renderer, fill with green props = { "color": "0,127,0" } fillSymbol = QgsFillSymbolV2.createSimple( props ) renderer = QgsSingleSymbolRendererV2( fillSymbol ) mVectorLayer.setRendererV2( renderer ) # the atlas map self.mAtlasMap = QgsComposerMap( self.mComposition, 20, 20, 130, 130 ) self.mAtlasMap.setFrameEnabled( True ) self.mComposition.addComposerMap( self.mAtlasMap ) # the atlas self.mAtlas = self.mComposition.atlasComposition() self.mAtlas.setCoverageLayer( mVectorLayer ) self.mAtlas.setEnabled( True ) self.mComposition.setAtlasMode( QgsComposition.ExportAtlas ) # an overview mOverview = QgsComposerMap( self.mComposition, 180, 20, 50, 50 ) mOverview.setFrameEnabled( True ) mOverview.setOverviewFrameMap( self.mAtlasMap.id() ) self.mComposition.addComposerMap( mOverview ) nextent = QgsRectangle( 49670.718, 6415139.086, 699672.519, 7065140.887 ) mOverview.setNewExtent( nextent ) # set the fill symbol of the overview map props2 = { "color": "127,0,0,127" } fillSymbol2 = QgsFillSymbolV2.createSimple( props2 ) mOverview.setOverviewFrameMapSymbol( fillSymbol2 ) # header label self.mLabel1 = QgsComposerLabel( self.mComposition ) self.mComposition.addComposerLabel( self.mLabel1 ) self.mLabel1.setText( "[% \"NAME_1\" %] area" ) self.mLabel1.setFont( QgsFontUtils.getStandardTestFont() ) self.mLabel1.adjustSizeToText() self.mLabel1.setSceneRect( QRectF( 150, 5, 60, 15 ) ) qWarning( "header label font: %s exactMatch:%s" % ( self.mLabel1.font().toString(), self.mLabel1.font().exactMatch() ) ) # feature number label self.mLabel2 = QgsComposerLabel( self.mComposition ) self.mComposition.addComposerLabel( self.mLabel2 ) self.mLabel2.setText( "# [%$feature || ' / ' || $numfeatures%]" ) self.mLabel2.setFont( QgsFontUtils.getStandardTestFont() ) self.mLabel2.adjustSizeToText() self.mLabel2.setSceneRect( QRectF( 150, 200, 60, 15 ) ) qWarning( "feature number label font: %s exactMatch:%s" % ( self.mLabel2.font().toString(), self.mLabel2.font().exactMatch() ) ) self.filename_test() self.autoscale_render_test() self.autoscale_render_test_old_api() self.fixedscale_render_test() self.predefinedscales_render_test() self.hidden_render_test()
def get_access_isochrones(self): """ Making the accessibility isochrones in few steps: - make a grid of points aroung the origin point, - snap each point (using OSRM locate function) on the road network, - get the time-distance between the origin point and each of these pts (using OSRM table function), - make an interpolation grid to extract polygons corresponding to the desired time intervals (using matplotlib library), - render the polygon. """ try: self.host = check_host(self.lineEdit_host.text()) self.profile = check_profile_name(self.lineEdit_profileName.text()) except (ValueError, AssertionError) as err: self.iface.messageBar().pushMessage( "Error", "Please provide a valid non-empty URL", duration=10) return if 'clicking' in self.comboBox_method.currentText(): pts = self.get_points_from_canvas() elif 'selecting' in self.comboBox_method.currentText(): layer = self.comboBox_pointlayer.currentLayer() pts, _ = get_coords_ids( layer, '', on_selected=self.checkBox_selectedFt.isChecked()) pts = tuple(pts) if not pts: return max_time = self.spinBox_max.value() interval_time = self.spinBox_intervall.value() nb_inter = int(round(max_time / interval_time)) + 1 levels = tuple([nb for nb in xrange(0, int( max_time + 1) + interval_time, interval_time)][:nb_inter]) self.make_prog_bar() self.max_points = 750 if len(pts) == 1 else 250 self.polygons = [] pts = [{"point": pt, "max": max_time, "levels": levels, "host": self.host, "profile": self.profile, "max_points": self.max_points} for pt in pts] pool = ThreadPool(processes=4 if len(pts) >= 4 else len(pts)) try: self.polygons = [i for i in pool.map(prep_access, pts)] except Exception as err: self.display_error(err, 1) return if len(self.polygons) == 1: self.polygons = self.polygons[0] else: self.polygons = np.array(self.polygons).transpose().tolist() self.polygons = [QgsGeometry.unaryUnion(polys) for polys in self.polygons] isochrone_layer = QgsVectorLayer( "MultiPolygon?crs=epsg:4326&field=id:integer" "&field=min:integer(10)" "&field=max:integer(10)", "isochrone_osrm_{}".format(self.nb_isocr), "memory") data_provider = isochrone_layer.dataProvider() # Add the features to the layer to display : features = [] levels = levels[1:] self.progress.setValue(8.5) for i, poly in enumerate(self.polygons): if not poly: continue ft = QgsFeature() ft.setGeometry(poly) ft.setAttributes( [i, levels[i] - interval_time, levels[i]]) features.append(ft) data_provider.addFeatures(features[::-1]) self.nb_isocr += 1 self.progress.setValue(9.5) # Render the value : renderer = self.prepare_renderer( levels, interval_time, len(self.polygons)) isochrone_layer.setRendererV2(renderer) isochrone_layer.setLayerTransparency(25) self.iface.messageBar().clearWidgets() QgsMapLayerRegistry.instance().addMapLayer(isochrone_layer) self.add_final_pts(pts) self.iface.setActiveLayer(isochrone_layer)
class TestQgsGeometryGeneratorSymbolLayerV2(TestCase): def setUp(self): polys_shp = os.path.join(TEST_DATA_DIR, 'polys.shp') points_shp = os.path.join(TEST_DATA_DIR, 'points.shp') lines_shp = os.path.join(TEST_DATA_DIR, 'lines.shp') self.polys_layer = QgsVectorLayer(polys_shp, 'Polygons', 'ogr') self.points_layer = QgsVectorLayer(points_shp, 'Points', 'ogr') self.lines_layer = QgsVectorLayer(lines_shp, 'Lines', 'ogr') QgsMapLayerRegistry.instance().addMapLayer(self.polys_layer) QgsMapLayerRegistry.instance().addMapLayer(self.lines_layer) QgsMapLayerRegistry.instance().addMapLayer(self.points_layer) # Create style sym1 = QgsFillSymbolV2.createSimple({'color': '#fdbf6f'}) sym2 = QgsLineSymbolV2.createSimple({'color': '#fdbf6f'}) sym3 = QgsMarkerSymbolV2.createSimple({'color': '#fdbf6f'}) self.polys_layer.setRendererV2(QgsSingleSymbolRendererV2(sym1)) self.lines_layer.setRendererV2(QgsSingleSymbolRendererV2(sym2)) self.points_layer.setRendererV2(QgsSingleSymbolRendererV2(sym3)) self.mapsettings = CANVAS.mapSettings() self.mapsettings.setOutputSize(QSize(400, 400)) self.mapsettings.setOutputDpi(96) self.mapsettings.setExtent(QgsRectangle(-133, 22, -70, 52)) def tearDown(self): QgsMapLayerRegistry.instance().removeAllMapLayers() def test_marker(self): sym = self.polys_layer.rendererV2().symbol() sym_layer = QgsGeometryGeneratorSymbolLayerV2.create({'geometryModifier': 'centroid($geometry)'}) sym_layer.setSymbolType(QgsSymbolV2.Marker) sym.changeSymbolLayer(0, sym_layer) rendered_layers = [self.polys_layer.id()] self.mapsettings.setLayers(rendered_layers) renderchecker = QgsMultiRenderChecker() renderchecker.setMapSettings(self.mapsettings) renderchecker.setControlName('expected_geometrygenerator_marker') self.assertTrue(renderchecker.runTest('geometrygenerator_marker')) def test_mixed(self): sym = self.polys_layer.rendererV2().symbol() buffer_layer = QgsGeometryGeneratorSymbolLayerV2.create({'geometryModifier': 'buffer($geometry, "value"/15)'}) buffer_layer.setSymbolType(QgsSymbolV2.Fill) self.assertIsNotNone(buffer_layer.subSymbol()) sym.appendSymbolLayer(buffer_layer) marker_layer = QgsGeometryGeneratorSymbolLayerV2.create({'geometryModifier': 'centroid($geometry)'}) marker_layer.setSymbolType(QgsSymbolV2.Marker) sym.appendSymbolLayer(marker_layer) rendered_layers = [self.polys_layer.id()] self.mapsettings.setLayers(rendered_layers) renderchecker = QgsMultiRenderChecker() renderchecker.setMapSettings(self.mapsettings) renderchecker.setControlName('expected_geometrygenerator_mixed') self.assertTrue(renderchecker.runTest('geometrygenerator_mixed')) def test_buffer_lines(self): sym = self.lines_layer.rendererV2().symbol() buffer_layer = QgsGeometryGeneratorSymbolLayerV2.create({'geometryModifier': 'buffer($geometry, "value"/15)'}) buffer_layer.setSymbolType(QgsSymbolV2.Fill) self.assertIsNotNone(buffer_layer.subSymbol()) sym.appendSymbolLayer(buffer_layer) rendered_layers = [self.lines_layer.id()] self.mapsettings.setLayers(rendered_layers) renderchecker = QgsMultiRenderChecker() renderchecker.setMapSettings(self.mapsettings) renderchecker.setControlName('expected_geometrygenerator_buffer_lines') self.assertTrue(renderchecker.runTest('geometrygenerator_buffer_lines')) def test_buffer_points(self): sym = self.points_layer.rendererV2().symbol() buffer_layer = QgsGeometryGeneratorSymbolLayerV2.create({'geometryModifier': 'buffer($geometry, "staff"/15)'}) buffer_layer.setSymbolType(QgsSymbolV2.Fill) self.assertIsNotNone(buffer_layer.subSymbol()) sym.appendSymbolLayer(buffer_layer) rendered_layers = [self.points_layer.id()] self.mapsettings.setLayers(rendered_layers) renderchecker = QgsMultiRenderChecker() renderchecker.setMapSettings(self.mapsettings) renderchecker.setControlName('expected_geometrygenerator_buffer_points') self.assertTrue(renderchecker.runTest('geometrygenerator_buffer_points'))
class CartoTools: def __init__(self, iface, dlg): self.iface = iface self.canvas = iface.mapCanvas() self.layerRegistry = QgsMapLayerRegistry.instance() self.dlg = dlg self.messageBar = iface.messageBar() def showNodes(self): """ Parse the geometry of a selected layer and show its vertices (nodes) """ mr = self.layerRegistry # Get the selected layer for which to show nodes selectedIndex = self.dlg.comboLayers.currentIndex() selectedLayer = self.dlg.comboLayers.itemData(selectedIndex) registeredLayers = self.layerRegistry.mapLayersByName('Noeuds') featuresCount = int(selectedLayer.featureCount()) # Remove the node layer if already existing if mr.mapLayersByName('Noeuds'): mr.removeMapLayer(mr.mapLayersByName('Noeuds')[0].id()) # Create memory layer to display nodes self.nodeLayer = QgsVectorLayer("Point?crs=EPSG:2056", "Noeuds", "memory") self.nodeLayerProvider = self.nodeLayer.dataProvider() # Create rendering style nodeSymbol = QgsMarkerSymbolV2.defaultSymbol( self.nodeLayer.geometryType()) nodeSymbol.setColor(QColor('#CC3300')) nodeSymbol.setSize(2.0) nodeRenderer = QgsSingleSymbolRendererV2(nodeSymbol) self.nodeLayer.setRendererV2(nodeRenderer) # Select features visible in current map canvas extent if self.dlg.chkSelectByCanvasExtent.checkState(): extent = self.canvas.extent() rect = QgsRectangle(extent.xMinimum(), extent.yMinimum(), extent.xMaximum(), extent.yMaximum()) request = QgsFeatureRequest() request.setFilterRect(rect) featureIterator = selectedLayer.getFeatures(request) # Select all features else: featureIterator = selectedLayer.getFeatures() # Create progress bar progressMessageBar = self.messageBar.createMessage( unicode("Création des noeuds...", "utf-8")) progress = QProgressBar() progress.setMinimum(0) progress.setMaximum(featuresCount) progress.setAlignment(Qt.AlignLeft | Qt.AlignVCenter) progressMessageBar.layout().addWidget(progress) self.messageBar.pushWidget(progressMessageBar, self.iface.messageBar().INFO) # Iterate over feature k = 0 for feature in featureIterator: k += 1 progress.setValue(k) geom = feature.geometry() feat = QgsFeature() # Adapt procedure for each geometry type if (geom): type = geom.wkbType() # LineString if type == QGis.WKBLineString: for point in geom.asPolyline(): feat.setGeometry(QgsGeometry.fromPoint(point)) self.nodeLayerProvider.addFeatures([feat]) # MultiLineString elif type == QGis.WKBMultiLineString: for line in geom.asMultiPolyline(): for vertex in line: feat.setGeometry( QgsGeometry.fromPoint( QgsPoint(vertex[0], vertex[1]))) self.nodeLayerProvider.addFeatures([feat]) # Polygon elif type == QGis.WKBPolygon: polygons = geom.asPolygon() for polygon in polygons: for vertex in polygon: feat.setGeometry( QgsGeometry.fromPoint( QgsPoint(vertex[0], vertex[1]))) self.nodeLayerProvider.addFeatures([feat]) # MultiPolygon elif type == QGis.WKBMultiPolygon: multiPoly = geom.asMultiPolygon() for polygons in multiPoly: for polygon in polygons: for vertex in polygon: feat.setGeometry( QgsGeometry.fromPoint( QgsPoint(vertex[0], vertex[1]))) self.nodeLayerProvider.addFeatures([feat]) else: self.messageBar.pushMessage( "Cartotools : ", unicode("Type de géométrie non" + "supporté: " + str(type), "utf-8"), level=QgsMessageBar.CRITICAL) self.messageBar.clearWidgets() self.layerRegistry.addMapLayer(self.nodeLayer) def clearNodeLayer(self): if self.layerRegistry.mapLayersByName('Noeuds'): self.layerRegistry.removeMapLayer( self.layerRegistry.mapLayersByName('Noeuds')[0].id())
class OSRM_DialogTSP(QtGui.QDialog, FORM_CLASS_tsp, TemplateOsrm): def __init__(self, iface, parent=None): """ Constructor""" super(OSRM_DialogTSP, self).__init__(parent) self.setupUi(self) self.iface = iface self.pushButton_display.clicked.connect(self.run_tsp) self.pushButton_clear.clicked.connect(self.clear_results) self.comboBox_layer.setFilters(QgsMapLayerProxyModel.PointLayer) self.nb_route = 0 def clear_results(self): """ Clear previous result and set back counter to 0. """ for layer in QgsMapLayerRegistry.instance().mapLayers(): if 'tsp_solution_osrm' in layer: QgsMapLayerRegistry.instance().removeMapLayer(layer) self.nb_route = 0 def run_tsp(self): """ Main method, preparing the query and displaying the result on the canvas. """ layer = self.comboBox_layer.currentLayer() coords, _ = get_coords_ids( layer, '', on_selected=self.checkBox_selec_features.isChecked()) if len(coords) < 2: return -1 try: self.host = check_host(self.lineEdit_host.text()) profile = check_profile_name(self.lineEdit_profileName.text()) except (ValueError, AssertionError) as err: print(err) self.iface.messageBar().pushMessage( "Error", "Please provide a valid non-empty URL and profile name", duration=10) return query = ''.join( ["http://", self.host, "/trip/", profile, "/", ";".join(["{},{}".format(coord[0], coord[1]) for coord in coords])]) try: self.parsed = self.query_url(query) except Exception as err: self.iface.messageBar().pushMessage( "Error", "An error occured when trying to contact the OSRM " "instance (see QGis log for error traceback)", duration=10) QgsMessageLog.logMessage( 'OSRM-plugin error report :\n {}'.format(err), level=QgsMessageLog.WARNING) return try: line_geoms = \ [decode_geom(self.parsed['trips'][i]['geometry']) for i in range(len(self.parsed['trips']))] except KeyError: self.iface.messageBar().pushMessage( "Error", "?...", duration=5) return tsp_route_layer = QgsVectorLayer( "Linestring?crs=epsg:4326&field=id:integer" "&field=total_time:integer(20)&field=distance:integer(20)", "tsp_solution_osrm{}".format(self.nb_route), "memory") my_symb = prepare_route_symbol(self.nb_route) tsp_route_layer.setRendererV2(QgsSingleSymbolRendererV2(my_symb)) features = [] for idx, feature in enumerate(self.parsed['trips']): ft = QgsFeature() ft.setGeometry(line_geoms[idx]) ft.setAttributes([idx, feature['distance'], feature['duration']]) features.append(ft) self.prepare_ordered_marker(coords, idx) tsp_route_layer.dataProvider().addFeatures(features) tsp_route_layer.updateExtents() QgsMapLayerRegistry.instance().addMapLayer(tsp_route_layer) self.iface.setActiveLayer(tsp_route_layer) self.iface.zoomToActiveLayer() put_on_top(self.tsp_marker_lr.id(), tsp_route_layer.id()) self.nb_route += 1 # if self.checkBox_instructions.isChecked(): # pr_instruct, instruct_layer = self.prep_instruction() # QgsMapLayerRegistry.instance().addMapLayer(instruct_layer) # self.iface.setActiveLayer(instruct_layer) def prepare_ordered_marker(self, coords, idx): """ Try to display nice marker on a point layer, showing the order of the path computed by OSRM. """ self.tsp_marker_lr = QgsVectorLayer( "Point?crs=epsg:4326&field=id:integer" "&field=TSP_nb:integer(20)&field=Origin_nb:integer(20)", "tsp_markers_osrm{}".format(self.nb_route), "memory") symbol = QgsSymbolV2.defaultSymbol(self.tsp_marker_lr.geometryType()) symbol.setSize(4.5) symbol.setColor(QtGui.QColor("yellow")) ordered_pts = \ [coords[i["waypoint_index"]] for i in self.parsed['waypoints']] print("ordered_pts : ", ordered_pts) features = [] for nb, pt in enumerate(ordered_pts): ft = QgsFeature() ft.setGeometry(QgsGeometry.fromPoint(QgsPoint(pt))) ft.setAttributes([nb, nb + 1, coords.index(pt)]) features.append(ft) self.tsp_marker_lr.dataProvider().addFeatures(features) pal_lyr = QgsPalLayerSettings() pal_lyr.readFromLayer(self.tsp_marker_lr) pal_lyr.enabled = True pal_lyr.fieldName = 'TSP_nb' pal_lyr.placement= QgsPalLayerSettings.OverPoint pal_lyr.setDataDefinedProperty(QgsPalLayerSettings.Size,True,True,'12','') pal_lyr.writeToLayer(self.tsp_marker_lr) self.tsp_marker_lr.setRendererV2(QgsSingleSymbolRendererV2(symbol)) QgsMapLayerRegistry.instance().addMapLayer(self.tsp_marker_lr)
class RFUDockWidget(QDockWidget, gui_dckwdgt_rfu_connector): closed = pyqtSignal() downloaded = pyqtSignal() uploaded = pyqtSignal() def __init__(self, iface, canvas, map_layer_registry, conn=None, parent=None): super(RFUDockWidget, self).__init__(parent) self.setupUi(self) self.iface = iface self.canvas = canvas self.map_layer_registry = map_layer_registry self.conn = conn self.zone = None self.precision_class = [] self.ellips_acronym = [] self.dflt_ellips_acronym = None self.selected_ellips_acronym = None self.nature = [] self.auth_creator = [] self.url = None self.l_vertex = None self.l_edge = None self.layers = [self.l_vertex, self.l_edge] # Initialize dicts which contains changed datasets self.edges_added = {} self.vertices_added = {} self.edges_removed = {} self.vertices_removed = {} self.edges_modified = {} self.vertices_modified = {} self.downloadPushButton.clicked.connect(self.on_downloaded) self.permalinkLineEdit.returnPressed.connect(self.on_downloaded) self.projComboBox.currentIndexChanged.connect(self.set_destination_crs) def closeEvent(self, event): self.closed.emit() def on_downloaded(self): widget = self.iface.messageBar().createMessage( u"Géofoncier", u"Téléchargement du RFU.") progress_bar = QProgressBar() progress_bar.setMinimum(0) progress_bar.setMaximum(2) widget.layout().addWidget(progress_bar) self.iface.messageBar().pushWidget(widget, QgsMessageBar.WARNING) progress_bar.setValue(1) # https://pro.geofoncier.fr/index.php?¢re=-196406,5983255&context=metropole url = self.permalinkLineEdit.text() if not url: return self.abort_action(msg=u"Veuillez renseigner le permalien.") self.url = url try: self.download(self.url) except Exception as e: return self.abort_action(msg=e.message) progress_bar.setValue(2) self.iface.messageBar().clearWidgets() return def on_reset(self): # Ensure that the action is intentional msg = (u"Cette action est irreversible. " u"Toute modification sera perdue. " u"Êtes-vous sûr de vouloir réinitialiser l'outil ?") resp = QMessageBox.question(self, r"Question", msg, QMessageBox.Yes, QMessageBox.No) if resp == QMessageBox.Yes: self.reset() return def on_uploaded(self): self.uploaded.emit() # Create message widget = self.iface.messageBar().createMessage( u"Géofoncier", u"Envoi des modifications.") progress_bar = QProgressBar() progress_bar.setMinimum(0) progress_bar.setMaximum(3) widget.layout().addWidget(progress_bar) self.iface.messageBar().pushWidget(widget, QgsMessageBar.WARNING) progress_bar.setValue(1) enr_ref_dossier, ok = QInputDialog.getText( self, u"Référence de dossier", u"Vous êtes sur le point de soumettre\n" u"les modifications au serveur Géofoncier.\n" u"Veuillez renseigner la référence du dossier.") if not ok: return self.abort_action() if not enr_ref_dossier: return self.abort_action( msg=u"Merci de renseigner une référence de dossier.") commentaire = u"Dossier %s" % enr_ref_dossier dossiers = self.conn.dossiersoge_dossiers(self.zone, enr_ref_dossier) if dossiers.code != 200: return self.abort_action(msg=dossiers.read()) tree = EltTree.fromstring(dossiers.read()) # Check if exception err = tree.find(r"./erreur") if err: return self.abort_action(msg=err.text) nb_dossiers = int(tree.find(r"./dossiers").attrib[r"total"]) if nb_dossiers == 0: return self.abort_action(msg=u"Le dossier \'%s\' n'existe pas." % enr_ref_dossier) if nb_dossiers >= 1: # Prendre par défaut le dernier dossier dans la liste dossier_uri = tree.getiterator( tag=r"dossier")[nb_dossiers - 1].find(r"{http://www.w3.org/2005/Atom}link") enr_api_dossier = dossier_uri.attrib[r"href"].split(r"/")[-1][1:] progress_bar.setValue(2) # Stop editing mode for layer in self.layers: if layer.isEditable(): layer.commitChanges() # Check if dataset changes if (self.edges_added or self.vertices_added or self.edges_removed or self.vertices_removed or self.edges_modified or self.vertices_modified): pass else: return self.abort_action( msg=u"Aucune modification des données n'est détecté.") # Upload, reset and re-download datasets try: log = self.upload(enr_api_dossier=enr_api_dossier, commentaire=commentaire) self.reset() self.download(self.url) except Exception as e: return self.abort_action(msg=e.message) self.canvas.zoomToFullExtent() self.iface.messageBar().clearWidgets() return QMessageBox.information(self, r"Information", u"\r".join(log)) def download(self, url): # Test if permalink is valid pattern = r"^(https?:\/\/(\w+[\w\-\.\:\/])+)\?((\&+)?(\w+)\=?([\w\-\.\:\,]+?)?)+(\&+)?$" if not re.match(pattern, self.url): raise Exception(u"Le permalien n'est pas valide.") # Extract params from url params = parse_qs(urlparse(self.url).query) # Check mandatory parameters try: context = str(params[r"context"][0]) center = params[r"centre"][0] except: raise Exception( u"Les paramètres \'Context\' et \'Centre\' sont obligatoires.") auth_contexts = [ r"metropole", r"guadeloupe", r"stmartin", r"stbarthelemy", r"guyane", r"reunion", r"mayotte" ] # Check if context is valid if context not in auth_contexts: raise Exception( u"La valeur \'%s\' est incorrecte.\n\n" u"\'Context\' doit prentre une des %s valeurs suivantes: " u"%s" % (context, len(auth_contexts), ", ".join(auth_contexts))) self.zone = context if self.zone in [r"guadeloupe", r"stmartin", r"stbarthelemy"]: self.zone = r"antilles" # Check if XY are valid if not re.match(r"^\-?\d+,\-?\d+$", center): raise Exception(u"Les coordonnées XY du centre sont incorrectes.") # Extract XY (¢re) xcenter = int(center.split(r",")[0]) ycenter = int(center.split(r",")[1]) # Compute the bbox xmin = xcenter - self.conn.extract_lim / 2 xmax = xcenter + self.conn.extract_lim / 2 ymin = ycenter - self.conn.extract_lim / 2 ymax = ycenter + self.conn.extract_lim / 2 # Transform coordinates in WGS84 bbox = tools.reproj(QgsRectangle(xmin, ymin, xmax, ymax), 3857, 4326) # Extract RFU (Send the request) resp = self.conn.extraction(bbox.xMinimum(), bbox.yMinimum(), bbox.xMaximum(), bbox.yMaximum()) if resp.code != 200: raise Exception(resp.read()) tree = EltTree.fromstring(resp.read()) # Check if error err = tree.find(r"./erreur") if err: raise Exception(err.text) # Create the layer: "Masque d'extraction" self.l_bbox = QgsVectorLayer(r"Polygon?crs=epsg:4326&index=yes", u"Zone de travail", r"memory") p_bbox = self.l_bbox.dataProvider() simple_symbol = QgsFillSymbolV2.createSimple({ r"color": r"116,97,87,255", r"style": r"b_diagonal", r"outline_style": r"no" }) renderer_bbox = QgsInvertedPolygonRenderer( QgsSingleSymbolRendererV2(simple_symbol)) self.l_bbox.setRendererV2(renderer_bbox) ft_bbox = QgsFeature() ft_bbox.setGeometry( QgsGeometry.fromRect( QgsRectangle(bbox.xMinimum(), bbox.yMinimum(), bbox.xMaximum(), bbox.yMaximum()))) p_bbox.addFeatures([ft_bbox]) self.l_bbox.updateFields() self.l_bbox.updateExtents() # Create layers.. self.layers = self.extract_layers(tree) self.l_vertex = self.layers[0] self.l_edge = self.layers[1] # Add layer to the registry self.map_layer_registry.addMapLayers( [self.l_vertex, self.l_edge, self.l_bbox]) # Set the map canvas layer set self.canvas.setLayerSet([ QgsMapCanvasLayer(self.l_vertex), QgsMapCanvasLayer(self.l_edge), QgsMapCanvasLayer(self.l_bbox) ]) # Set extent self.canvas.setExtent( QgsRectangle(bbox.xMinimum(), bbox.yMinimum(), bbox.xMaximum(), bbox.yMaximum())) self.features_vertex_backed_up = \ dict((ft[r"fid"], ft) for ft in self.get_features(self.l_vertex)) self.features_edge_backed_up = \ dict((ft[r"fid"], ft) for ft in self.get_features(self.l_edge)) # Get Capabitilies resp = self.conn.get_capabilities(self.zone) if resp.code != 200: raise Exception(resp.read()) tree = EltTree.fromstring(resp.read()) err = tree.find(r"./erreur") if err: raise Exception(err.text) for entry in tree.findall(r"./classe_rattachement/classe"): t = (entry.attrib[r"som_precision_rattachement"], entry.text) self.precision_class.append(t) for entry in tree.findall( r"./representation_plane_sommet_autorise/representation_plane_sommet" ): t = (entry.attrib[r"som_representation_plane"], entry.attrib[r"epsg_crs_id"], entry.text) self.ellips_acronym.append(t) for entry in tree.findall(r"./nature_sommet_conseille/nature"): self.nature.append(entry.text) for entry in tree.findall( r"./som_ge_createur_autorise/som_ge_createur"): t = (entry.attrib[r"num_ge"], entry.text) self.auth_creator.append(t) try: ft = next(ft for ft in self.l_vertex.getFeatures()) ft_attrib = tools.attrib_as_kv(ft.fields(), ft.attributes()) self.dflt_ellips_acronym = ft_attrib[r"som_representation_plane"] except: self.dflt_ellips_acronym = None for i, e in enumerate(self.ellips_acronym): self.projComboBox.addItem(e[2]) if not self.dflt_ellips_acronym: continue if self.dflt_ellips_acronym == e[0]: # Check projection in combobox self.projComboBox.setCurrentIndex(i) # Activate 'On The Fly' self.canvas.setCrsTransformEnabled(True) # Then change the CRS in canvas crs = QgsCoordinateReferenceSystem( int(e[1]), QgsCoordinateReferenceSystem.EpsgCrsId) self.canvas.setDestinationCrs(crs) # Then, start editing mode.. for layer in self.layers: if not layer.isEditable(): layer.startEditing() self.projComboBox.setDisabled(False) self.permalinkLineEdit.setDisabled(True) self.downloadPushButton.setDisabled(True) self.resetPushButton.setDisabled(False) self.uploadPushButton.setDisabled(False) self.downloadPushButton.clicked.disconnect(self.on_downloaded) self.permalinkLineEdit.returnPressed.disconnect(self.on_downloaded) self.resetPushButton.clicked.connect(self.on_reset) self.uploadPushButton.clicked.connect(self.on_uploaded) self.downloaded.emit() return True def reset(self): """Remove RFU layers.""" # Remove RFU layers try: self.map_layer_registry.removeMapLayers( [self.l_vertex.id(), self.l_edge.id(), self.l_bbox.id()]) except: return # Reset variable self.precision_class = [] self.ellips_acronym = [] self.dflt_ellips_acronym = None self.nature = [] self.auth_creator = [] self.l_vertex = None self.l_edge = None self.layers = [self.l_vertex, self.l_edge] self.edges_added = {} self.vertices_added = {} self.edges_removed = {} self.vertices_removed = {} self.edges_modified = {} self.vertices_modified = {} # Reset ComboBox which contains projections authorized self.projComboBox.clear() self.projComboBox.setDisabled(True) self.permalinkLineEdit.clear() self.permalinkLineEdit.setDisabled(False) self.permalinkLineEdit.returnPressed.connect(self.on_downloaded) self.downloadPushButton.setDisabled(False) self.downloadPushButton.clicked.connect(self.on_downloaded) self.resetPushButton.setDisabled(True) self.resetPushButton.clicked.disconnect(self.on_reset) self.uploadPushButton.setDisabled(True) self.uploadPushButton.clicked.disconnect(self.on_uploaded) return True def upload(self, enr_api_dossier=None, commentaire=None): """Upload data to Géofoncier REST API. On success returns the log messages (Array). """ # Set XML document root = EltTree.Element(r"rfu") # Add to our XML document datasets which have been changed if self.vertices_added: for fid in self.vertices_added: tools.xml_subelt_creator(root, u"sommet", data=self.vertices_added[fid], action=r"create") if self.edges_added: for fid in self.edges_added: tools.xml_subelt_creator(root, u"limite", data=self.edges_added[fid], action=r"create") if self.vertices_removed: for fid in self.vertices_removed: tools.xml_subelt_creator(root, u"sommet", data=self.vertices_removed[fid], action=r"delete") if self.edges_removed: for fid in self.edges_removed: tools.xml_subelt_creator(root, u"limite", data=self.edges_removed[fid], action=r"delete") if self.vertices_modified: for fid in self.vertices_modified: tools.xml_subelt_creator(root, u"sommet", data=self.vertices_modified[fid], action=r"update") if self.edges_modified: for fid in self.edges_modified: tools.xml_subelt_creator(root, u"limite", data=self.edges_modified[fid], action=r"update") # Create a new changeset Id changeset_id = self.create_changeset(enr_api_dossier=enr_api_dossier, commentaire=commentaire) # Add changeset value in our XML document root.attrib[r"changeset"] = changeset_id # Send data edit = self.conn.edit(self.zone, EltTree.tostring(root)) if edit.code != 200: raise Exception(edit.read()) tree = EltTree.fromstring(edit.read()) err = tree.find(r"./erreur") if err: raise Exception(err.text) # Returns log info msgs_log = [] for log in tree.iter(r"log"): msgs_log.append(u"%s: %s" % (log.attrib[u"type"], log.text)) # Close the changeset self.destroy_changeset(changeset_id) # Reset all self.edges_added = {} self.vertices_added = {} self.edges_removed = {} self.vertices_removed = {} self.edges_modified = {} self.vertices_modified = {} return msgs_log def create_changeset(self, enr_api_dossier=None, commentaire=None): """Open a new changeset from Géofoncier API. On success, returns the new changeset id. """ opencs = self.conn.open_changeset(self.zone, enr_api_dossier=enr_api_dossier, commentaire=commentaire) if opencs.code != 200: raise Exception(opencs.read()) tree = EltTree.fromstring(opencs.read()) err = tree.find(r"./erreur") if err: raise Exception(err.text) treeterator = tree.getiterator(tag=r"changeset") # We should get only one changeset if len(treeterator) != 1: raise Exception(u"Le nombre de \'changeset\' est incohérent.\n" u"Merci de contacter l'administrateur Géofoncier.") return treeterator[0].attrib[r"id"] def destroy_changeset(self, id): """Close a changeset.""" closecs = self.conn.close_changeset(self.zone, id) if closecs.code != 200: raise Exception(closecs.read()) tree = EltTree.fromstring(closecs.read()) err = tree.find(r"./erreur") if err: raise Exception(err.text) return True def abort_action(self, msg=None): for layer in self.layers: if layer and not layer.isEditable(): layer.startEditing() # Clear message bar self.iface.messageBar().clearWidgets() if msg: return QMessageBox.warning(self, r"Warning", msg) return def extract_layers(self, tree): """Return a list of RFU layers.""" # Create vector layers.. l_vertex = QgsVectorLayer(r"Point?crs=epsg:4326&index=yes", u"Sommet RFU", r"memory") l_edge = QgsVectorLayer(r"LineString?crs=epsg:4326&index=yes", u"Limite RFU", r"memory") p_vertex = l_vertex.dataProvider() p_edge = l_edge.dataProvider() # Define default style renderer.. renderer_vertex = QgsRuleBasedRendererV2(QgsMarkerSymbolV2()) vertex_root_rule = renderer_vertex.rootRule() vertex_rules = ( ((u"Borne, borne à puce, pierre, piquet, clou ou broche"), (u"$id >= 0 AND \"som_nature\" IN ('Borne'," u"'Borne à puce', 'Pierre', 'Piquet', 'Clou ou broche')"), r"#EC0000", 2.2), ((u"Axe cours d'eau, axe fossé, haut de talus, pied de talus"), (u"$id >= 0 AND \"som_nature\" IN ('Axe cours d\'\'eau'," u"'Axe fossé', 'Haut de talus', 'Pied de talus')"), r"#EE8012", 2.2), ((u"Angle de bâtiment, axe de mur, angle de mur, " u"angle de clôture, pylône et toute autre valeur"), (u"$id >= 0 AND \"som_nature\" NOT IN ('Borne'," u"'Borne à puce', 'Pierre', 'Piquet', 'Clou ou broche'," u"'Axe cours d\'\'eau', 'Axe fossé', 'Haut de talus'," u"'Pied de talus')"), r"#9784EC", 2.2), (u"Temporaire", r"$id < 0", "cyan", 2.4)) for label, expression, color, size in vertex_rules: rule = vertex_root_rule.children()[0].clone() rule.setLabel(label) rule.setFilterExpression(expression) rule.symbol().setColor(QColor(color)) rule.symbol().setSize(size) vertex_root_rule.appendChild(rule) vertex_root_rule.removeChildAt(0) l_vertex.setRendererV2(renderer_vertex) renderer_edge = QgsRuleBasedRendererV2(QgsLineSymbolV2()) edge_root_rule = renderer_edge.rootRule() edge_rules = ((r"Limite", r"$id >= 0", "#0A0AFF", 0.5), (r"Temporaire", r"$id < 0", "cyan", 1)) for label, expression, color, width in edge_rules: rule = edge_root_rule.children()[0].clone() rule.setLabel(label) rule.setFilterExpression(expression) rule.symbol().setColor(QColor(color)) rule.symbol().setWidth(width) edge_root_rule.appendChild(rule) edge_root_rule.removeChildAt(0) l_edge.setRendererV2(renderer_edge) # Add fields.. p_vertex.addAttributes([ QgsField(r"@id_noeud", QVariant.Int), # QgsField(r"@changeset", QVariant.Int), # QgsField(r"@timestamp", QVariant.Date), QgsField(r"@version", QVariant.Int), QgsField(r"som_ge_createur", QVariant.String), QgsField(r"som_nature", QVariant.String), QgsField(r"som_precision_rattachement", QVariant.Int), QgsField(r"som_coord_est", QVariant.Double), QgsField(r"som_coord_nord", QVariant.Double), QgsField(r"som_representation_plane", QVariant.String), # QgsField(r"date_creation", QVariant.Date) ]) p_edge.addAttributes([ QgsField(r"@id_arc", QVariant.Int), # QgsField(r"@id_noeud_debut", QVariant.Int), # QgsField(r"@id_noeud_fin", QVariant.Int), # QgsField(r"@changeset", QVariant.Int), # QgsField(r"@timestamp", QVariant.Date), QgsField(r"@version", QVariant.Int), QgsField(r"lim_ge_createur", QVariant.String), # QgsField(r"lim_date_creation", QVariant.Date) ]) # Add features from xml tree.. # ..to vertex layer.. fts_vertex = [] for e in tree.findall(r"sommet"): ft_vertex = QgsFeature() ft_vertex.setGeometry(QgsGeometry.fromWkt(e.attrib[r"geometrie"])) _id_noeud = int(e.attrib[r"id_noeud"]) # _changeset = int(e.attrib[r"changeset"]) # _timestamp = QDateTime(datetime.strptime( # e.attrib[r"timestamp"], r"%Y-%m-%d %H:%M:%S.%f")) _version = int(e.attrib[r"version"]) som_ge_createur = unicode(e.find(r"./som_ge_createur").text) som_nature = unicode(e.find(r"./som_nature").text) som_prec_rattcht = int( e.find(r"./som_precision_rattachement").text) som_coord_est = float(e.find(r"./som_coord_est").text) som_coord_nord = float(e.find(r"./som_coord_nord").text) som_repres_plane = unicode( e.find(r"./som_representation_plane").text) # som_date_creation = QDate(datetime.strptime( # e.find(r"./som_date_creation").text, r"%Y-%m-%d").date()) ft_vertex.setAttributes([ _id_noeud, # _changeset, # _timestamp, _version, som_ge_createur, som_nature, som_prec_rattcht, som_coord_est, som_coord_nord, som_repres_plane, # som_date_creation ]) fts_vertex.append(ft_vertex) # ..to edge layer.. fts_edge = [] for e in tree.findall(r"limite"): ft_edge = QgsFeature() ft_edge.setGeometry(QgsGeometry.fromWkt(e.attrib[r"geometrie"])) _id_arc = int(e.attrib[r"id_arc"]) # _id_noeud_debut = int(e.attrib[r"id_noeud_debut"]) # _id_noeud_fin = int(e.attrib[r"id_noeud_fin"]) # _changeset = int(e.attrib[r"changeset"]) # _timestamp = QDateTime(datetime.strptime( # e.attrib[r"timestamp"], r"%Y-%m-%d %H:%M:%S.%f")) _version = int(e.attrib[r"version"]) lim_ge_createur = unicode(e.find(r"./lim_ge_createur").text) # lim_date_creation = QDate(datetime.strptime( # e.find(r"./lim_date_creation").text, r"%Y-%m-%d").date()) ft_edge.setAttributes([ _id_arc, # _id_noeud_debut, # _id_noeud_fin, # _changeset, # _timestamp, _version, lim_ge_createur, # lim_date_creation ]) fts_edge.append(ft_edge) # Add features to layers.. p_vertex.addFeatures(fts_vertex) p_edge.addFeatures(fts_edge) # Update fields.. l_vertex.updateFields() l_edge.updateFields() # Update layer's extent.. l_vertex.updateExtents() l_edge.updateExtents() # Check if valid.. if not l_vertex.isValid() or not l_edge.isValid(): raise Exception( u"Une erreur est survenue lors du chargement de la couche.") # Set labelling... palyr = QgsPalLayerSettings() palyr.enabled = True # palyr.readFromLayer(l_vertex) palyr.fieldName = r"$id" # Expression $id palyr.placement = 1 # ::OverPoint palyr.quadOffset = 2 # ::QuadrantAboveRight palyr.setDataDefinedProperty(80, True, True, r"1", "") # ::OffsetUnits -> ::MM palyr.xOffset = 2.0 palyr.yOffset = -1.0 palyr.writeToLayer(l_vertex) # Then return layers.. return [l_vertex, l_edge] def get_features(self, layer): features = [] for ft in layer.getFeatures(): attributes = tools.attrib_as_kv(ft.fields(), ft.attributes()) attributes[r"fid"] = ft.id() features.append(attributes) return features def remove_features(self, layer_id, fids): for fid in fids: if layer_id == self.l_edge.id( ) and fid in self.features_edge_backed_up: self.edges_removed[fid] = self.features_edge_backed_up[fid] if layer_id == self.l_vertex.id( ) and fid in self.features_vertex_backed_up: self.vertices_removed[fid] = self.features_vertex_backed_up[ fid] def add_features(self, layer_id, features): for ft in features: attrib = tools.attrib_as_kv(ft.fields(), ft.attributes(), qgsgeom=ft.geometry()) if layer_id == self.l_vertex.id(): self.vertices_added[ft.id()] = attrib if layer_id == self.l_edge.id(): self.edges_added[ft.id()] = attrib def modify_feature(self, layer_id, feature, qgsgeom=None): if qgsgeom: f = tools.attrib_as_kv(feature.fields(), feature.attributes(), qgsgeom=qgsgeom) else: f = tools.attrib_as_kv(feature.fields(), feature.attributes()) if self.l_edge.id() == layer_id: if feature.id() not in self.features_edge_backed_up: return self.edges_modified[feature.id()] = f if self.l_vertex.id() == layer_id: if feature.id() not in self.features_vertex_backed_up: return self.vertices_modified[feature.id()] = f def set_destination_crs(self, j): epsg = 4326 # by default for i, e in enumerate(self.ellips_acronym): if i == j: self.selected_ellips_acronym = e[0] epsg = int(e[1]) continue crs = QgsCoordinateReferenceSystem( epsg, QgsCoordinateReferenceSystem.EpsgCrsId) self.canvas.setDestinationCrs(crs) self.canvas.zoomToFullExtent()
def process_layers(self): download_path = self.dlg.download_path.text() if self.dlg.download_path.text() is None or len(self.dlg.download_path.text()) == 0: QMessageBox.critical(None, self.tr('Error'), self.tr('Please insert the download folder')) elif (int(self.dlg.cbToYear.currentText())) - int(self.dlg.cbFromYear.currentText()) < 0: QMessageBox.critical(None, self.tr('Error'), self.tr('Year selection is not valid')) else: processed_layers = 0 self.dlg.progressBar.setValue(processed_layers) self.dlg.progressText.setText('Fetching Data from the World Bank') indicator_name = self.dlg.cbIndicator.currentText() indicator = self.indicators[indicator_name] from_year = int(self.dlg.cbFromYear.currentText()) to_year = int(self.dlg.cbToYear.currentText()) + 1 total_years = to_year - from_year layers = [] layers_not_available = [] # create tmp layer tmp_layer = QgsVectorLayer("Polygon?crs=EPSG:4326", "tmp", "memory") tmp_data_provider = tmp_layer.dataProvider() # add fields tmp_data_provider.addAttributes([QgsField("value", QVariant.Double)]) data = get_world_bank_data(indicator, str(from_year), str(to_year-1)) # copy layer output_file = copy_layer(download_path, indicator_name) layer = QgsVectorLayer(output_file, "layer_name", "ogr") # create layer by year for index, year in enumerate(range(from_year, to_year)): self.dlg.progressText.setText('Processing ' + str(year)) data_yearly = get_data_by_year(data, year) if len(data_yearly) > 0: added = create_layer(layer, tmp_layer, data_yearly, year, index) layers.append(str(year)) else: layers_not_available.append(str(year)) # update procgress bar processed_layers += 1 self.dlg.progressBar.setValue(int((float(processed_layers) / float(total_years)) * 100)) # commit changed on tmp layer tmp_layer.commitChanges() layer.commitChanges() renderer = create_join_renderer(tmp_layer, 'value', 5, QgsGraduatedSymbolRendererV2.Jenks) if self.dlg.open_in_qgis.isChecked(): for index, year in enumerate(reversed(layers)): l = QgsVectorLayer(output_file, indicator_name + ' (' + str(year) + ')', "ogr") r = renderer.clone() r.setClassAttribute(str(year)) l.setRendererV2(r) QgsMapLayerRegistry.instance().addMapLayer(l) self.iface.legendInterface().setLayerVisible(l, (index == 0)) # for index, year in enumerate(range(from_year, to_year)): # if str(year) not in layers_not_available: # l = QgsVectorLayer(output_file, indicator_name + ' (' + str(year) + ')', "ogr") # r = renderer.clone() # r.setClassAttribute(str(year)) # l.setRendererV2(r) # QgsMapLayerRegistry.instance().addMapLayer(l) # self.iface.legendInterface().setLayerVisible(l, (index == (to_year - from_year-1))) self.iface.mapCanvas().refresh() self.dlg.progressText.setText('Process Finished') if len(layers_not_available) > 0: self.iface.messageBar().pushMessage(indicator_name, 'Data are not available for ' + ', '.join(layers_not_available) + '', level=QgsMessageBar.WARNING)
def process_layers(self): download_path = self.dlg.download_path.text() if self.dlg.download_path.text() is None or len( self.dlg.download_path.text()) == 0: QMessageBox.critical(None, self.tr('Error'), self.tr('Please insert the download folder')) elif (int(self.dlg.cbToYear.currentText())) - int( self.dlg.cbFromYear.currentText()) < 0: QMessageBox.critical(None, self.tr('Error'), self.tr('Year selection is not valid')) else: processed_layers = 0 self.dlg.progressBar.setValue(processed_layers) self.dlg.progressText.setText('Fetching Data from the World Bank') indicator_name = self.dlg.cbIndicator.currentText() indicator = self.indicators[indicator_name] from_year = int(self.dlg.cbFromYear.currentText()) to_year = int(self.dlg.cbToYear.currentText()) + 1 total_years = to_year - from_year layers = [] layers_not_available = [] # create tmp layer tmp_layer = QgsVectorLayer("Polygon?crs=EPSG:4326", "tmp", "memory") tmp_data_provider = tmp_layer.dataProvider() # add fields tmp_data_provider.addAttributes( [QgsField("value", QVariant.Double)]) data = get_world_bank_data(indicator, str(from_year), str(to_year - 1)) # copy layer output_file = copy_layer(download_path, indicator_name) layer = QgsVectorLayer(output_file, "layer_name", "ogr") # create layer by year for index, year in enumerate(range(from_year, to_year)): self.dlg.progressText.setText('Processing ' + str(year)) data_yearly = get_data_by_year(data, year) if len(data_yearly) > 0: added = create_layer(layer, tmp_layer, data_yearly, year, index) layers.append(str(year)) else: layers_not_available.append(str(year)) # update procgress bar processed_layers += 1 self.dlg.progressBar.setValue( int((float(processed_layers) / float(total_years)) * 100)) # commit changed on tmp layer tmp_layer.commitChanges() layer.commitChanges() renderer = create_join_renderer(tmp_layer, 'value', 5, QgsGraduatedSymbolRendererV2.Jenks) if self.dlg.open_in_qgis.isChecked(): for index, year in enumerate(reversed(layers)): l = QgsVectorLayer(output_file, indicator_name + ' (' + str(year) + ')', "ogr") r = renderer.clone() r.setClassAttribute(str(year)) l.setRendererV2(r) QgsMapLayerRegistry.instance().addMapLayer(l) self.iface.legendInterface().setLayerVisible( l, (index == 0)) # for index, year in enumerate(range(from_year, to_year)): # if str(year) not in layers_not_available: # l = QgsVectorLayer(output_file, indicator_name + ' (' + str(year) + ')', "ogr") # r = renderer.clone() # r.setClassAttribute(str(year)) # l.setRendererV2(r) # QgsMapLayerRegistry.instance().addMapLayer(l) # self.iface.legendInterface().setLayerVisible(l, (index == (to_year - from_year-1))) self.iface.mapCanvas().refresh() self.dlg.progressText.setText('Process Finished') if len(layers_not_available) > 0: self.iface.messageBar().pushMessage( indicator_name, 'Data are not available for ' + ', '.join(layers_not_available) + '', level=QgsMessageBar.WARNING)
def run(self): """Run method that performs all the real work""" #~path = 'C:/Users/Sudhanshu/Downloads/Hivre_Bajar' #~ path = 'C:/Users/Rahul/Desktop/Gondala1' #~ path = 'C:/Users/Rahul/Desktop/BW_new' path = '' debugging = path != '' if debugging: zones_layer = self.iface.addVectorLayer(path + '/Zones.shp', 'Zones', 'ogr') soil_layer = self.iface.addVectorLayer(path + '/Soil.shp', 'Soil Cover', 'ogr') lulc_layer = self.iface.addVectorLayer(path + '/LULC.shp', 'Land-Use-Land-Cover', 'ogr') cadastral_layer = self.iface.addVectorLayer( path + '/Cadastral.shp', 'Cadastral Map', 'ogr') slope_layer = self.iface.addRasterLayer(path + '/Slope.tif', 'Slope') #~ drainage_layer = self.iface.addRasterLayer(path + '/Drainage.shp', 'Drainage', 'ogr') rainfall_csv = path + '/Rainfall.csv' sowing_threshold = 30 crop = 'soyabean' interval_points = [50, 100] monsoon_end_date_index = MONSOON_END_DATE_INDEX else: self.dlg.show() if self.dlg.exec_() == QFileDialog.Rejected: return path = self.dlg.folder_path.text() zones_layer = self.iface.addVectorLayer( self.dlg.zones_layer_filename.text(), 'Zones', 'ogr') soil_layer = self.iface.addVectorLayer( self.dlg.soil_layer_filename.text(), 'Soil Cover', 'ogr') lulc_layer = self.iface.addVectorLayer( self.dlg.lulc_layer_filename.text(), 'Land-Use-Land-Cover', 'ogr') cadastral_layer = self.iface.addVectorLayer( self.dlg.cadastral_layer_filename.text(), 'Cadastral Map', 'ogr') slope_layer = self.iface.addRasterLayer( self.dlg.slope_layer_filename.text(), 'Slope') if self.dlg.drainage_layer_filename.text() != '': drainage_layer = self.iface.addRasterLayer( self.dlg.drainage_layer_filename.text(), 'Drainage', 'ogr') rainfall_csv = self.dlg.rainfall_csv_filename.text() sowing_threshold = self.dlg.sowing_threshold.value() monsoon_end_date_index = self.dlg.monsoon_end.value() + 123 crop = self.dlg.crop_combo_box.currentText() interval_points = [ int( self.dlg.colour_code_intervals_list_widget.item( i).text().split('-')[0]) for i in range( 1, self.dlg.colour_code_intervals_list_widget.count()) ] #~ print path, zones_layer, soil_layer, lulc_layer, cadastral_layer, slope_layer, drainage_layer, rainfall_csv #~ start_qdate = self.dlg.from_date_edit.date() #~ date_with_index_0 = QDate(start_qdate.year(), 6, 1).dayOfYear() #~ start_date_index = start_qdate.dayOfYear() - date_with_index_0 #~ end_qdate = self.dlg.to_date_edit.date() #~ end_date_index = end_qdate.dayOfYear() - date_with_index_0 pointwise_output_csv_filename = '/kharif_model_pointwise_output.csv' zonewise_budget_csv_filename = '/kharif_model_zonewise_budget.csv' zonewise_budget_csv_filename_LU = '/kharif_model_zonewise_LU_budget.csv' zonewise_budget_areawise_csv_filename = '/kharif_model_zonewise_budget_area.csv' cadastral_vulnerability_csv_filename = '/kharif_model_cadastral_vulnerability.csv' model_calculator = KharifModelCalculator(path, zones_layer, soil_layer, lulc_layer, cadastral_layer, slope_layer, rainfall_csv) model_calculator.calculate(crop, pointwise_output_csv_filename, zonewise_budget_csv_filename, zonewise_budget_csv_filename_LU, zonewise_budget_areawise_csv_filename, cadastral_vulnerability_csv_filename, sowing_threshold, monsoon_end_date_index) uri = 'file:///' + path + pointwise_output_csv_filename + '?delimiter=%s&crs=epsg:32643&xField=%s&yField=%s' % ( ',', 'X', 'Y') kharif_model_output_layer = QgsVectorLayer(uri, 'Kharif Model Output', 'delimitedtext') graduated_symbol_renderer_range_list = [] ET_D_max = max([ point.budget.PET_minus_AET_crop_end for point in model_calculator.output_grid_points ]) opacity = 1 intervals_count = self.dlg.colour_code_intervals_list_widget.count() for i in range(intervals_count): percent_interval_start_text, percent_interval_end_text = self.dlg.colour_code_intervals_list_widget.item( i).text().split('-') interval_min = 0 if percent_interval_start_text == '0' else ( int(percent_interval_start_text) * ET_D_max / 100.0 + 0.01) interval_max = (int(percent_interval_end_text) * ET_D_max / 100.0) label = "{0:.2f} - {1:.2f}".format(interval_min, interval_max) colour = QColor( int(255 * (1 - (i + 1.0) / (intervals_count + 1.0))), 0, 0) # +1 done to tackle boundary cases symbol = QgsSymbolV2.defaultSymbol( kharif_model_output_layer.geometryType()) symbol.setColor(colour) symbol.setAlpha(opacity) interval_range = QgsRendererRangeV2(interval_min, interval_max, symbol, label) graduated_symbol_renderer_range_list.append(interval_range) renderer = QgsGraduatedSymbolRendererV2( '', graduated_symbol_renderer_range_list) renderer.setMode(QgsGraduatedSymbolRendererV2.EqualInterval) renderer.setClassAttribute('Crop duration PET-AET') kharif_model_output_layer.setRendererV2(renderer) QgsMapLayerRegistry.instance().addMapLayer(kharif_model_output_layer) QgsVectorFileWriter.writeAsVectorFormat( kharif_model_output_layer, path + '/kharif_et_deficit.shp', "utf-8", None, "ESRI Shapefile") #Dislpaying for long kharif crops if (crop in long_kharif_crops): kharif_model_monsoon_end_output_layer = QgsVectorLayer( uri, 'Kharif Model Monsoon End Output', 'delimitedtext') graduated_symbol_renderer_range_list = [] ET_D_max = max([ point.budget.PET_minus_AET_monsoon_end for point in model_calculator.output_grid_points ]) opacity = 1 intervals_count = self.dlg.colour_code_intervals_list_widget.count( ) geometry_type = kharif_model_monsoon_end_output_layer.geometryType( ) for i in range(intervals_count): percent_interval_start_text, percent_interval_end_text = self.dlg.colour_code_intervals_list_widget.item( i).text().split('-') interval_min = 0 if percent_interval_start_text == '0' else ( int(percent_interval_start_text) * ET_D_max / 100.0 + 0.01) interval_max = (int(percent_interval_end_text) * ET_D_max / 100.0) label = "{0:.2f} - {1:.2f}".format(interval_min, interval_max) colour = QColor( int(255 * (1 - (i + 1.0) / (intervals_count + 1.0))), 0, 0) # +1 done to tackle boundary cases symbol = QgsSymbolV2.defaultSymbol(geometry_type) symbol.setColor(colour) symbol.setAlpha(opacity) interval_range = QgsRendererRangeV2(interval_min, interval_max, symbol, label) graduated_symbol_renderer_range_list.append(interval_range) renderer = QgsGraduatedSymbolRendererV2( '', graduated_symbol_renderer_range_list) renderer.setMode(QgsGraduatedSymbolRendererV2.EqualInterval) renderer.setClassAttribute('Monsoon PET-AET') kharif_model_monsoon_end_output_layer.setRendererV2(renderer) QgsMapLayerRegistry.instance().addMapLayer( kharif_model_monsoon_end_output_layer) QgsVectorFileWriter.writeAsVectorFormat( kharif_model_monsoon_end_output_layer, path + '/kharif_post_monsoon_et_deficit.shp', "utf-8", None, "ESRI Shapefile") self.iface.actionHideAllLayers().trigger() self.iface.legendInterface().setLayerVisible(zones_layer, True) if 'drainage_layer' in locals(): self.iface.legendInterface().setLayerVisible(drainage_layer, True) if (crop in long_kharif_crops): self.iface.legendInterface().setLayerVisible( kharif_model_monsoon_end_output_layer, True) self.iface.legendInterface().setLayerVisible(kharif_model_output_layer, True) self.iface.mapCanvas().setExtent(zones_layer.extent()) self.iface.mapCanvas().mapRenderer().setDestinationCrs( zones_layer.crs()) self.iface.mapCanvas().refresh() if self.dlg.save_image_group_box.isChecked(): QTimer.singleShot( 1000, lambda: self.iface.mapCanvas().saveAsImage( self.dlg.save_image_filename.text()))
def download_data(self): # Get user selection group_code = self.cbGroups.itemData(self.cbGroups.currentIndex()) domain_code = self.cbDomains.itemData(self.cbDomains.currentIndex()) element_code = self.cbElements.itemData(self.cbElements.currentIndex()) item_code = self.cbItems.itemData(self.cbItems.currentIndex()) download_folder = self.download_folder.text() # Check selection if group_code is None: self.bar.pushMessage(None, self.tr('Please select a group'), level=QgsMessageBar.CRITICAL) elif domain_code is None: self.bar.pushMessage(None, self.tr('Please select a domain'), level=QgsMessageBar.CRITICAL) elif element_code is None: self.bar.pushMessage(None, self.tr('Please select an element'), level=QgsMessageBar.CRITICAL) elif item_code is None: self.bar.pushMessage(None, self.tr('Please select an item'), level=QgsMessageBar.CRITICAL) elif download_folder is None or len(download_folder) == 0: self.bar.pushMessage(None, self.tr('Please select a download folder'), level=QgsMessageBar.CRITICAL) else: # Get data data = get_data(domain_code, element_code, item_code) # Notify the user self.bar.pushMessage(None, self.tr('Downloaded rows: ') + str(len(data)), level=QgsMessageBar.INFO) # Layer name layer_name = self.cbItems.currentText().replace(' ', '_') + '_' + self.cbElements.currentText().replace(' ', '_') folder_name = os.path.join(download_folder, group_code, domain_code) if not os.path.exists(folder_name): os.makedirs(folder_name) # Copy template layer output_file = copy_layer(folder_name, layer_name) layer = QgsVectorLayer(output_file, 'layer_name', 'ogr') # Add all the years to the layer feature_idx = 64 year_to_be_shown = 2014 number_of_nulls = 0 for year in range(2014, 1960, -1): progress = (1 + (feature_idx - 64)) * 1.86 self.progress.setValue(progress) self.progress_label.setText('<b>' + self.tr('Progress') + ': ' + '</b> ' + self.tr('Adding Year ') + str(year)) year_data = self.get_year_data(data, year) layer.dataProvider().addAttributes([QgsField(str(year), QVariant.Double)]) if len(year_data) > 0: layer.startEditing() for feature in layer.getFeatures(): if feature['FAOSTAT'] is not None: feature_code = str(feature['FAOSTAT']) for d in year_data: data_code = str(d['code']) if data_code == feature_code: value = d['value'] layer.changeAttributeValue(feature.id(), (feature_idx), float(value)) tmp_feature = QgsFeature() tmp_feature.setAttributes([float(value)]) layer.dataProvider().addFeatures([tmp_feature]) if value is None: number_of_nulls += 1 layer.commitChanges() else: year_to_be_shown -= 1 feature_idx += 1 # Add layer to canvas if self.add_to_canvas.isChecked(): renderer = self.create_join_renderer(layer, str(year_to_be_shown), 11, QgsGraduatedSymbolRendererV2.Pretty) l = QgsVectorLayer(output_file, layer_name + '(' + str(year_to_be_shown) + ')', 'ogr') r = renderer.clone() r.setClassAttribute(str(year_to_be_shown)) l.setRendererV2(r) QgsMapLayerRegistry.instance().addMapLayer(l) self.iface.legendInterface().setLayerVisible(l, True) # Close pop-up self.dlg.close()
class OSRM_DialogTSP(QtGui.QDialog, FORM_CLASS_tsp, TemplateOsrm): def __init__(self, iface, parent=None): """ Constructor""" super(OSRM_DialogTSP, self).__init__(parent) self.setupUi(self) self.iface = iface self.pushButton_display.clicked.connect(self.run_tsp) self.pushButton_clear.clicked.connect(self.clear_results) self.comboBox_layer.setFilters(QgsMapLayerProxyModel.PointLayer) self.nb_route = 0 def clear_results(self): """ Clear previous result and set back counter to 0. """ for layer in QgsMapLayerRegistry.instance().mapLayers(): if 'tsp_solution_osrm' in layer: QgsMapLayerRegistry.instance().removeMapLayer(layer) self.nb_route = 0 def run_tsp(self): """ Main method, preparing the query and displaying the result on the canvas. """ layer = self.comboBox_layer.currentLayer() coords, _ = get_coords_ids( layer, '', on_selected=self.checkBox_selec_features.isChecked()) if len(coords) < 2: return -1 try: self.host = check_host(self.lineEdit_host.text()) profile = check_profile_name(self.lineEdit_profileName.text()) except (ValueError, AssertionError) as err: print(err) self.iface.messageBar().pushMessage( "Error", "Please provide a valid non-empty URL and profile name", duration=10) return query = ''.join([ "http://", self.host, "/trip/", profile, "/", ";".join(["{},{}".format(c[0], c[1]) for c in coords]) ]) try: self.parsed = self.query_url(query) except Exception as err: self.iface.messageBar().pushMessage( "Error", "An error occured when trying to contact the OSRM " "instance (see QGis log for error traceback)", duration=10) QgsMessageLog.logMessage( 'OSRM-plugin error report :\n {}'.format(err), level=QgsMessageLog.WARNING) return try: line_geoms = \ [decode_geom(self.parsed['trips'][i]['geometry']) for i in range(len(self.parsed['trips']))] except KeyError: self.iface.messageBar().pushMessage("Error", "?...", duration=5) return tsp_route_layer = QgsVectorLayer( "Linestring?crs=epsg:4326&field=id:integer" "&field=total_time:integer(20)&field=distance:integer(20)", "tsp_solution_osrm{}".format(self.nb_route), "memory") my_symb = prepare_route_symbol(self.nb_route) tsp_route_layer.setRendererV2(QgsSingleSymbolRendererV2(my_symb)) features = [] for idx, feature in enumerate(self.parsed['trips']): ft = QgsFeature() ft.setGeometry(line_geoms[idx]) ft.setAttributes([idx, feature['distance'], feature['duration']]) features.append(ft) self.prepare_ordered_marker(coords, idx) tsp_route_layer.dataProvider().addFeatures(features) tsp_route_layer.updateExtents() QgsMapLayerRegistry.instance().addMapLayer(tsp_route_layer) self.iface.setActiveLayer(tsp_route_layer) self.iface.zoomToActiveLayer() put_on_top(self.tsp_marker_lr.id(), tsp_route_layer.id()) self.nb_route += 1 # if self.checkBox_instructions.isChecked(): # pr_instruct, instruct_layer = self.prep_instruction() # QgsMapLayerRegistry.instance().addMapLayer(instruct_layer) # self.iface.setActiveLayer(instruct_layer) def prepare_ordered_marker(self, coords, idx): """ Try to display nice marker on a point layer, showing the order of the path computed by OSRM. """ self.tsp_marker_lr = QgsVectorLayer( "Point?crs=epsg:4326&field=id:integer" "&field=TSP_nb:integer(20)&field=Origin_nb:integer(20)", "tsp_markers_osrm{}".format(self.nb_route), "memory") symbol = QgsSymbolV2.defaultSymbol(self.tsp_marker_lr.geometryType()) symbol.setSize(4.5) symbol.setColor(QtGui.QColor("yellow")) ordered_pts = \ [coords[i["waypoint_index"]] for i in self.parsed['waypoints']] print("ordered_pts : ", ordered_pts) features = [] for nb, pt in enumerate(ordered_pts): ft = QgsFeature() ft.setGeometry(QgsGeometry.fromPoint(QgsPoint(pt))) ft.setAttributes([nb, nb + 1, coords.index(pt)]) features.append(ft) self.tsp_marker_lr.dataProvider().addFeatures(features) pal_lyr = QgsPalLayerSettings() pal_lyr.readFromLayer(self.tsp_marker_lr) pal_lyr.enabled = True pal_lyr.fieldName = 'TSP_nb' pal_lyr.placement = QgsPalLayerSettings.OverPoint pal_lyr.setDataDefinedProperty(QgsPalLayerSettings.Size, True, True, '12', '') pal_lyr.writeToLayer(self.tsp_marker_lr) self.tsp_marker_lr.setRendererV2(QgsSingleSymbolRendererV2(symbol)) QgsMapLayerRegistry.instance().addMapLayer(self.tsp_marker_lr)
def testCase(self): self.TEST_DATA_DIR = unitTestDataPath() tmppath = tempfile.mkdtemp() for file in glob.glob( os.path.join(self.TEST_DATA_DIR, 'france_parts.*')): shutil.copy(os.path.join(self.TEST_DATA_DIR, file), tmppath) vectorFileInfo = QFileInfo(tmppath + "/france_parts.shp") mVectorLayer = QgsVectorLayer(vectorFileInfo.filePath(), vectorFileInfo.completeBaseName(), "ogr") QgsMapLayerRegistry.instance().addMapLayers([mVectorLayer]) # create composition with composer map self.mapSettings = QgsMapSettings() layerStringList = [] layerStringList.append(mVectorLayer.id()) self.mapSettings.setLayers(layerStringList) self.mapSettings.setCrsTransformEnabled(True) self.mapSettings.setMapUnits(QGis.Meters) # select epsg:2154 crs = QgsCoordinateReferenceSystem() crs.createFromSrid(2154) self.mapSettings.setDestinationCrs(crs) self.mComposition = QgsComposition(self.mapSettings) self.mComposition.setPaperSize(297, 210) # fix the renderer, fill with green props = {"color": "0,127,0"} fillSymbol = QgsFillSymbolV2.createSimple(props) renderer = QgsSingleSymbolRendererV2(fillSymbol) mVectorLayer.setRendererV2(renderer) # the atlas map self.mAtlasMap = QgsComposerMap(self.mComposition, 20, 20, 130, 130) self.mAtlasMap.setFrameEnabled(True) self.mComposition.addComposerMap(self.mAtlasMap) # the atlas self.mAtlas = self.mComposition.atlasComposition() self.mAtlas.setCoverageLayer(mVectorLayer) self.mAtlas.setEnabled(True) self.mComposition.setAtlasMode(QgsComposition.ExportAtlas) # an overview mOverview = QgsComposerMap(self.mComposition, 180, 20, 50, 50) mOverview.setFrameEnabled(True) mOverview.setOverviewFrameMap(self.mAtlasMap.id()) self.mComposition.addComposerMap(mOverview) nextent = QgsRectangle(49670.718, 6415139.086, 699672.519, 7065140.887) mOverview.setNewExtent(nextent) # set the fill symbol of the overview map props2 = {"color": "127,0,0,127"} fillSymbol2 = QgsFillSymbolV2.createSimple(props2) mOverview.setOverviewFrameMapSymbol(fillSymbol2) # header label self.mLabel1 = QgsComposerLabel(self.mComposition) self.mComposition.addComposerLabel(self.mLabel1) self.mLabel1.setText("[% \"NAME_1\" %] area") self.mLabel1.setFont(QgsFontUtils.getStandardTestFont()) self.mLabel1.adjustSizeToText() self.mLabel1.setSceneRect(QRectF(150, 5, 60, 15)) qWarning( "header label font: %s exactMatch:%s" % (self.mLabel1.font().toString(), self.mLabel1.font().exactMatch())) # feature number label self.mLabel2 = QgsComposerLabel(self.mComposition) self.mComposition.addComposerLabel(self.mLabel2) self.mLabel2.setText("# [%$feature || ' / ' || $numfeatures%]") self.mLabel2.setFont(QgsFontUtils.getStandardTestFont()) self.mLabel2.adjustSizeToText() self.mLabel2.setSceneRect(QRectF(150, 200, 60, 15)) qWarning( "feature number label font: %s exactMatch:%s" % (self.mLabel2.font().toString(), self.mLabel2.font().exactMatch())) self.filename_test() self.autoscale_render_test() self.autoscale_render_test_old_api() self.fixedscale_render_test() self.predefinedscales_render_test() self.hidden_render_test() self.legend_test() shutil.rmtree(tmppath, True)
def get_route(self): """ Main method to prepare the request and display the result on the QGIS canvas. """ try: self.host = check_host(self.lineEdit_host.text()) profile = check_profile_name(self.lineEdit_profileName.text()) except (ValueError, AssertionError) as err: print(err) self.iface.messageBar().pushMessage( "Error", "Please provide a valid non-empty URL and profile name", duration=10) return origin = self.lineEdit_xyO.text() interm = self.lineEdit_xyI.text() destination = self.lineEdit_xyD.text() try: assert match('^[^a-zA-Z]+$', origin) \ and 46 > len(origin) > 4 assert match('^[^a-zA-Z]+$', destination) \ and 46 > len(destination) > 4 xo, yo = eval(origin) xd, yd = eval(destination) except: self.iface.messageBar().pushMessage( "Error", "Invalid coordinates !", duration=10) return -1 if interm: try: assert match('^[^a-zA-Z]+$', interm) \ and 150 > len(interm) > 4 interm = eval(''.join(['[', interm, ']'])) tmp = ';'.join( ['{},{}'.format(xi, yi) for xi, yi in interm]) url = ''.join(["http://", self.host, "/route/", profile, "/", "{},{};".format(xo, yo), tmp, ";{},{}".format(xd, yd), "?overview=full&steps={}&alternatives={}".format( str(self.checkBox_instruction.isChecked()).lower(), str(self.checkBox_alternative.isChecked()).lower())]) except: self.iface.messageBar().pushMessage( "Error", "Invalid intemediates coordinates", duration=10) else: url = ''.join([ "http://", self.host, "/route/", profile, "/", "polyline(", encode_to_polyline([(yo, xo), (yd, xd)]), ")", # "{},{};{},{}".format(xo, yo, xd, yd), "?overview=full&steps={}&alternatives={}" .format(str(self.checkBox_instruction.isChecked()).lower(), str(self.checkBox_alternative.isChecked()).lower())]) try: self.parsed = self.query_url(url) assert "code" in self.parsed except Exception as err: self.display_error(err, 1) return if not 'Ok' in self.parsed['code']: self.display_error(self.parsed['code'], 1) return try: enc_line = self.parsed['routes'][0]["geometry"] line_geom = decode_geom(enc_line) except KeyError: self.iface.messageBar().pushMessage( "Error", "No route found between {} and {}".format(origin, destination), duration=5) return self.nb_route += 1 osrm_route_layer = QgsVectorLayer( "Linestring?crs=epsg:4326&field=id:integer" "&field=total_time:integer(20)&field=distance:integer(20)", "route_osrm{}".format(self.nb_route), "memory") my_symb = prepare_route_symbol(self.nb_route) osrm_route_layer.setRendererV2(QgsSingleSymbolRendererV2(my_symb)) provider = osrm_route_layer.dataProvider() fet = QgsFeature() fet.setGeometry(line_geom) fet.setAttributes([0, self.parsed['routes'][0]['duration'], self.parsed['routes'][0]['distance']]) provider.addFeatures([fet]) OD_layer = self.make_OD_markers(self.nb_route, xo, yo, xd, yd, interm) QgsMapLayerRegistry.instance().addMapLayer(OD_layer) osrm_route_layer.updateExtents() QgsMapLayerRegistry.instance().addMapLayer(osrm_route_layer) self.iface.setActiveLayer(osrm_route_layer) self.iface.zoomToActiveLayer() put_on_top(OD_layer.id(), osrm_route_layer.id()) # if self.checkBox_instruction.isChecked(): # pr_instruct, instruct_layer = self.prep_instruction() # QgsMapLayerRegistry.instance().addMapLayer(instruct_layer) # self.iface.setActiveLayer(instruct_layer) if self.checkBox_alternative.isChecked() \ and 'alternative_geometries' in self.parsed: self.nb_alternative = len(self.parsed['routes'] - 1) self.get_alternatives(provider) # if self.dlg.checkBox_instruction.isChecked(): # for i in range(self.nb_alternative): # pr_instruct, instruct_layer = \ # self.prep_instruction( # i + 1, pr_instruct, instruct_layer) return
class TestQgsArrowSymbolLayer(unittest.TestCase): def setUp(self): self.iface = get_iface() lines_shp = os.path.join(TEST_DATA_DIR, 'lines.shp') self.lines_layer = QgsVectorLayer(lines_shp, 'Lines', 'ogr') QgsMapLayerRegistry.instance().addMapLayer(self.lines_layer) # Create style sym2 = QgsLineSymbolV2.createSimple({'color': '#fdbf6f'}) self.lines_layer.setRendererV2(QgsSingleSymbolRendererV2(sym2)) self.mapsettings = self.iface.mapCanvas().mapSettings() self.mapsettings.setOutputSize(QSize(400, 400)) self.mapsettings.setOutputDpi(96) self.mapsettings.setExtent(QgsRectangle(-113, 28, -91, 40)) self.mapsettings.setBackgroundColor(QColor("white")) def tearDown(self): QgsMapLayerRegistry.instance().removeAllMapLayers() def test_1(self): sym = self.lines_layer.rendererV2().symbol() sym_layer = QgsArrowSymbolLayer.create({ 'head_length': '6.5', 'head_thickness': '6.5' }) dd = QgsDataDefined("(@geometry_point_num % 4) * 2") sym_layer.setDataDefinedProperty("arrow_width", dd) dd2 = QgsDataDefined("(@geometry_point_num % 4) * 2") sym_layer.setDataDefinedProperty("head_length", dd2) dd3 = QgsDataDefined("(@geometry_point_num % 4) * 2") sym_layer.setDataDefinedProperty("head_thickness", dd3) fill_sym = QgsFillSymbolV2.createSimple({ 'color': '#8bcfff', 'outline_color': '#000000', 'outline_style': 'solid', 'outline_width': '1' }) sym_layer.setSubSymbol(fill_sym) sym.changeSymbolLayer(0, sym_layer) rendered_layers = [self.lines_layer.id()] self.mapsettings.setLayers(rendered_layers) renderchecker = QgsMultiRenderChecker() renderchecker.setMapSettings(self.mapsettings) renderchecker.setControlName('expected_arrowsymbollayer_1') self.assertTrue(renderchecker.runTest('arrowsymbollayer_1')) def test_2(self): sym = self.lines_layer.rendererV2().symbol() # double headed sym_layer = QgsArrowSymbolLayer.create({ 'arrow_width': '5', 'head_length': '4', 'head_thickness': '6', 'head_type': '2' }) fill_sym = QgsFillSymbolV2.createSimple({ 'color': '#8bcfff', 'outline_color': '#000000', 'outline_style': 'solid', 'outline_width': '1' }) sym_layer.setSubSymbol(fill_sym) sym.changeSymbolLayer(0, sym_layer) rendered_layers = [self.lines_layer.id()] self.mapsettings.setLayers(rendered_layers) renderchecker = QgsMultiRenderChecker() renderchecker.setMapSettings(self.mapsettings) renderchecker.setControlName('expected_arrowsymbollayer_2') self.assertTrue(renderchecker.runTest('arrowsymbollayer_2')) def test_3(self): sym = self.lines_layer.rendererV2().symbol() # double headed sym_layer = QgsArrowSymbolLayer.create({ 'arrow_width': '7', 'head_length': '6', 'head_thickness': '8', 'head_type': '0', 'arrow_type': '1', 'is_curved': '0' }) fill_sym = QgsFillSymbolV2.createSimple({ 'color': '#8bcfff', 'outline_color': '#000000', 'outline_style': 'solid', 'outline_width': '1' }) sym_layer.setSubSymbol(fill_sym) sym.changeSymbolLayer(0, sym_layer) rendered_layers = [self.lines_layer.id()] self.mapsettings.setLayers(rendered_layers) renderchecker = QgsMultiRenderChecker() ms = self.mapsettings ms.setExtent(QgsRectangle(-101, 35, -99, 37)) renderchecker.setMapSettings(ms) renderchecker.setControlName('expected_arrowsymbollayer_3') self.assertTrue(renderchecker.runTest('arrowsymbollayer_3')) def test_unrepeated(self): sym = self.lines_layer.rendererV2().symbol() # double headed sym_layer = QgsArrowSymbolLayer.create({ 'arrow_width': '7', 'head_length': '6', 'head_thickness': '8', 'head_type': '0', 'arrow_type': '0' }) # no repetition sym_layer.setIsRepeated(False) fill_sym = QgsFillSymbolV2.createSimple({ 'color': '#8bcfff', 'outline_color': '#000000', 'outline_style': 'solid', 'outline_width': '1' }) sym_layer.setSubSymbol(fill_sym) sym.changeSymbolLayer(0, sym_layer) rendered_layers = [self.lines_layer.id()] self.mapsettings.setLayers(rendered_layers) renderchecker = QgsMultiRenderChecker() ms = self.mapsettings ms.setExtent(QgsRectangle(-119, 17, -82, 50)) renderchecker.setMapSettings(ms) renderchecker.setControlName('expected_arrowsymbollayer_4') self.assertTrue(renderchecker.runTest('arrowsymbollayer_4')) def testColors(self): """ Test colors, need to make sure colors are passed/retrieved from subsymbol """ sym_layer = QgsArrowSymbolLayer.create() sym_layer.setColor(QColor(150, 50, 100)) self.assertEqual(sym_layer.color(), QColor(150, 50, 100)) self.assertEqual(sym_layer.subSymbol().color(), QColor(150, 50, 100)) sym_layer.subSymbol().setColor(QColor(250, 150, 200)) self.assertEqual(sym_layer.subSymbol().color(), QColor(250, 150, 200)) self.assertEqual(sym_layer.color(), QColor(250, 150, 200))
def get_route(self): """ Main method to prepare the request and display the result on the QGIS canvas. """ try: self.host = check_host(self.lineEdit_host.text()) profile = check_profile_name(self.lineEdit_profileName.text()) except (ValueError, AssertionError) as err: print(err) self.iface.messageBar().pushMessage( "Error", "Please provide a valid non-empty URL and profile name", duration=10) return origin = self.lineEdit_xyO.text() interm = self.lineEdit_xyI.text() destination = self.lineEdit_xyD.text() try: assert match('^[^a-zA-Z]+$', origin) \ and 46 > len(origin) > 4 assert match('^[^a-zA-Z]+$', destination) \ and 46 > len(destination) > 4 xo, yo = eval(origin) xd, yd = eval(destination) except: self.iface.messageBar().pushMessage("Error", "Invalid coordinates !", duration=10) return -1 if interm: try: assert match('^[^a-zA-Z]+$', interm) \ and 150 > len(interm) > 4 interm = eval(''.join(['[', interm, ']'])) tmp = ';'.join(['{},{}'.format(xi, yi) for xi, yi in interm]) url = ''.join([ "http://", self.host, "/route/", profile, "/", "{},{};".format(xo, yo), tmp, ";{},{}".format(xd, yd), "?overview=full&alternatives={}".format( str(self.checkBox_alternative.isChecked()).lower()) ]) except: self.iface.messageBar().pushMessage( "Error", "Invalid intemediates coordinates", duration=10) else: url = ''.join([ "http://", self.host, "/route/", profile, "/", "polyline(", encode_to_polyline([(yo, xo), (yd, xd)]), ")", "?overview=full&alternatives={}".format( str(self.checkBox_alternative.isChecked()).lower()) ]) try: self.parsed = self.query_url(url) assert "code" in self.parsed except Exception as err: self.display_error(err, 1) return if 'Ok' not in self.parsed['code']: self.display_error(self.parsed['code'], 1) return try: enc_line = self.parsed['routes'][0]["geometry"] line_geom = decode_geom(enc_line) except KeyError: self.iface.messageBar().pushMessage( "Error", "No route found between {} and {}".format(origin, destination), duration=5) return self.nb_route += 1 osrm_route_layer = QgsVectorLayer( "Linestring?crs=epsg:4326&field=id:integer" "&field=total_time:integer(20)&field=distance:integer(20)", "route_osrm{}".format(self.nb_route), "memory") my_symb = prepare_route_symbol(self.nb_route) osrm_route_layer.setRendererV2(QgsSingleSymbolRendererV2(my_symb)) provider = osrm_route_layer.dataProvider() fet = QgsFeature() fet.setGeometry(line_geom) fet.setAttributes([ 0, self.parsed['routes'][0]['duration'], self.parsed['routes'][0]['distance'] ]) provider.addFeatures([fet]) OD_layer = self.make_OD_markers(self.nb_route, xo, yo, xd, yd, interm) QgsMapLayerRegistry.instance().addMapLayer(OD_layer) osrm_route_layer.updateExtents() QgsMapLayerRegistry.instance().addMapLayer(osrm_route_layer) self.iface.setActiveLayer(osrm_route_layer) self.iface.zoomToActiveLayer() put_on_top(OD_layer.id(), osrm_route_layer.id()) # if self.checkBox_instruction.isChecked(): # pr_instruct, instruct_layer = self.prep_instruction() # QgsMapLayerRegistry.instance().addMapLayer(instruct_layer) # self.iface.setActiveLayer(instruct_layer) if self.checkBox_alternative.isChecked() \ and 'alternative_geometries' in self.parsed: self.nb_alternative = len(self.parsed['routes'] - 1) self.get_alternatives(provider) # if self.dlg.checkBox_instruction.isChecked(): # for i in range(self.nb_alternative): # pr_instruct, instruct_layer = \ # self.prep_instruction( # i + 1, pr_instruct, instruct_layer) return
def add_source_layers(self, sources): """ :param list sources: a list of nrmllib Source Models (e.g. SimpleFaultSource) """ source_type = collections.namedtuple( 'SourceType', 'layer_type transform color') geometries = { 'PointSource': source_type( 'Point', lambda x: x.geometry.wkt, "255,255,255,185"), 'AreaSource': source_type( 'Polygon', lambda x: x.geometry.wkt, '0,255,255,185'), 'SimpleFaultSource': source_type( 'Polygon', lambda x: simple_surface_from_source(x).wkt, '0,50,255,185'), 'ComplexFaultSource': source_type( 'MultiPolygon', lambda _: NotImplementedError, '50,50,50,185')} source_dict = collections.defaultdict(list) for s in sources: source_dict[s.__class__.__name__].append(s) for stype, sources in source_dict.items(): layer = QgsVectorLayer( '%s?crs=epsg:4326' % ( geometries[stype].layer_type), stype, 'memory') QgsMapLayerRegistry.instance().addMapLayer(layer) pr = layer.dataProvider() layer.startEditing() fields = [QgsField("source_id", QVariant.String)] pr.addAttributes(fields) qgs_fields = QgsFields() for field in fields: qgs_fields.append(field) features = [] for src in sources: fet = QgsFeature() fet.setFields(qgs_fields) fet['source_id'] = src.id if stype == 'SimpleFaultSource': self.sources[src.id] = _nrml_to_hazardlib(src, 1.) fet.setGeometry(QgsGeometry.fromWkt( geometries[stype].transform(src))) features.append(fet) pr.addFeatures(features) layer.commitChanges() layer.updateExtents() symbol = QgsFillSymbolV2.createSimple( {'style': 'diagonal_x', 'color': geometries[stype].color, 'style_border': 'solid'}) layer.setRendererV2(QgsSingleSymbolRendererV2(symbol)) self.source_layers[stype] = layer self.reset_map()
def run_tsp(self): """ Main method, preparing the query and displaying the result on the canvas. """ layer = self.comboBox_layer.currentLayer() coords, _ = get_coords_ids( layer, '', on_selected=self.checkBox_selec_features.isChecked()) if len(coords) < 2: return -1 try: self.host = check_host(self.lineEdit_host.text()) profile = check_profile_name(self.lineEdit_profileName.text()) except (ValueError, AssertionError) as err: print(err) self.iface.messageBar().pushMessage( "Error", "Please provide a valid non-empty URL and profile name", duration=10) return query = ''.join( ["http://", self.host, "/trip/", profile, "/", ";".join(["{},{}".format(coord[0], coord[1]) for coord in coords])]) try: self.parsed = self.query_url(query) except Exception as err: self.iface.messageBar().pushMessage( "Error", "An error occured when trying to contact the OSRM " "instance (see QGis log for error traceback)", duration=10) QgsMessageLog.logMessage( 'OSRM-plugin error report :\n {}'.format(err), level=QgsMessageLog.WARNING) return try: line_geoms = \ [decode_geom(self.parsed['trips'][i]['geometry']) for i in range(len(self.parsed['trips']))] except KeyError: self.iface.messageBar().pushMessage( "Error", "?...", duration=5) return tsp_route_layer = QgsVectorLayer( "Linestring?crs=epsg:4326&field=id:integer" "&field=total_time:integer(20)&field=distance:integer(20)", "tsp_solution_osrm{}".format(self.nb_route), "memory") my_symb = prepare_route_symbol(self.nb_route) tsp_route_layer.setRendererV2(QgsSingleSymbolRendererV2(my_symb)) features = [] for idx, feature in enumerate(self.parsed['trips']): ft = QgsFeature() ft.setGeometry(line_geoms[idx]) ft.setAttributes([idx, feature['distance'], feature['duration']]) features.append(ft) self.prepare_ordered_marker(coords, idx) tsp_route_layer.dataProvider().addFeatures(features) tsp_route_layer.updateExtents() QgsMapLayerRegistry.instance().addMapLayer(tsp_route_layer) self.iface.setActiveLayer(tsp_route_layer) self.iface.zoomToActiveLayer() put_on_top(self.tsp_marker_lr.id(), tsp_route_layer.id()) self.nb_route += 1
class LoadOutputAsLayerDialog(QDialog, FORM_CLASS): """ Modal dialog to load an oq-engine output as layer """ def __init__(self, iface, viewer_dock, session, hostname, calc_id, output_type=None, path=None, mode=None, zonal_layer_path=None, engine_version=None): # sanity check if output_type not in OQ_TO_LAYER_TYPES: raise NotImplementedError(output_type) self.iface = iface self.viewer_dock = viewer_dock self.path = path self.session = session self.hostname = hostname self.calc_id = calc_id self.output_type = output_type self.mode = mode # if 'testing' it will avoid some user interaction self.zonal_layer_path = zonal_layer_path self.engine_version = engine_version QDialog.__init__(self) # Set up the user interface from Designer. self.setupUi(self) # Disable ok_button until all user options are set self.ok_button = self.buttonBox.button(QDialogButtonBox.Ok) self.ok_button.setDisabled(True) def create_file_hlayout(self): self.file_hlayout = QHBoxLayout() self.file_lbl = QLabel('File to load') self.file_browser_tbn = QToolButton() self.file_browser_tbn.setText('...') self.file_browser_tbn.clicked.connect(self.on_file_browser_tbn_clicked) self.path_le = QLineEdit() self.path_le.setEnabled(False) self.file_hlayout.addWidget(self.file_lbl) self.file_hlayout.addWidget(self.file_browser_tbn) self.file_hlayout.addWidget(self.path_le) self.vlayout.addLayout(self.file_hlayout) def create_num_sites_indicator(self): self.num_sites_msg = 'Number of sites: %s' self.num_sites_lbl = QLabel(self.num_sites_msg % '') self.vlayout.addWidget(self.num_sites_lbl) def create_file_size_indicator(self): self.file_size_msg = 'File size: %s' self.file_size_lbl = QLabel(self.file_size_msg % '') self.vlayout.addWidget(self.file_size_lbl) def create_rlz_or_stat_selector(self, label='Realization'): self.rlz_or_stat_lbl = QLabel(label) self.rlz_or_stat_cbx = QComboBox() self.rlz_or_stat_cbx.setEnabled(False) self.rlz_or_stat_cbx.currentIndexChanged['QString'].connect( self.on_rlz_or_stat_changed) self.vlayout.addWidget(self.rlz_or_stat_lbl) self.vlayout.addWidget(self.rlz_or_stat_cbx) def create_imt_selector(self): self.imt_lbl = QLabel('Intensity Measure Type') self.imt_cbx = QComboBox() self.imt_cbx.setEnabled(False) self.imt_cbx.currentIndexChanged['QString'].connect( self.on_imt_changed) self.vlayout.addWidget(self.imt_lbl) self.vlayout.addWidget(self.imt_cbx) def create_poe_selector(self): self.poe_lbl = QLabel('Probability of Exceedance') self.poe_cbx = QComboBox() self.poe_cbx.setEnabled(False) self.poe_cbx.currentIndexChanged['QString'].connect( self.on_poe_changed) self.vlayout.addWidget(self.poe_lbl) self.vlayout.addWidget(self.poe_cbx) def create_loss_type_selector(self): self.loss_type_lbl = QLabel('Loss Type') self.loss_type_cbx = QComboBox() self.loss_type_cbx.setEnabled(False) self.loss_type_cbx.currentIndexChanged['QString'].connect( self.on_loss_type_changed) self.vlayout.addWidget(self.loss_type_lbl) self.vlayout.addWidget(self.loss_type_cbx) def create_eid_selector(self): self.eid_lbl = QLabel('Event ID') self.eid_sbx = QSpinBox() self.eid_sbx.setEnabled(False) self.vlayout.addWidget(self.eid_lbl) self.vlayout.addWidget(self.eid_sbx) def create_dmg_state_selector(self): self.dmg_state_lbl = QLabel('Damage state') self.dmg_state_cbx = QComboBox() self.dmg_state_cbx.setEnabled(False) self.dmg_state_cbx.currentIndexChanged['QString'].connect( self.on_dmg_state_changed) self.vlayout.addWidget(self.dmg_state_lbl) self.vlayout.addWidget(self.dmg_state_cbx) def create_taxonomy_selector(self): self.taxonomy_lbl = QLabel('Taxonomy') self.taxonomy_cbx = QComboBox() self.taxonomy_cbx.setEnabled(False) self.vlayout.addWidget(self.taxonomy_lbl) self.vlayout.addWidget(self.taxonomy_cbx) def create_style_by_selector(self): self.style_by_lbl = QLabel('Style by') self.style_by_cbx = QComboBox() self.vlayout.addWidget(self.style_by_lbl) self.vlayout.addWidget(self.style_by_cbx) def create_load_selected_only_ckb(self): self.load_selected_only_ckb = QCheckBox("Load only the selected items") self.load_selected_only_ckb.setChecked(True) self.vlayout.addWidget(self.load_selected_only_ckb) def create_save_as_shp_ckb(self): self.save_as_shp_ckb = QCheckBox("Save the loaded layer as shapefile") self.save_as_shp_ckb.setChecked(False) self.vlayout.addWidget(self.save_as_shp_ckb) def create_zonal_layer_selector(self): self.zonal_layer_gbx = QGroupBox() self.zonal_layer_gbx.setTitle('Aggregate by zone (optional)') self.zonal_layer_gbx.setCheckable(True) self.zonal_layer_gbx.setChecked(False) self.zonal_layer_gbx_v_layout = QVBoxLayout() self.zonal_layer_gbx.setLayout(self.zonal_layer_gbx_v_layout) self.zonal_layer_cbx = QComboBox() self.zonal_layer_cbx.addItem('') self.zonal_layer_lbl = QLabel('Zonal layer') self.zonal_layer_tbn = QToolButton() self.zonal_layer_tbn.setText('...') self.zonal_layer_h_layout = QHBoxLayout() self.zonal_layer_h_layout.addWidget(self.zonal_layer_cbx) self.zonal_layer_h_layout.addWidget(self.zonal_layer_tbn) self.zonal_layer_gbx_v_layout.addWidget(self.zonal_layer_lbl) self.zonal_layer_gbx_v_layout.addLayout(self.zonal_layer_h_layout) self.zone_id_field_lbl = QLabel('Field containing zone ids') self.zone_id_field_cbx = QComboBox() self.zonal_layer_gbx_v_layout.addWidget(self.zone_id_field_lbl) self.zonal_layer_gbx_v_layout.addWidget(self.zone_id_field_cbx) self.vlayout.addWidget(self.zonal_layer_gbx) self.zonal_layer_tbn.clicked.connect(self.on_zonal_layer_tbn_clicked) self.zonal_layer_cbx.currentIndexChanged[int].connect( self.on_zonal_layer_cbx_currentIndexChanged) self.zonal_layer_gbx.toggled[bool].connect( self.on_zonal_layer_gbx_toggled) def pre_populate_zonal_layer_cbx(self): for key, layer in \ QgsMapLayerRegistry.instance().mapLayers().iteritems(): # populate loss cbx only with layers containing points if layer.type() != QgsMapLayer.VectorLayer: continue if layer.geometryType() == QGis.Polygon: self.zonal_layer_cbx.addItem(layer.name()) self.zonal_layer_cbx.setItemData( self.zonal_layer_cbx.count() - 1, layer.id()) def on_zonal_layer_cbx_currentIndexChanged(self, new_index): self.zone_id_field_cbx.clear() zonal_layer = None if not self.zonal_layer_cbx.currentText(): if self.zonal_layer_gbx.isChecked(): self.ok_button.setEnabled(False) return zonal_layer_id = self.zonal_layer_cbx.itemData(new_index) zonal_layer = QgsMapLayerRegistry.instance().mapLayer(zonal_layer_id) # if the zonal_layer doesn't have a field containing a unique zone id, # the user can choose to add such unique id self.zone_id_field_cbx.addItem("Add field with unique zone id") for field in zonal_layer.fields(): # for the zone id accept both numeric or textual fields self.zone_id_field_cbx.addItem(field.name()) # by default, set the selection to the first textual field self.set_ok_button() def on_zonal_layer_gbx_toggled(self, on): if on and not self.zonal_layer_cbx.currentText(): self.ok_button.setEnabled(False) else: self.set_ok_button() def on_output_type_changed(self): if self.output_type in OQ_TO_LAYER_TYPES: self.create_load_selected_only_ckb() elif self.output_type in OQ_COMPLEX_CSV_TO_LAYER_TYPES: self.create_save_as_shp_ckb() self.set_ok_button() @pyqtSlot() def on_file_browser_tbn_clicked(self): path = self.open_file_dialog() if path: self.populate_out_dep_widgets() self.set_ok_button() def on_rlz_or_stat_changed(self): self.dataset = self.npz_file[self.rlz_or_stat_cbx.currentText()] self.set_ok_button() def on_loss_type_changed(self): self.set_ok_button() def on_imt_changed(self): self.set_ok_button() def on_poe_changed(self): self.set_ok_button() def on_eid_changed(self): self.set_ok_button() def on_dmg_state_changed(self): self.set_ok_button() def open_file_dialog(self): """ Open a file dialog to select the data file to be loaded """ text = self.tr('Select the OQ-Engine output file to import') if self.output_type in OQ_CSV_TO_LAYER_TYPES: filters = self.tr('CSV files (*.csv)') else: raise NotImplementedError(self.output_type) default_dir = QSettings().value('irmt/load_as_layer_dir', QDir.homePath()) path = QFileDialog.getOpenFileName(self, text, default_dir, filters) if not path: return selected_dir = QFileInfo(path).dir().path() QSettings().setValue('irmt/load_as_layer_dir', selected_dir) self.path = path self.path_le.setText(self.path) return path def populate_out_dep_widgets(self): self.populate_rlz_or_stat_cbx() self.show_num_sites() def get_taxonomies(self): raise NotImplementedError() def populate_rlz_or_stat_cbx(self): self.rlzs_or_stats = [ key for key in sorted(self.npz_file) if key not in ('imtls', 'array') ] self.rlz_or_stat_cbx.clear() self.rlz_or_stat_cbx.setEnabled(True) self.rlz_or_stat_cbx.addItems(self.rlzs_or_stats) def populate_loss_type_cbx(self, loss_types): self.loss_type_cbx.clear() self.loss_type_cbx.setEnabled(True) self.loss_type_cbx.addItems(loss_types) def show_num_sites(self): # NOTE: we are assuming all realizations have the same number of sites, # which currently is always true. # If different realizations have a different number of sites, we # need to move this block of code inside on_rlz_or_stat_changed() rlz_or_stat_data = self.npz_file[self.rlz_or_stat_cbx.currentText()] self.num_sites_lbl.setText(self.num_sites_msg % rlz_or_stat_data.shape) def set_ok_button(self): raise NotImplementedError() def build_layer_name(self, *args, **kwargs): raise NotImplementedError() def get_field_names(self, **kwargs): raise NotImplementedError() def add_field_to_layer(self, field_name): raise NotImplementedError() def read_npz_into_layer(self, field_names, **kwargs): raise NotImplementedError() def load_from_npz(self): raise NotImplementedError() def get_investigation_time(self): if self.output_type in ('hcurves', 'uhs', 'hmaps'): try: investigation_time = self.npz_file['investigation_time'] except KeyError: msg = ('investigation_time not found. It is mandatory for %s.' ' Please check if the ouptut was produced by an' ' obsolete version of the OpenQuake Engine' ' Server.') % self.output_type log_msg(msg, level='C', message_bar=self.iface.messageBar()) else: return investigation_time else: # some outputs do not need the investigation time return None def build_layer(self, rlz_or_stat=None, taxonomy=None, poe=None, loss_type=None, dmg_state=None, gsim=None): layer_name = self.build_layer_name(rlz_or_stat=rlz_or_stat, taxonomy=taxonomy, poe=poe, loss_type=loss_type, dmg_state=dmg_state, gsim=gsim) field_names = self.get_field_names(rlz_or_stat=rlz_or_stat, taxonomy=taxonomy, poe=poe, loss_type=loss_type, dmg_state=dmg_state) # create layer self.layer = QgsVectorLayer("Point?crs=epsg:4326", layer_name, "memory") for field_name in field_names: if field_name in ['lon', 'lat']: continue added_field_name = self.add_field_to_layer(field_name) if field_name != added_field_name: if field_name == self.default_field_name: self.default_field_name = added_field_name # replace field_name with the actual added_field_name field_name_idx = field_names.index(field_name) field_names.remove(field_name) field_names.insert(field_name_idx, added_field_name) self.read_npz_into_layer(field_names, rlz_or_stat=rlz_or_stat, taxonomy=taxonomy, poe=poe, loss_type=loss_type, dmg_state=dmg_state) self.layer.setCustomProperty('output_type', self.output_type) investigation_time = self.get_investigation_time() if investigation_time is not None: self.layer.setCustomProperty('investigation_time', investigation_time) if self.engine_version is not None: self.layer.setCustomProperty('engine_version', self.engine_version) irmt_version = get_irmt_version() self.layer.setCustomProperty('irmt_version', irmt_version) self.layer.setCustomProperty('calc_id', self.calc_id) QgsMapLayerRegistry.instance().addMapLayer(self.layer) self.iface.setActiveLayer(self.layer) self.iface.zoomToActiveLayer() def _set_symbol_size(self, symbol): if self.iface.mapCanvas().mapUnits() == QGis.Degrees: point_size = 0.05 elif self.iface.mapCanvas().mapUnits() == QGis.Meters: point_size = 4000 else: # it is not obvious how to choose the point size in the other # cases, so we conservatively keep the default sizing return symbol.symbolLayer(0).setSizeUnit(symbol.MapUnit) symbol.symbolLayer(0).setSize(point_size) map_unit_scale = QgsMapUnitScale() map_unit_scale.maxSizeMMEnabled = True map_unit_scale.minSizeMMEnabled = True map_unit_scale.minSizeMM = 0.5 map_unit_scale.maxSizeMM = 10 symbol.symbolLayer(0).setSizeMapUnitScale(map_unit_scale) def style_maps(self, layer=None, style_by=None): if layer is None: layer = self.layer if style_by is None: style_by = self.default_field_name symbol = QgsSymbolV2.defaultSymbol(layer.geometryType()) # see properties at: # https://qgis.org/api/qgsmarkersymbollayerv2_8cpp_source.html#l01073 symbol.setAlpha(1) # opacity if isinstance(symbol, QgsMarkerSymbolV2): # do it only for the layer with points self._set_symbol_size(symbol) symbol.symbolLayer(0).setOutlineStyle(Qt.PenStyle(Qt.NoPen)) style = get_style(layer, self.iface.messageBar()) # this is the default, as specified in the user settings ramp = QgsVectorGradientColorRampV2(style['color_from'], style['color_to']) mode = style['mode'] # in most cases, we override the user-specified setting, and use # instead a setting that was required by scientists if self.output_type in OQ_TO_LAYER_TYPES: default_qgs_style = QgsStyleV2().defaultStyle() default_color_ramp_names = default_qgs_style.colorRampNames() if self.output_type in ('dmg_by_asset', 'losses_by_asset', 'avg_losses-stats'): # options are EqualInterval, Quantile, Jenks, StdDev, Pretty # jenks = natural breaks mode = QgsGraduatedSymbolRendererV2.Jenks ramp_type_idx = default_color_ramp_names.index('Reds') inverted = False elif self.output_type in ('hmaps', 'gmf_data', 'ruptures'): # options are EqualInterval, Quantile, Jenks, StdDev, Pretty if self.output_type == 'ruptures': mode = QgsGraduatedSymbolRendererV2.Pretty else: mode = QgsGraduatedSymbolRendererV2.EqualInterval ramp_type_idx = default_color_ramp_names.index('Spectral') inverted = True ramp = default_qgs_style.colorRamp( default_color_ramp_names[ramp_type_idx]) graduated_renderer = QgsGraduatedSymbolRendererV2.createRenderer( layer, style_by, style['classes'], mode, symbol, ramp, inverted=inverted) label_format = graduated_renderer.labelFormat() # label_format.setTrimTrailingZeroes(True) # it might be useful label_format.setPrecision(2) graduated_renderer.setLabelFormat(label_format, updateRanges=True) # add a class for 0 values, unless while styling ruptures if self.output_type != 'ruptures': VERY_SMALL_VALUE = 1e-20 graduated_renderer.updateRangeLowerValue(0, VERY_SMALL_VALUE) symbol_zeros = QgsSymbolV2.defaultSymbol(layer.geometryType()) symbol_zeros.setColor(QColor(240, 240, 240)) # very light grey if isinstance(symbol, QgsMarkerSymbolV2): # do it only for the layer with points self._set_symbol_size(symbol_zeros) symbol_zeros.symbolLayer(0).setOutlineStyle( Qt.PenStyle(Qt.NoPen)) zeros_min = 0.0 zeros_max = VERY_SMALL_VALUE range_zeros = QgsRendererRangeV2( zeros_min, zeros_max, symbol_zeros, " %.2f - %.2f" % (zeros_min, zeros_max), True) graduated_renderer.addClassRange(range_zeros) graduated_renderer.moveClass( len(graduated_renderer.ranges()) - 1, 0) layer.setRendererV2(graduated_renderer) layer.setLayerTransparency(30) # percent layer.triggerRepaint() self.iface.legendInterface().refreshLayerSymbology(layer) self.iface.mapCanvas().refresh() def style_categorized(self, layer, style_by): # get unique values fni = layer.fieldNameIndex(style_by) unique_values = layer.dataProvider().uniqueValues(fni) # define categories categories = [] for unique_value in unique_values: # initialize the default symbol for this geometry type symbol = QgsSymbolV2.defaultSymbol(layer.geometryType()) # configure a symbol layer layer_style = {} layer_style['color'] = '%d, %d, %d' % (randrange( 0, 256), randrange(0, 256), randrange(0, 256)) layer_style['outline'] = '#000000' symbol_layer = QgsSimpleFillSymbolLayerV2.create(layer_style) # replace default symbol layer with the configured one if symbol_layer is not None: symbol.changeSymbolLayer(0, symbol_layer) # create renderer object category = QgsRendererCategoryV2(unique_value, symbol, str(unique_value)) # entry for the list of category items categories.append(category) # create renderer object renderer = QgsCategorizedSymbolRendererV2(style_by, categories) # assign the created renderer to the layer if renderer is not None: layer.setRendererV2(renderer) layer.triggerRepaint() self.iface.legendInterface().refreshLayerSymbology(layer) self.iface.mapCanvas().refresh() def style_curves(self): registry = QgsSymbolLayerV2Registry.instance() cross = registry.symbolLayerMetadata("SimpleMarker").createSymbolLayer( { 'name': 'cross2', 'color': '0,0,0', 'color_border': '0,0,0', 'offset': '0,0', 'size': '1.5', 'angle': '0' }) symbol = QgsSymbolV2.defaultSymbol(self.layer.geometryType()) symbol.deleteSymbolLayer(0) symbol.appendSymbolLayer(cross) self._set_symbol_size(symbol) renderer = QgsSingleSymbolRendererV2(symbol) effect = QgsOuterGlowEffect() effect.setSpread(0.5) effect.setTransparency(0) effect.setColor(QColor(255, 255, 255)) effect.setBlurLevel(1) renderer.paintEffect().appendEffect(effect) renderer.paintEffect().setEnabled(True) self.layer.setRendererV2(renderer) self.layer.setLayerTransparency(30) # percent self.layer.triggerRepaint() self.iface.legendInterface().refreshLayerSymbology(self.layer) self.iface.mapCanvas().refresh() def open_zonal_layer_dialog(self): """ Open a file dialog to select the zonal layer to be loaded :returns: the zonal layer """ text = self.tr('Select zonal layer to import') filters = self.tr('Vector shapefiles (*.shp);;SQLite (*.sqlite);;' 'All files (*.*)') default_dir = QSettings().value('irmt/select_layer_dir', QDir.homePath()) file_name, file_type = QFileDialog.getOpenFileNameAndFilter( self, text, default_dir, filters) if not file_name: return None selected_dir = QFileInfo(file_name).dir().path() QSettings().setValue('irmt/select_layer_dir', selected_dir) zonal_layer_plus_stats = self.load_zonal_layer(file_name) return zonal_layer_plus_stats def load_zonal_layer(self, zonal_layer_path, make_a_copy=False): # Load zonal layer zonal_layer = QgsVectorLayer(zonal_layer_path, tr('Zonal data'), 'ogr') if not zonal_layer.geometryType() == QGis.Polygon: msg = 'Zonal layer must contain zone polygons' log_msg(msg, level='C', message_bar=self.iface.messageBar()) return False if make_a_copy: # Make a copy, where stats will be added zonal_layer_plus_stats = ProcessLayer( zonal_layer).duplicate_in_memory() else: zonal_layer_plus_stats = zonal_layer # Add zonal layer to registry if zonal_layer_plus_stats.isValid(): QgsMapLayerRegistry.instance().addMapLayer(zonal_layer_plus_stats) else: msg = 'Invalid zonal layer' log_msg(msg, level='C', message_bar=self.iface.messageBar()) return None return zonal_layer_plus_stats def on_zonal_layer_tbn_clicked(self): zonal_layer_plus_stats = self.open_zonal_layer_dialog() if (zonal_layer_plus_stats and zonal_layer_plus_stats.geometryType() == QGis.Polygon): self.populate_zonal_layer_cbx(zonal_layer_plus_stats) def populate_zonal_layer_cbx(self, zonal_layer_plus_stats): cbx = self.zonal_layer_cbx cbx.addItem(zonal_layer_plus_stats.name()) last_index = cbx.count() - 1 cbx.setItemData(last_index, zonal_layer_plus_stats.id()) cbx.setCurrentIndex(last_index) def show_file_size(self): file_size = get_file_size(self.path) self.file_size_lbl.setText(self.file_size_msg % file_size) def accept(self): if self.output_type in OQ_EXTRACT_TO_LAYER_TYPES: self.load_from_npz() if self.output_type in ('losses_by_asset', 'dmg_by_asset', 'avg_losses-stats'): # check if also aggregating by zone or not if (not self.zonal_layer_cbx.currentText() or not self.zonal_layer_gbx.isChecked()): super(LoadOutputAsLayerDialog, self).accept() return loss_layer = self.layer self.iface.legendInterface().setLayerVisible(loss_layer, False) zonal_layer_id = self.zonal_layer_cbx.itemData( self.zonal_layer_cbx.currentIndex()) zonal_layer = QgsMapLayerRegistry.instance().mapLayer( zonal_layer_id) # if the two layers have different projections, display an # error message and return have_same_projection, check_projection_msg = ProcessLayer( loss_layer).has_same_projection_as(zonal_layer) if not have_same_projection: log_msg(check_projection_msg, level='C', message_bar=self.iface.messageBar()) # TODO: load only loss layer super(LoadOutputAsLayerDialog, self).accept() return loss_attr_names = [ field.name() for field in loss_layer.fields() ] zone_id_in_losses_attr_name = None # index 0 is for "Add field with unique zone id" if self.zone_id_field_cbx.currentIndex() == 0: zone_id_in_zones_attr_name = None else: zone_id_in_zones_attr_name = \ self.zone_id_field_cbx.currentText() # aggregate losses by zone (calculate count of points in the # zone, sum and average loss values for the same zone) loss_layer_is_vector = True try: res = calculate_zonal_stats(loss_layer, zonal_layer, loss_attr_names, loss_layer_is_vector, zone_id_in_losses_attr_name, zone_id_in_zones_attr_name, self.iface, extra=False) except TypeError as exc: log_msg(str(exc), level='C', message_bar=self.iface.messageBar()) return (loss_layer, zonal_layer, loss_attrs_dict) = res # sanity check assert len(loss_attrs_dict) == 1, ( "Only one attribute should be added to the zonal layer." " %s were added insted" % len(loss_attrs_dict)) # NOTE: in scenario damage, keys are like # u'structural_no_damage_mean', and not just # u'structural', therefore we can't just use the selected # loss type, but we must use the actual only key in the # dict [added_loss_attr] = loss_attrs_dict style_by = loss_attrs_dict[added_loss_attr]['sum'] self.style_maps(layer=zonal_layer, style_by=style_by) elif self.output_type in OQ_CSV_TO_LAYER_TYPES: self.load_from_csv() super(LoadOutputAsLayerDialog, self).accept() def reject(self): if (hasattr(self, 'npz_file') and self.npz_file is not None and self.output_type in OQ_TO_LAYER_TYPES): self.npz_file.close() super(LoadOutputAsLayerDialog, self).reject()
class TestQgsArrowSymbolLayer(unittest.TestCase): def setUp(self): self.iface = get_iface() lines_shp = os.path.join(TEST_DATA_DIR, 'lines.shp') self.lines_layer = QgsVectorLayer(lines_shp, 'Lines', 'ogr') QgsMapLayerRegistry.instance().addMapLayer(self.lines_layer) # Create style sym2 = QgsLineSymbolV2.createSimple({'color': '#fdbf6f'}) self.lines_layer.setRendererV2(QgsSingleSymbolRendererV2(sym2)) self.mapsettings = self.iface.mapCanvas().mapSettings() self.mapsettings.setOutputSize(QSize(400, 400)) self.mapsettings.setOutputDpi(96) self.mapsettings.setExtent(QgsRectangle(-113, 28, -91, 40)) self.mapsettings.setBackgroundColor(QColor("white")) def tearDown(self): QgsMapLayerRegistry.instance().removeAllMapLayers() def test_1(self): sym = self.lines_layer.rendererV2().symbol() sym_layer = QgsArrowSymbolLayer.create({'head_length': '6.5', 'head_thickness': '6.5'}) dd = QgsDataDefined("(@geometry_point_num % 4) * 2") sym_layer.setDataDefinedProperty("arrow_width", dd) dd2 = QgsDataDefined("(@geometry_point_num % 4) * 2") sym_layer.setDataDefinedProperty("head_length", dd2) dd3 = QgsDataDefined("(@geometry_point_num % 4) * 2") sym_layer.setDataDefinedProperty("head_thickness", dd3) fill_sym = QgsFillSymbolV2.createSimple({'color': '#8bcfff', 'outline_color': '#000000', 'outline_style': 'solid', 'outline_width': '1'}) sym_layer.setSubSymbol(fill_sym) sym.changeSymbolLayer(0, sym_layer) rendered_layers = [self.lines_layer.id()] self.mapsettings.setLayers(rendered_layers) renderchecker = QgsMultiRenderChecker() renderchecker.setMapSettings(self.mapsettings) renderchecker.setControlName('expected_arrowsymbollayer_1') self.assertTrue(renderchecker.runTest('arrowsymbollayer_1')) def test_2(self): sym = self.lines_layer.rendererV2().symbol() # double headed sym_layer = QgsArrowSymbolLayer.create({'arrow_width': '5', 'head_length': '4', 'head_thickness': '6', 'head_type': '2'}) fill_sym = QgsFillSymbolV2.createSimple({'color': '#8bcfff', 'outline_color': '#000000', 'outline_style': 'solid', 'outline_width': '1'}) sym_layer.setSubSymbol(fill_sym) sym.changeSymbolLayer(0, sym_layer) rendered_layers = [self.lines_layer.id()] self.mapsettings.setLayers(rendered_layers) renderchecker = QgsMultiRenderChecker() renderchecker.setMapSettings(self.mapsettings) renderchecker.setControlName('expected_arrowsymbollayer_2') self.assertTrue(renderchecker.runTest('arrowsymbollayer_2')) def test_3(self): sym = self.lines_layer.rendererV2().symbol() # double headed sym_layer = QgsArrowSymbolLayer.create({'arrow_width': '7', 'head_length': '6', 'head_thickness': '8', 'head_type': '0', 'arrow_type': '1', 'is_curved': '0'}) fill_sym = QgsFillSymbolV2.createSimple({'color': '#8bcfff', 'outline_color': '#000000', 'outline_style': 'solid', 'outline_width': '1'}) sym_layer.setSubSymbol(fill_sym) sym.changeSymbolLayer(0, sym_layer) rendered_layers = [self.lines_layer.id()] self.mapsettings.setLayers(rendered_layers) renderchecker = QgsMultiRenderChecker() ms = self.mapsettings ms.setExtent(QgsRectangle(-101, 35, -99, 37)) renderchecker.setMapSettings(ms) renderchecker.setControlName('expected_arrowsymbollayer_3') self.assertTrue(renderchecker.runTest('arrowsymbollayer_3')) def test_unrepeated(self): sym = self.lines_layer.rendererV2().symbol() # double headed sym_layer = QgsArrowSymbolLayer.create({'arrow_width': '7', 'head_length': '6', 'head_thickness': '8', 'head_type': '0', 'arrow_type': '0'}) # no repetition sym_layer.setIsRepeated(False) fill_sym = QgsFillSymbolV2.createSimple({'color': '#8bcfff', 'outline_color': '#000000', 'outline_style': 'solid', 'outline_width': '1'}) sym_layer.setSubSymbol(fill_sym) sym.changeSymbolLayer(0, sym_layer) rendered_layers = [self.lines_layer.id()] self.mapsettings.setLayers(rendered_layers) renderchecker = QgsMultiRenderChecker() ms = self.mapsettings ms.setExtent(QgsRectangle(-119, 17, -82, 50)) renderchecker.setMapSettings(ms) renderchecker.setControlName('expected_arrowsymbollayer_4') self.assertTrue(renderchecker.runTest('arrowsymbollayer_4')) def testColors(self): """ Test colors, need to make sure colors are passed/retrieved from subsymbol """ sym_layer = QgsArrowSymbolLayer.create() sym_layer.setColor(QColor(150, 50, 100)) self.assertEqual(sym_layer.color(), QColor(150, 50, 100)) self.assertEqual(sym_layer.subSymbol().color(), QColor(150, 50, 100)) sym_layer.subSymbol().setColor(QColor(250, 150, 200)) self.assertEqual(sym_layer.subSymbol().color(), QColor(250, 150, 200)) self.assertEqual(sym_layer.color(), QColor(250, 150, 200))
def run_tsp(self): """ Main method, preparing the query and displaying the result on the canvas. """ layer = self.comboBox_layer.currentLayer() coords, _ = get_coords_ids( layer, '', on_selected=self.checkBox_selec_features.isChecked()) if len(coords) < 2: return -1 try: self.host = check_host(self.lineEdit_host.text()) profile = check_profile_name(self.lineEdit_profileName.text()) except (ValueError, AssertionError) as err: print(err) self.iface.messageBar().pushMessage( "Error", "Please provide a valid non-empty URL and profile name", duration=10) return query = ''.join([ "http://", self.host, "/trip/", profile, "/", ";".join(["{},{}".format(c[0], c[1]) for c in coords]) ]) try: self.parsed = self.query_url(query) except Exception as err: self.iface.messageBar().pushMessage( "Error", "An error occured when trying to contact the OSRM " "instance (see QGis log for error traceback)", duration=10) QgsMessageLog.logMessage( 'OSRM-plugin error report :\n {}'.format(err), level=QgsMessageLog.WARNING) return try: line_geoms = \ [decode_geom(self.parsed['trips'][i]['geometry']) for i in range(len(self.parsed['trips']))] except KeyError: self.iface.messageBar().pushMessage("Error", "?...", duration=5) return tsp_route_layer = QgsVectorLayer( "Linestring?crs=epsg:4326&field=id:integer" "&field=total_time:integer(20)&field=distance:integer(20)", "tsp_solution_osrm{}".format(self.nb_route), "memory") my_symb = prepare_route_symbol(self.nb_route) tsp_route_layer.setRendererV2(QgsSingleSymbolRendererV2(my_symb)) features = [] for idx, feature in enumerate(self.parsed['trips']): ft = QgsFeature() ft.setGeometry(line_geoms[idx]) ft.setAttributes([idx, feature['distance'], feature['duration']]) features.append(ft) self.prepare_ordered_marker(coords, idx) tsp_route_layer.dataProvider().addFeatures(features) tsp_route_layer.updateExtents() QgsMapLayerRegistry.instance().addMapLayer(tsp_route_layer) self.iface.setActiveLayer(tsp_route_layer) self.iface.zoomToActiveLayer() put_on_top(self.tsp_marker_lr.id(), tsp_route_layer.id()) self.nb_route += 1
def download_data(self): # Get user selection group_code = self.cbGroups.itemData(self.cbGroups.currentIndex()) domain_code = self.cbDomains.itemData(self.cbDomains.currentIndex()) element_code = self.cbElements.itemData(self.cbElements.currentIndex()) item_code = self.cbItems.itemData(self.cbItems.currentIndex()) download_folder = self.download_folder.text() # Check selection if group_code is None: self.bar.pushMessage(None, self.tr('Please select a group'), level=QgsMessageBar.CRITICAL) elif domain_code is None: self.bar.pushMessage(None, self.tr('Please select a domain'), level=QgsMessageBar.CRITICAL) elif element_code is None: self.bar.pushMessage(None, self.tr('Please select an element'), level=QgsMessageBar.CRITICAL) elif item_code is None: self.bar.pushMessage(None, self.tr('Please select an item'), level=QgsMessageBar.CRITICAL) elif download_folder is None or len(download_folder) == 0: self.bar.pushMessage(None, self.tr('Please select a download folder'), level=QgsMessageBar.CRITICAL) else: # Get data data = get_data(domain_code, element_code, item_code) # Notify the user self.bar.pushMessage(None, self.tr('Downloaded rows: ') + str(len(data)), level=QgsMessageBar.INFO) # Layer name layer_name = self.cbItems.currentText().replace( ' ', '_') + '_' + self.cbElements.currentText().replace( ' ', '_') folder_name = os.path.join(download_folder, group_code, domain_code) if not os.path.exists(folder_name): os.makedirs(folder_name) # Copy template layer output_file = copy_layer(folder_name, layer_name) layer = QgsVectorLayer(output_file, 'layer_name', 'ogr') # Add all the years to the layer feature_idx = 64 year_to_be_shown = 2014 number_of_nulls = 0 for year in range(2014, 1960, -1): progress = (1 + (feature_idx - 64)) * 1.86 self.progress.setValue(progress) self.progress_label.setText('<b>' + self.tr('Progress') + ': ' + '</b> ' + self.tr('Adding Year ') + str(year)) year_data = self.get_year_data(data, year) layer.dataProvider().addAttributes( [QgsField(str(year), QVariant.Double)]) if len(year_data) > 0: layer.startEditing() for feature in layer.getFeatures(): if feature['FAOSTAT'] is not None: feature_code = str(feature['FAOSTAT']) for d in year_data: data_code = str(d['code']) if data_code == feature_code: value = d['value'] layer.changeAttributeValue( feature.id(), (feature_idx), float(value)) tmp_feature = QgsFeature() tmp_feature.setAttributes([float(value)]) layer.dataProvider().addFeatures( [tmp_feature]) if value is None: number_of_nulls += 1 layer.commitChanges() else: year_to_be_shown -= 1 feature_idx += 1 # Add layer to canvas if self.add_to_canvas.isChecked(): renderer = self.create_join_renderer( layer, str(year_to_be_shown), 11, QgsGraduatedSymbolRendererV2.Pretty) l = QgsVectorLayer( output_file, layer_name + '(' + str(year_to_be_shown) + ')', 'ogr') r = renderer.clone() r.setClassAttribute(str(year_to_be_shown)) l.setRendererV2(r) QgsMapLayerRegistry.instance().addMapLayer(l) self.iface.legendInterface().setLayerVisible(l, True) # Close pop-up self.dlg.close()
def get_access_isochrones(self): """ Making the accessibility isochrones in few steps: - make a grid of points aroung the origin point, - snap each point (using OSRM locate function) on the road network, - get the time-distance between the origin point and each of these pts (using OSRM table function), - make an interpolation grid to extract polygons corresponding to the desired time intervals (using matplotlib library), - render the polygon. """ try: self.host = check_host(self.lineEdit_host.text()) self.profile = check_profile_name(self.lineEdit_profileName.text()) except (ValueError, AssertionError) as err: self.iface.messageBar().pushMessage( "Error", "Please provide a valid non-empty URL", duration=10) return if 'clicking' in self.comboBox_method.currentText(): pts = self.get_points_from_canvas() elif 'selecting' in self.comboBox_method.currentText(): layer = self.comboBox_pointlayer.currentLayer() pts, ptids = get_coords_ids( layer, 'ID', on_selected=self.checkBox_selectedFt.isChecked( )) #HGP: Using fix ID-column here! pts = tuple(pts) if not pts: return max_time = self.spinBox_max.value() interval_time = self.spinBox_intervall.value() nb_inter = int(round(max_time / interval_time)) + 1 levels = tuple([ nb for nb in xrange(0, int(max_time + 1) + interval_time, interval_time) ][:nb_inter]) self.make_prog_bar() self.max_points = 5000 # 1500 if len(pts) == 1 else 500 self.polygons = [] pts = [{ "point": pt, "max": max_time, "levels": levels, "host": self.host, "profile": self.profile, "max_points": self.max_points } for pt in pts] pool = ThreadPool(processes=4 if len(pts) >= 4 else len(pts)) try: self.polygons = [i for i in pool.map(prep_access, pts)] except Exception as err: self.display_error(err, 1) return if len(self.polygons) == 1: self.polygons = self.polygons[0] else: self.polygons = np.array( self.polygons).transpose().tolist() #HGP: ravel self.polygons = \ [QgsGeometry.unaryUnion(polys) for polys in self.polygons] isochrone_layer = QgsVectorLayer( "MultiPolygon?crs=epsg:4326&field=id:integer" "&field=min:integer(10)" "&field=max:integer(10)" "&field=origid:integer(10)", "isochrone_osrm_{}".format(self.nb_isocr), "memory") data_provider = isochrone_layer.dataProvider() # Add the features to the layer to display : features = [] levels = levels[1:] self.progress.setValue(8.5) for i, poly in enumerate(self.polygons): if not poly: continue ft = QgsFeature() ft.setGeometry(poly) ft.setAttributes( [i, levels[i] - interval_time, levels[i], ptids[i % len(pts)]]) features.append(ft) data_provider.addFeatures(features[::-1]) self.nb_isocr += 1 self.progress.setValue(9.5) # Render the value : renderer = self.prepare_renderer(levels, interval_time, len(self.polygons)) isochrone_layer.setRendererV2(renderer) isochrone_layer.setLayerTransparency(25) self.iface.messageBar().clearWidgets() QgsMapLayerRegistry.instance().addMapLayer(isochrone_layer) self.add_final_pts(pts) self.iface.setActiveLayer(isochrone_layer)
def legend_test(self): self.mAtlasMap.setAtlasDriven(True) self.mAtlasMap.setAtlasScalingMode(QgsComposerMap.Auto) self.mAtlasMap.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.fromPoint(QgsPoint(-0.638, 48.954))) f2 = QgsFeature(2) f2.initAttributes(2) f2.setAttribute(0, 2) f2.setAttribute(1, "Test label 2") f2.setGeometry(QgsGeometry.fromPoint(QgsPoint(-1.682, 48.550))) pr.addFeatures([f1, f2]) # categorized symbology r = QgsCategorizedSymbolRendererV2("attr", [ QgsRendererCategoryV2( 1, QgsMarkerSymbolV2.createSimple({"color": "255,0,0"}), "red"), QgsRendererCategoryV2( 2, QgsMarkerSymbolV2.createSimple({"color": "0,0,255"}), "blue") ]) ptLayer.setRendererV2(r) QgsMapLayerRegistry.instance().addMapLayer(ptLayer) # add the point layer to the map settings layers = self.mapSettings.layers() layers = [ptLayer.id()] + layers self.mapSettings.setLayers(layers) # add a legend legend = QgsComposerLegend(self.mComposition) legend.moveBy(200, 100) # sets the legend filter parameter legend.setComposerMap(self.mAtlasMap) legend.setLegendFilterOutAtlas(True) self.mComposition.addComposerLegend(legend) self.mAtlas.beginRender() self.mAtlas.prepareForFeature(0) self.mLabel1.adjustSizeToText() checker = QgsCompositionChecker('atlas_legend', self.mComposition) myTestResult, myMessage = checker.testComposition() assert myTestResult self.mAtlas.endRender() # restore state self.mapSettings.setLayers([layers[1]]) self.mComposition.removeComposerItem(legend) QgsMapLayerRegistry.instance().removeMapLayer(ptLayer.id())
def extract_layers(self, tree): """Return a list of RFU layers.""" # Create vector layers.. l_vertex = QgsVectorLayer(r"Point?crs=epsg:4326&index=yes", u"Sommet RFU", r"memory") l_edge = QgsVectorLayer(r"LineString?crs=epsg:4326&index=yes", u"Limite RFU", r"memory") p_vertex = l_vertex.dataProvider() p_edge = l_edge.dataProvider() # Define default style renderer.. renderer_vertex = QgsRuleBasedRendererV2(QgsMarkerSymbolV2()) vertex_root_rule = renderer_vertex.rootRule() vertex_rules = ( ( (u"Borne, borne à puce, pierre, piquet, clou ou broche"), (u"$id >= 0 AND \"som_nature\" IN ('Borne'," u"'Borne à puce', 'Pierre', 'Piquet', 'Clou ou broche')"), r"#EC0000", 2.2 ), ( (u"Axe cours d'eau, axe fossé, haut de talus, pied de talus"), (u"$id >= 0 AND \"som_nature\" IN ('Axe cours d\'\'eau'," u"'Axe fossé', 'Haut de talus', 'Pied de talus')"), r"#EE8012", 2.2 ), ( (u"Angle de bâtiment, axe de mur, angle de mur, " u"angle de clôture, pylône et toute autre valeur"), (u"$id >= 0 AND \"som_nature\" NOT IN ('Borne'," u"'Borne à puce', 'Pierre', 'Piquet', 'Clou ou broche'," u"'Axe cours d\'\'eau', 'Axe fossé', 'Haut de talus'," u"'Pied de talus')"), r"#9784EC", 2.2 ), ( u"Temporaire", r"$id < 0", "cyan", 2.4 )) for label, expression, color, size in vertex_rules: rule = vertex_root_rule.children()[0].clone() rule.setLabel(label) rule.setFilterExpression(expression) rule.symbol().setColor(QColor(color)) rule.symbol().setSize(size) vertex_root_rule.appendChild(rule) vertex_root_rule.removeChildAt(0) l_vertex.setRendererV2(renderer_vertex) renderer_edge = QgsRuleBasedRendererV2(QgsLineSymbolV2()) edge_root_rule = renderer_edge.rootRule() edge_rules = ((r"Limite", r"$id >= 0", "#0A0AFF", 0.5), (r"Temporaire", r"$id < 0", "cyan", 1)) for label, expression, color, width in edge_rules: rule = edge_root_rule.children()[0].clone() rule.setLabel(label) rule.setFilterExpression(expression) rule.symbol().setColor(QColor(color)) rule.symbol().setWidth(width) edge_root_rule.appendChild(rule) edge_root_rule.removeChildAt(0) l_edge.setRendererV2(renderer_edge) # Add fields.. p_vertex.addAttributes([ QgsField(r"@id_noeud", QVariant.Int), # QgsField(r"@changeset", QVariant.Int), # QgsField(r"@timestamp", QVariant.Date), QgsField(r"@version", QVariant.Int), QgsField(r"som_ge_createur", QVariant.String), QgsField(r"som_nature", QVariant.String), QgsField(r"som_precision_rattachement", QVariant.Int), QgsField(r"som_coord_est", QVariant.Double), QgsField(r"som_coord_nord", QVariant.Double), QgsField(r"som_representation_plane", QVariant.String), # QgsField(r"date_creation", QVariant.Date) ]) p_edge.addAttributes([ QgsField(r"@id_arc", QVariant.Int), # QgsField(r"@id_noeud_debut", QVariant.Int), # QgsField(r"@id_noeud_fin", QVariant.Int), # QgsField(r"@changeset", QVariant.Int), # QgsField(r"@timestamp", QVariant.Date), QgsField(r"@version", QVariant.Int), QgsField(r"lim_ge_createur", QVariant.String), # QgsField(r"lim_date_creation", QVariant.Date) ]) # Add features from xml tree.. # ..to vertex layer.. fts_vertex = [] for e in tree.findall(r"sommet"): ft_vertex = QgsFeature() ft_vertex.setGeometry(QgsGeometry.fromWkt(e.attrib[r"geometrie"])) _id_noeud = int(e.attrib[r"id_noeud"]) # _changeset = int(e.attrib[r"changeset"]) # _timestamp = QDateTime(datetime.strptime( # e.attrib[r"timestamp"], r"%Y-%m-%d %H:%M:%S.%f")) _version = int(e.attrib[r"version"]) som_ge_createur = unicode(e.find(r"./som_ge_createur").text) som_nature = unicode(e.find(r"./som_nature").text) som_prec_rattcht = int(e.find(r"./som_precision_rattachement").text) som_coord_est = float(e.find(r"./som_coord_est").text) som_coord_nord = float(e.find(r"./som_coord_nord").text) som_repres_plane = unicode(e.find(r"./som_representation_plane").text) # som_date_creation = QDate(datetime.strptime( # e.find(r"./som_date_creation").text, r"%Y-%m-%d").date()) ft_vertex.setAttributes([ _id_noeud, # _changeset, # _timestamp, _version, som_ge_createur, som_nature, som_prec_rattcht, som_coord_est, som_coord_nord, som_repres_plane, # som_date_creation ]) fts_vertex.append(ft_vertex) # ..to edge layer.. fts_edge = [] for e in tree.findall(r"limite"): ft_edge = QgsFeature() ft_edge.setGeometry(QgsGeometry.fromWkt(e.attrib[r"geometrie"])) _id_arc = int(e.attrib[r"id_arc"]) # _id_noeud_debut = int(e.attrib[r"id_noeud_debut"]) # _id_noeud_fin = int(e.attrib[r"id_noeud_fin"]) # _changeset = int(e.attrib[r"changeset"]) # _timestamp = QDateTime(datetime.strptime( # e.attrib[r"timestamp"], r"%Y-%m-%d %H:%M:%S.%f")) _version = int(e.attrib[r"version"]) lim_ge_createur = unicode(e.find(r"./lim_ge_createur").text) # lim_date_creation = QDate(datetime.strptime( # e.find(r"./lim_date_creation").text, r"%Y-%m-%d").date()) ft_edge.setAttributes([ _id_arc, # _id_noeud_debut, # _id_noeud_fin, # _changeset, # _timestamp, _version, lim_ge_createur, # lim_date_creation ]) fts_edge.append(ft_edge) # Add features to layers.. p_vertex.addFeatures(fts_vertex) p_edge.addFeatures(fts_edge) # Update fields.. l_vertex.updateFields() l_edge.updateFields() # Update layer's extent.. l_vertex.updateExtents() l_edge.updateExtents() # Check if valid.. if not l_vertex.isValid() or not l_edge.isValid(): raise Exception(u"Une erreur est survenue lors du chargement de la couche.") # Set labelling... palyr = QgsPalLayerSettings() palyr.enabled = True # palyr.readFromLayer(l_vertex) palyr.fieldName = r"$id" # Expression $id palyr.placement = 1 # ::OverPoint palyr.quadOffset = 2 # ::QuadrantAboveRight palyr.setDataDefinedProperty(80, True, True, r"1", "") # ::OffsetUnits -> ::MM palyr.xOffset = 2.0 palyr.yOffset = -1.0 palyr.writeToLayer(l_vertex) # Then return layers.. return [l_vertex, l_edge]
def compute_and_display_cadastral_vulnerability(self, cadastral_layer, output_grid_points, output_cadastral_points, crop_index, crop_name, base_path): cadastral_points_per_plot = {} for p in (output_grid_points + output_cadastral_points): if p.cadastral_polygon is None: continue if p.lulc_type not in ['agriculture', 'fallow land']: continue if p.cadastral_polygon.id() in cadastral_points_per_plot: cadastral_points_per_plot[p.cadastral_polygon.id()].append( p.budget.PET_minus_AET_crop_end[crop_index]) else: cadastral_points_per_plot[p.cadastral_polygon.id()] = [ p.budget.PET_minus_AET_crop_end[crop_index] ] for k, v in cadastral_points_per_plot.items(): if len(v) > 0: cadastral_points_per_plot[k] = sum(v) / len(v) else: del cadastral_points_per_plot[k] # print cadastral_points_per_plot # Create duplicate cadastral layer in memory memory_cadastral_layer = QgsVectorLayer( 'Polygon?crs=epsg:32643', crop_name + ' Cadastral Level Vulnerability', 'memory') memory_cadastral_layer.startEditing() memory_cadastral_layer.dataProvider().addAttributes( cadastral_layer.qgsLayer.dataProvider().fields().toList()) memory_cadastral_layer.updateFields() dict_new_feature_id_to_old_feature_id = {} for old_plot_id in cadastral_points_per_plot: result, output_features = memory_cadastral_layer.dataProvider( ).addFeatures([cadastral_layer.feature_dict[old_plot_id]]) dict_new_feature_id_to_old_feature_id[ output_features[0].id()] = old_plot_id memory_cadastral_layer.dataProvider().addAttributes( [QgsField('Deficit', QVariant.Double)]) memory_cadastral_layer.updateFields() for new_feature in memory_cadastral_layer.getFeatures(): new_feature['Deficit'] = cadastral_points_per_plot[ dict_new_feature_id_to_old_feature_id[new_feature.id()]] memory_cadastral_layer.updateFeature(new_feature) memory_cadastral_layer.commitChanges() # Graduated Rendering graduated_symbol_renderer_range_list = [] ET_D_max = max(cadastral_points_per_plot.values()) opacity = 1 geometry_type = memory_cadastral_layer.geometryType() intervals_count = CADASTRAL_VULNERABILITY_DISPLAY_COLOUR_INTERVALS_COUNT dict_interval_colour = CADASTRAL_VULNERABILITY_DISPLAY_COLOURS_DICT for i in range(intervals_count): interval_min = 0 if i == 0 else (ET_D_max * float(i) / intervals_count) + 0.01 interval_max = ET_D_max * float(i + 1) / intervals_count label = "{0:.2f} - {1:.2f}".format(interval_min, interval_max) colour = QColor(*dict_interval_colour[i]) symbol = QgsSymbolV2.defaultSymbol(geometry_type) symbol.setColor(colour) symbol.setAlpha(opacity) interval_range = QgsRendererRangeV2(interval_min, interval_max, symbol, label) graduated_symbol_renderer_range_list.append(interval_range) renderer = QgsGraduatedSymbolRendererV2( '', graduated_symbol_renderer_range_list) renderer.setMode(QgsGraduatedSymbolRendererV2.EqualInterval) renderer.setClassAttribute('Deficit') memory_cadastral_layer.setRendererV2(renderer) QgsMapLayerRegistry.instance().addMapLayer(memory_cadastral_layer) memory_cadastral_layer.setCustomProperty('labeling', 'pal') memory_cadastral_layer.setCustomProperty('labeling/enabled', 'true') memory_cadastral_layer.setCustomProperty('labeling/fieldName', 'Number') memory_cadastral_layer.setCustomProperty('labeling/fontSize', '10') memory_cadastral_layer.setCustomProperty('labeling/placement', '0') memory_cadastral_layer.dataProvider().forceReload() memory_cadastral_layer.triggerRepaint() QgsVectorFileWriter.writeAsVectorFormat( memory_cadastral_layer, base_path + '/kharif_' + crop_name + '_cadastral_level_vulnerability.shp', "utf-8", None, "ESRI Shapefile")
def extract_layers(self, tree): """Return a list of RFU layers.""" # Create vector layers.. l_vertex = QgsVectorLayer(r"Point?crs=epsg:4326&index=yes", u"Sommet RFU", r"memory") l_edge = QgsVectorLayer(r"LineString?crs=epsg:4326&index=yes", u"Limite RFU", r"memory") p_vertex = l_vertex.dataProvider() p_edge = l_edge.dataProvider() # Define default style renderer.. renderer_vertex = QgsRuleBasedRendererV2(QgsMarkerSymbolV2()) vertex_root_rule = renderer_vertex.rootRule() vertex_rules = ( ((u"Borne, borne à puce, pierre, piquet, clou ou broche"), (u"$id >= 0 AND \"som_nature\" IN ('Borne'," u"'Borne à puce', 'Pierre', 'Piquet', 'Clou ou broche')"), r"#EC0000", 2.2), ((u"Axe cours d'eau, axe fossé, haut de talus, pied de talus"), (u"$id >= 0 AND \"som_nature\" IN ('Axe cours d\'\'eau'," u"'Axe fossé', 'Haut de talus', 'Pied de talus')"), r"#EE8012", 2.2), ((u"Angle de bâtiment, axe de mur, angle de mur, " u"angle de clôture, pylône et toute autre valeur"), (u"$id >= 0 AND \"som_nature\" NOT IN ('Borne'," u"'Borne à puce', 'Pierre', 'Piquet', 'Clou ou broche'," u"'Axe cours d\'\'eau', 'Axe fossé', 'Haut de talus'," u"'Pied de talus')"), r"#9784EC", 2.2), (u"Temporaire", r"$id < 0", "cyan", 2.4)) for label, expression, color, size in vertex_rules: rule = vertex_root_rule.children()[0].clone() rule.setLabel(label) rule.setFilterExpression(expression) rule.symbol().setColor(QColor(color)) rule.symbol().setSize(size) vertex_root_rule.appendChild(rule) vertex_root_rule.removeChildAt(0) l_vertex.setRendererV2(renderer_vertex) renderer_edge = QgsRuleBasedRendererV2(QgsLineSymbolV2()) edge_root_rule = renderer_edge.rootRule() edge_rules = ((r"Limite", r"$id >= 0", "#0A0AFF", 0.5), (r"Temporaire", r"$id < 0", "cyan", 1)) for label, expression, color, width in edge_rules: rule = edge_root_rule.children()[0].clone() rule.setLabel(label) rule.setFilterExpression(expression) rule.symbol().setColor(QColor(color)) rule.symbol().setWidth(width) edge_root_rule.appendChild(rule) edge_root_rule.removeChildAt(0) l_edge.setRendererV2(renderer_edge) # Add fields.. p_vertex.addAttributes([ QgsField(r"@id_noeud", QVariant.Int), # QgsField(r"@changeset", QVariant.Int), # QgsField(r"@timestamp", QVariant.Date), QgsField(r"@version", QVariant.Int), QgsField(r"som_ge_createur", QVariant.String), QgsField(r"som_nature", QVariant.String), QgsField(r"som_precision_rattachement", QVariant.Int), QgsField(r"som_coord_est", QVariant.Double), QgsField(r"som_coord_nord", QVariant.Double), QgsField(r"som_representation_plane", QVariant.String), # QgsField(r"date_creation", QVariant.Date) ]) p_edge.addAttributes([ QgsField(r"@id_arc", QVariant.Int), # QgsField(r"@id_noeud_debut", QVariant.Int), # QgsField(r"@id_noeud_fin", QVariant.Int), # QgsField(r"@changeset", QVariant.Int), # QgsField(r"@timestamp", QVariant.Date), QgsField(r"@version", QVariant.Int), QgsField(r"lim_ge_createur", QVariant.String), # QgsField(r"lim_date_creation", QVariant.Date) ]) # Add features from xml tree.. # ..to vertex layer.. fts_vertex = [] for e in tree.findall(r"sommet"): ft_vertex = QgsFeature() ft_vertex.setGeometry(QgsGeometry.fromWkt(e.attrib[r"geometrie"])) _id_noeud = int(e.attrib[r"id_noeud"]) # _changeset = int(e.attrib[r"changeset"]) # _timestamp = QDateTime(datetime.strptime( # e.attrib[r"timestamp"], r"%Y-%m-%d %H:%M:%S.%f")) _version = int(e.attrib[r"version"]) som_ge_createur = unicode(e.find(r"./som_ge_createur").text) som_nature = unicode(e.find(r"./som_nature").text) som_prec_rattcht = int( e.find(r"./som_precision_rattachement").text) som_coord_est = float(e.find(r"./som_coord_est").text) som_coord_nord = float(e.find(r"./som_coord_nord").text) som_repres_plane = unicode( e.find(r"./som_representation_plane").text) # som_date_creation = QDate(datetime.strptime( # e.find(r"./som_date_creation").text, r"%Y-%m-%d").date()) ft_vertex.setAttributes([ _id_noeud, # _changeset, # _timestamp, _version, som_ge_createur, som_nature, som_prec_rattcht, som_coord_est, som_coord_nord, som_repres_plane, # som_date_creation ]) fts_vertex.append(ft_vertex) # ..to edge layer.. fts_edge = [] for e in tree.findall(r"limite"): ft_edge = QgsFeature() ft_edge.setGeometry(QgsGeometry.fromWkt(e.attrib[r"geometrie"])) _id_arc = int(e.attrib[r"id_arc"]) # _id_noeud_debut = int(e.attrib[r"id_noeud_debut"]) # _id_noeud_fin = int(e.attrib[r"id_noeud_fin"]) # _changeset = int(e.attrib[r"changeset"]) # _timestamp = QDateTime(datetime.strptime( # e.attrib[r"timestamp"], r"%Y-%m-%d %H:%M:%S.%f")) _version = int(e.attrib[r"version"]) lim_ge_createur = unicode(e.find(r"./lim_ge_createur").text) # lim_date_creation = QDate(datetime.strptime( # e.find(r"./lim_date_creation").text, r"%Y-%m-%d").date()) ft_edge.setAttributes([ _id_arc, # _id_noeud_debut, # _id_noeud_fin, # _changeset, # _timestamp, _version, lim_ge_createur, # lim_date_creation ]) fts_edge.append(ft_edge) # Add features to layers.. p_vertex.addFeatures(fts_vertex) p_edge.addFeatures(fts_edge) # Update fields.. l_vertex.updateFields() l_edge.updateFields() # Update layer's extent.. l_vertex.updateExtents() l_edge.updateExtents() # Check if valid.. if not l_vertex.isValid() or not l_edge.isValid(): raise Exception( u"Une erreur est survenue lors du chargement de la couche.") # Set labelling... palyr = QgsPalLayerSettings() palyr.enabled = True # palyr.readFromLayer(l_vertex) palyr.fieldName = r"$id" # Expression $id palyr.placement = 1 # ::OverPoint palyr.quadOffset = 2 # ::QuadrantAboveRight palyr.setDataDefinedProperty(80, True, True, r"1", "") # ::OffsetUnits -> ::MM palyr.xOffset = 2.0 palyr.yOffset = -1.0 palyr.writeToLayer(l_vertex) # Then return layers.. return [l_vertex, l_edge]