Cesium 之加载ArcGIS Server 4490切片服务(含orgin -400 400)

        对于ArcGIS Server发布的切片服务,在地理坐标系中Cesium默认只支持wgs84的4326坐标系,无法通过ArcGisMapServerImageryProvider直接加载CGCS2000的4490坐标系,虽然可以使用WebMapTileServiceImageryProvider加载符合OGC标准的WMTS类型,但只能针对于原点在orgin X: -180.0Y: 90.0的情况,对于原点在orgin X: -400.0Y: 400.0时还是无法正常加载,为了能够实现加载,以下通过修改源码方式来达到目的。

笔者以Cesium 1.91版本为例。

目录

1、修改ArcGisMapServerImageryProvider类

2、修改GeographicTilingScheme类

 3、定义2000椭球参数

4、底图调用实现


1、修改ArcGisMapServerImageryProvider类

在metadataSuccess方法中修改

(1)读取切片模式时增加支持wkid 4490坐标系的判断,同时将切片信息也传入,目的是为了后面在获取行列号xy时,可以通过读取切片信息,使用自定义方法改写行列号的获取方式。

else if (data.fullExtent.spatialReference.wkid === 4490) {
          that._tilingScheme = new GeographicTilingScheme({
            ellipsoid: options.ellipsoid,
            tileInfo: data.tileInfo,
            rectangle: that._rectangle
          });
          that._tilingScheme._tileInfo = data.tileInfo;//附加自定义属性
        } 

如截图所示:

Cesium 之加载ArcGIS Server 4490切片服务(含orgin -400 400)_第1张图片

(2)增加最大层级定义(用来限制最大可缩放多少层级,达到一定层级后不显示,根据项目需要为可选修改项)

 //修改最大层级定义

        that._maximumLevel = defaultValue(options.maximumLevel, data.tileInfo.lods.length - 1);

(3)矩阵范围定义中 增加wkid 4490坐标系判断。

2、修改GeographicTilingScheme类

(1)增加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);
    }

Cesium 之加载ArcGIS Server 4490切片服务(含orgin -400 400)_第2张图片

(2)修改切片矩阵计算获取行列号xy值的原型方法getNumberOfXTilesAtLevel和getNumberOfYTilesAtLevel

/**
   * 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) {
    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) / (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) {
    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));
    }
  };

Cesium 之加载ArcGIS Server 4490切片服务(含orgin -400 400)_第3张图片

 3、定义2000椭球参数

  Ellipsoid.CGCS2000 = Object.freeze(
    new Ellipsoid(6378137.0, 6378137.0, 6356752.31414035585)
  );

 Cesium 之加载ArcGIS Server 4490切片服务(含orgin -400 400)_第4张图片

4、底图调用实现

 以上修改完后,接下来就是如何调用的问题了。

调用方式比一般的调用相对更复杂些,具体如下:

(1)确定椭球参数

如 CGCS2000椭球如下

 var cgs2000Ellipsolid = new Cesium.Ellipsoid(6378137.0, 6378137.0, 6356752.31414035585)

或者直接用源码中已修改过的Ellipsoid.CGCS2000

var cgs2000Ellipsolid=Cesium.Ellipsoid.CGCS2000

(2) 定义切片模式

如orgin 为-400 400时

var myGeographicTilingScheme = new Cesium.GeographicTilingScheme({
    ellipsoid: cgs2000Ellipsolid,
    rectangle: Cesium.Rectangle.fromDegrees(-400, -399.9999999999998, 400, 399.9999999999998),
    numberOfLevelZeroTilesX: 2,
    numberOfLevelZeroTilesY: 1
})

orgin -180 90时 等等

var myGeographicTilingScheme = new Cesium.GeographicTilingScheme({
    ellipsoid: cgs2000Ellipsolid,
    rectangle: Cesium.Rectangle.fromDegrees(-180, -90, 180, 90),
    numberOfLevelZeroTilesX: 4,
    numberOfLevelZeroTilesY: 2
})

(3)创建ArcGisMapServerImageryProvider

url为MapServer地址

layer的名称可在wmts下找到,这个大家应该都知道,我就不截图了,

具体参数设置如下:

Cesium 之加载ArcGIS Server 4490切片服务(含orgin -400 400)_第5张图片

生成的provider赋值到Viewer参数的imageryProvider下

 (4)初始化地图投影

var cgs2000GeographicProj = new Cesium.GeographicProjection(cgs2000Ellipsolid)

将其赋值到Viewer参数的mapProjection下

(5)初始化生成三维球体

let viewer2 = new Cesium.Viewer('map3D', {
    animation: false,
    baseLayerPicker: false,
    fullscreenButton: false,
    geocoder: false,
    homeButton: false,
    sceneModePicker: false,
    selectionIndicator: false,
    timeline: false,
    navigationHelpButton: false,
    infoBox: false,
    navigationInstructionsInitiallyVisible: false,
    mapProjection: cgs2000GeographicProj,
    imageryProvider: esriWMTS,
    scene3DOnly: false,
    sceneMode: Cesium.SceneMode.SCENE2D,
    terrainExaggeration: 1,
    showRenderLoopErrors: false,

});

OK完成,效果图如下:

你可能感兴趣的:(Cesium开发,Cesium,Arcgis,Server,CGCS2000,4490,orgin,400,-400)