cesium 效果

// cesium 动画效果
/**
 * @description 画扇形(从正北开始顺时针旋转)
 * @param {Viewer} viewer - Cesium的Viewer实例
 * @param {Number} d1 扇形下弧度的角度
 * @param {Number} d2 扇形上弧度的角度
 * @param {Number} longitude 中心点经度
 * @param {Number} latitude 中心点纬度
 * @param {Number} radius 扇形半径
 * @param {string} id 目标id
 */
function drawSector(viewer, d1, d2, longitude, latitude, radius, id) {
  var list = [Number(longitude), Number(latitude)];
  for (let i = d1; i < d2; i += 1) {
    var point = calculatingTargetPoints(
      longitude,
      latitude,
      0,
      (90 - i) * (Math.PI / 180),
      radius,
      viewer
    );
    list.push(point[0]);
    list.push(point[1]);
  }
  list.push(Number(longitude));
  list.push(Number(latitude));
  let color = Cesium.Color.BLUE.withAlpha(1);
  //蓝色扇形
  var box = viewer.entities.add({
    id: id + "hudu",
    polygon: {
      hierarchy: Cesium.Cartesian3.fromDegreesArray(list),
      material: color,
      outline: true, // height must be set for outlines to display
      outlineColor: {
        rgba: [255, 255, 255, 255],
      },
    },
  });
}

/**
 * 计算扇形的目标点经纬度
 * @param {number} longitude - 中心点经度
 * @param {number} latitude - 中心点纬度
 * @param {number} height - 中心点高度
 * @param {number} direction - 方向
 * @param {number} radius - 半径
 * @param {Viewer} viewer - Cesium的Viewer实例
 * @returns {number[]} - 目标点经纬度数组 [longitude, latitude]
 */
function calculatingTargetPoints(
  longitude,
  latitude,
  height,
  direction,
  radius,
  viewer
) {
  //根据位置,方位,距离求经纬度
  var viewPoint = Cesium.Cartesian3.fromDegrees(longitude, latitude, height);
  var webMercatorProjection = new Cesium.WebMercatorProjection(
    viewer.scene.globe.ellipsoid
  );
  var viewPointWebMercator = webMercatorProjection.project(
    Cesium.Cartographic.fromCartesian(viewPoint)
  );
  var toPoint = new Cesium.Cartesian3(
    viewPointWebMercator.x + radius * Math.cos(direction),
    viewPointWebMercator.y + radius * Math.sin(direction),
    0
  );
  toPoint = webMercatorProjection.unproject(toPoint);
  toPoint = Cesium.Cartographic.toCartesian(toPoint.clone());
  var cartographic = Cesium.Cartographic.fromCartesian(toPoint);
  var point = [
    Cesium.Math.toDegrees(cartographic.longitude),
    Cesium.Math.toDegrees(cartographic.latitude),
  ];
  return point;
}

/**
 * 在Cesium地图上添加圆形图形
 * @param {Viewer} viewer - Cesium的Viewer实例
 * @param {Cartesian3} centerPosition - 圆心的位置
 * @param {number} defense_radius - 圆形的半径(单位:米)
 * @param {Object} _this - 当前上下文对象
 */
function rotundity(viewer, centerPosition, defense_radius, _this) {
  // 创建实体 - 圆形图形
  let circleEntity = viewer.entities.add({
    id: "shebei",
    position: centerPosition,
    ellipse: {
      semiMinorAxis: defense_radius,
      semiMajorAxis: defense_radius,
      material: Cesium.Color.BLUE.withAlpha(0.1),
      outline: true,
      outlineColor: Cesium.Color.BLACK,
    },
  });
  let entity = viewer.entities.add({
    position: centerPosition,
    name: "圆形",
    ellipse: {
      semiMinorAxis: new Cesium.CallbackProperty(_this.changeR1, false),
      semiMajorAxis: new Cesium.CallbackProperty(
        _this.changeR1,
        false
      ) /* _this.changeR1 是一个函数 changeR1() {
      this.minR = this.minR + this.deviationR;
      if (this.minR > this.maxR) {
        this.minR = this.minR - this.maxR + this.deviationR;
      }
      return this.minR;
    } */,
      material: new Cesium.ColorMaterialProperty(
        new Cesium.CallbackProperty(
          _this.color,
          false
        ) /* _this.color  是一个函数,color() {
                    let x = 1 - this.minR / this.maxR;
                    return Cesium.Color.BLUE.withAlpha(0.3);
                  }         
                  */
      ),
      outlineColor: Cesium.Color.BLUE,
    },
  });
}

/**
 * 在Cesium地图上添加图形
 * @param {boolean} isAreaDefense - 是否是区域防御
 * @param {Viewer} viewer - Cesium的Viewer实例
 * @param {string} type - 图形类型('矩形', '圆形', '多边形')
 * @param {string} color - 图形的颜色(CSS颜色字符串)
 * @param {number} height - 图形的高度
 * @param {Array} points - 图形的点坐标数组
 * @param {number} radius - 圆形的半径
 */
function addfindList(
  isAreaDefense,
  viewer,
  type,
  color,
  height,
  points,
  radius
) {
  if (isAreaDefense) {
    if (type == "矩形") {
      var text = points;
      var positions = [
        Cesium.Cartesian3.fromDegrees(text[0].lng, text[0].lat, 0),
        Cesium.Cartesian3.fromDegrees(text[3].lng, text[3].lat, 0),
        Cesium.Cartesian3.fromDegrees(text[1].lng, text[1].lat, 0),
        Cesium.Cartesian3.fromDegrees(text[2].lng, text[2].lat, 0),
      ];

      var rectangle = viewer.entities.add({
        name: "矩形",
        polygon: {
          hierarchy: positions,
          material: Cesium.Color.fromCssColorString(color).withAlpha(0.5),
          extrudedHeight: height,
          perPositionHeight: true,
        },
      });
    } else if (type == "圆形") {
      var center;
      if (points != String([])) {
        if (points != String([])) {
          center = Cesium.Cartesian3.fromDegrees(
            JSON.parse(points)[0].lng,
            JSON.parse(points)[0].lat,
            0
          );
        }
        var cylinder = viewer.entities.add({
          name: "圆形",
          position: center,
          cylinder: {
            length: height,
            topRadius: radius,
            bottomRadius: radius,
            material: Cesium.Color.fromCssColorString(color).withAlpha(0.5),
            outline: false,
          },
        });
      }
    } else if (type == "多边形") {
      if (points != String([])) {
        var positions = [];
        points.forEach(function (point) {
          var position = Cesium.Cartesian3.fromDegrees(
            point.lng,
            point.lat,
            height
          );
          positions.push(position);
        });
        // 创建多边体实体对象
        var polygonEntity = viewer.entities.add({
          name: "多边形",
          polygon: {
            hierarchy: positions,
            extrudedHeight: height,
            material: Cesium.Color.fromCssColorString(color).withAlpha(0.5),
            outline: true,
            outlineColor: Cesium.Color.BLACK,
          },
        });
      }
    }
  }
}

/**
 * 在Cesium地图上创建圆形小圆点
 * @param {Viewer} viewer - Cesium的Viewer实例
 * @param {number} longitude - 圆点的经度
 * @param {number} latitude - 圆点的纬度
 * @param {number} detection_radius - 圆点的检测半径(单位:米)
 * @param {string} sensor_name - 圆点的名称
 */
function makeRotundity(
  viewer,
  longitude,
  latitude,
  detection_radius,
  sensor_name
) {
  var centerPosition = Cesium.Cartesian3.fromDegrees(longitude, latitude);
  // 创建半径
  var radius = detection_radius; // 单位:米

  // 创建实体 - 圆形图形
  var circleEntity = viewer.entities.add({
    position: centerPosition,
    ellipse: {
      semiMinorAxis: radius,
      semiMajorAxis: radius,
      material: Cesium.Color.RED.withAlpha(0.5),
      outline: true,
      outlineColor: Cesium.Color.BLACK,
    },
  });

  // 创建实体 - 小圆点
  var dotEntity = viewer.entities.add({
    position: centerPosition,
    point: {
      pixelSize: 10,
      color: Cesium.Color.BLUE,
      outlineColor: Cesium.Color.WHITE,
      outlineWidth: 2,
    },
  });

  // 创建实体 - 标签
  var labelEntity = viewer.entities.add({
    position: centerPosition,
    label: {
      text: sensor_name,
      font: "14px sans-serif",
      fillColor: Cesium.Color.WHITE,
      outlineColor: Cesium.Color.BLACK,
      outlineWidth: 1,
      style: Cesium.LabelStyle.FILL_AND_OUTLINE,
      horizontalOrigin: Cesium.HorizontalOrigin.CENTER,
      verticalOrigin: Cesium.VerticalOrigin.BOTTOM, // 标签底部对齐
      pixelOffset: new Cesium.Cartesian2(0, 30), // 将标签显示在小圆点下方
    },
  });
}

/**
 * 设置Cesium视图的位置和姿态
 * @param {Viewer} viewer - Cesium的Viewer实例
 * @param {number} longitude - 目标位置的经度
 * @param {number} latitude - 目标位置的纬度
 * @param {number} height - 目标位置的高度(单位:米)
 * @param {number} heading - 视图的方位角(单位:度)
 * @param {number} pitch - 视图的俯仰角(单位:度)
 * @param {number} roll - 视图的滚动角(单位:度)
 */
function setViewValue(
  viewer,
  longitude,
  latitude,
  height,
  heading,
  pitch,
  roll
) {
  viewer.camera.setView({
    destination: Cesium.Cartesian3.fromDegrees(longitude, latitude, height),
    orientation: {
      heading: Cesium.Math.toRadians(heading),
      pitch: Cesium.Math.toRadians(pitch),
      roll: Cesium.Math.toRadians(roll),
    },
  });
}

/**
 * 在Cesium中创建一个四边形柱体
 * @param {Viewer} viewer - Cesium的Viewer实例
 * @param {String} name - 四边形柱体的名称
 * @param {Array} positions - 四边形的位置数组,包含每个顶点的经纬度坐标
 * @param {String} color - 四边形的颜色,使用CSS颜色字符串表示
 * @param {Number} height - 柱体的高度
 */
/* 
var positions = [
    Cesium.Cartesian3.fromDegrees(-75.60354, 40.03883),
    Cesium.Cartesian3.fromDegrees(-75.60354, 40.04383),
    Cesium.Cartesian3.fromDegrees(-75.59854, 40.04383),
    Cesium.Cartesian3.fromDegrees(-75.59854, 40.03883)
]; // 四边形的位置数组,包含每个顶点的经纬度坐标
*/
function quadrilateral(viewer, name, positions, color, height) {
  var rectangle = viewer.entities.add({
    name: name,
    polygon: {
      hierarchy: positions,
      material: Cesium.Color.fromCssColorString(color).withAlpha(0.5),
      extrudedHeight: height,
      perPositionHeight: true,
    },
  });
}

/**
 * 在Cesium中创建一个圆形柱体
 * @param {Viewer} viewer - Cesium的Viewer实例
 * @param {string} name - 圆形柱体的名称
 * @param {Cartesian3} center - 圆形柱体的中心位置,使用Cesium.Cartesian3表示
 * @param {number} height - 圆柱体的高度
 * @param {number} radius - 圆柱体的半径
 * @param {string} color - 圆柱体的颜色,使用CSS颜色字符串表示
 */
function gardenShape(viewer, name, center, height, radius, color) {
  var cylinder = viewer.entities.add({
    name: name,
    position: center,
    cylinder: {
      length: height,
      topRadius: radius,
      bottomRadius: radius,
      material: Cesium.Color.fromCssColorString(color).withAlpha(0.5),
      outline: false,
    },
  });
}

/**
 * 在Cesium中创建一个多边形(柱体)
 * @param {Viewer} viewer - Cesium的Viewer实例
 * @param {String} name - 多边形的名称
 * @param {Array} positions - 多边形的位置数组,包含每个顶点的经纬度坐标
 * @param {Number} height - 柱体的高度
 * @param {String} color - 多边形的颜色,使用CSS颜色字符串表示
 */

function polygon(viewer, name, positions, height, color) {
  var polygonEntity = viewer.entities.add({
    name: name,
    polygon: {
      hierarchy: positions,
      extrudedHeight: height,
      material: Cesium.Color.fromCssColorString(color).withAlpha(0.5),
      outline: true,
      outlineColor: Cesium.Color.BLACK,
    },
  });
}

/**
 * 在Cesium中实现相机飞行动画
 * @param {Viewer} viewer - Cesium的Viewer实例
 * @param {Number} longitude - 目标位置的经度
 * @param {Number} latitude - 目标位置的纬度
 * @param {Number} height - 目标位置的高度
 * @param {Number} time - 飞行持续时间(以秒为单位)
 * @param {Number} heading - 方向角度(以度为单位)
 * @param {Number} pitch - 俯仰角度(以度为单位)
 * @param {Number} roll - 翻滚角度(以弧度为单位)
 */
function setflyTo(
  viewer,
  longitude,
  latitude,
  height,
  time,
  heading,
  pitch,
  roll
) {
  viewer.camera.flyTo({
    destination: Cesium.Cartesian3.fromDegrees(
      longitude,
      latitude,
      height
    ) /* 相机目标位置,即要飞往的目标位置 */,
    duration: time, // 转移持续时间(以秒为单位)
    orientation: {
      heading: Cesium.Math.toRadians(heading), // 方向角度(以弧度为单位)
      pitch: Cesium.Math.toRadians(pitch), // 俯仰角度(以弧度为单位)
      roll: roll, // 翻滚角度(以弧度为单位)
    },
  });
}

/**
 * @param {any} centerPosition :中心点
 * @param {any} viewer :实体
 * @param {Number} id  园的id
 * @param {Object} _this - 当前上下文对象
 * @param {String} color :圆形颜色  'rbg'或者'rgba(255,255,255,0.3)'
 */
function diffusion(centerPosition, viewer, id, _this, color) {
  viewer.entities.add({
    position: centerPosition,
    name: "圆形",
    id: id,
    ellipse: {
      semiMinorAxis: new Cesium.CallbackProperty(_this.changeR1, false),
      /* _this.changeR1 是一个函数 changeR1() {
      this.minR = this.minR + this.deviationR;
      if (this.minR > this.maxR) {
        this.minR = this.minR - this.maxR + this.deviationR;
      }
      return this.minR;
    } */
      semiMajorAxis: new Cesium.CallbackProperty(_this.changeR1, false),
      material: new Cesium.ColorMaterialProperty(
        new Cesium.CallbackProperty(function (time, result) {
          // 返回根据动态逻辑计算的颜色值
          return Cesium.Color.fromCssColorString(color);
        }, false)
      ),
      outlineColor: Cesium.Color.RED,
    },
  });
}

// 创建两点间的线段连接(折线)    实验 (120.277754, 31.533728, 2000)
/**
 * @description: 背景修改成天空盒(根据时间不同天空盒背景不同)
 * @param {any} viewer :实体
 * @param {Number} oldlongitude :上一个经度
 * @param {Number} oldlatitude :上一个纬度
 * @param {Number} oldheight :上一个高度
 * @param {Number} newlongitude :当前经度
 * @param {Number} newlatitude :当前纬度
 * @param {Number} newheight :当前高度
 * @param {String} name :名字
 * @param {String} color :线的颜色
 * @param {String} pointcolor :点的颜色
 */
function Polyline(
  viewer,
  oldlongitude,
  oldlatitude,
  oldheight,
  newlongitude,
  newlatitude,
  newheight,
  name,
  color,
  pointcolor
) {
  // 上一个点的位置
  var cartesianLast = Cesium.Cartesian3.fromDegrees(
    oldlongitude,
    oldlatitude,
    oldheight
  );
  // 现在点的位置
  var cartesianNow = Cesium.Cartesian3.fromDegrees(
    newlongitude,
    newlatitude,
    newheight
  );
  var polylinePosition = [cartesianLast, cartesianNow];
  viewer.entities.add({
    name: "line_" + name,
    polyline: new Cesium.PolylineGraphics({
      show: true,
      positions: polylinePosition,
      width: 1,
      material: Cesium.Color.fromCssColorString(color),
    }),
    position: cartesianNow,
    point: { pixelSize: 5, color: Cesium.Color.fromCssColorString(pointcolor) },
  });
}

/**
 * 在Cesium中添加倒三角模型并自动旋转
 * @param {Viewer} viewer - Cesium的Viewer实例
 * @param {number} longitude - 模型的经度
 * @param {number} latitude - 模型的纬度
 * @param {number} height - 模型的高度
 * @param {string} name - 模型的名称
 */
function invertedTriangle(viewer, longitude, latitude, height, name) {
  var position; // 模型的位置
  var heading = 0; //偏航角(Y轴)
  var pitch = 0; //俯仰角(X轴)
  var roll = 0; //翻滚角(Z轴)
  var lon = longitude;
  var lat = latitude;
  var hei = height;
  var flagevalue = true;
  //封装改变偏航角的方法
  function diaoyong() {
    heading = heading + Cesium.Math.toRadians(2);
    var hpr = new Cesium.HeadingPitchRoll(heading, pitch, roll);
    var orientation = Cesium.Transforms.headingPitchRollQuaternion(
      position,
      hpr
    );
    return orientation;
  }
  function positionvalue() {
    if (height - hei < 25 && flagevalue) {
      hei -= 0.2;
      position = Cesium.Cartesian3.fromDegrees(lon, lat, hei);
      return position;
    } else if (height - hei >= 0) {
      hei += 0.2;
      position = Cesium.Cartesian3.fromDegrees(lon, lat, hei);
      flagevalue = false;
      return position;
    } else {
      flagevalue = true;
    }
  }
  var zhui = viewer.entities.add({
    name: name,
    position: new Cesium.CallbackProperty(positionvalue, false) /* position */,
    orientation: new Cesium.CallbackProperty(diaoyong, false),
    model: {
      uri: "/model/zhui.glb", // 模型文件的路径
      scale: 40, // 模型的缩放比例
      minimumPixelSize: 50, // 模型的最小像素大小
      maximumScale: 200, // 模型的最大缩放比例
      color: Cesium.Color.DARKCYAN.withAlpha(0.5),
    },
  });
}

/**
 * @description: cesium 立体墙创建(高度有动画)
 * @param {any} viewer :实体
 * @param {Array} _positions :经纬度 [lon,lat,lon,lat....]
 */
function drawWall(viewer, _positions) {
  const maximumHeights = Array(_positions.length / 2).fill(600);
  const minimumHeights = Array(_positions.length / 2).fill(60);
  const positions = Cesium.Cartesian3.fromDegreesArray(_positions);
  const dayMaximumHeights = Array(minimumHeights.length).fill(600);

  const wallEntity = new Cesium.Entity({
    wall: {
      positions,
      maximumHeights: new Cesium.CallbackProperty(() => {
        for (let i = 0; i < minimumHeights.length; i++) {
          dayMaximumHeights[i] += maximumHeights[i] * 0.004;
          if (dayMaximumHeights[i] > maximumHeights[i]) {
            dayMaximumHeights[i] = minimumHeights[i];
          }
        }
        return dayMaximumHeights;
      }, false),
      minimumHeights,
      material: Cesium.Color.BLUE.withAlpha(0.3),
      heightReference: Cesium.HeightReference.NONE,
    },
  });

  viewer.entities.add(wallEntity);
}

/**
 * @description: 全屏报警状态(紧急状态)
 * @param {any} viewer :实体
 */
function emergencyAlarm(viewer) {
  const fragmentShaderSource = `
    precision highp float;
    
    float sdRoundBox(in vec2 p, in vec2 b, in vec4 r)
    {
        r.xy = (p.x > 0.0) ? r.xy : r.zw;
        r.x = (p.y > 0.0) ? r.x : r.y;
        vec2 q = abs(p) - b + r.x;
        return min(max(q.x, q.y), 0.0) + length(max(q, 0.0)) - r.x;
    }
    
    uniform sampler2D colorTexture;
    varying vec2 v_textureCoordinates;
    void main(void)
    {
        vec2 p = (gl_FragCoord.xy / (czm_viewport.zw / 2.0)) - 1.0;
        float d = sdRoundBox(p, vec2(0.8, 0.7), vec4(0.1));
        vec3 col = mix(vec3(0.0), vec3(1.0, 0.0, 0.0) * abs(sin(czm_frameNumber * 9.5)) * (d / 0.35), d > 0.0 ? 1.0 : 0.0);
        vec3 originalColor = texture2D(colorTexture, v_textureCoordinates).rgb;
        gl_FragColor = mix(vec4(originalColor, 1.0) * 2.0, vec4(col, 1.0), 0.5);
    }
`;

  viewer.scene.postProcessStages.add(
    new Cesium.PostProcessStage({
      fragmentShader: fragmentShaderSource,
    })
  );
}

/**
 * @description: 取消报警效果
 * @param {any} viewer :实体
 */
function cancelEmergencyAlarm(viewer) {
  const postProcessStages = viewer.scene.postProcessStages;
  const stages = postProcessStages._stages;
  const fragmentShaderSource = `
    precision highp float;
    
    float sdRoundBox(in vec2 p, in vec2 b, in vec4 r)
    {
        r.xy = (p.x > 0.0) ? r.xy : r.zw;
        r.x = (p.y > 0.0) ? r.x : r.y;
        vec2 q = abs(p) - b + r.x;
        return min(max(q.x, q.y), 0.0) + length(max(q, 0.0)) - r.x;
    }
    
    uniform sampler2D colorTexture;
    varying vec2 v_textureCoordinates;
    void main(void)
    {
        vec2 p = (gl_FragCoord.xy / (czm_viewport.zw / 2.0)) - 1.0;
        float d = sdRoundBox(p, vec2(0.8, 0.7), vec4(0.1));
        vec3 col = mix(vec3(0.0), vec3(1.0, 0.0, 0.0) * abs(sin(czm_frameNumber * 9.5)) * (d / 0.35), d > 0.0 ? 1.0 : 0.0);
        vec3 originalColor = texture2D(colorTexture, v_textureCoordinates).rgb;
        gl_FragColor = mix(vec4(originalColor, 1.0) * 2.0, vec4(col, 1.0), 0.5);
    }
`;

  for (let i = stages.length - 1; i >= 0; i--) {
    const stage = stages[i];
    if (stage.fragmentShader === fragmentShaderSource) {
      postProcessStages.remove(stage);
    }
  }
}

/**
 * @description: 发射线创建,可以用做信号传递
 * @param {any} viewer :实体
 * @param {Number} _num :数量
 */
function launchLine(viewer, _num) {
  // 获取viewer对象
  // const viewer = viewer;

  /**
   * @description: 抛物线构造函数
   * @param {*} startPosition 起始位置 [lon, lat]
   * @param {*} endPosition 结束位置 [lon, lat]
   * @param {*} height 抛物线顶点高度
   * @param {*} count 抛物线点的数量
   * @return {*} 抛物线点的数组
   */

  // 抛物线起始位置、结束位置和高度
  const startPosition = [120.277754, 31.533728];
  const endPosition = [120.277754, 31.628061];
  const height = 5000;

  // 创建抛物线飞线效果
  const siglePositions = parabola(startPosition, endPosition, height);
  for (let i = 0; i < _num; i++) {
    const polylineEntity = viewer.entities.add({
      polyline: {
        positions: new Cesium.CallbackProperty(function () {
          const currentTime = Cesium.JulianDate.now().secondsOfDay;
          const timeOffset = i * 0.5; // 每个线段的时间偏移量
          const index = Math.floor((currentTime + timeOffset) % 50);
          return siglePositions.slice(0, index + 1);
        }, false),
        width: 5,
        material: new Cesium.PolylineGlowMaterialProperty({
          glowPower: 0.2,
          color: Cesium.Color.RED,
        }),
      },
    });
  }

  // 创建轨迹线
  viewer.entities.add({
    polyline: {
      positions: siglePositions,
      width: 3,
      material: new Cesium.Color(1.0, 1.0, 0.0, 0.2),
    },
  });

  /**
   * @description: 抛物线构造函数(参考开源代码)
   * @param {*}
   * @return {*}
   */
  function parabola(startPosition, endPosition, height = 0, count = 50) {
    //方程 y=-(4h/L^2)*x^2+h h:顶点高度 L:横纵间距较大者
    let result = [];
    height = Math.max(+height, 100);
    count = Math.max(+count, 50);
    let diffLon = Math.abs(startPosition[0] - endPosition[0]);
    let diffLat = Math.abs(startPosition[1] - endPosition[1]);
    let L = Math.max(diffLon, diffLat);
    let dlt = L / count;
    if (diffLon > diffLat) {
      let delLat = (endPosition[1] - startPosition[1]) / count;
      if (startPosition[0] - endPosition[0] > 0) {
        dlt = -dlt;
      }
      for (let i = 0; i < count; i++) {
        let h =
          height -
          (Math.pow(-0.5 * L + Math.abs(dlt) * i, 2) * 4 * height) /
            Math.pow(L, 2);
        let lon = startPosition[0] + dlt * i;
        let lat = startPosition[1] + delLat * i;
        let point = new Cesium.Cartesian3.fromDegrees(lon, lat, h);
        result.push(point);
      }
    } else {
      let delLon = (endPosition[0] - startPosition[0]) / count;
      if (startPosition[1] - endPosition[1] > 0) {
        dlt = -dlt;
      }
      for (let i = 0; i < count; i++) {
        let h =
          height -
          (Math.pow(-0.5 * L + Math.abs(dlt) * i, 2) * 4 * height) /
            Math.pow(L, 2);
        let lon = startPosition[0] + delLon * i;
        let lat = startPosition[1] + dlt * i;
        let point = new Cesium.Cartesian3.fromDegrees(lon, lat, h);
        result.push(point);
      }
    }
    var pon = new Cesium.Cartesian3.fromDegrees(
      endPosition[0],
      endPosition[1],
      0
    );
    result.push(pon);
    return result;
  }
}

/**
 * @description: 旋转材质
 * @param {*} instance :实体
 * @param {*} _stRotation : 初始材质旋转角度
 * @param {*} _amount :旋转角度变化量
 */
function rotateMaterial(instance, _stRotation, _amount) {
  instance.stRotation = new Cesium.CallbackProperty(function () {
    _stRotation += _amount;
    if (_stRotation >= 360 || _stRotation <= -360) {
      _stRotation = 0;
    }
    return Cesium.Math.toRadians(_stRotation);
  }, false);
}

/**
 * @description: 等高线
 * @param {any} viewer :实体
 */
function contourLine(viewer) {
  let globe = viewer.scene.globe;

  let contourUniforms = {};

  // 使用等高线材质
  let material = Cesium.Material.fromType("ElevationContour");
  contourUniforms = material.uniforms;

  // 线宽2.0px
  contourUniforms.width = 2.0;
  // 高度间隔为150米
  contourUniforms.spacing = 150;

  contourUniforms.color = Cesium.Color.RED;

  // 设置材质
  globe.material = material;
}

/**
 * @description: 开启黑白视角
 * @param {any} viewer :实体
 */
function blackWhite(viewer) {
  var collection = viewer.scene.postProcessStages;
  var silhouette = collection.add(
    Cesium.PostProcessStageLibrary.createBlackAndWhiteStage()
  );
  silhouette.enabled = true;
  silhouette.uniforms.gradations = 15.0;
}

/**
 * @description: 开启夜视效果
 * @param {any} viewer :实体
 */
function nightVision(viewer) {
  var collection = viewer.scene.postProcessStages;
  var silhouette = collection.add(
    Cesium.PostProcessStageLibrary.createNightVisionStage()
  );
  silhouette.enabled = true;
}

/**
 * @description: 开启轮廓
 * @param {any} viewer :实体
 */
function makeContour(viewer) {
  var collection = viewer.scene.postProcessStages;
  var silhouette = collection.add(
    Cesium.PostProcessStageLibrary.createSilhouetteStage()
  );
  silhouette.enabled = true;
  silhouette.uniforms.color = Cesium.Color.YELLOW;
}

/**
 * 在Cesium中以动画效果将实体模型移动到目标位置
 * @param {Viewer} viewer - Cesium的Viewer实例
 * @param {Cartesian3} startPosition - 实体模型的起始位置
 * @param {Cartesian3} endPosition - 实体模型的目标位置
 * @param {boolean} isid - 是否根据ID删除匹配的实体
 */
function moveModelToPosition(viewer, startPosition, endPosition, isid) {
  if (isid) {
    const modelEntity = viewer.entities.getById("无人机mmm");
    if (modelEntity) {
      viewer.entities.remove(modelEntity); // 删除匹配的实体
    }
  }
  let factor = 0;
  const interpolatedPosition = new Cesium.Cartesian3(); // 创建一个用于插值结果的Cartesian3对象
  const cartesian = new Cesium.Cartesian3(
    startPosition.x,
    startPosition.y,
    startPosition.z
  );
  const cartesian2 = new Cesium.Cartesian3(
    endPosition.x,
    endPosition.y,
    endPosition.z
  );
  // 将Cartesian3转换为Cartographic
  const cartographic = Cesium.Cartographic.fromCartesian(cartesian);
  const cartographic2 = Cesium.Cartographic.fromCartesian(cartesian2);
  // 提取经纬度值
  const longitude = Cesium.Math.toDegrees(cartographic.longitude);
  const longitude2 = Cesium.Math.toDegrees(cartographic2.longitude);
  const latitude = Cesium.Math.toDegrees(cartographic.latitude);
  const latitude2 = Cesium.Math.toDegrees(cartographic2.latitude);
  // 根据距离和时间推算出速度
  let arrnum = getDistance(longitude, latitude, longitude2, latitude2);
  let juli = arrnum / 5000;
  // 添加模型
  const vehicleEntity = viewer.entities.add({
    id: "无人机mmm",
    position: new Cesium.CallbackProperty(function () {
      if (factor > 5000) {
        factor = 5000;
      }
      factor += juli;
      // 动态更新位置
      return Cesium.Cartesian3.lerp(
        startPosition,
        endPosition,
        factor / 5000.0,
        interpolatedPosition
      ); // 使用预先创建的Cartesian3对象
    }, false),
    model: {
      uri: "/model/drone/aviation_航空模型.glb",
      scale: 100.0,
    },
    orientation: Cesium.Transforms.headingPitchRollQuaternion(
      startPosition,
      new Cesium.HeadingPitchRoll(
        getHeading(endPosition, startPosition), // 设置这个属性即可(顺时针旋转的角度值)
        getPitch(endPosition, startPosition),
        Cesium.Math.toRadians(0)
      )
    ),
  });
}

/**
 * 计算两个经纬度坐标之间的距离
 * @param {number} lng_a - 第一个点的经度
 * @param {number} lat_a - 第一个点的纬度
 * @param {number} lng_b - 第二个点的经度
 * @param {number} lat_b - 第二个点的纬度
 * @returns {number} - 两点之间的距离(单位:米)
 */
function getDistance(lng_a, lat_a, lng_b, lat_b) {
  const earthRadius = 6371000; // 地球半径(单位:米)
  const deltaLng = toRadians(lng_b - lng_a);
  const deltaLat = toRadians(lat_b - lat_a);

  const a =
    Math.sin(deltaLat / 2) * Math.sin(deltaLat / 2) +
    Math.cos(toRadians(lat_a)) *
      Math.cos(toRadians(lat_b)) *
      Math.sin(deltaLng / 2) *
      Math.sin(deltaLng / 2);
  const c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));

  const distance = earthRadius * c;
  return distance;
}

/**
 * 将角度转换为弧度
 * @param {number} degrees - 角度值
 * @returns {number} - 弧度值
 */
function toRadians(degrees) {
  return degrees * (Math.PI / 180);
}

/**
 * 计算两个经纬度坐标之间的方位角(heading)
 * @param {Cartesian3} pointA - 第一个点的Cartesian3坐标
 * @param {Cartesian3} pointB - 第二个点的Cartesian3坐标
 * @returns {number} - 两点之间的方位角(单位:弧度)
 */
function getHeading(pointA, pointB) {
  //建立以点A为原点,X轴为east,Y轴为north,Z轴朝上的坐标系
  // debugger
  const transform = Cesium.Transforms.eastNorthUpToFixedFrame(pointA);
  //向量AB
  const positionvector = Cesium.Cartesian3.subtract(
    pointB,
    pointA,
    new Cesium.Cartesian3()
  );
  //因transform是将A为原点的eastNorthUp坐标系中的点转换到世界坐标系的矩阵
  //AB为世界坐标中的向量
  //因此将AB向量转换为A原点坐标系中的向量,需乘以transform的逆矩阵。
  const vector = Cesium.Matrix4.multiplyByPointAsVector(
    Cesium.Matrix4.inverse(transform, new Cesium.Matrix4()),
    positionvector,
    new Cesium.Cartesian3()
  );
  //归一化
  const direction = Cesium.Cartesian3.normalize(
    vector,
    new Cesium.Cartesian3()
  );
  //heading
  const heading =
    Math.atan2(direction.y, direction.x) - Cesium.Math.PI_OVER_TWO;
  return Cesium.Math.TWO_PI - Cesium.Math.zeroToTwoPi(heading);
}

/**
 * 计算两个经纬度坐标之间的俯仰角(pitch)
 * @param {Cartesian3} pointA - 第一个点的Cartesian3坐标
 * @param {Cartesian3} pointB - 第二个点的Cartesian3坐标
 * @returns {number} - 两点之间的俯仰角(单位:弧度)
 */
function getPitch(pointA, pointB) {
  let transfrom = Cesium.Transforms.eastNorthUpToFixedFrame(pointA);
  const vector = Cesium.Cartesian3.subtract(
    pointB,
    pointA,
    new Cesium.Cartesian3()
  );
  let direction = Cesium.Matrix4.multiplyByPointAsVector(
    Cesium.Matrix4.inverse(transfrom, transfrom),
    vector,
    vector
  );
  Cesium.Cartesian3.normalize(direction, direction);
  return Cesium.Math.PI_OVER_TWO - Cesium.Math.acosClamped(direction.z);
}

/* 获取到当前经纬度并添加标示 */
function addmarked(viewer) {
  function getLatLngFromMouseClick(viewer) {
    var handler = new Cesium.ScreenSpaceEventHandler(viewer.scene.canvas);

    function runOnce(event) {
      var cartesian = viewer.camera.pickEllipsoid(
        event.position,
        viewer.scene.globe.ellipsoid
      );

      if (cartesian) {
        var cartographic = Cesium.Cartographic.fromCartesian(cartesian);
        var longitude = Cesium.Math.toDegrees(cartographic.longitude);
        var latitude = Cesium.Math.toDegrees(cartographic.latitude);

        console.log("Clicked Longitude: " + longitude);
        console.log("Clicked Latitude: " + latitude);

        // 创建标记的位置(Cartesian3 或 Cartographic)
        var position = Cesium.Cartesian3.fromDegrees(longitude, latitude);

        // 创建一个标记实体
        var markerEntity = viewer.entities.add({
          name: "yuanpion",
          position: position,
          point: {
            pixelSize: 10,
            color: Cesium.Color.RED,
            outlineColor: Cesium.Color.WHITE,
            outlineWidth: 2,
          },
          label: {
            text: "经度:" + longitude + "\n" + "纬度:" + latitude,
            font: "14px sans-serif",
            fillColor: Cesium.Color.WHITE,
            outlineColor: Cesium.Color.BLACK,
            outlineWidth: 2,
            style: Cesium.LabelStyle.FILL_AND_OUTLINE,
            verticalOrigin: Cesium.VerticalOrigin.BOTTOM,
            pixelOffset: new Cesium.Cartesian2(0, -10),
          },
        });

        // 移除事件处理程序,使其只运行一次
        handler.removeInputAction(Cesium.ScreenSpaceEventType.LEFT_CLICK);
      }
    }

    handler.setInputAction(runOnce, Cesium.ScreenSpaceEventType.LEFT_CLICK);
  }
  getLatLngFromMouseClick(viewer);
}

export {
  drawSector,
  rotundity,
  addfindList,
  makeRotundity,
  setViewValue,
  quadrilateral,
  gardenShape,
  polygon,
  setflyTo,
  diffusion,
  Polyline,
  invertedTriangle,
  drawWall,
  emergencyAlarm,
  cancelEmergencyAlarm,
  launchLine,
  rotateMaterial,
  contourLine,
  blackWhite,
  nightVision,
  makeContour,
  moveModelToPosition,
  addmarked,
};

  • 2
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值