有些服务是发在场景(scene)下的,超图提供了一个很方便的方法:scene.open,这个方法会将场景中所有的图层(无论是OSGB还是影像和地形)加载进来。同时这个方法会自带一个自动地位功能,具体实现不深究。

  这个方法虽然很方便,省去了循环遍历场景下图层的代码,但是也会因此导致出现一些问题。

  1、删除图层的问题

    使用scene.open的首要问题就是如何删除图层。因为这个方法会将场景下面的所有图层一次性的加载进来,不需要我们单独进行台南佳。那么这个方法的内部在加载图层之初必然会进行判定,根据图层的不同调用不同的方法进行图层的叠加。目前我用到的图层的不同类型有:

    a、OSGBLayer

      这个图层是用来加载三维模型,目前还未单独使用进行添加。不过推测单独添加的方法应该如下:

  1. var promise = scene.addS3MTilesLayerByScp('http://localhost:8090/iserver/services/3D-zj/rest/realspace/datas/zj/config', {name : 'base'});
  2. promise.then(function(layer){
  3. layer.visible = false;
  4. });

      这个方法依旧是由超图进行了封装。

      删除的方法如下:

  1. scene.layers.remove(layerName)

      可见图层是加载了Layers中,所以才能使用layers.remove移除图层。

    b、ImageFileLayer

      影像文件图层,用来加载影像,单独加载方法如下:

  1. let imageryLayer = viewer.imageryLayers.addImageryProvider(imageryProvider);
  2. imageryLayer.getViewableRectangle().then(function (rectangle) {
  3. if(rectangle == undefined){
  4. return;
  5. }else{
  6. let cur_rectangle = viewer.camera.computeViewRectangle(); // 获取当前视角边界
  7. let inter_rectangle = Cesium.Rectangle.intersection(cur_rectangle,rectangle); // 取得当前视角边界和影像图层边界的交集
  8. // 若边界的交集不存在,说明所加载的影像图层不再视界范围内,这时候需要使用飞入效果。否则不使用飞入效果
  9. if(inter_rectangle == undefined || isNeedToFly(cur_rectangle)){
  10. viewer.camera.flyTo({
  11. destination: rectangle
  12. });
  13. }
  14. }
  15. },function(err){
  16. throw "影响图层叠加失败,请联系管理员"
  17. })
  18. viewer.imageryLayers.add(imageryLayer);

      删除方法:

  1. viewer.imageryLayers.remove(item, false)

    c、TerrainFileLayer

      地形图层,单独添加方法如下:

  1. let terrainProvider = new Cesium.CesiumTerrainProvider({url:path});
  2. viewer.terrainProvider = terrainProvider;

      删除方法目前感觉不理想,前端所作的效果不好。因为目前只能加载一个地形数据,如果你想动态的添加两地的地形数据,比如北京和河北,移除北京的地形图层保留河北地形图层,前端是做不到的。因为删除地形图层的时候相当于重新把椭球赋给当前球体,这样整个地球的地形图层也就没有了,也就不存在保留某个地区的地形数据。如果想要做到灵活的添加移除任意一个地形图层的话,应该是需要修改配置文件,具体可联系超图客服。删除的方法如下:

  1. viewer.terrainProvider = new window.Cesium.EllipsoidTerrainProvider({});

    这样的话,使用scene.open添加的话,我们不需要做的太多,主要在于删除的时候分清楚图层的类型,然后根据图层的类型进行删除就好了。

  2、获取整个场景的矩形范围以及飞行效果失效

    scene.open作用在于添加图层、自动定位到场景的位置,但是我很费劲的是,为什么官网没有这个方法的介绍,而且为什么不把自动定位关闭将视角返回,让用户自己去定位呢?

    还是首先去获取矩形范围。我发现在api文档中,有将矩形范围转换成视角的方法,但是却唯独没有将视角转换成矩形范围的方法。所以想要获取使用scene.open的矩形范围的话,只能通过一个方法(也或许我没有在找到这样的方法):对所有的图层进行遍历,获取所有图层的范围,然后取其并集。代码如下:

  1. /**
  2. * 将三维场景中图层的配置文件进行解析,得到其bounds;
  3. * @param data
  4. * @returns {{east: number, south: number, north: number, west: number}}
  5. */
  6. export function transFormXML(data){
  7. let Cesium = window.Cesium;
  8. // 获取bounds中的字符串
  9. let startIndex = data.indexOf("<sml:Bounds>");
  10. let endIndex = data.indexOf("</sml:Bounds>");
  11. let str_position = data.substring(startIndex + 12,endIndex);
  12. // 分别获取左上右下的坐标(角度)
  13. let left_startIndex = str_position.indexOf("<sml:Left>");
  14. let left_endIndex = str_position.indexOf("</sml:Left>");
  15. let top_startIndex = str_position.indexOf("<sml:Top>");
  16. let top_endIndex = str_position.indexOf("</sml:Top>");
  17. let right_startIndex = str_position.indexOf("<sml:Right>");
  18. let right_endIndex = str_position.indexOf("</sml:Right>");
  19. let bottom_startIndex = str_position.indexOf("<sml:Bottom>");
  20. let bottom_endIndex = str_position.indexOf("</sml:Bottom>");
  21. let west = parseFloat(str_position.substring(left_startIndex + 10,left_endIndex));
  22. let north = parseFloat(str_position.substring(top_startIndex + 9,top_endIndex));
  23. let east = parseFloat(str_position.substring(right_startIndex + 11,right_endIndex));
  24. let south = parseFloat(str_position.substring(bottom_startIndex + 12,bottom_endIndex));
  25. return Cesium.Rectangle.fromDegrees(west, south, east, north); // 将数据转换为rectangle对象
  26. }
  27.  
  28.         Cesium.loadJson(url + "/datas.json").then(function(datas){
  29. let arr_text = [];
  30. for(let i = 0;i < datas.length; i++){
  31. // 获取数据集配置文件
  32. Cesium.loadText(url + "/datas/" + datas[i].name + "/config").then(function(data){
  33. let obj_position = transFormXML(data); // 对获取的数据集配置文件进行解析得到矩形范围
  34. arr_text.push(obj_position);
  35. },function(err){
  36. console.log(err);
  37. })
  38. }
  39.  
  40. // 由于循环异步存在,会导致在arr_text还未获取到时就对其进行操作。故需要使用间歇调用
  41. let timer = setInterval(function(){
  42. if(arr_text.length == datas.length){
  43. clearInterval(timer); // 停止间歇调用
  44. // 使用reduce方法进行遍历,对所有的矩形范围取并集
  45. let max_rectangle = arr_text.reduce((max,item) => {
  46. if(isNaN(item.east) || isNaN(item.west) || isNaN(item.south)|| isNaN(item.north)){
  47. return max;
  48. }else{
  49. return Cesium.Rectangle.union(max, item); // 对两个矩形范围取并集
  50. }
  51. })
  52. // 设置视角飞行
  53. let cur_rectangle = viewer.camera.computeViewRectangle(); // 获取当前视角边界
  54. let inter_rectangle = Cesium.Rectangle.intersection(cur_rectangle,max_rectangle); // 取得当前视角边界和影像图层边界的交集
  55. if(inter_rectangle == undefined || isNeedToFly(cur_rectangle)) {
  56. scene.camera.flyTo({
  57. destination: new Cesium.Cartesian3.fromDegrees(cameraPosition.longitude, cameraPosition.latitude, cameraPosition.altitude),
  58. orientation: {
  59. heading: heading,
  60. pitch: tilt,
  61. roll: 0
  62. },
  63. });
  64. }else{
  65. let cur_heading = viewer.scene.camera.heading; // 获取当前时间的俯仰角
  66. let cur_pitch = viewer.scene.camera.pitch; // 获取当前视角的方位角
  67. let cur_roll = viewer.scene.camera.roll; // 获取当前视角的旋转角
  68. let cur_position = viewer.scene.camera.position.clone(); // 获取当前视角的e欸之
  69. cur_position.z += 1; // 由于使用scene.open 的时候,使用flyto中的数据相同的时候,会发生位置相同,scene.open内置的视角定位会发生作用,所以需要稍微修改值。
  70. scene.camera.flyTo({
  71. destination: cur_position,
  72. orientation: {
  73. heading: cur_heading,
  74. pitch: cur_pitch,
  75. roll: cur_roll
  76. },
  77. duration: 0.1
  78. })
  79. }
  80. try {
  81. let promise = scene.open(url);
  82. Cesium.when(promise, function (layers) { })
  83. }catch(e){
  84. message.error(e.message);
  85. }
  86. }
  87. },10)
  88. },function(err){
  89. console.log(err);
  90. })

    具体流程就是异步获取配置文件,得到所有的数据集信息,然后对这个数据集进行遍历,得到数据集的配置文件,解析配置文件中的位置信息,得到矩形范围转换成cesium中的矩形对象rectangle,然后将所有的矩形对象取并集。

    第70行处的代码是因为scene.open的自带的定位功能,可能会使得flyTo失效。具体的场景是:当当前视角与加载的图层的矩形范围存在交集,则视角不变(包括经纬度,高度,俯仰角等均不变)。但是却会出现一个问题,如果两次flyTo定位的视角都是一样的,那么视角就不会进行flyTo的动作,而是会定位到配置文件中的位置处。后来发现如果对视角进行一个微弱的数值改变,使其与上次的数值有不同,则可以正常进行flyTo。经测试,可以对Cartesian3的z坐标进行加1的操作,虽然进行了微调,但是在页面上是不会有明显的偏移的。

使用cesium中的scene.open中遇到的几个问题的更多相关文章

  1. 加载SpriteBuilder中的scene为何不能带后缀

    我们在Xcode中切换SpriteBuilder中的scene时,一般使用的是如下代码: -(void)exitButtonPressed:(CCControl*)sender{ CCLOG(@&qu ...

  2. Firebug中调试中的js脚本中中文内容显示为乱码

    Firebug中调试中的js脚本中中文内容显示为乱码 设置 页面 UFT-8 编码没用, 解决方法:点击 "Firebug"工具栏 中的"选项"---" ...

  3. JavaScript中让Html页面中循环播放文字

    JavaScript中让Html页面中循环播放文字 <html> <head> <meta http-equiv="Content-Type" con ...

  4. PHP中如何在数组中随机抽取n个数据的值 - array_rand()?

    PHP中如何在数组中随机抽取n个数据的值? 最佳答案 array_rand() 在你想从数组中取出一个或多个随机的单元时相当有用.它接受 input 作为输入数组和一个可选的参数 num_req,指明 ...

  5. 在eclipse的maven插件中搜寻本地仓库中的jar搜索不到的解决方案

    在eclipse的maven插件中搜寻本地仓库中的jar搜索不到的解决方案 之前,用过maven管理项目的童鞋都知道本地会有一个${User_Home}.m2/repository仓库 是用来存放ja ...

  6. .net dataGridView当鼠标经过时当前行背景色变色;然后【给GridView增加单击行事件,并获取单击行的数据填充到页面中的控件中】

    1.首先在前台dataGridview属性中增加onRowDataBound属性事件 2.然后在后台Observing_RowDataBound事件中增加代码 protected void Obser ...

  7. (原创)VM中的CentOS6.4中安装CloudStack6.3②

    接着VM中的CentOS6.4中安装CloudStack6.3①中文章接着,往下面安装 4.更新 yum 仓库 默认情况下,CentOS的软件源中没有收录最新版本CloudStack,为了能顺利安装, ...

  8. SQL中 将同一个表中的A列更新到B列,B列更新到A列

    有网友在SKYPE问及,如标题,SQL中 将同一个表中的A列更新到B列,B列更新到A列. 其实这个不是问题,直接写更新语句即可,可以参考下面动画演示: SQL source code: CREATE ...

  9. 解析sql语句中left_join、inner_join中的on与where的区别

    以下是对在sql语句中left_join.inner_join中的on与where的区别进行了详细的分析介绍,需要的朋友可以参考下 table a(id, type):id     type ---- ...

随机推荐

  1. C语言之带有数量可变的宏参数#define

    1.定义格式如下 #define PR(...)  printf(__VA_ARGS__) ...表示可变参数,__VA_ARGS__的作用是替换省略号的内容. 2.示例 #define ERROR( ...

  2. apache 部署

    <VirtualHost *:80> ServerAdmin webmaster@dummy-host.localhost DocumentRoot "D:/EmpireServ ...

  3. PAT Basic 1029 旧键盘 (20 分)

    旧键盘上坏了几个键,于是在敲一段文字的时候,对应的字符就不会出现.现在给出应该输入的一段文字.以及实际被输入的文字,请你列出肯定坏掉的那些键. 输入格式: 输入在 2 行中分别给出应该输入的文字.以及 ...

  4. [StructLayout(LayoutKind.Sequential) ] 是什么意思

    首先介绍一下 结构体和类的区别 :类是按引用传递 结构体是按值传递进入正题:结构体是由若干成员组成的.布局有两种1.Sequential,顺序布局,比如struct S1{int a;int b;}那 ...

  5. vue和cordova项目整合打包,并实现vue调用android的相机的demo

    经过网上查找很多资料,发现很多只有vue+cordova的项目整合,但是vue使用cordova插件的文章很少,现在把从创建cordova和创建vue到vue使用插件到项目打包到android手机运行 ...

  6. react保存用户的输入换行,空格等等

    <div dangerouslySetInnerHTML = {{ __html: '接口返回值' }} />

  7. 磁盘IO过高时的参考

    主要命令:echo deadline > /sys/block/sda/queue/scheduler 注:以下的内容仅是提供参考,如果磁盘IO确实比较大的话,是数据库,可以进行读写分离或者分库 ...

  8. layui 中的$符号有可以和jquery冲突,var & = layui.$

    在项目上使用到了滚动条插件,但是使用var & = layui.$,会影响到插件. 错误提示: Uncaught TypeError: $(...).perfectScrollbar is n ...

  9. 对JavaScript 引擎基础:原型优化的研究 -----------------------引用

    一.优化层级与执行效率的取舍 介绍了现代 JavaScript 引擎通用的工作流程: 我们也指出,尽管从高级抽象层面来看,引擎之间的处理流程都很相似,但他们在优化流程上通常都存在差异.为什么呢?为什么 ...

  10. vue 项目中 js命名规则

    类型 规范 示例 常量 全字符大写,单词用 '_' 分隔 FETCH_USERS.GET_USERS 变量.函数 小写开头驼峰式 camelCase 类.特殊意义的命名空间 大写开头驼峰式 Camel ...