Ion
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
fieldofview.h
Go to the documentation of this file.
1 
18 #ifndef ION_MATH_FIELDOFVIEW_H_
19 #define ION_MATH_FIELDOFVIEW_H_
20 
21 #include <cmath>
22 
23 #include "ion/math/angle.h"
24 #include "ion/math/matrixutils.h"
26 #include "ion/math/vector.h"
27 
28 namespace ion {
29 namespace math {
30 
35 template <typename T>
36 class FieldOfView {
37  public:
40  FieldOfView();
41 
43  FieldOfView(const Angle<T>& left, const Angle<T>& right,
44  const Angle<T>& bottom, const Angle<T>& top);
45 
48  static FieldOfView<T> FromProjectionMatrix(const Matrix<4, T>& matrix);
49 
52  static FieldOfView<T> FromTangents(const T& left, const T& right,
53  const T& bottom, const T& top);
54 
57  template <typename U>
58  explicit FieldOfView(const FieldOfView<U>& fov);
59 
74  const Angle<T> fov_y,
75  const Point<2, T>& optical_center_ndc);
76 
89  -1 p_ndc 0 1
96  * *
102  const Angle<T> centered_fov_x, const Angle<T> centered_fov_y,
103  const Point<2, T>& optical_center_ndc);
104 
108 
112  Matrix<4, T> GetProjectionMatrix(T near_p, T far_p) const;
113 
115  Angle<T> GetLeft() const { return left_; }
116  Angle<T> GetRight() const { return right_; }
117  Angle<T> GetBottom() const { return bottom_; }
118  Angle<T> GetTop() const { return top_; }
119 
121  void SetLeft(const Angle<T>& left) { left_ = left; }
122  void SetRight(const Angle<T>& right) { right_ = right; }
123  void SetBottom(const Angle<T>& bottom) { bottom_ = bottom; }
124  void SetTop(const Angle<T>& top) { top_ = top; }
125 
130  Angle<T> GetCenteredFovX() const;
131  Angle<T> GetCenteredFovY() const;
132 
134  void Print(std::ostream& out) const; // NOLINT
135 
137  void Read(std::istream& in); // NOLINT
138 
141  bool IsZero() const;
142 
144  friend bool operator==(const FieldOfView& fov0, const FieldOfView& fov1) {
145  return AreEqual(fov0, fov1);
146  }
147 
148  friend bool operator!=(const FieldOfView& fov0, const FieldOfView& fov1) {
149  return !AreEqual(fov0, fov1);
150  }
151 
152  private:
157  static bool ComputeHalfAnglesForTotalFovAndOpticalCenter1d(
158  const Angle<T> total_fov, const T optical_center_ndc,
159  Angle<T>* angle1_out, Angle<T>* angle2_out);
160 
167  static void ComputeHalfAnglesForCenteredFovAndOpticalCenter1d(
168  const Angle<T> centered_fov, const T optical_center_ndc,
169  Angle<T>* angle1_out, Angle<T>* angle2_out);
170 
171  static bool AreEqual(const FieldOfView& fov0, const FieldOfView& fov1);
172 
173  Angle<T> left_;
174  Angle<T> right_;
175  Angle<T> bottom_;
176  Angle<T> top_;
177 };
178 
181 
182 template <typename T>
184 
185 template <typename T>
186 inline FieldOfView<T>::FieldOfView(const Angle<T>& left, const Angle<T>& right,
187  const Angle<T>& bottom, const Angle<T>& top)
188  : left_(left), right_(right), bottom_(bottom), top_(top) {}
189 
190 template <typename T>
192  T far_p) const {
193  const T l = -std::tan(left_.Radians()) * near_p;
194  const T r = std::tan(right_.Radians()) * near_p;
195  const T b = -std::tan(bottom_.Radians()) * near_p;
196  const T t = std::tan(top_.Radians()) * near_p;
197  return ion::math::PerspectiveMatrixFromFrustum(l, r, b, t, near_p, far_p);
198 }
199 
200 template <typename T>
202  const T& right,
203  const T& bottom,
204  const T& top) {
205  return FieldOfView<T>(Angle<T>::FromRadians(std::atan(left)),
206  Angle<T>::FromRadians(std::atan(right)),
207  Angle<T>::FromRadians(std::atan(bottom)),
208  Angle<T>::FromRadians(std::atan(top)));
209 }
210 
211 template <typename T>
213  const Matrix<4, T>& m) {
214  const T kOne = static_cast<T>(1.0);
215 
217  const T kTanVertFov = kOne / m(1, 1);
218  const T kTanHorzFov = kOne / m(0, 0);
219  const T t = (m(1, 2) + kOne) * kTanVertFov;
220  const T b = (m(1, 2) - kOne) * kTanVertFov;
221  const T l = (m(0, 2) - kOne) * kTanHorzFov;
222  const T r = (m(0, 2) + kOne) * kTanHorzFov;
223 
224  return FromTangents(-l, r, -b, t);
225 }
226 
227 template <typename T>
228 template <typename U>
230  : left_(fov.GetLeft()),
231  right_(fov.GetRight()),
232  bottom_(fov.GetBottom()),
233  top_(fov.GetTop()) {}
234 
235 template <typename T>
237  const T kOne = static_cast<T>(1.0);
238  const T kTwo = static_cast<T>(2.0);
239  const T tan_left = std::tan(left_.Radians());
240  const T tan_right = std::tan(right_.Radians());
241  const T tan_bottom = std::tan(bottom_.Radians());
242  const T tan_top = std::tan(top_.Radians());
243  const T x_ndc = kTwo * tan_left / (tan_left + tan_right) - kOne;
244  const T y_ndc = kTwo * tan_bottom / (tan_bottom + tan_top) - kOne;
245  return Point<2, T>(x_ndc, y_ndc);
246 }
247 
248 template <typename T>
250  const Angle<T> fov_x, const Angle<T> fov_y,
251  const Point<2, T>& optical_center_ndc) {
252  Angle<T> bottom, top, left, right;
253  if (!ComputeHalfAnglesForTotalFovAndOpticalCenter1d(
254  fov_x, optical_center_ndc[0], &left, &right))
255  return false;
256  if (!ComputeHalfAnglesForTotalFovAndOpticalCenter1d(
257  fov_y, optical_center_ndc[1], &bottom, &top))
258  return false;
259 
262  left_ = left;
263  right_ = right;
264  bottom_ = bottom;
265  top_ = top;
266  return true;
267 }
268 
269 template <typename T>
271  const Angle<T> total_fov, const T optical_center_ndc, Angle<T>* angle1_out,
272  Angle<T>* angle2_out) {
273  const T kOne = static_cast<T>(1.0);
274  T p = optical_center_ndc;
275 
280  bool invert = false;
281  if (p > 0.0) {
282  invert = true;
283  p = -p;
284  }
285 
289  -1 p_ndc 1
327  const T inv_tan_total_fov = kOne / tan(total_fov.Radians());
328  const T discriminant = kOne + Square(inv_tan_total_fov) - Square(p);
329  if (discriminant < 0) return false;
330 
340  const double sign = p < -kOne ? -kOne : kOne;
341  *angle1_out = Angle<T>::FromRadians(
342  atan((sign * std::sqrt(discriminant) - inv_tan_total_fov) / (kOne - p)));
343 
346  *angle2_out = total_fov - *angle1_out;
347  if (invert) std::swap(*angle1_out, *angle2_out);
348  return true;
349 }
350 
351 template <typename T>
353  const Angle<T> fov_x, const Angle<T> fov_y,
354  const Point<2, T>& optical_center_ndc) {
355  Angle<T> bottom, top, left, right;
356  ComputeHalfAnglesForCenteredFovAndOpticalCenter1d(
357  fov_x, optical_center_ndc[0], &left, &right);
358  ComputeHalfAnglesForCenteredFovAndOpticalCenter1d(
359  fov_y, optical_center_ndc[1], &bottom, &top);
360 
361  return FieldOfView<T>(left, right, bottom, top);
362 }
363 
364 template <typename T>
366  const Angle<T> centered_fov, const T optical_center_ndc,
367  Angle<T>* angle1_out, Angle<T>* angle2_out) {
368  const T kOne = static_cast<T>(1.0);
369  const T kTwo = static_cast<T>(2.0);
370  const T p = optical_center_ndc;
371 
375  -1 p_ndc 0 1
396 
397  const T x = kOne / std::tan(centered_fov.Radians() / kTwo);
398 
399  *angle1_out = Angle<T>::FromRadians(std::atan2(p + kOne, x));
400  *angle2_out = Angle<T>::FromRadians(std::atan2(kOne - p, x));
401 }
402 
403 template <typename T>
404 inline Angle<T> FieldOfView<T>::GetCenteredFovX() const {
415 
416  const T tan_left = std::tan(left_.Radians());
417  const T tan_right = std::tan(right_.Radians());
418  return Angle<T>::FromRadians(2 * std::atan((tan_left + tan_right) / 2));
419 }
420 
421 template <typename T>
424 
425  const T tan_bottom = std::tan(bottom_.Radians());
426  const T tan_top = std::tan(top_.Radians());
427  return Angle<T>::FromRadians(2 * std::atan((tan_bottom + tan_top) / 2));
428 }
429 
430 template <typename T>
431 inline void FieldOfView<T>::Print(std::ostream& out) const { // NOLINT
432  out << "FOV[" << left_ << ", " << right_ << ", " << bottom_ << ", " << top_
433  << "]";
434 }
435 
436 template <typename T>
437 inline void FieldOfView<T>::Read(std::istream& in) { // NOLINT
438  FieldOfView fov;
439  if (base::GetExpectedString(in, "FOV[")) {
440  in >> left_;
441  if (!base::GetExpectedChar<','>(in)) {
442  *this = fov;
443  return;
444  }
445  in >> right_;
446  if (!base::GetExpectedChar<','>(in)) {
447  *this = fov;
448  return;
449  }
450  in >> bottom_;
451  if (!base::GetExpectedChar<','>(in)) {
452  *this = fov;
453  return;
454  }
455  in >> top_;
456  if (!base::GetExpectedChar<']'>(in)) {
457  *this = fov;
458  return;
459  }
460  }
461 }
462 
463 template <typename T>
464 inline std::ostream& operator<<(std::ostream& out,
465  const FieldOfView<T>& f) { // NOLINT
466  f.Print(out);
467  return out;
468 }
469 
470 template <typename T>
471 inline std::istream& operator>>(std::istream& in,
472  FieldOfView<T>& f) { // NOLINT
473  f.Read(in);
474  return in;
475 }
476 
477 template <typename T>
478 inline bool FieldOfView<T>::IsZero() const {
479  const T kZero = static_cast<T>(0.0);
480  if (left_.Radians() != kZero || right_.Radians() != kZero ||
481  bottom_.Radians() != kZero || top_.Radians() != kZero)
482  return false;
483  return true;
484 }
485 
486 template <typename T>
487 bool FieldOfView<T>::AreEqual(const FieldOfView& fov0,
488  const FieldOfView& fov1) {
489  if (fov0.GetLeft() != fov1.GetLeft() || fov0.GetRight() != fov1.GetRight() ||
490  fov0.GetBottom() != fov1.GetBottom() || fov0.GetTop() != fov1.GetTop())
491  return false;
492  return true;
493 }
494 
495 } // namespace math
496 } // namespace ion
497 
498 #endif // ION_MATH_FIELDOFVIEW_H_
void Read(std::istream &in)
This is used for reading FOV objects from a stream.
Definition: fieldofview.h:437
Angle< T > GetCenteredFovY() const
Definition: fieldofview.h:422
static FieldOfView< T > FromProjectionMatrix(const Matrix< 4, T > &matrix)
Constructs a FieldOfView by extracting the four frustum planes from the projection matrix...
Definition: fieldofview.h:212
FieldOfView< float > FieldOfViewf
Definition: fieldofview.h:179
bool SetFromTotalFovAndOpticalCenter(const Angle< T > fov_x, const Angle< T > fov_y, const Point< 2, T > &optical_center_ndc)
Resets the FieldOfView based on a total field of view in both dimensions, and an optical center for t...
Definition: fieldofview.h:249
FieldOfView()
The default constructor sets an angle of 0 (in any unit) for all four half-angles.
Definition: fieldofview.h:183
FieldOfView< double > FieldOfViewd
Definition: fieldofview.h:180
p_ndc **static FieldOfView< T > FromCenteredFovAndOpticalCenter(const Angle< T > centered_fov_x, const Angle< T > centered_fov_y, const Point< 2, T > &optical_center_ndc)
Constructs a FieldOfView based on a centered field of view and an optical center for the projection...
Definition: fieldofview.h:352
Matrix< 4, T > GetProjectionMatrix(T near_p, T far_p) const
Computes the projection matrix corresponding to the frustum defined by the four half angles and the t...
Definition: fieldofview.h:191
A simple class to represent angles.
Definition: angle.h:33
T Radians() const
Get the angle in degrees or radians.
Definition: angle.h:55
The Matrix class defines a square N-dimensional matrix.
Definition: matrix.h:35
ION_API const Matrix< 4, T > PerspectiveMatrixFromFrustum(T x_left, T x_right, T y_bottom, T y_top, T z_near, T z_far)
Returns a 4x4 perspective projection matrix based on the given parameters, which follow the conventio...
friend bool operator!=(const FieldOfView &fov0, const FieldOfView &fov1)
Definition: fieldofview.h:148
Angle< T > GetLeft() const
Accessors for all four half-angles.
Definition: fieldofview.h:115
std::istream & GetExpectedChar(std::istream &in)
Reads a single character from the stream and returns the stream.
Definition: stringutils.h:215
friend bool operator==(const FieldOfView &fov0, const FieldOfView &fov1)
Exact equality and inequality comparisons.
Definition: fieldofview.h:144
Encapsulates a generalized, asymmetric field of view with four half angles.
Definition: fieldofview.h:36
void SetBottom(const Angle< T > &bottom)
Definition: fieldofview.h:123
std::istream & GetExpectedString(std::istream &in, const std::string &expected)
Attempts to read a string from the stream and returns the stream.
Definition: stringutils.h:228
static Angle FromRadians(const T &angle)
Create a angle from radians (no conversion).
Definition: angle.h:45
void Print(std::ostream &out) const
This is used for printing FOV objects to a stream.
Definition: fieldofview.h:431
const T Square(const T &val)
Squares a value.
Definition: utils.h:48
Point.
Definition: vector.h:296
static FieldOfView< T > FromTangents(const T &left, const T &right, const T &bottom, const T &top)
Constructs a FieldOfView from four values tan(alpha) for each half-angle alpha.
Definition: fieldofview.h:201
Angle< T > GetBottom() const
Definition: fieldofview.h:117
std::istream & operator>>(std::istream &in, Angle< T > &a)
Definition: angle.h:135
bool IsZero() const
Returns true iff all four angles are zero (which is the case after using the default constructor)...
Definition: fieldofview.h:478
Angle< T > GetCenteredFovX() const
Gets the centered FOV in each dimension.
std::ostream & operator<<(std::ostream &out, const Angle< T > &a)
An Angle is streamed as degrees.
Definition: angle.h:130
void SetTop(const Angle< T > &top)
Definition: fieldofview.h:124
void SetRight(const Angle< T > &right)
Definition: fieldofview.h:122
void SetLeft(const Angle< T > &left)
Setters for all four half-angles.
Definition: fieldofview.h:121
Angle< T > GetTop() const
Definition: fieldofview.h:118
Point< 2, T > GetOpticalCenter() const
Returns the optical center of a projection that is created using this FieldOfView.
Definition: fieldofview.h:236
Angle< T > GetRight() const
Definition: fieldofview.h:116