#ifndef INCLUDE_NASTVECTOR2D_H
#define INCLUDE_NASTVECTOR2D_H
//-----------------------------------------------------------------------------
// NastVector2d.h
//-----------------------------------------------------------------------------
//
//  Copyright (C) 1998 Technische Universitaet Muenchen, Germany
//                   written by Bernhard Brueck
//
//  This file is part of Nast++
//
//-----------------------------------------------------------------------------
//  CNastVector2d ist ein zweidimensionaler Vektor. Es lassen sich
//  zusammen mit CNastPoint2d Berechnungen durchführen
//  Der Defaultkonstruktor legt die Koordinaten auf (0;0) fest.
//-----------------------------------------------------------------------------
//  moegliche Operationen:
//
//    scale( double d)        Skalierung des Vektors
//    normalize()             Normalisierung auf die Laenge 0
//    length()                Laenge des Vektors
//    lengthSquare()          Quadrat der Laenge
//
//    Vec1 == Vec2            Gleichheit (exakt)
//    Vec1 != Vec2            Ungleichheit (exakt)
//    Vec1 += Vec2            Vektor addieren
//    Vec1 -= Vec2            Vektor subdrahieren
//    Vec1 *= Skalar          Vektor skalieren
//    Vec1 + Vec2             Vektoraddition
//    Vec1   * Skalar         Vektor skalieren
//    Skalar * Vec1                 "
//-----------------------------------------------------------------------------
//  Aenderungen:
//     

#include "NastConfig.h"
#include "NastDebug.h"
#include "NastObject.h"

#include <math.h>

class CNastPoint2d;
class CNastVector2d : public CNastObject
{
public:
    //-------------------------------------------------------------------------
    //                         Konstruktor + Destruktor
    //-------------------------------------------------------------------------

    CNastVector2d();			                    
    CNastVector2d( double x, double y );                    
    virtual ~CNastVector2d();			            
    CNastVector2d( const CNastVector2d & o);	            
    const CNastVector2d& operator=( const CNastVector2d &o );

    //-------------------------------------------------------------------------
    //                             Memberfunktionen
    //-------------------------------------------------------------------------

    //  Zugriff auf die Koordinaten				
    void x( double x );
    void y( double y );

    double x() const;
    double y() const;

    //  exakter Vergleich
    bool operator==( const CNastVector2d &other ) const;
    bool operator!=( const CNastVector2d &other ) const;

    //  Berechnungen
    CNastVector2d& operator+=( const CNastVector2d &other );
    CNastVector2d& operator-=( const CNastVector2d &other );
    CNastVector2d& operator*=( double s );
    CNastVector2d& operator/=( double s );

    //  Operationen mit der Laenge
    double length() const;
    double lengthSquare() const;

    CNastVector2d& normalize();
    CNastVector2d& scale( double s );

    //-------------------------------------------------------------------------
    //                                  Debug
    //-------------------------------------------------------------------------
    //  debugInfo    gibt Information ueber den Zustand des Objekts aus
    //  assertValid  testet das Objekt auf Integritaet
    //

    virtual void debugDump( CNastDumpContext &dumpContext ) const;
    virtual void assertValid() const;


private:
    //-------------------------------------------------------------------------
    //                            Membervariablen
    //-------------------------------------------------------------------------
    double m_x;
    double m_y;
};

//-------------------------------------------------------------------------
//                               Operatoren
//-------------------------------------------------------------------------
inline CNastVector2d operator+(const CNastVector2d &vec1, const CNastVector2d &vec2);
inline CNastVector2d operator-(const CNastVector2d &vec1, const CNastVector2d &vec2);
inline CNastVector2d operator*(const CNastVector2d &vec, double fac);
inline CNastVector2d operator*(double fac, const CNastVector2d &vec);
inline CNastVector2d operator/(const CNastVector2d &vec, double fac);

//-------------------------------------------------------------------------
//                                 inline
//-------------------------------------------------------------------------

// Defaultkonstruktor
inline CNastVector2d::CNastVector2d()
    :m_x(0.0), 
     m_y(0.0)
{}

//  Konstruktor mit x,y-Angabe
inline CNastVector2d::CNastVector2d( double x, double y )
    :m_x( x ), 
     m_y( y )
{}

//  Copyconmstructor
inline CNastVector2d::CNastVector2d( const CNastVector2d & other)
    :CNastObject(),
     m_x( other.m_x ), 
     m_y( other.m_y )
{}

//  Zuweisungsoperator
inline const CNastVector2d&  CNastVector2d::operator=( const CNastVector2d &other )
{
    m_x = other.m_x;
    m_y = other.m_y;
    return *this;
}

//  x-Koordinate setzen
inline void CNastVector2d::x( double x ) 
{ 
    m_x = x; 
};

//  y-Koordinate setzen
inline void CNastVector2d::y( double y ) 
{ 
    m_y = y; 
};

//  x-Koordinate lesen
inline double CNastVector2d::x() const   
{ 
    return m_x; 
};

//  y-Koordinate lesen
inline double CNastVector2d::y() const   
{ 
    return m_y; 
};

//  exakter Test auf Gleichheit der Koordinaten
inline bool CNastVector2d::operator==( const CNastVector2d &other ) const
{ 
    return m_x == other.m_x 
        && m_y == other.m_y; 
}

//  exakter Test auf Ungleicheit der Koordinaten
inline bool CNastVector2d::operator!=( const CNastVector2d &other ) const
{ 
    return m_x != other.m_x 
        || m_y != other.m_y; 
}

//  Addition eines anderen Vektors
inline CNastVector2d& CNastVector2d::operator+=( const CNastVector2d &other )
{   
    m_x += other.m_x;
    m_y += other.m_y;
    return *this;     
}

//  Subdraktion eines anderen Vektors
inline CNastVector2d& CNastVector2d::operator-=( const CNastVector2d &other )
{  
    m_x -= other.m_x;
    m_y -= other.m_y;
    return *this; 
}

//  Skalierung um einen Faktor
inline CNastVector2d& CNastVector2d::operator*=( double fac )
{  
    m_x *= fac;
    m_y *= fac;
    return *this; 
}

//  Skalierung um einen 1/Faktor
inline CNastVector2d& CNastVector2d::operator/=( double fac )
{  
    NAST_ASSERT( fac != 0);
    m_x /= fac;
    m_y /= fac;
    return *this; 
}

//  Laenge des Vektors im Quadrat
inline double CNastVector2d::lengthSquare() const
{ 
    return m_x * m_x + m_y * m_y; 
}

// Laenge des Vektors
inline double CNastVector2d::length() const
{ 
    return hypot( m_x, m_y); 
}

// Skalierung des Vektors
inline CNastVector2d& CNastVector2d::scale( double s ) 
{ 
    m_x *= s;  
    m_y *= s; 
    return *this; 
}

//  Skalierung auf die Laenge 1
inline CNastVector2d& CNastVector2d::normalize()
{
    double l2 = lengthSquare();
    if( l2 > 0 && l2 != 1)
        scale( 1 / sqrt( l2 ));
    return *this;
}

//  Addition Vektor Vektor
inline CNastVector2d operator+(const CNastVector2d &vec1, const CNastVector2d &vec2)
{
    return CNastVector2d( vec1.x() + vec2.x(),
        		  vec1.y() + vec2.y());
}

//  Subdraktion Vektor Vektor
inline CNastVector2d operator-(const CNastVector2d &vec1, const CNastVector2d &vec2)
{
    return CNastVector2d( vec1.x() - vec2.x(),
        		  vec1.y() - vec2.y());
}

//  Multiplikation Vektor Faktor
inline CNastVector2d operator*(const CNastVector2d &vec, double fac)
{
    return CNastVector2d( fac * vec.x(),
        		  fac * vec.y() );
}

//  Multiplikation Faktor Vektor
inline CNastVector2d operator*(double fac, const CNastVector2d &vec)
{
    return CNastVector2d( fac * vec.x(),
        		  fac * vec.y() );
}

inline CNastVector2d operator/(const CNastVector2d &vec, double fac)
{
    NAST_ASSERT(fac != 0);
    return CNastVector2d( vec.x() / fac,
        		  vec.y() / fac);
}



#endif // INCLUDE_NASTVECTOR2D_H

