intrinsic_delaunay_triangulation.cpp 8.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198
  1. // This file is part of libigl, a simple c++ geometry processing library.
  2. //
  3. // Copyright (C) 2018 Alec Jacobson <alecjacobson@gmail.com>
  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 "intrinsic_delaunay_triangulation.h"
  9. #include "is_intrinsic_delaunay.h"
  10. #include "tan_half_angle.h"
  11. #include "unique_edge_map.h"
  12. #include "flip_edge.h"
  13. #include "EPS.h"
  14. #include <iostream>
  15. #include <queue>
  16. #include <map>
  17. template <
  18. typename Derivedl_in,
  19. typename DerivedF_in,
  20. typename Derivedl,
  21. typename DerivedF>
  22. IGL_INLINE void igl::intrinsic_delaunay_triangulation(
  23. const Eigen::MatrixBase<Derivedl_in> & l_in,
  24. const Eigen::MatrixBase<DerivedF_in> & F_in,
  25. Eigen::PlainObjectBase<Derivedl> & l,
  26. Eigen::PlainObjectBase<DerivedF> & F)
  27. {
  28. typedef Eigen::Matrix<typename DerivedF::Scalar,Eigen::Dynamic,2> MatrixX2I;
  29. typedef Eigen::Matrix<typename DerivedF::Scalar,Eigen::Dynamic,1> VectorXI;
  30. MatrixX2I E,uE;
  31. VectorXI EMAP;
  32. std::vector<std::vector<typename DerivedF::Scalar> > uE2E;
  33. return intrinsic_delaunay_triangulation(l_in,F_in,l,F,E,uE,EMAP,uE2E);
  34. }
  35. template <
  36. typename Derivedl_in,
  37. typename DerivedF_in,
  38. typename Derivedl,
  39. typename DerivedF,
  40. typename DerivedE,
  41. typename DeriveduE,
  42. typename DerivedEMAP,
  43. typename uE2EType>
  44. IGL_INLINE void igl::intrinsic_delaunay_triangulation(
  45. const Eigen::MatrixBase<Derivedl_in> & l_in,
  46. const Eigen::MatrixBase<DerivedF_in> & F_in,
  47. Eigen::PlainObjectBase<Derivedl> & l,
  48. Eigen::PlainObjectBase<DerivedF> & F,
  49. Eigen::PlainObjectBase<DerivedE> & E,
  50. Eigen::PlainObjectBase<DeriveduE> & uE,
  51. Eigen::PlainObjectBase<DerivedEMAP> & EMAP,
  52. std::vector<std::vector<uE2EType> > & uE2E)
  53. {
  54. igl::unique_edge_map(F_in, E, uE, EMAP, uE2E);
  55. // We're going to work in place
  56. l = l_in;
  57. F = F_in;
  58. typedef typename DerivedF::Scalar Index;
  59. typedef typename Derivedl::Scalar Scalar;
  60. const Index num_faces = F.rows();
  61. // Vector is faster than queue...
  62. std::vector<Index> Q;
  63. Q.reserve(uE2E.size());
  64. for (size_t uei=0; uei<uE2E.size(); uei++)
  65. {
  66. Q.push_back(uei);
  67. }
  68. // I tried using a "delaunay_since = iter" flag to avoid duplicates, but there
  69. // was no speed up.
  70. while(!Q.empty())
  71. {
  72. #ifdef IGL_INTRINSIC_DELAUNAY_TRIANGULATION_DEBUG
  73. // Expensive sanity check
  74. {
  75. Eigen::Matrix<bool,Eigen::Dynamic,1> inQ(uE2E.size(),1);
  76. inQ.setConstant(false);
  77. for(const auto uei : Q)
  78. {
  79. inQ(uei) = true;
  80. }
  81. for (Index uei=0; uei<uE2E.size(); uei++)
  82. {
  83. if(!inQ(uei) && !is_intrinsic_delaunay(l,uE2E,num_faces,uei))
  84. {
  85. std::cout<<" "<<uei<<" might never be fixed!"<<std::endl;
  86. }
  87. }
  88. }
  89. #endif
  90. const Index uei = Q.back();
  91. Q.pop_back();
  92. if (uE2E[uei].size() == 2)
  93. {
  94. if(!is_intrinsic_delaunay(l,uE2E,num_faces,uei))
  95. {
  96. // update l just before flipping edge
  97. // . //
  98. // /|\ //
  99. // a/ | \d //
  100. // / e \ //
  101. // / | \ //
  102. // .----|-f--. //
  103. // \ | / //
  104. // \ | / //
  105. // b\α|δ/c //
  106. // \|/ //
  107. // . //
  108. // Annotated from flip_edge:
  109. // Edge to flip [v1,v2] --> [v3,v4]
  110. // Before:
  111. // F(f1,:) = [v1,v2,v4] // in some cyclic order
  112. // F(f2,:) = [v1,v3,v2] // in some cyclic order
  113. // After:
  114. // F(f1,:) = [v1,v3,v4] // in *this* order
  115. // F(f2,:) = [v2,v4,v3] // in *this* order
  116. //
  117. // v1 v1
  118. // /|\ / \
  119. // c/ | \b c/f1 \b
  120. // v3 /f2|f1\ v4 => v3 /__f__\ v4
  121. // \ e / \ f2 /
  122. // d\ | /a d\ /a
  123. // \|/ \ /
  124. // v2 v2
  125. //
  126. // Compute intrinsic length of oppposite edge
  127. assert(uE2E[uei].size() == 2 && "edge should have 2 incident faces");
  128. const Index f1 = uE2E[uei][0]%num_faces;
  129. const Index f2 = uE2E[uei][1]%num_faces;
  130. const Index c1 = uE2E[uei][0]/num_faces;
  131. const Index c2 = uE2E[uei][1]/num_faces;
  132. assert(c1 < 3);
  133. assert(c2 < 3);
  134. assert(f1 != f2);
  135. const Index v1 = F(f1, (c1+1)%3);
  136. const Index v2 = F(f1, (c1+2)%3);
  137. const Index v4 = F(f1, c1);
  138. const Index v3 = F(f2, c2);
  139. assert(F(f2, (c2+2)%3) == v1);
  140. assert(F(f2, (c2+1)%3) == v2);
  141. assert( std::abs(l(f1,c1)-l(f2,c2)) < igl::EPS<Scalar>() );
  142. const Scalar e = l(f1,c1);
  143. const Scalar a = l(f1,(c1+1)%3);
  144. const Scalar b = l(f1,(c1+2)%3);
  145. const Scalar c = l(f2,(c2+1)%3);
  146. const Scalar d = l(f2,(c2+2)%3);
  147. // tan(α/2)
  148. const Scalar tan_a_2= tan_half_angle(a,b,e);
  149. // tan(δ/2)
  150. const Scalar tan_d_2 = tan_half_angle(d,e,c);
  151. // tan((α+δ)/2)
  152. const Scalar tan_a_d_2 = (tan_a_2 + tan_d_2)/(1.0-tan_a_2*tan_d_2);
  153. // cos(α+δ)
  154. const Scalar cos_a_d =
  155. (1.0 - tan_a_d_2*tan_a_d_2)/(1.0+tan_a_d_2*tan_a_d_2);
  156. const Scalar f = sqrt(b*b + c*c - 2.0*b*c*cos_a_d);
  157. l(f1,0) = f;
  158. l(f1,1) = b;
  159. l(f1,2) = c;
  160. l(f2,0) = f;
  161. l(f2,1) = d;
  162. l(f2,2) = a;
  163. // Important to grab these indices _before_ calling flip_edges (they
  164. // will be correct after)
  165. const size_t e_24 = f1 + ((c1 + 1) % 3) * num_faces;
  166. const size_t e_41 = f1 + ((c1 + 2) % 3) * num_faces;
  167. const size_t e_13 = f2 + ((c2 + 1) % 3) * num_faces;
  168. const size_t e_32 = f2 + ((c2 + 2) % 3) * num_faces;
  169. const size_t ue_24 = EMAP(e_24);
  170. const size_t ue_41 = EMAP(e_41);
  171. const size_t ue_13 = EMAP(e_13);
  172. const size_t ue_32 = EMAP(e_32);
  173. flip_edge(F, E, uE, EMAP, uE2E, uei);
  174. Q.push_back(ue_24);
  175. Q.push_back(ue_41);
  176. Q.push_back(ue_13);
  177. Q.push_back(ue_32);
  178. }
  179. }
  180. }
  181. }
  182. #ifdef IGL_STATIC_LIBRARY
  183. // Explicit template instantiation
  184. // generated by autoexplicit.sh
  185. template void igl::intrinsic_delaunay_triangulation<Eigen::Matrix<double, -1, 3, 0, -1, 3>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1> >(Eigen::MatrixBase<Eigen::Matrix<double, -1, 3, 0, -1, 3> > const&, Eigen::MatrixBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> >&);
  186. // generated by autoexplicit.sh
  187. template void igl::intrinsic_delaunay_triangulation<Eigen::Matrix<double, -1, 3, 0, -1, 3>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<double, -1, 3, 0, -1, 3>, Eigen::Matrix<int, -1, -1, 0, -1, -1> >(Eigen::MatrixBase<Eigen::Matrix<double, -1, 3, 0, -1, 3> > const&, Eigen::MatrixBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 3, 0, -1, 3> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> >&);
  188. // generated by autoexplicit.sh
  189. template void igl::intrinsic_delaunay_triangulation<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<int, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, 1, 0, -1, 1>, int>(Eigen::MatrixBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, Eigen::MatrixBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 1, 0, -1, 1> >&, std::vector<std::vector<int, std::allocator<int> >, std::allocator<std::vector<int, std::allocator<int> > > >&);
  190. // generated by autoexplicit.sh
  191. template void igl::intrinsic_delaunay_triangulation<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<int, -1, -1, 0, -1, -1> >(Eigen::MatrixBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, Eigen::MatrixBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> >&);
  192. #endif