//#####################################################################
// Copyright 2008, 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
//#####################################################################
#include <Core/Basic_Geometry/BOUNDED_HORIZONTAL_PLANE.h>
#include <Core/Basic_Geometry/PLANE.h>
#include <Core/Basic_Geometry/RAY.h>
#include <Core/Basic_Geometry/RAY_HIT.h>
#include <Core/Implicit_Objects/INTERSECTION_HELPERS.h>
#include <Core/Read_Write/READ_WRITE.h>
namespace PhysBAM{
//#####################################################################
// Function Read
//#####################################################################
template<class TV> template<class RW> void BOUNDED_HORIZONTAL_PLANE<TV>::
Read(UNTYPED_ISTREAM<RW>& input)
{
    Read_Binary_Group(input,half_width);
}
//#####################################################################
// Function Write
//#####################################################################
template<class TV> template<class RW> void BOUNDED_HORIZONTAL_PLANE<TV>::
Write(UNTYPED_OSTREAM<RW>& output) const
{
    Write_Binary_Group(output,half_width);
}
//#####################################################################
// Function Generate_Triangles
//#####################################################################
template<class T> TRIANGULATED_SURFACE<T>*
Generate_Triangles(const BOUNDED_HORIZONTAL_PLANE<VECTOR<T,3> >& plane)
{
    return Generate_Triangles(PLANE<T>(VECTOR<T,3>(0,1,0),VECTOR<T,3>()),plane.half_width);
}
//#####################################################################
// Function Intersects
//#####################################################################
template<class TV> RAY_HIT<typename TV::SCALAR>
Intersects(const RAY<TV>& ray,const BOUNDED_HORIZONTAL_PLANE<TV>& plane,
    typename TV::SCALAR isocontour)
{
    typedef typename TV::SCALAR T;
    T distance=ray.endpoint(1)-isocontour;
    T rate_of_approach=-ray.direction(1);
    if(rate_of_approach*distance<=0) return {}; // no intersection
    return RAY_HIT<T>{distance/rate_of_approach};
}
//#####################################################################
// Function Intersection_Interval
//#####################################################################
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)
{
    typedef typename TV::SCALAR T;
    T distance=ray.endpoint(1)-isocontour;
    T rate_of_approach=-ray.direction(1);
    VECTOR<RAY_HIT<T>,2> v;
    if(distance<0)
    {
        v(0).Set(0);
        if(rate_of_approach<0) v(1).Set(distance/rate_of_approach);
    }
    else if(rate_of_approach>0) v(0).Set(distance/rate_of_approach);
    return v;
}
//#####################################################################
// Function All_Intersections
//#####################################################################
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)
{
    auto iv=Intersection_Interval(ray,plane,isocontour);
    hits=iv.Array_View(0,Actual_Length(iv));
}
template class BOUNDED_HORIZONTAL_PLANE<VECTOR<float,3> >;
template class BOUNDED_HORIZONTAL_PLANE<VECTOR<double,3> >;
template TRIANGULATED_SURFACE<float>* Generate_Triangles(const BOUNDED_HORIZONTAL_PLANE<VECTOR<float,3> >&);
template TRIANGULATED_SURFACE<double>* Generate_Triangles(const BOUNDED_HORIZONTAL_PLANE<VECTOR<double,3> >&);
template RAY_HIT<double> Intersects<VECTOR<double,2> >(RAY<VECTOR<double,2> > const&,BOUNDED_HORIZONTAL_PLANE<VECTOR<double,2> > const&,VECTOR<double,2>::SCALAR);
template RAY_HIT<double> Intersects<VECTOR<double,3> >(RAY<VECTOR<double,3> > const&,BOUNDED_HORIZONTAL_PLANE<VECTOR<double,3> > const&,VECTOR<double,3>::SCALAR);
template RAY_HIT<float> Intersects<VECTOR<float,2> >(RAY<VECTOR<float,2> > const&,BOUNDED_HORIZONTAL_PLANE<VECTOR<float,2> > const&,VECTOR<float,2>::SCALAR);
template RAY_HIT<float> Intersects<VECTOR<float,3> >(RAY<VECTOR<float,3> > const&,BOUNDED_HORIZONTAL_PLANE<VECTOR<float,3> > const&,VECTOR<float,3>::SCALAR);
template void All_Intersections<VECTOR<double,2>,double>(ARRAY<RAY_HIT<double>,int>&,RAY<VECTOR<double,2> > const&,BOUNDED_HORIZONTAL_PLANE<VECTOR<double,2> > const&,double);
template void All_Intersections<VECTOR<double,3>,double>(ARRAY<RAY_HIT<double>,int>&,RAY<VECTOR<double,3> > const&,BOUNDED_HORIZONTAL_PLANE<VECTOR<double,3> > const&,double);
template void All_Intersections<VECTOR<float,2>,float>(ARRAY<RAY_HIT<float>,int>&,RAY<VECTOR<float,2> > const&,BOUNDED_HORIZONTAL_PLANE<VECTOR<float,2> > const&,float);
template void All_Intersections<VECTOR<float,3>,float>(ARRAY<RAY_HIT<float>,int>&,RAY<VECTOR<float,3> > const&,BOUNDED_HORIZONTAL_PLANE<VECTOR<float,3> > const&,float);
template void BOUNDED_HORIZONTAL_PLANE<VECTOR<double,2> >::Read(UNTYPED_ISTREAM<char>&);
template void BOUNDED_HORIZONTAL_PLANE<VECTOR<double,2> >::Read(UNTYPED_ISTREAM<double>&);
template void BOUNDED_HORIZONTAL_PLANE<VECTOR<double,2> >::Read(UNTYPED_ISTREAM<float>&);
template void BOUNDED_HORIZONTAL_PLANE<VECTOR<double,2> >::Write(UNTYPED_OSTREAM<char>&) const;
template void BOUNDED_HORIZONTAL_PLANE<VECTOR<double,2> >::Write(UNTYPED_OSTREAM<double>&) const;
template void BOUNDED_HORIZONTAL_PLANE<VECTOR<double,2> >::Write(UNTYPED_OSTREAM<float>&) const;
template void BOUNDED_HORIZONTAL_PLANE<VECTOR<double,3> >::Read(UNTYPED_ISTREAM<char>&);
template void BOUNDED_HORIZONTAL_PLANE<VECTOR<double,3> >::Read(UNTYPED_ISTREAM<double>&);
template void BOUNDED_HORIZONTAL_PLANE<VECTOR<double,3> >::Read(UNTYPED_ISTREAM<float>&);
template void BOUNDED_HORIZONTAL_PLANE<VECTOR<double,3> >::Write(UNTYPED_OSTREAM<char>&) const;
template void BOUNDED_HORIZONTAL_PLANE<VECTOR<double,3> >::Write(UNTYPED_OSTREAM<double>&) const;
template void BOUNDED_HORIZONTAL_PLANE<VECTOR<double,3> >::Write(UNTYPED_OSTREAM<float>&) const;
template void BOUNDED_HORIZONTAL_PLANE<VECTOR<float,2> >::Read(UNTYPED_ISTREAM<char>&);
template void BOUNDED_HORIZONTAL_PLANE<VECTOR<float,2> >::Read(UNTYPED_ISTREAM<double>&);
template void BOUNDED_HORIZONTAL_PLANE<VECTOR<float,2> >::Read(UNTYPED_ISTREAM<float>&);
template void BOUNDED_HORIZONTAL_PLANE<VECTOR<float,2> >::Write(UNTYPED_OSTREAM<char>&) const;
template void BOUNDED_HORIZONTAL_PLANE<VECTOR<float,2> >::Write(UNTYPED_OSTREAM<double>&) const;
template void BOUNDED_HORIZONTAL_PLANE<VECTOR<float,2> >::Write(UNTYPED_OSTREAM<float>&) const;
template void BOUNDED_HORIZONTAL_PLANE<VECTOR<float,3> >::Read(UNTYPED_ISTREAM<char>&);
template void BOUNDED_HORIZONTAL_PLANE<VECTOR<float,3> >::Read(UNTYPED_ISTREAM<double>&);
template void BOUNDED_HORIZONTAL_PLANE<VECTOR<float,3> >::Read(UNTYPED_ISTREAM<float>&);
template void BOUNDED_HORIZONTAL_PLANE<VECTOR<float,3> >::Write(UNTYPED_OSTREAM<char>&) const;
template void BOUNDED_HORIZONTAL_PLANE<VECTOR<float,3> >::Write(UNTYPED_OSTREAM<double>&) const;
template void BOUNDED_HORIZONTAL_PLANE<VECTOR<float,3> >::Write(UNTYPED_OSTREAM<float>&) const;
}
