商务网站运营与管理,免费制作封面的网站,驾校官方网站 模板,建设银行人才招聘官方网站Cesium在使用加载Cesium.ArcGisMapServerImageryProvider加载切片服务时#xff0c;默认只支持wgs84的4326坐标系#xff0c;不支持CGCS2000的4490坐标系。
如果是ArcGIS发布的4490坐标系的切片服务#xff0c;如果原点在orgin X: -180.0Y: 90.0的情况下#xff0c;我们可…Cesium在使用加载Cesium.ArcGisMapServerImageryProvider加载切片服务时默认只支持wgs84的4326坐标系不支持CGCS2000的4490坐标系。
如果是ArcGIS发布的4490坐标系的切片服务如果原点在orgin X: -180.0Y: 90.0的情况下我们可以通过WebMapTileServiceImageryProvider按照WMTS的方式加载需符合OGC标准的WMTS类型。
但是对于ArcGIS发布4490坐标系的切片服务如果原点在orgin X: -400.0Y: 400.0的情况下我们无法实现加载本文通过示例演示实现Cesium加载ArcGIS Server4490且orgin -400 400的切片服务。
本文使用
Cesium源码版本1.94
另外本文的一些解释需要对切片原理有一定了解想进一步了解的话可以去看看相关文档说明不想了解的话按步骤修改就行了。
为了能够调试源码打包的时候使用命令npm run combine
一、通过修改源码实现ArcGIS的切片服务需要修改的源码文件包括
ArcGisMapServerImageryProviderGeographicTilingScheme Ellipsoid
1、修改ArcGisMapServerImageryProvider类
通过查看ArcGisMapServerImageryProvider\Source\Scene\ArcGisMapServerImageryProvider.js源码我们发现它不支持CGCS2000的4490坐标系仅支持wgs84的4326坐标系 找到metadataSuccess方法进行以下修改
1读取切片元数据时增加支持wkid 4490坐标系的判断同时将切片信息也传入目的是为了后面在获取行列号xy时可以通过读取切片信息使用自定义方法改写行列号的获取方式。 else if (data.tileInfo.spatialReference.wkid 4490) {that._tilingScheme new GeographicTilingScheme({ellipsoid: options.ellipsoid,tileInfo: data.tileInfo,rectangle: that._rectangle,numberOfLevelZeroTilesX: options.numberOfLevelZeroTilesX,numberOfLevelZeroTilesY: options.numberOfLevelZeroTilesY});that._tilingScheme._tileInfo data.tileInfo;//附加自定义属性} 具体位置如图所示 2fullExtent范围增加wkid 4490坐标系判断。 else if (data.fullExtent.spatialReference.wkid 4326 || data.fullExtent.spatialReference.wkid 4490) {that._rectangle Rectangle.fromDegrees(data.fullExtent.xmin,data.fullExtent.ymin,data.fullExtent.xmax,data.fullExtent.ymax);} 代码位置 2、修改GeographicTilingScheme类
GeographicTilingScheme类的位置是\Source\Core\GeographicTilingScheme.js
通过增加4490坐标系的椭球、矩阵范围等定义4490坐标系默认椭球为CGCS2000矩阵范围为-180-9018090开放矩阵范围的目的就是为了支持自定义的origin原点。 if (defined(options.tileInfo) defined(options.tileInfo.spatialReference) defined(options.tileInfo.spatialReference.wkid) options.tileInfo.spatialReference.wkid 4490) {this._tileInfo options.tileInfo;this._ellipsoid defaultValue(options.ellipsoid, Ellipsoid.CGCS2000);this._rectangle defaultValue(options.rectangle, Rectangle.fromDegrees(-180, -90, 180, 90));this._numberOfLevelZeroTilesX defaultValue(options.numberOfLevelZeroTilesX, 4);this._numberOfLevelZeroTilesY defaultValue(options.numberOfLevelZeroTilesY, 2);}else {this._ellipsoid defaultValue(options.ellipsoid, Ellipsoid.WGS84);this._rectangle defaultValue(options.rectangle, Rectangle.MAX_VALUE);this._numberOfLevelZeroTilesX defaultValue(options.numberOfLevelZeroTilesX, 2);this._numberOfLevelZeroTilesY defaultValue(options.numberOfLevelZeroTilesY, 1);}this._projection new GeographicProjection(this._ellipsoid); 代码位置 2修改切片矩阵计算获取行列号数量xy值的原型方法getNumberOfXTilesAtLevel和getNumberOfYTilesAtLeve /*** Gets the total number of tiles in the X direction at a specified level-of-detail.** param {Number} level The level-of-detail.* returns {Number} The number of tiles in the X direction at the given level.*/
GeographicTilingScheme.prototype.getNumberOfXTilesAtLevel function (level) {// return this._numberOfLevelZeroTilesX level;if (!defined(this._tileInfo)) {return this._numberOfLevelZeroTilesX level} else { // 使用切片矩阵计算var currentMatrix this._tileInfo.lods.filter(function (item) {return item.level level})var currentResolution currentMatrix[0].resolution// return Math.round(360 / (this._tileInfo.rows * currentResolution))return Math.round(CesiumMath.toDegrees(CesiumMath.TWO_PI * 2) / (this._tileInfo.rows * currentResolution));}
};/*** Gets the total number of tiles in the Y direction at a specified level-of-detail.** param {Number} level The level-of-detail.* returns {Number} The number of tiles in the Y direction at the given level.*/
GeographicTilingScheme.prototype.getNumberOfYTilesAtLevel function (level) {// return this._numberOfLevelZeroTilesY level;if (!defined(this._tileInfo)) {return this._numberOfLevelZeroTilesY level} else { // 使用切片矩阵计算var currentMatrix this._tileInfo.lods.filter(function (item) {return item.level level})var currentResolution currentMatrix[0].resolution// return Math.round(180 / (this._tileInfo.cols * currentResolution))return Math.round(CesiumMath.toDegrees(CesiumMath.TWO_PI * 2) / (this._tileInfo.cols * currentResolution));}
}; 代码位置 这段代码和参考文章的代码存在一定出入在文末会做详细说明。
3、修改Ellipsoid类定义2000椭球参数
Ellipsoid类位置\Source\Core\Ion.js 定义2000椭球参数 /*** An Ellipsoid instance initialized to the CGCS2000 standard.** type {Ellipsoid}* constant*/
Ellipsoid.CGCS2000 Object.freeze(new Ellipsoid(6378137.0, 6378137.0, 6356752.31414035585)
); 代码位置 二、代码调用
源码修改后为了能够调试源码使用npm run combine打包下代码并在调用地方修改下引用
测试用html页面做测试的页面有一些其他代码可以忽略留意本文需要的代码部分 !DOCTYPE html
html langen
head!-- Use correct character set. --meta charsetutf-8/!-- Tell IE to use the latest, best version. --meta http-equivX-UA-Compatible contentIEedge/!-- Make the application on mobile take up the full browser screen and disable user scaling. --metanameviewportcontentwidthdevice-width, initial-scale1, maximum-scale1, minimum-scale1, user-scalableno/titlecesium加载影像和矢量数据/titlescript src../Build/CesiumUnminified/Cesium.js/scriptstyleimport url(../Build/CesiumUnminified/Widgets/widgets.css);html,body,#cesiumContainer {width: 100%;height: 100%;margin: 0;padding: 0;overflow: hidden;}/style
/head
body
div idcesiumContainer/div
script//天地图tokenlet TDT_tk b0df1f950b1fd6914abe9e17079c0345;//Cesium tokenlet cesium_tk eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJqdGkiOiI1NThjYTk0MC03YjQwLTQ3YWYtOTY5Yy04NDk3OTJmMmI4NDciLCJpZCI6NzAxOTMsImlhdCI6MTYzNDA4ODE1N30.TB1v9XXATQLUGE5GNki_fYFMHddIyQ9arXPIx65e09s;//天地图影像let TDT_IMG_C http://{s}.tianditu.gov.cn/img_c/wmts?servicewmtsrequestGetTileversion1.0.0 LAYERimgtileMatrixSetcTileMatrix{TileMatrix}TileRow{TileRow}TileCol{TileCol} styledefaultformattilestk TDT_tk;//标注let TDT_CIA_C http://{s}.tianditu.gov.cn/cia_c/wmts?servicewmtsrequestGetTileversion1.0.0 LAYERciatileMatrixSetcTileMatrix{TileMatrix}TileRow{TileRow}TileCol{TileCol} styledefaultformattilestk TDT_tk;//初始页面加载//Cesium.Ion.defaultAccessToken cesium_tk;var cgs2000Ellipsolid Cesium.Ellipsoid.CGCS2000var cgs2000GeographicProj new Cesium.GeographicProjection(cgs2000Ellipsolid)let viewer new Cesium.Viewer(cesiumContainer, {// baseLayerPicker: false,timeline: true,homeButton: true,fullscreenButton: true,infoBox: true,animation: true,shouldAnimate: true,mapProjection: cgs2000GeographicProj//imageryProvider: layer, //设置默认底图});let rightTilt true;if (rightTilt) {viewer.scene.screenSpaceCameraController.tiltEventTypes [Cesium.CameraEventType.RIGHT_DRAG,Cesium.CameraEventType.PINCH,{eventType: Cesium.CameraEventType.LEFT_DRAG,modifier: Cesium.KeyboardEventModifier.CTRL},{eventType: Cesium.CameraEventType.RIGHT_DRAG,modifier: Cesium.KeyboardEventModifier.CTRL}]viewer.scene.screenSpaceCameraController.zoomEventTypes [Cesium.CameraEventType.MIDDLE_DRAG,Cesium.CameraEventType.WHEEL,Cesium.CameraEventType.PINCH]}var handler new Cesium.ScreenSpaceEventHandler(viewer.scene.canvas);handler.setInputAction(function(evt) {var cartesianviewer.camera.pickEllipsoid(evt.position,viewer.scene.globe.ellipsoid);var cartographicCesium.Cartographic.fromCartesian(cartesian);var lngCesium.Math.toDegrees(cartographic.longitude);//经度值var latCesium.Math.toDegrees(cartographic.latitude);//纬度值var mapPosition{x:lng,y:lat,z:cartographic.height};//cartographic.height的值始终为零。alert(longitude: lng ;latitude: lat );}, Cesium.ScreenSpaceEventType.LEFT_CLICK);viewer.imageryLayers.remove(viewer.imageryLayers.get(0))//添加tmslet tms {};tms.url http://10.0.7.16:81/tms;if (tms) {const layerInfo {url: tms.url,fileExtension: tms.fileExtension || jpg,maximumLevel: tms.maxZoom || 7,name: tms}const tmsService new Cesium.TileMapServiceImageryProvider(layerInfo)tmsService.layerInfo layerInfo}//添加地形let terrain {};terrain.url http://data.marsgis.cn/terrain;if (terrain) {const terrainLayer new Cesium.CesiumTerrainProvider({url: terrain.url})viewer.terrainProvider terrainLayer}_matrixIds [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18]//调用影响中文注记服务/*viewer.imageryLayers.addImageryProvider(new Cesium.WebMapTileServiceImageryProvider({url: TDT_CIA_C,layer: tdtImg_c,style: default,format: tiles,tileMatrixSetID: c,subdomains: [t0, t1, t2, t3, t4, t5, t6, t7],tilingScheme: new Cesium.GeographicTilingScheme(),tileMatrixLabels: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19],maximumLevel: 50,show: false}))*//*var myGeographicTilingScheme new Cesium.GeographicTilingScheme({ellipsoid: cgs2000Ellipsolid,rectangle: Cesium.Rectangle.fromDegrees(-400, -399.9999999999998, 400, 399.9999999999998),numberOfLevelZeroTilesX: 4,numberOfLevelZeroTilesY: 4})*/var world4490 new Cesium.ArcGisMapServerImageryProvider({url: http://10.1.88.200:6080/arcgis/rest/services/test/global4490ori400/MapServer,//tilingScheme: myGeographicTilingScheme,rectangle: Cesium.Rectangle.fromDegrees(-400, -320, 320, 400),ellipsoid:cgs2000Ellipsolid,numberOfLevelZeroTilesX: 4,numberOfLevelZeroTilesY: 4});viewer.imageryLayers.addImageryProvider(world4490);//viewer.imageryLayers.addImageryProvider(world);//使用ArcGisMapServerImageryProvider加载影像没成功改用WebMapServiceImageryProvider//var world new Cesium.ArcGisMapServerImageryProvider({//url:http://10.1.88.200:6080/arcgis/rest/services/test/globaltdt5/MapServer,//});//viewer.imageryLayers.addImageryProvider(world);var arcgisyx new Cesium.WebMapServiceImageryProvider({url:http://10.1.88.200:6080/arcgis/rest/services/test/globaltdt5/MapServer/tile/{z}/{y}/{x},layers:[0]});// viewer.imageryLayers.addImageryProvider(arcgisyx);var china new Cesium.ArcGisMapServerImageryProvider({url:http://10.1.88.200:6080/arcgis/rest/services/test/china4490/MapServer});viewer.imageryLayers.addImageryProvider(china);
/script
/body
/html 1、定义椭球体部分 var cgs2000Ellipsolid Cesium.Ellipsoid.CGCS2000var cgs2000GeographicProj new Cesium.GeographicProjection(cgs2000Ellipsolid)
2、初始化Cesium.Viewer时增加2000的mapProjection let viewer new Cesium.Viewer(cesiumContainer, {// baseLayerPicker: false,timeline: true,homeButton: true,fullscreenButton: true,infoBox: true,animation: true,shouldAnimate: true,mapProjection: cgs2000GeographicProj//imageryProvider: layer, //设置默认底图}); 3、调用关键代码加载图层 var world4490 new Cesium.ArcGisMapServerImageryProvider({url: http://10.1.88.200:6080/arcgis/rest/services/test/global4490ori400/MapServer,//tilingScheme: myGeographicTilingScheme,rectangle: Cesium.Rectangle.fromDegrees(-400, -320, 320, 400),ellipsoid:cgs2000Ellipsolid,numberOfLevelZeroTilesX: 4,numberOfLevelZeroTilesY: 4});viewer.imageryLayers.addImageryProvider(world4490); 说明
1服务说明发布了一个全球影像4490坐标系-400,400起点的数据切片方案保证其他参数与-180,90一致可从本文文末获取切片方案xml文件用来切片测试 2在新建ArcGisMapServerImageryProvider时可以不设置tilingScheme。发现ArcGisMapServerImageryProvider里有新建tilingScheme如果设置了tilingScheme发现这里的行列数参数没有起作用故直接在新建ArcGisMapServerImageryProvider传入行列数参数并在类中新建切片方案的时候读取。
rectangle切片范围发现用(-400, -400, 400, 400)带入整个地图偏移了 对切片的原理进一步了解后 针对-400,400起点切片为了保证和-180,90按照0级两列一行的大小如上图按照格网一样90°大小划分成4行4列切片范围应该是(-400, -320, 320, 400),请求的切片应该6块行列是行在前列在后1,11,21,32,12,22,3 按照这样设置此时再次运行后能够正常加载-400,400起点切片了 以上是展开的效果球体的效果 注
本文参考文章Cesium 之加载ArcGIS Server 4490切片服务含orgin -400 400_cesium加载arcgis面切片失败_xizhjxust_GIS的博客-CSDN博客
关于getNumberOfXTilesAtLevel和getNumberOfYTilesAtLeve这段代码和上述参考的文档存在一定出入做进一步说明。
但是因为直接拷贝后发现不能正常加载通过切片原理判断得出计算的行列式数量不对改成了2π*2 这里0级的话-400,400起点切片获取的xy切片数量应该是4行4列通过反推应该是4π如果是-180,90起点的话是2行1列则x应该用2πy应该用π原文章应该是针对-180,90起点的计算方式。
这段代码的写法只支持-400,400起点因为只是为了测试能够把-400,400起点的切片数据偷懒直接这么写了。如果要同时支持两种起点这里的写法应该要改成公式右顶点X-左顶点X/(256*分辨率)上顶点Y-下顶点Y/(256*分辨率)
如
-180,90起点[180--180]/(256*分辨率) 范围右顶点经度-左顶点经度256是因为切片大小是256*256,当0级时候分辨率为0.7031250000026057
-400,400起点[320--400]/(256*分辨率) 范围右顶点经度-左顶点经度256是因为切片大小是256*256,当0级时候分辨率为0.7031250000026057