def makeLaplacianMatrixSolverIGLHard(VPos, ITris, anchorsIdx): VPosE = igl.eigen.MatrixXd(VPos) ITrisE = igl.eigen.MatrixXi(ITris) L = igl.eigen.SparseMatrixd() M = igl.eigen.SparseMatrixd() M_inv = igl.eigen.SparseMatrixd() igl.cotmatrix(VPosE,ITrisE,L) igl.massmatrix(VPosE,ITrisE,igl.MASSMATRIX_TYPE_VORONOI,M) igl.invert_diag(M,M_inv) L = M_inv*L deltaCoords = L*VPosE deltaCoords = np.array(deltaCoords) #Bi-laplacian Q = L.transpose()*L
viewer.data.set_mesh(V, F) viewer.core.show_lines = False viewer.callback_key_down = key_down # One fixed point on belly b = igl.eigen.MatrixXi([[2556]]) bc = igl.eigen.MatrixXd([[1]]) # Construct Laplacian and mass matrix L = igl.eigen.SparseMatrixd() M = igl.eigen.SparseMatrixd() Minv = igl.eigen.SparseMatrixd() igl.cotmatrix(V, F, L) igl.massmatrix(V, F, igl.MASSMATRIX_TYPE_VORONOI, M) igl.invert_diag(M, Minv) # Bi-Laplacian Q = L.transpose() * (Minv * L) # Zero linear term B = igl.eigen.MatrixXd.Zero(V.rows(), 1) # Lower and upper bound lx = igl.eigen.MatrixXd.Zero(V.rows(), 1) ux = igl.eigen.MatrixXd.Ones(V.rows(), 1) # Equality constraint constrain solution to sum to 1 Beq = igl.eigen.MatrixXd([[0.08]]) Aeq = M.diagonal().transpose().sparseView()
viewer.data.set_mesh(V, F) viewer.core.show_lines = False viewer.callback_key_down = key_down # One fixed point on belly b = igl.eigen.MatrixXi([[2556]]) bc = igl.eigen.MatrixXd([[1]]) # Construct Laplacian and mass matrix L = igl.eigen.SparseMatrixd() M = igl.eigen.SparseMatrixd() Minv = igl.eigen.SparseMatrixd() igl.cotmatrix(V,F,L) igl.massmatrix(V,F,igl.MASSMATRIX_TYPE_VORONOI,M); igl.invert_diag(M,Minv) # Bi-Laplacian Q = L.transpose() * (Minv * L) # Zero linear term B = igl.eigen.MatrixXd.Zero(V.rows(),1) # Lower and upper bound lx = igl.eigen.MatrixXd.Zero(V.rows(),1) ux = igl.eigen.MatrixXd.Ones(V.rows(),1) # Equality constraint constrain solution to sum to 1 Beq = igl.eigen.MatrixXd([[0.08]]) Aeq = M.diagonal().sparseView().transpose()
def makeLaplacianMatrixSolverIGLSoft(VPos, ITris, anchorsIdx, anchorWeights, makeSolver = True): VPosE = igl.eigen.MatrixXd(VPos) ITrisE = igl.eigen.MatrixXi(ITris) ''' #Doing this check slows things down by more than a factor of 2 (convert to numpy to make faster?) for f in range(ITrisE.rows()): v_list = ITrisE.row(f) v1 = VPosE.row(v_list[0]) v2 = VPosE.row(v_list[1]) v3 = VPosE.row(v_list[2]) if (v1-v2).norm() < 1e-10 and (v1-v3).norm() < 1e-10 and (v2-v3).norm() < 1e-10: print 'zero area triangle!',f ''' L = igl.eigen.SparseMatrixd() M = igl.eigen.SparseMatrixd() M_inv = igl.eigen.SparseMatrixd() igl.cotmatrix(VPosE,ITrisE,L) igl.massmatrix(VPosE,ITrisE,igl.MASSMATRIX_TYPE_VORONOI,M) #np.set_printoptions(threshold='nan') #print 'what is M?',M.diagonal() igl.invert_diag(M,M_inv) #L = M_inv*L deltaCoords = (M_inv*L)*VPosE #TODO: What to do with decaying_anchor_weights? ''' anchor_dists = [] for i in range(VPosE.rows()): anchor_dists.append(min([ (VPosE.row(i)-VPosE.row(j)).norm() for j in anchorsIdx ])) max_anchor_dist = max(anchor_dists) # assume linear weighting for anchor weights -> we are 0 at the anchors, anchorWeights at max_anchor_dist decaying_anchor_weights = [] for anchor_dist in anchor_dists: decaying_anchor_weights.append(anchorWeights*(anchor_dist/max_anchor_dist)) ''' solver = None if makeSolver: Q = L*(M_inv*M_inv)*L #Now add in sparse constraints diagTerms = igl.eigen.SparseMatrixd(VPos.shape[0], VPos.shape[0]) # anchor points for a in anchorsIdx: diagTerms.insert(a, a, anchorWeights) # off points ''' for adx,decay_weight in enumerate(decaying_anchor_weights): if decay_weight == 0: diagTerms.insert(adx, adx, anchorWeights) else: diagTerms.insert(adx, adx, decay_weight) ''' Q = Q + diagTerms Q.makeCompressed() start_time = time.time() solver = igl.eigen.SimplicialLLTsparse(Q) #solver = igl.eigen.CholmodSupernodalLLT(Q) end_time = time.time() print 'factorization elapsed time:',end_time-start_time,'seconds' return (L, M_inv, solver, np.array(deltaCoords))