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 <functional>
00051 #include <stdexcept>
00052 #include <time.h>
00053 #include <vector>
00054 #include <boost/lambda/lambda.hpp>
00055 #include "Region.h"
00056 #include "errormacros.h"
00057 #include "Image.h"
00058 #include "LevelSetFunction.h"
00059 #include "level_set.h"
00060 #include "simple_tools.h"
00061 #include "cimg_dependent.h"
00062
00063
00064 #include "Mask.h"
00065 #include "Filters.h"
00066 #include "DiscreteApproximations.h"
00067
00068 using namespace boost::lambda;
00069 using namespace std;
00070
00071 using namespace lsseg;
00072
00073 namespace
00074 {
00075 void visualize_multisets_impl(vector<const LevelSetFunction*> phi_pts,
00076 Image<double>& target,
00077 const int** const rgb_color);
00078
00079 inline void godunov_phi_2D(double a_term,
00080 double phi_xl, double phi_xr,
00081 double phi_yl, double phi_yr,
00082 double& phi_x,
00083 double& phi_y);
00084
00085 inline void godunov_phi_3D(double a_term,
00086 double phi_xl, double phi_xr,
00087 double phi_yl, double phi_yr,
00088 double phi_zl, double phi_zr,
00089 double& phi_x,
00090 double& phi_y,
00091 double& phi_z);
00092
00093
00094
00095
00096
00097 inline bool defined(int x, int y, int z, int X, int Y, int Z, const Mask* mask)
00098 {
00099 return (x >= 0 && x < X &&
00100 y >= 0 && y < Y &&
00101 z >= 0 && z < Z &&
00102 (!mask || (*mask)(x, y, z)));
00103 }
00104
00105 double neumann_curvature_at(int x,
00106 int y,
00107 int z,
00108 const Image<double>& phi,
00109 const Mask* mask);
00110
00111 double dirichlet_curvature_at(int x,
00112 int y,
00113 int z,
00114 const Image<double>& phi,
00115 const Mask* mask);
00116
00117 void neumann_d1_leftright_2D(int x,
00118 int y,
00119 const Image<double>& phi,
00120 const Mask* mask,
00121 double& dxl,
00122 double& dxr,
00123 double& dyl,
00124 double& dyr);
00125
00126 void dirichlet_d1_leftright_2D(int x,
00127 int y,
00128 const Image<double>& phi,
00129 const Mask* mask,
00130 double& dxl,
00131 double& dxr,
00132 double& dyl,
00133 double& dyr);
00134
00135 void neumann_d1_leftright_3D(int x,
00136 int y,
00137 int z,
00138 const Image<double>& phi,
00139 const Mask* mask,
00140 double& dxl,
00141 double& dxr,
00142 double& dyl,
00143 double& dyr,
00144 double& dzl,
00145 double& dzr);
00146
00147 void dirichlet_d1_leftright_3D(int x,
00148 int y,
00149 int z,
00150 const Image<double>& phi,
00151 const Mask* mask,
00152 double& dxl,
00153 double& dxr,
00154 double& dyl,
00155 double& dyr,
00156 double& dzl,
00157 double& dzr);
00158
00159 };
00160
00161 namespace lsseg {
00162
00163
00164
00165 void normal_direction_flow_2D(const LevelSetFunction& phi,
00166 LevelSetFunction& advect,
00167 BorderCondition bcond,
00168 double& H1,
00169 double& H2,
00170 const Mask* const changes_allowed_mask,
00171 const Mask* const defined_region_mask)
00172
00173 {
00174 assert(phi.dimz() == 1);
00175 assert(advect.size_compatible(phi));
00176 assert(phi.numChannels() == 1);
00177 const int X = phi.dimx();
00178 const int Y = phi.dimy();
00179 H1 = H2 = 0;
00180
00181 void (*der_estimate)(int, int, const Image<double>&, const Mask*,
00182 double&, double&, double&, double&);
00183 if (bcond == NEUMANN) {
00184 der_estimate = neumann_d1_leftright_2D;
00185 } else {
00186 assert(bcond == DIRICHLET);
00187 der_estimate = dirichlet_d1_leftright_2D;
00188 }
00189
00190 const Mask::value_type* m_it = changes_allowed_mask ? changes_allowed_mask->begin() : 0;
00191
00192 for (int yc = 0; yc < Y; ++yc) {
00193 for (int xc = 0; xc < X; ++xc) {
00194 if (changes_allowed_mask && !(*m_it++)) {
00195
00196 advect(xc, yc) = 0;
00197 continue;
00198 }
00199 const double a_term = advect(xc, yc);
00200 double phi_xl, phi_xr, phi_yl, phi_yr;
00201
00202 der_estimate(xc, yc, phi,
00203 defined_region_mask,
00204 phi_xl, phi_xr,
00205 phi_yl, phi_yr);
00206
00207 double phi_x, phi_y;
00208 godunov_phi_2D(a_term,
00209 phi_xl, phi_xr,
00210 phi_yl, phi_yr,
00211 phi_x,
00212 phi_y);
00213
00214 const double norm_phi2 = phi_x * phi_x + phi_y * phi_y;
00215 const double norm_phi = sqrt(norm_phi2);
00216 advect(xc, yc) = -a_term * norm_phi;
00217
00218 if (norm_phi > 0) {
00219 const double norm_inv = double(1) / norm_phi;
00220 const double fac = a_term * norm_inv;
00221 double tmp = fabs(phi_x * fac);
00222 H1 = H1 > tmp ? H1 : tmp;
00223 tmp = fabs(phi_y * fac);
00224 H2 = H2 > tmp ? H2 : tmp;
00225 }
00226 }
00227 }
00228 }
00229
00230
00231 void normal_direction_flow_3D(const LevelSetFunction& phi,
00232 LevelSetFunction& advect,
00233 BorderCondition bcond,
00234 double& H1,
00235 double& H2,
00236 double& H3,
00237 const Mask* const changes_allowed_mask,
00238 const Mask* const defined_region_mask)
00239
00240 {
00241 assert(advect.size_compatible(phi));
00242 assert(phi.numChannels() == 1);
00243 const int X = phi.dimx();
00244 const int Y = phi.dimy();
00245 const int Z = phi.dimz();
00246 H1 = H2 = H3 = 0;
00247
00248 void (*der_estimate)(int, int, int, const Image<double>&, const Mask*,
00249 double&, double&, double&, double&, double&, double&);
00250 if (bcond == NEUMANN) {
00251 der_estimate = neumann_d1_leftright_3D;
00252 } else {
00253 assert(bcond == DIRICHLET);
00254 der_estimate = dirichlet_d1_leftright_3D;
00255 }
00256
00257 const Mask::value_type* m_it = changes_allowed_mask ? changes_allowed_mask->begin() : 0;
00258
00259 for (int zc = 0; zc < Z; ++zc) {
00260 for (int yc = 0; yc < Y; ++yc) {
00261 for (int xc = 0; xc < X; ++xc) {
00262 if (changes_allowed_mask && !(*m_it++)) {
00263
00264 advect(xc, yc, zc) = 0;
00265 continue;
00266 }
00267 const double a_term = advect(xc, yc, zc);
00268
00269 double phi_xl, phi_xr, phi_yl, phi_yr, phi_zl, phi_zr;
00270
00271 der_estimate(xc, yc, zc, phi,
00272 defined_region_mask,
00273 phi_xl, phi_xr,
00274 phi_yl, phi_yr,
00275 phi_zl, phi_zr);
00276 double phi_x, phi_y, phi_z;
00277 godunov_phi_3D(a_term,
00278 phi_xl, phi_xr,
00279 phi_yl, phi_yr,
00280 phi_zl, phi_zr,
00281 phi_x,
00282 phi_y,
00283 phi_z);
00284 const double norm_phi2 = phi_x * phi_x + phi_y * phi_y + phi_z * phi_z;
00285 const double norm_phi = sqrt(norm_phi2);
00286 advect(xc, yc, zc) = -a_term * norm_phi;
00287
00288 if (norm_phi > 0) {
00289 const double norm_inv = double(1) / norm_phi;
00290 const double fac = a_term * norm_inv;
00291 double tmp = fabs(phi_x * fac);
00292
00293 H1 = H1 > tmp ? H1 : tmp;
00294 tmp = fabs(phi_y * fac);
00295 H2 = H2 > tmp ? H2 : tmp;
00296 tmp = fabs(phi_z * fac);
00297 H3 = H3 > tmp ? H3 : tmp;
00298 }
00299 }
00300 }
00301 }
00302 }
00303
00304
00305 void visualize_multisets(const LevelSetFunction** const images,
00306 int num_images,
00307 Image<double>& target,
00308 const int** const rgb_color)
00309
00310 {
00311 vector<const LevelSetFunction* > phi_pointers(images, images + num_images);
00312
00313
00314
00315 visualize_multisets_impl(phi_pointers, target, rgb_color);
00316 }
00317
00318
00319 int visualize_level_set(const LevelSetFunction& img,
00320 Image<double>& target,
00321 double threshold,
00322 double outside_intensity,
00323 double curve_intensity,
00324 double interior_intensity,
00325 const Mask* const mask,
00326 double mask_intensity)
00327
00328 {
00329 int num_border_pixels = 0;
00330 ALWAYS_ERROR_IF(img.numChannels() != 1, "dim should be 1 here");
00331 assert(img.size_compatible(target));
00332 assert(!mask || img.size_compatible(*mask));
00333 bool no_mask = (mask == 0);
00334 for (int z = 0; z < img.dimz(); ++z) {
00335 for (int y = 0; y < img.dimy(); ++y) {
00336 for (int x = 0; x < img.dimx(); ++x) {
00337 if (no_mask || (*mask)(x, y, z) > 0) {
00338 double Iccc = img(x, y, z);
00339 double Icnc = img(x, (y == img.dimy() - 1) ? y : y+1, z);
00340 double Incc = img((x == img.dimx() - 1) ? x : x+1, y, z);
00341 double Iccn = img(x, y, (z == img.dimz() - 1) ? z : z+1);
00342 double Icpc = img(x, (y==0) ? y : y-1, z);
00343 double Ipcc = img((x==0) ? 0 : x-1, y, z);
00344 double Iccp = img(x, y, (z==0) ? 0 : z-1);
00345
00346 Iccc -= threshold;
00347 Icnc -= threshold;
00348 Incc -= threshold;
00349 Iccn -= threshold;
00350 Icpc -= threshold;
00351 Ipcc -= threshold;
00352 Iccp -= threshold;
00353
00354 if (Iccc * Incc < 0 || (Iccc == 0 && Incc != 0) ||
00355 Iccc * Icnc < 0 || (Iccc == 0 && Icnc != 0) ||
00356 Iccc * Iccn < 0 || (Iccc == 0 && Iccn != 0) ||
00357 Iccc * Ipcc < 0 || (Iccc == 0 && Ipcc != 0) ||
00358 Iccc * Icpc < 0 || (Iccc == 0 && Icpc != 0) ||
00359 Iccc * Iccp < 0 || (Iccc == 0 && Iccp != 0)) {
00360 target(x, y, z) = curve_intensity;
00361 ++num_border_pixels;
00362 } else {
00363 target(x, y, z) = Iccc < 0 ? interior_intensity : outside_intensity;
00364 }
00365 } else {
00366 target(x, y, z) = mask_intensity;
00367 }
00368 }
00369 }
00370 }
00371 return num_border_pixels;
00372 }
00373
00374 };
00375
00376 namespace
00377 {
00378
00379
00380 void neumann_d1_leftright_2D(int x,
00381 int y,
00382 const Image<double>& phi,
00383 const Mask* mask,
00384 double& dxl,
00385 double& dxr,
00386 double& dyl,
00387 double& dyr)
00388
00389 {
00390 assert(phi.dimz() == 1);
00391 const int X = phi.dimx();
00392 const int Y = phi.dimy();
00393
00394
00395 int xp(-1), yp(-1), xn(-1), yn(-1);
00396
00397 if (!mask) {
00398 if (x > 0) { xp = x-1; }
00399 if (x < X-1) { xn = x+1; }
00400 if (y > 0) { yp = y-1; }
00401 if (y < Y-1) { yn = y+1; }
00402 } else {
00403 if (x > 0 && (*mask)(x-1, y)) { xp = x-1; }
00404 if (x < X-1 && (*mask)(x+1, y)) { xn = x+1; }
00405 if (y > 0 && (*mask)(x, y-1)) { yp = y-1; }
00406 if (y < Y-1 && (*mask)(x, y+1)) { yn = y+1; }
00407 }
00408 const double Icc = phi(x, y);
00409 const double Ipc = (xp >= 0) ? phi(xp, y) : (xn >= 0) ? 2 * Icc - phi(xn, y) : Icc;
00410 const double Inc = (xn >= 0) ? phi(xn, y) : (xp >= 0) ? 2 * Icc - phi(xp, y) : Icc;
00411 const double Icp = (yp >= 0) ? phi(x, yp) : (yn >= 0) ? 2 * Icc - phi(x, yn) : Icc;
00412 const double Icn = (yn >= 0) ? phi(x, yn) : (yp >= 0) ? 2 * Icc - phi(x, yp) : Icc;
00413
00414 dxl = Icc - Ipc;
00415 dxr = Inc - Icc;
00416 dyl = Icc - Icp;
00417 dyr = Icn - Icc;
00418
00419 }
00420
00421
00422 void dirichlet_d1_leftright_2D(int x,
00423 int y,
00424 const Image<double>& phi,
00425 const Mask* mask,
00426 double& dxl,
00427 double& dxr,
00428 double& dyl,
00429 double& dyr)
00430
00431 {
00432 const int X = phi.dimx();
00433 const int Y = phi.dimy();
00434
00435
00436 int xp, yp, xn, yn;
00437 if (!mask) {
00438 xp = (x > 0) ? x-1 : x;
00439 yp = (y > 0) ? y-1 : x;
00440 xn = (x < X-1) ? x+1 : x;
00441 yn = (y < Y-1) ? y+1 : y;
00442 } else {
00443 xp = (x > 0 && (*mask)(x-1, y)) ? x-1 : x;
00444 yp = (y > 0 && (*mask)( x, y-1)) ? y-1 : y;
00445 xn = (x < X-1 && (*mask)(x+1, y)) ? x+1 : x;
00446 yn = (y < Y-1 && (*mask)( x, y+1)) ? y+1 : y;
00447 }
00448
00449 double Icc = phi(x, y);
00450 double Ipc = phi(xp, y);
00451 double Inc = phi(xn, y);
00452 double Icp = phi(x, yp);
00453 double Icn = phi(x, yn);
00454
00455 dxl = Icc - Ipc;
00456 dxr = Inc - Icc;
00457 dyl = Icc - Icp;
00458 dyr = Icn - Icc;
00459 }
00460
00461
00462
00463 void dirichlet_d1_leftright_3D(int x,
00464 int y,
00465 int z,
00466 const Image<double>& phi,
00467 const Mask* mask,
00468 double& dxl,
00469 double& dxr,
00470 double& dyl,
00471 double& dyr,
00472 double& dzl,
00473 double& dzr)
00474
00475 {
00476 const int X = phi.dimx();
00477 const int Y = phi.dimy();
00478 const int Z = phi.dimz();
00479
00480
00481 int xp, yp, zp, xn, yn, zn;
00482 if (!mask) {
00483 xp = (x > 0) ? x-1 : x;
00484 yp = (y > 0) ? y-1 : x;
00485 zp = (z > 0) ? z-1 : x;
00486 xn = (x < X-1) ? x+1 : x;
00487 yn = (y < Y-1) ? y+1 : y;
00488 zn = (z < Z-1) ? z+1 : z;
00489 } else {
00490 xp = (x > 0 && (*mask)(x-1, y, z)) ? x-1 : x;
00491 yp = (y > 0 && (*mask)( x, y-1, z)) ? y-1 : y;
00492 zp = (z > 0 && (*mask)( x, y, z-1)) ? z-1 : z;
00493 xn = (x < X-1 && (*mask)(x+1, y, z)) ? x+1 : x;
00494 yn = (y < Y-1 && (*mask)( x, y+1, z)) ? y+1 : y;
00495 zn = (z < Z-1 && (*mask)( x, y, z+1)) ? z+1 : z;
00496 }
00497
00498 double Iccc = phi(x, y, z);
00499 double Ipcc = phi(xp, y, z);
00500 double Incc = phi(xn, y, z);
00501 double Icpc = phi(x, yp, z);
00502 double Icnc = phi(x, yn, z);
00503 double Iccp = phi(x, y, zp);
00504 double Iccn = phi(x, y, zn);
00505
00506 dxl = Iccc - Ipcc;
00507 dxr = Incc - Iccc;
00508 dyl = Iccc - Icpc;
00509 dyr = Icnc - Iccc;
00510 dzl = Iccc - Iccp;
00511 dzr = Iccn - Iccc;
00512 }
00513
00514
00515
00516 void neumann_d1_leftright_3D(int x,
00517 int y,
00518 int z,
00519 const Image<double>& phi,
00520 const Mask* mask,
00521 double& dxl,
00522 double& dxr,
00523 double& dyl,
00524 double& dyr,
00525 double& dzl,
00526 double& dzr)
00527
00528 {
00529 const int X = phi.dimx();
00530 const int Y = phi.dimy();
00531 const int Z = phi.dimz();
00532
00533
00534 int xp(-1), yp(-1), zp(-1), xn(-1), yn(-1), zn(-1);
00535
00536 if (!mask) {
00537 if (x > 0) { xp = x-1; }
00538 if (x < X-1) { xn = x+1; }
00539 if (y > 0) { yp = y-1; }
00540 if (y < Y-1) { yn = y+1; }
00541 if (z > 0) { zp = z-1; }
00542 if (z < Z-1) { zn = z+1; }
00543 } else {
00544 if (x > 0 && (*mask)(x-1, y, z)) { xp = x-1; }
00545 if (x < X-1 && (*mask)(x+1, y, z)) { xn = x+1; }
00546 if (y > 0 && (*mask)(x, y-1, z)) { yp = y-1; }
00547 if (y < Y-1 && (*mask)(x, y+1, z)) { yn = y+1; }
00548 if (z > 0 && (*mask)(x, y, z-1)) { zp = z-1; }
00549 if (z < Z-1 && (*mask)(x, y, z+1)) { zn = z+1; }
00550 }
00551 const double Iccc = phi(x, y, z);
00552 const double Ipcc = (xp >= 0) ? phi(xp, y, z) : (xn >= 0) ? 2 * Iccc - phi(xn, y, z) : Iccc;
00553 const double Incc = (xn >= 0) ? phi(xn, y, z) : (xp >= 0) ? 2 * Iccc - phi(xp, y, z) : Iccc;
00554 const double Icpc = (yp >= 0) ? phi(x, yp, z) : (yn >= 0) ? 2 * Iccc - phi(x, yn, z) : Iccc;
00555 const double Icnc = (yn >= 0) ? phi(x, yn, z) : (yp >= 0) ? 2 * Iccc - phi(x, yp, z) : Iccc;
00556 const double Iccp = (zp >= 0) ? phi(x, y, zp) : (zn >= 0) ? 2 * Iccc - phi(x, y, zn) : Iccc;
00557 const double Iccn = (zn >= 0) ? phi(x, y, zn) : (zp >= 0) ? 2 * Iccc - phi(x, y, zp) : Iccc;
00558
00559
00560 dxl = Iccc - Ipcc;
00561 dxr = Incc - Iccc;
00562 dyl = Iccc - Icpc;
00563 dyr = Icnc - Iccc;
00564 dzl = Iccc - Iccp;
00565 dzr = Iccn - Iccc;
00566 }
00567
00568
00569 double dirichlet_curvature_at(int x,
00570 int y,
00571 int z,
00572 const Image<double>& phi,
00573 const Mask* mask)
00574
00575 {
00576 MESSAGE("dirichlet_curvature_at() unimplemented.");
00577 exit(0);
00578 }
00579
00580
00581 double neumann_curvature_at(int x,
00582 int y,
00583 int z,
00584 const Image<double>& phi,
00585 const Mask* mask)
00586
00587 {
00588 const double EPS=1.0e-10;
00589 const int X = phi.dimx();
00590 const int Y = phi.dimy();
00591 const int Z = phi.dimz();
00592
00593
00594 int xp(-1), yp(-1), zp(-1), xn(-1), yn(-1), zn(-1);
00595
00596 if (!mask) {
00597 if (x > 0) { xp = x-1; }
00598 if (x < X-1) { xn = x+1; }
00599 if (y > 0) { yp = y-1; }
00600 if (y < Y-1) { yn = y+1; }
00601 if (z > 0) { zp = z-1; }
00602 if (z < Z-1) { zn = z+1; }
00603 } else {
00604 if (x > 0 && (*mask)(x-1, y, z)) { xp = x-1; }
00605 if (x < X-1 && (*mask)(x+1, y, z)) { xn = x+1; }
00606 if (y > 0 && (*mask)(x, y-1, z)) { yp = y-1; }
00607 if (y < Y-1 && (*mask)(x, y+1, z)) { yn = y+1; }
00608 if (z > 0 && (*mask)(x, y, z-1)) { zp = z-1; }
00609 if (z < Z-1 && (*mask)(x, y, x+1)) { zn = z+1; }
00610 }
00611 double Iccc = phi(x, y, z);
00612 double Ipcc = (xp >= 0) ? phi(xp, y, z) : (xn >= 0) ? 2 * Iccc - phi(xn, y, z) : Iccc;
00613 double Incc = (xn >= 0) ? phi(xn, y, z) : (xp >= 0) ? 2 * Iccc - phi(xp, y, z) : Iccc;
00614 double Icpc = (yp >= 0) ? phi(x, yp, z) : (yn >= 0) ? 2 * Iccc - phi(x, yn, z) : Iccc;
00615 double Icnc = (yn >= 0) ? phi(x, yn, z) : (yp >= 0) ? 2 * Iccc - phi(x, yp, z) : Iccc;
00616 double Iccp = (zp >= 0) ? phi(x, y, zp) : (zn >= 0) ? 2 * Iccc - phi(x, y, zn) : Iccc;
00617 double Iccn = (zn >= 0) ? phi(x, y, zn) : (zp >= 0) ? 2 * Iccc - phi(x, y, zp) : Iccc;
00618
00619 double dx = 0.5 * (Incc - Ipcc);
00620 double dy = 0.5 * (Icnc - Icpc);
00621 double dz = 0.5 * (Iccn - Iccp);
00622
00623 double norm2 = (dx * dx + dy * dy + dz * dz);
00624
00625 if (norm2 < EPS) return 0;
00626
00627
00628 double Ippc = defined(x-1,y-1,z ,X,Y,Z,mask) ? phi(x-1,y-1,z ) : Ipcc+Icpc - Iccc;
00629
00630 double Ipcp = defined(x-1,y ,z-1,X,Y,Z,mask) ? phi(x-1,y ,z-1) : Ipcc+ Iccp- Iccc;
00631 double Ipcn = defined(x-1,y ,z+1,X,Y,Z,mask) ? phi(x-1,y ,z+1) : Ipcc+ Iccn- Iccc;
00632
00633 double Ipnc = defined(x-1,y+1,z ,X,Y,Z,mask) ? phi(x-1,y+1,z ) : Ipcc+Icnc - Iccc;
00634
00635 double Icpp = defined(x ,y-1,z-1,X,Y,Z,mask) ? phi(x ,y-1,z-1) : Icpc+Iccp- Iccc;
00636 double Icpn = defined(x ,y-1,z+1,X,Y,Z,mask) ? phi(x ,y-1,z+1) : Icpc+Iccn- Iccc;
00637 double Icnp = defined(x ,y+1,z-1,X,Y,Z,mask) ? phi(x ,y+1,z-1) : Icnc+Iccp- Iccc;
00638 double Icnn = defined(x ,y+1,z+1,X,Y,Z,mask) ? phi(x ,y+1,z+1) : Icnc+Iccn- Iccc;
00639
00640 double Inpc = defined(x+1,y-1,z ,X,Y,Z,mask) ? phi(x+1,y-1,z ) : Incc+Icpc - Iccc;
00641
00642 double Incp = defined(x+1,y ,z-1,X,Y,Z,mask) ? phi(x+1,y ,z-1) : Incc+ Iccp- Iccc;
00643 double Incn = defined(x+1,y ,z+1,X,Y,Z,mask) ? phi(x+1,y ,z+1) : Incc+ Iccn- Iccc;
00644
00645 double Innc = defined(x+1,y+1,z ,X,Y,Z,mask) ? phi(x+1,y+1,z ) : Incc+Icnc - Iccc;
00646
00647
00648 double dxx = Incc + Ipcc - 2 * Iccc;
00649 double dyy = Icnc + Icpc - 2 * Iccc;
00650 double dzz = Iccn + Iccp - 2 * Iccc;
00651
00652 double dxy = (dx * dy < 0) ?
00653 0.5 * (2 * Iccc + Ippc + Innc - Ipcc - Incc - Icpc - Icnc) :
00654 0.5 * (Ipcc + Incc + Icpc + Icnc - 2 * Iccc - Ipnc - Inpc);
00655
00656 double dxz = (dx * dz < 0) ?
00657 0.5 * (2 * Iccc + Ipcp + Incn - Ipcc - Incc - Iccp - Iccn) :
00658 0.5 * (Ipcc + Incc + Iccp + Iccn - 2 * Iccc - Ipcn - Incp);
00659
00660 double dyz = (dy * dz < 0) ?
00661 0.5 * (2 * Iccc + Icpp + Icnn - Icpc - Icnc - Iccp - Iccn) :
00662 0.5 * (Icpc + Icnc + Iccp + Iccn - 2 * Iccc - Icpn - Icnp);
00663
00664 double norm = sqrt(norm2);
00665
00666 return (dx * dx * (dyy + dzz) +
00667 dy * dy * (dxx + dzz) +
00668 dz * dz * (dxx + dyy) -
00669 2 * (dx * dy * dxy +
00670 dx * dz * dxz +
00671 dy * dz * dyz)
00672 ) / (norm * norm2);
00673 }
00674
00675
00676 void visualize_multisets_impl(vector<const LevelSetFunction* > images,
00677 Image<double>& target,
00678 const int** const rgb_color)
00679
00680 {
00681 const int num_images = images.size();
00682 assert(num_images > 0);
00683 assert(images[0]->dimz() == 1);
00684 const int X = images[0]->dimx();
00685 const int Y = images[0]->dimy();
00686 target.resize(X, Y, 1, 3);
00687
00688 int blend[3];
00689 int num_covering = 0;
00690 for (int y = 0; y < Y; ++y) {
00691 for (int x = 0; x < X; ++x) {
00692 blend[0] = blend[1] = blend[2] = 0;
00693 num_covering = 0;
00694 for (int i = 0; i < num_images; ++i) {
00695 if ((*images[i])(x, y) <= 0) {
00696
00697 blend[0] += rgb_color[i][0];
00698 blend[1] += rgb_color[i][1];
00699 blend[2] += rgb_color[i][2];
00700 ++num_covering;
00701 }
00702 }
00703 if (num_covering > 0) {
00704 target(x, y, 0, 0) = blend[0] / num_covering;
00705 target(x, y, 0, 1) = blend[1] / num_covering;
00706 target(x, y, 0, 2) = blend[2] / num_covering;
00707 } else {
00708 target(x, y, 0, 0) = rgb_color[num_images][0];
00709 target(x, y, 0, 1) = rgb_color[num_images][1];
00710 target(x, y, 0, 2) = rgb_color[num_images][2];
00711 }
00712 }
00713 }
00714 }
00715
00716
00717 void godunov_phi_2D(double a_term,
00718 double phi_xl, double phi_xr,
00719 double phi_yl, double phi_yr,
00720 double& phi_x,
00721 double& phi_y)
00722
00723 {
00724
00725 if (a_term * phi_xr > 0) {
00726 phi_x = (a_term * phi_xl > 0) ? phi_xl : 0;
00727 } else {
00728 if (a_term * phi_xl > 0) {
00729 phi_x = (fabs(phi_xl) > fabs(phi_xr)) ? phi_xl : phi_xr;
00730 } else {
00731 phi_x = phi_xr;
00732 }
00733 }
00734 if (a_term * phi_yr > 0) {
00735 phi_y = (a_term * phi_yl > 0) ? phi_yl : 0;
00736 } else {
00737 if (a_term * phi_yl > 0) {
00738 phi_y = (fabs(phi_yl) > fabs(phi_yr)) ? phi_yl : phi_yr;
00739 } else {
00740 phi_y = phi_yr;
00741 }
00742 }
00743 }
00744
00745
00746 void godunov_phi_3D(double a_term,
00747 double phi_xl, double phi_xr,
00748 double phi_yl, double phi_yr,
00749 double phi_zl, double phi_zr,
00750 double& phi_x,
00751 double& phi_y,
00752 double& phi_z)
00753
00754 {
00755
00756 if (a_term * phi_xr > 0) {
00757 phi_x = (a_term * phi_xl > 0) ? phi_xl : 0;
00758 } else {
00759 if (a_term * phi_xl > 0) {
00760 phi_x = (fabs(phi_xl) > fabs(phi_xr)) ? phi_xl : phi_xr;
00761 } else {
00762 phi_x = phi_xr;
00763 }
00764 }
00765 if (a_term * phi_yr > 0) {
00766 phi_y = (a_term * phi_yl > 0) ? phi_yl : 0;
00767 } else {
00768 if (a_term * phi_yl > 0) {
00769 phi_y = (fabs(phi_yl) > fabs(phi_yr)) ? phi_yl : phi_yr;
00770 } else {
00771 phi_y = phi_yr;
00772 }
00773 }
00774 if (a_term * phi_zr > 0) {
00775 phi_z = (a_term * phi_zl > 0) ? phi_zl : 0;
00776 } else {
00777 if (a_term * phi_zl > 0) {
00778 phi_z = (fabs(phi_zl) > fabs(phi_zr)) ? phi_zl : phi_zr;
00779 } else {
00780 phi_z = phi_zr;
00781 }
00782 }
00783 }
00784
00785 };
00786