centroid.cpp 3.0 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768
  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 "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. using namespace Eigen;
  22. assert(F.cols() == 3 && "F should contain triangles.");
  23. assert(V.cols() == 3 && "V should contain 3d points.");
  24. const int m = F.rows();
  25. cen.setZero();
  26. vol = 0;
  27. // loop over faces
  28. for(int f = 0;f<m;f++)
  29. {
  30. // "Calculating the volume and centroid of a polyhedron in 3d" [Nuernberg 2013]
  31. // http://www2.imperial.ac.uk/~rn/centroid.pdf
  32. // rename corners
  33. typedef Eigen::Matrix<typename DerivedV::Scalar,1,3> RowVector3S;
  34. const RowVector3S & a = V.row(F(f,0));
  35. const RowVector3S & b = V.row(F(f,1));
  36. const RowVector3S & c = V.row(F(f,2));
  37. // un-normalized normal
  38. const RowVector3S & n = (b-a).cross(c-a);
  39. // total volume via divergence theorem: ∫ 1
  40. vol += n.dot(a)/6.;
  41. // centroid via divergence theorem and midpoint quadrature: ∫ x
  42. cen.array() += (1./24.*n.array()*((a+b).array().square() + (b+c).array().square() +
  43. (c+a).array().square()).array());
  44. }
  45. cen *= 1./(2.*vol);
  46. }
  47. template <
  48. typename DerivedV,
  49. typename DerivedF,
  50. typename Derivedc>
  51. IGL_INLINE void igl::centroid(
  52. const Eigen::MatrixBase<DerivedV>& V,
  53. const Eigen::MatrixBase<DerivedF>& F,
  54. Eigen::PlainObjectBase<Derivedc>& c)
  55. {
  56. typename Derivedc::Scalar vol;
  57. return centroid(V,F,c,vol);
  58. }
  59. #ifdef IGL_STATIC_LIBRARY
  60. // Explicit template instantiation
  61. // generated by autoexplicit.sh
  62. 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> >&);
  63. 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> >&);
  64. 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> >&);
  65. #endif