Salome HOME
Join modifications from branch OCC_development_for_3_2_0a2
[modules/gui.git] / src / SVTK / SVTK_Renderer.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   :
25 //  Author :
26 //  Module :
27 //  $Header$
28
29 #include "SVTK_Renderer.h"
30
31 #include "SVTK_Trihedron.h"
32 #include "SVTK_CubeAxesActor2D.h"
33 #include "SVTK_RectPicker.h"
34
35 #include "SALOME_Actor.h"
36 #include "VTKViewer_Actor.h"
37 #include "VTKViewer_Transform.h"
38 #include "VTKViewer_Utilities.h"
39
40 #include <vtkCamera.h>
41 #include <vtkRenderer.h>
42 #include <vtkTextProperty.h>
43 #include <vtkObjectFactory.h>
44 #include <vtkCallbackCommand.h>
45
46 #include <vtkPicker.h>
47 #include <vtkPointPicker.h>
48 #include <vtkCellPicker.h>
49
50 #include <vtkProperty.h>
51
52 // undefining min and max because CASCADE's defines them and
53 // it clashes with std::min(), std::max() included in utilities.h
54 #undef min
55 #undef max
56
57
58 //----------------------------------------------------------------------------
59 vtkStandardNewMacro(SVTK_Renderer);
60
61 //----------------------------------------------------------------------------
62 SVTK_Renderer
63 ::SVTK_Renderer():
64   myDevice(vtkRenderer::New()),
65   myInteractor(NULL),
66   myPriority(0.0),
67   myEventCallbackCommand(vtkCallbackCommand::New()),
68   myPointPicker(vtkPointPicker::New()),
69   myCellPicker(vtkCellPicker::New()),
70   myPointRectPicker(SVTK_RectPicker::New()),
71   myCellRectPicker(SVTK_RectPicker::New()),
72   myPreHighlightProperty(vtkProperty::New()),
73   myHighlightProperty(vtkProperty::New()),
74   myTransform(VTKViewer_Transform::New()),
75   myCubeAxes(SVTK_CubeAxesActor2D::New()),
76   myTrihedron(SVTK_Trihedron::New()),
77   myTrihedronSize(105),
78   myIsTrihedronRelative(true)
79 {
80   myDevice->Delete();
81   myTransform->Delete();
82
83   SetSelectionTolerance();
84
85   myPointPicker->Delete();
86   myCellPicker->Delete();
87
88   myPointRectPicker->Delete();
89   myPointRectPicker->PickFromListOn();
90
91   myCellRectPicker->Delete();
92   myCellRectPicker->PickFromListOn();
93   myCellRectPicker->PickPointsOff();
94
95   //SetPreselectionProp();
96   myPreHighlightProperty->Delete();
97   myPreHighlightProperty->SetColor(0,1,1);
98   myPreHighlightProperty->SetPointSize(SALOME_POINT_SIZE+2);
99   myPreHighlightProperty->SetLineWidth(SALOME_LINE_WIDTH+2);
100   myPreHighlightProperty->SetRepresentationToPoints();
101
102   //SetSelectionProp();
103   myHighlightProperty->Delete();
104   myHighlightProperty->SetColor(1,1,0);
105   myHighlightProperty->SetPointSize(SALOME_POINT_SIZE+2);
106   myHighlightProperty->SetLineWidth(SALOME_LINE_WIDTH+2);
107   myHighlightProperty->SetRepresentationToPoints();
108
109   myTrihedron->Delete();
110   myCubeAxes->Delete();
111   myEventCallbackCommand->Delete();
112
113   myTrihedron->AddToRender(GetDevice());
114   GetDevice()->AddProp(GetCubeAxes());
115
116   myBndBox[0] = myBndBox[2] = myBndBox[4] = 0;
117   myBndBox[1] = myBndBox[3] = myBndBox[5] = myTrihedron->GetSize();
118
119   myCubeAxes->SetBounds(myBndBox);
120   myCubeAxes->SetCamera(GetDevice()->GetActiveCamera());
121
122   myCubeAxes->SetLabelFormat("%6.4g");
123   myCubeAxes->SetFlyModeToOuterEdges(); // ENK remarks: it must bee
124   myCubeAxes->SetFontFactor(0.8);
125   myCubeAxes->SetCornerOffset(0);
126   myCubeAxes->SetScaling(0);
127   myCubeAxes->SetNumberOfLabels(5);
128   myCubeAxes->VisibilityOff();
129   myCubeAxes->SetTransform(GetTransform());
130
131   vtkTextProperty* aTextProp = vtkTextProperty::New();
132   aTextProp->SetColor(1, 1, 1);
133   aTextProp->ShadowOn();
134   myCubeAxes->SetAxisTitleTextProperty(aTextProp);
135   myCubeAxes->SetAxisLabelTextProperty(aTextProp);
136   aTextProp->Delete();
137
138   GetDevice()->GetActiveCamera()->ParallelProjectionOn();
139   GetDevice()->LightFollowCameraOn();
140   GetDevice()->TwoSidedLightingOn();
141
142   myEventCallbackCommand->SetClientData(this);
143   myEventCallbackCommand->SetCallback(SVTK_Renderer::ProcessEvents);
144   GetDevice()->AddObserver(vtkCommand::ConfigureEvent,
145                            myEventCallbackCommand.GetPointer(), 
146                            myPriority);
147   GetDevice()->AddObserver(vtkCommand::ResetCameraEvent,
148                            myEventCallbackCommand.GetPointer(), 
149                            myPriority);
150   GetDevice()->AddObserver(vtkCommand::ResetCameraClippingRangeEvent,
151                            myEventCallbackCommand.GetPointer(), 
152                            myPriority);
153 }
154
155 SVTK_Renderer
156 ::~SVTK_Renderer()
157 {
158   vtkActorCollection* anActors = GetDevice()->GetActors();
159   vtkActorCollection* anActors2 = vtkActorCollection::New();
160
161   anActors->InitTraversal();
162   while(vtkActor* anAct = anActors->GetNextActor()){
163     if(SALOME_Actor* anActor = dynamic_cast<SALOME_Actor*>(anAct)){
164       anActors2->AddItem(anActor);
165     }
166   }
167
168   anActors2->InitTraversal();
169   while(vtkActor* anAct = anActors2->GetNextActor()){
170     if(SALOME_Actor* anActor = dynamic_cast<SALOME_Actor*>(anAct)){
171       RemoveActor(anActor);
172     }
173   }
174
175   anActors2->Delete();
176 }
177
178
179 void 
180 SVTK_Renderer
181 ::ProcessEvents(vtkObject* vtkNotUsed(theObject), 
182                 unsigned long theEvent,
183                 void* theClientData, 
184                 void* vtkNotUsed(theCallData))
185 {
186   SVTK_Renderer* self = reinterpret_cast<SVTK_Renderer*>(theClientData);
187
188   switch(theEvent){
189   case vtkCommand::ConfigureEvent:
190     self->OnResetView();
191     break;
192   case vtkCommand::ResetCameraEvent:
193     self->OnFitAll();
194     break;
195   case vtkCommand::ResetCameraClippingRangeEvent:
196     self->OnResetClippingRange();
197     break;
198   }
199 }
200
201 //----------------------------------------------------------------------------
202 vtkRenderer* 
203 SVTK_Renderer
204 ::GetDevice()
205 {
206   return myDevice.GetPointer();
207 }
208
209 void 
210 SVTK_Renderer
211 ::Initialize(vtkRenderWindowInteractor* theInteractor,
212              SVTK_Selector* theSelector)
213 {
214   myInteractor = theInteractor;
215   mySelector = theSelector;
216 }
217
218 //----------------------------------------------------------------------------
219 void
220 SVTK_Renderer
221 ::AddActor(VTKViewer_Actor* theActor)
222 {
223   if(SALOME_Actor* anActor = dynamic_cast<SALOME_Actor*>(theActor)){
224     anActor->SetInteractor(myInteractor);
225     anActor->SetTransform(GetTransform());
226     anActor->SetSelector(mySelector.GetPointer());
227
228     anActor->SetPointPicker(myPointPicker.GetPointer());
229     anActor->SetCellPicker(myCellPicker.GetPointer());
230
231     anActor->SetPointRectPicker(myPointRectPicker.GetPointer());
232     anActor->SetCellRectPicker(myCellRectPicker.GetPointer());
233
234     anActor->SetPreHighlightProperty(myPreHighlightProperty.GetPointer());
235     anActor->SetHighlightProperty(myHighlightProperty.GetPointer());
236
237     anActor->AddToRender(GetDevice());
238     AdjustActors();
239   }
240 }
241
242 void
243 SVTK_Renderer
244 ::RemoveActor(VTKViewer_Actor* theActor)
245 {
246   if(SALOME_Actor* anActor = dynamic_cast<SALOME_Actor*>(theActor)){
247     // Order of the calls are important because VTKViewer_Actor::RemoveFromRender
248     //   can leads do destruction of the actor
249     anActor->SetInteractor(NULL);
250     anActor->SetTransform(NULL);
251     anActor->SetSelector(NULL);
252
253     anActor->SetPointPicker(NULL);
254     anActor->SetCellPicker(NULL);
255
256     anActor->SetPointRectPicker(NULL);
257     anActor->SetCellRectPicker(NULL);
258
259     anActor->SetPreHighlightProperty(NULL);
260     anActor->SetHighlightProperty(NULL);
261
262     anActor->RemoveFromRender(GetDevice());
263     AdjustActors();
264   }
265 }
266
267 VTKViewer_Transform* 
268 SVTK_Renderer
269 ::GetTransform()
270 {
271   return myTransform.GetPointer();
272 }
273
274 void
275 SVTK_Renderer
276 ::GetScale( double theScale[3] ) 
277 {
278   myTransform->GetMatrixScale( theScale );
279 }
280
281 void
282 SVTK_Renderer
283 ::SetScale( double theScale[3] ) 
284 {
285   myTransform->SetMatrixScale( theScale[0], theScale[1], theScale[2] );
286   AdjustActors();
287 }
288
289
290 //----------------------------------------------------------------------------
291 void
292 SVTK_Renderer
293 ::SetSelectionProp(const double& theRed, 
294                    const double& theGreen, 
295                    const double& theBlue, 
296                    const int& theWidth) 
297 {
298   myHighlightProperty->SetColor( theRed, theGreen, theBlue );
299   myHighlightProperty->SetLineWidth( theWidth );
300   myHighlightProperty->SetPointSize( theWidth );
301 }
302
303 //----------------------------------------------------------------------------
304 void
305 SVTK_Renderer
306 ::SetPreselectionProp(const double& theRed, 
307                       const double& theGreen, 
308                       const double& theBlue, 
309                       const int& theWidth) 
310 {
311   myPreHighlightProperty->SetColor( theRed, theGreen, theBlue );
312   myPreHighlightProperty->SetLineWidth( theWidth );
313   myPreHighlightProperty->SetPointSize( theWidth );
314 }
315
316 //----------------------------------------------------------------------------
317 void
318 SVTK_Renderer
319 ::SetSelectionTolerance(const double& theTolNodes, 
320                         const double& theTolCell)
321 {
322   myPointPicker->SetTolerance( theTolNodes );
323   myCellPicker->SetTolerance( theTolCell );
324
325   myPointRectPicker->SetTolerance( theTolNodes );
326   myCellRectPicker->SetTolerance( theTolCell );
327 }
328
329
330 //----------------------------------------------------------------------------
331 /*! If parameter theIsForcedUpdate is true, recalculate parameters for
332  *  trihedron and cube axes, even if trihedron and cube axes is invisible.
333  */
334
335 inline
336 bool
337 CheckBndBox(const float theBounds[6])
338 {
339   if(theBounds[0] > -VTK_LARGE_FLOAT && theBounds[1] < VTK_LARGE_FLOAT &&
340      theBounds[2] > -VTK_LARGE_FLOAT && theBounds[3] < VTK_LARGE_FLOAT &&
341      theBounds[4] > -VTK_LARGE_FLOAT && theBounds[5] < VTK_LARGE_FLOAT)
342     return true;
343   return false;
344 }
345
346 bool
347 SVTK_Renderer
348 ::OnAdjustActors()
349 {
350   bool aTDisplayed = IsTrihedronDisplayed();
351   bool aCDisplayed = IsCubeAxesDisplayed();
352
353   float aNewBndBox[6];
354   aNewBndBox[ 0 ] = aNewBndBox[ 2 ] = aNewBndBox[ 4 ] = VTK_LARGE_FLOAT;
355   aNewBndBox[ 1 ] = aNewBndBox[ 3 ] = aNewBndBox[ 5 ] = -VTK_LARGE_FLOAT;
356
357   int aVisibleNum = myTrihedron->GetVisibleActorCount(GetDevice());
358   if(aVisibleNum){
359     if(aTDisplayed)
360       myTrihedron->VisibilityOff();
361
362     if(aCDisplayed) 
363       myCubeAxes->VisibilityOff();
364
365     // if the new trihedron size have sufficient difference, then apply the value
366     double aSize = myTrihedron->GetSize();
367     if ( IsTrihedronRelative() )
368       {
369         ComputeTrihedronSize(GetDevice(),aSize,aSize,myTrihedronSize);
370         myTrihedron->SetSize(aSize);
371       }
372     else
373       myTrihedron->SetSize( myTrihedronSize );
374
375     // iterate through displayed objects and set size if necessary
376     vtkActorCollection* anActors = GetDevice()->GetActors();
377     anActors->InitTraversal();
378     while(vtkActor* anAct = anActors->GetNextActor()){
379       if(SALOME_Actor* anActor = dynamic_cast<SALOME_Actor*>(anAct)){
380         if(anActor->IsResizable())
381           anActor->SetSize(0.5*aSize);
382         if(anActor->GetVisibility() && !anActor->IsInfinitive()){
383           float *aBounds = anActor->GetBounds();
384           if(CheckBndBox(aBounds))
385             for(int i = 0; i < 5; i = i + 2){
386               if(aBounds[i] < aNewBndBox[i]) 
387                 aNewBndBox[i] = aBounds[i];
388               if(aBounds[i+1] > aNewBndBox[i+1]) 
389                 aNewBndBox[i+1] = aBounds[i+1];
390             }
391         }
392       }
393     }
394
395     if(aTDisplayed) 
396       myTrihedron->VisibilityOn();
397
398     if(aCDisplayed) 
399       myCubeAxes->VisibilityOn();
400     
401   }else{
402     double aSize = myTrihedron->GetSize();
403     aNewBndBox[0] = aNewBndBox[2] = aNewBndBox[4] = 0;
404     aNewBndBox[1] = aNewBndBox[3] = aNewBndBox[5] = aSize;
405   }
406   
407   if(CheckBndBox(aNewBndBox)){
408     for(int i = 0; i < 6; i++)
409       myBndBox[i] = aNewBndBox[i];
410     myCubeAxes->SetBounds(myBndBox);
411     return true;
412   }
413
414   return false;
415 }
416
417 void
418 SVTK_Renderer
419 ::AdjustActors()
420 {
421   if(OnAdjustActors())
422     ::ResetCameraClippingRange(GetDevice());
423 }
424
425 void
426 SVTK_Renderer
427 ::SetTrihedronSize(int theSize, const bool theRelative)
428 {
429   if(myTrihedronSize != theSize || myIsTrihedronRelative != theRelative){
430     myTrihedronSize = theSize;
431     myIsTrihedronRelative = theRelative;
432     AdjustActors();
433   }
434 }
435
436 int
437 SVTK_Renderer
438 ::GetTrihedronSize() const
439 {
440   return myTrihedronSize;
441 }
442
443 bool 
444 SVTK_Renderer
445 ::IsTrihedronRelative() const
446 {
447   return myIsTrihedronRelative;
448 }
449
450 //----------------------------------------------------------------------------
451 VTKViewer_Trihedron* 
452 SVTK_Renderer
453 ::GetTrihedron()
454 {
455   return myTrihedron.GetPointer();
456 }
457
458 bool
459 SVTK_Renderer
460 ::IsTrihedronDisplayed()
461 {
462   return myTrihedron->GetVisibility() == VTKViewer_Trihedron::eOn;
463 }
464
465 void 
466 SVTK_Renderer
467 ::OnViewTrihedron()
468 {
469   if(IsTrihedronDisplayed())
470     myTrihedron->VisibilityOff();
471   else
472     myTrihedron->VisibilityOn();
473 }
474
475 void
476 SVTK_Renderer
477 ::OnAdjustTrihedron()
478 {   
479   AdjustActors();
480 }
481
482
483 //----------------------------------------------------------------------------
484 SVTK_CubeAxesActor2D* 
485 SVTK_Renderer
486 ::GetCubeAxes()
487 {
488   return myCubeAxes.GetPointer();
489 }
490
491 bool
492 SVTK_Renderer
493 ::IsCubeAxesDisplayed()
494 {
495   return myCubeAxes->GetVisibility() == 1;
496 }
497
498 void
499 SVTK_Renderer
500 ::OnViewCubeAxes()
501 {
502   if(IsCubeAxesDisplayed())
503     myCubeAxes->VisibilityOff();
504   else
505     myCubeAxes->VisibilityOn();
506 }
507
508 void
509 SVTK_Renderer
510 ::OnAdjustCubeAxes()
511 {   
512   AdjustActors();
513 }
514
515
516 //----------------------------------------------------------------------------
517 void
518 SVTK_Renderer
519 ::OnResetView()
520 {
521   int aTrihedronIsVisible = IsTrihedronDisplayed();
522   int aCubeAxesIsVisible = IsCubeAxesDisplayed();
523
524   myTrihedron->SetVisibility( VTKViewer_Trihedron::eOnlyLineOn );
525   myCubeAxes->SetVisibility(0);
526
527   ::ResetCamera(GetDevice(),true);  
528   vtkCamera* aCamera = GetDevice()->GetActiveCamera();
529   aCamera->SetPosition(1,-1,1);
530   aCamera->SetViewUp(0,0,1);
531   ::ResetCamera(GetDevice(),true);  
532
533   if(aTrihedronIsVisible) 
534     myTrihedron->VisibilityOn();
535   else
536     myTrihedron->VisibilityOff();
537
538   if(aCubeAxesIsVisible) 
539     myCubeAxes->VisibilityOn();
540   else
541     myCubeAxes->VisibilityOff();
542
543   static float aCoeff = 3.0;
544   aCamera->SetParallelScale(aCoeff*aCamera->GetParallelScale());
545 }
546
547
548 //----------------------------------------------------------------------------
549 void
550 SVTK_Renderer
551 ::OnFitAll()
552 {
553   int aTrihedronWasVisible = false;
554   int aCubeAxesWasVisible = false;
555
556   aTrihedronWasVisible = IsTrihedronDisplayed();
557   if(aTrihedronWasVisible)
558     myTrihedron->VisibilityOff();
559
560   aCubeAxesWasVisible = IsCubeAxesDisplayed();
561   if(aCubeAxesWasVisible)
562     myCubeAxes->VisibilityOff();
563
564   if(myTrihedron->GetVisibleActorCount(GetDevice())){
565     myTrihedron->VisibilityOff();
566     myCubeAxes->VisibilityOff();
567     ::ResetCamera(GetDevice());
568   }else{
569     myTrihedron->SetVisibility(VTKViewer_Trihedron::eOnlyLineOn);
570     myCubeAxes->SetVisibility(2);
571     ::ResetCamera(GetDevice(),true);
572   }
573
574   if(aTrihedronWasVisible)
575     myTrihedron->VisibilityOn();
576   else
577     myTrihedron->VisibilityOff();
578   
579   if(aCubeAxesWasVisible)
580     myCubeAxes->VisibilityOn();
581   else
582     myCubeAxes->VisibilityOff();
583
584   ::ResetCameraClippingRange(GetDevice());
585 }
586
587
588 //----------------------------------------------------------------------------
589 void
590 SVTK_Renderer
591 ::OnResetClippingRange()
592 {
593   return;
594   ::ResetCameraClippingRange(GetDevice());
595 }
596
597
598 //----------------------------------------------------------------------------
599 void
600 SVTK_Renderer
601 ::OnFrontView()
602 {
603   vtkCamera* aCamera = GetDevice()->GetActiveCamera();
604   aCamera->SetPosition(1,0,0);
605   aCamera->SetViewUp(0,0,1);
606   aCamera->SetFocalPoint(0,0,0);
607   this->OnFitAll();
608 }
609
610 //----------------------------------------------------------------------------
611 void
612 SVTK_Renderer
613 ::OnBackView()
614 {
615   vtkCamera* aCamera = GetDevice()->GetActiveCamera();
616   aCamera->SetPosition(-1,0,0);
617   aCamera->SetViewUp(0,0,1);
618   aCamera->SetFocalPoint(0,0,0);
619   this->OnFitAll();
620 }
621
622 //----------------------------------------------------------------------------
623 void
624 SVTK_Renderer
625 ::OnTopView()
626 {
627   vtkCamera* aCamera = GetDevice()->GetActiveCamera();
628   aCamera->SetPosition(0,0,1);
629   aCamera->SetViewUp(0,1,0);
630   aCamera->SetFocalPoint(0,0,0);
631   this->OnFitAll();
632 }
633
634 //----------------------------------------------------------------------------
635 void
636 SVTK_Renderer
637 ::OnBottomView()
638 {
639   vtkCamera* aCamera = GetDevice()->GetActiveCamera();
640   aCamera->SetPosition(0,0,-1);
641   aCamera->SetViewUp(0,1,0);
642   aCamera->SetFocalPoint(0,0,0);
643   this->OnFitAll();
644 }
645
646 //----------------------------------------------------------------------------
647 void
648 SVTK_Renderer
649 ::OnLeftView()
650 {
651   vtkCamera* aCamera = GetDevice()->GetActiveCamera(); 
652   aCamera->SetPosition(0,-1,0);
653   aCamera->SetViewUp(0,0,1);
654   aCamera->SetFocalPoint(0,0,0);
655   this->OnFitAll();
656 }
657
658 //----------------------------------------------------------------------------
659 void
660 SVTK_Renderer
661 ::OnRightView()
662 {
663   vtkCamera* aCamera = GetDevice()->GetActiveCamera();
664   aCamera->SetPosition(0,1,0);
665   aCamera->SetViewUp(0,0,1);
666   aCamera->SetFocalPoint(0,0,0);
667   this->OnFitAll();
668 }