text: // This file is part of VecGeom and is distributed under the
  // conditions in the file LICENSE.txt in the top directory.
  // For the full list of authors see CONTRIBUTORS.txt and `git log`.
  
  /// Declaration of the unplaced tetrahedron shape
  /// @file volumes/UnplaceTet.h
  /// @author Raman Sehgal, Evgueni Tcherniaev
  
  #ifndef VECGEOM_VOLUMES_UNPLACEDTET_H_
  #define VECGEOM_VOLUMES_UNPLACEDTET_H_
  
  #include "VecGeom/base/Global.h"
  #include "VecGeom/base/AlignedBase.h"
  #include "VecGeom/base/Vector3D.h"
  #include "VecGeom/volumes/UnplacedVolume.h"
  #include "VecGeom/volumes/TetStruct.h" // the pure Tet struct
  #include "VecGeom/volumes/kernel/TetImplementation.h"
  #include "VecGeom/volumes/UnplacedVolumeImplHelper.h"
  
  namespace vecgeom {
  
  VECGEOM_DEVICE_FORWARD_DECLARE(class UnplacedTet;);
  VECGEOM_DEVICE_DECLARE_CONV(class, UnplacedTet);
  
  inline namespace VECGEOM_IMPL_NAMESPACE {
  
  /// Class for tetrahedron shape primitive
  ///
  /// Tetrahedron, also known as a triangular pyramid, is a polyhedron composed
  /// by four triangular faces. It is completely defined by its four vertices.
  class UnplacedTet : public SIMDUnplacedVolumeImplHelper<TetImplementation>, public AlignedBase {
  
  private:
    TetStruct<double> fTet; ///< The structure with the tetrahedron data members
  
  public:
    /// Default constructor
    VECCORE_ATT_HOST_DEVICE
    UnplacedTet();
  
    /// Constructor from four points
    /// @param [in] p0 Point given as 3D vector
    /// @param [in] p1 Point given as 3D vector
    /// @param [in] p2 Point given as 3D vector
    /// @param [in] p3 Point given as 3D vector
    VECCORE_ATT_HOST_DEVICE
    UnplacedTet(const Vector3D<Precision> &p0, const Vector3D<Precision> &p1, const Vector3D<Precision> &p2,
                const Vector3D<Precision> &p3);
  
    /// Constructor from four points
    /// @param [in] p0 Point given as array
    /// @param [in] p1 Point given as array
    /// @param [in] p2 Point given as array
    /// @param [in] p3 Point given as array
    VECCORE_ATT_HOST_DEVICE
    UnplacedTet(const Precision p0[], const Precision p1[], const Precision p2[], const Precision p3[])
        : fTet(p0, p1, p2, p3)
    {
      fGlobalConvexity = true;
    }
  
    /// Getter for the structure storing the tetrahedron data
    VECCORE_ATT_HOST_DEVICE
    TetStruct<double> const &GetStruct() const { return fTet; }
  
    /// Getter for the tetrahedron vertices
    /// @param [out] p0 Point given as 3D vector
    /// @param [out] p1 Point given as 3D vector
    /// @param [out] p2 Point given as 3D vector
    /// @param [out] p3 Point given as 3D vector
    VECCORE_ATT_HOST_DEVICE
    VECGEOM_FORCE_INLINE
    void GetVertices(Vector3D<Precision> &p0, Vector3D<Precision> &p1, Vector3D<Precision> &p2,
                     Vector3D<Precision> &p3) const
    {
      p0 = fTet.fVertex[0];
      p1 = fTet.fVertex[1];
      p2 = fTet.fVertex[2];
      p3 = fTet.fVertex[3];
    }
  
    VECCORE_ATT_HOST_DEVICE
    void Extent(Vector3D<Precision> &, Vector3D<Precision> &) const override;
  
    Precision Capacity() const override { return fTet.fCubicVolume; }
  
    Precision SurfaceArea() const override { return fTet.fSurfaceArea; }
  
    Vector3D<Precision> SamplePointOnSurface() const override;
  
    VECCORE_ATT_HOST_DEVICE
    virtual bool Normal(Vector3D<Precision> const &p, Vector3D<Precision> &normal) const override
    {
      bool valid;
      normal = TetImplementation::NormalKernel(fTet, p, valid);
      return valid;
    }
  
    /// Get the solid type as string
    /// @return Name of the solid type
    std::string GetEntityType() const;
  
    VECCORE_ATT_HOST_DEVICE
    void GetParametersList(int aNumber, double *aArray) const;
  
    std::ostream &StreamInfo(std::ostream &os) const;
  
  public:
    virtual int MemorySize() const final { return sizeof(*this); }
  
    VECCORE_ATT_HOST_DEVICE
    virtual void Print() const override;
  
    virtual void Print(std::ostream &os) const override;
  
  #ifndef VECCORE_CUDA
    virtual SolidMesh *CreateMesh3D(Transformation3D const &trans, size_t nSegments) const override;
  #endif
  
  #ifdef VECGEOM_CUDA_INTERFACE
    virtual size_t DeviceSizeOf() const override { return DevicePtr<cuda::UnplacedTet>::SizeOf(); }
    virtual DevicePtr<cuda::VUnplacedVolume> CopyToGpu() const override;
    virtual DevicePtr<cuda::VUnplacedVolume> CopyToGpu(DevicePtr<cuda::VUnplacedVolume> const gpu_ptr) const override;
  #endif
  
    /// Templated factory for creating a placed volume
  #ifndef VECCORE_CUDA
    template <TranslationCode trans_code, RotationCode rot_code>
    static VPlacedVolume *Create(LogicalVolume const *const logical_volume, Transformation3D const *const transformation,
                                 VPlacedVolume *const placement = NULL);
  
    VPlacedVolume *SpecializedVolume(LogicalVolume const *const volume, Transformation3D const *const transformation,
                                     const TranslationCode trans_code, const RotationCode rot_code,
                                     VPlacedVolume *const placement) const override;
  #else
    template <TranslationCode trans_code, RotationCode rot_code>
    VECCORE_ATT_DEVICE
    static VPlacedVolume *Create(LogicalVolume const *const logical_volume, Transformation3D const *const transformation,
                                 const int id, const int copy_no, const int child_id,
                                 VPlacedVolume *const placement = NULL);
    VECCORE_ATT_DEVICE VPlacedVolume *SpecializedVolume(LogicalVolume const *const volume,
                                                        Transformation3D const *const transformation,
                                                        const TranslationCode trans_code, const RotationCode rot_code,
                                                        const int id, const int copy_no, const int child_id,
                                                        VPlacedVolume *const placement) const override;
  
  #endif
  };
  } // namespace VECGEOM_IMPL_NAMESPACE
  } // namespace vecgeom
  
  #endif
  