
//=============================================
// 
// Mercredi 12 decembre 2001
//  
// Arash Habibi
// 
// Sphere.c
//
//============================================


#include <Sphere.h>

//-------------------------------------------
//-------------------------------------------

void S_Check(sphere_t s, char *commentaire)
{
  fprintf(stderr,"%s : check sphere\n", commentaire); 
  V_Check(s.centre, "centre");
  fprintf(stderr,"rayon  : \t%f\n", s.rayon);
}

//-------------------------------------------
//-------------------------------------------

void S_Set(sphere_t *s, vecteur_t centre, double rayon)
{
  s->centre = centre; 
  s->rayon  = rayon; 
}

//-------------------------------------------
// *nb_points est le nombre de points 
// d'intersection. S'il y a un seul point, 
// alors il est dans *M. Dans ce cas, *N 
// contient n'importe quoi. De meme quand
// il n'y a pas de solution, *M et *N 
// contiennent n'importe quoi. 
// Lorsqu'il y a deux points d'intersection
// *M est celui qui aurait le plus petit 
// abscisse si on reperait l'axe par u. 
//-------------------------------------------

void S_IntersectRayon(sphere_t s, rayon_t rayon, int *nb_points, vecteur_t *M, vecteur_t *normal)
{
  double 
    dist,  // la distance du rayon jusqu'au centre de s
    decal, // la distance HM et NH
    tH,    // H = O + tH.u (c'est le parametre de H en somme). 
    tM,tN; // idem pour M et pour N. 

  vecteur_t 
    OC, // le vecteur qui va de O jusqu'au centre de la sphere
    H,  // le projete de A sur la droite (A,u)
    u; // le vecteur unitaire correspondant a la direction du rayon. 

  dist = V_DistPointDroite(s.centre, rayon.origine, rayon.direction);

  if(dist > s.rayon) // aucune intersection
    *nb_points = 0; 

  else 
    {
      OC = V_Difference(s.centre, rayon.origine); 
       u = V_Unitaire(rayon.direction); 
      tH = V_ProduitScalaire(OC,u); 
       H = V_Addition2(rayon.origine, V_Homothetie(tH, u)); 

      if(dist == s.rayon) // une seule intersection. 
	{
	  if(tH>=0.0)
	    {
	      *nb_points = 1; 
	      *M = H; 
	      *normal = V_Unitaire(V_Difference(*M,s.centre)); 
	    }
	  else // la droite intersecte mais pas la demie-droite. 
	    *nb_points = 0; 
	}
      else // if(dist < s.rayon) (deux points d'intersection)
	{
	  decal = sqrt(s.rayon*s.rayon - dist*dist); 

	  tM = tH - decal; 
	  tN = tH + decal; 

	  if((tM<0.0)&&(tN<0.0))
	    *nb_points = 0; 

	  else if(tM<0.0)
	    {
	      *nb_points = 1; 
	      *M = V_Addition2(rayon.origine, V_Homothetie(tN, u)); 
	      *normal = V_Unitaire(V_Difference(*M,s.centre)); 
	    }
	  else // les deux sont positifs
	    {
	      *nb_points = 2; 
	      *M = V_Addition2(rayon.origine, V_Homothetie(tM, u)); 
	      *normal = V_Unitaire(V_Difference(*M,s.centre)); 
	    }
	}
    }
}

//-------------------------------------------
// Idem que la fonction précédente, mais avec
// en plus le deuxieme point d'intersection.
// et en moins la normale. 
//-------------------------------------------

void S_IntersectRayon2(sphere_t s, rayon_t rayon, int *nb_points, vecteur_t *M, vecteur_t *N)
{
  double 
    dist,  // la distance du rayon jusqu'au centre de s
    decal, // la distance HM et NH
    tH,    // H = O + tH.u (c'est le parametre de H en somme). 
    tM,tN; // idem pour M et pour N. 

  vecteur_t 
    OC, // le vecteur qui va de O jusqu'au centre de la sphere
    H,  // le projete de A sur la droite (A,u)
    u; // le vecteur unitaire correspondant a la direction du rayon. 

  dist = V_DistPointDroite(s.centre, rayon.origine, rayon.direction);

  if(dist > s.rayon) // aucune intersection
    *nb_points = 0; 

  else 
    {
      OC = V_Difference(s.centre, rayon.origine); 
      u = V_Unitaire(rayon.direction); 
      tH = V_ProduitScalaire(OC,u); 
      H  = V_Addition2(rayon.origine, V_Homothetie(tH, u)); 

      if(dist == s.rayon) // une seule intersection. 
	{
	  if(tH>=0.0)
	    {
	      *nb_points = 1; 
	      *M = H; 
	    }
	  else // la droite intersecte mais pas la demie-droite. 
	    *nb_points = 0; 
	}
      else // if(dist < s.rayon) (deux points d'intersection)
	{
	  decal = sqrt(s.rayon*s.rayon - dist*dist); 

	  tM = tH - decal; 
	  tN = tH + decal; 

	  if((tM<0.0)&&(tN<0.0))
	    *nb_points = 0; 

	  else if(tM<0.0)
	    {
	      *nb_points = 1; 
	      *M = V_Addition2(rayon.origine, V_Homothetie(tN, u)); 
	    }
	  else // les deux sont positifs
	    {
	      *nb_points = 2; 
	      *M = V_Addition2(rayon.origine, V_Homothetie(tM, u)); 
	      *N = V_Addition2(rayon.origine, V_Homothetie(tN, u)); 
	    }
	}
    }
}



