centroid.cpp 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384
  1. // This file is part of libigl, a simple c++ geometry processing library.
  2. //
  3. // Copyright (C) 2014 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 "centroid.h"
  9. #include <Eigen/Geometry>
  10. template <
  11. typename DerivedV,
  12. typename DerivedF,
  13. typename Derivedc,
  14. typename Derivedvol>
  15. IGL_INLINE void igl::centroid(
  16. const Eigen::MatrixBase<DerivedV>& V,
  17. const Eigen::MatrixBase<DerivedF>& F,
  18. Eigen::PlainObjectBase<Derivedc>& cen,
  19. Derivedvol & vol)
  20. {
  21. assert(F.cols() == 3 && "F should contain triangles.");
  22. assert(V.cols() == 3 && "V should contain 3d points.");
  23. const int m = F.rows();
  24. // static assert that cen is either a 3d rowvector a 3d vector or a variable
  25. // size vector
  26. static_assert(Derivedc::IsVectorAtCompileTime,"cen should be a vector");
  27. static_assert(
  28. Derivedc::RowsAtCompileTime == 3 ||
  29. Derivedc::RowsAtCompileTime == -1 ||
  30. Derivedc::ColsAtCompileTime == 3 ||
  31. Derivedc::ColsAtCompileTime == -1,
  32. "cen should be sizeable to 3 vector");
  33. cen.setZero(3);
  34. vol = 0;
  35. // loop over faces
  36. for(int f = 0;f<m;f++)
  37. {
  38. // "Calculating the volume and centroid of a polyhedron in 3d" [Nuernberg 2013]
  39. // http://www2.imperial.ac.uk/~rn/centroid.pdf
  40. // rename corners
  41. typedef Eigen::Matrix<typename DerivedV::Scalar,1,3> RowVector3S;
  42. const RowVector3S & a = V.row(F(f,0));
  43. const RowVector3S & b = V.row(F(f,1));
  44. const RowVector3S & c = V.row(F(f,2));
  45. // un-normalized normal
  46. const RowVector3S & n = (b-a).cross(c-a);
  47. // total volume via divergence theorem: ∫ 1
  48. vol += n.dot(a)/6.;
  49. // centroid via divergence theorem and midpoint quadrature: ∫ x
  50. cen.array() += (1./24.*n.array()*((a+b).array().square() + (b+c).array().square() +
  51. (c+a).array().square()).array());
  52. }
  53. cen *= 1./(2.*vol);
  54. }
  55. template <
  56. typename DerivedV,
  57. typename DerivedF,
  58. typename Derivedc>
  59. IGL_INLINE void igl::centroid(
  60. const Eigen::MatrixBase<DerivedV>& V,
  61. const Eigen::MatrixBase<DerivedF>& F,
  62. Eigen::PlainObjectBase<Derivedc>& c)
  63. {
  64. typename Derivedc::Scalar vol;
  65. return centroid(V,F,c,vol);
  66. }
  67. #ifdef IGL_STATIC_LIBRARY
  68. // Explicit template instantiation
  69. // generated by autoexplicit.sh
  70. template void igl::centroid<Eigen::Matrix<double, 8, 3, 0, 8, 3>, Eigen::Matrix<int, 12, 3, 0, 12, 3>, Eigen::Matrix<double, 1, 3, 1, 1, 3>, double>(Eigen::MatrixBase<Eigen::Matrix<double, 8, 3, 0, 8, 3> > const&, Eigen::MatrixBase<Eigen::Matrix<int, 12, 3, 0, 12, 3> > const&, Eigen::PlainObjectBase<Eigen::Matrix<double, 1, 3, 1, 1, 3> >&, double&);
  71. template void igl::centroid<Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<double, 1, 3, 1, 1, 3>, double>(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, 3, 1, 1, 3> >&, double&);
  72. // generated by autoexplicit.sh
  73. template void igl::centroid<Eigen::Matrix<float, -1, 3, 1, -1, 3>, Eigen::Matrix<unsigned int, -1, 3, 1, -1, 3>, Eigen::Matrix<float, 3, 1, 0, 3, 1>, float>(Eigen::MatrixBase<Eigen::Matrix<float, -1, 3, 1, -1, 3> > const&, Eigen::MatrixBase<Eigen::Matrix<unsigned int, -1, 3, 1, -1, 3> > const&, Eigen::PlainObjectBase<Eigen::Matrix<float, 3, 1, 0, 3, 1> >&, float&);
  74. // generated by autoexplicit.sh
  75. template void igl::centroid<Eigen::Matrix<float, -1, 3, 1, -1, 3>, Eigen::Matrix<unsigned int, -1, 3, 1, -1, 3>, Eigen::Matrix<float, 3, 1, 0, 3, 1> >(Eigen::MatrixBase<Eigen::Matrix<float, -1, 3, 1, -1, 3> > const&, Eigen::MatrixBase<Eigen::Matrix<unsigned int, -1, 3, 1, -1, 3> > const&, Eigen::PlainObjectBase<Eigen::Matrix<float, 3, 1, 0, 3, 1> >&);
  76. // generated by autoexplicit.sh
  77. template void igl::centroid<Eigen::Matrix<float, -1, 3, 1, -1, 3>, Eigen::Matrix<int, -1, 3, 1, -1, 3>, Eigen::Matrix<float, 1, 3, 1, 1, 3> >(Eigen::MatrixBase<Eigen::Matrix<float, -1, 3, 1, -1, 3> > const&, Eigen::MatrixBase<Eigen::Matrix<int, -1, 3, 1, -1, 3> > const&, Eigen::PlainObjectBase<Eigen::Matrix<float, 1, 3, 1, 1, 3> >&);
  78. template void igl::centroid<Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<double, 3, 1, 0, 3, 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, 3, 1, 0, 3, 1> >&);
  79. template void igl::centroid<Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<double, 1, 3, 1, 1, 3> >(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, 3, 1, 1, 3> >&);
  80. template void igl::centroid<Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<double, 1, -1, 1, 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, 1, 1, -1>>&);
  81. #endif