[QQuaternion] Introduce toAxisAndAngle()
This operation is the exact opposite to QQuaternion::fromAxisAndAngle() (so that it is a way to extract the axis and angle values suitable to create the same quaternion via QQuaternion::fromAxisAndAngle()). Change-Id: I41fda58f5fb2b867cccd6b2faf58ab671fa070da Reviewed-by: Laszlo Agocs <laszlo.agocs@theqtcompany.com>bb10
parent
255ecba269
commit
5d784deb71
|
|
@ -362,9 +362,22 @@ QVector3D QQuaternion::rotatedVector(const QVector3D& vector) const
|
|||
|
||||
#ifndef QT_NO_VECTOR3D
|
||||
|
||||
/*!
|
||||
\fn void QQuaternion::toAxisAndAngle(QVector3D *axis, float *angle) const
|
||||
\since 5.5
|
||||
\overload
|
||||
|
||||
Extracts a 3D axis \a axis and a rotating angle \a angle (in degrees)
|
||||
that corresponds to this quaternion.
|
||||
|
||||
\sa fromAxisAndAngle()
|
||||
*/
|
||||
|
||||
/*!
|
||||
Creates a normalized quaternion that corresponds to rotating through
|
||||
\a angle degrees about the specified 3D \a axis.
|
||||
|
||||
\sa toAxisAndAngle()
|
||||
*/
|
||||
QQuaternion QQuaternion::fromAxisAndAngle(const QVector3D& axis, float angle)
|
||||
{
|
||||
|
|
@ -381,9 +394,46 @@ QQuaternion QQuaternion::fromAxisAndAngle(const QVector3D& axis, float angle)
|
|||
|
||||
#endif
|
||||
|
||||
/*!
|
||||
\since 5.5
|
||||
|
||||
Extracts a 3D axis (\a x, \a y, \a z) and a rotating angle \a angle (in degrees)
|
||||
that corresponds to this quaternion.
|
||||
|
||||
\sa fromAxisAndAngle()
|
||||
*/
|
||||
void QQuaternion::toAxisAndAngle(float *x, float *y, float *z, float *angle) const
|
||||
{
|
||||
Q_ASSERT(x && y && z && angle);
|
||||
|
||||
// The quaternion representing the rotation is
|
||||
// q = cos(A/2)+sin(A/2)*(x*i+y*j+z*k)
|
||||
|
||||
float length = xp * xp + yp * yp + zp * zp;
|
||||
if (!qFuzzyIsNull(length)) {
|
||||
*x = xp;
|
||||
*y = yp;
|
||||
*z = zp;
|
||||
if (!qFuzzyIsNull(length - 1.0f)) {
|
||||
length = sqrtf(length);
|
||||
*x /= length;
|
||||
*y /= length;
|
||||
*z /= length;
|
||||
}
|
||||
*angle = 2.0f * acosf(wp);
|
||||
} else {
|
||||
// angle is 0 (mod 2*pi), so any axis will fit
|
||||
*x = *y = *z = *angle = 0.0f;
|
||||
}
|
||||
|
||||
*angle = qRadiansToDegrees(*angle);
|
||||
}
|
||||
|
||||
/*!
|
||||
Creates a normalized quaternion that corresponds to rotating through
|
||||
\a angle degrees about the 3D axis (\a x, \a y, \a z).
|
||||
|
||||
\sa toAxisAndAngle()
|
||||
*/
|
||||
QQuaternion QQuaternion::fromAxisAndAngle
|
||||
(float x, float y, float z, float angle)
|
||||
|
|
|
|||
|
|
@ -115,8 +115,10 @@ public:
|
|||
operator QVariant() const;
|
||||
|
||||
#ifndef QT_NO_VECTOR3D
|
||||
inline void toAxisAndAngle(QVector3D *axis, float *angle) const;
|
||||
static QQuaternion fromAxisAndAngle(const QVector3D& axis, float angle);
|
||||
#endif
|
||||
void toAxisAndAngle(float *x, float *y, float *z, float *angle) const;
|
||||
static QQuaternion fromAxisAndAngle
|
||||
(float x, float y, float z, float angle);
|
||||
|
||||
|
|
@ -299,6 +301,13 @@ inline QVector3D QQuaternion::vector() const
|
|||
return QVector3D(xp, yp, zp);
|
||||
}
|
||||
|
||||
inline void QQuaternion::toAxisAndAngle(QVector3D *axis, float *angle) const
|
||||
{
|
||||
float aX, aY, aZ;
|
||||
toAxisAndAngle(&aX, &aY, &aZ, angle);
|
||||
*axis = QVector3D(aX, aY, aZ);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
inline void QQuaternion::setVector(float aX, float aY, float aZ)
|
||||
|
|
|
|||
|
|
@ -721,11 +721,31 @@ void tst_QQuaternion::fromAxisAndAngle()
|
|||
QVERIFY(qFuzzyCompare(answer.z(), result.z()));
|
||||
QVERIFY(qFuzzyCompare(answer.scalar(), result.scalar()));
|
||||
|
||||
{
|
||||
QVector3D answerAxis;
|
||||
float answerAngle;
|
||||
answer.toAxisAndAngle(&answerAxis, &answerAngle);
|
||||
QVERIFY(qFuzzyCompare(answerAxis.x(), vector.x()));
|
||||
QVERIFY(qFuzzyCompare(answerAxis.y(), vector.y()));
|
||||
QVERIFY(qFuzzyCompare(answerAxis.z(), vector.z()));
|
||||
QVERIFY(qFuzzyCompare(answerAngle, angle));
|
||||
}
|
||||
|
||||
answer = QQuaternion::fromAxisAndAngle(x1, y1, z1, angle);
|
||||
QVERIFY(qFuzzyCompare(answer.x(), result.x()));
|
||||
QVERIFY(qFuzzyCompare(answer.y(), result.y()));
|
||||
QVERIFY(qFuzzyCompare(answer.z(), result.z()));
|
||||
QVERIFY(qFuzzyCompare(answer.scalar(), result.scalar()));
|
||||
|
||||
{
|
||||
float answerAxisX, answerAxisY, answerAxisZ;
|
||||
float answerAngle;
|
||||
answer.toAxisAndAngle(&answerAxisX, &answerAxisY, &answerAxisZ, &answerAngle);
|
||||
QVERIFY(qFuzzyCompare(answerAxisX, vector.x()));
|
||||
QVERIFY(qFuzzyCompare(answerAxisY, vector.y()));
|
||||
QVERIFY(qFuzzyCompare(answerAxisZ, vector.z()));
|
||||
QVERIFY(qFuzzyCompare(answerAngle, angle));
|
||||
}
|
||||
}
|
||||
|
||||
// Test quaternion convertion to and from rotation matrix.
|
||||
|
|
|
|||
Loading…
Reference in New Issue