Skip to content

Commit 99e4a98

Browse files
committed
Merge pull request #130 from gberaudo/olcs_core_angles
Olcs core angles
2 parents 28b641d + 692402a commit 99e4a98

File tree

1 file changed

+118
-0
lines changed

1 file changed

+118
-0
lines changed

src/core.js

Lines changed: 118 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,124 @@ goog.require('olcs.core.OlLayerPrimitive');
6060
return target;
6161
};
6262

63+
64+
/**
65+
* Compute the signed tilt angle on globe, between the opposite of the
66+
* camera direction and the target normal. Return undefined if there is no
67+
* intersection of the camera direction with the globe.
68+
* @param {!Cesium.Scene} scene
69+
* @return {number|undefined}
70+
* @api
71+
*/
72+
olcs.core.computeSignedTiltAngleOnGlobe = function(scene) {
73+
var camera = scene.camera;
74+
var ray = new Cesium.Ray(camera.position, camera.direction);
75+
var target = scene.globe.pick(ray, scene);
76+
77+
if (!target) {
78+
// no tiles in the area were loaded?
79+
var ellipsoid = Cesium.Ellipsoid.WGS84;
80+
var obj = Cesium.IntersectionTests.rayEllipsoid(ray, ellipsoid);
81+
if (obj) {
82+
target = Cesium.Ray.getPoint(ray, obj.start);
83+
}
84+
}
85+
86+
if (!target) {
87+
return undefined;
88+
}
89+
90+
var normal = new Cesium.Cartesian3();
91+
Cesium.Ellipsoid.WGS84.geocentricSurfaceNormal(target, normal);
92+
93+
var angleBetween = olcs.core.signedAngleBetween;
94+
var angle = angleBetween(camera.direction, normal, camera.right) - Math.PI;
95+
return Cesium.Math.convertLongitudeRange(angle);
96+
};
97+
98+
99+
/**
100+
* Compute the ray from the camera to the bottom-center of the screen.
101+
* @param {!Cesium.Scene} scene
102+
* @return {!Cesium.Ray}
103+
*/
104+
olcs.core.bottomFovRay = function(scene) {
105+
var camera = scene.camera;
106+
var fovy2 = camera.frustum.fovy / 2;
107+
var direction = camera.direction;
108+
var rotation = Cesium.Quaternion.fromAxisAngle(camera.right, fovy2);
109+
var matrix = Cesium.Matrix3.fromQuaternion(rotation);
110+
var vector = new Cesium.Cartesian3();
111+
Cesium.Matrix3.multiplyByVector(matrix, direction, vector);
112+
return new Cesium.Ray(camera.position, vector);
113+
};
114+
115+
116+
/**
117+
* Compute the angle between two Cartesian3.
118+
* @param {!Cesium.Cartesian3} first
119+
* @param {!Cesium.Cartesian3} second
120+
* @param {!Cesium.Cartesian3} normal Normal to test orientation against.
121+
* @return {number}
122+
*/
123+
olcs.core.signedAngleBetween = function(first, second, normal) {
124+
// We are using the dot for the angle.
125+
// Then the cross and the dot for the sign.
126+
var a = new Cesium.Cartesian3();
127+
var b = new Cesium.Cartesian3();
128+
var c = new Cesium.Cartesian3();
129+
Cesium.Cartesian3.normalize(first, a);
130+
Cesium.Cartesian3.normalize(second, b);
131+
Cesium.Cartesian3.cross(a, b, c);
132+
133+
var cosine = Cesium.Cartesian3.dot(a, b);
134+
var sine = Cesium.Cartesian3.magnitude(c);
135+
136+
// Sign of the vector product and the orientation normal
137+
var sign = Cesium.Cartesian3.dot(normal, c);
138+
var angle = Math.atan2(sine, cosine);
139+
return sign >= 0 ? angle : -angle;
140+
};
141+
142+
143+
/**
144+
* Compute the rotation angle around a given point, needed to reach the
145+
* zenith position.
146+
* At a zenith position, the camera direction is going througth the earth
147+
* center and the frustrum bottom ray is going through the chosen pivot
148+
* point.
149+
* The bottom-center of the screen is a good candidate for the pivot point.
150+
* @param {!Cesium.Scene} scene
151+
* @param {!Cesium.Cartesian3} pivot Point around which the camera rotates.
152+
* @return {number}
153+
* @api
154+
*/
155+
olcs.core.computeAngleToZenith = function(scene, pivot) {
156+
// This angle is the sum of the angles 'fy' and 'a', which are defined
157+
// using the pivot point and its surface normal.
158+
// Zenith | camera
159+
// \ | /
160+
// \fy| /
161+
// \ |a/
162+
// \|/pivot
163+
var camera = scene.camera;
164+
var fy = camera.frustum.fovy / 2;
165+
var ray = olcs.core.bottomFovRay(scene);
166+
var direction = Cesium.Cartesian3.clone(ray.direction);
167+
Cesium.Cartesian3.negate(direction, direction);
168+
169+
var normal = new Cesium.Cartesian3();
170+
Cesium.Ellipsoid.WGS84.geocentricSurfaceNormal(pivot, normal);
171+
172+
var left = new Cesium.Cartesian3();
173+
Cesium.Cartesian3.negate(camera.right, left);
174+
175+
var a = olcs.core.signedAngleBetween(normal, direction, left);
176+
return a + fy;
177+
};
178+
179+
180+
63181
/**
64182
* Rotate the camera so that its direction goes through the target point.
65183
* If a globe is given, the target height is first interpolated from terrain.

0 commit comments

Comments
 (0)