function Pnt()
{
    this.a = new Array();
    this.a[ 0 ] = 0.0;
    this.a[ 1 ] = 0.0;
    this.a[ 2 ] = 0.0;
    
    this.Set = function( _x, _y, _z )
    {
        this.a[ 0 ] = _x;
        this.a[ 1 ] = _y;        
        this.a[ 2 ] = _z;                
    }
    this.SetX = function( _t )
    {
        this.a[ 0 ] = _t;
    }
    this.SetY = function( _t )
    {
        this.a[ 1 ] = _t;
    }
    this.SetZ = function( _t )
    {
        this.a[ 2 ] = _t;
    }
    this.GetX = function()
    {
        return this.a[ 0 ];
    }
    this.GetY = function()
    {
        return this.a[ 1 ];
    }
    this.GetZ = function()
    {
        return this.a[ 2 ];
    }
    this.Dot = function( v )
    {
        m = 0;
        for ( var i = 0; i < this.a.length; i++ )
        {
            m = m + this.a[ i ] * v.a[ i ];
        }
        return m;
    }
    this.Cross = function( v )
    {
        p = new Pnt();
        p.SetX( this.GetY() * v.GetZ() - this.GetZ() * v.GetY() );
        p.SetY( -this.GetX() * v.GetZ() + this.GetZ() * v.GetX() );                
        p.SetZ( this.GetX() * v.GetY() - this.GetY() * v.GetX() );        
        return p;
    }
    this.Length = function()
    {
        m = 0;
        for ( var i = 0; i < this.a.length; i++ )
        {
            m = m + this.a[ i ] * this.a[ i ];
        }
        m = Math.sqrt( m ) ;
        return m;
    }
    this.Normalize = function()
    {
        m = this.Length();
        if ( m != 0 )
        {
            for ( var i = 0; i < this.a.length; i++ )
            {        
                this.a[ i ] = this.a[ i ] / m ;
            }
        }
    }
    this.AngleXY = function()
    {
        rad = Math.atan2( this.GetY(), this.GetX() );
        return  rad * 180 / Math.PI ;
    }
    
    this.Angle = function() // alias for AngleXY
    {
        return this.AngleXY();
    }
}

function Ucs()
{
    this.a = new Array();
    this.a[ 0 ] = new Pnt(); // x axis
    this.a[ 1 ] = new Pnt(); // y axis
    this.a[ 2 ] = new Pnt(); // z axis
    this.a[ 3 ] = new Pnt(); // origin

    // setting default values (Identity matrix)
    this.a[ 0 ].SetX( 1.0 ); 
    this.a[ 1 ].SetY( 1.0 );
    this.a[ 2 ].SetZ( 1.0 );
    
    /// Returns the row "i" from the transformation matrix. For example GetRow(0) will return
    /// the X coordinate of X, Y and Z axis. The value of i must range from 0 to 2.
    /// If the value of "i" is out of range, the returned value will be (0,0,0)    
    this.GetRow = function( i ) 
    {
        pRet = new Pnt();
        if( i >= 0 && i < this.a.length - 1 )
            pRet.Set( this.a[ 0 ].a[ i ], this.a[ 1 ].a[ i ], this.a[ 2 ].a[ i ] );
        return pRet;
    }
    /// Returns the column "i" from the transformation matrix.
    /// The value of "i" must range from 0 to 3: 0 = X axis, 1 = Y axis, 2 = Z axis, 3 = Origin.
    /// If the value of "i" is out of range, the returned value will be (0,0,0)
    this.GetCol = function( i ) 
    {
        pRet = new Pnt();
        if( i >= 0 && i < this.a.length )
            pRet.Set( this.a[ i ].a[ 0 ], this.a[ i ].a[ 1 ], this.a[ i ].a[ 2 ] );
        return pRet;
    }
    
    /// Converts the point "p", which is in Ucs coordinates to world coordinates: pWorld = A * pUcs
    this.UcsToWorld = function( p )
    {
        pRet = new Pnt();
        x = this.GetRow( 0 ).Dot( p ) + this.a[ 3 ].GetX();
        y = this.GetRow( 1 ).Dot( p ) + this.a[ 3 ].GetY();
        z = this.GetRow( 2 ).Dot( p ) + this.a[ 3 ].GetZ()        
        pRet.Set( x, y, z ) ;
        return pRet;
    }
    /// Converts the point "p", which is in world coordinates to Ucs coordinates: pUcs = Inv(A) * pWorld    
    this.WorldToUcs = function( p )
    {
        pRet = new Pnt();
        pAux = new Pnt();
        pAux.SetX( p.GetX() - this.a[ 3 ].GetX() );
        pAux.SetY( p.GetY() - this.a[ 3 ].GetY() );
        pAux.SetZ( p.GetZ() - this.a[ 3 ].GetZ() );       
        x = this.GetCol( 0 ).Dot( pAux );
        y = this.GetCol( 1 ).Dot( pAux );
        z = this.GetCol( 2 ).Dot( pAux );
        pRet.Set( x, y, z ) ;
        return pRet;
    }
    
    /// Sets the X axis using a Pnt variable. The axis will be normalized        
    this.SetX = function( x )
    {
        this.a[ 0 ] = x;
        this.a[ 0 ].Normalize() ;
    }
    /// Sets the Y axis using a Pnt variable. The axis will be normalized            
    this.SetY = function( y )
    {
        this.a[ 1 ] = y;
        this.a[ 1 ].Normalize() ;        
    }
    /// Sets the Z axis using a Pnt variable. The axis will be normalized            
    this.SetZ = function( z )
    {
        this.a[ 2 ] = z;
        this.a[ 2 ].Normalize() ;        
    }
    /// Sets the Origin using a Pnt variable.    
    this.SetOrigin = function( o )
    {
        this.a[ 3 ] = o;
    }
    
    /// Sets the X axis by its coordinates. The axis will be normalized    
    this.SetXCoord = function( x, y, z )
    {
        this.a[ 0 ].Set( x, y, z );
        this.a[ 0 ].Normalize() ;
    }
    /// Sets the Y axis by its coordinates. The axis will be normalized    
    this.SetYCoord = function( x, y, z )
    {
        this.a[ 1 ].Set( x, y, z );
        this.a[ 1 ].Normalize() ;        
    }
    /// Sets the Z axis by its coordinates. The axis will be normalized    
    this.SetZCoord = function( x, y, z )
    {
        this.a[ 2 ].Set( x, y, z );
        this.a[ 2 ].Normalize() ;        
    }
    /// Sets the origin    
    this.SetOriginCoord = function( x, y, z )
    {
        this.a[ 3 ].Set( x, y, z );
    }    
    
    /// Returns the X axis
    this.GetX = function()
    {
        return this.GetCol( 0 ) ;
    }
    /// Returns the Y axis    
    this.GetY = function()
    {
        return this.GetCol( 1 ) ;
    }
    /// Returns the Z axis    
    this.GetZ = function()
    {
        return this.GetCol( 2 ) ;
    }
    /// Returns the Origin coordinates    
    this.GetOrigin = function()
    {
        return this.GetCol( 3 ) ;
    }
    
    /// Creates the X axis from Y and Z: X = Y ^ Z
    this.MakeX = function()
    {
        this.SetX( this.GetY().Cross( this.GetZ() ) );
    }
    /// Creates the Y axis from Z and X: Y = Z ^ X    
    this.MakeY = function()
    {
        this.SetY( this.GetZ().Cross( this.GetX() ) );
    }    
    /// Creates the Z axis from X and Y: Z = X ^ Y        
    this.MakeZ = function()
    {
        this.SetZ( this.GetX().Cross( this.GetY() ) );
    }
}