16 #include "Base/Const/Units.h"
17 #include "Base/Util/Assert.h"
29 #include "Resample/Particle/ReParticle.h"
30 #include "Sample/Particle/MesoCrystal.h"
31 #include "Sample/Particle/Particle.h"
32 #include "Sample/Particle/ParticleCoreShell.h"
36 const double layerBorderWidth = 10.0;
38 const IFormFactor* getUnderlyingFormFactor(
const IFormFactor* ff)
41 while (
dynamic_cast<const ReParticle*
>(ff))
42 ff =
dynamic_cast<const ReParticle*
>(ff)->formfactor_at_bottom();
43 const auto* ffb =
dynamic_cast<const IFormFactor*
>(ff);
48 R3 to_kvector(
const QVector3D& origin)
50 return R3(
static_cast<double>(origin.x()),
static_cast<double>(origin.y()),
51 static_cast<double>(origin.z()));
58 std::function<QColor(
const QString&)> fnColorFromMaterialName)
59 : m_fnColorFromMaterialName(fnColorFromMaterialName)
61 ASSERT(fnColorFromMaterialName);
69 double total_abundance = 0.0;
70 QVector<double> cumulative_abundances;
72 for (
auto* particle : layoutItem.
particles()) {
73 total_abundance += particle->abundance();
75 cumulative_abundances.append(total_abundance);
78 return cumulative_abundances;
82 const std::vector<std::vector<double>>& lattice_positions,
83 const std::vector<Particle3DContainer>& particle3DContainer_vector,
87 double layer_size = sceneGeometry.
layerSize;
90 for (std::vector<double> position : lattice_positions) {
92 double rand_num = (rand() /
static_cast<double>(RAND_MAX));
95 for (
const auto& particle3DContainer : particle3DContainer_vector) {
96 if (rand_num <= particle3DContainer.cumulativeAbundance()) {
98 double pos_x = position[0];
99 double pos_y = position[1];
102 if (std::abs(pos_x) <= layer_size - layerBorderWidth
103 && std::abs(pos_y) <= layer_size - layerBorderWidth
104 && std::abs(pos_z) <= layer_thickness) {
106 model, particle3DContainer,
107 QVector3D(
static_cast<float>(position[0]),
static_cast<float>(position[1]),
108 static_cast<float>(0)));
125 if (
const auto* rotX =
dynamic_cast<const RotationX*
>(rotation)) {
126 beta = rotX->angle();
127 }
else if (
const auto* rotY =
dynamic_cast<const RotationY*
>(rotation)) {
128 alpha = Units::deg2rad(90.0);
129 beta = rotY->angle();
130 gamma = Units::deg2rad(-90.0);
131 }
else if (
const auto* rotZ =
dynamic_cast<const RotationZ*
>(rotation)) {
132 alpha = rotZ->angle();
133 }
else if (
const auto* rotEuler =
dynamic_cast<const RotationEuler*
>(rotation)) {
134 alpha = rotEuler->alpha();
135 beta = rotEuler->beta();
136 gamma = rotEuler->gamma();
139 static_cast<float>(gamma));
147 const IRotation* rotation = particle.rotation();
150 particle_rotate = implementParticleRotationfromIRotation(rotation);
153 float x =
static_cast<float>(particle.particlePosition().x());
154 float y =
static_cast<float>(particle.particlePosition().y());
155 float z =
static_cast<float>(particle.particlePosition().z());
157 y +
static_cast<float>(origin.y()),
158 z +
static_cast<float>(origin.z()));
170 const ParticleCoreShell& particleCoreShell,
const R3& origin)
172 std::unique_ptr<Particle> P_clone(particle.clone());
176 const IRotation* rotationCoreShell = particleCoreShell.rotation();
178 if (rotationCoreShell)
179 P_clone->rotate(*rotationCoreShell);
181 const IRotation* rotation = P_clone->rotation();
184 particle_rotate = implementParticleRotationfromIRotation(rotation);
187 R3 positionCoreShell = particleCoreShell.particlePosition();
189 P_clone->translate(positionCoreShell);
192 static_cast<float>(P_clone->particlePosition().x() + origin.x()),
193 static_cast<float>(P_clone->particlePosition().y() + origin.y()),
194 static_cast<float>(P_clone->particlePosition().z() + origin.z()));
196 particle3D.
transform(particle_rotate, position);
203 const Material* particle_material = particle.material();
205 m_fnColorFromMaterialName(QString::fromStdString(particle_material->materialName()));
206 color.setAlphaF(alpha);
207 particle3D.
color = color;
210 std::vector<Particle3DContainer>
212 const QVector3D& origin)
214 std::vector<Particle3DContainer> particle3DContainer_vector;
216 double total_abundance = computeCumulativeAbundances(layoutItem).last();
218 double cumulative_abundance = 0;
220 for (
auto* particleItem : layoutItem.
particles()) {
223 if (
const auto* pItem =
dynamic_cast<ParticleItem*
>(particleItem)) {
225 particle3DContainer = singleParticle3DContainer(*particle, total_abundance, origin);
228 if (!coreShellItem->core() || !coreShellItem->shell())
230 auto particleCoreShell = coreShellItem->createParticleCoreShell();
231 particle3DContainer =
232 particleCoreShell3DContainer(*particleCoreShell, total_abundance, origin);
233 }
else if (
const auto* compositionItem =
236 if (!compositionItem->particles().empty())
238 auto particleComposition = compositionItem->createParticleComposition();
239 particle3DContainer =
240 particleComposition3DContainer(*particleComposition, total_abundance, origin);
241 }
else if (
const auto* mesoCrystalItem =
dynamic_cast<MesoCrystalItem*
>(particleItem)) {
243 if (!mesoCrystalItem->basisParticle())
246 *mesoCrystalItem, total_abundance, origin);
251 particle3DContainer_vector.emplace_back(particle3DContainer);
254 return particle3DContainer_vector;
258 const Particle& particle,
double total_abundance,
const QVector3D& origin)
260 std::unique_ptr<Particle> P_clone(particle.clone());
262 const IFormFactor* ff = getUnderlyingFormFactor(P_clone->formfactor_at_bottom());
265 applyParticleTransformations(*P_clone, *particle3D, to_kvector(origin));
266 applyParticleColor(*P_clone, *particle3D);
269 singleParticle3DContainer.
addParticle(particle3D.release(),
false);
273 return singleParticle3DContainer;
277 const ParticleCoreShell& particleCoreShell,
double total_abundance,
const QVector3D& origin)
280 std::unique_ptr<ParticleCoreShell> PCS_clone(particleCoreShell.clone());
282 const auto* coreff = getUnderlyingFormFactor(PCS_clone->coreParticle()->formfactor_at_bottom());
283 const auto* shellff =
284 getUnderlyingFormFactor(PCS_clone->shellParticle()->formfactor_at_bottom());
290 applyParticleCoreShellTransformations(*PCS_clone->coreParticle(), *coreParticle3D, *PCS_clone,
292 applyParticleColor(*PCS_clone->coreParticle(), *coreParticle3D);
295 applyParticleCoreShellTransformations(*PCS_clone->shellParticle(), *shellParticle3D, *PCS_clone,
297 applyParticleColor(*PCS_clone->shellParticle(), *shellParticle3D, 0.5);
301 particleCoreShell3DContainer.
addParticle(coreParticle3D.release(),
false);
302 particleCoreShell3DContainer.
addParticle(shellParticle3D.release(),
true);
306 return particleCoreShell3DContainer;
310 const ParticleComposition& particleComposition,
double total_abundance,
const QVector3D& origin)
313 std::unique_ptr<ParticleComposition> PC_clone(particleComposition.clone());
317 for (
const auto& pc_particle : PC_clone->decompose()) {
321 if (
const auto* p =
dynamic_cast<const ParticleCoreShell*
>(pc_particle.get())) {
322 particle3DContainer = particleCoreShell3DContainer(*p, 1.0, origin);
323 }
else if (
dynamic_cast<const MesoCrystal*
>(pc_particle.get())) {
326 std::ostringstream ostr;
327 ostr <<
"Sorry, MesoCrystal inside ParticleComposition not yet implemented";
328 ostr <<
"\n\nStay tuned!";
329 throw std::runtime_error(ostr.str());
330 }
else if (
const auto* p =
dynamic_cast<const Particle*
>(pc_particle.get()))
331 particle3DContainer = singleParticle3DContainer(*p, 1.0, origin);
336 for (
size_t i = 0; i < particle3DContainer.
containerSize(); ++i) {
348 const MesoCrystalItem& mesoCrystalItem,
double total_abundance,
const QVector3D& origin)
351 m_fnColorFromMaterialName);
355 return mesoCrystal3DContainer;
Defines class DoubleDescriptor.
Defines class MesoCrystalItem.
Implements namespace GUI::View::TransformTo3D.
Defines class ParticleCompositionItem.
Defines class ParticleCoreShellItem.
Defines class ParticleItem.
Defines class ParticleLayoutItem.
Defines GUI::RealSpace::BuilderUtils namespace.
Defines class RealSpaceBuilder.
Defines class RealSpaceCanvas.
Defines GUI::RealSpace::BuilderUtils namespace.
GUI::RealSpace::Vector3D implementParticleRotationfromIRotation(const IRotation *&rotation)
Particle3DContainer mesoCrystal3DContainer(const MesoCrystalItem &mesoCrystalItem, double total_abundance=1.0, const QVector3D &origin={})
void applyParticleCoreShellTransformations(const Particle &particle, GUI::RealSpace::Particles::Particle &particle3D, const ParticleCoreShell &particleCoreShell, const R3 &origin=R3(0, 0, 0))
Apply transformations (translation, rotation) to a particle (core/shell) in a ParticleCoreShell.
void applyParticleColor(const Particle &particle, GUI::RealSpace::Particles::Particle &particle3D, double alpha=1)
Particle3DContainer particleCoreShell3DContainer(const ParticleCoreShell &particleCoreShell, double total_abundance=1.0, const QVector3D &origin={})
std::vector< Particle3DContainer > particle3DContainerVector(const ParticleLayoutItem &layoutItem, const QVector3D &origin={})
QVector< double > computeCumulativeAbundances(const ParticleLayoutItem &layoutItem)
BuilderUtils(std::function< QColor(const QString &)> fnColorFromMaterialName)
void populateParticlesAtLatticePositions(const std::vector< std::vector< double >> &lattice_positions, const std::vector< Particle3DContainer > &particle3DContainer_vector, GUI::RealSpace::Model *model, const SceneGeometry &sceneGeometry, const RealSpaceBuilder *builder3D)
void applyParticleTransformations(const Particle &particle, GUI::RealSpace::Particles::Particle &particle3D, const R3 &origin=R3(0, 0, 0))
Apply transformations (translation, rotation) to a 3D Particle or to a particle belonging to a Partic...
Particle3DContainer singleParticle3DContainer(const Particle &particle, double total_abundance=1.0, const QVector3D &origin={})
Particle3DContainer particleComposition3DContainer(const ParticleComposition &particleComposition3DContainer, double total_abundance=1.0, const QVector3D &origin={})
void transform(Vector3D rotate, Vector3D translate)
void addTransform(Vector3D rotate, Vector3D translate)
std::unique_ptr< GUI::RealSpace::Particles::Particle > createParticle(const size_t &index) const
double cumulativeAbundance() const
void setCumulativeAbundance(double cumulativeAbundance)
void addParticle(GUI::RealSpace::Particles::Particle *particle3D, bool blend)
size_t containerSize() const
void setParticleType(QString particleType)
bool particle3DBlend(const size_t &index) const
QVector< ItemWithParticles * > particles() const
The particles this layout contains.
void populateParticleFromParticle3DContainer(RealSpace::Model *model, const Particle3DContainer &particle3DContainer, const QVector3D &lattice_position={}) const
Particle3DContainer populateMesoCrystal()
Size and thickness information of layers.
double topOrBottomLayerThickness