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 #include "utilities.h"
57 #include <WNT_Window.hxx>
59 //#include <Xw_Window.hxx>
62 static double rx = 0.;
63 static double ry = 0.;
66 static Standard_Boolean zRotation = Standard_False;
68 //#include <Standard_Version.hxx>
73 OCCViewer_ViewPort3d::OCCViewer_ViewPort3d( QWidget* parent, const Handle( V3d_Viewer)& viewer, V3d_TypeOfView type )
74 : OCCViewer_ViewPort( parent ),
77 myIsAdvancedZoomingEnabled( false )
79 // VSR: 01/07/2010 commented to avoid SIGSEGV at SALOME exit
82 #if OCC_VERSION_LARGE > 0x06070100
83 myActiveView = new V3d_View( viewer, type );
85 if ( type == V3d_ORTHOGRAPHIC ) {
86 myOrthoView = new V3d_OrthographicView( viewer );
87 myActiveView = myOrthoView;
90 myPerspView = new V3d_PerspectiveView( viewer );
91 myActiveView = myPerspView;
103 OCCViewer_ViewPort3d::~OCCViewer_ViewPort3d()
112 Handle(V3d_View) aView = activeView();
118 Activates the desired 'type' of view in the viewer
119 ( view of 'type' is created if it doesn't exist ). [ public ]
121 /*void OCCViewer_ViewPort3d::setActive( V3d_TypeOfView type )
123 if ( activeView().IsNull() )
126 if ( activeView()->Type() != type )
128 if ( type == V3d_ORTHOGRAPHIC )
129 setView( myOrthoView );
130 if ( type == V3d_PERSPECTIVE )
131 setView( myPerspView );
136 Maps CasCade 'view' to this viewport. [ private ]
138 bool OCCViewer_ViewPort3d::mapView( const Handle(V3d_View)& view )
140 if ( !setWindow( view ) )
143 if ( !mapped( view ) ) {
144 view->SetWindow( myWindow );
145 if ( view != activeView() )
146 view->View()->Deactivate();
149 emit( vpMapped(this) );
157 Sets new CASCADE view on viewport. Returns the previous active view. [ public ]
159 Handle( V3d_View ) OCCViewer_ViewPort3d::setView( const Handle( V3d_View )& view )
161 /* map the new view */
162 if ( view == activeView() || !mapView( view ) )
165 /* activate the new view*/
166 Handle( V3d_View ) oldView = activeView();
167 if ( !oldView.IsNull() ) {
168 if (oldView->View()->IsDefined())
169 oldView->View()->Deactivate();
170 view->SetBackgroundColor( oldView->BackgroundColor() );
173 view->View()->Activate();
179 Returns CasCade 3D view. [ public ]
181 Handle(V3d_View) OCCViewer_ViewPort3d::getView() const
187 Returns CasCade 3D viewer [ public ]
189 Handle(V3d_Viewer) OCCViewer_ViewPort3d::getViewer() const
191 Handle(V3d_Viewer) viewer;
192 if ( !activeView().IsNull() )
193 viewer = activeView()->Viewer();
198 Syncronizes visual state of this viewport with 'ref'
199 ( scale, projection, eye etc ) Returns 'true' if copied OK,
200 'false' otherwise. [ virtual public ]
202 bool OCCViewer_ViewPort3d::syncronize( const OCCViewer_ViewPort3d* ref )
204 OCCViewer_ViewPort3d* ref3d = (OCCViewer_ViewPort3d*)ref;
205 Handle(V3d_View) refView = ref3d->getView();
206 Handle(V3d_View) tgtView = getView();
208 /* Syncronize view types */
209 /* if ( tgtView->Type() != refView->Type() )
211 setActive( refView->Type() );
215 /* The following params are copied:
216 - view type( ortho/persp )
217 - position of view point
218 - orientation of high point
219 - position of the eye
226 /* we'll update after setting all params */
227 tgtView->SetImmediateUpdate( Standard_False );
230 if ( refView->Type() == V3d_PERSPECTIVE )
231 tgtView->SetFocale( refView->Focale() );
234 Standard_Real x, y, z;
235 refView->At( x, y, z ); tgtView->SetAt( x, y, z );
236 refView->Up( x, y, z ); tgtView->SetUp( x, y, z );
237 refView->Eye( x, y, z ); tgtView->SetEye( x, y, z );
238 refView->Proj( x, y, z ); tgtView->SetProj( x, y, z );
239 #if OCC_VERSION_LARGE <= 0x06070100
240 refView->Center( x, y ); tgtView->SetCenter( x, y );
242 tgtView->SetScale( refView->Scale() );
243 tgtView->SetTwist( refView->Twist() );
247 tgtView->SetImmediateUpdate( Standard_True );
248 #if OCC_VERSION_LARGE <= 0x07000000
254 #if OCC_VERSION_LARGE <= 0x07000000
256 Returns Z-size of this view. [ public ]
258 double OCCViewer_ViewPort3d::getZSize() const
260 if ( !activeView().IsNull() )
261 return activeView()->ZSize();
266 Sets Z-size of this view ( for both orthographic and perspective ). [ public ]
268 void OCCViewer_ViewPort3d::setZSize( double zsize )
270 myActiveView->SetZSize( zsize );
271 /* if ( !myOrthoView.IsNull() )
272 myOrthoView->SetZSize( zsize );
273 if ( !myPerspView.IsNull() )
274 myPerspView->SetZSize( zsize );*/
279 Get axial scale to the view
281 void OCCViewer_ViewPort3d::getAxialScale( double& xScale, double& yScale, double& zScale )
283 xScale = yScale = zScale = 1.;
285 if ( !activeView().IsNull() )
286 activeView()->AxialScale( xScale, yScale, zScale );
290 Returns the background color [ virtual public ] [ obsolete ]
292 QColor OCCViewer_ViewPort3d::backgroundColor() const
294 return background().color();
298 Sets the background color [ virtual public ] [ obsolete ]
300 void OCCViewer_ViewPort3d::setBackgroundColor( const QColor& color )
302 Qtx::BackgroundData bg = background();
303 bg.setColor( color );
308 Returns the background data
310 Qtx::BackgroundData OCCViewer_ViewPort3d::background() const
316 Sets the background data
318 void OCCViewer_ViewPort3d::setBackground( const Qtx::BackgroundData& bgData )
320 if ( bgData.isValid() ) {
321 myBackground = bgData;
323 emit vpChangeBackground( myBackground );
327 void OCCViewer_ViewPort3d::updateBackground()
329 if ( activeView().IsNull() ) return;
330 if ( !myBackground.isValid() ) return;
332 switch ( myBackground.mode() ) {
333 case Qtx::ColorBackground:
335 QColor c = myBackground.color();
337 // Unset texture should be done here
339 Quantity_Color qCol( c.red()/255., c.green()/255., c.blue()/255., Quantity_TOC_RGB );
340 activeView()->SetBgGradientStyle( Aspect_GFM_NONE ); // cancel gradient background
341 activeView()->SetBgImageStyle( Aspect_FM_NONE ); // cancel texture background
342 // then change background color
343 activeView()->SetBackgroundColor( qCol );
345 activeView()->Update();
349 case Qtx::SimpleGradientBackground:
352 int type = myBackground.gradient( c1, c2 );
353 if ( c1.isValid() && type >= OCCViewer_Viewer::HorizontalGradient && type <= OCCViewer_Viewer::LastGradient ) {
354 // Unset texture should be done here
356 // Get colors and set-up gradiented background
357 if ( !c2.isValid() ) c2 = c1;
358 Quantity_Color qCol1( c1.red()/255., c1.green()/255., c1.blue()/255., Quantity_TOC_RGB );
359 Quantity_Color qCol2( c2.red()/255., c2.green()/255., c2.blue()/255., Quantity_TOC_RGB );
360 activeView()->SetBgImageStyle( Aspect_FM_NONE ); // cancel texture background
362 case OCCViewer_Viewer::HorizontalGradient:
363 activeView()->SetBgGradientColors( qCol1, qCol2, Aspect_GFM_HOR, Standard_True );
365 case OCCViewer_Viewer::VerticalGradient:
366 activeView()->SetBgGradientColors( qCol1, qCol2, Aspect_GFM_VER, Standard_True );
368 case OCCViewer_Viewer::Diagonal1Gradient:
369 activeView()->SetBgGradientColors( qCol1, qCol2, Aspect_GFM_DIAG1, Standard_True );
371 case OCCViewer_Viewer::Diagonal2Gradient:
372 activeView()->SetBgGradientColors( qCol1, qCol2, Aspect_GFM_DIAG2, Standard_True );
374 case OCCViewer_Viewer::Corner1Gradient:
375 activeView()->SetBgGradientColors( qCol1, qCol2, Aspect_GFM_CORNER1, Standard_True );
377 case OCCViewer_Viewer::Corner2Gradient:
378 activeView()->SetBgGradientColors( qCol1, qCol2, Aspect_GFM_CORNER2, Standard_True );
380 case OCCViewer_Viewer::Corner3Gradient:
381 activeView()->SetBgGradientColors( qCol1, qCol2, Aspect_GFM_CORNER3, Standard_True );
383 case OCCViewer_Viewer::Corner4Gradient:
384 activeView()->SetBgGradientColors( qCol1, qCol2, Aspect_GFM_CORNER4, Standard_True );
392 case Qtx::CustomGradientBackground:
394 // NOT IMPLEMENTED YET
400 if ( myBackground.isTextureShown() ) {
402 int textureMode = myBackground.texture( fileName );
403 QFileInfo fi( fileName );
404 if ( !fileName.isEmpty() && fi.exists() ) {
405 // set texture image: file name and fill mode
406 switch ( textureMode ) {
407 case Qtx::CenterTexture:
408 activeView()->SetBackgroundImage( fi.absoluteFilePath().toLatin1().constData(), Aspect_FM_CENTERED );
410 case Qtx::TileTexture:
411 activeView()->SetBackgroundImage( fi.absoluteFilePath().toLatin1().constData(), Aspect_FM_TILED );
413 case Qtx::StretchTexture:
414 activeView()->SetBackgroundImage( fi.absoluteFilePath().toLatin1().constData(), Aspect_FM_STRETCH );
419 activeView()->Update();
425 Updates the active viewport. [ virtual public ]
427 void OCCViewer_ViewPort3d::onUpdate()
429 if ( !activeView().IsNull() )
430 activeView()->Update();
434 Called at 'window fit' transformation. [ virtual protected ]
436 void OCCViewer_ViewPort3d::fitRect( const QRect& rect )
438 if ( !activeView().IsNull() ) {
439 activeView()->WindowFit( rect.left(), rect.top(), rect.right(), rect.bottom() );
440 emit vpTransformed( this );
445 Inits 'zoom' transformation. [ protected ]
447 void OCCViewer_ViewPort3d::startZoomAtPoint( int x, int y )
449 if ( !activeView().IsNull() && isAdvancedZoomingEnabled() )
450 activeView()->StartZoomAtPoint( x, y );
454 Called at 'zoom' transformation. [ virtual protected ]
456 void OCCViewer_ViewPort3d::zoom( int x0, int y0, int x, int y )
458 if ( !activeView().IsNull() ) {
459 // as OCCT respects a sign of only dx,
460 // but we want both signes to be taken into account
461 //activeView()->Zoom( x0, y0, x, y );
462 if ( isAdvancedZoomingEnabled() )
463 activeView()->ZoomAtPoint( x0, y0, x, y );
465 activeView()->Zoom( x0 + y0, 0, x + y, 0 );
466 emit vpTransformed( this );
471 Centers the viewport. [ virtual protected ]
473 void OCCViewer_ViewPort3d::setCenter( int x, int y )
475 if ( !activeView().IsNull() ) {
476 activeView()->Place( x, y, myScale );
477 emit vpTransformed( this );
482 Called at 'pan' transformation. [ virtual protected ]
484 void OCCViewer_ViewPort3d::pan( int dx, int dy )
486 if ( !activeView().IsNull() ) {
487 activeView()->Pan( dx, dy, 1.0 );
488 emit vpTransformed( this );
493 Inits 'rotation' transformation. [ protected ]
495 void OCCViewer_ViewPort3d::startRotation( int x, int y,
496 int theRotationPointType,
497 const gp_Pnt& theSelectedPoint )
499 if ( !activeView().IsNull() ) {
501 //double gx = activeView()->gx;
502 //activeView()->Gravity(gx,gy,gz);
504 switch ( theRotationPointType ) {
505 case OCCViewer_ViewWindow::BBCENTER:
506 activeView()->StartRotation( x, y, 0.45 );
508 case OCCViewer_ViewWindow::SELECTED:
512 activeView()->Size(X,Y);
513 rx = Standard_Real(activeView()->Convert(X));
514 ry = Standard_Real(activeView()->Convert(Y));
516 activeView()->Rotate( 0., 0., 0.,
517 theSelectedPoint.X(),theSelectedPoint.Y(), theSelectedPoint.Z(),
520 Quantity_Ratio zRotationThreshold;
521 zRotation = Standard_False;
522 zRotationThreshold = 0.45;
523 if( zRotationThreshold > 0. ) {
524 Standard_Real dx = Abs(sx - rx/2.);
525 Standard_Real dy = Abs(sy - ry/2.);
526 Standard_Real dd = zRotationThreshold * (rx + ry)/2.;
527 if( dx > dd || dy > dd ) zRotation = Standard_True;
533 // VSR: 10.06.2015: next line commented out - causes ugly blinking on starting rotation with Perspective projection mode
534 //activeView()->DepthFitAll();
539 Rotates the viewport. [ protected ]
541 void OCCViewer_ViewPort3d::rotate( int x, int y,
542 int theRotationPointType,
543 const gp_Pnt& theSelectedPoint )
545 if ( !activeView().IsNull() ) {
546 switch ( theRotationPointType ) {
547 case OCCViewer_ViewWindow::BBCENTER:
548 activeView()->Rotation( x, y );
550 case OCCViewer_ViewWindow::SELECTED:
553 dz = atan2(Standard_Real(x)-rx/2., ry/2.-Standard_Real(y)) -
554 atan2(sx-rx/2.,ry/2.-sy);
558 dx = (Standard_Real(x) - sx) * M_PI/rx;
559 dy = (sy - Standard_Real(y)) * M_PI/ry;
563 activeView()->Rotate( dx, dy, dz,
564 theSelectedPoint.X(),theSelectedPoint.Y(), theSelectedPoint.Z(),
570 emit vpTransformed( this );
572 // setZSize( getZSize() );
576 Resets the viewport after 'rotation'. [ protected ]
578 void OCCViewer_ViewPort3d::endRotation()
580 if ( !activeView().IsNull() ) {
581 #if OCC_VERSION_LARGE <= 0x07000000
582 activeView()->ZFitAll( 1.0 );
583 activeView()->SetZSize( 0.0 );
585 activeView()->Update();
586 emit vpTransformed( this );
591 Repaints the viewport. [ virtual protected ]
593 void OCCViewer_ViewPort3d::paintEvent( QPaintEvent* e )
596 /* X11 : map before show doesn't work */
597 if ( !mapped( activeView() ) )
598 mapView( activeView() );
600 if ( !myWindow.IsNull() ) {
601 #if QT_VERSION < QT_VERSION_CHECK(5, 0, 0)
602 QApplication::syncX();
604 if ( !myPaintersRedrawing ) {
605 #if OCC_VERSION_MAJOR < 7
606 QRect rc = e->rect();
607 activeView()->Redraw( rc.x(), rc.y(), rc.width(), rc.height() );
609 activeView()->Redraw();
613 OCCViewer_ViewPort::paintEvent( e );
618 Resizes the viewport. [ virtual protected ]
620 void OCCViewer_ViewPort3d::resizeEvent( QResizeEvent* e )
622 #if defined WIN32 || QT_VERSION >= QT_VERSION_CHECK(5, 0, 0)
623 /* Win32 : map before first show to avoid flicker */
624 if ( !mapped( activeView() ) )
625 mapView( activeView() );
627 #if QT_VERSION < QT_VERSION_CHECK(5, 0, 0)
628 QApplication::syncX();
630 QTimer::singleShot( 0, this, SLOT( repaintViewAfterMove() ) );
636 void OCCViewer_ViewPort3d::repaintViewAfterMove( )
638 if ( !activeView().IsNull() ){
639 activeView()->MustBeResized();
644 Fits all objects in view. [ virtual protected ]
646 void OCCViewer_ViewPort3d::fitAll( bool keepScale, bool withZ, bool upd )
648 if ( activeView().IsNull() )
652 myScale = activeView()->Scale();
654 Standard_Real margin = 0.01;
656 #if OCC_VERSION_LARGE > 0x06070100
657 activeView()->FitAll( margin, upd );
658 #if OCC_VERSION_LARGE <= 0x07000000
660 activeView()->ZFitAll();
663 activeView()->FitAll( margin, withZ, upd );
664 activeView()->SetZSize(0.);
666 emit vpTransformed( this );
670 Resets the view. [ virtual protected ]
672 void OCCViewer_ViewPort3d::reset()
674 // double zsize = getZSize();
675 if ( !activeView().IsNull() ) {
676 activeView()->Reset();
677 emit vpTransformed( this );
678 // setZSize( zsize );
683 Rotate the view in the view plane (orthogonal to the view vector)
685 void OCCViewer_ViewPort3d::rotateXY( double degrees )
687 if ( activeView().IsNull() )
690 int x = width()/2, y = height()/2;
692 activeView()->Convert( x, y, X, Y, Z );
693 activeView()->Rotate( 0, 0, degrees * M_PI / 180., X, Y, Z );
694 emit vpTransformed( this );
698 Set axial scale to the view
700 void OCCViewer_ViewPort3d::setAxialScale( double xScale, double yScale, double zScale )
702 if ( activeView().IsNull() )
705 activeView()->SetAxialScale( xScale, yScale, zScale );
706 emit vpTransformed( this );
710 Passed the handle of native window of the component to CASCADE view. [ private ]
712 bool OCCViewer_ViewPort3d::setWindow( const Handle(V3d_View)& view )
714 if ( !myWindow.IsNull() )
720 attachWindow( view, OCCViewer_VService::CreateWindow( view, winId() ) );
722 myWindow = view->Window();
723 return !myWindow.IsNull();
726 void OCCViewer_ViewPort3d::attachWindow( const Handle(V3d_View)& view,
727 const Handle(Aspect_Window)& window)
729 if (!view.IsNull()) {
730 view->SetWindow( window );
736 Returns the current active view. [ private ]
738 Handle(V3d_View) OCCViewer_ViewPort3d::activeView() const
744 Returns the current inactive view [ private ]
746 /*Handle(V3d_View) OCCViewer_ViewPort3d::inactiveView() const
748 return ( activeView() == myOrthoView ? myPerspView : myOrthoView );
752 Returns 'true' if the given view is mapped to window. [ private ]
754 bool OCCViewer_ViewPort3d::mapped( const Handle(V3d_View)& view ) const
756 return ( !view.IsNull() && view->View()->IsDefined() );
760 Performs synchronization of view parameters with the specified view.
761 Returns \c true if synchronization is done successfully or \c false otherwise.
762 Default implementation does nothing (return \c false)
764 bool OCCViewer_ViewPort3d::synchronize( OCCViewer_ViewPort* view )
767 OCCViewer_ViewPort3d* vp3d = qobject_cast<OCCViewer_ViewPort3d*>( view );
769 bool blocked = blockSignals( false );
770 Handle(V3d_View) aView3d = getView();
771 Handle(V3d_View) aRefView3d = vp3d->getView();
772 aView3d->SetImmediateUpdate( Standard_False );
773 #if OCC_VERSION_LARGE > 0x06070100
774 aView3d->Camera()->Copy( aRefView3d->Camera() );
776 aView3d->SetViewMapping( aRefView3d->ViewMapping() );
777 aView3d->SetViewOrientation( aRefView3d->ViewOrientation() );
779 #if OCC_VERSION_LARGE <= 0x07000000
782 aView3d->SetImmediateUpdate( Standard_True );
784 blockSignals( blocked );
791 * Show/Hide static triedron
793 void OCCViewer_ViewPort3d::showStaticTrihedron( bool on )
795 Handle(V3d_View) aView = activeView();
796 if ( !aView ) return;
799 aView->ZBufferTriedronSetup();
800 aView->TriedronDisplay( Aspect_TOTP_LEFT_LOWER, Quantity_NOC_WHITE, 0.05, V3d_ZBUFFER );
802 aView->TriedronErase();
808 * Create default cursor with a specific shape
810 void OCCViewer_ViewPort3d::setDefaultCursor( Qt::CursorShape theCursorShape )
813 myCursor = new QCursor();
815 myCursor->setShape( theCursorShape );
819 * Get default cursor with a specific shape
821 QCursor* OCCViewer_ViewPort3d::getDefaultCursor() const
827 * Set default parameters from preferences
829 void OCCViewer_ViewPort3d::setDefaultParams()
831 setBackground( Qtx::BackgroundData( Qt::black ) ); // set default background
833 // get ray tracing parameters from preferences
834 int aDepth = SUIT_Session::session()->resourceMgr()->integerValue( "OCCViewer", "rt_depth", 3 );
835 bool aReflection = SUIT_Session::session()->resourceMgr()->booleanValue( "OCCViewer", "rt_reflection", true );
836 bool anAntialiasing = SUIT_Session::session()->resourceMgr()->booleanValue( "OCCViewer", "rt_antialiasing", false );
837 bool aShadow = SUIT_Session::session()->resourceMgr()->booleanValue( "OCCViewer", "rt_shadow", true );
838 bool aTransparentShadow = SUIT_Session::session()->resourceMgr()->booleanValue( "OCCViewer", "rt_trans_shadow", true );
840 Graphic3d_RenderingParams& aParams = myActiveView->ChangeRenderingParams();
841 aParams.RaytracingDepth = aDepth;
842 aParams.IsReflectionEnabled = aReflection;
843 aParams.IsAntialiasingEnabled = anAntialiasing;
844 aParams.IsShadowEnabled = aShadow;
845 aParams.IsTransparentShadowEnabled = aTransparentShadow;
846 myActiveView->Redraw();