大家好,欢迎来到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 ……
1.3 kylin-v10安装
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<ype=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