#ifndef INCLUDE_NASTPOINT2D_H
#define INCLUDE_NASTPOINT2D_H

//-----------------------------------------------------------------------------
// NastPoint2d.h
//-----------------------------------------------------------------------------
//
//  Copyright (C) 1998 Technische Universitaet Muenchen, Germany
//                   written by Bernhard Brueck
//
//  This file is part of Nast++
//
//-----------------------------------------------------------------------------
//  CNastPoint2d stellt einen Punkt mit x- und y-Koordinate dar.
//  Punkte lassen sich durch Addition von Vektoren verschieben.
//  mit NastIsEqual(...) laesst sich testen ob zwei Punkte aufeinanderiegen.
//  Der Defaultkonstruktor legt die Koordinaten auf (0;0) fest.
//-----------------------------------------------------------------------------
//  moegliche Operationen:
//
//    scale( double d)        Skalierung des Vektors
//    normalize()             Normalisierung auf die Laenge 0
//    dist(Pnt)               Abstand zwischen zwei Punkten
//    distSquare(Pnt)         Quadrat des Abstand zwischen zwei Punkten
//    isEqual(Pnt1,Pnt2)      Gleichheit (bis auf NAST_GEOMETRIE_EPS)
//
//    Pnt1 == Pnt2            Gleichheit (exakt)
//    Pnt1 != Pnt2            Ungleichheit (exakt)
//    Pnt  += Vec             Vektor addieren
//    Pnt  -= Vec             Vektor subdrahieren
//    Pnt + Vec               Vektor addieren
//    Pnt - Vec               Vektor subdrahieren
//-----------------------------------------------------------------------------
//  Aenderungen:
//     

#include "NastConfig.h"
#include "NastObject.h"
#include "NastVector2d.h"

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

    CNastPoint2d();
    CNastPoint2d( double x, double y);

    virtual ~CNastPoint2d();

    CNastPoint2d( const CNastPoint2d & other);
    const CNastPoint2d& operator=( const CNastPoint2d &other );

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

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

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

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

    //  Berechnungen
    CNastPoint2d& operator+=( const CNastVector2d &vec );
    CNastPoint2d& operator-=( const CNastVector2d &vec );

    double dist( const CNastPoint2d &other) const;
    double distSquare( const CNastPoint2d &other) const;

    //-------------------------------------------------------------------------
    //                                  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 CNastPoint2d operator+( const CNastPoint2d  &pnt, const CNastVector2d &vec );
inline CNastPoint2d operator+( const CNastVector2d &vec, const CNastPoint2d  &pnt );
inline CNastPoint2d operator-( const CNastPoint2d  &pnt, const CNastVector2d &vec );
inline bool NastIsEqual( const CNastPoint2d &pnt1, const CNastPoint2d &pnt2 );


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

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

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

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

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

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

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

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

//  y-Koordinate lesen
inline double 
CNastPoint2d::y() const
{ 
    return m_y; 
}
 
//  exakter Test auf Gleichheit der Koordinaten
inline bool 
CNastPoint2d::operator==( const CNastPoint2d &other ) const
{ 
    return m_x == other.m_x 
        && m_y == other.m_y; 
}

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

//  Addition eines Vektors
inline CNastPoint2d& 
CNastPoint2d::operator+=( const CNastVector2d &vec )
{ 
    m_x += vec.x(); 
    m_y += vec.y(); 
    return *this; 
}

//  Subdraktion eines Vektors
inline CNastPoint2d& 
CNastPoint2d::operator-=( const CNastVector2d &vec )
{ 
    m_x -= vec.x(); 
    m_y -= vec.y(); 
    return *this; 
}

//  (eukl.) Abstand zu einem anderen Punkt im Quadrat
inline double 
CNastPoint2d::distSquare( const CNastPoint2d &other) const
{ 
    return (other.m_x - m_x) * (other.m_x - m_x) 
         + (other.m_y - m_y) * (other.m_y - m_y);
}

//  (eukl.) Abstand zu einem anderen Punkt
inline double 
CNastPoint2d::dist( const CNastPoint2d &other) const
{ 
    return sqrt( distSquare(other) ); 
}

//  Addition Punkt Vektor
inline CNastPoint2d 
operator+( const CNastPoint2d &pnt, const CNastVector2d &vec )
{
    return CNastPoint2d( pnt.x() + vec.x(),
        		 pnt.y() + vec.y() );
}

//  Addition Vektor Punkt
inline CNastPoint2d 
operator+( const CNastVector2d &vec, const CNastPoint2d &pnt )
{
    return CNastPoint2d( pnt.x() + vec.x(),
        		 pnt.y() + vec.y() );
}

// Subdraktion  Punkt Vektor
inline CNastPoint2d 
operator-( const CNastPoint2d  &pnt, const CNastVector2d &vec )
{
    return CNastPoint2d( pnt.x() - vec.x(),
        		 pnt.y() - vec.y() );
}

// Subdraktion Vektor Punkt
inline CNastPoint2d operator-( const CNastVector2d &vec, const CNastPoint2d  &pnt )
{
    return CNastPoint2d( vec.x() - pnt.x(),
        		 vec.y() - pnt.y() );
}

// Vergleich mit einer Toleranz von NAST_GEOMETRIE_EPS
inline bool 
NastIsEqual( const CNastPoint2d &pnt1, const CNastPoint2d &pnt2 )
{
    return fabs( pnt1.x() - pnt2.x() ) < NAST_GEOMETRIE_EPS
        && fabs( pnt1.x() - pnt2.x() ) < NAST_GEOMETRIE_EPS;
}

#endif // INCLUDE_NASTPOINT2D_H

