Skip to content

Instantly share code, notes, and snippets.

@pksorensen
Created August 27, 2015 11:34
Show Gist options
  • Save pksorensen/253954c11ca3a48859fb to your computer and use it in GitHub Desktop.
Save pksorensen/253954c11ca3a48859fb to your computer and use it in GitHub Desktop.
work in progress of custom projection in cesium
proj4.defs("EPSG:25832", "+proj=utm +zone=32 +ellps=GRS80 +towgs84=0,0,0,0,0,0,0 +units=m +no_defs");
class Proj4WebMapProjection {
private _proj :transformer;
constructor(public ellipsoid = Cesium.Ellipsoid.WGS84, code = "EPSG:25832") {
this._proj = proj4(code);
}
project(cartographic:Cesium.Cartographic, result) {
var epgscustom = this._proj.forward([Cesium.Math.toDegrees(cartographic.longitude), Cesium.Math.toDegrees(cartographic.latitude)]);
if (!defined(result)) {
return new Cesium.Cartesian3(epgscustom[0], epgscustom[1], cartographic.height);
}
result.x = epgscustom[0];
result.y = epgscustom[1];
result.z = cartographic.height;
return result;
};
unproject(cartesian:Cesium.Cartesian3, result) {
var wgs84 = this._proj.inverse([cartesian.x,cartesian.y,cartesian.z]);
if (!defined(result)) {
return new Cesium.Cartographic(Cesium.Math.toRadians(wgs84[0]), Cesium.Math.toRadians(wgs84[1]), cartesian.z);
}
result.longitude = Cesium.Math.toRadians(wgs84[0]);
result.latitude = Cesium.Math.toRadians(wgs84[1]);
result.height = cartesian.z;
return result;
};
}
interface Epsg25832TilingSchemaOptions {
ellipsoid?;
numberOfLevelZeroTilesX?;
numberOfLevelZeroTilesY?;
rectangleSouthwestInMeters?;
rectangleNortheastInMeters?
}
class Epsg25832TilingSchema {
private _numberOfLevelZeroTilesX = 1;
private _numberOfLevelZeroTilesY = 1;
private _rectangleSouthwestInMeters: Cesium.Cartesian3|Cesium.Cartesian2 = new Cesium.Cartesian2;
private _rectangleNortheastInMeters :Cesium.Cartesian3|Cesium.Cartesian2 = new Cesium.Cartesian2;
ellipsoid: Cesium.Ellipsoid;
rectangle: Cesium.Rectangle;
projection: Cesium.MapProjection;
constructor(options: Epsg25832TilingSchemaOptions = { }) {
this.ellipsoid = Cesium.defaultValue(options.ellipsoid, Cesium.Ellipsoid.WGS84);
this._numberOfLevelZeroTilesX = Cesium.defaultValue(options.numberOfLevelZeroTilesX, 1);
this._numberOfLevelZeroTilesY = Cesium.defaultValue(options.numberOfLevelZeroTilesY, 1);
this.projection = new Proj4WebMapProjection(this.ellipsoid);
if (defined(options.rectangleSouthwestInMeters) &&
defined(options.rectangleNortheastInMeters)) {
this._rectangleSouthwestInMeters = options.rectangleSouthwestInMeters;
this._rectangleNortheastInMeters = options.rectangleNortheastInMeters;
} else {
throw new Cesium.DeveloperError("The rectangle should be given for the extend, and it should be fitted to the tile extent");
}
var southwest = this.projection.unproject(<Cesium.Cartesian3>this._rectangleSouthwestInMeters);
var northeast = this.projection.unproject(<Cesium.Cartesian3>this._rectangleNortheastInMeters);
this.rectangle = new Cesium.Rectangle(southwest.longitude, southwest.latitude,
northeast.longitude, northeast.latitude);
}
getNumberOfXTilesAtLevel(level) {
return this._numberOfLevelZeroTilesX << level;
};
getNumberOfYTilesAtLevel(level) {
return this._numberOfLevelZeroTilesY << level;
};
rectangleToNativeRectangle(rectangle, result) {
console.log(["rectangleToNativeRectangle", rectangle]);
var southwest = this.projection.project(Cesium.Rectangle.southwest(rectangle));
var northeast = this.projection.project(Cesium.Rectangle.northeast(rectangle));
if (!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;
};
tileXYToNativeRectangle(x, y, level, result?: Cesium.Rectangle) {
var xTiles = this.getNumberOfXTilesAtLevel(level);
var yTiles = this.getNumberOfYTilesAtLevel(level);
var xTileWidth = (this._rectangleNortheastInMeters.x - this._rectangleSouthwestInMeters.x) / xTiles;
var west = this._rectangleSouthwestInMeters.x + x * xTileWidth;
var east = this._rectangleSouthwestInMeters.x + (x + 1) * xTileWidth;
var yTileHeight = (this._rectangleNortheastInMeters.y - this._rectangleSouthwestInMeters.y) / yTiles;
var north = this._rectangleNortheastInMeters.y - y * yTileHeight;
var south = this._rectangleNortheastInMeters.y - (y + 1) * yTileHeight;
console.log(["tileXYToNativeRectangle", x, y, level,xTiles,yTiles,xTileWidth,yTileHeight,west,east,north,south]);
if (!defined(result)) {
return new Cesium.Rectangle(west, south, east, north);
}
result.west = west;
result.south = south;
result.east = east;
result.north = north;
return result;
};
tileXYToRectangle(x, y, level, result) {
var nativeRectangle = this.tileXYToNativeRectangle(x, y, level, result);
var southwest = this.projection.unproject(new Cesium.Cartesian3(nativeRectangle.west, nativeRectangle.south,0));
var northeast = this.projection.unproject(new Cesium.Cartesian3(nativeRectangle.east, nativeRectangle.north,0));
console.log(["tileXYToRectangle", x, y, level, Cesium.Math.toDegrees(southwest.longitude), Cesium.Math.toDegrees(southwest.latitude), Cesium.Math.toDegrees(northeast.longitude), Cesium.Math.toDegrees( northeast.latitude)]);
nativeRectangle.west = southwest.longitude;
nativeRectangle.south = southwest.latitude;
nativeRectangle.east = northeast.longitude ;
nativeRectangle.north = northeast.latitude;
return nativeRectangle;
};
skipfirst2 = 2; //Have to skip those two to ignore the guard in ImageProvider.
positionToTileXY(position:Cesium.Cartographic, level, result) {
console.log(["positionToTileXY", this.rectangle, Cesium.Math.toDegrees(position.longitude),Cesium.Math.toDegrees(position.latitude), level]);
if (this.skipfirst2 && this.skipfirst2-- > 0)
return new Cesium.Cartesian2(0, 0);
if (!Cesium.Rectangle.contains(this.rectangle, position)) {
// outside the bounds of the tiling scheme
return undefined;
}
var xTiles = this.getNumberOfXTilesAtLevel(level);
var yTiles = this.getNumberOfYTilesAtLevel(level);
var overallWidth = this._rectangleNortheastInMeters.x - this._rectangleSouthwestInMeters.x;
var xTileWidth = overallWidth / xTiles;
var overallHeight = this._rectangleNortheastInMeters.y - this._rectangleSouthwestInMeters.y;
var yTileHeight = overallHeight / yTiles;
var webMercatorPosition = this.projection.project(position);
var distanceFromWest = webMercatorPosition.x - this._rectangleSouthwestInMeters.x;
var distanceFromNorth = this._rectangleNortheastInMeters.y - webMercatorPosition.y;
var xTileCoordinate = distanceFromWest / xTileWidth | 0;
if (xTileCoordinate >= xTiles) {
xTileCoordinate = xTiles - 1;
}
var yTileCoordinate = distanceFromNorth / yTileHeight | 0;
if (yTileCoordinate >= yTiles) {
yTileCoordinate = yTiles - 1;
}
if (!defined(result)) {
return new Cesium.Cartesian2(xTileCoordinate, yTileCoordinate);
}
result.x = xTileCoordinate;
result.y = yTileCoordinate;
return result;
};
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment