翻译 Cesium入门教程(二)------图层 Imagery Layers

和自甴很熟 提交于 2020-04-14 03:09:51

【今日推荐】:为什么一到面试就懵逼!>>>

转载请注明出处 http://my.oschina.net/u/149294/blog/202464


本人建了一个QQ群:115883691,欢迎大家一起来讨论Cesium相关技术

Cesium支持通过许多标准的服务,渲染和以图层的方式组织高分辨率的地图,图层可以是有序的并且可以融合(blend)在一起。每个图层的亮度、对比度、伽马值、色调以及饱和度都能动态的更改。本教程将介绍一个图层方面的概念和相关的Cesium APIs。

开搞

我们先暂时忽略掉一些细节,直接开始写几句代码来添加一些图层。首先打开Sandcastle中得HelloWorld。这个例子创建了一个CesiumWidget,它包含了一个渲染Bing maps的单一图层。通过个CesiumWidget的构造函数传递一个附加参数,我们可以另外定义一个底图图层。我们使用Esri ArcGIS MapServer的数据作为底图。

var widget = new Cesium.CesiumWidget('cesiumContainer', {
    imageryProvider : new Cesium.ArcGisMapServerImageryProvider({
        url : 'http://server.arcgisonline.com/ArcGIS/rest/services/World_Street_Map/MapServer',        proxy : new Cesium.DefaultProxy('/proxy/')
})});

修改完以后,按F8来运行。

现在我们可以对它进行放大缩小,数据是根据当前需要进行载入的。由于Esri的服务不支持跨域资源共享,所以我们提供了一个代理(其实它的代理被墙了,所以也访问不了)。

接下来,使用Tile Map Service(TMS)再添加一个NASA Black Marble的图层。

var blackMarble = layers.addImageryProvider(new Cesium.TileMapServiceImageryProvider({
    url : 'http://cesiumjs.org/blackmarble',    maximumLevel : 8,
    credit : 'Black Marble imagery courtesy NASA Earth Observatory'
}));

由于它是最后添加的并且覆盖整个地球,所以Black Marble覆盖了Esri的图层。当然我们可以通过layers.lower(blackMarble);将它移到Esri的下面,但是跟清晰的展示图层一件的联系,我们最好是将它与Esri图层进行一个混合。

blackMarble.alpha = 0.5; // 0.0 is transparent.  1.0 is opaque.

接下来我们增加blackMarble的亮度。

blackMarble.brightness = 2.0; // > 1.0 increases brightness.  < 1.0 decreases.

最后,我们添加第三个图层,在一个特定的范围内渲染一张图片。

layers.addImageryProvider(new Cesium.SingleTileImageryProvider({
    url : '../images/Cesium_Logo_overlay.png',
    extent : new Cesium.Extent(
        Cesium.Math.toRadians(-75.0),
        Cesium.Math.toRadians(28.0),
        Cesium.Math.toRadians(-67.0),
        Cesium.Math.toRadians(29.75))
}));

最终的完整代码如下:

var widget = new Cesium.CesiumWidget('cesiumContainer', {
    imageryProvider : new Cesium.ArcGisMapServerImageryProvider({
        url : 'http://server.arcgisonline.com/ArcGIS/rest/services/World_Street_Map/MapServer',        proxy : new Cesium.DefaultProxy('/proxy/')
})});

var layers = widget.centralBody.getImageryLayers();
var blackMarble = layers.addImageryProvider(new Cesium.TileMapServiceImageryProvider({
    url : 'http://cesiumjs.org/blackmarble',    
    maximumLevel : 8,
    credit : 'Black Marble imagery courtesy NASA Earth Observatory'
}));

blackMarble.alpha = 0.5;
blackMarble.brightness = 2.0;

layers.addImageryProvider(new Cesium.SingleTileImageryProvider({
    url : '../images/Cesium_Logo_overlay.png',
    extent : new Cesium.Extent(
        Cesium.Math.toRadians(-75.0),
        Cesium.Math.toRadians(28.0),
        Cesium.Math.toRadians(-67.0),
        Cesium.Math.toRadians(29.75))
}));

可以在Sandcastle中查看完整的例子。

接下来,我将详细的探讨有关图层的重要功能。首先是imagery providers,它支持许多获取地图数据的标准协议。

转载请注明出处 http://my.oschina.net/u/149294/blog/202464

Imagery providers

像前面用到的两个高分辨率的地图数据,对于我们电脑的内存甚至单一的硬盘来讲都太大了。所以我们把它分割成许多小的图片,或者叫瓦片(tiles),这样我们就可以根据视图所在位置动态的按需载入。对于使用imagery providers请求瓦片数据,Cesium支持非常多的标准,多数是使用REST风格的接口通过HTTP来请求瓦片。不同的Imagery provider的区别在于请求的格式和瓦片的组织方式。Cesium支持一下几种imagery provider:

  • Web Map Service(WMS) - 一个向分布式地理空间数据库请求瓦片数据的OGC标准。在Cesium中参见,WebMapServiceImageryProvider。

  • Tile Map Service(TMS) - 访问地图瓦片的REST风格接口。瓦片可以使用MapTiler或者GDAL2Tiles生成。在Cesium中参见,TileMapServiceImageryProvider。

  • OpenStreetMap - 访问OpenStreetMap地图瓦片或者其他Slippy map tiles。有多种方式来host there tiles。参见OpenStreetMapImageryProvider。

  • Bing Maps - Uses Bing Maps REST Services to access tiles.参见BingMapsImageryProvider.

  • Esri ArcGIS MapServer - 通过ArcGIS Server REST API 来访问托管在 ArcGIS MapServer上的瓦片。参见ArcGIsMapServerImageryProvider。

  • Google Earth Enterprise - 提供对托管在Google Earth企业服务器上的数据的访问。参见GoogleEarthImageryProvider。

  • Standard image files - 通过一张单一图片来创建瓦片。参见SingleTileImageryProvider。

  • Tile coordinates - 通过特殊的瓦片来展示地球是怎样被划分成一个一个的瓦片的。

通过实现ImageryProvider接口,我们也可以实现对其他地图服务的访问。假如你这样做过,希望你能将你的代码贡献给Cesium,这样大家都能从中获益。

关于怎样创建一个自定义的imagery provider请参见文档。我们来看看SingleTileImageryProvider的构造函数参数,其他的跟他是一样的。

  • url - 图片的url。和其他Imagery Provider一样,这个参数是必须的。在其他Imagery Provider中这个地址通常指向服务器或者服务的根目录。

  • extent - 可选参数,以经纬度来定义的图片的覆盖范围。默认是整个地球。

  • credit - 可选参数,数据的版权说明,显示在画布的左下角,有的provider像BingMapsImageryProvider和Arcgis server REST API还会有一个logo或者指向服务的字符串。

  • proxy - 可选参数,代理,用来解决资源跨域共享的问题。

资源跨域共享

作为一种安全机制,当今的浏览器通常蛋疼的阻止javascript读取那些来自其他网站的图片数据。特别是Cesium这样的WebGL程序,禁止使用那些来自不同主机或端口并且服务器没有显示声明可以那么用的图片(在本例中是瓦片数据)来作为纹理。服务器可以通过在HTTP响应中包含Cross Origin Resource Sharing(CORS)头,来表明图像数据不包含机密数据,并且可以安全的被其他网站读取。

不幸的是,并不是所有的地图服务都支持CORS。对于那些不支持的,那就必须在托管Cesium程度网站上添加一个代理。使用代理以后,这些瓦片数据对于浏览器和Cesium程序来说就像他们本来就是同源的一样了。要使用代理,可以在imagery provider的构造的时候,使用proxy属性即可。Cesium包含有一个java写的简单的代理,最好不要用于生产环境下,就像前面看到的:

layers.addImageryProvider(new Cesium.ArcGisMapServerImageryProvider({
    url : 'http://server.arcgisonline.com/ArcGIS/rest/services/World_Street_Map/MapServer',        proxy : new Cesium.DefaultProxy('/proxy/')
}));

假如你正想托管你的地图数据,我们建议你使用这里的方式,而不是使用代理。

Imagery providers(数据源) vs layers(图层)

到目前为止,我们还没有解释imager providers 和图层(layers)之间的不同。imagers providers负责从一个指定的服务地址请求瓦片数据,而layers负责组织和显示这些瓦片。代码如下:

var layer = layers.addImageryProvider(imageryProvider);

分解开就是

var layer = new ImageryLayer(imageryProvider);
layers.add(layer);

我们通常先构建一个imagery provider,再用它来构建一个图层,然后我们就可以通过图层提供的一些属性(像show,alpha,brightness,contrast)来改变地图的外观了。参见ImageryLayer。对imagery provider和layers进行解耦,可以让我们更方便的创建新的数据源。

一个图层的集合,如上面提到的layers,决定了图层被渲染的顺序。图层是以他们被添加的先后,从下到上的顺序被渲染的。对于这个集合,你可以像操作其他集合一样操作它,调用add,remove以及get这些函数。另外你还可以使用raise,raiseToTop,lower或者lowerToBottom来改变图层的顺序。

其他资源

没事多看看Sandcastle中关于图层的例子

另外可以看看文档

All imagery providers

ImageryLayer

ImageryLayerCollection

再不行,去论坛请教大神,附上地址


易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!