BornAgain  1.19.0
Simulate and fit neutron and x-ray scattering at grazing incidence
RealSpaceMesoCrystalUtils.cpp
Go to the documentation of this file.
1 // ************************************************************************************************
2 //
3 // BornAgain: simulate and fit reflection and scattering
4 //
5 //! @file GUI/coregui/Views/RealSpaceWidgets/RealSpaceMesoCrystalUtils.cpp
6 //! @brief Defines RealSpaceBuilderUtils namespace
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 "Base/Const/Units.h"
29 
30 namespace {
31 const int n = 10; // TODO: Adjust this parameter based on the size of the mesocrystal
32 
33 bool isPositionInsideMesoCrystal(const IFormFactor* outerShape, kvector_t positionInside)
34 {
35  bool check(false);
36  if (auto ff_AnisoPyramid = dynamic_cast<const FormFactorAnisoPyramid*>(outerShape)) {
37  double L = ff_AnisoPyramid->getLength();
38  double W = ff_AnisoPyramid->getWidth();
39  double H = ff_AnisoPyramid->getHeight();
40  double alpha = ff_AnisoPyramid->getAlpha();
41 
42  double l_z =
43  L / 2
44  - positionInside.z() / std::tan(alpha); // half-length of rectangle at a given height
45  double w_z =
46  W / 2
47  - positionInside.z() / std::tan(alpha); // half-width of rectangle at a given height
48  if (std::abs(positionInside.x()) <= l_z && std::abs(positionInside.y()) <= w_z
49  && (positionInside.z() >= 0 && positionInside.z() <= H))
50  check = true;
51  } else if (auto ff_BarGauss = dynamic_cast<const FormFactorBarGauss*>(outerShape)) {
52  double L = ff_BarGauss->getLength();
53  double W = ff_BarGauss->getWidth();
54  double H = ff_BarGauss->getHeight();
55 
56  if (std::abs(positionInside.x()) <= L / 2 && std::abs(positionInside.y()) <= W / 2
57  && (positionInside.z() >= 0 && positionInside.z() <= H))
58  check = true;
59  } else if (auto ff_BarLorentz = dynamic_cast<const FormFactorBarLorentz*>(outerShape)) {
60  double L = ff_BarLorentz->getLength();
61  double W = ff_BarLorentz->getWidth();
62  double H = ff_BarLorentz->getHeight();
63 
64  if (std::abs(positionInside.x()) <= L / 2 && std::abs(positionInside.y()) <= W / 2
65  && (positionInside.z() >= 0 && positionInside.z() <= H))
66  check = true;
67  } else if (auto ff_Box = dynamic_cast<const FormFactorBox*>(outerShape)) {
68  double L = ff_Box->getLength();
69  double W = ff_Box->getWidth();
70  double H = ff_Box->getHeight();
71 
72  if (std::abs(positionInside.x()) <= L / 2 && std::abs(positionInside.y()) <= W / 2
73  && (positionInside.z() >= 0 && positionInside.z() <= H))
74  check = true;
75  } else if (auto ff_Cone = dynamic_cast<const FormFactorCone*>(outerShape)) {
76  double R = ff_Cone->getRadius();
77  double H = ff_Cone->getHeight();
78  double alpha = ff_Cone->getAlpha();
79 
80  if (std::abs(positionInside.x()) > R || std::abs(positionInside.y()) > R
81  || positionInside.z() < 0 || positionInside.z() > H)
82  return check;
83 
84  double R_z = R - positionInside.z() / std::tan(alpha);
85  if (std::pow(positionInside.x() / R_z, 2) + std::pow(positionInside.y() / R_z, 2) <= 1)
86  check = true;
87  } else if (auto ff_Cone6 = dynamic_cast<const FormFactorCone6*>(outerShape)) {
88  double B = ff_Cone6->getBaseEdge();
89  double H = ff_Cone6->getHeight();
90  double alpha = ff_Cone6->getAlpha();
91 
92  if (std::abs(positionInside.x()) > B || std::abs(positionInside.y()) > B
93  || positionInside.z() < 0 || positionInside.z() > H)
94  return check;
95 
96  double l_z = B - positionInside.z() / std::tan(alpha); // edge of hexagon at a given height
97  double theta_prime = 0; // angle between positionInside & x-axis in positionInside.z() plane
98  if (positionInside.x() != 0 || positionInside.y() != 0)
99  theta_prime = Units::rad2deg(std::asin(
100  std::abs(positionInside.y())
101  / std::sqrt(std::pow(positionInside.x(), 2) + std::pow(positionInside.y(), 2))));
102  int c = static_cast<int>(theta_prime / 60); // multiplication constant
103  double theta = Units::deg2rad(theta_prime - c * 60);
104  double k_z = l_z / (std::cos(theta) + std::sin(theta) / std::tan(M_PI / 3));
105 
106  if (std::pow(positionInside.x(), 2) + std::pow(positionInside.y(), 2) <= std::pow(k_z, 2))
107  check = true;
108  } else if (auto ff_Cuboctahedron = dynamic_cast<const FormFactorCuboctahedron*>(outerShape)) {
109  double L = ff_Cuboctahedron->getLength();
110  double H = ff_Cuboctahedron->getHeight();
111  double rH = ff_Cuboctahedron->getHeightRatio();
112  double alpha = ff_Cuboctahedron->getAlpha();
113 
114  double total_Height = H + rH * H;
115 
116  if (std::abs(positionInside.x()) > L / 2 || std::abs(positionInside.y()) > L / 2
117  || positionInside.z() < 0 || positionInside.z() > total_Height)
118  return check;
119 
120  // half-length of square (i.e. horizontal cross-section of Cuboctahedron) at a given height
121  double l_z = L / 2 - std::abs(H - positionInside.z()) / std::tan(alpha);
122  if (std::abs(positionInside.x()) <= l_z && std::abs(positionInside.y()) <= l_z)
123  check = true;
124  } else if (auto ff_Cylinder = dynamic_cast<const FormFactorCylinder*>(outerShape)) {
125  double R = ff_Cylinder->getRadius();
126  double H = ff_Cylinder->getHeight();
127 
128  if (std::abs(positionInside.x()) > R || std::abs(positionInside.y()) > R
129  || positionInside.z() < 0 || positionInside.z() > H)
130  return check;
131 
132  if (std::pow(positionInside.x() / R, 2) + std::pow(positionInside.y() / R, 2) <= 1)
133  check = true;
134  } else if (dynamic_cast<const FormFactorDodecahedron*>(outerShape)) {
135  // TODO: Implement Dodecahedron
136  std::ostringstream ostr;
137  ostr << "Sorry, outer shape Dodecahedron not yet implemented for Mesocrystal";
138  ostr << "\n\nStay tuned!";
139  throw std::runtime_error(ostr.str());
140  } else if (dynamic_cast<const FormFactorDot*>(outerShape)) {
141  std::ostringstream ostr;
142  ostr << "Cannot display particles inside the Mesocrystal!";
143  ostr << "\n\nOuter shape is a Dot!";
144  throw std::runtime_error(ostr.str());
145  } else if (auto ff_EllipsoidalCylinder =
146  dynamic_cast<const FormFactorEllipsoidalCylinder*>(outerShape)) {
147  double a = ff_EllipsoidalCylinder->getRadiusX(); // semi-axis length along x
148  double b = ff_EllipsoidalCylinder->getRadiusY(); // semi-axis length along y
149  double H = ff_EllipsoidalCylinder->getHeight();
150 
151  if (std::abs(positionInside.x()) > a || std::abs(positionInside.y()) > b
152  || positionInside.z() < 0 || positionInside.z() > H)
153  return check;
154 
155  if (std::pow(positionInside.x() / a, 2) + std::pow(positionInside.y() / b, 2) <= 1)
156  check = true;
157  } else if (auto ff_FullSphere = dynamic_cast<const FormFactorFullSphere*>(outerShape)) {
158  double R = ff_FullSphere->getRadius();
159 
160  if (std::abs(positionInside.x()) > R || std::abs(positionInside.y()) > R
161  || positionInside.z() < 0 || positionInside.z() > 2 * R)
162  return check;
163 
164  if (std::pow(positionInside.x() / R, 2) + std::pow(positionInside.y() / R, 2)
165  + std::pow((positionInside.z() - R) / R, 2)
166  <= 1)
167  check = true;
168  } else if (auto ff_FullSpheroid = dynamic_cast<const FormFactorFullSpheroid*>(outerShape)) {
169  double a = ff_FullSpheroid->getRadius(); // semi-axis length along x and y
170  double H = ff_FullSpheroid->getHeight();
171  double c = H / 2; // semi-axis length along z
172 
173  if (std::abs(positionInside.x()) > a || std::abs(positionInside.y()) > a
174  || positionInside.z() < 0 || positionInside.z() > H)
175  return check;
176 
177  if (std::pow(positionInside.x() / a, 2) + std::pow(positionInside.y() / a, 2)
178  + std::pow((positionInside.z() - c) / c, 2)
179  <= 1)
180  check = true;
181  } else if (auto ff_HemiEllipsoid = dynamic_cast<const FormFactorHemiEllipsoid*>(outerShape)) {
182  double a = ff_HemiEllipsoid->getRadiusX(); // semi-axis length along x
183  double b = ff_HemiEllipsoid->getRadiusY(); // semi-axis length along y
184  double c = ff_HemiEllipsoid->getHeight(); // semi-axis length along z
185 
186  if (std::abs(positionInside.x()) > a || std::abs(positionInside.y()) > b
187  || positionInside.z() < 0 || positionInside.z() > c)
188  return check;
189 
190  if (std::pow(positionInside.x() / a, 2) + std::pow(positionInside.y() / b, 2)
191  + std::pow(positionInside.z() / c, 2)
192  <= 1)
193  check = true;
194  } else if (dynamic_cast<const FormFactorIcosahedron*>(outerShape)) {
195  // TODO: Implement Icosahedron
196  std::ostringstream ostr;
197  ostr << "Sorry, outer shape Icosahedron not yet implemented for Mesocrystal";
198  ostr << "\n\nStay tuned!";
199  throw std::runtime_error(ostr.str());
200  } else if (auto ff_Prism3 = dynamic_cast<const FormFactorPrism3*>(outerShape)) {
201  double B = ff_Prism3->getBaseEdge();
202  double H = ff_Prism3->getHeight();
203 
204  double l = B * std::sin(M_PI / 3);
205  double x_shift = B / 2 * std::tan(M_PI / 6);
206 
207  if (positionInside.x() + x_shift < 0 || positionInside.x() + x_shift > l
208  || std::abs(positionInside.y()) > B / 2 || positionInside.z() < 0
209  || positionInside.z() > H)
210  return check;
211 
212  double theta = 0; // angle between positionInside & x-axis in positionInside.z() plane
213  if (positionInside.x() + x_shift != 0 || positionInside.y() != 0)
214  theta = std::asin(std::abs(positionInside.y())
215  / std::sqrt(std::pow(positionInside.x() + x_shift, 2)
216  + std::pow(positionInside.y(), 2)));
217 
218  double k = l / (std::sin(theta) / std::tan(M_PI / 6) + std::cos(theta));
219 
220  if (std::pow(positionInside.x() + x_shift, 2) + std::pow(positionInside.y(), 2)
221  <= std::pow(k, 2))
222  check = true;
223  } else if (auto ff_Prism6 = dynamic_cast<const FormFactorPrism6*>(outerShape)) {
224  double B = ff_Prism6->getBaseEdge();
225  double H = ff_Prism6->getHeight();
226 
227  if (std::abs(positionInside.x()) > B || std::abs(positionInside.y()) > B
228  || positionInside.z() < 0 || positionInside.z() > H)
229  return check;
230 
231  double theta_prime = 0; // angle between positionInside & x-axis in positionInside.z() plane
232  if (positionInside.x() != 0 || positionInside.y() != 0)
233  theta_prime = Units::rad2deg(std::asin(
234  std::abs(positionInside.y())
235  / std::sqrt(std::pow(positionInside.x(), 2) + std::pow(positionInside.y(), 2))));
236  int c = static_cast<int>(theta_prime / 60); // multiplicative constant
237  double theta = Units::deg2rad(theta_prime - c * 60);
238  double k_z = B / (std::cos(theta) + std::sin(theta) / std::tan(M_PI / 3));
239 
240  if (std::pow(positionInside.x(), 2) + std::pow(positionInside.y(), 2) <= std::pow(k_z, 2))
241  check = true;
242  } else if (auto ff_Pyramid = dynamic_cast<const FormFactorPyramid*>(outerShape)) {
243  double B = ff_Pyramid->getBaseEdge();
244  double H = ff_Pyramid->getHeight();
245  double alpha = ff_Pyramid->getAlpha();
246 
247  double l_z =
248  B / 2 - positionInside.z() / std::tan(alpha); // half-length of square at a given height
249  if (std::abs(positionInside.x()) <= l_z && std::abs(positionInside.y()) <= l_z
250  && (positionInside.z() >= 0 && positionInside.z() <= H))
251  check = true;
252  } else if (dynamic_cast<const FormFactorCosineRippleBox*>(outerShape)) {
253  // TODO: Implement CosineRippleBox
254  std::ostringstream ostr;
255  ostr << "Sorry, outer shape CosineRippleBox not yet implemented for Mesocrystal";
256  ostr << "\n\nStay tuned!";
257  throw std::runtime_error(ostr.str());
258  } else if (dynamic_cast<const FormFactorCosineRippleGauss*>(outerShape)) {
259  // TODO: Implement CosineRippleGauss
260  std::ostringstream ostr;
261  ostr << "Sorry, outer shape CosineRippleGauss not yet implemented for Mesocrystal";
262  ostr << "\n\nStay tuned!";
263  throw std::runtime_error(ostr.str());
264  } else if (dynamic_cast<const FormFactorCosineRippleLorentz*>(outerShape)) {
265  // TODO: Implement CosineRippleLorentz
266  std::ostringstream ostr;
267  ostr << "Sorry, outer shape CosineRippleLorentz not yet implemented for Mesocrystal";
268  ostr << "\n\nStay tuned!";
269  throw std::runtime_error(ostr.str());
270  } else if (dynamic_cast<const FormFactorSawtoothRippleBox*>(outerShape)) {
271  // TODO: Implement SawtoothRippleBox
272  std::ostringstream ostr;
273  ostr << "Sorry, outer shape SawtoothRippleBox not yet implemented for Mesocrystal";
274  ostr << "\n\nStay tuned!";
275  throw std::runtime_error(ostr.str());
276  } else if (dynamic_cast<const FormFactorSawtoothRippleGauss*>(outerShape)) {
277  // TODO: Implement SawtoothRippleGauss
278  std::ostringstream ostr;
279  ostr << "Sorry, outer shape SawtoothRippleGauss not yet implemented for Mesocrystal";
280  ostr << "\n\nStay tuned!";
281  throw std::runtime_error(ostr.str());
282  } else if (dynamic_cast<const FormFactorSawtoothRippleLorentz*>(outerShape)) {
283  // TODO: Implement SawtoothRippleLorentz
284  std::ostringstream ostr;
285  ostr << "Sorry, outer shape SawtoothRippleLorentz not yet implemented for Mesocrystal";
286  ostr << "\n\nStay tuned!";
287  throw std::runtime_error(ostr.str());
288  } else if (auto ff_Tetrahedron = dynamic_cast<const FormFactorTetrahedron*>(outerShape)) {
289  double B = ff_Tetrahedron->getBaseEdge();
290  double H = ff_Tetrahedron->getHeight();
291  double alpha = ff_Tetrahedron->getAlpha();
292 
293  double B_z =
294  B - positionInside.z() * 2 / std::tan(alpha); // edge of triangle at a given height
295 
296  double l = B_z * std::sin(M_PI / 3);
297  double x_shift = B_z / 2 * std::tan(M_PI / 6);
298 
299  if (positionInside.x() + x_shift < 0 || positionInside.x() + x_shift > l
300  || std::abs(positionInside.y()) > B_z / 2 || positionInside.z() < 0
301  || positionInside.z() > H)
302  return check;
303 
304  double theta = 0; // angle between positionInside & x-axis in positionInside.z() plane
305  if (positionInside.x() + x_shift != 0 || positionInside.y() != 0)
306  theta = std::asin(std::abs(positionInside.y())
307  / std::sqrt(std::pow(positionInside.x() + x_shift, 2)
308  + std::pow(positionInside.y(), 2)));
309 
310  double k = l / (std::sin(theta) / std::tan(M_PI / 6) + std::cos(theta));
311 
312  if (std::pow(positionInside.x() + x_shift, 2) + std::pow(positionInside.y(), 2)
313  <= std::pow(k, 2))
314  check = true;
315  } else if (dynamic_cast<const FormFactorTruncatedCube*>(outerShape)) {
316  // TODO: Implement Truncated cube
317  std::ostringstream ostr;
318  ostr << "Sorry, outer shape Truncated cube not yet implemented for Mesocrystal";
319  ostr << "\n\nStay tuned!";
320  throw std::runtime_error(ostr.str());
321  } else if (auto ff_TruncatedSphere =
322  dynamic_cast<const FormFactorTruncatedSphere*>(outerShape)) {
323  double R = ff_TruncatedSphere->getRadius();
324  double H = ff_TruncatedSphere->getHeight();
325  double deltaH = ff_TruncatedSphere->getRemovedTop();
326  if (std::abs(positionInside.x()) > R || std::abs(positionInside.y()) > R
327  || positionInside.z() < 0 || positionInside.z() > (H - deltaH))
328  return check;
329 
330  if (std::pow(positionInside.x() / R, 2) + std::pow(positionInside.y() / R, 2)
331  + std::pow((positionInside.z() - (H - R)) / R, 2)
332  <= 1)
333  check = true;
334  } else if (dynamic_cast<const FormFactorTruncatedSpheroid*>(outerShape)) {
335  // TODO: Implement Truncated spheroid
336  std::ostringstream ostr;
337  ostr << "Sorry, outer shape Truncated spheroid not yet implemented for Mesocrystal";
338  ostr << "\n\nStay tuned!";
339  throw std::runtime_error(ostr.str());
340  }
341  return check;
342 }
343 } // namespace
344 
346 
348  double total_abundance, const QVector3D& origin)
349 {
350  m_mesoCrystalItem = mesoCrystalItem;
351  m_total_abundance = total_abundance;
352  m_origin = origin;
353 }
354 
356 {
357  auto mesoCrystal = m_mesoCrystalItem->createMesoCrystal();
358 
359  std::unique_ptr<MesoCrystal> M_clone(mesoCrystal->clone()); // clone of the mesoCrystal
360 
361  // These methods DO NOT add rotation/translation of the mesoCrystal to its children
362  // and hence they need to be added manually
363  auto lattice = m_mesoCrystalItem->getLattice();
364  auto particleBasis = m_mesoCrystalItem->getBasis();
365  auto outerShapeff = m_mesoCrystalItem->getOuterShape();
366 
367  auto mesoCrystal_rotation = M_clone->rotation();
368  auto mesoCrystal_translation = M_clone->position();
369 
370  Particle3DContainer mesoCrystalBasis3DContainer;
371 
372  if (dynamic_cast<const ParticleComposition*>(particleBasis.get())) {
373  auto particleComposition = dynamic_cast<const ParticleComposition*>(particleBasis.get());
374  mesoCrystalBasis3DContainer = RealSpaceBuilderUtils::particleComposition3DContainer(
375  *particleComposition, 1.0, m_origin);
376  } else if (dynamic_cast<const ParticleCoreShell*>(particleBasis.get())) {
377  auto particleCoreShell = dynamic_cast<const ParticleCoreShell*>(particleBasis.get());
378  mesoCrystalBasis3DContainer =
380  } else if (dynamic_cast<const MesoCrystal*>(particleBasis.get())) {
381  // TODO: Implement method to populate MesoCrystal from CORE and NOT from MesoCrystalItem
382  // as it is done currently in RealSpaceBuilderUtils::mesoCrystal3DContainer
383  std::ostringstream ostr;
384  ostr << "Sorry, MesoCrystal inside MesoCrystal not yet implemented";
385  ostr << "\n\nStay tuned!";
386  throw std::runtime_error(ostr.str());
387  } else {
388  auto particle = dynamic_cast<const Particle*>(particleBasis.get());
389  mesoCrystalBasis3DContainer =
391  }
392 
394 
395  for (int k = -n; k <= n; k++) {
396  for (int j = -n; j <= n; j++) {
397  for (int i = -n; i <= n; i++) {
398  auto positionInside = i * lattice.getBasisVectorA() + j * lattice.getBasisVectorB()
399  + k * lattice.getBasisVectorC();
400 
401  if (isPositionInsideMesoCrystal(outerShapeff.get(), positionInside)) {
402  for (size_t it = 0; it < mesoCrystalBasis3DContainer.containerSize(); ++it) {
403  auto particle3D = mesoCrystalBasis3DContainer.createParticle(it);
404  particle3D->addTranslation(
405  QVector3D(static_cast<float>(positionInside.x()),
406  static_cast<float>(positionInside.y()),
407  static_cast<float>(positionInside.z())));
408 
409  particle3D->addExtrinsicRotation(
411  mesoCrystal_rotation));
412 
413  particle3D->addTranslation(
414  QVector3D(static_cast<float>(mesoCrystal_translation.x()),
415  static_cast<float>(mesoCrystal_translation.y()),
416  static_cast<float>(mesoCrystal_translation.z())));
417 
419  particle3D.release(), mesoCrystalBasis3DContainer.particle3DBlend(it));
420  }
421  }
422  }
423  }
424  }
425 
426  // Add outer shape for visualisation
427  auto outerShape3D = TransformTo3D::createParticlefromIFormFactor(outerShapeff.get());
428  outerShape3D->addTransform(
430  QVector3D(static_cast<float>(mesoCrystal_translation.x()),
431  static_cast<float>(mesoCrystal_translation.y()),
432  static_cast<float>(mesoCrystal_translation.z())));
433 
434  // assign grey (default) color to the outer shape
435  QColor color = {};
436  color.setAlphaF(0.3);
437  outerShape3D->color = color;
438  mesoCrystal3DContainer.addParticle(outerShape3D.release(), true);
439 
440  // set the correct abundance for the MesoCrystal
443 
444  return mesoCrystal3DContainer;
445 }
#define M_PI
Definition: Constants.h:44
Includes all particle-shape form-factor definitions.
Defines classes Lattice2DItems.
Defines class MesoCrystalItem.
Defines class MesoCrystal.
Implements namespace TransformTo3D.
Defines class ParticleCompositionItem.
Defines class ParticleCoreShellItem.
Defines ParticleCoreShell.
Defines class ParticleDistributionItem.
Defines class Particle.
Defines RealSpaceBuilderUtils namespace.
Defines RealSpaceBuilderUtils namespace.
Defines namespace TransformTo3D.
Defines some unit conversion factors and other constants in namespace Units.
T z() const
Returns z-component in cartesian coordinate system.
Definition: BasicVector3D.h:67
T y() const
Returns y-component in cartesian coordinate system.
Definition: BasicVector3D.h:65
T x() const
Returns x-component in cartesian coordinate system.
Definition: BasicVector3D.h:63
A frustum (truncated pyramid) with rectangular base.
The form factor of an elongated bar, with Gaussian profile in elongation direction.
Definition: FormFactorBar.h:27
The form factor of an elongated, with Lorentz form factor in elongation direction.
Definition: FormFactorBar.h:40
A rectangular prism (parallelepiped).
Definition: FormFactorBox.h:23
A frustum (truncated pyramid) with regular hexagonal base.
A conical frustum (cone truncated parallel to the base) with circular base.
The form factor for a cosine ripple, with box profile in elongation direction.
The form factor for a cosine ripple, with Gaussian profile in elongation direction.
The form factor for a cosine ripple, with Lorentz form factor in elongation direction.
A truncated bifrustum with quadratic base.
A circular cylinder.
A regular dodecahedron.
A dot, with scattering power as a sphere of radius rscat, but with F(q)=const.
Definition: FormFactorDot.h:23
A cylinder with elliptical base.
A full spheroid (an ellipsoid with two equal axes, hence with circular cross section)
An hemi ellipsoid, obtained by truncating a full ellipsoid in the middle plane spanned by two princip...
A regular icosahedron.
A prism based on an equilateral triangle.
A prism based on a regular hexagonal.
A frustum with a quadratic base.
The form factor for a cosine ripple, with box profile in elongation direction.
The form factor for a cosine ripple, with Gaussian profile in elongation direction.
The form factor for a cosine ripple, with Lorentz form factor in elongation direction.
A frustum with equilateral trigonal base.
A cube, with tetrahedral truncation of all corners.
Abstract base class for all form factors.
Definition: IFormFactor.h:36
std::unique_ptr< IFormFactor > getOuterShape() const
std::unique_ptr< MesoCrystal > createMesoCrystal() const
std::unique_ptr< IParticle > getBasis() const
Lattice3D getLattice() const
A particle with an internal structure of smaller particles.
Definition: MesoCrystal.h:25
void setCumulativeAbundance(double cumulativeAbundance)
std::unique_ptr< RealSpace::Particles::Particle > createParticle(const size_t &index) const
void addParticle(RealSpace::Particles::Particle *particle3D, bool blend)
size_t containerSize() const
void setParticleType(QString particleType)
bool particle3DBlend(const size_t &index) const
A composition of particles at fixed positions.
A particle with a core/shell geometry.
A particle with a form factor and refractive index.
Definition: Particle.h:24
RealSpaceMesoCrystal(const MesoCrystalItem *mesoCrystalItem, double total_abundance, const QVector3D &origin)
Particle3DContainer populateMesoCrystal()
const MesoCrystalItem * m_mesoCrystalItem
Particle3DContainer particleCoreShell3DContainer(const ParticleCoreShell &particleCoreShell, double total_abundance=1.0, const QVector3D &origin={})
Particle3DContainer particleComposition3DContainer(const ParticleComposition &particleComposition3DContainer, double total_abundance=1.0, const QVector3D &origin={})
Particle3DContainer mesoCrystal3DContainer(const MesoCrystalItem &mesoCrystalItem, double total_abundance=1.0, const QVector3D &origin={})
RealSpace::Vector3D implementParticleRotationfromIRotation(const IRotation *&rotation)
Particle3DContainer singleParticle3DContainer(const Particle &particle, double total_abundance=1.0, const QVector3D &origin={})
std::unique_ptr< RealSpace::Particles::Particle > createParticlefromIFormFactor(const IFormFactor *ff)
double deg2rad(double angle)
Definition: Units.h:59
double rad2deg(double angle)
Definition: Units.h:55