// ===================================================================
// $Id: sphcoord.h,v 1.2 2003/10/30 16:36:35 havran Exp $
//
// sphcoord.h
//     Header file for spherical coordinates structures.
//
// Class: CSphCoordNorm
//
// 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 Jaroslav Krivanek, dec 2000, under the supervision
// of Vlastimil Havran.
//
// Given to BRDFLIB project for the Polina Kondratieva's
// HIWI JOB assignment in November 2003.
// ===================================================================

#ifndef __SPHCOORD_H__
#define __SPHCOORD_H__

// BRDFLIB headers
#include "configh.h"
#include "vector3.h"

// standard headers
#include <cassert>

__BEGIN_BRDFLIB_HEADER

/**
   Class which contains normalized direction in 3D space in
   spherical coordinates using two angles.

   Phi is in <0,2*PI> and theta in <0,PI>.

   z = cos(theta), phi is rotated from x to y.
   It is not the same as in Matrix4!!!!
*/
class CSphCoordNorm
{
public:
  float theta, phi;

  // Constructors
  CSphCoordNorm()  {}
  
  CSphCoordNorm(float t, float p):   theta(t), phi(p)  {}

  CSphCoordNorm(const CSphCoordNorm& c): theta(c.theta), phi(c.phi) {}

  CSphCoordNorm(const CVector3D& c) {  SetValue(c); }

  // Late constructors
  void SetValue(float t, float p)
  { theta=t; phi=p; }
  
  void SetValue(const CSphCoordNorm& c)
  { theta=c.theta; phi=c.phi; }

  void SetValue(const CVector3D& c);

  // Transformation to cartesian coords
  CVector3D ToCartesian() const;

  friend ostream& operator<<(ostream& o, const CSphCoordNorm& c);
};


inline void CSphCoordNorm::SetValue(const CVector3D& c)
{
  assert(c.x<=1.0);   assert(c.x>=-1.0);
  assert(c.y<=1.0);   assert(c.y>=-1.0);
  assert(c.z<=1.0);   assert(c.z>=-1.0);
  
  phi = atan2(c.y,c.x);
  if(phi<0)
    phi = 2.0*M_PI + phi;
  
  theta = acos(c.z);
}

inline CVector3D CSphCoordNorm::ToCartesian() const
{
  return CVector3D(cos(phi)*sin(theta),
		   sin(phi)*sin(theta),
		   cos(theta));
}

inline ostream& operator<<(ostream& o, const CSphCoordNorm& c)
{
  return o << "(" << c.theta/M_PI << " PI, " << c.phi/M_PI << " PI)";
}

__END_BRDFLIB_HEADER

#endif // __SPHCOORD_H__
