Welcome to my blog.|

Khru

园龄:2年11个月粉丝:22关注:1

2025-01-15 16:33阅读: 73评论: 0推荐: 0

Cesium-基础入门

Cesium 数据

影像数据:Bing、天地图、ArcGIS、OSM、WMTS、WMS等

地形数据:ArcGIS、谷歌、STK等

矢量数据:KML、KMZ、GeoJSON、TopoJSON、CZML

三维模型:GLTF、GLB(二进制glTF文件)

三维瓦片:3D Tiles(倾斜摄影、人工模型、 三维建筑物、CAD、BIM,点云数据等)

Cesium 坐标系统

  • WGS84弧度坐标系(Cartographic)
    弧度= π/180×经纬度角度

  • 笛卡尔空间直角坐标系(Cartesian3)

    平面坐标系(Cartesian2)

    4D笛卡尔坐标系(Cartesian4)

项目初始化

  1. vite一个项目

  2. npm i cesium@1.99 vite-plugin-cesium

  3. 配置插件

    import cesium from 'vite-plugin-cesium'
    export default defineConfig({
    plugins: [
    vue(),
    vueDevTools(),
    cesium(),
    ],
  4. app.vue中引入Cesium

    import * as Cesium from 'cesium'
    console.log(Cesium)
  5. 一个页面

    <template>
    <div id="cesiumContainer"></div>
    </template>
    <script setup>
    import { onMounted } from 'vue'
    import * as Cesium from 'cesium'
    onMounted(() => {
    // 使用Cesium的Ion服务进行认证
    Cesium.Ion.defaultAccessToken = '';
    // 创建一个Viewer实例
    const viewer = new Cesium.Viewer('cesiumContainer', {
    // 使用默认的影像图层和地形图层
    terrainProvider: Cesium.createWorldTerrain({ requestWaterMask: true })
    })
    })
    </script>
    <style scoped>
    #cesiumContainer {
    width: 100vw;
    height: 100vh;
    overflow: hidden;
    }
    </style>

Viewer基础操作

  • 地图加载与初始化
    通过创建一个Viewer对象来完成。这个对象包含了场景(scene)、相机(camera)和其他一些默认的控件。

    const viewer = new Cesium.Viewer('cesiumContainer', {
    terrainProvider: Cesium.createWorldTerrain({
    requestWaterMask: true,
    requestVertexNormals: true,
    }),
    })
  • 相机控制
    实现动态地图查看的关键部分

    1. setView方法

      立即将相机定位到指定的位置,没有动画过渡

      const position = Cesium.Cartesian3.fromDegrees(116.40, 39.90, 1000);
      viewer.camera.setView({
      destination: position,
      orientation: {
      heading: Cesium.Math.toRadians(0),
      pitch: Cesium.Math.toRadians(-90),
      roll: Cesium.Math.toRadians(0),
      },
      });
    2. flyTo方法
      让相机平滑地飞向指定位置,提供了动画效果

      viewer.camera.flyTo({
      destination: Cesium.Cartesian3.fromDegrees(120.0, 30.0, 2000000),
      duration: 3.0,
      orientation: {
      heading: Cesium.Math.toRadians(20),
      pitch: Cesium.Math.toRadians(-15),
      roll: 0.0,
      },
      });
    3. lookAt方法
      将相机指向一个特定的目标点,而不会改变当前的相机位置

      const target = Cesium.Cartesian3.fromDegrees(120.0, 30.0);
      viewer.camera.lookAt(target, new Cesium.HeadingPitchRange(0, -
      Cesium.Math.PI_OVER_TWO, 5000000));
  • 坐标转换

    1. 经纬度转笛卡尔

      const cartesian3 = Cesium.Cartesian3.fromDegrees(114.0, 30.0, 500000);
    2. 笛卡尔转经纬度

      const cartographic = Cesium.Cartographic.fromCartesian(cartesian3);
      const longitude = Cesium.Math.toDegrees(cartographic.longitude);
      const latitude = Cesium.Math.toDegrees(cartographic.latitude);

实体与数据源

  1. 实体(Entity)
    描述具有几何形状和属性的对象的基类

    • 添加实体

      const pointEntity = viewer.entities.add({
      position: Cesium.Cartesian3.fromDegrees(103.1, 25.0),
      point: {
      color: Cesium.Color.YELLOW,
      pixelSize: 10,
      },
      name: 'Sample Point',
      description: 'This is a description for the sample point.'
      });
    • 删除实体

      viewer.entities.remove(pointEntity);
    • 创建动态效果
      定义一个回调函数,这个函数可以在每个帧中被CallbackProperty调用,以动态地更新实体的属性

      // 定义一个回调函数,该函数将根据当前时间返回实体的位置
      function positionCallback(time, result) {
      // 获取当前时间,并转换为JulianDate
      var timestamp = Cesium.JulianDate.toDate(time);
      // 根据时间计算经度,这里假设每秒移动10度
      var longitude = Cesium.Math.toRadians(10 * timestamp.getSeconds());
      // 固定纬度值
      var latitude = Cesium.Math.toRadians(20);
      // 固定高度值
      var height = 100000.0;
      // 返回Cartesian3位置
      if (!Cesium.defined(result)) {
      result = new Cesium.Cartesian3();
      }
      result = Cesium.Cartesian3.fromRadians(longitude, latitude, height);
      return result;
      }
      // 创建一个CallbackProperty,该属性将在每一帧调用positionCallback函数
      var positionProperty = new Cesium.CallbackProperty(positionCallback, false);
      // 添加一个点状实体到Viewer
      var pointEntity = viewer.entities.add({
      name: 'Dynamic point',
      position: positionProperty,
      point: {
      pixelSize: 10,
      color: Cesium.Color.YELLOW
      }
      });
      // 定位到实体
      viewer.zoomTo(viewer.entities);
  2. 数据源(DataSources)
    加载和管理地理数据的组件, 可以处理多种格式的数据

    • 加载GeoJSON数据

      const geoJsonData = {
      "type": "FeatureCollection",
      "features": [
      {
      "type": "Feature",
      "geometry": {
      "type": "Point",
      "coordinates": [-122.39, 47.5]
      }
      }
      ]
      };
      const geoJsonPromise = Cesium.GeoJsonDataSource.load(geoJsonData);
      geoJsonPromise.then(function(dataSource) {
      viewer.dataSources.add(dataSource);
      viewer.zoomTo(dataSource);
      });
    • 加载TopoJSON数据

      const topoJsonPromise = Cesium.GeoJsonDataSource.load('path/to/topojson.data');
      topoJsonPromise.then(function(dataSource) {
      viewer.dataSources.add(dataSource);
      viewer.zoomTo(dataSource);
      });
    • 加载KML数据 (Google Earth)

      const kmlPromise = Cesium.KmlDataSource.load('path/to/placemark.kml');
      kmlPromise.then(function(dataSource) {
      viewer.dataSources.add(dataSource);
      viewer.zoomTo(dataSource);
      });
    • 加载CZML数据
      专为Cesium设计的动态数据格式, 使用JSON数组来描述随时间变化的图形属性

      const czmlPromise = Cesium.CzmlDataSource.load('path/to/document.czml');
      czmlPromise.then(function(dataSource) {
      viewer.dataSources.add(dataSource);
      viewer.trackedEntity = dataSource.entities.getById('ID_of_Entity');
      // 允许相机自动跟踪数据源中的特定实体
      });

图元(Primitive)

一种用于创建和操作三维几何形状的底层API, 面向三维图形开发者, 允许开发者直接控制几何体(Geometry)的创建和外观(Appearance)表现;
Entity API是数据驱动更高级一些

创建基本图元:

  1. 创建一个基本几何体对象(Primitive):
    使用Cesium.Primitive构造函数创建一个新的几何体对象。

  2. 定义几何实例:
    geometryInstances属性接受一个Cesium.GeometryInstance对象,这个对象包含几何体的具体信息。

  3. 创建椭圆形几何体(EllipseGeometry):
    geometry属性是一个Cesium.EllipseGeometry对象,它定义了一个椭圆的几何形状。
    rotation属性定义了椭圆的旋转角度,这里使用了Cesium.Math.PI_OVER_FOUR,表示旋转了45度。
    vertexFormat定义了顶点格式,表示顶点包含位置和纹理坐标。

  4. 定义外观(EllipsoidSurfaceAppearance):
    appearance属性接受一个Cesium.EllipsoidSurfaceAppearance对象,它定义了几何体的外观。
    material属性定义了材质,这里使用了Cesium.Material.fromType方法,并传入了Stripe类型,表示使用条纹材质。

  5. 添加几何体到场景(Viewer):
    使用viewer.scene.primitives.add(primitive)将创建的几何体添加到Cesium Viewer的场景中。

const primitive = new Cesium.Primitive({
geometryInstances: new Cesium.GeometryInstance({
geometry: new Cesium.EllipseGeometry({
center: Cesium.Cartesian3.fromDegrees(-100.0, 20.0),
semiMinorAxis: 500000.0,
semiMajorAxis: 1000000.0,
rotation: Cesium.Math.PI_OVER_FOUR,
vertexFormat: Cesium.VertexFormat.POSITION_AND_ST
}),
}),
appearance: new Cesium.EllipsoidSurfaceAppearance({
material: Cesium.Material.fromType('Stripe'),
}),
})
viewer.scene.primitives.add(primitive);

交互事件

ScreenSpaceEventHandler

  • 点击事件

    let viewer = new Cesium.Viewer('cesiumContainer', {
    terrainProvider: Cesium.createWorldTerrain()
    })
    let handler = new Cesium.ScreenSpaceEventHandler(viewer.scene.canvas)
    handler.setInputAction((event) => {
    // 返回一个笛卡尔坐标
    let position = viewer.scene.pickPosition(event.position)
    // 如果有这个坐标
    if (Cesium.defined(position)) {
    console.log(position)
    viewer.entities.add({
    position: position,
    point: {
    color: Cesium.Color.BLUE,
    pixelSize: 20,
    },
    })
    }
    console.log(viewer.entities)
    }, Cesium.ScreenSpaceEventType.LEFT_CLICK)
  • 移动事件

    let pickModel
    let viewer = new Cesium.Viewer('cesiumContainer', {
    terrainProvider: Cesium.createWorldTerrain()
    })
    // 添加建筑物
    const city = viewer.scene.primitives.add(
    new Cesium.Cesium3DTileset({
    url: Cesium.IonResource.fromAssetId(75343),
    })
    )
    viewer.flyTo(city)
    let handler = new Cesium.ScreenSpaceEventHandler(viewer.scene.canvas);
    handler.setInputAction((event) => {
    // 拾取模型
    const pick = viewer.scene.pick(event.endPosition);
    if (pick) {
    if (pickModel) {
    pickModel.color = Cesium.Color.WHITE;
    }
    pick.color = Cesium.Color.ORANGERED;
    pickModel = pick;
    }
    }, Cesium.ScreenSpaceEventType.MOUSE_MOVE)
  • 事件注销

    handler.removeInputAction(Cesium.ScreenSpaceEventType.LEFT_CLICK); //移除左键点击事件

综合应用

  1. 初始化Cesium Viewer
const viewer = new Cesium.Viewer('cesiumContainer', {
terrainProvider: Cesium.createWorldTerrain(),
baseLayerPicker: false, // 隐藏基础图层选择器
shouldAnimate: true
})
  1. 3D Tiles格式加载三维模型
const cityModel = viewer.scene.primitives.add(new Cesium.Cesium3DTileset({
url: Cesium.IonResource.fromAssetId(123456), // 替换为实际的模型ID
maximumScreenSpaceError: 16
}))
  1. 点击显示建筑物详细信息
viewer.screenSpaceEventHandler.setInputAction((event) => {
const clickPosition = event.position
const pickedObject = viewer.scene.pick(clickPosition)
if (pickedObject && pickedObject instanceof Cesium.Cesium3DTileFeature) {
const buildingInfo = pickedObject.getProperty('name')
showBuildingInfo(buildingInfo) // 显示建筑物信息的自定义函数
}
}, Cesium.ScreenSpaceEventType.LEFT_CLICK)
  1. 创建粒子系统来模拟城市中夜晚的灯光
const particleSystem = new Cesium.ParticleSystem({
image: 'path/to/particle-image.png',
emitter: new Cesium.CircleEmitter({
radius: 10
}),
emissionRate: 1,
lifetime: 60,
loop: true,
modelMatrix: Cesium.Matrix4.multiplyByTranslation({
Cesium.Transforms.eastNorthUpToFixedFrame(
Cesium.Cartesian3.fromDegrees(103.1, 25.0, 1000)
),
new Cesium.Cartesian3(0, 0, 0),
new Cesium.Matrix4()
})
})
viewer.scene.primitives.add(particleSystem)

本文作者:Khru

本文链接:https://www.cnblogs.com/khrushchefox/p/18673343

版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。

posted @   Khru  阅读(73)  评论(0编辑  收藏  举报
点击右上角即可分享
微信分享提示
评论
收藏
关注
推荐
深色
回顶
收起