# eryar

PipeCAD - Plant Piping Design Software.
RvmTranslator - Translate AVEVA RVM to OBJ, glTF, etc.
posts - 595, comments - 590, trackbacks - 0, articles - 0

Abstract. The quaternions are members of a noncommutative division algebra first invented by William Rowan Hamilton. The idea for quaternions occurred to him while he was walking along the Royal Cannal on his way to a meeting of the Irish Academy, and Hamilton was so pleased with his discovery that he scratched the fundamental formula of quaternion algebra. There are several different ways we can express orientation and angular displacement in 3D. Here we discuss the three most important methods-matrices, Euler angles, and quaternions.

Key Words. OpenCASCADE, Quaternion, Euler angles, Rotation, Transformation

1. Introduction

Figure 1.1 Modify the location of a Valve

2.Rotation in Matrix Form

Figure 2.1 Defining an orientation using a matrix

Figure 2.2  A Valve Orientation in PDMS

Figure 2.3 Rotating a vector about an arbitrary axis

void gp_Mat::SetRotation (const gp_XYZ& Axis,

const Standard_Real Ang)
{

//    Rot = I + sin(Ang) * M + (1. - cos(Ang)) * M*M

//    avec  M . XYZ = Axis ^ XYZ

gp_XYZ V = Axis.Normalized();
SetCross (V);
Multiply (sin(Ang));
gp_Mat Temp;
Temp.SetScale (
1.0);
Standard_Real A
= V.X();
Standard_Real B
= V.Y();
Standard_Real C
= V.Z();
Temp.SetRow (
1, gp_XYZ(- C*- B*B,      A*B,           A*C     ));
Temp.SetRow (
2, gp_XYZ(     A*B,      -A*- C*C,        B*C    ));
Temp.SetRow (
3, gp_XYZ(     A*C,          B*C,       - A*- B*B));
Temp.Multiply (
1.0 - cos(Ang));
}

3.Rotation with Euler Angles

Figure 3.1 Step 1: An object in its identity orientation

Figure 3.2 Step 2: Heading is the first rotation and rotates about the vertical axis(y-axis)

Figure 3.3 Step 3: Pitch is the second rotation and rotates about the object laterial axis(x-axis)

Figure 3.4 Step 4: Bank is the third and rotates about the object longitudinal axis(z-axis)

Figure 5. Model Editor in PDMS

Figure 6. Euler Angle in Model Editor

Figure 7. Orientation Properties in AVEVA Plant/PDMS

4.Quaternions

Quaternion能被解释为角位移的轴－角对方式。然而，旋转轴和角度不是直接存储在Quaternion的四个数中，它们的确在Quaternion中，但是不是那么直接，其关系式为：

//=======================================================================
//function : SetVectorAndAngle
//purpose  :
//=======================================================================
void gp_Quaternion::SetVectorAndAngle (const gp_Vec& theAxis,

const Standard_Real theAngle)
{
gp_Vec anAxis
= theAxis.Normalized();
Standard_Real anAngleHalf
= 0.5 * theAngle;
Standard_Real sin_a
= Sin (anAngleHalf);
Set (anAxis.X()
* sin_a, anAxis.Y() * sin_a, anAxis.Z() * sin_a, Cos (anAngleHalf));
}

Figure 4.1 Converting a quaternion to a 3x3 matrix

//=======================================================================
//function : GetMatrix
//purpose  :
//=======================================================================
gp_Mat gp_Quaternion::GetMatrix () const
{
Standard_Real wx, wy, wz, xx, yy, yz, xy, xz, zz, x2, y2, z2;
Standard_Real s
= 2.0 / SquareNorm();
x2
= x * s;    y2 = y * s;    z2 = z * s;
xx
= x * x2;   xy = x * y2;   xz = x * z2;
yy
= y * y2;   yz = y * z2;   zz = z * z2;
wx
= w * x2;   wy = w * y2;   wz = w * z2;

gp_Mat aMat;

aMat (
11= 1.0 - (yy + zz);
aMat (
12= xy - wz;
aMat (
13= xz + wy;

aMat (
21= xy + wz;
aMat (
22= 1.0 - (xx + zz);
aMat (
23= yz - wx;

aMat (
31= xz - wy;
aMat (
32= yz + wx;
aMat (
33= 1.0 - (xx + yy);

// 1 division    16 multiplications    15 addidtions    12 variables

return aMat;
}

//=======================================================================
//function : GetEulerAngles
//purpose  :
//=======================================================================
void gp_Quaternion::GetEulerAngles (const gp_EulerSequence theOrder,
Standard_Real
& theAlpha,
Standard_Real
& theBeta,
Standard_Real
& theGamma) const
{
gp_Mat M
= GetMatrix();

gp_EulerSequence_Parameters o
= translateEulerSequence (theOrder);

if ( o.isTwoAxes )
{

double sy = sqrt (M(o.i, o.j) * M(o.i, o.j) + M(o.i, o.k) * M(o.i, o.k));

if (sy > 16 * DBL_EPSILON)
{
theAlpha
= ATan2 (M(o.i, o.j),  M(o.i, o.k));
theGamma
= ATan2 (M(o.j, o.i), -M(o.k, o.i));
}

else
{
theAlpha
= ATan2 (-M(o.j, o.k), M(o.j, o.j));
theGamma
= 0.;
}
theBeta
= ATan2 (sy, M(o.i, o.i));
}

else
{

double cy = sqrt (M(o.i, o.i) * M(o.i, o.i) + M(o.j, o.i) * M(o.j, o.i));

if (cy > 16 * DBL_EPSILON)
{
theAlpha
= ATan2 (M(o.k, o.j), M(o.k, o.k));
theGamma
= ATan2 (M(o.j, o.i), M(o.i, o.i));
}

else
{
theAlpha
= ATan2 (-M(o.j, o.k), M(o.j, o.j));
theGamma
= 0.;
}
theBeta
= ATan2 (-M(o.k, o.i), cy);
}

if ( o.isOdd )
{
theAlpha
= -theAlpha;
theBeta
= -theBeta;
theGamma
= -theGamma;
}

if ( ! o.isExtrinsic )
{
Standard_Real aFirst
= theAlpha;
theAlpha
= theGamma;
theGamma
= aFirst;
}
}

/*
*    Copyright (c) 2013 to current year. All Rights Reserved.
*
*           File : Main.cpp
*         Author : eryar@163.com
*           Date : 2014-11-29 10:18
*
*    Description : Test OpenCASCADE quaternion.
*
*      Key Words : OpenCASCADE, Quaternion
*
*/

#define WNT
#include
<gp_Quaternion.hxx>

#pragma comment(lib,
"TKernel.lib")
#pragma comment(lib,
"TKMath.lib")

void TestQuaternion(void)
{
gp_Quaternion aQuaternion;

// create quaternion by axis-angle.
aQuaternion.SetVectorAndAngle(gp_Vec(1.00.00.0), M_PI_2);

// convert quaternion to matrix.
gp_Mat aMatrix = aQuaternion.GetMatrix();

Standard_Real aYaw
= 0.0;
Standard_Real aPitch
= 0.0;
Standard_Real aRoll
= 0.0;

// convert quaternion to Euler Angles.
aQuaternion.GetEulerAngles(gp_YawPitchRoll, aYaw, aPitch, aRoll);

}

int main(int argc, char* argv[])
{
TestQuaternion();

return 0;
}

5.Conclusions

6. References

1. WolframMathWorld, http://mathworld.wolfram.com/Quaternion.html

2. Ken Shoemake. Conversion between quaternion and Euler angles. Graphics Gems IV, P222-22

3. 苏步青, 华宣积. 应用几何教程. 复旦大学出版计. 2012

4. 丘维声. 解析几何. 北京大学出版社. 1996

5. 同济大学应用数学系编. 线性代数（第四版）. 高等教育出版社. 2003

6. Fletcher Dunn,Ian Parberry. 3D Math Primer for Graphics and Game Development. CRC Press

7. 史银雪,陈洪,王荣静. 3D数学基础：图形与游戏开发. 清华大学出版社. 2005

8. 苏步青. 神奇的符号. 湖南少年儿童出版社. 2010