Doxygen Source Code Documentation
SUMA_SphericalMapping.c File Reference
#include "SUMA_suma.h"
#include "SUMA_Macros.h"
Go to the source code of this file.
Functions | |
SUMA_Boolean | SUMA_SphereQuality (SUMA_SurfaceObject *SO, char *Froot, char *shist) |
A function to test if a spherical surface is indeed spherical. | |
void | SUMA_binTesselate (float *nodeList, int *triList, int *nCtr, int *tCtr, int recDepth, int depth, int n1, int n2, int n3) |
void | SUMA_tesselate (float *nodeList, int *triList, int *nCtr, int *tCtr, int N_Div, int n0, int n1, int n2) |
int * | SUMA_divEdge (float *nodeList, int *nCtr, int node1, int node2, int N_Div) |
void | SUMA_triangulateRow (float *nodeList, int *triList, int *nCtr, int *tCtr, int N_Div, int *currFloor, int node1, int node2) |
void | SUMA_addNode (float *nodeList, int *ctr, float x, float y, float z) |
void | SUMA_addTri (int *triList, int *ctr, int n1, int n2, int n3) |
SUMA_SurfaceObject * | SUMA_CreateIcosahedron (float r, int depth, float ctr[3], char bin[], int ToSphere) |
SUMA_Boolean | SUMA_inNodeNeighb (SUMA_SurfaceObject *surf, float *nodeList, int *node, float *P0, float *P1) |
float * | SUMA_detWeight (float node0[3], float node1[3], float node2[3], float ptHit[3]) |
SUMA_Boolean | SUMA_binSearch (float *nodeList, float target, int *seg) |
float | intersection_map (float a, float b, float c, float d, float val) |
SUMA_MorphInfo * | SUMA_MapSurface (SUMA_SurfaceObject *surf1, SUMA_SurfaceObject *surf2) |
void | SUMA_Search_Min_Dist (float *pt, float *nodeList, int *seg, float restr, float *dist, int *i_dist) |
SUMA_SO_map * | SUMA_Create_SO_map (void) |
SUMA_Boolean | SUMA_Free_SO_map (SUMA_SO_map *SOM) |
SUMA_Boolean | SUMA_Show_SO_map (SUMA_SO_map *SOM, FILE *out) |
SUMA_MorphInfo * | SUMA_Create_MorphInfo (void) |
SUMA_Boolean | SUMA_Free_MorphInfo (SUMA_MorphInfo *MI) |
SUMA_SurfaceObject * | SUMA_morphToStd (SUMA_SurfaceObject *SO, SUMA_MorphInfo *MI, SUMA_Boolean nodeChk) |
float * | SUMA_readColor (int numNodes, char *colFileNm) |
void | SUMA_writeColorFile (float *array, int numNode, int *index, char fileNm[]) |
void | SUMA_writeFSfile (SUMA_SurfaceObject *SO, char firstLine[], char fileNm[]) |
void | SUMA_writeSpecFile (SUMA_SpecSurfInfo *surfaces, int numSurf, char program[], char group[], char specFileNm[]) |
void | SUMA_read1D (char *fileNm, int *i_colm, int *i_locInfo, SUMA_1dData *data) |
void | SUMA_write1D (int *num, float *vals, int *index, char firstline[], char outFileNm[]) |
float * | SUMA_createColGradient (float *col, int numSeg, SUMA_Boolean allGvn) |
float * | SUMA_assignColors (float *vals, float *cols, int numVal, int numCol, float *gradRng, float *valDiv) |
SUMA_1dData * | SUMA_Create_1dData (void) |
SUMA_Boolean | SUMA_Free_1dData (SUMA_1dData *data) |
Variables | |
SUMA_CommonFields * | SUMAg_CF |
int | SUMAg_N_DOv |
SUMA_DO * | SUMAg_DOv |
float | ep = 1e-4 |
Function Documentation
|
gives value for intersection of two lines, as defined in SUMA_MapSurface (see p10 LNB) Definition at line 1175 of file SUMA_SphericalMapping.c. Referenced by SUMA_detWeight().
|
|
SUMA_addNode(nodeList, ctr, x, y, z); Function to add the x, y, z corrdinates of a node to nodeList.
Definition at line 606 of file SUMA_SphericalMapping.c. References SUMA_ENTRY, and SUMA_RETURNe. Referenced by SUMA_binTesselate(), SUMA_CreateIcosahedron(), SUMA_divEdge(), and SUMA_triangulateRow().
00606 { 00607 00608 static char FuncName[]={"SUMA_addNode"}; 00609 00610 SUMA_ENTRY; 00611 00612 ++*ctr; 00613 nodeList[*ctr] = x; 00614 ++*ctr; 00615 nodeList[*ctr] = y; 00616 ++*ctr; 00617 nodeList[*ctr] = z; 00618 00619 SUMA_RETURNe; 00620 } |
|
SUMA_addTri(triList, ctr, n1, n2, n3); Function to add the three nodes of a triangle to triList.
Definition at line 630 of file SUMA_SphericalMapping.c. References n1, n2, SUMA_ENTRY, and SUMA_RETURNe. Referenced by SUMA_binTesselate(), SUMA_CreateIcosahedron(), SUMA_tesselate(), and SUMA_triangulateRow().
00630 { 00631 00632 static char FuncName[]={"SUMA_addTri"}; 00633 00634 SUMA_ENTRY; 00635 00636 ++*ctr; 00637 triList[*ctr] = n1; 00638 ++*ctr; 00639 triList[*ctr] = n2; 00640 ++*ctr; 00641 triList[*ctr] = n3; 00642 00643 SUMA_RETURNe; 00644 } |
|
array = SUMA_assignColors( vals, cols, numVal, numCol, gradRng, valDiv ); Function to assign colors to vector of values.
Definition at line 4188 of file SUMA_SphericalMapping.c. References cols, i, SUMA_calloc, SUMA_ENTRY, and SUMA_free.
04188 { 04189 04190 int i, j, k; 04191 float *valCol=NULL; 04192 float min, max, segSize=0; 04193 static char FuncName[]={"SUMA_assignColors"}; 04194 04195 SUMA_ENTRY; 04196 valCol = SUMA_calloc( 3*numVal, sizeof(float)); 04197 valDiv = SUMA_calloc( numCol, sizeof(float)); 04198 04199 /*find min/max of vals*/ 04200 min = vals[0]; max = vals[0]; 04201 for (i=0; i<numVal; ++i) { 04202 if (vals[i]<min) min = vals[i]; 04203 else if (vals[i]>max) max = vals[i]; 04204 } 04205 04206 if (gradRng==NULL) { 04207 /*if no color value range given, base segment size on full range of values*/ 04208 segSize = (max-min)/numCol; 04209 /*set (high end only) value cutoffs for color segments*/ 04210 for (i=0; i<numCol; ++i) { 04211 valDiv[i] = min+(i+1)*segSize; 04212 } 04213 } 04214 else { 04215 /*else base segment size on color value range given (keeping in mind two colors must be saved for values out of range)*/ 04216 segSize = (gradRng[1]-gradRng[0])/(numCol-2); 04217 /*set (high end only) value cutoffs for color segments*/ 04218 valDiv[0] = gradRng[0]; 04219 valDiv[numCol-1] = max; 04220 for (i=1; i<numCol-1; ++i) { 04221 valDiv[i] = valDiv[0] + i*segSize; 04222 } 04223 } 04224 04225 for (i=0; i<numVal; ++i) { 04226 /*assign segment colors*/ 04227 j = 3*i; 04228 for (k=0; k<numCol; ++k) { 04229 if ( vals[i]<=valDiv[k] ) { 04230 /*value falls within segment k => assigned color k*/ 04231 valCol[j] = cols[ 3*k ]; 04232 valCol[j+1] = cols[ 3*k+1 ]; 04233 valCol[j+2] = cols[ 3*k+2 ]; 04234 break; 04235 } 04236 } 04237 } 04238 fprintf(SUMA_STDERR, "numCol = %d\n", numCol); 04239 /**write divisions to screen (if fairly discrete)*/ 04240 if (numCol<20) { 04241 fprintf(SUMA_STDERR, "COLOR RANGES:\n\t[%f, %f]\n", min, valDiv[0]); 04242 for (i=1; i<numCol; ++i) { 04243 fprintf(SUMA_STDERR, "\t(%f, %f]\n", valDiv[i-1], valDiv[i]); 04244 } 04245 fprintf(SUMA_STDERR, "\n"); 04246 } 04247 04248 SUMA_free(valDiv); 04249 04250 return valCol; 04251 } |
|
SUMA_binSearch( nodeList, target, seg); This function performs a binary search. The indices of the elements in nodeList surrounding target will be stored in (overwrite) seg; thus seg[0]=seg[1]=i implies that an exact match was found at index i.
Definition at line 1122 of file SUMA_SphericalMapping.c. References SUMA_Boolean, SUMA_ENTRY, and SUMA_RETURN. Referenced by SUMA_createColGradient(), and SUMA_MapSurface().
01122 { 01123 01124 int mid=0; 01125 int beg = seg[0], end = seg[1]; 01126 SUMA_Boolean found=YUP; 01127 static char FuncName[]={"SUMA_binSearch"}; 01128 01129 SUMA_ENTRY; 01130 // fprintf(SUMA_STDERR, "%f < %f < %f\n", nodeList[beg], target, nodeList[end]); 01131 if ( end<beg) { 01132 fprintf(SUMA_STDERR, "Error %s: Segment must be passed with seg[0] being of lower index of seg[1].\n\n", FuncName); 01133 SUMA_RETURN (found = NOPE); 01134 } 01135 if ( nodeList[end]<nodeList[beg] ) { 01136 fprintf(SUMA_STDERR, "Error %s: Nodelist must be passed sorted and in ascending order.\n\n", FuncName); 01137 SUMA_RETURN (found = NOPE); 01138 } 01139 if ( (nodeList[beg]>target) || (nodeList[end]<target) ) { 01140 fprintf(SUMA_STDERR, "Error %s: Target does not lie within segment!\n\n", FuncName); 01141 SUMA_RETURN (found = NOPE); 01142 } 01143 01144 if (beg!=end) { 01145 mid =(end-beg)/2 + beg; 01146 /**no exact match, but elements above and below found*/ 01147 if (beg+1==end) { 01148 seg[0] = beg; 01149 seg[1] = end; 01150 } 01151 else if (target==nodeList[mid]) { 01152 seg[0] = mid; 01153 seg[1] = mid; 01154 } 01155 /**keep searching*/ 01156 else if ( target < nodeList[mid]) { 01157 seg[0] = beg; seg[1] = mid; 01158 found = SUMA_binSearch( nodeList, target, seg); 01159 } 01160 else if ( target > nodeList[mid]) { 01161 seg[0] = mid; seg[1] = end; 01162 found = SUMA_binSearch( nodeList, target, seg); 01163 } 01164 } 01165 /**exact match; beg==end or target==nodeList[ indexList[mid] ]*/ 01166 else { 01167 seg[0] = mid; 01168 seg[1] = mid; 01169 } 01170 01171 SUMA_RETURN(found); 01172 } |
|
SUMA_binTesselate(nodeList, triList, nCtr, tCtr, recDepth, depth, n1, n2, n3); This function divides 1 triangle into 4 recursively to depth recDepth.
Definition at line 344 of file SUMA_SphericalMapping.c. References ep, i, n1, n2, SUMA_addNode(), SUMA_addTri(), SUMA_ENTRY, SUMA_RETURNe, x2, y1, and z1. Referenced by SUMA_CreateIcosahedron().
00345 { 00346 double x1=0,y1=0,z1=0, x2=0,y2=0,z2=0, x3=0,y3=0,z3=0; 00347 double x12=0, y12=0, z12=0; 00348 double x23=0, y23=0, z23=0; 00349 double x31=0, y31=0, z31=0; 00350 int currIndex, index1, index2, index3; 00351 int i=0, j=0, m=0, k=0; 00352 static char FuncName[]={"SUMA_binTesselate"}; 00353 00354 SUMA_ENTRY; 00355 00356 currIndex = (nCtr[0]-2)/3; 00357 00358 x1=(double)nodeList[3*n1]; y1=(double)nodeList[3*n1+1]; z1=(double)nodeList[3*n1+2]; 00359 x2=(double)nodeList[3*n2]; y2=(double)nodeList[3*n2+1]; z2=(double)nodeList[3*n2+2]; 00360 x3=(double)nodeList[3*n3]; y3=(double)nodeList[3*n3+1]; z3=(double)nodeList[3*n3+2]; 00361 00362 x12=(x1+x2)/2.0; y12=(y1+y2)/2.0; z12=(z1+z2)/2.0; 00363 x23=(x2+x3)/2.0; y23=(y2+y3)/2.0; z23=(z2+z3)/2.0; 00364 x31=(x3+x1)/2.0; y31=(y3+y1)/2.0; z31=(z3+z1)/2.0; 00365 00366 /**prevents creation of duplicate nodes*/ 00367 index1 = -1; index2 = -1; index3 = -1; 00368 i=0; j=0; 00369 for (i=0; i<=currIndex; ++i) { 00370 j = 3*i; 00371 if ( fabs(nodeList[j]-x12)<ep && fabs(nodeList[j+1]-y12)<ep && fabs(nodeList[j+2]-z12)<ep ) { 00372 index1 = i; 00373 } 00374 if ( fabs(nodeList[j]-x23)<ep && fabs(nodeList[j+1]-y23)<ep && fabs(nodeList[j+2]-z23)<ep ) { 00375 index2 = i; 00376 } 00377 if ( fabs(nodeList[j]-x31)<ep && fabs(nodeList[j+1]-y31)<ep && fabs(nodeList[j+2]-z31)<ep ) { 00378 index3 = i; 00379 } 00380 } 00381 00382 if (index1==-1) { 00383 ++currIndex; 00384 index1 = currIndex; 00385 SUMA_addNode( nodeList, nCtr, (float)x12, (float)y12, (float)z12); 00386 } 00387 if (index2==-1) { 00388 ++currIndex; 00389 index2 = currIndex; 00390 SUMA_addNode( nodeList, nCtr, (float)x23, (float)y23, (float)z23); 00391 } 00392 if (index3==-1) { 00393 ++currIndex; 00394 index3 = currIndex; 00395 SUMA_addNode( nodeList, nCtr, (float)x31, (float)y31, (float)z31); 00396 } 00397 00398 /**if recursion depth met, add 4 triangles to list referenced by tPtr*/ 00399 if (depth>=recDepth) { 00400 SUMA_addTri( triList, tCtr, n1, index1, index3); 00401 SUMA_addTri( triList, tCtr, index1, n2, index2); 00402 SUMA_addTri( triList, tCtr, index3, index2, n3); 00403 SUMA_addTri( triList, tCtr, index3, index2, index1); 00404 } 00405 00406 /**recursion depth not met: call tesselate on each of 4 new triangles*/ 00407 else { 00408 ++depth; 00409 SUMA_binTesselate( nodeList, triList, nCtr, tCtr, recDepth, depth, n1, index1, index3 ); 00410 SUMA_binTesselate( nodeList, triList, nCtr, tCtr, recDepth, depth, index1, n2, index2 ); 00411 SUMA_binTesselate( nodeList, triList, nCtr, tCtr, recDepth, depth, index3, index2, n3 ); 00412 SUMA_binTesselate( nodeList, triList, nCtr, tCtr, recDepth, depth, index3, index2, index1 ); 00413 } 00414 00415 SUMA_RETURNe; 00416 } |
|
function used to create a SUMA_1dData structure Definition at line 4256 of file SUMA_SphericalMapping.c. References i, SUMA_1dData::ijk_list, SUMA_1dData::nd_list, SUMA_1dData::nvox_list, SUMA_ENTRY, SUMA_malloc, SUMA_RETURN, SUMA_1dData::valArray, and SUMA_1dData::vxl_list.
04257 { 04258 static char FuncName[]={"SUMA_Create_1dData"}; 04259 int i=0; 04260 04261 SUMA_1dData *data = NULL; 04262 04263 SUMA_ENTRY; 04264 04265 data = (SUMA_1dData *) SUMA_malloc (sizeof(SUMA_1dData)); 04266 if (!data) { 04267 fprintf (SUMA_STDERR, "\nError %s: Failed to allocate for MI.\n", FuncName); 04268 SUMA_RETURN (NULL); 04269 } 04270 04271 data->nd_list = NULL; 04272 data->vxl_list = NULL; 04273 data->ijk_list = NULL; 04274 data->nvox_list = NULL; 04275 data->valArray = NULL; 04276 04277 SUMA_RETURN (data); 04278 } |
|
function used to create a SUMA_MorphInfo structure Definition at line 1778 of file SUMA_SphericalMapping.c. References SUMA_MorphInfo::ClsNodes, SUMA_MorphInfo::FaceSetList, SUMA_MorphInfo::IDcode, SUMA_MorphInfo::N_FaceSet, SUMA_MorphInfo::N_Node, SUMA_ENTRY, SUMA_malloc, SUMA_RETURN, and SUMA_MorphInfo::Weight. Referenced by SUMA_MapSurface().
01779 { 01780 static char FuncName[]={"SUMA_Create_MorphInfo"}; 01781 SUMA_MorphInfo *MI = NULL; 01782 01783 SUMA_ENTRY; 01784 01785 MI = (SUMA_MorphInfo *) SUMA_malloc (sizeof(SUMA_MorphInfo)); 01786 if (!MI) { 01787 fprintf (SUMA_STDERR, "Error %s: Failed to allocate for MI.\n", FuncName); 01788 SUMA_RETURN (NULL); 01789 } 01790 01791 MI->IDcode = NULL; 01792 MI->N_Node = 0; 01793 MI->N_FaceSet = 0; 01794 MI->Weight = NULL; 01795 MI->ClsNodes = NULL; 01796 MI->FaceSetList = NULL; 01797 01798 SUMA_RETURN (MI); 01799 } |
|
function used to create a SUMA_SO_map structure Definition at line 1700 of file SUMA_SphericalMapping.c. References SUMA_SO_map::N_Node, SUMA_SO_map::NewNodeList, SUMA_SO_map::NodeCol, SUMA_SO_map::NodeDisp, SUMA_SO_map::NodeVal, SUMA_ENTRY, SUMA_malloc, and SUMA_RETURN.
01701 { 01702 static char FuncName[]={"SUMA_Create_SO_map"}; 01703 SUMA_SO_map *SOM = NULL; 01704 01705 SUMA_ENTRY; 01706 01707 SOM = (SUMA_SO_map *) SUMA_malloc (sizeof(SUMA_SO_map)); 01708 if (!SOM) { 01709 fprintf (SUMA_STDERR, "Error %s: Failed to allocate for SOM.\n", FuncName); 01710 SUMA_RETURN (NULL); 01711 } 01712 01713 SOM->N_Node = 0; 01714 SOM->NewNodeList = NULL; 01715 SOM->NodeVal = NULL; 01716 SOM->NodeDisp = NULL; 01717 SOM->NodeCol = NULL; 01718 01719 SUMA_RETURN (SOM); 01720 } |
|
array = SUMA_createColGradient( col, numDiv); Function to create a color gradient.
Definition at line 3891 of file SUMA_SphericalMapping.c. References abs, color, i, SUMA_binSearch(), SUMA_Boolean, SUMA_calloc, SUMA_ENTRY, and SUMA_free.
03891 { 03892 03893 int i, j, k, it; 03894 int numCol=0, numStdIncr, numColGvn; 03895 int *colRngInt=NULL, *colUsed=NULL, i_incr=0; 03896 int *bind_currCol=NULL, *distTOint=NULL, colIntArray[8]; 03897 int dist_intTOrngBeg, dist_intTOrngEnd, *numColDiv=NULL, *tmpInt=NULL; 03898 float *colRng=NULL, color[8][3], *colSeg=NULL, *colIncr=NULL, *stdColIncr=NULL; 03899 float incR=0.0, incG=0.0, incB=0.0, temp, dist[2]; 03900 SUMA_Boolean decr = NOPE, noGrad = NOPE; 03901 static char FuncName[]={"SUMA_createColGradient"}; 03902 03903 SUMA_ENTRY; 03904 fprintf(SUMA_STDERR, "numSeg = %d\n", numSeg); 03905 if ( (col==NULL || numSeg<0) && allGvn) { 03906 /*should be mutually exclusive => assume meant !allGvn and use entire spectrum 03907 (claims all colors expressly given, yet none are passed or claims continuous gradient)*/ 03908 allGvn = NOPE; 03909 } 03910 03911 /**determine color range*/ 03912 03913 if (col==NULL) { 03914 /*assume full color range*/ 03915 colRngInt = SUMA_calloc(2, sizeof(int)); 03916 colRng = SUMA_calloc(2, sizeof(int)); 03917 colRng[0] = 0; 03918 colRng[1] = 7; 03919 /* colRngInt[0] = 0; 03920 colRngInt[1] = 0; 03921 colRngInt[2] = 7; 03922 colRngInt[3] = 7;*/ 03923 } 03924 else { 03925 if ( col[0]<0 || col[1]>7 || col[0]<0 || col[1]>7) { 03926 fprintf(SUMA_STDERR, "\nError %s: Color Ranges not within 0->7. Exiting.\n", FuncName); 03927 exit(1); 03928 } 03929 03930 /*take passed color range*/ 03931 if ( allGvn ) { 03932 /*assign each color*/ 03933 colRng = SUMA_calloc(numSeg, sizeof(float)); 03934 for (i=0; i<numSeg; ++i) { 03935 colRng[i] = col[i]; } 03936 } 03937 else { 03938 /*assign only endpoints*/ 03939 colRng = SUMA_calloc(2, sizeof(float)); 03940 colRng[0] = col[0]; 03941 colRng[1] = col[1]; 03942 03943 /**check decreasing or increasing color numbers (does not matter if all colors given)*/ 03944 if ( col[1] < col[0] ) { 03945 decr = YUP; 03946 } 03947 } 03948 } 03949 03950 /**roygbiv values for each color*/ 03951 color[0][0]=.75; color[0][1]=0; color[0][2]=0; //red 03952 color[1][0]=1; color[1][1]=.5; color[1][2]=0; //orange 03953 color[2][0]=1; color[2][1]=1; color[2][2]=0; //yellow 03954 color[3][0]=0; color[3][1]=.75; color[3][2]=0; //green 03955 color[4][0]=0; color[4][1]=.75; color[4][2]=.75; //blue 03956 color[5][0]=0; color[5][1]=0; color[5][2]=.75; //indigo 03957 color[6][0]=.5; color[6][1]=0; color[6][2]=.75; //violet 03958 color[7][0]=.75; color[7][1]=0; color[7][2]=0; //red 03959 03960 /*determine number of segments (to divide stdIncrements)*/ 03961 if (numSeg<0) numSeg = 700; /*continuous gradient*/ 03962 03963 03964 /*create array of 0.1 and integer increments*/ 03965 stdColIncr = SUMA_calloc( 71, sizeof(float)); 03966 stdColIncr[0] = 0.0; 03967 colIntArray[0] = 0; 03968 for ( i=0; i<7; ++i) { 03969 colIntArray[i+1] = i+1; 03970 for ( j=1; j<11; ++j) { 03971 stdColIncr[ 10*i+j ] = stdColIncr[ 10*i ] + j*0.1; 03972 } 03973 /*elaborate because just adding .1 was summing to less than 7 (likely float truncation issue)*/ 03974 } 03975 03976 03977 /**find stdColIncr and Integers affiliated with given colors*/ 03978 03979 if (allGvn) numColGvn = numSeg; 03980 else numColGvn = 2; 03981 if (!colRngInt) 03982 colRngInt = SUMA_calloc( 2*numColGvn, sizeof(int)); 03983 bind_currCol = SUMA_calloc( 2, sizeof(int)); 03984 distTOint = SUMA_calloc( numColGvn, sizeof(float)); 03985 03986 for (i=0; i<numColGvn; ++i) { 03987 03988 /*find stdColIncr elements nearest to given colors; set given colors to stdColIncr*/ 03989 bind_currCol[0] = 0; bind_currCol[1] = 70; 03990 if ( !SUMA_binSearch( stdColIncr, colRng[i], bind_currCol ) ) { 03991 fprintf(SUMA_STDERR, "\nError %s: Failed in binary search !(%f < %f < %f). Exiting.\n\n", FuncName, stdColIncr[bind_currCol[0]], colRng[i], stdColIncr[bind_currCol[1]]); 03992 if (colRng) SUMA_free(colRng); 03993 if (stdColIncr) SUMA_free(stdColIncr); 03994 if (colRngInt) SUMA_free(colRngInt); 03995 if (bind_currCol) SUMA_free(bind_currCol); 03996 if (distTOint) SUMA_free(distTOint); 03997 exit(1); 03998 } 03999 if ( abs( stdColIncr[bind_currCol[0]]-colRng[i] ) < abs( stdColIncr[bind_currCol[1]]-colRng[i] )) 04000 colRng[i] = stdColIncr[bind_currCol[0]]; 04001 else colRng[i] = stdColIncr[bind_currCol[1]]; 04002 04003 04004 /*find integers binding new color*/ 04005 /*(note integers passed as floats merely truncated to ints)*/ 04006 if ( abs( colRng[i] - (int)colRng[i] )<0.01 ) { 04007 /*(assume colRng[i] passed as integer in float format)*/ 04008 colRngInt[ 2*i ] = (int)colRng[i]; 04009 colRngInt[ 2*i+1 ] = (int)colRng[i]; 04010 } 04011 else { 04012 colRngInt[ 2*i ] = (int)colRng[i]; 04013 colRngInt[ 2*i+1 ] = (int)colRng[i]+1; 04014 } 04015 04016 /*find distance from color to low binding integer (high binding is 10-(dist to low))*/ 04017 distTOint[i] = bind_currCol[0]%10; 04018 04019 fprintf(SUMA_STDERR, "%d: %d < %f < %d dist = %d\n", i, colRngInt[2*i], colRng[i], colRngInt[2*i+1], distTOint[i]); 04020 } 04021 04022 04023 /**divide range*/ 04024 04025 if ( !allGvn ) { 04026 /*color range end point given - must divide range*/ 04027 04028 if ( !decr ) numCol = colRngInt[3]-colRngInt[0] + 1; 04029 else numCol = colRngInt[1] - colRngInt[2] + 1; 04030 04031 /*determine all colors within range*/ 04032 colUsed = SUMA_calloc(numCol, sizeof(int)); 04033 colUsed[0] = colRngInt[0]; 04034 for (i=1; i<numCol; ++i) { 04035 if ( !decr ) colUsed[i] = colUsed[i-1] + 1; 04036 else colUsed[i] = colUsed[i-1] - 1; 04037 } 04038 04039 /*determine distance from colRng to binding integers*/ 04040 if ( !decr ) { 04041 dist_intTOrngBeg = distTOint[0]; 04042 dist_intTOrngEnd = 10-distTOint[1]; 04043 } 04044 else { 04045 dist_intTOrngBeg = 10-distTOint[0]; 04046 dist_intTOrngEnd = distTOint[1]; 04047 } 04048 04049 /*determine the number of increments necessary for color (based upon 10 gradations between each color) 04050 to be later (further) divided by the number of segments needed for this specific gradient*/ 04051 /*numStdIncr is number of std (.1) gradations included in colRng*/ 04052 if (numCol>3) 04053 /*color blocks exist between the first and last*/ 04054 numStdIncr = 10*(numCol-1) - dist_intTOrngBeg - dist_intTOrngEnd; 04055 else if ( numCol==3 ) { 04056 /*first and last color blocks distinct but with no color blocks between*/ 04057 numStdIncr = 20 - dist_intTOrngBeg - dist_intTOrngEnd; 04058 } 04059 else { 04060 /*first and last color blocks the same (colRng found within only one color block)*/ 04061 numStdIncr = 10 - dist_intTOrngBeg - dist_intTOrngEnd; 04062 noGrad = YUP; 04063 } 04064 04065 if ( noGrad ) { 04066 /*start and end colors the same => no subdivisions necessary 04067 (an entirely redundant input if numSeg>1 since no divisions will even be seen)*/ 04068 04069 for (i=0; i<numSeg; ++i ) { 04070 k = 3*i; 04071 colSeg[k] = color[colRngInt[0]][0]; 04072 colSeg[k+1] = color[colRngInt[0]][1]; 04073 colSeg[k+2] = color[colRngInt[0]][2]; 04074 } 04075 } 04076 04077 else { 04078 /*subdivide colors*/ 04079 04080 /*create array containing number of .1 divisions within colRng for each color block*/ 04081 numColDiv = SUMA_calloc( numCol-1, sizeof(int)); 04082 numColDiv[0] = 10 - dist_intTOrngBeg; //first color block 04083 for (i=1; i<numCol-2; ++i) { numColDiv[i] = 10; } //middle color blocks 04084 numColDiv[numCol-2] = 10 - dist_intTOrngEnd; //last color block 04085 04086 /**create array of small increments to fractionize incremental colors for segments*/ 04087 /* (see LNB pg ??)*/ 04088 04089 colIncr = SUMA_calloc( 3*(numSeg-1)*(numStdIncr), sizeof(float)); 04090 04091 k=0; 04092 for (i=0; i<numCol-1; ++i) { 04093 04094 /*divide current color by the number of incremental segments*/ 04095 incR = (color[colUsed[i+1]][0] - color[colUsed[i]][0])/(10*(numSeg-1)); 04096 incG = (color[colUsed[i+1]][1] - color[colUsed[i]][1])/(10*(numSeg-1)); 04097 incB = (color[colUsed[i+1]][2] - color[colUsed[i]][2])/(10*(numSeg-1)); 04098 04099 /*place (numColDiv[i]*(numSeg-1)) color increments into colIncr array*/ 04100 for (j=0; j<numColDiv[i]*(numSeg-1); ++j) { 04101 colIncr[k++] = incR; 04102 colIncr[k++] = incG; 04103 colIncr[k++] = incB; 04104 } 04105 } 04106 } 04107 04108 04109 /**assign segment colors by summing increments*/ 04110 04111 colSeg = SUMA_calloc( 3*numSeg, sizeof(float)); 04112 04113 colSeg[0] = color[colUsed[0]][0]; 04114 colSeg[1] = color[colUsed[0]][1]; 04115 colSeg[2] = color[colUsed[0]][2]; 04116 for (i=0; i<dist_intTOrngBeg; ++i) { 04117 /*first colSeg must jump to fractional (.1) color*/ 04118 /*note that the first three elements (rgb) of colIncr are always increments of the first color block 04119 so taking just those three repeatedly is fine*/ 04120 colSeg[0] = colSeg[0] + colIncr[0]; 04121 colSeg[1] = colSeg[1] + colIncr[1]; 04122 colSeg[2] = colSeg[2] + colIncr[2]; 04123 } 04124 04125 i_incr = 0; 04126 fprintf(SUMA_STDERR, "numSeg = %d\n", numSeg); 04127 for (i=1; i<numSeg; ++i ) { 04128 k = 3*i; 04129 04130 /*first set segment colors to those of previous segment*/ 04131 colSeg[k] = colSeg[k-3]; 04132 colSeg[k+1] = colSeg[k-2]; 04133 colSeg[k+2] = colSeg[k-1]; 04134 04135 /*then add (numStdIncr) color increments*/ 04136 for (j=0; j<numStdIncr; ++j) { 04137 colSeg[k] = colSeg[k] + colIncr[3*i_incr]; 04138 colSeg[k+1] = colSeg[k+1] + colIncr[3*i_incr+1]; 04139 colSeg[k+2] = colSeg[k+2] + colIncr[3*i_incr+2]; 04140 ++i_incr; 04141 } 04142 } 04143 } 04144 04145 else { 04146 /*color segments already indicated - no incremtation etc necessary*/ 04147 04148 colSeg = SUMA_calloc( 3*numSeg, sizeof(float)); 04149 04150 for (i=0; i<numSeg; ++i) { 04151 /*create color*/ 04152 k = 3*i; 04153 colSeg[k] = ((10-distTOint[i])/10)*color[colRngInt[2*i]][0] + (distTOint[i]/10)*color[colRngInt[2*i+1]][0]; 04154 colSeg[k+1] = ((10-distTOint[i])/10)*color[colRngInt[2*i]][1] + (distTOint[i]/10)*color[colRngInt[2*i+1]][1]; 04155 colSeg[k+2] = ((10-distTOint[i])/10)*color[colRngInt[2*i]][2] + (distTOint[i]/10)*color[colRngInt[2*i+1]][2]; 04156 } 04157 } 04158 04159 SUMA_free(stdColIncr); 04160 SUMA_free(bind_currCol); 04161 SUMA_free(colRngInt); 04162 SUMA_free(distTOint); 04163 if (!allGvn) { 04164 SUMA_free(colUsed); 04165 SUMA_free(numColDiv); 04166 SUMA_free(colIncr); 04167 } 04168 04169 return colSeg; 04170 } |
|
SO = SUMA_CreateIcosahedron (r, depth, ctr, bin, ToSphere); This function creates an icosahedron of size r and to tesselation extent depth.
Definition at line 661 of file SUMA_SphericalMapping.c. References a, SUMA_SurfaceObject::EL, ep, SUMA_SurfaceObject::FaceNormList, SUMA_SURF_NORM::FaceNormList, SUMA_SurfaceObject::FaceSetDim, SUMA_SurfaceObject::FaceSetList, SUMA_SurfaceObject::FN, i, SUMA_SurfaceObject::idcode_str, LocalHead, SUMA_SurfaceObject::MF, SUMA_SurfaceObject::N_FaceSet, SUMA_SurfaceObject::N_Node, SUMA_SurfaceObject::NodeDim, SUMA_SurfaceObject::NodeList, SUMA_MEMBER_FACE_SETS::NodeMemberOfFaceSet, SUMA_SurfaceObject::NodeNormList, SUMA_SURF_NORM::NodeNormList, r, SUMA_addNode(), SUMA_addTri(), SUMA_Alloc_SurfObject_Struct(), SUMA_binTesselate(), SUMA_Boolean, SUMA_Build_FirstNeighb(), SUMA_calloc, SUMA_ENTRY, SUMA_Free_Surface_Object(), SUMA_ICOSAHEDRON_DIMENSIONS, SUMA_IDCODE_LENGTH, SUMA_Make_Edge_List(), SUMA_Make_Edge_List_eng(), SUMA_MakeConsistent(), SUMA_MemberFaceSets(), SUMA_POINT_AT_DISTANCE, SUMA_RETURN, SUMA_SurfNorm(), SUMA_tesselate(), and UNIQ_idcode_fill().
00662 { 00663 static char FuncName[]={"SUMA_CreateIcosahedron"}; 00664 SUMA_SurfaceObject *SO = NULL; 00665 int i, numNodes=0, numTri=0, j, i3; 00666 float a,b, lgth; 00667 int nodePtCt, triPtCt, *icosaTri=NULL; 00668 float *icosaNode=NULL; 00669 SUMA_SURF_NORM SN; 00670 SUMA_NODE_FIRST_NEIGHB *firstNeighb=NULL; 00671 SUMA_Boolean DoWind = YUP; 00672 int n=0, m=0, in=0, trouble; 00673 SUMA_Boolean LocalHead = NOPE; 00674 00675 SUMA_ENTRY; 00676 00677 SO = SUMA_Alloc_SurfObject_Struct(1); 00678 if (SO == NULL) { 00679 fprintf (SUMA_STDERR,"Error %s: Failed to allocate for Surface Object.", FuncName); 00680 SUMA_RETURN (NULL); 00681 } 00682 00683 00684 if (strcmp(bin, "y") == 0) { numTri = 20*pow(2,2*depth); } //exact 00685 else { 00686 if (depth !=0) { numTri = 20*pow(depth, 2); } 00687 else numTri = 20; 00688 } 00689 if (depth != 0) { numNodes = 3*numTri; } //conservative 00690 else numNodes = 12; 00691 00692 00693 if (LocalHead) fprintf(SUMA_STDERR,"%s: Allocated for %d Nodes, %d numTri\n", FuncName, numNodes, numTri); 00694 00695 /**icosahedron creation and tesselation*/ 00696 SUMA_ICOSAHEDRON_DIMENSIONS(r, a, b, lgth); /* lgth is the length of edge by dist node0->node1 */ 00697 00698 if (LocalHead) { 00699 fprintf(SUMA_STDERR,"%s: a = %f, b=%f, rad = %f, lgth = %f\n", FuncName, a, b, r, lgth); 00700 } 00701 /*assign ep to be 1/2 the lenth of the maximum final distance between two nodes 00702 (see LNB p3 / p29)*/ 00703 if (strcmp(bin, "y") == 0) { 00704 ep = lgth / pow(2, depth+1); 00705 } 00706 else ep = lgth / (2*depth); 00707 00708 /**create icosahedron node list*/ 00709 nodePtCt = -1; 00710 icosaNode = (float *) SUMA_calloc(3*numNodes, sizeof(float)); 00711 icosaTri = (int *) SUMA_calloc(3*numTri, sizeof(int)); 00712 00713 if (!icosaNode || !icosaTri) { 00714 fprintf (SUMA_STDERR,"Error %s: Could not allocate for icosaNode and/or icosaTri.\n",FuncName); 00715 SUMA_Free_Surface_Object (SO); 00716 SUMA_RETURN (NULL); 00717 } 00718 00719 SUMA_addNode( icosaNode, &nodePtCt, 0+ctr[0], b+ctr[1], -a+ctr[2] ); 00720 SUMA_addNode( icosaNode, &nodePtCt, 0+ctr[0], b+ctr[1], a+ctr[2] ); 00721 SUMA_addNode( icosaNode, &nodePtCt, 0+ctr[0], -b+ctr[1], a+ctr[2] ); 00722 SUMA_addNode( icosaNode, &nodePtCt, 0+ctr[0], -b+ctr[1], -a+ctr[2] ); 00723 SUMA_addNode( icosaNode, &nodePtCt, -b+ctr[0], a+ctr[1], 0+ctr[2] ); 00724 SUMA_addNode( icosaNode, &nodePtCt, -b+ctr[0], -a+ctr[1], 0+ctr[2] ); 00725 SUMA_addNode( icosaNode, &nodePtCt, b+ctr[0], a+ctr[1], 0+ctr[2] ); 00726 SUMA_addNode( icosaNode, &nodePtCt, b+ctr[0], -a+ctr[1], 0+ctr[2] ); 00727 SUMA_addNode( icosaNode, &nodePtCt, a+ctr[0], 0+ctr[1], b+ctr[2] ); 00728 SUMA_addNode( icosaNode, &nodePtCt, -a+ctr[0], 0+ctr[1], -b+ctr[2] ); 00729 SUMA_addNode( icosaNode, &nodePtCt, -a+ctr[0], 0+ctr[1], b+ctr[2] ); 00730 SUMA_addNode( icosaNode, &nodePtCt, a+ctr[0], 0+ctr[1], -b+ctr[2] ); 00731 00732 /**tesselate icosahedron*/ 00733 00734 triPtCt = -1; 00735 00736 /**if recursion depth is 0, just make icosahedron (no tesselation)*/ 00737 if (depth==0) { 00738 00739 SUMA_addTri( icosaTri, &triPtCt, 0, 4, 6 ); SUMA_addTri( icosaTri, &triPtCt, 1, 6, 4 ); 00740 SUMA_addTri( icosaTri, &triPtCt, 0, 9, 4 ); SUMA_addTri( icosaTri, &triPtCt, 1, 8, 6 ); 00741 SUMA_addTri( icosaTri, &triPtCt, 0, 3, 9 ); SUMA_addTri( icosaTri, &triPtCt, 1, 2, 8 ); 00742 SUMA_addTri( icosaTri, &triPtCt, 0, 11, 3 ); SUMA_addTri( icosaTri, &triPtCt, 1, 10, 2 ); 00743 SUMA_addTri( icosaTri, &triPtCt, 0, 6, 11 ); SUMA_addTri( icosaTri, &triPtCt, 1, 4, 10 ); 00744 SUMA_addTri( icosaTri, &triPtCt, 2, 7, 8 ); SUMA_addTri( icosaTri, &triPtCt, 3, 11, 7 ); 00745 SUMA_addTri( icosaTri, &triPtCt, 2, 5, 7 ); SUMA_addTri( icosaTri, &triPtCt, 3, 7, 5 ); 00746 SUMA_addTri( icosaTri, &triPtCt, 2, 10, 5 ); SUMA_addTri( icosaTri, &triPtCt, 3, 5, 9 ); 00747 SUMA_addTri( icosaTri, &triPtCt, 4, 9, 10 ); SUMA_addTri( icosaTri, &triPtCt, 6, 8, 11 ); 00748 SUMA_addTri( icosaTri, &triPtCt, 5, 10, 9 ); SUMA_addTri( icosaTri, &triPtCt, 7, 11, 8 ); 00749 } 00750 00751 else { 00752 if (strcmp(bin, "y") == 0) { 00753 /*binary tesselation*/ 00754 SUMA_binTesselate(icosaNode, icosaTri, &nodePtCt, &triPtCt, depth, 1, 0, 4, 6); 00755 SUMA_binTesselate(icosaNode, icosaTri, &nodePtCt, &triPtCt, depth, 1, 0, 9, 4 ); 00756 SUMA_binTesselate(icosaNode, icosaTri, &nodePtCt, &triPtCt, depth, 1, 0, 3, 9 ); 00757 SUMA_binTesselate(icosaNode, icosaTri, &nodePtCt, &triPtCt, depth, 1, 0, 11, 3 ); 00758 SUMA_binTesselate(icosaNode, icosaTri, &nodePtCt, &triPtCt, depth, 1, 0, 6, 11 ); 00759 00760 SUMA_binTesselate(icosaNode, icosaTri, &nodePtCt, &triPtCt, depth, 1, 1, 6, 4 ); 00761 SUMA_binTesselate(icosaNode, icosaTri, &nodePtCt, &triPtCt, depth, 1, 1, 8, 6 ); 00762 SUMA_binTesselate(icosaNode, icosaTri, &nodePtCt, &triPtCt, depth, 1, 1, 2, 8 ); 00763 SUMA_binTesselate(icosaNode, icosaTri, &nodePtCt, &triPtCt, depth, 1, 1, 10, 2 ); 00764 SUMA_binTesselate(icosaNode, icosaTri, &nodePtCt, &triPtCt, depth, 1, 1, 4, 10 ); 00765 00766 SUMA_binTesselate(icosaNode, icosaTri, &nodePtCt, &triPtCt, depth, 1, 2, 7, 8 ); 00767 SUMA_binTesselate(icosaNode, icosaTri, &nodePtCt, &triPtCt, depth, 1, 2, 5, 7 ); 00768 SUMA_binTesselate(icosaNode, icosaTri, &nodePtCt, &triPtCt, depth, 1, 2, 10, 5 ); 00769 SUMA_binTesselate(icosaNode, icosaTri, &nodePtCt, &triPtCt, depth, 1, 4, 9, 10 ); 00770 SUMA_binTesselate(icosaNode, icosaTri, &nodePtCt, &triPtCt, depth, 1, 5, 10, 9 ); 00771 00772 SUMA_binTesselate(icosaNode, icosaTri, &nodePtCt, &triPtCt, depth, 1, 3, 11, 7 ); 00773 SUMA_binTesselate(icosaNode, icosaTri, &nodePtCt, &triPtCt, depth, 1, 3, 7, 5 ); 00774 SUMA_binTesselate(icosaNode, icosaTri, &nodePtCt, &triPtCt, depth, 1, 3, 5, 9 ); 00775 SUMA_binTesselate(icosaNode, icosaTri, &nodePtCt, &triPtCt, depth, 1, 6, 8, 11 ); 00776 SUMA_binTesselate(icosaNode, icosaTri, &nodePtCt, &triPtCt, depth, 1, 7, 11, 8 ); 00777 } 00778 00779 else { 00780 /*brute tesselation*/ 00781 SUMA_tesselate(icosaNode, icosaTri, &nodePtCt, &triPtCt, depth, 0, 4, 6); 00782 SUMA_tesselate(icosaNode, icosaTri, &nodePtCt, &triPtCt, depth, 0, 9, 4 ); 00783 SUMA_tesselate(icosaNode, icosaTri, &nodePtCt, &triPtCt, depth, 0, 3, 9 ); 00784 SUMA_tesselate(icosaNode, icosaTri, &nodePtCt, &triPtCt, depth, 0, 11, 3 ); 00785 SUMA_tesselate(icosaNode, icosaTri, &nodePtCt, &triPtCt, depth, 0, 6, 11 ); 00786 00787 SUMA_tesselate(icosaNode, icosaTri, &nodePtCt, &triPtCt, depth, 1, 6, 4 ); 00788 SUMA_tesselate(icosaNode, icosaTri, &nodePtCt, &triPtCt, depth, 1, 8, 6 ); 00789 SUMA_tesselate(icosaNode, icosaTri, &nodePtCt, &triPtCt, depth, 1, 2, 8 ); 00790 SUMA_tesselate(icosaNode, icosaTri, &nodePtCt, &triPtCt, depth, 1, 10, 2 ); 00791 SUMA_tesselate(icosaNode, icosaTri, &nodePtCt, &triPtCt, depth, 1, 4, 10 ); 00792 00793 SUMA_tesselate(icosaNode, icosaTri, &nodePtCt, &triPtCt, depth, 2, 7, 8 ); 00794 SUMA_tesselate(icosaNode, icosaTri, &nodePtCt, &triPtCt, depth, 2, 5, 7 ); 00795 SUMA_tesselate(icosaNode, icosaTri, &nodePtCt, &triPtCt, depth, 2, 10, 5 ); 00796 SUMA_tesselate(icosaNode, icosaTri, &nodePtCt, &triPtCt, depth, 4, 9, 10 ); 00797 SUMA_tesselate(icosaNode, icosaTri, &nodePtCt, &triPtCt, depth, 5, 10, 9 ); 00798 00799 SUMA_tesselate(icosaNode, icosaTri, &nodePtCt, &triPtCt, depth, 3, 11, 7 ); 00800 SUMA_tesselate(icosaNode, icosaTri, &nodePtCt, &triPtCt, depth, 3, 7, 5 ); 00801 SUMA_tesselate(icosaNode, icosaTri, &nodePtCt, &triPtCt, depth, 3, 5, 9 ); 00802 SUMA_tesselate(icosaNode, icosaTri, &nodePtCt, &triPtCt, depth, 6, 8, 11 ); 00803 SUMA_tesselate(icosaNode, icosaTri, &nodePtCt, &triPtCt, depth, 7, 11, 8 ); 00804 } 00805 } 00806 00807 numNodes = (nodePtCt+1)/3; 00808 numTri = (triPtCt+1)/3; 00809 00810 if (LocalHead) fprintf(SUMA_STDERR,"%s: There are %d nodes, %d triangles in the icosahedron.\n", FuncName, numNodes, numTri); 00811 00812 /* store in SO and get out */ 00813 SO->NodeList = icosaNode; 00814 SO->FaceSetList = icosaTri; 00815 SO->N_Node = numNodes; 00816 SO->N_FaceSet = numTri; 00817 SO->NodeDim = 3; 00818 SO->FaceSetDim = 3; 00819 SO->idcode_str = (char *)SUMA_calloc (SUMA_IDCODE_LENGTH, sizeof(char)); 00820 UNIQ_idcode_fill (SO->idcode_str); 00821 00822 /* check the winding ? */ 00823 if (DoWind) { 00824 if (LocalHead) fprintf(SUMA_STDOUT, "%s: Making Edge list ....\n", FuncName); 00825 SO->EL = SUMA_Make_Edge_List_eng (SO->FaceSetList, SO->N_FaceSet, SO->N_Node, SO->NodeList, 0, SO->idcode_str); 00826 if (SO->EL == NULL) { 00827 fprintf(SUMA_STDERR, "Error %s: Failed in SUMA_Make_Edge_List. Neighbor list will not be created\n", FuncName); 00828 SUMA_Free_Surface_Object (SO); 00829 SUMA_RETURN (NULL); 00830 } else { 00831 } 00832 00833 if (!SUMA_MakeConsistent (SO->FaceSetList, SO->N_FaceSet, SO->EL, 0, &trouble)) { 00834 fprintf(SUMA_STDERR,"Error %s: Failed in SUMA_MakeConsistent.\n", FuncName); 00835 SUMA_Free_Surface_Object (SO); 00836 SUMA_RETURN (NULL); 00837 } 00838 else { 00839 if (LocalHead) fprintf(SUMA_STDERR,"%s: Eeeexcellent. All triangles consistent.\n", FuncName); 00840 } 00841 /* determine the MemberFaceSets */ 00842 if (LocalHead) fprintf(SUMA_STDOUT, "%s: Determining MemberFaceSets ...\n", FuncName); 00843 SO->MF = SUMA_MemberFaceSets(SO->N_Node, SO->FaceSetList, SO->N_FaceSet, SO->FaceSetDim, SO->idcode_str); 00844 if (SO->MF->NodeMemberOfFaceSet == NULL) { 00845 fprintf(SUMA_STDERR,"Error %s: Error in SUMA_MemberFaceSets\n", FuncName); 00846 SUMA_Free_Surface_Object (SO); /* that takes care of freeing leftovers in MF */ 00847 SUMA_RETURN (NULL); 00848 }else { /* create Inode to avoid whining upon cleanup */ 00849 } 00850 00851 00852 } 00853 00854 /* project to sphere ? */ 00855 if (ToSphere) { 00856 float dv, uv[3], U[2][3], *p1; 00857 for (i=0; i<SO->N_Node; ++i) { 00858 i3 = 3*i; 00859 p1 = &(SO->NodeList[i3]); 00860 /* SUMA_UNIT_VEC(ctr, p1, uv, dv); */ 00861 uv[0] = p1[0] - ctr[0]; uv[1] = p1[1] - ctr[1]; uv[2] = p1[2] - ctr[2]; 00862 SUMA_POINT_AT_DISTANCE(uv, ctr, r, U); 00863 SO->NodeList[i3 ] = U[0][0]; SO->NodeList[i3+1] = U[0][1]; SO->NodeList[i3+2] = U[0][2]; 00864 } 00865 } 00866 00867 /* create surface normals */ 00868 SN = SUMA_SurfNorm( SO->NodeList, SO->N_Node, SO->FaceSetList, SO->N_FaceSet); 00869 SO->NodeNormList = SN.NodeNormList; 00870 SO->FaceNormList = SN.FaceNormList; 00871 00872 /*create first neighbor list*/ 00873 if ( SO->EL && SO->N_Node ) 00874 firstNeighb = SUMA_Build_FirstNeighb( SO->EL, SO->N_Node, SO->idcode_str); 00875 00876 if (!DoWind) SO->EL = SUMA_Make_Edge_List (SO->FaceSetList, SO->N_FaceSet, SO->N_Node, SO->NodeList, SO->idcode_str); 00877 SO->FN = SUMA_Build_FirstNeighb( SO->EL, SO->N_Node, SO->idcode_str); 00878 if(SO->FN==NULL) { 00879 fprintf(SUMA_STDERR, "Error %s: Failed in creating neighb list.\n", FuncName); 00880 } else { 00881 } 00882 00883 00884 SUMA_RETURN (SO); 00885 } |
|
weight = SUMA_detWeight ( node0, node1, node2, hitPt ); This function determines the weight of each of three nodes on a given point based upon distance.
Definition at line 1020 of file SUMA_SphericalMapping.c. References i, intersection_map(), s2, SUMA_calloc, SUMA_ENTRY, and SUMA_RETURN.
01020 { 01021 01022 int i=0; 01023 float triNode0[3], triNode1[3], triNode2[3]; 01024 float p00[3], p01[3], p02[3]; 01025 float p10[3], p11[3], p12[3]; 01026 float p20[3], p21[3], p22[3]; 01027 float tri0[3], tri1[3], tri2[3], triOrig[3]; 01028 float s0=0, s1=0, s2=0, sOrig=0, A0=0, A1=0, A2=0, Aorig=0; 01029 float wsum=0, *weight=NULL; 01030 static char FuncName[]={"SUMA_detWeight"}; 01031 01032 SUMA_ENTRY; 01033 01034 /*weights determined by linear interpolation based on areas of triangles resulting 01035 from lines parallel to edges of hit triangle and intersecting ptHit (see p6-12 LNB)*/ 01036 01037 p00[0] = node0[0]; p00[1] = node0[1]; p00[2] = node0[2]; 01038 p11[0] = node1[0]; p11[1] = node1[1]; p11[2] = node1[2]; 01039 p22[0] = node2[0]; p22[1] = node2[1]; p22[2] = node2[2]; 01040 01041 /**end points of parallel lines*/ 01042 01043 /** (nodes of subtriangle / associated with original node) */ 01044 /** (p00,p01,p02 / triNode0), (p10,p11,p12 / triNode1), (p20,p21,p22 / triNode2)*/ 01045 for (i=0; i<3; ++i) { 01046 /*assign p01*/ 01047 if (p00[i]==p22[i]) { p01[i] = intersection_map( p11[i], p22[i], p00[i], p11[i], ptHit[i] ); } 01048 else { p01[i] = intersection_map( p11[i], p22[i], p11[i], p00[i], ptHit[i] ); } 01049 /*assign p02*/ 01050 if (p11[i]==p00[i]) { p02[i] = intersection_map( p11[i], p22[i], p22[i], p00[i], ptHit[i] ); } 01051 else { p02[i] = intersection_map( p11[i], p22[i], p00[i], p22[i], ptHit[i] ); } 01052 /*assign p10*/ 01053 if (p22[i]==p11[i]) { p10[i] = intersection_map( p22[i], p00[i], p00[i], p11[i], ptHit[i] ); } 01054 else { p10[i] = intersection_map( p22[i], p00[i], p11[i], p00[i], ptHit[i] ); } 01055 /*assign p12*/ 01056 if (p11[i]==p00[i]) { p12[i] = intersection_map( p22[i], p00[i], p11[i], p22[i], ptHit[i] ); } 01057 else { p12[i] = intersection_map( p22[i], p00[i], p22[i], p11[i], ptHit[i] ); } 01058 /*assign p20*/ 01059 if (p22[i]==p11[i]) { p20[i] = intersection_map( p00[i], p11[i], p22[i], p00[i], ptHit[i] ); } 01060 else { p20[i] = intersection_map( p00[i], p11[i], p00[i], p22[i], ptHit[i] ); } 01061 /*assign p21*/ 01062 if (p00[i]==p22[i]) { p21[i] = intersection_map( p00[i], p11[i], p11[i], p22[i], ptHit[i] ); } 01063 else { p21[i] = intersection_map( p00[i], p11[i], p22[i], p11[i], ptHit[i] ); } 01064 } 01065 01066 /**length of subtriangle edges*/ 01067 01068 tri0[0] = sqrt( pow(p01[0]-p00[0],2) + pow(p01[1]-p00[1],2) + pow(p01[2]-p00[2],2) ); 01069 tri0[1] = sqrt( pow(p02[0]-p01[0],2) + pow(p02[1]-p01[1],2) + pow(p02[2]-p01[2],2) ); 01070 tri0[2] = sqrt( pow(p00[0]-p02[0],2) + pow(p00[1]-p02[1],2) + pow(p00[2]-p02[2],2) ); 01071 01072 tri1[0] = sqrt( pow(p11[0]-p10[0],2) + pow(p11[1]-p10[1],2) + pow(p11[2]-p10[2],2) ); 01073 tri1[1] = sqrt( pow(p12[0]-p11[0],2) + pow(p12[1]-p11[1],2) + pow(p12[2]-p11[2],2) ); 01074 tri1[2] = sqrt( pow(p10[0]-p12[0],2) + pow(p10[1]-p12[1],2) + pow(p10[2]-p12[2],2) ); 01075 01076 tri2[0] = sqrt( pow(p21[0]-p20[0],2) + pow(p21[1]-p20[1],2) + pow(p21[2]-p20[2],2) ); 01077 tri2[1] = sqrt( pow(p22[0]-p21[0],2) + pow(p22[1]-p21[1],2) + pow(p22[2]-p21[2],2) ); 01078 tri2[2] = sqrt( pow(p20[0]-p22[0],2) + pow(p20[1]-p22[1],2) + pow(p20[2]-p22[2],2) ); 01079 01080 /**area of subtriangles*/ 01081 01082 s0 = .5*(tri0[0] + tri0[1] + tri0[2]); 01083 s1 = .5*(tri1[0] + tri1[1] + tri1[2]); 01084 s2 = .5*(tri2[0] + tri2[1] + tri2[2]); 01085 01086 A0 = sqrt( s0*(s0-tri0[0])*(s0-tri0[1])*(s0-tri0[2]) ); 01087 A1 = sqrt( s1*(s1-tri1[0])*(s1-tri1[1])*(s1-tri1[2]) ); 01088 A2 = sqrt( s2*(s2-tri2[0])*(s2-tri2[1])*(s2-tri2[2]) ); 01089 01090 /*length of edges and area of original triangle*/ 01091 01092 triOrig[0] = sqrt( pow(p11[0]-p00[0],2) + pow(p11[1]-p00[1],2) + pow(p11[2]-p00[2],2) ); 01093 triOrig[1] = sqrt( pow(p22[0]-p11[0],2) + pow(p22[1]-p11[1],2) + pow(p22[2]-p11[2],2) ); 01094 triOrig[2] = sqrt( pow(p00[0]-p22[0],2) + pow(p00[1]-p22[1],2) + pow(p00[2]-p22[2],2) ); 01095 01096 sOrig = .5*(triOrig[0] + triOrig[1] + triOrig[2]); 01097 Aorig = sqrt( sOrig*(sOrig-triOrig[0])*(sOrig-triOrig[1])*(sOrig-triOrig[2]) ); 01098 01099 /**weights*/ 01100 weight = (float *)SUMA_calloc( 3, sizeof(float) ); 01101 weight[0] = (Aorig-A0)/Aorig; weight[1] = (Aorig-A1)/Aorig; weight[2] = (Aorig-A2)/Aorig; 01102 wsum = weight[0] + weight[1] + weight[2]; 01103 weight[0] = weight[0]/wsum; weight[1] = weight[1]/wsum; weight[2] = weight[2]/wsum; 01104 01105 // fprintf(SUMA_STDERR, "weight: (%f, %f, %f)\n", weight[0], weight[1], weight[2]); 01106 01107 SUMA_RETURN (weight); 01108 01109 } |
|
edge = SUMA_divEdge( nodeList, nCtr, node1, node2, N_Div); Divides an edge defined by node1-node2 into N_Div segments.
Definition at line 476 of file SUMA_SphericalMapping.c. References ep, i, n1, n2, SUMA_addNode(), SUMA_calloc, SUMA_ENTRY, SUMA_free, and SUMA_RETURN. Referenced by SUMA_tesselate().
00476 { 00477 00478 float *newNodes = NULL; 00479 float n1[3], n2[3]; 00480 int *edge = NULL; 00481 int i=0, j=0, k=0, m=0; 00482 int currIndex = (nCtr[0]-2)/3; 00483 static char FuncName[]={"SUMA_divEdge"}; 00484 00485 SUMA_ENTRY; 00486 00487 00488 edge = (int *) SUMA_calloc(N_Div+1, sizeof(int)); 00489 newNodes = (float *)SUMA_calloc (3*(N_Div-1), sizeof(float)); 00490 00491 if (!edge || !newNodes) { 00492 fprintf (SUMA_STDERR, "Error %s: Failed to allocate.\n", FuncName); 00493 SUMA_RETURN (edge); 00494 } 00495 00496 for(i=0; i<N_Div+1; ++i) { 00497 edge[i] = -1; 00498 } 00499 00500 edge[0] = node1; edge[N_Div] = node2; 00501 00502 n1[0] = nodeList[3*node1]; n1[1] = nodeList[3*node1+1]; n1[2] = nodeList[3*node1+2]; 00503 n2[0] = nodeList[3*node2]; n2[1] = nodeList[3*node2+1]; n2[2] = nodeList[3*node2+2]; 00504 00505 /*create new nodes*/ 00506 for(i=0; i<N_Div-1; ++i) { 00507 j = 3*i; 00508 newNodes[j] = ((i+1.0)/(float)N_Div)*(n2[0]-n1[0]) + n1[0]; 00509 newNodes[j+1] = ((i+1.0)/(float)N_Div)*(n2[1]-n1[1]) + n1[1]; 00510 newNodes[j+2] = ((i+1.0)/(float)N_Div)*(n2[2]-n1[2]) + n1[2]; 00511 } 00512 00513 /*check for existing nodes*/ 00514 for (i=0; i<=currIndex; ++i) { 00515 j = 3*i; 00516 for (m=0; m<N_Div-1; ++m) { 00517 k = 3*m; 00518 if ( fabs(nodeList[j]-newNodes[k])<ep && fabs(nodeList[j+1]-newNodes[k+1])<ep && 00519 fabs(nodeList[j+2]-newNodes[k+2])<ep ) { 00520 edge[m+1] = i; 00521 } 00522 } 00523 } 00524 00525 for (i=1; i<N_Div; ++i) { 00526 if (edge[i]==-1) { 00527 SUMA_addNode( nodeList, nCtr, newNodes[3*(i-1)], newNodes[3*(i-1)+1], newNodes[3*(i-1)+2]); 00528 edge[i] = (nCtr[0]-2)/3; 00529 } 00530 } 00531 00532 if (newNodes) SUMA_free(newNodes); 00533 00534 SUMA_RETURN (edge); 00535 } |
|
function to free SUMA_1dData structure Definition at line 4283 of file SUMA_SphericalMapping.c. References SUMA_1dData::ijk_list, SUMA_1dData::nd_list, SUMA_1dData::nvox_list, SUMA_Boolean, SUMA_ENTRY, SUMA_free, SUMA_RETURN, SUMA_1dData::valArray, and SUMA_1dData::vxl_list.
04284 { 04285 static char FuncName[]={"SUMA_Free_1dData"}; 04286 04287 SUMA_ENTRY; 04288 04289 if (!data) { 04290 SUMA_RETURN (YUP); 04291 } 04292 if (data->nd_list) SUMA_free (data->nd_list); 04293 if (data->vxl_list) SUMA_free (data->vxl_list); 04294 if (data->ijk_list) SUMA_free (data->ijk_list); 04295 if (data->nvox_list) SUMA_free (data->nvox_list); 04296 if (data->valArray) SUMA_free (data->valArray); 04297 04298 SUMA_free (data); 04299 04300 SUMA_RETURN (YUP); 04301 } |
|
function to free MorphInfo Definition at line 1804 of file SUMA_SphericalMapping.c. References SUMA_MorphInfo::ClsNodes, SUMA_MorphInfo::FaceSetList, SUMA_MorphInfo::IDcode, SUMA_Boolean, SUMA_ENTRY, SUMA_free, SUMA_RETURN, and SUMA_MorphInfo::Weight.
01805 { 01806 static char FuncName[]={"SUMA_Free_MorphInfo"}; 01807 01808 SUMA_ENTRY; 01809 01810 if (!MI) { 01811 SUMA_RETURN (YUP); 01812 } 01813 01814 if (MI->IDcode) SUMA_free (MI->IDcode); 01815 if (MI->Weight) SUMA_free (MI->Weight); 01816 if (MI->ClsNodes) SUMA_free (MI->ClsNodes); 01817 if (MI->FaceSetList) SUMA_free (MI->FaceSetList); 01818 01819 SUMA_free (MI); 01820 01821 SUMA_RETURN (YUP); 01822 } |
|
function to free SO_map Definition at line 1725 of file SUMA_SphericalMapping.c. References SUMA_SO_map::NewNodeList, SUMA_SO_map::NodeCol, SUMA_SO_map::NodeDisp, SUMA_SO_map::NodeVal, SUMA_Boolean, SUMA_ENTRY, SUMA_free, and SUMA_RETURN.
01726 { 01727 static char FuncName[]={"SUMA_Free_SO_map"}; 01728 01729 SUMA_ENTRY; 01730 01731 if (!SOM) { 01732 SUMA_RETURN (YUP); 01733 } 01734 01735 if (SOM->NewNodeList) SUMA_free (SOM->NewNodeList); 01736 if (SOM->NodeVal) SUMA_free (SOM->NodeVal); 01737 if (SOM->NodeDisp) SUMA_free (SOM->NodeDisp); 01738 if (SOM->NodeCol) SUMA_free(SOM->NodeCol); 01739 01740 SUMA_free (SOM); 01741 01742 SUMA_RETURN (YUP); 01743 } |
|
SUMA_Boolean = SUMA_inNodeNeighb( surf, nodeList, node, PO, P1); Determines whether or not point P1 is inside of triangles of which node[0] or [1] or [2] is a node.
Definition at line 904 of file SUMA_SphericalMapping.c. References SUMA_SurfaceObject::EL, SUMA_SurfaceObject::FaceSetList, SUMA_NODE_FIRST_NEIGHB::FirstNeighb, SUMA_SurfaceObject::FN, i, SUMA_MT_INTERSECT_TRIANGLE::ifacemin, LocalHead, SUMA_SurfaceObject::N_FaceSet, SUMA_MT_INTERSECT_TRIANGLE::N_hits, SUMA_NODE_FIRST_NEIGHB::N_Neighb, SUMA_SurfaceObject::N_Node, SUMA_SurfaceObject::NodeList, SUMA_MT_INTERSECT_TRIANGLE::P, SUMA_Boolean, SUMA_ENTRY, SUMA_Free_MT_intersect_triangle(), SUMA_Get_Incident(), SUMA_IS_IN_VEC, SUMA_MT_intersect_triangle(), SUMA_MT_isIntersect_Triangle(), and SUMA_RETURN. Referenced by SUMA_MapSurface().
00904 { 00905 00906 int i=0, j=0, k=0, examinedNum=0; 00907 SUMA_Boolean found=NOPE; 00908 float hitOnSurf[3]; 00909 int incidentTri[100], N_incident = 0, itry; 00910 int examinedTri[100], ifound, i_node0 = -1, i_node1 = -1, i_node2 = -1; 00911 SUMA_Boolean LocalHead = NOPE; 00912 static char FuncName[]={"SUMA_inNodeNeighb"}; 00913 00914 SUMA_ENTRY; 00915 00916 if (nodeList==NULL) { 00917 fprintf (SUMA_STDERR, "Warning %s: Assigning surf->NodeList to nodeList.\n", FuncName); 00918 nodeList = surf->NodeList; 00919 } 00920 00921 if (LocalHead) fprintf(SUMA_STDERR, "%s: P0-P1 [%f, %f, %f] - [%f, %f, %f]\n", 00922 FuncName, P0[0], P0[1], P0[2], P1[0], P1[1], P1[2]); 00923 00924 found = NOPE; 00925 itry = 0; 00926 examinedNum = 0; 00927 while (itry < 3 && node[itry] >= 0 && !found) { 00928 if (LocalHead) fprintf(SUMA_STDERR, "%s: Trying neighbors of node %d.\n", FuncName, node[itry]); 00929 i = 0; 00930 while ((i < surf->FN->N_Neighb[node[itry]] ) && !found) { 00931 00932 if (!SUMA_Get_Incident( node[itry], surf->FN->FirstNeighb[node[itry]][i], surf->EL, incidentTri, &N_incident, 1)) { 00933 fprintf (SUMA_STDERR,"Error %s: Failed in SUMA_Get_Incident.\n", FuncName); 00934 SUMA_RETURN (NOPE); 00935 } 00936 00937 /**check triangles incident to current edge*/ 00938 j = 0; 00939 while ((j < N_incident) && !found) { 00940 00941 /**triangle in list?*/ 00942 SUMA_IS_IN_VEC(examinedTri, examinedNum, incidentTri[j], ifound); 00943 00944 /**if not found , add index to list and test for intersection*/ 00945 if (ifound < 0) { 00946 examinedTri[examinedNum] = incidentTri[j]; 00947 ++examinedNum; 00948 00949 i_node0 = surf->FaceSetList[ 3*incidentTri[j] ]; 00950 i_node1 = surf->FaceSetList[ 3*incidentTri[j]+1 ]; 00951 i_node2 = surf->FaceSetList[ 3*incidentTri[j]+2 ]; 00952 00953 if (SUMA_MT_isIntersect_Triangle (P0, P1, &(nodeList[3*i_node0]), &(nodeList[3*i_node1]), 00954 &(nodeList[3*i_node2]), hitOnSurf, NULL, NULL)) { 00955 found = YUP; 00956 node[0] = i_node0; 00957 node[1] = i_node1; 00958 node[2] = i_node2; 00959 if (LocalHead) { 00960 fprintf(SUMA_STDERR, "%s: Triangle %d [%d, %d, %d] is intersected at (%f, %f, %f)\n", 00961 FuncName, incidentTri[j], node[0], node[1], node[2], hitOnSurf[0], hitOnSurf[1], hitOnSurf[2]); 00962 fprintf(SUMA_STDERR, "%s: Coordinates of nodes forming triangle are:\n", FuncName); 00963 fprintf(SUMA_STDERR, "%f, %f, %f\n", nodeList[3*i_node0], nodeList[3*i_node0+1], nodeList[3*i_node0+2]); 00964 fprintf(SUMA_STDERR, "%f, %f, %f\n", nodeList[3*i_node1], nodeList[3*i_node1+1], nodeList[3*i_node1+2]); 00965 fprintf(SUMA_STDERR, "%f, %f, %f\n", nodeList[3*i_node2], nodeList[3*i_node2+1], nodeList[3*i_node2+2]); 00966 } 00967 #if 0 /* turn on to compare intersection results to those obtained with SUMA_MT_intersect_triangle */ 00968 { 00969 /* try the other (slower) method for intersection and compare results*/ 00970 SUMA_MT_INTERSECT_TRIANGLE *MTI; 00971 MTI = SUMA_MT_intersect_triangle (P1, P0, nodeList, surf->N_Node, surf->FaceSetList, surf->N_FaceSet, NULL); 00972 if (MTI) { 00973 if (LocalHead)fprintf(SUMA_STDERR, "%s: Meth2-Triangle %d [%d, %d, %d] is intersected at (%f, %f, %f)\n", 00974 FuncName, MTI->ifacemin, surf->FaceSetList[3*MTI->ifacemin], surf->FaceSetList[3*MTI->ifacemin+1], 00975 surf->FaceSetList[3*MTI->ifacemin+2], MTI->P[0], MTI->P[1], MTI->P[2]); 00976 00977 if (MTI->N_hits) { 00978 /* compare results */ 00979 if (MTI->ifacemin != incidentTri[j]) { 00980 fprintf (SUMA_STDERR,"Error %s: Warning, mismatch in results of triangle intersection. This should not be\n", FuncName); 00981 exit(1); 00982 } 00983 } 00984 00985 MTI = SUMA_Free_MT_intersect_triangle(MTI); 00986 } 00987 00988 } 00989 #endif 00990 00991 P1[0] = hitOnSurf[0]; P1[1] = hitOnSurf[1]; P1[2] = hitOnSurf[2]; 00992 }else { 00993 if (LocalHead)fprintf(SUMA_STDERR, "%s: Triangle %d [%d, %d, %d] is not intersected.\n", 00994 FuncName, incidentTri[j], i_node0, i_node1, i_node2); 00995 } 00996 } 00997 ++j; 00998 } 00999 ++i; 01000 } 01001 ++itry; 01002 } 01003 01004 SUMA_RETURN (found); 01005 } |
|
MI = MapSurface (surf1, surf2); This function creates a mapping of one surface onto another (surfaces assumed to be spherical).
Definition at line 1197 of file SUMA_SphericalMapping.c. References abs, SUMA_MorphInfo::ClsNodes, SUMA_SurfaceObject::FaceSetList, SUMA_MorphInfo::FaceSetList, SUMA_SurfaceObject::FN, i, SUMA_MT_INTERSECT_TRIANGLE::ifacemin, LocalHead, SUMA_SurfaceObject::N_FaceSet, SUMA_MorphInfo::N_FaceSet, SUMA_MT_INTERSECT_TRIANGLE::N_hits, SUMA_SurfaceObject::N_Node, SUMA_MorphInfo::N_Node, SUMA_SurfaceObject::NodeList, SUMA_MT_INTERSECT_TRIANGLE::P, SUMA_binSearch(), SUMA_Boolean, SUMA_calloc, SUMA_Create_MorphInfo(), SUMA_ENTRY, SUMA_free, SUMA_Free_MT_intersect_triangle(), SUMA_inNodeNeighb(), SUMA_MT_intersect_triangle(), SUMA_RETURN, SUMA_Search_Min_Dist(), SUMA_TRI_AREA, SUMA_z_qsort(), and SUMA_MorphInfo::Weight.
01198 { 01199 static char FuncName[]={"SUMA_MapSurface"}; 01200 01201 /**surf1 variables*/ 01202 int numNodes_1=0, numFace_1=0; 01203 float *nodeList_1=NULL, *ctrNodeList_1=NULL; 01204 int *faceList_1=NULL; 01205 01206 /**surf2 variables*/ 01207 int numNodes_2=0, numFace_2=0; 01208 float *nodeList_2=NULL, *ctrNodeList_2=NULL; 01209 int *faceList_2=NULL; 01210 01211 int i=0, j=0, k=0, m=0, j_srtd; 01212 float *weight=NULL; 01213 int *clsNodes=NULL; 01214 SUMA_MorphInfo *MI; 01215 float ctr1[3], ctr2[3], zero[3], r2, dist_tmp; 01216 float *justX_2=NULL, *justX_1=NULL, *srtdX_ctrNodeList_2=NULL; 01217 int *i_SrtdX_2=NULL; 01218 int N_outliers; 01219 float currNode[3], ptHit[3], currDist=0, avgDist=0.0, pi=3.14159265359; 01220 int seg[2], i_node[3]; 01221 float min_dist[3], curr_restr; 01222 01223 SUMA_Boolean found=NOPE; 01224 float *triNode0, *triNode1, *triNode2, weight_tot; 01225 SUMA_SO_map *SO=NULL; 01226 SUMA_Boolean LocalHead = NOPE; 01227 01228 SUMA_ENTRY; 01229 01230 MI = SUMA_Create_MorphInfo(); 01231 if (MI == NULL) { 01232 fprintf (SUMA_STDERR,"Error %s: Failed to allocate for MorphInfo.\n", FuncName); 01233 SUMA_RETURN (NULL); 01234 } 01235 01236 /**assign surf1 variables*/ 01237 nodeList_1 = surf1->NodeList; 01238 faceList_1 = surf1->FaceSetList; 01239 numNodes_1 = surf1->N_Node; 01240 numFace_1 = surf1->N_FaceSet; 01241 01242 /**assign surf2 variables*/ 01243 nodeList_2 = surf2->NodeList; 01244 faceList_2 = surf2->FaceSetList; 01245 numNodes_2 = surf2->N_Node; 01246 numFace_2 = surf2->N_FaceSet; 01247 01248 clsNodes = (int *)SUMA_calloc( 3*numNodes_1, sizeof(int) ); 01249 weight = (float *)SUMA_calloc( 3*numNodes_1, sizeof(float) ); 01250 if (!clsNodes || !weight) { 01251 if (clsNodes) SUMA_free(clsNodes); 01252 if (weight) SUMA_free(weight); 01253 fprintf (SUMA_STDERR,"Error %s: Failed to allocate for clsNodes || weight.\n", FuncName); 01254 SUMA_RETURN (NULL); 01255 } 01256 01257 01258 /**center surf1 to surf2 (that will make it easier to debug in SUMA)*/ 01259 01260 /*first find centers of each surface*/ 01261 ctr1[0]=0; ctr1[1]=0; ctr1[2]=0; 01262 ctr2[0]=0; ctr2[1]=0; ctr2[2]=0; 01263 zero[0]=0; zero[1]=0; zero[2]=0; 01264 01265 for (i=0; i<numNodes_1; ++i) { 01266 j = 3*i; 01267 ctr1[0] = ctr1[0] + nodeList_1[j]; 01268 ctr1[1] = ctr1[1] + nodeList_1[j+1]; 01269 ctr1[2] = ctr1[2] + nodeList_1[j+2]; 01270 } 01271 ctr1[0] = ctr1[0]/numNodes_1; 01272 ctr1[1] = ctr1[1]/numNodes_1; 01273 ctr1[2] = ctr1[2]/numNodes_1; 01274 01275 for (i=0; i<numNodes_2; ++i) { 01276 j = 3*i; 01277 ctr2[0] = ctr2[0] + nodeList_2[j]; 01278 ctr2[1] = ctr2[1] + nodeList_2[j+1]; 01279 ctr2[2] = ctr2[2] + nodeList_2[j+2]; 01280 } 01281 ctr2[0] = ctr2[0]/numNodes_2; 01282 ctr2[1] = ctr2[1]/numNodes_2; 01283 ctr2[2] = ctr2[2]/numNodes_2; 01284 01285 /* set the zero center to be that of surf 2 */ 01286 zero[0] = ctr2[0]; 01287 zero[1] = ctr2[1]; 01288 zero[2] = ctr2[2]; 01289 01290 ctrNodeList_1 = (float *) SUMA_calloc( 3*numNodes_1, sizeof(float) ); 01291 ctrNodeList_2 = (float *) SUMA_calloc( 3*numNodes_2, sizeof(float) ); 01292 if (!ctrNodeList_1 || !ctrNodeList_2) { 01293 if (ctrNodeList_1) SUMA_free(ctrNodeList_1); 01294 if (ctrNodeList_2) SUMA_free(ctrNodeList_2); 01295 if (clsNodes) SUMA_free(clsNodes); 01296 if (weight) SUMA_free(weight); 01297 if (i_SrtdX_2) SUMA_free(i_SrtdX_2); 01298 if (justX_2) SUMA_free(justX_2); 01299 fprintf (SUMA_STDERR,"Error %s: Failed to allocate for ctrNodeList_1 || ctrNodeList_2.\n", FuncName); 01300 SUMA_RETURN (NULL); 01301 } 01302 01303 /* one of these two loops will be useless if we stick to having zero be the center of the one of the two surfaces.... */ 01304 for (i=0; i<numNodes_1; ++i) { 01305 j = 3*i; 01306 ctrNodeList_1[j] = nodeList_1[j] - ctr1[0] + zero[0]; 01307 ctrNodeList_1[j+1] = nodeList_1[j+1] - ctr1[1] + zero[1]; 01308 ctrNodeList_1[j+2] = nodeList_1[j+2] - ctr1[2] + zero[2]; 01309 } 01310 for (i=0; i<numNodes_2; ++i) { 01311 j = 3*i; 01312 ctrNodeList_2[j] = nodeList_2[j] - ctr2[0] + zero[0]; 01313 ctrNodeList_2[j+1] = nodeList_2[j+1] - ctr2[1] + zero[1]; 01314 ctrNodeList_2[j+2] = nodeList_2[j+2] - ctr2[2] + zero[2]; 01315 } 01316 01317 /*find radius of surf2*/ 01318 /*(in theory should be able to just take distance first node -> center, but freesurfer surfs are not perfectly spherical)*/ 01319 r2 = 0.0; 01320 for (i=0; i<numNodes_2; ++i) { 01321 j = 3*i; 01322 r2 = r2 + 01323 sqrt( pow( ctrNodeList_2[j]-zero[0], 2) + pow( ctrNodeList_2[j+1]-zero[1], 2) + pow( ctrNodeList_2[j+2]-zero[2], 2) ); 01324 } 01325 r2 /= numNodes_2; 01326 01327 avgDist = (4*pi*pow(r2,2))/numNodes_2; //average distance between nodes on surf2 surface+ 01328 01329 01330 /**make certain surf2 is spherical*/ 01331 N_outliers = 0; 01332 for (i=0; i<numNodes_2; ++i) { 01333 j = 3*i; 01334 dist_tmp = sqrt( pow( ctrNodeList_2[j]-zero[0], 2) + pow( ctrNodeList_2[j+1]-zero[1], 2) 01335 + pow( ctrNodeList_2[j+2]-zero[2], 2) ); 01336 if ( abs(dist_tmp-r2)>r2/10) { 01337 /*node does not lie on sphere*/ 01338 if ( N_outliers>(numNodes_2/1000)) { 01339 /*too many outliers -> exit program*/ 01340 fprintf(SUMA_STDERR, "\nError %s: Too many outliers. Surface considered to be non-spherical.\n\n", FuncName); 01341 SUMA_RETURN(NULL); 01342 } 01343 fprintf(SUMA_STDERR, "Warning %s: Outlier detected! Resetting to lie on sphere...\n", FuncName); 01344 N_outliers = N_outliers+1; 01345 ctrNodeList_2[j] = (r2/dist_tmp)*ctrNodeList_2[j]; 01346 ctrNodeList_2[j+1] = (r2/dist_tmp)*ctrNodeList_2[j+1]; 01347 ctrNodeList_2[j+2] = (r2/dist_tmp)*ctrNodeList_2[j+2]; 01348 } 01349 } 01350 01351 01352 /**sort x of NodeList_2*/ 01353 01354 /*create array justX_2 of only X location values*/ 01355 justX_2 = (float *) SUMA_calloc( numNodes_2, sizeof(float) ); 01356 if (!justX_2 ) { 01357 fprintf (SUMA_STDERR,"Error %s: Failed to allocate for justX_2.\n", FuncName); 01358 if (ctrNodeList_1) SUMA_free(ctrNodeList_1); 01359 if (ctrNodeList_2) SUMA_free(ctrNodeList_2); 01360 if (clsNodes) SUMA_free(clsNodes); 01361 if (weight) SUMA_free(weight); 01362 SUMA_RETURN (NULL); 01363 } 01364 01365 for (i=0; i<numNodes_2; ++i) { 01366 j = 3*i; 01367 justX_2[i] = ctrNodeList_2[j]; 01368 } 01369 01370 /*sort justX_2 */ 01371 i_SrtdX_2 = SUMA_z_qsort( justX_2, numNodes_2 ); /*i_SrtdX_2 is array of indices of justX_2 corresponding to sorting*/ 01372 /*justX_2 is returned sorted*/ 01373 if (!i_SrtdX_2) { 01374 fprintf (SUMA_STDERR,"Error %s: Failed in SUMA_z_qsort.\n", FuncName); 01375 if (ctrNodeList_1) SUMA_free(ctrNodeList_1); 01376 if (ctrNodeList_2) SUMA_free(ctrNodeList_2); 01377 if (clsNodes) SUMA_free(clsNodes); 01378 if (weight) SUMA_free(weight); 01379 if (justX_2) SUMA_free(justX_2); 01380 01381 SUMA_RETURN (NULL); 01382 } 01383 01384 /*create sorted ctrNodeList_2 based upon i_SrtdX_2*/ 01385 srtdX_ctrNodeList_2 = SUMA_calloc( 3*numNodes_2, sizeof(float)); 01386 for (i=0; i<numNodes_2; ++i) { 01387 j = 3*i; 01388 j_srtd = 3*i_SrtdX_2[i]; 01389 srtdX_ctrNodeList_2[j] = ctrNodeList_2[j_srtd]; 01390 srtdX_ctrNodeList_2[j+1] = ctrNodeList_2[j_srtd+1]; 01391 srtdX_ctrNodeList_2[j+2] = ctrNodeList_2[j_srtd+2]; 01392 } 01393 01394 01395 01396 /** mapping surf1 to surf2 */ 01397 01398 fprintf(SUMA_STDERR,"\nComputing intersections...\n\n"); 01399 ptHit[0]=0; ptHit[1]=0; ptHit[2]=0; 01400 triNode0=0; triNode1=0; triNode2=0; 01401 01402 for (i=0; i<numNodes_1; ++i) { 01403 01404 j=3*i; 01405 currNode[0]=ctrNodeList_1[j]; 01406 currNode[1]=ctrNodeList_1[j+1]; 01407 currNode[2]=ctrNodeList_1[j+2]; 01408 currDist = sqrt( pow( currNode[0]-zero[0], 2) + pow( currNode[1]-zero[1], 2) + pow( currNode[2]-zero[2], 2) ); 01409 01410 /*compute inflation of node onto sphere by adjusting surf1 node so that its distance from zero[0],[1],[2] 01411 exactly equals the radius of the spherical surf2 (r2)*/ 01412 ptHit[0] = (r2/currDist)*currNode[0]; 01413 ptHit[1] = (r2/currDist)*currNode[1]; 01414 ptHit[2] = (r2/currDist)*currNode[2]; 01415 01416 01417 /**find 3 nodes in ctrNodeList_2 closest to ptHit*/ 01418 01419 /*initialize variables*/ 01420 found = NOPE; 01421 for (k=0; k<3; ++k) { 01422 min_dist[k] = 2*r2; 01423 i_node[k] = -1; 01424 } 01425 curr_restr = (float)12.0*avgDist; /*12.0 chosen by trial/error for best timing compromise between 01426 using expanded search vs brute force for trouble nodes*/ 01427 01428 /*find placement of ptHit[0] in justX_2*/ 01429 seg[0] = 0; 01430 seg[1] = numNodes_2-1; 01431 01432 if ( ptHit[0] < justX_2[seg[0]] ) /*note ptHit will be within r2/10 of either of these values, so assignment is ok*/ 01433 seg[1] = seg[0]; /*(since ctrNodeList2 was adjusted to have each distance within )*/ 01434 else if ( ptHit[0] > justX_2[seg[1]] ) /*(r2/10 of r2, which was used to scale ctrNodeList1, from which)*/ 01435 seg[0] = seg[1]; /*(justX_2 comes )*/ 01436 else { 01437 if ( !SUMA_binSearch( justX_2, ptHit[0], seg )) { 01438 fprintf(SUMA_STDERR, "Error %s: Failed in binary search !(%f < %f < %f).\n\n", FuncName, justX_2[seg[0]], ptHit[0], justX_2[seg[1]]); 01439 if (ctrNodeList_1) SUMA_free(ctrNodeList_1); 01440 if (ctrNodeList_2) SUMA_free(ctrNodeList_2); 01441 if (clsNodes) SUMA_free(clsNodes); 01442 if (weight) SUMA_free(weight); 01443 if (i_SrtdX_2) SUMA_free(i_SrtdX_2); 01444 if (justX_2) SUMA_free(justX_2); 01445 if (srtdX_ctrNodeList_2) SUMA_free(srtdX_ctrNodeList_2); 01446 SUMA_RETURN (NULL); 01447 } 01448 } 01449 01450 /*expand search segment*/ 01451 while ( (ptHit[0] - srtdX_ctrNodeList_2[3*seg[0]]) < curr_restr && seg[0]>0) { 01452 if ( seg[0]>10 ) seg[0] = seg[0]-10; 01453 else --seg[0]; 01454 } 01455 while ( (srtdX_ctrNodeList_2[3*seg[1]] - ptHit[0]) < curr_restr && seg[1]<(numNodes_2-1) ) { 01456 if ( seg[1]<(numNodes_2-11) ) seg[1] = seg[1]+10; 01457 else ++seg[1]; 01458 } 01459 01460 /*search for 3 minimum distances to ptHit*/ 01461 while ( !found && seg[1]-seg[0]<numNodes_2 && curr_restr<3*r2 ) { 01462 /*3 min distances have not yet been found*/ 01463 01464 SUMA_Search_Min_Dist( ptHit, srtdX_ctrNodeList_2, seg, curr_restr, min_dist, i_node ); 01465 01466 if ( i_node[0]==-1 || i_node[1]==-1 || i_node[2]==-1 ) { 01467 /*sufficient (3) min_dist were not found -> repeat and expand search of segment with more relaxed measures*/ 01468 curr_restr = (float) 1.5*curr_restr; 01469 found = NOPE; 01470 while ( ptHit[0] - srtdX_ctrNodeList_2[3*seg[0]] < curr_restr && seg[0]>0) { 01471 if (seg[0]>10) seg[0] = seg[0]-10; 01472 else --seg[0]; 01473 } 01474 while ( srtdX_ctrNodeList_2[3*seg[1]] - ptHit[0] < curr_restr && seg[1]<numNodes_2-1) { 01475 if (k<numNodes_2-11) seg[1] = seg[1]+10; 01476 else ++seg[1]; 01477 } 01478 } 01479 else found = YUP; 01480 } 01481 01482 01483 if ( i_node[0]==-1 || i_node[1]==-1 || i_node[2]==-1 ) { 01484 /*unable to acquire 3 closest nodes (???) -> exit*/ 01485 fprintf(SUMA_STDERR, "Error %s: Unable to acquire 3 closest nodes ?!?\n\n", FuncName); 01486 if (ctrNodeList_1) SUMA_free(ctrNodeList_1); 01487 if (ctrNodeList_2) SUMA_free(ctrNodeList_2); 01488 if (clsNodes) SUMA_free(clsNodes); 01489 if (weight) SUMA_free(weight); 01490 if (i_SrtdX_2) SUMA_free(i_SrtdX_2); 01491 if (justX_2) SUMA_free(justX_2); 01492 if (srtdX_ctrNodeList_2) SUMA_free(srtdX_ctrNodeList_2); 01493 SUMA_RETURN (NULL); 01494 } 01495 01496 /*translate back into unsorted ordering of ctrNodeList_2*/ 01497 i_node[0] = i_SrtdX_2[i_node[0]]; 01498 i_node[1] = i_SrtdX_2[i_node[1]]; 01499 i_node[2] = i_SrtdX_2[i_node[2]]; 01500 01501 if (LocalHead) { 01502 fprintf(SUMA_STDERR,"----------------------------------------\n"); 01503 fprintf(SUMA_STDERR, "%s: PtHit: [%f, %f, %f].\n", FuncName, ptHit[0], ptHit[1], ptHit[2]); 01504 fprintf(SUMA_STDERR, "%s: Node %d [%f, %f, %f], distances %f.\n", 01505 FuncName, i_node[0], ctrNodeList_2[3*i_node[0]], ctrNodeList_2[3*i_node[0]+1], ctrNodeList_2[3*i_node[0]+2], min_dist[0]); 01506 fprintf(SUMA_STDERR, "%s: Node %d [%f, %f, %f], distances %f.\n", 01507 FuncName, i_node[1], ctrNodeList_2[3*i_node[1]], ctrNodeList_2[3*i_node[1]+1], ctrNodeList_2[3*i_node[1]+2], min_dist[1]); 01508 fprintf(SUMA_STDERR, "%s: Node %d [%f, %f, %f], distances %f.\n", 01509 FuncName, i_node[2], ctrNodeList_2[3*i_node[2]], ctrNodeList_2[3*i_node[2]+1], ctrNodeList_2[3*i_node[2]+2], min_dist[2]); 01510 fprintf(SUMA_STDERR, "%s: orig ptHit (%f, %f, %f)\n", FuncName, ptHit[0], ptHit[1], ptHit[2]); 01511 fprintf(SUMA_STDERR, "%s: Trying 1- node %d\n", FuncName, i_node[0]); 01512 } 01513 01514 01515 /**find nodes of intersected triangle*/ 01516 01517 if (surf2->FN == NULL) { 01518 fprintf(SUMA_STDERR, "%s: Surf2->FN is NULL.\n", FuncName); 01519 if (ctrNodeList_1) SUMA_free(ctrNodeList_1); 01520 if (ctrNodeList_2) SUMA_free(ctrNodeList_2); 01521 if (clsNodes) SUMA_free(clsNodes); 01522 if (weight) SUMA_free(weight); 01523 if (i_SrtdX_2) SUMA_free(i_SrtdX_2); 01524 if (justX_2) SUMA_free(justX_2); 01525 if (srtdX_ctrNodeList_2) SUMA_free(srtdX_ctrNodeList_2); 01526 SUMA_RETURN (NULL); 01527 } 01528 01529 /* search neighborhoods of closest 3 nodes */ 01530 found = SUMA_inNodeNeighb( surf2, ctrNodeList_2, i_node, zero, ptHit); 01531 01532 if (!found) { 01533 /* try brute force */ 01534 if (LocalHead) fprintf(SUMA_STDERR, "%s: Trying Brute force. (%d)\n", FuncName, i); 01535 { 01536 SUMA_MT_INTERSECT_TRIANGLE *MTI; 01537 01538 MTI = SUMA_MT_intersect_triangle(ptHit, zero, ctrNodeList_2, numNodes_2, faceList_2, numFace_2, NULL); 01539 if (MTI) { 01540 if (MTI->N_hits) { 01541 if (LocalHead) fprintf(SUMA_STDERR, "%s: Brute force-Triangle %d [%d, %d, %d] is intersected at (%f, %f, %f)\n", 01542 FuncName, MTI->ifacemin, surf2->FaceSetList[3*MTI->ifacemin], surf2->FaceSetList[3*MTI->ifacemin+1], 01543 surf2->FaceSetList[3*MTI->ifacemin+2], MTI->P[0], MTI->P[1], MTI->P[2]); 01544 found = YUP; 01545 ptHit[0] = MTI->P[0]; 01546 ptHit[1] = MTI->P[1]; 01547 ptHit[2] = MTI->P[2]; 01548 i_node[0] = surf2->FaceSetList[3*MTI->ifacemin]; 01549 i_node[1] = surf2->FaceSetList[3*MTI->ifacemin+1]; 01550 i_node[2] = surf2->FaceSetList[3*MTI->ifacemin+2]; 01551 } 01552 MTI = SUMA_Free_MT_intersect_triangle(MTI); 01553 } 01554 } 01555 } 01556 01557 if (!found) { 01558 fprintf(SUMA_STDERR, "Error %s: !!!!!!!!!! intersected triangle not found.\n", FuncName); 01559 if (ctrNodeList_1) SUMA_free(ctrNodeList_1); 01560 if (ctrNodeList_2) SUMA_free(ctrNodeList_2); 01561 if (clsNodes) SUMA_free(clsNodes); 01562 if (weight) SUMA_free(weight); 01563 if (i_SrtdX_2) SUMA_free(i_SrtdX_2); 01564 if (justX_2) SUMA_free(justX_2); 01565 if (srtdX_ctrNodeList_2) SUMA_free(srtdX_ctrNodeList_2); 01566 SUMA_RETURN (NULL); 01567 } 01568 01569 if (LocalHead) fprintf (SUMA_STDERR, "%s: (%d : %d : %d)\n ptHit(%f, %f, %f)\n", FuncName, i_node[0], i_node[1], i_node[2], ptHit[0], ptHit[1], ptHit[2]); 01570 01571 /**node indices of triangle intersected by ptHit*/ 01572 clsNodes[j] = i_node[0]; clsNodes[j+1] = i_node[1]; clsNodes[j+2] = i_node[2]; 01573 01574 /** pointers to x,y,z of each node of intersected triangle*/ 01575 triNode0 = &(ctrNodeList_2[ 3*i_node[0] ]); 01576 triNode1 = &(ctrNodeList_2[ 3*i_node[1] ]); 01577 triNode2 = &(ctrNodeList_2[ 3*i_node[2] ]); 01578 01579 /**determine weights which are the barycetric corrdinates of the intersection node*/ 01580 SUMA_TRI_AREA( ptHit, triNode1, triNode2, weight[j]); 01581 SUMA_TRI_AREA( ptHit, triNode0, triNode2, weight[j+1]); 01582 SUMA_TRI_AREA( ptHit, triNode0, triNode1, weight[j+2]); /* if the index of the intersected triangle is very cheap to obtain, 01583 you could set weight[j+2] = SO->PolyArea[Face] - weight[j+1] - weight[j+0] 01584 Of course, you must first compute PolyArea with SUMA_SurfaceMetrics*/ 01585 01586 weight_tot = weight[j] + weight[j+1] + weight[j+2]; 01587 if (weight_tot) { 01588 weight[j] /= weight_tot; 01589 weight[j+1] /= weight_tot; 01590 weight[j+2] /= weight_tot; 01591 }else { /* some triangles have zero area in FreeSurfer surfaces */ 01592 weight[j] = weight[j+1] = weight[j+2] = 1.0/3.0; 01593 } 01594 01595 } 01596 01597 MI->N_Node = numNodes_1; 01598 MI->N_FaceSet = numFace_1; 01599 MI->Weight = weight; 01600 MI->ClsNodes = clsNodes; 01601 MI->FaceSetList = (int *) SUMA_calloc( 3*numFace_1, sizeof(int)); 01602 if (!MI->FaceSetList) { 01603 fprintf(SUMA_STDERR, "Error %s: Failed to allocate for MI->FaceSetList.\n", FuncName); 01604 if (ctrNodeList_1) SUMA_free(ctrNodeList_1); 01605 if (ctrNodeList_2) SUMA_free(ctrNodeList_2); 01606 if (clsNodes) SUMA_free(clsNodes); 01607 if (weight) SUMA_free(weight); 01608 if (i_SrtdX_2) SUMA_free(i_SrtdX_2); 01609 if (justX_2) SUMA_free(justX_2); 01610 if (srtdX_ctrNodeList_2) SUMA_free(srtdX_ctrNodeList_2); 01611 SUMA_RETURN (NULL); 01612 } 01613 for (i=0; i<numFace_1; ++i) { 01614 j = 3*i; 01615 MI->FaceSetList[j] = faceList_1[j]; 01616 MI->FaceSetList[j+1] = faceList_1[j+1]; 01617 MI->FaceSetList[j+2] = faceList_1[j+2]; 01618 } 01619 01620 if (ctrNodeList_1) SUMA_free(ctrNodeList_1); 01621 if (ctrNodeList_2) SUMA_free(ctrNodeList_2); 01622 if (i_SrtdX_2) SUMA_free(i_SrtdX_2); 01623 if (justX_2) SUMA_free(justX_2); 01624 if (srtdX_ctrNodeList_2) SUMA_free(srtdX_ctrNodeList_2); 01625 01626 SUMA_RETURN (MI); 01627 } |
|
newNodeList = SUMA_morphToStd( nodeList, MI); Function to morph surface to standard grid.
Definition at line 1835 of file SUMA_SphericalMapping.c. References SUMA_MorphInfo::ClsNodes, SUMA_SurfaceObject::FaceSetDim, SUMA_MorphInfo::FaceSetList, SUMA_SurfaceObject::FaceSetList, SUMA_SurfaceObject::FN, i, SUMA_SurfaceObject::idcode_str, SUMA_MorphInfo::N_FaceSet, SUMA_SurfaceObject::N_FaceSet, SUMA_NODE_FIRST_NEIGHB::N_Neighb, SUMA_MorphInfo::N_Node, SUMA_SurfaceObject::N_Node, SUMA_SurfaceObject::NodeDim, SUMA_SurfaceObject::NodeList, SUMA_SurfaceObject::State, SUMA_Alloc_SurfObject_Struct(), SUMA_Boolean, SUMA_calloc, SUMA_ENTRY, SUMA_free, SUMA_IDCODE_LENGTH, SUMA_RETURN, UNIQ_idcode_fill(), and SUMA_MorphInfo::Weight.
01835 { 01836 01837 float *newNodeList = NULL; 01838 int *tmp_newFaceSetList = NULL, *newFaceSetList = NULL, *inclNodes=NULL; 01839 int i, j, N_FaceSet; 01840 SUMA_SurfaceObject *SO_new=NULL; 01841 static char FuncName[] = {"SUMA_morphToStd"}; 01842 01843 SUMA_ENTRY; 01844 01845 SO_new = SUMA_Alloc_SurfObject_Struct(1); 01846 if (SO_new == NULL) { 01847 fprintf (SUMA_STDERR,"Error %s: Failed to allocate for Surface Object.", FuncName); 01848 SUMA_RETURN (NULL); 01849 } 01850 01851 newNodeList = (float *) SUMA_calloc( 3*MI->N_Node, sizeof(float)); 01852 if (!newNodeList) { 01853 fprintf (SUMA_STDERR, "Error %s: Failed to allocate. \n", FuncName); 01854 SUMA_RETURN (NULL); 01855 } 01856 N_FaceSet = 0; 01857 01858 if ( !nodeChk ) { 01859 /*assume all nodes contained in MI->ClsNodes to be also in SO->FaceSetList*/ 01860 fprintf(SUMA_STDERR, "Warning %s: Assuming face sets of surface %s to contain all nodes indicated in morphing to standard mesh.\n\n", 01861 FuncName, SO->State); 01862 01863 for (i=0; i<(MI->N_Node); ++i){ 01864 j = 3*i; 01865 01866 newNodeList[j] = (MI->Weight[j])*SO->NodeList[3*(MI->ClsNodes[j])] + //node0 x 01867 (MI->Weight[j+1])*SO->NodeList[3*(MI->ClsNodes[j+1])] + //node1 x 01868 (MI->Weight[j+2])*SO->NodeList[3*(MI->ClsNodes[j+2])]; //node2 x 01869 newNodeList[j+1] = (MI->Weight[j])*SO->NodeList[3*(MI->ClsNodes[j])+1] + //node0 y 01870 (MI->Weight[j+1])*SO->NodeList[3*(MI->ClsNodes[j+1])+1] + //node1 y 01871 (MI->Weight[j+2])*SO->NodeList[3*(MI->ClsNodes[j+2])+1]; //node2 y 01872 newNodeList[j+2] = (MI->Weight[j])*SO->NodeList[3*(MI->ClsNodes[j])+2] + //node0 z 01873 (MI->Weight[j+1])*SO->NodeList[3*(MI->ClsNodes[j+1])+2] + //node1 z 01874 (MI->Weight[j+2])*SO->NodeList[3*(MI->ClsNodes[j+2])+2]; //node2 z 01875 } 01876 01877 newFaceSetList = MI->FaceSetList; 01878 N_FaceSet = MI->N_FaceSet; 01879 } 01880 01881 else { 01882 /*check MI->ClsNodes for possibly containing nodes which are not included in SO->FaceSetList*/ 01883 01884 if ( !SO->FN ) { 01885 fprintf(SUMA_STDERR, "Error %s: No First Neighbor information passed.\n", FuncName); 01886 return (NULL); 01887 } 01888 01889 /*keep track of included MI nodes; 1=>included, 0=>not*/ 01890 inclNodes = SUMA_calloc( MI->N_Node, sizeof(int)); 01891 for (i=0; i<MI->N_Node; ++i) { 01892 inclNodes[i] = 0; 01893 } 01894 01895 for (i=0; i<(MI->N_Node); ++i) { 01896 01897 j = 3*i; 01898 if ( (MI->ClsNodes[j])<=(SO->N_Node) && (MI->ClsNodes[j+1])<=(SO->N_Node) && (MI->ClsNodes[j+2])<=(SO->N_Node) ) { 01899 /*index of 3 nodes in MI->ClsNodes do not exceed number of nodes in SO*/ 01900 if ( SO->FN->N_Neighb[MI->ClsNodes[j]]>0 && SO->FN->N_Neighb[MI->ClsNodes[j+1]]>0 && SO->FN->N_Neighb[MI->ClsNodes[j+2]]>0 ) { 01901 /*3 nodes in MI->ClsNodes are all a part of the SO mesh (have at least 1 neighbor in the SO mesh)*/ 01902 01903 inclNodes[i] = 1; 01904 newNodeList[j] = (MI->Weight[j])*SO->NodeList[3*(MI->ClsNodes[j])] + //node0 x 01905 (MI->Weight[j+1])*SO->NodeList[3*(MI->ClsNodes[j+1])] + //node1 x 01906 (MI->Weight[j+2])*SO->NodeList[3*(MI->ClsNodes[j+2])]; //node2 x 01907 newNodeList[j+1] = (MI->Weight[j])*SO->NodeList[3*(MI->ClsNodes[j])+1] + //node0 y 01908 (MI->Weight[j+1])*SO->NodeList[3*(MI->ClsNodes[j+1])+1] + //node1 y 01909 (MI->Weight[j+2])*SO->NodeList[3*(MI->ClsNodes[j+2])+1]; //node2 y 01910 newNodeList[j+2] = (MI->Weight[j])*SO->NodeList[3*(MI->ClsNodes[j])+2] + //node0 z 01911 (MI->Weight[j+1])*SO->NodeList[3*(MI->ClsNodes[j+1])+2] + //node1 z 01912 (MI->Weight[j+2])*SO->NodeList[3*(MI->ClsNodes[j+2])+2]; //node2 z 01913 } 01914 } 01915 /*otherwise, morphing for this node skipped*/ 01916 } 01917 01918 /*create list of MI facesets for which all 3 nodes were morphed*/ 01919 tmp_newFaceSetList = SUMA_calloc( 3*MI->N_FaceSet, sizeof(int)); 01920 if (!tmp_newFaceSetList) { 01921 fprintf (SUMA_STDERR, "Error %s: Failed to allocate. \n", FuncName); 01922 SUMA_RETURN (NULL); 01923 } 01924 01925 for (i=0; i<MI->N_FaceSet; ++i) { 01926 j = 3*i; 01927 if ( inclNodes[MI->FaceSetList[j]]==1 && inclNodes[MI->FaceSetList[j+1]]==1 && 01928 inclNodes[MI->FaceSetList[j+2]]==1) { 01929 /*all nodes morphed for this faceset*/ 01930 tmp_newFaceSetList[3*N_FaceSet] = MI->FaceSetList[j]; 01931 tmp_newFaceSetList[3*N_FaceSet+1] = MI->FaceSetList[j+1]; 01932 tmp_newFaceSetList[3*N_FaceSet+2] = MI->FaceSetList[j+2]; 01933 N_FaceSet++; 01934 } 01935 } 01936 01937 /*create final new face list of correct length*/ 01938 if ( N_FaceSet == MI->N_FaceSet ) { 01939 /*all facesets in MI->FaceSetList included*/ 01940 newFaceSetList = tmp_newFaceSetList; 01941 } 01942 else { 01943 /*some facesets in MI->FaceSetList not included*/ 01944 newFaceSetList = SUMA_calloc( 3*N_FaceSet, sizeof(int)); 01945 if (!newFaceSetList) { 01946 fprintf (SUMA_STDERR, "Error %s: Failed to allocate. \n", FuncName); 01947 SUMA_RETURN (NULL); 01948 } 01949 for (i=0; i<3*N_FaceSet; ++i) { 01950 newFaceSetList[i] = tmp_newFaceSetList[i]; 01951 } 01952 SUMA_free (tmp_newFaceSetList); 01953 } 01954 SUMA_free (inclNodes); 01955 } 01956 01957 /* store in SO_new and get out */ 01958 SO_new->NodeList = newNodeList; 01959 SO_new->FaceSetList = newFaceSetList; 01960 SO_new->N_Node = MI->N_Node; 01961 SO_new->N_FaceSet = N_FaceSet; 01962 SO_new->NodeDim = 3; 01963 SO_new->FaceSetDim = 3; 01964 SO_new->idcode_str = (char *)SUMA_calloc (SUMA_IDCODE_LENGTH, sizeof(char)); 01965 UNIQ_idcode_fill (SO_new->idcode_str); 01966 01967 SUMA_RETURN( SO_new ); 01968 } |
|
void = SUMA_readANOVA1D( fileNm, i_colm, i_locInfo, data ); Function to read a 1D file into an array.
Definition at line 3650 of file SUMA_SphericalMapping.c. References file, i, SUMA_1dData::ijk_list, SUMA_1dData::N_elem, SUMA_1dData::nd_list, SUMA_1dData::nvox_list, SUMA_Boolean, SUMA_calloc, SUMA_ENTRY, SUMA_free, SUMA_RETURNe, SUMA_z_dqsort(), SUMA_1dData::valArray, and SUMA_1dData::vxl_list.
03650 { 03651 03652 FILE *file=NULL; 03653 char *line=NULL, *frag=NULL; 03654 char scan[100]; 03655 int i=0, j=0, k=0, num_node=0, lgth=0, i_curr=0, i_last=0; 03656 int num_loc=0, num_val=0, num_tot=0, valCnt=0, tempInt=0; 03657 int *i_colm_ndx=NULL, *i_colmSrtd=NULL, *i_cat=NULL; 03658 float *valArray=NULL, tempFlt=0; 03659 int *ndx_list=NULL, *vxl_list=NULL, *ijk_list=NULL, *nvox_list=NULL; 03660 SUMA_Boolean nd_given=NOPE; 03661 static char FuncName[]={"SUMA_read1D"}; 03662 03663 SUMA_ENTRY; 03664 03665 /**set default length to 500,000*/ 03666 lgth = 500000; 03667 03668 /*find number of location indices*/ 03669 if (i_colm[0] == 0) { 03670 fprintf(SUMA_STDERR, "\nError %s: No column indices given! Exiting.\n", FuncName); 03671 exit(1); 03672 } 03673 else num_tot = i_colm[0]; 03674 num_loc=0; 03675 /**determine number of location columns and value columns to be read*/ 03676 for (i=0; i<6; ++i) { 03677 for (j=0; j<num_tot-1; ++j) { 03678 if ( i_locInfo[i]==i_colm[j+1] ) { 03679 /*indicates location column*/ 03680 ++num_loc; 03681 } 03682 } 03683 } 03684 03685 num_val = num_tot-num_loc; 03686 03687 /*sort column indicies*/ 03688 i_colmSrtd = SUMA_calloc( i_colm[0]-1, sizeof(int)); 03689 for (i=0; i<i_colm[0]; ++i) { 03690 /*copy i_colm removing first element (contains number of columns)*/ 03691 i_colmSrtd[i] = i_colm[i+1]; 03692 } 03693 i_colm_ndx = SUMA_z_dqsort( i_colmSrtd, num_tot ); 03694 03695 /*keep track of which columns are node, voxel, ijk, nvox and value*/ 03696 i_cat = SUMA_calloc( num_tot, sizeof(int)); 03697 for ( i=0; i<num_tot; ++i) { 03698 if ( i_colmSrtd[i]==i_locInfo[0] ) { // 0=>node index column 03699 i_cat[i] = 0; 03700 nd_given = YUP; 03701 } 03702 else if ( i_colmSrtd[i]==i_locInfo[1] ) i_cat[i] = 1; // 1=>voxel index column 03703 else if ( i_colmSrtd[i]==i_locInfo[2] ) i_cat[i] = 2; // 2=>i location column 03704 else if ( i_colmSrtd[i]==i_locInfo[3] ) i_cat[i] = 3; // 3=>j location column 03705 else if ( i_colmSrtd[i]==i_locInfo[4] ) i_cat[i] = 4; // 4=>k location column 03706 else if ( i_colmSrtd[i]==i_locInfo[5] ) i_cat[i] = 5; // 5=>nvox column 03707 else i_cat[i] = -1; //-1=> value column 03708 } 03709 03710 valArray = SUMA_calloc( num_val*lgth, sizeof(float) ); 03711 ndx_list = SUMA_calloc( lgth, sizeof(int) ); 03712 vxl_list = SUMA_calloc( lgth, sizeof(int) ); 03713 ijk_list = SUMA_calloc( 3*lgth, sizeof(int) ); 03714 nvox_list = SUMA_calloc( lgth, sizeof(int) ); 03715 03716 line = SUMA_calloc( 10000, sizeof(char)); 03717 03718 if ( !valArray || !ndx_list || !vxl_list || !ijk_list || !nvox_list || !line) { 03719 fprintf(SUMA_STDERR, "Error %s: Failed in allocation.\n", FuncName); 03720 if (valArray) SUMA_free(valArray); 03721 if (ndx_list) SUMA_free(ndx_list); 03722 if (vxl_list) SUMA_free(vxl_list); 03723 if (ijk_list) SUMA_free(ijk_list); 03724 if (nvox_list) SUMA_free(nvox_list); 03725 if (line) SUMA_free(line); 03726 exit(1); 03727 } 03728 03729 if( (file = fopen(fileNm, "r"))==NULL) { 03730 fprintf (SUMA_STDERR, "Failed in opening %s for reading.\n", fileNm); 03731 if (valArray) SUMA_free(valArray); 03732 if (ndx_list) SUMA_free(ndx_list); 03733 if (vxl_list) SUMA_free(vxl_list); 03734 if (ijk_list) SUMA_free(ijk_list); 03735 if (nvox_list) SUMA_free(nvox_list); 03736 if (line) SUMA_free(line); 03737 exit(1); 03738 } 03739 03740 else { 03741 03742 /**skip through comments*/ 03743 fgets( line, 1000, file); 03744 while( line[0]=='#' ) { 03745 fgets( line, 10000, file); 03746 } 03747 03748 /**read remaining values*/ 03749 num_node = 0; 03750 while( !feof(file) && line[0]!='#' && num_node<lgth) { 03751 valCnt = 0; 03752 i_last = 0; 03753 frag = strtok(line, " \t\n\r"); 03754 if (frag==NULL) { 03755 fprintf(SUMA_STDERR, "\nError %s: Indicated column for file not found. Exiting.\n", FuncName); 03756 exit(1); 03757 } 03758 03759 for ( k=0; k<num_tot; ++k ) { 03760 for ( i=0; i<i_colmSrtd[k]-i_last; ++i) { 03761 frag = strtok(NULL, " \t\n\r"); 03762 if (frag==NULL) { 03763 fprintf(SUMA_STDERR, "\nError %s: Indicated column for file not found. Exiting.\n", FuncName); 03764 exit(1); 03765 } 03766 } 03767 03768 if (frag==NULL) { 03769 fprintf(SUMA_STDERR, "\nError %s: Indicated column for file not found. Exiting.\n", FuncName); 03770 exit(1); 03771 } 03772 03773 if ( i_cat[k]!=-1 ) { 03774 /*look for int (location column)*/ 03775 sscanf(frag, "%d", &tempInt); 03776 } 03777 else { 03778 /*look for float (value column*/ 03779 sscanf(frag, "%f", &tempFlt); 03780 } 03781 03782 if ( i_cat[k]==0 ) ndx_list[num_node] = tempInt; // node 03783 else if ( i_cat[k]==1 ) vxl_list[num_node] = tempInt; // voxel 03784 else if ( i_cat[k]==2 ) ijk_list[3*num_node] = tempInt; // i 03785 else if ( i_cat[k]==3 ) ijk_list[3*num_node+1] = tempInt; // j 03786 else if ( i_cat[k]==4 ) ijk_list[3*num_node+2] = tempInt; // k 03787 else if ( i_cat[k]==5 ) nvox_list[num_node] = tempInt; // nvox 03788 else valArray[ (valCnt++)*lgth + num_node ] = tempFlt; // value 03789 i_last = i_colmSrtd[k]; 03790 } 03791 fgets( line, 10000, file); 03792 ++num_node; 03793 } 03794 fclose(file); 03795 } 03796 03797 03798 /**create array of exact length to pass back*/ 03799 data->N_elem = num_node; 03800 data->nd_list = SUMA_calloc( num_node, sizeof(int)); 03801 data->vxl_list = SUMA_calloc( num_node, sizeof(int)); 03802 data->ijk_list = SUMA_calloc( 3*num_node, sizeof(int)); 03803 data->nvox_list = SUMA_calloc( num_node, sizeof(int)); 03804 data->valArray = SUMA_calloc( num_val*num_node, sizeof(float)); 03805 03806 for (i=0; i<num_node; ++i) { 03807 if (nd_given) data->nd_list[i] = ndx_list[i]; 03808 else data->nd_list[i] = i; 03809 data->vxl_list[i] = vxl_list[i]; 03810 data->ijk_list[i] = ijk_list[i]; 03811 data->nvox_list[i] = nvox_list[i]; 03812 for (k=0; k<num_val; ++k) { 03813 data->valArray[ k*num_node +i ] = valArray[ k*lgth +i ]; 03814 } 03815 } 03816 03817 SUMA_free(line); 03818 SUMA_free(i_colm_ndx); 03819 SUMA_free(i_colmSrtd); 03820 SUMA_free(i_cat); 03821 03822 SUMA_free(valArray); 03823 SUMA_free(ndx_list); 03824 SUMA_free(vxl_list); 03825 SUMA_free(ijk_list); 03826 SUMA_free(nvox_list); 03827 03828 SUMA_RETURNe; 03829 } |
|
array = SUMA_readColor( numNodes, colFileNm); Function to read a colorfile into an array.
Definition at line 1980 of file SUMA_SphericalMapping.c. References i, SUMA_calloc, SUMA_ENTRY, SUMA_free, and SUMA_RETURN.
01980 { 01981 01982 float *colArray=NULL; 01983 FILE *colFile=NULL; 01984 char *line=NULL, *temp=NULL; 01985 int i=0, j=0, k=0, index=0; 01986 static char FuncName[]={"SUMA_readColor"}; 01987 01988 SUMA_ENTRY; 01989 01990 colArray = (float *) SUMA_calloc( 3*numNodes, sizeof(float) ); 01991 line = (char *) SUMA_calloc( 10000, sizeof(char)); 01992 temp = (char *) SUMA_calloc( 10000, sizeof(char)); 01993 01994 if( (colFile = fopen(colFileNm, "r"))==NULL) { 01995 fprintf (SUMA_STDERR, "Failed in opening %s for reading.\n", colFileNm); 01996 if (colArray) SUMA_free (colArray); 01997 if (line) SUMA_free (line); 01998 if (temp) SUMA_free (temp); 01999 exit(1); 02000 } 02001 else { 02002 fgets( line, 1000, colFile); 02003 while( !feof(colFile) ) { 02004 02005 j = 3*index; 02006 i = 0; 02007 while ( isdigit(line[i]) ) ++i; 02008 02009 ++i; k=0; 02010 while ( !isspace(line[i])) { 02011 temp[k] = line[i]; 02012 ++i; ++k; 02013 } 02014 colArray[j] = atof(temp); 02015 SUMA_free(temp); 02016 temp = SUMA_calloc(10000, sizeof(char)); 02017 02018 ++i; k=0; 02019 while ( !isspace(line[i])) { 02020 temp[k] = line[i]; 02021 ++i; ++k; 02022 } 02023 colArray[j+1] = atof(temp); 02024 SUMA_free(temp); 02025 temp = SUMA_calloc( 10000, sizeof(char)); 02026 02027 ++i; k=0; 02028 while ( !isspace(line[i])) { 02029 temp[k] = line[i]; 02030 ++i; ++k; 02031 } 02032 colArray[j+2] = atof(temp); 02033 SUMA_free(temp); 02034 temp = SUMA_calloc( 10000, sizeof(char)); 02035 02036 fgets( line, 10000, colFile ); 02037 ++index; 02038 } 02039 } 02040 SUMA_free(line); 02041 SUMA_free(temp); 02042 02043 SUMA_RETURN( colArray); 02044 } |
|
SUMA_Search_Min_dist( seg, pt, nodeList, restr, dist, i_dist) Function to search for three minimum distances between a given point and nodes within a given segment.
Definition at line 1643 of file SUMA_SphericalMapping.c. References SUMA_RETURNe. Referenced by SUMA_MapSurface().
01643 { 01644 01645 static char FuncName[]={"SUMA_Search_Min_Dist"}; 01646 float tempD; 01647 int j, k; 01648 01649 if ( !dist[0] || !dist[1] || !dist[2] ) { 01650 tempD = 3*pow(restr,2); 01651 dist[0] = tempD; dist[1] = tempD; dist[2] = tempD; 01652 i_dist[0] = -1; i_dist[1] = -1; i_dist[2] = -1; 01653 } 01654 else tempD = dist[2]+1; 01655 01656 for (k=seg[0]; k<=seg[1]; ++k) { 01657 j = 3*k; 01658 if (pt[0]-nodeList[j] < restr) { 01659 if (pt[0]-nodeList[j] > -restr) { 01660 if (pt[1]-nodeList[j+1] < restr) { 01661 if (pt[1]-nodeList[j+1] > -restr) { 01662 if (pt[2]-nodeList[j+2] < restr) { 01663 if (pt[2]-nodeList[j+2] > -restr) { 01664 01665 tempD = sqrt( pow(pt[0]-nodeList[j],2) + pow(pt[1]-nodeList[j+1],2) + 01666 pow(pt[2]-nodeList[j+2],2) ); 01667 01668 if (tempD < dist[2]) { 01669 if (tempD < dist[1]) { 01670 if (tempD < dist[0]) { 01671 dist[2] = dist[1]; i_dist[2] = i_dist[1]; 01672 dist[1] = dist[0]; i_dist[1] = i_dist[0]; 01673 dist[0] = tempD; i_dist[0] = k; 01674 } 01675 else { 01676 dist[2] = dist[1]; i_dist[2] = i_dist[1]; 01677 dist[1] = tempD; i_dist[1] = k; 01678 } 01679 } 01680 else { 01681 dist[2] = tempD; i_dist[2] = k; 01682 } 01683 } 01684 } 01685 } 01686 } 01687 } 01688 } 01689 } 01690 } 01691 01692 SUMA_RETURNe; 01693 } |
|
function to Show SO_map Definition at line 1748 of file SUMA_SphericalMapping.c. References i, SUMA_SO_map::N_Node, SUMA_SO_map::NewNodeList, SUMA_Boolean, SUMA_ENTRY, and SUMA_RETURN.
01749 { 01750 static char FuncName[]={"SUMA_Show_SO_map"}; 01751 int i=0, imax; 01752 01753 SUMA_ENTRY; 01754 01755 if (!out) out = SUMA_STDERR; 01756 01757 fprintf (out, "\n%s: Showing contents of SUMA_SO_map structure:\n", FuncName); 01758 if (!SOM) { 01759 fprintf (out, "\tpointer is NULL.\n"); 01760 SUMA_RETURN (YUP); 01761 } 01762 01763 if (SOM->N_Node > 5) imax = 5; 01764 else imax = SOM->N_Node; 01765 01766 fprintf (SUMA_STDERR, "NodeList, (1st %d elements):\n", imax); 01767 for (i=0; i<imax; ++i) { 01768 fprintf (SUMA_STDERR, "\t%f, %f, %f\n", SOM->NewNodeList[3*i], SOM->NewNodeList[3*i+1], SOM->NewNodeList[3*i+2]); 01769 } 01770 01771 SUMA_RETURN (YUP); 01772 } |
|
A function to test if a spherical surface is indeed spherical. SUMA_SphereQuality (SUMA_SurfaceObject *SO, char *Froot, char *historynote) This function reports on a few parameters indicative of the quality of a spherical surface: it calculates the absolute deviation between the distance of each node from SO->Center (d) and the estimated radius(r) abs (d - r) The distances are written to the file: <Froot>_Ddist.1D . The first column represents node index. A colorized version is written to <Froot>_Ddist.1D.col (node index followed by r g b values) The function also computes the cosine of the angle between the normal at a node and the direction vector formed by the center and that node. Since both vectors are normalized, the cosine of the angle is the dot product. On a sphere, the abs(dot product) should be 1 or pretty close. abs(dot product) < 0.9 are flagged as bad and written out to the file <Froot>_BadNodes.1D . The file <Froot>_dotprod.1D contains the dot product values for all the nodes. The file with colorized results are <Froot>_BadNodes.1D.col and <Froot>_dotprod.1D.col Definition at line 66 of file SUMA_SphericalMapping.c. References SUMA_SurfaceObject::Center, SUMA_COLOR_SCALED_VECT::cV, i, SUMA_SurfaceObject::Label, LocalHead, SUMA_SurfaceObject::N_Node, SUMA_SurfaceObject::NodeList, SUMA_SurfaceObject::NodeNormList, nr, r, SUMA_append_string(), SUMA_Boolean, SUMA_calloc, SUMA_CMAP_MATLAB_DEF_BYR64, SUMA_Create_ColorScaledVect(), SUMA_ENTRY, SUMA_free, SUMA_Free_ColorMap(), SUMA_Free_ColorScaledVect(), SUMA_GetStandardMap(), SUMA_MIN_MAX_VEC, SUMA_realloc, SUMA_RETURN, SUMA_ScaleToMap(), SUMA_ScaleToMapOptInit(), SUMA_SL_Err, and SUMA_z_qsort().
00067 { 00068 static char FuncName[]={"SUMA_SphereQuality"}; 00069 float *dist = NULL, mdist, *dot=NULL, nr, r[3], *bad_dot = NULL; 00070 float dmin, dmax, dminloc, dmaxloc; 00071 int i, i3, *isortdist = NULL; 00072 int *bad_ind = NULL, ibad =-1; 00073 FILE *fid; 00074 char *fname; 00075 SUMA_COLOR_MAP *CM; 00076 SUMA_SCALE_TO_MAP_OPT * OptScl; 00077 SUMA_COLOR_SCALED_VECT * SV; 00078 SUMA_Boolean LocalHead = NOPE; 00079 00080 SUMA_ENTRY; 00081 00082 if (!SO) { 00083 SUMA_SL_Err("NULL SO"); 00084 SUMA_RETURN(NOPE); 00085 } 00086 00087 /* get the options for creating the scaled color mapping */ 00088 OptScl = SUMA_ScaleToMapOptInit(); 00089 if (!OptScl) { 00090 fprintf (SUMA_STDERR,"Error %s: Could not get scaling option structure.\n", FuncName); 00091 exit (1); 00092 } 00093 00094 /* get the color map */ 00095 CM = SUMA_GetStandardMap (SUMA_CMAP_MATLAB_DEF_BYR64); 00096 if (CM == NULL) { 00097 fprintf (SUMA_STDERR,"Error %s: Could not get standard colormap.\n", FuncName); 00098 if (OptScl) SUMA_free(OptScl); 00099 exit (1); 00100 } 00101 00102 /* compare the distance of each node to the distance to estimated radius */ 00103 dist = (float *)SUMA_calloc(SO->N_Node, sizeof(float)); 00104 mdist = 0.0; 00105 for (i=0; i<SO->N_Node; ++i) { 00106 i3 = 3*i; 00107 dist[i] = sqrt ( pow((double)(SO->NodeList[i3] - SO->Center[0]), 2.0) + 00108 pow((double)(SO->NodeList[i3+1] - SO->Center[1]), 2.0) + 00109 pow((double)(SO->NodeList[i3+2] - SO->Center[2]), 2.0) ); 00110 mdist += dist[i]; 00111 } 00112 mdist /= (float)SO->N_Node; 00113 00114 /* calculate the difference from mdist */ 00115 for (i=0; i<SO->N_Node; ++i) dist[i] = fabs(dist[i] - mdist); 00116 00117 00118 /* Colorize results */ 00119 SV = SUMA_Create_ColorScaledVect(SO->N_Node); 00120 if (!SV) { 00121 fprintf (SUMA_STDERR,"Error %s: Could not allocate for SV.\n", FuncName); 00122 if (dist) SUMA_free(dist); 00123 if (CM) SUMA_Free_ColorMap (CM); 00124 if (OptScl) SUMA_free(OptScl); 00125 exit(1); 00126 } 00127 SUMA_MIN_MAX_VEC(dist, SO->N_Node, dmin, dmax, dminloc, dmaxloc); 00128 if (!SUMA_ScaleToMap (dist, SO->N_Node, dmin, dmax, CM, OptScl, SV)) { 00129 fprintf (SUMA_STDERR,"Error %s: Failed in SUMA_ScaleToMap.\n", FuncName); 00130 if (dist) SUMA_free(dist); 00131 if (CM) SUMA_Free_ColorMap (CM); 00132 if (OptScl) SUMA_free(OptScl); 00133 exit(1); 00134 } 00135 00136 /* write the data */ 00137 fname = SUMA_append_string(Froot, "_Dist.1D.dset"); 00138 if (LocalHead) fprintf (SUMA_STDERR,"%s:\nWriting %s...\n", FuncName, fname); 00139 fid = fopen(fname, "w"); 00140 fprintf(fid,"#Node distance from center of mass.\n" 00141 "#col 0: Node Index\n" 00142 "#col 1: distance\n"); 00143 if (shist) fprintf(fid,"#History:%s\n", shist); 00144 for (i=0; i<SO->N_Node; ++i) fprintf(fid,"%d\t%f\n", i, dist[i]); 00145 fclose(fid); 00146 SUMA_free(fname); fname = NULL; 00147 00148 /* write the colorized data */ 00149 fname = SUMA_append_string(Froot, "_Dist.1D.col"); 00150 if (LocalHead) fprintf (SUMA_STDERR,"%s:\nWriting %s...\n", FuncName, fname); 00151 fid = fopen(fname, "w"); 00152 fprintf(fid,"#Color file of node distance from center of mass.\n" 00153 "#col 0: Node Index\n" 00154 "#col 1: R\n" 00155 "#col 2: G\n" 00156 "#col 3: B\n"); 00157 if (shist) fprintf(fid,"#History:%s\n", shist); 00158 for (i=0; i<SO->N_Node; ++i) fprintf(fid,"%d\t%f\t%f\t%f\n", i, SV->cV[3*i ], SV->cV[3*i+1], SV->cV[3*i+2]); 00159 fclose(fid); 00160 SUMA_free(fname); fname = NULL; 00161 if (SV) SUMA_Free_ColorScaledVect (SV); 00162 00163 /* Now sort that */ 00164 isortdist = SUMA_z_qsort ( dist , SO->N_Node ); 00165 00166 /* report */ 00167 fprintf (SUMA_STDERR,"\n"); 00168 fprintf (SUMA_STDERR,"%s: \n" 00169 "Reporting on Spheriosity of %s\n", FuncName, SO->Label); 00170 fprintf (SUMA_STDERR," Mean distance from center (estimated radius): %f\n", mdist); 00171 fprintf (SUMA_STDERR," Largest 10 absolute departures from estimated radius:\n" 00172 " See output files for more detail.\n"); 00173 for (i=SO->N_Node-1; i > SO->N_Node - 10; --i) { 00174 fprintf (SUMA_STDERR,"dist @ %d: %f\n", isortdist[i], dist[i]); 00175 } 00176 00177 00178 /* New idea: 00179 If we had a perfect sphere then the normal of each node 00180 will be colinear with the direction of the vector between the 00181 sphere's center and the node. 00182 The mode the deviation, the worse the sphere */ 00183 dot = (float *)SUMA_calloc(SO->N_Node, sizeof(float)); 00184 bad_ind = (int *) SUMA_calloc(SO->N_Node, sizeof(int) ); 00185 bad_dot = (float *)SUMA_calloc(SO->N_Node, sizeof(float)); 00186 ibad = 0; 00187 for (i=0; i<SO->N_Node; ++i) { 00188 i3 = 3*i; 00189 r[0] = SO->NodeList[i3] - SO->Center[0]; 00190 r[1] = SO->NodeList[i3+1] - SO->Center[1]; 00191 r[2] = SO->NodeList[i3+2] - SO->Center[2]; 00192 nr = sqrt ( r[0] * r[0] + r[1] * r[1] + r[2] * r[2] ); 00193 r[0] /= nr; r[1] /= nr; r[2] /= nr; 00194 00195 dot[i] = r[0]*SO->NodeNormList[i3] + 00196 r[1]*SO->NodeNormList[i3+1] + 00197 r[2]*SO->NodeNormList[i3+2] ; 00198 00199 if (fabs(dot[i]) < 0.9) { 00200 bad_ind[ibad] = i; 00201 bad_dot[ibad] = dot[i]; 00202 ++ibad; 00203 } 00204 } 00205 00206 bad_ind = (int *) SUMA_realloc(bad_ind, ibad * sizeof(int)); 00207 bad_dot = (float *)SUMA_realloc(bad_dot, ibad * sizeof(float)); 00208 00209 fname = SUMA_append_string(Froot, "_dotprod.1D.dset"); 00210 if (LocalHead) fprintf (SUMA_STDERR,"%s:\nWriting %s...\n", FuncName, fname); 00211 fid = fopen(fname, "w"); 00212 fprintf(fid,"#Cosine of node normal angles with radial direction\n" 00213 "#col 0: Node Index\n" 00214 "#col 1: cos(angle)\n" 00215 ); 00216 if (shist) fprintf(fid,"#History:%s\n", shist); 00217 for (i=0; i<SO->N_Node; ++i) fprintf(fid,"%d\t%f\n", i, dot[i]); 00218 fclose(fid); 00219 SUMA_free(fname); fname = NULL; 00220 00221 /* write the colorized data */ 00222 SV = SUMA_Create_ColorScaledVect(SO->N_Node); 00223 if (!SV) { 00224 fprintf (SUMA_STDERR,"Error %s: Could not allocate for SV.\n", FuncName); 00225 if (dot) SUMA_free(dot); 00226 if (bad_dot) SUMA_free(bad_dot); 00227 if (bad_ind) SUMA_free(bad_ind); 00228 if (isortdist) SUMA_free(isortdist); 00229 if (dist) SUMA_free(dist); 00230 if (CM) SUMA_Free_ColorMap (CM); 00231 if (OptScl) SUMA_free(OptScl); 00232 exit(1); 00233 } 00234 00235 if (!SUMA_ScaleToMap (dot, SO->N_Node, -1.0, 1.0, CM, OptScl, SV)) { 00236 fprintf (SUMA_STDERR,"Error %s: Failed in SUMA_ScaleToMap.\n", FuncName); 00237 exit(1); 00238 } 00239 fname = SUMA_append_string(Froot, "_dotprod.1D.col"); 00240 if (LocalHead) fprintf (SUMA_STDERR,"%s:\nWriting %s...\n", FuncName, fname); 00241 fid = fopen(fname, "w"); 00242 fprintf(fid,"#Color file of cosine of node normal angles with radial direction\n" 00243 "#col 0: Node Index\n" 00244 "#col 1: R\n" 00245 "#col 2: G\n" 00246 "#col 3: B\n" 00247 ); 00248 if (shist) fprintf(fid,"#History:%s\n", shist); 00249 for (i=0; i<SO->N_Node; ++i) fprintf(fid,"%d\t%f\t%f\t%f\n", i, SV->cV[3*i ], SV->cV[3*i+1], SV->cV[3*i+2]); 00250 fclose(fid); 00251 SUMA_free(fname); fname = NULL; 00252 if (SV) SUMA_Free_ColorScaledVect (SV); 00253 00254 fname = SUMA_append_string(Froot, "_BadNodes.1D.dset"); 00255 if (LocalHead) fprintf (SUMA_STDERR,"%s:\nWriting %s...\n", FuncName, fname); 00256 fid = fopen(fname, "w"); 00257 fprintf(fid,"#Nodes with normals at angle with radial direction: abs(dot product < 0.9)\n" 00258 "#col 0: Node Index\n" 00259 "#col 1: cos(angle)\n" 00260 ); 00261 if (shist) fprintf(fid,"#History:%s\n", shist); 00262 for (i=0; i<ibad; ++i) fprintf(fid,"%d\t%f\n", bad_ind[i], bad_dot[i]); 00263 fclose(fid); 00264 SUMA_free(fname); fname = NULL; 00265 00266 /* write the colorized data */ 00267 SV = SUMA_Create_ColorScaledVect(ibad); 00268 if (!SV) { 00269 fprintf (SUMA_STDERR,"Error %s: Could not allocate for SV.\n", FuncName); 00270 if (dot) SUMA_free(dot); 00271 if (bad_dot) SUMA_free(bad_dot); 00272 if (bad_ind) SUMA_free(bad_ind); 00273 if (isortdist) SUMA_free(isortdist); 00274 if (dist) SUMA_free(dist); 00275 if (CM) SUMA_Free_ColorMap (CM); 00276 if (OptScl) SUMA_free(OptScl); 00277 exit(1); 00278 } 00279 00280 if (!SUMA_ScaleToMap (bad_dot, ibad, -1.0, 1.0, CM, OptScl, SV)) { 00281 fprintf (SUMA_STDERR,"Error %s: Failed in SUMA_ScaleToMap.\n", FuncName); 00282 if (dot) SUMA_free(dot); 00283 if (bad_dot) SUMA_free(bad_dot); 00284 if (bad_ind) SUMA_free(bad_ind); 00285 if (isortdist) SUMA_free(isortdist); 00286 if (dist) SUMA_free(dist); 00287 if (CM) SUMA_Free_ColorMap (CM); 00288 if (OptScl) SUMA_free(OptScl); 00289 exit(1); 00290 } 00291 fname = SUMA_append_string(Froot, "_BadNodes.1D.col"); 00292 if (LocalHead) fprintf (SUMA_STDERR,"%s:\nWriting %s...\n", FuncName, fname); 00293 fid = fopen(fname, "w"); 00294 fprintf(fid,"#Color file of nodes with normals at angle with radial direction: abs(dot product < 0.9)\n" 00295 "#col 0: Node Index\n" 00296 "#col 1: R\n" 00297 "#col 2: G\n" 00298 "#col 3: B\n" ); 00299 if (shist) fprintf(fid,"#History:%s\n", shist); 00300 for (i=0; i<ibad; ++i) fprintf(fid,"%d\t%f\t%f\t%f\n", bad_ind[i], SV->cV[3*i ], SV->cV[3*i+1], SV->cV[3*i+2]); 00301 fclose(fid); 00302 SUMA_free(fname); fname = NULL; 00303 if (SV) SUMA_Free_ColorScaledVect (SV); 00304 00305 00306 /* report, just 10 of them */ 00307 if (ibad > 10) ibad = 10; 00308 fprintf (SUMA_STDERR,"%d of the nodes with normals at angle with radial direction\n" 00309 " i.e. abs(dot product < 0.9)\n" 00310 " See output files for full list\n", ibad); 00311 for (i=0; i < ibad; ++i) { 00312 fprintf (SUMA_STDERR,"cos(ang) @ node %d: %f\n", bad_ind[i], bad_dot[i]); 00313 } 00314 00315 if (dot) SUMA_free(dot); 00316 if (bad_dot) SUMA_free(bad_dot); 00317 if (bad_ind) SUMA_free(bad_ind); 00318 if (isortdist) SUMA_free(isortdist); 00319 if (dist) SUMA_free(dist); 00320 if (CM) SUMA_Free_ColorMap (CM); 00321 if (OptScl) SUMA_free(OptScl); 00322 00323 00324 SUMA_RETURN(YUP); 00325 } |
|
SUMA_tesselate(nodeList, triList, nCtr, tCtr, N_Div, n0, n1, n2); This function tesselates triangle by dividing edges into N_Div segments.
Definition at line 433 of file SUMA_SphericalMapping.c. References i, n0, n1, n2, SUMA_addTri(), SUMA_divEdge(), SUMA_ENTRY, SUMA_free, SUMA_RETURNe, and SUMA_triangulateRow(). Referenced by SUMA_CreateIcosahedron().
00433 { 00434 00435 int i=0, j=0; 00436 int *edge01=NULL, *edge12=NULL, *edge20=NULL, *currFloor=NULL; 00437 static char FuncName[]={"SUMA_tesselate"}; 00438 00439 SUMA_ENTRY; 00440 00441 edge01 = SUMA_divEdge( nodeList, nCtr, n0, n1, N_Div); 00442 edge12 = SUMA_divEdge( nodeList, nCtr, n2, n1, N_Div); 00443 edge20 = SUMA_divEdge( nodeList, nCtr, n0, n2, N_Div); 00444 if (!edge01 || !edge12 || !edge20) { 00445 fprintf (SUMA_STDERR, "Error %s: Failed in SUMA_divEdge.\n", FuncName); 00446 SUMA_RETURNe; 00447 } 00448 00449 currFloor = edge20; 00450 00451 for (i=1; i<N_Div; ++i) { 00452 SUMA_triangulateRow( nodeList, triList, nCtr, tCtr, N_Div-i, currFloor, edge01[i], edge12[i]); 00453 } 00454 00455 SUMA_addTri( triList, tCtr, currFloor[1], n1, currFloor[0]); 00456 00457 if (edge01) SUMA_free(edge01); 00458 if (edge12) SUMA_free(edge12); 00459 if (edge20) SUMA_free(edge20); 00460 00461 SUMA_RETURNe; 00462 } |
|
SUMA_triangulateRow (nodeList, triList, nCtr, tCtr, N_Div, currFloor, node1, node2); Creates triangulation between line segments currFloor and node1-node2. It is expected that node1-node2 has one fewer node than currFloor.
Definition at line 553 of file SUMA_SphericalMapping.c. References i, n1, n2, SUMA_addNode(), SUMA_addTri(), SUMA_calloc, SUMA_ENTRY, SUMA_free, and SUMA_RETURNe. Referenced by SUMA_tesselate().
00553 { 00554 00555 int i=0, j=0; 00556 float n1[3], n2[3], newNode[3]; 00557 int *newArray = NULL; 00558 static char FuncName[]={"SUMA_triangulateRow"}; 00559 00560 SUMA_ENTRY; 00561 00562 newArray = (int *)SUMA_calloc(N_Div+1, sizeof(int)); 00563 if (!newArray) { 00564 fprintf (SUMA_STDERR, "Error %s: Failed to allocate.\n", FuncName); 00565 SUMA_RETURNe; 00566 } 00567 00568 n1[0] = nodeList[3*node1]; n1[1] = nodeList[3*node1+1]; n1[2] = nodeList[3*node1+2]; 00569 n2[0] = nodeList[3*node2]; n2[1] = nodeList[3*node2+1]; n2[2] = nodeList[3*node2+2]; 00570 newArray[0] = node1; newArray[N_Div] = node2; 00571 00572 SUMA_addTri( triList, tCtr, currFloor[1], currFloor[0], newArray[0]); 00573 00574 for (i=1; i<N_Div; ++i) { 00575 newNode[0] = ((float)i/(float)N_Div)*(n2[0]-n1[0]) + n1[0]; 00576 newNode[1] = ((float)i/(float)N_Div)*(n2[1]-n1[1]) + n1[1]; 00577 newNode[2] = ((float)i/(float)N_Div)*(n2[2]-n1[2]) + n1[2]; 00578 00579 SUMA_addNode( nodeList, nCtr, newNode[0], newNode[1], newNode[2]); 00580 newArray[i] = (nCtr[0]-2)/3; 00581 SUMA_addTri( triList, tCtr, newArray[i-1], currFloor[i], newArray[i]); 00582 SUMA_addTri( triList, tCtr, currFloor[i+1], newArray[i], currFloor[i]); 00583 } 00584 SUMA_addTri( triList, tCtr, newArray[N_Div-1], currFloor[N_Div], newArray[N_Div]); 00585 SUMA_addTri( triList, tCtr, newArray[N_Div], currFloor[N_Div+1], currFloor[N_Div]); 00586 00587 for (i=0; i<N_Div+1; ++i) { 00588 currFloor[i] = newArray[i]; 00589 } 00590 00591 if (newArray) SUMA_free(newArray); 00592 00593 SUMA_RETURNe; 00594 } |
|
SUMA_write1D( num, vals, outFileNm); Function to write simple 1D file.
Definition at line 3845 of file SUMA_SphericalMapping.c. References firstline, i, SUMA_ENTRY, and SUMA_RETURNe.
03845 { 03846 03847 FILE *outFile=NULL; 03848 int i=0, j=0, k=0; 03849 static char FuncName[]={"SUMA_write1D"}; 03850 03851 SUMA_ENTRY; 03852 03853 outFile = fopen(outFileNm, "w"); 03854 if (!outFile) { 03855 fprintf (SUMA_STDERR, "Failed in opening %s for writing.\n", outFileNm); 03856 exit (1); 03857 } 03858 else { 03859 if (firstline!=NULL) fprintf (outFile, "%s\n", firstline); 03860 for (i=0; i<num[0]; ++i) { 03861 if ( index!=NULL ) { 03862 /*index array given - use only those indices from vals*/ 03863 j = index[i] * num[1]; 03864 fprintf( outFile, "%10d ", index[i]); 03865 } 03866 else j = i*num[1]; /*index array not given - standard increment*/ 03867 for ( k=0; k<num[1]; ++k ) { 03868 /*print vals to file*/ 03869 fprintf( outFile, "%10f ", vals[ j+k ]); 03870 } 03871 fprintf( outFile, "\n"); 03872 } 03873 fclose(outFile); 03874 } 03875 SUMA_RETURNe; 03876 } |
|
SUMA_writeColorFile(array, size, fileNm); Function to write out colorfile.
Definition at line 2057 of file SUMA_SphericalMapping.c. References array, i, SUMA_ENTRY, and SUMA_RETURNe.
02057 { 02058 02059 FILE *outFile=NULL; 02060 int i=0, j=0; 02061 static char FuncName[] = {"SUMA_writeColorFile"}; 02062 02063 SUMA_ENTRY; 02064 02065 for (i=0; i<numNode; ++i) { 02066 j = 3*i; 02067 } 02068 02069 for (i=0; i<numNode; ++i) { 02070 j = 3*i; 02071 } 02072 02073 if((outFile = fopen(fileNm, "w"))==NULL) { 02074 fprintf(SUMA_STDERR, "Could not open file %s.\n", fileNm); 02075 exit(1); 02076 } 02077 else { 02078 if (index!=NULL) { 02079 /*use given indices*/ 02080 for (i=0; i<numNode; ++i) { 02081 j = 3*i; 02082 fprintf (outFile, "%d\t%f\t%f\t%f\n", index[i], array[j], array[j+1], array[j+2]); 02083 } 02084 } 02085 else { 02086 /*assume indices increment by 1 (all nodes have color)*/ 02087 for (i=0; i < numNode; ++i) { 02088 j = i*3; 02089 fprintf (outFile, "%d\t%f\t%f\t%f\n", i, array[j], array[j+1], array[j+2]); 02090 } 02091 } 02092 fclose (outFile); 02093 } 02094 SUMA_RETURNe; 02095 } |
|
SUMA_writeFSfile(nodeList, faceList, numNode, numFace, firstLine, fileNm); Function to write out file in freesurfer format.
Definition at line 2111 of file SUMA_SphericalMapping.c. References SUMA_SurfaceObject::FaceSetList, i, SUMA_SurfaceObject::N_FaceSet, SUMA_SurfaceObject::N_Node, SUMA_SurfaceObject::NodeList, SUMA_ENTRY, and SUMA_RETURNe.
02111 { 02112 02113 FILE *outFile=NULL; 02114 int i=0, j=0; 02115 static char FuncName[]={"SUMA_writeFSfile"}; 02116 02117 SUMA_ENTRY; 02118 02119 outFile = fopen(fileNm, "w"); 02120 if (!outFile) { 02121 fprintf (SUMA_STDERR, "Error %s: Failed in opening %s for writing.\n",FuncName, fileNm); 02122 exit(1); 02123 } 02124 else { 02125 if ( firstLine!=NULL ) 02126 fprintf (outFile,"# %s\n", firstLine); 02127 else fprintf (outFile, "#\n"); 02128 fprintf (outFile, "%d %d\n", SO->N_Node, SO->N_FaceSet); 02129 02130 j=0; 02131 for (i=0; i<SO->N_Node; ++i) { 02132 j=3*i; 02133 fprintf (outFile, "%f %f %f 0\n", SO->NodeList[j], SO->NodeList[j+1], SO->NodeList[j+2]); 02134 } 02135 02136 j=0; 02137 for (i=0; i<SO->N_FaceSet; ++i) { 02138 j = 3*i; 02139 fprintf (outFile, "%d %d %d 0\n", SO->FaceSetList[j], SO->FaceSetList[j+1], SO->FaceSetList[j+2]); 02140 } 02141 02142 fclose(outFile); 02143 } 02144 02145 SUMA_RETURNe; 02146 } |
|
SUMA_writeSpecFile( surfaces, numSurf, program, group, specFileNm); Function to write suma spec file.
Definition at line 2161 of file SUMA_SphericalMapping.c. References format, i, p, SUMA_ENTRY, and SUMA_RETURNe.
02161 { 02162 02163 FILE *outFile=NULL; 02164 int i=0, k=0, tag=0, ifSmwm=0, p=0; 02165 static char FuncName[]={"SUMA_writeSpecFile"}; 02166 02167 SUMA_ENTRY; 02168 02169 outFile = fopen(specFileNm, "w"); 02170 if (!outFile) { 02171 fprintf (SUMA_STDERR, "Failed in opening %s for writing.\n", specFileNm); 02172 exit (1); 02173 } 02174 else { 02175 fprintf (outFile, "# %s spec file for %s\n\n", program, group); 02176 fprintf (outFile, "#define the group\n\tGroup = %s\n\n", group); 02177 fprintf (outFile, "#define various States\n"); 02178 for (i=0; i<numSurf; ++i) { 02179 tag = 0; 02180 for (k=0; k<i; ++k) { 02181 if ( strcmp( surfaces[k].state, surfaces[i].state ) == 0) tag = -1; 02182 } 02183 if (tag==0) { 02184 fprintf( outFile, "\tStateDef = %s\n", surfaces[i].state); 02185 } 02186 } 02187 02188 for (i=0; i<numSurf; ++i) { 02189 fprintf (outFile, "\nNewSurface\n\tSurfaceFormat = %s\n\tSurfaceType = %s\n", surfaces[i].format, surfaces[i].type); 02190 fprintf (outFile, "\tFreeSurferSurface = %s\n\tLocalDomainParent = %s\n", surfaces[i].fileToRead, surfaces[i].mapRef ); 02191 fprintf (outFile, "\tSurfaceState = %s\n\tEmbedDimension = %s\n", surfaces[i].state, surfaces[i].dim); 02192 } 02193 02194 fclose(outFile); 02195 } 02196 SUMA_RETURNe; 02197 } |
Variable Documentation
|
Definition at line 39 of file SUMA_SphericalMapping.c. Referenced by cpexpr(), getenv_(), intrcall(), PLUG_get_many_plugins(), qzit_(), ratqr_(), SUMA_binTesselate(), SUMA_BrainVoyager_Read_vmr(), SUMA_CreateIcosahedron(), SUMA_divEdge(), SUMA_OpenDX_Read_CruiseVolHead(), and tztrim(). |
|
Global pointer to structure containing info common to all viewers Definition at line 34 of file SUMA_SphericalMapping.c. |
|
Global pointer to Displayable Object structure vector Definition at line 36 of file SUMA_SphericalMapping.c. |
|
Number of DOs stored in DOv Definition at line 35 of file SUMA_SphericalMapping.c. |