Ocean
Sphere3.h
Go to the documentation of this file.
1 /*
2  * Copyright (c) Meta Platforms, Inc. and affiliates.
3  *
4  * This source code is licensed under the MIT license found in the
5  * LICENSE file in the root directory of this source tree.
6  */
7 
8 #ifndef META_OCEAN_MATH_SPHERE_3_H
9 #define META_OCEAN_MATH_SPHERE_3_H
10 
11 #include "ocean/math/Math.h"
12 #include "ocean/math/Box3.h"
13 #include "ocean/math/Line3.h"
14 #include "ocean/math/Vector3.h"
15 
16 namespace Ocean
17 {
18 
19 // Forward declaration.
20 template <typename T>
21 class SphereT3;
22 
23 /**
24  * Definition of the Sphere3 object, depending on the OCEAN_MATH_USE_SINGLE_PRECISION either with single or double precision float data type.
25  * @see SphereT3
26  * @ingroup math
27  */
29 
30 /**
31  * Definition of a 3D sphere with double values.
32  * @see SphereT3
33  * @ingroup math
34  */
36 
37 /**
38  * Definition of a 3D sphere with float values.
39  * @see SphereT3
40  * @ingroup math
41  */
43 
44 /**
45  * Definition of a vector holding Shpere3 objects.
46  * @see Sphere3
47  * @ingroup math
48  */
49 typedef std::vector<Sphere3> Spheres3;
50 
51 /**
52  * This class implements a 3D sphere.
53  * @ingroup math
54  */
55 template <typename T>
56 class SphereT3
57 {
58  public:
59 
60  /**
61  * Creates an invalid sphere.
62  */
63  SphereT3() = default;
64 
65  /**
66  * Creates a new sphere by a center point and a radius.
67  * @param center The center of the sphere
68  * @param radius The radius of the sphere, with range [0, infinity), negative to create an invalid sphere
69  */
70  inline SphereT3(const VectorT3<T>& center, const T radius);
71 
72  /**
73  * Creates a new sphere entirely containing a given 3D box.
74  * @param boundingBox The box which will be contained by the new sphere, must be valid
75  */
76  explicit inline SphereT3(const BoxT3<T>& boundingBox);
77 
78  /**
79  * Returns the center of the sphere.
80  * @return Sphere center
81  */
82  inline const VectorT3<T>& center() const;
83 
84  /**
85  * Returns the radius of the sphere.
86  * @return Sphere radius, with range [0, infinity), negative if invalid
87  */
88  inline const T& radius() const;
89 
90  /**
91  * Returns whether a given point is inside this sphere.
92  * @param point The point to check
93  * @return True, if so
94  */
95  inline bool isInside(const VectorT3<T>& point) const;
96 
97  /**
98  * Returns whether a given point is inside this sphere including a thin epsilon boundary.
99  * @param point The point to check
100  * @param eps Epsilon to be used, with range [0, infinity)
101  * @return True, if so
102  */
103  inline bool isInsideEps(const VectorT3<T>& point, const T eps = NumericT<T>::eps()) const;
104 
105  /**
106  * Returns whether a given ray has an intersection with this sphere.
107  * @param ray The ray to be tested
108  * @return True, if so
109  */
110  bool hasIntersection(const LineT3<T>& ray) const;
111 
112  /**
113  * Returns whether a given ray has an intersection with this sphere.
114  * @param ray Ray to be tested, must be valid
115  * @param sphere_T_ray The transformation between ray and this sphere, must be valid
116  * @return True, if so
117  */
118  inline bool hasIntersection(const LineT3<T>& ray, const HomogenousMatrixT4<T>& sphere_T_ray) const;
119 
120  /**
121  * Returns whether two spheres have an intersection.
122  * @param sphere Second sphere to test
123  * @return True, if so
124  */
125  inline bool hasIntersection(const SphereT3<T>& sphere) const;
126 
127  /**
128  * Returns whether this radius of this sphere is not negative and thus the sphere is valid.
129  * @return True, if so
130  */
131  inline bool isValid() const;
132 
133  /**
134  * Returns a new sphere with an enlarged radius (the center of the sphere stays constant).
135  * @param factor The factor to be multiplied with the radius of this sphere, with range [0, infinity)
136  * @return New resulting sphere
137  */
138  inline SphereT3<T> operator*(const T factor) const;
139 
140  /**
141  * Multiplies the radius of this sphere with a given factor.
142  * @param factor The factor to be multiplied with the radius, with range [0, infinity)
143  * @return Reference to this sphere object
144  */
145  inline SphereT3<T>& operator*=(const T factor);
146 
147  /**
148  * Converts a 2D location coordinate on the surface of a unit sphere to a vector with unit length.
149  * The north/south axis of the sphere is parallel to the y-axis, the z-axis points towards the longitude 0 at the equator, the x-axis points towards the longitude PI/2 at the equator.
150  * @param latitude The latitude coordinate of the location, in radian, with range [-PI/2, PI/2]
151  * @param longitude The longitude coordinate of the location, in radian, with range [-PI, PI]
152  * @return The corresponding 3D vector with unit length
153  */
154  static VectorT3<T> coordinateToVector(const T latitude, const T longitude);
155 
156  /**
157  * Converts a vector pointing to the surface of a unit sphere to a 2D location coordinate.
158  * @param coordinateVector The vector pointing to the location on the unit sphere, must have unit length
159  * @param latitude The resulting latitude coordinate of the location, in radian, with range range [-PI/2, PI/2]
160  * @param longitude The resulting longitude coordinate of the location, in radian, with range range [-PI, PI]
161  */
162  static void vectorToCoordinate(const VectorT3<T>& coordinateVector, T& latitude, T& longitude);
163 
164  /**
165  * Calculates the shortest distance between two 2D location coordinates on the surface of a unit sphere.
166  * The shortest distance is identical to the shortest angle (in radian) in a unit sphere.<br>
167  * This function applies the Haversine formula.
168  * @param latitudeA The latitude coordinate of the first location, in radian, with range [-PI/2, PI/2]
169  * @param longitudeA The longitude coordinate of the first location, in radian, with range [-PI, PI]
170  * @param latitudeB The latitude coordinate of the second location, in radian, with range [-PI/2, PI/2]
171  * @param longitudeB The longitude coordinate of the second location, in radian, with range [-PI, PI]
172  * @return The shortest distance on the unit sphere, with range [0, PI]
173  */
174  static T shortestDistance(const T latitudeA, const T longitudeA, const T latitudeB, const T longitudeB);
175 
176  protected:
177 
178  /// Sphere center.
180 
181  /// Sphere radius.
182  T radius_ = T(-1);
183 };
184 
185 template <typename T>
186 inline SphereT3<T>::SphereT3(const VectorT3<T>& center, const T radius) :
187  center_(center),
188  radius_(radius)
189 {
190  // nothing to do here
191 }
192 
193 template <typename T>
194 inline SphereT3<T>::SphereT3(const BoxT3<T>& boundingBox) :
195  center_(boundingBox.center()),
196  radius_(boundingBox.diagonal() * T(0.5))
197 {
198  ocean_assert(boundingBox.isValid());
199  ocean_assert(isValid());
200 }
201 
202 template <typename T>
203 inline const VectorT3<T>& SphereT3<T>::center() const
204 {
205  return center_;
206 }
207 
208 template <typename T>
209 inline const T& SphereT3<T>::radius() const
210 {
211  return radius_;
212 }
213 
214 template <typename T>
215 inline bool SphereT3<T>::isInside(const VectorT3<T>& point) const
216 {
217  ocean_assert(isValid());
218 
219  // a point is inside this sphere if:
220  // |center - point| <= radius
221 
222  return center_.sqrDistance(point) <= NumericT<T>::sqr(radius_);
223 }
224 
225 template <typename T>
226 bool SphereT3<T>::isInsideEps(const VectorT3<T>& point, const T eps) const
227 {
228  ocean_assert(isValid());
229  ocean_assert(eps >= T(0));
230 
231  // a point is inside this sphere if:
232  // |center - point| <= radius + eps
233 
234  return center_.sqrDistance(point) <= NumericT<T>::sqr(radius_ + eps);
235 }
236 
237 template <typename T>
239 {
240  ocean_assert(isValid());
241  ocean_assert(ray.isValid());
242 
243  // (d * d) * t^2 + (2 * d * (p - o)) * t + (p - o)*(p - o) - r^2 == 0
244  // a * t^2 + b * t + c == 0
245 
246  const VectorT3<T>& d = ray.direction();
247  const VectorT3<T>& p = ray.point();
248  const VectorT3<T>& o = center_;
249 
250  const VectorT3<T> po(p - o);
251 
252  const T a = d * d;
253  const T b = (d * po) * 2;
254  const T c = po * po - radius_ * radius_;
255 
256  return b * b >= 4 * a * c;
257 }
258 
259 template <typename T>
260 inline bool SphereT3<T>::hasIntersection(const LineT3<T>& ray, const HomogenousMatrixT4<T>& sphere_T_ray) const
261 {
262  ocean_assert(sphere_T_ray.isValid());
263  ocean_assert(ray.isValid());
264 
265  return hasIntersection(LineT3<T>(sphere_T_ray * ray.point(), sphere_T_ray.rotationMatrix(ray.direction())));
266 }
267 
268 template <typename T>
269 inline bool SphereT3<T>::hasIntersection(const SphereT3<T>& sphere) const
270 {
271  ocean_assert(isValid());
272  ocean_assert(sphere.isValid());
273 
274  // two spheres have an intersection if:
275  // |center0 - center1| <= radius0 + radius1
276 
277  return center_.sqrDistance(sphere.center_) <= NumericT<T>::sqr(radius_ + sphere.radius_);
278 }
279 
280 template <typename T>
281 inline bool SphereT3<T>::isValid() const
282 {
283  return radius_ >= T(0);
284 }
285 
286 template <typename T>
287 inline SphereT3<T> SphereT3<T>::operator*(const T factor) const
288 {
289  ocean_assert(isValid());
290  ocean_assert(factor >= 0);
291 
292  return SphereT3<T>(center_, radius_ * factor);
293 }
294 
295 template <typename T>
296 inline SphereT3<T>& SphereT3<T>::operator*=(const T factor)
297 {
298  ocean_assert(isValid());
299  ocean_assert(factor >= T(0));
300 
301  radius_ *= factor;
302  return *this;
303 }
304 
305 template <typename T>
306 VectorT3<T> SphereT3<T>::coordinateToVector(const T latitude, const T longitude)
307 {
308  ocean_assert(NumericT<T>::isInsideRange(-NumericT<T>::pi_2(), latitude, NumericT<T>::pi_2()));
309  ocean_assert(NumericT<T>::isInsideRange(-NumericT<T>::pi(), longitude, NumericT<T>::pi()));
310 
311  const T d = NumericT<T>::cos(latitude);
312 
313  const VectorT3<T> coordinateVector(NumericT<T>::sin(longitude) * d, NumericT<T>::sin(latitude), NumericT<T>::cos(longitude) * d);
314  ocean_assert(coordinateVector.isUnit());
315 
316  return coordinateVector;
317 }
318 
319 template <typename T>
320 void SphereT3<T>::vectorToCoordinate(const VectorT3<T>& coordinateVector, T& latitude, T& longitude)
321 {
322  ocean_assert(coordinateVector.isUnit());
323 
324  latitude = NumericT<T>::asin(coordinateVector.y());
325 
326  if (NumericT<T>::isEqualEps(coordinateVector.x()) && NumericT<T>::isEqualEps(coordinateVector.z()))
327  {
328  longitude = 0; // we are at one of both poles, any value is correct
329  }
330  else
331  {
332  longitude = NumericT<T>::atan2(coordinateVector.x(), coordinateVector.z());
333  }
334 }
335 
336 template <typename T>
337 T SphereT3<T>::shortestDistance(const T latitudeA, const T longitudeA, const T latitudeB, const T longitudeB)
338 {
341 
342  // great-circle distance between two points (shortest distance between two points on a sphere) using Haversine formula
343 
344  const T latitudeDelta_2 = (latitudeB - latitudeA) * T(0.5);
345  const T longitudeDelta_2 = (longitudeB - longitudeA) * T(0.5);
346 
347  const T inner = NumericT<T>::sqr(NumericT<T>::sin(latitudeDelta_2)) + NumericT<T>::cos(latitudeA) * NumericT<T>::cos(latitudeB) * NumericT<T>::sqr(NumericT<T>::sin(longitudeDelta_2));
348  ocean_assert(inner >= T(0));
349 
350  return T(2) * NumericT<T>::asin(NumericT<T>::sqrt(inner));
351 }
352 
353 }
354 
355 #endif // META_OCEAN_MATH_SPHERE_3_H
This class implements an axis aligned 3D bounding box.
Definition: Box3.h:67
bool isValid() const
Returns whether the bounding box is valid.
This class implements a 4x4 homogeneous transformation matrix using floating point values with the pr...
Definition: HomogenousMatrix4.h:110
SquareMatrixT3< T > rotationMatrix() const
Returns the rotation matrix of the transformation.
Definition: HomogenousMatrix4.h:1493
bool isValid() const
Returns whether this matrix is a valid homogeneous transformation.
Definition: HomogenousMatrix4.h:1806
This class implements an infinite line in 3D space.
Definition: Line3.h:70
bool isValid() const
Returns whether this line has valid parameters.
Definition: Line3.h:303
const VectorT3< T > & direction() const
Returns the direction of the line.
Definition: Line3.h:284
const VectorT3< T > & point() const
Returns a point on the line.
Definition: Line3.h:271
This class provides basic numeric functionalities.
Definition: Numeric.h:57
static T atan2(const T y, const T x)
Returns the arctangent of a given value in radian.
Definition: Numeric.h:1632
static constexpr T sqr(const T value)
Returns the square of a given value.
Definition: Numeric.h:1495
static T cos(const T value)
Returns the cosine of a given value.
Definition: Numeric.h:1584
static T asin(const T value)
Returns the arcsine of a given value.
Definition: Numeric.h:2887
bool isInsideEps(const VectorT3< T > &point, const T eps=NumericT< T >::eps()) const
Returns whether a given point is inside this sphere including a thin epsilon boundary.
Definition: Sphere3.h:226
bool isInside(const VectorT3< T > &point) const
Returns whether a given point is inside this sphere.
Definition: Sphere3.h:215
bool hasIntersection(const LineT3< T > &ray, const HomogenousMatrixT4< T > &sphere_T_ray) const
Returns whether a given ray has an intersection with this sphere.
Definition: Sphere3.h:260
VectorT3< T > center_
Sphere center.
Definition: Sphere3.h:179
bool isValid() const
Returns whether this radius of this sphere is not negative and thus the sphere is valid.
Definition: Sphere3.h:281
const T & radius() const
Returns the radius of the sphere.
Definition: Sphere3.h:209
T radius_
Sphere radius.
Definition: Sphere3.h:182
static VectorT3< T > coordinateToVector(const T latitude, const T longitude)
Converts a 2D location coordinate on the surface of a unit sphere to a vector with unit length.
Definition: Sphere3.h:306
SphereT3()=default
Creates an invalid sphere.
SphereT3(const BoxT3< T > &boundingBox)
Creates a new sphere entirely containing a given 3D box.
Definition: Sphere3.h:194
bool hasIntersection(const SphereT3< T > &sphere) const
Returns whether two spheres have an intersection.
Definition: Sphere3.h:269
static void vectorToCoordinate(const VectorT3< T > &coordinateVector, T &latitude, T &longitude)
Converts a vector pointing to the surface of a unit sphere to a 2D location coordinate.
Definition: Sphere3.h:320
bool hasIntersection(const LineT3< T > &ray) const
Returns whether a given ray has an intersection with this sphere.
Definition: Sphere3.h:238
SphereT3< T > operator*(const T factor) const
Returns a new sphere with an enlarged radius (the center of the sphere stays constant).
Definition: Sphere3.h:287
const VectorT3< T > & center() const
Returns the center of the sphere.
Definition: Sphere3.h:203
static T shortestDistance(const T latitudeA, const T longitudeA, const T latitudeB, const T longitudeB)
Calculates the shortest distance between two 2D location coordinates on the surface of a unit sphere.
Definition: Sphere3.h:337
SphereT3< T > & operator*=(const T factor)
Multiplies the radius of this sphere with a given factor.
Definition: Sphere3.h:296
SphereT3(const VectorT3< T > &center, const T radius)
Creates a new sphere by a center point and a radius.
Definition: Sphere3.h:186
This class implements a vector with three elements.
Definition: Vector3.h:97
bool isUnit(const T eps=NumericT< T >::eps()) const
Returns whether this vector is a unit vector (whether the vector has the length 1).
Definition: Vector3.h:861
const T & y() const noexcept
Returns the y value.
Definition: Vector3.h:812
const T & x() const noexcept
Returns the x value.
Definition: Vector3.h:800
const T & z() const noexcept
Returns the z value.
Definition: Vector3.h:824
SphereT3< float > SphereF3
Definition of a 3D sphere with float values.
Definition: Sphere3.h:42
std::vector< Sphere3 > Spheres3
Definition of a vector holding Shpere3 objects.
Definition: Sphere3.h:49
SphereT3< Scalar > Sphere3
Definition of the Sphere3 object, depending on the OCEAN_MATH_USE_SINGLE_PRECISION either with single...
Definition: Sphere3.h:21
SphereT3< double > SphereD3
Definition of a 3D sphere with double values.
Definition: Sphere3.h:35
The namespace covering the entire Ocean framework.
Definition: Accessor.h:15