如何算三角形的cotangent

    xiaoxiao2021-03-26  23

    公式为:

    cotC=a2+b2c24A

    证明 根据余弦定理

    cosC=a2+b2c22ab

    根据面积公式 A=12absinC 所以 sinC=2Aab

    所以 cotC=cosCsinC=a2+b2c22abab2A=a2+b2c24A

    alec jacobson 代码:

    function C = cotangent(V,F,varargin) % COTANGENT compute the cotangents of each angle in mesh (V,F), more details % can be found in Section 1.1 of "Algorithms and Interfaces for Real-Time % Deformation of 2D and 3D shapes" [Jacobson 2013] % % C = cotangent(V,F) % C = cotangent(V,F,'ParameterName',parameter_value,...) % % Known bugs: % This seems to return 0.5*C and for tets already multiplies by % edge-lengths % % Inputs: % V #V by dim list of rest domain positions % F #F by {3|4} list of {triangle|tetrahedra} indices into V % Optional (3-manifolds only): % 'SideLengths' followed by #F by 3 list of edge lengths corresponding % to: 23 31 12. In this case V is ignored. % or % followed by #T by 6 list of tet edges lengths: % 41 42 43 23 31 12 % 'FaceAreas' followed by #T by 4 list of tet face areas % Outputs: % C #F by {3|6} list of cotangents corresponding % angles for triangles, columns correspond to edges 23,31,12 % dihedral angles *times opposite edge length* over 6 for tets, % WRONG: columns correspond to edges 23,31,12,41,42,43 % RIGHT: columns correspond to *faces* 23,31,12,41,42,43 % % See also: cotmatrix % % Copyright 2013, Alec Jacobson (jacobson@inf.ethz.ch) % switch size(F,2) case 3 % default values l = []; % Map of parameter names to variable names params_to_variables = containers.Map( ... {'SideLengths'}, {'l'}); v = 1; while v <= numel(varargin) param_name = varargin{v}; if isKey(params_to_variables,param_name) assert(v+1<=numel(varargin)); v = v+1; % Trick: use feval on anonymous function to use assignin to this workspace feval(@()assignin('caller',params_to_variables(param_name),varargin{v})); else error('Unsupported parameter: %s',varargin{v}); end v=v+1; end assert(numel(varargin) == 0); % triangles if isempty(l) % edge lengths numbered same as opposite vertices l = [ ... sqrt(sum((V(F(:,2),:)-V(F(:,3),:)).^2,2)) ... sqrt(sum((V(F(:,3),:)-V(F(:,1),:)).^2,2)) ... sqrt(sum((V(F(:,1),:)-V(F(:,2),:)).^2,2)) ... ]; end i1 = F(:,1); i2 = F(:,2); i3 = F(:,3); l1 = l(:,1); l2 = l(:,2); l3 = l(:,3); % semiperimeters s = (l1 + l2 + l3)*0.5; % Heron's formula for area dblA = 2*sqrt( s.*(s-l1).*(s-l2).*(s-l3)); % cotangents and diagonal entries for element matrices % correctly divided by 4 (alec 2010) C = [ ... (l2.^2 + l3.^2 -l1.^2)./dblA/4 ... (l1.^2 + l3.^2 -l2.^2)./dblA/4 ... (l1.^2 + l2.^2 -l3.^2)./dblA/4 ... ]; case 4 % Dealing with tets T = F; l = []; s = []; v = 1; while v <= numel(varargin) switch varargin{v} case 'SideLengths' assert((v+1)<=numel(varargin)); v = v+1; l = varargin{v}; case 'FaceAreas' assert((v+1)<=numel(varargin)); v = v+1; s = varargin{v}; otherwise error(['Unsupported parameter: ' varargin{v}]); end v = v+1; end if isempty(l) % lengths of edges opposite *face* pairs: 23 31 12 41 42 43 l = [ ... sqrt(sum((V(T(:,4),:)-V(T(:,1),:)).^2,2)) ... sqrt(sum((V(T(:,4),:)-V(T(:,2),:)).^2,2)) ... sqrt(sum((V(T(:,4),:)-V(T(:,3),:)).^2,2)) ... sqrt(sum((V(T(:,2),:)-V(T(:,3),:)).^2,2)) ... sqrt(sum((V(T(:,3),:)-V(T(:,1),:)).^2,2)) ... sqrt(sum((V(T(:,1),:)-V(T(:,2),:)).^2,2)) ... ]; end % (unsigned) face Areas (opposite vertices: 1 2 3 4) if isempty(s) s = 0.5*[ ... doublearea_intrinsic(l(:,[2 3 4])) ... doublearea_intrinsic(l(:,[1 3 5])) ... doublearea_intrinsic(l(:,[1 2 6])) ... doublearea_intrinsic(l(:,[4 5 6]))]; end [~,cos_theta] = dihedral_angles([],[],'SideLengths',l,'FaceAreas',s); % volume vol = volume_intrinsic(l); %% Law of cosines %% http://math.stackexchange.com/a/49340/35376 %H_sqr = (1/16) * ... % (4*l(:,[4 5 6 1 2 3]).^2.* l(:,[1 2 3 4 5 6]).^2 - ... % ((l(:, [2 3 4 5 6 1]).^2 + l(:,[5 6 1 2 3 4]).^2) - ... % (l(:, [3 4 5 6 1 2]).^2 + l(:,[6 1 2 3 4 5]).^2)).^2); %cos_theta= (H_sqr - s(:,[2 3 1 4 4 4]).^2 - ... % s(:,[3 1 2 1 2 3]).^2)./ ... % (-2*s(:,[2 3 1 4 4 4]).* ... % s(:,[3 1 2 1 2 3])); %% To retrieve dihedral angles stop here... %theta = acos(cos_theta); %theta/pi*180 % Law of sines % http://mathworld.wolfram.com/Tetrahedron.html %sin_theta = bsxfun(@rdivide,vol,(2./(3*l)) .* s(:,[1 2 3 2 3 1]) .* s(:,[4 4 4 3 1 2])); sin_theta = bsxfun(@rdivide,vol,(2./(3*l)) .* s(:,[2 3 1 4 4 4]) .* s(:,[3 1 2 1 2 3])); %% Using sin for dihedral angles gets into trouble with signs %theta = asin(sin_theta); %theta/pi*180 % http://arxiv.org/pdf/1208.0354.pdf Page 18 C = 1/6 * l .* cos_theta ./ sin_theta; %% One should probably never use acot to retrieve signed angles %theta = acot(C); %theta/pi*180 otherwise error('Unsupported simplex type'); end end
    转载请注明原文地址: https://ju.6miu.com/read-658773.html

    最新回复(0)