//#####################################################################
// Copyright 2007, Geoffrey Irving, Andrew Selle.
// This file is part of PhysBAM whose distribution is governed by the license contained in the accompanying file PHYSBAM_COPYRIGHT.txt.
//#####################################################################
#ifndef __ANALYTIC_IMPLICIT_OBJECT__
#define __ANALYTIC_IMPLICIT_OBJECT__

#include <Core/Basic_Geometry/RAY.h>
#include <Core/Basic_Geometry/RAY_HIT.h>
#include <Core/Implicit_Objects/IMPLICIT_OBJECT.h>
namespace PhysBAM{

template<class TV> class RAY;
template<class TV> class RAY_HIT;

template<class T_ANALYTIC>
class ANALYTIC_IMPLICIT_OBJECT:public IMPLICIT_OBJECT<typename T_ANALYTIC::VECTOR_T>
{
    typedef typename T_ANALYTIC::VECTOR_T TV;
    typedef typename TV::SCALAR T;
public:
    using IMPLICIT_OBJECT<TV>::box;
    T_ANALYTIC analytic;
    T cell_size;

    ANALYTIC_IMPLICIT_OBJECT(const T_ANALYTIC& analytic_input);
    ~ANALYTIC_IMPLICIT_OBJECT();

    static ANALYTIC_IMPLICIT_OBJECT* Create();
    void Update_Box() override;
    void Update_Minimum_Cell_Size(const int maximum_depth) override;
    T operator()(const TV& location) const override;
    T Extended_Phi(const TV& location) const override;
    TV Normal(const TV& location,const int aggregate=-1) const override;
    TV Extended_Normal(const TV& location,const int aggregate=-1) const override;
    void Compute_Normals() override;
    void Compute_Cell_Minimum_And_Maximum(const bool recompute_if_exists=true) override;
    bool Lazy_Inside(const TV& location,const T contour_value=0) const override;
    bool Lazy_Inside_And_Value(const TV& location,T& phi_value,const T contour_value=0) const override;
    bool Lazy_Inside_Extended_Levelset(const TV& unclamped_X,const T contour_value=0) const override;
    bool Lazy_Inside_Extended_Levelset_And_Value(const TV& unclamped_X,T& phi_value,const T contour_value=0) const override;
    bool Lazy_Outside(const TV& location,const T contour_value=0) const override;
    bool Lazy_Outside_Extended_Levelset(const TV& unclamped_X,const T contour_value=0) const override;
    bool Lazy_Outside_Extended_Levelset_And_Value(const TV& unclamped_X,T& phi_value,const T contour_value=0) const override;
    virtual std::string Name() const override;
    static std::string Static_Name();
    std::string Extension() const override;
    T Minimum_Cell_Size_Within_Box(const RANGE<TV>& box) const override;
    T Minimum_Cell_Size() const override;
    SYMMETRIC_MATRIX<T,TV::m> Hessian(const TV& X) const override;
    void Read(TYPED_ISTREAM& input) override;
    void Write(TYPED_OSTREAM& output) const override;
    RAY_HIT<T> Intersects(const RAY<TV>& ray,const T isocontour=0) const override;
    void All_Intersections(ARRAY<RAY_HIT<T> >& hits,const RAY<TV>& ray,const T isocontour=0) const override;
//#####################################################################
};

template<class OBJ>
enable_if_t<sizeof(&OBJ::Name)!=0,ANALYTIC_IMPLICIT_OBJECT<OBJ>*>
Make_IO(const OBJ& obj);
}
#endif
