vector3d_f.cc 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111
  1. // Copyright (c) 2012 The Chromium Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style license that can be
  3. // found in the LICENSE file.
  4. #include "ui/gfx/geometry/vector3d_f.h"
  5. #include <cmath>
  6. #include "base/strings/stringprintf.h"
  7. #include "ui/gfx/geometry/angle_conversions.h"
  8. namespace {
  9. const double kEpsilon = 1.0e-6;
  10. }
  11. namespace gfx {
  12. std::string Vector3dF::ToString() const {
  13. return base::StringPrintf("[%g %g %g]", x_, y_, z_);
  14. }
  15. bool Vector3dF::IsZero() const {
  16. return x_ == 0 && y_ == 0 && z_ == 0;
  17. }
  18. void Vector3dF::Add(const Vector3dF& other) {
  19. x_ += other.x_;
  20. y_ += other.y_;
  21. z_ += other.z_;
  22. }
  23. void Vector3dF::Subtract(const Vector3dF& other) {
  24. x_ -= other.x_;
  25. y_ -= other.y_;
  26. z_ -= other.z_;
  27. }
  28. double Vector3dF::LengthSquared() const {
  29. return static_cast<double>(x_) * x_ + static_cast<double>(y_) * y_ +
  30. static_cast<double>(z_) * z_;
  31. }
  32. float Vector3dF::Length() const {
  33. return static_cast<float>(std::sqrt(LengthSquared()));
  34. }
  35. void Vector3dF::Scale(float x_scale, float y_scale, float z_scale) {
  36. x_ *= x_scale;
  37. y_ *= y_scale;
  38. z_ *= z_scale;
  39. }
  40. void Vector3dF::Cross(const Vector3dF& other) {
  41. double dx = x_;
  42. double dy = y_;
  43. double dz = z_;
  44. float x = static_cast<float>(dy * other.z() - dz * other.y());
  45. float y = static_cast<float>(dz * other.x() - dx * other.z());
  46. float z = static_cast<float>(dx * other.y() - dy * other.x());
  47. x_ = x;
  48. y_ = y;
  49. z_ = z;
  50. }
  51. bool Vector3dF::GetNormalized(Vector3dF* out) const {
  52. double length_squared = LengthSquared();
  53. *out = *this;
  54. if (length_squared < kEpsilon * kEpsilon)
  55. return false;
  56. out->Scale(1 / sqrt(length_squared));
  57. return true;
  58. }
  59. float DotProduct(const Vector3dF& lhs, const Vector3dF& rhs) {
  60. return lhs.x() * rhs.x() + lhs.y() * rhs.y() + lhs.z() * rhs.z();
  61. }
  62. Vector3dF ScaleVector3d(const Vector3dF& v,
  63. float x_scale,
  64. float y_scale,
  65. float z_scale) {
  66. Vector3dF scaled_v(v);
  67. scaled_v.Scale(x_scale, y_scale, z_scale);
  68. return scaled_v;
  69. }
  70. float AngleBetweenVectorsInDegrees(const gfx::Vector3dF& base,
  71. const gfx::Vector3dF& other) {
  72. // Clamp the resulting value to prevent potential NANs from floating point
  73. // precision issues.
  74. return gfx::RadToDeg(std::acos(fmax(
  75. fmin(gfx::DotProduct(base, other) / base.Length() / other.Length(), 1.f),
  76. -1.f)));
  77. }
  78. float ClockwiseAngleBetweenVectorsInDegrees(const gfx::Vector3dF& base,
  79. const gfx::Vector3dF& other,
  80. const gfx::Vector3dF& normal) {
  81. float angle = AngleBetweenVectorsInDegrees(base, other);
  82. gfx::Vector3dF cross(base);
  83. cross.Cross(other);
  84. // If the dot product of this cross product is normal, it means that the
  85. // shortest angle between |base| and |other| was counterclockwise with respect
  86. // to the surface represented by |normal| and this angle must be reversed.
  87. if (gfx::DotProduct(cross, normal) > 0.0f)
  88. angle = 360.0f - angle;
  89. return angle;
  90. }
  91. } // namespace gfx