1 /*=========================================================================
2 
3   Program:   Visualization Toolkit
4   Module:    vtkImageTracerWidget.cxx
5 
6   Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
7   All rights reserved.
8   See Copyright.txt or http://www.kitware.com/Copyright.htm for details.
9 
10      This software is distributed WITHOUT ANY WARRANTY; without even
11      the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
12      PURPOSE.  See the above copyright notice for more information.
13 
14 =========================================================================*/
15 #include "vtkImageTracerWidget.h"
16 
17 #include "vtkAbstractPicker.h"
18 #include "vtkActor.h"
19 #include "vtkAssemblyPath.h"
20 #include "vtkAssemblyNode.h"
21 #include "vtkCallbackCommand.h"
22 #include "vtkCamera.h"
23 #include "vtkCellArray.h"
24 #include "vtkCellPicker.h"
25 #include "vtkFloatArray.h"
26 #include "vtkGlyphSource2D.h"
27 #include "vtkImageData.h"
28 #include "vtkMath.h"
29 #include "vtkObjectFactory.h"
30 #include "vtkPickingManager.h"
31 #include "vtkPolyData.h"
32 #include "vtkPolyDataMapper.h"
33 #include "vtkPolyLine.h"
34 #include "vtkProperty.h"
35 #include "vtkPropPicker.h"
36 #include "vtkRenderer.h"
37 #include "vtkRenderWindowInteractor.h"
38 #include "vtkTransformPolyDataFilter.h"
39 #include "vtkTransform.h"
40 
41 vtkStandardNewMacro(vtkImageTracerWidget);
42 
43 vtkCxxSetObjectMacro(vtkImageTracerWidget, HandleProperty, vtkProperty);
44 vtkCxxSetObjectMacro(vtkImageTracerWidget, SelectedHandleProperty, vtkProperty);
45 vtkCxxSetObjectMacro(vtkImageTracerWidget, LineProperty, vtkProperty);
46 vtkCxxSetObjectMacro(vtkImageTracerWidget, SelectedLineProperty, vtkProperty);
47 
vtkImageTracerWidget()48 vtkImageTracerWidget::vtkImageTracerWidget()
49 {
50   this->HandleLeftMouseButton = true;
51   this->HandleMiddleMouseButton = true;
52   this->HandleRightMouseButton = true;
53 
54   this->State = vtkImageTracerWidget::Start;
55   this->EventCallbackCommand->SetCallback(vtkImageTracerWidget::ProcessEvents);
56 
57   this->Interaction = 1;
58   this->ViewProp = NULL;
59   this->PickCount = 0;
60   this->SnapToImage = 0;
61   this->AutoClose = 0;
62   this->CaptureRadius = 1.0;
63   this->IsSnapping = 0;
64   this->ImageSnapType = VTK_ITW_SNAP_CELLS;
65   this->CurrentPicker = NULL;
66   this->CurrentHandle = NULL;
67   this->CurrentHandleIndex = -1;
68   this->ProjectionNormal = VTK_ITW_PROJECTION_XY;
69   this->ProjectionPosition = 0.0;
70   this->ProjectToPlane = 0;
71   this->NumberOfHandles = 0;
72   this->LastX = 0;
73   this->LastY = 0;
74 
75   this->PropPicker = vtkPropPicker::New();
76   this->PropPicker->PickFromListOn();
77 
78   // Build the representation of the widget
79   this->HandleGenerator = vtkGlyphSource2D::New();
80   this->HandleGenerator->SetGlyphTypeToCross();
81   this->HandleGenerator->FilledOff();
82   this->HandleGenerator->SetCenter(0,0,0);
83 
84   this->TransformFilter = vtkTransformPolyDataFilter::New();
85   this->Transform = vtkTransform::New();
86   this->TransformFilter->SetTransform(this->Transform);
87   this->Transform->Identity();
88   this->TransformFilter->SetInputConnection(
89     this->HandleGenerator->GetOutputPort());
90   this->TransformFilter->Update();
91 
92   this->TemporaryHandlePoints = vtkFloatArray::New();
93   this->TemporaryHandlePoints->SetNumberOfComponents(3);
94 
95   this->LinePoints = vtkPoints::New();
96   this->LinePoints->Allocate(1001);
97   this->LineCells = vtkCellArray::New();
98   this->LineCells->Allocate(this->LineCells->EstimateSize(1000,2));
99   this->LineActor = vtkActor::New();
100   vtkPolyDataMapper* lineMapper = vtkPolyDataMapper::New();
101   this->LineData = vtkPolyData::New();
102 
103   lineMapper->SetInputData(this->LineData);
104   lineMapper->SetResolveCoincidentTopologyToPolygonOffset();
105   lineMapper->ScalarVisibilityOff();
106   this->LineActor->SetMapper(lineMapper);
107   this->LineActor->PickableOff();
108   this->LineActor->VisibilityOff();
109   lineMapper->Delete();
110 
111   // Manage the picking stuff
112   this->HandlePicker = vtkCellPicker::New();
113   this->HandlePicker->SetTolerance(0.005);
114   this->HandlePicker->PickFromListOn();
115 
116   this->LinePicker = vtkCellPicker::New();
117   this->LinePicker->SetTolerance(0.005);
118   this->LinePicker->PickFromListOn();
119 
120   // Set up the initial properties
121   this->HandleProperty = NULL;
122   this->SelectedHandleProperty = NULL;
123   this->LineProperty = NULL;
124   this->SelectedLineProperty = NULL;
125   this->CreateDefaultProperties();
126 
127   // Initialize ivars
128   this->Handle = NULL;
129   this->HandleGeometry = NULL;
130 
131   // Create one handle
132   this->AllocateHandles(1);
133   this->AdjustHandlePosition(0,this->HandleGenerator->GetCenter());
134 
135   // Initial creation of the widget, serves to initialize it
136   // using default bounds to get started
137   double bounds[6];
138   vtkMath::UninitializeBounds(bounds);
139 
140   this->PlaceFactor = 1.0;
141   this->PlaceWidget(bounds);
142 }
143 
~vtkImageTracerWidget()144 vtkImageTracerWidget::~vtkImageTracerWidget()
145 {
146   for ( int i = 0; i < this->NumberOfHandles; ++i )
147     {
148     this->HandleGeometry[i]->Delete();
149     this->Handle[i]->Delete();
150     }
151   delete [] this->Handle;
152   this->Handle = NULL;
153 
154   delete [] this->HandleGeometry;
155   this->HandleGeometry = NULL;
156 
157   if ( this->HandleProperty )
158     {
159     this->HandleProperty->Delete();
160     }
161   if ( this->SelectedHandleProperty )
162     {
163     this->SelectedHandleProperty->Delete();
164     }
165   if ( this->LineProperty )
166     {
167     this->LineProperty->Delete();
168     }
169   if ( this->SelectedLineProperty )
170     {
171     this->SelectedLineProperty->Delete();
172     }
173   if ( this->ViewProp )
174     {
175     this->ViewProp->UnRegister(this);
176     }
177 
178   this->LinePoints->Delete();
179   this->LineCells->Delete();
180   this->LineActor->Delete();
181   this->LineData->Delete();
182 
183   this->LinePicker->Delete();
184   this->HandlePicker->Delete();
185   this->CurrentPicker = NULL;
186   this->CurrentHandle = NULL;
187 
188   this->PropPicker->Delete();
189   this->TransformFilter->Delete();
190   this->Transform->Delete();
191   this->TemporaryHandlePoints->Delete();
192   this->HandleGenerator->Delete();
193 }
194 
195 //----------------------------------------------------------------------------
SetViewProp(vtkProp * prop)196 void vtkImageTracerWidget::SetViewProp(vtkProp* prop)
197 {
198   if ( this->ViewProp != prop )
199     {
200     // Avoid destructor recursion
201     vtkProp *temp = this->ViewProp;
202     this->ViewProp = prop;
203     if ( temp )
204       {
205       temp->UnRegister(this);
206       }
207     if ( this->ViewProp )
208       {
209       this->ViewProp->Register(this);
210       this->PropPicker->InitializePickList();
211       this->PropPicker->AddPickList(this->ViewProp);
212       }
213     }
214 }
215 
216 //------------------------------------------------------------------------------
RegisterPickers()217 void vtkImageTracerWidget::RegisterPickers()
218 {
219   this->Interactor->GetPickingManager()->AddPicker(this->PropPicker, this);
220   this->Interactor->GetPickingManager()->AddPicker(this->HandlePicker, this);
221   this->Interactor->GetPickingManager()->AddPicker(this->LinePicker, this);
222 }
223 
SetEnabled(int enabling)224 void vtkImageTracerWidget::SetEnabled(int enabling)
225 {
226   if ( !this->Interactor )
227     {
228     vtkErrorMacro(<<"The interactor must be set prior to enabling/disabling widget");
229     return;
230     }
231 
232   if ( !this->ViewProp )
233     {
234     vtkErrorMacro(<<"The external prop must be set prior to enabling/disabling widget");
235     return;
236     }
237 
238   if ( enabling )
239     {
240     vtkDebugMacro(<<"Enabling line widget");
241 
242     if ( this->Enabled ) //already enabled, just return
243       {
244       return;
245       }
246 
247     if ( !this->CurrentRenderer )
248       {
249       this->SetCurrentRenderer(this->Interactor->FindPokedRenderer(
250                                this->Interactor->GetLastEventPosition()[0],
251                                this->Interactor->GetLastEventPosition()[1]));
252       if ( !this->CurrentRenderer )
253         {
254         return;
255         }
256       }
257 
258     this->Enabled = 1;
259 
260     this->AddObservers();
261 
262     // Turn on the handles
263     for ( int i = 0; i < this->NumberOfHandles; ++i )
264       {
265       this->CurrentRenderer->AddViewProp(this->Handle[i]);
266       this->Handle[i]->SetProperty(this->HandleProperty);
267       this->Handle[i]->PickableOff();
268       }
269 
270     this->SizeHandles();
271 
272     this->CurrentRenderer->AddViewProp(this->LineActor);
273     this->LineActor->SetProperty(this->LineProperty);
274     this->LineActor->PickableOff();
275 
276     this->InvokeEvent(vtkCommand::EnableEvent,NULL);
277     }
278 
279   else // disabling
280     {
281     vtkDebugMacro(<<"Disabling tracer widget");
282 
283     if ( !this->Enabled ) //already disabled, just return
284       {
285       return;
286       }
287 
288     // if disabling occurs without finishing an activity, cleanup states
289     if ( this->State == vtkImageTracerWidget::Tracing )
290       {
291       this->OnLeftButtonUp();
292       }
293     else if ( this->State == vtkImageTracerWidget::Snapping )
294       {
295       this->Interactor->SetControlKey( 1 );
296       this->OnMiddleButtonUp();
297       }
298 
299     this->Enabled = 0;
300 
301     // Don't listen for events any more
302     this->Interactor->RemoveObserver(this->EventCallbackCommand);
303 
304     // Turn off the handles
305     for ( int i = 0; i < this->NumberOfHandles; ++i )
306      {
307      this->CurrentRenderer->RemoveViewProp(this->Handle[i]);
308      }
309 
310     this->CurrentRenderer->RemoveViewProp(this->LineActor);
311 
312     this->CurrentHandle = NULL;
313     this->InvokeEvent(vtkCommand::DisableEvent,NULL);
314     this->SetCurrentRenderer(NULL);
315     }
316 
317   this->Interactor->Render();
318 }
319 
ProcessEvents(vtkObject * vtkNotUsed (object),unsigned long event,void * clientdata,void * vtkNotUsed (calldata))320 void vtkImageTracerWidget::ProcessEvents(vtkObject* vtkNotUsed(object),
321                                   unsigned long event,
322                                   void* clientdata,
323                                   void* vtkNotUsed(calldata))
324 {
325   vtkImageTracerWidget* self = reinterpret_cast<vtkImageTracerWidget *>( clientdata );
326 
327   switch ( event )
328     {
329     case vtkCommand::LeftButtonPressEvent:
330       self->OnLeftButtonDown();
331       break;
332     case vtkCommand::LeftButtonReleaseEvent:
333       self->OnLeftButtonUp();
334       break;
335     case vtkCommand::MiddleButtonPressEvent:
336       self->OnMiddleButtonDown();
337       break;
338     case vtkCommand::MiddleButtonReleaseEvent:
339       self->OnMiddleButtonUp();
340       break;
341     case vtkCommand::RightButtonPressEvent:
342       self->OnRightButtonDown();
343       break;
344     case vtkCommand::RightButtonReleaseEvent:
345       self->OnRightButtonUp();
346       break;
347     case vtkCommand::MouseMoveEvent:
348       self->OnMouseMove();
349       break;
350     }
351 }
352 
AddObservers(void)353 void vtkImageTracerWidget::AddObservers(void)
354 {
355   // Listen for the following events
356   vtkRenderWindowInteractor *i = this->Interactor;
357   if(!i)
358     {
359     return;
360     }
361 
362   i->AddObserver(vtkCommand::MouseMoveEvent, this->EventCallbackCommand,
363                   this->Priority);
364   if(this->HandleLeftMouseButton)
365     {
366     i->AddObserver(vtkCommand::LeftButtonPressEvent,
367                     this->EventCallbackCommand, this->Priority);
368     i->AddObserver(vtkCommand::LeftButtonReleaseEvent,
369                     this->EventCallbackCommand, this->Priority);
370     }
371   if(this->HandleMiddleMouseButton)
372     {
373     i->AddObserver(vtkCommand::MiddleButtonPressEvent,
374                     this->EventCallbackCommand, this->Priority);
375     i->AddObserver(vtkCommand::MiddleButtonReleaseEvent,
376                     this->EventCallbackCommand, this->Priority);
377     }
378   if(this->HandleRightMouseButton)
379     {
380     i->AddObserver(vtkCommand::RightButtonPressEvent,
381                     this->EventCallbackCommand, this->Priority);
382     i->AddObserver(vtkCommand::RightButtonReleaseEvent,
383                     this->EventCallbackCommand, this->Priority);
384     }
385 }
386 
SetInteraction(int interact)387 void vtkImageTracerWidget::SetInteraction(int interact)
388 {
389   if ( this->Interactor && this->Enabled )
390     {
391     if ( this->Interaction == interact )
392       {
393       return;
394       }
395     if ( interact == 0 )
396       {
397       this->Interactor->RemoveObserver(this->EventCallbackCommand);
398       }
399     else
400       {
401       this->AddObservers();
402       }
403     this->Interaction = interact;
404     }
405   else
406     {
407     vtkGenericWarningMacro(<<"Set interactor and Enabled before changing interaction...");
408     }
409 }
410 
PrintSelf(ostream & os,vtkIndent indent)411 void vtkImageTracerWidget::PrintSelf(ostream& os, vtkIndent indent)
412 {
413   this->Superclass::PrintSelf(os,indent);
414 
415   if ( this->HandleProperty )
416     {
417     os << indent << "Handle Property: " << this->HandleProperty << "\n";
418     }
419   else
420     {
421     os << indent << "Handle Property: (none)\n";
422     }
423 
424   if ( this->SelectedHandleProperty )
425     {
426     os << indent << "Selected Handle Property: "
427        << this->SelectedHandleProperty << "\n";
428     }
429   else
430     {
431     os << indent << "Selected Handle Property: (none)\n";
432     }
433 
434   if ( this->LineProperty )
435     {
436     os << indent << "Line Property: " << this->LineProperty << "\n";
437     }
438   else
439     {
440     os << indent << "Line Property: (none)\n";
441     }
442 
443   if ( this->SelectedLineProperty )
444     {
445     os << indent << "Selected Line Property: "
446        << this->SelectedLineProperty << "\n";
447     }
448   else
449     {
450     os << indent << "Selected Line Property: (none)\n";
451     }
452 
453   if ( this->ViewProp )
454     {
455     os << indent << "ViewProp: " << this->ViewProp << "\n";
456     }
457   else
458     {
459     os << indent << "ViewProp: (none)\n";
460     }
461 
462   os << indent << "Interaction: "
463      << (this->Interaction ? "On\n" : "Off\n") ;
464   os << indent << "ProjectionNormal: " << this->ProjectionNormal << "\n";
465   os << indent << "ProjectionPosition: " << this->ProjectionPosition << "\n";
466   os << indent << "ProjectToPlane: "
467      << (this->ProjectToPlane ? "On\n" : "Off\n") ;
468   os << indent << "ImageSnapType: " << this->ImageSnapType << "\n";
469   os << indent << "SnapToImage: "
470      << (this->SnapToImage ? "On\n" : "Off\n") ;
471   os << indent << "CaptureRadius: " << this->CaptureRadius << "\n";
472   os << indent << "NumberOfHandles: " << this->NumberOfHandles << "\n";
473   os << indent << "HandleLeftMouseButton: " << this->HandleLeftMouseButton << "\n";
474   os << indent << "HandleMiddleMouseButton: " << this->HandleMiddleMouseButton << "\n";
475   os << indent << "HandleRightMouseButton: " << this->HandleRightMouseButton << "\n";
476   os << indent << "AutoClose: "
477      << (this->AutoClose ? "On\n" : "Off\n") ;
478 }
479 
HighlightHandle(vtkProp * prop)480 int vtkImageTracerWidget::HighlightHandle(vtkProp* prop)
481 {
482   // First unhighlight anything picked
483   if ( this->CurrentHandle )
484     {
485     this->CurrentHandle->SetProperty(this->HandleProperty);
486     this->Interactor->Render();
487     }
488 
489   this->CurrentHandle = static_cast<vtkActor *>(prop);
490 
491   if ( this->CurrentHandle )
492     {
493     this->ValidPick = 1;
494     this->CurrentPicker->GetPickPosition(this->LastPickPosition);
495     this->CurrentHandle->SetProperty(this->SelectedHandleProperty);
496     for ( int i = 0; i < this->NumberOfHandles; ++i ) // find handle
497       {
498       if ( this->CurrentHandle == this->Handle[i] )
499         {
500         return i;
501         }
502       }
503     }
504   return -1;
505 }
506 
HighlightLine(const int & highlight)507 void vtkImageTracerWidget::HighlightLine(const int& highlight)
508 {
509   if ( highlight )
510     {
511     this->ValidPick = 1;
512     this->CurrentPicker->GetPickPosition(this->LastPickPosition);
513     this->LineActor->SetProperty(this->SelectedLineProperty);
514     }
515   else
516     {
517     this->LineActor->SetProperty(this->LineProperty);
518     }
519 }
520 
AdjustHandlePosition(const int & handle,double pos[3])521 void vtkImageTracerWidget::AdjustHandlePosition(const int& handle, double pos[3])
522 {
523   if ( handle < 0 || handle >= this->NumberOfHandles ){ return; }
524 
525   if ( this->ProjectToPlane )
526     {
527     pos[this->ProjectionNormal] = this->ProjectionPosition;
528     }
529 
530   this->HandleGenerator->SetCenter(0.0,0.0,0.0);
531   this->Transform->Identity();
532   this->Transform->PostMultiply();
533 
534   if ( this->ProjectionNormal == VTK_ITW_PROJECTION_YZ )
535     {
536     this->Transform->RotateY(90.0);
537     }
538   else if ( this->ProjectionNormal == VTK_ITW_PROJECTION_XZ )
539     {
540     this->Transform->RotateX(90.0);
541     }
542 
543   this->Transform->Translate(pos);
544   this->TransformFilter->Update();
545 
546   this->HandleGeometry[handle]->CopyStructure(this->TransformFilter->GetOutput());
547   this->HandleGeometry[handle]->Modified();
548 }
549 
SetProjectionPosition(double position)550 void vtkImageTracerWidget::SetProjectionPosition(double position)
551 {
552   this->ProjectionPosition = position;
553 
554   int i;
555   for ( i = 0; i < this->NumberOfHandles; ++i )
556     {
557     this->AdjustHandlePosition(i,this->HandleGeometry[i]->GetCenter());
558     }
559 
560   double pt[3];
561   for ( i = 0; i < this->NumberOfHandles; ++i )
562     {
563     this->LinePoints->GetPoint(i,pt);
564     pt[ this->ProjectionNormal ] = this->ProjectionPosition;
565     this->LinePoints->SetPoint(i,pt);
566     }
567 
568   this->LinePoints->GetData()->Modified();
569   this->LineData->Modified();
570 }
571 
SetHandlePosition(int handle,double xyz[3])572 void vtkImageTracerWidget::SetHandlePosition(int handle, double xyz[3])
573 {
574   this->AdjustHandlePosition(handle, xyz);
575 }
576 
SetHandlePosition(int handle,double x,double y,double z)577 void vtkImageTracerWidget::SetHandlePosition(int handle, double x, double y, double z)
578 {
579   double xyz[3] = {x,y,z};
580   this->AdjustHandlePosition(handle, xyz);
581 }
582 
GetHandlePosition(int handle,double xyz[3])583 void vtkImageTracerWidget::GetHandlePosition(int handle, double xyz[3])
584 {
585   if ( handle < 0 || handle >= this->NumberOfHandles ){ return; }
586   this->HandleGeometry[handle]->GetCenter(xyz);
587 }
588 
GetHandlePosition(int handle)589 double* vtkImageTracerWidget::GetHandlePosition(int handle)
590 {
591   if ( handle < 0 || handle >= this->NumberOfHandles ){ return NULL; }
592   return this->HandleGeometry[handle]->GetCenter();
593 }
594 
OnLeftButtonDown()595 void vtkImageTracerWidget::OnLeftButtonDown()
596 {
597   // If the user is snap defining a line by middle mouse button,
598   // ignore this button
599   if ( this->State == vtkImageTracerWidget::Snapping ){ return; }
600 
601   int X = this->Interactor->GetEventPosition()[0];
602   int Y = this->Interactor->GetEventPosition()[1];
603 
604   // Okay, make sure that the pick is in the current renderer
605   if ( !this->CurrentRenderer || !this->CurrentRenderer->IsInViewport(X,Y) )
606     {
607     this->State = vtkImageTracerWidget::Outside;
608     return;
609     }
610 
611   int found = 0;
612   if ( this->PropPicker->PickProp(X,Y,this->CurrentRenderer) )
613     {
614     if ( this->ViewProp == this->PropPicker->GetViewProp() )
615       {
616       found = 1;
617       this->State = vtkImageTracerWidget::Tracing;
618       }
619     }
620 
621    if ( !found )
622      {
623      this->State = vtkImageTracerWidget::Outside;
624      return;
625      }
626 
627   // first erase any handles if there any
628   if ( this->NumberOfHandles > 1 )
629     {
630     this->AllocateHandles(1);
631     }
632 
633   this->CurrentPicker = this->PropPicker;  //collect the pick position from the prop picker
634   this->CurrentHandleIndex = this->HighlightHandle(this->Handle[0]);
635 
636   if ( this->CurrentHandleIndex == -1 )    //this should never happen
637     {
638     this->State = vtkImageTracerWidget::Outside;
639     return;
640     }
641 
642   // set the handle to the picked position
643   this->AdjustHandlePosition(this->CurrentHandleIndex,this->LastPickPosition);
644 
645   // erase the line and initialize it
646   this->ResetLine(this->LastPickPosition);
647 
648   this->LastX = X;
649   this->LastY = Y;
650 
651   this->EventCallbackCommand->SetAbortFlag(1);
652   this->StartInteraction();
653   this->InvokeEvent(vtkCommand::StartInteractionEvent,NULL);
654   this->Interactor->Render();
655 }
656 
OnLeftButtonUp()657 void vtkImageTracerWidget::OnLeftButtonUp()
658 {
659   if ( this->State == vtkImageTracerWidget::Outside ||
660        this->State == vtkImageTracerWidget::Start   ||
661        this->State == vtkImageTracerWidget::Snapping )
662     {
663     return;
664     }
665 
666   this->State = vtkImageTracerWidget::Start;
667   this->CurrentHandleIndex = this->HighlightHandle(NULL);
668 
669   if ( this->AutoClose )  // attempt to close by tolerance
670     {
671     this->ClosePath();
672     if ( this->IsClosed() ) // if successful, remove the overlapping handle
673       {
674       this->EraseHandle(this->NumberOfHandles - 1);
675       }
676     }
677 
678   this->SizeHandles();
679 
680   this->EventCallbackCommand->SetAbortFlag(1);
681   this->EndInteraction();
682   this->InvokeEvent(vtkCommand::EndInteractionEvent,NULL);
683   this->Interactor->Render();
684   this->CurrentPicker = NULL;
685 }
686 
OnMiddleButtonDown()687 void vtkImageTracerWidget::OnMiddleButtonDown()
688 {
689   int X = this->Interactor->GetEventPosition()[0];
690   int Y = this->Interactor->GetEventPosition()[1];
691 
692   if ( !this->CurrentRenderer || !this->CurrentRenderer->IsInViewport(X,Y) )
693     {
694     this->State = vtkImageTracerWidget::Outside;
695     return;
696     }
697 
698   int found = 0;
699   if ( this->PropPicker->PickProp(X,Y,this->CurrentRenderer) )
700     {
701     if ( this->ViewProp == this->PropPicker->GetViewProp() )
702       {
703       found = 1;
704       this->State = vtkImageTracerWidget::Snapping; // do snap tracing
705       }
706     }
707 
708    if ( !found )
709      {
710      this->State = vtkImageTracerWidget::Outside;
711      return;
712      }
713 
714   if ( !this->IsSnapping )  // this is the first time so reset the handles
715     {
716     if ( this->NumberOfHandles > 1 )
717       {
718       this->AllocateHandles(1);
719       }
720     }
721 
722   this->CurrentPicker = this->PropPicker;         // highlight the last handle
723   this->CurrentHandleIndex = this->HighlightHandle(this->Handle[this->NumberOfHandles - 1]);
724 
725   if ( this->CurrentHandleIndex == -1 )  // sanity check: this should never happen
726     {
727     this->State = vtkImageTracerWidget::Outside;
728     return;
729     }
730 
731   this->AdjustHandlePosition(this->CurrentHandleIndex,this->LastPickPosition);
732 
733   if ( !this->IsSnapping )  // this is the first time so initialize the line
734     {
735     this->ResetLine(this->GetHandlePosition(this->CurrentHandleIndex));
736     }
737 
738   this->IsSnapping = this->NumberOfHandles;
739 
740   this->EventCallbackCommand->SetAbortFlag(1);
741   this->StartInteraction();
742   this->InvokeEvent(vtkCommand::StartInteractionEvent,NULL);
743   this->Interactor->Render();
744 }
745 
OnMiddleButtonUp()746 void vtkImageTracerWidget::OnMiddleButtonUp()
747 {
748   if ( this->State == vtkImageTracerWidget::Outside ||
749        this->State == vtkImageTracerWidget::Start )
750     {
751     return;
752     }
753 
754   if ( this->Interactor->GetControlKey() ) // finished the snapping
755     {
756     this->IsSnapping = 0;
757     }
758   else // continue snap drawing
759     {
760     return;
761     }
762 
763   this->State = vtkImageTracerWidget::Start;
764   this->CurrentHandleIndex = this->HighlightHandle(NULL);
765 
766   if ( this->AutoClose )
767     {
768     this->ClosePath();
769     if ( this->IsClosed() ) // if successful, remove the last overlapping handle
770       {
771       this->EraseHandle(this->NumberOfHandles - 1);
772       }
773     }
774 
775   this->SizeHandles();
776 
777   this->EventCallbackCommand->SetAbortFlag(1);
778   this->EndInteraction();
779   this->InvokeEvent(vtkCommand::EndInteractionEvent,NULL);
780   this->Interactor->Render();
781   this->CurrentPicker = NULL;
782 }
783 
OnRightButtonDown()784 void vtkImageTracerWidget::OnRightButtonDown()
785 {
786   if ( this->State == vtkImageTracerWidget::Snapping ){ return; }
787 
788   int X = this->Interactor->GetEventPosition()[0];
789   int Y = this->Interactor->GetEventPosition()[1];
790 
791   if ( !this->CurrentRenderer || !this->CurrentRenderer->IsInViewport(X,Y) )
792     {
793     this->State = vtkImageTracerWidget::Outside;
794     return;
795     }
796 
797   if ( this->Interactor->GetControlKey() && (this->NumberOfHandles > 1) )
798     {
799     this->State = vtkImageTracerWidget::Erasing; // pick a handle to delete
800     for ( int i = 0; i < this->NumberOfHandles; ++i )
801       {
802       this->Handle[i]->PickableOn();
803       }
804     this->CurrentPicker = this->HandlePicker;
805     }
806   else if ( this->Interactor->GetShiftKey()  && (this->NumberOfHandles > 1) )
807     {
808     this->State = vtkImageTracerWidget::Inserting; // pick a line to insert on
809     this->LineActor->PickableOn();
810     this->LinePicker->AddPickList(this->LineActor);
811     this->CurrentPicker = this->LinePicker;
812     }
813   else
814     {
815     if ( this->NumberOfHandles < 3 && this->LinePoints->GetNumberOfPoints() > this->NumberOfHandles )
816       {
817       this->State = vtkImageTracerWidget::Translating;
818       }
819     else
820       {
821       this->State = vtkImageTracerWidget::Moving;
822       }
823     for ( int i = 0; i < this->NumberOfHandles; ++i )
824       {
825       this->Handle[i]->PickableOn();
826       }
827     this->CurrentPicker = this->HandlePicker;
828     }
829 
830   if ( this->ViewProp )  // don't pick the prop
831     {
832     this->ViewProp->PickableOff();
833     }
834 
835   int found = 0;
836   vtkAssemblyPath* path = this->GetAssemblyPath(X, Y, 0., this->CurrentPicker);
837 
838   if ( path )
839     {
840     found = 1;
841     if ( this->State == vtkImageTracerWidget::Erasing ||
842          this->State == vtkImageTracerWidget::Moving  ||
843          this->State == vtkImageTracerWidget::Translating )
844       {
845       this->CurrentHandleIndex = this->HighlightHandle(path->GetFirstNode()->GetViewProp());
846       if ( this->CurrentHandleIndex == -1 )
847         {
848         found = 0;  // we didn't hit a handle
849         for ( int i = 0; i < this->NumberOfHandles; ++i )
850           {
851           this->Handle[i]->PickableOff();
852           }
853         }
854       }
855     else if ( this->State == vtkImageTracerWidget::Inserting )
856       {
857         if ( static_cast<vtkActor*>(path->GetFirstNode()->GetViewProp()) == this->LineActor )
858         {
859         this->HighlightLine(1);
860         }
861       else
862         {
863         found = 0;
864         this->LineActor->PickableOff();
865         }
866       }
867     }
868 
869   if ( !found )
870     {
871     this->State = vtkImageTracerWidget::Outside;
872     if ( this->ViewProp )
873       {
874       this->ViewProp->PickableOn();
875       }
876     this->CurrentPicker = NULL;
877     return;
878     }
879 
880   this->EventCallbackCommand->SetAbortFlag(1);
881   this->StartInteraction();
882   this->InvokeEvent(vtkCommand::StartInteractionEvent,NULL);
883   this->Interactor->Render();
884 }
885 
OnRightButtonUp()886 void vtkImageTracerWidget::OnRightButtonUp()
887 {
888   if ( this->State == vtkImageTracerWidget::Outside ||
889        this->State == vtkImageTracerWidget::Start   ||
890        this->State == vtkImageTracerWidget::Snapping)
891     {
892     return;
893     }
894 
895   if ( this->State == vtkImageTracerWidget::Erasing )
896     {
897     int index = this->CurrentHandleIndex;
898     this->CurrentHandleIndex = this->HighlightHandle(NULL);
899     int closed = this->IsClosed();
900     this->EraseHandle(index);
901     this->BuildLinesFromHandles();
902     if ( closed && this->NumberOfHandles > 2 )
903       {
904       this->AppendLine(this->HandleGeometry[0]->GetCenter());
905       }
906     }
907   else if ( this->State == vtkImageTracerWidget::Inserting )
908     {
909     this->HighlightLine(0);
910     int closed = this->IsClosed();
911     this->InsertHandleOnLine(this->LastPickPosition);
912     this->BuildLinesFromHandles();
913     if ( closed )
914       {
915       this->AppendLine(this->HandleGeometry[0]->GetCenter());
916       }
917     }
918   else if ( this->State == vtkImageTracerWidget::Moving )
919     {
920     this->CurrentHandleIndex = this->HighlightHandle(NULL);
921     if ( this->AutoClose && !this->IsClosed() )
922       {
923       this->ClosePath();
924       if ( this->IsClosed() ) // if successful, remove the last overlapping handle
925         {
926         this->EraseHandle(this->NumberOfHandles - 1);
927         }
928       }
929     }
930   else if ( this->State == vtkImageTracerWidget::Translating )
931     {
932     this->CurrentHandleIndex = this->HighlightHandle(NULL);
933     }
934 
935   this->State = vtkImageTracerWidget::Start;
936 
937   this->SizeHandles();
938 
939   if ( this->ViewProp )
940     {
941     this->ViewProp->PickableOn();
942     }
943 
944   this->EventCallbackCommand->SetAbortFlag(1);
945   this->EndInteraction();
946   this->InvokeEvent(vtkCommand::EndInteractionEvent,NULL);
947   this->Interactor->Render();
948   this->CurrentPicker = NULL;
949 }
950 
OnMouseMove()951 void vtkImageTracerWidget::OnMouseMove()
952 {
953   // See whether we're active
954   if ( this->State == vtkImageTracerWidget::Outside ||
955        this->State == vtkImageTracerWidget::Start )
956     {
957     return;
958     }
959 
960   int X = this->Interactor->GetEventPosition()[0];
961   int Y = this->Interactor->GetEventPosition()[1];
962   double z;
963 
964   // Process the motion
965   if ( this->CurrentHandle )
966     {
967     if ( this->State == vtkImageTracerWidget::Tracing ||
968          this->State == vtkImageTracerWidget::Snapping )
969       {
970       this->Trace(X,Y);
971       }
972     else if ( this->State == vtkImageTracerWidget::Moving ||
973               this->State == vtkImageTracerWidget::Translating )
974       {
975       double focalPoint[4], pickPoint[4], prevPickPoint[4];
976 
977       vtkCamera *camera = this->CurrentRenderer->GetActiveCamera();
978       if ( !camera ){ return; }
979 
980       // Compute the two points defining the motion vector
981       this->ComputeWorldToDisplay(this->LastPickPosition[0],
982                                   this->LastPickPosition[1],
983                                   this->LastPickPosition[2], focalPoint);
984       z = focalPoint[2];
985       this->ComputeDisplayToWorld(
986                       double(this->Interactor->GetLastEventPosition()[0]),
987                       double(this->Interactor->GetLastEventPosition()[1]),
988                       z, prevPickPoint);
989       this->ComputeDisplayToWorld(double(X), double(Y), z, pickPoint);
990 
991       if ( this->State == vtkImageTracerWidget::Moving )
992         {
993         this->MovePoint(prevPickPoint, pickPoint);
994         }
995       else
996         {
997         this->Translate(prevPickPoint, pickPoint);
998         }
999       }
1000     }
1001 
1002   // Interact, if desired
1003   this->EventCallbackCommand->SetAbortFlag(1);
1004   this->InvokeEvent(vtkCommand::InteractionEvent,NULL);
1005   this->Interactor->Render();
1006 }
1007 
Trace(int X,int Y)1008 void vtkImageTracerWidget::Trace(int X, int Y)
1009 {
1010   if ( !this->PropPicker->PickProp(X,Y,this->CurrentRenderer) ){ return; }
1011   if ( this->ViewProp !=  this->PropPicker->GetViewProp() ){ return; }
1012 
1013   double pos[3];
1014   this->PropPicker->GetPickPosition(pos);
1015 
1016   if ( this->SnapToImage )
1017     {
1018     this->Snap(pos);
1019     }
1020 
1021   if ( this->ProjectToPlane )
1022     {
1023     pos[this->ProjectionNormal] = this->ProjectionPosition;
1024     }
1025 
1026   if (  this->LastX != X || this->LastY != Y )
1027     {
1028     if ( this->State == vtkImageTracerWidget::Tracing )
1029       {
1030       if ( this->NumberOfHandles == 1 )
1031         {
1032         this->AppendHandles(pos);
1033         }
1034       else
1035         {
1036         this->AdjustHandlePosition(this->CurrentHandleIndex,pos);
1037         }
1038       this->AppendLine(pos);
1039       }
1040     else if ( this->State == vtkImageTracerWidget::Snapping )
1041       {
1042       if ( this->IsSnapping != this->CurrentHandleIndex  )
1043         {
1044         this->AppendHandles(pos);
1045         this->AppendLine(pos);
1046         this->IsSnapping = this->CurrentHandleIndex;
1047         }
1048       else
1049         {
1050         this->AdjustHandlePosition(this->CurrentHandleIndex,pos);
1051         this->LinePoints->SetPoint(this->PickCount,pos);
1052         this->LinePoints->GetData()->Modified();
1053         this->LineData->Modified();
1054         }
1055       }
1056    }
1057 
1058   this->LastX = X;
1059   this->LastY = Y;
1060 }
1061 
MovePoint(const double * p1,const double * p2)1062 void vtkImageTracerWidget::MovePoint(const double *p1, const double *p2)
1063 {
1064   // Get the motion vector
1065   double v[3];
1066   v[0] = p2[0] - p1[0];
1067   v[1] = p2[1] - p1[1];
1068   v[2] = p2[2] - p1[2];
1069 
1070   double *ctr = this->HandleGeometry[this->CurrentHandleIndex]->GetCenter();
1071 
1072   double newCtr[3];
1073   newCtr[0] = ctr[0] + v[0];
1074   newCtr[1] = ctr[1] + v[1];
1075   newCtr[2] = ctr[2] + v[2];
1076 
1077   // Move the widget handle
1078   this->AdjustHandlePosition(this->CurrentHandleIndex,newCtr);
1079 
1080   // Enforce consistency with the line
1081   int closed = this->IsClosed();
1082 
1083   this->LinePoints->SetPoint(this->CurrentHandleIndex,
1084             this->HandleGeometry[this->CurrentHandleIndex]->GetCenter());
1085 
1086   // Special case when moving the first point
1087   if ( closed && (this->CurrentHandleIndex == 0) )
1088     {
1089     this->LinePoints->SetPoint(this->LinePoints->GetNumberOfPoints()-1,
1090             this->HandleGeometry[0]->GetCenter());
1091     }
1092 
1093   this->LinePoints->GetData()->Modified();
1094   this->LineData->Modified();
1095 }
1096 
Translate(const double * p1,const double * p2)1097 void vtkImageTracerWidget::Translate(const double *p1, const double *p2)
1098 {
1099   // Get the motion vector
1100   double v[3];
1101   v[0] = p2[0] - p1[0];
1102   v[1] = p2[1] - p1[1];
1103   v[2] = p2[2] - p1[2];
1104 
1105   double newCtr[3];
1106   int i;
1107   for ( i = 0; i < this->NumberOfHandles; ++i )
1108     {
1109     double *ctr = this->HandleGeometry[i]->GetCenter();
1110     newCtr[0] = ctr[0] + v[0];
1111     newCtr[1] = ctr[1] + v[1];
1112     newCtr[2] = ctr[2] + v[2];
1113     this->AdjustHandlePosition(i,newCtr);
1114     }
1115 
1116   for ( i = 0; i < this->LinePoints->GetNumberOfPoints(); ++i )
1117     {
1118     double *ctr = this->LinePoints->GetPoint(i);
1119     newCtr[0] = ctr[0] + v[0];
1120     newCtr[1] = ctr[1] + v[1];
1121     newCtr[2] = ctr[2] + v[2];
1122     if ( this->ProjectToPlane )
1123       {
1124       newCtr[this->ProjectionNormal] = this->ProjectionPosition;
1125       }
1126     this->LinePoints->SetPoint(i,newCtr);
1127     }
1128 
1129   this->LinePoints->GetData()->Modified();
1130   this->LineData->Modified();
1131 }
1132 
ResetHandles(void)1133 void vtkImageTracerWidget::ResetHandles(void)
1134 {
1135   if ( this->NumberOfHandles == 0 ){ return; }
1136 
1137   if ( this->CurrentHandle )
1138     {
1139     this->CurrentHandle = NULL;
1140     }
1141 
1142   this->HandlePicker->InitializePickList();
1143 
1144   int i;
1145   if ( this->CurrentRenderer )
1146     {
1147     for (i = 0; i < this->NumberOfHandles; ++i )
1148       {
1149       this->CurrentRenderer->RemoveViewProp(this->Handle[i]);
1150       }
1151     }
1152 
1153   for ( i = 0; i < this->NumberOfHandles; ++i )
1154     {
1155     this->HandleGeometry[i]->Delete();
1156     this->Handle[i]->Delete();
1157     }
1158 
1159   this->NumberOfHandles = 0;
1160 
1161   delete [] this->Handle;
1162   this->Handle = NULL;
1163 
1164   delete [] this->HandleGeometry;
1165   this->HandleGeometry = NULL;
1166 }
1167 
AllocateHandles(const int & nhandles)1168 void vtkImageTracerWidget::AllocateHandles(const int& nhandles)
1169 {
1170   if ( (this->NumberOfHandles == nhandles) || (nhandles < 1) ){ return; }
1171 
1172   // De-allocate the handles
1173   this->ResetHandles();
1174   this->NumberOfHandles = nhandles;
1175 
1176   // Create the handles
1177   this->Handle         = new vtkActor* [this->NumberOfHandles];
1178   this->HandleGeometry = new vtkPolyData* [this->NumberOfHandles];
1179 
1180   int i;
1181   for ( i = 0; i < this->NumberOfHandles; ++i )
1182     {
1183     this->HandleGeometry[i] = vtkPolyData::New();
1184     vtkPolyDataMapper* handleMapper = vtkPolyDataMapper::New();
1185     handleMapper->SetInputData(this->HandleGeometry[i]);
1186     this->Handle[i] = vtkActor::New();
1187     this->Handle[i]->SetMapper(handleMapper);
1188     handleMapper->Delete();
1189     this->Handle[i]->SetProperty(this->HandleProperty);
1190     this->Handle[i]->PickableOff();
1191     this->HandlePicker->AddPickList(this->Handle[i]);
1192     }
1193 
1194   if ( this->CurrentRenderer && this->Enabled )
1195     {
1196     for ( i = 0; i < this->NumberOfHandles; ++i )
1197       {
1198       this->CurrentRenderer->AddViewProp(this->Handle[i]);
1199       }
1200     }
1201 }
1202 
AppendHandles(double * pos)1203 void vtkImageTracerWidget::AppendHandles(double* pos)
1204 {
1205   this->TemporaryHandlePoints->Reset();
1206   this->TemporaryHandlePoints->SetNumberOfTuples(this->NumberOfHandles+1);
1207   int i;
1208   for ( i = 0; i < this->NumberOfHandles; ++i )
1209     {
1210     this->TemporaryHandlePoints->SetTuple(i,this->HandleGeometry[i]->GetCenter());
1211     }
1212 
1213   this->TemporaryHandlePoints->SetTuple(this->NumberOfHandles,pos);
1214 
1215   this->AllocateHandles(this->TemporaryHandlePoints->GetNumberOfTuples());
1216 
1217   for ( i = 0; i < this->NumberOfHandles; ++i )
1218     {
1219     this->AdjustHandlePosition(i,this->TemporaryHandlePoints->GetTuple(i));
1220     }
1221 
1222   if ( this->CurrentHandleIndex != -1 )
1223     {
1224     this->CurrentHandleIndex = this->NumberOfHandles - 1;
1225     this->CurrentHandle = this->Handle[this->CurrentHandleIndex];
1226     this->CurrentHandle->SetProperty(this->SelectedHandleProperty);
1227     }
1228 }
1229 
InsertHandleOnLine(double * pos)1230 void vtkImageTracerWidget::InsertHandleOnLine(double* pos)
1231 {
1232   if ( this->NumberOfHandles < 3 &&
1233        this->LinePoints->GetNumberOfPoints() > 2 )
1234     {
1235     return; // don't insert on a continuously traced line
1236     }
1237 
1238   int id = this->LinePicker->GetCellId();
1239   if ( id == -1 ){ return; }
1240 
1241   this->TemporaryHandlePoints->Reset();
1242   this->TemporaryHandlePoints->SetNumberOfTuples(this->NumberOfHandles+1);
1243   int i;
1244   for ( i = 0; i <= id; i++ )
1245     {
1246     this->TemporaryHandlePoints->SetTuple(i,this->HandleGeometry[i]->GetCenter());
1247     }
1248 
1249   this->TemporaryHandlePoints->SetTuple(id+1,pos);
1250 
1251   for ( i = id + 1; i < this->NumberOfHandles; ++i )
1252     {
1253     this->TemporaryHandlePoints->SetTuple(i+1,this->HandleGeometry[i]->GetCenter());
1254     }
1255 
1256   this->AllocateHandles(this->TemporaryHandlePoints->GetNumberOfTuples());
1257 
1258   for ( i = 0; i < this->NumberOfHandles; ++i )
1259     {
1260     this->AdjustHandlePosition(i,this->TemporaryHandlePoints->GetTuple(i));
1261     }
1262 }
1263 
InitializeHandles(vtkPoints * points)1264 void vtkImageTracerWidget::InitializeHandles(vtkPoints* points)
1265 {
1266   if ( !points ){ return; }
1267 
1268   int npts = points->GetNumberOfPoints();
1269   if ( npts == 0 ){ return; }
1270 
1271   this->AllocateHandles( npts );
1272 
1273   for ( int i = 0; i < npts; ++i )
1274     {
1275     this->AdjustHandlePosition(i,points->GetPoint(i));
1276     }
1277 
1278   if ( npts > 1 )
1279     {
1280     this->BuildLinesFromHandles();
1281     if ( this->AutoClose )
1282       {
1283       this->ClosePath();
1284       if ( this->IsClosed() ) // if successful, remove the overlapping handle
1285         {
1286         this->EraseHandle(this->NumberOfHandles - 1);
1287         }
1288       }
1289     }
1290 }
1291 
EraseHandle(const int & index)1292 void vtkImageTracerWidget::EraseHandle(const int& index)
1293 {
1294   if ( this->NumberOfHandles == 1 ){ return; }
1295 
1296   this->TemporaryHandlePoints->Reset();
1297   this->TemporaryHandlePoints->SetNumberOfTuples(this->NumberOfHandles-1);
1298   int i;
1299   int count = 0;
1300   for ( i = 0; i < this->NumberOfHandles; ++i )
1301     {
1302     if ( i != index )
1303       {
1304       this->TemporaryHandlePoints->SetTuple(count++,this->HandleGeometry[i]->GetCenter());
1305       }
1306     }
1307 
1308   this->AllocateHandles(this->TemporaryHandlePoints->GetNumberOfTuples());
1309 
1310   for ( i = 0; i < this->NumberOfHandles; ++i )
1311     {
1312     this->AdjustHandlePosition(i,this->TemporaryHandlePoints->GetTuple(i));
1313     }
1314 }
1315 
ResetLine(double * pos)1316 void vtkImageTracerWidget::ResetLine(double* pos)
1317 {
1318   this->LinePicker->DeletePickList(this->LineActor);
1319   this->LineActor->VisibilityOff();
1320   this->LineActor->PickableOff();
1321 
1322   this->LinePoints->Delete();
1323   this->LineCells->Delete();
1324 
1325   this->LineData->Initialize();
1326   this->LineData->Squeeze();
1327 
1328   this->LinePoints = vtkPoints::New();
1329   this->LineCells = vtkCellArray::New();
1330 
1331   this->LineData->SetPoints( this->LinePoints );
1332   this->LineData->SetLines( this->LineCells );
1333 
1334   this->PickCount = 0;
1335 
1336   this->LinePoints->InsertPoint(this->PickCount,pos);
1337 }
1338 
AppendLine(double * pos)1339 void vtkImageTracerWidget::AppendLine(double* pos)
1340 {
1341   this->CurrentPoints[0] = this->PickCount++;
1342   this->CurrentPoints[1] = this->PickCount;
1343 
1344   this->LinePoints->InsertPoint(this->PickCount,pos);
1345   this->LineCells->InsertNextCell(2,this->CurrentPoints);
1346 
1347   this->LinePoints->GetData()->Modified();
1348   this->LineData->SetPoints(this->LinePoints);
1349   this->LineData->SetLines(this->LineCells);
1350   this->LineData->Modified();
1351 
1352   this->LineActor->VisibilityOn();
1353 }
1354 
BuildLinesFromHandles()1355 void vtkImageTracerWidget::BuildLinesFromHandles()
1356 {
1357   this->ResetLine(this->HandleGeometry[0]->GetCenter());
1358 
1359   for ( int i = 1; i < this->NumberOfHandles; ++i )
1360     {
1361     this->AppendLine(this->HandleGeometry[i]->GetCenter());
1362     }
1363 }
1364 
ClosePath()1365 void vtkImageTracerWidget::ClosePath()
1366 {
1367   int npts = this->LinePoints->GetNumberOfPoints();
1368   if ( npts < 4 ){ return; }
1369 
1370   double p0[3];
1371   this->LinePoints->GetPoint(0,p0);
1372   double p1[3];
1373   this->LinePoints->GetPoint(npts-1,p1);
1374 
1375   if ( sqrt(vtkMath::Distance2BetweenPoints(p0,p1)) <= this->CaptureRadius )
1376     {
1377     this->LinePoints->SetPoint(npts-1,p0);
1378     this->LinePoints->GetData()->Modified();
1379     this->LineData->Modified();
1380     }
1381 }
1382 
IsClosed()1383 int vtkImageTracerWidget::IsClosed() // can only be based on line data
1384 {
1385   int npts = this->LinePoints->GetNumberOfPoints();
1386   if ( npts < 4 ) { return 0; }
1387 
1388   double p0[3];
1389   this->LinePoints->GetPoint(0,p0);
1390   double p1[3];
1391   this->LinePoints->GetPoint(npts-1,p1);
1392 
1393    return (p0[0] == p1[0] && p0[1] == p1[1] && p0[2] == p1[2]);
1394 }
1395 
GetPath(vtkPolyData * pd)1396 void vtkImageTracerWidget::GetPath(vtkPolyData *pd)
1397 {
1398   pd->ShallowCopy(this->LineData);
1399 }
1400 
SetSnapToImage(int snap)1401 void vtkImageTracerWidget::SetSnapToImage(int snap)
1402 {
1403   if ( this->GetInput() )
1404     {
1405     if ( this->GetInput()->GetDataObjectType() != VTK_IMAGE_DATA )
1406       {
1407       vtkErrorMacro(<<"Input data must be of type vtkImageData");
1408       return;
1409       }
1410     else
1411       {
1412       this->SnapToImage = snap;
1413       }
1414     }
1415   else
1416     {
1417     vtkGenericWarningMacro(<<"SetInput with type vtkImageData first");
1418     return;
1419     }
1420 }
1421 
Snap(double * pos)1422 void vtkImageTracerWidget::Snap(double* pos) // overwrites pos
1423 {
1424   vtkImageData* ptr = vtkImageData::SafeDownCast(this->GetInput());
1425   if ( !ptr ){ return; }
1426 
1427   if ( this->ImageSnapType == VTK_ITW_SNAP_CELLS )  // snap to cell center
1428     {
1429     double bounds[6];
1430     double weights[8];
1431     double pcoords[3];
1432     int subId;
1433     vtkIdType cellId = ptr->FindCell(pos,NULL,-1,0.0,subId,pcoords,weights);
1434     if ( cellId != -1 )
1435       {
1436       ptr->GetCellBounds(cellId,bounds);
1437       for ( int i = 0; i < 3; ++i )
1438         {
1439         pos[i] = bounds[i*2]+ 0.5*(bounds[i*2+1]-bounds[i*2]);
1440         }
1441       }
1442     }
1443   else // snap to nearest point
1444     {
1445     vtkIdType ptId = ptr->FindPoint(pos);
1446     if ( ptId != -1 )
1447       {
1448       ptr->GetPoint(ptId,pos);
1449       }
1450     }
1451 }
1452 
CreateDefaultProperties()1453 void vtkImageTracerWidget::CreateDefaultProperties()
1454 {
1455   if ( !this->HandleProperty )
1456     {
1457     this->HandleProperty = vtkProperty::New();
1458     this->HandleProperty->SetAmbient(1.0);
1459     this->HandleProperty->SetDiffuse(0.0);
1460     this->HandleProperty->SetColor(1,0,1);
1461     this->HandleProperty->SetLineWidth(2);
1462     this->HandleProperty->SetRepresentationToWireframe();
1463     this->HandleProperty->SetInterpolationToFlat();
1464     }
1465   if ( !this->SelectedHandleProperty )
1466     {
1467     this->SelectedHandleProperty = vtkProperty::New();
1468     this->SelectedHandleProperty->SetAmbient(1.0);
1469     this->SelectedHandleProperty->SetDiffuse(0.0);
1470     this->SelectedHandleProperty->SetColor(0,1,0);
1471     this->SelectedHandleProperty->SetLineWidth(2);
1472     this->SelectedHandleProperty->SetRepresentationToWireframe();
1473     this->SelectedHandleProperty->SetInterpolationToFlat();
1474     }
1475   if ( !this->LineProperty )
1476     {
1477     this->LineProperty = vtkProperty::New();
1478     this->LineProperty->SetAmbient(1.0);
1479     this->LineProperty->SetDiffuse(0.0);
1480     this->LineProperty->SetColor(0,1,0);
1481     this->LineProperty->SetLineWidth(2);
1482     this->LineProperty->SetRepresentationToWireframe();
1483     this->LineProperty->SetInterpolationToFlat();
1484     }
1485   if ( !this->SelectedLineProperty )
1486     {
1487     this->SelectedLineProperty = vtkProperty::New();
1488     this->SelectedLineProperty->SetAmbient(1.0);
1489     this->SelectedLineProperty->SetDiffuse(0.0);
1490     this->SelectedLineProperty->SetColor(0,1,1);
1491     this->SelectedLineProperty->SetLineWidth(2);
1492     this->SelectedLineProperty->SetRepresentationToWireframe();
1493     this->SelectedLineProperty->SetInterpolationToFlat();
1494     }
1495 }
1496 
PlaceWidget(double bds[6])1497 void vtkImageTracerWidget::PlaceWidget(double bds[6])
1498 {
1499   double bounds[6], center[3];
1500   this->AdjustBounds(bds, bounds, center);
1501 
1502   // create a default handle within the data bounds
1503   double x0 = bounds[0];
1504   double x1 = bounds[1];
1505   double y0 = bounds[2];
1506   double y1 = bounds[3];
1507   double z0 = bounds[4];
1508   double z1 = bounds[5];
1509   double xyz[3];
1510   double position = 0.5;
1511   xyz[0] = (1.0-position)*x0 + position*x1;
1512   xyz[1] = (1.0-position)*y0 + position*y1;
1513   xyz[2] = (1.0-position)*z0 + position*z1;
1514 
1515   this->AdjustHandlePosition(0,xyz);
1516 
1517   for ( int i = 0; i < 6; ++i )
1518     {
1519     this->InitialBounds[i] = bounds[i];
1520     }
1521   this->InitialLength = sqrt((bounds[1]-bounds[0])*(bounds[1]-bounds[0]) +
1522                              (bounds[3]-bounds[2])*(bounds[3]-bounds[2]) +
1523                              (bounds[5]-bounds[4])*(bounds[5]-bounds[4]));
1524   this->SizeHandles();
1525 }
1526 
SizeHandles()1527 void vtkImageTracerWidget::SizeHandles()
1528 {
1529   // TODO...
1530   return;
1531 }
1532 
1533 //----------------------------------------------------------------------------
1534 #ifndef VTK_LEGACY_REMOVE
1535 # ifdef VTK_WORKAROUND_WINDOWS_MANGLE
1536 #  undef SetProp
SetPropA(vtkProp * prop)1537 void vtkImageTracerWidget::SetPropA(vtkProp* prop)
1538 {
1539   VTK_LEGACY_REPLACED_BODY(vtkImageTracerWidget::SetProp, "VTK 5.0",
1540                            vtkImageTracerWidget::SetViewProp);
1541   this->SetViewProp(prop);
1542 }
SetPropW(vtkProp * prop)1543 void vtkImageTracerWidget::SetPropW(vtkProp* prop)
1544 {
1545   VTK_LEGACY_REPLACED_BODY(vtkImageTracerWidget::SetProp, "VTK 5.0",
1546                            vtkImageTracerWidget::SetViewProp);
1547   this->SetViewProp(prop);
1548 }
1549 # endif
SetProp(vtkProp * prop)1550 void vtkImageTracerWidget::SetProp(vtkProp* prop)
1551 {
1552   VTK_LEGACY_REPLACED_BODY(vtkImageTracerWidget::SetProp, "VTK 5.0",
1553                            vtkImageTracerWidget::SetViewProp);
1554   this->SetViewProp(prop);
1555 }
1556 #endif
1557