// This file is part of libigl, a simple c++ geometry processing library. // // Copyright (C) 2013 Alec Jacobson // // This Source Code Form is subject to the terms of the Mozilla Public License // v. 2.0. If a copy of the MPL was not distributed with this file, You can // obtain one at http://mozilla.org/MPL/2.0/. #include "arap_linear_block.h" #include "verbose.h" #include "cotmatrix_entries.h" #include template IGL_INLINE void igl::arap_linear_block( const MatV & V, const MatF & F, const int d, const igl::ARAPEnergyType energy, Eigen::SparseMatrix & Kd) { switch(energy) { case ARAP_ENERGY_TYPE_SPOKES: return igl::arap_linear_block_spokes(V,F,d,Kd); break; case ARAP_ENERGY_TYPE_SPOKES_AND_RIMS: return igl::arap_linear_block_spokes_and_rims(V,F,d,Kd); break; case ARAP_ENERGY_TYPE_ELEMENTS: return igl::arap_linear_block_elements(V,F,d,Kd); break; default: verbose("Unsupported energy type: %d\n",energy); assert(false); } } template IGL_INLINE void igl::arap_linear_block_spokes( const MatV & V, const MatF & F, const int d, Eigen::SparseMatrix & Kd) { using namespace std; using namespace Eigen; // simplex size (3: triangles, 4: tetrahedra) int simplex_size = F.cols(); // Number of elements int m = F.rows(); // Temporary output Matrix edges; Kd.resize(V.rows(), V.rows()); vector > Kd_IJV; if(simplex_size == 3) { // triangles Kd.reserve(7*V.rows()); Kd_IJV.reserve(7*V.rows()); edges.resize(3,2); edges << 1,2, 2,0, 0,1; }else if(simplex_size == 4) { // tets Kd.reserve(17*V.rows()); Kd_IJV.reserve(17*V.rows()); edges.resize(6,2); edges << 1,2, 2,0, 0,1, 3,0, 3,1, 3,2; } // gather cotangent weights Matrix C; cotmatrix_entries(V,F,C); // should have weights for each edge assert(C.cols() == edges.rows()); // loop over elements for(int i = 0;i(source,dest,v)); Kd_IJV.push_back(Triplet(dest,source,-v)); Kd_IJV.push_back(Triplet(source,source,v)); Kd_IJV.push_back(Triplet(dest,dest,-v)); } } Kd.setFromTriplets(Kd_IJV.begin(),Kd_IJV.end()); Kd.makeCompressed(); } template IGL_INLINE void igl::arap_linear_block_spokes_and_rims( const MatV & V, const MatF & F, const int d, Eigen::SparseMatrix & Kd) { using namespace std; using namespace Eigen; // simplex size (3: triangles, 4: tetrahedra) int simplex_size = F.cols(); // Number of elements int m = F.rows(); // Temporary output Kd.resize(V.rows(), V.rows()); vector > Kd_IJV; Matrix edges; if(simplex_size == 3) { // triangles Kd.reserve(7*V.rows()); Kd_IJV.reserve(7*V.rows()); edges.resize(3,2); edges << 1,2, 2,0, 0,1; }else if(simplex_size == 4) { // tets Kd.reserve(17*V.rows()); Kd_IJV.reserve(17*V.rows()); edges.resize(6,2); edges << 1,2, 2,0, 0,1, 3,0, 3,1, 3,2; // Not implemented yet for tets assert(false); } // gather cotangent weights Matrix C; cotmatrix_entries(V,F,C); // should have weights for each edge assert(C.cols() == edges.rows()); // loop over elements for(int i = 0;i(Rs,Rd,v)); Kd_IJV.push_back(Triplet(Rd,Rs,-v)); }else if(Rd == source) { Kd_IJV.push_back(Triplet(Rd,Rs,v)); }else if(Rs == dest) { Kd_IJV.push_back(Triplet(Rs,Rd,-v)); } } Kd_IJV.push_back(Triplet(source,source,v)); Kd_IJV.push_back(Triplet(dest,dest,-v)); } } Kd.setFromTriplets(Kd_IJV.begin(),Kd_IJV.end()); Kd.makeCompressed(); } template IGL_INLINE void igl::arap_linear_block_elements( const MatV & V, const MatF & F, const int d, Eigen::SparseMatrix & Kd) { using namespace std; using namespace Eigen; // simplex size (3: triangles, 4: tetrahedra) int simplex_size = F.cols(); // Number of elements int m = F.rows(); // Temporary output Kd.resize(V.rows(), F.rows()); vector > Kd_IJV; Matrix edges; if(simplex_size == 3) { // triangles Kd.reserve(7*V.rows()); Kd_IJV.reserve(7*V.rows()); edges.resize(3,2); edges << 1,2, 2,0, 0,1; }else if(simplex_size == 4) { // tets Kd.reserve(17*V.rows()); Kd_IJV.reserve(17*V.rows()); edges.resize(6,2); edges << 1,2, 2,0, 0,1, 3,0, 3,1, 3,2; } // gather cotangent weights Matrix C; cotmatrix_entries(V,F,C); // should have weights for each edge assert(C.cols() == edges.rows()); // loop over elements for(int i = 0;i(source,i,v)); Kd_IJV.push_back(Triplet(dest,i,-v)); } } Kd.setFromTriplets(Kd_IJV.begin(),Kd_IJV.end()); Kd.makeCompressed(); } #ifdef IGL_STATIC_LIBRARY // Explicit template instantiation template IGL_INLINE void igl::arap_linear_block, Eigen::Matrix, double>(Eigen::Matrix const&, Eigen::Matrix const&, int, igl::ARAPEnergyType, Eigen::SparseMatrix&); #endif