The Callback Fct

 

The data structure has a number of "callback" anchor points where you can hook your own function.  These are mostly use to draw portion of the classes, but there is also a few callbacks to change the values of the pixels of the images, and return the metrics of the images.

 

Some callbacks are single function pointers.  Assigning your own function to these pointers will remove the default value.

 

Others are array of functions. For those, you must first obtain an ID so that you can assign your function to the appropriate slot in the array. To obtain this ID, you must define one of the following function in your module, if it exist, sliceOmatic will call the your function with your ID as parameter. This ID is unique and will not conflict with the callbacks from other modules.

 

The functions that provide callback IDs is:

 

Callback_Get_ID

 

This function provide callback IDs for the callback arrays.

 

 

The callback functions themselves are presented here and also, in the section describing the class where they are found.

 

 

Callbacks present in the "Class" class"

 

 

...

 

// --- we also have callbacks for the pixel values ---

int          (*Fct_Pixel_Get_GLI)( SliceO_Class *pt, void *ima, Vect pos ) ;

unsigned char          (*Fct_Pixel_Get_TAG)( SliceO_Class *pt, void *ima, Vect pos ) ;

int          (*Fct_Pixel_Set_TAG)( SliceO_Class *pt, void *ima, Vect pos, unsigned char tag ) ;

 

// ====================================================================

// Return the x & y image resolution

int          (*Fct_Metrics_Get_Res)( SliceO_Class *pt, void *ima, int *x, int *y ) ;

// return the 3D coord of a point in the image plane

Vect          (*Fct_Metrics_Get_Pos)( SliceO_Class *pt, void *ima, Vect pos_2D ) ;

 

// ====================================================================

// --- we also have callbacks for drawing the structure ---

int          (*Fct_Draw_Highlight)( SliceO_Class *pt, UInt64 flag, SliceO_Window *window ) ;

// --- default value is at "0", but first we try all the other ones. if

// --- a callback is present and it return=2, we do not call default.

int          (*Fct_Draw_Base[CALLBACK_NB_BASE])( SliceO_Class *pt, UInt64 flag, SliceO_Window *window ) ;

// --- these callback are to add drawings on top of the base.  The are called

// in increasing value starting at 0.  So the latest will be on top ---

int          (*Fct_Draw_OpenGL[CALLBACK_NB_OPENGL])( SliceO_Class *pt, UInt64 flag, SliceO_Window *window ) ;

int          (*Fct_Draw_Stencil[CALLBACK_NB_STENCIL])( SliceO_Class *pt, UInt64 flag, SliceO_Window *window ) ;

// --- this callback is to add 3D elements for each class in the 3D windows. ---

int          (*Fct_Draw_3D[CALLBACK_NB_3D])( SliceO_Class *pt, UInt64 flag, SliceO_Window *window ) ;

// ====================================================================

 

...

 

          

Some callbacks are specific to the "Frame" class

 

 

...

 

// ====================================================================

// --- we also have callbacks for updating the display buffers ---

// --- default value is at "0", but first we try all the other ones. if

// --- a callback is present and it return=2, we do not call default.

int          (*Fct_Update_GLI_Disp[CALLBACK_NB_DISPLAY])( SliceO_Class *pt ) ;

int          (*Fct_Update_TAG_Disp[CALLBACK_NB_DISPLAY])( SliceO_Class *pt ) ;

// ====================================================================

 

// ====================================================================

// --- Callback for mean and gradient values ---

int          (*Fct_Pixel_Get_Filter)(       SliceO_Frame *pt, void *ima, Vect pos ) ;

int          (*Fct_Pixel_Get_Gradient_Amp)( SliceO_Frame *pt, void *ima, Vect pos ) ;

Vect          (*Fct_Pixel_Get_Gradient_Dir)( SliceO_Frame *pt, void *ima, Vect pos ) ;

// ====================================================================

 

...

 

 

And finally we also have callbacks to redraw the geometries

 

 

...

 

// --- Drawing callbacks ---

int          (*Fct_Draw_Geom[CALLBACK_NB_GEOM])( SliceO_Geom *pt, UInt64 flag, SliceO_Window *window, int step, int nb_step ) ;

 

...

 

 

Example

For example, we want to draw a 10x10 pixel red square around the center of each frames:

 

First, we need a callback ID for a "Fct_Draw_OpenGL()" callback:

 

 

#include          <windows.h>

 

#include          "db_work.hpp"

#include          "sliceO_OpenGL.hpp"

 

static          unsigned short          Local_Callback_ID ;

 

// ----------------------------------------------------------------------------

//

//          Function:          Callback_Get_ID...

//

//          Parameters:          id (unsigned short)          // callback id assigned to the DLL

//          Returns:          (void)

//

//          This function should only exist if the DLL plan to use one of the

//          following callbacks:

//              in SliceO_Class

//                    Fct_Draw_3D[]()

//                    Fct_Draw_OpenGL[]()

//                    Fct_Draw_Stencil[]()

//              in SliceO_Geom

//                    Fct_Draw_Geom[]()

//              in SliceO_Frame

//                    Fct_Update_GLI_Disp[]()

//                    Fct_Update_TAG_Disp[]()

//

//          SliceOmatic will use this function at start-up to assign a unique

//          ID number to your DLL.

//

// ----------------------------------------------------------------------------

extern "C" __declspec(dllexport) unsigned short  Callback_Get_ID( unsigned short *id )

{

          Local_Callback_ID = id[CALLBACK_DRAW_OPENGL] ;

          return( 1 << CALLBACK_DRAW_OPENGL ) ;

}

 

 

 

Next we need our drawing function:

 

 

 

// ----------------------------------------------------------------------------

//

//          Square_Draw_Line

//

//          Our callback function to draw a square

//

//          Param:           pt (SliceO_Class *)

//                    flag (UInt64)

//                    window (SliceO_Window *)

//

//          Return:          (int)                    

//

// ----------------------------------------------------------------------------

int          Square_Draw_Line( SliceO_Class *pt, UInt64 flag, SliceO_Window *window )

{

 

          SliceO_Frame *frame = (SliceO_Frame *) pt ;

 

          // --- we will draw red lines ---

          glColor3ub( 255, 0, 0 ) ;

 

          // --- we want to know the start and size of the pixels in "display" space ---

          Region_2D delta_frm(COORD_FRM) ;

          delta_frm.Set( 0, 0, 1, 1 ) ;

          Region_2D delta_inf( frame->Frm_2_Inf(window, delta_frm) ) ;

          Region_2D delta_wnd( window->Inf_2_Wnd(delta_inf) ) ;

          

          float          p_x = delta_wnd[0] ;

          float          p_y = delta_wnd[1] ;

          float          d_x = delta_wnd[2] - delta_wnd[0] ;

          float          d_y = delta_wnd[3] - delta_wnd[1] ;

 

          // --- prepare the transformation matrix to go from image pixel pos to dsp pos ---

          glMatrixMode( GL_MODELVIEW ) ;

          glPushMatrix() ;

          glTranslatef( p_x, p_y, 0.0f ) ;

          glScalef( d_x, -d_y, 0.0f ) ;

 

          // --- center the square in the middle of the frame ---

          glTranslatef( frame->m_x/2.0f, frame->m_y/2.0f, 0.0f ) ;          

 

          // --- draw the 10x10 square ---

          glBegin( GL_LINES ) ;

              glVertex2i( -10, -10 ) ;

              glVertex2i( -10,  10 ) ;

              glVertex2i(  10,  10 ) ;

              glVertex2i(  10, -10 ) ;

          glEnd() ;

 

          glPopMatrix() ;

}

 

 

 

 

Next, we need a way to assign our function to the callback, and a way to remove it:

 

 

 

// ----------------------------------------------------------------------------

//

//          Function:          Sample_Callback_Register

//

//          Parameters:          (void)

//          Returns:          (int)                    0 for errors

//

//          This function will assign the "Square_Draw_Line" fct to the Fct_Draw_OpenGL

//          of each selected frames in the database.

//

// ----------------------------------------------------------------------------

int          Sample_Callback_Register( void )

{

          // --- for all frames ---

          if ( ! Iterator_Init( ITERATOR_2, "Sample_Callback_Register" ) )

              return( 0 ) ;

 

          while( SliceO_Frame *frame = (SliceO_Frame *) Iterator_Class( ITERATOR_2, CLASS_ID_FRAME ) )

 

              frame->Fct_Draw_OpenGL[Local_Callback_ID] = Square_Draw_Line ;

 

          Iterator_End( ITERATOR_2 ) ;

 

          return( 1 ) ;

}

 

 

// ----------------------------------------------------------------------------

//

//          Function:          Sample_Callback_Reset

//

//          Parameters:          (void)

//          Returns:          (int)                    0 for errors

//

//          This function will assign reset the fct of the Fct_Draw_OpenGL

//          of each frames in the database.

//

// ----------------------------------------------------------------------------

int          Sample_Callback_Reset( void )

{

          // --- for all frames ---

          if ( ! Iterator_Init( ITERATOR_2, "Sample_Callback_Reset" ) )

              return( 0 ) ;

 

          while( SliceO_Frame *frame = (SliceO_Frame *) Iterator_Class( ITERATOR_2, CLASS_ID_FRAME ) )

 

              frame->Fct_Draw_OpenGL[Local_Callback_ID] = NULL ;

 

          Iterator_End( ITERATOR_2 ) ;

 

          return( 1 ) ;

}

 

 

And finally we call these "Register" and "Reset" function when our module is activated, in this example we chose to enable the callback as soon as our module is activate (either as a tool or a mode):

 

 

 

// ----------------------------------------------------------------------------

//

//          Function:          Ctrl_Open

//

//          Parameters:          id (unsigned short)          Id of the ctrl interface (if

//                                                                      multiple instances are supported)

//          Returns:          (int)                    0 if error

//

//          This is called each time your control is activate from the menus

//

// ----------------------------------------------------------------------------

extern "C" __declspec(dllexport) int          Ctrl_Open( unsigned short id )

{

          ...          

 

          // --- register the "Square_Draw_Line" callbacks ---

          Sample_Callback_Register() ;

 

          ...

 

          return( 1 ) ;

}

 

// ----------------------------------------------------------------------------

//

//          Function:          Ctrl_Close

//

//          Parameters:          (void)

//          Returns:          (int)                    0 if error

//

//          This is called each time your control is deactivate from the menus

//

// ----------------------------------------------------------------------------

extern "C" __declspec(dllexport) int          Ctrl_Close( void )

{

          ...

 

          // --- reset the "Square_Draw_Line" callbacks ---

          Sample_Callback_Reset() ;

 

          ...

 

          return( 1 ) ;

}

 

 

Note:

 

There is a problem with calling the "Register" function in the Ctrl_Open() function. If a file is read after the module is opened, or if the database is re-computed after the module is activated, we loose the callbacks. So, instead, it would be better to place the register ("Sample_Callback_Register") in the "Update" function and have the Ctrl_Open() function call the Update.

 

 

// --- local prototypes ---

int          Ctrl_Update( UInt64 flag=NULL ) ;

 

// ----------------------------------------------------------------------------

extern "C" __declspec(dllexport) int          Ctrl_Open( unsigned short id )

{

          ...          

 

          // --- make sure Update register the "Square_Draw_Line" callbacks ---

          Ctrl_Update( UPDATE_SELECTION ) ;

 

          ...

 

          return( 1 ) ;

}

 

// ----------------------------------------------------------------------------

int          Ctrl_Update( UInt64 flag )

{

 

          ...

 

          // --- We changed the frame selection ---

          if ( flag & UPDATE_SELECTION ) {

              Sample_Callback_Register() ;

 

          }

 

          ...

 

          return( 1 ) ;

}