import CustomMercatorProjection from './CustomMercatorProjection.js';
|
/**
|
* A tiling scheme for geometry referenced to a {@link WebMercatorProjection}, EPSG:3857. This is
|
* the tiling scheme used by Google Maps, Microsoft Bing Maps, and most of ESRI ArcGIS Online.
|
*
|
* @alias BJ2000TilingScheme2
|
* @constructor
|
*
|
* @param {Object} [options] Object with the following properties:
|
* @param {Ellipsoid} [options.ellipsoid=Ellipsoid.WGS84] The ellipsoid whose surface is being tiled. Defaults to
|
* the WGS84 ellipsoid.
|
* @param {Number} [options.numberOfLevelZeroTilesX=1] The number of tiles in the X direction at level zero of
|
* the tile tree.
|
* @param {Number} [options.numberOfLevelZeroTilesY=1] The number of tiles in the Y direction at level zero of
|
* the tile tree.
|
* @param {Cartesian2} [options.rectangleSouthwestInMeters] The southwest corner of the rectangle covered by the
|
* tiling scheme, in meters. If this parameter or rectangleNortheastInMeters is not specified, the entire
|
* globe is covered in the longitude direction and an equal distance is covered in the latitude
|
* direction, resulting in a square projection.
|
* @param {Cartesian2} [options.rectangleNortheastInMeters] The northeast corner of the rectangle covered by the
|
* tiling scheme, in meters. If this parameter or rectangleSouthwestInMeters is not specified, the entire
|
* globe is covered in the longitude direction and an equal distance is covered in the latitude
|
* direction, resulting in a square projection.
|
*/
|
var Cesium = null;
|
function Bj2000TilingScheme(options) {
|
Cesium = options.SmartEarth;
|
options = Cesium.defaultValue(options, Cesium.defaultValue.EMPTY_OBJECT);
|
this._ellipsoid = Cesium.defaultValue(options.ellipsoid, Cesium.Ellipsoid.WGS84);
|
this._numberOfLevelZeroTilesX = Cesium.defaultValue(
|
options.numberOfLevelZeroTilesX,
|
1
|
);
|
this._numberOfLevelZeroTilesY = Cesium.defaultValue(
|
options.numberOfLevelZeroTilesY,
|
1
|
);
|
if(options.customEPSG){
|
this._projection = new CustomMercatorProjection(options.customEPSG,this._ellipsoid,Cesium,options.proj);
|
}else {
|
this._projection = new Cesium.WebMercatorProjection(this._ellipsoid);
|
}
|
if (
|
Cesium.defined(options.rectangleSouthwestInMeters) &&
|
Cesium.defined(options.rectangleNortheastInMeters)
|
) {
|
this._rectangleSouthwestInMeters = options.rectangleSouthwestInMeters;
|
this._rectangleNortheastInMeters = options.rectangleNortheastInMeters;
|
} else {
|
const semimajorAxisTimesPi = this._ellipsoid.maximumRadius * Math.PI;
|
this._rectangleSouthwestInMeters = new Cesium.Cartesian2(
|
-semimajorAxisTimesPi,
|
-semimajorAxisTimesPi
|
);
|
this._rectangleNortheastInMeters = new Cesium.Cartesian2(
|
semimajorAxisTimesPi,
|
semimajorAxisTimesPi
|
);
|
}
|
|
const southwest = this._projection.unproject(
|
this._rectangleSouthwestInMeters
|
);
|
const northeast = this._projection.unproject(
|
this._rectangleNortheastInMeters
|
);
|
this._rectangle = new Cesium.Rectangle(
|
southwest.longitude,
|
southwest.latitude,
|
northeast.longitude,
|
northeast.latitude
|
);
|
this._resolutions = Cesium.defaultValue(options.resolutions,[0]);
|
this._origin = Cesium.defaultValue(options.origin, [0,0]);
|
this.tileWidth = Cesium.defaultValue(options.tileWidth, 256);
|
this.tileHeight = Cesium.defaultValue(options.tileHeight, 256);
|
}
|
|
Object.defineProperties(Bj2000TilingScheme.prototype, {
|
/**
|
* Gets the ellipsoid that is tiled by this tiling scheme.
|
* @memberof Bj2000TilingScheme.prototype
|
* @type {Ellipsoid}
|
*/
|
ellipsoid: {
|
get: function () {
|
return this._ellipsoid;
|
},
|
},
|
|
/**
|
* Gets the rectangle, in radians, covered by this tiling scheme.
|
* @memberof Bj2000TilingScheme.prototype
|
* @type {Rectangle}
|
*/
|
rectangle: {
|
get: function () {
|
return this._rectangle;
|
},
|
},
|
|
/**
|
* Gets the map projection used by this tiling scheme.
|
* @memberof Bj2000TilingScheme.prototype
|
* @type {MapProjection}
|
*/
|
projection: {
|
get: function () {
|
return this._projection;
|
},
|
},
|
rectangleNortheastInMeters:{
|
get: function() {
|
return this._rectangleNortheastInMeters;
|
}
|
},
|
rectangleSouthwestInMeters:{
|
get: function() {
|
return this._rectangleSouthwestInMeters;
|
}
|
},
|
});
|
|
/**
|
* 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.
|
*/
|
Bj2000TilingScheme.prototype.getNumberOfXTilesAtLevel = function (level) {
|
return this._numberOfLevelZeroTilesX << level;
|
};
|
|
/**
|
* 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.
|
*/
|
Bj2000TilingScheme.prototype.getNumberOfYTilesAtLevel = function (level) {
|
return this._numberOfLevelZeroTilesY << level;
|
};
|
|
/**
|
* Transforms a rectangle specified in geodetic radians to the native coordinate system
|
* of this tiling scheme.
|
*
|
* @param {Rectangle} rectangle The rectangle to transform.
|
* @param {Rectangle} [result] The instance to which to copy the result, or undefined if a new instance
|
* should be created.
|
* @returns {Rectangle} The specified 'result', or a new object containing the native rectangle if 'result'
|
* is undefined.
|
*/
|
Bj2000TilingScheme.prototype.rectangleToNativeRectangle = function (
|
rectangle,
|
result
|
) {
|
const projection = this._projection;
|
const southwest = projection.project(Cesium.Rectangle.southwest(rectangle));
|
const northeast = projection.project(Cesium.Rectangle.northeast(rectangle));
|
|
if (!Cesium.defined(result)) {
|
return new Cesium.Rectangle(southwest.x, southwest.y, northeast.x, northeast.y);
|
}
|
|
result.west = southwest.x;
|
result.south = southwest.y;
|
result.east = northeast.x;
|
result.north = northeast.y;
|
return result;
|
};
|
|
/**
|
* Converts tile x, y coordinates and level to a rectangle expressed in the native coordinates
|
* of the tiling scheme.
|
*
|
* @param {Number} x The integer x coordinate of the tile.
|
* @param {Number} y The integer y coordinate of the tile.
|
* @param {Number} level The tile level-of-detail. Zero is the least detailed.
|
* @param {Object} [result] The instance to which to copy the result, or undefined if a new instance
|
* should be created.
|
* @returns {Rectangle} The specified 'result', or a new object containing the rectangle
|
* if 'result' is undefined.
|
*/
|
Bj2000TilingScheme.prototype.tileXYToNativeRectangle = function (
|
x,
|
y,
|
level,
|
result
|
) {
|
level +=6;
|
const xTiles = this.getNumberOfXTilesAtLevel(level);
|
const yTiles = this.getNumberOfYTilesAtLevel(level);
|
|
const resolution = this._resolutions[level];
|
const eastFromOrigin = this._rectangleNortheastInMeters.x - this._origin[0];
|
const southFromOrigin = this._origin[1] - this._rectangleSouthwestInMeters.y;
|
const xTileWidth = eastFromOrigin / xTiles;
|
const yTileHeight = southFromOrigin / yTiles;
|
|
// let west = this._origin[0] + x * xTileWidth;
|
// let east = this._origin[0] + (x + 1) * xTileWidth;
|
// if(west < this._rectangleSouthwestInMeters.x){
|
// west = this._rectangleSouthwestInMeters.x;
|
// }
|
// if(east >= this._rectangleNortheastInMeters.x) {
|
// east = this._rectangleNortheastInMeters.x;
|
// }
|
const west = this._origin[0] + x * this.tileWidth * resolution;
|
const east = west + this.tileWidth * resolution;
|
|
// let north = this._origin[1] - y * yTileHeight;
|
// let south = this._origin[1] - (y + 1) * yTileHeight;
|
// if(south < this._rectangleSouthwestInMeters.y) {
|
// south = this._rectangleSouthwestInMeters.y;
|
// }
|
// if(north > this._rectangleNortheastInMeters.y) {
|
// north = this._rectangleNortheastInMeters.y;
|
// }
|
|
const south = this._origin[1] - (y + 1) * this.tileHeight * resolution;
|
const north = south + this.tileHeight * resolution;
|
|
if (!Cesium.defined(result)) {
|
return new Cesium.Rectangle(west, south, east, north);
|
}
|
|
result.west = west;
|
result.south = south;
|
result.east = east;
|
result.north = north;
|
return result;
|
};
|
|
/**
|
* Converts tile x, y coordinates and level to a cartographic rectangle in radians.
|
*
|
* @param {Number} x The integer x coordinate of the tile.
|
* @param {Number} y The integer y coordinate of the tile.
|
* @param {Number} level The tile level-of-detail. Zero is the least detailed.
|
* @param {Object} [result] The instance to which to copy the result, or undefined if a new instance
|
* should be created.
|
* @returns {Rectangle} The specified 'result', or a new object containing the rectangle
|
* if 'result' is undefined.
|
*/
|
Bj2000TilingScheme.prototype.tileXYToRectangle = function (
|
x,
|
y,
|
level,
|
result
|
) {
|
const nativeRectangle = this.tileXYToNativeRectangle(x, y, level, result);
|
const projection = this._projection;
|
const southwest = projection.unproject(
|
new Cesium.Cartesian2(nativeRectangle.west, nativeRectangle.south)
|
);
|
const northeast = projection.unproject(
|
new Cesium.Cartesian2(nativeRectangle.east, nativeRectangle.north)
|
);
|
|
nativeRectangle.west = southwest.longitude;
|
nativeRectangle.south = southwest.latitude;
|
nativeRectangle.east = northeast.longitude;
|
nativeRectangle.north = northeast.latitude;
|
return nativeRectangle;
|
};
|
|
/**
|
* Calculates the tile x, y coordinates of the tile containing
|
* a given cartographic position.
|
*
|
* @param {Cartographic} position The position.
|
* @param {Number} level The tile level-of-detail. Zero is the least detailed.
|
* @param {Cartesian2} [result] The instance to which to copy the result, or undefined if a new instance
|
* should be created.
|
* @returns {Cartesian2} The specified 'result', or a new object containing the tile x, y coordinates
|
* if 'result' is undefined.
|
*/
|
Bj2000TilingScheme.prototype.positionToTileXY = function (
|
position,
|
level,
|
result
|
) {
|
const rectangle = this._rectangle;
|
if (!Cesium.Rectangle.contains(rectangle, position)) {
|
// outside the bounds of the tiling scheme
|
return undefined;
|
}
|
level +=6;
|
|
const xTiles = this.getNumberOfXTilesAtLevel(level);
|
const yTiles = this.getNumberOfYTilesAtLevel(level);
|
//
|
// const overallWidth =
|
// this._rectangleNortheastInMeters.x - this._rectangleSouthwestInMeters.x;
|
// const xTileWidth = overallWidth / xTiles;
|
// const overallHeight =
|
// this._rectangleNortheastInMeters.y - this._rectangleSouthwestInMeters.y;
|
// const yTileHeight = overallHeight / yTiles;
|
|
const projection = this._projection;
|
|
const webMercatorPosition = projection.project(position);
|
const resolution = this._resolutions[level];
|
const realTileWidth = resolution * this.tileWidth;
|
const realTileHeight = resolution * this.tileHeight;
|
|
let xTileCoordinate = (webMercatorPosition.x - this._origin[0]) / resolution / this.tileWidth;
|
let yTileCoordinate = (this._origin[1] - webMercatorPosition.y) / resolution / this.tileHeight;
|
xTileCoordinate = Math.floor(xTileCoordinate);
|
yTileCoordinate = Math.floor(yTileCoordinate);
|
|
// const westFromOrigin = this._rectangleSouthwestInMeters.x - this._origin[0];
|
// const eastFromOrigin = this._rectangleNortheastInMeters.x - this._origin[0];
|
// const northFromOrigin = this._origin[1] - this._rectangleNortheastInMeters.y;
|
// const southFromOrigin = this._origin[1] - this._rectangleSouthwestInMeters.y;
|
// const xTileWidth = eastFromOrigin / xTiles;
|
// const yTileHeight = southFromOrigin / yTiles;
|
// let xTileMin = Math.floor(westFromOrigin / realTileWidth) | 0;
|
// if (xTileMin >= xTiles) {
|
// xTileMin = xTiles - 1;
|
// }
|
// let xTileMax = Math.floor(eastFromOrigin / realTileWidth) | 0;
|
// if ( xTileMax >= xTiles) {
|
// xTileMax = xTiles - 1;
|
// }
|
// let yTileMin = Math.floor(northFromOrigin / realTileHeight) | 0;
|
// if (yTileMin >= yTiles) {
|
// yTileMin = yTiles - 1;
|
// }
|
// let yTileMax = Math.floor(southFromOrigin / realTileHeight) | 0;
|
// if(yTileMax >= yTiles) {
|
// yTileMax = yTiles - 1;
|
// }
|
|
// const distanceFromWest = webMercatorPosition.x - this._origin[0];
|
// const distanceFromNorth = this._origin[1] - webMercatorPosition.y;
|
// let xTileCoordinate = (distanceFromWest / xTileWidth) | 0;
|
// if (xTileCoordinate < xTileMin) {
|
// xTileCoordinate = xTileMin;
|
// // return undefined;
|
// }
|
// if ( xTileCoordinate > xTileMax ) {
|
// xTileCoordinate = xTileMax;
|
// // return undefined;
|
// }
|
// if (xTileCoordinate >= xTiles) {
|
// xTileCoordinate = xTiles - 1;
|
// }
|
|
// let yTileCoordinate = (distanceFromNorth / yTileHeight) | 0;
|
// if (yTileCoordinate < yTileMin) {
|
// yTileCoordinate = yTileMin;
|
// // return undefined;
|
// }
|
// if (yTileCoordinate > yTileMax) {
|
// yTileCoordinate = yTileMax;
|
// // return undefined;
|
// }
|
// if (yTileCoordinate >= yTiles) {
|
// yTileCoordinate = yTiles - 1;
|
// }
|
|
if (!Cesium.defined(result)) {
|
return new Cesium.Cartesian2(xTileCoordinate, yTileCoordinate);
|
}
|
|
result.x = xTileCoordinate;
|
result.y = yTileCoordinate;
|
return result;
|
};
|
export default Bj2000TilingScheme;
|