voxel_grid.cpp 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105
  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 "voxel_grid.h"
  9. #include "grid.h"
  10. template <
  11. typename Scalar,
  12. typename DerivedGV,
  13. typename Derivedside>
  14. IGL_INLINE void igl::voxel_grid(
  15. const Eigen::AlignedBox<Scalar,3> & box,
  16. const int in_s,
  17. const int pad_count,
  18. Eigen::PlainObjectBase<DerivedGV> & GV,
  19. Eigen::PlainObjectBase<Derivedside> & side)
  20. {
  21. typename DerivedGV::Index si = -1;
  22. side.resize(3);
  23. box.diagonal().maxCoeff(&si);
  24. //DerivedGV::Index si = 0;
  25. //assert(si>=0);
  26. const Scalar s_len = box.diagonal()(si);
  27. assert(in_s>(pad_count*2+1) && "s should be > 2*pad_count+1");
  28. const Scalar s = in_s - 2*pad_count;
  29. side(si) = s;
  30. for(int i = 0;i<3;i++)
  31. {
  32. if(i!=si)
  33. {
  34. side(i) = std::ceil(s * (box.max()(i)-box.min()(i))/s_len);
  35. }
  36. }
  37. side.array() += 2*pad_count;
  38. grid(side,GV);
  39. // A * p/s + B = min
  40. // A * (1-p/s) + B = max
  41. // B = min - A * p/s
  42. // A * (1-p/s) + min - A * p/s = max
  43. // A * (1-p/s) - A * p/s = max-min
  44. // A * (1-2p/s) = max-min
  45. // A = (max-min)/(1-2p/s)
  46. const Eigen::Array<Scalar,3,1> ps=
  47. (Scalar)(pad_count)/(side.transpose().template cast<Scalar>().array()-1.);
  48. const Eigen::Array<Scalar,3,1> A = box.diagonal().array()/(1.0-2.*ps);
  49. //// This would result in an "anamorphic", but perfectly fit grid:
  50. //const Array<Scalar,3,1> B = box.min().array() - A.array()*ps;
  51. //GV.array().rowwise() *= A.transpose();
  52. //GV.array().rowwise() += B.transpose();
  53. // Instead scale by largest factor and move to match center
  54. typename Eigen::Array<Scalar,3,1>::Index ai = -1;
  55. Scalar a = A.maxCoeff(&ai);
  56. const Eigen::Array<Scalar,1,3> ratio =
  57. a*(side.template cast<Scalar>().array()-1.0)/(Scalar)(side(ai)-1.0);
  58. GV.array().rowwise() *= ratio;
  59. const Eigen::Matrix<Scalar,1,3> offset = (box.center().transpose()-GV.colwise().mean()).eval();
  60. GV.rowwise() += offset;
  61. }
  62. template <
  63. typename DerivedV,
  64. typename DerivedGV,
  65. typename Derivedside>
  66. IGL_INLINE void igl::voxel_grid(
  67. const Eigen::MatrixBase<DerivedV> & V,
  68. const typename DerivedV::Scalar offset,
  69. const int s,
  70. const int pad_count,
  71. Eigen::PlainObjectBase<DerivedGV> & GV,
  72. Eigen::PlainObjectBase<Derivedside> & side)
  73. {
  74. typedef typename DerivedV::Scalar Scalar;
  75. Eigen::AlignedBox<Scalar,3> box;
  76. typedef Eigen::Matrix<Scalar,1,3> RowVector3S;
  77. assert(V.cols() == 3 && "V must contain positions in 3D");
  78. RowVector3S min_ext = V.colwise().minCoeff().array() - offset;
  79. RowVector3S max_ext = V.colwise().maxCoeff().array() + offset;
  80. box.extend(min_ext.transpose());
  81. box.extend(max_ext.transpose());
  82. return igl::voxel_grid(box,s,pad_count,GV,side);
  83. }
  84. #ifdef IGL_STATIC_LIBRARY
  85. // Explicit template instantiation
  86. // generated by autoexplicit.sh
  87. template void igl::voxel_grid<Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<double, -1, 3, 1, -1, 3>, Eigen::Matrix<int, 1, 3, 1, 1, 3> >(Eigen::MatrixBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, Eigen::Matrix<double, -1, -1, 0, -1, -1>::Scalar, int, int, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 3, 1, -1, 3> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, 1, 3, 1, 1, 3> >&);
  88. // generated by autoexplicit.sh
  89. template void igl::voxel_grid<Eigen::Matrix<float, -1, 3, 1, -1, 3>, Eigen::Matrix<float, -1, -1, 0, -1, -1>, Eigen::Matrix<int, 1, 3, 1, 1, 3> >(Eigen::MatrixBase<Eigen::Matrix<float, -1, 3, 1, -1, 3> > const&, Eigen::Matrix<float, -1, 3, 1, -1, 3>::Scalar, int, int, Eigen::PlainObjectBase<Eigen::Matrix<float, -1, -1, 0, -1, -1> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, 1, 3, 1, 1, 3> >&);
  90. // generated by autoexplicit.sh
  91. template void igl::voxel_grid<Eigen::Matrix<double, -1, 3, 1, -1, 3>, Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<int, 1, 3, 1, 1, 3> >(Eigen::MatrixBase<Eigen::Matrix<double, -1, 3, 1, -1, 3> > const&, Eigen::Matrix<double, -1, 3, 1, -1, 3>::Scalar, int, int, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, 1, 3, 1, 1, 3> >&);
  92. // generated by autoexplicit.sh
  93. template void igl::voxel_grid<Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<int, 1, 3, 1, 1, 3> >(Eigen::MatrixBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, Eigen::Matrix<double, -1, -1, 0, -1, -1>::Scalar, int, int, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, 1, 3, 1, 1, 3> >&);
  94. // generated by autoexplicit.sh
  95. template void igl::voxel_grid<float, Eigen::Matrix<float, -1, -1, 0, -1, -1>, Eigen::Matrix<int, 3, 1, 0, 3, 1> >(Eigen::AlignedBox<float, 3> const&, int, int, Eigen::PlainObjectBase<Eigen::Matrix<float, -1, -1, 0, -1, -1> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, 3, 1, 0, 3, 1> >&);
  96. // generated by autoexplicit.sh
  97. template void igl::voxel_grid<float, Eigen::Matrix<float, -1, -1, 0, -1, -1>, Eigen::Matrix<int, 1, 3, 1, 1, 3> >(Eigen::AlignedBox<float, 3> const&, int, int, Eigen::PlainObjectBase<Eigen::Matrix<float, -1, -1, 0, -1, -1> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, 1, 3, 1, 1, 3> >&);
  98. template void igl::voxel_grid<float, Eigen::Matrix<float, -1, 3, 0, -1, 3>, Eigen::Matrix<int, 3, 1, 0, 3, 1> >(Eigen::AlignedBox<float, 3> const&, int, int, Eigen::PlainObjectBase<Eigen::Matrix<float, -1, 3, 0, -1, 3> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, 3, 1, 0, 3, 1> >&);
  99. template void igl::voxel_grid<float, Eigen::Matrix<float, -1, 3, 1, -1, 3>, Eigen::Matrix<int, 3, 1, 0, 3, 1> >(Eigen::AlignedBox<float, 3> const&, int, int, Eigen::PlainObjectBase<Eigen::Matrix<float, -1, 3, 1, -1, 3> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, 3, 1, 0, 3, 1> >&);
  100. template void igl::voxel_grid<double, Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<int, 3, 1, 0, 3, 1> >(Eigen::AlignedBox<double, 3> const&, int, int, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, 3, 1, 0, 3, 1> >&);
  101. template void igl::voxel_grid<double, Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<int, 1, 3, 1, 1, 3> >(Eigen::AlignedBox<double, 3> const&, int, int, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, 1, 3, 1, 1, 3> >&);
  102. #endif