1 // Copyright (C) 2007-2015 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 #include <Visual3d_View.hxx>
43 #include <V3d_Viewer.hxx>
45 #if OCC_VERSION_LARGE > 0x06070100
46 #include <V3d_View.hxx>
48 #include <V3d_PerspectiveView.hxx>
49 #include <V3d_OrthographicView.hxx>
52 #include "utilities.h"
55 #include <WNT_Window.hxx>
57 //#include <Xw_Window.hxx>
60 static double rx = 0.;
61 static double ry = 0.;
64 static Standard_Boolean zRotation = Standard_False;
66 //#include <Standard_Version.hxx>
71 OCCViewer_ViewPort3d::OCCViewer_ViewPort3d( QWidget* parent, const Handle( V3d_Viewer)& viewer, V3d_TypeOfView type )
72 : OCCViewer_ViewPort( parent ),
75 myIsAdvancedZoomingEnabled( false )
77 // VSR: 01/07/2010 commented to avoid SIGSEGV at SALOME exit
80 #if OCC_VERSION_LARGE > 0x06070100
81 myActiveView = new V3d_View( viewer, type );
83 if ( type == V3d_ORTHOGRAPHIC ) {
84 myOrthoView = new V3d_OrthographicView( viewer );
85 myActiveView = myOrthoView;
88 myPerspView = new V3d_PerspectiveView( viewer );
89 myActiveView = myPerspView;
101 OCCViewer_ViewPort3d::~OCCViewer_ViewPort3d()
110 Handle(V3d_View) aView = activeView();
116 Activates the desired 'type' of view in the viewer
117 ( view of 'type' is created if it doesn't exist ). [ public ]
119 /*void OCCViewer_ViewPort3d::setActive( V3d_TypeOfView type )
121 if ( activeView().IsNull() )
124 if ( activeView()->Type() != type )
126 if ( type == V3d_ORTHOGRAPHIC )
127 setView( myOrthoView );
128 if ( type == V3d_PERSPECTIVE )
129 setView( myPerspView );
134 Maps CasCade 'view' to this viewport. [ private ]
136 bool OCCViewer_ViewPort3d::mapView( const Handle(V3d_View)& view )
138 if ( !setWindow( view ) )
141 if ( !mapped( view ) ) {
142 view->SetWindow( myWindow );
143 if ( view != activeView() )
144 view->View()->Deactivate();
147 emit( vpMapped(this) );
155 Sets new CASCADE view on viewport. Returns the previous active view. [ public ]
157 Handle( V3d_View ) OCCViewer_ViewPort3d::setView( const Handle( V3d_View )& view )
159 /* map the new view */
160 if ( view == activeView() || !mapView( view ) )
163 /* activate the new view*/
164 Handle( V3d_View ) oldView = activeView();
165 if ( !oldView.IsNull() ) {
166 if (oldView->View()->IsDefined())
167 oldView->View()->Deactivate();
168 view->SetBackgroundColor( oldView->BackgroundColor() );
171 view->View()->Activate();
177 Returns CasCade 3D view. [ public ]
179 Handle(V3d_View) OCCViewer_ViewPort3d::getView() const
185 Returns CasCade 3D viewer [ public ]
187 Handle(V3d_Viewer) OCCViewer_ViewPort3d::getViewer() const
189 Handle(V3d_Viewer) viewer;
190 if ( !activeView().IsNull() )
191 viewer = activeView()->Viewer();
196 Syncronizes visual state of this viewport with 'ref'
197 ( scale, projection, eye etc ) Returns 'true' if copied OK,
198 'false' otherwise. [ virtual public ]
200 bool OCCViewer_ViewPort3d::syncronize( const OCCViewer_ViewPort3d* ref )
202 OCCViewer_ViewPort3d* ref3d = (OCCViewer_ViewPort3d*)ref;
203 Handle(V3d_View) refView = ref3d->getView();
204 Handle(V3d_View) tgtView = getView();
206 /* Syncronize view types */
207 /* if ( tgtView->Type() != refView->Type() )
209 setActive( refView->Type() );
213 /* The following params are copied:
214 - view type( ortho/persp )
215 - position of view point
216 - orientation of high point
217 - position of the eye
224 /* we'll update after setting all params */
225 tgtView->SetImmediateUpdate( Standard_False );
228 if ( refView->Type() == V3d_PERSPECTIVE )
229 tgtView->SetFocale( refView->Focale() );
232 Standard_Real x, y, z;
233 refView->At( x, y, z ); tgtView->SetAt( x, y, z );
234 refView->Up( x, y, z ); tgtView->SetUp( x, y, z );
235 refView->Eye( x, y, z ); tgtView->SetEye( x, y, z );
236 refView->Proj( x, y, z ); tgtView->SetProj( x, y, z );
237 #if OCC_VERSION_LARGE <= 0x06070100
238 refView->Center( x, y ); tgtView->SetCenter( x, y );
240 tgtView->SetScale( refView->Scale() );
241 tgtView->SetTwist( refView->Twist() );
245 tgtView->SetImmediateUpdate( Standard_True );
251 Returns Z-size of this view. [ public ]
253 double OCCViewer_ViewPort3d::getZSize() const
255 if ( !activeView().IsNull() )
256 return activeView()->ZSize();
261 Sets Z-size of this view ( for both orthographic and perspective ). [ public ]
263 void OCCViewer_ViewPort3d::setZSize( double zsize )
265 myActiveView->SetZSize( zsize );
266 /* if ( !myOrthoView.IsNull() )
267 myOrthoView->SetZSize( zsize );
268 if ( !myPerspView.IsNull() )
269 myPerspView->SetZSize( zsize );*/
273 Get axial scale to the view
275 void OCCViewer_ViewPort3d::getAxialScale( double& xScale, double& yScale, double& zScale )
277 xScale = yScale = zScale = 1.;
279 if ( !activeView().IsNull() )
280 activeView()->AxialScale( xScale, yScale, zScale );
284 Returns the background color [ virtual public ] [ obsolete ]
286 QColor OCCViewer_ViewPort3d::backgroundColor() const
288 return background().color();
292 Sets the background color [ virtual public ] [ obsolete ]
294 void OCCViewer_ViewPort3d::setBackgroundColor( const QColor& color )
296 Qtx::BackgroundData bg = background();
297 bg.setColor( color );
302 Returns the background data
304 Qtx::BackgroundData OCCViewer_ViewPort3d::background() const
310 Sets the background data
312 void OCCViewer_ViewPort3d::setBackground( const Qtx::BackgroundData& bgData )
314 if ( bgData.isValid() ) {
315 myBackground = bgData;
317 emit vpChangeBackground( myBackground );
321 void OCCViewer_ViewPort3d::updateBackground()
323 if ( activeView().IsNull() ) return;
324 if ( !myBackground.isValid() ) return;
326 switch ( myBackground.mode() ) {
327 case Qtx::ColorBackground:
329 QColor c = myBackground.color();
331 // Unset texture should be done here
333 Quantity_Color qCol( c.red()/255., c.green()/255., c.blue()/255., Quantity_TOC_RGB );
334 activeView()->SetBgGradientStyle( Aspect_GFM_NONE ); // cancel gradient background
335 activeView()->SetBgImageStyle( Aspect_FM_NONE ); // cancel texture background
336 // then change background color
337 activeView()->SetBackgroundColor( qCol );
339 activeView()->Update();
343 case Qtx::SimpleGradientBackground:
346 int type = myBackground.gradient( c1, c2 );
347 if ( c1.isValid() && type >= OCCViewer_Viewer::HorizontalGradient && type <= OCCViewer_Viewer::LastGradient ) {
348 // Unset texture should be done here
350 // Get colors and set-up gradiented background
351 if ( !c2.isValid() ) c2 = c1;
352 Quantity_Color qCol1( c1.red()/255., c1.green()/255., c1.blue()/255., Quantity_TOC_RGB );
353 Quantity_Color qCol2( c2.red()/255., c2.green()/255., c2.blue()/255., Quantity_TOC_RGB );
354 activeView()->SetBgImageStyle( Aspect_FM_NONE ); // cancel texture background
356 case OCCViewer_Viewer::HorizontalGradient:
357 activeView()->SetBgGradientColors( qCol1, qCol2, Aspect_GFM_HOR, Standard_True );
359 case OCCViewer_Viewer::VerticalGradient:
360 activeView()->SetBgGradientColors( qCol1, qCol2, Aspect_GFM_VER, Standard_True );
362 case OCCViewer_Viewer::Diagonal1Gradient:
363 activeView()->SetBgGradientColors( qCol1, qCol2, Aspect_GFM_DIAG1, Standard_True );
365 case OCCViewer_Viewer::Diagonal2Gradient:
366 activeView()->SetBgGradientColors( qCol1, qCol2, Aspect_GFM_DIAG2, Standard_True );
368 case OCCViewer_Viewer::Corner1Gradient:
369 activeView()->SetBgGradientColors( qCol1, qCol2, Aspect_GFM_CORNER1, Standard_True );
371 case OCCViewer_Viewer::Corner2Gradient:
372 activeView()->SetBgGradientColors( qCol1, qCol2, Aspect_GFM_CORNER2, Standard_True );
374 case OCCViewer_Viewer::Corner3Gradient:
375 activeView()->SetBgGradientColors( qCol1, qCol2, Aspect_GFM_CORNER3, Standard_True );
377 case OCCViewer_Viewer::Corner4Gradient:
378 activeView()->SetBgGradientColors( qCol1, qCol2, Aspect_GFM_CORNER4, Standard_True );
386 case Qtx::CustomGradientBackground:
388 // NOT IMPLEMENTED YET
394 if ( myBackground.isTextureShown() ) {
396 int textureMode = myBackground.texture( fileName );
397 QFileInfo fi( fileName );
398 if ( !fileName.isEmpty() && fi.exists() ) {
399 // set texture image: file name and fill mode
400 switch ( textureMode ) {
401 case Qtx::CenterTexture:
402 activeView()->SetBackgroundImage( fi.absoluteFilePath().toLatin1().constData(), Aspect_FM_CENTERED );
404 case Qtx::TileTexture:
405 activeView()->SetBackgroundImage( fi.absoluteFilePath().toLatin1().constData(), Aspect_FM_TILED );
407 case Qtx::StretchTexture:
408 activeView()->SetBackgroundImage( fi.absoluteFilePath().toLatin1().constData(), Aspect_FM_STRETCH );
413 activeView()->Update();
419 Updates the active viewport. [ virtual public ]
421 void OCCViewer_ViewPort3d::onUpdate()
423 if ( !activeView().IsNull() )
424 activeView()->Update();
428 Called at 'window fit' transformation. [ virtual protected ]
430 void OCCViewer_ViewPort3d::fitRect( const QRect& rect )
432 if ( !activeView().IsNull() ) {
433 activeView()->WindowFit( rect.left(), rect.top(), rect.right(), rect.bottom() );
434 emit vpTransformed( this );
439 Inits 'zoom' transformation. [ protected ]
441 void OCCViewer_ViewPort3d::startZoomAtPoint( int x, int y )
443 if ( !activeView().IsNull() && isAdvancedZoomingEnabled() )
444 activeView()->StartZoomAtPoint( x, y );
448 Called at 'zoom' transformation. [ virtual protected ]
450 void OCCViewer_ViewPort3d::zoom( int x0, int y0, int x, int y )
452 if ( !activeView().IsNull() ) {
453 // as OCCT respects a sign of only dx,
454 // but we want both signes to be taken into account
455 //activeView()->Zoom( x0, y0, x, y );
456 if ( isAdvancedZoomingEnabled() )
457 activeView()->ZoomAtPoint( x0, y0, x, y );
459 activeView()->Zoom( x0 + y0, 0, x + y, 0 );
460 emit vpTransformed( this );
465 Centers the viewport. [ virtual protected ]
467 void OCCViewer_ViewPort3d::setCenter( int x, int y )
469 if ( !activeView().IsNull() ) {
470 activeView()->Place( x, y, myScale );
471 emit vpTransformed( this );
476 Called at 'pan' transformation. [ virtual protected ]
478 void OCCViewer_ViewPort3d::pan( int dx, int dy )
480 if ( !activeView().IsNull() ) {
481 activeView()->Pan( dx, dy, 1.0 );
482 emit vpTransformed( this );
487 Inits 'rotation' transformation. [ protected ]
489 void OCCViewer_ViewPort3d::startRotation( int x, int y,
490 int theRotationPointType,
491 const gp_Pnt& theSelectedPoint )
493 if ( !activeView().IsNull() ) {
495 //double gx = activeView()->gx;
496 //activeView()->Gravity(gx,gy,gz);
498 switch ( theRotationPointType ) {
499 case OCCViewer_ViewWindow::GRAVITY:
500 activeView()->StartRotation( x, y, 0.45 );
502 case OCCViewer_ViewWindow::SELECTED:
506 activeView()->Size(X,Y);
507 rx = Standard_Real(activeView()->Convert(X));
508 ry = Standard_Real(activeView()->Convert(Y));
510 activeView()->Rotate( 0., 0., 0.,
511 theSelectedPoint.X(),theSelectedPoint.Y(), theSelectedPoint.Z(),
514 Quantity_Ratio zRotationThreshold;
515 zRotation = Standard_False;
516 zRotationThreshold = 0.45;
517 if( zRotationThreshold > 0. ) {
518 Standard_Real dx = Abs(sx - rx/2.);
519 Standard_Real dy = Abs(sy - ry/2.);
520 Standard_Real dd = zRotationThreshold * (rx + ry)/2.;
521 if( dx > dd || dy > dd ) zRotation = Standard_True;
527 // VSR: 10.06.2015: next line commented out - causes ugly blinking on starting rotation with Perspective projection mode
528 //activeView()->DepthFitAll();
533 Rotates the viewport. [ protected ]
535 void OCCViewer_ViewPort3d::rotate( int x, int y,
536 int theRotationPointType,
537 const gp_Pnt& theSelectedPoint )
539 if ( !activeView().IsNull() ) {
540 switch ( theRotationPointType ) {
541 case OCCViewer_ViewWindow::GRAVITY:
542 activeView()->Rotation( x, y );
544 case OCCViewer_ViewWindow::SELECTED:
547 dz = atan2(Standard_Real(x)-rx/2., ry/2.-Standard_Real(y)) -
548 atan2(sx-rx/2.,ry/2.-sy);
552 dx = (Standard_Real(x) - sx) * M_PI/rx;
553 dy = (sy - Standard_Real(y)) * M_PI/ry;
557 activeView()->Rotate( dx, dy, dz,
558 theSelectedPoint.X(),theSelectedPoint.Y(), theSelectedPoint.Z(),
564 emit vpTransformed( this );
566 // setZSize( getZSize() );
570 Resets the viewport after 'rotation'. [ protected ]
572 void OCCViewer_ViewPort3d::endRotation()
574 if ( !activeView().IsNull() ) {
575 activeView()->ZFitAll( 1.0 );
576 #if OCC_VERSION_LARGE <= 0x06070100
577 activeView()->SetZSize( 0.0 );
579 activeView()->Update();
580 emit vpTransformed( this );
585 Repaints the viewport. [ virtual protected ]
587 void OCCViewer_ViewPort3d::paintEvent( QPaintEvent* e )
590 /* X11 : map before show doesn't work */
591 if ( !mapped( activeView() ) )
592 mapView( activeView() );
594 if ( !myWindow.IsNull() ) {
595 QApplication::syncX();
596 QRect rc = e->rect();
597 if ( !myPaintersRedrawing )
598 activeView()->Redraw( rc.x(), rc.y(), rc.width(), rc.height() );
600 OCCViewer_ViewPort::paintEvent( e );
605 Resizes the viewport. [ virtual protected ]
607 void OCCViewer_ViewPort3d::resizeEvent( QResizeEvent* e )
610 /* Win32 : map before first show to avoid flicker */
611 if ( !mapped( activeView() ) )
612 mapView( activeView() );
614 QApplication::syncX();
615 if ( !activeView().IsNull() )
616 activeView()->MustBeResized();
623 void OCCViewer_ViewPort3d::repaintViewAfterMove( )
625 if ( !activeView().IsNull() ){
626 activeView()->MustBeResized();
631 Fits all objects in view. [ virtual protected ]
633 void OCCViewer_ViewPort3d::fitAll( bool keepScale, bool withZ, bool upd )
635 if ( activeView().IsNull() )
639 myScale = activeView()->Scale();
641 Standard_Real margin = 0.01;
643 #if OCC_VERSION_LARGE > 0x06070100
644 activeView()->FitAll( margin, upd );
646 activeView()->ZFitAll();
648 activeView()->FitAll( margin, withZ, upd );
650 activeView()->SetZSize(0.);
651 emit vpTransformed( this );
655 Resets the view. [ virtual protected ]
657 void OCCViewer_ViewPort3d::reset()
659 // double zsize = getZSize();
660 if ( !activeView().IsNull() ) {
661 activeView()->Reset();
662 emit vpTransformed( this );
663 // setZSize( zsize );
668 Rotate the view in the view plane (orthogonal to the view vector)
670 void OCCViewer_ViewPort3d::rotateXY( double degrees )
672 if ( activeView().IsNull() )
675 int x = width()/2, y = height()/2;
677 activeView()->Convert( x, y, X, Y, Z );
678 activeView()->Rotate( 0, 0, degrees * M_PI / 180., X, Y, Z );
679 emit vpTransformed( this );
683 Set axial scale to the view
685 void OCCViewer_ViewPort3d::setAxialScale( double xScale, double yScale, double zScale )
687 if ( activeView().IsNull() )
690 activeView()->SetAxialScale( xScale, yScale, zScale );
691 emit vpTransformed( this );
695 Passed the handle of native window of the component to CASCADE view. [ private ]
697 bool OCCViewer_ViewPort3d::setWindow( const Handle(V3d_View)& view )
699 if ( !myWindow.IsNull() )
705 attachWindow( view, OCCViewer_VService::CreateWindow( view, winId() ) );
707 myWindow = view->Window();
708 return !myWindow.IsNull();
711 void OCCViewer_ViewPort3d::attachWindow( const Handle(V3d_View)& view,
712 const Handle(Aspect_Window)& window)
714 if (!view.IsNull()) {
715 view->SetWindow( window );
721 Returns the current active view. [ private ]
723 Handle(V3d_View) OCCViewer_ViewPort3d::activeView() const
729 Returns the current inactive view [ private ]
731 /*Handle(V3d_View) OCCViewer_ViewPort3d::inactiveView() const
733 return ( activeView() == myOrthoView ? myPerspView : myOrthoView );
737 Returns 'true' if the given view is mapped to window. [ private ]
739 bool OCCViewer_ViewPort3d::mapped( const Handle(V3d_View)& view ) const
741 return ( !view.IsNull() && view->View()->IsDefined() );
745 Performs synchronization of view parameters with the specified view.
746 Returns \c true if synchronization is done successfully or \c false otherwise.
747 Default implementation does nothing (return \c false)
749 bool OCCViewer_ViewPort3d::synchronize( OCCViewer_ViewPort* view )
752 OCCViewer_ViewPort3d* vp3d = qobject_cast<OCCViewer_ViewPort3d*>( view );
754 bool blocked = blockSignals( false );
755 Handle(V3d_View) aView3d = getView();
756 Handle(V3d_View) aRefView3d = vp3d->getView();
757 aView3d->SetImmediateUpdate( Standard_False );
758 #if OCC_VERSION_LARGE > 0x06070100
759 aView3d->Camera()->Copy( aRefView3d->Camera() );
761 aView3d->SetViewMapping( aRefView3d->ViewMapping() );
762 aView3d->SetViewOrientation( aRefView3d->ViewOrientation() );
765 aView3d->SetImmediateUpdate( Standard_True );
767 blockSignals( blocked );
774 * Show/Hide static triedron
776 void OCCViewer_ViewPort3d::showStaticTrihedron( bool on )
778 Handle(V3d_View) aView = activeView();
779 if ( !aView ) return;
782 aView->ZBufferTriedronSetup();
783 aView->TriedronDisplay( Aspect_TOTP_LEFT_LOWER, Quantity_NOC_WHITE, 0.05, V3d_ZBUFFER );
785 aView->TriedronErase();
791 * Create default cursor with a specific shape
793 void OCCViewer_ViewPort3d::setDefaultCursor( Qt::CursorShape theCursorShape )
796 myCursor = new QCursor();
798 myCursor->setShape( theCursorShape );
802 * Get default cursor with a specific shape
804 QCursor* OCCViewer_ViewPort3d::getDefaultCursor() const
810 * Set default parameters from preferences
812 void OCCViewer_ViewPort3d::setDefaultParams()
814 setBackground( Qtx::BackgroundData( Qt::black ) ); // set default background
816 // get ray tracing parameters from preferences
817 int aDepth = SUIT_Session::session()->resourceMgr()->integerValue( "OCCViewer", "rt_depth", 3 );
818 bool aReflection = SUIT_Session::session()->resourceMgr()->booleanValue( "OCCViewer", "rt_reflection", true );
819 bool anAntialiasing = SUIT_Session::session()->resourceMgr()->booleanValue( "OCCViewer", "rt_antialiasing", false );
820 bool aShadow = SUIT_Session::session()->resourceMgr()->booleanValue( "OCCViewer", "rt_shadow", true );
821 bool aTransparentShadow = SUIT_Session::session()->resourceMgr()->booleanValue( "OCCViewer", "rt_trans_shadow", true );
823 Graphic3d_RenderingParams& aParams = myActiveView->ChangeRenderingParams();
824 aParams.RaytracingDepth = aDepth;
825 aParams.IsReflectionEnabled = aReflection;
826 aParams.IsAntialiasingEnabled = anAntialiasing;
827 aParams.IsShadowEnabled = aShadow;
828 aParams.IsTransparentShadowEnabled = aTransparentShadow;
829 myActiveView->Redraw();