///////////////////////////////////////////////////////////////////////////////
// Copyright (c) 1995-1996 Virtual Design All Rights Reserved.
//
// Permission to use,  copy,  modify,  and  distribute  this  software and its 
// documentation for NON-COMMERCIAL purposes and without fee is hereby granted. 
//
// VIRTUAL DESIGN MAKES NO REPRESENTATIONS OR WARRANTIES ABOUT THE SUITABILITY
// OF THE SOFTWARE, EITHER EXPRESS  OR  IMPLIED,  INCLUDING BUT NOT LIMITED TO
// THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE,
// OR NON-INFRINGEMENT. VIRTUAL DESIGN SHALL  NOT  BE LIABLE FOR ANY DAMAGES
// SUFFERED BY  LICENSEE AS A RESULT OF USING,  MODIFYING OR DISTRIBUTING THIS
// SOFTWARE OR ITS DERIVATIVES.
//
// THIS SOFTWARE  IS   NOT  DESIGNED  OR  INTENDED FOR USE OR RESALE AS ONLINE
// OR NOT ONLINE CONTROL  EQUIPMENT IN HAZARDOUS  ENVIRONMENTS REQUIRING  FAIL-
// SAFE PERFORMANCE,  SUCH  AS  IN   THE   OPERATION   OF  NUCLEAR  FACILITIES,
// AIRCRAFT   NAVIGATION  OR  COMMUNICATION  SYSTEMS,  AIR   TRAFFIC   CONTROL,
// DIRECT LIFE  SUPPORT  MACHINES, OR WEAPONS SYSTEMS, IN  WHICH  THE  FAILURE
// OF  THE SOFTWARE COULD  LEAD DIRECTLY  TO DEATH, PERSONAL INJURY, OR SEVERE
// PHYSICAL OR ENVIRONMENTAL  DAMAGE ("HIGH RISK ACTIVITIES").  VIRTUAL DESIGN
// SPECIFICALLY DISCLAIMS  ANY EXPRESS OR IMPLIED WARRANTY OF FITNESS FOR HIGH
// RISK ACTIVITIES.
///////////////////////////////////////////////////////////////////////////////
/**
 * Classe des vecteurs.
 * @author Guillaume Pelletier.
 * @version 1.0
 */

 class Vecteur3DH
 {
 public Sommet3DH m_a, m_b;

 public Vecteur3DH (){}

 public Vecteur3DH ( Sommet3DH p_a, Sommet3DH p_b)
   {
   m_a = p_a ;
   m_b = p_b ;
   }

 public Vecteur3DH ( Vecteur3DH p_v)
   {
   this(p_v.m_a,p_v.m_b);
   }

 /**
  * Angle vertical theta du vecteur ( par rapport au plans xoy ).
  * Exprimé en Radian.
  */
 public float angle_ver()
  {
  float  l_n = norme() ;
  if ( l_n == 0 ) return 0.0f ;
  return (float)Math.asin(compoz()/l_n) ;
  }

 /**
  * cos et sin de l'angle vertical theta du vecteur.
  */
 public void cos_sin_angle_ver ( float p_cos , float p_sin )
  {
  float  l_n = norme(),
         l_dx = compox(),
         l_dy = compoy(),
         l_nxy = (float) Math.sqrt( l_dy*l_dy + l_dx*l_dx ) ;

  if ( l_n == 0 ) p_cos = p_sin = 0 ;
  else
   {
   p_cos = l_nxy / l_n ;
   p_sin = compoz() / l_n ;
   }
  }

 /**
  * cos de l'angle vertical theta du vecteur.
  */
 public float cos_angle_ver ()
  {
  float  l_n = norme(),
         l_dx = compox(),
         l_dy = compoy(),
         l_nxy = (float) Math.sqrt( l_dy*l_dy + l_dx*l_dx ) ;

  if ( l_n == 0 ) return 0.0f ;
  else
    return l_nxy / l_n ;
  }

 /**
  * sin de l'angle vertical theta du vecteur.
  */
 public float sin_angle_ver ()
  {
  float  l_n = norme(),
         l_dx = compox(),
         l_dy = compoy(),
         l_nxy = (float) Math.sqrt( l_dy*l_dy + l_dx*l_dx ) ;

  if ( l_n == 0 ) return 0.0f ;
  else
    return  compoz() / l_n ;
  }


 /**
  * Angle horizontal du vecteur ( sur le plans xoy à partir de l'axe ox dans
  * le sens trigonometrique pour un repère direct ).
  * Exprimé en Radian.
  */
 public float  angle_hor ()
  {
  return (float)Math.atan2(compoy(),compox()) ;
  }

 /**
  * cos et sin de l'angle vertical theta du vecteur.
  * Nb - le cas particulier où la visée est verticale rend la projection sur
  *      le plans XOY égale à un point. Dans ce cas, il n'y à pas de calcul
  *      d'angle possible. On suppose donc phi=0;
  */
 public void cos_sin_angle_hor(float p_cos, float p_sin)
  {
  float  l_n = norme(),
         l_dx = compox(),
         l_dy = compoy(),
         l_nxy = (float)Math.sqrt( l_dy*l_dy + l_dx*l_dx ) ;

  if ( l_n == 0 )
     {
     p_cos = p_sin = 0 ;
     return ;
     }

  if ( l_nxy == 0 )
     {
     p_cos = 1 ;
     p_sin = 0 ;
     return ;
     }

  p_cos = l_dx / l_nxy ;
  p_sin = l_dy / l_nxy ;
  }

 public float cos_angle_hor()
  {
  float  l_n = norme(),
         l_dx = compox(),
         l_dy = compoy(),
         l_nxy = (float)Math.sqrt( l_dy*l_dy + l_dx*l_dx ) ;

  if ( l_n == 0 ) return 0.0f;

  if ( l_nxy == 0 ) return 1.0f ;

  return  l_dx / l_nxy ;
  }

 public float sin_angle_hor()
  {
  float  l_n = norme(),
         l_dx = compox(),
         l_dy = compoy(),
         l_nxy = (float)Math.sqrt( l_dy*l_dy + l_dx*l_dx ) ;

  if ( l_n == 0 || l_nxy==0 ) return 0.0f ;

  return l_dy / l_nxy ;
  }


 /**
  * Norme du vecteur.
  */
 public float  norme()
  {
  float l_dx = compox(),
        l_dy = compoy(),
        l_dz = compoz();

  return (float) Math.sqrt( l_dx*l_dx + l_dy*l_dy + l_dz*l_dz ) ;
  }

 /**
  * Composante X du vecteur.
  */
 public float  compox()
  {
  return m_b.m_x - m_a.m_x ;
  }

 /**
  * Composante Y du vecteur.
  */
 public float  compoy()
  {
  return m_b.m_y - m_a.m_y ;
  }

 /**
  * Composante Z du vecteur.
  */
 public float  compoz()
  {
  return m_b.m_z - m_a.m_z ;
  }

 /**
  * normalisation du vecteur.
  */
 public void normalisation ()
  {
  float l_n = norme(),
        l_dx = compox()/l_n,
        l_dy = compoy()/l_n,
        l_dz = compoz()/l_n;

  m_b.m_x = m_a.m_x + l_dx ;
  m_b.m_y = m_a.m_y + l_dy ;
  m_b.m_z = m_a.m_z + l_dz ;
  }

 /**
  * produit scalaire du vecteur par un autre vecteur.
  */
 public float produit_scalaire ( Vecteur3DH p_v )
  {
  float l_scal ;
  l_scal = compox()*p_v.compox() +
           compoy()*p_v.compoy() +
           compoz()*p_v.compoz() ;
  return l_scal;
  }

  /**
  * produit vectoriel du vecteur par un autre vecteur.
  * Application à l'obtention du vecteur normal 1.
  */
 public void vecteur_normal( Vecteur3DH p_v, Sommet3DH p_result )
  {
  float l_adx = compox(),
        l_ady = compoy(),
        l_adz = compoz(),
        l_bdx = p_v.compox(),
        l_bdy = p_v.compoy(),
        l_bdz = p_v.compoz();

  p_result.m_x = l_ady * l_bdz - l_adz * l_bdy ;
  p_result.m_y = l_adz * l_bdx - l_adx * l_bdz ;
  p_result.m_z = l_adx * l_bdy - l_ady * l_bdx ;
  }

  /**
  * produit vectoriel du vecteur par un autre vecteur.
  * Application à l'obtention du vecteur normal 2.
  */
 public void  vecteur_normal ( Vecteur3DH p_v, Vecteur3DH p_vf)
  {
  p_vf.m_a = m_a ;
  vecteur_normal( p_v, p_vf.m_b ) ;
  }

 }

