侧边栏壁纸
博主头像
进一步,海阔天空 博主等级

进一步,海阔天空

  • 累计撰写 140 篇文章
  • 累计创建 19 个标签
  • 累计收到 7 条评论

目 录CONTENT

文章目录
GIS

Cesium不改源码支持坐标系为4490的ArcGIS Rest缓存服务的解决方案

海阔天空
2022-08-26 / 0 评论 / 0 点赞 / 462 阅读 / 0 字

本文完全参考了这篇文章的内容,只是把TypeScript代码改成了JavaScript代码,感谢原作者的无私奉献

typescript代码链接

Cesium不改源码支持坐标系为4490的ArcGIS Rest缓存服务的解决方案,代码为TypeScript编写(vx gzh【图说GIS】)

JavaScript版本

由于很多项目在使用cesium的时候,还是用的JavaScript,所以我把代码改成了JavaScript版本,供大家分享。

GeographicTilingScheme4490.js

"use strict";

class GeographicTilingScheme4490 extends Cesium.GeographicTilingScheme {
    options = {};
    constructor(options) {
        super(options);
        console.log("create object");
        this.options = options;
        this.init();
    }
    init() {
        console.log("init...");
        const EllipsoidExt = new Cesium.Ellipsoid();

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

        const { options } = this;
        const self = this;
        if (options
            && options.tileInfo
            && options.tileInfo.spatialReference
            && options.tileInfo.spatialReference.wkid
            && options.tileInfo.spatialReference.wkid == 4490) {
            self._tileInfo = options.tileInfo;
            self._ellipsoid = options.ellipsoid ? options.ellipsoid : EllipsoidExt.CGCS2000;
            self._rectangle = options.rectangle ? options.rectangle : Cesium.Rectangle.fromDegrees(-180, -90, 180, 90);
            self._numberOfLevelZeroTilesX = options.numberOfLevelZeroTilesX ? options.numberOfLevelZeroTilesX : 4;
            self._numberOfLevelZeroTilesY = options.numberOfLevelZeroTilesY ? options.numberOfLevelZeroTilesY : 2;
        }
        self._projection = new Cesium.GeographicProjection(self._ellipsoid);
    }
    getNumberOfXTilesAtLevel(level) {
        const self = this
        if (!self._tileInfo) {
            return self._numberOfLevelZeroTilesX << level;
        }
        else {
            var currentMatrix = self._tileInfo.lods.filter(function (item) {
                return item.level === level;
            });
            var currentResolution = currentMatrix[0].resolution;
            return Math.round(Cesium.Math.toDegrees(Cesium.Math.TWO_PI) / (self._tileInfo.rows * currentResolution));
        }
    }
    rectangleToNativeRectangle(rectangle, result) {
        var west = Cesium.Math.toDegrees(rectangle.west);
        var south = Cesium.Math.toDegrees(rectangle.south);
        var east = Cesium.Math.toDegrees(rectangle.east);
        var north = Cesium.Math.toDegrees(rectangle.north);

        if (!result) {
            return new Cesium.Rectangle(west, south, east, north);
        }

        result.west = west;
        result.south = south;
        result.east = east;
        result.north = north;
        return result;
    }
    tileXYToNativeRectangle(x, y, level, result) {
        var rectangleRadians = this.tileXYToRectangle(x, y, level, result);
        rectangleRadians.west = Cesium.Math.toDegrees(rectangleRadians.west);
        rectangleRadians.south = Cesium.Math.toDegrees(rectangleRadians.south);
        rectangleRadians.east = Cesium.Math.toDegrees(rectangleRadians.east);
        rectangleRadians.north = Cesium.Math.toDegrees(rectangleRadians.north);
        return rectangleRadians;
    }
    tileXYToRectangle(x, y, level, result) {
        const self = this
        var rectangle = self._rectangle;

        var west = 0;
        var east = 0;

        var north = 0;
        var south = 0;

        if (self._tileInfo) {
            var currentMatrix = self._tileInfo.lods.filter(function (item) {
                return item.level === level;
            });
            var currentResolution = currentMatrix[0].resolution;

            north = self._tileInfo.origin.y - y * (self._tileInfo.cols * currentResolution);
            west = self._tileInfo.origin.x + x * (self._tileInfo.rows * currentResolution);

            south = self._tileInfo.origin.y - (y + 1) * (self._tileInfo.cols * currentResolution);
            east = self._tileInfo.origin.x + (x + 1) * (self._tileInfo.rows * currentResolution);

            west = Cesium.Math.toRadians(west);
            north = Cesium.Math.toRadians(north);
            east = Cesium.Math.toRadians(east);
            south = Cesium.Math.toRadians(south);
        }
        else {
            var xTiles = this.getNumberOfXTilesAtLevel(level);
            var yTiles = this.getNumberOfYTilesAtLevel(level);

            var xTileWidth = rectangle.width / xTiles;
            west = x * xTileWidth + rectangle.west;
            east = (x + 1) * xTileWidth + rectangle.west;

            var yTileHeight = rectangle.height / yTiles;
            north = rectangle.north - y * yTileHeight;
            south = rectangle.north - (y + 1) * yTileHeight;
        }



        if (!result) {
            result = new Cesium.Rectangle(west, south, east, north);
        }

        result.west = west;
        result.south = south;
        result.east = east;
        result.north = north;
        return result;
    }
    positionToTileXY(
        position,
        level,
        result) {
        const self = this
        var rectangle = self._rectangle;
        if (!Cesium.Rectangle.contains(rectangle, position)) {
            // outside the bounds of the tiling scheme
            return undefined;
        }

        if (self._tileInfo) {
            var currentMatrix = self._tileInfo.lods.filter(function (item) {
                return item.level === level;
            });
            var currentResolution = currentMatrix[0].resolution;

            var degLon = Cesium.Math.toDegrees(position.longitude);
            var degLat = Cesium.Math.toDegrees(position.latitude);

            var x_4490 = Math.floor((degLon - self._tileInfo.origin.x) / (self._tileInfo.rows * currentResolution));
            var y_4490 = Math.floor((self._tileInfo.origin.y - degLat) / (self._tileInfo.cols * currentResolution));

            return new Cesium.Cartesian2(x_4490, y_4490);
        }

        var xTiles = self.getNumberOfXTilesAtLevel(level);
        var yTiles = this.getNumberOfYTilesAtLevel(level);

        var xTileWidth = rectangle.width / xTiles;
        var yTileHeight = rectangle.height / yTiles;

        var longitude = position.longitude;
        if (rectangle.east < rectangle.west) {
            longitude += Cesium.Math.TWO_PI;
        }

        var xTileCoordinate = ((longitude - rectangle.west) / xTileWidth) | 0;
        if (xTileCoordinate >= xTiles) {
            xTileCoordinate = xTiles - 1;
        }

        var yTileCoordinate =
            ((rectangle.north - position.latitude) / yTileHeight) | 0;
        if (yTileCoordinate >= yTiles) {
            yTileCoordinate = yTiles - 1;
        }

        if (!result) {
            return new Cesium.Cartesian2(xTileCoordinate, yTileCoordinate);
        }

        result.x = xTileCoordinate;
        result.y = yTileCoordinate;
        return result;
    }
}
export default GeographicTilingScheme4490;

ArcGisMapServerImageryProvider4490.js

"use strict";

import GeographicTilingScheme4490 from "./GeographicTilingScheme4490";

class ArcGisMapServerImageryProvider4490 extends Cesium.ArcGisMapServerImageryProvider {
    options = {};
    constructor(options) {
        super(options)
        this.options = options
        this.init()
    }

    init() {
        const self = this
        function requestMetadata() {
            const resource = self._resource.getDerivedResource({
                queryParameters: {
                    f: "json",
                },
            });
            const metadata = resource.fetchJsonp();
            metadata.then((data) => {
                self.metadata4490Success(data)
            })
        }
        requestMetadata()
    }

    metadata4490Success(data) {
        const tileInfo = data.tileInfo;
        if (data.spatialReference.wkid === 4490 && tileInfo) {
            const self = this
            const { options } = this
            if (options) {
                if (data.tileInfo.spatialReference.wkid === 4490) {
                    const geoTilingScheme = new GeographicTilingScheme4490({
                        ellipsoid: options.ellipsoid,
                        tileInfo: tileInfo
                    });
                    self._tilingScheme = geoTilingScheme
                }
                self._maximumLevel = tileInfo.lods.length - 1;
                self._useTiles = true;
                if (data.fullExtent) {
                    if (
                        data.fullExtent.spatialReference &&
                        data.fullExtent.spatialReference.wkid
                    ) {
                        if (data.fullExtent.spatialReference.wkid === 4490) {
                            self._rectangle = Cesium.Rectangle.fromDegrees(
                                data.fullExtent.xmin,
                                data.fullExtent.ymin,
                                data.fullExtent.xmax,
                                data.fullExtent.ymax
                            );
                        }
                    }
                } else {
                    self._rectangle = self._tilingScheme.rectangle;
                }

                // Install the default tile discard policy if none has been supplied.
                if (!self._tileDiscardPolicy) {
                    self._tileDiscardPolicy = new Cesium.DiscardMissingTileImagePolicy({
                        missingImageUrl: self.buildImageResource(self, 0, 0, self._maximumLevel).url,
                        pixelsToCheck: [
                            new Cesium.Cartesian2(0, 0),
                            new Cesium.Cartesian2(200, 20),
                            new Cesium.Cartesian2(20, 200),
                            new Cesium.Cartesian2(80, 110),
                            new Cesium.Cartesian2(160, 130),
                        ],
                        disableCheckIfAllPixelsAreTransparent: true,
                    });
                }

            }

            if (data.copyrightText && data.copyrightText.length > 0) {
                self._credit = new Cesium.Credit(data.copyrightText);
            }
            self._ready = true;
            self._readyPromise.resolve(true);
        }
    }

    buildImageResource(imageryProvider, x, y, level, request) {
        var resource;
        if (imageryProvider._useTiles) {
            resource = imageryProvider._resource.getDerivedResource({
                url: "tile/" + level + "/" + y + "/" + x,
                request: request,
            });
        } else {
            var nativeRectangle = imageryProvider._tilingScheme.tileXYToNativeRectangle(
                x,
                y,
                level
            );
            var bbox =
                nativeRectangle.west +
                "," +
                nativeRectangle.south +
                "," +
                nativeRectangle.east +
                "," +
                nativeRectangle.north;

            var query = {
                bbox: bbox,
                size: imageryProvider._tileWidth + "," + imageryProvider._tileHeight,
                format: "png32",
                transparent: true,
                f: "image",
            };

            if (
                imageryProvider._tilingScheme.projection instanceof Cesium.GeographicProjection
            ) {
                query.bboxSR = 4490;
                query.imageSR = 4490;
            } else {
                query.bboxSR = 3857;
                query.imageSR = 3857;
            }
            if (imageryProvider.layers) {
                query.layers = "show:" + imageryProvider.layers;
            }

            resource = imageryProvider._resource.getDerivedResource({
                url: "export",
                request: request,
                queryParameters: query,
            });
        }

        return resource;
    }
}

export default ArcGisMapServerImageryProvider4490;

使用

const szdomProvider = new ArcGisMapServerImageryProvider4490({
      url: "ArcgisServer URL",
    });
viewer.imageryLayers.addImageryProvider(szdomProvider);
0

评论区