0


cesium绘制路线,实现三维漫游

1.鼠标点击添加点和线

handler.setInputAction(function(event){//返回地球表面上的点坐标const earthPosition = positionUtil.cartesian2ToCartesian3(event.position)if(Cesium.defined(earthPosition)){const ellipsoid = viewer.scene.globe.ellipsoid;const cartographic = ellipsoid.cartesianToCartographic(earthPosition);const lon = Cesium.Math.toDegrees(cartographic.longitude);const lat = Cesium.Math.toDegrees(cartographic.latitude);const alt = cartographic.height +20// 高度加20AddPoint({
                lon,
                lat,
                alt,color: Cesium.Color.YELLOW}, viewer);
            positions.push(Cesium.Cartesian3.fromDegrees(lon, lat, alt))
            positons2.push({x:lon,y:lat,z:alt})if(positions.length >=2){if(!polyline)
                polyline =AddPolyline(viewer)}}}, Cesium.ScreenSpaceEventType.LEFT_CLICK);// 添加点constAddPoint=(params, viewer)=>{constentity:any =newCesium.Entity({id:`${params.lon}点`,name:'点',show:true,position: Cesium.Cartesian3.fromDegrees(params.lon, params.lat, params.alt),point:newCesium.PointGraphics({show:true,//是否展示pixelSize:10,//点大小color: params.color
      })});//收集Id
  viewer.entities.add(entity);return entity;}// 添加线constAddPolyline=(viewer)=>{const entity =newCesium.Entity({id:`${newDate().getTime()}线`,name:'线',polyline:newCesium.PolylineGraphics({show:true,clampToGround:false,positions:newCesium.CallbackProperty(function(){return positions;},false),//params.positions,width:10,material:newCesium.PolylineGlowMaterialProperty({glowPower:0.2,color: Cesium.Color.BLUE})})}as any);
  viewer.entities.add(entity);return entity;}

2.右键结束绘制时,计算折线中心点和绘制方向;折线中心点可以替换为模型中心点,这样就会看着这个点飞行;计算方向主要是判断绘制的顺序是顺时针绘制的还是逆时针绘制的

handler.setInputAction(function(event){// 计算折线中心点
      centerPos =caclPolyCenter(viewer)
      isRight =_judgeDirection(positions)// console.log(isRight, '逆时针');if(handler){
        handler.removeInputAction(Cesium.ScreenSpaceEventType.LEFT_CLICK);
        handler.removeInputAction(Cesium.ScreenSpaceEventType.RIGHT_CLICK);}}, Cesium.ScreenSpaceEventType.RIGHT_CLICK)constcaclPolyCenter=(viewer)=>{const entity =newCesium.Entity({name:"Red polygon on surface",polygon:{hierarchy:newCesium.PolygonHierarchy(positions),material: Cesium.Color.RED.withAlpha(0.5),},});const polyPositions = entity.polygon.hierarchy.getValue(Cesium.JulianDate.now()).positions;let polyCenter = Cesium.BoundingSphere.fromPoints(polyPositions).center;//中心点
  polyCenter = Cesium.Ellipsoid.WGS84.scaleToGeodeticSurface(polyCenter);const cartographic = Cesium.Cartographic.fromCartesian(polyCenter, viewer.scene.globe.ellipsoid,newCesium.Cartographic());const lat = Cesium.Math.toDegrees(cartographic.latitude);const lng = Cesium.Math.toDegrees(cartographic.longitude);const height = cartographic.height;return{x: lng,y: lat,z: height}}/**
   * 判断点的顺序是顺时针还是逆时针
   * @param {Cesium.Cartesian3[]} points
   */const_judgeDirection=(points)=>{const lonlat1 = Cesium.Cartographic.fromCartesian(points[0])const lonlat2 = Cesium.Cartographic.fromCartesian(points[1])const lonlat3 = Cesium.Cartographic.fromCartesian(points[2])const x1 = lonlat1.longitude,
    y1 = lonlat1.latitude,
    x2 = lonlat2.longitude,
    y2 = lonlat2.latitude,
    x3 = lonlat3.longitude,
    y3 = lonlat3.latitude,
    dirRes =(x2 - x1)*(y3 - y2)-(y2 - y1)*(x3 - x2)const isR = dirRes >0return isR
}

3.点击飞行
pitch默认为-5
setExtentTime: 在viewer的clock中设置时间间隔,flytime默认为15,也可以根据线段的长度来定义每一段的飞行时间
TimeExecution: 添加clock.onTick事件监听,每一帧调用,根据时间动态计算下一个点的坐标,然后更新相机位置.关于viewer.clock.onTick可查看api深入学习
changeCameraHeading: 如果当前的时间=设定的停止时间,移除监听并开始转向,当前时间=设定的停止时间时,开始下一段线的飞行marksIndex+1

constflyExtent=(viewer)=>{// 相机看点的角度,如果大于0那么则是从地底往上看,所以要为负值const pitch = Cesium.Math.toRadians(pitchValue);//  默认-5// 时间间隔15秒钟setExtentTime(flytime, viewer);Exection=functionTimeExecution(){let preIndex = marksIndex -1;if(marksIndex ===0){
      preIndex = positons2.length -1;}//计算俯仰角// 当前已经过去的时间,单位sconst delTime = Cesium.JulianDate.secondsDifference(viewer.clock.currentTime, viewer.clock.startTime);const originLat = marksIndex ==0? positons2[positons2.length -1].y : positons2[marksIndex -1].y;const originLng = marksIndex ==0? positons2[positons2.length -1].x : positons2[marksIndex -1].x;const endPosition = Cesium.Cartesian3.fromDegrees((originLng +(positons2[marksIndex].x - originLng)/ flytime * delTime),(originLat +(positons2[marksIndex].y - originLat)/ flytime * delTime),
      positons2[marksIndex].z
    );let heading =bearing(originLat,originLng, centerPos.y, centerPos.x);// let heading = bearing(centerPos.y, centerPos.x, originLat,originLng);
    heading = Cesium.Math.toRadians(heading);
    viewer.scene.camera.setView({destination: endPosition,orientation:{heading: heading,pitch: pitch,}});if(Cesium.JulianDate.compare(viewer.clock.currentTime, viewer.clock.stopTime)>=0){
      viewer.clock.onTick.removeEventListener(Exection);//有个转向的功能changeCameraHeading(viewer);}};
  viewer.clock.onTick.addEventListener(Exection);}// 相机原地定点转向constchangeCameraHeading=(viewer)=>{// 计算两点之间的方向let nextIndex = marksIndex +1;if(marksIndex == positons2.length -1){
    nextIndex =0;}const heading =bearing(positons2[marksIndex].y, positons2[marksIndex].x,centerPos.y, centerPos.x );
  console.log(heading, Cesium.Math.toDegrees(viewer.camera.heading));// 相机看点的角度,如果大于0那么则是从地底往上看,所以要为负值const pitch = Cesium.Math.toRadians(pitchValue);// 给定飞行一周所需时间,比如10s, 那么每秒转动度数// 相机是始终往角度小的方向转, 先确定绘制的线路是顺时针还是逆时针_judgeDirection// 判断当前camera.heading > 两点的heading// 如果大于,则360 - camera.heading + heading, eg: 360-340+20//这部分主要解决的是相机朝哪个方向转的问题,顺时针绘制的线和逆时针绘制的线转向不同,所以有了下面这些判断,或许还有更好的办法处理let angle =0if(!isRight){// 顺时针if(Cesium.Math.toDegrees(viewer.camera.heading)> heading){
      angle =((Cesium.Math.toDegrees(Cesium.Math.TWO_PI- viewer.camera.heading)+ heading)/ changeCameraTime);}else{
      angle =((heading - Cesium.Math.toDegrees(viewer.camera.heading))/ changeCameraTime);}}else{if(Cesium.Math.toDegrees(viewer.camera.heading)< heading){
      angle =((Cesium.Math.toDegrees(Cesium.Math.toRadians(heading)- Cesium.Math.TWO_PI)- Cesium.Math.toDegrees(viewer.camera.heading))/ changeCameraTime);}else{
      angle =((heading - Cesium.Math.toDegrees(viewer.camera.heading))/ changeCameraTime);}// angle = ((heading - Cesium.Math.toDegrees(viewer.camera.heading)) / changeCameraTime);}// const angle = ((heading - Cesium.Math.toDegrees(viewer.camera.heading)) / changeCameraTime);
  console.log(angle,'angle');// 时间间隔2秒钟setExtentTime(changeCameraTime, viewer);// 相机的当前headingconst initialHeading = viewer.camera.heading;Exection=functionTimeExecution(){// 当前已经过去的时间,单位sconst delTime = Cesium.JulianDate.secondsDifference(viewer.clock.currentTime, viewer.clock.startTime);// console.log(Cesium.Math.toRadians(delTime * angle), '1s转动的角度');const heading = Cesium.Math.toRadians(delTime * angle)+ initialHeading;
    viewer.scene.camera.setView({orientation:{heading: heading,pitch: pitch
      }});if(Cesium.JulianDate.compare(viewer.clock.currentTime, viewer.clock.stopTime)>=0){
      viewer.clock.onTick.removeEventListener(Exection);
      marksIndex =++marksIndex >= positons2.length ?0: marksIndex;if(marksIndex !=0){
        console.log(marksIndex,'marksIndex');flyExtent(viewer);}}};
  viewer.clock.onTick.addEventListener(Exection);}//计算俯仰角constbearing=(startLat, startLng, destLat, destLng)=>{
  startLat =toRadians(startLat);
  startLng =toRadians(startLng);
  destLat =toRadians(destLat);
  destLng =toRadians(destLng);const y = Math.sin(destLng - startLng)* Math.cos(destLat);const x = Math.cos(startLat)* Math.sin(destLat)- Math.sin(startLat)* Math.cos(destLat)* Math.cos(destLng - startLng);const brng = Math.atan2(y, x);const brngDgr =toDegrees(brng);return(brngDgr +360)%360;}// 角度转弧度consttoRadians=(degrees)=>{return degrees * Math.PI/180;}// 弧度转角度consttoDegrees=(radians)=>{return radians *180/ Math.PI;}

desktop 2023-04-03 11-55-18

参考大佬文章: https://blog.csdn.net/CFXXXL/article/details/125365952


本文转载自: https://blog.csdn.net/More_and_More1/article/details/129928630
版权归原作者 \'qiangwaer\' 所有, 如有侵权,请联系我们删除。

“cesium绘制路线,实现三维漫游”的评论:

还没有评论