3. Caricamento del vettore

I frammenti di codice in questa pagina hanno bisogno dei seguenti import:

import os # This is is needed in the pyqgis console also
from qgis.core import (
    QgsVectorLayer
)

Apri alcuni layer con dati. QGIS riconosce vettori e raster. inoltre sono disponibili tipi di layer personalizzati ma non li discuteremo qui.

3.1. Vettori

Per creare e aggiungere un’istanza di layer vettoriale al progetto, specificare l’identificatore della fonte di dati del layer, il nome del layer ed il nome del provider:

 1# get the path to the shapefile e.g. /home/project/data/ports.shp
 2path_to_airports_layer = "testdata/airports.shp"
 3
 4# The format is:
 5# vlayer = QgsVectorLayer(data_source, layer_name, provider_name)
 6
 7vlayer = QgsVectorLayer(path_to_airports_layer, "Airports layer", "ogr")
 8if not vlayer.isValid():
 9    print("Layer failed to load!")
10else:
11    QgsProject.instance().addMapLayer(vlayer)

L’identificativo dell’origine dati è una stringa ed è specifico per ciascun fornitore di dati vettoriali. Il nome del livello viene utilizzato nell’oggetto elenco livelli. È importante verificare se il layer è stato caricato correttamente. In caso contrario, viene restituita un’istanza di livello non valida.

Per un vettore geopackage:

 1# get the path to a geopackage  e.g. /usr/share/qgis/resources/data/world_map.gpkg
 2path_to_gpkg = os.path.join(QgsApplication.pkgDataPath(), "resources", "data", "world_map.gpkg")
 3# append the layername part
 4gpkg_countries_layer = path_to_gpkg + "|layername=countries"
 5# e.g. gpkg_places_layer = "/usr/share/qgis/resources/data/world_map.gpkg|layername=countries"
 6vlayer = QgsVectorLayer(gpkg_countries_layer, "Countries layer", "ogr")
 7if not vlayer.isValid():
 8    print("Layer failed to load!")
 9else:
10    QgsProject.instance().addMapLayer(vlayer)

Il modo più rapido per aprire e visualizzare un vettore in QGIS è il metodo addVectorLayer() della classe QgisInterface:

vlayer = iface.addVectorLayer(path_to_airports_layer, "Airports layer", "ogr")
if not vlayer:
  print("Layer failed to load!")

Questo crea un nuovo layer e lo aggiunge al progetto QGIS corrente (facendolo apparire nell’elenco dei layer) in un solo passaggio. La funzione restituisce l’istanza del layer o None se non è stato possibile caricare il layer.

Il seguente elenco mostra come accedere a varie fonti di dati usando i fornitori di dati vettoriali:

  • Libreria OGR (shapefile e molti altri formati di file) — l’origine dati è il percorso del file:

    • per shapefile:

      vlayer = QgsVectorLayer("testdata/airports.shp", "layer_name_you_like", "ogr")
      QgsProject.instance().addMapLayer(vlayer)
      
    • per dxf (nota le opzioni nell’origine dati uri):

      uri = "testdata/sample.dxf|layername=entities|geometrytype=Polygon"
      vlayer = QgsVectorLayer(uri, "layer_name_you_like", "ogr")
      QgsProject.instance().addMapLayer(vlayer)
      
  • Database PostGIS - data source è una stringa con tutte le informazioni necessarie per creare una connessione al database PostgreSQL.

    La classe QgsDataSourceUri può generare questa stringa per te. Nota che QGIS deve essere stato compilato con il supporto Postgres, altrimenti questo provider non è disponibile:

    1uri = QgsDataSourceUri()
    2# set host name, port, database name, username and password
    3uri.setConnection("localhost", "5432", "dbname", "johny", "xxx")
    4# set database schema, table name, geometry column and optionally
    5# subset (WHERE clause)
    6uri.setDataSource("public", "roads", "the_geom", "cityid = 2643", "primary_key_field")
    7
    8vlayer = QgsVectorLayer(uri.uri(False), "layer name you like", "postgres")
    

    Nota

    L’argomento False passato a uri.uri(False) previene l’espansione dei parametri di configurazione di autenticazione, se tu non usi nessuna configurazione di autenticazione questo argomento non produrrà nessun effetto.

  • CSV o altri file di testo delimitati — per aprire un file con un punto e virgola come delimitatore, con il campo «x» per la coordinata X e il campo «y» per la coordinata Y si userebbe qualcosa di simile:

    uri = "file://{}/testdata/delimited_xy.csv?delimiter={}&xField={}&yField={}".format(os.getcwd(), ";", "x", "y")
    vlayer = QgsVectorLayer(uri, "layer name you like", "delimitedtext")
    QgsProject.instance().addMapLayer(vlayer)
    

    Nota

    La stringa provider è strutturata come un URL, quindi il percorso deve avere il prefisso file://. Inoltre permette di formattare geometrie WKT (well known text) in alternativa ai campi x``e `y, e permette di specificare il sistema di riferimento di coordinate. Per esempio:

    uri = "file:///some/path/file.csv?delimiter={}&crs=epsg:4723&wktField={}".format(";", "shape")
    
  • I file GPX – il provider di dati «gpx» legge tracce, percorsi e waypoint dai file gpx. Per aprire un file, il tipo (track/route/waypoint) deve essere specificato come parte dell’url:

    uri = "testdata/layers.gpx?type=track"
    vlayer = QgsVectorLayer(uri, "layer name you like", "gpx")
    QgsProject.instance().addMapLayer(vlayer)
    
  • Database SpatiaLite — Analogamente ai database PostGIS, :class:`Qgsdatasourceuri <qgis.core.Qgsdatasourceuri>`può essere utilizzato per la generazione dell’identificatore della fonte di dati:

     1uri = QgsDataSourceUri()
     2uri.setDatabase('/home/martin/test-2.3.sqlite')
     3schema = ''
     4table = 'Towns'
     5geom_column = 'Geometry'
     6uri.setDataSource(schema, table, geom_column)
     7
     8display_name = 'Towns'
     9vlayer = QgsVectorLayer(uri.uri(), display_name, 'spatialite')
    10QgsProject.instance().addMapLayer(vlayer)
    
  • Mysql WKB-based geometries, attraverso OGR — data source è la stringa di connessione alla tabella:

    uri = "MySQL:dbname,host=localhost,port=3306,user=root,password=xxx|layername=my_table"
    vlayer = QgsVectorLayer( uri, "my table", "ogr" )
    QgsProject.instance().addMapLayer(vlayer)
    
  • Connessione WFS: la connessione è definita con un URI e usando il ``WFS``provider:

    uri = "https://demo.mapserver.org/cgi-bin/wfs?service=WFS&version=2.0.0&request=GetFeature&typename=ms:cities"
    vlayer = QgsVectorLayer(uri, "my wfs layer", "WFS")
    

    L’uri può essere creato usando la libreria standard urllib:

     1import urllib
     2
     3params = {
     4    'service': 'WFS',
     5    'version': '2.0.0',
     6    'request': 'GetFeature',
     7    'typename': 'ms:cities',
     8    'srsname': "EPSG:4326"
     9}
    10uri2 = 'https://demo.mapserver.org/cgi-bin/wfs?' + urllib.parse.unquote(urllib.parse.urlencode(params))
    

Nota

È possibile cambiare la fonte di dati di un livello esistente chiamando setDataSource() qgis.core.Qgsvectorlayer.setDataSource>() su un’istanza Qgsvectorlayer qgis.core.Qgsvectorlayer>, come nell’esempio seguente:

1uri = "https://demo.mapserver.org/cgi-bin/wfs?service=WFS&version=2.0.0&request=GetFeature&typename=ms:cities"
2provider_options = QgsDataProvider.ProviderOptions()
3# Use project's transform context
4provider_options.transformContext = QgsProject.instance().transformContext()
5vlayer.setDataSource(uri, "layer name you like", "WFS", provider_options)
6
7del(vlayer)

3.2. Raster

Per accedere ai file raster, viene utilizzata la libreria GDAL. Supporta una vasta gamma di formati di file. In caso di problemi con l’apertura di alcuni file, verificare se il GDAL ha il supporto per il formato particolare (non tutti i formati sono disponibili per impostazione predefinita). Per caricare un raster da un file, specificare il nome del file e il nome di visualizzazione:

1# get the path to a tif file  e.g. /home/project/data/srtm.tif
2path_to_tif = "qgis-projects/python_cookbook/data/srtm.tif"
3rlayer = QgsRasterLayer(path_to_tif, "SRTM layer name")
4if not rlayer.isValid():
5    print("Layer failed to load!")

Per caricare un raster da un geopackage:

1# get the path to a geopackage  e.g. /home/project/data/data.gpkg
2path_to_gpkg = os.path.join(os.getcwd(), "testdata", "sublayers.gpkg")
3# gpkg_raster_layer = "GPKG:/home/project/data/data.gpkg:srtm"
4gpkg_raster_layer = "GPKG:" + path_to_gpkg + ":srtm"
5
6rlayer = QgsRasterLayer(gpkg_raster_layer, "layer name you like", "gdal")
7
8if not rlayer.isValid():
9    print("Layer failed to load!")

Analogamente ai livelli vettoriali, i livelli raster possono essere caricati usando la funzione addRasterLayer dell’oggetto classe:QgisInterface <qgis.gui.QgisInterface>:

iface.addRasterLayer(path_to_tif, "layer name you like")

Questo crea un nuovo livello e lo aggiunge al progetto corrente (facendolo apparire nella lista dei livelli) in un solo passaggio.

Per caricare un raster Postgis:

I raster PostGIS, simili ai vettori PostGIS, possono essere aggiunti a un progetto usando una stringa URI. È efficiente mantenere un dizionario riutilizzabile di stringhe per i parametri di connessione al database. Questo rende facile modificare il dizionario per la connessione appropriata. Il dizionario viene poi codificato in un URI usando l’oggetto metadati del provider “postgraster”. Dopo di che il raster può essere aggiunto al progetto.

 1uri_config = {
 2    # database parameters
 3    'dbname':'gis_db',      # The PostgreSQL database to connect to.
 4    'host':'localhost',     # The host IP address or localhost.
 5    'port':'5432',          # The port to connect on.
 6    'sslmode':QgsDataSourceUri.SslDisable, # SslAllow, SslPrefer, SslRequire, SslVerifyCa, SslVerifyFull
 7    # user and password are not needed if stored in the authcfg or service
 8    'authcfg':'QconfigId',  # The QGIS athentication database ID holding connection details.
 9    'service': None,         # The PostgreSQL service to be used for connection to the database.
10    'username':None,        # The PostgreSQL user name.
11    'password':None,        # The PostgreSQL password for the user.
12    # table and raster column details
13    'schema':'public',      # The database schema that the table is located in.
14    'table':'my_rasters',   # The database table to be loaded.
15    'geometrycolumn':'rast',# raster column in PostGIS table
16    'sql':None,             # An SQL WHERE clause. It should be placed at the end of the string.
17    'key':None,             # A key column from the table.
18    'srid':None,            # A string designating the SRID of the coordinate reference system.
19    'estimatedmetadata':'False', # A boolean value telling if the metadata is estimated.
20    'type':None,            # A WKT string designating the WKB Type.
21    'selectatid':None,      # Set to True to disable selection by feature ID.
22    'options':None,         # other PostgreSQL connection options not in this list.
23    'enableTime': None,
24    'temporalDefaultTime': None,
25    'temporalFieldIndex': None,
26    'mode':'2',             # GDAL 'mode' parameter, 2 unions raster tiles, 1 adds tiles separately (may require user input)
27}
28# remove any NULL parameters
29uri_config = {key:val for key, val in uri_config.items() if val is not None}
30# get the metadata for the raster provider and configure the URI
31md = QgsProviderRegistry.instance().providerMetadata('postgresraster')
32uri = QgsDataSourceUri(md.encodeUri(uri_config))
33
34# the raster can then be loaded into the project
35rlayer = iface.addRasterLayer(uri.uri(False), "raster layer name", "postgresraster")

I livelli raster possono anche essere creati da un servizio WCS:

layer_name = 'modis'
url = "https://demo.mapserver.org/cgi-bin/wcs?identifier={}".format(layer_name)
rlayer = QgsRasterLayer(uri, 'my wcs layer', 'wcs')

Ecco una descrizione dei parametri che l’URI WCS può contenere:

L’URI WCS è composto da coppie key=value separate da &. È lo stesso formato come la stringa di interrogazione nell’URL, codificata nello stesso modo. : class:Qgsdatasourceuri qgis.core.Qgsdatasourceuri> dovrebbe essere usato per costruire l’URI per garantire che i caratteri speciali siano codificati correttamente.

  • url (obbligatorio) : URL del server WCS. Non usare VERSION nell” URL, perché ogni versione del WCS usa un nome di parametro diverso per la versione Getcapabilities, vedi param version.

  • identifier (obbligatorio) : Coverage name

  • time (opzionale) : posizione temporale o periodo temporale (beginPosition/endposition[/timeResolution])

  • format (opzionale) : Nome formato supportato. Il formato predefinito è il primo formato supportato con tif nel nome o il primo formato supportato.

  • crs (facoltativo): CRS nel modulo AUTHORITY:ID, ad es. EPSG:4326. Il valore predefinito è EPSG:4326 se supportato o il primo SR supportato.

  • username (opzionale) : Nome utente per l’autenticazione di base.

  • password (opzionale) : password per l’autenticazione di base.

  • IgnoreGetMapUrl (opzionale, hack) : Se specificato (impostato a 1), ignora l’URL di GetCoverage pubblicizzato da GetCapabilities. Può essere necessario se un server non è configurato correttamente.

  • InvertAxisOrientation (opzionale, hack): Se specificato (impostato a 1), inverte l’asse nella richiesta Getcoverage. Può essere necessario per un SR geografico se un server sta” usando un’ordine errato dell’asse.

  • IgnoreAxisOrientation (opzionale, hack): Se specificato (impostato a 1), non invertire l’orientamento dell’asse secondo lo standard WCS per SR geografico.

  • cache (opzionale) : controllo del carico della cache, come descritto in QNetworkRequest::CacheLoadControl, ma la richiesta viene rinviata come PreferCache se non riuscita con AlwaysCcache. Valori ammessi: AlwaysCache, PreferCache, PreferNetwork, AlwaysNetwork. Il valore predefinito è AlwaysCache.

In alternativa è possibile caricare un livello raster dal server WMS. Tuttavia attualmente non è possibile accedere alla risposta GetCapabilities da API — devi sapere quali livelli vuoi:

urlWithParams = "crs=EPSG:4326&format=image/png&layers=continents&styles&url=https://demo.mapserver.org/cgi-bin/wms"
rlayer = QgsRasterLayer(urlWithParams, 'some layer name', 'wms')
if not rlayer.isValid():
  print("Layer failed to load!")

3.3. Istanza QgsProject

Se volete usare i livelli aperti per il rendering, non dimenticate di aggiungerli all’istanza QgsProject qgis.core.QgsProject>. L’istanza QgsProject prende la proprietà di livelli e possono essere successivamente accessibili da qualsiasi parte dell’applicazione dal loro ID univoco. Quando il livello viene rimosso dal progetto, viene anche eliminato. I livelli possono essere rimossi dall’utente nell’interfaccia QGIS, o tramite Python usando il metodo removeMapLayer() qgis.core.Qgsproject.removeMapLayer>().

L’aggiunta di un livello al progetto corrente viene effettuata utilizzando il metodo addMapLayer() :

QgsProject.instance().addMapLayer(rlayer)

Per aggiungere un livello in una posizione assoluta:

1# first add the layer without showing it
2QgsProject.instance().addMapLayer(rlayer, False)
3# obtain the layer tree of the top-level group in the project
4layerTree = iface.layerTreeCanvasBridge().rootGroup()
5# the position is a number starting from 0, with -1 an alias for the end
6layerTree.insertChildNode(-1, QgsLayerTreeLayer(rlayer))

Se si desidera eliminare il livello utilizzare il metodo removeMapLayer() :

# QgsProject.instance().removeMapLayer(layer_id)
QgsProject.instance().removeMapLayer(rlayer.id())

Nel codice precedente, l’id del livello viene passato (si può ottenere chiamando il metodo id() del livello), ma si può anche passare l’oggetto del livello stesso.

Per una lista di livelli caricati e id di livello, usare il metodo mapLayers() :

QgsProject.instance().mapLayers()