前言
本章講述使用qgis c++ Api加載各種類型的矢量地圖數(shù)據(jù)顯示。
- 說明:文章中的示例代碼均來自開源項目qgis_cpp_api_apps
加載矢量(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格式的矢量圖層

代碼導(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*>();
}


gpx
GPX是一種以xml格式記錄的坐標軌跡文件,通常由GPS設(shè)備生成
GPX通常包括航點(Waypoints)、路線(Routes)和軌跡(Tracks)三個主要圖層。
QGis導(dǎo)入GPX文件
不同于Shapefile,GPX文件通常包含多個圖層,在QGis中會提示用戶選擇圖層

選擇之后,添加圖層

代碼導(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*>();
}


- 這樣添加有一個問題,需要事先知道文件包含的圖層名稱,后邊的章節(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中會提示用戶選擇圖層


代碼導(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*>();
}


geojson
包含空間信息的數(shù)據(jù)交換格式,經(jīng)常用于Web服務(wù),進行數(shù)據(jù)交換
QGis導(dǎo)入GeoJson文件


代碼導(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*>();
}

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


代碼導(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*>();
}

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



代碼導(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*>();
}

dxf/dwg
DXF 是Autodesk公司開發(fā)的用于AutoCAD與其它軟件之間進行CAD數(shù)據(jù)交換的CAD數(shù)據(jù)文件格式
QGis導(dǎo)入dxf



代碼導(dǎo)入
-
注意:這里使用了新參數(shù)
geometrytype=Point和geometrytype=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*>();
}

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


代碼導(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*>();
}

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


代碼導(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*>();
}


總結(jié)
- 分別使用qgis軟件和代碼導(dǎo)入了ogr,gpx支持的圖層格式


