一.leaflet转cesium
比较简单,
先用leaflet的getBounds获取边界
再使用cesium的viewer.camera.setView({
destination:Cesium.Rectangle.fromDegrees(args)
})来实现相机位置切换,最后效果还不错。

2TO3

二.cesium转leaflet
首先获取屏幕内地球的二维中心点坐标(有多种办法,我是使用viewer.camera.pickEllipsoid配合二分查找拿到的),将相机移动至中点上方并姿态调整,使之正对地球。获取中心点对应的经纬度坐标P(lng,lat)。

接下来比较困难的是三维地图高度与二维地图上zoom的对应关系,即在变形较小的前提下将三维地图转换为二维。
我尝试过几种办法
1.viewer.camera.computeViewRectangle
这也是我看到目前网络上传的最多的方法,不过这种有两个问题,第一个问题是只有在地球上下左右四个边界都超出屏幕后才能使用,否则获取的矩形坐标不对(我对着中国调用,每次都定位到科特迪瓦)。第二个问题是就算将三维地球放大,因为球体的投影在矩形转换过程中也会出现leaflet的zoom不是最佳缩放比例。
2.通过viewer.scene.globe._surface._tilesToRender[0]._level获取当前三维地球的正对瓦片的层级,然后将leaflet的zoom设置相同值。这种也存在视差问题,比如三维上看同等大小的区域是3级,在二维地图上需要5级,因此使用这种方法需要设置几个层级关系,一般三个就够,效果还行,但这种方法总感觉不够优雅。
3.通过墨卡托投影实现完美转换
@#%?!~反正没搞出来
4.通过两点间的经纬度与二维像素长度关系实现转换。这种方法不需要专业的gis投影知识也能简单实现。首先分析问题:①想要转换形变小,也就是三维地图中某区域大小形状在二维地图看也差不多,但毕竟一个是球体一个是平面,所以想全局无形变也是不现实的,所以我们的目标是让屏幕中心一块区域实现形变很小的转换。②球体的俯视图,使用九宫格划分后,它的中间一块接近一个平面,越靠近边缘倾角越大,所以我们只需要中间的区域的转换效果最佳。③区域的转换可以用固定线段的转换来模拟,因此我们在三维地球的中心区域取1/3可视地球高度的垂直线段,两端点分别为P1、P2。获取线段P1P2的长度h,转换为2维地图后,使P1、P2两坐标像素间距最接近h的zoom,即为所求。
解决方法:
①先通过viewer.camera.pickEllipsoid获取屏幕内可见地球的上下界坐标,然后取x=1/2屏幕宽,y分别是可见上下界1/3和2/3的两点P1、P2。

P1=[1/2viewer.camera.canvas.width,y1]
P2=[1/2
viewer.camera.canvas.width,y2]
此时P1,P2均为像素坐标
h = y2 - y1 = 1/3H’
然后通过viewer.camera.pickEllipsoid将屏幕坐标P1、P2转为经纬度坐标P1’,P2’
②leaflet的project方法可以获取指定坐标在指定zoom下的相对CRS原点P0的像素位置,使用for循环获得不同zoom下p1’与p2’的对应像素坐标P1’‘、P2’‘,因为两个坐标的x’‘相同,因此Math.abs(y2’‘-y1’‘)就是两点间像素距离h’,找到刚好h’≥h时的zoom,就是我们需要的结果。

3TO2


leaflet to cesium 示例代码

const bound = Lmap.getBounds();
Lmap.remove();
Lmap = null;
var Cmap = this.init3DMap([bound._southWest.lng,bound._southWest.lat,bound._northEast.lng,bound._northEast.lat
]);init3DMap(defaultView){let map = new Cesium.Viewer("map", {imageryProvider: new Cesium.UrlTemplateImageryProvider({url: "http://localhost:8080/mapTiles/{z}/{x}/{y}.png"}),baseLayerPicker: false,animation: false,shouldAnimate: true,geocoder: false,navigationHelpButton: false,timeline: false,fullscreenButton: false,homeButton: false,infoBox: false,scene3DOnly: true,selectionIndicator: false,navigationInstructionsInitiallyVisible: false,useDefaultRenderLoop: true,showRenderLoopErrors: true,projectionPicker: false,vrButton: false});map._cesiumWidget._creditContainer.style.display = "none";if (defaultView) {map.camera.setView({destination: Cesium.Rectangle.fromDegrees(...defaultView)});} else {map.camera.setView({destination: Cesium.Cartesian3.fromDegrees(centerLng,centerLat,centerHei)});}defaultView = nullreturn map
}

cesium to leaflet 示例代码

this.switchTo2D(Cmap).then(args => {Cmap.destroy();Cmap = null;var Lmap = this.init2DMap(args);
});switchTo2D(map){return new Promise((resolve, reject) => {const ellipsoid = map.scene.globe.ellipsoid;const canvas = map.scene.canvas;let if_top = map.camera.pickEllipsoid(new Cesium.Cartesian2(canvas.width / 2, 0));let if_bottom = map.camera.pickEllipsoid(new Cesium.Cartesian2(canvas.width / 2, canvas.height));let top_view = 0;let bottom_view = canvas.height;if (if_top === undefined) {top_view = getViewBorder(map,[[top_view, bottom_view]],canvas.width / 2,ellipsoid,"top");}if (if_bottom === undefined) {bottom_view = getViewBorder(map,[[top_view, bottom_view]],canvas.width / 2,ellipsoid,"bottom");}let newCenterLng = centerLnglet newCenterLat = centerLatlet newCenterHei = centerHeiif (top_view !== undefined && bottom_view !== undefined) {let lnglat = Cartesian2ToLngLat(map,[canvas.width / 2, (top_view + bottom_view) / 2],ellipsoid);//将相机高度传入,重新转换为笛卡尔三维坐标newCenterLng = (lnglat.longitude * 180) / Math.PI;newCenterLat = (lnglat.latitude * 180) / Math.PI;newCenterHei = map.camera.positionCartographic.height;}map.camera.flyTo({destination: Cesium.Cartesian3.fromDegrees(newCenterLng,newCenterLat,newCenterHei,ellipsoid),duration: 1.5,complete: () => {let screenDistance = null;let topLngLat = [];let bottomLngLat = [];// 当视口内地球高度像素大于200px时,获取距离中心点1/6地球可视高度的上下两点处位置的坐标// 当地球高度像素小于等于200px时,只传入中心点,并让2维地图zoom为最小if (Math.abs(bottom_view - top_view) > 200) {screenDistance = Math.abs(bottom_view - top_view) / 3;const centerX = canvas.width / 2;const centerY = (top_view + bottom_view) / 2;let topPoint = Cartesian2ToLngLat(map,[centerX, centerY + screenDistance / 2],ellipsoid);let bottomPoint = Cartesian2ToLngLat(map,[centerX, centerY - screenDistance / 2],ellipsoid);topLngLat = [(topPoint.longitude * 180) / Math.PI,(topPoint.latitude * 180) / Math.PI];bottomLngLat = [(bottomPoint.longitude * 180) / Math.PI,(bottomPoint.latitude * 180) / Math.PI];}map = nullresolve([[newCenterLng, newCenterLat],topLngLat,bottomLngLat,screenDistance])}});})
}init2DMap(defaultView){let satelliteMap = L.tileLayer("http://localhost:8080/mapTiles/{z}/{x}/{y}.png", {});let center = [34.3227, 108.5525];const minZoom = 3,maxZoom = 9;let zoom = 5;let type = "satellite";if (defaultView) {center = [defaultView[0][1], defaultView[0][0]];zoom = minZoom;type = defaultView[4];}let map = L.map("map", {layers: satelliteMap, //默认卫星图center: center, // 地图中心zoom: zoom,minZoom: minZoom,maxZoom: maxZoom,zoomControl: false,trackResize: true,dragging: true,scrollWheelZoom: true,doubleClickZoom: false,attributionControl: false // 移除右下角leaflet标识});// 添加比例尺L.control.scale({maxWidth: 100,metric: true,imperial: false,updateWhenIdle: true,position: "bottomleft"}).addTo(map);if (defaultView && defaultView[3] !== null) {let topPoint,bottomPoint,flag = true;for (let zoom = minZoom; zoom <= maxZoom; zoom++) {topPoint = map.project([defaultView[1][1], defaultView[1][0]], zoom);bottomPoint = map.project([defaultView[2][1], defaultView[2][0]],zoom);if (Math.abs(topPoint.y - bottomPoint.y) > defaultView[3]) {map.setZoomAround(center, zoom);flag = false;break;}}if (flag) {map.setZoomAround(center, maxZoom);}}defaultView = nullreturn map
}

一种新的leaflet+cesium二三维切换的解决方案相关推荐

  1. 超图Cesium二三维切换

    Viewer.Scene.mode:Number 超图上点心!这样写容易误导大家是个对象类型呢.其实是个枚举数字. Cesium.SceneMode Cesium.SceneMode.COLUMBUS ...

  2. cesium模仿百度地图二三维切换

    百度地图二三维切换效果感觉比cesium自带的更平滑 不过百度地图的二三维切换只是简单的三维视角切换,二维是垂直视角 //传入viewer和要切换的维数 onChange2D3DClick(viewe ...

  3. Cesium 自定义二三维切换按钮

    有时我们不想用cesium自带的那个二三维切换,想自己写切换按钮,通过给按钮绑定事件,然后触发切换: 关键是切换事件怎么写,通过对源码的研究,还是找到了这个切换的事件: $("#to2d&q ...

  4. cesium自定义二三维切换

    实现源码如下: //viewType:视图类型 function setViewType (viewType) {var scene = this.viewer.scene;switch (viewT ...

  5. 第一章:Vue3.0+Openlayers+Cesium创建二三维联动项目

    Vue3.0+Openlayers+Cesium创建二三维联动项目 简介 Vue项目创建 安装依赖 框架结构 地图加载 显示效果 结语 简介 大家好!从今天开始,我将分享我在GIS开发的过程中如何利用 ...

  6. 【ol-cesium】OpenLayers与Cesium的二三维联动

    OpenLayers与Cesium的二三维联动 本文主要介绍OpenLayers与Cesium二三维联动的实现过程,以及在实现的过程中所遇到的问题以及解决方法. 研究二三维联动的动机是需要开发基于Ge ...

  7. M2DP:一种新的三维点云描述子及其在回环检测中的应用

    文章:M2DP: A Novel 3D Point Cloud Descriptor and Its Application in Loop Closure Detection 作者:Li He , ...

  8. 提出了一种新的基于一致性算法的直流微电网均流和均压二级控制方案 关键词:一致性算法;直流微电网;下垂控制;分布式二次控制

    关键词:一致性算法;直流微电网;下垂控制;分布式二次控制;电压电流恢复与均分;非线性负载;MATLAB/Simulink;顶刊复现, 主题:提出了一种新的基于一致性算法的直流微电网均流和均压二级控制方 ...

  9. 基于cesium的二三维地图

    一.项目简介 基于cesium的二三维地图 二.实现功能 支持虚线和阴影 支持以标注的方式显示属性 支持要素查询 支持二三维度地球显示 支持小数据量文件矢量动态切片 三.技术选型 Cesium pro ...

最新文章

  1. linux系统信号控制进程的重启,Linux系统中的信号(进程间通信)及其含义
  2. [模板]欧几里得算法/扩展欧几里得
  3. TweetLouder.com:在微博上找你喜好的乐队
  4. 有了这套模板,女朋友再也不用担心我刷不动 LeetCode 了
  5. android 每分钟广播,每1分钟Android发布一次警报管理器?
  6. 高性能网站建设的14个原则(转载)
  7. php strchr 截断,PHP strchr() 函数
  8. (5)容器级标签和文本级标签
  9. mysql 头行关联_mysql实现一样变多行(表关联,批量实现)
  10. htpasswd用法
  11. ●洛谷P2606 [ZJOI2010]排列计数
  12. 15.Object Manager
  13. 修改SAP下载文件路径
  14. 计算机xp桌面没有下面的图标,Windows XP 启动后桌面无图标、无任务栏的问题
  15. UC浏览器去广告、联网、升级(支持新版8.1)
  16. 平流方程基于MATLAB数值解法,Matlab微分方程高效解法:谱方法原理与实现
  17. Git Commit failed with error The Git process exited with the code -1,073,741,819
  18. 用python计算工资工资_薪资计算-Python,薪水,python
  19. html尖角效果,CSS3之尖角标签_html/css_WEB-ITnose
  20. 副屏幕全屏_win7双屏电脑主屏副屏设置|Win7系统如何设置双屏显示?

热门文章

  1. 前端系列——vue2+高德地图web端开发(使用和引入)
  2. 苹果iPhone XS Max 贴膜之后面容无法使用
  3. 【毕业设计】远程智能浇花灌溉系统 - stm32 单片机 嵌入式 物联网
  4. 【oracle】无法通过 1024 (在表空间 USERS 中) 扩展 ORA-06512
  5. MapGis中如何输入分数、带有上下标格式的注释_map2shp_新浪博客
  6. Python-机器学习(三)-KMeans聚类算法
  7. 电力系统微型计算机继电保护2018,4月全国自考电力系统微型计算机继电保护试卷及答案解析.docx...
  8. ARP欺骗攻击原理及其防御
  9. python 滚动字幕软件_文字跑马灯(滚动字幕)效果并指定速度
  10. d3 svg path添加文本_D3.js 力导向图的显示优化