//#####################################################################
// 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 CONE
//##################################################################### 
#ifndef __CONE__
#define __CONE__

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

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

    TV base,dir;
    T radius,height;

    CONE()
        :dir(1,0,0),radius(1),height(1)
    {}

    CONE(const TV& bottom,const TV& top,const T bottom_radius)
        :base(bottom),dir(top-bottom),radius(bottom_radius),height(dir.Normalize())
    {}

//#####################################################################
    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 T> class RAY_HIT;
template<class TV> class RAY;

template<class T,class TV> CONE<T> Scaled(const CONE<T>& b,const TV& center,T scale);
template<class T,class TV> CONE<T> Transformed(const CONE<T>& b,const FRAME<TV>& f);
template<class T> RAY_HIT<T> Intersects(const RAY<VECTOR<T,3> >& ray,const CONE<T>& cone,T isocontour=0);
template<class T> VECTOR<RAY_HIT<T>,2>
Intersection_Interval(const RAY<VECTOR<T,3> >& ray,const CONE<T>& cone,T isocontour=0);
template<class T> VECTOR<RAY_HIT<T>,3>
Intersection_Interval_Infinite_Double_Cone(const RAY<VECTOR<T,3> >& ray,const CONE<T>& cone,T isocontour=0);
template<class TV,class T> void
All_Intersections(ARRAY<RAY_HIT<T> >& hits,const RAY<TV>& ray,const CONE<T>& cone,const T isocontour=0);
}
#endif
