Ocean
Loading...
Searching...
No Matches
Line3.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_LINE_3_H
9#define META_OCEAN_MATH_LINE_3_H
10
11#include "ocean/math/Math.h"
12#include "ocean/math/Numeric.h"
13#include "ocean/math/Vector3.h"
14
15namespace Ocean
16{
17
18// Forward declaration.
19template <typename T> class LineT3;
20
21/**
22 * Definition of the Line3 object, depending on the OCEAN_MATH_USE_SINGLE_PRECISION either with single or double precision float data type.
23 * @see LineT3
24 * @ingroup math
25 */
27
28/**
29 * Instantiation of the LineT3 template class using a double precision float data type.
30 * @see LineT3
31 * @ingroup math
32 */
34
35/**
36 * Instantiation of the LineT3 template class using a single precision float data type.
37 * @see LineT3
38 * @ingroup math
39 */
41
42/**
43 * Definition of a typename alias for vectors with LineT3 objects.
44 * @see LineT3
45 * @ingroup math
46 */
47template <typename T>
48using LinesT3 = std::vector<LineT3<T>>;
49
50/**
51 * Definition of a vector holding Line3 objects.
52 * @see Line3
53 * @ingroup math
54 */
55typedef std::vector<Line3> Lines3;
56
57/**
58 * This class implements an infinite line in 3D space.
59 * The line is defined by a point lying on the line and a direction vector.<br>
60 * The direction vector must not be a zero vector.<br>
61 * The length of the vector may be arbitrary, however a unit vector is necessary for most functions.<br>
62 * @tparam T Data type used to represent lines
63 * @see Line3, LineF3, LineD3, FiniteLine3, FiniteLine3.
64 * @ingroup math
65 */
66template <typename T>
67class LineT3
68{
69 template <typename U> friend class LineT3;
70
71 public:
72
73 /**
74 * Definition of the used data type.
75 */
76 typedef T Type;
77
78 public:
79
80 /**
81 * Creates an invalid line.
82 */
83 LineT3() = default;
84
85 /**
86 * Creates a line defined by two different intersection points.
87 * @param point Intersection point on the line
88 * @param direction Vector representing the direction of the line, a unit vector might be appropriate
89 */
91
92 /**
93 * Copies a line with different data type than T.
94 * @param line The line to copy
95 * @tparam U The data type of the second line
96 */
97 template <typename U>
98 inline explicit LineT3(const LineT3<U>& line);
99
100 /**
101 * Returns a point on the line.
102 * @return Point on line
103 */
104 inline const VectorT3<T>& point() const;
105
106 /**
107 * Returns a point on the line that is defined by a scalar.
108 * The result is determined by point() + direction() * distance;
109 * @param distance The distance to determine the line point for
110 * @return Point on line
111 */
112 inline const VectorT3<T> point(const T distance) const;
113
114 /**
115 * Returns the direction of the line.
116 * @return Unit vector
117 */
118 inline const VectorT3<T>& direction() const;
119
120 /**
121 * Sets a point of this line.
122 * @param point The point of this line
123 */
124 inline void setPoint(const VectorT3<T>& point);
125
126 /**
127 * Sets the direction of this line.
128 * @param direction Vector defining the new direction, a unit vector might be appropriate
129 */
130 inline void setDirection(const VectorT3<T>& direction);
131
132 /**
133 * Returns whether a given point is part of the line.
134 * This function needs a unit vector as direction!
135 * @param point The point to check
136 * @return True, if so
137 */
138 bool isOnLine(const VectorT3<T>& point) const;
139
140 /**
141 * Returns the distance between the line and a given point.
142 * This function needs a unit vector as direction!
143 * @param point The point to return the distance for
144 * @return Positive distance between point and line, with range [0, infinity)
145 */
146 T distance(const VectorT3<T>& point) const;
147
148 /**
149 * Returns the distance between two lines.
150 * This function needs a unit vector as direction!<br>
151 * @param line Second line to calculate the distance for
152 * @return Distance
153 */
154 T distance(const LineT3<T>& line) const;
155
156 /**
157 * Returns the square distance between the line and a given point.
158 * This function needs a unit vector as direction!
159 * @param point The point to return the distance for
160 * @return The square distance between point and line, with range [0, infinity)
161 */
162 T sqrDistance(const VectorT3<T>& point) const;
163
164 /**
165 * Returns the point on this line nearest to an arbitrary given point.
166 * This function needs a unit vector as direction!<br>
167 * @param point Arbitrary point outside the line
168 * @return Nearest point on the line
169 */
171
172 /**
173 * Returns the middle of two nearest points for two crossing lines.
174 * This function needs a unit vector as direction!<br>
175 * Both lines must not be parallel.<br>
176 * @param line Second line to calculate the point for
177 * @param middle Nearest point between two lines
178 * @return True, if succeeded
179 */
180 bool nearestPoint(const LineT3<T>& line, VectorT3<T>& middle) const;
181
182 /**
183 * Returns the two nearest points for two crossing lines.
184 * Both lines must not be parallel.<br>
185 * This function needs a unit vector as direction!<br>
186 * @param line Second line to calculate the points for
187 * @param first Nearest point on the first line
188 * @param second Nearest point on the second line
189 * @return True, if succeeded
190 */
191 bool nearestPoints(const LineT3<T>& line, VectorT3<T>& first, VectorT3<T>& second) const;
192
193 /**
194 * Returns whether two lines are parallel up to a small epsilon.
195 * This function needs a unit vector as direction!
196 * @param right Second line
197 * @return True, if so
198 */
199 inline bool isParallel(const LineT3<T>& right) const;
200
201 /**
202 * Returns whether this line and a given vector are parallel up to a small epsilon.
203 * This function needs a unit vector as direction!
204 * @param right Vector to be compared
205 * @return True, if so
206 */
207 inline bool isParallel(const VectorT3<T>& right) const;
208
209 /**
210 * Returns whether this line has valid parameters.
211 * @return True, if so
212 */
213 inline bool isValid() const;
214
215 /**
216 * Returns whether this line has a unit vector as direction.
217 * @return True, if so
218 */
219 inline bool hasUnitDirection() const;
220
221 /**
222 * Returns whether two line are identical up to a small epsilon.
223 * This function needs a unit vector as direction!
224 * @param right The right line
225 * @return True, if so
226 */
227 inline bool operator==(const LineT3<T>& right) const;
228
229 /**
230 * Returns whether two line are identical up to a small epsilon.
231 * This function needs a unit vector as direction!
232 * @param right The right line
233 * @return True, if so
234 */
235 inline bool operator!=(const LineT3<T>& right) const;
236
237 /**
238 * Returns whether this line is valid.
239 * @return True, if so
240 */
241 explicit inline operator bool() const;
242
243 protected:
244
245 /// Point on the line.
247
248 /// Direction of the line.
250};
251
252template <typename T>
253LineT3<T>::LineT3(const VectorT3<T>& first, const VectorT3<T>& direction) :
254 point_(first),
255 direction_(direction)
256{
257 ocean_assert(!direction_.isNull());
258}
259
260template <typename T>
261template <typename U>
262inline LineT3<T>::LineT3(const LineT3<U>& line)
263{
264 point_ = VectorT3<T>(line.point_);
265 direction_ = VectorT3<T>(line.direction_);
266}
267
268template <typename T>
269inline const VectorT3<T>& LineT3<T>::point() const
270{
271 return point_;
272}
273
274template <typename T>
275inline const VectorT3<T> LineT3<T>::point(const T distance) const
276{
277 ocean_assert(isValid());
278 return point_ + direction_ * distance;
279}
280
281template <typename T>
283{
284 return direction_;
285}
286
287template <typename T>
288inline void LineT3<T>::setPoint(const VectorT3<T>& point)
289{
290 point_ = point;
291}
292
293template <typename T>
294inline void LineT3<T>::setDirection(const VectorT3<T>& direction)
295{
296 ocean_assert(NumericT<T>::isEqual(direction.length(), T(1.0)));
297 direction_ = direction;
298}
299
300template <typename T>
302{
303 return !direction_.isNull();
304}
305
306template <typename T>
308{
309 return NumericT<T>::isEqual(direction_.length(), T(1.0));
310}
311
312template <typename T>
313inline bool LineT3<T>::isParallel(const LineT3<T>& right) const
314{
315 ocean_assert(isValid() && right.isValid());
316 ocean_assert(hasUnitDirection() && right.hasUnitDirection());
317
318 const T scalarProduct = direction_ * right.direction_;
319
320 return NumericT<T>::isEqual(NumericT<T>::abs(scalarProduct), T(1.0));
321}
322
323template <typename T>
324inline bool LineT3<T>::isParallel(const VectorT3<T>& right) const
325{
326 ocean_assert(isValid());
327 ocean_assert(hasUnitDirection() && NumericT<T>::isEqual(right.length(), T(1.0)));
328
329 const T scalarProduct = direction_ * right;
330
331 return NumericT<T>::isEqual(NumericT<T>::abs(scalarProduct), T(1.0));
332}
333
334template <typename T>
335inline bool LineT3<T>::operator==(const LineT3<T>& right) const
336{
337 ocean_assert(isValid() && right.isValid());
338
339 return isParallel(right) && isOnLine(right.point());
340}
341
342template <typename T>
343inline bool LineT3<T>::operator!=(const LineT3<T>& right) const
344{
345 return !(*this == right);
346}
347
348template <typename T>
349inline LineT3<T>::operator bool() const
350{
351 return isValid();
352}
353
354template <typename T>
355bool LineT3<T>::isOnLine(const VectorT3<T>& point) const
356{
357 ocean_assert(isValid());
358 ocean_assert(hasUnitDirection());
359
360 const VectorT3<T> offset(point - point_);
361 const T length = offset.length();
362
363 if (NumericT<T>::isEqualEps(length))
364 {
365 return true;
366 }
367
368#ifdef OCEAN_DEBUG
369 if (!std::is_same<T, float>::value)
370 {
371 ocean_assert(NumericT<T>::isEqual(NumericT<T>::abs((offset / length) * direction_), T(1.0))
372 == NumericT<T>::isEqual(NumericT<T>::abs(offset * direction_), length, NumericT<T>::eps() * length));
373 }
374#endif
375
376 // we explicitly adjust the epsilon by the length of the offset vector ensuring that the result is still correct for long vectors (short vectors would have been caught before)
377 return NumericT<T>::isEqual(NumericT<T>::abs(offset * direction_), length, NumericT<T>::eps() * length);
378}
379
380template <>
381inline bool LineT3<float>::isOnLine(const VectorT3<float>& point) const
382{
383 ocean_assert(isValid());
384 ocean_assert(hasUnitDirection());
385
386 const VectorT3<float> offset(point - point_);
387 const float length = offset.length();
388
389 if (NumericT<float>::isEqualEps(length))
390 {
391 return true;
392 }
393
394 if (length > 1.0f)
395 {
396 // we explicitly adjust the epsilon by the length of the offset vector ensuring that the result is still correct for long vectors (short vectors would have been caught before)
397 return NumericT<float>::isEqual(NumericT<float>::abs(offset * direction_), length, NumericT<float>::eps() * length);
398 }
399
400 return NumericT<float>::isEqual(NumericT<float>::abs(offset * direction_), length, NumericT<float>::eps());
401}
402
403template <typename T>
404T LineT3<T>::distance(const VectorT3<T>& point) const
405{
406 ocean_assert(isValid());
407 ocean_assert(hasUnitDirection());
408
409 const VectorT3<T> pointOnLine(nearestPoint(point));
410
411 return (pointOnLine - point).length();
412}
413
414template <typename T>
415T LineT3<T>::distance(const LineT3<T>& line) const
416{
417 // idea: creating a plane which intersect the second line and is parallel to the first line
418 // the distance is the projection of the vector between the two base point onto the plane normal
419
420 ocean_assert(isValid() && line.isValid());
421 ocean_assert(hasUnitDirection() && line.hasUnitDirection());
422
423 const VectorT3<T> offset(point_ - line.point_);
424
425 // if the base points of the two lines are identical
426 if (NumericT<T>::isEqualEps(offset.sqr()))
427 {
428 return T(0.0);
429 }
430
431 if (isParallel(line))
432 {
433 return (line.point_ - point_ + direction_ * (direction_ * offset)).length();
434 }
435
436 // plane normal
437 const VectorT3<T> normal(direction_.cross(line.direction_).normalizedOrZero());
438
439 // projection of point offset onto plane normal
440 return NumericT<T>::abs(offset * normal);
441}
442
443template <typename T>
445{
446 ocean_assert(isValid());
447 ocean_assert(hasUnitDirection());
448
449 const VectorT3<T> pointOnLine(nearestPoint(point));
450
451 return (pointOnLine - point).sqr();
452}
453
454template <typename T>
456{
457 ocean_assert(isValid());
458 ocean_assert(hasUnitDirection());
459
460 const VectorT3<T> offset(point - point_);
461
462 return point_ + direction_ * (direction_ * offset);
463}
464
465template <typename T>
466bool LineT3<T>::nearestPoint(const LineT3<T>& line, VectorT3<T>& middle) const
467{
468 ocean_assert(isValid() && line.isValid());
469 ocean_assert(hasUnitDirection() && line.hasUnitDirection());
470
471 VectorT3<T> first, second;
472 if (nearestPoints(line, first, second))
473 {
474 middle = (first + second) * T(0.5);
475 return true;
476 }
477
478 return false;
479}
480
481template <typename T>
482bool LineT3<T>::nearestPoints(const LineT3<T>& line, VectorT3<T>& first, VectorT3<T>& second) const
483{
484 ocean_assert(isValid() && line.isValid());
485 ocean_assert(hasUnitDirection() && line.hasUnitDirection());
486
487 if (isParallel(line))
488 {
489 return false;
490 }
491
492 const VectorT3<T> d = line.direction_ - direction_ * (direction_ * line.direction_);
493 const VectorT3<T> p = line.point_ - point_ + direction_ * (direction_ * point_);
494
495 const T denominator = d.sqr();
496
497 if (NumericT<T>::isEqualEps(denominator))
498 {
499 return false;
500 }
501
502 const T factor = - (p * d) / denominator;
503
504 second = line.point_ + line.direction_ * factor;
505 first = nearestPoint(second);
506
507 return true;
508}
509
510}
511
512#endif // META_OCEAN_MATH_LINE_3_H
This class implements an infinite line in 3D space.
Definition Line3.h:68
bool isParallel(const LineT3< T > &right) const
Returns whether two lines are parallel up to a small epsilon.
Definition Line3.h:313
bool operator==(const LineT3< T > &right) const
Returns whether two line are identical up to a small epsilon.
Definition Line3.h:335
void setPoint(const VectorT3< T > &point)
Sets a point of this line.
Definition Line3.h:288
VectorT3< T > direction_
Direction of the line.
Definition Line3.h:249
T sqrDistance(const VectorT3< T > &point) const
Returns the square distance between the line and a given point.
Definition Line3.h:444
bool isOnLine(const VectorT3< T > &point) const
Returns whether a given point is part of the line.
Definition Line3.h:355
void setDirection(const VectorT3< T > &direction)
Sets the direction of this line.
Definition Line3.h:294
bool isValid() const
Returns whether this line has valid parameters.
Definition Line3.h:301
const VectorT3< T > & direction() const
Returns the direction of the line.
Definition Line3.h:282
T Type
Definition of the used data type.
Definition Line3.h:76
bool nearestPoints(const LineT3< T > &line, VectorT3< T > &first, VectorT3< T > &second) const
Returns the two nearest points for two crossing lines.
Definition Line3.h:482
VectorT3< T > nearestPoint(const VectorT3< T > &point) const
Returns the point on this line nearest to an arbitrary given point.
Definition Line3.h:455
friend class LineT3
Definition Line3.h:69
const VectorT3< T > & point() const
Returns a point on the line.
Definition Line3.h:269
LineT3()=default
Creates an invalid line.
VectorT3< T > point_
Point on the line.
Definition Line3.h:246
T distance(const VectorT3< T > &point) const
Returns the distance between the line and a given point.
Definition Line3.h:404
bool hasUnitDirection() const
Returns whether this line has a unit vector as direction.
Definition Line3.h:307
bool operator!=(const LineT3< T > &right) const
Returns whether two line are identical up to a small epsilon.
Definition Line3.h:343
This class provides basic numeric functionalities.
Definition Numeric.h:57
static T abs(const T value)
Returns the absolute value of a given value.
Definition Numeric.h:1220
static bool isEqual(const T first, const T second)
Returns whether two values are equal up to a small epsilon.
Definition Numeric.h:2386
This class implements a vector with three elements.
Definition Vector3.h:97
bool isNull() const
Returns whether this vector is a null vector up to a small epsilon.
Definition Vector3.h:866
T length() const
Returns the length of the vector.
Definition Vector3.h:676
T sqr() const
Returns the square of the vector length.
Definition Vector3.h:682
LineT3< Scalar > Line3
Definition of the Line3 object, depending on the OCEAN_MATH_USE_SINGLE_PRECISION either with single o...
Definition Line3.h:26
LineT3< double > LineD3
Instantiation of the LineT3 template class using a double precision float data type.
Definition Line3.h:33
std::vector< Line3 > Lines3
Definition of a vector holding Line3 objects.
Definition Line3.h:55
LineT3< float > LineF3
Instantiation of the LineT3 template class using a single precision float data type.
Definition Line3.h:40
std::vector< LineT3< T > > LinesT3
Definition of a typename alias for vectors with LineT3 objects.
Definition Line3.h:48
The namespace covering the entire Ocean framework.
Definition Accessor.h:15