123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563 |
- #include "mex.h"
- #include <stdio.h>
- #include <stdlib.h>
- #include <malloc.h>
- #include <math.h>
- #include <string.h>
- #define SUCCESS 1
- #define FAILURE 0
- #define GRIDIND3D(x,y,z,dim) ((x) + dim[0]*(y) + dim[0]*dim[1]*(z))
- typedef struct
- {
- float x;
- float y;
- float z;
- } POINT;
- typedef struct
- {
- POINT start;
- POINT inc;
- int x_count;
- int y_count;
- int z_count;
- float *matrix;
- } FLOAT_GRID;
- #define GRID_VALUE(GRID_ptr, i, j, k)\
- ((GRID_ptr)->matrix[(i) +\
- (GRID_ptr)->x_count *\
- ((j) + ((k) * (GRID_ptr)->y_count))])
- #define DENS (prhs[0])
- #define START (prhs[1])
- #define INC (prhs[2])
- #define POINT1 (prhs[3])
- #define POINT2 (prhs[4])
- #define INDVISITED (plhs[0])
- #define DEFFVISITED (plhs[1])
- int raytrace(FLOAT_GRID *,POINT,POINT,int *, float *, int *);
- double round(double);
- char errstr[200];
- void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
- {
-
- int k,M,N,Q;
-
- const int *densDim,*startDim,*incDim,*p1Dim,*p2Dim;
- float *densPtr,*startPtr,*incPtr,*p1Ptr,*p2Ptr;
- int *indVisitedPtr;
- float *deffVisitedPtr;
- int dims[2];
- int *indVisited;
- float *deffVisited;
- int maxVisited;
- int Nvisited;
-
- POINT p1;
- POINT p2;
-
- FLOAT_GRID dens;
-
-
- densDim = mxGetDimensions(DENS);
- startDim = mxGetDimensions(START);
- incDim = mxGetDimensions(INC);
- p1Dim = mxGetDimensions(POINT1);
- p2Dim = mxGetDimensions(POINT2);
-
- if ( ((mxGetNumberOfDimensions(DENS) != 2) && (mxGetNumberOfDimensions(DENS) != 3))
- || (mxGetClassID(DENS) != mxSINGLE_CLASS))
- mexErrMsgTxt("DENS must be a 3-D float array.");
-
- if ( (mxGetNumberOfDimensions(START) != 2)
- || (mxGetClassID(START) != mxSINGLE_CLASS)
- || (startDim[0]*startDim[1] != 3))
- mexErrMsgTxt("START must be a 3-element float vector.");
-
- if ( (mxGetNumberOfDimensions(INC) != 2)
- || (mxGetClassID(INC) != mxSINGLE_CLASS)
- || (incDim[0]*incDim[1] != 3))
- mexErrMsgTxt("INC must be a 3-element float vector.");
- if ( (mxGetNumberOfDimensions(POINT1) != 2)
- || (mxGetClassID(POINT1) != mxSINGLE_CLASS)
- || (p1Dim[0]*p1Dim[1] != 3))
- mexErrMsgTxt("POINT1 must be a 3-element float vector.");
- if ( (mxGetNumberOfDimensions(POINT2) != 2)
- || (mxGetClassID(POINT2) != mxSINGLE_CLASS)
- || (p2Dim[0]*p2Dim[1] != 3))
- mexErrMsgTxt("POINT2 must be a 3-element float vector.");
-
- densPtr = (float *)mxGetData(DENS);
- startPtr = (float *)mxGetData(START);
- incPtr = (float *)mxGetData(INC);
- p1Ptr = (float *)mxGetData(POINT1);
- p2Ptr = (float *)mxGetData(POINT2);
-
-
- M = densDim[0];
- N = densDim[1];
- if (mxGetNumberOfDimensions(DENS) == 3)
- Q = densDim[2];
- else
- Q = 1;
-
-
- maxVisited = (int)(2*sqrt((double)(M*M+N*N+Q*Q)) + 1);
- indVisited = (int *)malloc(sizeof(int)*maxVisited);
- deffVisited = (float *)malloc(sizeof(int)*maxVisited);
- for (k=0;k<maxVisited;k++)
- {
- indVisited[k] = 0;
- deffVisited[k] = 0.0;
- }
-
-
-
- dens.matrix = densPtr;
- dens.start.x = startPtr[0];
- dens.start.y = startPtr[1];
- dens.start.z = startPtr[2];
- dens.inc.x = incPtr[0];
- dens.inc.y = incPtr[1];
- dens.inc.z = incPtr[2];
- dens.x_count = M;
- dens.y_count = N;
- dens.z_count = Q;
-
- p1.x = p1Ptr[0];
- p1.y = p1Ptr[1];
- p1.z = p1Ptr[2];
- p2.x = p2Ptr[0];
- p2.y = p2Ptr[1];
- p2.z = p2Ptr[2];
-
- if (raytrace(&dens,p1,p2,indVisited,deffVisited,&Nvisited) == FAILURE)
- mexErrMsgTxt(errstr);
- dims[0] = 1;
- dims[1] = Nvisited;
-
-
- INDVISITED = mxCreateNumericArray(2,dims,mxINT32_CLASS,mxREAL);
- DEFFVISITED = mxCreateNumericArray(2,dims,mxSINGLE_CLASS,mxREAL);
-
- indVisitedPtr = (int *)mxGetData(INDVISITED);
- deffVisitedPtr = (float *)mxGetData(DEFFVISITED);
-
- for (k=0;k<Nvisited;k++)
- {
- indVisitedPtr[k] = indVisited[k];
- deffVisitedPtr[k] = deffVisited[k];
- }
- }
- extern char errstr[200];
- int raytrace(FLOAT_GRID *electron_density_grid,POINT point1,POINT point2,
- int *indVisited, float *deffVisited, int *Nvisited)
- {
- float x1,y1,z1,
- x2,y2,z2,
- xp1,yp1,zp1,
- dx,dy,dz;
- int Nx,Ny,Nz;
- float xpN, ypN, zpN;
- float alpha_x_min,alpha_y_min,alpha_z_min,alpha_x_max,alpha_y_max,alpha_z_max;
-
- float alpha_min, alpha_max;
- int i_min,i_max,j_min,j_max,k_min,k_max;
- float *alpha_x,*alpha_y,*alpha_z;
- float *alpha;
- int i_index,j_index,k_index;
- int a;
- int max_index;
- float d12;
- float alpha_mid;
- float length;
- int i,j,k;
- float rpl = 0.0;
- float voxel_density;
- float lmax;
- float pnorm;
- x1 = point1.x;
- y1 = point1.y;
- z1 = point1.z;
- x2 = point2.x;
- y2 = point2.y;
- z2 = point2.z;
- Nx = electron_density_grid->x_count + 1;
- Ny = electron_density_grid->y_count + 1;
- Nz = electron_density_grid->z_count + 1;
- dx = electron_density_grid->inc.x;
- dy = electron_density_grid->inc.y;
- dz = electron_density_grid->inc.z;
- xp1 = electron_density_grid->start.x - (float)0.5*dx;
- yp1 = electron_density_grid->start.y - (float)0.5*dy;
- zp1 = electron_density_grid->start.z - (float)0.5*dz;
- pnorm = (float)sqrt((x2-x1)*(x2-x1) + (y2-y1)*(y2-y1) + (z2-z1)*(z2-z1));
- lmax = (float)sqrt(pow((x2-x1)*dx,2.0f)+pow((y2-y1)*dy,2.0f)+pow((z2-z1)*dz,2.0f))/pnorm;
- xpN = xp1 + (Nx-1)*dx;
- ypN = yp1 + (Ny-1)*dy;
- zpN = zp1 + (Nz-1)*dz;
- if (x1==x2)
- x2 += 0.00001;
- if (y1==y2)
- y2 += 0.00001;
- if (z1==z2)
- z2 += 0.00001;
- if ((fabs(x1-x2)<dx) && (fabs(y1-y2)<dy) && (fabs(z1-z2)<dz))
- {
- sprintf(errstr,"Error - ray trace region too small.");
- return(FAILURE);
- }
- alpha_x_min = (((xp1-x1)/(x2-x1))<((xpN-x1)/(x2-x1))) ? ((xp1-x1)/(x2-x1))
- : ((xpN-x1)/(x2-x1));
- alpha_y_min = (((yp1-y1)/(y2-y1))<((ypN-y1)/(y2-y1))) ? ((yp1-y1)/(y2-y1))
- : ((ypN-y1)/(y2-y1));
- alpha_z_min = (((zp1-z1)/(z2-z1))<((zpN-z1)/(z2-z1))) ? ((zp1-z1)/(z2-z1))
- : ((zpN-z1)/(z2-z1));
- alpha_x_max = (((xp1-x1)/(x2-x1))>((xpN-x1)/(x2-x1))) ? ((xp1-x1)/(x2-x1))
- : ((xpN-x1)/(x2-x1));
- alpha_y_max = (((yp1-y1)/(y2-y1))>((ypN-y1)/(y2-y1))) ? ((yp1-y1)/(y2-y1))
- : ((ypN-y1)/(y2-y1));
- alpha_z_max = (((zp1-z1)/(z2-z1))>((zpN-z1)/(z2-z1))) ? ((zp1-z1)/(z2-z1))
- : ((zpN-z1)/(z2-z1));
- alpha_min = (alpha_x_min>alpha_y_min) ? alpha_x_min : alpha_y_min;
- if (alpha_z_min>alpha_min)
- alpha_min = alpha_z_min;
- if (alpha_min<0)
- alpha_min = 0;
- alpha_max = (alpha_x_max<alpha_y_max) ? alpha_x_max : alpha_y_max;
- if (alpha_z_max<alpha_max)
- alpha_max = alpha_z_max;
- if (alpha_max>1)
- alpha_max = 1;
-
- i_min = (x2>x1) ? (int) ceil((float) Nx - (xpN-alpha_min*(x2-x1)-x1)/dx-0.001)
- : (int) ceil((float) Nx - (xpN-alpha_max*(x2-x1)-x1)/dx-0.001);
- i_max = (x2>x1) ? (int) floor(1.0000 + (x1+alpha_max*(x2-x1)-xp1)/dx+0.001)
- : (int) floor(1.0000 + (x1+alpha_min*(x2-x1)-xp1)/dx+0.001);
- j_min = (y2>y1) ? (int) ceil((float) Ny - (ypN-alpha_min*(y2-y1)-y1)/dy-0.001)
- : (int) ceil((float) Ny - (ypN-alpha_max*(y2-y1)-y1)/dy-0.001);
- j_max = (y2>y1) ? (int) floor(1.0000 + (y1+alpha_max*(y2-y1)-yp1)/dy+0.001)
- : (int) floor(1.0000 + (y1+alpha_min*(y2-y1)-yp1)/dy+0.001);
- k_min = (z2>z1) ? (int) ceil((float) Nz - (zpN-alpha_min*(z2-z1)-z1)/dz-0.001)
- : (int) ceil((float) Nz - (zpN-alpha_max*(z2-z1)-z1)/dz-0.001);
- k_max = (z2>z1) ? (int) floor(1.0000 + (z1+alpha_max*(z2-z1)-zp1)/dz+0.001)
- : (int) floor(1.0000 + (z1+alpha_min*(z2-z1)-zp1)/dz+0.001);
- if ( i_max - i_min + 1 < 0 || i_max - i_min + 1 > Nx
- || j_max - j_min + 1 < 0 || j_max - j_min + 1 > Ny
- || k_max - k_min + 1 < 0 || k_max - k_min + 1 > Nz)
- {
- *Nvisited = 0;
- return(SUCCESS);
- }
- if ((alpha_x = (float*) calloc(Nx+1,sizeof(float))) == NULL)
- {
- sprintf(errstr,"Error - insufficient heap for alpha_x allocation.");
- return(FAILURE);
- }
- if ((alpha_y = (float*) calloc(Ny+1,sizeof(float))) == NULL)
- {
- sprintf(errstr,"Error - insufficient heap for alpha_y allocation.");
- return(FAILURE);
- }
- if ((alpha_z = (float*) calloc(Nz+1,sizeof(float))) == NULL)
- {
- sprintf(errstr,"Error - insufficient heap for alpha_z allocation.");
- return(FAILURE);
- }
-
- if (i_min <= i_max)
- if (x2>x1)
- {
- alpha_x[0] = ((xp1+(i_min-1)*dx)-x1)/(x2-x1);
- for (a=1;a<=i_max-i_min;a++)
- alpha_x[a] = alpha_x[a-1]+dx/(x2-x1);
- }
- else
- {
- alpha_x[i_max-i_min] = ((xp1+(i_min-1)*dx)-x1)/(x2-x1);
- for (a=i_max-i_min-1;a>=0;a--)
- alpha_x[a] = alpha_x[a+1]+(dx/(x2-x1));
- }
- alpha_x[i_max-i_min+1] = 10000.0;
- if (j_min <= j_max)
- if (y2>y1)
- {
- alpha_y[0] = ((yp1+(j_min-1)*dy)-y1)/(y2-y1);
- for (a=1;a<=j_max-j_min;a++)
- alpha_y[a] = alpha_y[a-1]+dy/(y2-y1);
- }
- else
- {
- alpha_y[j_max-j_min] = ((yp1+(j_min-1)*dy)-y1)/(y2-y1);
- for (a=j_max-j_min-1;a>=0;a--)
- alpha_y[a] = alpha_y[a+1]+(dy/(y2-y1));
- }
- alpha_y[j_max-j_min+1] = 10001.0;
- if (k_min <= k_max)
- if (z2>z1)
- {
- alpha_z[0] = ((zp1+(k_min-1)*dz)-z1)/(z2-z1);
- for (a=1;a<=k_max-k_min;a++)
- alpha_z[a] = alpha_z[a-1]+(dz/(z2-z1));
- }
- else
- {
- alpha_z[k_max-k_min] = ((zp1+(k_min-1)*dz)-z1)/(z2-z1);
- for (a=k_max-k_min-1;a>=0;a--)
- alpha_z[a] = alpha_z[a+1]+(dz/(z2-z1));
- }
- alpha_z[k_max-k_min+1] = 10002.0;
- if ((alpha = (float*) calloc(Nx+Ny+Nz+3,sizeof(float))) == NULL)
- {
- sprintf(errstr,"Error - insufficient heap for alpha allocation.");
- return(FAILURE);
- }
- max_index = (i_max-i_min+1)+(j_max-j_min+1)+(k_max-k_min+1)+1;
- alpha[0] = alpha_min;
- i_index = 0;
- j_index = 0;
- k_index = 0;
- for (a=1;a<=max_index-1;a++)
- if (alpha_x[i_index]<alpha_y[j_index])
- if (alpha_x[i_index]<alpha_z[k_index])
- {
- alpha[a] = alpha_x[i_index];
- i_index += 1;
- }
- else
- {
- alpha[a] = alpha_z[k_index];
- k_index += 1;
- }
- else
- if (alpha_y[j_index]<alpha_z[k_index])
- {
- alpha[a] = alpha_y[j_index];
- j_index += 1;
- }
- else
- {
- alpha[a] = alpha_z[k_index];
- k_index += 1;
- }
- alpha[max_index] = alpha_max;
- free(alpha_x);
- free(alpha_y);
- free(alpha_z);
- d12 = sqrt((x2-x1)*(x2-x1)+(y2-y1)*(y2-y1)+(z2-z1)*(z2-z1));
-
- *Nvisited = 0;
- for (a=1;a<=max_index;a++)
- {
- length = d12*(alpha[a]-alpha[a-1]);
- if (fabs(length)>0.01)
- {
- alpha_mid = (alpha[a]+alpha[a-1])/2.0;
-
- i = (int) round((x1 + alpha_mid*(x2-x1) - xp1)/dx - 0.5);
- j = (int) round((y1 + alpha_mid*(y2-y1) - yp1)/dy - 0.5);
- k = (int) round((z1 + alpha_mid*(z2-z1) - zp1)/dz - 0.5);
-
-
- if (i>=0 && i<Nx-1 && j>=0 && j<Ny-1 && k>=0 && k<Nz-1)
- {
- voxel_density = GRID_VALUE(electron_density_grid,i,j,k);
- rpl += length * voxel_density/2.0;
-
-
-
-
- indVisited[*Nvisited] = i + j*electron_density_grid->x_count
- + k*electron_density_grid->x_count*electron_density_grid->y_count+1;
- deffVisited[*Nvisited] = rpl;
- (*Nvisited)++;
- rpl += length * voxel_density/2.0;
- }
- }
- }
- free(alpha);
- return(SUCCESS);
- }
- double round(double x)
- {
- static double xfl;
- xfl = floor((double)x);
- if ( ((double)x - xfl) >= 0.5)
- return(xfl + 1.0);
- else
- return(xfl);
- }
|