mirror of
https://github.com/mcneel/opennurbs.git
synced 2026-03-06 15:05:52 +08:00
Co-authored-by: Alain <alain@mcneel.com> Co-authored-by: Andrew Le Bihan <andy@mcneel.com> Co-authored-by: croudyj <croudyj@gmail.com> Co-authored-by: Dale Fugier <dale@mcneel.com> Co-authored-by: Dale Lear <dalelear@mcneel.com> Co-authored-by: David Eränen <david.eranen@mcneel.com> Co-authored-by: Greg Arden <greg@mcneel.com> Co-authored-by: Mikko Oksanen <mikko@mcneel.com> Co-authored-by: piac <giulio@mcneel.com> Co-authored-by: Steve Baer <steve@mcneel.com> Co-authored-by: TimHemmelman <tim@mcneel.com> Co-authored-by: Will Pearson <will@mcneel.com>
428 lines
12 KiB
C++
428 lines
12 KiB
C++
//
|
|
// 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);
|
|
|
|
/*
|
|
Descriptin:
|
|
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
|