Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
51 changes: 51 additions & 0 deletions Apps/Sandcastle/gallery/Rotatable 2D Map.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, minimum-scale=1, user-scalable=no">
<meta name="description" content="Configure viewer to make the 2D map rotatable.">
<meta name="cesium-sandcastle-labels" content="Beginner, Showcases">
<title>Cesium Demo</title>
<script type="text/javascript" src="../Sandcastle-header.js"></script>
<script type="text/javascript" src="../../../ThirdParty/requirejs-2.1.20/require.js"></script>
<script type="text/javascript">
require.config({
baseUrl : '../../../Source',
waitSeconds : 60
});
</script>
</head>
<body class="sandcastle-loading" data-sandcastle-bucket="bucket-requirejs.html">
<style>
@import url(../templates/bucket.css);
</style>
<div id="cesiumContainer" class="fullSize"></div>
<div id="loadingOverlay"><h1>Loading...</h1></div>
<div id="toolbar"></div>
<script id="cesium_sandcastle_script">
function startup(Cesium) {
'use strict';
//Sandcastle_Begin
var viewer = new Cesium.Viewer('cesiumContainer', {
sceneMode : Cesium.SceneMode.SCENE2D,
mapMode2D : Cesium.MapMode2D.ROTATE
});

viewer.scene.camera.setView({
destination : Cesium.Cartesian3.fromDegrees(-73.0, 42.0, 50000000.0),
orientation : {
heading : Cesium.Math.toRadians(-45.0)
}
});
//Sandcastle_End
Sandcastle.finishedLoading();
}
if (typeof Cesium !== "undefined") {
startup(Cesium);
} else if (typeof require === "function") {
require(["Cesium"], startup);
}
</script>
</body>
</html>
Binary file added Apps/Sandcastle/gallery/Rotatable 2D Map.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
5 changes: 5 additions & 0 deletions CHANGES.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,11 @@
Change Log
==========

### 1.23 - 2016-07-01

* Add a `rotatable2D` option to to `Scene`, `CesiumWidget` and `Viewer` to enable a rotatable map in 2D. [#3897](https://github.com/AnalyticalGraphicsInc/cesium/issues/3897)
* `Camera.setView` and `Camera.flyTo` will now use the `orientation.heading` parameter in 2D if the map is rotatable.

### 1.22 - 2016-06-01

* Breaking changes
Expand Down
104 changes: 64 additions & 40 deletions Source/Scene/Camera.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ define([
'../Core/Rectangle',
'../Core/Transforms',
'./CameraFlightPath',
'./MapMode2D',
'./PerspectiveFrustum',
'./SceneMode'
], function(
Expand Down Expand Up @@ -51,6 +52,7 @@ define([
Rectangle,
Transforms,
CameraFlightPath,
MapMode2D,
PerspectiveFrustum,
SceneMode) {
'use strict';
Expand Down Expand Up @@ -186,18 +188,11 @@ define([
this.constrainedAxis = undefined;
/**
* The factor multiplied by the the map size used to determine where to clamp the camera position
* when translating across the surface. The default is 1.5. Only valid for 2D and Columbus view.
* when zooming out from the surface. The default is 1.5. Only valid for 2D and the map is rotatable.
* @type {Number}
* @default 1.5
*/
this.maximumTranslateFactor = 1.5;
/**
* The factor multiplied by the the map size used to determine where to clamp the camera position
* when zooming out from the surface. The default is 2.5. Only valid for 2D.
* @type {Number}
* @default 2.5
*/
this.maximumZoomFactor = 2.5;
this.maximumZoomFactor = 1.5;

this._moveStart = new Event();
this._moveEnd = new Event();
Expand Down Expand Up @@ -624,7 +619,7 @@ define([
* @readonly
*/
heading : {
get : function () {
get : function() {
if (this._mode !== SceneMode.MORPHING) {
var ellipsoid = this._projection.ellipsoid;

Expand Down Expand Up @@ -743,8 +738,7 @@ define([
var frustum = this._max2Dfrustum = this.frustum.clone();

//>>includeStart('debug', pragmas.debug);
if (!defined(frustum.left) || !defined(frustum.right) ||
!defined(frustum.top) || !defined(frustum.bottom)) {
if (!defined(frustum.left) || !defined(frustum.right) || !defined(frustum.top) || !defined(frustum.bottom)) {
throw new DeveloperError('The camera frustum is expected to be orthographic for 2D camera control.');
}
//>>includeEnd('debug');
Expand Down Expand Up @@ -831,7 +825,10 @@ define([
camera._setTransform(currentTransform);
}

function setView2D(camera, position, convert) {
function setView2D(camera, position, heading, convert) {
var pitch = -CesiumMath.PI_OVER_TWO;
var roll = 0.0;

var currentTransform = Matrix4.clone(camera.transform, scratchSetViewTransform1);
camera._setTransform(Matrix4.IDENTITY);

Expand All @@ -857,6 +854,14 @@ define([
}
}

if (camera._scene.mapMode2D === MapMode2D.ROTATE) {
var rotQuat = Quaternion.fromHeadingPitchRoll(heading - CesiumMath.PI_OVER_TWO, pitch, roll, scratchSetViewQuaternion);
var rotMat = Matrix3.fromQuaternion(rotQuat, scratchSetViewMatrix3);

Matrix3.getColumn(rotMat, 2, camera.up);
Cartesian3.cross(camera.direction, camera.up, camera.right);
}

camera._setTransform(currentTransform);
}

Expand Down Expand Up @@ -895,7 +900,7 @@ define([
pitch : undefined,
roll : undefined
},
convert: undefined,
convert : undefined,
endTransform : undefined
};

Expand All @@ -906,7 +911,7 @@ define([
* @param {Cartesian3|Rectangle} [options.destination] The final position of the camera in WGS84 (world) coordinates or a rectangle that would be visible from a top-down view.
* @param {Object} [options.orientation] An object that contains either direction and up properties or heading, pith and roll properties. By default, the direction will point
* towards the center of the frame in 3D and in the negative z direction in Columbus view. The up direction will point towards local north in 3D and in the positive
* y direction in Columbus view. Orientation is not used in 2D.
* y direction in Columbus view. Orientation is not used in 2D when in infinite scrolling mode.
* @param {Matrix4} [options.endTransform] Transform matrix representing the reference frame of the camera.
*
* @example
Expand Down Expand Up @@ -980,7 +985,7 @@ define([
if (mode === SceneMode.SCENE3D) {
setView3D(this, destination, heading, pitch, roll);
} else if (mode === SceneMode.SCENE2D) {
setView2D(this, destination, convert);
setView2D(this, destination, heading, convert);
} else {
setViewCV(this, destination, heading, pitch, roll, convert);
}
Expand Down Expand Up @@ -1052,7 +1057,7 @@ define([
}
//>>includeEnd('debug');

if (!defined(result)){
if (!defined(result)) {
result = new Cartesian4();
}
updateMembers(this);
Expand All @@ -1073,7 +1078,7 @@ define([
}
//>>includeEnd('debug');

if (!defined(result)){
if (!defined(result)) {
result = new Cartesian3();
}
updateMembers(this);
Expand All @@ -1094,7 +1099,7 @@ define([
}
//>>includeEnd('debug');

if (!defined(result)){
if (!defined(result)) {
result = new Cartesian3();
}
updateMembers(this);
Expand All @@ -1115,7 +1120,7 @@ define([
}
//>>includeEnd('debug');

if (!defined(result)){
if (!defined(result)) {
result = new Cartesian4();
}
updateMembers(this);
Expand All @@ -1136,7 +1141,7 @@ define([
}
//>>includeEnd('debug');

if (!defined(result)){
if (!defined(result)) {
result = new Cartesian3();
}
updateMembers(this);
Expand All @@ -1157,28 +1162,40 @@ define([
}
//>>includeEnd('debug');

if (!defined(result)){
if (!defined(result)) {
result = new Cartesian3();
}
updateMembers(this);
return Matrix4.multiplyByPointAsVector(this._actualTransform, cartesian, result);
};

function clampMove2D(camera, position) {
var maxX = camera._maxCoord.x;
if (position.x > maxX) {
position.x = position.x - maxX * 2.0;
var rotatable2D = camera._scene.mapMode2D === MapMode2D.ROTATE;
var maxProjectedX = camera._maxCoord.x;
var maxProjectedY = camera._maxCoord.y;

var minX;
var maxX;
if (rotatable2D) {
maxX = maxProjectedX;
minX = -maxX;
} else {
maxX = position.x - maxProjectedX * 2.0;
minX = position.x + maxProjectedX * 2.0;
}
if (position.x < -maxX) {
position.x = position.x + maxX * 2.0;

if (position.x > maxProjectedX) {
position.x = maxX;
}
if (position.x < -maxProjectedX) {
position.x = minX;
}

var maxY = camera._maxCoord.y;
if (position.y > maxY) {
position.y = maxY;
if (position.y > maxProjectedY) {
position.y = maxProjectedY;
}
if (position.y < -maxY) {
position.y = -maxY;
if (position.y < -maxProjectedY) {
position.y = -maxProjectedY;
}
}

Expand Down Expand Up @@ -1536,6 +1553,10 @@ define([
var newLeft = frustum.left + amount;

var maxRight = camera._maxCoord.x;
if (camera._scene.mapMode2D === MapMode2D.ROTATE) {
maxRight *= camera.maximumZoomFactor;
}

if (newRight > maxRight) {
newRight = maxRight;
newLeft = -maxRight;
Expand Down Expand Up @@ -1602,7 +1623,7 @@ define([
} else if (this._mode === SceneMode.COLUMBUS_VIEW) {
return Math.abs(this.position.z);
} else if (this._mode === SceneMode.SCENE2D) {
return Math.max(this.frustum.right - this.frustum.left, this.frustum.top - this.frustum.bottom);
return Math.max(this.frustum.right - this.frustum.left, this.frustum.top - this.frustum.bottom);
}
};

Expand Down Expand Up @@ -1779,15 +1800,19 @@ define([
var viewRectangle3DSouthCenter = new Cartesian3();
var viewRectangle3DCenter = new Cartesian3();
var viewRectangle3DEquator = new Cartesian3();
var defaultRF = {direction: new Cartesian3(), right: new Cartesian3(), up: new Cartesian3()};
var defaultRF = {
direction : new Cartesian3(),
right : new Cartesian3(),
up : new Cartesian3()
};
var viewRectangle3DEllipsoidGeodesic;

function computeD(direction, upOrRight, corner, tanThetaOrPhi) {
var opposite = Math.abs(Cartesian3.dot(upOrRight, corner));
return opposite / tanThetaOrPhi - Cartesian3.dot(direction, corner);
}

function rectangleCameraPosition3D (camera, rectangle, result, updateCamera) {
function rectangleCameraPosition3D(camera, rectangle, result, updateCamera) {
var ellipsoid = camera._projection.ellipsoid;
var cameraRF = updateCamera ? camera : defaultRF;

Expand Down Expand Up @@ -1944,7 +1969,7 @@ define([
var viewRectangle2DCartographic = new Cartographic();
var viewRectangle2DNorthEast = new Cartesian3();
var viewRectangle2DSouthWest = new Cartesian3();
function rectangleCameraPosition2D (camera, rectangle, result) {
function rectangleCameraPosition2D(camera, rectangle, result) {
var projection = camera._projection;
if (rectangle.west > rectangle.east) {
rectangle = Rectangle.MAX_VALUE;
Expand Down Expand Up @@ -2050,7 +2075,7 @@ define([
var cart = projection.unproject(new Cartesian3(result.y, result.z, 0.0));

if (cart.latitude < -CesiumMath.PI_OVER_TWO || cart.latitude > CesiumMath.PI_OVER_TWO ||
cart.longitude < - Math.PI || cart.longitude > Math.PI) {
cart.longitude < -Math.PI || cart.longitude > Math.PI) {
return undefined;
}

Expand Down Expand Up @@ -2316,7 +2341,6 @@ define([
return undefined;
};


var scratchFlyToDestination = new Cartesian3();
var scratchFlyToCarto = new Cartographic();
var newOptions = {
Expand All @@ -2339,7 +2363,7 @@ define([
* @param {Cartesian3|Rectangle} options.destination The final position of the camera in WGS84 (world) coordinates or a rectangle that would be visible from a top-down view.
* @param {Object} [options.orientation] An object that contains either direction and up properties or heading, pith and roll properties. By default, the direction will point
* towards the center of the frame in 3D and in the negative z direction in Columbus view. The up direction will point towards local north in 3D and in the positive
* y direction in Columbus view. Orientation is not used in 2D.
* y direction in Columbus view. Orientation is not used in 2D when in infinite scrolling mode.
* @param {Number} [options.duration] The duration of the flight in seconds. If omitted, Cesium attempts to calculate an ideal duration based on the distance to be traveled by the flight.
* @param {Camera~FlightCompleteCallback} [options.complete] The function to execute when the flight is complete.
* @param {Camera~FlightCancelledCallback} [options.cancel] The function to execute if the flight is cancelled.
Expand Down Expand Up @@ -2407,7 +2431,7 @@ define([
setViewOptions.convert = options.convert;
setViewOptions.endTransform = options.endTransform;
this.setView(setViewOptions);
if (typeof options.complete === 'function'){
if (typeof options.complete === 'function') {
options.complete();
}
return;
Expand Down
7 changes: 7 additions & 0 deletions Source/Scene/CameraFlightPath.js
Original file line number Diff line number Diff line change
Expand Up @@ -192,13 +192,20 @@ define([
var camera = scene.camera;

var start = Cartesian3.clone(camera.position, scratchStart);
var startHeading = adjustAngleForLERP(camera.heading, heading);

var startHeight = camera.frustum.right - camera.frustum.left;
var heightFunction = createHeightFunction(camera, destination, startHeight, destination.z, optionAltitude);

function update(value) {
var time = value.time / duration;

camera.setView({
orientation: {
heading : CesiumMath.lerp(startHeading, heading, time)
}
});

Cartesian2.lerp(start, destination, time, camera.position);

var zoom = heightFunction(time);
Expand Down
Loading