BornAgain  1.19.0
Simulate and fit neutron and x-ray scattering at grazing incidence
object.cpp
Go to the documentation of this file.
1 // ************************************************************************************************
2 //
3 // BornAgain: simulate and fit reflection and scattering
4 //
5 //! @file GUI/ba3d/model/object.cpp
6 //! @brief Implements Object class
7 //!
8 //! @homepage http://www.bornagainproject.org
9 //! @license GNU General Public License v3 or higher (see COPYING)
10 //! @copyright Forschungszentrum Jülich GmbH 2018
11 //! @authors Scientific Computing Group at MLZ (see CITATION, AUTHORS)
12 //
13 // ************************************************************************************************
14 
16 #include "GUI/ba3d/model/model.h"
17 #include "GUI/ba3d/view/canvas.h"
18 #include <cmath>
19 
20 namespace {
21 QQuaternion EulerToQuaternion(const RealSpace::Vector3D& euler);
22 
23 RealSpace::Vector3D QuaternionToEuler(const QQuaternion& q);
24 } // namespace
25 
26 namespace RealSpace {
27 
28 #ifdef Q_OS_LINUX
29 QColor const clrObject = Qt::lightGray;
30 #else
31 QColor const clrObject = Qt::black;
32 #endif
33 
34 Object::Object(GeometricID::Key gky_) : color(clrObject), isNull(false), model(nullptr), gky(gky_)
35 {
36 }
37 
39 {
41  if (model)
42  model->rem(this);
43 }
44 
45 void Object::transform(float scale, Vector3D rotate, Vector3D translate)
46 {
47  transform(Vector3D(scale, scale, scale), rotate, translate);
48 }
49 
50 void Object::transform(Vector3D scale, Vector3D rotate, Vector3D translate)
51 {
52  mat.setToIdentity();
53  mat.translate(translate);
54  mat.rotate(EulerToQuaternion(rotate));
55  mat.scale(scale);
56 }
57 
58 void Object::transform(Vector3D turn, Vector3D scale, Vector3D rotate, Vector3D translate)
59 {
60  // 1. turn to align with x/y/z as needed
61  // 2. scale to desired x/y/z size
62  // 3. rotate as needed by the scene
63  // 4. move to the position
64  mat.setToIdentity();
65  mat.translate(translate);
66  mat.rotate(EulerToQuaternion(rotate));
67  mat.scale(scale);
68  mat.rotate(EulerToQuaternion(turn));
69 }
70 
71 // This method allows the addition of an extrinsic global rotation to an object i.e.
72 // it rotates the object about the global origin of the coordinate system
74  Vector3D rotateExtrinsic, Vector3D& translate)
75 {
76  mat.setToIdentity();
77  mat.rotate(EulerToQuaternion(rotateExtrinsic));
78  mat.translate(translate);
79  mat.rotate(EulerToQuaternion(rotate));
80  mat.scale(scale);
81  mat.rotate(EulerToQuaternion(turn));
82 
83  // first apply the particle's intrinsic and then extrinsic rotations
84  QQuaternion q = EulerToQuaternion(rotateExtrinsic) * EulerToQuaternion(rotate);
85  rotate = QuaternionToEuler(q);
86 
87  // translate the object to the extrinsically rotated translation vector
88  translate = EulerToQuaternion(rotateExtrinsic).rotatedVector(translate);
89 }
90 
92 {
93  geo.reset();
94 }
95 
96 void Object::draw(Canvas& canvas)
97 {
98  if (isNull)
99  return;
100 
101  if (!geo)
103  canvas.draw(color, mat, *geo);
104 }
105 
106 } // namespace RealSpace
107 
108 namespace {
109 QQuaternion EulerToQuaternion(const RealSpace::Vector3D& euler)
110 {
111  float cpsi2 = std::cos(euler.x / 2.0f);
112  float spsi2 = std::sin(euler.x / 2.0f);
113  float cth2 = std::cos(euler.y / 2.0f);
114  float sth2 = std::sin(euler.y / 2.0f);
115  float cphi2 = std::cos(euler.z / 2.0f);
116  float sphi2 = std::sin(euler.z / 2.0f);
117  auto a = cphi2 * cth2 * cpsi2 - sphi2 * cth2 * spsi2;
118  auto b = cphi2 * cpsi2 * sth2 + sphi2 * sth2 * spsi2;
119  auto c = cphi2 * sth2 * spsi2 - sphi2 * cpsi2 * sth2;
120  auto d = cphi2 * cth2 * spsi2 + cth2 * cpsi2 * sphi2;
121  return QQuaternion{a, b, c, d};
122 }
123 
124 RealSpace::Vector3D QuaternionToEuler(const QQuaternion& q)
125 {
126  auto qvec = q.toVector4D();
127 
128  float a = qvec.w(); // scalar part of quaternion
129  float b = qvec.x();
130  float c = qvec.y();
131  float d = qvec.z();
132 
133  float term1 = std::atan(d / a);
134  float term2 = 0;
135 
136  if (b == 0)
137  term2 = static_cast<float>(M_PI_2);
138  else
139  term2 = std::atan(c / b);
140 
141  float x = term1 + term2;
142  float y = 2 * std::atan(std::sqrt((b * b + c * c) / (a * a + d * d)));
143  float z = term1 - term2;
144 
145  return RealSpace::Vector3D(x, y, z);
146 }
147 } // namespace
#define M_PI_2
Definition: Constants.h:45
Defines Canvas class.
void draw(QColor const &, QMatrix4x4 const &, Geometry const &)
Definition: canvas.cpp:280
GeometryHandle getGeometry(GeometricID::Key)
Definition: geometry.cpp:148
void rem(Object *)
Definition: model.cpp:135
void addExtrinsicRotation(Vector3D turn, Vector3D scale, Vector3D &rotate, Vector3D rotateExtrinsic, Vector3D &translate)
Definition: object.cpp:73
virtual ~Object()
Definition: object.cpp:38
QMatrix4x4 mat
Definition: object.h:54
Object(GeometricID::Key)
Definition: object.cpp:34
GeometryHandle geo
Definition: object.h:51
Model * model
Definition: object.h:48
void transform(float scale, Vector3D rotate, Vector3D translate)
Definition: object.cpp:45
void releaseGeometry()
Definition: object.cpp:91
GeometricID::Key gky
Definition: object.h:50
QColor color
Definition: object.h:34
void draw(Canvas &)
Definition: object.cpp:96
Defines Geometry class.
Defines Model class.
QColor const clrObject
Definition: object.cpp:31
GeometryStore & geometryStore()
Definition: geometry.cpp:166