Created
August 27, 2015 11:34
-
-
Save pksorensen/253954c11ca3a48859fb to your computer and use it in GitHub Desktop.
work in progress of custom projection in cesium
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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