Cesium封装-cone

11 篇文章 0 订阅

一、初始化地图

<template>
  <div class="cesium_map">
    <div id="cesiumContainer"></div>
  </div>
</template>

<script setup>
import { reactive, ref, onMounted } from "vue";
import { Cone } from "../../utils/Model";

// ---------------------------<<数据>>---------------------------
const me = reactive({
  cone: null,
});

// ---------------------------<<函数>>---------------------------
// 初始化地图
const initMap = () => {
  // 在线地图token
  Cesium.Ion.defaultAccessToken = "map_token";

  // 在线地图
  let imageryProvider = new Cesium.ArcGisMapServerImageryProvider({
    url: "map_url",
  });

  window.viewer = new Cesium.Viewer("cesiumContainer", {
    geocoder: false, // 右上角 搜索
    homeButton: false, // 右上角 Home
    sceneModePicker: false, // 右上角 2D/3D切换
    baseLayerPicker: false, // 右上角 地形
    navigationHelpButton: false, // 右上角 Help
    animation: false, // 左下角 圆盘动画控件
    timeline: false, // 时间轴
    fullscreenButton: false, // 右下角 全屏控件
    vrButton: false, // 如果设置为true,将创建VRButton小部件。
    scene3DOnly: false, // 每个几何实例仅以3D渲染以节省GPU内存
    infoBox: false, // 隐藏点击要素后的提示信息
    imageryProvider: imageryProvider, // 地图地址
    shouldAnimate: true,
  });
  viewer._cesiumWidget._creditContainer.style.display = "none";

  viewer.scene.globe.enableLighting = false;
  viewer.shadows = false;

  viewer.scene.globe.enableLighting = false;
  Cesium.Camera.DEFAULT_VIEW_FACTOR = 0.2; // 摄像机到地图的距离放大倍数
  viewer.camera.flyHome(0);

  // // 调整画面精细度
  viewer.resolutionScale = 1; //默认值为1.0
  viewer.scene.backgroundColor = Cesium.Color.TRANSPARENT;
  viewer.scene.globe.baseColor = Cesium.Color.TRANSPARENT;
  // //是否开启抗锯齿
  viewer.scene.fxaa = false;
  viewer.scene.postProcessStages.fxaa.enabled = false;
  viewer.scene.globe.showGroundAtmosphere = true;

  // 设置相机位置
  viewer.scene.camera.setView({
    destination: Cesium.Cartesian3.fromDegrees(
      110.82474250408677,
      22.095133670052277,
      80000
    ),
    orientation: {
      heading: Cesium.Math.toRadians(0),
      pitch: Cesium.Math.toRadians(-90),
      roll: 0.0,
    },
  });

  //取消双击事件
  viewer.cesiumWidget.screenSpaceEventHandler.removeInputAction(
    Cesium.ScreenSpaceEventType.LEFT_DOUBLE_CLICK
  );
};

// 初始化模型
const initModel = () => {
    // 请查看 “步骤三” 使用示例
};
// 初始化模型类
const initModelClass = () => {
  me.cone = new Cone(viewer, Cesium);
};

// ---------------------------<<执行>>---------------------------
// 挂载后生命周期
onMounted(() => {
  initMap();
  initModelClass();
  initModel();
});
</script>

<style lang="less" scoped>
.cesium_map {
  width: 100%;
  height: 100%;
  position: relative;

  #cesiumContainer {
    width: 100%;
    height: 100%;
  }
}
</style>

二、封装文件

export class Cone {
  constructor(viewer, Cesium) {
    this.viewer = viewer
    this.Cesium = Cesium
  }

  add(option) {
    let {
      position,
      config
    } = option;

    let {
      id,
      name,
      color,
      length,
      releaseGeometry,
    } = config

    var result = this.calcBeamScaleMatrix4(position);

    //绘制圆锥几何体
    var cone = new this.Cesium.Primitive({
      show: true,
      releaseGeometryInstances: releaseGeometry, // 默认为true,自动清空geometryInstances配置
      geometryInstances: new this.Cesium.GeometryInstance({
        id,
        name,
        geometry: new this.Cesium.CylinderGeometry({
          length,
          topRadius: 0.0,
          bottomRadius: result.bottomRadius,
        }),
      }),
      modelMatrix: result.mm, //提供位置与姿态参数
      appearance: new this.Cesium.EllipsoidSurfaceAppearance({
        material: this.getRingM({ color }), // 交替
        faceForward: true,
        closed: true,
      }),
    });

    this.viewer.scene.primitives.add(cone);
  }
  adjustAngle({ startAngle, endAngle }) {
    if (endAngle < startAngle) {
      if (endAngle > 180 && startAngle < 180) {
        var Az = startAngle; //先大小-前后交换顺序
        startAngle = endAngle;
        endAngle = Az;
      }
    }
    if (Math.abs(endAngle - startAngle) > 180) {
      if (endAngle > 180) {
        Az = startAngle;
        startAngle = endAngle - 360;
        endAngle = startAngle;
      }
    }
    return {
      startAngle,
      endAngle,
    };
  }
  calcBeamMatrix4({ lon, lat, alt, pitch, heading, length }) {
    //北天东与cesium坐标系的差距
    heading += 90;
    pitch = 270 - pitch;
    var center = this.Cesium.Cartesian3.fromDegrees(lon, lat, alt);
    heading = this.Cesium.Math.toRadians(heading);
    pitch = this.Cesium.Math.toRadians(pitch);

    var deadingPitchRoll = new this.Cesium.HeadingPitchRoll(heading, pitch, 0);
    var hprRotation = this.Cesium.Matrix3.fromHeadingPitchRoll(deadingPitchRoll);

    var subtract = new this.Cesium.Cartesian3(0, 0, -length / 2);
    var rotated = this.Cesium.Matrix3.multiplyByVector(
      hprRotation,
      subtract,
      new this.Cesium.Cartesian3()
    );

    var hpr = this.Cesium.Matrix4.fromRotationTranslation(hprRotation, rotated);

    var modelMatrix = this.Cesium.Transforms.eastNorthUpToFixedFrame(center);
    this.Cesium.Matrix4.multiply(modelMatrix, hpr, modelMatrix);
    return modelMatrix;
  }
  calcBeamScaleMatrix4({
    lon,
    lat,
    alt,
    length,
    startAz, //波束起始方位角
    endAz, //波束终止方位角
    startEl, //俯仰
    endEl, //俯仰
  }) {
    //俯仰在正负180之间
    if (startEl > 180) startEl -= 360;
    if (startEl < -180) startEl += 360;
    if (endEl > 180) endEl -= 360;
    if (endEl < -180) endEl += 360;

    var newParam = this.adjustAngle({
      startAngle: startAz,
      endAngle: endAz,
    });
    startAz = newParam.startAngle;
    endAz = newParam.endAngle;

    var newParam1 = this.adjustAngle({
      startAngle: startEl,
      endAngle: endEl,
    });
    startEl = newParam1.startAngle;
    endEl = newParam1.endAngle;

    var heading = (endAz + startAz) / 2; //圆锥的方位指向
    var pitch = ((startEl + endEl) / 2) % 180; //圆锥的俯仰指向俯仰在-180到180之间

    var angle0 = (endAz - startAz) / 2; //方位
    var angle1 = (endEl - startEl) / 2; //俯仰

    if (endAz < 0 && startAz < 0) {
      //计算缩放比列,取最小角度和取绝对值
      angle0 = Math.abs(((endAz % 360) - (startAz % 360)) / 2); //方位圆锥底面
      angle1 = Math.abs(((endEl % 360) - (startEl % 360)) / 2); //俯仰圆锥底面
    }
    var angle = 0;
    var scaleX = 1,
      scaleY = 1;
    if (angle0 < angle1) {
      angle = angle1;
      scaleX = angle0 / angle1; //计算x,y,z的缩放比例(以便形成椭圆面)
    } else {
      angle = angle0;
      scaleY = angle1 / angle0; //计算x,y,z的缩放比例(以便形成椭圆面)
    }

    var bottomRadius = length * Math.tan(Cesium.Math.toRadians(angle)); //计算底边半径(以最小的方位或俯仰角为准)
    var modelMatrix = this.calcBeamMatrix4({
      lon,
      lat,
      alt,
      heading,
      pitch,
      length,
    });

    var s = this.Cesium.Matrix3.fromScale(new Cesium.Cartesian3(scaleY, scaleX, 1.0));
    var scaleMatrix = this.Cesium.Matrix4.fromRotationTranslation(s);

    let mm = modelMatrix.clone();
    this.Cesium.Matrix4.multiply(mm, scaleMatrix, mm);
    return { mm, bottomRadius };
  }
  getRingM(params) {
    var { color, thickness, repeat } = params || {};
    var material = new this.Cesium.Material({
      fabric: {
        type: "VtxfShader",
        uniforms: {
          color: this.Cesium.Color.fromCssColorString(color || "rgba(255,0,0,0.3)"),
          repeat: repeat || 40.0, //40.0,/重复次数
          offset: 10, // 1.0,
          thickness: thickness || 0.5, //环宽度比列(0, 1]
        },
        source: `
                      uniform vec4 color;
                      uniform float repeat;
                      uniform float offset;
                      uniform float thickness;
                      czm_material czm_getMaterial(czm_materialInput materialInput)
                      {
                          czm_material material = czm_getDefaultMaterial(materialInput);
                          float sp = 1.0/repeat;
                          vec2 st = materialInput.st;
                          float dis = distance(st, vec2(0.5));
                          float m = mod(dis + offset, sp);
                          float a = step(sp*(1.0-thickness), m);
                          material.diffuse = color.rgb;
                          material.alpha = a * color.a;
                          return material;
                      }
                  `,
      },
      // translucent: false,
    });
    return material;
  }
}

三、使用示例

1、代码
const initModel = () => {
  me.cone.add({
    position: {
      lon: 110.82474250408677, // 经度
      lat: 22.095133670052277, // 纬度
      alt: 0, // 高度
      length: 8000, // 圆锥高度
      startAz: 30, // 起始方位
      endAz: 45, // 结束方位
      startEl: 30, // 起始俯仰
      endEl: 45, // 结束俯仰
    },
    config: {
      id: "cone", // 圆锥id
      name: "cone", // 圆锥name
      color: "#00ff00", // 圆锥颜色
      length: 8000, // 圆锥长度
      releaseGeometry: false, // 是否自动清空geometryInstances配置,默认为true,
    },
  });
}
2、效果

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值