diff options
Diffstat (limited to 'ui/gfx/geometry/vector3d_f.cc')
-rw-r--r-- | ui/gfx/geometry/vector3d_f.cc | 108 |
1 files changed, 108 insertions, 0 deletions
diff --git a/ui/gfx/geometry/vector3d_f.cc b/ui/gfx/geometry/vector3d_f.cc new file mode 100644 index 0000000000..749e330f27 --- /dev/null +++ b/ui/gfx/geometry/vector3d_f.cc @@ -0,0 +1,108 @@ +// Copyright (c) 2012 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "ui/gfx/geometry/vector3d_f.h" + +#include <cmath> + +#include "base/strings/stringprintf.h" +#include "ui/gfx/geometry/angle_conversions.h" + +namespace { +const double kEpsilon = 1.0e-6; +} + +namespace gfx { + +std::string Vector3dF::ToString() const { + return base::StringPrintf("[%f %f %f]", x_, y_, z_); +} + +bool Vector3dF::IsZero() const { + return x_ == 0 && y_ == 0 && z_ == 0; +} + +void Vector3dF::Add(const Vector3dF& other) { + x_ += other.x_; + y_ += other.y_; + z_ += other.z_; +} + +void Vector3dF::Subtract(const Vector3dF& other) { + x_ -= other.x_; + y_ -= other.y_; + z_ -= other.z_; +} + +double Vector3dF::LengthSquared() const { + return static_cast<double>(x_) * x_ + static_cast<double>(y_) * y_ + + static_cast<double>(z_) * z_; +} + +float Vector3dF::Length() const { + return static_cast<float>(std::sqrt(LengthSquared())); +} + +void Vector3dF::Scale(float x_scale, float y_scale, float z_scale) { + x_ *= x_scale; + y_ *= y_scale; + z_ *= z_scale; +} + +void Vector3dF::Cross(const Vector3dF& other) { + double dx = x_; + double dy = y_; + double dz = z_; + float x = static_cast<float>(dy * other.z() - dz * other.y()); + float y = static_cast<float>(dz * other.x() - dx * other.z()); + float z = static_cast<float>(dx * other.y() - dy * other.x()); + x_ = x; + y_ = y; + z_ = z; +} + +bool Vector3dF::GetNormalized(Vector3dF* out) const { + double length_squared = LengthSquared(); + *out = *this; + if (length_squared < kEpsilon * kEpsilon) + return false; + out->Scale(1 / sqrt(length_squared)); + return true; +} + +float DotProduct(const Vector3dF& lhs, const Vector3dF& rhs) { + return lhs.x() * rhs.x() + lhs.y() * rhs.y() + lhs.z() * rhs.z(); +} + +Vector3dF ScaleVector3d(const Vector3dF& v, + float x_scale, + float y_scale, + float z_scale) { + Vector3dF scaled_v(v); + scaled_v.Scale(x_scale, y_scale, z_scale); + return scaled_v; +} + +float AngleBetweenVectorsInDegrees(const gfx::Vector3dF& base, + const gfx::Vector3dF& other) { + return gfx::RadToDeg( + std::acos(gfx::DotProduct(base, other) / base.Length() / other.Length())); +} + +float ClockwiseAngleBetweenVectorsInDegrees(const gfx::Vector3dF& base, + const gfx::Vector3dF& other, + const gfx::Vector3dF& normal) { + float angle = AngleBetweenVectorsInDegrees(base, other); + gfx::Vector3dF cross(base); + cross.Cross(other); + + // If the dot product of this cross product is normal, it means that the + // shortest angle between |base| and |other| was counterclockwise with respect + // to the surface represented by |normal| and this angle must be reversed. + if (gfx::DotProduct(cross, normal) > 0.0f) + angle = 360.0f - angle; + return angle; +} + +} // namespace gfx |