cesium修改源码支持4490坐标系

最近对接某政务中心申请的地图服务,是4490的坐标系,其内部的sdk当一个宝一样催了n回也不愿意发,一直说走流程,无奈项目开发周期紧只能自己动手了。

本篇内容参考文章 Cesium 之加载ArcGIS Server 4490切片服务(含orgin -400 400

本文基于cesium 1.132.0版本调整,不同版本可能代码行数或者文件结构不同

主要分为三步

  1. 修改下载cesium源码
  2. 修改源码内对应文件
  3. 打包项目到本地目录中使用

一、克隆源码

js 复制代码
   //1.通过git下载源码
   git clone https://github.com/CesiumGS/cesium.git
   //2.npm install
   npm install

二、修改文件

1.修改ArcGisMapServerImageryProvider.js

路径:packages\engine\Source\Scene\ArcGisMapServerImageryProvider.js

在文件夹内搜索 spatialReference.wkid === 4326 有两处需要调整的地方

js 复制代码
  // 1.在148行左右添加对4490坐标系的判断
  else if (data.tileInfo.spatialReference.wkid === 4490) {
        imageryProviderBuilder.tilingScheme  = new GeographicTilingScheme({
            ellipsoid : imageryProviderBuilder.ellipsoid,
        });
    }
  //2.在206行左右增加对4490坐标系的判断
  else if (data.fullExtent.spatialReference.wkid === 4326 || data.fullExtent.spatialReference.wkid === 4490) {
          imageryProviderBuilder.rectangle = Rectangle.fromDegrees(
            data.fullExtent.xmin,
            data.fullExtent.ymin,
            data.fullExtent.xmax,
            data.fullExtent.ymax,
          );
        }
  

2.修改GeographicTilingScheme.js文件

路径:packages\engine\Source\Core\GeographicTilingScheme.js

有三处修改的地方,分别搜索1和2可以一起替换

  • 1.GeographicTilingScheme
  • 2.getNumberOfXTilesAtLevel和getNumberOfYTilesAtLevel
js 复制代码
//1.在25行附近替换GeographicTilingScheme 
function GeographicTilingScheme(options) {
  options = options ?? Frozen.EMPTY_OBJECT;
  if (defined(options.tileInfo)
    && defined(options.tileInfo.spatialReference)
    && defined(options.tileInfo.spatialReference.wkid)
    && options.tileInfo.spatialReference.wkid == 4490) {
    this._tileInfo = options.tileInfo;
    this._ellipsoid = options.ellipsoid ?? Ellipsoid.CGCS2000;
    this._rectangle = options.rectangle ??  Rectangle.fromDegrees(-180, -90, 180, 90);
    this._numberOfLevelZeroTilesX = options.numberOfLevelZeroTilesX ?? 4;
    this._numberOfLevelZeroTilesY = options.numberOfLevelZeroTilesY ?? 2;
  }
  else {
    this._ellipsoid = options.ellipsoid ?? Ellipsoid.WGS84;
    this._rectangle = options.rectangle ?? Rectangle.MAX_VALUE;
    this._numberOfLevelZeroTilesX = options.numberOfLevelZeroTilesX ?? 2;
    this._numberOfLevelZeroTilesY = options.numberOfLevelZeroTilesY ?? 1;
  }
  this._projection = new GeographicProjection(this._ellipsoid);
}
js 复制代码
//2.在130行附近替换掉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 * 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) {
  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.js

路径:packages\engine\Source\Core\Ellipsoid.js

搜索:new Ellipsoid(6378137.0, 6378137.0, 6356752.3142451793)

js 复制代码
//在235行附近将这段代码添加到WGS84的下方
Ellipsoid.CGCS2000 = Object.freeze(new Ellipsoid(6378137.0, 6378137.0, 6356752.31414035585));

到这里源码的替换部分已经全部完成,接下来就是打包进行使用

三、打包cesium

在package.json中可以看到对应的打包命令,这里直接使用build-release

js 复制代码
npm run build-release

打包后的文件放在Build/Cesium文件夹内 在build目录下还有其他版本,有兴趣可以自行关注

打包的文件结构

将整体Cesium文件夹放到public目录下使用

js 复制代码
//如果通过<script>标签引用
<link href="/public/Cesium/Widgets/widgets.css" rel="stylesheet">
<script type="text/javascript" src="/public/Cesium2/Cesium.js"></script>   
//通过import使用
import * as Cesium from "/public/Cesium/index.js";
import "/public/Cesium/Widgets/widgets.css";

最后具体使用示例

js 复制代码
// 声明Cesium Viewer实例
let viewer = null;

// 组件挂载后初始化Cesium
onMounted(async () => {
    // 初始化Cesium Viewer
    viewer = new Cesium.Viewer('cesiumContainer', {
        // 基础配置
        animation: false, // 动画小部件
        baseLayerPicker: false, // 底图选择器
        fullscreenButton: false, // 全屏按钮
        vrButton: false, // VR按钮
        geocoder: false, // 地理编码搜索框
        homeButton: false, // 主页按钮
        infoBox: false, // 信息框
        sceneModePicker: false, // 场景模式选择器
        selectionIndicator: false, // 选择指示器
        timeline: false, // 时间轴
        navigationHelpButton: false, // 导航帮助按钮
        navigationInstructionsInitiallyVisible: false, // 导航说明初始可见性
        scene3DOnly: false, // 仅3D场景
    });
    // 隐藏logo
    viewer.cesiumWidget.creditContainer.style.display = "none";
    viewer.scene.globe.enableLighting = false;
    //前提先把场景上的图层全部移除或者隐藏 
    viewer.scene.globe.baseColor = new Cesium.Color(0.0, 0.1, 0.2, 1.0); //修改地图为暗蓝色背景
    // 设置抗锯齿
    viewer.scene.postProcessStages.fxaa.enabled = true;
    // 清除默认底图
    viewer.imageryLayers.remove(viewer.imageryLayers.get(0));

    //这里使用的是开源的4326坐标系展示,替换成自己的4490坐标系就行
    const esri = await Cesium.ArcGisMapServerImageryProvider.fromUrl('https://services.arcgisonline.com/arcgis/rest/services/World_Imagery/MapServer')
    viewer.imageryLayers.addImageryProvider(esri);
    viewer.cesiumWidget.screenSpaceEventHandler.removeInputAction(Cesium.ScreenSpaceEventType.LEFT_DOUBLE_CLICK );

    // 设置初始位置 长沙市上空经纬度28.2312227, 112.9334574
      const boundingSphere = new Cesium.BoundingSphere(
        Cesium.Cartesian3.fromDegrees(113.1334574, 28.2312227, 500),
        60000
      );
      // 定位到初始位置
      viewer.camera.flyToBoundingSphere(boundingSphere, {
        // 定位到初始位置的过渡时间,设置成0,就没有过渡,类似一个过场的动画时长
        duration: 0,
      });

})
相关推荐
Dolphin_海豚16 分钟前
vapor 语法糖是如何被解析的
前端·源码·vapor
Bdygsl1 小时前
前端开发:HTML(5)—— 表单
前端·html
望获linux1 小时前
【实时Linux实战系列】实时数据流处理框架分析
linux·运维·前端·数据库·chrome·操作系统·wpf
国家不保护废物2 小时前
TailwindCSS:原子化CSS的革命,让React开发爽到飞起!🚀
前端·css·react.js
程序视点2 小时前
如何高效率使用 Cursor ?
前端·后端·cursor
前端领航者2 小时前
重学Vue3《 v-for的key属性:性能差异与最佳实践》
前端·javascript
归于尽2 小时前
跨域问题从青铜到王者:JSONP、CORS原理详解与实战(前端必会)
前端·浏览器
Andy_GF2 小时前
纯血鸿蒙HarmonyOS Next 远程测试包分发
前端·ios·harmonyos
小山不高3 小时前
react实现leaferjs编辑器之形状裁剪功能点
前端