// ****************************************************************************
// ****************************************************************************
// ****************************************************************************
//                   V E K T O R K L A S S E    V1.0
//               Written by Jens Thiele in Spetember 1995
// ****************************************************************************
// ****************************************************************************
// ****************************************************************************

/*_____________________________________________________________________________
To Do:
Punkt in parallelogramm ??
testen => universal Testprogramm wird man je alle Routinen benutzt haben ? :-) 
speedtest und evtl beschleunigen !!
einen besseren Gauss schreiben (naja fuer 2x2 ist er suppergut !)
int vektoren ?
punktauflinie ?

KNOWN BUGS :
schneide bei parallele Linien hintereinander (BISJETZT FALSCH !)
routinen muessen const benutzen ueberhaupt nicht staendig dieser zeigerkack

_____________________________________________________________________________*/

#ifndef _vektor_H
#define _vektor_H

#include <math.h>
#include "listen2.H"

// spaeter !
#include "iotype.H"

// ****************************************************************************
// ****************************************************************************
// ****************************************************************************
// ****************************************************************************
//                 K L A S S E N - D E K L A R A T I O N E N
// ****************************************************************************
// ****************************************************************************
// ****************************************************************************
// ****************************************************************************



// ****************************************************************************
// ****************************************************************************
// ****************************************************************************
//                       V E K T O R - O B J E K T E
// ****************************************************************************
// ****************************************************************************
// ****************************************************************************





// ****************************************************************************
// ****************************************************************************
// Koordinaten Vektor:  gut zum addieren, schlecht zum rotieren 
// ****************************************************************************
// ****************************************************************************
// Forward :
class vektor2_poltype;

/// 2-dimensional vector
class vektor2_koordtype
{
public:
    float x;
    float y;

    vektor2_koordtype();
    vektor2_koordtype(float _x,float _y);
    vektor2_koordtype(const vektor2_koordtype *source);
    vektor2_koordtype(const vektor2_poltype *source);
    vektor2_koordtype(iotype *ioptr,int8 mode);

    void change(iotype *ioptr,int8 mode);

  /// Addition
  void add(const vektor2_koordtype *source);
  void add(const vektor2_poltype *source);
  void neg();
  void sub(const vektor2_koordtype *source);
  void sub(const vektor2_poltype *source);
  void rotate(float rad);
  float betrag() const;
  void import(float _x,float _y);
  void import(const vektor2_koordtype *source);
  void import(const vektor2_poltype *source);
};
vektor2_koordtype operator+(const vektor2_koordtype &v1,const vektor2_koordtype &v2);
ostream &operator<<(ostream &ost,const vektor2_koordtype &v);
istream &operator>>(istream &ist,vektor2_koordtype &v);

machezeigerelem_changetype(vektor2_koord);
machekette_changetype(vektor2_koord);


// ****************************************************************************
// ****************************************************************************
// Pol-Vektor:  gut zum rotieren, schlecht zum addieren 
// ****************************************************************************
// ****************************************************************************

/// 2-dimensional vector (in polar format)
class vektor2_poltype
{
public:
    float betrag;
    float dir;

    vektor2_poltype();
    vektor2_poltype(float _betrag,float _dir);
    vektor2_poltype(const vektor2_poltype *source);
    vektor2_poltype(const vektor2_koordtype *source);
    vektor2_poltype(iotype *ioptr,int8 mode);

    void change(iotype *ioptr,int8 mode);
    
    void add(const vektor2_poltype *source);
    void add(const vektor2_koordtype *source);
    void neg();
    void sub(const vektor2_koordtype *source);
    void sub(const vektor2_poltype *source);
    void rotate(float rad);
    void import(float _betrag,float _dir);
    void import(const vektor2_koordtype *source);
    void import(const vektor2_poltype *source);
};

machezeigerelem_changetype(vektor2_pol)
machekette_changetype(vektor2_pol)






// ****************************************************************************
// ****************************************************************************
// ****************************************************************************
//                     L I N I E N - O B J E K T E
// ****************************************************************************
// ****************************************************************************
// ****************************************************************************


// ****************************************************************************
// ****************************************************************************
//  Linie mit Startpunkt und Endpunkt in Koordinatenform !
//  Einfach zum Eingeben !   Nicht zum Rechnen !
// ****************************************************************************
// ****************************************************************************
// Forward:
class linie2_koordpunkt_koorddirtype;
class linie2_polpunkt_poldirtype;

/// A line 
class linie2_koordpunkt_koordpunkttype
{
public:
  vektor2_koordtype startp;
  vektor2_koordtype endp;
  
  linie2_koordpunkt_koordpunkttype();
  linie2_koordpunkt_koordpunkttype(float _x1,float _y1,float _x2,float _y2);
  linie2_koordpunkt_koordpunkttype(const vektor2_koordtype *_startp,const vektor2_koordtype *_endp);
  linie2_koordpunkt_koordpunkttype(const linie2_koordpunkt_koordpunkttype *source);
  linie2_koordpunkt_koordpunkttype(const linie2_koordpunkt_koorddirtype *source);
  linie2_koordpunkt_koordpunkttype(const linie2_polpunkt_poldirtype *source);
  linie2_koordpunkt_koordpunkttype(iotype *ioptr,int8 mode);
  
  void change(iotype *ioptr,int8 mode);
  
  void rotate(float rad);
  // Rueckgabewert 0=keine-,1=eine-,-1=unendlich viele Loesungen
  // sp macht nur sinn bei einer lsg.
  // linie muss eine linie sein d.h. startp!=endp 
  int schneide(const linie2_koordpunkt_koordpunkttype &source,vektor2_koordtype *sp);
  int schneide(const linie2_koordpunkt_koorddirtype &source,vektor2_koordtype *sp);
  int schneide(const linie2_polpunkt_poldirtype &source,vektor2_koordtype *sp);
  
  void import(float _x1,float _y1,float _x2,float _y2);
  void import(const vektor2_koordtype *_startp,const vektor2_koordtype *_endp);
  void import(const linie2_koordpunkt_koordpunkttype *source);
  void import(const linie2_koordpunkt_koorddirtype *source);
  void import(const linie2_polpunkt_poldirtype *source);
};

machezeigerelem_changetype(linie2_koordpunkt_koordpunkt);
machekette_changetype(linie2_koordpunkt_koordpunkt);


// ****************************************************************************
// ****************************************************************************
//  Linie mit Startpunkt und Richtungsvektor in Koordinatenform !
//  Relativ einfach zum Eingeben und gut zum Schneiden !!!! schlecht zum Drehen
//  g: vektor(x) = vektor(startp) + a * vektor(richtung); 0<=a<=1
// ****************************************************************************
// ****************************************************************************

/// Line
class linie2_koordpunkt_koorddirtype
{
public:
  /// Starting point
    vektor2_koordtype startp;
  /// Direction
    vektor2_koordtype richtung;

    linie2_koordpunkt_koorddirtype();
    linie2_koordpunkt_koorddirtype(const vektor2_koordtype *_startp,const vektor2_koordtype *_richtung);
    linie2_koordpunkt_koorddirtype(const linie2_koordpunkt_koordpunkttype *source);
    linie2_koordpunkt_koorddirtype(const linie2_koordpunkt_koorddirtype *source);
    linie2_koordpunkt_koorddirtype(const linie2_polpunkt_poldirtype *source);
    linie2_koordpunkt_koorddirtype(iotype *ioptr,int8 mode);

    void change(iotype *ioptr,int8 mode);

    void rotate(float rad);
    // Rueckgabewert 0=keine-,1=eine-,-1=unendlich viele Loesungen
    int schneide(const linie2_koordpunkt_koordpunkttype &source,
		 vektor2_koordtype *sp);
    int schneide(const linie2_koordpunkt_koorddirtype &source,
		 vektor2_koordtype *sp);
    int schneide(const linie2_polpunkt_poldirtype &source,
		 vektor2_koordtype *sp);
//    int punktauflinie(vektor2_koordtype *punkt);
    void import(const vektor2_koordtype *_startp,
		       const vektor2_koordtype *_richtung);
    void import(const linie2_koordpunkt_koordpunkttype *source);
    void import(const linie2_koordpunkt_koorddirtype *source);
    void import(const linie2_polpunkt_poldirtype *source);
};

machezeigerelem_changetype(linie2_koordpunkt_koorddir)
machekette_changetype(linie2_koordpunkt_koorddir)


// ****************************************************************************
// ****************************************************************************
//  Linie mit Startpunkt und Richtungsvektor in Pol-Koordinatenform !
//  Schlecht zum Eingeben, gut zum Drehen, schlecht zum Schneiden
// ****************************************************************************
// ****************************************************************************

class linie2_polpunkt_poldirtype
{
public:
    vektor2_poltype startp;
    vektor2_poltype richtung;

    linie2_polpunkt_poldirtype();
    linie2_polpunkt_poldirtype(
	const vektor2_poltype *_startp,const vektor2_poltype *_richtung);
    linie2_polpunkt_poldirtype(
	const linie2_koordpunkt_koordpunkttype *source);
    linie2_polpunkt_poldirtype(
	const linie2_koordpunkt_koorddirtype *source);
    linie2_polpunkt_poldirtype(
	const linie2_polpunkt_poldirtype *source);
    linie2_polpunkt_poldirtype(iotype *ioptr,int8 mode);

    void change(iotype *ioptr,int8 mode);

    void rotate(float rad);
    // Rueckgabewert 0=keine-,1=eine-,-1=unendlich viele Loesungen
    int schneide(const linie2_koordpunkt_koordpunkttype &source,
		 vektor2_koordtype *sp);
    int schneide(const linie2_koordpunkt_koorddirtype &source,
		 vektor2_koordtype *sp);
    int schneide(const linie2_polpunkt_poldirtype &source,
		 vektor2_koordtype *sp);
    void import(const vektor2_poltype *_startp,
		       const vektor2_poltype *_richtung);
    void import(const linie2_koordpunkt_koordpunkttype *source);
    void import(const linie2_koordpunkt_koorddirtype *source);
    void import(const linie2_polpunkt_poldirtype *source);
};

machezeigerelem_changetype(linie2_polpunkt_poldir)
machekette_changetype(linie2_polpunkt_poldir)








// ****************************************************************************
// ****************************************************************************
// ****************************************************************************
// ****************************************************************************
//                      P U B L I C - F U N K T I O N E N
// ****************************************************************************
// ****************************************************************************
// ****************************************************************************
// ****************************************************************************


// ********************************** BERECHNET ABSOLUTWERT VON FLOAT
float floatabs(float a);

// Runden !! float als int interpretieren ist FALSCH !!!!!!!!
inline int ftoi(float x)
{
    x+=0.5;
    int ix=int(x);
    if (x>=0)
	{
	    return(ix);
	}
    ix--;
    return(ix);
}


// 2 Gleichungen, 2 Unbekannte (r,s)
// r*vektor2(a) + s*vektor2(b) = vektor2(c)  
// ________________________________________
// |_____r______|______s_____|____________|
// |   a->x     |    b->x    |    c->x    |
// |   a->y     |    b->y    |    c->y    |
// |____________|____________|____________|

/// Gaussian algorithm for 2 rows and 3 columns 
int gauss_dim2(vektor2_koordtype *a,vektor2_koordtype *b,
		vektor2_koordtype *c,float *r,float *s);


#endif




















