#ifndef __CTM_H__
#define __CTM_H__

#include <Matrix.H>
#include <Transform.H>

class CTM {
 public:
   inline CTM(void);

   inline CTM& Identify(void);

   inline CTM& Scale(double, double, double);
   inline CTM& Translate(double, double, double);
   inline CTM& RotateX(double, double=0.0, double=0.0, double=0.0);
   inline CTM& RotateY(double, double=0.0, double=0.0, double=0.0);
   inline CTM& RotateZ(double, double=0.0, double=0.0, double=0.0);

   inline Matrix Points(void) const;
   inline Matrix Vectors(void) const;

   inline friend CTM operator*(const CTM&, const CTM&);
 private:
   Matrix ctm_points;
   Matrix ctm_vectors;
};

inline CTM::CTM(void)
:ctm_points(4,4), ctm_vectors(4,4)
{
   ctm_points.Identify();
   ctm_vectors.Identify();
}

inline CTM& CTM::Identify(void)
{
   ctm_points.Identify();
   ctm_vectors.Identify();

   return(*this);
}

inline CTM& CTM::Scale(double x, double y, double z)
{
   ctm_points *= ::Scale(x,y,z);

   return(*this);
}

inline CTM& CTM::Translate(double x, double y, double z)
{
   ctm_points *= ::Translate(x,y,z);

   return(*this);
}

inline CTM& CTM::RotateX(double t, double x, double y, double z)
{
   ctm_points *= ::RotateX(t,x,y,z);
   ctm_vectors *= ::RotateX(t,0.0,0.0,0.0);

   return(*this);
}

inline CTM& CTM::RotateY(double t, double x, double y, double z)
{
   ctm_points *= ::RotateY(t,x,y,z);
   ctm_vectors *= ::RotateY(t,0.0,0.0,0.0);

   return(*this);
}

inline CTM& CTM::RotateZ(double t, double x, double y, double z)
{
   ctm_points *= ::RotateZ(t,x,y,z);
   ctm_vectors *= ::RotateZ(t,0.0,0.0,0.0);

   return(*this);
}

inline Matrix CTM::Points(void) const
{
   return(ctm_points);
}

inline Matrix CTM::Vectors(void) const
{
   return(ctm_vectors);
}

inline CTM operator*(const CTM& c1, const CTM& c2)
{
   CTM c3(c1);

   c3.ctm_points *= c2.ctm_points;
   c3.ctm_vectors *= c2.ctm_vectors;

   return(c3);
}

#endif /* __CTM_H__ */
