00001
#include <volume_io/internal_volume_io.h>
00002
#include <bicpl/deform.h>
00003
#include <bicpl/numerical.h>
00004
00005 #define MAX_DERIVS 2
00006
00007
private void get_voxel_coefs(
00008
int degrees_continuity,
00009 Real voxel[],
00010 Real coefs[MAX_DERIVS+2][MAX_DERIVS+2][MAX_DERIVS+2] );
00011
private void make_coefs_uv(
00012
int degrees_continuity,
00013 Real voxels[MAX_DERIVS+2],
00014 Real interpolation_coefs[MAX_DERIVS+2][MAX_DERIVS+2],
00015 Real coefs[MAX_DERIVS+2] );
00016
private void make_coefs_u(
00017
int degrees_continuity,
00018 Real coefs_uv[MAX_DERIVS+2][MAX_DERIVS+2],
00019 Real interpolation_coefs[MAX_DERIVS+2][MAX_DERIVS+2],
00020 Real coefs_u[MAX_DERIVS+2][MAX_DERIVS+2] );
00021
private void find_coefs_of_line(
00022
int degrees_continuity,
00023 Real coefs[MAX_DERIVS+2][MAX_DERIVS+2][MAX_DERIVS+2],
00024 Real ou,
00025 Real ov,
00026 Real ow,
00027 Real du,
00028 Real dv,
00029 Real dw,
00030 Real line_coefs[(MAX_DERIVS+1) * N_DIMENSIONS+1] );
00031
00032 private void get_voxel_line_tricubic(
00033 Real coefs[],
00034
int x,
00035
int y,
00036
int z,
00037 Real line_origin[],
00038 Real line_direction[],
00039 Real line_poly[] )
00040 {
00041 Real du, dv, dw, ou, ov, ow, delta0, delta1, delta0t, delta1t, delta0tt;
00042 Real d00, d01, d10, d11;
00043 Real c00a, c01a, c10a, c11a;
00044 Real c00t, c01t, c10t, c11t;
00045 Real c0a, c1a, c0t, c1t, c0tt, c1tt;
00046
00047 d00 = coefs[1] - coefs[0];
00048 d01 = coefs[3] - coefs[2];
00049 d10 = coefs[5] - coefs[4];
00050 d11 = coefs[7] - coefs[6];
00051
00052 du = line_direction[X];
00053 dv = line_direction[Y];
00054 dw = line_direction[Z];
00055 ou = line_origin[X] - (Real) x;
00056 ov = line_origin[Y] - (Real)
y;
00057 ow = line_origin[Z] - (Real) z;
00058
00059 c00a = coefs[0] + ow * d00;
00060 c01a = coefs[2] + ow * d01;
00061 c10a = coefs[4] + ow * d10;
00062 c11a = coefs[6] + ow * d11;
00063 c00t = dw * d00;
00064 c01t = dw * d01;
00065 c10t = dw * d10;
00066 c11t = dw * d11;
00067
00068 delta0 = c01a - c00a;
00069 delta1 = c11a - c10a;
00070 delta0t = c01t - c00t;
00071 delta1t = c11t - c10t;
00072
00073 c0a = c00a + ov * delta0;
00074 c0t = c00t + ov * delta0t + dv * delta0;
00075 c0tt = dv * delta0t;
00076 c1a = c10a + ov * delta1;
00077 c1t = c10t + ov * delta1t + dv * delta1;
00078 c1tt = dv * delta1t;
00079
00080 delta0 = c1a - c0a;
00081 delta0t = c1t - c0t;
00082 delta0tt = c1tt - c0tt;
00083
00084 line_poly[0] = c0a + ou * delta0;
00085 line_poly[1] = c0t + ou * delta0t + du * delta0;
00086 line_poly[2] = c0tt + ou * delta0tt + du * delta0t;
00087 line_poly[3] = du * delta0tt;
00088 }
00089
00090 public int find_voxel_line_polynomial(
00091 Real coefs[],
00092
int degrees_continuity,
00093
int x,
00094
int y,
00095
int z,
00096 Real line_origin[],
00097 Real line_direction[],
00098 Real line_poly[] )
00099 {
00100 Real du, dv, dw, ou, ov, ow, voxel_offset;
00101 Real voxel_coefs[
MAX_DERIVS+2][
MAX_DERIVS+2][
MAX_DERIVS+2];
00102
00103
if( degrees_continuity == 0 )
00104 {
00105
get_voxel_line_tricubic( coefs, x,
y, z, line_origin,
00106 line_direction, line_poly );
00107
00108
return( 4 );
00109 }
00110
00111
get_voxel_coefs( degrees_continuity, coefs, voxel_coefs );
00112
00113
if( degrees_continuity % 2 == 1 )
00114 voxel_offset = -0.5;
00115
else
00116 voxel_offset = 0.0;
00117
00118 du = line_direction[X];
00119 dv = line_direction[Y];
00120 dw = line_direction[Z];
00121 ou = line_origin[X] - ((Real) x + voxel_offset);
00122 ov = line_origin[Y] - ((Real)
y + voxel_offset);
00123 ow = line_origin[Z] - ((Real) z + voxel_offset);
00124
00125
find_coefs_of_line( degrees_continuity, voxel_coefs, ou, ov, ow, du, dv, dw,
00126 line_poly );
00127
00128
return( (degrees_continuity + 1) * 3 + 1 );
00129 }
00130
00131 #define N_STEPS 8
00132
00133 private int get_cubic_root(
00134 Real coefs[],
00135 Real u_min,
00136 Real u_max,
00137 Real *solution )
00138 {
00139
#ifndef OLD
00140
int n;
00141 Real sol[3];
00142 n =
get_roots_of_polynomial( 4, coefs, u_min, u_max, 0.0, sol );
00143
if( n > 0 )
00144 {
00145 n = 1;
00146 *solution = sol[0];
00147 }
00148
return( n );
00149
#else
00150
int i;
00151 Real value, prev_value, h, hh, u, alpha;
00152 Real h1, h2, h3;
00153
00154 u = u_min;
00155 h = (u_max - u_min) / (Real)
N_STEPS;
00156 value =
evaluate_polynomial( 4, coefs, u );
00157
00158 hh = h * h;
00159 h1 = h*(coefs[3]*(3.0*u*(h+u) + hh) + coefs[2]*(2.0*u+h) + coefs[1]);
00160 h2 = 2.0 * hh * (3.0*coefs[3]*(u+h) + coefs[2]);
00161 h3 = 6.0*coefs[3]*h*hh;
00162
00163 for_less( i, 0,
N_STEPS )
00164 {
00165 prev_value = value;
00166 value += h1;
00167 h1 += h2;
00168 h2 += h3;
00169
00170
if( prev_value * value <= 0.0 )
00171 {
00172
if( prev_value == 0.0 && value == 0.0 )
00173 alpha = ((Real) i + 0.5) / (Real)
N_STEPS;
00174
else
00175 {
00176 alpha = ((Real) i + prev_value / (prev_value - value)) /
00177 (Real)
N_STEPS;
00178 }
00179
00180 *solution = (1.0 - alpha) * u_min + alpha * u_max;
00181
return( 1 );
00182 }
00183 }
00184
00185
return( 0 );
00186
#endif
00187
}
00188
00189 public int find_voxel_line_value_intersection(
00190 Real coefs[],
00191
int degrees_continuity,
00192
int x,
00193
int y,
00194
int z,
00195 Real line_origin[],
00196 Real line_direction[],
00197 Real t_min,
00198 Real t_max,
00199 Real isovalue,
00200 Real distances[3] )
00201 {
00202 Real line_coefs[(
MAX_DERIVS+1) * N_DIMENSIONS+1];
00203
int degrees, n_intersections;
00204
00205 degrees =
find_voxel_line_polynomial( coefs, degrees_continuity,
00206 x,
y, z, line_origin, line_direction,
00207 line_coefs );
00208
00209 n_intersections = 0;
00210
00211
if( degrees > 0 )
00212 {
00213 line_coefs[0] -= isovalue;
00214
if( degrees == 4 )
00215 {
00216 n_intersections =
get_cubic_root( line_coefs,
00217 t_min, t_max, &distances[0] );
00218 }
00219
else
00220 {
00221 n_intersections =
get_roots_of_polynomial( degrees,
00222 line_coefs, t_min, t_max, .01, distances );
00223 }
00224 }
00225
00226
return( n_intersections );
00227 }
00228
00229 private void get_voxel_coefs(
00230
int degrees_continuity,
00231 Real voxel[],
00232 Real coefs[MAX_DERIVS+2][MAX_DERIVS+2][MAX_DERIVS+2] )
00233 {
00234
int u, v, du, dv, dw, i, j, ind;
00235 Real val, **bases;
00236 Real interpolation_coefs[
MAX_DERIVS+2][
MAX_DERIVS+2];
00237 Real coefs_uv[
MAX_DERIVS+2][
MAX_DERIVS+2][
MAX_DERIVS+2];
00238 Real coefs_u[
MAX_DERIVS+2][
MAX_DERIVS+2][
MAX_DERIVS+2];
00239
00240 ALLOC2D( bases, 4, 4 );
00241
00242
switch( degrees_continuity )
00243 {
00244
case 0:
00245 get_linear_spline_coefs( bases );
00246
break;
00247
00248
case 1:
00249 get_quadratic_spline_coefs( bases );
00250
break;
00251
00252
case 2:
00253 get_cubic_spline_coefs( bases );
00254
break;
00255 }
00256
00257 for_less( i, 0, degrees_continuity + 2 )
00258 {
00259 for_less( j, 0, degrees_continuity + 2 )
00260 interpolation_coefs[i][j] = bases[i][j];
00261 }
00262
00263 FREE2D( bases );
00264
00265 ind = 0;
00266 for_less( u, 0, degrees_continuity + 2 )
00267 {
00268 for_less( v, 0, degrees_continuity + 2 )
00269 {
00270
make_coefs_uv( degrees_continuity, &voxel[ind],
00271 interpolation_coefs, coefs_uv[u][v] );
00272 ind += degrees_continuity + 2;
00273 }
00274 }
00275
00276 for_less( u, 0, degrees_continuity + 2 )
00277 {
00278
make_coefs_u( degrees_continuity, coefs_uv[u],
00279 interpolation_coefs, coefs_u[u] );
00280 }
00281
00282 for_less( du, 0, degrees_continuity + 2 )
00283 {
00284 for_less( dv, 0, degrees_continuity + 2 )
00285 {
00286 for_less( dw, 0, degrees_continuity + 2 )
00287 {
00288 val = 0.0;
00289
00290 for_less( u, 0, degrees_continuity + 2 )
00291 val += coefs_u[u][dv][dw] * interpolation_coefs[du][u];
00292
00293 coefs[du][dv][dw] = val;
00294 }
00295 }
00296 }
00297 }
00298
00299 private void make_coefs_uv(
00300
int degrees_continuity,
00301 Real voxels[MAX_DERIVS+2],
00302 Real interpolation_coefs[MAX_DERIVS+2][MAX_DERIVS+2],
00303 Real coefs[MAX_DERIVS+2] )
00304 {
00305 Real val;
00306
int dw, w;
00307
00308 for_less( dw, 0, degrees_continuity + 2 )
00309 {
00310 val = 0.0;
00311 for_less( w, 0, degrees_continuity + 2 )
00312 val += voxels[w] * interpolation_coefs[dw][w];
00313 coefs[dw] = val;
00314 }
00315 }
00316
00317 private void make_coefs_u(
00318
int degrees_continuity,
00319 Real coefs_uv[MAX_DERIVS+2][MAX_DERIVS+2],
00320 Real interpolation_coefs[MAX_DERIVS+2][MAX_DERIVS+2],
00321 Real coefs_u[MAX_DERIVS+2][MAX_DERIVS+2] )
00322 {
00323 Real val;
00324
int v, dv, dw;
00325
00326 for_less( dv, 0, degrees_continuity + 2 )
00327 {
00328 for_less( dw, 0, degrees_continuity + 2 )
00329 {
00330 val = 0.0;
00331 for_less( v, 0, degrees_continuity + 2 )
00332 val += coefs_uv[v][dw] * interpolation_coefs[dv][v];
00333 coefs_u[dv][dw] = val;
00334 }
00335 }
00336 }
00337
00338 private void add_components(
00339
int du,
00340
int dv,
00341
int dw,
00342 Real coef,
00343 Real line[2][N_DIMENSIONS],
00344 Real line_coefs[(MAX_DERIVS+1) * N_DIMENSIONS+1] )
00345 {
00346
int u1, u2, u3, v1, v2, v3, w1, w2, w3;
00347 Real u1f, u2f, u3f, v1f, v2f, v3f, w1f, w2f, w3f;
00348
00349 for_less( u1, 0, 2 )
00350 {
00351
if( du < 1 )
00352 {
00353
if( u1 == 1 )
00354
break;
00355 u1f = coef;
00356 }
00357
else
00358 u1f = coef * line[u1][X];
00359 for_less( u2, 0, 2 )
00360 {
00361
if( du < 2 )
00362 {
00363
if( u2 == 1 )
00364
break;
00365 u2f = u1f;
00366 }
00367
else
00368 u2f = u1f * line[u2][X];
00369 for_less( u3, 0, 2 )
00370 {
00371
if( du < 3 )
00372 {
00373
if( u3 == 1 )
00374
break;
00375 u3f = u2f;
00376 }
00377
else
00378 u3f = u2f * line[u3][X];
00379 for_less( v1, 0, 2 )
00380 {
00381
if( dv < 1 )
00382 {
00383
if( v1 == 1 )
00384
break;
00385 v1f = u3f;
00386 }
00387
else
00388 v1f = u3f * line[v1][Y];
00389 for_less( v2, 0, 2 )
00390 {
00391
if( dv < 2 )
00392 {
00393
if( v2 == 1 )
00394
break;
00395 v2f = v1f;
00396 }
00397
else
00398 v2f = v1f * line[v2][Y];
00399 for_less( v3, 0, 2 )
00400 {
00401
if( dv < 3 )
00402 {
00403
if( v3 == 1 )
00404
break;
00405 v3f = v2f;
00406 }
00407
else
00408 v3f = v2f * line[v3][Y];
00409 for_less( w1, 0, 2 )
00410 {
00411
if( dw < 1 )
00412 {
00413
if( w1 == 1 )
00414
break;
00415 w1f = v3f;
00416 }
00417
else
00418 w1f = v3f * line[w1][Z];
00419 for_less( w2, 0, 2 )
00420 {
00421
if( dw < 2 )
00422 {
00423
if( w2 == 1 )
00424
break;
00425 w2f = w1f;
00426 }
00427
else
00428 w2f = w1f * line[w2][Z];
00429 for_less( w3, 0, 2 )
00430 {
00431
if( dw < 3 )
00432 {
00433
if( w3 == 1 )
00434
break;
00435 w3f = w2f;
00436 }
00437
else
00438 w3f = w2f * line[w3][Z];
00439
00440 line_coefs[u1+u2+u3+v1+v2+v3+w1+w2+w3] += w3f;
00441 }
00442 }
00443 }
00444 }
00445 }
00446 }
00447 }
00448 }
00449 }
00450 }
00451
00452 private void find_coefs_of_line(
00453
int degrees_continuity,
00454 Real coefs[MAX_DERIVS+2][MAX_DERIVS+2][MAX_DERIVS+2],
00455 Real ou,
00456 Real ov,
00457 Real ow,
00458 Real du,
00459 Real dv,
00460 Real dw,
00461 Real line_coefs[(MAX_DERIVS+1) * N_DIMENSIONS+1] )
00462 {
00463
int deg, u_deg, v_deg, w_deg;
00464 Real line[2][N_DIMENSIONS];
00465
00466 line[0][0] = ou;
00467 line[0][1] = ov;
00468 line[0][2] = ow;
00469 line[1][0] = du;
00470 line[1][1] = dv;
00471 line[1][2] = dw;
00472
00473 for_less( deg, 0, (degrees_continuity+1) * N_DIMENSIONS+1 )
00474 line_coefs[deg] = 0.0;
00475
00476 for_less( u_deg, 0, degrees_continuity + 2 )
00477 {
00478 for_less( v_deg, 0, degrees_continuity + 2 )
00479 {
00480 for_less( w_deg, 0, degrees_continuity + 2 )
00481 {
00482
add_components( u_deg, v_deg, w_deg, coefs[u_deg][v_deg][w_deg],
00483 line, line_coefs );
00484 }
00485 }
00486 }
00487 }