1 /*****************************************************************************
2 Major portions of this software are copyrighted by the Medical College
3 of Wisconsin, 1994-2000, and are released under the Gnu General Public
4 License, Version 2. See the file README.Copyright for details.
5 ******************************************************************************/
6
7 #undef MAIN
8
9 #include "afni.h"
10
11 #undef STAMPER
12 #define STAMPER(ar,ww) \
13 do{ if( (ar) != NULL ) \
14 (ar)->last_when[(ww)-RECEIVE_BASEVAL] = NI_clock_time() ; } while(0)
15
16 #undef STAMPCHECK
17 #if 1
18 #define STAMPCHECK(ar,ww) \
19 ( (ar) != NULL && NI_clock_time() > (ar)->last_when[(ww)-RECEIVE_BASEVAL]+33 )
20 #else
21 #define STAMPCHECK(ar,ww) ((ar) != NULL)
22 #endif
23
24 #undef STAMPSHOW
25 #define STAMPSHOW(iq,ar,ww) \
26 INFO_message("%d: last_when[%d] = %d", \
27 (iq),(ww)-RECEIVE_BASEVAL,(ar)->last_when[(ww)-RECEIVE_BASEVAL])
28
29 /*---------------------------------------------------------------------------*/
30 /*! Set up to have AFNI send data to a receiver (callback function):
31
32 rmask = bitwise OR (|) mask of RECEIVE_*_MASK (cf. afni.h)
33
34 cb = callback function to receive data; will be called like
35 cb( int why , int np , void *vp , void *cb_data )
36 where why = a RECEIVE_* code (cf. below)
37 np = count of data in vp (may be 0)
38 vp = pointer to data being sent (may be NULL)
39 cb_data = pointer passed into this routine (may be NULL)
40
41 cbname = string to identify callback func (for debugging)
42
43 why = RECEIVE_VIEWPOINT --> np = 3, vp = int *, pointing to
44 array of dataset voxel indices just
45 jumped to; vp[0] = x index, etc.
46
47 why = RECEIVE_REDISPLAY --> the user did something to cause
48 an image redisplay besides changing
49 the viewpoint. For this call, np and
50 vp are unused.
51
52 why = RECEIVE_FUNCDISPLAY --> the user did something to cause
53 the function display to change.
54 For this call, np and vp are unused.
55
56 why = RECEIVE_POINTS --> np = number of points drawn
57 vp = int **, pointer to array of arrays
58 of dataset voxel indices:
59 vp[0][i] = x index of point i
60 vp[1][i] = y index of point i
61 vp[2][i] = z index of point i,
62 vp[3][0] = sending mode
63 for i=0..np-1
64
65 why = RECEIVE_DRAWNOTICE --> the user drew something and that
66 information was sent to a receiver.
67 This call will occur AFTER all the
68 RECEIVE_POINTS calls have been done.
69 If no RECEIVE_POINTS calls are made,
70 then no RECEIVE_DRAWNOTICE calls will
71 be made either. For this call,
72 np and vp are unused.
73
74 why = RECEIVE_DSETCHANGE --> the user did something (like rescan
75 a session) that may have changed
76 dataset pointers. The receiving
77 routine should use dataset idcodes
78 to re-find the correct dataset
79 pointers. For this call, np and vp
80 are unused.
81
82 why = RECEIVE_CLOSURE --> the user closed the controller window,
83 which means that no more data will
84 be coming from it -- even if it is
85 reopened, AFNI_receive_init must be
86 called again. For this call, np and
87 vp are unused.
88
89 why = RECEIVE_ALTERATION --> the user changed something in the
90 controller -- the dataset, the
91 time index, the resampling, ....
92 This is basically a warning
93 message. For this call, np and
94 vp are unused.
95
96 why = RECEIVE_TIMEINDEX --> the time index changed in im3d;
97 for this call, np,vp are unused.
98 The new time index is in
99 im3d->vinfo->time_index
100
101 This function returns a non-negative int if all is OK -- this
102 value is the "key" that is used in calls to AFNI_receive_control
103 when you want to manipulate the status of this connection.
104
105 This function returns -1 if an error occurs.
106
107 Modified 29 Mar 1999 to allow for multiple receivers
108 (but drawing can only be done in one mode).
109 *//*-------------------------------------------------------------------------*/
110
AFNI_receive_init(Three_D_View * im3d,int rmask,gen_func * cb,void * cb_data,char * cbname)111 int AFNI_receive_init( Three_D_View *im3d , int rmask ,
112 gen_func *cb , void *cb_data , char *cbname )
113 {
114 int ir , kk ;
115
116 ENTRY("AFNI_receive_init") ;
117
118 /* check for invalid entries */
119
120 if( ! IM3D_VALID(im3d) || /* no good? */
121 cb == NULL || /* no receiver? */
122 (rmask & RECEIVE_ALL_MASK) == 0 ) RETURN(-1) ; /* no action? */
123
124 for( ir=0 ; ir < im3d->vinfo->num_receiver ; ir++ )
125 if( im3d->vinfo->receiver[ir] == NULL ) break ;
126
127 if( ir == im3d->vinfo->num_receiver ){
128 #if 0
129 fprintf(stderr,"AFNI_receive_init AFREALL() with ir=%d num_receiver=%d\n",
130 ir,im3d->vinfo->num_receiver ) ;
131 #endif
132 im3d->vinfo->receiver = AFREALL( im3d->vinfo->receiver, AFNI_receiver *, ir+1 );
133 im3d->vinfo->num_receiver ++ ;
134 }
135 im3d->vinfo->receiver[ir] = AFMALL( AFNI_receiver, sizeof(AFNI_receiver)) ;
136
137 im3d->vinfo->receiver[ir]->receiver_func = cb ;
138 im3d->vinfo->receiver[ir]->receiver_mask = rmask ;
139 im3d->vinfo->receiver[ir]->receiver_data = cb_data ;
140 for( kk=0 ; kk < RECEIVE_NUMVAL ; kk++ )
141 im3d->vinfo->receiver[ir]->last_when[kk] = -666 ; /* 08 Sep 2009 */
142
143 im3d->vinfo->receiver[ir]->receiver_funcname =
144 strdup( (cbname != NULL && *cbname != '\0') ? cbname : "[unknown func]" ) ;
145
146 AFNI_toggle_drawing( im3d ) ;
147
148 RETURN(ir) ; /* 15 Jun 1999: used to return 0, which is not correct! */
149 }
150
151 /*-------------------------------------------------------------------------*/
152 /*! Turn off all reception for this viewer.
153 ---------------------------------------------------------------------------*/
154
AFNI_receive_destroy(Three_D_View * im3d)155 void AFNI_receive_destroy( Three_D_View *im3d )
156 {
157 int ir ;
158
159 ENTRY("AFNI_receive_destroy") ;
160
161 if( !IM3D_VALID(im3d) ) EXRETURN ;
162
163 if( im3d->vinfo->receiver != NULL && im3d->vinfo->num_receiver > 0 ){
164
165 for( ir=0 ; ir < im3d->vinfo->num_receiver ; ir++ ){
166
167 if( im3d->vinfo->receiver[ir] != NULL ){
168 #if 0
169 im3d->vinfo->receiver[ir]->receiver_func(
170 RECEIVE_CLOSURE , 0 , NULL ,
171 im3d->vinfo->receiver[ir]->receiver_data ) ;
172 #else
173 AFNI_CALL_VOID_4ARG( im3d->vinfo->receiver[ir]->receiver_func ,
174 int,RECEIVE_CLOSURE , int,0 ,
175 void *,NULL ,
176 void *,im3d->vinfo->receiver[ir]->receiver_data ) ;
177 #endif
178
179 if( im3d->vinfo->receiver[ir]->receiver_funcname != NULL )
180 free( im3d->vinfo->receiver[ir]->receiver_funcname ) ;
181 free( im3d->vinfo->receiver[ir] ) ;
182 im3d->vinfo->receiver[ir] = NULL ;
183 }
184 }
185
186 im3d->vinfo->num_receiver = 0 ;
187 im3d->vinfo->drawing_enabled = 0 ;
188 im3d->vinfo->drawing_mode = DRAWING_LINES ; /* default */
189 }
190
191 EXRETURN ;
192 }
193
194 /*-------------------------------------------------------------------*/
195 /*! Control how the receiver works:
196 - code = indicates what action is
197 - arg = extra information, if code needs it
198
199 This function returns 0 if all is OK, and returns -1 if an error
200 occurs.
201 ---------------------------------------------------------------------*/
202
AFNI_receive_control(Three_D_View * im3d,int key,int code,void * arg)203 int AFNI_receive_control( Three_D_View *im3d, int key, int code, void *arg )
204 {
205 ENTRY("AFNI_receive_control") ;
206
207 /* check input for OK-osity */
208
209 if( ! IM3D_VALID(im3d) || im3d->vinfo->receiver == NULL ) RETURN(-1) ;
210 if( key < 0 || key >= im3d->vinfo->num_receiver ) RETURN(-1) ;
211 if( im3d->vinfo->receiver[key] == NULL ) RETURN(-1) ;
212
213 /* take appropriate actions */
214
215 switch( code ){
216
217 default: RETURN(-1) ;
218
219 case DRAWNOTICE_STARTUP:{ /* 30 Mar 1999 */
220 im3d->vinfo->receiver[key]->receiver_mask |= RECEIVE_DRAWNOTICE_MASK ;
221 }
222 break ;
223
224 case DRAWNOTICE_SHUTDOWN:{ /* 30 Mar 1999 */
225 im3d->vinfo->receiver[key]->receiver_mask &= (RECEIVE_ALL_MASK - RECEIVE_DRAWNOTICE_MASK) ;
226 }
227 break ;
228
229 case DSETCHANGE_STARTUP:{ /* 31 Mar 1999 */
230 im3d->vinfo->receiver[key]->receiver_mask |= RECEIVE_DSETCHANGE_MASK ;
231 }
232 break ;
233
234 case DSETCHANGE_SHUTDOWN:{ /* 30 Mar 1999 */
235 im3d->vinfo->receiver[key]->receiver_mask &= (RECEIVE_ALL_MASK - RECEIVE_DSETCHANGE_MASK) ;
236 }
237 break ;
238
239 case DRAWING_STARTUP:{
240 im3d->vinfo->receiver[key]->receiver_mask |= RECEIVE_DRAWING_MASK ;
241 AFNI_toggle_drawing( im3d ) ;
242 }
243 break ;
244
245 case DRAWING_SHUTDOWN:{
246 im3d->vinfo->receiver[key]->receiver_mask &= (RECEIVE_ALL_MASK - RECEIVE_DRAWING_MASK) ;
247 AFNI_toggle_drawing( im3d ) ;
248 }
249 break ;
250
251 case DRAWING_OVCINDEX:{
252 int ind = PTOI(arg) ;
253
254 if( ind <= 0 || ind >= im3d->dc->ovc->ncol_ov ){
255 RETURN(-1) ;
256 } else {
257 Pixel ppp = im3d->dc->ovc->pix_ov[ind] ;
258 drive_MCW_imseq( im3d->s123, isqDR_button2_pixel, (XtPointer)ppp ) ;
259 drive_MCW_imseq( im3d->s231, isqDR_button2_pixel, (XtPointer)ppp ) ;
260 drive_MCW_imseq( im3d->s312, isqDR_button2_pixel, (XtPointer)ppp ) ;
261 im3d->vinfo->drawing_pixel = ppp ;
262 }
263 }
264 break ;
265
266 case DRAWING_X11PIXEL:{
267 Pixel ppp = (Pixel) arg ;
268 drive_MCW_imseq( im3d->s123, isqDR_button2_pixel, (XtPointer)ppp ) ;
269 drive_MCW_imseq( im3d->s231, isqDR_button2_pixel, (XtPointer)ppp ) ;
270 drive_MCW_imseq( im3d->s312, isqDR_button2_pixel, (XtPointer)ppp ) ;
271 im3d->vinfo->drawing_pixel = ppp ;
272 }
273 break ;
274
275 case DRAWING_LINES:
276 case DRAWING_FILL:
277 case DRAWING_POINTS:
278 case DRAWING_NODRAW:{
279 im3d->vinfo->drawing_mode = code ;
280 drive_MCW_imseq( im3d->s123, isqDR_button2_mode, (XtPointer)ITOP(code) ) ;
281 drive_MCW_imseq( im3d->s231, isqDR_button2_mode, (XtPointer)ITOP(code) ) ;
282 drive_MCW_imseq( im3d->s312, isqDR_button2_mode, (XtPointer)ITOP(code) ) ;
283 }
284 break ;
285
286 case DRAWING_LINEWIDTH:{ /* 08 Oct 2002 */
287 int ww = PTOI(arg) ;
288 if( ww >= 0 ){
289 drive_MCW_imseq( im3d->s123, isqDR_button2_width, (XtPointer)ITOP(ww) ) ;
290 drive_MCW_imseq( im3d->s231, isqDR_button2_width, (XtPointer)ITOP(ww) ) ;
291 drive_MCW_imseq( im3d->s312, isqDR_button2_width, (XtPointer)ITOP(ww) ) ;
292 }
293 }
294 break ;
295
296 case VIEWPOINT_STARTUP:{
297 im3d->vinfo->receiver[key]->receiver_mask |= RECEIVE_VIEWPOINT_MASK ;
298 }
299 break ;
300
301 case VIEWPOINT_SHUTDOWN:{
302 im3d->vinfo->receiver[key]->receiver_mask &= (RECEIVE_ALL_MASK - RECEIVE_VIEWPOINT_MASK) ;
303 }
304 break ;
305
306 case REDISPLAY_STARTUP:{
307 im3d->vinfo->receiver[key]->receiver_mask |= RECEIVE_REDISPLAY_MASK ;
308 }
309 break ;
310
311 case REDISPLAY_SHUTDOWN:{
312 im3d->vinfo->receiver[key]->receiver_mask &= (RECEIVE_ALL_MASK - RECEIVE_REDISPLAY_MASK) ;
313 }
314 break ;
315
316 case FUNCDISPLAY_STARTUP:{
317 im3d->vinfo->receiver[key]->receiver_mask |= RECEIVE_FUNCDISPLAY_MASK ;
318 }
319 break ;
320
321 case FUNCDISPLAY_SHUTDOWN:{
322 im3d->vinfo->receiver[key]->receiver_mask &= (RECEIVE_ALL_MASK - RECEIVE_FUNCDISPLAY_MASK) ;
323 }
324 break ;
325
326 case OVERLAY_STARTUP:{
327 im3d->vinfo->receiver[key]->receiver_mask |= RECEIVE_OVERLAY_MASK ;
328 }
329 break ;
330
331 case OVERLAY_SHUTDOWN:{
332 im3d->vinfo->receiver[key]->receiver_mask &= (RECEIVE_ALL_MASK - RECEIVE_OVERLAY_MASK) ;
333 }
334 break ;
335
336 case TIMEINDEX_STARTUP:{
337 im3d->vinfo->receiver[key]->receiver_mask |= RECEIVE_TIMEINDEX_MASK ;
338 }
339 break ;
340
341 case TIMEINDEX_SHUTDOWN:{
342 im3d->vinfo->receiver[key]->receiver_mask &= (RECEIVE_ALL_MASK - RECEIVE_TIMEINDEX_MASK) ;
343 }
344 break ;
345
346 case EVERYTHING_SHUTDOWN:{
347 im3d->vinfo->receiver[key]->receiver_mask = 0 ;
348 AFNI_toggle_drawing( im3d ) ;
349 }
350 break ;
351
352 } /* end of switch on codes */
353
354 /* possibly remove this receiver, and maybe even all receivers */
355
356 if( im3d->vinfo->receiver[key]->receiver_mask == 0 ){ /* receiving nothing at all? */
357 int ir , nn=0 ;
358
359 if( im3d->vinfo->receiver[key]->receiver_funcname != NULL )
360 free( im3d->vinfo->receiver[key]->receiver_funcname ) ;
361
362 free( im3d->vinfo->receiver[key] ) ; /* toss this one fer shur */
363 im3d->vinfo->receiver[key] = NULL ;
364
365 for( ir=0 ; ir < im3d->vinfo->num_receiver ; ir++ ) /* see if any are left */
366 if( im3d->vinfo->receiver[ir] != NULL ) nn++ ;
367
368 if( nn == 0 ) im3d->vinfo->num_receiver = 0 ; /* if not, toss them all */
369 }
370
371 RETURN(0) ;
372 }
373
374 /*-------------------------------------------------------------------
375 Turn the drawing on or off for the given controller
376 ---------------------------------------------------------------------*/
377
AFNI_toggle_drawing(Three_D_View * im3d)378 void AFNI_toggle_drawing( Three_D_View *im3d )
379 {
380 int turn_on = 0 ;
381
382 ENTRY("AFNI_toggle_drawing") ;
383
384 if( ! IM3D_OPEN(im3d) ) EXRETURN ;
385
386 /* count up how many receivers want the drawing */
387
388 if( im3d->vinfo->receiver != NULL ){
389 int ir ;
390 for( ir=0 ; ir < im3d->vinfo->num_receiver ; ir++ )
391 if( im3d->vinfo->receiver[ir] != NULL &&
392 (im3d->vinfo->receiver[ir]->receiver_mask & RECEIVE_DRAWING_MASK) )
393 turn_on++ ;
394 }
395 im3d->vinfo->drawing_enabled = (turn_on != 0) ;
396
397 if( ! im3d->vinfo->drawing_enabled ){
398
399 /*-- quench the flames --*/
400
401 drive_MCW_imseq( im3d->s123 , isqDR_button2_disable , NULL ) ;
402 drive_MCW_imseq( im3d->s231 , isqDR_button2_disable , NULL ) ;
403 drive_MCW_imseq( im3d->s312 , isqDR_button2_disable , NULL ) ;
404
405 drive_MCW_grapher( im3d->g123 , graDR_button2_disable , NULL ) ;
406 drive_MCW_grapher( im3d->g231 , graDR_button2_disable , NULL ) ;
407 drive_MCW_grapher( im3d->g312 , graDR_button2_disable , NULL ) ;
408
409 } else {
410
411 /*-- come on baby, light my fire --*/
412
413 drive_MCW_imseq( im3d->s123 , isqDR_button2_enable , NULL ) ;
414 drive_MCW_imseq( im3d->s231 , isqDR_button2_enable , NULL ) ;
415 drive_MCW_imseq( im3d->s312 , isqDR_button2_enable , NULL ) ;
416
417 if( im3d->vinfo->drawing_pixel > 0 ){
418 drive_MCW_imseq( im3d->s123, isqDR_button2_pixel,
419 (XtPointer)im3d->vinfo->drawing_pixel ) ;
420 drive_MCW_imseq( im3d->s231, isqDR_button2_pixel,
421 (XtPointer)im3d->vinfo->drawing_pixel ) ;
422 drive_MCW_imseq( im3d->s312, isqDR_button2_pixel,
423 (XtPointer)im3d->vinfo->drawing_pixel ) ;
424 }
425
426 drive_MCW_imseq( im3d->s123, isqDR_button2_mode,
427 (XtPointer)ITOP(im3d->vinfo->drawing_mode) ) ;
428 drive_MCW_imseq( im3d->s231, isqDR_button2_mode,
429 (XtPointer)ITOP(im3d->vinfo->drawing_mode) ) ;
430 drive_MCW_imseq( im3d->s312, isqDR_button2_mode,
431 (XtPointer)ITOP(im3d->vinfo->drawing_mode) ) ;
432
433 drive_MCW_grapher( im3d->g123 , graDR_button2_enable , NULL ) ;
434 drive_MCW_grapher( im3d->g231 , graDR_button2_enable , NULL ) ;
435 drive_MCW_grapher( im3d->g312 , graDR_button2_enable , NULL ) ;
436
437 }
438
439 EXRETURN ;
440 }
441
442 /*-------------------------------------------------------------------
443 Send alteration message to all receivers
444 (they don't have to register for this information)
445 ---------------------------------------------------------------------*/
446
AFNI_process_alteration(Three_D_View * im3d)447 void AFNI_process_alteration( Three_D_View *im3d )
448 {
449 int ir ;
450
451 ENTRY("AFNI_process_alteration") ;
452
453 if( !IM3D_VALID(im3d) || im3d->vinfo->receiver == NULL ||
454 im3d->vinfo->num_receiver == 0 ) EXRETURN ;
455
456 for( ir=0 ; ir < im3d->vinfo->num_receiver ; ir++ ){
457 if( STAMPCHECK(im3d->vinfo->receiver[ir],RECEIVE_ALTERATION) ){
458 STATUS(im3d->vinfo->receiver[ir]->receiver_funcname) ;
459 #if 0
460 im3d->vinfo->receiver[ir]->receiver_func(
461 RECEIVE_ALTERATION , 0 , NULL ,
462 im3d->vinfo->receiver[ir]->receiver_data ) ;
463 #else
464 AFNI_CALL_VOID_4ARG( im3d->vinfo->receiver[ir]->receiver_func ,
465 int,RECEIVE_ALTERATION , int,0 ,
466 void *,NULL ,
467 void *,im3d->vinfo->receiver[ir]->receiver_data ) ;
468 #endif
469 STAMPER(im3d->vinfo->receiver[ir],RECEIVE_ALTERATION) ;
470 }
471 }
472
473 EXRETURN ;
474 }
475
476 /*-------------------------------------------------------------------
477 Send drawing notices to interested receivers.
478 Really used to indicate that the values in a dataset have changed.
479 ---------------------------------------------------------------------*/
480
AFNI_process_drawnotice(Three_D_View * im3d)481 void AFNI_process_drawnotice( Three_D_View *im3d )
482 {
483 int ir ;
484
485 ENTRY("AFNI_process_drawnotice") ;
486
487 if( !IM3D_VALID(im3d) || im3d->vinfo->receiver == NULL ||
488 im3d->vinfo->num_receiver == 0 ) EXRETURN ;
489
490 for( ir=0 ; ir < im3d->vinfo->num_receiver ; ir++ ){
491
492 if( STAMPCHECK(im3d->vinfo->receiver[ir],RECEIVE_DRAWNOTICE) &&
493 (im3d->vinfo->receiver[ir]->receiver_mask & RECEIVE_DRAWNOTICE_MASK) ){
494
495 STATUS(im3d->vinfo->receiver[ir]->receiver_funcname) ;
496 #if 0
497 im3d->vinfo->receiver[ir]->receiver_func(
498 RECEIVE_DRAWNOTICE , 0 , NULL ,
499 im3d->vinfo->receiver[ir]->receiver_data ) ;
500 #else
501 AFNI_CALL_VOID_4ARG( im3d->vinfo->receiver[ir]->receiver_func ,
502 int,RECEIVE_DRAWNOTICE , int,0 ,
503 void *,NULL ,
504 void *,im3d->vinfo->receiver[ir]->receiver_data ) ;
505 #endif
506 STAMPER(im3d->vinfo->receiver[ir],RECEIVE_DRAWNOTICE) ;
507 }
508 }
509
510 EXRETURN ;
511 }
512
513 /*-------------------------------------------------------------------
514 Send dset change notices to interested receivers
515 ---------------------------------------------------------------------*/
516
AFNI_process_dsetchange(Three_D_View * im3d)517 void AFNI_process_dsetchange( Three_D_View *im3d )
518 {
519 int ir ;
520
521 ENTRY("AFNI_process_dsetchange") ;
522
523 if( !IM3D_VALID(im3d) || im3d->vinfo->receiver == NULL ||
524 im3d->vinfo->num_receiver == 0 ) EXRETURN ;
525
526 for( ir=0 ; ir < im3d->vinfo->num_receiver ; ir++ ){
527
528 if( STAMPCHECK(im3d->vinfo->receiver[ir],RECEIVE_DSETCHANGE) &&
529 (im3d->vinfo->receiver[ir]->receiver_mask & RECEIVE_DSETCHANGE_MASK) ){
530
531 STATUS(im3d->vinfo->receiver[ir]->receiver_funcname) ;
532 #if 0
533 im3d->vinfo->receiver[ir]->receiver_func(
534 RECEIVE_DSETCHANGE , 0 , NULL ,
535 im3d->vinfo->receiver[ir]->receiver_data ) ;
536 #else
537 AFNI_CALL_VOID_4ARG( im3d->vinfo->receiver[ir]->receiver_func ,
538 int,RECEIVE_DSETCHANGE , int,0 ,
539 void *,NULL ,
540 void *,im3d->vinfo->receiver[ir]->receiver_data ) ;
541 #endif
542 STAMPER(im3d->vinfo->receiver[ir],RECEIVE_DSETCHANGE) ;
543 }
544 }
545
546 EXRETURN ;
547 }
548
549 /*-------------------------------------------------------------------
550 Send new (i,j,k) coordinates to all receivers that care
551 ---------------------------------------------------------------------*/
552
AFNI_process_viewpoint(Three_D_View * im3d)553 void AFNI_process_viewpoint( Three_D_View *im3d )
554 {
555 int ir , ijk[3] ;
556
557 ENTRY("AFNI_process_viewpoint") ;
558
559 if( !IM3D_VALID(im3d) || im3d->vinfo->receiver == NULL ||
560 im3d->vinfo->num_receiver == 0 ) EXRETURN ;
561
562 #if 0
563 if( AFNI_yesenv("BOBCOX") ){
564 INFO_message("AFNI_process_viewpoint"); DBG_traceback();
565 }
566 #endif
567
568 ijk[0] = im3d->vinfo->i1 ;
569 ijk[1] = im3d->vinfo->j2 ;
570 ijk[2] = im3d->vinfo->k3 ;
571
572 for( ir=0 ; ir < im3d->vinfo->num_receiver ; ir++ ){
573 if( STAMPCHECK(im3d->vinfo->receiver[ir],RECEIVE_VIEWPOINT) &&
574 (im3d->vinfo->receiver[ir]->receiver_mask & RECEIVE_VIEWPOINT_MASK) ){
575
576 #if 0
577 if( AFNI_yesenv("BOBCOX") ) STAMPSHOW(ir,im3d->vinfo->receiver[ir],RECEIVE_FUNCDISPLAY) ;
578 #endif
579
580 STATUS(im3d->vinfo->receiver[ir]->receiver_funcname) ;
581 #if 0
582 im3d->vinfo->receiver[ir]->receiver_func(
583 RECEIVE_VIEWPOINT , 3 , ijk ,
584 im3d->vinfo->receiver[ir]->receiver_data ) ;
585 #else
586 AFNI_CALL_VOID_4ARG( im3d->vinfo->receiver[ir]->receiver_func ,
587 int,RECEIVE_VIEWPOINT , int,3 ,
588 void *,ijk ,
589 void *,im3d->vinfo->receiver[ir]->receiver_data ) ;
590 #endif
591 STAMPER(im3d->vinfo->receiver[ir],RECEIVE_VIEWPOINT) ;
592
593 #if 0
594 if( AFNI_yesenv("BOBCOX") ) STAMPSHOW(ir,im3d->vinfo->receiver[ir],RECEIVE_VIEWPOINT) ;
595 #endif
596 }
597 }
598
599 EXRETURN ;
600 }
601
602 /*-------------------------------------------------------------------*/
603 /*! Send time index change notice to receivers that care [29 Jan 2003]
604 ---------------------------------------------------------------------*/
605
AFNI_process_timeindex(Three_D_View * im3d)606 void AFNI_process_timeindex( Three_D_View *im3d )
607 {
608 int ir ;
609
610 ENTRY("AFNI_process_timeindex") ;
611
612 if( !IM3D_VALID(im3d) || im3d->vinfo->receiver == NULL ||
613 im3d->vinfo->num_receiver == 0 ) EXRETURN ;
614
615 for( ir=0 ; ir < im3d->vinfo->num_receiver ; ir++ ){
616 if( STAMPCHECK(im3d->vinfo->receiver[ir],RECEIVE_TIMEINDEX) &&
617 (im3d->vinfo->receiver[ir]->receiver_mask & RECEIVE_TIMEINDEX_MASK) ){
618
619 STATUS(im3d->vinfo->receiver[ir]->receiver_funcname) ;
620 #if 0
621 im3d->vinfo->receiver[ir]->receiver_func(
622 RECEIVE_TIMEINDEX , 0 , NULL ,
623 im3d->vinfo->receiver[ir]->receiver_data ) ;
624 #else
625 AFNI_CALL_VOID_4ARG( im3d->vinfo->receiver[ir]->receiver_func ,
626 int,RECEIVE_TIMEINDEX , int,0 ,
627 void *,NULL ,
628 void *,im3d->vinfo->receiver[ir]->receiver_data ) ;
629 #endif
630 STAMPER(im3d->vinfo->receiver[ir],RECEIVE_TIMEINDEX) ;
631 }
632 }
633
634 EXRETURN ;
635 }
636
637 /*-------------------------------------------------------------------*/
638 /*! Send redisplay notification to receivers that care [04 Mar 2002].
639 ---------------------------------------------------------------------*/
640
AFNI_process_redisplay(Three_D_View * im3d)641 void AFNI_process_redisplay( Three_D_View *im3d )
642 {
643 int ir ;
644
645 ENTRY("AFNI_process_redisplay") ;
646
647 if( !IM3D_VALID(im3d) || im3d->vinfo->receiver == NULL ||
648 im3d->vinfo->num_receiver == 0 ) EXRETURN ;
649
650 for( ir=0 ; ir < im3d->vinfo->num_receiver ; ir++ ){
651 if( STAMPCHECK(im3d->vinfo->receiver[ir],RECEIVE_REDISPLAY) &&
652 (im3d->vinfo->receiver[ir]->receiver_mask & RECEIVE_REDISPLAY_MASK) ){
653
654 STATUS(im3d->vinfo->receiver[ir]->receiver_funcname) ;
655 #if 0
656 im3d->vinfo->receiver[ir]->receiver_func(
657 RECEIVE_REDISPLAY , 0 , NULL ,
658 im3d->vinfo->receiver[ir]->receiver_data ) ;
659 #else
660 AFNI_CALL_VOID_4ARG( im3d->vinfo->receiver[ir]->receiver_func ,
661 int,RECEIVE_REDISPLAY , int,0 ,
662 void *,NULL ,
663 void *,im3d->vinfo->receiver[ir]->receiver_data ) ;
664 #endif
665 STAMPER(im3d->vinfo->receiver[ir],RECEIVE_REDISPLAY) ;
666 }
667 }
668
669 EXRETURN ;
670 }
671
672 /*-------------------------------------------------------------------*/
673 /*! Send funcdisplay notification to receivers that care [05 Mar 2002].
674 ---------------------------------------------------------------------*/
675
AFNI_process_funcdisplay(Three_D_View * im3d)676 void AFNI_process_funcdisplay( Three_D_View *im3d )
677 {
678 int ir ;
679
680 ENTRY("AFNI_process_funcdisplay") ;
681
682 if( !IM3D_VALID(im3d) || im3d->vinfo->receiver == NULL ||
683 im3d->vinfo->num_receiver == 0 ) EXRETURN ;
684
685 #if 0
686 if( AFNI_yesenv("BOBCOX") ){
687 INFO_message("AFNI_process_funcdisplay"); DBG_traceback();
688 }
689 #endif
690
691 for( ir=0 ; ir < im3d->vinfo->num_receiver ; ir++ ){
692 if( STAMPCHECK(im3d->vinfo->receiver[ir],RECEIVE_FUNCDISPLAY) &&
693 (im3d->vinfo->receiver[ir]->receiver_mask & RECEIVE_FUNCDISPLAY_MASK) ){
694
695 #if 0
696 if( AFNI_yesenv("BOBCOX") ) STAMPSHOW(ir,im3d->vinfo->receiver[ir],RECEIVE_FUNCDISPLAY) ;
697 #endif
698
699 STATUS(im3d->vinfo->receiver[ir]->receiver_funcname) ;
700 #if 0
701 im3d->vinfo->receiver[ir]->receiver_func(
702 RECEIVE_FUNCDISPLAY , 0 , NULL ,
703 im3d->vinfo->receiver[ir]->receiver_data ) ;
704 #else
705 AFNI_CALL_VOID_4ARG( im3d->vinfo->receiver[ir]->receiver_func ,
706 int,RECEIVE_FUNCDISPLAY , int,0 ,
707 void *,NULL ,
708 void *,im3d->vinfo->receiver[ir]->receiver_data ) ;
709 #endif
710 STAMPER(im3d->vinfo->receiver[ir],RECEIVE_FUNCDISPLAY) ;
711
712 #if 0
713 if( AFNI_yesenv("BOBCOX") ) STAMPSHOW(ir,im3d->vinfo->receiver[ir],RECEIVE_FUNCDISPLAY) ;
714 #endif
715 }
716 }
717
718 EXRETURN ;
719 }
720
721 /*-------------------------------------------------------------------*/
722 /*! Process drawn points:
723 - npts = number of points sent in
724 - mode = type of points to follow:
725 - PLANAR_MODE + zz ==> axis zz is fixed, for zz=1,2,3
726 - SINGLE_MODE + zz ==> one point only, clicked in a
727 window with zz fixed
728 - THREED_MODE ==> points are in 3D (not planar)
729 (not currently possible)
730 - UNDO_MODE ==> undo last drawing action
731 - INCVAL_MODE ==> add 1 to drawing value
732 - DECVAL_MODE ==> subtract 1 from drawing value
733
734 - xd[i] = x index of point i, for i=0..npts-1
735 - yd[i] = y index of point i, for i=0..npts-1
736 - zd[i] = z index of point i, for i=0..npts-1
737
738 These indices are with respect to the dataset brick axes.
739 ---------------------------------------------------------------------*/
740
AFNI_process_drawing(Three_D_View * im3d,int mode,int npts,int * xd,int * yd,int * zd)741 void AFNI_process_drawing( Three_D_View *im3d , int mode ,
742 int npts , int *xd , int *yd , int *zd )
743 {
744 int ii , nn , ir , nsent ;
745 int *vp[4] , *xn=NULL , *yn=NULL , *zn=NULL ;
746
747 ENTRY("AFNI_process_drawing") ;
748
749 if( !IM3D_VALID(im3d) || im3d->vinfo->receiver == NULL ||
750 im3d->vinfo->num_receiver == 0 ||
751 npts < 0 || im3d->vinfo->drawing_enabled == 0 ) EXRETURN ;
752
753 if(PRINT_TRACING){
754 char str[256] ; sprintf(str,"received %d points",npts) ; STATUS(str) ;
755 }
756
757 /*-- if no further treatment is needed,
758 just flag input data to be set to receiver --*/
759
760 if( im3d->vinfo->drawing_mode == DRAWING_POINTS ||
761 im3d->vinfo->drawing_mode == DRAWING_NODRAW || npts <= 1 ){
762
763 xn = xd ; yn = yd ; zn = zd ; nn = npts ;
764 }
765
766 /*-- must fill in the lines:
767 create arrays xn, yn, zn of length nn --*/
768
769 else if( im3d->vinfo->drawing_mode == DRAWING_LINES ){
770
771 AFNI_3d_linefill( npts , xd,yd,zd , &nn , &xn , &yn , &zn ) ;
772 }
773
774 /*-- must fill in the polygon --*/
775
776 else if( im3d->vinfo->drawing_mode == DRAWING_FILL ){
777
778 /* this just fills the lines like above --
779 need to write a real polygon filling routine? */
780
781 AFNI_3d_linefill( npts , xd,yd,zd , &nn , &xn , &yn , &zn ) ;
782 }
783
784 /*-- send data to receivers that want it --*/
785
786 #if 0
787 fprintf(stderr,"Sending %d points to receiver\n",nn) ;
788 #endif
789
790 vp[3] = &mode ; /* how the points are arranged */
791
792 vp[0] = xn ; vp[1] = yn ; vp[2] = zn ;
793
794 for( nsent=ir=0 ; ir < im3d->vinfo->num_receiver ; ir++ ){
795
796 if( STAMPCHECK(im3d->vinfo->receiver[ir],RECEIVE_POINTS) &&
797 (im3d->vinfo->receiver[ir]->receiver_mask & RECEIVE_DRAWING_MASK) ){
798
799 STATUS(im3d->vinfo->receiver[ir]->receiver_funcname) ;
800 #if 0
801 im3d->vinfo->receiver[ir]->receiver_func(
802 RECEIVE_POINTS , nn ,
803 (void *) vp , im3d->vinfo->receiver[ir]->receiver_data ) ;
804 #else
805 AFNI_CALL_VOID_4ARG( im3d->vinfo->receiver[ir]->receiver_func ,
806 int,RECEIVE_POINTS , int,nn ,
807 void *,vp ,
808 void *,im3d->vinfo->receiver[ir]->receiver_data ) ;
809 #endif
810 nsent++ ;
811 STAMPER(im3d->vinfo->receiver[ir],RECEIVE_POINTS) ;
812 }
813 }
814
815 /* 30 Mar 1999: also send DRAWNOTICE to receivers that like this stuff */
816
817 if( nsent > 0 ) AFNI_process_drawnotice( im3d ) ;
818
819 /*-- free any created arrays --*/
820
821 if( xn != xd ){ free(xn); free(yn); free(zn); }
822 EXRETURN ;
823 }
824
825 /*--------------------------------------------------------------------
826 3D line filler-inner -- quick and dirty.
827 The output arrays (*xout, *yout, *zout) should be freed when
828 their usefulness is over.
829 ----------------------------------------------------------------------*/
830
AFNI_3d_linefill(int nin,int * xin,int * yin,int * zin,int * nout,int ** xout,int ** yout,int ** zout)831 void AFNI_3d_linefill( int nin , int * xin , int * yin , int * zin ,
832 int * nout , int ** xout , int ** yout , int ** zout )
833 {
834 int * xut , * yut , * zut ;
835 int nut , iin , jout , nall ;
836 int x1,y1,z1 , x2,y2,z2 , dx,dy,dz , adx,ady,adz , xlast,ylast,zlast ;
837 float fdxyz , fdx,fdy,fdz , fx,fy,fz ;
838
839 ENTRY("AFNI_3d_linefill") ;
840
841 /* sanity check */
842
843 if( nin <= 0 || xin == NULL || yin == NULL || zin == NULL ){
844 *nout = 0 ; *xout = *yout = *zout = NULL ; EXRETURN ;
845 }
846
847 /* trivial case */
848
849 if( nin == 1 ){
850 nut = 1 ; *nout = nut ;
851 xut = (int *) malloc(sizeof(int)) ; xut[0] = xin[0] ; *xout = xut ;
852 yut = (int *) malloc(sizeof(int)) ; yut[0] = yin[0] ; *yout = yut ;
853 zut = (int *) malloc(sizeof(int)) ; zut[0] = zin[0] ; *zout = zut ;
854 EXRETURN ;
855 }
856
857 /* setup to scan through lines */
858
859 nall = nin ;
860 xut = (int *) malloc( sizeof(int) * nall ) ;
861 yut = (int *) malloc( sizeof(int) * nall ) ;
862 zut = (int *) malloc( sizeof(int) * nall ) ;
863 nut = 0 ;
864
865 #undef ADDPT
866 #define ADDPT(i,j,k) \
867 do{ if( nut == nall ){ \
868 nall += 128 ; \
869 xut = (int *) realloc( xut , sizeof(int) * nall ) ; \
870 yut = (int *) realloc( yut , sizeof(int) * nall ) ; \
871 zut = (int *) realloc( zut , sizeof(int) * nall ) ; \
872 } \
873 xut[nut] = xlast = (i) ; \
874 yut[nut] = ylast = (j) ; \
875 zut[nut] = zlast = (k) ; nut++ ; } while(0)
876
877 /* draw line from point #iin to #iin+1 */
878
879 x2 = xin[0] ; y2 = yin[0] ; z2 = zin[0] ;
880 for( iin=0 ; iin < nin-1 ; iin++ ){
881 x1 = x2 ; y1 = y2 ; z1 = z2 ;
882 x2 = xin[iin+1] ; y2 = yin[iin+1] ; z2 = zin[iin+1] ;
883 dx = x2 - x1 ; dy = y2 - y1 ; dz = z2 - z1 ;
884 adx = abs(dx) ; ady = abs(dy) ; adz = abs(dz) ;
885
886 /* add start point to list */
887
888 ADDPT(x1,y1,z1) ;
889
890 /* special case: neighbors ==> skip to next line */
891
892 if( adx <= 1 && ady <= 1 && adz <= 1 ) continue ;
893
894 /* OK, we have to do work (moan) */
895
896 #define SFRAC 0.495
897
898 fdxyz = adx + ady + adz ; /* Manhattan distance */
899 fdx = SFRAC * dx / fdxyz ; /* steps */
900 fdy = SFRAC * dy / fdxyz ;
901 fdz = SFRAC * dz / fdxyz ;
902
903 /* step thru in small increments,
904 adding new integer points, and stopping at line's end */
905
906 #if 0
907 fprintf(stderr,"linefill: from %d %d %d to %d %d %d\n",
908 x1,y1,z1 , x2,y2,z2 ) ;
909 #endif
910
911 fx = x1+fdx+0.499 ; fy = y1+fdy+0.499 ; fz = z1+fdz+0.499 ;
912 do {
913 fx = fx + fdx ; fy = fy + fdy ; fz = fz + fdz ;
914 x1 = (int) fx ; y1 = (int) fy ; z1 = (int) fz ;
915
916 #if 0
917 fprintf(stderr," at %d %d %d\n",x1,y1,z1) ;
918 #endif
919
920 if( x1 == x2 && y1 == y2 && z1 == z2 ) break ;
921
922 if( x1 != xlast || y1 != ylast || z1 != zlast ) ADDPT(x1,y1,z1) ;
923 } while(1) ;
924
925 } /* end of loop over lines */
926
927 ADDPT(x2,y2,z2) ; /* add last point */
928
929 *nout = nut ; *xout = xut ; *yout = yut ; *zout = zut ;
930 EXRETURN ;
931 }
932
933