37 double L = ff_AnisoPyramid->getLength();
38 double W = ff_AnisoPyramid->getWidth();
39 double H = ff_AnisoPyramid->getHeight();
40 double alpha = ff_AnisoPyramid->getAlpha();
44 - positionInside.
z() / std::tan(alpha);
47 - positionInside.
z() / std::tan(alpha);
48 if (std::abs(positionInside.
x()) <= l_z && std::abs(positionInside.
y()) <= w_z
49 && (positionInside.
z() >= 0 && positionInside.
z() <= H))
52 double L = ff_BarGauss->getLength();
53 double W = ff_BarGauss->getWidth();
54 double H = ff_BarGauss->getHeight();
56 if (std::abs(positionInside.
x()) <= L / 2 && std::abs(positionInside.
y()) <= W / 2
57 && (positionInside.
z() >= 0 && positionInside.
z() <= H))
60 double L = ff_BarLorentz->getLength();
61 double W = ff_BarLorentz->getWidth();
62 double H = ff_BarLorentz->getHeight();
64 if (std::abs(positionInside.
x()) <= L / 2 && std::abs(positionInside.
y()) <= W / 2
65 && (positionInside.
z() >= 0 && positionInside.
z() <= H))
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();
72 if (std::abs(positionInside.
x()) <= L / 2 && std::abs(positionInside.
y()) <= W / 2
73 && (positionInside.
z() >= 0 && positionInside.
z() <= H))
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();
80 if (std::abs(positionInside.
x()) > R || std::abs(positionInside.
y()) > R
81 || positionInside.
z() < 0 || positionInside.
z() > H)
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)
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();
92 if (std::abs(positionInside.
x()) > B || std::abs(positionInside.
y()) > B
93 || positionInside.
z() < 0 || positionInside.
z() > H)
96 double l_z = B - positionInside.
z() / std::tan(alpha);
97 double theta_prime = 0;
98 if (positionInside.
x() != 0 || positionInside.
y() != 0)
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);
104 double k_z = l_z / (std::cos(theta) + std::sin(theta) / std::tan(
M_PI / 3));
106 if (std::pow(positionInside.
x(), 2) + std::pow(positionInside.
y(), 2) <= std::pow(k_z, 2))
109 double L = ff_Cuboctahedron->getLength();
110 double H = ff_Cuboctahedron->getHeight();
111 double rH = ff_Cuboctahedron->getHeightRatio();
112 double alpha = ff_Cuboctahedron->getAlpha();
114 double total_Height = H + rH * H;
116 if (std::abs(positionInside.
x()) > L / 2 || std::abs(positionInside.
y()) > L / 2
117 || positionInside.
z() < 0 || positionInside.
z() > total_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)
125 double R = ff_Cylinder->getRadius();
126 double H = ff_Cylinder->getHeight();
128 if (std::abs(positionInside.
x()) > R || std::abs(positionInside.
y()) > R
129 || positionInside.
z() < 0 || positionInside.
z() > H)
132 if (std::pow(positionInside.
x() / R, 2) + std::pow(positionInside.
y() / R, 2) <= 1)
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());
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 =
147 double a = ff_EllipsoidalCylinder->getRadiusX();
148 double b = ff_EllipsoidalCylinder->getRadiusY();
149 double H = ff_EllipsoidalCylinder->getHeight();
151 if (std::abs(positionInside.
x()) > a || std::abs(positionInside.
y()) > b
152 || positionInside.
z() < 0 || positionInside.
z() > H)
155 if (std::pow(positionInside.
x() / a, 2) + std::pow(positionInside.
y() / b, 2) <= 1)
158 double R = ff_FullSphere->getRadius();
160 if (std::abs(positionInside.
x()) > R || std::abs(positionInside.
y()) > R
161 || positionInside.
z() < 0 || positionInside.
z() > 2 * R)
164 if (std::pow(positionInside.
x() / R, 2) + std::pow(positionInside.
y() / R, 2)
165 + std::pow((positionInside.
z() - R) / R, 2)
169 double a = ff_FullSpheroid->getRadius();
170 double H = ff_FullSpheroid->getHeight();
173 if (std::abs(positionInside.
x()) > a || std::abs(positionInside.
y()) > a
174 || positionInside.
z() < 0 || positionInside.
z() > H)
177 if (std::pow(positionInside.
x() / a, 2) + std::pow(positionInside.
y() / a, 2)
178 + std::pow((positionInside.
z() - c) / c, 2)
182 double a = ff_HemiEllipsoid->getRadiusX();
183 double b = ff_HemiEllipsoid->getRadiusY();
184 double c = ff_HemiEllipsoid->getHeight();
186 if (std::abs(positionInside.
x()) > a || std::abs(positionInside.
y()) > b
187 || positionInside.
z() < 0 || positionInside.
z() > c)
190 if (std::pow(positionInside.
x() / a, 2) + std::pow(positionInside.
y() / b, 2)
191 + std::pow(positionInside.
z() / c, 2)
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();
204 double l = B * std::sin(
M_PI / 3);
205 double x_shift = B / 2 * std::tan(
M_PI / 6);
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)
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)));
218 double k = l / (std::sin(theta) / std::tan(
M_PI / 6) + std::cos(theta));
220 if (std::pow(positionInside.
x() + x_shift, 2) + std::pow(positionInside.
y(), 2)
223 }
else if (
auto ff_Prism6 =
dynamic_cast<const FormFactorPrism6*
>(outerShape)) {
224 double B = ff_Prism6->getBaseEdge();
225 double H = ff_Prism6->getHeight();
227 if (std::abs(positionInside.
x()) > B || std::abs(positionInside.
y()) > B
228 || positionInside.
z() < 0 || positionInside.
z() > H)
231 double theta_prime = 0;
232 if (positionInside.
x() != 0 || positionInside.
y() != 0)
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);
238 double k_z = B / (std::cos(theta) + std::sin(theta) / std::tan(
M_PI / 3));
240 if (std::pow(positionInside.
x(), 2) + std::pow(positionInside.
y(), 2) <= std::pow(k_z, 2))
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();
248 B / 2 - positionInside.
z() / std::tan(alpha);
249 if (std::abs(positionInside.
x()) <= l_z && std::abs(positionInside.
y()) <= l_z
250 && (positionInside.
z() >= 0 && positionInside.
z() <= H))
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());
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());
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());
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());
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());
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());
289 double B = ff_Tetrahedron->getBaseEdge();
290 double H = ff_Tetrahedron->getHeight();
291 double alpha = ff_Tetrahedron->getAlpha();
294 B - positionInside.
z() * 2 / std::tan(alpha);
296 double l = B_z * std::sin(
M_PI / 3);
297 double x_shift = B_z / 2 * std::tan(
M_PI / 6);
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)
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)));
310 double k = l / (std::sin(theta) / std::tan(
M_PI / 6) + std::cos(theta));
312 if (std::pow(positionInside.
x() + x_shift, 2) + std::pow(positionInside.
y(), 2)
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 =
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))
330 if (std::pow(positionInside.
x() / R, 2) + std::pow(positionInside.
y() / R, 2)
331 + std::pow((positionInside.
z() - (H - R)) / R, 2)
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());
348 double total_abundance,
const QVector3D& origin)
359 std::unique_ptr<MesoCrystal> M_clone(mesoCrystal->clone());
367 auto mesoCrystal_rotation = M_clone->rotation();
368 auto mesoCrystal_translation = M_clone->position();
375 *particleComposition, 1.0,
m_origin);
377 auto particleCoreShell =
dynamic_cast<const ParticleCoreShell*
>(particleBasis.get());
378 mesoCrystalBasis3DContainer =
380 }
else if (
dynamic_cast<const MesoCrystal*
>(particleBasis.get())) {
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());
388 auto particle =
dynamic_cast<const Particle*
>(particleBasis.get());
389 mesoCrystalBasis3DContainer =
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();
401 if (isPositionInsideMesoCrystal(outerShapeff.get(), positionInside)) {
402 for (
size_t it = 0; it < mesoCrystalBasis3DContainer.
containerSize(); ++it) {
404 particle3D->addTranslation(
405 QVector3D(
static_cast<float>(positionInside.
x()),
406 static_cast<float>(positionInside.
y()),
407 static_cast<float>(positionInside.
z())));
409 particle3D->addExtrinsicRotation(
411 mesoCrystal_rotation));
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())));
419 particle3D.release(), mesoCrystalBasis3DContainer.
particle3DBlend(it));
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())));
436 color.setAlphaF(0.3);
437 outerShape3D->color = color;
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 RealSpaceBuilderUtils namespace.
Defines RealSpaceBuilderUtils namespace.
Defines some unit conversion factors and other constants in namespace Units.
T z() const
Returns z-component in cartesian coordinate system.
T y() const
Returns y-component in cartesian coordinate system.
T x() const
Returns x-component in cartesian coordinate system.
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.
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.
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={})
double deg2rad(double angle)
double rad2deg(double angle)