1 |
|
|
/* |
2 |
|
|
Teem: Tools to process and visualize scientific data and images . |
3 |
|
|
Copyright (C) 2013, 2012, 2011, 2010, 2009 University of Chicago |
4 |
|
|
Copyright (C) 2008, 2007, 2006, 2005 Gordon Kindlmann |
5 |
|
|
Copyright (C) 2004, 2003, 2002, 2001, 2000, 1999, 1998 University of Utah |
6 |
|
|
|
7 |
|
|
This library is free software; you can redistribute it and/or |
8 |
|
|
modify it under the terms of the GNU Lesser General Public License |
9 |
|
|
(LGPL) as published by the Free Software Foundation; either |
10 |
|
|
version 2.1 of the License, or (at your option) any later version. |
11 |
|
|
The terms of redistributing and/or modifying this software also |
12 |
|
|
include exceptions to the LGPL that facilitate static linking. |
13 |
|
|
|
14 |
|
|
This library is distributed in the hope that it will be useful, |
15 |
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of |
16 |
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
17 |
|
|
Lesser General Public License for more details. |
18 |
|
|
|
19 |
|
|
You should have received a copy of the GNU Lesser General Public License |
20 |
|
|
along with this library; if not, write to Free Software Foundation, Inc., |
21 |
|
|
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
22 |
|
|
*/ |
23 |
|
|
|
24 |
|
|
#include "ten.h" |
25 |
|
|
#include "privateTen.h" |
26 |
|
|
|
27 |
|
|
/* |
28 |
|
|
** learned: don't take sqrt(FLT_EPSILON) and expect it to still be |
29 |
|
|
** negligible |
30 |
|
|
*/ |
31 |
|
|
|
32 |
|
|
/* |
33 |
|
|
******** !!!! NOTE NOTE NOTE NOTE NOTE !!!! |
34 |
|
|
******** |
35 |
|
|
******** THIS CODE IS NOT REALLY MEANT TO BE EDITED BY HUMANS |
36 |
|
|
******** (only GLK :) |
37 |
|
|
******** |
38 |
|
|
******** It is the worst possible example of the dangers of cut-and-paste |
39 |
|
|
******** |
40 |
|
|
******** !!!! NOTE NOTE NOTE NOTE NOTE !!!! |
41 |
|
|
*/ |
42 |
|
|
float _tenAnisoEval_Conf_f(const float eval[3]) { |
43 |
|
|
AIR_UNUSED(eval); |
44 |
|
|
return 1.0; |
45 |
|
|
} |
46 |
|
|
double _tenAnisoEval_Conf_d(const double eval[3]) { |
47 |
|
|
AIR_UNUSED(eval); |
48 |
|
|
return 1.0; return 1.0; |
49 |
|
|
} |
50 |
|
|
float _tenAnisoTen_Conf_f(const float ten[7]) { |
51 |
|
|
return ten[0]; |
52 |
|
|
} |
53 |
|
|
double _tenAnisoTen_Conf_d(const double ten[7]) { |
54 |
|
|
return ten[0]; |
55 |
|
|
} |
56 |
|
|
|
57 |
|
|
|
58 |
|
|
float _tenAnisoEval_Cl1_f(const float eval[3]) { |
59 |
|
|
float sum = eval[0] + eval[1] + eval[2]; |
60 |
|
|
sum = AIR_MAX(0, sum); |
61 |
|
|
return sum ? (eval[0] - eval[1])/sum : 0.0f; |
62 |
|
|
} |
63 |
|
|
double _tenAnisoEval_Cl1_d(const double eval[3]) { |
64 |
|
|
double sum = eval[0] + eval[1] + eval[2]; |
65 |
|
|
sum = AIR_MAX(0, sum); |
66 |
|
|
return sum ? (eval[0] - eval[1])/sum : 0.0; |
67 |
|
|
} |
68 |
|
|
float _tenAnisoTen_Cl1_f(const float ten[7]) { |
69 |
|
|
float eval[3]; |
70 |
|
|
tenEigensolve_f(eval, NULL, ten); |
71 |
|
|
return _tenAnisoEval_Cl1_f(eval); |
72 |
|
|
} |
73 |
|
|
double _tenAnisoTen_Cl1_d(const double ten[7]) { |
74 |
|
|
double eval[3]; |
75 |
|
|
tenEigensolve_d(eval, NULL, ten); |
76 |
|
|
return _tenAnisoEval_Cl1_d(eval); |
77 |
|
|
} |
78 |
|
|
|
79 |
|
|
|
80 |
|
|
float _tenAnisoEval_Cp1_f(const float eval[3]) { |
81 |
|
|
float sum = eval[0] + eval[1] + eval[2]; |
82 |
|
|
sum = AIR_MAX(0, sum); |
83 |
|
|
return sum ? 2*(eval[1] - eval[2])/sum : 0.0f; |
84 |
|
|
} |
85 |
|
|
double _tenAnisoEval_Cp1_d(const double eval[3]) { |
86 |
|
|
double sum = eval[0] + eval[1] + eval[2]; |
87 |
|
|
sum = AIR_MAX(0, sum); |
88 |
|
|
return sum ? 2*(eval[1] - eval[2])/sum : 0.0; |
89 |
|
|
} |
90 |
|
|
float _tenAnisoTen_Cp1_f(const float ten[7]) { |
91 |
|
|
float eval[3]; |
92 |
|
|
tenEigensolve_f(eval, NULL, ten); |
93 |
|
|
return _tenAnisoEval_Cp1_f(eval); |
94 |
|
|
} |
95 |
|
|
double _tenAnisoTen_Cp1_d(const double ten[7]) { |
96 |
|
|
double eval[3]; |
97 |
|
|
tenEigensolve_d(eval, NULL, ten); |
98 |
|
|
return _tenAnisoEval_Cp1_d(eval); |
99 |
|
|
} |
100 |
|
|
|
101 |
|
|
|
102 |
|
|
float _tenAnisoEval_Ca1_f(const float eval[3]) { |
103 |
|
|
float sum = eval[0] + eval[1] + eval[2]; |
104 |
|
|
sum = AIR_MAX(0, sum); |
105 |
|
|
return sum ? (eval[0] + eval[1] - 2*eval[2])/sum : 0.0f; |
106 |
|
|
} |
107 |
|
|
double _tenAnisoEval_Ca1_d(const double eval[3]) { |
108 |
|
|
double sum = eval[0] + eval[1] + eval[2]; |
109 |
|
|
sum = AIR_MAX(0, sum); |
110 |
|
|
return sum ? (eval[0] + eval[1] - 2*eval[2])/sum : 0.0; |
111 |
|
|
} |
112 |
|
|
float _tenAnisoTen_Ca1_f(const float ten[7]) { |
113 |
|
|
float eval[3]; |
114 |
|
|
tenEigensolve_f(eval, NULL, ten); |
115 |
|
|
return _tenAnisoEval_Ca1_f(eval); |
116 |
|
|
} |
117 |
|
|
double _tenAnisoTen_Ca1_d(const double ten[7]) { |
118 |
|
|
double eval[3]; |
119 |
|
|
tenEigensolve_d(eval, NULL, ten); |
120 |
|
|
return _tenAnisoEval_Ca1_d(eval); |
121 |
|
|
} |
122 |
|
|
|
123 |
|
|
|
124 |
|
|
float _tenAnisoEval_Clpmin1_f(const float eval[3]) { |
125 |
|
|
float cl, cp, sum = eval[0] + eval[1] + eval[2]; |
126 |
|
|
sum = AIR_MAX(0, sum); |
127 |
|
|
cl = sum ? (eval[0] - eval[1])/sum : 0.0f; |
128 |
|
|
cp = sum ? 2*(eval[1] - eval[2])/sum : 0.0f; |
129 |
|
|
return AIR_MIN(cl, cp); |
130 |
|
|
} |
131 |
|
|
double _tenAnisoEval_Clpmin1_d(const double eval[3]) { |
132 |
|
|
double cl, cp, sum = eval[0] + eval[1] + eval[2]; |
133 |
|
|
sum = AIR_MAX(0, sum); |
134 |
|
|
cl = sum ? (eval[0] - eval[1])/sum : 0.0; |
135 |
|
|
cp = sum ? 2*(eval[1] - eval[2])/sum : 0.0; |
136 |
|
|
return AIR_MIN(cl, cp); |
137 |
|
|
} |
138 |
|
|
float _tenAnisoTen_Clpmin1_f(const float ten[7]) { |
139 |
|
|
float eval[3]; |
140 |
|
|
tenEigensolve_f(eval, NULL, ten); |
141 |
|
|
return _tenAnisoEval_Clpmin1_f(eval); |
142 |
|
|
} |
143 |
|
|
double _tenAnisoTen_Clpmin1_d(const double ten[7]) { |
144 |
|
|
double eval[3]; |
145 |
|
|
tenEigensolve_d(eval, NULL, ten); |
146 |
|
|
return _tenAnisoEval_Clpmin1_d(eval); |
147 |
|
|
} |
148 |
|
|
|
149 |
|
|
|
150 |
|
|
float _tenAnisoEval_Cs1_f(const float eval[3]) { |
151 |
|
|
float sum = eval[0] + eval[1] + eval[2]; |
152 |
|
|
sum = AIR_MAX(0, sum); |
153 |
|
|
return sum ? 3*eval[2]/sum : 0.0f; |
154 |
|
|
} |
155 |
|
|
double _tenAnisoEval_Cs1_d(const double eval[3]) { |
156 |
|
|
double sum = eval[0] + eval[1] + eval[2]; |
157 |
|
|
sum = AIR_MAX(0, sum); |
158 |
|
|
return sum ? 3*eval[2]/sum : 0.0; |
159 |
|
|
} |
160 |
|
|
float _tenAnisoTen_Cs1_f(const float ten[7]) { |
161 |
|
|
float eval[3]; |
162 |
|
|
tenEigensolve_f(eval, NULL, ten); |
163 |
|
|
return _tenAnisoEval_Cs1_f(eval); |
164 |
|
|
} |
165 |
|
|
double _tenAnisoTen_Cs1_d(const double ten[7]) { |
166 |
|
|
double eval[3]; |
167 |
|
|
tenEigensolve_d(eval, NULL, ten); |
168 |
|
|
return _tenAnisoEval_Cs1_d(eval); |
169 |
|
|
} |
170 |
|
|
|
171 |
|
|
|
172 |
|
|
float _tenAnisoEval_Ct1_f(const float _eval[3]) { |
173 |
|
|
float dem, mn, eval[3]; |
174 |
|
|
mn = (_eval[0] + _eval[1] + _eval[2])/3; |
175 |
|
|
ELL_3V_SET(eval, _eval[0] - mn, _eval[1] - mn, _eval[2] - mn); |
176 |
|
|
dem = eval[0] + eval[1] - 2*eval[2]; |
177 |
|
|
return dem ? 2*(eval[1] - eval[2])/dem : 0.0f; |
178 |
|
|
} |
179 |
|
|
double _tenAnisoEval_Ct1_d(const double _eval[3]) { |
180 |
|
|
double dem, mn, eval[3]; |
181 |
|
|
mn = (_eval[0] + _eval[1] + _eval[2])/3; |
182 |
|
|
ELL_3V_SET(eval, _eval[0] - mn, _eval[1] - mn, _eval[2] - mn); |
183 |
|
|
dem = eval[0] + eval[1] - 2*eval[2]; |
184 |
|
|
return dem ? 2*(eval[1] - eval[2])/dem : 0.0; |
185 |
|
|
} |
186 |
|
|
float _tenAnisoTen_Ct1_f(const float ten[7]) { |
187 |
|
|
float eval[3]; |
188 |
|
|
tenEigensolve_f(eval, NULL, ten); |
189 |
|
|
return _tenAnisoEval_Ct1_f(eval); |
190 |
|
|
} |
191 |
|
|
double _tenAnisoTen_Ct1_d(const double ten[7]) { |
192 |
|
|
double eval[3]; |
193 |
|
|
tenEigensolve_d(eval, NULL, ten); |
194 |
|
|
return _tenAnisoEval_Ct1_d(eval); |
195 |
|
|
} |
196 |
|
|
|
197 |
|
|
|
198 |
|
|
float _tenAnisoEval_Cl2_f(const float eval[3]) { |
199 |
|
|
float eval0 = AIR_MAX(0, eval[0]); |
200 |
|
|
return eval0 ? (eval[0] - eval[1])/eval0 : 0.0f; |
201 |
|
|
} |
202 |
|
|
double _tenAnisoEval_Cl2_d(const double eval[3]) { |
203 |
|
|
double eval0 = AIR_MAX(0, eval[0]); |
204 |
|
|
return eval0 ? (eval[0] - eval[1])/eval0 : 0.0; |
205 |
|
|
} |
206 |
|
|
float _tenAnisoTen_Cl2_f(const float ten[7]) { |
207 |
|
|
float eval[3]; |
208 |
|
|
tenEigensolve_f(eval, NULL, ten); |
209 |
|
|
return _tenAnisoEval_Cl2_f(eval); |
210 |
|
|
} |
211 |
|
|
double _tenAnisoTen_Cl2_d(const double ten[7]) { |
212 |
|
|
double eval[3]; |
213 |
|
|
tenEigensolve_d(eval, NULL, ten); |
214 |
|
|
return _tenAnisoEval_Cl2_d(eval); |
215 |
|
|
} |
216 |
|
|
|
217 |
|
|
|
218 |
|
|
float _tenAnisoEval_Cp2_f(const float eval[3]) { |
219 |
|
|
float eval0 = AIR_MAX(0, eval[0]); |
220 |
|
|
return eval0 ? (eval[1] - eval[2])/eval0 : 0.0f; |
221 |
|
|
} |
222 |
|
|
double _tenAnisoEval_Cp2_d(const double eval[3]) { |
223 |
|
|
double eval0 = AIR_MAX(0, eval[0]); |
224 |
|
|
return eval0 ? (eval[1] - eval[2])/eval0 : 0.0; |
225 |
|
|
} |
226 |
|
|
float _tenAnisoTen_Cp2_f(const float ten[7]) { |
227 |
|
|
float eval[3]; |
228 |
|
|
tenEigensolve_f(eval, NULL, ten); |
229 |
|
|
return _tenAnisoEval_Cp2_f(eval); |
230 |
|
|
} |
231 |
|
|
double _tenAnisoTen_Cp2_d(const double ten[7]) { |
232 |
|
|
double eval[3]; |
233 |
|
|
tenEigensolve_d(eval, NULL, ten); |
234 |
|
|
return _tenAnisoEval_Cp2_d(eval); |
235 |
|
|
} |
236 |
|
|
|
237 |
|
|
|
238 |
|
|
float _tenAnisoEval_Ca2_f(const float eval[3]) { |
239 |
|
|
float eval0 = AIR_MAX(0, eval[0]); |
240 |
|
|
return eval0 ? (eval[0] - eval[2])/eval0 : 0.0f; |
241 |
|
|
} |
242 |
|
|
double _tenAnisoEval_Ca2_d(const double eval[3]) { |
243 |
|
|
double eval0 = AIR_MAX(0, eval[0]); |
244 |
|
|
return eval0 ? (eval[0] - eval[2])/eval0 : 0.0; |
245 |
|
|
} |
246 |
|
|
float _tenAnisoTen_Ca2_f(const float ten[7]) { |
247 |
|
|
float eval[3]; |
248 |
|
|
tenEigensolve_f(eval, NULL, ten); |
249 |
|
|
return _tenAnisoEval_Ca2_f(eval); |
250 |
|
|
} |
251 |
|
|
double _tenAnisoTen_Ca2_d(const double ten[7]) { |
252 |
|
|
double eval[3]; |
253 |
|
|
tenEigensolve_d(eval, NULL, ten); |
254 |
|
|
return _tenAnisoEval_Ca2_d(eval); |
255 |
|
|
} |
256 |
|
|
|
257 |
|
|
|
258 |
|
|
float _tenAnisoEval_Clpmin2_f(const float eval[3]) { |
259 |
|
|
float cl, cp, eval0 = AIR_MAX(0, eval[0]); |
260 |
|
|
cl = eval0 ? (eval[0] - eval[1])/eval0 : 0.0f; |
261 |
|
|
cp = eval0 ? (eval[1] - eval[2])/eval0 : 0.0f; |
262 |
|
|
return AIR_MIN(cl, cp); |
263 |
|
|
} |
264 |
|
|
double _tenAnisoEval_Clpmin2_d(const double eval[3]) { |
265 |
|
|
double cl, cp, eval0 = AIR_MAX(0, eval[0]); |
266 |
|
|
cl = eval0 ? (eval[0] - eval[1])/eval0 : 0.0; |
267 |
|
|
cp = eval0 ? (eval[1] - eval[2])/eval0 : 0.0; |
268 |
|
|
return AIR_MIN(cl, cp); |
269 |
|
|
} |
270 |
|
|
float _tenAnisoTen_Clpmin2_f(const float ten[7]) { |
271 |
|
|
float eval[3]; |
272 |
|
|
tenEigensolve_f(eval, NULL, ten); |
273 |
|
|
return _tenAnisoEval_Clpmin2_f(eval); |
274 |
|
|
} |
275 |
|
|
double _tenAnisoTen_Clpmin2_d(const double ten[7]) { |
276 |
|
|
double eval[3]; |
277 |
|
|
tenEigensolve_d(eval, NULL, ten); |
278 |
|
|
return _tenAnisoEval_Clpmin2_d(eval); |
279 |
|
|
} |
280 |
|
|
|
281 |
|
|
|
282 |
|
|
float _tenAnisoEval_Cs2_f(const float eval[3]) { |
283 |
|
|
float eval0 = AIR_MAX(0, eval[0]); |
284 |
|
|
return eval0 ? eval[2]/eval0 : 0.0f; |
285 |
|
|
} |
286 |
|
|
double _tenAnisoEval_Cs2_d(const double eval[3]) { |
287 |
|
|
double eval0 = AIR_MAX(0, eval[0]); |
288 |
|
|
return eval0 ? eval[2]/eval0 : 0.0; |
289 |
|
|
} |
290 |
|
|
float _tenAnisoTen_Cs2_f(const float ten[7]) { |
291 |
|
|
float eval[3]; |
292 |
|
|
tenEigensolve_f(eval, NULL, ten); |
293 |
|
|
return _tenAnisoEval_Cs2_f(eval); |
294 |
|
|
} |
295 |
|
|
double _tenAnisoTen_Cs2_d(const double ten[7]) { |
296 |
|
|
double eval[3]; |
297 |
|
|
tenEigensolve_d(eval, NULL, ten); |
298 |
|
|
return _tenAnisoEval_Cs2_d(eval); |
299 |
|
|
} |
300 |
|
|
|
301 |
|
|
|
302 |
|
|
float _tenAnisoEval_Ct2_f(const float eval[3]) { |
303 |
|
|
float denom; |
304 |
|
|
denom = eval[0] - eval[2]; |
305 |
|
|
return denom ? (eval[1] - eval[2])/denom : 0.0f; |
306 |
|
|
} |
307 |
|
|
double _tenAnisoEval_Ct2_d(const double eval[3]) { |
308 |
|
|
double denom; |
309 |
|
|
denom = eval[0] - eval[2]; |
310 |
|
|
return denom ? (eval[1] - eval[2])/denom : 0.0; |
311 |
|
|
} |
312 |
|
|
float _tenAnisoTen_Ct2_f(const float ten[7]) { |
313 |
|
|
float eval[3]; |
314 |
|
|
tenEigensolve_f(eval, NULL, ten); |
315 |
|
|
return _tenAnisoEval_Ct2_f(eval); |
316 |
|
|
} |
317 |
|
|
double _tenAnisoTen_Ct2_d(const double ten[7]) { |
318 |
|
|
double eval[3]; |
319 |
|
|
tenEigensolve_d(eval, NULL, ten); |
320 |
|
|
return _tenAnisoEval_Ct2_d(eval); |
321 |
|
|
} |
322 |
|
|
|
323 |
|
|
|
324 |
|
|
#define SQRT6 2.44948974278317809819 |
325 |
|
|
float _tenAnisoEval_RA_f(const float eval[3]) { |
326 |
|
|
float mean, stdv; |
327 |
|
|
mean = (eval[0] + eval[1] + eval[2])/3; |
328 |
|
|
stdv = AIR_CAST(float, |
329 |
|
|
sqrt((mean-eval[0])*(mean-eval[0]) /* not exactly stdv */ |
330 |
|
|
+ (mean-eval[1])*(mean-eval[1]) |
331 |
|
|
+ (mean-eval[2])*(mean-eval[2]))); |
332 |
|
|
return mean ? AIR_CAST(float, stdv/(mean*SQRT6)) : 0.0f; |
333 |
|
|
} |
334 |
|
|
double _tenAnisoEval_RA_d(const double eval[3]) { |
335 |
|
|
double mean, stdv; |
336 |
|
|
mean = (eval[0] + eval[1] + eval[2])/3; |
337 |
|
|
stdv = sqrt((mean-eval[0])*(mean-eval[0]) /* not exactly standard dev */ |
338 |
|
|
+ (mean-eval[1])*(mean-eval[1]) |
339 |
|
|
+ (mean-eval[2])*(mean-eval[2])); |
340 |
|
|
return mean ? stdv/(mean*SQRT6) : 0.0; |
341 |
|
|
} |
342 |
|
|
float _tenAnisoTen_RA_f(const float tt[7]) { |
343 |
|
|
float mn, stdv, dev[7]; |
344 |
|
|
mn = TEN_T_TRACE(tt)/3; |
345 |
|
|
TEN_T_SET(dev, tt[0], tt[1]-mn, tt[2], tt[3], tt[4]-mn, tt[5], tt[6]-mn); |
346 |
|
|
stdv = AIR_CAST(float, sqrt(TEN_T_DOT(dev, dev))); |
347 |
|
|
return mn ? AIR_CAST(float, stdv/(mn*SQRT6)) : 0.0f; |
348 |
|
|
} |
349 |
|
|
double _tenAnisoTen_RA_d(const double tt[7]) { |
350 |
|
|
double mn, stdv, dev[7]; |
351 |
|
|
mn = TEN_T_TRACE(tt)/3; |
352 |
|
|
TEN_T_SET(dev, tt[0], tt[1]-mn, tt[2], tt[3], tt[4]-mn, tt[5], tt[6]-mn); |
353 |
|
|
stdv = sqrt(TEN_T_DOT(dev, dev)); |
354 |
|
|
return mn ? stdv/(mn*SQRT6) : 0.0; |
355 |
|
|
} |
356 |
|
|
|
357 |
|
|
|
358 |
|
|
float _tenAnisoEval_FA_f(const float eval[3]) { |
359 |
|
|
float denom, mean, stdv; |
360 |
|
|
denom = 2.0f*(eval[0]*eval[0] + eval[1]*eval[1] + eval[2]*eval[2]); |
361 |
|
|
mean = (eval[0] + eval[1] + eval[2])/3; |
362 |
|
|
stdv = AIR_CAST(float, |
363 |
|
|
(mean-eval[0])*(mean-eval[0]) /* not exactly stdv */ |
364 |
|
|
+ (mean-eval[1])*(mean-eval[1]) |
365 |
|
|
+ (mean-eval[2])*(mean-eval[2])); |
366 |
|
|
return denom ? AIR_CAST(float, sqrt(3.0*stdv/denom)) : 0.0f; |
367 |
|
|
} |
368 |
|
|
double _tenAnisoEval_FA_d(const double eval[3]) { |
369 |
|
|
double denom, mean, stdv; |
370 |
|
|
denom = 2.0*(eval[0]*eval[0] + eval[1]*eval[1] + eval[2]*eval[2]); |
371 |
|
|
mean = (eval[0] + eval[1] + eval[2])/3; |
372 |
|
|
stdv = ((mean-eval[0])*(mean-eval[0]) /* not exactly standard dev */ |
373 |
|
|
+ (mean-eval[1])*(mean-eval[1]) |
374 |
|
|
+ (mean-eval[2])*(mean-eval[2])); |
375 |
|
|
return denom ? sqrt(3.0*stdv/denom) : 0.0; |
376 |
|
|
} |
377 |
|
|
float _tenAnisoTen_FA_f(const float tt[7]) { |
378 |
|
|
float denom, mn, stdv, dev[7]; |
379 |
|
|
denom = AIR_CAST(float, 2.0*TEN_T_DOT(tt, tt)); |
380 |
|
|
mn = TEN_T_TRACE(tt)/3; |
381 |
|
|
TEN_T_SET(dev, tt[0], tt[1]-mn, tt[2], tt[3], tt[4]-mn, tt[5], tt[6]-mn); |
382 |
|
|
stdv = TEN_T_DOT(dev, dev); |
383 |
|
|
return denom ? AIR_CAST(float, sqrt(3.0*stdv/denom)) : 0.0f; |
384 |
|
|
} |
385 |
|
|
double _tenAnisoTen_FA_d(const double tt[7]) { |
386 |
|
|
double denom, mn, stdv, dev[7]; |
387 |
|
|
denom = 2.0*TEN_T_DOT(tt, tt); |
388 |
|
|
mn = TEN_T_TRACE(tt)/3; |
389 |
|
|
TEN_T_SET(dev, tt[0], tt[1]-mn, tt[2], tt[3], tt[4]-mn, tt[5], tt[6]-mn); |
390 |
|
|
stdv = TEN_T_DOT(dev, dev); |
391 |
|
|
return denom ? AIR_CAST(float, sqrt(3.0*stdv/denom)) : 0.0; |
392 |
|
|
} |
393 |
|
|
|
394 |
|
|
|
395 |
|
|
float _tenAnisoEval_VF_f(const float eval[3]) { |
396 |
|
|
float mean; |
397 |
|
|
mean = (eval[0] + eval[1] + eval[2])/3.0f; |
398 |
|
|
mean = mean*mean*mean; |
399 |
|
|
return 1.0f - (mean ? eval[0]*eval[1]*eval[2]/mean : 0.0f); |
400 |
|
|
} |
401 |
|
|
double _tenAnisoEval_VF_d(const double eval[3]) { |
402 |
|
|
double mean; |
403 |
|
|
mean = (eval[0] + eval[1] + eval[2])/3; |
404 |
|
|
mean = mean*mean*mean; |
405 |
|
|
return 1.0 - (mean ? eval[0]*eval[1]*eval[2]/mean : 0.0); |
406 |
|
|
} |
407 |
|
|
float _tenAnisoTen_VF_f(const float ten[7]) { |
408 |
|
|
float mean; |
409 |
|
|
mean = TEN_T_TRACE(ten)/3.0f; |
410 |
|
|
mean = mean*mean*mean; |
411 |
|
|
return 1.0f - (mean ? TEN_T_DET(ten)/mean : 0.0f); |
412 |
|
|
} |
413 |
|
|
double _tenAnisoTen_VF_d(const double ten[7]) { |
414 |
|
|
double mean; |
415 |
|
|
mean = TEN_T_TRACE(ten)/3.0; |
416 |
|
|
mean = mean*mean*mean; |
417 |
|
|
return 1.0 - (mean ? TEN_T_DET(ten)/mean : 0.0); |
418 |
|
|
} |
419 |
|
|
|
420 |
|
|
|
421 |
|
|
float _tenAnisoEval_B_f(const float eval[3]) { |
422 |
|
|
return eval[0]*eval[1] + eval[0]*eval[2] + eval[1]*eval[2]; |
423 |
|
|
} |
424 |
|
|
double _tenAnisoEval_B_d(const double eval[3]) { |
425 |
|
|
return eval[0]*eval[1] + eval[0]*eval[2] + eval[1]*eval[2]; |
426 |
|
|
} |
427 |
|
|
float _tenAnisoTen_B_f(const float ten[7]) { |
428 |
|
|
return (ten[1]*ten[4] + ten[1]*ten[6] + ten[4]*ten[6] |
429 |
|
|
- ten[2]*ten[2] - ten[3]*ten[3] - ten[5]*ten[5]); |
430 |
|
|
} |
431 |
|
|
double _tenAnisoTen_B_d(const double ten[7]) { |
432 |
|
|
return (ten[1]*ten[4] + ten[1]*ten[6] + ten[4]*ten[6] |
433 |
|
|
- ten[2]*ten[2] - ten[3]*ten[3] - ten[5]*ten[5]); |
434 |
|
|
} |
435 |
|
|
|
436 |
|
|
|
437 |
|
|
float _tenAnisoEval_Q_f(const float eval[3]) { |
438 |
|
|
float A, B; |
439 |
|
|
A = -(eval[0] + eval[1] + eval[2]); |
440 |
|
|
B = _tenAnisoEval_B_f(eval); |
441 |
|
|
A = (A*A - 3.0f*B)/9.0f; |
442 |
|
|
return AIR_MAX(0, A); |
443 |
|
|
} |
444 |
|
|
double _tenAnisoEval_Q_d(const double eval[3]) { |
445 |
|
|
double A, B; |
446 |
|
|
A = -(eval[0] + eval[1] + eval[2]); |
447 |
|
|
B = _tenAnisoEval_B_d(eval); |
448 |
|
|
A = (A*A - 3.0*B)/9.0; |
449 |
|
|
return AIR_MAX(0, A); |
450 |
|
|
} |
451 |
|
|
float _tenAnisoTen_Q_f(const float ten[7]) { |
452 |
|
|
float A, B; |
453 |
|
|
A = -TEN_T_TRACE(ten); |
454 |
|
|
B = _tenAnisoTen_B_f(ten); |
455 |
|
|
A = (A*A - 3.0f*B)/9.0f; |
456 |
|
|
return AIR_MAX(0, A); |
457 |
|
|
} |
458 |
|
|
double _tenAnisoTen_Q_d(const double ten[7]) { |
459 |
|
|
double A, B; |
460 |
|
|
A = -TEN_T_TRACE(ten); |
461 |
|
|
B = _tenAnisoTen_B_d(ten); |
462 |
|
|
A = (A*A - 3.0*B)/9.0; |
463 |
|
|
return AIR_MAX(0, A); |
464 |
|
|
} |
465 |
|
|
|
466 |
|
|
|
467 |
|
|
float _tenAnisoEval_R_f(const float eval[3]) { |
468 |
|
|
float A, B, C; |
469 |
|
|
A = -(eval[0] + eval[1] + eval[2]); |
470 |
|
|
B = _tenAnisoEval_B_f(eval); |
471 |
|
|
C = -eval[0]*eval[1]*eval[2]; |
472 |
|
|
return (-2*A*A*A + 9*A*B - 27*C)/54; |
473 |
|
|
} |
474 |
|
|
double _tenAnisoEval_R_d(const double eval[3]) { |
475 |
|
|
double A, B, C; |
476 |
|
|
A = -(eval[0] + eval[1] + eval[2]); |
477 |
|
|
B = _tenAnisoEval_B_d(eval); |
478 |
|
|
C = -eval[0]*eval[1]*eval[2]; |
479 |
|
|
return (-2*A*A*A + 9*A*B - 27*C)/54; |
480 |
|
|
} |
481 |
|
|
float _tenAnisoTen_R_f(const float ten[7]) { |
482 |
|
|
float A, B, C; |
483 |
|
|
A = -TEN_T_TRACE(ten); |
484 |
|
|
B = _tenAnisoTen_B_f(ten); |
485 |
|
|
C = -TEN_T_DET(ten); |
486 |
|
|
return (-2*A*A*A + 9*A*B - 27*C)/54; |
487 |
|
|
} |
488 |
|
|
double _tenAnisoTen_R_d(const double ten[7]) { |
489 |
|
|
double A, B, C; |
490 |
|
|
A = -TEN_T_TRACE(ten); |
491 |
|
|
B = _tenAnisoTen_B_d(ten); |
492 |
|
|
C = -TEN_T_DET(ten); |
493 |
|
|
return (-2*A*A*A + 9*A*B - 27*C)/54; |
494 |
|
|
} |
495 |
|
|
|
496 |
|
|
|
497 |
|
|
float _tenAnisoEval_S_f(const float eval[3]) { |
498 |
|
|
return eval[0]*eval[0] + eval[1]*eval[1] + eval[2]*eval[2]; |
499 |
|
|
} |
500 |
|
|
double _tenAnisoEval_S_d(const double eval[3]) { |
501 |
|
|
return eval[0]*eval[0] + eval[1]*eval[1] + eval[2]*eval[2]; |
502 |
|
|
} |
503 |
|
|
float _tenAnisoTen_S_f(const float ten[7]) { |
504 |
|
1556640 |
return TEN_T_DOT(ten, ten); |
505 |
|
|
} |
506 |
|
|
double _tenAnisoTen_S_d(const double ten[7]) { |
507 |
|
|
return TEN_T_DOT(ten, ten); |
508 |
|
|
} |
509 |
|
|
|
510 |
|
|
#define OOSQRT2 0.70710678118654752440 |
511 |
|
|
float _tenAnisoEval_Skew_f(const float _eval[3]) { |
512 |
|
|
float Q, num, dnm, ret, mn, eval[3]; |
513 |
|
|
mn = (_eval[0] + _eval[1] + _eval[2])/3; |
514 |
|
|
ELL_3V_SET(eval, _eval[0] - mn, _eval[1] - mn, _eval[2] - mn); |
515 |
|
|
Q = _tenAnisoEval_Q_f(eval); |
516 |
|
|
num = _tenAnisoEval_R_f(eval); |
517 |
|
|
dnm = AIR_CAST(float, Q*sqrt(2*Q)); |
518 |
|
|
ret = dnm ? AIR_CAST(float, num/dnm) : 0.0f; |
519 |
|
|
return AIR_CAST(float, AIR_CLAMP(-OOSQRT2, ret, OOSQRT2)); |
520 |
|
|
} |
521 |
|
|
double _tenAnisoEval_Skew_d(const double _eval[3]) { |
522 |
|
|
double Q, num, dnm, ret, mn, eval[3]; |
523 |
|
|
mn = (_eval[0] + _eval[1] + _eval[2])/3; |
524 |
|
|
ELL_3V_SET(eval, _eval[0] - mn, _eval[1] - mn, _eval[2] - mn); |
525 |
|
|
Q = _tenAnisoEval_Q_d(eval); |
526 |
|
|
num = _tenAnisoEval_R_d(eval); |
527 |
|
|
dnm = Q*sqrt(2*Q); |
528 |
|
|
ret = dnm ? num/dnm : 0.0; |
529 |
|
|
return AIR_CLAMP(-OOSQRT2, ret, OOSQRT2); |
530 |
|
|
} |
531 |
|
|
float _tenAnisoTen_Skew_f(const float _t[7]) { |
532 |
|
|
float Q, num, dnm, ret, mn, ten[7]; |
533 |
|
|
mn = TEN_T_TRACE(_t)/3; |
534 |
|
|
TEN_T_SET(ten, _t[0], _t[1]-mn, _t[2], _t[3], _t[4]-mn, _t[5], _t[6]-mn); |
535 |
|
|
Q = _tenAnisoTen_Q_f(ten); |
536 |
|
|
num = _tenAnisoTen_R_f(ten); |
537 |
|
|
dnm = AIR_CAST(float, Q*sqrt(2*Q)); |
538 |
|
|
ret = dnm ? AIR_CAST(float, num/dnm) : 0.0f; |
539 |
|
|
return AIR_CAST(float, AIR_CLAMP(-OOSQRT2, ret, OOSQRT2)); |
540 |
|
|
} |
541 |
|
|
double _tenAnisoTen_Skew_d(const double _t[7]) { |
542 |
|
|
double Q, num, dnm, ret, mn, ten[7]; |
543 |
|
|
mn = TEN_T_TRACE(_t)/3; |
544 |
|
|
TEN_T_SET(ten, _t[0], _t[1]-mn, _t[2], _t[3], _t[4]-mn, _t[5], _t[6]-mn); |
545 |
|
|
Q = _tenAnisoTen_Q_d(ten); |
546 |
|
|
num = _tenAnisoTen_R_d(ten); |
547 |
|
|
dnm = Q*sqrt(2*Q); |
548 |
|
|
ret = dnm ? num/dnm : 0.0; |
549 |
|
|
return AIR_CLAMP(-OOSQRT2, ret, OOSQRT2); |
550 |
|
|
} |
551 |
|
|
|
552 |
|
|
|
553 |
|
|
float _tenAnisoEval_Mode_f(const float _eval[3]) { |
554 |
|
|
float n, d, mn, e[3], ret; |
555 |
|
|
mn = (_eval[0] + _eval[1] + _eval[2])/3; |
556 |
|
|
ELL_3V_SET(e, _eval[0] - mn, _eval[1] - mn, _eval[2] - mn); |
557 |
|
|
n = (e[0] + e[1] - 2*e[2])*(2*e[0] - e[1] - e[2])*(e[0] - 2*e[1] + e[2]); |
558 |
|
|
d = (e[0]*e[0] + e[1]*e[1] + e[2]*e[2] |
559 |
|
|
- e[0]*e[1] - e[1]*e[2] - e[0]*e[2]); |
560 |
|
|
d = AIR_CAST(float, sqrt(AIR_MAX(0, d))); |
561 |
|
|
d = 2*d*d*d; |
562 |
|
|
ret = d ? AIR_CAST(float, n/d) : 0.0f; |
563 |
|
|
return AIR_CLAMP(-1, ret, 1); |
564 |
|
|
} |
565 |
|
|
double _tenAnisoEval_Mode_d(const double _eval[3]) { |
566 |
|
|
double n, d, mn, e[3], ret; |
567 |
|
|
mn = (_eval[0] + _eval[1] + _eval[2])/3; |
568 |
|
|
ELL_3V_SET(e, _eval[0] - mn, _eval[1] - mn, _eval[2] - mn); |
569 |
|
|
n = (e[0] + e[1] - 2*e[2])*(2*e[0] - e[1] - e[2])*(e[0] - 2*e[1] + e[2]); |
570 |
|
|
d = (e[0]*e[0] + e[1]*e[1] + e[2]*e[2] |
571 |
|
|
- e[0]*e[1] - e[1]*e[2] - e[0]*e[2]); |
572 |
|
|
d = sqrt(AIR_MAX(0, d)); |
573 |
|
|
d = 2*d*d*d; |
574 |
|
|
ret = d ? n/d : 0.0; |
575 |
|
|
return AIR_CLAMP(-1, ret, 1); |
576 |
|
|
} |
577 |
|
|
float _tenAnisoTen_Mode_f(const float tt[7]) { |
578 |
|
|
float mn, dev[7], tmp, ret; |
579 |
|
|
mn = TEN_T_TRACE(tt)/3.0f; |
580 |
|
|
TEN_T_SET(dev, tt[0], tt[1]-mn, tt[2], tt[3], tt[4]-mn, tt[5], tt[6]-mn); |
581 |
|
|
tmp = AIR_CAST(float, TEN_T_NORM(dev)); |
582 |
|
|
tmp = tmp ? 1.0f/tmp : 0.0f; |
583 |
|
|
TEN_T_SCALE(dev, tmp, dev); |
584 |
|
|
ret = AIR_CAST(float, 3*SQRT6*TEN_T_DET(dev)); |
585 |
|
|
return AIR_CLAMP(-1, ret, 1); |
586 |
|
|
} |
587 |
|
|
double _tenAnisoTen_Mode_d(const double tt[7]) { |
588 |
|
|
double mn, dev[7], tmp, ret; |
589 |
|
|
mn = TEN_T_TRACE(tt)/3.0; |
590 |
|
|
TEN_T_SET(dev, tt[0], tt[1]-mn, tt[2], tt[3], tt[4]-mn, tt[5], tt[6]-mn); |
591 |
|
|
tmp = TEN_T_NORM(dev); |
592 |
|
|
tmp = tmp ? 1.0/tmp : 0.0; |
593 |
|
|
TEN_T_SCALE(dev, tmp, dev); |
594 |
|
|
ret = 3*SQRT6*TEN_T_DET(dev); |
595 |
|
|
return AIR_CLAMP(-1, ret, 1); |
596 |
|
|
} |
597 |
|
|
|
598 |
|
|
/* NOTE: yes, the AIR_CLAMPs here are needed even though |
599 |
|
|
** the _Skew_ functions clamp their output |
600 |
|
|
*/ |
601 |
|
|
#define SQRT2 1.41421356237309504880 |
602 |
|
|
float _tenAnisoEval_Th_f(const float eval[3]) { |
603 |
|
|
float tmp; |
604 |
|
|
tmp = AIR_CAST(float, SQRT2*_tenAnisoEval_Skew_f(eval)); |
605 |
|
|
return AIR_CAST(float, acos(AIR_CLAMP(-1, tmp, 1))/3); |
606 |
|
|
} |
607 |
|
|
double _tenAnisoEval_Th_d(const double eval[3]) { |
608 |
|
|
double tmp; |
609 |
|
|
tmp = SQRT2*_tenAnisoEval_Skew_d(eval); |
610 |
|
|
return acos(AIR_CLAMP(-1, tmp, 1))/3; |
611 |
|
|
} |
612 |
|
|
float _tenAnisoTen_Th_f(const float ten[7]) { |
613 |
|
|
float tmp; |
614 |
|
|
tmp = AIR_CAST(float, SQRT2*_tenAnisoTen_Skew_f(ten)); |
615 |
|
|
return AIR_CAST(float, acos(AIR_CLAMP(-1, tmp, 1))/3); |
616 |
|
|
} |
617 |
|
|
double _tenAnisoTen_Th_d(const double ten[7]) { |
618 |
|
|
double tmp; |
619 |
|
|
tmp = SQRT2*_tenAnisoTen_Skew_d(ten); |
620 |
|
|
return acos(AIR_CLAMP(-1, tmp, 1))/3; |
621 |
|
|
} |
622 |
|
|
|
623 |
|
|
|
624 |
|
|
float _tenAnisoEval_Omega_f(const float eval[3]) { |
625 |
|
|
return _tenAnisoEval_FA_f(eval)*(1.0f+_tenAnisoEval_Mode_f(eval))/2.0f; |
626 |
|
|
} |
627 |
|
|
double _tenAnisoEval_Omega_d(const double eval[3]) { |
628 |
|
|
return _tenAnisoEval_FA_d(eval)*(1.0f+_tenAnisoEval_Mode_d(eval))/2.0f; |
629 |
|
|
} |
630 |
|
|
float _tenAnisoTen_Omega_f(const float ten[7]) { |
631 |
|
|
return _tenAnisoTen_FA_f(ten)*(1.0f+_tenAnisoTen_Mode_f(ten))/2.0f; |
632 |
|
|
} |
633 |
|
|
double _tenAnisoTen_Omega_d(const double ten[7]) { |
634 |
|
|
return _tenAnisoTen_FA_d(ten)*(1.0f+_tenAnisoTen_Mode_d(ten))/2.0f; |
635 |
|
|
} |
636 |
|
|
|
637 |
|
|
|
638 |
|
|
float _tenAnisoEval_Det_f(const float eval[3]) { |
639 |
|
|
return eval[0]*eval[1]*eval[2]; |
640 |
|
|
} |
641 |
|
|
double _tenAnisoEval_Det_d(const double eval[3]) { |
642 |
|
|
return eval[0]*eval[1]*eval[2]; |
643 |
|
|
} |
644 |
|
|
float _tenAnisoTen_Det_f(const float ten[7]) { |
645 |
|
|
return TEN_T_DET(ten); |
646 |
|
|
} |
647 |
|
|
double _tenAnisoTen_Det_d(const double ten[7]) { |
648 |
|
|
return TEN_T_DET(ten); |
649 |
|
|
} |
650 |
|
|
|
651 |
|
|
|
652 |
|
|
float _tenAnisoEval_Tr_f(const float eval[3]) { |
653 |
|
|
return eval[0] + eval[1] + eval[2]; |
654 |
|
|
} |
655 |
|
|
double _tenAnisoEval_Tr_d(const double eval[3]) { |
656 |
|
|
return eval[0] + eval[1] + eval[2]; |
657 |
|
|
} |
658 |
|
|
float _tenAnisoTen_Tr_f(const float ten[7]) { |
659 |
|
|
return TEN_T_TRACE(ten); |
660 |
|
|
} |
661 |
|
|
double _tenAnisoTen_Tr_d(const double ten[7]) { |
662 |
|
|
return TEN_T_TRACE(ten); |
663 |
|
|
} |
664 |
|
|
|
665 |
|
|
|
666 |
|
|
float _tenAnisoEval_eval0_f(const float eval[3]) { return eval[0]; } |
667 |
|
|
double _tenAnisoEval_eval0_d(const double eval[3]) { return eval[0]; } |
668 |
|
|
float _tenAnisoTen_eval0_f(const float ten[7]) { |
669 |
|
|
float eval[3]; |
670 |
|
|
tenEigensolve_f(eval, NULL, ten); |
671 |
|
|
return eval[0]; |
672 |
|
|
} |
673 |
|
|
double _tenAnisoTen_eval0_d(const double ten[7]) { |
674 |
|
|
double eval[3]; |
675 |
|
|
tenEigensolve_d(eval, NULL, ten); |
676 |
|
|
return eval[0]; |
677 |
|
|
} |
678 |
|
|
|
679 |
|
|
float _tenAnisoEval_eval1_f(const float eval[3]) { return eval[1]; } |
680 |
|
|
double _tenAnisoEval_eval1_d(const double eval[3]) { return eval[1]; } |
681 |
|
|
float _tenAnisoTen_eval1_f(const float ten[7]) { |
682 |
|
|
float eval[3]; |
683 |
|
|
tenEigensolve_f(eval, NULL, ten); |
684 |
|
|
return eval[1]; |
685 |
|
|
} |
686 |
|
|
double _tenAnisoTen_eval1_d(const double ten[7]) { |
687 |
|
|
double eval[3]; |
688 |
|
|
tenEigensolve_d(eval, NULL, ten); |
689 |
|
|
return eval[1]; |
690 |
|
|
} |
691 |
|
|
|
692 |
|
|
|
693 |
|
|
float _tenAnisoEval_eval2_f(const float eval[3]) { return eval[2]; } |
694 |
|
|
double _tenAnisoEval_eval2_d(const double eval[3]) { return eval[2]; } |
695 |
|
|
float _tenAnisoTen_eval2_f(const float ten[7]) { |
696 |
|
|
float eval[3]; |
697 |
|
|
tenEigensolve_f(eval, NULL, ten); |
698 |
|
|
return eval[2]; |
699 |
|
|
} |
700 |
|
|
double _tenAnisoTen_eval2_d(const double ten[7]) { |
701 |
|
|
double eval[3]; |
702 |
|
|
tenEigensolve_d(eval, NULL, ten); |
703 |
|
|
return eval[2]; |
704 |
|
|
} |
705 |
|
|
|
706 |
|
|
|
707 |
|
|
float (*_tenAnisoEval_f[TEN_ANISO_MAX+1])(const float eval[3]) = { |
708 |
|
|
NULL, |
709 |
|
|
_tenAnisoEval_Conf_f, |
710 |
|
|
_tenAnisoEval_Cl1_f, |
711 |
|
|
_tenAnisoEval_Cp1_f, |
712 |
|
|
_tenAnisoEval_Ca1_f, |
713 |
|
|
_tenAnisoEval_Clpmin1_f, |
714 |
|
|
_tenAnisoEval_Cs1_f, |
715 |
|
|
_tenAnisoEval_Ct1_f, |
716 |
|
|
_tenAnisoEval_Cl2_f, |
717 |
|
|
_tenAnisoEval_Cp2_f, |
718 |
|
|
_tenAnisoEval_Ca2_f, |
719 |
|
|
_tenAnisoEval_Clpmin2_f, |
720 |
|
|
_tenAnisoEval_Cs2_f, |
721 |
|
|
_tenAnisoEval_Ct2_f, |
722 |
|
|
_tenAnisoEval_RA_f, |
723 |
|
|
_tenAnisoEval_FA_f, |
724 |
|
|
_tenAnisoEval_VF_f, |
725 |
|
|
_tenAnisoEval_B_f, |
726 |
|
|
_tenAnisoEval_Q_f, |
727 |
|
|
_tenAnisoEval_R_f, |
728 |
|
|
_tenAnisoEval_S_f, |
729 |
|
|
_tenAnisoEval_Skew_f, |
730 |
|
|
_tenAnisoEval_Mode_f, |
731 |
|
|
_tenAnisoEval_Th_f, |
732 |
|
|
_tenAnisoEval_Omega_f, |
733 |
|
|
_tenAnisoEval_Det_f, |
734 |
|
|
_tenAnisoEval_Tr_f, |
735 |
|
|
_tenAnisoEval_eval0_f, |
736 |
|
|
_tenAnisoEval_eval1_f, |
737 |
|
|
_tenAnisoEval_eval2_f |
738 |
|
|
}; |
739 |
|
|
|
740 |
|
|
double (*_tenAnisoEval_d[TEN_ANISO_MAX+1])(const double eval[3]) = { |
741 |
|
|
NULL, |
742 |
|
|
_tenAnisoEval_Conf_d, |
743 |
|
|
_tenAnisoEval_Cl1_d, |
744 |
|
|
_tenAnisoEval_Cp1_d, |
745 |
|
|
_tenAnisoEval_Ca1_d, |
746 |
|
|
_tenAnisoEval_Clpmin1_d, |
747 |
|
|
_tenAnisoEval_Cs1_d, |
748 |
|
|
_tenAnisoEval_Ct1_d, |
749 |
|
|
_tenAnisoEval_Cl2_d, |
750 |
|
|
_tenAnisoEval_Cp2_d, |
751 |
|
|
_tenAnisoEval_Ca2_d, |
752 |
|
|
_tenAnisoEval_Clpmin2_d, |
753 |
|
|
_tenAnisoEval_Cs2_d, |
754 |
|
|
_tenAnisoEval_Ct2_d, |
755 |
|
|
_tenAnisoEval_RA_d, |
756 |
|
|
_tenAnisoEval_FA_d, |
757 |
|
|
_tenAnisoEval_VF_d, |
758 |
|
|
_tenAnisoEval_B_d, |
759 |
|
|
_tenAnisoEval_Q_d, |
760 |
|
|
_tenAnisoEval_R_d, |
761 |
|
|
_tenAnisoEval_S_d, |
762 |
|
|
_tenAnisoEval_Skew_d, |
763 |
|
|
_tenAnisoEval_Mode_d, |
764 |
|
|
_tenAnisoEval_Th_d, |
765 |
|
|
_tenAnisoEval_Omega_d, |
766 |
|
|
_tenAnisoEval_Det_d, |
767 |
|
|
_tenAnisoEval_Tr_d, |
768 |
|
|
_tenAnisoEval_eval0_d, |
769 |
|
|
_tenAnisoEval_eval1_d, |
770 |
|
|
_tenAnisoEval_eval2_d |
771 |
|
|
}; |
772 |
|
|
|
773 |
|
|
float (*_tenAnisoTen_f[TEN_ANISO_MAX+1])(const float ten[7]) = { |
774 |
|
|
NULL, |
775 |
|
|
_tenAnisoTen_Conf_f, |
776 |
|
|
_tenAnisoTen_Cl1_f, |
777 |
|
|
_tenAnisoTen_Cp1_f, |
778 |
|
|
_tenAnisoTen_Ca1_f, |
779 |
|
|
_tenAnisoTen_Clpmin1_f, |
780 |
|
|
_tenAnisoTen_Cs1_f, |
781 |
|
|
_tenAnisoTen_Ct1_f, |
782 |
|
|
_tenAnisoTen_Cl2_f, |
783 |
|
|
_tenAnisoTen_Cp2_f, |
784 |
|
|
_tenAnisoTen_Ca2_f, |
785 |
|
|
_tenAnisoTen_Clpmin2_f, |
786 |
|
|
_tenAnisoTen_Cs2_f, |
787 |
|
|
_tenAnisoTen_Ct2_f, |
788 |
|
|
_tenAnisoTen_RA_f, |
789 |
|
|
_tenAnisoTen_FA_f, |
790 |
|
|
_tenAnisoTen_VF_f, |
791 |
|
|
_tenAnisoTen_B_f, |
792 |
|
|
_tenAnisoTen_Q_f, |
793 |
|
|
_tenAnisoTen_R_f, |
794 |
|
|
_tenAnisoTen_S_f, |
795 |
|
|
_tenAnisoTen_Skew_f, |
796 |
|
|
_tenAnisoTen_Mode_f, |
797 |
|
|
_tenAnisoTen_Th_f, |
798 |
|
|
_tenAnisoTen_Omega_f, |
799 |
|
|
_tenAnisoTen_Det_f, |
800 |
|
|
_tenAnisoTen_Tr_f, |
801 |
|
|
_tenAnisoTen_eval0_f, |
802 |
|
|
_tenAnisoTen_eval1_f, |
803 |
|
|
_tenAnisoTen_eval2_f |
804 |
|
|
}; |
805 |
|
|
|
806 |
|
|
double (*_tenAnisoTen_d[TEN_ANISO_MAX+1])(const double ten[7]) = { |
807 |
|
|
NULL, |
808 |
|
|
_tenAnisoTen_Conf_d, |
809 |
|
|
_tenAnisoTen_Cl1_d, |
810 |
|
|
_tenAnisoTen_Cp1_d, |
811 |
|
|
_tenAnisoTen_Ca1_d, |
812 |
|
|
_tenAnisoTen_Clpmin1_d, |
813 |
|
|
_tenAnisoTen_Cs1_d, |
814 |
|
|
_tenAnisoTen_Ct1_d, |
815 |
|
|
_tenAnisoTen_Cl2_d, |
816 |
|
|
_tenAnisoTen_Cp2_d, |
817 |
|
|
_tenAnisoTen_Ca2_d, |
818 |
|
|
_tenAnisoTen_Clpmin2_d, |
819 |
|
|
_tenAnisoTen_Cs2_d, |
820 |
|
|
_tenAnisoTen_Ct2_d, |
821 |
|
|
_tenAnisoTen_RA_d, |
822 |
|
|
_tenAnisoTen_FA_d, |
823 |
|
|
_tenAnisoTen_VF_d, |
824 |
|
|
_tenAnisoTen_B_d, |
825 |
|
|
_tenAnisoTen_Q_d, |
826 |
|
|
_tenAnisoTen_R_d, |
827 |
|
|
_tenAnisoTen_S_d, |
828 |
|
|
_tenAnisoTen_Skew_d, |
829 |
|
|
_tenAnisoTen_Mode_d, |
830 |
|
|
_tenAnisoTen_Th_d, |
831 |
|
|
_tenAnisoTen_Omega_d, |
832 |
|
|
_tenAnisoTen_Det_d, |
833 |
|
|
_tenAnisoTen_Tr_d, |
834 |
|
|
_tenAnisoTen_eval0_d, |
835 |
|
|
_tenAnisoTen_eval1_d, |
836 |
|
|
_tenAnisoTen_eval2_d |
837 |
|
|
}; |
838 |
|
|
|
839 |
|
|
float |
840 |
|
|
tenAnisoEval_f(const float eval[3], int aniso) { |
841 |
|
|
|
842 |
|
|
return (AIR_IN_OP(tenAnisoUnknown, aniso, tenAnisoLast) |
843 |
|
|
? _tenAnisoEval_f[aniso](eval) |
844 |
|
|
: 0); |
845 |
|
|
} |
846 |
|
|
|
847 |
|
|
double |
848 |
|
|
tenAnisoEval_d(const double eval[3], int aniso) { |
849 |
|
|
|
850 |
|
|
return (AIR_IN_OP(tenAnisoUnknown, aniso, tenAnisoLast) |
851 |
|
|
? _tenAnisoEval_d[aniso](eval) |
852 |
|
|
: 0); |
853 |
|
|
} |
854 |
|
|
|
855 |
|
|
float |
856 |
|
|
tenAnisoTen_f(const float ten[7], int aniso) { |
857 |
|
|
|
858 |
✓✗ |
3113280 |
return (AIR_IN_OP(tenAnisoUnknown, aniso, tenAnisoLast) |
859 |
|
778320 |
? _tenAnisoTen_f[aniso](ten) |
860 |
|
|
: 0); |
861 |
|
|
} |
862 |
|
|
|
863 |
|
|
double |
864 |
|
|
tenAnisoTen_d(const double ten[7], int aniso) { |
865 |
|
|
|
866 |
|
|
return (AIR_IN_OP(tenAnisoUnknown, aniso, tenAnisoLast) |
867 |
|
|
? _tenAnisoTen_d[aniso](ten) |
868 |
|
|
: 0); |
869 |
|
|
} |
870 |
|
|
|
871 |
|
|
#if 0 |
872 |
|
|
/* |
873 |
|
|
******** tenAnisoCalc_f |
874 |
|
|
** |
875 |
|
|
** !!! THIS FUNCTION HAS BEEN MADE OBSOLETE BY THE NEW |
876 |
|
|
** !!! tenAnisoEval_{f,d} AND tenAnisoTen_{f,d} FUNCTIONS |
877 |
|
|
** !!! THIS WILL LIKELY BE REMOVED FROM FUTURE RELEASES |
878 |
|
|
** |
879 |
|
|
** Because this function does not subtract out the eigenvalue mean |
880 |
|
|
** when computing quantities like Skew and Mode, it has really lousy |
881 |
|
|
** accuracy on those measures compared to tenAnisoEval_{f,d}. |
882 |
|
|
** |
883 |
|
|
** given an array of three SORTED (descending) eigenvalues "e", |
884 |
|
|
** calculates the anisotropy coefficients of Westin et al., |
885 |
|
|
** as well as various others. |
886 |
|
|
** |
887 |
|
|
** NOTE: with time, so many metrics have ended up here that under |
888 |
|
|
** no cases should this be used in any kind of time-critical operations |
889 |
|
|
** |
890 |
|
|
** This does NOT use biff. |
891 |
|
|
*/ |
892 |
|
|
void |
893 |
|
|
tenAnisoCalc_f(float c[TEN_ANISO_MAX+1], const float e[3]) { |
894 |
|
|
float e0, e1, e2, stdv, mean, sum, cl, cp, ca, ra, fa, vf, denom; |
895 |
|
|
float A, B, C, R, Q, N, D; |
896 |
|
|
|
897 |
|
|
if (!( e[0] >= e[1] && e[1] >= e[2] )) { |
898 |
|
|
fprintf(stderr, "tenAnisoCalc_f: eigen values not sorted: " |
899 |
|
|
"%g %g %g (%d %d)\n", |
900 |
|
|
e[0], e[1], e[2], e[0] >= e[1], e[1] >= e[2]); |
901 |
|
|
} |
902 |
|
|
if ((tenVerbose > 1) && !( e[0] >= 0 && e[1] >= 0 && e[2] >= 0 )) { |
903 |
|
|
fprintf(stderr, "tenAnisoCalc_f: eigen values not all >= 0: %g %g %g\n", |
904 |
|
|
e[0], e[1], e[2]); |
905 |
|
|
} |
906 |
|
|
e0 = AIR_MAX(e[0], 0); |
907 |
|
|
e1 = AIR_MAX(e[1], 0); |
908 |
|
|
e2 = AIR_MAX(e[2], 0); |
909 |
|
|
sum = e0 + e1 + e2; |
910 |
|
|
|
911 |
|
|
/* first version of cl, cp, cs */ |
912 |
|
|
cl = sum ? (e0 - e1)/sum : 0.0f; |
913 |
|
|
c[tenAniso_Cl1] = cl; |
914 |
|
|
cp = sum ? 2*(e1 - e2)/sum : 0.0f; |
915 |
|
|
c[tenAniso_Cp1] = cp; |
916 |
|
|
ca = cl + cp; |
917 |
|
|
c[tenAniso_Ca1] = ca; |
918 |
|
|
c[tenAniso_Clpmin1] = AIR_MIN(cl, cp); |
919 |
|
|
/* extra logic here for equality with expressions above */ |
920 |
|
|
c[tenAniso_Cs1] = sum ? 1 - ca : 0.0f; |
921 |
|
|
c[tenAniso_Ct1] = ca ? cp/ca : 0; |
922 |
|
|
/* second version of cl, cp, cs */ |
923 |
|
|
cl = e0 ? (e0 - e1)/e0 : 0.0f; |
924 |
|
|
c[tenAniso_Cl2] = cl; |
925 |
|
|
cp = e0 ? (e1 - e2)/e0 : 0.0f; |
926 |
|
|
c[tenAniso_Cp2] = cp; |
927 |
|
|
ca = cl + cp; |
928 |
|
|
c[tenAniso_Ca2] = ca; |
929 |
|
|
c[tenAniso_Clpmin2] = AIR_MIN(cl, cp); |
930 |
|
|
/* extra logic here for equality with expressions above */ |
931 |
|
|
c[tenAniso_Cs2] = e0 ? 1 - ca : 0.0f; |
932 |
|
|
c[tenAniso_Ct2] = ca ? cp/ca : 0.0f; |
933 |
|
|
/* non-westin anisos */ |
934 |
|
|
mean = sum/3.0f; |
935 |
|
|
stdv = AIR_CAST(float, |
936 |
|
|
sqrt((mean-e0)*(mean-e0) /* okay, not exactly standard dev */ |
937 |
|
|
+ (mean-e1)*(mean-e1) |
938 |
|
|
+ (mean-e2)*(mean-e2))); |
939 |
|
|
ra = mean ? AIR_CAST(float, stdv/(mean*SQRT6)) : 0.0f; |
940 |
|
|
ra = AIR_CLAMP(0.0f, ra, 1.0f); |
941 |
|
|
c[tenAniso_RA] = ra; |
942 |
|
|
denom = 2.0f*(e0*e0 + e1*e1 + e2*e2); |
943 |
|
|
if (denom) { |
944 |
|
|
fa = AIR_CAST(float, stdv*sqrt(3.0/denom)); |
945 |
|
|
fa = AIR_CLAMP(0.0f, fa, 1.0f); |
946 |
|
|
} else { |
947 |
|
|
fa = 0.0f; |
948 |
|
|
} |
949 |
|
|
c[tenAniso_FA] = fa; |
950 |
|
|
vf = 1 - (mean ? e0*e1*e2/(mean*mean*mean) : 0.0f); |
951 |
|
|
vf = AIR_CLAMP(0.0f, vf, 1.0f); |
952 |
|
|
c[tenAniso_VF] = vf; |
953 |
|
|
|
954 |
|
|
A = (-e0 - e1 - e2); |
955 |
|
|
B = c[tenAniso_B] = e0*e1 + e0*e2 + e1*e2; |
956 |
|
|
C = -e0*e1*e2; |
957 |
|
|
Q = c[tenAniso_Q] = (A*A - 3*B)/9; |
958 |
|
|
R = c[tenAniso_R] = (-2*A*A*A + 9*A*B - 27*C)/54; |
959 |
|
|
c[tenAniso_S] = e0*e0 + e1*e1 + e2*e2; |
960 |
|
|
c[tenAniso_Skew] = Q ? AIR_CAST(float, R/(Q*sqrt(2*Q))) : 0.0f; |
961 |
|
|
c[tenAniso_Skew] = AIR_CLAMP(-OOSQRT2, c[tenAniso_Skew], OOSQRT2); |
962 |
|
|
N = (e0 + e1 - 2*e2)*(2*e0 - e1 - e2)*(e0 - 2*e1 + e2); |
963 |
|
|
D = AIR_CAST(float, sqrt(e0*e0+e1*e1+e2*e2 - e0*e1-e1*e2-e0*e2)); |
964 |
|
|
c[tenAniso_Mode] = D ? N/(2*D*D*D) : 0.0f; |
965 |
|
|
c[tenAniso_Mode] = AIR_CLAMP(-1, c[tenAniso_Mode], 1); |
966 |
|
|
c[tenAniso_Th] = |
967 |
|
|
AIR_CAST(float, acos(AIR_CLAMP(-1, sqrt(2)*c[tenAniso_Skew], 1))/3); |
968 |
|
|
c[tenAniso_Omega] = c[tenAniso_FA]*(1+c[tenAniso_Mode])/2; |
969 |
|
|
c[tenAniso_Det] = e0*e1*e2; |
970 |
|
|
c[tenAniso_Tr] = e0 + e1 + e2; |
971 |
|
|
c[tenAniso_eval0] = e0; |
972 |
|
|
c[tenAniso_eval1] = e1; |
973 |
|
|
c[tenAniso_eval2] = e2; |
974 |
|
|
return; |
975 |
|
|
} |
976 |
|
|
#endif |
977 |
|
|
|
978 |
|
|
int |
979 |
|
|
tenAnisoPlot(Nrrd *nout, int aniso, unsigned int res, |
980 |
|
|
int hflip, int whole, int nanout) { |
981 |
|
|
static const char me[]="tenAnisoMap"; |
982 |
|
|
float *out, tmp; |
983 |
|
|
unsigned int x, y; |
984 |
|
|
float m0[3], m1[3], m2[3], c0, c1, c2, e[3]; |
985 |
|
|
float S = 1/3.0f, L = 1.0f, P = 1/2.0f; /* these make Westin's original |
986 |
|
|
(cl,cp,cs) align with the |
987 |
|
|
barycentric coordinates */ |
988 |
|
|
|
989 |
|
|
if (airEnumValCheck(tenAniso, aniso)) { |
990 |
|
|
biffAddf(TEN, "%s: invalid aniso (%d)", me, aniso); |
991 |
|
|
return 1; |
992 |
|
|
} |
993 |
|
|
if (!(res > 2)) { |
994 |
|
|
biffAddf(TEN, "%s: resolution (%d) invalid", me, res); |
995 |
|
|
return 1; |
996 |
|
|
} |
997 |
|
|
if (nrrdMaybeAlloc_va(nout, nrrdTypeFloat, 2, |
998 |
|
|
AIR_CAST(size_t, res), AIR_CAST(size_t, res))) { |
999 |
|
|
biffMovef(TEN, NRRD, "%s: ", me); |
1000 |
|
|
return 1; |
1001 |
|
|
} |
1002 |
|
|
out = (float *)nout->data; |
1003 |
|
|
if (whole) { |
1004 |
|
|
ELL_3V_SET(m0, 1, 0, 0); |
1005 |
|
|
ELL_3V_SET(m1, 0, 1, 0); |
1006 |
|
|
ELL_3V_SET(m2, 0, 0, 1); |
1007 |
|
|
} else { |
1008 |
|
|
ELL_3V_SET(m0, S, S, S); |
1009 |
|
|
if (hflip) { |
1010 |
|
|
ELL_3V_SET(m1, P, P, 0); |
1011 |
|
|
ELL_3V_SET(m2, L, 0, 0); |
1012 |
|
|
} else { |
1013 |
|
|
ELL_3V_SET(m1, L, 0, 0); |
1014 |
|
|
ELL_3V_SET(m2, P, P, 0); |
1015 |
|
|
} |
1016 |
|
|
} |
1017 |
|
|
for (y=0; y<res; y++) { |
1018 |
|
|
for (x=0; x<=y; x++) { |
1019 |
|
|
/* (c0,c1,c2) are the barycentric coordinates */ |
1020 |
|
|
c0 = AIR_CAST(float, 1.0 - AIR_AFFINE(-0.5, y, res-0.5, 0.0, 1.0)); |
1021 |
|
|
c2 = AIR_CAST(float, AIR_AFFINE(-0.5, x, res-0.5, 0.0, 1.0)); |
1022 |
|
|
c1 = 1 - c0 - c2; |
1023 |
|
|
e[0] = c0*m0[0] + c1*m1[0] + c2*m2[0]; |
1024 |
|
|
e[1] = c0*m0[1] + c1*m1[1] + c2*m2[1]; |
1025 |
|
|
e[2] = c0*m0[2] + c1*m1[2] + c2*m2[2]; |
1026 |
|
|
ELL_SORT3(e[0], e[1], e[2], tmp); /* got some warnings w/out this */ |
1027 |
|
|
out[x + res*y] = tenAnisoEval_f(e, aniso); |
1028 |
|
|
} |
1029 |
|
|
if (nanout) { |
1030 |
|
|
for (x=y+1; x<res; x++) { |
1031 |
|
|
out[x + res*y] = AIR_NAN; |
1032 |
|
|
} |
1033 |
|
|
} |
1034 |
|
|
} |
1035 |
|
|
|
1036 |
|
|
return 0; |
1037 |
|
|
} |
1038 |
|
|
|
1039 |
|
|
int |
1040 |
|
|
tenAnisoVolume(Nrrd *nout, const Nrrd *nin, int aniso, double confThresh) { |
1041 |
|
|
static const char me[]="tenAnisoVolume"; |
1042 |
|
|
size_t N, I; |
1043 |
|
|
float *out, *in, *tensor; |
1044 |
|
16 |
int map[NRRD_DIM_MAX]; |
1045 |
|
8 |
size_t sx, sy, sz, size[3]; |
1046 |
|
|
|
1047 |
✗✓ |
8 |
if (tenTensorCheck(nin, nrrdTypeFloat, AIR_TRUE, AIR_TRUE)) { |
1048 |
|
|
biffAddf(TEN, "%s: didn't get a tensor nrrd", me); |
1049 |
|
|
return 1; |
1050 |
|
|
} |
1051 |
✗✓ |
8 |
if (airEnumValCheck(tenAniso, aniso)) { |
1052 |
|
|
biffAddf(TEN, "%s: invalid aniso (%d)", me, aniso); |
1053 |
|
|
return 1; |
1054 |
|
|
} |
1055 |
✓✗ |
24 |
confThresh = AIR_CLAMP(0.0, confThresh, 1.0); |
1056 |
|
|
|
1057 |
|
8 |
size[0] = sx = nin->axis[1].size; |
1058 |
|
8 |
size[1] = sy = nin->axis[2].size; |
1059 |
|
8 |
size[2] = sz = nin->axis[3].size; |
1060 |
|
8 |
N = sx*sy*sz; |
1061 |
✗✓ |
8 |
if (nrrdMaybeAlloc_va(nout, nrrdTypeFloat, 3, sx, sy, sz)) { |
1062 |
|
|
biffMovef(TEN, NRRD, "%s: trouble", me); |
1063 |
|
|
return 1; |
1064 |
|
|
} |
1065 |
|
8 |
out = (float *)nout->data; |
1066 |
|
8 |
in = (float *)nin->data; |
1067 |
✓✓ |
1556656 |
for (I=0; I<=N-1; I++) { |
1068 |
|
|
/* tenVerbose = (I == 911327); */ |
1069 |
|
778320 |
tensor = in + I*7; |
1070 |
✓✗✗✓
|
1556640 |
if (tenAniso_Conf != aniso && tensor[0] < confThresh) { |
1071 |
|
|
out[I] = 0.0; |
1072 |
|
|
continue; |
1073 |
|
|
} |
1074 |
|
|
/* no longer used |
1075 |
|
|
tenEigensolve_f(eval, NULL, tensor); |
1076 |
|
|
if (!(AIR_EXISTS(eval[0]) && AIR_EXISTS(eval[1]) && AIR_EXISTS(eval[2]))) { |
1077 |
|
|
NRRD_COORD_GEN(coord, size, 3, I); |
1078 |
|
|
biffAddf(TEN, "%s: not all eigenvalues exist (%g,%g,%g) at sample " |
1079 |
|
|
"%d = (%d,%d,%d)", |
1080 |
|
|
me, eval[0], eval[1], eval[2], (int)I, |
1081 |
|
|
(int)coord[0], (int)coord[1], (int)coord[2]); |
1082 |
|
|
return 1; |
1083 |
|
|
} |
1084 |
|
|
*/ |
1085 |
|
778320 |
out[I] = tenAnisoTen_f(tensor, aniso); |
1086 |
✗✓ |
778320 |
if (!AIR_EXISTS(out[I])) { |
1087 |
|
|
size_t coord[3]; |
1088 |
|
|
NRRD_COORD_GEN(coord, size, 3, I); |
1089 |
|
|
biffAddf(TEN, "%s: generated non-existent aniso %g from tensor " |
1090 |
|
|
"(%g) %g %g %g %g %g %g at sample %u = (%u,%u,%u)", me, |
1091 |
|
|
out[I], |
1092 |
|
|
tensor[0], tensor[1], tensor[2], tensor[3], |
1093 |
|
|
tensor[4], tensor[5], tensor[6], |
1094 |
|
|
AIR_CAST(unsigned int, I), |
1095 |
|
|
AIR_CAST(unsigned int, coord[0]), |
1096 |
|
|
AIR_CAST(unsigned int, coord[1]), |
1097 |
|
|
AIR_CAST(unsigned int, coord[2])); |
1098 |
|
|
return 1; |
1099 |
|
|
} |
1100 |
|
|
} |
1101 |
|
8 |
ELL_3V_SET(map, 1, 2, 3); |
1102 |
✗✓ |
8 |
if (nrrdAxisInfoCopy(nout, nin, map, NRRD_AXIS_INFO_SIZE_BIT)) { |
1103 |
|
|
biffMovef(TEN, NRRD, "%s: trouble", me); |
1104 |
|
|
return 1; |
1105 |
|
|
} |
1106 |
✗✓ |
8 |
if (nrrdBasicInfoCopy(nout, nin, |
1107 |
|
|
NRRD_BASIC_INFO_ALL ^ NRRD_BASIC_INFO_SPACE)) { |
1108 |
|
|
biffAddf(NRRD, "%s:", me); |
1109 |
|
|
return 1; |
1110 |
|
|
} |
1111 |
|
|
|
1112 |
|
8 |
return 0; |
1113 |
|
8 |
} |
1114 |
|
|
|
1115 |
|
|
int |
1116 |
|
|
tenAnisoHistogram(Nrrd *nout, const Nrrd *nin, const Nrrd *nwght, |
1117 |
|
|
int right, int version, unsigned int res) { |
1118 |
|
|
static const char me[]="tenAnisoHistogram"; |
1119 |
|
|
size_t N, I; |
1120 |
|
|
int csIdx, clIdx, cpIdx; |
1121 |
|
|
float *tdata, *out, eval[3], |
1122 |
|
|
cs, cl, cp, (*wlup)(const void *data, size_t idx), weight; |
1123 |
|
|
unsigned int yres, xi, yi; |
1124 |
|
|
|
1125 |
|
|
if (tenTensorCheck(nin, nrrdTypeFloat, AIR_TRUE, AIR_TRUE)) { |
1126 |
|
|
biffAddf(TEN, "%s: didn't get a tensor nrrd", me); |
1127 |
|
|
return 1; |
1128 |
|
|
} |
1129 |
|
|
if (nwght) { |
1130 |
|
|
if (nrrdCheck(nwght)) { |
1131 |
|
|
biffMovef(TEN, NRRD, "%s: trouble with weighting nrrd", me); |
1132 |
|
|
return 1; |
1133 |
|
|
} |
1134 |
|
|
if (nrrdElementNumber(nwght) |
1135 |
|
|
!= nrrdElementNumber(nin)/nrrdKindSize(nrrdKind3DMaskedSymMatrix) ) { |
1136 |
|
|
char stmp1[AIR_STRLEN_SMALL], stmp2[AIR_STRLEN_SMALL]; |
1137 |
|
|
size_t numten; |
1138 |
|
|
numten = nrrdElementNumber(nin)/nrrdKindSize(nrrdKind3DMaskedSymMatrix); |
1139 |
|
|
biffAddf(TEN, "%s: # elements in weight nrrd (%s) != # tensors (%s)", me, |
1140 |
|
|
airSprintSize_t(stmp1, nrrdElementNumber(nwght)), |
1141 |
|
|
airSprintSize_t(stmp2, numten)); |
1142 |
|
|
return 1; |
1143 |
|
|
} |
1144 |
|
|
} |
1145 |
|
|
if (!( 1 == version || 2 == version )) { |
1146 |
|
|
biffAddf(TEN, "%s: version (%d) wasn't 1 or 2", me, version); |
1147 |
|
|
return 1; |
1148 |
|
|
} |
1149 |
|
|
if (!(res > 10)) { |
1150 |
|
|
biffAddf(TEN, "%s: resolution (%d) invalid", me, res); |
1151 |
|
|
return 1; |
1152 |
|
|
} |
1153 |
|
|
if (right) { |
1154 |
|
|
yres = AIR_CAST(unsigned int, AIR_CAST(double, res)/sqrt(3)); |
1155 |
|
|
} else { |
1156 |
|
|
yres = res; |
1157 |
|
|
} |
1158 |
|
|
if (nwght) { |
1159 |
|
|
wlup = nrrdFLookup[nwght->type]; |
1160 |
|
|
} else { |
1161 |
|
|
wlup = NULL; |
1162 |
|
|
} |
1163 |
|
|
if (nrrdMaybeAlloc_va(nout, nrrdTypeFloat, 2, |
1164 |
|
|
AIR_CAST(size_t, res), AIR_CAST(size_t, yres))) { |
1165 |
|
|
biffMovef(TEN, NRRD, "%s: ", me); |
1166 |
|
|
return 1; |
1167 |
|
|
} |
1168 |
|
|
out = (float *)nout->data; |
1169 |
|
|
tdata = (float *)nin->data; |
1170 |
|
|
if (right || 1 == version) { |
1171 |
|
|
clIdx = tenAniso_Cl1; |
1172 |
|
|
cpIdx = tenAniso_Cp1; |
1173 |
|
|
csIdx = tenAniso_Cs1; |
1174 |
|
|
} else { |
1175 |
|
|
clIdx = tenAniso_Cl2; |
1176 |
|
|
cpIdx = tenAniso_Cp2; |
1177 |
|
|
csIdx = tenAniso_Cs2; |
1178 |
|
|
} |
1179 |
|
|
N = nrrdElementNumber(nin)/nrrdKindSize(nrrdKind3DMaskedSymMatrix); |
1180 |
|
|
for (I=0; I<N; I++) { |
1181 |
|
|
tenEigensolve_f(eval, NULL, tdata); |
1182 |
|
|
cl = tenAnisoEval_f(eval, clIdx); |
1183 |
|
|
cp = tenAnisoEval_f(eval, cpIdx); |
1184 |
|
|
cs = tenAnisoEval_f(eval, csIdx); |
1185 |
|
|
if (right) { |
1186 |
|
|
xi = AIR_CAST(unsigned int, cs*0 + cl*(res-1) + cp*0); |
1187 |
|
|
yi = AIR_CAST(unsigned int, cs*0 + cl*(yres-1) + cp*(yres-1)); |
1188 |
|
|
} else { |
1189 |
|
|
xi = AIR_CAST(unsigned int, cs*0 + cl*0 + cp*(res-1)); |
1190 |
|
|
yi = AIR_CAST(unsigned int, cs*0 + cl*(res-1) + cp*(res-1)); |
1191 |
|
|
} |
1192 |
|
|
weight = wlup ? wlup(nwght->data, I) : 1.0f; |
1193 |
|
|
if (xi < res && yi < yres-1) { |
1194 |
|
|
out[xi + res*yi] += tdata[0]*weight; |
1195 |
|
|
} |
1196 |
|
|
tdata += nrrdKindSize(nrrdKind3DMaskedSymMatrix); |
1197 |
|
|
} |
1198 |
|
|
|
1199 |
|
|
return 0; |
1200 |
|
|
} |
1201 |
|
|
|
1202 |
|
|
tenEvecRGBParm * |
1203 |
|
|
tenEvecRGBParmNew() { |
1204 |
|
|
tenEvecRGBParm *rgbp; |
1205 |
|
|
|
1206 |
|
2 |
rgbp = AIR_CAST(tenEvecRGBParm *, calloc(1, sizeof(tenEvecRGBParm))); |
1207 |
✓✗ |
1 |
if (rgbp) { |
1208 |
|
1 |
rgbp->which = 0; |
1209 |
|
1 |
rgbp->aniso = tenAniso_Cl2; |
1210 |
|
1 |
rgbp->confThresh = 0.5; |
1211 |
|
1 |
rgbp->anisoGamma = 1.0; |
1212 |
|
1 |
rgbp->gamma = 1.0; |
1213 |
|
1 |
rgbp->bgGray = 0.0; |
1214 |
|
1 |
rgbp->isoGray = 0.0; |
1215 |
|
1 |
rgbp->maxSat = 1.0; |
1216 |
|
1 |
rgbp->typeOut = nrrdTypeFloat; |
1217 |
|
1 |
rgbp->genAlpha = AIR_FALSE; |
1218 |
|
1 |
} |
1219 |
|
1 |
return rgbp; |
1220 |
|
|
} |
1221 |
|
|
|
1222 |
|
|
tenEvecRGBParm * |
1223 |
|
|
tenEvecRGBParmNix(tenEvecRGBParm *rgbp) { |
1224 |
|
|
|
1225 |
✓✗ |
2 |
if (rgbp) { |
1226 |
|
1 |
airFree(rgbp); |
1227 |
|
1 |
} |
1228 |
|
1 |
return NULL; |
1229 |
|
|
} |
1230 |
|
|
|
1231 |
|
|
int |
1232 |
|
|
tenEvecRGBParmCheck(const tenEvecRGBParm *rgbp) { |
1233 |
|
|
static const char me[]="tenEvecRGBParmCheck"; |
1234 |
|
|
|
1235 |
|
|
if (!rgbp) { |
1236 |
|
|
biffAddf(TEN, "%s: got NULL pointer", me); |
1237 |
|
|
return 1; |
1238 |
|
|
} |
1239 |
|
|
if (!( rgbp->which <= 2 )) { |
1240 |
|
|
biffAddf(TEN, "%s: which must be 0, 1, or 2 (not %u)", me, rgbp->which); |
1241 |
|
|
return 1; |
1242 |
|
|
} |
1243 |
|
|
if (airEnumValCheck(tenAniso, rgbp->aniso)) { |
1244 |
|
|
biffAddf(TEN, "%s: anisotropy metric %d not valid", me, rgbp->aniso); |
1245 |
|
|
return 1; |
1246 |
|
|
} |
1247 |
|
|
if (nrrdTypeDefault != rgbp->typeOut |
1248 |
|
|
&& airEnumValCheck(nrrdType, rgbp->typeOut)) { |
1249 |
|
|
biffAddf(TEN, "%s: output type (%d) not valid", me, rgbp->typeOut); |
1250 |
|
|
return 1; |
1251 |
|
|
} |
1252 |
|
|
return 0; |
1253 |
|
|
} |
1254 |
|
|
|
1255 |
|
|
float |
1256 |
|
|
_tenEvecRGBComp_f(float conf, float aniso, float comp, |
1257 |
|
|
const tenEvecRGBParm *rgbp) { |
1258 |
|
|
double X; |
1259 |
|
|
|
1260 |
|
|
X = AIR_ABS(comp); |
1261 |
|
|
X = pow(X, 1.0/rgbp->gamma); |
1262 |
|
|
X = AIR_LERP(rgbp->maxSat*aniso, rgbp->isoGray, X); |
1263 |
|
|
return AIR_CAST(float, conf > rgbp->confThresh ? X : rgbp->bgGray); |
1264 |
|
|
} |
1265 |
|
|
|
1266 |
|
|
double |
1267 |
|
|
_tenEvecRGBComp_d(double conf, double aniso, double comp, |
1268 |
|
|
const tenEvecRGBParm *rgbp) { |
1269 |
|
|
double X; |
1270 |
|
|
|
1271 |
|
|
X = AIR_ABS(comp); |
1272 |
|
|
X = pow(X, 1.0/rgbp->gamma); |
1273 |
|
|
X = AIR_LERP(rgbp->maxSat*aniso, rgbp->isoGray, X); |
1274 |
|
|
return conf > rgbp->confThresh ? X : rgbp->bgGray; |
1275 |
|
|
} |
1276 |
|
|
|
1277 |
|
|
void |
1278 |
|
|
tenEvecRGBSingle_f(float RGB[3], float conf, const float eval[3], |
1279 |
|
|
const float evec[3], const tenEvecRGBParm *rgbp) { |
1280 |
|
|
float aniso; |
1281 |
|
|
|
1282 |
|
|
if (RGB && eval && rgbp) { |
1283 |
|
|
aniso = tenAnisoEval_f(eval, rgbp->aniso); |
1284 |
|
|
aniso = AIR_CAST(float, pow(aniso, 1.0/rgbp->anisoGamma)); |
1285 |
|
|
ELL_3V_SET(RGB, |
1286 |
|
|
_tenEvecRGBComp_f(conf, aniso, evec[0], rgbp), |
1287 |
|
|
_tenEvecRGBComp_f(conf, aniso, evec[1], rgbp), |
1288 |
|
|
_tenEvecRGBComp_f(conf, aniso, evec[2], rgbp)); |
1289 |
|
|
} |
1290 |
|
|
return; |
1291 |
|
|
} |
1292 |
|
|
|
1293 |
|
|
void |
1294 |
|
|
tenEvecRGBSingle_d(double RGB[3], double conf, const double eval[3], |
1295 |
|
|
const double evec[3], const tenEvecRGBParm *rgbp) { |
1296 |
|
|
double aniso; |
1297 |
|
|
|
1298 |
|
|
if (RGB && eval && rgbp) { |
1299 |
|
|
aniso = tenAnisoEval_d(eval, rgbp->aniso); |
1300 |
|
|
aniso = pow(aniso, 1.0/rgbp->anisoGamma); |
1301 |
|
|
ELL_3V_SET(RGB, |
1302 |
|
|
_tenEvecRGBComp_d(conf, aniso, evec[0], rgbp), |
1303 |
|
|
_tenEvecRGBComp_d(conf, aniso, evec[1], rgbp), |
1304 |
|
|
_tenEvecRGBComp_d(conf, aniso, evec[2], rgbp)); |
1305 |
|
|
} |
1306 |
|
|
return; |
1307 |
|
|
} |
1308 |
|
|
|