120 return 4 * TNumTraits::pi *
num::sqr(radius_);
128const typename Sphere3D<T>::TValue
131 return (4 * TNumTraits::pi *
num::sqr(radius_) * radius_) / 3;
152const typename Sphere3D<T>::TValue
155 const TVector difference = iPoint - center_;
165const typename Sphere3D<T>::TValue
169 return eq >= TNumTraits::zero ? num::sqrt(eq) : -num::sqrt(-eq);
177const typename Sphere3D<T>::TValue
192 return eq <= TNumTraits::zero;
203 const TValue eq =
equation(iPoint, iRelativeTolerance);
213const typename Sphere3D<T>::TValue
216 const TVector difference = iPoint - center_;
218 const TValue r2 =
num::sqr(radius_);
219 return num::almostEqual(d2, r2, iRelativeTolerance) ? TNumTraits::zero : (d2 - r2);
228const typename Sphere3D<T>::TValue
231 const TValue eq =
equation(iPoint, iRelativeTolerance);
232 return eq >= TNumTraits::zero ? num::sqrt(eq) : -num::sqrt(-eq);
240const typename Sphere3D<T>::TValue
254 const TValue eq =
equation(iPoint, iRelativeTolerance);
255 return eq <= TNumTraits::zero;
265 return radius_ >= TNumTraits::zero;
293const T distance(
const Sphere3D<T>& sphere,
const Point3D<T>& point)
295 return num::sqrt(sphere.squaredDistance(point));
303bool intersects(
const Sphere3D<T>& a,
const Sphere3D<T>& b)
305 return (a.center() - b.center()).squaredNorm() <= num::sqr(a.radius() + b.radius());
311 template <
typename T>
312 Sphere3D<T> circumSphere2(
const Point3D<T>& a,
const Point3D<T>& b)
314 const auto center = (a + b).affine();
315 const auto radius = distance(a, b) / 2;
316 return Sphere3D<T>(center, radius);
319 template <
typename T>
320 Sphere3D<T> circumSphere3(
const Point3D<T>& a,
const Point3D<T>& b,
const Point3D<T>& c)
322 const auto v1 = b - a;
323 const auto v2 = c - a;
324 const auto n = cross(v1, v2);
325 const auto center = a + cross(v1.squaredNorm() * v2 - v2.squaredNorm() * v1, n) / (2 * n.squaredNorm());
326 const auto radius = distance(center, a);
327 return Sphere3D<T>(center, radius);
330 template <
typename T>
331 Sphere3D<T> circumSphere4(
const Point3D<T>& a,
const Point3D<T>& b,
const Point3D<T>& c,
const Point3D<T>& d)
334 const auto v1 = b - a;
335 const auto v2 = c - a;
336 const auto v3 = d - a;
337 const auto d1 = v1.squaredNorm();
338 const auto d2 = v2.squaredNorm();
339 const auto d3 = v3.squaredNorm();
340 const auto center = a + (d1 * cross(v2, v3) + d2 * cross(v3, v1) + d3 * cross(v1, v2)) / (2 * dot(v1, cross(v2, v3)));
341 const auto radius = distance(center, a);
342 return Sphere3D<T>(center, radius);
345 template <
typename T,
typename ForwardIterator>
346 Sphere3D<T> boundingSphere(std::vector<ForwardIterator>& points,
size_t size,
size_t bounds)
361 sphere = circumSphere2(*points[0], *points[1]);
365 sphere = circumSphere3(*points[0], *points[1], *points[2]);
369 return circumSphere4(*points[0], *points[1], *points[2], *points[3]);
371 throw std::logic_error(
"invalid bounds");
374 for (; i < size; ++i)
376 T bestE = sphere.equation(*points[i]);
378 for (
size_t k = i + 1; k < size; ++k)
380 const T e = sphere.equation(*points[k]);
391 ForwardIterator p = points[best];
392 for (
size_t k = best; k > bounds; --k)
394 points[k] = points[k - 1];
397 sphere = boundingSphere<T>(points, i + 1, bounds + 1);
408template <
typename T,
typename ForwardIterator>
409Sphere3D<T> boundingSphere(ForwardIterator first, ForwardIterator last)
411 using TSphere = Sphere3D<T>;
412 using TNumTraits =
typename TSphere::TNumTraits;
413 using TPoint =
typename TSphere::TPoint;
415 std::vector<ForwardIterator> points;
416 for (ForwardIterator p = first; p != last; ++p)
421 const size_t size = points.size();
426 const auto nan = TNumTraits::qNaN;
427 return TSphere(TPoint(nan, nan, nan), nan);
430 return TSphere(*points[0], TNumTraits::zero);
433 return impl::boundingSphere<T>(points, size, 0);
440Sphere3D<T> boundingSphere(
const std::vector<Point3D<T>>& points)
442 return boundingSphere<T>(points.begin(), points.end());
450std::ostream& operator<<(std::ostream& ioOStream,
const Sphere3D<T>& iSphere)
452 LASS_ENFORCE(ioOStream) <<
"{S=" << iSphere.center() <<
", r=" << iSphere.radius() <<
"}";
461io::XmlOStream& operator<<(io::XmlOStream& ioOStream,
const Sphere3D<T>& iSphere)
463 LASS_ENFORCE_STREAM(ioOStream)
465 <<
"<center>" << iSphere.center() <<
"</center>\n"
466 <<
"<radius>" << iSphere.radius() <<
"</radius>\n"