https://gitlab.opengeosys.org/ogs/ogs.git
Raw File
Tip revision: 35d2cf594b1daa447bc5708c1c22f9b640086f33 authored by Lars Bilke on 23 July 2021, 11:28:16 UTC
Merge branch 'pre-commit-format' into 'master'
Tip revision: 35d2cf5
TestAABB.cpp
/**
 * \file
 * \author Thomas Fischer
 * \date   Oct 24, 2012
 * \brief  Tests of AABB class.
 *
 * \copyright
 * Copyright (c) 2012-2021, OpenGeoSys Community (http://www.opengeosys.org)
 *            Distributed under a Modified BSD License.
 *              See accompanying file LICENSE.txt or
 *              http://www.opengeosys.org/project/license
 *
 */

#include <gtest/gtest.h>

#include <cstdlib>
#include <ctime>
#include <list>
#include <random>

#include "GeoLib/AABB.h"
#include "GeoLib/Point.h"
#include "MathLib/Point3d.h"

TEST(GeoLibAABB, RandomNumberOfPointersToRandomPoints)
{
    /* initialize random seed: */
    srand(static_cast<unsigned>(time(nullptr)));
    int n(rand() % 100000);
    int box_size(rand());
    double half_box_size(box_size / 2);
    double minus_half_box_size(-half_box_size);

    // fill list with points
    std::list<GeoLib::Point*> pnts_list;
    for (int k(0); k < n; k++)
    {
        pnts_list.push_back(
            new GeoLib::Point(rand() % box_size - half_box_size,
                              rand() % box_size - half_box_size,
                              rand() % box_size - half_box_size));
    }

    // construct from list points a axis aligned bounding box
    GeoLib::AABB aabb(pnts_list.begin(), pnts_list.end());

    auto const& min_pnt(aabb.getMinPoint());
    auto const& max_pnt(aabb.getMaxPoint());

    ASSERT_LE(minus_half_box_size, min_pnt[0])
        << "coordinate 0 of min_pnt is smaller than " << minus_half_box_size;
    ASSERT_LE(minus_half_box_size, min_pnt[1])
        << "coordinate 1 of min_pnt is smaller than " << minus_half_box_size;
    ASSERT_LE(minus_half_box_size, min_pnt[2])
        << "coordinate 2 of min_pnt is smaller than " << minus_half_box_size;

    // since the interval is half-open we have to move the upper bound also
    half_box_size =
        std::nexttoward(half_box_size, std::numeric_limits<double>::max());
    ASSERT_GE(half_box_size, max_pnt[0])
        << "coordinate 0 of max_pnt is greater than " << half_box_size;
    ASSERT_GE(half_box_size, max_pnt[1])
        << "coordinate 1 of max_pnt is greater than " << half_box_size;
    ASSERT_GE(half_box_size, max_pnt[2])
        << "coordinate 2 of max_pnt is greater than " << half_box_size;

    for (auto& point : pnts_list)
    {
        delete point;
    }
}

TEST(GeoLibAABB, RandomNumberOfPointsRandomPointInAList)
{
    /* initialize random seed: */
    srand(static_cast<unsigned>(time(nullptr)));
    int n(rand() % 1000000);
    int box_size(rand());
    double half_box_size(box_size / 2);
    double minus_half_box_size(-half_box_size);

    // fill list with points
    std::list<GeoLib::Point> pnts_list;
    for (int k(0); k < n; k++)
    {
        pnts_list.emplace_back(rand() % box_size - half_box_size,
                               rand() % box_size - half_box_size,
                               rand() % box_size - half_box_size);
    }

    // construct from list points a axis aligned bounding box
    GeoLib::AABB aabb(pnts_list.begin(), pnts_list.end());

    auto const& min_pnt(aabb.getMinPoint());
    auto const& max_pnt(aabb.getMaxPoint());

    ASSERT_LE(minus_half_box_size, min_pnt[0])
        << "coordinate 0 of min_pnt is smaller than " << minus_half_box_size;
    ASSERT_LE(minus_half_box_size, min_pnt[1])
        << "coordinate 1 of min_pnt is smaller than " << minus_half_box_size;
    ASSERT_LE(minus_half_box_size, min_pnt[2])
        << "coordinate 2 of min_pnt is smaller than " << minus_half_box_size;

    // since the interval is half-open we have to move the upper bound also
    half_box_size =
        std::nexttoward(half_box_size, std::numeric_limits<double>::max());
    ASSERT_GE(half_box_size, max_pnt[0])
        << "coordinate 0 of max_pnt is greater than " << half_box_size;
    ASSERT_GE(half_box_size, max_pnt[1])
        << "coordinate 1 of max_pnt is greater than " << half_box_size;
    ASSERT_GE(half_box_size, max_pnt[2])
        << "coordinate 2 of max_pnt is greater than " << half_box_size;
}

TEST(GeoLibAABB, RandomNumberOfPointersToRandomPointsInAVector)
{
    /* initialize random seed: */
    srand(static_cast<unsigned>(time(nullptr)));
    int n(rand() % 100000);
    int box_size(rand());
    double half_box_size(box_size / 2);
    double minus_half_box_size(-half_box_size);

    // fill list with points
    std::vector<GeoLib::Point*> pnts;
    for (int k(0); k < n; k++)
    {
        pnts.push_back(new GeoLib::Point(rand() % box_size - half_box_size,
                                         rand() % box_size - half_box_size,
                                         rand() % box_size - half_box_size));
    }

    // construct from list points a axis aligned bounding box
    GeoLib::AABB aabb(pnts.begin(), pnts.end());

    auto const& min_pnt(aabb.getMinPoint());
    auto const& max_pnt(aabb.getMaxPoint());

    ASSERT_LE(minus_half_box_size, min_pnt[0])
        << "coordinate 0 of min_pnt is smaller than " << minus_half_box_size;
    ASSERT_LE(minus_half_box_size, min_pnt[1])
        << "coordinate 1 of min_pnt is smaller than " << minus_half_box_size;
    ASSERT_LE(minus_half_box_size, min_pnt[2])
        << "coordinate 2 of min_pnt is smaller than " << minus_half_box_size;

    // since the interval is half-open we have to move the upper bound also
    half_box_size =
        std::nexttoward(half_box_size, std::numeric_limits<double>::max());
    ASSERT_GE(half_box_size, max_pnt[0])
        << "coordinate 0 of max_pnt is greater than " << half_box_size;
    ASSERT_GE(half_box_size, max_pnt[1])
        << "coordinate 1 of max_pnt is greater than " << half_box_size;
    ASSERT_GE(half_box_size, max_pnt[2])
        << "coordinate 2 of max_pnt is greater than " << half_box_size;

    for (auto& point : pnts)
    {
        delete point;
    }
}

TEST(GeoLibAABB, RandomNumberOfPointsRandomPointInAVector)
{
    /* initialize random seed: */
    srand(static_cast<unsigned>(time(nullptr)));
    int n(rand() % 1000000);
    int box_size(rand());
    double half_box_size(box_size / 2);
    double minus_half_box_size(-half_box_size);

    // fill list with points
    std::list<GeoLib::Point> pnts;
    for (int k(0); k < n; k++)
    {
        pnts.emplace_back(rand() % box_size - half_box_size,
                          rand() % box_size - half_box_size,
                          rand() % box_size - half_box_size);
    }

    // construct from list points a axis aligned bounding box
    GeoLib::AABB aabb(pnts.begin(), pnts.end());

    auto const& min_pnt(aabb.getMinPoint());
    auto const& max_pnt(aabb.getMaxPoint());

    ASSERT_LE(minus_half_box_size, min_pnt[0])
        << "coordinate 0 of min_pnt is smaller than " << minus_half_box_size;
    ASSERT_LE(minus_half_box_size, min_pnt[1])
        << "coordinate 1 of min_pnt is smaller than " << minus_half_box_size;
    ASSERT_LE(minus_half_box_size, min_pnt[2])
        << "coordinate 2 of min_pnt is smaller than " << minus_half_box_size;

    // since the interval is half-open we have to move the upper bound also
    half_box_size =
        std::nexttoward(half_box_size, std::numeric_limits<double>::max());
    ASSERT_GE(half_box_size, max_pnt[0])
        << "coordinate 0 of max_pnt is greater than " << half_box_size;
    ASSERT_GE(half_box_size, max_pnt[1])
        << "coordinate 1 of max_pnt is greater than " << half_box_size;
    ASSERT_GE(half_box_size, max_pnt[2])
        << "coordinate 2 of max_pnt is greater than " << half_box_size;
}

TEST(GeoLibAABB, RandomNumberOfPointsRandomBox)
{
    /* initialize random seed: */
    srand(static_cast<unsigned>(time(nullptr)));
    int n(rand() % 1000000);
    int box_size_x(rand());
    int box_size_y(rand());
    int box_size_z(rand());
    double half_box_size_x(box_size_x / 2);
    double half_box_size_y(box_size_y / 2);
    double half_box_size_z(box_size_z / 2);
    auto minus_half_box_size_x(static_cast<int>(-half_box_size_x));
    auto minus_half_box_size_y(static_cast<int>(-half_box_size_y));
    auto minus_half_box_size_z(static_cast<int>(-half_box_size_z));

    // fill list with points
    std::list<GeoLib::Point> pnts;
    for (int k(0); k < n; k++)
    {
        pnts.emplace_back(rand() % box_size_x - half_box_size_x,
                          rand() % box_size_y - half_box_size_y,
                          rand() % box_size_z - half_box_size_z);
    }

    // construct from list points a axis aligned bounding box
    GeoLib::AABB aabb(pnts.begin(), pnts.end());

    auto const& min_pnt(aabb.getMinPoint());
    auto const& max_pnt(aabb.getMaxPoint());

    ASSERT_LE(minus_half_box_size_x, min_pnt[0])
        << "coordinate 0 of min_pnt is smaller than " << minus_half_box_size_x;
    ASSERT_LE(minus_half_box_size_y, min_pnt[1])
        << "coordinate 1 of min_pnt is smaller than " << minus_half_box_size_y;
    ASSERT_LE(minus_half_box_size_z, min_pnt[2])
        << "coordinate 2 of min_pnt is smaller than " << minus_half_box_size_z;

    // since the interval is half-open we have to move the upper bound also
    half_box_size_x =
        std::nexttoward(half_box_size_x, std::numeric_limits<double>::max());
    half_box_size_y =
        std::nexttoward(half_box_size_y, std::numeric_limits<double>::max());
    half_box_size_z =
        std::nexttoward(half_box_size_z, std::numeric_limits<double>::max());
    ASSERT_GE(half_box_size_x, max_pnt[0])
        << "coordinate 0 of max_pnt is greater than " << half_box_size_x;
    ASSERT_GE(half_box_size_y, max_pnt[1])
        << "coordinate 1 of max_pnt is greater than " << half_box_size_y;
    ASSERT_GE(half_box_size_z, max_pnt[2])
        << "coordinate 2 of max_pnt is greater than " << half_box_size_z;
}

TEST(GeoLib, AABBAllPointsWithNegativeCoordinatesI)
{
    std::vector<GeoLib::Point*> pnts;
    pnts.push_back(new GeoLib::Point(-1, -1, -1));
    pnts.push_back(new GeoLib::Point(-10, -10, -10));

    std::vector<std::size_t> ids;
    ids.push_back(0);
    ids.push_back(1);
    GeoLib::AABB aabb(pnts, ids);

    auto const& max_pnt(aabb.getMaxPoint());

    ASSERT_NEAR(-1.0, max_pnt[0], std::numeric_limits<double>::epsilon());
    ASSERT_NEAR(-1.0, max_pnt[1], std::numeric_limits<double>::epsilon());
    ASSERT_NEAR(-1.0, max_pnt[2], std::numeric_limits<double>::epsilon());

    for (auto p : pnts)
    {
        delete p;
    }
}

TEST(GeoLib, AABBAllPointsWithNegativeCoordinatesII)
{
    std::vector<GeoLib::Point> pnts;

    pnts.emplace_back(-1, -1, -1);
    pnts.emplace_back(-10, -10, -10);

    // construct from points of the vector a axis aligned bounding box
    GeoLib::AABB aabb(pnts.begin(), pnts.end());

    auto const& max_pnt(aabb.getMaxPoint());

    ASSERT_NEAR(-1.0, max_pnt[0], std::numeric_limits<double>::epsilon());
    ASSERT_NEAR(-1.0, max_pnt[1], std::numeric_limits<double>::epsilon());
    ASSERT_NEAR(-1.0, max_pnt[2], std::numeric_limits<double>::epsilon());
}

// This test creates an AABB containing a single point.
// This point is moved in every space direction to the next possible double
// value. It is checked that the AABB contains the point iff it has not been
// moved.
TEST(GeoLib, AABBSinglePoint)
{
    std::random_device rd;
    std::mt19937 random_number_generator(rd());
    std::uniform_real_distribution<double> rnd(-1000000.0, 10000000.0);
    std::vector<GeoLib::Point> pnts;
    GeoLib::Point p{
        {{rnd(random_number_generator), rnd(random_number_generator),
          rnd(random_number_generator)}}};
    pnts.push_back(p);

    ASSERT_EQ(1u, pnts.size());

    // construct from points of the vector a axis aligned bounding box
    GeoLib::AABB aabb(pnts.begin(), pnts.end());

    double const to_lowest(std::numeric_limits<double>::lowest());
    double const to_max(std::numeric_limits<double>::max());

    // Check the point within the aabb (i==j==k). The outer 26 (3 * 3 * 3 - 1)
    // points around the aabb are also checked.
    for (int i(-1); i < 2; ++i)
    {
        // Modify the first coordinate of p.
        if (i == -1)
        {
            p[0] = std::nextafter(pnts.front()[0], to_lowest);
        }
        else if (i == 0)
        {
            p[0] = pnts.front()[0];
        }
        else
        {
            p[0] = std::nextafter(pnts.front()[0], to_max);
        }
        for (int j(-1); j < 2; ++j)
        {
            // Modify the second coordinate of p.
            if (j == -1)
            {
                p[1] = std::nextafter(pnts.front()[1], to_lowest);
            }
            else if (j == 0)
            {
                p[1] = pnts.front()[1];
            }
            else
            {
                p[1] = std::nextafter(pnts.front()[1], to_max);
            }
            for (int k(-1); k < 2; ++k)
            {
                // Modify the third coordinate of p.
                if (k == -1)
                {
                    p[2] = std::nextafter(pnts.front()[2], to_lowest);
                }
                else if (k == 0)
                {
                    p[2] = pnts.front()[2];
                }
                else
                {
                    p[2] = std::nextafter(pnts.front()[2], to_max);
                }
                if (i == 0 && j == 0 && k == 0)
                {
                    ASSERT_TRUE(aabb.containsPoint(p, 0));
                }
                else
                {
                    ASSERT_FALSE(aabb.containsPoint(p, 0));
                }
            }
        }
    }
}
back to top