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
 2
 3
 4
 5
 6
 7
 8
 9
10
11
# get the path to the shapefile e.g. /home/project/data/ports.shp
path_to_airports_layer = "testdata/airports.shp"

# The format is:
# vlayer = QgsVectorLayer(data_source, layer_name, provider_name)

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

    1
    2
    3
    4
    5
    6
    7
    8
    uri = QgsDataSourceUri()
    # set host name, port, database name, username and password
    uri.setConnection("localhost", "5432", "dbname", "johny", "xxx")
    # set database schema, table name, geometry column and optionally
    # subset (WHERE clause)
    uri.setDataSource("public", "roads", "the_geom", "cityid = 2643", "primary_key_field")
    
    vlayer = 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:

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    uri = QgsDataSourceUri()
    uri.setDatabase('/home/martin/test-2.3.sqlite')
    schema = ''
    table = 'Towns'
    geom_column = 'Geometry'
    uri.setDataSource(schema, table, geom_column)
    
    display_name = 'Towns'
    vlayer = QgsVectorLayer(uri.uri(), display_name, 'spatialite')
    QgsProject.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.geo-solutions.it/geoserver/ows?service=WFS&version=1.1.0&request=GetFeature&typename=geosolutions:regioni"
    vlayer = QgsVectorLayer(uri, "my wfs layer", "WFS")
    QgsProject.instance().addMapLayer(vlayer)
    

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

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    import urllib
    
    params = {
        'service': 'WFS',
        'version': '1.1.0',
        'request': 'GetFeature',
        'typename': 'geosolutions:regioni',
        'srsname': "EPSG:4326"
    }
    uri2 = 'https://demo.geo-solutions.it/geoserver/ows?' + 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:

1
2
3
4
5
6
uri = "https://demo.geo-solutions.it/geoserver/ows?service=WFS&version=1.1.0&request=GetFeature&typename=geosolutions:regioni"
provider_options = QgsDataProvider.ProviderOptions()
# Use project's transform context
provider_options.transformContext = QgsProject.instance().transformContext()
vlayer.setDataSource(uri, "layer name you like", "WFS", provider_options)
QgsProject.instance().addMapLayer(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
2
3
4
5
# get the path to a tif file  e.g. /home/project/data/srtm.tif
path_to_tif = "qgis-projects/python_cookbook/data/srtm.tif"
rlayer = QgsRasterLayer(path_to_tif, "SRTM layer name")
if not rlayer.isValid():
    print("Layer failed to load!")

Per caricare un raster da un geopackage:

1
2
3
4
5
6
7
8
9
# get the path to a geopackage  e.g. /home/project/data/data.gpkg
path_to_gpkg = os.path.join(os.getcwd(), "testdata", "sublayers.gpkg")
# gpkg_raster_layer = "GPKG:/home/project/data/data.gpkg:srtm"
gpkg_raster_layer = "GPKG:" + path_to_gpkg + ":srtm"

rlayer = QgsRasterLayer(gpkg_raster_layer, "layer name you like", "gdal")

if not rlayer.isValid():
    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 creare un dizionario di stringhe per i parametri di connessione del database. Il dizionario viene poi caricato in un URI vuoto, prima di aggiungere il raster. Notare che None dovrebbe essere usato quando si desidera lasciare il parametro vuoto:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
uri_config = {#
# a dictionary of database parameters
'dbname':'gis_db', # The PostgreSQL database to connect to.
'host':'localhost',     # The host IP address or localhost.
'port':'5432',          # The port to connect on.
'sslmode':'disable',    # The SSL/TLS mode. Options: allow, disable, prefer, require, verify-ca, verify-full
# user and password are not needed if stored in the authcfg or service
'user':None,            # The PostgreSQL user name, also accepts the new WFS provider naming.
'password':None,        # The PostgreSQL password for the user.
'service':None,         # The PostgreSQL service to be used for connection to the database.
'authcfg':'QconfigId',  # The QGIS athentication database ID holding connection details.
# table and raster column details
'schema':'public',      # The database schema that the table is located in.
'table':'my_rasters',   # The database table to be loaded.
'column':'rast',        # raster column in PostGIS table
'mode':'2',             # GDAL 'mode' parameter, 2 union raster tiles, 1 separate tiles (may require user input)
'sql':None,             # An SQL WHERE clause.
'key':None,             # A key column from the table.
'srid':None,            # A string designating the SRID of the coordinate reference system.
'estimatedmetadata':'False', # A boolean value telling if the metadata is estimated.
'type':None,            # A WKT string designating the WKB Type.
'selectatid':None,      # Set to True to disable selection by feature ID.
'options':None,         # other PostgreSQL connection options not in this list.
'connect_timeout':None,
'hostaddr':None,
'driver':None,
'tty':None,
'requiressl':None,
'krbsrvname':None,
'gsslib':None,
}
# configure the URI string with the dictionary
uri = QgsDataSourceUri()
for param in uri_config:
    if (uri_config[param] != None):
        uri.setParam(param, uri_config[param]) # add parameters to the URI

# the raster can now be loaded into the project using the URI string and GDAL data provider
rlayer = iface.addRasterLayer('PG: ' + uri.uri(False), "raster layer name", "gdal")

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

layer_name = 'nurc:mosaic'
uri = "https://demo.geo-solutions.it/geoserver/ows?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=tasmania&styles&url=https://demo.geo-solutions.it/geoserver/ows"
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
2
3
4
5
6
# first add the layer without showing it
QgsProject.instance().addMapLayer(rlayer, False)
# obtain the layer tree of the top-level group in the project
layerTree = iface.layerTreeCanvasBridge().rootGroup()
# the position is a number starting from 0, with -1 an alias for the end
layerTree.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()