/*****************************************************************************
Major portions of this software are copyrighted by the Medical College
of Wisconsin, 1994-2000, and are released under the Gnu General Public
License, Version 2. See the file README.Copyright for details.
******************************************************************************/
#undef MAIN
#include "afni.h"
/*-------------------------------------------------------------------*/
/*! Set up to have AFNI send data to a receiver:
rmask = bitwise OR (|) mask of RECEIVE_*_MASK (cf. afni.h)
cb = callback function to receive data; will be called like
cb( int why , int np , void * vp , void * cb_data )
where why = a RECEIVE_* code (cf. below)
np = count of data in vp (may be 0)
vp = pointer to data being sent (may be NULL)
cb_data = pointer passed into this routine
cbname = string to identify callback func (for debugging)
why = RECEIVE_VIEWPOINT --> np = 3, vp = int *, pointing to
array of dataset voxel indices just
jumped to; vp[0] = x index, etc.
why = RECEIVE_REDISPLAY --> the user did something to cause
an image redisplay besides changing
the viewpoint. For this call, np and
vp are unused.
why = RECEIVE_FUNCDISPLAY --> the user did something to cause
the function display to change.
For this call, np and vp are unused.
why = RECEIVE_POINTS --> np = number of points drawn
vp = int **, pointer to array of arrays
of dataset voxel indices:
vp[0][i] = x index of point i
vp[1][i] = y index of point i
vp[2][i] = z index of point i,
vp[3][0] = sending mode
for i=0..np-1
why = RECEIVE_DRAWNOTICE --> the user drew something and that
information was sent to a receiver.
This call will occur AFTER all the
RECEIVE_POINTS calls have been done.
If no RECEIVE_POINTS calls are made,
then no RECEIVE_DRAWNOTICE calls will
be made either. For this call,
np and vp are unused.
why = RECEIVE_DSETCHANGE --> the user did something (like rescan
a session) that may have changed
dataset pointers. The receiving
routine should use dataset idcodes
to re-find the correct dataset
pointers. For this call, np and vp
are unused.
why = RECEIVE_CLOSURE --> the user closed the controller window,
which means that no more data will
be coming from it -- even if it is
reopened, AFNI_receive_init must be
called again. For this call, np and
vp are unused.
why = RECEIVE_ALTERATION --> the user changed something in the
controller -- the dataset, the
time index, the resampling, ....
This is basically a warning
message. For this call, np and
vp are unused.
why = RECEIVE_TIMEINDEX --> the time index changed in im3d;
for this call, np,vp are unused.
The new time index is in
im3d->vinfo->time_index
This function returns a non-negative int if all is OK -- this
value is the "key" that is used in calls to AFNI_receive_control
when you want to manipulate the status of this connection.
This function returns -1 if an error occurs.
Modified 29 Mar 1999 to allow for multiple receivers
(but drawing can only be done in one mode).
---------------------------------------------------------------------*/
int AFNI_receive_init( Three_D_View * im3d , int rmask ,
gen_func * cb , void * cb_data , char * cbname )
{
int ir ;
ENTRY("AFNI_receive_init") ;
/* check for invalid entries */
if( ! IM3D_VALID(im3d) || /* no good? */
cb == NULL || /* no receiver? */
(rmask & RECEIVE_ALL_MASK) == 0 ) RETURN(-1) ; /* no action? */
for( ir=0 ; ir < im3d->vinfo->num_receiver ; ir++ )
if( im3d->vinfo->receiver[ir] == NULL ) break ;
if( ir == im3d->vinfo->num_receiver ){
#if 0
fprintf(stderr,"AFNI_receive_init AFREALL() with ir=%d num_receiver=%d\n",
ir,im3d->vinfo->num_receiver ) ;
#endif
im3d->vinfo->receiver = AFREALL( im3d->vinfo->receiver, AFNI_receiver *, ir+1 );
im3d->vinfo->num_receiver ++ ;
}
im3d->vinfo->receiver[ir] = AFMALL( AFNI_receiver, sizeof(AFNI_receiver)) ;
im3d->vinfo->receiver[ir]->receiver_func = cb ;
im3d->vinfo->receiver[ir]->receiver_mask = rmask ;
im3d->vinfo->receiver[ir]->receiver_data = cb_data ;
im3d->vinfo->receiver[ir]->receiver_funcname =
strdup( (cbname != NULL) ? cbname : "[unknown func]" ) ;
AFNI_toggle_drawing( im3d ) ;
RETURN(ir) ; /* 15 Jun 1999: used to return 0, which is not correct! */
}
/*-------------------------------------------------------------------------*/
/*! Turn off all reception for this viewer.
---------------------------------------------------------------------------*/
void AFNI_receive_destroy( Three_D_View * im3d )
{
int ir ;
ENTRY("AFNI_receive_destroy") ;
if( !IM3D_VALID(im3d) ) EXRETURN ;
if( im3d->vinfo->receiver != NULL && im3d->vinfo->num_receiver > 0 ){
for( ir=0 ; ir < im3d->vinfo->num_receiver ; ir++ ){
if( im3d->vinfo->receiver[ir] != NULL ){
#if 0
im3d->vinfo->receiver[ir]->receiver_func(
RECEIVE_CLOSURE , 0 , NULL ,
im3d->vinfo->receiver[ir]->receiver_data ) ;
#else
AFNI_CALL_VOID_4ARG( im3d->vinfo->receiver[ir]->receiver_func ,
int,RECEIVE_CLOSURE , int,0 ,
void *,NULL ,
void *,im3d->vinfo->receiver[ir]->receiver_data ) ;
#endif
if( im3d->vinfo->receiver[ir]->receiver_funcname != NULL )
free( im3d->vinfo->receiver[ir]->receiver_funcname ) ;
free( im3d->vinfo->receiver[ir] ) ;
im3d->vinfo->receiver[ir] = NULL ;
}
}
im3d->vinfo->num_receiver = 0 ;
im3d->vinfo->drawing_enabled = 0 ;
im3d->vinfo->drawing_mode = DRAWING_LINES ; /* default */
}
EXRETURN ;
}
/*-------------------------------------------------------------------*/
/*! Control how the receiver works:
- code = indicates what action is
- arg = extra information, if code needs it
This function returns 0 if all is OK, and returns -1 if an error
occurs.
---------------------------------------------------------------------*/
int AFNI_receive_control( Three_D_View *im3d, int key, int code, void *arg )
{
ENTRY("AFNI_receive_control") ;
/* check input for OK-osity */
if( ! IM3D_VALID(im3d) || im3d->vinfo->receiver == NULL ) RETURN(-1) ;
if( key < 0 || key >= im3d->vinfo->num_receiver ) RETURN(-1) ;
if( im3d->vinfo->receiver[key] == NULL ) RETURN(-1) ;
/* take appropriate actions */
switch( code ){
default: RETURN(-1) ;
case DRAWNOTICE_STARTUP:{ /* 30 Mar 1999 */
im3d->vinfo->receiver[key]->receiver_mask |= RECEIVE_DRAWNOTICE_MASK ;
}
break ;
case DRAWNOTICE_SHUTDOWN:{ /* 30 Mar 1999 */
im3d->vinfo->receiver[key]->receiver_mask &= (RECEIVE_ALL_MASK - RECEIVE_DRAWNOTICE_MASK) ;
}
break ;
case DSETCHANGE_STARTUP:{ /* 31 Mar 1999 */
im3d->vinfo->receiver[key]->receiver_mask |= RECEIVE_DSETCHANGE_MASK ;
}
break ;
case DSETCHANGE_SHUTDOWN:{ /* 30 Mar 1999 */
im3d->vinfo->receiver[key]->receiver_mask &= (RECEIVE_ALL_MASK - RECEIVE_DSETCHANGE_MASK) ;
}
break ;
case DRAWING_STARTUP:{
im3d->vinfo->receiver[key]->receiver_mask |= RECEIVE_DRAWING_MASK ;
AFNI_toggle_drawing( im3d ) ;
}
break ;
case DRAWING_SHUTDOWN:{
im3d->vinfo->receiver[key]->receiver_mask &= (RECEIVE_ALL_MASK - RECEIVE_DRAWING_MASK) ;
AFNI_toggle_drawing( im3d ) ;
}
break ;
case DRAWING_OVCINDEX:{
int ind = (int) arg ;
if( ind <= 0 || ind >= im3d->dc->ovc->ncol_ov ){
RETURN(-1) ;
} else {
Pixel ppp = im3d->dc->ovc->pix_ov[ind] ;
drive_MCW_imseq( im3d->s123, isqDR_button2_pixel, (XtPointer)ppp ) ;
drive_MCW_imseq( im3d->s231, isqDR_button2_pixel, (XtPointer)ppp ) ;
drive_MCW_imseq( im3d->s312, isqDR_button2_pixel, (XtPointer)ppp ) ;
im3d->vinfo->drawing_pixel = ppp ;
}
}
break ;
case DRAWING_X11PIXEL:{
Pixel ppp = (Pixel) arg ;
drive_MCW_imseq( im3d->s123, isqDR_button2_pixel, (XtPointer)ppp ) ;
drive_MCW_imseq( im3d->s231, isqDR_button2_pixel, (XtPointer)ppp ) ;
drive_MCW_imseq( im3d->s312, isqDR_button2_pixel, (XtPointer)ppp ) ;
im3d->vinfo->drawing_pixel = ppp ;
}
break ;
case DRAWING_LINES:
case DRAWING_FILL:
case DRAWING_POINTS:
case DRAWING_NODRAW:{
im3d->vinfo->drawing_mode = code ;
drive_MCW_imseq( im3d->s123, isqDR_button2_mode, (XtPointer)code ) ;
drive_MCW_imseq( im3d->s231, isqDR_button2_mode, (XtPointer)code ) ;
drive_MCW_imseq( im3d->s312, isqDR_button2_mode, (XtPointer)code ) ;
}
break ;
case DRAWING_LINEWIDTH:{ /* 08 Oct 2002 */
int ww = (int) arg ;
if( ww >= 0 ){
drive_MCW_imseq( im3d->s123, isqDR_button2_width, (XtPointer)ww ) ;
drive_MCW_imseq( im3d->s231, isqDR_button2_width, (XtPointer)ww ) ;
drive_MCW_imseq( im3d->s312, isqDR_button2_width, (XtPointer)ww ) ;
}
}
break ;
case VIEWPOINT_STARTUP:{
im3d->vinfo->receiver[key]->receiver_mask |= RECEIVE_VIEWPOINT_MASK ;
}
break ;
case VIEWPOINT_SHUTDOWN:{
im3d->vinfo->receiver[key]->receiver_mask &= (RECEIVE_ALL_MASK - RECEIVE_VIEWPOINT_MASK) ;
}
break ;
case REDISPLAY_STARTUP:{
im3d->vinfo->receiver[key]->receiver_mask |= RECEIVE_REDISPLAY_MASK ;
}
break ;
case REDISPLAY_SHUTDOWN:{
im3d->vinfo->receiver[key]->receiver_mask &= (RECEIVE_ALL_MASK - RECEIVE_REDISPLAY_MASK) ;
}
break ;
case FUNCDISPLAY_STARTUP:{
im3d->vinfo->receiver[key]->receiver_mask |= RECEIVE_FUNCDISPLAY_MASK ;
}
break ;
case FUNCDISPLAY_SHUTDOWN:{
im3d->vinfo->receiver[key]->receiver_mask &= (RECEIVE_ALL_MASK - RECEIVE_FUNCDISPLAY_MASK) ;
}
break ;
case OVERLAY_STARTUP:{
im3d->vinfo->receiver[key]->receiver_mask |= RECEIVE_OVERLAY_MASK ;
}
break ;
case OVERLAY_SHUTDOWN:{
im3d->vinfo->receiver[key]->receiver_mask &= (RECEIVE_ALL_MASK - RECEIVE_OVERLAY_MASK) ;
}
break ;
case TIMEINDEX_STARTUP:{
im3d->vinfo->receiver[key]->receiver_mask |= RECEIVE_TIMEINDEX_MASK ;
}
break ;
case TIMEINDEX_SHUTDOWN:{
im3d->vinfo->receiver[key]->receiver_mask &= (RECEIVE_ALL_MASK - RECEIVE_TIMEINDEX_MASK) ;
}
break ;
case EVERYTHING_SHUTDOWN:{
im3d->vinfo->receiver[key]->receiver_mask = 0 ;
AFNI_toggle_drawing( im3d ) ;
}
break ;
} /* end of switch on codes */
/* possibly remove this receiver, and maybe even all receivers */
if( im3d->vinfo->receiver[key]->receiver_mask == 0 ){ /* receiving nothing at all? */
int ir , nn=0 ;
if( im3d->vinfo->receiver[key]->receiver_funcname != NULL )
free( im3d->vinfo->receiver[key]->receiver_funcname ) ;
free( im3d->vinfo->receiver[key] ) ; /* toss this one fer shur */
im3d->vinfo->receiver[key] = NULL ;
for( ir=0 ; ir < im3d->vinfo->num_receiver ; ir++ ) /* see if any are left */
if( im3d->vinfo->receiver[ir] != NULL ) nn++ ;
if( nn == 0 ) im3d->vinfo->num_receiver = 0 ; /* if not, toss them all */
}
RETURN(0) ;
}
/*-------------------------------------------------------------------
Turn the drawing on or off for the given controller
---------------------------------------------------------------------*/
void AFNI_toggle_drawing( Three_D_View * im3d )
{
int turn_on = 0 ;
ENTRY("AFNI_toggle_drawing") ;
if( ! IM3D_OPEN(im3d) ) EXRETURN ;
/* count up how many receivers want the drawing */
if( im3d->vinfo->receiver != NULL ){
int ir ;
for( ir=0 ; ir < im3d->vinfo->num_receiver ; ir++ )
if( im3d->vinfo->receiver[ir] != NULL &&
(im3d->vinfo->receiver[ir]->receiver_mask & RECEIVE_DRAWING_MASK) )
turn_on++ ;
}
im3d->vinfo->drawing_enabled = (turn_on != 0) ;
if( ! im3d->vinfo->drawing_enabled ){
/*-- quench the flames --*/
drive_MCW_imseq( im3d->s123 , isqDR_button2_disable , NULL ) ;
drive_MCW_imseq( im3d->s231 , isqDR_button2_disable , NULL ) ;
drive_MCW_imseq( im3d->s312 , isqDR_button2_disable , NULL ) ;
drive_MCW_grapher( im3d->g123 , graDR_button2_disable , NULL ) ;
drive_MCW_grapher( im3d->g231 , graDR_button2_disable , NULL ) ;
drive_MCW_grapher( im3d->g312 , graDR_button2_disable , NULL ) ;
} else {
/*-- come on baby, light my fire --*/
drive_MCW_imseq( im3d->s123 , isqDR_button2_enable , NULL ) ;
drive_MCW_imseq( im3d->s231 , isqDR_button2_enable , NULL ) ;
drive_MCW_imseq( im3d->s312 , isqDR_button2_enable , NULL ) ;
if( im3d->vinfo->drawing_pixel > 0 ){
drive_MCW_imseq( im3d->s123, isqDR_button2_pixel,
(XtPointer)im3d->vinfo->drawing_pixel ) ;
drive_MCW_imseq( im3d->s231, isqDR_button2_pixel,
(XtPointer)im3d->vinfo->drawing_pixel ) ;
drive_MCW_imseq( im3d->s312, isqDR_button2_pixel,
(XtPointer)im3d->vinfo->drawing_pixel ) ;
}
drive_MCW_imseq( im3d->s123, isqDR_button2_mode,
(XtPointer)im3d->vinfo->drawing_mode ) ;
drive_MCW_imseq( im3d->s231, isqDR_button2_mode,
(XtPointer)im3d->vinfo->drawing_mode ) ;
drive_MCW_imseq( im3d->s312, isqDR_button2_mode,
(XtPointer)im3d->vinfo->drawing_mode ) ;
drive_MCW_grapher( im3d->g123 , graDR_button2_enable , NULL ) ;
drive_MCW_grapher( im3d->g231 , graDR_button2_enable , NULL ) ;
drive_MCW_grapher( im3d->g312 , graDR_button2_enable , NULL ) ;
}
EXRETURN ;
}
/*-------------------------------------------------------------------
Send alteration message to all receivers
(they don't have to register for this information)
---------------------------------------------------------------------*/
void AFNI_process_alteration( Three_D_View * im3d )
{
int ir ;
ENTRY("AFNI_process_alteration") ;
if( !IM3D_VALID(im3d) || im3d->vinfo->receiver == NULL ||
im3d->vinfo->num_receiver == 0 ) EXRETURN ;
for( ir=0 ; ir < im3d->vinfo->num_receiver ; ir++ ){
if( im3d->vinfo->receiver[ir] != NULL ){
STATUS(im3d->vinfo->receiver[ir]->receiver_funcname) ;
#if 0
im3d->vinfo->receiver[ir]->receiver_func(
RECEIVE_ALTERATION , 0 , NULL ,
im3d->vinfo->receiver[ir]->receiver_data ) ;
#else
AFNI_CALL_VOID_4ARG( im3d->vinfo->receiver[ir]->receiver_func ,
int,RECEIVE_ALTERATION , int,0 ,
void *,NULL ,
void *,im3d->vinfo->receiver[ir]->receiver_data ) ;
#endif
}
}
EXRETURN ;
}
/*-------------------------------------------------------------------
Send drawing notices to interested receivers
---------------------------------------------------------------------*/
void AFNI_process_drawnotice( Three_D_View * im3d )
{
int ir ;
ENTRY("AFNI_process_drawnotice") ;
if( !IM3D_VALID(im3d) || im3d->vinfo->receiver == NULL ||
im3d->vinfo->num_receiver == 0 ) EXRETURN ;
for( ir=0 ; ir < im3d->vinfo->num_receiver ; ir++ ){
if( im3d->vinfo->receiver[ir] != NULL &&
(im3d->vinfo->receiver[ir]->receiver_mask & RECEIVE_DRAWNOTICE_MASK) ){
STATUS(im3d->vinfo->receiver[ir]->receiver_funcname) ;
#if 0
im3d->vinfo->receiver[ir]->receiver_func(
RECEIVE_DRAWNOTICE , 0 , NULL ,
im3d->vinfo->receiver[ir]->receiver_data ) ;
#else
AFNI_CALL_VOID_4ARG( im3d->vinfo->receiver[ir]->receiver_func ,
int,RECEIVE_DRAWNOTICE , int,0 ,
void *,NULL ,
void *,im3d->vinfo->receiver[ir]->receiver_data ) ;
#endif
}
}
EXRETURN ;
}
/*-------------------------------------------------------------------
Send dset change notices to interested receivers
---------------------------------------------------------------------*/
void AFNI_process_dsetchange( Three_D_View * im3d )
{
int ir ;
ENTRY("AFNI_process_dsetchange") ;
if( !IM3D_VALID(im3d) || im3d->vinfo->receiver == NULL ||
im3d->vinfo->num_receiver == 0 ) EXRETURN ;
for( ir=0 ; ir < im3d->vinfo->num_receiver ; ir++ ){
if( im3d->vinfo->receiver[ir] != NULL &&
(im3d->vinfo->receiver[ir]->receiver_mask & RECEIVE_DSETCHANGE_MASK) ){
STATUS(im3d->vinfo->receiver[ir]->receiver_funcname) ;
#if 0
im3d->vinfo->receiver[ir]->receiver_func(
RECEIVE_DSETCHANGE , 0 , NULL ,
im3d->vinfo->receiver[ir]->receiver_data ) ;
#else
AFNI_CALL_VOID_4ARG( im3d->vinfo->receiver[ir]->receiver_func ,
int,RECEIVE_DSETCHANGE , int,0 ,
void *,NULL ,
void *,im3d->vinfo->receiver[ir]->receiver_data ) ;
#endif
}
}
EXRETURN ;
}
/*-------------------------------------------------------------------
Send new (i,j,k) coordinates to all receivers that care
---------------------------------------------------------------------*/
void AFNI_process_viewpoint( Three_D_View * im3d )
{
int ir , ijk[3] ;
ENTRY("AFNI_process_viewpoint") ;
if( !IM3D_VALID(im3d) || im3d->vinfo->receiver == NULL ||
im3d->vinfo->num_receiver == 0 ) EXRETURN ;
ijk[0] = im3d->vinfo->i1 ;
ijk[1] = im3d->vinfo->j2 ;
ijk[2] = im3d->vinfo->k3 ;
for( ir=0 ; ir < im3d->vinfo->num_receiver ; ir++ ){
if( im3d->vinfo->receiver[ir] != NULL &&
(im3d->vinfo->receiver[ir]->receiver_mask & RECEIVE_VIEWPOINT_MASK) ){
STATUS(im3d->vinfo->receiver[ir]->receiver_funcname) ;
#if 0
im3d->vinfo->receiver[ir]->receiver_func(
RECEIVE_VIEWPOINT , 3 , ijk ,
im3d->vinfo->receiver[ir]->receiver_data ) ;
#else
AFNI_CALL_VOID_4ARG( im3d->vinfo->receiver[ir]->receiver_func ,
int,RECEIVE_VIEWPOINT , int,3 ,
void *,ijk ,
void *,im3d->vinfo->receiver[ir]->receiver_data ) ;
#endif
}
}
EXRETURN ;
}
/*-------------------------------------------------------------------*/
/*! Send time index change notice to receivers that care [29 Jan 2003]
---------------------------------------------------------------------*/
void AFNI_process_timeindex( Three_D_View * im3d )
{
int ir ;
ENTRY("AFNI_process_timeindex") ;
if( !IM3D_VALID(im3d) || im3d->vinfo->receiver == NULL ||
im3d->vinfo->num_receiver == 0 ) EXRETURN ;
for( ir=0 ; ir < im3d->vinfo->num_receiver ; ir++ ){
if( im3d->vinfo->receiver[ir] != NULL &&
(im3d->vinfo->receiver[ir]->receiver_mask & RECEIVE_TIMEINDEX_MASK) ){
STATUS(im3d->vinfo->receiver[ir]->receiver_funcname) ;
#if 0
im3d->vinfo->receiver[ir]->receiver_func(
RECEIVE_TIMEINDEX , 0 , NULL ,
im3d->vinfo->receiver[ir]->receiver_data ) ;
#else
AFNI_CALL_VOID_4ARG( im3d->vinfo->receiver[ir]->receiver_func ,
int,RECEIVE_TIMEINDEX , int,0 ,
void *,NULL ,
void *,im3d->vinfo->receiver[ir]->receiver_data ) ;
#endif
}
}
EXRETURN ;
}
/*-------------------------------------------------------------------*/
/*! Send redisplay notification to receivers that care [04 Mar 2002].
---------------------------------------------------------------------*/
void AFNI_process_redisplay( Three_D_View * im3d )
{
int ir ;
ENTRY("AFNI_process_redisplay") ;
if( !IM3D_VALID(im3d) || im3d->vinfo->receiver == NULL ||
im3d->vinfo->num_receiver == 0 ) EXRETURN ;
for( ir=0 ; ir < im3d->vinfo->num_receiver ; ir++ ){
if( im3d->vinfo->receiver[ir] != NULL &&
(im3d->vinfo->receiver[ir]->receiver_mask & RECEIVE_REDISPLAY_MASK) ){
STATUS(im3d->vinfo->receiver[ir]->receiver_funcname) ;
#if 0
im3d->vinfo->receiver[ir]->receiver_func(
RECEIVE_REDISPLAY , 0 , NULL ,
im3d->vinfo->receiver[ir]->receiver_data ) ;
#else
AFNI_CALL_VOID_4ARG( im3d->vinfo->receiver[ir]->receiver_func ,
int,RECEIVE_REDISPLAY , int,0 ,
void *,NULL ,
void *,im3d->vinfo->receiver[ir]->receiver_data ) ;
#endif
}
}
EXRETURN ;
}
/*-------------------------------------------------------------------*/
/*! Send funcdisplay notification to receivers that care [05 Mar 2002].
---------------------------------------------------------------------*/
void AFNI_process_funcdisplay( Three_D_View * im3d )
{
int ir ;
ENTRY("AFNI_process_funcdisplay") ;
if( !IM3D_VALID(im3d) || im3d->vinfo->receiver == NULL ||
im3d->vinfo->num_receiver == 0 ) EXRETURN ;
for( ir=0 ; ir < im3d->vinfo->num_receiver ; ir++ ){
if( im3d->vinfo->receiver[ir] != NULL &&
(im3d->vinfo->receiver[ir]->receiver_mask & RECEIVE_FUNCDISPLAY_MASK) ){
STATUS(im3d->vinfo->receiver[ir]->receiver_funcname) ;
#if 0
im3d->vinfo->receiver[ir]->receiver_func(
RECEIVE_FUNCDISPLAY , 0 , NULL ,
im3d->vinfo->receiver[ir]->receiver_data ) ;
#else
AFNI_CALL_VOID_4ARG( im3d->vinfo->receiver[ir]->receiver_func ,
int,RECEIVE_FUNCDISPLAY , int,0 ,
void *,NULL ,
void *,im3d->vinfo->receiver[ir]->receiver_data ) ;
#endif
}
}
EXRETURN ;
}
/*-------------------------------------------------------------------*/
/*! Process drawn points:
- npts = number of points sent in
- mode = type of points to follow:
- PLANAR_MODE + zz ==> axis zz is fixed, for zz=1,2,3
- SINGLE_MODE + zz ==> one point only, clicked in a
window with zz fixed
- THREED_MODE ==> points are in 3D (not planar)
(not currently possible)
- UNDO_MODE ==> undo last drawing action
- xd[i] = x index of point i, for i=0..npts-1
- yd[i] = y index of point i, for i=0..npts-1
- zd[i] = z index of point i, for i=0..npts-1
These indices are with respect to the dataset brick axes.
---------------------------------------------------------------------*/
void AFNI_process_drawing( Three_D_View *im3d , int mode ,
int npts , int *xd , int *yd , int *zd )
{
int ii , nn , ir , nsent ;
int *vp[4] , *xn=NULL , *yn=NULL , *zn=NULL ;
ENTRY("AFNI_process_drawing") ;
if( !IM3D_VALID(im3d) || im3d->vinfo->receiver == NULL ||
im3d->vinfo->num_receiver == 0 ||
npts < 0 || im3d->vinfo->drawing_enabled == 0 ) EXRETURN ;
if(PRINT_TRACING){
char str[256] ; sprintf(str,"received %d points",npts) ; STATUS(str) ;
}
/*-- if no further treatment is needed,
just flag input data to be set to receiver --*/
if( im3d->vinfo->drawing_mode == DRAWING_POINTS ||
im3d->vinfo->drawing_mode == DRAWING_NODRAW || npts <= 1 ){
xn = xd ; yn = yd ; zn = zd ; nn = npts ;
}
/*-- must fill in the lines:
create arrays xn, yn, zn of length nn --*/
else if( im3d->vinfo->drawing_mode == DRAWING_LINES ){
AFNI_3d_linefill( npts , xd,yd,zd , &nn , &xn , &yn , &zn ) ;
}
/*-- must fill in the polygon --*/
else if( im3d->vinfo->drawing_mode == DRAWING_FILL ){
/* this just fills the lines like above --
need to write a real polygon filling routine? */
AFNI_3d_linefill( npts , xd,yd,zd , &nn , &xn , &yn , &zn ) ;
}
/*-- send data to receivers that want it --*/
#if 0
fprintf(stderr,"Sending %d points to receiver\n",nn) ;
#endif
vp[3] = &mode ; /* how the points are arranged */
vp[0] = xn ; vp[1] = yn ; vp[2] = zn ;
for( nsent=ir=0 ; ir < im3d->vinfo->num_receiver ; ir++ ){
if( im3d->vinfo->receiver[ir] != NULL &&
(im3d->vinfo->receiver[ir]->receiver_mask & RECEIVE_DRAWING_MASK) ){
STATUS(im3d->vinfo->receiver[ir]->receiver_funcname) ;
#if 0
im3d->vinfo->receiver[ir]->receiver_func(
RECEIVE_POINTS , nn ,
(void *) vp , im3d->vinfo->receiver[ir]->receiver_data ) ;
#else
AFNI_CALL_VOID_4ARG( im3d->vinfo->receiver[ir]->receiver_func ,
int,RECEIVE_POINTS , int,nn ,
void *,vp ,
void *,im3d->vinfo->receiver[ir]->receiver_data ) ;
#endif
nsent++ ;
}
}
/* 30 Mar 1999: also send DRAWNOTICE to receivers that like this stuff */
if( nsent > 0 ) AFNI_process_drawnotice( im3d ) ;
/*-- free any created arrays --*/
if( xn != xd ){ free(xn); free(yn); free(zn); }
EXRETURN ;
}
/*--------------------------------------------------------------------
3D line filler-inner -- quick and dirty.
The output arrays (*xout, *yout, *zout) should be freed when
their usefulness is over.
----------------------------------------------------------------------*/
void AFNI_3d_linefill( int nin , int * xin , int * yin , int * zin ,
int * nout , int ** xout , int ** yout , int ** zout )
{
int * xut , * yut , * zut ;
int nut , iin , jout , nall ;
int x1,y1,z1 , x2,y2,z2 , dx,dy,dz , adx,ady,adz , xlast,ylast,zlast ;
float fdxyz , fdx,fdy,fdz , fx,fy,fz ;
ENTRY("AFNI_3d_linefill") ;
/* sanity check */
if( nin <= 0 || xin == NULL || yin == NULL || zin == NULL ){
*nout = 0 ; *xout = *yout = *zout = NULL ; EXRETURN ;
}
/* trivial case */
if( nin == 1 ){
nut = 1 ; *nout = nut ;
xut = (int *) malloc(sizeof(int)) ; xut[0] = xin[0] ; *xout = xut ;
yut = (int *) malloc(sizeof(int)) ; yut[0] = yin[0] ; *yout = yut ;
zut = (int *) malloc(sizeof(int)) ; zut[0] = zin[0] ; *zout = zut ;
EXRETURN ;
}
/* setup to scan through lines */
nall = nin ;
xut = (int *) malloc( sizeof(int) * nall ) ;
yut = (int *) malloc( sizeof(int) * nall ) ;
zut = (int *) malloc( sizeof(int) * nall ) ;
nut = 0 ;
#undef ADDPT
#define ADDPT(i,j,k) \
do{ if( nut == nall ){ \
nall += 128 ; \
xut = (int *) realloc( xut , sizeof(int) * nall ) ; \
yut = (int *) realloc( yut , sizeof(int) * nall ) ; \
zut = (int *) realloc( zut , sizeof(int) * nall ) ; \
} \
xut[nut] = xlast = (i) ; \
yut[nut] = ylast = (j) ; \
zut[nut] = zlast = (k) ; nut++ ; } while(0)
/* draw line from point #iin to #iin+1 */
x2 = xin[0] ; y2 = yin[0] ; z2 = zin[0] ;
for( iin=0 ; iin < nin-1 ; iin++ ){
x1 = x2 ; y1 = y2 ; z1 = z2 ;
x2 = xin[iin+1] ; y2 = yin[iin+1] ; z2 = zin[iin+1] ;
dx = x2 - x1 ; dy = y2 - y1 ; dz = z2 - z1 ;
adx = abs(dx) ; ady = abs(dy) ; adz = abs(dz) ;
/* add start point to list */
ADDPT(x1,y1,z1) ;
/* special case: neighbors ==> skip to next line */
if( adx <= 1 && ady <= 1 && adz <= 1 ) continue ;
/* OK, we have to do work (moan) */
#define SFRAC 0.495
fdxyz = adx + ady + adz ; /* Manhattan distance */
fdx = SFRAC * dx / fdxyz ; /* steps */
fdy = SFRAC * dy / fdxyz ;
fdz = SFRAC * dz / fdxyz ;
/* step thru in small increments,
adding new integer points, and stopping at line's end */
#if 0
fprintf(stderr,"linefill: from %d %d %d to %d %d %d\n",
x1,y1,z1 , x2,y2,z2 ) ;
#endif
fx = x1+fdx+0.499 ; fy = y1+fdy+0.499 ; fz = z1+fdz+0.499 ;
do {
fx = fx + fdx ; fy = fy + fdy ; fz = fz + fdz ;
x1 = (int) fx ; y1 = (int) fy ; z1 = (int) fz ;
#if 0
fprintf(stderr," at %d %d %d\n",x1,y1,z1) ;
#endif
if( x1 == x2 && y1 == y2 && z1 == z2 ) break ;
if( x1 != xlast || y1 != ylast || z1 != zlast ) ADDPT(x1,y1,z1) ;
} while(1) ;
} /* end of loop over lines */
ADDPT(x2,y2,z2) ; /* add last point */
*nout = nut ; *xout = xut ; *yout = yut ; *zout = zut ;
EXRETURN ;
}
/*********************************************************************
Coordinate inter-conversion routines.
**********************************************************************/
void AFNI_ijk_to_xyz( THD_3dim_dataset * dset ,
int ii , int jj , int kk ,
float * xx , float * yy , float * zz )
{
THD_fvec3 fv ;
if( ! ISVALID_DSET(dset) ) return ;
fv = THD_3dind_to_3dmm( dset , TEMP_IVEC3(ii,jj,kk) ) ;
*xx = fv.xyz[0] ;
*yy = fv.xyz[1] ;
*zz = fv.xyz[2] ;
return ;
}
void AFNI_xyz_to_ijk( THD_3dim_dataset * dset ,
float xx , float yy , float zz ,
int * ii , int * jj , int * kk )
{
THD_ivec3 iv ;
if( ! ISVALID_DSET(dset) ) return ;
iv = THD_3dmm_to_3dind ( dset , TEMP_FVEC3(xx,yy,zz) ) ;
*ii = iv.ijk[0] ;
*jj = iv.ijk[1] ;
*kk = iv.ijk[2] ;
return ;
}
void AFNI_xyz_to_dicomm( THD_3dim_dataset * dset ,
float xx , float yy , float zz ,
float * xd , float * yd , float * zd )
{
THD_fvec3 fv ;
if( ! ISVALID_DSET(dset) ) return ;
fv = THD_3dmm_to_dicomm( dset , TEMP_FVEC3(xx,yy,zz) ) ;
*xd = fv.xyz[0] ;
*yd = fv.xyz[1] ;
*zd = fv.xyz[2] ;
return ;
}
void AFNI_dicomm_to_xyz( THD_3dim_dataset * dset ,
float xd , float yd , float zd ,
float * xx , float * yy , float * zz )
{
THD_fvec3 fv ;
if( ! ISVALID_DSET(dset) ) return ;
fv = THD_3dmm_to_dicomm( dset , TEMP_FVEC3(xd,yd,zd) ) ;
*xx = fv.xyz[0] ;
*yy = fv.xyz[1] ;
*zz = fv.xyz[2] ;
return ;
}
syntax highlighted by Code2HTML, v. 0.9.1