1 // Copyright (C) 2007-2023 CEA, EDF, 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 #include <V3d_View.hxx>
45 #include "utilities.h"
48 #include <WNT_Window.hxx>
50 //#include <Xw_Window.hxx>
53 static double rx = 0.;
54 static double ry = 0.;
57 static Standard_Boolean zRotation = Standard_False;
59 //#include <Standard_Version.hxx>
64 OCCViewer_ViewPort3d::OCCViewer_ViewPort3d( QWidget* parent, const Handle( V3d_Viewer)& viewer, V3d_TypeOfView type )
65 : OCCViewer_ViewPort( parent ),
68 myIsAdvancedZoomingEnabled( false )
70 // VSR: 01/07/2010 commented to avoid SIGSEGV at SALOME exit
73 myActiveView = new V3d_View( viewer, type );
83 OCCViewer_ViewPort3d::~OCCViewer_ViewPort3d()
92 Handle(V3d_View) aView = activeView();
98 Activates the desired 'type' of view in the viewer
99 ( view of 'type' is created if it doesn't exist ). [ public ]
101 /*void OCCViewer_ViewPort3d::setActive( V3d_TypeOfView type )
103 if ( activeView().IsNull() )
106 if ( activeView()->Type() != type )
108 if ( type == V3d_ORTHOGRAPHIC )
109 setView( myOrthoView );
110 if ( type == V3d_PERSPECTIVE )
111 setView( myPerspView );
116 Maps CasCade 'view' to this viewport. [ private ]
118 bool OCCViewer_ViewPort3d::mapView( const Handle(V3d_View)& view )
120 if ( !setWindow( view ) )
123 if ( !mapped( view ) ) {
124 view->SetWindow( myWindow );
125 if ( view != activeView() )
126 view->View()->Deactivate();
129 emit( vpMapped(this) );
137 Sets new CASCADE view on viewport. Returns the previous active view. [ public ]
139 Handle( V3d_View ) OCCViewer_ViewPort3d::setView( const Handle( V3d_View )& view )
141 /* map the new view */
142 if ( view == activeView() || !mapView( view ) )
145 /* activate the new view*/
146 Handle( V3d_View ) oldView = activeView();
147 if ( !oldView.IsNull() ) {
148 if (oldView->View()->IsDefined())
149 oldView->View()->Deactivate();
150 view->SetBackgroundColor( oldView->BackgroundColor() );
153 view->View()->Activate();
159 Returns CasCade 3D view. [ public ]
161 Handle(V3d_View) OCCViewer_ViewPort3d::getView() const
167 Returns CasCade 3D viewer [ public ]
169 Handle(V3d_Viewer) OCCViewer_ViewPort3d::getViewer() const
171 Handle(V3d_Viewer) viewer;
172 if ( !activeView().IsNull() )
173 viewer = activeView()->Viewer();
178 Syncronizes visual state of this viewport with 'ref'
179 ( scale, projection, eye etc ) Returns 'true' if copied OK,
180 'false' otherwise. [ virtual public ]
182 bool OCCViewer_ViewPort3d::syncronize( const OCCViewer_ViewPort3d* ref )
184 OCCViewer_ViewPort3d* ref3d = (OCCViewer_ViewPort3d*)ref;
185 Handle(V3d_View) refView = ref3d->getView();
186 Handle(V3d_View) tgtView = getView();
188 /* Syncronize view types */
189 /* if ( tgtView->Type() != refView->Type() )
191 setActive( refView->Type() );
195 /* The following params are copied:
196 - view type( ortho/persp )
197 - position of view point
198 - orientation of high point
199 - position of the eye
206 /* we'll update after setting all params */
207 tgtView->SetImmediateUpdate( Standard_False );
210 if ( refView->Type() == V3d_PERSPECTIVE )
211 tgtView->SetFocale( refView->Focale() );
214 Standard_Real x, y, z;
215 refView->At( x, y, z ); tgtView->SetAt( x, y, z );
216 refView->Up( x, y, z ); tgtView->SetUp( x, y, z );
217 refView->Eye( x, y, z ); tgtView->SetEye( x, y, z );
218 refView->Proj( x, y, z ); tgtView->SetProj( x, y, z );
219 tgtView->SetScale( refView->Scale() );
220 tgtView->SetTwist( refView->Twist() );
224 tgtView->SetImmediateUpdate( Standard_True );
231 Get axial scale to the view
233 void OCCViewer_ViewPort3d::getAxialScale( double& xScale, double& yScale, double& zScale )
235 xScale = yScale = zScale = 1.;
237 if ( !activeView().IsNull() )
238 activeView()->AxialScale( xScale, yScale, zScale );
242 Returns the background color [ virtual public ] [ obsolete ]
244 QColor OCCViewer_ViewPort3d::backgroundColor() const
246 return background().color();
250 Sets the background color [ virtual public ] [ obsolete ]
252 void OCCViewer_ViewPort3d::setBackgroundColor( const QColor& color )
254 Qtx::BackgroundData bg = background();
255 bg.setColor( color );
260 Returns the background data
262 Qtx::BackgroundData OCCViewer_ViewPort3d::background() const
268 Sets the background data
270 void OCCViewer_ViewPort3d::setBackground( const Qtx::BackgroundData& bgData )
272 if ( bgData.isValid() ) {
273 myBackground = bgData;
275 emit vpChangeBackground( myBackground );
279 void OCCViewer_ViewPort3d::updateBackground()
281 if ( activeView().IsNull() ) return;
282 if ( !myBackground.isValid() ) return;
284 switch ( myBackground.mode() ) {
285 case Qtx::ColorBackground:
287 QColor c = myBackground.color();
289 // Unset texture should be done here
291 Quantity_Color qCol( c.red()/255., c.green()/255., c.blue()/255., Quantity_TOC_RGB );
292 activeView()->SetBgGradientStyle( Aspect_GFM_NONE ); // cancel gradient background
293 activeView()->SetBgImageStyle( Aspect_FM_NONE ); // cancel texture background
294 // then change background color
295 activeView()->SetBackgroundColor( qCol );
297 activeView()->Update();
301 case Qtx::SimpleGradientBackground:
304 int type = myBackground.gradient( c1, c2 );
305 if ( c1.isValid() && type >= OCCViewer_Viewer::HorizontalGradient && type <= OCCViewer_Viewer::LastGradient ) {
306 // Unset texture should be done here
308 // Get colors and set-up gradiented background
309 if ( !c2.isValid() ) c2 = c1;
310 Quantity_Color qCol1( c1.red()/255., c1.green()/255., c1.blue()/255., Quantity_TOC_RGB );
311 Quantity_Color qCol2( c2.red()/255., c2.green()/255., c2.blue()/255., Quantity_TOC_RGB );
312 activeView()->SetBgImageStyle( Aspect_FM_NONE ); // cancel texture background
314 case OCCViewer_Viewer::HorizontalGradient:
315 activeView()->SetBgGradientColors( qCol1, qCol2, Aspect_GFM_HOR, Standard_True );
317 case OCCViewer_Viewer::VerticalGradient:
318 activeView()->SetBgGradientColors( qCol1, qCol2, Aspect_GFM_VER, Standard_True );
320 case OCCViewer_Viewer::Diagonal1Gradient:
321 activeView()->SetBgGradientColors( qCol1, qCol2, Aspect_GFM_DIAG1, Standard_True );
323 case OCCViewer_Viewer::Diagonal2Gradient:
324 activeView()->SetBgGradientColors( qCol1, qCol2, Aspect_GFM_DIAG2, Standard_True );
326 case OCCViewer_Viewer::Corner1Gradient:
327 activeView()->SetBgGradientColors( qCol1, qCol2, Aspect_GFM_CORNER1, Standard_True );
329 case OCCViewer_Viewer::Corner2Gradient:
330 activeView()->SetBgGradientColors( qCol1, qCol2, Aspect_GFM_CORNER2, Standard_True );
332 case OCCViewer_Viewer::Corner3Gradient:
333 activeView()->SetBgGradientColors( qCol1, qCol2, Aspect_GFM_CORNER3, Standard_True );
335 case OCCViewer_Viewer::Corner4Gradient:
336 activeView()->SetBgGradientColors( qCol1, qCol2, Aspect_GFM_CORNER4, Standard_True );
344 case Qtx::CustomGradientBackground:
346 // NOT IMPLEMENTED YET
352 if ( myBackground.isTextureShown() ) {
354 int textureMode = myBackground.texture( fileName );
355 QFileInfo fi( fileName );
356 if ( !fileName.isEmpty() && fi.exists() ) {
357 // set texture image: file name and fill mode
358 switch ( textureMode ) {
359 case Qtx::CenterTexture:
360 activeView()->SetBackgroundImage( fi.absoluteFilePath().toUtf8().constData(), Aspect_FM_CENTERED );
362 case Qtx::TileTexture:
363 activeView()->SetBackgroundImage( fi.absoluteFilePath().toUtf8().constData(), Aspect_FM_TILED );
365 case Qtx::StretchTexture:
366 activeView()->SetBackgroundImage( fi.absoluteFilePath().toUtf8().constData(), Aspect_FM_STRETCH );
371 activeView()->Update();
377 Updates the active viewport. [ virtual public ]
379 void OCCViewer_ViewPort3d::onUpdate()
381 if ( !activeView().IsNull() )
382 activeView()->Update();
386 Called at 'window fit' transformation. [ virtual protected ]
388 void OCCViewer_ViewPort3d::fitRect( const QRect& rect )
390 if ( !activeView().IsNull() ) {
391 activeView()->WindowFit( rect.left(), rect.top(), rect.right(), rect.bottom() );
392 emit vpTransformed( this );
397 Inits 'zoom' transformation. [ protected ]
399 void OCCViewer_ViewPort3d::startZoomAtPoint( int x, int y )
401 if ( !activeView().IsNull() && isAdvancedZoomingEnabled() )
402 activeView()->StartZoomAtPoint( x, y );
406 Called at 'zoom' transformation. [ virtual protected ]
408 void OCCViewer_ViewPort3d::zoom( int x0, int y0, int x, int y )
410 if ( !activeView().IsNull() ) {
411 // as OCCT respects a sign of only dx,
412 // but we want both signes to be taken into account
413 //activeView()->Zoom( x0, y0, x, y );
414 if ( isAdvancedZoomingEnabled() )
415 activeView()->ZoomAtPoint( x0, y0, x, y );
417 activeView()->Zoom( x0 + y0, 0, x + y, 0 );
418 emit vpTransformed( this );
423 Centers the viewport. [ virtual protected ]
425 void OCCViewer_ViewPort3d::setCenter( int x, int y )
427 if ( !activeView().IsNull() ) {
428 activeView()->Place( x, y, myScale );
429 emit vpTransformed( this );
434 Called at 'pan' transformation. [ virtual protected ]
436 void OCCViewer_ViewPort3d::pan( int dx, int dy )
438 if ( !activeView().IsNull() ) {
439 activeView()->Pan( dx, dy, 1.0 );
440 emit vpTransformed( this );
445 Inits 'rotation' transformation. [ protected ]
447 void OCCViewer_ViewPort3d::startRotation( int x, int y,
448 int theRotationPointType,
449 const gp_Pnt& theSelectedPoint )
451 if ( !activeView().IsNull() ) {
453 //double gx = activeView()->gx;
454 //activeView()->Gravity(gx,gy,gz);
456 switch ( theRotationPointType ) {
457 case OCCViewer_ViewWindow::BBCENTER:
458 activeView()->StartRotation( x, y, 0.45 );
460 case OCCViewer_ViewWindow::SELECTED:
464 activeView()->Size(X,Y);
465 rx = Standard_Real(activeView()->Convert(X));
466 ry = Standard_Real(activeView()->Convert(Y));
468 activeView()->Rotate( 0., 0., 0.,
469 theSelectedPoint.X(),theSelectedPoint.Y(), theSelectedPoint.Z(),
472 Standard_Real zRotationThreshold;
473 zRotation = Standard_False;
474 zRotationThreshold = 0.45;
475 if( zRotationThreshold > 0. ) {
476 Standard_Real dx = Abs(sx - rx/2.);
477 Standard_Real dy = Abs(sy - ry/2.);
478 Standard_Real dd = zRotationThreshold * (rx + ry)/2.;
479 if( dx > dd || dy > dd ) zRotation = Standard_True;
485 // VSR: 10.06.2015: next line commented out - causes ugly blinking on starting rotation with Perspective projection mode
486 //activeView()->DepthFitAll();
491 Rotates the viewport. [ protected ]
493 void OCCViewer_ViewPort3d::rotate( int x, int y,
494 int theRotationPointType,
495 const gp_Pnt& theSelectedPoint )
497 if ( !activeView().IsNull() ) {
498 switch ( theRotationPointType ) {
499 case OCCViewer_ViewWindow::BBCENTER:
500 activeView()->Rotation( x, y );
502 case OCCViewer_ViewWindow::SELECTED:
505 dz = atan2(Standard_Real(x)-rx/2., ry/2.-Standard_Real(y)) -
506 atan2(sx-rx/2.,ry/2.-sy);
510 dx = (Standard_Real(x) - sx) * M_PI/rx;
511 dy = (sy - Standard_Real(y)) * M_PI/ry;
515 activeView()->Rotate( dx, dy, dz,
516 theSelectedPoint.X(),theSelectedPoint.Y(), theSelectedPoint.Z(),
522 emit vpTransformed( this );
524 // setZSize( getZSize() );
528 Resets the viewport after 'rotation'. [ protected ]
530 void OCCViewer_ViewPort3d::endRotation()
532 if ( !activeView().IsNull() ) {
533 activeView()->Update();
534 emit vpTransformed( this );
539 Repaints the viewport. [ virtual protected ]
541 void OCCViewer_ViewPort3d::paintEvent( QPaintEvent* e )
544 /* X11 : map before show doesn't work */
545 if ( !mapped( activeView() ) )
546 mapView( activeView() );
548 if ( !myWindow.IsNull() ) {
549 if ( !myPaintersRedrawing ) {
550 activeView()->Redraw();
553 OCCViewer_ViewPort::paintEvent( e );
558 Resizes the viewport. [ virtual protected ]
560 void OCCViewer_ViewPort3d::resizeEvent( QResizeEvent* e )
562 /* Map before first show to avoid flicker */
563 if ( !mapped( activeView() ) )
564 mapView( activeView() );
565 QTimer::singleShot( 0, this, SLOT( repaintViewAfterMove() ) );
566 emit vpResizeEvent( e );
572 void OCCViewer_ViewPort3d::repaintViewAfterMove( )
574 if ( !activeView().IsNull() ){
575 activeView()->MustBeResized();
580 Fits all objects in view. [ virtual protected ]
582 void OCCViewer_ViewPort3d::fitAll( bool keepScale, bool /*withZ*/, bool upd )
584 if ( activeView().IsNull() )
588 myScale = activeView()->Scale();
590 Standard_Real margin = 0.01;
592 activeView()->FitAll( margin, upd );
594 emit vpTransformed( this );
598 Resets the view. [ virtual protected ]
600 void OCCViewer_ViewPort3d::reset()
602 // double zsize = getZSize();
603 if ( !activeView().IsNull() ) {
604 activeView()->Reset();
605 emit vpTransformed( this );
606 // setZSize( zsize );
611 Rotate the view in the view plane (orthogonal to the view vector)
613 void OCCViewer_ViewPort3d::rotateXY( double degrees )
615 if ( activeView().IsNull() )
618 int x = width()/2, y = height()/2;
620 activeView()->Convert( x, y, X, Y, Z );
621 activeView()->Rotate( 0, 0, degrees * M_PI / 180., X, Y, Z );
622 emit vpTransformed( this );
626 Set axial scale to the view
628 void OCCViewer_ViewPort3d::setAxialScale( double xScale, double yScale, double zScale )
630 if ( activeView().IsNull() )
633 activeView()->SetAxialScale( xScale, yScale, zScale );
634 emit vpTransformed( this );
638 Passed the handle of native window of the component to CASCADE view. [ private ]
640 bool OCCViewer_ViewPort3d::setWindow( const Handle(V3d_View)& view )
642 if ( !myWindow.IsNull() )
648 attachWindow( view, OCCViewer_VService::CreateWindow( view, winId() ) );
650 myWindow = view->Window();
651 return !myWindow.IsNull();
654 void OCCViewer_ViewPort3d::attachWindow( const Handle(V3d_View)& view,
655 const Handle(Aspect_Window)& window)
657 if (!view.IsNull()) {
658 view->SetWindow( window );
664 Returns the current active view. [ private ]
666 Handle(V3d_View) OCCViewer_ViewPort3d::activeView() const
672 Returns the current inactive view [ private ]
674 /*Handle(V3d_View) OCCViewer_ViewPort3d::inactiveView() const
676 return ( activeView() == myOrthoView ? myPerspView : myOrthoView );
680 Returns 'true' if the given view is mapped to window. [ private ]
682 bool OCCViewer_ViewPort3d::mapped( const Handle(V3d_View)& view ) const
684 return ( !view.IsNull() && view->View()->IsDefined() );
688 Performs synchronization of view parameters with the specified view.
689 Returns \c true if synchronization is done successfully or \c false otherwise.
690 Default implementation does nothing (return \c false)
692 bool OCCViewer_ViewPort3d::synchronize( OCCViewer_ViewPort* view )
695 OCCViewer_ViewPort3d* vp3d = qobject_cast<OCCViewer_ViewPort3d*>( view );
697 bool blocked = blockSignals( false );
698 Handle(V3d_View) aView3d = getView();
699 Handle(V3d_View) aRefView3d = vp3d->getView();
700 aView3d->SetImmediateUpdate( Standard_False );
701 aView3d->Camera()->Copy( aRefView3d->Camera() );
702 aView3d->SetImmediateUpdate( Standard_True );
704 blockSignals( blocked );
711 * Show/Hide static triedron
713 void OCCViewer_ViewPort3d::showStaticTrihedron( bool on )
715 Handle(V3d_View) aView = activeView();
716 if ( !aView ) return;
719 aView->ZBufferTriedronSetup();
720 aView->TriedronDisplay( Aspect_TOTP_LEFT_LOWER, Quantity_NOC_WHITE, 0.05, V3d_ZBUFFER );
722 aView->TriedronErase();
728 * Create default cursor with a specific shape
730 void OCCViewer_ViewPort3d::setDefaultCursor( Qt::CursorShape theCursorShape )
733 myCursor = new QCursor();
735 myCursor->setShape( theCursorShape );
739 * Get default cursor with a specific shape
741 QCursor* OCCViewer_ViewPort3d::getDefaultCursor() const
747 * Set default parameters from preferences
749 void OCCViewer_ViewPort3d::setDefaultParams()
751 setBackground( Qtx::BackgroundData( Qt::black ) ); // set default background
753 // get ray tracing parameters from preferences
754 int aDepth = SUIT_Session::session()->resourceMgr()->integerValue( "OCCViewer", "rt_depth", 3 );
755 bool aReflection = SUIT_Session::session()->resourceMgr()->booleanValue( "OCCViewer", "rt_reflection", true );
756 bool anAntialiasing = SUIT_Session::session()->resourceMgr()->booleanValue( "OCCViewer", "rt_antialiasing", false );
757 bool aShadow = SUIT_Session::session()->resourceMgr()->booleanValue( "OCCViewer", "rt_shadow", true );
758 bool aTransparentShadow = SUIT_Session::session()->resourceMgr()->booleanValue( "OCCViewer", "rt_trans_shadow", true );
760 Graphic3d_RenderingParams& aParams = myActiveView->ChangeRenderingParams();
761 aParams.RaytracingDepth = aDepth;
762 aParams.IsReflectionEnabled = aReflection;
763 aParams.IsAntialiasingEnabled = anAntialiasing;
764 aParams.IsShadowEnabled = aShadow;
765 aParams.IsTransparentShadowEnabled = aTransparentShadow;
766 myActiveView->Redraw();