/** * \file * \author Karsten Rink * \date 2014-08-29 * * \copyright * Copyright (c) 2012-2020, 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 #include "gtest/gtest.h" #include "GeoLib/MinimalBoundingSphere.h" #include "MathLib/Point3d.h" TEST(GeoLib, TestBoundingSphere) { std::vector pnts; pnts.push_back(new MathLib::Point3d(std::array({{0, 0 , 0}}))); pnts.push_back(new MathLib::Point3d(std::array({{2, 0 , 0}}))); pnts.push_back(new MathLib::Point3d(std::array({{1, 0.1 , 0}}))); pnts.push_back(new MathLib::Point3d(std::array({{1, -0.1 , 0}}))); { /** * Four points located like this: * * * * * * * * * * Tests if a smaller number of points than available is used if the resulting sphere is smaller. * Expected result is C=(1,0,0), r=1 */ GeoLib::MinimalBoundingSphere s(pnts); MathLib::Point3d center = s.getCenter(); ASSERT_NEAR(1.0, center[0], std::numeric_limits::epsilon()); ASSERT_NEAR(0.0, center[1], std::numeric_limits::epsilon()); ASSERT_NEAR(0.0, center[2], std::numeric_limits::epsilon()); ASSERT_NEAR(1.0, s.getRadius(), std::numeric_limits::epsilon()); } { /** * Four points located like this: * * * * * * * * * * * * The smallest sphere has a diameter that is larger than the distance between any two points. * Expected result is C=(1,0.0246,-0.3446), r=1.058 */ (*pnts[2])[2] -= 1.4; GeoLib::MinimalBoundingSphere s(pnts); MathLib::Point3d center = s.getCenter(); ASSERT_NEAR(1.0, center[0], 0.0001); ASSERT_NEAR(0.0246, center[1], 0.0001); ASSERT_NEAR(-0.3446, center[2], 0.0001); ASSERT_NEAR(1.0580, s.getRadius(), 0.0001); } (*pnts[0])[0] = 0.0; (*pnts[0])[1] = 0.0; (*pnts[0])[2] = 0.0; (*pnts[1])[0] = 1.0; (*pnts[1])[1] = 0.0; (*pnts[1])[2] = 0.0; (*pnts[2])[0] = 1.0; (*pnts[2])[1] = 1.0; (*pnts[2])[2] = 0.0; (*pnts[3])[0] = 0.0; (*pnts[3])[1] = 1.0; (*pnts[3])[2] = 0.0; pnts.push_back(new MathLib::Point3d(std::array({{0, 0, 1}}))); pnts.push_back(new MathLib::Point3d(std::array({{1, 0, 1}}))); pnts.push_back(new MathLib::Point3d(std::array({{1, 1, 1}}))); pnts.push_back(new MathLib::Point3d(std::array({{0, 1, 0.9}}))); { /** * A "cube" where one node is pushed slightly towards the centre (and should be ignored). * Expected result is C=(0.5,0.5,0.5), r=0.866 */ GeoLib::MinimalBoundingSphere s(pnts); MathLib::Point3d center = s.getCenter(); ASSERT_NEAR(0.5, center[0], std::numeric_limits::epsilon()); ASSERT_NEAR(0.5, center[1], std::numeric_limits::epsilon()); ASSERT_NEAR(0.5, center[2], std::numeric_limits::epsilon()); ASSERT_NEAR(0.8660, s.getRadius(), 0.0001); } /** * A "cube" where one node is pulled away from the centre (making the resulting sphere larger). * Expected result is C=(0.5,0.5,0.6), r=0.9273 */ (*pnts[7])[2] += 0.3; GeoLib::MinimalBoundingSphere s(pnts); { MathLib::Point3d center = s.getCenter(); ASSERT_NEAR(0.5, center[0], std::numeric_limits::epsilon()); ASSERT_NEAR(0.5, center[1], std::numeric_limits::epsilon()); ASSERT_NEAR(0.6, center[2], std::numeric_limits::epsilon()); ASSERT_NEAR(0.9273, s.getRadius(), 0.0001); } /// Calculates the bounding sphere of points on a bounding sphere auto sphere_points = std::unique_ptr< std::vector>(s.getRandomSpherePoints(1000)); GeoLib::MinimalBoundingSphere t(*sphere_points); for (auto p : *sphere_points) { delete p; } MathLib::Point3d center = s.getCenter(); ASSERT_NEAR(0.5, center[0], std::numeric_limits::epsilon()); ASSERT_NEAR(0.5, center[1], std::numeric_limits::epsilon()); ASSERT_NEAR(0.6, center[2], std::numeric_limits::epsilon()); ASSERT_NEAR(0.9273, s.getRadius(), 0.0001); std::for_each(pnts.begin(), pnts.end(), std::default_delete()); }