产品介绍

Wish3D Earth是基于WebGL技术开发实现的三维地球渲染引擎,通过Wish3D Earth可以无需任何插件即可轻松的构建出在浏览器端可用的多功能三维数字地球,实现数据的快速共享。支持海量实景三维模型、影像、地形数据、三维模型的加载和展示;支持多种矢量数据格式的加载和展示;同时具备接入二维平台数据的能力,具备良好的扩展能力。

Wish3D Earth拥有强大的三维量测、可视域分析、体积量算、日照分析等特色功能,同时具备多种数据的场景构建与场景对比、单体化、模型压平、矢量标绘等特色应用,能够对辅助规划决策、管理规划成果数据起到重要作用。

平台采用多层架构,充分保证系统的安全性、跨平台性、易扩展性、易维护性,同时平台数据经过统一转换成为加密数据结构,在实现快速加载的同时,保证了数据的安全性。

数据层

数据层使用Postgress SQL和MongoDB作为数据存储仓库,Postgress SQL负责存储用户信息、权限信息、基本的场景、数据等;MongoDB负责存储大数据量的倾斜模型、地形、影像,以及一些零碎的文件数据。

服务层

服务层介绍

服务层使用Spring Cloud微服务,包含了三个重要的管理模块:场景管理器、用户管理器、团队管理器和数据管理器。场景管理器主要负责场景信息的保存与加载,包括数据图层、场景基本信息、场景视角等;用户管理器主要负责对用户的管理,包括注册用户、登陆\注销、密码服务、权限管理等;数据管理器主要负责对数据的上传、发布、处理及许可控制等。三个模块相互影响,缺一不可。

服务层开放接口API

API文档地址

API框架

应用层

应用层提供了后台管理系统和三维场景预览界面,后台管理系统提供了数据上传、场景编辑、用户管理、许可管理、以及磁盘预警等功能,作为统一的数据管理和场景管理平台;前端展示提供了场景和数据的三维可视化,并且包含丰富的三维功能,包括基础测量、三维分析、双屏对比、飞行浏览、单体化、模型压平,图层管理等。
注:应用层中的前端展示即为二次开发模块,用户可针对自身需求,定制属于自己的前端展示平台。

前端应用层有着丰富的三维数据、三维场景操作接口,基本类图结构如下:

类图结构

具体的示例代码请参考案例沙箱给出的示例。

如需查阅相关API内容,请参阅API说明文档

概述

Wish3D Earth是用于展示数据的平台,支持多种类型数据的混合加载,可对数据进行标绘、量测、分析等操作。但是这些操作必须是在场景中进行。Wish3D Earth的场景实际就是一个拟真的三维地球。如何构建一个拥有三维球的场景是开始开发的第一步。

Wish3D Earth SDK

SDK由两个部分构成,核心引擎和功能插件,如下图显示:

SDK构成

1.核心引擎如图展示:

核心引擎

2.功能插件包含:模型平移、测量、指北针、标绘绘制、水面、大矢量加载等,如图展示:

功能插件

场景构建

场景页面构建

<!DOCTYPE html>
<html lang="en">
 <head> 
  <meta charset="UTF-8" /> 
  <title>Hello World</title> 
  <link href="LSGlobe/Widgets/widgets.css" type="text/css" rel="stylesheet" /> 
  <script src="Build/LSGlobe/LSGlobe.js"></script> 
 </head> 
 <body> 
  <div id="lsGlobe" class="fullSize"></div> 
  <div id="loadingOverlay">
   <h1>Loading...</h1>
  </div>  
 </body>
</html>

初始化一个球

在初始化之前我们必须要有许可服务地址(lincenseUrl)和许可码(licenseCode),获取方法我们可以参考许可相关,来获取lincenseUrl和licenseCode。

初始化地球代码:


<!DOCTYPE html>
<html lang="en">
 <head> 
  <meta charset="UTF-8" /> 
  <title>Hello World</title> 
  <link href="LSGlobe/Widgets/widgets.css" type="text/css" rel="stylesheet" /> 
  <script src="Build/LSGlobe/LSGlobe.js"></script> 
 </head> 
 <body> 
  <div id="lsGlobe" class="fullSize"></div> 
  <div id="loadingOverlay">
   <h1>Loading...</h1>
  </div> 
  <script>
        var viewer = new LSGlobe.Viewer('lsGlobe', {
            baseLayerPicker: false,
            sceneModePicker: false,
            fullscreenButton:false,
            guid:licenseCode,
            //许可码
            licenseUrl:lincenseUrl
            //许可服务地址
        });
        //token是当前用户的登录凭证、权限验证凭证(如果没有用户系统可以不设)
        LSGlobe.LSOnline.defaultAccessToken = token;
    </script>   
 </body>
</html>

token :是当前用户的登录凭证,可以通过接口获取素材权限、团队权限、用户信息等,获取方法可以参照登录接口

场景事件

//1.初始化事件句柄
var handler = new LSGlobe.ScreenSpaceEventHandler(viewer.scene.canvas);

//2.添加事件句柄鼠标操作类型
handler.setInputAction(function (movement){
    //movement.position当前的屏幕坐标
}, LSGlobe.ScreenSpaceEventType.LEFT_CLICK);
//LEFT_DOWN左键按下时触发
//LEFT_UP 左键弹起时触发
//LEFT_CLICK 左击时触发
//RIGHT_CLICK 右击时触发
//DOUBLE_CLICK 双击时触发
//MOUSE_MOVE 鼠标移动时触发

//3.事件销毁
Handler.destroy();

场景坐标转换

//1.屏幕坐标转换和世界坐标相互转换

//屏幕坐标转世界坐标
var Pos=scene.pickGlobe(movement.position);
//movement.position 鼠标事件触发时返回的坐标

//世界坐标转屏幕坐标
var movement = LSGlobe.SceneTransforms.wgs84ToWindowCoordinates(scene, pos);
//scene 场景对象 pos世界坐标

//2.世界坐标和经纬度相互转换
//世界坐标转换为经纬度
var cartographic = LSGlobe.Cartographic.fromCartesian(Pos);
//Pos世界坐标对象  
var currentClickLon = LSGlobe.Math.toDegrees(cartographic.longitude);
//经度
var currentClickLat = LSGlobe.Math.toDegrees(cartographic.latitude);
//纬度
var height= cartographic.height;
//高度

//经纬度换为世界坐标转
var ellipsoid=viewer.scene.globe.ellipsoid;
var cartographic=LSGlobe.Cartographic.fromDegrees(longitude,latitude,height);
//longitude经度 latitude维度 height高度  
var cartesian3=ellipsoid.cartographicToCartesian(cartographic);

//3.经纬度弧度相互转换

//经纬度转弧度
LSGlobe.Math.toRadians(degrees)

//弧度转经纬度
LSGlobe.Math.toDegrees (radians)

素材

素材类型

目前Wish3DEarth支持的空间数据类型,如下表:

类型 格式 上传要求
实景三维 osgb 压缩成zip格式
人工模型 obj、fbx、skp obj需要将纹理等附属文件一并压缩成zip文件;skp直接上传
矢量数据 shp、kml shp需要将所有同名文件一并压缩成zip文件;kml直接上传
影像数据 tif tif文件直接上传
地形数据 tif tif文件直接上传

素材管理

素材上传前端使用插件是webuploader.js,数据的上传是分片上传的,上传前获取MD5码,上传完成后请求后台合并文件接口。数据的修改和删除均是利用ajax请求后台接口进行操作的。具体接口请查询api文档素材相关

素材预览

注意事项:使用sdk开发的用户会出现数据加载时跨域,无法正常加载数据的情况.此时需要在加载数据之前,将要跨域的服务地址(ip和port),添加到后台管理系统菜单中的 系统管理设置白名单中

域名白名单

在加载数据之前我们需要获取素材的路径,通过请求素材信息接口返回的参数中取extraJson字段中的jsonPath(下面引用地方均指该参数)。

实景三维数据的预览

  1. 加载实景三维数据

     var sTimeSeconds = new Date().getTime(); //防止缓存
     var tileset = new LSGlobe.LSPageLOD({
         //dataGuid 数据的唯一标识
         url: jsonPath + "?" + sTimeSeconds,
         shadows: LSGlobe.ShadowMode.DISABLED,
         //开启将耗性能
         // shadows属性值详解
         // LSGlobe.ShadowMode.ENABLED  即接受阴影也自己投影
         // LSGlobe.ShadowMode.DISABLED  即不接受投影也不自己投影
         // LSGlobe.ShadowMode.RECEIVE_ONLY 只接受阴影不自己投影
         // LSGlobe.ShadowMode.CAST_ONLY  不接受阴影只自己投影
         viewer: viewer
     });
     tileset.name = {
         "在加入到场景时添加一些字段来区分各种数据,预览时无需添加"
     }
     //倾斜模型对象加入到球中
     viewer.scene.pageLODLayers.add(tileset);
     tileset.readyPromise.then(function(pagelod) {
         //飞到倾斜模型的位置(可解决中心点不准问题)
         var oCenter = tileset.tileBoundingSphere.center;
         var cartesian3 = new LSGlobe.Cartesian3(oCenter.x, oCenter.y, oCenter.z);
         var cartographic = ellipsoid.cartesianToCartographic(cartesian3);
         var lat = LSGlobe.Math.toDegrees(cartographic.latitude);
         var lng = LSGlobe.Math.toDegrees(cartographic.longitude);
         var height = cartographic.height;
         viewer.camera.flyTo({
             destination: LSGlobe.Cartesian3.fromDegrees(lng, lat, height + 1500),
             duration: 1 //过渡时间,单位秒
         })
     }).otherwise(function(error) {
         console.error(error); //打印报错内容(可扩展通知等方法)
     });
    

人工三维数据的预览

与倾斜模型不同,倾斜模型一般是由无人机飞出来数据,经过建模软件处理最终生成带有坐标信息的瓦片文件,而人工三维数据通常不带坐标信息,需要我们自己指定好放人工三维数据的坐标,才能达到我们想要的效果。

人工三维数据最终加载有两种方式,是由数据转换环节决定的,目前Wish3D Earth统一把obj数据转换为lmz数据,skp数据和fbx数据转为3dtiles数据。lmz数据加载是等所有细节加载完成后再显示在场景中,适合体积小且简单的模型加载。3dtiles数据加载是根据角度可视区域加载,因此不会因为数据过大导致阻塞假死现象出现,适合体积较大细节复杂的人工模型(体积小的效果媲美lmz)。

  1. lmz加载(obj转换为lmz)

     //人工三维加载的位置信息可自己设置
     var position={x:120,y:30,z:0};
     var model = new LSGlobe.LSModelLOD({
         //dataGuid 数据的唯一标识
         url :jsonPath,
         shadows : LSGlobe.ShadowMode.ENABLED,
         // shadows属性值详解
         // LSGlobe.ShadowMode.ENABLED  即接受阴影也自己投影
         // LSGlobe.ShadowMode.DISABLED  即不接受投影也不自己投影
         // LSGlobe.ShadowMode.RECEIVE_ONLY 只接受阴影不自己投影
         // LSGlobe.ShadowMode.CAST_ONLY  不接受阴影只自己投影
         position : new LSGlobe.Cartesian3(position.x,position.y, position.z)
     });
     model.name={"在加入到场景时添加一些字段来区分各种数据,预览时无需添加"}
     //人工模型加入到球中
     viewer.scene.primitives.add(model);
     //飞到人工模型的位置
     viewer.camera.flyTo({
         destination : LSGlobe.Cartesian3.fromDegrees(position.x,position.y,position.z+120),
         orientation : {
             heading : LSGlobe.Math.toRadians(0.0),
             pitch : LSGlobe.Math.toRadians(-90.0),
             roll : 0.0
         },
         duration: 2
     });
    
  2. 3dtiles(skp转换为3dtiles)

     var tileset = new LSGlobe.Cesium3DTileset({
         //dataGuid 数据的唯一标识
         url: jsonPath,
         maximumScreenSpaceError:0
     });
     //上面的Cesium3DTileset如果不能正常加载可替换为LSGlobe3DTiles
     //3dtiles加入到球中
     tileset.name={"在加入到场景时添加一些字段来区分各种数据,预览时无需添加"}
     viewer.scene.primitives.add(tileset);
     tileset.readyPromise.then(function(tileset) {
         //飞到3dtiles模型的位置
         var boundingSphere = tileset.boundingSphere;
         viewer.camera.viewBoundingSphere(boundingSphere, new LSGlobe.HeadingPitchRange(0, -2.0, 0));
         viewer.camera.lookAtTransform(LSGlobe.Matrix4.IDENTITY);
     });
    

矢量数据的预览

目前Wish3D Earth支持shp和kml数据加载。

  1. shp加载,Wish3D Earth已经支持大矢量数据加载,加载此类数据需要使用插件VectorTileProvider.js。在页面中引用该插件,代码如下:

     <!DOCTYPE html>
     <html lang="en">
     <head>
         <meta charset="UTF-8">
         <title>Hello World</title>
         <link href="LSGlobe/Widgets/widgets.css" type="text/css" rel="stylesheet" />
         <script src="Build/LSGlobe/LSGlobe.js"></script>
         <script src="Plugins/VectorTileProvider.js"></script>
     </head>
     <body>
     <div id="lsGlobe" class="fullSize"></div>
     <div id="loadingOverlay"><h1>Loading...</h1></div>
     <script>
         var viewer = new LSGlobe.Viewer('lsGlobe', {
             baseLayerPicker: false,
             sceneModePicker: false,
             fullscreenButton:false,
             guid:licenseCode,
             //许可码
             licenseUrl:lincenseUrl
             //许可服务地址
         });
         //token是当前用户的登录凭证
         LSGlobe.LSOnline.defaultAccessToken = token;
     </script>
     </body>
     </html>    
    

    加载矢量代码如下:

     oShpImageLayer = new LSGlobe.VectorTileProvider({
         url: jsonPath,
         viewer: viewer
     });
     //设置矢量样式
     var oStyle = {
                 styletyle: "default",
                 color: "rgba(187, 187, 187,1)",//矢量的颜色
                 lineType: LSGlobe.VectorTileLineType.SOLID,//边框类型
                 lineWidth: 2,//边框宽度
                 outline: false,//是否显示边框
                 outlineColor: "#2196F3",//边框
                 icon: "images/GEMarker/red-circle.png",//如果是矢量点,则用该图标路径
                 textField: "NAME",//参照字段
                 font: 'bold 14px sans-serif'//字体相关
             };
     var styles = new LSGlobe.VectorTileStyleCollection([new LSGlobe.VectorTileStyle(oStyle)]);
    
     /*
     var style = new LSGlobe.VectorTileStyle({
                     color: LSGlobe.Color.fromRandom().toCssColorString(),
                     classificationField: 'height',//参照字段
                     classificationFieldValue: [301, 400]//对应字段的数值区间
             });
     */
     //正常显示样式
    oShpImageLayer.styles = styles;
    //选种样式
    oShpImageLayer.selectedStyles = styles;//最好和正常样式有区别这样才能体现选中效果
    
     viewer.imageryLayers.addImageryProvider(oShpImageLayer);
     oShpImageLayer.readyPromise.then(function (flag) {
         var rect = oShpImageLayer._rectangle;
         viewer.camera.flyTo({
             destination: rect
         });
     }).otherwise(function (error) {
             console.error(error);
     })
    
  2. KML加载

     var options = {
         camera: viewer.scene.camera,
         canvas: viewer.scene.canvas,
         clampToGround: true
     };
     //dataGuid 数据的唯一标识
     var promise= LSGlobe.KmlDataSource.load(jsonPath,options);
     promise.then(function(dataSource){
         dataSource.name ={"在加入到场景时添加一些字段来区分各种数据,预览时无需添加"}
         //KML加载到球中
         viewer.dataSources.add(dataSource);
         //飞到KML数据的位置
         viewer.flyTo(dataSource);
     }).otherwise(function(error) {
         console.error("加载kml数据失败");
     });
    

影像数据的预览

  1. 载lrc文件影像(Wish3D Earth中的谷歌影像、天地图影像均采用该接口)

     var oLrcImgPath = "lrc/google-satellite.lrc";//lrc文件路径
     var oGoogleImg = new LSGlobe.LSLRCImageryProvider(oLrcImgPath);
     oGoogleImg.name = "google";
     viewer.imageryLayers.addImageryProvider(oGoogleImg);
    
    
  1. 加载tif经过earth服务处理后的影像(Wish3D Earth 服务处理后的数据)

    
     var imageryLayers = viewer.imageryLayers;
     var imageLayer = new LSGlobe.LSImageryProvider({
         "url": jsonPath
     })
     currentImageLayer = imageLayer;
     imageryLayers.addImageryProvider(imageLayer);
     imageLayer.readyPromise.then(function (flag) {
         var rect = imageLayer.rectangle;
         viewer.camera.flyTo({
             destination: rect
         });
     }).otherwise(function (error) {
         console.error(error)
     });
    
    

地形数据的预览

var terrainLayers = viewer.terrainLayers;
var terrainLayer = new LSGlobe.LSLRPTerrainProvider({
    "url": jsonPath
}) terrainLayer.name = {
    "在加入到场景时添加一些字段来区分各种数据,预览时无需添加"
}
//地形加载到球中
terrainLayers.addTerrainProvider(terrainLayer);
terrainLayer.readyPromise.then(function(flag) {
    var rect = imageLayer._rectangle;
    //飞到地形数据的位置
    viewer.camera.flyTo({
        destination: rect
    });
}).otherwise(function(error) {
    console.error(error);
})  

场景

场景构建保存

  • 场景构建

场景是用数据构建成的,场景中可以添加多种数据(目前该平台支持:osgb、obj、skp、shp、kml、tif影像、tif地形等),每种数据也可添加多个,对于人工模型只上传一次即可在场景中添加多个相同的数据,用户可以使用自己添加的数据来构建自己想要的各种场景,除此之外还可以利用标绘功能进行点、线、面、单体化、压平、水面、裁剪,达到预期的效果。

场景数据结构

  1. 场景添加

    进行场景构建之前需要先定义场景,由于场景的数据保存是以json的格式保存所以也可以人为的拼接一个和场景相关的json数据和定义场景关联起来,以达到场景构建时就拥有某些数据(该方法主要用于添加场景默认的底图)

    保存场景的接口(既可以新增也可以更新,区别在于传参里面的sceneId数据库是否已存在,存在即更新,反之是新增)

    http://localhost:1000/wish3dearth/api/scene/v1.0.0/saveScene

    其中dataJson需要注意,是json对象通过JSON.stringify()方法转换而来的字符串,json对象实例代码如下:

     var oSubSceneData = {
     /*场景基本信息*/
         basicInfo: {
             'sceneId': "a3f13f9410d540818a45c84eb38dacbe",//场景id
             'title': '我的场景',//场景名称
             'keyWord': '',//场景开屏弹框
             'coverImg': '',//缩略图部分路径
             'logoImg': '',//场景Logo
             'description': '',//场景标注
             'sceneStatus': '1',//1:正式保存,2:临时保存,3:另存为
             'viewPoint':{
                 /*场景的默认视角的基本信息*/
                 "posx":-2764325.5750570972,
                 "posy":4787969.484454991,
                 "posz":3170427.8013527235,
                 "upx":0.10971595179642417,
                 "upy":-0.2804932817046718,
                 "upz":0.9535648529806184,
                 "directionx":0.4685107860447898,
                 "directiony":-0.8315036975588643,
                 "directionz":-0.2984949652936043,
                 "viewImg":"image/eca4f9ac49e84d26a0e2a5212480010b.jpg"//场景默认视角的缩略图
                 }
         },
         /*该对象通过viewer.toJSON()获取,二次组合JSON*/
         scene: {
             "VERSION": "1.6.534",//手动加入:js引擎版本号,LSGlobe.VERSION获取
             "asset": {
                 "version": "1.0.0",
                 "date": "2019-12-18 17:06:36"
             },
             Tree:"",//手动加入:zTree节点数组,JSON.stringify(oLayerTree.transformToArray(oLayerTree.getNodes())),oLayerTree是zTree实例化对象
             "scene": {
                 "properties": {
                     "minimumDisableDepthTestDistance": 0,
                     "shadows": true
                 },
                 /*人工模型图层*/
                 "layers": [],
                 /*实景三维模型图层*/
                 "pageLODLayers": [],
                 /*影像或shp矢量数据图层*/
                 "imageryLayers": [
                     {
                         "show": true,
                         "name": "LSGlobe/Build/LSGlobe/Assets/Textures/GlobalBkLayer.jpg",
                         "url": "LSGlobe/Build/LSGlobe/Assets/Textures/GlobalBkLayer.jpg",
                         "tileWidth": 1024,
                         "tileHeight": 512,
                         "tilingScheme": {
                             "type": "GeographicTilingScheme",
                             "numberOfLevelZeroTilesX": 1,
                             "numberOfLevelZeroTilesY": 1
                         }
                     }, {
                         "type": "LSLRCImageryProvider",
                         "show": true,
                         "name": "google",
                         "url": earth_url + "LSGlobe/lrc/google-satellite.lrc",
                         "tilingScheme": {
                             "type": "WebMercatorTilingScheme",
                             "numberOfLevelZeroTilesX": 1,
                             "numberOfLevelZeroTilesY": 1
                         }
                     }, {
                         "type": "LSLRCImageryProvider",
                         "show": true,
                         "name": "skyLandImage",
                         "url": earth_url + "LSGlobe/lrc/skyLandMarker.lrc",
                         "tilingScheme": {
                             "type": "GeographicTilingScheme",
                             "numberOfLevelZeroTilesX": 2,
                             "numberOfLevelZeroTilesY": 1
                         }
                     }
                 ],
                 /*矢量图层*/
                 "datasources": [],
                 /*地形图层*/
                 "terrainLayers": [{
                     "type": "LRPTerrainProvider",
                     "show": true,
                     "name": "Terrain1800",
                     "url": "http://e0.wish3d.com/servicedata/globalocean/globalocean.ltc"
                 }]
             }
         },
         fly: {
             "sceneId":"4a8cbec3413417e58f227060e464c7c5",
             "lines":[{
                 "id":"1730757e513417e310674b92267f33ad",//路径id
                 "title":"飞行路径",//路径名称
                 /*关键视点数组*/
                 "points":[{
                     "id":"846f1897313417e3106751bdd54f5365",//视点id
                     "title":"视点",//视点名称
                     /*视点视角的基本信息*/
                     "directionx":0.4685107860447907,
                     "directiony":-0.8315036975588634,
                     "directionz":-0.29849496529360536,
                     "posx":-2764325.5750570996,
                     "posy":4787969.48445499,
                     "posz":3170427.8013527235,                
                     "upx":0.10971595179642323,
                     "upy":-0.28049328170467314,
                     "upz":0.9535648529806181,
    
                     "timeInterval":2,//视点的过渡时间,单位s
    
                     "viewImg":"temp/scene/4a8cbec3413417e58f227060e464c7c5/image/e5b067e5febe4df7a155f26d3515a0be.jpg"//视点的缩略图路径
                     }]
                 }
             ]
         },
         splitscreen: {
             "sceneId":"4a8cbec3413417e58f227060e464c7c5",
             "screens":[{"id":"b5eedb0ad13417e4f4f44d7c3ca436cd"//...场景信息
                 }]
         },
         draw: {},//drawDataSource.toGeoJson()获取
         monomer: {},//monomerDataSource.toGeoJson()获取
         push: {},//pushDataSource.toGeoJson()获取
         water: {},//waterDataSource.toGeoJson()获取
         clip: {},//cutDataSource.toGeoJson()获取
         drawDetail: {
             "sceneId":"4a8cbec3413417e58f227060e464c7c5",
             /*点的附属信息*/
             "points":[
                 {
                     "id":"48305169713417e3109408c9e90242b1",
                     "title":"无标题",
                     "viewPoint":{
                         /*视角视角信息*/
                         "posx":-2764325.5750570996,
                         "posy":4787969.48445499,
                         "posz":3170427.8013527235,
                         "upx":0.1097159517963033,
                         "upy":-0.2804932817046312,
                         "upz":0.9535648529806443,
                         "directionx":0.4685107860447907,
                         "directiony":-0.8315036975588634,
                         "directionz":-0.29849496529360536,
                         "viewImg":"temp/scene/4a8cbec3413417e58f227060e464c7c5/image/05aaf15a88354e0793feea8bf5c5fefa.jpg"
                     },
                     "text":{
                         "title":"dfdf",//文本标题
                         "content":"dffd"//文本内容
                     },
                     "image":{
                         "title":"dfdf",//图片标题
                         "pics":[
                             {"id":"306c7418d13417e31095a1f02edec708",//图片id
                             "path":"temp/scene/4a8cbec3413417e58f227060e464c7c5/file/5ac7f5def6084bebb33632a05b3c4c4e.png"//图片路径
                             }]
                     },
                     "video":[{"id":"1b4a148a013417e31095edf386cff10a",//视频id
                             "title":"fdf",//视频标题
                             "type":"2",//视频类型,1:本地上传 2:在线视频
                             "url":"http:video.com"
                     }],
                     "panoramic":[{
                             "id":"311167ca313417e31096b4c4d3c9a345",//全景id
                             "title":"720",//全景标题
                             "url":"http://720yun.com"//全景链接
                 }]
                 }
             ]},
         deleteObj: {
             'sceneId': "a3f13f9410d540818a45c84eb38dacbe",
             'images': [],//删除的图片路径
             'videos': [],//删除的视频路径
             'drawDetails': []//删除的entity的id
         }
     }
    

    如果场景里面含有shp矢量数据,还要把对应的shp涂层的样式存储,接口如下:

    其中注意参数styleJson,该参数是对应的shp矢量数据的imageryProvider.styles.toJson()得到

    http://localhost:1000/wish3dearth/api/material/shp/v1.0.0/setStyle

  2. 场景基本信息获取

    通过接口获取当前场景的基本信息,返回信息包含场景id、名称、描述、缩略图、默认视角等信息,详情参照一下接口。

    http://localhost:1000/wish3dearth/api/scene/v1.0.0/getSceneJsonInfo

  3. 场景飞行到默认位置(相机定位接口)

    从上一条获取到场景的默认视角字段,经过转换后得到视角信息, 然后利用以下方法飞行到默认位置。

     //position direction up保存的视角信息
     viewer.camera.flyTo({
         destination :new LSGlobe.Cartesian3(position.x,position.y,position.z),
         orientation : {
             direction : new LSGlobe.Cartesian3(direction.x,direction.y,direction.z),
             up : new LSGlobe.Cartesian3(up.x,up.y,up.z)
         }
     });
    
    
  4. 场景删除

    删除接口参照:

    http://localhost:1000/wish3dearth/api/scene/v1.0.0/deleteScene

  5. 场景图层信息

    获取场景图层信息接口,参数jsonType=1如下:

    http://localhost:1000/wish3dearth/api/scene/v1.0.0/getSceneJsonInfo

    返回参数data直接加载到场景中,方法如下:

     //加载到场景
     viewer.fromJSON(data);
      //使用上面方法数据会自动加载到球上形成一个场景
    

    zTreec插件使用方法可以参照插件官网

    data.Tree数据,树结构渲染(通过 zTree插件渲染)

     //初始化树
     $.fn.zTree.init($("#treeLayer"), {}, data.Tree);
    
  6. 场景中数据管理

    场景中一般有多个,多种类型的数据,我们需要对这些数据进行操作管理达到构建场景的目的。

    1.场景中的数据获取

     //1).实景三维数据获取
     viewer.scene.pageLODLayers._pageLODs[1] //1是实景三维数据的索引
     //为了精确获取实景三维数据可使用根据数据id获取的方式获取,获取方法如下
     function getPageLODLayersById(primitiveid) {
         var aPrimitives = viewer.scene.pageLODLayers;
         var oPrimitive = "";
         for (var i = 0; i < aPrimitives._pageLODs.length; i++) {
             if ( !! aPrimitives._pageLODs[i].name) {
                 if (aPrimitives._pageLODs[i].name.guid == primitiveid) {
                     oPrimitive = aPrimitives._pageLODs[i];
                     break;
                 }
             }
         }
         return oPrimitive;
     }
     //2).人工三维数据获取
     viewer.scene.primitives._primitives[1] //1是人工三维数据的索引
     //精确获取参照实景三维数据获取方法
     //3).矢量数据获取
     viewer.dataSources._dataSources[1] //1是矢量数据的索引
     //精确获取参照实景三维数据获取方法
     //4).影像数据获取
     viewer.scene.imageryLayers._layers[1] //1影像数据的索引
     //精确获取参照实景三维数据获取方法
     //5).地形数据获取
     viewer.scene.terrainLayers._layers[1] //1是地形数据的索引
     //精确获取参照实景三维数据获取方法
    
    

    2.场景中的数据飞行

     //1).实景三维数据飞行
         //tileset第一步获取的数据对象
         var oCenter=tileset.tileBoundingSphere.center;
         var cartesian3=new LSGlobe.Cartesian3(oCenter.x,oCenter.y,oCenter.z);
         var cartographic=ellipsoid.cartesianToCartographic(cartesian3);
    
         var lat=LSGlobe.Math.toDegrees(cartographic.latitude);
         var lng=LSGlobe.Math.toDegrees(cartographic.longitude);
         var height=cartographic.height;
         viewer.camera.flyTo({
             destination: LSGlobe.Cartesian3.fromDegrees(lng, lat, height + 1500),
             duration: 1
         })
     //2).人工三维数据飞行
         //tileset第一步获取的数据对象(lmz格式)
         var addpointStrs = tileset._position.split(',');
         viewer.camera.flyTo({
             destination : LSGlobe.Cartesian3.fromDegrees(addpointStrs[0],addpointStrs[1], addpointStrs[2]+120),
             orientation : {
                     heading : LSGlobe.Math.toRadians(0.0),
                     pitch : LSGlobe.Math.toRadians(-90.0),
                     roll : 0.0
             },
             duration: 2
         });
         //tileset第一步获取的数据对象(3tiles格式)
         var boundingSphere = tileset.boundingSphere;
         viewer.camera.viewBoundingSphere(boundingSphere, new LSGlobe.HeadingPitchRange(0, -2.0, 0));
         viewer.camera.lookAtTransform(LSGlobe.Matrix4.IDENTITY);
     //3).矢量数据飞行
         //datasource第一步获取的数据对象
         viewer.flyTo(datasource)
     //4).影像数据飞行
             //imageLayer第一步获取的数据对象
             var rect = imageLayer._imageryProvider.rectangle;
             viewer.camera.flyTo({
                 destination: rect
             }, {duration: 3});
    
     //5).地形数据飞行
             //terrainLayer第一步获取的数据对象
             var rect = terrainLayer._imageryProvider.rectangle;
             viewer.camera.flyTo({
                 destination: rect
             }, {duration: 3});
    

    3.场景中的数据显示隐藏

     //1).实景三维数据显示隐藏
         //tileset第一步获取的数据对象
         tileset.show=false;
         //false 隐藏 true 显示
     //2).人工三维数据显示隐藏
         //参考实景三维数据显示隐藏
     //3).矢量数据显示隐藏
         //参考实景三维数据显示隐藏
     //4).影像数据显示隐藏
         //参考实景三维数据显示隐藏
     //5).地形数据显示隐藏
         //参考实景三维数据显示隐藏
    

    4.场景中的数据删除

     //1).实景三维数据删除
         //tileset第一步获取的数据对象
         viewer.scene.pageLODLayers.remove(tileset)
     //2).人工三维数据删除
         //tileset第一步获取的数据对象
         viewer.scene.primitives.remove(tileset)
     //3).矢量数据删除
         //dataSources第一步获取的数据对象
         viewer.dataSources.remove(dataSources)
     //4).影像数据删除
         //imageLayer第一步获取的数据对象
         viewer.imageryLayers.remove(imageLayer)
     //5).地形数据删除
         //terainLayer第一步获取的数据对象
         viewer.imageryLayers.remove(terainLayer)
    

场景底图

加载在线影像

//1).google影像
var google = new LSGlobe.UrlTemplateImageryProvider({
    url: 'http://mt0.google.cn/vt/lyrs=s&hl=zh-CN&x={x}&y={y}&z={z}',
    tilingScheme: new LSGlobe.WebMercatorTilingScheme(),
    maximumLevel: 20,
    name: "google"
});
viewer.imageryLayers.addImageryProvider(google);
//2).天地图        
var tianditu = new LSGlobe.WebMapTileServiceImageryProvider({
    url: "http://t0.tianditu.com/img_w/wmts?service=wmts&request=GetTile&version=1.0.0&LAYER=img&tileMatrixSet=w&TileMatrix={TileMatrix}&TileRow={TileRow}&TileCol={TileCol}&style=default&format=tiles&tk=9dd6ff82e27b5411290191ae41776f6d",
    layer: "tdtBasicLayer",
    style: "default",
    format: "image/jpeg",
    tileMatrixSetID: "GoogleMapsCompatible",
    show: false
}) viewer.imageryLayers.addImageryProvider(tianditu);
//3).bingmap
var bing = new LSGlobe.BingMapsImageryProvider({
    url: 'https://dev.virtualearth.net',
    key: 'Ak1xFbfMYLAAsWU7cZMRyvDHY13HFN1PESWP98WJLoK49OQDb8HSeUjBV3MpC5Yf',
    //bingmap秘钥
    mapStyle: LSGlobe.BingMapsStyle.AERIAL
});
viewer.imageryLayers.addImageryProvider(bing);

加载lrc文件作为底图

var oLrcPath = "lrc文件路径";
var oLrc = new LSGlobe.LSLRCImageryProvider(oLrcPath);
viewer.imageryLayers.addImageryProvider(oLrc);

设置图层的层级

//初始添加影像时设置层级
viewer.imageryLayers.addImageryProvider(bing, index);
//index影像图层的层级number类型,对lrp也适用
//设置某一个影像为最高层级
viewer.imageryLayers.raiseToTop(imageLayer)
//imageLayer获取的影像对象

设置在线google地形(google地形为国外数据加载较慢)

 var stkTerrainProviderMeshes = new LSGlobe.CesiumTerrainProvider({
    url: 'http://assets02.agi.com/stk-terrain/v1/tilesets/world/tiles',
    requestWaterMask: true,
    requestVertexNormals: true
});
viewer.terrainLayers.addTerrainProvider(terrainLayer);

飞行

飞行路径构建

  1. 添加一条飞行路径,即向场景JSON,oSubSceneData.fly.lines数组添加路径

     oSubSceneData.fly={
         "sceneId":"4a8cbec3413417e58f227060e464c7c5",
         "lines":[]
     }
     //添加一条飞行路径
     var line={
         "id":"1730757e513417e310674b92267f33ad",//路径id
         "title":"飞行路径",//路径名称
         /*关键视点数组*/
         "points":[]
     }
     oSubSceneData.fly.lines.push(line)
     //向飞行路径中添加当前视点
     var oPos=viewer.camera.postion;
     var oDir=viewer.camera.direction;
     var oUp=viewer.camera.up;
    
     line.points.push({
         "id": "846f1897313417e3106751bdd54f5365",
         //视点id
         "title": "视点",
         //视点名称
         /*视点视角的基本信息*/
         "posx": oPos.x,
         "posy": oPos.y,
         "posz": oPos.z,
         "directionx": oDir.x,
         "directiony": oDir.y,
         "directionz": oDir.z,        
         "upx": oUp.x,
         "upy": oUp.y,
         "upz": oUp.z,
    
         "timeInterval": 2,
         //视点的过渡时间,单位s
         "viewImg": "temp/scene/4a8cbec3413417e58f227060e464c7c5/image/e5b067e5febe4df7a155f26d3515a0be.jpg" //视点的缩略图路径
     });
    
    
  2. 修改、删除某条飞行路径

    修改数飞行路径的名称和视点仅修改对应数组的信息,最后随场景保存接口一并提交

  3. 获取飞行路径

    根据场景id获取飞行路径

    http://localhost:1000/wish3dearth/api/scene/v1.0.0/getSceneJsonInfo

  4. 生成视点缩略图,并上传该图片,同时修改对应视点的缩略图路径(标注缩略图获取方法相同)

     //截取canvas方形图片    
     var oOriginImg = $("#visibleImg");
     var canvasWidth = $("canvas").width();
     var canvasHeight = $("canvas").height();
     var sImg = getRenderer();
     oOriginImg.off("load");
     oOriginImg.attr("src", sImg);
     oOriginImg.attr("style", "width:" + canvasWidth + "px;height:" + canvasHeight + "px;");
     oOriginImg.off("load").load(function () {
         //原始尺寸
         var orinWidth = oOriginImg.width();
         var orinHeight = oOriginImg.height();
         //计算比例
         var fProportion = parseFloat(orinHeight / orinWidth);
         //现在尺寸
         var iCurrentWidth = orinWidth;
         var iCurrentheight = orinHeight;
         if (fProportion >= 1) {
             iCurrentWidth = parseInt(orinWidth * 0.6);
             iCurrentheight = iCurrentWidth;
         } else {
             iCurrentWidth = parseInt(orinHeight * 0.6);
             iCurrentheight = iCurrentWidth;
         }
         var left = parseInt(orinWidth / 2) - parseInt(iCurrentWidth / 2);
         var top = parseInt(orinHeight / 2) - parseInt(iCurrentheight / 2);
         var crop_canvas = document.createElement('canvas');
         crop_canvas.width = 150;
         crop_canvas.height = 150;
         crop_canvas.getContext('2d').drawImage(oOriginImg.get(0), left, top, iCurrentWidth, iCurrentheight, 0, 0, 150, 150);
         var imgUrl = crop_canvas.toDataURL("image/jpeg");
     });
    
     //注意:每添加一个飞行视点或者删除一个视点都需要更新一下对应该条飞行路径的视点的缩略图,并操作oSubSceneData.deleteObj.images数组
    
  5. 上传飞行视点的缩略图

    上传接口参照http://localhost:1000/wish3dearth/api/scene/v1.0.0/uploadTempImg

飞行路径的预览

  1. 初始化一条飞行路径

     var cameraTrackControls = new LSGlobe.LSCameraTrackControls(viewer.scene);
    
  2. 向飞行路径中添加视点信息

     //向飞行路径中添加单个视点
     //pos,direction,up这些值是保存视点中的相机位置信息
     //timeDelta 保存视点中的timeInterval值
     cameraTrackControls.getAllKeys().push(
     {
         destination: new LSGlobe.Cartesian3(posx,posy,posz),
         orientation: {
             direction: new LSGlobe.Cartesian3(directionx,directiony,directionz),
             up: new LSGlobe.Cartesian3(upx,upy,upz)
         },
         time: timeDelta
     });
     //添加视点完成该飞行路径初始化完成
    
  3. 飞行路径的操作

     //开始飞行路径的飞行或继续飞行路径的飞行
     cameraTrackControls.play();
    
     //暂停飞行路径的飞行,从暂停视点开始飞行
     cameraTrackControls.pause();
    
     //清除飞行路径并停止飞行路径的飞行
     cameraTrackControls.clear();
    
     //停止飞行路径的飞行,再次飞行从第一个视点飞行
     cameraTrackControls.stop()
    
    

标绘

标绘功能包含标绘点、标绘线、标绘面。这些标绘信息统一保存在一个drawDataSource对象中,保存时数据可转换为json文件,加载时获取到之前保存的json,可以统一一次将各种标绘数据加载到场景中并与保存前的显示效果一致。

为了更好的绘制体验,标绘线面的绘制可以应用现在封装好的线面绘制插件来绘制。而标注的绘制需要在事件句柄中点击绘制添加

初始化标绘存储对象

var drawDataSource;
//标绘存储对象绘制的标绘要素(线或者面)会保存到该对象中
var promise = viewer.dataSources.add(new LSGlobe.GeoJsonDataSource("drawDataSource"));
promise.then(function(dataSource) {
    drawDataSource = dataSource;
}).otherwise(function(error) {

});

标绘绘制

绘制点

  1. 添加至场景

     //第一步新加事件句柄
     var handler = new LSGlobe.ScreenSpaceEventHandler(viewer.scene.canvas);
     handler.setInputAction(function(movement) {
         //获取的坐标上添加标绘点,具体的坐标获取参照坐标转换
         var Pos = scene.pickGlobe(movement.position);
     },
     LSGlobe.ScreenSpaceEventType.LEFT_CLICK);
    
     //第二部将标注添加到球上
     //drawDataSource 保存标绘集合的对象,标绘初始化定义的
     var NewPoint = drawDataSource.entities.add({
         //标注的坐标 x,y,z 经度纬度和高度的值
         position: new LSGlobe.Cartesian3(Pos.x, Pos.y, Pos.z),
         label: {
             text: name,
             //标注文字描述
             font: "32px Microsoft YaHei",
             //标注文字大小、字体
             style: LSGlobe.LabelStyle.FILL_AND_OUTLINE,
             outlineWidth: 6,
             translucencyByDistance: new LSGlobe.NearFarScalar(1.5e2, 1.0, 1.5e5, 0.0),
             //根据告诉改变透明度
             horizontalOrigin: LSGlobe.HorizontalOrigin.LEFT,
             pixelOffset: new LSGlobe.Cartesian2(15, -15),
             disableDepthTestDistance: 0,
             //标注的遮挡距离设置为100则视角与标注的距离大于100米时会有遮挡
             scale: 0.5
         },
         billboard: {
             image: iconPath,
             //标注图标路径
             width: 64,
             height: 64,
             disableDepthTestDistance: 1000000000,
             //标注的遮挡距离设置为100则视角与标注的距离大于100米时会有遮挡
             scale: 0.5,
             translucencyByDistance: new LSGlobe.NearFarScalar(1.5e2, 1.0, 1.5e5, 0.0),
         },
         id: id,
         //标注唯一标识
         show: true //标绘点对象的true显示,false隐藏属性
     });
    
     NewPoint.properties.addProperty(des, description);
     //使用该方法加入单个自定义属性  des自定义属性名 description自定义属性值
     //NewPoint刚刚添加的标绘点对象
     NewPoint.properties = new LSGlobe.PropertyBag({
         des: description
     });
     //使用该方法加入多个自定义属性  des自定义属性名 description自定义属性值
     //NewPoint刚刚添加的标绘点对象
     //标绘点自定义属性中一般需要有标绘点的图片地址信息和相机位置信息 这些信息需要添加到自定义的属性中用于再次加载时使用
    
    
  2. 缩略图信息上传

    获取标绘点缩略图同飞行视点获取视点的缩略图一致。

  3. 标会点附属信息

    每个标绘点都可以挂载附属信息,分为文本、图片、视频、全景,在Wish3DEarth中称其为附属信息。在场景设置中,所有标会点的附属信息,均存储在oSubSceneData.drawDetail.points中(如需要其他标绘也可以挂载在不同属性中),

     //附属信息容器
     oSubSceneData.drawDetail= {
         'sceneId': '场景ID',
         'points': []
     },
     //附属信息单个示例
    var oDrawDetail={
     'id': 'GUID',
     'title': '名称',
     'viewPoint': {
         /*标绘点的视角信息*/
         "posx": -2765417.479773966600000,
         "posy": 4789433.917735196000000,
         "posz": 3171073.033866435000000,
         "upx": 0.479484059578550,
         "upy": 0.042675029450645,
         "upz": 0.876512337888898,
         "directionx": 0.578378444536402,
         "directiony": -0.766548590616974,
         "directionz": -0.279072809708834,
         "viewImg": "scene/44446d72-0039-443a-bcb0-f20fbe25ca64/image/34546d72-0039-443a-bcb0-f20fbe25ca64.jpg"
     },
     /*文本附属信息*/
     text: {
         title: '标题',
         content: '内容'
     },
     /*图片附属信息*/
     image: {
         title: '标题',
         pics: [{
             'id': 'GUID',
             path: '图片地址'
         }]
     },
     /*视频附属信息*/
     video: [{
         'id': 'GUID',
         title: '',
         type: '视频类型(1;url, 2自定义上传)',
         url: '视频地址'
     }],
     /*全景附属信息*/
     panoramic: [{
         'id': 'GUID',
         title: '标题',
         url: '全景地址'
     }]
    
     }
    
    
  4. 附属信息-图片和视频(本地视频,非在线)上传

    上传接口参照http://localhost:1000//wish3dearth/api/scene/v1.0.0/uploadTempFile

标绘线

//获取线上点,>=2个点
var handler = new LSGlobe.ScreenSpaceEventHandler(viewer.scene.canvas);
handler.setInputAction(function(movement) {
    //获取的坐标上添加标绘点,具体的坐标获取参照坐标转换
    var Pos = scene.pickGlobe(movement.position);
},
LSGlobe.ScreenSpaceEventType.LEFT_CLICK);

//添加到场景中
drawDataSource.entities.add({
    //特殊字段该字段会保存下来,可以是字符串也可以是个对象
    name: "标绘线",
    //线的唯一标识会存储下来,再次加载也不改变,用于查找
    id: "1ab133f2-6a13-4575-a65a-aa2e9bbbc3ca",
    polyline: {
        //线点的集合
        positions: [{
            "x": -2762093.143122826,
            "y": 4700702.533345467,
            "z": 3299201.561099788
        },
        {
            "x": -2762049.697649547,
            "y": 4700739.367655585,
            "z": 3299182.502160778
        },
        {
            "x": -2762049.5886295093,
            "y": 4700739.656572349,
            "z": 3299182.139584659
        }],
        //线宽
        width: 2,
        //线的材质
        material: LSGlobe.Color.fromCssColorString("rgb(255,120,255)"),
        /*
        1.虚实线material: new LSGlobe.PolylineDashMaterialProperty({
            color:oMaterial,
            dashPattern:LSGlobe.LineType.SOLID//SOLID:实线,DASH:虚线,DOT:浮点,DASHDOT:-.-.-,DASHDOTDOT:-..-..
        })
        2.箭头:material: new LSGlobe.PolylineArrowMaterialProperty(LSGlobe.Color.PURPLE)
        3.边框线:material: new LSGlobe.PolylineOutlineMaterialProperty({
                    color: LSGlobe.Color.ORANGE,
                    outlineWidth: 2,
                    outlineColor: LSGlobe.Color.BLACK
                })
        4.发光线:material: new LSGlobe.PolylineGlowMaterialProperty({
                    glowPower: 0.2,
                    color: LSGlobe.Color.BLUE
                })
        */
        //空间线被遮挡部分样式,仅适用空间线
        depthFailMaterial: new LSGlobe.PolylineDashMaterialProperty({
                    color:LSGlobe.Color.fromCssColorString("rgba(0,186,255,0.5)")
                }),
        clampToGround: false,//是否贴地(空间线必须为false,贴地形、贴模型、贴地表模型必须为true)
        classificationType: undefined//TERRAIN:贴地表,CESIUM_3D_TILE:贴模型,BOTH贴模型贴地表,undefined:空间线
    }
});

标绘面

drawDataSource.entities.add({
    //特殊字段该字段会保存下来,可以是字符串也可以是个对象
    name: '标绘面',
    //面的唯一标识会存储下来,再次加载也不改变,用于查找
    id: id,
    polygon: {
        hierarchy: {
            //面的点集合
            positions: event.positions,
        },
        //面的材质
        material: LSGlobe.Color.fromCssColorString("rgb(0,186,255)"),
        //是否填充面
        fill: true,
        //是否显示面的外边框(仅空间面有效)
        outline: true,
        //面的外边框的材质
        outlineColor: LSGlobe.Color.fromCssColorString("rgb(0,186,255)"),
        //面的外边框的宽度(暂不支持非1)
        outlineWidth:1,
        //面的类型    
        classificationType: LSGlobe.ClassificationType.BOTH,
        //LSGlobe.ClassificationType.BOTH           即可贴地又可贴模型
        //LSGlobe.ClassificationType.TERRAIN        仅贴地
        //LSGlobe.ClassificationType.CESIUM_3D_TILE 仅贴模型
        //undefined 空间面
        perPositionHeight:false//是否绝对高度(当设置非空间面时候一定要设置false,空间面一定要设置true)
    }
});

标绘要素获取

//id 绘制线面时加入的唯一标识
var entity = drawDataSource.entities.getById(id)

标绘显示隐藏

//entity获取到的标绘要素对象
entity.show=true;//true:显示,false:隐藏

标绘飞行

//entity获取到的标绘要素对象

//空间线面的飞行(发光线等都是空间线)
viewer.flyto(entity)

//特殊线面的飞行(贴地,贴模型)
//使用单体化的飞行方式飞行

标绘删除

//单个标绘线面删除
//id绘制时添加的唯一标识
drawDataSource.entities.removeById(id)

//删除drawDataSource对象中的所有标绘要素
drawDataSource.entities.removeAll();

标绘编辑

编辑标绘点

//entity
//markid是标注添加时的唯一标识
entity.billboard = new LSGlobe.BillboardGraphics({ //图标
    image: iconPath,//标注图标
    width: 64,
    height: 64,
    pixelOffset: new LSGlobe.Cartesian2(0, -13),
    //偏移量
    disableDepthTestDistance: 0,
    scale: 0.5,
    translucencyByDistance: new LSGlobe.NearFarScalar(1.5e2, 1.0, 1.5e5, 0.0),
});
//修改标注图标信息
entity.label = new LSGlobe.LabelGraphics({
    text: objEntity.name,
    //修改后的文字信息
    font: "64px Microsoft YaHei",//修改后的文字类型和大小
    fillColor: LSGlobe.Color.fromCssColorString('rgb(0,0,0)'),
    //文字填充颜色
    style: LSGlobe.LabelStyle.FILL_AND_OUTLINE,
    outlineWidth: 6,
    translucencyByDistance: new LSGlobe.NearFarScalar(1.5e2, 1.0, 1.5e5, 0.0),
    horizontalOrigin: LSGlobe.HorizontalOrigin.LEFT,
    pixelOffset: new LSGlobe.Cartesian2(15, -15),
    disableDepthTestDistance: 0,
    scale: 0.5//缩放
});
//修改标注位置信息(经纬度)
entity.position = new LSGlobe.Cartesian3.fromDegrees(position.x, position.y, position.z);
//修改标注文字信息
entity.label.text = new LSGlobe.ConstantProperty(objEntity.name);
//单独修改标注文字信息中的文本
entity.label.fillColor = LSGlobe.Color.fromCssColorString('rgb(255,255,255)');
//单独修改标注文字信息中的文本填充颜色

编辑标绘线


//编辑线的特殊字段
entity.name = '面标绘名称';
//编辑线宽度
entity.polyline.width = 10;
//编辑线材质(颜色)
entity.polyline.materia = LSGlobe.Color.fromCssColorString('rgb(0,0,0)');
//编辑线的透明度
entity.polyline.materia = LSGlobe.Color.fromCssColorString('rgb(0,0,0)').withAlpha('0.5')
//线的材质
/*
1.虚实线
entity.polyline.materia = new LSGlobe.PolylineDashMaterialProperty({
    color: oMaterial,
    dashPattern: LSGlobe.LineType.SOLID //SOLID:实线,DASH:虚线,DOT:浮点,DASHDOT:-.-.-,DASHDOTDOT:-..-..
}) 
2.箭头:
entity.polyline.materia = new LSGlobe.PolylineArrowMaterialProperty(LSGlobe.Color.PURPLE) 
3.边框线:material: new LSGlobe.PolylineOutlineMaterialProperty({
    color: LSGlobe.Color.ORANGE,
    outlineWidth: 2,
    outlineColor: LSGlobe.Color.BLACK
})
4.发光线:
entity.polyline.materia = new LSGlobe.PolylineGlowMaterialProperty({
    glowPower: 0.2,
    color: LSGlobe.Color.BLUE
})        
*/
//编辑线的遮挡部分虚线属性
entity.polyline.depthFailMaterial = new LSGlobe.PolylineDashMaterialProperty({
    color: LSGlobe.Color.fromCssColorString('rgb(0,0,0)').withAlpha('0.5')
});
//是否贴地(空间线必须为false,贴地形、贴模型、贴地表模型必须为true)
entity.polyline.clampToGround = false;
entity.polyline.classificationType = undefined//TERRAIN:贴地表,CESIUM_3D_TILE:贴模型,BOTH贴模型贴地表,undefined:空间线

编辑标绘面

//编辑线的特殊字段
entity.name = '面标绘名称';
//编辑面的材质
entity.polygon.material = LSGlobe.Color.fromCssColorString('rgb(0,0,0)');
//编辑面的透明度
entity.polygon.material = LSGlobe.Color.fromCssColorString('rgb(0,0,0)').withAlpha('0.5');
//编辑面的外边框(特殊面不显示边框不能设置该属性)
entitie.polygon.outline = true / false;
//编辑面是否填充
entitie.polygon.fill = true / false;
//编辑面外边框材质(特殊面不显示边框不能设置该属性)
entitie.polygon.outlineColor = LSGlobe.Color.fromCssColorString('rgb(0,0,0)');
//编辑面外边框透明度(特殊面不显示边框不能设置该属性)
entitie.polygon.outlineColor = LSGlobe.Color.fromCssColorString('rgb(0,0,0)').withAlpha('0.5');

entitie.polygon.classificationType = LSGlobe.ClassificationType.BOTH;
//LSGlobe.ClassificationType.BOTH           即可贴地又可贴模型
//LSGlobe.ClassificationType.TERRAIN        仅贴地
//LSGlobe.ClassificationType.CESIUM_3D_TILE 仅贴模型
//undefined 空间面
entitie.polygon.perPositionHeight:false//是否绝对高度(当设置非空间面时候一定要设置false,空间面一定要设置true)

标绘存储

标绘的存储是以json格式保存的,直接赋值给oSubSceneData.draw,然后随场景保存接口一并提交保存

oSubSceneData.draw = drawDataSource.toGeoJson()

标绘重载

标绘获取接口,参数jsonType为2

http://localhost:1000/wish3dearth/api/scene/v1.0.0/getSceneJsonInfo

var oGeoJson = result.data;
//result.data前面获取的标绘数据json
var promise = LSGlobe.GeoJsonDataSource.load(oGeoJson, {});
promise.then(function(dataSource) {
    //将数据再次加载到初始化存储标绘要素的对象中  
    drawDataSource = dataSource;
    //添加到球中
    viewer.dataSources.add(dataSource);
}).otherwise(function(error) {
    console.log(error);
});

单体化

单体化原理:本质就是贴模型地表的标绘面,在默认0.01的透明度下,当鼠标移动到该面时候,改变面的材质的透明度为1,当鼠标移出后透明度重新设置透明度为0.01,从而实现高亮效果。

单体化绘制


//1).初始化单体化存储对象
var monomerDataSource;
var promise = viewer.dataSources.add(new LSGlobe.GeoJsonDataSource("monomerDataSource"));

promise.then(function(dataSource) {
    monomerDataSource = dataSource;
    monomerDataSource.name="monomerDataSource"
}).otherwise(function(error) {

});

//2).单体化绘制 
monomerDataSource.entities.add({
    //特殊字段该字段会保存下来,可以是字符串也可以是个对象
    name: '单体化面',
    //面的唯一标识会存储下来,再次加载也不改变,用于查找
    id: id,
    polygon: {
        hierarchy: {
            //面的点集合
            positions: event.positions,
        },
        //面的材质
        material: LSGlobe.Color.fromCssColorString("rgb(0,186,255)").withAlpha('0.5');,
        //是否填充面
        fill: true,
        //是否显示面的外边框(仅空间面有效)
        outline: false,
        //面的类型    
        classificationType: LSGlobe.ClassificationType.BOTH,
        perPositionHeight:false//是否绝对高度(当设置非空间面时候一定要设置false,空间面一定要设置true)
    }
});

单体化要素获取

//id 绘制单体化时加入的唯一标识
var entity = monomerDataSource.entities.getById(id)

单体化显示隐藏

//entity获取到的单体化对象
entity.show=true/false;

单体化飞行

//entity获取到的单体化对象
//单体化飞行(贴地,贴模型)
var entity = monomerDataSource.entities.getById(id);
if (entity) {
    entity.polygon.material = LSGlobe.Color.fromRandom({
        red: entity.polygon.material.color._value.red,
        green: entity.polygon.material.color._value.green,
        blue: entity.polygon.material.color._value.blue,
        alpha: 0.7
    });
    var entityPosition = getRealPosition(entity);
    //获取单体化真实飞行坐标
    viewer.camera.flyTo({
        destination: LSGlobe.Cartesian3.fromDegrees(entityPosition.lng, entityPosition.lat, entityPosition.alt),
        duration: 3
    })
}

function getRealPosition(Entities) {
    if (Entities._corridor) {
        var aPos = Entities._corridor.positions._value;
    } else {
        var aPos = Entities.polygon.hierarchy._value.positions || Entities.polygon.hierarchy._value;
    }
    var iX = 0,
    iY = 0,
    iZ = 0,
    maxX = 0,
    maxY = 0,
    minX, minY, realheight;
    for (var i = 0; i < aPos.length; i++) {
        iX = aPos[i].x + iX;
        iY = aPos[i].y + iY;
        iZ = aPos[i].z + iZ;
    }
    iX = iX / aPos.length;
    iY = iY / aPos.length;
    iZ = iZ / aPos.length;
    //中心点经纬度
    var WorlsPos = new LSGlobe.Cartesian3(iX, iY, iZ);
    var oDegree = ellipsoid.cartesianToCartographic(WorlsPos);
    var lng = LSGlobe.Math.toDegrees(oDegree.longitude);
    var lat = LSGlobe.Math.toDegrees(oDegree.latitude);
    for (var a = 0; a < aPos.length; a++) {
        //当前点的经纬度
        var sWorlsPos = new LSGlobe.Cartesian3(aPos[a].x, aPos[a].y, aPos[a].z);
        var sDegree = ellipsoid.cartesianToCartographic(sWorlsPos);
        var slng = LSGlobe.Math.toDegrees(sDegree.longitude);
        var slat = LSGlobe.Math.toDegrees(sDegree.latitude);
        //中心点经纬度
        var oPos = {
            "x": slng,
            "y": slat
        };
        var currentheight = getDistance(oPos, lng, lat);
        if (a == 0) {
            realheight = currentheight
        }
        if (realheight < currentheight) {
            realheight = currentheight
        }
    }
    var sTileset = whichTileset(lng, lat)[0];
    //获取单体化当前依附的模型
    if (sTileset) {
        var alt = realheight * 1.7320508075689 + 50 + sTileset._boundingSphere.center.z * 1 + sTileset.name.position.split(",")[2] * 1;
        return {
            "lat": lat,
            "lng": lng,
            "alt": alt
        };
    } else {
        return {
            "lat": lat,
            "lng": lng,
            "alt": realheight
        };
    }
    return {
        "lat": lat,
        "lng": lng,
        "alt": alt
    };
}
//根据经纬度获取当前经纬度下的模型集合
//x经度值 y维度值
function whichTileset(x, y) {
    var returnValue = [];
    for (var i = 0; i < viewer.scene.pageLODLayers._pageLODs.length; i++) {
        var aTileSet = viewer.scene.pageLODLayers._pageLODs[i];
        var oCenter = aTileSet.tileBoundingSphere.center;
        var ellipsoid = viewer.scene.globe.ellipsoid;
        var cartesian3 = new LSGlobe.Cartesian3(oCenter.x, oCenter.y, oCenter.z);
        var cartographic = ellipsoid.cartesianToCartographic(cartesian3);
        var lat = LSGlobe.Math.toDegrees(cartographic.latitude);
        var lng = LSGlobe.Math.toDegrees(cartographic.longitude);
        var position = {
            x: lng,
            y: lat,
            z: cartographic.height
        };
        var distance = getDistance(position, x, y);
        if (distance < aTileSet.tileBoundingSphere.radius) {
            returnValue.push(aTileSet);
        }
    }
    return returnValue;
}
//获取两个经纬度之间的距离函数
function getDistance(position, x, y) {
    var radLatA = position.y * 0.0174532925199432957692369077;
    var radLatB = y * 0.0174532925199432957692369077;
    var radLonA = position.x * 0.0174532925199432957692369077;
    var radLonB = x * 0.0174532925199432957692369077;
    return Math.acos(Math.cos(radLatA) * Math.cos(radLatB) * Math.cos(radLonA - radLonB) + Math.sin(radLatA) * Math.sin(radLatB)) * 6378137;
}

单体化删除

//单个单体化删除
//id绘制时添加的唯一标识
monomerDataSource.entities.removeById(id)

//删除monomerDataSource对象中的所有单体化
monomerDataSource.entities.removeAll();

单体化编辑

//entity获取到的单体化要素对象
//1.编辑单体化样式
//编辑单体化的特殊字段
entity.name = '单体化面';
//编辑单体化材质(颜色)
entity.polygon.materia = LSGlobe.Color.fromCssColorString('rgb(0,0,0)');
//编辑单体化的透明度
entity.polygon.materia = LSGlobe.Color.fromCssColorString('rgb(0,0,0)').withAlpha('0.5')

//2.获取属性和属性值展示出来
var oEntityProperties = entity.properties.getValue();

for (var key in oEntityProperties) {
    console.log(key+":"+oEntityProperties.key);
}
//3.编辑单体化的属性属性值
//添加属性属性值
entity.properties.addProperty("属性","属性值");
//下面是整体属性替换(谨慎使用,会覆盖之前的属性)
entities.properties = {
    "属性":"属性值"
};
//删除属性属性值
entity.properties.removeProperty("属性");

单体化(以及单体化类似对象)的鼠标点击获取


//初始化一个鼠标事件
var handlerMonomer = new LSGlobe.ScreenSpaceEventHandler(viewer.scene.canvas);
handlerMonomer.setInputAction(function(movement) {
    var posit = viewer.scene.pick(movement.position);
    if (LSGlobe.defined(posit)) {
        //如果posit值存在说明鼠标点击的地方有内容
        //(该内容可以是标注,标绘,单体化,矢量数据等要素)需要判断该数据是什么类型需要根据该对象中的特殊字段来判断或者是否包含关系
        if ( !! posit.id && monomerDataSource.entities.contains(posit.id)) {
            //如果被monomerDataSource.entities包含则是单体化

        }
    }
},
LSGlobe.ScreenSpaceEventType.LEFT_CLICK);

单体化存储

单体化的存储是以json格式保存的,直接赋值给oSubSceneData.monomer,然后随场景保存接口一并提交保存

oSubSceneData.monomer = monomerDataSource.toGeoJson()

单体化重载

标绘获取接口,参数jsonType为3

http://localhost:1000/wish3dearth/api/scene/v1.0.0/getSceneJsonInfo

var oGeoJson = result.data;
//result.data前面获取的标绘数据json
var promise = LSGlobe.GeoJsonDataSource.load(oGeoJson, {});
promise.then(function(dataSource) {
    //将数据再次加载到初始化存储标绘要素的对象中  
    monomerDataSource = dataSource;
    //添加到球中
    viewer.dataSources.add(dataSource);
}).otherwise(function(error) {
    console.log(error);
});

压平

压平面的保存和标绘、单体化相同,都是使用togeojson()的方式直接转换为json格式数据上传保存,但是压平需要额外调用压平接口

压平绘制


var pushDataSource;
//存储压平绘制的面要素会保存到该对象中
var promise = viewer.dataSources.add(new LSGlobe.GeoJsonDataSource("pushDataSource"));
promise.then(function(dataSource) {
    pushDataSource = dataSource;
}).otherwise(function(error) {

});

//压平面的绘制
var pushHandler = new LSGlobe.ScreenSpaceEventHandler(viewer.scene.canvas);
pushHandler.setInputAction(function(movement) {
    //获取的坐标上添加标绘点,具体的坐标获取参照坐标转换
    var Pos = scene.pickGlobe(movement.position);
},
LSGlobe.ScreenSpaceEventType.LEFT_CLICK);
//根据上面获取到的点集合经过处理后达到新的数据
var oValuePoint = ChangePolygonPosition(event.positions);
//该面是辅助设置压平面的面,最后压平的高度和范围是该面显示的高度和范围(该面用于保存,存储于pushDataSource.entities,如果需要对比高度效果可以多创建一个面)
pushDataSource.entities.add({
    name: '压平面',//压平面名称
    id: id,
    polygon: {
        hierarchy: {
            positions:LSGlobe.Cartesian3.fromDegreesArrayHeights(oValuePoint)
        },        
        material: new LSGlobe.Color(0.5, 1.0, 1.0, 0.7),
        fill: true,
        //显示填充
        outline: false,
        outlineColor: LSGlobe.Color.YELLOW,
        perPositionHeight: true
    }
});
//坐标转换函数
function ChangePolygonPosition(oPositions) {
    var oValuePoint = [];
    //所有点统一高度,使压平面在同一水平面(此处计算所有点的平均高度)
    var fSumHeight = 0;
    for (var a = 0; a < oPositions.length; a++) {
        var cartographic = LSGlobe.Cartographic.fromCartesian(oPositions[a]);
        fSumHeight = fSumHeight + cartographic.height;
    }
    var Height = fSumHeight / oPositions.length;

    for (var a = 0; a < oPositions.length; a++) {
        var CurrentPoint = oPositions[a];
        var cartographic = LSGlobe.Cartographic.fromCartesian(CurrentPoint);
        var currentClickLon = LSGlobe.Math.toDegrees(cartographic.longitude);
        var currentClickLat = LSGlobe.Math.toDegrees(cartographic.latitude);
        oValuePoint.push(currentClickLon);
        oValuePoint.push(currentClickLat);
        oValuePoint.push(Height);
    }
    return oValuePoint;
};

//模型的压平
var pos = oValuePoint;//同上面oValuePoint

//获取该压平面上的点与哪些实景三维模型有交集
var aTileset = [];
//遍历所有点存储有交集的实景三维模型
for (var i = 0; i < pos.length; i++) {
    var cartographic = LSGlobe.Cartographic.fromCartesian(pos[i]);
    var longitude = LSGlobe.Math.toDegrees(cartographic.longitude);
    var latitude = LSGlobe.Math.toDegrees(cartographic.latitude);
    var tileset = whichTileset(longitude, latitude);
    if (tileset.length < 1) {
        continue;
    }else{
        for(var j =0;j<tileset.length;j++){
            if(aTileset.indexOf(tileset[j])<0){
                aTileset.push(tileset[j]);
            }
        }
    }
}
//根据辅助面中的点来获取需要压平的模型
var myPolygon = new LSGlobe.PolygonGeometry({
    polygonHierarchy: new LSGlobe.PolygonHierarchy(pos),
    perPositionHeight: true
});

//使用辅助面的点集合绘制一个面对象
for (var i = 0; i < aTileset.length; i++) {
    aTileset[i]._flattenPolygons.push(myPolygon);
    aTileset[i].updateFlatten();
}

//可以选择让辅助面是否显示
pushDataSource.entities.getById(id).show = false;

//获取当前压平的模型对象函数
function whichTileset(x, y) {
    var returnValue = [];
    for (var i = 0; i < viewer.scene.pageLODLayers._pageLODs.length; i++) {
        var aTileSet = viewer.scene.pageLODLayers._pageLODs[i];
        var oCenter = aTileSet.tileBoundingSphere.center;
        var ellipsoid = viewer.scene.globe.ellipsoid;
        var cartesian3 = new LSGlobe.Cartesian3(oCenter.x, oCenter.y, oCenter.z);
        var cartographic = ellipsoid.cartesianToCartographic(cartesian3);
        //ellipsoid表示球对象
        var lat = LSGlobe.Math.toDegrees(cartographic.latitude);
        var lng = LSGlobe.Math.toDegrees(cartographic.longitude);
        var position = {
            x: lng,
            y: lat,
            z: cartographic.height
        };
        var distance = getDistance(position, x, y);
        if (distance < aTileSet.tileBoundingSphere.radius) {
            returnValue.push(aTileSet);
        }
    }
    return returnValue;
}
//获取两个经纬度之间的距离函数
function getDistance(position, x, y) {
    var radLatA = position.y * 0.0174532925199432957692369077;
    var radLatB = y * 0.0174532925199432957692369077;
    var radLonA = position.x * 0.0174532925199432957692369077;
    var radLonB = x * 0.0174532925199432957692369077;
    return Math.acos(Math.cos(radLatA) * Math.cos(radLatB) * Math.cos(radLonA - radLonB) + Math.sin(radLatA) * Math.sin(radLatB)) * 6378137;
}

压平面的编辑


//1).设置高度
//获取对应参考面
var entity = pushDataSource.entities.getById(id);
//获取压平点坐标
var aFlatArray = ChangePolygonPosition(entity.polygon.hierarchy.getValue().positions);
for (var i = 2; i < aFlatArray.length; i = i + 3) {
    aFlatArray[i] = height; //height 改变后的高度值
}

//删除原参考面,新增参考面
pushDataSource.entities.remove(entity);
pushDataSource.entities.add({
    name: '压平面',
    //压平面名称
    id: id,
    polygon: {
        hierarchy: {
            positions: LSGlobe.Cartesian3.fromDegreesArrayHeights(aFlatArray)
        },
        material: new LSGlobe.Color(0.5, 1.0, 1.0, 0.7),
        fill: true,
        //显示填充
        outline: false,
        outlineColor: LSGlobe.Color.YELLOW,
        perPositionHeight: true
    }
});

// 清空所有压平面和辅助面
var aPagelodLayers = viewer.scene.pageLODLayers._pageLODs;
for (var i = 0; i < aPagelodLayers.length; i++) {
    try {
        aPagelodLayers[i].cleanflattenPolygon();
    } catch(e) {

}
}
//重新压平
var aPushEntities = pushDataSource.entities.values;
for (var i = 0; i < aPushEntities.length; i++) {
    if (aPushEntities[i].show) {
        var aTileset = [];
        var pos = aPushEntities[i].polygon.hierarchy.getValue().positions;
        //遍历所有点存储有交集的实景三维模型
        for (var i = 0; i < pos.length; i++) {
            var cartographic = LSGlobe.Cartographic.fromCartesian(pos[i]);
            var longitude = LSGlobe.Math.toDegrees(cartographic.longitude);
            var latitude = LSGlobe.Math.toDegrees(cartographic.latitude);
            var tileset = whichTileset(longitude, latitude);
            if (tileset.length < 1) {
                continue;
            } else {
                for (var j = 0; j < tileset.length; j++) {
                    if (aTileset.indexOf(tileset[j]) < 0) {
                        aTileset.push(tileset[j]);
                    }
                }
            }
        }
        //使用辅助面的点集合绘制一个面对象
        var myPolygon = new LSGlobe.PolygonGeometry({
            polygonHierarchy: new LSGlobe.PolygonHierarchy(pos),
            perPositionHeight: true
        });
        for (var i = 0; i < aTileset.length; i++) {
            aTileset[i]._flattenPolygons.push(myPolygon);
            aTileset[i].updateFlatten();
        }
    }
}

//2).设置名称
entity.name = "修改后的名称";

压平面的飞行

//压平面的飞行借助了压平辅助面
var entity = pushDataSource.entities.getById(id);
//粗略定位
viewer.flyTo(entity);

//精准定位(参考单体化定位)
var entity = pushDataSource.entities.getById(id);
    var entityPosition = getRealPosition(entity);
    viewer.camera.flyTo({
        destination: LSGlobe.Cartesian3.fromDegrees(entityPosition.lng,entityPosition.lat,entityPosition.alt),
        duration: 3
    })

设置显示隐藏


//对应的实景三维模型
tileset._flattenPolygons[0].show=true;//true显示,false:影藏
tileset.updateFlatten();
//对应的entity也要做对应同步
entity.show=true;//true显示,false:影藏

压平面的删除


//删除对应的entity
pushDataSource.entities.removeById(id);
//对应的实景三维模型的对应的压平面隐藏并更新
tileset._flattenPolygons[0].show=false;
tileset.updateFlatten();

压平存储

压平的存储是以json格式保存的,直接赋值给oSubSceneData.push,然后随场景保存接口一并提交保存

oSubSceneData.push = pushDataSource.toGeoJson()

压平面的重载

压平获取接口,参数jsonType为4

http://localhost:1000/wish3dearth/api/scene/v1.0.0/getSceneJsonInfo

var oGeoJson = result.data;
//result.data前面获取的标绘数据json
var promise = LSGlobe.GeoJsonDataSource.load(oGeoJson, {});
promise.then(function(dataSource) {
    //将数据再次加载到初始化存储压平的对象中  
    pushDataSource = dataSource;
    //添加到球中
    viewer.dataSources.add(dataSource);

     var aPagelodLayers = viewer.scene.pageLODLayers._pageLODs;
        for (var i = 0; i < aPagelodLayers.length; i++) {
            try {
                aPagelodLayers[i].cleanflattenPolygon();
            } catch (e) {
            }
        }
        //重新压平
        var aPushEntities = pushDataSource.entities.values;
        for (var i = 0; i < aPushEntities.length; i++) {
            if(aPushEntities[i].id.indexOf("common") < 0){
                aPushEntities[i].polygon.perPositionHeight=false;
            }
            if (aPushEntities[i].show && aPushEntities[i].id.indexOf("common") < 0) {
                var aPushPos=aPushEntities[i].polygon.hierarchy.getValue().positions?aPushEntities[i].polygon.hierarchy.getValue().positions:aPushEntities[i].polygon.hierarchy.getValue();
                var oDegree = fnCartesian2Degreen(aPushPos[0]);
                var mtileset = whichTileset(oDegree.lng, oDegree.lat);
                var myPolygon = new LSGlobe.PolygonGeometry({
                        polygonHierarchy: new LSGlobe.PolygonHierarchy(aPushPos),
                        perPositionHeight: true
                    });
                    for (var j = 0; j < mtileset.length; j++) {
                        mtileset[j]._flattenPolygons.push(myPolygon);
                        mtileset[j].updateFlatten();
                    }
            }
        }
}).otherwise(function(error) {
    console.log(error);
});

水面

水面的保存和压平相同,都是使用togeojson()的方式直接转换为json格式数据上传保存,水面需要额外调用水面接口,需要引用插件Water.js

<script type="text/javascript" src="Build/Plugins/Water/Water.js"></script>

水面绘制


var waterDataSource;
//存储水面的面要素会保存到该对象中
var promise = viewer.dataSources.add(new LSGlobe.GeoJsonDataSource("waterDataSource"));
promise.then(function(dataSource) {
    waterDataSource = dataSource;
}).otherwise(function(error) {

});

//水面的绘制
var waterHandler = new LSGlobe.ScreenSpaceEventHandler(viewer.scene.canvas);
waterHandler.setInputAction(function(movement) {
    //获取的坐标上添加标绘点,具体的坐标获取参照坐标转换
    var Pos = scene.pickGlobe(movement.position);
},LSGlobe.ScreenSpaceEventType.LEFT_CLICK);

//根据上面获取到的点集合经过处理后达到新的数据
var oValuePoint = ChangePolygonPosition(event.positions);//同压平的坐标处理方法



var pos = oValuePoint;//同上面oValuePoint

//创建
var wateritem = new LSGlobe.Water(viewer.scene);
wateritem.name = "水面";//水面名称
wateritem.id = id;//水面的id
wateritem.waveWidth = 5;//波纹宽度
wateritem.flowDirection = 90;//水流方向
wateritem.flowSpeed =10;//水流速度
wateritem._waterColor = LSGlobe.Color.fromCssColorString("#FFFF00");//水面颜色
wateritem.des = "";//水面描述
wateritem.alpha = 100;//
wateritem.waterPolygon = new LSGlobe.PolygonGeometry({
    polygonHierarchy: new LSGlobe.PolygonHierarchy(LSGlobe.Cartesian3.fromDegreesArrayHeights(oValuePoint)),
    perPositionHeight: true
});

//属性
var oWaterEntityProp = {};
oWaterEntityProp.waveWidth = wateritem.waveWidth;
oWaterEntityProp.flowDirection = wateritem.flowDirection;
oWaterEntityProp.flowSpeed = wateritem.flowSpeed;
oWaterEntityProp._waterColor = "#006ab4";
oWaterEntityProp.alpha = 100;
oWaterEntityProp.des = wateritem.des;
oWaterEntityProp.name = wateritem.name;
//该面是辅助设置水面的面,最后水面的高度和范围是该面显示的高度和范围(该面用于保存,存储于waterDataSource.entities)
var waterEntity = waterDataSource.entities.add({
    name: '水面',//水面名称
    id: id,
    polygon: {
        hierarchy: {
            positions:LSGlobe.Cartesian3.fromDegreesArrayHeights(oValuePoint)
        },        
        material: new LSGlobe.Color(0.5, 1.0, 1.0, 0.01),
        fill: true,
        //显示填充
        outline: false,
        outlineColor: LSGlobe.Color.YELLOW,
        perPositionHeight: true
    }
});
waterEntity.properties = oWaterEntityProp;

viewer.scene.waterCollection._water.push(wateritem);

水面编辑

//获取水面对象
function fnGetOwaterById(id) {
    var oSingleWater;
    var aWater = scene.waterCollection._water;
    for (var i = 0; i < aWater.length; i++) {
        if (id == aWater[i].id) {
            aWater[i].index = i;
            oSingleWater = aWater[i];
            break;
        }
    }
    return oSingleWater;
}
//笛卡尔积转经纬度
function fnCartesian2Degreen(oCartesian){
    var ellipsoid=viewer.scene.globe.ellipsoid;
    var cartesian3=new LSGlobe.Cartesian3(oCartesian.x,oCartesian.y,oCartesian.z);
    var cartograhphic=ellipsoid.cartesianToCartographic(cartesian3);
    var lat=LSGlobe.Math.toDegrees(cartograhphic.latitude);
    var lng=LSGlobe.Math.toDegrees(cartograhphic.longitude);
    var alt=cartograhphic.height;
    return {lng:lng,lat:lat,alt:alt}
}
//经纬度转笛卡尔积坐标
function  fnDegreen2Cartesian(oDegreen) {
    return LSGlobe.Cartesian3.fromDegrees(oDegreen.lng?oDegreen.lng:oDegreen.x, oDegreen.lat?oDegreen.lat:oDegreen.y, oDegreen.alt?oDegreen.alt:oDegreen.z, viewer.scene.globe.ellipsoid);
}

var oWater = fnGetOwaterById(id);//水面对象
var oWaterEntity = waterDataSource.entities.getById(id);//水面数据存储对象

//水面名称修改
oWater.name = "水面新名称";
oWaterEntity.name = = "水面新名称";

//水面描述修改
oWater.des = "水面新描述";
oWaterEntity.properties.addProperty("des", "水面新描述");

//水面位置修改
var originWaterCenter = fnCartesian2Degreen(oWater._waterCenterPos);//原水面的中心的经纬度坐标
oWater._waterCenterPos=SGlobe.Cartesian3.fromDegrees(120, 30, 10, viewer.scene.globe.ellipsoid);//新的水面中心坐标

//计算出originWaterCenter和新中心坐标(120,30,10)的经纬度高度差值
var fDiffLng=120-originWaterCenter.lng;
var fDiffLat=30-originWaterCenter.lat;
var fDiffAlt=10-originWaterCenter.alt;

//获取原水面所有点坐标
var aWaterPointArray = ChangePolygonPosition(oWaterEntity.polygon.hierarchy.getValue().positions);

//经度差值不为0
for (var i = 0; i < aWaterPointArray.length; i = i + 3) {
    aWaterPointArray[i] += fDiffLng; //height 改变后的高度值
}
//纬度差值不为0
for (var i = 1; i < aWaterPointArray.length; i = i + 3) {
    aWaterPointArray[i] += fDiffLat; //height 改变后的高度值
}
//高度差值不为0
for (var i = 2; i < aWaterPointArray.length; i = i + 3) {
    aWaterPointArray[i] += fDiffAlt; //height 改变后的高度值
}
//重新存储坐标点
oWaterEntity.polygon.hierarchy = {positions:LSGlobe.Cartesian3.fromDegreesArrayHeights(aWaterPointArray)};

//波纹宽度
oWater.waveWidth = 5;
oWaterEntity.properties.addProperty("waveWidth", 5);

//水流速度
oWater.flowSpeed = 5;
oWaterEntity.properties.addProperty("flowSpeed", 5);

//水立方向
oWater.flowDirection = 90;
oWaterEntity.properties.addProperty("flowDirection", 90);

//水面的颜色
oWater._waterColor = LSGlobe.Color.fromCssColorString("#FF0000").withAlpha(1);
oWaterEntity.properties.addProperty("_waterColor", "#FF0000");

水面显示隐藏


oWater.isVisible = true;//true:显示,false:隐藏

水面飞行


var entity = waterDataSource.entities.getById(waterid);
var entityPosition = getRealPosition(entity);//同单体化
viewer.camera.flyTo({
    destination: LSGlobe.Cartesian3.fromDegrees(entityPosition.lng, entityPosition.lat, entityPosition.alt),
    duration: 3
})

水面删除


waterDataSource.entities.removeById(id);
var oWater = fnGetOwaterById(treeNode.id);
if (oWater) oWater.destroy();

水面存储

水面存储是以json格式保存的,直接赋值给oSubSceneData.water,然后随场景保存接口一并提交保存

oSubSceneData.water = waterDataSource.toGeoJson()

水面重载

水面获取接口,参数jsonType为5

http://localhost:1000/wish3dearth/api/scene/v1.0.0/getSceneJsonInfo

var oGeoJson = result.data;
//result.data前面获取的水面数据json
var promise = LSGlobe.GeoJsonDataSource.load(oGeoJson, {});
promise.then(function(dataSource) {
    //将数据再次加载到初始化存储水面的对象中  
    waterDataSource = dataSource;
    //添加到球中
    viewer.dataSources.add(dataSource);

    var entities = waterDataSource.entities._entities._array;
    for (var i = 0; i < entities.length; i++) {
        var entity = entities[i];
        var WaterId = entity.id;
        var WaterName = entity.name;
        if (entity.polygon) {
            entity.polygon.outline = false;
            var wateritem = new LSGlobe.Water(viewer.scene);
            wateritem.waterPolygon = new LSGlobe.PolygonGeometry({
                polygonHierarchy: new LSGlobe.PolygonHierarchy(entity.polygon.hierarchy._value.positions),
                perPositionHeight: true
            });
            var oProperties = entity.properties.getValue();
            wateritem.id = WaterId;
            wateritem.waveWidth = oProperties.waveWidth;
            wateritem.flowDirection = oProperties.flowDirection;
            wateritem.flowSpeed = oProperties.flowSpeed;
            wateritem._waterColor = LSGlobe.Color.fromCssColorString(oProperties._waterColor).withAlpha(oProperties.alpha / 100);
            wateritem.name = WaterName;
            wateritem.des = oProperties.des;
            wateritem.alpha = oProperties.alpha;
            wateritem.isVisible = entity.show;
            viewer.scene.waterCollection._water.push(wateritem);
        }
    }
}).otherwise(function(error) {
    console.log(error);
});

模型裁剪

裁剪的保存和水面相同,都是使用togeojson()的方式直接转换为json格式数据上传保存,裁剪需要额外调用裁剪接口

模型裁剪绘制

var cutDataSource;
//裁剪的面要素会保存到该对象中
var promise = viewer.dataSources.add(new LSGlobe.GeoJsonDataSource("cutDataSource"));
promise.then(function(dataSource) {
    cutDataSource = dataSource;
}).otherwise(function(error) {

});

//裁剪的绘制
var cutHandler = new LSGlobe.ScreenSpaceEventHandler(viewer.scene.canvas);
cutHandler.setInputAction(function(movement) {
    //获取的坐标上添加标绘点,具体的坐标获取参照坐标转换
    var Pos = scene.pickGlobe(movement.position);
},LSGlobe.ScreenSpaceEventType.LEFT_CLICK);

//根据上面获取到的点集合经过处理后达到新的数据
var oValuePoint = ChangePolygonPosition(event.positions);//同压平的坐标处理方法

包含模式

var oClipProperty = {
    name: "裁剪面",
    cutType: "clip"
};
var clipPolygon = new LSGlobe.PolygonGeometry({
    polygonHierarchy: new LSGlobe.PolygonHierarchy(oValuePoint),
    perPositionHeight: true
});
clipPolygon.id = sEntityGuid;//裁剪id
clipPolygon.name = oClipProperty.name;

var cutEntity = cutDataSource.entities.add({
    name: '裁剪面',
    id: sEntityGuid,
    polygon: {
        hierarchy: {
            positions: oValuePoint
        },
        material: new LSGlobe.Color(0.5, 1.0, 1.0, 0.01),
        fill: true,
        perPositionHeight: true,
        outline: false
    }
});
var entityPosition = getRealPosition(cutEntity);

var oTargetTileset = whichTileset(entityPosition.lng, entityPosition.lat)[0];
if (oTargetTileset) {
    oClipProperty.tilesetId = oTargetTileset.name.id;
    if (oTargetTileset._clipPolygons.length > 0 ) {
        alert("实景三维模型只能进行一次包含模式裁剪!");
        cutDataSource.entities.removeById(sEntityGuid);
        return;
    } else {
        oTargetTileset.cleanClipPolygons();
    }
    cutEntity.properties = oClipProperty;
    oTargetTileset.addClipPolygon(clipPolygon);
} else {
    cutDataSource.entities.removeById(sEntityGuid);
}

抠取模式

var oClipProperty = {
    name: "裁剪面",
    cutType: "pit"
};
var clipPolygon = new LSGlobe.PolygonGeometry({
    polygonHierarchy: new LSGlobe.PolygonHierarchy(oValuePoint),
    perPositionHeight: true
});
clipPolygon.id = sEntityGuid;//裁剪id
clipPolygon.name = oClipProperty.name;

var cutEntity = cutDataSource.entities.add({
    name: '裁剪面',
    id: sEntityGuid,
    polygon: {
        hierarchy: {
            positions: oValuePoint
        },
        material: new LSGlobe.Color(0.5, 1.0, 1.0, 0.01),
        fill: true,
        perPositionHeight: true,
        outline: false
    }
});
var entityPosition = getRealPosition(cutEntity);

var oTargetTileset = whichTileset(entityPosition.lng, entityPosition.lat)[0];
if (oTargetTileset) {
    oClipProperty.tilesetId = oTargetTileset.name.id;    
    cutEntity.properties = oClipProperty;
    oTargetTileset.pitPolygons.push(clipPolygon);
    oTargetTileset.oPageLOD.updatePit();
} else {
    cutDataSource.entities.removeById(sEntityGuid);
}

裁剪编辑

主要通过操作裁剪集合数据-cutDataSource.entities,然后进行对应的裁剪类型进行操作

var entities = cutDataSource.entities.values;
    for (var i = 0; i < entities.length; i++) {
        var entity = entities[i];
        var oProperties=entity.properties.getValue();
        var CutId = entity.id;
        var CutName = entity.name;
        if(tilesetid&&oProperties.tilesetId!=tilesetid){
            continue;
        }
        if (entity.polygon&&entity.show) {
            entity.polygon.outline=false;
            var cutPolygon= new LSGlobe.PolygonGeometry({
                polygonHierarchy: new LSGlobe.PolygonHierarchy(entity.polygon.hierarchy._value.positions),
                perPositionHeight : true
            });
            cutPolygon.name=CutName;
            cutPolygon.id=CutId;
            var oPageLOD=getPageLODLayersById(oProperties.tilesetId);//实景三维数据获取方法
            if(oPageLOD){
                if("clip"==oProperties.cutType){
                    oPageLOD.addClipPolygon(cutPolygon);
                }else{
                    oPageLOD.pitPolygons.push(cutPolygon);
                    oPageLOD.updatePit();
                }
            }
        }
    }

裁剪显示隐藏

var cutEntity = cutDataSource.entities.getById(id);//获取对应裁剪entity.
cutEntity.show=true;//true:显示,false:隐藏
var oProperties = cutEntity.properties.getValue();//获取裁剪的类型
var tileset = getPageLODLayersById(oProperties.tilesetId);//实景三维数据获取方法

if(oProperties.cutType=="clicp"){
    if(cutEntity.show){
        var cutPolygon = new LSGlobe.PolygonGeometry({
            polygonHierarchy: new LSGlobe.PolygonHierarchy(cutEntity.polygon.hierarchy._value.positions),
            perPositionHeight: true
        });
        tileset.addClipPolygon(cutPolygon);
    }else{
        tileset.cleanClipPolygons();
    }
}else{
    for (var i = 0; i < tileset._pitPolygons.length; i++) {
        if (cutEntity.id == tileset._pitPolygons[i].id) {
            tileset._pitPolygons[i].show = cutEntity.show;
            tileset.updatePit();
        }
    }
}

裁剪飞行


var entity = cutDataSource.entities.getById(id);
var entityPosition = getRealPosition(entity);//同单体化
viewer.camera.flyTo({
    destination: LSGlobe.Cartesian3.fromDegrees(entityPosition.lng, entityPosition.lat, entityPosition.alt),
    duration: 3
})

裁剪删除

var cutEntity = cutDataSource.entities.getById(id);//根据裁剪id获取对应的参考entity
var oProperties = cutEntity.properties.getValue();//获取裁剪的类型
var tileset = getPageLODLayersById(oProperties.tilesetId);//实景三维数据获取方法

if(oProperties.cutType=="clicp"){
    tileset.cleanClipPolygons();
}else{
    for (var i = 0; i < tileset._pitPolygons.length; i++) {
        if (cutEntity.id == tileset._pitPolygons[i].id) {
            tileset._pitPolygons[i].show =false;
            tileset.updatePit();
        }
    }
}

cutDataSource.entities.removeById(id);

裁剪存储

裁剪存储是以json格式保存的,直接赋值给oSubSceneData.clip,然后随场景保存接口一并提交保存

oSubSceneData.clip = cutDataSource.toGeoJson()

裁剪重载

裁剪获取接口,参数jsonType为6

http://localhost:1000/wish3dearth/api/scene/v1.0.0/getSceneJsonInfo

var oGeoJson = result.data;
//result.data前面获取的压平数据json
var promise = LSGlobe.GeoJsonDataSource.load(oGeoJson, {});
promise.then(function(dataSource) {
    //将数据再次加载到初始化存储裁剪的对象中  
    cutDataSource = dataSource;
    //添加到球中
    viewer.dataSources.add(dataSource);

    var entities = cutDataSource.entities._entities._array;
    for (var i = 0; i < entities.length; i++) {
        var entity = entities[i];
        var oProperties = entity.properties.getValue();
        var CutId = entity.id;
        var CutName = entity.name;
        if (tilesetid && oProperties.tilesetId != tilesetid) {
            continue;
        }
        if (entity.polygon && entity.show) {
            entity.polygon.outline = false;
            var cutPolygon = new LSGlobe.PolygonGeometry({
                polygonHierarchy: new LSGlobe.PolygonHierarchy(entity.polygon.hierarchy._value.positions),
                perPositionHeight: true
            });
            cutPolygon.name = CutName;
            cutPolygon.id = CutId;
            var oPageLOD = getPageLODLayersById(oProperties.tilesetId);
            if (oPageLOD) {
                if ("clip" == oProperties.cutType) {
                    oPageLOD.addClipPolygon(cutPolygon);
                } else {
                    oPageLOD.pitPolygons.push(cutPolygon);
                    oPageLOD.updatePit();
                }
            }
        }
    }
}).otherwise(function(error) {
    console.log(error);
});

双屏对比

添加双屏对比

http://localhost:1000/wish3dearth/api/scene/v1.0.0/pageList

获取当前用户的场景列表,把要添加的分屏场景数据加到oSubSceneData.splitscreen.screens中,如下代码:

oSubSceneData.splitscreen.screens.push(item);//item是场景的数据对象

双屏删除

oSubSceneData.splitscreen.screens.splice(0,1);//删除第一个副场景

双屏对比联动

双屏对比的原理:是同一个页面用两个相同的iframe分别加载一个预览的场景;只要在其中一个iframe页面中操作,对应的camera信息同步到另外一个iframe页面。

//在一个iframe中获取到另一个iframe的document对象
var otherIframe = parent.document.getElementById("另一个iframe的唯一标识 id").contentWindow
//camera.position,camera.direction,camera.up
//当前iframe中球的相机位置
otherIframe.jumpToViewPoint(camera.position, camera.direction, camera.up);
//为了让两个球的相机位置相同,移动一个iframe中球的相机位置时,让另一个球的相机位置同步飞到当前iframe中球的相同的相机位置即可
function jumpToViewPoint(position, direction, up) {
    viewer.camera.flyTo({
        destination: new LSGlobe.Cartesian3(position.x, position.y, position.z),
        orientation: {
            direction: new LSGlobe.Cartesian3(direction.x, direction.y, direction.z),
            up: new LSGlobe.Cartesian3(up.x, up.y, up.z)
        },
        duration: 0
    });
}
//上面的操作需要放到鼠标滑动事件中
var handler = new LSGlobe.ScreenSpaceEventHandler(viewer.scene.canvas);
handler.setInputAction(function(movement) {
    //在此处执行双屏对比的联动事件
},
LSGlobe.ScreenSpaceEventType.WHEEL);
handler.setInputAction(function(movement) {
    //在此处执行双屏对比的联动事件
},
LSGlobe.ScreenSpaceEventType.MOUSE_MOVE);

双屏保存

随场景保存接口一并保存

分析

光照分析

//是否开启光照
viewer.shadows=true;//光照分析时候一定要设置true

//光照阴影位置和当前的时间有关
//设置当前时间可以改变阴影的位置
var julianDay =computes(new Date());
//当天已经过去的时间单位s
var julianSecound=hour*60*60+minute*60+secound;//hour当前时,minute当前分,secound当前秒
viewer.clock.currentTime= new LSGlobe.JulianDate(julianDay,julianSecound);

//当前时间转换为朱莉安时间
function computes(now){
    var month = now.getUTCMonth() + 1;
    var day = now.getUTCDate();
    var year = now.getUTCFullYear()
    var y = eval(year);
    var m = eval(month);
    var d = eval(day);
    var extra = 100.0*y + m - 190002.5;
    var rjd = 367.0*y;
    rjd -= Math.floor(7.0*(y+Math.floor((m+9.0)/12.0))/4.0);
    rjd += Math.floor(275.0*m/9.0);
    rjd += d;
    rjd += 1721013.5;
    rjd -= 0.5*extra/Math.abs(extra);
    rjd += 0.5;
    return rjd;
}

可视域分析

//1).初始化可视域分析
var viewshed3ding = false; //用于是否正在绘制可视域分析
var viewshed3d; //当前可视域对象
var aViewshed3d = []; //保存可视域分析的数组
//初始化可视域对象
viewshed3d = new LSGlobe.Viewshed3D(viewer.scene);
//将可视域分析对象加入到可是与分析数组中
aViewshed3d.push(viewshed3d);

//2).绘制可视域分析
//初始化鼠标事件
var ViewAnalysisHandler = new LSGlobe.ScreenSpaceEventHandler(viewer.scene.canvas);
ViewAnalysisHandler.setInputAction(function(movement) {
    var cartesian = scene.pickGlobe(movement.position);
    var cartographic = LSGlobe.Cartographic.fromCartesian(cartesian);
    var currentClickLon = LSGlobe.Math.toDegrees(cartographic.longitude);
    var currentClickLat = LSGlobe.Math.toDegrees(cartographic.latitude);
    var CurrentTileSet = whichTileset(currentClickLon, currentClickLat);
    //判断点是否在模型上函数和压平获取压平对象相同
    //可视域分析点必须在模型上
    if (CurrentTileSet.length < 1) {
        //如果点没有点在模型上不在向下走
        return;
    }
    if (cartesian != undefined && !viewshed3ding) {
        viewshed3d.viewerPosition = cartesian;
        //初始添加一个点
        viewshed3ding = true;
    } else {
        viewshed3d.setPoseByTargetPoint(cartesian);
        //点击第二个点绘制结束
        viewshed3ding = false;
    }
},
LSGlobe.ScreenSpaceEventType.LEFT_CLICK);

ViewAnalysisHandler.setInputAction(function(movement) {
    if (viewshed3daction && viewshed3ding) {
        var cartesian = viewer.scene.pickGlobe(movement.endPosition);
        viewshed3d.setPoseByTargetPoint(cartesian);
    }
},
LSGlobe.ScreenSpaceEventType.MOUSE_MOVE);

//3).删除可视域分析
for (var i = 0; i < aViewshed3d.length; i++) {
    try {
        aViewshed3d[i].destroy();
    } catch(e) {}
}
aViewshed3d = [];
viewshed3ding = false;

方量分析

//1).初始化方量分析
var cutfill = new LSGlobe.LSCutFill(viewer);
var nodeMesh, tileset; //实景三维对象
var poinsTemp = []; //用于保存绘制的点
//分析对象
var tempDataSource;
//用于存储方量分析辅助面
var promise = viewer.dataSources.add(new LSGlobe.GeoJsonDataSource("tempDataSource"));
promise.then(function(dataSource) {
    tempDataSource = dataSource;
}).otherwise(function(error) {

});

//2).点击收集构成放量分析的面
//注意:绘制方量分析时点必须点在模型上
//初始化鼠标事件
var oCutFillHandler = new LSGlobe.ScreenSpaceEventHandler(viewer.scene.canvas);
oCutFillHandler.setInputAction(function(movement) {
    var cartesian = scene.pickGlobe(movement.position);
    poinsTemp.push(cartesian);

    var CurrentTileSet = whichTileset(currentClickLon, currentClickLat);
    //判断点是否在模型上函数和压平获取压平对象相同
    //可视域分析点必须在模型上
    if (CurrentTileSet.length < 1) {
        alert("请在模型上点击");
        //如果点没有点在模型上不在向下走
        return;
    } else {

        tempDataSource.entities.add({
            position: cartesian,
            clampToGround: true,
            point: {
                pixelSize: 3,
                color: LSGlobe.Color.YELLOW,
                perPositionHeight: false,
                disableDepthTestDistance: 1000000000 //优先级
            }
        });
        if (poinsTemp.length >= 2) {
            tempDataSource.entities.removeById("20191225");
            tempDataSource.entities.add({
                id: "20191225",
                name: 'line on the surface',
                polyline: {
                    positions: poinsTemp,
                    width: 2,
                    material: LSGlobe.Color.fromCssColorString("rgba(0,186,255,0.5)"),
                    depthFailMaterial: new LSGlobe.PolylineDashMaterialProperty({
                        color: LSGlobe.Color.fromCssColorString("rgba(0,186,255,0.5)")
                    }),
                    disableDepthTestDistance: 1000000000 //优先级
                }
            });
        }

    }

},
LSGlobe.ScreenSpaceEventType.LEFT_CLICK);

oCutFillHandler.setInputAction(function(movement) {
    //生成面
    var oValuePoint = ChangePolygonPosition(poinsTemp);
    //点集合设置为统一高度
    for (var i = 2; i < oValuePoint.length; i = i + 3) {
        oValuePoint[i] = oHeight;
    }
    tempDataSource.entities.removeAll();
    //该面是辅助方量分析结果的面,最后方量分析的高度和范围是该面显示的高度和范围
    tempDataSource.entities.add({
        name: '方量分析辅助面',
        id: new Date().getTime(),
        polygon: {
            hierarchy: LSGlobe.Cartesian3.fromDegreesArrayHeights(oValuePoint),
            material: new LSGlobe.Color(0.5, 1.0, 1.0, 0.7),
            fill: true,
            outline: true,
            outlineColor: LSGlobe.Color.YELLOW,
            perPositionHeight: true
        }
    });
},
LSGlobe.ScreenSpaceEventType.RIGHT_CLICK);

//3).开始分析
function getProgress() {
    nodeMesh = tileset.NodeMesh;
}
modelAnalysis(oHeight);
function modelAnalysis(oHeight) {
    cutfill.clear();
    cutfill.completeEvent.addEventListener(progress);
    var cartographic = LSGlobe.Cartographic.fromCartesian(poinsTemp[0]);
    cutfill.vertice = nodeMesh;
    cutfill.matLocal = tileset.m_matLocal;
    LSGlobe.Matrix4.inverseTransformation(tileset.m_matLocal, cutfill.matLocalInvert);
    if (oHeight) {
        cutfill.zFactor = height;
    } else {
        cutfill.zFactor = cartographic.height;
    }
    //分析的面对象
    var Mypolygon = new LSGlobe.PolygonGeometry({
        polygonHierarchy: new LSGlobe.PolygonHierarchy(poinsTemp),
        perPositionHeight: true
    });
    cutfill.polygon = Mypolygon;
    //采样间隔
    cutfill.sampleGap = interval;
    //执行分析
    cutfill.apply();
}

插件的应用

线面绘制插件

线面插件的引用

 <!-- 在引入LSGlobe.js后引用插件javascript文件 -->
<script type="text/javascript" src="Plugins/VectorEditor/VectorEditor.js"></script>

线面插件的应用

使用前需要初始化标会插件

//初始化标绘插件对象
var oVectorEditor = new LSGlobe.VectorEditor(viewer);
//在结束绘制同时取消编辑状态
oVectorEditor._endDrawEvent.addEventListener(function () {
    oVectorEditor.endEdit();
});

绘制线

//绘制线
oVectorEditor.lineWidth = 5;//线宽
oVectorEditor.color = LSGlobe.Color.fromCssColorString("#FF0000");//线颜色
oVectorEditor.lineType = LSGlobe.LineTypeLSGlobe.LineType.SOLID//SOLID:实线,DASH:虚线,DOT:浮点,DASHDOT:-.-.-,DASHDOTDOT:-..-..
oVectorEditor.classificationType = undefined//TERRAIN:贴地表,CESIUM_3D_TILE:贴模型,BOTH贴模型贴地表,undefined:空间线

oVectorEditor._endEditEvent.addEventListener(fnEndPolylineEdit);

var fnEndPolylineEdit = function(entity) {
    //检测标绘集合中是否已经含有该entity
    if (!drawDataSource.entities.getById(entity.id)) {
        //添加到场景中
        drawDataSource.entities.add(entity);
        //也可以扩展其他功能,如向树节点添加节点等
    }else{
        //修改当前entity,参照标绘编辑--线编辑
    }
    viewer.entities.removeById(sEntityGuid);
}
oVectorEditor.drawPolyline();

//如需要删除该回调可以用删除监听接口
oVectorEditor._endEditEvent.removeEventListener(fnEndPolylineEdit);

绘制面

标绘面功能在我们场景中使用比较广,如单体化、压平、裁剪、水面等都有用到。此处主要介绍怎样绘出面,拿到面怎样扩展我们可以参照前面单体化、压平、裁剪、水面的接口,进行下一步的操作。

//绘制面
oVectorEditor.lineWidth = 1;//线宽(仅空间面支持,且只有1有效)
oVectorEditor.color = LSGlobe.Color.fromCssColorString("#FF0000");//面颜色
oVectorEditor.classificationType = undefined//TERRAIN:贴地表,CESIUM_3D_TILE:贴模型,BOTH贴模型贴地表,undefined:空间线
oVectorEditor.outlinecolor = LSGlobe.Color.fromCssColorString("rgba(255,255,255,0)");

oVectorEditor._endEditEvent.addEventListener(fnEndPolygonEdit);

var fnEndPolygonEdit = function(entity) {
    //检测标绘集合中是否已经含有该entity
    if (!drawDataSource.entities.getById(entity.id)) {
        //添加到场景中
        drawDataSource.entities.add(entity);
        //也可以扩展其他功能,如向树节点添加节点等
    }else{
        //修改当前entity,参照标绘编辑--线编辑
    }
    viewer.entities.removeById(sEntityGuid);

    var positions = entity.polygon.hierarchy.getValue().positions//拿到面的点参照对应接口,可以进行压平、裁剪、水面
}
oVectorEditor.drawPolygon();

//如需要删除该回调可以用删除监听接口
oVectorEditor._endEditEvent.removeEventListener(fnEndPolygonEdit);

指北针比例尺插件

<!--1).引用插件css文件 -->
<link href="Plugins/Navigation/Navigation.css" rel="stylesheet" type="text/css"/>
<!-- 如果想改变插件的位置修改该css文件即可 -->

<!--2).引用插件javascript文件 -->
<script type="text/javascript" src="Plugins/Navigation/viewerNavigationMixin.js"></script>

<!--3).将插件引入到场景中 -->

初始化指北针比例尺

viewer.extend(LSGlobe.viewerNavigationMixin);

量测插件

<!--1).引用插件css文件 -->
<link href="Plugins/Measure/Measure.css" rel="stylesheet" type="text/css"/>
<!-- 如果想改变插件的位置修改该css文件即可 -->

<!--2).引用插件javascript文件 -->
<script type="text/javascript" src="Plugins/Measure/viewerMeasureMixin.js"></script>

初始化量测插件

//3).将插件引入到场景中
viewer.extend(LSGlobe.viewerMeasureMixin);
viewer.measureEditer.viewModel.editerVisible = false;//量测控件是否显示
//4).插件的使用
//空间距离测量
viewer.measureEditer.viewModel.Distance();
//空间面积测量
viewer.measureEditer.viewModel.AreaMeasure();
//空间高度测量(三角量测)
viewer.measureEditer.viewModel.HeightMeasure();
//坐标测量
viewer.measureEditer.viewModel.Point();
//清空所有量测的结果
viewer.measureEditer.viewModel.ClearAll();
//重置量测状态
viewer.measureEditer.viewModel.ResetState();

模型编辑插件

模型编辑插件的使用主要为了在构建场景时快速的调整模型位置,所以模型编辑插件只能对实景三维模型和人工模型有效果,其中实景三维模型只能进行模型的左右和上下移动,人工模型可以进行模型和上下左右移动,还可进行模型绕z轴旋转

模型编辑引用

<!-- 1).引用插件css文件 -->
<link href="Plugins/EditBoxGeometry/EditBoxGeometry.css" rel="stylesheet" type="text/css"/>
<!-- 如果想改变插件的位置修改该css文件即可 -->

<!--2).引用插件javascript文件 -->
<script type="text/javascript" src="Plugins/EditBoxGeometry/EditBoxGeometry.js"></script>

模型编辑应用

//初始化模型平移插件
viewer.extend(LSGlobe.viewerEditBoxGeometryMixin);

//插件的使用
//1).添加对象
//添加某个想要编辑对象到插件中开始编辑(对象必须是人工或实景三维模型)
viewer.boxEditBoxGeometry.viewModel.editObject = "获取到的人工或者实景三维对象";
//2).设置平移模式
//只能上下左右平移的对象
viewer.boxEditBoxGeometry.viewModel.move();
//即能上下左右平移也可绕z轴旋转(人工模型)
viewer.boxEditBoxGeometry.viewModel.all();
//3).在球中拖动编辑框编辑刚刚插入的编辑对象
//4).编辑状态的保存
//模型平移结果在保存场景json的时候(viewer.toJSON())自动保存
//5).点击到编辑模型框的外面自动结束编辑状态
//插件的常用接口
//隐藏xyz轴、缩放
viewer.boxEditBoxGeometry.viewModel.cancel();
//xyz轴显示隐藏
viewer.boxEditBoxGeometry.viewModel.showAxis=true
//提示文字的显示隐藏
viewer.boxEditBoxGeometry.viewModel.showTooltip=false;
//z轴平移圆锥显隐
viewer.boxEditBoxGeometry.viewModel._showCylinder=true;

大矢量数据加载插件

参照前面矢量数据的预览功能

水面插件

参照前面水面功能

用户系统

该模块包含用户的登录、退出、获取用户信息、验证功能权限等

服务接口文档-用户相关

许可相关

该模块包含获取授权码、上传许可、获取许可信息等

服务接口文档-许可相关

团队权限管理

该模块包含对数据是否有数据预览、数据编辑、数据删除、数据权限配置等权限和是否具有场景预览、场景编辑、场景删除、场景权限配置等权,以及具有哪些菜单栏的权限比如:成员管理、团队管理等

服务接口文档-团队相关