BornAgain  1.19.79
Simulate and fit neutron and x-ray scattering at grazing incidence
RealSpaceBuilder.cpp
Go to the documentation of this file.
1 // ************************************************************************************************
2 //
3 // BornAgain: simulate and fit reflection and scattering
4 //
5 //! @file GUI/View/Realspace/RealSpaceBuilder.cpp
6 //! @brief Implements class RealSpaceBuilder
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 
30 #include "GUI/ba3d/model/model.h"
31 #include "Sample/Aggregate/Interferences.h"
32 #include "Sample/Particle/Particle.h"
33 #include "Sample/Particle/ParticleCoreShell.h"
34 
35 namespace {
36 
37 std::vector<std::vector<double>> generatePositions(const ParticleLayoutItem& layoutItem,
38  double layerSize, double density)
39 {
40  auto* interferenceItem = layoutItem.interference().currentItem();
41  if (interferenceItem) {
42  auto interference = interferenceItem->createInterference();
43 
44  if (auto* p = dynamic_cast<Interference1DLattice*>(interference.get()))
45  return Lattice1DPositionBuilder(p).generatePositions(layerSize, density);
46 
47  if (auto* p = dynamic_cast<Interference2DLattice*>(interference.get()))
48  return Lattice2DPositionBuilder(p).generatePositions(layerSize, density);
49 
50  if (auto* p = dynamic_cast<Interference2DParaCrystal*>(interference.get()))
51  return ParaCrystal2DPositionBuilder(p).generatePositions(layerSize, density);
52 
53  if (auto* p = dynamic_cast<InterferenceFinite2DLattice*>(interference.get()))
54  return Finite2DLatticePositionBuilder(p).generatePositions(layerSize, density);
55 
56  if (auto* p = dynamic_cast<InterferenceRadialParaCrystal*>(interference.get()))
57  return RadialParacrystalPositionBuilder(p).generatePositions(layerSize, density);
58  }
59 
60  return RandomPositionBuilder().generatePositions(layerSize, density);
61 }
62 
63 } // namespace
64 
65 
66 RealSpaceBuilder::RealSpaceBuilder(std::function<QColor(const QString&)> fnColorFromMaterialName)
67 {
68  m_builderUtils = std::make_unique<RealSpace::BuilderUtils>(fnColorFromMaterialName);
69 }
70 
72  const SceneGeometry& sceneGeometry,
73  const RealSpace::Camera::Position& cameraPosition) const
74 {
75  // default value of cameraPosition is in RealSpaceBuilder.h
76  model->defCamPos = cameraPosition;
77 
78  if (const auto* p = std::get_if<MultiLayerItem*>(&item))
79  populateMultiLayer(model, **p, sceneGeometry);
80  else if (const auto* p = std::get_if<LayerItem*>(&item))
81  populateLayer(model, **p, sceneGeometry);
82  else if (const auto* p = std::get_if<ParticleLayoutItem*>(&item))
83  populateLayout(model, **p, sceneGeometry);
84  else if (const auto* p = std::get_if<ItemWithParticles*>(&item))
86 }
87 
89  const MultiLayerItem& mlayerItem,
90  const SceneGeometry& sceneGeometry,
91  const QVector3D&) const
92 {
93  double total_height(0.0);
94  int index(0);
95  for (LayerItem* layer : mlayerItem.layers()) {
96  bool isTopLayer = index == 0;
97  populateLayer(model, *layer, sceneGeometry,
98  QVector3D(0, 0, static_cast<float>(-total_height)), isTopLayer);
99 
100  if (index != 0)
101  total_height += GUI::View::TransformTo3D::visualLayerThickness(*layer, sceneGeometry);
102 
103  ++index;
104  }
105 }
106 
108  const SceneGeometry& sceneGeometry, const QVector3D& origin,
109  const bool isTopLayer) const
110 {
111  auto layer = GUI::View::TransformTo3D::createLayer(layerItem, sceneGeometry, origin);
112  if (layer && !isTopLayer)
113  model->addBlend(layer.release());
114 
115  for (ParticleLayoutItem* layout : layerItem.layouts())
116  populateLayout(model, *layout, sceneGeometry, origin);
117 }
118 
120  const ParticleLayoutItem& layoutItem,
121  const SceneGeometry& sceneGeometry,
122  const QVector3D& origin) const
123 {
124  // If there is no particle to populate
125  if (layoutItem.particles().empty())
126  return;
127 
128  double layer_size = sceneGeometry.layerSize;
129  double total_density = layoutItem.totalDensity();
130 
131  auto particle3DContainer_vector = m_builderUtils->particle3DContainerVector(layoutItem, origin);
132 
133  const auto latticePositions = generatePositions(layoutItem, layer_size, total_density);
134  m_builderUtils->populateParticlesAtLatticePositions(
135  latticePositions, particle3DContainer_vector, model, sceneGeometry, this);
136 }
137 
139  const ItemWithParticles& particleItem) const
140 {
141  Particle3DContainer particle3DContainer;
142  if (const auto* pItem = dynamic_cast<const ParticleItem*>(&particleItem)) {
143  auto particle = pItem->createParticle();
144  particle3DContainer = m_builderUtils->singleParticle3DContainer(*particle);
145  } else if (const auto* particleCoreShellItem =
146  dynamic_cast<const ParticleCoreShellItem*>(&particleItem)) {
147  // If there is no CORE or SHELL to populate inside ParticleCoreShellItem
148  if (!particleCoreShellItem->core() || !particleCoreShellItem->shell())
149  return;
150  auto particleCoreShell = particleCoreShellItem->createParticleCoreShell();
151  particle3DContainer = m_builderUtils->particleCoreShell3DContainer(*particleCoreShell);
152  } else if (const auto* particleCompositionItem =
153  dynamic_cast<const ParticleCompositionItem*>(&particleItem)) {
154  // If there is no particle to populate inside ParticleCompositionItem
155  if (!particleCompositionItem->particles().empty())
156  return;
157  auto particleComposition = particleCompositionItem->createParticleComposition();
158  particle3DContainer = m_builderUtils->particleComposition3DContainer(*particleComposition);
159  } else if (const auto* mesoCrystalItem = dynamic_cast<const MesoCrystalItem*>(&particleItem)) {
160  // If there is no particle to populate inside MesoCrystalItem
161  if (!mesoCrystalItem->basisParticle())
162  return;
163  particle3DContainer = m_builderUtils->mesoCrystal3DContainer(*mesoCrystalItem);
164  }
165 
166  populateParticleFromParticle3DContainer(model, particle3DContainer);
167 }
168 
170  RealSpace::Model* model, const Particle3DContainer& particle3DContainer,
171  const QVector3D& lattice_position) const
172 {
173  if (particle3DContainer.containerSize()) {
174  for (size_t i = 0; i < particle3DContainer.containerSize(); ++i) {
175  auto particle3D = particle3DContainer.createParticle(i);
176  particle3D->addTranslation(lattice_position);
177  if (particle3D) {
178  if (!particle3DContainer.particle3DBlend(i))
179  model->add(particle3D.release());
180  else
181  model->addBlend(particle3D.release()); // use addBlend() for transparent object
182  }
183  }
184  }
185 }
Defines class DoubleDescriptor.
Declares interface IPositionBuilder and subclasses.
Defines InterferenceItems's classes.
Defines class LayerItem.
Defines class MesoCrystalItem.
Defines class MultiLayerItem.
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 namespace GUI::View::TransformTo3D.
void addBlend(Object *)
add a transparent object, the model takes ownership
Definition: model.cpp:136
void add(Object *)
add an opaque object, the model takes ownership
Definition: model.cpp:128
Camera::Position defCamPos
default camera params
Definition: model.h:52
std::vector< std::vector< double > > generatePositions(double layer_size, double density=0.0) const
QVector< ParticleLayoutItem * > layouts() const
Definition: LayerItem.cpp:136
QVector< LayerItem * > layers() const
std::unique_ptr< GUI::RealSpace::Particles::Particle > createParticle(const size_t &index) const
size_t containerSize() const
bool particle3DBlend(const size_t &index) const
DoubleDescriptor totalDensity() const
The real density.
QVector< ItemWithParticles * > particles() const
The particles this layout contains.
SelectionDescriptor< InterferenceItem * > interference() const
RealSpaceBuilder(std::function< QColor(const QString &)> fnColorFromMaterialName)
std::variant< MultiLayerItem *, LayerItem *, ParticleLayoutItem *, ItemWithParticles * > ItemForRealSpace
Defines the item types this class can handle.
void populateParticleFromParticle3DContainer(RealSpace::Model *model, const Particle3DContainer &particle3DContainer, const QVector3D &lattice_position={}) const
void populateLayer(RealSpace::Model *model, const LayerItem &layerItem, const SceneGeometry &sceneGeometry, const QVector3D &origin={}, bool isTopLayer=false) const
void populateParticleFromParticleItem(RealSpace::Model *model, const ItemWithParticles &particleItem) const
std::unique_ptr< RealSpace::BuilderUtils > m_builderUtils
void populateMultiLayer(RealSpace::Model *model, const MultiLayerItem &mlayerItem, const SceneGeometry &sceneGeometry, const QVector3D &origin={}) const
void populateLayout(RealSpace::Model *model, const ParticleLayoutItem &layoutItem, const SceneGeometry &sceneGeometry, const QVector3D &origin={}) const
void populate(RealSpace::Model *model, ItemForRealSpace item, const SceneGeometry &sceneGeometry, const RealSpace::Camera::Position &cameraPosition=RealSpace::Camera::Position(RealSpace::Vector3D(0, -200, 120), RealSpace::Vector3D(0, 0, 0), RealSpace::Vector3D::_z)) const
Defines Model class.
std::vector< std::vector< double > > latticePositions(const Interference2DParaCrystal *, double layer_size)
std::unique_ptr< GUI::RealSpace::Layer > createLayer(const LayerItem &layerItem, const SceneGeometry &sceneGeometry, const QVector3D &origin={})
double visualLayerThickness(const LayerItem &layerItem, const SceneGeometry &sceneGeometry)
Size and thickness information of layers.