//#####################################################################
// Copyright 2003-2007, Zhaosheng Bao, Geoffrey Irving, Eftychios Sifakis.
// This file is part of PhysBAM whose distribution is governed by the license contained in the accompanying file PHYSBAM_COPYRIGHT.txt.
//#####################################################################
// Class LINE_2D
//##################################################################### 
#ifndef __LINE_2D__
#define __LINE_2D__

#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/VECTOR.h>
#include <cfloat>
namespace PhysBAM{

template<class T>
class LINE_2D
{
    typedef VECTOR<T,2> TV;
public:
    typedef TV VECTOR_T;

    TV normal;
    TV x0; // point on the line

    LINE_2D()
        :normal(0,1)
    {}

    LINE_2D(const TV& normal_input,const TV& x1_input)
        :normal(normal_input),x0(x1_input)
    {}

    TV Normal(const TV&) const
    {return normal;}

    RANGE<TV> Bounding_Box() const
    {return RANGE<TV>::Full_Box();}

    T Signed_Distance(const TV& location) const
    {return normal.Dot(location-x0);}

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

    // inside is the half space behind the normal
    bool Inside(const TV& location,const T thickness_over_two) const
    {return Signed_Distance(location)<=-thickness_over_two;}

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

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

    bool Lazy_Outside(const TV& location) const
    {return !Lazy_Inside(location);}

    bool Segment_Intersection(const TV& endpoint1,const TV& endpoint2,T& interpolation_fraction) const
    {return Segment_Line_Intersection(endpoint1,endpoint2,interpolation_fraction);}

    bool Segment_Line_Intersection(const TV& endpoint1,const TV& endpoint2,
        T& interpolation_fraction) const ;

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

    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> LINE_2D<T>
Scaled(const LINE_2D<T>& b,const TV& center,T scale);
template<class T,class TV> LINE_2D<T>
Transformed(const LINE_2D<T>& b,const FRAME<TV>& f);
template<class T> SEGMENTED_CURVE<VECTOR<T,2> >*
Tessellate_Boundary(const LINE_2D<T>& line,T tesselated_size,int elements_per_side);
template<class T> RAY_HIT<T> Intersects(const RAY<VECTOR<T,2> >& ray,const LINE_2D<T>& plane,T isocontour=0);
template<class T> VECTOR<RAY_HIT<T>,2> Intersection_Interval(const RAY<VECTOR<T,2> >& ray,const LINE_2D<T>& plane,T isocontour=0);
template<class T> void
All_Intersections(ARRAY<RAY_HIT<T> >& hits,const RAY<VECTOR<T,2> >& ray,const LINE_2D<T>& plane, T isocontour=0);
}
#endif
