Doxygen Source Code Documentation
SUMA_GeomComp.c File Reference
#include "SUMA_suma.h"Go to the source code of this file.
Data Structures | |
| struct | SUMA_AreaDiffDataStruct |
| struct | SUMA_VolDiffDataStruct |
Defines | |
| #define | DBG 1 |
| A function to calculate the geodesic distance of nodes connected to node n See labbook NIH-3 pp 138 and on for notes on algorithm. | |
| #define | DoCheck 1 |
| #define | SUMA_BEGINNING_OF_LAYER(list, LayInd, Elm) |
| #define | SUMA_FIND_ELMENT_FOR_NODE(list, n_jne, Elm) |
| #define | SUMA_MAX_BRANCHES 300 |
| SBv = SUMA_AssignTriBranch (SO, SPI, Nx, BranchCount, DoCopy). | |
| #define | NO_LOG |
| #define | LARGE_NUM 9e300 |
| Path = SUMA_Dijkstra (SO, Nx, Ny, isNodeInMesh, N_isNodeInMesh, Method_Number, Path_length, N_Path); Finds the shortest distance between nodes Nx and Ny on SO with a restriction on the number of nodes available for travel. In other terms, the search space is limited to a subset of the nodes forming SO. The subset of nodes is stored in isNodeInMesh. This subset is typically specified in SUMA_Surf_Plane_Intersect. | |
Functions | |
| int | SUMA_Subdivide_Mesh (float **NodeListp, int *N_Nodep, int **FaceSetListp, int *N_FaceSetp, float maxarea) |
| function to subdivide triangles to meet a maxarea criterion Divisions are done by adding a node at the centroid of the triangle to be subdivided. Bad idea, for very large triangles, such as produced by convex hull, you could end up with nodes that have hundreds of neighbors... | |
| SUMA_VTI * | SUMA_CreateVTI (int N_TriIndex, int *TriIndex) |
| Function to allocate and initialize a SUMA_VTI * structure. | |
| SUMA_VTI * | SUMA_FreeVTI (SUMA_VTI *vti) |
| SUMA_VTI * | SUMA_GetVoxelsIntersectingTriangle (SUMA_SurfaceObject *SO, SUMA_VOLPAR *VolPar, float *NodeIJKlist, SUMA_VTI *vti) |
| Function to return a set of voxels that are intersected by a triangle. | |
| int | SUMA_isSelfIntersect (SUMA_SurfaceObject *SO, int StopAt) |
| Function to detect surface self intersection returns -1 in case of error, 0 in case of no intersection 1 in case of intersection. | |
| int | SUMA_VoxelNeighbors (int ijk, int ni, int nj, int nk, SUMA_VOX_NEIGHB_TYPES ntype, int *nl) |
| find the neighbors to a voxel. | |
| byte * | SUMA_FillToVoxelMask (byte *ijkmask, int ijkseed, int ni, int nj, int nk, int *N_in, byte *usethisisin) |
| Function to fill the volume enclose in a mask. | |
| SUMA_Boolean | SUMA_VoxelsInBox (int *voxelsijk, int *N_in, float *c1, float *c2) |
| find voxels whose centers are inside the box with corners c1 and c2 c1, c2 are in voxel index coordinates. c1 is the minimum coordinates point. c2 is the maximum coordinates point. | |
| SUMA_Boolean | SUMA_ApplyAffine (float *NodeList, int N_Node, float M[][4], float *center) |
| Applies an affine transform the coordinates in NodeList. | |
| SUMA_Boolean | SUMA_getoffsets (int n, SUMA_SurfaceObject *SO, float *Off, float lim) |
| SUMA_GET_OFFSET_STRUCT * | SUMA_Initialize_getoffsets (int N_Node) |
| Allocate and initialize SUMA_GET_OFFSET_STRUCT* struct OffS = SUMA_Initialize_getoffsets (N_Node);. | |
| SUMA_Boolean | SUMA_AddNodeToLayer (int n, int LayInd, SUMA_GET_OFFSET_STRUCT *OffS) |
| Add node n to neighboring layer LayInd in OffS ans = SUMA_AddNodeToLayer (n, LayInd, OffS);. | |
| SUMA_GET_OFFSET_STRUCT * | SUMA_Free_getoffsets (SUMA_GET_OFFSET_STRUCT *OffS) |
| free memory associated with SUMA_GET_OFFSET_STRUCT * struct | |
| SUMA_Boolean | SUMA_Recycle_getoffsets (SUMA_GET_OFFSET_STRUCT *OffS) |
| reset the SUMA_GET_OFFSET_STRUCT after it has been used by a node | |
| float ** | SUMA_CalcNeighbDist (SUMA_SurfaceObject *SO) |
| calculates the length of the segments defined by a node and its first-order neighbors. The resulting matrix very closely resembles SO->FN->FirstNeighb DistFirstNeighb = SUMA_CalcNeighbDist (SO); | |
| SUMA_Boolean | SUMA_getoffsets2 (int n, SUMA_SurfaceObject *SO, float lim, SUMA_GET_OFFSET_STRUCT *OffS, int *CoverThisNode, int N_CoverThisNode) |
| A function to calculate the geodesic distance of nodes connected to node n SUMA_getoffsets was the first incarnation but it was too slow. ans = SUMA_getoffsets2 (n, SO, lim, OffS, CoverThisNode, N_CoverThisNode). | |
| void | SUMA_Free_Offset_ll_Datum (void *data) |
| SUMA_OFFSET_LL_DATUM * | SUMA_New_Offset_ll_Datum (int n, int layer) |
| DList * | SUMA_getoffsets_ll (int n, SUMA_SurfaceObject *SO, float lim, int *CoverThisNode, int N_CoverThisNode) |
| double | SUMA_NewAreaAtRadius (SUMA_SurfaceObject *SO, double r, double Rref, float *tmpList) |
| Changes the coordinates of SO's nodes so that the new average radius of the surface is equal to r. | |
| double | SUMA_NewVolumeAtRadius (SUMA_SurfaceObject *SO, double r, double Rref, float *tmpList) |
| Changes the coordinates of SO's nodes so that the new average radius of the surface is equal to r. | |
| double | SUMA_AreaDiff (double r, void *fvdata) |
| double | SUMA_VolDiff (double r, void *fvdata) |
| double | SUMA_BinaryZeroSearch (double a, double b, double(*f)(double x, void *data), void *fdata, int Nitermax, double tol) |
| Binary Zero Search, a function to find the zero of a function. | |
| SUMA_Boolean | SUMA_GetAreaDiffRange (SUMA_AreaDiffDataStruct *fdata, double *ap, double *bp) |
| a function to find two values a and b such that DA(a) is < 0 and DA(b) is > 0 These two starting points are used for the optimization function SUMA_BinaryZeroSearch | |
| SUMA_Boolean | SUMA_GetVolDiffRange (SUMA_VolDiffDataStruct *fdata, double *ap, double *bp) |
| a function to find two values a and b such that DV(a) is < 0 and DV(b) is > 0 These two starting points are used for the optimization function SUMA_BinaryZeroSearch | |
| SUMA_Boolean | SUMA_EquateSurfaceAreas (SUMA_SurfaceObject *SO, SUMA_SurfaceObject *SOref, float tol, SUMA_COMM_STRUCT *cs) |
| inflates or deflates a surface to make the area of one surface (SO) equal to the area of another (SOref) | |
| SUMA_Boolean | SUMA_EquateSurfaceVolumes (SUMA_SurfaceObject *SO, SUMA_SurfaceObject *SOref, float tol, SUMA_COMM_STRUCT *cs) |
| inflates or deflates a surface to make the volume of one surface (SO) equal to the volume of another (SOref) | |
| SUMA_Boolean | SUMA_ProjectSurfaceToSphere (SUMA_SurfaceObject *SO, SUMA_SurfaceObject *SOref,float radius, SUMA_COMM_STRUCT *cs) |
| stretch each node along the center--node direction such that the new distance is = radius | |
| SUMA_Boolean | SUMA_EquateSurfaceSize (SUMA_SurfaceObject *SO, SUMA_SurfaceObject *SOref, float max_off, SUMA_COMM_STRUCT *cs) |
| make the size of 2 surfaces match see help -match_size option in SurfSmooth | |
| float ** | SUMA_Chung_Smooth_Weights (SUMA_SurfaceObject *SO) |
| calculate the interpolation weights required to smooth data on the surface using M.K. Chung et al. Neuroimage 03 | |
| SUMA_Boolean | SUMA_Taubin_Smooth_TransferFunc (float l, float m, int N, FILE *Out) |
| Show the transfer function (f(k)) for the Taubin smoothing algorithm for a combination of scaling factors and number of iterations. | |
| SUMA_Boolean | SUMA_Taubin_Smooth_Coef (float k, float *l, float *m) |
| Calculates Mu(m) and Lambda(l) smoothing coefficients based on Taubin's smoothing algorithm in Geometric Signal Processing on Polygonal Meshes (Eurographics 2000). | |
| float * | SUMA_Taubin_Smooth (SUMA_SurfaceObject *SO, float **wgt, float lambda, float mu, float *fin_orig, int N_iter, int vpn, SUMA_INDEXING_ORDER d_order, float *fout_final_user, SUMA_COMM_STRUCT *cs, byte *nmask) |
| performs smoothing based on Taubin's smoothing algorithm in Geometric Signal Processing on Polygonal Meshes (Eurographics 2000) | |
| SUMA_Boolean | SUMA_GetOffset2Offset (SUMA_GET_OFFSET_STRUCT *GOS, SUMA_OFFSET_STRUCT *OS) |
| a function to turn the often cumbersome SUMA_GET_OFFSET_STRUCT to a more friendly SUMA_OFFSET_STRUCT | |
| char * | SUMA_ShowOffset_Info (SUMA_GET_OFFSET_STRUCT *OffS, int detail) |
| char * | SUMA_ShowOffset_ll_Info (DList *list, int detail) |
| SUMA_OFFSET_STRUCT * | SUMA_FormNeighbOffset (SUMA_SurfaceObject *SO, float OffsetLim) |
| creates a vector of node neighbors structures such that: OffS = SUMA_FormNeighbOffset ( SUMA_SurfaceObject *SO, float OffsetLim); | |
| SUMA_OFFSET_STRUCT * | SUMA_free_NeighbOffset (SUMA_SurfaceObject *SO, SUMA_OFFSET_STRUCT *OffS_out) |
| frees what is created by SUMA_FormNeighbOffset | |
| float * | SUMA_Offset_GeomSmooth (SUMA_SurfaceObject *SO, int N_iter, float OffsetLim, float *fin_orig, int vpn, SUMA_INDEXING_ORDER d_order, float *fout_final_user, SUMA_COMM_STRUCT *cs) |
| A filtering function that is based on brute force estimates of node neighbor distance matrix. It is not finished because it makes no use of the neighbor distances to properly weigh the interpolation. It ends up being too slow because of the high memory load for computing OffS_out. | |
| float * | SUMA_NN_GeomSmooth (SUMA_SurfaceObject *SO, int N_iter, float *fin_orig, int vpn, SUMA_INDEXING_ORDER d_order, float *fout_final_user, SUMA_COMM_STRUCT *cs) |
| float * | SUMA_Chung_Smooth (SUMA_SurfaceObject *SO, float **wgt, int N_iter, float FWHM, float *fin_orig, int vpn, SUMA_INDEXING_ORDER d_order, float *fout_final_user, SUMA_COMM_STRUCT *cs) |
| Filter data defined on the surface using M.K. Chung et al.'s method (Neuroimage 03) dm_smooth = SUMA_Chung_Smooth (SO, wgt, N_iter, FWHM, fin, vpn, d_order, fout_user, SUMA_COMM_STRUCT *cs);. | |
| int | SUMA_OrientTriangles (float *NodeList, int N_Node, int *FaceSetList, int N_FaceSet, int orient, int Force) |
| determine overall orientation of triangle normals and change triangle orientation if required | |
| SUMA_SurfaceObject * | SUMA_Patch2Surf (float *NodeList, int N_NodeList, int *PatchFaces, int N_PatchFaces, int PatchDim) |
| SUMA_Boolean * | SUMA_MaskOfNodesInPatch (SUMA_SurfaceObject *SO, int *N_NodesUsedInPatch) |
| a function to return a mask indicating if a node is part of a patch or not isNodeInPatch = SUMA_MaskOfNodesInPatch( SUMA_SurfaceObject *SO, int * N_NodesUsedInPatch); | |
| SUMA_PATCH * | SUMA_getPatch (int *NodesSelected, int N_Nodes, int *Full_FaceSetList, int N_Full_FaceSetList, SUMA_MEMBER_FACE_SETS *Memb, int MinHits) |
| SUMA_Boolean | SUMA_freePatch (SUMA_PATCH *Patch) |
| SUMA_Boolean | SUMA_ShowPatch (SUMA_PATCH *Patch, FILE *Out) |
| SUMA_CONTOUR_EDGES * | SUMA_GetContour (SUMA_SurfaceObject *SO, int *Nodes, int N_Node, int *N_ContEdges, int ContourMode, SUMA_PATCH *UseThisPatch) |
| Returns the contour of a patch if you have the patch already created, then pass it in the last argument mode (int) 0: nice contour, not necessarily outermost boundary 1: outermost edge, might look a tad jagged. | |
| double | SUMA_Pattie_Volume (SUMA_SurfaceObject *SO1, SUMA_SurfaceObject *SO2, int *Nodes, int N_Node, SUMA_SurfaceObject *UseThisSO, int minPatchHits) |
| Stitch together two isotopic patches to calculate the volume between them. | |
| double | SUMA_Mesh_Volume (SUMA_SurfaceObject *SO, int *FSI, int N_FaceSet) |
| Calculate the volume of a mesh per the method in Hughes, S.W. et al. Phys. Med. Biol. 1996. | |
| double | SUMA_Mesh_Area (SUMA_SurfaceObject *SO, int *FaceSets, int N_FaceSet) |
| computes the total area of a surface. NOTE: This function will replace whatever values you have in SO->PolyArea. If SO->PolyArea is NULL, it will remain that way. | |
| float * | SUMA_Plane_Equation (float *P1, float *P2, float *P3, float *usethisEq) |
| finds the plane passing through 3 points | |
| SUMA_SURF_PLANE_INTERSECT * | SUMA_Surf_Plane_Intersect (SUMA_SurfaceObject *SO, float *PlaneEq) |
| Determines the intersection of a plane and a surface. | |
| SUMA_ROI_DATUM * | SUMA_Surf_Plane_Intersect_ROI (SUMA_SurfaceObject *SO, int Nfrom, int Nto, float *P) |
| a wrapper function for SUMA_Surf_Plane_Intersect that returns the intersection in the form of an ROI datum | |
| SUMA_TRI_BRANCH * | SUMA_AssignTriBranch (SUMA_SurfaceObject *SO, SUMA_SURF_PLANE_INTERSECT *SPI, int Nx, int *BranchCount, SUMA_Boolean DoCopy) |
| SUMA_Boolean | SUMA_show_STB (SUMA_TRI_BRANCH *B, FILE *Out) |
| void | SUMA_free_STB (SUMA_TRI_BRANCH *Bv, int N_Bv) |
| SUMA_SURF_PLANE_INTERSECT * | SUMA_Allocate_SPI (SUMA_SurfaceObject *SO) |
| Allocates a structure for computing the intersection of a surface with a plane The allocation is done conservatively, expecting the worse case scenario. | |
| void | SUMA_free_SPI (SUMA_SURF_PLANE_INTERSECT *SPI) |
| SUMA_Boolean | SUMA_Show_SPI (SUMA_SURF_PLANE_INTERSECT *SPI, FILE *Out, SUMA_SurfaceObject *SO) |
| SUMA_Boolean | SUMA_Mark_Tri (SUMA_EDGE_LIST *EL, int E1, int iBranch, int *TriBranch, int *IsInter, int *N_IsInter, int *VisitationOrder, int *ivisit) |
| int | SUMA_Find_Edge_Nhost (SUMA_EDGE_LIST *EL, int *IsInter, int N_IsInter, int *i, int Nhost) |
| Finds an edge that has Nhost hosting triangles. Only the edges indexed in IsInter are examined. | |
| int * | SUMA_Dijkstra (SUMA_SurfaceObject *SO, int Nx, int Ny, SUMA_Boolean *isNodeInMesh, int *N_isNodeInMesh, int Method_Number, float *Lfinal, int *N_Path) |
| int * | SUMA_NodePath_to_EdgePath (SUMA_EDGE_LIST *EL, int *Path, int N_Path, int *N_Edge) |
| Converts a path formed by a series of connected nodes to a series of edges ePath = SUMA_NodePath_to_EdgePath (EL, Path, N_Path, N_Edge);. | |
| SUMA_Boolean | SUMA_isSameEdge (SUMA_EDGE_LIST *EL, int E1, int E2) |
| determines whether to edges are identical or not. Recall that an edge can be represented multiple times in SO->EL, once for each triangle that uses it. Two edges are the same if and only if EL->EL[E1][0] == EL->EL[E2][0] && EL->EL[E1][1] == EL->EL[E2][1] | |
| int * | SUMA_IntersectionStrip (SUMA_SurfaceObject *SO, SUMA_SURF_PLANE_INTERSECT *SPI, int *nPath, int N_nPath, float *dinters, float dmax, int *N_tPath) |
| This function determines the strip of triangles necessary to go from one node to another along intersected edges. tPath = SUMA_IntersectionStrip (SO, SPI, int *nPath, int N_nPath, float *dinters, float dmax, int *N_tPath). | |
| SUMA_Boolean | SUMA_FromIntEdgeToIntEdge (int Tri, int E1, int E2, SUMA_EDGE_LIST *EL, SUMA_SURF_PLANE_INTERSECT *SPI, int Ny, SUMA_Boolean *Visited, float *d, float dmax, int *tPath, int *N_tPath) |
| This function moves from one intersected edge to the next until a certain node is encountered or a a certain distance is exceeded. By intersected edge, I mean an edge of the surface's mesh that was intersected by a plane. | |
| int * | SUMA_NodePath_to_TriPath_Inters (SUMA_SurfaceObject *SO, SUMA_SURF_PLANE_INTERSECT *SPI, int *nPath, int N_nPath, int *N_tPath) |
| Converts a series of connected nodes into a series of connected triangles that were intersected by the plane. There is no guarantee that two nodes that belong to triangles intersected by the plane and part of the shortest path (as returned by SUMA_Dijkstra) for an edge that belongs to a triangle intersected by the plane. See labbook NIH-2 page 158 for sketches illustrating this point. So the strip of triangles that you will get back may have holes in it since it only allows intersected triangles to be members of the path. | |
| int * | SUMA_NodePath_to_TriPath_Inters_OLD (SUMA_SurfaceObject *SO, SUMA_TRI_BRANCH *Bv, int *Path, int N_Path, int *N_Tri) |
| Converts a series of connected nodes into a series of connected triangles that belong to a branch. The function fails at times, picking the long instead of the short path but it is left here in case I need it in the future. | |
Variables | |
| SUMA_CommonFields * | SUMAg_CF |
| SUMA_DO * | SUMAg_DOv |
| SUMA_SurfaceViewer * | SUMAg_SVv |
| int | SUMAg_N_SVv |
| int | SUMAg_N_DOv |
Define Documentation
|
|
A function to calculate the geodesic distance of nodes connected to node n See labbook NIH-3 pp 138 and on for notes on algorithm.
Definition at line 43 of file SUMA_GeomComp.c. |
|
|
Definition at line 44 of file SUMA_GeomComp.c. |
|
|
Path = SUMA_Dijkstra (SO, Nx, Ny, isNodeInMesh, N_isNodeInMesh, Method_Number, Path_length, N_Path); Finds the shortest distance between nodes Nx and Ny on SO with a restriction on the number of nodes available for travel. In other terms, the search space is limited to a subset of the nodes forming SO. The subset of nodes is stored in isNodeInMesh. This subset is typically specified in SUMA_Surf_Plane_Intersect. Path = SUMA_Dijkstra (SO, Nx, Ny, isNodeInMesh, N_isNodeInMesh, Method_Number, Path_length, N_Path)
Definition at line 6835 of file SUMA_GeomComp.c. Referenced by SUMA_Dijkstra(). |
|
|
Definition at line 6675 of file SUMA_GeomComp.c. |
|
|
Value: { \
SUMA_OFFSET_LL_DATUM * m_dat = NULL; \
DListElmt *m_Elm = NULL; \
do { \
if (m_Elm) m_Elm = m_Elm->next; \
else m_Elm = dlist_head(list); \
m_dat = (SUMA_OFFSET_LL_DATUM *)m_Elm->data; \
} while(m_dat->layer != LayInd && m_Elm != dlist_tail(list)); \
if (m_dat->layer != LayInd) Elm = NULL; \
else Elm = m_Elm; \
}Definition at line 1170 of file SUMA_GeomComp.c. Referenced by SUMA_getoffsets_ll(). |
|
|
Value: { \
SUMA_OFFSET_LL_DATUM * m_dat = NULL; \
DListElmt *m_Elm = NULL; \
do { \
if (m_Elm) m_Elm = m_Elm->next; \
else m_Elm = dlist_head(list); \
m_dat = (SUMA_OFFSET_LL_DATUM *)m_Elm->data; \
} while(m_dat->ni != n_jne && m_Elm != dlist_tail(list)); \
if (m_dat->ni != n_jne) Elm = NULL; \
else Elm = m_Elm; \
}Definition at line 1181 of file SUMA_GeomComp.c. Referenced by SUMA_getoffsets_ll(). |
|
|
SBv = SUMA_AssignTriBranch (SO, SPI, Nx, BranchCount, DoCopy).
Definition at line 6331 of file SUMA_GeomComp.c. Referenced by SUMA_AssignTriBranch(). |
Function Documentation
|
||||||||||||||||
|
Add node n to neighboring layer LayInd in OffS ans = SUMA_AddNodeToLayer (n, LayInd, OffS);.
Definition at line 818 of file SUMA_GeomComp.c. References SUMA_GET_OFFSET_STRUCT::layers, LocalHead, SUMA_NODE_NEIGHB_LAYER::N_AllocNodesInLayer, SUMA_GET_OFFSET_STRUCT::N_layers, SUMA_NODE_NEIGHB_LAYER::N_NodesInLayer, SUMA_NODE_NEIGHB_LAYER::NodesInLayer, SUMA_Boolean, SUMA_LH, SUMA_malloc, SUMA_realloc, SUMA_RETURN, and SUMA_SL_Err. Referenced by SUMA_getoffsets2().
00819 {
00820 static char FuncName[]={"SUMA_AddNodeToLayer"};
00821 static SUMA_Boolean LocalHead = NOPE;
00822
00823 /* is this a new layer */
00824 if (LayInd > OffS->N_layers) { /* error */
00825 SUMA_SL_Err("LayInd > OffS->N_layers. This should not be!");
00826 SUMA_RETURN(NOPE);
00827 } else if (LayInd == OffS->N_layers) { /* need a new one */
00828 SUMA_LH("Adding layer");
00829 OffS->N_layers += 1;
00830 OffS->layers = (SUMA_NODE_NEIGHB_LAYER *) SUMA_realloc(OffS->layers, OffS->N_layers*sizeof(SUMA_NODE_NEIGHB_LAYER));
00831 OffS->layers[LayInd].N_AllocNodesInLayer = 200;
00832 OffS->layers[LayInd].NodesInLayer = (int *) SUMA_malloc(OffS->layers[LayInd].N_AllocNodesInLayer * sizeof(int));
00833 OffS->layers[LayInd].N_NodesInLayer = 0;
00834 }
00835
00836 OffS->layers[LayInd].N_NodesInLayer += 1;
00837 /* do we need to reallocate for NodesInLayer ? */
00838 if (OffS->layers[LayInd].N_NodesInLayer == OffS->layers[LayInd].N_AllocNodesInLayer) { /* need more space */
00839 SUMA_LH("reallocating neighbors");
00840 OffS->layers[LayInd].N_AllocNodesInLayer += 200;
00841 OffS->layers[LayInd].NodesInLayer = (int *) SUMA_realloc (OffS->layers[LayInd].NodesInLayer, OffS->layers[LayInd].N_AllocNodesInLayer * sizeof(int));
00842 }
00843
00844 OffS->layers[LayInd].NodesInLayer[OffS->layers[LayInd].N_NodesInLayer - 1] = n;
00845
00846 SUMA_RETURN(YUP);
00847 }
|
|
|
Allocates a structure for computing the intersection of a surface with a plane The allocation is done conservatively, expecting the worse case scenario.
Definition at line 6584 of file SUMA_GeomComp.c. References SUMA_SurfaceObject::EL, i, SUMA_SURF_PLANE_INTERSECT::IntersEdges, SUMA_SURF_PLANE_INTERSECT::IntersNodes, SUMA_SURF_PLANE_INTERSECT::IntersTri, SUMA_SURF_PLANE_INTERSECT::isEdgeInters, SUMA_SURF_PLANE_INTERSECT::isNodeInMesh, SUMA_SURF_PLANE_INTERSECT::isTriHit, SUMA_EDGE_LIST::N_EL, SUMA_SurfaceObject::N_FaceSet, SUMA_SURF_PLANE_INTERSECT::N_IntersEdges, SUMA_SURF_PLANE_INTERSECT::N_IntersTri, SUMA_SurfaceObject::N_Node, SUMA_SURF_PLANE_INTERSECT::N_NodesInMesh, SUMA_Boolean, SUMA_calloc, SUMA_ENTRY, SUMA_malloc, and SUMA_RETURN. Referenced by SUMA_Surf_Plane_Intersect().
06585 {
06586 static char FuncName[]={"SUMA_Allocate_SPI"};
06587 int i;
06588 SUMA_SURF_PLANE_INTERSECT *SPI = NULL;
06589
06590 SUMA_ENTRY;
06591
06592 SPI = (SUMA_SURF_PLANE_INTERSECT *) SUMA_malloc(sizeof(SUMA_SURF_PLANE_INTERSECT));
06593 if (!SPI) {
06594 fprintf (SUMA_STDERR, "Error %s: Could not allocate for SPI\n", FuncName);
06595 SUMA_RETURN (SPI);
06596 }
06597
06598 SPI->IntersEdges = (int *) SUMA_calloc (SO->EL->N_EL, sizeof(int)); /* allocate for the max imaginable*/
06599 SPI->IntersNodes = (float *) SUMA_calloc (3 * SO->EL->N_EL, sizeof(float));
06600 SPI->isEdgeInters = (SUMA_Boolean *) SUMA_calloc (SO->EL->N_EL, sizeof(SUMA_Boolean));
06601 SPI->IntersTri = (int *) SUMA_calloc (SO->N_FaceSet, sizeof(int));
06602 SPI->isNodeInMesh = (SUMA_Boolean *) SUMA_calloc (SO->N_Node, sizeof(SUMA_Boolean));
06603 SPI->isTriHit = (SUMA_Boolean *) SUMA_calloc (SO->N_FaceSet, sizeof(SUMA_Boolean));
06604
06605 if (!SPI->IntersEdges || !SPI->IntersTri || !SPI->IntersNodes || !SPI->isTriHit || !SPI->isEdgeInters)
06606 {
06607 fprintf (SUMA_STDERR, "Error %s: Could not allocate \n", FuncName);
06608 SUMA_RETURN (SPI);
06609 }
06610
06611 SPI->N_IntersEdges = 0;
06612 SPI->N_IntersTri = 0;
06613 SPI->N_NodesInMesh = 0;
06614 SUMA_RETURN (SPI);
06615 }
|
|
||||||||||||||||||||
|
Applies an affine transform the coordinates in NodeList.
Definition at line 623 of file SUMA_GeomComp.c. References i, LocalHead, SUMA_allocate2D(), SUMA_Boolean, SUMA_ENTRY, SUMA_free2D(), SUMA_LH, SUMA_MULT_MAT, SUMA_RETURN, and SUMA_SL_Err.
00624 {
00625 static char FuncName[] = {"SUMA_ApplyAffine"};
00626 float **XYZo, **Mr, **XYZn, D[3];
00627 int i, i3, idbg = 0;
00628 SUMA_Boolean LocalHead = NOPE;
00629
00630 SUMA_ENTRY;
00631
00632 if (!NodeList || N_Node <=0) {
00633 SUMA_SL_Err("Bad Entries.\n");
00634 SUMA_RETURN(NOPE);
00635 }
00636
00637 Mr = (float **)SUMA_allocate2D(3, 3, sizeof(float));
00638 XYZn = (float **)SUMA_allocate2D(3, 1, sizeof(float));
00639 XYZo = (float **)SUMA_allocate2D(3, 1, sizeof(float));
00640
00641 SUMA_LH("Forming Mr");
00642 Mr[0][0] = M[0][0]; Mr[0][1] = M[0][1]; Mr[0][2] = M[0][2];
00643 Mr[1][0] = M[1][0]; Mr[1][1] = M[1][1]; Mr[1][2] = M[1][2];
00644 Mr[2][0] = M[2][0]; Mr[2][1] = M[2][1]; Mr[2][2] = M[2][2];
00645 D[0] = M[0][3]; D[1] = M[1][3]; D[2] = M[2][3];
00646
00647 SUMA_LH("Transforming");
00648 if (LocalHead ) {
00649 i3 = 3*idbg;
00650 fprintf (SUMA_STDERR,"In: %f %f %f\n", NodeList[i3], NodeList[i3+1], NodeList[i3+2]);
00651 }
00652 for (i=0; i< N_Node; ++i) {
00653 i3 = 3 * i;
00654 if (!center) {
00655 XYZo[0][0] = NodeList[i3]; XYZo[1][0] = NodeList[i3+1]; XYZo[2][0] = NodeList[i3+2];
00656 } else {
00657 XYZo[0][0] = NodeList[i3] - center[0]; XYZo[1][0] = NodeList[i3+1] - center[1]; XYZo[2][0] = NodeList[i3+2] - center[2];
00658 }
00659
00660 SUMA_MULT_MAT(Mr, XYZo, XYZn, 3, 3, 1, float,float,float);
00661
00662 if (!center) {
00663 NodeList[i3] = XYZn[0][0]+D[0]; NodeList[i3+1] = XYZn[1][0]+D[1]; NodeList[i3+2] = XYZn[2][0]+D[2];
00664 } else {
00665 NodeList[i3] = XYZn[0][0]+D[0] + center[0]; NodeList[i3+1] = XYZn[1][0]+D[1]+ center[1]; NodeList[i3+2] = XYZn[2][0]+D[2]+ center[2];
00666 }
00667
00668 }
00669 if (LocalHead ) {
00670 i3 = 3*idbg;
00671 fprintf (SUMA_STDERR,"Out: %f %f %f\n", NodeList[i3], NodeList[i3+1], NodeList[i3+2]);
00672 }
00673 SUMA_LH("Done");
00674
00675 SUMA_free2D((char**)Mr, 3);
00676 SUMA_free2D((char**)XYZn, 3);
00677 SUMA_free2D((char**)XYZo, 3);
00678
00679 SUMA_RETURN(YUP);
00680 }
|
|
||||||||||||
|
Definition at line 1433 of file SUMA_GeomComp.c. References SUMA_AreaDiffDataStruct::Aref, SUMA_AreaDiffDataStruct::cs, i, LocalHead, SUMA_SurfaceObject::NodeList, r, SUMA_AreaDiffDataStruct::Rref, SUMA_COMM_STRUCT::Send, SUMA_AreaDiffDataStruct::SO, SUMA_AreaDiffDataStruct::SOref, SUMA_Boolean, SUMA_ENTRY, SUMA_LH, SUMA_NewAreaAtRadius(), SUMA_NODE_XYZ, SUMA_RETURN, SUMA_SendToSuma(), SUMA_SL_Warn, and SUMA_AreaDiffDataStruct::tmpList. Referenced by SUMA_EquateSurfaceAreas().
01434 {
01435 static char FuncName[]={"SUMA_AreaDiff"};
01436 double da, *fp, Dr, A;
01437 static int ncall=0;
01438 int i;
01439 static double Rref = 0.0, Aref = 0.0;
01440 SUMA_SurfaceObject *SO, *SOref;
01441 SUMA_COMM_STRUCT *cs=NULL;
01442 SUMA_AreaDiffDataStruct *fdata = (SUMA_AreaDiffDataStruct*)fvdata ;
01443 SUMA_Boolean LocalHead = NOPE;
01444
01445 SUMA_ENTRY;
01446
01447 if (!fdata) {
01448 SUMA_LH("Reset");
01449 Rref = 0.0; Aref = 0.0;
01450 ncall = 0;
01451 SUMA_RETURN(0.0);
01452 }
01453
01454 SO = fdata->SO;
01455 SOref = fdata->SOref;
01456 cs = fdata->cs;
01457
01458 if (!ncall) {
01459 SUMA_LH("Initializing, calculating Aref and Rref");
01460 Aref = fdata->Aref;
01461 Rref = fdata->Rref;
01462 if (LocalHead) { fprintf(SUMA_STDERR,"%s: Reference volume = %f, radius = %f \n", FuncName, Aref, Rref); }
01463 if (cs->Send) { /* send the first monster (it's SOref "in SUMA" that's being modified on the fly) */
01464 if (!SUMA_SendToSuma (SOref, cs, (void *)SO->NodeList, SUMA_NODE_XYZ, 1)) {
01465 SUMA_SL_Warn("Failed in SUMA_SendToSuma\nCommunication halted.");
01466 }
01467 }
01468 }
01469
01470 A = SUMA_NewAreaAtRadius(SO, r, Rref, fdata->tmpList);
01471 da = Aref - A; /* the area difference */
01472 if (LocalHead) {
01473 fprintf(SUMA_STDERR,"%s: Call %d, A = %f, Aref = %f, da = %f\n", FuncName,ncall, A, Aref, da);
01474 }
01475
01476 /* need an update ? */
01477 if (cs->Send) { /* send the update (it's SOref "in SUMA" that's being modified on the fly) */
01478 if (!SUMA_SendToSuma (SOref, cs, (void *)fdata->tmpList, SUMA_NODE_XYZ, 1)) {
01479 SUMA_SL_Warn("Failed in SUMA_SendToSuma\nCommunication halted.");
01480 }
01481 }
01482
01483 ++ncall;
01484
01485 SUMA_RETURN(da);
01486 }
|
|
||||||||||||||||||||||||
|
Definition at line 6334 of file SUMA_GeomComp.c. References SUMA_SurfaceObject::EL, SUMA_EDGE_LIST::EL, SUMA_EDGE_LIST::ELps, i, SUMA_TRI_BRANCH::iBranch, SUMA_SURF_PLANE_INTERSECT::IntersEdges, SUMA_TRI_BRANCH::list, LocalHead, SUMA_EDGE_LIST::N_EL, SUMA_SurfaceObject::N_FaceSet, SUMA_SURF_PLANE_INTERSECT::N_IntersEdges, SUMA_SURF_PLANE_INTERSECT::N_IntersTri, SUMA_TRI_BRANCH::N_list, Nx, SUMA_Boolean, SUMA_calloc, SUMA_disp_dvect(), SUMA_ENTRY, SUMA_Find_Edge_Nhost(), SUMA_free, SUMA_malloc, SUMA_Mark_Tri(), SUMA_MAX_BRANCHES, and SUMA_RETURN.
06336 {
06337 static char FuncName[]={"SUMA_AssignTriBranch"};
06338 int *IntersEdgesCopy = NULL, N_IntersEdgesCopy, i_Branch, E1, kedge, i,
06339 N_iBranch[SUMA_MAX_BRANCHES], NBlist[SUMA_MAX_BRANCHES], iBranch = 0,
06340 N_Branch, Bcnt, ilist, j, ivisit, *VisitationOrder, TriCheck;
06341 SUMA_Boolean Local_IntersEdgesCopy = NOPE;
06342 int *TriBranch = NULL; /*!< Vector of SO->EL->N_EL / 3 elements but with only N_IntersTri meaningful values. If TriBranch[j] = b
06343 then triangle j in SO->FaceSet is a member of Branch b. Branch numbering starts at 1 and may not be consecutive.
06344 A branch is a collection of connected triangles and may form a closed loop */
06345 SUMA_TRI_BRANCH *Bv = NULL;
06346 SUMA_Boolean LocalHead = NOPE;
06347
06348 SUMA_ENTRY;
06349
06350
06351 i_Branch = 0;
06352
06353 /* make a copy of SPI->N_IntersEdges since this vector will be modified and might be needed later,
06354 might make that optional later and just copy pointers if IntersEdgesCopy is not needed elsewhere.
06355 IntersEdgesCopy flag is used to decide on freeing IntersEdgesCopy or not.*/
06356
06357 VisitationOrder = (int *)SUMA_calloc (SO->N_FaceSet, sizeof (int)); /* keeps track of the order in which triangles are visited. This is used for creating branches with the proper sequence */
06358 TriBranch = (int *)SUMA_calloc (SO->EL->N_EL / 3, sizeof(int));
06359
06360 if (!VisitationOrder || !TriBranch) {
06361 fprintf (SUMA_STDERR, "Error %s: Failed to allocate.\n", FuncName);
06362 if (TriBranch) SUMA_free(TriBranch);
06363 if (VisitationOrder) SUMA_free(VisitationOrder);
06364 SUMA_RETURN (NULL);
06365 }
06366
06367 N_IntersEdgesCopy = SPI->N_IntersEdges;
06368 if (DoCopy) {
06369 IntersEdgesCopy = (int *) SUMA_calloc (N_IntersEdgesCopy, sizeof (int));
06370 Local_IntersEdgesCopy = YUP;
06371 for (i=0; i < N_IntersEdgesCopy; ++i) {
06372 IntersEdgesCopy[i] = SPI->IntersEdges[i];
06373 }
06374 }else {
06375 Local_IntersEdgesCopy = NOPE;
06376 IntersEdgesCopy = SPI->IntersEdges;
06377 }
06378
06379 if (!IntersEdgesCopy) {
06380 fprintf (SUMA_STDERR, "Error %s: Failed to allocate for or receive IntersEdgesCopy.\n", FuncName);
06381 if (TriBranch) SUMA_free(TriBranch);
06382 if (VisitationOrder) SUMA_free(VisitationOrder);
06383 SUMA_RETURN (NULL);
06384 }
06385
06386 ivisit = 0;
06387 while (N_IntersEdgesCopy) {
06388
06389 if (!i_Branch && Nx >= 0) {
06390 /* start from edge containing Nx, this is only done at the starting point (i_Branch = 0) */
06391 E1 = -1;
06392 i=0;
06393 while (i < N_IntersEdgesCopy && E1 < 0) {
06394 if ( (SO->EL->EL[IntersEdgesCopy[i]][0] == Nx) || (SO->EL->EL[IntersEdgesCopy[i]][1] == Nx) ) {
06395 E1 = IntersEdgesCopy[i];
06396 kedge = i;
06397 }
06398 ++i;
06399 }
06400 }else {
06401 /* no starting orders, start from any decent edge */
06402 /* find an edge with one hosting triangle */
06403 E1 = SUMA_Find_Edge_Nhost (SO->EL, IntersEdgesCopy, N_IntersEdgesCopy, &kedge, 1);
06404 }
06405
06406 if (E1 < 0) { /* no such edge found, take first edge in InInter */
06407 kedge = 0;
06408 E1 = IntersEdgesCopy[kedge];
06409 if (LocalHead) fprintf (SUMA_STDERR, "%s: No 1 host edge edge found.\n", FuncName);
06410 }else {
06411 if (LocalHead) fprintf (SUMA_STDERR, "%s: Found edge.\n", FuncName);
06412 }
06413
06414 /* remove this edge from the list */
06415 --(N_IntersEdgesCopy);
06416 if (LocalHead) fprintf (SUMA_STDERR, "%s: kedge = %d, N_IntersEdgesCopy = %d.\n", FuncName, kedge, N_IntersEdgesCopy);
06417 IntersEdgesCopy[kedge] = IntersEdgesCopy[N_IntersEdgesCopy];
06418
06419 /* start a new i_Branch - All i_Branch indices must be > 0*/
06420 ++i_Branch;
06421 if (i_Branch > SUMA_MAX_BRANCHES-1) {
06422 fprintf (SUMA_STDERR, "Error %s: No more than %d branches allowed.\n", FuncName, SUMA_MAX_BRANCHES);
06423 SUMA_RETURN (NULL);
06424 }
06425
06426 /* mark the triangle containing E1 */
06427 if (LocalHead) fprintf (SUMA_STDERR, "%s: Marking triangle %d with branch %d.\n", FuncName, SO->EL->ELps[E1][1], i_Branch);
06428 TriBranch[SO->EL->ELps[E1][1]] = i_Branch;
06429 VisitationOrder[ivisit] = SO->EL->ELps[E1][1]; ++ivisit;
06430
06431 if (LocalHead) fprintf (SUMA_STDERR, "%s: Called recursive SUMA_Mark_Tri.\n", FuncName);
06432 if (!SUMA_Mark_Tri (SO->EL, E1, i_Branch, TriBranch, IntersEdgesCopy, &(N_IntersEdgesCopy), VisitationOrder, &ivisit)) {
06433 fprintf (SUMA_STDERR, "Error %s: Failed in SUMA_Mark_Tri.\n", FuncName);
06434 }
06435 if (LocalHead) fprintf (SUMA_STDERR, "%s: Returned from recursive SUMA_Mark_Tri.\n", FuncName);
06436
06437 /* repeat till all edges are used up */
06438 }
06439
06440 if (Local_IntersEdgesCopy) {
06441 if (LocalHead) fprintf (SUMA_STDERR, "%s: freeing IntersEdgesCopy.\n", FuncName);
06442 SUMA_free(IntersEdgesCopy);
06443 }else {
06444 /* also change N_IntersEdges */
06445 SPI->N_IntersEdges = N_IntersEdgesCopy;
06446 }
06447
06448 /* SUMA_disp_dvect (TriBranch, SO->N_FaceSet); */
06449
06450 N_Branch = i_Branch;
06451
06452 /* determine the number of branch elements to allocate for - IDIOT PROOF, doing it in the recursive function SUMA_Mark_Tri was annoying*/
06453 for (i=0; i <= N_Branch; ++i) N_iBranch[i] = 0; /* remember, Branch numbering starts at 1 */
06454 if (LocalHead) fprintf (SUMA_STDERR, "%s: Searching all %d intersected triangles.\n", FuncName, SPI->N_IntersTri);
06455 Bcnt = 0;
06456 for (i=0; i < SO->N_FaceSet; ++i) {
06457 if (TriBranch[i]) {
06458 /* fprintf (SUMA_STDERR, "%d:%d\t", TriBranch[i], N_iBranch[TriBranch[i]]); */
06459 ++Bcnt;
06460 N_iBranch[TriBranch[i]] = N_iBranch[TriBranch[i]] + 1;
06461 }
06462 }
06463
06464 #if 0
06465 fprintf (SUMA_STDERR, "Values in N_iBranch, idiot proof:\n");
06466 SUMA_disp_dvect (N_iBranch, N_Branch+1);
06467 fprintf (SUMA_STDERR, "\n");
06468 #endif
06469
06470 if (LocalHead) fprintf (SUMA_STDERR, "%s: Found %d triangles belonging to a branch out of %d intersected triangles.\n", FuncName, Bcnt, SPI->N_IntersTri);
06471
06472 /* Now you want to create a vector of N_Branches to represent the intersection */
06473 Bv = (SUMA_TRI_BRANCH *) SUMA_malloc (sizeof(SUMA_TRI_BRANCH)*(N_Branch+1)); /* you should only need N_Branch, but that 1 won't hurt ...*/
06474 if (!Bv) {
06475 fprintf (SUMA_STDERR, "Error %s: Could not allocate for Bv.\n", FuncName);
06476 SUMA_RETURN (NULL);
06477 }
06478
06479 /* initialize allocated Bv elements */
06480 for (i=0; i<= N_Branch; ++i) { /* You have allocated for N_Branch+1*/
06481 Bv[i].list = NULL;
06482 Bv[i].N_list = 0;
06483 }
06484
06485 Bcnt = 0;
06486 for (i=0; i<= N_Branch; ++i) { /* Branch numbering starts at 1 */
06487 if (N_iBranch[i]) {
06488 /* something in that branch, allocate and initialize*/
06489 if (LocalHead) fprintf (SUMA_STDERR, "%s: Allocating for %d elements, Old Branch %d, New Branch %d.\n", FuncName, N_iBranch[i], i, Bcnt);
06490 Bv[Bcnt].list = (int *) SUMA_calloc (N_iBranch[i]+1, sizeof(int));
06491 Bv[Bcnt].N_list = N_iBranch[i];
06492 Bv[Bcnt].iBranch = Bcnt;
06493 NBlist[i] = Bcnt; /* store new indexing for Branches */
06494 ++Bcnt;
06495 }
06496
06497 }
06498
06499 /* store the total number of used branches */
06500 *BranchCount = Bcnt;
06501
06502 /* now fill up the branches*/
06503 if (LocalHead) fprintf (SUMA_STDERR, "%s: Filling up branches...\n", FuncName);
06504 for (i=0; i <= N_Branch; ++i) N_iBranch[i] = 0; /* now use this vector as a counter for the filling at each new branch index */
06505 for (i=0; i < SPI->N_IntersTri; ++i) { /* only go over visited triangles */
06506 TriCheck = TriBranch[VisitationOrder[i]]; /* returns the branch number of triangle VisitationOrder[i] */
06507 if (TriCheck) {
06508 Bcnt = NBlist[TriCheck]; /* get the new branch number from the original (old) branch number */
06509 #if 0
06510 fprintf (SUMA_STDERR,"%s: Tricheck = %d\n", FuncName, TriCheck); */
06511 if (Bcnt >= *BranchCount) {
06512 fprintf (SUMA_STDERR, "\aError %s: BranchCount = %d <= Bcnt = %d.\n", FuncName, *BranchCount, Bcnt);
06513 }
06514 if (N_iBranch[Bcnt] >= Bv[Bcnt].N_list) {
06515 fprintf (SUMA_STDERR, "\aError %s: Bcnt = %d. N_iBranch[Bcnt] = %d >= Bv[Bcnt].N_list = %d\n", FuncName, Bcnt, N_iBranch[Bcnt], Bv[Bcnt].N_list);
06516 }
06517 #endif
06518 Bv[Bcnt].list[N_iBranch[Bcnt]] = VisitationOrder[i]; /* store the index of the visited triangle in that branch */
06519 N_iBranch[Bcnt] += 1; /* store the number of elements in that branch */
06520 }
06521 }
06522
06523 if (LocalHead) fprintf (SUMA_STDERR, "%s: freeing ...\n", FuncName);
06524 if (VisitationOrder) SUMA_free(VisitationOrder);
06525 if (TriBranch) SUMA_free(TriBranch);
06526 SUMA_RETURN (Bv);
06527 }
|
|
||||||||||||||||||||||||||||
|
Binary Zero Search, a function to find the zero of a function.
Definition at line 1548 of file SUMA_GeomComp.c. References a, LocalHead, SUMA_Boolean, SUMA_ENTRY, SUMA_RETURN, and SUMA_SL_Warn. Referenced by SUMA_EquateSurfaceAreas(), and SUMA_EquateSurfaceVolumes().
01548 {
01549 static char FuncName[]={"SUMA_BinaryZeroSearch"};
01550 int Niter;
01551 double x, fx;
01552 SUMA_Boolean done;
01553 SUMA_Boolean LocalHead = NOPE;
01554
01555 SUMA_ENTRY;
01556
01557 if (Nitermax < 0) Nitermax = 1000;
01558
01559 x = 0.0;
01560 Niter = 0;
01561 done = NOPE;
01562 while(!done && Niter < Nitermax) {
01563 x = (a+b)/2.0;
01564 fx = (*f)(x, fdata);
01565 if (LocalHead) fprintf(SUMA_STDERR,"%s: %d\ta=%.4f\tb=%.4f\tx=%.4f\tfx=%.4f\n",
01566 FuncName, Niter, a, b, x, fx);
01567 if (fx < 0) a = x;
01568 else b = x;
01569 if (fabs(fx) < tol) done = YUP;
01570 ++Niter;
01571 }
01572
01573 if (!done) {
01574 SUMA_SL_Warn( "Reached iteration limit\n"
01575 "without converging.\n");
01576 }
01577
01578 SUMA_RETURN(x);
01579 }
|
|
|
calculates the length of the segments defined by a node and its first-order neighbors. The resulting matrix very closely resembles SO->FN->FirstNeighb DistFirstNeighb = SUMA_CalcNeighbDist (SO);
"); exit(1); } { int n1, n2, iseg; n1 = 5; n2 = SO->FN->FirstNeighb[n1][2]; iseg = SUMA_FindEdge(SO->EL, n1, n2); fprintf(SUMA_STDERR, "s: Distance between nodes d and d: " "from DistFirstNeighb = f " "from SO->EL->Le = f ", FuncName, n1, n2, DistFirstNeighb[n1][2], SO->EL->Le[iseg]); exit(1); } endif Definition at line 945 of file SUMA_GeomComp.c. References a, SUMA_NODE_FIRST_NEIGHB::FirstNeighb, SUMA_SurfaceObject::FN, i, LocalHead, SUMA_NODE_FIRST_NEIGHB::N_Neighb, SUMA_NODE_FIRST_NEIGHB::N_Neighb_max, SUMA_NODE_FIRST_NEIGHB::N_Node, SUMA_NODE_FIRST_NEIGHB::NodeId, SUMA_SurfaceObject::NodeList, SUMA_allocate2D(), SUMA_Boolean, SUMA_ENTRY, SUMA_RETURN, SUMA_SEG_LENGTH, and SUMA_SL_Crit.
00946 {
00947 static char FuncName[]={"SUMA_CalcNeighbDist"};
00948 float **DistFirstNeighb=NULL, *a, *b;
00949 int i, j;
00950 static SUMA_Boolean LocalHead = NOPE;
00951
00952 SUMA_ENTRY;
00953
00954 if (!SO) { SUMA_RETURN(NULL); }
00955 if (!SO->FN) { SUMA_RETURN(NULL); }
00956
00957 DistFirstNeighb = (float **)SUMA_allocate2D(SO->FN->N_Node, SO->FN->N_Neighb_max, sizeof(float));
00958 if (!DistFirstNeighb) {
00959 SUMA_SL_Crit("Failed to allocate for DistFirstNeighb");
00960 SUMA_RETURN(NULL);
00961 }
00962 for (i=0; i < SO->FN->N_Node; ++i) {
00963 a = &(SO->NodeList[3*SO->FN->NodeId[i]]);
00964 for (j=0; j < SO->FN->N_Neighb[i]; ++j) {
00965 b = &(SO->NodeList[3*SO->FN->FirstNeighb[i][j]]);
00966 SUMA_SEG_LENGTH(a, b, DistFirstNeighb[i][j]);
00967 if (SO->FN->NodeId[i] == 5 && SO->FN->FirstNeighb[i][j] == 133092) {
00968 fprintf (SUMA_STDERR, "%f %f %f\n%f %f %f\n%f\n",
00969 SO->NodeList[3*SO->FN->NodeId[i]], SO->NodeList[3*SO->FN->NodeId[i]+1], SO->NodeList[3*SO->FN->NodeId[i]+2],
00970 SO->NodeList[3*SO->FN->FirstNeighb[i][j]], SO->NodeList[3*SO->FN->FirstNeighb[i][j]+1],
00971 SO->NodeList[3*SO->FN->FirstNeighb[i][j]+2], DistFirstNeighb[i][j]);
00972 }
00973 }
00974 }
00975
00976 SUMA_RETURN (DistFirstNeighb);
00977 }
|
|
||||||||||||||||||||||||||||||||||||||||
|
Filter data defined on the surface using M.K. Chung et al.'s method (Neuroimage 03) dm_smooth = SUMA_Chung_Smooth (SO, wgt, N_iter, FWHM, fin, vpn, d_order, fout_user, SUMA_COMM_STRUCT *cs);.
Definition at line 3068 of file SUMA_GeomComp.c. References SUMA_NODE_FIRST_NEIGHB::FirstNeighb, SUMA_SurfaceObject::FN, fout, LocalHead, SUMA_NODE_FIRST_NEIGHB::N_Neighb, SUMA_SurfaceObject::N_Node, SUMA_COMM_STRUCT::Send, SUMA_Boolean, SUMA_calloc, SUMA_COLUMN_MAJOR, SUMA_ENTRY, SUMA_free, SUMA_INDEXING_ORDER, SUMA_NODE_RGBAb, SUMA_RETURN, SUMA_ROW_MAJOR, SUMA_SendToSuma(), SUMA_SL_Crit, SUMA_SL_Err, SUMA_SL_Warn, and vpn. Referenced by SUMA_Reposition_Touchup().
03072 {
03073 static char FuncName[]={"SUMA_Chung_Smooth"};
03074 float *fout_final = NULL, *fbuf=NULL, *fin=NULL, *fout=NULL, *fin_next = NULL;
03075 float delta_time, fp, dfp, fpj, minfn=0.0, maxfn=0.0;
03076 int n , k, j, niter, vnk, os;
03077 SUMA_Boolean LocalHead = NOPE;
03078
03079 SUMA_ENTRY;
03080
03081 if (N_iter % 2) {
03082 SUMA_SL_Err("N_iter must be an even number\n");
03083 SUMA_RETURN(NULL);
03084 }
03085
03086 if (!SO || !wgt || !fin_orig) {
03087 SUMA_SL_Err("NULL SO or wgt or fin_orig\n");
03088 SUMA_RETURN(NULL);
03089 }
03090 if (!SO->FN) {
03091 SUMA_SL_Err("NULL SO->FN\n");
03092 SUMA_RETURN(NULL);
03093 }
03094
03095 if (vpn < 1) {
03096 SUMA_SL_Err("vpn < 1\n");
03097 SUMA_RETURN(NULL);
03098 }
03099
03100 if (fout_final_user == fin_orig) {
03101 SUMA_SL_Err("fout_final_user == fin_orig");
03102 SUMA_RETURN(NULL);
03103 }
03104
03105 if (!fout_final_user) { /* allocate for output */
03106 fout_final = (float *)SUMA_calloc(SO->N_Node * vpn, sizeof(float));
03107 if (!fout_final) {
03108 SUMA_SL_Crit("Failed to allocate for fout_final\n");
03109 SUMA_RETURN(NULL);
03110 }
03111 }else {
03112 fout_final = fout_final_user; /* pre-allocated */
03113 }
03114
03115 /* allocate for buffer */
03116 fbuf = (float *)SUMA_calloc(SO->N_Node * vpn, sizeof(float));
03117 if (!fbuf) {
03118 SUMA_SL_Crit("Failed to allocate for fbuf\n");
03119 SUMA_RETURN(NULL);
03120 }
03121
03122
03123 if (cs->Send) { /* send the first monster */
03124 if (!SUMA_SendToSuma (SO, cs, (void *)fin_orig, SUMA_NODE_RGBAb, 1)) {
03125 SUMA_SL_Warn("Failed in SUMA_SendToSuma\nCommunication halted.");
03126 }
03127 }
03128
03129 fin_next = fin_orig;
03130 delta_time= (FWHM * FWHM)/(16*N_iter*log(2));
03131 switch (d_order) {
03132 case SUMA_COLUMN_MAJOR:
03133 for (niter=0; niter < N_iter; ++niter) {
03134 if ( niter % 2 ) { /* odd */
03135 fin = fin_next; /* input from previous output buffer */
03136 fout = fout_final; /* results go into final vector */
03137 fin_next = fout_final; /* in the next iteration, the input is from fout_final */
03138 } else { /* even */
03139 /* input data is in fin_new */
03140 fin = fin_next;
03141 fout = fbuf; /* results go into buffer */
03142 fin_next = fbuf; /* in the next iteration, the input is from the buffer */
03143 }
03144 for (k=0; k < vpn; ++k) {
03145 os = SO->N_Node*k; /* node value indexing offset */
03146 for (n=0; n < SO->N_Node; ++n) {
03147 vnk = n+os; /* index of kth value at node n */
03148 fp = fin[vnk]; /* kth value at node n */
03149 dfp = 0.0;
03150 if (SO->FN->N_Neighb[n]) minfn = maxfn = fin[SO->FN->FirstNeighb[n][0]+os];
03151 for (j=0; j < SO->FN->N_Neighb[n]; ++j) {
03152 fpj = fin[SO->FN->FirstNeighb[n][j]+os]; /* value at jth neighbor of n */
03153 if (fpj < minfn) minfn = fpj;
03154 if (fpj > maxfn) maxfn = fpj;
03155 dfp += wgt[n][j] * (fpj - fp);
03156 }/* for j*/
03157 fout[vnk] = fin[vnk] + delta_time * dfp;
03158 if (fout[vnk] < minfn) fout[vnk] = minfn;
03159 if (fout[vnk] > maxfn) fout[vnk] = maxfn;
03160 }/* for n */
03161
03162 if (cs->Send) {
03163 if (!SUMA_SendToSuma (SO, cs, (void *)fout, SUMA_NODE_RGBAb, 1)) {
03164 SUMA_SL_Warn("Failed in SUMA_SendToSuma\nCommunication halted.");
03165 }
03166 }
03167 } /* for k */
03168 }/* for niter */
03169 break;
03170 case SUMA_ROW_MAJOR:
03171 SUMA_SL_Err("Row Major not implemented");
03172 SUMA_RETURN(NULL);
03173 break;
03174 default:
03175 SUMA_SL_Err("Bad Major, very bad.\n");
03176 SUMA_RETURN(NULL);
03177 break;
03178 }
03179
03180 if (fbuf) SUMA_free(fbuf); fbuf = NULL;
03181
03182 SUMA_RETURN(fout);
03183 }
|
|
|
calculate the interpolation weights required to smooth data on the surface using M.K. Chung et al. Neuroimage 03
Definition at line 2095 of file SUMA_GeomComp.c. References SUMA_NODE_FIRST_NEIGHB::FirstNeighb, SUMA_SurfaceObject::FN, i, LocalHead, SUMA_NODE_FIRST_NEIGHB::N_Neighb, SUMA_NODE_FIRST_NEIGHB::N_Neighb_max, SUMA_SurfaceObject::N_Node, SUMA_SurfaceObject::NodeList, p, q, SUMA_allocate2D(), SUMA_Boolean, SUMA_disp_vect(), SUMA_ENTRY, SUMA_free, SUMA_malloc, SUMA_MT_CROSS, SUMA_MT_DOT, SUMA_NORM, SUMA_RETURN, SUMA_SL_Crit, and SUMA_SL_Err. Referenced by SUMA_Reposition_Touchup().
02096 {
02097 static char FuncName[]={"SUMA_Chung_Smooth_Weights"};
02098 float **wgt=NULL, *coord_nbr=NULL, *cotan=NULL, *tfp=NULL;
02099 float dv[3], p[3], q[3];
02100 float area, area_p, area_q, dot_p, dot_q;
02101 int i, j, k, n, j3p1, j3m1, n3, j3=0, nj, nj3, i_dbg;
02102 SUMA_Boolean LocalHead = NOPE;
02103
02104 SUMA_ENTRY;
02105
02106 if (!SO) {
02107 SUMA_SL_Err("Null SO");
02108 SUMA_RETURN(NULL);
02109 }
02110 if (!SO->FN) {
02111 SUMA_SL_Err("Null SO->FN");
02112 SUMA_RETURN(NULL);
02113 }
02114
02115 i_dbg = -1; /* index of debugging node, set to -1 for no debugging */
02116 /* in the demo mesh that Moo Chung gave me,
02117 Node 17 has the following neighbors in ccw order:
02118 231 230 250 261 239 236 - 231 230 250 261 239 236
02119 Set i_dbg = 17 and turn on LocalHead to get a confirmation of this
02120 by this function*/
02121 /* implement the non-parametric weight estimation method */
02122 wgt = (float **)SUMA_allocate2D(SO->N_Node, SO->FN->N_Neighb_max, sizeof(float)); /* vector of node weights */
02123 coord_nbr = (float *)SUMA_malloc((SO->FN->N_Neighb_max + 2) * sizeof(float) * 3); /* vector of neighboring node coordinates */
02124 cotan = (float *)SUMA_malloc(SO->FN->N_Neighb_max * sizeof(float));
02125 if (!wgt || !coord_nbr || !cotan) {
02126 SUMA_SL_Crit("Failed to allocate for wgt &/|coord_nbr &/|cotan");
02127 SUMA_RETURN(NULL);
02128 }
02129
02130 for (n=0; n < SO->N_Node; ++n) {
02131 n3 = 3 * n;
02132 /* translate the coordinates of the neighboring nodes to make n be the origin */
02133 for (j=0; j<SO->FN->N_Neighb[n]; ++j) {
02134 j3 = 3 * (j+1);
02135 nj = SO->FN->FirstNeighb[n][j]; nj3 = 3 * nj;
02136 coord_nbr[j3] = SO->NodeList[nj3] - SO->NodeList[n3];
02137 coord_nbr[j3+1] = SO->NodeList[nj3+1] - SO->NodeList[n3+1];
02138 coord_nbr[j3+2] = SO->NodeList[nj3+2] - SO->NodeList[n3+2];
02139 } /* for j */
02140 /* padd with last neighbor at the very beginning and 1st neighbor at the end
02141 in matlab: coord_nbr = [coord_nbr(:,last_neighb) coord_nbr coord_nbr(:,first_neighb)];
02142 */
02143 for (k=0; k < 3; ++k) coord_nbr[k] = coord_nbr[j3+k];
02144 j3 = 3 * ( SO->FN->N_Neighb[n] + 1);
02145 for (k=0; k < 3; ++k) coord_nbr[j3+k] = coord_nbr[3+k];
02146 if (LocalHead && n == i_dbg) { SUMA_disp_vect (coord_nbr, 3 * (SO->FN->N_Neighb[n] + 2)) ; }
02147
02148
02149 area = 0.0;
02150 for (j=1; j<=SO->FN->N_Neighb[n]; ++j) {
02151 j3 = 3 * j; j3p1 = 3 * (j+1); j3m1 = 3 * (j-1);
02152 for (k=0; k < 3; ++k) dv[k] = coord_nbr[j3p1+k] - coord_nbr[j3+k];
02153 tfp = &(coord_nbr[j3p1]);
02154 dot_p = SUMA_MT_DOT (tfp, dv);
02155 SUMA_MT_CROSS(p, tfp, dv);
02156 for (k=0; k < 3; ++k) dv[k] = coord_nbr[j3m1+k] - coord_nbr[j3+k];
02157 tfp = &(coord_nbr[j3m1]);
02158 dot_q = SUMA_MT_DOT (tfp, dv);
02159 SUMA_MT_CROSS(q, tfp, dv);
02160
02161 SUMA_NORM(area_p, p);
02162 SUMA_NORM(area_q, q);
02163
02164 cotan[j-1] = dot_p/area_p + dot_q/area_q;
02165 area += area_p/2.0;
02166 if (LocalHead && n == i_dbg) {
02167 fprintf (SUMA_STDERR,"[%d->%d] area_p, area_q = %f, %f\n",
02168 n, SO->FN->FirstNeighb[n][j-1],
02169 area_p / 2.0, area_q / 2.0);
02170 }
02171 }
02172
02173 for (j=0; j<SO->FN->N_Neighb[n]; ++j) {
02174 wgt[n][j] = cotan[j]/area;
02175 }
02176 if (LocalHead && n == i_dbg) {
02177 fprintf (SUMA_STDERR,"%s: Weight Results for neighbors of %d (matlab node %d):\n",
02178 FuncName, n, n+1);
02179 SUMA_disp_vect (wgt[n], SO->FN->N_Neighb[n]);
02180 }
02181 } /* for n */
02182
02183 /* free local variables */
02184 if (coord_nbr) SUMA_free(coord_nbr); coord_nbr = NULL;
02185 if (cotan) SUMA_free(cotan); cotan = NULL;
02186
02187 SUMA_RETURN(wgt);
02188 }
|
|
||||||||||||
|
Function to allocate and initialize a SUMA_VTI * structure.
Definition at line 132 of file SUMA_GeomComp.c. References SUMA_VTI::IntersectedVoxels, SUMA_VTI::N_IntersectedVoxels, SUMA_VTI::N_TriIndex, SUMA_calloc, SUMA_ENTRY, SUMA_malloc, SUMA_RETURN, SUMA_SL_Crit, SUMA_SL_Err, and SUMA_VTI::TriIndex.
00133 {
00134 static char FuncName[]={"SUMA_CreateVTI"};
00135 SUMA_VTI *vti = NULL;
00136
00137 SUMA_ENTRY;
00138 if (!N_TriIndex) {
00139 SUMA_SL_Err("Nothing to do !");
00140 SUMA_RETURN(vti);
00141 }
00142
00143 vti = (SUMA_VTI *)SUMA_malloc(sizeof(SUMA_VTI));
00144 vti->N_TriIndex = N_TriIndex;
00145 if (TriIndex ) {
00146 vti->TriIndex = TriIndex;
00147 }else {
00148 /* create empty copy */
00149 vti->TriIndex = (int *)SUMA_calloc(N_TriIndex, sizeof(int));
00150 if (!vti->TriIndex) {
00151 SUMA_SL_Crit("Failed to allocate for vti->TriIndex");
00152 SUMA_RETURN(NULL);
00153 }
00154 }
00155 vti->N_IntersectedVoxels = (int *)SUMA_calloc(N_TriIndex, sizeof(int));
00156 vti->IntersectedVoxels = (int **)SUMA_calloc(N_TriIndex, sizeof(int*));
00157 if (!vti->N_IntersectedVoxels || !vti->IntersectedVoxels) {
00158 SUMA_SL_Crit("Failed to allocate for vti's innerds");
00159 SUMA_RETURN(NULL);
00160 }
00161
00162 SUMA_RETURN(vti);
00163 }
|
|
||||||||||||||||||||||||||||||||||||
|
Definition at line 6837 of file SUMA_GeomComp.c. References SUMA_NODE_FIRST_NEIGHB::FirstNeighb, SUMA_SurfaceObject::FN, i, L, LARGE_NUM, LocalHead, SUMA_NODE_FIRST_NEIGHB::N_Neighb, SUMA_SurfaceObject::N_Node, SUMA_SurfaceObject::NodeList, Nx, SUMA_Boolean, SUMA_calloc, SUMA_ENTRY, SUMA_etime(), SUMA_free, SUMA_malloc, SUMA_MIN_LOC_VEC, SUMA_RETURN, and v. Referenced by SUMA_ReportDrawnROIDatumLength(), and SUMA_Surf_Plane_Intersect_ROI().
06838 {
06839 static char FuncName[] = {"SUMA_Dijkstra"};
06840 SUMA_Boolean LocalHead = NOPE;
06841 float *L = NULL, Lmin = -1.0, le = 0.0, DT_DIJKSTRA;
06842 int i, iw, iv, v, w, N_Neighb, *Path = NULL;
06843 struct timeval start_time;
06844 SUMA_DIJKSTRA_PATH_CHAIN *DC = NULL, *DCi, *DCp;
06845 SUMA_Boolean Found = NOPE;
06846 /* variables for method 2 */
06847 int N_Lmins, *vLmins, *vLocInLmins, iLmins, ReplacingNode, ReplacedNodeLocation;
06848 float *Lmins;
06849
06850
06851 SUMA_ENTRY;
06852
06853 *Lfinal = -1.0;
06854 *N_Path = 0;
06855
06856 /* make sure Both Nx and Ny exist in isNodeInMesh */
06857 if (!isNodeInMesh[Nx]) {
06858 fprintf (SUMA_STDERR,"\aError %s: Node %d (Nx) is not in mesh.\n", FuncName, Nx);
06859 SUMA_RETURN (NULL);
06860 }
06861 if (!isNodeInMesh[Ny]) {
06862 fprintf (SUMA_STDERR,"\aError %s: Node %d (Ny) is not in mesh.\n", FuncName, Ny);
06863 SUMA_RETURN (NULL);
06864 }
06865
06866 if (!SO->FN) {
06867 fprintf (SUMA_STDERR, "Error %s: SO does not have FN structure.\n", FuncName);
06868 SUMA_RETURN (NULL);
06869 }
06870
06871 if (LocalHead) {
06872 /* Start timer for next function */
06873 SUMA_etime(&start_time,0);
06874 }
06875
06876 /* allocate for chain */
06877 DC = (SUMA_DIJKSTRA_PATH_CHAIN *) SUMA_malloc (sizeof(SUMA_DIJKSTRA_PATH_CHAIN) * SO->N_Node);
06878 if (!DC) {
06879 fprintf (SUMA_STDERR, "Error %s: Could not allocate. \n", FuncName);
06880 SUMA_RETURN (NULL);
06881 }
06882
06883 switch (Method_Number) {
06884
06885 case 0: /* Method 0, Brute force */
06886 /* allocate for vertices labels */
06887 L = (float *) SUMA_calloc (SO->N_Node, sizeof (float));
06888 if (!L) {
06889 fprintf (SUMA_STDERR, "Error %s: Failed to allocate.\n", FuncName);
06890 SUMA_free(DC);
06891 SUMA_RETURN (NULL);
06892 }
06893
06894 /* label all vertices with very large numbers, initialize path previous pointers to null */
06895 for (i=0; i < SO->N_Node; ++i) {
06896 L[i] = LARGE_NUM;
06897 DC[i].Previous = NULL;
06898 }
06899 /* label starting vertex with 0 */
06900 L[Nx] = 0.0;
06901 Lmin = 0.0;
06902 v = Nx;
06903 *Lfinal = -1.0;
06904 /* initialize path at Nx */
06905 DC[Nx].Previous = NULL;
06906 DC[Nx].node = Nx;
06907 DC[Nx].le = 0.0;
06908 DC[Nx].order = 0;
06909 *N_Path = 0;
06910 /* Brute force method */
06911 do {
06912 /* find v in Mesh / L(v) is minimal */
06913 /* this sucks up a lot of time because it is searching the entire set of SO->N_Node instead of the one that was intersected only.
06914 This can be sped up, considerably */
06915 SUMA_MIN_LOC_VEC(L, SO->N_Node, Lmin, v); /* locates and finds the minimum of L, nodes not in mesh will keep their large values and will not be picked*/
06916 if (!isNodeInMesh[v]) {
06917 fprintf (SUMA_STDERR, "\aERROR %s: Dijkstra derailed. v = %d, Lmin = %f\n. Try another point.", FuncName, v, Lmin);
06918 SUMA_free (L);
06919 SUMA_free(DC);
06920 SUMA_RETURN (NULL);
06921 }
06922 if (v == Ny) {
06923 if (LocalHead) fprintf (SUMA_STDERR, "%s: Done.\n", FuncName);
06924 *Lfinal = L[v];
06925 Found = YUP;
06926 } else {
06927 N_Neighb = SO->FN->N_Neighb[v];
06928 for (i=0; i < N_Neighb; ++i) {
06929 w = SO->FN->FirstNeighb[v][i];
06930 if (isNodeInMesh[w]) {
06931 iw = 3*w;
06932 iv = 3*v;
06933 le = sqrt ( (SO->NodeList[iw] - SO->NodeList[iv]) * (SO->NodeList[iw] - SO->NodeList[iv]) +
06934 (SO->NodeList[iw+1] - SO->NodeList[iv+1]) * (SO->NodeList[iw+1] - SO->NodeList[iv+1]) +
06935 (SO->NodeList[iw+2] - SO->NodeList[iv+2]) * (SO->NodeList[iw+2] - SO->NodeList[iv+2]) );
06936 if (L[w] > L[v] + le ) {
06937 L[w] = L[v] + le;
06938 /* update the path */
06939 DCp = &(DC[v]); /* previous path */
06940 DC[w].Previous = (void *) DCp;
06941 DC[w].le = le;
06942 DC[w].node = w;
06943 DC[w].order = DCp->order + 1;
06944 }
06945 }
06946 }
06947
06948 /* remove node v from isNodeInMesh and reset their distance value to a very large one,
06949 this way you do not have to reinitialize this variable. */
06950 isNodeInMesh[v] = NOPE;
06951 *N_isNodeInMesh -= 1;
06952 L[v] = LARGE_NUM;
06953 Found = NOPE;
06954 }
06955 } while (*N_isNodeInMesh > 0 && !Found);
06956
06957 if (!Found) {
06958 fprintf (SUMA_STDERR, "Error %s: No more nodes in mesh, failed to reach target.\n", FuncName);
06959 SUMA_free (L);
06960 SUMA_free(DC);
06961 SUMA_RETURN (NULL);
06962 }else {
06963 if (LocalHead) fprintf (SUMA_STDERR, "%s: Path between Nodes %d and %d is %f.\n", FuncName, Nx, Ny, *Lfinal);
06964 }
06965
06966
06967 if (LocalHead) {
06968 /* stop timer */
06969 DT_DIJKSTRA = SUMA_etime(&start_time,1);
06970 fprintf (SUMA_STDERR, "%s: Method 1- Elapsed time in function %f seconds.\n", FuncName, DT_DIJKSTRA);
06971 }
06972
06973 SUMA_free(L);
06974 break;
06975
06976 case 1: /********* Method 1- faster minimum searching *******************/
06977 if (LocalHead) {
06978 /* Start timer for next function */
06979 SUMA_etime(&start_time,0);
06980 }
06981
06982 /* allocate for vertices labels and minimums vectors*/
06983 L = (float *) SUMA_calloc (SO->N_Node, sizeof (float)); /* L[i] = distance to a node i*/
06984 Lmins = (float *) SUMA_calloc (SO->N_Node, sizeof (float)); /* Lmins = vector containing minimum calculated distances to node */
06985 vLmins = (int *) SUMA_calloc (SO->N_Node, sizeof (int)); /* vLmins[i] = index (into L) of the node having a distance Lmins[i] */
06986 vLocInLmins = (int *) SUMA_calloc (SO->N_Node, sizeof (int)); /* vLocInLmin[j] = index (into Lmins) of a node having index j (into L) */
06987
06988 if (!L || !Lmins || !vLmins || !vLocInLmins) {
06989 fprintf (SUMA_STDERR, "Error %s: Failed to allocate.\n", FuncName);
06990 SUMA_RETURN (NULL);
06991 }
06992
06993 /* label all vertices with very large numbers and initialize vLocInLmins to -1*/
06994 for (i=0; i < SO->N_Node; ++i) {
06995 L[i] = LARGE_NUM;
06996 Lmins[i] = LARGE_NUM;
06997 vLocInLmins[i] = -1;
06998 DC[i].Previous = NULL;
06999 }
07000
07001 /* label starting vertex with 0 */
07002 L[Nx] = 0.0;
07003 *Lfinal = -1.0;
07004
07005 /* initialize values of vectors used to keep track of minimum values of L and their corresponding nodes */
07006 Lmins[0] = 0.0;
07007 vLmins[0] = Nx;
07008 vLocInLmins[Nx] = 0;
07009 N_Lmins = 1;
07010
07011 /* initialize path at Nx */
07012 DC[Nx].Previous = NULL;
07013 DC[Nx].node = Nx;
07014 DC[Nx].le = 0.0;
07015 DC[Nx].order = 0;
07016 *N_Path = 0;
07017
07018 /* method with efficient tracking of minimum */
07019 if (LocalHead) fprintf (SUMA_STDERR, "%s: about to MIN_LOC ....N_isNodeInMesh = %d\n", FuncName, *N_isNodeInMesh);
07020 do {
07021 /* find v in Mesh / L(v) is minimal */
07022 SUMA_MIN_LOC_VEC(Lmins, N_Lmins, Lmin, iLmins); /* locates the minimum value in Lmins vector */
07023 v = vLmins[iLmins]; /* get the node for this Lmin value */
07024 if (!isNodeInMesh[v]) {
07025 fprintf (SUMA_STDERR, "\aERROR %s: Dijkstra derailed. v = %d, Lmin = %f\n. Try another point.", FuncName, v, Lmin);
07026 SUMA_free (L);
07027 SUMA_free (Lmins);
07028 SUMA_free(vLmins);
07029 SUMA_free(vLocInLmins);
07030 SUMA_free(DC);
07031 SUMA_RETURN (NULL);
07032 }
07033 #ifdef LOCALDEBUG
07034 fprintf (SUMA_STDERR, "%s: Node v = %d.\n", FuncName, v);
07035 #endif
07036 if (v == Ny) {
07037 if (LocalHead) fprintf (SUMA_STDERR, "%s: Done.\n", FuncName);
07038 *Lfinal = L[v];
07039 Found = YUP;
07040 } else {
07041 N_Neighb = SO->FN->N_Neighb[v];
07042 for (i=0; i < N_Neighb; ++i) {
07043 w = SO->FN->FirstNeighb[v][i];
07044 if (isNodeInMesh[w]) {
07045 iw = 3*w;
07046 iv = 3*v;
07047 le = sqrt ( (SO->NodeList[iw] - SO->NodeList[iv]) * (SO->NodeList[iw] - SO->NodeList[iv]) +
07048 (SO->NodeList[iw+1] - SO->NodeList[iv+1]) * (SO->NodeList[iw+1] - SO->NodeList[iv+1]) +
07049 (SO->NodeList[iw+2] - SO->NodeList[iv+2]) * (SO->NodeList[iw+2] - SO->NodeList[iv+2]) );
07050 if (L[w] > L[v] + le ) {
07051 #ifdef LOCALDEBUG
07052 fprintf (SUMA_STDERR, "%s: L[%d]=%f > L[%d] = %f + le = %f.\n", FuncName, w, L[w], v, L[v], le);
07053 #endif
07054 L[w] = L[v] + le;
07055 /* update the path */
07056 DCp = &(DC[v]); /* previous path */
07057 DC[w].Previous = (void *) DCp;
07058 DC[w].le = le;
07059 DC[w].node = w;
07060 DC[w].order = DCp->order + 1;
07061
07062 if (vLocInLmins[w] < 0) {
07063 #ifdef LOCALDEBUG
07064 fprintf (SUMA_STDERR, "%s: adding entry for w = %d - First Hit. \n", FuncName, w);
07065 #endif
07066 Lmins[N_Lmins] = L[w]; /* add this value to Lmins vector */
07067 vLmins[N_Lmins] = w; /* store the node for this Lmins value */
07068 vLocInLmins[w] = N_Lmins; /* store where that node is represented in Lmins */
07069 ++N_Lmins; /* increment N_Lmins */
07070 } else {
07071 #ifdef LOCALDEBUG
07072 fprintf (SUMA_STDERR, "%s: modifying entry for w = %d Second Hit.\n", FuncName, w); */
07073 #endif
07074 Lmins[vLocInLmins[w]] = L[w]; /* update value for Lmins */
07075 }
07076 }else {
07077 #ifdef LOCALDEBUG
07078 fprintf (SUMA_STDERR, "%s: L[%d]=%f < L[%d] = %f + le = %f.\n", FuncName, w, L[w], v, L[v], le); */
07079 #endif
07080 }
07081 }
07082 }
07083
07084 /* remove node v from isNodeInMesh and reset their distance value to a very large one,
07085 this way you do not have to reinitialize this variable. */
07086 isNodeInMesh[v] = NOPE;
07087 *N_isNodeInMesh -= 1;
07088 L[v] = LARGE_NUM;
07089 Found = NOPE;
07090
07091 /* also remove the values (by swapping it with last element) for this node from Lmins */
07092 #ifdef LOCALDEBUG
07093 {
07094 int kkk;
07095 fprintf (SUMA_STDERR,"Lmins\tvLmins\tvLocInLmins\n");
07096 for (kkk=0; kkk < N_Lmins; ++kkk) fprintf (SUMA_STDERR,"%f\t%d\t%d\n", Lmins[kkk], vLmins[kkk], vLocInLmins[vLmins[kkk]] );
07097
07098 }
07099 #endif
07100
07101 if (vLocInLmins[v] >= 0) { /* remove its entry if there is one */
07102 #ifdef LOCALDEBUG
07103 fprintf (SUMA_STDERR, "%s: removing node v = %d. N_Lmins = %d\n", FuncName, v, N_Lmins);
07104 #endif
07105 --N_Lmins;
07106 ReplacingNode = vLmins[N_Lmins];
07107 ReplacedNodeLocation = vLocInLmins[v];
07108 Lmins[vLocInLmins[v]] = Lmins[N_Lmins];
07109 vLmins[vLocInLmins[v]] = vLmins[N_Lmins];
07110 vLocInLmins[ReplacingNode] = ReplacedNodeLocation;
07111 vLocInLmins[v] = -1;
07112 Lmins[N_Lmins] = LARGE_NUM;
07113 }
07114 }
07115 } while (*N_isNodeInMesh > 0 && !Found);
07116
07117 if (!Found) {
07118 fprintf (SUMA_STDERR, "Error %s: No more nodes in mesh, failed to reach target %d. NLmins = %d\n", FuncName, Ny, N_Lmins);
07119 SUMA_free (L);
07120 SUMA_free (Lmins);
07121 SUMA_free(vLmins);
07122 SUMA_free(vLocInLmins);
07123 SUMA_free(DC);
07124 SUMA_RETURN (NULL);
07125 }else {
07126 if (LocalHead) fprintf (SUMA_STDERR, "%s: Path between Nodes %d and %d is %f.\n", FuncName, Nx, Ny, *Lfinal);
07127 }
07128
07129
07130 if (LocalHead) {
07131 /* stop timer */
07132 DT_DIJKSTRA = SUMA_etime(&start_time,1);
07133 fprintf (SUMA_STDERR, "%s: Method 2- Elapsed time in function %f seconds.\n", FuncName, DT_DIJKSTRA);
07134 }
07135
07136 SUMA_free(L);
07137 SUMA_free(Lmins);
07138 SUMA_free(vLmins);
07139 SUMA_free(vLocInLmins);
07140 break; /********** Method 1- faster minimum searching **************/
07141 default:
07142 fprintf (SUMA_STDERR, "Error %s: No such method (%d).\n", FuncName, Method_Number);
07143 if (DC) SUMA_free(DC);
07144 SUMA_RETURN (NULL);
07145 break;
07146 }
07147
07148 /* now reconstruct the path */
07149 *N_Path = DC[Ny].order+1;
07150 Path = (int *) SUMA_calloc (*N_Path, sizeof(int));
07151 if (!Path) {
07152 fprintf (SUMA_STDERR, "Error %s: Failed to allocate.\n", FuncName);
07153 if (DC) SUMA_free(DC);
07154 SUMA_RETURN (NULL);
07155 }
07156
07157 DCi = &(DC[Ny]);
07158 iv = *N_Path - 1;
07159 Path[iv] = Ny;
07160 if (iv > 0) {
07161 do {
07162 --iv;
07163 DCp = (SUMA_DIJKSTRA_PATH_CHAIN *) DCi->Previous;
07164 Path[iv] = DCp->node;
07165 DCi = DCp;
07166 } while (DCi->Previous);
07167 }
07168
07169 if (iv != 0) {
07170 fprintf (SUMA_STDERR, "Error %s: iv = %d. This should not be.\n", FuncName, iv);
07171 }
07172
07173 SUMA_free(DC);
07174 SUMA_RETURN (Path);
07175 }
|
|
||||||||||||||||||||
|
inflates or deflates a surface to make the area of one surface (SO) equal to the area of another (SOref)
Definition at line 1700 of file SUMA_GeomComp.c. References a, SUMA_SurfaceObject::Center, SUMA_AreaDiffDataStruct::cs, i, LocalHead, SUMA_SurfaceObject::N_FaceSet, SUMA_SurfaceObject::N_Node, SUMA_SurfaceObject::NodeDim, SUMA_SurfaceObject::NodeList, SUMA_AreaDiffDataStruct::SO, SUMA_AreaDiffDataStruct::SOref, SUMA_AreaDiff(), SUMA_BinaryZeroSearch(), SUMA_Boolean, SUMA_ENTRY, SUMA_free, SUMA_GetAreaDiffRange(), SUMA_malloc, SUMA_RETURN, SUMA_SL_Err, and SUMA_AreaDiffDataStruct::tmpList.
01701 {
01702 static char FuncName[]={"SUMA_EquateSurfaceAreas"};
01703 int iter, i, iter_max, ndiv;
01704 double a, b, d;
01705 SUMA_AreaDiffDataStruct fdata;
01706 SUMA_Boolean LocalHead = NOPE;
01707
01708 SUMA_ENTRY;
01709
01710 if (!SO || !SOref) { SUMA_SL_Err("NULL surfaces"); SUMA_RETURN(NOPE); }
01711 if (SO->N_Node != SOref->N_Node || SO->N_FaceSet != SOref->N_FaceSet) { SUMA_SL_Err("Surfaces not isotopic"); SUMA_RETURN(NOPE); }
01712
01713 if (LocalHead) {
01714 fprintf(SUMA_STDERR, "%s:\n"
01715 " SO Center: %f, %f, %f\n"
01716 " SOref Center: %f, %f, %f\n"
01717 , FuncName,
01718 SO->Center[0], SO->Center[1], SO->Center[2],
01719 SOref->Center[0], SOref->Center[1], SOref->Center[2]);
01720 }
01721
01722 /* fill up fdata */
01723 fdata.SO = SO; fdata.SOref = SOref; fdata.cs = cs;
01724 fdata.tmpList = (float *)SUMA_malloc(SOref->NodeDim * SOref->N_Node * sizeof(float));
01725 if (!fdata.tmpList) {
01726 SUMA_SL_Err("Failed to allocate");
01727 SUMA_RETURN(0);
01728 }
01729
01730 if (!SUMA_GetAreaDiffRange(&fdata, &a, &b)) {
01731 SUMA_SL_Err("Failed to get range");
01732 SUMA_RETURN(NOPE);
01733 }
01734
01735 if (LocalHead) {
01736 fprintf(SUMA_STDERR,"%s:\na = %f\tb=%f\n", FuncName, a, b);
01737 }
01738 SUMA_BinaryZeroSearch(a, b, SUMA_AreaDiff, &fdata, 500, tol);
01739
01740 /* now make the new node list be SO's thingy*/
01741 SUMA_free(SO->NodeList); SO->NodeList = fdata.tmpList; fdata.tmpList = NULL;
01742
01743 SUMA_RETURN(YUP);
01744 }
|
|
||||||||||||||||||||
|
make the size of 2 surfaces match see help -match_size option in SurfSmooth
Definition at line 1942 of file SUMA_GeomComp.c. References a, SUMA_SurfaceObject::Center, free, i, SUMA_GET_OFFSET_STRUCT::LayerVect, LocalHead, SUMA_SurfaceObject::N_FaceSet, SUMA_SurfaceObject::N_Node, SUMA_GET_OFFSET_STRUCT::N_Nodes, SUMA_SurfaceObject::NodeList, SUMA_GET_OFFSET_STRUCT::OffVect, SUMA_COMM_STRUCT::Send, SUMA_append_replace_string(), SUMA_Boolean, SUMA_ENTRY, SUMA_etime(), SUMA_Extension(), SUMA_Free_getoffsets(), SUMA_getoffsets2(), SUMA_Initialize_getoffsets(), SUMA_NODE_XYZ, SUMA_POINT_AT_DISTANCE_NORM, SUMA_Recycle_getoffsets(), SUMA_RETURN, SUMA_SEG_LENGTH, SUMA_SendToSuma(), SUMA_SL_Err, SUMA_SL_Warn, and SUMA_UNIT_VEC.
01943 {
01944 static char FuncName[]={"SUMA_EquateSurfaceSize"};
01945 int i=0, j=0, cnt = 0, istrt, istp;
01946 struct timeval start_time, start_time_all;
01947 float etime_GetOffset, etime_GetOffset_all, ave_dist= 0.0, dj = 0.0, ave_dist_ref= 0.0, *a=NULL;
01948 float P2[2][3], U[3], Un;
01949 SUMA_GET_OFFSET_STRUCT *OffS = NULL;
01950 SUMA_Boolean LocalHead = NOPE;
01951
01952 SUMA_ENTRY;
01953
01954 if (!SO || !SOref) { SUMA_SL_Err("NULL surfaces"); SUMA_RETURN(NOPE); }
01955 if (SO->N_Node != SOref->N_Node || SO->N_FaceSet != SOref->N_FaceSet) { SUMA_SL_Err("Surfaces not isotopic"); SUMA_RETURN(NOPE); }
01956
01957 if (LocalHead) {
01958 fprintf(SUMA_STDERR, "%s:\n"
01959 " SO Center: %f, %f, %f\n"
01960 " SOref Center: %f, %f, %f\n"
01961 " max_off = %f\n", FuncName,
01962 SO->Center[0], SO->Center[1], SO->Center[2],
01963 SOref->Center[0], SOref->Center[1], SOref->Center[2],
01964 max_off);
01965 }
01966
01967 OffS = SUMA_Initialize_getoffsets (SOref->N_Node);
01968 #ifdef FROM_THIS_NODE
01969 istrt = FROM_THIS_NODE;
01970 istp = TO_THIS_NODE+1;
01971 #else
01972 istrt = 0;
01973 istp = SOref->N_Node;
01974 #endif
01975 for (i =istrt ; i<istp; ++i) {
01976 if (i == 0) {
01977 SUMA_etime(&start_time,0);
01978 }
01979 SUMA_getoffsets2 (i, SOref, max_off, OffS, NULL, 0);
01980 /* find average distance between nodes within offset and center of surface */
01981 a = &(SOref->NodeList[3*i]); SUMA_SEG_LENGTH(a, SOref->Center, ave_dist_ref);
01982 cnt = 1;
01983 #ifdef FROM_THIS_NODE
01984 fprintf(SUMA_STDERR, "%s: Considering the following %d neighbors to:\n"
01985 "i=%d; [%f, %f, %f]; d[%d] = %f\n", FuncName, OffS->N_Nodes,
01986 i, SOref->NodeList[3*i], SOref->NodeList[3*i+1], SOref->NodeList[3*i+2],
01987 cnt, ave_dist_ref);
01988 #endif
01989 for (j=0; j<OffS->N_Nodes; ++j)
01990 {
01991
01992 if (i!=j && OffS->LayerVect[j] >= 0 && OffS->OffVect[j] <= max_off)
01993 {
01994
01995 a = &(SOref->NodeList[3*j]); SUMA_SEG_LENGTH(a, SOref->Center, dj);
01996 ave_dist_ref += dj;
01997 ++cnt;
01998 #ifdef FROM_THIS_NODE
01999 fprintf(SUMA_STDERR, ""
02000 "j=%d; [%f, %f, %f]; d[%d] = %f\n",
02001 j, SOref->NodeList[3*j], SOref->NodeList[3*j+1], SOref->NodeList[3*j+2],
02002 cnt, dj);
02003 #endif
02004 }
02005 }
02006 ave_dist_ref /= (float)cnt;
02007 /* move node i to the reference average location
02008 Do not travel along normals, you should travel along
02009 radial direction Center-->node*/
02010 a = &(SO->NodeList[3*i]); SUMA_UNIT_VEC(SO->Center, a, U, Un);
02011 if (Un) {
02012 SUMA_POINT_AT_DISTANCE_NORM(U, SO->Center, ave_dist_ref, P2);
02013 SO->NodeList[3*i] = P2[0][0]; SO->NodeList[3*i+1] = P2[0][1]; SO->NodeList[3*i+2] = P2[0][2];
02014 } else {
02015 SUMA_SL_Err("Identical points!\n"
02016 "No coordinates modified");
02017 }
02018
02019 if (LocalHead) {
02020 if (! (i%999)) {
02021 a = &(SO->NodeList[3*i]);
02022 SUMA_SEG_LENGTH(a, SOref->Center, dj);
02023 fprintf(SUMA_STDERR, "%s:\n"
02024 "node i=%d, avg_dist_ref = %f\ncnt = %d\n"
02025 "Check on P2: New dist =%f ?=? %f\n",
02026 FuncName, i, ave_dist_ref, cnt, dj, ave_dist_ref);
02027 etime_GetOffset = SUMA_etime(&start_time,1);
02028 fprintf(SUMA_STDERR, "%s: Search to %f mm took %f seconds for %d nodes.\n"
02029 "Projected completion time: %f minutes\n",
02030 FuncName, max_off, etime_GetOffset, i+1,
02031 etime_GetOffset * SO->N_Node / 60.0 / (i+1));
02032 }
02033 }
02034 if (! (i%99) && cs) {
02035 if (cs->Send) { /* send the first monster (it's SOref "in SUMA" that's being modified on the fly*/
02036 if (!SUMA_SendToSuma (SOref, cs, (void *)SO->NodeList, SUMA_NODE_XYZ, 1)) {
02037 SUMA_SL_Warn("Failed in SUMA_SendToSuma\nCommunication halted.");
02038 }
02039 }
02040 }
02041
02042 #ifdef FROM_THIS_NODE
02043 {
02044 FILE *fid=NULL;
02045 char *outname=NULL, tmp[20];
02046 int ii;
02047 if (cs->Send) { /* send the first monster (it's SOref that's being modified on the fly*/
02048 if (!SUMA_SendToSuma (SOref, cs, (void *)SO->NodeList, SUMA_NODE_XYZ, 1)) {
02049 SUMA_SL_Warn("Failed in SUMA_SendToSuma\nCommunication halted.");
02050 }
02051 }
02052 sprintf(tmp,"offset_n%d", FROM_THIS_NODE);
02053 outname = SUMA_Extension("", ".1D", YUP);
02054 outname = SUMA_append_replace_string(outname, "offset.1D", "", 1);
02055 fid = fopen(outname, "w"); free(outname); outname = NULL;
02056 if (!fid) {
02057 SUMA_SL_Err("Could not open file for writing.\nCheck file permissions, disk space.\n");
02058 } else {
02059 fprintf (fid,"#Column 1 = Node index\n"
02060 "#column 2 = Neighborhood layer\n"
02061 "#Column 3 = Distance from node %d\n", 99);
02062 for (ii=0; ii<SO->N_Node; ++ii) {
02063 if (OffS->LayerVect[ii] >= 0) {
02064 fprintf(fid,"%d\t%d\t%f\n", ii, OffS->LayerVect[ii], OffS->OffVect[ii]);
02065 }
02066 }
02067 fclose(fid);
02068 }
02069 { int jnk; fprintf(SUMA_STDOUT,"Pausing, next node is %d...", i+1); jnk = getchar(); fprintf(SUMA_STDOUT,"\n"); }
02070 }
02071 #endif
02072
02073 /* recycle offsets structure */
02074 SUMA_Recycle_getoffsets (OffS);
02075
02076 }
02077
02078 /* offsets are to be freed */
02079 SUMA_Free_getoffsets(OffS); OffS = NULL;
02080
02081 SUMA_RETURN(YUP);
02082 }
|
|
||||||||||||||||||||
|
inflates or deflates a surface to make the volume of one surface (SO) equal to the volume of another (SOref)
Definition at line 1756 of file SUMA_GeomComp.c. References a, SUMA_SurfaceObject::Center, SUMA_VolDiffDataStruct::cs, i, LocalHead, SUMA_SurfaceObject::N_FaceSet, SUMA_SurfaceObject::N_Node, SUMA_SurfaceObject::NodeDim, SUMA_SurfaceObject::NodeList, SUMA_VolDiffDataStruct::SO, SUMA_VolDiffDataStruct::SOref, SUMA_BinaryZeroSearch(), SUMA_Boolean, SUMA_ENTRY, SUMA_free, SUMA_GetVolDiffRange(), SUMA_malloc, SUMA_RETURN, SUMA_SL_Err, SUMA_VolDiff(), and SUMA_VolDiffDataStruct::tmpList.
01757 {
01758 static char FuncName[]={"SUMA_EquateSurfaceVolumes"};
01759 int iter, i, iter_max, ndiv;
01760 double a, b, d;
01761 SUMA_VolDiffDataStruct fdata;
01762 SUMA_Boolean LocalHead = NOPE;
01763
01764 SUMA_ENTRY;
01765
01766 if (!SO || !SOref) { SUMA_SL_Err("NULL surfaces"); SUMA_RETURN(NOPE); }
01767 if (SO->N_Node != SOref->N_Node || SO->N_FaceSet != SOref->N_FaceSet) { SUMA_SL_Err("Surfaces not isotopic"); SUMA_RETURN(NOPE); }
01768
01769 if (LocalHead) {
01770 fprintf(SUMA_STDERR, "%s:\n"
01771 " SO Center: %f, %f, %f\n"
01772 " SOref Center: %f, %f, %f\n"
01773 , FuncName,
01774 SO->Center[0], SO->Center[1], SO->Center[2],
01775 SOref->Center[0], SOref->Center[1], SOref->Center[2]);
01776 }
01777
01778 /* fill up fdata */
01779 fdata.SO = SO; fdata.SOref = SOref; fdata.cs = cs;
01780 fdata.tmpList = (float *)SUMA_malloc(SOref->NodeDim * SOref->N_Node * sizeof(float));
01781 if (!fdata.tmpList) {
01782 SUMA_SL_Err("Failed to allocate");
01783 SUMA_RETURN(0);
01784 }
01785
01786 if (!SUMA_GetVolDiffRange(&fdata, &a, &b)) {
01787 SUMA_SL_Err("Failed to get range");
01788 SUMA_RETURN(NOPE);
01789 }
01790
01791 if (LocalHead) {
01792 fprintf(SUMA_STDERR,"%s:\na = %f\tb=%f\n", FuncName, a, b);
01793 }
01794 SUMA_BinaryZeroSearch(a, b, SUMA_VolDiff, &fdata, 500, tol);
01795
01796 /* now make the new node list be SO's thingy*/
01797 SUMA_free(SO->NodeList); SO->NodeList = fdata.tmpList; fdata.tmpList = NULL;
01798
01799 SUMA_RETURN(YUP);
01800 }
|
|
||||||||||||||||||||||||||||||||
|
Function to fill the volume enclose in a mask.
Definition at line 481 of file SUMA_GeomComp.c. References DListElmt_::data, dlist_destroy(), dlist_head, dlist_init(), dlist_ins_next(), dlist_remove(), dlist_size, dlist_tail, i, itmp, LocalHead, SUMA_1D_2_3D_index, SUMA_Boolean, SUMA_calloc, SUMA_ENTRY, SUMA_free, SUMA_malloc, SUMA_RETURN, SUMA_SL_Crit, SUMA_SL_Err, SUMA_VOX_NEIGHB_FACE, and SUMA_VoxelNeighbors(). Referenced by SUMA_SurfGridIntersect().
00482 {
00483 static char FuncName[]={"SUMA_FillToVoxelMask"};
00484 byte *isin = NULL, *visited=NULL;
00485 DList*candlist=NULL;
00486 DListElmt *dothiselm=NULL;
00487 int dothisvoxel, itmp;
00488 int nl[50], N_n, in ,neighb, nijk, i, j, k, nij;
00489 SUMA_Boolean LocalHead = NOPE;
00490
00491 SUMA_ENTRY;
00492
00493 *N_in = 0;
00494
00495 if (!ijkmask) {
00496 SUMA_SL_Err("Nothing to do");
00497 SUMA_RETURN(NULL);
00498 }
00499 if (ijkmask[ijkseed]) {
00500 SUMA_SL_Err("Seed is on mask. Bad business.");
00501 SUMA_RETURN(NULL);
00502 }
00503
00504 nij = ni * nj;
00505 nijk = ni * nj * nk;
00506
00507 if (LocalHead) {
00508 SUMA_1D_2_3D_index (ijkseed, i, j, k, ni, nij);
00509 fprintf(SUMA_STDERR,"%s:\nSeed is %d %d %d\n", FuncName, i, j, k);
00510 }
00511 candlist = (DList*)SUMA_malloc(sizeof(DList));
00512 visited = (byte *)SUMA_calloc(nijk, sizeof(byte));
00513 if (!visited || !candlist) {
00514 SUMA_SL_Crit("Failed to allocate for visited or candlist");
00515 SUMA_RETURN(NULL);
00516 }
00517
00518 if (usethisisin) isin = usethisisin;
00519 else {
00520 isin = (byte *)SUMA_calloc(nijk, sizeof(byte));
00521 if (!isin) {
00522 SUMA_SL_Crit("Failed to allocate");
00523 SUMA_RETURN(NULL);
00524 }
00525 }
00526
00527 dothisvoxel = ijkseed;
00528 dlist_init(candlist, NULL);
00529
00530
00531 isin[dothisvoxel] = 1; ++(*N_in); /* Add voxel to cluster */
00532 visited[dothisvoxel] = 1;
00533 dlist_ins_next(candlist, dlist_tail(candlist), (void *)dothisvoxel); /* Add voxel as next candidate*/
00534
00535 while (dlist_size(candlist)) {
00536 /* find neighbors in its vicinity */
00537 dothiselm = dlist_head(candlist); dothisvoxel = (int) dothiselm->data;
00538 N_n = SUMA_VoxelNeighbors (dothisvoxel, ni, nj, nk, SUMA_VOX_NEIGHB_FACE, nl);
00539 /* remove node from candidate list */
00540 dlist_remove(candlist, dothiselm, (void*)&itmp);
00541 /* search to see if any are to be assigned */
00542 for (in=0; in<N_n; ++in) {
00543 neighb = nl[in];
00544 if (!ijkmask[neighb]) {
00545 isin[neighb] = 1; ++(*N_in); /* Add voxel to cluster */
00546 /* mark it as a candidate if it has not been visited as a candidate before */
00547 if (!visited[neighb]) {
00548 dlist_ins_next(candlist, dlist_tail(candlist), (void *)neighb);
00549 visited[neighb] = 1;
00550 }
00551 }
00552 }
00553 }
00554
00555 if (visited) SUMA_free(visited); visited = NULL;
00556 if (candlist) { dlist_destroy(candlist); SUMA_free(candlist); candlist = NULL; }
00557
00558
00559 SUMA_RETURN(isin);
00560 }
|
|
||||||||||||||||||||||||
|
Finds an edge that has Nhost hosting triangles. Only the edges indexed in IsInter are examined. E = SUMA_Find_Edge_N_Host (EL, IsInter, N_IsInter, Nhost);
Definition at line 6787 of file SUMA_GeomComp.c. References SUMA_EDGE_LIST::ELps, i, SUMA_ENTRY, and SUMA_RETURN. Referenced by SUMA_AssignTriBranch().
06788 {
06789 static char FuncName[]={"SUMA_Find_Edge_Nhost"};
06790
06791 SUMA_ENTRY;
06792
06793 for (*i=0; *i < N_IsInter; ++(*i)) {
06794 if (EL->ELps[IsInter[*i]][2] == Nhost) SUMA_RETURN (IsInter[*i]);
06795 }
06796
06797 SUMA_RETURN (-1);
06798
06799 }
|
|
||||||||||||
|
creates a vector of node neighbors structures such that: OffS = SUMA_FormNeighbOffset ( SUMA_SurfaceObject *SO, float OffsetLim);
Definition at line 2699 of file SUMA_GeomComp.c. References SUMA_SurfaceObject::FN, free, i, SUMA_GET_OFFSET_STRUCT::layers, SUMA_GET_OFFSET_STRUCT::LayerVect, LocalHead, SUMA_GET_OFFSET_STRUCT::N_layers, SUMA_SurfaceObject::N_Node, SUMA_NODE_NEIGHB_LAYER::N_NodesInLayer, SUMA_NODE_NEIGHB_LAYER::NodesInLayer, SUMA_GET_OFFSET_STRUCT::OffVect, SUMA_append_replace_string(), SUMA_Boolean, SUMA_ENTRY, SUMA_etime(), SUMA_Extension(), SUMA_Free_getoffsets(), SUMA_getoffsets2(), SUMA_Initialize_getoffsets(), SUMA_malloc, SUMA_Recycle_getoffsets(), SUMA_RETURN, and SUMA_SL_Err. Referenced by SUMA_Offset_GeomSmooth().
02700 {
02701 static char FuncName[]={"SUMA_FormNeighbOffset"};
02702 int i, ii, il, jl, noffs, ShowNode = 4;
02703 SUMA_GET_OFFSET_STRUCT *OffS = NULL;
02704 struct timeval start_time;
02705 float etime_GetOffset, mean_N_Neighb, dist, dist_norm;
02706 SUMA_OFFSET_STRUCT *OffS_out=NULL;
02707 SUMA_Boolean LocalHead = NOPE;
02708
02709 SUMA_ENTRY;
02710 if (!SO) { SUMA_SL_Err("NULL SO"); SUMA_RETURN(NULL); }
02711 if (!SO->FN) {
02712 SUMA_SL_Err("NULL SO->FN");
02713 SUMA_RETURN(NULL);
02714 }
02715 OffS_out = (SUMA_OFFSET_STRUCT *)SUMA_malloc(SO->N_Node * sizeof(SUMA_OFFSET_STRUCT));
02716
02717 SUMA_etime(&start_time,0);
02718
02719 OffS = SUMA_Initialize_getoffsets (SO->N_Node);
02720 mean_N_Neighb = 0;
02721 dist_norm = 1.1 * OffsetLim;
02722 for (i=0; i < SO->N_Node; ++i) {
02723 SUMA_getoffsets2 (i, SO, OffsetLim, OffS, NULL, 0);
02724 /* Now store all the relevant info in OffS in OffS_out[i] */
02725 OffS_out[i].N_Neighb = 0;
02726 for (il=1; il<OffS->N_layers; ++il) {
02727 OffS_out[i].N_Neighb += OffS->layers[il].N_NodesInLayer;
02728 }
02729 OffS_out[i].Neighb_ind = (int *)SUMA_malloc(OffS_out[i].N_Neighb * sizeof(int));
02730 OffS_out[i].Neighb_dist = (float *)SUMA_malloc(OffS_out[i].N_Neighb * sizeof(float));
02731 mean_N_Neighb += OffS_out[i].N_Neighb;
02732 noffs = 0;
02733 for (il=1; il<OffS->N_layers; ++il) {
02734 for (jl=0; jl<OffS->layers[il].N_NodesInLayer; ++jl) {
02735 OffS_out[i].Neighb_ind[noffs] = OffS->layers[il].NodesInLayer[jl];
02736 #if 1
02737 /* don't play fancy with the weights here */
02738 OffS_out[i].Neighb_dist[noffs] = OffS->OffVect[OffS_out[i].Neighb_ind[noffs]];
02739 #else
02740 dist = OffS->OffVect[OffS_out[i].Neighb_ind[noffs]];
02741 if (dist > OffsetLim) OffS_out[i].Neighb_dist[noffs] = 0;
02742 else OffS_out[i].Neighb_dist[noffs] = (dist );
02743 #endif
02744 ++noffs;
02745 }
02746 }
02747
02748 /* Show me the offsets for one node*/
02749 if (0) {
02750 if (i == ShowNode) {
02751 FILE *fid=NULL;
02752 char *outname=NULL;
02753 outname = SUMA_Extension("SomethingOffset", ".1D", YUP);
02754 outname = SUMA_append_replace_string(outname, "offset.1D", "", 1);
02755 fid = fopen(outname, "w"); free(outname); outname = NULL;
02756 if (!fid) {
02757 SUMA_SL_Err("Could not open file for writing.\nCheck file permissions, disk space.\n");
02758 } else {
02759 fprintf (fid,"#Column 1 = Node index\n"
02760 "#column 2 = Neighborhood layer\n"
02761 "#Column 3 = Distance from node %d\n", ShowNode);
02762 for (ii=0; ii<SO->N_Node; ++ii) {
02763 if (OffS->LayerVect[ii] >= 0) {
02764 fprintf(fid,"%d\t%d\t%f\n", ii, OffS->LayerVect[ii], OffS->OffVect[ii]);
02765 }
02766 }
02767 fclose(fid);
02768 }
02769 }
02770 }
02771
02772 if (i == 99) {
02773 etime_GetOffset = SUMA_etime(&start_time,1);
02774 fprintf(SUMA_STDERR, "%s: Search to %f mm took %f seconds for %d nodes.\n"
02775 "Projected completion time: %f minutes\n"
02776 "Projected memory need for structure %f MB",
02777 FuncName, OffsetLim, etime_GetOffset, i+1,
02778 etime_GetOffset * SO->N_Node / 60.0 / (i+1),
02779 (mean_N_Neighb / (i+1) * 8 + 12)* SO->N_Node/1000000.0);
02780 }
02781 SUMA_Recycle_getoffsets (OffS);
02782 }
02783 SUMA_Free_getoffsets(OffS); OffS = NULL;
02784
02785 etime_GetOffset = SUMA_etime(&start_time,1);
02786 fprintf(SUMA_STDERR, "%s: Search to %f mm took %f seconds for %d nodes.\n"
02787 "Mean number of neighbors per node: %f\n",
02788 FuncName, OffsetLim, etime_GetOffset, SO->N_Node, mean_N_Neighb / SO->N_Node);
02789
02790 SUMA_RETURN(OffS_out);
02791 }
|
|
|
||||||||||||
|
frees what is created by SUMA_FormNeighbOffset
Definition at line 2798 of file SUMA_GeomComp.c. References i, SUMA_SurfaceObject::N_Node, SUMA_ENTRY, SUMA_free, SUMA_RETURN, and SUMA_S_Err. Referenced by SUMA_Offset_GeomSmooth().
02799 {
02800 static char FuncName[]={"SUMA_free_NeighbOffset"};
02801 int i;
02802 SUMA_ENTRY;
02803
02804 if (!SO) {
02805 SUMA_S_Err("NULL SO!");
02806 SUMA_RETURN(NULL);
02807 }
02808 if (!OffS_out) SUMA_RETURN(NULL);
02809 for (i=0; i < SO->N_Node; ++i) {
02810 OffS_out[i].N_Neighb = 0;
02811 if (OffS_out[i].Neighb_dist) SUMA_free(OffS_out[i].Neighb_dist); OffS_out[i].Neighb_dist = NULL;
02812 if (OffS_out[i].Neighb_ind) SUMA_free(OffS_out[i].Neighb_ind); OffS_out[i].Neighb_ind = NULL;
02813 }
02814 SUMA_free(OffS_out);
02815 SUMA_RETURN(NULL);
02816 }
|
|
|
*** SegPres added Jul 08 04, ZSS bug before ... Definition at line 1141 of file SUMA_GeomComp.c. References dt, SUMA_ENTRY, SUMA_free, and SUMA_RETURNe. Referenced by SUMA_getoffsets_ll().
01142 {
01143 static char FuncName[]={"SUMA_Free_Offset_ll_Datum"};
01144 SUMA_OFFSET_LL_DATUM *dt;
01145
01146 SUMA_ENTRY;
01147
01148 if (data) {
01149 dt = (SUMA_OFFSET_LL_DATUM *)data;
01150 SUMA_free(dt);
01151 }
01152
01153 SUMA_RETURNe;
01154 }
|
|
|
free the SPI structure Definition at line 6620 of file SUMA_GeomComp.c. References SUMA_SURF_PLANE_INTERSECT::IntersEdges, SUMA_SURF_PLANE_INTERSECT::IntersNodes, SUMA_SURF_PLANE_INTERSECT::IntersTri, SUMA_SURF_PLANE_INTERSECT::isEdgeInters, SUMA_SURF_PLANE_INTERSECT::isNodeInMesh, SUMA_SURF_PLANE_INTERSECT::isTriHit, SUMA_ENTRY, SUMA_free, and SUMA_RETURNe. Referenced by SUMA_Surf_Plane_Intersect(), and SUMA_Surf_Plane_Intersect_ROI().
06621 {
06622 static char FuncName[]={"SUMA_free_SPI"};
06623
06624 SUMA_ENTRY;
06625
06626 if (!SPI) SUMA_RETURNe;
06627 if (SPI->IntersTri) SUMA_free(SPI->IntersTri);
06628 if (SPI->IntersNodes) SUMA_free(SPI->IntersNodes);
06629 if (SPI->IntersEdges) SUMA_free(SPI->IntersEdges);
06630 if (SPI->isNodeInMesh) SUMA_free(SPI->isNodeInMesh);
06631 if (SPI->isTriHit) SUMA_free (SPI->isTriHit);
06632 if (SPI->isEdgeInters) SUMA_free (SPI->isEdgeInters);
06633
06634 if (SPI) SUMA_free(SPI);
06635
06636 SUMA_RETURNe;
06637 }
|
|
||||||||||||
|
Function to free a vector of SUMA_TRI_BRANCH structures. Definition at line 6558 of file SUMA_GeomComp.c. References i, SUMA_ENTRY, SUMA_free, and SUMA_RETURNe.
06559 {
06560
06561 static char FuncName[]={"SUMA_free_STB"};
06562 int i;
06563
06564 SUMA_ENTRY;
06565
06566 for (i=0; i < N_Bv; ++i) {
06567 if (Bv[i].list) SUMA_free(Bv[i].list);
06568 }
06569 if (Bv) SUMA_free(Bv);
06570
06571 SUMA_RETURNe;
06572
06573 }
|
|
|
ans = SUMA_freePatch (SUMA_PATCH *Patch) ; frees Patch pointer
Definition at line 5298 of file SUMA_GeomComp.c. References SUMA_PATCH::FaceSetIndex, SUMA_PATCH::FaceSetList, SUMA_PATCH::nHits, SUMA_Boolean, SUMA_ENTRY, SUMA_free, and SUMA_RETURN. Referenced by main(), SUMA_GetContour(), and SUMA_Pattie_Volume().
05299 {
05300 static char FuncName[]={"SUMA_freePatch"};
05301
05302 SUMA_ENTRY;
05303
05304
05305 if (Patch->FaceSetIndex) SUMA_free(Patch->FaceSetIndex);
05306 if (Patch->FaceSetList) SUMA_free(Patch->FaceSetList);
05307 if (Patch->nHits) SUMA_free(Patch->nHits);
05308 if (Patch) SUMA_free(Patch);
05309 SUMA_RETURN(YUP);
05310
05311 }
|
|
|
Definition at line 165 of file SUMA_GeomComp.c. References free, i, SUMA_VTI::IntersectedVoxels, SUMA_VTI::N_IntersectedVoxels, SUMA_VTI::N_TriIndex, SUMA_ENTRY, SUMA_free, SUMA_RETURN, and SUMA_VTI::TriIndex.
00166 {
00167 static char FuncName[]={"SUMA_FreeVTI"};
00168 int i;
00169
00170 SUMA_ENTRY;
00171
00172 if (!vti) SUMA_RETURN(NULL);
00173 if (vti->TriIndex) SUMA_free(vti->TriIndex);
00174 if (vti->IntersectedVoxels) {
00175 for (i=0; i<vti->N_TriIndex; ++i) {
00176 if (vti->IntersectedVoxels[i]) free(vti->IntersectedVoxels[i]);
00177 }
00178 SUMA_free(vti->IntersectedVoxels);
00179 }
00180 if (vti->N_IntersectedVoxels) SUMA_free(vti->N_IntersectedVoxels);
00181 SUMA_free(vti);
00182
00183 SUMA_RETURN(NULL);
00184 }
|
|
||||||||||||||||||||||||||||||||||||||||||||||||
|
This function moves from one intersected edge to the next until a certain node is encountered or a a certain distance is exceeded. By intersected edge, I mean an edge of the surface's mesh that was intersected by a plane. ans = SUMA_FromIntEdgeToIntEdge (int Tri, int E1, int E2, SUMA_EDGE_LIST *EL, SPI, int Ny, Visited, float *d, float dmax, int *tPath, int *N_tPath);
Definition at line 7483 of file SUMA_GeomComp.c. References SUMA_EDGE_LIST::EL, SUMA_SURF_PLANE_INTERSECT::IntersNodes, SUMA_SURF_PLANE_INTERSECT::isEdgeInters, SUMA_SURF_PLANE_INTERSECT::isTriHit, LocalHead, SUMA_Boolean, SUMA_ENTRY, SUMA_Get_Incident(), SUMA_isSameEdge(), SUMA_RETURN, and SUMA_EDGE_LIST::Tri_limb. Referenced by SUMA_IntersectionStrip().
07485 { static char FuncName[]={"SUMA_FromIntEdgeToIntEdge"};
07486 int Tri2 = 0, cnt, Incident[5], N_Incident;
07487 float dx, dy, dz;
07488 SUMA_Boolean Found, LocalHead = NOPE;
07489
07490 SUMA_ENTRY;
07491
07492 if (Tri < 0 || E1 < 0 || E2 < 0) {
07493 fprintf (SUMA_STDERR, "Error %s: Tri (%d) or E1 (%d) or E2 (%d) is negative!\n", FuncName, Tri, E1, E2);
07494 SUMA_RETURN (NOPE);
07495 }
07496
07497
07498 dx = (SPI->IntersNodes[3*E2] - SPI->IntersNodes[3*E1]);
07499 dy = (SPI->IntersNodes[3*E2+1] - SPI->IntersNodes[3*E1+1]);
07500 dz = (SPI->IntersNodes[3*E2+2] - SPI->IntersNodes[3*E1+2]);
07501 if (LocalHead) {
07502 fprintf (SUMA_STDERR, "%s: Entered - Tri %d, E1 %d [%d %d], E2 %d [%d %d]\n\tdx = %f dy = %f dz = %f\n",
07503 FuncName, Tri, E1, EL->EL[E1][0], EL->EL[E1][1], E2, EL->EL[E2][0], EL->EL[E2][1], dx, dy, dz);
07504 }
07505 *d += sqrt( dx * dx + dy * dy + dz * dz);
07506
07507 if (*d > dmax) {
07508 /* path already longer than Dijkstra path, no need to search further in this direction, get out with this d value */
07509 fprintf (SUMA_STDERR, "%s: Path longer than dmax. Returning.\n", FuncName);
07510 SUMA_RETURN (YUP);
07511 }
07512
07513 if (EL->EL[E2][0] == Ny || EL->EL[E2][1] == Ny) {
07514 fprintf (SUMA_STDERR, "%s: Found Ny, d = %f\n", FuncName, *d);
07515 if (!Visited[Tri]) {
07516 /* add triangle to path */
07517 tPath[*N_tPath] = Tri;
07518 ++*N_tPath;
07519 }
07520 SUMA_RETURN (YUP);
07521 } else if (Visited[Tri]) {
07522 fprintf (SUMA_STDERR, "Error %s: Triangle %d already visited.\n",FuncName, Tri);
07523 SUMA_RETURN (NOPE);
07524 }
07525
07526 /* mark triangle as visited */
07527 if (LocalHead) fprintf (SUMA_STDERR, "%s: Marking triangle %d and adding %dth element to tPath.\n", FuncName, Tri, *N_tPath);
07528 Visited[Tri] = YUP;
07529
07530 /* add triangle to path */
07531 tPath[*N_tPath] = Tri;
07532 ++*N_tPath;
07533
07534 /* now get the second intersected triangle, incident to E2 */
07535 if (LocalHead) fprintf (SUMA_STDERR, "%s: Searching for triangles incident to E2 %d.\n", FuncName, E2);
07536 if (!SUMA_Get_Incident(EL->EL[E2][0], EL->EL[E2][1], EL, Incident, &N_Incident, 1)) {
07537 fprintf (SUMA_STDERR,"Error %s: Failed to get Incident triangles.\n", FuncName);
07538 SUMA_RETURN (NOPE);
07539 }
07540
07541 /* find Tri2 such that Tri2 != Tri and Tri2 is an intersected triangle */
07542 cnt = 0;
07543 Found = NOPE;
07544 while (cnt < N_Incident && !Found) {
07545 if (SPI->isTriHit[Incident[cnt]] && Incident[cnt] != Tri && !Visited[Incident[cnt]]) {
07546 Found = YUP;
07547 Tri2 = Incident[cnt];
07548 }
07549 ++cnt;
07550 }
07551
07552 if (!Found) {
07553 fprintf (SUMA_STDERR,"Error %s: Could not find next triangle.\n", FuncName);
07554 SUMA_RETURN (NOPE);
07555 }
07556
07557 Tri = Tri2;
07558 E1 = E2;
07559
07560 /* now find the new E2 */
07561 if (LocalHead) fprintf (SUMA_STDERR, "%s: Finding new E2.\n", FuncName);
07562
07563 if (!SUMA_isSameEdge (EL, EL->Tri_limb[Tri][0], E1) && SPI->isEdgeInters[EL->Tri_limb[Tri][0]]) {
07564 E2 = EL->Tri_limb[Tri][0];
07565 }else if (!SUMA_isSameEdge (EL, EL->Tri_limb[Tri][1], E1) && SPI->isEdgeInters[EL->Tri_limb[Tri][1]]) {
07566 E2 = EL->Tri_limb[Tri][1];
07567 }else if (!SUMA_isSameEdge (EL, EL->Tri_limb[Tri][2], E1) && SPI->isEdgeInters[EL->Tri_limb[Tri][2]]) {
07568 E2 = EL->Tri_limb[Tri][2];
07569 }else {
07570 fprintf (SUMA_STDERR,"Error %s: No E2 found.\n", FuncName);
07571 SUMA_RETURN (NOPE);
07572 }
07573
07574 /* call the same function again */
07575 if (!SUMA_FromIntEdgeToIntEdge (Tri, E1, E2, EL, SPI, Ny, Visited, d, dmax, tPath, N_tPath)) {
07576 fprintf (SUMA_STDERR,"Error %s: Failed in SUMA_FromIntEdgeToIntEdge.\n", FuncName);
07577 SUMA_RETURN (NOPE);
07578 }
07579
07580 SUMA_RETURN (YUP);
07581 }
|
|
||||||||||||||||
|
a function to find two values a and b such that DA(a) is < 0 and DA(b) is > 0 These two starting points are used for the optimization function SUMA_BinaryZeroSearch
Definition at line 1592 of file SUMA_GeomComp.c. References SUMA_AreaDiffDataStruct::A, a, SUMA_AreaDiffDataStruct::Aref, LocalHead, SUMA_AreaDiffDataStruct::R, SUMA_AreaDiffDataStruct::Rref, SUMA_AreaDiffDataStruct::SO, SUMA_AreaDiffDataStruct::SOref, SUMA_Boolean, SUMA_ENTRY, SUMA_LH, SUMA_Mesh_Area(), SUMA_NewAreaAtRadius(), SUMA_RETURN, SUMA_SL_Err, SUMA_SO_RADIUS, and SUMA_AreaDiffDataStruct::tmpList. Referenced by SUMA_EquateSurfaceAreas().
01593 {
01594 static char FuncName[]={"SUMA_GetAreaDiffRange"};
01595 double a = 0.0, b = 0.0, nat=0, nbt=0, An, Bn;
01596 SUMA_Boolean LocalHead = NOPE;
01597
01598 SUMA_ENTRY;
01599
01600 /* decide on segment range */
01601 fdata->Aref = fabs((double)SUMA_Mesh_Area(fdata->SOref, NULL, -1));
01602 SUMA_SO_RADIUS(fdata->SOref, fdata->Rref);
01603 fdata->A = fabs((double)SUMA_Mesh_Area(fdata->SO, NULL, -1));
01604 SUMA_SO_RADIUS(fdata->SO, fdata->R);
01605
01606 /* a very simple range setting. might very well fail at times */
01607 if (fdata->Aref - fdata->A < 0) {
01608 a = fdata->R; /* choose 'a' such that Aref - A is < 0, Choose b later*/
01609 An = fdata->A;
01610 b = fdata->Rref;
01611 do {
01612 SUMA_LH("Looking for b");
01613 b *= 1.3; /* choose A that Aref - A is > 0 */
01614 Bn = SUMA_NewAreaAtRadius(fdata->SO, b, fdata->Rref, fdata->tmpList);
01615 ++nbt;
01616 } while ( fdata->Aref - Bn < 0 && nbt < 200);
01617 }else{
01618 b = fdata->R; /* choose 'b' such that Aref - A is > 0, Choose a later*/
01619 Bn = fdata->A;
01620 a = fdata->Rref;
01621 do {
01622 SUMA_LH("Looking for a");
01623 a *= 0.7;
01624 An = SUMA_NewAreaAtRadius(fdata->SO, a, fdata->Rref, fdata->tmpList);
01625 ++nat;
01626 } while ( fdata->Aref - An> 0 && nat < 200);
01627 }
01628
01629 *ap = a; *bp = b;
01630
01631 if (nat >= 200 || nbt >= 200) {
01632 SUMA_SL_Err("Failed to find segment.");
01633 SUMA_RETURN(NOPE);
01634 }
01635
01636 if (LocalHead) {
01637 fprintf (SUMA_STDERR,"%s:\nChosen range is [%f %f] with Areas [%f %f], reference Area is %f\n",
01638 FuncName, a, b, An, Bn, fdata->Aref);
01639 }
01640
01641 SUMA_RETURN(YUP);
01642 }
|
|
||||||||||||||||||||||||||||
|
Returns the contour of a patch if you have the patch already created, then pass it in the last argument mode (int) 0: nice contour, not necessarily outermost boundary 1: outermost edge, might look a tad jagged.
Definition at line 5340 of file SUMA_GeomComp.c. References SUMA_EDGE_LIST::EL, SUMA_EDGE_LIST::ELps, SUMA_SurfaceObject::FaceSetList, SUMA_PATCH::FaceSetList, i, LocalHead, SUMA_SurfaceObject::MF, SUMA_CONTOUR_EDGES::n1, SUMA_CONTOUR_EDGES::n2, SUMA_EDGE_LIST::N_EL, SUMA_SurfaceObject::N_FaceSet, SUMA_PATCH::N_FaceSet, SUMA_SurfaceObject::N_Node, SUMA_PATCH::nHits, SUMA_SurfaceObject::NodeList, SUMA_Boolean, SUMA_calloc, SUMA_ENTRY, SUMA_free, SUMA_free_Edge_List(), SUMA_freePatch(), SUMA_getPatch(), SUMA_LH, SUMA_Make_Edge_List_eng(), SUMA_malloc, SUMA_realloc, SUMA_RETURN, SUMA_Show_Edge_List(), SUMA_ShowPatch(), SUMA_SL_Err, SUMA_SLP_Crit, and SUMA_SLP_Err. Referenced by SUMA_1DROI_to_DrawnROI(), SUMA_FinishedROI(), and SUMA_Pattie_Volume().
05341 {
05342 static char FuncName[]={"SUMA_GetContour"};
05343 SUMA_EDGE_LIST * SEL=NULL;
05344 SUMA_PATCH *Patch = NULL;
05345 int i, Tri, Tri1, Tri2, sHits;
05346 SUMA_CONTOUR_EDGES *CE = NULL;
05347 SUMA_Boolean *isNode=NULL;
05348 SUMA_Boolean LocalHead = NOPE;
05349
05350 SUMA_ENTRY;
05351
05352 *N_ContEdges = -1;
05353
05354 /* get the Node member structure if needed*/
05355 if (!SO->MF) {
05356 SUMA_SLP_Err("Member FaceSet not created.\n");
05357 SUMA_RETURN(CE);
05358 }
05359
05360 /* create a flag vector of which node are in Nodes */
05361 isNode = (SUMA_Boolean *) SUMA_calloc(SO->N_Node, sizeof(SUMA_Boolean));
05362 if (!isNode) {
05363 SUMA_SLP_Crit("Failed to allocate for isNode");
05364 SUMA_RETURN(CE);
05365 }
05366
05367 for (i=0; i < N_Node; ++i) isNode[Nodes[i]] = YUP;
05368
05369 if (UseThisPatch) {
05370 SUMA_LH("Using passed patch");
05371 Patch = UseThisPatch;
05372 } else {
05373 SUMA_LH("Creating patch");
05374 switch (ContourMode) {
05375 case 0:
05376 Patch = SUMA_getPatch (Nodes, N_Node, SO->FaceSetList, SO->N_FaceSet, SO->MF, 2);
05377 break;
05378 case 1:
05379 Patch = SUMA_getPatch (Nodes, N_Node, SO->FaceSetList, SO->N_FaceSet, SO->MF, 1);
05380 break;
05381 default:
05382 SUMA_SL_Err("Bad contour mode"); SUMA_RETURN(NULL);
05383 break;
05384 }
05385 }
05386 if (LocalHead) SUMA_ShowPatch (Patch,NULL);
05387
05388 if (Patch->N_FaceSet) {
05389 SEL = SUMA_Make_Edge_List_eng (Patch->FaceSetList, Patch->N_FaceSet, SO->N_Node, SO->NodeList, 0, NULL);
05390
05391 if (0 && LocalHead) SUMA_Show_Edge_List (SEL, NULL);
05392 /* allocate for maximum */
05393 CE = (SUMA_CONTOUR_EDGES *) SUMA_malloc(SEL->N_EL * sizeof(SUMA_CONTOUR_EDGES));
05394 if (!CE) {
05395 SUMA_SLP_Crit("Failed to allocate for CE");
05396 SUMA_RETURN(CE);
05397 }
05398
05399 switch (ContourMode) {
05400 case 0: /* a pretty contour, edges used here may not be the outermost of the patch */
05401 /* edges that are part of unfilled triangles are good */
05402 i = 0;
05403 *N_ContEdges = 0;
05404 while (i < SEL->N_EL) {
05405 if (SEL->ELps[i][2] == 2) {
05406 Tri1 = SEL->ELps[i][1];
05407 Tri2 = SEL->ELps[i+1][1];
05408 sHits = Patch->nHits[Tri1] + Patch->nHits[Tri2];
05409 if (sHits == 5 || sHits == 4) { /* one tri with 3 hits and one with 2 hits or 2 Tris with 2 hits each */
05410 /* Pick edges that are part of only one triangle with three hits */
05411 /* or two triangles with two hits */
05412 /* There's one more condition, both nodes have to be a part of the original list */
05413 if (isNode[SEL->EL[i][0]] && isNode[SEL->EL[i][1]]) {
05414 CE[*N_ContEdges].n1 = SEL->EL[i][0];
05415 CE[*N_ContEdges].n2 = SEL->EL[i][1];
05416 ++ *N_ContEdges;
05417
05418 if (LocalHead) {
05419 fprintf (SUMA_STDERR,"%s: Found edge made up of nodes [%d %d]\n",
05420 FuncName, SEL->EL[i][0], SEL->EL[i][1]);
05421 }
05422 }
05423 }
05424 }
05425
05426 if (SEL->ELps[i][2] > 0) {
05427 i += SEL->ELps[i][2];
05428 } else {
05429 i ++;
05430 }
05431 }
05432 break;
05433 case 1: /* outermost contour, not pretty, but good for getting the outermost edge */
05434 i = 0;
05435 *N_ContEdges = 0;
05436 while (i < SEL->N_EL) {
05437 if (SEL->ELps[i][2] == 1) {
05438 CE[*N_ContEdges].n1 = SEL->EL[i][0];
05439 CE[*N_ContEdges].n2 = SEL->EL[i][1];
05440 ++ *N_ContEdges;
05441 if (LocalHead) {
05442 fprintf (SUMA_STDERR,"%s: Found edge made up of nodes [%d %d]\n",
05443 FuncName, SEL->EL[i][0], SEL->EL[i][1]);
05444 }
05445 }
05446 if (SEL->ELps[i][2] > 0) {
05447 i += SEL->ELps[i][2];
05448 } else {
05449 i ++;
05450 }
05451 }
05452 break;
05453 default:
05454 SUMA_SL_Err("Bad ContourMode");
05455 SUMA_RETURN(NULL);
05456 break;
05457 }
05458
05459 /* Now reallocate */
05460 if (! *N_ContEdges) {
05461 SUMA_free(CE); CE = NULL;
05462 SUMA_RETURN(CE);
05463 }else {
05464 CE = (SUMA_CONTOUR_EDGES *) SUMA_realloc (CE, *N_ContEdges * sizeof(SUMA_CONTOUR_EDGES));
05465 if (!CE) {
05466 SUMA_SLP_Crit("Failed to reallocate for CE");
05467 SUMA_RETURN(CE);
05468 }
05469 }
05470
05471 SUMA_free_Edge_List (SEL);
05472 }
05473
05474 if (!UseThisPatch) {
05475 SUMA_freePatch (Patch);
05476 }
05477 Patch = NULL;
05478
05479 SUMA_free(isNode);
05480
05481 SUMA_RETURN(CE);
05482 }
|
|
||||||||||||
|
a function to turn the often cumbersome SUMA_GET_OFFSET_STRUCT to a more friendly SUMA_OFFSET_STRUCT
Definition at line 2563 of file SUMA_GeomComp.c. References SUMA_GET_OFFSET_STRUCT::layers, LocalHead, SUMA_GET_OFFSET_STRUCT::N_layers, SUMA_OFFSET_STRUCT::N_Neighb, SUMA_NODE_NEIGHB_LAYER::N_NodesInLayer, SUMA_OFFSET_STRUCT::Neighb_dist, SUMA_OFFSET_STRUCT::Neighb_ind, SUMA_NODE_NEIGHB_LAYER::NodesInLayer, SUMA_GET_OFFSET_STRUCT::OffVect, SUMA_Boolean, SUMA_ENTRY, SUMA_malloc, SUMA_RETURN, SUMA_SL_Crit, and SUMA_SL_Err. Referenced by SUMA_ClusterCenterofMass().
02564 {
02565 static char FuncName[]={"SUMA_GetOffset2Offset"};
02566 int il, jl, noffs;
02567 SUMA_Boolean LocalHead = NOPE;
02568
02569 SUMA_ENTRY;
02570
02571 if (!GOS || !OS) {
02572 SUMA_SL_Err("NULL input"); SUMA_RETURN(NOPE);
02573 }
02574
02575 OS->N_Neighb = 0;
02576 for (il=1; il<GOS->N_layers; ++il) {
02577 OS->N_Neighb += GOS->layers[il].N_NodesInLayer;
02578 }
02579 OS->Neighb_ind = (int *)SUMA_malloc(OS->N_Neighb * sizeof(int));
02580 OS->Neighb_dist = (float *)SUMA_malloc(OS->N_Neighb * sizeof(float));
02581 if (!OS->Neighb_ind || !OS->Neighb_dist) {
02582 SUMA_SL_Crit("Failed to allocate.");
02583 SUMA_RETURN(NOPE);
02584 }
02585
02586 noffs = 0;
02587 for (il=1; il<GOS->N_layers; ++il) {
02588 for (jl=0; jl<GOS->layers[il].N_NodesInLayer; ++jl) {
02589 OS->Neighb_ind[noffs] = GOS->layers[il].NodesInLayer[jl];
02590 OS->Neighb_dist[noffs] = GOS->OffVect[OS->Neighb_ind[noffs]];
02591 ++noffs;
02592 }
02593 }
02594
02595 SUMA_RETURN(YUP);
02596 }
|
|
||||||||||||||||||||
|
Definition at line 682 of file SUMA_GeomComp.c. References SUMA_SurfaceObject::EL, SUMA_NODE_FIRST_NEIGHB::FirstNeighb, SUMA_SurfaceObject::FN, i, SUMA_EDGE_LIST::Le, LocalHead, SUMA_NODE_FIRST_NEIGHB::N_Neighb, SUMA_Boolean, SUMA_ENTRY, SUMA_FindEdge(), SUMA_RETURN, and SUMA_SL_Err.
00683 {
00684 static char FuncName[]={"SUMA_getoffsets"};
00685 int i, ni, iseg;
00686 float Off_tmp;
00687 SUMA_Boolean Visit = NOPE;
00688 static SUMA_Boolean LocalHead = NOPE;
00689
00690 SUMA_ENTRY;
00691
00692 #if DoCheck
00693 if (!SO->FN || !SO->EL) {
00694 SUMA_SL_Err("SO->FN &/| SO->EL are NULL.\n");
00695 SUMA_RETURN(NOPE);
00696 }
00697 #endif
00698
00699 #if DBG
00700 if (LocalHead) fprintf(SUMA_STDERR,"%s: Working node %d, %d neighbs. lim = %f\n",
00701 FuncName, n, SO->FN->N_Neighb[n], lim);
00702 #endif
00703
00704 for (i=0; i < SO->FN->N_Neighb[n]; ++i) {
00705 ni = SO->FN->FirstNeighb[n][i]; /* for notational sanity */
00706 iseg = SUMA_FindEdge (SO->EL, n, SO->FN->FirstNeighb[n][i]);
00707 #if DoCheck
00708 if (iseg < 0) {
00709 SUMA_SL_Err("Failed to find segment");
00710 SUMA_RETURN(NOPE);
00711 }
00712 #endif
00713
00714 Off_tmp = Off[n] + SO->EL->Le[iseg]; /* that is the distance from n (original n) to ni along
00715 that particular path */
00716
00717 Visit = NOPE;
00718 if (Off[ni] < 0 || Off_tmp < Off[ni]) { /* Distance improvement, visit/revist that node */
00719 if (Off_tmp < lim) { /* only record if less than lim */
00720 Visit = YUP;
00721 Off[ni] = Off_tmp;
00722 }
00723 }
00724
00725 #if DBG
00726 if (LocalHead) fprintf(SUMA_STDERR,"%s: %d --> %d. Visit %d, Current %f, Old %f\n",
00727 FuncName, n, ni, Visit, Off_tmp, Off[ni]);
00728 #endif
00729
00730 #if 0
00731 { int jnk; fprintf(SUMA_STDOUT,"Pausing ..."); jnk = getchar(); fprintf(SUMA_STDOUT,"\n"); }
00732 #endif
00733
00734 if (Visit) { /* a new node has been reached with an offset less than limit, go down that road */
00735 if (!SUMA_getoffsets (ni, SO, Off, lim)) {
00736 SUMA_SL_Err("Failed in SUMA_getoffsets");
00737 SUMA_RETURN (NOPE);
00738 }
00739 }
00740 }
00741
00742 SUMA_RETURN(YUP);
00743 }
|
|
||||||||||||||||||||||||||||
|
A function to calculate the geodesic distance of nodes connected to node n SUMA_getoffsets was the first incarnation but it was too slow. ans = SUMA_getoffsets2 (n, SO, lim, OffS, CoverThisNode, N_CoverThisNode).
static int SEG_METHOD; switch (SEG_METHOD) { case CALC_SEG: this is the slow part, too many redundant computations. cuts computation time by a factor > 3 if Seg was set to a constant However, attempts at accessing pre-calculated segment lengths proved to be slower. SUMA_SEG_LENGTH (a, b, Seg); break; case FIND_EDGE_MACRO: this one's even slower, calculations have been made once but function calls are costly (7.53 min) iseg = -1; if (n_k < n_jne) {SUMA_FIND_EDGE (SO->EL, n_k, n_jne, iseg);} else {SUMA_FIND_EDGE (SO->EL, n_jne, n_k, iseg);} if (iseg < 0) { SUMA_SL_Err("Segment not found.\nSetting Seg = 10000.0"); Seg = 10000.0; } else Seg = SO->EL->Le[iseg]; break; case FIND_EDGE: this one's even slower, calculations have been made once but function calls are costly iseg = SUMA_FindEdge (SO->EL, n_k, n_jne); Seg = SO->EL->Le[iseg]; break; case DIST_FIRST_NEIGHB: consumes memory but might be faster than previous 2 (5.22 min) Seg = DistFirstNeighb[n_jne][k]; break; case CONST: 1.7 min Seg = 1.0; break; default: SUMA_SL_Err("Bad option"); break; } Definition at line 1050 of file SUMA_GeomComp.c. References a, SUMA_NODE_FIRST_NEIGHB::FirstNeighb, SUMA_SurfaceObject::FN, SUMA_GET_OFFSET_STRUCT::layers, SUMA_GET_OFFSET_STRUCT::LayerVect, LocalHead, SUMA_NODE_FIRST_NEIGHB::N_Neighb, SUMA_NODE_NEIGHB_LAYER::N_NodesInLayer, SUMA_SurfaceObject::NodeList, SUMA_NODE_NEIGHB_LAYER::NodesInLayer, SUMA_GET_OFFSET_STRUCT::OffVect, SUMA_AddNodeToLayer(), SUMA_Boolean, SUMA_ENTRY, SUMA_Free_getoffsets(), SUMA_RETURN, SUMA_SEG_LENGTH_SQ, SUMA_SL_Crit, and SUMA_SL_Err. Referenced by calcWithOffsets(), SUMA_Build_Cluster_From_Node(), SUMA_Build_Cluster_From_Node_NoRec(), SUMA_ClusterCenterofMass(), SUMA_EquateSurfaceSize(), and SUMA_FormNeighbOffset().
01051 {
01052 static char FuncName[]={"SUMA_getoffsets2"};
01053 int LayInd, il, n_il, n_jne, k, n_prec = -1, n_k, jne, iseg=0;
01054 float Off_tmp, Seg, *a, *b, minSeg, SegPres; /*! *** SegPres added Jul 08 04, ZSS bug before ... */
01055 SUMA_Boolean Visit = NOPE;
01056 SUMA_Boolean AllDone = NOPE;
01057 static SUMA_Boolean LocalHead = NOPE;
01058
01059 SUMA_ENTRY;
01060
01061 if (!OffS) {
01062 SUMA_SL_Err("NULL OffS");
01063 SUMA_RETURN(NOPE);
01064 }
01065
01066 /* setup 0th layer */
01067 OffS->OffVect[n] = 0.0; /* n is at a distance 0.0 from itself */
01068 OffS->LayerVect[n] = 0; /* n is on the zeroth layer */
01069 OffS->layers[0].N_NodesInLayer = 1;
01070 OffS->layers[0].NodesInLayer[0] = n;
01071 if (CoverThisNode) {
01072 if (CoverThisNode[n]) {
01073 CoverThisNode[n] = 0; --N_CoverThisNode;
01074 }
01075 }
01076 LayInd = 1; /* index of next layer to build */
01077 AllDone = NOPE;
01078 while (!AllDone) {
01079
01080 AllDone = YUP; /* assume that this would be the last layer */
01081 for (il=0; il < OffS->layers[LayInd - 1].N_NodesInLayer; ++il) { /* go over all nodes in previous layer */
01082 n_il = OffS->layers[LayInd - 1].NodesInLayer[il]; /* node from previous layer */
01083 for (jne=0; jne < SO->FN->N_Neighb[n_il]; ++jne) { /* go over all the neighbours of node n_il */
01084 n_jne = SO->FN->FirstNeighb[n_il][jne]; /* node that is an immediate neighbor to n_il */
01085 if (OffS->LayerVect[n_jne] < 0) { /* node is not assigned to a layer yet */
01086 OffS->LayerVect[n_jne] = LayInd; /* assign new layer index to node */
01087 OffS->OffVect[n_jne] = 0.0; /* reset its distance from node n */
01088 SUMA_AddNodeToLayer (n_jne, LayInd, OffS); /* add the node to the nodes in the layer */
01089 minSeg = 100000.0;
01090 n_prec = -1;
01091 Seg = 0.0;
01092 SegPres = 0.0;
01093 for (k=0; k < SO->FN->N_Neighb[n_jne]; ++k) { /* calculate shortest distance of node to any precursor */
01094 n_k = SO->FN->FirstNeighb[n_jne][k];
01095 if (OffS->LayerVect[n_k] == LayInd - 1) { /* this neighbor is a part of the previous layer, good */
01096 if (n_prec < 0) n_prec = SO->FN->FirstNeighb[n_jne][0];
01097 a = &(SO->NodeList[3*n_k]); b = &(SO->NodeList[3*n_jne]);
01098 /* this is the slow part, too many redundant computations.
01099 Computation time is cut by a factor > 2 if Seg was set to a constant
01100 However, attempts at accessing pre-calculated segment lengths
01101 proved to be slower. See Comments in function help*/
01102 SUMA_SEG_LENGTH_SQ (a, b, Seg);
01103 if (OffS->OffVect[n_prec] + Seg < minSeg) {
01104 minSeg = Seg + OffS->OffVect[n_prec];
01105 SegPres = Seg;
01106 n_prec = n_k;
01107 }
01108 }
01109 }/* for k */
01110
01111 if (n_prec < 0) { /* bad news */
01112 SUMA_SL_Crit("No precursor found for node.");
01113 OffS = SUMA_Free_getoffsets (OffS);
01114 SUMA_RETURN(NOPE);
01115 } else {
01116 OffS->OffVect[n_jne] = OffS->OffVect[n_prec] + sqrt(SegPres); SegPres = 0.0;
01117 if (!CoverThisNode) {
01118 if (OffS->OffVect[n_jne] < lim) { /* must go at least one more layer */
01119 AllDone = NOPE;
01120 }
01121 } else {
01122 if (CoverThisNode[n_jne]) {
01123 CoverThisNode[n_jne] = 0; --N_CoverThisNode;
01124 }
01125 if (N_CoverThisNode > 0) {
01126 AllDone = NOPE;
01127 }
01128 }
01129 }
01130 } /* node not already in layer */
01131
01132 } /* for jne */
01133
01134 } /* for il */
01135 ++LayInd;
01136 } /* while AllDone */
01137
01138 SUMA_RETURN(YUP);
01139 }
|
|
||||||||||||||||||||||||
|
Definition at line 1192 of file SUMA_GeomComp.c. References a, DListElmt_::data, dlist_init(), dlist_ins_next(), dlist_tail, SUMA_NODE_FIRST_NEIGHB::FirstNeighb, SUMA_SurfaceObject::FN, SUMA_OFFSET_LL_DATUM::layer, LocalHead, SUMA_NODE_FIRST_NEIGHB::N_Neighb, DListElmt_::next, SUMA_OFFSET_LL_DATUM::ni, SUMA_SurfaceObject::NodeList, SUMA_OFFSET_LL_DATUM::off, SUMA_BEGINNING_OF_LAYER, SUMA_Boolean, SUMA_ENTRY, SUMA_FIND_ELMENT_FOR_NODE, SUMA_Free_Offset_ll_Datum(), SUMA_LH, SUMA_malloc, SUMA_New_Offset_ll_Datum(), SUMA_RETURN, SUMA_SEG_LENGTH_SQ, SUMA_SL_Crit, and SUMA_SL_Err. Referenced by SUMA_Build_Cluster_From_Node().
01193 {
01194 static char FuncName[]={"SUMA_getoffsets_ll"};
01195 int LayInd, il, n_il, n_jne, k, n_prec = -1, n_k, jne, iseg=0;
01196 float Off_tmp, Seg, *a, *b, minSeg, SegPres; /*! *** SegPres added Jul 08 04, ZSS bug before ... */
01197 SUMA_Boolean Visit = NOPE;
01198 SUMA_Boolean AllDone = NOPE;
01199 SUMA_OFFSET_LL_DATUM * n_dat = NULL, *dat = NULL, *dat_nk = NULL, *dat_prec = NULL, *dat_ne=NULL;
01200 DList *list = NULL;
01201 DListElmt *elm = NULL, *elm_prec = NULL, *elm_ne=NULL, *elm_nk=NULL;
01202 static SUMA_Boolean LocalHead = NOPE;
01203
01204 SUMA_ENTRY;
01205
01206
01207 /* create the list */
01208 SUMA_LH("Initializing list ...");
01209 list = (DList *)SUMA_malloc(sizeof(DList));
01210 dlist_init(list, SUMA_Free_Offset_ll_Datum);
01211
01212 /* setup 0th layer */
01213 SUMA_LH("New OffsetDatum");
01214 n_dat = SUMA_New_Offset_ll_Datum(n, 0);
01215 n_dat->off = 0.0; /* n is at a distance 0.0 from itself */
01216 dlist_ins_next(list, dlist_tail(list), (void*)n_dat);
01217
01218 if (CoverThisNode) {
01219 if (CoverThisNode[n]) {
01220 CoverThisNode[n] = 0; --N_CoverThisNode;
01221 }
01222 }
01223 LayInd = 1; /* index of next layer to build */
01224 AllDone = NOPE;
01225 while (!AllDone) {
01226 AllDone = YUP; /* assume that this would be the last layer */
01227 elm = NULL;
01228 do {
01229 if (!elm) { SUMA_BEGINNING_OF_LAYER(list, (LayInd-1), elm); }
01230 else elm = elm->next;
01231 if (!elm) {
01232 SUMA_SL_Err("Could not find beginning of layer!");
01233 SUMA_RETURN(NULL);
01234 }
01235 dat = (SUMA_OFFSET_LL_DATUM *)elm->data;
01236 if (dat->layer == LayInd -1) {
01237 n_il = dat->ni;
01238 for (jne=0; jne < SO->FN->N_Neighb[n_il]; ++jne) { /* go over all the neighbours of node n_il */
01239 n_jne = SO->FN->FirstNeighb[n_il][jne]; /* node that is an immediate neighbor to n_il */
01240 SUMA_FIND_ELMENT_FOR_NODE(list, n_jne, elm_ne);
01241 if (!elm_ne) { /* node not in any layer */
01242 dat_ne = SUMA_New_Offset_ll_Datum(n_jne, LayInd); /* create an element for it */
01243 dat_ne->off = 0.0;
01244 dlist_ins_next(list, dlist_tail(list), (void*)dat_ne);
01245 minSeg = 100000.0;
01246 n_prec = -1;
01247 Seg = 0.0;
01248 SegPres = 0.0;
01249 for (k=0; k < SO->FN->N_Neighb[n_jne]; ++k) { /* calculate shortest distance of node to any precursor */
01250 n_k = SO->FN->FirstNeighb[n_jne][k];
01251 SUMA_FIND_ELMENT_FOR_NODE(list, n_k, elm_nk);
01252 if (n_prec < 0 && elm_nk) {
01253 n_prec = n_k; elm_prec = elm_nk;
01254 dat_prec = (SUMA_OFFSET_LL_DATUM *)elm_prec->data;
01255 }
01256 if (elm_nk) {
01257 dat_nk = (SUMA_OFFSET_LL_DATUM *)elm_nk->data;
01258 if (dat_nk->layer == LayInd - 1) { /* this neighbor is a part of the previous layer, good */
01259 a = &(SO->NodeList[3*n_k]); b = &(SO->NodeList[3*n_jne]);
01260 /* this is the slow part, too many redundant computations.
01261 Computation time is cut by a factor > 2 if Seg was set to a constant
01262 However, attempts at accessing pre-calculated segment lengths
01263 proved to be slower. See Comments in function help*/
01264 SUMA_SEG_LENGTH_SQ (a, b, Seg);
01265 if (dat_prec->off + Seg < minSeg) {
01266 minSeg = Seg + dat_prec->off;
01267 SegPres = Seg;
01268 n_prec = n_k;
01269 elm_prec = elm_nk;
01270 dat_prec = dat_nk;
01271 }
01272 }
01273 } /* if elm_nk */
01274 }/* for k */
01275 if (n_prec < 0) { /* bad news */
01276 SUMA_SL_Crit("No precursor found for node.");
01277 SUMA_RETURN(NULL);
01278 } else {
01279 dat_ne->off = dat_prec->off + sqrt(SegPres); SegPres = 0.0;
01280 if (!CoverThisNode) {
01281 if (dat_ne->off < lim) { /* must go at least one more layer */
01282 AllDone = NOPE;
01283 }
01284 } else {
01285 if (CoverThisNode[n_jne]) {
01286 CoverThisNode[n_jne] = 0; --N_CoverThisNode;
01287 }
01288 if (N_CoverThisNode > 0) {
01289 AllDone = NOPE;
01290 }
01291 }
01292 }
01293 } /* if elm_ne */
01294 } /* for jne */
01295 } /* dat->layer == LayInd */
01296 } while (dat->layer == (LayInd-1) && elm != dlist_tail(list));
01297
01298 ++LayInd;
01299 } /* while AllDone */
01300
01301 SUMA_RETURN(list);
01302 }
|
|
||||||||||||||||||||||||||||
|
Given a set of node indices, return a patch of the original surface that contains them Patch = SUMA_getPatch (NodesSelected, N_Nodes, Full_FaceSetList, N_Full_FaceSetList, Memb, MinHits)
Definition at line 5223 of file SUMA_GeomComp.c. References SUMA_PATCH::FaceSetIndex, SUMA_PATCH::FaceSetList, i, SUMA_PATCH::N_FaceSet, SUMA_MEMBER_FACE_SETS::N_Memb, SUMA_PATCH::nHits, SUMA_MEMBER_FACE_SETS::NodeMemberOfFaceSet, SUMA_calloc, SUMA_ENTRY, SUMA_free, SUMA_malloc, and SUMA_RETURN. Referenced by main(), SUMA_GetContour(), and SUMA_Pattie_Volume().
05226 {
05227 int * BeenSelected;
05228 int i, j, node, ip, ip2, NP;
05229 SUMA_PATCH *Patch;
05230 static char FuncName[]={"SUMA_getPatch"};
05231
05232 SUMA_ENTRY;
05233
05234 NP = 3;
05235 BeenSelected = (int *)SUMA_calloc (N_Full_FaceSetList, sizeof(int));
05236 Patch = (SUMA_PATCH *)SUMA_malloc(sizeof(SUMA_PATCH));
05237
05238 if (!BeenSelected || !Patch) {
05239 fprintf (SUMA_STDERR,"Error %s: Could not allocate for BeenSelected or patch.\n", FuncName);
05240 SUMA_RETURN(NULL);
05241 }
05242 /* find out the total number of facesets these nodes are members of */
05243 Patch->N_FaceSet = 0; /* total number of facesets containing these nodes */
05244 for (i=0; i < N_Nodes; ++i) {
05245 node = NodesSelected[i];
05246 for (j=0; j < Memb->N_Memb[node]; ++j) {
05247 if (!BeenSelected[Memb->NodeMemberOfFaceSet[node][j]]) {
05248 /* this faceset has not been selected, select it */
05249 ++ Patch->N_FaceSet;
05250 }
05251 ++ BeenSelected[Memb->NodeMemberOfFaceSet[node][j]];
05252 }
05253 }
05254
05255 /* now load these facesets into a new matrix */
05256
05257 Patch->FaceSetList = (int *) SUMA_calloc (Patch->N_FaceSet * 3, sizeof(int));
05258 Patch->FaceSetIndex = (int *) SUMA_calloc (Patch->N_FaceSet, sizeof(int));
05259 Patch->nHits = (int *) SUMA_calloc (Patch->N_FaceSet, sizeof(int));
05260
05261 if (!Patch->FaceSetList || !Patch->FaceSetIndex || !Patch->nHits) {
05262 fprintf (SUMA_STDERR,"Error %s: Could not allocate for Patch->FaceSetList || Patch_FaceSetIndex.\n", FuncName);
05263 SUMA_RETURN(NULL);
05264 }
05265
05266 j=0;
05267 for (i=0; i < N_Full_FaceSetList; ++i) {
05268 if (BeenSelected[i] >= MinHits) {
05269 Patch->nHits[j] = BeenSelected[i];
05270 Patch->FaceSetIndex[j] = i;
05271 ip = NP * j;
05272 ip2 = NP * i;
05273 Patch->FaceSetList[ip] = Full_FaceSetList[ip2];
05274 Patch->FaceSetList[ip+1] = Full_FaceSetList[ip2+1];
05275 Patch->FaceSetList[ip+2] = Full_FaceSetList[ip2+2];
05276 ++j;
05277 }
05278 }
05279
05280 /* reset the numer of facesets because it might have changed given the MinHits condition,
05281 It won't change if MinHits = 1.
05282 It's OK not to change the allocated space as long as you are using 1D arrays*/
05283 Patch->N_FaceSet = j;
05284
05285 if (BeenSelected) SUMA_free(BeenSelected);
05286
05287 SUMA_RETURN(Patch);
05288 }
|
|
||||||||||||||||
|
a function to find two values a and b such that DV(a) is < 0 and DV(b) is > 0 These two starting points are used for the optimization function SUMA_BinaryZeroSearch
Definition at line 1649 of file SUMA_GeomComp.c. References a, LocalHead, SUMA_VolDiffDataStruct::R, SUMA_VolDiffDataStruct::Rref, SUMA_VolDiffDataStruct::SO, SUMA_VolDiffDataStruct::SOref, SUMA_Boolean, SUMA_ENTRY, SUMA_LH, SUMA_Mesh_Volume(), SUMA_NewVolumeAtRadius(), SUMA_RETURN, SUMA_SL_Err, SUMA_SO_RADIUS, SUMA_VolDiffDataStruct::tmpList, SUMA_VolDiffDataStruct::V, and SUMA_VolDiffDataStruct::Vref. Referenced by SUMA_EquateSurfaceVolumes().
01650 {
01651 static char FuncName[]={"SUMA_GetVolDiffRange"};
01652 double a = 0.0, b = 0.0, nat=0, nbt=0;
01653 SUMA_Boolean LocalHead = NOPE;
01654
01655 SUMA_ENTRY;
01656
01657 /* decide on segment range */
01658 fdata->Vref = fabs((double)SUMA_Mesh_Volume(fdata->SOref, NULL, -1));
01659 SUMA_SO_RADIUS(fdata->SOref, fdata->Rref);
01660 fdata->V = fabs((double)SUMA_Mesh_Volume(fdata->SO, NULL, -1));
01661 SUMA_SO_RADIUS(fdata->SO, fdata->R);
01662
01663 /* a very simple range setting. might very well fail at times */
01664 if (fdata->Vref - fdata->V < 0) {
01665 a = fdata->R; /* choose 'a' such that Vref - V is < 0, Choose b later*/
01666 b = fdata->Rref;
01667 do {
01668 SUMA_LH("Looking for b");
01669 b *= 1.3; ++nbt; /* choose b that Vref - V is > 0 */
01670 } while ( fdata->Vref - SUMA_NewVolumeAtRadius(fdata->SO, b, fdata->Rref, fdata->tmpList) < 0 && nbt < 200);
01671 }else{
01672 b = fdata->R; /* choose 'b' such that Vref - V is > 0, Choose a later*/
01673 a = fdata->Rref;
01674 do {
01675 SUMA_LH("Looking for a");
01676 a *= 0.7; ++nat;
01677 } while ( fdata->Vref - SUMA_NewVolumeAtRadius(fdata->SO, a, fdata->Rref, fdata->tmpList) > 0 && nat < 200);
01678 }
01679
01680 *ap = a; *bp = b;
01681
01682 if (nat >= 200 || nbt >= 200) {
01683 SUMA_SL_Err("Failed to find segment.");
01684 SUMA_RETURN(NOPE);
01685 }
01686
01687 SUMA_RETURN(YUP);
01688 }
|
|
||||||||||||||||||||
|
Function to return a set of voxels that are intersected by a triangle.
Definition at line 199 of file SUMA_GeomComp.c. References SUMA_VOLPAR::dx, SUMA_VOLPAR::dy, SUMA_VOLPAR::dz, SUMA_SurfaceObject::FaceSetDim, SUMA_SurfaceObject::FaceSetList, SUMA_VOLPAR::filecode, SUMA_VOLPAR::Hand, SUMA_VTI::IntersectedVoxels, LocalHead, malloc, n1, n2, SUMA_VTI::N_IntersectedVoxels, SUMA_VTI::N_TriIndex, SUMA_SurfaceObject::NodeDim, SUMA_VOLPAR::nx, SUMA_VOLPAR::ny, nz, SUMA_VOLPAR::nz, p, SUMA_3D_2_1D_index, SUMA_ABS, SUMA_Boolean, SUMA_DIST_FROM_PLANE, SUMA_ENTRY, SUMA_IS_STRICT_NEG, SUMA_isVoxelIntersect_Triangle(), SUMA_malloc, SUMA_realloc, SUMA_RETURN, SUMA_SL_Crit, SUMA_SL_Err, SUMA_SL_Warn, SUMA_TRIANGLE_BOUNDING_BOX, SUMA_VoxelsInBox(), and SUMA_VTI::TriIndex.
00201 {
00202 static char FuncName[]={"SUMA_GetVoxelsIntersectingTriangle"};
00203 int ti, nx, ny, nz, nxy, nxyz, N_inbox, n1, n2, n3, nt, nt3, nijk, nf;
00204 int N_alloc, N_realloc, en, *voxelsijk=NULL, N_voxels1d = 0, *voxels1d = NULL;
00205 int *TriIndex=NULL, N_TriIndex;
00206 float dxyz[3];
00207 float tol_dist = 0; /* A way to fatten up the shell a little bit. Set to 0 if no fat is needed */
00208 float *p1, *p2, *p3, min_v[3], max_v[3], p[3], dist;
00209 FILE *fp=NULL;
00210 SUMA_Boolean LocalHead = YUP;
00211
00212 SUMA_ENTRY;
00213
00214 if (SO->FaceSetDim != 3 || SO->NodeDim != 3) {
00215 SUMA_SL_Err("SO->FaceSetDim != 3 || SO->NodeDim != 3");
00216 SUMA_RETURN(NULL);
00217 }
00218 if (!vti) {
00219 SUMA_SL_Err("vti must be non NULL");
00220 SUMA_RETURN(NULL);
00221 }
00222 if (vti->N_TriIndex <= 0) {
00223 SUMA_SL_Err("vti must be initialized");
00224 SUMA_RETURN(NULL);
00225 }
00226
00227 TriIndex = vti->TriIndex;
00228 N_TriIndex = vti->N_TriIndex;
00229
00230 nx = VolPar->nx; ny = VolPar->ny; nz = VolPar->nz; nxy = nx * ny; nxyz = nx * ny * nz;
00231
00232 if (LocalHead) {
00233 fp = fopen("SUMA_GetVoxelsIntersectingTriangle.1D","w");
00234 if (fp) fprintf(fp, "# Voxels from %s that intersect the triangles \n", VolPar->filecode);
00235 }
00236 /* cycle through all triangles and find voxels that intersect them */
00237 N_alloc = 2000; /* expected maximum number of voxels in triangle's bounding box */
00238 N_realloc = 0;
00239 voxelsijk = (int *)SUMA_malloc(sizeof(int)*N_alloc*3);
00240 if (!voxelsijk) { SUMA_SL_Crit("Failed to Allocate!"); SUMA_RETURN(NULL); }
00241 dxyz[0] = VolPar->dx; dxyz[1] = VolPar->dy; dxyz[2] = VolPar->dz;
00242 for (ti=0; ti<N_TriIndex; ++ti) {
00243 if (LocalHead) fprintf(SUMA_STDERR,"%s: Now processing %dth triangle\n", FuncName, ti);
00244 nf = TriIndex[ti];
00245 if (LocalHead) fprintf(SUMA_STDERR,"\t\tindexed %d, \n", nf);
00246 n1 = SO->FaceSetList[SO->FaceSetDim*nf]; n2 = SO->FaceSetList[SO->FaceSetDim*nf+1]; n3 = SO->FaceSetList[SO->FaceSetDim*nf+2];
00247 if (LocalHead) fprintf(SUMA_STDERR,"\t\tmade up of nodes %d, %d. %d . \n", n1, n2, n3);
00248 /* find the bounding box of the triangle */
00249 p1 = &(NodeIJKlist[3*n1]); p2 = &(NodeIJKlist[3*n2]); p3 = &(NodeIJKlist[3*n3]);
00250 SUMA_TRIANGLE_BOUNDING_BOX(p1, p2, p3, min_v, max_v);
00251
00252 /* quick check of preallocate size of voxelsijk */
00253 en =((int)(max_v[0] - min_v[0] + 5) * (int)(max_v[1] - min_v[1] + 5) * (int)(max_v[2] - min_v[2] + 5));
00254 if ( en > N_alloc) {
00255 ++N_realloc; if (N_realloc > 5) { SUMA_SL_Warn("Reallocating, increase limit to improve speed.\nEither triangles too large or grid too small"); }
00256 N_alloc = 2*en;
00257 voxelsijk = (int *)SUMA_realloc(voxelsijk, 3*N_alloc*sizeof(int));
00258 if (!voxelsijk) { SUMA_SL_Crit("Failed to Allocate!"); SUMA_RETURN(NULL); }
00259 }
00260 /* find the list of voxels inhabiting this box */
00261 N_inbox = 0;
00262 if (!SUMA_VoxelsInBox(voxelsijk, &N_inbox, min_v, max_v)) {
00263 SUMA_SL_Err("Unexpected error!"); SUMA_RETURN(NULL);
00264 }
00265 if (!N_inbox) { SUMA_SL_Err("Unexpected error, no voxels in box!"); SUMA_RETURN(NULL); }
00266 if (N_inbox >= N_alloc) { SUMA_SL_Err("Allocation trouble!"); SUMA_RETURN(NULL); }
00267 if (LocalHead) fprintf(SUMA_STDERR,"\t\t%d nodes in box\n", N_inbox);
00268
00269 /* allocate for 1D indices of voxels intersecting the triangle */
00270 if (voxels1d) {
00271 SUMA_SL_Err("NULL pointer expected here");
00272 SUMA_RETURN(NULL);
00273 }
00274 if (LocalHead) fprintf(SUMA_STDERR,"\t\tShit man, %d nodes in box\n", N_inbox);
00275 voxels1d = (int *)malloc(N_inbox * sizeof(int)); /* Too many SUMA_mallocs keep it simple here, this function is called many many times */
00276 if (LocalHead) fprintf(SUMA_STDERR,"\t\tWTF man, %d nodes in box\n", N_inbox);
00277 N_voxels1d=0;
00278 if (!voxels1d) {
00279 SUMA_SL_Crit("Failed to allocate voxels1d");
00280 SUMA_RETURN(NULL);
00281 }
00282 /* mark these voxels as inside the business */
00283 if (LocalHead) fprintf(SUMA_STDERR,"%s:\t\tabout to process %d voxels\n", FuncName, N_inbox);
00284 for (nt=0; nt < N_inbox; ++nt) {
00285 nt3 = 3*nt;
00286 if (voxelsijk[nt3] < nx && voxelsijk[nt3+1] < ny && voxelsijk[nt3+2] < nz) {
00287 nijk = SUMA_3D_2_1D_index(voxelsijk[nt3], voxelsijk[nt3+1], voxelsijk[nt3+2], nx , nxy);
00288 {
00289 /* what side of the plane is this voxel on ? */
00290 p[0] = (float)voxelsijk[nt3]; p[1] = (float)voxelsijk[nt3+1]; p[2] = (float)voxelsijk[nt3+2];
00291 SUMA_DIST_FROM_PLANE(p1, p2, p3, p, dist);
00292 /* Does voxel contain any of the nodes ? */
00293 if (tol_dist && SUMA_ABS(dist) < tol_dist) dist = tol_dist; /* Fatten the representation a little bit
00294 There are holes in the mask created using
00295 the condition below alone. I am not sure
00296 why that is the case but whatever gap there
00297 is in one plane, results from a thick line in
00298 the other. Don't know if that is a bug yet
00299 or an effect of discretization. At any rate
00300 it should not affect what I plan to do with
00301 this. Could the bug be in
00302 SUMA_isVoxelIntersect_Triangle?*/
00303 if (!(SUMA_IS_STRICT_NEG(VolPar->Hand * dist))) { /* voxel is outside (along normal) */
00304 /* does this triangle actually intersect this voxel ?*/
00305 if (SUMA_isVoxelIntersect_Triangle (p, dxyz, p1, p2, p3)) {
00306 /* looks good, store it */
00307 if (LocalHead) fprintf(SUMA_STDERR,"nt %d, N_voxels1d %d\n", nt, N_voxels1d);
00308 voxels1d[N_voxels1d] = nijk; ++N_voxels1d;
00309 if (fp) fprintf(fp, "%d %d %d\n", voxelsijk[nt3], voxelsijk[nt3+1], voxelsijk[nt3+2]);
00310 }
00311 }
00312
00313 }
00314 }
00315 }
00316 /* store the results */
00317 vti->IntersectedVoxels[ti] = voxels1d;
00318 vti->N_IntersectedVoxels[ti] = N_voxels1d;
00319 voxels1d = NULL; N_voxels1d = 0;
00320 }
00321
00322 if (LocalHead) {
00323 if (fp) fclose(fp); fp = NULL;
00324 }
00325 SUMA_RETURN(vti);
00326 }
|
|
|
Allocate and initialize SUMA_GET_OFFSET_STRUCT* struct OffS = SUMA_Initialize_getoffsets (N_Node);.
Definition at line 758 of file SUMA_GeomComp.c. References i, SUMA_GET_OFFSET_STRUCT::layers, SUMA_GET_OFFSET_STRUCT::LayerVect, SUMA_NODE_NEIGHB_LAYER::N_AllocNodesInLayer, SUMA_GET_OFFSET_STRUCT::N_layers, SUMA_GET_OFFSET_STRUCT::N_Nodes, SUMA_NODE_NEIGHB_LAYER::N_NodesInLayer, SUMA_NODE_NEIGHB_LAYER::NodesInLayer, SUMA_GET_OFFSET_STRUCT::OffVect, SUMA_ENTRY, SUMA_free, SUMA_malloc, SUMA_RETURN, and SUMA_SL_Err. Referenced by calcWithOffsets(), SUMA_Build_Cluster_From_Node(), SUMA_Build_Cluster_From_Node_NoRec(), SUMA_ClusterCenterofMass(), SUMA_EquateSurfaceSize(), and SUMA_FormNeighbOffset().
00759 {
00760 static char FuncName[]={"SUMA_Initialize_getoffsets"};
00761 int i;
00762 SUMA_GET_OFFSET_STRUCT *OffS = NULL;
00763
00764 SUMA_ENTRY;
00765
00766 if (N_Node <= 0) {
00767 SUMA_SL_Err("Bad values for N_Node");
00768 SUMA_RETURN (OffS);
00769 }
00770
00771 OffS = (SUMA_GET_OFFSET_STRUCT *)SUMA_malloc(sizeof(SUMA_GET_OFFSET_STRUCT));
00772 if (!OffS) {
00773 SUMA_SL_Err("Failed to allocate for OffS");
00774 SUMA_RETURN (OffS);
00775 }
00776
00777 OffS->OffVect = (float *) SUMA_malloc(N_Node * sizeof(float));
00778 OffS->LayerVect = (int *) SUMA_malloc(N_Node * sizeof(int));
00779 OffS->N_Nodes = N_Node;
00780
00781 if (!OffS->LayerVect || !OffS->OffVect) {
00782 SUMA_SL_Err("Failed to allocate for OffS->LayerVect &/| OffS->OffVect");
00783 SUMA_free(OffS);
00784 SUMA_RETURN (OffS);
00785 }
00786
00787 /* initialize vectors */
00788 for (i=0; i< N_Node; ++i) {
00789 OffS->OffVect[i] = 0.0;
00790 OffS->LayerVect[i] = -1;
00791 }
00792
00793 /* add a zeroth layer for node n */
00794 OffS->N_layers = 1;
00795 OffS->layers = (SUMA_NODE_NEIGHB_LAYER *) SUMA_malloc(OffS->N_layers * sizeof(SUMA_NODE_NEIGHB_LAYER));
00796 OffS->layers[0].N_AllocNodesInLayer = 1;
00797 OffS->layers[0].NodesInLayer = (int *) SUMA_malloc(OffS->layers[0].N_AllocNodesInLayer * sizeof(int));
00798 OffS->layers[0].N_NodesInLayer = 0;
00799
00800 SUMA_RETURN (OffS);
00801
00802 }
|
|
||||||||||||||||||||||||||||||||
|
This function determines the strip of triangles necessary to go from one node to another along intersected edges. tPath = SUMA_IntersectionStrip (SO, SPI, int *nPath, int N_nPath, float *dinters, float dmax, int *N_tPath).
NOTE: This function can be used to create a node path formed by intersection points along edges but that is not implemented yet.
Definition at line 7284 of file SUMA_GeomComp.c. References SUMA_SurfaceObject::EL, SUMA_EDGE_LIST::EL, SUMA_EDGE_LIST::ELloc, SUMA_EDGE_LIST::ELps, SUMA_SurfaceObject::FaceSetList, SUMA_SURF_PLANE_INTERSECT::isEdgeInters, SUMA_SURF_PLANE_INTERSECT::isTriHit, LocalHead, n2, SUMA_SurfaceObject::N_FaceSet, SUMA_SurfaceObject::N_Node, Nx, SUMA_Boolean, SUMA_calloc, SUMA_ENTRY, SUMA_FindEdgeInTri(), SUMA_free, SUMA_FromIntEdgeToIntEdge(), SUMA_Get_Incident(), SUMA_isSameEdge(), SUMA_RETURN, and SUMA_EDGE_LIST::Tri_limb. Referenced by SUMA_Surf_Plane_Intersect_ROI().
07286 {
07287 static char FuncName[]={"SUMA_IntersectionStrip"};
07288 int *tPath1 = NULL, *tPath2 = NULL, Incident[50], N_Incident, Nx = -1,
07289 Ny = -1, Tri = -1, Tri1 = -1, istart, n2 = -1, n3 = -1, E1, E2, cnt, N_tPath1, N_tPath2;
07290 float d1, d2;
07291 SUMA_Boolean *Visited = NULL, Found, LocalHead = NOPE;
07292
07293 SUMA_ENTRY;
07294
07295 /* find the edge containing the 1st 2 nodes of the Dijkstra path */
07296 /* find the triangle that contains the edge formed by the 1st 2 nodes of the Dijkstra path and is intersected by the plane*/
07297 Tri1 = -1;
07298 if (LocalHead) {
07299 fprintf (SUMA_STDERR, "%s: Looking for a triangle containing nodes [%d %d].\n", FuncName, nPath[0], nPath[1]);
07300 }
07301
07302 Found = SUMA_Get_Incident(nPath[0], nPath[1], SO->EL, Incident, &N_Incident, 1);
07303 if (!Found) {
07304 /* no such triangle, get a triangle that contains nPath[0] and is intersected */
07305 fprintf (SUMA_STDERR, "%s: No triangle contains nodes [%d %d].\n", FuncName, nPath[0], nPath[1]);
07306 if (nPath[0] == SO->N_Node - 1) {
07307 fprintf (SUMA_STDERR, "Warning %s: 1st node is last node of surface, traversing path backwards.\n", FuncName);
07308 Nx = nPath[N_nPath - 1];
07309 Ny = nPath[0];
07310 }else {
07311 Nx = nPath[0];
07312 Ny = nPath[N_nPath - 1];
07313 }
07314 istart = SO->EL->ELloc[Nx];
07315 /* find an edge containing the first node and belonging to an intersected triangle */
07316 Found = NOPE;
07317 while (SO->EL->EL[istart][0] == Nx && !Found) {
07318 Tri = SO->EL->ELps[istart][1];
07319 if (SPI->isTriHit[Tri]) {
07320 Found = YUP;
07321 Tri1 = Tri;
07322 }
07323 ++istart;
07324 }
07325 }else {
07326 Nx = nPath[0];
07327 Ny = nPath[N_nPath - 1];
07328
07329 /* find which of these triangles was intersected */
07330 if (LocalHead) {
07331 fprintf (SUMA_STDERR, "%s: Found %d triangles containing nodes [%d %d].\n", FuncName, N_Incident, nPath[0], nPath[1]);
07332 for (cnt = 0; cnt < N_Incident; ++cnt) fprintf (SUMA_STDERR, "%d isHit %d\n", Incident[cnt], SPI->isTriHit[Incident[cnt]]);
07333 fprintf (SUMA_STDERR, "\n");
07334 }
07335 Found = NOPE;
07336 cnt = 0;
07337 while (cnt < N_Incident && !Found) {
07338 if (SPI->isTriHit[Incident[cnt]]) {
07339 Found = YUP;
07340 Tri1 = Incident[cnt];
07341 }
07342 ++cnt;
07343 }
07344 }
07345
07346 if (!Found) {
07347 fprintf (SUMA_STDERR, "Error %s: Starting Edge could not be found.\n", FuncName);
07348 SUMA_RETURN (NULL);
07349 }else if (LocalHead) {
07350 fprintf (SUMA_STDERR, "%s: Starting with triangle %d.\n", FuncName, Tri1);
07351 }
07352
07353 /* found starting triangle edge, begin with side 1 */
07354 if (SO->FaceSetList[3*Tri1] == Nx) {
07355 n2 = SO->FaceSetList[3*Tri1+1];
07356 n3 = SO->FaceSetList[3*Tri1+2];
07357 } else if (SO->FaceSetList[3*Tri1+1] == Nx) {
07358 n2 = SO->FaceSetList[3*Tri1];
07359 n3 = SO->FaceSetList[3*Tri1+2];
07360 } else if (SO->FaceSetList[3*Tri1+2] == Nx) {
07361 n2 = SO->FaceSetList[3*Tri1];
07362 n3 = SO->FaceSetList[3*Tri1+1];
07363 } else {
07364 fprintf (SUMA_STDERR, "Error %s: Triangle %d does not contain Nx %d.\n", FuncName, Tri1, Nx);
07365 SUMA_RETURN (NULL);
07366 }
07367
07368
07369
07370 E1 = SUMA_FindEdgeInTri (SO->EL, Nx, n2, Tri1);
07371 if (!SPI->isEdgeInters[E1]) {
07372 E1 = SUMA_FindEdgeInTri (SO->EL, Nx, n3, Tri1);
07373 }
07374 /* now choose E2 such that E2 is also intersected */
07375 if (!SUMA_isSameEdge (SO->EL, SO->EL->Tri_limb[Tri1][0], E1) && SPI->isEdgeInters[SO->EL->Tri_limb[Tri1][0]]) {
07376 E2 = SO->EL->Tri_limb[Tri1][0];
07377 }else if (!SUMA_isSameEdge (SO->EL, SO->EL->Tri_limb[Tri1][1], E1) && SPI->isEdgeInters[SO->EL->Tri_limb[Tri1][1]]) {
07378 E2 = SO->EL->Tri_limb[Tri1][1];
07379 }else if (!SUMA_isSameEdge (SO->EL, SO->EL->Tri_limb[Tri1][2], E1) && SPI->isEdgeInters[SO->EL->Tri_limb[Tri1][2]]) {
07380 E2 = SO->EL->Tri_limb[Tri1][2];
07381 }else {
07382 fprintf (SUMA_STDERR,"Error %s: No E2 found.\n", FuncName);
07383 SUMA_RETURN (NULL);
07384 }
07385
07386 Visited = (SUMA_Boolean *) SUMA_calloc (SO->N_FaceSet, sizeof(SUMA_Boolean));
07387 tPath1 = (int *) SUMA_calloc (SO->N_FaceSet, sizeof(int));
07388 if (!Visited || !tPath1) {
07389 fprintf (SUMA_STDERR, "Error %s: Failed to allocate.\n", FuncName);
07390 if (Visited) SUMA_free(Visited);
07391 if (tPath2) SUMA_free(tPath1);
07392 SUMA_RETURN (NULL);
07393 }
07394
07395 N_tPath1 = 0;
07396 if (!SUMA_FromIntEdgeToIntEdge (Tri1, E1, E2, SO->EL, SPI, Ny, Visited, &d1, dmax, tPath1, &N_tPath1)) {
07397 fprintf (SUMA_STDERR, "Error %s: Failed in SUMA_FromIntEdgeToIntEdge.\n", FuncName);
07398 if (Visited) SUMA_free(Visited);
07399 if (tPath2) SUMA_free(tPath1);
07400 SUMA_RETURN (NULL);
07401 }
07402
07403 if (LocalHead) {
07404 fprintf (SUMA_STDERR, "%s: Found a distance of %f.\n\n\n", FuncName, d1);
07405 }
07406
07407 /* Now try going in the other direction, E2->E1 */
07408 cnt = E2;
07409 E2 = E1;
07410 E1 = cnt;
07411
07412 /* reset the values of Visited */
07413 for (cnt=0; cnt < SO->N_FaceSet; ++cnt) if (Visited[cnt]) Visited[cnt] = NOPE;
07414
07415 tPath2 = (int *) SUMA_calloc (SO->N_FaceSet, sizeof(int));
07416 if (!Visited || !tPath2) {
07417 fprintf (SUMA_STDERR, "Error %s: Failed to allocate.\n", FuncName);
07418 if (Visited) SUMA_free(Visited);
07419 if (tPath1) SUMA_free(tPath1);
07420 if (tPath2) SUMA_free(tPath2);
07421 SUMA_RETURN (NULL);
07422 }
07423
07424 N_tPath2 = 0;
07425 if (!SUMA_FromIntEdgeToIntEdge (Tri1, E1, E2, SO->EL, SPI, Ny, Visited, &d2, dmax, tPath2, &N_tPath2)) {
07426 fprintf (SUMA_STDERR, "Error %s: Failed in SUMA_FromIntEdgeToIntEdge.\n", FuncName);
07427 if (Visited) SUMA_free(Visited);
07428 if (tPath1) SUMA_free(tPath1);
07429 if (tPath2) SUMA_free(tPath2);
07430 SUMA_RETURN (NULL);
07431 }
07432
07433 if (Visited) SUMA_free(Visited);
07434
07435 if (LocalHead) {
07436 fprintf (SUMA_STDERR, "%s: Found a distance of %f.\n", FuncName, d2);
07437 }
07438
07439 if (d2 < d1) {
07440 *N_tPath = N_tPath2;
07441 *dinters = d2;
07442 if (tPath1) SUMA_free(tPath1);
07443 SUMA_RETURN (tPath2);
07444 } else {
07445 *dinters = d1;
07446 *N_tPath = N_tPath1;
07447 if (tPath2) SUMA_free(tPath2);
07448 SUMA_RETURN (tPath1);
07449 }
07450
07451 }
|
|
||||||||||||||||
|
determines whether to edges are identical or not. Recall that an edge can be represented multiple times in SO->EL, once for each triangle that uses it. Two edges are the same if and only if EL->EL[E1][0] == EL->EL[E2][0] && EL->EL[E1][1] == EL->EL[E2][1] ans = SUMA_isSameEdge ( EL, E1, E2);
Definition at line 7242 of file SUMA_GeomComp.c. References SUMA_EDGE_LIST::EL, SUMA_Boolean, SUMA_ENTRY, and SUMA_RETURN. Referenced by SUMA_FromIntEdgeToIntEdge(), and SUMA_IntersectionStrip().
07243 {
07244 static char FuncName[]={"SUMA_isSameEdge"};
07245
07246 SUMA_ENTRY;
07247
07248 if (EL->EL[E1][0] == EL->EL[E2][0] && EL->EL[E1][1] == EL->EL[E2][1]) {
07249 SUMA_RETURN (YUP);
07250 } else {
07251 SUMA_RETURN (NOPE);
07252 }
07253
07254 }
|
|
||||||||||||
|
Function to detect surface self intersection returns -1 in case of error, 0 in case of no intersection 1 in case of intersection.
Definition at line 333 of file SUMA_GeomComp.c. References SUMA_SurfaceObject::EL, SUMA_EDGE_LIST::EL, SUMA_EDGE_LIST::ELps, SUMA_SurfaceObject::FaceSetDim, SUMA_SurfaceObject::FaceSetList, SUMA_MT_INTERSECT_TRIANGLE::isHit, LocalHead, n1, n2, SUMA_EDGE_LIST::N_EL, SUMA_SurfaceObject::N_FaceSet, SUMA_SurfaceObject::N_Node, SUMA_SurfaceObject::NodeDim, SUMA_SurfaceObject::NodeList, p, SUMA_Boolean, SUMA_ENTRY, SUMA_Free_MT_intersect_triangle(), SUMA_FROM_BARYCENTRIC, SUMA_LH, SUMA_MIN_PAIR, SUMA_MT_intersect_triangle(), SUMA_RETURN, SUMA_SL_Err, SUMA_MT_INTERSECT_TRIANGLE::u, and SUMA_MT_INTERSECT_TRIANGLE::v.
00334 {
00335 static char FuncName[]={"SUMA_isSelfIntersect"};
00336 float *NodePos = NULL, *p1=NULL, *p2=NULL, *p3 = NULL, p[3], *ep1=NULL, *ep2=NULL;
00337 int hit = 0, k, t1, t2, it, it3, n1, n2, n3;
00338 SUMA_MT_INTERSECT_TRIANGLE *MTI = NULL;
00339 SUMA_Boolean LocalHead = NOPE;
00340
00341 SUMA_ENTRY;
00342
00343 if (!SO->EL) {
00344 SUMA_SL_Err("NULL SO->EL");
00345 SUMA_RETURN(-1);
00346 }
00347
00348 if (StopAt < 1) StopAt = 1;
00349
00350 hit = 0; k = 0;
00351 while (k < SO->EL->N_EL) {
00352 t1 = SO->EL->ELps[k][1]; t2 = SO->EL->ELps[SUMA_MIN_PAIR(k+1, SO->EL->N_EL-1)][1];
00353 ep1 = &(SO->NodeList[3*SO->EL->EL[k][0]]); ep2 = &(SO->NodeList[3*SO->EL->EL[k][1]]);
00354 /* find out if segment intersects */
00355 MTI = SUMA_MT_intersect_triangle(ep1, ep2, SO->NodeList, SO->N_Node, SO->FaceSetList, SO->N_FaceSet, MTI);
00356 for (it=0; it<SO->N_FaceSet; ++it) {
00357 if (MTI->isHit[it] && it != t1 && it != t2) {
00358 /* ray hit triangle, is intersection inside segment ? */
00359 /* SUMA_LH("Checking hit..."); */
00360 it3 = SO->FaceSetDim*it;
00361 n1 = SO->FaceSetList[it3]; n2 = SO->FaceSetList[it3+1]; n3 = SO->FaceSetList[it3+2];
00362 p1 = &(SO->NodeList[SO->NodeDim*n1]); p2 = &(SO->NodeList[SO->NodeDim*n2]); p3 = &(SO->NodeList[SO->NodeDim*n3]);
00363 SUMA_FROM_BARYCENTRIC(MTI->u[it], MTI->v[it], p1, p2, p3, p);
00364 if (p[0] > ep1[0] && p[0] < ep2[0]) {
00365 if (p[1] > ep1[1] && p[1] < ep2[1]) {
00366 if (p[2] > ep1[2] && p[2] < ep2[2]) {
00367 /* point in segment, self intersection detected. */
00368 if (LocalHead) fprintf(SUMA_STDERR,"%s: Triangle %d (%d, %d, %d) was hit by segment formed by nodes [%d, %d]\n",
00369 FuncName, it, n1, n2, n3, SO->EL->EL[k][0], SO->EL->EL[k][1]);
00370 ++ hit;
00371 break;
00372 }
00373 }
00374 }
00375 }
00376 }
00377 if (hit >= StopAt) break;
00378 /* skip duplicate edges */
00379 if (SO->EL->ELps[k][2] > 0) {
00380 k += SO->EL->ELps[k][2];
00381 } else ++k;
00382 }
00383
00384 if (MTI) MTI = SUMA_Free_MT_intersect_triangle(MTI);
00385
00386 if (LocalHead) {
00387 if (!hit) {
00388 SUMA_LH("Surface does not self intersect.");
00389 } else {
00390 SUMA_LH("Surface self intersects.");
00391 }
00392 }
00393 SUMA_RETURN(hit);
00394 }
|
|
||||||||||||||||||||||||||||||||||||
|
Definition at line 6676 of file SUMA_GeomComp.c. References SUMA_EDGE_LIST::EL, SUMA_EDGE_LIST::ELps, LocalHead, SUMA_Boolean, and SUMA_EDGE_LIST::Tri_limb. Referenced by SUMA_AssignTriBranch().
06677 {
06678 static char FuncName[]={"SUMA_Mark_Tri"};
06679 int Tri = -1, Found, k, kedge = 0, E2, Ntri = 0;
06680 static int In = 0;
06681 SUMA_Boolean LocalHead = NOPE;
06682
06683 /* this is a recursive function, you don't want to log every time it is called */
06684 /* SUMA_ENTRY; */
06685
06686 ++In;
06687 if (LocalHead) fprintf (SUMA_STDERR, "%s: Entered #%d.\n", FuncName, In);
06688
06689 /* find the next triangle hosting E1, if possible, otherwise it is the end of the branch. */
06690 if (EL->ELps[E1][2] != 2) { /* reached a dead end , end of branch */
06691 /* mark triangle, remove E1 from list and return */
06692 if (LocalHead) fprintf (SUMA_STDERR, "%s: reached end of branch.\n", FuncName);
06693 kedge = 0;
06694 Found = NOPE;
06695 while (!Found && kedge < *N_IsInter) {
06696 if (IsInter[kedge] == E1) {
06697 Found = YUP;
06698 *N_IsInter = *N_IsInter - 1;
06699 IsInter[kedge] = IsInter[*N_IsInter];
06700 } else ++kedge;
06701 }
06702 return (YUP);
06703 }else {
06704 Tri = EL->ELps[E1][1];
06705 if (TriBranch[Tri]) { /* try second triangle */
06706 Tri = EL->ELps[E1+1][1];
06707 }
06708 if (LocalHead) fprintf (SUMA_STDERR, "%s: moving on to triangle %d.\n", FuncName, Tri);
06709 }
06710
06711 if (!TriBranch[Tri]) {
06712 /* unvisited, mark with iBranch */
06713 TriBranch[Tri] = iBranch;
06714 VisitationOrder[*ivisit] = Tri;
06715 ++(*ivisit);
06716 /* find other edges in this triangle that have been intersected */
06717 Found = NOPE;
06718 k = 0;
06719 while (!Found && k < 3) {
06720 E2 = EL->Tri_limb[Tri][k]; /* this may not be the first occurence of this edge since the list contains duplicates */
06721 if (LocalHead) {
06722 fprintf (SUMA_STDERR, "%s: Trying edge E2 %d (%d %d), tiangle %d, edge %d.\n",
06723 FuncName, E2, EL->EL[E2][0], EL->EL[E2][1], Tri, k);
06724 }
06725 while (EL->ELps[E2][2] < 0) { /* find the first occurence of this edge in the list */
06726 E2--;
06727 }
06728 if (LocalHead) fprintf (SUMA_STDERR, "%s: E2 changed to %d. E1 is %d\n", FuncName, E2, E1);
06729 if (E2 != E1) {
06730 /* was E2 intersected ? */
06731 kedge = 0;
06732 while (!Found && kedge < *N_IsInter) {
06733 if (IsInter[kedge] == E2) {
06734 Found = YUP;
06735 if (LocalHead) fprintf (SUMA_STDERR, "%s: E2 is intersected.\n", FuncName);
06736 }
06737 else ++kedge;
06738 }
06739 }
06740 ++k;
06741 }
06742
06743 if (!Found) {
06744 fprintf (SUMA_STDERR, "Error %s: No second edge found.\n", FuncName);
06745 return (NOPE);
06746 } else {
06747 if (LocalHead) fprintf (SUMA_STDERR, "%s: Removing E2 from List and calling SUMA_Mark_Tri.\n", FuncName);
06748 /* remove this new edge from the list */
06749 *N_IsInter = *N_IsInter - 1;
06750 IsInter[kedge] = IsInter[*N_IsInter];
06751
06752 /* continue visitation */
06753 if (!SUMA_Mark_Tri (EL, E2, iBranch, TriBranch, IsInter, N_IsInter, VisitationOrder, ivisit)) {
06754 fprintf (SUMA_STDERR, "Error %s: Failed in SUMA_Mark_Tri.\n", FuncName);
06755 return (NOPE);
06756 }
06757 return (YUP);
06758 }
06759 } else {
06760 if (TriBranch[Tri] != iBranch) {
06761 fprintf (SUMA_STDERR, "\a%s: Branches colliding, Must weld %d to %d.\n", FuncName, iBranch, TriBranch[Tri]);
06762
06763 /* DO NOT MODIFY THE VALUE OF BRANCH or you will mistakingly link future branches*/
06764 }
06765 /* visited, end of branch return */
06766 if (LocalHead) fprintf (SUMA_STDERR, "%s: End of branch. Returning.\n", FuncName);
06767 return (YUP);
06768 }
06769
06770 fprintf (SUMA_STDERR, "Error %s: Should not be here.\n", FuncName);
06771 return (NOPE);
06772 }
|
|
||||||||||||
|
a function to return a mask indicating if a node is part of a patch or not isNodeInPatch = SUMA_MaskOfNodesInPatch( SUMA_SurfaceObject *SO, int * N_NodesUsedInPatch);
Definition at line 5169 of file SUMA_GeomComp.c. References SUMA_SurfaceObject::FaceSetDim, SUMA_SurfaceObject::FaceSetList, SUMA_SurfaceObject::N_FaceSet, SUMA_SurfaceObject::N_Node, SUMA_Boolean, SUMA_calloc, SUMA_ENTRY, SUMA_RETURN, SUMA_SL_Crit, and SUMA_SL_Err. Referenced by SUMA_FreeSurfer_WritePatch(), and SUMA_PrepSO_GeomProp_GL().
05170 {
05171 static char FuncName[]={"SUMA_MaskOfNodesInPatch"};
05172 int k;
05173 SUMA_Boolean *NodesInPatchMesh = NULL;
05174
05175 SUMA_ENTRY;
05176
05177 *N_NodesUsedInPatch = 0;
05178
05179 if (!SO) {
05180 SUMA_SL_Err("NULL SO");
05181 SUMA_RETURN(NULL);
05182 }
05183 if (!SO->FaceSetList || !SO->N_FaceSet) {
05184 SUMA_SL_Err("NULL or empty SO->FaceSetList");
05185 SUMA_RETURN(NULL);
05186 }
05187
05188 NodesInPatchMesh = (SUMA_Boolean *)SUMA_calloc(SO->N_Node, sizeof(SUMA_Boolean));
05189 if (!NodesInPatchMesh) {
05190 SUMA_SL_Crit("Failed to allocate for NodesInPatchMesh");
05191 SUMA_RETURN(NULL);
05192 }
05193 for (k=0; k<SO->FaceSetDim*SO->N_FaceSet; ++k) {
05194 if (!NodesInPatchMesh[SO->FaceSetList[k]]) {
05195 ++*N_NodesUsedInPatch;
05196 NodesInPatchMesh[SO->FaceSetList[k]] = 1;
05197 }
05198 }
05199
05200 SUMA_RETURN(NodesInPatchMesh);
05201 }
|
|
||||||||||||||||
|
computes the total area of a surface. NOTE: This function will replace whatever values you have in SO->PolyArea. If SO->PolyArea is NULL, it will remain that way.
Definition at line 5820 of file SUMA_GeomComp.c. References a, SUMA_SurfaceObject::FaceSetList, i, LocalHead, n0, n1, n2, SUMA_SurfaceObject::N_FaceSet, SUMA_SurfaceObject::NodeList, SUMA_SurfaceObject::PolyArea, SUMA_Boolean, SUMA_ENTRY, SUMA_RETURN, SUMA_SL_Err, and SUMA_TRI_AREA. Referenced by SUMA_GetAreaDiffRange(), SUMA_NewAreaAtRadius(), and SUMA_StretchToFitLeCerveau().
05821 {
05822 static char FuncName[]={"SUMA_Mesh_Area"};
05823 double A = 0.0, a = 0.0;
05824 int i, i3;
05825 float *n0, *n1, *n2;
05826 SUMA_Boolean LocalHead = NOPE;
05827
05828 SUMA_ENTRY;
05829
05830 if (!SO) { SUMA_SL_Err("NULL SO"); SUMA_RETURN(A); }
05831 if (!SO->FaceSetList) { SUMA_SL_Err("NULL SO->FaceSetList"); SUMA_RETURN(A); }
05832
05833 if (!FaceSets ) {
05834 if (N_FaceSet != -1) {
05835 SUMA_SL_Err("With NULL FaceSets, use -1 for N_FaceSet");
05836 SUMA_RETURN(A);
05837 }
05838 N_FaceSet = SO->N_FaceSet;
05839 FaceSets = SO->FaceSetList;
05840 }else {
05841 if (N_FaceSet < 0) {
05842 SUMA_SL_Err("N_FaceSet < 0");
05843 SUMA_RETURN(A);
05844 }
05845 }
05846
05847 A = 0.0;
05848 if (SO->PolyArea) {
05849 for (i=0; i<N_FaceSet; ++i) {
05850 i3 = 3*i;
05851 n0 = &(SO->NodeList[3*FaceSets[i3]]);
05852 n1 = &(SO->NodeList[3*FaceSets[i3+1]]);
05853 n2 = &(SO->NodeList[3*FaceSets[i3+2]]);
05854 SUMA_TRI_AREA( n0, n1, n2, a);
05855 SO->PolyArea[i] = (float)a;
05856 A += a;
05857 }
05858 } else {
05859 for (i=0; i<N_FaceSet; ++i) {
05860 i3 = 3*i;
05861 n0 = &(SO->NodeList[3*FaceSets[i3]]);
05862 n1 = &(SO->NodeList[3*FaceSets[i3+1]]);
05863 n2 = &(SO->NodeList[3*FaceSets[i3+2]]);
05864 SUMA_TRI_AREA( n0, n1, n2, a);
05865 A += a;
05866 }
05867 }
05868 if (LocalHead) {
05869 fprintf(SUMA_STDERR,"%s:\n A = %f\n", FuncName, A);
05870 }
05871 SUMA_RETURN(A);
05872 }
|
|
||||||||||||||||
|
Calculate the volume of a mesh per the method in Hughes, S.W. et al. Phys. Med. Biol. 1996. Tested with Icosahedron surface (see direct vol computation in CreateIcosahedron) Tested with tetrahedron below, which has a volume of 0.166667 Also, the same volume was obtained with a rotated version of the same tetrahedron TetraFaceSetList.1D 0 1 2 0 3 1 0 2 3 2 1 3 TetraNodeList.1D 0 0 0 1 0 0 0 1 0 1 1 1 which should have a volume of (1/3)A*h of 1/3 * 0.5 * 1 Volume of smoothwm surface did not change if surface was rotated and shifted, a very good thing. If you try to calculate the volume of a boxe's surface with the box's axes in alignment with the X, Y and Z directions, you will get nan for an answer because the sum of the weights is ~= 0 . If you rotate the surface, the problem will be solved.
Definition at line 5743 of file SUMA_GeomComp.c. References c, SUMA_CommonFields::DsetList, SUMA_SurfaceObject::FaceNormList, i, LocalHead, SUMA_SurfaceObject::N_FaceSet, SUMA_SurfaceObject::PolyArea, SUMA_Boolean, SUMA_ENTRY, SUMA_FACE_CENTROID, SUMA_RETURN, SUMA_SL_Err, SUMA_SL_Warn, and SUMA_SurfaceMetrics_eng(). Referenced by SUMA_GetVolDiffRange(), SUMA_NewVolumeAtRadius(), and SUMA_Pattie_Volume().
05744 {
05745 static char FuncName[]={"SUMA_Mesh_Volume"};
05746 double Vol = 0.0, c[3], anx, any, anz, sx, sy, sz, kx, ky, kz, kt;
05747 float *pa = NULL;
05748 int i, fc;
05749 SUMA_Boolean LocalHead = NOPE;
05750
05751 SUMA_ENTRY;
05752
05753 if (!SO) { SUMA_SL_Err("NULL SO"); SUMA_RETURN(Vol); }
05754 if (!SO->FaceNormList) { SUMA_SL_Err("NULL SO->FaceNormList"); SUMA_RETURN(Vol); }
05755 if (!SO->PolyArea) {
05756 if (!SUMA_SurfaceMetrics_eng (SO, "PolyArea", NULL, 0, SUMAg_CF->DsetList)) {
05757 SUMA_SL_Err("Failed to compute SO->PolyArea"); SUMA_RETURN(Vol);
05758 }
05759 }
05760 pa = SO->PolyArea;
05761
05762 if (FSI || N_FaceSet != -1) {
05763 SUMA_SL_Err("FSI and N_FaceSet are two stupid options never to be used.\nUse NULL and -1, respectively.");
05764 SUMA_RETURN(Vol);
05765 }
05766
05767 if (!FSI) {
05768 N_FaceSet = SO->N_FaceSet;
05769 }
05770
05771
05772 /* calculate vector of areas * normals */
05773 kx = ky = kz = sx = sy = sz = 0.0;
05774 for (i=0; i<N_FaceSet; ++i) {
05775 if (FSI) fc = FSI[i];
05776 else fc = i;
05777 SUMA_FACE_CENTROID(SO, fc, c);
05778 #if 0
05779 if (LocalHead) fprintf(SUMA_STDERR,"Area: %f , normal (%f, %f, %f)\n",
05780 pa[fc], SO->FaceNormList[3*fc], SO->FaceNormList[3*fc+1], SO->FaceNormList[3*fc+2]);
05781 #endif
05782 anx = pa[fc] * SO->FaceNormList[3*fc]; kx += anx; sx += c[0] * anx;
05783 any = pa[fc] * SO->FaceNormList[3*fc+1]; ky += any; sy += c[1] * any;
05784 anz = pa[fc] * SO->FaceNormList[3*fc+2]; kz += anz; sz += c[2] * anz;
05785 }
05786 kt = (kx+ky+kz); /* need to normalize k so that sum is 1, kx, ky and kz are supposed to
05787 "weight the volume according to its orientation relative to the axes."
05788 For a sphere, you can use 1/3 for kx, ky and kz... */
05789 if (fabs(kt) < 1e-15) {
05790 SUMA_SL_Warn("Weight constants sum to ~= 0.\n"
05791 "Volume measurements may be off.\n"
05792 "If your surface's axes are along\n"
05793 "the X, Y and Z directions, as you \n"
05794 "could have with a box's surface, rotating\n"
05795 "the surface will solve the problem.");
05796 fprintf(SUMA_STDERR, "%s:\n"
05797 "kx + ky + kz = kt\n"
05798 "%f + %f + %f = %f\n"
05799 "sx, sy, sz = %f, %f, %f\n",
05800 FuncName, kx, ky, kz, kx+ky+kz, sx, sy, sz); }
05801 kx /= kt;
05802 ky /= kt;
05803 kz /= kt;
05804 if (LocalHead) {
05805 fprintf(SUMA_STDERR, "%s:\n"
05806 "%f + %f + %f = %f\n"
05807 "sx, sy, sz = %f, %f, %f\n",
05808 FuncName, kx, ky, kz, kx+ky+kz, sx, sy, sz);
05809 }
05810 Vol = kx * sx + ky *sy + kz * sz;
05811
05812 SUMA_RETURN(Vol);
05813 }
|
|
||||||||||||
|
Definition at line 1156 of file SUMA_GeomComp.c. References SUMA_OFFSET_LL_DATUM::layer, SUMA_OFFSET_LL_DATUM::ni, SUMA_OFFSET_LL_DATUM::off, SUMA_ENTRY, SUMA_malloc, and SUMA_RETURN. Referenced by SUMA_getoffsets_ll().
01157 {
01158 static char FuncName[]={"SUMA_New_Offset_ll_Datum"};
01159 SUMA_OFFSET_LL_DATUM * datum = NULL;
01160
01161 SUMA_ENTRY;
01162
01163 datum = (SUMA_OFFSET_LL_DATUM *)SUMA_malloc(sizeof(SUMA_OFFSET_LL_DATUM));
01164 datum->ni = n;
01165 datum->layer = layer;
01166 datum->off = -1.0;
01167
01168 SUMA_RETURN(datum);
01169 }
|
|
||||||||||||||||||||
|
Changes the coordinates of SO's nodes so that the new average radius of the surface is equal to r. This function is an integral part of the function for equating the areas of 2 surfaces. Nodes are stretched by a fraction equal to: (Rref - r) / Rref * Un where Un is the distance of the node from the center of the surface Rref is the reference radius, r is the desired radius
Definition at line 1340 of file SUMA_GeomComp.c. References c, SUMA_SurfaceObject::Center, i, LocalHead, SUMA_SurfaceObject::N_Node, SUMA_SurfaceObject::NodeList, r, SUMA_Boolean, SUMA_COPY_VEC, SUMA_ENTRY, SUMA_Mesh_Area(), SUMA_POINT_AT_DISTANCE_NORM, SUMA_RETURN, SUMA_SL_Err, and SUMA_UNIT_VEC. Referenced by SUMA_AreaDiff(), and SUMA_GetAreaDiffRange().
01341 {
01342 static char FuncName[]={"SUMA_NewAreaAtRadius"};
01343 double Dr, A=0.0, Un, U[3], Dn, P2[2][3], c[3];
01344 float *fp;
01345 int i;
01346 SUMA_Boolean LocalHead = NOPE;
01347
01348 SUMA_ENTRY;
01349
01350 /* calculate Dr and normalize by the radius of SOref */
01351 Dr = ( Rref - r ) / Rref;
01352
01353 /* Now loop over all the nodes in SO and add the deal */
01354 for (i=0; i<SO->N_Node; ++i) {
01355 /* change node coordinate of each node by Dr, along radial direction */
01356 fp = &(SO->NodeList[3*i]); SUMA_UNIT_VEC(SO->Center, fp, U, Un);
01357 Dn = Dr*Un + Un;
01358 if (Un) {
01359 SUMA_COPY_VEC(SO->Center, c, 3, float, double);
01360 SUMA_POINT_AT_DISTANCE_NORM(U, c, Dn, P2);
01361 tmpList[3*i] = (float)P2[0][0]; tmpList[3*i+1] = (float)P2[0][1]; tmpList[3*i+2] = (float)P2[0][2];
01362 } else {
01363 SUMA_SL_Err("Identical points!\n"
01364 "No coordinates modified");
01365 SUMA_RETURN(0);
01366 }
01367 }
01368
01369
01370 /* calculate the new Area */
01371 fp = SO->NodeList;/* save NodeList */
01372 SO->NodeList = tmpList; /* use new coordinates */
01373 A = fabs((double)SUMA_Mesh_Area(SO, NULL, -1));
01374 SO->NodeList = fp; fp = NULL; /* make NodeList point to the original data */
01375
01376 SUMA_RETURN(A);
01377 }
|
|
||||||||||||||||||||
|
Changes the coordinates of SO's nodes so that the new average radius of the surface is equal to r. This function is an integral part of the function for equating the volumes of 2 surfaces. Nodes are stretched by a fraction equal to: (Rref - r) / Rref * Un where Un is the distance of the node from the center of the surface Rref is the reference radius, r is the desired radius
Definition at line 1394 of file SUMA_GeomComp.c. References c, SUMA_SurfaceObject::Center, i, LocalHead, SUMA_SurfaceObject::N_Node, SUMA_SurfaceObject::NodeList, r, SUMA_Boolean, SUMA_COPY_VEC, SUMA_ENTRY, SUMA_Mesh_Volume(), SUMA_POINT_AT_DISTANCE_NORM, SUMA_RETURN, SUMA_SL_Err, and SUMA_UNIT_VEC. Referenced by SUMA_GetVolDiffRange(), and SUMA_VolDiff().
01395 {
01396 static char FuncName[]={"SUMA_NewVolumeAtRadius"};
01397 double Dr, V=0.0, Un, U[3], Dn, P2[2][3], c[3];
01398 float *fp;
01399 int i;
01400 SUMA_Boolean LocalHead = NOPE;
01401
01402 SUMA_ENTRY;
01403
01404 /* calculate Dr and normalize by the radius of SOref */
01405 Dr = ( Rref - r ) / Rref;
01406
01407 /* Now loop over all the nodes in SO and add the deal */
01408 for (i=0; i<SO->N_Node; ++i) {
01409 /* change node coordinate of each node by Dr, along radial direction */
01410 fp = &(SO->NodeList[3*i]); SUMA_UNIT_VEC(SO->Center, fp, U, Un);
01411 Dn = Dr*Un + Un;
01412 if (Un) {
01413 SUMA_COPY_VEC(SO->Center, c, 3, float, double);
01414 SUMA_POINT_AT_DISTANCE_NORM(U, c, Dn, P2);
01415 tmpList[3*i] = (float)P2[0][0]; tmpList[3*i+1] = (float)P2[0][1]; tmpList[3*i+2] = (float)P2[0][2];
01416 } else {
01417 SUMA_SL_Err("Identical points!\n"
01418 "No coordinates modified");
01419 SUMA_RETURN(0);
01420 }
01421 }
01422
01423
01424 /* calculate the new volume */
01425 fp = SO->NodeList;/* save NodeList */
01426 SO->NodeList = tmpList; /* use new coordinates */
01427 V = fabs((double)SUMA_Mesh_Volume(SO, NULL, -1));
01428 SO->NodeList = fp; fp = NULL; /* make NodeList point to the original data */
01429
01430 SUMA_RETURN(V);
01431 }
|
|
||||||||||||||||||||||||||||||||
|
Definition at line 2939 of file SUMA_GeomComp.c. References SUMA_SurfaceObject::FN, fout, SUMA_SurfaceObject::N_Node, SUMA_COMM_STRUCT::Send, SUMA_calloc, SUMA_COLUMN_MAJOR, SUMA_ENTRY, SUMA_free, SUMA_INDEXING_ORDER, SUMA_NODE_XYZ, SUMA_RETURN, SUMA_ROW_MAJOR, SUMA_SendToSuma(), SUMA_SL_Crit, SUMA_SL_Err, SUMA_SL_Warn, SUMA_SmoothAttr_Neighb(), and vpn.
02942 {
02943 static char FuncName[]= {"SUMA_NN_GeomSmooth"};
02944 float *fout_final=NULL, *fbuf=NULL, *fin_next=NULL, *fin=NULL, *fout=NULL;
02945 int niter=0;
02946
02947 SUMA_ENTRY;
02948 if (!SO) { SUMA_SL_Err("NULL SO"); SUMA_RETURN(NULL); }
02949 if (!SO->FN) {
02950 SUMA_SL_Err("NULL SO->FN");
02951 SUMA_RETURN(NULL);
02952 }
02953 if (N_iter % 2) {
02954 SUMA_SL_Err("N_iter must be an even number\n");
02955 SUMA_RETURN(NULL);
02956 }
02957 if (vpn < 1) {
02958 SUMA_SL_Err("vpn < 1\n");
02959 SUMA_RETURN(NULL);
02960 }
02961
02962 if (fout_final_user == fin_orig) {
02963 SUMA_SL_Err("fout_final_user == fin_orig");
02964 SUMA_RETURN(NULL);
02965 }
02966
02967 if (!fout_final_user) { /* allocate for output */
02968 fout_final = (float *)SUMA_calloc(SO->N_Node * vpn, sizeof(float));
02969 if (!fout_final) {
02970 SUMA_SL_Crit("Failed to allocate for fout_final\n");
02971 SUMA_RETURN(NULL);
02972 }
02973 }else {
02974 fout_final = fout_final_user; /* pre-allocated */
02975 }
02976
02977 /* allocate for buffer */
02978 fbuf = (float *)SUMA_calloc(SO->N_Node * vpn, sizeof(float));
02979 if (!fbuf) {
02980 SUMA_SL_Crit("Failed to allocate for fbuf\n");
02981 SUMA_RETURN(NULL);
02982 }
02983
02984
02985 if (cs->Send) { /* send the first monster */
02986 if (!SUMA_SendToSuma (SO, cs, (void *)fin_orig, SUMA_NODE_XYZ, 1)) {
02987 SUMA_SL_Warn("Failed in SUMA_SendToSuma\nCommunication halted.");
02988 }
02989 }
02990
02991 fin_next = fin_orig;
02992 switch (d_order) {
02993 case SUMA_ROW_MAJOR:
02994 for (niter=0; niter < N_iter; ++niter) {
02995 if ( niter % 2 ) { /* odd */
02996 fin = fin_next; /* input from previous output buffer */
02997 fout = fout_final; /* results go into final vector */
02998 fin_next = fout_final; /* in the next iteration, the input is from fout_final */
02999 } else { /* even */
03000 /* input data is in fin_new */
03001 fin = fin_next;
03002 fout = fbuf; /* results go into buffer */
03003 fin_next = fbuf; /* in the next iteration, the input is from the buffer */
03004 }
03005 fout = SUMA_SmoothAttr_Neighb ( fin, vpn*SO->N_Node,
03006 fout, SO->FN, vpn);
03007 if (cs->Send) {
03008 if (!SUMA_SendToSuma (SO, cs, (void *)fout, SUMA_NODE_XYZ, 1)) {
03009 SUMA_SL_Warn("Failed in SUMA_SendToSuma\nCommunication halted.");
03010 }
03011 }
03012 }
03013 break;
03014 case SUMA_COLUMN_MAJOR:
03015 SUMA_SL_Err("Column Major not implemented");
03016 SUMA_RETURN(NULL);
03017 break;
03018 default:
03019 SUMA_SL_Err("Bad Major, very bad.\n");
03020 SUMA_RETURN(NULL);
03021 break;
03022 }
03023
03024 if (fbuf) SUMA_free(fbuf); fbuf = NULL;
03025
03026 SUMA_RETURN(fout);
03027 }
|
|
||||||||||||||||||||
|
Converts a path formed by a series of connected nodes to a series of edges ePath = SUMA_NodePath_to_EdgePath (EL, Path, N_Path, N_Edge);.
Definition at line 7195 of file SUMA_GeomComp.c. References i, LocalHead, SUMA_Boolean, SUMA_calloc, SUMA_ENTRY, SUMA_FindEdge(), SUMA_free, and SUMA_RETURN.
07196 {
07197 static char FuncName[]={"SUMA_NodePath_to_EdgePath"};
07198 int *ePath = NULL, i, i0;
07199 SUMA_Boolean LocalHead = NOPE;
07200
07201 SUMA_ENTRY;
07202
07203
07204 *N_Edge = 0;
07205 ePath = (int *) SUMA_calloc(N_Path, sizeof(int));
07206 if (!ePath) {
07207 fprintf (SUMA_STDERR, "Error %s: Failed to allocate.\n", FuncName);
07208 SUMA_RETURN (NULL);
07209 }
07210
07211 for (i=1; i<N_Path; ++i) {
07212 i0 = Path[i-1];
07213 /* find the location of the edge between i0 and i1 */
07214 ePath[i-1] = SUMA_FindEdge (EL, i0, Path[i]);
07215 if (ePath[i-1] < 0) { /* error */
07216 fprintf (SUMA_STDERR, "Error %s: Failed in SUMA_FindEdge.\n", FuncName);
07217 SUMA_free(ePath);
07218 *N_Edge = 0;
07219 SUMA_RETURN (NULL);
07220 }else {
07221 ++(*N_Edge);
07222 }
07223 }
07224
07225 SUMA_RETURN (ePath);
07226 }
|
|
||||||||||||||||||||||||
|
Converts a series of connected nodes into a series of connected triangles that were intersected by the plane. There is no guarantee that two nodes that belong to triangles intersected by the plane and part of the shortest path (as returned by SUMA_Dijkstra) for an edge that belongs to a triangle intersected by the plane. See labbook NIH-2 page 158 for sketches illustrating this point. So the strip of triangles that you will get back may have holes in it since it only allows intersected triangles to be members of the path. tPath = SUMA_NodePath_to_TriPath_Inters (SO, SPI, int *nPath, int N_nPath, int *N_tPath)
Definition at line 7606 of file SUMA_GeomComp.c. References E, SUMA_SurfaceObject::EL, SUMA_EDGE_LIST::ELps, SUMA_SurfaceObject::FaceSetList, i, SUMA_SURF_PLANE_INTERSECT::isTriHit, LocalHead, nc, SUMA_Boolean, SUMA_calloc, SUMA_ENTRY, SUMA_FindEdge(), SUMA_free, SUMA_isTriLinked(), SUMA_RETURN, and SUMA_whichTri().
07607 {
07608 static char FuncName[]={"SUMA_NodePath_to_TriPath_Inters"};
07609 int *tPath = NULL, e, i, N_nc, nc[3], N_HostTri, E, j,
07610 HostTri, PrevTri, k, N1[2], N2[2], cnt, MissTri = 0, candidate;
07611 SUMA_Boolean Found, LocalHead = NOPE;
07612
07613 SUMA_ENTRY;
07614
07615 tPath = (int *) SUMA_calloc(2*N_nPath, sizeof(int));
07616 if (!tPath) {
07617 fprintf (SUMA_STDERR, "Error %s: Failed to allocate.\n", FuncName);
07618 SUMA_RETURN (NULL);
07619 }
07620
07621 *N_tPath = 0;
07622 for (i=0; i < N_nPath - 1; ++i) {
07623 /* find the edge corresponding to two consecutive nodes in the path */
07624 E = SUMA_FindEdge (SO->EL, nPath[i], nPath[i+1]);
07625 if (E < 0) {
07626 fprintf (SUMA_STDERR, "Error %s: Failed in SUMA_FindEdge.\n", FuncName);
07627 SUMA_free(tPath);
07628 SUMA_RETURN(NULL);
07629 }
07630 /* find the triangles containing E and intersected by the plane */
07631 N_HostTri = SO->EL->ELps[E][2]; /* number of hosting triangles */
07632 if (N_HostTri > 2) {
07633 fprintf (SUMA_STDERR, "Warning %s: Surface is not a surface, Edge %d has more than %d hosting triangles.\n", FuncName, E, N_HostTri);
07634 }
07635 candidate = 0;
07636 /* search for a hosting triangle that was intersected */
07637 for (j=0; j < N_HostTri; ++j) {
07638 HostTri = SO->EL->ELps[E+j][1];
07639 if (SPI->isTriHit[HostTri]) { /* a candidate for adding to the path */
07640 ++candidate;
07641 if (*N_tPath > 2*N_nPath) {
07642 fprintf (SUMA_STDERR, "Error %s: N_tPath = %d > %d allocated.\n", FuncName, *N_tPath, 2*N_nPath);
07643 }
07644 #if 1
07645 /* This block is an attempt to get All triangles intersected by plane AND having a node as part of the shortest path.
07646 It does not work well, probably because some of the functions called need fixing... */
07647 if (*N_tPath == 0) { /* if that is the first triangle in the path, add it without much fuss */
07648 tPath[*N_tPath] = HostTri; /* hosting triangle index */
07649 ++ (*N_tPath);
07650 } else { /* make sure there is continuation along edges */
07651 PrevTri = tPath[*N_tPath - 1];
07652 N_nc = SUMA_isTriLinked (&(SO->FaceSetList[3*PrevTri]), &(SO->FaceSetList[3*HostTri]), nc);
07653 if (!N_nc) {
07654 fprintf (SUMA_STDERR, "Warning %s: Triangles %d and %d are not linked.\nAdding triangle %d anyway.\n",
07655 FuncName, PrevTri, HostTri, HostTri);
07656 /* add triangle, anyway */
07657 tPath[*N_tPath] = HostTri;
07658 ++ (*N_tPath);
07659 }else if (N_nc == 1) {
07660 /* must fill triangle gap get the triangle with the common node and common edges*/
07661 /* first, find remaining nodes in PrevTri */
07662 e = 0;
07663 for (k=0; k <3; ++k) {
07664 if (SO->FaceSetList[3*PrevTri+k] != nc[0]) {
07665 N1[e] = SO->FaceSetList[3*PrevTri+k]; ++e;
07666 }
07667 }
07668 /* then find remaining nodes in HostTri */
07669 e = 0;
07670 for (k=0; k <3; ++k) {
07671 if (SO->FaceSetList[3*HostTri+k] != nc[0]) {
07672 N2[e] = SO->FaceSetList[3*HostTri+k]; ++e;
07673 }
07674 }
07675 /* find a triangle that has either one of the following node combinations, in addition to nc[0]:
07676 N1[0], N2[0] or N1[0], N2[1] or N1[1], N2[0] or N1[1], N2[1] */
07677 Found = NOPE;
07678 cnt = 0;
07679 while (!Found && cnt < 4) {
07680 switch (cnt) {
07681 case 0:
07682 MissTri = SUMA_whichTri (SO->EL, nc[0], N1[0], N2[0], 1);
07683 if (LocalHead) fprintf (SUMA_STDERR, "%s: looking for triangle with nodes %d and %d... Tri = %d\n",
07684 FuncName, N1[0], N2[0], MissTri);
07685 break;
07686 case 1:
07687 MissTri = SUMA_whichTri (SO->EL, nc[0], N1[0], N2[1], 1);
07688 if (LocalHead) fprintf (SUMA_STDERR, "%s: looking for triangle with nodes %d and %d... Tri = %d\n",
07689 FuncName, N1[0], N2[1], MissTri);
07690 break;
07691 case 2:
07692 MissTri = SUMA_whichTri (SO->EL, nc[0], N1[1], N2[0], 1);
07693 if (LocalHead) fprintf (SUMA_STDERR, "%s: looking for triangle with nodes %d and %d... Tri = %d\n",
07694 FuncName, N1[1], N2[0], MissTri);
07695 break;
07696 case 3:
07697 MissTri = SUMA_whichTri (SO->EL, nc[0], N1[1], N2[1], 1);
07698 if (LocalHead) fprintf (SUMA_STDERR, "%s: looking for triangle with nodes %d and %d... Tri = %d\n",
07699 FuncName, N1[1], N2[1], MissTri);
07700 break;
07701 }
07702 if (MissTri >= 0) {
07703 Found = YUP;
07704 }
07705 ++cnt;
07706 }
07707 if (!Found) {
07708 fprintf (SUMA_STDERR, "Warning %s: Failed to find missing triangle.\n", FuncName);
07709 tPath[*N_tPath] = HostTri;
07710 ++ (*N_tPath);
07711 }else {
07712 /* add the missing triangle first, then the HostTri */
07713 tPath[*N_tPath] = MissTri;
07714 ++ (*N_tPath);
07715 tPath[*N_tPath] = HostTri;
07716 ++ (*N_tPath);
07717 }
07718 }else if (N_nc == 2) {
07719 /* Triangles share an edge so no problem, insert the new triangle in the path */
07720 tPath[*N_tPath] = HostTri;
07721 ++ (*N_tPath);
07722 }else {
07723 fprintf (SUMA_STDERR, "Error %s: Triangles %d and %d are identical.\n", FuncName, PrevTri, HostTri);
07724 SUMA_free(tPath);
07725 SUMA_RETURN(NULL);
07726 }
07727 }
07728 #else
07729 tPath[*N_tPath] = HostTri;
07730 ++ (*N_tPath);
07731 #endif
07732 }
07733 }
07734 if (!candidate) {
07735 fprintf (SUMA_STDERR, "\aWarning %s: Nodes %d and %d of edge %d had no intersected hosting triangle.\n", FuncName, nPath[i], nPath[i+1], E);
07736
07737 }
07738 }
07739
07740 SUMA_RETURN (tPath);
07741 }
|
|
||||||||||||||||||||||||
|
Converts a series of connected nodes into a series of connected triangles that belong to a branch. The function fails at times, picking the long instead of the short path but it is left here in case I need it in the future. tPath = SUMA_NodePath_to_TriPath_Inters_OLD (SO, Bv, Path, N_Path, N_Tri);
Definition at line 7762 of file SUMA_GeomComp.c. References SUMA_SurfaceObject::FaceSetList, i1, SUMA_TRI_BRANCH::list, LocalHead, SUMA_TRI_BRANCH::N_list, SUMA_Boolean, SUMA_calloc, SUMA_ENTRY, SUMA_free, and SUMA_RETURN.
07763 {
07764 static char FuncName[]={"SUMA_NodePath_to_TriPath_Inters_OLD"};
07765 int *tPath = NULL, ilist, i0, Tri, eTri, EdgeBuf, Tri0, Tri1, Direction, i1, loc2f, iDirSet;
07766 SUMA_Boolean LocalHead = NOPE, Found = NOPE;
07767
07768 SUMA_ENTRY;
07769
07770
07771 *N_Tri = 0;
07772 tPath = (int *) SUMA_calloc(Bv->N_list+1, sizeof(int));
07773 if (!tPath) {
07774 fprintf (SUMA_STDERR, "Error %s: Failed to allocate.\n", FuncName);
07775 SUMA_RETURN (NULL);
07776 }
07777
07778 /* the first triangle should contain the first node in the path */
07779 i0 = Path[0];
07780 Tri0 = Bv->list[0];
07781 if (SO->FaceSetList[3*Tri0] != i0 && SO->FaceSetList[3*Tri0+1] != i0 && SO->FaceSetList[3*Tri0+2] != i0) {
07782 fprintf (SUMA_STDERR, "Error %s: Did not find node %d in first triangle in branch.\n", FuncName, i0);
07783 SUMA_free(tPath);
07784 *N_Tri = 0;
07785 SUMA_RETURN (NULL);
07786 }
07787
07788
07789 /* initiliaze first node results and look for the second node */
07790 tPath[0] = Tri0;
07791 *N_Tri = 1;
07792 Found = NOPE;
07793 ilist = 0;
07794
07795 if (LocalHead) fprintf(SUMA_STDERR, "%s: Going forward looking for third node\n", FuncName);
07796 if (N_Path > 2) {
07797 iDirSet = 2; /* search for third node in list, that helps determine the direction more reliably */
07798 }else {
07799 iDirSet = 1; /* settle for the second node */
07800 }
07801
07802 ilist = 1;
07803 while (!Found && ilist < Bv->N_list) {
07804 tPath[*N_Tri] = Bv->list[ilist];
07805 if (SO->FaceSetList[3*Bv->list[ilist]] == Path[iDirSet] ||
07806 SO->FaceSetList[3*Bv->list[ilist]+1] == Path[iDirSet] ||
07807 SO->FaceSetList[3*Bv->list[ilist]+2] == Path[iDirSet]) {
07808 Found = YUP;
07809 }
07810 ++(*N_Tri);
07811 ++ilist;
07812 }
07813
07814 if (!Found) {
07815 fprintf (SUMA_STDERR, "Error %s: Did not find next node %d in branch.\n", FuncName, Path[iDirSet]);
07816 SUMA_free(tPath);
07817 *N_Tri = 0;
07818 SUMA_RETURN (NULL);
07819 }
07820
07821 loc2f = *N_Tri; /* number of steps to find second node in the forward direction */
07822
07823 /* do the same in the backwards direction */
07824 tPath[0] = Tri0;
07825 *N_Tri = 1;
07826 Found = NOPE;
07827 ilist = 0;
07828
07829 if (LocalHead) fprintf(SUMA_STDERR, "%s: Going backwards looking for third node\n", FuncName);
07830 ilist = Bv->N_list - 1;
07831 while (!Found && ilist >= 0) {
07832 tPath[*N_Tri] = Bv->list[ilist];
07833 if (LocalHead) fprintf(SUMA_STDERR, "%s: trying triangle %d for node %d.\n", FuncName, Bv->list[ilist], Path[N_Path-1]);
07834 if (SO->FaceSetList[3*Bv->list[ilist]] == Path[iDirSet] ||
07835 SO->FaceSetList[3*Bv->list[ilist]+1] == Path[iDirSet] ||
07836 SO->FaceSetList[3*Bv->list[ilist]+2] == Path[iDirSet]) {
07837 Found = YUP;
07838 }
07839 ++(*N_Tri);
07840 --ilist;
07841 }
07842
07843 if (*N_Tri < loc2f) {
07844 /* go backwards, shorter. This is based on triangle count,
07845 it would be more accurate based on distance of intersected edge */
07846 Direction = -1;
07847 } else Direction = 1;
07848
07849 /* now do the whole thing */
07850
07851 tPath[0] = Tri0;
07852 *N_Tri = 1;
07853 Found = NOPE;
07854 ilist = 0;
07855 if (Direction == 1) { /* move forward until you reach the last node */
07856 if (LocalHead) fprintf(SUMA_STDERR, "%s: Going forward, final pass \n", FuncName);
07857 ilist = 1;
07858 while (!Found && ilist < Bv->N_list) {
07859 tPath[*N_Tri] = Bv->list[ilist];
07860 if (SO->FaceSetList[3*Bv->list[ilist]] == Path[N_Path-1] ||
07861 SO->FaceSetList[3*Bv->list[ilist]+1] == Path[N_Path-1] ||
07862 SO->FaceSetList[3*Bv->list[ilist]+2] == Path[N_Path-1]) {
07863 Found = YUP;
07864 }
07865 ++(*N_Tri);
07866 ++ilist;
07867 }
07868 } else { /* move backwards */
07869 if (LocalHead) fprintf(SUMA_STDERR, "%s: Going backwards, final pass \n", FuncName);
07870 ilist = Bv->N_list - 1;
07871 while (!Found && ilist >= 0) {
07872 tPath[*N_Tri] = Bv->list[ilist];
07873 if (LocalHead) fprintf(SUMA_STDERR, "%s: trying triangle %d for node %d.\n", FuncName, Bv->list[ilist], Path[N_Path-1]);
07874 if (SO->FaceSetList[3*Bv->list[ilist]] == Path[N_Path-1] ||
07875 SO->FaceSetList[3*Bv->list[ilist]+1] == Path[N_Path-1] ||
07876 SO->FaceSetList[3*Bv->list[ilist]+2] == Path[N_Path-1]) {
07877 Found = YUP;
07878 }
07879 ++(*N_Tri);
07880 --ilist;
07881 }
07882
07883 }
07884
07885 if (!Found) {
07886 fprintf (SUMA_STDERR, "Error %s: Path not completed.\n", FuncName);
07887 SUMA_free(tPath);
07888 *N_Tri = 0;
07889 SUMA_RETURN (NULL);
07890 }else {
07891 if (LocalHead) {
07892 fprintf (SUMA_STDERR,"%s: Path is %d triangles long:\n", FuncName, *N_Tri);
07893 for (ilist=0; ilist< *N_Tri; ++ilist) {
07894 fprintf (SUMA_STDERR,"t%d\t", tPath[ilist]);
07895 }
07896 fprintf (SUMA_STDERR,"\n");
07897 }
07898 }
07899 SUMA_RETURN (tPath);
07900 }
|
|
||||||||||||||||||||||||||||||||||||
|
A filtering function that is based on brute force estimates of node neighbor distance matrix. It is not finished because it makes no use of the neighbor distances to properly weigh the interpolation. It ends up being too slow because of the high memory load for computing OffS_out.
Definition at line 2824 of file SUMA_GeomComp.c. References SUMA_SurfaceObject::FN, fout, i, LocalHead, SUMA_SurfaceObject::N_Node, SUMA_COMM_STRUCT::Send, SUMA_Boolean, SUMA_calloc, SUMA_COLUMN_MAJOR, SUMA_ENTRY, SUMA_etime(), SUMA_FormNeighbOffset(), SUMA_free, SUMA_free_NeighbOffset(), SUMA_INDEXING_ORDER, SUMA_LH, SUMA_NODE_XYZ, SUMA_RETURN, SUMA_ROW_MAJOR, SUMA_SendToSuma(), SUMA_SL_Crit, SUMA_SL_Err, SUMA_SL_Warn, and vpn.
02827 {
02828
02829 static char FuncName[]= {"SUMA_Offset_GeomSmooth"};
02830 float *fout_final=NULL, *fbuf=NULL, *fin_next=NULL, *fin=NULL, *fout=NULL;
02831 int niter=0, i, il,jl, j, ii, noffs;
02832 struct timeval start_time;
02833 float etime_GetOffset, weight_tot;
02834 SUMA_OFFSET_STRUCT *OffS_out=NULL;
02835 SUMA_Boolean LocalHead = NOPE;
02836
02837 SUMA_ENTRY;
02838 if (!SO) { SUMA_SL_Err("NULL SO"); SUMA_RETURN(NULL); }
02839 if (!SO->FN) {
02840 SUMA_SL_Err("NULL SO->FN");
02841 SUMA_RETURN(NULL);
02842 }
02843 if (N_iter % 2) {
02844 SUMA_SL_Err("N_iter must be an even number\n");
02845 SUMA_RETURN(NULL);
02846 }
02847 if (vpn < 1) {
02848 SUMA_SL_Err("vpn < 1\n");
02849 SUMA_RETURN(NULL);
02850 }
02851
02852 if (fout_final_user == fin_orig) {
02853 SUMA_SL_Err("fout_final_user == fin_orig");
02854 SUMA_RETURN(NULL);
02855 }
02856
02857 if (!fout_final_user) { /* allocate for output */
02858 fout_final = (float *)SUMA_calloc(SO->N_Node * vpn, sizeof(float));
02859 if (!fout_final) {
02860 SUMA_SL_Crit("Failed to allocate for fout_final\n");
02861 SUMA_RETURN(NULL);
02862 }
02863 }else {
02864 fout_final = fout_final_user; /* pre-allocated */
02865 }
02866
02867 /* allocate for buffer */
02868 fbuf = (float *)SUMA_calloc(SO->N_Node * vpn, sizeof(float));
02869 if (!fbuf) {
02870 SUMA_SL_Crit("Failed to allocate for fbuf\n");
02871 SUMA_RETURN(NULL);
02872 }
02873
02874
02875 if (cs->Send) { /* send the first monster */
02876 if (!SUMA_SendToSuma (SO, cs, (void *)fin_orig, SUMA_NODE_XYZ, 1)) {
02877 SUMA_SL_Warn("Failed in SUMA_SendToSuma\nCommunication halted.");
02878 }
02879 }
02880 SUMA_LH("Calculating OffS_out ...");
02881 OffS_out = SUMA_FormNeighbOffset (SO, OffsetLim);
02882 fin_next = fin_orig;
02883 switch (d_order) {
02884 case SUMA_ROW_MAJOR:
02885 for (niter=0; niter < N_iter; ++niter) {
02886 if ( niter % 2 ) { /* odd */
02887 fin = fin_next; /* input from previous output buffer */
02888 fout = fout_final; /* results go into final vector */
02889 fin_next = fout_final; /* in the next iteration, the input is from fout_final */
02890 } else { /* even */
02891 /* input data is in fin_new */
02892 fin = fin_next;
02893 fout = fbuf; /* results go into buffer */
02894 fin_next = fbuf; /* in the next iteration, the input is from the buffer */
02895 }
02896
02897 SUMA_etime(&start_time,0);
02898
02899 for (i=0; i < SO->N_Node; ++i) {
02900 for (j=0; j < vpn; ++j) {
02901 /* do the averaging using OffS_out NO ATTENTION IS GIVEN TO PROPER WEIGHING YET!*/
02902 fout[i*vpn+j] = fin[i*vpn+j];
02903 for (il=0; il<OffS_out[i].N_Neighb; ++il) {
02904 fout[i*vpn+j] += fin[OffS_out[i].Neighb_ind[il]*vpn+j];
02905 }
02906 fout[i*vpn+j] /= (OffS_out[i].N_Neighb+1);
02907 }
02908 }
02909
02910 etime_GetOffset = SUMA_etime(&start_time,1);
02911 fprintf(SUMA_STDERR, "%s: Smoothing at dist %f took %f seconds for %d nodes.\n",
02912 FuncName, OffsetLim, etime_GetOffset, SO->N_Node);
02913
02914 if (cs->Send) {
02915 if (!SUMA_SendToSuma (SO, cs, (void *)fout, SUMA_NODE_XYZ, 1)) {
02916 SUMA_SL_Warn("Failed in SUMA_SendToSuma\nCommunication halted.");
02917 }
02918 }
02919 }
02920 break;
02921 case SUMA_COLUMN_MAJOR:
02922 SUMA_SL_Err("Column Major not implemented");
02923 SUMA_RETURN(NULL);
02924 break;
02925 default:
02926 SUMA_SL_Err("Bad Major, very bad.\n");
02927 SUMA_RETURN(NULL);
02928 break;
02929 }
02930
02931 if (fbuf) SUMA_free(fbuf); fbuf = NULL;
02932
02933 /* Have to free OffS_out */
02934 OffS_out = SUMA_free_NeighbOffset (SO, OffS_out);
02935
02936 SUMA_RETURN(fout);
02937 }
|
|
||||||||||||||||||||||||||||
|
determine overall orientation of triangle normals and change triangle orientation if required
Definition at line 4983 of file SUMA_GeomComp.c. References c, flip(), fout, i, LocalHead, n1, n2, SUMA_Boolean, SUMA_calloc, SUMA_DOTP_VEC, SUMA_ENTRY, SUMA_free, SUMA_LH, SUMA_NORM_VEC, SUMA_RETURN, SUMA_SL_Crit, SUMA_SL_Err, SUMA_SL_Note, and SUMA_SL_Warn. Referenced by main(), and SUMA_LoadPrepInVol().
04984 {
04985 static char FuncName[]={"SUMA_OrientTriangles"};
04986 int i, j, ip, negdot, posdot, sgn, NP, ND, n1, n2, n3, flip;
04987 float d1[3], d2[3], c[3], tc[3], U[3], dot, *norm, mag;
04988 FILE *fout = NULL;
04989 SUMA_Boolean LocalHead = NOPE;
04990
04991 SUMA_ENTRY;
04992
04993
04994 if (!NodeList || !FaceSetList || !N_Node || !N_FaceSet) {
04995 SUMA_SL_Err("Null or no input");
04996 SUMA_RETURN(0);
04997 }
04998 norm = (float *)SUMA_calloc(3*N_FaceSet, sizeof(float));
04999 if (!norm) {
05000 SUMA_SL_Crit("Failed to allocate for norm"); SUMA_RETURN(0);
05001 }
05002 if (Force) {
05003 SUMA_SL_Warn("Using Force option! You might destroy triangulation consistency of surface!");
05004 }
05005 NP = ND = 3;
05006 /* calculate the center coordinate */
05007 c[0] = c[1] = c[2];
05008 for (i=0; i < N_Node; ++i) {
05009 ip = ND * i; c[0] += NodeList[ip]; c[1] += NodeList[ip+1]; c[2] += NodeList[ip+2];
05010 }
05011 c[0] /= N_Node; c[1] /= N_Node; c[2] /= N_Node;
05012
05013 /* calculate normals for each triangle, taken from SUMA_SurfNorm*/
05014 if (0 && LocalHead) {
05015 SUMA_SL_Note("Writing SUMA_OrientTriangles.1D");
05016 fout = fopen("SUMA_OrientTriangles.1D", "w");
05017 }
05018 negdot = 0; posdot = 0;
05019 for (i=0; i < N_FaceSet; i++) {
05020 ip = NP * i;
05021 n1 = FaceSetList[ip]; n2 = FaceSetList[ip+1]; n3 = FaceSetList[ip+2]; /* node indices making up triangle */
05022 tc[0] = (NodeList[3*n1] + NodeList[3*n2] + NodeList[3*n3] )/3; /* centroid of triangle */
05023 tc[1] = (NodeList[3*n1+1] + NodeList[3*n2+1] + NodeList[3*n3+1])/3;
05024 tc[2] = (NodeList[3*n1+2] + NodeList[3*n2+2] + NodeList[3*n3+2])/3;
05025 /* calc normal */
05026 for (j=0; j < 3; j++) {
05027 d1[j] = NodeList[(ND*n1)+j] - NodeList[(ND*n2)+j];
05028 d2[j] = NodeList[(ND*n2)+j] - NodeList[(ND*n3)+j];
05029 }
05030 norm[ip] = d1[1]*d2[2] - d1[2]*d2[1];
05031 norm[ip+1] = d1[2]*d2[0] - d1[0]*d2[2];
05032 norm[ip+2] = d1[0]*d2[1] - d1[1]*d2[0];
05033
05034 /* dot the normal with vector from center to node */
05035 U[0] = tc[0] - c[0]; U[1] = tc[1] - c[1]; U[2] = tc[2] - c[2];
05036 SUMA_DOTP_VEC(U, &(norm[ip]), dot, 3, float, float);
05037 if (dot < 0) {
05038 ++negdot;
05039 if (0 && LocalHead) { fprintf (SUMA_STDERR,"%s: Triangle %d has a negative dot product %f\nc =[%.3f %.3f %.3f]\ntc =[%.3f %.3f %.3f]\nnorm=[%.3f %.3f %.3f]\n",
05040 FuncName, i, dot, c[0], c[1], c[2], tc[0], tc[1], tc[2], norm[ip+0], norm[ip+1], norm[ip+2]); }
05041
05042 } else {
05043 if (fout) {
05044 SUMA_NORM_VEC(norm,3,mag); if (!mag) mag = 1; mag /= 5;
05045 if (fout) fprintf (fout,"%.3f %.3f %.3f %.3f %.3f %.3f\n", tc[0], tc[1], tc[2], tc[0]+norm[ip+0]/mag, tc[1]+norm[ip+1]/mag, tc[2]+norm[ip+2]/mag);
05046 }
05047 ++posdot;
05048 }
05049
05050 if (Force) {
05051 if ( (dot < 0 && orient > 0) || (dot > 0 && orient < 0)) {
05052 n1 = FaceSetList[ip]; FaceSetList[ip] = FaceSetList[ip+2]; FaceSetList[ip+2] = n1;
05053 }
05054 }
05055 }
05056 if (fout) fclose(fout); fout = NULL;
05057 flip = 0; sgn = 0;
05058 if (posdot >= negdot) {
05059 SUMA_LH("Normals appear to point away from center");
05060 sgn = 1;
05061 if (orient < 0) flip = 1;
05062 } else {
05063 SUMA_LH("Normals appear to point towards center");
05064 sgn = -1;
05065 if (orient > 0) flip = 1;
05066 }
05067 if (LocalHead) {
05068 fprintf(SUMA_STDERR,"%s:\n Found %d positive dot products and %d negative ones.\n", FuncName, posdot, negdot);
05069 }
05070
05071 if (flip && !Force) {
05072 SUMA_LH("Flipping");
05073 for (i=0; i < N_FaceSet; i++) {
05074 ip = NP * i;
05075 n1 = FaceSetList[ip]; FaceSetList[ip] = FaceSetList[ip+2]; FaceSetList[ip+2] = n1;
05076 }
05077 }
05078
05079 if (norm) SUMA_free(norm); norm = NULL;
05080
05081 SUMA_RETURN(sgn);
05082 }
|
|
||||||||||||||||||||||||
|
Definition at line 5096 of file SUMA_GeomComp.c. References SUMA_SurfaceObject::FaceSetDim, SUMA_SurfaceObject::FaceSetList, i, LocalHead, SUMA_SurfaceObject::N_FaceSet, SUMA_SurfaceObject::N_Node, SUMA_SurfaceObject::NodeDim, SUMA_SurfaceObject::NodeList, SUMA_Alloc_SurfObject_Struct(), SUMA_Boolean, SUMA_calloc, SUMA_ENTRY, SUMA_malloc, SUMA_RETURN, and SUMA_SL_Err. Referenced by SUMA_ConvexHullSurface(), and SUMA_LoadPrepInVol().
05097 {
05098 static char FuncName[]={"SUMA_Patch2Surf"};
05099 SUMA_SurfaceObject *SO=NULL;
05100 int i = 0, cnt = 0;
05101 int *imask = NULL;
05102 int N_Node = 0;
05103 SUMA_Boolean LocalHead = NOPE;
05104
05105 SUMA_ENTRY;
05106
05107 if (!NodeList || !PatchFaces) {
05108 SUMA_SL_Err("Null input");
05109 SUMA_RETURN(SO);
05110 }
05111
05112 imask = (int*)SUMA_calloc(N_NodeList , sizeof(int));
05113 if (!imask) {
05114 SUMA_SL_Err("Failed to allocate");
05115 SUMA_RETURN(SO);
05116 }
05117 /* count the number of nodes and initialize imask*/
05118 SO = SUMA_Alloc_SurfObject_Struct(1);
05119 if (!SO) {
05120 SUMA_SL_Err("Failed to allocate");
05121 SUMA_RETURN(SO);
05122 }
05123 SO->N_FaceSet = N_PatchFaces;
05124 SO->N_Node = 0;
05125 for (i=0; i<3*N_PatchFaces; ++i) {
05126 if (!imask[PatchFaces[i]]) {
05127 imask[PatchFaces[i]] = -1;
05128 ++SO->N_Node;
05129 }
05130 }
05131 if (LocalHead) {
05132 fprintf (SUMA_STDERR,"%s: %d nodes in patch\n", FuncName, SO->N_Node);
05133 }
05134 SO->NodeList = (float *)SUMA_malloc(sizeof(float)*3*SO->N_Node);
05135 SO->FaceSetList = (int *)SUMA_malloc(sizeof(int)*PatchDim*N_PatchFaces);
05136 if (!SO->NodeList || !SO->FaceSetList) {
05137 SUMA_SL_Err("Failed to allocate");
05138 SUMA_RETURN(SO);
05139 }
05140 SO->NodeDim = 3;
05141 SO->FaceSetDim = PatchDim;
05142
05143 cnt = 0;
05144 for (i=0; i<3*N_PatchFaces; ++i) {
05145 if (imask[PatchFaces[i]] < 0) {
05146 imask[PatchFaces[i]] = cnt;
05147 SO->NodeList[3*cnt ] = NodeList[3*PatchFaces[i] ];
05148 SO->NodeList[3*cnt+1] = NodeList[3*PatchFaces[i]+1];
05149 SO->NodeList[3*cnt+2] = NodeList[3*PatchFaces[i]+2];
05150 ++cnt;
05151 }
05152 SO->FaceSetList[i] = imask[PatchFaces[i]];
05153 }
05154
05155 SUMA_RETURN(SO);
05156 }
|
|
||||||||||||||||||||||||||||
|
Stitch together two isotopic patches to calculate the volume between them.
for a single node (remember change -hits option to 1): SurfMeasures -func node_vol -spec ../SurfData/SUMA/DemoSubj_lh.spec -surf_A lh.smoothwm.asc -surf_B lh.pial.asc -nodes_1D lhpatch_1node.1D'[0]' -out_1D SM_out_1node.1D SurfPatch -spec ../SurfData/SUMA/DemoSubj_lh.spec -surf_A lh.smoothwm -surf_B lh.pial.asc -hits 1 -input lhpatch_1node.1D 0 1 (divide answer of 2.219910 by 3 (0.73997), difference at 3rd signifcant digit from SM_out_1node.1D of 0.731866) for a box: SurfMeasures -func node_vol -spec RectPly.spec -surf_A RectSurf.ply -surf_B RectSurf2.ply -nodes_1D RectAllPatch.1D'[1]' -out_1D SM_out_Rect.1D SurfPatch -spec RectPly.spec -surf_A RectSurf.ply -surf_B RectSurf2.ply -hits 3 -input RectAllPatch.1D 0 1 -vol_only Definition at line 5520 of file SUMA_GeomComp.c. References SUMA_CommonFields::DsetList, SUMA_SurfaceObject::EL, SUMA_SurfaceObject::FaceNormList, SUMA_SURF_NORM::FaceNormList, SUMA_SurfaceObject::FaceSetDim, SUMA_SurfaceObject::FaceSetList, SUMA_PATCH::FaceSetList, i, LocalHead, SUMA_EDGE_LIST::max_N_Hosts, SUMA_SurfaceObject::MF, SUMA_EDGE_LIST::min_N_Hosts, n1, n2, SUMA_SurfaceObject::N_FaceSet, SUMA_PATCH::N_FaceSet, SUMA_SurfaceObject::N_Node, SUMA_SurfaceObject::NodeDim, SUMA_SurfaceObject::NodeList, SUMA_SurfaceObject::NodeNormList, SUMA_SURF_NORM::NodeNormList, SUMA_Alloc_SurfObject_Struct(), SUMA_Boolean, SUMA_disp_vecdmat(), SUMA_disp_vecmat(), SUMA_ENTRY, SUMA_free, SUMA_Free_Surface_Object(), SUMA_freePatch(), SUMA_GetContour(), SUMA_getPatch(), SUMA_INIT_VEC, SUMA_LH, SUMA_MakeConsistent(), SUMA_malloc, SUMA_Mesh_Volume(), SUMA_RETURN, SUMA_ROW_MAJOR, SUMA_SL_Crit, SUMA_SL_Err, SUMA_SurfaceMetrics_eng(), and SUMA_SurfNorm().
05521 {
05522 static char FuncName[]={"SUMA_Pattie_Volume"};
05523 double Vol = 0.0;
05524 int N_ContEdges=0, i, i3, n, NodesPerPatch, *NewIndex = NULL, inew3, cnt, n1, n2, trouble;
05525 SUMA_PATCH *P1 = NULL;
05526 FILE *fid=NULL;
05527 SUMA_CONTOUR_EDGES *CE = NULL;
05528 SUMA_SurfaceObject *SOc = NULL;
05529 SUMA_SURF_NORM SN;
05530 SUMA_Boolean LocalHead = NOPE;
05531
05532 SUMA_ENTRY;
05533
05534 if (!SO1 || !SO2 || !Nodes || !N_Node) {
05535 SUMA_SL_Err("Bad input.");
05536 SUMA_RETURN(Vol);
05537 }
05538 if (SO1->N_Node != SO2->N_Node || SO1->N_FaceSet != SO2->N_FaceSet) {
05539 SUMA_SL_Err("Surfaces Not Isotopic");
05540 SUMA_RETURN(Vol);
05541 }
05542
05543 /* form the patch */
05544 SUMA_LH("Forming patch...");
05545 P1 = SUMA_getPatch (Nodes, N_Node, SO1->FaceSetList, SO1->N_FaceSet, SO1->MF, minPatchHits);
05546 if (!P1) {
05547 SUMA_SL_Err("Failed to create patches.\n");
05548 SUMA_RETURN(Vol);
05549 }
05550 if (!P1->N_FaceSet) {
05551 SUMA_SL_Err("No patch could be formed");
05552 SUMA_RETURN(Vol);
05553 }
05554 /* form the contour */
05555 SUMA_LH("Forming contour...");
05556 CE = SUMA_GetContour (SO1, Nodes, N_Node, &N_ContEdges, 1, P1);
05557 if (!N_ContEdges) {
05558 SUMA_SL_Err("No contour edges found.\n"
05559 "It looks like patches form\n"
05560 "closed surfaces.\n");
05561 SUMA_RETURN(Vol);
05562 }
05563 if (LocalHead) {
05564 fprintf(SUMA_STDERR,"%s:\n Found %d contour segments.\n", FuncName, N_ContEdges);
05565 }
05566
05567 /* create a mapping from old numbering scheme to new one */
05568 SUMA_LH("Creating Mapping Index...");
05569 NewIndex = (int *)SUMA_malloc(SO1->N_Node * sizeof(int));
05570 if (!NewIndex) {
05571 SUMA_SL_Crit("Failed to allocate for NewIndex");
05572 SUMA_RETURN(Vol);
05573 }
05574 SUMA_INIT_VEC(NewIndex, SO1->N_Node, -1, int);
05575 NodesPerPatch = 0;
05576 for (i=0; i < P1->N_FaceSet; ++i) {
05577 i3 = 3*i;
05578 n = P1->FaceSetList[i3]; if (NewIndex[n] < 0) { NewIndex[n] = NodesPerPatch; ++NodesPerPatch; }
05579 n = P1->FaceSetList[i3+1]; if (NewIndex[n] < 0) { NewIndex[n] = NodesPerPatch; ++NodesPerPatch; }
05580 n = P1->FaceSetList[i3+2]; if (NewIndex[n] < 0) { NewIndex[n] = NodesPerPatch; ++NodesPerPatch; }
05581 }
05582 if (LocalHead) {
05583 fprintf(SUMA_STDERR,"%s:\n"
05584 "Number of nodes in patch (%d), in N_Node (%d)\n"
05585 , FuncName, NodesPerPatch, N_Node);
05586 }
05587 if (NodesPerPatch != N_Node) {
05588 fprintf(SUMA_STDERR, "Note:\n"
05589 "Have %d nodes in patch, %d nodes in input.\n", NodesPerPatch, N_Node);
05590 }
05591
05592 /* Building composite surface */
05593 SUMA_LH("Building composite surface...");
05594 if (UseThisSO) {
05595 SOc = UseThisSO;
05596 if (SOc->NodeList || SOc->FaceSetList) {
05597 SUMA_SL_Err("You want me to use a filled SurfaceObject structure!\n"
05598 "How rude!");
05599 SUMA_RETURN(Vol);
05600 }
05601 } else {
05602 SOc = SUMA_Alloc_SurfObject_Struct(1);
05603 }
05604 SOc->N_Node = NodesPerPatch*2;
05605 SOc->N_FaceSet = P1->N_FaceSet*2+2*N_ContEdges;
05606 SOc->NodeDim = 3;
05607 SOc->FaceSetDim = 3;
05608 SOc->NodeList = (float *)SUMA_malloc(SOc->NodeDim*SOc->N_Node*sizeof(float));
05609 SOc->FaceSetList = (int *)SUMA_malloc(SOc->FaceSetDim*SOc->N_FaceSet*sizeof(int));
05610 /* first create the NodeList from S01 && SO2*/
05611 for (i=0; i<SO1->N_Node; ++i) {
05612 if (NewIndex[i] >=0) { /* this node is used */
05613 i3 = 3*i;
05614 inew3 = 3 * NewIndex[i];
05615 SOc->NodeList[inew3 ] = SO1->NodeList[i3 ];
05616 SOc->NodeList[inew3+1] = SO1->NodeList[i3+2];
05617 SOc->NodeList[inew3+2] = SO1->NodeList[i3+1];
05618 inew3 = 3 * (NewIndex[i]+NodesPerPatch);
05619 SOc->NodeList[inew3 ] = SO2->NodeList[i3 ];
05620 SOc->NodeList[inew3+1] = SO2->NodeList[i3+2];
05621 SOc->NodeList[inew3+2] = SO2->NodeList[i3+1];
05622 }
05623 }
05624 /* Now add the pre-existing patches */
05625 cnt = 0;
05626 for (i=0; i<P1->N_FaceSet; ++i) {
05627 i3 = 3*i;
05628 n = P1->FaceSetList[i3 ]; SOc->FaceSetList[cnt] = NewIndex[n]; ++cnt;
05629 n = P1->FaceSetList[i3+1]; SOc->FaceSetList[cnt] = NewIndex[n]; ++cnt;
05630 n = P1->FaceSetList[i3+2]; SOc->FaceSetList[cnt] = NewIndex[n]; ++cnt;
05631 }
05632 for (i=0; i<P1->N_FaceSet; ++i) { /* Now for SO2's */
05633 i3 = 3*i;
05634 n = P1->FaceSetList[i3 ]; SOc->FaceSetList[cnt] = NewIndex[n]+NodesPerPatch; ++cnt;
05635 n = P1->FaceSetList[i3+1]; SOc->FaceSetList[cnt] = NewIndex[n]+NodesPerPatch; ++cnt;
05636 n = P1->FaceSetList[i3+2]; SOc->FaceSetList[cnt] = NewIndex[n]+NodesPerPatch; ++cnt;
05637 }
05638
05639 /* Now you need to add the stitches, for each segment you'll need 2 triangles*/
05640 for (i=0; i<N_ContEdges; ++i) {
05641 n1 = NewIndex[CE[i].n1]; n2 = NewIndex[CE[i].n2];
05642 SOc->FaceSetList[cnt] = n1; ++cnt;
05643 SOc->FaceSetList[cnt] = n2; ++cnt;
05644 SOc->FaceSetList[cnt] = n2+NodesPerPatch; ++cnt;
05645 SOc->FaceSetList[cnt] = n1; ++cnt;
05646 SOc->FaceSetList[cnt] = n2+NodesPerPatch; ++cnt;
05647 SOc->FaceSetList[cnt] = n1+NodesPerPatch; ++cnt;
05648 }
05649
05650 /* calculate EdgeList */
05651 if (!SUMA_SurfaceMetrics_eng(SOc, "EdgeList", NULL, 0, SUMAg_CF->DsetList)){
05652 SUMA_SL_Err("Failed to create EdgeList");
05653 SUMA_RETURN(Vol);
05654 }
05655
05656 /* make sure that's a closed surface */
05657 if (SOc->EL->max_N_Hosts != 2 || SOc->EL->min_N_Hosts != 2) {
05658 SUMA_SL_Err("Created surface is not a closed one.\n"
05659 "Or patches have tessellation problems.");
05660 SUMA_RETURN(Vol);
05661 }
05662
05663 /* fix the winding */
05664 if (!SUMA_MakeConsistent(SOc->FaceSetList, SOc->N_FaceSet, SOc->EL, 0, &trouble)) {
05665 SUMA_SL_Err("Failed to make surface consistent");
05666 SUMA_RETURN(Vol);
05667 }
05668
05669 /* Now calculate FaceSetNormals and triangle areas*/
05670 SN = SUMA_SurfNorm(SOc->NodeList, SOc->N_Node, SOc->FaceSetList, SOc->N_FaceSet );
05671 SOc->NodeNormList = SN.NodeNormList;
05672 SOc->FaceNormList = SN.FaceNormList;
05673
05674 if (!SUMA_SurfaceMetrics_eng(SOc, "PolyArea", NULL, 0, SUMAg_CF->DsetList)){
05675 SUMA_SL_Err("Failed to create EdgeList");
05676 SUMA_RETURN(Vol);
05677 }
05678
05679 /* debug */
05680 if (LocalHead) {
05681 fid = fopen("Junk_NodeList.1D", "w");
05682 SUMA_disp_vecmat (SOc->NodeList, SOc->N_Node, SOc->NodeDim, 1, SUMA_ROW_MAJOR, fid, NOPE);
05683 fclose(fid);
05684 fid = fopen("Junk_FaceSetList.1D", "w");
05685 SUMA_disp_vecdmat(SOc->FaceSetList, SOc->N_FaceSet, SOc->FaceSetDim, 1, SUMA_ROW_MAJOR, fid , NOPE);
05686 fclose(fid);
05687 }
05688
05689 /* calculate the volume */
05690 SUMA_LH("Calculating volume");
05691 Vol = SUMA_Mesh_Volume(SOc, NULL, -1);
05692 if (LocalHead) {
05693 fprintf (SUMA_STDERR,"%s:\n"
05694 "Volume = %f\n", FuncName, Vol);
05695 }
05696
05697 /* cleanup */
05698 SUMA_LH("Cleanup");
05699 if (P1) SUMA_freePatch(P1); P1 = NULL;
05700 if (NewIndex) SUMA_free(NewIndex); NewIndex = NULL;
05701 if (SOc != UseThisSO) SUMA_Free_Surface_Object(SOc); SOc = NULL;
05702 if (CE) SUMA_free(CE); CE=NULL;
05703
05704 SUMA_RETURN(Vol);
05705 }
|
|
||||||||||||||||||||
|
finds the plane passing through 3 points From File : Plane_Equation.c Author : Ziad Saad Date : Thu Nov 19 14:55:54 CST 1998 Usage : Eq = SUMA_Plane_Equation (P1, P2, P3, thisEq)
Definition at line 5897 of file SUMA_GeomComp.c. References SUMA_calloc, SUMA_ENTRY, and SUMA_RETURN. Referenced by SUMA_Surf_Plane_Intersect_ROI().
05898 {/*SUMA_Plane_Equation*/
05899 float *Eq;
05900 static char FuncName[] = {"SUMA_Plane_Equation"};
05901
05902 SUMA_ENTRY;
05903 if (usethisEq) Eq = usethisEq;
05904 else Eq = (float *) SUMA_calloc(4,sizeof(float));
05905 if (!Eq)
05906 {
05907 fprintf (SUMA_STDERR, "Error %s: Failed to allocate.\n", FuncName);
05908 SUMA_RETURN (NULL);
05909 }
05910
05911 Eq[0] = P1[1] * (P2[2]-P3[2])
05912 + P2[1] * (P3[2]-P1[2])
05913 + P3[1] * (P1[2]-P2[2]);
05914
05915 Eq[1] = P1[2] * (P2[0]-P3[0])
05916 + P2[2] * (P3[0]-P1[0])
05917 + P3[2] * (P1[0]-P2[0]);
05918
05919 Eq[2] = P1[0] * (P2[1]-P3[1])
05920 + P2[0] * (P3[1]-P1[1])
05921 + P3[0] * (P1[1]-P2[1]);
05922
05923 Eq[3] = - P1[0] * (P2[1] * P3[2] - P3[1] * P2[2])
05924 - P2[0] * (P3[1] * P1[2] - P1[1] * P3[2])
05925 - P3[0] * (P1[1] * P2[2] - P2[1] * P1[2]);
05926
05927 SUMA_RETURN (Eq);
05928 }/*SUMA_Plane_Equation*/
|
|
||||||||||||||||||||
|
stretch each node along the center--node direction such that the new distance is = radius
Definition at line 1817 of file SUMA_GeomComp.c. References a, SUMA_SurfaceObject::Center, free, i, LocalHead, SUMA_SurfaceObject::N_Node, SUMA_SurfaceObject::NodeList, SUMA_COMM_STRUCT::Send, SUMA_append_replace_string(), SUMA_Boolean, SUMA_ENTRY, SUMA_etime(), SUMA_Extension(), SUMA_NODE_XYZ, SUMA_POINT_AT_DISTANCE_NORM, SUMA_RETURN, SUMA_SEG_LENGTH, SUMA_SendToSuma(), SUMA_SL_Err, SUMA_SL_Warn, and SUMA_UNIT_VEC.
01818 {
01819 static char FuncName[]={"SUMA_ProjectSurfaceToSphere"};
01820 int i=0, j=0, cnt = 0, istrt, istp;
01821 struct timeval start_time, start_time_all;
01822 float etime_GetOffset, etime_GetOffset_all, ave_dist= 0.0, dj = 0.0, ave_dist_ref= 0.0, *a=NULL;
01823 float P2[2][3], U[3], Un;
01824 SUMA_Boolean LocalHead = NOPE;
01825
01826 SUMA_ENTRY;
01827
01828 if (!SO || !SOref) { SUMA_SL_Err("NULL surface"); SUMA_RETURN(NOPE); }
01829
01830 if (LocalHead) {
01831 fprintf(SUMA_STDERR, "%s:\n"
01832 " SO Center: %f, %f, %f\n"
01833 " radius = %f\n", FuncName,
01834 SO->Center[0], SO->Center[1], SO->Center[2],
01835 radius);
01836 }
01837
01838 #ifdef FROM_THIS_NODE
01839 istrt = FROM_THIS_NODE;
01840 istp = TO_THIS_NODE+1;
01841 #else
01842 istrt = 0;
01843 istp = SO->N_Node;
01844 #endif
01845 ave_dist_ref = radius;
01846 for (i =istrt ; i<istp; ++i) {
01847 if (i == 0) {
01848 SUMA_etime(&start_time,0);
01849 }
01850 /* move node i to the reference average location
01851 Do not travel along normals, you should travel along
01852 radial direction Center-->node*/
01853 a = &(SO->NodeList[3*i]); SUMA_UNIT_VEC(SO->Center, a, U, Un);
01854 if (Un) {
01855 SUMA_POINT_AT_DISTANCE_NORM(U, SO->Center, ave_dist_ref, P2);
01856 SO->NodeList[3*i] = P2[0][0]; SO->NodeList[3*i+1] = P2[0][1]; SO->NodeList[3*i+2] = P2[0][2];
01857 } else {
01858 SUMA_SL_Err("Identical points!\n"
01859 "No coordinates modified");
01860 }
01861
01862 if (LocalHead) {
01863 if (! (i%999)) {
01864 a = &(SO->NodeList[3*i]);
01865 SUMA_SEG_LENGTH(a, SO->Center, dj);
01866 fprintf(SUMA_STDERR, "%s:\n"
01867 "node i=%d, avg_dist_ref = %f\ncnt = %d\n"
01868 "Check on P2: New dist =%f ?=? %f\n",
01869 FuncName, i, ave_dist_ref, cnt, dj, ave_dist_ref);
01870 etime_GetOffset = SUMA_etime(&start_time,1);
01871 fprintf(SUMA_STDERR, "%s: Search to %f mm took %f seconds for %d nodes.\n"
01872 "Projected completion time: %f minutes\n",
01873 FuncName, radius, etime_GetOffset, i+1,
01874 etime_GetOffset * SO->N_Node / 60.0 / (i+1));
01875 }
01876 }
01877 if (! (i%99) && cs) {
01878 if (cs->Send) { /* send the first monster (it's SOref "in SUMA" that's being modified on the fly*/
01879 if (!SUMA_SendToSuma (SOref, cs, (void *)SO->NodeList, SUMA_NODE_XYZ, 1)) {
01880 SUMA_SL_Warn("Failed in SUMA_SendToSuma\nCommunication halted.");
01881 }
01882 }
01883 }
01884
01885 #ifdef FROM_THIS_NODE
01886 {
01887 FILE *fid=NULL;
01888 char *outname=NULL, tmp[20];
01889 int ii;
01890 if (cs->Send) { /* send the first monster (it's SOref that's being modified on the fly*/
01891 if (!SUMA_SendToSuma (SOref, cs, (void *)SO->NodeList, SUMA_NODE_XYZ, 1)) {
01892 SUMA_SL_Warn("Failed in SUMA_SendToSuma\nCommunication halted.");
01893 }
01894 }
01895 sprintf(tmp,"offset_n%d", FROM_THIS_NODE);
01896 outname = SUMA_Extension("", ".1D", YUP);
01897 outname = SUMA_append_replace_string(outname, "offset.1D", "", 1);
01898 fid = fopen(outname, "w"); free(outname); outname = NULL;
01899 if (!fid) {
01900 SUMA_SL_Err("Could not open file for writing.\nCheck file permissions, disk space.\n");
01901 } else {
01902 fprintf (fid,"#Column 1 = Node index\n"
01903 "#column 2 = Neighborhood layer\n"
01904 "#Column 3 = Distance from node %d\n", 99);
01905 for (ii=0; ii<SO->N_Node; ++ii) {
01906 if (OffS->LayerVect[ii] >= 0) {
01907 fprintf(fid,"%d\t%d\t%f\n", ii, OffS->LayerVect[ii], OffS->OffVect[ii]);
01908 }
01909 }
01910 fclose(fid);
01911 }
01912 { int jnk; fprintf(SUMA_STDOUT,"Pausing, next node is %d...", i+1); jnk = getchar(); fprintf(SUMA_STDOUT,"\n"); }
01913 }
01914 #endif
01915
01916
01917 }
01918
01919
01920 SUMA_RETURN(YUP);
01921 }
|
|
|
reset the SUMA_GET_OFFSET_STRUCT after it has been used by a node
Definition at line 893 of file SUMA_GeomComp.c. References i, SUMA_GET_OFFSET_STRUCT::layers, SUMA_GET_OFFSET_STRUCT::LayerVect, LocalHead, SUMA_GET_OFFSET_STRUCT::N_layers, SUMA_Boolean, and SUMA_RETURN. Referenced by calcWithOffsets(), SUMA_Build_Cluster_From_Node_NoRec(), SUMA_EquateSurfaceSize(), and SUMA_FormNeighbOffset().
00894 {
00895 static char FuncName[]={"SUMA_Recycle_getoffsets"};
00896 int i, j;
00897 static SUMA_Boolean LocalHead = NOPE;
00898
00899 for (i=0; i < OffS->N_layers; ++i) {
00900 /* reset the layer index of used nodes in LayerVect */
00901 for (j=0; j < OffS->layers[i].N_NodesInLayer; ++j) {
00902 OffS->LayerVect[OffS->layers[i].NodesInLayer[j]] = -1;
00903 }
00904 /* reset number of nodes in each layer */
00905 OffS->layers[i].N_NodesInLayer = 0;
00906 }
00907
00908 SUMA_RETURN(YUP);
00909 }
|
|
||||||||||||||||
|
Show the SPI structure Definition at line 6642 of file SUMA_GeomComp.c. References SUMA_SurfaceObject::EL, SUMA_EDGE_LIST::EL, i, SUMA_SURF_PLANE_INTERSECT::IntersEdges, SUMA_SURF_PLANE_INTERSECT::IntersNodes, SUMA_SURF_PLANE_INTERSECT::IntersTri, SUMA_SURF_PLANE_INTERSECT::isEdgeInters, SUMA_EDGE_LIST::N_EL, SUMA_SURF_PLANE_INTERSECT::N_IntersEdges, SUMA_SURF_PLANE_INTERSECT::N_IntersTri, SUMA_Boolean, SUMA_ENTRY, and SUMA_RETURN.
06643 {
06644 static char FuncName[]={"SUMA_Show_SPI"};
06645 int i;
06646
06647 SUMA_ENTRY;
06648
06649 if (!Out) Out = SUMA_STDERR;
06650
06651 if (!SPI) {
06652 fprintf (Out,"Error %s: NULL POINTER.\n", FuncName);
06653 }
06654
06655 fprintf (Out,"Intersection Edges: %d\n[", SPI->N_IntersEdges);
06656 for (i=0; i < SPI->N_IntersEdges; ++i) {
06657 fprintf (Out, "%d, %d\n", SO->EL->EL[SPI->IntersEdges[i]][0], SO->EL->EL[SPI->IntersEdges[i]][1]);
06658 }
06659 fprintf (Out," ]\n");
06660
06661 fprintf (Out,"Intersection Nodes: %d\n[", SPI->N_IntersEdges);
06662 for (i=0; i < SO->EL->N_EL; ++i) {
06663 if (SPI->isEdgeInters[i]) fprintf (Out, "%f, %f, %f, ", SPI->IntersNodes[3*i], SPI->IntersNodes[3*i+1], SPI->IntersNodes[3*i+2]);
06664 }
06665 fprintf (Out," ]\n");
06666
06667 fprintf (Out,"Intersected Triangles: %d\n[", SPI->N_IntersTri);
06668 for (i=0; i < SPI->N_IntersTri; ++i) {
06669 fprintf (Out, "t%d\t", SPI->IntersTri[i]);
06670 }
06671 fprintf (Out," ]\n");
06672 SUMA_RETURN(YUP);
06673 }
|
|
||||||||||||
|
Function to show the contents of a SUMA_TRI_BRANCH structure Definition at line 6532 of file SUMA_GeomComp.c. References i, SUMA_TRI_BRANCH::iBranch, SUMA_TRI_BRANCH::list, SUMA_TRI_BRANCH::N_list, SUMA_Boolean, SUMA_ENTRY, and SUMA_RETURN.
06533 {
06534 static char FuncName[]={"SUMA_show_STB"};
06535 int i;
06536
06537 SUMA_ENTRY;
06538
06539 if (!Out) Out = SUMA_STDERR;
06540
06541 if (!B) {
06542 fprintf (Out, "%s: Empy structure.\n", FuncName);
06543 }
06544
06545 fprintf (Out, "%s:\tBranch #%d. %d elements in list\nlist:\t", FuncName, B->iBranch, B->N_list);
06546 for (i=0; i < B->N_list; ++i) {
06547 fprintf (Out, "%d\t", B->list[i]);
06548 }
06549 fprintf (Out, "\n");
06550
06551 SUMA_RETURN (YUP);
06552 }
|
|
||||||||||||
|
Definition at line 2598 of file SUMA_GeomComp.c. References SUMA_GET_OFFSET_STRUCT::layers, SUMA_GET_OFFSET_STRUCT::LayerVect, SUMA_GET_OFFSET_STRUCT::N_Nodes, SUMA_NODE_NEIGHB_LAYER::NodesInLayer, SUMA_GET_OFFSET_STRUCT::OffVect, SUMA_ENTRY, SUMA_free, SUMA_malloc, SUMA_RETURN, SUMA_SL_Crit, SUMA_SS2S, SUMA_StringAppend(), SUMA_StringAppend_va(), and SUMA_z_dqsort(). Referenced by SUMA_Build_Cluster_From_Node().
02599 {
02600 static char FuncName[]={"SUMA_ShowOffset_Info"};
02601 SUMA_STRING *SS = NULL;
02602 int ii, *ltmp=NULL, *imap = NULL;
02603 char *s=NULL;
02604
02605 SUMA_ENTRY;
02606
02607 SS = SUMA_StringAppend (NULL, NULL);
02608
02609 if (!OffS) {
02610 SS = SUMA_StringAppend (SS,"#NULL offset structure.\n");
02611 } else {
02612 SS = SUMA_StringAppend_va (SS,"#Node Offsets (graph distance) from node %d\n", OffS->layers[0].NodesInLayer[0]);
02613 SS = SUMA_StringAppend_va (SS,"#Column 0 = Node index\n"
02614 "#column 1 = Neighborhood layer\n"
02615 "#Column 2 = Distance from node %d\n", OffS->layers[0].NodesInLayer[0]);
02616 ltmp = (int *)SUMA_malloc(OffS->N_Nodes*sizeof(int)); /* make a copy to avoid disturbinh OffS's contents*/
02617 if (!ltmp) {
02618 SUMA_SL_Crit("Failed to allocate for ltmp");
02619 SUMA_RETURN(NULL);
02620 }
02621 for (ii=0; ii<OffS->N_Nodes; ++ii) ltmp[ii] = OffS->LayerVect[ii];
02622 imap = SUMA_z_dqsort(ltmp,OffS->N_Nodes);
02623 for (ii=0; ii<OffS->N_Nodes; ++ii) {
02624 if (OffS->LayerVect[imap[ii]] >= 0) {
02625 SS = SUMA_StringAppend_va (SS,"%6d\t%6d\t%f\n", imap[ii], OffS->LayerVect[imap[ii]], OffS->OffVect[imap[ii]]);
02626 }
02627 }
02628 }
02629 if (ltmp) SUMA_free(ltmp); ltmp = NULL;
02630 if (imap) SUMA_free(imap); imap = NULL;
02631 SUMA_SS2S(SS,s);
02632
02633 SUMA_RETURN(s);
02634 }
|
|
||||||||||||
|
Definition at line 2636 of file SUMA_GeomComp.c. References DListElmt_::data, dlist_head, dlist_tail, SUMA_OFFSET_LL_DATUM::layer, DListElmt_::next, SUMA_OFFSET_LL_DATUM::ni, SUMA_OFFSET_LL_DATUM::off, SUMA_ENTRY, SUMA_RETURN, SUMA_SS2S, SUMA_StringAppend(), and SUMA_StringAppend_va(). Referenced by SUMA_Build_Cluster_From_Node().
02637 {
02638 static char FuncName[]={"SUMA_ShowOffset_ll_Info"};
02639 SUMA_STRING *SS = NULL;
02640 DListElmt *elm = NULL;
02641 SUMA_OFFSET_LL_DATUM *dat=NULL;
02642 int ii;
02643 char *s=NULL;
02644
02645 SUMA_ENTRY;
02646
02647 SS = SUMA_StringAppend (NULL, NULL);
02648
02649 if (!list) {
02650 SS = SUMA_StringAppend (SS,"#NULL offset list.\n");
02651 } else {
02652 do {
02653 if (!elm) elm = dlist_head(list);
02654 else elm = elm->next;
02655 dat = (SUMA_OFFSET_LL_DATUM *)elm->data;
02656 if (elm == dlist_head(list)) {
02657 SS = SUMA_StringAppend_va (SS,"#Node Offsets (graph distance) from node %d\n", dat->ni);
02658 SS = SUMA_StringAppend_va (SS,"#Column 0 = Node index\n"
02659 "#column 1 = Neighborhood layer\n"
02660 "#Column 2 = Distance from node %d\n", dat->ni);
02661 }
02662 SS = SUMA_StringAppend_va (SS,"%6d\t%6d\t%f\n", dat->ni, dat->layer, dat->off);
02663 } while (elm != dlist_tail(list));
02664 }
02665 SUMA_SS2S(SS,s);
02666
02667 SUMA_RETURN(s);
02668 }
|
|
||||||||||||
|
Definition at line 5313 of file SUMA_GeomComp.c. References SUMA_PATCH::FaceSetIndex, SUMA_PATCH::FaceSetList, i, SUMA_PATCH::N_FaceSet, SUMA_PATCH::nHits, SUMA_Boolean, SUMA_ENTRY, and SUMA_RETURN. Referenced by SUMA_GetContour().
05314 {
05315 static char FuncName[]={"SUMA_freePatch"};
05316 int ip, i;
05317
05318 SUMA_ENTRY;
05319
05320 if (!Out) Out = stderr;
05321
05322 fprintf (Out, "Patch Contains %d triangles:\n", Patch->N_FaceSet);
05323 fprintf (Out, "FaceIndex (nHits): FaceSetList[0..2]\n");
05324 for (i=0; i < Patch->N_FaceSet; ++i) {
05325 ip = 3 * i;
05326 fprintf (Out, "%d(%d): %d %d %d\n",
05327 Patch->FaceSetIndex[i], Patch->nHits[i], Patch->FaceSetList[ip],
05328 Patch->FaceSetList[ip+1], Patch->FaceSetList[ip+2]);
05329 }
05330
05331 SUMA_RETURN(YUP);
05332 }
|
|
||||||||||||||||||||||||
|
function to subdivide triangles to meet a maxarea criterion Divisions are done by adding a node at the centroid of the triangle to be subdivided. Bad idea, for very large triangles, such as produced by convex hull, you could end up with nodes that have hundreds of neighbors...
Definition at line 56 of file SUMA_GeomComp.c. References a, c, SUMA_SurfaceObject::FaceSetList, LocalHead, n0, n1, n2, SUMA_SurfaceObject::NodeList, SUMA_Boolean, SUMA_ENTRY, SUMA_FACE_CENTROID, SUMA_realloc, SUMA_RETURN, SUMA_SL_Crit, SUMA_SL_Err, and SUMA_TRI_AREA.
00057 {
00058 static char FuncName[]={"SUMA_Subdivide_Mesh"};
00059 int in, it, N_NodeAlloc, N_FaceSetAlloc, N_Node, N_FaceSet, it3, in0, in1, in2, inc3, inc, itn, itn3;
00060 float c[3];
00061 float *NodeList = NULL, a, *n1, *n2, *n0;
00062 int *FaceSetList = NULL;
00063 SUMA_SurfaceObject SObuf, *SO=NULL;
00064 SUMA_Boolean LocalHead = YUP;
00065
00066 SUMA_ENTRY;
00067
00068 SO = &SObuf;
00069
00070 N_NodeAlloc = N_Node = *N_Nodep;
00071 N_FaceSetAlloc = N_FaceSet = *N_FaceSetp;
00072 NodeList = *NodeListp;
00073 FaceSetList = *FaceSetListp;
00074 SO->NodeList = NodeList; SO->FaceSetList = FaceSetList;
00075 if (!NodeList || !FaceSetList) { SUMA_SL_Err("NULL input"); SUMA_RETURN(NOPE); }
00076
00077 it = 0; /* triangle index */
00078 while (it < N_FaceSet) {
00079 it3 = 3*it;
00080 in0 = FaceSetList[it3]; in1 = FaceSetList[it3+1]; in2 = FaceSetList[it3+2]; /* node indices */
00081 n0 = &(NodeList[3*in0]); n1 = &(NodeList[3*in1]); n2 = &(NodeList[3*in2]); /* node coordinates */
00082 SUMA_TRI_AREA(n0, n1, n2, a); /* area of triangle */
00083 if (a > maxarea) {
00084 if (N_NodeAlloc <= N_Node) { /* need to realloc ?*/
00085 N_NodeAlloc += 20000;
00086 NodeList = (float *)SUMA_realloc(NodeList, N_NodeAlloc * 3 * sizeof(float));
00087 /* you always add 2 triangles per new node here */
00088 N_FaceSetAlloc += 40000;
00089 FaceSetList = (int *)SUMA_realloc(FaceSetList, N_FaceSetAlloc * 3 * sizeof(int));
00090 if (!NodeList || !FaceSetList) { SUMA_SL_Crit("Failed to realloc"); SUMA_RETURN(NOPE); }
00091 SO->NodeList = NodeList; SO->FaceSetList = FaceSetList;
00092 }
00093 SUMA_FACE_CENTROID(SO, it, c); /* c is the centroid of triangle it */
00094 inc = N_Node; inc3 = inc*3; ++N_Node; /* index of new centroid node */
00095 NodeList[inc3] = c[0]; NodeList[inc3+1] = c[1]; NodeList[inc3+2] = c[2]; /* add new centroid to bottom of list */
00096 FaceSetList[it3+2] = inc; /* old triangle is now 1st new triangle in0 in1 inc */
00097 itn = N_FaceSet; itn3 = 3 * itn; ++N_FaceSet; /* index of new second triangle */
00098 FaceSetList[itn3] = inc; FaceSetList[itn3+1] = in1; FaceSetList[itn3+2] = in2;
00099 itn = N_FaceSet; itn3 = 3 * itn; ++N_FaceSet; /* index of new third triangle */
00100 FaceSetList[itn3] = inc; FaceSetList[itn3+1] = in2; FaceSetList[itn3+2] = in0;
00101 } else {
00102 ++it;
00103 }
00104 }
00105
00106 /* reallocate */
00107 FaceSetList = (int *)SUMA_realloc(FaceSetList, N_FaceSet * 3 * sizeof(int));
00108 NodeList = (float *)SUMA_realloc(NodeList, N_Node * 3 * sizeof(float));
00109
00110 *NodeListp = NodeList;
00111 *FaceSetListp = FaceSetList;
00112 *N_FaceSetp = N_FaceSet;
00113 *N_Nodep = N_Node;
00114
00115 SUMA_RETURN(YUP);
00116 }
|
|
||||||||||||
|
Determines the intersection of a plane and a surface. SPI = SUMA_Surf_Plane_Intersect (SO, PlaneEq)
Definition at line 5955 of file SUMA_GeomComp.c. References SUMA_SurfaceObject::EL, SUMA_EDGE_LIST::EL, SUMA_EDGE_LIST::ELps, i, SUMA_SURF_PLANE_INTERSECT::IntersEdges, SUMA_SURF_PLANE_INTERSECT::IntersNodes, SUMA_SURF_PLANE_INTERSECT::IntersTri, SUMA_SURF_PLANE_INTERSECT::isEdgeInters, SUMA_SURF_PLANE_INTERSECT::isNodeInMesh, SUMA_SURF_PLANE_INTERSECT::isTriHit, LocalHead, n1, n2, SUMA_EDGE_LIST::N_EL, SUMA_SURF_PLANE_INTERSECT::N_IntersEdges, SUMA_SURF_PLANE_INTERSECT::N_IntersTri, SUMA_SurfaceObject::N_Node, SUMA_SURF_PLANE_INTERSECT::N_NodesInMesh, SUMA_SurfaceObject::NodeList, SUMA_Allocate_SPI(), SUMA_Boolean, SUMA_calloc, SUMA_ENTRY, SUMA_etime(), SUMA_free, SUMA_free_SPI(), SUMA_RETURN, and SUMA_SIGN. Referenced by SUMA_Surf_Plane_Intersect_ROI().
05956 {/*SUMA_Surf_Plane_Intersect*/
05957 static char FuncName[]={"SUMA_Surf_Plane_Intersect"};
05958 int i, k , k3, i3, n1, n2;
05959 float DT_ABVBEL, DT_POSNEG, u;
05960 float *NodePos;
05961 SUMA_SURF_PLANE_INTERSECT *SPI;
05962 struct timeval start_time, start_time2;
05963 SUMA_Boolean LocalHead = NOPE;
05964 SUMA_Boolean Hit;
05965
05966 SUMA_ENTRY;
05967
05968 /* Start timer for next function */
05969 SUMA_etime(&start_time2,0);
05970
05971 if (LocalHead) fprintf(SUMA_STDERR, "%s : Determining intersecting segments ...\n", FuncName);
05972
05973 /* allocate for the return structure.
05974 NOTE: If (in a different form of this function) you do not allocate for SPI each time you call the function, make sure you reset all
05975 elements of the following vector fields:
05976 IsTriHit[] = NOPE;
05977 TriBranch[] = 0
05978 */
05979 SPI = SUMA_Allocate_SPI (SO);
05980 if (!SPI) {
05981 fprintf (SUMA_STDERR, "Error %s: Failed in SUMA_Allocate_SPI\n", FuncName);
05982 SUMA_RETURN (SPI);
05983 }
05984
05985 /* allocate for temporary stuff */
05986 NodePos = (float *) SUMA_calloc (SO->N_Node , sizeof(float));
05987
05988 if (!NodePos )
05989 {
05990 fprintf (SUMA_STDERR, "Error %s: Could not allocate in SUMA_Surf_Plane_Intersect\n", FuncName);
05991 SUMA_free_SPI (SPI); SPI = NULL;
05992 SUMA_RETURN (SPI);
05993 }
05994
05995
05996 /* Start timer for next function */
05997 SUMA_etime(&start_time,0);
05998
05999 /* Find out which nodes are above and which are below the plane */
06000 for (k=0;k<SO->N_Node; ++k)
06001 {
06002 k3 = 3*k;
06003 NodePos[k] = PlaneEq[0] * SO->NodeList[k3] + PlaneEq[1] * SO->NodeList[k3+1]
06004 +PlaneEq[2] * SO->NodeList[k3+2] + PlaneEq[3] ;
06005 }
06006
06007 /* stop timer */
06008 DT_ABVBEL = SUMA_etime(&start_time,1);
06009
06010
06011 /*
06012 NodePos is < 0 for nodes below the plane and > 0 for points above the plane
06013 Go through each connection and determine if it intersects the plane
06014 If a segment intersects the surface, it means that the sign
06015 of p would be <= 0 (each point is on a different side of the plane)
06016 */
06017
06018 /* Start timer for next function */
06019 SUMA_etime(&start_time,0);
06020
06021 /*
06022 Determine the segments intersecting the surface,
06023 The triangles that contain these segments.
06024 The nodes that form the intersected segments
06025 */
06026 SPI->N_IntersEdges = 0;
06027 SPI->N_IntersTri = 0;
06028 SPI->N_NodesInMesh = 0;
06029 k=0;
06030 Hit = NOPE;
06031 while (k < SO->EL->N_EL)
06032 {
06033 /* find out if segment intersects */
06034 /* if (SUMA_IS_NEG(NodePos[SO->EL->EL[k][0]] * NodePos[SO->EL->EL[k][1]])) { *//* can speed this check by explicitly checking for sign difference:
06035 if (SUMA_SIGN(a) != SUMA_SIGN(b)) ... */
06036 if (SUMA_SIGN(NodePos[SO->EL->EL[k][0]]) != SUMA_SIGN(NodePos[SO->EL->EL[k][1]]) ) {
06037 Hit = YUP;
06038 /* find the intersection point in that segment */
06039 u = -NodePos[SO->EL->EL[k][0]] / (NodePos[SO->EL->EL[k][1]] - NodePos[SO->EL->EL[k][0]]);
06040 i3 = 3 * k;
06041 n1 = 3 * SO->EL->EL[k][0];
06042 n2 = 3 * SO->EL->EL[k][1];
06043
06044 SPI->IntersNodes[i3] = SO->NodeList[n1] + u * ( SO->NodeList[n2] - SO->NodeList[n1] ); ++i3; ++n2; ++n1;
06045 SPI->IntersNodes[i3] = SO->NodeList[n1] + u * ( SO->NodeList[n2] - SO->NodeList[n1] ); ++i3; ++n2; ++n1;
06046 SPI->IntersNodes[i3] = SO->NodeList[n1] + u * ( SO->NodeList[n2] - SO->NodeList[n1] ); ++i3; ++n2; ++n1;
06047
06048 /*
06049 fprintf (SUMA_STDERR,"%s: Edge %d, IntersNodes[%d]= [%f, %f, %f]\n",
06050 FuncName, k, 3*k, SPI->IntersNodes[3*k], SPI->IntersNodes[3*k+1], SPI->IntersNodes[3*k+2]);
06051 */
06052
06053 /* Store the intersected segment */
06054 SPI->IntersEdges[SPI->N_IntersEdges] = k;
06055 ++SPI->N_IntersEdges;
06056
06057 /* mark this segment in the boolean vector to speed up some other functions */
06058 SPI->isEdgeInters[k] = YUP;
06059
06060 /* Store the index of the triangle hosting this edge*/
06061 if (!SPI->isTriHit[SO->EL->ELps[k][1]]) {
06062 SPI->IntersTri[SPI->N_IntersTri] = SO->EL->ELps[k][1];
06063 ++(SPI->N_IntersTri);
06064 SPI->isTriHit[SO->EL->ELps[k][1]] = YUP;
06065 }
06066
06067 /* mark the nodes forming the intersection edges */
06068 if (!SPI->isNodeInMesh[SO->EL->EL[k][0]]) {
06069 SPI->isNodeInMesh[SO->EL->EL[k][0]] = YUP;
06070 ++(SPI->N_NodesInMesh);
06071 }
06072 if (!SPI->isNodeInMesh[SO->EL->EL[k][1]]) {
06073 SPI->isNodeInMesh[SO->EL->EL[k][1]] = YUP;
06074 ++(SPI->N_NodesInMesh);
06075 }
06076 } else {
06077 Hit = NOPE;
06078 }
06079
06080 /* skip ahead of duplicate edge listings */
06081 if (SO->EL->ELps[k][2] > 0) {
06082 if (Hit) { /* you must mark these triangles */
06083 i3 = 3 * k;
06084 for (i=1; i < SO->EL->ELps[k][2]; ++i) {
06085 SPI->isEdgeInters[k+i] = YUP;
06086 n1 = 3 * (k+i);
06087 SPI->IntersNodes[n1] = SPI->IntersNodes[i3]; ++i3; ++n1;
06088 SPI->IntersNodes[n1] = SPI->IntersNodes[i3]; ++i3; ++n1;
06089 SPI->IntersNodes[n1] = SPI->IntersNodes[i3]; ++i3; ++n1;
06090 /*
06091 fprintf (SUMA_STDERR,"%s: Edge %d, IntersNodes[%d]= [%f, %f, %f]\n",
06092 FuncName, k+i, n1, SPI->IntersNodes[3*(k+i)], SPI->IntersNodes[3*(k+i)+1], SPI->IntersNodes[3*(k+i)+2]);
06093 */
06094 if (!SPI->isTriHit[SO->EL->ELps[k+i][1]]) {
06095 SPI->IntersTri[SPI->N_IntersTri] = SO->EL->ELps[k+i][1];
06096 ++(SPI->N_IntersTri);
06097 SPI->isTriHit[SO->EL->ELps[k+i][1]] = YUP;
06098 }
06099 }
06100 }
06101 k += SO->EL->ELps[k][2];
06102 } else ++k;
06103 }
06104
06105
06106 /* stop timer */
06107 DT_POSNEG = SUMA_etime(&start_time,1);
06108
06109 if (LocalHead) fprintf (SUMA_STDERR, "%s: Found %d intersect segments, %d intersected triangles, %d nodes in mesh (exec time %f + %f = %f secs).\n",
06110 FuncName, SPI->N_IntersEdges, SPI->N_IntersTri, SPI->N_NodesInMesh, DT_ABVBEL, DT_POSNEG, DT_ABVBEL + DT_POSNEG);
06111
06112 /* free locally allocated memory */
06113 if (NodePos) SUMA_free (NodePos);
06114
06115
06116 SUMA_RETURN (SPI);
06117 }/*SUMA_Surf_Plane_Intersect*/
|
|
||||||||||||||||||||
|
a wrapper function for SUMA_Surf_Plane_Intersect that returns the intersection in the form of an ROI datum
Definition at line 6131 of file SUMA_GeomComp.c. References SUMA_SurfaceObject::idcode_str, SUMA_SURF_PLANE_INTERSECT::IntersEdges, SUMA_SURF_PLANE_INTERSECT::IntersTri, SUMA_SURF_PLANE_INTERSECT::isNodeInMesh, LocalHead, SUMA_CommonFields::MessageList, SUMA_SURF_PLANE_INTERSECT::N_IntersEdges, SUMA_SURF_PLANE_INTERSECT::N_IntersTri, SUMA_ROI_DATUM::N_n, SUMA_SURF_PLANE_INTERSECT::N_NodesInMesh, SUMA_ROI_DATUM::N_t, SUMA_ROI_DATUM::nDistance, SUMA_SurfaceObject::NodeList, SUMA_ROI_DATUM::nPath, ROIO_type, SMA_LogAndPopup, SMT_Critical, SUMA_AddDO(), SUMA_AllocateROI(), SUMA_AllocROIDatum(), SUMA_Boolean, SUMA_calloc, SUMA_Dijkstra(), SUMA_ENTRY, SUMA_free, SUMA_free_SPI(), SUMA_freeROI(), SUMA_FreeROIDatum(), SUMA_IntersectionStrip(), SUMA_LOCAL, SUMA_Plane_Equation(), SUMA_RegisterMessage(), SUMA_RETURN, SUMA_ROI_EdgeGroup, SUMA_ROI_FaceGroup, SUMA_ROI_NodeGroup, SUMA_ROI_NodeSegment, SUMA_Surf_Plane_Intersect(), SUMAg_N_DOv, SUMA_ROI_DATUM::tDistance, SUMA_ROI_DATUM::tPath, and SUMA_ROI_DATUM::Type. Referenced by SUMA_cb_DrawROI_Join(), SUMA_LinkTailNodeToNodeStroke(), SUMA_LinkThisNodeToNodeInStroke(), and SUMA_ProcessBrushStroke().
06132 {
06133 static char FuncName[]={"SUMA_Surf_Plane_Intersect_ROI"};
06134 SUMA_ROI_DATUM *ROId=NULL;
06135 SUMA_Boolean LocalHead = NOPE;
06136 int N_left;
06137 SUMA_SURF_PLANE_INTERSECT *SPI = NULL;
06138 SUMA_ROI *ROIe = NULL, *ROIt = NULL, *ROIn = NULL, *ROIts = NULL;
06139 float *Eq = NULL;
06140 /* The 3 flags below are for debugging. */
06141 SUMA_Boolean DrawIntersEdges=NOPE; /* Draw edges intersected by plane */
06142 SUMA_Boolean DrawIntersTri = NOPE; /* Draw triangles intersected by plane */
06143 SUMA_Boolean DrawIntersNodeStrip = NOPE; /* Draw intersection node strip which is the shortest path between beginning and ending nodes */
06144 SUMA_Boolean DrawIntersTriStrip=NOPE; /* Draw intersection triangle strip which is the shortest path between beginning and ending nodes */
06145
06146 SUMA_ENTRY;
06147
06148 /* computing plane's equation */
06149 Eq = SUMA_Plane_Equation ( &(SO->NodeList[3*Nfrom]),
06150 P,
06151 &(SO->NodeList[3*Nto]) , NULL);
06152
06153 if (!Eq) {
06154 fprintf(SUMA_STDOUT,"Error %s: Failed in SUMA_Plane_Equation.\n", FuncName);
06155 SUMA_RETURN(ROId);
06156 }
06157
06158 if (LocalHead) fprintf (SUMA_STDERR, "%s: Computing Intersection with Surface.\n", FuncName);
06159 SPI = SUMA_Surf_Plane_Intersect (SO, Eq);
06160 if (!SPI) {
06161 fprintf(SUMA_STDOUT,"Error %s: Failed in SUMA_Surf_Plane_Intersect.\n", FuncName);
06162 SUMA_RETURN(ROId);
06163 }
06164
06165 if (DrawIntersEdges) {
06166 /* Show all intersected edges */
06167 ROIe = SUMA_AllocateROI (SO->idcode_str, SUMA_ROI_EdgeGroup, "SurfPlane Intersection - Edges", SPI->N_IntersEdges, SPI->IntersEdges);
06168 if (!ROIe) {
06169 fprintf(SUMA_STDERR,"Error %s: Failed in SUMA_AllocateROI.\n", FuncName);
06170 } else {
06171 if (!SUMA_AddDO (SUMAg_DOv, &SUMAg_N_DOv, (void *)ROIe, ROIO_type, SUMA_LOCAL)) {
06172 fprintf(SUMA_STDERR,"Error %s: Failed in SUMA_AddDO.\n", FuncName);
06173 }
06174 }
06175 }
06176
06177 if (DrawIntersTri) {
06178 /* Show all intersected triangles */
06179 ROIt = SUMA_AllocateROI (SO->idcode_str, SUMA_ROI_FaceGroup, "SurfPlane Intersection - Triangles", SPI->N_IntersTri, SPI->IntersTri);
06180 if (!ROIt) {
06181 fprintf(SUMA_STDERR,"Error %s: Failed in SUMA_AllocateROI.\n", FuncName);
06182 } else {
06183 if (!SUMA_AddDO (SUMAg_DOv, &SUMAg_N_DOv, (void *)ROIt, ROIO_type, SUMA_LOCAL)) {
06184 fprintf(SUMA_STDERR,"Error %s: Failed in SUMA_AddDO.\n", FuncName);
06185 }
06186 }
06187 }
06188
06189 /* create ROId */
06190 ROId = SUMA_AllocROIDatum ();
06191 ROId->Type = SUMA_ROI_NodeSegment;
06192
06193 /* calculate shortest path */
06194 N_left = SPI->N_NodesInMesh;
06195 ROId->nPath = SUMA_Dijkstra (SO, Nfrom, Nto, SPI->isNodeInMesh, &N_left, 1, &(ROId->nDistance), &(ROId->N_n));
06196 if (ROId->nDistance < 0 || !ROId->nPath) {
06197 fprintf(SUMA_STDERR,"\aError %s: Failed in fast SUMA_Dijkstra.\n*** Two points are not connected by intersection. Repeat last selection.\n", FuncName);
06198
06199 /* clean up */
06200 if (SPI) SUMA_free_SPI (SPI);
06201 SPI = NULL;
06202 if (ROId) SUMA_FreeROIDatum (ROId);
06203 SUMA_RETURN(NULL);
06204 }
06205
06206 if (LocalHead) fprintf (SUMA_STDERR, "%s: Shortest inter nodal distance along edges between nodes %d <--> %d (%d nodes) is %f.\n",
06207 FuncName, Nfrom, Nto, ROId->N_n, ROId->nDistance);
06208
06209
06210 #if 0
06211
06212 /* FOR FUTURE USAGE:
06213 When drawing on the surface, it is possible to end up with node paths for which the
06214 triangle strip tracing routines fail. That's paretly because it is possible for these
06215 node paths to visit one node more than once, eg: ... 34 23 34 ....
06216 That is OK for drawing purposes but not for say, making measurements on the surface.
06217 */
06218
06219 /* calculate shortest path along the intersection of the plane with the surface */
06220 /* get the triangle path corresponding to shortest distance between Nx and Ny */
06221
06222 /* Old Method: Does not result is a strip of triangle that is continuous or connected
06223 by an intersected edge. Function is left here for historical reasons.
06224 tPath = SUMA_NodePath_to_TriPath_Inters (SO, SPI, Path, N_Path, &N_Tri); */
06225
06226 /* you should not need to go much larger than NodeDist except when you are going for
06227 1 or 2 triangles away where discrete jumps in d might exceed the limit.
06228 Ideally, you want this measure to be 1.5 NodeDist or say, 15 mm, whichever is less.... */
06229
06230 /* THIS SHOULD BE OPTIONAL */
06231 ROId->tPath = SUMA_IntersectionStrip (SO, SPI, ROId->nPath, ROId->N_n, &(ROId->tDistance), 2.5 *ROId->nDistance, &(ROId->N_t));
06232 if (!ROId->tPath) {
06233 fprintf(SUMA_STDERR,"Error %s: Failed in SUMA_IntersectionStrip. Proceeding\n", FuncName);
06234 /* do not stop here, it is OK if you can't find the triangle strip */
06235 /* if (ROId) SUMA_FreeROIDatum (ROId);
06236 SUMA_RETURN(NULL); */
06237 } else {
06238 /* ROId->tPath has a potentially enourmous chunk of memory allocated for it. Trim the fat. */
06239 {
06240 int *tPath_tmp=NULL, i_tmp=0;
06241 tPath_tmp = (int *)SUMA_calloc (ROId->N_t, sizeof(int));
06242 if (!tPath_tmp) {
06243 SUMA_RegisterMessage (SUMAg_CF->MessageList, "Failed to allocate for tpath_tmp", FuncName, SMT_Critical, SMA_LogAndPopup);
06244 SUMA_RETURN(NULL);
06245 }
06246 for (i_tmp=0; i_tmp<ROId->N_t; ++i_tmp) tPath_tmp[i_tmp] = ROId->tPath[i_tmp];
06247 SUMA_free(ROId->tPath);
06248 ROId->tPath = tPath_tmp;
06249 }
06250
06251 fprintf (SUMA_STDERR, "%s: Shortest inter nodal distance along surface between nodes %d <--> %d is %f.\nTiangle 1 is %d\n",
06252 FuncName, Nfrom, Nto, ROId->tDistance, ROId->tPath[0]);
06253
06254 if (DrawIntersTriStrip) {
06255 /* Show intersected triangles, along shortest path */
06256 ROIts = SUMA_AllocateROI (SO->idcode_str, SUMA_ROI_FaceGroup, "SurfPlane Intersection - Triangles- Shortest", ROId->N_t, ROId->tPath);
06257 if (!ROIts) {
06258 fprintf(SUMA_STDERR,"Error %s: Failed in SUMA_AllocateROI.\n", FuncName);
06259 if (ROIn) SUMA_freeROI(ROIn);
06260 if (ROIts) SUMA_freeROI(ROIts);
06261 if (ROId) SUMA_FreeROIDatum (ROId);
06262 SUMA_RETURN(NULL);
06263 }
06264 if (!SUMA_AddDO (SUMAg_DOv, &SUMAg_N_DOv, (void *)ROIts, ROIO_type, SUMA_LOCAL)) {
06265 fprintf(SUMA_STDERR,"Error %s: Failed in SUMA_AddDO.\n", FuncName);
06266 if (ROIn) SUMA_freeROI(ROIn);
06267 if (ROIts) SUMA_freeROI(ROIts);
06268 if (ROId) SUMA_FreeROIDatum (ROId);
06269 SUMA_RETURN(NULL);
06270 }
06271 }
06272
06273 if (ROId->nPath && DrawIntersNodeStrip) {
06274 #if 0
06275 /* Show me the Path */
06276 for (ii=0; ii < ROId->N_n; ++ii) fprintf(SUMA_STDERR," %d\t", ROId->nPath[ii]);
06277 #endif
06278
06279 /* Show Path */
06280 ROIn = SUMA_AllocateROI (SO->idcode_str, SUMA_ROI_NodeGroup, "SurfPlane Intersection - Nodes", ROId->N_n, ROId->nPath);
06281 if (!ROIn) {
06282 fprintf(SUMA_STDERR,"Error %s: Failed in SUMA_AllocateROI.\n", FuncName);
06283 if (ROIn) SUMA_freeROI(ROIn);
06284 if (ROIts) SUMA_freeROI(ROIts);
06285 if (ROId) SUMA_FreeROIDatum (ROId);
06286 SUMA_RETURN(NULL);
06287 }
06288 if (!SUMA_AddDO (SUMAg_DOv, &SUMAg_N_DOv, (void *)ROIn, ROIO_type, SUMA_LOCAL)) {
06289 fprintf(SUMA_STDERR,"Error %s: Failed in SUMA_AddDO.\n", FuncName);
06290 if (ROIn) SUMA_freeROI(ROIn);
06291 if (ROIts) SUMA_freeROI(ROIts);
06292 if (ROId) SUMA_FreeROIDatum (ROId);
06293 SUMA_RETURN(NULL);
06294 }
06295
06296 }
06297 }
06298 #endif
06299
06300 if (LocalHead) fprintf(SUMA_STDERR,"%s: Freeing Eq...\n", FuncName);
06301 if (Eq) SUMA_free(Eq);
06302
06303 if (LocalHead) fprintf(SUMA_STDERR,"%s: Freeing SPI...\n", FuncName);
06304 if (SPI) SUMA_free_SPI (SPI);
06305
06306 if (LocalHead) fprintf(SUMA_STDERR,"%s:Done Freeing...\n", FuncName);
06307
06308 SUMA_RETURN(ROId);
06309 }
|
|
||||||||||||||||||||||||||||||||||||||||||||||||
|
performs smoothing based on Taubin's smoothing algorithm in Geometric Signal Processing on Polygonal Meshes (Eurographics 2000) fout = SUMA_Taubin_Smooth (SUMA_SurfaceObject *SO, float **wgt, float lambda, float mu, float *fin, int N_iter, int vpn, d_order, float *fout_user, SUMA_COMM_STRUCT *cs);
Definition at line 2363 of file SUMA_GeomComp.c. References SUMA_NODE_FIRST_NEIGHB::FirstNeighb, SUMA_SurfaceObject::FN, fout, ftmp, i, LocalHead, SUMA_NODE_FIRST_NEIGHB::N_Neighb, SUMA_SurfaceObject::N_Node, SUMA_COMM_STRUCT::Send, SUMA_Boolean, SUMA_calloc, SUMA_COLUMN_MAJOR, SUMA_ENTRY, SUMA_free, SUMA_INDEXING_ORDER, SUMA_malloc, SUMA_NODE_XYZ, SUMA_RETURN, SUMA_ROW_MAJOR, SUMA_SendToSuma(), SUMA_SL_Crit, SUMA_SL_Err, SUMA_SL_Warn, and vpn. Referenced by SUMA_Reposition_Touchup(), and SUMA_SkullMask().
02368 {
02369 static char FuncName[]={"SUMA_Taubin_Smooth"};
02370 float *fout_final=NULL, *fbuf=NULL, *fin=NULL, *fout=NULL, *fin_next=NULL, *ftmp=NULL;
02371 float fp, dfp, fpj;
02372 int i, n , k, j, niter, vnk, n_offset, DoThis;
02373 SUMA_Boolean LocalHead = NOPE;
02374
02375 SUMA_ENTRY;
02376
02377 if (N_iter % 2) {
02378 SUMA_SL_Err("N_iter must be an even number\n");
02379 SUMA_RETURN(NULL);
02380 }
02381
02382 if (!SO || !fin_orig) {
02383 SUMA_SL_Err("NULL SO or fin_orig\n");
02384 SUMA_RETURN(NULL);
02385 }
02386 if (!SO->FN) {
02387 SUMA_SL_Err("NULL SO->FN\n");
02388 SUMA_RETURN(NULL);
02389 }
02390
02391 if (vpn < 1) {
02392 SUMA_SL_Err("vpn < 1\n");
02393 SUMA_RETURN(NULL);
02394 }
02395
02396 if (fout_final_user == fin_orig) {
02397 SUMA_SL_Err("fout_final_user == fin_orig");
02398 SUMA_RETURN(NULL);
02399 }
02400
02401 if (!fout_final_user) { /* allocate for output */
02402 fout_final = (float *)SUMA_calloc(SO->N_Node * vpn, sizeof(float));
02403 if (!fout_final) {
02404 SUMA_SL_Crit("Failed to allocate for fout_final\n");
02405 SUMA_RETURN(NULL);
02406 }
02407 }else {
02408 fout_final = fout_final_user; /* pre-allocated */
02409 }
02410
02411 if (d_order == SUMA_COLUMN_MAJOR) {
02412 SUMA_SL_Warn("SUMA_COLUMN_MAJOR has not been thoroughly tested.");
02413 }
02414
02415 if (cs->Send) {
02416 if(vpn != 3) {
02417 SUMA_SL_Warn("It does not look like you are smoothing coordinates!\nCommunication halted.");
02418 cs->Send = NOPE;
02419 }
02420 if (d_order == SUMA_COLUMN_MAJOR) {
02421 SUMA_SL_Warn("Talking with SUMA_COLUMN_MAJOR has not been tested.");
02422 }
02423 }
02424
02425 /* allocate for buffer */
02426 fbuf = (float *)SUMA_calloc(SO->N_Node * vpn, sizeof(float));
02427 if (!fbuf) {
02428 SUMA_SL_Crit("Failed to allocate for fbuf\n");
02429 SUMA_RETURN(NULL);
02430 }
02431
02432 if (LocalHead) {
02433 fprintf (SUMA_STDERR,"%s: Mu = %f, Lambda = %f\nShould have M(%f)< -L(%f) < 0\nN_iter=%d\n",
02434 FuncName, mu, lambda, mu, -lambda, N_iter);
02435 }
02436
02437 if (cs->Send) { /* send the first monster */
02438 if (!SUMA_SendToSuma (SO, cs, (void *)fin_orig, SUMA_NODE_XYZ, 1)) {
02439 SUMA_SL_Warn("Failed in SUMA_SendToSuma\nCommunication halted.");
02440 }
02441 }
02442
02443 fin_next = fin_orig;
02444 switch (d_order) {
02445 case SUMA_COLUMN_MAJOR:
02446 for (niter=0; niter < N_iter; ++niter) {
02447 if ( niter % 2 ) { /* odd */
02448 fin = fin_next; /* input from previous output buffer */
02449 fout = fout_final; /* results go into final vector */
02450 fin_next = fout_final; /* in the next iteration, the input is from fout_final */
02451 } else { /* even */
02452 /* input data is in fin_new */
02453 fin = fin_next;
02454 fout = fbuf; /* results go into buffer */
02455 fin_next = fbuf; /* in the next iteration, the input is from the buffer */
02456 }
02457 for (k=0; k < vpn; ++k) {
02458 n_offset = k * SO->N_Node; /* offset of kth node value in fin */
02459 for (n=0; n < SO->N_Node; ++n) {
02460 DoThis = 1;
02461 if (nmask && !nmask[n]) DoThis = 0;
02462 vnk = n+n_offset;
02463 if (DoThis) {
02464 fp = fin[vnk]; /* kth value at node n */
02465 dfp = 0.0;
02466 for (j=0; j < SO->FN->N_Neighb[n]; ++j) { /* calculating the laplacian */
02467 fpj = fin[SO->FN->FirstNeighb[n][j]+n_offset]; /* value at jth neighbor of n */
02468 if (wgt) dfp += wgt[n][j] * (fpj - fp);
02469 else dfp += (fpj - fp); /* will apply equal weight later */
02470 }/* for j*/
02471 if (niter%2) { /* odd */
02472 if (wgt) fout[vnk] = fin[vnk] + mu * dfp;
02473 else fout[vnk] = fin[vnk] + mu * dfp / (float)SO->FN->N_Neighb[n]; /* apply equal weight factor here */
02474 }else{ /* even */
02475 if (wgt) fout[vnk] = fin[vnk] + lambda * dfp;
02476 else fout[vnk] = fin[vnk] + lambda * dfp / (float)SO->FN->N_Neighb[n]; /* apply equal weight factor here */
02477 }
02478 } else {
02479 fout[vnk] = fin[vnk];
02480 }
02481 }/* for n */
02482 }/* for k */
02483 if (cs->Send) {
02484 /* SUMA_SendToSuma does not deal with such COLUMN_MAJOR order.
02485 Must flip things here, boooooring */
02486 if (!niter) { /* allocate for buffer */
02487 ftmp = (float *) SUMA_malloc(3*SO->N_Node*sizeof(float));
02488 if (!ftmp) { SUMA_SL_Err("Failed to allocate. Communication Off.\n"); cs->Send = NOPE; }
02489 }
02490 if (ftmp) {
02491 for (i=0; i<SO->N_Node; ++i) { ftmp[3*i] = fout[i]; ftmp[3*i+1] = fout[i+SO->N_Node]; ftmp[3*i+2] = fout[i+2*SO->N_Node];}
02492 if (!SUMA_SendToSuma (SO, cs, (void *)ftmp, SUMA_NODE_XYZ, 1)) {
02493 SUMA_SL_Warn("Failed in SUMA_SendToSuma\nCommunication halted.");
02494 }
02495 }
02496 if (niter == N_iter -1) { /* free the buffer */
02497 if (ftmp) { SUMA_free(ftmp); ftmp = NULL; }
02498 }
02499 }
02500 }/* for niter */
02501 break;
02502 case SUMA_ROW_MAJOR:
02503 for (niter=0; niter < N_iter; ++niter) {
02504 if ( niter % 2 ) { /* odd */
02505 fin = fin_next; /* input from previous output buffer */
02506 fout = fout_final; /* results go into final vector */
02507 fin_next = fout_final; /* in the next iteration, the input is from fout_final */
02508 } else { /* even */
02509 /* input data is in fin_new */
02510 fin = fin_next;
02511 fout = fbuf; /* results go into buffer */
02512 fin_next = fbuf; /* in the next iteration, the input is from the buffer */
02513 }
02514 for (n=0; n < SO->N_Node; ++n) {
02515 DoThis = 1;
02516 if (nmask && !nmask[n]) DoThis = 0;
02517 vnk = n * vpn; /* index of 1st value at node n */
02518 for (k=0; k < vpn; ++k) {
02519 if (DoThis) {
02520 fp = fin[vnk]; /* kth value at node n */
02521 dfp = 0.0;
02522 for (j=0; j < SO->FN->N_Neighb[n]; ++j) { /* calculating the laplacian */
02523 fpj = fin[SO->FN->FirstNeighb[n][j]*vpn+k]; /* value at jth neighbor of n */
02524 if (wgt) dfp += wgt[n][j] * (fpj - fp);
02525 else dfp += (fpj - fp); /* will apply equal weight later */
02526 }/* for j*/
02527 if (niter%2) { /* odd */
02528 if (wgt) fout[vnk] = fin[vnk] + mu * dfp;
02529 else fout[vnk] = fin[vnk] + mu * dfp / (float)SO->FN->N_Neighb[n]; /* apply equal weight factor here */
02530 }else{ /* even */
02531 if (wgt) fout[vnk] = fin[vnk] + lambda * dfp;
02532 else fout[vnk] = fin[vnk] + lambda * dfp / (float)SO->FN->N_Neighb[n]; /* apply equal weight factor here */
02533 }
02534 } else {
02535 fout[vnk] = fin[vnk];
02536 }
02537 ++vnk; /* index of next value at node n */
02538 } /* for k */
02539 }/* for n */
02540 if (cs->Send) {
02541 if (!SUMA_SendToSuma (SO, cs, (void *)fout, SUMA_NODE_XYZ, 1)) {
02542 SUMA_SL_Warn("Failed in SUMA_SendToSuma\nCommunication halted.");
02543 }
02544 }
02545 }/* for niter */
02546 break;
02547 default:
02548 SUMA_SL_Err("Bad Major, very bad.\n");
02549 SUMA_RETURN(NULL);
02550 break;
02551 }
02552
02553 if (fbuf) SUMA_free(fbuf); fbuf = NULL;
02554
02555 SUMA_RETURN(fout);
02556 }
|
|
||||||||||||||||
|
Calculates Mu(m) and Lambda(l) smoothing coefficients based on Taubin's smoothing algorithm in Geometric Signal Processing on Polygonal Meshes (Eurographics 2000).
k = 1/l + 1/m (eq 8) 0 = 1 - 3(l+m) + 5lm (eq 9) the solutions must verify the following: l > 0 m < -l < 0
Definition at line 2270 of file SUMA_GeomComp.c. References i, l, LocalHead, SUMA_Boolean, SUMA_ENTRY, SUMA_RETURN, and SUMA_SL_Err.
02271 {
02272 static char FuncName[]={"SUMA_Taubin_Smooth_Coef"};
02273 int i;
02274 float ls[2], delta;
02275 SUMA_Boolean Done = NOPE;
02276 SUMA_Boolean LocalHead = NOPE;
02277
02278 SUMA_ENTRY;
02279
02280 if (k < 0) { SUMA_SL_Err("k < 0"); SUMA_RETURN(NOPE); }
02281
02282 /* l1 and l2 are solutions of the quadratic equation:
02283 (5 - 3 k) l^2 + k l - 1 = 0 */
02284 delta = ( k * k - 12.0 * k + 20 );
02285 if (delta < 0) { SUMA_SL_Err("Delta is < 0 for specified k"); SUMA_RETURN(NOPE); }
02286
02287 ls[0] = ( -k + sqrt(delta) ) / ( 10 - 6 * k );
02288 ls[1] = ( -k - sqrt(delta) ) / ( 10 - 6 * k );
02289 if (ls[0] < 0 && ls[1] < 0) { SUMA_SL_Err("No positive solution for l"); SUMA_RETURN(NOPE); }
02290
02291 if (ls[1] > ls[0]) { /* swap them */
02292 *l = ls[0]; ls[0] = ls[1]; ls[1] = *l;
02293 }
02294
02295 Done = NOPE;
02296 i = 0;
02297 while (!Done && i < 2) {
02298 /* calculate mu */
02299 *l = ls[i];
02300 *m = *l / ( k * *l - 1.0 );
02301 if (*m < 0) Done = YUP;
02302 ++i;
02303 }
02304
02305 if (!Done) { SUMA_SL_Err("No good solutions found."); SUMA_RETURN(NOPE); }
02306
02307 if ( ! ( ( *m < -1.0 * *l ) && ( -1.0 * *l < 0 ) ) ) {
02308 SUMA_SL_Err("Solution did not meet m < -l < 0"); SUMA_RETURN(NOPE);
02309 }
02310
02311 SUMA_RETURN(YUP);
02312 }
|
|
||||||||||||||||||||
|
Show the transfer function (f(k)) for the Taubin smoothing algorithm for a combination of scaling factors and number of iterations.
where k is the normalized frequency and f(k) is the value of the transfer function at k
Definition at line 2217 of file SUMA_GeomComp.c. References i, l, LocalHead, SUMA_Boolean, SUMA_ENTRY, SUMA_RETURN, and SUMA_SL_Err.
02218 {
02219 static char FuncName[]={"SUMA_Taubin_Smooth_TransferFunc"};
02220 FILE *Outp = NULL;
02221 int i, imax = 100;
02222 float fk, k;
02223 SUMA_Boolean LocalHead = NOPE;
02224
02225 SUMA_ENTRY;
02226
02227 if (N % 2) {
02228 SUMA_SL_Err("N_iter must be even");
02229 SUMA_RETURN(NOPE);
02230 }
02231
02232 if (!Out) Outp = stdout;
02233 else Outp = Out;
02234
02235 k = 0.0;
02236 for (i=0; i< imax; ++i) {
02237 fk = pow( ( ( 1-m*k ) * ( 1-l*k ) ) , N / 2 );
02238 fprintf (Outp,"%f %f\n", k, fk);
02239 k += (float)i/(float)imax;
02240 }
02241
02242
02243 SUMA_RETURN(YUP);
02244 }
|
|
||||||||||||
|
Definition at line 1488 of file SUMA_GeomComp.c. References SUMA_VolDiffDataStruct::cs, i, LocalHead, SUMA_SurfaceObject::NodeList, r, SUMA_VolDiffDataStruct::Rref, SUMA_COMM_STRUCT::Send, SUMA_VolDiffDataStruct::SO, SUMA_VolDiffDataStruct::SOref, SUMA_Boolean, SUMA_ENTRY, SUMA_LH, SUMA_NewVolumeAtRadius(), SUMA_NODE_XYZ, SUMA_RETURN, SUMA_SendToSuma(), SUMA_SL_Warn, SUMA_VolDiffDataStruct::tmpList, and SUMA_VolDiffDataStruct::Vref. Referenced by SUMA_EquateSurfaceVolumes().
01489 {
01490 static char FuncName[]={"SUMA_VolDiff"};
01491 double dv, *fp, Dr, V;
01492 static int ncall=0;
01493 int i;
01494 static double Rref = 0.0, Vref = 0.0;
01495 SUMA_SurfaceObject *SO, *SOref;
01496 SUMA_COMM_STRUCT *cs=NULL;
01497 SUMA_VolDiffDataStruct *fdata = (SUMA_VolDiffDataStruct*)fvdata ;
01498 SUMA_Boolean LocalHead = NOPE;
01499
01500 SUMA_ENTRY;
01501
01502 if (!fdata) {
01503 SUMA_LH("Reset");
01504 Rref = 0.0; Vref = 0.0;
01505 ncall = 0;
01506 SUMA_RETURN(0.0);
01507 }
01508
01509 SO = fdata->SO;
01510 SOref = fdata->SOref;
01511 cs = fdata->cs;
01512
01513 if (!ncall) {
01514 SUMA_LH("Initializing, calculating Vref and Rref");
01515 Vref = fdata->Vref;
01516 Rref = fdata->Rref;
01517 if (LocalHead) { fprintf(SUMA_STDERR,"%s: Reference volume = %f, radius = %f \n", FuncName, Vref, Rref); }
01518 if (cs->Send) { /* send the first monster (it's SOref "in SUMA" that's being modified on the fly) */
01519 if (!SUMA_SendToSuma (SOref, cs, (void *)SO->NodeList, SUMA_NODE_XYZ, 1)) {
01520 SUMA_SL_Warn("Failed in SUMA_SendToSuma\nCommunication halted.");
01521 }
01522 }
01523 }
01524
01525 V = SUMA_NewVolumeAtRadius(SO, r, Rref, fdata->tmpList);
01526 dv = Vref - V; /* the volume difference */
01527
01528 /* need an update ? */
01529 if (cs->Send) { /* send the update (it's SOref "in SUMA" that's being modified on the fly) */
01530 if (!SUMA_SendToSuma (SOref, cs, (void *)fdata->tmpList, SUMA_NODE_XYZ, 1)) {
01531 SUMA_SL_Warn("Failed in SUMA_SendToSuma\nCommunication halted.");
01532 }
01533 }
01534
01535 ++ncall;
01536
01537 SUMA_RETURN(dv);
01538 }
|
|
||||||||||||||||||||||||||||
|
find the neighbors to a voxel.
Definition at line 409 of file SUMA_GeomComp.c. References i, SUMA_1D_2_3D_index, SUMA_3D_2_1D_index, SUMA_ENTRY, SUMA_RETURN, SUMA_SL_Err, SUMA_VOX_NEIGHB_CORNER, SUMA_VOX_NEIGHB_EDGE, and SUMA_VOX_NEIGHB_TYPES. Referenced by SUMA_FillToVoxelMask().
00410 {
00411 static char FuncName[]={"SUMA_VoxelNeighbors"};
00412 int i, j, k;
00413 int nij, N_n;
00414
00415 SUMA_ENTRY;
00416
00417 N_n = 0; nij = ni * nj;
00418
00419 /* change ijk to 3D */
00420 SUMA_1D_2_3D_index(ijk, i, j, k, ni, nij);
00421
00422 if (i >= ni || i < 0) { SUMA_SL_Err("Voxel out of bounds along i direction"); SUMA_RETURN(N_n); }
00423 if (j >= nj || j < 0) { SUMA_SL_Err("Voxel out of bounds along j direction"); SUMA_RETURN(N_n); }
00424 if (k >= nk || k < 0) { SUMA_SL_Err("Voxel out of bounds along k direction"); SUMA_RETURN(N_n); }
00425
00426 /* start with the face neighbors */
00427 if (i-1 >= 0) { nl[N_n] = SUMA_3D_2_1D_index(i-1, j, k, ni, nij); ++N_n; }
00428 if (j-1 >= 0) { nl[N_n] = SUMA_3D_2_1D_index(i, j-1, k, ni, nij); ++N_n; }
00429 if (k-1 >= 0) { nl[N_n] = SUMA_3D_2_1D_index(i, j, k-1, ni, nij); ++N_n; }
00430 if (i+1 < ni) { nl[N_n] = SUMA_3D_2_1D_index(i+1, j, k, ni, nij); ++N_n; }
00431 if (j+1 < nj) { nl[N_n] = SUMA_3D_2_1D_index(i, j+1, k, ni, nij); ++N_n; }
00432 if (k+1 < nk) { nl[N_n] = SUMA_3D_2_1D_index(i, j, k+1, ni, nij); ++N_n; }
00433
00434 if ( ntype < SUMA_VOX_NEIGHB_EDGE) { SUMA_RETURN(N_n); }
00435
00436 /* add edge neighbors */
00437 if (i-1 >= 0 && j-1 >= 0) { nl[N_n] = SUMA_3D_2_1D_index(i-1, j-1, k, ni, nij); ++N_n; }
00438 if (i-1 >= 0 && j+1 < nj) { nl[N_n] = SUMA_3D_2_1D_index(i-1, j+1, k, ni, nij); ++N_n; }
00439 if (i-1 >= 0 && k-1 >= 0) { nl[N_n] = SUMA_3D_2_1D_index(i-1, j, k-1, ni, nij); ++N_n; }
00440 if (i-1 >= 0 && k+1 < nk) { nl[N_n] = SUMA_3D_2_1D_index(i-1, j, k+1, ni, nij); ++N_n; }
00441 if (j-1 >= 0 && k-1 >= 0) { nl[N_n] = SUMA_3D_2_1D_index(i, j-1, k-1, ni, nij); ++N_n; }
00442 if (j-1 >= 0 && k+1 < nk) { nl[N_n] = SUMA_3D_2_1D_index(i, j-1, k+1, ni, nij); ++N_n; }
00443 if (i+1 < ni && j-1 >= 0) { nl[N_n] = SUMA_3D_2_1D_index(i+1, j-1, k, ni, nij); ++N_n; }
00444 if (i+1 < ni && j+1 < nj) { nl[N_n] = SUMA_3D_2_1D_index(i+1, j+1, k, ni, nij); ++N_n; }
00445 if (i+1 < ni && k-1 >= 0) { nl[N_n] = SUMA_3D_2_1D_index(i+1, j, k-1, ni, nij); ++N_n; }
00446 if (i+1 < ni && k+1 < nk) { nl[N_n] = SUMA_3D_2_1D_index(i+1, j, k+1, ni, nij); ++N_n; }
00447 if (j+1 < nj && k-1 >= 0) { nl[N_n] = SUMA_3D_2_1D_index(i, j+1, k-1, ni, nij); ++N_n; }
00448 if (j+1 < nj && k+1 < nk) { nl[N_n] = SUMA_3D_2_1D_index(i, j+1, k+1, ni, nij); ++N_n; }
00449
00450 if ( ntype < SUMA_VOX_NEIGHB_CORNER) { SUMA_RETURN(N_n); }
00451
00452 /* add corner neighbors */
00453 if (i-1 >= 0 && j-1 >= 0 && k-1 >= 0) { nl[N_n] = SUMA_3D_2_1D_index(i-1, j-1, k-1, ni, nij); ++N_n; }
00454 if (i-1 >= 0 && j-1 >= 0 && k+1 < nk) { nl[N_n] = SUMA_3D_2_1D_index(i-1, j-1, k+1, ni, nij); ++N_n; }
00455 if (i-1 >= 0 && j+1 < nj && k-1 >= 0) { nl[N_n] = SUMA_3D_2_1D_index(i-1, j+1, k-1, ni, nij); ++N_n; }
00456 if (i-1 >= 0 && j+1 < nj && k+1 < nk) { nl[N_n] = SUMA_3D_2_1D_index(i-1, j+1, k+1, ni, nij); ++N_n; }
00457 if (i+1 < ni && j-1 >= 0 && k-1 >= 0) { nl[N_n] = SUMA_3D_2_1D_index(i+1, j-1, k-1, ni, nij); ++N_n; }
00458 if (i+1 < ni && j-1 >= 0 && k+1 < nk) { nl[N_n] = SUMA_3D_2_1D_index(i+1, j-1, k+1, ni, nij); ++N_n; }
00459 if (i+1 < ni && j+1 < nj && k-1 >= 0) { nl[N_n] = SUMA_3D_2_1D_index(i+1, j+1, k-1, ni, nij); ++N_n; }
00460 if (i+1 < ni && j+1 < nj && k+1 < nk) { nl[N_n] = SUMA_3D_2_1D_index(i+1, j+1, k+1, ni, nij); ++N_n; }
00461
00462
00463 SUMA_RETURN(N_n);
00464 }
|
|
||||||||||||||||||||
|
find voxels whose centers are inside the box with corners c1 and c2 c1, c2 are in voxel index coordinates. c1 is the minimum coordinates point. c2 is the maximum coordinates point.
Definition at line 567 of file SUMA_GeomComp.c. References i, SUMA_Boolean, SUMA_CEIL, SUMA_ENTRY, SUMA_RETURN, SUMA_ROUND, and SUMA_SL_Err. Referenced by SUMA_GetVoxelsIntersectingTriangle(), and SUMA_SurfGridIntersect().
00568 {
00569 static char FuncName[]={"SUMA_VoxelsInBox"};
00570 int n3, i, j, k;
00571
00572 SUMA_ENTRY;
00573
00574 if (!voxelsijk) {
00575 SUMA_SL_Err("NULL voxelsijk");
00576 SUMA_RETURN(NOPE);
00577 }
00578
00579 *N_in = 0;
00580
00581 #if 0
00582 for (k = SUMA_ROUND(c1[2]); k <= SUMA_ROUND(c2[2]); ++k) {
00583 for (j = SUMA_ROUND(c1[1]); j <= SUMA_ROUND(c2[1]); ++j) {
00584 for (i = SUMA_ROUND(c1[0]); i <= SUMA_ROUND(c2[0]); ++i) {
00585 n3 = 3*(*N_in);
00586 voxelsijk[n3] = i; voxelsijk[n3+1] = j; voxelsijk[n3+2] = k;
00587 ++(*N_in);
00588 }
00589 }
00590 }
00591 #else
00592 for (k = (int)(c1[2]); k <= SUMA_CEIL(c2[2]); ++k) {
00593 for (j = (int)(c1[1]); j <= SUMA_CEIL(c2[1]); ++j) {
00594 for (i = (int)(c1[0]); i <= SUMA_CEIL(c2[0]); ++i) {
00595 n3 = 3*(*N_in);
00596 voxelsijk[n3] = i; voxelsijk[n3+1] = j; voxelsijk[n3+2] = k;
00597 ++(*N_in);
00598 }
00599 }
00600 }
00601 #endif
00602 SUMA_RETURN(YUP);
00603 }
|
Variable Documentation
|
|
Global pointer to structure containing info common to all viewers Definition at line 23 of file SUMA_GeomComp.c. |
|
|
Global pointer to Displayable Object structure vector Definition at line 24 of file SUMA_GeomComp.c. |
|
|
Number of DOs stored in DOv Definition at line 27 of file SUMA_GeomComp.c. Referenced by SUMA_Surf_Plane_Intersect_ROI(). |
|
|
Number of SVs stored in SVv Definition at line 26 of file SUMA_GeomComp.c. |
|
|
Global pointer to the vector containing the various Surface Viewer Structures Definition at line 25 of file SUMA_GeomComp.c. |