-
Notifications
You must be signed in to change notification settings - Fork 4
/
Copy pathTriSystemSmoothEnergy.m
163 lines (127 loc) · 4.36 KB
/
TriSystemSmoothEnergy.m
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
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% Smoothed Quadratic Energies on Meshes
%% J. Martinez Esturo, C. Rössl, and H. Theisel
%%
%% ACM Transactions on Graphics 2014
%%
%% Copyright J. Martinez Esturo 2014 (MIT License)
%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
classdef TriSystemSmoothEnergy < handle
%TRISYSTEMSMOOTHENERGY
properties (SetAccess = protected)
AAs
bbs
E = []
b = []
end
properties (Access = protected)
Wn = []
EtWn = []
Um = []
vm = []
en = []
d = []
nv = []
nt = []
%for later total and local energy evaluation
An = []
Bn = []
Dn = []
end
methods
function obj = TriSystemSmoothEnergy(mesh,beta, en, d,c)
%% Generic Smoothed Energy Regularization
% This function implements the generic regularization of
%
% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Smoothed Quadratic Energies on Meshes
% J. Martinez Esturo, C. Rössl, and H. Theisel
%
% ACM Transactions on Graphics 2014
% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% For a given mesh and smoothing value the generic norm W_n is
% setup.
%
% Using the functions updateLHS() and updateRHS() the actual
% discretized energy can be set up.
%
% Its normal equation are given by the properties obj.AAs * u = obj.bbs.
%
%% Input:
% mesh - triangle mesh to apply energy smoothing to
% (mesh.p3_0 is used for integration domain / vertex coordinates)
% beta - smoothing factor in [0,1]
% en - number of quadratic error components per triangle
% d - dimension of unknown coefficients at vertices
% c - number of independent functions to setup system rhs
% (defaults to 1)
%% Output:
% AAs - (property) the normal equations of the energy system
% bbs - (property) the rhs of the normal equations of the energy system
if nargin < 6, c = 1; end
%% number of error components
obj.en = en;
obj.d = d;
obj.nv = mesh.nv;
obj.nt = mesh.nt;
%% compute triangle areas for replicated area weighting
obj.An = sparse(1:(en*obj.nt), 1:(en*obj.nt), repmat(mesh.A0,en,1));
ie = mesh.ie;
%% get internal edge lengths
ie_lengths = mesh.p3_0(:,ie(2,:)) - mesh.p3_0(:,ie(1,:));
ie_lengths = sqrt(sum(ie_lengths .* ie_lengths, 1));
%% setup internal edge difference operator replicated over the en error
% components for each triangle
nie = size(ie,2);
obj.Dn = TriSystemSmoothEnergy.setupEdgeDifferenceOp(mesh,en);
%% replicated edge length diagonal matrices
obj.Bn = sparse(1:(en*nie), 1:(en*nie), repmat(ie_lengths,en,1));
%% final smoothing inner product
obj.Wn = (1-beta) .* obj.An + beta .* obj.Dn'*obj.Bn*obj.Dn;
%% init rhs if b == 0
obj.bbs = zeros(d *obj.nv,c);
obj.b = zeros(en*obj.nt,c);
end
function updateLHS(obj,E)
assert(size(E,1) == obj.nt*obj.en);
assert(size(E,2) == obj.nv*obj.d);
obj.E = E;
obj.EtWn = E'*obj.Wn;
obj.AAs = obj.EtWn*E;
end
function updateRHS(obj,b)
assert(size(obj.E,1) == obj.nt*obj.en);
assert(size(obj.E,1) == size(b,1));
obj.b = b;
obj.bbs = obj.EtWn*b;
end
function [terrEnergy,errEnergy,errSmoothn,errTotal] = ...
evalTriangleErrors(obj,u)
% local problem per triangle errors
e = obj.E * u - obj.b;
terrEnergy = sum(e.*e,2);
terrEnergy = sum(reshape(terrEnergy,obj.en,[]));
if nargout < 2, return; end;
% integrated local errors
errEnergy = trace(e'*obj.An*e);
if nargout < 3, return; end;
% integrated smoothness errors
errSmoothn = obj.Dn*e;
errSmoothn = trace(errSmoothn'*obj.Bn*errSmoothn);
errTotal = errEnergy + errSmoothn;
end
end
methods(Static, Access = private)
function D = setupEdgeDifferenceOp(mesh,n)
ie = mesh.ie;
iet = mesh.iet;
nie = size(ie,2);
D_i = [1:(n*nie),1:(n*nie)];
D_j = repmat([n.*(iet(1,:)-1)+1,n.*(iet(2,:)-1)+1],n,1) + ...
repmat((0:(n-1))',1,2*nie);
D_v = [ones(n*size(iet,2),1),-1.*ones(n*size(iet,2),1)];
D = sparse(D_i, D_j, D_v, n * nie, n * mesh.nt);
end
end
end