// ===================================================================
// $Id: vector2.cpp,v 1.1.1.1 2002/10/21 13:20:03 damez Exp $
//
// vector2.cpp
//     CVector2D class implements an 2D vector
//
// Licence and usage conditions in November 2003:
// This file can be used and modified only with written permission of
// Vlastimil Havran, Pohodli 27, 57001 Litomysl, the Czech Republic.
// This library is granted to be used by Polina Kondratieva within
// her MPI HIWI job working on BRDFLIB library. The usage condition
// may change in the next version of the library. At the moment,
// the library development is supported by Max-Planck-Institut for
// Informatik, Stuhlsatzenhausweg 85, 66123 Saarbruecken Germany
// See WWW: http://www.mpi-sb.mpg.de
// REPLACEMENT_STRING
//
// Initial coding by Jiri Bittner and Vlastimil Havran, 1998.
//
// Given to BRDFLIB project for the Polina Kondratieva's
// HIWI JOB assignment in November 2003.
// ===================================================================


// BRDFLIB headers
#include "config.h"
#include "vector2.h"


__BEGIN_BRDFLIB_SOURCE

// Overload << operator for C++-style output
ostream&
operator<< (ostream &s, const CVector2D &A)
{
  return s << "(" << A.x() << ", " << A.y() << ")";
}

// Overload >> operator for C++-style input
istream&
operator>> (istream &s, CVector2D &A)
{
  char a;
  // read "(x, y)"
  return s >> a >> A.x() >> a >> A.y() >> a;
}


// Precompute which.  which is 0 if the normal is dominant
// in the X direction, 1 if the Y direction.
int
CVector2D::DominantAxis()
{
  return (fabs(x()) > fabs(y())) ?  0 : 1;
}

void
CVector2D::ExtractVerts(float *p, int dominant) const
{
  if (dominant == 0)
    *p = y();
  else
    *p = x();
}

float
CVector2D::Normalize()
{
  float s = Size();

  if (s != 0.0) {
    xx /= s;
    yy /= s;
  }
  return s;
}

CVector2D
CVector2D::operator-(const CVector2D &v) const
{
  CVector2D u;
  u.SetX(x()-v.x());
  u.SetY(y()-v.y());
  return u;
}

CVector2D
CVector2D::operator+(const CVector2D &v) const
{
  CVector2D u;
  u.SetX(x()+v.x());
  u.SetY(y()+v.y());
  return u;
}

CVector2D
CVector2D::operator*(const float t) const
{
  CVector2D u;
  u.SetX(t*x());
  u.SetY(t*y());
  return u;
}

int
CVector2D::Equal(const CVector2D &u, float trash) const
{
 return ( (fabs(x() - u.x()) < trash) && (fabs(y() - u.y()) < trash) ); 
}


// get the angle between two vectors in range 0 - PI

float
CVector2D::Angle(const CVector2D &v) const
{
  float cosine;
  cosine = DotProd(*this, v) / (Size() * v.Size());
  return acos(cosine);
}

float
CVector2D::Cosine(const CVector2D &v) const
{
  return DotProd(*this, v)  /  (Size() * v.Size());
}

// cosine assuming that this vector is normalized
float
CVector2D::CosineN(const CVector2D &v) const
{
  return DotProd(*this, v) / v.Size();
}

// if a given vector is smaller in one of coordinates than this, update
CVector2D&
CVector2D::UpdateMin(const CVector2D &v)
{
  if (x() > v.x())
    SetX(v.x());
  if (y() > v.y())
    SetY(v.y());
  return *this;
}

CVector2D&
CVector2D::UpdateMax(const CVector2D &v)
{
  if ( x() < v.x() )
    SetX(v.x());
  if ( y() < v.y() )
    SetY(v.y());
  return *this;
}


__END_BRDFLIB_SOURCE
