Salome HOME
Fix for Bug IPAL8945
[modules/visu.git] / src / PIPELINE / VISU_PlanesWidget.cxx
1 //  SALOME VTKViewer : build VTK viewer into Salome desktop
2 //
3 //  Copyright (C) 2003  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
4 //  CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS 
5 // 
6 //  This library is free software; you can redistribute it and/or 
7 //  modify it under the terms of the GNU Lesser General Public 
8 //  License as published by the Free Software Foundation; either 
9 //  version 2.1 of the License. 
10 // 
11 //  This library is distributed in the hope that it will be useful, 
12 //  but WITHOUT ANY WARRANTY; without even the implied warranty of 
13 //  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU 
14 //  Lesser General Public License for more details. 
15 // 
16 //  You should have received a copy of the GNU Lesser General Public 
17 //  License along with this library; if not, write to the Free Software 
18 //  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA 
19 // 
20 //  See http://www.opencascade.org/SALOME/ or email : webmaster.salome@opencascade.org 
21 //
22 //
23 //
24 //  File   : VVTK_ImplicitFunctionWidget.cxx
25 //  Author : Peter KURNEV
26 //  Module : SALOME
27 //  $Header$
28
29 #include "VISU_PlanesWidget.hxx"
30 #include "VISU_ImplicitFunctionWidget.hxx"
31
32 #include <vtkActor.h>
33 #include <vtkAssemblyNode.h>
34 #include <vtkAssemblyPath.h>
35 #include <vtkCallbackCommand.h>
36 #include <vtkCamera.h>
37 #include <vtkCellPicker.h>
38 #include <vtkConeSource.h>
39 #include <vtkCutter.h>
40 #include <vtkFeatureEdges.h>
41 #include <vtkImageData.h>
42 #include <vtkLineSource.h>
43 #include <vtkMath.h>
44 #include <vtkObjectFactory.h>
45 #include <vtkOutlineFilter.h>
46 #include <vtkPlane.h>
47 #include <vtkPolyData.h>
48 #include <vtkPolyDataMapper.h>
49 #include <vtkProperty.h>
50 #include <vtkRenderWindowInteractor.h>
51 #include <vtkRenderer.h>
52 #include <vtkSphereSource.h>
53 #include <vtkTransform.h>
54 #include <vtkTubeFilter.h>
55 #include <vtkImplicitBoolean.h>
56 #include <vtkImplicitFunctionCollection.h>
57 ////
58 #include <vtkFollower.h>
59 #include <vtkObjectFactory.h>
60 #include <vtkDataSet.h>
61 #include <vtkRenderWindow.h>
62
63 static
64   bool IsValidPlane2Position(vtkPlane *pPx,
65                              vtkDataSet *pDataSet,
66                              float aTol=0.003);
67 static 
68   void GetBndPoints(vtkDataSet *pDataSet, 
69                     float aPnts[24]);
70 static 
71   float DistanceToPlane(const float x[3], 
72                         const float n[3], 
73                         const float p0[3]);
74
75 vtkCxxRevisionMacro(VISU_PlanesWidget, "$Revision$");
76 vtkStandardNewMacro(VISU_PlanesWidget);
77
78 //==================================================================
79 // function: VISU_PlanesWidget
80 // purpose :
81 //==================================================================
82 VISU_PlanesWidget::VISU_PlanesWidget() 
83
84   VISU_ImplicitFunctionWidget()
85 {
86   State = VISU_PlanesWidget::Start;
87   EventCallbackCommand->SetCallback(VISU_PlanesWidget::ProcessEvents);
88   
89   NormalToXAxis = 0;
90   NormalToYAxis = 0;
91   NormalToZAxis = 0;
92
93   HandleMoveEvent = true;
94   HandleLeftButtonEvent = true;
95   HandleMiddleButtonEvent = false;
96   HandleRightButtonEvent = false;
97
98   // Build the representation of the widget
99   // 
100   myPlane1 = vtkPlane::New();
101   myPlane1->SetNormal(0,0,1);
102   myPlane1->SetOrigin(0,0,0);
103   //
104   myDistance = 10.;
105   myPlane2 = vtkPlane::New();
106   myPlane2->SetNormal(0.,0.,-1.);
107   myPlane2->SetOrigin(0,0,myDistance);
108   //
109   myImplicitFunction = vtkImplicitBoolean::New();
110   myImplicitFunction->SetOperationType(VTK_UNION);  
111   //
112   myBox = vtkImageData::New();
113   myBox->SetDimensions(2,2,2);
114   myOutline = vtkOutlineFilter::New();
115   myOutline->SetInput(myBox);
116   myOutlineMapper = vtkPolyDataMapper::New();
117   myOutlineMapper->SetInput(myOutline->GetOutput());
118   myOutlineActor = vtkActor::New();
119   this->myOutlineActor->SetMapper(this->myOutlineMapper);
120   this->myOutlineActor->PickableOff();
121   this->OutlineTranslation = 0;
122   
123   this->myCutter1 = vtkCutter::New();
124   this->myCutter1->SetInput(myBox);
125   this->myCutter1->SetCutFunction(myPlane1);
126   this->myCutMapper1 = vtkPolyDataMapper::New();
127   this->myCutMapper1->SetInput(this->myCutter1->GetOutput());
128   this->myCutActor1 = vtkActor::New();
129   this->myCutActor1->SetMapper(this->myCutMapper1);
130   this->myDrawPlane = 1;
131
132   this->myEdges1 = vtkFeatureEdges::New();
133   myEdges1->SetColoring(0); 
134   this->myEdges1->SetInput(this->myCutter1->GetOutput());
135   this->myEdgesMapper1 = vtkPolyDataMapper::New();
136   this->myEdgesMapper1->SetInput(this->myEdges1->GetOutput());
137   this->myEdgesActor1 = vtkActor::New();
138   this->myEdgesActor1->SetMapper(this->myEdgesMapper1);
139   myEdgesActor1->GetProperty()->SetLineWidth(4.); 
140   myEdgesActor1->GetProperty()->SetColor(0., .5, .7); 
141
142   this->myCutter2 = vtkCutter::New();
143   this->myCutter2->SetInput(myBox);
144   this->myCutter2->SetCutFunction(this->myPlane2);
145   this->myCutMapper2 = vtkPolyDataMapper::New();
146   this->myCutMapper2->SetInput(this->myCutter2->GetOutput());
147   this->myCutActor2 = vtkActor::New();
148   this->myCutActor2->SetMapper(this->myCutMapper2);
149
150   myEdges2 = vtkFeatureEdges::New();
151   myEdges2->SetColoring(0); 
152   myEdges2->SetInput(myCutter2->GetOutput());
153   myEdgesMapper2 = vtkPolyDataMapper::New();
154   myEdgesMapper2->SetInput(myEdges2->GetOutput());
155   myEdgesActor2 = vtkActor::New();
156   myEdgesActor2->SetMapper(myEdgesMapper2);
157   myEdgesActor2->GetProperty()->SetLineWidth(4.); 
158   myEdgesActor2->GetProperty()->SetColor(.7, .0, .0); 
159
160   // Create the + plane normal
161   this->LineSource = vtkLineSource::New();
162   this->LineSource->SetResolution(1);
163   this->LineMapper = vtkPolyDataMapper::New();
164   this->LineMapper->SetInput(this->LineSource->GetOutput());
165   this->LineActor = vtkActor::New();
166   this->LineActor->SetMapper(this->LineMapper);
167
168   this->ConeSource = vtkConeSource::New();
169   this->ConeSource->SetResolution(12);
170   this->ConeSource->SetAngle(20.);
171   this->ConeMapper = vtkPolyDataMapper::New();
172   this->ConeMapper->SetInput(this->ConeSource->GetOutput());
173   this->ConeActor = VISU_UnScaledActor::New();
174   this->ConeActor->SetMapper(this->ConeMapper);
175   ConeActor->SetSize(36);
176   ConeActor->SetCenter(ConeSource->GetCenter());
177
178   // Create the - plane normal
179   this->LineSource2 = vtkLineSource::New();
180   this->LineSource2->SetResolution(1);
181   this->LineMapper2 = vtkPolyDataMapper::New();
182   this->LineMapper2->SetInput(this->LineSource2->GetOutput());
183   this->LineActor2 = vtkActor::New();
184   this->LineActor2->SetMapper(this->LineMapper2);
185
186   this->ConeSource2 = vtkConeSource::New();
187   this->ConeSource2->SetResolution(12);
188   this->ConeSource2->SetAngle(20.);
189   this->ConeMapper2 = vtkPolyDataMapper::New();
190   this->ConeMapper2->SetInput(this->ConeSource2->GetOutput());
191   this->ConeActor2 = VISU_UnScaledActor::New();
192   this->ConeActor2->SetMapper(this->ConeMapper2);
193   ConeActor2->SetSize(36);
194   ConeActor2->SetCenter(ConeSource2->GetCenter());
195
196   // Create the origin handle
197   this->Sphere = vtkSphereSource::New();
198   this->Sphere->SetThetaResolution(16);
199   this->Sphere->SetPhiResolution(8);
200   this->SphereMapper = vtkPolyDataMapper::New();
201   this->SphereMapper->SetInput(this->Sphere->GetOutput());
202   this->SphereActor = VISU_UnScaledActor::New();
203   this->SphereActor->SetMapper(this->SphereMapper);
204   SphereActor->SetSize(36);
205   SphereActor->SetCenter(Sphere->GetCenter());
206
207   this->Transform = vtkTransform::New();
208
209   // Define the point coordinates
210   float bounds[6];
211   bounds[0] = -0.5;
212   bounds[1] = 0.5;
213   bounds[2] = -0.5;
214   bounds[3] = 0.5;
215   bounds[4] = -0.5;
216   bounds[5] = 0.5;
217
218   // Initial creation of the widget, serves to initialize it
219   this->PlaceWidget(bounds);
220
221   //Manage the picking stuff
222   this->Picker = vtkCellPicker::New();
223   this->Picker->SetTolerance(0.005);
224   this->Picker->AddPickList(this->myCutActor1);
225   this->Picker->AddPickList(this->myCutActor2);
226   this->Picker->AddPickList(this->LineActor);
227   this->Picker->AddPickList(this->ConeActor);
228   this->Picker->AddPickList(this->LineActor2);
229   this->Picker->AddPickList(this->ConeActor2);
230   this->Picker->AddPickList(this->SphereActor);
231   this->Picker->AddPickList(this->myOutlineActor);
232   this->Picker->PickFromListOn();
233   
234   // Set up the initial properties
235   this->CreateDefaultProperties();
236   
237 }
238 //==================================================================
239 // function: ~
240 // purpose :
241 //==================================================================
242 VISU_PlanesWidget::~VISU_PlanesWidget()
243 {  
244   myPlane1->Delete();
245
246   this->myPlane2->Delete();
247   this->myImplicitFunction->Delete();
248
249   myBox->Delete();
250   this->myOutline->Delete();
251   this->myOutlineMapper->Delete();
252   this->myOutlineActor->Delete();
253   
254   this->myCutter1->Delete();
255   this->myCutMapper1->Delete();
256   this->myCutActor1->Delete();
257
258   this->myEdges1->Delete();
259   this->myEdgesMapper1->Delete();
260   this->myEdgesActor1->Delete();
261   
262   myCutter2->Delete();
263   myCutMapper2->Delete();
264   myCutActor2->Delete();
265
266   myEdges2->Delete();
267   myEdgesMapper2->Delete();
268   myEdgesActor2->Delete();
269   
270   this->LineSource->Delete();
271   this->LineMapper->Delete();
272   this->LineActor->Delete();
273
274   this->ConeSource->Delete();
275   this->ConeMapper->Delete();
276   this->ConeActor->Delete();
277
278   this->LineSource2->Delete();
279   this->LineMapper2->Delete();
280   this->LineActor2->Delete();
281
282   this->ConeSource2->Delete();
283   this->ConeMapper2->Delete();
284   this->ConeActor2->Delete();
285
286   this->Sphere->Delete();
287   this->SphereMapper->Delete();
288   this->SphereActor->Delete();
289
290   this->Transform->Delete();
291
292   this->Picker->Delete();
293
294   this->NormalProperty->Delete();
295   this->SelectedNormalProperty->Delete();
296   this->PlaneProperty->Delete();
297   this->SelectedPlaneProperty->Delete();
298   this->OutlineProperty->Delete();
299   this->SelectedOutlineProperty->Delete();
300   this->EdgesProperty->Delete();
301 }
302 //==================================================================
303 // function: ImplicitFunction
304 // purpose :
305 //==================================================================
306 vtkImplicitFunction* VISU_PlanesWidget::ImplicitFunction()
307 {
308   return this->myImplicitFunction;
309 }
310 //==================================================================
311 // function: SetDistance
312 // purpose :
313 //==================================================================
314 void VISU_PlanesWidget::SetDistance(const float theDistance)
315 {
316   if( theDistance <= 0.0 || theDistance == myDistance )
317     return;
318
319   myDistance=theDistance;
320   //
321   float *origin, *normal, oNew[3], aN2[3]; 
322   origin = myPlane1->GetOrigin();
323   normal = myPlane1->GetNormal();
324   vtkMath::Normalize(normal);
325   oNew[0] = origin[0] + myDistance*normal[0];
326   oNew[1] = origin[1] + myDistance*normal[1];
327   oNew[2] = origin[2] + myDistance*normal[2];
328   myPlane2->SetOrigin(oNew);
329   aN2[0] = -normal[0];
330   aN2[1] = -normal[1];
331   aN2[2] = -normal[2];
332   myPlane2->SetNormal(aN2);
333 }
334 //==================================================================
335 // function: Distance
336 // purpose :
337 //==================================================================
338 float VISU_PlanesWidget::Distance()const
339 {
340   return myDistance;
341 }
342 //==================================================================
343 // function: SetEnabled
344 // purpose :
345 //==================================================================
346 void VISU_PlanesWidget::SetEnabled(int enabling)
347 {
348   if ( ! this->Interactor )    {
349     vtkErrorMacro(<<"The interactor must be set prior to enabling/disabling widget");
350     return;
351   }
352
353   if ( enabling ) {//------------------------------------------------------------
354     vtkDebugMacro(<<"Enabling plane widget");
355     
356     if ( this->Enabled ){ //already enabled, just return
357       return;
358     }
359     
360     if ( ! this->CurrentRenderer ){
361       this->CurrentRenderer = this->Interactor->FindPokedRenderer(
362         this->Interactor->GetLastEventPosition()[0],
363         this->Interactor->GetLastEventPosition()[1]);
364       if (this->CurrentRenderer == NULL)        {
365         return;
366       }
367     }
368     //
369     vtkCamera *pCamera=CurrentRenderer->GetActiveCamera();
370     pCamera->SetParallelProjection(1);
371     //
372     this->myImplicitFunction->AddFunction(myPlane1);
373     this->myImplicitFunction->AddFunction(this->myPlane2);
374
375     this->Enabled = 1;
376
377     // listen for the following events
378     vtkRenderWindowInteractor *i = this->Interactor;
379     if( this->HandleMoveEvent )    {
380       i->AddObserver(vtkCommand::MouseMoveEvent, 
381                      this->EventCallbackCommand, 
382                      this->Priority);
383     }
384     if( this->HandleLeftButtonEvent )    {
385       i->AddObserver(vtkCommand::LeftButtonPressEvent, 
386                      this->EventCallbackCommand, 
387                      this->Priority);
388       i->AddObserver(vtkCommand::LeftButtonReleaseEvent, 
389                      this->EventCallbackCommand, 
390                      this->Priority);
391     }
392     if( this->HandleMiddleButtonEvent )    {
393       i->AddObserver(vtkCommand::MiddleButtonPressEvent, 
394                      this->EventCallbackCommand, 
395                      this->Priority);
396       i->AddObserver(vtkCommand::MiddleButtonReleaseEvent, 
397                      this->EventCallbackCommand, 
398                      this->Priority);
399     }
400     if( this->HandleRightButtonEvent )    {
401       i->AddObserver(vtkCommand::RightButtonPressEvent, 
402                      this->EventCallbackCommand, 
403                      this->Priority);
404       i->AddObserver(vtkCommand::RightButtonReleaseEvent, 
405                      this->EventCallbackCommand, 
406                      this->Priority);
407     }
408     // add the outline
409     this->CurrentRenderer->AddActor(this->myOutlineActor);
410     this->myOutlineActor->SetProperty(this->OutlineProperty);
411
412     // add the edges
413     this->CurrentRenderer->AddActor(this->myEdgesActor1);
414     this->CurrentRenderer->AddActor(myEdgesActor2);
415
416     this->myOutlineActor->SetProperty(this->EdgesProperty);
417
418     // add the normal vector
419     this->CurrentRenderer->AddActor(this->LineActor);
420     this->LineActor->SetProperty(this->NormalProperty);
421     this->CurrentRenderer->AddActor(this->ConeActor);
422     this->ConeActor->SetProperty(this->NormalProperty);
423
424     this->CurrentRenderer->AddActor(this->LineActor2);
425     this->LineActor2->SetProperty(this->NormalProperty);
426     this->CurrentRenderer->AddActor(this->ConeActor2);
427     this->ConeActor2->SetProperty(this->NormalProperty);
428     
429     // add the origin handle
430     this->CurrentRenderer->AddActor(this->SphereActor);
431     this->SphereActor->SetProperty(this->NormalProperty);
432
433     // add the plane (if desired)
434     if ( this->myDrawPlane )      {
435       this->CurrentRenderer->AddActor(this->myCutActor1);
436       this->CurrentRenderer->AddActor(this->myCutActor2);
437     }
438     this->myCutActor1->SetProperty(this->PlaneProperty);
439     myCutActor2->SetProperty(this->PlaneProperty);
440     
441     this->UpdateRepresentation();
442     //this->SizeHandles();
443     this->InvokeEvent(vtkCommand::EnableEvent,NULL);
444   }
445   
446   else {//disabling----------------------------------------------------------
447     vtkDebugMacro(<<"Disabling plane widget");
448
449     if ( ! this->Enabled ) {//already disabled, just return
450       return;
451     }
452     
453     if(vtkImplicitFunctionCollection* aFunction = this->myImplicitFunction->GetFunction()){
454       aFunction->RemoveAllItems();
455       this->myImplicitFunction->Modified(); // VTK bug
456     }
457
458     this->Enabled = 0;
459
460     // don't listen for events any more
461     this->Interactor->RemoveObserver(this->EventCallbackCommand);
462
463     // turn off the various actors
464     this->CurrentRenderer->RemoveActor(this->myOutlineActor);
465     this->CurrentRenderer->RemoveActor(this->myEdgesActor1);
466     this->CurrentRenderer->RemoveActor(myEdgesActor2);
467     this->CurrentRenderer->RemoveActor(this->LineActor);
468     this->CurrentRenderer->RemoveActor(this->ConeActor);
469     this->CurrentRenderer->RemoveActor(this->LineActor2);
470     this->CurrentRenderer->RemoveActor(this->ConeActor2);
471     this->CurrentRenderer->RemoveActor(this->SphereActor);
472     this->CurrentRenderer->RemoveActor(this->myCutActor1);
473     this->CurrentRenderer->RemoveActor(myCutActor2);
474
475     this->InvokeEvent(vtkCommand::DisableEvent,NULL);
476     this->CurrentRenderer = NULL;
477   }
478   
479   this->Interactor->Render();
480 }
481 //==================================================================
482 // function: ProcessEvents
483 // purpose :
484 //==================================================================
485 void VISU_PlanesWidget::ProcessEvents(vtkObject* vtkNotUsed(object), 
486                                                 unsigned long event,
487                                                 void* clientdata, 
488                                                 void* vtkNotUsed(calldata))
489 {
490   VISU_PlanesWidget* self = 
491     reinterpret_cast<VISU_PlanesWidget *>( clientdata );
492
493   //okay, let's do the right thing
494   switch(event)
495     {
496     case vtkCommand::LeftButtonPressEvent:
497       self->OnLeftButtonDown();
498       break;
499     case vtkCommand::LeftButtonReleaseEvent:
500       self->OnLeftButtonUp();
501       break;
502     case vtkCommand::MiddleButtonPressEvent:
503       self->OnMiddleButtonDown();
504       break;
505     case vtkCommand::MiddleButtonReleaseEvent:
506       self->OnMiddleButtonUp();
507       break;
508     case vtkCommand::RightButtonPressEvent:
509       self->OnRightButtonDown();
510       break;
511     case vtkCommand::RightButtonReleaseEvent:
512       self->OnRightButtonUp();
513       break;
514     case vtkCommand::MouseMoveEvent:
515       self->OnMouseMove();
516       break;
517     default:
518       break;
519     }
520 }
521 //==================================================================
522 // function: HighlightNormal
523 // purpose :
524 //==================================================================
525 void VISU_PlanesWidget::HighlightNormal(int highlight)
526 {
527   if ( highlight ) {
528     this->LineActor->SetProperty(this->SelectedNormalProperty);
529     this->ConeActor->SetProperty(this->SelectedNormalProperty);
530     this->LineActor2->SetProperty(this->SelectedNormalProperty);
531     this->ConeActor2->SetProperty(this->SelectedNormalProperty);
532     this->SphereActor->SetProperty(this->SelectedNormalProperty);
533     }
534   else
535     {
536     this->LineActor->SetProperty(this->NormalProperty);
537     this->ConeActor->SetProperty(this->NormalProperty);
538     this->LineActor2->SetProperty(this->NormalProperty);
539     this->ConeActor2->SetProperty(this->NormalProperty);
540     this->SphereActor->SetProperty(this->NormalProperty);
541     }
542 }
543 //==================================================================
544 // function: HighlightPlane
545 // purpose :
546 //==================================================================
547 void VISU_PlanesWidget::HighlightPlane(int highlight)
548 {
549   if ( highlight )    {
550     this->myCutActor1->SetProperty(this->SelectedPlaneProperty);
551     myCutActor2->SetProperty(this->SelectedPlaneProperty);
552   }
553   else    {
554     this->myCutActor1->SetProperty(this->PlaneProperty);
555     myCutActor2->SetProperty(this->PlaneProperty);
556   }
557 }
558 //==================================================================
559 // function: HighlightOutline
560 // purpose :
561 //==================================================================
562 void VISU_PlanesWidget::HighlightOutline(int highlight)
563 {
564   if (highlight)    {
565     this->myOutlineActor->SetProperty(this->SelectedOutlineProperty);
566   }
567   else    {
568     this->myOutlineActor->SetProperty(this->OutlineProperty);
569   }
570 }
571 //==================================================================
572 // function: OnLeftButtonDown
573 // purpose :
574 //==================================================================
575 void VISU_PlanesWidget::OnLeftButtonDown()
576 {
577   // We're only here if we are enabled
578   int X = this->Interactor->GetEventPosition()[0];
579   int Y = this->Interactor->GetEventPosition()[1];
580   //
581   // Okay, we can process this. See if we've picked anything.
582   // Make sure it's in the activated renderer
583   vtkRenderer *ren = this->Interactor->FindPokedRenderer(X,Y);
584   if ( ren != this->CurrentRenderer )    {
585     this->State = VISU_PlanesWidget::Outside;
586     return;
587   }
588   
589   vtkAssemblyPath *path;
590   this->Picker->Pick(X,Y,0.0,this->CurrentRenderer);
591   path = this->Picker->GetPath();
592
593   if ( path == NULL ) {//not picking this widget
594     this->HighlightPlane(0);
595     this->HighlightNormal(0);
596     this->HighlightOutline(0);
597     this->State = VISU_PlanesWidget::Outside;
598     return;
599   }
600
601   vtkProp *prop = path->GetFirstNode()->GetProp();
602   this->ValidPick = 1;
603   this->Picker->GetPickPosition(this->LastPickPosition);
604   //
605   if ( prop == this->ConeActor || prop == this->LineActor ||
606        prop == this->ConeActor2 || prop == this->LineActor2 )  {
607     this->HighlightPlane(1);
608     this->HighlightNormal(1);
609     this->State = VISU_PlanesWidget::Rotating;
610   }
611   else if ( prop == this->myCutActor1)    {
612     this->HighlightPlane(1);
613     this->State = VISU_PlanesWidget::Pushing;
614   }
615   else if ( prop == this->SphereActor )    {
616     this->HighlightNormal(1);
617     this->State = VISU_PlanesWidget::MovingOrigin;
618   }
619   else if (prop == myCutActor2)    {
620     this->HighlightPlane(1);
621     this->State = VISU_PlanesWidget::ChangeDistance;
622   }
623   else    {
624     if ( this->OutlineTranslation )      {
625       this->HighlightOutline(1);
626       this->State = VISU_PlanesWidget::MovingOutline;
627     }
628   }
629   
630   this->EventCallbackCommand->SetAbortFlag(1);
631   this->StartInteraction();
632   this->InvokeEvent(vtkCommand::StartInteractionEvent,NULL);
633   this->Interactor->Render();
634 }
635 //==================================================================
636 // function: OnLeftButtonUp
637 // purpose :
638 //==================================================================
639 void VISU_PlanesWidget::OnLeftButtonUp()
640 {
641   if ( this->State == VISU_PlanesWidget::Outside )    {
642     return;
643   }
644
645   this->State = VISU_PlanesWidget::Start;
646   this->HighlightPlane(0);
647   this->HighlightOutline(0);
648   this->HighlightNormal(0);
649   //this->SizeHandles();
650   
651   this->EventCallbackCommand->SetAbortFlag(1);
652   this->EndInteraction();
653   this->InvokeEvent(vtkCommand::EndInteractionEvent,NULL);
654   this->Interactor->Render();
655 }
656 //==================================================================
657 // function: OnMiddleButtonDown
658 // purpose :
659 //==================================================================
660 void VISU_PlanesWidget::OnMiddleButtonDown()
661 {
662   int X = this->Interactor->GetEventPosition()[0];
663   int Y = this->Interactor->GetEventPosition()[1];
664
665   // Okay, we can process this. See if we've picked anything.
666   // Make sure it's in the activated renderer
667   vtkRenderer *ren = this->Interactor->FindPokedRenderer(X,Y);
668   if ( ren != this->CurrentRenderer )    {
669     this->State = VISU_PlanesWidget::Outside;
670     return;
671   }
672   
673   // Okay, we can process this.
674   vtkAssemblyPath *path;
675   this->Picker->Pick(X,Y,0.0,this->CurrentRenderer);
676   path = this->Picker->GetPath();
677   
678   if ( path == NULL ) {//nothing picked
679     this->State = VISU_PlanesWidget::Outside;
680     return;
681   }
682
683   this->ValidPick = 1;
684   this->Picker->GetPickPosition(this->LastPickPosition);
685   this->State = VISU_PlanesWidget::MovingPlane;
686   this->HighlightNormal(1);
687   this->HighlightPlane(1);
688   
689   this->EventCallbackCommand->SetAbortFlag(1);
690   this->StartInteraction();
691   this->InvokeEvent(vtkCommand::StartInteractionEvent,NULL);
692   this->Interactor->Render();
693 }
694 //==================================================================
695 // function: OnMiddleButtonUp
696 // purpose :
697 //==================================================================
698 void VISU_PlanesWidget::OnMiddleButtonUp()
699 {
700   if ( this->State == VISU_PlanesWidget::Outside )    {
701     return;
702   }
703
704   this->State = VISU_PlanesWidget::Start;
705   this->HighlightPlane(0);
706   this->HighlightOutline(0);
707   this->HighlightNormal(0);
708   //this->SizeHandles();
709   
710   this->EventCallbackCommand->SetAbortFlag(1);
711   this->EndInteraction();
712   this->InvokeEvent(vtkCommand::EndInteractionEvent,NULL);
713   this->Interactor->Render();
714 }
715 //==================================================================
716 // function: OnRightButtonDown
717 // purpose :
718 //==================================================================
719 void VISU_PlanesWidget::OnRightButtonDown()
720 {
721   this->State = VISU_PlanesWidget::Scaling;
722
723   int X = this->Interactor->GetEventPosition()[0];
724   int Y = this->Interactor->GetEventPosition()[1];
725
726   // Okay, we can process this. See if we've picked anything.
727   // Make sure it's in the activated renderer
728   vtkRenderer *ren = this->Interactor->FindPokedRenderer(X,Y);
729   if ( ren != this->CurrentRenderer )    {
730     this->State = VISU_PlanesWidget::Outside;
731     return;
732   }
733   
734   // Okay, we can process this. Try to pick handles first;
735   // if no handles picked, then pick the bounding box.
736   vtkAssemblyPath *path;
737   this->Picker->Pick(X,Y,0.0,this->CurrentRenderer);
738   path = this->Picker->GetPath();
739   if ( path == NULL ){ //nothing picked
740     this->State = VISU_PlanesWidget::Outside;
741     return;
742   }
743   
744   this->ValidPick = 1;
745   this->Picker->GetPickPosition(this->LastPickPosition);
746   this->HighlightPlane(1);
747   this->HighlightOutline(1);
748   this->HighlightNormal(1);
749   
750   this->EventCallbackCommand->SetAbortFlag(1);
751   this->StartInteraction();
752   this->InvokeEvent(vtkCommand::StartInteractionEvent,NULL);
753   this->Interactor->Render();
754 }
755 //==================================================================
756 // function: OnRightButtonUp
757 // purpose :
758 //==================================================================
759 void VISU_PlanesWidget::OnRightButtonUp()
760 {
761   if ( this->State == VISU_PlanesWidget::Outside )    {
762     return;
763   }
764   
765   this->State = VISU_PlanesWidget::Start;
766   this->HighlightPlane(0);
767   this->HighlightOutline(0);
768   this->HighlightNormal(0);
769   //this->SizeHandles();
770   
771   this->EventCallbackCommand->SetAbortFlag(1);
772   this->EndInteraction();
773   this->InvokeEvent(vtkCommand::EndInteractionEvent,NULL);
774   this->Interactor->Render();
775 }
776 //==================================================================
777 // function: OnMouseMove
778 // purpose :
779 //==================================================================
780 void VISU_PlanesWidget::OnMouseMove()
781 {
782   //this->SizeHandles();
783
784   // See whether we're active
785   if ( this->State == VISU_PlanesWidget::Outside || 
786        this->State == VISU_PlanesWidget::Start )    {
787     return;
788   }
789   
790   int X = this->Interactor->GetEventPosition()[0];
791   int Y = this->Interactor->GetEventPosition()[1];
792
793   // Do different things depending on state
794   // Calculations everybody does
795   double focalPoint[4], pickPoint[4], prevPickPoint[4];
796   double z, vpn[3];
797
798   vtkCamera *camera = this->CurrentRenderer->GetActiveCamera();
799   if ( !camera ) {
800     return;
801   }
802
803   // Compute the two points defining the motion vector
804   this->ComputeWorldToDisplay(this->LastPickPosition[0], this->LastPickPosition[1],
805                               this->LastPickPosition[2], focalPoint);
806   z = focalPoint[2];
807   this->ComputeDisplayToWorld(double(this->Interactor->GetLastEventPosition()[0]),
808                               double(this->Interactor->GetLastEventPosition()[1]),
809                               z, prevPickPoint);
810   this->ComputeDisplayToWorld(double(X), double(Y), z, pickPoint);
811
812   // Process the motion
813   if ( this->State == VISU_PlanesWidget::MovingPlane )    {
814     //this->TranslatePlane(prevPickPoint, pickPoint);
815     //printf(" TranslatePlane\n");
816   }
817   else if ( this->State == VISU_PlanesWidget::MovingOutline )    {
818     //this->TranslateOutline(prevPickPoint, pickPoint);
819     //printf(" TranslateOutline\n");
820   }
821   else if ( this->State == VISU_PlanesWidget::MovingOrigin )    {
822     this->TranslateOrigin(prevPickPoint, pickPoint);
823     //printf(" TranslateOrigin\n");
824   }
825   else if ( this->State == VISU_PlanesWidget::Pushing )    {
826     this->Push(prevPickPoint, pickPoint);
827    // printf(" Push\n");
828   }
829   else if ( this->State == VISU_PlanesWidget::Scaling )    {
830     //this->Scale(prevPickPoint, pickPoint, X, Y);
831     //printf(" Scale\n");
832   }
833   else if ( this->State == VISU_PlanesWidget::Rotating )    {
834     camera->GetViewPlaneNormal(vpn);
835     this->Rotate(X, Y, prevPickPoint, pickPoint, vpn);
836     //printf(" Rotate\n");
837   }
838   else if ( this->State == VISU_PlanesWidget::ChangeDistance )    {
839     this->PushDistance(prevPickPoint, pickPoint);
840     //printf(" PushDistance\n");
841   }
842   // Interact, if desired
843   this->EventCallbackCommand->SetAbortFlag(1);
844   this->InvokeEvent(vtkCommand::InteractionEvent,NULL);
845   
846   this->Interactor->Render();
847 }
848 //==================================================================
849 // function: Push
850 // purpose :
851 //==================================================================
852 void VISU_PlanesWidget::Push(double *p1, double *p2)
853 {
854   //Get the motion vector
855   int i;
856   float v[3];
857   //
858   for (i=0; i<3; ++i){  
859     v[i] = p2[i] - p1[i];
860   }
861   //
862   float aOr1[3], aNr1[3], aNr2[3], aD, z1;
863   //
864   myPlane1->GetOrigin(aOr1);
865   myPlane1->GetNormal(aNr1);
866   myPlane2->GetNormal(aNr2);
867   //
868   aD=vtkMath::Dot(v, aNr2);
869   z1 = aOr1[2]+aD*aNr2[2];
870   if( z1 <= myBox->GetOrigin()[2] ){
871     return;
872   }
873   //  
874   aD=vtkMath::Dot(v, aNr1);
875   for (i=0; i < 3; ++i) {
876     aOr1[i]=aOr1[i]+aD*aNr1[i];
877   }
878   SetOriginInternal(aOr1);
879   this->UpdateRepresentation();
880 }
881 //==================================================================
882 // function: TranslateOrigin
883 // purpose :
884 //==================================================================
885 void VISU_PlanesWidget::TranslateOrigin(double *p1, double *p2)
886 {
887   //Get the motion vector
888   int i;
889   double v[3];
890   //
891   for (i=0; i<3; ++i){  
892     v[i] = p2[i] - p1[i];
893   }
894   //
895   //Add to the current point, project back down onto plane
896   float *o = myPlane1->GetOrigin();
897   float *n = myPlane1->GetNormal();
898   float newOrigin[3];
899   //
900   for (i=0; i<3; ++i){
901     newOrigin[i]=o[i] + v[i];
902   }
903   vtkPlane::ProjectPoint(newOrigin, o, n, newOrigin);
904   SetOriginInternal(newOrigin); 
905   this->UpdateRepresentation();
906 }
907 //==================================================================
908 // function: SetOriginInternal
909 // purpose : Set the origin of the plane.(for Internal calls)
910 //==================================================================
911 void VISU_PlanesWidget::SetOriginInternal(float x[3]) 
912 {
913   float *bounds = this->myOutline->GetOutput()->GetBounds();
914   int i, j;
915   for (i=0; i<3; ++i)    {
916     j=2*i;
917     if ( x[i] < bounds[j] ) {
918       x[i] = bounds[j];
919     }
920     else if ( x[i] > bounds[j+1] ) {
921       x[i] = bounds[j+1];
922     }
923   }
924   //
925   bool bFlag;
926   float aOr2[3], aNr2[3], aNr1[3];
927   vtkPlane *pPx;
928   //
929   myPlane1->GetNormal(aNr1);
930   myPlane2->GetNormal(aNr2);
931   for (i=0; i<3; ++i)    {
932     aOr2[i]=x[i]+myDistance*aNr1[i];
933   }
934   pPx=vtkPlane::New();
935   pPx->SetOrigin(aOr2);
936   pPx->SetNormal(aNr2);
937   bFlag=IsValidPlane2Position(pPx, myBox);
938   if (bFlag){
939     myPlane1->SetOrigin(x);
940     myPlane2->SetOrigin(aOr2);
941   }
942   pPx->Delete();
943 }
944 //==================================================================
945 // function: Rotate
946 // purpose :
947 //==================================================================
948 void VISU_PlanesWidget::Rotate(int X, int Y, 
949                                          double *p1, double *p2, 
950                                          double *vpn)
951 {
952   double v[3];    //vector of motion
953   double axis[3]; //axis of rotation
954   double theta;   //rotation angle
955   int i;
956
957   // mouse motion vector in world space
958   for (i=0; i<3; ++i){ 
959     v[i] = p2[i] - p1[i];
960   }
961   //
962   float *origin = myPlane1->GetOrigin();
963   float *normal = myPlane1->GetNormal();
964
965   // Create axis of rotation and angle of rotation
966   vtkMath::Cross(vpn,v,axis);
967   if ( vtkMath::Normalize(axis) == 0.0 )    {
968     return;
969   }
970
971   int *size = this->CurrentRenderer->GetSize();
972   double l2 = (X-this->Interactor->GetLastEventPosition()[0])*
973     (X-this->Interactor->GetLastEventPosition()[0]) + 
974     (Y-this->Interactor->GetLastEventPosition()[1])*
975     (Y-this->Interactor->GetLastEventPosition()[1]);
976   theta = 360.0 * sqrt(l2/((double)size[0]*size[0]+size[1]*size[1]));
977
978   //Manipulate the transform to reflect the rotation
979   this->Transform->Identity();
980   this->Transform->Translate(origin[0],origin[1],origin[2]);
981   this->Transform->RotateWXYZ(theta,axis);
982   this->Transform->Translate(-origin[0],-origin[1],-origin[2]);
983
984   //Set the new normal
985   float nNew[3], aN2[3], oNew[3];
986   this->Transform->TransformNormal(normal,nNew);
987   //
988   for (i=0; i<3; ++i){  
989     aN2[i] = -nNew[i];
990   }
991   vtkMath::Normalize(nNew);
992   for (i=0; i<3; ++i){  
993     oNew[i] = origin[i] + myDistance*nNew[i];
994   }
995   //
996   vtkPlane *pPx=vtkPlane::New();
997   pPx->SetNormal(aN2); 
998   pPx->SetOrigin(oNew);
999   //
1000   bool bFlag=IsValidPlane2Position(pPx, myBox);
1001   if (bFlag) {
1002     myPlane1->SetNormal(nNew);
1003     this->myPlane2->SetNormal(aN2); 
1004     this->myPlane2->SetOrigin(oNew);
1005   } 
1006   pPx->Delete();
1007   this->UpdateRepresentation();
1008 }
1009 //==================================================================
1010 // function: PushDistance
1011 // purpose :
1012 //==================================================================
1013 void VISU_PlanesWidget::PushDistance(double *p1, double *p2)
1014 {
1015   int i;
1016   float v[3],  *anOrigin1, *aN1, *anOrigin2, *aN2, aD;
1017   //Get the motion vector
1018   for (i=0; i<3; ++i){ 
1019     v[i] = p2[i] - p1[i];
1020   }
1021   //
1022   anOrigin1 = myPlane1->GetOrigin();
1023   aN1 = myPlane1->GetNormal();
1024   anOrigin2 = myPlane2->GetOrigin();
1025   aN2 = myPlane2->GetNormal();
1026
1027   vtkMath::Normalize(aN1);
1028
1029   float origin[3];
1030   double distance = vtkMath::Dot( v, aN2 );
1031   for(i=0; i<3; ++i) {
1032     origin[i] = anOrigin2[i] + distance * aN2[i];
1033   }
1034   float d = DistanceToPlane(origin, aN1, anOrigin1);
1035   if( d <= 0.0 )
1036     return;
1037   //
1038   bool bFlag;
1039   float aOr2[3], aNr2[3];
1040   vtkPlane *pPx;
1041   //
1042   myPlane2->GetOrigin(aOr2);
1043   myPlane2->GetNormal(aNr2);
1044   pPx=vtkPlane::New();
1045   pPx->SetNormal(aNr2);
1046   aD=vtkMath::Dot(v, aNr2);
1047   for (i=0; i < 3; ++i) {
1048     aOr2[i]=aOr2[i]+aD*aNr2[i];
1049   }
1050   pPx->SetOrigin(aOr2);
1051   bFlag=IsValidPlane2Position(pPx, myBox);
1052   if(bFlag) {
1053     myPlane2->SetOrigin(aOr2);
1054     myPlane2->Modified();
1055     aD=DistanceToPlane(aOr2, aN1, anOrigin1);
1056     //
1057     myDistance=aD;
1058   }
1059   pPx->Delete();
1060   this->UpdateRepresentation();
1061 }
1062
1063 //==================================================================
1064 // function: TranslatePlane
1065 // purpose : Loop through all points and translate them
1066 //==================================================================
1067 void VISU_PlanesWidget::TranslatePlane(double *p1, double *p2)
1068 {
1069   //Get the motion vector
1070   double v[3];
1071   v[0] = p2[0] - p1[0];
1072   v[1] = p2[1] - p1[1];
1073   v[2] = p2[2] - p1[2];
1074   
1075   //Translate the plane
1076   float oNew[3];
1077   float *origin = myPlane1->GetOrigin();
1078   oNew[0] = origin[0] + v[0];
1079   oNew[1] = origin[1] + v[1];
1080   oNew[2] = origin[2] + v[2];
1081   myPlane1->SetOrigin(oNew);
1082   
1083   origin = this->myPlane2->GetOrigin();
1084   oNew[0] = origin[0] + v[0];
1085   oNew[1] = origin[1] + v[1];
1086   oNew[2] = origin[2] + v[2];
1087   this->myPlane2->SetOrigin(oNew);
1088
1089   this->UpdateRepresentation();
1090 }
1091 //==================================================================
1092 // function: TranslateOutline
1093 // purpose :Loop through all points and translate them
1094 //==================================================================
1095 void VISU_PlanesWidget::TranslateOutline(double *p1, double *p2)
1096 {
1097   //Get the motion vector
1098   double v[3];
1099   v[0] = p2[0] - p1[0];
1100   v[1] = p2[1] - p1[1];
1101   v[2] = p2[2] - p1[2];
1102   
1103   //Translate the bounding box
1104   float *origin = myBox->GetOrigin();
1105   float oNew[3];
1106   oNew[0] = origin[0] + v[0];
1107   oNew[1] = origin[1] + v[1];
1108   oNew[2] = origin[2] + v[2];
1109   myBox->SetOrigin(oNew);
1110
1111   //Translate the plane
1112   origin = myPlane1->GetOrigin();
1113   oNew[0] = origin[0] + v[0];
1114   oNew[1] = origin[1] + v[1];
1115   oNew[2] = origin[2] + v[2];
1116   myPlane1->SetOrigin(oNew);
1117
1118   origin = this->myPlane2->GetOrigin();
1119   oNew[0] = origin[0] + v[0];
1120   oNew[1] = origin[1] + v[1];
1121   oNew[2] = origin[2] + v[2];
1122   this->myPlane2->SetOrigin(oNew);
1123
1124   this->UpdateRepresentation();
1125 }
1126
1127 //==================================================================
1128 // function: Scale
1129 // purpose :
1130 //==================================================================
1131 void VISU_PlanesWidget::Scale(double *p1, double *p2, 
1132                                         int vtkNotUsed(X), int Y)
1133 {
1134   //Get the motion vector
1135   double v[3];
1136   v[0] = p2[0] - p1[0];
1137   v[1] = p2[1] - p1[1];
1138   v[2] = p2[2] - p1[2];
1139
1140   //int res = this->PlaneSource->GetXResolution();
1141   float *o = myPlane1->GetOrigin();
1142
1143   // Compute the scale factor
1144   float sf = vtkMath::Norm(v) / this->myOutline->GetOutput()->GetLength();
1145   if ( Y > this->Interactor->GetLastEventPosition()[1] )    {
1146     sf = 1.0 + sf;
1147   }
1148   else    {
1149     sf = 1.0 - sf;
1150   }
1151   
1152   this->Transform->Identity();
1153   this->Transform->Translate(o[0],o[1],o[2]);
1154   this->Transform->Scale(sf,sf,sf);
1155   this->Transform->Translate(-o[0],-o[1],-o[2]);
1156
1157   float *origin = myBox->GetOrigin();
1158   float *spacing = myBox->GetSpacing();
1159   float oNew[3], p[3], pNew[3];
1160   p[0] = origin[0] + spacing[0];
1161   p[1] = origin[1] + spacing[1];
1162   p[2] = origin[2] + spacing[2];
1163
1164   this->Transform->TransformPoint(origin,oNew);
1165   this->Transform->TransformPoint(p,pNew);
1166
1167   myBox->SetOrigin(oNew);
1168   myBox->SetSpacing( (pNew[0]-oNew[0]), (pNew[1]-oNew[1]), (pNew[2]-oNew[2]) );
1169
1170   this->UpdateRepresentation();
1171 }
1172
1173
1174
1175 //==================================================================
1176 // function: CreateDefaultProperties
1177 // purpose :
1178 //==================================================================
1179 void VISU_PlanesWidget::CreateDefaultProperties()
1180 {
1181   // Normal properties
1182   this->NormalProperty = vtkProperty::New();
1183   this->NormalProperty->SetColor(1,1,1);
1184   this->NormalProperty->SetLineWidth(2);
1185
1186   this->SelectedNormalProperty = vtkProperty::New();
1187   this->SelectedNormalProperty->SetColor(1,0,0);
1188   this->NormalProperty->SetLineWidth(2);
1189
1190   // Plane properties
1191   this->PlaneProperty = vtkProperty::New();
1192   this->PlaneProperty->SetAmbient(1.0);
1193   this->PlaneProperty->SetAmbientColor(1.0,1.0,1.0);
1194
1195   this->SelectedPlaneProperty = vtkProperty::New();
1196   this->SelectedPlaneProperty->SetAmbient(1.0);
1197   this->SelectedPlaneProperty->SetAmbientColor(0.0,1.0,0.0);
1198   this->SelectedPlaneProperty->SetOpacity(0.25);
1199
1200   // Outline properties
1201   this->OutlineProperty = vtkProperty::New();
1202   this->OutlineProperty->SetAmbient(1.0);
1203   this->OutlineProperty->SetAmbientColor(1.0,1.0,1.0);
1204
1205   this->SelectedOutlineProperty = vtkProperty::New();
1206   this->SelectedOutlineProperty->SetAmbient(1.0);
1207   this->SelectedOutlineProperty->SetAmbientColor(0.0,1.0,0.0);
1208
1209   // Edge property
1210   this->EdgesProperty = vtkProperty::New();
1211   this->EdgesProperty->SetAmbient(1.0);
1212   this->EdgesProperty->SetAmbientColor(1.0,1.0,1.0);
1213 }
1214 //==================================================================
1215 // function: InitialPlaceWidget
1216 // purpose :
1217 //==================================================================
1218 void VISU_PlanesWidget::InitialPlaceWidget(float bds[6])
1219 {
1220   float bounds[6], origin[3];
1221
1222   PlaceWidget(bds);
1223   //
1224   this->AdjustBounds(bds, bounds, origin);
1225   this->SetOrigin((bounds[1]+bounds[0])/2.0,
1226                   (bounds[3]+bounds[2])/2.0,
1227                   (bounds[5]+bounds[4])/2.0);
1228
1229   static float DIST_COEFF = 0.1;
1230   SetDistance(this->InitialLength*DIST_COEFF);
1231   //
1232   this->UpdateRepresentation();
1233 }
1234 //==================================================================
1235 // function: PlaceWidget
1236 // purpose :
1237 //==================================================================
1238 void VISU_PlanesWidget::PlaceWidget(float bds[6])
1239 {
1240   int i;
1241   float bounds[6], origin[3];
1242
1243   this->AdjustBounds(bds, bounds, origin);
1244
1245   // Set up the bounding box
1246   myBox->SetOrigin(bounds[0],bounds[2],bounds[4]);
1247   myBox->SetSpacing((bounds[1]-bounds[0]),(bounds[3]-bounds[2]),
1248                         (bounds[5]-bounds[4]));
1249   this->myOutline->Update();
1250
1251   if (this->Input || this->Prop3D)    {
1252     this->LineSource->SetPoint1(myPlane1->GetOrigin());
1253     if ( this->NormalToYAxis )      {
1254       myPlane1->SetNormal(0,1,0);
1255       myPlane2->SetNormal(0,-1,0);
1256       this->LineSource->SetPoint2(0,1,0);
1257     }
1258     else if ( this->NormalToZAxis )      {
1259       myPlane1->SetNormal(0,0,1);
1260       myPlane2->SetNormal(0,0,-1);
1261       this->LineSource->SetPoint2(0,0,1);
1262     }
1263     else{ //default or x-normal
1264       myPlane1->SetNormal(1,0,0);
1265       myPlane2->SetNormal(-1,0,0);
1266       this->LineSource->SetPoint2(1,0,0);
1267     }
1268   }
1269   
1270   for (i=0; i<6; i++)    {
1271     this->InitialBounds[i] = bounds[i];
1272   }
1273
1274   this->InitialLength = sqrt((bounds[1]-bounds[0])*(bounds[1]-bounds[0]) +
1275                              (bounds[3]-bounds[2])*(bounds[3]-bounds[2]) +
1276                              (bounds[5]-bounds[4])*(bounds[5]-bounds[4]));
1277
1278   this->UpdateRepresentation();
1279 }
1280 //==================================================================
1281 // function: SetOrigin
1282 // purpose :Set the origin of the plane.(for external calls)
1283 //==================================================================
1284 void VISU_PlanesWidget::SetOrigin(float x, float y, float z) 
1285 {
1286   float origin[3];
1287   origin[0] = x;
1288   origin[1] = y;
1289   origin[2] = z;
1290   this->SetOrigin(origin);
1291 }
1292 //==================================================================
1293 // function: SetOrigin 
1294 // purpose : Set the origin of the plane.(for external calls)
1295 //==================================================================
1296 void VISU_PlanesWidget::SetOrigin(float x[3])
1297 {
1298   float *bounds = this->myOutline->GetOutput()->GetBounds();
1299   for (int i=0; i<3; i++)    {
1300     if ( x[i] < bounds[2*i] )      {
1301       x[i] = bounds[2*i];
1302     }
1303     else if ( x[i] > bounds[2*i+1] )      {
1304       x[i] = bounds[2*i+1];
1305     }
1306   }
1307   myPlane1->SetOrigin(x);
1308   float *origin, *normal, oNew[3];
1309   origin = myPlane1->GetOrigin();
1310   normal = myPlane1->GetNormal();
1311   vtkMath::Normalize(normal);
1312   oNew[0] = origin[0] + myDistance*normal[0];
1313   oNew[1] = origin[1] + myDistance*normal[1];
1314   oNew[2] = origin[2] + myDistance*normal[2];
1315   this->myPlane2->SetOrigin(oNew);
1316   this->UpdateRepresentation();
1317 }
1318 //==================================================================
1319 // function: GetOrigin
1320 // purpose :Get the origin of the plane.
1321 //==================================================================
1322 float* VISU_PlanesWidget::GetOrigin() 
1323 {
1324   return myPlane1->GetOrigin();
1325 }
1326
1327 void VISU_PlanesWidget::GetOrigin(float xyz[3]) 
1328 {
1329   myPlane1->GetOrigin(xyz);
1330 }
1331 //==================================================================
1332 // function: SetNormal
1333 // purpose :Set the normal to the plane.
1334 //==================================================================
1335 void VISU_PlanesWidget::SetNormal(float x, float y, float z) 
1336 {
1337   float n[3];
1338   n[0] = x;
1339   n[1] = y;
1340   n[2] = z;
1341   vtkMath::Normalize(n);
1342   myPlane1->SetNormal(n);
1343   n[0] =- x;
1344   n[1] =- y;
1345   n[2] =- z;
1346   this->myPlane2->SetNormal(n);
1347
1348   this->UpdateRepresentation();
1349 }
1350
1351 //==================================================================
1352 // function: SetNormal
1353 // purpose :Set the normal to the plane.
1354 //==================================================================
1355 void VISU_PlanesWidget::SetNormal(float n[3]) 
1356 {
1357   this->SetNormal(n[0], n[1], n[2]);
1358 }
1359 //==================================================================
1360 // function: GetNormal
1361 // purpose :Get the normal to the plane.
1362 //==================================================================
1363 float* VISU_PlanesWidget::GetNormal() 
1364 {
1365   return myPlane1->GetNormal();
1366 }
1367 //==================================================================
1368 // function: GetNormal
1369 // purpose :Get the normal to the plane.
1370 //==================================================================
1371 void VISU_PlanesWidget::GetNormal(float xyz[3]) 
1372 {
1373   myPlane1->GetNormal(xyz);
1374 }
1375 //==================================================================
1376 // function: SetDrawPlane
1377 // purpose :
1378 //==================================================================
1379 void VISU_PlanesWidget::SetDrawPlane(int drawPlane)
1380 {
1381   if ( drawPlane == this->myDrawPlane )    {
1382     return;
1383   }
1384   
1385   this->Modified();
1386   this->myDrawPlane = drawPlane;
1387   if ( this->Enabled ) {
1388     if ( drawPlane ) {
1389       this->CurrentRenderer->AddActor(this->myCutActor1);
1390       this->CurrentRenderer->AddActor(myCutActor2);
1391     }
1392     else {
1393       this->CurrentRenderer->RemoveActor(this->myCutActor1);
1394       this->CurrentRenderer->RemoveActor(myCutActor2);
1395     }
1396     this->Interactor->Render();
1397   }
1398 }
1399 //==================================================================
1400 // function: SetNormalToXAxis
1401 // purpose :
1402 //==================================================================
1403 void VISU_PlanesWidget::SetNormalToXAxis (int var)
1404 {
1405   if (this->NormalToXAxis != var)    {
1406     this->NormalToXAxis = var;
1407     this->Modified();
1408   }
1409   if (var)    {
1410     this->NormalToYAxisOff();
1411     this->NormalToZAxisOff();
1412   }
1413 }
1414 //==================================================================
1415 // function: SetNormalToYAxis
1416 // purpose :
1417 //==================================================================
1418 void VISU_PlanesWidget::SetNormalToYAxis (int var)
1419 {
1420   if (this->NormalToYAxis != var)    {
1421     this->NormalToYAxis = var;
1422     this->Modified();
1423   }
1424   if (var)    {
1425     this->NormalToXAxisOff();
1426     this->NormalToZAxisOff();
1427   }
1428 }
1429 //==================================================================
1430 // function: SetNormalToZAxis
1431 // purpose :
1432 //==================================================================
1433 void VISU_PlanesWidget::SetNormalToZAxis (int var)
1434 {
1435   if (this->NormalToZAxis != var)    {
1436     this->NormalToZAxis = var;
1437     this->Modified();
1438   }
1439   if (var)    {
1440     this->NormalToXAxisOff();
1441     this->NormalToYAxisOff();
1442   }
1443 }
1444 //==================================================================
1445 // function: GetPolyData
1446 // purpose :
1447 //==================================================================
1448 void VISU_PlanesWidget::GetPolyData(vtkPolyData *pd)
1449
1450   pd->ShallowCopy(this->myCutter1->GetOutput()); 
1451 }
1452 //==================================================================
1453 // function: GetPolyDataSource
1454 // purpose :
1455 //==================================================================
1456 /*
1457 vtkPolyDataSource *VISU_PlanesWidget::GetPolyDataSource()
1458 {
1459   return this->myCutter1;
1460 }
1461 */
1462 //==================================================================
1463 // function:GetPlane
1464 // purpose :
1465 //==================================================================
1466 void VISU_PlanesWidget::GetPlane(vtkPlane *plane)
1467 {
1468   if ( plane == NULL )    {
1469     return;
1470   }
1471   
1472   plane->SetNormal(myPlane1->GetNormal());
1473   plane->SetOrigin(myPlane1->GetOrigin());
1474 }
1475 //==================================================================
1476 // function:UpdatePlacement
1477 // purpose :
1478 //==================================================================
1479 void VISU_PlanesWidget::UpdatePlacement(void)
1480 {
1481   this->myOutline->Update();
1482   this->myCutter1->Update();
1483   this->myEdges1->Update();
1484 }
1485 //==================================================================
1486 // function:UpdateRepresentation
1487 // purpose :
1488 //==================================================================
1489 void VISU_PlanesWidget::UpdateRepresentation()
1490 {
1491   if ( ! this->CurrentRenderer )    {
1492     return;
1493   }
1494
1495   float *origin = myPlane1->GetOrigin();
1496   float *normal = myPlane1->GetNormal();
1497   float p2[3];
1498
1499   // Setup the plane normal
1500   float d = this->myOutline->GetOutput()->GetLength();
1501
1502   p2[0] = origin[0] + 0.30 * d * normal[0];
1503   p2[1] = origin[1] + 0.30 * d * normal[1];
1504   p2[2] = origin[2] + 0.30 * d * normal[2];
1505
1506   this->LineSource->SetPoint1(origin);
1507   this->LineSource->SetPoint2(p2);
1508   this->ConeSource->SetCenter(p2);
1509   this->ConeSource->SetDirection(normal);
1510   ConeActor->SetCenter(p2);
1511
1512   p2[0] = origin[0] - 0.30 * d * normal[0];
1513   p2[1] = origin[1] - 0.30 * d * normal[1];
1514   p2[2] = origin[2] - 0.30 * d * normal[2];
1515
1516   this->LineSource2->SetPoint1(origin);
1517   this->LineSource2->SetPoint2(p2);
1518   this->ConeSource2->SetCenter(p2);
1519   this->ConeSource2->SetDirection(normal);
1520   ConeActor2->SetCenter(p2);
1521
1522   // Set up the position handle
1523   this->Sphere->SetCenter(origin);
1524   SphereActor->SetCenter(origin);
1525
1526   this->myEdgesMapper1->SetInput(this->myEdges1->GetOutput());
1527 }
1528
1529 //==================================================================
1530 // function:PrintSelf
1531 // purpose :
1532 //==================================================================
1533 void VISU_PlanesWidget::PrintSelf(ostream& os, vtkIndent indent)
1534 {
1535   this->Superclass::PrintSelf(os,indent);
1536 }
1537 //==================================================================
1538 // function: IsValidPlane2Position
1539 // purpose :
1540 //==================================================================
1541 bool IsValidPlane2Position(vtkPlane *pPx,
1542                            vtkDataSet *pDataSet,
1543                            float aTol)
1544 {
1545   bool bRet;
1546   int i, iFound;
1547   float aD, aDmax, aPnts[24], aDiagonal;
1548   float aTol1, aOr[3], aN[3];
1549   //
1550   bRet=false;
1551   aDiagonal=pDataSet->GetLength();
1552   aTol1=aDiagonal*aTol;
1553   //
1554   GetBndPoints(pDataSet, aPnts);
1555   //
1556   pPx->GetOrigin(aOr);
1557   pPx->GetNormal(aN);
1558   vtkMath::Normalize(aN);
1559   //
1560   iFound=0;
1561   aDmax=0.;
1562   for (i=0; i<24; i+=3){
1563     aD=-DistanceToPlane(aPnts+i, aN, aOr);
1564     if (aD>aDmax){
1565             aDmax=aD;
1566             iFound=1;
1567     }
1568   }
1569   if (iFound && aDmax>aTol1) {
1570     bRet=!bRet;
1571   }
1572   return bRet;
1573 }
1574 //==================================================================
1575 // function: GetBndPoints
1576 // purpose :
1577 //==================================================================
1578 void GetBndPoints(vtkDataSet *pDataSet, 
1579                   float aPnts[24])
1580 {
1581   int aIndx[24]={
1582     0,2,4,1,2,4,1,3,4,0,3,4,
1583     0,2,5,1,2,5,1,3,5,0,3,5
1584   };
1585   int i;
1586   float *pBounds=pDataSet->GetBounds();
1587   //
1588   for (i=0; i<24; ++i){
1589     aPnts[i]=pBounds[aIndx[i]];
1590   }
1591 }
1592 //==================================================================
1593 // function: DistanceToPlane
1594 // purpose :
1595 //==================================================================
1596 float DistanceToPlane(const float x[3], 
1597                       const float n[3], 
1598                       const float p0[3])
1599 {
1600   return ((float) (n[0]*(x[0]-p0[0]) + 
1601                    n[1]*(x[1]-p0[1]) +  
1602                    n[2]*(x[2]-p0[2])));
1603 }
1604 /*
1605 //==================================================================
1606 // function:SizeHandles
1607 // purpose :
1608 //==================================================================
1609 void VISU_PlanesWidget::SizeHandles()
1610 {
1611   //  float radius = 
1612   this->vtk3DWidget::SizeHandles(1.35);
1613 }
1614 */