#ifndef POINT_3D_IMPL_H
#define POINT_3D_IMPL_H

#ifndef POINT_3D_H
#include "Point_3D.h"
#endif

#ifndef VECTOR_3D_IMPL_H
#include "Vector_3D_impl.h"
#endif


namespace MM
{

class Point_3D_impl : public Point_3D
{
     double x_, y_, z_;

public:
    friend class Vector_3D_impl;

                        Point_3D_impl (double x, double y, double z);
                        Point_3D_impl (Point_3D const & v);
    //explicit            Point_3D_impl (Point_3D_impl const & v);

    /*// Vector protocol {
    virtual int         size () const                   {return 3;}
    virtual void        get (double * values) const;
    virtual void        set (double const* new_values);
    virtual void        add (double const* values);
    virtual void        add_scaled (double scale, double const* values);
    virtual void        multiply (double value);
    virtual Linear_combination_handler
                        linear_combination (double a);
    // Vector protocol }//*/

    virtual void        difference (Point_3D const & p, Vector_3D * result) const;

    virtual double      x() const                       {return x_;}
    virtual double      y() const                       {return y_;}
    virtual double      z() const                       {return z_;}

    virtual void        set_x(double x)                 {x_ = x;}
    virtual void        set_y(double y)                 {y_ = y;}
    virtual void        set_z(double z)                 {z_ = z;}
    virtual void        set_zero()                      {x_=0.;  y_=0.;  z_=0;}
    void                set(double x, double y, double z)   {x_=x; y_=y; z_=z;}

    virtual void        operator += (Vector_3D const & v);
    virtual void        operator -= (Vector_3D const & v);

    virtual void        operator += (Vector_3D_impl const & v);
    virtual void        operator -= (Vector_3D_impl const & v);

    virtual void        add_scaled (double scale,
                                    Vector_3D const& v);

    virtual double      distance   (Point_3D const & p) const;
    virtual double      distance_2 (Point_3D const & p) const;

    virtual double      distance   (Point_3D_impl const & p) const;
    virtual double      distance_2 (Point_3D_impl const & p) const;

    virtual void        affine     (Point_3D const & p, double t);
private:
};

inline void Point_3D_impl::
operator += (Vector_3D_impl const & v)
{
    x_ += v.x_;
    y_ += v.y_;
    z_ += v.z_;
}

inline void Point_3D_impl::
operator -= (Vector_3D_impl const & v)
{
    x_ -= v.x_;
    y_ -= v.y_;
    z_ -= v.z_;
}

inline double Point_3D_impl::
distance_2 (Point_3D_impl const & p) const
{
    double x = x_ - p.x_;
    double y = y_ - p.y_;
    double z = z_ - p.z_;

    return x*x + y*y + z*z;
}

}//MM

#endif //POINT_3D_IMPL_H
