//#####################################################################
// Copyright 2021, Craig Schroeder.
// This file is part of PhysBAM whose distribution is governed by the license contained in the accompanying file PHYSBAM_COPYRIGHT.txt.
//#####################################################################
#ifndef __INTERSECTION_HELPERS__
#define __INTERSECTION_HELPERS__

#include <Core/Arrays/ARRAYS_FORWARD.h>
#include <Core/Basic_Geometry/BASIC_GEOMETRY_FORWARD.h>
namespace PhysBAM{
template<class T> class RAY_HIT;

// type:  0=intersect, 1=difference, 2=union
template<class T>
int Boolean(ARRAY_VIEW<RAY_HIT<T> > o,ARRAY_VIEW<const RAY_HIT<T> > a,
    ARRAY_VIEW<const RAY_HIT<T> > b,int type);
template<class T>
inline int Intersection(ARRAY_VIEW<RAY_HIT<T> > o,ARRAY_VIEW<const RAY_HIT<T> > a,
    ARRAY_VIEW<const RAY_HIT<T> > b)
{return Boolean(o,a,b,0);}
template<class T>
inline int Difference(ARRAY_VIEW<RAY_HIT<T> > o,ARRAY_VIEW<const RAY_HIT<T> > a,
    ARRAY_VIEW<const RAY_HIT<T> > b)
{return Boolean(o,a,b,1);}
template<class T>
inline int Union(ARRAY_VIEW<RAY_HIT<T> > o,ARRAY_VIEW<const RAY_HIT<T> > a,
    ARRAY_VIEW<const RAY_HIT<T> > b)
{return Boolean(o,a,b,2);}

template<class T>
void Boolean(ARRAY<RAY_HIT<T> >& o,const ARRAY<RAY_HIT<T> >& a,
    const ARRAY<RAY_HIT<T> >& b,int type);
template<class T>
inline void Intersection(ARRAY<RAY_HIT<T> >& o,const ARRAY<RAY_HIT<T> >& a,
    const ARRAY<RAY_HIT<T> >& b)
{Boolean(o,a,b,0);}
template<class T>
inline void Difference(ARRAY<RAY_HIT<T> >& o,const ARRAY<RAY_HIT<T> >& a,
    const ARRAY<RAY_HIT<T> >& b)
{Boolean(o,a,b,1);}
template<class T>
inline void Union(ARRAY<RAY_HIT<T> >& o,const ARRAY<RAY_HIT<T> >& a,
    const ARRAY<RAY_HIT<T> >& b)
{Boolean(o,a,b,2);}

template<class T,int m> int
Actual_Length(const VECTOR<RAY_HIT<T>,m>& a)
{
    for(int i=0;i<m;i++)
        if(!a(i).Hit())
            return i;
    return m;
}
template<class T,int m,int n>
inline VECTOR<RAY_HIT<T>,(m+n)> Intersection(const VECTOR<RAY_HIT<T>,m>& a,
    const VECTOR<RAY_HIT<T>,n>& b)
{
    VECTOR<RAY_HIT<T>,(m+n)> o;
    ARRAY_VIEW<const RAY_HIT<T> > ha(a),hb(b);
    ha.m=Actual_Length(a);
    hb.m=Actual_Length(b);
    Boolean<T>(o,ha,hb,0);
    return o;
}
template<class T,int m,int n>
inline VECTOR<RAY_HIT<T>,m+n> Difference(const VECTOR<RAY_HIT<T>,m>& a,
    const VECTOR<RAY_HIT<T>,n>& b)
{
    VECTOR<RAY_HIT<T>,m+n> o;
    ARRAY_VIEW<const RAY_HIT<T> > ha(a),hb(b);
    ha.m=Actual_Length(a);
    hb.m=Actual_Length(b);
    Boolean<T>(o,ha,hb,1);
    return o;
}
template<class T,int m,int n>
inline VECTOR<RAY_HIT<T>,m+n> Union(const VECTOR<RAY_HIT<T>,m>& a,
    const VECTOR<RAY_HIT<T>,n>& b)
{
    VECTOR<RAY_HIT<T>,m+n> o;
    ARRAY_VIEW<const RAY_HIT<T> > ha(a),hb(b);
    ha.m=Actual_Length(a);
    hb.m=Actual_Length(b);
    Boolean<T>(o,ha,hb,2);
    return o;
}
}
#endif
