/*---------------------------------------------------------------------------*\

    geophase: A C++ template library for geometrical operations on non-convex
    polyhedra with non-planar faces
     
    Copyright (C) 2019 Tomislav Maric, TU Darmstadt 

    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.


Description
    Triangulation intersection implemented as two vectors, one for tetrahedra
    contained within the halfspace, one for polyhedra resulting from
    intersections.

Author
    Tomislav Maric maric@mma.tu-darmstadt.de

\*---------------------------------------------------------------------------*/

#ifndef TriangulationIntersection_H
#define TriangulationIntersection_H

#include <vector>
#include <memory>
#include <algorithm>
#include "tag.H"

// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //

namespace Foam { namespace GeometricalTransport { 

/*---------------------------------------------------------------------------*\
                         Class TriangulationIntersection Declaration
\*---------------------------------------------------------------------------*/

template<typename Triangulation, typename P>  
class TriangulationIntersection 
{

public:

    typedef typename Triangulation::value_type Tetrahedron; 
    typedef P Polyhedron;
    typedef std::vector<Polyhedron> polyhedronContainer;

    TriangulationIntersection()
    {
        polyhedra_.reserve(24);
    } 

    TriangulationIntersection(Triangulation const& tri)
        :
            tetrahedra_(tri),
            polyhedra_()
    {
        polyhedra_.reserve(tri.size());
    }
    
    template<typename Q>
    void addPolyhedron(Q const & q)
    {
        polyhedra_.push_back(q); 
    }

    template<typename T>
    void addTetrahedron(T const & t)
    {
        tetrahedra_.push_back(t); 
    }

    void append(TriangulationIntersection const & other)
    {
        for(const auto& tetrahedron : other.tetrahedra())
        {
            this->addTetrahedron(tetrahedron);
        }

        for(const auto& polyhedron : other.polyhedra())
        {
            this->addPolyhedron(polyhedron);
        }
    }

    auto tetrahera_begin()
    {
        return tetrahedra_.begin(); 
    }

    auto tetrahera_begin() const
    {
        return tetrahedra_.begin(); 
    }

    auto tetrahedra_end()
    {
        return tetrahedra_.end(); 
    }

    auto tetrahedra_end() const
    {
        return tetrahedra_.end(); 
    }

    const auto& tetrahedra() const
    {
        return tetrahedra_; 
    }

    const auto& polyhedra() const
    {
        return polyhedra_;  
    }

    auto polyhedra_size() const
    {
        return polyhedra_.size(); 
    }

    auto tetrahedra_size() const
    {
        return tetrahedra_.size(); 
    }

    auto size() 
    {
        return tetrahedra_.size() + polyhedra_.size(); 
    }

    bool empty() const
    { 
        return (tetrahedra_.empty() && polyhedra_.empty()); 
    }

private:

    Triangulation tetrahedra_; 
    polyhedronContainer polyhedra_;
};

namespace Traits
{
    template<typename Triangulation, typename Polyhedron>
    struct tag<TriangulationIntersection<Triangulation, Polyhedron>>
    {
        typedef triangulation_intersection_tag type;
    };

// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //

} // End namespace Traits 

// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //

}} // End namespace Foam::GeometricalTransport

// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //

#endif

// ************************************************************************* //
