请问如何将已经写好的cesium,改变为cesium+mapV,达到性能的提升?

发布于 2023-08-24 10:09:49

由于后期的websocket会发送大量的数据,Cesium可能会面临性能瓶颈,而MapV是一个专门处理大规模地理数据可视化的库,它在处理大数据量时具有较好的性能和渲染效果,结合使用Cesium和MapV,请问我该如何在原有的cesium基础上进行Cesium来展示整体的3D地球模型,并将大量的轨迹点和轨迹线数据传递给MapV来进行可视化处理。以提高性能和渲染效果?求大佬们帮帮忙

<template>
  <div class="container">
    <div class="map">
      <div id="cesiumContainer">
      </div>
      <div class="getLongLat">
        经度:{{ longitude }},纬度:{{ latitude }}
      </div>
      <!--系统设置 -->
      <div class="right_top">
        <el-dropdown ref="dropdown1" trigger="click">
          <ul>
            <li>显示设置</li>
          </ul>
          <template #dropdown>
            <el-dropdown-menu>
              <el-dropdown-item>
                <el-checkbox v-model="checkedPoint" label="显示轨迹点" size="large" style="color: #606266;" />
              </el-dropdown-item>
              <el-dropdown-item>
                <el-checkbox v-model="checkedLines" label="显示轨迹线" size="large" style="color: #606266;" />
              </el-dropdown-item>
            </el-dropdown-menu>
          </template>
        </el-dropdown>
      </div>
    </div>
  </div>
</template>
<script setup >
import { onMounted, onUnmounted, reactive, defineProps, ref, computed, watch, } from 'vue';
import * as Cesium from 'cesium';
import * as MapV from 'mapv'
import { SampledPositionProperty } from "cesium";
import CesiumNavigation from 'cesium-navigation-es6'
import api from '@/api/api';
import back from '@/api/back'
import { ElMessage } from 'element-plus';
import emitter from '@/api/eventpus/eventbus';
import { map } from 'lodash';
let socketInfo = 'ws://192.168.0.45:8089/kunchen-plsms-websocket/webSocket'
let ws = new WebSocket(socketInfo)
let pingInterval = ref(null) // 心跳间隔ID
let viewer = null
let entity = null
// 从服务器获取用户角色名
const userRole = computed(() => {
  return window.localStorage.getItem('roles')
})
const dropdown1 = ref()
// 点击地图获取经纬度
let longitude = ref(null);
let latitude = ref(null);
let isFirstExecution = true;//处理第一次监听watch的标志
onMounted(() => {
  init() //加载3d地图,
  webValue()//加载websocket
  LocusModel()//3D地图模型
  AdmainInfo()//基站设备显示
  getautoDrive()//获取申请路径规划
})

// 地图的基础配置
function init() {
  viewer = new Cesium.Viewer('cesiumContainer', {
    //cesium的查看器的基本属性
    baseLayerPicker: false,//配置图层底图的图标
    //加载谷歌影像地图,UrlTemplateImageryProvider该接口是加载谷歌地图服务的接口
    imageryProvider: new Cesium.ArcGisMapServerImageryProvider({
      // url: "https://map.geoq.cn/arcgis/rest/services/ChinaOnlineStreetPurplishBlue/MapServer",
      url: 'https://services.arcgisonline.com/ArcGIS/rest/services/World_Imagery/MapServer' //卫星地图
    }),
    //需要纯色背景必须设置
    contextOptions: {
      webgl: {
        alpha: true,
      }
    },
    infoBox: false,//去除原生自带右上角弹窗
    sceneMode: 3,//初始场景模式 1 2D模式 2 2D循环模式 3 3D模式  Cesium.SceneMode
    geocoder: false,   //查找位置工具
    homeButton: true, // 视角返回初始位置
    sceneModePicker: false, //选择视角模式,有三种 3D,2D,哥伦比视图
    baseLayerPicker: false, //图层选择器,选择要显示的地图服务和地形服务
    navigationHelpButton: false, //导航帮助按钮,显示默认的地图控制帮助
    animation: false, //动画器件,控制视图动画的播放速度.
    // creditContainer: "credit", // 版权显示,显示数据归属
    timeline: false, //时间线,指示当前时间,并允许用户跳到特定的时间
    fullscreenButton: false, //全屏按钮
    vrButton: false,
    baseLayerPicker: false,
    // terrainProvider: Cesium.createWorldTerrain({ // 设置cesium世界地形
    //   requestWaterMask: true,//地形的开启
    //   requestVertexNormals: true,//水面效果的开启
    // })
  })
  // viewer.scene.skyBox.show = false //关闭天空盒,否则会显示天空颜色
  //背景透明
  // 取消标点的双击事件
  viewer.cesiumWidget.screenSpaceEventHandler.removeInputAction(Cesium.ScreenSpaceEventType.LEFT_DOUBLE_CLICK);
  viewer.scene.globe.depthTestAgainstTerrain = false;
  viewer.scene.backgroundColor = new Cesium.Color(0.0, 0.0, 0.0, 0.0);
  //关闭大气
  viewer.scene.skyAtmosphere.show = false
  //抗锯齿
  viewer.scene.fxaa = true;
  viewer.scene.postProcessStages.fxaa.enabled = true;
  //清除月亮太阳
  viewer.scene.moon.show = false
  viewer.scene.sun.show = false
  // 设置最小缩放级别
  // viewer.scene.screenSpaceCameraController.minimumZoomDistance = 20; // 米为单位
  // 去除logo 版权显示,显示数据归属
  viewer.cesiumWidget.creditContainer.style.display = "none";
  // 设置初始默认视角
  // let camera = { longitude: 104.2255077, latitude: 30.57514052 }
  let camera = { longitude: 104.22499925, latitude: 30.57339262 }
  viewer.camera.setView({
    destination: Cesium.Cartesian3.fromDegrees(camera.longitude, camera.latitude, 150),
    orientation: {
      heading: 6.283185307179581,//方向
      // heading: Cesium.Math.toRadians(18),//方向 
      pitch: Cesium.Math.toRadians(-45),//视角 设置俯仰角度为-45度
      roll: 0.0
    }
  });
  // 修改homeButton的默认返回位置
  viewer.homeButton.viewModel.command.beforeExecute.addEventListener(function (e) {
    e.cancel = true;
    viewer.camera.flyTo({
      destination: Cesium.Cartesian3.fromDegrees(camera.longitude, camera.latitude, 150),
      orientation: {
        heading: 6.283185307179581,//方向
        pitch: Cesium.Math.toRadians(-45),//视角 设置俯仰角度为-45度
        roll: 0.0
      }
    })
  })
  // 显示帧率
  viewer.scene.debugShowFramesPerSecond = false;
  // 添加罗盘,比例尺等控件
  //配置项
  var options = {
    // 用于在使用重置导航重置地图视图时设置默认视图控制。接受的值是Cesium.Cartographic 和 Cesium.Rectangle.
    defaultResetView: Cesium.Rectangle.fromDegrees(80, 22, 130, 50),
    // 用于启用或禁用罗盘。
    enableCompass: false,
    // 用于启用或禁用缩放控件。
    enableZoomControls: true,
    // 用于启用或禁用距离图例。
    enableDistanceLegend: true,
    // 用于启用或禁用指南针外环。
    enableCompassOuterRing: true
  };
  // 初始化罗盘
  new CesiumNavigation(viewer, options);
  // 鼠标移动获取地图经纬度
  let handler = new Cesium.ScreenSpaceEventHandler(viewer.scene.canvas);
  handler.setInputAction(function (event) {
    // 获取地图画布尺寸
    let canvas = viewer.scene.canvas;
    let canvasWidth = canvas.clientWidth;
    let canvasHeight = canvas.clientHeight;
    // 检查鼠标是否在地图画布内
    let mouseX = event.endPosition.x;
    let mouseY = event.endPosition.y;
    if (mouseX < 0 || mouseX > canvasWidth || mouseY < 0 || mouseY > canvasHeight) {
      return; // 鼠标不在地图画布内,忽略该事件
    }
    // 获取鼠标对应的地图坐标
    let cartesian = viewer.camera.pickEllipsoid(event.endPosition);
    if (!cartesian) {
      return; // 没有获取到合法的地图坐标,忽略该事件
    }
    let cartographic = Cesium.Cartographic.fromCartesian(cartesian);
    let lng = Cesium.Math.toDegrees(cartographic.longitude); // 经度
    let lat = Cesium.Math.toDegrees(cartographic.latitude); // 纬度
    let coordinate = {
      longitude: Number(lng.toFixed(8)),
      latitude: Number(lat.toFixed(8)),
    };
    longitude.value = coordinate.longitude;
    latitude.value = coordinate.latitude;
  }, Cesium.ScreenSpaceEventType.MOUSE_MOVE);

}
// 加载websocket
function webValue() {
  // 初始Websocket
  const onOpen = () => {
    const data = JSON.stringify({ command: 1, serializeAlgorithm: 1, token: window.localStorage.getItem('token') });
    ws.send(data); // 发送JSON字符串
    // 设置心跳间隔为5秒
    pingInterval.value = window.setInterval(() => {
      const pingMessage = JSON.stringify({
        command: 2,
        serializeAlgorithm: 1
      });
      ws.send(pingMessage);
    }, 5000);
  };
  if (window.localStorage.getItem('CardUID') === null) {
    return ElMessage({
      message: '车辆终端ID未绑定,请点击右上角的“设置”图标进行绑定。',
      type: 'warning',
      showClose: true
    });
  }
  // 接收websocket数据
  const onMessage = async (event) => {
    const data = JSON.parse(event.data);
    if (data.data == undefined) {
      console.log('未响应');
    } else {
      processPositionParams(data.data);
    }
  };
  // 封装处理位置参数的函数
  const positionParams = []; // 用于存储所有的位置参数数据
  const bufferLimit = 50; // 缓冲区大小限制,可以根据需求调整
  function processPositionParams(data) {
    const targetingTypes = {
      0x10: 'RTK',
      0x11: 'UWB',
      0x12: '融合'
    };
    const newPositionParam = {
      TargetingType: targetingTypes[data.type],
      UID: data.uid,
      Angle: data.angle,
      Height: data.height,
      longitude: data.longitude,
      latitude: data.latitude
    };
    positionParams.push(newPositionParam);
    // 超过缓冲区大小限制时移除最旧的位置参数数据
    if (positionParams.length > bufferLimit) {
      positionParams.shift();
    }
    const labelText = `终端ID:${data.uid},定位类型:${targetingTypes[data.type]}\n经度:${data.longitude},纬度:${data.latitude}\n角度:${data.angle},高度:${data.height}`;
    CarModel(positionParams, newPositionParam.Angle, data.uid); // 车辆模型
    pointPolyline(positionParams, labelText, data.uid) // 轨迹点和轨迹线
  }
  const onClose = () => {
    window.clearInterval(pingInterval.value); // 清除心跳间隔定时器
    console.log('Websocket连接关闭');
    webValue();
  };
  const onError = (error) => {
    console.log('Websocket连接错误');
    ws.close();
    window.clearInterval(pingInterval.value); // 清除心跳间隔定时器
    webValue();
  };
  ws.addEventListener('open', onOpen);
  ws.addEventListener('message', onMessage);
  ws.addEventListener('close', onClose);
  ws.addEventListener('error', onError);
}

// 退出登录
emitter.on('logout', () => {
  // 关闭 Websocket 连接
  ws.close();
  window.clearInterval(pingInterval.value); // 清除心跳间隔定时器
});


// 绘制车辆模型和轨迹点、轨迹线
let checkedPoint = ref(true);
let checkedLines = ref(false);
// 保存checkedPoint和checkedLines的值到LocalStorage
function saveCheckedValues() {
  localStorage.setItem('checkedPoint', JSON.stringify(checkedPoint.value));
  localStorage.setItem('checkedLines', JSON.stringify(checkedLines.value));
}
// 从LocalStorage中获取checkedPoint和checkedLines的值
function loadCheckedValues() {
  const storedCheckedPoint = localStorage.getItem('checkedPoint');
  const storedCheckedLines = localStorage.getItem('checkedLines');
  if (storedCheckedPoint) {
    checkedPoint.value = JSON.parse(storedCheckedPoint);
  }
  if (storedCheckedLines) {
    checkedLines.value = JSON.parse(storedCheckedLines);
  }
}
// 监听checkedPoint和checkedLines的变化,并保存到LocalStorage
watch([checkedPoint, checkedLines], saveCheckedValues, { deep: true });
// 在页面加载时加载checkedPoint和checkedLines的值
window.addEventListener('load', loadCheckedValues);
// 车辆模型
let carModelData = null;
function CarModel(positions, angle, uid) {
  const headingPitchRoll = new Cesium.HeadingPitchRoll(
    Cesium.Math.toRadians(angle + 90),
    Cesium.Math.toRadians(0),
    Cesium.Math.toRadians(0)
  );
  const scaleByDistance = new Cesium.NearFarScalar(200, 120, 1200, 0.6);
  const distanceDisplayCondition = new Cesium.DistanceDisplayCondition(0, 10000);

  // 获取最新的位置
  const latestPosition = positions[positions.length - 1];
  const cartesian3 = Cesium.Cartesian3.fromDegrees(latestPosition.longitude, latestPosition.latitude, 0.4);
  if (!carModelData) {
    carModelData = viewer.entities.add({
      position: cartesian3,
      orientation: Cesium.Transforms.headingPitchRollQuaternion(cartesian3, headingPitchRoll),
      model: {
        uri: "http://127.0.0.1:5501/car/scene.gltf",
        // color: Cesium.Color.CORAL,
        scale: 75,
        scaleByDistance,
        distanceDisplayCondition,
      },
    });
  } else {
    carModelData.position = cartesian3;
    carModelData.orientation = Cesium.Transforms.headingPitchRollQuaternion(cartesian3, headingPitchRoll);
  }
}

// 轨迹点  和  轨迹线   和  标签文字npm add mapv
let polylineEntity = null;
let entityList = [];
let positionsArray = [];
function pointPolyline(positions, labelText, uid) {
  const cartesian3Array = [];
  positionsArray = positions.flatMap(pos => [pos.longitude, pos.latitude]);
  // 移除之前的实体点
  for (const entity of entityList) {
    viewer.entities.remove(entity);
  }
  entityList = [];
  for (const position of positions) {
    let entityIndex = entityList.length;
    const cartesian3 = Cesium.Cartesian3.fromDegrees(
      position.longitude,
      position.latitude,
      0.02
    );
    const pointLabel = new Cesium.Entity({
      position: cartesian3,
      point: {
        pixelSize: 10,
        color: Cesium.Color.BLUE,
        show: checkedPoint.value,
        outlineColor: Cesium.Color.WHITE,
        outlineWidth: 1,
      },
      // label: {
      //   text: labelText,
      //   font: '14pt monospace',
      //   show: new Cesium.CallbackProperty(() => {
      //     return entityIndex === entityList.length - 1;
      //   }, false),
      //   style: Cesium.LabelStyle.FILL_AND_OUTLINE,
      //   outlineWidth: 2,
      //   verticalOrigin: Cesium.VerticalOrigin.BOTTOM,
      //   pixelOffset: new Cesium.Cartesian2(0, -9),
      //   fillColor: Cesium.Color.WHITE,//标签的文本填充颜色。
      //   outlineColor: Cesium.Color.WHITE,//标签的文本轮廓颜色。
      // },
    });
    entityList.push(pointLabel);
    viewer.entities.add(pointLabel);
    cartesian3Array.push(cartesian3);
  }

  // 更新轨迹线位置
  if (polylineEntity) {
    polylineEntity.polyline.positions = new Cesium.CallbackProperty(() => {
      return Cesium.Cartesian3.fromDegreesArray(positionsArray);
    }, false);
    polylineEntity.polyline.show = checkedLines.value;
  } else {
    // 创建新的轨迹线
    polylineEntity = viewer.entities.add({
      polyline: {
        positions: new Cesium.CallbackProperty(() => {
          return Cesium.Cartesian3.fromDegreesArray(positionsArray);
        }, false),
        width: 15,
        material: Cesium.Color.RED,
      },
    });
  }
}

// 获取父组件传递的停车场信息的经纬度
let props = defineProps({
  cesiumData: Object,
})

// 3D地图模型
function LocusModel() {
  const positions = [{ longitude: 104.2255077, latitude: 30.57514052 }]//停车场区域中心点
  positions.forEach((position, index) => {
    // 加载3d地图模型
    position = Cesium.Cartesian3.fromDegrees(position.longitude, position.latitude);
    let entity = new Cesium.Entity({
      position: position,
      model: {
        uri: 'http://127.0.0.1:5501/parking/lq_parking_space.gltf',
        // uri: '/car/lq_parking_space.gltf',
        show: true,
        maximumSize: 1,
        minimumPixelSize: 0.1,
        scale: 1, //放大倍数
        // 当距离小于300米时,模型的缩放比例为1,当距离大于1200米时,缩放比例为0.4
        scaleByDistance: new Cesium.NearFarScalar(300, 1, 1200, 0.5), //设置随图缩放距离和比例
        distanceDisplayCondition: new Cesium.DistanceDisplayCondition(0, 10000), //设置可见距离 10000米可见
        // color: new Cesium.Color(1, 1, 1, .5)
      },
      // 旋转模型
      orientation: Cesium.Transforms.headingPitchRollQuaternion(
        position,
        new Cesium.HeadingPitchRoll(
          Cesium.Math.toRadians(-66),  // 设置这个属性即可(顺时针旋转的角度值)
          Cesium.Math.toRadians(0),
          Cesium.Math.toRadians(0)
        )
      ),
    });
    viewer.entities.add(entity)
  });

}

// 点击“预约车位内的按钮”, 实现全局路径规划
function getautoDrive() {
  // 创建 Polyline 坐标数组
  const positions = JSON.parse(localStorage.getItem('requestData'));
  if (positions === null) {
    return;
  }
  // 转成Cesium里的Cartesian3坐标
  const cartesianPositions = positions.map(pos => {
    return Cesium.Cartesian3.fromDegrees(pos.pos_lon, pos.pos_lat);
  });
  // 创建几何实例
  const polylineGeometry = new Cesium.PolylineGeometry({
    positions: cartesianPositions,
    width: 5,
    vertexFormat: Cesium.PolylineColorAppearance.VERTEX_FORMAT,
  });
  // 创建GeometryInstance,将几何实例赋值给geometry
  const geometryInstance = new Cesium.GeometryInstance({
    geometry: polylineGeometry,
    attributes: {
      color: Cesium.ColorGeometryInstanceAttribute.fromColor(Cesium.Color.GREEN)
    },
  });
  // 加载primitive,通过geometryInstances可以将多个PolygonGeometry一次性加载出来
  const polylinePrimitive = new Cesium.Primitive({
    geometryInstances: geometryInstance,
    appearance: new Cesium.PolylineColorAppearance(),
    compressVertices: true
  });

  viewer.scene.primitives.add(polylinePrimitive);
}

// 在onUnmounted钩子函数中销毁Cesium Viewer
// onUnmounted(() => {
//   // viewer.destroy()
// })
</script>

查看更多

关注者
0
被浏览
861
1 个回答
地虎降天龙
地虎降天龙 图形社区官方人员 2023-08-24
也许宇宙中最反直觉的真理是,你给别人的越多,你得到的也越多。

不好意思,不清楚你是想用cesium 还是想用mapv

撰写答案

请登录后再发布答案,点击登录

发布
问题

分享
好友

手机
浏览

扫码手机浏览