//#####################################################################
// Copyright 2002-2007, Robert Bridson, Ronald Fedkiw, Eran Guendelman, Geoffrey Irving, Nipun Kwatra, Neil Molino, Andrew Selle, Jonathan Su, Joseph Teran.
// This file is part of PhysBAM whose distribution is governed by the license contained in the accompanying file PHYSBAM_COPYRIGHT.txt.
//#####################################################################
// Class INTERSECTING_PAIRS_VISITOR
//##################################################################### 
#include <Deformables/Collisions_And_Interactions/INTERSECTING_PAIRS_VISITOR.h>
#include <Core/Basic_Geometry/SEGMENT_2D.h>
#include <Core/Data_Structures/HASHTABLE.h>
#include <Core/Intersections/SEGMENT_2D_SEGMENT_2D_INTERSECTION.h>
#include <Core/Intersections/SEGMENT_3D_TRIANGLE_3D_INTERSECTION.h>
#include <Deformables/Collisions_And_Interactions/STRUCTURE_INTERACTION_GEOMETRY.h>
namespace PhysBAM
{
//#####################################################################
// Constructor
//#####################################################################
template<class TV> INTERSECTING_PAIRS_VISITOR<TV>::
INTERSECTING_PAIRS_VISITOR(HASHTABLE<VECTOR<int,d+1> >& intersecting_point_face_pairs,HASHTABLE<VECTOR<int,2*d-2> >& intersecting_edge_edge_pairs,
    const STRUCTURE_INTERACTION_GEOMETRY<TV>& segment_structure,STRUCTURE_INTERACTION_GEOMETRY<TV>& face_structure,
    const ARRAY<TV>& X_self_collision_free,const T thickness_over_2,int& count)
    :intersecting_point_face_pairs(intersecting_point_face_pairs),intersecting_edge_edge_pairs(intersecting_edge_edge_pairs),face_structure(face_structure),
    segments(segment_structure.segmented_curve->mesh.elements),faces(face_structure.Face_Mesh_Object()->mesh.elements),
    X_self_collision_free(X_self_collision_free),thickness_over_2(thickness_over_2),count(count)
{}
//#####################################################################
// Destructor
//#####################################################################
template<class TV> INTERSECTING_PAIRS_VISITOR<TV>::
~INTERSECTING_PAIRS_VISITOR()
{}
//#####################################################################
// Function Store
//#####################################################################
template<class TV> void INTERSECTING_PAIRS_VISITOR<TV>::
Store(const int segment,const int face)
{
    if(segments(segment).Contains_Any(faces(face))) return;
    if constexpr(TV::m==2)
    {
        const VECTOR<VECTOR<int,2>,2> nodes(segments(segment),faces(face));
        if(Intersects(SEGMENT_2D<T>(X_self_collision_free.Subset(nodes[0])),SEGMENT_2D<T>(X_self_collision_free.Subset(nodes[1])),thickness_over_2)) return;
        for(int i=0;i<2;i++){int j=1-i;
            for(int a=0;a<2;a++){
                intersecting_point_face_pairs.Set(VECTOR<int,3>(nodes[i][a],nodes[j][0],nodes[j][1]));
                for(int b=0;b<2;b++) intersecting_edge_edge_pairs.Set(VECTOR<int,2>(nodes[i][a],nodes[j][b]));}}
        count++;
    }
    else
    {
        const VECTOR<int,2>& segment_nodes=segments(segment);
        const VECTOR<int,3>& triangle_nodes=faces(face);
        if(Intersects(SEGMENT_3D<T>(X_self_collision_free.Subset(segment_nodes)),TRIANGLE_3D<T>(X_self_collision_free.Subset(triangle_nodes)),thickness_over_2))
            return;
        if(!face_structure.triangulated_surface->mesh.element_edges) face_structure.triangulated_surface->mesh.Initialize_Element_Edges();
        const VECTOR<int,3>& triangle_edges=(*face_structure.triangulated_surface->mesh.element_edges)(face);
        for(int a=0;a<2;a++) intersecting_point_face_pairs.Set(VECTOR<int,4>(segment_nodes[a],triangle_nodes[0],triangle_nodes[1],triangle_nodes[2]));
        for(int a=0;a<3;a++){
            const VECTOR<int,2> other_segment_nodes=segments(triangle_edges[a]); // need to use triangle_edges to get the correct segment orientation
            intersecting_edge_edge_pairs.Set(VECTOR<int,4>(segment_nodes[0],segment_nodes[1],other_segment_nodes[0],other_segment_nodes[1]));
            intersecting_edge_edge_pairs.Set(VECTOR<int,4>(other_segment_nodes[0],other_segment_nodes[1],segment_nodes[0],segment_nodes[1]));}
        count++;
    }
}
//####################################################################
template class INTERSECTING_PAIRS_VISITOR<VECTOR<double,2> >;
template class INTERSECTING_PAIRS_VISITOR<VECTOR<double,3> >;
template class INTERSECTING_PAIRS_VISITOR<VECTOR<float,2> >;
template class INTERSECTING_PAIRS_VISITOR<VECTOR<float,3> >;
}
