~ubuntu-branches/ubuntu/lucid/igstk/lucid

« back to all changes in this revision

Viewing changes to Examples/NeedleBiopsy/NeedleBiopsy.cxx

  • Committer: Bazaar Package Importer
  • Author(s): Dominique Belhachemi
  • Date: 2009-10-07 17:35:43 UTC
  • mfrom: (2.1.3 squeeze)
  • Revision ID: james.westby@ubuntu.com-20091007173543-69eyhyjrh0bfoqe5
Tags: 4.2.0-2
* Fixed link issue (Closes: #549799)
* switch to quilt

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*=========================================================================
 
2
 
 
3
Program:   Image Guided Surgery Software Toolkit
 
4
Module:    $RCSfile: NeedleBiopsy.cxx,v $
 
5
Language:  C++
 
6
Date:      $Date: 2009-06-12 15:23:31 $
 
7
Version:   $Revision: 1.3 $
 
8
 
 
9
Copyright (c) ISC  Insight Software Consortium.  All rights reserved.
 
10
  See IGSTKCopyright.txt or http://www.igstk.org/copyright.htm for details.
 
11
 
 
12
This software is distributed WITHOUT ANY WARRANTY; without even
 
13
the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
 
14
PURPOSE.  See the above copyright notices for more information.
 
15
 
 
16
=========================================================================*/
 
17
 
 
18
#include "NeedleBiopsy.h"
 
19
 
 
20
#include "FL/Fl_File_Chooser.H"
 
21
#include "FL/Fl_Input.H"
 
22
#include "igstkEvents.h"
 
23
#include "itksys/SystemTools.hxx"
 
24
#include "itksys/Directory.hxx"
 
25
#include "igstkTransformObserver.h"
 
26
 
 
27
#include "PolarisTrackerConfigurationGUI.h"
 
28
#include "AuroraTrackerConfigurationGUI.h"
 
29
#include "MicronTrackerConfigurationGUI.h"
 
30
 
 
31
/** -----------------------------------------------------------------
 
32
*     Constructor
 
33
*  -----------------------------------------------------------------
 
34
*/
 
35
NeedleBiopsy::NeedleBiopsy() : m_LogFile()
 
36
{
 
37
 
 
38
  /** Setup logger, for all igstk components. */
 
39
  m_Logger   = LoggerType::New();
 
40
  this->GetLogger()->SetTimeStampFormat( itk::LoggerBase::HUMANREADABLE );
 
41
  this->GetLogger()->SetHumanReadableFormat("%Y %b %d, %H:%M:%S");
 
42
  this->GetLogger()->SetPriorityLevel( LoggerType::INFO );
 
43
 
 
44
  /** Direct the application log message to the std::cout */
 
45
  itk::StdStreamLogOutput::Pointer m_LogCoutOutput
 
46
                                           = itk::StdStreamLogOutput::New();
 
47
  m_LogCoutOutput->SetStream( std::cout );
 
48
  this->GetLogger()->AddLogOutput( m_LogCoutOutput );
 
49
 
 
50
  /** Direct the igstk components log message to the file. */
 
51
  itk::StdStreamLogOutput::Pointer m_LogFileOutput
 
52
                                           = itk::StdStreamLogOutput::New();
 
53
  std::string   logFileName;
 
54
  logFileName = "logNeedleBiopsy"
 
55
  + itksys::SystemTools::GetCurrentDateTime( "_%Y_%m_%d_%H_%M_%S" ) + ".txt";
 
56
  m_LogFile.open( logFileName.c_str() );
 
57
  if( !m_LogFile.fail() )
 
58
    {
 
59
    m_LogFileOutput->SetStream( m_LogFile );
 
60
    this->GetLogger()->AddLogOutput( m_LogFileOutput );
 
61
    }
 
62
  else
 
63
    {
 
64
    //Return if fail to open the log file
 
65
    igstkLogMacro( DEBUG, "Problem opening Log file:"
 
66
                                                    << logFileName << "\n" );
 
67
    return;
 
68
    }
 
69
 
 
70
  /** Initialize all member variables  */
 
71
  
 
72
  m_ImageReader           = ImageReaderType::New();
 
73
  m_LandmarkRegistration  = RegistrationType::New();
 
74
  m_Annotation            = igstk::Annotation2D::New();
 
75
  m_WorldReference        = igstk::AxesObject::New();
 
76
  m_TrackerInitializerList.clear();
 
77
  m_Plan                  = new igstk::TreatmentPlan;
 
78
 
 
79
  /** Setting up spatial objects and their representations */
 
80
  m_NeedleTip                   = EllipsoidType::New();
 
81
  m_NeedleTipRepresentation     = EllipsoidRepresentationType::New();
 
82
  m_NeedleTip->SetRadius( 5, 5, 5 );
 
83
  m_NeedleTipRepresentation->RequestSetEllipsoidObject( m_NeedleTip );
 
84
  m_NeedleTipRepresentation->SetColor(1.0,0.0,0.0);
 
85
  m_NeedleTipRepresentation->SetOpacity(1.0);
 
86
 
 
87
  m_Needle                    = CylinderType::New();
 
88
  m_NeedleRepresentation      = CylinderRepresentationType::New();
 
89
  m_Needle->SetRadius( 1.5 ); 
 
90
  m_Needle->SetHeight( 100 );
 
91
  m_NeedleRepresentation->RequestSetCylinderObject( m_Needle );
 
92
  m_NeedleRepresentation->SetColor(0.0,1.0,0.0);
 
93
  m_NeedleRepresentation->SetOpacity(1.0);
 
94
 
 
95
  m_TargetPoint                 = EllipsoidType::New();
 
96
  m_TargetRepresentation        = EllipsoidRepresentationType::New();
 
97
  m_TargetPoint->SetRadius( 6, 6, 6 );
 
98
  m_TargetRepresentation->RequestSetEllipsoidObject( m_TargetPoint );
 
99
  m_TargetRepresentation->SetColor( 1.0, 0.0, 0.0);
 
100
  m_TargetRepresentation->SetOpacity( 0.6 );
 
101
 
 
102
  m_EntryPoint                  = EllipsoidType::New();
 
103
  m_EntryRepresentation         = EllipsoidRepresentationType::New();
 
104
  m_EntryPoint->SetRadius( 6, 6, 6 );
 
105
  m_EntryRepresentation->RequestSetEllipsoidObject( m_EntryPoint );
 
106
  m_EntryRepresentation->SetColor( 0.0, 0.0, 1.0);
 
107
  m_EntryRepresentation->SetOpacity( 0.6 );
 
108
 
 
109
  m_FiducialPoint                 = EllipsoidType::New();
 
110
  m_FiducialRepresentation        = EllipsoidRepresentationType::New();
 
111
  m_FiducialPoint->SetRadius( 6, 6, 6 );
 
112
  m_FiducialRepresentation->RequestSetEllipsoidObject( m_FiducialPoint );
 
113
  m_FiducialRepresentation->SetColor( 0.0, 1.0, 0.0);
 
114
  m_FiducialRepresentation->SetOpacity( 0.6 );
 
115
 
 
116
 
 
117
  m_Path                       = PathType::New();
 
118
  TubePointType point;
 
119
  point.SetPosition( 0, 0, 0);
 
120
  point.SetRadius( 2 );
 
121
  m_Path->AddPoint( point );
 
122
  m_Path->AddPoint( point );
 
123
 
 
124
  m_PathRepresentation.clear();
 
125
  for( int i=0; i<4; i++ )
 
126
    {
 
127
    PathRepresentationType::Pointer rep  = PathRepresentationType::New();
 
128
    rep->RequestSetTubeObject( m_Path );
 
129
    rep->SetColor( 0.0, 1.0, 0.0);
 
130
    rep->SetOpacity( 0.4 );
 
131
    m_PathRepresentation.push_back( rep );
 
132
    }
 
133
 
 
134
  /** Creating observers and their call back functions */
 
135
 
 
136
  /** This observes picking event from view */
 
137
  m_ViewPickerObserver = LoadedObserverType::New();
 
138
  m_ViewPickerObserver->SetCallbackFunction( this, &NeedleBiopsy::Picking );
 
139
 
 
140
  /** This observes reslicing events from FourQuadrantView class */
 
141
  m_ViewResliceObserver = LoadedObserverType::New();
 
142
  m_ViewResliceObserver->SetCallbackFunction( this,
 
143
                                                &NeedleBiopsy::ResliceImage);
 
144
 
 
145
  /** 
 
146
   *  This observer catches the tracker configuration sent out by
 
147
   *  TrackerConfiguration GUI
 
148
   */
 
149
  m_TrackerConfigurationObserver = LoadedObserverType::New();
 
150
  m_TrackerConfigurationObserver->SetCallbackFunction( this,
 
151
                                    &NeedleBiopsy::RequestInitializeTracker);
 
152
 
 
153
  /** 
 
154
   *  This observer listens to the TrackerToolTransformUpdateEvent from
 
155
   *  TrackerTool class, notice this event doesn't carry any payload, it
 
156
   *  only functions as a ticker here to trigger image representation class
 
157
   *  to do image reslicing according to the current tooltip location.
 
158
   *  Refer to:
 
159
   *  NeedleBiopsy::Tracking()
 
160
   */
 
161
  m_TrackerToolUpdateObserver    = LoadedObserverType::New();
 
162
  m_TrackerToolUpdateObserver->SetCallbackFunction( this,
 
163
                                                 &NeedleBiopsy::Tracking);
 
164
 
 
165
  /** Create image slice representations  */
 
166
  m_ImageRepresentation.clear();
 
167
  for (int i=0; i<6; i++)
 
168
    {
 
169
    ImageRepresentationType::Pointer rep = ImageRepresentationType::New();
 
170
    m_ImageRepresentation.push_back( rep );
 
171
    }
 
172
 
 
173
}
 
174
 
 
175
/** -----------------------------------------------------------------
 
176
*     Destructor
 
177
*  -----------------------------------------------------------------
 
178
*/
 
179
NeedleBiopsy::~NeedleBiopsy()
 
180
{
 
181
  m_TrackerInitializerList.clear();
 
182
  m_TrackerToolList.clear();
 
183
 
 
184
}
 
185
 
 
186
 
 
187
/** -----------------------------------------------------------------
 
188
*      Loading images
 
189
* This methods asks for folder directory contains a single dicom
 
190
* series. If it loads the image successfully, it will try loading
 
191
* the previously saved treatment plan, in the same parent directory
 
192
* which should be named "folderName_TreatmentPlan.igstk".
 
193
* See also:
 
194
* Method:
 
195
*        ReadTreatmentPlan()
 
196
*        WriteTreatmentPlan()
 
197
* Class:
 
198
*        igstkTreatmentPlan
 
199
*        igstkTreatmentPlanIO
 
200
*  -----------------------------------------------------------------
 
201
*/
 
202
int NeedleBiopsy::RequestLoadImage()
 
203
{
 
204
  const char * directoryname = fl_dir_chooser("DICOM Volume directory","");
 
205
  if ( directoryname != NULL )
 
206
    {
 
207
    igstkLogMacro( DEBUG,
 
208
      "Set ImageReader directory: " << directoryname << "\n" )
 
209
    m_ImageDir = directoryname;
 
210
    m_ImageReader->RequestSetDirectory( directoryname );
 
211
 
 
212
    igstkLogMacro( DEBUG, "ImageReader loading images... \n" )
 
213
    m_ImageReader->RequestReadImage();
 
214
 
 
215
 
 
216
    /** 
 
217
    * IGSTK uses event for inter-components communication.
 
218
    * Event/observer model is used to replace the normal Get() method.
 
219
    * CTImageObserver here is defined by Macro in header file:
 
220
    * igstkObserverObjectMacro( CTImage,
 
221
    *                           igstk::CTImageReader::ImageModifiedEvent,
 
222
    *                           igstk::CTImageSpatialObject);
 
223
    * Refer to igstkMacros.h for more detail about this macro.
 
224
    */
 
225
    CTImageObserver::Pointer  m_CTImageObserver = CTImageObserver::New();
 
226
    m_ImageReader->AddObserver(igstk::CTImageReader::ImageModifiedEvent(),
 
227
                                                      m_CTImageObserver);
 
228
 
 
229
    m_ImageReader->RequestGetImage(); // This will invoke the event
 
230
 
 
231
    if(m_CTImageObserver->GotCTImage())
 
232
      {
 
233
      igstkLogMacro(          DEBUG, "Image loaded...\n" )
 
234
      m_ImageSpatialObject = m_CTImageObserver->GetCTImage();
 
235
      this->ConnectImageRepresentation();
 
236
      this->ReadTreatmentPlan();
 
237
      return 1;
 
238
      }
 
239
    else
 
240
      {
 
241
      igstkLogMacro(          DEBUG, "Reading image failure...\n" )
 
242
      return 0;
 
243
      }
 
244
    }
 
245
  else
 
246
    {
 
247
    igstkLogMacro(          DEBUG, "No directory is selected\n" )
 
248
    return 0;
 
249
    }
 
250
 
 
251
}
 
252
 
 
253
/** -----------------------------------------------------------------
 
254
*  This method should be invoked only when the Image has been loaded
 
255
*  -----------------------------------------------------------------
 
256
*/
 
257
void NeedleBiopsy::ConnectImageRepresentation()
 
258
{
 
259
  /** Setting up annotation and added to four views  */
 
260
  m_Annotation->RequestSetAnnotationText( 2, "Georgetown ISIS Center" );
 
261
  for( int i=0; i<4; i++)
 
262
    {
 
263
    ViewerGroup->m_Views[i]->RequestAddAnnotation2D( m_Annotation );
 
264
    }
 
265
 
 
266
  /**
 
267
  * Pass image spatial object to image slice representation and set
 
268
  * the desired slice orientation for each representations, and then 
 
269
  * add them to the views
 
270
  */
 
271
  for( int i=0; i<6; i++)
 
272
    {
 
273
    m_ImageRepresentation[i]->RequestSetImageSpatialObject(
 
274
      m_ImageSpatialObject );
 
275
    }
 
276
 
 
277
  m_ImageRepresentation[0]->RequestSetOrientation(
 
278
    ImageRepresentationType::Axial );
 
279
  m_ImageRepresentation[1]->RequestSetOrientation(
 
280
    ImageRepresentationType::Sagittal );
 
281
  m_ImageRepresentation[2]->RequestSetOrientation(
 
282
    ImageRepresentationType::Coronal );
 
283
 
 
284
  m_ImageRepresentation[3]->RequestSetOrientation(
 
285
    ImageRepresentationType::Axial );
 
286
  m_ImageRepresentation[4]->RequestSetOrientation(
 
287
    ImageRepresentationType::Sagittal );
 
288
  m_ImageRepresentation[5]->RequestSetOrientation(
 
289
    ImageRepresentationType::Coronal );
 
290
 
 
291
  for ( int i=0; i<3; i++)
 
292
    {
 
293
    ViewerGroup->m_Views[i]->RequestRemoveObject( m_ImageRepresentation[i] );
 
294
    ViewerGroup->m_Views[3]->RequestRemoveObject( m_ImageRepresentation[i+3] );
 
295
    ViewerGroup->m_Views[i]->RequestAddObject( m_ImageRepresentation[i] );
 
296
    ViewerGroup->m_Views[3]->RequestAddObject( m_ImageRepresentation[i+3] );
 
297
    }
 
298
 
 
299
  /**
 
300
  *  Add all the spatial object to the views
 
301
  *  Notice the Copy() method is used for most of the representation
 
302
  *  classes but not the path. This is because the underlying geometry
 
303
  *  is fixed for those spatial object once it's created.But the path
 
304
  *  will change it's shape, so we need to keep seperate pointer for
 
305
  *  path representation in each view
 
306
  */
 
307
  for ( int i=0; i<4; i++)
 
308
    {
 
309
    igstk::View::Pointer view =  ViewerGroup->m_Views[i];
 
310
    view->RequestAddObject( m_NeedleTipRepresentation->Copy() );
 
311
    view->RequestAddObject( m_NeedleRepresentation->Copy() );
 
312
    view->RequestAddObject( m_TargetRepresentation->Copy() );
 
313
    view->RequestAddObject( m_EntryRepresentation->Copy() );
 
314
    view->RequestAddObject( m_FiducialRepresentation->Copy() );
 
315
    view->RequestAddObject( m_PathRepresentation[i] );
 
316
    }
 
317
 
 
318
  /** 
 
319
  *  Here we connect the scene graph
 
320
  *  Here we created a virtual world reference system(as the root) and
 
321
  *  attached all the objects as its children.
 
322
  *  This is for the convenience in the following implementation. You 
 
323
  *  use any spatial object, view, tracker, or tracker tool as a 
 
324
  *  reference system in IGSTK. And you can create your own class to
 
325
  *  use the coordinate system API by using this macro:
 
326
  *     igstkCoordinateSystemClassInterfaceMacro()
 
327
  *  Refer to:
 
328
  *      igstkCoordinateSystemInterfaceMacros.h
 
329
  *  Class:
 
330
  *      igstkCoordinateSystem
 
331
  *      igstkCoordinateSystemDelegator
 
332
  */
 
333
  igstk::Transform transform;
 
334
  transform.SetToIdentity( igstk::TimeStamp::GetLongestPossibleTime() );
 
335
  for( int i=0; i<4; i++)
 
336
    {
 
337
    ViewerGroup->m_Views[i]->RequestSetTransformAndParent(
 
338
      transform, m_WorldReference );
 
339
    }
 
340
 
 
341
  m_ImageSpatialObject->RequestSetTransformAndParent(
 
342
    transform, m_WorldReference );
 
343
 
 
344
  m_EntryPoint->RequestSetTransformAndParent( transform, m_WorldReference );
 
345
  m_TargetPoint->RequestSetTransformAndParent( transform, m_WorldReference );
 
346
  m_FiducialPoint->RequestSetTransformAndParent( transform, m_WorldReference );
 
347
  m_Path->RequestSetTransformAndParent( transform, m_WorldReference );
 
348
 
 
349
  m_Needle->RequestSetTransformAndParent( transform, m_WorldReference );
 
350
  m_NeedleTip->RequestSetTransformAndParent( transform, m_WorldReference );
 
351
 
 
352
  /** Reset and enable the view */
 
353
  for( int i=0; i<4; i++)
 
354
    {
 
355
    ViewerGroup->m_Views[i]->RequestResetCamera();
 
356
    ViewerGroup->m_Views[i]->SetRefreshRate( 30 );
 
357
    ViewerGroup->m_Views[i]->RequestStart();
 
358
    ViewerGroup->m_Displays[i]->RequestEnableInteractions();
 
359
    }
 
360
 
 
361
  /** 
 
362
   *  Request information about the slice bounds. The answers will be
 
363
   *  received in the form of events. This will be used to initialize
 
364
   *  the reslicing sliders and initial slice position
 
365
   */
 
366
  SliceBoundsObserver::Pointer boundsObs = SliceBoundsObserver::New();
 
367
  for ( int i=0; i<3; i++)
 
368
    {
 
369
    m_ImageRepresentation[i]->AddObserver(
 
370
      igstk::IntegerBoundsEvent(), boundsObs);
 
371
 
 
372
    m_ImageRepresentation[i]->RequestGetSliceNumberBounds();
 
373
 
 
374
    if( boundsObs->GotSliceBounds() )
 
375
      {
 
376
      const unsigned int min = boundsObs->GetSliceBounds().minimum;
 
377
      const unsigned int max = boundsObs->GetSliceBounds().maximum;
 
378
      const unsigned int slice =
 
379
        static_cast< unsigned int > ( (min + max) / 2.0 );
 
380
      m_ImageRepresentation[i]->RequestSetSliceNumber( slice );
 
381
      m_ImageRepresentation[i+3]->RequestSetSliceNumber( slice );
 
382
      ViewerGroup->m_Sliders[i]->minimum( min );
 
383
      ViewerGroup->m_Sliders[i]->maximum( max );
 
384
      ViewerGroup->m_Sliders[i]->value( slice );
 
385
      ViewerGroup->m_Sliders[i]->activate();
 
386
      boundsObs->Reset();
 
387
      }
 
388
    }
 
389
 
 
390
  /** Adding observer for picking event */
 
391
  for ( int i=0; i<3; i++)
 
392
    {
 
393
    ViewerGroup->m_Views[i]->AddObserver(
 
394
      igstk::CoordinateSystemTransformToEvent(),
 
395
      m_ViewPickerObserver );
 
396
    }
 
397
 
 
398
  /** Adding observer for slider bar reslicing event*/
 
399
  ViewerGroup->AddObserver( igstk::QuadrantViews::ReslicingEvent(),
 
400
    m_ViewResliceObserver );
 
401
}
 
402
 
 
403
/** -----------------------------------------------------------------
 
404
*  Here we read the treatment plan. In this simple example
 
405
*  we assume there is one entry point, one target point, and at least
 
406
*  3 fiducial points. Here is a sample format
 
407
---------------------------------------------------------------------
 
408
# Entry point
 
409
0.820425  -143.635  -186
 
410
# Target point
 
411
54.268    -108.513  -191
 
412
# Fiducial points
 
413
98.4887   -152.976  -181
 
414
-1.89214  -148.996  -191
 
415
-59.2006  -190.563  -191
 
416
--------------------------------------------------------------------
 
417
* Refer to class:
 
418
*        igstkTreatmentPlan
 
419
*        igstkTreatmentPlanIO
 
420
*  -----------------------------------------------------------------
 
421
*/
 
422
void NeedleBiopsy::ReadTreatmentPlan()
 
423
{
 
424
  igstk::TreatmentPlanIO * reader = new igstk::TreatmentPlanIO;
 
425
 
 
426
  m_PlanFilename = m_ImageDir + "_TreatmentPlan.igstk";
 
427
 
 
428
  m_Plan = new igstk::TreatmentPlan;
 
429
 
 
430
  if (itksys::SystemTools::FileExists( m_PlanFilename.c_str()))
 
431
    {
 
432
    reader->SetFileName( m_PlanFilename );
 
433
    if ( reader->RequestRead( ) )
 
434
      {
 
435
      m_Plan = reader->GetTreatmentPlan();
 
436
      }
 
437
    }
 
438
 
 
439
  /** Populate the choice box */
 
440
  TPlanPointList->clear();
 
441
  TPlanPointList->add( "Entry" );
 
442
  TPlanPointList->add( "Target" );
 
443
 
 
444
  m_TrackerLandmarksContainer.clear();
 
445
  char buf[10];
 
446
  for( unsigned int i = 0; i < m_Plan->m_FiducialPoints.size(); i++ )
 
447
    {
 
448
    sprintf( buf, "Fiducial%i", i+1 );
 
449
    TPlanPointList->add( buf );
 
450
    RegistrationType::LandmarkTrackerPointType p;
 
451
    m_TrackerLandmarksContainer.push_back(p);
 
452
    }
 
453
 
 
454
  // Setting object position according to treatment plan
 
455
  m_EntryPoint->RequestSetTransformAndParent( 
 
456
  PointToTransform( m_Plan->m_EntryPoint ), m_WorldReference);
 
457
 
 
458
  m_TargetPoint->RequestSetTransformAndParent( 
 
459
  PointToTransform( m_Plan->m_TargetPoint ), m_WorldReference);
 
460
 
 
461
  this->UpdatePath();
 
462
 
 
463
  TPlanPointList->value(0);
 
464
  ChangeSelectedTPlanPoint();
 
465
}
 
466
 
 
467
/** -----------------------------------------------------------------
 
468
*  Overwrite the current treatment plan to the file
 
469
*  Refer to class:
 
470
*        igstkTreatmentPlan
 
471
*        igstkTreatmentPlanIO
 
472
*---------------------------------------------------------------------
 
473
*/
 
474
void NeedleBiopsy::WriteTreatmentPlan()
 
475
{
 
476
  igstk::TreatmentPlanIO * writer = new igstk::TreatmentPlanIO;
 
477
  writer->SetFileName( m_PlanFilename );
 
478
  writer->SetTreatmentPlan( m_Plan );
 
479
  writer->RequestWrite();
 
480
}
 
481
 
 
482
/** -----------------------------------------------------------------
 
483
*  When changing the selection in the choice box, this function 
 
484
*  reslices images to the current point location, and also show the
 
485
*  position in the annotation in blue. Whenever a point is selected
 
486
*  in the choice box, the picking event will update this point's location
 
487
*  See also:
 
488
*         NeedleBiopsy::Picking
 
489
*---------------------------------------------------------------------
 
490
*/
 
491
void NeedleBiopsy::ChangeSelectedTPlanPoint()
 
492
{
 
493
  if ( TPlanPointList->size() == 0)
 
494
    {
 
495
    return;
 
496
    }
 
497
  
 
498
  /** 
 
499
   * Check which point is selected, the first two are entry and target 
 
500
   * point
 
501
   */
 
502
  ImageSpatialObjectType::PointType    point;
 
503
  int choice = TPlanPointList->value();
 
504
  if( choice == 0 )
 
505
    {
 
506
    point = m_Plan->m_EntryPoint;
 
507
    }
 
508
  else if ( choice == 1 )
 
509
    {
 
510
    point = m_Plan->m_TargetPoint;
 
511
    }
 
512
  else
 
513
    {
 
514
    point = m_Plan->m_FiducialPoints[ choice-2];
 
515
    m_FiducialPoint->RequestSetTransformAndParent(
 
516
                                 PointToTransform(point), m_WorldReference );
 
517
    }
 
518
 
 
519
  /** Display point position as annotation */
 
520
  char buf[50];
 
521
  sprintf( buf, "[%.2f, %.2f, %.2f]", point[0], point[1], point[2]);
 
522
  m_Annotation->RequestSetAnnotationText(0, buf);
 
523
  m_Annotation->RequestSetFontColor(0, 0, 0, 1.0);
 
524
  m_Annotation->RequestSetFontSize(0, 12);
 
525
 
 
526
  /** Reslice image to the selected point position */
 
527
  if( m_ImageSpatialObject->IsInside( point ) )
 
528
    {
 
529
    ImageSpatialObjectType::IndexType index;
 
530
    m_ImageSpatialObject->TransformPhysicalPointToIndex( point, index);
 
531
    igstkLogMacro( DEBUG, index <<"\n");
 
532
    ResliceImage( index );
 
533
    }
 
534
  else
 
535
    {
 
536
    igstkLogMacro( DEBUG,  "This point is not defined in the image...\n" )
 
537
    }
 
538
}
 
539
 
 
540
 
 
541
/** -----------------------------------------------------------------
 
542
*  Choose to connect to a tracker
 
543
*  A tracker specific GUI is initialized, and the observer is hooked
 
544
*  to it to catch the configuration. When the "confirm" button is
 
545
*  pressed, an event loaded with tracker configuration will be sent out.
 
546
*  And it will trigger the RequestInitializeTracker(), which does the 
 
547
*  actual tracker initialization
 
548
*---------------------------------------------------------------------
 
549
*/
 
550
void NeedleBiopsy::RequestConnectToTracker()
 
551
{
 
552
  RequestStopTracking();
 
553
 
 
554
  switch( ConnectToTrackerBtn->value() )
 
555
    {
 
556
    case 0:
 
557
      {
 
558
      igstk::TrackerConfiguration config = igstk::TrackerConfiguration();
 
559
      config.SetTrackerType( igstk::TrackerConfiguration::Polaris );
 
560
      PolarisTrackerConfigurationGUI * gui;
 
561
      m_TrackerConfigurationGUI = gui = new PolarisTrackerConfigurationGUI();
 
562
      m_TrackerConfigurationGUI->SetConfiguration( config );
 
563
      m_TrackerConfigurationGUI->RemoveAllObservers();
 
564
      m_TrackerConfigurationGUI->AddObserver(
 
565
        igstk::TrackerConfigurationGUIBase::ConfigurationEvent(),
 
566
        m_TrackerConfigurationObserver);
 
567
      break;
 
568
      }
 
569
    case 1:
 
570
      {
 
571
      igstk::TrackerConfiguration config = igstk::TrackerConfiguration();
 
572
      config.SetTrackerType( igstk::TrackerConfiguration::Aurora );
 
573
      AuroraTrackerConfigurationGUI * gui;
 
574
      m_TrackerConfigurationGUI = gui = new AuroraTrackerConfigurationGUI();
 
575
      m_TrackerConfigurationGUI->SetConfiguration( config );
 
576
      m_TrackerConfigurationGUI->RemoveAllObservers();
 
577
      m_TrackerConfigurationGUI->AddObserver(
 
578
        igstk::TrackerConfigurationGUIBase::ConfigurationEvent(),
 
579
        m_TrackerConfigurationObserver);
 
580
      break;
 
581
      }
 
582
    case 2:
 
583
      {
 
584
      igstk::TrackerConfiguration config = igstk::TrackerConfiguration();
 
585
      config.SetTrackerType( igstk::TrackerConfiguration::Micron );
 
586
      MicronTrackerConfigurationGUI * gui;
 
587
      m_TrackerConfigurationGUI = gui = new MicronTrackerConfigurationGUI();
 
588
      m_TrackerConfigurationGUI->SetConfiguration( config );
 
589
      m_TrackerConfigurationGUI->RemoveAllObservers();
 
590
      m_TrackerConfigurationGUI->AddObserver(
 
591
        igstk::TrackerConfigurationGUIBase::ConfigurationEvent(),
 
592
        m_TrackerConfigurationObserver);
 
593
      break;
 
594
      }
 
595
    }
 
596
}
 
597
 
 
598
/** -----------------------------------------------------------------
 
599
*  Call back function for ConfigurationEvent observer
 
600
*---------------------------------------------------------------------
 
601
*/
 
602
void NeedleBiopsy::RequestInitializeTracker(const itk::EventObject & event)
 
603
{
 
604
  typedef igstk::TrackerConfigurationGUIBase  GUIType;
 
605
  if ( GUIType::ConfigurationEvent().CheckEvent( &event ) )
 
606
    {
 
607
    GUIType::ConfigurationEvent *confEvent =
 
608
                                   ( GUIType::ConfigurationEvent *) & event;
 
609
 
 
610
    igstk::TrackerConfiguration  tc = confEvent->Get();
 
611
 
 
612
    m_TrackerInitializer = new igstk::TrackerInitializer;
 
613
    m_TrackerInitializer->SetTrackerConfiguration( & tc );
 
614
 
 
615
    if ( m_TrackerInitializer->RequestInitializeTracker() )
 
616
      { 
 
617
      igstk::Tracker::Pointer    tracker = m_TrackerInitializer->GetTracker();
 
618
      igstk::TrackerTool::Pointer tool  = 
 
619
                          m_TrackerInitializer->GetNonReferenceToolList()[0];
 
620
      igstk::TrackerTool::Pointer refTool = 
 
621
                                     m_TrackerInitializer->GetReferenceTool();
 
622
      
 
623
      /** Connect the scene graph with an identity transform first */
 
624
      igstk::Transform transform;
 
625
      transform.SetToIdentity( igstk::TimeStamp::GetLongestPossibleTime() );
 
626
      if ( m_TrackerInitializer->HasReferenceTool() )
 
627
        {
 
628
        refTool->RequestSetTransformAndParent(transform, m_WorldReference);
 
629
        }
 
630
      else
 
631
        {
 
632
        tracker->RequestSetTransformAndParent(transform, m_WorldReference);
 
633
        }
 
634
 
 
635
      /** Now who the registration window and initialize it */
 
636
      RegistrationWindow->show();
 
637
      FiducialNumber->clear();
 
638
      m_TrackerLandmarksContainer.clear();
 
639
      char buf[8];
 
640
      for ( unsigned int i=0; i<m_Plan->m_FiducialPoints.size(); i++)
 
641
        {
 
642
          sprintf( buf, "%d", i+1 );
 
643
          FiducialNumber->add(buf);
 
644
          RegistrationType::LandmarkTrackerPointType p;
 
645
          m_TrackerLandmarksContainer.push_back(p);
 
646
        }
 
647
 
 
648
      /** 
 
649
       *  Set the tracker and image fiducial landmark to the first point
 
650
       *  and reslice the image to show this fiducial point
 
651
       */
 
652
      FiducialNumber->value(0);
 
653
      TPlanPointList->value(2);
 
654
      ChangeSelectedTPlanPoint();
 
655
      }
 
656
    }
 
657
}
 
658
 
 
659
/** -----------------------------------------------------------------
 
660
*  Call this method every time we successfully connect or disconnect to
 
661
*  a tracker. This updates the available tracker and tracker tool
 
662
*  in the GUI list as well as internal pointer list.
 
663
*---------------------------------------------------------------------
 
664
*/
 
665
void NeedleBiopsy::UpdateTrackerAndTrackerToolList()
 
666
{
 
667
  TrackerList->clear();
 
668
  TrackerToolList->clear();
 
669
  m_TrackerToolList.clear();
 
670
  int n = 0;
 
671
  std::string s;
 
672
  for ( unsigned int i=0; i<m_TrackerInitializerList.size(); i++)
 
673
    {
 
674
      char buf[10];
 
675
      sprintf(buf, "%d", i+1);
 
676
      s = "Tracker ";
 
677
      s = s + buf + " [" + 
 
678
                  m_TrackerInitializerList[i]->GetTrackerTypeAsString() + "]";
 
679
      TrackerList->add( s.c_str() );
 
680
      std::vector< igstk::TrackerTool::Pointer > toolList = 
 
681
                      m_TrackerInitializerList[i]->GetNonReferenceToolList();
 
682
      for ( unsigned int j=0; j< toolList.size(); j++)
 
683
        {
 
684
          char buf[10];
 
685
          sprintf(buf,"%d", ++n);
 
686
          s = "Tool ";
 
687
          s = s + buf + " [" + 
 
688
                  m_TrackerInitializerList[i]->GetTrackerTypeAsString() + "]";
 
689
          TrackerToolList->add( s.c_str() );
 
690
          m_TrackerToolList.push_back( toolList[j] );
 
691
        }
 
692
    }
 
693
 
 
694
}
 
695
 
 
696
/** -----------------------------------------------------------------
 
697
*  Disconnect a tracker. After disconnecting it, set the active tool
 
698
*  to the first available tool
 
699
*---------------------------------------------------------------------
 
700
*/
 
701
void NeedleBiopsy::RequestDisconnetTracker()
 
702
{
 
703
  RequestStopTracking();
 
704
  unsigned int n = TrackerList->value();
 
705
  if ( n < m_TrackerInitializerList.size() )
 
706
    {
 
707
    m_TrackerInitializerList[n]->StopAndCloseTracker();
 
708
    m_TrackerInitializerList.erase( m_TrackerInitializerList.begin() + n );
 
709
    UpdateTrackerAndTrackerToolList();
 
710
    if (m_TrackerInitializerList.size()>0)
 
711
      {
 
712
        TrackerList->value(0);
 
713
        TrackerToolList->value(0);
 
714
      }
 
715
    ChangeActiveTrackerTool();
 
716
    }
 
717
}
 
718
 
 
719
/** -----------------------------------------------------------------
 
720
*  Hot switch the active tool, the one that drives the reslicing and
 
721
*  needle display. The reslicing is done by using an observer listening
 
722
*  to the TrackerToolTransformUpdateEvent, and the call back function
 
723
*  will get the tool tip position in the image space and reslice image 
 
724
*  to that point. Refer to:
 
725
*       NeedleBiopsy::Tracking
 
726
*  First, we stop the tracking and disconnect the observer from other tools
 
727
*  Second, we connect observer to the selected tool
 
728
*  Finally, we attach spatial objects representing the needle to this tool
 
729
*           and restart the tracking again
 
730
*---------------------------------------------------------------------
 
731
*/
 
732
void NeedleBiopsy::ChangeActiveTrackerTool()
 
733
{
 
734
  RequestStopTracking();
 
735
  itksys::SystemTools::Delay( 500 );
 
736
 
 
737
  if (m_TrackerToolList.size() != 0)
 
738
    {
 
739
      for (unsigned int i=0; i<m_TrackerToolList.size(); i++)
 
740
      {
 
741
        m_TrackerToolList[i]->RemoveAllObservers();
 
742
      }
 
743
      m_ActiveTool = m_TrackerToolList[ TrackerToolList->value()];
 
744
 
 
745
      m_ActiveTool->AddObserver(
 
746
      igstk::TrackerToolTransformUpdateEvent(), m_TrackerToolUpdateObserver);
 
747
      
 
748
      igstk::Transform transform;
 
749
      transform.SetToIdentity(igstk::TimeStamp::GetLongestPossibleTime());
 
750
      m_Needle->RequestDetachFromParent();
 
751
      m_NeedleTip->RequestDetachFromParent();
 
752
      m_Needle->RequestSetTransformAndParent( transform, m_ActiveTool);
 
753
      m_NeedleTip->RequestSetTransformAndParent( transform, m_ActiveTool);
 
754
    }
 
755
  RequestStartTracking();
 
756
}
 
757
 
 
758
/** -----------------------------------------------------------------
 
759
*  Call back functions for registration window. Every time user clicks
 
760
*  on the set fiducial point button, it will read from the recently
 
761
*  initialized tracker's first non-reference tool. The reading will 
 
762
*  serve as a tracker landmark point for registration. 
 
763
*  This will automatic jump to the next fiducial point for user to set
 
764
*---------------------------------------------------------------------
 
765
*/
 
766
void NeedleBiopsy::SetTrackerFiducialPoint()
 
767
{
 
768
  igstk::TrackerTool::Pointer tool = 
 
769
                           m_TrackerInitializer->GetNonReferenceToolList()[0];
 
770
 
 
771
  typedef igstk::TransformObserver ObserverType;
 
772
  ObserverType::Pointer transformObserver = ObserverType::New();
 
773
  transformObserver->ObserveTransformEventsFrom( tool );
 
774
  transformObserver->Clear();
 
775
  tool->RequestComputeTransformTo( m_WorldReference );
 
776
  if ( transformObserver->GotTransform() )
 
777
    {
 
778
    int n = FiducialNumber->value();
 
779
    int m = FiducialNumber->size();
 
780
    m_TrackerLandmarksContainer[n] = 
 
781
                       TransformToPoint( transformObserver->GetTransform() );
 
782
    std::cout << m_TrackerLandmarksContainer[n] <<"\n";
 
783
    if ( n < m )
 
784
    {
 
785
      FiducialNumber->value(n+1);
 
786
      TPlanPointList->value(n+3);
 
787
      ChangeSelectedTPlanPoint();
 
788
    }
 
789
    } 
 
790
}
 
791
 
 
792
/** -----------------------------------------------------------------
 
793
*  Pair points 3D landmark registration
 
794
*  Image landmarks are from treatment plan. Refer to:
 
795
*         ReadTreatmentPlan
 
796
*         Picking
 
797
* tracker landmarks are set in the registration window. Refer to:
 
798
*         SetTrackerFiducialPoint
 
799
*---------------------------------------------------------------------
 
800
*/
 
801
void NeedleBiopsy::RequestRegistration()
 
802
{
 
803
  m_LandmarkRegistration->RequestResetRegistration();
 
804
  for( unsigned int i=0; i< m_TrackerLandmarksContainer.size(); i++)
 
805
    {
 
806
    m_LandmarkRegistration->RequestAddImageLandmarkPoint( 
 
807
                                               m_Plan->m_FiducialPoints[i] );
 
808
    m_LandmarkRegistration->RequestAddTrackerLandmarkPoint( 
 
809
                                            m_TrackerLandmarksContainer[i] );
 
810
    }
 
811
 
 
812
  m_LandmarkRegistration->RequestComputeTransform();
 
813
 
 
814
  igstk::TransformObserver::Pointer lrtcb = igstk::TransformObserver::New();
 
815
  lrtcb->ObserveTransformEventsFrom( m_LandmarkRegistration );
 
816
  lrtcb->Clear();
 
817
 
 
818
  m_LandmarkRegistration->RequestGetTransformFromTrackerToImage();
 
819
 
 
820
  if( lrtcb->GotTransform() )
 
821
    {
 
822
      RegistrationErrorObserver::Pointer lRmscb =  
 
823
                                            RegistrationErrorObserver::New();
 
824
      m_LandmarkRegistration->AddObserver( igstk::DoubleTypeEvent(), lRmscb );
 
825
      m_LandmarkRegistration->RequestGetRMSError();
 
826
      if( lRmscb->GotRegistrationError() )
 
827
      {
 
828
        std::cout << "\nRegistration Error" << 
 
829
                                  lRmscb->GetRegistrationError() << "\n";
 
830
      }
 
831
 
 
832
    igstk::Transform transform = lrtcb->GetTransform();
 
833
    std::cout << transform << "\n";
 
834
    if ( m_TrackerInitializer->HasReferenceTool() )
 
835
    {
 
836
      m_TrackerInitializer->GetReferenceTool()
 
837
        ->RequestSetTransformAndParent(transform, m_WorldReference);
 
838
    }
 
839
    else
 
840
    {
 
841
      m_TrackerInitializer->GetTracker()
 
842
        ->RequestSetTransformAndParent(transform, m_WorldReference);
 
843
    }
 
844
    
 
845
    /** 
 
846
     * Only when a tracker is registered with the image, it will show up
 
847
     * on the gui as available. Otherwise it will be disconnected
 
848
     */
 
849
    m_TrackerInitializerList.push_back( m_TrackerInitializer );
 
850
    UpdateTrackerAndTrackerToolList();
 
851
    TrackerList->value(m_TrackerInitializerList.size()-1);
 
852
    TrackerToolList->value(m_TrackerInitializerList.size()-1);
 
853
    ChangeActiveTrackerTool();
 
854
    RequestStartTracking();
 
855
    }
 
856
  else
 
857
  {
 
858
    m_TrackerInitializer->StopAndCloseTracker();
 
859
  }
 
860
 
 
861
}
 
862
 
 
863
/** -----------------------------------------------------------------
 
864
*  Start tracking of all the connected trackers  
 
865
*---------------------------------------------------------------------
 
866
*/
 
867
void NeedleBiopsy::RequestStartTracking()
 
868
{
 
869
  for (unsigned int i=0; i<m_TrackerInitializerList.size(); i++)
 
870
    {
 
871
    m_TrackerInitializerList[i]->GetTracker()->RequestStartTracking();
 
872
    }
 
873
 
 
874
  TrackingBtn->label("Stop");
 
875
  TrackingBtn->value(1);
 
876
  ControlGroup->redraw();
 
877
}
 
878
 
 
879
/** -----------------------------------------------------------------
 
880
*  Stop tracking of all the connected trackers  
 
881
*---------------------------------------------------------------------
 
882
*/
 
883
void NeedleBiopsy::RequestStopTracking()
 
884
{
 
885
  for (unsigned int i=0; i<m_TrackerInitializerList.size(); i++)
 
886
  {
 
887
    m_TrackerInitializerList[i]->GetTracker()->RequestStopTracking();
 
888
  }
 
889
 
 
890
  TrackingBtn->label("Tracking");
 
891
  TrackingBtn->value(0);
 
892
  ControlGroup->redraw();
 
893
}
 
894
 
 
895
/** -----------------------------------------------------------------
 
896
*  Callback function for observer listening to the slider bar
 
897
*  ReslicingEvent
 
898
*---------------------------------------------------------------------
 
899
*/
 
900
void NeedleBiopsy::ResliceImage( const itk::EventObject & event )
 
901
{
 
902
 
 
903
  if ( igstk::QuadrantViews::ReslicingEvent().CheckEvent( &event ) )
 
904
    {
 
905
    igstk::QuadrantViews::ReslicingEvent *resliceEvent =
 
906
      ( igstk::QuadrantViews::ReslicingEvent *) & event;
 
907
    this->ResliceImage( resliceEvent->Get() );
 
908
 
 
909
    }
 
910
}
 
911
 
 
912
/** -----------------------------------------------------------------
 
913
*  Methods for reslicing images given an index number  
 
914
*---------------------------------------------------------------------
 
915
*/
 
916
void NeedleBiopsy::ResliceImage ( IndexType index )
 
917
{
 
918
  m_ImageRepresentation[0]->RequestSetSliceNumber( index[2] );
 
919
  m_ImageRepresentation[1]->RequestSetSliceNumber( index[0] );
 
920
  m_ImageRepresentation[2]->RequestSetSliceNumber( index[1] );
 
921
 
 
922
  m_ImageRepresentation[3]->RequestSetSliceNumber( index[2] );
 
923
  m_ImageRepresentation[4]->RequestSetSliceNumber( index[0] );
 
924
  m_ImageRepresentation[5]->RequestSetSliceNumber( index[1] );
 
925
 
 
926
  ViewerGroup->m_AxialSlider->value( index[2] );
 
927
  ViewerGroup->m_SagittalSlider->value( index[0] );
 
928
  ViewerGroup->m_CoronalSlider->value( index[1] );
 
929
 
 
930
  this->ViewerGroup->redraw();
 
931
  Fl::check();
 
932
}
 
933
 
 
934
 
 
935
/** -----------------------------------------------------------------
 
936
*  Callback function for picking event.
 
937
*  Upon receiving a valid picking event, this method will change the 
 
938
*  value of currently selected treatment plan point, reslice the image
 
939
*  to that location, update the annotation with the new point position,
 
940
*  and write the modified treatment plan to the file.
 
941
*---------------------------------------------------------------------
 
942
*/
 
943
void NeedleBiopsy::Picking( const itk::EventObject & event)
 
944
{
 
945
  if ( igstk::CoordinateSystemTransformToEvent().CheckEvent( &event ) )
 
946
    {
 
947
    typedef igstk::CoordinateSystemTransformToEvent TransformEventType;
 
948
    const TransformEventType * tmevent =
 
949
      dynamic_cast< const TransformEventType *>( & event );
 
950
 
 
951
    igstk::CoordinateSystemTransformToResult transformCarrier = tmevent->Get();
 
952
    igstk::Transform  transform = transformCarrier.GetTransform();
 
953
    ImageSpatialObjectType::PointType point = TransformToPoint( transform );
 
954
 
 
955
    if( m_ImageSpatialObject->IsInside( point ) )
 
956
      {
 
957
      int choice = TPlanPointList->value();
 
958
 
 
959
      if( choice == 0 )
 
960
        {
 
961
        m_EntryPoint->RequestSetTransformAndParent( 
 
962
          transform , m_WorldReference );
 
963
        m_Plan->m_EntryPoint = point;
 
964
        this->UpdatePath();
 
965
        }
 
966
      else if ( choice == 1 )
 
967
        {
 
968
        m_TargetPoint->RequestSetTransformAndParent( 
 
969
          transform, m_WorldReference );
 
970
        m_Plan->m_TargetPoint = point;
 
971
        this->UpdatePath();
 
972
        }
 
973
      else
 
974
        {
 
975
        m_FiducialPoint->RequestSetTransformAndParent( 
 
976
          transform, m_WorldReference );
 
977
        m_Plan->m_FiducialPoints[ choice-2] = point;
 
978
        }
 
979
 
 
980
      /** Update annotation */
 
981
      char buf[50];
 
982
      sprintf( buf, "[%.2f, %.2f, %.2f]", point[0], point[1], point[2]);
 
983
      m_Annotation->RequestSetAnnotationText(0, buf);
 
984
      m_Annotation->RequestSetFontColor(0, 1.0, 0, 0);
 
985
      m_Annotation->RequestSetFontSize(0, 12);
 
986
 
 
987
      /** Wirte the updated plan to file */
 
988
      this->WriteTreatmentPlan();
 
989
 
 
990
      /** Reslice image */
 
991
      ImageSpatialObjectType::IndexType index;
 
992
      m_ImageSpatialObject->TransformPhysicalPointToIndex( point, index);
 
993
      igstkLogMacro( DEBUG, index <<"\n")
 
994
      ResliceImage( index );
 
995
      }
 
996
    else
 
997
      {
 
998
      igstkLogMacro( DEBUG,  "Picked point outside image...\n" )
 
999
      }
 
1000
    }
 
1001
}
 
1002
 
 
1003
/** -----------------------------------------------------------------
 
1004
*  Every time we modify the entry point or target point, we need to
 
1005
*  rebuild the geometry of the path, and add them to the View again
 
1006
*---------------------------------------------------------------------
 
1007
*/
 
1008
void NeedleBiopsy::UpdatePath()
 
1009
{
 
1010
  m_Path->Clear();
 
1011
 
 
1012
  TubePointType point;
 
1013
  igstk::Transform::VectorType v;
 
1014
 
 
1015
  v = ( PointToTransform( m_Plan->m_EntryPoint) ).GetTranslation();
 
1016
  point.SetPosition( v[0], v[1], v[2]);
 
1017
  point.SetRadius( 2 );
 
1018
  m_Path->AddPoint( point );
 
1019
 
 
1020
  v = ( PointToTransform( m_Plan->m_TargetPoint) ).GetTranslation();
 
1021
  point.SetPosition( v[0], v[1], v[2]);
 
1022
  point.SetRadius( 2.1 );
 
1023
  m_Path->AddPoint( point );
 
1024
 
 
1025
 
 
1026
  for (int i=0; i<4; i++)
 
1027
    {
 
1028
    ViewerGroup->m_Views[i]->RequestRemoveObject( m_PathRepresentation[i] );
 
1029
    m_PathRepresentation[i]->RequestSetTubeObject( NULL );
 
1030
    m_PathRepresentation[i]->RequestSetTubeObject( m_Path );
 
1031
    m_PathRepresentation[i]->SetColor( 0.0, 1.0, 0.0 );
 
1032
    m_PathRepresentation[i]->SetOpacity( 0.5 );
 
1033
    ViewerGroup->m_Views[i]->RequestAddObject( m_PathRepresentation[i] );
 
1034
    }
 
1035
 
 
1036
}
 
1037
 
 
1038
/** -----------------------------------------------------------------
 
1039
*  Callback function for TrackerToolTransformUpdateEvent
 
1040
*  This function computes the transform of the tooltip location in
 
1041
*  the image space (WorldReference is essential image coordinate system
 
1042
*  since image is attached to WorldReference using an identity transform),
 
1043
*  and reslice image to that tip location
 
1044
*---------------------------------------------------------------------
 
1045
*/
 
1046
 
 
1047
void NeedleBiopsy::Tracking(const itk::EventObject & event )
 
1048
{
 
1049
  if ( igstk::TrackerToolTransformUpdateEvent().CheckEvent( &event ) )
 
1050
  {
 
1051
    typedef igstk::TransformObserver ObserverType;
 
1052
    ObserverType::Pointer transformObserver = ObserverType::New();
 
1053
    transformObserver->ObserveTransformEventsFrom( m_ActiveTool );
 
1054
    transformObserver->Clear();
 
1055
    m_ActiveTool->RequestComputeTransformTo( m_WorldReference );
 
1056
    if ( transformObserver->GotTransform() )
 
1057
      {
 
1058
      ImageSpatialObjectType::PointType point = 
 
1059
                      TransformToPoint( transformObserver->GetTransform() );
 
1060
 
 
1061
      if( m_ImageSpatialObject->IsInside( point ) )
 
1062
      { 
 
1063
        ImageSpatialObjectType::IndexType index;
 
1064
        m_ImageSpatialObject->TransformPhysicalPointToIndex( point, index);
 
1065
        ResliceImage( index );
 
1066
        }
 
1067
      }
 
1068
  }
 
1069
}