引言

我们一般都是在线地图,比如百度、高德、腾讯地图用的多,在线地图API也非常方便调用,并且可以利用在线地图强大的地图服务,比如路径规划等功能,但是有些特殊的项目需要在内网环境下展示地图,而且是3D地图。这就要求我们能够在离线情况下,实现对3D地图的展示。

基石

实现离线地图的基础,是地图瓦片的获取,我们需要先有离线的地图瓦片或者地图的合成文件(.tif)。所以依据输入的不同,我们有不同的实现。如果是离线的地图瓦片,我们可以直接利用,至于为啥,我们后面会有说明。如果是离线的地图合成文件(.tif),我们需要利用地图引擎(ArcGIS、SuperMap、GeoServer等)发布为地图服务(比如OGC的WMTS),然后在内网使用地图服务即可。

实现

方式一:

利用离线的地图瓦片,地图瓦片的获取,有多种方式,可以使用现成的地图下载器,也可以编写爬虫来下载。不论采用哪种方式,下载下来都是按照指定的目录结构和文件命名方式来的。比如zoom级别为1,横坐标网格为1,则文件路径为 1/1,即文件夹1里面有文件夹1,再里面就是不同的纵坐标的图片,比如1/1/0.png1/1/-1.png1/1/1.png1/1/2.png,配上我下载好的目录,可以看一下:

为什么都要按照指定的目录结构和文件命名方式呢?因为在线地图瓦片地址,都是含有x、y、z值参数的,比如:

  • 百度:https://maponline1.bdimg.com/starpic/?qt=satepc&u=x=1630;y=431;z=13;v=009;type=sate&fm=46&app=webearth2&v=009&udt=20210318
  • 高德:https://webst03.is.autonavi.com/appmaptile?style=6&x=428&y=209&z=9
  • 腾讯:https://p3.map.gtimg.com/sateTiles/14/853/602/13656_9639.jpg?version=239
  • 更多:参考维基百科

所以针对不同的地图,要采用对应的目录结构进行存放瓦片。

有了离线瓦片,我们便可以直接利用静态瓦片服务来访问,什么是静态瓦片服务?就是把刚才的离线瓦片,放到一个tomcat中或者nginx指向即可,搭建一个静态文件服务,通过内网可以访问即可。注意tomcat要处理一下跨域问题。

有了离线瓦片静态服务器,便可以利用各种前端地图库,比如OpenLayers(tileLayer XYZ Souce)、Leaflet(tileLayer)等实现二维地图展示、Cesium(UrlTemplateImageryProvider)、deck.gl(TileLayer)等实现三维地图展示。这里以deck.gl为例:

const tileLayer = new TileLayer({// data: "http://10.1.100.47:8080/tms/{z}/{x}/{-y}.jpg",// data: "https://webst01.is.autonavi.com/appmaptile?style=6&x={x}&y={y}&z={z}",data: "http://10.0.30.152:8180/mapabc/satellite/{z}/{x}/{y}.jpg",minZoom: 1,maxZoom: 7,tileSize: 256,renderSubLayers: props => {const {bbox: { west, south, east, north }} = props.tile;return new BitmapLayer(props, {data: null,image: props.data,bounds: [west, south, east, north]});}
});

展示:

方式二:

利用离线的大地图合成文件(.tif),通过地图引擎发布为瓦片服务(WMTS、WMS),然后通过各种前端地图库,比如OpenLayers(tileLayer WMTS source)展示二维地图,Cesium(WebMapTileServiceImageryProvider)展示三维地图。

合成地图(.tif)可以通过地图下载器获取,即选择拼接瓦片为大图。也可以是从其他方式获取。注意,每一个zoom级别,都会有一个.tif文件。发布服务时,要对每一个级别分别发布,以方便利用geoserver的gwc进行切图,但是使用时只需要一个级别即可,详见后文。这里以GeoServer为例,可以按照如下步骤进行:

  1. 安装GeoServer,选择war形式,放到tomcat中webapps目录下;
  2. 上传.tif文件到GeoServer所在服务器(即tomcat下webapps/geoserver/data目录下);
  3. 新建工作区(如果已经有了,可以不用新建,主要是和已有工作区以示区分);
  4. 添加新的数据存储(选择“栅格数据源”-GeoTIFF,导入.tif文件);
  5. 发布图层(数据选项卡,可以对关键词进行删改,其他默认配置,Tile Caching选项卡,最下面的Gridset可以设置发布和缓存的级别,一般对于每一层级可以直接写死,即Min/Max为指定层级,比如3级,就都为3,这样可以方便切图);
  6. 对于每一个层级,进行上述4-5步骤;
  7. 在Tile Layers功能菜单下,选择刚才发布的地图,进行切图(切图是为了加快显示,将切图放到gwc指定的缓存目录下,可以加快显示,消除一块一块的卡顿感),切图时注意zoom start和zoom stop,为了提高效率,只需要切一级即可,即和对应发布的地图层级匹配即可;
  8. 对于每一个层级,进行上述7步骤;
  9. 比如我们要使用1-7级的地图,这个时候,需要把2-7级的切图文件放到第1级的切图文件目录下,然后对1级地图图层设置Tile Caching选项卡,将最下面的Gridset,设置为Min=1,Max=7;
  10. 然后我们只需要访问1级图层对应的gwc的wmts服务地址即可。 wmts服务地址,可以通过网址:ip:port/geoserver/gwc下找到“A list of all the layers and automatic demos”点击进去找到。

    我们以Cesium为例,实现3D地图的显示:
let viewer = new Cesium.Viewer("cesiumContainer");let imageryLayers = viewer.imageryLayers;let url = "http://10.0.30.152:8180/geoserver/gwc/service/wmts"; //Geoserver URLlet tileMatrixLabels = [];for (let i = 0; i < 7; i++) {tileMatrixLabels.push("EPSG:4326:" + i);}let wmtsMap = new Cesium.WebMapTileServiceImageryProvider({url: url,layer: "amap:gaode1",style: "",tileMatrixLabels,format: "image/png",tileMatrixSetID: "EPSG:4326",maximumLevel: 7,tilingScheme: new Cesium.GeographicTilingScheme()});imageryLayers.addImageryProvider(wmtsMap);// flyviewer.camera.flyTo({destination: Cesium.Cartesian3.fromDegrees(114.296063,30.55245,20000000),orientation: {heading: Cesium.Math.toRadians(0),pitch: Cesium.Math.toRadians(-90),roll: 0.0},duration: 5 // fly time 10s});

展示:

3D离线地图的两种实现方式相关推荐

  1. CSS学习记录9/3D的正方体的两种编写方式/3D长方体的编写方式/3D动画/3D播放器

    什么是2D什么是3D? 2D就是一个平面,只是宽度和高度,没有厚度. 3D就是一个立体,有宽度有高度,还有厚度. 默认情况下所有的元素都是呈2D展现的. 如何让某个元素呈3D展现? 和透视一样,只需给 ...

  2. vue中基于echarts和基于高德地图的两种地图下钻与上浮方式

    ** vue中基于echarts和基于高德地图的两种地图下钻与上浮方式 ** 基于echarts的地图下钻与上浮(浙江省为例) 第一步:在<template>中构建承载echarts的do ...

  3. 3d离线地图,如何实现?

    3d离线地图,如何实现? 离线地图说白了就是把地图上加载的在线服务转成本地发布的地图服务,地图服务有很多种,地图数据也有很多种,例如tif,shp等等 离线服务      wms服务.wmts服务.x ...

  4. android中资源文件的两种访问方式,Android_Android学习笔记-保存文件(Saving Files),Android设备有两种文件存储区域 - phpStudy...

    Android学习笔记-保存文件(Saving Files) Android设备有两种文件存储区域: 内部存储和外部存储 ("internal" and "externa ...

  5. Python爬虫的两种请求方式,读者都了解吗?

    Python爬虫中的get和post请求 前言 Python爬虫请求数据有get和post两种请求方式,也许读者对于它们的应用已经掌握到炉火纯青的地步了,但是关于它们的基本语法是否了解吗? 文章目录 ...

  6. C++中的两种绑定方式(静态绑定、动态绑定)

    两种绑定方式 静态绑定:在编译时刻,根据指针或引用变量的静态类型来决定成员函数属于哪一个类. 动态绑定:在运行时刻,根据指针或引用变量实际指向或引用的对象类型(动态类型)来确定成员函数属于哪一个类. ...

  7. (C++)string 的两种输入方式和输出方式

    注:头文件如下 #include<string> #include<cstdio> #include<iostream>using namespace std; 注 ...

  8. 三十张图片让你彻底弄明白图的两种遍历方式:DFS和BFS

    1 引言   遍历是指从某个节点出发,按照一定的的搜索路线,依次访问对数据结构中的全部节点,且每个节点仅访问一次.图的遍历.遍历过程中得到的顶点序列称为图遍历序列. 2 深度优先搜索 2.1 算法思想 ...

  9. Java两种排序方式快慢比较

    2019独角兽企业重金招聘Python工程师标准>>> Java中List的排序方式有两种,现在我们测试下这两种排序方式的快慢吧,我们需要用到两个类, 一个是运行程序的Main类,另 ...

最新文章

  1. 菜鸟笔记(一) - Java常见的乱码问题
  2. Mysql连接数据库的操作
  3. java.io.IOException cannot be resolved
  4. 微软解释 Edge 浏览器比 Chrome 更加安全的原因
  5. 如何玩转CSS列表样式?速查!
  6. .net与mysql,ASP.NET与MySql的连接
  7. JavaScript基础修炼(14)——WebRTC在浏览器中如何获得指定格式的PCM数据【华为云分享】
  8. php页面设定语言,php实现获取及设置用户访问页面语言类,php页面_PHP教程
  9. Android内核开发:系统分区与镜像文件的烧写
  10. 网络编程聊天室----服务器端
  11. springBoot笔记2
  12. oracle驱动的区别吗,oracle10g下JDBC驱动包的区别
  13. 4G无线预付费电表系统设计及其应用
  14. 通州区机器人比赛活动总结_机器人社团活动课总结
  15. 计算机的计量单位以及常见的数据类型
  16. R语言---scale函数,match函数和%in%详解
  17. 空间想象力差学计算机,空间思维想象力差怎么办
  18. 在 sys.servers 中找不到服务器 '******'。请验证指定的服务器名称是否正确。
  19. linux中有一个备份程序,技术|SBackup: 一个Linux下的简单备份软件
  20. DOSBox+MASM搭建汇编环境

热门文章

  1. angelababy机器人唱_Angelababy压轴亮相《机器人争霸》 变身女战神
  2. app审核被拒:App Tracking Transparency permission request when reviewed on iOS 15.0
  3. USB OTG简介、与普通USB线的区别
  4. ifix从sqlserver里读数据_基于GE Fanuc产品PBS汽车总装生产线监控系统设计
  5. pip速度慢,更换清华镜像源试试?
  6. 地理坐标系、大地坐标系、地图投影与重投影
  7. Fiddler抓取HTTPS最强攻略
  8. 【深度学习】入门之keras
  9. 【 FPGA 】稳态与亚稳态小结
  10. (汇总篇)语义SLAM相关开源方案| 全球优秀作者与实验室 | SLAM学习资料整理