//  ************************************************************************************************
//
//  BornAgain: simulate and fit reflection and scattering
//
//! @file      Img3D/Model/Particles.h
//! @brief     Defines 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)
//
//  ************************************************************************************************

#ifndef BORNAGAIN_IMG3D_MODEL_PARTICLES_H
#define BORNAGAIN_IMG3D_MODEL_PARTICLES_H

#include "Img3D/Model/PlottableBody.h"

namespace Img3D {

enum class EShape {
    BarGauss,
    BarLorentz,
    Bipyramid4,
    Box,
    CantellatedCube,
    Cone,
    CosineRippleBox,
    CosineRippleGauss,
    CosineRippleLorentz,
    Cylinder,
    Dodecahedron,
    EllipsoidalCylinder,
    Sphere,
    Spheroid,
    HemiEllipsoid,
    HorizontalCylinder,
    Icosahedron,
    None,
    PlatonicOctahedron,
    PlatonicTetrahedron,
    Prism3,
    Prism6,
    Pyramid2,
    Pyramid3,
    Pyramid4,
    Pyramid6,
    SawtoothRippleBox,
    SawtoothRippleGauss,
    SawtoothRippleLorentz,
    TruncatedCube,
    TruncatedSphere,
    TruncatedSpheroid
};

//------------------------------------------------------------------------------

class PlotParticle : public PlottableBody {
protected:
    PlotParticle(GeometricID::Key);
    F3 turn;      // turn before scale
    F3 scale;     // geometries are of 1-size (box 1x1x1, sphere D=1), need scaling
    F3 offset;    // geometries centered around origin; particles stand on z=0 plane
    F3 rotate;    // remembered
    F3 translate; // remembered

    void set();

public:
    static EShape const firstKind = EShape::BarGauss;
    static EShape const lastKind = EShape::TruncatedSpheroid;

    void transform(F3 rotate, F3 translate);

    void addTransform(F3 rotate, F3 translate);
    void addTranslation(F3 translate_);
    void addExtrinsicRotation(F3 rotateExtrinsic);
};

//------------------------------------------------------------------------------

namespace Particles {

class Sphere : public PlotParticle {
public:
    Sphere(float R);
};

class Spheroid : public PlotParticle {
public:
    Spheroid(float R, float H);
};

class Cylinder : public PlotParticle {
public:
    Cylinder(float R, float H);
};

class TruncatedSphere : public PlotParticle {
public:
    TruncatedSphere(float R, float H, float deltaH = 0.0f);
};

class TruncatedSpheroid : public PlotParticle {
public:
    TruncatedSpheroid(float R, float H, float fp, float deltaH = 0.0f);
};

class Cone : public PlotParticle {
public:
    Cone(float R, float H, float alpha);
};

class Icosahedron : public PlotParticle {
public:
    Icosahedron(float L);
};

class Dodecahedron : public PlotParticle {
public:
    Dodecahedron(float L);
};

class TruncatedCube : public PlotParticle {
public:
    TruncatedCube(float L, float t);
};

class Prism6 : public PlotParticle {
public:
    Prism6(float R, float H);
};

class Pyramid6 : public PlotParticle {
public:
    Pyramid6(float R, float H, float alpha);
};

class Pyramid4 : public PlotParticle {
public:
    Pyramid4(float L, float H, float alpha);
};

class Bipyramid4 : public PlotParticle {
public:
    Bipyramid4(float L, float H, float rH, float alpha);
};

class Prism3 : public PlotParticle {
public:
    Prism3(float L, float H);
};

class Pyramid3 : public PlotParticle {
public:
    Pyramid3(float L, float H, float alpha);
};

class EllipsoidalCylinder : public PlotParticle {
public:
    EllipsoidalCylinder(float Ra, float Rb, float H);
};

class BarGauss : public PlotParticle {
public:
    BarGauss(float L, float W, float H);
};

class BarLorentz : public PlotParticle {
public:
    BarLorentz(float L, float W, float H);
};

class Box : public PlotParticle {
public:
    Box(float L, float W, float H);
};

class HemiEllipsoid : public PlotParticle {
public:
    HemiEllipsoid(float Ra, float Rb, float H);
};

class CosineRippleBox : public PlotParticle {
public:
    CosineRippleBox(float L, float W, float H);
};

class CosineRippleGauss : public PlotParticle {
public:
    CosineRippleGauss(float L, float W, float H);
};

class CosineRippleLorentz : public PlotParticle {
public:
    CosineRippleLorentz(float L, float W, float H);
};

class SawtoothRippleBox : public PlotParticle {
public:
    SawtoothRippleBox(float L, float W, float H);
};

class SawtoothRippleGauss : public PlotParticle {
public:
    SawtoothRippleGauss(float L, float W, float H);
};

class SawtoothRippleLorentz : public PlotParticle {
public:
    SawtoothRippleLorentz(float L, float W, float H);
};

class SawtoothRipple : public PlotParticle {
public:
    SawtoothRipple(float L, float W, float H, float asymmetry);
};

class CantellatedCube : public PlotParticle {
public:
    CantellatedCube(float L, float t);
};

class HorizontalCylinder : public PlotParticle {
public:
    HorizontalCylinder(float R, float L, float s_b, float s_t);
};

class PlatonicOctahedron : public PlotParticle {
public:
    PlatonicOctahedron(float L);
};

class PlatonicTetrahedron : public PlotParticle {
public:
    PlatonicTetrahedron(float L);
};

class Pyramid2 : public PlotParticle {
public:
    Pyramid2(float L, float W, float H, float alpha);
};

} // namespace Particles
} // namespace Img3D

#endif // BORNAGAIN_IMG3D_MODEL_PARTICLES_H
