// // SPDX-License-Identifier: BSD-3-Clause // Copyright Contributors to the OpenEXR Project. // // // A 3D sphere class template // #ifndef INCLUDED_IMATHSPHERE_H #define INCLUDED_IMATHSPHERE_H #include "ImathExport.h" #include "ImathNamespace.h" #include "ImathBox.h" #include "ImathLine.h" #include "ImathVec.h" IMATH_INTERNAL_NAMESPACE_HEADER_ENTER /// /// A 3D sphere /// template class IMATH_EXPORT_TEMPLATE_TYPE Sphere3 { public: /// @{ /// @name Direct access to member fields /// Center Vec3 center; /// Radius T radius; /// @} /// @{ /// @name Constructors /// Default is center at (0,0,0) and radius of 0. IMATH_HOSTDEVICE constexpr Sphere3() : center (0, 0, 0), radius (0) {} /// Initialize to a given center and radius IMATH_HOSTDEVICE constexpr Sphere3 (const Vec3& c, T r) : center (c), radius (r) {} /// @} /// @{ /// @name Manipulation /// Set the center and radius of the sphere so that it tightly /// encloses Box b. IMATH_HOSTDEVICE void circumscribe (const Box>& box); /// @} /// @{ /// @name Utility Methods /// If the sphere and line `l` intersect, then compute the /// smallest `t` with `t>=0` so that `l(t)` is a point on the sphere. /// /// @param[in] l The line /// @param[out] intersection The point of intersection /// @return True if the sphere and line intersect, false if they /// do not. IMATH_HOSTDEVICE IMATH_CONSTEXPR14 bool intersect (const Line3& l, Vec3& intersection) const; /// If the sphere and line `l` intersect, then compute the /// smallest `t` with `t>=0` so that `l(t)` is a point on the sphere. /// /// @param[in] l The line /// @param[out] t The parameter of the line at the intersection point /// @return True if the sphere and line intersect, false if they /// do not. IMATH_HOSTDEVICE IMATH_CONSTEXPR14 bool intersectT (const Line3& l, T& t) const; /// @} }; /// Sphere of type float typedef Sphere3 Sphere3f; /// Sphere of type double typedef Sphere3 Sphere3d; //--------------- // Implementation //--------------- template IMATH_HOSTDEVICE inline void Sphere3::circumscribe (const Box>& box) { center = T (0.5) * (box.min + box.max); radius = (box.max - center).length(); } template IMATH_HOSTDEVICE IMATH_CONSTEXPR14 bool Sphere3::intersectT (const Line3& line, T& t) const { bool doesIntersect = true; Vec3 v = line.pos - center; T B = T (2.0) * (line.dir ^ v); T C = (v ^ v) - (radius * radius); // compute discriminant // if negative, there is no intersection T discr = B * B - T (4.0) * C; if (discr < 0.0) { // line and Sphere3 do not intersect doesIntersect = false; } else { // t0: (-B - sqrt(B^2 - 4AC)) / 2A (A = 1) T sqroot = std::sqrt (discr); t = (-B - sqroot) * T (0.5); if (t < 0.0) { // no intersection, try t1: (-B + sqrt(B^2 - 4AC)) / 2A (A = 1) t = (-B + sqroot) * T (0.5); } if (t < 0.0) doesIntersect = false; } return doesIntersect; } template IMATH_CONSTEXPR14 bool Sphere3::intersect (const Line3& line, Vec3& intersection) const { T t (0); if (intersectT (line, t)) { intersection = line (t); return true; } else { return false; } } IMATH_INTERNAL_NAMESPACE_HEADER_EXIT #endif // INCLUDED_IMATHSPHERE_H