Cesium加载ArcGIS Server4490且orgin -400 400的切片服务

科技资讯 投稿 7300 0 评论

Cesium加载ArcGIS Server4490且orgin -400 400的切片服务

如果是ArcGIS发布的4490坐标系的切片服务,如果原点在orgin X: -180.0Y: 90.0的情况下,我们可以通过WebMapTileServiceImageryProvider按照WMTS的方式加载(需符合OGC标准的WMTS类型)。

本文使用:

源码打包测试参考另一篇文档:cesium源码编译调试及调用全过程

为了能够调试源码,打包的时候使用命令:npm run combine

一、通过修改源码实现ArcGIS的切片服务,需要修改的源码文件包括:

    ArcGisMapServerImageryProvider
  • GeographicTilingScheme
  • Ellipsoid

1、修改ArcGisMapServerImageryProvider类

(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;//附加自定义属性 }

 具体位置如图所示:

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类

通过增加4490坐标系的椭球、矩阵范围等定义,4490坐标系默认椭球为CGCS2000,矩阵范围为(-180,-90,180,90),开放矩阵范围的目的就是为了支持自定义的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;

代码位置: 

/**
 * 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椭球参数

 定义2000椭球参数:

/** * An Ellipsoid instance initialized to the CGCS2000 standard. * * @type {Ellipsoid} * @constant */ Ellipsoid.CGCS2000 = Object.freeze( new Ellipsoid(6378137.0, 6378137.0, 6356752.31414035585 ;

 代码位置:

二、代码调用

测试用html页面(做测试的页面,有一些其他代码,可以忽略,留意本文需要的代码部分):

<!DOCTYPE html> <html lang="en"> <head> <!-- Use correct character set. --> <meta charset="utf-8"/> <!-- Tell IE to use the latest, best version. --> <meta http-equiv="X-UA-Compatible" content="IE=edge"/> <!-- Make the application on mobile take up the full browser screen and disable user scaling. --> <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, minimum-scale=1, user-scalable=no" /> <title>cesium加载影像和矢量数据</title> <script src="../Build/CesiumUnminified/Cesium.js"></script> <style> @import url(../Build/CesiumUnminified/Widgets/widgets.css; html, body, #cesiumContainer { width: 100%; height: 100%; margin: 0; padding: 0; overflow: hidden; } </style> </head> <body> <div id="cesiumContainer"></div> <script> //天地图token let TDT_tk = "b0df1f950b1fd6914abe9e17079c0345"; //Cesium token let cesium_tk = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJqdGkiOiI1NThjYTk0MC03YjQwLTQ3YWYtOTY5Yy04NDk3OTJmMmI4NDciLCJpZCI6NzAxOTMsImlhdCI6MTYzNDA4ODE1N30.TB1v9XXATQLUGE5GNki_fYFMHddIyQ9arXPIx65e09s"; //天地图影像 let TDT_IMG_C = "http://{s}.tianditu.gov.cn/img_c/wmts?service=wmts&request=GetTile&version=1.0.0" + "&LAYER=img&tileMatrixSet=c&TileMatrix={TileMatrix}&TileRow={TileRow}&TileCol={TileCol}" + "&style=default&format=tiles&tk=" + TDT_tk; //标注 let TDT_CIA_C = "http://{s}.tianditu.gov.cn/cia_c/wmts?service=wmts&request=GetTile&version=1.0.0" + "&LAYER=cia&tileMatrixSet=c&TileMatrix={TileMatrix}&TileRow={TileRow}&TileCol={TileCol}" + "&style=default&format=tiles&tk=" + TDT_tk; //初始页面加载 //Cesium.Ion.defaultAccessToken = cesium_tk; var cgs2000Ellipsolid = Cesium.Ellipsoid.CGCS2000 var 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 cartesian=viewer.camera.pickEllipsoid(evt.position,viewer.scene.globe.ellipsoid; var cartographic=Cesium.Cartographic.fromCartesian(cartesian; var lng=Cesium.Math.toDegrees(cartographic.longitude;//经度值 var lat=Cesium.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 //添加tms let 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.CGCS2000 var 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;

说明:

rectangle切片范围:发现用(-400, -400, 400, 400带入整个地图偏移了:

注:

关于getNumberOfXTilesAtLevel和getNumberOfYTilesAtLeve这段代码和上述参考的文档存在一定出入做进一步说明。

 

这段代码的写法只支持-400,400起点,因为只是为了测试能够把-400,400起点的切片数据,偷懒直接这么写了。如果要同时支持两种起点,这里的写法应该要改成公式:(右顶点X-左顶点X)/(256*分辨率;(上顶点Y-下顶点Y)/(256*分辨率

-180,90起点:[180-(-180)]/(256*分辨率      范围右顶点经度-左顶点经度,256是因为切片大小是256*256,当0级时候,分辨率为0.7031250000026057

 

影像数据:用来切4490起点-400,400的切片数据,全球影像,天地图5级数据合成的。

矢量数据:用来验证与影像数据叠加是否大致吻合,全国行政区数据,包括省会,国界、省界

切片方案:起点-400,400的切片方案

测试页面:cesiumlayer.html

<本文完>

 

编程笔记 » Cesium加载ArcGIS Server4490且orgin -400 400的切片服务

赞同 (42) or 分享 (0)
游客 发表我的评论   换个身份
取消评论

表情
(0)个小伙伴在吐槽