gen_normal.h
Go to the documentation of this file.
00001 /****************************************************************************
00002 * VCGLib                                                            o o     *
00003 * Visual and Computer Graphics Library                            o     o   *
00004 *                                                                _   O  _   *
00005 * Copyright(C) 2004                                                \/)\/    *
00006 * Visual Computing Lab                                            /\/|      *
00007 * ISTI - Italian National Research Council                           |      *
00008 *                                                                    \      *
00009 * All rights reserved.                                                      *
00010 *                                                                           *
00011 * This program is free software; you can redistribute it and/or modify      *
00012 * it under the terms of the GNU General Public License as published by      *
00013 * the Free Software Foundation; either version 2 of the License, or         *
00014 * (at your option) any later version.                                       *
00015 *                                                                           *
00016 * This program is distributed in the hope that it will be useful,           *
00017 * but WITHOUT ANY WARRANTY; without even the implied warranty of            *
00018 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the             *
00019 * GNU General Public License (http://www.gnu.org/licenses/gpl.txt)          *
00020 * for more details.                                                         *
00021 *                                                                           *
00022 ****************************************************************************/
00023 /****************************************************************************
00024   History
00025 
00026 $Log: gen_normal.h,v $
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 // Implementation of the Spherical Fibonacci Point Sets
00074 // according to the description of
00075 // Spherical Fibonacci Mapping
00076 // Benjamin Keinert, Matthias Innmann, Michael Sanger, Marc Stamminger
00077 // TOG 2015
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   // per prima cosa si calcola il volume della spherical cap di angolo AngleRad
00090   ScalarType Height= 1.0 - cos(AngleRad); // height is measured from top...
00091   // Surface is the one of the tangent cylinder
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 // This is an Implementation of the Dave Rusin’s Disco Ball algorithm
00108 // You can spread the points as follows:
00109 // Put  N+1  points on the meridian from north to south poles, equally spaced.
00110 // If you swing this meridian around the sphere, you'll sweep out the entire
00111 // surface; in the process, each of the points will sweep out a circle. You
00112 // can show that the  ith  point will sweep out a circle of radius sin(pi i/N).
00113 // If you space points equally far apart on this circle, keeping the
00114 // displacement roughly the same as on that original meridian, you'll be
00115 // able to fit about  2N sin(pi i/N) points here. This process will put points
00116 // pretty evenly spaced on the sphere; the number of such points is about
00117 //     2+ 2N*Sum(i=1 to N-1) sin(pi i/N).
00118 // The closed form of this summation
00119 //     2.0 - ( (2.0*N * sin (M_PI/N))/(cos(M_PI/N) - 1.0));
00120 static void DiscoBall(int vn, std::vector<Point3<ScalarType > > &NN)
00121 {
00122   // Guess the right N
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     // Z is the north/south axis
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   //Perturb(NN);
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 Trova la normale piu vicina a quella data.
00187 Assume che tutte normale in ingresso sia normalizzata;
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  *  Only the first quadrant is generated and replicated onto the other ones.
00225  *
00226  *   o         lev == 1
00227  *   | \       sz2 = 2^lev = 2
00228  *   o - o     sz = 5 (eg. all the points lie in a 5x5 squre)
00229  *   | \ | \
00230  *   o - o - o
00231  *
00232  *     |
00233  *     V
00234  *
00235  *   o
00236  *   | \       lev == 1
00237  *   o - o     sz2 = 4
00238  *   | \ | \   sz = 9 (eg. all the points lie in a 9x9 squre)
00239  *   o - o - o
00240  *   | \ | \ | \
00241  *   o - o - o - o
00242  *   | \ | \ | \ | \
00243  *   o - o - o - o - o
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


shape_reconstruction
Author(s): Roberto Martín-Martín
autogenerated on Sat Jun 8 2019 18:31:15