Main Page | Modules | Data Structures | File List | Data Fields | Globals | Related Pages

intersect_voxel.c

Go to the documentation of this file.
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 }

Generated on Wed Jul 28 09:10:57 2004 for BICPL by doxygen 1.3.7