Skip to content

AFNI/NIfTI Server

Sections
Personal tools
You are here: Home » AFNI » Documentation

Doxygen Source Code Documentation


Main Page   Alphabetical List   Data Structures   File List   Data Fields   Globals   Search  

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_SurfaceObjectSUMA_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_MorphInfoSUMA_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_mapSUMA_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_MorphInfoSUMA_Create_MorphInfo (void)
SUMA_Boolean SUMA_Free_MorphInfo (SUMA_MorphInfo *MI)
SUMA_SurfaceObjectSUMA_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_1dDataSUMA_Create_1dData (void)
SUMA_Boolean SUMA_Free_1dData (SUMA_1dData *data)

Variables

SUMA_CommonFieldsSUMAg_CF
int SUMAg_N_DOv
SUMA_DOSUMAg_DOv
float ep = 1e-4

Function Documentation

float intersection_map float    a,
float    b,
float    c,
float    d,
float    val
 

gives value for intersection of two lines, as defined in SUMA_MapSurface (see p10 LNB)

Definition at line 1175 of file SUMA_SphericalMapping.c.

References a, and c.

Referenced by SUMA_detWeight().

01175                                                                       {
01176   
01177    float sol = (val*(c-d) - d*(a-b)) / (c+b-a-d);
01178 
01179    return sol;
01180 }

void SUMA_addNode float *    nodeList,
int *    ctr,
float    x,
float    y,
float    z
 

SUMA_addNode(nodeList, ctr, x, y, z);

Function to add the x, y, z corrdinates of a node to nodeList.

Parameters:
nodeList  (float *) 3 x N_node array of x,y,z coordinates of nodes
ctr  (int *) current position in nodeList
x, y, z  (float) x, y, z values of added node

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 }

void SUMA_addTri int *    triList,
int *    ctr,
int    n1,
int    n2,
int    n3
 

SUMA_addTri(triList, ctr, n1, n2, n3);

Function to add the three nodes of a triangle to triList.

Parameters:
triList  (int *) 3 x N_tri array of node indices creating triangles
ctr  (int *) current position in triList
n1, n2, n3  (int *) nodeList indices of nodes creating added triangle

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 }

float* SUMA_assignColors float *    vals,
float *    cols,
int    numVal,
int    numCol,
float *    gradRng,
float *    valDiv
 

array = SUMA_assignColors( vals, cols, numVal, numCol, gradRng, valDiv );

Function to assign colors to vector of values.

Parameters:
vals  (float *) vector (size numVal) of values to be assigned colors
cols  (float *) vector (size 3 x numCol) of RGB colors
numVal  (int) number of values in vals vector
numCol  (int) number of colors in cols vector
gradRng  (float *) range of values through which color gradient changes - implies colors below range all assigned to same color (same goes for above range); passing NULL assumes min/max of vals vector taken as gradient range
valDiv  (float *) returned containing upper limit on value divisions (pass as NULL) \ret valCol (float *) 3 x numVal vector of RGB colors (or 100, if numDiv==-1) colors, in 3x(numDiv+1) format (corresponding to RGB)
Written by Brenna Argall

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_Boolean SUMA_binSearch float *    nodeList,
float    target,
int *    seg
 

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.

Parameters:
nodeList  (float *) vector of sorted values
target  (float) value seeking
seg  (int *) contains begin and end point of segment being searched
Returns:
found (SUMA_Boolean) YUP if all passed correctly and target within segment, NOPE otherwise
Written by Brenna Argall

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 }

void SUMA_binTesselate float *    nodeList,
int *    triList,
int *    nCtr,
int *    tCtr,
int    recDepth,
int    depth,
int    n1,
int    n2,
int    n3
 

SUMA_binTesselate(nodeList, triList, nCtr, tCtr, recDepth, depth, n1, n2, n3);

This function divides 1 triangle into 4 recursively to depth recDepth.

Parameters:
nodeList  (float *) 3 x N_Node list of nodes (updated as new nodes created during tesselation)
triList  (int *) 3 x N_Triangle list of nodes assoicated with each triangle (updated as new triangles created during tesselation)
nCtr  (int *) index of most recently added node to nodeList
tCtr  (int *) index of most recently added triangle to triList
recDepth  (int) recursion depth
depth  (int) current depth
n1, n2, n3  (int) indices in nodeList corresponding to three nodes of triangle being tesselated
Returns:
void (but nodeList and triList updated)
Written by Brenna Argall

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 }

SUMA_1dData* SUMA_Create_1dData void   
 

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 }

SUMA_MorphInfo* SUMA_Create_MorphInfo void   
 

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 }

SUMA_SO_map* SUMA_Create_SO_map void   
 

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 }

float* SUMA_createColGradient float *    col,
int    numSeg,
SUMA_Boolean    allGvn
 

array = SUMA_createColGradient( col, numDiv);

Function to create a color gradient.

Parameters:
col  (float *) vector of colors for range (1->8, roygbivr). If allGvn==YUP, pass only two (which are taken as endpoints). If NULL, assumed to be continuous
numSeg  (int) number of segments in final gradient (=length of col if allGvn==YUP); pass as -1 for continuous gradient
addGvn  (SUMA_Boolean) indicates whether col expressly gives all colors to be used in colSeg \ret colSeg (float *) vector of numSeg (or 700, if numSeg==-1) colors, in 3x(numSeg) format (corresponding to RGB)
Written by Brenna Argall

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 }

SUMA_SurfaceObject* SUMA_CreateIcosahedron float    r,
int    depth,
float    ctr[3],
char    bin[],
int    ToSphere
 

SO = SUMA_CreateIcosahedron (r, depth, ctr, bin, ToSphere);

This function creates an icosahedron of size r and to tesselation extent depth.

Parameters:
r  (float) size of icosahedron (distance from center to node).
depth  (int) number of edge subdivisions (bin='n') or depth of recursive tesselation (bin='y')
ctr  (float[]) coordinates of center of icosahedron
bin  (char[]) indicates whether tesselation binary/recursive ('y') or brute ('n')
ToSpHere  (int) if 1 then project nodes to form a sphere of radius r \ret SO (SUMA_SurfaceObject *) icosahedron is a surface object structure. returns NULL if function fails. SO returned with NodeList, N_Node, FaceSetList, N_FaceSet, and NodeNormList
Written by Brenna Argall

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 }

float* SUMA_detWeight float    node0[3],
float    node1[3],
float    node2[3],
float    ptHit[3]
 

weight = SUMA_detWeight ( node0, node1, node2, hitPt );

This function determines the weight of each of three nodes on a given point based upon distance.

Parameters:
node0  (double[3]) contains x,y,z coordinates for first node
node1  (double[3]) contains x,y,z coordinates for second node
node2  (double[3]) contains x,y,z coordinates for third node
ptHit  (double[3]) contains x,y,z coordinates for point feeling weight
Returns:
weight (double[3]) contains weights for each node0, node1, node2
Written by Brenna Argall

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 } 

int* SUMA_divEdge float *    nodeList,
int *    nCtr,
int    node1,
int    node2,
int    N_Div
 

edge = SUMA_divEdge( nodeList, nCtr, node1, node2, N_Div);

Divides an edge defined by node1-node2 into N_Div segments.

Parameters:
nodeList  (float *) 3 x N_Node list of nodes
nCtr  (int *) current number of elements in nodeList
node1, node2  (int) nodes defining edge being divided
N_Div  (int) number of segments edge divided into
Returns:
edge (int *) N_Div+1 list of nodes on edge (after segmentation)
Written by Brenna Argall

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 }

SUMA_Boolean SUMA_Free_1dData SUMA_1dData   data
 

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 }

SUMA_Boolean SUMA_Free_MorphInfo SUMA_MorphInfo   MI
 

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 }

SUMA_Boolean SUMA_Free_SO_map SUMA_SO_map   SOM
 

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 SUMA_SurfaceObject   surf,
float *    nodeList,
int *    node,
float *    P0,
float *    P1
 

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.

Parameters:
surf  (SUMA_SurfaceObject) surface being intersected by P1
nodeList  (float *) 3 x N_Node vector of nodes in surface (pass as NULL if equals surf->NodeList)
node  (int *) vector to contain 3 nodes of intersected triangle, originally contains three nodes to work with. if you want only 1 or 2 nodes examined, use node[1] = -1 or node[2] = -1, respectively
PO  (float *) point to form ray with P1 st ray slope = node normal of P1
P1  (float *) intersecting point in question; if not on surface, returned with point where ray intersects surface \ret found (SUMA_Boolean) true if P1 in triangle with node[0] as a node
Written by Ziad Saad / Brenna Argall

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 }

SUMA_MorphInfo* SUMA_MapSurface SUMA_SurfaceObject   surf1,
SUMA_SurfaceObject   surf2
 

MI = MapSurface (surf1, surf2);

This function creates a mapping of one surface onto another (surfaces assumed to be spherical).

Parameters:
surf1  (SUMA_SurfaceObject *) first surface of surface object structure
surf2  (SUMA_SurfaceObject *) second surface of surface object structure
Returns:
MI (SUMA_MorphInfo *) contains information necessary to perform forwards and backwards morphing; returns NULL if function fails. MI returned with N_Node, N_FaceSet, Weight, ClsNodes and FaceSetList.
Written by Brenna Argall

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 } 

SUMA_SurfaceObject* SUMA_morphToStd SUMA_SurfaceObject   SO,
SUMA_MorphInfo   MI,
SUMA_Boolean    nodeChk
 

newNodeList = SUMA_morphToStd( nodeList, MI);

Function to morph surface to standard grid.

Parameters:
SO  (SurfaceObject *) surface being morphed
MI  (SUMA_MorphInfo *) structure containing morph information
nodeChk  (SUMA_Boolean) checks that nodes indicated in MI for morphing actually exist in SO (possibly do not if SO is a patch); if nodeChk, SO->FN cannot be NULL \ret SO_new (SUMA_SurfaceObject *) morphed surface; returned with NodeList, FaceSetList, N_Node, N_FaceSet, NodeDim, FaceSetDim, idcode_st
Written by Brenna Argall

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_read1D char *    fileNm,
int *    i_colm,
int *    i_locInfo,
SUMA_1dData   data
 

void = SUMA_readANOVA1D( fileNm, i_colm, i_locInfo, data );

Function to read a 1D file into an array.

Parameters:
fileNm  (char *) name of 1D file to be read
i_colm  (int *) indicates which value columns of 1D file to be read; [0] should contain the number of columns to be read
i_locInfo  (int *) gives column index of location information; [0] for node index, [1] for voxel index, [2],[3],[4] for ijk values; pass as NULL if file contains none of this information, or with -1 for the absence of a particular column
data  (SUMA_1dData *) structure passed back containing file information (can be passed empty, must be allocated for); multiple value columns are passed back concatanated as a 1D array in 'valArray' \ret A (SUMA_1dData *) structure containing column information indicated
Written by Brenna Argall

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 }

float* SUMA_readColor int    numNodes,
char *    colFileNm
 

array = SUMA_readColor( numNodes, colFileNm);

Function to read a colorfile into an array.

Parameters:
numNodes  (int) size of created array
colFileNm  (char *) name of color file to be read \ret colArray (float *) array of colorfile values
Written by Brenna Argall

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 }

void SUMA_Search_Min_Dist float *    pt,
float *    nodeList,
int *    seg,
float    restr,
float *    dist,
int *    i_dist
 

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.

Parameters:
pt  (float *) Point to which distances are calculated (length is 3: x y z).
nodeList  (float *) Array (1D) of x,y,z values of nodes.
seg  (int *) Contains beginning and ending indices of search segment of nodeList.
restr  (float) Restriction distance for searching within each (x,y,z) dimension.
dist  (float *) Returned containing 3 minimum distances; may be passed already containing distances to be updated or as empty (but allocated for). If empty, default initializes to 3*pow(restr,2).
i_dist  (int *) Indices of nodes within nodeList from which distances contained in dist were calculated. \ret void

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 }

SUMA_Boolean SUMA_Show_SO_map SUMA_SO_map   SOM,
FILE *    out
 

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 }

SUMA_Boolean SUMA_SphereQuality SUMA_SurfaceObject   SO,
char *    Froot,
char *    shist
 

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 }

void SUMA_tesselate float *    nodeList,
int *    triList,
int *    nCtr,
int *    tCtr,
int    N_Div,
int    n0,
int    n1,
int    n2
 

SUMA_tesselate(nodeList, triList, nCtr, tCtr, N_Div, n0, n1, n2);

This function tesselates triangle by dividing edges into N_Div segments.

Parameters:
nodeList  (float *) 3 x N_Node list of nodes (updated as new nodes created during tesselation)
triList  (int *) 3 x N_Triangle list of nodes assoicated with each triangle (updated as new triangles created during tesselation)
nCtr  (int *) index of most recently added node to nodeList
tCtr  (int *) index of most recently added triangle to triList
N_Div  (int) number of edge divides
n1,n2,n3  (int) indices in nodeList corresponding to three nodes of triangle being tesselated
Returns:
void (but nodeList and triList updated)
Written by Brenna Argall

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 }

void SUMA_triangulateRow float *    nodeList,
int *    triList,
int *    nCtr,
int *    tCtr,
int    N_Div,
int *    currFloor,
int    node1,
int    node2
 

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.

Parameters:
nodeList  (float *) 3 x N_Node list of nodes
triList  (int *) 3 x N_Tri list of node indicies corresponding to triangles
nCtr  (int *) current number of elements in nodeList
tCtr  (int *) current number of elements in triList
N_Div  (int) number of divisions to be created from line segment node1-node2
currFloor  (int *) vector containing nodes of line segment "below" segment node1-node2 (length N_Div+1)
node1, node2  (int) nodeList indices of nodes defining segment "above" currFloor
Returns:
void (but triList and nodeList updated)
Written by Brenna Argall

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 }

void SUMA_write1D int *    num,
float *    vals,
int *    index,
char    firstline[],
char    outFileNm[]
 

SUMA_write1D( num, vals, outFileNm);

Function to write simple 1D file.

Parameters:
num  (int*) [0] contains number of rows, [1] number of columns, to be written
vals  (float*) vector of values (size: num[0]*num[1], format: contcatanated rows)
index  (int*) vector of indicies (size: num[0]); pass as NULL if standard increment
firstline  (char[]) comment for top of file
outFileNm  (char[]) name of file written to
Returns:
void
Written by Brenna Argall

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 }

void SUMA_writeColorFile float *    array,
int    numNode,
int *    index,
char    fileNm[]
 

SUMA_writeColorFile(array, size, fileNm);

Function to write out colorfile.

Parameters:
array  (float*) list of colors to be written
numNode  (int) number of nodes to be xwritten to file
index  (int*) array of node indices to receive color; pass as NULL if index standard (increments by one)
fileNm  (char) name of file to be written to
Written by Brenna Argall

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 }

void SUMA_writeFSfile SUMA_SurfaceObject   SO,
char    firstLine[],
char    fileNm[]
 

SUMA_writeFSfile(nodeList, faceList, numNode, numFace, firstLine, fileNm);

Function to write out file in freesurfer format.

Parameters:
nodeList  (float *) list of nodes
faceList  (int *) list of faces
numNode  (int) number of nodes
numFace  (int) number of faces
firstLine  (char) comment string for first line of file
fileNm  (char) name of file to be written to \ret void
Written by Brenna Argall

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 }

void SUMA_writeSpecFile SUMA_SpecSurfInfo   surfaces,
int    numSurf,
char    program[],
char    group[],
char    specFileNm[]
 

SUMA_writeSpecFile( surfaces, numSurf, program, group, specFileNm);

Function to write suma spec file.

Parameters:
surfaces  (SUMA_specSurfInfo *) necessary surface information for spec file
numSurf  (int) number of surfaces in spec file
program  (char[]) name of program calling function
group  (char[]) name of group
fileNm  (char[]) name of created spec file
Returns:
void
Written by Brenna Argall

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

float ep = 1e-4
 

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().

SUMA_CommonFields* SUMAg_CF  
 

Global pointer to structure containing info common to all viewers

Definition at line 34 of file SUMA_SphericalMapping.c.

SUMA_DO* SUMAg_DOv  
 

Global pointer to Displayable Object structure vector

Definition at line 36 of file SUMA_SphericalMapping.c.

int SUMAg_N_DOv  
 

Number of DOs stored in DOv

Definition at line 35 of file SUMA_SphericalMapping.c.

 

Powered by Plone

This site conforms to the following standards: