00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029 #ifndef __VCG_GEN_NORMAL
00030 #define __VCG_GEN_NORMAL
00031
00032 #include <algorithm>
00033
00034 namespace vcg {
00035
00036 template <class ScalarType>
00037 class GenNormal
00038 {
00039 public:
00040 typedef Point3<ScalarType> Point3x;
00041
00042 static void Random(int vn, std::vector<Point3<ScalarType > > &NN)
00043 {
00044 NN.clear();
00045 while(NN.size()<vn)
00046 {
00047 Point3x pp(((float)rand())/RAND_MAX,
00048 ((float)rand())/RAND_MAX,
00049 ((float)rand())/RAND_MAX);
00050 pp=pp*2.0-Point3x(1,1,1);
00051 if(pp.SquaredNorm()<1)
00052 {
00053 Normalize(pp);
00054 NN.push_back(pp);
00055 }
00056 }
00057 }
00058
00059
00060 static Point3x FibonacciPt(int i, int n)
00061 {
00062 const ScalarType Phi = ScalarType(sqrt(5)*0.5 + 0.5);
00063 const ScalarType phi = 2.0*M_PI* (i/Phi - floor(i/Phi));
00064 ScalarType cosTheta = 1.0 - (2*i + 1.0)/ScalarType(n);
00065 ScalarType sinTheta = 1 - cosTheta*cosTheta;
00066 sinTheta = sqrt(std::min(ScalarType(1),std::max(ScalarType(0),sinTheta)));
00067 return Point3x(
00068 cos(phi)*sinTheta,
00069 sin(phi)*sinTheta,
00070 cosTheta);
00071 }
00072
00073
00074
00075
00076
00077
00078 static void Fibonacci(int n, std::vector<Point3x > &NN)
00079 {
00080 NN.resize(n);
00081 for(int i=0;i<n;++i)
00082 NN[i]=FibonacciPt(i,n);
00083 }
00084
00085 static void UniformCone(int vn, std::vector<Point3<ScalarType > > &NN, ScalarType AngleRad, Point3x dir=Point3x(0,1,0))
00086 {
00087 std::vector<Point3<ScalarType > > NNT;
00088 NN.clear();
00089
00090 ScalarType Height= 1.0 - cos(AngleRad);
00091
00092 ScalarType CapArea = 2.0*M_PI*Height;
00093 ScalarType Ratio = CapArea / (4.0*M_PI );
00094
00095 printf("----------AngleRad %f Angledeg %f ratio %f vn %i vn2 %i \n",AngleRad,math::ToDeg(AngleRad),Ratio,vn,int(vn/Ratio));
00096 Fibonacci(vn/Ratio,NNT);
00097 printf("asked %i got %i (expecting %i instead of %i)\n", int(vn/Ratio), NNT.size(), int(NNT.size()*Ratio), vn);
00098 typename std::vector<Point3<ScalarType> >::iterator vi;
00099
00100 ScalarType cosAngle = cos(AngleRad);
00101 for(vi=NNT.begin();vi!=NNT.end();++vi)
00102 {
00103 if(dir.dot(*vi) >= cosAngle) NN.push_back(*vi);
00104 }
00105 }
00106
00107
00108
00109
00110
00111
00112
00113
00114
00115
00116
00117
00118
00119
00120 static void DiscoBall(int vn, std::vector<Point3<ScalarType > > &NN)
00121 {
00122
00123 ScalarType N=0;
00124
00125 for(N=1;N<vn;++N)
00126 {
00127 ScalarType expectedPoints = 2.0 - ( (2.0*N * sin (M_PI/N))/(cos(M_PI/N) - 1.0));
00128 if(expectedPoints >= vn) break;
00129 }
00130
00131 ScalarType VerticalAngle = M_PI / N;
00132 NN.push_back(Point3<ScalarType>(0,0,1.0));
00133 for (int i =1; i<N; ++i)
00134 {
00135
00136 ScalarType HorizRadius = sin(i*VerticalAngle);
00137 ScalarType CircleLength = 2.0 * M_PI * HorizRadius;
00138 ScalarType Z = cos(i*VerticalAngle);
00139 ScalarType PointNumPerCircle = floor( CircleLength / VerticalAngle);
00140 ScalarType HorizontalAngle = 2.0*M_PI/PointNumPerCircle;
00141 for(ScalarType j=0;j<PointNumPerCircle;++j)
00142 {
00143 ScalarType X = cos(j*HorizontalAngle)*HorizRadius;
00144 ScalarType Y = sin(j*HorizontalAngle)*HorizRadius;
00145 NN.push_back(Point3<ScalarType>(X,Y,Z));
00146 }
00147 }
00148 NN.push_back(Point3<ScalarType>(0,0,-1.0));
00149 }
00150
00151 static void RecursiveOctahedron(int vn, std::vector<Point3<ScalarType > > &NN)
00152 {
00153 OctaLevel pp;
00154
00155 int ll=10;
00156 while(pow(4.0f,ll)+2>vn) ll--;
00157
00158 pp.Init(ll);
00159 sort(pp.v.begin(),pp.v.end());
00160 int newsize = unique(pp.v.begin(),pp.v.end())-pp.v.begin();
00161 pp.v.resize(newsize);
00162
00163 NN=pp.v;
00164
00165 }
00166
00167 static void Perturb(std::vector<Point3<ScalarType > > &NN)
00168 {
00169 float width=0.2f/sqrt(float(NN.size()));
00170
00171 typename std::vector<Point3<ScalarType> >::iterator vi;
00172 for(vi=NN.begin(); vi!=NN.end();++vi)
00173 {
00174 Point3x pp(((float)rand())/RAND_MAX,
00175 ((float)rand())/RAND_MAX,
00176 ((float)rand())/RAND_MAX);
00177 pp=pp*2.0-Point3x(1,1,1);
00178 pp*=width;
00179 (*vi)+=pp;
00180 (*vi).Normalize();
00181 }
00182
00183 }
00184
00185
00186
00187
00188
00189 static int BestMatchingNormal(const Point3x &n, std::vector<Point3x> &nv)
00190 {
00191 int ret=-1;
00192 ScalarType bestang=-1;
00193 ScalarType cosang;
00194 typename std::vector<Point3x>::iterator ni;
00195 for(ni=nv.begin();ni!=nv.end();++ni)
00196 {
00197 cosang=(*ni).dot(n);
00198 if(cosang>bestang) {
00199 bestang=cosang;
00200 ret=ni-nv.begin();
00201 }
00202 }
00203 assert(ret>=0 && ret <int(nv.size()));
00204 return ret;
00205 }
00206
00207
00208 private :
00209 class OctaLevel
00210 {
00211 public:
00212 std::vector<Point3x> v;
00213 int level;
00214 int sz;
00215 int sz2;
00216
00217 Point3x &Val(int i, int j) {
00218
00219 assert(i>=-sz2 && i<=sz2);
00220 assert(j>=-sz2 && j<=sz2);
00221 return v[i+sz2 +(j+sz2)*sz];
00222 }
00223
00224
00225
00226
00227
00228
00229
00230
00231
00232
00233
00234
00235
00236
00237
00238
00239
00240
00241
00242
00243
00244
00245
00246
00247 void Init(int lev)
00248 {
00249 sz2=pow(2.0f,lev);
00250 sz=sz2*2+1;
00251 v.resize(sz*sz,Point3x(0,0,0));
00252 if(lev==0)
00253 {
00254 Val( 0,0)=Point3x( 0, 0, 1);
00255 Val( 1,0)=Point3x( 1, 0, 0);
00256 Val( 0,1)=Point3x( 0, 1, 0);
00257 }
00258 else
00259 {
00260 OctaLevel tmp;
00261 tmp.Init(lev-1);
00262 int i,j;
00263 for(i=0;i<=sz2;++i)
00264 for(j=0;j<=(sz2-i);++j)
00265 {
00266 if((i%2)==0 && (j%2)==0)
00267 Val(i,j)=tmp.Val(i/2,j/2);
00268 if((i%2)!=0 && (j%2)==0)
00269 Val(i,j)=(tmp.Val((i-1)/2,j/2)+tmp.Val((i+1)/2,j/2))/2.0;
00270 if((i%2)==0 && (j%2)!=0)
00271 Val(i,j)=(tmp.Val(i/2,(j-1)/2)+tmp.Val(i/2,(j+1)/2))/2.0;
00272 if((i%2)!=0 && (j%2)!=0)
00273 Val(i,j)=(tmp.Val((i-1)/2,(j+1)/2)+tmp.Val((i+1)/2,(j-1)/2))/2.0;
00274
00275 Val( sz2-j, sz2-i)[0] = Val(i,j)[0]; Val( sz2-j, sz2-i)[1] = Val(i,j)[1]; Val( sz2-j, sz2-i)[2] = -Val(i,j)[2];
00276 Val(-sz2+j, sz2-i)[0] =-Val(i,j)[0]; Val(-sz2+j, sz2-i)[1] = Val(i,j)[1]; Val(-sz2+j, sz2-i)[2] = -Val(i,j)[2];
00277 Val( sz2-j,-sz2+i)[0] = Val(i,j)[0]; Val( sz2-j,-sz2+i)[1] =-Val(i,j)[1]; Val( sz2-j,-sz2+i)[2] = -Val(i,j)[2];
00278 Val(-sz2+j,-sz2+i)[0] =-Val(i,j)[0]; Val(-sz2+j,-sz2+i)[1] =-Val(i,j)[1]; Val(-sz2+j,-sz2+i)[2] = -Val(i,j)[2];
00279
00280 Val(-i,-j)[0] = -Val(i,j)[0]; Val(-i,-j)[1] = -Val(i,j)[1]; Val(-i,-j)[2] = Val(i,j)[2];
00281 Val( i,-j)[0] = Val(i,j)[0]; Val( i,-j)[1] = -Val(i,j)[1]; Val( i,-j)[2] = Val(i,j)[2];
00282 Val(-i, j)[0] = -Val(i,j)[0]; Val(-i, j)[1] = Val(i,j)[1]; Val(-i, j)[2] = Val(i,j)[2];
00283 }
00284
00285 typename std::vector<Point3<ScalarType> >::iterator vi;
00286 for(vi=v.begin(); vi!=v.end();++vi)
00287 (*vi).Normalize();
00288 }
00289 }
00290 };
00291 };
00292 }
00293 #endif