QGis的使用

QGis的使用QGis 源码 https download qgis org downloads pyqt5 源码 http www riverbankcom com software pyqt download5

大家好,欢迎来到IT知识分享网。

1. QGis编译安装

1.1. Linux下的编译安装

(1)下载源码

(2)ccache

You should also setup ccache to speed up compile times:

or simply add /usr/lib/ccache to your PATH.

(3)编译pyqt5

编译:Ubuntu 14.04 64bit上安装python-pyqt5软件包(python 2.7)

python configure.py --sip-incdir=/usr/include/python2.7 make -j4 sudo make install 

sip版本一致的问题:

sip -V #pythoy import sip print(sip.SIP_VERSION_STR) import PyQt5 print(PyQt5.sip.SIP_VERSION_STR) 

问题:

INCPATH = -I/opt/Qt/5.3/gcc/mkspecs/linux-g++ -I. -I. -I/usr/include/python3.4m -I/opt/Qt/5.3/gcc/include -I/opt/Qt/5.3/gcc/include/QtWebKitWidgets -I/opt/Qt/5.3/gcc/include/QtWebKit -I/opt/Qt/5.3/gcc/include/QtWidgets -I/opt/Qt/5.3/gcc/include/QtNetwork -I/opt/Qt/5.3/gcc/include/QtGui -I/opt/Qt/5.3/gcc/include/QtCore -I. 

修改为:

INCPATH = -I/opt/Qt/5.3/gcc/mkspecs/linux-g++ -I. -I. -I/usr/include/python3.4m -I/opt/Qt/5.3/gcc/include -I/opt/Qt/5.3/gcc/include/QtWebKitWidgets -I/opt/Qt/5.3/gcc/include/QtWebKit -I/opt/Qt/5.3/gcc/include/QtWidgets -I/opt/Qt/5.3/gcc/include/QtNetwork -I/opt/Qt/5.3/gcc/include/QtPrintSupport -I/opt/Qt/5.3/gcc/include/QtGui -I/opt/Qt/5.3/gcc/include/QtCore -I. 

第二种方法:直接在QtWebKitWidgets模块源文件的QtWebKitWidgets.pro文件中加入

QT += printsupport 

接下来执行编译安装:

sudo make sudo make install 

(4)编译qgis

apt-get install bison ca-certificates ccache cmake cmake-curses-gui dh-python doxygen expect flex flip gdal-bin git graphviz grass-dev libexiv2-dev libexpat1-dev libfcgi-dev libgdal-dev libgeos-dev libgsl-dev libpq-dev libproj-dev libprotobuf-dev libqca-qt5-2-dev libqca-qt5-2-plugins libqscintilla2-qt5-dev libqt5opengl5-dev libqt5serialport5-dev libqt5sql5-sqlite libqt5svg5-dev libqt5webkit5-dev libqt5xmlpatterns5-dev libqwt-qt5-dev libspatialindex-dev libspatialite-dev libsqlite3-dev libsqlite3-mod-spatialite libyaml-tiny-perl libzip-dev lighttpd locales ninja-build ocl-icd-opencl-dev opencl-headers pkg-config poppler-utils protobuf-compiler pyqt5-dev pyqt5-dev-tools pyqt5.qsci-dev python3-all-dev python3-autopep8 python3-dateutil python3-dev python3-future python3-gdal python3-httplib2 python3-jinja2 python3-lxml python3-markupsafe python3-mock python3-nose2 python3-owslib python3-plotly python3-psycopg2 python3-pygments python3-pyproj python3-pyqt5 python3-pyqt5.qsci python3-pyqt5.qtsql python3-pyqt5.qtsvg python3-pyqt5.qtwebkit python3-requests python3-sip python3-sip-dev python3-six python3-termcolor python3-tz python3-yaml qt3d-assimpsceneimport-plugin qt3d-defaultgeometryloader-plugin qt3d-gltfsceneio-plugin qt3d-scene2d-plugin qt3d5-dev qt5-default qt5keychain-dev qtbase5-dev qtbase5-private-dev qtpositioning5-dev qttools5-dev qttools5-dev-tools saga spawn-fcgi pandoc xauth xfonts-100dpi xfonts-75dpi xfonts-base xfonts-scalable xvfb 
mkdir BUILD cd BUILD cmake .. make -j8 sudo make install 

(5)qgis_core提示无法解析外部符号

1.2 CMakeList.txt解析

 # 编译版本设置 SET(CPACK_PACKAGE_VERSION_MAJOR "2") …… # Note the version no is Mmmpp for Major/minor/patch, 0-padded, thus '10100' for 1.1.0 MATH(EXPR QGIS_VERSION_INT "${CPACK_PACKAGE_VERSION_MAJOR}*10000+${CPACK_PACKAGE_VERSION_MINOR}*100+${CPACK_PACKAGE_VERSION_PATCH}") MESSAGE(STATUS "QGIS version: ${COMPLETE_VERSION} ${RELEASE_NAME} (${QGIS_VERSION_INT})") # CMake设置 CMAKE_MINIMUM_REQUIRED(VERSION 2.8.6) # CMake最低要求 …… # 配置GRASS插件 FOREACH (GRASS_SEARCH_VERSION 6 7) …… # 下面是各种编译选项 SET (WITH_DESKTOP TRUE CACHE BOOL "Determines whether QGIS desktop should be built") SET (WITH_SERVER FALSE CACHE BOOL "Determines whether QGIS server should be built") …… SET (WITH_CUSTOM_WIDGETS FALSE CACHE BOOL "Determines whether QGIS custom widgets for Qt Designer should be built") SET (WITH_ASTYLE FALSE CACHE BOOL "If you plan to contribute you should reindent with scripts/prepare-commit.sh (using 'our' astyle)") SET (WITH_POSTGRESQL TRUE CACHE BOOL "Determines whether POSTGRESQL support should be built") …… SET (WITH_INTERNAL_QEXTSERIALPORT TRUE CACHE BOOL "Use internal build of Qextserialport") SET (WITH_QSPATIALITE FALSE CACHE BOOL "Determines whether QSPATIALITE sql driver should be built") SET (WITH_ORACLE FALSE CACHE BOOL "Determines whether Oracle support should be built") …… # 如果你需要Python支持,关注这一块 SET (WITH_BINDINGS TRUE CACHE BOOL "Determines whether python bindings should be built") IF (WITH_BINDINGS) …… ENDIF (WITH_BINDINGS) # Android移动端支持 IF (ANDROID) SET (DEFAULT_WITH_QTMOBILITY TRUE) ELSE (ANDROID) SET (DEFAULT_WITH_QTMOBILITY FALSE) ENDIF (ANDROID) SET (WITH_QTMOBILITY ${ 
   DEFAULT_WITH_QTMOBILITY} CACHE BOOL "Determines if QtMobility related code should be build (for example internal GPS)") # globe三维支持 SET (WITH_GLOBE FALSE CACHE BOOL "Determines whether Globe plugin should be built") …… SET (PEDANTIC TRUE CACHE BOOL "Determines if we should compile in pedantic mode.") SET (ENABLE_TESTS TRUE CACHE BOOL "Build unit tests?") SET (ENABLE_COVERAGE FALSE CACHE BOOL "Perform coverage tests?") SET (GENERATE_COVERAGE_DOCS FALSE CACHE BOOL "Generate coverage docs (requires lcov)?") # hide this variable because building of python bindings might fail # if set to other directory than expected MARK_AS_ADVANCED(LIBRARY_OUTPUT_PATH) # 这里是指定编译器类型 IF (MSVC AND CMAKE_GENERATOR MATCHES "NMake") # following variable is also used in qgsconfig.h SET (USING_NMAKE TRUE) ENDIF (MSVC AND CMAKE_GENERATOR MATCHES "NMake") # 这里是Flex和Bison INCLUDE(Flex) FIND_FLEX() IF (NOT FLEX_EXECUTABLE) MESSAGE(FATAL_ERROR "Couldn't find Flex") ENDIF (NOT FLEX_EXECUTABLE) INCLUDE(Bison) FIND_BISON() IF (NOT BISON_EXECUTABLE) MESSAGE(FATAL_ERROR "Couldn't find Bison") ENDIF (NOT BISON_EXECUTABLE) # 下面就开始找依赖库了 IF(NOT WIN32 AND NOT ANDROID) …… # 必须要的依赖库 FIND_PACKAGE(Proj) FIND_PACKAGE(GEOS) FIND_PACKAGE(GDAL) FIND_PACKAGE(Expat REQUIRED) FIND_PACKAGE(Spatialindex REQUIRED) FIND_PACKAGE(Qwt REQUIRED) IF (WITH_INTERNAL_QEXTSERIALPORT) SET(QEXTSERIALPORT_INCLUDE_DIR ${ 
   CMAKE_SOURCE_DIR}/src/core/gps/qextserialport) ELSE (WITH_INTERNAL_QEXTSERIALPORT) FIND_PACKAGE(Qextserialport REQUIRED) ENDIF(WITH_INTERNAL_QEXTSERIALPORT) FIND_PACKAGE(Sqlite3) IF (NOT SQLITE3_FOUND) MESSAGE (SEND_ERROR "sqlite3 dependency was not found!") ENDIF (NOT SQLITE3_FOUND) # 可选的依赖库 IF (WITH_POSTGRESQL) FIND_PACKAGE(Postgres) # PostgreSQL provider ENDIF (WITH_POSTGRESQL) FIND_PACKAGE(SpatiaLite REQUIRED) # spatialite的版本处理 IF(SPATIALITE_VERSION_GE_4_0_0) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DSPATIALITE_VERSION_GE_4_0_0") ENDIF(SPATIALITE_VERSION_GE_4_0_0) IF(SPATIALITE_VERSION_G_4_1_1) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DSPATIALITE_VERSION_G_4_1_1") ENDIF(SPATIALITE_VERSION_G_4_1_1) IF(SPATIALITE_HAS_INIT_EX) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DSPATIALITE_HAS_INIT_EX") ENDIF(SPATIALITE_HAS_INIT_EX) IF (NOT PROJ_FOUND OR NOT GEOS_FOUND OR NOT GDAL_FOUND) MESSAGE (SEND_ERROR "Some dependencies were not found! Proj: ${PROJ_FOUND}, Geos: ${GEOS_FOUND}, GDAL: ${GDAL_FOUND}") ENDIF (NOT PROJ_FOUND OR NOT GEOS_FOUND OR NOT GDAL_FOUND) IF (POSTGRES_FOUND) # following variable is used in qgsconfig.h SET (HAVE_POSTGRESQL TRUE) ENDIF (POSTGRES_FOUND) SET (WITH_QTWEBKIT TRUE CACHE INTERNAL "Enable QtWebkit support") IF (WITH_QTWEBKIT) ADD_DEFINITIONS(-DWITH_QTWEBKIT) ENDIF(WITH_QTWEBKIT) # 找Qt4,如果设置了ENABLE_QT5会尝试去找Qt5,需要用Qt5编译的,关注这里的详细代码 SET(QT_MIN_VERSION 4.8.0) SET (ENABLE_QT5 FALSE CACHE BOOL "If enabled will try to find Qt5 before looking for Qt4") IF (ENABLE_QT5) …… # 下面是模型测试 SET(ENABLE_MODELTEST FALSE CACHE BOOL "Enable QT ModelTest (not for production)") IF (ENABLE_TESTS) …… # C++11的支持 # enable use of c++11 features where available # full c++11 support in clang 3.3+: http://clang.llvm.org/cxx_status.html # for Mac, this is probably Apple LLVM 4.2 (based on LLVM 3.2svn, in XCode 4.6+) # or definitely Apple LLVM 5.0 (based on LLVM 3.3svn, in Xcode 5+): # https://gist.github.com/yamaya/ IF (CMAKE_CXX_COMPILER_ID MATCHES "GNU") EXECUTE_PROCESS(COMMAND ${ 
   CMAKE_CXX_COMPILER} -dumpversion OUTPUT_VARIABLE GCC_VERSION) IF (GCC_VERSION VERSION_GREATER 4.7 OR GCC_VERSION VERSION_EQUAL 4.7) SET(USE_CXX_11 TRUE) SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11") ENDIF() ELSEIF (CMAKE_CXX_COMPILER_ID MATCHES "Clang") IF ((NOT APPLE AND CMAKE_CXX_COMPILER_VERSION VERSION_GREATER "3.2") OR (APPLE AND CMAKE_CXX_COMPILER_VERSION VERSION_GREATER "4.1")) SET(USE_CXX_11 TRUE) SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -Wno-error=c++11-narrowing") ENDIF() ELSEIF (MSVC AND MSVC_VERSION GREATER 1600) SET(USE_CXX_11 TRUE) ELSE() SET(USE_CXX_11 FALSE) ENDIF() #allow override keyword if available IF (NOT USE_CXX_11) ADD_DEFINITIONS("-Doverride=") ADD_DEFINITIONS("-Dnoexcept=") ADD_DEFINITIONS("-Dnullptr=0") ENDIF() # 设置警告信息可用 IF (PEDANTIC) MESSAGE (STATUS "Pedantic compiler settings enabled") IF(MSVC) …… # disable warnings SET(_warnings "${_warnings} /wd4100 ") # unused formal parameters …… ENDIF (PEDANTIC) IF (CMAKE_CXX_COMPILER_ID MATCHES "Clang") …… IF(CMAKE_SYSTEM_PROCESSOR MATCHES "^(powerpc|ppc)") …… IF (CMAKE_BUILD_TYPE MATCHES Debug OR CMAKE_BUILD_TYPE MATCHES RelWithDebInfo) …… IF(MSVC) …… IF(ENABLE_COVERAGE) …… # 操作系统环境指定的一些配置 IF (WIN32) …… IF (MSVC) …… IF (APPLE) …… ENDIF (WIN32) IF (ANDROID) …… # 看一看这里,是配置预编译器选项需要的设置 ADD_DEFINITIONS("-DCORE_EXPORT=${DLLIMPORT}") ADD_DEFINITIONS("-DGUI_EXPORT=${DLLIMPORT}") ADD_DEFINITIONS("-DPYTHON_EXPORT=${DLLIMPORT}") ADD_DEFINITIONS("-DANALYSIS_EXPORT=${DLLIMPORT}") ADD_DEFINITIONS("-DAPP_EXPORT=${DLLIMPORT}") ADD_DEFINITIONS("-DCUSTOMWIDGETS_EXPORT=${DLLIMPORT}") ADD_DEFINITIONS("-DSERVER_EXPORT=${DLLIMPORT}") # 用户可以指定的一些QGIS配置,主要针对安装好的应用程序 # user-changeable settings which can be used to customize # layout of QGIS installation # (default values are platform-specific) SET (QGIS_BIN_SUBDIR ${ 
   DEFAULT_BIN_SUBDIR} CACHE STRING "Subdirectory where executables will be installed") …… # Python的一些依赖 SET (ENABLE_PYTHON3 ${ 
   ENABLE_QT5} CACHE BOOL "If enabled will try to find Python 3 before looking for Python 2") IF(ENABLE_PYTHON3) SET(PYTHON_VER 3 CACHE STRING "Python version") ELSE(ENABLE_PYTHON3) SET(PYTHON_VER 2.7 CACHE STRING "Python version") ENDIF(ENABLE_PYTHON3) FIND_PACKAGE(PythonInterp ${ 
   PYTHON_VER} REQUIRED) # Python bindings IF (WITH_BINDINGS) …… # create qgsconfig.h # installed with app target CONFIGURE_FILE(${ 
   CMAKE_SOURCE_DIR}/cmake_templates/qgsconfig.h.in ${ 
   CMAKE_BINARY_DIR}/qgsconfig.h) INCLUDE_DIRECTORIES(${ 
   CMAKE_BINARY_DIR}) # Added by Jef to prevent python core and gui libs linking to other qgisCore and qgisGui libs # that may be in the same install prefix LINK_DIRECTORIES(${ 
   CMAKE_BINARY_DIR}/src/core ${ 
   CMAKE_BINARY_DIR}/src/gui) # create qgsversion.h IF (EXISTS ${ 
   CMAKE_SOURCE_DIR}/.git/index) …… # 在输出目录中添加一些子文件夹 #create a variable to specify where our test data is #so that unit tests can use TEST_DATA_DIR to locate #the test data. See CMakeLists in test dirs for more info #TEST_DATA_DIR is also used by QgsRenderChecker currently in core SET (TEST_DATA_DIR "${CMAKE_CURRENT_SOURCE_DIR}/tests/testdata") ADD_SUBDIRECTORY(src) ADD_SUBDIRECTORY(doc) ADD_SUBDIRECTORY(images) ADD_SUBDIRECTORY(resources) ADD_SUBDIRECTORY(i18n) IF (WITH_BINDINGS) ADD_SUBDIRECTORY(python) ENDIF (WITH_BINDINGS) IF (ENABLE_TESTS) ADD_SUBDIRECTORY(tests) SET (CTEST_BINARY_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/output/bin" ) MESSAGE (STATUS "Ctest Binary Directory set to: ${CTEST_BINARY_DIRECTORY}") ENDIF (ENABLE_TESTS) IF (APPLE) …… INSTALL(FILES cmake/FindQGIS.cmake DESTINATION ${ 
   QGIS_DATA_DIR}) # Post-install commands ADD_SUBDIRECTORY(postinstall) # Uninstall stuff see: http://www.vtk.org/Wiki/CMake_FAQ CONFIGURE_FILE( …… # Enable packaging …… 

QGis的使用 1.3 kylin-v10安装 QGis的使用

kylin@kylin-pc:~$ sudo apt-get install qgis
正在读取软件包列表... 完成
正在分析软件包的依赖关系树       
正在读取状态信息... 完成       
下列软件包是自动安装的并且现在不需要了:
  archdetect-deb dmeventd libaio1 libdebian-installer4 libdevmapper-event1.02.1 liblvm2cmd2.03 localechooser-data lvm2 user-setup
使用'sudo apt autoremove'来卸载它(它们)。
将会同时安装下列软件:
  fonts-lyx gdal-bin libassimp5 libclang1-10 libfcgi0ldbl libjs-jquery-ui libjs-leaflet libllvm10 libqca-qt5-2 libqca-qt5-2-plugins libqgis-3d3.10.4 libqgis-analysis3.10.4 libqgis-app3.10.4 libqgis-core3.10.4 libqgis-customwidgets
  libqgis-gui3.10.4 libqgis-native3.10.4 libqgis-server3.10.4 libqgispython3.10.4 libqscintilla2-qt5-15 libqscintilla2-qt5-l10n libqt53danimation5 libqt53dcore5 libqt53dextras5 libqt53dinput5 libqt53dlogic5 libqt53dquickscene2d5
  libqt53drender5 libqt5designercomponents5 libqt5keychain1 libqt5serialport5 libqwt-qt5-6 libspatialindex6 libsqlite3-mod-spatialite libzip5 python-matplotlib-data python3-attr python3-cycler python3-future python3-gdal
  python3-importlib-metadata python3-ipython-genutils python3-jsonschema python3-jupyter-core python3-kiwisolver python3-matplotlib python3-more-itertools python3-nbformat python3-numpy python3-owslib python3-plotly python3-psycopg2
  python3-pygments python3-pyparsing python3-pyproj python3-pyqt5.qsci python3-pyqt5.qtsql python3-pyqt5.qtsvg python3-pyqt5.qtwebkit python3-pyrsistent python3-qgis python3-qgis-common python3-retrying python3-traitlets python3-zipp
  qdoc-qt5 qgis-common qgis-providers qgis-providers-common qhelpgenerator-qt5 qt3d-assimpsceneimport-plugin qt3d-defaultgeometryloader-plugin qt3d-gltfsceneio-plugin qt3d-scene2d-plugin qt5-assistant qtattributionsscanner-qt5 qtchooser
  qttools5-dev-tools ttf-bitstream-vera
建议安装:
  libgdal-grass libjs-jquery-ui-docs libqscintilla2-doc python-attr-doc python-cycler-doc python-future-doc python-jsonschema-doc python3-pip dvipng inkscape ipython3 python-matplotlib-doc python3-cairocffi python3-gobject python3-nose
  python3-scipy python3-tornado texlive-extra-utils texlive-latex-extra ttf-staypuft gfortran python-numpy-doc python3-dev python3-pytest python3-numpy-dbg owslib-doc python3-pandas python3-ipykernel python-psycopg2-doc
  python-pygments-doc python-pyparsing-doc otb-qgis saga gpsbabel qt5-doc
推荐安装:
  libfcgi-bin javascript-common python3-tk qgis-plugin-grass
下列【新】软件包将被安装:
  fonts-lyx gdal-bin libassimp5 libclang1-10 libfcgi0ldbl libjs-jquery-ui libjs-leaflet libllvm10 libqca-qt5-2 libqca-qt5-2-plugins libqgis-3d3.10.4 libqgis-analysis3.10.4 libqgis-app3.10.4 libqgis-core3.10.4 libqgis-customwidgets
  libqgis-gui3.10.4 libqgis-native3.10.4 libqgis-server3.10.4 libqgispython3.10.4 libqscintilla2-qt5-15 libqscintilla2-qt5-l10n libqt53danimation5 libqt53dcore5 libqt53dextras5 libqt53dinput5 libqt53dlogic5 libqt53dquickscene2d5
  libqt53drender5 libqt5designercomponents5 libqt5keychain1 libqt5serialport5 libqwt-qt5-6 libspatialindex6 libsqlite3-mod-spatialite libzip5 python-matplotlib-data python3-attr python3-cycler python3-future python3-gdal
  python3-importlib-metadata python3-ipython-genutils python3-jsonschema python3-jupyter-core python3-kiwisolver python3-matplotlib python3-more-itertools python3-nbformat python3-numpy python3-owslib python3-plotly python3-psycopg2
  python3-pygments python3-pyparsing python3-pyproj python3-pyqt5.qsci python3-pyqt5.qtsql python3-pyqt5.qtsvg python3-pyqt5.qtwebkit python3-pyrsistent python3-qgis python3-qgis-common python3-retrying python3-traitlets python3-zipp
  qdoc-qt5 qgis qgis-common qgis-providers qgis-providers-common qhelpgenerator-qt5 qt3d-assimpsceneimport-plugin qt3d-defaultgeometryloader-plugin qt3d-gltfsceneio-plugin qt3d-scene2d-plugin qt5-assistant qtattributionsscanner-qt5
  qtchooser qttools5-dev-tools ttf-bitstream-vera
升级了 0 个软件包,新安装了 80 个软件包,要卸载 0 个软件包,有 456 个软件包未被升级。
需要下载 138 MB 的归档。
解压缩后会消耗 541 MB 的额外空间。
您希望继续执行吗? [Y/n]   

2. 使用

2.1 添加xyz源

能用的:

//高德
https://webst01.is.autonavi.com/appmaptile?style=6&x={x}&y={y}&z={z}
//google无标注
http://gac-geo.googlecnapps.cn/maps/vt?lyrs=s&x={x}&y={y}&z={z}
//google有标注
http://gac-geo.googlecnapps.cn/maps/vt?lyrs=s,m&gl=CN&x={x}&y={y}&z={z}
//google map
http://gac-geo.googlecnapps.cn/maps/vt/lyrs=r&x={x}&y={y}&z={z} //替换能用的
//OSM(OpenStreetMap)
http://a.tile.openstreetmap.org/{z}/{x}/{y}.png

google的地址解析:

https://mt{num}.google.com/vt?lyrs={lyrs}&x={x}&y={y}&z={z}&hl={hl}&gl={gl}
https://mt2.google.com/vt?lyrs=s,m&x=1083&y=1666&z=12&hl=zh&gl=cn

a) num不同服务器,范围为 0,1,2,3
b) lyrs地图类型:
	m:路线图
	t:地形图
	p:带标签的地形图
	s:卫星图
	y:带标签的卫星图
	h:标签层(路名、地名等)
	地图类型可以组合使用,中间使用,(英文逗号)分割
c) hl: host language(interface languages) 本地语言
	比如 zh-CN,zh-TW,en
d) gl: 国家码(country code)
	比如 cn us
e) x y z 

lyrs为瓦片类型:m-路线图,t-地形图,p-带标签的地形图,s-卫星图,y-带标签的卫星图,h-标签层(路名、地名)

Google Maps: 
https://mt1.google.com/vt/lyrs=r&x={x}&y={y}&z={z} //不能用
http://gac-geo.googlecnapps.cn/maps/vt/lyrs=r&x={x}&y={y}&z={z} //替换能用的
Google Satellite: 
http://www.google.cn/maps/vt?lyrs=s@189&gl=cn&x={x}&y={y}&z={z}
Google Satellite Hybrid: 
https://mt1.google.com/vt/lyrs=y&x={x}&y={y}&z={z}
Google Terrain: 
https://mt1.google.com/vt/lyrs=t&x={x}&y={y}&z={z}
Google Roads: 
https://mt1.google.com/vt/lyrs=h&x={x}&y={y}&z={z}


OpenTopoMap
https://tile.opentopomap.org/{z}/{x}/{y}.png
OpenStreetMap
http://tile.openstreetmap.org/{z}/{x}/{y}.png
Google Hybrid
https://mt1.google.com/vt/lyrs=y&x={x}&y={y}&z={z}
Google Satellite
https://mt1.google.com/vt/lyrs=s&x={x}&y={y}&z={z}
Google Road
https://mt1.google.com/vt/lyrs=m&x={x}&y={y}&z={z}
Bing Aerial
http://ecn.t3.tiles.virtualearth.net/tiles/a{q}.jpeg?g=1
高德卫星影像
https://webst01.is.autonavi.com/appmaptile?style=6&x={x}&y={y}&z={z}
高德路网
https://wprd01.is.autonavi.com/appmaptile?x={x}&y={y}&z={z}&lang=zh_cn&size=1&scl=2&style=8&ltype=11


//---------------------
Google_Maps: https://mt1.google.com/vt/lyrs=r&x={x}&y={y}&z={z}
Google_Terrain: https://mt1.google.com/vt/lyrs=t&x={x}&y={y}&z={z}
Google_Roads:https://mt1.google.com/vt/lyrs=h&x={x}&y={y}&z={z}
Google_Satellite: https://mt1.google.com/vt/lyrs=s&x={x}&y={y}&z={z}
Google_Streets:https://mt1.google.com/vt/lyrs=m&x={x}&y={y}&z={z}

cartocdn_dark_nolabel:http://basemaps.cartocdn.com/dark_nolabels/{z}/{x}/{y}.png
cartocdn_light_nolabels:http://basemaps.cartocdn.com/light_nolabels/{z}/{x}/{y}{r}.png
cartocdn_voyager_nolabels:https://basemaps.cartocdn.com/rastertiles/voyager_nolabels/{z}/{x}/{y}.png

ESRI_World_Imagery:https://server.arcgisonline.com/ArcGIS/rest/services/World_Imagery/MapServer/tile/{z}/{y}/{x}
ESRI_World_Light_Gray_Base:https://server.arcgisonline.com/ArcGIS/rest/services/Canvas/World_Light_Gray_Base/MapServer/tile/{z}/{y}/{x}
ESRI_World_Topo_Map:https://server.arcgisonline.com/ArcGIS/rest/services/World_Topo_Map/MapServer/tile/{z}/{y}/{x}

memomaps_tilegen:http://tileserver.memomaps.de/tilegen/{z}/{x}/{y}.png

openstreetmap:https://tile.openstreetmap.org/{z}/{x}/{y}.png
openstreetmap_br:https://tile.openstreetmap.bzh/br/{z}/{x}/{y}.png
openstreetmap_cyclosm:https://a.tile-cyclosm.openstreetmap.fr/cyclosm/{z}/{x}/{y}.png
openstreetmap_hot:https://a.tile.openstreetmap.fr/hot/{z}/{x}/{y}.png

stamen_terrain:http://a.tile.stamen.com/terrain/{z}/{x}/{y}.png
stamen_terrain_background:http://a.tile.stamen.com/terrain-background/{z}/{x}/{y}.png
stamen_terrain(高清):http://a.tile.stamen.com/terrain/{z}/{x}/{y}@2x.png
stamen_watercolor:https://stamen-tiles-c.a.ssl.fastly.net/watercolor/{z}/{x}/{y}.jpg
staman水彩图:http://a.tile.stamen.com/watercolor/{z}/{x}/{y}.jpg

thunderforest_cycle:https://tile.thunderforest.com/cycle/{z}/{x}/{y}.png?apikey=
thunderforest_pioneer:https://tile.thunderforest.com/pioneer/{z}/{x}/{y}.png?apikey=

wmflabs_bw_mapnik:http://tiles.wmflabs.org/bw-mapnik/{z}/{x}/{y}.png

高德:https://blog.csdn.net/ldlzhy1984/article/details/81015180
https://blog.csdn.net/fredricen/article/details/77189453
高德矢量图:https://webrd02.is.autonavi.com/appmaptile?lang=zh_cn&size=1&scale=1&style=8&x={x}&y={y}&z={z}
高德遥感图:http://webst02.is.autonavi.com/appmaptile?style=6&x={x}&y={y}&z={z}



Mapbox底图:https://api.mapbox.com/styles/v1/mapbox/streets-v10/tiles/256/{z}/{x}/{y}?access_token=<mapbox key>

天地图矢量图:https://t6.tianditu.gov.cn/vec_w/wmts?SERVICE=WMTS&REQUEST=GetTile&VERSION=1.0.0&LAYER=vec&STYLE=default&TILEMATRIXSET=w&FORMAT=tiles&TILECOL={x}&TILEROW={y}&TILEMATRIX={z}&tk=<tianditu key>
天地图矢量注记:https://t2.tianditu.gov.cn/cva_w/wmts?SERVICE=WMTS&REQUEST=GetTile&VERSION=1.0.0&LAYER=cva&STYLE=default&TILEMATRIXSET=w&FORMAT=tiles&TILECOL={x}&TILEROW={y}&TILEMATRIX={z}&tk=<tianditu key>
天地图遥感图:https://t3.tianditu.gov.cn/img_w/wmts?SERVICE=WMTS&REQUEST=GetTile&VERSION=1.0.0&LAYER=img&STYLE=default&TILEMATRIXSET=w&FORMAT=tiles&TILECOL={x}&TILEROW={y}&TILEMATRIX={z}&tk=<tianditu key>
天地图遥感注记:https://t2.tianditu.gov.cn/cia_w/wmts?SERVICE=WMTS&REQUEST=GetTile&VERSION=1.0.0&LAYER=cia&STYLE=default&TILEMATRIXSET=w&FORMAT=tiles&TILECOL={x}&TILEROW={y}&TILEMATRIX={z}&tk=<tianditu key>

WMTS:
Mapbox:https://api.mapbox.com/styles/v1/mapbox/streets-v11/wmts?access_token=<mapbox key>

WFS:
天地图:http://gisserver.tianditu.gov.cn/TDTService/wf

2.2 画图

QGis画各种图

3. 二次开发

QT       += core gui xml

greaterThan(QT_MAJOR_VERSION, 4): QT += widgets

TARGET = qgisdemo
TEMPLATE = app


SOURCES += main.cpp# \
    #mainwindow.cpp

#INCLUDEPATH += qgis-2.4.0
#INCLUDEPATH += qgis-2.4.0\core
#INCLUDEPATH += qgis-2.4.0\core\symbology-ng
#INCLUDEPATH += qgis-2.4.0\analysis
#INCLUDEPATH += qgis-2.4.0\gui

INCLUDEPATH += qgis-2.4.0
INCLUDEPATH += qgis-2.4.0/core
INCLUDEPATH += qgis-2.4.0/core/symbology-ng
INCLUDEPATH += qgis-2.4.0/analysis
INCLUDEPATH += qgis-2.4.0/gui


FORMS    += mainwindow.ui

win32:CONFIG(release, debug|release): LIBS += -L$$PWD/lib/ -llibqgis_analysis
else:win32:CONFIG(debug, debug|release): LIBS += -L$$PWD/lib/ -llibqgis_analysis
else:unix:!macx: LIBS += -L$$PWD/lib/ -llibqgis_analysis

INCLUDEPATH += $$PWD/
DEPENDPATH += $$PWD/

win32:CONFIG(release, debug|release): LIBS += -L$$PWD/lib/ -llibqgis_core
else:win32:CONFIG(debug, debug|release): LIBS += -L$$PWD/lib/ -llibqgis_core
else:unix:!macx: LIBS += -L$$PWD/lib/ -llibqgis_core

INCLUDEPATH += $$PWD/
DEPENDPATH += $$PWD/

win32:CONFIG(release, debug|release): LIBS += -L$$PWD/lib/ -llibqgis_gui
else:win32:CONFIG(debug, debug|release): LIBS += -L$$PWD/lib/ -llibqgis_gui
else:unix:!macx: LIBS += -L$$PWD/lib/ -llibqgis_gui

INCLUDEPATH += $$PWD/
DEPENDPATH += $$PWD/
-----------------------------------
Qt4.8.6+mingw+Qgis2.4.0基于QGis的二次开发
https://blog.51cto.com/u_15127553/4237274
#include <QApplication>
#include <QString>
#include <QWidget>
#include <qgis.h>
#include <qgsapplication.h>
#include <qgsproviderregistry.h>
#include <qgssinglesymbolrendererv2.h>
#include <qgsmaplayerregistry.h>
#include <qgsvectorlayer.h>
#include <qgsmapcanvas.h>
#include <qgsgeometry.h>
#include "mouseprocess.h"
#include "paintprocess.h"
int main( int argc, char *argv[] )
{ 
     
	QgsApplication a( argc, argv ,true);
	//
	//注意这三行代码须要更改路径;
	QString myPluginsDir        ="D:/Qt/workspace/qgis-2.4.0/qgis-2.4.0/build/output/plugins";//插件路径(编译好的qgis目录下的plugins目录);
	QString myLayerPath1         ="F:/gis/data_1_3/10m_admin_0_countries.shp";//图层路径,必须设置为你电脑里面shp文件的路径,不然打不开数据;
	QString myLayerPath2         ="F:/gis/qgis_sample_data/shapefiles/airports.shp";//图层路径,必须设置为你电脑里面shp文件的路径,不然打不开数据;
	//

	QgsProviderRegistry::instance( myPluginsDir); //初始化插件的文件夹;
	QgsVectorLayer * mypLayer1 = new QgsVectorLayer( myLayerPath1, "myLayer1", "ogr" ); //初始化矢量图层;
	QgsVectorLayer * mypLayer2 = new QgsVectorLayer( myLayerPath2, "myLayer2", "ogr" ); //初始化矢量图层;
	QgsVectorLayer * mypLayer3 = new QgsVectorLayer(); //初始化矢量图层;
	mypLayer3->setRendererV2(QgsFeatureRendererV2::defaultRenderer(QGis::Point));
	QgsFeatureIterator iter = mypLayer2->getFeatures();
	QgsFeature feature;
	while(iter.nextFeature(feature))
	{ 
     
		QgsGeometry *geo = feature.geometry();
		QgsPoint point = geo->asPoint();
		//qDebug() << point.x() << point.y() << endl;
	}
	for(int index = 0; index < 100; index ++)
	{ 
     
		QgsPoint point;
		double xmin = -4.4802e+06;
		double xmax = 4.61512e+06;
		double ymin = 1.43353e+06;
		double ymax = 6.50259e+06;
		point.setX(xmin + (xmax - xmin) * ((double) qrand()) / RAND_MAX);
		point.setY(ymin + (ymax - ymin) * ((double) qrand()) / RAND_MAX);
		QgsFeature feature;
		QgsGeometry *geo = QgsGeometry::fromPoint(point);
		feature.setGeometry(geo);
		mypLayer3->addFeature(feature);
		mypLayer3->updateFeature(feature);
		qDebug() << point.x() << point.y() << endl;
	}
	QList<QgsPoint> ring;
	//-4.4802e+06 4.61512e+06 1.43353e+06 6.50259e+06
	ring.append(QgsPoint(-4.4802e+06, 1.43353e+06));
	ring.append(QgsPoint(4.61512e+06, 6.50259e+06));
	ring.append(QgsPoint(2.61512e+06, 4.50259e+06));
	//mypLayer2->addRing(ring);
	qDebug() << mypLayer2->featureCount() << endl;
	//QgsSingleSymbolRendererV2 *mypRenderer = new QgsSingleSymbolRendererV2( mypLayer->geometryType() );
	QList <QgsMapCanvasLayer> myLayerSet;
	// mypLayer->setRenderer( mypRenderer );
	//mypLayer->setRendererV2(mypRenderer);
	QgsMapLayerRegistry::instance()->addMapLayer( mypLayer1, true );
	QgsMapLayerRegistry::instance()->addMapLayer( mypLayer2, true );
	QgsMapLayerRegistry::instance()->addMapLayer( mypLayer3, true );
	//myLayerSet.append( QgsMapCanvasLayer(mypLayer3, true ) );
	myLayerSet.append( QgsMapCanvasLayer(mypLayer2, true ) );
	//myLayerSet.append( QgsMapCanvasLayer(mypLayer1, true ) );
	QgsRectangle extent = mypLayer2->extent();
	qDebug() << extent.xMinimum() << extent.xMaximum() << extent.yMinimum() << extent.yMaximum() << endl;
	QgsMapCanvas * mypMapCanvas = new QgsMapCanvas( 0, 0 );
	mypMapCanvas->setExtent(mypLayer2->extent() );
	mypMapCanvas->enableAntiAliasing( true);
	mypMapCanvas->setCanvasColor( QColor(255, 255, 255 ) );
	mypMapCanvas->freeze( false );
	mypMapCanvas->setLayerSet( myLayerSet);
	mypMapCanvas->setVisible( true );
	mypMapCanvas->refresh();
	mypMapCanvas->show();
	MouseProcess *mouseProcess = new MouseProcess();
	PaintProcess *paintProcess = new PaintProcess();
	QObject::connect(mypMapCanvas, SIGNAL(xyCoordinates(QgsPoint)), 
					 mouseProcess, SLOT(xyCoordinates(QgsPoint)));
	QObject::connect(mypMapCanvas, SIGNAL(renderComplete(QPainter*)), 
					 paintProcess, SLOT(renderComplete(QPainter*)));

	return a.exec();
}
//pro中引入 qgis_core.lib qgis_gui.lib
#include "mainwindow.h"
#include <qgsapplication.h>
int main(int argc char *argv[])
{ 
     
	QgsApplication a(argc, argv, true);
	QgsApplication::setPrefixPath("C:/OSGeo4W64/apps/qgis", true);
	QgsApplication::initQgis();
	MainWindow w;
	w.show();
	return a.exec();
}

// maiwindow.cpp
#include <qgsproject.h>
#include <qgsvectorlayer.h>
#include <qgseditorwidgetregistry.h>

mapCanvas = new QgsMapCanvas(this);
ui->verticalLayout->addWidget(mapCanvas);

QString str = QString("d:/course/test.qgz");
QgsProject::instance()->read(str);
QVector<QgsVectorLayer*> vecLayers = QgsProject::instance()->layers<QgsVectorLayer*>();
qDebug()<<vecLayers.count();

//QList<QgsMapLayer*> layers;
//layers.append(vecLayers[0]);
//mapCanvas->setLayers(layers);

QgsEditorWidgetRegistry a;
a.initEditors(mapCanvas);
bridge = new QgsLayerTreeMapCanvasBridge(QgsProject::instance()->layerTreeRoot(), mapCanvas, this);


4. 源码解析

在这里插入图片描述

4.1 源码目录

文件名 说明
ci
cmake 工程组织说明文件,主要是依赖库的配置说明
cmake_templates cmake模板文件
debian Linux操作系统所需
doc 帮助文档
!18n 翻译所需文件
images 图片资源文件
mac 苹果Mac操作系统所需
ms-windows 微软Windows操作系统所需
postinstall 软件安装完成之后执行的脚本操作
python python脚本支持
resources 各种资源、配置文件
rpm 默认配置文件
scripts 各种脚本
src 源代码,这个是我们关注的重点
tests 各种测试代码
tools 目前这里面只有一个Qt3迁移到Qt4的工具

src文件夹下的主要内容:

文件名 说明
3d 3d要用的
analysis 工程组织说明文件,主要是依赖库的配置说明
app cmake模板文件
auth Linux操作系统所需
core 帮助文档
crashhandler 翻译所需文件
crssync 图片资源文件
customwidgets 苹果Mac操作系统所需
gui 微软Windows操作系统所需
native 软件安装完成之后执行的脚本操作
plugins python脚本支持
process 各种资源、配置文件
providers 默认配置文件
python 各种脚本
quickgui 源代码,这个是我们关注的重点
server 各种测试代码
test 各种测试代码
ui 目前这里面只有一个Qt3迁移到Qt4的工具
/app/main.cpp    			主程序
/app/qgisapp.cpp			主窗体

/core/qgsmaplayer.cpp		图层类QgsMapLayer
/core/qgsmaptopixel.cpp		转像素坐标QgsMapToPixel
/core/qgstiledownloadmanager.cpp 瓦片下载管理
/core/vectortile/qgsvectortileloader.cpp		矢量瓦片加载
/core/vectortile/qgsvectortilelayer.cpp			矢量瓦片图层
/core/vectortile/qgsvectortilebasicrenderer.cpp 矢量瓦片渲染
/core/network/qgsblockingnetworkrequest.cpp

/gui/qgsbrowserdockwidget.cpp	浏览Dock窗体QgsBrowserDockWidget
/gui/qgsbrowserwidget.cpp		浏览Dock中的主窗体
/gui/qgslayertreeview.cpp		图层树控件
/gui/qgsmapcanvas.cpp			地图画布QgsMapCanvas
/gui/qgsmapcanvasitem.cpp		item类 QgsMapCanvasItem
 QgsDockWidget *mLayerTreeDock		//图层的DockWidget
 QgsStatusBar  *mStatusBar			//状态栏
//鼠标坐标的实时显示的流程(从canvas到edit)
QgsMapCanvas::mouseMoveEvent( QMouseEvent *e )
	mCursorPoint = getCoordinateTransform()->toMapCoordinates( mCanvasProperties->mouseLastXY );
    emit xyCoordinates( mCursorPoint );
QgsStatusBarCoordinatesWidget::setMapCanvas( QgsMapCanvas *mapCanvas )
	connect( mMapCanvas, &QgsMapCanvas::xyCoordinates, this, &QgsStatusBarCoordinatesWidget::showMouseCoordinates );
  	connect( mMapCanvas, &QgsMapCanvas::extentsChanged, this, &QgsStatusBarCoordinatesWidget::showExtent );
QgsStatusBarCoordinatesWidget::showMouseCoordinates( const QgsPointXY &p )
  	mLastCoordinate = p;
  	updateCoordinateDisplay();
QgsStatusBarCoordinatesWidget::updateCoordinateDisplay()
    mLineEdit->setText( QgsCoordinateUtils::formatCoordinateForProject( QgsProject::instance(), mLastCoordinate, mMapCanvas->mapSettings().destinationCrs(),
                        static_cast< int >( mMousePrecisionDecimalPlaces ) ) );

4.2 主程序main()

位置:/src/app/main.cpp

//这是基于MainWindow的
QgisApp *qgis = new QgisApp( mypSplash, myRestorePlugins, mySkipBadLayers, mySkipVersionCheck, rootProfileFolder, profileName ); 
qgis->show();
qgis->completeInitialization();

4.3 图层操作

qgis图层操作源码

/* * +--------+ +------+ +---------+ * | DATA | | RAW | | DECODED | * | | --> LOADER --> | | --> DECODER --> | | --> RENDERER * | SOURCE | | TILE | | TILE | * +--------+ +------+ +---------+ * QgsVectorTileLoader QgsVectorTileDecoder QgsVectorTileBasicRenderer * * Data source is a place from where tiles are fetched from (URL for HTTP access, local * files, MBTiles file, GeoPackage file or others. Loader (QgsVectorTileLoader) class * takes care of loading data from the data source. The "raw tile" data is just a blob * (QByteArray) that is encoded in some way. There are multiple ways how vector tiles * are encoded just like there are different formats how to store images. For example, * tiles can be encoded using Mapbox Vector Tiles (MVT) format or in GeoJSON. Decoder * (QgsVectorTileDecoder) takes care of decoding raw tile data into QgsFeature objects. * A decoded tile is essentially an array of vector features for each sub-layer found * in the tile - this is what vector tile renderer (QgsVectorTileRenderer) expects * and does the map rendering. */
/core/vector/qgsvectorlayer.h   矢量图层
/core/vectortile/qgsvectortilelayer.cpp		矢量瓦片图层
QgsVectorTileLayerRenderer::render()
{ 
     

}

4.5 瓦片下载

//底层请求(最终调用)------
QgsTileDownloadManagerReply *QgsTileDownloadManager::get( const QNetworkRequest &request )
{ 
     
	QgsTileDownloadManager::QueueEntry entry = findEntryForRequest( request );
	if ( !entry.isValid() )
	{ 
     
		QgsDebugMsgLevel( QStringLiteral( "Tile download manager: get (new entry): " ) + request.url().toString(), 2 );
		// create a new entry and add it to queue
		entry.request = request;
		entry.objWorker = new QgsTileDownloadManagerReplyWorkerObject( this, request );
		entry.objWorker->moveToThread( mWorkerThread );
		
		QObject::connect( entry.objWorker, &QgsTileDownloadManagerReplyWorkerObject::finished, reply, &QgsTileDownloadManagerReply::requestFinished ); 
	}
}
QgsMapToolIdentify::identify( const QgsGeometry &geometry, IdentifyMode mode, const QList<QgsMapLayer *> &layerList, LayerType layerType, const QgsIdentifyContext &identifyContext )
{ 
     
	for ( int i = 0; i < layerCount; i++ )
    { 
     
	    QgsMapLayer *layer = targetLayers.value( i );
	    if ( identifyLayer( &results, layer,  mLastGeometry, mLastExtent, mLastMapUnitsPerPixel, layerType, identifyContext ) )
	    { 
     
	    	if ( mode == TopDownStopAtFirst )
	       		break;
	    }
    }
}
QgsMapToolIdentify::identifyLayer( QList<IdentifyResult> *results, QgsMapLayer *layer, const QgsGeometry &geometry, const QgsRectangle &viewExtent, double mapUnitsPerPixel, QgsMapToolIdentify::LayerType layerType, const QgsIdentifyContext &identifyContext )
{ 
     
	if ( layer->type() == QgsMapLayerType::RasterLayer && layerType.testFlag( RasterLayer ) )
	{ 
     
	  	return identifyRasterLayer( results, qobject_cast<QgsRasterLayer *>( layer ), geometry, viewExtent, mapUnitsPerPixel, identifyContext );
	}
	else if ( layer->type() == QgsMapLayerType::VectorLayer && layerType.testFlag( VectorLayer ) )
	{ 
     
	  	return identifyVectorLayer( results, qobject_cast<QgsVectorLayer *>( layer ), geometry, identifyContext );
	}
	else if ( layer->type() == QgsMapLayerType::MeshLayer && layerType.testFlag( MeshLayer ) )
	{ 
     
	  	return identifyMeshLayer( results, qobject_cast<QgsMeshLayer *>( layer ), geometry, identifyContext );
	}
	else if ( layer->type() == QgsMapLayerType::VectorTileLayer && layerType.testFlag( VectorTileLayer ) )
	{ 
     
	  	return identifyVectorTileLayer( results, qobject_cast<QgsVectorTileLayer *>( layer ), geometry, identifyContext );
	}
	else if ( layer->type() == QgsMapLayerType::PointCloudLayer && layerType.testFlag( PointCloudLayer ) )
	{ 
     
	  	return identifyPointCloudLayer( results, qobject_cast<QgsPointCloudLayer *>( layer ), geometry, identifyContext );
	}
	else
	{ 
     
	  	return false;
	}
}
QgsMapToolIdentify::identifyVectorTileLayer( QList<QgsMapToolIdentify::IdentifyResult> *results, QgsVectorTileLayer *layer, const QgsGeometry &geometry, const QgsIdentifyContext &identifyContext )
{ 
     
	const int tileZoom = layer->tileMatrixSet().scaleToZoomLevel( mCanvas->scale() );
	const QgsTileMatrix tileMatrix = layer->tileMatrixSet().tileMatrix( tileZoom );
	const QgsTileRange tileRange = tileMatrix.tileRangeFromExtent( r );
	
	for ( int row = tileRange.startRow(); row <= tileRange.endRow(); ++row )
	{ 
     
		for ( int col = tileRange.startColumn(); col <= tileRange.endColumn(); ++col )
	  	{ 
     
	    	QgsTileXYZ tileID( col, row, tileZoom );
	    	QByteArray data = layer->getRawTile( tileID );	//图层获取瓦片(见下)
	    	if ( data.isEmpty() )
	      		continue;  // failed to get data
	
	    	QgsVectorTileMVTDecoder decoder( layer->tileMatrixSet() );
	    	if ( !decoder.decode( tileID, data ) )
	      		continue;  // failed to decode
	
	   	 	QMap<QString, QgsFields> perLayerFields;
	    	const QStringList layerNames = decoder.layers();
	    	for ( const QString &layerName : layerNames )
	    	{ 
     
	      		QSet<QString> fieldNames = qgis::listToSet( decoder.layerFieldNames( layerName ) );
	      		perLayerFields[layerName] = QgsVectorTileUtils::makeQgisFields( fieldNames );
	    	}
	
	    	const QgsVectorTileFeatures features = decoder.layerFeatures( perLayerFields, QgsCoordinateTransform() );
	    	const QStringList featuresLayerNames = features.keys();
	    	for ( const QString &layerName : featuresLayerNames )
	    	{ 
     
	      		const QgsFields fFields = perLayerFields[layerName];
	      		const QVector<QgsFeature> &layerFeatures = features[layerName];
	      		for ( const QgsFeature &f : layerFeatures )
	      		{ 
     
	        		if ( f.geometry().intersects( r ) && ( !selectionGeomPrepared || selectionGeomPrepared->intersects( f.geometry().constGet() ) ) )
	        		{ 
     
	          			QMap< QString, QString > derivedAttributes = commonDerivedAttributes;
	          			derivedAttributes.insert( tr( "Feature ID" ), FID_TO_STRING( f.id() ) );
	
	          			results->append( IdentifyResult( layer, layerName, fFields, f, derivedAttributes ) );
	
	          			featureCount++;
	        		}
	      		}
	    	}
	  	}
	}
}
//图层选择
QgsVectorTileLayer::selectByGeometry( const QgsGeometry &geometry, const QgsSelectionContext &context, Qgis::SelectBehavior behavior, Qgis::SelectGeometryRelationship relationship, Qgis::SelectionFlags flags, QgsRenderContext *renderContext )
{ 
     
	for ( int row = tileRange.startRow(); row <= tileRange.endRow(); ++row )
	{ 
     
		for ( int col = tileRange.startColumn(); col <= tileRange.endColumn(); ++col )
		{ 
     
			QgsTileXYZ tileID( col, row, tileZoom );
			QByteArray data = getRawTile( tileID );
			...
		}
	}
}
//矢量图层获取瓦片
QByteArray QgsVectorTileLayer::getRawTile( QgsTileXYZ tileID )
{ 
     
  const QgsTileMatrix tileMatrix = mMatrixSet.tileMatrix( tileID.zoomLevel() );
  const QgsTileRange tileRange( tileID.column(), tileID.column(), tileID.row(), tileID.row() );

  QgsDataSourceUri dsUri;
  dsUri.setEncodedUri( mDataSource );
  const QString authcfg = dsUri.authConfigId();

  QList<QgsVectorTileRawData> rawTiles = QgsVectorTileLoader::blockingFetchTileRawData( mSourceType, mSourcePath, tileMatrix, QPointF(), tileRange, authcfg, dsUri.httpHeaders() );
  if ( rawTiles.isEmpty() )
    return QByteArray();
  return rawTiles.first().data;
}
//矢量加载器阻塞下载
QList<QgsVectorTileRawData> QgsVectorTileLoader::blockingFetchTileRawData( const QString &sourceType, const QString &sourcePath, const QgsTileMatrix &tileMatrix, const QPointF &viewCenter, const QgsTileRange &range, const QString &authid, const QgsHttpHeaders &headers, QgsFeedback *feedback )
{ 
     
	for ( QgsTileXYZ id : std::as_const( tiles ) )
	{ 
     
		if ( feedback && feedback->isCanceled() )
			return rawTiles;
		//三种下载方式:网络下载、MB瓦片下载、Vtpk下载
		QByteArray rawData = isUrl ? loadFromNetwork( id, tileMatrix, sourcePath, authid, headers, feedback )
		                     : ( mbReader ? loadFromMBTiles( id, *mbReader ) : loadFromVtpk( id, *vtpkReader ) );
		if ( !rawData.isEmpty() )
		{ 
     
		 	rawTiles.append( QgsVectorTileRawData( id, rawData ) );
		}
	}
}
//网络下载
QByteArray QgsVectorTileLoader::loadFromNetwork( const QgsTileXYZ &id, const QgsTileMatrix &tileMatrix, const QString &requestUrl, const QString &authid, const QgsHttpHeaders &headers, QgsFeedback *feedback )
{ 
     
	QgsBlockingNetworkRequest req;			//阻塞请求
	req.setAuthCfg( authid ); 
	QgsBlockingNetworkRequest::ErrorCode errCode = req.get( nr, false, feedback );  
	QgsNetworkReplyContent reply = req.reply(); 
	return reply.content();
}
//阻塞式网络请求
QgsBlockingNetworkRequest::get( QNetworkRequest &request, bool forceRefresh, QgsFeedback *feedback )
{ 
     
  return doRequest( Get, request, forceRefresh, feedback );
}
QgsBlockingNetworkRequest::doRequest( QgsBlockingNetworkRequest::Method method, QNetworkRequest &request, bool forceRefresh, QgsFeedback *feedback )
{ 
     
	const std::function<void()> downloaderFunction = [ this, request, &waitConditionMutex, &authRequestBufferNotEmpty, &threadFinished, &success, requestMadeFromMainThread ]()
	{ 
     
		// this function will always be run in worker threads -- either the blocking call is being made in a worker thread,
		// or the blocking call has been made from the main thread and we've fired up a new thread for this function
		Q_ASSERT( QThread::currentThread() != QgsApplication::instance()->thread() );		
		QgsNetworkAccessManager::instance( Qt::DirectConnection );		
		success = true;		
		sendRequestToNetworkAccessManager( request );	//执行请求(见下)
		
		if ( mFeedback )
		 	connect( mFeedback, &QgsFeedback::canceled, mReply, &QNetworkReply::abort );
		 			
		if ( !mAuthCfg.isEmpty() && !QgsApplication::authManager()->updateNetworkReply( mReply, mAuthCfg ) )
		{ 
     
			mErrorCode = NetworkError;
			mErrorMessage = errorMessageFailedAuth();
			QgsMessageLog::logMessage( mErrorMessage, tr( "Network" ) );
			if ( requestMadeFromMainThread )
			 	authRequestBufferNotEmpty.wakeAll();
			success = false;
		}
		else
		{ 
     
			// We are able to use direct connection here, because we
			// * either run on the thread mReply lives in, so DirectConnection is standard and safe anyway
			// * or the owner thread of mReply is currently not doing anything because it's blocked in future.waitForFinished() (if it is the main thread)
			connect( mReply, &QNetworkReply::finished, this, &QgsBlockingNetworkRequest::replyFinished, Qt::DirectConnection );
			connect( mReply, &QNetworkReply::downloadProgress, this, &QgsBlockingNetworkRequest::replyProgress, Qt::DirectConnection );
			connect( mReply, &QNetworkReply::uploadProgress, this, &QgsBlockingNetworkRequest::replyProgress, Qt::DirectConnection );
			
			auto resumeMainThread = [&waitConditionMutex, &authRequestBufferNotEmpty ]()
			{ 
     
			  // when this method is called we have "produced" a single authentication request -- so the buffer is now full
			  // and it's time for the "consumer" (main thread) to do its part
			  waitConditionMutex.lock();
			  authRequestBufferNotEmpty.wakeAll();
			  waitConditionMutex.unlock();
			
			  // note that we don't need to handle waking this thread back up - that's done automatically by QgsNetworkAccessManager
			};
			
			if ( requestMadeFromMainThread )
			{ 
     
			  connect( QgsNetworkAccessManager::instance(), &QgsNetworkAccessManager::authRequestOccurred, this, resumeMainThread, Qt::DirectConnection );
			  connect( QgsNetworkAccessManager::instance(), &QgsNetworkAccessManager::proxyAuthenticationRequired, this, resumeMainThread, Qt::DirectConnection );
			
			#ifndef QT_NO_SSL
			  connect( QgsNetworkAccessManager::instance(), &QgsNetworkAccessManager::sslErrorsOccurred, this, resumeMainThread, Qt::DirectConnection );
			#endif
			 }
			 QEventLoop loop;
			 // connecting to aboutToQuit avoids an on-going request to remain stalled
			 // when QThreadPool::globalInstance()->waitForDone()
			 // is called at process termination
			 connect( qApp, &QCoreApplication::aboutToQuit, &loop, &QEventLoop::quit, Qt::DirectConnection );
			 connect( this, &QgsBlockingNetworkRequest::finished, &loop, &QEventLoop::quit, Qt::DirectConnection );
			 loop.exec();
		} //end of else
	};	//end of function
}
QgsBlockingNetworkRequest::sendRequestToNetworkAccessManager( const QNetworkRequest &request )
{ 
     
	switch ( mMethod )
	{ 
     
		case Get:
		  mReply = QgsNetworkAccessManager::instance()->get( request );  //instance()回头看一下,有意思
		  break;
		
		case Post:
		  mReply = QgsNetworkAccessManager::instance()->post( request, mPayloadData );
		  break;
		
		case Head:
		  mReply = QgsNetworkAccessManager::instance()->head( request );
		  break;
		
		case Put:
		  mReply = QgsNetworkAccessManager::instance()->put( request, mPayloadData );
		  break;
		
		case Delete:
		  mReply = QgsNetworkAccessManager::instance()->deleteResource( request );
		  break;
	};
}

//矢量瓦片加载器构造时调用了异步加载
QgsVectorTileLoader::QgsVectorTileLoader( const QString &uri, const QgsTileMatrix &tileMatrix, const QgsTileRange &range, const QPointF &viewCenter, const QString &authid, const QgsHttpHeaders &headers, QgsFeedback *feedback )
  : mEventLoop( new QEventLoop )
  , mFeedback( feedback )
  , mAuthCfg( authid )
  , mHeaders( headers )
{ 
      
	QVector<QgsTileXYZ> tiles = QgsVectorTileUtils::tilesInRange( range, tileMatrix.zoomLevel() );
	QgsVectorTileUtils::sortTilesByDistanceFromCenter( tiles, viewCenter );
	for ( QgsTileXYZ id : std::as_const( tiles ) )
	{ 
     
	  	loadFromNetworkAsync( id, tileMatrix, uri );
	}
}
//异步矢量下载
QgsVectorTileLoader::loadFromNetworkAsync( const QgsTileXYZ &id, const QgsTileMatrix &tileMatrix, const QString &requestUrl )
{ 
     
	 QString url = QgsVectorTileUtils::formatXYZUrlTemplate( requestUrl, id, tileMatrix );
	 QNetworkRequest request( url );		//网络请求
	 QgsSetRequestInitiatorClass( request, QStringLiteral( "QgsVectorTileLoader" ) );
	 QgsSetRequestInitiatorId( request, id.toString() );
	
	 request.setAttribute( static_cast<QNetworkRequest::Attribute>( QNetworkRequest::User + 1 ), id.column() );
	 request.setAttribute( static_cast<QNetworkRequest::Attribute>( QNetworkRequest::User + 2 ), id.row() );
	 request.setAttribute( static_cast<QNetworkRequest::Attribute>( QNetworkRequest::User + 3 ), id.zoomLevel() );
	
	 request.setAttribute( QNetworkRequest::CacheLoadControlAttribute, QNetworkRequest::PreferCache );
	 request.setAttribute( QNetworkRequest::CacheSaveControlAttribute, true );
	
	 mHeaders.updateNetworkRequest( request );
	
	 if ( !mAuthCfg.isEmpty() &&  !QgsApplication::authManager()->updateNetworkRequest( request, mAuthCfg ) )
	 { 
     
	   QgsMessageLog::logMessage( tr( "network request update failed for authentication config" ), tr( "Network" ) );
	 }
	
	 QgsTileDownloadManagerReply *reply = QgsApplication::tileDownloadManager()->get( request );	//执行请求(见下)
	 connect( reply, &QgsTileDownloadManagerReply::finished, this, &QgsVectorTileLoader::tileReplyFinished );
	 mReplies << reply;
}

//wms下载
QgsWmsTiledImageDownloadHandler::QgsWmsTiledImageDownloadHandler( )
{ 
     
	for ( const QgsWmsProvider::TileRequest &r : constRequests )
	{ 
     
		QNetworkRequest request( r.url );
		QgsSetRequestInitiatorClass( request, QStringLiteral( "QgsWmsTiledImageDownloadHandler" ) );
		auth.setAuthorization( request );
		request.setRawHeader( "Accept", "*/*" );
		request.setAttribute( QNetworkRequest::CacheLoadControlAttribute, QNetworkRequest::PreferCache );
		request.setAttribute( QNetworkRequest::CacheSaveControlAttribute, true );
		request.setAttribute( static_cast<QNetworkRequest::Attribute>( TileReqNo ), mTileReqNo );
		request.setAttribute( static_cast<QNetworkRequest::Attribute>( TileIndex ), r.index );
		request.setAttribute( static_cast<QNetworkRequest::Attribute>( TileRect ), r.rect );
		request.setAttribute( static_cast<QNetworkRequest::Attribute>( TileRetry ), 0 );
		//执行请求------
		QgsTileDownloadManagerReply *reply = QgsApplication::tileDownloadManager()->get( request );
		connect( reply, &QgsTileDownloadManagerReply::finished, this, &QgsWmsTiledImageDownloadHandler::tileReplyFinished );
		mReplies << reply;
	}
}

4.6 qgis插件框架

4.7 坐标转换

//文件位置:/core/qgsmaptopixel.h
 QgsPointXY toMapCoordinates( double x, double y ) const SIP_PYNAME( toMapCoordinatesF )
    { 
     
      bool invertible;
      const QTransform matrix = mMatrix.inverted( &invertible );
      assert( invertible );
      qreal mx, my;
      matrix.map( static_cast< qreal >( x ), static_cast< qreal >( y ), &mx, &my );
      return QgsPointXY( mx, my );
    }

4.8 拖动

QgsMapCanvas::mousePressEvent( QMouseEvent *e )
 	if ( mMapTool->flags() & QgsMapTool::AllowZoomRect  && 
 	     e->button() == Qt::LeftButton 					&& 
 	     e->modifiers() & Qt::ShiftModifier )
    { 
     
        beginZoomRect( e->pos() );
    }
QgsMapCanvas::mouseReleaseEvent( QMouseEvent *e )
	if ( mZoomDragging && e->button() == Qt::LeftButton )		//鼠标左键拖动地图
    	endZoomRect( e->pos() );     
QgsMapCanvas::endZoomRect( QPoint pos )
	QgsPointXY c = mSettings.mapToPixel().toMapCoordinates( mZoomRect.center() );		//中心点geo坐标
  	zoomByFactor( sf, &c );
QgsMapCanvas::zoomByFactor( double scaleFactor, const QgsPointXY *center, bool ignoreScaleLock )
	setExtent( r, true );
QgsMapCanvas::setExtent( const QgsRectangle &r, bool magnified )
	emit extentsChanged();

免责声明:本站所有文章内容,图片,视频等均是来源于用户投稿和互联网及文摘转载整编而成,不代表本站观点,不承担相关法律责任。其著作权各归其原作者或其出版社所有。如发现本站有涉嫌抄袭侵权/违法违规的内容,侵犯到您的权益,请在线联系站长,一经查实,本站将立刻删除。 本文来自网络,若有侵权,请联系删除,如若转载,请注明出处:https://haidsoft.com/127835.html

(0)
上一篇 2025-09-04 20:20
下一篇 2025-09-04 20:26

相关推荐

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注微信