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)
Beispiel #2
0
    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']))
Beispiel #3
0
 def setCompareKey(self, key):
     try:
         QgsExpressionContextUtils.setLayerVariable(
             self.coverage.imagesLayer, "mapillaryCompareKey", key)
         self.coverage.imagesLayer.triggerRepaint()
     except:
         pass
Beispiel #4
0
 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 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)
Beispiel #10
0
    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
Beispiel #11
0
    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
Beispiel #12
0
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
Beispiel #13
0
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
Beispiel #14
0
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)
Beispiel #15
0
    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
Beispiel #16
0
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