Esempio n. 1
0
void Compute_Eig_Dec_3D(int npixels, double *Dxx, double *Dxy, double *Dxz, double *Dyy, double *Dyz, double *Dzz, 
    double *Dvec1x, double *Dvec1y, double *Dvec1z, double *Dvec2x, double *Dvec2y, double *Dvec2z, double *Dvec3x, double *Dvec3y, double *Dvec3z,
    double *Deiga, double *Deigb, double *Deigc)
{
    double Ma[3][3];
    double Davec[3][3];
    double Daeig[3];
    
    /* Loop variable */
    int i;
    
	for(i=0; i<npixels; i++)
	{
        Ma[0][0]=Dxx[i]; Ma[0][1]=Dxy[i]; Ma[0][2]=Dxz[i];
        Ma[1][0]=Dxy[i]; Ma[1][1]=Dyy[i]; Ma[1][2]=Dyz[i];
        Ma[2][0]=Dxz[i]; Ma[2][1]=Dyz[i]; Ma[2][2]=Dzz[i];
        eigen_decomposition(Ma, Davec, Daeig);
        Deiga[i]=Daeig[0]; Deigb[i]=Daeig[1]; Deigc[i]=Daeig[2];
        /* Main direction (smallest eigenvector) */
        Dvec1x[i] = Davec[0][0]; 
        Dvec1y[i] = Davec[1][0]; 
        Dvec1z[i] = Davec[2][0];
        Dvec2x[i] = Davec[0][1]; 
        Dvec2y[i] = Davec[1][1]; 
        Dvec2z[i] = Davec[2][1];
        Dvec3x[i] = Davec[0][2]; 
        Dvec3y[i] = Davec[1][2]; 
        Dvec3z[i] = Davec[2][2];
	}
}
Esempio n. 2
0
void	mat3 :: mat3GetEigen ( float l [3], vec3 e [3] ) const
{
	double	      a [3][3];
	double        d [3];
	double        v [3][3];
	double      * aPtr = (double *)a;
	const float * mPtr = m;

	for ( int i = 0; i < 9; i++ )
		*aPtr++ = (double) *mPtr++;

	eigen_decomposition ( a, v, d );

	l [0] = (float) d [0];
	l [1] = (float) d [1];
	l [2] = (float) d [2];

	e [0].x = (float) v [0][0];
	e [0].y = (float) v [0][1];
	e [0].z = (float) v [0][2];

	e [1].x = (float) v [1][0];
	e [1].y = (float) v [1][1];
	e [1].z = (float) v [1][2];

	e [2].x = (float) v [2][0];
	e [2].y = (float) v [2][1];
	e [2].z = (float) v [2][2];
}
Esempio n. 3
0
  int matrix_square_root_n(int n, double *X, double *I, double *Y) {

    /*
      This function calculates one of the square roots of the matrix X and stores it in Y:
      X = sqrt(Y);
      X needs to be a symmetric positive definite matrix of dimension n*n in Fortran vector
      format. Y is of course a vector of similar size, and will contain the result on exit.
      Y will be used as a workspace variable in the meantime.
      The variable I is a vector of length n containing +1 and -1 elements. It can be used
      to select one of the 2^n different square roots of X
      This function first calculates the eigenvalue decomposition of X: X = U*D*U^T
      A new matrix F is then calculated with on the diagonal the square roots of D, with
      signs taken from I.
      The square root is then obtained by calculating U*F*U^T
    */

    if (check_input(X, Y, "matrix_square_root_n")) return 1;

    double *eigval, *eigvec, *temp;
    int info = 0, i, j;

    /* Memory allocation */
    eigval=(double*) malloc(n*sizeof(double));
    eigvec=(double*) malloc(n*n*sizeof(double));
    temp=(double*) malloc(n*n*sizeof(double));
    if ((eigval==NULL)||(eigvec==NULL)||(temp==NULL)) {
      printf("malloc failed in matrix_square_root_n\n");
      return 2;
    }

    /* Eigen decomposition */
    info=eigen_decomposition(n, X, eigvec, eigval);
    if (info != 0) return info;

    /* Check for positive definitiveness*/
    for (i=0; i<n; i++) if (eigval[i]<0) {
	fprintf(stderr, "In matrix_square_root_n: Matrix is not positive definite.\n");
	return 1;
      }

    /* Build square rooted diagonal matrix, with sign signature I */
    for (i=0; i<n; i++) for (j=0; j<n; j++) Y[i*n+j] = 0.0;
    for (i=0; i<n; i++) Y[i*n+i] = I[i]*sqrt(eigval[i]);

    /* Multiply the eigenvectors with this diagonal matrix Y. Store back in Y */
    matrix_matrix_mult(n, n, n, 1.0, 0, eigvec, Y, temp);
    vector_copy(n*n, temp, Y);

    /* Transpose eigenvectors. Store in temp */
    matrix_transpose(n, n, eigvec, temp);

    /* Multiply Y with this temp. Store in eigvec which is no longer required. Copy to Y */
    matrix_matrix_mult(n, n, n, 1.0, 0, Y, temp, eigvec);
    vector_copy(n*n, eigvec, Y);

    /* Cleanup and exit */
    free(eigvec); free(eigval); free(temp);
    return info;
  }
Esempio n. 4
0
// Decompose a covariance matrix [a] into a rotation matrix [r] and a diagonal
// matrix [d] such that a = r d r^T.
void pf_matrix_unitary (pf_matrix_t* r, pf_matrix_t* d, pf_matrix_t a)
{
    int i, j;
    /*
    gsl_matrix *aa;
    gsl_vector *eval;
    gsl_matrix *evec;
    gsl_eigen_symmv_workspace *w;

    aa = gsl_matrix_alloc(3, 3);
    eval = gsl_vector_alloc(3);
    evec = gsl_matrix_alloc(3, 3);
    */

    double aa[3][3];
    double eval[3];
    double evec[3][3];

    for (i = 0; i < 3; i++)
    {
        for (j = 0; j < 3; j++)
        {
            //gsl_matrix_set(aa, i, j, a.m[i][j]);
            aa[i][j] = a.m[i][j];
        }
    }

    // Compute eigenvectors/values
    /*
    w = gsl_eigen_symmv_alloc(3);
    gsl_eigen_symmv(aa, eval, evec, w);
    gsl_eigen_symmv_free(w);
    */

    eigen_decomposition (aa, evec, eval);

    *d = pf_matrix_zero();

    for (i = 0; i < 3; i++)
    {
        //d->m[i][i] = gsl_vector_get(eval, i);
        d->m[i][i] = eval[i];

        for (j = 0; j < 3; j++)
        {
            //r->m[i][j] = gsl_matrix_get(evec, i, j);
            r->m[i][j] = evec[i][j];
        }
    }

    //gsl_matrix_free(evec);
    //gsl_vector_free(eval);
    //gsl_matrix_free(aa);

    return;
}
Esempio n. 5
0
// This routine was written by Jernej Barbic.
void eigen_sym(Mat3d & a, Vec3d & eig_val, Vec3d eig_vec[3])
{
  double A[3][3] = { {a[0][0], a[0][1], a[0][2]},
                     {a[1][0], a[1][1], a[1][2]},
                     {a[2][0], a[2][1], a[2][2]} };
  double V[3][3];
  double d[3];
  eigen_decomposition(A, V, d);

  eig_val = Vec3d(d[2],d[1],d[0]);
  if(eig_vec)
  {
    eig_vec[0] = Vec3d(V[0][2], V[1][2], V[2][2]);
    eig_vec[1] = Vec3d(V[0][1], V[1][1], V[2][1]);
    eig_vec[2] = Vec3d(V[0][0], V[1][0], V[2][0]);
  }
}
Esempio n. 6
0
int sqrtm(const dgematrix &A, dgematrix & sqrtA)
{
      dgematrix P,D;
      int i;
      
      if (!eigen_decomposition(A,P,D))
            {
                  for (i=0;i<D.m; i++)
                        D(i,i)=sqrt(fabs(D(i,i)));
                  sqrtA = P * D * t(P);
                  return 0;
            }
      else
            {
                  cerr<<"BFilt :: SQRTM Problem."<<endl;
                  return 1;
            }
}
Esempio n. 7
0
// Add Tompson
void getSymMatEigenvectors(double3 * ret, const double3x3 &A)
{
	double inputA[3][3];
	double outputEigVec[3][3];
	double outputEigVal[3];

	inputA[0][0] = A[0][0]; inputA[0][1] = A[0][1]; inputA[0][2] = A[0][2];
	inputA[1][0] = A[1][0]; inputA[1][1] = A[1][1]; inputA[1][2] = A[1][2];
	inputA[2][0] = A[2][0]; inputA[2][1] = A[2][1]; inputA[2][2] = A[2][2];

	eigen_decomposition(inputA, outputEigVec, outputEigVal);

	// The eigen vectors are colonm-wise in the return vector --> Verified with matlab
	// Transforming <1,0,0> with the return matrix gives us the column of the origional matrix (which suggests I am correct).
	ret[0].x = outputEigVec[0][0]; ret[0].y = outputEigVec[1][0]; ret[0].z = outputEigVec[2][0];
	ret[1].x = outputEigVec[0][1]; ret[1].y = outputEigVec[1][1]; ret[1].z = outputEigVec[2][1];
	ret[2].x = outputEigVec[0][2]; ret[2].y = outputEigVec[1][2]; ret[2].z = outputEigVec[2][2];
}
Esempio n. 8
0
int sqrtm(const dsymatrix &A, dgematrix & sqrtA)
{
      dgematrix P,D;
      int i;
      
      if (!cholesky(A,sqrtA))
            {
                  return 0;
            }
      if (!eigen_decomposition(A,P,D))
            {
                  for (i=0;i<D.m; i++)
                        {
                              D(i,i)=sqrt(fabs(D(i,i)));
                        }
                  sqrtA = P * D * t(P);
                  return 0;
            }
      
      cerr<<"BFilt :: SQRTM Problem."<<endl;
      return 1;
}
Esempio n. 9
0
void GaussianDistribution::updateParameters(glm::vec3 m, glm::mat3 c) {
    _mean = m;
    _cov = c;
    det = glm::determinant(_cov);
    firstTerm = glm::sqrt(glm::pow(2 * 3.14159265359f, 3.0f) * det);
    inv = glm::inverse(_cov);

    double A[3][3];
    double V[3][3];
    double d[3];

    for (int i=0; i<3; i++)
        for (int j=0; j<3; j++)
            A[i][j] = _cov[i][j];
    eigen_decomposition(A, V, d);

    _U = glm::mat3(V[0][0], V[0][1], V[0][2], V[1][0], V[1][1], V[1][2], V[2][0], V[2][1], V[2][2]);
    _sqrtsig = glm::mat3(sqrt(d[0]), 0, 0, 0, sqrt(d[1]), 0, 0, 0, sqrt(d[2]));

    // mozda bitno!
    _U = glm::transpose(_U);
}
Esempio n. 10
0
void mexFunction( int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[] ) {
    double *Dxx, *Dxy, *Dxz, *Dyy, *Dyz, *Dzz;
    double *Dvecx, *Dvecy, *Dvecz, *Deiga, *Deigb, *Deigc;

    float *Dxx_f, *Dxy_f, *Dxz_f, *Dyy_f, *Dyz_f, *Dzz_f;
    float *Dvecx_f, *Dvecy_f, *Dvecz_f, *Deiga_f, *Deigb_f, *Deigc_f;

    mwSize output_dims[2]={1, 3};
    double Ma[3][3];
    double Davec[3][3];
    double Daeig[3];
    
    /* Loop variable */
    int i;
    
    /* Size of input */
    const mwSize *idims;
    int nsubs=0;
    
    /* Number of pixels */
    int npixels=1;
    
    /* Check for proper number of arguments. */
    if(nrhs!=6) {
        mexErrMsgTxt("Six inputs are required.");
    } else if(nlhs<3) {
        mexErrMsgTxt("Three or Six outputs are required");
    }
    
   
    /*  Get the number of dimensions */
    nsubs = mxGetNumberOfDimensions(prhs[0]);
    /* Get the sizes of the inputs */
    idims = mxGetDimensions(prhs[0]);
    for (i=0; i<nsubs; i++) { npixels=npixels*idims[i]; }
    
    if(mxGetClassID(prhs[0])==mxDOUBLE_CLASS) {
       /* Assign pointers to each input. */
        Dxx = (double *)mxGetPr(prhs[0]);
        Dxy = (double *)mxGetPr(prhs[1]);
        Dxz = (double *)mxGetPr(prhs[2]);
        Dyy = (double *)mxGetPr(prhs[3]);
        Dyz = (double *)mxGetPr(prhs[4]);
        Dzz = (double *)mxGetPr(prhs[5]);

        /* Assign pointers to each output. */
        plhs[0] = mxCreateNumericArray(nsubs, idims, mxDOUBLE_CLASS, mxREAL);
        plhs[1] = mxCreateNumericArray(nsubs, idims, mxDOUBLE_CLASS, mxREAL);
        plhs[2] = mxCreateNumericArray(nsubs, idims, mxDOUBLE_CLASS, mxREAL);
        Deiga = mxGetPr(plhs[0]); Deigb = mxGetPr(plhs[1]); Deigc = mxGetPr(plhs[2]);
        if(nlhs==6) {
            /* Main direction (larged eigenvector) */
            plhs[3] = mxCreateNumericArray(nsubs, idims, mxDOUBLE_CLASS, mxREAL);
            plhs[4] = mxCreateNumericArray(nsubs, idims, mxDOUBLE_CLASS, mxREAL);
            plhs[5] = mxCreateNumericArray(nsubs, idims, mxDOUBLE_CLASS, mxREAL);
            Dvecx = mxGetPr(plhs[3]); Dvecy = mxGetPr(plhs[4]); Dvecz = mxGetPr(plhs[5]);
        }
        
        
        for(i=0; i<npixels; i++) {
            Ma[0][0]=Dxx[i]; Ma[0][1]=Dxy[i]; Ma[0][2]=Dxz[i];
            Ma[1][0]=Dxy[i]; Ma[1][1]=Dyy[i]; Ma[1][2]=Dyz[i];
            Ma[2][0]=Dxz[i]; Ma[2][1]=Dyz[i]; Ma[2][2]=Dzz[i];
            eigen_decomposition(Ma, Davec, Daeig);
            Deiga[i]=Daeig[0]; Deigb[i]=Daeig[1]; Deigc[i]=Daeig[2];
            if(nlhs==6) {
                /* Main direction (smallest eigenvector) */
                Dvecx[i]=Davec[0][0];
                Dvecy[i]=Davec[1][0];
                Dvecz[i]=Davec[2][0];
            }
        }
    }
    else if(mxGetClassID(prhs[0])==mxSINGLE_CLASS) {
       /* Assign pointers to each input. */
        Dxx_f = (float *)mxGetPr(prhs[0]);
        Dxy_f = (float *)mxGetPr(prhs[1]);
        Dxz_f = (float *)mxGetPr(prhs[2]);
        Dyy_f = (float *)mxGetPr(prhs[3]);
        Dyz_f = (float *)mxGetPr(prhs[4]);
        Dzz_f = (float *)mxGetPr(prhs[5]);

        /* Assign pointers to each output. */
        plhs[0] = mxCreateNumericArray(nsubs, idims, mxSINGLE_CLASS, mxREAL);
        plhs[1] = mxCreateNumericArray(nsubs, idims, mxSINGLE_CLASS, mxREAL);
        plhs[2] = mxCreateNumericArray(nsubs, idims, mxSINGLE_CLASS, mxREAL);
        Deiga_f  = (float *)mxGetPr(plhs[0]); 
        Deigb_f  = (float *)mxGetPr(plhs[1]); 
        Deigc_f  = (float *)mxGetPr(plhs[2]);
        if(nlhs==6) {
            /* Main direction (smallest eigenvector) */
            plhs[3] = mxCreateNumericArray(nsubs, idims, mxSINGLE_CLASS, mxREAL);
            plhs[4] = mxCreateNumericArray(nsubs, idims, mxSINGLE_CLASS, mxREAL);
            plhs[5] = mxCreateNumericArray(nsubs, idims, mxSINGLE_CLASS, mxREAL);
            Dvecx_f  = (float *)mxGetPr(plhs[3]); 
            Dvecy_f  = (float *)mxGetPr(plhs[4]); 
            Dvecz_f  = (float *)mxGetPr(plhs[5]);
        }
        
        
        for(i=0; i<npixels; i++) {
            Ma[0][0]=(double)Dxx_f[i]; Ma[0][1]=(double)Dxy_f[i]; Ma[0][2]=(double)Dxz_f[i];
            Ma[1][0]=(double)Dxy_f[i]; Ma[1][1]=(double)Dyy_f[i]; Ma[1][2]=(double)Dyz_f[i];
            Ma[2][0]=(double)Dxz_f[i]; Ma[2][1]=(double)Dyz_f[i]; Ma[2][2]=(double)Dzz_f[i];
            eigen_decomposition(Ma, Davec, Daeig);
            Deiga_f[i]=(float)Daeig[0]; 
            Deigb_f[i]=(float)Daeig[1]; 
            Deigc_f[i]=(float)Daeig[2];
            if(nlhs==6) {
                /* Main direction (smallest eigenvector) */
                Dvecx_f[i]=(float)Davec[0][0]; 
                Dvecy_f[i]=(float)Davec[1][0]; 
                Dvecz_f[i]=(float)Davec[2][0];
            }
        }

    }
}
void mexFunction( int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[] ) {
    float *Dxx, *Dxy, *Dxz, *Dyy, *Dyz, *Dzz;
    float *Jxx, *Jxy, *Jxz, *Jyy, *Jyz, *Jzz;

    /* Matrices of Eigenvector calculation */
    double Ma[3][3];
    double Davec[3][3];
    double Daeig[3];
    
    /* Eigenvector and eigenvalues as scalars */
    double mu1, mu2, mu3, v1x, v1y, v1z, v2x, v2y, v2z, v3x, v3y, v3z;
    
    /* Amplitudes of diffustion tensor */
    double lambda1, lambda2, lambda3;
      
    /* Constants used in diffusion tensor calculation */
    double alpha, C, m;

    /* Denominator  */
    double di;
    /* Eps for finite values */
    float eps=(float)1e-20;
        

    /* Used to read Options structure */
    double *OptionsField;
    int field_num;
    
    /* Loop variable */
    int i;
    
    /* Size of input */
    const mwSize *idims;
    int nsubs=0;
    
    /* Number of pixels */
    int npixels=1;
    
    /* Check for proper number of arguments. */
    if(nrhs!=7) {
        mexErrMsgTxt("Seven inputs are required.");
    } else if(nlhs!=6) {
        mexErrMsgTxt("Six outputs are required");
    }
    
    for(i=0; i<6; i++) {
        if(!mxIsSingle(prhs[i])){ mexErrMsgTxt("Inputs must be single"); }
    }
    
    /* Get constants from Options structure */
    if(!mxIsStruct(prhs[6])){ mexErrMsgTxt("Options must be structure"); }
    field_num = mxGetFieldNumber(prhs[6], "alpha");
    if(field_num>=0) {
        OptionsField=mxGetPr(mxGetFieldByNumber(prhs[6], 0, field_num));
        alpha=(double)OptionsField[0];
    }
    field_num = mxGetFieldNumber(prhs[6], "C");
    if(field_num>=0) {
        OptionsField=mxGetPr(mxGetFieldByNumber(prhs[6], 0, field_num));
        C=(double)OptionsField[0];
    }
    field_num = mxGetFieldNumber(prhs[6], "m");
    if(field_num>=0) {
        OptionsField=mxGetPr(mxGetFieldByNumber(prhs[6], 0, field_num));
        m=(double)OptionsField[0];
    }
    
    
    /*  Get the number of dimensions */
    nsubs = mxGetNumberOfDimensions(prhs[0]);
    /* Get the sizes of the inputs */
    idims = mxGetDimensions(prhs[0]);
    for (i=0; i<nsubs; i++) { npixels=npixels*idims[i]; }
    
    /* Create output Tensor Volumes */
    plhs[0] = mxCreateNumericArray(nsubs, idims, mxSINGLE_CLASS, mxREAL);
    plhs[1] = mxCreateNumericArray(nsubs, idims, mxSINGLE_CLASS, mxREAL);
    plhs[2] = mxCreateNumericArray(nsubs, idims, mxSINGLE_CLASS, mxREAL);
    plhs[3] = mxCreateNumericArray(nsubs, idims, mxSINGLE_CLASS, mxREAL);
    plhs[4] = mxCreateNumericArray(nsubs, idims, mxSINGLE_CLASS, mxREAL);
    plhs[5] = mxCreateNumericArray(nsubs, idims, mxSINGLE_CLASS, mxREAL);

    /* Assign pointers to each input. */
    Jxx = (float *)mxGetPr(prhs[0]);
    Jxy = (float *)mxGetPr(prhs[1]);
    Jxz = (float *)mxGetPr(prhs[2]);
    Jyy = (float *)mxGetPr(prhs[3]);
    Jyz = (float *)mxGetPr(prhs[4]);
    Jzz = (float *)mxGetPr(prhs[5]);

    
    /* Assign pointers to each output. */
    Dxx = (float *)mxGetPr(plhs[0]); 
    Dxy = (float *)mxGetPr(plhs[1]); 
    Dxz = (float *)mxGetPr(plhs[2]);
    Dyy = (float *)mxGetPr(plhs[3]);
    Dyz = (float *)mxGetPr(plhs[4]);
    Dzz = (float *)mxGetPr(plhs[5]);
        
	for(i=0; i<npixels; i++) {
        /* Calculate eigenvectors and values of local Hessian */
		Ma[0][0]=(double)Jxx[i]+eps; Ma[0][1]=(double)Jxy[i]; Ma[0][2]=(double)Jxz[i];
		Ma[1][0]=(double)Jxy[i]; Ma[1][1]=(double)Jyy[i]+eps; Ma[1][2]=(double)Jyz[i];
		Ma[2][0]=(double)Jxz[i]; Ma[2][1]=(double)Jyz[i]; Ma[2][2]=(double)Jzz[i]+eps;
		eigen_decomposition(Ma, Davec, Daeig);

        /* Convert eigenvector and eigenvalue matrices back to scalar variables */
        mu1=Daeig[2]; 
        mu2=Daeig[1]; 
        mu3=Daeig[0];
		v1x=Davec[0][0]; v1y=Davec[1][0]; v1z=Davec[2][0];
		v2x=Davec[0][1]; v2y=Davec[1][1]; v2z=Davec[2][1];
        v3x=Davec[0][2]; v3y=Davec[1][2]; v3z=Davec[2][2];
        
        /* Scaling of diffusion tensor */
        di=mu1-mu3;
        if((di<eps)&&(di>-eps)) { lambda1 = alpha; } else { lambda1 = alpha + (1.0- alpha)*exp(-C/pow(di,(2.0*m))); }
        lambda2 = alpha;
		lambda3 = alpha;
      
        /* Construct the diffusion tensor */
        Dxx[i] = (float)(lambda1*v1x*v1x + lambda2*v2x*v2x + lambda3*v3x*v3x);
        Dyy[i] = (float)(lambda1*v1y*v1y + lambda2*v2y*v2y + lambda3*v3y*v3y);
        Dzz[i] = (float)(lambda1*v1z*v1z + lambda2*v2z*v2z + lambda3*v3z*v3z);
        Dxy[i] = (float)(lambda1*v1x*v1y + lambda2*v2x*v2y + lambda3*v3x*v3y);
        Dxz[i] = (float)(lambda1*v1x*v1z + lambda2*v2x*v2z + lambda3*v3x*v3z);
        Dyz[i] = (float)(lambda1*v1y*v1z + lambda2*v2y*v2z + lambda3*v3y*v3z);
	}
}
Esempio n. 12
0
void updateHandPosition(PointCloud handPcl) {
	
	int i, j;
	
	int pointCount = barycenter(handPcl, &barycX, &barycY, &barycZ) ;
	if (pointCount < MIN_HAND_POINT_NUMBER) {
		return;
	}
		

	isOpenHand = openHand(handPcl);
	
	double posCovarMat[3][3];
	double posCovarMatEigVec[3][3];
	double posCovarMatEigVal[3];
	
	
	for (i=0; i<3; i++) {
		for (j=0; j<3; j++) {
			posCovarMat[i][j] = 0;
		}
	}
	
	
	for(j=0; j<FREENECT_FRAME_H; j++) {
		for(i=0; i<FREENECT_FRAME_W; i++) {
			if (handPcl[j][i].valid) {
				posCovarMat[0][0] += (handPcl[j][i].x - barycX)*(handPcl[j][i].x - barycX);
				posCovarMat[0][1] += (handPcl[j][i].x - barycX)*(handPcl[j][i].y - barycY);
				posCovarMat[0][2] += (handPcl[j][i].x - barycX)*(handPcl[j][i].z - barycZ);
				
				posCovarMat[1][0] += (handPcl[j][i].y - barycY)*(handPcl[j][i].x - barycX);
				posCovarMat[1][1] += (handPcl[j][i].y - barycY)*(handPcl[j][i].y - barycY);
				posCovarMat[1][2] += (handPcl[j][i].y - barycY)*(handPcl[j][i].z - barycZ);
				
				posCovarMat[2][0] += (handPcl[j][i].z - barycZ)*(handPcl[j][i].x - barycX);
				posCovarMat[2][1] += (handPcl[j][i].z - barycZ)*(handPcl[j][i].y - barycY);
				posCovarMat[2][2] += (handPcl[j][i].z - barycZ)*(handPcl[j][i].z - barycZ);
			}
		}
	}
	
	for (i=0; i<3; i++) {
		for (j=0; j<3; j++) {
			posCovarMat[i][j] = posCovarMat[i][j] / pointCount;
		}
	}
	
	eigen_decomposition(posCovarMat, posCovarMatEigVec, posCovarMatEigVal);
	
//	printMatrix("Covar Mat", posCovarMat, 3);
//	printMatrix("Pos Eigen Vec", posCovarMatEigVec, 3);
	
	
	majorAxeX = posCovarMatEigVec[1][2] > 0 ? posCovarMatEigVec[0][2] : - posCovarMatEigVec[0][2]; 
	majorAxeY = posCovarMatEigVec[1][2] > 0 ? posCovarMatEigVec[1][2] : - posCovarMatEigVec[1][2];
	majorAxeZ = posCovarMatEigVec[1][2] > 0 ? posCovarMatEigVec[2][2] : - posCovarMatEigVec[2][2];
	
	normVecX = posCovarMatEigVec[2][0] > 0 ? posCovarMatEigVec[0][0] : - posCovarMatEigVec[0][0]; 
	normVecY = posCovarMatEigVec[2][0] > 0 ? posCovarMatEigVec[1][0] : - posCovarMatEigVec[1][0];
	normVecZ = posCovarMatEigVec[2][0] > 0 ? posCovarMatEigVec[2][0] : - posCovarMatEigVec[2][0];
	
	//arduinoCmd();
	//printf("Barycenter: X: %.4f Y: %.4f  Z: %.4f\tDirection: X: %.4f Y: %.4f  Z: %.4f\n",  barycX, barycY, barycZ, normVecX, normVecY, normVecZ);
	
	moveMouse();
}
  unsigned __stdcall   StructureTensor2DiffusionTensorThread(float **Args)  {
#else
  void StructureTensor2DiffusionTensorThread(float **Args)  {
#endif
    /* Matrices of Eigenvector calculation */
    double Ma[3][3];
    double Davec[3][3];
    double Daeig[3];
    
    /* Eigenvector and eigenvalues as scalars */
    double mu1, mu2, mu3, v1x, v1y, v1z, v2x, v2y, v2z, v3x, v3y, v3z;
    
    /* Magnitude of gradient */
    float *gradA;
    
    /* Amplitudes of diffustion tensor */
    double lambda1, lambda2, lambda3;
    double lambdac1, lambdac2, lambdac3;
    double lambdae1, lambdae2, lambdae3;
          
    /* Eps for finite values */
    const float eps=(float)1e-20;
    
    /* Loop variable */
    int i;
    
    /* Number of pixels */
    int npixels=1;

    /* The diffusion tensors and structure tensors */
    float *Jxx, *Jxy, *Jxz, *Jyy, *Jyz, *Jzz;
    float *Dxx, *Dxy, *Dxz, *Dyy, *Dyz, *Dzz;
    
    int dimsu[3];
    float *dimsu_f, *constants_f, *Nthreads_f, *ThreadID_f;
    
    /* Number of threads */
    int ThreadOffset, Nthreads;
    
    /* Constants */
    double C, m, alpha, lambda_h, lambda_e, lambda_c;

    /* Choice of eigenvalue equation */
    int eigenmode;
    
    /* Temporary variables */
    double di, epsilon, xi;
       
    Jxx=Args[0];
    Jxy=Args[1];
    Jxz=Args[2];
    Jyy=Args[3];
    Jyz=Args[4];
    Jzz=Args[5];
    Dxx=Args[6];
    Dxy=Args[7];
    Dxz=Args[8];
    Dyy=Args[9];
    Dyz=Args[10];
    Dzz=Args[11];
    gradA=Args[12];
    dimsu_f=Args[13];
    constants_f=Args[14];
    ThreadID_f=Args[15];
    Nthreads_f=Args[16];
            
    for(i=0;i<3;i++){ dimsu[i]=(int)dimsu_f[i]; }
    eigenmode=(int)constants_f[0];
    C=(double)constants_f[1]; 
    m=(double)constants_f[2]; 
    alpha=(double)constants_f[3];
    lambda_e=(double)constants_f[4];
    lambda_h=(double)constants_f[5];
    lambda_c=(double)constants_f[6];
    
    
    ThreadOffset=(int)ThreadID_f[0];
    Nthreads=(int)Nthreads_f[0];    
    
    npixels=dimsu[0]*dimsu[1]*dimsu[2];
    
    for(i=ThreadOffset; i<npixels; i=i+Nthreads) {
        /* Calculate eigenvectors and values of local Hessian */
        Ma[0][0]=(double)Jxx[i]+eps; Ma[0][1]=(double)Jxy[i]; Ma[0][2]=(double)Jxz[i];
        Ma[1][0]=(double)Jxy[i]; Ma[1][1]=(double)Jyy[i]+eps; Ma[1][2]=(double)Jyz[i];
        Ma[2][0]=(double)Jxz[i]; Ma[2][1]=(double)Jyz[i]; Ma[2][2]=(double)Jzz[i]+eps;
        eigen_decomposition(Ma, Davec, Daeig);

        /* Convert eigenvector and eigenvalue matrices back to scalar variables */
        mu1=Daeig[2]; 
        mu2=Daeig[1]; 
        mu3=Daeig[0];
        v1x=Davec[0][0]; v1y=Davec[1][0]; v1z=Davec[2][0];
        v2x=Davec[0][1]; v2y=Davec[1][1]; v2z=Davec[2][1];
        v3x=Davec[0][2]; v3y=Davec[1][2]; v3z=Davec[2][2];

        /* Scaling of diffusion tensor */
        if(eigenmode==0) /* Weickert line shaped */
        {
            di=(mu1-mu3);
            if((di<eps)&&(di>-eps)) { lambda1 = alpha; } else { lambda1 = alpha + (1.0- alpha)*exp(-C/pow(di,(2.0*m))); }
            lambda2 = alpha;
            lambda3 = alpha;
        }
        else if(eigenmode==1) /* Weickert plane shaped */
        {
            di=(mu1-mu3);
            if((di<eps)&&(di>-eps)) { lambda1 = alpha; } else { lambda1 = alpha + (1.0- alpha)*exp(-C/pow(di,(2.0*m))); }
            di=(mu2-mu3); 
            if((di<eps)&&(di>-eps)) { lambda2 = alpha; } else { lambda2 = alpha + (1.0- alpha)*exp(-C/pow(di,(2.0*m))); } 
            lambda3 = alpha;
        }
        else if (eigenmode==2) /* EED */
        {
            if(gradA[i]<eps){ lambda3 = 1; } else { lambda3 = 1 - exp(-3.31488/pow4(gradA[i]/pow2(lambda_e))); }
            lambda2 = 1;
            lambda1 = 1;
        }
        else if (eigenmode==3) /* CED */
        {
            lambda3 = alpha;
            lambda2 = alpha;
            if((mu2<eps)&&(mu2>-eps)){ lambda1=1;}
            else if ((mu3<eps)&&(mu3>-eps)) { lambda1=1; }
            else { lambda1= alpha + (1.0- alpha)*exp(-0.6931*pow2(lambda_c)/pow4(mu2/(alpha+mu3)));  }
        }
        else if (eigenmode==4) /* Hybrid Diffusion with Continous Switch */
        {
            if(gradA[i]<eps) { lambdae3 = 1; } else { lambdae3 = 1 - exp(-3.31488/pow4(gradA[i]/pow2(lambda_e))); }
            lambdae2 = 1;
            lambdae1 = 1;

            lambdac3 = alpha;
            lambdac2 = alpha;
            if((mu2<eps)&&(mu2>-eps)){ lambdac1=1;}
            else if ((mu3<eps)&&(mu3>-eps)) { lambdac1=1;}
            else { lambdac1 = alpha + (1.0- alpha)*exp(-0.6931*pow2(lambda_c)/pow4(mu2/(alpha+mu3)));  }

            xi= ( (mu1 / (alpha + mu2)) - (mu2 / (alpha + mu3) ));
            di=2.0*pow4(lambda_h);
            epsilon = exp(mu2*(pow2(lambda_h)*(xi-absd(xi))-2.0*mu3)/di);
            
            
            lambda1 = (1-epsilon) * lambdac1 + epsilon * lambdae1;
            lambda2 = (1-epsilon) * lambdac2 + epsilon * lambdae2;
            lambda3 = (1-epsilon) * lambdac3 + epsilon * lambdae3;
        }


        
          
        /* Construct the diffusion tensor */
        Dxx[i] = (float)(lambda1*v1x*v1x + lambda2*v2x*v2x + lambda3*v3x*v3x);
        Dyy[i] = (float)(lambda1*v1y*v1y + lambda2*v2y*v2y + lambda3*v3y*v3y);
        Dzz[i] = (float)(lambda1*v1z*v1z + lambda2*v2z*v2z + lambda3*v3z*v3z);
        Dxy[i] = (float)(lambda1*v1x*v1y + lambda2*v2x*v2y + lambda3*v3x*v3y);
        Dxz[i] = (float)(lambda1*v1x*v1z + lambda2*v2x*v2z + lambda3*v3x*v3z);
        Dyz[i] = (float)(lambda1*v1y*v1z + lambda2*v2y*v2z + lambda3*v3y*v3z);
    }
    
    /*  explicit end thread, helps to ensure proper recovery of resources allocated for the thread */
    #ifdef _WIN32
	_endthreadex( 0 );
    return 0;
	#else
	pthread_exit(NULL);
	#endif
}