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

    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
    Volume correction. 

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

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

#ifndef CorrectVolume_H 
#define CorrectVolume_H 

#include "Volume.H"
#include "Build.H"

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

namespace Foam { namespace GeometricalTransport {

    // Correct volume of a polygon sequence by replacing one of its polygons with 
    // a triangle cone with an adjustable peak point in the direction of the polygon
    // normal area vector. TM
    template
    <
        typename MixedPolyhedron, 
        typename PolygonSequence, 
        typename Label, 
        typename RT
    > 
    typename std::enable_if
    <
        Traits::tag_enabled<PolygonSequence, polygon_sequence_tag>::value &&
        Traits::tag_enabled<MixedPolyhedron, mixed_polyhedron_tag>::value,
        MixedPolyhedron 
    >::type 
    correct_volume(
        PolygonSequence const& polyhedron, 
        Label polygonLabel, 
        RT volumeDifference
    )
    {
        auto polygonIter = std::next(polyhedron.begin(), polygonLabel); 

        const auto polygonAreaNormal = normal_area_vec(*polygonIter); 

        const auto delta = (3.0 * volumeDifference) / (polygonAreaNormal & polygonAreaNormal); 

        const auto polygonCentroid = centroid(*polygonIter); 

        const auto conePeakPoint = polygonCentroid + delta * polygonAreaNormal; 

        return build<MixedPolyhedron>(polyhedron, conePeakPoint, polygonLabel);
    }

    // Correct volume of a polygon sequence by replacing one of its polygons with 
    // a triangle cone with an adjustable peak point in a given direction. TM
    template
    <
        typename MixedPolyhedron, 
        typename PolygonSequence, 
        typename Label, 
        typename Vector, 
        typename RT
    > 
    typename std::enable_if
    <
        Traits::tag_enabled<PolygonSequence, polygon_sequence_tag>::value &&
        Traits::tag_enabled<MixedPolyhedron, mixed_polyhedron_tag>::value,
        MixedPolyhedron 
    >::type 
    correct_volume(
        PolygonSequence const& polyhedron, 
        Label polygonLabel,
        Vector d,
        RT volumeDifference
    )
    {
        auto polygonIter = std::next(polyhedron.begin(), polygonLabel); 

        const auto polygonAreaNormal = normal_area_vec(*polygonIter); 

        const auto delta = (3.0 * volumeDifference) / (d & polygonAreaNormal); 

        const auto polygonCentroid = centroid(*polygonIter); 

        const auto conePeakPoint = polygonCentroid + delta * d; 

        return build<MixedPolyhedron>(polyhedron, conePeakPoint, polygonLabel);
    }

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

}} // End namespace Foam::GeometricalTransport

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

#endif

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