//-- FILE:   coordinates.h
//-- CODER:  KUBO Takuya (kubo@ees.hokudai.ac.jp)
//-- 
//-- (C)opyright 1999 KUBO Takuya (kubo@ees.hokudai.ac.jp).
//--    All rights are reserved.
//--    Do not modify without amending copyright,
//--    distribute freely but retain this paragraph.
//-- 
//-- CHANGE: Sat Aug 28 17:00:36 1999
//   MODIFY: Sat Aug 21 19:26:47 1999

#if !defined(___Class_Coordinates)
#define ___Class_Coordinates

#include        <iostream>
#include        <vector>

using namespace std;

class Xyz;
class Polar;

ostream& operator<<(ostream&, const Xyz& );
ostream& operator<<(ostream&, const Polar& );
Xyz operator+( const Xyz&, const Xyz& );
Xyz operator-( const Xyz&, const Xyz& );
Polar operator+( const Polar&, const Polar& );
Polar operator-( const Polar&, const Polar& );

//-----------------------------------------------
//[ Xyz coordinates ]
//
//        z+|  /y+
//          | /
//    x-    |/
//    ------+------
//         /|    x+
//        / |
//     y-/  |z-

class Xyz {
        friend ostream& operator<<( ostream&, const Xyz& );
        friend Xyz operator+( const Xyz& v0, const Xyz& v1 );
        friend Xyz operator-( const Xyz& v0, const Xyz& v1 );

private:
        double  x, y, z;

public:
        Xyz( void ) { x = y = z = 0.0; }
        Xyz( double x0, double y0, double z0 );
        Xyz( const Xyz& xyz0 );
        ~Xyz( void ) { ; }

        void    Input( double x0, double y0, double z0 );
        void    Scaling( double, double, double );
        double  Scalar( void );

        double  X( void ) const { return x; }
        double  Y( void ) const { return y; }
        double  Z( void ) const { return z; }

        Xyz&    operator+=( const Xyz& );
        Xyz&    operator-=( const Xyz& );
        Xyz&    operator+=( const Polar& );
        Xyz&    operator-=( const Polar& );
};


//-----------------------------------------------
//[ Polar coordinates ]
//
//          |y+                  z+|  /
//          |                      | /
//    x-    |    x+          x-y   |/)phi
//    ------+------          ------+------
//          |\) theta              |
//          | \                    |
//        y-|  \                 z-|

class Polar {
        friend ostream& operator<<( ostream&, const Polar& );
        friend Polar operator+( const Polar& v0, const Polar& v1 );
        friend Polar operator-( const Polar& v0, const Polar& v1 );

private:
        double  theta, phi, radius;
        double  px, py, pz;
        vector<Xyz>     components;

public:
        Polar( void );
        Polar( double theta0, double phi0, double radius0 );
        Polar( Xyz );
        Polar( const Polar& );
        ~Polar( void ) { ; }

        void    Input( double theta0, double phi0, double radius0 );
        void    Input( Xyz xyz );
        Xyz     ToXyz( void ) { return Xyz( px, py, pz ); };

        void    PlusTheta( double theta0 );
        void    PlusPhi( double phi0 );
        void    Multiple( double multiplier );
        void    ChangeRadius( double radius0 );

        // Plane P : its normal vector is '*this'
        // v1 : on (theta, 0 <= phi < 2 Pi ) plane ( _|_ x-y)
        // v2 : on (0 <= theta < 2 Pi, phi = 0 ) plane ( == x-y)
        // ---------------------
        // |P             v1   |     *this 
        // |              A    |     A   .(`Rotated' vector)
        // |        v'o   |    |     |  /
        // |           \  |    |     | /
        // |            \ |    |     |/) phi_dash
        // |  theta_dash(\|    |     +------o v'
        // | v2<----------+    |       v1-v2 plane
        // ---------------------
        void    Rotate( Polar* branch_angle );

        double  Px( void ) const { return px; }
        double  Py( void ) const { return py; }
        double  Pz( void ) const { return pz; }
        double  Scalar( void ) const { return radius; }

        vector<Xyz>*    Components( void ); // Scaled { 1, 1, 1 }
        vector<Xyz>*    Components( Xyz scale );

        Polar&  operator+=( const Polar& );
        Polar&  operator-=( const Polar& );
};

#endif