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 |
|
|
|
25 |
|
|
#include "pull.h" |
26 |
|
|
#include "privatePull.h" |
27 |
|
|
|
28 |
|
|
pullContext * |
29 |
|
|
pullContextNew(void) { |
30 |
|
|
pullContext *pctx; |
31 |
|
|
unsigned int ii; |
32 |
|
|
|
33 |
|
|
pctx = (pullContext *)calloc(1, sizeof(pullContext)); |
34 |
|
|
if (!pctx) { |
35 |
|
|
return NULL; |
36 |
|
|
} |
37 |
|
|
|
38 |
|
|
_pullInitParmInit(&(pctx->initParm)); |
39 |
|
|
_pullIterParmInit(&(pctx->iterParm)); |
40 |
|
|
_pullSysParmInit(&(pctx->sysParm)); |
41 |
|
|
_pullFlagInit(&(pctx->flag)); |
42 |
|
|
pctx->verbose = 0; |
43 |
|
|
pctx->threadNum = 1; |
44 |
|
|
pctx->rngSeed = 42; |
45 |
|
|
pctx->progressBinMod = 50; |
46 |
|
|
pctx->iter_cb = NULL; |
47 |
|
|
pctx->data_cb = NULL; |
48 |
|
|
|
49 |
|
|
for (ii=0; ii<PULL_VOLUME_MAXNUM; ii++) { |
50 |
|
|
pctx->vol[ii] = NULL; |
51 |
|
|
} |
52 |
|
|
pctx->volNum = 0; |
53 |
|
|
for (ii=0; ii<=PULL_INFO_MAX; ii++) { |
54 |
|
|
pctx->ispec[ii] = NULL; |
55 |
|
|
pctx->infoIdx[ii] = UINT_MAX; |
56 |
|
|
} |
57 |
|
|
pctx->interType = pullInterTypeUnknown; |
58 |
|
|
pctx->energySpecR = pullEnergySpecNew(); |
59 |
|
|
pctx->energySpecS = pullEnergySpecNew(); |
60 |
|
|
pctx->energySpecWin = pullEnergySpecNew(); |
61 |
|
|
|
62 |
|
|
pctx->haltonOffset = 0; |
63 |
|
|
ELL_4V_SET(pctx->bboxMin, AIR_NAN, AIR_NAN, AIR_NAN, AIR_NAN); |
64 |
|
|
ELL_4V_SET(pctx->bboxMax, AIR_NAN, AIR_NAN, AIR_NAN, AIR_NAN); |
65 |
|
|
pctx->infoTotalLen = 0; /* will be set later */ |
66 |
|
|
pctx->idtagNext = 0; |
67 |
|
|
pctx->haveScale = AIR_FALSE; |
68 |
|
|
pctx->constraint = 0; |
69 |
|
|
pctx->constraintDim = -1; |
70 |
|
|
pctx->targetDim = -1; |
71 |
|
|
pctx->finished = AIR_FALSE; |
72 |
|
|
pctx->maxDistSpace = AIR_NAN; |
73 |
|
|
pctx->maxDistScale = AIR_NAN; |
74 |
|
|
pctx->voxelSizeSpace = AIR_NAN; |
75 |
|
|
pctx->voxelSizeScale = AIR_NAN; |
76 |
|
|
pctx->eipScale = 1.0; |
77 |
|
|
|
78 |
|
|
pctx->bin = NULL; |
79 |
|
|
ELL_4V_SET(pctx->binsEdge, 0, 0, 0, 0); |
80 |
|
|
pctx->binNum = 0; |
81 |
|
|
pctx->binNextIdx = 0; |
82 |
|
|
|
83 |
|
|
pctx->tmpPointPerm = NULL; |
84 |
|
|
pctx->tmpPointPtr = NULL; |
85 |
|
|
pctx->tmpPointNum = 0; |
86 |
|
|
|
87 |
|
|
/* pctx->binMutex setup my pullStart */ |
88 |
|
|
pctx->task = NULL; |
89 |
|
|
pctx->iterBarrierA = NULL; |
90 |
|
|
pctx->iterBarrierB = NULL; |
91 |
|
|
#if PULL_HINTER |
92 |
|
|
pctx->nhinter = nrrdNew(); |
93 |
|
|
#endif |
94 |
|
|
pctx->logAdd = NULL; |
95 |
|
|
|
96 |
|
|
pctx->timeIteration = 0; |
97 |
|
|
pctx->timeRun = 0; |
98 |
|
|
pctx->energy = AIR_NAN; |
99 |
|
|
pctx->addNum = 0; |
100 |
|
|
pctx->nixNum = 0; |
101 |
|
|
pctx->stuckNum = 0; |
102 |
|
|
pctx->pointNum = 0; |
103 |
|
|
pctx->iter = 0; |
104 |
|
|
for (ii=pullCountUnknown; ii<pullCountLast; ii++) { |
105 |
|
|
pctx->count[ii] = 0; |
106 |
|
|
} |
107 |
|
|
return pctx; |
108 |
|
|
} |
109 |
|
|
|
110 |
|
|
/* |
111 |
|
|
** this should only nix things created by pullContextNew, or the things |
112 |
|
|
** (vols and ispecs) that were explicitly added to this context |
113 |
|
|
*/ |
114 |
|
|
pullContext * |
115 |
|
|
pullContextNix(pullContext *pctx) { |
116 |
|
|
unsigned int ii; |
117 |
|
|
|
118 |
|
|
if (pctx) { |
119 |
|
|
for (ii=0; ii<pctx->volNum; ii++) { |
120 |
|
|
pctx->vol[ii] = pullVolumeNix(pctx->vol[ii]); |
121 |
|
|
} |
122 |
|
|
pctx->volNum = 0; |
123 |
|
|
for (ii=0; ii<=PULL_INFO_MAX; ii++) { |
124 |
|
|
if (pctx->ispec[ii]) { |
125 |
|
|
pctx->ispec[ii] = pullInfoSpecNix(pctx->ispec[ii]); |
126 |
|
|
} |
127 |
|
|
} |
128 |
|
|
pctx->energySpecR = pullEnergySpecNix(pctx->energySpecR); |
129 |
|
|
pctx->energySpecS = pullEnergySpecNix(pctx->energySpecS); |
130 |
|
|
pctx->energySpecWin = pullEnergySpecNix(pctx->energySpecWin); |
131 |
|
|
#if PULL_HINTER |
132 |
|
|
nrrdNuke(pctx->nhinter); |
133 |
|
|
#endif |
134 |
|
|
/* handled elsewhere: bin, task, iterBarrierA, iterBarrierB */ |
135 |
|
|
airFree(pctx); |
136 |
|
|
} |
137 |
|
|
return NULL; |
138 |
|
|
} |
139 |
|
|
|
140 |
|
|
int |
141 |
|
|
_pullMiscParmCheck(pullContext *pctx) { |
142 |
|
|
static const char me[]="_pullMiscParmCheck"; |
143 |
|
|
double denr; |
144 |
|
|
|
145 |
|
|
if (!( AIR_IN_CL(1, pctx->threadNum, PULL_THREAD_MAXNUM) )) { |
146 |
|
|
biffAddf(PULL, "%s: pctx->threadNum (%d) outside valid range [1,%d]", me, |
147 |
|
|
pctx->threadNum, PULL_THREAD_MAXNUM); |
148 |
|
|
return 1; |
149 |
|
|
} |
150 |
|
|
if (airEnumValCheck(pullInterType, pctx->interType)) { |
151 |
|
|
biffAddf(PULL, "%s: pctx->interType %d not a valid %s", me, |
152 |
|
|
pctx->interType, pullInterType->name); |
153 |
|
|
return 1; |
154 |
|
|
} |
155 |
|
|
/* HEY: error checking on energySpec's seems rather spotty . . . */ |
156 |
|
|
if (pullEnergyUnknown == pctx->energySpecR->energy) { |
157 |
|
|
biffAddf(PULL, "%s: need to set space energy", me); |
158 |
|
|
return 1; |
159 |
|
|
} |
160 |
|
|
if (pullInterTypeJustR == pctx->interType |
161 |
|
|
|| pullInterTypeUnivariate == pctx->interType) { |
162 |
|
|
if (pullEnergyZero != pctx->energySpecS->energy) { |
163 |
|
|
biffAddf(PULL, "%s: can't use scale energy %s with inter type %s", me, |
164 |
|
|
pctx->energySpecS->energy->name, |
165 |
|
|
airEnumStr(pullInterType, pctx->interType)); |
166 |
|
|
return 1; |
167 |
|
|
} |
168 |
|
|
} else { |
169 |
|
|
if (pullEnergyZero == pctx->energySpecS->energy) { |
170 |
|
|
biffAddf(PULL, "%s: need a non-zero scale energy for inter type %s", me, |
171 |
|
|
airEnumStr(pullInterType, pctx->interType)); |
172 |
|
|
return 1; |
173 |
|
|
} |
174 |
|
|
} |
175 |
|
|
/* make sure that spatial repulsion is really repulsive at r=0 */ |
176 |
|
|
pctx->energySpecR->energy->eval(&denr, 0.0000001, pctx->energySpecR->parm); |
177 |
|
|
if (!( denr < 0 )) { |
178 |
|
|
biffAddf(PULL, "%s: spatial energy doesn't have negative slope near r=0", |
179 |
|
|
me); |
180 |
|
|
return 1; |
181 |
|
|
} |
182 |
|
|
|
183 |
|
|
return 0; |
184 |
|
|
} |
185 |
|
|
|
186 |
|
|
int |
187 |
|
|
_pullContextCheck(pullContext *pctx) { |
188 |
|
|
static const char me[]="_pullContextCheck"; |
189 |
|
|
unsigned int ii, ccount; |
190 |
|
|
int gotIspec, gotConstr; |
191 |
|
|
const pullInfoSpec *lthr, *strn; |
192 |
|
|
|
193 |
|
|
if (!pctx) { |
194 |
|
|
biffAddf(PULL, "%s: got NULL pointer", me); |
195 |
|
|
return 1; |
196 |
|
|
} |
197 |
|
|
if (_pullInitParmCheck(&(pctx->initParm)) |
198 |
|
|
|| _pullIterParmCheck(&(pctx->iterParm)) |
199 |
|
|
|| _pullSysParmCheck(&(pctx->sysParm)) |
200 |
|
|
|| _pullMiscParmCheck(pctx)) { |
201 |
|
|
biffAddf(PULL, "%s: problem with parameters", me); |
202 |
|
|
return 1; |
203 |
|
|
} |
204 |
|
|
|
205 |
|
|
if (!pctx->volNum) { |
206 |
|
|
biffAddf(PULL, "%s: have no volumes set", me); |
207 |
|
|
return 1; |
208 |
|
|
} |
209 |
|
|
gotConstr = 0; |
210 |
|
|
gotIspec = AIR_FALSE; |
211 |
|
|
for (ii=0; ii<=PULL_INFO_MAX; ii++) { |
212 |
|
|
if (pctx->ispec[ii]) { |
213 |
|
|
if (pctx->ispec[ii]->constraint) { |
214 |
|
|
if (1 != pullInfoLen(ii)) { |
215 |
|
|
biffAddf(PULL, "%s: can't use non-scalar (len %u) %s as constraint", |
216 |
|
|
me, pullInfoLen(ii), airEnumStr(pullInfo, ii)); |
217 |
|
|
return 1; |
218 |
|
|
} |
219 |
|
|
if (pullSourceGage != pctx->ispec[ii]->source) { |
220 |
|
|
biffAddf(PULL, "%s: sorry, constraints can currently only " |
221 |
|
|
"come from %s", me, |
222 |
|
|
airEnumStr(pullSource, pullSourceGage)); |
223 |
|
|
return 1; |
224 |
|
|
} |
225 |
|
|
if (gotConstr) { |
226 |
|
|
biffAddf(PULL, "%s: can't also have %s constraint, already have " |
227 |
|
|
"constraint on %s ", me, airEnumStr(pullInfo, ii), |
228 |
|
|
airEnumStr(pullInfo, gotConstr)); |
229 |
|
|
return 1; |
230 |
|
|
} |
231 |
|
|
/* elso no problems having constraint on ii */ |
232 |
|
|
gotConstr = ii; |
233 |
|
|
} |
234 |
|
|
/* make sure we have extra info as necessary */ |
235 |
|
|
switch (ii) { |
236 |
|
|
case pullInfoInside: |
237 |
|
|
case pullInfoHeight: |
238 |
|
|
case pullInfoHeightLaplacian: |
239 |
|
|
case pullInfoSeedThresh: |
240 |
|
|
case pullInfoLiveThresh: |
241 |
|
|
case pullInfoLiveThresh2: |
242 |
|
|
case pullInfoLiveThresh3: |
243 |
|
|
case pullInfoIsovalue: |
244 |
|
|
case pullInfoStrength: |
245 |
|
|
if (!( AIR_EXISTS(pctx->ispec[ii]->scale) |
246 |
|
|
&& AIR_EXISTS(pctx->ispec[ii]->zero) )) { |
247 |
|
|
biffAddf(PULL, "%s: %s info needs scale (%g) and zero (%g)", me, |
248 |
|
|
airEnumStr(pullInfo, ii), |
249 |
|
|
pctx->ispec[ii]->scale, pctx->ispec[ii]->zero); |
250 |
|
|
return 1; |
251 |
|
|
} |
252 |
|
|
break; |
253 |
|
|
} |
254 |
|
|
gotIspec = AIR_TRUE; |
255 |
|
|
} |
256 |
|
|
} |
257 |
|
|
|
258 |
|
|
if (!gotIspec) { |
259 |
|
|
biffAddf(PULL, "%s: have no infos set", me); |
260 |
|
|
return 1; |
261 |
|
|
} |
262 |
|
|
if (pctx->ispec[pullInfoStrength]) { |
263 |
|
|
if (pullSourceGage != pctx->ispec[pullInfoStrength]->source) { |
264 |
|
|
biffAddf(PULL, "%s: %s info must come from %s (not %s)", me, |
265 |
|
|
airEnumStr(pullInfo, pullInfoStrength), |
266 |
|
|
airEnumStr(pullSource, pullSourceGage), |
267 |
|
|
airEnumStr(pullSource, pctx->ispec[pullInfoStrength]->source)); |
268 |
|
|
return 1; |
269 |
|
|
} |
270 |
|
|
} |
271 |
|
|
if (pctx->ispec[pullInfoInside]) { |
272 |
|
|
if (!pctx->ispec[pullInfoInsideGradient]) { |
273 |
|
|
biffAddf(PULL, "%s: want %s but don't have %s set", me, |
274 |
|
|
airEnumStr(pullInfo, pullInfoInside), |
275 |
|
|
airEnumStr(pullInfo, pullInfoInsideGradient)); |
276 |
|
|
return 1; |
277 |
|
|
} |
278 |
|
|
} |
279 |
|
|
if (pctx->ispec[pullInfoTangent2]) { |
280 |
|
|
if (!pctx->ispec[pullInfoTangent1]) { |
281 |
|
|
biffAddf(PULL, "%s: want %s but don't have %s set", me, |
282 |
|
|
airEnumStr(pullInfo, pullInfoTangent2), |
283 |
|
|
airEnumStr(pullInfo, pullInfoTangent1)); |
284 |
|
|
return 1; |
285 |
|
|
} |
286 |
|
|
} |
287 |
|
|
if (pctx->ispec[pullInfoNegativeTangent2]) { |
288 |
|
|
if (!pctx->ispec[pullInfoNegativeTangent1]) { |
289 |
|
|
biffAddf(PULL, "%s: want %s but don't have %s set", me, |
290 |
|
|
airEnumStr(pullInfo, pullInfoNegativeTangent2), |
291 |
|
|
airEnumStr(pullInfo, pullInfoNegativeTangent1)); |
292 |
|
|
return 1; |
293 |
|
|
} |
294 |
|
|
} |
295 |
|
|
ccount = 0; |
296 |
|
|
ccount += !!(pctx->ispec[pullInfoTangent1]); |
297 |
|
|
ccount += !!(pctx->ispec[pullInfoTangent2]); |
298 |
|
|
ccount += !!(pctx->ispec[pullInfoNegativeTangent1]); |
299 |
|
|
ccount += !!(pctx->ispec[pullInfoNegativeTangent2]); |
300 |
|
|
if (4 == ccount) { |
301 |
|
|
biffAddf(PULL, "%s: can't specify all 4 tangents together", me); |
302 |
|
|
return 1; |
303 |
|
|
} |
304 |
|
|
if (3 == ccount && !pctx->flag.allowCodimension3Constraints) { |
305 |
|
|
biffAddf(PULL, "%s: must turn on allowCodimension3Constraints " |
306 |
|
|
"with 3 tangents", me); |
307 |
|
|
return 1; |
308 |
|
|
} |
309 |
|
|
if (pctx->ispec[pullInfoHeight]) { |
310 |
|
|
if (!( pctx->ispec[pullInfoHeightGradient] )) { |
311 |
|
|
biffAddf(PULL, "%s: want %s but don't have %s set", me, |
312 |
|
|
airEnumStr(pullInfo, pullInfoHeight), |
313 |
|
|
airEnumStr(pullInfo, pullInfoHeightGradient)); |
314 |
|
|
return 1; |
315 |
|
|
} |
316 |
|
|
if (pctx->ispec[pullInfoHeight]->constraint) { |
317 |
|
|
if (!pctx->ispec[pullInfoHeightHessian]) { |
318 |
|
|
biffAddf(PULL, "%s: want constrained %s but don't have %s set", me, |
319 |
|
|
airEnumStr(pullInfo, pullInfoHeight), |
320 |
|
|
airEnumStr(pullInfo, pullInfoHeightHessian)); |
321 |
|
|
return 1; |
322 |
|
|
} |
323 |
|
|
if (!( pctx->ispec[pullInfoTangent1] |
324 |
|
|
|| pctx->ispec[pullInfoNegativeTangent1] )) { |
325 |
|
|
if (!pctx->flag.allowCodimension3Constraints) { |
326 |
|
|
biffAddf(PULL, "%s: want constrained %s but need (at least) " |
327 |
|
|
"%s or %s set (maybe enable " |
328 |
|
|
"pullFlagAllowCodimension3Constraints?)", |
329 |
|
|
me, |
330 |
|
|
airEnumStr(pullInfo, pullInfoHeight), |
331 |
|
|
airEnumStr(pullInfo, pullInfoTangent1), |
332 |
|
|
airEnumStr(pullInfo, pullInfoNegativeTangent1)); |
333 |
|
|
return 1; |
334 |
|
|
} |
335 |
|
|
} |
336 |
|
|
} |
337 |
|
|
} |
338 |
|
|
if (pctx->ispec[pullInfoHeightLaplacian]) { |
339 |
|
|
if (!( pctx->ispec[pullInfoHeight] )) { |
340 |
|
|
biffAddf(PULL, "%s: want %s but don't have %s set", me, |
341 |
|
|
airEnumStr(pullInfo, pullInfoHeightLaplacian), |
342 |
|
|
airEnumStr(pullInfo, pullInfoHeight)); |
343 |
|
|
return 1; |
344 |
|
|
} |
345 |
|
|
} |
346 |
|
|
if (pctx->ispec[pullInfoIsovalue]) { |
347 |
|
|
if (!( pctx->ispec[pullInfoIsovalueGradient] |
348 |
|
|
&& pctx->ispec[pullInfoIsovalueHessian] )) { |
349 |
|
|
biffAddf(PULL, "%s: want %s but don't have %s and %s set", me, |
350 |
|
|
airEnumStr(pullInfo, pullInfoIsovalue), |
351 |
|
|
airEnumStr(pullInfo, pullInfoIsovalueGradient), |
352 |
|
|
airEnumStr(pullInfo, pullInfoIsovalueHessian)); |
353 |
|
|
return 1; |
354 |
|
|
} |
355 |
|
|
} |
356 |
|
|
if ((lthr = pctx->ispec[pullInfoLiveThresh]) |
357 |
|
|
&& (strn = pctx->ispec[pullInfoStrength]) |
358 |
|
|
&& lthr->volIdx == strn->volIdx |
359 |
|
|
&& lthr->item == strn->item |
360 |
|
|
&& lthr->scale*strn->scale < 0) { |
361 |
|
|
biffAddf(PULL, "%s: %s and %s refer to same item (%s in %s), but have " |
362 |
|
|
"scaling factors with different signs (%g and %g); really?", me, |
363 |
|
|
airEnumStr(pullInfo, pullInfoLiveThresh), |
364 |
|
|
airEnumStr(pullInfo, pullInfoStrength), |
365 |
|
|
airEnumStr(pctx->vol[lthr->volIdx]->kind->enm, lthr->item), |
366 |
|
|
lthr->volName, lthr->scale, strn->scale); |
367 |
|
|
return 1; |
368 |
|
|
} |
369 |
|
|
if (pullInitMethodPointPerVoxel == pctx->initParm.method) { |
370 |
|
|
if (!( pctx->ispec[pullInfoSeedThresh] )) { |
371 |
|
|
biffAddf(PULL, "%s: sorry, need to have %s info set with %s init", |
372 |
|
|
me, airEnumStr(pullInfo, pullInfoSeedThresh), |
373 |
|
|
"point-per-voxel" /* HEY no airEnum for this */); |
374 |
|
|
return 1; |
375 |
|
|
} |
376 |
|
|
} |
377 |
|
|
|
378 |
|
|
return 0; |
379 |
|
|
} |
380 |
|
|
|
381 |
|
|
/* |
382 |
|
|
** the API for this is most certainly going to change; the |
383 |
|
|
** tensor output at this point is a hack created for vis purposes |
384 |
|
|
*/ |
385 |
|
|
int |
386 |
|
|
pullOutputGetFilter(Nrrd *nPosOut, Nrrd *nTenOut, Nrrd *nStrengthOut, |
387 |
|
|
const double _scaleVec[3], double scaleRad, |
388 |
|
|
pullContext *pctx, |
389 |
|
|
unsigned int idtagMin, unsigned int idtagMax) { |
390 |
|
|
static const char me[]="pullOutputGetFilter"; |
391 |
|
|
unsigned int binIdx, pointNum, pointIdx, outIdx; |
392 |
|
|
int E; |
393 |
|
|
double *posOut, *tenOut, *strnOut, scaleVec[3], scaleDir[3], scaleMag; |
394 |
|
|
pullBin *bin; |
395 |
|
|
pullPoint *point; |
396 |
|
|
|
397 |
|
|
if (!pctx) { |
398 |
|
|
biffAddf(PULL, "%s: got NULL pointer", me); |
399 |
|
|
return 1; |
400 |
|
|
} |
401 |
|
|
if (nStrengthOut && !pctx->ispec[pullInfoStrength]) { |
402 |
|
|
biffAddf(PULL, "%s: can't save out %s info that hasn't been set", |
403 |
|
|
me, airEnumStr(pullInfo, pullInfoStrength)); |
404 |
|
|
return 1; |
405 |
|
|
} |
406 |
|
|
if (!AIR_EXISTS(scaleRad)) { |
407 |
|
|
biffAddf(PULL, "%s: got non-existent scaleRad %g", me, scaleRad); |
408 |
|
|
return 1; |
409 |
|
|
} |
410 |
|
|
if (!_scaleVec) { |
411 |
|
|
ELL_3V_SET(scaleVec, 0, 0, 0); |
412 |
|
|
ELL_3V_SET(scaleDir, 0, 0, 0); |
413 |
|
|
scaleMag = 0; |
414 |
|
|
} else { |
415 |
|
|
ELL_3V_COPY(scaleVec, _scaleVec); |
416 |
|
|
if (ELL_3V_LEN(scaleVec)) { |
417 |
|
|
ELL_3V_NORM(scaleDir, scaleVec, scaleMag); |
418 |
|
|
} else { |
419 |
|
|
ELL_3V_SET(scaleDir, 0, 0, 0); |
420 |
|
|
scaleMag = 0; |
421 |
|
|
} |
422 |
|
|
} |
423 |
|
|
pointNum = pullPointNumberFilter(pctx, idtagMin, idtagMax); |
424 |
|
|
E = AIR_FALSE; |
425 |
|
|
if (nPosOut) { |
426 |
|
|
E |= nrrdMaybeAlloc_va(nPosOut, nrrdTypeDouble, 2, |
427 |
|
|
AIR_CAST(size_t, 4), |
428 |
|
|
AIR_CAST(size_t, pointNum)); |
429 |
|
|
} |
430 |
|
|
if (nTenOut) { |
431 |
|
|
E |= nrrdMaybeAlloc_va(nTenOut, nrrdTypeDouble, 2, |
432 |
|
|
AIR_CAST(size_t, 7), |
433 |
|
|
AIR_CAST(size_t, pointNum)); |
434 |
|
|
} |
435 |
|
|
if (nStrengthOut) { |
436 |
|
|
E |= nrrdMaybeAlloc_va(nStrengthOut, nrrdTypeDouble, 1, |
437 |
|
|
AIR_CAST(size_t, pointNum)); |
438 |
|
|
} |
439 |
|
|
if (E) { |
440 |
|
|
biffMovef(PULL, NRRD, "%s: trouble allocating outputs", me); |
441 |
|
|
return 1; |
442 |
|
|
} |
443 |
|
|
posOut = nPosOut ? (double*)(nPosOut->data) : NULL; |
444 |
|
|
tenOut = nTenOut ? (double*)(nTenOut->data) : NULL; |
445 |
|
|
strnOut = nStrengthOut ? (double*)(nStrengthOut->data) : NULL; |
446 |
|
|
|
447 |
|
|
outIdx = 0; |
448 |
|
|
for (binIdx=0; binIdx<pctx->binNum; binIdx++) { |
449 |
|
|
bin = pctx->bin + binIdx; |
450 |
|
|
for (pointIdx=0; pointIdx<bin->pointNum; pointIdx++) { |
451 |
|
|
point = bin->point[pointIdx]; |
452 |
|
|
if (!( idtagMin <= point->idtag |
453 |
|
|
&& (0 == idtagMax |
454 |
|
|
|| point->idtag <= idtagMax) )) { |
455 |
|
|
continue; |
456 |
|
|
} |
457 |
|
|
/** to find idtag of point at particular location **/ |
458 |
|
|
/* |
459 |
|
|
if (AIR_ABS(514.113 - point->pos[0]) < 0.5 && |
460 |
|
|
AIR_ABS(453.519 - point->pos[1]) < 0.5 && |
461 |
|
|
AIR_ABS(606.723 - point->pos[ 2 ]) < 0.5) { |
462 |
|
|
printf("!%s: point %u at (%g,%g,%g,%g) ##############\n", |
463 |
|
|
me, point->idtag, |
464 |
|
|
point->pos[0], point->pos[1], |
465 |
|
|
point->pos[2], point->pos[3]); |
466 |
|
|
} |
467 |
|
|
*/ |
468 |
|
|
if (nPosOut) { |
469 |
|
|
ELL_4V_COPY(posOut + 4*outIdx, point->pos); |
470 |
|
|
if (pctx->haveScale && scaleMag) { |
471 |
|
|
double *tpos, tvec[3], sc; |
472 |
|
|
tpos = posOut + 4*outIdx; |
473 |
|
|
sc = ELL_3V_DOT(tpos, scaleDir); |
474 |
|
|
ELL_3V_SCALE(tvec, sc, scaleDir); |
475 |
|
|
ELL_3V_SUB(tpos, tpos, tvec); |
476 |
|
|
ELL_3V_SCALE(tvec, scaleMag*tpos[3], scaleDir); |
477 |
|
|
ELL_3V_ADD2(tpos, tpos, tvec); |
478 |
|
|
} |
479 |
|
|
/* |
480 |
|
|
if (4523 == point->idtag) { |
481 |
|
|
fprintf(stderr, "!%s: point %u at index %u and pos %g %g %g %g\n", |
482 |
|
|
me, point->idtag, outIdx, |
483 |
|
|
(posOut + 4*outIdx)[0], (posOut + 4*outIdx)[1], |
484 |
|
|
(posOut + 4*outIdx)[2], (posOut + 4*outIdx)[3]); |
485 |
|
|
} |
486 |
|
|
*/ |
487 |
|
|
} |
488 |
|
|
if (nStrengthOut) { |
489 |
|
|
strnOut[outIdx] = pullPointScalar(pctx, point, pullInfoStrength, |
490 |
|
|
NULL, NULL); |
491 |
|
|
} |
492 |
|
|
if (nTenOut) { |
493 |
|
|
double scl, tout[7]; |
494 |
|
|
scl = 1; |
495 |
|
|
if (pctx->ispec[pullInfoTensor]) { |
496 |
|
|
TEN_T_COPY(tout, point->info + pctx->infoIdx[pullInfoTensor]); |
497 |
|
|
} else if (pctx->ispec[pullInfoHeightHessian]) { |
498 |
|
|
double *hess, eval[3], evec[9], eceil, maxeval, elen; |
499 |
|
|
unsigned int maxi; |
500 |
|
|
hess = point->info + pctx->infoIdx[pullInfoHeightHessian]; |
501 |
|
|
if (0) { |
502 |
|
|
/* do this if using general symmetric tensor glyphs */ |
503 |
|
|
TEN_M2T(tout, hess); |
504 |
|
|
tout[0] = 1.0; |
505 |
|
|
} if (0) { |
506 |
|
|
/* for spheres and only spheres */ |
507 |
|
|
TEN_T_SET(tout, 1, 1, 0, 0, 1, 0, 1); |
508 |
|
|
} else { |
509 |
|
|
ell_3m_eigensolve_d(eval, evec, hess, 10); |
510 |
|
|
eval[0] = AIR_ABS(eval[0]); |
511 |
|
|
eval[1] = AIR_ABS(eval[1]); |
512 |
|
|
eval[2] = AIR_ABS(eval[2]); |
513 |
|
|
/* elen = ELL_3V_LEN(eval); */ |
514 |
|
|
elen = (eval[0]+eval[1]+eval[2]); |
515 |
|
|
eceil = elen ? 10/elen : 10; |
516 |
|
|
eval[0] = eval[0] ? AIR_MIN(eceil, 1.0/eval[0]) : eceil; |
517 |
|
|
eval[1] = eval[1] ? AIR_MIN(eceil, 1.0/eval[1]) : eceil; |
518 |
|
|
eval[2] = eval[2] ? AIR_MIN(eceil, 1.0/eval[2]) : eceil; |
519 |
|
|
maxi = ELL_MAX3_IDX(eval[0], eval[1], eval[2]); |
520 |
|
|
maxeval = eval[maxi]; |
521 |
|
|
ELL_3V_SCALE(eval, 1/maxeval, eval); |
522 |
|
|
tenMakeSingle_d(tout, 1, eval, evec); |
523 |
|
|
if (scaleRad && pctx->ispec[pullInfoHeight]->constraint) { |
524 |
|
|
double emin, sig; |
525 |
|
|
if (pctx->flag.scaleIsTau) { |
526 |
|
|
sig = gageSigOfTau(point->pos[3]); |
527 |
|
|
} else { |
528 |
|
|
sig = point->pos[3]; |
529 |
|
|
} |
530 |
|
|
tenEigensolve_d(eval, evec, tout); /* lazy way to sort */ |
531 |
|
|
emin = eval[2]; |
532 |
|
|
if (1 == pctx->constraintDim) { |
533 |
|
|
eval[1] = scaleRad*sig + emin/2; |
534 |
|
|
eval[2] = scaleRad*sig + emin/2; |
535 |
|
|
} if (2 == pctx->constraintDim) { |
536 |
|
|
double eavg; |
537 |
|
|
eavg = (2*eval[0] + eval[2])/3; |
538 |
|
|
eval[0] = eavg; |
539 |
|
|
eval[1] = eavg; |
540 |
|
|
eval[2] = scaleRad*sig + emin/2; |
541 |
|
|
} |
542 |
|
|
tenMakeSingle_d(tout, 1, eval, evec); |
543 |
|
|
} |
544 |
|
|
} |
545 |
|
|
} else if (0 /* another hack for general symmetric tensor glyphs */ |
546 |
|
|
&& pctx->constraint |
547 |
|
|
&& (pctx->ispec[pullInfoIsovalueHessian])) { |
548 |
|
|
double *hess; |
549 |
|
|
hess = point->info + pctx->infoIdx[pullInfoIsovalueHessian]; |
550 |
|
|
TEN_M2T(tout, hess); |
551 |
|
|
tout[0] = 1.0; |
552 |
|
|
} else if (pctx->constraint |
553 |
|
|
&& (pctx->ispec[pullInfoHeightGradient] |
554 |
|
|
|| pctx->ispec[pullInfoIsovalueGradient])) { |
555 |
|
|
double *grad, norm[3], len, mat[9], out[9]; |
556 |
|
|
grad = point->info + (pctx->ispec[pullInfoHeightGradient] |
557 |
|
|
? pctx->infoIdx[pullInfoHeightGradient] |
558 |
|
|
: pctx->infoIdx[pullInfoIsovalueGradient]); |
559 |
|
|
ELL_3V_NORM(norm, grad, len); |
560 |
|
|
ELL_3MV_OUTER(out, norm, norm); |
561 |
|
|
ELL_3M_IDENTITY_SET(mat); |
562 |
|
|
ELL_3M_SCALE_INCR(mat, -0.95, out); |
563 |
|
|
TEN_M2T(tout, mat); |
564 |
|
|
tout[0] = 1; |
565 |
|
|
} else { |
566 |
|
|
TEN_T_SET(tout, 1, 1, 0, 0, 1, 0, 1); |
567 |
|
|
} |
568 |
|
|
TEN_T_SCALE(tout, scl, tout); |
569 |
|
|
TEN_T_COPY(tenOut + 7*outIdx, tout); |
570 |
|
|
/* |
571 |
|
|
if (4523 == point->idtag) { |
572 |
|
|
fprintf(stderr, "!%s: point %u at index %u and ten (%g) %g %g %g %g %g %g\n", |
573 |
|
|
me, point->idtag, outIdx, |
574 |
|
|
tout[0], tout[1], tout[2], tout[3], |
575 |
|
|
tout[4], tout[5], tout[6]); |
576 |
|
|
} |
577 |
|
|
*/ |
578 |
|
|
} /* if (nTenOut) */ |
579 |
|
|
++outIdx; |
580 |
|
|
} |
581 |
|
|
} |
582 |
|
|
|
583 |
|
|
return 0; |
584 |
|
|
} |
585 |
|
|
|
586 |
|
|
int |
587 |
|
|
pullOutputGet(Nrrd *nPosOut, Nrrd *nTenOut, Nrrd *nStrengthOut, |
588 |
|
|
const double scaleVec[3], double scaleRad, |
589 |
|
|
pullContext *pctx) { |
590 |
|
|
static const char me[]="pullOutputGet"; |
591 |
|
|
|
592 |
|
|
if (pullOutputGetFilter(nPosOut, nTenOut, nStrengthOut, scaleVec, scaleRad, pctx, 0, 0)) { |
593 |
|
|
biffAddf(PULL, "%s: trouble", me); |
594 |
|
|
return 1; |
595 |
|
|
} |
596 |
|
|
return 0; |
597 |
|
|
} |
598 |
|
|
|
599 |
|
|
|
600 |
|
|
int |
601 |
|
|
pullPropGet(Nrrd *nprop, int prop, pullContext *pctx) { |
602 |
|
|
static const char me[]="pullPropGet"; |
603 |
|
|
int typeOut; |
604 |
|
|
size_t size[2]; |
605 |
|
|
unsigned int dim, pointNum, pointIdx, binIdx, *out_ui, outIdx; |
606 |
|
|
double *out_d, covar[16]; |
607 |
|
|
float *out_f, *pnc; |
608 |
|
|
unsigned char *out_uc; |
609 |
|
|
pullBin *bin; |
610 |
|
|
pullPoint *point; |
611 |
|
|
|
612 |
|
|
pointNum = pullPointNumber(pctx); |
613 |
|
|
switch(prop) { |
614 |
|
|
case pullPropEnergy: |
615 |
|
|
case pullPropStepEnergy: |
616 |
|
|
case pullPropStepConstr: |
617 |
|
|
case pullPropScale: |
618 |
|
|
case pullPropNeighCovarTrace: |
619 |
|
|
case pullPropNeighCovarDet: |
620 |
|
|
case pullPropStability: |
621 |
|
|
dim = 1; |
622 |
|
|
size[0] = pointNum; |
623 |
|
|
typeOut = nrrdTypeDouble; |
624 |
|
|
break; |
625 |
|
|
case pullPropIdtag: |
626 |
|
|
case pullPropIdCC: |
627 |
|
|
case pullPropNeighInterNum: |
628 |
|
|
dim = 1; |
629 |
|
|
size[0] = pointNum; |
630 |
|
|
typeOut = nrrdTypeUInt; |
631 |
|
|
break; |
632 |
|
|
case pullPropStuck: |
633 |
|
|
dim = 1; |
634 |
|
|
size[0] = pointNum; |
635 |
|
|
/* HEY should be nrrdTypeUInt, no? */ |
636 |
|
|
typeOut = nrrdTypeUChar; |
637 |
|
|
break; |
638 |
|
|
case pullPropPosition: |
639 |
|
|
case pullPropForce: |
640 |
|
|
dim = 2; |
641 |
|
|
size[0] = 4; |
642 |
|
|
size[1] = pointNum; |
643 |
|
|
typeOut = nrrdTypeDouble; |
644 |
|
|
break; |
645 |
|
|
case pullPropNeighDistMean: |
646 |
|
|
dim = 1; |
647 |
|
|
size[0] = pointNum; |
648 |
|
|
typeOut = nrrdTypeDouble; |
649 |
|
|
break; |
650 |
|
|
case pullPropNeighCovar: |
651 |
|
|
dim = 2; |
652 |
|
|
size[0] = 10; |
653 |
|
|
size[1] = pointNum; |
654 |
|
|
typeOut = nrrdTypeFloat; |
655 |
|
|
break; |
656 |
|
|
case pullPropNeighCovar7Ten: |
657 |
|
|
case pullPropNeighTanCovar: |
658 |
|
|
dim = 2; |
659 |
|
|
size[0] = 7; |
660 |
|
|
size[1] = pointNum; |
661 |
|
|
typeOut = nrrdTypeFloat; |
662 |
|
|
break; |
663 |
|
|
default: |
664 |
|
|
biffAddf(PULL, "%s: prop %d unrecognized", me, prop); |
665 |
|
|
return 1; |
666 |
|
|
break; |
667 |
|
|
} |
668 |
|
|
if (nrrdMaybeAlloc_nva(nprop, typeOut, dim, size)) { |
669 |
|
|
biffMovef(PULL, NRRD, "%s: trouble allocating output", me); |
670 |
|
|
return 1; |
671 |
|
|
} |
672 |
|
|
out_d = AIR_CAST(double *, nprop->data); |
673 |
|
|
out_f = AIR_CAST(float *, nprop->data); |
674 |
|
|
out_ui = AIR_CAST(unsigned int *, nprop->data); |
675 |
|
|
out_uc = AIR_CAST(unsigned char *, nprop->data); |
676 |
|
|
|
677 |
|
|
outIdx = 0; |
678 |
|
|
for (binIdx=0; binIdx<pctx->binNum; binIdx++) { |
679 |
|
|
bin = pctx->bin + binIdx; |
680 |
|
|
for (pointIdx=0; pointIdx<bin->pointNum; pointIdx++) { |
681 |
|
|
point = bin->point[pointIdx]; |
682 |
|
|
pnc = point->neighCovar; |
683 |
|
|
switch(prop) { |
684 |
|
|
case pullPropEnergy: |
685 |
|
|
out_d[outIdx] = point->energy; |
686 |
|
|
break; |
687 |
|
|
case pullPropStepEnergy: |
688 |
|
|
out_d[outIdx] = point->stepEnergy; |
689 |
|
|
break; |
690 |
|
|
case pullPropStepConstr: |
691 |
|
|
out_d[outIdx] = point->stepConstr; |
692 |
|
|
break; |
693 |
|
|
case pullPropIdtag: |
694 |
|
|
out_ui[outIdx] = point->idtag; |
695 |
|
|
break; |
696 |
|
|
case pullPropIdCC: |
697 |
|
|
out_ui[outIdx] = point->idCC; |
698 |
|
|
break; |
699 |
|
|
case pullPropNeighInterNum: |
700 |
|
|
out_ui[outIdx] = point->neighInterNum; |
701 |
|
|
break; |
702 |
|
|
case pullPropStuck: |
703 |
|
|
out_uc[outIdx] = ((point->status & PULL_STATUS_STUCK_BIT) |
704 |
|
|
? point->stuckIterNum |
705 |
|
|
: 0); |
706 |
|
|
break; |
707 |
|
|
case pullPropPosition: |
708 |
|
|
ELL_4V_COPY(out_d + 4*outIdx, point->pos); |
709 |
|
|
break; |
710 |
|
|
case pullPropForce: |
711 |
|
|
ELL_4V_COPY(out_d + 4*outIdx, point->force); |
712 |
|
|
break; |
713 |
|
|
case pullPropNeighDistMean: |
714 |
|
|
out_d[outIdx] = point->neighDistMean; |
715 |
|
|
break; |
716 |
|
|
case pullPropScale: |
717 |
|
|
out_d[outIdx] = (pctx->flag.scaleIsTau |
718 |
|
|
? gageSigOfTau(point->pos[3]) |
719 |
|
|
: point->pos[3]); |
720 |
|
|
break; |
721 |
|
|
/* |
722 |
|
|
0:xx 1:xy 2:xz 3:xs |
723 |
|
|
1 4:yy 5:yz 6:ys |
724 |
|
|
2 5 7:zz 8:zs |
725 |
|
|
3 6 8 9:ss |
726 |
|
|
*/ |
727 |
|
|
case pullPropNeighCovar: |
728 |
|
|
ELL_10V_COPY(out_f + 10*outIdx, point->neighCovar); |
729 |
|
|
break; |
730 |
|
|
case pullPropNeighCovar7Ten: |
731 |
|
|
TEN_T_SET(out_f + 7*outIdx, 1.0f, |
732 |
|
|
pnc[0], |
733 |
|
|
pnc[1], |
734 |
|
|
pnc[2], |
735 |
|
|
pnc[4], |
736 |
|
|
pnc[5], |
737 |
|
|
pnc[7]); |
738 |
|
|
break; |
739 |
|
|
case pullPropNeighTanCovar: |
740 |
|
|
#if PULL_TANCOVAR |
741 |
|
|
TEN_T_SET(out_f + 7*outIdx, 1.0f, |
742 |
|
|
point->neighTanCovar[0], |
743 |
|
|
point->neighTanCovar[1], |
744 |
|
|
point->neighTanCovar[2], |
745 |
|
|
point->neighTanCovar[3], |
746 |
|
|
point->neighTanCovar[4], |
747 |
|
|
point->neighTanCovar[5]); |
748 |
|
|
#else |
749 |
|
|
TEN_T_SET(out_f + 7*outIdx, 0.0f, |
750 |
|
|
0.0f, 0.0f, 0.0f, |
751 |
|
|
0.0f, 0.0f, |
752 |
|
|
0.0f); |
753 |
|
|
#endif |
754 |
|
|
break; |
755 |
|
|
case pullPropNeighCovarTrace: |
756 |
|
|
out_d[outIdx] = pnc[0] + pnc[4] + pnc[7] + pnc[9]; |
757 |
|
|
break; |
758 |
|
|
case pullPropNeighCovarDet: |
759 |
|
|
if (pctx->haveScale) { |
760 |
|
|
ELL_4V_SET(covar + 0, pnc[0], pnc[1], pnc[2], pnc[3]); |
761 |
|
|
ELL_4V_SET(covar + 4, pnc[1], pnc[4], pnc[5], pnc[6]); |
762 |
|
|
ELL_4V_SET(covar + 8, pnc[2], pnc[5], pnc[7], pnc[8]); |
763 |
|
|
ELL_4V_SET(covar + 12, pnc[3], pnc[6], pnc[8], pnc[9]); |
764 |
|
|
out_d[outIdx] = ELL_4M_DET(covar); |
765 |
|
|
} else { |
766 |
|
|
ELL_3V_SET(covar + 0, pnc[0], pnc[1], pnc[2]); |
767 |
|
|
ELL_3V_SET(covar + 3, pnc[1], pnc[4], pnc[5]); |
768 |
|
|
ELL_3V_SET(covar + 6, pnc[2], pnc[5], pnc[7]); |
769 |
|
|
out_d[outIdx] = ELL_3M_DET(covar); |
770 |
|
|
} |
771 |
|
|
break; |
772 |
|
|
case pullPropStability: |
773 |
|
|
out_d[outIdx] = point->stability; |
774 |
|
|
break; |
775 |
|
|
default: |
776 |
|
|
biffAddf(PULL, "%s: prop %d unrecognized", me, prop); |
777 |
|
|
return 1; |
778 |
|
|
break; |
779 |
|
|
} |
780 |
|
|
++outIdx; |
781 |
|
|
} /* for (pointIdx) */ |
782 |
|
|
} |
783 |
|
|
|
784 |
|
|
return 0; |
785 |
|
|
} |
786 |
|
|
|
787 |
|
|
/* |
788 |
|
|
** extract history as single array, possibly specific to only a single point0 |
789 |
|
|
*/ |
790 |
|
|
int |
791 |
|
|
pullPositionHistoryNrrdGet(Nrrd *nhist, pullContext *pctx, pullPoint *point0) { |
792 |
|
|
static const char me[]="pullPositionHistoryNrrdGet"; |
793 |
|
|
#if PULL_PHIST |
794 |
|
|
pullBin *bin; |
795 |
|
|
unsigned int binIdx, pointIdx, stepNum, stepIdx, phistIdx, phistNum, ii; |
796 |
|
|
double *hist; |
797 |
|
|
|
798 |
|
|
if (!(nhist && pctx)) { |
799 |
|
|
biffAddf(PULL, "%s: got NULL pointer", me); |
800 |
|
|
return 1; |
801 |
|
|
} |
802 |
|
|
|
803 |
|
|
if (!point0) { |
804 |
|
|
stepNum = 0; |
805 |
|
|
for (binIdx=0; binIdx<pctx->binNum; binIdx++) { |
806 |
|
|
bin = pctx->bin + binIdx; |
807 |
|
|
for (pointIdx=0; pointIdx<bin->pointNum; pointIdx++) { |
808 |
|
|
pullPoint *point; |
809 |
|
|
point = bin->point[pointIdx]; |
810 |
|
|
stepNum += point->phistArr->len; |
811 |
|
|
} |
812 |
|
|
} |
813 |
|
|
} else { |
814 |
|
|
stepNum = point0->phistArr->len; |
815 |
|
|
} |
816 |
|
|
if (nrrdMaybeAlloc_va(nhist, nrrdTypeDouble, 2, |
817 |
|
|
AIR_CAST(size_t, 1 + _PHN), |
818 |
|
|
AIR_CAST(size_t, stepNum))) { |
819 |
|
|
biffMovef(PULL, NRRD, "%s: couldn't allocate output", me); |
820 |
|
|
return 1; |
821 |
|
|
} |
822 |
|
|
hist = AIR_CAST(double *, nhist->data); |
823 |
|
|
stepIdx = 0; |
824 |
|
|
if (!point0) { |
825 |
|
|
for (binIdx=0; binIdx<pctx->binNum; binIdx++) { |
826 |
|
|
bin = pctx->bin + binIdx; |
827 |
|
|
for (pointIdx=0; pointIdx<bin->pointNum; pointIdx++) { |
828 |
|
|
pullPoint *point; |
829 |
|
|
point = bin->point[pointIdx]; |
830 |
|
|
phistNum = point->phistArr->len; |
831 |
|
|
for (phistIdx=0; phistIdx<phistNum; phistIdx++) { |
832 |
|
|
double *hh; |
833 |
|
|
hh = hist + stepIdx*(1 + _PHN); |
834 |
|
|
hh[0] = AIR_CAST(double, point->idtag); |
835 |
|
|
for (ii=0; ii<_PHN; ii++) { |
836 |
|
|
hh[ii+1] = (point->phist + _PHN*phistIdx)[ii]; |
837 |
|
|
} |
838 |
|
|
stepIdx++; |
839 |
|
|
} |
840 |
|
|
} |
841 |
|
|
} |
842 |
|
|
} else { |
843 |
|
|
for (stepIdx=0; stepIdx<stepNum; stepIdx++) { |
844 |
|
|
double *hh; |
845 |
|
|
hh = hist + stepIdx*(1 + _PHN); |
846 |
|
|
hh[0] = AIR_CAST(double, point0->idtag); |
847 |
|
|
for (ii=0; ii<_PHN; ii++) { |
848 |
|
|
hh[ii+1] = (point0->phist + _PHN*stepIdx)[ii]; |
849 |
|
|
} |
850 |
|
|
} |
851 |
|
|
} |
852 |
|
|
|
853 |
|
|
return 0; |
854 |
|
|
#else |
855 |
|
|
AIR_UNUSED(nhist); |
856 |
|
|
AIR_UNUSED(pctx); |
857 |
|
|
AIR_UNUSED(point0); |
858 |
|
|
biffAddf(PULL, "%s: sorry, not compiled with PULL_PHIST", me); |
859 |
|
|
return 1; |
860 |
|
|
#endif |
861 |
|
|
} |
862 |
|
|
|
863 |
|
|
int |
864 |
|
|
pullPositionHistoryPolydataGet(limnPolyData *pld, pullContext *pctx) { |
865 |
|
|
static const char me[]="pullPositionHistoryPolydataGet"; |
866 |
|
|
#if PULL_PHIST |
867 |
|
|
pullBin *bin; |
868 |
|
|
pullPoint *point; |
869 |
|
|
unsigned int binIdx, pointIdx, pointNum, vertNum, vertIdx, |
870 |
|
|
primIdx, phistIdx, phistNum; |
871 |
|
|
|
872 |
|
|
if (!(pld && pctx)) { |
873 |
|
|
biffAddf(PULL, "%s: got NULL pointer", me); |
874 |
|
|
return 1; |
875 |
|
|
} |
876 |
|
|
|
877 |
|
|
pointNum = 0; |
878 |
|
|
vertNum = 0; |
879 |
|
|
for (binIdx=0; binIdx<pctx->binNum; binIdx++) { |
880 |
|
|
bin = pctx->bin + binIdx; |
881 |
|
|
for (pointIdx=0; pointIdx<bin->pointNum; pointIdx++) { |
882 |
|
|
point = bin->point[pointIdx]; |
883 |
|
|
vertNum += point->phistArr->len; |
884 |
|
|
pointNum++; |
885 |
|
|
} |
886 |
|
|
} |
887 |
|
|
if (limnPolyDataAlloc(pld, 1 << limnPolyDataInfoRGBA, |
888 |
|
|
vertNum, vertNum, pointNum)) { |
889 |
|
|
biffMovef(PULL, LIMN, "%s: couldn't allocate output", me); |
890 |
|
|
return 1; |
891 |
|
|
} |
892 |
|
|
primIdx = 0; |
893 |
|
|
vertIdx = 0; |
894 |
|
|
for (binIdx=0; binIdx<pctx->binNum; binIdx++) { |
895 |
|
|
bin = pctx->bin + binIdx; |
896 |
|
|
for (pointIdx=0; pointIdx<bin->pointNum; pointIdx++) { |
897 |
|
|
point = bin->point[pointIdx]; |
898 |
|
|
phistNum = point->phistArr->len; |
899 |
|
|
for (phistIdx=0; phistIdx<phistNum; phistIdx++) { |
900 |
|
|
int cond; |
901 |
|
|
unsigned char rgb[3]; |
902 |
|
|
ELL_3V_SET(rgb, 0, 0, 0); |
903 |
|
|
ELL_3V_COPY(pld->xyzw + 4*vertIdx, point->phist + 5*phistIdx); |
904 |
|
|
(pld->xyzw + 4*vertIdx)[3] = 1; |
905 |
|
|
cond = AIR_CAST(int, (point->phist + 5*phistIdx)[4]); |
906 |
|
|
switch (cond) { |
907 |
|
|
case pullCondOld: |
908 |
|
|
ELL_3V_SET(rgb, 128, 128, 128); |
909 |
|
|
break; |
910 |
|
|
case pullCondConstraintSatA: |
911 |
|
|
ELL_3V_SET(rgb, 0, 255, 0); |
912 |
|
|
break; |
913 |
|
|
case pullCondConstraintSatB: |
914 |
|
|
ELL_3V_SET(rgb, 0, 0, 255); |
915 |
|
|
break; |
916 |
|
|
case pullCondEnergyTry: |
917 |
|
|
ELL_3V_SET(rgb, 255, 255, 255); |
918 |
|
|
break; |
919 |
|
|
case pullCondEnergyBad: |
920 |
|
|
ELL_3V_SET(rgb, 255, 0, 0); |
921 |
|
|
break; |
922 |
|
|
case pullCondConstraintFail: |
923 |
|
|
ELL_3V_SET(rgb, 255, 0, 255); |
924 |
|
|
break; |
925 |
|
|
case pullCondNew: |
926 |
|
|
ELL_3V_SET(rgb, 128, 255, 128); |
927 |
|
|
break; |
928 |
|
|
} |
929 |
|
|
ELL_4V_SET(pld->rgba + 4*vertIdx, rgb[0], rgb[1], rgb[2], 255); |
930 |
|
|
pld->indx[vertIdx] = vertIdx; |
931 |
|
|
vertIdx++; |
932 |
|
|
} |
933 |
|
|
pld->type[primIdx] = limnPrimitiveLineStrip; |
934 |
|
|
pld->icnt[primIdx] = phistNum; |
935 |
|
|
primIdx++; |
936 |
|
|
} |
937 |
|
|
} |
938 |
|
|
|
939 |
|
|
return 0; |
940 |
|
|
#else |
941 |
|
|
AIR_UNUSED(pld); |
942 |
|
|
AIR_UNUSED(pctx); |
943 |
|
|
biffAddf(PULL, "%s: sorry, not compiled with PULL_PHIST", me); |
944 |
|
|
return 1; |
945 |
|
|
#endif |
946 |
|
|
} |
947 |
|
|
|