/** * @brief Find the largest interval of projection coordinates if the interval is large then VAC_SPACE. If we can find any one are satified in the i dierction, then vac[i][0]= 0 vac[i][1]= 0 * @param pos * @param vac (Direct Coordinates) */ void FindVac( POSCAR* pos, double vac[3][2]) { int i,j,v; double post; double len[3]; double *interval=NULL; double max_interval=-1; POSCAR* posTmp=NULL; /*Init*/ for (i=0; i<3; i++) for (j=0; j<2; j++) vac[i][j]=0; POSCAR_Copy(pos, posTmp); POSCAR_C2D(posTmp); POSCAR_Confined(posTmp); for (i=0; i<3; i++) { len[i]= dot3D(posTmp->lat->a[i], posTmp->lat->a[i]); len[i]= sqrt(len[i]); } interval= malloc(sizeof(double)*posTmp->natom); if (interval==NULL) { fprintf(stderr, "POSCAR_FindVac: Memory Allocate Error.\n"); exit(1); } for (v=0; v<3; v++) { insort(&(posTmp->atom_pos[0][0]), posTmp->natom, 3, v, false); for (i=0; i<posTmp->natom; i++) { if (i==posTmp->natom-1) post= posTmp->atom_pos[0][v]+1.0; else post= posTmp->atom_pos[i+1][v]; interval[i]=(post-posTmp->atom_pos[i][v])*len[v]; if (interval[i]>max_interval && interval[i]>VAC_SPACE) { vac[v][0]= posTmp->atom_pos[i][v]; vac[v][1]= post; } } } free(interval); POSCAR_Free(posTmp); }
int barycentricProjection(char *path_m,char *path_rm, char *path_bin) { /* If the mesh is a smooth mesh (for example, spherical), and given a smooth reference mesh (rm) print for each vertex in rm its barycentric coordinates within the triangles of the mesh. This permits, for example, to map data defined over the vertices of the mesh over rm. */ Mesh m,rm; FILE *fo; int nt; int3D *t; int np_rm; float3D *p,*p_rm; float c0,c1; int i,j,result; float3D n; float flipTest; FreeSurfer_load_mesh(path_m,&m); FreeSurfer_load_mesh(path_rm,&rm); // Check whether the meshes are properly oriented n=normal3D(0,&m); flipTest=dot3D(m.p[m.t[0].a],n); if(flipTest<0) { printf("ERROR: the mesh is mis-oriented\n"); return 1; } n=normal3D(0,&rm); flipTest=dot3D(rm.p[rm.t[0].a],n); if(flipTest<0) { printf("ERROR: rm is mis-oriented\n"); return 1; } // Mesh (smooth) p=m.p; nt=m.nt; t=m.t; // Reference mesh (smooth) np_rm=rm.np; p_rm=rm.p; // Open output file for writing fo=fopen(path_bin,"w"); // Write mesh topology for(i=0;i<nt;i++) { fwrite(&(m.t[i].a),1,sizeof(int),fo); fwrite(&(m.t[i].b),1,sizeof(int),fo); fwrite(&(m.t[i].c),1,sizeof(int),fo); } printf("Mesh topology written\n"); // Write barycentric coordinates for(i=0;i<np_rm;i++) { if((int)(100*i/(float)np_rm)<(int)(100*(i+1)/(float)np_rm)) printf("%i%%\n",(int)(100*(i+1)/(float)np_rm)); for(j=0;j<nt;j++) { result=intersect_VectorTriangle(p_rm[i],j,&c0,&c1,&m); if(result==1) { //printf("%i %f %f\n",j,c0,c1); fwrite(&j,1,sizeof(int),fo); fwrite(&c0,1,sizeof(float),fo); fwrite(&c1,1,sizeof(float),fo); break; } } if(j==nt) { int k,imin=0; float d,dmin=1000; printf("ERROR: could not resample point %i of the reference mesh (%f %f %f)\n",i,p_rm[i].x,p_rm[i].y,p_rm[i].z); for(k=0;k<m.np;k++) { d=norm3D(sub3D(m.p[k],p_rm[i])); if(d<dmin) { dmin=d; imin=k; } } printf("closest vertex %i (%f,%f,%f), dist=%f\n",imin,p[imin].x,p[imin].y,p[imin].z,dmin); result=intersect_VectorTriangle(p_rm[i],1984,&c0,&c1,&m); printf(">> t[1984] c0,c1: %f, %f\n",c0,c1); result=intersect_VectorTriangle(p_rm[i],1920,&c0,&c1,&m); printf(">> t[1920] c0,c1: %f, %f\n",c0,c1); printf("triangles including vertex %i\n",imin); for(k=0;k<nt;k++) { if(t[k].a==imin||t[k].b==imin||t[k].c==imin) { printf("%i. %i,%i,%i\n",k,t[k].a,t[k].b,t[k].c); printf(" %i: %f,%f,%f\n",t[k].a,p[t[k].a].x,p[t[k].a].y,p[t[k].a].z); printf(" %i: %f,%f,%f\n",t[k].b,p[t[k].b].x,p[t[k].b].y,p[t[k].b].z); printf(" %i: %f,%f,%f\n",t[k].c,p[t[k].c].x,p[t[k].c].y,p[t[k].c].z); } } return 1; } } printf("Barycentric coordinates written\n"); fclose(fo); return 0; }
// Adapted from intersect_RayTriangle() // Copyright 2001, softSurfer (www.softsurfer.com) // This code may be freely used and modified for any purpose // providing that this copyright notice is included with it. // SoftSurfer makes no warranty for this code, and cannot be held // liable for any real or imagined damage resulting from its use. // Users of this code must verify correctness for their application. // Input: vector "x", triangle index "it" // Output: *c0, *c1 = the triangle-based coordinates of the intersection (when it exists) // Return: -1 = triangle is degenerate (a segment or point) // 0 = disjoint (no intersect) // 1 = intersect in unique point I1 // 2 = are in the same plane int intersect_VectorTriangle(float3D x, int i, float *c0, float *c1, Mesh *m) { float3D *p=m->p; int3D *t=m->t; int3D T=t[i]; float3D xx; float3D u, v, n; // triangle vectors float3D dir,w0, w; // ray vectors float r, a, b; // params to calc ray-plane intersect u=sub3D(p[T.b],p[T.a]); v=sub3D(p[T.c],p[T.a]); n=cross3D(u,v); if(norm3D(n)<=EPSILON) // triangle is degenerate, do not deal with this case return -1; dir=x; w0 = sca3D(p[T.a],-1); a = dot3D(n,w0); b = dot3D(n,dir); if (fabs(b) < EPSILON) { // ray is parallel to triangle plane if (a == 0) // ray lies in triangle plane return 2; else return 0; // ray disjoint from plane } // get intersect point of ray with triangle plane r = -a/b; if (r < 0.0) // ray goes away from triangle return 0; // => no intersect // for a segment, also test if (r > 1.0) => no intersect xx = sca3D(dir,r); // intersect point of ray and plane // is I inside T? float uu, uv, vv, wu, wv, D; uu = dot3D(u,u); uv = dot3D(u,v); vv = dot3D(v,v); w = sub3D(xx,p[T.a]); wu = dot3D(w,u); wv = dot3D(w,v); D = uv * uv - uu * vv; // get and test parametric coords *c0 = (uv * wv - vv * wu) / D; if(fabs(*c0)<EPSILON) *c0=0; if(fabs(1-*c0)<EPSILON) *c0=1; if (*c0 < 0.0 || *c0 > 1.0) // I is outside T return 0; *c1 = (uv * wu - uu * wv) / D; if(fabs(*c1)<EPSILON) *c1=0; if(fabs(1-*c1)<EPSILON) *c1=1; if (*c1 < 0.0 || (*c0 + *c1) > 1.0) // I is outside T return 0; return 1; // I is in T }