Skip to content

AFNI/NIfTI Server

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

Doxygen Source Code Documentation


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

SUMA_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_ROISUMA_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_DATUMSUMA_NodeStrokeToConnectedNodes (SUMA_SurfaceViewer *sv)
SUMA_ROI_DATUMSUMA_LinkTailNodeToNodeStroke (SUMA_SurfaceViewer *sv, SUMA_DRAWN_ROI *DrawnROI)
 Function to link a node on the surface to the first node of a NodeStroke.

DListElmtSUMA_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_DATUMSUMA_LinkThisNodeToNodeInStroke (SUMA_SurfaceViewer *sv, int NonSurf, DListElmt *El)
 Function to link a node on the surface to a certain node in NodeStroke.

DListElmtSUMA_UndoAction (DList *ActionStack, DListElmt *StackPos)
DListElmtSUMA_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_DATUMSUMA_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

#define SUMA_BRUSH_BLOCK   500
 

Definition at line 4 of file SUMA_input.h.

#define SUMA_BS_COUNT_SURF_NODES bs,
N_SurfNode   
 

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

#define SUMA_BS_FIRST_SURF_NODE bs,
fn,
ft,
NE   
 

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);   \
      }  \
   }
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.

Parameters:
bs  (DList *) containing brushstroke
fn  (int) the first SurfNode (>= 0) of the list
ft  (int) the value of SurfTri corresponding to fn
NE  (DList_Elmt *) pointer to list element where the first SurfNode was found

Definition at line 52 of file SUMA_input.h.

Referenced by SUMA_LinkTailNodeToNodeStroke(), SUMA_NodeStrokeToConnectedNodes(), and SUMA_ProcessBrushStroke().

#define SUMA_BS_NEXT_SURF_NODE bs,
oEl,
El   
 

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; \
      }  \
   }
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.

Definition at line 74 of file SUMA_input.h.

Referenced by SUMA_NodeStrokeToConnectedNodes().

#define SUMA_REMOVE_NEXT_NON_DECIMATED bs,
Eli,
Eln   
 

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

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.

Parameters:
data  (void *) of SUMA_ROI_ACTION_STRUCT * containing the ROIlist and the ROIdatum
Pol  (SUMA_ACTION_POLARITY) SAP_Do, SAP_Redo, SAP_Undo

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 }

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

Parameters:
sv  (SUMA_SurfaceViewer *) pointer to surface viewer where stroke is occuring
x  (int) X coordinate of mouse
y  (int) Y coordinate of mouse
NP  (GLdouble *) vector of XYZ coordinates of Near Plane intersection point
FP  (GLdouble *) vector of XYZ coordinates of Far Plane intersection point.
Show  (SUMA_Boolean) if YUP: Then trace is drawn as you move the mouse
Returns:
YUP/NOPE, success indicator

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 }

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.

Parameters:
data  (void *) of SUMA_ROI_ACTION_STRUCT * containing the ROIlist and the ROIdatum
Pol  (SUMA_ACTION_POLARITY) SAP_Do, SAP_Redo, SAP_Undo

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 }

SUMA_ACTION_RESULT SUMA_AddToTailROIDatum void *    data,
SUMA_ACTION_POLARITY    Pol
 

Adds (or removes) an ROIdatum to the tail of the ROI list.

Parameters:
data  (void *) of SUMA_ROI_ACTION_STRUCT * containing the ROIlist and the ROIdatum
Pol  (SUMA_ACTION_POLARITY) SAP_Do, SAP_Redo, SAP_Undo

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 }

SUMA_Boolean SUMA_BrushStrokeToNodeStroke SUMA_SurfaceViewer   sv
 

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 }

void SUMA_ClearBrushStroke SUMA_SurfaceViewer   sv
 

Clear the contents of sv->BS and sets it to NULL.

SUMA_ClearBrushStroke (sv);

See also:
SUMA_CreateBrushStroke

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 }

SUMA_Boolean SUMA_CreateBrushStroke SUMA_SurfaceViewer   sv
 

Creates the BrushStroke structure inside sv structure success = SUMA_CreateBrushStroke (sv);.

Parameters:
sv  (SUMA_SurfaceViewer *) Surface viewer structure
Returns:
YUP/NOPE
sv->BS must be null before this function is called. The liat and its components are then allocated for.

See also:
SUMA_ClearBrushStroke

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 }

SUMA_BRUSH_STROKE_DATUM* SUMA_CreateBSDatum void   
 

Definition at line 2286 of file SUMA_input.c.

References SUMA_BRUSH_STROKE_DATUM::Decimated, SUMA_BRUSH_STROKE_DATUM::FP, SUMA_CommonFields::MessageList, SUMA_BRUSH_STROKE_DATUM::NP, SMA_LogAndPopup, SMT_Critical, SUMA_ENTRY, SUMA_malloc, SUMA_RegisterMessage(), SUMA_RETURN, SUMA_BRUSH_STROKE_DATUM::SurfNode, SUMA_BRUSH_STROKE_DATUM::SurfTri, SUMA_BRUSH_STROKE_DATUM::x, and SUMA_BRUSH_STROKE_DATUM::y.

Referenced by SUMA_AddToBrushStroke(), and SUMA_BrushStrokeToNodeStroke().

02287 {
02288    static char FuncName[]={"SUMA_CreateBSDatum"};
02289    SUMA_BRUSH_STROKE_DATUM *bsd = NULL;
02290    
02291    SUMA_ENTRY;
02292    
02293    bsd = (SUMA_BRUSH_STROKE_DATUM *)SUMA_malloc(sizeof(SUMA_BRUSH_STROKE_DATUM));
02294    if (!bsd) {
02295       SUMA_RegisterMessage (SUMAg_CF->MessageList, 
02296                             "Failed to allocate.", FuncName, 
02297                             SMT_Critical, SMA_LogAndPopup);
02298       SUMA_RETURN(NULL); 
02299    }
02300    /* setup defaults */
02301    bsd->x = bsd->y = 0.0;
02302    bsd->NP[0] = bsd->NP[1] = bsd->NP[2] = 0.0;
02303    bsd->FP[0] = bsd->FP[1] = bsd->FP[2] = 0.0;
02304    bsd->SurfNode = -1;
02305    bsd->SurfTri = -1;
02306    bsd->Decimated = NOPE;
02307    
02308    SUMA_RETURN(bsd);
02309 }

void SUMA_DestroyROIActionData void *    data
 

A function to destroy the ROI action data structure.

Parameters:
data  (void *) of SUMA_ROI_ACTION_STRUCT * containing the ROIlist and the ROIdatum

  • Only ROIA->ROId and ROIA are freed. ROIA->DrawnROI should be freed when the DrawnROI list is destroyed.

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 }

void SUMA_DrawBrushStroke SUMA_SurfaceViewer   sv,
SUMA_Boolean    incr
 

Draws the brushstroke.

Parameters:
sv  (SUMA_SurfaceViewer *) pointer to surface viewer structure
incremental  (SUMA_Boolean) YUP: draw a line between the last two points NOPE: draw the whole thing

  • NB: This function used to crash when run on SGI if display is not in TrueColor mode. This happens even though the visual chosen by SUMA does not change. To put the SGI in true color mode, you need to add to /var/X11/xdm/Xservers the following: -class TrueColor -depth 24 and then restart X or the system. The bug was that the graphics context (sv->X->gc) was created using the Screen's root window and not the GLX visual's window.

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 }

SUMA_ACTION_RESULT SUMA_FinishedROI void *    data,
SUMA_ACTION_POLARITY    Pol
 

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 }

void SUMA_FreeBSDatum void *    bsd
 

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 }

void SUMA_HighlightBox char *    s,
void *    data
 

Highlight a set of nodes within a box.

Parameters:
s  (char *) a string containing box center followed by box size (6 values)
data  (void *) a typecast of the pointer to the surface viewer to be affected

  • operates by coloring nodes inside box.
  • coloring is not permanent and modifies other colors already present
  • operates on current viewer only

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 }

void SUMA_input Widget    w,
XtPointer    clientData,
XtPointer    callData
 

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 }

void SUMA_JumpFocusFace char *    s,
void *    data
 

changes the selected faceset (Focus FaceSet)

Parameters:
s  (char *) a string containing FaceSet index
data  (void *) a typecast of the pointer to the surface viewer to be affected

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 }

void SUMA_JumpFocusNode char *    s,
void *    data
 

Changes the focus node without moving the cross hair.

Parameters:
s  (char *) a string containing node index
data  (void *) a typecast of the pointer to the surface viewer to be affected
-actions of this function are limited to the viewer that launched it

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 }

void SUMA_JumpIndex char *    s,
void *    data
 

sends the cross hair to a certain node index

Parameters:
s  (char *) a string containing node index
data  (void *) a typecast of the pointer to the surface viewer to be affected

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 }  

void SUMA_JumpXYZ char *    s,
void *    data
 

sends the cross hair to a certain XYZ location.

Parameters:
s  (char *) a string containing XYZ coordinates
data  (void *) a typecast of the pointer to the surface viewer to be affected

  • Update to AFNI is done if linked
  • Update to other viewers is performed IF they are XYZ locked (that can get confusing)

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 }

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.

-This function returns an ROI_datum that represents the link between the last node visited and the first node of the Nodestroke

See also:
SUMA_LinkThisNodeToNodeInStroke

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 }

SUMA_ROI_DATUM* SUMA_LinkThisNodeToNodeInStroke SUMA_SurfaceViewer   sv,
int    NonSurf,
DListElmt   ELinStroke
 

Function to link a node on the surface to a certain node in NodeStroke.

Parameters:
sv  (SUMA_SurfaceViewer *) with a valid BrushStroke in it
NonSurf  (int) index of node on surface to connect to NinStroke
ELinStroke  (DListElmt *) sv->BS element containing in SurfNode the index of the node to connect NonSurf to
See also:
SUMA_LinkTailNodeToNodeStroke

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 }

void SUMA_LookAtCoordinates char *    s,
void *    data
 

rotates surface to face a certain coordinate

Parameters:
s  (char *) a strng containing X, Y, Z coordinates
data  (void *) a typecast of the pointer to the surface viewer to be affected

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 }

int SUMA_MarkLineSurfaceIntersect SUMA_SurfaceViewer   sv,
SUMA_DO   dov
 

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);

Parameters:
sv  (SUMA_SurfaceViewer *) surface viewer pointer
dov  (SUMA_DO *) displayable object vector pointer \ret ans (int) -1 error, 0 no hit, hit
also requires SUMAg_DOv and SUMAg_N_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 */

void SUMA_momentum XtPointer    clientData,
XtIntervalId *    id
 

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 }

SUMA_ROI_DATUM* SUMA_NodeStrokeToConnectedNodes SUMA_SurfaceViewer   sv
 

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 }

SUMA_DRAWN_ROI* SUMA_ProcessBrushStroke SUMA_SurfaceViewer   sv,
SUMA_BRUSH_STROKE_ACTION    BsA
 

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 }

DListElmt* SUMA_PushActionStack DList   ActionStack,
DListElmt   StackPos,
SUMA_ACTION_RESULT(*    ActionFunction)(void *ActionData, SUMA_ACTION_POLARITY Pol),
void *    ActionData,
void(*    ActionDataDestructor)(void *Actiondata)
 

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 }

DListElmt* SUMA_RedoAction DList   ActionStack,
DListElmt   StackPos
 

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 }   

void SUMA_SetLight0 char *    s,
void *    data
 

set the position of light0

Parameters:
s  (char *) a strng containing X, Y, Z coordinates
data  (void *) a typecast of the pointer to the surface viewer to be affected

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 }

void SUMA_SetNumForeSmoothing char *    s,
void *    data
 

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 }

void SUMA_SetSVForegroundColor SUMA_SurfaceViewer   sv,
const char *    Color
 

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 }

void SUMA_ShowBrushStroke SUMA_SurfaceViewer   sv,
FILE *    out
 

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 }

DListElmt* SUMA_UndoAction DList   ActionStack,
DListElmt   StackPos
 

Undo an action on the ActionStack

Returns:
StackNewPos = StackPos if reached the bottom of the stack. It is your job to make sure this function is not called again. = StackPos->prev if all went well =NULL if trouble

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 }
 

Powered by Plone

This site conforms to the following standards: