5.1 加載矢量圖層(ogr,gpx)

前言

本章講述使用qgis c++ Api加載各種類型的矢量地圖數(shù)據(jù)顯示。

加載矢量(vector)圖層

在QGIS中,圖層并不保存數(shù)據(jù)的實體,而是引用各種類型的數(shù)據(jù)源,并利用圖層樣式等屬性渲染數(shù)據(jù)。

  • QgsVectorLayer代表矢量圖層,首先看一下官方文檔

The QgsVectorLayer is instantiated by specifying the name of a data provider, such as postgres or wfs, and url defining the specific data set to connect to. The vector layer constructor in turn instantiates a QgsVectorDataProvider subclass corresponding to the provider type, and passes it the url. The data provider connects to the data source.

  • 實例化QgsVectorLayer需要提供data provider的名稱以及文件路徑或url,其構(gòu)造函數(shù)如下
QgsVectorLayer (const QString &path=QString(), const QString &baseName=QString(), const QString &providerLib="ogr", const QgsVectorLayer::LayerOptions &options=QgsVectorLayer::LayerOptions())
  • data provider可以指定的值包括:
Provider 說明
ogr OGR提供了一組基于標準的接口和函數(shù)庫,用于處理和操作地理空間數(shù)據(jù)。
delimitedtext 文本數(shù)據(jù)按指定的分隔符進行分割
gpx GPX(GPS eXchange Format,GPS交換格式)是一種用于存儲坐標數(shù)據(jù)的 XML 文件格式
spatialite Spatialite是SQLite數(shù)據(jù)庫的空間數(shù)據(jù)引擎。
memory 數(shù)據(jù)存在內(nèi)存中
postgres POSTGRES是一個對象-關(guān)系型數(shù)據(jù)庫管理系統(tǒng)(ORDBMS)
mssql MSSQL是指微軟的SQLServer數(shù)據(jù)庫服務(wù)器
wfs WFS(Web Feature Service)是一種允許用戶在分布式環(huán)境下通過HTTP對空間數(shù)據(jù)進行增加、刪除、修改、查詢的GIS數(shù)據(jù)服務(wù)
grass GRASS GIS是一個開源的地理信息系統(tǒng),可用于處理柵格、拓撲矢量、影像和圖表數(shù)據(jù)。
  • data provider分兩類,內(nèi)置和外部,外部data provider以動態(tài)庫的形式存在,如下圖


    image.png

以下是完整加載data provider后的輸出

C:\src\OSGeo4W\src\qgis-ltr-dev\qgis\src\core\providers\qgsproviderregistry.cpp(337) : (QgsProviderRegistry::init) [633ms] Loaded 25 providers (OAPIF;WFS;arcgisfeatureserver;arcgismapserver;copc;delimitedtext;ept;gdal;geonode;gpx;hana;mdal;memory;mesh_memory;mssql;ogr;pdal;postgres;postgresraster;spatialite;vectortile;virtual;virtualraster;wcs;wms) 

下邊分別加載不同data provider的數(shù)據(jù)

ogr

Accesses data using the OGR drivers (https://gdal.org/drivers/vector/index.html). The url is the OGR connection string. A wide variety of data formats can be accessed using this driver, including file based formats used by many GIS systems, database formats, and web services. Some of these formats are also supported by custom data providers listed below.
OGR是用于讀寫矢量數(shù)據(jù)的抽象數(shù)據(jù)模型類庫,是GDAL開源項目的一個分支,也采用X/MIT協(xié)議發(fā)布。

  • OGR支持的矢量數(shù)據(jù)格式完整列表見鏈接
  • 常見的矢量數(shù)據(jù)包括Shapefile、KML/KMZ、DXF/DMG、GPX、OSM等多種類型


    image.png

Shapefile

  • 一個Shapefile數(shù)據(jù)僅存儲單一要素類型(如點、線、面)
  • 一個Shapefile只包含一個圖層

QGis導(dǎo)入.shp文件

QGis中打開后綴名為.shp格式的矢量圖層


image.png

代碼導(dǎo)入

  • 傳入文件路徑,圖層名,provider名稱,構(gòu)造QgsVectorLayer
  • 調(diào)用QgsProject的成員函數(shù)addMapLayer即可
void MainWindow::addShpSlot()
{
    QString filename = QStringLiteral("maps/shapefile/protected_areas.shp");
    QFileInfo ff(filename);
    //創(chuàng)建圖層
    QgsVectorLayer* vecLayer = new QgsVectorLayer(filename,ff.baseName(),"ogr");
    if(!vecLayer->isValid())
    {
        QMessageBox::critical(this,tr("error"),tr("invalid layer"));
        return;
    }
    QgsProject::instance()->addMapLayer(vecLayer);
    zoomToFirstLayer<QgsVectorLayer*>();
}
image.png

image.png

gpx

GPX是一種以xml格式記錄的坐標軌跡文件,通常由GPS設(shè)備生成
GPX通常包括航點(Waypoints)、路線(Routes)和軌跡(Tracks)三個主要圖層。

QGis導(dǎo)入GPX文件

不同于Shapefile,GPX文件通常包含多個圖層,在QGis中會提示用戶選擇圖層


image.png

選擇之后,添加圖層


image.png

代碼導(dǎo)入

  • 基本流程和Shapefile一致
  • ==注意:==路徑參數(shù),要通過在文件路徑添加后綴|layername=tracks 如下示例代碼
void MainWindow::addGpxSlot()
{
    QString filename = QStringLiteral("maps/route.gpx");
    QFileInfo ff(filename);
    //創(chuàng)建圖層
    QgsVectorLayer* route_pointsLayer = new QgsVectorLayer(QString("%1%2").arg(filename).arg("|layername=route_points"),"route_points","ogr");
    QgsVectorLayer* routesLayer = new QgsVectorLayer(QString("%1%2").arg(filename).arg("|layername=routes"),"routes","ogr");
    QgsVectorLayer* tracks_pointsLayer = new QgsVectorLayer(QString("%1%2").arg(filename).arg("|layername=track_points"),"track_points","ogr");
    QgsVectorLayer* tracksLayer = new QgsVectorLayer(QString("%1%2").arg(filename).arg("|layername=tracks"),"tracks","ogr");
    QgsVectorLayer* waypointsLayer = new QgsVectorLayer(QString("%1%2").arg(filename).arg("|layername=waypoints"),"waypoints","ogr");
    QList<QgsMapLayer *> mapLayers;
    mapLayers << route_pointsLayer << routesLayer << tracks_pointsLayer << tracksLayer << waypointsLayer;
    QgsProject::instance()->addMapLayers(mapLayers);
    zoomToFirstLayer<QgsVectorLayer*>();
}
image.png
image.png
  • 這樣添加有一個問題,需要事先知道文件包含的圖層名稱,后邊的章節(jié)會講述如何獲取包含的圖層
  • 這里QgsVectorLayer第三個參數(shù)provider傳入的是ogr,也可以傳入gpx,功能相同,但是uri不同,詳情見下章

gpkg

全稱是GeoPackage,是一種開放的、基于標準的、獨立于平臺的、可移植的、自描述的、用于傳輸?shù)乩砜臻g信息的緊湊數(shù)據(jù)格式。

它是一個獨立于平臺的SQLite數(shù)據(jù)庫文件,其中包含矢量要素、不同比例尺的圖像和光柵映射的瓦矩陣集、屬性(非空間數(shù)據(jù))以及擴展機制。

QGis導(dǎo)入GPKG文件

gpkg基于SQLite,一般會存儲多個圖層,在QGis中會提示用戶選擇圖層


image.png
image.png

代碼導(dǎo)入

  • 流程同gpx,示例代碼如下
void MainWindow::addGpkgSlot()
{
    QString filename = QStringLiteral("maps/points_gpkg.gpkg");
    QFileInfo ff(filename);
    //創(chuàng)建圖層
    QgsVectorLayer* points_gpkgLayer = new QgsVectorLayer(QString("%1%2").arg(filename).arg("|layername=points_gpkg"),"points_gpkg","ogr");
    QgsVectorLayer* points_smallLayer = new QgsVectorLayer(QString("%1%2").arg(filename).arg("|layername=points_small"),"points_small","ogr");
    QList<QgsMapLayer *> mapLayers;
    mapLayers << points_gpkgLayer << points_smallLayer;
    QgsProject::instance()->addMapLayers(mapLayers);
    zoomToFirstLayer<QgsVectorLayer*>();
}
image.png
image.png

geojson

包含空間信息的數(shù)據(jù)交換格式,經(jīng)常用于Web服務(wù),進行數(shù)據(jù)交換

QGis導(dǎo)入GeoJson文件

image.png
image.png

代碼導(dǎo)入

  • 流程和Shapefile相同,代碼如下
void MainWindow::addGeoJsonSlot()
{
    QString filename = QStringLiteral("maps/grid_4326.geojson");
    QFileInfo ff(filename);
    QgsVectorLayer* vecLayer = new QgsVectorLayer(filename,ff.baseName(),"ogr");
    if(!vecLayer->isValid())
    {
        QMessageBox::critical(this,tr("error"),tr("invalid layer"));
        return;
    }
    QgsProject::instance()->addMapLayer(vecLayer);
    zoomToFirstLayer<QgsVectorLayer*>();
}
image.png

gml

地理標記語言(GML)是一種用可擴展標記語言(XML)編寫地理信息的方式,以方便地理信息的傳輸和存儲。可以將其視為描述應(yīng)用程序架構(gòu)的XML語法,應(yīng)用程序架構(gòu)描述特定領(lǐng)域或給定上下文中的概念結(jié)構(gòu)。

QGis導(dǎo)入GML

image.png
image.png

代碼導(dǎo)入

void MainWindow::addGmlSlot()
{
    QString filename = QStringLiteral("maps/linedensity.gml");
    QFileInfo ff(filename);
    QgsVectorLayer* vecLayer = new QgsVectorLayer(filename,ff.baseName(),"ogr");
    if(!vecLayer->isValid())
    {
        QMessageBox::critical(this,tr("error"),tr("invalid layer"));
        return;
    }
    QgsProject::instance()->addMapLayer(vecLayer);
    zoomToFirstLayer<QgsVectorLayer*>();
}
image.png

kml/kmz

Keyhole 標記語言 (KML) 是一種基于 XML 的格式,用于存儲地理數(shù)據(jù)和相關(guān)內(nèi)容,是一種官方的開放地理空間聯(lián)盟 (OGC) 標準。 KML 格式便于在 Internet 上發(fā)布并可通過許多免費應(yīng)用程序(例如 Google Earth 和 ArcGIS Explorer)進行查看,因此常用于與非 GIS 用戶共享地理數(shù)據(jù)。 KML 文件以 .kml 或 .kmz(表示壓縮的 KML 文件)為擴展名。

QGis導(dǎo)入Kml

image.png
image.png
image.png

代碼導(dǎo)入

void MainWindow::addKmlSlot()
{
    QString filename = QStringLiteral("maps/multilayer.kml");
    QFileInfo ff(filename);
    //創(chuàng)建圖層
    QgsVectorLayer* layer1 = new QgsVectorLayer(QString("%1%2").arg(filename).arg("|layername=Layer1"),"Layer1","ogr");
    QgsVectorLayer* layer2 = new QgsVectorLayer(QString("%1%2").arg(filename).arg("|layername=Layer2"),"Layer2","ogr");
    QgsVectorLayer* layer3 = new QgsVectorLayer(QString("%1%2").arg(filename).arg("|layername=Layer3"),"Layer3","ogr");
    QList<QgsMapLayer *> mapLayers;
    mapLayers << layer1 << layer2 << layer3;
    QgsProject::instance()->addMapLayers(mapLayers);
    zoomToFirstLayer<QgsVectorLayer*>();
}
image.png

dxf/dwg

DXF 是Autodesk公司開發(fā)的用于AutoCAD與其它軟件之間進行CAD數(shù)據(jù)交換的CAD數(shù)據(jù)文件格式

QGis導(dǎo)入dxf

image.png
image.png
image.png

代碼導(dǎo)入

  • 注意:這里使用了新參數(shù)geometrytype=Pointgeometrytype=LineString
  • 由于layername相同,所以使用geometrytype區(qū)分不同類型圖層
void MainWindow::addDxfSlot()
{
    QString filename = QStringLiteral("maps/points_lines_3d.dxf");
    QFileInfo ff(filename);
    //創(chuàng)建圖層
    QgsVectorLayer* points_gpkgLayer = new QgsVectorLayer(QString("%1%2").arg(filename).arg("|layername=entities|geometrytype=LineString"),"entities1","ogr");
    QgsVectorLayer* points_smallLayer = new QgsVectorLayer(QString("%1%2").arg(filename).arg("|layername=entities|geometrytype=Point"),"entities2","ogr");
    QList<QgsMapLayer *> mapLayers;
    mapLayers << points_gpkgLayer << points_smallLayer;
    QgsProject::instance()->addMapLayers(mapLayers);
    zoomToFirstLayer<QgsVectorLayer*>();
}
image.png

Coverage

Coverage 是一種用于存儲矢量數(shù)據(jù)的地理相關(guān)數(shù)據(jù)模型,它包含地理要素的空間(位置)數(shù)據(jù)和屬性(描述性)數(shù)據(jù)。Coverage 使用一組要素類來表示地理要素。每個要素類存儲一組點、線(?。⒚婊蜃⒂洠ㄎ谋荆?。Coverage 可以具有拓撲,用于確定要素間的關(guān)系。
Coverage 以目錄形式存儲,而目錄中的每個要素類則以一組文件的形式進行存儲。

QGis導(dǎo)入Coverage矢量數(shù)據(jù)

  • 注意: 這里Source Type選的是Directory
    image.png
image.png
image.png

代碼導(dǎo)入

void MainWindow::addCoverageSlot()
{
    QString filename = QStringLiteral("maps/CoverageDir/testvector");
    QFileInfo ff(filename);
    QgsVectorLayer* aaLayer = new QgsVectorLayer(QString("%1%2").arg(filename).arg("|layername=aa"),"aa","ogr");
    QgsVectorLayer* ARCLayer = new QgsVectorLayer(QString("%1%2").arg(filename).arg("|layername=ARC"),"ARC","ogr");
    QgsVectorLayer* CNTLayer = new QgsVectorLayer(QString("%1%2").arg(filename).arg("|layername=CNT"),"CNT","ogr");
    QgsVectorLayer* PALLayer = new QgsVectorLayer(QString("%1%2").arg(filename).arg("|layername=PAL"),"PAC","ogr");
    QList<QgsMapLayer *> mapLayers;
    mapLayers << aaLayer << ARCLayer << CNTLayer << PALLayer;
    QgsProject::instance()->addMapLayers(mapLayers);
    zoomToFirstLayer<QgsVectorLayer*>();
}
image.png

ogr參數(shù)總結(jié)

  • 加載圖層的過程中用到了layerName,geometryType等參數(shù),這里給出ogr支持的所有參數(shù)
  • qgis源碼中qgsogrprovidermetadata.cpp中encodeUri函數(shù)
QString QgsOgrProviderMetadata::encodeUri( const QVariantMap &parts ) const
{
  const QString vsiPrefix = parts.value( QStringLiteral( "vsiPrefix" ) ).toString();
  const QString vsiSuffix = parts.value( QStringLiteral( "vsiSuffix" ) ).toString();
  const QString path = parts.value( QStringLiteral( "path" ) ).toString();
  const QString layerName = parts.value( QStringLiteral( "layerName" ) ).toString();
  const QString layerId = parts.value( QStringLiteral( "layerId" ) ).toString();
  const QString subset = parts.value( QStringLiteral( "subset" ) ).toString();
  const QString geometryType = parts.value( QStringLiteral( "geometryType" ) ).toString();
  const QString authcfg = parts.value( QStringLiteral( "authcfg" ) ).toString();
  const QStringList openOptions = parts.value( QStringLiteral( "openOptions" ) ).toStringList();
  const QString uniqueGeometryType = parts.value( QStringLiteral( "uniqueGeometryType" ) ).toString();
  ......
  }

gpx

Provider reads tracks, routes, and waypoints from a GPX file. The url defines the name of the file, and the type of data to retrieve from it ("track", "route", or "waypoint").
An example url is "/home/user/data/holiday.gpx?type=route"

  • 注意: 這次使用的data provider是gpx

QGis導(dǎo)入gpx

image.png
image.png

代碼導(dǎo)入

  • 注意 uri格式是maps/route.gpx?type=route,并且只支持route,track和waypoint
void MainWindow::addGpx1Slot()
{
    QString filename = QStringLiteral("maps/route.gpx");
    QFileInfo ff(filename);
    QgsVectorLayer* routesLayer = new QgsVectorLayer(QString("%1%2").arg(filename).arg("?type=route"),"route","gpx");
    QgsVectorLayer* tracksLayer = new QgsVectorLayer(QString("%1%2").arg(filename).arg("?type=track"),"track","gpx");
    QgsVectorLayer* waypointsLayer = new QgsVectorLayer(QString("%1%2").arg(filename).arg("?type=waypoint"),"waypoint","gpx");
    QList<QgsMapLayer *> mapLayers;
    mapLayers << routesLayer << tracksLayer << waypointsLayer;
    QgsProject::instance()->addMapLayers(mapLayers);
    zoomToFirstLayer<QgsVectorLayer*>();
}
image.png
image.png

總結(jié)

  • 分別使用qgis軟件和代碼導(dǎo)入了ogr,gpx支持的圖層格式
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容