pseudonormal_test.cpp 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230
  1. // This file is part of libigl, a simple c++ geometry processing library.
  2. //
  3. // Copyright (C) 2014 Alec Jacobson <[email protected]>
  4. //
  5. // This Source Code Form is subject to the terms of the Mozilla Public License
  6. // v. 2.0. If a copy of the MPL was not distributed with this file, You can
  7. // obtain one at http://mozilla.org/MPL/2.0/.
  8. #include "pseudonormal_test.h"
  9. #include "barycentric_coordinates.h"
  10. #include "doublearea.h"
  11. #include "project_to_line_segment.h"
  12. #include <cassert>
  13. template <
  14. typename DerivedV,
  15. typename DerivedF,
  16. typename DerivedFN,
  17. typename DerivedVN,
  18. typename DerivedEN,
  19. typename DerivedEMAP,
  20. typename Derivedq,
  21. typename Derivedc,
  22. typename Scalar,
  23. typename Derivedn>
  24. IGL_INLINE void igl::pseudonormal_test(
  25. const Eigen::MatrixBase<DerivedV> & V,
  26. const Eigen::MatrixBase<DerivedF> & F,
  27. const Eigen::MatrixBase<DerivedFN> & FN,
  28. const Eigen::MatrixBase<DerivedVN> & VN,
  29. const Eigen::MatrixBase<DerivedEN> & EN,
  30. const Eigen::MatrixBase<DerivedEMAP> & EMAP,
  31. const Eigen::MatrixBase<Derivedq> & q,
  32. const int f,
  33. Eigen::PlainObjectBase<Derivedc> & c,
  34. Scalar & s,
  35. Eigen::PlainObjectBase<Derivedn> & n)
  36. {
  37. static_assert(DerivedV::ColsAtCompileTime == 3 || DerivedV::ColsAtCompileTime == Eigen::Dynamic,"V must either have 3 or Dynamic columns");
  38. static_assert(DerivedFN::ColsAtCompileTime == 3 || DerivedFN::ColsAtCompileTime == Eigen::Dynamic,"FN must either have 3 or Dynamic columns");
  39. static_assert(DerivedVN::ColsAtCompileTime == 3 || DerivedVN::ColsAtCompileTime == Eigen::Dynamic,"VN must either have 3 or Dynamic columns");
  40. static_assert(DerivedEN::ColsAtCompileTime == 3 || DerivedEN::ColsAtCompileTime == Eigen::Dynamic,"EN must either have 3 or Dynamic columns");
  41. static_assert(
  42. Derivedc::ColsAtCompileTime*Derivedc::RowsAtCompileTime == 3 ||
  43. Derivedc::ColsAtCompileTime*Derivedc::RowsAtCompileTime == Eigen::Dynamic,"c must be size 3 or Dynamic");
  44. static_assert(
  45. Derivedq::ColsAtCompileTime*Derivedq::RowsAtCompileTime == 3 ||
  46. Derivedq::ColsAtCompileTime*Derivedq::RowsAtCompileTime == Eigen::Dynamic,"q must be size 3 or Dynamic");
  47. static_assert(
  48. Derivedn::ColsAtCompileTime*Derivedn::RowsAtCompileTime == 3 ||
  49. Derivedn::ColsAtCompileTime*Derivedn::RowsAtCompileTime == Eigen::Dynamic,"q must be size 3 or Dynamic");
  50. const auto & qc = q-c;
  51. typedef Eigen::Matrix<Scalar,1,3> RowVector3S;
  52. RowVector3S b;
  53. // Using barycentric coorindates to determine whether close to a vertex/edge
  54. // seems prone to error when dealing with nearly degenerate triangles: Even
  55. // the barycenter (1/3,1/3,1/3) can be made arbitrarily close to an
  56. // edge/vertex
  57. //
  58. const RowVector3S A = V.row(F(f,0));
  59. const RowVector3S B = V.row(F(f,1));
  60. const RowVector3S C = V.row(F(f,2));
  61. const double area = [&A,&B,&C]()
  62. {
  63. Eigen::Matrix<double,1,1> area;
  64. doublearea(A,B,C,area);
  65. return area(0);
  66. }();
  67. // These were chosen arbitrarily. In a floating point scenario, I'm not sure
  68. // the best way to determine if c is on a vertex/edge or in the middle of the
  69. // face: specifically, I'm worrying about degenerate triangles where
  70. // barycentric coordinates are error-prone.
  71. const double MIN_DOUBLE_AREA = 1e-4;
  72. const double epsilon = 1e-12;
  73. if(area>MIN_DOUBLE_AREA)
  74. {
  75. barycentric_coordinates( c,A,B,C,b);
  76. // Determine which normal to use
  77. const int type = (b.array()<=epsilon).template cast<int>().sum();
  78. switch(type)
  79. {
  80. case 2:
  81. // Find vertex
  82. for(int x = 0;x<3;x++)
  83. {
  84. if(b(x)>epsilon)
  85. {
  86. n = VN.row(F(f,x));
  87. break;
  88. }
  89. }
  90. break;
  91. case 1:
  92. // Find edge
  93. for(int x = 0;x<3;x++)
  94. {
  95. if(b(x)<=epsilon)
  96. {
  97. n = EN.row(EMAP(F.rows()*x+f));
  98. break;
  99. }
  100. }
  101. break;
  102. default:
  103. assert(false && "all barycentric coords zero.");
  104. case 0:
  105. n = FN.row(f);
  106. break;
  107. }
  108. }else
  109. {
  110. // Check each vertex
  111. bool found = false;
  112. for(int v = 0;v<3 && !found;v++)
  113. {
  114. if( (c-V.row(F(f,v))).norm() < epsilon)
  115. {
  116. found = true;
  117. n = VN.row(F(f,v));
  118. }
  119. }
  120. // Check each edge
  121. for(int e = 0;e<3 && !found;e++)
  122. {
  123. const RowVector3S s = V.row(F(f,(e+1)%3));
  124. const RowVector3S d = V.row(F(f,(e+2)%3));
  125. Eigen::Matrix<double,1,1> sqr_d_j_x(1,1);
  126. Eigen::Matrix<double,1,1> t(1,1);
  127. project_to_line_segment(c,s,d,t,sqr_d_j_x);
  128. if(sqrt(sqr_d_j_x(0)) < epsilon)
  129. {
  130. n = EN.row(EMAP(F.rows()*e+f));
  131. found = true;
  132. }
  133. }
  134. // Finally just use face
  135. if(!found)
  136. {
  137. n = FN.row(f);
  138. }
  139. }
  140. s = (qc.dot(n) >= 0 ? 1. : -1.);
  141. }
  142. template <
  143. typename DerivedV,
  144. typename DerivedF,
  145. typename DerivedEN,
  146. typename DerivedVN,
  147. typename Derivedq,
  148. typename Derivedc,
  149. typename Scalar,
  150. typename Derivedn>
  151. IGL_INLINE void igl::pseudonormal_test(
  152. const Eigen::MatrixBase<DerivedV> & V,
  153. const Eigen::MatrixBase<DerivedF> & E,
  154. const Eigen::MatrixBase<DerivedEN> & EN,
  155. const Eigen::MatrixBase<DerivedVN> & VN,
  156. const Eigen::MatrixBase<Derivedq> & q,
  157. const int e,
  158. Eigen::PlainObjectBase<Derivedc> & c,
  159. Scalar & s,
  160. Eigen::PlainObjectBase<Derivedn> & n)
  161. {
  162. static_assert(DerivedV::ColsAtCompileTime == 2 || DerivedV::ColsAtCompileTime == Eigen::Dynamic,"V must either have 2 or Dynamic columns");
  163. static_assert(DerivedEN::ColsAtCompileTime == 2 || DerivedEN::ColsAtCompileTime == Eigen::Dynamic,"EN must either have 2 or Dynamic columns");
  164. static_assert(DerivedVN::ColsAtCompileTime == 2 || DerivedVN::ColsAtCompileTime == Eigen::Dynamic,"VN must either have 2 or Dynamic columns");
  165. static_assert(
  166. Derivedc::ColsAtCompileTime*Derivedc::RowsAtCompileTime == 2 ||
  167. Derivedc::ColsAtCompileTime*Derivedc::RowsAtCompileTime == Eigen::Dynamic,"c must be size 2 or Dynamic");
  168. static_assert(
  169. Derivedq::ColsAtCompileTime*Derivedq::RowsAtCompileTime == 2 ||
  170. Derivedq::ColsAtCompileTime*Derivedq::RowsAtCompileTime == Eigen::Dynamic,"q must be size 2 or Dynamic");
  171. static_assert(
  172. Derivedn::ColsAtCompileTime*Derivedn::RowsAtCompileTime == 2 ||
  173. Derivedn::ColsAtCompileTime*Derivedn::RowsAtCompileTime == Eigen::Dynamic,"q must be size 2 or Dynamic");
  174. const auto & qc = q-c;
  175. const double len = (V.row(E(e,1))-V.row(E(e,0))).norm();
  176. // barycentric coordinates
  177. // this .head() nonsense is for "ridiculus" templates instantiations that AABB
  178. // needs to compile
  179. Eigen::Matrix<Scalar,1,2>
  180. b((c-V.row(E(e,1))).norm()/len,(c-V.row(E(e,0))).norm()/len);
  181. //b((c-V.row(E(e,1)).head(c.size())).norm()/len,(c-V.row(E(e,0)).head(c.size())).norm()/len);
  182. // Determine which normal to use
  183. const double epsilon = 1e-12;
  184. const int type = (b.array()<=epsilon).template cast<int>().sum();
  185. switch(type)
  186. {
  187. case 1:
  188. // Find vertex
  189. for(int x = 0;x<2;x++)
  190. {
  191. if(b(x)>epsilon)
  192. {
  193. n = VN.row(E(e,x)).head(2);
  194. break;
  195. }
  196. }
  197. break;
  198. default:
  199. assert(false && "all barycentric coords zero.");
  200. case 0:
  201. n = EN.row(e).head(2);
  202. break;
  203. }
  204. s = (qc.dot(n) >= 0 ? 1. : -1.);
  205. }
  206. #ifdef IGL_STATIC_LIBRARY
  207. // Explicit template instantiation
  208. // generated by autoexplicit.sh
  209. template void igl::pseudonormal_test<Eigen::Matrix<double, -1, 3, 0, -1, 3>, Eigen::Matrix<int, -1, 3, 0, -1, 3>, Eigen::Matrix<double, -1, 3, 0, -1, 3>, Eigen::Matrix<double, -1, 3, 0, -1, 3>, Eigen::Matrix<double, -1, 3, 0, -1, 3>, Eigen::Matrix<int, -1, 1, 0, -1, 1>, Eigen::Matrix<double, 1, 3, 1, 1, 3>, Eigen::Matrix<double, 1, 3, 1, 1, 3>, double, Eigen::Matrix<double, 1, 3, 1, 1, 3> >(Eigen::MatrixBase<Eigen::Matrix<double, -1, 3, 0, -1, 3> > const&, Eigen::MatrixBase<Eigen::Matrix<int, -1, 3, 0, -1, 3> > const&, Eigen::MatrixBase<Eigen::Matrix<double, -1, 3, 0, -1, 3> > const&, Eigen::MatrixBase<Eigen::Matrix<double, -1, 3, 0, -1, 3> > const&, Eigen::MatrixBase<Eigen::Matrix<double, -1, 3, 0, -1, 3> > const&, Eigen::MatrixBase<Eigen::Matrix<int, -1, 1, 0, -1, 1> > const&, Eigen::MatrixBase<Eigen::Matrix<double, 1, 3, 1, 1, 3> > const&, int, Eigen::PlainObjectBase<Eigen::Matrix<double, 1, 3, 1, 1, 3> >&, double&, Eigen::PlainObjectBase<Eigen::Matrix<double, 1, 3, 1, 1, 3> >&);
  210. // generated by autoexplicit.sh
  211. template void igl::pseudonormal_test<Eigen::Matrix<double, -1, 2, 0, -1, 2>, Eigen::Matrix<int, -1, 2, 0, -1, 2>, Eigen::Matrix<double, -1, 2, 0, -1, 2>, Eigen::Matrix<double, -1, 2, 0, -1, 2>, Eigen::Matrix<double, 1, 2, 1, 1, 2>, Eigen::Matrix<double, 1, 2, 1, 1, 2>, double, Eigen::Matrix<double, 1, 2, 1, 1, 2> >(Eigen::MatrixBase<Eigen::Matrix<double, -1, 2, 0, -1, 2> > const&, Eigen::MatrixBase<Eigen::Matrix<int, -1, 2, 0, -1, 2> > const&, Eigen::MatrixBase<Eigen::Matrix<double, -1, 2, 0, -1, 2> > const&, Eigen::MatrixBase<Eigen::Matrix<double, -1, 2, 0, -1, 2> > const&, Eigen::MatrixBase<Eigen::Matrix<double, 1, 2, 1, 1, 2> > const&, int, Eigen::PlainObjectBase<Eigen::Matrix<double, 1, 2, 1, 1, 2> >&, double&, Eigen::PlainObjectBase<Eigen::Matrix<double, 1, 2, 1, 1, 2> >&);
  212. // generated by autoexplicit.sh
  213. template void igl::pseudonormal_test<Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<double, -1, 2, 0, -1, 2>, Eigen::Matrix<double, -1, 2, 0, -1, 2>, Eigen::Matrix<double, 1, 2, 1, 1, 2>, Eigen::Matrix<double, 1, 2, 1, 1, 2>, double, Eigen::Matrix<double, 1, 2, 1, 1, 2> >(Eigen::MatrixBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, Eigen::MatrixBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, Eigen::MatrixBase<Eigen::Matrix<double, -1, 2, 0, -1, 2> > const&, Eigen::MatrixBase<Eigen::Matrix<double, -1, 2, 0, -1, 2> > const&, Eigen::MatrixBase<Eigen::Matrix<double, 1, 2, 1, 1, 2> > const&, int, Eigen::PlainObjectBase<Eigen::Matrix<double, 1, 2, 1, 1, 2> >&, double&, Eigen::PlainObjectBase<Eigen::Matrix<double, 1, 2, 1, 1, 2> >&);
  214. // NEW
  215. template void igl::pseudonormal_test<Eigen::Matrix<float, -1, 3, 1, -1, 3>, Eigen::Matrix<int, -1, 3, 1, -1, 3>, Eigen::Matrix<float, -1, -1, 0, -1, -1>, Eigen::Matrix<float, -1, -1, 0, -1, -1>, Eigen::Matrix<float, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, 1, 0, -1, 1>, Eigen::Matrix<float, 1, 3, 1, 1, 3>, Eigen::Matrix<float, 1, 3, 1, 1, 3>, float, Eigen::Matrix<float, 1, 3, 1, 1, 3> >(Eigen::MatrixBase<Eigen::Matrix<float, -1, 3, 1, -1, 3> > const&, Eigen::MatrixBase<Eigen::Matrix<int, -1, 3, 1, -1, 3> > const&, Eigen::MatrixBase<Eigen::Matrix<float, -1, -1, 0, -1, -1> > const&, Eigen::MatrixBase<Eigen::Matrix<float, -1, -1, 0, -1, -1> > const&, Eigen::MatrixBase<Eigen::Matrix<float, -1, -1, 0, -1, -1> > const&, Eigen::MatrixBase<Eigen::Matrix<int, -1, 1, 0, -1, 1> > const&, Eigen::MatrixBase<Eigen::Matrix<float, 1, 3, 1, 1, 3> > const&, int, Eigen::PlainObjectBase<Eigen::Matrix<float, 1, 3, 1, 1, 3> >&, float&, Eigen::PlainObjectBase<Eigen::Matrix<float, 1, 3, 1, 1, 3> >&);
  216. template void igl::pseudonormal_test<Eigen::Matrix<float, -1, 3, 0, -1, 3>, Eigen::Matrix<int, -1, 3, 0, -1, 3>, Eigen::Matrix<float, -1, -1, 0, -1, -1>, Eigen::Matrix<float, -1, -1, 0, -1, -1>, Eigen::Matrix<float, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, 1, 0, -1, 1>, Eigen::Matrix<float, 1, 3, 1, 1, 3>, Eigen::Matrix<float, 1, 3, 1, 1, 3>, float, Eigen::Matrix<float, 1, 3, 1, 1, 3> >(Eigen::MatrixBase<Eigen::Matrix<float, -1, 3, 0, -1, 3> > const&, Eigen::MatrixBase<Eigen::Matrix<int, -1, 3, 0, -1, 3> > const&, Eigen::MatrixBase<Eigen::Matrix<float, -1, -1, 0, -1, -1> > const&, Eigen::MatrixBase<Eigen::Matrix<float, -1, -1, 0, -1, -1> > const&, Eigen::MatrixBase<Eigen::Matrix<float, -1, -1, 0, -1, -1> > const&, Eigen::MatrixBase<Eigen::Matrix<int, -1, 1, 0, -1, 1> > const&, Eigen::MatrixBase<Eigen::Matrix<float, 1, 3, 1, 1, 3> > const&, int, Eigen::PlainObjectBase<Eigen::Matrix<float, 1, 3, 1, 1, 3> >&, float&, Eigen::PlainObjectBase<Eigen::Matrix<float, 1, 3, 1, 1, 3> >&);
  217. template void igl::pseudonormal_test<Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<double, 1, 2, 1, 1, 2>, Eigen::Matrix<double, 1, 2, 1, 1, 2>, double, Eigen::Matrix<double, 1, 2, 1, 1, 2> >(Eigen::MatrixBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, Eigen::MatrixBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, Eigen::MatrixBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, Eigen::MatrixBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, Eigen::MatrixBase<Eigen::Matrix<double, 1, 2, 1, 1, 2> > const&, int, Eigen::PlainObjectBase<Eigen::Matrix<double, 1, 2, 1, 1, 2> >&, double&, Eigen::PlainObjectBase<Eigen::Matrix<double, 1, 2, 1, 1, 2> >&);
  218. // OLD
  219. template void igl::pseudonormal_test<Eigen::Matrix<double, -1, 3, 1, -1, 3>, Eigen::Matrix<int, -1, 3, 1, -1, 3>, Eigen::Matrix<double, -1, 3, 0, -1, 3>, Eigen::Matrix<double, -1, 3, 0, -1, 3>, Eigen::Matrix<double, -1, 3, 0, -1, 3>, Eigen::Matrix<int, -1, 1, 0, -1, 1>, Eigen::Matrix<double, 1, 3, 1, 1, 3>, Eigen::Matrix<double, 1, 3, 1, 1, 3>, double, Eigen::Matrix<double, 1, 3, 1, 1, 3> >(Eigen::MatrixBase<Eigen::Matrix<double, -1, 3, 1, -1, 3> > const&, Eigen::MatrixBase<Eigen::Matrix<int, -1, 3, 1, -1, 3> > const&, Eigen::MatrixBase<Eigen::Matrix<double, -1, 3, 0, -1, 3> > const&, Eigen::MatrixBase<Eigen::Matrix<double, -1, 3, 0, -1, 3> > const&, Eigen::MatrixBase<Eigen::Matrix<double, -1, 3, 0, -1, 3> > const&, Eigen::MatrixBase<Eigen::Matrix<int, -1, 1, 0, -1, 1> > const&, Eigen::MatrixBase<Eigen::Matrix<double, 1, 3, 1, 1, 3> > const&, int, Eigen::PlainObjectBase<Eigen::Matrix<double, 1, 3, 1, 1, 3> >&, double&, Eigen::PlainObjectBase<Eigen::Matrix<double, 1, 3, 1, 1, 3> >&);
  220. template void igl::pseudonormal_test<Eigen::Matrix<float, -1, 3, 0, -1, 3>, Eigen::Matrix<int, -1, 3, 0, -1, 3>, Eigen::Matrix<float, -1, 3, 0, -1, 3>, Eigen::Matrix<float, -1, 3, 0, -1, 3>, Eigen::Matrix<float, -1, 3, 0, -1, 3>, Eigen::Matrix<int, -1, 1, 0, -1, 1>, Eigen::Matrix<float, 1, 3, 1, 1, 3>, Eigen::Matrix<float, 1, 3, 1, 1, 3>, float, Eigen::Matrix<float, 1, 3, 1, 1, 3> >(Eigen::MatrixBase<Eigen::Matrix<float, -1, 3, 0, -1, 3> > const&, Eigen::MatrixBase<Eigen::Matrix<int, -1, 3, 0, -1, 3> > const&, Eigen::MatrixBase<Eigen::Matrix<float, -1, 3, 0, -1, 3> > const&, Eigen::MatrixBase<Eigen::Matrix<float, -1, 3, 0, -1, 3> > const&, Eigen::MatrixBase<Eigen::Matrix<float, -1, 3, 0, -1, 3> > const&, Eigen::MatrixBase<Eigen::Matrix<int, -1, 1, 0, -1, 1> > const&, Eigen::MatrixBase<Eigen::Matrix<float, 1, 3, 1, 1, 3> > const&, int, Eigen::PlainObjectBase<Eigen::Matrix<float, 1, 3, 1, 1, 3> >&, float&, Eigen::PlainObjectBase<Eigen::Matrix<float, 1, 3, 1, 1, 3> >&);
  221. template void igl::pseudonormal_test<Eigen::Matrix<float, -1, 3, 1, -1, 3>, Eigen::Matrix<int, -1, 3, 1, -1, 3>, Eigen::Matrix<float, -1, 3, 0, -1, 3>, Eigen::Matrix<float, -1, 3, 0, -1, 3>, Eigen::Matrix<float, -1, 3, 0, -1, 3>, Eigen::Matrix<int, -1, 1, 0, -1, 1>, Eigen::Matrix<float, 1, 3, 1, 1, 3>, Eigen::Matrix<float, 1, -1, 1, 1, -1>, float, Eigen::Matrix<float, 1, 3, 1, 1, 3> >(Eigen::MatrixBase<Eigen::Matrix<float, -1, 3, 1, -1, 3> > const&, Eigen::MatrixBase<Eigen::Matrix<int, -1, 3, 1, -1, 3> > const&, Eigen::MatrixBase<Eigen::Matrix<float, -1, 3, 0, -1, 3> > const&, Eigen::MatrixBase<Eigen::Matrix<float, -1, 3, 0, -1, 3> > const&, Eigen::MatrixBase<Eigen::Matrix<float, -1, 3, 0, -1, 3> > const&, Eigen::MatrixBase<Eigen::Matrix<int, -1, 1, 0, -1, 1> > const&, Eigen::MatrixBase<Eigen::Matrix<float, 1, 3, 1, 1, 3> > const&, int, Eigen::PlainObjectBase<Eigen::Matrix<float, 1, -1, 1, 1, -1> >&, float&, Eigen::PlainObjectBase<Eigen::Matrix<float, 1, 3, 1, 1, 3> >&);
  222. template void igl::pseudonormal_test<Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<double, -1, 3, 0, -1, 3>, Eigen::Matrix<double, -1, 3, 0, -1, 3>, Eigen::Matrix<double, -1, 3, 0, -1, 3>, Eigen::Matrix<int, -1, 1, 0, -1, 1>, Eigen::Matrix<double, 1, 3, 1, 1, 3>, Eigen::Matrix<double, 1, -1, 1, 1, -1>, double, Eigen::Matrix<double, 1, 3, 1, 1, 3> >(Eigen::MatrixBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, Eigen::MatrixBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, Eigen::MatrixBase<Eigen::Matrix<double, -1, 3, 0, -1, 3> > const&, Eigen::MatrixBase<Eigen::Matrix<double, -1, 3, 0, -1, 3> > const&, Eigen::MatrixBase<Eigen::Matrix<double, -1, 3, 0, -1, 3> > const&, Eigen::MatrixBase<Eigen::Matrix<int, -1, 1, 0, -1, 1> > const&, Eigen::MatrixBase<Eigen::Matrix<double, 1, 3, 1, 1, 3> > const&, int, Eigen::PlainObjectBase<Eigen::Matrix<double, 1, -1, 1, 1, -1> >&, double&, Eigen::PlainObjectBase<Eigen::Matrix<double, 1, 3, 1, 1, 3> >&);
  223. template void igl::pseudonormal_test<Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<double, -1, 3, 0, -1, 3>, Eigen::Matrix<double, -1, 3, 0, -1, 3>, Eigen::Matrix<double, -1, 3, 0, -1, 3>, Eigen::Matrix<int, -1, 1, 0, -1, 1>, Eigen::Block<Eigen::Matrix<double, -1, -1, 0, -1, -1>, 1, -1, false>, Eigen::Matrix<double, 1, 3, 1, 1, 3>, double, Eigen::Matrix<double, 1, 3, 1, 1, 3> >(Eigen::MatrixBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, Eigen::MatrixBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, Eigen::MatrixBase<Eigen::Matrix<double, -1, 3, 0, -1, 3> > const&, Eigen::MatrixBase<Eigen::Matrix<double, -1, 3, 0, -1, 3> > const&, Eigen::MatrixBase<Eigen::Matrix<double, -1, 3, 0, -1, 3> > const&, Eigen::MatrixBase<Eigen::Matrix<int, -1, 1, 0, -1, 1> > const&, Eigen::MatrixBase<Eigen::Block<Eigen::Matrix<double, -1, -1, 0, -1, -1>, 1, -1, false> > const&, int, Eigen::PlainObjectBase<Eigen::Matrix<double, 1, 3, 1, 1, 3> >&, double&, Eigen::PlainObjectBase<Eigen::Matrix<double, 1, 3, 1, 1, 3> >&);
  224. template void igl::pseudonormal_test<Eigen::Matrix<float, -1, 3, 1, -1, 3>, Eigen::Matrix<int, -1, 3, 1, -1, 3>, Eigen::Matrix<float, -1, 3, 0, -1, 3>, Eigen::Matrix<float, -1, 3, 0, -1, 3>, Eigen::Matrix<float, -1, 3, 0, -1, 3>, Eigen::Matrix<int, -1, 1, 0, -1, 1>, Eigen::Matrix<float, 1, 3, 1, 1, 3>, Eigen::Matrix<float, 1, 3, 1, 1, 3>, float, Eigen::Matrix<float, 1, 3, 1, 1, 3> >(Eigen::MatrixBase<Eigen::Matrix<float, -1, 3, 1, -1, 3> > const&, Eigen::MatrixBase<Eigen::Matrix<int, -1, 3, 1, -1, 3> > const&, Eigen::MatrixBase<Eigen::Matrix<float, -1, 3, 0, -1, 3> > const&, Eigen::MatrixBase<Eigen::Matrix<float, -1, 3, 0, -1, 3> > const&, Eigen::MatrixBase<Eigen::Matrix<float, -1, 3, 0, -1, 3> > const&, Eigen::MatrixBase<Eigen::Matrix<int, -1, 1, 0, -1, 1> > const&, Eigen::MatrixBase<Eigen::Matrix<float, 1, 3, 1, 1, 3> > const&, int, Eigen::PlainObjectBase<Eigen::Matrix<float, 1, 3, 1, 1, 3> >&, float&, Eigen::PlainObjectBase<Eigen::Matrix<float, 1, 3, 1, 1, 3> >&);
  225. template void igl::pseudonormal_test<Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, 1, 0, -1, 1>, Eigen::Matrix<double, 1, 3, 1, 1, 3>, Eigen::Matrix<double, 1, 3, 1, 1, 3>, double, Eigen::Matrix<double, 1, 3, 1, 1, 3> >(Eigen::MatrixBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, Eigen::MatrixBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, Eigen::MatrixBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, Eigen::MatrixBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, Eigen::MatrixBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, Eigen::MatrixBase<Eigen::Matrix<int, -1, 1, 0, -1, 1> > const&, Eigen::MatrixBase<Eigen::Matrix<double, 1, 3, 1, 1, 3> > const&, int, Eigen::PlainObjectBase<Eigen::Matrix<double, 1, 3, 1, 1, 3> >&, double&, Eigen::PlainObjectBase<Eigen::Matrix<double, 1, 3, 1, 1, 3> >&);
  226. template void igl::pseudonormal_test<Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<double, -1, 3, 0, -1, 3>, Eigen::Matrix<double, -1, 3, 0, -1, 3>, Eigen::Matrix<double, -1, 3, 0, -1, 3>, Eigen::Matrix<int, -1, 1, 0, -1, 1>, Eigen::Matrix<double, 1, 3, 1, 1, 3>, Eigen::Matrix<double, 1, 3, 1, 1, 3>, double, Eigen::Matrix<double, 1, 3, 1, 1, 3> >(Eigen::MatrixBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, Eigen::MatrixBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, Eigen::MatrixBase<Eigen::Matrix<double, -1, 3, 0, -1, 3> > const&, Eigen::MatrixBase<Eigen::Matrix<double, -1, 3, 0, -1, 3> > const&, Eigen::MatrixBase<Eigen::Matrix<double, -1, 3, 0, -1, 3> > const&, Eigen::MatrixBase<Eigen::Matrix<int, -1, 1, 0, -1, 1> > const&, Eigen::MatrixBase<Eigen::Matrix<double, 1, 3, 1, 1, 3> > const&, int, Eigen::PlainObjectBase<Eigen::Matrix<double, 1, 3, 1, 1, 3> >&, double&, Eigen::PlainObjectBase<Eigen::Matrix<double, 1, 3, 1, 1, 3> >&);
  227. #endif