Cesium画形状的一些方式-前端文章论坛-前端交流-技术鸭(jishuya.cn)

Cesium画形状的一些方式

画扇形 

import * as Cesium from 'cesium'

/**
 * 绘制扇形。
 *
 * @param {*} params: {
 *   olon // 扇形中心经度
 *   olat // 扇形中心纬度
 *   radius // 扇形半径
 *   fromAngle // 扇形起始角度(从正北开始计算,单位:度)
 *   toAngle // 扇形结束角度(从正北开始计算,单位:度)
 *   step // 每隔几度计算一次
 * }
 */
function calculateSectorHierarchy(viewer, params) {
  const points = []

  const oCartesian3 = Cesium.Cartesian3.fromDegrees(params.olon, params.olat)
  points.push(oCartesian3)

  const step = typeof params.step === 'undefined' ? 1 : params.step
  for (let angle = params.fromAngle; angle <= params.toAngle; angle += step) {
    const point = calculatePointInSector(
      viewer,
      params.olon,
      params.olat,
      params.radius,
      angle
    )
    points.push(point)
  }

  return points
}

/**
 * 计算扇形弧线上的各点的坐标,以绘制完整的扇形。
 *
 * 该函数解决的问题:已知圆心、半径,设圆心与正北方向的连线为0°,按照顺时针方向角度递增,求指定角度下的圆上的点的坐标。
 *
 * 注意:该函数计算的扇形弧线上的点的坐标是基于地球这个椭球体的,而非某个平面。
 *
 * @param {*} olon 圆心经度
 * @param {*} olat 圆心纬度
 * @param {*} radius 圆半径(单位:米)
 * @param {*} angle 角度(单位:°)
 */

function calculatePointInSector(viewer, olon, olat, radius, angle) {
  angle = Cesium.Math.toRadians(90 - angle)

  const webMercatorProjection = new Cesium.WebMercatorProjection(
    viewer.scene.globe.ellipsoid
  )
  const oMercator = webMercatorProjection.project(
    new Cesium.Cartographic(
      Cesium.Math.toRadians(olon),
      Cesium.Math.toRadians(olat),
      0
    )
  )

  const pMercator = new Cesium.Cartesian3(
    oMercator.x + radius * Math.cos(angle),
    oMercator.y + radius * Math.sin(angle),
    0
  )
  const pCartographic = webMercatorProjection.unproject(pMercator)

  return Cesium.Cartographic.toCartesian(pCartographic)
}

export { calculateSectorHierarchy}

根据经纬度方位距离计算点 

let mapNumberUtil = {};
// 弧度转角度
mapNumberUtil.deg = function (rad) {
  return (rad * 180) / Math.PI;
};

// 角度转弧度
mapNumberUtil.rad = function (deg) {
  return (deg * Math.PI) / 180;
};
mapNumberUtil.getLonAndLat = function (lng, lat, brng, dist) {
  // WGS-84 椭球体参数
  let a = 6378137; // 长半径
  let b = 6356752.3142; // 短半径
  let f = 1 / 298.257223563; // 扁率

  // 将输入经纬度、方位角转换为弧度
  let lon1 = this.rad(lng);
  let lat1 = this.rad(lat);
  let alpha1 = this.rad(brng);

  let sinAlpha1 = Math.sin(alpha1);
  let cosAlpha1 = Math.cos(alpha1);

  // 一些中间变量的计算
  let tanU1 = (1 - f) * Math.tan(lat1);
  let cosU1 = 1 / Math.sqrt(1 + tanU1 * tanU1);
  let sinU1 = tanU1 * cosU1;
  let sigma1 = Math.atan2(tanU1, cosAlpha1);
  let sinAlpha = cosU1 * sinAlpha1;
  let cosSqAlpha = 1 - sinAlpha * sinAlpha;
  let uSq = (cosSqAlpha * (a * a - b * b)) / (b * b);
  let A = 1 + (uSq / 16384) * (4096 + uSq * (-768 + uSq * (320 - 175 * uSq)));
  let B = (uSq / 1024) * (256 + uSq * (-128 + uSq * (74 - 47 * uSq)));

  // 迭代计算
  let sigma = dist / (b * A);
  let sigmaP = 2 * Math.PI;
  while (Math.abs(sigma - sigmaP) > 1e-12) {
    let cos2SigmaM = Math.cos(2 * sigma1 + sigma);
    let sinSigma = Math.sin(sigma);
    let cosSigma = Math.cos(sigma);
    let deltaSigma =
      B * sinSigma * (cos2SigmaM + (B / 4) * (cosSigma * (-1 + 2 * cos2SigmaM * cos2SigmaM) - (B / 6) * cos2SigmaM * (-3 + 4 * sinSigma * sinSigma) * (-3 + 4 * cos2SigmaM * cos2SigmaM)));
    sigmaP = sigma;
    sigma = dist / (b * A) + deltaSigma;
  }

  // 计算目标点的经纬度
  let tmp = sinU1 * sinSigma - cosU1 * cosSigma * cosAlpha1;
  let lat2 = Math.atan2(sinU1 * cosSigma + cosU1 * sinSigma * cosAlpha1, (1 - f) * Math.sqrt(sinAlpha * sinAlpha + tmp * tmp));
  let lambda = Math.atan2(sinSigma * sinAlpha1, cosU1 * cosSigma - sinU1 * sinSigma * cosAlpha1);
  let C = (f / 16) * cosSqAlpha * (4 + f * (4 - 3 * cosSqAlpha));
  let L = lambda - (1 - C) * f * sinAlpha * (sigma + C * sinSigma * (cos2SigmaM + C * cosSigma * (-1 + 2 * cos2SigmaM * cos2SigmaM)));

  // 计算目标点的经度和纬度,并返回结果
  let revAz = Math.atan2(sinAlpha, -tmp); // 最终方位角
  let lngLatObj = { lng: this.deg(lon1 + L), lat: this.deg(lat2) };
  return lngLatObj;
};

图片

viewer.entities.add({
    position: Cesium.Cartesian3.fromDegrees(),  //  传递经纬度
    billboard: {
      scaleByDistance: new Cesium.NearFarScalar(1.5e2, 1, 30.0e6, 0),
      image:,  // 图片
      color: Cesium.Color.WHITE.withAlpha(0.8),
      // 高度
      height: 50,
      width: 50,
      // 逆时针旋转
      //   rotation: 20,
      // 大小是否以米为单位
      sizeInMeters: false,
      // 相对于坐标的垂直位置
      // verticalOrigin: Cesium.VerticalOrigin.CENTER,
      // // 相对于坐标的水平位置
      // horizontalOrigin: Cesium.HorizontalOrigin.LEFT,
      scale: 1.0,
      show: true
    },
// 这里可以挂载其他属性上去
  })

多边形 

viewer.entities.add({
    polygon: {
      hierarchy: {
        positions: Cesium.Cartesian3.fromDegreesArray() // 传递经纬度
        // holes: 图形内需要挖空的区域
        // holes: [
        //   {
        //     positions: Cesium.Cartesian3.fromDegreesArray([
        //       119,
        //       32,
        //       115,
        //       34,
        //       119,
        //       40
        //     ])
        //   }
        // ]
      },
      // 边框
      outline: true,
      // 边框颜色
      outlineColor: Cesium.Color.BLUE, // WHITE: 白色
      // 边框尺寸
      outlineWidth: 2,
      // 填充的颜色 withAlpha透明度
      material: Cesium.Color.BLUE.withAlpha(0.3),
      // 是否被提供的材质填充
      fill: true,
      // 恒定高度
      height: 50,
      // 显示在距相机距离处的属性
      //   distanceDisplayCondition: new Cesium.DistanceDisplayCondition(
      //     100,
      //     10000000
      //   ),
      // 是否显示
      show: true
    },
  })

viewer.entities.add({
      position: Cesium.Cartesian3.fromDegrees(), // 经纬度
      ellipse: {
        semiMinorAxis: radius * 1000,
        semiMajorAxis: radius * 1000,
        rotation: Cesium.Math.toRadians(-40.0),
        // 边框
        outline: true,
        // 边框颜色
        outlineColor: Cesium.Color.BLUE, // WHITE: 白色
        // 边框尺寸
        outlineWidth: 2,
        // 填充颜色
        material: Cesium.Color.BURLYWOOD.withAlpha(0.3),
        outerWidth: 4,
        stRotation: Cesium.Math.toRadians(90)
      }
    })

画线

viewer.entities.add({
        polyline: {
          positions: Cesium.Cartesian3.fromDegreesArray(), // 两个经纬度
          // 宽度
          width: 2,
          // 线的颜色
          material: color || this.material || Cesium.Color.BLUE.withAlpha(0.3),
          // 流动的线
          // material: new LineFlowMaterialProperty({
          //   color: new Cesium.Color(1.0, 1.0, 0.0, 0.8),
          //   // color: Cesium.Color.BLUE.withAlpha(0.3),
          //   speed: 10,
          //   percent: 0.1,
          //   gradient: 0.2
          // }),

          // 线的顺序
          zIndex: 10,
          // 是否显示
          show: true
        },
        item, // 可以挂载自己需要的一些对象
      })

使用动态的线条需要使用的函数

import * as Cesium from 'cesium'

export class LineFlowMaterialProperty {
  constructor(options) {
    this._definitionChanged = new Cesium.Event()
    this._color = undefined
    this._speed = undefined
    this._percent = undefined
    this._gradient = undefined
    this.color = options.color
    this.speed = options.speed
    this.percent = options.percent
    this.gradient = options.gradient
  }

  get isConstant() {
    return false
  }

  get definitionChanged() {
    return this._definitionChanged
  }

  getType(time) {
    return Cesium.Material.LineFlowMaterialType
  }

  getValue(time, result) {
    if (!Cesium.defined(result)) {
      result = {}
    }

    result.color = Cesium.Property.getValueOrDefault(
      this._color,
      time,
      Cesium.Color.RED,
      result.color
    )
    result.speed = Cesium.Property.getValueOrDefault(
      this._speed,
      time,
      5.0,
      result.speed
    )
    result.percent = Cesium.Property.getValueOrDefault(
      this._percent,
      time,
      0.1,
      result.percent
    )
    result.gradient = Cesium.Property.getValueOrDefault(
      this._gradient,
      time,
      0.01,
      result.gradient
    )
    return result
  }

  equals(other) {
    return (
      this === other ||
      (other instanceof LineFlowMaterialProperty &&
        Cesium.Property.equals(this._color, other._color) &&
        Cesium.Property.equals(this._speed, other._speed) &&
        Cesium.Property.equals(this._percent, other._percent) &&
        Cesium.Property.equals(this._gradient, other._gradient))
    )
  }
}

Object.defineProperties(LineFlowMaterialProperty.prototype, {
  color: Cesium.createPropertyDescriptor('color'),
  speed: Cesium.createPropertyDescriptor('speed'),
  percent: Cesium.createPropertyDescriptor('percent'),
  gradient: Cesium.createPropertyDescriptor('gradient')
})

// Cesium.LineFlowMaterialProperty = LineFlowMaterialProperty;
Cesium.Material.LineFlowMaterialProperty = 'LineFlowMaterialProperty'
Cesium.Material.LineFlowMaterialType = 'LineFlowMaterialType'
Cesium.Material.LineFlowMaterialSource = `
    uniform vec4 color;
    uniform float speed;
    uniform float percent;
    uniform float gradient;

    czm_material czm_getMaterial(czm_materialInput materialInput) {
      czm_material material = czm_getDefaultMaterial(materialInput);
      vec2 st = materialInput.st;
      float t = fract(czm_frameNumber * speed / 1000.0);
      t *= (1.0 + percent);
      float alpha = smoothstep(t - percent, t, st.s) * step(-t, -st.s);
      alpha += gradient;
      material.diffuse = color.rgb;
      material.alpha = alpha;
      return material;
    }
  `

Cesium.Material._materialCache.addMaterial(
  Cesium.Material.LineFlowMaterialType,
  {
    fabric: {
      type: Cesium.Material.LineFlowMaterialType,
      uniforms: {
        color: new Cesium.Color(1.0, 0.0, 0.0, 1.0),
        speed: 10.0,
        percent: 0.1,
        gradient: 0.01
      },
      source: Cesium.Material.LineFlowMaterialSource
    },
    translucent: function(material) {
      return true
    }
  }
)

 

 

 

 

请登录后发表评论

    请登录后查看回复内容