00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00047
00048
00049
00050 #include <iostream>
00051 #include <cmath>
00052 #include <limits>
00053 #include "errormacros.h"
00054 #include "LIC.h"
00055
00056 #include "simplethreads.h"
00057
00058 const int NUM_PROC=4;
00059
00060 using namespace lsseg;
00061 using namespace std;
00062
00063
00064 namespace {
00065
00066 const double TAN_LIM_ANGLE = tan(0.05);
00067 const double SIN2_LIM_ANGLE = sin(0.05) * sin(0.05);
00068 const double ROUNDOFF_TERM = 1.0e-5;
00069 const double INFINITE = std::numeric_limits<double>::max();
00070
00071 double steplength(const double posx,
00072 const double posy,
00073 const double vecx,
00074 const double vecy);
00075
00076
00077 inline double steplength(const double posx,
00078 const double posy,
00079 const double posz,
00080 const double vecx,
00081 const double vecy,
00082 const double vecz);
00083
00084 struct LIC_idata {
00085 int start;
00086 int end;
00087 const Image<double>* src;
00088 const Image<double>* vec;
00089 double* target_ptr;
00090 double (*kernel_func)(double);
00091 double L;
00092 };
00093
00094 struct LIC_FS_idata {
00095 int start;
00096 int end;
00097 const Image<double>* src;
00098 const Image<double>* vec;
00099 double* target_ptr;
00100 double (*kernel_func)(double);
00101 double L;
00102 double dl;
00103 };
00104
00105 void LIC_2D_subpart(const int job,
00106 const int thread,
00107 void * const idata,
00108 void * const odata);
00109
00110 void LIC_3D_subpart(const int job,
00111 const int thread,
00112 void * const idata,
00113 void * const odata);
00114
00115 void LIC_2D_FS_subpart(const int job,
00116 const int thread,
00117 void * const idata,
00118 void * const odata);
00119 void LIC_3D_FS_subpart(const int job,
00120 const int thread,
00121 void * const idata,
00122 void * const odata);
00123
00124 };
00125
00126 namespace lsseg {
00127
00128 void LIC_2D_FS(const Image<double>& src,
00129 const Image<double>& vec,
00130 Image<double>& target,
00131 double (*kernel_func)(double),
00132 const double dl,
00133 const double L)
00134 {
00135 ALWAYS_ERROR_IF(!src.spatial_compatible(vec),
00136 "source image and vector field size mismatch");
00137 ALWAYS_ERROR_IF(vec.numChannels() != 3, "given vector field was not 2D + magnitude");
00138 ALWAYS_ERROR_IF(!target.size_compatible(src), "target not same size as input image");
00139
00140
00141 const int Y = src.dimy();
00142 const int USED_PROC = Y < NUM_PROC ? Y : NUM_PROC;
00143 vector<LIC_FS_idata> job_idata(USED_PROC);
00144 for (int i = 0; i < USED_PROC; ++i) {
00145 int y1 = (i * Y) / USED_PROC;
00146 int y2 = ((i+1) * Y) / USED_PROC;
00147 job_idata[i].start = y1;
00148 job_idata[i].end = y2;
00149
00150 job_idata[i].target_ptr = &(target(0, y1, 0, 0));
00151 job_idata[i].src = &src;
00152 job_idata[i].vec = &vec;
00153 job_idata[i].kernel_func = kernel_func;
00154 job_idata[i].L = L;
00155 job_idata[i].dl = dl;
00156 }
00157
00158 do_threaded_jobs(LIC_2D_FS_subpart, &job_idata[0], USED_PROC, USED_PROC, false, NULL);
00159 }
00160
00161 void LIC_3D_FS(const Image<double>& src,
00162 const Image<double>& vec,
00163 Image<double>& target,
00164 double (*kernel_func)(double),
00165 const double dl,
00166 const double L)
00167 {
00168 ALWAYS_ERROR_IF(!src.spatial_compatible(vec),
00169 "source image and vector field size mismatch");
00170 ALWAYS_ERROR_IF(vec.numChannels() != 4, "given vector field was not 3D + magnitude");
00171 ALWAYS_ERROR_IF(!target.size_compatible(src), "target not same size as input image");
00172
00173
00174 const int Z = src.dimz();
00175 const int USED_PROC = Z < NUM_PROC ? Z : NUM_PROC;
00176 vector<LIC_FS_idata> job_idata(USED_PROC);
00177 for (int i = 0; i < USED_PROC; ++i) {
00178 int z1 = (i * Z) / USED_PROC;;
00179 int z2 = ((i+1) * Z) / USED_PROC;
00180 job_idata[i].start = z1;
00181 job_idata[i].end = z2;
00182
00183 job_idata[i].target_ptr = &(target(0, 0, z1, 0));
00184 job_idata[i].src = &src;
00185 job_idata[i].vec = &vec;
00186 job_idata[i].kernel_func = kernel_func;
00187 job_idata[i].L = L;
00188 job_idata[i].dl = dl;
00189 }
00190
00191 do_threaded_jobs(LIC_3D_FS_subpart, &job_idata[0], USED_PROC, USED_PROC, false, NULL);
00192 }
00193
00194
00195
00196
00197 void LIC_3D(const Image<double>& src,
00198 const Image<double>& vec,
00199 Image<double>& target,
00200 double (*kernel_func)(double),
00201 const double L)
00202 {
00203 ALWAYS_ERROR_IF(!src.spatial_compatible(vec),
00204 "source image and vector field size mismatch");
00205 ALWAYS_ERROR_IF(vec.numChannels() != 3, "given vector field was not 3D");
00206 ALWAYS_ERROR_IF(!target.size_compatible(src), "target not same size as input image");
00207
00208
00209 const int Z = src.dimz();
00210 const int USED_PROC = Z < NUM_PROC ? Z : NUM_PROC;
00211 vector<LIC_idata> job_idata(USED_PROC);
00212 for (int i = 0; i < USED_PROC; ++i) {
00213 int z1 = (i * Z) / USED_PROC;;
00214 int z2 = ((i+1) * Z) / USED_PROC;
00215 job_idata[i].start = z1;
00216 job_idata[i].end = z2;
00217
00218 job_idata[i].target_ptr = &(target(0, 0, z1, 0));
00219 job_idata[i].src = &src;
00220 job_idata[i].vec = &vec;
00221 job_idata[i].kernel_func = kernel_func;
00222 job_idata[i].L = L;
00223 }
00224
00225 do_threaded_jobs(LIC_3D_subpart, &job_idata[0], USED_PROC, USED_PROC, false, NULL);
00226 }
00227
00228
00229 void LIC_2D(const Image<double>& src,
00230 const Image<double>& vec,
00231 Image<double>& target,
00232 double (*kernel_func)(double),
00233 const double L)
00234 {
00235 ALWAYS_ERROR_IF(!src.spatial_compatible(vec),
00236 "source image and vector field size mismatch");
00237 ALWAYS_ERROR_IF(vec.numChannels() != 2, "given vector field was not 2D");
00238 ALWAYS_ERROR_IF(!target.size_compatible(src), "target not same size as input image");
00239
00240
00241 const int Y = src.dimy();
00242 const int USED_PROC = Y < NUM_PROC ? Y : NUM_PROC;
00243 vector<LIC_idata> job_idata(USED_PROC);
00244 for (int i = 0; i < USED_PROC; ++i) {
00245 int y1 = (i * Y) / USED_PROC;
00246 int y2 = ((i+1) * Y) / USED_PROC;
00247 job_idata[i].start = y1;
00248 job_idata[i].end = y2;
00249
00250 job_idata[i].target_ptr = &(target(0, y1, 0, 0));
00251 job_idata[i].src = &src;
00252 job_idata[i].vec = &vec;
00253 job_idata[i].kernel_func = kernel_func;
00254 job_idata[i].L = L;
00255 }
00256
00257 do_threaded_jobs(LIC_2D_subpart, &job_idata[0], USED_PROC, USED_PROC, false, NULL);
00258 }
00259
00260
00261
00262
00263
00264
00265
00266
00267
00268
00269
00270
00271
00272
00273
00274
00275
00276
00277
00278
00279
00280
00281
00282
00283
00284
00285
00286
00287
00288
00289
00290
00291
00292
00293
00294
00295
00296
00297
00298
00299
00300
00301
00302
00303
00304
00305
00306
00307
00308
00309
00310
00311
00312
00313
00314
00315
00316
00317
00318
00319
00320
00321
00322
00323
00324
00325
00326
00327
00328
00329
00330
00331
00332
00333
00334
00335
00336
00337
00338
00339
00340
00341
00342
00343
00344
00345
00346
00347
00348
00349
00350
00351
00352
00353
00354
00355
00356
00357
00358
00359
00360
00361
00362
00363
00364
00365
00366
00367
00368
00369
00370
00371
00372
00373
00374
00375
00376
00377
00378
00379
00380
00381
00382
00383
00384
00385
00386
00387
00388
00389
00390
00391
00392
00393
00394
00395
00396
00397
00398
00399
00400
00401
00402
00403
00404
00405
00406
00407
00408
00409
00410
00411
00412
00413
00414
00415
00416
00417
00418
00419
00420
00421
00422 };
00423
00424
00425 namespace {
00426
00427 void LIC_3D_subpart(const int job,
00428 const int thread,
00429 void * const idata,
00430 void * const odata)
00431 {
00432
00433 LIC_idata& input = ((LIC_idata*)idata)[job];
00434
00435 const int zstart = input.start;
00436 const int zend = input.end;
00437 const Image<double>& src = *(input.src);
00438 const Image<double>& vec = *(input.vec);
00439 double* t_ptr = input.target_ptr;
00440 const double L = input.L;
00441 double (*kernel_func)(double) = input.kernel_func;
00442
00443 std::cout <<"Now started job " << job << " in thread " << thread << endl;
00444
00445 const int X = src.dimx();
00446 const int Y = src.dimy();
00447 const int Z = src.dimz();
00448 const int C = src.numChannels();
00449 const unsigned long int channelsize = src.channelSize();
00450 std::vector<double> px_val(C);
00451 for (int z = zstart; z != zend; ++z) {
00452 for (int y = 0; y < Y; ++y) {
00453 for (int x = 0; x < X; ++x) {
00454 fill(px_val.begin(), px_val.end(), 0);
00455 double accum = 0;
00456 int sign = 1;
00457 for (int pass = 0; pass != 2; ++pass) {
00458
00459 double posx = x + 0.5;
00460 double posy = y + 0.5;
00461 double posz = z + 0.5;
00462 double l = 0;
00463 bool end_reached = false;
00464 int prev_x = int(posx);
00465 int prev_y = int(posy);
00466 int prev_z = int(posz);
00467 do {
00468 const int iposx = int(posx);
00469 const int iposy = int(posy);
00470 const int iposz = int(posz);
00471 const double w_x = sign * vec(iposx, iposy, iposz, 0);
00472 const double w_y = sign * vec(iposx, iposy, iposz, 1);
00473 const double w_z = sign * vec(iposx, iposy, iposz, 2);
00474 double dl = steplength(posx, posy, posz, w_x, w_y, w_z);
00475 if (dl < 0) break;
00476 l += dl;
00477 if (l > L) {
00478 dl = (l - L);
00479 l = L;
00480
00481 end_reached = true;
00482 }
00483
00484
00485
00486 const double h = kernel_func(l) * dl;
00487 for (int c = 0; c < C; ++c) {
00488 px_val[c] += h * src(iposx, iposy, iposz, c);
00489 }
00490 accum += h;
00491
00492
00493 posx += dl * w_x;
00494 posy += dl * w_y;
00495 posz += dl * w_z;
00496 if (posx < 0 || posx > X) break;
00497 if (posy < 0 || posy > Y) break;
00498 if (posz < 0 || posz > Z) break;
00499 if (int(posx) == prev_x &&
00500 int(posy) == prev_y &&
00501 int(posz) == prev_z) break;
00502 prev_x = iposx;
00503 prev_y = iposy;
00504 prev_z = iposz;
00505 } while (!end_reached);
00506 sign *= -1;
00507 }
00508 if (accum > 0) {
00509 for (int c = 0; c < C; ++c)
00510 *(t_ptr + c * channelsize) += px_val[c] / accum;
00511 } else {
00512 for (int c = 0; c < C; ++c)
00513 *(t_ptr + c * channelsize) += src(x, y, z, c);
00514 }
00515 ++t_ptr;
00516 }
00517 }
00518 }
00519 }
00520
00521 void LIC_2D_FS_subpart(const int job,
00522 const int thread,
00523 void * const idata,
00524 void * const odata)
00525 {
00526
00527 LIC_FS_idata& input = ((LIC_FS_idata*)idata)[job];
00528 const int ystart = input.start;
00529 const int yend = input.end;
00530 const Image<double>& src = *(input.src);
00531 const Image<double>& vec = *(input.vec);
00532 double* t_ptr = input.target_ptr;
00533 const double L = input.L;
00534 const double dl = input.dl;
00535 double (*kernel_func)(double) = input.kernel_func;
00536
00537 std::cout << "Now started job " << job << " in thread: " << thread << endl;
00538
00539 const int X = src.dimx();
00540 const int Y = src.dimy();
00541 const int C = src.numChannels();
00542 const unsigned long int channelsize = src.channelSize();
00543 std::vector<double> px_val(C);
00544 for (int y = ystart; y != yend; ++y) {
00545 for (int x = 0; x < X; ++x) {
00546 fill(px_val.begin(), px_val.end(), 0);
00547 double accum = 0;
00548 for (int pass = 0; pass != 2; ++pass) {
00549 double posx = x + 0.5;
00550 double posy = y + 0.5;
00551
00552
00553 double prev_wx = vec(int(posx), int(posy), 0, 0);
00554 double prev_wy = vec(int(posx), int(posy), 0, 1);
00555 if (pass != 0) {
00556 prev_wx *= -1;
00557 prev_wy *= -1;
00558 }
00559 double magnitude = vec(int(posx), int(posy), 0, 2);
00560 const double traverse_length = L * magnitude;
00561 for (double l = 0; l < traverse_length; l+=dl) {
00562 const int iposx = int(posx);
00563 const int iposy = int(posy);
00564 double wx = vec(iposx, iposy, 0, 0);
00565 double wy = vec(iposx, iposy, 0, 1);
00566 if (wx * prev_wx + wy * prev_wy < 0) {
00567 wx *= -1;
00568 wy *= -1;
00569 }
00570
00571 const double h= kernel_func(l) * dl;
00572 for (int c = 0; c < C; ++c) {
00573 px_val[c] += h * src(iposx, iposy, 0, c);
00574 }
00575 accum += h;
00576
00577
00578 posx += dl * wx;
00579 posy += dl * wy;
00580 if (posx < 0 || posx >= X) break;
00581 if (posy < 0 || posy >= Y) break;
00582 prev_wx = wx;
00583 prev_wy = wy;
00584 }
00585 }
00586 if (accum > 0) {
00587 for (int c = 0; c < C; ++c) {
00588 *(t_ptr + c * channelsize) += px_val[c] / accum;
00589 }
00590 } else {
00591 for (int c = 0; c < C; ++c) {
00592 *(t_ptr + c * channelsize) = src(x, y, 0, c);
00593 }
00594 }
00595 ++t_ptr;
00596 }
00597 }
00598 }
00599
00600 void LIC_3D_FS_subpart(const int job,
00601 const int thread,
00602 void * const idata,
00603 void * const odata)
00604 {
00605
00606 LIC_FS_idata& input = ((LIC_FS_idata*)idata)[job];
00607 const int zstart = input.start;
00608 const int zend = input.end;
00609 const Image<double>& src = *(input.src);
00610 const Image<double>& vec = *(input.vec);
00611 double* t_ptr = input.target_ptr;
00612 const double L = input.L;
00613 const double dl = input.dl;
00614 double (*kernel_func)(double) = input.kernel_func;
00615
00616 std::cout << "Now started job " << job << " in thread: " << thread << endl;
00617
00618 const int X = src.dimx();
00619 const int Y = src.dimy();
00620 const int Z = src.dimz();
00621 const int C = src.numChannels();
00622 const unsigned long int channelsize = src.channelSize();
00623 std::vector<double> px_val(C);
00624 for (int z = zstart; z != zend; ++z) {
00625 for (int y = 0; y != Y; ++y) {
00626 for (int x = 0; x < X; ++x) {
00627 fill(px_val.begin(), px_val.end(), 0);
00628 double accum = 0;
00629 for (int pass = 0; pass != 2; ++pass) {
00630 double posx = x + 0.5;
00631 double posy = y + 0.5;
00632 double posz = z + 0.5;
00633
00634
00635 double prev_wx = vec(int(posx), int(posy), int(posz), 0);
00636 double prev_wy = vec(int(posx), int(posy), int(posz), 1);
00637 double prev_wz = vec(int(posx), int(posy), int(posz), 2);
00638 if (pass != 0) {
00639 prev_wx *= -1;
00640 prev_wy *= -1;
00641 prev_wz *= -1;
00642 }
00643 double magnitude = vec(int(posx), int(posy), int(posz), 3);
00644 const double traverse_length = L * magnitude;
00645 for (double l = 0; l < traverse_length; l+=dl) {
00646 const int iposx = int(posx);
00647 const int iposy = int(posy);
00648 const int iposz = int(posz);
00649 double wx = vec(iposx, iposy, iposz, 0);
00650 double wy = vec(iposx, iposy, iposz, 1);
00651 double wz = vec(iposx, iposy, iposz, 2);
00652 assert(wx >= -1 && wx <= 1);
00653 assert(wy >= -1 && wy <= 1);
00654 assert(wz >= -1 && wz <= 1);
00655 if (wx * prev_wx + wy * prev_wy + wz * prev_wz < 0) {
00656 wx *= -1;
00657 wy *= -1;
00658 wz *= -1;
00659 }
00660
00661 const double h= kernel_func(l) * dl;
00662 for (int c = 0; c < C; ++c) {
00663 px_val[c] += h * src(iposx, iposy, iposz, c);
00664 }
00665 accum += h;
00666
00667
00668 posx += dl * wx;
00669 posy += dl * wy;
00670 posz += dl * wz;
00671 if (posx < 0 || posx >= X) break;
00672 if (posy < 0 || posy >= Y) break;
00673 if (posz < 0 || posz >= Z) break;
00674 prev_wx = wx;
00675 prev_wy = wy;
00676 prev_wz = wz;
00677 }
00678 }
00679 if (accum > 0) {
00680 for (int c = 0; c < C; ++c) {
00681 *(t_ptr + c * channelsize) += px_val[c] / accum;
00682 }
00683 } else {
00684 for (int c = 0; c < C; ++c) {
00685 *(t_ptr + c * channelsize) = src(x, y, z, c);
00686 }
00687 }
00688 ++t_ptr;
00689 }
00690 }
00691 }
00692 }
00693
00694
00695 void LIC_2D_subpart(const int job, const int thread, void * const idata, void * const odata)
00696 {
00697
00698 LIC_idata& input = ((LIC_idata*)idata)[job];
00699
00700 const int ystart = input.start;
00701 const int yend = input.end;
00702 const Image<double>& src = *(input.src);
00703 const Image<double>& vec = *(input.vec);
00704 double* t_ptr = input.target_ptr;
00705 const double L = input.L;
00706 double (*kernel_func)(double) = input.kernel_func;
00707
00708 std::cout << "Now started job " << job << " in thread " << thread << endl;
00709
00710 const int X = src.dimx();
00711 const int Y = src.dimy();
00712 const int C = src.numChannels();
00713 const unsigned long int channelsize = src.channelSize();
00714 std::vector<double> px_val(C);
00715 for (int y = ystart; y != yend; ++y) {
00716 for (int x = 0; x < X; ++x) {
00717 fill(px_val.begin(), px_val.end(), 0);
00718 double accum = 0;
00719 int sign = 1;
00720 for (int pass = 0; pass != 2; ++pass) {
00721 double posx = x + 0.5;
00722 double posy = y + 0.5;
00723 double l = 0;
00724 bool end_reached = false;
00725 int prev_x = int(posx);
00726 int prev_y = int(posy);
00727 do {
00728 const int iposx = int(posx);
00729 const int iposy = int(posy);
00730 const double w_x = sign * vec(iposx, iposy, 0, 0);
00731 const double w_y = sign * vec(iposx, iposy, 0, 1);
00732 double dl = steplength(posx, posy, w_x, w_y);
00733 if (dl < 0) break;
00734 l += dl;
00735 if (l > L) {
00736 dl = (l - L);
00737 l = L;
00738
00739 end_reached = true;
00740 }
00741
00742
00743
00744 const double h = kernel_func(l) * dl;
00745 for (int c = 0; c < C; ++c) {
00746 px_val[c] += h * src(iposx, iposy, 0, c);
00747 }
00748 accum += h;
00749
00750
00751 posx += dl * w_x;
00752 posy += dl * w_y;
00753 if (posx < 0 || posx > X) break;
00754 if (posy < 0 || posy > Y) break;
00755 if (int(posx) == prev_x && int(posy) == prev_y) break;
00756 prev_x = iposx;
00757 prev_y = iposy;
00758 } while (!end_reached);
00759 sign *= -1;
00760 }
00761 if (accum > 0) {
00762 for (int c = 0; c < C; ++c) {
00763
00764 *(t_ptr + c * channelsize) += px_val[c] / accum;
00765 }
00766 } else {
00767 for (int c = 0; c < C; ++c)
00768 *(t_ptr + c * channelsize) = src(x, y, 0, c);
00769 }
00770 ++t_ptr;
00771 }
00772 }
00773 }
00774
00775
00776 double steplength(const double posx,
00777 const double posy,
00778 const double vecx,
00779 const double vecy)
00780 {
00781 const double EPS = 1.0e-10;
00782 if (fabs(vecx) < EPS && fabs(vecy) < EPS) {
00783
00784
00785 return -1;
00786 }
00787 const double rem_x = int(posx) - posx;
00788 const double rem_y = int(posy) - posy;
00789
00790
00791 const double x_limit = TAN_LIM_ANGLE * fabs(vecy);
00792 const double y_limit = TAN_LIM_ANGLE * fabs(vecx);
00793
00794 double sx_left, sx_right, sy_left, sy_right;
00795 if (vecx < -x_limit) {
00796 sx_left = rem_x / vecx;
00797 sx_right = INFINITE;
00798 } else if (vecx > x_limit) {
00799 sx_left = INFINITE;
00800 sx_right = (rem_x+1)/vecx;
00801 } else {
00802 sx_left = sx_right = INFINITE;
00803 }
00804 if (vecy < -y_limit) {
00805 sy_left = rem_y / vecy;
00806 sy_right = INFINITE;
00807 } else if (vecy > y_limit) {
00808 sy_left = INFINITE;
00809 sy_right = (rem_y+1)/vecy;
00810 } else {
00811 sy_left = sy_right = INFINITE;
00812 }
00813
00814 const double min_x = (sx_left < sx_right) ? sx_left : sx_right;
00815 const double min_y = (sy_left < sy_right) ? sy_left : sy_right;
00816 assert(min_x >=0);
00817 assert(min_y >=0);
00818
00819 const double res = min_x < min_y ? min_x : min_y;
00820 if (res == INFINITE) {
00821
00822 return -1;
00823 }
00824 return res + ROUNDOFF_TERM;
00825 }
00826
00827 inline double steplength(const double posx,
00828 const double posy,
00829 const double posz,
00830 const double vecx,
00831 const double vecy,
00832 const double vecz)
00833 {
00834 const double EPS = 1.0e-10;
00835 if ((fabs(vecx) < EPS) && (fabs(vecy) < EPS) && (fabs(vecz) < EPS)) {
00836
00837
00838 return -1;
00839 }
00840 const double rem_x = int(posx) - posx;
00841 const double rem_y = int(posy) - posy;
00842 const double rem_z = int(posz) - posz;
00843
00844 const double vecx2 = vecx*vecx;
00845 const double vecy2 = vecy*vecy;
00846 const double vecz2 = vecz*vecz;
00847 const double vnorm2 = vecx2 + vecy2 + vecz2;
00848 const double limit2 = vnorm2 * SIN2_LIM_ANGLE;
00849
00850 double sx_left, sx_right, sy_left, sy_right, sz_left, sz_right;
00851 sx_left = sx_right = sy_left = sy_right = sz_left = sz_right = INFINITE;
00852 if (vecx2 > limit2) {
00853 if (vecx < 0) {
00854 sx_left = rem_x / vecx;
00855 } else {
00856 sx_right = (rem_x + 1)/vecx;
00857 }
00858 }
00859 if (vecy2 > limit2) {
00860 if (vecy < 0) {
00861 sy_left = rem_y / vecy;
00862 } else {
00863 sy_right = (rem_y + 1) / vecy;
00864 }
00865 }
00866 if (vecz2 > limit2) {
00867 if (vecz < 0) {
00868 sz_left = rem_z / vecz;
00869 } else {
00870 sz_right = (rem_z + 1) / vecz;
00871 }
00872 }
00873 const double min_x = (sx_left < sx_right) ? sx_left : sx_right;
00874 const double min_y = (sy_left < sy_right) ? sy_left : sy_right;
00875 const double min_z = (sz_left < sz_right) ? sz_left : sz_right;
00876 assert(min_x >=0);
00877 assert(min_y >=0);
00878 assert(min_z >=0);
00879
00880 double res = min_x < min_y ? min_x : min_y;
00881 res = (min_z < res) ? min_z : res;
00882 if (res == INFINITE) {
00883
00884 return -1;
00885 }
00886 return res + ROUNDOFF_TERM;
00887 }
00888
00889 };