// This file is part of libhedra, a library for polyhedral mesh processing // // Copyright (C) 2016 Amir Vaxman // // 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/. #ifndef HEDRA_DISCRETE_SHELLS_TRAITS_H #define HEDRA_DISCRETE_SHELLS_TRAITS_H #include #include #include #include #include #include #include namespace hedra { namespace optimization { //this class is a traits class for optimization of discrete shells deformation by given positional constraints. It is an implementation on [Froehlich and Botsch 2012] for general polyhedral meshes, using a triangulation of them //the solution vector is assumed to be arranged as xyzxyzxyz... where each triplet is a coordinate of the free vertices. class DiscreteShellsTraits{ public: //Requisites of the traits class Eigen::VectorXi JRows, JCols; //rows and column indices for the jacobian matrix Eigen::VectorXd JVals; //values for the jacobian matrix. int xSize; //size of the solution Eigen::VectorXd EVec; //energy vector //These are for the the full Jacobian matrix without removing the handles Eigen::VectorXi fullJRows, fullJCols; Eigen::VectorXd fullJVals; Eigen::MatrixXi flapVertexIndices; //vertices (i,j,k,l) of a flap on edge e=(k,i) where the triangles are f=(i,j,k) and g=(i,k,l) Eigen::MatrixXi EV; Eigen::VectorXi h; //list of handles Eigen::MatrixXd qh; //#h by 3 positions Eigen::VectorXi a2x; //from the entire set of variables "a" to the free variables in the optimization "x". Eigen::VectorXi colMap; //raw map of a2x into the columns from fullJCols into JCols Eigen::VectorXd origLengths; //the original edge lengths. Eigen::VectorXd origDihedrals; //Original dihedral angles Eigen::MatrixXd VOrig; //original positions Eigen::MatrixXi T; //triangles Eigen::VectorXd Wd, Wl; //geometric weights for the lengths and the dihedral angles. double bendCoeff, lengthCoeff; //coefficients for the different terms //Eigen::VectorXd x0; //the initial solution to the optimization Eigen::MatrixXd fullSolution; //The final solution of the last optimization void init(const Eigen::MatrixXd& _VOrig, const Eigen::MatrixXi& _T, const Eigen::VectorXi& _h, const Eigen::MatrixXi& _EV, const Eigen::MatrixXi& ET, const Eigen::MatrixXi& ETi, const Eigen::VectorXi& innerEdges){ using namespace std; using namespace Eigen; std::set > edgeIndicesList; VOrig=_VOrig; T=_T; h=_h; EV=_EV; lengthCoeff=10.0; bendCoeff=1.0; //lengths of edges and diagonals flapVertexIndices.resize(innerEdges.size(),4); //dihedral angles for (int i=0;i= 0 ? 1.0 : -1.0); double sinHalf=sign*sqrt((1.0-n1.normalized().dot(n2.normalized()))/2.0); origDihedrals(i)=2.0*asin(sinHalf); double areaSum=(n1.norm()+n2.norm())/2.0; Wd(i)=eki.norm()/sqrt(areaSum); } //creating the Jacobian pattern xSize=3*(VOrig.rows()-h.size()); fullJRows.resize(6*EV.rows()+12*flapVertexIndices.rows()); fullJCols.resize(6*EV.rows()+12*flapVertexIndices.rows()); fullJVals.resize(6*EV.rows()+12*flapVertexIndices.rows()); //Jacobian indices for edge lengths for (int i=0;i= 0 ? 1.0 : -1.0); double dotn1n2=1.0-n1.normalized().dot(n2.normalized()); if (dotn1n2<0.0) dotn1n2=0.0; //sanitizing double sinHalf=sign*sqrt(dotn1n2/2.0); if (sinHalf>1.0) sinHalf=1.0; if (sinHalf<-1.0) sinHalf=-1.0; EVec(EV.rows()+i)=(2.0*asin(sinHalf)-origDihedrals(i))*Wd(i)*bendCoeff; } for (int i=0;i= 0 ? 1.0 : -1.0); double dotn1n2=1.0-n1.normalized().dot(n2.normalized()); if (dotn1n2<0.0) dotn1n2=0.0; //sanitizing double sinHalf=sign*sqrt(dotn1n2/2.0); if (sinHalf>1.0) sinHalf=1.0; if (sinHalf<-1.0) sinHalf=-1.0; fullJVals.segment(6*EV.rows()+12*i,3)<<(Wd(i)*((ejk.dot(-eki)/(n1.squaredNorm()*eki.norm()))*n1+(elk.dot(-eki)/(n2.squaredNorm()*eki.norm()))*n2)).transpose()*bendCoeff; fullJVals.segment(6*EV.rows()+12*i+3,3)<<(Wd(i)*(-eki.norm()/n1.squaredNorm())*n1).transpose()*bendCoeff; fullJVals.segment(6*EV.rows()+12*i+6,3)<<(Wd(i)*((eji.dot(eki)/(n1.squaredNorm()*eki.norm()))*n1+(eli.dot(eki)/(n2.squaredNorm()*eki.norm()))*n2)).transpose()*bendCoeff; fullJVals.segment(6*EV.rows()+12*i+9,3)<<(Wd(i)*(-eki.norm()/n2.squaredNorm())*n2).transpose()*bendCoeff; } int actualGradCounter=0; for (int i=0;i