Doxygen Source Code Documentation
SUMA_input.h File Reference
Go to the source code of this file.
Defines | |
#define | SUMA_BRUSH_BLOCK 500 |
#define | SUMA_BS_FIRST_SURF_NODE(bs, fn, ft, NE) |
Macro to retrieve the first node and first triangle intersected by a brushstroke Since not all elements of brushstroke have a surface node, the macro continues searching until a non-negative SurfNode is found. Note that SurfTri is not monitored. | |
#define | SUMA_BS_NEXT_SURF_NODE(bs, oEl, El) |
Find the next element in bs that contains a non-negative value for SurfNode returns NULL in El if failed to find such an element. | |
#define | SUMA_BS_COUNT_SURF_NODES(bs, N_SurfNode) |
#define | SUMA_REMOVE_NEXT_NON_DECIMATED(bs, Eli, Eln) |
Functions | |
void | SUMA_input (Widget w, XtPointer clientData, XtPointer callData) |
int | SUMA_MarkLineSurfaceIntersect (SUMA_SurfaceViewer *sv, SUMA_DO *dov) |
void | SUMA_momentum (XtPointer clientData, XtIntervalId *id) |
SUMA_Boolean | SUMA_AddToBrushStroke (SUMA_SurfaceViewer *sv, int x, int y, GLdouble *NP, GLdouble *FP, SUMA_Boolean Show) |
Adds, new point to the brush stroke success = SUMA_AddToBrushStroke ( sv, x, y, Show);. | |
SUMA_Boolean | SUMA_CreateBrushStroke (SUMA_SurfaceViewer *sv) |
Creates the BrushStroke structure inside sv structure success = SUMA_CreateBrushStroke (sv);. | |
void | SUMA_ClearBrushStroke (SUMA_SurfaceViewer *sv) |
Clear the contents of sv->BS and sets it to NULL. | |
void | SUMA_ShowBrushStroke (SUMA_SurfaceViewer *sv, FILE *out) |
Show the contents of a brush stroke SUMA_ShowBrushStroke (sv, Out);. | |
void | SUMA_DrawBrushStroke (SUMA_SurfaceViewer *sv, SUMA_Boolean Incremental) |
Draws the brushstroke. | |
void | SUMA_SetSVForegroundColor (SUMA_SurfaceViewer *sv, const char *Color) |
SUMA_DRAWN_ROI * | SUMA_ProcessBrushStroke (SUMA_SurfaceViewer *sv, SUMA_BRUSH_STROKE_ACTION BsA) |
Processes the brushstroke sent from a viewer. | |
SUMA_Boolean | SUMA_BrushStrokeToNodeStroke (SUMA_SurfaceViewer *sv) |
SUMA_ROI_DATUM * | SUMA_NodeStrokeToConnectedNodes (SUMA_SurfaceViewer *sv) |
SUMA_ROI_DATUM * | SUMA_LinkTailNodeToNodeStroke (SUMA_SurfaceViewer *sv, SUMA_DRAWN_ROI *DrawnROI) |
Function to link a node on the surface to the first node of a NodeStroke. | |
DListElmt * | SUMA_PushActionStack (DList *ActionStack, DListElmt *StackPos, SUMA_ACTION_RESULT(*ActionFunction)(void *ActionData, SUMA_ACTION_POLARITY Pol), void *ActionData, void(*ActionDataDestructor)(void *Actiondata)) |
SUMA_ACTION_RESULT | SUMA_AddToTailROIDatum (void *data, SUMA_ACTION_POLARITY Pol) |
Adds (or removes) an ROIdatum to the tail of the ROI list. | |
SUMA_ACTION_RESULT | SUMA_AddToTailJunctionROIDatum (void *data, SUMA_ACTION_POLARITY Pol) |
This function is like SUMA_AddToTailROIDatum, except that it also updates the type of the ROI to be a closed one. You call this function when you are addind the last ROIDatum that closes the path. | |
void | SUMA_DestroyROIActionData (void *data) |
SUMA_ROI_DATUM * | SUMA_LinkThisNodeToNodeInStroke (SUMA_SurfaceViewer *sv, int NonSurf, DListElmt *El) |
Function to link a node on the surface to a certain node in NodeStroke. | |
DListElmt * | SUMA_UndoAction (DList *ActionStack, DListElmt *StackPos) |
DListElmt * | SUMA_RedoAction (DList *ActionStack, DListElmt *StackPos) |
void | SUMA_FreeBSDatum (void *bsd) |
free a brush stroke datum that is contained inside the doubly linked BS | |
SUMA_BRUSH_STROKE_DATUM * | SUMA_CreateBSDatum (void) |
SUMA_ACTION_RESULT | SUMA_AddFillROIDatum (void *data, SUMA_ACTION_POLARITY Pol) |
This function is like SUMA_AddToTailROIDatum, except that it also updates the type of the ROI to be a filled one. You call this function when you are adding an ROIDatum that fills a closed path. | |
SUMA_ACTION_RESULT | SUMA_FinishedROI (void *data, SUMA_ACTION_POLARITY Pol) |
Mark an ROI as finished. | |
void | SUMA_LookAtCoordinates (char *s, void *data) |
rotates surface to face a certain coordinate | |
void | SUMA_SetLight0 (char *s, void *data) |
set the position of light0 | |
void | SUMA_JumpIndex (char *s, void *data) |
sends the cross hair to a certain node index | |
void | SUMA_JumpXYZ (char *s, void *data) |
sends the cross hair to a certain XYZ location. | |
void | SUMA_JumpFocusNode (char *s, void *data) |
Changes the focus node without moving the cross hair. | |
void | SUMA_JumpFocusFace (char *s, void *data) |
changes the selected faceset (Focus FaceSet) | |
void | SUMA_HighlightBox (char *s, void *data) |
Highlight a set of nodes within a box. | |
void | SUMA_SetNumForeSmoothing (char *s, void *data) |
sets the number of smoothing operations to perform on foreground colors before display |
Define Documentation
|
Definition at line 4 of file SUMA_input.h. |
|
Value: { \ SUMA_BRUSH_STROKE_DATUM *m_bsd=NULL; \ DListElmt *m_El=NULL; \ \ N_SurfNode = 0; \ do { \ if (!m_El) m_El = dlist_head(bs); \ else m_El = m_El->next; \ m_bsd = (SUMA_BRUSH_STROKE_DATUM *)m_El->data; \ if (m_bsd->SurfNode >= 0) ++N_SurfNode; \ } while (m_El != dlist_tail(bs)); \ } Definition at line 90 of file SUMA_input.h. Referenced by SUMA_ProcessBrushStroke(). |
|
Value: { \ SUMA_BRUSH_STROKE_DATUM *m_bsd=NULL; \ \ if (!dlist_size(bs)) { \ fn = -1; \ ft = -1; \ } else { \ do { \ if (!NE) NE = dlist_head(bs); \ else NE = NE->next; \ m_bsd = (SUMA_BRUSH_STROKE_DATUM *)NE->data; \ fn = m_bsd->SurfNode; \ ft = m_bsd->SurfTri; \ } while ( (NE != dlist_tail(bs)) && fn < 0); \ } \ }
Definition at line 52 of file SUMA_input.h. Referenced by SUMA_LinkTailNodeToNodeStroke(), SUMA_NodeStrokeToConnectedNodes(), and SUMA_ProcessBrushStroke(). |
|
Value: { \ SUMA_BRUSH_STROKE_DATUM *m_bsd=NULL; \ \ if (oEl == dlist_tail (bs)) {\ El = NULL; \ } else { \ El = oEl; \ do { \ El = El->next; \ m_bsd = (SUMA_BRUSH_STROKE_DATUM *)El->data; \ } while (El != dlist_tail(bs) && m_bsd->SurfNode < 0); \ if (m_bsd->SurfNode < 0) El = NULL; \ } \ }
Definition at line 74 of file SUMA_input.h. Referenced by SUMA_NodeStrokeToConnectedNodes(). |
|
Value: { \ SUMA_BRUSH_STROKE_DATUM *m_bsd=NULL; \ SUMA_Boolean m_wasDecimated; \ do { \ Eln = Eli->next; \ m_bsd = (SUMA_BRUSH_STROKE_DATUM *)Eln->data; \ if (m_bsd->Decimated) { \ m_wasDecimated = YUP; \ dlist_remove (bs, Eln, (void *)(&m_bsd)); \ SUMA_FreeBSDatum (m_bsd); \ } else { \ m_wasDecimated = NOPE; \ } \ } while (Eln != dlist_tail(bs) && m_wasDecimated); \ if (m_bsd->Decimated) Eln = NULL; \ } Definition at line 104 of file SUMA_input.h. Referenced by SUMA_BrushStrokeToNodeStroke(). |
Function Documentation
|
This function is like SUMA_AddToTailROIDatum, except that it also updates the type of the ROI to be a filled one. You call this function when you are adding an ROIDatum that fills a closed path.
Definition at line 3490 of file SUMA_input.c. References DListElmt_::data, dlist_ins_next(), dlist_remove(), dlist_tail, SUMA_ROI_ACTION_STRUCT::DrawnROI, LocalHead, SUMA_ROI_ACTION_STRUCT::ROId, SUMA_DRAWN_ROI::ROIstrokelist, SAP_Do, SAP_Redo, SAP_Undo, SAR_Succeed, SUMA_ACTION_POLARITY, SUMA_ACTION_RESULT, SUMA_Boolean, SUMA_ENTRY, SUMA_RETURN, SUMA_ROI_ClosedPath, SUMA_ROI_FilledArea, SUMA_ROI_NodeSegment, SUMA_ROI_DATUM::Type, and SUMA_DRAWN_ROI::Type. Referenced by SUMA_ProcessBrushStroke().
03491 { 03492 static char FuncName[]={"SUMA_AddFillROIDatum"}; 03493 SUMA_Boolean LocalHead = NOPE; 03494 SUMA_ROI_ACTION_STRUCT *ROIA=NULL; 03495 void *eldata=NULL; 03496 DListElmt *tail_elm=NULL; 03497 SUMA_ROI_DATUM *ROId=NULL; 03498 03499 SUMA_ENTRY; 03500 03501 ROIA = (SUMA_ROI_ACTION_STRUCT *)data; 03502 03503 switch (Pol) { 03504 case SAP_Do: 03505 case SAP_Redo: 03506 if (LocalHead) fprintf (SUMA_STDERR, "%s: Adding to ROIstrokelist...\n", FuncName); 03507 dlist_ins_next(ROIA->DrawnROI->ROIstrokelist, dlist_tail(ROIA->DrawnROI->ROIstrokelist), (void *)ROIA->ROId); 03508 ROIA->DrawnROI->Type = SUMA_ROI_FilledArea; 03509 break; 03510 case SAP_Undo: 03511 if (LocalHead) fprintf (SUMA_STDERR, "%s: Removing from ROIstrokelist...\n", FuncName); 03512 dlist_remove(ROIA->DrawnROI->ROIstrokelist, dlist_tail(ROIA->DrawnROI->ROIstrokelist), &eldata); 03513 /* eldata contains the ROIdatum that has been removed from the list. It should not be freed here 03514 This structure is to remain in the stack for later usage.*/ 03515 /* if the tail is a segment, then turn the ROI type to a closedpath */ 03516 tail_elm = dlist_tail(ROIA->DrawnROI->ROIstrokelist); 03517 ROId = (SUMA_ROI_DATUM *)tail_elm->data; 03518 if (ROId->Type == SUMA_ROI_NodeSegment) { /* we are no longer dealing with filled ROI */ 03519 ROIA->DrawnROI->Type = SUMA_ROI_ClosedPath; 03520 } 03521 break; 03522 default: 03523 fprintf (SUMA_STDERR, "Error %s: Should not be here.\n", FuncName); 03524 break; 03525 } 03526 03527 SUMA_RETURN(SAR_Succeed); 03528 } |
|
Adds, new point to the brush stroke success = SUMA_AddToBrushStroke ( sv, x, y, Show);.
Definition at line 2341 of file SUMA_input.c. References SUMA_SurfaceViewer::BS, dlist_ins_next(), dlist_tail, SUMA_BRUSH_STROKE_DATUM::FP, SUMA_BRUSH_STROKE_DATUM::NP, SUMA_Boolean, SUMA_CreateBSDatum(), SUMA_DrawBrushStroke(), SUMA_ENTRY, SUMA_RETURN, SUMA_BRUSH_STROKE_DATUM::x, and SUMA_BRUSH_STROKE_DATUM::y. Referenced by SUMA_input().
02342 { 02343 static char FuncName[]={"SUMA_AddToBrushStroke"}; 02344 int ip; 02345 SUMA_BRUSH_STROKE_DATUM *bsd=NULL; 02346 02347 SUMA_ENTRY; 02348 02349 /* New version */ 02350 bsd = SUMA_CreateBSDatum(); 02351 bsd->x = (float)x; 02352 bsd->y = (float)y; 02353 bsd->NP[0] = NP[0]; bsd->NP[1] = NP[1]; bsd->NP[2] = NP[2]; 02354 bsd->FP[0] = FP[0]; bsd->FP[1] = FP[1]; bsd->FP[2] = FP[2]; 02355 dlist_ins_next (sv->BS, dlist_tail(sv->BS), (void*)bsd); 02356 02357 /* incremental draw */ 02358 if (Show) SUMA_DrawBrushStroke (sv, YUP); 02359 02360 SUMA_RETURN (YUP); 02361 } |
|
This function is like SUMA_AddToTailROIDatum, except that it also updates the type of the ROI to be a closed one. You call this function when you are addind the last ROIDatum that closes the path.
Definition at line 3536 of file SUMA_input.c. References dlist_ins_next(), dlist_remove(), dlist_tail, SUMA_ROI_ACTION_STRUCT::DrawnROI, LocalHead, SUMA_ROI_ACTION_STRUCT::ROId, SUMA_DRAWN_ROI::ROIstrokelist, SAP_Do, SAP_Redo, SAP_Undo, SAR_Fail, SAR_Succeed, SUMA_ACTION_POLARITY, SUMA_ACTION_RESULT, SUMA_Boolean, SUMA_ENTRY, SUMA_RETURN, SUMA_ROI_ClosedPath, SUMA_ROI_OpenPath, SUMA_SLP_Err, and SUMA_DRAWN_ROI::Type. Referenced by SUMA_ProcessBrushStroke().
03537 { 03538 static char FuncName[]={"SUMA_AddToTailJunctionROIDatum"}; 03539 SUMA_Boolean LocalHead = NOPE; 03540 SUMA_ROI_ACTION_STRUCT *ROIA=NULL; 03541 void *eldata=NULL; 03542 03543 SUMA_ENTRY; 03544 03545 ROIA = (SUMA_ROI_ACTION_STRUCT *)data; 03546 03547 switch (Pol) { 03548 case SAP_Do: 03549 case SAP_Redo: 03550 if (ROIA->DrawnROI->Type == SUMA_ROI_ClosedPath) { 03551 SUMA_SLP_Err ("Trying to close a closed path!"); 03552 SUMA_RETURN(SAR_Fail); 03553 } 03554 if (LocalHead) fprintf (SUMA_STDERR, "%s: Adding to ROIstrokelist...\n", FuncName); 03555 dlist_ins_next(ROIA->DrawnROI->ROIstrokelist, dlist_tail(ROIA->DrawnROI->ROIstrokelist), (void *)ROIA->ROId); 03556 ROIA->DrawnROI->Type = SUMA_ROI_ClosedPath; 03557 break; 03558 case SAP_Undo: 03559 if (ROIA->DrawnROI->Type == SUMA_ROI_OpenPath) { 03560 SUMA_SLP_Err ("Trying to open an open path!"); 03561 SUMA_RETURN(SAR_Fail); 03562 } 03563 if (LocalHead) fprintf (SUMA_STDERR, "%s: Removing from ROIstrokelist...\n", FuncName); 03564 dlist_remove(ROIA->DrawnROI->ROIstrokelist, dlist_tail(ROIA->DrawnROI->ROIstrokelist), &eldata); 03565 /* eldata contains the ROIdatum that has been removed from the list. It should not be freed here 03566 This structure is to remain in the stack for later usage.*/ 03567 ROIA->DrawnROI->Type = SUMA_ROI_OpenPath; 03568 break; 03569 default: 03570 fprintf (SUMA_STDERR, "Error %s: Should not be here.\n", FuncName); 03571 break; 03572 } 03573 03574 SUMA_RETURN(SAR_Succeed); 03575 } |
|
Adds (or removes) an ROIdatum to the tail of the ROI list.
Definition at line 3584 of file SUMA_input.c. References dlist_ins_next(), dlist_remove(), dlist_tail, SUMA_ROI_ACTION_STRUCT::DrawnROI, LocalHead, SUMA_ROI_ACTION_STRUCT::ROId, SUMA_DRAWN_ROI::ROIstrokelist, SAP_Do, SAP_Redo, SAP_Undo, SAR_Succeed, SUMA_ACTION_POLARITY, SUMA_ACTION_RESULT, SUMA_Boolean, SUMA_ENTRY, and SUMA_RETURN. Referenced by SUMA_ProcessBrushStroke().
03585 { 03586 static char FuncName[]={"SUMA_AddToTailROIDatum"}; 03587 SUMA_Boolean LocalHead = NOPE; 03588 SUMA_ROI_ACTION_STRUCT *ROIA=NULL; 03589 void *eldata=NULL; 03590 03591 SUMA_ENTRY; 03592 03593 ROIA = (SUMA_ROI_ACTION_STRUCT *)data; 03594 03595 switch (Pol) { 03596 case SAP_Do: 03597 case SAP_Redo: 03598 if (LocalHead) fprintf (SUMA_STDERR, "%s: Adding to ROIstrokelist...\n", FuncName); 03599 dlist_ins_next(ROIA->DrawnROI->ROIstrokelist, dlist_tail(ROIA->DrawnROI->ROIstrokelist), (void *)ROIA->ROId); 03600 break; 03601 case SAP_Undo: 03602 if (LocalHead) fprintf (SUMA_STDERR, "%s: Removing from ROIstrokelist...\n", FuncName); 03603 dlist_remove(ROIA->DrawnROI->ROIstrokelist, dlist_tail(ROIA->DrawnROI->ROIstrokelist), &eldata); 03604 /* eldata contains the ROIdatum that has been removed from the list. It should not be freed here 03605 This structure is to remain in the stack for later usage.*/ 03606 break; 03607 default: 03608 fprintf (SUMA_STDERR, "Error %s: Should not be here.\n", FuncName); 03609 break; 03610 } 03611 03612 SUMA_RETURN(SAR_Succeed); 03613 } |
|
Function that turns a brushstroke to a series of nodes on the surface. No surface paths are created from one node to the next yet. It is not always the case that BrushStroke->N_SurfNodes is equal to BrushStroke->N Definition at line 2774 of file SUMA_input.c. References SUMA_SurfaceViewer::BS, DListElmt_::data, SUMA_BRUSH_STROKE_DATUM::Decimated, dlist_head, dlist_ins_next(), dlist_remove(), dlist_size, dlist_tail, SUMA_SurfaceObject::EL, SUMA_SurfaceObject::FaceSetDim, SUMA_SurfaceObject::FaceSetList, SUMA_NODE_FIRST_NEIGHB::FirstNeighb, SUMA_SurfaceObject::FN, SUMA_SurfaceViewer::Focus_SO_ID, SUMA_BRUSH_STROKE_DATUM::FP, i, SUMA_MT_INTERSECT_TRIANGLE::ifacemin, SUMA_MT_INTERSECT_TRIANGLE::inodemin, LocalHead, n1, n2, SUMA_SurfaceObject::N_FaceSet, SUMA_MT_INTERSECT_TRIANGLE::N_hits, SUMA_NODE_FIRST_NEIGHB::N_Neighb, SUMA_SurfaceObject::N_Node, DListElmt_::next, SUMA_SurfaceObject::NodeList, SUMA_BRUSH_STROKE_DATUM::NP, DListElmt_::prev, SUMA_SurfaceObject::SelectedFaceSet, SUMA_SurfaceObject::SelectedNode, SUMA_Boolean, SUMA_calloc, SUMA_CreateBSDatum(), SUMA_ENTRY, SUMA_etime(), SUMA_free, SUMA_Free_MT_intersect_triangle(), SUMA_FreeBSDatum(), SUMA_MT_intersect_triangle(), SUMA_MT_isIntersect_Triangle(), SUMA_REMOVE_NEXT_NON_DECIMATED, SUMA_RETURN, SUMA_SL_Err, SUMA_SLP_Err, SUMA_whichTri(), SUMA_BRUSH_STROKE_DATUM::SurfNode, SUMA_BRUSH_STROKE_DATUM::SurfTri, SUMA_BRUSH_STROKE_DATUM::x, and SUMA_BRUSH_STROKE_DATUM::y. Referenced by SUMA_ProcessBrushStroke().
02775 { 02776 static char FuncName[]={"SUMA_BrushStrokeToNodeStroke"}; 02777 DList * NS=NULL; 02778 SUMA_SurfaceObject *SO=NULL; 02779 SUMA_MT_INTERSECT_TRIANGLE *MTI = NULL; 02780 float delta_t_tmp; 02781 struct timeval tt_tmp; 02782 int N = -1; 02783 SUMA_Boolean LocalHead=NOPE; 02784 SUMA_BRUSH_STROKE_DATUM *bsd=NULL, *obsd=NULL; 02785 DListElmt *Elmt = NULL, *oElmt=NULL; 02786 02787 SUMA_ENTRY; 02788 02789 02790 SO = (SUMA_SurfaceObject *)SUMAg_DOv[sv->Focus_SO_ID].OP; 02791 /* ONLY WORK ON FocusSO */ 02792 if (SO->FaceSetDim != 3) { 02793 fprintf(SUMA_STDERR,"Error %s: SUMA_MT_intersect_triangle only works for triangular meshes.\n", FuncName); 02794 SUMA_RETURN(NOPE); 02795 } 02796 02797 N = dlist_size(sv->BS); 02798 if (!N) { 02799 fprintf (SUMA_STDERR, "%s: Empty brushstroke, nothing to do.\n", FuncName); 02800 SUMA_RETURN(NOPE); 02801 }else if (LocalHead) fprintf (SUMA_STDERR, "%s: %d element(s) in sv->BS.\n", FuncName, N); 02802 02803 /* the first node of the brushstroke is stored as the cross hair's node id, just copy it */ 02804 Elmt = dlist_head(sv->BS); 02805 bsd = (SUMA_BRUSH_STROKE_DATUM *)Elmt->data; 02806 02807 bsd->SurfNode = SO->SelectedNode; 02808 bsd->SurfTri = SO->SelectedFaceSet; 02809 02810 #ifdef DISASTER_LOOP 02811 /* Now as a brute force method, do all the remaing nodes in the path. 02812 In the future, you want to downsample the path is some clever fashion */ 02813 if (N > 1) { 02814 if (LocalHead) { 02815 fprintf (SUMA_STDERR, "%s: Disaster loop, hold on .\n", FuncName); 02816 SUMA_etime (&tt_tmp, 0); 02817 } 02818 02819 MTI = NULL; 02820 do { 02821 Elmt = Elmt->next; 02822 bsd = (SUMA_BRUSH_STROKE_DATUM *)Elmt->data; 02823 02824 MTI = SUMA_MT_intersect_triangle( bsd->NP, bsd->FP, 02825 SO->NodeList, SO->N_Node, 02826 SO->FaceSetList, SO->N_FaceSet, 02827 MTI); 02828 02829 if (!MTI) { 02830 fprintf(SUMA_STDERR,"Error %s: SUMA_MT_intersect_triangle failed.\n", FuncName); 02831 SUMA_RETURN (NOPE); 02832 } 02833 02834 if (MTI->N_hits) { /* There is a hit, store it if useful */ 02835 oElmt = Elmt->prev; 02836 obsd = (SUMA_BRUSH_STROKE_DATUM *)oElmt->data; 02837 if (obsd->SurfNode != MTI->inodemin) { /* a new one, bring it on */ 02838 bsd->SurfNode = MTI->inodemin; 02839 bsd->SurfTri = MTI->ifacemin; 02840 }else { 02841 /* destroy Elmt, it is redundant */ 02842 if (LocalHead) fprintf (SUMA_STDERR, "%s: Removing redundant BS element.\n", FuncName); 02843 dlist_remove (sv->BS, Elmt, (void*)(&bsd)); 02844 SUMA_FreeBSDatum (bsd); 02845 Elmt = oElmt; 02846 } 02847 } 02848 02849 }while (Elmt != dlist_tail(sv->BS)); 02850 02851 /* free MTI */ 02852 MTI = SUMA_Free_MT_intersect_triangle(MTI); 02853 02854 if (LocalHead) { 02855 delta_t_tmp = SUMA_etime (&tt_tmp, 1); 02856 if (LocalHead) fprintf (SUMA_STDERR, "Local Debug %s: Intersections took %f seconds.\n", FuncName, delta_t_tmp); 02857 } 02858 02859 } 02860 #else 02861 if (N > 1) { /* new, faster method */ 02862 DListElmt *Eli=NULL, *Eln=NULL; 02863 float ip[3], d[3]; 02864 int IncTri[100], N_IncTri=0, n1=-1, n2=-1, n3=-1, ni = -1, ti = -1, N_Neighb=0,DeciLevel = 0, i, j, Removed=0; 02865 int DeciReentry=0, UsedNode[3]; 02866 SUMA_BRUSH_STROKE_DATUM *bsdi=NULL, *bsdn=NULL, *bsd_deci=NULL; 02867 SUMA_Boolean DoesInters=NOPE; /* flag for Decimation mode */ 02868 SUMA_Boolean TrackOscillation = YUP; /* flag to tracking algorithm oscillation */ 02869 SUMA_Boolean TryBruteForce = NOPE; 02870 int *Visited = NULL; 02871 02872 if (TrackOscillation) { 02873 Visited = (int *)SUMA_calloc(SO->N_Node, sizeof(int)); 02874 if (!Visited) { 02875 SUMA_SLP_Err("Failed to allocate for Visited.\n"); 02876 SUMA_RETURN(NOPE); 02877 } 02878 } 02879 02880 Eli = Elmt; /* initialize current element to the very fist in the brushstroke */ 02881 MTI = NULL; 02882 TryBruteForce = NOPE; 02883 do { 02884 bsdi = (SUMA_BRUSH_STROKE_DATUM *)Eli->data; 02885 n1 = bsdi->SurfNode; 02886 02887 Eln = Eli->next; /* get the next element in line */ 02888 bsdn = (SUMA_BRUSH_STROKE_DATUM *)Eln->data; 02889 02890 if (LocalHead) fprintf(SUMA_STDERR,"%s: Working from node %d.\n", FuncName, n1); 02891 02892 if (!TryBruteForce) { /* try the fast method */ 02893 N_Neighb = SO->FN->N_Neighb[n1]; 02894 if (N_Neighb < 3) { 02895 /* nothing found */ 02896 SUMA_SLP_Err ("Node has less than 3 neighbors.\n.This method will not apply."); 02897 SUMA_RETURN(NOPE); 02898 } 02899 02900 /* does the ray formed by Eln's NP and FP hit any of the triangles incident to bsdi->SurfNode (or n1) ? */ 02901 if (LocalHead) fprintf (SUMA_STDERR, "%s: Searching incident triangles:\n", FuncName); 02902 i=0; 02903 DoesInters = NOPE; 02904 while ((i < N_Neighb ) && (!DoesInters)) { 02905 n2 = SO->FN->FirstNeighb[n1][i]; 02906 if ( i+1 == N_Neighb) n3 = SO->FN->FirstNeighb[n1][0]; 02907 else n3 = SO->FN->FirstNeighb[n1][i+1]; 02908 #if 0 02909 if (LocalHead) { 02910 fprintf (SUMA_STDERR, " %d: [%d %d %d] Tri %d\n", i, n1, n2, n3, SUMA_whichTri(SO->EL, n1, n2, n3, 1)); 02911 fprintf (SUMA_STDERR, " %d: [%.2f, %.2f, %.2f]\n", 02912 n1, SO->NodeList[3*n1], SO->NodeList[3*n1+1], SO->NodeList[3*n1+2]); 02913 fprintf (SUMA_STDERR, " %d: [%.2f, %.2f, %.2f]\n", 02914 n2, SO->NodeList[3*n2], SO->NodeList[3*n2+1], SO->NodeList[3*n2+2]); 02915 fprintf (SUMA_STDERR, " %d: [%.2f, %.2f, %.2f]\n", 02916 n3, SO->NodeList[3*n3], SO->NodeList[3*n3+1], SO->NodeList[3*n3+2]); 02917 fprintf (SUMA_STDERR, " NP: [%.2f, %.2f, %.2f] FP: [%.3f, %.2f, %.2f]\n", 02918 bsdn->NP[0], bsdn->NP[1], bsdn->NP[2], 02919 bsdn->FP[0], bsdn->FP[1], bsdn->FP[2]); 02920 } 02921 #endif 02922 DoesInters = SUMA_MT_isIntersect_Triangle (bsdn->NP, bsdn->FP, 02923 &(SO->NodeList[3*n1]), &(SO->NodeList[3*n2]), &(SO->NodeList[3*n3]), 02924 ip, d, &ni); 02925 if (DoesInters) { 02926 if (ni == 0) ni = n1; 02927 else if (ni == 1) ni = n2; 02928 else ni = n3; 02929 02930 ti = SUMA_whichTri(SO->EL, n1, n2, n3, 1); 02931 } 02932 02933 #if 0 02934 if (LocalHead) fprintf (SUMA_STDERR, "%s: DoesInters = %d, ni = %d\n", FuncName, DoesInters, ni); 02935 { 02936 /* for debuging */ 02937 MTI = NULL;MTI = SUMA_MT_intersect_triangle( bsdn->NP, bsdn->FP, 02938 SO->NodeList, SO->N_Node, 02939 SO->FaceSetList, SO->N_FaceSet, 02940 MTI); 02941 fprintf (SUMA_STDERR, "%s: Intersection would be with triangle %d, node %d\n", FuncName, MTI->ifacemin, MTI->inodemin); 02942 } 02943 #endif 02944 ++i; 02945 } 02946 if (LocalHead) fprintf (SUMA_STDERR, "\n"); 02947 02948 } else { /* try brute force flag has been set*/ 02949 02950 if (LocalHead) fprintf (SUMA_STDERR, "%s: Trying brute force here \n", FuncName); 02951 /* Now skip and remove decimated elements */ 02952 SUMA_REMOVE_NEXT_NON_DECIMATED (sv->BS, Eli, Eln); 02953 DeciLevel = 0; 02954 DeciReentry = 0; 02955 if (!Eln) { 02956 SUMA_SL_Err ("I tried hard to figure out your trace.\nI failed, now you try again."); 02957 SUMA_RETURN(YUP); 02958 } 02959 02960 bsdn = (SUMA_BRUSH_STROKE_DATUM *)Eln->data; 02961 MTI = SUMA_MT_intersect_triangle( bsdn->NP, bsdn->FP, 02962 SO->NodeList, SO->N_Node, 02963 SO->FaceSetList, SO->N_FaceSet, 02964 MTI); 02965 02966 if (!MTI) { 02967 SUMA_SL_Err ("I tried harder to figure out your trace.\nI failed, do try again."); 02968 SUMA_RETURN (YUP); 02969 } 02970 02971 if (MTI->N_hits) { /* There is a hit, store it if useful */ 02972 DoesInters = YUP; 02973 if (bsdi->SurfNode != MTI->inodemin) { /* a new one, bring it on */ 02974 if (LocalHead) fprintf (SUMA_STDERR, "%s: Brute Force: Found intersection at new node %d.\n", FuncName, MTI->inodemin); 02975 ni = MTI->inodemin; 02976 ti = MTI->ifacemin; 02977 }else { 02978 /* set ni to n1 and let the element be destroyed */ 02979 if (LocalHead) fprintf (SUMA_STDERR, "%s: Brute Force: Found intersection at n1 = %d!.\n", FuncName, MTI->inodemin); 02980 ni = n1; 02981 } 02982 } else { 02983 /* No hits at all, get out of this business */ 02984 SUMA_SL_Err ("Why are you drawing out of bounds ?"); 02985 SUMA_RETURN (YUP); 02986 } 02987 /* reset the TryBruteForce flag */ 02988 TryBruteForce = NOPE; 02989 } 02990 02991 if (!DoesInters) { /* no intersection found, insert an element between Eli and Eln and try again */ 02992 ++DeciLevel; 02993 if (LocalHead) fprintf (SUMA_STDERR, "%s: No intersection found. Decimating, level %d.\n", FuncName, DeciLevel); 02994 02995 if (DeciLevel > 3000) { /* this condition is only here to keep things from going awry. */ 02996 if (LocalHead) fprintf (SUMA_STDERR,"%s: Decimation method failed. Trying from brute force", FuncName); 02997 TryBruteForce = YUP; 02998 } else { 02999 bsd_deci = SUMA_CreateBSDatum(); 03000 bsd_deci->Decimated = YUP; 03001 bsd_deci->x = (bsdi->x + bsdn->x)/2.0; 03002 bsd_deci->y = (bsdi->y + bsdn->y)/2.0; 03003 for (j=0; j < 3; ++j) bsd_deci->NP[j] = (bsdi->NP[j] + bsdn->NP[j])/2.0; 03004 for (j=0; j < 3; ++j) bsd_deci->FP[j] = (bsdi->FP[j] + bsdn->FP[j])/2.0; 03005 bsd_deci->SurfNode = -1; 03006 bsd_deci->SurfTri = -1; 03007 03008 dlist_ins_next (sv->BS, Eli, bsd_deci); 03009 } 03010 } else { 03011 /* intersection found */ 03012 if (ni == n1 && !DeciLevel) { 03013 /* same node reached, not during decimation, perhaps path was too densely sampled, delete Eln */ 03014 ++Removed; 03015 if (LocalHead) fprintf (SUMA_STDERR, "%s: Same node reached without decimation, deleting for the %dth time.\n", 03016 FuncName, Removed); 03017 dlist_remove(sv->BS, Eln, (void*)&bsdn); 03018 SUMA_FreeBSDatum(bsdn); 03019 } else { 03020 if (ni == n1 && DeciLevel) { 03021 /* back to the starting point during decimation */ 03022 if (DeciLevel) { /* user went out of bounds or drawing over cuts in surface */ 03023 #if 0 03024 /* same node reached during decimation, to hell with it, use brute force intersection: YOU PAY PRICE IN TIME MISTER*/ 03025 TryBruteForce = YUP; 03026 /* cancel the find */ 03027 DoesInters = NOPE; 03028 #else 03029 /* same node reached during decimation, try othernode in triangle */ 03030 if (!DeciReentry) { 03031 UsedNode[0] = n1; 03032 if (LocalHead) fprintf (SUMA_STDERR, "%s: Same node reached during decimation.\n Switching to second closest node.\n", FuncName); 03033 if (d[1] < d[2]) { 03034 ni = n2; 03035 UsedNode[1] = n2; 03036 } else { 03037 ni = n3; 03038 UsedNode[1] = n3; 03039 } 03040 } else if (DeciReentry == 1){ 03041 /* been there before, one last node is left */ 03042 if (LocalHead) fprintf (SUMA_STDERR, "%s: Last chance!\n", FuncName); 03043 if (n2 != UsedNode[0] && n2 != UsedNode[1]) ni = n2; 03044 else if (n3 != UsedNode[0] && n3 != UsedNode[1]) ni = n3; 03045 } else { 03046 /* Decimation failed, Do intersection with entire surface */ 03047 TryBruteForce = YUP; 03048 /* cancel the find */ 03049 DoesInters = NOPE; 03050 } 03051 #endif 03052 ++DeciReentry; 03053 } 03054 }else { 03055 /* ni != n1 Reset DeciLevel */ 03056 DeciLevel = 0; 03057 DeciReentry = 0; 03058 } 03059 03060 /* algorithm might fall into oscillatory patterns, keep track of nodes visited. 03061 It is possible that a node is visited multiple times when users go over the 03062 same region over and over and over.*/ 03063 if (TrackOscillation) { 03064 ++Visited[ni]; 03065 if (Visited[ni] == 9) { 03066 DoesInters = NOPE; 03067 TryBruteForce = YUP; 03068 SUMA_SL_Err ("Path tracing oscillation. Trying with brute force."); 03069 } 03070 if (Visited[ni] > 9) { 03071 SUMA_SL_Err ("Path tracing oscillation remaining. Quitting tracing."); 03072 SUMA_RETURN(YUP); 03073 } 03074 } 03075 03076 if (DoesInters) { /* it is possible that the find is cancelled */ 03077 if (LocalHead) fprintf (SUMA_STDERR, "%s: Found new node.\n", FuncName); 03078 /* good, new node is useful*/ 03079 bsdn->SurfNode = ni; 03080 bsdn->SurfTri = ti; 03081 /* set Eli to Eln */ 03082 Eli = Eln; 03083 } 03084 } 03085 } 03086 /* repeat until you have no more element */ 03087 } while (Eli != dlist_tail(sv->BS)); 03088 03089 if (MTI) MTI = SUMA_Free_MT_intersect_triangle(MTI); 03090 if (TrackOscillation) { 03091 if (Visited) SUMA_free(Visited); 03092 } 03093 }/* new, faster method */ 03094 #endif 03095 SUMA_RETURN(YUP); 03096 } |
|
Clear the contents of sv->BS and sets it to NULL. SUMA_ClearBrushStroke (sv);
Definition at line 2240 of file SUMA_input.c. References SUMA_SurfaceViewer::BS, SUMA_EmptyDestroyList(), SUMA_ENTRY, and SUMA_RETURNe. Referenced by SUMA_input().
02241 { 02242 static char FuncName[]={"SUMA_ClearBrushStroke"}; 02243 02244 SUMA_ENTRY; 02245 02246 /* THE NEW VERSION */ 02247 if (sv->BS) { 02248 SUMA_EmptyDestroyList(sv->BS); 02249 sv->BS = NULL; 02250 } 02251 02252 SUMA_RETURNe; 02253 } |
|
Creates the BrushStroke structure inside sv structure success = SUMA_CreateBrushStroke (sv);.
Definition at line 2266 of file SUMA_input.c. References SUMA_SurfaceViewer::BS, dlist_init(), SUMA_CommonFields::MessageList, SMA_LogAndPopup, SMT_Critical, SUMA_Boolean, SUMA_ENTRY, SUMA_FreeBSDatum(), SUMA_malloc, SUMA_RegisterMessage(), and SUMA_RETURN. Referenced by SUMA_input().
02267 { 02268 static char FuncName[]={"SUMA_CreateBrushStroke"}; 02269 02270 SUMA_ENTRY; 02271 02272 /* New Version */ 02273 if (sv->BS) { /* bad news, this should be NULL to begin with */ 02274 SUMA_RegisterMessage (SUMAg_CF->MessageList, 02275 "Brush Stroke not NULL.", FuncName, 02276 SMT_Critical, SMA_LogAndPopup); 02277 SUMA_RETURN(NOPE); 02278 02279 } 02280 sv->BS = (DList *)SUMA_malloc(sizeof(DList)); 02281 dlist_init(sv->BS, SUMA_FreeBSDatum); 02282 02283 SUMA_RETURN (YUP); 02284 } |
|
|
A function to destroy the ROI action data structure.
Definition at line 3623 of file SUMA_input.c. References SUMA_ROI_ACTION_STRUCT::DrawnROI, LocalHead, SUMA_ROI_ACTION_STRUCT::ROId, SUMA_Boolean, SUMA_ENTRY, SUMA_free, SUMA_FreeROIDatum(), and SUMA_RETURNe. Referenced by SUMA_ProcessBrushStroke().
03624 { 03625 static char FuncName[]={"SUMA_DestroyROIActionData"}; 03626 SUMA_Boolean LocalHead = NOPE; 03627 SUMA_ROI_ACTION_STRUCT *ROIA=NULL; 03628 03629 SUMA_ENTRY; 03630 03631 ROIA = (SUMA_ROI_ACTION_STRUCT *)data; 03632 03633 if (!ROIA) SUMA_RETURNe; 03634 03635 if (ROIA->ROId) { /* free the ROI datum */ 03636 SUMA_FreeROIDatum ((void *)ROIA->ROId); 03637 ROIA->ROId = NULL; 03638 } 03639 03640 ROIA->DrawnROI = NULL; /* this should not be freed here, it is freed when the function for destroying DrawnROI is called */ 03641 SUMA_free(ROIA); 03642 03643 SUMA_RETURNe; 03644 } |
|
Draws the brushstroke.
Definition at line 2399 of file SUMA_input.c. References SUMA_SurfaceViewer::BS, DListElmt_::data, dlist_head, dlist_size, dlist_tail, i, DListElmt_::next, DListElmt_::prev, SUMA_Boolean, SUMA_DrawWindowLine(), SUMA_ENTRY, SUMA_RETURNe, SUMA_BRUSH_STROKE_DATUM::x, and SUMA_BRUSH_STROKE_DATUM::y. Referenced by SUMA_AddToBrushStroke().
02400 { 02401 static char FuncName[]={"SUMA_DrawBrushStroke"}; 02402 int i, N; 02403 DListElmt *NE=NULL, *NEn=NULL; 02404 SUMA_BRUSH_STROKE_DATUM *bsd=NULL, *bsdn = NULL; 02405 02406 SUMA_ENTRY; 02407 02408 if (!sv->BS) SUMA_RETURNe; 02409 02410 N = dlist_size(sv->BS); 02411 if (N < 2) SUMA_RETURNe; 02412 02413 if (!incr) { 02414 do { 02415 if (!NE) NE = dlist_head(sv->BS); 02416 else NE = NE->next; 02417 02418 NEn = NE->next; 02419 02420 bsd = (SUMA_BRUSH_STROKE_DATUM *)NE->data; 02421 bsdn = (SUMA_BRUSH_STROKE_DATUM *)NEn->data; 02422 02423 SUMA_DrawWindowLine(sv, (int)bsd->x, (int)bsd->y, (int)bsdn->x, (int)bsdn->y, 1); 02424 } while (NEn != dlist_tail(sv->BS)); 02425 02426 } else { 02427 NEn = dlist_tail(sv->BS); 02428 NE = NEn->prev; 02429 02430 bsd = (SUMA_BRUSH_STROKE_DATUM *)NE->data; 02431 bsdn = (SUMA_BRUSH_STROKE_DATUM *)NEn->data; 02432 02433 SUMA_DrawWindowLine(sv, (int)bsd->x, (int)bsd->y, (int)bsdn->x, (int)bsdn->y, 1 ); 02434 02435 } 02436 SUMA_RETURNe; 02437 02438 } |
|
Mark an ROI as finished.
Definition at line 3417 of file SUMA_input.c. References SUMA_DRAWN_ROI::CE, SUMA_ROI_ACTION_STRUCT::DrawnROI, SUMA_DRAWN_ROI::DrawStatus, LocalHead, SUMA_DRAWN_ROI::N_CE, SUMA_DRAWN_ROI::Parent_idcode_str, SAP_Do, SAP_Redo, SAP_Undo, SAR_Fail, SAR_Succeed, SUMA_ACTION_POLARITY, SUMA_ACTION_RESULT, SUMA_Boolean, SUMA_ENTRY, SUMA_findSOp_inDOv(), SUMA_free, SUMA_GetContour(), SUMA_LH, SUMA_NodesInROI(), SUMA_RETURN, SUMA_ROI_Finished, SUMA_ROI_InCreation, SUMA_SLP_Err, SUMA_SLP_Warn, and SUMAg_N_DOv.
03418 { 03419 static char FuncName[]={"SUMA_FinishedROI"}; 03420 SUMA_ROI_ACTION_STRUCT *ROIA=NULL; 03421 SUMA_SurfaceObject *SOparent=NULL; 03422 SUMA_Boolean LocalHead = NOPE; 03423 03424 SUMA_ENTRY; 03425 03426 ROIA = (SUMA_ROI_ACTION_STRUCT *)data; 03427 03428 switch (Pol) { 03429 case SAP_Do: 03430 case SAP_Redo: 03431 if (LocalHead) fprintf (SUMA_STDERR, "%s: Marking as finished...\n", FuncName); 03432 /* set the drawing status */ 03433 ROIA->DrawnROI->DrawStatus = SUMA_ROI_Finished; 03434 03435 SOparent = SUMA_findSOp_inDOv(ROIA->DrawnROI->Parent_idcode_str, SUMAg_DOv, SUMAg_N_DOv); 03436 if (!SOparent) { 03437 SUMA_SLP_Warn( "Parent surface\n" 03438 "not found for ROI\n" 03439 "No contour will\n" 03440 "be determined." ); 03441 SUMA_RETURN(SAR_Succeed); 03442 }else { 03443 03444 /* calculate the contours */ 03445 if (!ROIA->DrawnROI->CE) { /* must create contour */ 03446 int *Nodes, N_Nodes; 03447 SUMA_Boolean Unique = NOPE; 03448 03449 SUMA_LH("Getting Contour "); 03450 N_Nodes = 0; 03451 Unique = YUP; /* Set to YUP if you have node indices listed more than once. */ 03452 Nodes = SUMA_NodesInROI (ROIA->DrawnROI, &N_Nodes, Unique); 03453 if (Nodes) { 03454 ROIA->DrawnROI->CE = SUMA_GetContour ( 03455 SOparent, 03456 Nodes, N_Nodes, &(ROIA->DrawnROI->N_CE), 0, NULL); 03457 if (!ROIA->DrawnROI->CE) { SUMA_LH("Null DrawnROI->CE"); } 03458 else { SUMA_LH("Good DrawnROI->CE"); } 03459 SUMA_free(Nodes); 03460 } 03461 }else { 03462 SUMA_SLP_Err("Unexpected Contour"); 03463 SUMA_RETURN(SAR_Fail); 03464 } 03465 } 03466 03467 break; 03468 case SAP_Undo: 03469 if (LocalHead) fprintf (SUMA_STDERR, "%s: Marking as InCreation...\n", FuncName); 03470 ROIA->DrawnROI->DrawStatus = SUMA_ROI_InCreation; 03471 /* remove any contour if present */ 03472 if (ROIA->DrawnROI->CE) SUMA_free(ROIA->DrawnROI->CE); ROIA->DrawnROI->CE = NULL; 03473 ROIA->DrawnROI->N_CE = -1; 03474 break; 03475 default: 03476 fprintf (SUMA_STDERR, "Error %s: Should not be here.\n", FuncName); 03477 break; 03478 } 03479 03480 SUMA_RETURN(SAR_Succeed); 03481 } |
|
free a brush stroke datum that is contained inside the doubly linked BS
Definition at line 2314 of file SUMA_input.c. References SUMA_ENTRY, SUMA_free, and SUMA_RETURNe. Referenced by SUMA_BrushStrokeToNodeStroke(), and SUMA_CreateBrushStroke().
02315 { 02316 static char FuncName[]={"SUMA_FreeBSDatum"}; 02317 02318 SUMA_ENTRY; 02319 02320 /* nothing is allocated for inside bsd */ 02321 if (bsd) SUMA_free(bsd); 02322 02323 SUMA_RETURNe; 02324 } |
|
Highlight a set of nodes within a box.
Definition at line 4093 of file SUMA_input.c. References LocalHead, SE_HighlightNodes, SE_Redisplay, SEF_fv15, SEI_Head, SES_Suma, SUMA_Boolean, SUMA_CreateList(), SUMA_Engine(), SUMA_ENTRY, SUMA_InitializeEngineListData(), SUMA_REGISTER_HEAD_COMMAND_NO_DATA, SUMA_RegisterEngineListCommand(), SUMA_RETURNe, SUMA_StringToNum(), SUMA_X::TOPLEVEL, and SUMA_SurfaceViewer::X. Referenced by SUMA_input().
04094 { 04095 static char FuncName[]={"SUMA_HighlightBox"}; 04096 DList *list=NULL; 04097 SUMA_EngineData *ED = NULL; 04098 SUMA_SurfaceViewer *sv = NULL; 04099 float fv15[15]; 04100 int it; 04101 SUMA_Boolean LocalHead = NOPE; 04102 04103 SUMA_ENTRY; 04104 04105 if (!s) SUMA_RETURNe; 04106 04107 sv = (SUMA_SurfaceViewer *)data; 04108 04109 /* parse s */ 04110 if (SUMA_StringToNum (s, fv15, 6) != 6) { /* problem, beep and ignore */ 04111 XBell (XtDisplay (sv->X->TOPLEVEL), 50); 04112 SUMA_RETURNe; 04113 } 04114 04115 /* register fv15 with ED */ 04116 if (!list) list = SUMA_CreateList(); 04117 ED = SUMA_InitializeEngineListData (SE_HighlightNodes); 04118 if (!SUMA_RegisterEngineListCommand ( list, ED, 04119 SEF_fv15, (void*)fv15, 04120 SES_Suma, (void *)sv, NOPE, 04121 SEI_Head, NULL)) { 04122 fprintf(SUMA_STDERR,"Error %s: Failed to register element\n", FuncName); 04123 SUMA_RETURNe; 04124 } 04125 04126 SUMA_REGISTER_HEAD_COMMAND_NO_DATA(list, SE_Redisplay, SES_Suma, sv); 04127 04128 if (!SUMA_Engine (&list)) { 04129 fprintf(stderr, "Error %s: SUMA_Engine call failed.\n", FuncName); 04130 } 04131 04132 04133 SUMA_RETURNe; 04134 04135 } |
|
Mouse and Keyboard input handler function for SUMA's viewer Definition at line 14 of file SUMA_input.c. References a, add_quats(), SUMA_X_AllView::App, SUMA_SCALE_TO_MAP_OPT::ApplyClip, SUMA_SurfaceViewer::ArrowRotationAngle, axis_to_quat(), SUMA_SurfaceViewer::Back_Modfact, SUMA_SurfaceViewer::BF_Cull, SUMA_SCALE_TO_MAP_OPT::BrightFact, SUMA_SurfaceViewer::BS, SUMA_CrossHair::c, cbuf, SUMA_SurfaceViewer::Ch, SUMA_SurfaceViewer::clear_color, SUMA_CommonFields::ColMixMode, SUMA_SurfaceViewer::CurGroupName, SUMA_COLOR_SCALED_VECT::cV, Cx, SUMA_CommonFields::Dev, SUMA_X_AllView::DPY_controller1, SUMA_CommonFields::DsetList, SUMA_SurfaceObject::EL, SUMA_SurfaceObject::FN, SUMA_SurfaceViewer::Focus_SO_ID, SUMA_SurfaceViewer::FOV, FOV_IN_FACT, FOV_INITIAL, FOV_MAX, FOV_MIN, FOV_OUT_FACT, SUMA_X::GLXAREA, SUMA_SurfaceViewer::GVS, SUMA_X::HEIGHT, SUMA_X::HighlightBox_prmpt, i, SUMA_SurfaceObject::idcode_str, SUMA_SCALE_TO_MAP_OPT::IntRange, ISQ_snapsave(), SUMA_SurfaceViewer::iState, SUMA_X::JumpFocusFace_prmpt, SUMA_X::JumpFocusNode_prmpt, SUMA_X::JumpIndex_prmpt, SUMA_X::JumpXYZ_prmpt, SUMA_SurfaceObject::Label, SUMA_SurfaceViewer::LastNonMapStateID, SUMA_SurfaceViewer::light0_position, SUMA_SurfaceObject::LocalDomainParentID, LocalHead, SUMA_X::LookAt_prmpt, mcw_malloc_dump(), SUMA_CommonFields::MessageList, SUMA_X::MOMENTUMID, MOUSE_ZOOM_FACT, SUMA_EngineData::N_cols, SUMA_SurfaceViewer::N_DO, SUMA_SurfaceObject::N_FaceSet, SUMA_X_AllView::N_ForeSmooth_prmpt, SUMA_SurfaceObject::N_Node, SUMA_SurfaceObject::N_Overlays, SUMA_EngineData::N_rows, SUMA_SurfaceViewer::N_VSv, SUMA_ViewState::Name, SUMA_SurfaceObject::NodeList, SUMA_SurfaceObject::NodeNormList, SUMA_X_AllView::NumForeSmoothing, SUMA_DO::OP, SUMA_SurfaceViewer::ortho, SUMA_SurfaceObject::Overlays, SUMA_CommonFields::Pen_mode, SUMA_SurfaceViewer::Pick0, SUMA_SurfaceViewer::Pick1, pixels, SUMA_SurfaceObject::PolyArea, SUMA_SurfaceViewer::PolyMode, SUMA_SurfaceViewer::Record, SUMA_SurfaceViewer::RegisteredDO, SUMA_SurfaceViewer::ResetGLStateVariables, SUMA_CommonFields::ROI_mode, SUMA_STRING::s, SUMA_SurfaceObject::SC, SE_FlipLight0Pos, SE_FOVreset, SE_GetNearestNode, SE_Help, SE_Home, SE_LoadSegDO, SE_OpenColFileSelection, SE_Redisplay, SE_Redisplay_AllVisible, SE_RedisplayNow, SE_RedisplayNow_AllOtherVisible, SE_SaveSOFileSelection, SE_SetForceAfniSurf, SE_SetLookAt, SE_SetNodeColor, SE_StartListening, SE_ToggleBackground, SE_ToggleConnected, SE_ToggleCrossHair, SE_ToggleForeground, SE_ToggleLockAllCrossHair, SE_ToggleShowSelectedFaceSet, SE_ToggleShowSelectedNode, SEF_Empty, SEF_fm, SEF_fv15, SEF_fv3, SEF_ip, SEF_vp, SEI_Head, SEI_In, SES_Suma, SES_SumaWidget, SUMA_SurfaceObject::Show, SUMA_SurfaceViewer::ShowBackground, SUMA_SurfaceViewer::ShowEyeAxis, SUMA_SurfaceViewer::ShowForeground, SUMA_SurfaceViewer::ShowLeft, SUMA_SurfaceViewer::ShowMeshAxis, SUMA_SurfaceViewer::ShowRight, SUMA_SurfaceViewer::ShowWorldAxis, SUMA_SurfaceObject::Side, SMA_Log, SMA_LogAndPopup, SMT_Critical, SMT_Error, SMT_Notice, SMT_Warning, SO_type, SRM_Fill, SRM_N_RenderModes, SRM_ViewerDefault, SUMA_SurfaceObject::State, SUMA_SurfaceViewer::State, SUMA_SurfaceViewer::StdView, SUMA_AddToBrushStroke(), SUMA_allocate2D(), SUMA_append_replace_string(), SUMA_append_string(), SUMA_APPLY_BUTTON, SUMA_BACKGROUND_MODULATION_FACTOR, SUMA_BEEP, SUMA_BestStandardView(), SUMA_Boolean, SUMA_BRUSH_STROKE_ACTION, SUMA_BSA_AppendStrokeOrFill, SUMA_BSA_JoinEnds, SUMA_BSA_Undefined, SUMA_ButtClose_pushed(), SUMA_Button_12_Motion, SUMA_Button_1_Motion, SUMA_Button_2_Motion, SUMA_Button_2_Shift_Motion, SUMA_Button_3_Motion, SUMA_calloc, SUMA_ClearBrushStroke(), SUMA_CMAP_nGRAY20, SUMA_ColMixModeString(), SUMA_Convexity(), SUMA_COPY_VEC, SUMA_Create_ColorScaledVect(), SUMA_CreateBrushStroke(), SUMA_CreateList(), SUMA_CreatePromptDialog(), SUMA_CreatePromptDialogStruct(), SUMA_display(), SUMA_DOUBLE_CLICK_MAX_DELAY, SUMA_Engine(), SUMA_ENTRY, SUMA_etime(), SUMA_findSO_inDOv(), SUMA_ForceUser_YesNo(), SUMA_free, SUMA_free2D(), SUMA_Free_ColorMap(), SUMA_Free_ColorScaledVect(), SUMA_GetColorList(), SUMA_GetCx(), SUMA_GetDO_Type(), SUMA_GetSelectionLine(), SUMA_GetStandardMap(), SUMA_GLXAREA_WIDGET2SV, SUMA_grabPixels(), SUMA_handleRedisplay(), SUMA_HighlightBox(), SUMA_InitializeEngineListData(), SUMA_isLocalDomainParent(), SUMA_isSO(), SUMA_isSO_G(), SUMA_JumpFocusFace(), SUMA_JumpFocusNode(), SUMA_JumpIndex(), SUMA_JumpXYZ(), SUMA_LEFT, SUMA_LookAtCoordinates(), SUMA_malloc, SUMA_MarkLineSurfaceIntersect(), SUMA_MAX_COMMAND_LENGTH, SUMA_MAX_MODES, SUMA_MAX_STRING_LENGTH, SUMA_momentum(), SUMA_N_WAX_OPTIONS, SUMA_NextState(), SUMA_OK_APPLY_CLEAR_CANCEL, SUMA_ORIG_MIX_MODE, SUMA_Overlays_2_GLCOLAR4(), SUMA_PercRange(), SUMA_PI, SUMA_postRedisplay(), SUMA_PrevState(), SUMA_Print_Surface_Object(), SUMA_ProcessBrushStroke(), SUMA_Read_2Dfile(), SUMA_ReadNumStdin(), SUMA_REGISTER_HEAD_COMMAND_NO_DATA, SUMA_REGISTER_TAIL_COMMAND_NO_DATA, SUMA_RegisteredSOs(), SUMA_RegisterEngineListCommand(), SUMA_RegisterMessage(), SUMA_RenderToPixMap(), SUMA_RETURNe, SUMA_RGBvec_2_GLCOLAR4, SUMA_RIGHT, SUMA_ScaleToMap(), SUMA_ScaleToMapOptInit(), SUMA_SET_GL_PROJECTION, SUMA_SET_GL_RENDER_MODE, SUMA_SetAllRemixFlag(), SUMA_SetLight0(), SUMA_SetNumForeSmoothing(), SUMA_SetShownLocalRemixFlag(), SUMA_Show_DOv(), SUMA_Show_SurfaceViewer_Struct(), SUMA_ShowBrushStroke(), SUMA_ShowDrawnROI(), SUMA_SL_Err, SUMA_SLP_Err, SUMA_SLP_Note, SUMA_SLP_Warn, SUMA_SmoothAttr_Neighb(), SUMA_STANDARD_CMAP, SUMA_STANDARD_VIEWS, SUMA_StringAppend(), SUMA_Surface_Curvature(), SUMA_SurfaceMetrics(), SUMA_SwitchState(), SUMA_UpdateViewerTitle(), SUMA_VisibleSOs(), SUMA_WhichState(), SUMA_WhichSV(), SUMA_WhichViewerInMomentum(), SUMA_WorldAxisStandard(), SUMA_X_SurfaceViewer_Create(), SUMA_YES, SUMAg_N_DOv, SUMAg_N_SVv, SUMA_CommonFields::SwapButtons_1_3, SWP_DONT_CARE, SWP_TOP_RIGHT, SUMA_X::Title, SUMA_X::TOPLEVEL, trackball(), trackball_Phi(), SUMA_CommonFields::ViewLocked, SUMA_SurfaceViewer::VSv, SUMA_X_AllView::WarnClose, SUMA_SurfaceViewer::WAx, SUMA_X::WIDTH, SUMA_SurfaceViewer::WindHeight, SUMA_SurfaceViewer::WindWidth, SUMA_SurfaceViewer::X, SUMA_CommonFields::X, and SUMA_SurfaceViewer::ZoomCompensate.
00015 { 00016 static char FuncName[]= {"SUMA_input"}; 00017 GLwDrawingAreaCallbackStruct *cd; 00018 char buffer[10], cbuf = '\0', cbuf2='\0'; 00019 KeySym keysym; 00020 int xls, ntot, id = 0, ND, ip, NP; 00021 float ArrowDeltaRot = 0.05; /* The larger the value, the bigger the rotation increment */ 00022 SUMA_EngineData *ED = NULL; 00023 char CommString[SUMA_MAX_COMMAND_LENGTH]; 00024 char s[SUMA_MAX_STRING_LENGTH], sfield[100], sdestination[100]; 00025 static char ssource[]={"suma"}; 00026 int it, ii, iv3[3], hit = 0; 00027 float **fm, fv3[3], fv15[15]; 00028 XKeyEvent Kev; 00029 XButtonEvent Bev; 00030 XMotionEvent Mev; 00031 int isv; 00032 SUMA_SurfaceViewer *sv, *svi = NULL; 00033 GLfloat *glar_ColorList = NULL; 00034 static Time B1time = 0; 00035 static int pButton, mButton, rButton; 00036 SUMA_Boolean ROI_mode; 00037 static SUMA_Boolean DoubleClick = NOPE; 00038 DList *list = NULL; 00039 DListElmt *NextElm= NULL; 00040 float bevx, bevy, mevx, mevy, wwid, whei, zc_fac; 00041 SUMA_PROMPT_DIALOG_STRUCT *prmpt=NULL; /* Use this only to create prompt that are not to be preserved */ 00042 SUMA_Boolean LocalHead = NOPE; /* local debugging messages */ 00043 00044 /*float ft; 00045 int **im, iv15[15];*/ /* keep unused variables undeclared to quite compiler */ 00046 00047 SUMA_ENTRY; 00048 00049 /* get the callData pointer */ 00050 cd = (GLwDrawingAreaCallbackStruct *) callData; 00051 00052 /* find out who's calling, only GLXAREA calls this function */ 00053 SUMA_GLXAREA_WIDGET2SV(w, sv, isv); 00054 if (isv < 0) { 00055 fprintf (SUMA_STDERR, "Error %s: Failed in macro SUMA_GLXAREA_WIDGET2SV.\n", FuncName); 00056 SUMA_RETURNe; 00057 } 00058 if (LocalHead) fprintf (SUMA_STDERR,"%s: A call from SUMA_SurfaceViewer[%d], Pointer %p\n", FuncName, isv, sv); 00059 00060 00061 Kev = *(XKeyEvent *) &cd->event->xkey; /* RickR's suggestion to comply with ANSI C, no type casting of structures July 04*/ 00062 Bev = *(XButtonEvent *) &cd->event->xbutton; 00063 Mev = *(XMotionEvent *) &cd->event->xmotion; 00064 00065 /* a sample keypresses */ 00066 #if 0 00067 if (Kev.state & ShiftMask) { 00068 fprintf (SUMA_STDERR,"%s: Shift down\n", FuncName); 00069 }else if (Kev.state & ControlMask){ 00070 fprintf (SUMA_STDERR,"%s: Control down\n", FuncName); 00071 }else if (Kev.state & Mod1Mask){ 00072 fprintf (SUMA_STDERR,"%s: alt down\n", FuncName); 00073 }else if (Kev.state & Mod2Mask){ 00074 fprintf (SUMA_STDERR,"%s: Mod2 down (apple on mac)\n", FuncName); 00075 }else if (Kev.state & Mod3Mask){ 00076 fprintf (SUMA_STDERR,"%s: Mod3 down\n", FuncName); 00077 }else if (Kev.state & Mod4Mask){ 00078 fprintf (SUMA_STDERR,"%s: Mod4 down\n", FuncName); 00079 }else if (Kev.state & Mod5Mask){ 00080 fprintf (SUMA_STDERR,"%s: Mod5 down\n", FuncName); 00081 }else { 00082 /*fprintf (SUMA_STDERR,"%s: Vanilla kind.\n", FuncName);*/ 00083 } 00084 #endif 00085 00086 switch (Kev.type) { /* switch event type */ 00087 case KeyPress: 00088 xls = XLookupString((XKeyEvent *) cd->event, buffer, 8, &keysym, NULL); 00089 00090 /* XK_* are found in keysymdef.h */ 00091 switch (keysym) { /* keysym */ 00092 case XK_bracketleft: /* The left bracket */ 00093 /* toggle showing left hemispheres */ 00094 { 00095 #if 0 00096 int Registered_IDs[SUMAg_N_DOv], N_RegisteredSOs, k; 00097 SUMA_SurfaceObject *SO = NULL; 00098 00099 N_RegisteredSOs = SUMA_RegisteredSOs (sv, SUMAg_DOv, Registered_IDs); 00100 for (k=0; k< N_RegisteredSOs; ++k) { 00101 SO = (SUMA_SurfaceObject *)SUMAg_DOv[Registered_IDs[k]].OP; 00102 if (SO->Side == SUMA_LEFT) SO->Show = !SO->Show; 00103 } 00104 #endif 00105 sv->ShowLeft = !sv->ShowLeft; 00106 } 00107 /* do the axis setup */ 00108 SUMA_WorldAxisStandard (sv->WAx, sv); 00109 SUMA_UpdateViewerTitle(sv); 00110 SUMA_postRedisplay(w, clientData, callData); 00111 break; 00112 00113 case XK_bracketright: /* The left bracket */ 00114 /* toggle showing left hemispheres */ 00115 { 00116 #if 0 00117 int Registered_IDs[SUMAg_N_DOv], N_RegisteredSOs, k; 00118 SUMA_SurfaceObject *SO = NULL; 00119 00120 N_RegisteredSOs = SUMA_RegisteredSOs (sv, SUMAg_DOv, Registered_IDs); 00121 for (k=0; k< N_RegisteredSOs; ++k) { 00122 SO = (SUMA_SurfaceObject *)SUMAg_DOv[Registered_IDs[k]].OP; 00123 if (SO->Side == SUMA_RIGHT) SO->Show = !SO->Show; 00124 } 00125 #endif 00126 sv->ShowRight = !sv->ShowRight; 00127 } 00128 /* do the axis setup */ 00129 SUMA_WorldAxisStandard (sv->WAx, sv); 00130 SUMA_UpdateViewerTitle(sv); 00131 SUMA_postRedisplay(w, clientData, callData); 00132 break; 00133 00134 case XK_space: /* The spacebar. */ 00135 /* toggle between state containing mapping reference of SO in focus and other view */ 00136 { 00137 SUMA_SurfaceObject *SO = NULL, *SOmap = NULL; 00138 int curstateID = -1, nxtstateID = -1, dov_ID = -1; 00139 00140 /* make sure switching is OK */ 00141 curstateID = SUMA_WhichState(sv->State, sv, sv->CurGroupName); 00142 SO = (SUMA_SurfaceObject *)SUMAg_DOv[sv->Focus_SO_ID].OP; 00143 if (SUMA_isLocalDomainParent (SO)) { 00144 /* get the last non mappable state in SV */ 00145 if (sv->LastNonMapStateID < 0) { /* not recorded, complain and quit */ 00146 fprintf(SUMA_STDERR,"Warning %s: Nothing defined to toggle with yet.\n", FuncName); 00147 break; 00148 } 00149 00150 if (LocalHead) 00151 fprintf (SUMA_STDERR,"%s: surface is inherrently mappable, switching to last non mappable state %d.\n", \ 00152 FuncName, sv->LastNonMapStateID); 00153 00154 if (!SUMA_SwitchState (SUMAg_DOv, SUMAg_N_DOv, sv, sv->LastNonMapStateID, sv->CurGroupName)) { 00155 fprintf(SUMA_STDERR,"Error %s: Failed in SUMA_SwitchState.\n", FuncName); 00156 break; 00157 } 00158 00159 } else {/* that's a non mappable, go to state containing reference */ 00160 if (LocalHead) 00161 fprintf (SUMA_STDERR,"%s: surface is not inherrently mappable, searching for mapping reference and its state.\n", \ 00162 FuncName); 00163 00164 /* find SO that is mappable reference & get corresponding state ID*/ 00165 dov_ID = SUMA_findSO_inDOv(SO->LocalDomainParentID, SUMAg_DOv, SUMAg_N_DOv); 00166 SOmap = (SUMA_SurfaceObject *)SUMAg_DOv[dov_ID].OP; 00167 nxtstateID = SUMA_WhichState(SOmap->State, sv, sv->CurGroupName); 00168 00169 if (nxtstateID < 0) { 00170 fprintf (SUMA_STDERR,"%s: Failed in SUMA_findSO_inDOv This should not happen.\n", FuncName); 00171 break; 00172 } 00173 00174 if (LocalHead) 00175 fprintf (SUMA_STDERR,"%s: Found mapping reference in viewer state %d.\n", FuncName, nxtstateID); 00176 00177 /* store this location */ 00178 sv->LastNonMapStateID = curstateID; 00179 00180 /* go there */ 00181 if (!SUMA_SwitchState (SUMAg_DOv, SUMAg_N_DOv, sv, nxtstateID, sv->CurGroupName)) { 00182 fprintf(SUMA_STDERR,"Error %s: Failed in SUMA_SwitchState.\n", FuncName); 00183 break; 00184 } 00185 } 00186 00187 } 00188 SUMA_postRedisplay(w, clientData, callData); 00189 break; 00190 00191 case XK_Escape: /* there's more: XK_BackSpace XK_Tab XK_Linefeed XK_Return XK_Delete */ 00192 /* control mask and escape is grabbed by gnome window manager .... */ 00193 if (Kev.state & ShiftMask){/* kill all */ 00194 if( SUMAg_CF->X->WarnClose) { 00195 if (SUMA_ForceUser_YesNo(sv->X->TOPLEVEL, "Close All Viewers?", SUMA_YES, SWP_DONT_CARE) != SUMA_YES) { 00196 break; 00197 } 00198 } 00199 XtCloseDisplay( SUMAg_CF->X->DPY_controller1 ) ; 00200 exit(0); 00201 }else { 00202 if( SUMAg_CF->X->WarnClose) { 00203 #ifdef DARWIN 00204 if (SUMA_ForceUser_YesNo(sv->X->TOPLEVEL, 00205 "Close This Viewer?\n" 00206 "OS-X users: If answering YES,\n" 00207 "this prompt should not lie \n" 00208 "over viewer to be closed.\n" 00209 "Blame Bill Gates for this bug.", 00210 SUMA_YES, SWP_TOP_RIGHT) != SUMA_YES) { 00211 break; 00212 } 00213 #else 00214 if (SUMA_ForceUser_YesNo(sv->X->TOPLEVEL, "Close This Viewer?", SUMA_YES, SWP_DONT_CARE) != SUMA_YES) { 00215 break; 00216 } 00217 #endif 00218 } 00219 SUMA_ButtClose_pushed (w, clientData, callData); 00220 } 00221 break; 00222 00223 case XK_a: 00224 /* toggle background attenuation */ 00225 00226 if (sv->Back_Modfact) { 00227 fprintf (SUMA_STDOUT,"%s: Modulation by background intensity OFF.\n", FuncName); 00228 sv->Back_Modfact = 0; 00229 } else { 00230 fprintf (SUMA_STDOUT,"%s: Modulation by background intensity ON.\n", FuncName); 00231 sv->Back_Modfact = SUMA_BACKGROUND_MODULATION_FACTOR; 00232 } 00233 00234 /* set the remix flag */ 00235 if (!SUMA_SetShownLocalRemixFlag (sv)) { 00236 fprintf (SUMA_STDERR,"Error %s: Failed in SUMA_SetShownLocalRemixFlag.\n", FuncName); 00237 break; 00238 } 00239 00240 #if 0 00241 { 00242 SUMA_SurfaceObject *SO = NULL; 00243 00244 for (ii=0; ii< sv->N_DO; ++ii) { 00245 if (SUMA_isSO_G(SUMAg_DOv[sv->RegisteredDO[ii]], sv->Group)) { 00246 SO = (SUMA_SurfaceObject*)SUMAg_DOv[sv->RegisteredDO[ii]].OP; 00247 /* remix colors */ 00248 glar_ColorList = SUMA_GetColorList (sv, SO->idcode_str); 00249 if (!glar_ColorList) { 00250 fprintf (SUMA_STDERR,"Error %s: NULL glar_ColorList.\n", FuncName); 00251 SUMA_RETURNe; 00252 } 00253 if (!SUMA_Overlays_2_GLCOLAR4(SO->Overlays, SO->N_Overlays, glar_ColorList, SO->N_Node, \ 00254 sv->Back_Modfact, sv->ShowBackground, sv->ShowForeground)) { 00255 fprintf (SUMA_STDERR,"Error %s: Failed in SUMA_Overlays_2_GLCOLAR4.\n", FuncName); 00256 SUMA_RETURNe; 00257 } 00258 } 00259 } 00260 } 00261 #endif 00262 00263 SUMA_postRedisplay(w, clientData, callData); 00264 break; 00265 00266 case XK_B: 00267 sv->BF_Cull = !sv->BF_Cull; 00268 if (sv->BF_Cull) { 00269 glCullFace (GL_BACK); 00270 glEnable (GL_CULL_FACE); 00271 SUMA_SLP_Note ("BackFace Culling enabled."); 00272 } else { 00273 glDisable(GL_CULL_FACE); 00274 SUMA_SLP_Note ("BackFace Culling disabled."); 00275 } 00276 SUMA_postRedisplay(w, clientData, callData); 00277 break; 00278 00279 case XK_b: 00280 /* Show/hide the background */ 00281 if (!list) list = SUMA_CreateList(); 00282 ED = SUMA_InitializeEngineListData (SE_ToggleBackground); 00283 if (!SUMA_RegisterEngineListCommand ( list, ED, 00284 SEF_Empty, NULL, 00285 SES_Suma, (void *)sv, NOPE, 00286 SEI_Head, NULL)) { 00287 fprintf (SUMA_STDERR, "Error %s: Failed to register command.\n", FuncName); 00288 } 00289 00290 ED = SUMA_InitializeEngineListData (SE_Redisplay); 00291 if (!SUMA_RegisterEngineListCommand ( list, ED, 00292 SEF_Empty, NULL, 00293 SES_Suma, (void *)sv, NOPE, 00294 SEI_Head, NULL)) { 00295 fprintf (SUMA_STDERR, "Error %s: Failed to register command.\n", FuncName); 00296 } 00297 00298 if (!SUMA_Engine (&list)) { 00299 fprintf(SUMA_STDERR, "Error SUMA_input: SUMA_Engine call failed.\n"); 00300 } 00301 break; 00302 00303 case XK_c: 00304 if (!list) list = SUMA_CreateList(); 00305 ED = SUMA_InitializeEngineListData (SE_OpenColFileSelection); 00306 if (!(NextElm = SUMA_RegisterEngineListCommand ( list, ED, 00307 SEF_vp, (void *)(SUMAg_DOv[sv->Focus_SO_ID].OP), 00308 SES_Suma, (void *)sv, NOPE, 00309 SEI_Head, NULL))) { 00310 fprintf (SUMA_STDERR, "Error %s: Failed to register command.\n", FuncName); 00311 } 00312 00313 if (!SUMA_RegisterEngineListCommand ( list, ED, 00314 SEF_ip, sv->X->TOPLEVEL, 00315 SES_Suma, (void *)sv, NOPE, 00316 SEI_In, NextElm)) { 00317 fprintf (SUMA_STDERR, "Error %s: Failed to register command.\n", FuncName); 00318 } 00319 00320 if (!SUMA_Engine (&list)) { 00321 fprintf(SUMA_STDERR, "Error %s: SUMA_Engine call failed.\n", FuncName); 00322 } 00323 00324 break; 00325 00326 #if 0 00327 /* THE OLD WAY (part of it) FOR SETTING NODE COLORS DIRECTLY, Left here for documentation */ 00328 /* allocate space */ 00329 fm = (float **)SUMA_allocate2D (ntot/4, 4, sizeof(float)); 00330 if (fm == NULL) { 00331 fprintf(stderr,"Error SUMA_input: Failed to allocate space for fm\n"); 00332 SUMA_RETURNe; 00333 } 00334 00335 if (SUMA_Read_2Dfile (s, fm, 4, ntot/4) != ntot/4 ) { 00336 fprintf(stderr,"SUMA_input Error: Failed to read full matrix from %s\n", s); 00337 SUMA_RETURNe; 00338 } 00339 00340 if (!list) list = SUMA_CreateList(); 00341 ED = SUMA_InitializeEngineListData (SE_SetNodeColor); 00342 ED->N_cols = 4; 00343 ED->N_rows = ntot/4; 00344 if (!SUMA_RegisterEngineListCommand ( list, ED, 00345 SEF_fm, (void*)fm, 00346 SES_Suma, (void *)sv, YUP, 00347 SEI_Head, NULL)) { 00348 fprintf(SUMA_STDERR,"Error %s: Failed to register element\n", FuncName); 00349 break; 00350 } 00351 00352 00353 SUMA_REGISTER_HEAD_COMMAND_NO_DATA(list, SE_Redisplay, SES_Suma, sv); 00354 00355 if (!SUMA_Engine (&list)) { 00356 fprintf(SUMA_STDERR, "Error %s: SUMA_Engine call failed.\n", FuncName); 00357 } 00358 00359 /* free fm since it was registered by pointer and is not automatically freed after the call to SUMA_Engine */ 00360 if (fm) SUMA_free2D ((char **)fm, ntot/4); 00361 break; 00362 #endif 00363 00364 00365 case XK_d: 00366 if (SUMAg_CF->Dev) { 00367 SUMA_Show_DOv(SUMAg_DOv, SUMAg_N_DOv, stdout); 00368 } 00369 break; 00370 00371 case XK_e: 00372 if (SUMAg_CF->Dev) { 00373 if (Kev.state & Mod1Mask || Kev.state & Mod2Mask){ /* Mod1Mask is alt in linux, Mod2Mask is the apple on mac*/ 00374 int error, cnt = 0; 00375 fprintf (SUMA_STDERR, "%s: Looking for OpenGL errors ...\n", FuncName); 00376 while ((error = glGetError()) != GL_NO_ERROR) { 00377 ++cnt; 00378 fprintf (SUMA_STDERR, "GL error %d: %s\n", cnt, gluErrorString(error)); 00379 } 00380 if (!cnt) { 00381 fprintf (SUMA_STDERR, "%s: No errors found.\n", FuncName); 00382 } 00383 } 00384 } 00385 break; 00386 00387 case XK_F: 00388 /* flip light position */ 00389 if (!list) list = SUMA_CreateList(); 00390 SUMA_REGISTER_HEAD_COMMAND_NO_DATA(list, SE_FlipLight0Pos, SES_Suma, sv); 00391 SUMA_REGISTER_HEAD_COMMAND_NO_DATA(list, SE_Redisplay, SES_Suma, sv); 00392 00393 if (!SUMA_Engine (&list)) { 00394 fprintf(stderr, "Error SUMA_input: SUMA_Engine call failed.\n"); 00395 } 00396 break; 00397 00398 case XK_f: 00399 /* Show/hide the foreground */ 00400 if (!list) list = SUMA_CreateList(); 00401 SUMA_REGISTER_HEAD_COMMAND_NO_DATA(list, SE_ToggleForeground, SES_Suma, sv); 00402 SUMA_REGISTER_HEAD_COMMAND_NO_DATA(list, SE_Redisplay, SES_Suma, sv); 00403 00404 if (!SUMA_Engine (&list)) { 00405 fprintf(stderr, "Error SUMA_input: SUMA_Engine call failed.\n"); 00406 } 00407 break; 00408 00409 case XK_H: 00410 sv->X->HighlightBox_prmpt = SUMA_CreatePromptDialogStruct (SUMA_OK_APPLY_CLEAR_CANCEL, 00411 "Enter XYZ of box's center\n" 00412 "followed by it's size (6 values)", 00413 "", 00414 sv->X->TOPLEVEL, YUP, 00415 SUMA_APPLY_BUTTON, 00416 SUMA_HighlightBox, (void *)sv, 00417 NULL, NULL, 00418 NULL, NULL, 00419 SUMA_isNumString, (void*)6, 00420 sv->X->HighlightBox_prmpt); 00421 00422 sv->X->HighlightBox_prmpt = SUMA_CreatePromptDialog(sv->X->Title, sv->X->HighlightBox_prmpt); 00423 00424 break; 00425 00426 case XK_h: 00427 if (Kev.state & ControlMask){ 00428 if (!list) list = SUMA_CreateList(); 00429 SUMA_REGISTER_HEAD_COMMAND_NO_DATA(list, SE_Help, SES_Suma, NULL); 00430 if (!SUMA_Engine (&list)) { 00431 fprintf(stderr, "Error %s: SUMA_Engine call failed.\n", FuncName); 00432 } 00433 }else{ 00434 if (SUMAg_CF->Dev) { 00435 SUMA_SLP_Note("Please use ctrl+h for help.\nh alone will be reassigned\nin future versions."); 00436 #if 0 00437 /* fake some error logs */ 00438 SUMA_RegisterMessage (SUMAg_CF->MessageList, "Test Notice", FuncName, SMT_Notice, SMA_Log); 00439 SUMA_RegisterMessage (SUMAg_CF->MessageList, "Test Notice2", FuncName, SMT_Notice, SMA_LogAndPopup); 00440 SUMA_RegisterMessage (SUMAg_CF->MessageList, "Test Warning", FuncName, SMT_Warning, SMA_LogAndPopup); 00441 SUMA_RegisterMessage (SUMAg_CF->MessageList, "Test Error", FuncName, SMT_Error, SMA_LogAndPopup); 00442 SUMA_RegisterMessage (SUMAg_CF->MessageList, "Test Critical", FuncName, SMT_Critical, SMA_LogAndPopup); 00443 #endif 00444 } 00445 } 00446 break; 00447 00448 case XK_j: 00449 if (Kev.state & ControlMask){ 00450 sv->X->JumpXYZ_prmpt = SUMA_CreatePromptDialogStruct (SUMA_OK_APPLY_CLEAR_CANCEL, 00451 "Enter XYZ to send the cross hair to:", 00452 "", 00453 sv->X->TOPLEVEL, YUP, 00454 SUMA_APPLY_BUTTON, 00455 SUMA_JumpXYZ, (void *)sv, 00456 NULL, NULL, 00457 NULL, NULL, 00458 SUMA_isNumString, (void*)3, 00459 sv->X->JumpXYZ_prmpt); 00460 00461 sv->X->JumpXYZ_prmpt = SUMA_CreatePromptDialog(sv->X->Title, sv->X->JumpXYZ_prmpt); 00462 00463 } else if (Kev.state & Mod1Mask || Kev.state & Mod2Mask){ 00464 sv->X->JumpFocusNode_prmpt = SUMA_CreatePromptDialogStruct (SUMA_OK_APPLY_CLEAR_CANCEL, 00465 "Enter index of focus node\nCross hair's XYZ will not be affected:", 00466 "", 00467 sv->X->TOPLEVEL, YUP, 00468 SUMA_APPLY_BUTTON, 00469 SUMA_JumpFocusNode, (void *)sv, 00470 NULL, NULL, 00471 NULL, NULL, 00472 SUMA_isNumString, (void*)1, 00473 sv->X->JumpFocusNode_prmpt); 00474 00475 sv->X->JumpFocusNode_prmpt = SUMA_CreatePromptDialog(sv->X->Title, sv->X->JumpFocusNode_prmpt); 00476 00477 } else { 00478 sv->X->JumpIndex_prmpt = SUMA_CreatePromptDialogStruct (SUMA_OK_APPLY_CLEAR_CANCEL, 00479 "Enter index of node \nto send the cross hair to:", 00480 "", 00481 sv->X->TOPLEVEL, YUP, 00482 SUMA_APPLY_BUTTON, 00483 SUMA_JumpIndex, (void *)sv, 00484 NULL, NULL, 00485 NULL, NULL, 00486 SUMA_isNumString, (void*)1, 00487 sv->X->JumpIndex_prmpt); 00488 00489 sv->X->JumpIndex_prmpt = SUMA_CreatePromptDialog(sv->X->Title, sv->X->JumpIndex_prmpt); 00490 } 00491 00492 break; 00493 00494 case XK_J: 00495 sv->X->JumpFocusFace_prmpt = SUMA_CreatePromptDialogStruct (SUMA_OK_APPLY_CLEAR_CANCEL, 00496 "Enter index of FaceSet\nto highlight (this viewer only):", 00497 "", 00498 sv->X->TOPLEVEL, YUP, 00499 SUMA_APPLY_BUTTON, 00500 SUMA_JumpFocusFace, (void *)sv, 00501 NULL, NULL, 00502 NULL, NULL, 00503 SUMA_isNumString, (void*)1, 00504 sv->X->JumpFocusFace_prmpt); 00505 00506 sv->X->JumpFocusFace_prmpt = SUMA_CreatePromptDialog(sv->X->Title, sv->X->JumpFocusFace_prmpt); 00507 00508 break; 00509 00510 case XK_l: 00511 if (Kev.state & ControlMask){ 00512 00513 if (SUMAg_CF->Dev) { 00514 if (!list) list = SUMA_CreateList(); 00515 ED = SUMA_InitializeEngineListData (SE_ToggleLockAllCrossHair); 00516 if (!SUMA_RegisterEngineListCommand ( list, ED, 00517 SEF_Empty, NULL, 00518 SES_Suma, (void *)sv, NOPE, 00519 SEI_Head, NULL )) { 00520 fprintf(SUMA_STDERR,"Error %s: Failed to register command\n", FuncName); 00521 break; 00522 } 00523 if (!SUMA_Engine (&list)) { 00524 fprintf(stderr, "Error %s: SUMA_Engine call failed.\n", FuncName); 00525 } 00526 } 00527 } if (Kev.state & Mod1Mask || Kev.state & Mod2Mask){ /* alt + l */ 00528 /* register cross hair XYZ with ED */ 00529 if (!list) list = SUMA_CreateList(); 00530 ED = SUMA_InitializeEngineListData (SE_SetLookAt); 00531 if (!SUMA_RegisterEngineListCommand ( list, ED, 00532 SEF_fv3, (void *)sv->Ch->c, 00533 SES_Suma, (void *)sv, NOPE, 00534 SEI_Head, NULL )) { 00535 fprintf(SUMA_STDERR,"Error %s: Failed to register command\n", FuncName); 00536 SUMA_RETURNe; 00537 } 00538 if (!SUMA_Engine (&list)) { 00539 fprintf(stderr, "Error %s: SUMA_Engine call failed.\n", FuncName); 00540 } 00541 } else { 00542 sv->X->LookAt_prmpt = SUMA_CreatePromptDialogStruct (SUMA_OK_APPLY_CLEAR_CANCEL, "X,Y,Z coordinates to look at:", 00543 "0,0,0", 00544 sv->X->TOPLEVEL, YUP, 00545 SUMA_APPLY_BUTTON, 00546 SUMA_LookAtCoordinates, (void *)sv, 00547 NULL, NULL, 00548 NULL, NULL, 00549 SUMA_isNumString, (void*)3, 00550 sv->X->LookAt_prmpt); 00551 00552 sv->X->LookAt_prmpt = SUMA_CreatePromptDialog(sv->X->Title, sv->X->LookAt_prmpt); 00553 00554 } 00555 break; 00556 00557 case XK_L: 00558 prmpt = SUMA_CreatePromptDialogStruct (SUMA_OK_APPLY_CLEAR_CANCEL, "X,Y,Z coordinates of light0:", 00559 "", 00560 sv->X->TOPLEVEL, NOPE, 00561 SUMA_APPLY_BUTTON, 00562 SUMA_SetLight0, (void *)sv, 00563 NULL, NULL, 00564 NULL, NULL, 00565 SUMA_isNumString, (void*)3, 00566 NULL); 00567 00568 prmpt = SUMA_CreatePromptDialog(sv->X->Title, prmpt); 00569 00570 break; 00571 00572 case XK_M: 00573 if ((Kev.state & Mod1Mask || Kev.state & Mod2Mask) && (Kev.state & ControlMask) ){ 00574 #ifndef DONT_USE_MCW_MALLOC 00575 /* write memtrace results to disk */ 00576 if (!mcw_malloc_enabled) { 00577 SUMA_SLP_Warn("Memory tracing\n" 00578 "is not enabled.\n" 00579 "Use Help-->MemTrace."); 00580 SUMA_RETURNe; 00581 } else { 00582 SUMA_SLP_Note("Dumping memory tracing\n" 00583 "to latest ./malldump.???\n" 00584 "file (if possible)."); 00585 mcw_malloc_dump(); 00586 } 00587 #else 00588 SUMA_SLP_Warn("Sorry, memory tracing\n" 00589 "was not enabled at compile.\n" 00590 "time. You are out of luck\n" 00591 "if using SUN."); 00592 SUMA_RETURNe; 00593 #endif 00594 } 00595 break; 00596 00597 case XK_m: 00598 if (Kev.state & ControlMask){ 00599 if (SUMAg_CF->Dev) { 00600 SUMA_SurfaceObject *SO; 00601 00602 fprintf(SUMA_STDOUT, "%s: Enter mm distance [RAI] to move center of all mappable surfaces in DOv by.\n", FuncName); 00603 it = SUMA_ReadNumStdin (fv3, 3); 00604 if (it > 0 && it < 3) { 00605 fprintf(SUMA_STDERR,"Error %s: read %d values, expected 3.\n", FuncName, it); 00606 SUMA_RETURNe; 00607 }else if (it < 0) { 00608 fprintf(SUMA_STDERR,"Error %s: Error in SUMA_ReadNumStdin.\n", FuncName); 00609 SUMA_RETURNe; 00610 }else if (it == 0) { 00611 fprintf(SUMA_STDERR,"%s: Nothing read.\n", FuncName); 00612 SUMA_RETURNe; 00613 } 00614 00615 for (it = 0; it < SUMAg_N_DOv; ++it) { 00616 if (SUMA_isSO_G (SUMAg_DOv[it], sv->CurGroupName)) { 00617 SO = (SUMA_SurfaceObject *)SUMAg_DOv[it].OP; 00618 if (SUMA_isLocalDomainParent(SO)) { 00619 int imax; 00620 /* add the shift */ 00621 fprintf (SUMA_STDERR,"%s: Shifting %s by %f %f %f mm RAI.\n", FuncName, SO->Label, fv3[0], fv3[1], fv3[2]); 00622 ii = 0; 00623 imax = 3 * SO->N_Node; 00624 while (ii < imax) { 00625 SO->NodeList[ii] += fv3[0]; ++ii; 00626 SO->NodeList[ii] += fv3[1]; ++ii; 00627 SO->NodeList[ii] += fv3[2]; ++ii; 00628 } 00629 } 00630 } 00631 } 00632 00633 SUMA_postRedisplay(w, clientData, callData); 00634 } 00635 } else { 00636 sv->GVS[sv->StdView].ApplyMomentum = !sv->GVS[sv->StdView].ApplyMomentum; 00637 SUMA_UpdateViewerTitle(sv); 00638 if (sv->GVS[sv->StdView].ApplyMomentum) { 00639 sv->X->MOMENTUMID = XtAppAddTimeOut(SUMAg_CF->X->App, 1, SUMA_momentum, (XtPointer) w); 00640 /* wait till user initiates turning */ 00641 sv->GVS[sv->StdView].spinDeltaX = 0; sv->GVS[sv->StdView].spinDeltaY = 0; 00642 sv->GVS[sv->StdView].translateDeltaX = 0; sv->GVS[sv->StdView].translateDeltaY = 0; 00643 } else { 00644 if (sv->X->MOMENTUMID) { 00645 XtRemoveTimeOut(sv->X->MOMENTUMID); 00646 sv->X->MOMENTUMID = 0; 00647 } 00648 } 00649 } 00650 break; 00651 00652 case XK_n: 00653 if (Kev.state & ControlMask){ 00654 if (LocalHead) fprintf(SUMA_STDOUT, "%s: Opening a new controller...\n", FuncName); 00655 /* open a new controller */ 00656 if (!SUMA_X_SurfaceViewer_Create ()) { 00657 fprintf (SUMA_STDERR,"Error %s: Failed in SUMA_X_SurfaceViewer_Create.\n", FuncName); 00658 SUMA_RETURNe; 00659 } 00660 }else { 00661 if (SUMAg_CF->Dev) { 00662 fprintf(stdout,"BAD IDEA Enter XYZ of center followed by size of Box (enter nothing to cancel):\n"); 00663 00664 it = SUMA_ReadNumStdin (fv15, 6); 00665 if (it > 0 && it < 6) { 00666 fprintf(SUMA_STDERR,"Error %s: read %d values, expected 6.\n", FuncName, it); 00667 SUMA_RETURNe; 00668 }else if (it < 0) { 00669 fprintf(SUMA_STDERR,"Error %s: Error in SUMA_ReadNumStdin.\n", FuncName); 00670 SUMA_RETURNe; 00671 }else if (it == 0) { 00672 SUMA_RETURNe; 00673 } 00674 00675 fprintf (SUMA_STDOUT, "Parsed Input:\n\tCenter %f, %f, %f.\n\tBox Size %f, %f, %f\n", \ 00676 fv15[0], fv15[1],fv15[2],\ 00677 fv15[3], fv15[4],fv15[5]); 00678 00679 /* register fv15 with ED */ 00680 if (!list) list = SUMA_CreateList (); 00681 ED = SUMA_InitializeEngineListData (SE_GetNearestNode); 00682 if (!SUMA_RegisterEngineListCommand ( list, ED, 00683 SEF_fv15, (void *)fv15, 00684 SES_Suma, (void *)sv, NOPE, 00685 SEI_Head, NULL )) { 00686 fprintf(SUMA_STDERR,"Error %s: Failed to register command\n", FuncName); 00687 break; 00688 } 00689 00690 SUMA_REGISTER_HEAD_COMMAND_NO_DATA(list, SE_Redisplay, SES_Suma, sv); 00691 if (!SUMA_Engine (&list)) { 00692 fprintf(stderr, "Error %s: SUMA_Engine call failed.\n", FuncName); 00693 } 00694 } 00695 } 00696 break; 00697 00698 case XK_p: 00699 sv->PolyMode = ((sv->PolyMode+1) % SRM_N_RenderModes); 00700 if (sv->PolyMode <= SRM_ViewerDefault) sv->PolyMode = SRM_Fill; 00701 00702 SUMA_SET_GL_RENDER_MODE(sv->PolyMode); 00703 SUMA_postRedisplay(w, clientData, callData); 00704 break; 00705 00706 case XK_r: 00707 { 00708 GLvoid *pixels; 00709 pixels = SUMA_grabPixels(1, sv->X->WIDTH, sv->X->HEIGHT); 00710 if (pixels) { 00711 ISQ_snapsave (sv->X->WIDTH, -sv->X->HEIGHT, (unsigned char *)pixels, sv->X->GLXAREA ); 00712 SUMA_free(pixels); 00713 }else { 00714 SUMA_SLP_Err("Failed to record image."); 00715 } 00716 } 00717 break; 00718 00719 case XK_R: 00720 sv->Record = !sv->Record; 00721 if (sv->Record) { SUMA_SLP_Note ("Recording ON"); } 00722 else { SUMA_SLP_Note ("Recording OFF"); } 00723 SUMA_UpdateViewerTitle(sv); 00724 break; 00725 00726 case XK_S: 00727 if (SUMAg_CF->Dev) { 00728 int *do_id, n_do_id; 00729 do_id = SUMA_GetDO_Type(SUMAg_DOv, SUMAg_N_DOv, SO_type, &n_do_id); 00730 if (n_do_id) { 00731 while (n_do_id) { 00732 SUMA_Print_Surface_Object((SUMA_SurfaceObject *)SUMAg_DOv[do_id[n_do_id-1]].OP, stdout); 00733 --n_do_id; 00734 } 00735 SUMA_free(do_id); 00736 } 00737 break; 00738 } 00739 case XK_s: 00740 if ((Kev.state & Mod1Mask || Kev.state & Mod2Mask) && (Kev.state & ControlMask) && SUMAg_CF->Dev){ 00741 if (!list) list = SUMA_CreateList(); 00742 ED = SUMA_InitializeEngineListData (SE_LoadSegDO); 00743 if (!SUMA_RegisterEngineListCommand ( list, ED, 00744 SEF_ip, sv->X->TOPLEVEL, 00745 SES_Suma, (void *)sv, NOPE, 00746 SEI_Head, NULL)) { 00747 fprintf (SUMA_STDERR, "Error %s: Failed to register command.\n", FuncName); 00748 } 00749 if (!SUMA_Engine (&list)) { 00750 fprintf(SUMA_STDERR, "Error %s: SUMA_Engine call failed.\n", FuncName); 00751 } 00752 00753 } else if (Kev.state & Mod1Mask || Kev.state & Mod2Mask){ 00754 /* swap buttons 1 and 3 */ 00755 SUMAg_CF->SwapButtons_1_3 = !SUMAg_CF->SwapButtons_1_3; 00756 if (SUMAg_CF->SwapButtons_1_3) { 00757 fprintf (SUMA_STDOUT,"%s: Buttons 1 and 3 are swapped.\n", FuncName); 00758 } else { 00759 fprintf (SUMA_STDOUT,"%s: Default functions for buttons 1 and 3.\n", FuncName); 00760 } 00761 } else if (SUMAg_CF->Dev) { 00762 #if 0 00763 /** Feb 03/03 No longer in use.*/ 00764 for (ii=0; ii< sv->N_DO; ++ii) { 00765 if (SUMA_isSO(SUMAg_DOv[sv->RegisteredDO[ii]])) 00766 SUMA_Print_Surface_Object((SUMA_SurfaceObject*)SUMAg_DOv[sv->RegisteredDO[ii]].OP, stdout); 00767 } 00768 #endif 00769 } 00770 break; 00771 00772 case XK_t: 00773 if ((Kev.state & ControlMask)){ 00774 SUMA_SLP_Note("Forcing a resend of Surfaces to Afni..."); 00775 if (!list) list = SUMA_CreateList(); 00776 SUMA_REGISTER_HEAD_COMMAND_NO_DATA(list, SE_SetForceAfniSurf, SES_Suma, sv); 00777 00778 if (!SUMA_Engine (&list)) { 00779 fprintf(SUMA_STDERR, "Error %s: SUMA_Engine call failed.\n", FuncName); 00780 } 00781 } else { 00782 if (!list) list = SUMA_CreateList(); 00783 SUMA_REGISTER_HEAD_COMMAND_NO_DATA(list, SE_ToggleConnected, SES_Suma, sv); 00784 00785 if (!SUMA_Engine (&list)) { 00786 fprintf(SUMA_STDERR, "Error %s: SUMA_Engine call failed.\n", FuncName); 00787 } 00788 } 00789 break; 00790 00791 case XK_T: 00792 if (!list) list = SUMA_CreateList(); 00793 SUMA_REGISTER_HEAD_COMMAND_NO_DATA(list, SE_StartListening, SES_Suma, sv); 00794 00795 if (!SUMA_Engine (&list)) { 00796 fprintf(SUMA_STDERR, "Error %s: SUMA_Engine call failed.\n", FuncName); 00797 } 00798 break; 00799 00800 case XK_v: 00801 #if 0 00802 /*** No longer in use, Jan 03 2004 */ 00803 if (SUMAg_CF->Dev) { 00804 SUMA_Show_SurfaceViewer_Struct (sv, stdout, 0); 00805 } 00806 #endif 00807 break; 00808 00809 case XK_W: 00810 { 00811 SUMA_SurfaceObject *SO; 00812 00813 SO = (SUMA_SurfaceObject *)SUMAg_DOv[sv->Focus_SO_ID].OP; 00814 if (SO) { 00815 if (!list) list = SUMA_CreateList(); 00816 ED = SUMA_InitializeEngineListData (SE_SaveSOFileSelection); 00817 if (!(NextElm = SUMA_RegisterEngineListCommand ( list, ED, 00818 SEF_vp, (void *)SO, 00819 SES_Suma, (void *)sv, NOPE, 00820 SEI_Head, NULL))) { 00821 fprintf (SUMA_STDERR, "Error %s: Failed to register command.\n", FuncName); 00822 } 00823 00824 if (!SUMA_RegisterEngineListCommand ( list, ED, 00825 SEF_ip, sv->X->TOPLEVEL, 00826 SES_Suma, (void *)sv, NOPE, 00827 SEI_In, NextElm)) { 00828 fprintf (SUMA_STDERR, "Error %s: Failed to register command.\n", FuncName); 00829 } 00830 00831 if (!SUMA_Engine (&list)) { 00832 fprintf(SUMA_STDERR, "Error %s: SUMA_Engine call failed.\n", FuncName); 00833 } 00834 } 00835 } 00836 break; 00837 00838 case XK_w: 00839 SUMA_SLP_Warn("Option 'w' no longer supported.\nUse 'R' or 'r' instead."); 00840 #if 0 00841 fprintf(SUMA_STDOUT,"%s: Began rendering to file. Please wait ...\n", FuncName); 00842 if (!SUMA_RenderToPixMap (sv, SUMAg_DOv)) { 00843 fprintf(SUMA_STDERR, "Error %s: Failed to write image.\n", FuncName); 00844 } 00845 #endif 00846 break; 00847 00848 case XK_Z: 00849 /*fprintf(stdout,"Zoom in");*/ 00850 sv->FOV[sv->iState] /= FOV_IN_FACT; if (sv->FOV[sv->iState] < FOV_MIN) { SUMA_BEEP; sv->FOV[sv->iState] = FOV_MIN; } 00851 /* Now update the zoom compensation variable */ 00852 if (sv->ZoomCompensate) { 00853 sv->ZoomCompensate = sv->FOV[sv->iState] / FOV_INITIAL; 00854 if (sv->ZoomCompensate > 1) sv->ZoomCompensate = 1.0; /* weird stuff at zc_fac higher that 1.5 */ 00855 else if (sv->ZoomCompensate < 0.005) sv->ZoomCompensate = 0.005; 00856 } 00857 SUMA_postRedisplay(w, clientData, callData); 00858 break; 00859 00860 case XK_z: 00861 /*fprintf(stdout,"Zoom out");*/ 00862 sv->FOV[sv->iState] /= FOV_OUT_FACT; if (sv->FOV[sv->iState] > FOV_MAX) { SUMA_BEEP; sv->FOV[sv->iState] = FOV_MAX; } 00863 /* Now update the zoom compensation variable */ 00864 if (sv->ZoomCompensate) { 00865 sv->ZoomCompensate = sv->FOV[sv->iState] / FOV_INITIAL; 00866 if (sv->ZoomCompensate > 1) sv->ZoomCompensate = 1.0; /* weird stuff at zc_fac higher that 1.5 */ 00867 else if (sv->ZoomCompensate < 0.005) sv->ZoomCompensate = 0.005; /* weird stuff cause by integer spin variables! Proper way to handle all this is with float position storage and no recalculation of zc_fac except at zooming.*/ 00868 } 00869 SUMA_postRedisplay(w, clientData, callData); 00870 break; 00871 00872 case XK_8: 00873 { 00874 char stmp[100]; 00875 sprintf(stmp, "%d", SUMAg_CF->X->NumForeSmoothing); 00876 SUMAg_CF->X->N_ForeSmooth_prmpt = SUMA_CreatePromptDialogStruct (SUMA_OK_APPLY_CLEAR_CANCEL, "Foreground smoothing iterations", 00877 stmp, 00878 sv->X->TOPLEVEL, YUP, 00879 SUMA_APPLY_BUTTON, 00880 SUMA_SetNumForeSmoothing, (void *)sv, 00881 NULL, NULL, 00882 NULL, NULL, 00883 SUMA_isNumString, (void*)1, 00884 SUMAg_CF->X->N_ForeSmooth_prmpt); 00885 00886 SUMAg_CF->X->N_ForeSmooth_prmpt = SUMA_CreatePromptDialog("Foreground smoothing iterations", SUMAg_CF->X->N_ForeSmooth_prmpt); 00887 } 00888 break; 00889 00890 case XK_asterisk: 00891 fprintf(SUMA_STDOUT, "%s: smoothing node attributes ...\n", FuncName); 00892 { 00893 SUMA_SurfaceObject *SO; 00894 float * attr_sm; 00895 float *attrbuf; 00896 int ic, cnt; 00897 int allcols; 00898 00899 SO = (SUMA_SurfaceObject *)SUMAg_DOv[sv->Focus_SO_ID].OP; 00900 attrbuf = (float *)SUMA_calloc(SO->N_Node, sizeof(int)); 00901 if (attrbuf == NULL) { 00902 fprintf(stderr,"Error SUMA_input: Failed to allocate for attrbuf.\n"); 00903 break; 00904 } 00905 00906 allcols = 4 * SO->N_Node; 00907 /* the colors are stored in glar_ColorList, RGBA */ 00908 glar_ColorList = SUMA_GetColorList (sv, SO->idcode_str); 00909 if (!glar_ColorList) { 00910 fprintf(SUMA_STDERR, "Error %s: Null glar_ColorList.\n", FuncName); 00911 break; 00912 } 00913 for (ic=0; ic < 3; ++ic) { /* ic */ 00914 ii = ic; 00915 cnt = 0; 00916 while (ii < allcols) { 00917 attrbuf[cnt] = glar_ColorList[ii]; 00918 ii += 4; 00919 cnt += 1; 00920 } 00921 00922 attr_sm = SUMA_SmoothAttr_Neighb (attrbuf, SO->N_Node, NULL, SO->FN, 1); 00923 if (attr_sm == NULL) { 00924 fprintf(stderr,"Error SUMA_input: Failed in SUMA_SmoothAttr_Neighb\n"); 00925 break; 00926 } 00927 00928 /* copy results back into colorvector */ 00929 ii = ic; 00930 cnt = 0; 00931 while (ii < allcols) { 00932 glar_ColorList[ii] = attr_sm[cnt]; 00933 ii += 4; 00934 cnt += 1; 00935 } 00936 } /* ic */ 00937 00938 SUMA_free(attr_sm); 00939 SUMA_free(attrbuf); 00940 /*fprintf(SUMA_STDOUT, "%s: Smoothing Done ...\n", FuncName);*/ 00941 SUMA_postRedisplay(w, clientData, callData); 00942 } 00943 00944 break; 00945 00946 case XK_at: 00947 if (SUMAg_CF->Dev) { 00948 /* calculate the curvature */ 00949 fprintf(SUMA_STDOUT, "%s: Calculating surface curvature ...\n", FuncName); 00950 { 00951 SUMA_SurfaceObject *SO; 00952 SO = (SUMA_SurfaceObject *)SUMAg_DOv[sv->Focus_SO_ID].OP; 00953 if (!SO->PolyArea) { 00954 fprintf(SUMA_STDOUT, "%s: Computing required mesh area.\n", FuncName); 00955 if (!SUMA_SurfaceMetrics (SO, "PolyArea", NULL)) { 00956 fprintf (SUMA_STDERR,"Error %s: Failed in SUMA_SurfaceMetrics.\n", FuncName); 00957 break; 00958 } 00959 } 00960 SO->SC = SUMA_Surface_Curvature (SO->NodeList, SO->N_Node, SO->NodeNormList, SO->PolyArea, SO->N_FaceSet, SO->FN, SO->EL); 00961 if (SO->SC == NULL) { 00962 fprintf(stderr,"Error %s: Failed in SUMA_Surface_Curvature\n", FuncName); 00963 break; 00964 } 00965 } 00966 } 00967 break; 00968 00969 case XK_parenleft: 00970 if (SUMAg_CF->Dev) { 00971 SUMA_SurfaceObject *SO; 00972 SUMA_COLOR_MAP *CM; 00973 SUMA_SCALE_TO_MAP_OPT * OptScl; 00974 SUMA_STANDARD_CMAP MapType; 00975 SUMA_COLOR_SCALED_VECT * SV; 00976 float IntRange[2], *Vsort; 00977 float * attr_sm; 00978 float *Cx = NULL; 00979 00980 fprintf(SUMA_STDOUT, "%s: Calculating convexity ...\n", FuncName); 00981 SO = (SUMA_SurfaceObject *)SUMAg_DOv[sv->Focus_SO_ID].OP; 00982 Cx = (float *)SUMA_GetCx(SO->idcode_str, SUMAg_CF->DsetList, 0); 00983 if (Cx) { 00984 fprintf(stderr,"Error %s: Cx must be null prior to new assignment\n", FuncName); 00985 break; 00986 } 00987 Cx = SUMA_Convexity (SO->NodeList, SO->N_Node, SO->NodeNormList, SO->FN); 00988 if (Cx == NULL) { 00989 fprintf(stderr,"Error %s: Failed in SUMA_Convexity\n", FuncName); 00990 break; 00991 } 00992 /* smooth estimate twice */ 00993 attr_sm = SUMA_SmoothAttr_Neighb (Cx, SO->N_Node, NULL, SO->FN, 1); 00994 if (attr_sm == NULL) { 00995 fprintf(stderr,"Error %s: Failed in SUMA_SmoothAttr_Neighb\n", FuncName); 00996 break; 00997 } 00998 Cx = SUMA_SmoothAttr_Neighb (attr_sm, SO->N_Node, Cx, SO->FN, 1); 00999 if (attr_sm) SUMA_free(attr_sm); 01000 01001 fprintf(SUMA_STDOUT, "%s: Use SUMA_ScaleToMap to colorize Conv.txt and display it on surface.\n", FuncName); 01002 CM = SUMA_GetStandardMap (SUMA_CMAP_nGRAY20); 01003 if (CM == NULL) { 01004 fprintf (SUMA_STDERR,"Error %s: Could not get standard colormap.\n", FuncName); 01005 exit (1); 01006 } 01007 01008 /* get the options for creating the scaled color mapping */ 01009 OptScl = SUMA_ScaleToMapOptInit(); 01010 if (!OptScl) { 01011 fprintf (SUMA_STDERR,"Error %s: Could not get scaling option structure.\n", FuncName); 01012 exit (1); 01013 } 01014 01015 /* work the options a bit */ 01016 OptScl->ApplyClip = YUP; 01017 IntRange[0] = 5; IntRange[1] = 95; /* percentile clipping range*/ 01018 Vsort = SUMA_PercRange (Cx, NULL, SO->N_Node, IntRange, IntRange, NULL); 01019 OptScl->IntRange[0] = IntRange[0]; OptScl->IntRange[1] = IntRange[1]; 01020 01021 OptScl->BrightFact = 0.4; 01022 01023 /* map the values in SO->Cx to the colormap */ 01024 /* allocate space for the result */ 01025 SV = SUMA_Create_ColorScaledVect(SO->N_Node); 01026 if (!SV) { 01027 fprintf (SUMA_STDERR,"Error %s: Could not allocate for SV.\n", FuncName); 01028 exit(1); 01029 } 01030 01031 /* finally ! */ 01032 /*fprintf (SUMA_STDERR,"%s: 1st color in map %f %f %f\n", FuncName, CM->M[0][0], CM->M[0][1],CM->M[0][2]);*/ 01033 if (!SUMA_ScaleToMap (Cx, SO->N_Node, Vsort[0], Vsort[SO->N_Node-1], CM, OptScl, SV)) { 01034 fprintf (SUMA_STDERR,"Error %s: Failed in SUMA_ScaleToMap.\n", FuncName); 01035 exit(1); 01036 } 01037 01038 /* Now place SV in the color array */ 01039 glar_ColorList = SUMA_GetColorList (sv, SO->idcode_str); 01040 if (!glar_ColorList) { 01041 fprintf (SUMA_STDERR,"Error %s: NULL glar_ColorList. BAD.\n", FuncName); 01042 break; 01043 } 01044 SUMA_RGBvec_2_GLCOLAR4(SV->cV, glar_ColorList, SO->N_Node); 01045 01046 /* free */ 01047 if (Vsort) SUMA_free(Vsort); 01048 if (CM) SUMA_Free_ColorMap (CM); 01049 if (OptScl) SUMA_free(OptScl); 01050 if (SV) SUMA_Free_ColorScaledVect (SV); 01051 if (Cx) { 01052 SUMA_free(Cx); 01053 Cx = NULL; 01054 } 01055 01056 fprintf(SUMA_STDOUT, "%s: Convexity mapping done ...\n", FuncName); 01057 SUMA_postRedisplay(w, clientData, callData); 01058 } 01059 break; 01060 case XK_comma: 01061 { 01062 /* switch state, back one */ 01063 int nxtstateID = -1, curstateID = -1; 01064 int origState = sv->iState; 01065 char *note=NULL; 01066 01067 if (sv->N_VSv < 2) break; 01068 01069 curstateID = SUMA_WhichState (sv->State, sv, sv->CurGroupName); 01070 if (curstateID < 0) { 01071 SUMA_SL_Err("Current State not found.\n" 01072 "Should not happen here."); 01073 SUMA_RETURNe; 01074 } 01075 01076 if (SUMAg_N_SVv > 1) { 01077 ii = SUMA_WhichViewerInMomentum (SUMAg_SVv, SUMAg_N_SVv, sv); 01078 if (ii >= 0) { 01079 sprintf (s, "You cannot switch states while other viewers\n" 01080 "(like %c) are in momentum mode.\n", ii+65); 01081 SUMA_RegisterMessage (SUMAg_CF->MessageList, 01082 s, FuncName, SMT_Error, SMA_LogAndPopup); 01083 SUMA_RETURNe; 01084 } 01085 } 01086 01087 do { 01088 if (nxtstateID > -1) { 01089 note = SUMA_append_string("Skipping state ",sv->State); 01090 note = SUMA_append_replace_string(note, ".\nNo surfaces visible.", "", 1); 01091 SUMA_SLP_Note(note); 01092 SUMA_free(note); note = NULL; 01093 } 01094 01095 /*fprintf(SUMA_STDERR,"%s: Current viewing state is %s ...\n", FuncName, sv->State);*/ 01096 /* toggle to the next view state */ 01097 nxtstateID = SUMA_PrevState(sv); 01098 if (nxtstateID == curstateID) break; 01099 if (nxtstateID < 0) { 01100 fprintf(SUMA_STDERR,"Error %s: Failed in SUMA_PrevState.\n", FuncName); 01101 break; 01102 } 01103 fprintf(SUMA_STDERR,"%s: Switching from %s to %s viewing state.\n", \ 01104 FuncName, sv->State, sv->VSv[nxtstateID].Name); 01105 01106 if (!SUMA_SwitchState (SUMAg_DOv, SUMAg_N_DOv, sv, nxtstateID, sv->CurGroupName)) { 01107 fprintf(SUMA_STDERR,"Error %s: Failed in SUMA_SwitchState.\n", FuncName); 01108 break; 01109 } 01110 01111 /* find out if there are any surfaces that will be rendered */ 01112 01113 } while (!SUMA_VisibleSOs (sv, SUMAg_DOv, NULL) && sv->iState != origState); 01114 01115 /* register a call to redisplay (you also need to copy the color data, in case the next surface is of the same family*/ 01116 if (!list) list = SUMA_CreateList(); 01117 SUMA_REGISTER_HEAD_COMMAND_NO_DATA(list, SE_Redisplay, SES_Suma, sv); 01118 if (!SUMA_Engine (&list)) { 01119 fprintf(stderr, "Error %s: SUMA_Engine call failed.\n", FuncName); 01120 } 01121 01122 /* update titles */ 01123 SUMA_UpdateViewerTitle(sv); 01124 } 01125 break; 01126 01127 case XK_period: 01128 { 01129 /* switch state, forward one */ 01130 int nxtstateID=-1, curstateID = -1; 01131 int origState = sv->iState; 01132 char *note=NULL; 01133 01134 if (sv->N_VSv < 2) break; 01135 01136 curstateID = SUMA_WhichState (sv->State, sv, sv->CurGroupName); 01137 if (curstateID < 0) { 01138 SUMA_SL_Err("Current State not found.\n" 01139 "Should not happen here."); 01140 SUMA_RETURNe; 01141 } 01142 01143 if (SUMAg_N_SVv > 1) { 01144 ii = SUMA_WhichViewerInMomentum (SUMAg_SVv, SUMAg_N_SVv, sv); 01145 if (ii >= 0) { 01146 sprintf (s, "You cannot switch states while other viewers\n" 01147 "(like %c) are in momentum mode.\n", ii+65); 01148 SUMA_RegisterMessage (SUMAg_CF->MessageList, 01149 s, FuncName, SMT_Error, SMA_LogAndPopup); 01150 SUMA_RETURNe; 01151 } 01152 } 01153 01154 do { 01155 if (nxtstateID > -1) { 01156 note = SUMA_append_string("Skipping state ",sv->State); 01157 note = SUMA_append_replace_string(note, ".\nNo surfaces visible.", "", 1); 01158 SUMA_SLP_Note(note); 01159 SUMA_free(note); note = NULL; 01160 } 01161 01162 if (LocalHead) fprintf(SUMA_STDERR,"%s: Current viewing state is %s ...\n", FuncName, sv->State); 01163 01164 /* toggle to the next view state */ 01165 nxtstateID = SUMA_NextState(sv); 01166 if (nxtstateID == curstateID) break; 01167 if (nxtstateID < 0) { 01168 fprintf(SUMA_STDERR,"Error %s: Failed in SUMA_NextState.\n", FuncName); 01169 break; 01170 } 01171 fprintf(SUMA_STDERR,"%s: Switching from %s to %s viewing state.\n", FuncName, sv->State, sv->VSv[nxtstateID].Name); 01172 01173 if (!SUMA_SwitchState (SUMAg_DOv, SUMAg_N_DOv, sv, nxtstateID, sv->CurGroupName)) { 01174 fprintf(SUMA_STDERR,"Error %s: Failed in SUMA_SwitchState.\n", FuncName); 01175 break; 01176 } 01177 01178 } while (!SUMA_VisibleSOs (sv, SUMAg_DOv, NULL) && sv->iState != origState); 01179 /* register a call to redisplay 01180 (you also need to copy the color data, in case the next surface is of the same family*/ 01181 if (!list) list = SUMA_CreateList(); 01182 SUMA_REGISTER_HEAD_COMMAND_NO_DATA(list, SE_Redisplay, SES_Suma, sv); 01183 if (!SUMA_Engine (&list)) { 01184 fprintf(stderr, "Error %s: SUMA_Engine call failed.\n", FuncName); 01185 } 01186 01187 /* update titles */ 01188 SUMA_UpdateViewerTitle(sv); 01189 } 01190 break; 01191 01192 case XK_F1: /* F1 */ 01193 /*printf("F1\n");*/ 01194 sv->ShowEyeAxis = !sv->ShowEyeAxis; 01195 SUMA_postRedisplay(w, clientData, callData); 01196 break; 01197 01198 case XK_F2: 01199 /*printf("F2\n");*/ 01200 { 01201 int *do_id, n_do_id; 01202 ++sv->ShowWorldAxis; sv->ShowWorldAxis = sv->ShowWorldAxis % SUMA_N_WAX_OPTIONS; 01203 sv->ShowMeshAxis = 0; /* used to be = !sv->ShowMeshAxis; , Turned off Oct 15 04 , in favor or WorldAxis */ 01204 do_id = SUMA_GetDO_Type(SUMAg_DOv, SUMAg_N_DOv, SO_type, &n_do_id); 01205 if (n_do_id) { 01206 while (n_do_id) { 01207 ((SUMA_SurfaceObject *)SUMAg_DOv[do_id[n_do_id-1]].OP)->ShowMeshAxis = sv->ShowMeshAxis; 01208 --n_do_id; 01209 } 01210 SUMA_free(do_id); 01211 } 01212 } 01213 SUMA_postRedisplay(w, clientData, callData); 01214 break; 01215 01216 case XK_F3: /* F3 */ 01217 if (!list) list = SUMA_CreateList(); 01218 SUMA_REGISTER_HEAD_COMMAND_NO_DATA(list, SE_ToggleCrossHair, SES_Suma, sv); 01219 SUMA_REGISTER_HEAD_COMMAND_NO_DATA(list, SE_Redisplay, SES_Suma, sv); 01220 if (!SUMA_Engine (&list)) { 01221 fprintf(stderr, "Error %s: SUMA_Engine call failed.\n", FuncName); 01222 } 01223 break; 01224 01225 case XK_F4: /* F4 */ 01226 if (!list) list = SUMA_CreateList(); 01227 SUMA_REGISTER_HEAD_COMMAND_NO_DATA(list, SE_ToggleShowSelectedNode, SES_Suma, sv); 01228 SUMA_REGISTER_HEAD_COMMAND_NO_DATA(list, SE_Redisplay, SES_Suma, sv); 01229 if (!SUMA_Engine (&list)) { 01230 fprintf(stderr, "Error %s: SUMA_Engine call failed.\n", FuncName); 01231 } 01232 break; 01233 01234 case XK_F5: /* F5 */ 01235 if (!list) list = SUMA_CreateList(); 01236 SUMA_REGISTER_HEAD_COMMAND_NO_DATA(list, SE_ToggleShowSelectedFaceSet, SES_Suma, sv); 01237 SUMA_REGISTER_HEAD_COMMAND_NO_DATA(list, SE_Redisplay, SES_Suma, sv); 01238 if (!SUMA_Engine (&list)) { 01239 fprintf(stderr, "Error %s: SUMA_Engine call failed.\n", FuncName); 01240 } 01241 break; 01242 01243 case XK_F6: /*F6 */ 01244 sv->clear_color[0] = 1 - sv->clear_color[0]; 01245 sv->clear_color[1] = 1 - sv->clear_color[1]; 01246 sv->clear_color[2] = 1 - sv->clear_color[2]; 01247 01248 if (!list) list = SUMA_CreateList(); 01249 SUMA_REGISTER_HEAD_COMMAND_NO_DATA(list, SE_Redisplay, SES_Suma, sv); 01250 if (!SUMA_Engine (&list)) { 01251 fprintf(stderr, "Error %s: SUMA_Engine call failed.\n", FuncName); 01252 } 01253 break; 01254 01255 case XK_F7: /*F7 */ 01256 ++SUMAg_CF->ColMixMode; 01257 if (SUMAg_CF->ColMixMode >= SUMA_MAX_MODES) { 01258 SUMAg_CF->ColMixMode = SUMA_ORIG_MIX_MODE; 01259 } 01260 { 01261 char stmp[200]; 01262 sprintf(stmp,"Using %s color mixing mode.", SUMA_ColMixModeString(SUMAg_CF->ColMixMode)); 01263 SUMA_SLP_Note(stmp); 01264 } 01265 01266 SUMA_SetAllRemixFlag (SUMAg_SVv, SUMAg_N_SVv); 01267 01268 if (!list) list = SUMA_CreateList(); 01269 SUMA_REGISTER_HEAD_COMMAND_NO_DATA(list, SE_Redisplay_AllVisible, SES_Suma, NULL); 01270 if (!SUMA_Engine (&list)) { 01271 fprintf(stderr, "Error %s: SUMA_Engine call failed.\n", FuncName); 01272 } 01273 break; 01274 01275 case XK_F8: /*F8 */ 01276 sv->ortho = !sv->ortho; 01277 01278 { 01279 char stmp[200]; 01280 if (sv->ortho) sprintf(stmp,"Using orthographic projection viewing"); 01281 else sprintf(stmp,"Using perspective viewing"); 01282 SUMA_SLP_Note(stmp); 01283 } 01284 01285 SUMA_SET_GL_PROJECTION(sv); 01286 SUMA_postRedisplay(w, clientData, callData); 01287 break; 01288 01289 case XK_F12: /* F12 */ 01290 /* time display speed */ 01291 { 01292 int i, nd = 20, N_vis, *Vis_IDs=NULL, NodeTot, FaceTot; 01293 GLfloat buf; 01294 float delta_t; 01295 SUMA_SurfaceObject *SO=NULL; 01296 struct timeval tti; 01297 char stmp[500]; 01298 SUMA_STRING *SS = NULL; 01299 01300 SS = SUMA_StringAppend (NULL, NULL); 01301 01302 buf = sv->light0_position[2]; 01303 SUMA_SLP_Note ("Timing Display speed\n" 01304 "(20 displays): \n"); 01305 SUMA_etime (&tti, 0); 01306 for (i=0; i< nd-1; ++i) { 01307 fprintf (SUMA_STDOUT,"%d\t", i); fflush (SUMA_STDOUT); 01308 sv->light0_position[2] *= -1; 01309 glLightfv(GL_LIGHT0, GL_POSITION, sv->light0_position); 01310 /* direct call to display */ 01311 SUMA_display(sv, SUMAg_DOv); 01312 /* wait for display */ 01313 glFinish(); 01314 } 01315 fprintf (SUMA_STDOUT,"\n"); 01316 delta_t = SUMA_etime (&tti, 1); 01317 sv->light0_position[2] = buf; 01318 glLightfv(GL_LIGHT0, GL_POSITION, sv->light0_position); 01319 SUMA_postRedisplay(w, clientData, callData); 01320 sprintf (stmp,"Elapsed time: %f seconds.\n%.2f displays/second.\n", delta_t, nd/delta_t); 01321 SS = SUMA_StringAppend (SS, stmp); 01322 01323 /* Estimate how many nodes and triangles were rendered */ 01324 Vis_IDs = (int *)SUMA_malloc(sizeof(int)*SUMAg_N_DOv); 01325 N_vis = SUMA_VisibleSOs (sv, SUMAg_DOv, Vis_IDs); 01326 NodeTot = 0; 01327 FaceTot = 0; 01328 for (i=0; i<N_vis;++i) { 01329 SO = (SUMA_SurfaceObject *)SUMAg_DOv[Vis_IDs[i]].OP; 01330 FaceTot += SO->N_FaceSet; 01331 NodeTot += SO->N_Node; 01332 } 01333 if (N_vis) { 01334 sprintf (stmp,"In Polymode %d, rendered \n%.2f Ktri/sec %.2f Kpnt/sec.\n", 01335 sv->PolyMode, 01336 (float)FaceTot / 1000.0 / delta_t , 01337 (float)NodeTot / 1000.0 / delta_t ); 01338 SS = SUMA_StringAppend (SS, stmp); 01339 } 01340 01341 SUMA_SLP_Note(SS->s); 01342 01343 if (Vis_IDs) SUMA_free(Vis_IDs); 01344 SUMA_free(SS->s); 01345 SUMA_free(SS); 01346 01347 } 01348 break; 01349 01350 case XK_Home: 01351 /*printf("HOME\n");*/ 01352 if (!list) list = SUMA_CreateList(); 01353 SUMA_REGISTER_HEAD_COMMAND_NO_DATA(list, SE_Home, SES_Suma, sv); 01354 SUMA_REGISTER_HEAD_COMMAND_NO_DATA(list, SE_FOVreset, SES_Suma, sv); 01355 SUMA_REGISTER_HEAD_COMMAND_NO_DATA(list, SE_Redisplay, SES_Suma, sv); 01356 if (!SUMA_Engine (&list)) { 01357 fprintf(stderr, "Error %s: SUMA_Engine call failed.\n", FuncName); 01358 } 01359 break; 01360 01361 case XK_Left: /*KEY_LEFT:*/ 01362 /*fprintf(stdout,"Left Key\n");*/ 01363 if ((Kev.state & ControlMask) && (Kev.state & ShiftMask)) { 01364 /* do nothing about ctrl+shift+this key */ 01365 }else if (Kev.state & ShiftMask) { 01366 /*fprintf (SUMA_STDERR,"%s: Shift down\n", FuncName);*/ 01367 sv->GVS[sv->StdView].translateVec[0] -= (GLfloat)sv->GVS[sv->StdView].ArrowtranslateDeltaX/(float)sv->WindWidth*sv->GVS[sv->StdView].TranslateGain; 01368 /*sv->GVS[sv->StdView].translateVec[1] -= 0;*/ 01369 SUMA_postRedisplay(w, clientData, callData); 01370 }else if (Kev.state & ControlMask){ 01371 float a[3], cQ[4], dQ[4]; 01372 /* From top view, rotate about x 90 degrees.*/ 01373 a[0] = 1.0; a[1] = 0.0; 01374 axis_to_quat(a, SUMA_PI/2.0, cQ); 01375 /* then rotate about y 90 degrees */ 01376 a[0] = 0.0; a[1] = 1.0; a[2] = 0.0; 01377 axis_to_quat(a, SUMA_PI/2.0, dQ); 01378 /*add and apply rotation*/ 01379 add_quats (dQ, cQ, sv->GVS[sv->StdView].currentQuat); 01380 SUMA_postRedisplay(w, clientData, callData); 01381 }else if (Kev.state & Mod1Mask || Kev.state & Mod2Mask) { 01382 /*ffprintf (SUMA_STDERR,"%s: alt down\n", FuncName);*/ 01383 }else { 01384 /*ffprintf (SUMA_STDERR,"%s: Vanilla kind.\n", FuncName);*/ 01385 trackball_Phi(sv->GVS[sv->StdView].deltaQuat, 01386 ArrowDeltaRot, 0.0, /* first point */ 01387 -ArrowDeltaRot, 0.0, /* ending x,y */ 01388 sv->ArrowRotationAngle); 01389 add_quats (sv->GVS[sv->StdView].deltaQuat, sv->GVS[sv->StdView].currentQuat, sv->GVS[sv->StdView].currentQuat); 01390 sv->GVS[sv->StdView].spinDeltaX = -2.0*ArrowDeltaRot*sv->WindWidth; 01391 sv->GVS[sv->StdView].spinDeltaY = 0; 01392 SUMA_postRedisplay(w, clientData, callData); 01393 } 01394 01395 break; 01396 01397 case XK_Right: /*KEY_RIGHT: */ 01398 /*printf("Right Key\n");*/ 01399 if ((Kev.state & ControlMask) && (Kev.state & ShiftMask)) { 01400 /* do nothing about ctrl+shift+this key */ 01401 }else if (Kev.state & ShiftMask) { 01402 /*fprintf (SUMA_STDERR,"%s: Shift down\n", FuncName);*/ 01403 sv->GVS[sv->StdView].translateVec[0] += (GLfloat)sv->GVS[sv->StdView].ArrowtranslateDeltaX/(float)sv->WindWidth*sv->GVS[sv->StdView].TranslateGain; 01404 /*sv->GVS[sv->StdView].translateVec[1] -= 0;*/ 01405 SUMA_postRedisplay(w, clientData, callData); 01406 }else if (Kev.state & ControlMask){ 01407 float a[3], cQ[4], dQ[4]; 01408 /* From top view, rotate about x 90 degrees */ 01409 a[0] = 1.0; a[1] = 0.0; a[2] = 0.0; 01410 axis_to_quat(a, SUMA_PI/2.0, cQ); 01411 /* then rotate about y -90 degrees */ 01412 a[0] = 0.0; a[1] = 1.0; 01413 axis_to_quat(a, -SUMA_PI/2.0, dQ); 01414 /*add and apply rotation*/ 01415 add_quats (dQ, cQ, sv->GVS[sv->StdView].currentQuat); 01416 SUMA_postRedisplay(w, clientData, callData); 01417 01418 }else if (Kev.state & Mod1Mask || Kev.state & Mod2Mask) { 01419 /*fprintf (SUMA_STDERR,"%s: alt down\n", FuncName);*/ 01420 }else { 01421 /*fprintf (SUMA_STDERR,"%s: Vanilla kind.\n", FuncName);*/ 01422 trackball_Phi(sv->GVS[sv->StdView].deltaQuat, 01423 -ArrowDeltaRot, 0.0, /* first point */ 01424 ArrowDeltaRot, 0.0, /* ending x,y */ 01425 sv->ArrowRotationAngle); 01426 add_quats (sv->GVS[sv->StdView].deltaQuat, sv->GVS[sv->StdView].currentQuat, sv->GVS[sv->StdView].currentQuat); 01427 sv->GVS[sv->StdView].spinDeltaX = 2.0*ArrowDeltaRot*sv->WindWidth; 01428 sv->GVS[sv->StdView].spinDeltaY = 0; 01429 SUMA_postRedisplay(w, clientData, callData); 01430 } 01431 break; 01432 01433 case XK_Down: /*KEY_DOWN*/ 01434 /*printf("Down Key\n");*/ 01435 if ((Kev.state & ControlMask) && (Kev.state & ShiftMask)) { 01436 float a[3], cQ[4], dQ[4]; 01437 /* Posterior view ctrl+shift+down*/ 01438 /* From top view, first rotate by 90 degrees about x axis */ 01439 a[0] = 1.0; a[1] = 0.0; a[2] = 0.0; 01440 axis_to_quat(a, SUMA_PI/2, cQ); 01441 /* then rotate by 180 degrees about y axis */ 01442 a[0] = 0.0; a[1] = 1.0; a[2] = 0.0; 01443 axis_to_quat(a, SUMA_PI, dQ); 01444 /*add rotation */ 01445 add_quats (dQ, cQ, sv->GVS[sv->StdView].currentQuat); 01446 SUMA_postRedisplay(w, clientData, callData); 01447 }else if (Kev.state & ShiftMask) { 01448 /*fprintf (SUMA_STDERR,"%s: Shift down\n", FuncName);*/ 01449 /*sv->GVS[sv->StdView].translateVec[0] += 0;*/ 01450 sv->GVS[sv->StdView].translateVec[1] -= (GLfloat)sv->GVS[sv->StdView].ArrowtranslateDeltaY/(float)sv->WindHeight*sv->GVS[sv->StdView].TranslateGain; 01451 SUMA_postRedisplay(w, clientData, callData); 01452 }else if (Kev.state & ControlMask){ 01453 /*fprintf (SUMA_STDERR,"%s: Control down\n", FuncName);*/ 01454 /* Inferior view ctrl+down*/ 01455 float a[3]; 01456 /* From top view, rotate by 180 degrees about y axis */ 01457 a[0] = 0.0; a[1] = 1.0; a[2] = 0.0; 01458 axis_to_quat(a, SUMA_PI, sv->GVS[sv->StdView].currentQuat); 01459 SUMA_postRedisplay(w, clientData, callData); 01460 }else if (Kev.state & Mod1Mask || Kev.state & Mod2Mask) { 01461 /*fprintf (SUMA_STDERR,"%s: alt down\n", FuncName);*/ 01462 }else { 01463 /*fprintf (SUMA_STDERR,"%s: Vanilla kind.\n", FuncName);*/ 01464 trackball_Phi(sv->GVS[sv->StdView].deltaQuat, 01465 0.0, ArrowDeltaRot, /* first point */ 01466 0.0, -ArrowDeltaRot, /* ending x,y */ 01467 sv->ArrowRotationAngle); 01468 /*fprintf(stdout,"\ncurrentQuat\n");for (i=0; i<4; ++i) { fprintf(stdout,"%f\t", sv->GVS[sv->StdView].currentQuat[i]);} fprintf(stdout,"\n"); 01469 fprintf(stdout,"\ndeltaQuat\n");for (i=0; i<4; ++i) { fprintf(stdout,"%f\t", sv->GVS[sv->StdView].deltaQuat[i]);} fprintf(stdout,"\n");*/ 01470 add_quats (sv->GVS[sv->StdView].deltaQuat, sv->GVS[sv->StdView].currentQuat, sv->GVS[sv->StdView].currentQuat); 01471 /*fprintf(stdout,"\nnewQuat\n");for (i=0; i<4; ++i) { fprintf(stdout,"%f\t", sv->GVS[sv->StdView].currentQuat[i]);} fprintf(stdout,"\n");*/ 01472 sv->GVS[sv->StdView].spinDeltaX = 0; 01473 sv->GVS[sv->StdView].spinDeltaY = -2.0*ArrowDeltaRot*sv->WindHeight; 01474 SUMA_postRedisplay(w, clientData, callData); 01475 } 01476 01477 break; 01478 01479 case XK_Up: /*KEY_UP*/ 01480 /*printf("Up Key\n");*/ 01481 if ((Kev.state & ControlMask) && (Kev.state & ShiftMask)) { 01482 float a[3]; 01483 /* Posterior view ctrl+shift+up*/ 01484 /* From top view, rotate by 90 degrees about x axis */ 01485 a[0] = 1.0; a[1] = 0.0; a[2] = 0.0; 01486 axis_to_quat(a, SUMA_PI/2, sv->GVS[sv->StdView].currentQuat); 01487 SUMA_postRedisplay(w, clientData, callData); 01488 }else if (Kev.state & ShiftMask) { 01489 /*fprintf (SUMA_STDERR,"%s: Shift down\n", FuncName);*/ 01490 sv->GVS[sv->StdView].translateVec[1] += (GLfloat)sv->GVS[sv->StdView].ArrowtranslateDeltaY/(float)sv->WindHeight*sv->GVS[sv->StdView].TranslateGain; 01491 SUMA_postRedisplay(w, clientData, callData); 01492 }else if (Kev.state & ControlMask){ 01493 /*fprintf (SUMA_STDERR,"%s: Control down\n", FuncName);*/ 01494 /* Top view ctrl+up*/ 01495 float a[3]; 01496 /* Default top view, rotate by nothing */ 01497 a[0] = 1.0; a[1] = 0.0; a[2] = 0.0; 01498 axis_to_quat(a, 0, sv->GVS[sv->StdView].currentQuat); 01499 SUMA_postRedisplay(w, clientData, callData); 01500 }else if (Kev.state & Mod1Mask || Kev.state & Mod2Mask) { 01501 /*fprintf (SUMA_STDERR,"%s: alt down\n", FuncName);*/ 01502 }else { 01503 if (LocalHead) fprintf (SUMA_STDERR,"%s: Vanilla kind.\n", FuncName); 01504 trackball_Phi(sv->GVS[sv->StdView].deltaQuat, 01505 0.0, -ArrowDeltaRot, /* first point */ 01506 0.0, ArrowDeltaRot, /* ending x,y */ 01507 sv->ArrowRotationAngle); 01508 if (LocalHead) { 01509 fprintf(stdout,"\ncurrentQuat\n"); 01510 for (ii=0; ii<4; ++ii) { 01511 fprintf(stdout,"%f\t", sv->GVS[sv->StdView].currentQuat[ii]); 01512 } 01513 fprintf(stdout,"\n"); 01514 fprintf(stdout,"\ndeltaQuat\n"); 01515 for (ii=0; ii<4; ++ii) { 01516 fprintf(stdout,"%f\t", sv->GVS[sv->StdView].deltaQuat[ii]); 01517 } 01518 fprintf(stdout,"\n"); 01519 } 01520 add_quats (sv->GVS[sv->StdView].deltaQuat, sv->GVS[sv->StdView].currentQuat, sv->GVS[sv->StdView].currentQuat); 01521 if (LocalHead) { 01522 fprintf(stdout,"\nnewQuat\n"); 01523 for (ii=0; ii<4; ++ii) { 01524 fprintf(stdout,"%f\t", sv->GVS[sv->StdView].currentQuat[ii]); 01525 } 01526 fprintf(stdout,"\n"); 01527 } 01528 sv->GVS[sv->StdView].spinDeltaX = 0; 01529 sv->GVS[sv->StdView].spinDeltaY = 2.0*ArrowDeltaRot*sv->WindHeight; 01530 SUMA_postRedisplay(w, clientData, callData); 01531 01532 } 01533 01534 break; 01535 01536 default: 01537 break; 01538 01539 } /* keysym */ 01540 break; 01541 01542 case ButtonPress: 01543 if (LocalHead) fprintf(stdout,"In ButtonPress\n"); 01544 pButton = Bev.button; 01545 if (SUMAg_CF->SwapButtons_1_3 || (SUMAg_CF->ROI_mode && SUMAg_CF->Pen_mode)) { 01546 if (pButton == Button1) pButton = Button3; 01547 else if (pButton == Button3) pButton = Button1; 01548 } 01549 01550 /* trap for double click */ 01551 if (Bev.time - B1time < SUMA_DOUBLE_CLICK_MAX_DELAY) { 01552 if (LocalHead) fprintf(SUMA_STDERR, "%s: Double click.\n", FuncName); 01553 DoubleClick = YUP; 01554 } else { 01555 DoubleClick = NOPE; 01556 } 01557 B1time = Bev.time; 01558 01559 switch (pButton) { /* switch type of button Press */ 01560 case Button1: 01561 if (Bev.state & Button2Mask) { 01562 /* setup initial zooming conditions */ 01563 /*fprintf(SUMA_STDERR,"%s: Button 1 &2 down. New\n", FuncName); */ 01564 sv->GVS[sv->StdView].zoomBegin = (float)Bev.y; 01565 sv->GVS[sv->StdView].zoomDelta = 0; 01566 }else { 01567 bevx=(float)Bev.x; bevy = (float)Bev.y; 01568 /*fprintf(SUMA_STDERR,"%s: Button 1 down. New\n", FuncName);*/ 01569 /* setup initial spinning conditions */ 01570 sv->GVS[sv->StdView].spinBeginX = bevx; 01571 sv->GVS[sv->StdView].spinBeginY = bevy; 01572 sv->GVS[sv->StdView].spinDeltaX = 0; 01573 sv->GVS[sv->StdView].spinDeltaY = 0; 01574 /* check to see if other viewers need to be notified */ 01575 ii = SUMA_WhichSV(sv, SUMAg_SVv, SUMAg_N_SVv); 01576 if (SUMAg_CF->ViewLocked[ii]) { 01577 for (it=0; it < SUMAg_N_SVv; ++it) { 01578 svi = &SUMAg_SVv[it]; 01579 if (it != ii && SUMAg_CF->ViewLocked[it]) { 01580 svi->GVS[svi->StdView].spinBeginX = bevx; 01581 svi->GVS[svi->StdView].spinBeginY = bevy; 01582 svi->GVS[svi->StdView].spinDeltaX = 0; 01583 svi->GVS[svi->StdView].spinDeltaY = 0; 01584 } 01585 } 01586 } 01587 } 01588 break; 01589 01590 case Button2: 01591 if (Bev.state & ShiftMask) { 01592 /* setup initial zooming conditions */ 01593 /*fprintf(SUMA_STDERR,"%s: Button 2 & Shift\n", FuncName); */ 01594 sv->GVS[sv->StdView].zoomBegin = (float)Bev.y; 01595 sv->GVS[sv->StdView].zoomDelta = 0; 01596 } else { 01597 /*fprintf(stdout,"Button 2 down, plain jane\n");*/ 01598 /* setup initial translation conditions */ 01599 bevx = (float)Bev.x; bevy = (float)Bev.y; 01600 sv->GVS[sv->StdView].translateBeginX = bevx;; 01601 sv->GVS[sv->StdView].translateBeginY = bevy; 01602 sv->GVS[sv->StdView].translateDeltaX = 0.0; 01603 sv->GVS[sv->StdView].translateDeltaY = 0.0; 01604 } 01605 break; 01606 01607 case Button3: 01608 if (LocalHead) fprintf(SUMA_STDERR,"%s: Button 3 downplain jane, viewer #%d : X=%f, Y = %f\n", \ 01609 FuncName, SUMA_WhichSV(sv, SUMAg_SVv, SUMAg_N_SVv), (float)Bev.x, (float)Bev.y); 01610 01611 #if 0 01612 /* are we in ROI drawing mode ? */ 01613 if (Bev.state & ShiftMask && SUMAg_CF->ROI_mode && sv->Focus_SO_ID >= 0) { 01614 /* ROI drawing mode */ 01615 ROI_mode = YUP; 01616 }else { 01617 ROI_mode = NOPE; 01618 } 01619 #endif 01620 /* are we in ROI drawing mode ? */ 01621 if (SUMAg_CF->ROI_mode && sv->Focus_SO_ID >= 0 && !(Bev.state & ShiftMask)) { 01622 /* ROI drawing mode */ 01623 ROI_mode = YUP; 01624 }else { 01625 ROI_mode = NOPE; 01626 } 01627 01628 if (!DoubleClick) { 01629 /* you do not want to waist time doing double calculations if the user clicks twice by mistake */ 01630 /* make sure no viewer, other than the one clicked in is in momentum mode */ 01631 if (SUMAg_N_SVv > 1) { 01632 ii = SUMA_WhichViewerInMomentum (SUMAg_SVv, SUMAg_N_SVv, NULL); 01633 if (ii >= 0) { 01634 sprintf (s, "You cannot select or draw while viewers\n" 01635 "(like %c) are in momentum mode.\n", ii+65); 01636 SUMA_RegisterMessage (SUMAg_CF->MessageList, 01637 s, FuncName, SMT_Error, SMA_LogAndPopup); 01638 SUMA_RETURNe; 01639 } 01640 } 01641 01642 01643 ii = SUMA_RegisteredSOs(sv, SUMAg_DOv, NULL); 01644 if (ii == 0) { /* no surfaces, break */ 01645 break; 01646 } 01647 01648 01649 if (!SUMA_GetSelectionLine (sv, (int)Bev.x, (int)Bev.y, sv->Pick0, sv->Pick1, 0, NULL, NULL, NULL)) { 01650 fprintf (SUMA_STDERR, "Error %s: Failed in SUMA_GetSelectionLine.\n", FuncName); 01651 break; 01652 } 01653 01654 01655 /* perform the intersection calcluation and mark the surface */ 01656 hit = SUMA_MarkLineSurfaceIntersect (sv, SUMAg_DOv); 01657 if (hit < 0) { 01658 fprintf(SUMA_STDERR,"Error %s: Failed in SUMA_MarkLineSurfaceIntersect.\n", FuncName); 01659 break; 01660 }else if (hit == 0) { /* nothing hit, get out */ 01661 break; 01662 } 01663 01664 01665 } 01666 01667 if (ROI_mode) { 01668 /* keep track of mouse motion in window */ 01669 if (!SUMA_CreateBrushStroke (sv)) { 01670 SUMA_RegisterMessage (SUMAg_CF->MessageList, 01671 "Failed to create BrushStroke.", FuncName, 01672 SMT_Error, SMA_LogAndPopup); 01673 SUMA_RETURNe; 01674 01675 } 01676 01677 SUMA_AddToBrushStroke (sv, (int)Bev.x, (int)Bev.y, sv->Pick0, 01678 sv->Pick1, YUP); 01679 } 01680 01681 01682 01683 /* redisplay */ 01684 sv->ResetGLStateVariables = YUP; 01685 SUMA_handleRedisplay((XtPointer)sv->X->GLXAREA); 01686 01687 01688 break; 01689 } /* switch type of button Press */ 01690 break; 01691 01692 case ButtonRelease: 01693 if (LocalHead) fprintf(SUMA_STDERR,"%s: In ButtonRelease\n", FuncName); 01694 rButton = Bev.button; 01695 if (SUMAg_CF->SwapButtons_1_3 || (SUMAg_CF->ROI_mode && SUMAg_CF->Pen_mode)) { 01696 if (rButton == Button1) rButton = Button3; 01697 else if (rButton == Button3) rButton = Button1; 01698 } 01699 switch (rButton) { /* switch type of button Press */ 01700 case Button3: 01701 if (LocalHead) fprintf(SUMA_STDERR,"%s: In ButtonRelease3\n", FuncName); 01702 if (SUMAg_CF->ROI_mode) { 01703 SUMA_DRAWN_ROI *DrawnROI = NULL; 01704 SUMA_SurfaceObject *SO = NULL; 01705 SUMA_BRUSH_STROKE_ACTION BsA=SUMA_BSA_Undefined; 01706 01707 if (sv->BS) { 01708 /* Process the brush stroke*/ 01709 if (DoubleClick) BsA = SUMA_BSA_JoinEnds; 01710 else BsA = SUMA_BSA_AppendStrokeOrFill; 01711 if (!(DrawnROI = SUMA_ProcessBrushStroke (sv, BsA))) { 01712 if (LocalHead) fprintf (SUMA_STDERR, "%s: NULL DrawnROI returned.\n", FuncName); 01713 SUMA_ClearBrushStroke (sv); 01714 break; 01715 } 01716 01717 /* Showme the DrawnROI */ 01718 if (LocalHead) SUMA_ShowDrawnROI (DrawnROI, NULL, NOPE); 01719 01720 /* do smething with the BrushStroke, then wipe it clean, OK to show even if empty*/ 01721 if (LocalHead) SUMA_ShowBrushStroke (sv, NULL); 01722 01723 /* SUMA_DrawBrushStroke (sv, YUP); */ 01724 SUMA_ClearBrushStroke (sv); 01725 01726 /* redisplay all others */ 01727 if (!list) list = SUMA_CreateList (); 01728 SUMA_REGISTER_TAIL_COMMAND_NO_DATA(list, SE_RedisplayNow_AllOtherVisible, SES_SumaWidget, sv); 01729 SUMA_Engine (&list); 01730 01731 /* redisplay . DO NOT REDISPLAY WITH SE_Redisplay_AllVisible or you will have GL state synchronization problems */ 01732 sv->ResetGLStateVariables = YUP; 01733 SUMA_handleRedisplay((XtPointer)sv->X->GLXAREA); 01734 01735 }/* if sv->BS */ 01736 } /* if SUMAg_CF->ROImode */ 01737 01738 break; 01739 } /* switch type of button Press */ 01740 break; 01741 01742 case MotionNotify: 01743 if (LocalHead) fprintf(stdout,"In MotionNotify\n"); 01744 if (SUMAg_CF->SwapButtons_1_3 || (SUMAg_CF->ROI_mode && SUMAg_CF->Pen_mode)) { 01745 if (((Mev.state & Button3MotionMask) && (Mev.state & Button2MotionMask)) || ((Mev.state & Button2MotionMask) && (Mev.state & ShiftMask))) { 01746 mButton = SUMA_Button_12_Motion; 01747 } else if(Mev.state & Button3MotionMask) { 01748 mButton = SUMA_Button_1_Motion; 01749 }else if(Mev.state & Button2MotionMask) { 01750 mButton = SUMA_Button_2_Motion; 01751 }else if(Mev.state & Button1MotionMask) { 01752 mButton = SUMA_Button_3_Motion; 01753 }else { 01754 break; 01755 } 01756 } else { 01757 if (((Mev.state & Button1MotionMask) && (Mev.state & Button2MotionMask)) || ((Mev.state & Button2MotionMask) && (Mev.state & ShiftMask))) { 01758 mButton = SUMA_Button_12_Motion; 01759 } else if(Mev.state & Button1MotionMask) { 01760 mButton = SUMA_Button_1_Motion; 01761 }else if(Mev.state & Button2MotionMask) { 01762 mButton = SUMA_Button_2_Motion; 01763 } else if(Mev.state & Button3MotionMask) { 01764 mButton = SUMA_Button_3_Motion; 01765 }else { 01766 break; 01767 } 01768 } 01769 01770 switch (mButton) { 01771 case SUMA_Button_12_Motion: 01772 case SUMA_Button_2_Shift_Motion: 01773 /*fprintf(SUMA_STDERR,"%s: In motion, Butt1 & Butt2\n", FuncName);*/ 01774 sv->GVS[sv->StdView].zoomDelta = 1.0 + (float)((int)Mev.y - sv->GVS[sv->StdView].zoomBegin)/MOUSE_ZOOM_FACT; 01775 if (sv->GVS[sv->StdView].zoomDelta > 2.0) sv->GVS[sv->StdView].zoomDelta = 2.0; 01776 else if (sv->GVS[sv->StdView].zoomDelta < 0.5) sv->GVS[sv->StdView].zoomDelta = 0.5; 01777 sv->FOV[sv->iState] /= sv->GVS[sv->StdView].zoomDelta; 01778 if (sv->FOV[sv->iState] < FOV_MIN) sv->FOV[sv->iState] = FOV_MIN; 01779 else if (sv->FOV[sv->iState] > FOV_MAX) sv->FOV[sv->iState] = FOV_MAX; 01780 sv->GVS[sv->StdView].zoomBegin = (float)(int)Mev.y; 01781 /*fprintf(stdout, "FOV zoom Delta = %f=n", sv->GVS[sv->StdView].zoomDelta);*/ 01782 /* Now update the zoom compensation variable */ 01783 if (sv->ZoomCompensate) { 01784 sv->ZoomCompensate = sv->FOV[sv->iState] / FOV_INITIAL; 01785 if (sv->ZoomCompensate > 1) sv->ZoomCompensate = 1.0; /* no need to compensate at low zooms */ 01786 else if (sv->ZoomCompensate < 0.005) sv->ZoomCompensate = 0.005; /* no need to go lower */ 01787 } 01788 ii = SUMA_WhichSV (sv, SUMAg_SVv, SUMAg_N_SVv); 01789 SUMA_postRedisplay(w, clientData, callData); 01790 break; 01791 01792 case SUMA_Button_1_Motion: 01793 /*fprintf(SUMA_STDERR,"%s: In motion, Butt1 \n", FuncName); */ 01794 mevx = (float)Mev.x; 01795 mevy = (float)Mev.y; 01796 wwid = (float)sv->WindWidth; 01797 whei = (float)sv->WindHeight; 01798 /* spinning mode */ 01799 if (sv->ZoomCompensate) { 01800 zc_fac = sv->ZoomCompensate; 01801 }else { 01802 zc_fac = 1.0; 01803 } 01804 sv->GVS[sv->StdView].spinDeltaX = (mevx - sv->GVS[sv->StdView].spinBeginX); 01805 sv->GVS[sv->StdView].spinDeltaY = (mevy - sv->GVS[sv->StdView].spinBeginY); 01806 01807 /* fprintf(stdout,"\n" 01808 "spinBeginX %f \n" 01809 "spinBeginY %f \n" 01810 "spinDeltaX %f \n" 01811 "spinDeltaY %f \n" 01812 "WindWidth %d \n" 01813 "WindHeight %d\n" 01814 "ZoomCompensate %f\n", 01815 sv->GVS[sv->StdView].spinBeginX, sv->GVS[sv->StdView].spinBeginY, 01816 sv->GVS[sv->StdView].spinDeltaX, sv->GVS[sv->StdView].spinDeltaY, 01817 sv->WindWidth, sv->WindHeight, sv->ZoomCompensate); */ 01818 if (sv->GVS[sv->StdView].spinDeltaX || sv->GVS[sv->StdView].spinDeltaY){ 01819 trackball( sv->GVS[sv->StdView].deltaQuat, 01820 (2*sv->GVS[sv->StdView].spinBeginX - wwid)/wwid*zc_fac, 01821 (whei - 2*sv->GVS[sv->StdView].spinBeginY)/whei*zc_fac, 01822 (2*mevx - wwid)/wwid*zc_fac, 01823 (whei - 2*mevy)/whei*zc_fac); /* comput the increment Quat */ 01824 sv->GVS[sv->StdView].spinBeginX = mevx; 01825 sv->GVS[sv->StdView].spinBeginY = mevy; 01826 add_quats (sv->GVS[sv->StdView].deltaQuat, sv->GVS[sv->StdView].currentQuat, sv->GVS[sv->StdView].currentQuat); 01827 01828 ii = SUMA_WhichSV(sv, SUMAg_SVv, SUMAg_N_SVv); 01829 if (ii < 0) { 01830 fprintf (SUMA_STDERR,"Error %s: Failed to find index of sv.\n", FuncName); 01831 break; 01832 } 01833 if (!SUMAg_CF->ViewLocked[ii]) { /* No locking, just redisplay current viewer */ 01834 SUMA_postRedisplay(w, clientData, callData); 01835 } else { /* locking, update and redisplay those locked */ 01836 DList *list = NULL; 01837 SUMA_EngineData *ED = NULL; 01838 SUMA_STANDARD_VIEWS ed_sv, ed_svi; 01839 /* redisplay current viewer immediately */ 01840 list = SUMA_CreateList (); 01841 ED = SUMA_InitializeEngineListData (SE_RedisplayNow); 01842 SUMA_RegisterEngineListCommand (list, ED, 01843 SEF_Empty, NULL, 01844 SES_Suma, (void *)sv, NOPE, 01845 SEI_Head, NULL); 01846 ed_sv = SUMA_BestStandardView(sv, SUMAg_DOv, SUMAg_N_DOv); 01847 for (it=0; it < SUMAg_N_SVv; ++it) { 01848 svi = &SUMAg_SVv[it]; 01849 ed_svi = SUMA_BestStandardView(svi, SUMAg_DOv, SUMAg_N_DOv); 01850 if (it != ii && SUMAg_CF->ViewLocked[it] && ed_svi == ed_sv) { 01851 /* copy quaternions */ 01852 svi->GVS[svi->StdView].spinBeginX = sv->GVS[sv->StdView].spinBeginX; 01853 svi->GVS[svi->StdView].spinBeginY = sv->GVS[sv->StdView].spinBeginY; 01854 SUMA_COPY_VEC(sv->GVS[sv->StdView].deltaQuat, svi->GVS[svi->StdView].deltaQuat, 4, float, float); 01855 SUMA_COPY_VEC(sv->GVS[sv->StdView].currentQuat, svi->GVS[svi->StdView].currentQuat, 4, float, float); 01856 01857 /* add a redisplay now */ 01858 ED = SUMA_InitializeEngineListData (SE_RedisplayNow); 01859 SUMA_RegisterEngineListCommand ( list, ED, 01860 SEF_Empty, NULL, 01861 SES_Suma, (void *)svi, NOPE, 01862 SEI_Head, NULL); 01863 } 01864 } 01865 if (!SUMA_Engine (&list)) { 01866 fprintf (SUMA_STDERR, "Error %s: Failed calling SUMA_Engine.\n", FuncName); 01867 break; 01868 } 01869 } 01870 } 01871 01872 break; 01873 01874 case SUMA_Button_2_Motion: 01875 /* fprintf(SUMA_STDERR,"%s: In motion, Butt2 \n", FuncName);*/ 01876 mevx = (float)Mev.x; mevy = (float)Mev.y; 01877 if (sv->ZoomCompensate) { 01878 zc_fac = sv->ZoomCompensate; 01879 }else { 01880 zc_fac = 1.0; 01881 } 01882 sv->GVS[sv->StdView].translateDeltaX = (mevx - sv->GVS[sv->StdView].translateBeginX)/(float)sv->WindWidth*sv->GVS[sv->StdView].TranslateGain; 01883 sv->GVS[sv->StdView].translateDeltaY = -(mevy - sv->GVS[sv->StdView].translateBeginY)/(float)sv->WindHeight*sv->GVS[sv->StdView].TranslateGain; 01884 01885 if (sv->GVS[sv->StdView].translateDeltaX || sv->GVS[sv->StdView].translateDeltaY){ 01886 sv->GVS[sv->StdView].translateVec[0] += (GLfloat)sv->GVS[sv->StdView].translateDeltaX * zc_fac; 01887 sv->GVS[sv->StdView].translateVec[1] += (GLfloat)sv->GVS[sv->StdView].translateDeltaY * zc_fac; 01888 sv->GVS[sv->StdView].translateBeginX = mevx; 01889 sv->GVS[sv->StdView].translateBeginY = mevy; 01890 SUMA_postRedisplay(w, clientData, callData); 01891 } 01892 break; 01893 01894 case SUMA_Button_3_Motion: 01895 if (LocalHead) fprintf(SUMA_STDERR,"%s: In motion, Butt3 \n", FuncName); 01896 01897 if (SUMAg_CF->ROI_mode && sv->Focus_SO_ID >= 0 && sv->BS) { 01898 /* ROI drawing mode */ 01899 ii = SUMA_RegisteredSOs(sv, SUMAg_DOv, NULL); 01900 if (ii == 0) { /* no surfaces, break */ 01901 break; 01902 } 01903 01904 01905 if (!SUMA_GetSelectionLine (sv, (int)Mev.x, (int)Mev.y, sv->Pick0, sv->Pick1, 0, NULL, NULL, NULL)) { 01906 fprintf (SUMA_STDERR, "Error %s: Failed in " 01907 "SUMA_GetSelectionLine.\n", FuncName); 01908 break; 01909 } 01910 01911 if (!SUMA_AddToBrushStroke (sv, (int)Mev.x, (int)Mev.y, 01912 sv->Pick0, sv->Pick1, YUP)) { 01913 SUMA_RegisterMessage (SUMAg_CF->MessageList, 01914 "Failed to add to BrushStroke.", 01915 FuncName, 01916 SMT_Error, SMA_LogAndPopup); 01917 break; 01918 } 01919 } 01920 01921 break; 01922 } 01923 01924 01925 break; 01926 }/* switch event type */ 01927 01928 SUMA_RETURNe; 01929 } |
|
changes the selected faceset (Focus FaceSet)
Definition at line 4034 of file SUMA_input.c. References SUMA_X::GLXAREA, LocalHead, SUMA_SurfaceViewer::ResetGLStateVariables, SE_SetSelectedFaceSet, SEF_i, SEI_Head, SES_Suma, SUMA_Boolean, SUMA_CreateList(), SUMA_Engine(), SUMA_ENTRY, SUMA_handleRedisplay(), SUMA_InitializeEngineListData(), SUMA_RegisterEngineListCommand(), SUMA_RETURNe, SUMA_StringToNum(), SUMA_X::TOPLEVEL, and SUMA_SurfaceViewer::X. Referenced by SUMA_input(), and SUMA_TriInput().
04035 { 04036 static char FuncName[]={"SUMA_JumpFocusFace"}; 04037 DList *list=NULL; 04038 SUMA_EngineData *ED = NULL; 04039 SUMA_SurfaceViewer *sv = NULL; 04040 float fv3[3]; 04041 int it; 04042 SUMA_Boolean LocalHead = NOPE; 04043 04044 SUMA_ENTRY; 04045 04046 if (!s) SUMA_RETURNe; 04047 04048 sv = (SUMA_SurfaceViewer *)data; 04049 04050 /* parse s */ 04051 if (SUMA_StringToNum (s, fv3, 1) != 1) { /* problem, beep and ignore */ 04052 XBell (XtDisplay (sv->X->TOPLEVEL), 50); 04053 SUMA_RETURNe; 04054 } 04055 04056 04057 04058 /* Set the Faceselection */ 04059 it = (int) fv3[0]; 04060 if (!list) list = SUMA_CreateList (); 04061 ED = SUMA_InitializeEngineListData (SE_SetSelectedFaceSet); 04062 if (!SUMA_RegisterEngineListCommand ( list, ED, 04063 SEF_i, (void*)&it, 04064 SES_Suma, (void *)sv, NOPE, 04065 SEI_Head, NULL)) { 04066 fprintf(SUMA_STDERR,"Error %s: Failed to register element\n", FuncName); 04067 SUMA_RETURNe; 04068 } 04069 04070 /* call with the list */ 04071 if (!SUMA_Engine (&list)) { 04072 fprintf(stderr, "Error %s: SUMA_Engine call failed.\n", FuncName); 04073 SUMA_RETURNe; 04074 } 04075 04076 /* redisplay curent only*/ 04077 sv->ResetGLStateVariables = YUP; 04078 SUMA_handleRedisplay((XtPointer)sv->X->GLXAREA); 04079 04080 SUMA_RETURNe; 04081 04082 } |
|
Changes the focus node without moving the cross hair.
Definition at line 3979 of file SUMA_input.c. References SUMA_X::GLXAREA, LocalHead, SUMA_SurfaceViewer::ResetGLStateVariables, SE_SetSelectedNode, SEF_i, SEI_Head, SES_Suma, SUMA_Boolean, SUMA_CreateList(), SUMA_Engine(), SUMA_ENTRY, SUMA_handleRedisplay(), SUMA_InitializeEngineListData(), SUMA_RegisterEngineListCommand(), SUMA_RETURNe, SUMA_SLP_Err, SUMA_StringToNum(), SUMA_X::TOPLEVEL, and SUMA_SurfaceViewer::X. Referenced by SUMA_input().
03980 { 03981 static char FuncName[]={"SUMA_JumpFocusNode"}; 03982 DList *list=NULL; 03983 SUMA_EngineData *ED = NULL; 03984 SUMA_SurfaceViewer *sv = NULL; 03985 float fv3[3]; 03986 int it; 03987 SUMA_Boolean LocalHead = NOPE; 03988 03989 SUMA_ENTRY; 03990 03991 if (!s) SUMA_RETURNe; 03992 03993 sv = (SUMA_SurfaceViewer *)data; 03994 03995 /* parse s */ 03996 if (SUMA_StringToNum (s, fv3, 1) != 1) { /* problem, beep and ignore */ 03997 XBell (XtDisplay (sv->X->TOPLEVEL), 50); 03998 SUMA_RETURNe; 03999 } 04000 04001 04002 /* Set the Nodeselection */ 04003 it = (int) fv3[0]; 04004 if (!list) list = SUMA_CreateList (); 04005 ED = SUMA_InitializeEngineListData (SE_SetSelectedNode); 04006 if (!SUMA_RegisterEngineListCommand ( list, ED, 04007 SEF_i, (void*)(&it), 04008 SES_Suma, (void *)sv, NOPE, 04009 SEI_Head, NULL)) { 04010 SUMA_SLP_Err("Failed to register element"); 04011 SUMA_RETURNe; 04012 } 04013 04014 /* call with the list */ 04015 if (!SUMA_Engine (&list)) { 04016 fprintf(stderr, "Error %s: SUMA_Engine call failed.\n", FuncName); 04017 SUMA_RETURNe; 04018 } 04019 04020 /* redisplay curent only*/ 04021 sv->ResetGLStateVariables = YUP; 04022 SUMA_handleRedisplay((XtPointer)sv->X->GLXAREA); 04023 04024 SUMA_RETURNe; 04025 04026 } |
|
sends the cross hair to a certain node index
Definition at line 3790 of file SUMA_input.c. References SUMA_CommonFields::Connected_v, SUMA_SurfaceViewer::Focus_SO_ID, SUMA_X::GLXAREA, SUMA_SurfaceObject::idcode_str, SUMA_SurfaceViewer::LinkAfniCrossHair, LocalHead, SUMA_SurfaceObject::NodeList, SUMA_SurfaceViewer::ResetGLStateVariables, SE_BindCrossHair, SE_LockCrossHair, SE_SetAfniCrossHair, SE_SetCrossHair, SE_SetSelectedNode, SEF_fv3, SEF_i, SEF_iv3, SEI_Head, SEI_Tail, SES_Suma, SUMA_AFNI_STREAM_INDEX, SUMA_Boolean, SUMA_CreateList(), SUMA_Engine(), SUMA_ENTRY, SUMA_findSO_inDOv(), SUMA_handleRedisplay(), SUMA_InitializeEngineListData(), SUMA_REGISTER_TAIL_COMMAND_NO_DATA, SUMA_RegisterEngineListCommand(), SUMA_RETURNe, SUMA_StringToNum(), SUMAg_N_DOv, SUMA_X::TOPLEVEL, and SUMA_SurfaceViewer::X. Referenced by SUMA_input(), SUMA_NodeInput(), and SUMA_RangeTableCell_EV().
03791 { 03792 static char FuncName[]={"SUMA_JumpIndex"}; 03793 DList *list=NULL; 03794 SUMA_EngineData *ED = NULL; 03795 SUMA_SurfaceViewer *sv = NULL; 03796 SUMA_SurfaceObject *SO= NULL; 03797 float fv3[3]; 03798 int it, iv3[3]; 03799 SUMA_Boolean LocalHead = NOPE; 03800 03801 SUMA_ENTRY; 03802 03803 if (!s) SUMA_RETURNe; 03804 03805 sv = (SUMA_SurfaceViewer *)data; 03806 03807 /* parse s */ 03808 if (SUMA_StringToNum (s, fv3, 1) != 1) { /* problem, beep and ignore */ 03809 XBell (XtDisplay (sv->X->TOPLEVEL), 50); 03810 SUMA_RETURNe; 03811 } 03812 03813 /* Set the Nodeselection */ 03814 it = (int) fv3[0]; 03815 if (!list) list = SUMA_CreateList (); 03816 ED = SUMA_InitializeEngineListData (SE_SetSelectedNode); 03817 if (!SUMA_RegisterEngineListCommand ( list, ED, 03818 SEF_i, (void*)(&it), 03819 SES_Suma, (void *)sv, NOPE, 03820 SEI_Head, NULL)) { 03821 fprintf(SUMA_STDERR,"Error %s: Failed to register element\n", FuncName); 03822 SUMA_RETURNe; 03823 } 03824 03825 03826 /* Now set the cross hair position at the selected node*/ 03827 SO = (SUMA_SurfaceObject *)SUMAg_DOv[sv->Focus_SO_ID].OP; 03828 ED = SUMA_InitializeEngineListData (SE_SetCrossHair); 03829 if (!SUMA_RegisterEngineListCommand ( list, ED, 03830 SEF_fv3, (void*)&(SO->NodeList[3*it]), 03831 SES_Suma, (void *)sv, NOPE, 03832 SEI_Head, NULL)) { 03833 fprintf(SUMA_STDERR,"Error %s: Failed to register element\n", FuncName); 03834 SUMA_RETURNe; 03835 } 03836 03837 /* attach the cross hair to the selected surface */ 03838 iv3[0] = SUMA_findSO_inDOv(SO->idcode_str, SUMAg_DOv, SUMAg_N_DOv); 03839 iv3[1] = it; 03840 ED = SUMA_InitializeEngineListData (SE_BindCrossHair); 03841 if (!SUMA_RegisterEngineListCommand ( list, ED, 03842 SEF_iv3, (void*)iv3, 03843 SES_Suma, (void *)sv, NOPE, 03844 SEI_Head, NULL)) { 03845 fprintf(SUMA_STDERR,"Error %s: Failed to register element\n", FuncName); 03846 SUMA_RETURNe; 03847 } 03848 03849 /* check to see if AFNI needs to be notified */ 03850 if (SUMAg_CF->Connected_v[SUMA_AFNI_STREAM_INDEX] && sv->LinkAfniCrossHair) { 03851 if (LocalHead) fprintf(SUMA_STDERR,"%s: Notifying Afni of CrossHair XYZ\n", FuncName); 03852 /* register a call to SetAfniCrossHair */ 03853 SUMA_REGISTER_TAIL_COMMAND_NO_DATA(list, SE_SetAfniCrossHair, SES_Suma, sv); 03854 } 03855 03856 /* call with the list */ 03857 if (!SUMA_Engine (&list)) { 03858 fprintf(stderr, "Error %s: SUMA_Engine call failed.\n", FuncName); 03859 SUMA_RETURNe; 03860 } 03861 03862 /* now put in a request for locking cross hair but you must do this after the node selection has been executed 03863 NOTE: You do not always have SetNodeElem because the list might get emptied in the call to AFNI notification. 03864 You should just put the next call at the end of the list.*/ 03865 if (!list) list = SUMA_CreateList(); 03866 ED = SUMA_InitializeEngineListData (SE_LockCrossHair); 03867 if (!SUMA_RegisterEngineListCommand ( list, ED, 03868 SEF_iv3, (void*)iv3, 03869 SES_Suma, (void *)sv, NOPE, 03870 SEI_Tail, NULL)) { 03871 fprintf(SUMA_STDERR,"Error %s: Failed to register element\n", FuncName); 03872 SUMA_RETURNe; 03873 } 03874 03875 /* call with the list */ 03876 if (!SUMA_Engine (&list)) { 03877 fprintf(stderr, "Error %s: SUMA_Engine call failed.\n", FuncName); 03878 SUMA_RETURNe; 03879 } 03880 03881 /* redisplay curent only*/ 03882 sv->ResetGLStateVariables = YUP; 03883 SUMA_handleRedisplay((XtPointer)sv->X->GLXAREA); 03884 03885 SUMA_RETURNe; 03886 03887 } |
|
sends the cross hair to a certain XYZ location.
Definition at line 3898 of file SUMA_input.c. References SUMA_CommonFields::Connected_v, SUMA_X::GLXAREA, SUMA_SurfaceViewer::LinkAfniCrossHair, LocalHead, SUMA_SurfaceViewer::ResetGLStateVariables, SE_LockCrossHair, SE_SetAfniCrossHair, SE_SetCrossHair, SEF_Empty, SEF_fv3, SEI_Head, SEI_Tail, SES_Suma, SUMA_AFNI_STREAM_INDEX, SUMA_Boolean, SUMA_CreateList(), SUMA_Engine(), SUMA_ENTRY, SUMA_handleRedisplay(), SUMA_InitializeEngineListData(), SUMA_REGISTER_TAIL_COMMAND_NO_DATA, SUMA_RegisterEngineListCommand(), SUMA_RETURNe, SUMA_SLP_Err, SUMA_StringToNum(), SUMA_X::TOPLEVEL, and SUMA_SurfaceViewer::X. Referenced by SUMA_input(), and SUMA_XhairInput().
03899 { 03900 static char FuncName[]={"SUMA_JumpXYZ"}; 03901 DList *list=NULL; 03902 SUMA_EngineData *ED = NULL; 03903 SUMA_SurfaceViewer *sv = NULL; 03904 float fv3[3]; 03905 SUMA_Boolean LocalHead = NOPE; 03906 03907 SUMA_ENTRY; 03908 03909 if (!s) SUMA_RETURNe; 03910 03911 sv = (SUMA_SurfaceViewer *)data; 03912 03913 /* parse s */ 03914 if (SUMA_StringToNum (s, fv3, 3) != 3) { /* problem, beep and ignore */ 03915 XBell (XtDisplay (sv->X->TOPLEVEL), 50); 03916 SUMA_RETURNe; 03917 } 03918 03919 /* Now set the cross hair position */ 03920 if (!list) list = SUMA_CreateList (); 03921 ED = SUMA_InitializeEngineListData (SE_SetCrossHair); 03922 if (!SUMA_RegisterEngineListCommand ( list, ED, 03923 SEF_fv3, (void*)fv3, 03924 SES_Suma, (void *)sv, NOPE, 03925 SEI_Head, NULL)) { 03926 fprintf(SUMA_STDERR,"Error %s: Failed to register element\n", FuncName); 03927 SUMA_RETURNe; 03928 } 03929 03930 /* check to see if AFNI needs to be notified */ 03931 if (SUMAg_CF->Connected_v[SUMA_AFNI_STREAM_INDEX] && sv->LinkAfniCrossHair) { 03932 if (LocalHead) fprintf(SUMA_STDERR,"%s: Notifying Afni of CrossHair XYZ\n", FuncName); 03933 /* register a call to SetAfniCrossHair */ 03934 SUMA_REGISTER_TAIL_COMMAND_NO_DATA(list, SE_SetAfniCrossHair, SES_Suma, sv); 03935 } 03936 03937 /* call with the list */ 03938 if (!SUMA_Engine (&list)) { 03939 fprintf(stderr, "Error %s: SUMA_Engine call failed.\n", FuncName); 03940 SUMA_RETURNe; 03941 } 03942 03943 /* now put in a request for locking cross hair but you must do this after the node selection has been executed 03944 NOTE: You do not always have SetNodeElem because the list might get emptied in the call to AFNI notification. 03945 You should just put the next call at the end of the list.*/ 03946 /* NOTE2: Only viewers that are XYZ locked will be affected */ 03947 if (!list) list = SUMA_CreateList(); 03948 ED = SUMA_InitializeEngineListData (SE_LockCrossHair); 03949 if (!SUMA_RegisterEngineListCommand ( list, ED, 03950 SEF_Empty, NULL, 03951 SES_Suma, (void *)sv, NOPE, 03952 SEI_Tail, NULL)) { 03953 SUMA_SLP_Err("Failed to register element"); 03954 SUMA_RETURNe; 03955 } 03956 03957 /* call with the list */ 03958 if (!SUMA_Engine (&list)) { 03959 fprintf(stderr, "Error %s: SUMA_Engine call failed.\n", FuncName); 03960 SUMA_RETURNe; 03961 } 03962 03963 03964 /* redisplay curent only*/ 03965 sv->ResetGLStateVariables = YUP; 03966 SUMA_handleRedisplay((XtPointer)sv->X->GLXAREA); 03967 03968 SUMA_RETURNe; 03969 } |
|
Function to link a node on the surface to the first node of a NodeStroke. -This function returns an ROI_datum that represents the link between the last node visited and the first node of the Nodestroke
Definition at line 3143 of file SUMA_input.c. References SUMA_SurfaceViewer::BS, DListElmt_::data, SUMA_SurfaceViewer::Focus_SO_ID, LocalHead, SUMA_BRUSH_STROKE_DATUM::NP, SUMA_Boolean, SUMA_BS_FIRST_SURF_NODE, SUMA_DRAWN_ROI_TAIL_NODE, SUMA_ENTRY, SUMA_RETURN, SUMA_SLP_Err, and SUMA_Surf_Plane_Intersect_ROI(). Referenced by SUMA_ProcessBrushStroke().
03144 { 03145 03146 static char FuncName[]={"SUMA_LinkTailNodeToNodeStroke"}; 03147 SUMA_ROI_DATUM *ROId=NULL; 03148 SUMA_SurfaceObject *SO=NULL; 03149 SUMA_Boolean LocalHead = NOPE; 03150 int Nfrom=-1, Nto=-1, Trito=-1; 03151 DListElmt *Elm=NULL; 03152 SUMA_BRUSH_STROKE_DATUM *bsd=NULL; 03153 03154 SUMA_ENTRY; 03155 03156 SO = (SUMA_SurfaceObject *)SUMAg_DOv[sv->Focus_SO_ID].OP; 03157 03158 /* get the equation of the plane fromed by TailNode, FirstNodeinBrushStroke and its NearPlanePoint */ 03159 SUMA_DRAWN_ROI_TAIL_NODE(DrawnROI, Nfrom); 03160 if (Nfrom < 0) { 03161 fprintf (SUMA_STDERR, "Error %s: No tail node found.\n", FuncName); 03162 SUMA_RETURN(NULL); 03163 } 03164 03165 /* get the first node in the stroke */ 03166 SUMA_BS_FIRST_SURF_NODE(sv->BS, Nto, Trito, Elm); 03167 if (Nto < 0 || !Elm) { 03168 SUMA_SLP_Err ("Failed in SUMA_BS_FIRST_SURF_NODE macro."); 03169 SUMA_RETURN(NULL); 03170 } 03171 bsd = (SUMA_BRUSH_STROKE_DATUM *)Elm->data; 03172 03173 /* Now compute the intersection of the surface with the plane */ 03174 ROId = SUMA_Surf_Plane_Intersect_ROI (SO, Nfrom, Nto, bsd->NP); 03175 03176 if (!ROId) { 03177 fprintf (SUMA_STDERR, "Error %s: Failed to link tail node to first node in new stroke. Repeat new stroke.\n", FuncName); 03178 SUMA_RETURN(NULL); 03179 } 03180 03181 SUMA_RETURN(ROId); 03182 } |
|
Function to link a node on the surface to a certain node in NodeStroke.
Definition at line 3107 of file SUMA_input.c. References DListElmt_::data, SUMA_SurfaceViewer::Focus_SO_ID, LocalHead, SUMA_BRUSH_STROKE_DATUM::NP, SUMA_Boolean, SUMA_ENTRY, SUMA_RETURN, SUMA_Surf_Plane_Intersect_ROI(), and SUMA_BRUSH_STROKE_DATUM::SurfNode. Referenced by SUMA_NodeStrokeToConnectedNodes().
03108 { 03109 static char FuncName[]={"SUMA_LinkThisNodeToNodeInStroke"}; 03110 SUMA_Boolean LocalHead = NOPE; 03111 SUMA_ROI_DATUM *ROId=NULL; 03112 SUMA_SurfaceObject *SO=NULL; 03113 int Nfrom, Nto; 03114 SUMA_BRUSH_STROKE_DATUM *bsd=NULL; 03115 03116 SUMA_ENTRY; 03117 03118 SO = (SUMA_SurfaceObject *)SUMAg_DOv[sv->Focus_SO_ID].OP; 03119 03120 Nfrom = NonSurf; 03121 bsd = (SUMA_BRUSH_STROKE_DATUM *)ELinStroke->data; 03122 Nto = bsd->SurfNode; 03123 03124 /* Now compute the intersection of the surface with the plane */ 03125 ROId = SUMA_Surf_Plane_Intersect_ROI (SO, Nfrom, Nto, bsd->NP); 03126 03127 if (!ROId) { 03128 fprintf (SUMA_STDERR, "Error %s: Failed to link tail node to first node in new stroke. Repeat new stroke.\n", FuncName); 03129 SUMA_RETURN(NULL); 03130 } 03131 03132 SUMA_RETURN(ROId); 03133 } |
|
rotates surface to face a certain coordinate
Definition at line 3746 of file SUMA_input.c. References LocalHead, SE_SetLookAt, SEF_fv3, SEI_Head, SES_Suma, SUMA_Boolean, SUMA_CreateList(), SUMA_Engine(), SUMA_ENTRY, SUMA_InitializeEngineListData(), SUMA_RegisterEngineListCommand(), SUMA_RETURNe, SUMA_StringToNum(), SUMA_X::TOPLEVEL, and SUMA_SurfaceViewer::X. Referenced by SUMA_input().
03747 { 03748 static char FuncName[]={"SUMA_LookAtCoordinates"}; 03749 DList *list=NULL; 03750 SUMA_EngineData *ED = NULL; 03751 SUMA_SurfaceViewer *sv = NULL; 03752 float fv3[3]; 03753 SUMA_Boolean LocalHead = NOPE; 03754 03755 SUMA_ENTRY; 03756 03757 if (!s) SUMA_RETURNe; 03758 03759 sv = (SUMA_SurfaceViewer *)data; 03760 03761 /* parse s */ 03762 if (SUMA_StringToNum (s, fv3, 3) != 3) { /* problem, beep and ignore */ 03763 XBell (XtDisplay (sv->X->TOPLEVEL), 50); 03764 SUMA_RETURNe; 03765 } 03766 03767 /* register fv3 with ED */ 03768 if (!list) list = SUMA_CreateList(); 03769 ED = SUMA_InitializeEngineListData (SE_SetLookAt); 03770 if (!SUMA_RegisterEngineListCommand ( list, ED, 03771 SEF_fv3, (void *)fv3, 03772 SES_Suma, (void *)sv, NOPE, 03773 SEI_Head, NULL )) { 03774 fprintf(SUMA_STDERR,"Error %s: Failed to register command\n", FuncName); 03775 SUMA_RETURNe; 03776 } 03777 if (!SUMA_Engine (&list)) { 03778 fprintf(stderr, "Error %s: SUMA_Engine call failed.\n", FuncName); 03779 } 03780 03781 SUMA_RETURNe; 03782 } |
|
Determines the intersection between ]sv->Pick0 sv->Pick1[ and SO Highlights the intersected faceset, node and updates cross hair location This used to be part of Button3's code in SUMA_input ans = SUMA_MarkLineSurfaceIntersect (sv, dov);
Definition at line 1991 of file SUMA_input.c. References SUMA_CommonFields::Connected_v, SUMA_SurfaceObject::FaceSetDim, SUMA_SurfaceObject::FaceSetList, SUMA_SurfaceViewer::Focus_SO_ID, SUMA_SurfaceObject::idcode_str, SUMA_MT_INTERSECT_TRIANGLE::ifacemin, SUMA_MT_INTERSECT_TRIANGLE::inodemin, SUMA_SurfaceObject::Label, SUMA_SurfaceViewer::LinkAfniCrossHair, LocalHead, SUMA_SurfaceObject::N_FaceSet, SUMA_MT_INTERSECT_TRIANGLE::N_hits, SUMA_SurfaceObject::N_Node, SUMA_SurfaceObject::NodeDim, SUMA_SurfaceObject::NodeList, SUMA_DO::OP, SUMA_MT_INTERSECT_TRIANGLE::P, SUMA_SurfaceViewer::Pick0, SUMA_SurfaceViewer::Pick1, SE_BindCrossHair, SE_LockCrossHair, SE_SetAfniCrossHair, SE_SetCrossHair, SE_SetSelectedFaceSet, SE_SetSelectedNode, SEF_fv3, SEF_i, SEF_iv3, SEI_Head, SEI_Tail, SES_Suma, SUMA_AFNI_STREAM_INDEX, SUMA_Boolean, SUMA_CreateList(), SUMA_Engine(), SUMA_ENTRY, SUMA_etime(), SUMA_findSO_inDOv(), SUMA_Free_MT_intersect_triangle(), SUMA_Init_SurfCont_SurfParam(), SUMA_InitializeEngineListData(), SUMA_MAX_COMMAND_LENGTH, SUMA_MAX_DISPLAYABLE_OBJECTS, SUMA_MT_intersect_triangle(), SUMA_REGISTER_TAIL_COMMAND_NO_DATA, SUMA_RegisterEngineListCommand(), SUMA_RETURN, SUMA_UpdateViewerTitle(), SUMA_VisibleSOs(), SUMAg_N_DOv, SUMA_SurfaceObject::SurfCont, SUMA_MT_INTERSECT_TRIANGLE::t, and SUMA_X_SurfCont::TopLevelShell. Referenced by SUMA_input().
01992 {/* determine intersection */ 01993 float P0f[3], P1f[3]; 01994 static char FuncName[]={"SUMA_MarkLineSurfaceIntersect"}; 01995 int NP; 01996 SUMA_MT_INTERSECT_TRIANGLE *MTI = NULL, *MTIi = NULL; 01997 float delta_t_tmp, dmin; 01998 struct timeval tt_tmp; 01999 int ip, it, id, iv3[3], ii, N_SOlist, SOlist[SUMA_MAX_DISPLAYABLE_OBJECTS], imin; 02000 char sfield[100], sdestination[100], CommString[SUMA_MAX_COMMAND_LENGTH]; 02001 SUMA_EngineData *ED = NULL; 02002 DList *list = NULL; 02003 DListElmt *SetNodeElem = NULL; 02004 SUMA_SurfaceObject *SO = NULL; 02005 SUMA_Boolean LocalHead = NOPE; 02006 02007 SUMA_ENTRY; 02008 02009 02010 P0f[0] = sv->Pick0[0]; 02011 P0f[1] = sv->Pick0[1]; 02012 P0f[2] = sv->Pick0[2]; 02013 P1f[0] = sv->Pick1[0]; 02014 P1f[1] = sv->Pick1[1]; 02015 P1f[2] = sv->Pick1[2]; 02016 02017 N_SOlist = SUMA_VisibleSOs(sv, dov, SOlist); 02018 imin = -1; 02019 dmin = 10000000.0; 02020 for (ii=0; ii < N_SOlist; ++ii) { /* find the closest intersection */ 02021 if (LocalHead) fprintf (SUMA_STDERR, "%s: working %d/%d shown surfaces ...\n", FuncName, ii, N_SOlist); 02022 SO = (SUMA_SurfaceObject *)dov[SOlist[ii]].OP; 02023 if (SO->FaceSetDim != 3) { 02024 fprintf(SUMA_STDERR,"Error %s: SUMA_MT_intersect_triangle only works for triangular meshes.\n", FuncName); 02025 } else { 02026 02027 SUMA_etime (&tt_tmp, 0); 02028 02029 MTIi = SUMA_MT_intersect_triangle(P0f, P1f, SO->NodeList, SO->N_Node, SO->FaceSetList, SO->N_FaceSet, NULL); 02030 02031 delta_t_tmp = SUMA_etime (&tt_tmp, 1); 02032 if (LocalHead) fprintf (SUMA_STDERR, "Local Debug %s: Intersection took %f seconds.\n", FuncName, delta_t_tmp); 02033 02034 if (MTIi == NULL) { 02035 fprintf(SUMA_STDERR,"Error %s: SUMA_MT_intersect_triangle failed.\n", FuncName); 02036 SUMA_RETURN (-1); 02037 } 02038 02039 if (MTIi->N_hits) { /* decide on the closest surface to the clicking point */ 02040 if (MTIi->t[MTIi->ifacemin] < dmin) { 02041 if (LocalHead) fprintf (SUMA_STDERR, "%s: A minimum for surface %d.\n", FuncName, ii); 02042 dmin = MTIi->t[MTIi->ifacemin]; 02043 imin = SOlist[ii]; 02044 MTI = MTIi; 02045 }else { 02046 /* not good, toss it away */ 02047 if (LocalHead) fprintf (SUMA_STDERR, "%s: ii=%d freeing MTIi...\n", FuncName, ii); 02048 MTIi = SUMA_Free_MT_intersect_triangle(MTIi); 02049 } 02050 }else { 02051 /* not good, toss it away */ 02052 if (LocalHead) fprintf (SUMA_STDERR, "%s: ii=%d freeing MTIi no hits...\n", FuncName, ii); 02053 MTIi = SUMA_Free_MT_intersect_triangle(MTIi); 02054 } 02055 } 02056 } 02057 02058 if (LocalHead) fprintf (SUMA_STDERR, "%s: Closest surface is indexed %d in DOv.\n", FuncName, imin); 02059 02060 /* Mark intersection Facsets */ 02061 if (imin >= 0) { 02062 sv->Focus_SO_ID = imin; 02063 SUMA_UpdateViewerTitle(sv); 02064 SO = (SUMA_SurfaceObject *)dov[imin].OP; 02065 NP = SO->FaceSetDim; 02066 ip = NP * MTI->ifacemin; 02067 02068 /* if the surface controller is open, update it */ 02069 if (SO->SurfCont->TopLevelShell) SUMA_Init_SurfCont_SurfParam(SO); 02070 02071 /* print nodes about the closets faceset*/ 02072 fprintf(SUMA_STDOUT, "\nvvvvvvvvvvvvvvvvvvvvvvvvvvvv\n"); 02073 fprintf(SUMA_STDOUT, "Selected surface %s (Focus_SO_ID # %d). FaceSet %d, Closest Node %d\n", 02074 SO->Label, sv->Focus_SO_ID, MTI->ifacemin, MTI->inodemin); 02075 fprintf(SUMA_STDOUT, "Nodes forming closest FaceSet:\n"); 02076 fprintf(SUMA_STDOUT, "%d, %d, %d\n", \ 02077 SO->FaceSetList[ip], SO->FaceSetList[ip+1],SO->FaceSetList[ip+2]); 02078 02079 fprintf (SUMA_STDOUT,"Coordinates of Nodes forming closest FaceSet:\n"); 02080 for (it=0; it < 3; ++it) { 02081 02082 id = SO->NodeDim * SO->FaceSetList[ip+it]; 02083 fprintf(SUMA_STDOUT, "%f, %f, %f\n", SO->NodeList[id],\ 02084 SO->NodeList[id+1],\ 02085 SO->NodeList[id+2]); 02086 } 02087 fprintf(SUMA_STDOUT, "\n^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n"); 02088 02089 /* Set the Nodeselection at the closest node */ 02090 it = MTI->inodemin; 02091 if (!list) list = SUMA_CreateList(); 02092 ED = SUMA_InitializeEngineListData (SE_SetSelectedNode); 02093 SetNodeElem = SUMA_RegisterEngineListCommand ( list, ED, 02094 SEF_i, (void*)&it, 02095 SES_Suma, (void *)sv, NOPE, 02096 SEI_Head, NULL); 02097 if (!SetNodeElem) { 02098 fprintf(SUMA_STDERR,"Error %s: Failed to register SetNodeElem\n", FuncName); 02099 SUMA_RETURN (-1); 02100 } 02101 02102 /* Set the FaceSetselection */ 02103 it = MTI->ifacemin; 02104 ED = SUMA_InitializeEngineListData (SE_SetSelectedFaceSet); 02105 if (!SUMA_RegisterEngineListCommand ( list, ED, 02106 SEF_i, (void*)&it, 02107 SES_Suma, (void *)sv, NOPE, 02108 SEI_Head, NULL)) { 02109 fprintf(SUMA_STDERR,"Error %s: Failed to register element\n", FuncName); 02110 SUMA_RETURN (-1); 02111 } 02112 02113 /* Now set the cross hair position at the intersection*/ 02114 ED = SUMA_InitializeEngineListData (SE_SetCrossHair); 02115 if (!SUMA_RegisterEngineListCommand ( list, ED, 02116 SEF_fv3, (void*)MTI->P, 02117 SES_Suma, (void *)sv, NOPE, 02118 SEI_Head, NULL)) { 02119 fprintf(SUMA_STDERR,"Error %s: Failed to register element\n", FuncName); 02120 SUMA_RETURN (-1); 02121 } 02122 02123 /* attach the cross hair to the selected surface */ 02124 iv3[0] = SUMA_findSO_inDOv(SO->idcode_str, SUMAg_DOv, SUMAg_N_DOv); 02125 iv3[1] = MTI->inodemin; 02126 ED = SUMA_InitializeEngineListData (SE_BindCrossHair); 02127 if (!SUMA_RegisterEngineListCommand ( list, ED, 02128 SEF_iv3, (void*)iv3, 02129 SES_Suma, (void *)sv, NOPE, 02130 SEI_Head, NULL)) { 02131 fprintf(SUMA_STDERR,"Error %s: Failed to register element\n", FuncName); 02132 SUMA_RETURN (-1); 02133 } 02134 02135 /* check to see if AFNI needs to be notified */ 02136 if (SUMAg_CF->Connected_v[SUMA_AFNI_STREAM_INDEX] && sv->LinkAfniCrossHair) { 02137 if (LocalHead) fprintf(SUMA_STDERR,"%s: Notifying Afni of CrossHair XYZ\n", FuncName); 02138 /* register a call to SetAfniCrossHair */ 02139 if (!list) list = SUMA_CreateList(); 02140 SUMA_REGISTER_TAIL_COMMAND_NO_DATA(list, SE_SetAfniCrossHair, SES_Suma, sv); 02141 if (!SUMA_Engine (&list)) { 02142 fprintf(SUMA_STDERR, "Error %s: SUMA_Engine call failed.\n", FuncName); 02143 SUMA_RETURN (-1); 02144 } 02145 }else { 02146 if (LocalHead) fprintf(SUMA_STDERR,"%s: No Notification to AFNI.\n", FuncName); 02147 } 02148 02149 /* now put in a request for locking cross hair but you must do this after the node selection has been executed 02150 NOTE: You do not always have SetNodeElem because the list might get emptied in the call to AFNI notification. 02151 You should just put the next call at the end of the list.*/ 02152 if (!list) list = SUMA_CreateList(); 02153 ED = SUMA_InitializeEngineListData (SE_LockCrossHair); 02154 if (!SUMA_RegisterEngineListCommand ( list, ED, 02155 SEF_iv3, (void*)iv3, 02156 SES_Suma, (void *)sv, NOPE, 02157 SEI_Tail, NULL)) { 02158 fprintf(SUMA_STDERR,"Error %s: Failed to register element\n", FuncName); 02159 SUMA_RETURN (-1); 02160 } 02161 02162 if (!SUMA_Engine (&list)) { 02163 fprintf(SUMA_STDERR, "Error %s: SUMA_Engine call failed.\n", FuncName); 02164 SUMA_RETURN (-1); 02165 } 02166 02167 02168 } 02169 /* clear MTI */ 02170 if (MTI) { 02171 MTI = SUMA_Free_MT_intersect_triangle(MTI); 02172 } 02173 02174 if (imin >= 0) { 02175 SUMA_RETURN (1); /* hit */ 02176 } else { 02177 SUMA_RETURN (0); /* no hit */ 02178 } 02179 }/* determine intersection */ |
|
SUMA_momentum(XtPointer clientData, XtIntervalId *id); client data contains the widget responsible for the call to SUMA_momentum Definition at line 1936 of file SUMA_input.c. References add_quats(), SUMA_X_AllView::App, SUMA_SurfaceViewer::GVS, SUMA_X::MOMENTUMID, SUMA_SurfaceViewer::StdView, SUMA_ANY_WIDGET2SV, SUMA_ENTRY, SUMA_momentum(), SUMA_postRedisplay(), SUMA_RETURNe, SUMA_CommonFields::X, and SUMA_SurfaceViewer::X. Referenced by SUMA_input(), and SUMA_momentum().
01937 { 01938 static char FuncName[]={"SUMA_momentum"}; 01939 static int ReDisp; 01940 Widget w; 01941 int isv; 01942 SUMA_SurfaceViewer *sv; 01943 01944 SUMA_ENTRY; 01945 01946 /* the widget is passed as client data */ 01947 w = (Widget)clientData; 01948 01949 /* find out which Surface viewer the widget belongs to */ 01950 SUMA_ANY_WIDGET2SV((Widget)clientData, sv, isv); 01951 if (isv < 0) { 01952 fprintf (SUMA_STDERR, "Error %s: Failed in macro SUMA_ANY_WIDGET2SV.\n", FuncName); 01953 SUMA_RETURNe; 01954 } 01955 01956 01957 ReDisp = 0; 01958 if ( ((sv->GVS[sv->StdView].spinDeltaX*sv->GVS[sv->StdView].spinDeltaX) > sv->GVS[sv->StdView].MinIdleDelta ) || ((sv->GVS[sv->StdView].spinDeltaY*sv->GVS[sv->StdView].spinDeltaY) > sv->GVS[sv->StdView].MinIdleDelta ) ) 01959 { /* rotate if SUMA_momentum is enabled and spinDeltaX or spinDeltaY are larger than the minimum set */ 01960 /*fprintf(stdout,"SUMA_momentum: spinDeltaX %f spinDeltaY %f\n", sv->GVS[sv->StdView].spinDeltaX, sv->GVS[sv->StdView].spinDeltaY);*/ 01961 add_quats (sv->GVS[sv->StdView].deltaQuat, sv->GVS[sv->StdView].currentQuat, sv->GVS[sv->StdView].currentQuat); 01962 ReDisp = 1; 01963 } 01964 if ( ((sv->GVS[sv->StdView].translateDeltaX*sv->GVS[sv->StdView].translateDeltaX) > sv->GVS[sv->StdView].MinIdleDelta ) || ((sv->GVS[sv->StdView].translateDeltaY*sv->GVS[sv->StdView].translateDeltaY) > sv->GVS[sv->StdView].MinIdleDelta ) ) 01965 { /* translate */ 01966 sv->GVS[sv->StdView].translateVec[0] += (GLfloat)sv->GVS[sv->StdView].translateDeltaX; 01967 sv->GVS[sv->StdView].translateVec[1] += (GLfloat)sv->GVS[sv->StdView].translateDeltaY; 01968 ReDisp = 1; 01969 } 01970 if (ReDisp) { 01971 /*fprintf(stdout,"Momentum Redisplay\n");*/ 01972 SUMA_postRedisplay(w, NULL, NULL); 01973 } 01974 sv->X->MOMENTUMID = XtAppAddTimeOut(SUMAg_CF->X->App, 1, SUMA_momentum, (XtPointer) w); 01975 01976 SUMA_RETURNe; 01977 } |
|
This function turns the NodeStroke into a datum of connected nodes Definition at line 3188 of file SUMA_input.c. References SUMA_SurfaceViewer::BS, DListElmt_::data, dlist_tail, SUMA_SurfaceObject::EL, SUMA_SurfaceViewer::Focus_SO_ID, i, LocalHead, SUMA_CommonFields::MessageList, SUMA_ROI_DATUM::N_n, SUMA_ROI_DATUM::N_t, SUMA_ROI_DATUM::nPath, SMA_LogAndPopup, SMT_Critical, SUMA_AllocROIDatum(), SUMA_AppendToROIdatum(), SUMA_Boolean, SUMA_BS_FIRST_SURF_NODE, SUMA_BS_NEXT_SURF_NODE, SUMA_calloc, SUMA_ENTRY, SUMA_FindEdge(), SUMA_FreeROIDatum(), SUMA_LinkThisNodeToNodeInStroke(), SUMA_realloc, SUMA_RegisterMessage(), SUMA_RETURN, SUMA_ROI_NodeSegment, SUMA_S_Note, SUMA_SLP_Err, SUMA_BRUSH_STROKE_DATUM::SurfNode, SUMA_ROI_DATUM::tPath, and SUMA_ROI_DATUM::Type. Referenced by SUMA_ProcessBrushStroke().
03189 { 03190 static char FuncName[]={"SUMA_NodeStrokeToConnectedNodes"}; 03191 SUMA_Boolean LocalHead = NOPE; 03192 SUMA_ROI_DATUM *ROId=NULL, *ROIlink = NULL; 03193 int i=0; 03194 SUMA_SurfaceObject *SO=NULL; 03195 DListElmt *Elmt = NULL, *oElmt = NULL; 03196 SUMA_BRUSH_STROKE_DATUM *bsd=NULL; 03197 03198 SUMA_ENTRY; 03199 03200 03201 ROId = SUMA_AllocROIDatum(); 03202 03203 /* fill up node series here */ 03204 ROId->N_n = 1; 03205 ROId->N_t = 1; 03206 ROId->nPath = (int *) SUMA_calloc (ROId->N_n, sizeof(int)); 03207 ROId->tPath = (int *) SUMA_calloc (ROId->N_t, sizeof(int)); 03208 03209 SUMA_BS_FIRST_SURF_NODE(sv->BS, ROId->nPath[0], ROId->tPath[0], Elmt); 03210 ROId->Type = SUMA_ROI_NodeSegment; 03211 03212 /* try filling up the rest */ 03213 SO = (SUMA_SurfaceObject *)SUMAg_DOv[sv->Focus_SO_ID].OP; 03214 oElmt = Elmt; 03215 do { 03216 /* get the next element with a surfnode */ 03217 SUMA_BS_NEXT_SURF_NODE(sv->BS, oElmt, Elmt); 03218 03219 if (!Elmt) { 03220 /* perhaps reached end of list without success */ 03221 SUMA_S_Note("Reached EOL without finding Elmt.\nNot necessarily a bad thing."); 03222 SUMA_RETURN(ROId); 03223 } else { 03224 if (LocalHead) { 03225 fprintf (SUMA_STDERR, "%s: Working with element %p.\n", FuncName, Elmt); 03226 } 03227 } 03228 bsd = (SUMA_BRUSH_STROKE_DATUM *)Elmt->data; 03229 if (LocalHead) fprintf (SUMA_STDERR, "%s: %d %d\nWill look for edge %d %d\n", 03230 FuncName, ROId->N_n, bsd->SurfNode, 03231 ROId->nPath[ROId->N_n-1], bsd->SurfNode); 03232 if (SUMA_FindEdge(SO->EL, ROId->nPath[ROId->N_n-1], bsd->SurfNode) < 0) { 03233 /* Not found, link nodes together*/ 03234 if (LocalHead) fprintf (SUMA_STDERR, "%s: Edge not found, linking together.\n", FuncName); 03235 if (!(ROIlink = SUMA_LinkThisNodeToNodeInStroke (sv, ROId->nPath[ROId->N_n-1], Elmt))) { 03236 SUMA_SLP_Err ("Failed to connect nodes in stroke."); 03237 SUMA_RETURN (ROId); 03238 } 03239 /* merge ROIlink with ROId */ 03240 if (LocalHead) fprintf (SUMA_STDERR, "%s: Merging ROIs together.\n", FuncName); 03241 if (!SUMA_AppendToROIdatum (ROIlink, ROId)) { 03242 SUMA_RegisterMessage (SUMAg_CF->MessageList, 03243 "Failed to merge ROIs.", FuncName, 03244 SMT_Critical, SMA_LogAndPopup); 03245 if (ROIlink) SUMA_FreeROIDatum((void *)ROIlink); ROIlink = NULL; 03246 SUMA_RETURN(ROId); 03247 } 03248 if (ROIlink) SUMA_FreeROIDatum((void *)ROIlink); ROIlink = NULL; 03249 }else { 03250 if (LocalHead) fprintf (SUMA_STDERR, "%s: Nodes connected.\n", FuncName); 03251 /* nodes are connected, just add to path */ 03252 ++ROId->N_n; 03253 ROId->nPath = (int *) SUMA_realloc (ROId->nPath, sizeof(int)*ROId->N_n); 03254 ROId->nPath[ROId->N_n-1] = bsd->SurfNode; 03255 } 03256 03257 oElmt = Elmt; 03258 } while (Elmt != dlist_tail(sv->BS)); 03259 03260 SUMA_RETURN (ROId); 03261 } |
|
Processes the brushstroke sent from a viewer.
Definition at line 2444 of file SUMA_input.c. References SUMA_ROI_DATUM::action, SUMA_DRAWN_ROI::ActionStack, SUMA_SurfaceViewer::BS, SUMA_X_DrawROI::curDrawnROI, DListElmt_::data, dlist_size, SUMA_ROI_ACTION_STRUCT::DrawnROI, SUMA_X_AllView::DrawROI, SUMA_DRAWN_ROI::DrawStatus, SUMA_SurfaceViewer::Focus_SO_ID, ft, SUMA_SurfaceObject::idcode_str, LocalHead, SUMA_CommonFields::MessageList, SUMA_ROI_DATUM::N_n, SUMA_SurfaceObject::N_Node, SUMA_BRUSH_STROKE_DATUM::NP, SUMA_ROI_DATUM::nPath, SUMA_CommonFields::ROI_FillMode, SUMA_CommonFields::ROI_mode, SUMA_ROI_ACTION_STRUCT::ROId, ROIdO_type, SUMA_X_DrawROI::ROIlbl, SUMA_DRAWN_ROI::ROIstrokelist, SUMA_X_DrawROI::ROIval, SMA_LogAndPopup, SMT_Critical, SMT_Error, SUMA_DRAWN_ROI::StackPos, SUMA_AddDO(), SUMA_AddFillROIDatum(), SUMA_AddToTailJunctionROIDatum(), SUMA_AddToTailROIDatum(), SUMA_AllocateDrawnROI(), SUMA_Boolean, SUMA_BRUSH_STROKE_ACTION, SUMA_BrushStrokeToNodeStroke(), SUMA_BS_COUNT_SURF_NODES, SUMA_BS_FIRST_SURF_NODE, SUMA_BSA_AppendStroke, SUMA_BSA_AppendStrokeOrFill, SUMA_BSA_FillArea, SUMA_BSA_JoinEnds, SUMA_Build_Mask_AllROI(), SUMA_Build_Mask_DrawnROI(), SUMA_calloc, SUMA_cb_DrawROI_SwitchROI(), SUMA_DestroyROIActionData(), SUMA_DRAWN_ROI_HEAD_NODE, SUMA_DRAWN_ROI_TAIL_NODE, SUMA_ENTRY, SUMA_FetchROI_InCreation(), SUMA_FillToMask(), SUMA_free, SUMA_FreeROIDatum(), SUMA_GET_TEXT_FIELD, SUMA_InitializeDrawROIWindow(), SUMA_IS_DRAW_ROI_SWITCH_ROI_SHADED, SUMA_isdROIrelated(), SUMA_LinkTailNodeToNodeStroke(), SUMA_LOCAL, SUMA_malloc, SUMA_NodeStrokeToConnectedNodes(), SUMA_Paint_SO_ROIplanes_w(), SUMA_PrependToROIdatum(), SUMA_PushActionStack(), SUMA_RegisterMessage(), SUMA_ReportDrawnROIDatumLength(), SUMA_RETURN, SUMA_ROI_ClosedPath, SUMA_ROI_FILL_TO_ALLROI, SUMA_ROI_FILL_TO_THISROI, SUMA_ROI_FilledArea, SUMA_ROI_Finished, SUMA_ROI_InCreation, SUMA_ROI_OpenPath, SUMA_ShowDrawnROIDatum(), SUMA_SL_Err, SUMA_SLP_Crit, SUMA_SLP_Err, SUMA_Surf_Plane_Intersect_ROI(), SUMAg_N_DOv, SW_DrawROI_WhatDistAll, SW_DrawROI_WhatDistTrace, SUMA_X_DrawROI::SwitchROIlst, SUMA_ARROW_TEXT_FIELD::textfield, SUMA_DRAWN_ROI::Type, SUMA_ARROW_TEXT_FIELD::value, SUMA_X_DrawROI::WhatDist, and SUMA_CommonFields::X. Referenced by SUMA_input().
02445 { 02446 static char FuncName[]={"SUMA_ProcessBrushStroke"}; 02447 SUMA_DRAWN_ROI *DrawnROI = NULL; 02448 SUMA_ROI_DATUM *ROIstroke = NULL, *ROIlink=NULL, *ROIfill=NULL; 02449 SUMA_SurfaceObject *SO = NULL; 02450 int ii=0, TailNode = -1, FirstSurfNode = -1, ft = -1, N_SurfNode = 0; 02451 int HeadNode = -1, *ROI_Mask=NULL, N_ROI_Mask = 0; 02452 DListElmt *El = NULL; 02453 SUMA_BRUSH_STROKE_DATUM *bsd=NULL; 02454 char *sbuf; 02455 SUMA_ROI_ACTION_STRUCT *ROIA; 02456 DListElmt *tmpStackPos=NULL; 02457 SUMA_Boolean Shaded = NOPE, LocalHead = NOPE; 02458 02459 02460 SO = (SUMA_SurfaceObject *)SUMAg_DOv[sv->Focus_SO_ID].OP; 02461 02462 SUMA_ENTRY; 02463 02464 if (!SO) { 02465 fprintf (SUMA_STDERR, "%s: No surface object in focus, nothing to do.\n", FuncName); 02466 SUMA_RETURN (DrawnROI); 02467 } 02468 02469 if (!sv->BS) { 02470 fprintf (SUMA_STDERR, "%s: No Brushstroke (BS), nothing to do.\n", FuncName); 02471 SUMA_RETURN (DrawnROI); 02472 } 02473 02474 if (!SUMAg_CF->ROI_mode) { 02475 fprintf (SUMA_STDERR, "%s: Not in ROI mode, nothing to do.\n", FuncName); 02476 SUMA_RETURN (DrawnROI); 02477 } 02478 02479 /* We are in ROI mode, is there an ROI in curDrawnROI that works with the current surface ? */ 02480 if (SUMAg_CF->X->DrawROI->curDrawnROI) { 02481 if (SUMA_isdROIrelated(SUMAg_CF->X->DrawROI->curDrawnROI, SO) && SUMAg_CF->X->DrawROI->curDrawnROI->DrawStatus != SUMA_ROI_Finished) { 02482 if (LocalHead) fprintf (SUMA_STDERR,"%s: using currDrawnROI.\n", FuncName); 02483 DrawnROI = SUMAg_CF->X->DrawROI->curDrawnROI; 02484 }else { 02485 if (LocalHead) fprintf (SUMA_STDERR,"%s: No match between currDrawnROI and SO.\n", FuncName); 02486 DrawnROI = NULL; 02487 } 02488 } 02489 if (!DrawnROI) { /* try some more */ 02490 if ((DrawnROI = SUMA_FetchROI_InCreation (SO, SUMAg_DOv, SUMAg_N_DOv))){ 02491 if (LocalHead) fprintf (SUMA_STDERR,"%s: using ROI in creation.\n", FuncName); 02492 /* There is an ROI being created on this surface, initialize DrawROI window*/ 02493 SUMA_InitializeDrawROIWindow(DrawnROI); 02494 } else { 02495 /* wait till later */ 02496 if (LocalHead) fprintf (SUMA_STDERR,"%s: will create a new ROI.\n", FuncName); 02497 } 02498 } 02499 02500 if (!DrawnROI && BsA == SUMA_BSA_JoinEnds) { 02501 SUMA_SLP_Err ("NO ROI to close."); 02502 SUMA_RETURN (DrawnROI); 02503 } 02504 02505 if (!DrawnROI) { /* No ROI found, create one */ 02506 if (LocalHead) fprintf (SUMA_STDERR, "%s: No ROI found, creating a new one.\n", FuncName); 02507 SUMA_GET_TEXT_FIELD(SUMAg_CF->X->DrawROI->ROIlbl->textfield, sbuf); 02508 DrawnROI = SUMA_AllocateDrawnROI (SO->idcode_str, SUMA_ROI_InCreation, SUMA_ROI_OpenPath, 02509 sbuf, 02510 SUMAg_CF->X->DrawROI->ROIval->value); 02511 if (!DrawnROI) { 02512 SUMA_RegisterMessage (SUMAg_CF->MessageList, 02513 "Failed to allocate for DrawnROI.", FuncName, 02514 SMT_Critical, SMA_LogAndPopup); 02515 SUMA_RETURN (NULL); 02516 } 02517 02518 /* Although ROIs are stored as DOs, they are dependent on the surfaces they are related to 02519 ROIs at this stage are node indices only (and perhaps the mesh) but the coordinates of the indices 02520 come from the surface onto which they are displayed. So when you are drawing a surface, using CreateMesh, 02521 you will search DOv for ROIs related to the surface displayed and overlay them accordingly */ 02522 /* Add the ROI to DO */ 02523 if (!SUMA_AddDO (SUMAg_DOv, &SUMAg_N_DOv, (void *)DrawnROI, ROIdO_type, SUMA_LOCAL)) { 02524 fprintf(SUMA_STDERR,"Error %s: Failed in SUMA_AddDO.\n", FuncName); 02525 } 02526 02527 /* is the Switch ROI window open ? */ 02528 SUMA_IS_DRAW_ROI_SWITCH_ROI_SHADED(Shaded); 02529 if (!Shaded) { 02530 SUMA_cb_DrawROI_SwitchROI (NULL, (XtPointer) SUMAg_CF->X->DrawROI->SwitchROIlst, NULL); 02531 } 02532 02533 02534 } else { 02535 if (LocalHead) fprintf(SUMA_STDOUT,"%s: ROI %p fetched. Status %d.\n", FuncName, DrawnROI, DrawnROI->DrawStatus); 02536 } 02537 02538 if (BsA == SUMA_BSA_AppendStrokeOrFill) { 02539 if (DrawnROI->Type == SUMA_ROI_ClosedPath || DrawnROI->Type == SUMA_ROI_FilledArea) BsA = SUMA_BSA_FillArea; 02540 else if (DrawnROI->Type == SUMA_ROI_OpenPath) BsA = SUMA_BSA_AppendStroke; 02541 } 02542 if (DrawnROI->Type == SUMA_ROI_ClosedPath && BsA != SUMA_BSA_FillArea) { 02543 SUMA_SLP_Err ("You can only fill a closed path.\nYou cannot append more paths to it."); 02544 SUMA_RETURN (DrawnROI); 02545 } 02546 if (DrawnROI->Type == SUMA_ROI_FilledArea && BsA != SUMA_BSA_FillArea) { 02547 SUMA_SLP_Err ("You cannot add paths to a filled ROI."); 02548 SUMA_RETURN (DrawnROI); 02549 } 02550 02551 /* Good, now initialize the DrawROI widget, if needed */ 02552 if (SUMAg_CF->X->DrawROI->curDrawnROI != DrawnROI) { 02553 if (!SUMA_InitializeDrawROIWindow (DrawnROI)) { 02554 SUMA_SL_Err("Failed to initialize DrawWindow."); 02555 } 02556 } 02557 02558 /* Now you must transform the brushstroke to a series of nodes (not necessarily connected)*/ 02559 if (LocalHead) fprintf (SUMA_STDERR, "%s: Turning BrushStroke to NodeStroke ...\n", FuncName); 02560 if (!SUMA_BrushStrokeToNodeStroke (sv)) { 02561 SUMA_RegisterMessage (SUMAg_CF->MessageList, 02562 "Failed in SUMA_BrushStrokeToNodeStroke.", FuncName, 02563 SMT_Error, SMA_LogAndPopup); 02564 SUMA_RETURN(NULL); 02565 } 02566 02567 switch (BsA) { 02568 case SUMA_BSA_AppendStroke: 02569 /* Turn the brush stroke into a series of connected nodes */ 02570 if (LocalHead) fprintf (SUMA_STDERR, "%s: Turning NodeStroke to ROIStroke ...\n", FuncName); 02571 if (!(ROIstroke = SUMA_NodeStrokeToConnectedNodes (sv))) { 02572 SUMA_RegisterMessage (SUMAg_CF->MessageList, 02573 "Failed in SUMA_NodeStrokeToConnectedNodes.", FuncName, 02574 SMT_Critical, SMA_LogAndPopup); 02575 if (ROIlink) SUMA_FreeROIDatum((void *)ROIlink); ROIlink = NULL; 02576 if (ROIstroke) SUMA_FreeROIDatum((void *)ROIstroke); ROIstroke = NULL; 02577 SUMA_RETURN(NULL); 02578 } 02579 02580 if (LocalHead) fprintf (SUMA_STDERR, "%s: Turning NodeStroke to ROIStroke . DONE.\n", FuncName); 02581 /* if this is the first element of ROI, create the first ROIdatum and get out */ 02582 if (dlist_size(DrawnROI->ROIstrokelist)) { 02583 /* Not the beginning of an ROI */ 02584 if (LocalHead) fprintf (SUMA_STDERR, "%s: Adding ROIstroke to previous ones ...\n", FuncName); 02585 /* make sure new brushstroke is not just one node that is the tail of the ROI*/ 02586 SUMA_DRAWN_ROI_TAIL_NODE(DrawnROI,TailNode); 02587 02588 SUMA_BS_FIRST_SURF_NODE(sv->BS, FirstSurfNode, ft, El); 02589 SUMA_BS_COUNT_SURF_NODES(sv->BS, N_SurfNode); 02590 if (FirstSurfNode == TailNode && N_SurfNode == 1) { 02591 /* nothing to do here */ 02592 fprintf (SUMA_STDERR, "%s: New stroke has one node that is identical to tail node. Dumping element.\n", FuncName); 02593 SUMA_RETURN(DrawnROI); 02594 } 02595 02596 /* Connect this chunk to the last open Node in ROI */ 02597 if (FirstSurfNode != TailNode) { 02598 if (LocalHead) fprintf (SUMA_STDERR, "%s: linking Tail Node to New stroke.\n", FuncName); 02599 02600 ROIlink = SUMA_LinkTailNodeToNodeStroke (sv, DrawnROI); 02601 if (!ROIlink) { 02602 SUMA_SL_Err("Failed to connect Tail node to Node stroke, try again."); 02603 SUMA_RETURN(NULL); 02604 } 02605 if (LocalHead) { 02606 fprintf (SUMA_STDERR, "%s: RIOlink, before prepending:\n", FuncName); 02607 SUMA_ShowDrawnROIDatum (ROIlink, NULL, NOPE); 02608 } 02609 02610 /* connect the ROIlink with the ROIstroke */ 02611 if (LocalHead) { 02612 fprintf (SUMA_STDERR, "%s: RIOstroke, before prepending:\n", FuncName); 02613 SUMA_ShowDrawnROIDatum (ROIstroke, NULL, NOPE); 02614 } 02615 if (!SUMA_PrependToROIdatum (ROIlink, ROIstroke)) { 02616 SUMA_RegisterMessage (SUMAg_CF->MessageList, 02617 "Failed to merge ROIs.", FuncName, 02618 SMT_Critical, SMA_LogAndPopup); 02619 if (ROIlink) SUMA_FreeROIDatum((void *)ROIlink); ROIlink = NULL; 02620 if (ROIstroke) SUMA_FreeROIDatum((void *)ROIstroke); ROIstroke = NULL; 02621 SUMA_RETURN(NULL); 02622 } 02623 02624 if (LocalHead) { 02625 fprintf (SUMA_STDERR, "%s: RIOstroke, after prepending:\n", FuncName); 02626 SUMA_ShowDrawnROIDatum (ROIstroke, NULL, NOPE); 02627 } 02628 /* now free ROIlink, not needed anymore */ 02629 if (ROIlink) SUMA_FreeROIDatum ((void *)ROIlink); ROIlink = NULL; 02630 } 02631 }else{ 02632 if (LocalHead) fprintf (SUMA_STDERR, "%s: First ROIStroke of ROI.\n", FuncName); 02633 } 02634 break; 02635 case SUMA_BSA_JoinEnds: 02636 /* Join ends here */ 02637 if (DrawnROI) { /* close ROI */ 02638 SUMA_DRAWN_ROI_HEAD_NODE(DrawnROI,HeadNode); 02639 SUMA_BS_FIRST_SURF_NODE(sv->BS, FirstSurfNode, ft, El); 02640 bsd = (SUMA_BRUSH_STROKE_DATUM *)El->data; 02641 if (LocalHead) fprintf(SUMA_STDERR, "%s: Trying to join node %d to node %d.\n", FuncName, FirstSurfNode, HeadNode); 02642 /* Now compute the intersection of the surface with the plane */ 02643 ROIstroke = SUMA_Surf_Plane_Intersect_ROI (SO, FirstSurfNode, HeadNode, bsd->NP); 02644 02645 if (!ROIstroke) { 02646 SUMA_SL_Err ("Failed to close path. Repeat new stroke."); 02647 SUMA_RETURN(DrawnROI); 02648 } 02649 /* what is the last node of ROIstroke ? 02650 It is possible that the returned ROIstroke 02651 was not a successful closure (a partial success), investigate*/ 02652 if (LocalHead) fprintf(SUMA_STDERR, "%s: Last node of ROIstroke is %d\n", FuncName, ROIstroke->nPath[ROIstroke->N_n-1]); 02653 if (ROIstroke->nPath[ROIstroke->N_n-1] != HeadNode) { 02654 /* pretend this is not a JoinEnds exercice */ 02655 BsA = SUMA_BSA_AppendStroke; 02656 SUMA_SL_Err ("Failed to close path. Continue with stroke."); 02657 SUMA_RETURN(DrawnROI); 02658 }else { 02659 /* Do not remove the last point from ROIstroke, otherwise it will make drawing a closed ROI painful */ 02660 } 02661 } else { 02662 /* tremors, nothing to do */ 02663 } 02664 break; 02665 case SUMA_BSA_FillArea: 02666 SUMA_BS_FIRST_SURF_NODE(sv->BS, FirstSurfNode, ft, El); 02667 if (LocalHead) fprintf (SUMA_STDERR, "%s: Should be filling from node %d\n", FuncName, FirstSurfNode); 02668 02669 /* create the mask from ROIs on this surface */ 02670 switch (SUMAg_CF->ROI_FillMode) { 02671 case SUMA_ROI_FILL_TO_ALLROI: 02672 ROI_Mask = SUMA_Build_Mask_AllROI (SUMAg_DOv, SUMAg_N_DOv, SO, NULL, &N_ROI_Mask); 02673 break; 02674 case SUMA_ROI_FILL_TO_THISROI: 02675 ROI_Mask = (int *)SUMA_calloc (SO->N_Node, sizeof(int)); 02676 if (!ROI_Mask) { 02677 SUMA_SLP_Crit("Failed to allocate"); 02678 SUMA_RETURN(DrawnROI); 02679 } 02680 SUMA_Build_Mask_DrawnROI (DrawnROI, ROI_Mask); 02681 break; 02682 default: 02683 SUMA_SLP_Err("No such mode."); 02684 SUMA_RETURN(DrawnROI); 02685 break; 02686 } 02687 02688 /* Now fill it up */ 02689 ROIfill = SUMA_FillToMask (SO, ROI_Mask, FirstSurfNode); 02690 if (ROI_Mask) SUMA_free(ROI_Mask); ROI_Mask = NULL; 02691 if (!ROIfill) { 02692 SUMA_SLP_Err("Failed to fill area:\nPerhaps seed on edge\nor nothing to fill."); 02693 SUMA_RETURN(DrawnROI); 02694 } 02695 02696 break; 02697 default: 02698 fprintf (SUMA_STDERR, "Error %s: Why are you doing this to me ?.\n", FuncName); 02699 break; 02700 } 02701 02702 02703 /* Another switch on BsA, it is possible that its value changed within this function */ 02704 02705 switch (BsA) { 02706 case SUMA_BSA_AppendStroke: 02707 /* store the action */ 02708 ROIstroke->action = SUMA_BSA_AppendStroke; 02709 /*now add the ROIdatum to the list of ROIs */ 02710 if (LocalHead) fprintf (SUMA_STDERR, "%s: Adding ROIStroke to DrawnROI->ROIstrokelist\n", FuncName); 02711 ROIA = (SUMA_ROI_ACTION_STRUCT *) SUMA_malloc (sizeof(SUMA_ROI_ACTION_STRUCT)); /* this structure is freed in SUMA_DestroyROIActionData */ 02712 ROIA->DrawnROI = DrawnROI; 02713 ROIA->ROId = ROIstroke; 02714 tmpStackPos = SUMA_PushActionStack (DrawnROI->ActionStack, DrawnROI->StackPos, SUMA_AddToTailROIDatum, (void *)ROIA, SUMA_DestroyROIActionData); 02715 if (tmpStackPos) DrawnROI->StackPos = tmpStackPos; 02716 else { 02717 fprintf (SUMA_STDERR, "Error %s: Failed in SUMA_PushActionStack.\n", FuncName); 02718 SUMA_RETURN (DrawnROI); 02719 } 02720 if (SUMAg_CF->X->DrawROI->WhatDist == SW_DrawROI_WhatDistTrace || SUMAg_CF->X->DrawROI->WhatDist == SW_DrawROI_WhatDistAll) 02721 SUMA_ReportDrawnROIDatumLength(SO, ROIA->ROId, NULL, SUMAg_CF->X->DrawROI->WhatDist); 02722 break; 02723 case SUMA_BSA_JoinEnds: 02724 /* store the action */ 02725 ROIstroke->action = SUMA_BSA_JoinEnds; 02726 if (LocalHead) fprintf (SUMA_STDERR, "%s: Closing path.\n", FuncName); 02727 ROIA = (SUMA_ROI_ACTION_STRUCT *) SUMA_malloc (sizeof(SUMA_ROI_ACTION_STRUCT)); /* this structure is freed in SUMA_DestroyROIActionData */ 02728 ROIA->DrawnROI = DrawnROI; 02729 ROIA->ROId = ROIstroke; 02730 tmpStackPos = SUMA_PushActionStack (DrawnROI->ActionStack, DrawnROI->StackPos, SUMA_AddToTailJunctionROIDatum, (void *)ROIA, SUMA_DestroyROIActionData); 02731 if (tmpStackPos) DrawnROI->StackPos = tmpStackPos; 02732 else { 02733 fprintf (SUMA_STDERR, "Error %s: Failed in SUMA_PushActionStack.\n", FuncName); 02734 SUMA_RETURN (DrawnROI); 02735 } 02736 if (SUMAg_CF->X->DrawROI->WhatDist == SW_DrawROI_WhatDistTrace || SUMAg_CF->X->DrawROI->WhatDist == SW_DrawROI_WhatDistAll) 02737 SUMA_ReportDrawnROIDatumLength(SO, ROIA->ROId, NULL, SUMAg_CF->X->DrawROI->WhatDist); 02738 break; 02739 case SUMA_BSA_FillArea: 02740 /* store the action */ 02741 ROIfill->action = SUMA_BSA_FillArea; 02742 /* Now add ROIdatum to stack */ 02743 ROIA = (SUMA_ROI_ACTION_STRUCT *) SUMA_malloc (sizeof(SUMA_ROI_ACTION_STRUCT)); /* this structure is freed in SUMA_DestroyROIActionData */ 02744 ROIA->DrawnROI = DrawnROI; 02745 ROIA->ROId = ROIfill; 02746 tmpStackPos = SUMA_PushActionStack (DrawnROI->ActionStack, DrawnROI->StackPos, SUMA_AddFillROIDatum, (void *)ROIA, SUMA_DestroyROIActionData); 02747 if (tmpStackPos) DrawnROI->StackPos = tmpStackPos; 02748 else { 02749 fprintf (SUMA_STDERR, "Error %s: Failed in SUMA_PushActionStack.\n", FuncName); 02750 SUMA_RETURN (DrawnROI); 02751 } 02752 break; 02753 default: 02754 fprintf (SUMA_STDERR, "Error %s: Why are you doing this to me ?.\n", FuncName); 02755 break; 02756 } 02757 02758 /* Now update the Paint job on the ROI plane */ 02759 if (!SUMA_Paint_SO_ROIplanes_w (SO, SUMAg_DOv, SUMAg_N_DOv)) { 02760 SUMA_SLP_Err("Failed in SUMA_Paint_SO_ROIplanes_w."); 02761 SUMA_RETURN(DrawnROI); 02762 } 02763 02764 SUMA_RETURN(DrawnROI); 02765 } |
|
Executes an action Adds it to the action stack Update the action stack pointer DO not do StckPos = SUMA_PushActionStack (..., StackPos, ....); that is because the function might return NULL if something failed and you'd lose the current stack position for good. Definition at line 3271 of file SUMA_input.c. References SUMA_ACTION_STACK_DATA::ActionData, SUMA_ACTION_STACK_DATA::ActionDataDestructor, SUMA_ACTION_STACK_DATA::ActionFunction, dlist_ins_next(), dlist_remove(), dlist_tail, LocalHead, SAP_Do, SAR_Fail, SAR_Succeed, SAR_Undefined, SUMA_ACTION_POLARITY, SUMA_ACTION_RESULT, SUMA_Boolean, SUMA_ENTRY, SUMA_FreeActionStackData(), SUMA_malloc, SUMA_RETURN, and SUMA_SLP_Err. Referenced by SUMA_cb_DrawROI_Finish(), SUMA_cb_DrawROI_Join(), SUMA_NIMLDrawnROI_to_DrawnROI(), and SUMA_ProcessBrushStroke().
03275 { 03276 static char FuncName[]={"SUMA_PushActionStack"}; 03277 SUMA_Boolean LocalHead = NOPE; 03278 SUMA_ACTION_STACK_DATA *AS_data=NULL; 03279 SUMA_ACTION_RESULT ActionResult = SAR_Undefined; 03280 03281 SUMA_ENTRY; 03282 03283 /* execute action */ 03284 if (LocalHead) fprintf (SUMA_STDERR, "%s: Executing Action.\n", FuncName); 03285 ActionResult = ActionFunction (ActionData, SAP_Do); 03286 switch (ActionResult) { 03287 case SAR_Fail: 03288 SUMA_SLP_Err("Action failed."); 03289 SUMA_RETURN(NULL); 03290 break; 03291 case SAR_Succeed: 03292 break; 03293 default: 03294 SUMA_SLP_Err("Action result not understood."); 03295 SUMA_RETURN(NULL); 03296 break; 03297 } 03298 03299 /* remove all elements above the position in the stack */ 03300 if (LocalHead) fprintf (SUMA_STDERR, "%s: Removing Action Stack Elements above current position.\n", FuncName); 03301 while (StackPos != dlist_tail(ActionStack)) { 03302 void *asdata=NULL; 03303 03304 dlist_remove(ActionStack, dlist_tail(ActionStack), &asdata); 03305 03306 /* now free the asdata */ 03307 SUMA_FreeActionStackData(asdata); 03308 } 03309 03310 /* Pushing the action and its data onto the stack */ 03311 if (LocalHead) fprintf (SUMA_STDERR, "%s: Pushing the action and its data onto the stack.\n", FuncName); 03312 AS_data = (SUMA_ACTION_STACK_DATA *)SUMA_malloc (sizeof(SUMA_ACTION_STACK_DATA)); 03313 AS_data->ActionDataDestructor = ActionDataDestructor; 03314 AS_data->ActionFunction = ActionFunction; 03315 AS_data->ActionData = ActionData; 03316 dlist_ins_next (ActionStack, dlist_tail(ActionStack), (void*)AS_data); 03317 if (LocalHead) fprintf (SUMA_STDERR, "%s: Updating StackPos ...\n", FuncName); 03318 StackPos = dlist_tail(ActionStack); 03319 03320 SUMA_RETURN(StackPos); 03321 } |
|
Redo an action of the ActionStack If StackPos is NULL, it is assumed that you are at the bottom of the stack Definition at line 3327 of file SUMA_input.c. References SUMA_ACTION_STACK_DATA::ActionData, SUMA_ACTION_STACK_DATA::ActionFunction, DListElmt_::data, dlist_head, dlist_next, dlist_tail, LocalHead, SAP_Redo, SAR_Fail, SAR_Succeed, SAR_Undefined, SUMA_ACTION_RESULT, SUMA_Boolean, SUMA_ENTRY, SUMA_RETURN, and SUMA_SLP_Err. Referenced by SUMA_cb_DrawROI_Redo().
03328 { 03329 static char FuncName[]={"SUMA_RedoAction"}; 03330 SUMA_ACTION_STACK_DATA *AS_data=NULL; 03331 SUMA_ACTION_RESULT ActionResult = SAR_Undefined; 03332 SUMA_Boolean LocalHead = NOPE; 03333 03334 SUMA_ENTRY; 03335 03336 if (!StackPos) { 03337 if (LocalHead) fprintf (SUMA_STDERR, "%s: At bottom of stack. Working up.\n", FuncName); 03338 StackPos = dlist_head(ActionStack); 03339 } else if (StackPos == dlist_tail(ActionStack)) { 03340 SUMA_SLP_Err("At top of stack, nothing to do."); 03341 SUMA_RETURN(StackPos); 03342 } else { 03343 StackPos = dlist_next(StackPos); 03344 } 03345 03346 /* execute action above StackPos again */ 03347 AS_data = (SUMA_ACTION_STACK_DATA *)StackPos->data; 03348 ActionResult = AS_data->ActionFunction (AS_data->ActionData, SAP_Redo); 03349 switch (ActionResult) { 03350 case SAR_Fail: 03351 SUMA_SLP_Err("Action failed."); 03352 SUMA_RETURN(NULL); 03353 break; 03354 case SAR_Succeed: 03355 break; 03356 default: 03357 SUMA_SLP_Err("Action result not understood."); 03358 SUMA_RETURN(NULL); 03359 break; 03360 } 03361 03362 SUMA_RETURN(StackPos); 03363 } |
|
set the position of light0
Definition at line 3652 of file SUMA_input.c. References LocalHead, SE_Redisplay, SE_SetLight0Pos, SEF_fv3, SEI_Tail, SES_Suma, SUMA_Boolean, SUMA_CreateList(), SUMA_Engine(), SUMA_ENTRY, SUMA_InitializeEngineListData(), SUMA_REGISTER_TAIL_COMMAND_NO_DATA, SUMA_RegisterEngineListCommand(), SUMA_RETURNe, SUMA_StringToNum(), SUMA_X::TOPLEVEL, and SUMA_SurfaceViewer::X. Referenced by SUMA_input().
03653 { 03654 static char FuncName[]={"SUMA_SetLight0"}; 03655 DList *list=NULL; 03656 SUMA_EngineData *ED = NULL; 03657 SUMA_SurfaceViewer *sv = NULL; 03658 float fv3[3]; 03659 SUMA_Boolean LocalHead = NOPE; 03660 03661 SUMA_ENTRY; 03662 03663 if (!s) SUMA_RETURNe; 03664 03665 sv = (SUMA_SurfaceViewer *)data; 03666 03667 /* parse s */ 03668 if (SUMA_StringToNum (s, fv3, 3) != 3) { /* problem, beep and ignore */ 03669 XBell (XtDisplay (sv->X->TOPLEVEL), 50); 03670 SUMA_RETURNe; 03671 } 03672 03673 /* register fv3 with ED */ 03674 if (!list) list = SUMA_CreateList(); 03675 ED = SUMA_InitializeEngineListData (SE_SetLight0Pos); 03676 if (!SUMA_RegisterEngineListCommand ( list, ED, 03677 SEF_fv3, (void *)fv3, 03678 SES_Suma, (void *)sv, NOPE, 03679 SEI_Tail, NULL )) { 03680 fprintf(SUMA_STDERR,"Error %s: Failed to register command\n", FuncName); 03681 SUMA_RETURNe; 03682 } 03683 03684 SUMA_REGISTER_TAIL_COMMAND_NO_DATA(list, SE_Redisplay, SES_Suma, sv); 03685 03686 if (!SUMA_Engine (&list)) { 03687 fprintf(stderr, "Error %s: SUMA_Engine call failed.\n", FuncName); 03688 } 03689 03690 SUMA_RETURNe; 03691 } |
|
sets the number of smoothing operations to perform on foreground colors before display
Definition at line 3697 of file SUMA_input.c. References LocalHead, SUMA_X_AllView::NumForeSmoothing, SE_Redisplay_AllVisible, SES_Suma, SUMA_Boolean, SUMA_CreateList(), SUMA_Engine(), SUMA_ENTRY, SUMA_REGISTER_HEAD_COMMAND_NO_DATA, SUMA_RETURNe, SUMA_SetAllRemixFlag(), SUMA_SLP_Err, SUMA_StringToNum(), SUMAg_N_SVv, SUMA_X::TOPLEVEL, SUMA_CommonFields::X, and SUMA_SurfaceViewer::X. Referenced by SUMA_input().
03698 { 03699 static char FuncName[]={"SUMA_SetNumForeSmoothing"}; 03700 DList *list=NULL; 03701 SUMA_EngineData *ED = NULL; 03702 SUMA_SurfaceViewer *sv = NULL; 03703 float fv3[3]; 03704 SUMA_Boolean LocalHead = NOPE; 03705 03706 SUMA_ENTRY; 03707 03708 if (!s) SUMA_RETURNe; 03709 03710 sv = (SUMA_SurfaceViewer *)data; 03711 03712 /* parse s */ 03713 if (SUMA_StringToNum (s, fv3, 1) != 1) { /* problem, beep and ignore */ 03714 XBell (XtDisplay (sv->X->TOPLEVEL), 50); 03715 SUMA_RETURNe; 03716 } 03717 03718 /* set sv */ 03719 03720 if ((int)fv3[0] < 0) { 03721 SUMA_SLP_Err("Only positive integer\nvalues are valid.\n"); 03722 SUMA_RETURNe; 03723 } 03724 SUMAg_CF->X->NumForeSmoothing = (int)fv3[0]; 03725 03726 /* flag surfaces for remix */ 03727 SUMA_SetAllRemixFlag(SUMAg_SVv, SUMAg_N_SVv); 03728 03729 /* register a redisplay for sv*/ 03730 if (!list) list = SUMA_CreateList(); 03731 SUMA_REGISTER_HEAD_COMMAND_NO_DATA(list, SE_Redisplay_AllVisible, SES_Suma, sv); 03732 if (!SUMA_Engine (&list)) { 03733 fprintf(stderr, "Error %s: SUMA_Engine call failed.\n", FuncName); 03734 } 03735 03736 SUMA_RETURNe; 03737 03738 } |
|
Sets the foreground color of the drawing area Definition at line 2366 of file SUMA_input.c. References SUMA_X::DPY, SUMA_X::gc, SUMA_X::GLXAREA, SUMA_ENTRY, SUMA_RETURNe, and SUMA_SurfaceViewer::X. Referenced by SUMA_X_SurfaceViewer_Create().
02367 { 02368 static char FuncName[]={"SUMA_SetSVForegroundColor"}; 02369 XColor col, unused; 02370 02371 SUMA_ENTRY; 02372 /* using sv->X->CMAP instead of 02373 DefaultColormapOfScreen(XtScreen(sv->X->GLXAREA)) 02374 is useless */ 02375 if (!XAllocNamedColor (sv->X->DPY, DefaultColormapOfScreen(XtScreen(sv->X->GLXAREA)), 02376 Color, &col, &unused)) { 02377 fprintf (SUMA_STDERR, "Error %s: Can't allocate for %s color.\n", FuncName, Color); 02378 SUMA_RETURNe; 02379 } 02380 XSetForeground (sv->X->DPY, sv->X->gc, col.pixel); 02381 02382 SUMA_RETURNe; 02383 } |
|
Show the contents of a brush stroke SUMA_ShowBrushStroke (sv, Out);.
Definition at line 2186 of file SUMA_input.c. References SUMA_SurfaceViewer::BS, DListElmt_::data, dlist_head, dlist_size, dlist_tail, SUMA_BRUSH_STROKE_DATUM::FP, i, DListElmt_::next, SUMA_BRUSH_STROKE_DATUM::NP, SUMA_ENTRY, SUMA_RETURNe, SUMA_BRUSH_STROKE_DATUM::SurfNode, SUMA_BRUSH_STROKE_DATUM::SurfTri, SUMA_BRUSH_STROKE_DATUM::x, and SUMA_BRUSH_STROKE_DATUM::y. Referenced by SUMA_input().
02187 { 02188 static char FuncName[]={"SUMA_ShowBrushStroke"}; 02189 int i, k, N=0; 02190 SUMA_BRUSH_STROKE_DATUM *bsd=NULL; 02191 DListElmt *Next_Elm = NULL; 02192 02193 SUMA_ENTRY; 02194 02195 if (!out) out = SUMA_STDERR; 02196 02197 if (!sv->BS) { 02198 fprintf(out, "%s: NULL sv->BS\n", FuncName); 02199 SUMA_RETURNe; 02200 } 02201 02202 N = dlist_size(sv->BS); 02203 if (!N) { 02204 fprintf(out, "%s: Empty sv->BS. (N = 0)\n", FuncName); 02205 SUMA_RETURNe; 02206 } 02207 02208 fprintf(out, "%s: Brush stroke has %d elements:\n", FuncName, N); 02209 02210 i = 0; 02211 do { 02212 if (Next_Elm==NULL) Next_Elm = dlist_head(sv->BS); 02213 else Next_Elm = Next_Elm->next; 02214 if (!Next_Elm->data) { 02215 fprintf(out, "%s: Element->data %d is NULL!\n", FuncName, i); 02216 }else { 02217 bsd = (SUMA_BRUSH_STROKE_DATUM *)Next_Elm->data; 02218 fprintf(out, "%d: (%f %f) [%.2f, %.2f, %.2f <--> %.2f, %.2f, %.2f]\t Node %d, Tri %d\n", 02219 i, bsd->x, bsd->y, 02220 bsd->NP[0], bsd->NP[1], bsd->NP[2], 02221 bsd->FP[0], bsd->FP[1], bsd->FP[2], 02222 bsd->SurfNode, bsd->SurfTri); 02223 } 02224 ++i; 02225 }while (dlist_tail(sv->BS) != Next_Elm); 02226 02227 fprintf(out, "\n"); 02228 02229 SUMA_RETURNe; 02230 } |
|
Undo an action on the ActionStack
Definition at line 3373 of file SUMA_input.c. References SUMA_ACTION_STACK_DATA::ActionData, SUMA_ACTION_STACK_DATA::ActionFunction, DListElmt_::data, dlist_head, dlist_prev, LocalHead, SAP_Undo, SAR_Fail, SAR_Succeed, SAR_Undefined, SUMA_ACTION_RESULT, SUMA_Boolean, SUMA_ENTRY, SUMA_RETURN, and SUMA_SLP_Err. Referenced by SUMA_cb_DrawROI_Undo().
03374 { 03375 static char FuncName[]={"SUMA_UndoAction"}; 03376 SUMA_ACTION_STACK_DATA *AS_data=NULL; 03377 SUMA_ACTION_RESULT ActionResult = SAR_Undefined; 03378 SUMA_Boolean LocalHead = NOPE; 03379 03380 SUMA_ENTRY; 03381 03382 if (!StackPos) { 03383 SUMA_SLP_Err("At bottom of stack."); 03384 SUMA_RETURN(StackPos); 03385 } 03386 03387 AS_data = (SUMA_ACTION_STACK_DATA *)StackPos->data; 03388 03389 /* execute reverse of action */ 03390 ActionResult = AS_data->ActionFunction (AS_data->ActionData, SAP_Undo); 03391 switch (ActionResult) { 03392 case SAR_Fail: 03393 SUMA_SLP_Err("Action failed."); 03394 SUMA_RETURN(NULL); 03395 break; 03396 case SAR_Succeed: 03397 break; 03398 default: 03399 SUMA_SLP_Err("Action result not understood."); 03400 SUMA_RETURN(NULL); 03401 break; 03402 } 03403 03404 /* now move StackPos down */ 03405 if (StackPos == dlist_head(ActionStack)) { 03406 /* do nothing to StackPos */ 03407 } else { 03408 StackPos = dlist_prev(StackPos); 03409 } 03410 03411 SUMA_RETURN(StackPos); 03412 } |