GCC Code Coverage Report | |||||||||||||||||||||
|
|||||||||||||||||||||
Line | Branch | Exec | Source |
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 "gage.h" |
||
25 |
#include "privateGage.h" |
||
26 |
|||
27 |
void |
||
28 |
gageShapeReset(gageShape *shape) { |
||
29 |
|||
30 |
/* NOTE this guards against NULL */ |
||
31 |
✓✗ | 1536 |
if (shape) { |
32 |
/* input */ |
||
33 |
768 |
shape->defaultCenter = gageDefDefaultCenter; |
|
34 |
768 |
shape->orientationFromSpacing = gageDefOrientationFromSpacing; |
|
35 |
/* output; setting this in ways that can be used to test |
||
36 |
whether the shape has been set */ |
||
37 |
768 |
shape->center = nrrdCenterUnknown; |
|
38 |
768 |
shape->fromOrientation = AIR_FALSE; |
|
39 |
768 |
ELL_3V_SET(shape->size, 0, 0, 0); |
|
40 |
768 |
ELL_3V_SET(shape->spacing, AIR_NAN, AIR_NAN, AIR_NAN); |
|
41 |
768 |
ELL_4M_NAN_SET(shape->ItoW); |
|
42 |
768 |
ELL_4M_NAN_SET(shape->WtoI); |
|
43 |
768 |
ELL_3M_NAN_SET(shape->ItoWSubInvTransp); |
|
44 |
768 |
ELL_3M_NAN_SET(shape->ItoWSubInv); |
|
45 |
768 |
} |
|
46 |
768 |
return; |
|
47 |
} |
||
48 |
|||
49 |
static void * |
||
50 |
_mopShapeReset(void *_shape) { |
||
51 |
gageShape *shape; |
||
52 |
|||
53 |
shape = AIR_CAST(gageShape *, _shape); |
||
54 |
gageShapeReset(shape); |
||
55 |
return NULL; |
||
56 |
} |
||
57 |
|||
58 |
gageShape * |
||
59 |
gageShapeNew() { |
||
60 |
gageShape *shape; |
||
61 |
|||
62 |
842 |
shape = (gageShape *)calloc(1, sizeof(gageShape)); |
|
63 |
✓✗ | 421 |
if (shape) { |
64 |
421 |
gageShapeReset(shape); |
|
65 |
421 |
} |
|
66 |
421 |
return shape; |
|
67 |
} |
||
68 |
|||
69 |
gageShape * |
||
70 |
gageShapeCopy(const gageShape *shp) { |
||
71 |
gageShape *nhp; |
||
72 |
|||
73 |
✓✗ | 148 |
if ((nhp = gageShapeNew())) { |
74 |
/* no pointers, so this is easy */ |
||
75 |
74 |
memcpy(nhp, shp, sizeof(gageShape)); |
|
76 |
74 |
} |
|
77 |
74 |
return nhp; |
|
78 |
} |
||
79 |
|||
80 |
gageShape * |
||
81 |
gageShapeNix(gageShape *shape) { |
||
82 |
|||
83 |
822 |
airFree(shape); |
|
84 |
411 |
return NULL; |
|
85 |
} |
||
86 |
|||
87 |
static void |
||
88 |
shapeUnitItoW(const gageShape *shape, double world[3], |
||
89 |
const double indx[3], const double volHalfLen[3]) { |
||
90 |
unsigned int i; |
||
91 |
|||
92 |
if (nrrdCenterNode == shape->center) { |
||
93 |
for (i=0; i<=2; i++) { |
||
94 |
world[i] = NRRD_NODE_POS(-volHalfLen[i], volHalfLen[i], |
||
95 |
shape->size[i], indx[i]); |
||
96 |
} |
||
97 |
} else { |
||
98 |
for (i=0; i<=2; i++) { |
||
99 |
world[i] = NRRD_CELL_POS(-volHalfLen[i], volHalfLen[i], |
||
100 |
shape->size[i], indx[i]); |
||
101 |
} |
||
102 |
} |
||
103 |
} |
||
104 |
|||
105 |
/* |
||
106 |
** _gageShapeSet |
||
107 |
** |
||
108 |
** we are serving two masters here. If ctx is non-NULL, we are being called |
||
109 |
** from within gage, and we are to be lax or strict according to the settings |
||
110 |
** of ctx->parm.requireAllSpacings and ctx->parm.requireEqualCenters. If |
||
111 |
** ctx is NULL, gageShapeSet was called, in which case we go with lax |
||
112 |
** behavior (nothing "required") |
||
113 |
** |
||
114 |
** This function has subsumed the contents of the old gageVolumeCheck, |
||
115 |
** and hence has become this weird beast- part error checker and part |
||
116 |
** (gageShape) initializer. Oh well... |
||
117 |
*/ |
||
118 |
int |
||
119 |
_gageShapeSet(const gageContext *ctx, gageShape *shape, |
||
120 |
const Nrrd *nin, unsigned int baseDim) { |
||
121 |
static const char me[]="_gageShapeSet"; |
||
122 |
int ai, cx, cy, cz, statCalc[3], status, ofspc; |
||
123 |
unsigned int minsize; |
||
124 |
const NrrdAxisInfo *ax[3]; |
||
125 |
1388 |
double vecA[4], vecB[3], vecC[3], vecD[4], matA[9], |
|
126 |
spcCalc[3], vecCalc[3][NRRD_SPACE_DIM_MAX], orig[NRRD_SPACE_DIM_MAX]; |
||
127 |
airArray *mop; |
||
128 |
|||
129 |
/* |
||
130 |
fprintf(stderr, "!%s: ctx = %p (%s, %s)\n", me, ctx, |
||
131 |
(ctx |
||
132 |
? (ctx->shape->fromOrientation |
||
133 |
? "YES from orient" |
||
134 |
: "not from orient") |
||
135 |
: "???"), |
||
136 |
(ctx |
||
137 |
? (ctx->parm.orientationFromSpacing |
||
138 |
? "YES ofs" |
||
139 |
: "not ofs") |
||
140 |
: "???")); |
||
141 |
*/ |
||
142 |
/* ------ basic error checking */ |
||
143 |
694 |
mop = airMopNew(); |
|
144 |
694 |
airMopAdd(mop, shape, _mopShapeReset, airMopOnError); |
|
145 |
✗✓ | 694 |
if (!( shape && nin )) { |
146 |
biffAddf(GAGE, "%s: got NULL pointer", me); |
||
147 |
airMopError(mop); return 1; |
||
148 |
} |
||
149 |
✗✓ | 694 |
if (nrrdCheck(nin)) { |
150 |
biffMovef(GAGE, NRRD, "%s: basic nrrd validity check failed", me); |
||
151 |
airMopError(mop); return 1; |
||
152 |
} |
||
153 |
✗✓ | 694 |
if (nrrdTypeBlock == nin->type) { |
154 |
biffAddf(GAGE, "%s: need a non-block type nrrd", me); |
||
155 |
airMopError(mop); return 1; |
||
156 |
} |
||
157 |
✗✓ | 694 |
if (!(nin->dim == 3 + baseDim)) { |
158 |
biffAddf(GAGE, "%s: nrrd should be %u-D, not %u-D", |
||
159 |
me, 3 + baseDim, nin->dim); |
||
160 |
airMopError(mop); return 1; |
||
161 |
} |
||
162 |
694 |
ax[0] = &(nin->axis[baseDim+0]); |
|
163 |
694 |
ax[1] = &(nin->axis[baseDim+1]); |
|
164 |
694 |
ax[2] = &(nin->axis[baseDim+2]); |
|
165 |
|||
166 |
694 |
statCalc[0] = nrrdSpacingCalculate(nin, baseDim + 0, |
|
167 |
694 |
spcCalc + 0, vecCalc[0]); |
|
168 |
694 |
statCalc[1] = nrrdSpacingCalculate(nin, baseDim + 1, |
|
169 |
694 |
spcCalc + 1, vecCalc[1]); |
|
170 |
694 |
statCalc[2] = nrrdSpacingCalculate(nin, baseDim + 2, |
|
171 |
694 |
spcCalc + 2, vecCalc[2]); |
|
172 |
/* see if nrrdSpacingCalculate ever *failed* */ |
||
173 |
✗✓ | 1388 |
if (nrrdSpacingStatusUnknown == statCalc[0] |
174 |
✓✗ | 1388 |
|| nrrdSpacingStatusUnknown == statCalc[1] |
175 |
✓✗ | 1388 |
|| nrrdSpacingStatusUnknown == statCalc[2]) { |
176 |
biffAddf(GAGE, "%s: nrrdSpacingCalculate trouble on axis %d, %d, or %d", |
||
177 |
me, baseDim + 0, baseDim + 1, baseDim + 2); |
||
178 |
airMopError(mop); return 1; |
||
179 |
} |
||
180 |
✓✗✗✓ |
1388 |
if (!( statCalc[0] == statCalc[1] && statCalc[1] == statCalc[2] )) { |
181 |
biffAddf(GAGE, "%s: inconsistent spacing information on axes " |
||
182 |
"%u (%s), %u (%s), and %u (%s)", me, |
||
183 |
baseDim + 0, airEnumDesc(nrrdSpacingStatus, statCalc[0]), |
||
184 |
baseDim + 1, airEnumDesc(nrrdSpacingStatus, statCalc[1]), |
||
185 |
baseDim + 2, airEnumDesc(nrrdSpacingStatus, statCalc[2])); |
||
186 |
airMopError(mop); return 1; |
||
187 |
} |
||
188 |
/* this simplifies reasoning in the code that follows */ |
||
189 |
status = statCalc[0]; |
||
190 |
/* zero spacing would be problematic */ |
||
191 |
✗✓✗✗ ✗✗ |
694 |
if (0 == spcCalc[0] && 0 == spcCalc[1] && 0 == spcCalc[2]) { |
192 |
biffAddf(GAGE, "%s: spacings (%g,%g,%g) for axes %d,%d,%d not all " |
||
193 |
"non-zero", me, spcCalc[1], spcCalc[1], spcCalc[2], |
||
194 |
baseDim+0, baseDim+1, baseDim+2); |
||
195 |
airMopError(mop); return 1; |
||
196 |
} |
||
197 |
|||
198 |
/* error checking based on status */ |
||
199 |
✗✓ | 694 |
if (nrrdSpacingStatusScalarWithSpace == status) { |
200 |
biffAddf(GAGE, "%s: sorry, can't handle per-axis spacing that isn't part " |
||
201 |
"of a surrounding world space (%s)", |
||
202 |
me, airEnumStr(nrrdSpacingStatus, status)); |
||
203 |
airMopError(mop); return 1; |
||
204 |
} |
||
205 |
/* we no longer allow a nrrd to come in with no spacing info at all */ |
||
206 |
✗✓ | 694 |
if (nrrdSpacingStatusNone == status) { |
207 |
biffAddf(GAGE, "%s: sorry, need some spacing info for spatial axes " |
||
208 |
"%u, %u, %u", me, |
||
209 |
baseDim+0, baseDim+1, baseDim+2); |
||
210 |
airMopError(mop); return 1; |
||
211 |
} |
||
212 |
/* actually, there shouldn't be any other options for spacing status |
||
213 |
besides these too; this is just being careful */ |
||
214 |
694 |
if (!( nrrdSpacingStatusDirection == status |
|
215 |
✗✓ | 694 |
|| nrrdSpacingStatusScalarNoSpace == status )) { |
216 |
biffAddf(GAGE, "%s: sorry, can only handle spacing status %d (%s) " |
||
217 |
"or %d (%s), not %d (%s)", me, |
||
218 |
nrrdSpacingStatusDirection, |
||
219 |
airEnumStr(nrrdSpacingStatus, nrrdSpacingStatusDirection), |
||
220 |
nrrdSpacingStatusScalarNoSpace, |
||
221 |
airEnumStr(nrrdSpacingStatus, nrrdSpacingStatusScalarNoSpace), |
||
222 |
status, airEnumStr(nrrdSpacingStatus, status)); |
||
223 |
airMopError(mop); return 1; |
||
224 |
} |
||
225 |
|||
226 |
✓✗ | 694 |
if (nrrdSpacingStatusDirection == status) { |
227 |
1388 |
shape->fromOrientation = AIR_TRUE; |
|
228 |
✗✓ | 694 |
if (3 != nin->spaceDim) { |
229 |
biffAddf(GAGE, "%s: orientation space dimension %d != 3", |
||
230 |
me, nin->spaceDim); |
||
231 |
airMopError(mop); return 1; |
||
232 |
} |
||
233 |
} else { |
||
234 |
shape->fromOrientation = AIR_FALSE; |
||
235 |
} |
||
236 |
|||
237 |
/* ------ find centering (set shape->center) */ |
||
238 |
/* NOTE: when the volume is being crammed in a bi-unit cube, the centering |
||
239 |
will actually affect the positions of the samples. Otherwise, |
||
240 |
(having full orientation, or using orientationFromSpacing), the |
||
241 |
centering will only affect the probe-able bounds of the volume, but |
||
242 |
the sample positions in space don't depend on centering */ |
||
243 |
694 |
cx = ax[0]->center; |
|
244 |
694 |
cy = ax[1]->center; |
|
245 |
694 |
cz = ax[2]->center; |
|
246 |
✓✗✗✓ |
1388 |
if (!( cx == cy && cy == cz )) { |
247 |
biffAddf(GAGE, |
||
248 |
"%s: axes %d,%d,%d centerings (%s,%s,%s) not all equal", |
||
249 |
me, baseDim+0, baseDim+1, baseDim+2, |
||
250 |
airEnumStr(nrrdCenter, cx), |
||
251 |
airEnumStr(nrrdCenter, cy), |
||
252 |
airEnumStr(nrrdCenter, cz)); |
||
253 |
airMopError(mop); return 1; |
||
254 |
} |
||
255 |
/* Hopefully, ctx->parm.defaultCenter == shape->defaultCenter; and this |
||
256 |
worry will be moot if ctx->parm.defaultCenter goes away */ |
||
257 |
✓✓ | 1882 |
shape->center = (nrrdCenterUnknown != cx |
258 |
? cx /* cx == cy == cz, by above */ |
||
259 |
✓✓ | 400 |
: (ctx |
260 |
100 |
? ctx->parm.defaultCenter |
|
261 |
100 |
: shape->defaultCenter)); |
|
262 |
|||
263 |
/* ------ find sizes (set shape->size[0,1,2]) */ |
||
264 |
694 |
shape->size[0] = ax[0]->size; |
|
265 |
694 |
shape->size[1] = ax[1]->size; |
|
266 |
694 |
shape->size[2] = ax[2]->size; |
|
267 |
694 |
minsize = (nrrdCenterCell == shape->center ? 1 : 2); |
|
268 |
/* this can't be relaxed in the face of having full orientation info, |
||
269 |
because even then, you can't have a non-zero probe-able volume if |
||
270 |
there's only one sample along a node-centered axis */ |
||
271 |
✗✓ | 1388 |
if (!(shape->size[0] >= minsize |
272 |
✓✗ | 1388 |
&& shape->size[1] >= minsize |
273 |
✓✗ | 1388 |
&& shape->size[2] >= minsize )) { |
274 |
biffAddf(GAGE, "%s: sizes (%u,%u,%u) must all be >= %u " |
||
275 |
"(min number of %s-centered samples)", me, |
||
276 |
shape->size[0], shape->size[1], shape->size[2], |
||
277 |
minsize, airEnumStr(nrrdCenter, shape->center)); |
||
278 |
airMopError(mop); return 1; |
||
279 |
} |
||
280 |
|||
281 |
/* ------ find spacings[0,1,2] and ItoW matrix */ |
||
282 |
/* Hopefully, ctx->parm.orientationFromSpacing and |
||
283 |
shape->orientationFromSpacing don't represent competing interests; |
||
284 |
this worry will be moot if ctx->parm.orientationFromSpacing goes away */ |
||
285 |
✓✓ | 1041 |
ofspc = ((ctx && ctx->parm.orientationFromSpacing) |
286 |
✓✗ | 1735 |
|| shape->orientationFromSpacing); |
287 |
✓✗ | 694 |
if (shape->fromOrientation || ofspc) { |
288 |
✗✓ | 694 |
if (ofspc) { |
289 |
/* need abs() in case an axis had negative spacing */ |
||
290 |
694 |
ELL_3V_ABS(shape->spacing, spcCalc); |
|
291 |
ELL_3V_SET(vecCalc[0], airSgn(spcCalc[0]), 0.0, 0.0); |
||
292 |
ELL_3V_SET(vecCalc[1], 0.0, airSgn(spcCalc[1]), 0.0); |
||
293 |
ELL_3V_SET(vecCalc[2], 0.0, 0.0, airSgn(spcCalc[2])); |
||
294 |
} else { |
||
295 |
694 |
ELL_3V_COPY(shape->spacing, spcCalc); |
|
296 |
/* vecCalc set by nrrdSpacingCalculate */ |
||
297 |
} |
||
298 |
✓✗ | 694 |
if (shape->fromOrientation) { |
299 |
/* if the spaceOrigin isn't set, this will be all NaNs */ |
||
300 |
694 |
nrrdSpaceOriginGet(nin, orig); |
|
301 |
694 |
} else { |
|
302 |
/* sorry, if you want to specify an image origin that over-rides the |
||
303 |
behavior of centering the volume at (0,0,0), then it has to be |
||
304 |
done through the full orientation info. That is, we don't want |
||
305 |
to use nrrdOriginCalculate() because otherwise the logic gets |
||
306 |
too complicated */ |
||
307 |
ELL_3V_SET(orig, AIR_NAN, AIR_NAN, AIR_NAN); |
||
308 |
} |
||
309 |
✓✗✓✗ ✗✓ |
2082 |
if (!ELL_3V_EXISTS(orig)) { |
310 |
/* don't have origin, for whatever reason; center volume on (0,0,0) */ |
||
311 |
ELL_3V_SET(orig, 0.0, 0.0, 0.0); |
||
312 |
ELL_3V_SCALE_INCR(orig, -(shape->size[0] - 1.0)*shape->spacing[0]/2.0, |
||
313 |
vecCalc[0]); |
||
314 |
ELL_3V_SCALE_INCR(orig, -(shape->size[1] - 1.0)*shape->spacing[1]/2.0, |
||
315 |
vecCalc[1]); |
||
316 |
ELL_3V_SCALE_INCR(orig, -(shape->size[2] - 1.0)*shape->spacing[2]/2.0, |
||
317 |
vecCalc[2]); |
||
318 |
} |
||
319 |
vecD[3] = 0; |
||
320 |
694 |
ELL_3V_SCALE(vecD, spcCalc[0], vecCalc[0]); |
|
321 |
694 |
ELL_4MV_COL0_SET(shape->ItoW, vecD); |
|
322 |
694 |
ELL_3V_SCALE(vecD, spcCalc[1], vecCalc[1]); |
|
323 |
694 |
ELL_4MV_COL1_SET(shape->ItoW, vecD); |
|
324 |
694 |
ELL_3V_SCALE(vecD, spcCalc[2], vecCalc[2]); |
|
325 |
694 |
ELL_4MV_COL2_SET(shape->ItoW, vecD); |
|
326 |
vecD[3] = 1; |
||
327 |
694 |
ELL_3V_COPY(vecD, orig); |
|
328 |
694 |
ELL_4MV_COL3_SET(shape->ItoW, vecD); |
|
329 |
/* |
||
330 |
fprintf(stderr, "%s: %g (%g,%g,%g)\n", me, |
||
331 |
spcCalc[0], vecCalc[0][0], vecCalc[0][1], vecCalc[0][2]); |
||
332 |
fprintf(stderr, "%s: %g (%g,%g,%g)\n", me, |
||
333 |
spcCalc[1], vecCalc[1][0], vecCalc[1][1], vecCalc[1][2]); |
||
334 |
fprintf(stderr, "%s: %g (%g,%g,%g)\n", me, |
||
335 |
spcCalc[2], vecCalc[2][0], vecCalc[2][1], vecCalc[2][2]); |
||
336 |
*/ |
||
337 |
/* |
||
338 |
fprintf(stderr, "%s: ItoW = %g %g %g %g\n", me, |
||
339 |
shape->ItoW[ 0], shape->ItoW[ 1], shape->ItoW[ 2], shape->ItoW[ 3]); |
||
340 |
fprintf(stderr, "%s: %g %g %g %g\n", me, |
||
341 |
shape->ItoW[ 4], shape->ItoW[ 5], shape->ItoW[ 6], shape->ItoW[ 7]); |
||
342 |
fprintf(stderr, "%s: %g %g %g %g\n", me, |
||
343 |
shape->ItoW[ 8], shape->ItoW[ 9], shape->ItoW[10], shape->ItoW[11]); |
||
344 |
fprintf(stderr, "%s: %g %g %g %g\n", me, |
||
345 |
shape->ItoW[12], shape->ItoW[13], shape->ItoW[14], shape->ItoW[15]); |
||
346 |
*/ |
||
347 |
694 |
} else { /* not (shape->fromOrientation || ofspc) */ |
|
348 |
double maxLen, volHalfLen[3]; |
||
349 |
size_t num[3]; |
||
350 |
/* ------ learn lengths for bounding nrrd in bi-unit cube */ |
||
351 |
ELL_3V_ABS(shape->spacing, spcCalc); |
||
352 |
maxLen = 0.0; |
||
353 |
for (ai=0; ai<=2; ai++) { |
||
354 |
num[ai] = (nrrdCenterNode == shape->center |
||
355 |
? shape->size[ai]-1 |
||
356 |
: shape->size[ai]); |
||
357 |
volHalfLen[ai] = num[ai]*shape->spacing[ai]; |
||
358 |
maxLen = AIR_MAX(maxLen, volHalfLen[ai]); |
||
359 |
} |
||
360 |
/* Thu Dec 13 02:45:01 EST 2007 |
||
361 |
fixed long-standing bug in handling vols without full orientation info: |
||
362 |
spacing[ai] was never scaled to account for being crammed into |
||
363 |
the bi-unit cube!! */ |
||
364 |
for (ai=0; ai<=2; ai++) { |
||
365 |
volHalfLen[ai] /= maxLen; |
||
366 |
shape->spacing[ai] = 2*volHalfLen[ai]/num[ai]; |
||
367 |
} |
||
368 |
ELL_3V_SET(vecC, 0, 0, 0); |
||
369 |
shapeUnitItoW(shape, vecA, vecC, volHalfLen); |
||
370 |
ELL_3V_SET(vecC, 1, 0, 0); |
||
371 |
shapeUnitItoW(shape, vecB, vecC, volHalfLen); |
||
372 |
ELL_3V_SUB(vecD, vecB, vecA); |
||
373 |
vecD[3] = 0; |
||
374 |
ELL_4MV_COL0_SET(shape->ItoW, vecD); |
||
375 |
|||
376 |
ELL_3V_SET(vecC, 0, 1, 0); |
||
377 |
shapeUnitItoW(shape, vecB, vecC, volHalfLen); |
||
378 |
ELL_3V_SUB(vecD, vecB, vecA); |
||
379 |
vecD[3] = 0; |
||
380 |
ELL_4MV_COL1_SET(shape->ItoW, vecD); |
||
381 |
|||
382 |
ELL_3V_SET(vecC, 0, 0, 1); |
||
383 |
shapeUnitItoW(shape, vecB, vecC, volHalfLen); |
||
384 |
ELL_3V_SUB(vecD, vecB, vecA); |
||
385 |
vecD[3] = 0; |
||
386 |
ELL_4MV_COL2_SET(shape->ItoW, vecD); |
||
387 |
|||
388 |
vecA[3] = 1; |
||
389 |
ELL_4MV_COL3_SET(shape->ItoW, vecA); |
||
390 |
} |
||
391 |
|||
392 |
/* ------ set the rest of the matrices */ |
||
393 |
694 |
ell_4m_inv_d(shape->WtoI, shape->ItoW); |
|
394 |
694 |
ELL_34M_EXTRACT(matA, shape->ItoW); |
|
395 |
694 |
ell_3m_inv_d(shape->ItoWSubInv, matA); |
|
396 |
694 |
ELL_3M_TRANSPOSE(shape->ItoWSubInvTransp, shape->ItoWSubInv); |
|
397 |
|||
398 |
694 |
airMopOkay(mop); |
|
399 |
694 |
return 0; |
|
400 |
694 |
} |
|
401 |
|||
402 |
int |
||
403 |
gageShapeSet(gageShape *shape, const Nrrd *nin, int baseDim) { |
||
404 |
static const char me[]="gageShapeSet"; |
||
405 |
|||
406 |
if (_gageShapeSet(NULL, shape, nin, baseDim)) { |
||
407 |
biffAddf(GAGE, "%s: trouble", me); |
||
408 |
return 1; |
||
409 |
} |
||
410 |
return 0; |
||
411 |
} |
||
412 |
|||
413 |
/* |
||
414 |
** this wasn't being used at all |
||
415 |
void |
||
416 |
gageShapeUnitWtoI(gageShape *shape, double indx[3], double world[3]) { |
||
417 |
int i; |
||
418 |
|||
419 |
if (nrrdCenterNode == shape->center) { |
||
420 |
for (i=0; i<=2; i++) { |
||
421 |
indx[i] = NRRD_NODE_IDX(-shape->volHalfLen[i], shape->volHalfLen[i], |
||
422 |
shape->size[i], world[i]); |
||
423 |
} |
||
424 |
} else { |
||
425 |
for (i=0; i<=2; i++) { |
||
426 |
indx[i] = NRRD_CELL_IDX(-shape->volHalfLen[i], shape->volHalfLen[i], |
||
427 |
shape->size[i], world[i]); |
||
428 |
} |
||
429 |
} |
||
430 |
} |
||
431 |
*/ |
||
432 |
|||
433 |
void |
||
434 |
gageShapeWtoI(const gageShape *shape, |
||
435 |
double _indx[3], const double _world[3]) { |
||
436 |
/* static const char me[]="gageShapeWtoI"; */ |
||
437 |
double indx[4], world[4]; |
||
438 |
|||
439 |
/* |
||
440 |
fprintf(stderr, "!%s: hello %p %p %p; %p\n", me, |
||
441 |
shape, _indx, _world, shape->WtoI); |
||
442 |
*/ |
||
443 |
ELL_3V_COPY(world, _world); |
||
444 |
world[3] = 1.0; |
||
445 |
ELL_4MV_MUL(indx, shape->WtoI, world); |
||
446 |
ELL_3V_SCALE(_indx, 1.0/indx[3], indx); |
||
447 |
} |
||
448 |
|||
449 |
void |
||
450 |
gageShapeItoW(const gageShape *shape, |
||
451 |
double _world[3], const double _indx[3]) { |
||
452 |
double world[4], indx[4]; |
||
453 |
|||
454 |
ELL_3V_COPY(indx, _indx); |
||
455 |
indx[3] = 1.0; |
||
456 |
ELL_4MV_MUL(world, shape->ItoW, indx); |
||
457 |
ELL_3V_SCALE(_world, 1.0/world[3], world); |
||
458 |
} |
||
459 |
|||
460 |
/* |
||
461 |
******** gageShapeEqual |
||
462 |
** |
||
463 |
** shapes not being equal is a biffable error, |
||
464 |
** returning 0 signifies this "error" |
||
465 |
** returning 1 means no error, they ARE equal |
||
466 |
*/ |
||
467 |
int |
||
468 |
gageShapeEqual(const gageShape *shape1, const char *_name1, |
||
469 |
const gageShape *shape2, const char *_name2) { |
||
470 |
static const char me[]="gageShapeEqual"; |
||
471 |
const char *name1, *name2, what[] = "???"; |
||
472 |
|||
473 |
✗✓ | 468 |
if (!( shape1 && shape2 )) { |
474 |
biffAddf(GAGE, "%s: can't judge equality w/ NULL pointer", me); |
||
475 |
return 0; |
||
476 |
} |
||
477 |
234 |
name1 = _name1 ? _name1 : what; |
|
478 |
234 |
name2 = _name2 ? _name2 : what; |
|
479 |
✗✓ | 234 |
if (!( shape1->fromOrientation == shape2->fromOrientation )) { |
480 |
biffAddf(GAGE, |
||
481 |
"%s: fromOrientation of %s (%s) != %s's (%s)", me, |
||
482 |
name1, shape1->fromOrientation ? "true" : "false", |
||
483 |
name2, shape2->fromOrientation ? "true" : "false"); |
||
484 |
return 0; |
||
485 |
} |
||
486 |
✓✗✗✓ |
468 |
if (!( shape1->size[0] == shape2->size[0] && |
487 |
✓✗ | 234 |
shape1->size[1] == shape2->size[1] && |
488 |
234 |
shape1->size[2] == shape2->size[2] )) { |
|
489 |
biffAddf(GAGE, |
||
490 |
"%s: dimensions of %s (%u,%u,%u) != %s's (%u,%u,%u)", |
||
491 |
me, name1, |
||
492 |
shape1->size[0], shape1->size[1], shape1->size[2], |
||
493 |
name2, |
||
494 |
shape2->size[0], shape2->size[1], shape2->size[2]); |
||
495 |
return 0; |
||
496 |
} |
||
497 |
✓✗ | 234 |
if (shape1->fromOrientation) { |
498 |
✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✗✓ |
3744 |
if (!( ELL_4M_EQUAL(shape1->ItoW, shape2->ItoW) )) { |
499 |
biffAddf(GAGE, "%s: ItoW matrices of %s and %s not the same", me, |
||
500 |
name1, name2); |
||
501 |
return 0; |
||
502 |
} |
||
503 |
} else { |
||
504 |
if (!( shape1->spacing[0] == shape2->spacing[0] && |
||
505 |
shape1->spacing[1] == shape2->spacing[1] && |
||
506 |
shape1->spacing[2] == shape2->spacing[2] )) { |
||
507 |
biffAddf(GAGE, "%s: spacings of %s (%g,%g,%g) != %s's (%g,%g,%g)", |
||
508 |
me, name1, |
||
509 |
shape1->spacing[0], shape1->spacing[1], shape1->spacing[2], |
||
510 |
name2, |
||
511 |
shape2->spacing[0], shape2->spacing[1], shape2->spacing[2]); |
||
512 |
return 0; |
||
513 |
} |
||
514 |
if (!( shape1->center == shape2->center )) { |
||
515 |
biffAddf(GAGE, |
||
516 |
"%s: centering of %s (%s) != %s's (%s)", me, |
||
517 |
name1, airEnumStr(nrrdCenter, shape1->center), |
||
518 |
name2, airEnumStr(nrrdCenter, shape2->center)); |
||
519 |
return 0; |
||
520 |
} |
||
521 |
} |
||
522 |
|||
523 |
234 |
return 1; |
|
524 |
234 |
} |
|
525 |
|||
526 |
void |
||
527 |
gageShapeBoundingBox(double min[3], double max[3], |
||
528 |
const gageShape *shape) { |
||
529 |
/* static const char me[]="gageShapeBoundingBox"; */ |
||
530 |
double minIdx[3], maxIdx[3], cornerIdx[8][3], tmp[3]; |
||
531 |
unsigned int ii; |
||
532 |
|||
533 |
if (!( min && max && shape )) { |
||
534 |
return; |
||
535 |
} |
||
536 |
if (nrrdCenterNode == shape->center) { |
||
537 |
ELL_3V_SET(minIdx, 0, 0, 0); |
||
538 |
ELL_3V_SET(maxIdx, |
||
539 |
shape->size[0]-1, |
||
540 |
shape->size[1]-1, |
||
541 |
shape->size[2]-1); |
||
542 |
} else { |
||
543 |
ELL_3V_SET(minIdx, -0.5, -0.5, -0.5); |
||
544 |
ELL_3V_SET(maxIdx, |
||
545 |
shape->size[0]-0.5, |
||
546 |
shape->size[1]-0.5, |
||
547 |
shape->size[2]-0.5); |
||
548 |
} |
||
549 |
ELL_3V_SET(cornerIdx[0], minIdx[0], minIdx[1], minIdx[2]); |
||
550 |
ELL_3V_SET(cornerIdx[1], maxIdx[0], minIdx[1], minIdx[2]); |
||
551 |
ELL_3V_SET(cornerIdx[2], minIdx[0], maxIdx[1], minIdx[2]); |
||
552 |
ELL_3V_SET(cornerIdx[3], maxIdx[0], maxIdx[1], minIdx[2]); |
||
553 |
ELL_3V_SET(cornerIdx[4], minIdx[0], minIdx[1], maxIdx[2]); |
||
554 |
ELL_3V_SET(cornerIdx[5], maxIdx[0], minIdx[1], maxIdx[2]); |
||
555 |
ELL_3V_SET(cornerIdx[6], minIdx[0], maxIdx[1], maxIdx[2]); |
||
556 |
ELL_3V_SET(cornerIdx[7], maxIdx[0], maxIdx[1], maxIdx[2]); |
||
557 |
gageShapeItoW(shape, tmp, cornerIdx[0]); |
||
558 |
ELL_3V_COPY(min, tmp); |
||
559 |
ELL_3V_COPY(max, tmp); |
||
560 |
for (ii=1; ii<8; ii++) { |
||
561 |
gageShapeItoW(shape, tmp, cornerIdx[ii]); |
||
562 |
ELL_3V_MIN(min, min, tmp); |
||
563 |
ELL_3V_MAX(max, max, tmp); |
||
564 |
} |
||
565 |
return; |
||
566 |
} |
Generated by: GCOVR (Version 3.3) |