//#####################################################################
// Copyright 2003-2008, Eran Guendelman, Geoffrey Irving, Sergey Koltakov.
// This file is part of PhysBAM whose distribution is governed by the license contained in the accompanying file PHYSBAM_COPYRIGHT.txt.
//#####################################################################
// Class RING
//##################################################################### 
#ifndef __RING__
#define __RING__

#include <Core/Basic_Geometry/BASIC_GEOMETRY_FORWARD.h>
#include <Core/Basic_Geometry/PLANE.h>
namespace PhysBAM{

template<class T>
class RING
{
    typedef VECTOR<T,3> TV;
public:
    typedef TV VECTOR_T;

    T height,outer_radius,inner_radius;
    PLANE<T> plane1,plane2; // plane2 is height units behind circle

    RING()
        :height(1),outer_radius(2),inner_radius(1),plane2(plane1.x0-height*plane1.normal,-plane1.normal)
    {}

    RING(const TV& X0,const TV& X1,const T outer_radius,const T inner_radius)
        :outer_radius(outer_radius),inner_radius(inner_radius)
    {
        Set_Endpoints(X0,X1);
    }

    void Set_Height(const T height_input)
    {height=height_input;plane2.x0=plane1.x0-height*plane1.normal;}

    void Set_Endpoints(const TV& X0,const TV& X1)
    {TV plane_normal=X0-X1;height=plane_normal.Normalize();
    plane1.x0=X0;plane1.normal=plane_normal;
    plane2.x0=X1;plane2.normal=-plane_normal;}

//#####################################################################
    RANGE<TV> Bounding_Box() const;
    T Signed_Distance(const TV& X) const;
    TV Surface(const TV& X) const;
    TV Normal(const TV& X) const;
    TV Normal(const TV& X,const int aggregate) const;
    SYMMETRIC_MATRIX<T,3> Hessian(const TV& X) const PHYSBAM_FLATTEN;
    bool Lazy_Inside(const TV& X) const;
    bool Lazy_Outside(const TV& X) const;
    bool Inside(const TV& X,const T thickness_over_two=0) const;
    bool Outside(const TV& X,const T thickness_over_two=0) const;
    bool Boundary(const TV& X,const T thickness_over_two) const;
    static std::string Name();
    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 TV> class RAY;
template<class TV> class RAY_HIT;

template<class T,class TV> RING<T> Scaled(const RING<T>& b,const TV& center,T scale);
template<class T,class TV> RING<T> Transformed(const RING<T>& b,const FRAME<TV>& f);
template<class T> TRIANGULATED_SURFACE<T>* Generate_Triangles(const RING<T>& ring,const int m=40,const int n=4,const int p=4);
template<class T> RAY_HIT<T> Intersects(const RAY<VECTOR<T,3> >& ray,const RING<T>& ring,const T isocontour=0);
template<class T> VECTOR<RAY_HIT<T>,8>
Intersection_Interval(const RAY<VECTOR<T,3> >& ray,const RING<T>& ring,T isocontour=0);
template<class TV,class T> void
All_Intersections(ARRAY<RAY_HIT<T> >& hits,const RAY<TV>& ray,const RING<T>& ring,const T isocontour=0);
}
#endif
