Salome HOME
7fc204ddd3a1e489df889386d10da86c93c4ac02
[modules/gui.git] / src / OCCViewer / OCCViewer_ViewPort3d.cxx
1 //  Copyright (C) 2007-2008  CEA/DEN, EDF R&D, OPEN CASCADE
2 //
3 //  Copyright (C) 2003-2007  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.salome-platform.org/ or email : webmaster.salome@opencascade.com
21 //
22 #include "OCCViewer_ViewPort3d.h"
23
24 #include "OCCViewer_VService.h"
25 #include "OCCViewer_ViewWindow.h"
26 #include "OCCViewer_ViewModel.h"
27
28 #include <SUIT_ViewManager.h>
29
30 #include <QColor>
31 #include <QRect>
32 #include <QPaintEvent>
33 #include <QResizeEvent>
34 #include <QApplication>
35
36 #include <Visual3d_View.hxx>
37 #include <V3d_Viewer.hxx>
38 #include <V3d_PerspectiveView.hxx>
39 #include <V3d_OrthographicView.hxx>
40
41 #if defined WNT
42 #include <WNT_Window.hxx>
43 #else
44 #include <Xw_Window.hxx>
45 #endif
46
47 static double rx = 0.;
48 static double ry = 0.;
49 static int sx = 0;
50 static int sy = 0;
51 static Standard_Boolean zRotation = Standard_False;
52
53 /*!
54     Constructor
55 */
56 OCCViewer_ViewPort3d::OCCViewer_ViewPort3d( QWidget* parent, const Handle( V3d_Viewer)& viewer, V3d_TypeOfView  type )
57 : OCCViewer_ViewPort( parent ),
58 myScale( 1.0 ),
59 myDegenerated( true ),
60 myAnimate( false ),
61 myBusy( true )
62 {
63   selectVisualId();
64
65   if ( type == V3d_ORTHOGRAPHIC ) {
66     myOrthoView = new V3d_OrthographicView( viewer );
67     myActiveView = myOrthoView;
68     myPerspView = 0;
69   } else {
70     myPerspView = new V3d_PerspectiveView( viewer );
71     myActiveView = myPerspView;
72   }
73   if ( myDegenerated )
74     activeView()->SetDegenerateModeOn();
75 }
76
77 /*!
78     Destructor
79 */
80 OCCViewer_ViewPort3d::~OCCViewer_ViewPort3d()
81 {
82   Handle(V3d_View) aView = activeView();
83   if (!aView.IsNull())
84     aView->Remove();
85 }
86
87 /*!
88     Activates the desired 'type' of view in the viewer
89     ( view of 'type' is created if it doesn't exist ). [ public ]
90 */
91 /*void OCCViewer_ViewPort3d::setActive( V3d_TypeOfView type )
92 {
93     if ( activeView().IsNull() )
94         return;
95
96     if ( activeView()->Type() != type )
97     {
98         if ( type == V3d_ORTHOGRAPHIC )
99             setView( myOrthoView );
100         if ( type == V3d_PERSPECTIVE )
101             setView( myPerspView );
102     }
103 }*/
104
105 /*!
106     Maps CasCade 'view' to this viewport. [ private ]
107 */
108 bool OCCViewer_ViewPort3d::mapView( const Handle(V3d_View)& view )
109 {
110   if ( !setWindow( view ) )
111     return false;
112
113   if ( !mapped( view ) )
114         {
115                 view->SetWindow( myWindow );
116                 if ( view != activeView() )
117             view->View()->Deactivate();
118         }
119
120   /* create static trihedron (16551: EDF PAL 501) */
121   OCCViewer_ViewWindow* aVW = dynamic_cast<OCCViewer_ViewWindow*>( parentWidget() );
122   if ( aVW ){
123     OCCViewer_Viewer* aViewModel = dynamic_cast<OCCViewer_Viewer*>( aVW->getViewManager()->getViewModel() );
124     if ( aViewModel && aViewModel->isStaticTrihedronDisplayed() ){
125       view->ZBufferTriedronSetup();
126       view->TriedronDisplay( Aspect_TOTP_LEFT_LOWER, Quantity_NOC_WHITE, 0.05, V3d_ZBUFFER );
127     }
128   }
129   return true;
130 }
131
132 /*!
133     Sets new CASCADE view on viewport. Returns the previous active view. [ public ]
134 */
135 Handle( V3d_View ) OCCViewer_ViewPort3d::setView( const Handle( V3d_View )& view )
136 {
137   /* map the new view */
138   if ( view == activeView() || !mapView( view ) )
139     return activeView();
140
141     /* activate the new view*/
142   Handle( V3d_View ) oldView = activeView();
143         if ( !oldView.IsNull() )
144   {
145                 oldView->View()->Deactivate();
146                 view->SetBackgroundColor( oldView->BackgroundColor() );
147         }
148   if ( myDegenerated )
149     view->SetDegenerateModeOn();
150   else
151     view->SetDegenerateModeOff();
152
153   view->View()->Activate();
154   activeView() = view;
155         return oldView;
156 }
157
158 /*!
159     Returns CasCade 3D view. [ public ]
160 */
161 Handle(V3d_View) OCCViewer_ViewPort3d::getView() const
162 {
163         return activeView();
164 }
165
166 /*!
167     Returns CasCade 3D viewer [ public ]
168 */
169 Handle(V3d_Viewer) OCCViewer_ViewPort3d::getViewer() const
170 {
171         Handle(V3d_Viewer) viewer;
172         if ( !activeView().IsNull() )
173     viewer = activeView()->Viewer();
174         return viewer;
175 }
176
177 /*!
178     Syncronizes visual state of this viewport with 'ref'
179     ( scale, projection, eye etc ) Returns 'true' if copied OK,
180     'false' otherwise. [ virtual public ]
181 */
182 bool OCCViewer_ViewPort3d::syncronize( const OCCViewer_ViewPort3d* ref )
183 {
184   OCCViewer_ViewPort3d* ref3d = (OCCViewer_ViewPort3d*)ref;
185   Handle(V3d_View) refView = ref3d->getView();
186   Handle(V3d_View) tgtView = getView();
187
188   /* Syncronize view types */
189 /*    if ( tgtView->Type() != refView->Type() )
190   {
191       setActive( refView->Type() );
192       tgtView = getView();
193   }*/
194
195   /*  The following params are copied:
196       - view type( ortho/persp )
197       - position of view point
198       - orientation of high point
199       - position of the eye
200       - projection vector
201       - view center ( 2D )
202       - view twist
203       - view scale
204   */
205
206   /* we'll update after setting all params */
207   tgtView->SetImmediateUpdate( Standard_False );
208
209   /* perspective */
210   if ( refView->Type() == V3d_PERSPECTIVE )
211       tgtView->SetFocale( refView->Focale() );
212
213   /* copy params */
214   Standard_Real x, y, z;
215   refView->At( x, y, z ); tgtView->SetAt( x, y, z );
216   refView->Up( x, y, z ); tgtView->SetUp( x, y, z );
217   refView->Eye( x, y, z ); tgtView->SetEye( x, y, z );
218   refView->Proj( x, y, z ); tgtView->SetProj( x, y, z );
219   refView->Center( x, y ); tgtView->SetCenter( x, y );
220   tgtView->SetScale( refView->Scale() );
221   tgtView->SetTwist( refView->Twist() );
222
223   /* update */
224   tgtView->Update();
225   tgtView->SetImmediateUpdate( Standard_True );
226   return true;
227 }
228
229 /*!
230     Returns Z-size of this view. [ public ]
231 */
232 double OCCViewer_ViewPort3d::getZSize() const
233 {
234   if ( !activeView().IsNull() )
235     return activeView()->ZSize();
236   return 0;
237 }
238
239 /*!
240     Sets Z-size of this view ( for both orthographic and perspective ). [ public ]
241 */
242 void OCCViewer_ViewPort3d::setZSize( double zsize )
243 {
244   myActiveView->SetZSize( zsize );
245 /*    if ( !myOrthoView.IsNull() )
246         myOrthoView->SetZSize( zsize );
247     if ( !myPerspView.IsNull() )
248         myPerspView->SetZSize( zsize );*/
249 }
250
251 /*!
252     Returns the background color [ virtual public ]
253 */
254 QColor OCCViewer_ViewPort3d::backgroundColor() const
255 {
256         if ( !activeView().IsNull() )
257         {
258                 Standard_Real aRed, aGreen, aBlue;
259                 activeView()->BackgroundColor( Quantity_TOC_RGB, aRed, aGreen, aBlue );
260                 int red = (int) (aRed * 255);
261                 int green = (int) (aGreen * 255);
262                 int blue = (int) (aBlue * 255);
263                 return QColor( red, green, blue );
264         }
265         return OCCViewer_ViewPort::backgroundColor();
266 }
267
268 /*!
269     Sets the background color [ virtual public ]
270 */
271 void OCCViewer_ViewPort3d::setBackgroundColor( const QColor& color )
272 {
273         if ( !activeView().IsNull() )
274         {
275           activeView()->SetBackgroundColor( Quantity_TOC_RGB, color.red()/255.,
276                                             color.green()/255., color.blue()/255.);
277           activeView()->Update();
278           emit vpChangeBGColor( color );
279         }
280 }
281
282 /*!
283   Set animation mode
284   \param theDegenerated - degenerated mode
285 */
286 void OCCViewer_ViewPort3d::setAnimationMode(bool theDegenerated)
287 {
288         if ( !activeView().IsNull() )
289         {
290     myAnimate = theDegenerated;
291     activeView()->SetAnimationMode(true, theDegenerated);
292   }
293 }
294
295 /*!
296     Updates the active viewport. [ virtual public ]
297 */
298 void OCCViewer_ViewPort3d::onUpdate()
299 {
300   if ( !activeView().IsNull() )
301     activeView()->Update();
302 }
303
304 /*!
305     Called at 'window fit' transformation. [ virtual protected ]
306 */
307 void OCCViewer_ViewPort3d::fitRect( const QRect& rect )
308 {
309         if ( !activeView().IsNull() )
310           activeView()->WindowFit( rect.left(), rect.top(), rect.right(), rect.bottom() );
311 }
312
313 /*!
314     Called at 'zoom' transformation. [ virtual protected ]
315 */
316 void OCCViewer_ViewPort3d::zoom( int x0, int y0, int x, int y )
317 {
318   if ( !activeView().IsNull() ) {
319     // as OCCT respects a sign of only dx,
320     // but we want both signes to be taken into account
321     //activeView()->Zoom( x0, y0, x, y );
322     activeView()->Zoom( x0 + y0, 0, x + y, 0 );
323   }
324 }
325
326 /*!
327     Centers the viewport. [ virtual protected ]
328 */
329 void OCCViewer_ViewPort3d::setCenter( int x, int y )
330 {
331         if ( !activeView().IsNull() )
332             activeView()->Place( x, y, myScale );
333 }
334
335 /*!
336     Called at 'pan' transformation. [ virtual protected ]
337 */
338 void OCCViewer_ViewPort3d::pan( int dx, int dy )
339 {
340         if ( !activeView().IsNull() )
341         activeView()->Pan( dx, dy, 1.0 );
342 }
343
344 /*!
345     Inits 'rotation' transformation. [ protected ]
346 */
347 void OCCViewer_ViewPort3d::startRotation( int x, int y, 
348                                           int theRotationPointType,
349                                           const gp_Pnt& theSelectedPoint )
350 {
351   if ( !activeView().IsNull() )
352     {
353       myDegenerated = activeView()->DegenerateModeIsOn();
354       activeView()->SetDegenerateModeOn();
355       if (myAnimate) activeView()->SetAnimationModeOn();
356
357       //double gx, gy, gz;
358       //double gx = activeView()->gx;
359       //activeView()->Gravity(gx,gy,gz);
360
361       switch ( theRotationPointType ) {
362       case OCCViewer_ViewWindow::GRAVITY:
363         activeView()->StartRotation( x, y, 0.45 );
364         break;
365       case OCCViewer_ViewWindow::SELECTED:
366         sx = x; sy = y;
367         
368         double X,Y;
369         activeView()->Size(X,Y);
370         rx = Standard_Real(activeView()->Convert(X)); 
371         ry = Standard_Real(activeView()->Convert(Y)); 
372         
373         activeView()->Rotate( 0., 0., 0., 
374                               theSelectedPoint.X(),theSelectedPoint.Y(), theSelectedPoint.Z(), 
375                               Standard_True );
376         
377         Quantity_Ratio zRotationThreshold;
378         zRotation = Standard_False;
379         zRotationThreshold = 0.45;
380         if( zRotationThreshold > 0. ) {
381           Standard_Real dx = Abs(sx - rx/2.);
382           Standard_Real dy = Abs(sy - ry/2.);
383           Standard_Real dd = zRotationThreshold * (rx + ry)/2.;
384           if( dx > dd || dy > dd ) zRotation = Standard_True;
385         }
386         break;
387       default:
388         break;
389       }
390     }
391 }
392
393 /*!
394     Rotates the viewport. [ protected ]
395 */
396 void OCCViewer_ViewPort3d::rotate( int x, int y, 
397                                    int theRotationPointType,
398                                    const gp_Pnt& theSelectedPoint )
399 {
400   if ( !activeView().IsNull() ) {
401     switch ( theRotationPointType ) {
402     case OCCViewer_ViewWindow::GRAVITY:
403       activeView()->Rotation( x, y );
404       break;
405     case OCCViewer_ViewWindow::SELECTED:
406       double dx, dy, dz;
407       if( zRotation ) {
408         dz = atan2(Standard_Real(x)-rx/2., ry/2.-Standard_Real(y)) - 
409           atan2(sx-rx/2.,ry/2.-sy);
410         dx = dy = 0.;
411       }
412       else {
413         dx = (Standard_Real(x) - sx) * Standard_PI/rx;
414         dy = (sy - Standard_Real(y)) * Standard_PI/ry;
415         dz = 0.;
416       }
417       
418       activeView()->Rotate( dx, dy, dz, 
419                             theSelectedPoint.X(),theSelectedPoint.Y(), theSelectedPoint.Z(),
420                             Standard_False );
421       break;
422     default:
423       break;
424     }
425   }
426   //  setZSize( getZSize() );
427 }
428
429 /*!
430     Resets the viewport after 'rotation'. [ protected ]
431 */
432 void OCCViewer_ViewPort3d::endRotation()
433 {
434   if ( !activeView().IsNull() )
435     {
436       if (myAnimate) activeView()->SetAnimationModeOff();
437       if ( !myDegenerated )
438         activeView()->SetDegenerateModeOff();
439       activeView()->ZFitAll(1.);
440       activeView()->SetZSize(0.);
441       activeView()->Update();
442     }
443 }
444
445 /*!
446     Repaints the viewport. [ virtual protected ]
447 */
448 void OCCViewer_ViewPort3d::paintEvent( QPaintEvent* e )
449 {
450 #ifndef WNT
451         /* X11 : map before show doesn't work */
452         if ( !mapped( activeView() ) )
453         mapView( activeView() );
454 #endif
455         if ( !myWindow.IsNull() )
456         {
457                 QApplication::syncX();
458                 QRect rc = e->rect();
459                 if ( !myPaintersRedrawing )
460                     activeView()->Redraw( rc.x(), rc.y(), rc.width(), rc.height() );
461         }
462         OCCViewer_ViewPort::paintEvent( e );
463         myBusy = false;
464 }
465
466 /*!
467     Resizes the viewport. [ virtual protected ]
468 */
469 void OCCViewer_ViewPort3d::resizeEvent( QResizeEvent* e )
470 {
471 #ifdef WNT
472         /* Win32 : map before first show to avoid flicker */
473         if ( !mapped( activeView() ) )
474             mapView( activeView() );
475 #endif
476         QApplication::syncX();
477     if ( !activeView().IsNull() )
478         activeView()->MustBeResized();
479 }
480
481 /*!
482     Fits all objects in view. [ virtual protected ]
483 */
484 void OCCViewer_ViewPort3d::fitAll( bool keepScale, bool withZ, bool upd )
485 {
486   if ( activeView().IsNull() )
487     return;
488
489
490   if ( keepScale )
491     myScale = activeView()->Scale();
492
493   Standard_Real margin = 0.01;
494   activeView()->FitAll( margin, withZ, upd );
495   activeView()->SetZSize(0.);
496 }
497
498 /*!
499     Resets the view. [ virtual protected ]
500 */
501 void OCCViewer_ViewPort3d::reset()
502 {
503 //  double zsize = getZSize();
504         if ( !activeView().IsNull() )
505         activeView()->Reset();
506 //    setZSize( zsize );
507 }
508
509 /*!
510     Passed the handle of native window of the component to CASCADE view. [ private ]
511 */
512 bool OCCViewer_ViewPort3d::setWindow( const Handle(V3d_View)& view )
513 {
514         if ( !myWindow.IsNull() )
515                 return true;
516
517         if ( view.IsNull() )
518                 return false;
519
520         int hwnd = (int)winId();
521         if ( !hwnd )
522         return false;
523
524         /* set this widget as the drawing window */
525         short lo = (short)hwnd;
526         short hi = (short)( hwnd >> 16 );
527         OCCViewer_VService::SetWindow( view, (int)hi, (int)lo, Xw_WQ_SAMEQUALITY );
528         myWindow = view->Window();
529         return !myWindow.IsNull();
530 }
531
532 /*!
533         Returns the current active view. [ private ]
534 */
535 Handle(V3d_View) OCCViewer_ViewPort3d::activeView() const
536 {
537         return myActiveView;
538 }
539
540 /*!
541         Returns the current inactive view [ private ]
542 */
543 /*Handle(V3d_View) OCCViewer_ViewPort3d::inactiveView() const
544 {
545         return ( activeView() == myOrthoView ? myPerspView : myOrthoView );
546 }*/
547
548 /*!
549         Returns 'true' if the given view is mapped to window. [ private ]
550 */
551 bool OCCViewer_ViewPort3d::mapped( const Handle(V3d_View)& view ) const
552 {
553         return ( !view.IsNull() && view->View()->IsDefined() );
554 }