From e6e7999c6c2afb2472aae342c987a0801bd1f7d0 Mon Sep 17 00:00:00 2001 From: cignoni Date: Tue, 17 Jun 2014 14:51:20 +0000 Subject: [PATCH] =?UTF-8?q?Added=20an=20implementation=20of=20the=20Dave?= =?UTF-8?q?=20Rusin=E2=80=99s=20Disco=20Ball=20algorithm=20for=20the=20gen?= =?UTF-8?q?eration=20of=20regular=20points=20on=20a=20sphere.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- vcg/math/gen_normal.h | 103 ++++++++++++++++++++++++++++++------------ 1 file changed, 74 insertions(+), 29 deletions(-) diff --git a/vcg/math/gen_normal.h b/vcg/math/gen_normal.h index 497910ca..757d47a6 100644 --- a/vcg/math/gen_normal.h +++ b/vcg/math/gen_normal.h @@ -8,7 +8,7 @@ * \ * * All rights reserved. * * * -* This program is free software; you can redistribute it and/or modify * +* This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * @@ -34,7 +34,7 @@ $Log: gen_normal.h,v $ namespace vcg { template -class GenNormal +class GenNormal { public: typedef Point3 Point3x; @@ -45,8 +45,8 @@ static void Random(int vn, std::vector > &NN) while(NN.size() > &NN, ScalarTyp Uniform(vn/Ratio,NNT); printf("asked %i got %i (expecting %i instead of %i)\n", int(vn/Ratio), NNT.size(), int(NNT.size()*Ratio), vn); typename std::vector >::iterator vi; - + ScalarType DotProd = cos(AngleRad); for(vi=NNT.begin();vi!=NNT.end();++vi) { @@ -77,6 +77,51 @@ static void UniformCone(int vn, std::vector > &NN, ScalarTyp } } +// This is an Implementation of the Dave Rusin’s Disco Ball algorithm +// You can spread the points as follows: +// Put N+1 points on the meridian from north to south poles, equally spaced. +// If you swing this meridian around the sphere, you'll sweep out the entire +// surface; in the process, each of the points will sweep out a circle. You +// can show that the ith point will sweep out a circle of radius sin(pi i/N). +// If you space points equally far apart on this circle, keeping the +// displacement roughly the same as on that original meridian, you'll be +// able to fit about 2N sin(pi i/N) points here. This process will put points +// pretty evenly spaced on the sphere; the number of such points is about +// 2+ 2N*Sum(i=1 to N-1) sin(pi i/N). +// The closed form of this summation +// 2.0 - ( (2.0*N * sin (M_PI/N))/(cos(M_PI/N) - 1.0)); +static void Regular(int vn, std::vector > &NN) +{ + // Guess the right N + ScalarType N=0; + + for(N=1;N %f",N,expectedPoints); + if(expectedPoints >= vn) break; + } + + + ScalarType VerticalAngle = M_PI / N; + NN.push_back(Point3(0,0,1.0)); + for (int i =1; i(X,Y,Z)); + } + } + NN.push_back(Point3(0,0,-1.0)); +} static void Uniform(int vn, std::vector > &NN) { @@ -99,11 +144,11 @@ static void Perturb(std::vector > &NN) float width=0.2f/sqrt(float(NN.size())); typename std::vector >::iterator vi; - for(vi=NN.begin(); vi!=NN.end();++vi) + for(vi=NN.begin(); vi!=NN.end();++vi) { Point3x pp(((float)rand())/RAND_MAX, - ((float)rand())/RAND_MAX, - ((float)rand())/RAND_MAX); + ((float)rand())/RAND_MAX, + ((float)rand())/RAND_MAX); pp=pp*2.0-Point3x(1,1,1); pp*=width; (*vi)+=pp; @@ -118,20 +163,20 @@ Assume che tutte normale in ingresso sia normalizzata; */ static int BestMatchingNormal(const Point3x &n, std::vector &nv) { - int ret=-1; - ScalarType bestang=-1; - ScalarType cosang; - typename std::vector::iterator ni; - for(ni=nv.begin();ni!=nv.end();++ni) - { - cosang=(*ni).dot(n); - if(cosang>bestang) { - bestang=cosang; - ret=ni-nv.begin(); - } - } + int ret=-1; + ScalarType bestang=-1; + ScalarType cosang; + typename std::vector::iterator ni; + for(ni=nv.begin();ni!=nv.end();++ni) + { + cosang=(*ni).dot(n); + if(cosang>bestang) { + bestang=cosang; + ret=ni-nv.begin(); + } + } assert(ret>=0 && ret >::iterator vi; - for(vi=v.begin(); vi!=v.end();++vi) + typename std::vector >::iterator vi; + for(vi=v.begin(); vi!=v.end();++vi) (*vi).Normalize(); - + } } };