outer_facet.cpp 9.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163
  1. // This file is part of libigl, a simple c++ geometry processing library.
  2. //
  3. // Copyright (C) 2015 Qingnan Zhou <qnzhou@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 "outer_facet.h"
  9. #include "outer_element.h"
  10. #include "order_facets_around_edge.h"
  11. #include <algorithm>
  12. #include <CGAL/Exact_predicates_exact_constructions_kernel.h>
  13. template<
  14. typename DerivedV,
  15. typename DerivedF,
  16. typename DerivedI,
  17. typename IndexType
  18. >
  19. IGL_INLINE void igl::copyleft::cgal::outer_facet(
  20. const Eigen::PlainObjectBase<DerivedV> & V,
  21. const Eigen::PlainObjectBase<DerivedF> & F,
  22. const Eigen::PlainObjectBase<DerivedI> & I,
  23. IndexType & f,
  24. bool & flipped) {
  25. // Algorithm:
  26. //
  27. // 1. Find an outer edge (s, d).
  28. //
  29. // 2. Order adjacent facets around this edge. Because the edge is an
  30. // outer edge, there exists a plane passing through it such that all its
  31. // adjacent facets lie on the same side. The implementation of
  32. // order_facets_around_edge() will find a natural start facet such that
  33. // The first and last facets according to this order are on the outside.
  34. //
  35. // 3. Because the vertex s is an outer vertex by construction (see
  36. // implemnetation of outer_edge()). The first adjacent facet is facing
  37. // outside (i.e. flipped=false) if it has positive X normal component.
  38. // If it has zero normal component, it is facing outside if it contains
  39. // directed edge (s, d).
  40. //typedef typename DerivedV::Scalar Scalar;
  41. typedef typename DerivedV::Index Index;
  42. Index s,d;
  43. Eigen::Matrix<Index,Eigen::Dynamic,1> incident_faces;
  44. outer_edge(V, F, I, s, d, incident_faces);
  45. assert(incident_faces.size() > 0);
  46. auto convert_to_signed_index = [&](size_t fid) -> int{
  47. if ((F(fid, 0) == s && F(fid, 1) == d) ||
  48. (F(fid, 1) == s && F(fid, 2) == d) ||
  49. (F(fid, 2) == s && F(fid, 0) == d) ) {
  50. return int(fid+1) * -1;
  51. } else {
  52. return int(fid+1);
  53. }
  54. };
  55. auto signed_index_to_index = [&](int signed_id) -> size_t {
  56. return size_t(abs(signed_id) - 1);
  57. };
  58. std::vector<int> adj_faces(incident_faces.size());
  59. std::transform(incident_faces.data(),
  60. incident_faces.data() + incident_faces.size(),
  61. adj_faces.begin(),
  62. convert_to_signed_index);
  63. DerivedV pivot_point = V.row(s);
  64. pivot_point(0, 0) += 1.0;
  65. Eigen::VectorXi order;
  66. order_facets_around_edge(V, F, s, d, adj_faces, pivot_point, order);
  67. f = signed_index_to_index(adj_faces[order[0]]);
  68. flipped = adj_faces[order[0]] > 0;
  69. }
  70. template<
  71. typename DerivedV,
  72. typename DerivedF,
  73. typename DerivedN,
  74. typename DerivedI,
  75. typename IndexType
  76. >
  77. IGL_INLINE void igl::copyleft::cgal::outer_facet(
  78. const Eigen::PlainObjectBase<DerivedV> & V,
  79. const Eigen::PlainObjectBase<DerivedF> & F,
  80. const Eigen::PlainObjectBase<DerivedN> & N,
  81. const Eigen::PlainObjectBase<DerivedI> & I,
  82. IndexType & f,
  83. bool & flipped) {
  84. // Algorithm:
  85. // Find an outer edge.
  86. // Find the incident facet with the largest absolute X normal component.
  87. // If there is a tie, keep the one with positive X component.
  88. // If there is still a tie, pick the face with the larger signed index
  89. // (flipped face has negative index).
  90. typedef typename DerivedV::Scalar Scalar;
  91. typedef typename DerivedV::Index Index;
  92. const size_t INVALID = std::numeric_limits<size_t>::max();
  93. Index v1,v2;
  94. Eigen::Matrix<Index,Eigen::Dynamic,1> incident_faces;
  95. outer_edge(V, F, I, v1, v2, incident_faces);
  96. assert(incident_faces.size() > 0);
  97. auto generic_fabs = [&](const Scalar& val) -> const Scalar {
  98. if (val >= 0) return val;
  99. else return -val;
  100. };
  101. Scalar max_nx = 0;
  102. size_t outer_fid = INVALID;
  103. const size_t num_incident_faces = incident_faces.size();
  104. for (size_t i=0; i<num_incident_faces; i++)
  105. {
  106. const auto& fid = incident_faces(i);
  107. const Scalar nx = N(fid, 0);
  108. if (outer_fid == INVALID) {
  109. max_nx = nx;
  110. outer_fid = fid;
  111. } else {
  112. if (generic_fabs(nx) > generic_fabs(max_nx)) {
  113. max_nx = nx;
  114. outer_fid = fid;
  115. } else if (nx == -max_nx && nx > 0) {
  116. max_nx = nx;
  117. outer_fid = fid;
  118. } else if (nx == max_nx) {
  119. if ((max_nx >= 0 && outer_fid < fid) ||
  120. (max_nx < 0 && outer_fid > fid)) {
  121. max_nx = nx;
  122. outer_fid = fid;
  123. }
  124. }
  125. }
  126. }
  127. assert(outer_fid != INVALID);
  128. f = outer_fid;
  129. flipped = max_nx < 0;
  130. }
  131. #ifdef IGL_STATIC_LIBRARY
  132. // Explicit template specialization
  133. #include <CGAL/Exact_predicates_exact_constructions_kernel.h>
  134. #include <CGAL/Exact_predicates_inexact_constructions_kernel.h>
  135. template void igl::copyleft::cgal::outer_facet<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<long, -1, 1, 0, -1, 1>, int>(Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 3, 0, -1, 3> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 3, 0, -1, 3> > const&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 3, 0, -1, 3> > const&, Eigen::PlainObjectBase<Eigen::Matrix<long, -1, 1, 0, -1, 1> > const&, int&, bool&);
  136. template void igl::copyleft::cgal::outer_facet<Eigen::Matrix<double, -1, -1, 1, -1, -1>, Eigen::Matrix<int, -1, -1, 1, -1, -1>, Eigen::Matrix<double, -1, -1, 1, -1, -1>, Eigen::Matrix<int, -1, -1, 1, -1, -1>, unsigned long>(Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 1, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 1, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 1, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 1, -1, -1> > const&, unsigned long&, bool&);
  137. template void igl::copyleft::cgal::outer_facet<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<int, -1, 1, 0, -1, 1>, int>(Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 3, 0, -1, 3> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 1, 0, -1, 1> > const&, int&, bool&);
  138. template void igl::copyleft::cgal::outer_facet<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>, int>(Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 1, 0, -1, 1> > const&, int&, bool&);
  139. template void igl::copyleft::cgal::outer_facet<Eigen::Matrix<CGAL::Lazy_exact_nt<CGAL::Gmpq>, -1, 3, 0, -1, 3>, Eigen::Matrix<int, -1, 3, 0, -1, 3>, Eigen::Matrix<long, -1, 1, 0, -1, 1>, int>(Eigen::PlainObjectBase<Eigen::Matrix<CGAL::Lazy_exact_nt<CGAL::Gmpq>, -1, 3, 0, -1, 3> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 3, 0, -1, 3> > const&, Eigen::PlainObjectBase<Eigen::Matrix<long, -1, 1, 0, -1, 1> > const&, int&, bool&);
  140. template void igl::copyleft::cgal::outer_facet<Eigen::Matrix<double, -1, 3, 0, -1, 3>, Eigen::Matrix<int, -1, 3, 0, -1, 3>, Eigen::Matrix<long, -1, 1, 0, -1, 1>, int>(Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 3, 0, -1, 3> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 3, 0, -1, 3> > const&, Eigen::PlainObjectBase<Eigen::Matrix<long, -1, 1, 0, -1, 1> > const&, int&, bool&);
  141. template void igl::copyleft::cgal::outer_facet<Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, 1, 0, -1, 1>, int>(Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 1, 0, -1, 1> > const&, int&, bool&);
  142. template void igl::copyleft::cgal::outer_facet<Eigen::Matrix<CGAL::Lazy_exact_nt<CGAL::Gmpq>, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, 1, 0, -1, 1>, unsigned long>(Eigen::PlainObjectBase<Eigen::Matrix<CGAL::Lazy_exact_nt<CGAL::Gmpq>, -1, -1, 0, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 1, 0, -1, 1> > const&, unsigned long&, bool&);
  143. template void igl::copyleft::cgal::outer_facet<Eigen::Matrix<CGAL::Lazy_exact_nt<CGAL::Gmpq>, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, 1, 0, -1, 1>, int>(Eigen::PlainObjectBase<Eigen::Matrix<CGAL::Lazy_exact_nt<CGAL::Gmpq>, -1, -1, 0, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 1, 0, -1, 1> > const&, int&, bool&);
  144. #endif