/** \file
 *
 *  Contains the Point3D class definition.
 *
 *  Copyright (c) 2007,2008,2009 MBARI
 *  MBARI Proprietary Information.  All Rights Reserved
 *
 */

#ifndef POINT3D_H_
#define POINT3D_H_

#include "data/I1D.h"
#include "utils/Str.h"

class Matrix3x3;

/**
 *  Wraps three double precision (8-byte) floating point numbers.
 *
 *  The 3 numbers are normally accessed as
 *  \li x, y, and z
 *  \n -OR-
 *  \li u, v, and w
 *
 * \ingroup data
 */
class Point3D: public I1D<double>
{
public:
    /// X positive along the vehicle axis, starting at the nose
    inline void setX( const double x )
    {
        value_[0] = x;
    }
    inline double getX() const
    {
        return value_[0];
    }

    /// Y
    inline void setY( const double y )
    {
        value_[1] = y;
    }
    inline double getY() const
    {
        return value_[1];
    }

    /// Z
    inline void setZ( const double z )
    {
        value_[2] = z;
    }
    inline double getZ() const
    {
        return value_[2];
    }

    /// U -- shares storage with X, alias for dX/dt
    inline void setU( const double u )
    {
        value_[0] = u;
    }
    inline double getU() const
    {
        return value_[0];
    }

    /// V -- shares storage with Y, alias for dY/dt
    inline void setV( const double v )
    {
        value_[1] = v;
    }
    inline double getV() const
    {
        return value_[1];
    }

    /// W -- shares storage with Z, alias for dZ/dt
    inline void setW( const double w )
    {
        value_[2] = w;
    }
    inline double getW() const
    {
        return value_[2];
    }

    /// P -- shares storage with X, alias for angular velocity dRoll/dt
    inline void setP( const double p )
    {
        value_[0] = p;
    }
    inline double getP() const
    {
        return value_[0];
    }

    /// Q -- shares storage with Y, alias for angular velocity dPitch/dt
    inline void setQ( const double q )
    {
        value_[1] = q;
    }
    inline double getQ() const
    {
        return value_[1];
    }

    /// R -- shares storage with Z, alias for angular velocity dYaw/dt
    inline void setR( const double r )
    {
        value_[2] = r;
    }
    inline double getR() const
    {
        return value_[2];
    }

    /// Default constructior
    Point3D( );

    /// Single value constructior
    Point3D( const double& init );

    /// Multi value constructior
    Point3D( const double& x, const double& y, const double& z );

    /// Copy Constructor
    Point3D( const Point3D& value );

    /// Destructor
    virtual ~Point3D()
    {}
    ;

    /// Return a pointer to a new copy
    Point3D* copy() const;

    // as a Str
    virtual Str toString() const;

    Point3D& operator=( const Point3D & rhs );

    Point3D& operator=( const double rhs );

    Point3D& operator+=( const Point3D & rhs );

    Point3D& operator+=( const double rhs );

    Point3D operator+( const Point3D & rhs );

    Point3D& operator-=( const Point3D & rhs );

    Point3D operator-( const Point3D & rhs );

    Point3D& operator-=( const double rhs );

    Point3D& operator*=( const Point3D & rhs );

    Point3D operator*( const double rhs );

    Point3D& operator*=( const double rhs );

    bool operator==( const Point3D & rhs );

    bool operator!=( const Point3D & rhs );

    Point3D& addProduct( Matrix3x3& lhs, Point3D& rhs );

    Point3D& toAbs();

    bool isNan() const;

    double getMagnitude() const;

    double& operator[]( int index );

    const double sum() const;

    const double sumSquared() const;

    /// Implement abstract I1D method
    virtual double* getPtr1d()
    {
        return value_;
    }

    /// Implement abstract I1D method
    virtual int getM() const
    {
        return 3;
    }

protected:

    // The actual data
    double value_[3];
};

#endif /*POINT3D_H_*/
