OGS
MinimalBoundingSphere.cpp
Go to the documentation of this file.
1 
15 #include "MinimalBoundingSphere.h"
16 
17 #include <ctime>
18 
20 #include "MathLib/MathTools.h"
21 #include "MathLib/Point3d.h"
22 
23 namespace GeoLib
24 {
26 
28  double radius)
29  : _radius(radius), _center(p)
30 {
31 }
32 
34  MathLib::Point3d const& q)
35  : _radius(std::numeric_limits<double>::epsilon()), _center(p)
36 {
37  auto const vp = Eigen::Map<Eigen::Vector3d const>(p.getCoords());
38  auto const vq = Eigen::Map<Eigen::Vector3d const>(q.getCoords());
39  Eigen::Vector3d const a = vq - vp;
40 
41  Eigen::Vector3d o = a / 2;
42  _radius = o.norm() + std::numeric_limits<double>::epsilon();
43  o += vp;
44  _center = MathLib::Point3d{{o[0], o[1], o[2]}};
45 }
46 
48  MathLib::Point3d const& q,
49  MathLib::Point3d const& r)
50 {
51  auto const vp = Eigen::Map<Eigen::Vector3d const>(p.getCoords());
52  auto const vq = Eigen::Map<Eigen::Vector3d const>(q.getCoords());
53  auto const vr = Eigen::Map<Eigen::Vector3d const>(r.getCoords());
54  Eigen::Vector3d const a = vr - vp;
55  Eigen::Vector3d const b = vq - vp;
56  Eigen::Vector3d const axb = a.cross(b);
57 
58  if (axb.squaredNorm() > 0)
59  {
60  double const denom = 2.0 * axb.dot(axb);
61  Eigen::Vector3d o =
62  (b.dot(b) * axb.cross(a) + a.dot(a) * b.cross(axb)) / denom;
63  _radius = o.norm() + std::numeric_limits<double>::epsilon();
64  o += vp;
65  _center = MathLib::Point3d{{o[0], o[1], o[2]}};
66  }
67  else
68  {
69  MinimalBoundingSphere two_pnts_sphere;
70  if (a.squaredNorm() > b.squaredNorm())
71  {
72  two_pnts_sphere = MinimalBoundingSphere(p, r);
73  }
74  else
75  {
76  two_pnts_sphere = MinimalBoundingSphere(p, q);
77  }
78  _radius = two_pnts_sphere.getRadius();
79  _center = two_pnts_sphere.getCenter();
80  }
81 }
82 
84  MathLib::Point3d const& q,
85  MathLib::Point3d const& r,
86  MathLib::Point3d const& s)
87 {
88  auto const vp = Eigen::Map<Eigen::Vector3d const>(p.getCoords());
89  auto const vq = Eigen::Map<Eigen::Vector3d const>(q.getCoords());
90  auto const vr = Eigen::Map<Eigen::Vector3d const>(r.getCoords());
91  auto const vs = Eigen::Map<Eigen::Vector3d const>(s.getCoords());
92 
93  Eigen::Vector3d const va = vq - vp;
94  Eigen::Vector3d const vb = vr - vp;
95  Eigen::Vector3d const vc = vs - vp;
96 
97  if (!MathLib::isCoplanar(p, q, r, s))
98  {
99  double const denom = 2.0 * va.cross(vb).dot(vc);
100  Eigen::Vector3d o =
101  (vc.dot(vc) * va.cross(vb) + vb.dot(vb) * vc.cross(va) +
102  va.dot(va) * vb.cross(vc)) /
103  denom;
104 
105  _radius = o.norm() + std::numeric_limits<double>::epsilon();
106  o += vp;
107  _center = MathLib::Point3d({o[0], o[1], o[2]});
108  }
109  else
110  {
111  MinimalBoundingSphere const pqr(p, q, r);
112  MinimalBoundingSphere const pqs(p, q, s);
113  MinimalBoundingSphere const prs(p, r, s);
114  MinimalBoundingSphere const qrs(q, r, s);
115  _radius = pqr.getRadius();
116  _center = pqr.getCenter();
117  if (_radius < pqs.getRadius())
118  {
119  _radius = pqs.getRadius();
120  _center = pqs.getCenter();
121  }
122  if (_radius < prs.getRadius())
123  {
124  _radius = prs.getRadius();
125  _center = prs.getCenter();
126  }
127  if (_radius < qrs.getRadius())
128  {
129  _radius = qrs.getRadius();
130  _center = qrs.getCenter();
131  }
132  }
133 }
134 
136  std::vector<MathLib::Point3d*> const& points)
137  : _radius(-1), _center({0, 0, 0})
138 {
139  const std::vector<MathLib::Point3d*>& sphere_points(points);
140  MinimalBoundingSphere const bounding_sphere =
141  recurseCalculation(sphere_points, 0, sphere_points.size(), 0);
142  _center = bounding_sphere.getCenter();
143  _radius = bounding_sphere.getRadius();
144 }
145 
147  std::vector<MathLib::Point3d*> sphere_points,
148  std::size_t start_idx,
149  std::size_t length,
150  std::size_t n_boundary_points)
151 {
152  MinimalBoundingSphere sphere;
153  switch (n_boundary_points)
154  {
155  case 0:
156  sphere = MinimalBoundingSphere();
157  break;
158  case 1:
159  sphere = MinimalBoundingSphere(*sphere_points[start_idx - 1]);
160  break;
161  case 2:
162  sphere = MinimalBoundingSphere(*sphere_points[start_idx - 1],
163  *sphere_points[start_idx - 2]);
164  break;
165  case 3:
166  sphere = MinimalBoundingSphere(*sphere_points[start_idx - 1],
167  *sphere_points[start_idx - 2],
168  *sphere_points[start_idx - 3]);
169  break;
170  case 4:
171  sphere = MinimalBoundingSphere(
172  *sphere_points[start_idx - 1], *sphere_points[start_idx - 2],
173  *sphere_points[start_idx - 3], *sphere_points[start_idx - 4]);
174  return sphere;
175  }
176 
177  for (std::size_t i = 0; i < length; ++i)
178  {
179  // current point is located outside of sphere
180  if (sphere.pointDistanceSquared(*sphere_points[start_idx + i]) > 0)
181  {
182  if (i > start_idx)
183  {
184  using DiffType =
185  std::vector<MathLib::Point3d*>::iterator::difference_type;
186  std::vector<MathLib::Point3d*> const tmp_ps(
187  sphere_points.cbegin() + static_cast<DiffType>(start_idx),
188  sphere_points.cbegin() +
189  static_cast<DiffType>(start_idx + i + 1));
190  std::copy(tmp_ps.cbegin(), --tmp_ps.cend(),
191  sphere_points.begin() +
192  static_cast<DiffType>(start_idx + 1));
193  sphere_points[start_idx] = tmp_ps.back();
194  }
195  sphere = recurseCalculation(sphere_points, start_idx + 1, i,
196  n_boundary_points + 1);
197  }
198  }
199  return sphere;
200 }
201 
203  MathLib::Point3d const& pnt) const
204 {
205  return MathLib::sqrDist(_center, pnt) - (_radius * _radius);
206 }
207 
208 } // namespace GeoLib
Calculation of a minimum bounding sphere for a vector of points.
Definition of the Point3d class.
static MinimalBoundingSphere recurseCalculation(std::vector< MathLib::Point3d * > sphere_points, std::size_t start_idx, std::size_t length, std::size_t n_boundary_points)
MinimalBoundingSphere()
Constructor using no points.
double getRadius() const
Returns the radius of the sphere.
MathLib::Point3d getCenter() const
Returns the center point of the sphere.
double pointDistanceSquared(MathLib::Point3d const &pnt) const
Returns the squared euclidean distance of a point from the sphere (for points within the sphere dista...
const T * getCoords() const
Definition: TemplatePoint.h:75
void copy(PETScVector const &x, PETScVector &y)
Definition: LinAlg.cpp:37
static const double q
bool isCoplanar(const MathLib::Point3d &a, const MathLib::Point3d &b, const MathLib::Point3d &c, const MathLib::Point3d &d)
Checks if the four given points are located on a plane.
MathLib::TemplatePoint< double, 3 > Point3d
static const double r
double sqrDist(MathLib::Point3d const &p0, MathLib::Point3d const &p1)
Definition: Point3d.h:48