Skip to content
Snippets Groups Projects
Particle.cpp 2.91 KiB
//  ************************************************************************************************
//
//  BornAgain: simulate and fit reflection and scattering
//
//! @file      Sample/Particle/Particle.cpp
//! @brief     Implements class Particle.
//!
//! @homepage  http://www.bornagainproject.org
//! @license   GNU General Public License v3 or higher (see COPYING)
//! @copyright Forschungszentrum Jülich GmbH 2018
//! @authors   Scientific Computing Group at MLZ (see CITATION, AUTHORS)
//
//  ************************************************************************************************

#include "Sample/Particle/Particle.h"
#include "Base/Util/Assert.h"
#include "Base/Vector/Transform3D.h"
#include "Sample/Material/MaterialFactoryFuncs.h"
#include "Sample/Particle/SlicedParticle.h"
#include "Sample/Scattering/FormFactorDecoratorMaterial.h"
#include "Sample/Scattering/FormFactorDecoratorPositionFactor.h"
#include "Sample/Scattering/Rotations.h"

Particle::~Particle() = default;

Particle::Particle(Material material) : m_material(std::move(material))
{
    initialize();
}

Particle::Particle(Material material, const IFormFactor& form_factor)
    : m_material(std::move(material)), m_form_factor(form_factor.clone())
{
    initialize();
}

Particle::Particle(Material material, const IFormFactor& form_factor, const IRotation& rotation)
    : m_material(std::move(material)), m_form_factor(form_factor.clone())
{
    initialize();
    setRotation(rotation);
}

Particle* Particle::clone() const
{
    auto* p_result = new Particle(m_material);
    p_result->setAbundance(m_abundance);
    if (m_form_factor)
        p_result->setFormFactor(*m_form_factor);
    if (m_rotation)
        p_result->setRotation(*m_rotation);
    p_result->setPosition(m_position);

    return p_result;
}

SlicedParticle Particle::createSlicedParticle(const ZLimits& limits) const
{
    ASSERT(m_form_factor);
    std::unique_ptr<IRotation> rotation(new IdentityRotation);
    if (m_rotation)
        rotation.reset(m_rotation->clone());
    std::unique_ptr<IFormFactor> sliced_raw_ff(
        m_form_factor->createSlicedFormFactor(limits, *rotation, m_position));
    if (!sliced_raw_ff)
        return {};
    auto sliced_ff = std::make_unique<FormFactorDecoratorMaterial>(*sliced_raw_ff);
    double volume = sliced_raw_ff->volume();
    Material transformed_material(m_material.rotatedMaterial(rotation->getTransform3D()));
    sliced_ff->setMaterial(transformed_material);
    return {std::move(sliced_ff), {{{volume, transformed_material}}}};
}

void Particle::setMaterial(Material material)
{
    m_material = std::move(material);
}

void Particle::setFormFactor(const IFormFactor& form_factor)
{
    if (&form_factor != m_form_factor.get())
        m_form_factor.reset(form_factor.clone());
}

std::vector<const INode*> Particle::getChildren() const
{
    return std::vector<const INode*>() << IParticle::getChildren() << m_form_factor;
}

void Particle::initialize() {}