subdivide_segments.cpp 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137
  1. // This file is part of libigl, a simple c++ geometry processing library.
  2. //
  3. // Copyright (C) 2016 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 "subdivide_segments.h"
  9. #include "row_to_point.h"
  10. #include "assign_scalar.h"
  11. #include "../../unique.h"
  12. #include "../../list_to_matrix.h"
  13. #include <CGAL/Exact_predicates_exact_constructions_kernel.h>
  14. #include <CGAL/Segment_2.h>
  15. #include <CGAL/Point_2.h>
  16. #include <algorithm>
  17. #include <vector>
  18. template <
  19. typename DerivedV,
  20. typename DerivedE,
  21. typename Kernel,
  22. typename DerivedVI,
  23. typename DerivedEI,
  24. typename DerivedJ,
  25. typename DerivedIM>
  26. IGL_INLINE void igl::copyleft::cgal::subdivide_segments(
  27. const Eigen::PlainObjectBase<DerivedV> & V,
  28. const Eigen::PlainObjectBase<DerivedE> & E,
  29. const std::vector<std::vector<CGAL::Point_2<Kernel> > > & _steiner,
  30. Eigen::PlainObjectBase<DerivedVI> & VI,
  31. Eigen::PlainObjectBase<DerivedEI> & EI,
  32. Eigen::PlainObjectBase<DerivedJ> & J,
  33. Eigen::PlainObjectBase<DerivedIM> & IM)
  34. {
  35. using namespace Eigen;
  36. using namespace igl;
  37. using namespace std;
  38. // Exact scalar type
  39. typedef Kernel K;
  40. typedef typename Kernel::FT EScalar;
  41. typedef CGAL::Point_2<Kernel> Point_2;
  42. typedef Matrix<EScalar,Dynamic,Dynamic> MatrixXE;
  43. // non-const copy
  44. std::vector<std::vector<CGAL::Point_2<Kernel> > > steiner = _steiner;
  45. // Convert vertex positions to exact kernel
  46. MatrixXE VE(V.rows(),V.cols());
  47. for(int i = 0;i<V.rows();i++)
  48. {
  49. for(int j = 0;j<V.cols();j++)
  50. {
  51. VE(i,j) = V(i,j);
  52. }
  53. }
  54. // number of original vertices
  55. const int n = V.rows();
  56. // number of original segments
  57. const int m = E.rows();
  58. // now steiner contains lists of points (unsorted) for each edge. Sort them
  59. // and count total number of vertices and edges
  60. // new steiner points
  61. std::vector<Point_2> S;
  62. std::vector<std::vector<typename DerivedE::Scalar> > vEI;
  63. std::vector<typename DerivedJ::Scalar> vJ;
  64. for(int i = 0;i<m;i++)
  65. {
  66. {
  67. const Point_2 s = row_to_point<K>(VE,E(i,0));
  68. std::sort(
  69. steiner[i].begin(),
  70. steiner[i].end(),
  71. [&s](const Point_2 & A, const Point_2 & B)->bool
  72. {
  73. return (A-s).squared_length() < (B-s).squared_length();
  74. });
  75. }
  76. // remove duplicates
  77. steiner[i].erase(
  78. std::unique(steiner[i].begin(), steiner[i].end()),
  79. steiner[i].end());
  80. {
  81. int s = E(i,0);
  82. // legs to each steiner in order
  83. for(int j = 1;j<steiner[i].size()-1;j++)
  84. {
  85. int d = n+S.size();
  86. S.push_back(steiner[i][j]);
  87. vEI.push_back({s,d});
  88. vJ.push_back(i);
  89. s = d;
  90. }
  91. // don't forget last (which might only) leg
  92. vEI.push_back({s,E(i,1)});
  93. vJ.push_back(i);
  94. }
  95. }
  96. // potentially unnecessary copying ...
  97. VI.resize(n+S.size(),2);
  98. for(int i = 0;i<V.rows();i++)
  99. {
  100. for(int j = 0;j<V.cols();j++)
  101. {
  102. assign_scalar(V(i,j),VI(i,j));
  103. }
  104. }
  105. for(int i = 0;i<S.size();i++)
  106. {
  107. assign_scalar(S[i].x(),VI(n+i,0));
  108. assign_scalar(S[i].y(),VI(n+i,1));
  109. }
  110. list_to_matrix(vEI,EI);
  111. list_to_matrix(vJ,J);
  112. {
  113. // Find unique mapping
  114. std::vector<Point_2> vVES,_1;
  115. for(int i = 0;i<n;i++)
  116. {
  117. vVES.push_back(row_to_point<K>(VE,i));
  118. }
  119. vVES.insert(vVES.end(),S.begin(),S.end());
  120. std::vector<size_t> vA,vIM;
  121. igl::unique(vVES,_1,vA,vIM);
  122. // Push indices back into vVES
  123. for_each(vIM.data(),vIM.data()+vIM.size(),[&vA](size_t & i){i=vA[i];});
  124. list_to_matrix(vIM,IM);
  125. }
  126. }
  127. #ifdef IGL_STATIC_LIBRARY
  128. // Explicit template instantiation
  129. template void igl::copyleft::cgal::subdivide_segments<Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, CGAL::Epeck, Eigen::Matrix<CGAL::Epeck::FT, -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::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, std::vector<std::vector<CGAL::Point_2<CGAL::Epeck>, std::allocator<CGAL::Point_2<CGAL::Epeck> > >, std::allocator<std::vector<CGAL::Point_2<CGAL::Epeck>, std::allocator<CGAL::Point_2<CGAL::Epeck> > > > > const&, Eigen::PlainObjectBase<Eigen::Matrix<CGAL::Epeck::FT, -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> >&);
  130. template void igl::copyleft::cgal::subdivide_segments<Eigen::Matrix<CGAL::Epeck::FT, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, CGAL::Epeck, Eigen::Matrix<CGAL::Epeck::FT, -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::PlainObjectBase<Eigen::Matrix<CGAL::Epeck::FT, -1, -1, 0, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, std::vector<std::vector<CGAL::Point_2<CGAL::Epeck>, std::allocator<CGAL::Point_2<CGAL::Epeck> > >, std::allocator<std::vector<CGAL::Point_2<CGAL::Epeck>, std::allocator<CGAL::Point_2<CGAL::Epeck> > > > > const&, Eigen::PlainObjectBase<Eigen::Matrix<CGAL::Epeck::FT, -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> >&);
  131. #endif