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().toUtf8().constData(), Aspect_FM_CENTERED );
363 case Qtx::TileTexture:
364 activeView()->SetBackgroundImage( fi.absoluteFilePath().toUtf8().constData(), Aspect_FM_TILED );
366 case Qtx::StretchTexture:
367 activeView()->SetBackgroundImage( fi.absoluteFilePath().toUtf8().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() ) );
580 void OCCViewer_ViewPort3d::repaintViewAfterMove( )
582 if ( !activeView().IsNull() ){
583 activeView()->MustBeResized();
588 Fits all objects in view. [ virtual protected ]
590 void OCCViewer_ViewPort3d::fitAll( bool keepScale, bool withZ, bool upd )
592 if ( activeView().IsNull() )
596 myScale = activeView()->Scale();
598 Standard_Real margin = 0.01;
600 activeView()->FitAll( margin, upd );
602 emit vpTransformed( this );
606 Resets the view. [ virtual protected ]
608 void OCCViewer_ViewPort3d::reset()
610 // double zsize = getZSize();
611 if ( !activeView().IsNull() ) {
612 activeView()->Reset();
613 emit vpTransformed( this );
614 // setZSize( zsize );
619 Rotate the view in the view plane (orthogonal to the view vector)
621 void OCCViewer_ViewPort3d::rotateXY( double degrees )
623 if ( activeView().IsNull() )
626 int x = width()/2, y = height()/2;
628 activeView()->Convert( x, y, X, Y, Z );
629 activeView()->Rotate( 0, 0, degrees * M_PI / 180., X, Y, Z );
630 emit vpTransformed( this );
634 Set axial scale to the view
636 void OCCViewer_ViewPort3d::setAxialScale( double xScale, double yScale, double zScale )
638 if ( activeView().IsNull() )
641 activeView()->SetAxialScale( xScale, yScale, zScale );
642 emit vpTransformed( this );
646 Passed the handle of native window of the component to CASCADE view. [ private ]
648 bool OCCViewer_ViewPort3d::setWindow( const Handle(V3d_View)& view )
650 if ( !myWindow.IsNull() )
656 attachWindow( view, OCCViewer_VService::CreateWindow( view, winId() ) );
658 myWindow = view->Window();
659 return !myWindow.IsNull();
662 void OCCViewer_ViewPort3d::attachWindow( const Handle(V3d_View)& view,
663 const Handle(Aspect_Window)& window)
665 if (!view.IsNull()) {
666 view->SetWindow( window );
672 Returns the current active view. [ private ]
674 Handle(V3d_View) OCCViewer_ViewPort3d::activeView() const
680 Returns the current inactive view [ private ]
682 /*Handle(V3d_View) OCCViewer_ViewPort3d::inactiveView() const
684 return ( activeView() == myOrthoView ? myPerspView : myOrthoView );
688 Returns 'true' if the given view is mapped to window. [ private ]
690 bool OCCViewer_ViewPort3d::mapped( const Handle(V3d_View)& view ) const
692 return ( !view.IsNull() && view->View()->IsDefined() );
696 Performs synchronization of view parameters with the specified view.
697 Returns \c true if synchronization is done successfully or \c false otherwise.
698 Default implementation does nothing (return \c false)
700 bool OCCViewer_ViewPort3d::synchronize( OCCViewer_ViewPort* view )
703 OCCViewer_ViewPort3d* vp3d = qobject_cast<OCCViewer_ViewPort3d*>( view );
705 bool blocked = blockSignals( false );
706 Handle(V3d_View) aView3d = getView();
707 Handle(V3d_View) aRefView3d = vp3d->getView();
708 aView3d->SetImmediateUpdate( Standard_False );
709 aView3d->Camera()->Copy( aRefView3d->Camera() );
710 aView3d->SetImmediateUpdate( Standard_True );
712 blockSignals( blocked );
719 * Show/Hide static triedron
721 void OCCViewer_ViewPort3d::showStaticTrihedron( bool on )
723 Handle(V3d_View) aView = activeView();
724 if ( !aView ) return;
727 aView->ZBufferTriedronSetup();
728 aView->TriedronDisplay( Aspect_TOTP_LEFT_LOWER, Quantity_NOC_WHITE, 0.05, V3d_ZBUFFER );
730 aView->TriedronErase();
736 * Create default cursor with a specific shape
738 void OCCViewer_ViewPort3d::setDefaultCursor( Qt::CursorShape theCursorShape )
741 myCursor = new QCursor();
743 myCursor->setShape( theCursorShape );
747 * Get default cursor with a specific shape
749 QCursor* OCCViewer_ViewPort3d::getDefaultCursor() const
755 * Set default parameters from preferences
757 void OCCViewer_ViewPort3d::setDefaultParams()
759 setBackground( Qtx::BackgroundData( Qt::black ) ); // set default background
761 // get ray tracing parameters from preferences
762 int aDepth = SUIT_Session::session()->resourceMgr()->integerValue( "OCCViewer", "rt_depth", 3 );
763 bool aReflection = SUIT_Session::session()->resourceMgr()->booleanValue( "OCCViewer", "rt_reflection", true );
764 bool anAntialiasing = SUIT_Session::session()->resourceMgr()->booleanValue( "OCCViewer", "rt_antialiasing", false );
765 bool aShadow = SUIT_Session::session()->resourceMgr()->booleanValue( "OCCViewer", "rt_shadow", true );
766 bool aTransparentShadow = SUIT_Session::session()->resourceMgr()->booleanValue( "OCCViewer", "rt_trans_shadow", true );
768 Graphic3d_RenderingParams& aParams = myActiveView->ChangeRenderingParams();
769 aParams.RaytracingDepth = aDepth;
770 aParams.IsReflectionEnabled = aReflection;
771 aParams.IsAntialiasingEnabled = anAntialiasing;
772 aParams.IsShadowEnabled = aShadow;
773 aParams.IsTransparentShadowEnabled = aTransparentShadow;
774 myActiveView->Redraw();