非教学文章,仅用于学习记录。
以前的GIS开发多使用ArcGIS系列,开源GIS有过接触但未深入,现因工作需要,开始深入学习开源三维GIS体系,暂仅记录学习重点和想法(不保证正确性),后续可考虑出系列文章。
学后感(个人暂时见解)
最近因工作需要,学习了Cesium,并基于Cesium开发了一个小型CIM系统;
使用下来的整体感觉是:毕竟还是开源产品,API较为散乱、原始,很多业务上的功能还需要自行封装、扩展,配套体系也不够商业化,如果是希望学习底层,或者基于Cesium做二次封装、扩展形成自己的三维库,是可以的;但如果是商业化开发,做项目设施,需求不是很复杂的情况下,建议还是采用arcgis系列;
如果项目资金不足,可考虑arcgis api 4.x配合开源GIS软件和平台(如pg、geoserver等)进行开发(该方案暂未验证,有机会可以考虑尝试)
Cesium API 常用类及其常用属性和方法整理(进行中)
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]。
- WGS84 弧度坐标系(Cesium.Cartographic)
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 API
的角度来说,WGS84 弧度坐标系的经纬度以弧度(radians)为单位,WGS84 经纬度坐标系的经纬度以度(degrees)为单位。
笛卡尔空间直角坐标系(Cartesian3)
笛卡尔空间坐标的原点就是椭球的中心,我们在计算机上进行绘图时,不方便使用经纬度直接进行绘图,一般会将坐标系转换为笛卡尔坐标系,使用计算机图形学中的知识进行绘图。
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
:面向图形开发人员的低级APIEntity API
:面向数据驱动可视化的高级API
实体类型
- Cesium.PointGraphics 点
- Cesium.LabelGraphics 标注
- Cesium.BillboardGraphics 图标点
- Cesium.ModelGraphics:基于glTF的 3D 模型
- entity.box 盒
- entity.ellipse 圆和椭圆
- entity.corridor 走廊
- entity.cylinder 圆柱
- entity.polygon 多边形
- entity.polyline 折线
- entity.polylineVolume 立体折线
- entity.rectangle 矩形
- entity.ellipsoid 球体和椭球
- entity.wall 墙
MaterialProperty 材质
- ColorMaterialProperty 颜色
- CompositeMaterialProperty
- GridMaterialProperty 网格
- ImageMaterialProperty 图片
- PolylineGlowMaterialProperty 折线发光
- PolylineOutlineMaterialProperty 折线轮廓
- StripeMaterialProperty 条纹
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
- add()、remove()、removeAll()
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
- WebMapServiceImageryProvider: Web 地图服务 (WMS)
- TileMapServiceImageryProvider : Tile Map Service (TMS)
- WebMapTileServiceImageryProvider: OpenGIS Web Map Tile Service (WMTS)
- OpenStreetMapImageryProvider
- ArcGisMapServerImageryProvider:使用 Esri ArcGIS Server REST API 访问由 ArcGIS MapServer 托管的切片。
- MapboxImageryProvider:使用 Mapbox API 访问瓦片。创建一个帐户并提供您的 访问令牌。
- SingleTileImageryProvider:从单个图像创建图块。
- UrlTemplateImageryProvider:创建自定义切片方案。使用 URL 模板连接到各种图像源
- TileCoordiantesImageryProvider:在切片方案中围绕每个渲染图块绘制一个框,并在其中绘制一个标签,指示图块的 X、Y、Level 坐标 。这对于调试地形和图像渲染问题非常有用。
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)
})
);
未完待续