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() ) );
631 emit vpResizeEvent( e );
637 void OCCViewer_ViewPort3d::repaintViewAfterMove( )
639 if ( !activeView().IsNull() ){
640 activeView()->MustBeResized();
645 Fits all objects in view. [ virtual protected ]
647 void OCCViewer_ViewPort3d::fitAll( bool keepScale, bool withZ, bool upd )
649 if ( activeView().IsNull() )
653 myScale = activeView()->Scale();
655 Standard_Real margin = 0.01;
657 #if OCC_VERSION_LARGE > 0x06070100
658 activeView()->FitAll( margin, upd );
659 #if OCC_VERSION_LARGE <= 0x07000000
661 activeView()->ZFitAll();
664 activeView()->FitAll( margin, withZ, upd );
665 activeView()->SetZSize(0.);
667 emit vpTransformed( this );
671 Resets the view. [ virtual protected ]
673 void OCCViewer_ViewPort3d::reset()
675 // double zsize = getZSize();
676 if ( !activeView().IsNull() ) {
677 activeView()->Reset();
678 emit vpTransformed( this );
679 // setZSize( zsize );
684 Rotate the view in the view plane (orthogonal to the view vector)
686 void OCCViewer_ViewPort3d::rotateXY( double degrees )
688 if ( activeView().IsNull() )
691 int x = width()/2, y = height()/2;
693 activeView()->Convert( x, y, X, Y, Z );
694 activeView()->Rotate( 0, 0, degrees * M_PI / 180., X, Y, Z );
695 emit vpTransformed( this );
699 Set axial scale to the view
701 void OCCViewer_ViewPort3d::setAxialScale( double xScale, double yScale, double zScale )
703 if ( activeView().IsNull() )
706 activeView()->SetAxialScale( xScale, yScale, zScale );
707 emit vpTransformed( this );
711 Passed the handle of native window of the component to CASCADE view. [ private ]
713 bool OCCViewer_ViewPort3d::setWindow( const Handle(V3d_View)& view )
715 if ( !myWindow.IsNull() )
721 attachWindow( view, OCCViewer_VService::CreateWindow( view, winId() ) );
723 myWindow = view->Window();
724 return !myWindow.IsNull();
727 void OCCViewer_ViewPort3d::attachWindow( const Handle(V3d_View)& view,
728 const Handle(Aspect_Window)& window)
730 if (!view.IsNull()) {
731 view->SetWindow( window );
737 Returns the current active view. [ private ]
739 Handle(V3d_View) OCCViewer_ViewPort3d::activeView() const
745 Returns the current inactive view [ private ]
747 /*Handle(V3d_View) OCCViewer_ViewPort3d::inactiveView() const
749 return ( activeView() == myOrthoView ? myPerspView : myOrthoView );
753 Returns 'true' if the given view is mapped to window. [ private ]
755 bool OCCViewer_ViewPort3d::mapped( const Handle(V3d_View)& view ) const
757 return ( !view.IsNull() && view->View()->IsDefined() );
761 Performs synchronization of view parameters with the specified view.
762 Returns \c true if synchronization is done successfully or \c false otherwise.
763 Default implementation does nothing (return \c false)
765 bool OCCViewer_ViewPort3d::synchronize( OCCViewer_ViewPort* view )
768 OCCViewer_ViewPort3d* vp3d = qobject_cast<OCCViewer_ViewPort3d*>( view );
770 bool blocked = blockSignals( false );
771 Handle(V3d_View) aView3d = getView();
772 Handle(V3d_View) aRefView3d = vp3d->getView();
773 aView3d->SetImmediateUpdate( Standard_False );
774 #if OCC_VERSION_LARGE > 0x06070100
775 aView3d->Camera()->Copy( aRefView3d->Camera() );
777 aView3d->SetViewMapping( aRefView3d->ViewMapping() );
778 aView3d->SetViewOrientation( aRefView3d->ViewOrientation() );
780 #if OCC_VERSION_LARGE <= 0x07000000
783 aView3d->SetImmediateUpdate( Standard_True );
785 blockSignals( blocked );
792 * Show/Hide static triedron
794 void OCCViewer_ViewPort3d::showStaticTrihedron( bool on )
796 Handle(V3d_View) aView = activeView();
797 if ( !aView ) return;
800 aView->ZBufferTriedronSetup();
801 aView->TriedronDisplay( Aspect_TOTP_LEFT_LOWER, Quantity_NOC_WHITE, 0.05, V3d_ZBUFFER );
803 aView->TriedronErase();
809 * Create default cursor with a specific shape
811 void OCCViewer_ViewPort3d::setDefaultCursor( Qt::CursorShape theCursorShape )
814 myCursor = new QCursor();
816 myCursor->setShape( theCursorShape );
820 * Get default cursor with a specific shape
822 QCursor* OCCViewer_ViewPort3d::getDefaultCursor() const
828 * Set default parameters from preferences
830 void OCCViewer_ViewPort3d::setDefaultParams()
832 setBackground( Qtx::BackgroundData( Qt::black ) ); // set default background
834 // get ray tracing parameters from preferences
835 int aDepth = SUIT_Session::session()->resourceMgr()->integerValue( "OCCViewer", "rt_depth", 3 );
836 bool aReflection = SUIT_Session::session()->resourceMgr()->booleanValue( "OCCViewer", "rt_reflection", true );
837 bool anAntialiasing = SUIT_Session::session()->resourceMgr()->booleanValue( "OCCViewer", "rt_antialiasing", false );
838 bool aShadow = SUIT_Session::session()->resourceMgr()->booleanValue( "OCCViewer", "rt_shadow", true );
839 bool aTransparentShadow = SUIT_Session::session()->resourceMgr()->booleanValue( "OCCViewer", "rt_trans_shadow", true );
841 Graphic3d_RenderingParams& aParams = myActiveView->ChangeRenderingParams();
842 aParams.RaytracingDepth = aDepth;
843 aParams.IsReflectionEnabled = aReflection;
844 aParams.IsAntialiasingEnabled = anAntialiasing;
845 aParams.IsShadowEnabled = aShadow;
846 aParams.IsTransparentShadowEnabled = aTransparentShadow;
847 myActiveView->Redraw();