From 9a8dafc4a89f23b0bf1a41f197c9136d89a3fee7 Mon Sep 17 00:00:00 2001 From: Karsten Rink <karsten.rink@ufz.de> Date: Tue, 2 Sep 2014 12:07:04 +0200 Subject: [PATCH] renamed class, adjusted dates, shortened det calculation --- ...ngSphere.cpp => MinimalBoundingSphere.cpp} | 77 +++++++------------ ...undingSphere.h => MinimalBoundingSphere.h} | 42 +++++----- Tests/GeoLib/TestBoundingSphere.cpp | 12 +-- 3 files changed, 55 insertions(+), 76 deletions(-) rename GeoLib/{BoundingSphere.cpp => MinimalBoundingSphere.cpp} (62%) rename GeoLib/{BoundingSphere.h => MinimalBoundingSphere.h} (64%) diff --git a/GeoLib/BoundingSphere.cpp b/GeoLib/MinimalBoundingSphere.cpp similarity index 62% rename from GeoLib/BoundingSphere.cpp rename to GeoLib/MinimalBoundingSphere.cpp index 57f92a70408..19774ae808a 100644 --- a/GeoLib/BoundingSphere.cpp +++ b/GeoLib/MinimalBoundingSphere.cpp @@ -2,17 +2,17 @@ * \file Calculation of a minimum bounding sphere for a vector of points * \author Karsten Rink * \date 2014-07-11 - * \brief Implementation of the BoundingSphere class. + * \brief Implementation of the MinimalBoundingSphere class. * * \copyright - * Copyright (c) 2013, OpenGeoSys Community (http://www.opengeosys.org) + * Copyright (c) 2012-2014, 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 "BoundingSphere.h" +#include "MinimalBoundingSphere.h" #include <ctime> @@ -21,33 +21,17 @@ namespace GeoLib { -BoundingSphere::BoundingSphere() +MinimalBoundingSphere::MinimalBoundingSphere() : _radius(-1), _center(std::numeric_limits<double>::max(), std::numeric_limits<double>::max(), std::numeric_limits<double>::max()) { } -BoundingSphere::BoundingSphere(BoundingSphere const& sphere) -: _radius(sphere.getRadius()), _center(sphere.getCenter()) -{ -} - -BoundingSphere::BoundingSphere(BoundingSphere const&& sphere) -: _radius(sphere.getRadius()), _center(sphere.getCenter()) -{ -} - - -BoundingSphere::BoundingSphere(GeoLib::Point const& p) -: _radius(std::numeric_limits<double>::epsilon()), _center(p) -{ -} - -BoundingSphere::BoundingSphere(GeoLib::Point const& p, double radius) +MinimalBoundingSphere::MinimalBoundingSphere(GeoLib::Point const& p, double radius) : _radius(radius), _center(p) { } -BoundingSphere::BoundingSphere(GeoLib::Point const& p, GeoLib::Point const& q) +MinimalBoundingSphere::MinimalBoundingSphere(GeoLib::Point const& p, GeoLib::Point const& q) : _radius(std::numeric_limits<double>::epsilon()), _center(p) { MathLib::Vector3 const a(p, q); @@ -60,7 +44,7 @@ BoundingSphere::BoundingSphere(GeoLib::Point const& p, GeoLib::Point const& q) } } -BoundingSphere::BoundingSphere(GeoLib::Point const& p, GeoLib::Point const& q, GeoLib::Point const& r) +MinimalBoundingSphere::MinimalBoundingSphere(GeoLib::Point const& p, GeoLib::Point const& q, GeoLib::Point const& r) { MathLib::Vector3 const a(p,r); MathLib::Vector3 const b(p,q); @@ -78,17 +62,17 @@ BoundingSphere::BoundingSphere(GeoLib::Point const& p, GeoLib::Point const& q, G } else { - BoundingSphere two_pnts_sphere; + MinimalBoundingSphere two_pnts_sphere; if (a.getLength() > b.getLength()) - two_pnts_sphere = BoundingSphere(p,r); + two_pnts_sphere = MinimalBoundingSphere(p,r); else - two_pnts_sphere = BoundingSphere(p,q); + two_pnts_sphere = MinimalBoundingSphere(p,q); _radius = two_pnts_sphere.getRadius(); _center = two_pnts_sphere.getCenter(); } } -BoundingSphere::BoundingSphere(GeoLib::Point const& p, GeoLib::Point const& q, GeoLib::Point const& r, GeoLib::Point const& s) +MinimalBoundingSphere::MinimalBoundingSphere(GeoLib::Point const& p, GeoLib::Point const& q, GeoLib::Point const& r, GeoLib::Point const& s) { MathLib::Vector3 const a(p, q); MathLib::Vector3 const b(p, r); @@ -96,10 +80,7 @@ BoundingSphere::BoundingSphere(GeoLib::Point const& p, GeoLib::Point const& q, G if (!GeoLib::isCoplanar(p, q, r, s)) { - // det of matrix [a^T, b^T, c^T]^T - double const denom = 2.0 * (a[0] * (b[1] * c[2] - c[1] * b[2]) - - b[0] * (a[1] * c[2] - c[1] * a[2]) - + c[0] * (a[1] * b[2] - b[1] * a[2])); + double const denom = 2.0 * GeoLib::scalarTriple(a,b,c); MathLib::Vector3 const o = (scalarProduct(c,c) * crossProduct(a,b) + scalarProduct(b,b) * crossProduct(c,a) + scalarProduct(a,a) * crossProduct(b,c)) @@ -110,10 +91,10 @@ BoundingSphere::BoundingSphere(GeoLib::Point const& p, GeoLib::Point const& q, G } else { - BoundingSphere const pqr(p, q , r); - BoundingSphere const pqs(p, q , s); - BoundingSphere const prs(p, r , s); - BoundingSphere const qrs(q, r , s); + MinimalBoundingSphere const pqr(p, q , r); + MinimalBoundingSphere const pqs(p, q , s); + MinimalBoundingSphere const prs(p, r , s); + MinimalBoundingSphere const qrs(q, r , s); _radius = pqr.getRadius(); _center = pqr.getCenter(); if (_radius < pqs.getRadius()) @@ -134,36 +115,34 @@ BoundingSphere::BoundingSphere(GeoLib::Point const& p, GeoLib::Point const& q, G } } -BoundingSphere::BoundingSphere(std::vector<GeoLib::Point*> const& points) -: _center(0,0,0), _radius(-1) +MinimalBoundingSphere::MinimalBoundingSphere(std::vector<GeoLib::Point*> const& points) +: _radius(-1), _center(0,0,0) { - std::size_t const n_points (points.size()); std::vector<GeoLib::Point*> sphere_points(points); - - BoundingSphere const bounding_sphere = recurseCalculation(sphere_points, 0, sphere_points.size(), 0); + MinimalBoundingSphere const bounding_sphere = recurseCalculation(sphere_points, 0, sphere_points.size(), 0); _center = bounding_sphere.getCenter(); _radius = bounding_sphere.getRadius(); } -BoundingSphere BoundingSphere::recurseCalculation(std::vector<GeoLib::Point*> sphere_points, std::size_t start_idx, std::size_t length, std::size_t n_boundary_points) +MinimalBoundingSphere MinimalBoundingSphere::recurseCalculation(std::vector<GeoLib::Point*> sphere_points, std::size_t start_idx, std::size_t length, std::size_t n_boundary_points) { - BoundingSphere sphere; + MinimalBoundingSphere sphere; switch(n_boundary_points) { case 0: - sphere = BoundingSphere(); + sphere = MinimalBoundingSphere(); break; case 1: - sphere = BoundingSphere(*sphere_points[start_idx-1]); + sphere = MinimalBoundingSphere(*sphere_points[start_idx-1]); break; case 2: - sphere = BoundingSphere(*sphere_points[start_idx-1], *sphere_points[start_idx-2]); + sphere = MinimalBoundingSphere(*sphere_points[start_idx-1], *sphere_points[start_idx-2]); break; case 3: - sphere = BoundingSphere(*sphere_points[start_idx-1], *sphere_points[start_idx-2], *sphere_points[start_idx-3]); + sphere = MinimalBoundingSphere(*sphere_points[start_idx-1], *sphere_points[start_idx-2], *sphere_points[start_idx-3]); break; case 4: - sphere = BoundingSphere(*sphere_points[start_idx-1], *sphere_points[start_idx-2], *sphere_points[start_idx-3], *sphere_points[start_idx-4]); + sphere = MinimalBoundingSphere(*sphere_points[start_idx-1], *sphere_points[start_idx-2], *sphere_points[start_idx-3], *sphere_points[start_idx-4]); return sphere; } @@ -184,12 +163,12 @@ BoundingSphere BoundingSphere::recurseCalculation(std::vector<GeoLib::Point*> sp return sphere; } -double BoundingSphere::pointDistanceSquared(GeoLib::Point const& pnt) const +double MinimalBoundingSphere::pointDistanceSquared(GeoLib::Point const& pnt) const { return MathLib::sqrDist(_center.getCoords(), pnt.getCoords())-(_radius*_radius); } -std::vector<GeoLib::Point*>* BoundingSphere::getRandomSpherePoints(std::size_t n_points) const +std::vector<GeoLib::Point*>* MinimalBoundingSphere::getRandomSpherePoints(std::size_t n_points) const { std::vector<GeoLib::Point*> *pnts = new std::vector<GeoLib::Point*>; pnts->reserve(n_points); diff --git a/GeoLib/BoundingSphere.h b/GeoLib/MinimalBoundingSphere.h similarity index 64% rename from GeoLib/BoundingSphere.h rename to GeoLib/MinimalBoundingSphere.h index 1ec2d467d30..cf3f48665ce 100644 --- a/GeoLib/BoundingSphere.h +++ b/GeoLib/MinimalBoundingSphere.h @@ -2,10 +2,10 @@ * \file Calculation of a minimum bounding sphere for a vector of points * \author Karsten Rink * \date 2014-07-11 - * \brief Definition of the BoundingSphere class. + * \brief Definition of the MinimalBoundingSphere class. * * \copyright - * Copyright (c) 2013, OpenGeoSys Community (http://www.opengeosys.org) + * Copyright (c) 2012-2014, OpenGeoSys Community (http://www.opengeosys.org) * Distributed under a Modified BSD License. * See accompanying file LICENSE.txt or * http://www.opengeosys.org/project/license @@ -13,8 +13,8 @@ * */ -#ifndef BOUNDINGSPHERE_H_ -#define BOUNDINGSPHERE_H_ +#ifndef MINIMALBOUNDINGSPHERE_H_ +#define MINIMALBOUNDINGSPHERE_H_ #include <vector> @@ -24,28 +24,25 @@ namespace GeoLib { -class BoundingSphere +/** + * Calculated center and radius of a minimal bounding sphere for a given number of geometric points. + */ +class MinimalBoundingSphere { public: - /// Constructor using no points - BoundingSphere(); /// Copy constructor - BoundingSphere(BoundingSphere const& sphere); - /// Move constructor - BoundingSphere(BoundingSphere const&& sphere); + MinimalBoundingSphere(MinimalBoundingSphere const& sphere) = default; /// Point-Sphere - BoundingSphere(GeoLib::Point const& p); - /// Constructor using center and radius - BoundingSphere(GeoLib::Point const& p, double radius); + MinimalBoundingSphere(GeoLib::Point const& p, double radius = std::numeric_limits<double>::epsilon()); /// Bounding sphere using two points - BoundingSphere(GeoLib::Point const& p, GeoLib::Point const& q); + MinimalBoundingSphere(GeoLib::Point const& p, GeoLib::Point const& q); /// Bounding sphere using three points - BoundingSphere(GeoLib::Point const& p, GeoLib::Point const& q, GeoLib::Point const& r); + MinimalBoundingSphere(GeoLib::Point const& p, GeoLib::Point const& q, GeoLib::Point const& r); /// Bounding sphere using four points - BoundingSphere(GeoLib::Point const& p, GeoLib::Point const& q, GeoLib::Point const& r, GeoLib::Point const& s); + MinimalBoundingSphere(GeoLib::Point const& p, GeoLib::Point const& q, GeoLib::Point const& r, GeoLib::Point const& s); /// Bounding sphere of n points - BoundingSphere(std::vector<GeoLib::Point*> const& points); - ~BoundingSphere() {} + MinimalBoundingSphere(std::vector<GeoLib::Point*> const& points); + ~MinimalBoundingSphere() {} /// Returns the center point of the sphere GeoLib::Point getCenter() const { return GeoLib::Point(_center.getCoords()); } @@ -60,6 +57,9 @@ public: std::vector<GeoLib::Point*>* getRandomSpherePoints(std::size_t n_points) const; private: + /// Constructor using no points + MinimalBoundingSphere(); + /** * Recursive method for calculating a minimal bounding sphere for an arbitrary number of points. * Note: This method will change the order of elements in the vector sphere_points. @@ -70,10 +70,10 @@ private: * * Algorithm based the following two papers: * Emo Welzl: Smallest enclosing disks (balls and ellipsoids). New Results and New Trends in Computer Science, pp. 359--370, 1991 - * Bernd Gärtner: Fast and Robust Smallest Enclosing Balls. ESA99, pp. 325--338, 1999. + * Bernd Gaertner: Fast and Robust Smallest Enclosing Balls. ESA99, pp. 325--338, 1999. * Code based on "Smallest Enclosing Spheres" implementation by Nicolas Capens on flipcode's Developer Toolbox (www.flipcode.com) */ - static BoundingSphere recurseCalculation(std::vector<GeoLib::Point*> sphere_points, std::size_t start_idx, std::size_t length, std::size_t n_boundary_points); + static MinimalBoundingSphere recurseCalculation(std::vector<GeoLib::Point*> sphere_points, std::size_t start_idx, std::size_t length, std::size_t n_boundary_points); double _radius; MathLib::Vector3 _center; @@ -81,4 +81,4 @@ private: } // namespace -#endif /* BOUNDINGSPHERE_H_ */ +#endif /* MINIMALBOUNDINGSPHERE_H_ */ diff --git a/Tests/GeoLib/TestBoundingSphere.cpp b/Tests/GeoLib/TestBoundingSphere.cpp index 96697e9ffe9..69c00f3014a 100644 --- a/Tests/GeoLib/TestBoundingSphere.cpp +++ b/Tests/GeoLib/TestBoundingSphere.cpp @@ -4,7 +4,7 @@ * \date 2014-08-29 * * \copyright - * Copyright (c) 2013, OpenGeoSys Community (http://www.opengeosys.org) + * Copyright (c) 2012-2014, OpenGeoSys Community (http://www.opengeosys.org) * Distributed under a Modified BSD License. * See accompanying file LICENSE.txt or * http://www.opengeosys.org/project/license @@ -14,7 +14,7 @@ #include "gtest/gtest.h" -#include "GeoLib/BoundingSphere.h" +#include "GeoLib/MinimalBoundingSphere.h" #include "GeoLib/Point.h" TEST(GeoLib, TestBoundingSphere) @@ -40,7 +40,7 @@ TEST(GeoLib, TestBoundingSphere) * 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::BoundingSphere s(pnts); + GeoLib::MinimalBoundingSphere s(pnts); GeoLib::Point center = s.getCenter(); ASSERT_NEAR(1.0, center[0], std::numeric_limits<double>::epsilon()); ASSERT_NEAR(0.0, center[1], std::numeric_limits<double>::epsilon()); @@ -62,7 +62,7 @@ TEST(GeoLib, TestBoundingSphere) * Expected result is C=(1,0.0246,-0.3446), r=1.058 */ (*pnts[2])[2] -= 1.4; - GeoLib::BoundingSphere s(pnts); + GeoLib::MinimalBoundingSphere s(pnts); GeoLib::Point center = s.getCenter(); ASSERT_NEAR(1.0, center[0], 0.0001); ASSERT_NEAR(0.0246, center[1], 0.0001); @@ -84,7 +84,7 @@ TEST(GeoLib, TestBoundingSphere) * 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::BoundingSphere s(pnts); + GeoLib::MinimalBoundingSphere s(pnts); GeoLib::Point center = s.getCenter(); ASSERT_NEAR(0.5, center[0], std::numeric_limits<double>::epsilon()); ASSERT_NEAR(0.5, center[1], std::numeric_limits<double>::epsilon()); @@ -98,7 +98,7 @@ TEST(GeoLib, TestBoundingSphere) * Expected result is C=(0.5,0.5,0.6), r=0.9273 */ (*pnts[7])[2] += 0.3; - GeoLib::BoundingSphere s(pnts); + GeoLib::MinimalBoundingSphere s(pnts); GeoLib::Point center = s.getCenter(); ASSERT_NEAR(0.5, center[0], std::numeric_limits<double>::epsilon()); ASSERT_NEAR(0.5, center[1], std::numeric_limits<double>::epsilon()); -- GitLab