Doxygen Source Code Documentation
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_SETS * | SUMA_MemberFaceSets (int Nind, int *FaceSetList, int nFr, int FaceDim, char *ownerid) |
| SUMA_Boolean | SUMA_Free_MemberFaceSets (SUMA_MEMBER_FACE_SETS *MF) |
Variables | |
| SUMA_CommonFields * | SUMAg_CF |
Function Documentation
|
|
||||||||||||||||||||||||
|
** File : SUMA_MemberFaceSets.c
Usage : RetStruct = SUMA_MemberFaceSets (int Nind, int * FaceSetList, int nFace, int FaceSetDim); Input paramters :
Support :
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*/
|
|
||||||||||||||||||||
|
** File : SUMA_SurfNorm.c
Usage : RetStrct = SUMA_SurfNorm (NodeList, N_NodeList, FaceSetList, N_FaceSetList ); Input paramters :
------------------- ## * 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
|
|
Global pointer to structure containing info common to all viewers Definition at line 22 of file SUMA_SurfNorm.c. |