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

#include "Point2D.h"

#include <math.h>

#include "units/Units.h"
#include "utils/AuvMath.h"

/// Default constructior
Point2D::Point2D( )
{
    setX( __builtin_nan( "" ) );
    setY( __builtin_nan( "" ) );
}

/// Single value constructior
Point2D::Point2D( const double& init )
{
    setX( init );
    setY( init );
}

/// Multi value constructior
Point2D::Point2D( const double& x, const double& y )
{
    setX( x );
    setY( y );
}


/// Copy Constructor
Point2D::Point2D( const Point2D& value )
{
    setX( value.getX() );
    setY( value.getY() );
}

/// Return a pointer to a new copy
Point2D* Point2D::copy() const
{
    return new Point2D( *this );
}

// as a Str
Str Point2D::toString() const
{
    return "[" + Str( value_[0] ) + ","
           + Str( value_[1] ) + "]";
}

Point2D& Point2D::operator=( const Point2D & rhs )
{
    setX( rhs.getX() );
    setY( rhs.getY() );
    return *this;
}

Point2D& Point2D::operator=( const double rhs )
{
    setX( rhs );
    setY( rhs );
    return *this;
}

Point2D& Point2D::operator+=( const Point2D & rhs )
{
    setX( getX() + rhs.getX() );
    setY( getY() + rhs.getY() );
    return *this;
}

Point2D& Point2D::operator+=( const double rhs )
{
    setX( getX() + rhs );
    setY( getY() + rhs );
    return *this;
}

Point2D Point2D::operator+( const Point2D & rhs )
{
    Point2D Point2DSum;
    Point2DSum.setX( getX() + rhs.getX() );
    Point2DSum.setY( getY() + rhs.getY() );
    return Point2DSum;
}

Point2D& Point2D::operator-=( const Point2D & rhs )
{
    setX( getX() - rhs.getX() );
    setY( getY() - rhs.getY() );
    return *this;
}

Point2D Point2D::operator-( const Point2D & rhs )
{
    Point2D Point2DSub;
    Point2DSub.setX( getX() - rhs.getX() );
    Point2DSub.setY( getY() - rhs.getY() );
    return Point2DSub;
}

Point2D& Point2D::operator-=( const double rhs )
{
    setX( getX() - rhs );
    setY( getY() - rhs );
    return *this;
}

Point2D& Point2D::operator*=( const Point2D & rhs )
{
    setX( getX() * rhs.getX() );
    setY( getY() * rhs.getY() );
    return *this;
}

Point2D& Point2D::operator*=( const double rhs )
{
    setX( getX() * rhs );
    setY( getY() * rhs );
    return *this;
}

Point2D Point2D::operator*( const double rhs )
{
    Point2D Point2DMult;
    Point2DMult.setX( getX() * rhs );
    Point2DMult.setY( getY() * rhs );
    return Point2DMult;
}

Point2D& Point2D::toAbs()
{
    setX( fabs( getX() ) );
    setY( fabs( getY() ) );
    return *this;
}

double Point2D::getMagnitude() const
{
    return sqrt( value_[0] * value_[0] + value_[1] * value_[1] );
}

bool Point2D::isNan() const
{
    return isnan( value_[0] ) || isnan( value_[1] );
}

double& Point2D::operator[]( int index )
{
    if( index < 0 || index > 1 )
    {
        index = 0;
    }
    return value_[ index ];
}

const double Point2D::sum() const
{
    return getX() + getY();
}

const double Point2D::sumSquared() const
{
    return getX() * getX() + getY() * getY();
}

const double Point2D::dot( const Point2D& rhs ) const
{
    return getX() * rhs.getY() + getY() * rhs.getX();
}

