// coordinate.h: interface for the coordinate class.
//
//////////////////////////////////////////////////////////////////////

#if !defined(AFX_COORDINATE_H__D8D2460C_10FF_4219_8916_46072191940A__INCLUDED_)
#define AFX_COORDINATE_H__D8D2460C_10FF_4219_8916_46072191940A__INCLUDED_

#include <iostream>
#include <cmath>
#include "iarrays.h"
#include "kryomolecule_export.h"

class KRYOMOLECULE_EXPORT coordinate
{
public:
  coordinate();
  coordinate(float cx,float cy,float cz);
  coordinate(const IMArray<float>& m);
  coordinate(const IMArray<double>& m);
  coordinate operator^(coordinate c);
  float operator*(coordinate c);
  coordinate operator* (float f) const;
  coordinate operator/(float f);
  void operator-=(coordinate c);
  void operator +=(float f);
  void operator +=(coordinate c);
  void operator *=(float f);
  void operator /=(float f);
  coordinate operator -(coordinate b);
  coordinate operator+(coordinate b) const;

  virtual ~coordinate();
  float z;
  float y;
  float x;
  static float distance(coordinate a, coordinate b);
  /** No descriptions */
  float norm() const;
  /** No descriptions */
  static  float GetAngleVector(coordinate a, coordinate b);
  static float dihedral(coordinate a, coordinate b, coordinate c, coordinate d);
  static  coordinate GetMiddle(coordinate a, coordinate b);
  static coordinate RotAroundAxis(coordinate a, coordinate b, coordinate c, float theta);


};

class quaternion
{
public:
  quaternion() { w=v.x=v.y=v.z=0; }
  quaternion(float scalar,const coordinate& c) { w=scalar; v=c; }
  float w;
  coordinate v;
  float norm()
  {
    return std::sqrt(w*w+v.x*v.x+v.y*v.y+v.z*v.z);
  }
  quaternion invert()
  {
    quaternion q1;

    q1.w=this->w;
    q1.v.x=-(this->v.x);
    q1.v.y=-(this->v.y);
    q1.v.z=-(this->v.z);
    return q1;
  }
  quaternion operator^(quaternion q)
  {
    quaternion  q1;
    q1.w=  this->w*q.w -  this->v.x*q.v.x - this->v.y*q.v.y -this->v.z*q.v.z;
    q1.v.x=this->w*q.v.x+this->v.x*q.w+this->v.y*q.v.z-this->v.z*q.v.y;
    q1.v.y=this->w*q.v.y+this->v.y*q.w+this->v.z*q.v.x-this->v.x*q.v.z;
    q1.v.z=this->w*q.v.z+this->v.z*q.w+this->v.x*q.v.y-this->v.y*q.v.x;

    return q1;
  }

};
/** used mainly for debugging purposes */

inline std::ostream& operator << (std::ostream& s,coordinate& c)
{
  s << " (" << c.x << "," << c.y << ","  << c.z << ") ";

  return s;
}

inline coordinate operator*(float f,coordinate& c)
{
  coordinate a=c*f;
  return a;
}
#endif // !defined(AFX_COORDINATE_H__D8D2460C_10FF_4219_8916_46072191940A__INCLUDED_)
