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 );
253 Returns Z-size of this view. [ public ]
255 double OCCViewer_ViewPort3d::getZSize() const
257 if ( !activeView().IsNull() )
258 return activeView()->ZSize();
263 Sets Z-size of this view ( for both orthographic and perspective ). [ public ]
265 void OCCViewer_ViewPort3d::setZSize( double zsize )
267 myActiveView->SetZSize( zsize );
268 /* if ( !myOrthoView.IsNull() )
269 myOrthoView->SetZSize( zsize );
270 if ( !myPerspView.IsNull() )
271 myPerspView->SetZSize( zsize );*/
275 Get axial scale to the view
277 void OCCViewer_ViewPort3d::getAxialScale( double& xScale, double& yScale, double& zScale )
279 xScale = yScale = zScale = 1.;
281 if ( !activeView().IsNull() )
282 activeView()->AxialScale( xScale, yScale, zScale );
286 Returns the background color [ virtual public ] [ obsolete ]
288 QColor OCCViewer_ViewPort3d::backgroundColor() const
290 return background().color();
294 Sets the background color [ virtual public ] [ obsolete ]
296 void OCCViewer_ViewPort3d::setBackgroundColor( const QColor& color )
298 Qtx::BackgroundData bg = background();
299 bg.setColor( color );
304 Returns the background data
306 Qtx::BackgroundData OCCViewer_ViewPort3d::background() const
312 Sets the background data
314 void OCCViewer_ViewPort3d::setBackground( const Qtx::BackgroundData& bgData )
316 if ( bgData.isValid() ) {
317 myBackground = bgData;
319 emit vpChangeBackground( myBackground );
323 void OCCViewer_ViewPort3d::updateBackground()
325 if ( activeView().IsNull() ) return;
326 if ( !myBackground.isValid() ) return;
328 switch ( myBackground.mode() ) {
329 case Qtx::ColorBackground:
331 QColor c = myBackground.color();
333 // Unset texture should be done here
335 Quantity_Color qCol( c.red()/255., c.green()/255., c.blue()/255., Quantity_TOC_RGB );
336 activeView()->SetBgGradientStyle( Aspect_GFM_NONE ); // cancel gradient background
337 activeView()->SetBgImageStyle( Aspect_FM_NONE ); // cancel texture background
338 // then change background color
339 activeView()->SetBackgroundColor( qCol );
341 activeView()->Update();
345 case Qtx::SimpleGradientBackground:
348 int type = myBackground.gradient( c1, c2 );
349 if ( c1.isValid() && type >= OCCViewer_Viewer::HorizontalGradient && type <= OCCViewer_Viewer::LastGradient ) {
350 // Unset texture should be done here
352 // Get colors and set-up gradiented background
353 if ( !c2.isValid() ) c2 = c1;
354 Quantity_Color qCol1( c1.red()/255., c1.green()/255., c1.blue()/255., Quantity_TOC_RGB );
355 Quantity_Color qCol2( c2.red()/255., c2.green()/255., c2.blue()/255., Quantity_TOC_RGB );
356 activeView()->SetBgImageStyle( Aspect_FM_NONE ); // cancel texture background
358 case OCCViewer_Viewer::HorizontalGradient:
359 activeView()->SetBgGradientColors( qCol1, qCol2, Aspect_GFM_HOR, Standard_True );
361 case OCCViewer_Viewer::VerticalGradient:
362 activeView()->SetBgGradientColors( qCol1, qCol2, Aspect_GFM_VER, Standard_True );
364 case OCCViewer_Viewer::Diagonal1Gradient:
365 activeView()->SetBgGradientColors( qCol1, qCol2, Aspect_GFM_DIAG1, Standard_True );
367 case OCCViewer_Viewer::Diagonal2Gradient:
368 activeView()->SetBgGradientColors( qCol1, qCol2, Aspect_GFM_DIAG2, Standard_True );
370 case OCCViewer_Viewer::Corner1Gradient:
371 activeView()->SetBgGradientColors( qCol1, qCol2, Aspect_GFM_CORNER1, Standard_True );
373 case OCCViewer_Viewer::Corner2Gradient:
374 activeView()->SetBgGradientColors( qCol1, qCol2, Aspect_GFM_CORNER2, Standard_True );
376 case OCCViewer_Viewer::Corner3Gradient:
377 activeView()->SetBgGradientColors( qCol1, qCol2, Aspect_GFM_CORNER3, Standard_True );
379 case OCCViewer_Viewer::Corner4Gradient:
380 activeView()->SetBgGradientColors( qCol1, qCol2, Aspect_GFM_CORNER4, Standard_True );
388 case Qtx::CustomGradientBackground:
390 // NOT IMPLEMENTED YET
396 if ( myBackground.isTextureShown() ) {
398 int textureMode = myBackground.texture( fileName );
399 QFileInfo fi( fileName );
400 if ( !fileName.isEmpty() && fi.exists() ) {
401 // set texture image: file name and fill mode
402 switch ( textureMode ) {
403 case Qtx::CenterTexture:
404 activeView()->SetBackgroundImage( fi.absoluteFilePath().toLatin1().constData(), Aspect_FM_CENTERED );
406 case Qtx::TileTexture:
407 activeView()->SetBackgroundImage( fi.absoluteFilePath().toLatin1().constData(), Aspect_FM_TILED );
409 case Qtx::StretchTexture:
410 activeView()->SetBackgroundImage( fi.absoluteFilePath().toLatin1().constData(), Aspect_FM_STRETCH );
415 activeView()->Update();
421 Updates the active viewport. [ virtual public ]
423 void OCCViewer_ViewPort3d::onUpdate()
425 if ( !activeView().IsNull() )
426 activeView()->Update();
430 Called at 'window fit' transformation. [ virtual protected ]
432 void OCCViewer_ViewPort3d::fitRect( const QRect& rect )
434 if ( !activeView().IsNull() ) {
435 activeView()->WindowFit( rect.left(), rect.top(), rect.right(), rect.bottom() );
436 emit vpTransformed( this );
441 Inits 'zoom' transformation. [ protected ]
443 void OCCViewer_ViewPort3d::startZoomAtPoint( int x, int y )
445 if ( !activeView().IsNull() && isAdvancedZoomingEnabled() )
446 activeView()->StartZoomAtPoint( x, y );
450 Called at 'zoom' transformation. [ virtual protected ]
452 void OCCViewer_ViewPort3d::zoom( int x0, int y0, int x, int y )
454 if ( !activeView().IsNull() ) {
455 // as OCCT respects a sign of only dx,
456 // but we want both signes to be taken into account
457 //activeView()->Zoom( x0, y0, x, y );
458 if ( isAdvancedZoomingEnabled() )
459 activeView()->ZoomAtPoint( x0, y0, x, y );
461 activeView()->Zoom( x0 + y0, 0, x + y, 0 );
462 emit vpTransformed( this );
467 Centers the viewport. [ virtual protected ]
469 void OCCViewer_ViewPort3d::setCenter( int x, int y )
471 if ( !activeView().IsNull() ) {
472 activeView()->Place( x, y, myScale );
473 emit vpTransformed( this );
478 Called at 'pan' transformation. [ virtual protected ]
480 void OCCViewer_ViewPort3d::pan( int dx, int dy )
482 if ( !activeView().IsNull() ) {
483 activeView()->Pan( dx, dy, 1.0 );
484 emit vpTransformed( this );
489 Inits 'rotation' transformation. [ protected ]
491 void OCCViewer_ViewPort3d::startRotation( int x, int y,
492 int theRotationPointType,
493 const gp_Pnt& theSelectedPoint )
495 if ( !activeView().IsNull() ) {
497 //double gx = activeView()->gx;
498 //activeView()->Gravity(gx,gy,gz);
500 switch ( theRotationPointType ) {
501 case OCCViewer_ViewWindow::GRAVITY:
502 activeView()->StartRotation( x, y, 0.45 );
504 case OCCViewer_ViewWindow::SELECTED:
508 activeView()->Size(X,Y);
509 rx = Standard_Real(activeView()->Convert(X));
510 ry = Standard_Real(activeView()->Convert(Y));
512 activeView()->Rotate( 0., 0., 0.,
513 theSelectedPoint.X(),theSelectedPoint.Y(), theSelectedPoint.Z(),
516 Quantity_Ratio zRotationThreshold;
517 zRotation = Standard_False;
518 zRotationThreshold = 0.45;
519 if( zRotationThreshold > 0. ) {
520 Standard_Real dx = Abs(sx - rx/2.);
521 Standard_Real dy = Abs(sy - ry/2.);
522 Standard_Real dd = zRotationThreshold * (rx + ry)/2.;
523 if( dx > dd || dy > dd ) zRotation = Standard_True;
529 // VSR: 10.06.2015: next line commented out - causes ugly blinking on starting rotation with Perspective projection mode
530 //activeView()->DepthFitAll();
535 Rotates the viewport. [ protected ]
537 void OCCViewer_ViewPort3d::rotate( int x, int y,
538 int theRotationPointType,
539 const gp_Pnt& theSelectedPoint )
541 if ( !activeView().IsNull() ) {
542 switch ( theRotationPointType ) {
543 case OCCViewer_ViewWindow::GRAVITY:
544 activeView()->Rotation( x, y );
546 case OCCViewer_ViewWindow::SELECTED:
549 dz = atan2(Standard_Real(x)-rx/2., ry/2.-Standard_Real(y)) -
550 atan2(sx-rx/2.,ry/2.-sy);
554 dx = (Standard_Real(x) - sx) * M_PI/rx;
555 dy = (sy - Standard_Real(y)) * M_PI/ry;
559 activeView()->Rotate( dx, dy, dz,
560 theSelectedPoint.X(),theSelectedPoint.Y(), theSelectedPoint.Z(),
566 emit vpTransformed( this );
568 // setZSize( getZSize() );
572 Resets the viewport after 'rotation'. [ protected ]
574 void OCCViewer_ViewPort3d::endRotation()
576 if ( !activeView().IsNull() ) {
577 activeView()->ZFitAll( 1.0 );
578 #if OCC_VERSION_LARGE <= 0x06070100
579 activeView()->SetZSize( 0.0 );
581 activeView()->Update();
582 emit vpTransformed( this );
587 Repaints the viewport. [ virtual protected ]
589 void OCCViewer_ViewPort3d::paintEvent( QPaintEvent* e )
592 /* X11 : map before show doesn't work */
593 if ( !mapped( activeView() ) )
594 mapView( activeView() );
596 if ( !myWindow.IsNull() ) {
597 #if QT_VERSION < QT_VERSION_CHECK(5, 0, 0)
598 QApplication::syncX();
600 if ( !myPaintersRedrawing ) {
601 #if OCC_VERSION_MAJOR < 7
602 QRect rc = e->rect();
603 activeView()->Redraw( rc.x(), rc.y(), rc.width(), rc.height() );
605 activeView()->Redraw();
609 OCCViewer_ViewPort::paintEvent( e );
614 Resizes the viewport. [ virtual protected ]
616 void OCCViewer_ViewPort3d::resizeEvent( QResizeEvent* e )
618 #if defined WIN32 || QT_VERSION >= QT_VERSION_CHECK(5, 0, 0)
619 /* Win32 : map before first show to avoid flicker */
620 if ( !mapped( activeView() ) )
621 mapView( activeView() );
623 #if QT_VERSION < QT_VERSION_CHECK(5, 0, 0)
624 QApplication::syncX();
626 QTimer::singleShot( 0, this, SLOT( repaintViewAfterMove() ) );
632 void OCCViewer_ViewPort3d::repaintViewAfterMove( )
634 if ( !activeView().IsNull() ){
635 activeView()->MustBeResized();
640 Fits all objects in view. [ virtual protected ]
642 void OCCViewer_ViewPort3d::fitAll( bool keepScale, bool withZ, bool upd )
644 if ( activeView().IsNull() )
648 myScale = activeView()->Scale();
650 Standard_Real margin = 0.01;
652 #if OCC_VERSION_LARGE > 0x06070100
653 activeView()->FitAll( margin, upd );
655 activeView()->ZFitAll();
657 activeView()->FitAll( margin, withZ, upd );
659 activeView()->SetZSize(0.);
660 emit vpTransformed( this );
664 Resets the view. [ virtual protected ]
666 void OCCViewer_ViewPort3d::reset()
668 // double zsize = getZSize();
669 if ( !activeView().IsNull() ) {
670 activeView()->Reset();
671 emit vpTransformed( this );
672 // setZSize( zsize );
677 Rotate the view in the view plane (orthogonal to the view vector)
679 void OCCViewer_ViewPort3d::rotateXY( double degrees )
681 if ( activeView().IsNull() )
684 int x = width()/2, y = height()/2;
686 activeView()->Convert( x, y, X, Y, Z );
687 activeView()->Rotate( 0, 0, degrees * M_PI / 180., X, Y, Z );
688 emit vpTransformed( this );
692 Set axial scale to the view
694 void OCCViewer_ViewPort3d::setAxialScale( double xScale, double yScale, double zScale )
696 if ( activeView().IsNull() )
699 activeView()->SetAxialScale( xScale, yScale, zScale );
700 emit vpTransformed( this );
704 Passed the handle of native window of the component to CASCADE view. [ private ]
706 bool OCCViewer_ViewPort3d::setWindow( const Handle(V3d_View)& view )
708 if ( !myWindow.IsNull() )
714 attachWindow( view, OCCViewer_VService::CreateWindow( view, winId() ) );
716 myWindow = view->Window();
717 return !myWindow.IsNull();
720 void OCCViewer_ViewPort3d::attachWindow( const Handle(V3d_View)& view,
721 const Handle(Aspect_Window)& window)
723 if (!view.IsNull()) {
724 view->SetWindow( window );
730 Returns the current active view. [ private ]
732 Handle(V3d_View) OCCViewer_ViewPort3d::activeView() const
738 Returns the current inactive view [ private ]
740 /*Handle(V3d_View) OCCViewer_ViewPort3d::inactiveView() const
742 return ( activeView() == myOrthoView ? myPerspView : myOrthoView );
746 Returns 'true' if the given view is mapped to window. [ private ]
748 bool OCCViewer_ViewPort3d::mapped( const Handle(V3d_View)& view ) const
750 return ( !view.IsNull() && view->View()->IsDefined() );
754 Performs synchronization of view parameters with the specified view.
755 Returns \c true if synchronization is done successfully or \c false otherwise.
756 Default implementation does nothing (return \c false)
758 bool OCCViewer_ViewPort3d::synchronize( OCCViewer_ViewPort* view )
761 OCCViewer_ViewPort3d* vp3d = qobject_cast<OCCViewer_ViewPort3d*>( view );
763 bool blocked = blockSignals( false );
764 Handle(V3d_View) aView3d = getView();
765 Handle(V3d_View) aRefView3d = vp3d->getView();
766 aView3d->SetImmediateUpdate( Standard_False );
767 #if OCC_VERSION_LARGE > 0x06070100
768 aView3d->Camera()->Copy( aRefView3d->Camera() );
770 aView3d->SetViewMapping( aRefView3d->ViewMapping() );
771 aView3d->SetViewOrientation( aRefView3d->ViewOrientation() );
774 aView3d->SetImmediateUpdate( Standard_True );
776 blockSignals( blocked );
783 * Show/Hide static triedron
785 void OCCViewer_ViewPort3d::showStaticTrihedron( bool on )
787 Handle(V3d_View) aView = activeView();
788 if ( !aView ) return;
791 aView->ZBufferTriedronSetup();
792 aView->TriedronDisplay( Aspect_TOTP_LEFT_LOWER, Quantity_NOC_WHITE, 0.05, V3d_ZBUFFER );
794 aView->TriedronErase();
800 * Create default cursor with a specific shape
802 void OCCViewer_ViewPort3d::setDefaultCursor( Qt::CursorShape theCursorShape )
805 myCursor = new QCursor();
807 myCursor->setShape( theCursorShape );
811 * Get default cursor with a specific shape
813 QCursor* OCCViewer_ViewPort3d::getDefaultCursor() const
819 * Set default parameters from preferences
821 void OCCViewer_ViewPort3d::setDefaultParams()
823 setBackground( Qtx::BackgroundData( Qt::black ) ); // set default background
825 // get ray tracing parameters from preferences
826 int aDepth = SUIT_Session::session()->resourceMgr()->integerValue( "OCCViewer", "rt_depth", 3 );
827 bool aReflection = SUIT_Session::session()->resourceMgr()->booleanValue( "OCCViewer", "rt_reflection", true );
828 bool anAntialiasing = SUIT_Session::session()->resourceMgr()->booleanValue( "OCCViewer", "rt_antialiasing", false );
829 bool aShadow = SUIT_Session::session()->resourceMgr()->booleanValue( "OCCViewer", "rt_shadow", true );
830 bool aTransparentShadow = SUIT_Session::session()->resourceMgr()->booleanValue( "OCCViewer", "rt_trans_shadow", true );
832 Graphic3d_RenderingParams& aParams = myActiveView->ChangeRenderingParams();
833 aParams.RaytracingDepth = aDepth;
834 aParams.IsReflectionEnabled = aReflection;
835 aParams.IsAntialiasingEnabled = anAntialiasing;
836 aParams.IsShadowEnabled = aShadow;
837 aParams.IsTransparentShadowEnabled = aTransparentShadow;
838 myActiveView->Redraw();