00001 #ifndef __VCGTEST_IMPLICITSPHERE 00002 #define __VCGTEST_IMPLICITSPHERE 00003 00004 class ImplicitSphere 00005 { 00006 public: 00007 ImplicitSphere() 00008 { 00009 _center.SetZero(); 00010 _radius = _sqr_radius = 0.0; 00011 }; 00012 00013 ImplicitSphere(vcg::Point3f ¢er, float radius) 00014 { 00015 _center = center; 00016 _radius = radius; 00017 _sqr_radius = radius*radius; 00018 }; 00019 00020 ImplicitSphere(const ImplicitSphere &sphere) 00021 { 00022 _center = sphere._center; 00023 _radius = sphere._radius; 00024 _sqr_radius = sphere._sqr_radius; 00025 }; 00026 00027 ImplicitSphere& operator=(const ImplicitSphere &sphere) 00028 { 00029 if (this != &sphere) 00030 { 00031 _center = sphere._center; 00032 _radius = sphere._radius; 00033 _sqr_radius = sphere._sqr_radius; 00034 } 00035 return *this; 00036 }; 00037 00038 ~ImplicitSphere() 00039 {}; 00040 00041 bool operator!=(const ImplicitSphere &sphere) 00042 { 00043 return (sphere._center!=_center && sphere._radius!=_radius); 00044 }; 00045 00046 00047 float V(int x, int y, int z) const 00048 { 00049 vcg::Point3f point((float) x, (float) y, (float) z); 00050 return (_center-point).Norm() - _radius; 00051 }; 00052 00053 bool DirectedDistance(const vcg::Point3i &p1, const vcg::Point3i &p2, vcg::Point3f &v, vcg::Point3f &n, float &dist) 00054 { 00055 vcg::Point3f orig, dir; 00056 orig.X() = (float) p1.X(); 00057 orig.Y() = (float) p1.Y(); 00058 orig.Z() = (float) p1.Z(); 00059 dir.X() = (float) p2.X()-p1.X(); 00060 dir.Y() = (float) p2.Y()-p1.Y(); 00061 dir.Z() = (float) p2.Z()-p1.Z(); 00062 00063 double a = dir.SquaredNorm(); 00064 double b = 2.0*(dir*(orig - _center)); 00065 double c = (orig - _center).SquaredNorm() - _radius*_radius; 00066 double d = b*b - 4.0*a*c; 00067 00068 if (d >= 0) 00069 { 00070 d = sqrt(d); 00071 00072 double t1 = (-b-d) / (2.0*a); 00073 double t2 = (-b+d) / (2.0*a); 00074 double t = 1.00001; 00075 if (t1 >= 0.0 && t1 < t) t = t1; 00076 if (t2 >= 0.0 && t2 < t) t = t2; 00077 00078 if (t != 1.00001) 00079 { 00080 v = (vcg::Point3f) (orig + dir*((float)t)); 00081 n = (vcg::Point3f) ((v - _center) / _radius); 00082 dist = (float) ((dir*n) < 0.0) ? dir.Norm()*t : -dir.Norm()*t; 00083 return true; 00084 } 00085 } 00086 return false; 00087 }; 00088 00089 private: 00090 vcg::Point3f _center; 00091 float _radius; 00092 float _sqr_radius; 00093 }; 00094 00095 #endif // __VCGTEST_IMPLICITSPHERE