random_points_on_mesh.cpp 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384
  1. // This file is part of libigl, a simple c++ geometry processing library.
  2. //
  3. // Copyright (C) 2014 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 "random_points_on_mesh.h"
  9. #include "doublearea.h"
  10. #include "cumsum.h"
  11. #include "histc.h"
  12. #include "matlab_format.h"
  13. #include <iostream>
  14. #include <cassert>
  15. template <typename DerivedV, typename DerivedF, typename DerivedB, typename DerivedFI>
  16. IGL_INLINE void igl::random_points_on_mesh(
  17. const int n,
  18. const Eigen::PlainObjectBase<DerivedV > & V,
  19. const Eigen::PlainObjectBase<DerivedF > & F,
  20. Eigen::PlainObjectBase<DerivedB > & B,
  21. Eigen::PlainObjectBase<DerivedFI > & FI)
  22. {
  23. using namespace Eigen;
  24. using namespace std;
  25. typedef typename DerivedV::Scalar Scalar;
  26. typedef Matrix<Scalar,Dynamic,1> VectorXs;
  27. VectorXs A;
  28. doublearea(V,F,A);
  29. A /= A.array().sum();
  30. // Should be traingle mesh. Although Turk's method 1 generalizes...
  31. assert(F.cols() == 3);
  32. VectorXs C;
  33. VectorXs A0(A.size()+1);
  34. A0(0) = 0;
  35. A0.bottomRightCorner(A.size(),1) = A;
  36. // Even faster would be to use the "Alias Table Method"
  37. cumsum(A0,1,C);
  38. const VectorXs R = (VectorXs::Random(n,1).array() + 1.)/2.;
  39. assert(R.minCoeff() >= 0);
  40. assert(R.maxCoeff() <= 1);
  41. histc(R,C,FI);
  42. const VectorXs S = (VectorXs::Random(n,1).array() + 1.)/2.;
  43. const VectorXs T = (VectorXs::Random(n,1).array() + 1.)/2.;
  44. B.resize(n,3);
  45. B.col(0) = 1.-T.array().sqrt();
  46. B.col(1) = (1.-S.array()) * T.array().sqrt();
  47. B.col(2) = S.array() * T.array().sqrt();
  48. }
  49. template <typename DerivedV, typename DerivedF, typename ScalarB, typename DerivedFI>
  50. IGL_INLINE void igl::random_points_on_mesh(
  51. const int n,
  52. const Eigen::PlainObjectBase<DerivedV > & V,
  53. const Eigen::PlainObjectBase<DerivedF > & F,
  54. Eigen::SparseMatrix<ScalarB > & B,
  55. Eigen::PlainObjectBase<DerivedFI > & FI)
  56. {
  57. using namespace Eigen;
  58. using namespace std;
  59. Matrix<ScalarB,Dynamic,3> BC;
  60. random_points_on_mesh(n,V,F,BC,FI);
  61. vector<Triplet<ScalarB> > BIJV;
  62. BIJV.reserve(n*3);
  63. for(int s = 0;s<n;s++)
  64. {
  65. for(int c = 0;c<3;c++)
  66. {
  67. assert(FI(s) < F.rows());
  68. assert(FI(s) >= 0);
  69. const int v = F(FI(s),c);
  70. BIJV.push_back(Triplet<ScalarB>(s,v,BC(s,c)));
  71. }
  72. }
  73. B.resize(n,V.rows());
  74. B.reserve(n*3);
  75. B.setFromTriplets(BIJV.begin(),BIJV.end());
  76. }
  77. #ifdef IGL_STATIC_LIBRARY
  78. // Explicit template specialization
  79. template void igl::random_points_on_mesh<Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, double, 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::SparseMatrix<double, 0, int>&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> >&);
  80. template void igl::random_points_on_mesh<Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, double, 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::SparseMatrix<double, 0, int>&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 1, 0, -1, 1> >&);
  81. #endif