//#####################################################################
// 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.
//#####################################################################
// Class BOUNDED_HORIZONTAL_PLANE
//#####################################################################
#ifndef __BOUNDED_HORIZONTAL_PLANE__
#define __BOUNDED_HORIZONTAL_PLANE__

#include <Core/Basic_Geometry/BASIC_GEOMETRY_FORWARD.h>
#include <Core/Log/LOG.h>
#include <Core/Math_Tools/RANGE.h>
#include <Core/Meshes/MESHES_FORWARD.h>
#include <Core/Vectors/VECTOR.h>
namespace PhysBAM{

template<class TV>
class BOUNDED_HORIZONTAL_PLANE
{
    typedef typename TV::SCALAR T;
public:
    typedef TV VECTOR_T; 

    T half_width;

    BOUNDED_HORIZONTAL_PLANE(const T half_width=1)
        :half_width(half_width)
    {}

    TV Normal(const TV& location) const
    {TV normal;normal.y=1;return normal;}

    T Signed_Distance(const TV& location) const
    {return location.y;}

    SYMMETRIC_MATRIX<T,TV::m> Hessian(const TV& X) const
    {return SYMMETRIC_MATRIX<T,TV::m>();}

    bool Inside(const TV& location,const T thickness_over_two) const
    {return location.y<=-thickness_over_two;}

    bool Lazy_Inside(const TV& location) const
    {return location.y<=0;}

    bool Outside(const TV& location,const T thickness_over_two) const
    {return location.y>=thickness_over_two;}

    bool Lazy_Outside(const TV& location) const
    {return location.y>=0;}

    bool Boundary(const TV& location,const T thickness_over_two) const
    {return !Inside(location,thickness_over_two) && !Outside(location,thickness_over_two);}

    TV Surface(const TV& location) const
    {TV projected=location;projected.y=0;return projected;}

    RANGE<TV> Bounding_Box() const
    {
        RANGE<TV> r(-half_width*TV::All_Ones_Vector(),half_width*TV::All_Ones_Vector());
        r.max_corner.y=0;
        return r;
    }

    static std::string Name()
    {return LOG::sprintf("BOUNDED_HORIZONTAL_PLANE<VECTOR<T,%d> >",TV::m);}

    template<class RW> void Read(UNTYPED_ISTREAM<RW>& input);
    template<class RW> void Write(UNTYPED_OSTREAM<RW>& output) const;
//#####################################################################
};
template<class T> class RAY_HIT;
template<class TV> class RAY;
template<class T> TRIANGULATED_SURFACE<T>*
Generate_Triangles(const BOUNDED_HORIZONTAL_PLANE<VECTOR<T,3> >& plane);
template<class TV> RAY_HIT<typename TV::SCALAR> Intersects(const RAY<TV>& ray,
    const BOUNDED_HORIZONTAL_PLANE<TV>& plane,typename TV::SCALAR thickness=0);

template<class TV> VECTOR<RAY_HIT<typename TV::SCALAR>,2>
Intersection_Interval(const RAY<TV>& ray,const BOUNDED_HORIZONTAL_PLANE<TV>& plane,
    typename TV::SCALAR isocontour=0);
template<class TV,class T> void
All_Intersections(ARRAY<RAY_HIT<T> >& hits,const RAY<TV>& ray,
    const BOUNDED_HORIZONTAL_PLANE<TV>& plane, T isocontour=0);

}
#endif
