@@ -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