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

    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

    An intersection of a PolygonSequence polyhedron and a halfspace. Composites
    the resulting intersection polyhedron and the intersection points.

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

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

#ifndef PolyhedronIntersection_HPP
#define PolyhedronIntersection_HPP

#include "tag.hpp"
#include "Polyhedron.hpp"

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

namespace geophase {  

/*---------------------------------------------------------------------------*\
                         Class PolyhedronIntersection Declaration
\*---------------------------------------------------------------------------*/

template<typename PolygonSequence>  
class PolyhedronIntersectionBase 
{

public:

    typedef PolygonSequence Polyhedron; 
    typedef typename PolygonSequence::value_type PointSequence;
    typedef typename PointSequence::value_type Point;

    PolyhedronIntersectionBase() = default; 

    PolyhedronIntersectionBase(PolygonSequence const & polyhedron) 
        :
            polyhedron_(polyhedron)
    {}

    const PolygonSequence& polyhedron() const
    {
        return polyhedron_; 
    }

    void addPolygon(PointSequence const& p)
    {
        polyhedron_.push_back(p);  
    }

    auto polygon_size() const
    {
        return polyhedron_.back().size(); 
    }

    auto polyhedron_size() const
    {
        return polyhedron_.size(); 
    }

    template<typename Point>
    void addIntersectionPoint(Point const & p)
    {
        intersectionPoints_.push_back(p); 
    }

    const PointSequence& intersectionPoints() const
    {
        return intersectionPoints_; 
    }

    template<typename Points>
    void addIntersectionPoints(Points const & points)
    {
        for (const auto& point : points)
        {
            intersectionPoints_.push_back(point); 
        }
    }


    template<typename Points> 
    void setIntersectionPoints(Points const& points)
    {   
        intersectionPoints_ = points; 
    }

    decltype(auto) capPolygon() const
    {
        return intersectionPoints_; 
    }

    void clear() 
    {
        polyhedron_.clear(); 
        intersectionPoints_.clear(); 
    }

protected:

    PolygonSequence polyhedron_; 

    PointSequence intersectionPoints_; 
};

template<typename PolygonSequence>  
class PolyhedronIntersection 
:
    public PolyhedronIntersectionBase<PolygonSequence>
{};

template<>  
class PolyhedronIntersection<vectorPolyhedron> 
:
    public PolyhedronIntersectionBase<vectorPolyhedron>
{
    typedef PolyhedronIntersectionBase<vectorPolyhedron> Base;

    public: 

    PolyhedronIntersection()
    {
        Base::intersectionPoints_.reserve(8); 
        Base::polyhedron_.reserve(8); 
    } 

    PolyhedronIntersection(const vectorPolyhedron& polyhedron) 
        :
            Base(polyhedron) 
    {
        PolyhedronIntersection(); 
    }
};

using vectorPolyhedronIntersection = PolyhedronIntersection<vectorPolyhedron>;

} // End namespace geophase 

#endif

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