//#####################################################################
// Copyright 2003-2008, Christopher Allocco, Ronald Fedkiw, Geoffrey Irving, Neil Molino, Igor Neverov, Duc Nguyen, Andrew Selle, Joseph Teran.
// This file is part of PhysBAM whose distribution is governed by the license contained in the accompanying file PHYSBAM_COPYRIGHT.txt.
//#####################################################################
// Class TRIANGLULATED_AREA
//##################################################################### 
#ifndef __TRIANGULATED_AREA__
#define __TRIANGULATED_AREA__

#include <Core/Basic_Geometry/TRIANGLE_2D.h>
#include <Core/Meshes/MESH_OBJECT_BASE.h>
#include <Core/Meshes/TRIANGLE_MESH.h>
#include <Core/Spatial_Acceleration/SPATIAL_ACCELERATION_FORWARD.h>
#include <Core/Vectors/VECTOR.h>
namespace PhysBAM{

template<class TV> class GRID;
template<class TV> class IMPLICIT_OBJECT;

template<class T>
class MESH_OBJECT<VECTOR<T,2>,2>:public MESH_OBJECT_BASE<VECTOR<T,2>,TRIANGLE_MESH>
{
    typedef VECTOR<T,2> TV;typedef VECTOR<int,2> IV;
    typedef MESH_HIERARCHY<TV,TRIANGLE_MESH>* T_HIERARCHY;
public:
    typedef MESH_OBJECT_BASE<TV,TRIANGLE_MESH> BASE;
    using BASE::mesh;using BASE::particles;using BASE::bounding_box;
    using BASE::Refresh_Auxiliary_Structures;using BASE::Rescale;
    using BASE::hierarchy;

    SEGMENTED_CURVE<TV>* segmented_curve;
    ARRAY<T>* nodal_areas;

    MESH_OBJECT();
    MESH_OBJECT(TRIANGLE_MESH& triangle_mesh_input,GEOMETRY_PARTICLES<TV>& particles_input);
    virtual ~MESH_OBJECT();

    SEGMENT_MESH& Get_Segment_Mesh()
    {return mesh.Get_Segment_Mesh();}

    SEGMENTED_CURVE<TV>& Get_Boundary_Object()
    {if(!segmented_curve) Initialize_Segmented_Curve();
    return *segmented_curve;}

    TRIANGLE_2D<T> Get_Element(const int aggregate_id) const
    {return TRIANGLE_2D<T>(particles.X.Subset(mesh.elements(aggregate_id)));}

    T Element_Size(const int triangle) const
    {return Area(triangle);}

    virtual std::string Name() const override {return Static_Name();}
    static std::string Static_Name()
    {return "SIMPLICIAL_OBJECT<T,VECTOR<T,2>,2>";}

    virtual std::string Extension() const override {return Static_Extension();}
    static std::string Static_Extension()
    {return "tri2d";}

    T Total_Size() const
    {return Total_Area(); }

    T Size(const int triangle) const
    {return Area(triangle);}

    T Signed_Size(const int triangle) const
    {return Signed_Area(triangle);}

//#####################################################################
    void Clean_Memory() override;
    void Initialize_Square_Mesh_And_Particles(const GRID<TV>& grid,const bool reverse_triangles=false);
    void Initialize_Circle_Mesh_And_Particles(const T outer_radius,const T inner_radius,const int num_radial,const int num_tangential);
    void Initialize_Herring_Bone_Mesh_And_Particles(const GRID<TV>& grid);
    void Initialize_Equilateral_Mesh_And_Particles(const GRID<TV>& grid);
    int Inside(const TV& location,const T thickness_over_two=0) const;
    bool Inside_Any_Simplex(const VECTOR<T,2>& location,int& triangle_id,const T thickness_over_two) const;
    void Check_Signed_Area_And_Make_Consistent(const int triangle,const bool verbose);
    void Check_Signed_Areas_And_Make_Consistent(const bool verbose=true);
    TV Centroid(const int triangle) const;
    void Rescale(const T scaling_factor) override;
    void Rescale(const T scaling_x,const T scaling_y);
    T Area(const int triangle) const;
    T Signed_Area(const int triangle) const;
    T Minimum_Area(int* index=0) const;
    T Minimum_Signed_Area(int* index=0) const;   
    T Total_Area() const;
    T Minimum_Altitude(int* index=0) const;
    T Minimum_Edge_Length(int* index=0) const;
    T Maximum_Edge_Length(int* index=0) const;
    void Initialize_Segmented_Curve();
    T Area_Incident_On_A_Particle(const int particle_index);
private:
    void Refresh_Auxiliary_Structures_Helper() override;
//#####################################################################
};
}
#endif

