-
Wuttke, Joachim authoredWuttke, Joachim authored
particles.cpp 11.35 KiB
// ************************************************************************************************
//
// BornAgain: simulate and fit reflection and scattering
//
//! @file GUI/ba3d/model/particles.cpp
//! @brief Implements Particle class
//!
//! @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 "GUI/ba3d/model/particles.h"
#include <cmath>
namespace GUI::RealSpace::Particles {
QString const& name(EShape k)
{
static QString names[] = {"",
"BarGauss",
"BarLorentz",
"Bipyramid4",
"Box",
"CantellatedCube",
"Cone",
"CosineRippleBox",
"CosineRippleGauss",
"CosineRippleLorentz",
"Cylinder",
"Dodecahedron",
"EllipsoidalCylinder",
"Sphere",
"Spheroid",
"HemiEllipsoid",
"HorizontalCylinder",
"Icosahedron",
"PlatonicOctahedron",
"PlatonicTetrahedron",
"Prism3",
"Prism6",
"Pyramid2",
"Pyramid3",
"Pyramid4",
"Pyramid6",
"SawtoothRippleBox",
"SawtoothRippleGauss",
"SawtoothRippleLorentz",
"TruncatedCube",
"TruncatedSphere",
"TruncatedSpheroid"};
return names[uint(k)];
}
//------------------------------------------------------------------------------
using namespace GeometricID;
Particle::Particle(Key key)
: Object(key)
, scale(F3(1, 1, 1))
{
}
void Particle::set()
{
transform(F3(0, 0, 0), F3(0, 0, 0));
}
void Particle::transform(F3 rotate_, F3 translate_)
{
Object::transform(turn, scale, (rotate = rotate_), offset + (translate = translate_));
}
void Particle::fancy(F3 rotate, float r)
{
Object::transform(turn, scale * r, rotate, offset + translate);
}
void Particle::addTransform(F3 rotate_, F3 translate_)
{
Object::transform(turn, scale, (rotate = rotate + rotate_),
offset + (translate = translate + translate_));
}
void Particle::addTranslation(F3 translate_)
{
Object::transform(turn, scale, rotate, offset + (translate = translate + translate_));
}
void Particle::addExtrinsicRotation(F3 rotateExtrinsic)
{
Object::addExtrinsicRotation(turn, scale, rotate, rotateExtrinsic,
(translate = offset + translate));
}
//------------------------------------------------------------------------------
static float const pi = float(M_PI);
static float const pi2f = float(M_PI_2);
static float const sqrt2f = std::sqrt(2.f);
static float const sqrt3f = std::sqrt(3.f);
// see ~/BornAgain/GUI/ba3d/ba3d/model/geometry/ for BaseShape construction
// TODO : issue #269 : wrong BaseShape model. Now Pyramid2 always has top vertex. The true Pyramid2
// should have top edge if L!=W.
Pyramid2::Pyramid2(float L, float W, float H, float alpha)
: Particle(Key(BaseShape::Column, (1.0f - H / (std::min(L, W) / 2 * std::tan(alpha))), 4))
{
isNull = (L <= 0 || W <= 0 || H <= 0 || alpha <= 0);
turn = F3(0, 0, 45 * pi / 180.0f);
scale = F3(L * sqrt2f, W * sqrt2f, H);
offset = F3(0, 0, 0);
set();
}
BarGauss::BarGauss(float L, float W, float H)
: Particle(Key(BaseShape::Column, 1.0f, 4))
{
isNull = (L < 0 || W < 0 || H < 0) || (L <= 0 && W <= 0 && H <= 0);
turn = F3(0, 0, 45 * pi / 180.0f);
scale = F3(L * sqrt2f, W * sqrt2f, H);
offset = F3(0, 0, 0);
set();
}
BarLorentz::BarLorentz(float L, float W, float H)
: Particle(Key(BaseShape::Column, 1.0f, 4))
{
isNull = (L < 0 || W < 0 || H < 0) || (L <= 0 && W <= 0 && H <= 0);
turn = F3(0, 0, 45 * pi / 180.0f);
scale = F3(L * sqrt2f, W * sqrt2f, H);
offset = F3(0, 0, 0);
set();
}
Box::Box(float L, float W, float H)
: Particle(Key(BaseShape::Column, 1.0f, 4))
{
isNull = (L < 0 || W < 0 || H < 0) || (L <= 0 && W <= 0 && H <= 0);
turn = F3(0, 0, 45 * pi / 180.0f);
scale = F3(L * sqrt2f, W * sqrt2f, H);
offset = F3(0, 0, 0);
set();
}
Cone::Cone(float R, float H, float alpha)
: Particle(Key(BaseShape::Column, (1.0f - H / (R * std::tan(alpha))), 0))
{
isNull = (R <= 0 || H <= 0 || alpha <= 0);
scale = F3(R * 2, R * 2, H);
offset = F3(0, 0, 0);
set();
}
Pyramid6::Pyramid6(float R, float H, float alpha)
: Particle(Key(BaseShape::Column, (1.0f - H / (R * sqrt3f / 2 * std::tan(alpha))), 6))
{
isNull = (R <= 0 || H <= 0 || alpha <= 0);
scale = F3(R * 2, R * 2, H);
offset = F3(0, 0, 0);
set();
}
Bipyramid4::Bipyramid4(float L, float H, float rH, float alpha)
: Particle(Key(BaseShape::Bipyramid4, rH, alpha, H / L))
{
isNull = (L <= 0 || H <= 0 || rH <= 0 || alpha >= pi2f);
scale = F3(L, L, L);
offset = F3(0, 0, 0);
set();
}
Cylinder::Cylinder(float R, float H)
: Particle(Key(BaseShape::Column, 1.0f, 0))
{
isNull = (R <= 0 || H <= 0);
scale = F3(R * 2, R * 2, H);
offset = F3(0, 0, 0);
set();
}
Dodecahedron::Dodecahedron(float L)
: Particle(Key(BaseShape::Dodecahedron))
{
isNull = (L <= 0);
float R = L / DodecahedronL2R;
scale = F3(R * 2, R * 2, R * 2);
offset = F3(0, 0, 0);
set();
}
EllipsoidalCylinder::EllipsoidalCylinder(float Ra, float Rb, float H)
: Particle(Key(BaseShape::Column, 1.0f, 0))
{
isNull = (Ra <= 0 || Rb <= 0 || H <= 0);
scale = F3(Ra * 2, Rb * 2, H);
offset = F3(0, 0, 0);
set();
}
Sphere::Sphere(float R)
: Particle(Key(BaseShape::Sphere, 0, 0.5f))
{
isNull = (R <= 0);
float D = 2 * R;
scale = F3(D, D, D);
offset = F3(0, 0, 0);
set();
}
Spheroid::Spheroid(float R, float H)
: Particle(Key(BaseShape::Sphere, 0, 0.5f))
{
isNull = (R <= 0 || H <= 0);
scale = F3(R * 2, R * 2, H);
offset = F3(0, 0, 0);
set();
}
HemiEllipsoid::HemiEllipsoid(float Ra, float Rb, float H)
: Particle(Key(BaseShape::Sphere, .5f, 0.0f))
{
isNull = (Ra <= 0 || Rb <= 0 || H <= 0);
scale = F3(Ra * 2, Rb * 2, H * 2);
offset = F3(0, 0, 0);
set();
}
Icosahedron::Icosahedron(float L)
: Particle(Key(BaseShape::Icosahedron))
{
isNull = (L <= 0);
scale = F3(L, L, L);
offset = F3(0, 0, 0);
set();
}
Prism3::Prism3(float L, float H)
: Particle(Key(BaseShape::Column, 1.0f, 3))
{
isNull = (L <= 0 || H <= 0);
float D = L / sqrt3f;
scale = F3(D * 2, D * 2, H);
offset = F3(0, 0, 0);
set();
}
Prism6::Prism6(float R, float H)
: Particle(Key(BaseShape::Column, 1.0f, 6))
{
isNull = (R <= 0 || H <= 0);
scale = F3(R * 2, R * 2, H);
offset = F3(0, 0, 0);
set();
}
Pyramid4::Pyramid4(float L, float H, float alpha)
: Particle(Key(BaseShape::Column, (1.0f - H / (L / 2 * std::tan(alpha))), 4))
{
isNull = (L <= 0 || H <= 0 || alpha <= 0);
float L2 = L * sqrt2f;
turn = F3(0, 0, 45 * pi / 180.0f);
scale = F3(L2, L2, H);
offset = F3(0, 0, 0);
set();
}
CosineRippleBox::CosineRippleBox(float L, float W, float H)
: Particle(Key(BaseShape::Ripple, 0, 0))
{
isNull = (L < 0 || W < 0 || H < 0) || (L <= 0 && W <= 0 && H <= 0);
turn = F3(0, 0, 0);
scale = F3(L, W, H);
offset = F3(0, 0, 0);
set();
}
CosineRippleGauss::CosineRippleGauss(float L, float W, float H)
: Particle(Key(BaseShape::Ripple, 0, 0))
{
isNull = (L < 0 || W < 0 || H < 0) || (L <= 0 && W <= 0 && H <= 0);
turn = F3(0, 0, 0);
scale = F3(L, W, H);
offset = F3(0, 0, 0);
set();
}
CosineRippleLorentz::CosineRippleLorentz(float L, float W, float H)
: Particle(Key(BaseShape::Ripple, 0, 0))
{
isNull = (L < 0 || W < 0 || H < 0) || (L <= 0 && W <= 0 && H <= 0);
turn = F3(0, 0, 0);
scale = F3(L, W, H);
offset = F3(0, 0, 0);
set();
}
SawtoothRippleBox::SawtoothRippleBox(float L, float W, float H)
: Particle(Key(BaseShape::Ripple, 0, 0))
{
isNull = (L < 0 || W < 0 || H < 0) || (L <= 0 && W <= 0 && H <= 0);
turn = F3(0, 0, 0);
scale = F3(L, W, H);
offset = F3(0, 0, 0);
set();
}
SawtoothRippleGauss::SawtoothRippleGauss(float L, float W, float H)
: Particle(Key(BaseShape::Ripple, 0, 0))
{
isNull = (L < 0 || W < 0 || H < 0) || (L <= 0 && W <= 0 && H <= 0);
turn = F3(0, 0, 0);
scale = F3(L, W, H);
offset = F3(0, 0, 0);
set();
}
SawtoothRippleLorentz::SawtoothRippleLorentz(float L, float W, float H)
: Particle(Key(BaseShape::Ripple, 0, 0))
{
isNull = (L < 0 || W < 0 || H < 0) || (L <= 0 && W <= 0 && H <= 0);
turn = F3(0, 0, 0);
scale = F3(L, W, H);
offset = F3(0, 0, 0);
set();
}
Pyramid3::Pyramid3(float L, float H, float alpha)
: Particle(Key(BaseShape::Column, (1.0f - H / (L / (2 * sqrt3f) * std::tan(alpha))), 3))
{
isNull = (L <= 0 || H <= 0 || alpha <= 0);
float D = L / sqrt3f;
scale = F3(D * 2, D * 2, H);
offset = F3(0, 0, 0);
set();
}
TruncatedCube::TruncatedCube(float L, float t)
: Particle(Key(BaseShape::TruncatedBox, 2 * t / L))
{
isNull = (L <= 0);
scale = F3(L, L, L);
offset = F3(0, 0, 0);
set();
}
TruncatedSphere::TruncatedSphere(float R, float H, float deltaH)
: Particle(Key(BaseShape::Sphere, 1 - H / R / 2, (H - R) / R / 2, deltaH / R / 2))
{
isNull = (R <= 0 || H <= 0);
float D = 2 * R;
scale = F3(D, D, D);
offset = F3(0, 0, 0);
set();
}
TruncatedSpheroid::TruncatedSpheroid(float R, float H, float fp, float deltaH)
: Particle(
Key(BaseShape::Sphere, 1 - H / fp / R / 2, (H - fp * R) / fp / R / 2, deltaH / fp / R / 2))
{
isNull = (R <= 0 || H <= 0 || fp <= 0);
scale = F3(R * 2, R * 2, fp * R * 2);
offset = F3(0, 0, 0);
set();
}
// TODO : issue #269 : change base shape to cantellated box
CantellatedCube::CantellatedCube(float L, float t)
: Particle(Key(BaseShape::TruncatedBox, 2 * t / L))
{
isNull = (L <= 0);
scale = F3(L, L, L);
offset = F3(0, 0, 0);
set();
}
HorizontalCylinder::HorizontalCylinder(float R, float L, float s_b, float s_t)
: Particle(Key(BaseShape::Column, 1.0f, 0))
{
isNull = (R <= 0 || L <= 0 || s_b >= s_t);
turn = F3(90 * pi / 180.0f, 90 * pi / 180.0f, 0);
scale = F3(L, R * 2, R * 2);
offset = F3(0, 0, 0);
set();
}
PlatonicOctahedron::PlatonicOctahedron(float L)
: Particle(Key(BaseShape::Bipyramid4, 1.0f, asin(sqrt(2.0f / 3)), 1.0f / sqrt(2.0f)))
{
isNull = (L <= 0);
scale = F3(L, L, L);
offset = F3(0, 0, 0);
set();
}
PlatonicTetrahedron::PlatonicTetrahedron(float L)
: Particle(Key(BaseShape::Column, 0, 3))
{
isNull = (L <= 0);
float D = L / sqrt3f;
scale = F3(D * 2, D * 2, L * sqrt(6.f) / 3);
offset = F3(0, 0, 0);
set();
}
} // namespace GUI::RealSpace::Particles