Skip to content
Snippets Groups Projects

Visualize rough interfaces in Img3D

Merged Mikhail Svechnikov requested to merge m.i57 into main
@@ -21,6 +21,7 @@
#include "GUI/Model/Sample/MesocrystalItem.h"
#include "GUI/Model/Sample/ParticleItem.h"
#include "GUI/Model/Sample/ParticleLayoutItem.h"
#include "GUI/Model/Sample/RoughnessItems.h"
#include "GUI/Model/Sample/SampleItem.h"
#include "Img3D/Build/BuilderUtil.h"
#include "Img3D/Build/Particle3DContainer.h"
@@ -30,6 +31,8 @@
#include "Img3D/Model/ParticleFromFF.h"
#include "Img3D/Type/SceneGeometry.h"
#include "Sample/Aggregate/Interferences.h"
#include "Sample/Interface/LayerRoughness.h"
#include "Sample/Interface/RoughnessMap.h"
#include "Sample/Particle/Compound.h"
#include "Sample/Particle/CoreAndShell.h"
#include "Sample/Particle/Mesocrystal.h"
@@ -40,9 +43,9 @@ using Img3D::Model;
using Img3D::Particle3DContainer;
namespace {
using double2d_t = RealspaceBuilder::double2d_t;
std::vector<std::vector<double>> generatePositions(IInterference* const iff, double layerSize,
double density)
double2d_t generatePositions(IInterference* const iff, double layerSize, double density)
{
if (!iff)
return RandomPositionBuilder().generatePositions(layerSize, density);
@@ -80,17 +83,66 @@ double visualLayerThickness(const LayerItem& layerItem, const SceneGeometry& sce
return thickness == 0.0 ? sceneGeometry.layerMinimumThickness : thickness;
}
std::unique_ptr<Img3D::Layer> createLayer(const LayerItem& layerItem,
std::unique_ptr<double2d_t> scaledArray(const double2d_t& src, double factor)
{
ASSERT(src.size());
std::unique_ptr<double2d_t> result =
std::make_unique<double2d_t>(src.size(), std::vector<double>(src[0].size()));
for (size_t i = 0; i < src.size(); i++)
for (size_t j = 0; j < src[0].size(); j++)
(*result)[i][j] = src[i][j] * factor;
return result;
}
std::unique_ptr<const double2d_t> layerRoughnessMap(const LayerItem& layerItem,
const SceneGeometry& sceneGeometry, int seed)
{
std::unique_ptr<const double2d_t> result;
if (const auto* br = dynamic_cast<const BasicRoughnessItem*>(layerItem.certainRoughness())) {
auto roughness = LayerRoughness(br->sigma().dVal(), br->hurst().dVal(),
br->lateralCorrelationLength().dVal());
int n = sceneGeometry.numRoughnessPointsAlongAxis;
double L = 2 * sceneGeometry.layerSize;
auto rmap = RoughnessMap(n, n, L, L, &roughness, seed); // seed < 0 ==> random every time
result.reset(new double2d_t(rmap.generateMap()));
}
return result;
}
std::unique_ptr<Img3D::Layer> createLayer(const LayerItem& layerItem, const double2d_t* topRoughMap,
const double2d_t* bottomRoughMap,
const SceneGeometry& sceneGeometry, const F3& origin)
{
double thickness = visualLayerThickness(layerItem, sceneGeometry);
double s2 = sceneGeometry.layerSize;
double thickness = ::visualLayerThickness(layerItem, sceneGeometry);
ASSERT(thickness > 0);
auto ztop = static_cast<double>(origin.z());
double zbottom = static_cast<double>(origin.z()) - thickness;
// visual mesh will later be scaled, so we divide roughness by thickness factor in advance
std::unique_ptr<double2d_t> top;
if (topRoughMap)
top.reset(::scaledArray(*topRoughMap, 1. / thickness).release());
else {
// TODO rework
// try to generate it roughness map if is not provided (individual layer visualization)
int seed = 1; // TODO accept seed from SampleItem/LayerItem
auto new_top = ::layerRoughnessMap(layerItem, sceneGeometry, seed);
if (new_top.get())
top.reset(::scaledArray(*new_top, 1. / thickness).release());
}
std::unique_ptr<double2d_t> bottom;
if (bottomRoughMap)
bottom.reset(::scaledArray(*bottomRoughMap, 1. / thickness).release());
std::unique_ptr<Img3D::Layer> result = std::make_unique<Img3D::Layer>(
Img3D::F3Range(Img3D::F3fromR3({-s2, -s2, ztop}), Img3D::F3fromR3({s2, s2, zbottom})));
Img3D::F3Range(Img3D::F3fromR3({-s2, -s2, ztop}), Img3D::F3fromR3({s2, s2, zbottom})),
top.get(), bottom.get());
QColor color = layerItem.materialColor();
color.setAlphaF(.3);
@@ -137,24 +189,32 @@ void RealspaceBuilder::populateSample(Model* model, const SampleItem& mlayerItem
const F3&) const
{
double total_height(0.0);
int index(0);
for (LayerItem* layer : mlayerItem.layerItems()) {
bool isTopLayer = index == 0;
populateLayer(model, *layer, sceneGeometry, numParticles,
const std::vector<LayerItem*>& layers = mlayerItem.layerItems();
int seed = 1; // TODO accept seed from SampleItem/LayerItem
OwningVector<const double2d_t> rough_maps;
for (const LayerItem* layer : layers)
rough_maps.push_back(::layerRoughnessMap(*layer, sceneGeometry, seed).release());
rough_maps.push_back(nullptr);
for (size_t i = 0; i < layers.size(); i++) {
const LayerItem* layer = layers[i];
bool isTopLayer = (i == 0);
populateLayer(model, *layer, sceneGeometry, numParticles, rough_maps[i], rough_maps[i + 1],
F3(0, 0, static_cast<float>(-total_height)), isTopLayer);
if (index != 0)
total_height += visualLayerThickness(*layer, sceneGeometry);
++index;
if (i != 0)
total_height += ::visualLayerThickness(*layer, sceneGeometry);
}
}
void RealspaceBuilder::populateLayer(Model* model, const LayerItem& layerItem,
const SceneGeometry& sceneGeometry, unsigned& numParticles,
const F3& origin, const bool isTopLayer) const
const double2d_t* topRoughMap,
const double2d_t* bottomRoughMap, const F3& origin,
const bool isTopLayer) const
{
auto layer = createLayer(layerItem, sceneGeometry, origin);
auto layer = ::createLayer(layerItem, topRoughMap, bottomRoughMap, sceneGeometry, origin);
if (layer && !isTopLayer)
model->emplaceTransparentBody(layer.release());
@@ -178,7 +238,7 @@ void RealspaceBuilder::populateLayout(Model* model, const ParticleLayoutItem& la
if (interferenceItem)
iff = interferenceItem->createInterference();
const auto latticePositions = generatePositions(iff.get(), layer_size, total_density);
const auto latticePositions = ::generatePositions(iff.get(), layer_size, total_density);
populateParticlesInLattice(latticePositions, particle3DContainer_vector, model, sceneGeometry,
numParticles);
}
Loading