//#####################################################################
// Copyright 2006-2007, Geoffrey Irving, Craig Schroeder, Tamar Shinar.
// This file is part of PhysBAM whose distribution is governed by the license contained in the accompanying file PHYSBAM_COPYRIGHT.txt.
//#####################################################################
// Class TORUS
//##################################################################### 
#ifndef __TORUS__
#define __TORUS__

#include <Core/Arrays/ARRAYS_FORWARD.h>
#include <Core/Basic_Geometry/BASIC_GEOMETRY_FORWARD.h>
#include <Core/Math_Tools/RANGE.h>
#include <Core/Matrices/SYMMETRIC_MATRIX.h>
#include <Core/Meshes/MESHES_FORWARD.h>
#include <Core/Vectors/Dot_Product.h>
#include <string>
namespace PhysBAM{

template<class T>
class TORUS
{
    typedef VECTOR<T,3> TV;
public:
    typedef TV VECTOR_T;
    TV center,axis;
    T inner_radius,outer_radius;

    TORUS()
        :axis(TV(0,0,1)),inner_radius(1),outer_radius(2)
    {}

    TORUS(const TV& center_input,const TV& axis_input,const T inner_radius_input,
        const T outer_radius_input)
        :center(center_input),axis(axis_input.Normalized()),
        inner_radius(inner_radius_input),outer_radius(outer_radius_input)
    {}

    static std::string Name()
    {return "TORUS<T>";}

    T Signed_Distance(const TV& X) const;
    TV Normal(const TV& X) const;
    SYMMETRIC_MATRIX<T,3> Hessian(const TV& X) const PHYSBAM_FLATTEN;
    RANGE<TV> Bounding_Box() const;
    T Volume() const;
    template<class RW> void Read(UNTYPED_ISTREAM<RW>& input);
    template<class RW> void Write(UNTYPED_OSTREAM<RW>& output) const;
    void Fill_Uniform(RANDOM_NUMBERS<T>& rand,const RANGE<TV>& box);
//#####################################################################
};   
template<class T> class RAY_HIT;
template<class TV> class RAY;

template<class T,class TV> TORUS<T> Scaled(const TORUS<T>& b,const TV& center,T scale);
template<class T,class TV> TORUS<T> Transformed(const TORUS<T>& b,const FRAME<TV>& f);

template<class T> TRIANGULATED_SURFACE<T>*
Generate_Triangles(const TORUS<T>& torus,const int inner_resolution=8,
    const int outer_resolution=16);
template<class T> VECTOR<RAY_HIT<T>,4> Intersection_Interval(const RAY<VECTOR<T,3> >& ray,const TORUS<T>& torus,T thickness=0);
template<class T> RAY_HIT<T> Intersects(const RAY<VECTOR<T,3> >& ray,const TORUS<T>& torus,T isocontour=0);
template<class TV,class T> void
All_Intersections(ARRAY<RAY_HIT<T> >& hits,const RAY<TV>& ray,const TORUS<T>& torus,const T isocontour=0);
}
#endif
