def load_shapefile(self, feature_type, base_path): """Load downloaded shape file to QGIS Main Window. :param feature_type: What kind of features should be downloaded. Currently 'buildings', 'building-points' or 'roads' are supported. :type feature_type: str :param base_path: The base path of the shape file (without extension). :type base_path: str :raises: FileMissingError - when buildings.shp not exist """ path = '%s.shp' % base_path if not os.path.exists(path): message = self.tr( '%s does not exist. The server does not have any data for ' 'this extent.' % path) raise FileMissingError(message) layer = self.iface.addVectorLayer(path, feature_type, 'ogr') # Check if it's a building layer about the 2.5D if feature_type == 'buildings': layer_scope = QgsExpressionContextUtils.layerScope(layer) if not layer_scope.variable('qgis_25d_height'): QgsExpressionContextUtils.setLayerVariable( layer, 'qgis_25d_height', 0.0002) if not layer_scope.variable('qgis_25d_angle'): QgsExpressionContextUtils.setLayerVariable( layer, 'qgis_25d_angle', 70)
def viewerConnection(self, message): #print (message) if message: if message["transport"] == "move_cursor": self.sample_cursor.draw(message["pov"], message["orig_pov"], message["cursor"], message["endOfSight"]) if message["transport"] == "disable_cursor": self.sample_cursor.delete() if message["transport"] == "create_marker": self.sample_cursor.sample("marker", message['id'], message['key'], message['markerPos']) if message["transport"] == "drag_marker": s,key,id = message['id'].split(':') self.sample_cursor.moveMarker(key, id, message['markerPos']) if message["transport"] == "view": self.sample_cursor.delete() self.currentLocation = message try: QgsExpressionContextUtils.setLayerVariable(self.coverage.imagesLayer, "mapillaryCurrentKey", self.currentLocation['key']) if self.sample_settings.settings['sample_source'] != 'memory': self.sample_cursor.addSampleLayerToCanvas() self.coverage.imagesLayer.triggerRepaint() except Exception as e: print ("error opening key %s: %s" % (self.currentLocation['key'],e)) pass if message["transport"] == "focusOn": self.sample_cursor.delete() self.viewer.enable() self.canvas.setMapTool(self.mapSelectionTool) if message["transport"] == "open_settings": self.sample_settings.open() if message["transport"] == "image_info": mapillaryImageInfo.openKey(self,message["key"]) if message["transport"] == "store_tag": self.sample_cursor.sample("tag", message['id'], message['key'], message['loc'], json.dumps(message['geometry']))
def setCompareKey(self, key): try: QgsExpressionContextUtils.setLayerVariable( self.coverage.imagesLayer, "mapillaryCompareKey", key) self.coverage.imagesLayer.triggerRepaint() except: pass
def changeMapillary_images(self, feature): #print("changeMapillary_images") if not self.openAttrDialog(feature): QgsExpressionContextUtils.setLayerVariable(self.coverage.sequencesLayer, "mapillaryCurrentKey", feature['skey']) self.viewer.openLocation(feature['key']) QgsExpressionContextUtils.setLayerVariable(self.coverage.imagesLayer, "mapillaryCurrentKey", feature['key']) self.coverage.imagesLayer.triggerRepaint() self.coverage.sequencesLayer.triggerRepaint()
def setupLocationsLayer(self): self.mapillaryLocations = self.coverage.get_images_layer() if self.mapillaryLocations: print ("setup locations") QgsExpressionContextUtils.setLayerVariable(self.mapillaryLocations, "mapillaryCurrentKey", "undefined") self.mapSelectionTool = IdentifyGeometry(self.canvas, self.mapillaryLocations) self.mapSelectionTool.geomIdentified.connect(self.changeMapillaryLocation) QgsProject.instance().addMapLayer(self.mapillaryLocations)
def changeMapillaryLocation(self, feature): if self.mapillaryLocations: context = self.mapillaryLocations elif self.mapillaryCoverage: context = self.mapillaryCoverage else: context = self.mapillaryOverview self.viewer.openLocation(feature['key']) QgsExpressionContextUtils.setLayerVariable(context, "mapillaryCurrentKey", feature['key']) self.mapillaryLocations.triggerRepaint()
def load_shapefile(self, feature_type, base_path): """Load downloaded shape file to QGIS Main Window. :param feature_type: What kind of features should be downloaded. Currently 'buildings', 'building-points' or 'roads' are supported. :type feature_type: str :param base_path: The base path of the shape file (without extension). :type base_path: str :raises: FileMissingError - when buildings.shp not exist """ path = '%s.shp' % base_path if not os.path.exists(path): message = self.tr( '%s does not exist. The server does not have any data for ' 'this extent.' % path) raise FileMissingError(message) layer = self.iface.addVectorLayer(path, feature_type, 'ogr') # Check if it's a building layer and if it's QGIS 2.14 about the 2.5D if qgis_version() >= 21400 and feature_type == 'buildings': layer_scope = QgsExpressionContextUtils.layerScope(layer) if not layer_scope.variable('qgis_25d_height'): QgsExpressionContextUtils.setLayerVariable( layer, 'qgis_25d_height', 0.0002) if not layer_scope.variable('qgis_25d_angle'): QgsExpressionContextUtils.setLayerVariable( layer, 'qgis_25d_angle', 70) canvas_srid = self.canvas.mapSettings().destinationCrs().srsid() on_the_fly_projection = self.canvas.hasCrsTransformEnabled() if canvas_srid != 4326 and not on_the_fly_projection: if QGis.QGIS_VERSION_INT >= 20400: self.canvas.setCrsTransformEnabled(True) else: display_warning_message_bar( self.iface, self.tr('Enable \'on the fly\''), self.tr( 'Your current projection is different than EPSG:4326. ' 'You should enable \'on the fly\' to display ' 'correctly your layers') )
def viewerConnection(self, message): print (message) if message: #print tmpPOV if message["transport"] == "view": print (message) self.currentLocation = message try: #set a variable to view selected mapillary layer feature as selected QgsExpressionContextUtils.setLayerVariable(self.mapillaryLocations, "mapillaryCurrentKey", self.currentLocation['key']) self.mapillaryLocations.triggerRepaint() except: pass elif message["transport"] == "focusOn": print (("enabled MAPTOOL", self.mapSelectionTool)) self.viewer.enable() self.canvas.setMapTool(self.mapSelectionTool)
def create(self): if self.__layer is None: layer_name = self.alias or self.name settings = QSettings() # Take the "CRS for new layers" config, overwrite it while loading layers and... old_proj_value = settings.value("/Projections/defaultBehaviour", "prompt", type=str) settings.setValue("/Projections/defaultBehaviour", "useProject") self.__layer = QgsVectorLayer(self.uri, layer_name, self.provider) settings.setValue("/Projections/defaultBehavior", old_proj_value) if (self.srid is not None and not self.__layer.crs().authid() == "EPSG:{}".format(self.srid)): crs = QgsCoordinateReferenceSystem().fromEpsgId(self.srid) if not crs.isValid(): crs = QgsCoordinateReferenceSystem(self.srid) # Fallback self.__layer.setCrs(crs) if self.is_domain or self.is_dataset_table: self.__layer.setReadOnly() if self.display_expression: self.__layer.setDisplayExpression(self.display_expression) if self.coordinate_precision and self.coordinate_precision < 1: self.__layer.geometryOptions().setGeometryPrecision( self.coordinate_precision) self.__layer.geometryOptions().setRemoveDuplicateNodes(True) if self.model_topic_name: QgsExpressionContextUtils.setLayerVariable( self.__layer, "interlis_topic", self.model_topic_name) for field in self.fields: field.create(self) return self.__layer
def download_tiles(self, force=None): #calculate zoom_level con current canvas extents ex = self.iface.mapCanvas().extent() wgs84_minimum = self.transformToWGS84( QgsPointXY(ex.xMinimum(), ex.yMinimum())) wgs84_maximum = self.transformToWGS84( QgsPointXY(ex.xMaximum(), ex.yMaximum())) bounds = (wgs84_minimum.x(), wgs84_minimum.y(), wgs84_maximum.x(), wgs84_maximum.y()) map_units_per_pixel = (wgs84_maximum.x() - wgs84_minimum.x() ) / self.iface.mapCanvas().width() zoom_level = ZoomForPixelSize(map_units_per_pixel) if zoom_level > 14: zoom_level = 14 try: ranges = getTileRange(bounds, zoom_level) except ValueError: return if not self.actual_ranges or not ( ranges[0][0] == self.actual_ranges[0][0] and ranges[0][1] == self.actual_ranges[0][1] and ranges[1][0] == self.actual_ranges[1][0] and ranges[1][1] == self.actual_ranges[1][1]): #print ("ZOOM_LEVEL", zoom_level, "NEW RANGES", ranges, "LAST RANGES", self.actual_ranges) self.actual_ranges = ranges x_range = ranges[0] y_range = ranges[1] overview_features = [] sequences_features = [] images_features = [] progress = progressBar(self, 'go2mapillary') start_time = datetime.datetime.now() for y in range(y_range[0], y_range[1] + 1): for x in range(x_range[0], x_range[1] + 1): folderPath = os.path.join(self.cache_dir, str(zoom_level), str(x)) filePathMvt = os.path.join(folderPath, str(y) + '.mvt') #filePathJson = os.path.join(folderPath, str(y) + '.json') if not os.path.exists(folderPath): os.makedirs(folderPath) res = None if not os.path.exists(filePathMvt) or ( datetime.datetime.fromtimestamp( os.path.getmtime(filePathMvt)) < (datetime.datetime.now() - self.expire_time)): # make the URL url = getURL(x, y, zoom_level, SERVER_URL) with open(filePathMvt, 'wb') as f: response = requests.get(url, proxies=getProxiesConf(), stream=True) total_length = response.headers.get( 'content-length') if total_length is None: # no content length header f.write(response.content) else: dl = 0 total_length = int(total_length) progress.start( total_length, 'caching vector tile [%d,%d,%d]' % (x, y, zoom_level)) QgsMessageLog.logMessage("MISS [%d,%d,%d]" % (x, y, zoom_level), tag="go2mapillary", level=Qgis.Info) for data in response.iter_content( chunk_size=4096): dl += len(data) f.write(data) progress.setProgress(dl) if os.path.exists(filePathMvt): progress.start( 0, 'loading vector tile [%d,%d,%d]' % (x, y, zoom_level)) if not res: with open(filePathMvt, "rb") as f: mvt = f.read() QgsMessageLog.logMessage("CACHE [%d,%d,%d]" % (x, y, zoom_level), tag="go2mapillary", level=Qgis.Info) else: mvt = res.content bounds = mercantile.bounds(x, y, zoom_level) tile_box = (bounds.west, bounds.south, bounds.east, bounds.north) json_data = mapbox_vector_tile.decode( mvt, quantize_bounds=tile_box) if "mapillary-sequence-overview" in json_data: overview_features = overview_features + json_data[ "mapillary-sequence-overview"]["features"] elif "mapillary-sequences" in json_data: sequences_features = sequences_features + json_data[ "mapillary-sequences"]["features"] if "mapillary-images" in json_data and zoom_level == 14: images_features = images_features + json_data[ "mapillary-images"]["features"] # print("loading time", datetime.datetime.now() - start_time) progress.stop('loading complete') for level in LAYER_LEVELS: geojson_file = os.path.join(self.cache_dir, "mapillary_%s.geojson" % level) try: QgsProject.instance().removeMapLayer( getattr(self, level + 'Layer').id()) except: pass if locals()[level + '_features']: setattr(self, level, True) geojson = { "type": "FeatureCollection", "features": locals()[level + '_features'] } with open(geojson_file, 'w') as outfile: json.dump(geojson, outfile) defLyr = QgsVectorLayer( os.path.join(self.cache_dir, 'mapillary_%s.geojson' % level), "Mapillary " + level, "ogr") defLyr.loadNamedStyle( os.path.join(os.path.dirname(__file__), "res", "mapillary_%s.qml" % level)) QgsExpressionContextUtils.setLayerVariable( defLyr, "mapillaryCurrentKey", self.module.viewer.locationKey) defLyr.setCrs(QgsCoordinateReferenceSystem(4326)) QgsProject.instance().addMapLayer(defLyr) self.iface.addCustomActionForLayerType( getattr(self.module, 'filterAction_' + level), None, QgsMapLayer.VectorLayer, allLayers=False) self.module.filterDialog.applySqlFilter(layer=defLyr) self.iface.addCustomActionForLayer( getattr(self.module, 'filterAction_' + level), defLyr) legendLayerNode = QgsProject.instance().layerTreeRoot( ).findLayer(defLyr.id()) legendLayerNode.setExpanded(False) defLyr.setDisplayExpression('"key"') setattr(self, level + 'Layer', defLyr) else: setattr(self, level, False) else: pass
def open_file( dialog=None, osm_file=None, output_geom_types=None, white_list_column=None, layer_name="OsmFile", config_outputs=None, output_dir=None, final_query=None, prefix_file=None): """ Open an osm file. Memory layer if no output directory is set, or Geojson in the output directory. :param final_query: The query where the file comes from. Might be empty if it's a local OSM file. :type final_query: basestring """ outputs = {} if output_dir: for layer in ['points', 'lines', 'multilinestrings', 'multipolygons']: if not prefix_file: prefix_file = layer_name outputs[layer] = join( output_dir, prefix_file + "_" + layer + ".geojson") if isfile(outputs[layer]): raise FileOutPutException(suffix='(' + outputs[layer] + ')') # Legacy, waiting to remove the OsmParser for QGIS >= 3.6 # Change in osm_file_dialog.py L131 too output_geom_legacy = [l.value.lower() for l in output_geom_types] if not white_list_column: white_list_column = {} white_list_legacy = ( {l.value.lower(): csv for l, csv in white_list_column.items()} ) LOGGER.info('The OSM file is: {}'.format(osm_file)) # Parsing the file osm_parser = OsmParser( osm_file=osm_file, layers=output_geom_legacy, white_list_column=white_list_legacy) osm_parser.signalText.connect(dialog.set_progress_text) osm_parser.signalPercentage.connect(dialog.set_progress_percentage) start_time = time.time() layers = osm_parser.parse() elapsed_time = time.time() - start_time parser_time = time.strftime("%Hh %Mm %Ss", time.gmtime(elapsed_time)) LOGGER.info('The OSM parser took: {}'.format(parser_time)) # Finishing the process with geojson or memory layer num_layers = 0 for i, (layer, item) in enumerate(layers.items()): dialog.set_progress_percentage(i / len(layers) * 100) QApplication.processEvents() if item['featureCount'] and LayerType(layer.capitalize()) in output_geom_types: final_layer_name = layer_name # If configOutputs is not None (from My Queries) if config_outputs: if config_outputs[layer]['namelayer']: final_layer_name = config_outputs[layer]['namelayer'] if output_dir: dialog.set_progress_text(tr('From memory to GeoJSON: ' + layer)) # Transforming the vector file osm_geometries = { 'points': QgsWkbTypes.Point, 'lines': QgsWkbTypes.LineString, 'multilinestrings': QgsWkbTypes.MultiLineString, 'multipolygons': QgsWkbTypes.MultiPolygon} memory_layer = item['vector_layer'] encoding = get_default_encoding() writer = QgsVectorFileWriter( outputs[layer], encoding, memory_layer.fields(), osm_geometries[layer], memory_layer.crs(), "GeoJSON") for f in memory_layer.getFeatures(): writer.addFeature(f) del writer # Loading the final vector file new_layer = QgsVectorLayer(outputs[layer], final_layer_name, "ogr") else: new_layer = item['vector_layer'] new_layer.setName(final_layer_name) # Try to set styling if defined if config_outputs and config_outputs[layer]['style']: new_layer.loadNamedStyle(config_outputs[layer]['style']) else: # Loading default styles if layer == "multilinestrings" or layer == "lines": if "colour" in item['tags']: new_layer.loadNamedStyle( join(dirname(dirname(abspath(__file__))), "styles", layer + "_colour.qml")) # Add action about OpenStreetMap add_actions(new_layer, item['tags']) if final_query: QgsExpressionContextUtils.setLayerVariable( new_layer, 'quickosm_query', final_query) QgsProject.instance().addMapLayer(new_layer) num_layers += 1 return num_layers
def open_file( dialog=None, osm_file=None, output_geom_types=None, white_list_column=None, layer_name="OsmFile", config_outputs=None, output_dir=None, final_query=None, prefix_file=None): """ Open an osm file. Memory layer if no output directory is set, or Geojson in the output directory. :param final_query: The query where the file comes from. Might be empty if it's a local OSM file. :type final_query: basestring """ outputs = {} if output_dir: for layer in ['points', 'lines', 'multilinestrings', 'multipolygons']: if not prefix_file: prefix_file = layer_name outputs[layer] = join( output_dir, prefix_file + "_" + layer + ".geojson") if isfile(outputs[layer]): raise FileOutPutException(suffix='(' + outputs[layer] + ')') # Legacy, waiting to remove the OsmParser for QGIS >= 3.6 # Change in osm_file_dialog.py L131 too output_geom_legacy = [l.value.lower() for l in output_geom_types] if not white_list_column: white_list_column = {} white_list_legacy = ( {l.value.lower(): csv for l, csv in white_list_column.items()} ) LOGGER.info('The OSM file is: {}'.format(osm_file)) # Parsing the file osm_parser = OsmParser( osm_file=osm_file, layers=output_geom_legacy, white_list_column=white_list_legacy) osm_parser.signalText.connect(dialog.set_progress_text) osm_parser.signalPercentage.connect(dialog.set_progress_percentage) start_time = time.time() layers = osm_parser.parse() elapsed_time = time.time() - start_time parser_time = time.strftime("%Hh %Mm %Ss", time.gmtime(elapsed_time)) LOGGER.info('The OSM parser took: {}'.format(parser_time)) # Finishing the process with geojson or memory layer num_layers = 0 for i, (layer, item) in enumerate(layers.items()): dialog.set_progress_percentage(i / len(layers) * 100) QApplication.processEvents() if item['featureCount'] and ( LayerType(layer.capitalize()) in output_geom_types): final_layer_name = layer_name # If configOutputs is not None (from My Queries) if config_outputs: if config_outputs[layer]['namelayer']: final_layer_name = config_outputs[layer]['namelayer'] if output_dir: dialog.set_progress_text( tr('From memory layer to GeoJSON: ' + layer)) # Transforming the vector file osm_geometries = { 'points': QgsWkbTypes.Point, 'lines': QgsWkbTypes.LineString, 'multilinestrings': QgsWkbTypes.MultiLineString, 'multipolygons': QgsWkbTypes.MultiPolygon} memory_layer = item['vector_layer'] encoding = get_default_encoding() writer = QgsVectorFileWriter( outputs[layer], encoding, memory_layer.fields(), osm_geometries[layer], memory_layer.crs(), "GeoJSON") for f in memory_layer.getFeatures(): writer.addFeature(f) del writer # Loading the final vector file new_layer = QgsVectorLayer( outputs[layer], final_layer_name, "ogr") else: new_layer = item['vector_layer'] new_layer.setName(final_layer_name) # Try to set styling if defined if config_outputs and config_outputs[layer]['style']: new_layer.loadNamedStyle(config_outputs[layer]['style']) else: # Loading default styles if layer == "multilinestrings" or layer == "lines": if "colour" in item['tags']: new_layer.loadNamedStyle( join(dirname(dirname(abspath(__file__))), "styles", layer + "_colour.qml")) # Add action about OpenStreetMap add_actions(new_layer, item['tags']) if final_query: QgsExpressionContextUtils.setLayerVariable( new_layer, 'quickosm_query', final_query) QgsProject.instance().addMapLayer(new_layer) num_layers += 1 return num_layers
def add_design_to_map(qris_project, item, node): """adds designs to the map""" # Establish paths to layers design_id = item.data(item_code['feature_id']) subset_string = ("design_id = " + str(design_id)) design_name = item.text() geopackage_path = qris_project.project_designs.geopackage_path( qris_project.project_path) designs_layer = QgsVectorLayer(geopackage_path + "|layername=designs", "Designs", "ogr") structure_types_layer = QgsVectorLayer( geopackage_path + "|layername=structure_types", "Structure Types", "ogr") phases_layer = QgsVectorLayer(geopackage_path + "|layername=phases", "Implementation Phases", "ogr") zoi_layer = QgsVectorLayer(geopackage_path + "|layername=zoi", "ZOI", "ogr") zoi_types_layer = QgsVectorLayer(geopackage_path + "|layername=zoi_types", "ZOI", "ogr") complexes_layer = QgsVectorLayer(geopackage_path + "|layername=complexes", "Complexes", "ogr") structure_points_layer = QgsVectorLayer( geopackage_path + "|layername=structure_points", "Structures", "ogr") structure_lines_layer = QgsVectorLayer( geopackage_path + "|layername=structure_lines", "Structures", "ogr") # Get the structure geometry type # Could also do this with SQL design_iterator = designs_layer.getFeatures( QgsFeatureRequest().setFilterFid(design_id)) design_feature = next(design_iterator) structure_geometry = design_feature['structure_geometry'] def add_design_table(display_name, table_name, qml_name, read_only, group_node): """A handy way to add design layers and tables to the map""" if not any([c.name() == display_name for c in group_node.children()]): layer = QgsProject.instance().addMapLayer( QgsVectorLayer(geopackage_path + "|layername=" + table_name, display_name, "ogr"), False) if qml_name: layer_qml = os.path.join(symbology_path, 'symbology', qml_name) layer.loadNamedStyle(layer_qml) if read_only: layer.setReadOnly() group_node.addLayer(layer) # Summary tables (views) if any([c.name() == "Low-Tech Tables" for c in node.children()]): # if is there set it to the design node table_node = next(n for n in node.children() if n.name() == "Low-Tech Tables") else: # if not add the node as a group table_node = node.addGroup("Low-Tech Tables") table_node.setExpanded(False) # Summary tables (views) if any([c.name() == "Summary Tables" for c in table_node.children()]): # if is there set it to the design node summary_node = next(n for n in table_node.children() if n.name() == "Summary Tables") else: # if not add the node as a group summary_node = table_node.addGroup("Summary Tables") summary_node.setExpanded(False) add_design_table('Structure Totals - Points', 'qry_total_structures_points', None, True, summary_node) add_design_table('Structure Totals - Lines', 'qry_total_structures_lines', None, True, summary_node) add_design_table('Structure Summary - Points', 'qry_structure_summary_points', None, True, summary_node) add_design_table('Structure Summary - Lines', 'qry_structure_summary_lines', None, True, summary_node) add_design_table('Complexes Summary - Points', 'qry_complexes_by_type_points', None, True, summary_node) add_design_table('Complexes Summary - Lines', 'qry_complexes_by_type_lines', None, True, summary_node) add_design_table('ZOI Summary', 'qry_zoi_summary', None, True, summary_node) # Lookup Tables if any([c.name() == "Lookup Tables" for c in table_node.children()]): # if is there set it to the design node lookup_node = next(n for n in table_node.children() if n.name() == "Lookup Tables") else: # if not add the node as a group lookup_node = table_node.addGroup("Lookup Tables") lookup_node.setExpanded(False) add_design_table('Design Status', 'lkp_design_status', 'lkp_design_status.qml', True, lookup_node) add_design_table('Phase Action', 'lkp_phase_action', 'lkp_phase_action.qml', True, lookup_node) add_design_table('ZOI Influence', 'lkp_zoi_influence', 'lkp_zoi_influence.qml', True, lookup_node) add_design_table('ZOI Stage', 'lkp_zoi_stage', 'lkp_zoi_stage.qml', True, lookup_node) add_design_table('Structure Mimics', 'lkp_structure_mimics', 'lkp_structure_mimics.qml', True, lookup_node) # Add Design Tables if any([c.name() == "Design Tables" for c in table_node.children()]): # if is there set it to the design node design_tables_node = next(n for n in table_node.children() if n.name() == "Design Tables") else: # if not add the node as a group design_tables_node = table_node.addGroup("Design Tables") design_tables_node.setExpanded(False) # Check if the designs table has been added and if not add it. add_design_table('Designs', 'designs', 'designs.qml', False, design_tables_node) add_design_table('Structure Types', 'structure_types', 'structure_types.qml', False, design_tables_node) add_design_table('ZOI Types', 'zoi_types', 'zoi_types.qml', False, design_tables_node) add_design_table('Phases', 'phases', 'phases.qml', False, design_tables_node) # Check if the design node is already added design_group_name = str(design_id) + "-" + item.text() if any([c.name() == design_group_name for c in node.children()]): # if is there set it to the design node design_node = next(n for n in node.children() if n.name() == design_group_name) else: # if not add the node as a group design_node = node.addGroup(design_group_name) # Add structures structure_layer_name = str(design_id) + "-Structures" if structure_geometry == 'Point': # Start setting custom symbology # TODO Refactor into a functio unique_values = [] for feature in structure_types_layer.getFeatures(): values = (feature["fid"], feature["name"]) unique_values.append(values) categories = [] for value in unique_values: layer_style = {} layer_style["color"] = '%d, %d, %d' % (randrange( 0, 256), randrange(0, 256), randrange(0, 256)) layer_style['size'] = '3' layer_style['outline_color'] = 'black' symbol_layer = QgsMarkerSymbol.createSimple(layer_style) category = QgsRendererCategory(str(value[0]), symbol_layer, value[1]) categories.append(category) renderer = QgsCategorizedSymbolRenderer('structure_type_id', categories) if not any( [c.name() == structure_layer_name for c in design_node.children()]): # Adding the type suffix as I could see adding qml that symbolizes on other attributes structure_points_qml = os.path.join(symbology_path, 'symbology', 'structure_points.qml') structure_points_layer.loadNamedStyle(structure_points_qml) QgsExpressionContextUtils.setLayerVariable(structure_points_layer, 'parent_id', design_id) structure_points_layer.setSubsetString(subset_string) QgsProject.instance().addMapLayer(structure_points_layer, False) structure_points_layer.setName(structure_layer_name) design_node.addLayer(structure_points_layer) layer_node = design_node.findLayer(structure_points_layer.id()) layer_node.setExpanded(False) else: structure_points_layer = QgsProject.instance().mapLayersByName( structure_layer_name)[0] if renderer is not None: structure_points_layer.setRenderer(renderer) structure_points_layer.triggerRepaint() else: # Add line structures # Start setting custom symbology # TODO Refactor into a function unique_values = [] for feature in structure_types_layer.getFeatures(): values = (feature["fid"], feature["name"]) unique_values.append(values) categories = [] for value in unique_values: layer_style = {} layer_style["color"] = '%d, %d, %d' % (randrange( 0, 256), randrange(0, 256), randrange(0, 256)) layer_style['width'] = '1' layer_style['capstyle'] = 'round' symbol_layer = QgsLineSymbol.createSimple(layer_style) category = QgsRendererCategory(str(value[0]), symbol_layer, value[1]) categories.append(category) renderer = QgsCategorizedSymbolRenderer('structure_type_id', categories) # end custom symbology if not any( [c.name() == structure_layer_name for c in design_node.children()]): structures_lines_qml = os.path.join(symbology_path, 'symbology', 'structure_lines.qml') structure_lines_layer.loadNamedStyle(structures_lines_qml) QgsExpressionContextUtils.setLayerVariable(structure_lines_layer, 'parent_id', design_id) structure_lines_layer.setSubsetString(subset_string) QgsProject.instance().addMapLayer(structure_lines_layer, False) structure_lines_layer.setName(structure_layer_name) design_node.addLayer(structure_lines_layer) layer_node = design_node.findLayer(structure_lines_layer.id()) layer_node.setExpanded(False) else: structure_lines_layer = QgsProject.instance().mapLayersByName( structure_layer_name)[0] if renderer is not None: structure_lines_layer.setRenderer(renderer) structure_lines_layer.triggerRepaint() # Add zoi zoi_layer_name = str(design_id) + "-ZOI" # TODO Refactor into a function # TODO Refactor into sql query unique_values = [] for feature in zoi_types_layer.getFeatures(): values = (feature["fid"], feature["name"]) unique_values.append(values) categories = [] for value in unique_values: layer_style = {} alpha = 60 layer_style["color"] = "{}, {}, {}, {}".format(randrange(0, 256), randrange(0, 256), randrange(0, 256), alpha) layer_style["outline_width"] = '0.50' layer_style["outline_style"] = 'dash' symbol_layer = QgsFillSymbol.createSimple(layer_style) category = QgsRendererCategory(str(value[0]), symbol_layer, value[1]) categories.append(category) renderer = QgsCategorizedSymbolRenderer('influence_type_id', categories) # End custom symbology # check for the zoi layer, and if it is not there symbolize and add it if not any([c.name() == zoi_layer_name for c in design_node.children()]): zoi_qml = os.path.join(symbology_path, 'symbology', 'zoi.qml') zoi_layer.loadNamedStyle(zoi_qml) QgsExpressionContextUtils.setLayerVariable(zoi_layer, 'parent_id', design_id) zoi_layer.setSubsetString(subset_string) QgsProject.instance().addMapLayer(zoi_layer, False) zoi_layer.setName(zoi_layer_name) design_node.addLayer(zoi_layer) layer_node = design_node.findLayer(zoi_layer.id()) layer_node.setExpanded(False) else: zoi_layer = QgsProject.instance().mapLayersByName(zoi_layer_name)[0] if renderer is not None: zoi_layer.setRenderer(renderer) zoi_layer.triggerRepaint() # Add complexes complex_layer_name = str(design_id) + "-Complexes" if not any( [c.name() == complex_layer_name for c in design_node.children()]): complex_qml = os.path.join(symbology_path, 'symbology', 'complexes.qml') complexes_layer.loadNamedStyle(complex_qml) QgsExpressionContextUtils.setLayerVariable(complexes_layer, 'parent_id', design_id) complexes_layer.setSubsetString(subset_string) QgsProject.instance().addMapLayer(complexes_layer, False) complexes_layer.setName(complex_layer_name) design_node.addLayer(complexes_layer)
def agregacio(self, llegenda, nomCapa: str, zona: str, tipusAgregacio: str, renderParams: QvMapRendererParams, campAgregat: str = '', simple=True, tipusDistribucio: str = "Total", campExtensio: str = mv.MAP_EXTENSIO, filtre: str = '', veure: bool = True, form: QDialog = None) -> bool: """ Realiza la agragación de los datos por zona, la generación del mapa y su simbología. Arguments: llegenda {QvLlegenda} -- Leyenda nomCapa {str} -- Nombre de la capa del mapa a generar zona {str} -- Zona de agregación tipusAgregacio {str} -- Tipo de agregación renderParams {QvMapRendererParams} -- Parámetros de simbología Keyword Arguments: campAgregat {str} -- Campo que se utiliza en el cálculo de la agragación (default: {''}) tipusDistribucio {str} -- Tipo de distribución (default: {"Total"}) campExtensio {str} -- Nombre del campo que indica la extensión del mapa (default: {''}) filtre {str} -- Expresión para filtrar los datos (default: {''}) veure {bool} -- Si es True, añade la nueva capa con el mapa en la leyenda (default: {True}) form {QDialog} -- Formulario desde donde se invoca la función (default: {None}) Returns: bool -- False si hubo errores (mensaje de error en self.msgError) """ if not PANDAS_ENABLED: self.msgError = PANDAS_ERROR return False self.fMapa = '' self.fSQL = '' self.llegenda = llegenda self.msgError = '' self.form = form self.descripcio = "Arxiu de dades: " + self.fZones + '\n' + \ "Data: " + QDate.currentDate().toString(QvApp().locale.dateFormat(QvApp().locale.ShortFormat)) + '\n' + \ "Zona: " + zona + '\n' + \ "Tipus d'agregació: " + tipusAgregacio + '\n' + \ "Camp de càlcul: " + campAgregat if not simple: self.descripcio += '\n' + \ "Filtre: " + filtre + '\n' + \ "Distribució: " + tipusDistribucio if not self.verifZona(zona): self.msgError = "Error en zona" return False if campAgregat is not None and campAgregat != '': self.campAgregat = campAgregat elif tipusAgregacio == 'Recompte' and campAgregat == '': self.campAgregat = '*' else: self.msgError = "Error en campAgregat" return False if tipusAgregacio is None or tipusAgregacio not in mv.MAP_AGREGACIO.keys( ): self.msgError = "Error en tipusAgregacio" return False self.tipusAgregacio = mv.MAP_AGREGACIO[tipusAgregacio].format( self.campAgregat) if tipusDistribucio is None or tipusDistribucio not in mv.MAP_DISTRIBUCIO.keys( ): self.msgError = "Error en tipusDistribucio" return False self.tipusDistribucio = mv.MAP_DISTRIBUCIO[tipusDistribucio] self.filtre = filtre self.nomCapa = self.netejaString(nomCapa, True) # if not self.generaCapaQgis(nomCapa): # return False if not self.generaCapaGpd(self.nomCapa, tipusAgregacio, tipusDistribucio, renderParams, campExtensio): return False # Carga capa de agregación mapLyr = QgsVectorLayer(self.fSQL, nomCapa, "ogr") mapLyr.setProviderEncoding("UTF-8") if not mapLyr.isValid(): self.msgError = "No s'ha pogut carregar capa de agregació: " + self.fSQL return False # Renderer para mapificar mapRenderer = renderParams.mapRenderer(self.llegenda) self.renderer = mapRenderer.calcRender(mapLyr) if self.renderer is None: self.msgError = "No s'ha pogut elaborar el mapa" return False else: mapLyr.setRenderer(self.renderer) # Identificador de mapificación para qVista QgsExpressionContextUtils.setLayerVariable(mapLyr, mv.MAP_ID, self.descripcio) mapLyr.setDisplayExpression(renderParams.campCalculat) # Guarda simbología en GPKG err = self.llegenda.saveStyleToGeoPackage(mapLyr, mv.MAP_ID) if err != '': self.msgError = "Hi ha hagut problemes al desar la simbologia\n({})".format( err) return False # Fin correcto self.fMapa = self.fSQL if veure: self.llegenda.project.addMapLayer(mapLyr) return True
def open_file(dialog: QDialog = None, osm_file: str = None, output_geom_types: list = None, white_list_column: dict = None, key: Union[str, List[str]] = None, layer_name: str = "OsmFile", config_outputs: dict = None, output_dir: str = None, output_format: Format = None, final_query: str = None, prefix_file: str = None, subset: bool = False, subset_query: str = None, feedback: QgsFeedback = None) -> int: """ Open an osm file. Memory layer if no output directory is set, or Geojson in the output directory. :param final_query: The query where the file comes from. Might be empty if it's a local OSM file. :type final_query: basestring """ if output_geom_types is None: output_geom_types = OSM_LAYERS # Legacy, waiting to remove the OsmParser for QGIS >= 3.6 # Change in osm_file_dialog.py L131 too output_geom_legacy = [geom.value.lower() for geom in output_geom_types] if not white_list_column: white_list_column = None LOGGER.info('The OSM file is: {}'.format(osm_file)) if feedback: if feedback.isCanceled(): return None # Parsing the file osm_parser = OsmParser(osm_file=osm_file, layers=output_geom_legacy, output_format=output_format, output_dir=output_dir, prefix_file=prefix_file, layer_name=layer_name, key=key, white_list_column=white_list_column, subset=subset, subset_query=subset_query, feedback=feedback) if dialog: osm_parser.signalText.connect(dialog.set_progress_text) osm_parser.signalPercentage.connect(dialog.set_progress_percentage) start_time = time.time() layers = osm_parser.processing_parse() elapsed_time = time.time() - start_time parser_time = time.strftime("%Hh %Mm %Ss", time.gmtime(elapsed_time)) LOGGER.info('The OSM parser took: {}'.format(parser_time)) if feedback: if feedback.isCanceled(): return None # Finishing the process with an output format or memory layer num_layers = 0 for i, (layer, item) in enumerate(layers.items()): if dialog: dialog.set_progress_percentage(i / len(layers) * 100) QApplication.processEvents() if item['featureCount'] and (LayerType(layer.capitalize()) in output_geom_types): final_layer_name = layer_name # If configOutputs is not None (from My Queries) if config_outputs: if config_outputs[layer]['namelayer']: final_layer_name = config_outputs[layer]['namelayer'] new_layer = item['vector_layer'] new_layer.setName(final_layer_name) # Try to set styling if defined if config_outputs and config_outputs[layer]['style']: new_layer.loadNamedStyle(config_outputs[layer]['style']) else: if "colour" in item['tags']: index = item['tags'].index('colour') colors = new_layer.uniqueValues(index) categories = [] for value in colors: if str(value) == 'None': value = '' if layer in ['lines', 'multilinestrings']: symbol = QgsSymbol.defaultSymbol( QgsWkbTypes.LineGeometry) elif layer == "points": symbol = QgsSymbol.defaultSymbol( QgsWkbTypes.PointGeometry) elif layer == "multipolygons": symbol = QgsSymbol.defaultSymbol( QgsWkbTypes.PolygonGeometry) symbol.setColor(QColor(value)) category = QgsRendererCategory(str(value), symbol, str(value)) categories.append(category) renderer = QgsCategorizedSymbolRenderer( "colour", categories) new_layer.setRenderer(renderer) # Add action about OpenStreetMap actions.add_actions(new_layer, item['tags']) QgsProject.instance().addMapLayer(new_layer) if final_query: QgsExpressionContextUtils.setLayerVariable( new_layer, 'quickosm_query', final_query) actions.add_relaunch_action(new_layer, final_layer_name) if dialog: dialog.iface.addCustomActionForLayer( dialog.reload_action, new_layer) metadata = QgsLayerMetadata() metadata.setRights([tr("© OpenStreetMap contributors")]) metadata.setLicenses(['https://openstreetmap.org/copyright']) new_layer.setMetadata(metadata) num_layers += 1 return num_layers