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_SurfNorm.c File Reference

#include "SUMA_suma.h"

Go to the source code of this file.


Functions

SUMA_SURF_NORM SUMA_SurfNorm (float *NodeList, int N_NodeList, int *FaceSetList, int N_FaceSetList)
SUMA_MEMBER_FACE_SETSSUMA_MemberFaceSets (int Nind, int *FaceSetList, int nFr, int FaceDim, char *ownerid)
SUMA_Boolean SUMA_Free_MemberFaceSets (SUMA_MEMBER_FACE_SETS *MF)

Variables

SUMA_CommonFieldsSUMAg_CF

Function Documentation

SUMA_Boolean SUMA_Free_MemberFaceSets SUMA_MEMBER_FACE_SETS   MF
 

Free a SUMA_MEMBER_FACE_SETS structure

Definition at line 386 of file SUMA_SurfNorm.c.

References SUMA_MEMBER_FACE_SETS::idcode_str, LocalHead, SUMA_MEMBER_FACE_SETS::N_links, SUMA_MEMBER_FACE_SETS::N_Memb, SUMA_MEMBER_FACE_SETS::Nnode, SUMA_MEMBER_FACE_SETS::NodeMemberOfFaceSet, SUMA_Boolean, SUMA_ENTRY, SUMA_free, SUMA_free2D(), SUMA_LH, SUMA_RETURN, and SUMA_UnlinkFromPointer().

Referenced by SUMA_Free_Surface_Object().

00387 {
00388    static char FuncName[]={"SUMA_Free_MemberFaceSets"};
00389    SUMA_Boolean LocalHead = NOPE;
00390    
00391    SUMA_ENTRY;
00392    if (!MF) { SUMA_RETURN (YUP); }
00393    if (MF->N_links) {
00394       SUMA_LH("Just a link release");
00395       MF = (SUMA_MEMBER_FACE_SETS *)SUMA_UnlinkFromPointer((void *)MF);
00396       SUMA_RETURN (YUP);
00397    }
00398    
00399    SUMA_LH("No more links, here we go");
00400    if (MF->idcode_str) SUMA_free(MF->idcode_str);
00401    if (MF->NodeMemberOfFaceSet) SUMA_free2D((char **)MF->NodeMemberOfFaceSet, MF->Nnode);
00402    if (MF->N_Memb) SUMA_free(MF->N_Memb);
00403    if (MF) SUMA_free(MF);
00404    SUMA_RETURN (YUP);
00405 }   

SUMA_MEMBER_FACE_SETS* SUMA_MemberFaceSets int    Nind,
int *    FaceSetList,
int    nFr,
int    FaceDim,
char *    ownerid
 

** File : SUMA_MemberFaceSets.c

Author:
Ziad Saad Date : Thu Jan 3 12:01:49 EST 2002
Purpose : Determines for each Node Index, from 0 to Nind-1 the indices of the FaceSets to which the node belongs.

Usage : RetStruct = SUMA_MemberFaceSets (int Nind, int * FaceSetList, int nFace, int FaceSetDim);

Input paramters :

Parameters:
Nind  (int) : Total number of nodes in Index. ( No value (node index) in FaceSetList can be > Nind-1 )
FaceSetList  (int *) : The FaceSetList vector (used to be matrix, prior to SUMA 1.2), [nFace x FaceSetDim]
nFace  (int) : number of FaceSets in FaceSetList
FaceSetDim  (int): column (2nd) dimension of FaceSetList (usually 3 or 4)
Returns :
Returns:
RetStruct : a SUMA_MEMBER_FACE_SETS type structure with the following fields NodeMemberOfFaceSet (int **) a matrix containing the indices of the FaceSets containing the nodes. Each row i in NodeMemberOfFaceSet lists all FaceSets containing the node i. The list is delimited by a -1 entry for all but the node that has a max of N_Memb_max members. the size of NodeMemberOfFaceSet is [Nind x N_Memb_max]; N_Memb (int *) the number of 1st order neighbors for each node in Index N_Memb_max (int) the second dimension of NodeMemberOfFaceSet, also represents the maximum number of FaceSets that any node belongs to. Nnode (int) : it's equal to Nind but it is kept here so that the structure can contain enough info to free memory that is allocated to it.
if (RetStruct.NodeMemberOfFaceSet == NULL) then an error occurred in the function

Support :

See also:
MemberFaceSets.c and .m for methods that work when the search is required for a few nodes only
Example: FaceSetList is: 1 4 6 6 4 2 6 1 3

and Nind is: 7

Then RetStruct.NodeMemberOfFaceSet is: -1 0 0 ( Node 0 is not used in FaceSetList ) 0 2 -1 (Node 1 is used in Facesets 0 & 2 ) 1 -1 0 (Node 2 is used in Faceset 1) 2 -1 0 (Node 3 is used in Faceset 2) 0 1 -1 (Node 4 is used in Facesets 0 & 1) -1 0 0 (Node 5 in not used in FaceSetList) 0 1 2 (Node 6 is used in all Facesets)

and RetStruct.N_Memb is: 0 2 1 1 2 0 3

Side effects : To free RetStruct, use: if (RetStruct.NodeMemberOfFaceSet) SUMA_free2D((char **)RetStruct.NodeMemberOfFaceSet, Nind); if (RetStruct.N_Memb) SUMA_free(RetStruct.N_Memb); if (RetStruct) SUMA_free(RetStrct);

Definition at line 303 of file SUMA_SurfNorm.c.

References i, SUMA_MEMBER_FACE_SETS::idcode_str, SUMA_MEMBER_FACE_SETS::LinkedPtrType, SUMA_MEMBER_FACE_SETS::N_links, SUMA_MEMBER_FACE_SETS::N_Memb, SUMA_MEMBER_FACE_SETS::N_Memb_max, SUMA_MEMBER_FACE_SETS::Nnode, SUMA_MEMBER_FACE_SETS::NodeMemberOfFaceSet, SUMA_MEMBER_FACE_SETS::owner_id, SUMA_allocate2D(), SUMA_calloc, SUMA_ENTRY, SUMA_free2D(), SUMA_LINKED_MEMB_FACE_TYPE, SUMA_malloc, SUMA_MAX_MEMBER_FACE_SETS, SUMA_NEW_ID, and SUMA_RETURN.

Referenced by main(), SUMA_CreateIcosahedron(), and SUMA_SurfaceMetrics_eng().

00304 {/*SUMA_MemberFaceSets*/
00305    static char FuncName[]={"SUMA_MemberFaceSets"}; 
00306    SUMA_MEMBER_FACE_SETS *RetStrct;
00307    int **tmpMember;
00308    int i, inode, iface, ip , NP;
00309    
00310    SUMA_ENTRY;
00311 
00312    NP = FaceDim;
00313    RetStrct = (SUMA_MEMBER_FACE_SETS *)SUMA_malloc(sizeof(SUMA_MEMBER_FACE_SETS));
00314    RetStrct->idcode_str = NULL;
00315    SUMA_NEW_ID(RetStrct->idcode_str, NULL);
00316    RetStrct->N_links = 0;
00317    if (ownerid) sprintf(RetStrct->owner_id, "%s", ownerid);
00318    else RetStrct->owner_id[0] = '\0';
00319    RetStrct->LinkedPtrType = SUMA_LINKED_MEMB_FACE_TYPE;
00320    
00321    RetStrct->N_Memb_max = RetStrct->Nnode = 0;
00322    RetStrct->N_Memb = NULL;
00323    RetStrct->NodeMemberOfFaceSet = NULL;
00324    
00325    /* Allocate return variables */
00326    tmpMember = (int **) SUMA_allocate2D (Nind, SUMA_MAX_MEMBER_FACE_SETS ,sizeof(int));
00327    RetStrct->N_Memb = (int *) SUMA_calloc (Nind, sizeof(int));
00328    
00329    if (!tmpMember || !RetStrct->N_Memb)
00330       {
00331          fprintf (SUMA_STDERR,"Error %s: Failed to allocate for tmpMember or RetStrct->N_Memb\n", FuncName);
00332          SUMA_RETURN (RetStrct);
00333       }
00334    
00335    /* loop through all facesets and tag nodes that make up FaceSets*/
00336    for (iface=0; iface<nFr; ++iface) {/*iface*/
00337       i = 0;
00338       ip = NP * iface;
00339       do {
00340          inode = FaceSetList[ip + i];
00341          if (inode > Nind) {
00342             fprintf (SUMA_STDERR,"Error %s: FaceSetList contains node indices >= Nind\n", FuncName);
00343             SUMA_RETURN (RetStrct);
00344          }
00345          tmpMember[inode][RetStrct->N_Memb[inode]] = iface; 
00346          ++RetStrct->N_Memb[inode];
00347          if (RetStrct->N_Memb[inode] >= SUMA_MAX_MEMBER_FACE_SETS) {
00348             fprintf (SUMA_STDERR,"Error %s: Node %d is member of (%d FaceSets) more than SUMA_MAX_MEMBER_FACE_SETS (%d)\n",\
00349                 FuncName, inode, RetStrct->N_Memb[inode], SUMA_MAX_MEMBER_FACE_SETS);
00350             SUMA_RETURN (RetStrct);
00351          }
00352          if (RetStrct->N_Memb[inode] > RetStrct->N_Memb_max) RetStrct->N_Memb_max = RetStrct->N_Memb[inode];
00353          ++i;
00354       } while (i < FaceDim);
00355    }
00356    
00357    /*allocate just enough for returning variables */
00358    RetStrct->NodeMemberOfFaceSet = (int **) SUMA_allocate2D (Nind, RetStrct->N_Memb_max ,sizeof(int));
00359    if (!RetStrct->NodeMemberOfFaceSet)
00360       {
00361          fprintf(SUMA_STDERR,"Error %s: Failed to allocate for RetStrct->NodeMemberOfFaceSet\n", FuncName);
00362          SUMA_RETURN (RetStrct);
00363       }
00364 
00365    /* loop through all nodes, cp results into RetStrct->NodeMemberOfFaceSet and seal with -1 */
00366    for (inode = 0; inode < Nind; ++inode) {
00367       i = 0;
00368       while (i < RetStrct->N_Memb[inode]) {
00369          RetStrct->NodeMemberOfFaceSet[inode][i] = tmpMember[inode][i];
00370          ++i;
00371       }
00372       /*seal with -1 */
00373       if (RetStrct->N_Memb[inode] < RetStrct->N_Memb_max) RetStrct->NodeMemberOfFaceSet[inode][i] = -1;
00374    }
00375 
00376    /* Clean up time */
00377    if (tmpMember) SUMA_free2D((char **)tmpMember, Nind);
00378    
00379    RetStrct->Nnode = Nind;
00380    SUMA_RETURN (RetStrct);
00381 
00382 }/*SUMA_MemberFaceSets*/

SUMA_SURF_NORM SUMA_SurfNorm float *    NodeList,
int    N_NodeList,
int *    FaceSetList,
int    N_FaceSetList
 

** File : SUMA_SurfNorm.c

Author:
Ziad Saad Date : Thu Jan 3 14:46:55 EST 2002
Purpose : Calculate the polygon and node normals making up a surface It is assumed that FaceSetList does NOT contain an index >= N_NodeList

Usage : RetStrct = SUMA_SurfNorm (NodeList, N_NodeList, FaceSetList, N_FaceSetList );

Input paramters :

Parameters:
NodeList  (float *): N_NodeList x 3 vector containing the XYZ coordinates of each node
N_NodeList  (int): number of nodes in NodeList
FaceSetList  (int *): [N_FaceSetList x 3] vector (matrix prior to SUMA 1.2) of node indices forming each triangular facet (FaceSets). The indices must be relative to NodeList
N_FaceSetList  (int): 1st dimension of FaceSetList
Returns :
Returns:
RetStrct, a structure of the type SUMA_SURF_NORM with the following fields N_Node (int) Number of nodes, 1st dim of NodeNormList N_Face (int) Number of facesets, 1st dim of FaceNormList FaceNormList (float *) N_Face x 3 vector (was matrix prior to SUMA 1.2) containing normalized normal vectors for each triangular faceset NodeNormList (float *) N_Node x 3 vector (was matrix prior to SUMA 1.2) containing normalized normal vectors for each node
Support :
See also:
SUMA_MemberFaceSets , Side effects : to free memory from RetStrct if (RetStrct.FaceNormList) SUMA_free(RetStrct.FaceNormList); if (RetStrct.NodeNormList) SUMA_free(RetStrct.NodeNormList);
The node normals are obtained by averaging the normals of the surrounding facesets (ie facesets containing the node). This is an approximation and in special cases like a cube with a particular tesselation, the normals could be biased in direction if the node is a member of more triangles on one side of the object than the other sides. See Lab-book NIH-2, page 142 for an illustration or this miserable ascii rendition.

------------------- ## * Here, Node I will have its normal biased towards the direction of N2 and N3 ## * | because node I is part of two triangles from one side and one triangle in ## N1 * | each of the other 2 sides. ## * | ## I * N3 | ------------------ * | |## |######| | ## N4 | * | ## | N2 * | ## | * | ## | * | ## | * ------------------

Definition at line 87 of file SUMA_SurfNorm.c.

References SUMA_SURF_NORM::FaceNormList, i, LocalHead, SUMA_SURF_NORM::N_Face, SUMA_SURF_NORM::N_Node, SUMA_SURF_NORM::NodeNormList, SUMA_alloc_problem(), SUMA_Boolean, SUMA_calloc, SUMA_ENTRY, SUMA_error_message(), SUMA_free, SUMA_LH, SUMA_RETURN, SUMA_SL_Warn, and SUMA_TriNorm().

Referenced by main(), SUMA_Cmap_To_SO(), SUMA_Cmap_To_SO_old(), SUMA_CreateIcosahedron(), SUMA_Pattie_Volume(), and SUMA_PrepSO_GeomProp_GL().

00088 {/*SUMA_SurfNorm*/
00089    static char stmp[200], FuncName[]={"SUMA_SurfNorm"}; 
00090    float d1[3], d2[3], d, nrm;
00091    SUMA_SURF_NORM RetStrct;
00092    int *Index, *N_Memb, i, j, maxind, NotMember, id, id2, ND, ip, NP;
00093    SUMA_Boolean LocalHead = NOPE;
00094    
00095    SUMA_ENTRY;
00096    
00097    ND = 3;
00098    NP = 3;
00099    RetStrct.N_Node = N_NodeList; /* redundant, but practical for clean up outside the function */
00100    RetStrct.N_Face = N_FaceSetList;
00101 
00102    /* allocate space */
00103    if (LocalHead) fprintf(SUMA_STDERR,"%s: %d %d\n", FuncName, N_NodeList, N_FaceSetList);
00104    RetStrct.FaceNormList = (float *)SUMA_calloc (N_FaceSetList * NP, sizeof(float));
00105    RetStrct.NodeNormList = (float *)SUMA_calloc (N_NodeList * ND, sizeof(float));
00106    Index = (int *)SUMA_calloc (N_NodeList, sizeof(int));
00107    N_Memb = (int *)SUMA_calloc (N_NodeList, sizeof(int));
00108    if (!RetStrct.FaceNormList || !RetStrct.NodeNormList || !Index || !N_Memb)
00109       {
00110          SUMA_alloc_problem (FuncName);
00111          SUMA_RETURN (RetStrct);
00112       }
00113 
00114    /* calculate and normalize triangle normals */
00115    maxind = N_NodeList -1;
00116    for (i=0; i < N_FaceSetList; i++) {
00117       ip = NP * i;
00118       for (j=0; j < 3; j++) {
00119          d1[j] = NodeList[(ND*FaceSetList[ip])+j] - NodeList[(ND*FaceSetList[ip+1])+j];
00120          d2[j] = NodeList[(ND*FaceSetList[ip+1])+j] - NodeList[(ND*FaceSetList[ip+2])+j];
00121       }
00122       RetStrct.FaceNormList[ip] = d1[1]*d2[2] - d1[2]*d2[1];
00123       RetStrct.FaceNormList[ip+1] = d1[2]*d2[0] - d1[0]*d2[2];
00124       RetStrct.FaceNormList[ip+2] = d1[0]*d2[1] - d1[1]*d2[0];
00125       d = sqrt(RetStrct.FaceNormList[ip]*RetStrct.FaceNormList[ip]+RetStrct.FaceNormList[ip+1]*RetStrct.FaceNormList[ip+1]+RetStrct.FaceNormList[ip+2]*RetStrct.FaceNormList[ip+2]);
00126       if (d == 0.0) {
00127          /* I used to return here with a nasty message, but it seems that FreeSurfer surfaces contain such conditions 
00128          So, now I just set the normal to 1.0 in that case */
00129          /*SUMA_error_message (FuncName,"Zero length vector, returning",1);
00130          if (RetStrct.FaceNormList) SUMA_free(RetStrct.FaceNormList);
00131          if (RetStrct.NodeNormList) SUMA_free(RetStrct.NodeNormList);
00132          if (Index) SUMA_free(Index);
00133          if (N_Memb) SUMA_free(N_Memb);
00134          SUMA_RETURN (RetStrct);*/
00135          RetStrct.FaceNormList[ip] = 1.0;
00136          RetStrct.FaceNormList[ip+1] = 1.0;
00137          RetStrct.FaceNormList[ip+2] = 1.0;
00138          
00139       } else {
00140          RetStrct.FaceNormList[ip] /= d;
00141          RetStrct.FaceNormList[ip+1] /= d;
00142          RetStrct.FaceNormList[ip+2] /= d;
00143       }
00144       
00145       #if 0
00146          /* a test for the function SUMA_TriNorm */
00147          {
00148             float test_norm[3];
00149             SUMA_TriNorm (&(NodeList[(ND*FaceSetList[ip])]), &(NodeList[(ND*FaceSetList[ip+1])]), &(NodeList[(ND*FaceSetList[ip+2])]), test_norm);
00150             if (test_norm[0] != RetStrct.FaceNormList[ip] || test_norm[1] != RetStrct.FaceNormList[ip+1] || test_norm[2] != RetStrct.FaceNormList[ip+2]) {
00151                fprintf (SUMA_STDERR, "Error %s: Test of SUMA_TriNorm failed, difference in norms. Exiting.\n", FuncName);
00152                exit(1);
00153             } 
00154             fprintf (SUMA_STDERR,".");
00155          }
00156          
00157       #endif
00158       
00159          /*each node making up the FaceSet will get its normal vector updated*/
00160          if (FaceSetList[ip] > maxind || FaceSetList[ip+1] > maxind || FaceSetList[ip+2] > maxind) {
00161             SUMA_error_message (FuncName,"FaceSetList contains indices >= N_NodeList",1);
00162             if (RetStrct.FaceNormList) SUMA_free(RetStrct.FaceNormList);
00163             if (RetStrct.NodeNormList) SUMA_free(RetStrct.NodeNormList);
00164             if (Index) SUMA_free(Index);
00165             if (N_Memb) SUMA_free(N_Memb);
00166             SUMA_RETURN (RetStrct);
00167          }
00168 
00169          
00170          id2 = ND * FaceSetList[ip];
00171          RetStrct.NodeNormList[id2] += RetStrct.FaceNormList[ip];
00172          RetStrct.NodeNormList[id2+1] += RetStrct.FaceNormList[ip+1];
00173          RetStrct.NodeNormList[id2+2] += RetStrct.FaceNormList[ip+2];
00174          ++N_Memb[FaceSetList[ip]];
00175          id2 = ND * FaceSetList[ip+1];
00176          RetStrct.NodeNormList[id2] += RetStrct.FaceNormList[ip];
00177          RetStrct.NodeNormList[id2+1] += RetStrct.FaceNormList[ip+1];
00178          RetStrct.NodeNormList[id2+2] += RetStrct.FaceNormList[ip+2];
00179          ++N_Memb[FaceSetList[ip+1]];
00180          id2 = ND * FaceSetList[ip+2];
00181          RetStrct.NodeNormList[id2] += RetStrct.FaceNormList[ip];
00182          RetStrct.NodeNormList[id2+1] += RetStrct.FaceNormList[ip+1];
00183          RetStrct.NodeNormList[id2+2] += RetStrct.FaceNormList[ip+2];
00184          ++N_Memb[FaceSetList[ip+2]];
00185    }
00186       SUMA_LH("Normalizing");
00187       /*Now normalize NodeNormList*/
00188       NotMember = 0;
00189       for (i=0; i<N_NodeList; ++i)
00190          {
00191             id = ND * i;
00192             if (N_Memb[i])
00193             {
00194                /* fprintf(SUMA_STDERR,"%s: Node %d, Normal (pre scale) %f %f %f\n", FuncName, i, RetStrct.NodeNormList[id], RetStrct.NodeNormList[id+1], RetStrct.NodeNormList[id+2]); */
00195                RetStrct.NodeNormList[id] /= N_Memb[i];
00196                RetStrct.NodeNormList[id+1] /= N_Memb[i];
00197                RetStrct.NodeNormList[id+2] /= N_Memb[i];
00198                /* normalize */
00199                nrm = sqrt(RetStrct.NodeNormList[id]*RetStrct.NodeNormList[id] + RetStrct.NodeNormList[id+1]*RetStrct.NodeNormList[id+1] + RetStrct.NodeNormList[id+2]*RetStrct.NodeNormList[id+2]); 
00200                if (nrm) { /* at times nrm is 0. This happened once on a flat surface that was not consistently wound. Nodes that were 
00201                               members of two triangles of opposed normals ended up with a normal (and nrm) of 0 */ 
00202                   RetStrct.NodeNormList[id] /= nrm;
00203                   RetStrct.NodeNormList[id+1] /= nrm;
00204                   RetStrct.NodeNormList[id+2] /= nrm;
00205                } 
00206                
00207                /* fprintf(SUMA_STDERR,"%s: Node %d, N_Memb[i] = %d, nrm = %f\n", FuncName, i, N_Memb[i], nrm); */
00208             }
00209             else
00210             {
00211                ++NotMember;
00212                /*
00213                For some patches (Free Surfer's) such conditions are frequent, spitting out that message becomes old too quick */
00214                /*
00215                fprintf(stdout,"\n%s Warning: Node %d is not a member of any FaceSets, returning unit vector as normal.\n", FuncName, i); 
00216                */
00217                RetStrct.NodeNormList[id] = RetStrct.NodeNormList[id+1] = RetStrct.NodeNormList[id+2] = 1.0;
00218             }
00219          }
00220       if (NotMember) {
00221          sprintf (stmp, "(IGNORE for surface patches\n"
00222                         "%d nodes (%f%% of total) are\n"
00223                         "not members of any FaceSets.\n"
00224                         "Their normals are set to the\n"
00225                         "unit vector.\n", NotMember, (float)NotMember/(float)N_NodeList*100.0);
00226          SUMA_SL_Warn(stmp);
00227       }
00228       
00229    if (N_Memb) SUMA_free(N_Memb);
00230    if (Index) SUMA_free(Index);
00231    SUMA_RETURN (RetStrct);
00232 }/*SUMA_SurfNorm*/

Variable Documentation

SUMA_CommonFields* SUMAg_CF  
 

Global pointer to structure containing info common to all viewers

Definition at line 22 of file SUMA_SurfNorm.c.

 

Powered by Plone

This site conforms to the following standards: