Switch to unified view

a b/Cobiveco/functions/computeLongAxis.m
1
function longAx = computeLongAxis(sur, directionVec)
2
% Computes the heart's long axis as the vector minimizing the dot product
3
% with the surface normals of the LV endocardium, i.e. the vector that is
4
% "most orthogonal" to the surface normals.
5
%
6
% longAx = computeLongAxis(sur, basePoints)
7
%
8
% Inputs:
9
%   sur: LV endocardial surface as VTK struct
10
%   directionVec: A vector coarsely directed from base towards apex
11
%
12
% Outputs:
13
%   longAx: Unit vector directed from base towards apex
14
%
15
% Written by Steffen Schuler, Institute of Biomedical Engineering, KIT
16
17
TR = vtkToTriangulation(sur);
18
normals = TR.faceNormal;
19
areaWeights = doublearea(TR.Points, TR.ConnectivityList);
20
areaWeights = areaWeights/mean(areaWeights);
21
22
% p-norm is chosen to have average properties of 1-norm and 2-norm
23
h = (1/sqrt(2)+1)/2;
24
p = 1/(log2(sqrt(2)/h));
25
26
objFun = @(longAxis) sum(abs(areaWeights.*normals*longAxis').^p) + size(normals,1)*abs(norm(longAxis)-1)^p;
27
options = optimset('MaxFunEvals', 1e4);
28
longAx = NaN(3);
29
objVal = NaN(3,1);
30
[longAx(1,:),objVal(1)] = fminsearch(objFun, [1 0 0], options);
31
[longAx(2,:),objVal(2)] = fminsearch(objFun, [0 1 0], options);
32
[longAx(3,:),objVal(3)] = fminsearch(objFun, [0 0 1], options);
33
[~,minInd] = min(objVal);
34
longAx = longAx(minInd,:);
35
longAx = longAx/norm(longAx);
36
37
% make sure longAxis is directed from base towards apex
38
d = directionVec(:)' * longAx';
39
longAx = sign(d) * longAx;
40
41
end