// 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) {
  // Clamp the resulting value to prevent potential NANs from floating point
  // precision issues.
  return gfx::RadToDeg(std::acos(fmax(
      fmin(gfx::DotProduct(base, other) / base.Length() / other.Length(), 1.f),
      -1.f)));
}

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
