前端 VUE 框架加载 Cesium 3D 模型(3dtiles)并计算 3dtiles 面积

下面是通过前端 VUE 框架加载 Cesium 3D 模型(3dtiles)并计算 3dtiles 面积的参考代码:

首先在 Vue 组件中引入 Cesium 库和相关组件,需要使用 npm install cesium --save 命令来安装 Cesium 包。然后在组件中开始编写加载 3dtiles 和计算面积的逻辑:

<template>
  <div class="cesium-container">
    <div
      ref="cesiumContainer"
      class="cesium-viewer full"
      id="cesiumContainer"
    ></div>
    <div>模型面积:{{area}}㎡</div>
  </div>
</template>

<script>
import * as Cesium from "cesium/Cesium";
import "cesium/Widgets/widgets.css";

export default {
  name: "CesiumDemo",
  data() {
    return {
      viewer: null,
      modelViewer: null,
      tileset: null,
      area: 0,
    };
  },
  mounted() {
    this.initCesium();
  },
  methods: {
    initCesium() {
      const self = this;
      // 创建地球场景
      const viewer = new Cesium.Viewer("cesiumContainer", {});
      self.viewer = viewer;

      Cesium.Ion.defaultAccessToken =
        "your_token_here"; // 如果需要访问 Cesium Ion 资源则需要填写 token

      // 加载 3dtiles 模型
      let tileset = new Cesium.Cesium3DTileset({
        url: "/static/tileset.json",
      });

      tileset.readyPromise
        .then(function (tileset) {
          self.tileset = tileset;
          viewer.scene.primitives.add(tileset);
        })
        .otherwise(function (error) {
          console.log(error);
          reject();
        });

      // 计算 3dtiles 面积
     viewer.camera.changed.addEventListener(() => {
            let tilesToProcess = [];
            getTilesInitial(delta + cameraHeight, tilesToProcess, self.tileset.root);
      
            for (let i = 0; i < tilesToProcess.length; ++i) {
                calculateTileArea(tilesToProcess[i], projections)
            }
        
            let tempArea = 0;
            for (const obj in projections) {
                tempArea += projections[obj];
            }
            const area = Math.abs(tempArea).toFixed(2); // 保留两位小数
         
            if (self.area !== area && !isNaN(area)) { 
                self.area = area;
            }
      })
    },
  },
};

/**
 * 获取根节点下所有细分瓦片,放入数组中
 * @param {*} currentDelta 当前维度
 * @param {*} tilesToProcess 存储的所有瓦片组成的数组
 * @param {*} currentNode 瓦片对象
 */
function getTilesInitial(currentDelta, tilesToProcess, currentNode) {
    if (!currentNode.content || !currentNode.allTilesLoaded) {
        return;
    }
  
    let refinedTiles = Array.from(currentNode.children);
  
    while (refinedTiles.length > 0) {
        let thisTile = refinedTiles.pop();
        if (thisTile.imageryLayers) {
            thisTile.imageryLayers = undefined;
            thisTile.readyImageryLayersPromise = undefined;
            thisTile.readyPromise = undefined;
        }
        if ((thisTile.refine === Cesium.Cesium3DTileRefine.NONE && !(thisTile instanceof Cesium.Cesium3DTilePointCloud)) ||
            (thisTile.refine === Cesium.Cesium3DTileRefine.ADD || thisTile.refine === Cesium.Cesium3DTileRefine.REPLACE)) {
  
            let distance = currentDelta / thisTile._geometricError;
            let tileDistance = Math.sqrt(Cesium.Cartesian3.magnitudeSquared(thisTile.boundingSphere.center) + thisTile.state.renderedBB) - (Cesium.Ellipsoid.WGS84.maximumRadius * 2.0); 
            // 缩放系数
            const scaleCoefitient = (tileDistance / distance) > 1 ? (tileDistance / distance) : 1;
  
            var boundingBox = new Cesium.BoundingRectangle();
            boundingBox.minimum.x = 0;
            boundingBox.minimum.y = 0;
            boundingBox.maximum.x = 256 / scaleCoefitient;
            boundingBox.maximum.y = 256 / scaleCoefitient;
            tilesToProcess.push({
                "boundingBox": boundingBox,
                "content": thisTile.content
            });
        } else {
            refinedTiles.push.apply(refinedTiles, Array.from(thisTile.children));
        }
    }
}


// 计算瓦片面积
function calculateTileArea(tileInfo, projections) {
    const boxXLength = tileInfo.boundingBox.width;
    const tileHeight = tileInfo.boundingBox.height;
    let arrayBuffer = tileInfo.content.positions;
    tileInfo.content._batchTable.properties.areas.values.length = 0;
  
    while (arrayBuffer && arrayBuffer.length > 0) {
        const positionsLength = readPositionsLength(arrayBuffer);
        if (!positionsLength) {
            break;
        }
  
        const positions = readPositions(arrayBuffer, positionsLength);
        if (!positions) {
            break;
        }
  
        for (let i = 0; i < positionsLength; ++i) {
            positions[i].z += tileHeight;
        }
  
        let area = calculateEllipsoidRegionArea(positions);
  
        // Project a position onto the map and creates a plane in WGS84 normal space.
        const centerPosition = calculateCenterPosition(positions);
        const carto = Cesium.Cartographic.fromCartesian(centerPosition);
        const n = calculateNormal(carto);
        projections[tileInfo.content.url] += area * (boxXLength / 256.0) * Math.sqrt(1 + n.z * n.z);
    }
  }

以上代码仅供参考,具体实现会根据业务需求而有所不同。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Vue3项目中gltf模型Cesium地球,您需要进行以下步骤: 1. 首先,在Vue项目中安装Cesium库。您可以使用 npm 命令来安装它:npm install cesium 2. 打开 Vue 项目的入口文件(比如 main.js),并在顶部导入 Cesium 库。在这之前,确保在项目的 public/index.html 文件中引入了 Cesium 的静态资源,以便正确 Cesium 的依赖。 3. 创建一个 Cesium 的实例,这样您可以在项目中使用它。您可以在 Vue 组件中的 mounted 钩子函数中进行这个步骤。创建一个 div 元素,并为其设置一个唯一的 id 属性,这个 div 元素将用于显示 Cesium 地球。 4. 在 mounted 钩子函数中,使用 Cesium 的 Viewer 类来创建一个地图视图。将要模型的场景地球放入到之前创建的 div 元素中。您可以设置地图视图的一些属性,例如初始视角、瓦片地图的地址等等。 5. 使用 Cesium 的 Entity 类来创建一个实体对象,用于表示要的 gltf 模型。您可以设置模型的位置、方向、缩放等属性。 6. 使用 Cesium 的 Scene 类的方法来 gltf 模型。您可以使用 load 方法来 gltf 文件,然后将其添到场景中。 7. 配置视图的更新循环以确保地球视图不断更新,以呈现 gltf 模型以及其他地球上的实体。 8. 最后,您可以在 Vue 组件的模板中使用之前创建的 div 元素来显示 Cesium 地球。 请注意,上述步骤是一个大致的指南。在实际项目中,您可能需要根据具体需求进行一些调整和配置。此外,还可以利用 VueCesium 提供的其他功能和组件来增强您的项目。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值