// // SPDX-License-Identifier: BSD-3-Clause // Copyright Contributors to the OpenEXR Project. // // // A 3D line class template // #ifndef INCLUDED_IMATHLINE_H #define INCLUDED_IMATHLINE_H #include "ImathMatrix.h" #include "ImathNamespace.h" #include "ImathVec.h" IMATH_INTERNAL_NAMESPACE_HEADER_ENTER /// /// The `Line3` class represents a 3D line, defined by a point and a /// direction vector. /// template class Line3 { public: /// @{ /// @name Direct access to member fields /// A point on the line Vec3 pos; /// The direction of the line Vec3 dir; /// @} /// @{ /// @name Constructors /// Uninitialized by default IMATH_HOSTDEVICE constexpr Line3() IMATH_NOEXCEPT {} /// Initialize with two points. The direction is the difference /// between the points. IMATH_HOSTDEVICE IMATH_CONSTEXPR14 Line3 (const Vec3& point1, const Vec3& point2) IMATH_NOEXCEPT; /// @} /// @{ /// @name Manipulation /// Set the line defined by two points. The direction is the difference /// between the points. IMATH_HOSTDEVICE void set (const Vec3& point1, const Vec3& point2) IMATH_NOEXCEPT; /// @} /// @{ /// @name Utility Methods /// Return the point on the line at the given parameter value, /// e.g. L(t) IMATH_HOSTDEVICE constexpr Vec3 operator() (T parameter) const IMATH_NOEXCEPT; /// Return the distance to the given point IMATH_HOSTDEVICE constexpr T distanceTo (const Vec3& point) const IMATH_NOEXCEPT; /// Return the distance to the given line IMATH_HOSTDEVICE IMATH_CONSTEXPR14 T distanceTo (const Line3& line) const IMATH_NOEXCEPT; /// Return the point on the line closest to the given point IMATH_HOSTDEVICE constexpr Vec3 closestPointTo (const Vec3& point) const IMATH_NOEXCEPT; /// Return the point on the line closest to the given line IMATH_HOSTDEVICE IMATH_CONSTEXPR14 Vec3 closestPointTo (const Line3& line) const IMATH_NOEXCEPT; /// @} }; /// Line of type float typedef Line3 Line3f; /// Line of type double typedef Line3 Line3d; template IMATH_HOSTDEVICE IMATH_CONSTEXPR14 inline Line3::Line3 (const Vec3& p0, const Vec3& p1) IMATH_NOEXCEPT { set (p0, p1); } template IMATH_HOSTDEVICE inline void Line3::set (const Vec3& p0, const Vec3& p1) IMATH_NOEXCEPT { pos = p0; dir = p1 - p0; dir.normalize(); } template IMATH_HOSTDEVICE constexpr inline Vec3 Line3::operator() (T parameter) const IMATH_NOEXCEPT { return pos + dir * parameter; } template IMATH_HOSTDEVICE constexpr inline T Line3::distanceTo (const Vec3& point) const IMATH_NOEXCEPT { return (closestPointTo (point) - point).length(); } template IMATH_HOSTDEVICE constexpr inline Vec3 Line3::closestPointTo (const Vec3& point) const IMATH_NOEXCEPT { return ((point - pos) ^ dir) * dir + pos; } template IMATH_HOSTDEVICE IMATH_CONSTEXPR14 inline T Line3::distanceTo (const Line3& line) const IMATH_NOEXCEPT { T d = (dir % line.dir) ^ (line.pos - pos); return (d >= 0) ? d : -d; } template IMATH_HOSTDEVICE IMATH_CONSTEXPR14 inline Vec3 Line3::closestPointTo (const Line3& line) const IMATH_NOEXCEPT { // Assumes the lines are normalized Vec3 posLpos = pos - line.pos; T c = dir ^ posLpos; T a = line.dir ^ dir; T f = line.dir ^ posLpos; T num = c - a * f; T denom = a * a - 1; T absDenom = ((denom >= 0) ? denom : -denom); if (absDenom < 1) { T absNum = ((num >= 0) ? num : -num); if (absNum >= absDenom * std::numeric_limits::max()) return pos; } return pos + dir * (num / denom); } /// Stream output, as "(pos dir)" template std::ostream& operator<< (std::ostream& o, const Line3& line) { return o << "(" << line.pos << ", " << line.dir << ")"; } /// Transform a line by a matrix template IMATH_HOSTDEVICE constexpr inline Line3 operator* (const Line3& line, const Matrix44& M) IMATH_NOEXCEPT { return Line3 (line.pos * M, (line.pos + line.dir) * M); } IMATH_INTERNAL_NAMESPACE_HEADER_EXIT #endif // INCLUDED_IMATHLINE_H