diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 000000000..d3c7a4758 --- /dev/null +++ b/.gitmodules @@ -0,0 +1,6 @@ +[submodule "ol3"] + path = ol3 + url = https://github.com/openlayers/ol3.git +[submodule "cesium"] + path = cesium + url = https://github.com/AnalyticalGraphicsInc/cesium.git diff --git a/Cesium.externs.js b/Cesium.externs.js new file mode 100644 index 000000000..1082d57ad --- /dev/null +++ b/Cesium.externs.js @@ -0,0 +1,1751 @@ +/** + * @externs + * @see http://cesium.agi.com/ + */ +var Cesium = {}; + + + +/** + * @constructor + * @param {string} text + * @param {Object=} opt_description + * @return {HTMLCanvasElement} + */ +Cesium.prototype.writeTextToCanvas = function(text, opt_description) {}; + + + +/** + * @constructor + */ +Cesium.Billboard = function() {}; + + +/** + * @type {!Cesium.Cartesian3} + */ +Cesium.Billboard.prototype.position; + + +/** + * @type {boolean} + */ +Cesium.Billboard.prototype.show; + + +/** + * @type {number} + */ +Cesium.Billboard.prototype.scale; + + +/** + * @type {number} + */ +Cesium.Billboard.prototype.imageIndex; + + +/** + * @type {!Cesium.VerticalOrigin} + */ +Cesium.Billboard.prototype.verticalOrigin; + + +/** + * @constructor + */ +Cesium.VerticalOrigin = function() {}; + + +/** + * @type {!Cesium.VerticalOrigin} . + */ +Cesium.VerticalOrigin.TOP; + + +/** + * @type {!Cesium.VerticalOrigin} . + */ +Cesium.VerticalOrigin.CENTER; + + +/** + * @type {!Cesium.VerticalOrigin} . + */ +Cesium.VerticalOrigin.BOTTOM; + + + +/** + * @constructor + */ +Cesium.BillboardCollection = function() {}; + + +/** + * @param {Object=} opt_opts . + * @return {Cesium.Billboard} . + */ +Cesium.BillboardCollection.prototype.add = function(opt_opts) {}; + + +/** + * @param {Cesium.Billboard} what . + */ +Cesium.BillboardCollection.prototype.remove = function(what) {}; + + +/** + * @type {boolean} . + */ +Cesium.BillboardCollection.prototype.sizeReal; + + +/** + * @type {Cesium.TextureAtlas} + */ +Cesium.BillboardCollection.prototype.textureAtlas; + + + +/** + * @param {Object.} opts + * @constructor + */ +Cesium.TextureAtlas = function(opts) {}; + + +/** + * @param {Image} image . + */ +Cesium.TextureAtlas.prototype.addImage = function(image) {}; + + +/** + * @type {Array.} . + */ +Cesium.TextureAtlas.prototype.textureCoordinates; + + +/** + * @type {!Cesium.Texture} . + */ +Cesium.TextureAtlas.prototype.texture; + + + +/** + * @constructor + */ +Cesium.Texture = function() {}; + + +/** + * @type {number} . + */ +Cesium.Texture.prototype.width; + + +/** + * @type {number} . + */ +Cesium.Texture.prototype.height; + + + +/** + * @constructor + */ +Cesium.BoundingRectangle = function() {}; + + +/** + * @type {number} + */ +Cesium.BoundingRectangle.prototype.x; + + +/** + * @type {number} + */ +Cesium.BoundingRectangle.prototype.y; + + +/** + * @type {number} + */ +Cesium.BoundingRectangle.prototype.width; + + +/** + * @type {number} + */ +Cesium.BoundingRectangle.prototype.height; + + + +/** + * @constructor + */ +Cesium.Camera = function() {}; + + +/** + * @type {Cesium.Cartesian3} + */ +Cesium.Camera.prototype.direction; + + +/** + * @type {Cesium.PerspectiveFrustrum} + */ +Cesium.Camera.prototype.frustum; + + +/** + * @type {Cesium.Cartesian3} + */ +Cesium.Camera.prototype.position; + + +/** + * @type {Cesium.Cartesian3} + */ +Cesium.Camera.prototype.right; + + +/** + * @type {Cesium.Matrix4} + */ +Cesium.Camera.prototype.transform; + + +/** + * @type {Cesium.Cartesian3} + */ +Cesium.Camera.prototype.up; + + +/** + * @type {Cesium.Cartesian3} + */ +Cesium.Camera.prototype.constrainedAxis; + + +/** + * @type {Cesium.Cartographic} . + */ +Cesium.Camera.prototype.positionCartographic; + + +/** + * @type {Cesium.Cartesian3} . + */ +Cesium.Camera.prototype.positionWC; + + +/** + * @type {number} + */ +Cesium.Camera.prototype.heading; + + +/** + * @type {number} + */ +Cesium.Camera.prototype.tilt; + + +/** + * @param {!Cesium.Cartesian2} windowPosition + * @param {Cesium.Ray=} opt_result + * @return {!Cesium.Ray} + */ +Cesium.Camera.prototype.getPickRay = function(windowPosition, opt_result) {}; + + +/** + * @param {Cesium.Cartesian4} cartesian . + * @param {Cesium.Cartesian4=} opt_result . + * @return {Cesium.Cartesian4} . + */ +Cesium.Camera.prototype.worldToCameraCoordinates = function(cartesian, opt_result) {}; + + +/** + * @param {Cesium.Cartesian3} cartesian . + * @param {Cesium.Cartesian3=} opt_result . + * @return {Cesium.Cartesian3} . + */ +Cesium.Camera.prototype.worldToCameraCoordinatesPoint = function(cartesian, opt_result) {}; + + +/** + * @type {!Cesium.Matrix4} + */ +Cesium.Camera.prototype.viewMatrix; + + +/** + * @typedef {Object} + */ +Cesium.CameraEventType; + + +/** + * @type {Cesium.CameraEventType} + */ +Cesium.CameraEventType.LEFT_DRAG; + + +/** + * @type {Cesium.CameraEventType} + */ +Cesium.CameraEventType.MIDDLE_DRAG; + + +/** + * @type {Cesium.CameraEventType} + */ +Cesium.CameraEventType.PINCH; + + +/** + * @type {Cesium.CameraEventType} + */ +Cesium.CameraEventType.RIGHT_DRAG; + + +/** + * @type {Cesium.CameraEventType} + */ +Cesium.CameraEventType.WHEEL; + + +/** + * @typedef {Object} + */ +Cesium.KeyboardEventModifier; + + +/** + * @type {Cesium.KeyboardEventModifier} + */ +Cesium.KeyboardEventModifier.ALT; + + +/** + * @type {Cesium.KeyboardEventModifier} + */ +Cesium.KeyboardEventModifier.CTRL; + + +/** + * @type {Cesium.KeyboardEventModifier} + */ +Cesium.KeyboardEventModifier.SHIFT; + + + + +/** + * @param {Object} canvas . + * @constructor + */ +Cesium.CameraEventAggregator = function(canvas) {}; + + +/** + * @param {Object} type + * @param {Object=} opt_mod + * @return {boolean} . + */ +Cesium.CameraEventAggregator.prototype.isMoving = function(type, opt_mod) {}; + + +/** + * @param {Object} type + * @param {Object=} opt_mod + * @return {Object} . + */ +Cesium.CameraEventAggregator.prototype.getMovement = function(type, opt_mod) {}; + + +/** + * @param {Object} type + * @param {Object=} opt_mod + * @return {Object} . + */ +Cesium.CameraEventAggregator.prototype.getLastMovement = function(type, opt_mod) {}; + + +/** + * @param {Object} type + * @param {Object=} opt_mod + * @return {boolean} . + */ +Cesium.CameraEventAggregator.prototype.isButtonDown = function(type, opt_mod) {}; + + +/** + * @return {boolean} . + */ +Cesium.CameraEventAggregator.prototype.anyButtonDown = function() {}; + + +/** + * @param {Object} type + * @param {Object=} opt_mod + * @return {number} . + */ +Cesium.CameraEventAggregator.prototype.getButtonPressTime = function(type, opt_mod) {}; + + +/** + * @param {Object} type + * @param {Object=} opt_mod + * @return {number} . + */ +Cesium.CameraEventAggregator.prototype.getButtonReleaseTime = function(type, opt_mod) {}; + + +/** + * @return {boolean} . + */ +Cesium.CameraEventAggregator.prototype.isDestroyed = function() {} + + +/** + */ +Cesium.CameraEventAggregator.prototype.destroy = function() {}; + + +/** + * @param {Cesium.Cartographic} carto + */ +Cesium.Camera.prototype.setPositionCartographic = function(carto) {}; + + +/** + * @param {Cesium.Cartesian3} eye . + * @param {Cesium.Cartesian3} target . + * @param {Cesium.Cartesian3} up . + */ +Cesium.Camera.prototype.lookAt = function(eye, target, up) {}; + + +/** + * @param {number} amount . + */ +Cesium.Camera.prototype.twistLeft = function(amount) {}; + +/** + * @param {number} amount . + */ +Cesium.Camera.prototype.twistRight = function(amount) {}; + +/** + * @param {number} amount . + */ +Cesium.Camera.prototype.lookLeft = function(amount) {}; + +/** + * @param {number} amount . + */ +Cesium.Camera.prototype.lookRight = function(amount) {}; + +/** + * @param {number} amount . + */ +Cesium.Camera.prototype.lookUp = function(amount) {}; + +/** + * @param {number} amount . + */ +Cesium.Camera.prototype.lookDown = function(amount) {}; + +/** + * @param {number} amount . + */ +Cesium.Camera.prototype.moveForward = function(amount) {}; + +/** + * @param {number} amount . + */ +Cesium.Camera.prototype.moveBackward = function(amount) {}; + +/** + * @param {!Cesium.Cartesian2} windowPos . + * @return {!Cesium.Cartesian3} . + */ +Cesium.Camera.prototype.pickEllipsoid = function(windowPos) {}; + + +/** + * @constructor + * @param {number} x + * @param {number} y + */ +Cesium.Cartesian2 = function(x, y) {}; + + +/** + * @type {number} + */ +Cesium.Cartesian2.prototype.x; + + +/** + * @type {number} + */ +Cesium.Cartesian2.prototype.y; + + + +/** + * @constructor + * @param {number=} opt_x + * @param {number=} opt_y + * @param {number=} opt_z + */ +Cesium.Cartesian3 = function(opt_x, opt_y, opt_z) {}; + + +/** + * @type {!Cesium.Cartesian3} + */ +Cesium.Cartesian3.UNIT_X; + + +/** + * @type {!Cesium.Cartesian3} + */ +Cesium.Cartesian3.UNIT_Y; + + +/** + * @type {!Cesium.Cartesian3} + */ +Cesium.Cartesian3.UNIT_Z; + + +/** + * @type {!Cesium.Cartesian3} + */ +Cesium.Cartesian3.ZERO; + + +/** + * @type {number} + */ +Cesium.Cartesian3.prototype.x; + + +/** + * @type {number} + */ +Cesium.Cartesian3.prototype.y; + + +/** + * @type {number} + */ +Cesium.Cartesian3.prototype.z; + + +/** + * @param {Cesium.Cartesian3} left + * @return {number} + */ +Cesium.Cartesian3.magnitude = function(left) {}; + + +/** + * @param {Cesium.Cartesian3} left + * @param {Cesium.Cartesian3} right + * @param {Cesium.Cartesian3=} opt_result + * @return {!Cesium.Cartesian3} + */ +Cesium.Cartesian3.add = function(left, right, opt_result) {}; + + +/** + * @param {Cesium.Cartesian3} left + * @param {Cesium.Cartesian3} right + * @param {Cesium.Cartesian3=} opt_result + * @return {!Cesium.Cartesian3} + */ +Cesium.Cartesian3.subtract = function(left, right, opt_result) {}; + + +/** + * @param {Cesium.Cartesian3} cartesian + * @param {Cesium.Cartesian3} result + * @return {!Cesium.Cartesian3} + */ +Cesium.Cartesian3.normalize = function(cartesian, result) {}; + + +/** + * @param {Cesium.Cartesian3} cartesian + * @param {Cesium.Cartesian3} result + * @return {!Cesium.Cartesian3} + */ +Cesium.Cartesian3.negate = function(cartesian, result) {}; + + +/** + * @param {Cesium.Cartesian3} left + * @param {Cesium.Cartesian3} right + * @param {Cesium.Cartesian3=} opt_result + * @return {!Cesium.Cartesian3} + */ +Cesium.Cartesian3.cross = function(left, right, opt_result) {}; + + +/** + * @param {Cesium.Cartesian3} left + * @param {Cesium.Cartesian3} right + * @return {number} + */ +Cesium.Cartesian3.dot = function(left, right) {}; + + +/** + * @param {Cesium.Cartesian3} left + * @param {Cesium.Cartesian3} right + * @return {number} + */ +Cesium.Cartesian3.distance = function(left, right) {}; + + +/** + * @param {Cesium.Cartesian3} left + * @param {Cesium.Cartesian3} right + * @return {number} + */ +Cesium.Cartesian3.angleBetween = function(left, right) {}; + + + +/** + * @constructor + * @param {number=} opt_x + * @param {number=} opt_y + * @param {number=} opt_z + * @param {number=} opt_w + */ +Cesium.Cartesian4 = function(opt_x, opt_y, opt_z, opt_w) {}; + + +/** + * @type {number} + */ +Cesium.Cartesian4.prototype.x; + + +/** + * @type {number} + */ +Cesium.Cartesian4.prototype.y; + + +/** + * @type {number} + */ +Cesium.Cartesian4.prototype.z; + +/** + * @type {number} + */ +Cesium.Cartesian4.prototype.w; + + + +/** + * @constructor + * @param {number=} longitude + * @param {number=} latitude + * @param {number=} height + */ +Cesium.Cartographic = function(longitude, latitude, height) {}; + + +/** + * @type {number} + */ +Cesium.Cartographic.prototype.longitude; + + +/** + * @type {number} + */ +Cesium.Cartographic.prototype.latitude; + + +/** + * @type {number} + */ +Cesium.Cartographic.prototype.height; + + +/** + * @param {Cesium.Cartographic=} opt_result + * @return {!Cesium.Cartographic} + */ +Cesium.Cartographic.prototype.clone = function(opt_result) {}; + + +/** + * @param {number} lat . + * @param {number} lng . + * @return {!Cesium.Cartographic} + */ +Cesium.Cartographic.fromDegrees = function(lat, lng) {}; + + +/** + * @constructor + */ +Cesium.Ray = function() {}; + + +/** + * @constructor + * @param {Cesium.Ellipsoid} ellipsoid + */ +Cesium.Globe = function(ellipsoid) {}; + + +/** + * @type {Cesium.Ellipsoid} + */ +Cesium.Globe.prototype.ellipsoid; + + +/** + * @param {!Cesium.Ray} ray + * @param {!Cesium.Scene} scene + * @param {Cesium.Cartesian3=} opt_result + * @return {Cesium.Cartesian3|undefined} + */ +Cesium.Globe.prototype.pick = function(ray, scene, opt_result) {}; + + + +/** + * @param {Object.=} opt_opts + * @constructor + */ +Cesium.Polygon = function(opt_opts) {}; + + +/** + * @type {!Array.} + */ +Cesium.Polygon.prototype.positions; + + +/** + * @type {!Cesium.Material} material . + */ +Cesium.Polygon.prototype.material; + + +/** + * @type {boolean} . + */ +Cesium.Polygon.prototype.show; + + +/** + */ +Cesium.Polygon.prototype.update = function() {}; + + + +/** + * @constructor + */ +Cesium.PolylineCollection = function() {}; + + +/** + * @param {Object=} opt_opts . + * @return {!Cesium.Polyline} . + */ +Cesium.PolylineCollection.prototype.add = function(opt_opts) {}; + + +/** + * @constructor + */ +Cesium.Material = function() {}; + + +/** + * @type {!Object} . + */ +Cesium.Material.prototype.uniforms; + + + + +/** + * @constructor + */ +Cesium.Polyline = function() {}; + + +/** + * @type {!Array.} + */ +Cesium.Polyline.prototype.positions; + + +/** + * @type {!Cesium.Material} + */ +Cesium.Polyline.prototype.material; + + +/** + * @type {number} + */ +Cesium.Polyline.prototype.width; + + + +/** + * @constructor + */ +Cesium.PrimitiveCollection = function() {}; + + +/** + * @param {!Cesium.Polygon|!Cesium.PolylineCollection|!Cesium.BillboardCollection|!Cesium.PrimitiveCollection} poly . + */ +Cesium.PrimitiveCollection.prototype.add = function(poly) {}; + + +/** + * @param {!Cesium.Polygon|!Cesium.PolylineCollection|!Cesium.BillboardCollection|!Cesium.PrimitiveCollection} poly . + */ +Cesium.PrimitiveCollection.prototype.raiseToTop = function(poly) {}; + + +/** + * @param {!Cesium.Polygon|!Cesium.PolylineCollection|!Cesium.BillboardCollection|!Cesium.PrimitiveCollection} poly . + */ +Cesium.PrimitiveCollection.prototype.remove = function(poly) {}; + + +/** + * @type {number} + */ +Cesium.PrimitiveCollection.prototype.length; + + + +/** + * @constructor + * @param {string} proxy + */ +Cesium.DefaultProxy = function(proxy) {}; + + + +/** + * @constructor + */ +Cesium.Event = function() {}; + + + +/** + * @constructor + * @param {string=} opt_text + * @param {string=} opt_imageUrl + * @param {string=} opt_link + */ +Cesium.Credit = function(opt_text, opt_imageUrl, opt_link) {}; + + + +/** + * @constructor + */ +Cesium.GeographicTilingScheme = function() {}; + + +/** + * @type {Cesium.Rectangle} + */ +Cesium.GeographicTilingScheme.prototype.rectangle; + + + +/** + * @constructor + * @param {Cesium.ImageryProvider} imageryProvider + */ +Cesium.ImageryLayer = function(imageryProvider) {}; + +/** + * @type {Cesium.ImageryProvider} + */ +Cesium.ImageryLayer.prototype.imageryProvider; + + +/** + * @param {string} url . + * @return {Object} . + */ +Cesium.ImageryLayer.prototype.loadImage = function(url) {}; + + + +/** + * @constructor + */ +Cesium.ImageryLayerCollection = function() {}; + + +/** + * @param {Cesium.ImageryProvider} provider + */ +Cesium.ImageryLayerCollection.prototype.addImageryProvider = function(provider) {}; + + +/** + * @type {number} + */ +Cesium.ImageryLayerCollection.prototype.length; + + +/** + * @param {number} index + * @return {Cesium.ImageryLayer} layer + */ +Cesium.ImageryLayerCollection.prototype.get = function(index) {}; + + +/** + * @param {Cesium.ImageryLayer} layer + * @param {number=} opt_index + */ +Cesium.ImageryLayerCollection.prototype.add = function(layer, opt_index) {}; + + +/** + * @param {Cesium.ImageryLayer} layer + * @param {boolean} destroy + */ +Cesium.ImageryLayerCollection.prototype.remove = function(layer, destroy) {}; + + + +/** + * @constructor + */ +Cesium.ImageryProvider = function() {}; + + +/** + * @return {boolean} + */ +Cesium.ImageryProvider.prototype.isReady = function() {}; + + +/** + * @type {Cesium.Rectangle} + */ +Cesium.ImageryProvider.prototype.rectangle; + + +/** + * @type {number} + */ +Cesium.ImageryProvider.prototype.tileWidth; + + +/** + * @type {number} + */ +Cesium.ImageryProvider.prototype.tileHeight; + + +/** + * @type {number} + */ +Cesium.ImageryProvider.prototype.minimumLevel; + + +/** + * @type {number} + */ +Cesium.ImageryProvider.prototype.maximumLevel; + + +/** + * @type {string} + */ +Cesium.ImageryProvider.prototype.url; + + +/** + * //@return {TilingScheme} The tiling scheme. + * // TODO + * //@return {Cesium.GeographicTilingScheme} + * @type {Cesium.WebMercatorTilingScheme} + */ +Cesium.ImageryProvider.prototype.tilingScheme; + + +/** + * //@returns {TileDiscardPolicy} The discard policy. + * // TODO + * @type {undefined} + */ +Cesium.ImageryProvider.prototype.tileDiscardPolicy; + + +/** + * @type {Cesium.Event} The event. + */ +Cesium.ImageryProvider.prototype.errorEvent; + + +/** + * @return {Cesium.Credit} + */ +Cesium.ImageryProvider.prototype.credit; + + +/** + * @param {number} x The tile X coordinate. + * @param {number} y The tile Y coordinate. + * @param {number} level The tile level. + * @return {Object|undefined} + */ +Cesium.ImageryProvider.prototype.requestImage = function(x, y, level) {}; + + +/** + * @param {Cesium.ImageryProvider} imageryProvider + * @param {string} url + * @return {Object} + */ +Cesium.ImageryProvider.loadImage = function(imageryProvider, url) {}; + + +/** + * @constructor + * @extends {Cesium.ImageryProvider} + */ +Cesium.BingMapsImageryProvider = function(options) {}; + + +/** + * @constructor + * @param {Cesium.Cartesian3} radii + */ +Cesium.Ellipsoid = function(radii) {}; + + +/** + * @type {Cesium.Ellipsoid} + */ +Cesium.Ellipsoid.WGS84; + + +/** + * @param {Cesium.Cartographic} cartographic + * @param {Cesium.Cartesian3=} opt_result + * @return {!Cesium.Cartesian3} + */ +Cesium.Ellipsoid.prototype.cartographicToCartesian = function(cartographic, opt_result) {}; + + +/** + * @param {!Array.} cartographic + * @param {!Array.=} opt_result + * @return {!Array.} + */ +Cesium.Ellipsoid.prototype.cartographicArrayToCartesianArray = function(cartographic, opt_result) {}; + + +/** + * @param {Cesium.Cartesian3} cartesian + * @param {Cesium.Cartographic=} opt_result + * @return {Cesium.Cartographic} + */ +Cesium.Ellipsoid.prototype.cartesianToCartographic = function(cartesian, opt_result) {}; + + +/** + * @param {!Cesium.Cartesian3} position . + * @param {Cesium.Cartesian3=} opt_result . + * @return {!Cesium.Cartesian3} + */ +Cesium.Ellipsoid.prototype.transformPositionToScaledSpace = function(position, opt_result) {}; + + +/** + * @param {Cesium.Cartesian3} cartesian + * @param {Cesium.Cartesian3} result + * @return {Cesium.Cartesian3} + */ +Cesium.Ellipsoid.prototype.geocentricSurfaceNormal = function(cartesian, result) {}; + + +/** + * @constructor + * @param {number} west + * @param {number} south + * @param {number} east + * @param {number} north + */ +Cesium.Rectangle = function(west, south, east, north) {}; + +/** @type {number} */ +Cesium.Rectangle.prototype.west; + +/** @type {number} */ +Cesium.Rectangle.prototype.south; + +/** @type {number} */ +Cesium.Rectangle.prototype.east; + +/** @type {number} */ +Cesium.Rectangle.prototype.north; + +/** @type {!Cesium.Rectangle} */ +Cesium.Rectangle.MAX_VALUE; + + + +/** + * @constructor + */ +Cesium.FeatureDetection = function() {}; + + +/** + * @return {boolean} + */ +Cesium.FeatureDetection.supportsCrossOriginImagery = function() {}; + + + +/** + * @constructor + */ +Cesium.Math = function() {}; + + +/** + * @param {number} value + * @param {number} min + * @param {number} max + * @return {number} + */ +Cesium.Math.clamp = function(value, min, max) {}; + + +/** + * @type {number} + */ +Cesium.Math.PI_OVER_TWO; + + +/** + * @type {number} + */ +Cesium.Math.TWO_PI; + + + +/** + * @constructor + */ +Cesium.Matrix3 = function() {}; + + +/** + * @param {Cesium.Quaternion} quaternion + */ +Cesium.Matrix3.fromQuaternion = function(quaternion) {}; + + +/** + * @param {Cesium.Matrix3} matrix + * @param {Cesium.Cartesian3} cartesian + * @param {Cesium.Cartesian3} result + * @return {Cesium.Cartesian3} + */ +Cesium.Matrix3.multiplyByVector = function(matrix, cartesian, result) {}; + + + +/** + * @constructor + * @param {number=} opt_a00 . + * @param {number=} opt_a10 . + * @param {number=} opt_a20 . + * @param {number=} opt_a30 . + * @param {number=} opt_a01 . + * @param {number=} opt_a11 . + * @param {number=} opt_a21 . + * @param {number=} opt_a31 . + * @param {number=} opt_a02 . + * @param {number=} opt_a12 . + * @param {number=} opt_a22 . + * @param {number=} opt_a32 . + * @param {number=} opt_a03 . + * @param {number=} opt_a13 . + * @param {number=} opt_a23 . + * @param {number=} opt_a33 . + */ +Cesium.Matrix4 = function(opt_a00, opt_a10, opt_a20, opt_a30, + opt_a01, opt_a11, opt_a21, opt_a31, + opt_a02, opt_a12, opt_a22, opt_a32, + opt_a03, opt_a13, opt_a23, opt_a33) {}; + + +/** + * @param {Cesium.Cartesian3} translation . + * @param {Cesium.Matrix4=} opt_result . + * @return {Cesium.Matrix4} . + */ +Cesium.Matrix4.fromTranslation = function(translation, opt_result) {}; + + +/** + * @param {Cesium.Matrix4} left . + * @param {Cesium.Matrix4} right . + * @param {Cesium.Matrix4=} opt_result . + * @return {Cesium.Matrix4} . + */ +Cesium.Matrix4.multiply = function(left, right, opt_result) {}; + + +/** + * @param {Cesium.Matrix4} matrix . + * @return {boolean} . + */ +Cesium.Matrix4.prototype.equals = function(matrix) {}; + + +/** + * @param {Cesium.Matrix4=} opt_result + */ +Cesium.Matrix4.prototype.clone = function(opt_result) {}; + + +/** + * @param {Cesium.Matrix4} matrix . + * @param {Cesium.Cartesian3} point . + * @param {Cesium.Cartesian3=} opt_result . + * @return {Cesium.Cartesian3} . + */ +Cesium.Matrix4.multiplyByPoint = function(matrix, point, opt_result) {}; + + +/** + * @param {Cesium.Matrix4} matrix . + * @param {Cesium.Cartesian4} point . + * @param {Cesium.Cartesian4=} opt_result . + * @return {Cesium.Cartesian4} . + */ +Cesium.Matrix4.multiplyByVector = function(matrix, point, opt_result) {}; + + +/** + * @param {Cesium.Matrix4} matrix . + * @return {Array.} . + */ +Cesium.Matrix4.toArray = function(matrix) {}; + + + +/** + * @constructor + * @param {number=} opt_r . + * @param {number=} opt_g . + * @param {number=} opt_b . + * @param {number=} opt_a . + */ +Cesium.Color = function(opt_r, opt_g, opt_b, opt_a) {}; + + + +/** + * @constructor + * @param {Object=} opt_opts + * @extends {Cesium.ImageryProvider} + */ +Cesium.OpenStreetMapImageryProvider = function(opt_opts) {}; + + + +/** + * @constructor + * @param {Object} options + * @extends {Cesium.ImageryProvider} + */ +Cesium.WebMapServiceImageryProvider = function(options) {}; + + + +/** + * @constructor + */ +Cesium.PerspectiveFrustrum = function() {}; + + +/** + * @type {number} + */ +Cesium.PerspectiveFrustrum.prototype.aspectRatio; + + +/** + * @type {number} + */ +Cesium.PerspectiveFrustrum.prototype.far; + + +/** + * @type {number} + */ +Cesium.PerspectiveFrustrum.prototype.fov; + + +/** + * @type {number} + */ +Cesium.PerspectiveFrustrum.prototype.near; + + +/** + * @type {!Cesium.Matrix4} + */ +Cesium.PerspectiveFrustrum.prototype.projectionMatrix; + + +/** + * @param {!Cesium.Cartesian2} canvasDim . + * @param {number=} opt_dist . + * @return {!Cesium.Cartesian2} + */ +Cesium.PerspectiveFrustrum.prototype.getPixelSize = function(canvasDim, opt_dist) {}; + + + +/** + * @constructor + */ +Cesium.Quaternion = function() {}; + + +/** + * @param {Cesium.Cartesian3} axis + * @param {number} angle + */ +Cesium.Quaternion.fromAxisAngle = function(axis, angle) {}; + + + + +/** + * @constructor + */ +Cesium.Context = function() {}; + + +/** + * @type {!Cesium.UniformState} + */ +Cesium.Context.prototype.uniformState; + + + +/** + * @constructor + * @param {{canvas: HTMLCanvasElement, + contextOptions: (Object|undefined), + creditContainer: (Element|undefined), + mapProjection: (Object|undefined), + scene3DOnly: (boolean|undefined)}} opt_opts + */ +Cesium.Scene = function(opt_opts) {}; + + +/** + * @type {!HTMLCanvasElement} + */ +Cesium.Scene.prototype.canvas; + + +/** + * @type {!Cesium.Context} + */ +Cesium.Scene.prototype.context; + + +/** + */ +Cesium.Scene.prototype.initializeFrame = function() {}; + + +/** + */ +Cesium.Scene.prototype.render = function() {}; + + +/** + * @type {Cesium.ScreenSpaceCameraController} + */ +Cesium.Scene.prototype.screenSpaceCameraController; + + +/** + */ +Cesium.Scene.prototype.destroy = function() {}; + + +/** + * @type {!Cesium.Camera} + */ +Cesium.Scene.prototype.camera; + + +/** + * @type {Cesium.Globe} + */ +Cesium.Scene.prototype.globe; + + +/** + * @type {Cesium.ImageryLayerCollection} + */ +Cesium.Scene.prototype.imageryLayers; + + +/** + * @type {Cesium.SceneMode} + */ +Cesium.Scene.prototype.mode; + + +/** + * @type {Cesium.PrimitiveCollection} + */ +Cesium.Scene.prototype.primitives; + + +/** + * @type {Object} + */ +Cesium.Scene.prototype.scene2D; + + +/** + * @type {Cesium.SkyBox} + */ +Cesium.Scene.prototype.skyBox; + + +/** + * @type {Cesium.SkyAtmosphere} + */ +Cesium.Scene.prototype.skyAtmosphere; + + + +/** + * @constructor + */ +Cesium.SceneMode = function() {}; + + +/** + * @type {Cesium.SceneMode} + */ +Cesium.SceneMode.COLOMBUS_VIEW; + + +/** + * @type {Cesium.SceneMode} + */ +Cesium.SceneMode.MORPHING; + + +/** + * @type {Cesium.SceneMode} + */ +Cesium.SceneMode.SCENE2D; + + +/** + * @type {Cesium.SceneMode} + */ +Cesium.SceneMode.SCENE3D; + + + +/** + * @constructor + */ +Cesium.UniformState = function() {}; + + +/** + * @type {!Cesium.Matrix4} + */ +Cesium.UniformState.prototype.modelViewProjection; + + + +/** + * @constructor + */ +Cesium.ScreenSpaceCameraController = function() {}; + + +/** + * @type {boolean} + */ +Cesium.ScreenSpaceCameraController.prototype.enableRotate; + +/** + * @type {boolean} + */ +Cesium.ScreenSpaceCameraController.prototype.enableLook; + +/** + * @type {boolean} + */ +Cesium.ScreenSpaceCameraController.prototype.enableTilt; + +/** + * @type {boolean} + */ +Cesium.ScreenSpaceCameraController.prototype.enableZoom; + +/** + * @type {number} + */ +Cesium.ScreenSpaceCameraController.prototype.inertiaSpin; + +/** + * @type {number} + */ +Cesium.ScreenSpaceCameraController.prototype.ineartiaTranslate; + +/** + * @type {number} + */ +Cesium.ScreenSpaceCameraController.prototype.inertiaZoom; + +/** + * Helper typedef. + * @typedef {{eventType: Cesium.CameraEventType, + modifier: Cesium.KeyboardEventModifier}|Cesium.CameraEventType} + */ +Cesium._SingleEventType; + +/** + * @type {Cesium._SingleEventType|Array.|undefined} + */ +Cesium.ScreenSpaceCameraController.prototype.lookEventTypes; + +/** + * @type {Cesium._SingleEventType|Array.|undefined} + */ +Cesium.ScreenSpaceCameraController.prototype.rotateEventTypes; + +/** + * @type {Cesium._SingleEventType|Array.|undefined} + */ +Cesium.ScreenSpaceCameraController.prototype.tiltEventTypes; + +/** + * @type {Cesium._SingleEventType|Array.|undefined} + */ +Cesium.ScreenSpaceCameraController.prototype.translateEventTypes; + +/** + * @type {Cesium._SingleEventType|Array.|undefined} + */ +Cesium.ScreenSpaceCameraController.prototype.zoomEventTypes; + + + +/** + * @constructor + * @param {!Element} canvas . + */ +Cesium.ScreenSpaceEventHandler = function(canvas) {}; + + +/** + * @param {Function} callback . + * @param {Cesium.ScreenSpaceEventType} type . + */ +Cesium.ScreenSpaceEventHandler.prototype.setInputAction = function(callback, type) {}; + + +/** @constructor */ +Cesium.ScreenSpaceEventType = function() {}; + +/** @type {Cesium.ScreenSpaceEventType} */ +Cesium.ScreenSpaceEventType.LEFT_DOWN; + +/** @type {Cesium.ScreenSpaceEventType} */ +Cesium.ScreenSpaceEventType.RIGHT_DOWN; + +/** @type {Cesium.ScreenSpaceEventType} */ +Cesium.ScreenSpaceEventType.MIDDLE_DOWN; + +/** @type {Cesium.ScreenSpaceEventType} */ +Cesium.ScreenSpaceEventType.WHEEL; + +/** @type {Cesium.ScreenSpaceEventType} */ +Cesium.ScreenSpaceEventType.PINCH_START; + + + +/** + * @constructor + * @extends {Cesium.ImageryProvider} + * @param {Cesium.SingleTileImageryProviderOptions} options + */ +Cesium.SingleTileImageryProvider = function(options) {}; + + +/** + * @typedef {{url: string}} + */ +Cesium.SingleTileImageryProviderOptions; + + + +/** + * @constructor + * @extends {Cesium.ImageryProvider} + * @param {Object} options + */ +Cesium.TileMapServiceImageryProvider = function(options) {}; + + + +/** + * @constructor + */ +Cesium.SkyAtmosphere = function() {}; + + +/** + * @constructor + * @param {{sources: {positiveX: string, negativeX: string, + * positiveY: string, negativeY: string, + * positiveZ: string, negativeZ: string}}} options + */ +Cesium.SkyBox = function(options) {}; + + + +/** + * @interface + * HACK This type definition prevents positiveX and friends + * to be renamed when passing options to Cesium.SkyBox. There + * must be a better way to do this! + */ +Cesium.SkyBoxOptions_ = function() {}; + + +/** + * @type {string} + */ +Cesium.SkyBoxOptions_.prototype.positiveX; + + +/** + * @type {string} + */ +Cesium.SkyBoxOptions_.prototype.negativeX; + + +/** + * @type {string} + */ +Cesium.SkyBoxOptions_.prototype.positiveY; + + +/** + * @type {string} + */ +Cesium.SkyBoxOptions_.prototype.negativeY; + + +/** + * @type {string} + */ +Cesium.SkyBoxOptions_.prototype.positiveZ; + + +/** + * @type {string} + */ +Cesium.SkyBoxOptions_.prototype.negativeZ; + + + +/** + * @constructor + * @param {Cesium.Ellipsoid} ellipsoid + */ +Cesium.WebMercatorProjection = function(ellipsoid) {}; + + +/** + * @param {Cesium.Cartographic} cartographic + * @return {Cesium.Cartesian3} + */ +Cesium.WebMercatorProjection.prototype.project = function(cartographic) {}; + + +/** + * @param {Cesium.Cartesian3} cartesian + * @return {Cesium.Cartographic} + */ +Cesium.WebMercatorProjection.prototype.unproject = function(cartesian) {}; + + + +/** + * @constructor + */ +Cesium.WebMercatorTilingScheme = function() {}; + + +/** + * @type {Cesium.Rectangle} + */ +//Cesium.WebMercatorTilingScheme.prototype.rectangle; + + +/** @constructor */ +Cesium.BingMapsStyle = function() {}; + +/** @type {!Cesium.BingMapsStyle} */ +Cesium.BingMapsStyle.AERIAL; + +/** @type {!Cesium.BingMapsStyle} */ +Cesium.BingMapsStyle.AERIAL_WITH_LABELS; + +/** @type {!Cesium.BingMapsStyle} */ +Cesium.BingMapsStyle.ROAD; diff --git a/Makefile b/Makefile new file mode 100644 index 000000000..5aef08bc1 --- /dev/null +++ b/Makefile @@ -0,0 +1,28 @@ +PLOVR = ./plovr-81ed862.jar + +.PHONY: ol3, cesium, build + +all: serve + +ol3: + @echo --- Runing OL3 compilation ... + cd ./ol3 && python build.py + node tasks/generate-externs.js build/ol-externs.js +cesium: + @echo --- Runing Cesium compilation ... + cd cesium && "./Tools/apache-ant-1.8.2/bin/ant" minify + +serve: ol3, cesium + @echo --- Serving ol3cesium-debug.json... + java -jar $(PLOVR) serve ol3cesium-debug.json +build: ol3 + @echo --- Compiling ol3cesium.json... + java -jar $(PLOVR) build ol3cesium.json > deploy/ol3cesium.js + +lint: + fixjsstyle --strict -r ./src + gjslint --strict -r ./src +server: + @echo --- Starting the webserver... +# java -jar $(PLOVR) soyweb --dir . + python -m SimpleHTTPServer 9811 diff --git a/cesium b/cesium new file mode 160000 index 000000000..d82679120 --- /dev/null +++ b/cesium @@ -0,0 +1 @@ +Subproject commit d82679120ed6b62c357f47a7efa9001d8fcafbd1 diff --git a/examples/exports.html b/examples/exports.html new file mode 100644 index 000000000..46359f13f --- /dev/null +++ b/examples/exports.html @@ -0,0 +1,74 @@ + + + + + + + ol3cesium exported methods example + + + + + + + + + + + +
+
+ +
+ + + + +
+ + + + + diff --git a/examples/main.html b/examples/main.html new file mode 100644 index 000000000..fb6f79817 --- /dev/null +++ b/examples/main.html @@ -0,0 +1,50 @@ + + + + + + + ol3cesium example + + + + + + + + + + + +
+ + + diff --git a/examples/sidebyside.html b/examples/sidebyside.html new file mode 100644 index 000000000..344552921 --- /dev/null +++ b/examples/sidebyside.html @@ -0,0 +1,56 @@ + + + + + + + ol3cesium side-by-side example + + + + + + + + + + + +
+
+ + + + diff --git a/ol3 b/ol3 new file mode 160000 index 000000000..f468239e7 --- /dev/null +++ b/ol3 @@ -0,0 +1 @@ +Subproject commit f468239e7170c16fbb20b9b99f38e6888d49fd3f diff --git a/ol3cesium-debug.json b/ol3cesium-debug.json new file mode 100644 index 000000000..011901e83 --- /dev/null +++ b/ol3cesium-debug.json @@ -0,0 +1,13 @@ +{ + "id": "ol3cesium-debug", + "inherits": "ol3cesium.json", + + "define": { + "goog.DEBUG": true + }, + + "mode": "ADVANCED", + + "pretty-print": true, + "debug": true +} diff --git a/ol3cesium.json b/ol3cesium.json new file mode 100644 index 000000000..69da31ee8 --- /dev/null +++ b/ol3cesium.json @@ -0,0 +1,42 @@ +{ + "id": "ol3cesium", + + "inputs": ['src/ol3cesium.js'], + "paths": ['src'], + + "externs": [ + "ol3/build/ol-externs.js", + "Cesium.externs.js" + ], + + "define": { + // "goog.dom.ASSUME_STANDARDS_MODE": true, + "goog.DEBUG": false + }, + + "mode": "ADVANCED", + "level": "VERBOSE", + + // "pretty-print": true, + // "debug": true, + + "checks": { + // Unfortunately, the Closure Library violates these in many places. + // "accessControls": "ERROR", + // "visibility": "ERROR" + + "checkTypes": "OFF", + "checkRegExp": "ERROR", + "checkVars": "ERROR", + "deprecated": "ERROR", + "fileoverviewTags": "ERROR", + "invalidCasts": "ERROR", + "missingProperties": "ERROR", + "nonStandardJsDocs": "OFF", + "undefinedVars": "ERROR" + }, + + "output-wrapper": "(function(){%output%})();", + + "jsdoc-html-output-path": "." +} diff --git a/src/camera.js b/src/camera.js new file mode 100644 index 000000000..53ee8676a --- /dev/null +++ b/src/camera.js @@ -0,0 +1,449 @@ +goog.provide('olcs.Camera'); + +goog.require('goog.events'); + + + +/** + * This object takes care of additional 3d-specific properties of the view and + * ensures proper synchronization with the underlying raw Cesium.Camera object. + * @param {!Cesium.Scene} scene + * @param {!ol.View} view + * @constructor + */ +olcs.Camera = function(scene, view) { + /** + * @type {!Cesium.Scene} + * @private + */ + this.scene_ = scene; + + /** + * @type {!HTMLCanvasElement} + * @private + */ + this.canvas_ = scene.canvas; + + /** + * @type {!Cesium.Camera} + * @private + */ + this.cam_ = scene.camera; + + /** + * @type {!ol.View} + * @private + */ + this.view_ = view; + + /** + * @type {ol.TransformFunction} + * @private + */ + this.toLonLat_ = ol.proj.getTransform(this.view_.getProjection(), + 'EPSG:4326'); + + /** + * @type {ol.TransformFunction} + * @private + */ + this.fromLonLat_ = ol.proj.getTransform('EPSG:4326', + this.view_.getProjection()); + + /** + * 0 -- topdown, PI/2 -- the horizon + * @type {number} + * @private + */ + this.tilt_ = 0; + + /** + * @type {number} + * @private + */ + this.distance_ = 0; + + /** + * @type {?Cesium.Matrix4} + * @private + */ + this.lastCameraViewMatrix_ = null; + + /** + * This is used to discard change events on view caused by updateView method. + * @type {boolean} + * @private + */ + this.viewUpdateInProgress_ = false; + + goog.events.listen(/** @type {!goog.events.EventTarget} */(this.view_), + ['change:center', 'change:resolution', 'change:rotation'], function(e) { + if (!this.viewUpdateInProgress_) { + this.readFromView(); + } + }, false, this); + +}; + + +/** + * @param {number} heading In radians. + */ +olcs.Camera.prototype.setHeading = function(heading) { + this.view_.setRotation(heading); +}; + + +/** + * @return {number} Heading in radians. + */ +olcs.Camera.prototype.getHeading = function() { + var rotation = this.view_.getRotation(); + return goog.isDef(rotation) ? rotation : 0; +}; + + +/** + * @param {number} tilt In radians. + */ +olcs.Camera.prototype.setTilt = function(tilt) { + this.tilt_ = tilt; + this.updateCamera_(); +}; + + +/** + * @return {number} Tilt in radians. + */ +olcs.Camera.prototype.getTilt = function() { + return this.tilt_; +}; + + +/** + * @param {number} distance In meters. + */ +olcs.Camera.prototype.setDistance = function(distance) { + this.distance_ = distance; + this.updateCamera_(); + this.updateView(); +}; + + +/** + * @return {number} Distance in meters. + */ +olcs.Camera.prototype.getDistance = function() { + return this.distance_; +}; + + +/** + * Shortcut for ol.View.setCenter(). + * @param {!ol.Coordinate} center Same projection as the ol.View. + */ +olcs.Camera.prototype.setCenter = function(center) { + this.view_.setCenter(center); +}; + + +/** + * Shortcut for ol.View.getCenter(). + * @return {!ol.Coordinate} Same projection as the ol.View. + */ +olcs.Camera.prototype.getCenter = function() { + return this.view_.getCenter(); +}; + + +/** + * Sets the position of the camera. + * @param {!ol.Coordinate} position Same projection as the ol.View. + */ +olcs.Camera.prototype.setPosition = function(position) { + var ll = this.toLonLat_(position); + + var carto = new Cesium.Cartographic(goog.math.toRadians(ll[0]), + goog.math.toRadians(ll[1]), + this.getAltitude()); + + this.cam_.position = Cesium.Ellipsoid.WGS84.cartographicToCartesian(carto); + this.updateView(); +}; + + +/** + * Calculates position under the camera. + * @return {!ol.Coordinate} Same projection as the ol.View. + */ +olcs.Camera.prototype.getPosition = function() { + var carto = Cesium.Ellipsoid.WGS84.cartesianToCartographic( + this.cam_.position); + + return this.fromLonLat_([goog.math.toDegrees(carto.longitude), + goog.math.toDegrees(carto.latitude)]); +}; + + +/** + * @param {number} altitude In meters. + */ +olcs.Camera.prototype.setAltitude = function(altitude) { + var carto = Cesium.Ellipsoid.WGS84.cartesianToCartographic( + this.cam_.position); + carto.height = altitude; + this.cam_.position = Cesium.Ellipsoid.WGS84.cartographicToCartesian(carto); + + this.updateView(); +}; + + +/** + * @return {number} Altitude in meters. + */ +olcs.Camera.prototype.getAltitude = function() { + var carto = Cesium.Ellipsoid.WGS84.cartesianToCartographic( + this.cam_.position); + + return carto.height; +}; + + +/** + * Rotates the camera to point at the specified target. + * @param {!ol.Coordinate} position Same projection as the ol.View. + */ +olcs.Camera.prototype.lookAt = function(position) { + var ll = this.toLonLat_(position); + + var carto = new Cesium.Cartographic(goog.math.toRadians(ll[0]), + goog.math.toRadians(ll[1])); + if (this.scene_.globe) { + var height = this.scene_.globe.getHeight(carto); + carto.height = goog.isDef(height) ? height : 0; + } + var carte = Cesium.Ellipsoid.WGS84.cartographicToCartesian(carto); + + var pos = this.cam_.position; + var up = Cesium.Ellipsoid.WGS84.geocentricSurfaceNormal( + pos, new Cesium.Cartesian3()); + this.cam_.lookAt(pos, carte, up); + + this.updateView(); +}; + + +/** + * Updates the state of the underlying Cesium.Camera + * according to the current values of the properties. + * @private + */ +olcs.Camera.prototype.updateCamera_ = function() { + var ll = this.toLonLat_(this.view_.getCenter()); + + var carto = new Cesium.Cartographic(goog.math.toRadians(ll[0]), + goog.math.toRadians(ll[1])); + if (this.scene_.globe) { + var height = this.scene_.globe.getHeight(carto); + carto.height = goog.isDef(height) ? height : 0; + } + this.cam_.setPositionCartographic(carto); + + var rotation = this.view_.getRotation(); + this.cam_.twistLeft(goog.isDef(rotation) ? rotation : 0); + if (this.tilt_) { + this.cam_.lookUp(this.tilt_); + } + this.cam_.moveBackward(this.distance_); + + this.checkCameraChange(true); +}; + + +/** + * Calculates the values of the properties from the current ol.View state. + */ +olcs.Camera.prototype.readFromView = function() { + var resolution = this.view_.getResolution(); + this.distance_ = this.calcDistanceForResolution_( + goog.isDef(resolution) ? resolution : 0, + goog.math.toRadians(this.toLonLat_(this.view_.getCenter())[1])); + + this.updateCamera_(); +}; + + +/** + * Calculates the values of the properties from the current Cesium.Camera state. + * Modifies the center, resolution and rotation properties of the view. + */ +olcs.Camera.prototype.updateView = function() { + this.viewUpdateInProgress_ = true; + + // target & distance + var center = new Cesium.Cartesian2(this.canvas_.width / 2, + this.canvas_.height / 2); + var target = this.scene_.globe.pick(this.cam_.getPickRay(center), + this.scene_); + + var bestTarget = target; + if (!bestTarget) { + //TODO: how to handle this properly ? + var carto = this.cam_.positionCartographic.clone(); + if (this.scene_.globe) { + var height = this.scene_.globe.getHeight(carto); + carto.height = goog.isDef(height) ? height : 0; + } + bestTarget = Cesium.Ellipsoid.WGS84.cartographicToCartesian(carto); + } + this.distance_ = Cesium.Cartesian3.distance(bestTarget, this.cam_.position); + var bestTargetCartographic = + Cesium.Ellipsoid.WGS84.cartesianToCartographic(bestTarget); + this.view_.setCenter(this.fromLonLat_([ + goog.math.toDegrees(bestTargetCartographic.longitude), + goog.math.toDegrees(bestTargetCartographic.latitude)])); + + // resolution + this.view_.setResolution( + this.calcResolutionForDistance_(this.distance_, + bestTargetCartographic ? bestTargetCartographic.latitude : 0)); + + + /* + * Since we are positioning the target, the values of heading and tilt + * need to be calculated _at the target_. + */ + if (target) { + var pos = this.cam_.position; + + // normal to the ellipsoid at the target + var targetNormal = new Cesium.Cartesian3(); + this.scene_.globe.ellipsoid.geocentricSurfaceNormal(target, targetNormal); + + // vector from the target to the camera + var targetToCamera = new Cesium.Cartesian3(); + Cesium.Cartesian3.subtract(pos, target, targetToCamera); + Cesium.Cartesian3.normalize(targetToCamera, targetToCamera); + + + // HEADING + var normal = new Cesium.Cartesian3(-target.y, target.x, 0); + var heading = Cesium.Cartesian3.angleBetween(this.cam_.right, normal); + var orientation = Cesium.Cartesian3.cross(target, this.cam_.up, + new Cesium.Cartesian3()).z; + + this.view_.setRotation((orientation < 0 ? heading : -heading)); + + // TILT + var tiltAngle = Math.acos( + Cesium.Cartesian3.dot(targetNormal, targetToCamera)); + this.tilt_ = isNaN(tiltAngle) ? 0 : tiltAngle; + } else { + // fallback when there is no target + this.view_.setRotation(this.cam_.heading); + this.tilt_ = -this.cam_.tilt + Math.PI / 2; + } + + this.viewUpdateInProgress_ = false; +}; + + +/** + * Check if the underlying camera state has changed and ensure synchronization. + * @param {boolean=} opt_dontSync Do not synchronize the view. + */ +olcs.Camera.prototype.checkCameraChange = function(opt_dontSync) { + var viewMatrix = this.cam_.viewMatrix; + if (!this.lastCameraViewMatrix_ || + !this.lastCameraViewMatrix_.equals(viewMatrix)) { + this.lastCameraViewMatrix_ = viewMatrix.clone(); + if (opt_dontSync !== true) { + this.updateView(); + } + } +}; + + +/** + * @param {number} resolution + * @param {number} latitude + * @return {number} The calculated distance. + * @private + */ +olcs.Camera.prototype.calcDistanceForResolution_ = function(resolution, + latitude) { + var fovy = this.cam_.frustum.fov; // vertical field of view + var metersPerUnit = + ol.proj.METERS_PER_UNIT[this.view_.getProjection().getUnits()]; + + var visibleMapUnits = resolution * this.canvas_.width; + var relativeCircumference = Math.cos(Math.abs(latitude)); + var visibleMeters = visibleMapUnits * metersPerUnit * relativeCircumference; + + // distance required to view the calculated length in meters + // + // fovy/2 + // |\ + // x | \ + // |--\ + // visibleMeters/2 + var requiredDistance = (visibleMeters / 2) / Math.tan(fovy / 2); + + return requiredDistance; +}; + + +/** + * @param {number} distance + * @param {number} latitude + * @return {number} The calculated resolution. + * @private + */ +olcs.Camera.prototype.calcResolutionForDistance_ = function(distance, + latitude) { + // See the reverse calculation (calcDistanceForResolution_) for details + var fovy = this.cam_.frustum.fov; + var metersPerUnit = + ol.proj.METERS_PER_UNIT[this.view_.getProjection().getUnits()]; + + var visibleMeters = 2 * distance * Math.tan(fovy / 2); + var relativeCircumference = Math.cos(Math.abs(latitude)); + var visibleMapUnits = visibleMeters / metersPerUnit / relativeCircumference; + var resolution = visibleMapUnits / this.canvas_.width; + + return resolution; +}; + + + +goog.exportSymbol('olcs.Camera', + olcs.Camera); +goog.exportProperty(olcs.Camera.prototype, 'getHeading', + olcs.Camera.prototype.getHeading); +goog.exportProperty(olcs.Camera.prototype, 'setHeading', + olcs.Camera.prototype.setHeading); +goog.exportProperty(olcs.Camera.prototype, 'getTilt', + olcs.Camera.prototype.getTilt); +goog.exportProperty(olcs.Camera.prototype, 'setTilt', + olcs.Camera.prototype.setTilt); +goog.exportProperty(olcs.Camera.prototype, 'getDistance', + olcs.Camera.prototype.getDistance); +goog.exportProperty(olcs.Camera.prototype, 'setDistance', + olcs.Camera.prototype.setDistance); +goog.exportProperty(olcs.Camera.prototype, 'getCenter', + olcs.Camera.prototype.getCenter); +goog.exportProperty(olcs.Camera.prototype, 'setCenter', + olcs.Camera.prototype.setCenter); +goog.exportProperty(olcs.Camera.prototype, 'getPosition', + olcs.Camera.prototype.getPosition); +goog.exportProperty(olcs.Camera.prototype, 'setPosition', + olcs.Camera.prototype.setPosition); +goog.exportProperty(olcs.Camera.prototype, 'getAltitude', + olcs.Camera.prototype.getAltitude); +goog.exportProperty(olcs.Camera.prototype, 'setAltitude', + olcs.Camera.prototype.setAltitude); +goog.exportProperty(olcs.Camera.prototype, 'lookAt', + olcs.Camera.prototype.lookAt); + +goog.exportProperty(olcs.Camera.prototype, 'updateView', + olcs.Camera.prototype.updateView); diff --git a/src/ol3cesium.js b/src/ol3cesium.js new file mode 100644 index 000000000..d68469d77 --- /dev/null +++ b/src/ol3cesium.js @@ -0,0 +1,207 @@ +goog.provide('olcs.OLCesium'); + +goog.require('goog.dom'); +goog.require('goog.events'); + +goog.require('olcs.Camera'); + + + +/** + * @param {!ol.Map} map + * @param {Element|string=} opt_target Target element for the Cesium container. + * @constructor + */ +olcs.OLCesium = function(map, opt_target) { + /** + * @type {!ol.Map} + * @private + */ + this.map_ = map; + + var fillArea = 'position:absolute;top:0;left:0;width:100%;height:100%;'; + + /** + * @type {!Element} + * @private + */ + this.container_ = goog.dom.createDom(goog.dom.TagName.DIV, + {style: fillArea + 'visibility:hidden;'}); + + var targetElement = goog.dom.getElement(opt_target || null); + if (targetElement) { + goog.dom.appendChild(targetElement, this.container_); + } else { + var vp = this.map_.getViewport(); + var oc = goog.dom.getElementByClass('ol-overlaycontainer', vp); + if (oc) { + goog.dom.insertSiblingBefore(this.container_, oc); + } + } + + /** + * Whether the Cesium container is placed over the ol map. + * @type {boolean} + * @private + */ + this.isOverMap_ = !goog.isDefAndNotNull(targetElement); + + /** + * @type {!HTMLCanvasElement} + * @private + */ + this.canvas_ = /** @type {!HTMLCanvasElement} */ + (goog.dom.createDom(goog.dom.TagName.CANVAS, {style: fillArea})); + goog.dom.appendChild(this.container_, this.canvas_); + + /** + * @type {boolean} + * @private + */ + this.enabled_ = false; + + /** + * @type {!Array.} + * @private + */ + this.pausedInteractions_ = []; + + /** + * @type {!Cesium.Scene} + * @private + */ + this.scene_ = new Cesium.Scene({ + canvas: this.canvas_, + scene3DOnly: true + }); + + var sscc = this.scene_.screenSpaceCameraController; + sscc.inertiaSpin = 0; + sscc.ineartiaTranslate = 0; + sscc.inertiaZoom = 0; + + sscc.tiltEventTypes.push({ + 'eventType': Cesium.CameraEventType.LEFT_DRAG, + 'modifier': Cesium.KeyboardEventModifier.SHIFT + }); + + sscc.enableLook = false; + + this.scene_.camera.constrainedAxis = Cesium.Cartesian3.UNIT_Z; + + /** + * @type {!olcs.Camera} + * @private + */ + this.camera_ = new olcs.Camera(this.scene_, this.map_.getView()); + + //TODO: handle change of view + + /** + * @type {!Cesium.Globe} + * @private + */ + this.globe_ = new Cesium.Globe(Cesium.Ellipsoid.WGS84); + this.scene_.globe = this.globe_; + this.scene_.skyAtmosphere = new Cesium.SkyAtmosphere(); + + var osm = new Cesium.OpenStreetMapImageryProvider(); + this.scene_.imageryLayers.addImageryProvider(osm); + + this.camera_.readFromView(); + + var tick = goog.bind(function() { + this.scene_.initializeFrame(); + this.scene_.render(); + this.camera_.checkCameraChange(); + Cesium.requestAnimationFrame(tick); + }, this); + Cesium.requestAnimationFrame(tick); +}; + + +/** + * @private + */ +olcs.OLCesium.prototype.handleResize_ = function() { + var width = this.canvas_.clientWidth; + var height = this.canvas_.clientHeight; + + if (this.canvas_.width === width && this.canvas_.height === height) { + return; + } + + this.canvas_.width = width; + this.canvas_.height = height; + this.scene_.camera.frustum.aspectRatio = width / height; +}; + + +/** + * @return {!olcs.Camera} + */ +olcs.OLCesium.prototype.getCamera = function() { + return this.camera_; +}; + + +/** + * @return {!Cesium.Scene} + */ +olcs.OLCesium.prototype.getCesiumScene = function() { + return this.scene_; +}; + + +/** + * @return {boolean} + */ +olcs.OLCesium.prototype.getEnabled = function() { + return this.enabled_; +}; + + +/** + * Enables/disables the Cesium. + * This modifies the visibility style of the container element. + * @param {boolean=} opt_enable + */ +olcs.OLCesium.prototype.setEnabled = function(opt_enable) { + this.enabled_ = opt_enable !== false; + + // some Cesium operations are operating with canvas.clientWidth, + // so we can't remove it from DOM or even make display:none; + this.container_.style.visibility = this.enabled_ ? 'visible' : 'hidden'; + if (this.enabled_) { + if (this.isOverMap_) { + var interactions = this.map_.getInteractions(); + interactions.forEach(function(el, i, arr) { + this.pausedInteractions_.push(el); + }, this); + interactions.clear(); + } + this.handleResize_(); + this.camera_.readFromView(); + } else { + if (this.isOverMap_) { + var interactions = this.map_.getInteractions(); + goog.array.forEach(this.pausedInteractions_, function(el, i, arr) { + interactions.push(el); + }, this); + this.pausedInteractions_.length = 0; + } + + this.camera_.updateView(); + } +}; + + +goog.exportSymbol('olcs.OLCesium', olcs.OLCesium); +goog.exportProperty(olcs.OLCesium.prototype, 'getEnabled', + olcs.OLCesium.prototype.getEnabled); +goog.exportProperty(olcs.OLCesium.prototype, 'getCamera', + olcs.OLCesium.prototype.getCamera); +goog.exportProperty(olcs.OLCesium.prototype, 'getCesiumScene', + olcs.OLCesium.prototype.getCesiumScene); +goog.exportProperty(olcs.OLCesium.prototype, 'setEnabled', + olcs.OLCesium.prototype.setEnabled);