123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241 |
- #include "grad.h"
- #include <Eigen/Geometry>
- #include <vector>
- #include "per_face_normals.h"
- #include "volume.h"
- #include "doublearea.h"
- template <typename DerivedV, typename DerivedF>
- IGL_INLINE void grad_tet(const Eigen::PlainObjectBase<DerivedV>&V,
- const Eigen::PlainObjectBase<DerivedF>&T,
- Eigen::SparseMatrix<typename DerivedV::Scalar> &G,
- bool uniform) {
- using namespace Eigen;
- assert(T.cols() == 4);
- const int n = V.rows(); int m = T.rows();
-
- MatrixXi F(4*m,3);
- for (int i = 0; i < m; i++) {
- F.row(0*m + i) << T(i,0), T(i,1), T(i,2);
- F.row(1*m + i) << T(i,0), T(i,2), T(i,3);
- F.row(2*m + i) << T(i,0), T(i,3), T(i,1);
- F.row(3*m + i) << T(i,1), T(i,3), T(i,2);
- }
-
- VectorXd vol; igl::volume(V,T,vol);
- VectorXd A(F.rows());
- MatrixXd N(F.rows(),3);
- if (!uniform) {
-
- igl::per_face_normals(V,F,N); int norm_rows = N.rows();
- for (int i = 0; i < norm_rows; i++)
- N.row(i) /= N.row(i).norm();
- igl::doublearea(V,F,A); A/=2.;
- } else {
-
-
-
-
-
-
-
- for (int i = 0; i < m; i++) {
- N.row(0*m+i) << 0,0,1;
- double a = sqrt(2)*std::cbrt(3*vol(i));
- A(0*m+i) = (pow(a,2)*sqrt(3))/4.;
- }
- for (int i = 0; i < m; i++) {
- N.row(1*m+i) << 0.8165,-0.4714,-0.3333;
- double a = sqrt(2)*std::cbrt(3*vol(i));
- A(1*m+i) = (pow(a,2)*sqrt(3))/4.;
- }
- for (int i = 0; i < m; i++) {
- N.row(2*m+i) << 0,0.9428,-0.3333;
- double a = sqrt(2)*std::cbrt(3*vol(i));
- A(2*m+i) = (pow(a,2)*sqrt(3))/4.;
- }
- for (int i = 0; i < m; i++) {
- N.row(3*m+i) << -0.8165,-0.4714,-0.3333;
- double a = sqrt(2)*std::cbrt(3*vol(i));
- A(3*m+i) = (pow(a,2)*sqrt(3))/4.;
- }
- }
-
- std::vector<Triplet<double> > G_t;
- for (int i = 0; i < 4*m; i++) {
- int T_j;
- switch (i/m) {
- case 0:
- T_j = 3;
- break;
- case 1:
- T_j = 1;
- break;
- case 2:
- T_j = 2;
- break;
- case 3:
- T_j = 0;
- break;
- }
- int i_idx = i%m;
- int j_idx = T(i_idx,T_j);
- double val_before_n = A(i)/(3*vol(i_idx));
- G_t.push_back(Triplet<double>(0*m+i_idx, j_idx, val_before_n * N(i,0)));
- G_t.push_back(Triplet<double>(1*m+i_idx, j_idx, val_before_n * N(i,1)));
- G_t.push_back(Triplet<double>(2*m+i_idx, j_idx, val_before_n * N(i,2)));
- }
- G.resize(3*m,n);
- G.setFromTriplets(G_t.begin(), G_t.end());
- }
- template <typename DerivedV, typename DerivedF>
- IGL_INLINE void grad_tri(const Eigen::PlainObjectBase<DerivedV>&V,
- const Eigen::PlainObjectBase<DerivedF>&F,
- Eigen::SparseMatrix<typename DerivedV::Scalar> &G,
- bool uniform)
- {
- Eigen::Matrix<typename DerivedV::Scalar,Eigen::Dynamic,3>
- eperp21(F.rows(),3), eperp13(F.rows(),3);
- for (int i=0;i<F.rows();++i)
- {
-
- int i1 = F(i,0);
- int i2 = F(i,1);
- int i3 = F(i,2);
-
- Eigen::Matrix<typename DerivedV::Scalar, 1, 3> v32 = V.row(i3) - V.row(i2);
- Eigen::Matrix<typename DerivedV::Scalar, 1, 3> v13 = V.row(i1) - V.row(i3);
- Eigen::Matrix<typename DerivedV::Scalar, 1, 3> v21 = V.row(i2) - V.row(i1);
- Eigen::Matrix<typename DerivedV::Scalar, 1, 3> n = v32.cross(v13);
-
-
-
-
- double dblA = std::sqrt(n.dot(n));
- Eigen::Matrix<typename DerivedV::Scalar, 1, 3> u(0,0,1);
- if (!uniform) {
-
- u = n / dblA;
- } else {
-
-
- double h = sqrt( (dblA)/sin(M_PI / 3.0));
- Eigen::Vector3d v1,v2,v3;
- v1 << 0,0,0;
- v2 << h,0,0;
- v3 << h/2.,(sqrt(3)/2.)*h,0;
-
- v32 = v3-v2;
- v13 = v1-v3;
- v21 = v2-v1;
- n = v32.cross(v13);
- }
-
- double norm21 = std::sqrt(v21.dot(v21));
- double norm13 = std::sqrt(v13.dot(v13));
- eperp21.row(i) = u.cross(v21);
- eperp21.row(i) = eperp21.row(i) / std::sqrt(eperp21.row(i).dot(eperp21.row(i)));
- eperp21.row(i) *= norm21 / dblA;
- eperp13.row(i) = u.cross(v13);
- eperp13.row(i) = eperp13.row(i) / std::sqrt(eperp13.row(i).dot(eperp13.row(i)));
- eperp13.row(i) *= norm13 / dblA;
- }
- std::vector<int> rs;
- rs.reserve(F.rows()*4*3);
- std::vector<int> cs;
- cs.reserve(F.rows()*4*3);
- std::vector<double> vs;
- vs.reserve(F.rows()*4*3);
-
- for(int r=0;r<3;r++)
- {
- for(int j=0;j<4;j++)
- {
- for(int i=r*F.rows();i<(r+1)*F.rows();i++) rs.push_back(i);
- }
- }
-
- for(int r=0;r<3;r++)
- {
- for(int i=0;i<F.rows();i++) cs.push_back(F(i,1));
- for(int i=0;i<F.rows();i++) cs.push_back(F(i,0));
- for(int i=0;i<F.rows();i++) cs.push_back(F(i,2));
- for(int i=0;i<F.rows();i++) cs.push_back(F(i,0));
- }
-
- for(int i=0;i<F.rows();i++) vs.push_back(eperp13(i,0));
- for(int i=0;i<F.rows();i++) vs.push_back(-eperp13(i,0));
- for(int i=0;i<F.rows();i++) vs.push_back(eperp21(i,0));
- for(int i=0;i<F.rows();i++) vs.push_back(-eperp21(i,0));
- for(int i=0;i<F.rows();i++) vs.push_back(eperp13(i,1));
- for(int i=0;i<F.rows();i++) vs.push_back(-eperp13(i,1));
- for(int i=0;i<F.rows();i++) vs.push_back(eperp21(i,1));
- for(int i=0;i<F.rows();i++) vs.push_back(-eperp21(i,1));
- for(int i=0;i<F.rows();i++) vs.push_back(eperp13(i,2));
- for(int i=0;i<F.rows();i++) vs.push_back(-eperp13(i,2));
- for(int i=0;i<F.rows();i++) vs.push_back(eperp21(i,2));
- for(int i=0;i<F.rows();i++) vs.push_back(-eperp21(i,2));
-
- G.resize(3*F.rows(),V.rows());
- std::vector<Eigen::Triplet<typename DerivedV::Scalar> > triplets;
- for (int i=0;i<(int)vs.size();++i)
- {
- triplets.push_back(Eigen::Triplet<typename DerivedV::Scalar>(rs[i],cs[i],vs[i]));
- }
- G.setFromTriplets(triplets.begin(), triplets.end());
- }
- template <typename DerivedV, typename DerivedF>
- IGL_INLINE void igl::grad(const Eigen::PlainObjectBase<DerivedV>&V,
- const Eigen::PlainObjectBase<DerivedF>&F,
- Eigen::SparseMatrix<typename DerivedV::Scalar> &G,
- bool uniform)
- {
- assert(F.cols() == 3 || F.cols() == 4);
- if (F.cols() == 3)
- return grad_tri(V,F,G,uniform);
- if (F.cols() == 4)
- return grad_tet(V,F,G,uniform);
- }
- #ifdef IGL_STATIC_LIBRARY
- template void igl::grad<Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1> >(Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, Eigen::SparseMatrix<Eigen::Matrix<double, -1, -1, 0, -1, -1>::Scalar, 0, int>&, bool);
- template void igl::grad<Eigen::Matrix<double, -1, 3, 0, -1, 3>, Eigen::Matrix<int, -1, 3, 0, -1, 3> >(Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 3, 0, -1, 3> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 3, 0, -1, 3> > const&, Eigen::SparseMatrix<Eigen::Matrix<double, -1, 3, 0, -1, 3>::Scalar, 0, int>&, bool);
- #endif
|