cotangent matrix or laplacian mesh operator

来源:互联网 发布:eclipse 测试java程序 编辑:程序博客网 时间:2024/06/13 03:56

Actually, stiffness matrix can be transformed to cotangent matrix. In regard to stiffness matrix please refer http://blog.csdn.net/seamanj/article/details/51359991



https://uk.mathworks.com/matlabcentral/fileexchange/49692-gptoolbox

C:\TestMatlab\alec_jacobson\alecjacobson-gptoolbox-9dc4ff4\mesh\cotmatrix.m



function L = cotmatrix(V,F)  % COTMATRIX computes cotangent matrix (laplacian mesh operator), (mass/area  % terms already cancelled out)  %  % L = cotmatrix(V,F)  % L = cotmatrix(V,T)  %  % For size(F,2)==4, This is distinctly NOT following definition that appears  % in the appendix of: ``Interactive Topology-aware Surface Reconstruction,''  % by Sharf, A. et al  % http://www.cs.bgu.ac.il/~asharf/Projects/InSuRe/Insure_siggraph_final.pdf  %  % Instead it is a purely geometric construction. Find more details in Section  % 1.1 of "Algorithms and Interfaces for Real-Time Deformation of 2D and 3D  % shapes" [Jacobson 2013]  %  % ND derivation given in "A MONOTONE FINITE ELEMENT SCHEME FOR  % CONVECTION-DIFFUSION EQUATIONS" [Xu & ZIKATANOV 1999]  %  % 3D derivation given in "Aspects of unstructured grids and finite-volume  % solvers for the Euler and Navier-Stokes equations" [Barth 1992]  %  %  % Inputs:  %   V  #V x dim matrix of vertex coordinates  %   F  #F x simplex-size matrix of indices of triangle or tetrahedron corners  % Outputs:  %   L  sparse #V x #V matrix of cot weights   %  % Copyright 2011, Alec Jacobson (jacobson@inf.ethz.ch), Denis Zorin  %  % See also: cotangent  %  ss = size(F,2);  switch ss  case 3    %% Could just replace everything with:    %C = cotangent(V,F);    %L = sparse(F(:,[2 3 1]), F(:,[3 1 2]), C,size(V,1),size(V,1));    %L = L+L';    %L = L-diag(sum(L,2));        % should change code below, so we don't need this transpose    if(size(F,1) == 3)      warning('F seems to be 3 by #F, it should be #F by 3');    end    F = F';    % renaming indices of vertices of triangles for convenience    i1 = F(1,:); i2 = F(2,:); i3 = F(3,:);     % #F x 3 matrices of triangle edge vectors, named after opposite vertices    v1 = V(i3,:) - V(i2,:);  v2 = V(i1,:) - V(i3,:); v3 = V(i2,:) - V(i1,:);    % computing *unsigned* areas     if size(V,2) == 2        % 2d vertex data        dblA = abs(v1(:,1).*v2(:,2)-v1(:,2).*v2(:,1));    elseif size(V,2) == 3        %n  = cross(v1,v2,2);  dblA  = multinorm(n,2);        % area of parallelogram is twice area of triangle        % area of parallelogram is || v1 x v2 ||         n  = cross(v1,v2,2);         % THIS DOES MATRIX NORM!!! don't use it!!        % dblA  = norm(n,2);        % This does correct l2 norm of rows        dblA = (sqrt(sum((n').^2)))';    else         error('unsupported vertex dimension %d', size(V,2))    end    % cotangents and diagonal entries for element matrices    cot12 = -dot(v1,v2,2)./dblA/2; cot23 = -dot(v2,v3,2)./dblA/2; cot31 = -dot(v3,v1,2)./dblA/2;    % diag entries computed from the condition that rows of the matrix sum up to 1    % (follows from  the element matrix formula E_{ij} = (v_i dot v_j)/4/A )    diag1 = -cot12-cot31; diag2 = -cot12-cot23; diag3 = -cot31-cot23;    % indices of nonzero elements in the matrix for sparse() constructor    i = [i1 i2 i2 i3 i3 i1  i1 i2 i3];    j = [i2 i1 i3 i2 i1 i3  i1 i2 i3];    % values corresponding to pairs form (i,j)    v = [cot12 cot12 cot23 cot23 cot31 cot31 diag1 diag2 diag3];    % for repeated indices (i,j) sparse automatically sums up elements, as we    % want    L = sparse(i,j,v,size(V,1),size(V,1));  case 4    if(size(F,1) == 4 && size(F,2) ~=4)      warning('F seems to be 4 by #F, it should be #F by 4');    end    % number of mesh vertices    n = size(V,1);    % cotangents of dihedral angles    C = cotangent(V,F);    %% TODO: fix cotangent to have better accuracy so this isn't necessary    %% Zero-out almost zeros to help sparsity    %C(abs(C)<10*eps) = 0;    % add to entries    L = sparse(F(:,[2 3 1 4 4 4]),F(:,[3 1 2 1 2 3]),C,n,n);    % add in other direction    L = L + L';    % diagonal is minus sum of offdiagonal entries    L = L - diag(sum(L,2));    %% divide by factor so that regular grid laplacian matches finite-difference    %% laplacian in interior    %L = L./(4+2/3*sqrt(3));    %% multiply by factor so that matches legacy laplacian in sign and    %% "off-by-factor-of-two-ness"    %L = L*0.5;    % flip sign to match cotmatix.m    if(all(diag(L)>0))      warning('Flipping sign of cotmatrix3, so that diag is negative');      L = -L;    end  endend


0 0