Cesium三维地图入门教程

Posted 知心宝贝

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Cesium三维地图入门教程相关的知识,希望对你有一定的参考价值。


Cesium三维地图入门教程


一、前言

Cesium是一个用于显示三维地球的开源库,旨在释放3D数据的力量。Cesium基于WebGL技术,能够在Web平台搭建虚拟地球及场景展示应用。

项目目录

  • libs存放一些依赖文件
  • stage_0阶段的html页面代码
  • stage_1阶段的html页面代码
  • token官网的token,记得替换成你的

源码开源地址Cesium三维地图入门教程

二、环境搭建

初始化后的界面及各个控件的名称如图:

// 引入token,装入容器
Cesium.Ion.defaultAccessToken='xxx'
const viewer=new Cesium.Viewer('cesium-container')

cesium主要分为下面四个核心类,后续详细介绍:

  • viewer:场景的总管理者
  • scene:加载场景的物体,所有3D图形对象的容器
  • entity:由Primitive封装而来,主要加载实体模型几何模型
  • dataSourceCollection:加载矢量数据

三、坐标系及转化

3.1 wgs84坐标系


WGS-84坐标系 [1] 的几何意义是:坐标系的原点位于地球质心,z轴指向(国际时间局)BIH1984.0定义的协议地球极(CTP)方向,x轴指向BIH1984.0的零度子午面和CTP赤道的交点,y轴通过右手规则确定。

3.2 wgs84弧度计算

一般cesium使用这个计算坐标,把经纬度转变为弧度计算

  • 根据弧度创建实例:Cesium.Cartographic.fromRadians(longitude, latitude, height, result)
  • 经纬度=>弧度:Cesium.Cartographic.fromDegrees(longitude, latitude, height, result)

3.3 笛卡尔空间直角坐标系


笛卡尔空间直角坐标系:以地球中心作为原点计算坐标

3.4 平面坐标系


对于cesium来说通常用第一种坐标系

四、视图与场景

4.1 Viewer

在Cesium中Viewer是一切的开端,通过**new Cesium.Viewer(container, options)**来创建一个Viewer对象,可以把该对象理解为三维虚拟地球,在Viewer对象上的所有操作,可以看作是对三维虚拟地球的操作。
日常Cesium开发中,几乎都是围绕着这个对象展开的。

4.2 Scene

Scene为Cesium视图下的3D图形对象和状态的容器,Scene对象并不是显式创建的,而是由Viewer或CesiumWidget初始化视图时隐式创建的,通过Scene对象可以在视图下添加图形(primitive)、添加场景特效(如后处理特效postProcessStage)、添加场景事件或控制视图下的星空skyBox、大气层skyAtmosphere、地球globe、太阳sun和月亮moon。

4.3 Camera

在Cesium通过相机来操作场景的视角,从浏览器端看是场景移动,其实是相机移动,所以要注意方向。
例如:相机向左移,那么屏幕的场景就会偏右

我们通常可以使用相机的变换完成视角操作:

  • 飞行fly
  • 缩放zoom
  • 移动move
  • 视角look
  • 平面扭转twist
  • 3d旋转rotate
  • 将相机视角直接定位到某个位置setView
  • 用于将相机视角锁定到目标位置lookAt
  • 将地球或场景缩放到该实体的视图范围内viewer.zoomTo()

五、界面操作

5.1 视图控件隐藏

const viewer = new Cesium.Viewer('cesium-container',
  timeline:false,
  fullscreenButton: false // 隐藏全屏按钮
) 


// 隐藏版权信息
viewer._cesiumWidget._creditContainer.style.display = "none"

隐藏视图控件可以在创建视图的时候隐藏,如果一开始想要最简化的场景,可以使用下面的代码:

// 除了场景,其他控件都被隐藏
const viewer = new Cesium.CesiumWidget("cesiumContainer")

5.2 场景操作

// 场景操作
        // 显示帧率
        viewer.scene.debugShowFramesPerSecond=true
        viewer.scene.skyBox.show=false
        viewer.scene.sun.show = false  // 隐藏太阳

场景就是包含一些物体,可以通过上述的方法隐藏

六、影像和标注

6.1 影像

概述:所谓的影像就是附着在地球上面的一层贴图,有不同的供应商、创建方式、管理方式,可以叠加。
加载方式

// 引入token,装入容器
Cesium.Ion.defaultAccessToken = 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJqdGkiOiI0NmY4OGRkZS03ZTljLTQ5MDMtYmUwZC0wNmM2ZjdmM2M1MzMiLCJpZCI6MTI2MjUzLCJpYXQiOjE2NzczMTI2ODJ9.KO5KCez-xGcJBJfY8XYWAlUXHO4WWrZUm6tCZ1MfCWM'

// 1初始化添加图层,为空默认加载bingmaps
const viewer = new Cesium.Viewer('cesium-container',
    // imageryProvider:new Cesium.ArcGisMapServerImageryProvider(
    //     url: 'https://services.arcgisonline.com/ArcGIS/rest/services/World_Imagery/MapServer'
    // )
) 
// 隐藏版权信息
viewer._cesiumWidget._creditContainer.style.display = "none"

//2 后续添加
const  arcGisImagery=new Cesium.ArcGisMapServerImageryProvider(
    url: 'https://services.arcgisonline.com/ArcGIS/rest/services/World_Imagery/MapServer'
)
// viewer.imageryLayers.addImageryProvider(arcGisImagery)


//3更具ionCesium的资源库id添加,需要提前加好资源
const ionNightEarth=new Cesium.IonImageryProvider(assetId:3812)
viewer.imageryLayers.addImageryProvider(ionNightEarth)

管理方式

// 引入token,装入容器
Cesium.Ion.defaultAccessToken = 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJqdGkiOiI0NmY4OGRkZS03ZTljLTQ5MDMtYmUwZC0wNmM2ZjdmM2M1MzMiLCJpZCI6MTI2MjUzLCJpYXQiOjE2NzczMTI2ODJ9.KO5KCez-xGcJBJfY8XYWAlUXHO4WWrZUm6tCZ1MfCWM'

// 1初始化添加图层
const viewer = new Cesium.Viewer('cesium-container', 
    imageryProvider: new Cesium.ArcGisMapServerImageryProvider(
        url: 'https://services.arcgisonline.com/ArcGIS/rest/services/World_Imagery/MapServer'
    )
)
// 隐藏版权信息
viewer._cesiumWidget._creditContainer.style.display = "none"

//2 后续添加
const arcGisImageryLoad = new Cesium.ArcGisMapServerImageryProvider(
    url: 'https://services.arcgisonline.com/ArcGIS/rest/services/World_Imagery/MapServer'
)
const arcGisImagery = viewer.imageryLayers.addImageryProvider(arcGisImageryLoad)


//3更具ionCesium的资源库id添加,需要提前加好资源
const ionNightEarthLoad= new Cesium.IonImageryProvider( assetId: 3812 )
const ionNightEarth = viewer.imageryLayers.addImageryProvider(ionNightEarthLoad)

const target = viewer.imageryLayers._layers[1]
target.alpha = 0.5
target.brightness = 2.0
target.contrast = 1.0
// target.hue = 2.0
target.saturation = 1.0
target.gamma=1.0

// ImageryLayerCollection父类,资源导入无法识别,只有viewer.imageryLayers.addImageryProvider才行
const isContains=viewer.imageryLayers.contains(ionNightEarth)
console.log('是否包含',isContains);

const getImagery=viewer.imageryLayers.get(1)
console.log('下标寻找', getImagery);


// 图层移动,lower 1 - 0   raise 0 - 1
viewer.imageryLayers.lowerToBottom(ionNightEarth)


const index = viewer.imageryLayers.indexOf(ionNightEarth)
console.log('下标', index);

6.2 标注

概述:标注也是一层贴图,只不过可以显示具体的位置名称和相关信息

// 引入token,装入容器
Cesium.Ion.defaultAccessToken = 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJqdGkiOiI0NmY4OGRkZS03ZTljLTQ5MDMtYmUwZC0wNmM2ZjdmM2M1MzMiLCJpZCI6MTI2MjUzLCJpYXQiOjE2NzczMTI2ODJ9.KO5KCez-xGcJBJfY8XYWAlUXHO4WWrZUm6tCZ1MfCWM'


// 1初始化添加图层
const viewer = new Cesium.Viewer('cesium-container', 
  imageryProvider: new Cesium.ArcGisMapServerImageryProvider(
    url: 'https://services.arcgisonline.com/ArcGIS/rest/services/World_Imagery/MapServer'
  )
)
// 隐藏版权信息
viewer._cesiumWidget._creditContainer.style.display = "none"


//  1 高德地图标注
const guadMapLoad=new Cesium.UrlTemplateImageryProvider(
  url: "http://webst02.is.autonavi.com/appmaptile?x=x&y=y&z=z&lang=zh_cn&size=1&scale=1&style=8"
)
// viewer.imageryLayers.addImageryProvider(guadMapLoad)


//  2 天地图标注
const token= 'xxx'
const webMapTileLoad=new Cesium.WebMapTileServiceImageryProvider(
  url: `http://t0.tianditu.com/cva_w/wmts?service=wmts&request=GetTile&version=1.0.0&LAYER=cva&tileMatrixSet=w&TileMatrix=TileMatrix&TileRow=TileRow&TileCol=TileCol&style=default&format=tiles&tk=$token`,
  layer: "tdtAnnoLayer",
  style: "default",
  format: "image/jpeg",
  tileMatrixSetID: "GoogleMapsCompatible",
  show: false
)
viewer.imageryLayers.addImageryProvider(webMapTileLoad)

七、地形

Cesium默认加载的地形是没有起伏效果的,和影像加载方式一致。
外部加载

// 引入token,装入容器
Cesium.Ion.defaultAccessToken = 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJqdGkiOiI0NmY4OGRkZS03ZTljLTQ5MDMtYmUwZC0wNmM2ZjdmM2M1MzMiLCJpZCI6MTI2MjUzLCJpYXQiOjE2NzczMTI2ODJ9.KO5KCez-xGcJBJfY8XYWAlUXHO4WWrZUm6tCZ1MfCWM'

// 一个视图下地形只能加载一个,而影像图层是可以加载多个的
// 1初始化添加地形
const viewer = new Cesium.Viewer('cesium-container', 
        imageryProvider: new Cesium.ArcGisMapServerImageryProvider(
        url: 'https://services.arcgisonline.com/ArcGIS/rest/services/World_Imagery/MapServer'
    ),
    terrainProvider: new Cesium.ArcGISTiledElevationTerrainProvider(
        url: 'https://elevation3d.arcgis.com/arcgis/rest/services/WorldElevation3D/Terrain3D/ImageServer',
    )
)
// 隐藏版权信息
viewer._cesiumWidget._creditContainer.style.display = "none"

// 2后期添加地形
const ArcGisTerrainProvider = new Cesium.ArcGISTiledElevationTerrainProvider(
        url: 'https://elevation3d.arcgis.com/arcgis/rest/services/WorldElevation3D/Terrain3D/ImageServer',
)
viewer.terrainProvider = ArcGisTerrainProvider

Cesium ion 地形

const terrainProvider = Cesium.createWorldTerrain(
        requestWaterMask: true, // 请求水体效果所需要的海岸线数据
)
viewer.terrainProvider = terrainProvider

八、事件

Cesium中的事件按照类型进行分类,可以分为如下几种:

  • 鼠标键盘事件
  • 相机事件
  • 数据加载事件
  • 场景加载事件

九、实体

实体(entity)是Cesium中自带的创建图形的方法,通过该方法可以在场景中创建点、线、面、多边形、立方体、圆等基本图形,相当于three.js的物体。

const target= Cesium.Cartesian3.fromDegrees(118, 34, 0)
const boxEntity=viewer.entities.add(
    id:'123',
    name:'box-entity',
    position:target,
    box:
        dimensions:new Cesium.Cartesian3(100,100,100),
        distanceDisplayCondition:new Cesium.DistanceDisplayCondition(0,10000),
        material:Cesium.Color.RED.withAlpha(0.5),
        fill:true,
        outline:true,
        outlineWidth:110,
        outlineColor:Cesium.Color.PINK,
        show:true
    
)

十、图形

图形(Primitive)是Cesium中更加高阶的创建图形的方法,那么相对低阶的方法就是使用实体(Entity)定义一个图形。当创建一个图形时,两者的流程都是定义实体的尺寸大小和定义实体的材质外观。图形(Primitive)由两部分组成:

  1. 几何形状(Geometry):定义了Primitive的结构,例如三角形、线条、点等;
  2. 外观(Appearance ):定义Primitive的着色(Sharding),包括GLSL(OpenGL着色语言,OpenGL Shading Language)顶点着色器和片段着色器( vertex and fragment shaders),以及渲染状态(render state)。

十一、模型

11.1 gltf

图像库传输格式(Graphic Library Transmission Format, glTF)本质上是一种JSON文件,该文件描述包含以下内容的场景的结构和组成3D模型。

//目标位置与视角方向
const target=Cesium.Cartesian3.fromDegrees(118,34,100)
// 加载物体
const plane=viewer.entities.add(
    name:'flyingPlane',
    position:target,
    
    model:
        uri:'../libs/Assets/models/CesiumDrone.glb',
        minimumPixelSize: 128,
        maximumScale: 20000,
    

)

11.2 3dTitles

3dTiles三维模型使用了 glTF 规范,继承它的渲染高性能,除了嵌入的 glTF,3dTiles 自己 只记录各级Tile的空间逻辑关系(如何构成整个3dtiles)和属性信息,以及模型与属性如何挂接在一起的信息

//目标位置与视角方向
const tileset= viewer.scene.primitives.add(
    new Cesium.Cesium3DTileset(
        url: '../libs/Assets/3dTitles/tilesset/tileset.json',
    )
)

// 开始调整tileset位置和缩放大小
let params=
    // 模型中心经纬度和高度
    tx:118,
    ty:34,
    tz:0,

    // 模型旋转方向
    rx:0,
    ry:0,
    rz:0,

    // 缩放
    scale:0.5


// 显示3dtiles包围盒
tileset.debugShowContentBoundingVolume=true

// 开启 3D Tiles 监视器
// viewer.extend(Cesium.viewerCesium3DTilesInspectorMixin)

// 修改 3D Tiles 的颜色和透明度
// tileset.style = new Cesium.Cesium3DTileStyle(
//     color: "color('rgba(178, 34, 34, 0.5)')", // 淡红色,透明度为0.5,半透明
// )

// 点击修改3dtiles颜色,使用坐标拾取
const handler=new Cesium.ScreenSpaceEventHandler(viewer.scene.canvas)

handler.setInputAction((target)=>

    // 判断点击的元素
    const feature=viewer.scene.pick(target.position)
    if(feature instanceof Cesium.Cesium3DTileFeature)
        feature.color=Cesium.Color.RED
    
    // console.log(feature.getProperty('Longitude'));
    console.log(target.position);
,Cesium.ScreenSpaceEventType.LEFT_CLICK)

// 后续修改模型
// 修改高度值大于50的3D Tiles的颜色和透明度
tileset.style = new Cesium.Cesium3DTileStyle(
    color: 
        // 条件筛选
        conditions: [
            ["$Height > 50", "color('rgba(100,100,100, 0.5)')"],
        ]
    ,
    show:'$Height > 12'
)

资料:

openlayers和cesium实现地图二三维切换

本文介绍如何在普通2d的gis项目里实现地图的二、三维切换。二维地图引擎市面上比较多,比较有代表性的像openlayers、leaflet等。三维地图目前比较流行的开源方案有cesium,它本身是基于webGL实现的地图引擎。

cesium在vue上实现需要很多步骤,我之前写过一篇总结,是基于vuecli2.0实现的。按步骤一步步实现,问题不大。如果你是用vuecli3搭建的项目,这里有篇文章介绍用vuecli3实现引用cesium。如果要实现二三维地图切换,难点是地图引擎的转换,有个插件已经帮忙实现了这个工作:ol-cesium。

 

场景需求

好了,我来捋捋场景,搞清楚需求:

1、openlayers加载地图

2、cesium加载三维地图

3、实现二、三维地图切换

4、在vue框架上实现以上功能

实现步骤

一、用openlayers加载地图

此处略过,虽然简单,但是对于没有接触过gis的前端同学还是有入门门槛的。那既然是要实现以上需求,应该就是要做gis项目的人。既然是做gis项目的,那这个ol加载地图就不应该是难点,官网有很多示例,所以此处略过。

还是给一个示例代码:

<template>
<div id = "map">

</div>
</template>
<script>
import \'ol/ol.css\';
import Map from \'ol/Map\';
import OSM from \'ol/source/OSM\';
import TileLayer from \'ol/layer/Tile\';
import View from \'ol/View\';

var olmap = new Map({
layers: [
new TileLayer({
source: new OSM(),
}) ],
target: \'map\',
view: new View({
center: [0, 0],
zoom: 2,
}),
});
</script>

二、用cesium加载三维地图

cesium加载三维地图对于gis行业的同学来说也是个麻烦事,更别说要在vue框架上实现了。

以vuecli3为例,引用cesium其实只用几步:

安装vue-cli-plugin-cesium插件
// npm
npm install--save-dev vue-cli-plugin-cesium

// yarn
yarn add vue-cli-plugin-cesium
直接在vue组件中使用

安装好了就可以直接new出来用,因为它已经绑定了vue实例;

<template>
<div id= "cesiumContainer">
</div>
</template>
<script>
export default {
name: "",
mounted(){
var viewer = new Cesium.Viewer("cesiumContainer")
}
}
</script>

三、实现二、三维地图切换

安装olcs插件

这是一个用于实现openlayers与cesium切换的插件,详细文档移步官网

npmi --save olcs
实现二、三维切换
import OLCesium from \'olcs/OLCesium.js\';
const ol3d = new OLCesium({map: ol2dMap}); // ol2dMap 是openlayers绑定的地图对象
ol3d.setEnabled(true);

需要注意的就是上面代码中的ol2dMap是openlayers绑定的地图对象,这个业内同学都懂。结合前面的ol示例,就是那个olmap对象。

四、注意要点

如果有这样的需求:本来是二维地图有个矢量地图,比如一个什么专题图;然后切换到了三维地图,我仍然要能在三维地图上看到那个专题图。

现在切换到三维后,效果是有了,平面变三维地球,问题是之前的那个专题图也看不见了!原因就是切换到三维后,二维地图被覆盖了。 解决办法就是,切换到三维后,再用cesium引擎加载平面专题图;

cesium加载平面地图
var ol3dLayers = ol3d.getCesiumScene().imageryLayers;
        // eslint-disable-next-line no-undef
        ol3dLayers.addImageryProvider(new Cesium.ArcGisMapServerImageryProvider({
          url: \'http://**************/arcgis/rest/services/**/******/MapServer\'
        }))

上面的示例地图是一个aricgis动态服务;

最后上图,来看下效果:

参考资料:

https://blog.csdn.net/u010001043/article/details/74279380

https://cesium.com/docs/cesiumjs-ref-doc/ArcGisMapServerImageryProvider.html

https://mp.weixin.qq.com/s/3Of_xKhUOxiwFhJoZ0U-Mg

 

本文分享自微信公众号 - 字节逆旅(wvivw_007)。
如有侵权,请联系 support@oschina.cn 删除。
本文参与“OSC源创计划”,欢迎正在阅读的你也加入,一起分享。

以上是关于Cesium三维地图入门教程的主要内容,如果未能解决你的问题,请参考以下文章

用three.js开发三维地图实例

cesium是啥

Cesium专栏-百度地图加载(附源码下载)

Cesium官方教程5--地形图层

cesium 卫星扫过哪里显示地球上的图片一部分

openlayers和cesium实现地图二三维切换