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>
36 #include <QPaintEvent>
37 #include <QResizeEvent>
38 #include <QApplication>
40 #include <Visual3d_View.hxx>
41 #include <V3d_Viewer.hxx>
43 #if OCC_VERSION_LARGE > 0x06070100
44 #include <V3d_View.hxx>
46 #include <V3d_PerspectiveView.hxx>
47 #include <V3d_OrthographicView.hxx>
50 #include "utilities.h"
53 #include <WNT_Window.hxx>
55 //#include <Xw_Window.hxx>
58 static double rx = 0.;
59 static double ry = 0.;
62 static Standard_Boolean zRotation = Standard_False;
64 //#include <Standard_Version.hxx>
69 OCCViewer_ViewPort3d::OCCViewer_ViewPort3d( QWidget* parent, const Handle( V3d_Viewer)& viewer, V3d_TypeOfView type )
70 : OCCViewer_ViewPort( parent ),
73 myIsAdvancedZoomingEnabled( false )
75 // VSR: 01/07/2010 commented to avoid SIGSEGV at SALOME exit
78 #if OCC_VERSION_LARGE > 0x06070100
79 myActiveView = new V3d_View( viewer, type );
81 if ( type == V3d_ORTHOGRAPHIC ) {
82 myOrthoView = new V3d_OrthographicView( viewer );
83 myActiveView = myOrthoView;
86 myPerspView = new V3d_PerspectiveView( viewer );
87 myActiveView = myPerspView;
91 setBackground( Qtx::BackgroundData( Qt::black ) ); // set default background
99 OCCViewer_ViewPort3d::~OCCViewer_ViewPort3d()
108 Handle(V3d_View) aView = activeView();
114 Activates the desired 'type' of view in the viewer
115 ( view of 'type' is created if it doesn't exist ). [ public ]
117 /*void OCCViewer_ViewPort3d::setActive( V3d_TypeOfView type )
119 if ( activeView().IsNull() )
122 if ( activeView()->Type() != type )
124 if ( type == V3d_ORTHOGRAPHIC )
125 setView( myOrthoView );
126 if ( type == V3d_PERSPECTIVE )
127 setView( myPerspView );
132 Maps CasCade 'view' to this viewport. [ private ]
134 bool OCCViewer_ViewPort3d::mapView( const Handle(V3d_View)& view )
136 if ( !setWindow( view ) )
139 if ( !mapped( view ) ) {
140 view->SetWindow( myWindow );
141 if ( view != activeView() )
142 view->View()->Deactivate();
145 emit( vpMapped(this) );
153 Sets new CASCADE view on viewport. Returns the previous active view. [ public ]
155 Handle( V3d_View ) OCCViewer_ViewPort3d::setView( const Handle( V3d_View )& view )
157 /* map the new view */
158 if ( view == activeView() || !mapView( view ) )
161 /* activate the new view*/
162 Handle( V3d_View ) oldView = activeView();
163 if ( !oldView.IsNull() ) {
164 if (oldView->View()->IsDefined())
165 oldView->View()->Deactivate();
166 view->SetBackgroundColor( oldView->BackgroundColor() );
169 view->View()->Activate();
175 Returns CasCade 3D view. [ public ]
177 Handle(V3d_View) OCCViewer_ViewPort3d::getView() const
183 Returns CasCade 3D viewer [ public ]
185 Handle(V3d_Viewer) OCCViewer_ViewPort3d::getViewer() const
187 Handle(V3d_Viewer) viewer;
188 if ( !activeView().IsNull() )
189 viewer = activeView()->Viewer();
194 Syncronizes visual state of this viewport with 'ref'
195 ( scale, projection, eye etc ) Returns 'true' if copied OK,
196 'false' otherwise. [ virtual public ]
198 bool OCCViewer_ViewPort3d::syncronize( const OCCViewer_ViewPort3d* ref )
200 OCCViewer_ViewPort3d* ref3d = (OCCViewer_ViewPort3d*)ref;
201 Handle(V3d_View) refView = ref3d->getView();
202 Handle(V3d_View) tgtView = getView();
204 /* Syncronize view types */
205 /* if ( tgtView->Type() != refView->Type() )
207 setActive( refView->Type() );
211 /* The following params are copied:
212 - view type( ortho/persp )
213 - position of view point
214 - orientation of high point
215 - position of the eye
222 /* we'll update after setting all params */
223 tgtView->SetImmediateUpdate( Standard_False );
226 if ( refView->Type() == V3d_PERSPECTIVE )
227 tgtView->SetFocale( refView->Focale() );
230 Standard_Real x, y, z;
231 refView->At( x, y, z ); tgtView->SetAt( x, y, z );
232 refView->Up( x, y, z ); tgtView->SetUp( x, y, z );
233 refView->Eye( x, y, z ); tgtView->SetEye( x, y, z );
234 refView->Proj( x, y, z ); tgtView->SetProj( x, y, z );
235 #if OCC_VERSION_LARGE <= 0x06070100
236 refView->Center( x, y ); tgtView->SetCenter( x, y );
238 tgtView->SetScale( refView->Scale() );
239 tgtView->SetTwist( refView->Twist() );
243 tgtView->SetImmediateUpdate( Standard_True );
249 Returns Z-size of this view. [ public ]
251 double OCCViewer_ViewPort3d::getZSize() const
253 if ( !activeView().IsNull() )
254 return activeView()->ZSize();
259 Sets Z-size of this view ( for both orthographic and perspective ). [ public ]
261 void OCCViewer_ViewPort3d::setZSize( double zsize )
263 myActiveView->SetZSize( zsize );
264 /* if ( !myOrthoView.IsNull() )
265 myOrthoView->SetZSize( zsize );
266 if ( !myPerspView.IsNull() )
267 myPerspView->SetZSize( zsize );*/
271 Get axial scale to the view
273 void OCCViewer_ViewPort3d::getAxialScale( double& xScale, double& yScale, double& zScale )
275 xScale = yScale = zScale = 1.;
277 if ( !activeView().IsNull() )
278 activeView()->AxialScale( xScale, yScale, zScale );
282 Returns the background color [ virtual public ] [ obsolete ]
284 QColor OCCViewer_ViewPort3d::backgroundColor() const
286 return background().color();
290 Sets the background color [ virtual public ] [ obsolete ]
292 void OCCViewer_ViewPort3d::setBackgroundColor( const QColor& color )
294 Qtx::BackgroundData bg = background();
295 bg.setColor( color );
300 Returns the background data
302 Qtx::BackgroundData OCCViewer_ViewPort3d::background() const
308 Sets the background data
310 void OCCViewer_ViewPort3d::setBackground( const Qtx::BackgroundData& bgData )
312 if ( bgData.isValid() ) {
313 myBackground = bgData;
315 emit vpChangeBackground( myBackground );
319 void OCCViewer_ViewPort3d::updateBackground()
321 if ( activeView().IsNull() ) return;
322 if ( !myBackground.isValid() ) return;
324 switch ( myBackground.mode() ) {
325 case Qtx::ColorBackground:
327 QColor c = myBackground.color();
329 // Unset texture should be done here
331 Quantity_Color qCol( c.red()/255., c.green()/255., c.blue()/255., Quantity_TOC_RGB );
332 activeView()->SetBgGradientStyle( Aspect_GFM_NONE ); // cancel gradient background
333 activeView()->SetBgImageStyle( Aspect_FM_NONE ); // cancel texture background
334 // then change background color
335 activeView()->SetBackgroundColor( qCol );
337 activeView()->Update();
341 case Qtx::SimpleGradientBackground:
344 int type = myBackground.gradient( c1, c2 );
345 if ( c1.isValid() && type >= OCCViewer_Viewer::HorizontalGradient && type <= OCCViewer_Viewer::LastGradient ) {
346 // Unset texture should be done here
348 // Get colors and set-up gradiented background
349 if ( !c2.isValid() ) c2 = c1;
350 Quantity_Color qCol1( c1.red()/255., c1.green()/255., c1.blue()/255., Quantity_TOC_RGB );
351 Quantity_Color qCol2( c2.red()/255., c2.green()/255., c2.blue()/255., Quantity_TOC_RGB );
352 activeView()->SetBgImageStyle( Aspect_FM_NONE ); // cancel texture background
354 case OCCViewer_Viewer::HorizontalGradient:
355 activeView()->SetBgGradientColors( qCol1, qCol2, Aspect_GFM_HOR, Standard_True );
357 case OCCViewer_Viewer::VerticalGradient:
358 activeView()->SetBgGradientColors( qCol1, qCol2, Aspect_GFM_VER, Standard_True );
360 case OCCViewer_Viewer::Diagonal1Gradient:
361 activeView()->SetBgGradientColors( qCol1, qCol2, Aspect_GFM_DIAG1, Standard_True );
363 case OCCViewer_Viewer::Diagonal2Gradient:
364 activeView()->SetBgGradientColors( qCol1, qCol2, Aspect_GFM_DIAG2, Standard_True );
366 case OCCViewer_Viewer::Corner1Gradient:
367 activeView()->SetBgGradientColors( qCol1, qCol2, Aspect_GFM_CORNER1, Standard_True );
369 case OCCViewer_Viewer::Corner2Gradient:
370 activeView()->SetBgGradientColors( qCol1, qCol2, Aspect_GFM_CORNER2, Standard_True );
372 case OCCViewer_Viewer::Corner3Gradient:
373 activeView()->SetBgGradientColors( qCol1, qCol2, Aspect_GFM_CORNER3, Standard_True );
375 case OCCViewer_Viewer::Corner4Gradient:
376 activeView()->SetBgGradientColors( qCol1, qCol2, Aspect_GFM_CORNER4, Standard_True );
384 case Qtx::CustomGradientBackground:
386 // NOT IMPLEMENTED YET
392 if ( myBackground.isTextureShown() ) {
394 int textureMode = myBackground.texture( fileName );
395 QFileInfo fi( fileName );
396 if ( !fileName.isEmpty() && fi.exists() ) {
397 // set texture image: file name and fill mode
398 switch ( textureMode ) {
399 case Qtx::CenterTexture:
400 activeView()->SetBackgroundImage( fi.absoluteFilePath().toLatin1().constData(), Aspect_FM_CENTERED );
402 case Qtx::TileTexture:
403 activeView()->SetBackgroundImage( fi.absoluteFilePath().toLatin1().constData(), Aspect_FM_TILED );
405 case Qtx::StretchTexture:
406 activeView()->SetBackgroundImage( fi.absoluteFilePath().toLatin1().constData(), Aspect_FM_STRETCH );
411 activeView()->Update();
417 Updates the active viewport. [ virtual public ]
419 void OCCViewer_ViewPort3d::onUpdate()
421 if ( !activeView().IsNull() )
422 activeView()->Update();
426 Called at 'window fit' transformation. [ virtual protected ]
428 void OCCViewer_ViewPort3d::fitRect( const QRect& rect )
430 if ( !activeView().IsNull() ) {
431 activeView()->WindowFit( rect.left(), rect.top(), rect.right(), rect.bottom() );
432 emit vpTransformed( this );
437 Inits 'zoom' transformation. [ protected ]
439 void OCCViewer_ViewPort3d::startZoomAtPoint( int x, int y )
441 if ( !activeView().IsNull() && isAdvancedZoomingEnabled() )
442 activeView()->StartZoomAtPoint( x, y );
446 Called at 'zoom' transformation. [ virtual protected ]
448 void OCCViewer_ViewPort3d::zoom( int x0, int y0, int x, int y )
450 if ( !activeView().IsNull() ) {
451 // as OCCT respects a sign of only dx,
452 // but we want both signes to be taken into account
453 //activeView()->Zoom( x0, y0, x, y );
454 if ( isAdvancedZoomingEnabled() )
455 activeView()->ZoomAtPoint( x0, y0, x, y );
457 activeView()->Zoom( x0 + y0, 0, x + y, 0 );
458 emit vpTransformed( this );
463 Centers the viewport. [ virtual protected ]
465 void OCCViewer_ViewPort3d::setCenter( int x, int y )
467 if ( !activeView().IsNull() ) {
468 activeView()->Place( x, y, myScale );
469 emit vpTransformed( this );
474 Called at 'pan' transformation. [ virtual protected ]
476 void OCCViewer_ViewPort3d::pan( int dx, int dy )
478 if ( !activeView().IsNull() ) {
479 activeView()->Pan( dx, dy, 1.0 );
480 emit vpTransformed( this );
485 Inits 'rotation' transformation. [ protected ]
487 void OCCViewer_ViewPort3d::startRotation( int x, int y,
488 int theRotationPointType,
489 const gp_Pnt& theSelectedPoint )
491 if ( !activeView().IsNull() ) {
493 //double gx = activeView()->gx;
494 //activeView()->Gravity(gx,gy,gz);
496 switch ( theRotationPointType ) {
497 case OCCViewer_ViewWindow::GRAVITY:
498 activeView()->StartRotation( x, y, 0.45 );
500 case OCCViewer_ViewWindow::SELECTED:
504 activeView()->Size(X,Y);
505 rx = Standard_Real(activeView()->Convert(X));
506 ry = Standard_Real(activeView()->Convert(Y));
508 activeView()->Rotate( 0., 0., 0.,
509 theSelectedPoint.X(),theSelectedPoint.Y(), theSelectedPoint.Z(),
512 Quantity_Ratio zRotationThreshold;
513 zRotation = Standard_False;
514 zRotationThreshold = 0.45;
515 if( zRotationThreshold > 0. ) {
516 Standard_Real dx = Abs(sx - rx/2.);
517 Standard_Real dy = Abs(sy - ry/2.);
518 Standard_Real dd = zRotationThreshold * (rx + ry)/2.;
519 if( dx > dd || dy > dd ) zRotation = Standard_True;
525 activeView()->DepthFitAll();
530 Rotates the viewport. [ protected ]
532 void OCCViewer_ViewPort3d::rotate( int x, int y,
533 int theRotationPointType,
534 const gp_Pnt& theSelectedPoint )
536 if ( !activeView().IsNull() ) {
537 switch ( theRotationPointType ) {
538 case OCCViewer_ViewWindow::GRAVITY:
539 activeView()->Rotation( x, y );
541 case OCCViewer_ViewWindow::SELECTED:
544 dz = atan2(Standard_Real(x)-rx/2., ry/2.-Standard_Real(y)) -
545 atan2(sx-rx/2.,ry/2.-sy);
549 dx = (Standard_Real(x) - sx) * M_PI/rx;
550 dy = (sy - Standard_Real(y)) * M_PI/ry;
554 activeView()->Rotate( dx, dy, dz,
555 theSelectedPoint.X(),theSelectedPoint.Y(), theSelectedPoint.Z(),
561 emit vpTransformed( this );
563 // setZSize( getZSize() );
567 Resets the viewport after 'rotation'. [ protected ]
569 void OCCViewer_ViewPort3d::endRotation()
571 if ( !activeView().IsNull() ) {
572 activeView()->ZFitAll( 1.0 );
573 #if OCC_VERSION_LARGE <= 0x06070100
574 activeView()->SetZSize( 0.0 );
576 activeView()->Update();
577 emit vpTransformed( this );
582 Repaints the viewport. [ virtual protected ]
584 void OCCViewer_ViewPort3d::paintEvent( QPaintEvent* e )
587 /* X11 : map before show doesn't work */
588 if ( !mapped( activeView() ) )
589 mapView( activeView() );
591 if ( !myWindow.IsNull() ) {
592 QApplication::syncX();
593 QRect rc = e->rect();
594 if ( !myPaintersRedrawing )
595 activeView()->Redraw( rc.x(), rc.y(), rc.width(), rc.height() );
597 OCCViewer_ViewPort::paintEvent( e );
602 Resizes the viewport. [ virtual protected ]
604 void OCCViewer_ViewPort3d::resizeEvent( QResizeEvent* e )
607 /* Win32 : map before first show to avoid flicker */
608 if ( !mapped( activeView() ) )
609 mapView( activeView() );
611 QApplication::syncX();
612 if ( !activeView().IsNull() )
613 activeView()->MustBeResized();
617 Fits all objects in view. [ virtual protected ]
619 void OCCViewer_ViewPort3d::fitAll( bool keepScale, bool withZ, bool upd )
621 if ( activeView().IsNull() )
625 myScale = activeView()->Scale();
627 Standard_Real margin = 0.01;
629 #if OCC_VERSION_LARGE > 0x06070100
630 activeView()->FitAll( margin, upd );
632 activeView()->ZFitAll();
634 activeView()->FitAll( margin, withZ, upd );
636 activeView()->SetZSize(0.);
637 emit vpTransformed( this );
641 Resets the view. [ virtual protected ]
643 void OCCViewer_ViewPort3d::reset()
645 // double zsize = getZSize();
646 if ( !activeView().IsNull() ) {
647 activeView()->Reset();
648 emit vpTransformed( this );
649 // setZSize( zsize );
654 Rotate the view in the view plane (orthogonal to the view vector)
656 void OCCViewer_ViewPort3d::rotateXY( double degrees )
658 if ( activeView().IsNull() )
661 int x = width()/2, y = height()/2;
663 activeView()->Convert( x, y, X, Y, Z );
664 activeView()->Rotate( 0, 0, degrees * M_PI / 180., X, Y, Z );
665 emit vpTransformed( this );
669 Set axial scale to the view
671 void OCCViewer_ViewPort3d::setAxialScale( double xScale, double yScale, double zScale )
673 if ( activeView().IsNull() )
676 activeView()->SetAxialScale( xScale, yScale, zScale );
677 emit vpTransformed( this );
681 Passed the handle of native window of the component to CASCADE view. [ private ]
683 bool OCCViewer_ViewPort3d::setWindow( const Handle(V3d_View)& view )
685 if ( !myWindow.IsNull() )
691 attachWindow( view, OCCViewer_VService::CreateWindow( view, winId() ) );
693 myWindow = view->Window();
694 return !myWindow.IsNull();
697 void OCCViewer_ViewPort3d::attachWindow( const Handle(V3d_View)& view,
698 const Handle(Aspect_Window)& window)
700 if (!view.IsNull()) {
701 view->SetWindow( window );
707 Returns the current active view. [ private ]
709 Handle(V3d_View) OCCViewer_ViewPort3d::activeView() const
715 Returns the current inactive view [ private ]
717 /*Handle(V3d_View) OCCViewer_ViewPort3d::inactiveView() const
719 return ( activeView() == myOrthoView ? myPerspView : myOrthoView );
723 Returns 'true' if the given view is mapped to window. [ private ]
725 bool OCCViewer_ViewPort3d::mapped( const Handle(V3d_View)& view ) const
727 return ( !view.IsNull() && view->View()->IsDefined() );
731 Performs synchronization of view parameters with the specified view.
732 Returns \c true if synchronization is done successfully or \c false otherwise.
733 Default implementation does nothing (return \c false)
735 bool OCCViewer_ViewPort3d::synchronize( OCCViewer_ViewPort* view )
738 OCCViewer_ViewPort3d* vp3d = qobject_cast<OCCViewer_ViewPort3d*>( view );
740 bool blocked = blockSignals( false );
741 Handle(V3d_View) aView3d = getView();
742 Handle(V3d_View) aRefView3d = vp3d->getView();
743 aView3d->SetImmediateUpdate( Standard_False );
744 #if OCC_VERSION_LARGE > 0x06070100
745 aView3d->Camera()->Copy( aRefView3d->Camera() );
747 aView3d->SetViewMapping( aRefView3d->ViewMapping() );
748 aView3d->SetViewOrientation( aRefView3d->ViewOrientation() );
751 aView3d->SetImmediateUpdate( Standard_True );
753 blockSignals( blocked );
760 * Show/Hide static triedron
762 void OCCViewer_ViewPort3d::showStaticTrihedron( bool on )
764 Handle(V3d_View) aView = activeView();
765 if ( !aView ) return;
768 aView->ZBufferTriedronSetup();
769 aView->TriedronDisplay( Aspect_TOTP_LEFT_LOWER, Quantity_NOC_WHITE, 0.05, V3d_ZBUFFER );
771 aView->TriedronErase();
777 * Create default cursor with a specific shape
779 void OCCViewer_ViewPort3d::setDefaultCursor( Qt::CursorShape theCursorShape )
782 myCursor = new QCursor();
784 myCursor->setShape( theCursorShape );
788 * Get default cursor with a specific shape
790 QCursor* OCCViewer_ViewPort3d::getDefaultCursor() const