winding_number.cpp 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217
  1. #include "winding_number.h"
  2. #include "WindingNumberAABB.h"
  3. #include <igl/PI.h>
  4. #include <cmath>
  5. // IF THIS IS EVER TEMPLATED BE SURE THAT V IS COLMAJOR
  6. IGL_INLINE void igl::winding_number(
  7. const Eigen::MatrixXd & V,
  8. const Eigen::MatrixXi & F,
  9. const Eigen::MatrixXd & O,
  10. Eigen::VectorXd & W)
  11. {
  12. using namespace Eigen;
  13. // make room for output
  14. W.resize(O.rows(),1);
  15. switch(F.cols())
  16. {
  17. case 2:
  18. return winding_number_2(
  19. V.data(),
  20. V.rows(),
  21. F.data(),
  22. F.rows(),
  23. O.data(),
  24. O.rows(),
  25. W.data());
  26. case 3:
  27. {
  28. WindingNumberAABB<Vector3d> hier(V,F);
  29. hier.grow();
  30. // loop over origins
  31. const int no = O.rows();
  32. # pragma omp parallel for if (no>IGL_WINDING_NUMBER_OMP_MIN_VALUE)
  33. for(int o = 0;o<no;o++)
  34. {
  35. Vector3d p = O.row(o);
  36. W(o) = hier.winding_number(p);
  37. }
  38. break;
  39. }
  40. default: assert(false && "Bad simplex size"); break;
  41. }
  42. }
  43. template <typename Scalar, typename DerivedF>
  44. IGL_INLINE void igl::winding_number_3(
  45. const Scalar * V,
  46. const int n,
  47. const DerivedF * F,
  48. const int m,
  49. const Scalar * O,
  50. const int no,
  51. Scalar * S)
  52. {
  53. // Initialize output
  54. // loop over origins
  55. #pragma omp parallel for if (no>IGL_WINDING_NUMBER_OMP_MIN_VALUE)
  56. for(int o = 0;o<no;o++)
  57. {
  58. S[o] = 0;
  59. }
  60. // Only use parallel for if there are many facets and more than one origin.
  61. // Assumes that if there is exactly one origin then this is being called
  62. // within an outer for loop which may be parallel
  63. #pragma omp parallel for if (m>IGL_WINDING_NUMBER_OMP_MIN_VALUE && no>1)
  64. // loop over faces
  65. for(int f = 0;f<m;f++)
  66. {
  67. // Gather corners
  68. Scalar C[3][3];
  69. // loop around triangle
  70. for(int t=0;t<3;t++)
  71. {
  72. // loop over dimensions
  73. for(int d = 0;d<3;d++)
  74. {
  75. // Indices are offset by 1
  76. int Ff = F[m*t + f];
  77. C[t][d] = V[d*n + Ff];
  78. }
  79. }
  80. // loop over origins
  81. for(int o = 0;o<no;o++)
  82. {
  83. // Gather vectors to corners
  84. Scalar v[3][3];
  85. Scalar vl[3];
  86. // loop around triangle
  87. for(int t=0;t<3;t++)
  88. {
  89. vl[t] = 0;
  90. // loop over dimensions
  91. for(int d = 0;d<3;d++)
  92. {
  93. v[t][d] = C[t][d] - O[d*no + o];
  94. // compute edge length contribution
  95. vl[t] += v[t][d]*v[t][d];
  96. }
  97. // finish edge length computation
  98. // Matlab crashes on NaN
  99. if(vl[t]!=0)
  100. {
  101. vl[t] = sqrt(vl[t]);
  102. }
  103. }
  104. //printf("\n");
  105. // Compute determinant
  106. Scalar detf =
  107. v[0][0]*v[1][1]*v[2][2]+
  108. v[1][0]*v[2][1]*v[0][2]+
  109. v[2][0]*v[0][1]*v[1][2]-
  110. v[2][0]*v[1][1]*v[0][2]-
  111. v[1][0]*v[0][1]*v[2][2]-
  112. v[0][0]*v[2][1]*v[1][2];
  113. // Compute pairwise dotproducts
  114. Scalar dp[3];
  115. dp[0] = v[1][0]*v[2][0];
  116. dp[0] += v[1][1]*v[2][1];
  117. dp[0] += v[1][2]*v[2][2];
  118. dp[1] = v[2][0]*v[0][0];
  119. dp[1] += v[2][1]*v[0][1];
  120. dp[1] += v[2][2]*v[0][2];
  121. dp[2] = v[0][0]*v[1][0];
  122. dp[2] += v[0][1]*v[1][1];
  123. dp[2] += v[0][2]*v[1][2];
  124. // Compute winding number
  125. // Only divide by TWO_PI instead of 4*pi because there was a 2 out front
  126. Scalar val = atan2(detf,
  127. vl[0]*vl[1]*vl[2] +
  128. dp[0]*vl[0] +
  129. dp[1]*vl[1] +
  130. dp[2]*vl[2]) / (2.*igl::PI);
  131. #pragma omp atomic
  132. S[o] += val;
  133. }
  134. }
  135. }
  136. template <typename DerivedF>
  137. IGL_INLINE void igl::winding_number_2(
  138. const double * V,
  139. const int n,
  140. const DerivedF * F,
  141. const int m,
  142. const double * O,
  143. const int no,
  144. double * S)
  145. {
  146. // Initialize output
  147. // loop over origins
  148. #pragma omp parallel for if (no>IGL_WINDING_NUMBER_OMP_MIN_VALUE)
  149. for(int o = 0;o<no;o++)
  150. {
  151. S[o] = 0;
  152. }
  153. #pragma omp parallel for if (m>IGL_WINDING_NUMBER_OMP_MIN_VALUE && no>1)
  154. // loop over faces
  155. for(int f = 0;f<m;f++)
  156. {
  157. // Index of source and destination
  158. int s = F[m*0 + f];
  159. int d = F[m*1 + f];
  160. // Positions of source and destination
  161. double vs[2];
  162. double vd[2];
  163. vs[0] = V[0*n + s];
  164. vs[1] = V[1*n + s];
  165. vd[0] = V[0*n + d];
  166. vd[1] = V[1*n + d];
  167. // loop over origins
  168. for(int o = 0;o<no;o++)
  169. {
  170. // Gather vectors to source and destination
  171. double o2vs[2];
  172. double o2vd[2];
  173. // and lengths
  174. double o2vsl = 0;
  175. double o2vdl = 0;
  176. for(int i = 0;i<2;i++)
  177. {
  178. o2vs[i] = O[i*no + o] - vs[i];
  179. o2vd[i] = O[i*no + o] - vd[i];
  180. o2vsl += o2vs[i]*o2vs[i];
  181. o2vdl += o2vd[i]*o2vd[i];
  182. }
  183. o2vsl = sqrt(o2vsl);
  184. o2vdl = sqrt(o2vdl);
  185. // Normalize
  186. for(int i = 0;i<2;i++)
  187. {
  188. // Matlab crashes on NaN
  189. if(o2vsl!=0)
  190. {
  191. o2vs[i] /= o2vsl;
  192. }
  193. if(o2vdl!=0)
  194. {
  195. o2vd[i] /= o2vdl;
  196. }
  197. }
  198. double val =
  199. atan2(o2vd[0]*o2vs[1]-o2vd[1]*o2vs[0],o2vd[0]*o2vs[0]+o2vd[1]*o2vs[1])/
  200. (2.*igl::PI);
  201. #pragma omp atomic
  202. S[o] += val;
  203. }
  204. }
  205. }
  206. #ifdef IGL_STATIC_LIBRARY
  207. // Explicit template specialization
  208. template void igl::winding_number_2<double>(double const*, int, double const*, int, double const*, int, double*);
  209. template void igl::winding_number_3<double>(double const*, int, double const*, int, double const*, int, double*);
  210. template void igl::winding_number_3<double, int>(double const*, int, int const*, int, double const*, int, double*);
  211. #endif