www.pudn.com > MyGame.rar > Sphere3.h


/***************************************************************************** 
 * VCGLib                                                                    * 
 *																																					 * 
 * Visual Computing Group                                                o>  * 
 * IEI Institute, CNUCE Institute, CNR Pisa                             <|   * 
 *                                                                      / \  * 
 * Copyright(C) 1999 by Paolo Cignoni, Claudio Rocchini                      * 
 * All rights reserved.                                                      * 
 *																																					 * 
 * Permission  to use, copy, modify, distribute  and sell this  software and * 
 * its documentation for any purpose is hereby granted without fee, provided * 
 * that  the above copyright notice appear  in all copies and that both that * 
 * copyright   notice  and  this  permission  notice  appear  in  supporting * 
 * documentation. the author makes  no representations about the suitability * 
 * of this software for any purpose. It is provided  "as is" without express * 
 * or implied warranty.                                                      * 
 *					                                                         * 
 *****************************************************************************/ 
/**************************************************************************** 
  History 
 
 1999 Nov 02 First Draft. 
 
*/ 
#ifndef __VCGLIB_SPHERE3 
#define __VCGLIB_SPHERE3 
 
#include  
#include  
#include  
 
namespace vcg { 
 
template  class Sphere3 
{ 
  public: 
	Point3 c; 
	FLTYPE r; 
	inline Sphere3( void ){} 
	inline Sphere3(Point3 const & cc,FLTYPE const & rr){c=cc;r=rr;} 
	inline Sphere3(Point3 const & cc){c=cc;r=0;} 
	 
	inline int Circumscribe(Point3 &v0,Point3 &v1,Point3 &v2,Point3 &v3); 
	bool operator < (Sphere3 const & s) const { 
		if(c!=s.c) return c const & p) const { 
		if((c-p).Norm2() < r*r) return true; 
		else return false; 
	} 
 
	inline bool Intersect(Sphere3 const & s) const { 
		if((c-s.c).Norm()< r+s.r) return true; 
		else return false; 
	} 
 
	inline FLTYPE Distance( Sphere3 const & s ) const{ 
			return (c-s.c).Norm()-(r+s.r); 
	} 
	// It is not faster that Distance!!! 
		inline FLTYPE SquaredDistance( Sphere3 const & s ) const{ 
			return (c-s.c).Norm()-(r+s.r)*(c-s.c).Norm()-(r+s.r); 
	} 
 
 
 
/* Sphere3::Inscribe 
Si assume che i punti describano i vertici di un tetraedro ben orientato 
cioe v0 vede v1v2v3 in senso antiorario; 
 
 
La sfera inscritta a un tetraedro verifica che: 
			  Ni*(c-vi) = r 
cioe' il centro e' equidistante dai piani dele facce del tetraedro  
(Ni sono le normali alle facce orientate verso L'INTERNO!!); 
 Si puo' riscrivere come: 
 
    (Ni.x,Ni.y,Ni.z,-1)*(c.x,c.y,c.z,r) = Ni*vi 
 
Che si risolve facilmente con un sistema 4x4;  
Osservando la matrice e sottraendo (N0,-1) a tutti le righe del sistema  
viene la prima riga e l'ultima colonna di zeri e si puo' risolvere  
piu' rapidamente con l'inversa di una 3x3  
*/ 
int Inscribe(Point3 const &v0,Point3 const &v1,Point3 const &v2,Point3 const &v3)  
{ 
  // Egdes (nota basterebbe calcolarne solo 4...) 
  Point3 e10=v1-v0; 
  Point3 e20=v2-v0; 
  Point3 e30=v3-v0; 
  Point3 e21=v2-v1; 
  Point3 e31=v3-v1; 
 
  // Face Normals 
  Point3 n0 = e21 ^ e31; 
  Point3 n1 = e30 ^ e20; 
  Point3 n2 = e10 ^ e30; 
  Point3 n3 = e20 ^ e10; 
 
  // Si dovrebbe controllare che le normali non sono degeneri 
  n0.Normalize();	  
  n1.Normalize();	 
  n2.Normalize();	 
  n3.Normalize();	 
 
  FLTYPE A[3][3]; 
  A[0][0] = n1.v[0]-n0.v[0];  A[0][1] = n1.v[1]-n0.v[1];  A[0][2] = n1.v[2]-n0.v[2]; 
  A[1][0] = n2.v[0]-n0.v[0];  A[1][1] = n2.v[1]-n0.v[1];  A[1][2] = n2.v[2]-n0.v[2]; 
  A[2][0] = n3.v[0]-n0.v[0];  A[2][1] = n3.v[1]-n0.v[1];  A[2][2] = n3.v[2]-n0.v[2]; 
 
  FLTYPE b[3]; 
  b[0] = 0; 
  b[1] = 0; 
  b[2] = -n3.v[0]*e30.v[0]-n3.v[1]*e30.v[1]-n3.v[2]*e30.v[2]; 
 
  FLTYPE sol[3]; 
  if ( !Solve3x3(A,b,sol) ){ 
		r=0; 
		//printf("Sphere3::Inscribe: Unable to solve the system\n") ; 
		return 0; 
  } 
   
  c.v[0] = v3.v[0]+sol[0]; 
  c.v[1] = v3.v[1]+sol[1]; 
  c.v[2] = v3.v[2]+sol[2]; 
  r = n0.v[0]*sol[0]+n0.v[1]*sol[1]+n0.v[2]*sol[2]; 
	if(r<0) r = -r;  
  return 1; 
} 
private: 
 
//-- Nota che questa funzione deve sparire!!!   
int Solve2x2 (FLTYPE A[2][2], FLTYPE b[2], FLTYPE x[2]) 
{ 
    FLTYPE det = A[0][0]*A[1][1]-A[0][1]*A[1][0]; 
    if ( fabs(det) < 1e-06 ) 
        return 0; 
 
    FLTYPE invDet = 1.0/det; 
    x[0] = (A[1][1]*b[0]-A[0][1]*b[1])*invDet; 
    x[1] = (A[0][0]*b[1]-A[1][0]*b[0])*invDet; 
    return 1; 
} 
//-- Nota che questa funzione deve sparire!!!  
int Solve3x3 (FLTYPE A[3][3], FLTYPE b[3], FLTYPE x[3]) 
{ 
    FLTYPE Ainv[3][3]; 
	Ainv[0][0] = A[1][1]*A[2][2]-A[1][2]*A[2][1]; 
	Ainv[0][1] = A[0][2]*A[2][1]-A[0][1]*A[2][2]; 
	Ainv[0][2] = A[0][1]*A[1][2]-A[0][2]*A[1][1]; 
	Ainv[1][0] = A[1][2]*A[2][0]-A[1][0]*A[2][2]; 
	Ainv[1][1] = A[0][0]*A[2][2]-A[0][2]*A[2][0]; 
	Ainv[1][2] = A[0][2]*A[1][0]-A[0][0]*A[1][2]; 
	Ainv[2][0] = A[1][0]*A[2][1]-A[1][1]*A[2][0]; 
	Ainv[2][1] = A[0][1]*A[2][0]-A[0][0]*A[2][1]; 
	Ainv[2][2] = A[0][0]*A[1][1]-A[0][1]*A[1][0]; 
	FLTYPE dDet = A[0][0]*Ainv[0][0]+A[0][1]*Ainv[1][0]+A[0][2]*Ainv[2][0]; 
	if ( fabs(dDet) < 1e-06 ) 
		return 0; 
 
	FLTYPE dInvdet = 1.0/dDet; 
    int row, col; 
	for (row = 0; row < 3; row++) 
    { 
		for (col = 0; col < 3; col++) 
        { 
			Ainv[row][col] *= dInvdet; 
        } 
    } 
 
    for (row = 0; row < 3; row++) 
    { 
        x[row] = 0.0; 
        for (col = 0; col < 3; col++) 
        { 
            x[row] += Ainv[row][col]*b[col]; 
        } 
    } 
	return 1; 
} 
 
 
}; // End Class 
 
 
/** Algorithms Working with spheres and points */ 
 
template  
inline FLTYPE Distance( Sphere3 const & s,Point3 const & p ){ 
    return Norm(s.c-p)-s.r; 
} 
template  
inline FLTYPE SquaredDistance( Sphere3 const & s,Point3 const & p ){ 
    return SquaredNorm(s.c-p)-s.r*s.r; 
} 
 
template  
inline FLTYPE Distance( Sphere3 const & s1,Sphere3 const & s2 ){ 
    return Norm(s1.c-s2.c)-(s1.r+s2.r); 
} 
template  
inline FLTYPE SquaredDistance( Sphere3 const & s,Sphere3 const & p ){ 
    return Norm(s1.c-s2.c)-(s1.r+s2.r)*Norm(s1.c-s2.c)-(s1.r+s2.r); 
} 
 
 
 
/** Algorithms Returning Spheres */ 
 
template  
inline Sphere3 MinSphere2 (Point3 const &p0, Point3 const &p1) 
{ 
    Sphere3 minimal; 
 
    minimal.c.v[0] = 0.5*(p0.v[0]+p1.v[0]); 
    minimal.c.v[1] = 0.5*(p0.v[1]+p1.v[1]); 
    minimal.c.v[2] = 0.5*(p0.v[2]+p1.v[2]); 
    double dx = p1.v[0]-p0.v[0]; 
    double dy = p1.v[1]-p0.v[1]; 
    double dz = p1.v[2]-p0.v[2]; 
    minimal.r = 0.5*vcg::sqrt(dx*dx+dy*dy+dz*dz); 
 
    return minimal; 
} 
 
template  
inline Sphere3 MinSphere2 (Point3 const &p0, Point3 const &p1, Point3 const &p2) 
{ 
    // Compute the circle (in 3D) containing p0, p1, and p2.  The center in 
	// barycentric coordinates is C = u0*P0+u1*P1+u2*P2 where u0+u1+u2=1, 
    // 0 < u0 < 1, 0 < u1 < 1, and 0 < u2 < 1.  The center is equidistant 
    // from the three points, so |C-p0| = |C-p1| = |C-p2| = R where R is the 
    // radius of the circle. 
	// 
	// From these conditions, 
	//   C-p0 = u0*A + u1*B - A 
	//   C-p1 = u0*A + u1*B - B 
	//   C-p2 = u0*A + u1*B 
	// where A = P0-P2 and B = P1-P2, which leads to 
	//   r^2 = |u0*A+u1*B|^2 - 2*Dot(A,u0*A+u1*B) + |A|^2 
	//   r^2 = |u0*A+u1*B|^2 - 2*Dot(B,u0*A+u1*B) + |B|^2 
	//   r^2 = |u0*A+u1*B|^2 
	// Subtracting the last equation from the first two and writing 
	// the equations as a linear system, 
	// 
	// +-                 -++   -+       +-        -+ 
	// | Dot(A,A) Dot(A,B) || u0 | = 0.5 | Dot(A,A) | 
	// | Dot(A,B) Dot(B,B) || u1 |       | Dot(B,B) | 
	// +-                 -++   -+       +-        -+ 
	// 
	// The following code solves this system for u0 and u1, then 
	// evaluates the third equation in r^2 to obtain r. 
 
  Sphere3 minimal; 
 
	Point3 A( p0.v[0]-p2.v[0], p0.v[1]-p2.v[1], p0.v[2]-p2.v[2]); 
	Point3 B(p1.v[0]-p2.v[0], p1.v[1]-p2.v[1], p1.v[2]-p2.v[2]); 
	double AA = A.v[0]*A.v[0]+A.v[1]*A.v[1]+A.v[2]*A.v[2]; 
	FLTYPE AB = A.v[0]*B.v[0]+A.v[1]*B.v[1]+A.v[2]*B.v[2]; 
	FLTYPE BB = B.v[0]*B.v[0]+B.v[1]*B.v[1]+B.v[2]*B.v[2]; 
    FLTYPE det = AA*BB-AB*AB; 
 
    if ( fabs(det) > 1e-06 ) 
    { 
        FLTYPE halfInvDet = 0.5f/(AA*BB-AB*AB); 
        FLTYPE u0 = halfInvDet*BB*(AA-AB); 
        FLTYPE u1 = halfInvDet*AA*(BB-AB); 
        FLTYPE u2 = 1.0f-u0-u1; 
        Point3 tmp(u0*A.v[0]+u1*B.v[0], u0*A.v[1]+u1*B.v[1], u0*A.v[2]+u1*B.v[2] ); 
        minimal.c.v[0] = u0*p0.v[0]+u1*p1.v[0]+u2*p2.v[0]; 
        minimal.c.v[1] = u0*p0.v[1]+u1*p1.v[1]+u2*p2.v[1]; 
        minimal.c.v[2] = u0*p0.v[2]+u1*p1.v[2]+u2*p2.v[2]; 
        minimal.r = sqrt(tmp.v[0]*tmp.v[0]+tmp.v[1]*tmp.v[1]+tmp.v[2]*tmp.v[2]); 
    } 
    else 
    { 
        minimal.c.v[0] = DBL_MAX; 
        minimal.c.v[1] = DBL_MAX; 
        minimal.c.v[2] = DBL_MAX; 
        minimal.r = DBL_MAX; 
    } 
 
    return minimal; 
} 
 
 
 
 
typedef Sphere3  Sphere3s; 
typedef Sphere3	  Sphere3i; 
typedef Sphere3  Sphere3f; 
typedef Sphere3 Sphere3d; 
 
} // end namespace 
#endif