V_K4.h 6.51 KB
/**
 * \file V_K4.h
 *
 * \brief Klasse die einen 4er-Vektor mathematisch beschreibt und handled.
 *
 * Hier gibt alles was man für Vektoren so braucht (Vektorprodukt,
 * Skalarprodukt, Addition, Subtraktion, Multiplikation mit Matrize)
 *
 * \author Georg Steffers <georg@steffers.org> [gs]
 *
 * \date 04.12.2003
 *
 * \version ..2002 [gs]: erste funktionierende Implementation
 * \version 18.12.2003 [gs]: Vergleichsoperator hinzugef&uuml;gt.
 */ 

/* 
 * Copyright (C)2003 Georg Steffers
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 * 
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */

#ifndef __V_K4_H__
#define __V_K4_H__

#include <cmath>
#include <iostream>

#include "Mmn.h"

/**
 * \brief Winkel auf -360 bis +360 beschr&auml;nken und als double
 *        handhaben.
 *
 * Wird ein Winkel < -360 oder > +360 angegeben, so wird sein Vorkommateil
 * auf diesen Bereich gestuzt und der Nachkommateil hinzuaddiert.
 */
#define WINKEL(x)    ((double)((int)(x)%360)+(double)(x)-(int)(x))
#define BOGENMASS(x) (WINKEL((x))*M_PI/180)
#define RAD(x)       (BOGENMASS((x)))
#define GRAD(x)      (WINKEL((x))*180/M_PI)
#define SQR(x)       ((x)*(x))

using namespace std;

template <class K>
class V_K4 : public Mmn<K> {
    public:
        V_K4() : Mmn<K>(4, 1) {}
        V_K4(Mmn<K> m) : Mmn<K>(m) {}
        V_K4(K* a) : Mmn<K>(a, 4, 1) {}
        V_K4(K e1, K e2, K e3, K e4=0) : Mmn<K>(4,1) {
            _a[0][0]=e1; _a[1][0]=e2; 
            _a[2][0]=e3; _a[3][0]=e4;
        }

        const K& operator[](unsigned i) const {  return _a[i>m-1?m-1:i][0]; }
        K& operator[](unsigned i) { return _a[i>m-1?m-1:i][0]; }
        K& X(unsigned i) { return (*this)[0]; }
        K& Y(unsigned i) { return (*this)[1]; }
        K& Z(unsigned i) { return (*this)[2]; }
        K& W(unsigned i) { return (*this)[3]; }

        K v_betr(void) const { return sqrt(*this % *this); }

        V_K4<K> v_norm(void) const { return *this * (1/v_betr()); }

        K operator% (const V_K4<K>&) const;
        V_K4<K> operator| (const V_K4<K>&) const;
        bool operator== (const V_K4<K>& v) const {
           if(this->m==v.m &&
              this->n==v.n) {
              for(unsigned i=0; i<m; i++)
                 for(unsigned j=0; j<n; j++)
                    if(_a[i][j]!=v._a[i][j])
                       return false;
           }
           else
              return false;

           return true;
        }
};

template <class K>
inline ostream& operator<<(ostream& strm, const V_K4<K>& A) {
    A.print(strm);

    return strm;
}

#include "V_K4_tpl.h"

/**
 * \brief Liefert die Matrize zur Rotation eines Punktes um einen
 *        beliebigen Vektor
 */
class mat_rot_axe : public Mmn<double> {
   public:
      mat_rot_axe(double* a) : Mmn<double>(a, 4, 4) {}
      mat_rot_axe(double w=0, 
            V_K4<double> const& axe=V_K4<double>(0,0,1,0)) {
         V_K4<double> u(axe.v_norm());

         double A[4][4]={{SQR(u[0])+cos(RAD(w))*(1-SQR(u[0])),
                          u[0]*u[1]*(1-cos(RAD(w)))-u[2]*sin(RAD(w)),
                          u[2]*u[0]*(1-cos(RAD(w)))+u[1]*sin(RAD(w)),
                          0},
                         {u[0]*u[1]*(1-cos(RAD(w)))+u[2]*sin(RAD(w)),
                          SQR(u[1])+cos(RAD(w))*(1-SQR(u[1])),
                          u[1]*u[2]*(1-cos(RAD(w)))-u[0]*sin(RAD(w)),
                          0},
                         {u[2]*u[0]*(1-cos(RAD(w)))-u[1]*sin(RAD(w)),
                          u[1]*u[2]*(1-cos(RAD(w)))+u[0]*sin(RAD(w)),
                          SQR(u[2])+cos(RAD(w))*(1-SQR(u[2])),
                          0},
                         {0,0,0,1}};

         *this=mat_rot_axe((double*)A);
      }
};

/**
 * \brief Liefert die Matrize zur Rotation eines Punktes um die
 *        X-Achse
 */
class mat_rot_x : public Mmn<double> {
   public:
      mat_rot_x(double* a) : Mmn<double>(a, 4, 4) {}
      mat_rot_x(double w=0) {
         double A[4][4]={{1,0,0,0},
                         {0,cos(RAD(w)),-sin(RAD(w)),0},
                         {0,sin(RAD(w)),cos(RAD(w)),0},
                         {0,0,0,1}};

         *this=mat_rot_x((double*)A);
      }
};

/**
 * \brief Liefert die Matrize zur Rotation eines Punktes um die
 *        Y-Achse
 */
class mat_rot_y : public Mmn<double> {
   public:
      mat_rot_y(double* a) : Mmn<double>(a, 4, 4) {}
      mat_rot_y(double w=0) {
         double A[4][4]={{cos(RAD(w)),0,sin(RAD(w)),0},
                         {0,1,0,0},
                         {-sin(RAD(w)),0,cos(RAD(w)),0},
                         {0,0,0,1}};

         *this=mat_rot_y((double*)A);
      }
};

/**
 * \brief Liefert die Matrize zur Rotation eines Punktes um die
 *        Z-Achse
 */
class mat_rot_z : public Mmn<double> {
   public:
      mat_rot_z(double* a) : Mmn<double>(a, 4, 4) {}
      mat_rot_z(double w=0) {
         double A[4][4]={{cos(RAD(w)),-sin(RAD(w)),0,0},
                         {sin(RAD(w)),cos(RAD(w)),0,0},
                         {0,0,1,0},
                         {0,0,0,1}};

         *this=mat_rot_z((double*)A);
      }
};

/**
 * \brief Liefert die Matrize zur Verschiebung eines Punktes um 
 *        tx. ty und tz
 */
class mat_translate : public Mmn<double> {
   public:
      mat_translate(double* a) : Mmn<double>(a, 4, 4) {}
      mat_translate(double tx=0, double ty=0, double tz=0) {
         double A[4][4]={{1,0,0,tx},
                         {0,1,0,ty},
                         {0,0,1,tz},
                         {0,0,0,1}};

         *this=mat_translate((double*)A);
      }
};

/**
 * \brief Liefert die Matrize zur Verformung eines Punktes um 
 *        sx. sy und sz
 */
class mat_transform : public Mmn<double> {
   public:
      mat_transform(double* a) : Mmn<double>(a, 4, 4) {}
      mat_transform(double sx=0, double sy=0, double sz=0) {
         double A[4][4]={{sx,0,0,0},
                         {0,sy,0,0},
                         {0,0,sz,0},
                         {0,0,0,1}};

         *this=mat_transform((double*)A);
      }
};

#endif // __V_K4_H__