comb_cross_field.cpp 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190
  1. #include "comb_cross_field.h"
  2. #include <vector>
  3. #include <deque>
  4. #include "per_face_normals.h"
  5. #include "is_border_vertex.h"
  6. #include "tt.h"
  7. namespace igl {
  8. template <typename DerivedV, typename DerivedF>
  9. class Comb
  10. {
  11. public:
  12. const Eigen::PlainObjectBase<DerivedV> &V;
  13. const Eigen::PlainObjectBase<DerivedF> &F;
  14. const Eigen::PlainObjectBase<DerivedV> &PD1;
  15. const Eigen::PlainObjectBase<DerivedV> &PD2;
  16. Eigen::PlainObjectBase<DerivedV> N;
  17. private:
  18. // internal
  19. Eigen::PlainObjectBase<DerivedF> TT;
  20. Eigen::PlainObjectBase<DerivedF> TTi;
  21. private:
  22. static double Sign(double a){return (double)((a>0)?+1:-1);}
  23. ///given 2 vector centered into origin calculate the rotation matrix from first to the second
  24. static Eigen::Matrix<typename DerivedV::Scalar, 3, 3> RotationMatrix(Eigen::Matrix<typename DerivedV::Scalar, 3, 1> v0,
  25. Eigen::Matrix<typename DerivedV::Scalar, 3, 1> v1,
  26. bool normalized=true)
  27. {
  28. Eigen::Matrix<typename DerivedV::Scalar, 3, 3> rotM;
  29. const double epsilon=0.00001;
  30. if (!normalized)
  31. {
  32. v0.normalize();
  33. v1.normalize();
  34. }
  35. typename DerivedV::Scalar dot=v0.dot(v1);
  36. ///control if there is no rotation
  37. if (dot>((double)1-epsilon))
  38. {
  39. rotM = Eigen::Matrix<typename DerivedV::Scalar, 3, 3>::Identity();
  40. return rotM;
  41. }
  42. ///find the axis of rotation
  43. Eigen::Matrix<typename DerivedV::Scalar, 3, 1> axis;
  44. axis=v0.cross(v1);
  45. axis.normalize();
  46. ///construct rotation matrix
  47. typename DerivedV::Scalar u=axis(0);
  48. typename DerivedV::Scalar v=axis(1);
  49. typename DerivedV::Scalar w=axis(2);
  50. typename DerivedV::Scalar phi=acos(dot);
  51. typename DerivedV::Scalar rcos = cos(phi);
  52. typename DerivedV::Scalar rsin = sin(phi);
  53. rotM(0,0) = rcos + u*u*(1-rcos);
  54. rotM(1,0) = w * rsin + v*u*(1-rcos);
  55. rotM(2,0) = -v * rsin + w*u*(1-rcos);
  56. rotM(0,1) = -w * rsin + u*v*(1-rcos);
  57. rotM(1,1) = rcos + v*v*(1-rcos);
  58. rotM(2,1) = u * rsin + w*v*(1-rcos);
  59. rotM(0,2) = v * rsin + u*w*(1-rcos);
  60. rotM(1,2) = -u * rsin + v*w*(1-rcos);
  61. rotM(2,2) = rcos + w*w*(1-rcos);
  62. return rotM;
  63. }
  64. public:
  65. ///rotate a given vector from the tangent space
  66. ///of f0 to the tangent space of f1 by considering the difference of normals
  67. static Eigen::Matrix<typename DerivedV::Scalar, 3, 1> Rotate(Eigen::Matrix<typename DerivedV::Scalar, 3, 1> N0,
  68. Eigen::Matrix<typename DerivedV::Scalar, 3, 1> N1,
  69. const Eigen::Matrix<typename DerivedV::Scalar, 3, 1>& dir3D)
  70. {
  71. ///find the rotation matrix that maps between normals
  72. // vcg::Matrix33<ScalarType> rotation=vcg::RotationMatrix(N0,N1);
  73. Eigen::Matrix<typename DerivedV::Scalar, 3, 3> rotation = RotationMatrix(N0,N1);
  74. Eigen::Matrix<typename DerivedV::Scalar, 3, 1> rotated=rotation*dir3D;
  75. return rotated;
  76. }
  77. private:
  78. // returns the 90 deg rotation of a (around n) most similar to target b
  79. /// a and b should be in the same plane orthogonal to N
  80. static Eigen::Matrix<typename DerivedV::Scalar, 3, 1> K_PI_new(const Eigen::Matrix<typename DerivedV::Scalar, 3, 1>& a,
  81. const Eigen::Matrix<typename DerivedV::Scalar, 3, 1>& b,
  82. const Eigen::Matrix<typename DerivedV::Scalar, 3, 1>& n)
  83. {
  84. Eigen::Matrix<typename DerivedV::Scalar, 3, 1> c = (a.cross(n)).normalized();
  85. typename DerivedV::Scalar scorea = a.dot(b);
  86. typename DerivedV::Scalar scorec = c.dot(b);
  87. if (fabs(scorea)>=fabs(scorec))
  88. return a*Sign(scorea);
  89. else
  90. return c*Sign(scorec);
  91. }
  92. public:
  93. Comb(const Eigen::PlainObjectBase<DerivedV> &_V,
  94. const Eigen::PlainObjectBase<DerivedF> &_F,
  95. const Eigen::PlainObjectBase<DerivedV> &_PD1,
  96. const Eigen::PlainObjectBase<DerivedV> &_PD2
  97. ):
  98. V(_V),
  99. F(_F),
  100. PD1(_PD1),
  101. PD2(_PD2)
  102. {
  103. igl::per_face_normals(V,F,N);
  104. igl::tt(V,F,TT,TTi);
  105. }
  106. void comb(Eigen::PlainObjectBase<DerivedV> &PD1out,
  107. Eigen::PlainObjectBase<DerivedV> &PD2out)
  108. {
  109. // PD1out = PD1;
  110. // PD2out = PD2;
  111. PD1out.setZero(F.rows(),3);PD1out<<PD1;
  112. PD2out.setZero(F.rows(),3);PD2out<<PD2;
  113. Eigen::VectorXi mark = Eigen::VectorXi::Constant(F.rows(),false);
  114. std::deque<int> d;
  115. d.push_back(0);
  116. mark(0) = true;
  117. while (!d.empty())
  118. {
  119. int f0 = d.at(0);
  120. d.pop_front();
  121. for (int k=0; k<3; k++)
  122. {
  123. int f1 = TT(f0,k);
  124. if (f1==-1) continue;
  125. if (mark(f1)) continue;
  126. Eigen::Matrix<typename DerivedV::Scalar, 3, 1> dir0 = PD1out.row(f0);
  127. Eigen::Matrix<typename DerivedV::Scalar, 3, 1> dir1 = PD1out.row(f1);
  128. Eigen::Matrix<typename DerivedV::Scalar, 3, 1> n0 = N.row(f0);
  129. Eigen::Matrix<typename DerivedV::Scalar, 3, 1> n1 = N.row(f1);
  130. Eigen::Matrix<typename DerivedV::Scalar, 3, 1> dir0Rot = Rotate(n0,n1,dir0);
  131. dir0Rot.normalize();
  132. Eigen::Matrix<typename DerivedV::Scalar, 3, 1> targD = K_PI_new(dir1,dir0Rot,n1);
  133. PD1out.row(f1) = targD;
  134. PD2out.row(f1) = n1.cross(targD).normalized();
  135. mark(f1) = true;
  136. d.push_back(f1);
  137. }
  138. }
  139. // everything should be marked
  140. for (int i=0; i<F.rows(); i++)
  141. {
  142. assert(mark(i));
  143. }
  144. }
  145. };
  146. }
  147. template <typename DerivedV, typename DerivedF>
  148. IGL_INLINE void igl::comb_cross_field(const Eigen::PlainObjectBase<DerivedV> &V,
  149. const Eigen::PlainObjectBase<DerivedF> &F,
  150. const Eigen::PlainObjectBase<DerivedV> &PD1,
  151. const Eigen::PlainObjectBase<DerivedV> &PD2,
  152. Eigen::PlainObjectBase<DerivedV> &PD1out,
  153. Eigen::PlainObjectBase<DerivedV> &PD2out)
  154. {
  155. igl::Comb<DerivedV, DerivedF> cmb(V, F, PD1, PD2);
  156. cmb.comb(PD1out, PD2out);
  157. }