/
SceneTransforms.js
151 lines (129 loc) · 5.47 KB
/
SceneTransforms.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
/*global define*/
define([
'../Core/defaultValue',
'../Core/DeveloperError',
'../Core/Cartographic',
'../Core/Cartesian2',
'../Core/Cartesian3',
'../Core/Cartesian4',
'../Core/Matrix4',
'../Core/BoundingRectangle',
'../Core/Math',
'./SceneMode'
],
function(
defaultValue,
DeveloperError,
Cartographic,
Cartesian2,
Cartesian3,
Cartesian4,
Matrix4,
BoundingRectangle,
CesiumMath,
SceneMode) {
"use strict";
/**
* Functions that do scene-dependent transforms between rendering-related coordinate systems.
*
* @exports SceneTransforms
*/
var SceneTransforms = {};
var actualPosition = new Cartesian3();
var positionCC = new Cartesian4();
/**
* Transforms a position in WGS84 coordinates to window coordinates. This is commonly used to place an
* HTML element at the same screen position as an object in the scene.
*
* @memberof SceneTransforms
*
* @param {Scene} scene The scene.
* @param {Cartesian3} position The position in WGS84 (world) coordinates.
* @param {Cartesian2} [result=undefined] An optional object to return the input position transformed to window coordinates.
*
* @return {Cartesian2} The modified result parameter or a new Cartesian3 instance if one was not provided. This may be <code>undefined</code> if the input position is near the center of the ellipsoid.
*
* @exception {DeveloperError} scene is required.
* @exception {DeveloperError} position is required.
*
* @example
* // Output the window position of longitude/latitude (0, 0) every time the mouse moves.
* var scene = widget.scene;
* var ellipsoid = widget.centralBody.getEllipsoid();
* var position = ellipsoid.cartographicToCartesian(new Cartographic(0.0, 0.0));
* var handler = new Cesium.ScreenSpaceEventHandler(scene.getCanvas());
* handler.setInputAction(function(movement) {
* console.log(Cesium.SceneTransforms.wgs84ToWindowCoordinates(scene, position));
* }, Cesium.ScreenSpaceEventType.MOUSE_MOVE);
*/
SceneTransforms.wgs84ToWindowCoordinates = function(scene, position, result) {
if (typeof scene === 'undefined') {
throw new DeveloperError('scene is required.');
}
if (typeof position === 'undefined') {
throw new DeveloperError('position is required.');
}
// Transform for 3D, 2D, or Columbus view
SceneTransforms.computeActualWgs84Position(scene.getFrameState(), position, actualPosition);
if (typeof actualPosition === 'undefined') {
result = undefined;
return undefined;
}
// View-projection matrix to transform from world coordinates to clip coordinates
var viewProjection = scene.getUniformState().getViewProjection();
viewProjection.multiplyByPoint(actualPosition, positionCC);
return SceneTransforms.clipToWindowCoordinates(scene.getCanvas(), positionCC, result);
};
var projectedPosition = new Cartesian3();
var positionInCartographic = new Cartographic();
/**
* @private
*/
SceneTransforms.computeActualWgs84Position = function(frameState, position, result) {
var mode = frameState.mode;
if (mode === SceneMode.SCENE3D) {
return Cartesian3.clone(position, result);
}
var projection = frameState.scene2D.projection;
projection.getEllipsoid().cartesianToCartographic(position, positionInCartographic);
if (typeof positionInCartographic === 'undefined') {
result = undefined;
return result;
}
projection.project(positionInCartographic, projectedPosition);
if (mode === SceneMode.COLUMBUS_VIEW) {
return Cartesian3.fromElements(projectedPosition.z, projectedPosition.x, projectedPosition.y, result);
}
if (mode === SceneMode.SCENE2D) {
return Cartesian3.fromElements(0.0, projectedPosition.x, projectedPosition.y, result);
}
// mode === SceneMode.MORPHING
var morphTime = frameState.morphTime;
return Cartesian3.fromElements(
CesiumMath.lerp(projectedPosition.z, position.x, morphTime),
CesiumMath.lerp(projectedPosition.x, position.y, morphTime),
CesiumMath.lerp(projectedPosition.y, position.z, morphTime),
result);
};
var positionNDC = new Cartesian3();
var positionWC = new Cartesian4();
var viewport = new BoundingRectangle();
var viewportTransform = new Matrix4();
/**
* @private
*/
SceneTransforms.clipToWindowCoordinates = function(canvas, position, result) {
// Perspective divide to transform from clip coordinates to normalized device coordinates
positionNDC.x = position.x / position.w;
positionNDC.y = position.y / position.w;
positionNDC.z = position.z / position.w;
// Assuming viewport takes up the entire canvas...
viewport.width = canvas.clientWidth;
viewport.height = canvas.clientHeight;
Matrix4.computeViewportTransformation(viewport, 0.0, 1.0, viewportTransform);
// Viewport transform to transform from clip coordinates to window coordinates
viewportTransform.multiplyByPoint(positionNDC, positionWC);
return Cartesian2.fromCartesian4(positionWC, result);
};
return SceneTransforms;
});