Cesium学习记录

503 阅读4分钟

非教学文章,仅用于学习记录。

以前的GIS开发多使用ArcGIS系列,开源GIS有过接触但未深入,现因工作需要,开始深入学习开源三维GIS体系,暂仅记录学习重点和想法(不保证正确性),后续可考虑出系列文章。

学后感(个人暂时见解)

最近因工作需要,学习了Cesium,并基于Cesium开发了一个小型CIM系统;

使用下来的整体感觉是:毕竟还是开源产品,API较为散乱、原始,很多业务上的功能还需要自行封装、扩展,配套体系也不够商业化,如果是希望学习底层,或者基于Cesium做二次封装、扩展形成自己的三维库,是可以的;但如果是商业化开发,做项目设施,需求不是很复杂的情况下,建议还是采用arcgis系列;

如果项目资金不足,可考虑arcgis api 4.x配合开源GIS软件和平台(如pg、geoserver等)进行开发(该方案暂未验证,有机会可以考虑尝试)

Cesium API 常用类及其常用属性和方法整理(进行中)

Cesium API 梳理.png

Cesium 坐标系统

Cesium中常用的坐标有两种WGS84 地理坐标系笛卡尔空间坐标系。其中,WGS84 地理坐标系包括WGS84 经纬度坐标系(没有实际的对象)和WGS84 弧度坐标系(Cartographic),笛卡尔空间坐标系包括笛卡尔空间直角坐标系(Cartesian3)笛卡尔平面坐标系(cartesian2)

WGS84 坐标系

World Geodetic System 1984,是为 GPS 全球定位系统使用而建立的坐标系统,坐标原点为地球质心,其地心空间直角坐标系的 Z 轴指向 BIH (国际时间服务机构)1984.O 定义的协议地球极(CTP)方向,X 轴指向 BIH 1984.0 的零子午面和 CTP 赤道的交点,Y 轴与 Z 轴、X 轴垂直构成右手坐标系。我们平常手机上的指南针显示的经纬度就是这个坐标系下当前的坐标,进度范围[-180,180],纬度范围[-90,90]。 image.png

let cartographic = new Cesium.Cartographic(longitude, latitude, height);
  • WGS84 经纬度坐标系
let cartographic = new Cesium.Cartographic(longitude, latitude, height); //WGS84 弧度坐标系
var lat = Cesium.Math.toDegrees(cartographic.latitude);
var lng = Cesium.Math.toDegrees(cartographic.longitude);
var alt = cartographic.height;
cartographic = { lat: lat, lng: lng, alt: alt }; //WGS84 经纬度坐标系

Cesium.Math.toDegrees

两种坐标的核心区别是啥?从Cesium API的角度来说,WGS84 弧度坐标系的经纬度以弧度(radians)为单位,WGS84 经纬度坐标系的经纬度以度(degrees)为单位。

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

笛卡尔空间坐标的原点就是椭球的中心,我们在计算机上进行绘图时,不方便使用经纬度直接进行绘图,一般会将坐标系转换为笛卡尔坐标系,使用计算机图形学中的知识进行绘图。

image.png

let cartesian3 = new Cesium.Cartesian3(x, y, z);

平面坐标系(Cartesian2)

平面坐标系也就是平面直角坐标系,是一个二维笛卡尔坐标系,与 Cartesian3 相比少了一个 z 的分量。Cartesian2 经常用来描述屏幕坐标系,比如鼠标在电脑屏幕上的点击位置,返回的就是 Cartesian2。

let cartesian2 = new Cesium.Cartesian2(x, y);

Creating Entities 实体

Entity API

  • Primitive API:面向图形开发人员的低级API
  • Entity API:面向数据驱动可视化的高级API

实体类型

MaterialProperty 材质

Heights and extrusions 拉伸

2维转3维

wyoming.polygon.height = 200000;
wyoming.polygon.extrudedHeight = 250000;

viewer 上与实体相关的属性

  • viewer.zoomTo(entity, new Cesium.HeadingPitchRange(heading, pitch));
  • viewer.infoBox.frame
  • viewer.selectedEntity
  • viewer.trackedEntity 追踪实体
  • viewer.entities(EntityCollection)
    • add()、remove()、removeAll()
      • viewer.entities.add(entity);
    • 实体ID
      • var entity = viewer.entities.getById('uniqueId');
      • var entity = viewer.entities.getOrCreateEntity('uniqueId');
    • collectionChanged事件
      • viewer.entities.collectionChanged.addEventListener(onChanged);
    • 挂起和恢复事件
      • viewer.entities.suspendEvents
      • viewer.entities.resumeEvents

pick 拾取

  • viewer.scene.pick
var picked = viewer.scene.pick(windowPosition);
entity = Cesium.defaultValue(picked.id, picked.primitive.id);
  • viewer.scene.drillPick
var pickedPrimitives = viewer.scene.drillPick(windowPosition);

图层

ImageryProvider

Imagery providers vs. layers

var layers = viewer.scene.imageryLayers; // ImageryLayerCollection

var layer = layers.addImageryProvider(imageryProvider);
// 是下方内容的简写
var layer = new Cesium.ImageryLayer(imageryProvider, options)
layers.add(layer);

Visualizing 3D Terrain 地形

默认

var viewer = new Cesium.Viewer('cesiumContainer', {
    terrainProvider : Cesium.createWorldTerrain({
        requestVertexNormals: true; // Lighting 效果
        requestWaterMask: true // 水效果
    })
});

Terrain providers

Camera 相机

// 1
viewer.camera.flyTo({
    destination: Cesium.Cartesian3.fromDegrees(-117.16, 32.71, 15000.0), // 目的地
    orientation: {
        heading: Cesium.Math.toRadians(20.0),
        pitch: Cesium.Math.toRadians(-35.0),
        roll: 0.0,
    }, // 相机方向
    easingFunction: Cesium.EasingFunction.QUADRATIC_IN_OUT, // 缓动函数
    duration: 5 // 持续时间
});

// 2
viewer.flyTo(rectangle); // 可接受Entity, EntityCollection, DataSource, Cesium3DTilset等等

// 3
viewer.scene.screenSpaceCameraController.enableCollisionDetection = false; // 是否允许相机进入地下

Cesium API

Cesium.createWorldTerrain()
Cesium.createWorldImagery()
Cesium.createOsmBuildings()
viewer.camera.flyTo()
viewer.zoomTo(entity, new Cesium.HeadingPitchRange(heading, pitch));
Cesium.Cartesian3.fromDegrees(-104.9965, 39.74248, 4000)
Cesium.Cartesian3.fromDegreesArray([-77, 35, -77.1, 35])



const dataPoint = { longitude: -122.38985, latitude: 37.61864, height: -27.32 };
const pointEntity = viewer.entities.add({
    description: `First data point at (${dataPoint.longitude}, ${dataPoint.latitude})`,
    position: Cesium.Cartesian3.fromDegrees(dataPoint.longitude, dataPoint.latitude, dataPoint.height),
    point: { pixelSize: 10, color: Cesium.Color.RED }
});
viewer.flyTo(pointEntity);


const newBuildingTileset = viewer.scene.primitives.add(
    new Cesium.Cesium3DTileset({
        url: Cesium.IonResource.fromAssetId(your_asset_id)
    })
);

未完待续