principal_curvature.cpp 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837
  1. #include "principal_curvature.h"
  2. #include <iostream>
  3. #include <fstream>
  4. #include <iomanip>
  5. #include <queue>
  6. #include <list>
  7. #include <cmath>
  8. #include <limits>
  9. #include <Eigen/SparseCholesky>
  10. // Lib IGL includes
  11. #include <igl/adjacency_list.h>
  12. #include <igl/per_face_normals.h>
  13. #include <igl/per_vertex_normals.h>
  14. #include <igl/avg_edge_length.h>
  15. #include <igl/vf.h>
  16. using std::setfill;
  17. using std::setw;
  18. using std::cout;
  19. using std::endl;
  20. typedef enum
  21. {
  22. SPHERE_SEARCH,
  23. K_RING_SEARCH
  24. } searchType;
  25. typedef enum
  26. {
  27. AVERAGE,
  28. PROJ_PLANE
  29. } normalType;
  30. class CurvatureCalculator
  31. {
  32. public:
  33. /* Row number i represents the i-th vertex, whose columns are:
  34. curv[i][0] : K2
  35. curv[i][1] : K1
  36. curvDir[i][0] : PD1
  37. curvDir[i][1] : PD2
  38. */
  39. std::vector< std::vector<double> > curv;
  40. std::vector< std::vector<Eigen::Vector3d> > curvDir;
  41. bool curvatureComputed;
  42. class Quadric
  43. {
  44. public:
  45. IGL_INLINE Quadric ()
  46. {
  47. a() = b() = c() = d() = e() = 1.0;
  48. }
  49. IGL_INLINE Quadric(double av, double bv, double cv, double dv, double ev)
  50. {
  51. a() = av;
  52. b() = bv;
  53. c() = cv;
  54. d() = dv;
  55. e() = ev;
  56. }
  57. IGL_INLINE double& a() { return data[0];}
  58. IGL_INLINE double& b() { return data[1];}
  59. IGL_INLINE double& c() { return data[2];}
  60. IGL_INLINE double& d() { return data[3];}
  61. IGL_INLINE double& e() { return data[4];}
  62. double data[5];
  63. IGL_INLINE double evaluate(double u, double v)
  64. {
  65. return a()*u*u + b()*u*v + c()*v*v + d()*u + e()*v;
  66. }
  67. IGL_INLINE double du(double u, double v)
  68. {
  69. return 2.0*a()*u + b()*v + d();
  70. }
  71. IGL_INLINE double dv(double u, double v)
  72. {
  73. return 2.0*c()*v + b()*u + e();
  74. }
  75. IGL_INLINE double duv(double u, double v)
  76. {
  77. return b();
  78. }
  79. IGL_INLINE double duu(double u, double v)
  80. {
  81. return 2.0*a();
  82. }
  83. IGL_INLINE double dvv(double u, double v)
  84. {
  85. return 2.0*c();
  86. }
  87. IGL_INLINE static Quadric fit(vector<Eigen::Vector3d> &VV, bool zeroDetCheck, bool svd)
  88. {
  89. assert(VV.size() >= 5);
  90. if (VV.size() < 5)
  91. {
  92. cerr << "ASSERT FAILED!" << endl;
  93. exit(0);
  94. }
  95. Eigen::MatrixXd A(VV.size(),5);
  96. Eigen::MatrixXd b(VV.size(),1);
  97. Eigen::MatrixXd sol(5,1);
  98. for(unsigned int c=0; c < VV.size(); ++c)
  99. {
  100. double u = VV[c][0];
  101. double v = VV[c][1];
  102. double n = VV[c][2];
  103. A(c,0) = u*u;
  104. A(c,1) = u*v;
  105. A(c,2) = v*v;
  106. A(c,3) = u;
  107. A(c,4) = v;
  108. b(c) = n;
  109. }
  110. static int count = 0, index = 0;
  111. double min = 0.000000000001; //1.0e-12
  112. //Devo fare solving svd del sistema A*sol=b
  113. if (zeroDetCheck && ((A.transpose()*A).determinant() < min && (A.transpose()*A).determinant() > -min))
  114. {
  115. printf("Quadric: unsolvable vertex %d %d\n", count, ++index);
  116. sol=A.jacobiSvd(Eigen::ComputeThinU | Eigen::ComputeThinV).solve(b);
  117. // sol=A.jacobiSvd().solve(b);
  118. // double res = (A*sol-b).norm();
  119. // if (res > 10e-6)
  120. // {
  121. // cerr << "Norm residuals: " << res << endl;
  122. // cerr << "A:" << A << endl;
  123. // cerr << "sol:" << sol << endl;
  124. // cerr << "b:" << b << endl;
  125. // }
  126. return Quadric(sol(0),sol(1),sol(2),sol(3),sol(4));
  127. }
  128. count++;
  129. //for (int i = 0; i < 100; i++)
  130. {
  131. if (svd)
  132. sol=A.jacobiSvd(Eigen::ComputeThinU | Eigen::ComputeThinV).solve(b);
  133. else
  134. sol = ((A.transpose()*A).inverse()*A.transpose())*b;
  135. }
  136. return Quadric(sol(0),sol(1),sol(2),sol(3),sol(4));
  137. }
  138. };
  139. public:
  140. Eigen::MatrixXd vertices;
  141. // Face list of current mesh (#F x 3) or (#F x 4)
  142. // The i-th row contains the indices of the vertices that forms the i-th face in ccw order
  143. Eigen::MatrixXi faces;
  144. std::vector<std::vector<int> > vertex_to_vertices;
  145. std::vector<std::vector<int> > vertex_to_faces;
  146. std::vector<std::vector<int> > vertex_to_faces_index;
  147. Eigen::MatrixXd face_normals;
  148. Eigen::MatrixXd vertex_normals;
  149. /* Size of the neighborhood */
  150. double sphereRadius;
  151. int kRing;
  152. bool localMode; /* Use local mode */
  153. bool projectionPlaneCheck; /* Check collected vertices on tangent plane */
  154. bool montecarlo;
  155. bool svd; /* Use svd calculation instead of pseudoinverse */
  156. bool zeroDetCheck; /* Check if the determinant is close to zero */
  157. unsigned int montecarloN;
  158. searchType st; /* Use either a sphere search or a k-ring search */
  159. normalType nt;
  160. double lastRadius;
  161. double scaledRadius;
  162. std::string lastMeshName;
  163. /* Benchmark related variables */
  164. bool expStep; /* True if we want the radius to increase exponentially */
  165. int step; /* If expStep==false, by how much rhe radius increases on every step */
  166. int maxSize; /* The maximum limit of the radius in the benchmark */
  167. IGL_INLINE CurvatureCalculator();
  168. IGL_INLINE void init(const Eigen::MatrixXd& V, const Eigen::MatrixXi& F);
  169. IGL_INLINE void finalEigenStuff (int, vector<Eigen::Vector3d>, Quadric );
  170. IGL_INLINE void fitQuadric (Eigen::Vector3d, std::vector<Eigen::Vector3d> ref, const std::vector<int>& , Quadric *);
  171. IGL_INLINE void applyProjOnPlane(Eigen::Vector3d, std::vector<int>, std::vector<int>&);
  172. IGL_INLINE void getSphere(const int, const double, std::vector<int>&, int min);
  173. IGL_INLINE void getKRing(const int, const double,std::vector<int>&);
  174. IGL_INLINE Eigen::Vector3d project(Eigen::Vector3d, Eigen::Vector3d, Eigen::Vector3d);
  175. IGL_INLINE void computeReferenceFrame(int, Eigen::Vector3d, std::vector<Eigen::Vector3d>&);
  176. IGL_INLINE void getAverageNormal(int, std::vector<int>, Eigen::Vector3d&);
  177. IGL_INLINE void getProjPlane(int, std::vector<int>, Eigen::Vector3d&);
  178. IGL_INLINE void applyMontecarlo(std::vector<int>&,std::vector<int>*);
  179. IGL_INLINE void computeCurvature();
  180. IGL_INLINE void printCurvature(std::string outpath);
  181. IGL_INLINE double getAverageEdge();
  182. IGL_INLINE static int rotateForward (float *v0, float *v1, float *v2)
  183. {
  184. float t;
  185. if (abs(*v2) >= abs(*v1) && abs(*v2) >= abs(*v0))
  186. return 0;
  187. t = *v0;
  188. *v0 = *v2;
  189. *v2 = *v1;
  190. *v1 = t;
  191. return 1 + rotateForward (v0, v1, v2);
  192. }
  193. IGL_INLINE static void rotateBackward (int nr, float *v0, float *v1, float *v2)
  194. {
  195. float t;
  196. if (nr == 0)
  197. return;
  198. t = *v2;
  199. *v2 = *v0;
  200. *v0 = *v1;
  201. *v1 = t;
  202. rotateBackward (nr - 1, v0, v1, v2);
  203. }
  204. IGL_INLINE static Eigen::Vector3d chooseMax (Eigen::Vector3d n, Eigen::Vector3d abc, float ab)
  205. {
  206. int i, max_i;
  207. float max_sp;
  208. Eigen::Vector3d nt[8];
  209. n.normalize ();
  210. abc.normalize ();
  211. max_sp = - std::numeric_limits<float>::max();
  212. for (i = 0; i < 4; i++)
  213. {
  214. nt[i] = n;
  215. if (ab > 0)
  216. {
  217. switch (i)
  218. {
  219. case 0:
  220. break;
  221. case 1:
  222. nt[i][2] = -n[2];
  223. break;
  224. case 2:
  225. nt[i][0] = -n[0];
  226. nt[i][1] = -n[1];
  227. break;
  228. case 3:
  229. nt[i][0] = -n[0];
  230. nt[i][1] = -n[1];
  231. nt[i][2] = -n[2];
  232. break;
  233. }
  234. }
  235. else
  236. {
  237. switch (i)
  238. {
  239. case 0:
  240. nt[i][0] = -n[0];
  241. break;
  242. case 1:
  243. nt[i][1] = -n[1];
  244. break;
  245. case 2:
  246. nt[i][0] = -n[0];
  247. nt[i][2] = -n[2];
  248. break;
  249. case 3:
  250. nt[i][1] = -n[1];
  251. nt[i][2] = -n[2];
  252. break;
  253. }
  254. }
  255. if (nt[i].dot(abc) > max_sp)
  256. {
  257. max_sp = nt[i].dot(abc);
  258. max_i = i;
  259. }
  260. }
  261. return nt[max_i];
  262. }
  263. };
  264. class comparer
  265. {
  266. public:
  267. IGL_INLINE bool operator() (const std::pair<int, double>& lhs, const std::pair<int, double>&rhs) const
  268. {
  269. return lhs.second>rhs.second;
  270. }
  271. };
  272. IGL_INLINE CurvatureCalculator::CurvatureCalculator()
  273. {
  274. this->localMode=false;
  275. this->projectionPlaneCheck=false;
  276. this->sphereRadius=5;
  277. this->st=SPHERE_SEARCH;
  278. this->nt=PROJ_PLANE;
  279. this->montecarlo=false;
  280. this->montecarloN=0;
  281. this->kRing=3;
  282. this->svd=true;
  283. this->zeroDetCheck=true;
  284. this->curvatureComputed=false;
  285. this->expStep=true;
  286. }
  287. IGL_INLINE void CurvatureCalculator::init(const Eigen::MatrixXd& V, const Eigen::MatrixXi& F)
  288. {
  289. // Normalize vertices
  290. vertices = V;
  291. // vertices = vertices.array() - vertices.minCoeff();
  292. // vertices = vertices.array() / vertices.maxCoeff();
  293. // vertices = vertices.array() * (1.0/igl::avg_edge_length(V,F));
  294. faces = F;
  295. igl::adjacency_list(F, vertex_to_vertices);
  296. igl::vf(V, F, vertex_to_faces, vertex_to_faces_index);
  297. igl::per_face_normals(V, F, face_normals);
  298. igl::per_vertex_normals(V, F, face_normals, vertex_normals);
  299. }
  300. IGL_INLINE void CurvatureCalculator::fitQuadric (Eigen::Vector3d v, std::vector<Eigen::Vector3d> ref, const std::vector<int>& vv, Quadric *q)
  301. {
  302. vector<Eigen::Vector3d> points;
  303. points.reserve (vv.size());
  304. for (unsigned int i = 0; i < vv.size(); ++i) {
  305. Eigen::Vector3d cp = vertices.row(vv[i]);
  306. // vtang non e` il v tangente!!!
  307. Eigen::Vector3d vTang = cp - v;
  308. double x = vTang.dot(ref[0]);
  309. double y = vTang.dot(ref[1]);
  310. double z = vTang.dot(ref[2]);
  311. points.push_back(Eigen::Vector3d (x,y,z));
  312. }
  313. *q = Quadric::fit (points, zeroDetCheck, svd);
  314. }
  315. IGL_INLINE void CurvatureCalculator::finalEigenStuff (int i, vector<Eigen::Vector3d> ref, Quadric q)
  316. {
  317. double a = q.a();
  318. double b = q.b();
  319. double c = q.c();
  320. double d = q.d();
  321. double e = q.e();
  322. double E = 1.0 + d*d;
  323. double F = d*e;
  324. double G = 1.0 + e*e;
  325. Eigen::Vector3d n = Eigen::Vector3d(-d,-e,1.0).normalized();
  326. double L = 2.0 * a * n[2];
  327. double M = b * n[2];
  328. double N = 2 * c * n[2];
  329. // ----------------- Eigen stuff
  330. Eigen::Matrix2d m;
  331. m << L*G - M*F, M*E-L*F, M*E-L*F, N*E-M*F;
  332. m = m / (E*G-F*F);
  333. Eigen::SelfAdjointEigenSolver<Eigen::Matrix2d> eig(m);
  334. Eigen::Vector2d c_val = eig.eigenvalues();
  335. Eigen::Matrix2d c_vec = eig.eigenvectors();
  336. c_val = -c_val;
  337. Eigen::Vector3d v1, v2;
  338. v1[0] = c_vec(0);
  339. v1[1] = c_vec(1);
  340. v1[2] = d * v1[0] + e * v1[1];
  341. v2[0] = c_vec(2);
  342. v2[1] = c_vec(3);
  343. v2[2] = d * v2[0] + e * v2[1];
  344. v1 = v1.normalized();
  345. v2 = v2.normalized();
  346. Eigen::Vector3d v1global = ref[0] * v1[0] + ref[1] * v1[1] + ref[2] * v1[2];
  347. Eigen::Vector3d v2global = ref[0] * v2[0] + ref[1] * v2[1] + ref[2] * v2[2];
  348. v1global.normalize();
  349. v2global.normalize();
  350. v1global *= c_val(0);
  351. v2global *= c_val(1);
  352. if (c_val[0] > c_val[1])
  353. {
  354. curv[i]=std::vector<double>(2);
  355. curv[i][0]=c_val(1);
  356. curv[i][1]=c_val(0);
  357. curvDir[i]=std::vector<Eigen::Vector3d>(2);
  358. curvDir[i][0]=v2global;
  359. curvDir[i][1]=v1global;
  360. }
  361. else
  362. {
  363. curv[i]=std::vector<double>(2);
  364. curv[i][0]=c_val(0);
  365. curv[i][1]=c_val(1);
  366. curvDir[i]=std::vector<Eigen::Vector3d>(2);
  367. curvDir[i][0]=v1global;
  368. curvDir[i][1]=v2global;
  369. }
  370. // ---- end Eigen stuff
  371. }
  372. IGL_INLINE void CurvatureCalculator::getKRing(const int start, const double r, std::vector<int>&vv)
  373. {
  374. int bufsize=vertices.rows();
  375. vv.reserve(bufsize);
  376. std::list<std::pair<int,int> > queue;
  377. bool* visited = (bool*)calloc(bufsize,sizeof(bool));
  378. queue.push_back(std::pair<int,int>(start,0));
  379. visited[start]=true;
  380. while (!queue.empty())
  381. {
  382. int toVisit=queue.front().first;
  383. int distance=queue.front().second;
  384. queue.pop_front();
  385. vv.push_back(toVisit);
  386. if (distance<(int)r)
  387. {
  388. for (unsigned int i=0; i<vertex_to_vertices[toVisit].size(); i++)
  389. {
  390. int neighbor=vertex_to_vertices[toVisit][i];
  391. if (!visited[neighbor])
  392. {
  393. queue.push_back(std::pair<int,int> (neighbor,distance+1));
  394. visited[neighbor]=true;
  395. }
  396. }
  397. }
  398. }
  399. free(visited);
  400. return;
  401. }
  402. IGL_INLINE void CurvatureCalculator::getSphere(const int start, const double r, std::vector<int> &vv, int min)
  403. {
  404. int bufsize=vertices.rows();
  405. vv.reserve(bufsize);
  406. std::list<int>* queue= new std::list<int>();
  407. bool* visited = (bool*)calloc(bufsize,sizeof(bool));
  408. queue->push_back(start);
  409. visited[start]=true;
  410. Eigen::Vector3d me=vertices.row(start);
  411. std::priority_queue<std::pair<int, double>, vector<std::pair<int, double> >, comparer >* extra_candidates= new std::priority_queue<std::pair<int, double>, vector<std::pair<int, double> >, comparer >();
  412. while (!queue->empty())
  413. {
  414. int toVisit=queue->front();
  415. queue->pop_front();
  416. vv.push_back(toVisit);
  417. for (unsigned int i=0; i<vertex_to_vertices[toVisit].size(); i++)
  418. {
  419. int neighbor=vertex_to_vertices[toVisit][i];
  420. if (!visited[neighbor])
  421. {
  422. Eigen::Vector3d neigh=vertices.row(neighbor);
  423. float distance=(me-neigh).norm();
  424. if (distance<r)
  425. queue->push_back(neighbor);
  426. else if (vv.size()<min)
  427. extra_candidates->push(std::pair<int,double>(neighbor,distance));
  428. visited[neighbor]=true;
  429. }
  430. }
  431. }
  432. while (!extra_candidates->empty() && vv.size()<min)
  433. {
  434. std::pair<int, double> cand=extra_candidates->top();
  435. extra_candidates->pop();
  436. vv.push_back(cand.first);
  437. for (unsigned int i=0; i<vertex_to_vertices[cand.first].size(); i++)
  438. {
  439. int neighbor=vertex_to_vertices[cand.first][i];
  440. if (!visited[neighbor])
  441. {
  442. Eigen::Vector3d neigh=vertices.row(neighbor);
  443. float distance=(me-neigh).norm();
  444. extra_candidates->push(std::pair<int,double>(neighbor,distance));
  445. visited[neighbor]=true;
  446. }
  447. }
  448. }
  449. free(extra_candidates);
  450. free(queue);
  451. free(visited);
  452. }
  453. IGL_INLINE inline Eigen::Vector3d CurvatureCalculator::project(Eigen::Vector3d v, Eigen::Vector3d vp, Eigen::Vector3d ppn)
  454. {
  455. return (vp - (ppn * ((vp - v).dot(ppn))));
  456. }
  457. IGL_INLINE void CurvatureCalculator::computeReferenceFrame(int i, Eigen::Vector3d normal, std::vector<Eigen::Vector3d>& ref )
  458. {
  459. Eigen::Vector3d longest_v=Eigen::Vector3d::Zero();
  460. longest_v=Eigen::Vector3d(vertices.row(vertex_to_vertices[i][0]));
  461. longest_v=(project(vertices.row(i),longest_v,normal)-Eigen::Vector3d(vertices.row(i))).normalized();
  462. /* L'ultimo asse si ottiene come prodotto vettoriale tra i due
  463. * calcolati */
  464. Eigen::Vector3d y_axis=(normal.cross(longest_v)).normalized();
  465. ref[0]=longest_v;
  466. ref[1]=y_axis;
  467. ref[2]=normal;
  468. }
  469. IGL_INLINE void CurvatureCalculator::getAverageNormal(int j, std::vector<int> vv, Eigen::Vector3d& normal)
  470. {
  471. normal=(vertex_normals.row(j)).normalized();
  472. if (localMode)
  473. return;
  474. for (unsigned int i=0; i<vv.size(); i++)
  475. {
  476. normal+=vertex_normals.row(vv[i]).normalized();
  477. }
  478. normal.normalize();
  479. }
  480. IGL_INLINE void CurvatureCalculator::getProjPlane(int j, std::vector<int> vv, Eigen::Vector3d& ppn)
  481. {
  482. int nr;
  483. float a, b, c;
  484. float nx, ny, nz;
  485. float abcq;
  486. a = b = c = 0;
  487. if (localMode)
  488. {
  489. for (unsigned int i=0; i<vertex_to_faces.at(j).size(); ++i)
  490. {
  491. Eigen::Vector3d faceNormal=face_normals.row(vertex_to_faces.at(j).at(i));
  492. a += faceNormal[0];
  493. b += faceNormal[1];
  494. c += faceNormal[2];
  495. }
  496. }
  497. else
  498. {
  499. for (unsigned int i=0; i<vv.size(); ++i)
  500. {
  501. a+= vertex_normals.row(vv[i])[0];
  502. b+= vertex_normals.row(vv[i])[1];
  503. c+= vertex_normals.row(vv[i])[2];
  504. }
  505. }
  506. nr = rotateForward (&a, &b, &c);
  507. abcq = a*a + b*b + c*c;
  508. nx = sqrt (a*a / abcq);
  509. ny = sqrt (b*b / abcq);
  510. nz = sqrt (1 - nx*nx - ny*ny);
  511. rotateBackward (nr, &a, &b, &c);
  512. rotateBackward (nr, &nx, &ny, &nz);
  513. ppn = chooseMax (Eigen::Vector3d(nx, ny, nz), Eigen::Vector3d (a, b, c), a * b);
  514. ppn.normalize();
  515. }
  516. IGL_INLINE double CurvatureCalculator::getAverageEdge()
  517. {
  518. double sum = 0;
  519. int count = 0;
  520. for (int i = 0; i<faces.rows(); i++)
  521. {
  522. for (short unsigned j=0; j<3; j++)
  523. {
  524. Eigen::Vector3d p1=vertices.row(faces.row(i)[j]);
  525. Eigen::Vector3d p2=vertices.row(faces.row(i)[(j+1)%3]);
  526. double l = (p1-p2).norm();
  527. sum+=l;
  528. ++count;
  529. }
  530. }
  531. return (sum/(double)count);
  532. }
  533. IGL_INLINE void CurvatureCalculator::applyProjOnPlane(Eigen::Vector3d ppn, std::vector<int> vin, std::vector<int> &vout)
  534. {
  535. for (vector<int>::iterator vpi = vin.begin(); vpi != vin.end(); ++vpi)
  536. if (vertex_normals.row(*vpi) * ppn > 0.0f)
  537. vout.push_back (*vpi);
  538. }
  539. IGL_INLINE void CurvatureCalculator::applyMontecarlo(std::vector<int>& vin, std::vector<int> *vout)
  540. {
  541. if (montecarloN >= vin.size ())
  542. {
  543. *vout = vin;
  544. return;
  545. }
  546. float p = ((float) montecarloN) / (float) vin.size();
  547. for (std::vector<int>::iterator vpi = vin.begin(); vpi != vin.end(); ++vpi)
  548. {
  549. float r;
  550. if ((r = ((float)rand () / RAND_MAX)) < p)
  551. {
  552. vout->push_back (*vpi);
  553. }
  554. }
  555. }
  556. IGL_INLINE void CurvatureCalculator::computeCurvature()
  557. {
  558. //CHECK che esista la mesh
  559. size_t vertices_count=vertices.rows() ;
  560. if (vertices_count <=0)
  561. return;
  562. curvDir=std::vector< std::vector<Eigen::Vector3d> >(vertices_count);
  563. curv=std::vector<std::vector<double> >(vertices_count);
  564. scaledRadius=getAverageEdge()*sphereRadius;
  565. std::vector<int> vv;
  566. std::vector<int> vvtmp;
  567. Eigen::Vector3d normal;
  568. double time_spent;
  569. double searchtime=0, ref_time=0, fit_time=0, final_time=0;
  570. for (size_t i=0; i<vertices_count; ++i)
  571. {
  572. vv.clear();
  573. vvtmp.clear();
  574. Eigen::Vector3d me=vertices.row(i);
  575. switch (st)
  576. {
  577. case SPHERE_SEARCH:
  578. getSphere(i,scaledRadius,vv,6);
  579. break;
  580. case K_RING_SEARCH:
  581. getKRing(i,kRing,vv);
  582. break;
  583. default:
  584. fprintf(stderr,"Error: search type not recognized");
  585. return;
  586. }
  587. std::vector<Eigen::Vector3d> ref(3);
  588. if (vv.size()<6)
  589. {
  590. std::cerr << "Could not compute curvature of radius " << scaledRadius << endl;
  591. return;
  592. }
  593. switch (nt)
  594. {
  595. case AVERAGE:
  596. getAverageNormal(i,vv,normal);
  597. break;
  598. case PROJ_PLANE:
  599. getProjPlane(i,vv,normal);
  600. break;
  601. default:
  602. fprintf(stderr,"Error: normal type not recognized");
  603. return;
  604. }
  605. if (projectionPlaneCheck)
  606. {
  607. vvtmp.reserve (vv.size ());
  608. applyProjOnPlane (normal, vv, vvtmp);
  609. if (vvtmp.size() >= 6)
  610. vv = vvtmp;
  611. }
  612. if (vv.size()<6)
  613. {
  614. std::cerr << "Could not compute curvature of radius " << scaledRadius << endl;
  615. return;
  616. }
  617. if (montecarlo)
  618. {
  619. if(montecarloN<6)
  620. break;
  621. vvtmp.reserve(vv.size());
  622. applyMontecarlo(vv,&vvtmp);
  623. vv=vvtmp;
  624. }
  625. if (vv.size()<6)
  626. return;
  627. computeReferenceFrame(i,normal,ref);
  628. Quadric q;
  629. fitQuadric (me, ref, vv, &q);
  630. finalEigenStuff(i,ref,q);
  631. }
  632. lastRadius=sphereRadius;
  633. curvatureComputed=true;
  634. }
  635. IGL_INLINE void CurvatureCalculator::printCurvature(std::string outpath)
  636. {
  637. if (!curvatureComputed)
  638. return;
  639. std::ofstream of;
  640. of.open(outpath.c_str());
  641. if (!of)
  642. {
  643. fprintf(stderr, "Error: could not open output file %s\n", outpath.c_str());
  644. return;
  645. }
  646. int vertices_count=vertices.rows();
  647. of << vertices_count << endl;
  648. for (int i=0; i<vertices_count; i++)
  649. {
  650. of << curv[i][0] << " " << curv[i][1] << " " << curvDir[i][0][0] << " " << curvDir[i][0][1] << " " << curvDir[i][0][2] << " " <<
  651. curvDir[i][1][0] << " " << curvDir[i][1][1] << " " << curvDir[i][1][2] << endl;
  652. }
  653. of.close();
  654. }
  655. template <typename DerivedV, typename DerivedF>
  656. IGL_INLINE void igl::principal_curvature(
  657. const Eigen::PlainObjectBase<DerivedV>& V,
  658. const Eigen::PlainObjectBase<DerivedF>& F,
  659. Eigen::PlainObjectBase<DerivedV>& PD1,
  660. Eigen::PlainObjectBase<DerivedV>& PD2,
  661. unsigned radius
  662. )
  663. {
  664. // Preallocate memory
  665. PD1.resize(V.rows(),3);
  666. PD2.resize(V.rows(),3);
  667. // Precomputation
  668. CurvatureCalculator cc;
  669. cc.init(V.template cast<double>(),F.template cast<int>());
  670. cc.sphereRadius = radius;
  671. // Compute
  672. cc.computeCurvature();
  673. // Copy it back
  674. for (unsigned i=0; i<V.rows(); i++)
  675. {
  676. Eigen::Vector3d d1;
  677. Eigen::Vector3d d2;
  678. d1 << cc.curvDir[i][0][0], cc.curvDir[i][0][1], cc.curvDir[i][0][2];
  679. d2 << cc.curvDir[i][1][0], cc.curvDir[i][1][1], cc.curvDir[i][1][2];
  680. d1.normalize();
  681. d2.normalize();
  682. d1 *= cc.curv[i][0];
  683. d2 *= cc.curv[i][1];
  684. PD1.row(i) = d1;
  685. PD2.row(i) = d2;
  686. if (PD1.row(i) * PD2.row(i).transpose() > 10e-6)
  687. {
  688. cerr << "Something is wrong, vertex: i" << endl;
  689. PD1.row(i) *= 0;
  690. PD2.row(i) *= 0;
  691. }
  692. }
  693. }