isolines.cpp 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117
  1. // This file is part of libigl, a simple c++ geometry processing library.
  2. //
  3. // Copyright (C) 2017 Oded Stein <oded.stein@columbia.edu>
  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 "isolines.h"
  9. #include <vector>
  10. #include <array>
  11. #include <iostream>
  12. #include "sort.h"
  13. #include "remove_duplicate_vertices.h"
  14. template <typename DerivedV,
  15. typename DerivedF,
  16. typename DerivedZ,
  17. typename DerivedIsoV,
  18. typename DerivedIsoE>
  19. IGL_INLINE void igl::isolines(
  20. const Eigen::MatrixBase<DerivedV>& V,
  21. const Eigen::MatrixBase<DerivedF>& F,
  22. const Eigen::MatrixBase<DerivedZ>& z,
  23. const int n,
  24. Eigen::PlainObjectBase<DerivedIsoV>& isoV,
  25. Eigen::PlainObjectBase<DerivedIsoE>& isoE)
  26. {
  27. //Constants
  28. const int dim = V.cols();
  29. assert(dim==2 || dim==3);
  30. const int nVerts = V.rows();
  31. assert(z.rows() == nVerts &&
  32. "There must be as many function entries as vertices");
  33. const int nFaces = F.rows();
  34. const int np1 = n+1;
  35. const double min = z.minCoeff(), max = z.maxCoeff();
  36. //Following http://www.alecjacobson.com/weblog/?p=2529
  37. typedef typename DerivedZ::Scalar Scalar;
  38. typedef Eigen::Matrix<Scalar, Eigen::Dynamic, 1> Vec;
  39. Vec iso(np1);
  40. for(int i=0; i<np1; ++i)
  41. iso(i) = Scalar(i)/Scalar(n)*(max-min) + min;
  42. typedef Eigen::Matrix<Scalar, Eigen::Dynamic, Eigen::Dynamic> Matrix;
  43. std::array<Matrix,3> t{{Matrix(nFaces, np1),
  44. Matrix(nFaces, np1), Matrix(nFaces, np1)}};
  45. for(int i=0; i<nFaces; ++i) {
  46. for(int k=0; k<3; ++k) {
  47. const Scalar z1=z(F(i,k)), z2=z(F(i,(k+1)%3));
  48. for(int j=0; j<np1; ++j) {
  49. t[k](i,j) = (iso(j)-z1) / (z2-z1);
  50. if(t[k](i,j)<0 || t[k](i,j)>1)
  51. t[k](i,j) = std::numeric_limits<Scalar>::quiet_NaN();
  52. }
  53. }
  54. }
  55. std::array<std::vector<int>,3> Fij, Iij;
  56. for(int i=0; i<nFaces; ++i) {
  57. for(int j=0; j<np1; ++j) {
  58. for(int k=0; k<3; ++k) {
  59. const int kp1=(k+1)%3, kp2=(k+2)%3;
  60. if(std::isfinite(t[kp1](i,j)) && std::isfinite(t[kp2](i,j))) {
  61. Fij[k].push_back(i);
  62. Iij[k].push_back(j);
  63. }
  64. }
  65. }
  66. }
  67. const int K = Fij[0].size()+Fij[1].size()+Fij[2].size();
  68. isoV.resize(2*K, dim);
  69. int b = 0;
  70. for(int k=0; k<3; ++k) {
  71. const int kp1=(k+1)%3, kp2=(k+2)%3;
  72. for(int i=0; i<Fij[k].size(); ++i) {
  73. isoV.row(b+i) = (1.-t[kp1](Fij[k][i],Iij[k][i]))*
  74. V.row(F(Fij[k][i],kp1)) +
  75. t[kp1](Fij[k][i],Iij[k][i])*V.row(F(Fij[k][i],kp2));
  76. isoV.row(K+b+i) = (1.-t[kp2](Fij[k][i],Iij[k][i]))*
  77. V.row(F(Fij[k][i],kp2)) +
  78. t[kp2](Fij[k][i],Iij[k][i])*V.row(F(Fij[k][i],k));
  79. }
  80. b += Fij[k].size();
  81. }
  82. isoE.resize(K,2);
  83. for(int i=0; i<K; ++i)
  84. isoE.row(i) << i, K+i;
  85. //Remove double entries
  86. typedef typename DerivedIsoV::Scalar LScalar;
  87. typedef typename DerivedIsoE::Scalar LInt;
  88. typedef Eigen::Matrix<LInt, Eigen::Dynamic, 1> LIVec;
  89. typedef Eigen::Matrix<LScalar, Eigen::Dynamic, Eigen::Dynamic> LMat;
  90. typedef Eigen::Matrix<LInt, Eigen::Dynamic, Eigen::Dynamic> LIMat;
  91. LIVec dummy1, dummy2;
  92. igl::remove_duplicate_vertices(LMat(isoV), LIMat(isoE),
  93. 1e-12, isoV, dummy1, dummy2, isoE);
  94. }
  95. #ifdef IGL_STATIC_LIBRARY
  96. // Explicit template instantiation
  97. template void igl::isolines<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<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::MatrixBase<Eigen::Matrix<double, -1, 1, 0, -1, 1> > const&, int const, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > &, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > &);
  98. #endif