forked from mcneel/opennurbs
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathopennurbs_quaternion.h
427 lines (363 loc) · 11.7 KB
/
opennurbs_quaternion.h
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
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
//
// Copyright (c) 1993-2022 Robert McNeel & Associates. All rights reserved.
// OpenNURBS, Rhinoceros, and Rhino3D are registered trademarks of Robert
// McNeel & Associates.
//
// THIS SOFTWARE IS PROVIDED "AS IS" WITHOUT EXPRESS OR IMPLIED WARRANTY.
// ALL IMPLIED WARRANTIES OF FITNESS FOR ANY PARTICULAR PURPOSE AND OF
// MERCHANTABILITY ARE HEREBY DISCLAIMED.
//
// For complete openNURBS copyright information see <http://www.opennurbs.org>.
//
////////////////////////////////////////////////////////////////
#if !defined(ON_QUATERNION_INC_)
#define ON_QUATERNION_INC_
class ON_CLASS ON_Quaternion
{
public:
// quaternion = a + bi + cj + dk
double a;
double b;
double c;
double d;
static const ON_Quaternion Zero; // 0 = (0,0,0,0
static const ON_Quaternion Identity; // 1 = (1,0,0,0)
static const ON_Quaternion I; // "i" = (0,1,0,0)
static const ON_Quaternion J; // "j" = (0,0,1,0)
static const ON_Quaternion K; // "k" = (0,0,0,1)
ON_Quaternion() { a = b = c = d = 0.0; }
ON_Quaternion(double qa, double qb, double qc, double qd);
// (a,b,c,d) = (0,v.x,v.y,v.z)
ON_Quaternion(const ON_3dVector& v);
// (a,b,c,d) = (0,v.x,v.y,v.z)
ON_Quaternion& operator=(const ON_3dVector& v);
void Set(double qa, double qb, double qc, double qd);
// arithmetic operators
ON_Quaternion operator*(int) const;
ON_Quaternion operator/(int) const;
ON_Quaternion operator*(float) const;
ON_Quaternion operator/(float) const;
ON_Quaternion operator*(double) const;
ON_Quaternion operator/(double) const;
ON_Quaternion operator+(const ON_Quaternion&) const;
ON_Quaternion operator-(const ON_Quaternion&) const;
// quaternion multiplication is not commutative
ON_Quaternion operator*(const ON_Quaternion&) const;
/*
Returns:
True if a, b, c, and d are valid finite IEEE doubles.
*/
bool IsValid() const;
/*
Description:
Returns the conjugate of the quaternion = (a,-b,-c,-d).
*/
ON_Quaternion Conjugate() const;
/*
Description:
Sets the quaternion to a/L2, -b/L2, -c/L2, -d/L2,
where L2 = length squared = (a*a + b*b + c*c + d*d).
This is the multiplicative inverse, i.e.,
(a,b,c,d)*(a/L2, -b/L2, -c/L2, -d/L2) = (1,0,0,0).
Returns:
True if successful. False if the quaternion is zero
and cannot be inverted.
*/
bool Invert();
/*
Returns:
Sets the quaternion to a/L2, -b/L2, -c/L2, -d/L2,
where L2 = length squared = (a*a + b*b + c*c + d*d).
This is the multiplicative inverse, i.e.,
(a,b,c,d)*(a/L2, -b/L2, -c/L2, -d/L2) = (1,0,0,0).
If "this" is the zero quaternion, then the zero quaternion
is returned.
*/
ON_Quaternion Inverse() const;
/*
Returns:
Returns the length or norm of the quaternion
sqrt(a*a + b*b + c*c + d*d).
*/
double Length() const;
/*
Returns:
Returns a*a + b*b + c*c + d*d.
*/
double LengthSquared() const;
/*
Returns:
The distance or norm of the difference between the two quaternions.
= ("this" - q).Length().
*/
double DistanceTo(const ON_Quaternion& q) const;
/*
Returns:
The distance or norm of the difference between the two quaternions.
= (p - q).Length().
*/
static double Distance(const ON_Quaternion& p, const ON_Quaternion& q);
/*
Returns:
4x4 real valued matrix form of the quaternion
a b c d
-b a -d c
-c d a -b
-d -c b a
which has the same arithmetic properties in as the
quaternion.
Remarks:
Do not confuse this with the rotation defined
by the quaternion. This function will only be interesting
to math nerds and is not useful in rendering or animation
applications.
*/
ON_Xform MatrixForm() const;
/*
Description:
Scales the quaternion's coordinates so that
a*a + b*b + c*c + d*d = 1.
Returns:
True if successful. False if the quaternion is zero
and cannot be unitized.
*/
bool Unitize();
/*
Description:
Sets the quaternion to
cos(angle/2), sin(angle/2)*x, sin(angle/2)*y, sin(angle/2)*z
where (x,y,z) is the unit vector parallel to axis. This is
the unit quaternion that represents the rotation of angle
about axis.
Parameters:
angle - [in] in radians
axis - [in] axis of rotation
Returns:
*/
void SetRotation(double angle, const ON_3dVector& axis);
/*
Parameters:
angle - [in] in radians
axis - [in] axis of rotation
Returns:
The unit quaternion
cos(angle/2), sin(angle/2)*x, sin(angle/2)*y, sin(angle/2)*z
where (x,y,z) is the unit vector parallel to axis. This is the
unit quaternion that represents the rotation of angle about axis.
*/
static ON_Quaternion Rotation(double angle, const ON_3dVector& axis);
/*
Description:
Returns a Quaternion defined by Tait-Byran angles (also loosely known as Euler angles).
Parameters:
yaw - angle (in radians) to rotate about the Z axis
pitch - angle (in radians) to rotate about the Y axis
roll - angle (in radians) to rotate about the X axis
Details:
RotationZYX(yaw, pitch, roll) = R_z( yaw) * R_y(pitch) * R_x(roll)
where R_*(angle) is rotation of angle radians about the corresponding world coordinate axis.
See Also:
GetYawPitchRoll, RotationZYZ
*/
static ON_Quaternion RotationZYX(double yaw, double pitch, double roll);
/*
Description:
Returns a Quaternion defined by Euler angles.
Parameters:
alpha - angle (in radians) to rotate about the Z axis
beta - angle (in radians) to rotate about the Y axis
gamma - angle (in radians) to rotate about the Z axis
Details:
RotationZYZ(alpha, beta, gamma) = R_z( alpha) * R_y(beta) * R_z(gamma)
where R_*(angle) is rotation of angle radians about the corresponding *-world coordinate axis.
See Also:
GetEulerZYZ, RotationZYX
*/
static ON_Quaternion RotationZYZ(double alpha, double beta, double gamma);
/*
Description:
Sets the quaternion to the unit quaternion which rotates
plane0.xaxis to plane1.xaxis,
plane0.yaxis to plane1.yaxis, and
plane0.zaxis to plane1.zaxis.
Parameters:
plane0 - [in]
plane1 - [in]
Remarks:
The plane origins are ignored.
*/
void SetRotation(const ON_Plane& plane0, const ON_Plane& plane1);
/*
Parameters:
plane0 - [in]
plane1 - [in]
Returns:
The unit quaternion that represents the the rotation that maps
plane0.xaxis to plane1.xaxis,
plane0.yaxis to plane1.yaxis, and
plane0.zaxis to plane1.zaxis.
Remarks:
The plane origins are ignored.
*/
static ON_Quaternion Rotation(const ON_Plane& plane0, const ON_Plane& plane1);
/*
Parameters:
angle - [out]
in radians
axis - [out]
unit axis of rotation of 0 if (b,c,d) is the zero vector.
Returns:
The rotation defined by the quaternion.
Remarks:
If the quaternion is not unitized, the rotation of its
unitized form is returned.
*/
bool GetRotation(double& angle, ON_3dVector& axis) const;
/*
Description:
The transformation returned by this function has the property
that xform*V = q.Rotate(V).
Parameters:
xform - [out]
Returns:
A transformation matrix that performs the rotation defined
by the quaternion.
Remarks:
If the quaternion is not unitized, the rotation of its
unitized form is returned. Do not confuse the result of this
function the matrix returned by ON_Quaternion::MatrixForm().
The transformation returned by this function has the property
that xform*V = q.Rotate(V).
*/
bool GetRotation(ON_Xform& xform) const;
/*
Parameters:
plane - [out]
Returns:
The frame created by applying the quaternion's rotation
to the canonical world frame (1,0,0),(0,1,0),(0,0,1).
*/
bool GetRotation(ON_Plane& plane) const;
/*
Description:
Find the Tait-Byran angles (also loosely called Euler angles) for this quaternion.
Parameters:
yaw - angle (in radians) to rotate about the Z axis
pitch - angle (in radians) to rotate about the Y axis
roll - angle (in radians) to rotate about the X axis
Details:
When true is returned.
this = RotationZYX(yaw, pitch, roll) = R_z( yaw) * R_y(pitch) * R_x(roll)
where R_*(angle) is rotation of angle radians about the corresponding world coordinate axis.
Returns false if this is not a rotation.
Notes:
roll and yaw are in the range (-pi, pi] and pitch is in [-pi/2, pi/2]
*/
bool GetYawPitchRoll(double& yaw, double& pitch, double& roll)const;
/*
Description:
Find the Euler angles for a rotation transformation.
Parameters:
alpha - angle (in radians) to rotate about the Z axis
beta - angle (in radians) to rotate about the Y axis
gamma - angle (in radians) to rotate about the Z axis
Details:
When true is returned.
*this = RotationZYZ(alpha, beta, gamma) = R_z( alpha) * R_y(beta) * R_z(gamma)
where R_*(angle) is rotation of angle radians about the corresponding *-world coordinate axis.
Returns false if this is not a rotation.
Notes:
alpha and gamma are in the range (-pi, pi] while beta in in the range [0, pi]
*/
bool GetEulerZYZ(double& alpha, double& beta, double& gamma)const;
/*
Description
Rotate a 3d vector. This operation is also called
conjugation, because the result is the same as
(q.Conjugate()*(0,x,y,x)*q/q.LengthSquared()).Vector()
Parameters:
v - [in]
Returns:
R*v, where R is the rotation defined by the unit quaternion.
This is mathematically the same as the values
(Inverse(q)*(0,x,y,z)*q).Vector()
and
(q.Conjugate()*(0,x,y,x)*q/q.LengthSquared()).Vector()
Remarks:
If you need to rotate more than a dozen or so vectors, it will
be more efficient to call GetRotation(ON_Xform& xform)
and multiply the vectors by xform.
*/
ON_3dVector Rotate(ON_3dVector v) const;
/*
Returns:
The "vector" or "imaginary" part of the quaternion = (b,c,d)
*/
ON_3dVector Vector() const;
/*
Returns:
The "real" or "scalar" part of the quaternion = a.
*/
double Scalar() const;
/*
Returns:
True if a, b, c, and d are all zero.
*/
bool IsZero() const;
/*
Returns:
True if a, b, c, and d are all valid, finite and at least one is non-zero.
*/
bool IsNotZero() const;
/*
Returns:
True if b, c, and d are all zero.
*/
bool IsScalar() const;
/*
Returns:
True if a = 0 and at least one of b, c, or d is not zero.
*/
bool IsVector() const;
/*
Returns:
exp(q) = e^a*( cos(|V|) + V/|V|*sin(|V|) ), where V = b*i + c*j + d*k.
*/
static ON_Quaternion Exp(ON_Quaternion q);
/*
Returns:
log(q) = log(|q|) + V/|V|*acos(a/|q|), where V = b*i + c*j + d*k.
*/
static ON_Quaternion Log(ON_Quaternion q);
/*
Returns:
q^t = Exp(t*Log(q))
*/
static ON_Quaternion Pow(ON_Quaternion q, double t);
static ON_Quaternion Slerp(ON_Quaternion q0, ON_Quaternion q1, double t);
/*
Returns the quaternion obtained by rotating q0 towards q1 limiting the rotation by MaxRadians.
*/
static ON_Quaternion RotateTowards(ON_Quaternion q0, ON_Quaternion q1, double MaxRadians);
};
/*
Returns:
The quaternion product of p and q. This is the same value as p*q.
*/
ON_DECL
ON_Quaternion ON_QuaternionProduct( const ON_Quaternion& p, const ON_Quaternion& q);
/*
Returns:
The vector cross product of p and q = (0,x,y,z) where
(x,y,z) = ON_CrossProduct(p.Vector(),q.Vector())
This is NOT the same as the quaternion product p*q.
*/
ON_DECL
ON_Quaternion ON_CrossProduct( const ON_Quaternion& p, const ON_Quaternion& q);
ON_DECL
ON_Quaternion operator*(int, const ON_Quaternion&);
ON_DECL
ON_Quaternion operator*(float, const ON_Quaternion&);
ON_DECL
ON_Quaternion operator*(double, const ON_Quaternion&);
#endif