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>
42 #if OCC_VERSION_MAJOR < 7
43 #include <Visual3d_View.hxx>
46 #if OCC_VERSION_LARGE > 0x06070100
47 #include <V3d_View.hxx>
49 #include <V3d_PerspectiveView.hxx>
50 #include <V3d_OrthographicView.hxx>
53 #include "utilities.h"
56 #include <WNT_Window.hxx>
58 //#include <Xw_Window.hxx>
61 static double rx = 0.;
62 static double ry = 0.;
65 static Standard_Boolean zRotation = Standard_False;
67 //#include <Standard_Version.hxx>
72 OCCViewer_ViewPort3d::OCCViewer_ViewPort3d( QWidget* parent, const Handle( V3d_Viewer)& viewer, V3d_TypeOfView type )
73 : OCCViewer_ViewPort( parent ),
76 myIsAdvancedZoomingEnabled( false )
78 // VSR: 01/07/2010 commented to avoid SIGSEGV at SALOME exit
81 #if OCC_VERSION_LARGE > 0x06070100
82 myActiveView = new V3d_View( viewer, type );
84 if ( type == V3d_ORTHOGRAPHIC ) {
85 myOrthoView = new V3d_OrthographicView( viewer );
86 myActiveView = myOrthoView;
89 myPerspView = new V3d_PerspectiveView( viewer );
90 myActiveView = myPerspView;
102 OCCViewer_ViewPort3d::~OCCViewer_ViewPort3d()
111 Handle(V3d_View) aView = activeView();
117 Activates the desired 'type' of view in the viewer
118 ( view of 'type' is created if it doesn't exist ). [ public ]
120 /*void OCCViewer_ViewPort3d::setActive( V3d_TypeOfView type )
122 if ( activeView().IsNull() )
125 if ( activeView()->Type() != type )
127 if ( type == V3d_ORTHOGRAPHIC )
128 setView( myOrthoView );
129 if ( type == V3d_PERSPECTIVE )
130 setView( myPerspView );
135 Maps CasCade 'view' to this viewport. [ private ]
137 bool OCCViewer_ViewPort3d::mapView( const Handle(V3d_View)& view )
139 if ( !setWindow( view ) )
142 if ( !mapped( view ) ) {
143 view->SetWindow( myWindow );
144 if ( view != activeView() )
145 view->View()->Deactivate();
148 emit( vpMapped(this) );
156 Sets new CASCADE view on viewport. Returns the previous active view. [ public ]
158 Handle( V3d_View ) OCCViewer_ViewPort3d::setView( const Handle( V3d_View )& view )
160 /* map the new view */
161 if ( view == activeView() || !mapView( view ) )
164 /* activate the new view*/
165 Handle( V3d_View ) oldView = activeView();
166 if ( !oldView.IsNull() ) {
167 if (oldView->View()->IsDefined())
168 oldView->View()->Deactivate();
169 view->SetBackgroundColor( oldView->BackgroundColor() );
172 view->View()->Activate();
178 Returns CasCade 3D view. [ public ]
180 Handle(V3d_View) OCCViewer_ViewPort3d::getView() const
186 Returns CasCade 3D viewer [ public ]
188 Handle(V3d_Viewer) OCCViewer_ViewPort3d::getViewer() const
190 Handle(V3d_Viewer) viewer;
191 if ( !activeView().IsNull() )
192 viewer = activeView()->Viewer();
197 Syncronizes visual state of this viewport with 'ref'
198 ( scale, projection, eye etc ) Returns 'true' if copied OK,
199 'false' otherwise. [ virtual public ]
201 bool OCCViewer_ViewPort3d::syncronize( const OCCViewer_ViewPort3d* ref )
203 OCCViewer_ViewPort3d* ref3d = (OCCViewer_ViewPort3d*)ref;
204 Handle(V3d_View) refView = ref3d->getView();
205 Handle(V3d_View) tgtView = getView();
207 /* Syncronize view types */
208 /* if ( tgtView->Type() != refView->Type() )
210 setActive( refView->Type() );
214 /* The following params are copied:
215 - view type( ortho/persp )
216 - position of view point
217 - orientation of high point
218 - position of the eye
225 /* we'll update after setting all params */
226 tgtView->SetImmediateUpdate( Standard_False );
229 if ( refView->Type() == V3d_PERSPECTIVE )
230 tgtView->SetFocale( refView->Focale() );
233 Standard_Real x, y, z;
234 refView->At( x, y, z ); tgtView->SetAt( x, y, z );
235 refView->Up( x, y, z ); tgtView->SetUp( x, y, z );
236 refView->Eye( x, y, z ); tgtView->SetEye( x, y, z );
237 refView->Proj( x, y, z ); tgtView->SetProj( x, y, z );
238 #if OCC_VERSION_LARGE <= 0x06070100
239 refView->Center( x, y ); tgtView->SetCenter( x, y );
241 tgtView->SetScale( refView->Scale() );
242 tgtView->SetTwist( refView->Twist() );
246 tgtView->SetImmediateUpdate( Standard_True );
252 Returns Z-size of this view. [ public ]
254 double OCCViewer_ViewPort3d::getZSize() const
256 if ( !activeView().IsNull() )
257 return activeView()->ZSize();
262 Sets Z-size of this view ( for both orthographic and perspective ). [ public ]
264 void OCCViewer_ViewPort3d::setZSize( double zsize )
266 myActiveView->SetZSize( zsize );
267 /* if ( !myOrthoView.IsNull() )
268 myOrthoView->SetZSize( zsize );
269 if ( !myPerspView.IsNull() )
270 myPerspView->SetZSize( zsize );*/
274 Get axial scale to the view
276 void OCCViewer_ViewPort3d::getAxialScale( double& xScale, double& yScale, double& zScale )
278 xScale = yScale = zScale = 1.;
280 if ( !activeView().IsNull() )
281 activeView()->AxialScale( xScale, yScale, zScale );
285 Returns the background color [ virtual public ] [ obsolete ]
287 QColor OCCViewer_ViewPort3d::backgroundColor() const
289 return background().color();
293 Sets the background color [ virtual public ] [ obsolete ]
295 void OCCViewer_ViewPort3d::setBackgroundColor( const QColor& color )
297 Qtx::BackgroundData bg = background();
298 bg.setColor( color );
303 Returns the background data
305 Qtx::BackgroundData OCCViewer_ViewPort3d::background() const
311 Sets the background data
313 void OCCViewer_ViewPort3d::setBackground( const Qtx::BackgroundData& bgData )
315 if ( bgData.isValid() ) {
316 myBackground = bgData;
318 emit vpChangeBackground( myBackground );
322 void OCCViewer_ViewPort3d::updateBackground()
324 if ( activeView().IsNull() ) return;
325 if ( !myBackground.isValid() ) return;
327 switch ( myBackground.mode() ) {
328 case Qtx::ColorBackground:
330 QColor c = myBackground.color();
332 // Unset texture should be done here
334 Quantity_Color qCol( c.red()/255., c.green()/255., c.blue()/255., Quantity_TOC_RGB );
335 activeView()->SetBgGradientStyle( Aspect_GFM_NONE ); // cancel gradient background
336 activeView()->SetBgImageStyle( Aspect_FM_NONE ); // cancel texture background
337 // then change background color
338 activeView()->SetBackgroundColor( qCol );
340 activeView()->Update();
344 case Qtx::SimpleGradientBackground:
347 int type = myBackground.gradient( c1, c2 );
348 if ( c1.isValid() && type >= OCCViewer_Viewer::HorizontalGradient && type <= OCCViewer_Viewer::LastGradient ) {
349 // Unset texture should be done here
351 // Get colors and set-up gradiented background
352 if ( !c2.isValid() ) c2 = c1;
353 Quantity_Color qCol1( c1.red()/255., c1.green()/255., c1.blue()/255., Quantity_TOC_RGB );
354 Quantity_Color qCol2( c2.red()/255., c2.green()/255., c2.blue()/255., Quantity_TOC_RGB );
355 activeView()->SetBgImageStyle( Aspect_FM_NONE ); // cancel texture background
357 case OCCViewer_Viewer::HorizontalGradient:
358 activeView()->SetBgGradientColors( qCol1, qCol2, Aspect_GFM_HOR, Standard_True );
360 case OCCViewer_Viewer::VerticalGradient:
361 activeView()->SetBgGradientColors( qCol1, qCol2, Aspect_GFM_VER, Standard_True );
363 case OCCViewer_Viewer::Diagonal1Gradient:
364 activeView()->SetBgGradientColors( qCol1, qCol2, Aspect_GFM_DIAG1, Standard_True );
366 case OCCViewer_Viewer::Diagonal2Gradient:
367 activeView()->SetBgGradientColors( qCol1, qCol2, Aspect_GFM_DIAG2, Standard_True );
369 case OCCViewer_Viewer::Corner1Gradient:
370 activeView()->SetBgGradientColors( qCol1, qCol2, Aspect_GFM_CORNER1, Standard_True );
372 case OCCViewer_Viewer::Corner2Gradient:
373 activeView()->SetBgGradientColors( qCol1, qCol2, Aspect_GFM_CORNER2, Standard_True );
375 case OCCViewer_Viewer::Corner3Gradient:
376 activeView()->SetBgGradientColors( qCol1, qCol2, Aspect_GFM_CORNER3, Standard_True );
378 case OCCViewer_Viewer::Corner4Gradient:
379 activeView()->SetBgGradientColors( qCol1, qCol2, Aspect_GFM_CORNER4, Standard_True );
387 case Qtx::CustomGradientBackground:
389 // NOT IMPLEMENTED YET
395 if ( myBackground.isTextureShown() ) {
397 int textureMode = myBackground.texture( fileName );
398 QFileInfo fi( fileName );
399 if ( !fileName.isEmpty() && fi.exists() ) {
400 // set texture image: file name and fill mode
401 switch ( textureMode ) {
402 case Qtx::CenterTexture:
403 activeView()->SetBackgroundImage( fi.absoluteFilePath().toLatin1().constData(), Aspect_FM_CENTERED );
405 case Qtx::TileTexture:
406 activeView()->SetBackgroundImage( fi.absoluteFilePath().toLatin1().constData(), Aspect_FM_TILED );
408 case Qtx::StretchTexture:
409 activeView()->SetBackgroundImage( fi.absoluteFilePath().toLatin1().constData(), Aspect_FM_STRETCH );
414 activeView()->Update();
420 Updates the active viewport. [ virtual public ]
422 void OCCViewer_ViewPort3d::onUpdate()
424 if ( !activeView().IsNull() )
425 activeView()->Update();
429 Called at 'window fit' transformation. [ virtual protected ]
431 void OCCViewer_ViewPort3d::fitRect( const QRect& rect )
433 if ( !activeView().IsNull() ) {
434 activeView()->WindowFit( rect.left(), rect.top(), rect.right(), rect.bottom() );
435 emit vpTransformed( this );
440 Inits 'zoom' transformation. [ protected ]
442 void OCCViewer_ViewPort3d::startZoomAtPoint( int x, int y )
444 if ( !activeView().IsNull() && isAdvancedZoomingEnabled() )
445 activeView()->StartZoomAtPoint( x, y );
449 Called at 'zoom' transformation. [ virtual protected ]
451 void OCCViewer_ViewPort3d::zoom( int x0, int y0, int x, int y )
453 if ( !activeView().IsNull() ) {
454 // as OCCT respects a sign of only dx,
455 // but we want both signes to be taken into account
456 //activeView()->Zoom( x0, y0, x, y );
457 if ( isAdvancedZoomingEnabled() )
458 activeView()->ZoomAtPoint( x0, y0, x, y );
460 activeView()->Zoom( x0 + y0, 0, x + y, 0 );
461 emit vpTransformed( this );
466 Centers the viewport. [ virtual protected ]
468 void OCCViewer_ViewPort3d::setCenter( int x, int y )
470 if ( !activeView().IsNull() ) {
471 activeView()->Place( x, y, myScale );
472 emit vpTransformed( this );
477 Called at 'pan' transformation. [ virtual protected ]
479 void OCCViewer_ViewPort3d::pan( int dx, int dy )
481 if ( !activeView().IsNull() ) {
482 activeView()->Pan( dx, dy, 1.0 );
483 emit vpTransformed( this );
488 Inits 'rotation' transformation. [ protected ]
490 void OCCViewer_ViewPort3d::startRotation( int x, int y,
491 int theRotationPointType,
492 const gp_Pnt& theSelectedPoint )
494 if ( !activeView().IsNull() ) {
496 //double gx = activeView()->gx;
497 //activeView()->Gravity(gx,gy,gz);
499 switch ( theRotationPointType ) {
500 case OCCViewer_ViewWindow::GRAVITY:
501 activeView()->StartRotation( x, y, 0.45 );
503 case OCCViewer_ViewWindow::SELECTED:
507 activeView()->Size(X,Y);
508 rx = Standard_Real(activeView()->Convert(X));
509 ry = Standard_Real(activeView()->Convert(Y));
511 activeView()->Rotate( 0., 0., 0.,
512 theSelectedPoint.X(),theSelectedPoint.Y(), theSelectedPoint.Z(),
515 Quantity_Ratio zRotationThreshold;
516 zRotation = Standard_False;
517 zRotationThreshold = 0.45;
518 if( zRotationThreshold > 0. ) {
519 Standard_Real dx = Abs(sx - rx/2.);
520 Standard_Real dy = Abs(sy - ry/2.);
521 Standard_Real dd = zRotationThreshold * (rx + ry)/2.;
522 if( dx > dd || dy > dd ) zRotation = Standard_True;
528 // VSR: 10.06.2015: next line commented out - causes ugly blinking on starting rotation with Perspective projection mode
529 //activeView()->DepthFitAll();
534 Rotates the viewport. [ protected ]
536 void OCCViewer_ViewPort3d::rotate( int x, int y,
537 int theRotationPointType,
538 const gp_Pnt& theSelectedPoint )
540 if ( !activeView().IsNull() ) {
541 switch ( theRotationPointType ) {
542 case OCCViewer_ViewWindow::GRAVITY:
543 activeView()->Rotation( x, y );
545 case OCCViewer_ViewWindow::SELECTED:
548 dz = atan2(Standard_Real(x)-rx/2., ry/2.-Standard_Real(y)) -
549 atan2(sx-rx/2.,ry/2.-sy);
553 dx = (Standard_Real(x) - sx) * M_PI/rx;
554 dy = (sy - Standard_Real(y)) * M_PI/ry;
558 activeView()->Rotate( dx, dy, dz,
559 theSelectedPoint.X(),theSelectedPoint.Y(), theSelectedPoint.Z(),
565 emit vpTransformed( this );
567 // setZSize( getZSize() );
571 Resets the viewport after 'rotation'. [ protected ]
573 void OCCViewer_ViewPort3d::endRotation()
575 if ( !activeView().IsNull() ) {
576 activeView()->ZFitAll( 1.0 );
577 #if OCC_VERSION_LARGE <= 0x06070100
578 activeView()->SetZSize( 0.0 );
580 activeView()->Update();
581 emit vpTransformed( this );
586 Repaints the viewport. [ virtual protected ]
588 void OCCViewer_ViewPort3d::paintEvent( QPaintEvent* e )
591 /* X11 : map before show doesn't work */
592 if ( !mapped( activeView() ) )
593 mapView( activeView() );
595 if ( !myWindow.IsNull() ) {
596 #if QT_VERSION < QT_VERSION_CHECK(5, 0, 0)
597 QApplication::syncX();
599 if ( !myPaintersRedrawing ) {
600 #if OCC_VERSION_MAJOR < 7
601 QRect rc = e->rect();
602 activeView()->Redraw( rc.x(), rc.y(), rc.width(), rc.height() );
604 activeView()->Redraw();
608 OCCViewer_ViewPort::paintEvent( e );
613 Resizes the viewport. [ virtual protected ]
615 void OCCViewer_ViewPort3d::resizeEvent( QResizeEvent* e )
617 #if defined WIN32 || QT_VERSION >= QT_VERSION_CHECK(5, 0, 0)
618 /* Win32 : map before first show to avoid flicker */
619 if ( !mapped( activeView() ) )
620 mapView( activeView() );
622 #if QT_VERSION < QT_VERSION_CHECK(5, 0, 0)
623 QApplication::syncX();
625 if ( !activeView().IsNull() )
626 activeView()->MustBeResized();
633 void OCCViewer_ViewPort3d::repaintViewAfterMove( )
635 if ( !activeView().IsNull() ){
636 activeView()->MustBeResized();
641 Fits all objects in view. [ virtual protected ]
643 void OCCViewer_ViewPort3d::fitAll( bool keepScale, bool withZ, bool upd )
645 if ( activeView().IsNull() )
649 myScale = activeView()->Scale();
651 Standard_Real margin = 0.01;
653 #if OCC_VERSION_LARGE > 0x06070100
654 activeView()->FitAll( margin, upd );
656 activeView()->ZFitAll();
658 activeView()->FitAll( margin, withZ, upd );
660 activeView()->SetZSize(0.);
661 emit vpTransformed( this );
665 Resets the view. [ virtual protected ]
667 void OCCViewer_ViewPort3d::reset()
669 // double zsize = getZSize();
670 if ( !activeView().IsNull() ) {
671 activeView()->Reset();
672 emit vpTransformed( this );
673 // setZSize( zsize );
678 Rotate the view in the view plane (orthogonal to the view vector)
680 void OCCViewer_ViewPort3d::rotateXY( double degrees )
682 if ( activeView().IsNull() )
685 int x = width()/2, y = height()/2;
687 activeView()->Convert( x, y, X, Y, Z );
688 activeView()->Rotate( 0, 0, degrees * M_PI / 180., X, Y, Z );
689 emit vpTransformed( this );
693 Set axial scale to the view
695 void OCCViewer_ViewPort3d::setAxialScale( double xScale, double yScale, double zScale )
697 if ( activeView().IsNull() )
700 activeView()->SetAxialScale( xScale, yScale, zScale );
701 emit vpTransformed( this );
705 Passed the handle of native window of the component to CASCADE view. [ private ]
707 bool OCCViewer_ViewPort3d::setWindow( const Handle(V3d_View)& view )
709 if ( !myWindow.IsNull() )
715 attachWindow( view, OCCViewer_VService::CreateWindow( view, winId() ) );
717 myWindow = view->Window();
718 return !myWindow.IsNull();
721 void OCCViewer_ViewPort3d::attachWindow( const Handle(V3d_View)& view,
722 const Handle(Aspect_Window)& window)
724 if (!view.IsNull()) {
725 view->SetWindow( window );
731 Returns the current active view. [ private ]
733 Handle(V3d_View) OCCViewer_ViewPort3d::activeView() const
739 Returns the current inactive view [ private ]
741 /*Handle(V3d_View) OCCViewer_ViewPort3d::inactiveView() const
743 return ( activeView() == myOrthoView ? myPerspView : myOrthoView );
747 Returns 'true' if the given view is mapped to window. [ private ]
749 bool OCCViewer_ViewPort3d::mapped( const Handle(V3d_View)& view ) const
751 return ( !view.IsNull() && view->View()->IsDefined() );
755 Performs synchronization of view parameters with the specified view.
756 Returns \c true if synchronization is done successfully or \c false otherwise.
757 Default implementation does nothing (return \c false)
759 bool OCCViewer_ViewPort3d::synchronize( OCCViewer_ViewPort* view )
762 OCCViewer_ViewPort3d* vp3d = qobject_cast<OCCViewer_ViewPort3d*>( view );
764 bool blocked = blockSignals( false );
765 Handle(V3d_View) aView3d = getView();
766 Handle(V3d_View) aRefView3d = vp3d->getView();
767 aView3d->SetImmediateUpdate( Standard_False );
768 #if OCC_VERSION_LARGE > 0x06070100
769 aView3d->Camera()->Copy( aRefView3d->Camera() );
771 aView3d->SetViewMapping( aRefView3d->ViewMapping() );
772 aView3d->SetViewOrientation( aRefView3d->ViewOrientation() );
775 aView3d->SetImmediateUpdate( Standard_True );
777 blockSignals( blocked );
784 * Show/Hide static triedron
786 void OCCViewer_ViewPort3d::showStaticTrihedron( bool on )
788 Handle(V3d_View) aView = activeView();
789 if ( !aView ) return;
792 aView->ZBufferTriedronSetup();
793 aView->TriedronDisplay( Aspect_TOTP_LEFT_LOWER, Quantity_NOC_WHITE, 0.05, V3d_ZBUFFER );
795 aView->TriedronErase();
801 * Create default cursor with a specific shape
803 void OCCViewer_ViewPort3d::setDefaultCursor( Qt::CursorShape theCursorShape )
806 myCursor = new QCursor();
808 myCursor->setShape( theCursorShape );
812 * Get default cursor with a specific shape
814 QCursor* OCCViewer_ViewPort3d::getDefaultCursor() const
820 * Set default parameters from preferences
822 void OCCViewer_ViewPort3d::setDefaultParams()
824 setBackground( Qtx::BackgroundData( Qt::black ) ); // set default background
826 // get ray tracing parameters from preferences
827 int aDepth = SUIT_Session::session()->resourceMgr()->integerValue( "OCCViewer", "rt_depth", 3 );
828 bool aReflection = SUIT_Session::session()->resourceMgr()->booleanValue( "OCCViewer", "rt_reflection", true );
829 bool anAntialiasing = SUIT_Session::session()->resourceMgr()->booleanValue( "OCCViewer", "rt_antialiasing", false );
830 bool aShadow = SUIT_Session::session()->resourceMgr()->booleanValue( "OCCViewer", "rt_shadow", true );
831 bool aTransparentShadow = SUIT_Session::session()->resourceMgr()->booleanValue( "OCCViewer", "rt_trans_shadow", true );
833 Graphic3d_RenderingParams& aParams = myActiveView->ChangeRenderingParams();
834 aParams.RaytracingDepth = aDepth;
835 aParams.IsReflectionEnabled = aReflection;
836 aParams.IsAntialiasingEnabled = anAntialiasing;
837 aParams.IsShadowEnabled = aShadow;
838 aParams.IsTransparentShadowEnabled = aTransparentShadow;
839 myActiveView->Redraw();