赞
踩
QGis源码: https://download.qgis.org/downloads/
官方api查询:https://api.qgis.org/api/3.28/index.html
官方文档:https://qgis.org/en/docs/index.html#
官方文档中点击对应的版本-》building QGis from source(查看对应的编译要求)
QGis3.16在Ubuntu18.04(bionic)下的编译要求:qt5.9
You should also setup ccache to speed up compile times:
cd /usr/local/bin
sudo ln -s /usr/bin/ccache gcc
sudo ln -s /usr/bin/ccache g++
or simply add /usr/lib/ccache to your PATH.
PyQt5源码下载:http://www.riverbankcomputing.com/software/pyqt/download5
PyQt5-sip下载:https://pypi.org/project/PyQt5-sip/
编译: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)
问题:
问题0 :"no module named pyqt5.sip"解决
解决:PyQt5-sip在configure时须指定PyQt5.sip(不是sip的安装)
python3 configure.py --sip-module PyQt5.sip
sip下载地址:
https://www.riverbankcomputing.com/static/Downloads/sip/4.19.25/sip-4.19.25.tar.gz
https://www.riverbankcomputing.com/software/sip/download/
PyQt5-sip下载地址:
https://www.cnpython.com/pypi/pyqt5-sip/download
PyQt5_sip-12.8.1.tar.gz下载地址
问题1 :qmake: could not exec ‘/usr/lib/x86_64-linux-gnu/qt4/bin/qmake’: No such file or directory
解决:没安装qt库,sudo apt-get install qt-sdk
问题2 :Error: Make sure you have a working sip on your PATH or use the --sip argument to explicitly specify a working sip.
解决:没安装sip,
问题3:sipAPIQtCore.h:28:17: fatal error: sip.h: 没有那个文件或目录
解决:没有指定sip.h所在路径,configure时使用 python configure.py --sip-incdir=/usr/include/python2.7
问题4:qprinter.h: No such file or directory
解决:第一步python configure.py命令生成各种Qt模块后,其中的QtWebKitWidgets模块由于Qt4和Qt5的qprinter.h所属模块的调整(Qt4存在于QtGui中,Qt5将其调整到QtPrintSupport中了),QtWebKitWidgets的Makefile中缺失了对QtPrintSupport的头文件目录引用,会导致后面编译PyQt5时无法找到qprinter.h头文件,编译失败(编译过程非常漫长),所以需要向刚生成的QtWebKitWidgets模块源文件的MakeFile文件的INCPATH中添加QtPrintSupport引用。
第一种方法:修改路径
原INCPATH为:
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
QGis官方编译说明
中标麒麟下编译QGis
linux下直接cmake编译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
库的原因,去掉spatialite.lib,更改为spatialite_i.lib就可以
############################################################## # 编译版本设置 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/2924292 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 ……
能用的:
//高德
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的地址解析:
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
qt二次开发时的配置
QGIS二次开发:加载XYZ Tiles形式的瓦片地图
QGis二次开发例子
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(); }
验证QGis的代码:
QGIS二次开发2–读取qgis工程文件并显示
//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);
文件名 | 说明 |
---|---|
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 ) ) );
位置:/src/app/main.cpp
//这是基于MainWindow的
QgisApp *qgis = new QgisApp( mypSplash, myRestorePlugins, mySkipBadLayers, mySkipVersionCheck, rootProfileFolder, profileName );
qgis->show();
qgis->completeInitialization();
/* * +--------+ +------+ +---------+ * | 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()
{
}
//底层请求(最终调用)------
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; } }
//文件位置:/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 );
}
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();
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。