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 #if OCC_VERSION_MAJOR < 7
44 #include <Visual3d_View.hxx>
47 #if OCC_VERSION_LARGE > 0x06070100
48 #include <V3d_View.hxx>
50 #include <V3d_PerspectiveView.hxx>
51 #include <V3d_OrthographicView.hxx>
54 #if OCC_VERSION_LARGE > 0x07010000
55 #include <Quantity_Ratio.hxx>
58 #include "utilities.h"
61 #include <WNT_Window.hxx>
63 //#include <Xw_Window.hxx>
66 static double rx = 0.;
67 static double ry = 0.;
70 static Standard_Boolean zRotation = Standard_False;
72 //#include <Standard_Version.hxx>
77 OCCViewer_ViewPort3d::OCCViewer_ViewPort3d( QWidget* parent, const Handle( V3d_Viewer)& viewer, V3d_TypeOfView type )
78 : OCCViewer_ViewPort( parent ),
81 myIsAdvancedZoomingEnabled( false )
83 // VSR: 01/07/2010 commented to avoid SIGSEGV at SALOME exit
86 #if OCC_VERSION_LARGE > 0x06070100
87 myActiveView = new V3d_View( viewer, type );
89 if ( type == V3d_ORTHOGRAPHIC ) {
90 myOrthoView = new V3d_OrthographicView( viewer );
91 myActiveView = myOrthoView;
94 myPerspView = new V3d_PerspectiveView( viewer );
95 myActiveView = myPerspView;
107 OCCViewer_ViewPort3d::~OCCViewer_ViewPort3d()
116 Handle(V3d_View) aView = activeView();
122 Activates the desired 'type' of view in the viewer
123 ( view of 'type' is created if it doesn't exist ). [ public ]
125 /*void OCCViewer_ViewPort3d::setActive( V3d_TypeOfView type )
127 if ( activeView().IsNull() )
130 if ( activeView()->Type() != type )
132 if ( type == V3d_ORTHOGRAPHIC )
133 setView( myOrthoView );
134 if ( type == V3d_PERSPECTIVE )
135 setView( myPerspView );
140 Maps CasCade 'view' to this viewport. [ private ]
142 bool OCCViewer_ViewPort3d::mapView( const Handle(V3d_View)& view )
144 if ( !setWindow( view ) )
147 if ( !mapped( view ) ) {
148 view->SetWindow( myWindow );
149 if ( view != activeView() )
150 view->View()->Deactivate();
153 emit( vpMapped(this) );
161 Sets new CASCADE view on viewport. Returns the previous active view. [ public ]
163 Handle( V3d_View ) OCCViewer_ViewPort3d::setView( const Handle( V3d_View )& view )
165 /* map the new view */
166 if ( view == activeView() || !mapView( view ) )
169 /* activate the new view*/
170 Handle( V3d_View ) oldView = activeView();
171 if ( !oldView.IsNull() ) {
172 if (oldView->View()->IsDefined())
173 oldView->View()->Deactivate();
174 view->SetBackgroundColor( oldView->BackgroundColor() );
177 view->View()->Activate();
183 Returns CasCade 3D view. [ public ]
185 Handle(V3d_View) OCCViewer_ViewPort3d::getView() const
191 Returns CasCade 3D viewer [ public ]
193 Handle(V3d_Viewer) OCCViewer_ViewPort3d::getViewer() const
195 Handle(V3d_Viewer) viewer;
196 if ( !activeView().IsNull() )
197 viewer = activeView()->Viewer();
202 Syncronizes visual state of this viewport with 'ref'
203 ( scale, projection, eye etc ) Returns 'true' if copied OK,
204 'false' otherwise. [ virtual public ]
206 bool OCCViewer_ViewPort3d::syncronize( const OCCViewer_ViewPort3d* ref )
208 OCCViewer_ViewPort3d* ref3d = (OCCViewer_ViewPort3d*)ref;
209 Handle(V3d_View) refView = ref3d->getView();
210 Handle(V3d_View) tgtView = getView();
212 /* Syncronize view types */
213 /* if ( tgtView->Type() != refView->Type() )
215 setActive( refView->Type() );
219 /* The following params are copied:
220 - view type( ortho/persp )
221 - position of view point
222 - orientation of high point
223 - position of the eye
230 /* we'll update after setting all params */
231 tgtView->SetImmediateUpdate( Standard_False );
234 if ( refView->Type() == V3d_PERSPECTIVE )
235 tgtView->SetFocale( refView->Focale() );
238 Standard_Real x, y, z;
239 refView->At( x, y, z ); tgtView->SetAt( x, y, z );
240 refView->Up( x, y, z ); tgtView->SetUp( x, y, z );
241 refView->Eye( x, y, z ); tgtView->SetEye( x, y, z );
242 refView->Proj( x, y, z ); tgtView->SetProj( x, y, z );
243 #if OCC_VERSION_LARGE <= 0x06070100
244 refView->Center( x, y ); tgtView->SetCenter( x, y );
246 tgtView->SetScale( refView->Scale() );
247 tgtView->SetTwist( refView->Twist() );
251 tgtView->SetImmediateUpdate( Standard_True );
252 #if OCC_VERSION_LARGE <= 0x07000000
258 #if OCC_VERSION_LARGE <= 0x07000000
260 Returns Z-size of this view. [ public ]
262 double OCCViewer_ViewPort3d::getZSize() const
264 if ( !activeView().IsNull() )
265 return activeView()->ZSize();
270 Sets Z-size of this view ( for both orthographic and perspective ). [ public ]
272 void OCCViewer_ViewPort3d::setZSize( double zsize )
274 myActiveView->SetZSize( zsize );
275 /* if ( !myOrthoView.IsNull() )
276 myOrthoView->SetZSize( zsize );
277 if ( !myPerspView.IsNull() )
278 myPerspView->SetZSize( zsize );*/
283 Get axial scale to the view
285 void OCCViewer_ViewPort3d::getAxialScale( double& xScale, double& yScale, double& zScale )
287 xScale = yScale = zScale = 1.;
289 if ( !activeView().IsNull() )
290 activeView()->AxialScale( xScale, yScale, zScale );
294 Returns the background color [ virtual public ] [ obsolete ]
296 QColor OCCViewer_ViewPort3d::backgroundColor() const
298 return background().color();
302 Sets the background color [ virtual public ] [ obsolete ]
304 void OCCViewer_ViewPort3d::setBackgroundColor( const QColor& color )
306 Qtx::BackgroundData bg = background();
307 bg.setColor( color );
312 Returns the background data
314 Qtx::BackgroundData OCCViewer_ViewPort3d::background() const
320 Sets the background data
322 void OCCViewer_ViewPort3d::setBackground( const Qtx::BackgroundData& bgData )
324 if ( bgData.isValid() ) {
325 myBackground = bgData;
327 emit vpChangeBackground( myBackground );
331 void OCCViewer_ViewPort3d::updateBackground()
333 if ( activeView().IsNull() ) return;
334 if ( !myBackground.isValid() ) return;
336 switch ( myBackground.mode() ) {
337 case Qtx::ColorBackground:
339 QColor c = myBackground.color();
341 // Unset texture should be done here
343 Quantity_Color qCol( c.red()/255., c.green()/255., c.blue()/255., Quantity_TOC_RGB );
344 activeView()->SetBgGradientStyle( Aspect_GFM_NONE ); // cancel gradient background
345 activeView()->SetBgImageStyle( Aspect_FM_NONE ); // cancel texture background
346 // then change background color
347 activeView()->SetBackgroundColor( qCol );
349 activeView()->Update();
353 case Qtx::SimpleGradientBackground:
356 int type = myBackground.gradient( c1, c2 );
357 if ( c1.isValid() && type >= OCCViewer_Viewer::HorizontalGradient && type <= OCCViewer_Viewer::LastGradient ) {
358 // Unset texture should be done here
360 // Get colors and set-up gradiented background
361 if ( !c2.isValid() ) c2 = c1;
362 Quantity_Color qCol1( c1.red()/255., c1.green()/255., c1.blue()/255., Quantity_TOC_RGB );
363 Quantity_Color qCol2( c2.red()/255., c2.green()/255., c2.blue()/255., Quantity_TOC_RGB );
364 activeView()->SetBgImageStyle( Aspect_FM_NONE ); // cancel texture background
366 case OCCViewer_Viewer::HorizontalGradient:
367 activeView()->SetBgGradientColors( qCol1, qCol2, Aspect_GFM_HOR, Standard_True );
369 case OCCViewer_Viewer::VerticalGradient:
370 activeView()->SetBgGradientColors( qCol1, qCol2, Aspect_GFM_VER, Standard_True );
372 case OCCViewer_Viewer::Diagonal1Gradient:
373 activeView()->SetBgGradientColors( qCol1, qCol2, Aspect_GFM_DIAG1, Standard_True );
375 case OCCViewer_Viewer::Diagonal2Gradient:
376 activeView()->SetBgGradientColors( qCol1, qCol2, Aspect_GFM_DIAG2, Standard_True );
378 case OCCViewer_Viewer::Corner1Gradient:
379 activeView()->SetBgGradientColors( qCol1, qCol2, Aspect_GFM_CORNER1, Standard_True );
381 case OCCViewer_Viewer::Corner2Gradient:
382 activeView()->SetBgGradientColors( qCol1, qCol2, Aspect_GFM_CORNER2, Standard_True );
384 case OCCViewer_Viewer::Corner3Gradient:
385 activeView()->SetBgGradientColors( qCol1, qCol2, Aspect_GFM_CORNER3, Standard_True );
387 case OCCViewer_Viewer::Corner4Gradient:
388 activeView()->SetBgGradientColors( qCol1, qCol2, Aspect_GFM_CORNER4, Standard_True );
396 case Qtx::CustomGradientBackground:
398 // NOT IMPLEMENTED YET
404 if ( myBackground.isTextureShown() ) {
406 int textureMode = myBackground.texture( fileName );
407 QFileInfo fi( fileName );
408 if ( !fileName.isEmpty() && fi.exists() ) {
409 // set texture image: file name and fill mode
410 switch ( textureMode ) {
411 case Qtx::CenterTexture:
412 activeView()->SetBackgroundImage( fi.absoluteFilePath().toLatin1().constData(), Aspect_FM_CENTERED );
414 case Qtx::TileTexture:
415 activeView()->SetBackgroundImage( fi.absoluteFilePath().toLatin1().constData(), Aspect_FM_TILED );
417 case Qtx::StretchTexture:
418 activeView()->SetBackgroundImage( fi.absoluteFilePath().toLatin1().constData(), Aspect_FM_STRETCH );
423 activeView()->Update();
429 Updates the active viewport. [ virtual public ]
431 void OCCViewer_ViewPort3d::onUpdate()
433 if ( !activeView().IsNull() )
434 activeView()->Update();
438 Called at 'window fit' transformation. [ virtual protected ]
440 void OCCViewer_ViewPort3d::fitRect( const QRect& rect )
442 if ( !activeView().IsNull() ) {
443 activeView()->WindowFit( rect.left(), rect.top(), rect.right(), rect.bottom() );
444 emit vpTransformed( this );
449 Inits 'zoom' transformation. [ protected ]
451 void OCCViewer_ViewPort3d::startZoomAtPoint( int x, int y )
453 if ( !activeView().IsNull() && isAdvancedZoomingEnabled() )
454 activeView()->StartZoomAtPoint( x, y );
458 Called at 'zoom' transformation. [ virtual protected ]
460 void OCCViewer_ViewPort3d::zoom( int x0, int y0, int x, int y )
462 if ( !activeView().IsNull() ) {
463 // as OCCT respects a sign of only dx,
464 // but we want both signes to be taken into account
465 //activeView()->Zoom( x0, y0, x, y );
466 if ( isAdvancedZoomingEnabled() )
467 activeView()->ZoomAtPoint( x0, y0, x, y );
469 activeView()->Zoom( x0 + y0, 0, x + y, 0 );
470 emit vpTransformed( this );
475 Centers the viewport. [ virtual protected ]
477 void OCCViewer_ViewPort3d::setCenter( int x, int y )
479 if ( !activeView().IsNull() ) {
480 activeView()->Place( x, y, myScale );
481 emit vpTransformed( this );
486 Called at 'pan' transformation. [ virtual protected ]
488 void OCCViewer_ViewPort3d::pan( int dx, int dy )
490 if ( !activeView().IsNull() ) {
491 activeView()->Pan( dx, dy, 1.0 );
492 emit vpTransformed( this );
497 Inits 'rotation' transformation. [ protected ]
499 void OCCViewer_ViewPort3d::startRotation( int x, int y,
500 int theRotationPointType,
501 const gp_Pnt& theSelectedPoint )
503 if ( !activeView().IsNull() ) {
505 //double gx = activeView()->gx;
506 //activeView()->Gravity(gx,gy,gz);
508 switch ( theRotationPointType ) {
509 case OCCViewer_ViewWindow::BBCENTER:
510 activeView()->StartRotation( x, y, 0.45 );
512 case OCCViewer_ViewWindow::SELECTED:
516 activeView()->Size(X,Y);
517 rx = Standard_Real(activeView()->Convert(X));
518 ry = Standard_Real(activeView()->Convert(Y));
520 activeView()->Rotate( 0., 0., 0.,
521 theSelectedPoint.X(),theSelectedPoint.Y(), theSelectedPoint.Z(),
524 Quantity_Ratio zRotationThreshold;
525 zRotation = Standard_False;
526 zRotationThreshold = 0.45;
527 if( zRotationThreshold > 0. ) {
528 Standard_Real dx = Abs(sx - rx/2.);
529 Standard_Real dy = Abs(sy - ry/2.);
530 Standard_Real dd = zRotationThreshold * (rx + ry)/2.;
531 if( dx > dd || dy > dd ) zRotation = Standard_True;
537 // VSR: 10.06.2015: next line commented out - causes ugly blinking on starting rotation with Perspective projection mode
538 //activeView()->DepthFitAll();
543 Rotates the viewport. [ protected ]
545 void OCCViewer_ViewPort3d::rotate( int x, int y,
546 int theRotationPointType,
547 const gp_Pnt& theSelectedPoint )
549 if ( !activeView().IsNull() ) {
550 switch ( theRotationPointType ) {
551 case OCCViewer_ViewWindow::BBCENTER:
552 activeView()->Rotation( x, y );
554 case OCCViewer_ViewWindow::SELECTED:
557 dz = atan2(Standard_Real(x)-rx/2., ry/2.-Standard_Real(y)) -
558 atan2(sx-rx/2.,ry/2.-sy);
562 dx = (Standard_Real(x) - sx) * M_PI/rx;
563 dy = (sy - Standard_Real(y)) * M_PI/ry;
567 activeView()->Rotate( dx, dy, dz,
568 theSelectedPoint.X(),theSelectedPoint.Y(), theSelectedPoint.Z(),
574 emit vpTransformed( this );
576 // setZSize( getZSize() );
580 Resets the viewport after 'rotation'. [ protected ]
582 void OCCViewer_ViewPort3d::endRotation()
584 if ( !activeView().IsNull() ) {
585 #if OCC_VERSION_LARGE <= 0x07000000
586 activeView()->ZFitAll( 1.0 );
587 activeView()->SetZSize( 0.0 );
589 activeView()->Update();
590 emit vpTransformed( this );
595 Repaints the viewport. [ virtual protected ]
597 void OCCViewer_ViewPort3d::paintEvent( QPaintEvent* e )
600 /* X11 : map before show doesn't work */
601 if ( !mapped( activeView() ) )
602 mapView( activeView() );
604 if ( !myWindow.IsNull() ) {
605 #if QT_VERSION < QT_VERSION_CHECK(5, 0, 0)
606 QApplication::syncX();
608 if ( !myPaintersRedrawing ) {
609 #if OCC_VERSION_MAJOR < 7
610 QRect rc = e->rect();
611 activeView()->Redraw( rc.x(), rc.y(), rc.width(), rc.height() );
613 activeView()->Redraw();
617 OCCViewer_ViewPort::paintEvent( e );
622 Resizes the viewport. [ virtual protected ]
624 void OCCViewer_ViewPort3d::resizeEvent( QResizeEvent* e )
626 #if defined WIN32 || QT_VERSION >= QT_VERSION_CHECK(5, 0, 0)
627 /* Win32 : map before first show to avoid flicker */
628 if ( !mapped( activeView() ) )
629 mapView( activeView() );
631 #if QT_VERSION < QT_VERSION_CHECK(5, 0, 0)
632 QApplication::syncX();
634 QTimer::singleShot( 0, this, SLOT( repaintViewAfterMove() ) );
640 void OCCViewer_ViewPort3d::repaintViewAfterMove( )
642 if ( !activeView().IsNull() ){
643 activeView()->MustBeResized();
648 Fits all objects in view. [ virtual protected ]
650 void OCCViewer_ViewPort3d::fitAll( bool keepScale, bool withZ, bool upd )
652 if ( activeView().IsNull() )
656 myScale = activeView()->Scale();
658 Standard_Real margin = 0.01;
660 #if OCC_VERSION_LARGE > 0x06070100
661 activeView()->FitAll( margin, upd );
662 #if OCC_VERSION_LARGE <= 0x07000000
664 activeView()->ZFitAll();
667 activeView()->FitAll( margin, withZ, upd );
668 activeView()->SetZSize(0.);
670 emit vpTransformed( this );
674 Resets the view. [ virtual protected ]
676 void OCCViewer_ViewPort3d::reset()
678 // double zsize = getZSize();
679 if ( !activeView().IsNull() ) {
680 activeView()->Reset();
681 emit vpTransformed( this );
682 // setZSize( zsize );
687 Rotate the view in the view plane (orthogonal to the view vector)
689 void OCCViewer_ViewPort3d::rotateXY( double degrees )
691 if ( activeView().IsNull() )
694 int x = width()/2, y = height()/2;
696 activeView()->Convert( x, y, X, Y, Z );
697 activeView()->Rotate( 0, 0, degrees * M_PI / 180., X, Y, Z );
698 emit vpTransformed( this );
702 Set axial scale to the view
704 void OCCViewer_ViewPort3d::setAxialScale( double xScale, double yScale, double zScale )
706 if ( activeView().IsNull() )
709 activeView()->SetAxialScale( xScale, yScale, zScale );
710 emit vpTransformed( this );
714 Passed the handle of native window of the component to CASCADE view. [ private ]
716 bool OCCViewer_ViewPort3d::setWindow( const Handle(V3d_View)& view )
718 if ( !myWindow.IsNull() )
724 attachWindow( view, OCCViewer_VService::CreateWindow( view, winId() ) );
726 myWindow = view->Window();
727 return !myWindow.IsNull();
730 void OCCViewer_ViewPort3d::attachWindow( const Handle(V3d_View)& view,
731 const Handle(Aspect_Window)& window)
733 if (!view.IsNull()) {
734 view->SetWindow( window );
740 Returns the current active view. [ private ]
742 Handle(V3d_View) OCCViewer_ViewPort3d::activeView() const
748 Returns the current inactive view [ private ]
750 /*Handle(V3d_View) OCCViewer_ViewPort3d::inactiveView() const
752 return ( activeView() == myOrthoView ? myPerspView : myOrthoView );
756 Returns 'true' if the given view is mapped to window. [ private ]
758 bool OCCViewer_ViewPort3d::mapped( const Handle(V3d_View)& view ) const
760 return ( !view.IsNull() && view->View()->IsDefined() );
764 Performs synchronization of view parameters with the specified view.
765 Returns \c true if synchronization is done successfully or \c false otherwise.
766 Default implementation does nothing (return \c false)
768 bool OCCViewer_ViewPort3d::synchronize( OCCViewer_ViewPort* view )
771 OCCViewer_ViewPort3d* vp3d = qobject_cast<OCCViewer_ViewPort3d*>( view );
773 bool blocked = blockSignals( false );
774 Handle(V3d_View) aView3d = getView();
775 Handle(V3d_View) aRefView3d = vp3d->getView();
776 aView3d->SetImmediateUpdate( Standard_False );
777 #if OCC_VERSION_LARGE > 0x06070100
778 aView3d->Camera()->Copy( aRefView3d->Camera() );
780 aView3d->SetViewMapping( aRefView3d->ViewMapping() );
781 aView3d->SetViewOrientation( aRefView3d->ViewOrientation() );
783 #if OCC_VERSION_LARGE <= 0x07000000
786 aView3d->SetImmediateUpdate( Standard_True );
788 blockSignals( blocked );
795 * Show/Hide static triedron
797 void OCCViewer_ViewPort3d::showStaticTrihedron( bool on )
799 Handle(V3d_View) aView = activeView();
800 if ( !aView ) return;
803 aView->ZBufferTriedronSetup();
804 aView->TriedronDisplay( Aspect_TOTP_LEFT_LOWER, Quantity_NOC_WHITE, 0.05, V3d_ZBUFFER );
806 aView->TriedronErase();
812 * Create default cursor with a specific shape
814 void OCCViewer_ViewPort3d::setDefaultCursor( Qt::CursorShape theCursorShape )
817 myCursor = new QCursor();
819 myCursor->setShape( theCursorShape );
823 * Get default cursor with a specific shape
825 QCursor* OCCViewer_ViewPort3d::getDefaultCursor() const
831 * Set default parameters from preferences
833 void OCCViewer_ViewPort3d::setDefaultParams()
835 setBackground( Qtx::BackgroundData( Qt::black ) ); // set default background
837 // get ray tracing parameters from preferences
838 int aDepth = SUIT_Session::session()->resourceMgr()->integerValue( "OCCViewer", "rt_depth", 3 );
839 bool aReflection = SUIT_Session::session()->resourceMgr()->booleanValue( "OCCViewer", "rt_reflection", true );
840 bool anAntialiasing = SUIT_Session::session()->resourceMgr()->booleanValue( "OCCViewer", "rt_antialiasing", false );
841 bool aShadow = SUIT_Session::session()->resourceMgr()->booleanValue( "OCCViewer", "rt_shadow", true );
842 bool aTransparentShadow = SUIT_Session::session()->resourceMgr()->booleanValue( "OCCViewer", "rt_trans_shadow", true );
844 Graphic3d_RenderingParams& aParams = myActiveView->ChangeRenderingParams();
845 aParams.RaytracingDepth = aDepth;
846 aParams.IsReflectionEnabled = aReflection;
847 aParams.IsAntialiasingEnabled = anAntialiasing;
848 aParams.IsShadowEnabled = aShadow;
849 aParams.IsTransparentShadowEnabled = aTransparentShadow;
850 myActiveView->Redraw();