BornAgain  1.19.79
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 
22 QQuaternion EulerToQuaternion(const GUI::RealSpace::Vector3D& euler);
23 
24 GUI::RealSpace::Vector3D QuaternionToEuler(const QQuaternion& q);
25 
26 } // namespace
27 
28 namespace GUI::RealSpace {
29 
30 #ifdef Q_OS_LINUX
31 QColor const clrObject = Qt::lightGray;
32 #else
33 QColor const clrObject = Qt::black;
34 #endif
35 
37  : color(clrObject)
38  , isNull(false)
39  , model(nullptr)
40  , gky(gky_)
41 {
42 }
43 
45 {
47  if (model)
48  model->rem(this);
49 }
50 
51 void Object::transform(float scale, Vector3D rotate, Vector3D translate)
52 {
53  transform(Vector3D(scale, scale, scale), rotate, translate);
54 }
55 
56 void Object::transform(Vector3D scale, Vector3D rotate, Vector3D translate)
57 {
58  mat.setToIdentity();
59  mat.translate(translate);
60  mat.rotate(EulerToQuaternion(rotate));
61  mat.scale(scale);
62 }
63 
64 void Object::transform(Vector3D turn, Vector3D scale, Vector3D rotate, Vector3D translate)
65 {
66  // 1. turn to align with x/y/z as needed
67  // 2. scale to desired x/y/z size
68  // 3. rotate as needed by the scene
69  // 4. move to the position
70  mat.setToIdentity();
71  mat.translate(translate);
72  mat.rotate(EulerToQuaternion(rotate));
73  mat.scale(scale);
74  mat.rotate(EulerToQuaternion(turn));
75 }
76 
77 // This method allows the addition of an extrinsic global rotation to an object i.e.
78 // it rotates the object about the global origin of the coordinate system
80  Vector3D rotateExtrinsic, Vector3D& translate)
81 {
82  mat.setToIdentity();
83  mat.rotate(EulerToQuaternion(rotateExtrinsic));
84  mat.translate(translate);
85  mat.rotate(EulerToQuaternion(rotate));
86  mat.scale(scale);
87  mat.rotate(EulerToQuaternion(turn));
88 
89  // first apply the particle's intrinsic and then extrinsic rotations
90  QQuaternion q = EulerToQuaternion(rotateExtrinsic) * EulerToQuaternion(rotate);
91  rotate = QuaternionToEuler(q);
92 
93  // translate the object to the extrinsically rotated translation vector
94  translate = EulerToQuaternion(rotateExtrinsic).rotatedVector(translate);
95 }
96 
98 {
99  geo.reset();
100 }
101 
102 void Object::draw(Canvas& canvas)
103 {
104  if (isNull)
105  return;
106 
107  if (!geo)
109  canvas.draw(color, mat, *geo);
110 }
111 
112 } // namespace GUI::RealSpace
113 
114 namespace {
115 
116 QQuaternion EulerToQuaternion(const GUI::RealSpace::Vector3D& euler)
117 {
118  float cpsi2 = std::cos(euler.x / 2.0f);
119  float spsi2 = std::sin(euler.x / 2.0f);
120  float cth2 = std::cos(euler.y / 2.0f);
121  float sth2 = std::sin(euler.y / 2.0f);
122  float cphi2 = std::cos(euler.z / 2.0f);
123  float sphi2 = std::sin(euler.z / 2.0f);
124  auto a = cphi2 * cth2 * cpsi2 - sphi2 * cth2 * spsi2;
125  auto b = cphi2 * cpsi2 * sth2 + sphi2 * sth2 * spsi2;
126  auto c = cphi2 * sth2 * spsi2 - sphi2 * cpsi2 * sth2;
127  auto d = cphi2 * cth2 * spsi2 + cth2 * cpsi2 * sphi2;
128  return QQuaternion{a, b, c, d};
129 }
130 
131 GUI::RealSpace::Vector3D QuaternionToEuler(const QQuaternion& q)
132 {
133  auto qvec = q.toVector4D();
134 
135  float a = qvec.w(); // scalar part of quaternion
136  float b = qvec.x();
137  float c = qvec.y();
138  float d = qvec.z();
139 
140  float term1 = std::atan(d / a);
141  float term2 = 0;
142 
143  if (b == 0)
144  term2 = static_cast<float>(M_PI_2);
145  else
146  term2 = std::atan(c / b);
147 
148  float x = term1 + term2;
149  float y = 2 * std::atan(std::sqrt((b * b + c * c) / (a * a + d * d)));
150  float z = term1 - term2;
151 
152  return GUI::RealSpace::Vector3D(x, y, z);
153 }
154 
155 } // namespace
Defines Canvas class.
void draw(QColor const &, QMatrix4x4 const &, Geometry const &)
Definition: canvas.cpp:282
GeometryHandle getGeometry(GeometricID::Key)
Definition: geometry.cpp:158
void rem(Object *)
removes an object, the caller becomes responsible
Definition: model.cpp:144
GeometricID::Key gky
Definition: object.h:51
void transform(float scale, Vector3D rotate, Vector3D translate)
Definition: object.cpp:51
void addExtrinsicRotation(Vector3D turn, Vector3D scale, Vector3D &rotate, Vector3D rotateExtrinsic, Vector3D &translate)
Definition: object.cpp:79
void draw(Canvas &)
Definition: object.cpp:102
GeometryHandle geo
Definition: object.h:52
QMatrix4x4 mat
Definition: object.h:55
Object(GeometricID::Key)
Definition: object.cpp:36
Defines Geometry class.
Defines Model class.
QColor const clrObject
Definition: object.cpp:33
GeometryStore & geometryStore()
Definition: geometry.cpp:176
Real shapes will be parameterized by BaseShape enum and possibly two floats.
Definition: geometry_inc.h:51