/*---------------------------------------------------------------------------*\
  =========                 |
  \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
   \\    /   O peration     |
    \\  /    A nd           | Copyright (C) 2013 OpenFOAM Foundation
     \\/     M anipulation  |
-------------------------------------------------------------------------------
License
    This file is part of OpenFOAM.

    OpenFOAM 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.

    OpenFOAM 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 OpenFOAM.  If not, see <http://www.gnu.org/licenses/>.

Application
    geomTestNormal 

Description
    Test normal calculation algorithms. 
   
Authors
    Tomislav Maric maric@csi.tu-darmstadt.de

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

#include "fvCFD.H"
#include "Geometry.H"

using namespace GeometricalTransport;

#include "gtest/gtest.h" 

// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
// Main program:

TEST(normal, triangle)
{
    auto triangle = build<arrayTriangle>(point(0,0,0), point(1,0,0), point(0,1,0)); 

    auto triangleAreaNormal = normal_area_vec(triangle); 

    ASSERT_TRUE(mag(triangleAreaNormal) == 0.5); 
}

TEST(normal, squarePolygon) 
{
    pointVector square = {{0,0,0}, {2,0,0}, {2,2,0}, {0,2,0}}; 

    // Choose the barycentric triangulation strategy and type of the result.
    typedef barycentric_triangulation<triangleVector> barycentricTriangulation;  

    auto squareNormal = normal_area_vec<barycentricTriangulation>(square); 

    ASSERT_TRUE(mag(squareNormal) == 4) << mag(squareNormal) << std::endl; 

    ASSERT_TRUE((squareNormal & vector(0,0,1)) > 0);

    // Choose the oriented triangulation strategy and type of the result.
    typedef oriented_triangulation<triangleVector> orientedTriangulation; 

    squareNormal = normal_area_vec<orientedTriangulation>(square); 

    ASSERT_TRUE(mag(squareNormal) == 4); 


    ASSERT_TRUE((squareNormal & vector(0,0,1)) > 0);
}

TEST(normal, perturbedSquarePolygon) 
{
    pointVector square = {{0,0,0}, {2,0,0}, {2,2,0}, {0,2,0}}; 

    const double EPSILON = 1e-15; 

    perturb(square, EPSILON); 

    auto squareHspace = build<Halfspace<point,point>>(square); 

    const auto& squareNormal = squareHspace.direction(); 

    ASSERT_TRUE((squareNormal & vector(0,0,1)) > 0)
        << "n = " << squareNormal[0] << " " 
        << squareNormal[1] << " " 
        << squareNormal[1] << "\n"
        << "mag(n) = " << mag(squareNormal) << "\n";  

    ASSERT_LE(mag(squareNormal ^ vector(0,0,1)), EPSILON)
        << "n = " << squareNormal[0] << " " 
        << squareNormal[1] << " " 
        << squareNormal[1] << "\n"
        << "mag(n) = " << mag(squareNormal) << "\n";  
}
TEST(normal, perturbedBoxPolyhedron) 
{
    typedef AABBox<point> aabbox; 
    auto polyhedron = build<pointVectorVector>(aabbox(point(0,0,0),point(1,1,1))); 

    const double EPSILON = 1e-15; 
    perturb(polyhedron, EPSILON); 

    for (const auto& polygon : polyhedron)
    {
        auto polygonHspace = build<Halfspace<point,point>>(polygon); 

        const auto& polygonNormal = polygonHspace.direction(); 

        auto polygonNormalArea = normal_area_vec(polygon);  

        ASSERT_LE(mag(polygonNormal - polygonNormalArea), EPSILON)
           << "polygonNormal : " << polygonNormal << "\n" 
           << "polygonNormalArea : " << polygonNormalArea << "\n";
    }
}


int main(int argc, char *argv[])
{
    ::testing::InitGoogleTest(&argc, argv);
    return RUN_ALL_TESTS();
}


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