00001 #include "SUMA_suma.h"
00002
00003
00004 extern int SUMAg_N_DOv;
00005 extern SUMA_DO *SUMAg_DOv;
00006 extern SUMA_CommonFields *SUMAg_CF;
00007 extern SUMA_SurfaceViewer *SUMAg_SVv;
00008 extern int SUMAg_N_SVv;
00009
00010
00011
00012
00013
00014 void SUMA_input(Widget w, XtPointer clientData, XtPointer callData)
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;
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;
00042 SUMA_Boolean LocalHead = NOPE;
00043
00044
00045
00046
00047 SUMA_ENTRY;
00048
00049
00050 cd = (GLwDrawingAreaCallbackStruct *) callData;
00051
00052
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;
00062 Bev = *(XButtonEvent *) &cd->event->xbutton;
00063 Mev = *(XMotionEvent *) &cd->event->xmotion;
00064
00065
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
00083 }
00084 #endif
00085
00086 switch (Kev.type) {
00087 case KeyPress:
00088 xls = XLookupString((XKeyEvent *) cd->event, buffer, 8, &keysym, NULL);
00089
00090
00091 switch (keysym) {
00092 case XK_bracketleft:
00093
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
00108 SUMA_WorldAxisStandard (sv->WAx, sv);
00109 SUMA_UpdateViewerTitle(sv);
00110 SUMA_postRedisplay(w, clientData, callData);
00111 break;
00112
00113 case XK_bracketright:
00114
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
00129 SUMA_WorldAxisStandard (sv->WAx, sv);
00130 SUMA_UpdateViewerTitle(sv);
00131 SUMA_postRedisplay(w, clientData, callData);
00132 break;
00133
00134 case XK_space:
00135
00136 {
00137 SUMA_SurfaceObject *SO = NULL, *SOmap = NULL;
00138 int curstateID = -1, nxtstateID = -1, dov_ID = -1;
00139
00140
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
00145 if (sv->LastNonMapStateID < 0) {
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 {
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
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
00178 sv->LastNonMapStateID = curstateID;
00179
00180
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:
00192
00193 if (Kev.state & ShiftMask){
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
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
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
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
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
00328
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
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){
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
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
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
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){
00528
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
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
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
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
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
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
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
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
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
00850 sv->FOV[sv->iState] /= FOV_IN_FACT; if (sv->FOV[sv->iState] < FOV_MIN) { SUMA_BEEP; sv->FOV[sv->iState] = FOV_MIN; }
00851
00852 if (sv->ZoomCompensate) {
00853 sv->ZoomCompensate = sv->FOV[sv->iState] / FOV_INITIAL;
00854 if (sv->ZoomCompensate > 1) sv->ZoomCompensate = 1.0;
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
00862 sv->FOV[sv->iState] /= FOV_OUT_FACT; if (sv->FOV[sv->iState] > FOV_MAX) { SUMA_BEEP; sv->FOV[sv->iState] = FOV_MAX; }
00863
00864 if (sv->ZoomCompensate) {
00865 sv->ZoomCompensate = sv->FOV[sv->iState] / FOV_INITIAL;
00866 if (sv->ZoomCompensate > 1) sv->ZoomCompensate = 1.0;
00867 else if (sv->ZoomCompensate < 0.005) sv->ZoomCompensate = 0.005;
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
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) {
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
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 }
00937
00938 SUMA_free(attr_sm);
00939 SUMA_free(attrbuf);
00940
00941 SUMA_postRedisplay(w, clientData, callData);
00942 }
00943
00944 break;
00945
00946 case XK_at:
00947 if (SUMAg_CF->Dev) {
00948
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
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
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
01016 OptScl->ApplyClip = YUP;
01017 IntRange[0] = 5; IntRange[1] = 95;
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
01024
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
01032
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
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
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
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
01096
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
01112
01113 } while (!SUMA_VisibleSOs (sv, SUMAg_DOv, NULL) && sv->iState != origState);
01114
01115
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
01123 SUMA_UpdateViewerTitle(sv);
01124 }
01125 break;
01126
01127 case XK_period:
01128 {
01129
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
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
01180
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
01188 SUMA_UpdateViewerTitle(sv);
01189 }
01190 break;
01191
01192 case XK_F1:
01193
01194 sv->ShowEyeAxis = !sv->ShowEyeAxis;
01195 SUMA_postRedisplay(w, clientData, callData);
01196 break;
01197
01198 case XK_F2:
01199
01200 {
01201 int *do_id, n_do_id;
01202 ++sv->ShowWorldAxis; sv->ShowWorldAxis = sv->ShowWorldAxis % SUMA_N_WAX_OPTIONS;
01203 sv->ShowMeshAxis = 0;
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:
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:
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:
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:
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:
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:
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:
01290
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
01311 SUMA_display(sv, SUMAg_DOv);
01312
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
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
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:
01362
01363 if ((Kev.state & ControlMask) && (Kev.state & ShiftMask)) {
01364
01365 }else if (Kev.state & ShiftMask) {
01366
01367 sv->GVS[sv->StdView].translateVec[0] -= (GLfloat)sv->GVS[sv->StdView].ArrowtranslateDeltaX/(float)sv->WindWidth*sv->GVS[sv->StdView].TranslateGain;
01368
01369 SUMA_postRedisplay(w, clientData, callData);
01370 }else if (Kev.state & ControlMask){
01371 float a[3], cQ[4], dQ[4];
01372
01373 a[0] = 1.0; a[1] = 0.0;
01374 axis_to_quat(a, SUMA_PI/2.0, cQ);
01375
01376 a[0] = 0.0; a[1] = 1.0; a[2] = 0.0;
01377 axis_to_quat(a, SUMA_PI/2.0, dQ);
01378
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
01383 }else {
01384
01385 trackball_Phi(sv->GVS[sv->StdView].deltaQuat,
01386 ArrowDeltaRot, 0.0,
01387 -ArrowDeltaRot, 0.0,
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:
01398
01399 if ((Kev.state & ControlMask) && (Kev.state & ShiftMask)) {
01400
01401 }else if (Kev.state & ShiftMask) {
01402
01403 sv->GVS[sv->StdView].translateVec[0] += (GLfloat)sv->GVS[sv->StdView].ArrowtranslateDeltaX/(float)sv->WindWidth*sv->GVS[sv->StdView].TranslateGain;
01404
01405 SUMA_postRedisplay(w, clientData, callData);
01406 }else if (Kev.state & ControlMask){
01407 float a[3], cQ[4], dQ[4];
01408
01409 a[0] = 1.0; a[1] = 0.0; a[2] = 0.0;
01410 axis_to_quat(a, SUMA_PI/2.0, cQ);
01411
01412 a[0] = 0.0; a[1] = 1.0;
01413 axis_to_quat(a, -SUMA_PI/2.0, dQ);
01414
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
01420 }else {
01421
01422 trackball_Phi(sv->GVS[sv->StdView].deltaQuat,
01423 -ArrowDeltaRot, 0.0,
01424 ArrowDeltaRot, 0.0,
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:
01434
01435 if ((Kev.state & ControlMask) && (Kev.state & ShiftMask)) {
01436 float a[3], cQ[4], dQ[4];
01437
01438
01439 a[0] = 1.0; a[1] = 0.0; a[2] = 0.0;
01440 axis_to_quat(a, SUMA_PI/2, cQ);
01441
01442 a[0] = 0.0; a[1] = 1.0; a[2] = 0.0;
01443 axis_to_quat(a, SUMA_PI, dQ);
01444
01445 add_quats (dQ, cQ, sv->GVS[sv->StdView].currentQuat);
01446 SUMA_postRedisplay(w, clientData, callData);
01447 }else if (Kev.state & ShiftMask) {
01448
01449
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
01454
01455 float a[3];
01456
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
01462 }else {
01463
01464 trackball_Phi(sv->GVS[sv->StdView].deltaQuat,
01465 0.0, ArrowDeltaRot,
01466 0.0, -ArrowDeltaRot,
01467 sv->ArrowRotationAngle);
01468
01469
01470 add_quats (sv->GVS[sv->StdView].deltaQuat, sv->GVS[sv->StdView].currentQuat, sv->GVS[sv->StdView].currentQuat);
01471
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:
01480
01481 if ((Kev.state & ControlMask) && (Kev.state & ShiftMask)) {
01482 float a[3];
01483
01484
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
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
01494
01495 float a[3];
01496
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
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,
01506 0.0, ArrowDeltaRot,
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 }
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
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) {
01560 case Button1:
01561 if (Bev.state & Button2Mask) {
01562
01563
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
01569
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
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
01593
01594 sv->GVS[sv->StdView].zoomBegin = (float)Bev.y;
01595 sv->GVS[sv->StdView].zoomDelta = 0;
01596 } else {
01597
01598
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
01613 if (Bev.state & ShiftMask && SUMAg_CF->ROI_mode && sv->Focus_SO_ID >= 0) {
01614
01615 ROI_mode = YUP;
01616 }else {
01617 ROI_mode = NOPE;
01618 }
01619 #endif
01620
01621 if (SUMAg_CF->ROI_mode && sv->Focus_SO_ID >= 0 && !(Bev.state & ShiftMask)) {
01622
01623 ROI_mode = YUP;
01624 }else {
01625 ROI_mode = NOPE;
01626 }
01627
01628 if (!DoubleClick) {
01629
01630
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) {
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
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) {
01661 break;
01662 }
01663
01664
01665 }
01666
01667 if (ROI_mode) {
01668
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
01684 sv->ResetGLStateVariables = YUP;
01685 SUMA_handleRedisplay((XtPointer)sv->X->GLXAREA);
01686
01687
01688 break;
01689 }
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) {
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
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
01718 if (LocalHead) SUMA_ShowDrawnROI (DrawnROI, NULL, NOPE);
01719
01720
01721 if (LocalHead) SUMA_ShowBrushStroke (sv, NULL);
01722
01723
01724 SUMA_ClearBrushStroke (sv);
01725
01726
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
01732 sv->ResetGLStateVariables = YUP;
01733 SUMA_handleRedisplay((XtPointer)sv->X->GLXAREA);
01734
01735 }
01736 }
01737
01738 break;
01739 }
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
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
01782
01783 if (sv->ZoomCompensate) {
01784 sv->ZoomCompensate = sv->FOV[sv->iState] / FOV_INITIAL;
01785 if (sv->ZoomCompensate > 1) sv->ZoomCompensate = 1.0;
01786 else if (sv->ZoomCompensate < 0.005) sv->ZoomCompensate = 0.005;
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
01794 mevx = (float)Mev.x;
01795 mevy = (float)Mev.y;
01796 wwid = (float)sv->WindWidth;
01797 whei = (float)sv->WindHeight;
01798
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
01808
01809
01810
01811
01812
01813
01814
01815
01816
01817
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);
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]) {
01834 SUMA_postRedisplay(w, clientData, callData);
01835 } else {
01836 DList *list = NULL;
01837 SUMA_EngineData *ED = NULL;
01838 SUMA_STANDARD_VIEWS ed_sv, ed_svi;
01839
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
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
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
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
01899 ii = SUMA_RegisteredSOs(sv, SUMAg_DOv, NULL);
01900 if (ii == 0) {
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 }
01927
01928 SUMA_RETURNe;
01929 }
01930
01931
01932
01933
01934
01935
01936 void SUMA_momentum(XtPointer clientData, XtIntervalId *id)
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
01947 w = (Widget)clientData;
01948
01949
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 {
01960
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 {
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
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 }
01978
01979
01980
01981
01982
01983
01984
01985
01986
01987
01988
01989
01990
01991 int SUMA_MarkLineSurfaceIntersect (SUMA_SurfaceViewer *sv, SUMA_DO *dov)
01992 {
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) {
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) {
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
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
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
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
02069 if (SO->SurfCont->TopLevelShell) SUMA_Init_SurfCont_SurfParam(SO);
02070
02071
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
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
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
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
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
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
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
02150
02151
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
02170 if (MTI) {
02171 MTI = SUMA_Free_MT_intersect_triangle(MTI);
02172 }
02173
02174 if (imin >= 0) {
02175 SUMA_RETURN (1);
02176 } else {
02177 SUMA_RETURN (0);
02178 }
02179 }
02180
02181
02182
02183
02184
02185
02186 void SUMA_ShowBrushStroke (SUMA_SurfaceViewer *sv, FILE *out)
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 }
02231
02232
02233
02234
02235
02236
02237
02238
02239
02240 void SUMA_ClearBrushStroke (SUMA_SurfaceViewer *sv)
02241 {
02242 static char FuncName[]={"SUMA_ClearBrushStroke"};
02243
02244 SUMA_ENTRY;
02245
02246
02247 if (sv->BS) {
02248 SUMA_EmptyDestroyList(sv->BS);
02249 sv->BS = NULL;
02250 }
02251
02252 SUMA_RETURNe;
02253 }
02254
02255
02256
02257
02258
02259
02260
02261
02262
02263
02264
02265
02266 SUMA_Boolean SUMA_CreateBrushStroke (SUMA_SurfaceViewer *sv)
02267 {
02268 static char FuncName[]={"SUMA_CreateBrushStroke"};
02269
02270 SUMA_ENTRY;
02271
02272
02273 if (sv->BS) {
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 }
02285
02286 SUMA_BRUSH_STROKE_DATUM * SUMA_CreateBSDatum(void)
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
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 }
02310
02311
02312
02313
02314 void SUMA_FreeBSDatum (void *bsd)
02315 {
02316 static char FuncName[]={"SUMA_FreeBSDatum"};
02317
02318 SUMA_ENTRY;
02319
02320
02321 if (bsd) SUMA_free(bsd);
02322
02323 SUMA_RETURNe;
02324 }
02325
02326
02327
02328
02329
02330
02331
02332
02333
02334
02335
02336
02337
02338
02339
02340
02341 SUMA_Boolean SUMA_AddToBrushStroke (SUMA_SurfaceViewer *sv, int x, int y, GLdouble *NP, GLdouble *FP, SUMA_Boolean Show)
02342 {
02343 static char FuncName[]={"SUMA_AddToBrushStroke"};
02344 int ip;
02345 SUMA_BRUSH_STROKE_DATUM *bsd=NULL;
02346
02347 SUMA_ENTRY;
02348
02349
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
02358 if (Show) SUMA_DrawBrushStroke (sv, YUP);
02359
02360 SUMA_RETURN (YUP);
02361 }
02362
02363
02364
02365
02366 void SUMA_SetSVForegroundColor (SUMA_SurfaceViewer *sv, const char *Color)
02367 {
02368 static char FuncName[]={"SUMA_SetSVForegroundColor"};
02369 XColor col, unused;
02370
02371 SUMA_ENTRY;
02372
02373
02374
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 }
02384
02385
02386
02387
02388
02389
02390
02391
02392
02393
02394
02395
02396
02397
02398
02399 void SUMA_DrawBrushStroke (SUMA_SurfaceViewer *sv, SUMA_Boolean incr)
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 }
02439
02440
02441
02442
02443
02444 SUMA_DRAWN_ROI * SUMA_ProcessBrushStroke (SUMA_SurfaceViewer *sv, SUMA_BRUSH_STROKE_ACTION BsA)
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
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) {
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
02493 SUMA_InitializeDrawROIWindow(DrawnROI);
02494 } else {
02495
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) {
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
02519
02520
02521
02522
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
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
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
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
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
02582 if (dlist_size(DrawnROI->ROIstrokelist)) {
02583
02584 if (LocalHead) fprintf (SUMA_STDERR, "%s: Adding ROIstroke to previous ones ...\n", FuncName);
02585
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
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
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
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
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
02637 if (DrawnROI) {
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
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
02650
02651
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
02655 BsA = SUMA_BSA_AppendStroke;
02656 SUMA_SL_Err ("Failed to close path. Continue with stroke.");
02657 SUMA_RETURN(DrawnROI);
02658 }else {
02659
02660 }
02661 } else {
02662
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
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
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
02704
02705 switch (BsA) {
02706 case SUMA_BSA_AppendStroke:
02707
02708 ROIstroke->action = SUMA_BSA_AppendStroke;
02709
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));
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
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));
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
02741 ROIfill->action = SUMA_BSA_FillArea;
02742
02743 ROIA = (SUMA_ROI_ACTION_STRUCT *) SUMA_malloc (sizeof(SUMA_ROI_ACTION_STRUCT));
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
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 }
02766
02767
02768
02769
02770
02771
02772
02773
02774 SUMA_Boolean SUMA_BrushStrokeToNodeStroke (SUMA_SurfaceViewer *sv)
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
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
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
02812
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) {
02835 oElmt = Elmt->prev;
02836 obsd = (SUMA_BRUSH_STROKE_DATUM *)oElmt->data;
02837 if (obsd->SurfNode != MTI->inodemin) {
02838 bsd->SurfNode = MTI->inodemin;
02839 bsd->SurfTri = MTI->ifacemin;
02840 }else {
02841
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
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) {
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;
02868 SUMA_Boolean TrackOscillation = YUP;
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;
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;
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) {
02893 N_Neighb = SO->FN->N_Neighb[n1];
02894 if (N_Neighb < 3) {
02895
02896 SUMA_SLP_Err ("Node has less than 3 neighbors.\n.This method will not apply.");
02897 SUMA_RETURN(NOPE);
02898 }
02899
02900
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
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 {
02949
02950 if (LocalHead) fprintf (SUMA_STDERR, "%s: Trying brute force here \n", FuncName);
02951
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) {
02972 DoesInters = YUP;
02973 if (bsdi->SurfNode != MTI->inodemin) {
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
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
02984 SUMA_SL_Err ("Why are you drawing out of bounds ?");
02985 SUMA_RETURN (YUP);
02986 }
02987
02988 TryBruteForce = NOPE;
02989 }
02990
02991 if (!DoesInters) {
02992 ++DeciLevel;
02993 if (LocalHead) fprintf (SUMA_STDERR, "%s: No intersection found. Decimating, level %d.\n", FuncName, DeciLevel);
02994
02995 if (DeciLevel > 3000) {
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
03012 if (ni == n1 && !DeciLevel) {
03013
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
03022 if (DeciLevel) {
03023 #if 0
03024
03025 TryBruteForce = YUP;
03026
03027 DoesInters = NOPE;
03028 #else
03029
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
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
03047 TryBruteForce = YUP;
03048
03049 DoesInters = NOPE;
03050 }
03051 #endif
03052 ++DeciReentry;
03053 }
03054 }else {
03055
03056 DeciLevel = 0;
03057 DeciReentry = 0;
03058 }
03059
03060
03061
03062
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) {
03077 if (LocalHead) fprintf (SUMA_STDERR, "%s: Found new node.\n", FuncName);
03078
03079 bsdn->SurfNode = ni;
03080 bsdn->SurfTri = ti;
03081
03082 Eli = Eln;
03083 }
03084 }
03085 }
03086
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 }
03094 #endif
03095 SUMA_RETURN(YUP);
03096 }
03097
03098
03099
03100
03101
03102
03103
03104
03105
03106
03107 SUMA_ROI_DATUM *SUMA_LinkThisNodeToNodeInStroke (SUMA_SurfaceViewer *sv, int NonSurf, DListElmt *ELinStroke)
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
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 }
03134
03135
03136
03137
03138
03139
03140
03141
03142
03143 SUMA_ROI_DATUM *SUMA_LinkTailNodeToNodeStroke (SUMA_SurfaceViewer *sv, SUMA_DRAWN_ROI *DrawnROI)
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
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
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
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 }
03183
03184
03185
03186
03187
03188 SUMA_ROI_DATUM *SUMA_NodeStrokeToConnectedNodes (SUMA_SurfaceViewer *sv)
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
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
03213 SO = (SUMA_SurfaceObject *)SUMAg_DOv[sv->Focus_SO_ID].OP;
03214 oElmt = Elmt;
03215 do {
03216
03217 SUMA_BS_NEXT_SURF_NODE(sv->BS, oElmt, Elmt);
03218
03219 if (!Elmt) {
03220
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
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
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
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 }
03262
03263
03264
03265
03266
03267
03268
03269
03270
03271 DListElmt * SUMA_PushActionStack (DList *ActionStack, DListElmt *StackPos,
03272 SUMA_ACTION_RESULT (*ActionFunction)(void *ActionData, SUMA_ACTION_POLARITY Pol),
03273 void *ActionData,
03274 void (*ActionDataDestructor)(void *Actiondata))
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
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
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
03307 SUMA_FreeActionStackData(asdata);
03308 }
03309
03310
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 }
03322
03323
03324
03325
03326
03327 DListElmt * SUMA_RedoAction (DList *ActionStack, DListElmt *StackPos)
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
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 }
03364
03365
03366
03367
03368
03369
03370
03371
03372
03373 DListElmt * SUMA_UndoAction (DList *ActionStack, DListElmt *StackPos)
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
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
03405 if (StackPos == dlist_head(ActionStack)) {
03406
03407 } else {
03408 StackPos = dlist_prev(StackPos);
03409 }
03410
03411 SUMA_RETURN(StackPos);
03412 }
03413
03414
03415
03416
03417 SUMA_ACTION_RESULT SUMA_FinishedROI (void *data, SUMA_ACTION_POLARITY Pol)
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
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
03445 if (!ROIA->DrawnROI->CE) {
03446 int *Nodes, N_Nodes;
03447 SUMA_Boolean Unique = NOPE;
03448
03449 SUMA_LH("Getting Contour ");
03450 N_Nodes = 0;
03451 Unique = YUP;
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
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 }
03482
03483
03484
03485
03486
03487
03488
03489
03490 SUMA_ACTION_RESULT SUMA_AddFillROIDatum (void *data, SUMA_ACTION_POLARITY Pol)
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
03514
03515
03516 tail_elm = dlist_tail(ROIA->DrawnROI->ROIstrokelist);
03517 ROId = (SUMA_ROI_DATUM *)tail_elm->data;
03518 if (ROId->Type == SUMA_ROI_NodeSegment) {
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 }
03529
03530
03531
03532
03533
03534
03535
03536 SUMA_ACTION_RESULT SUMA_AddToTailJunctionROIDatum (void *data, SUMA_ACTION_POLARITY Pol)
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
03566
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 }
03576
03577
03578
03579
03580
03581
03582
03583
03584 SUMA_ACTION_RESULT SUMA_AddToTailROIDatum (void *data, SUMA_ACTION_POLARITY Pol)
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
03605
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 }
03614
03615
03616
03617
03618
03619
03620
03621
03622
03623 void SUMA_DestroyROIActionData (void *data)
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) {
03636 SUMA_FreeROIDatum ((void *)ROIA->ROId);
03637 ROIA->ROId = NULL;
03638 }
03639
03640 ROIA->DrawnROI = NULL;
03641 SUMA_free(ROIA);
03642
03643 SUMA_RETURNe;
03644 }
03645
03646
03647
03648
03649
03650
03651
03652 void SUMA_SetLight0 (char *s, void *data)
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
03668 if (SUMA_StringToNum (s, fv3, 3) != 3) {
03669 XBell (XtDisplay (sv->X->TOPLEVEL), 50);
03670 SUMA_RETURNe;
03671 }
03672
03673
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 }
03692
03693
03694
03695
03696
03697 void SUMA_SetNumForeSmoothing (char *s, void *data)
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
03713 if (SUMA_StringToNum (s, fv3, 1) != 1) {
03714 XBell (XtDisplay (sv->X->TOPLEVEL), 50);
03715 SUMA_RETURNe;
03716 }
03717
03718
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
03727 SUMA_SetAllRemixFlag(SUMAg_SVv, SUMAg_N_SVv);
03728
03729
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 }
03739
03740
03741
03742
03743
03744
03745
03746 void SUMA_LookAtCoordinates (char *s, void *data)
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
03762 if (SUMA_StringToNum (s, fv3, 3) != 3) {
03763 XBell (XtDisplay (sv->X->TOPLEVEL), 50);
03764 SUMA_RETURNe;
03765 }
03766
03767
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 }
03783
03784
03785
03786
03787
03788
03789
03790 void SUMA_JumpIndex (char *s, void *data)
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
03808 if (SUMA_StringToNum (s, fv3, 1) != 1) {
03809 XBell (XtDisplay (sv->X->TOPLEVEL), 50);
03810 SUMA_RETURNe;
03811 }
03812
03813
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
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
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
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
03853 SUMA_REGISTER_TAIL_COMMAND_NO_DATA(list, SE_SetAfniCrossHair, SES_Suma, sv);
03854 }
03855
03856
03857 if (!SUMA_Engine (&list)) {
03858 fprintf(stderr, "Error %s: SUMA_Engine call failed.\n", FuncName);
03859 SUMA_RETURNe;
03860 }
03861
03862
03863
03864
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
03876 if (!SUMA_Engine (&list)) {
03877 fprintf(stderr, "Error %s: SUMA_Engine call failed.\n", FuncName);
03878 SUMA_RETURNe;
03879 }
03880
03881
03882 sv->ResetGLStateVariables = YUP;
03883 SUMA_handleRedisplay((XtPointer)sv->X->GLXAREA);
03884
03885 SUMA_RETURNe;
03886
03887 }
03888
03889
03890
03891
03892
03893
03894
03895
03896
03897
03898 void SUMA_JumpXYZ (char *s, void *data)
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
03914 if (SUMA_StringToNum (s, fv3, 3) != 3) {
03915 XBell (XtDisplay (sv->X->TOPLEVEL), 50);
03916 SUMA_RETURNe;
03917 }
03918
03919
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
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
03934 SUMA_REGISTER_TAIL_COMMAND_NO_DATA(list, SE_SetAfniCrossHair, SES_Suma, sv);
03935 }
03936
03937
03938 if (!SUMA_Engine (&list)) {
03939 fprintf(stderr, "Error %s: SUMA_Engine call failed.\n", FuncName);
03940 SUMA_RETURNe;
03941 }
03942
03943
03944
03945
03946
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
03958 if (!SUMA_Engine (&list)) {
03959 fprintf(stderr, "Error %s: SUMA_Engine call failed.\n", FuncName);
03960 SUMA_RETURNe;
03961 }
03962
03963
03964
03965 sv->ResetGLStateVariables = YUP;
03966 SUMA_handleRedisplay((XtPointer)sv->X->GLXAREA);
03967
03968 SUMA_RETURNe;
03969 }
03970
03971
03972
03973
03974
03975
03976
03977
03978
03979 void SUMA_JumpFocusNode (char *s, void *data)
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
03996 if (SUMA_StringToNum (s, fv3, 1) != 1) {
03997 XBell (XtDisplay (sv->X->TOPLEVEL), 50);
03998 SUMA_RETURNe;
03999 }
04000
04001
04002
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
04015 if (!SUMA_Engine (&list)) {
04016 fprintf(stderr, "Error %s: SUMA_Engine call failed.\n", FuncName);
04017 SUMA_RETURNe;
04018 }
04019
04020
04021 sv->ResetGLStateVariables = YUP;
04022 SUMA_handleRedisplay((XtPointer)sv->X->GLXAREA);
04023
04024 SUMA_RETURNe;
04025
04026 }
04027
04028
04029
04030
04031
04032
04033
04034 void SUMA_JumpFocusFace (char *s, void *data)
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
04051 if (SUMA_StringToNum (s, fv3, 1) != 1) {
04052 XBell (XtDisplay (sv->X->TOPLEVEL), 50);
04053 SUMA_RETURNe;
04054 }
04055
04056
04057
04058
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
04071 if (!SUMA_Engine (&list)) {
04072 fprintf(stderr, "Error %s: SUMA_Engine call failed.\n", FuncName);
04073 SUMA_RETURNe;
04074 }
04075
04076
04077 sv->ResetGLStateVariables = YUP;
04078 SUMA_handleRedisplay((XtPointer)sv->X->GLXAREA);
04079
04080 SUMA_RETURNe;
04081
04082 }
04083
04084
04085
04086
04087
04088
04089
04090
04091
04092
04093 void SUMA_HighlightBox (char *s, void *data)
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
04110 if (SUMA_StringToNum (s, fv15, 6) != 6) {
04111 XBell (XtDisplay (sv->X->TOPLEVEL), 50);
04112 SUMA_RETURNe;
04113 }
04114
04115
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 }