1 // Copyright (C) 2007-2016 CEA/DEN, EDF R&D, OPEN CASCADE
3 // Copyright (C) 2003-2007 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
4 // CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
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, or (at your option) any later version.
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.
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
20 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
23 #include "OCCViewer_ViewPort3d.h"
25 #include "OCCViewer_VService.h"
26 #include "OCCViewer_ViewWindow.h"
27 #include "OCCViewer_ViewModel.h"
29 #include <SUIT_ViewManager.h>
30 #include <SUIT_ViewModel.h>
31 #include <SUIT_Session.h>
32 #include <SUIT_ResourceMgr.h>
38 #include <QPaintEvent>
39 #include <QResizeEvent>
40 #include <QApplication>
43 #include <V3d_View.hxx>
44 #include <Quantity_Ratio.hxx>
46 #include "utilities.h"
49 #include <WNT_Window.hxx>
51 //#include <Xw_Window.hxx>
54 static double rx = 0.;
55 static double ry = 0.;
58 static Standard_Boolean zRotation = Standard_False;
60 //#include <Standard_Version.hxx>
65 OCCViewer_ViewPort3d::OCCViewer_ViewPort3d( QWidget* parent, const Handle( V3d_Viewer)& viewer, V3d_TypeOfView type )
66 : OCCViewer_ViewPort( parent ),
69 myIsAdvancedZoomingEnabled( false )
71 // VSR: 01/07/2010 commented to avoid SIGSEGV at SALOME exit
74 myActiveView = new V3d_View( viewer, type );
84 OCCViewer_ViewPort3d::~OCCViewer_ViewPort3d()
93 Handle(V3d_View) aView = activeView();
99 Activates the desired 'type' of view in the viewer
100 ( view of 'type' is created if it doesn't exist ). [ public ]
102 /*void OCCViewer_ViewPort3d::setActive( V3d_TypeOfView type )
104 if ( activeView().IsNull() )
107 if ( activeView()->Type() != type )
109 if ( type == V3d_ORTHOGRAPHIC )
110 setView( myOrthoView );
111 if ( type == V3d_PERSPECTIVE )
112 setView( myPerspView );
117 Maps CasCade 'view' to this viewport. [ private ]
119 bool OCCViewer_ViewPort3d::mapView( const Handle(V3d_View)& view )
121 if ( !setWindow( view ) )
124 if ( !mapped( view ) ) {
125 view->SetWindow( myWindow );
126 if ( view != activeView() )
127 view->View()->Deactivate();
130 emit( vpMapped(this) );
138 Sets new CASCADE view on viewport. Returns the previous active view. [ public ]
140 Handle( V3d_View ) OCCViewer_ViewPort3d::setView( const Handle( V3d_View )& view )
142 /* map the new view */
143 if ( view == activeView() || !mapView( view ) )
146 /* activate the new view*/
147 Handle( V3d_View ) oldView = activeView();
148 if ( !oldView.IsNull() ) {
149 if (oldView->View()->IsDefined())
150 oldView->View()->Deactivate();
151 view->SetBackgroundColor( oldView->BackgroundColor() );
154 view->View()->Activate();
160 Returns CasCade 3D view. [ public ]
162 Handle(V3d_View) OCCViewer_ViewPort3d::getView() const
168 Returns CasCade 3D viewer [ public ]
170 Handle(V3d_Viewer) OCCViewer_ViewPort3d::getViewer() const
172 Handle(V3d_Viewer) viewer;
173 if ( !activeView().IsNull() )
174 viewer = activeView()->Viewer();
179 Syncronizes visual state of this viewport with 'ref'
180 ( scale, projection, eye etc ) Returns 'true' if copied OK,
181 'false' otherwise. [ virtual public ]
183 bool OCCViewer_ViewPort3d::syncronize( const OCCViewer_ViewPort3d* ref )
185 OCCViewer_ViewPort3d* ref3d = (OCCViewer_ViewPort3d*)ref;
186 Handle(V3d_View) refView = ref3d->getView();
187 Handle(V3d_View) tgtView = getView();
189 /* Syncronize view types */
190 /* if ( tgtView->Type() != refView->Type() )
192 setActive( refView->Type() );
196 /* The following params are copied:
197 - view type( ortho/persp )
198 - position of view point
199 - orientation of high point
200 - position of the eye
207 /* we'll update after setting all params */
208 tgtView->SetImmediateUpdate( Standard_False );
211 if ( refView->Type() == V3d_PERSPECTIVE )
212 tgtView->SetFocale( refView->Focale() );
215 Standard_Real x, y, z;
216 refView->At( x, y, z ); tgtView->SetAt( x, y, z );
217 refView->Up( x, y, z ); tgtView->SetUp( x, y, z );
218 refView->Eye( x, y, z ); tgtView->SetEye( x, y, z );
219 refView->Proj( x, y, z ); tgtView->SetProj( x, y, z );
220 tgtView->SetScale( refView->Scale() );
221 tgtView->SetTwist( refView->Twist() );
225 tgtView->SetImmediateUpdate( Standard_True );
232 Get axial scale to the view
234 void OCCViewer_ViewPort3d::getAxialScale( double& xScale, double& yScale, double& zScale )
236 xScale = yScale = zScale = 1.;
238 if ( !activeView().IsNull() )
239 activeView()->AxialScale( xScale, yScale, zScale );
243 Returns the background color [ virtual public ] [ obsolete ]
245 QColor OCCViewer_ViewPort3d::backgroundColor() const
247 return background().color();
251 Sets the background color [ virtual public ] [ obsolete ]
253 void OCCViewer_ViewPort3d::setBackgroundColor( const QColor& color )
255 Qtx::BackgroundData bg = background();
256 bg.setColor( color );
261 Returns the background data
263 Qtx::BackgroundData OCCViewer_ViewPort3d::background() const
269 Sets the background data
271 void OCCViewer_ViewPort3d::setBackground( const Qtx::BackgroundData& bgData )
273 if ( bgData.isValid() ) {
274 myBackground = bgData;
276 emit vpChangeBackground( myBackground );
280 void OCCViewer_ViewPort3d::updateBackground()
282 if ( activeView().IsNull() ) return;
283 if ( !myBackground.isValid() ) return;
285 switch ( myBackground.mode() ) {
286 case Qtx::ColorBackground:
288 QColor c = myBackground.color();
290 // Unset texture should be done here
292 Quantity_Color qCol( c.red()/255., c.green()/255., c.blue()/255., Quantity_TOC_RGB );
293 activeView()->SetBgGradientStyle( Aspect_GFM_NONE ); // cancel gradient background
294 activeView()->SetBgImageStyle( Aspect_FM_NONE ); // cancel texture background
295 // then change background color
296 activeView()->SetBackgroundColor( qCol );
298 activeView()->Update();
302 case Qtx::SimpleGradientBackground:
305 int type = myBackground.gradient( c1, c2 );
306 if ( c1.isValid() && type >= OCCViewer_Viewer::HorizontalGradient && type <= OCCViewer_Viewer::LastGradient ) {
307 // Unset texture should be done here
309 // Get colors and set-up gradiented background
310 if ( !c2.isValid() ) c2 = c1;
311 Quantity_Color qCol1( c1.red()/255., c1.green()/255., c1.blue()/255., Quantity_TOC_RGB );
312 Quantity_Color qCol2( c2.red()/255., c2.green()/255., c2.blue()/255., Quantity_TOC_RGB );
313 activeView()->SetBgImageStyle( Aspect_FM_NONE ); // cancel texture background
315 case OCCViewer_Viewer::HorizontalGradient:
316 activeView()->SetBgGradientColors( qCol1, qCol2, Aspect_GFM_HOR, Standard_True );
318 case OCCViewer_Viewer::VerticalGradient:
319 activeView()->SetBgGradientColors( qCol1, qCol2, Aspect_GFM_VER, Standard_True );
321 case OCCViewer_Viewer::Diagonal1Gradient:
322 activeView()->SetBgGradientColors( qCol1, qCol2, Aspect_GFM_DIAG1, Standard_True );
324 case OCCViewer_Viewer::Diagonal2Gradient:
325 activeView()->SetBgGradientColors( qCol1, qCol2, Aspect_GFM_DIAG2, Standard_True );
327 case OCCViewer_Viewer::Corner1Gradient:
328 activeView()->SetBgGradientColors( qCol1, qCol2, Aspect_GFM_CORNER1, Standard_True );
330 case OCCViewer_Viewer::Corner2Gradient:
331 activeView()->SetBgGradientColors( qCol1, qCol2, Aspect_GFM_CORNER2, Standard_True );
333 case OCCViewer_Viewer::Corner3Gradient:
334 activeView()->SetBgGradientColors( qCol1, qCol2, Aspect_GFM_CORNER3, Standard_True );
336 case OCCViewer_Viewer::Corner4Gradient:
337 activeView()->SetBgGradientColors( qCol1, qCol2, Aspect_GFM_CORNER4, Standard_True );
345 case Qtx::CustomGradientBackground:
347 // NOT IMPLEMENTED YET
353 if ( myBackground.isTextureShown() ) {
355 int textureMode = myBackground.texture( fileName );
356 QFileInfo fi( fileName );
357 if ( !fileName.isEmpty() && fi.exists() ) {
358 // set texture image: file name and fill mode
359 switch ( textureMode ) {
360 case Qtx::CenterTexture:
361 activeView()->SetBackgroundImage( fi.absoluteFilePath().toLatin1().constData(), Aspect_FM_CENTERED );
363 case Qtx::TileTexture:
364 activeView()->SetBackgroundImage( fi.absoluteFilePath().toLatin1().constData(), Aspect_FM_TILED );
366 case Qtx::StretchTexture:
367 activeView()->SetBackgroundImage( fi.absoluteFilePath().toLatin1().constData(), Aspect_FM_STRETCH );
372 activeView()->Update();
378 Updates the active viewport. [ virtual public ]
380 void OCCViewer_ViewPort3d::onUpdate()
382 if ( !activeView().IsNull() )
383 activeView()->Update();
387 Called at 'window fit' transformation. [ virtual protected ]
389 void OCCViewer_ViewPort3d::fitRect( const QRect& rect )
391 if ( !activeView().IsNull() ) {
392 activeView()->WindowFit( rect.left(), rect.top(), rect.right(), rect.bottom() );
393 emit vpTransformed( this );
398 Inits 'zoom' transformation. [ protected ]
400 void OCCViewer_ViewPort3d::startZoomAtPoint( int x, int y )
402 if ( !activeView().IsNull() && isAdvancedZoomingEnabled() )
403 activeView()->StartZoomAtPoint( x, y );
407 Called at 'zoom' transformation. [ virtual protected ]
409 void OCCViewer_ViewPort3d::zoom( int x0, int y0, int x, int y )
411 if ( !activeView().IsNull() ) {
412 // as OCCT respects a sign of only dx,
413 // but we want both signes to be taken into account
414 //activeView()->Zoom( x0, y0, x, y );
415 if ( isAdvancedZoomingEnabled() )
416 activeView()->ZoomAtPoint( x0, y0, x, y );
418 activeView()->Zoom( x0 + y0, 0, x + y, 0 );
419 emit vpTransformed( this );
424 Centers the viewport. [ virtual protected ]
426 void OCCViewer_ViewPort3d::setCenter( int x, int y )
428 if ( !activeView().IsNull() ) {
429 activeView()->Place( x, y, myScale );
430 emit vpTransformed( this );
435 Called at 'pan' transformation. [ virtual protected ]
437 void OCCViewer_ViewPort3d::pan( int dx, int dy )
439 if ( !activeView().IsNull() ) {
440 activeView()->Pan( dx, dy, 1.0 );
441 emit vpTransformed( this );
446 Inits 'rotation' transformation. [ protected ]
448 void OCCViewer_ViewPort3d::startRotation( int x, int y,
449 int theRotationPointType,
450 const gp_Pnt& theSelectedPoint )
452 if ( !activeView().IsNull() ) {
454 //double gx = activeView()->gx;
455 //activeView()->Gravity(gx,gy,gz);
457 switch ( theRotationPointType ) {
458 case OCCViewer_ViewWindow::BBCENTER:
459 activeView()->StartRotation( x, y, 0.45 );
461 case OCCViewer_ViewWindow::SELECTED:
465 activeView()->Size(X,Y);
466 rx = Standard_Real(activeView()->Convert(X));
467 ry = Standard_Real(activeView()->Convert(Y));
469 activeView()->Rotate( 0., 0., 0.,
470 theSelectedPoint.X(),theSelectedPoint.Y(), theSelectedPoint.Z(),
473 Quantity_Ratio zRotationThreshold;
474 zRotation = Standard_False;
475 zRotationThreshold = 0.45;
476 if( zRotationThreshold > 0. ) {
477 Standard_Real dx = Abs(sx - rx/2.);
478 Standard_Real dy = Abs(sy - ry/2.);
479 Standard_Real dd = zRotationThreshold * (rx + ry)/2.;
480 if( dx > dd || dy > dd ) zRotation = Standard_True;
486 // VSR: 10.06.2015: next line commented out - causes ugly blinking on starting rotation with Perspective projection mode
487 //activeView()->DepthFitAll();
492 Rotates the viewport. [ protected ]
494 void OCCViewer_ViewPort3d::rotate( int x, int y,
495 int theRotationPointType,
496 const gp_Pnt& theSelectedPoint )
498 if ( !activeView().IsNull() ) {
499 switch ( theRotationPointType ) {
500 case OCCViewer_ViewWindow::BBCENTER:
501 activeView()->Rotation( x, y );
503 case OCCViewer_ViewWindow::SELECTED:
506 dz = atan2(Standard_Real(x)-rx/2., ry/2.-Standard_Real(y)) -
507 atan2(sx-rx/2.,ry/2.-sy);
511 dx = (Standard_Real(x) - sx) * M_PI/rx;
512 dy = (sy - Standard_Real(y)) * M_PI/ry;
516 activeView()->Rotate( dx, dy, dz,
517 theSelectedPoint.X(),theSelectedPoint.Y(), theSelectedPoint.Z(),
523 emit vpTransformed( this );
525 // setZSize( getZSize() );
529 Resets the viewport after 'rotation'. [ protected ]
531 void OCCViewer_ViewPort3d::endRotation()
533 if ( !activeView().IsNull() ) {
534 activeView()->Update();
535 emit vpTransformed( this );
540 Repaints the viewport. [ virtual protected ]
542 void OCCViewer_ViewPort3d::paintEvent( QPaintEvent* e )
545 /* X11 : map before show doesn't work */
546 if ( !mapped( activeView() ) )
547 mapView( activeView() );
549 if ( !myWindow.IsNull() ) {
550 #if QT_VERSION < QT_VERSION_CHECK(5, 0, 0)
551 QApplication::syncX();
553 if ( !myPaintersRedrawing ) {
554 activeView()->Redraw();
557 OCCViewer_ViewPort::paintEvent( e );
562 Resizes the viewport. [ virtual protected ]
564 void OCCViewer_ViewPort3d::resizeEvent( QResizeEvent* e )
566 #if defined WIN32 || QT_VERSION >= QT_VERSION_CHECK(5, 0, 0)
567 /* Win32 : map before first show to avoid flicker */
568 if ( !mapped( activeView() ) )
569 mapView( activeView() );
571 #if QT_VERSION < QT_VERSION_CHECK(5, 0, 0)
572 QApplication::syncX();
574 QTimer::singleShot( 0, this, SLOT( repaintViewAfterMove() ) );
575 emit vpResizeEvent( e );
581 void OCCViewer_ViewPort3d::repaintViewAfterMove( )
583 if ( !activeView().IsNull() ){
584 activeView()->MustBeResized();
589 Fits all objects in view. [ virtual protected ]
591 void OCCViewer_ViewPort3d::fitAll( bool keepScale, bool withZ, bool upd )
593 if ( activeView().IsNull() )
597 myScale = activeView()->Scale();
599 Standard_Real margin = 0.01;
601 activeView()->FitAll( margin, upd );
603 emit vpTransformed( this );
607 Resets the view. [ virtual protected ]
609 void OCCViewer_ViewPort3d::reset()
611 // double zsize = getZSize();
612 if ( !activeView().IsNull() ) {
613 activeView()->Reset();
614 emit vpTransformed( this );
615 // setZSize( zsize );
620 Rotate the view in the view plane (orthogonal to the view vector)
622 void OCCViewer_ViewPort3d::rotateXY( double degrees )
624 if ( activeView().IsNull() )
627 int x = width()/2, y = height()/2;
629 activeView()->Convert( x, y, X, Y, Z );
630 activeView()->Rotate( 0, 0, degrees * M_PI / 180., X, Y, Z );
631 emit vpTransformed( this );
635 Set axial scale to the view
637 void OCCViewer_ViewPort3d::setAxialScale( double xScale, double yScale, double zScale )
639 if ( activeView().IsNull() )
642 activeView()->SetAxialScale( xScale, yScale, zScale );
643 emit vpTransformed( this );
647 Passed the handle of native window of the component to CASCADE view. [ private ]
649 bool OCCViewer_ViewPort3d::setWindow( const Handle(V3d_View)& view )
651 if ( !myWindow.IsNull() )
657 attachWindow( view, OCCViewer_VService::CreateWindow( view, winId() ) );
659 myWindow = view->Window();
660 return !myWindow.IsNull();
663 void OCCViewer_ViewPort3d::attachWindow( const Handle(V3d_View)& view,
664 const Handle(Aspect_Window)& window)
666 if (!view.IsNull()) {
667 view->SetWindow( window );
673 Returns the current active view. [ private ]
675 Handle(V3d_View) OCCViewer_ViewPort3d::activeView() const
681 Returns the current inactive view [ private ]
683 /*Handle(V3d_View) OCCViewer_ViewPort3d::inactiveView() const
685 return ( activeView() == myOrthoView ? myPerspView : myOrthoView );
689 Returns 'true' if the given view is mapped to window. [ private ]
691 bool OCCViewer_ViewPort3d::mapped( const Handle(V3d_View)& view ) const
693 return ( !view.IsNull() && view->View()->IsDefined() );
697 Performs synchronization of view parameters with the specified view.
698 Returns \c true if synchronization is done successfully or \c false otherwise.
699 Default implementation does nothing (return \c false)
701 bool OCCViewer_ViewPort3d::synchronize( OCCViewer_ViewPort* view )
704 OCCViewer_ViewPort3d* vp3d = qobject_cast<OCCViewer_ViewPort3d*>( view );
706 bool blocked = blockSignals( false );
707 Handle(V3d_View) aView3d = getView();
708 Handle(V3d_View) aRefView3d = vp3d->getView();
709 aView3d->SetImmediateUpdate( Standard_False );
710 aView3d->Camera()->Copy( aRefView3d->Camera() );
711 aView3d->SetImmediateUpdate( Standard_True );
713 blockSignals( blocked );
720 * Show/Hide static triedron
722 void OCCViewer_ViewPort3d::showStaticTrihedron( bool on )
724 Handle(V3d_View) aView = activeView();
725 if ( !aView ) return;
728 aView->ZBufferTriedronSetup();
729 aView->TriedronDisplay( Aspect_TOTP_LEFT_LOWER, Quantity_NOC_WHITE, 0.05, V3d_ZBUFFER );
731 aView->TriedronErase();
737 * Create default cursor with a specific shape
739 void OCCViewer_ViewPort3d::setDefaultCursor( Qt::CursorShape theCursorShape )
742 myCursor = new QCursor();
744 myCursor->setShape( theCursorShape );
748 * Get default cursor with a specific shape
750 QCursor* OCCViewer_ViewPort3d::getDefaultCursor() const
756 * Set default parameters from preferences
758 void OCCViewer_ViewPort3d::setDefaultParams()
760 setBackground( Qtx::BackgroundData( Qt::black ) ); // set default background
762 // get ray tracing parameters from preferences
763 int aDepth = SUIT_Session::session()->resourceMgr()->integerValue( "OCCViewer", "rt_depth", 3 );
764 bool aReflection = SUIT_Session::session()->resourceMgr()->booleanValue( "OCCViewer", "rt_reflection", true );
765 bool anAntialiasing = SUIT_Session::session()->resourceMgr()->booleanValue( "OCCViewer", "rt_antialiasing", false );
766 bool aShadow = SUIT_Session::session()->resourceMgr()->booleanValue( "OCCViewer", "rt_shadow", true );
767 bool aTransparentShadow = SUIT_Session::session()->resourceMgr()->booleanValue( "OCCViewer", "rt_trans_shadow", true );
769 Graphic3d_RenderingParams& aParams = myActiveView->ChangeRenderingParams();
770 aParams.RaytracingDepth = aDepth;
771 aParams.IsReflectionEnabled = aReflection;
772 aParams.IsAntialiasingEnabled = anAntialiasing;
773 aParams.IsShadowEnabled = aShadow;
774 aParams.IsTransparentShadowEnabled = aTransparentShadow;
775 myActiveView->Redraw();