[390c2f]: / Cobiveco / utilities / inputPreparation / cobiveco_createClasses.m

Download this file

85 lines (73 with data), 2.9 kB

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
function [sur,debug] = cobiveco_createClasses(sur, baseNormal, maxAngle, numSubdiv)
if nargin < 4 || isempty(numSubdiv)
numSubdiv = 0;
end
s = vtkLoopSubdivisionFilter(sur, numSubdiv);
tr = vtkToTriangulation(s);
dotProd = double(tr.faceNormal * baseNormal');
dotProd = min(max(dotProd,-1),1);
s.cellData.angle = acos(-dotProd)/pi*180;
centroids = vtkCellCentroids(s);
center = vtkCenterOfArea(s);
s.cellData.centerDist = (centroids.points-center)*baseNormal';
s.pointData.centerDist = (s.points-center)*baseNormal';
s.cellData.base = double(s.cellData.angle < maxAngle & s.cellData.centerDist < 0);
s.pointData.ids = int32(1:size(s.points,1))';
base = vtkConnectivityFilter(vtkThreshold(s, 'cells', 'base', [1 inf]));
idsUnknown = [];
if numel(unique(base.pointData.RegionId)) > 1
rid = mode(base.pointData.RegionId);
idsUnknown = base.pointData.ids(base.pointData.RegionId ~= rid);
end
nonbase = vtkConnectivityFilter(vtkThreshold(s, 'cells', 'base', [-inf 0]));
if numel(unique(nonbase.pointData.RegionId)) ~= 3
warning('cobiveco_createClasses: Number of non-base regions ~= 3. Manual interaction needed - aborting.');
debug = s;
return;
end
region = cell(3,1);
radius = NaN(3,1);
region{1} = vtkThreshold(nonbase, 'points', 'RegionId', [0 0]);
region{2} = vtkThreshold(nonbase, 'points', 'RegionId', [1 1]);
region{3} = vtkThreshold(nonbase, 'points', 'RegionId', [2 2]);
[~,radius(1)] = vtkSmallestEnclosingSphere(region{1});
[~,radius(2)] = vtkSmallestEnclosingSphere(region{2});
[~,radius(3)] = vtkSmallestEnclosingSphere(region{3});
[~,epiInd] = max(radius);
endoInd = setdiff(1:3,epiInd);
epi = region{epiInd};
endo1 = region{endoInd(1)};
endo2 = region{endoInd(2)};
contour1 = vtkContourFilter(endo1, 'points', 'centerDist', 0);
contour2 = vtkContourFilter(endo2, 'points', 'centerDist', 0);
d1 = min(sqrt(sum((contour1.points-center).^2,2)));
d2 = min(sqrt(sum((contour2.points-center).^2,2)));
ids_epi = vtkMapPointIds(s, epi);
if d1 < d2
ids_lv = vtkMapPointIds(s, endo1);
ids_rv = vtkMapPointIds(s, endo2);
else
ids_lv = vtkMapPointIds(s, endo2);
ids_rv = vtkMapPointIds(s, endo1);
end
s.pointData.class = ones(size(s.points,1), 1, 'uint8');
s.pointData.class(ids_epi) = 2;
s.pointData.class(ids_lv) = 3;
s.pointData.class(ids_rv) = 4;
if any(idsUnknown)
L = cotmatrix(double(s.points), double(s.cells));
idsKnown = setdiff(1:size(s.points,1), idsUnknown);
s.pointData.class = uint8(round(solveLaplace(L, idsKnown, double(s.pointData.class(idsKnown)))));
end
debug = s;
s = vtkDeleteDataArrays(s, {'pointData.class'});
if numSubdiv > 0
sur.pointData.class = zeros(size(sur.points,1), 1, 'uint8');
ids = vtkMapPointIds(sur, s);
for i = 1:size(sur.points,1)
sur.pointData.class(i) = mode(s.pointData.class(ismember(ids, i)));
end
else
sur = s;
end
end