Exemplo n.º 1
0
real_T bisection2(real_T a, real_T b, real_T tol)
{
  real_T p;
  const mxArray *y;
  static const int32_T iv0[2] = { 1, 16 };

  const mxArray *m0;
  static const char_T cv0[16] = { 'W', 'r', 'o', 'n', 'g', ' ', 'c', 'h', 'o',
    'i', 'c', 'e', ' ', 'b', 'r', 'o' };

  real_T err;

  /*  provide the equation you want to solve with R.H.S = 0 form.  */
  /*  Write the L.H.S by using inline function */
  /*  Give initial guesses. */
  /*  Solves it by method of bisection. */
  /*  A very simple code and very handy! */
  if ((muDoubleScalarPower(a - 1.5, 3.0) + 10.0) * (muDoubleScalarPower(b - 1.5,
        3.0) + 10.0) > 0.0) {
    EMLRTPUSHRTSTACK(&emlrtRSI);
    EMLRTPUSHRTSTACK(&b_emlrtRSI);
    y = NULL;
    m0 = mxCreateCharArray(2, iv0);
    emlrtInitCharArray(16, m0, cv0);
    emlrtAssign(&y, m0);
    error(y, &emlrtMCI);
    EMLRTPOPRTSTACK(&b_emlrtRSI);
    EMLRTPOPRTSTACK(&emlrtRSI);
  } else {
    p = (a + b) / 2.0;
    err = muDoubleScalarAbs(b - a);
    while (err >= tol) {
      if ((muDoubleScalarPower(a - 1.5, 3.0) + 10.0) * (muDoubleScalarPower(p -
            1.5, 3.0) + 10.0) < 0.0) {
        b = p;
      } else {
        a = p;
      }

      p = (a + b) / 2.0;
      err = muDoubleScalarAbs(b - a);
      emlrtBreakCheck();
    }
  }

  return p;
}
void drr_SK_Simplified(const emxArray_boolean_T *voxel_data, const real_T
  voxel_size_mm[3], const real_T detector_dimensions[2], real_T pixel_size_mm,
  const real_T voxel_corner_min[3], const real_T T_carm[16], emxArray_real_T
  *projection)
{
  int32_T ix;
  int32_T i;
  uint32_T voxDim[3];
  real_T voxPlanes__max[3];
  real_T source[3];
  real_T pixel_size_mmel__hn[3];
  real_T pixel_size_mmel__wn[3];
  real_T corner[3];
  real_T b_ix;
  real_T iy;
  int32_T ih;
  int32_T iw;
  real_T tnext[3];
  real_T tstep[3];
  real_T b_voxPlanes__max[3];
  real_T ray_source2pixel[3];
  real_T b_ray_source2pixel[3];
  real_T pixel_point_mm[3];
  real_T t_plane_min[3];
  real_T t_plane_max[3];
  boolean_T exitg8;
  boolean_T exitg7;
  real_T iz;
  boolean_T exitg6;
  real_T t_larger[4];
  boolean_T exitg5;
  boolean_T exitg4;
  boolean_T exitg3;
  real_T t_smaller[4];
  real_T temp;
  int32_T itmp;
  boolean_T exitg2;
  real_T tmax;
  boolean_T exitg1;
  real_T tx;
  real_T ty;
  real_T tz;

  /* function [projection] = drr (voxel_data, voxel_size_mm, detector_dimensions, pixel_size_mm, isocenter_mm, cbct_angles_deg) */
  /* Creates a 2D projection at each cbct_angle of voxel_data. the projection */
  /* axis is defined by the isocenter to which the source and center of */
  /* the detector are aligned. This simulation assumes standard Cone Beam CT */
  /* geometry (source to isocenter distance is 100 cm and source to detector */
  /* distance is 150cm). */
  /*  */
  /* voxel_data: must be a 3 dimensional matrix (typically of CT data) */
  /* voxel_size_mm: a 3 element vector listing the size (in mm) of the voxels */
  /*                along each dimension */
  /* detector_dimension: a 2 element vector listing the dimensions (number of */
  /*                     pixels) in each dimension (u,v) */
  /* pixel_size_mm: a number defining the height and width of each pixel */
  /*                (assumes square pixel) */
  /* isocenter_mm: a 3 element vector pointing from the origin (corner) of the */
  /*               matrix element(1,1,1) to the isocenter */
  /* cbct_angles_deg: a list of angles to generate projections */
  /*  */
  /* Retrun Variable */
  /* projection: a 3D matrix with the 3rd dimension representing the angle of */
  /* roatation */
  /*  */
  /* { */
  /*  Author: Michael M. Folkerts [email protected] */
  /*  Institution: UCSD Physics, UTSW Radiation Oncology */
  /*  Updated: 2014-July. */
  /*  Notes: Siddon's Incremental algorithm | modified to read in 3D matlab matrix | Simplified Input | No guarantees!! */
  /*  */
  /*  References:  */
  /*  R.L. Siddon, */
  /*  "Fast calculation of the exact radiological path for a three-dimensional CT */
  /*  array," Medical Physics 12, 252-255 (1985). */
  /*  */
  /*  F. Jacobs, E. Sundermann, B. De Sutter, M. Christiaens and I. Lemahieu, */
  /*  "A fast algorithm to calculate the exact radiological path through a pixel_size_mmel or voxel space," */
  /*  Journal of Computing and Information Technology 6, 89-94 (1998). */
  /*   */
  /*  G. Han, Z. Liang and J. You, */
  /*  "A fast ray tracing technique for TCT and ECT studies," */
  /*  IEEE Medical Imaging Conference 1999. */
  /* } */
  /*  if(0) */
  /*      voxel_data = OUTPUTgrid; */
  /*      voxel_size_mm = voxel_size; */
  /*      detector_dimensions = detector_dimension; */
  /*      pixel_size_mm = pixel_size; */
  /*      isocenter_mm = isocenter; */
  /*      T_carm: Transformation matrix of C-arm (that is set at the middle of */
  /*              detector & source) with respect to Voxel coordinates */
  /* tic; */
  /* this will verify the size: */
  if (eml_ndims_varsized(*(int32_T (*)[3])voxel_data->size) != 3) {
    EMLRTPUSHRTSTACK(&emlrtRSI);
    error();
    EMLRTPOPRTSTACK(&emlrtRSI);
  }

  /* constants: */
  /* .0001; */
  /* .0001; */
  /* sounce to imager(detector) distance */
  /* source to axis distance %% RRI set the coordinate at the middle between source and the detector */
  /* initialize memory for speed: */
  ix = projection->size[0] * projection->size[1];
  projection->size[0] = (int32_T)emlrtIntegerCheckR2009b
    (emlrtNonNegativeCheckR2009b(detector_dimensions[0], &b_emlrtDCI), &emlrtDCI);
  projection->size[1] = (int32_T)emlrtIntegerCheckR2009b
    (emlrtNonNegativeCheckR2009b(detector_dimensions[1], &d_emlrtDCI),
     &c_emlrtDCI);
  emxEnsureCapacity((emxArray__common *)projection, ix, (int32_T)sizeof(real_T),
                    &emlrtRTEI);
  i = (int32_T)emlrtIntegerCheckR2009b(emlrtNonNegativeCheckR2009b
    (detector_dimensions[0], &f_emlrtDCI), &e_emlrtDCI) * (int32_T)
    emlrtIntegerCheckR2009b(emlrtNonNegativeCheckR2009b(detector_dimensions[1],
    &h_emlrtDCI), &g_emlrtDCI) - 1;
  for (ix = 0; ix <= i; ix++) {
    projection->data[ix] = 0.0;
  }

  for (ix = 0; ix < 3; ix++) {
    voxDim[ix] = (uint32_T)voxel_data->size[ix];
  }

  /* [size(voxel_data,1), size(voxel_data,2), size(voxel_data,3)]; */
  /* difine voxel boundaries: */
  /* vector from origin to source */
  /* vector from origin to CENTER of detector */
  /* define pixel_size_mmel vectors: */
  /* define upper lefthand corner of detector: */
  for (i = 0; i < 3; i++) {
    voxPlanes__max[i] = voxel_corner_min[i] + voxel_size_mm[i] * (real_T)
      voxDim[i];

    /* define up: */
    /* up = [0,0,1]; */
    /*  width of projection image */
    /*  height of projection image */
    /*  direction from the detector to the source */
    /* end initialization timer: */
    /* init_time = toc */
    /* start tracing timer: */
    /* tic; */
    source[i] = 550.0 * T_carm[4 + i] + T_carm[12 + i];
    b_ix = -pixel_size_mm * T_carm[i];

    /*  length of pixel_size_mmel */
    iy = pixel_size_mm * T_carm[8 + i];

    /* vector pointing left, parallel to detector */
    /* define incremental vectors: */
    pixel_size_mmel__hn[i] = -iy;
    pixel_size_mmel__wn[i] = -b_ix;
    corner[i] = (-550.0 * T_carm[4 + i] + T_carm[12 + i]) +
      (detector_dimensions[0] * b_ix + detector_dimensions[1] * iy) / 2.0;
  }

  emlrtForLoopVectorCheckR2011b(1.0, 1.0, detector_dimensions[0], mxDOUBLE_CLASS,
                                (int32_T)detector_dimensions[0], &d_emlrtRTEI,
    &emlrtContextGlobal, 0);
  ih = 0;
  while (ih <= (int32_T)detector_dimensions[0] - 1) {
    /* if(mod(ih,100)==0),fprintf('height:\t%i...\n',ih);end */
    emlrtForLoopVectorCheckR2011b(1.0, 1.0, detector_dimensions[1],
      mxDOUBLE_CLASS, (int32_T)detector_dimensions[1], &c_emlrtRTEI,
      &emlrtContextGlobal, 0);
    iw = 0;
    while (iw <= (int32_T)detector_dimensions[1] - 1) {
      /* ray to be traced */
      /*  find parametrized (t) voxel plane (min or max) intersections: */
      /*  PLANE = P1 + t(P2-P1) */
      /*  SK added */
      /*  t_x = (i-x1) / (x2-x1), t_y = (j-y1) / (y2-y1), t_z = (k-z1) / (z2-z1) */
      for (i = 0; i < 3; i++) {
        b_ix = (corner[i] + ((1.0 + (real_T)ih) - 1.0) * pixel_size_mmel__hn[i])
          + ((1.0 + (real_T)iw) - 1.0) * pixel_size_mmel__wn[i];

        /* ray end point */
        iy = b_ix - source[i];
        tnext[i] = voxel_corner_min[i] - source[i];
        tstep[i] = iy + 2.2250738585072014E-308;
        b_voxPlanes__max[i] = voxPlanes__max[i] - source[i];
        ray_source2pixel[i] = iy + 2.2250738585072014E-308;
        b_ray_source2pixel[i] = iy;
        pixel_point_mm[i] = b_ix;
      }

      rdivide(tnext, tstep, t_plane_min);
      rdivide(b_voxPlanes__max, ray_source2pixel, t_plane_max);

      /*  compute (parametric) intersection values */
      /*  tmin = max { min{tx(0), tx(Nx)}, min{ty(0), ty(Ny)], min{tz(0), tz(Nz)}, 0.0 } */
      /*  tmax = min { max{tx(0), tx(Nx)}, max{ty(0), ty(Ny)], max{tz(0), tz(Nz)}, 1.0 } */
      /* t_larger = [ max([t_plane_min(1), t_plane_max(1)]), max([t_plane_min(2), t_plane_max(2)]), max([t_plane_min(3), t_plane_max(3)]), 1.0 ]; */
      /* t_smaller = [ min([t_plane_min(1), t_plane_max(1)]), min([t_plane_min(2), t_plane_max(2)]), min([t_plane_min(3), t_plane_max(3)]), 0.0 ]; */
      i = 1;
      b_ix = t_plane_min[0];
      if (muDoubleScalarIsNaN(t_plane_min[0])) {
        ix = 2;
        exitg8 = FALSE;
        while ((exitg8 == 0U) && (ix < 3)) {
          i = 2;
          if (!muDoubleScalarIsNaN(t_plane_max[0])) {
            b_ix = t_plane_max[0];
            exitg8 = TRUE;
          } else {
            ix = 3;
          }
        }
      }

      if ((i < 2) && (t_plane_max[0] > b_ix)) {
        b_ix = t_plane_max[0];
      }

      i = 1;
      iy = t_plane_min[1];
      if (muDoubleScalarIsNaN(t_plane_min[1])) {
        ix = 2;
        exitg7 = FALSE;
        while ((exitg7 == 0U) && (ix < 3)) {
          i = 2;
          if (!muDoubleScalarIsNaN(t_plane_max[1])) {
            iy = t_plane_max[1];
            exitg7 = TRUE;
          } else {
            ix = 3;
          }
        }
      }

      if ((i < 2) && (t_plane_max[1] > iy)) {
        iy = t_plane_max[1];
      }

      i = 1;
      iz = t_plane_min[2];
      if (muDoubleScalarIsNaN(t_plane_min[2])) {
        ix = 2;
        exitg6 = FALSE;
        while ((exitg6 == 0U) && (ix < 3)) {
          i = 2;
          if (!muDoubleScalarIsNaN(t_plane_max[2])) {
            iz = t_plane_max[2];
            exitg6 = TRUE;
          } else {
            ix = 3;
          }
        }
      }

      if ((i < 2) && (t_plane_max[2] > iz)) {
        iz = t_plane_max[2];
      }

      t_larger[0] = b_ix;
      t_larger[1] = iy;
      t_larger[2] = iz;
      t_larger[3] = 1.0;
      i = 1;
      b_ix = t_plane_min[0];
      if (muDoubleScalarIsNaN(t_plane_min[0])) {
        ix = 2;
        exitg5 = FALSE;
        while ((exitg5 == 0U) && (ix < 3)) {
          i = 2;
          if (!muDoubleScalarIsNaN(t_plane_max[0])) {
            b_ix = t_plane_max[0];
            exitg5 = TRUE;
          } else {
            ix = 3;
          }
        }
      }

      if ((i < 2) && (t_plane_max[0] < b_ix)) {
        b_ix = t_plane_max[0];
      }

      i = 1;
      iy = t_plane_min[1];
      if (muDoubleScalarIsNaN(t_plane_min[1])) {
        ix = 2;
        exitg4 = FALSE;
        while ((exitg4 == 0U) && (ix < 3)) {
          i = 2;
          if (!muDoubleScalarIsNaN(t_plane_max[1])) {
            iy = t_plane_max[1];
            exitg4 = TRUE;
          } else {
            ix = 3;
          }
        }
      }

      if ((i < 2) && (t_plane_max[1] < iy)) {
        iy = t_plane_max[1];
      }

      i = 1;
      iz = t_plane_min[2];
      if (muDoubleScalarIsNaN(t_plane_min[2])) {
        ix = 2;
        exitg3 = FALSE;
        while ((exitg3 == 0U) && (ix < 3)) {
          i = 2;
          if (!muDoubleScalarIsNaN(t_plane_max[2])) {
            iz = t_plane_max[2];
            exitg3 = TRUE;
          } else {
            ix = 3;
          }
        }
      }

      if ((i < 2) && (t_plane_max[2] < iz)) {
        iz = t_plane_max[2];
      }

      t_smaller[0] = b_ix;
      t_smaller[1] = iy;
      t_smaller[2] = iz;
      t_smaller[3] = 0.0;
      i = 1;
      temp = t_smaller[0];
      itmp = 0;
      if (muDoubleScalarIsNaN(t_smaller[0])) {
        ix = 2;
        exitg2 = FALSE;
        while ((exitg2 == 0U) && (ix < 5)) {
          i = ix;
          if (!muDoubleScalarIsNaN(t_smaller[ix - 1])) {
            temp = t_smaller[ix - 1];
            exitg2 = TRUE;
          } else {
            ix++;
          }
        }
      }

      if (i < 4) {
        while (i + 1 < 5) {
          if (t_smaller[i] > temp) {
            temp = t_smaller[i];
            itmp = i;
          }

          i++;
        }
      }

      i = 1;
      tmax = t_larger[0];
      if (muDoubleScalarIsNaN(t_larger[0])) {
        ix = 2;
        exitg1 = FALSE;
        while ((exitg1 == 0U) && (ix < 5)) {
          i = ix;
          if (!muDoubleScalarIsNaN(t_larger[ix - 1])) {
            tmax = t_larger[ix - 1];
            exitg1 = TRUE;
          } else {
            ix++;
          }
        }
      }

      if (i < 4) {
        while (i + 1 < 5) {
          if (t_larger[i] < tmax) {
            tmax = t_larger[i];
          }

          i++;
        }
      }

      for (ix = 0; ix < 3; ix++) {
        pixel_point_mm[ix] = (real_T)(pixel_point_mm[ix] < source[ix]) * -2.0 +
          1.0;
      }

      if (temp < tmax) {
        /*  if ray intersects volume */
        /* find index for each dimension: */
        for (i = 0; i < 3; i++) {
          b_ix = muDoubleScalarFloor((((b_ray_source2pixel[i] * temp + source[i])
            - voxel_corner_min[i]) + 2.2250738585072014E-308) / voxel_size_mm[i]);

          /* (parametric) intersection values... */
          /* makes 0 or 1 */
          tnext[i] = (voxel_corner_min[i] + ((b_ix + (pixel_point_mm[i] + 1.0) /
            2.0) * voxel_size_mm[i] - source[i])) / (b_ray_source2pixel[i] +
            2.2250738585072014E-308);

          /*  parametric value for next plane intersection */
          iy = voxel_size_mm[i] / (b_ray_source2pixel[i] +
            2.2250738585072014E-308);
          tstep[i] = muDoubleScalarAbs(iy);
          b_ray_source2pixel[i] = iy;
          t_plane_min[i] = b_ix;
        }

        /*  parametric step size */
        /* address special cases... */
        if (temp == t_plane_max[emlrtBoundsCheck(itmp + 1, &c_emlrtBCI) - 1]) {
          /* if intersection is a "max" plane */
          if (itmp + 1 == 1) {
            t_plane_min[0] = (real_T)voxDim[0] - 1.0;
          } else if (itmp + 1 == 2) {
            t_plane_min[1] = (real_T)voxDim[1] - 2.0;
          } else {
            t_plane_min[2] = (real_T)voxDim[2] - 2.0;
          }

          tnext[itmp] = temp + tstep[itmp];

          /* next plane crossing */
        } else {
          t_plane_min[itmp] = 0.0;
          tnext[itmp] = temp + tstep[itmp];

          /* next plane crossing */
        }

        /*  voxel index values(add one for matlab): */
        b_ix = t_plane_min[0] + 1.0;
        iy = t_plane_min[1] + 1.0;
        iz = t_plane_min[2] + 1.0;
        tx = tnext[0];
        ty = tnext[1];
        tz = tnext[2];
        i = 0;

        /* uncomment to generate P-matrix: */
        /* pixel_size_mmNum = 1; */
        /* len = norm(ray_source2pixel); % ray length */
        while ((temp + 0.0001 < tmax) && (!(b_ix * iy * iz == 0.0))) {
          if ((tx < ty) && (tx < tz)) {
            /*  실제 DRR을 그리지 않고, 한점이라도 지나면 해당 점에 포함시킴 */
            if (voxel_data->data[((emlrtDynamicBoundsCheck((int32_T)
                   emlrtIntegerCheckR2009b(b_ix, &o_emlrtDCI), 1,
                   voxel_data->size[0], &j_emlrtBCI) + voxel_data->size[0] *
                                   (emlrtDynamicBoundsCheck((int32_T)
                    emlrtIntegerCheckR2009b(iy, &p_emlrtDCI), 1,
                    voxel_data->size[1], &k_emlrtBCI) - 1)) + voxel_data->size[0]
                                  * voxel_data->size[1] *
                                  (emlrtDynamicBoundsCheck((int32_T)
                   emlrtIntegerCheckR2009b(iz, &q_emlrtDCI), 1, voxel_data->
                   size[2], &l_emlrtBCI) - 1)) - 1]) {
              i = 255;
              tmax = rtMinusInf;
            }

            temp = tx;
            tx += tstep[0];
            b_ix += pixel_point_mm[0];
          } else if (ty < tz) {
            /*  실제 DRR을 그리지 않고, 한점이라도 지나면 해당 점에 포함시킴 */
            if (voxel_data->data[((emlrtDynamicBoundsCheck((int32_T)
                   emlrtIntegerCheckR2009b(b_ix, &l_emlrtDCI), 1,
                   voxel_data->size[0], &g_emlrtBCI) + voxel_data->size[0] *
                                   (emlrtDynamicBoundsCheck((int32_T)
                    emlrtIntegerCheckR2009b(iy, &m_emlrtDCI), 1,
                    voxel_data->size[1], &h_emlrtBCI) - 1)) + voxel_data->size[0]
                                  * voxel_data->size[1] *
                                  (emlrtDynamicBoundsCheck((int32_T)
                   emlrtIntegerCheckR2009b(iz, &n_emlrtDCI), 1, voxel_data->
                   size[2], &i_emlrtBCI) - 1)) - 1]) {
              i = 255;
              tmax = rtMinusInf;
            }

            temp = ty;
            ty += tstep[1];
            iy += pixel_point_mm[1];
          } else {
            /*  실제 DRR을 그리지 않고, 한점이라도 지나면 해당 점에 포함시킴 */
            if (voxel_data->data[((emlrtDynamicBoundsCheck((int32_T)
                   emlrtIntegerCheckR2009b(b_ix, &i_emlrtDCI), 1,
                   voxel_data->size[0], &d_emlrtBCI) + voxel_data->size[0] *
                                   (emlrtDynamicBoundsCheck((int32_T)
                    emlrtIntegerCheckR2009b(iy, &j_emlrtDCI), 1,
                    voxel_data->size[1], &e_emlrtBCI) - 1)) + voxel_data->size[0]
                                  * voxel_data->size[1] *
                                  (emlrtDynamicBoundsCheck((int32_T)
                   emlrtIntegerCheckR2009b(iz, &k_emlrtDCI), 1, voxel_data->
                   size[2], &f_emlrtBCI) - 1)) - 1]) {
              i = 255;
              tmax = rtMinusInf;
            }

            temp = tz;
            tz += tstep[2];
            iz += pixel_point_mm[2];
          }

          emlrtBreakCheck();
        }

        /* end while */
        projection->data[(emlrtDynamicBoundsCheck((int32_T)(1.0 + (real_T)ih), 1,
          projection->size[0], &m_emlrtBCI) + projection->size[0] *
                          (emlrtDynamicBoundsCheck((int32_T)(1.0 + (real_T)iw),
          1, projection->size[1], &n_emlrtBCI) - 1)) - 1] = (real_T)i;
      } else {
        /* if no intersections */
        projection->data[(emlrtDynamicBoundsCheck((int32_T)(1.0 + (real_T)ih), 1,
          projection->size[0], &emlrtBCI) + projection->size[0] *
                          (emlrtDynamicBoundsCheck((int32_T)(1.0 + (real_T)iw),
          1, projection->size[1], &b_emlrtBCI) - 1)) - 1] = 0.0;
      }

      /* if intersections */
      /* uncomment to generate P-matrix: */
      /* rayCount = rayCount + 1; */
      iw++;
      emlrtBreakCheck();
    }

    /* width */
    /* fprintf('\n'); */
    ih++;
    emlrtBreakCheck();
  }

  /* height */
  /* uncomment to generate P-matrix: */
  /* matrix = matrix(1:mtxCount-1,:); */
  /* stop trace timer: */
  /* trace_time = toc */
  /* fprintf('\n') */
  /* function */
  /* } */
}