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 // VSR: 10.06.2015: next line commented out - causes ugly blinking on starting rotation with Perspective projection mode
526 //activeView()->DepthFitAll();
531 Rotates the viewport. [ protected ]
533 void OCCViewer_ViewPort3d::rotate( int x, int y,
534 int theRotationPointType,
535 const gp_Pnt& theSelectedPoint )
537 if ( !activeView().IsNull() ) {
538 switch ( theRotationPointType ) {
539 case OCCViewer_ViewWindow::GRAVITY:
540 activeView()->Rotation( x, y );
542 case OCCViewer_ViewWindow::SELECTED:
545 dz = atan2(Standard_Real(x)-rx/2., ry/2.-Standard_Real(y)) -
546 atan2(sx-rx/2.,ry/2.-sy);
550 dx = (Standard_Real(x) - sx) * M_PI/rx;
551 dy = (sy - Standard_Real(y)) * M_PI/ry;
555 activeView()->Rotate( dx, dy, dz,
556 theSelectedPoint.X(),theSelectedPoint.Y(), theSelectedPoint.Z(),
562 emit vpTransformed( this );
564 // setZSize( getZSize() );
568 Resets the viewport after 'rotation'. [ protected ]
570 void OCCViewer_ViewPort3d::endRotation()
572 if ( !activeView().IsNull() ) {
573 activeView()->ZFitAll( 1.0 );
574 #if OCC_VERSION_LARGE <= 0x06070100
575 activeView()->SetZSize( 0.0 );
577 activeView()->Update();
578 emit vpTransformed( this );
583 Repaints the viewport. [ virtual protected ]
585 void OCCViewer_ViewPort3d::paintEvent( QPaintEvent* e )
588 /* X11 : map before show doesn't work */
589 if ( !mapped( activeView() ) )
590 mapView( activeView() );
592 if ( !myWindow.IsNull() ) {
593 QApplication::syncX();
594 QRect rc = e->rect();
595 if ( !myPaintersRedrawing )
596 activeView()->Redraw( rc.x(), rc.y(), rc.width(), rc.height() );
598 OCCViewer_ViewPort::paintEvent( e );
603 Resizes the viewport. [ virtual protected ]
605 void OCCViewer_ViewPort3d::resizeEvent( QResizeEvent* e )
608 /* Win32 : map before first show to avoid flicker */
609 if ( !mapped( activeView() ) )
610 mapView( activeView() );
612 QApplication::syncX();
613 if ( !activeView().IsNull() )
614 activeView()->MustBeResized();
621 void OCCViewer_ViewPort3d::repaintViewAfterMove( )
623 if ( !activeView().IsNull() ){
624 activeView()->MustBeResized();
629 Fits all objects in view. [ virtual protected ]
631 void OCCViewer_ViewPort3d::fitAll( bool keepScale, bool withZ, bool upd )
633 if ( activeView().IsNull() )
637 myScale = activeView()->Scale();
639 Standard_Real margin = 0.01;
641 #if OCC_VERSION_LARGE > 0x06070100
642 activeView()->FitAll( margin, upd );
644 activeView()->ZFitAll();
646 activeView()->FitAll( margin, withZ, upd );
648 activeView()->SetZSize(0.);
649 emit vpTransformed( this );
653 Resets the view. [ virtual protected ]
655 void OCCViewer_ViewPort3d::reset()
657 // double zsize = getZSize();
658 if ( !activeView().IsNull() ) {
659 activeView()->Reset();
660 emit vpTransformed( this );
661 // setZSize( zsize );
666 Rotate the view in the view plane (orthogonal to the view vector)
668 void OCCViewer_ViewPort3d::rotateXY( double degrees )
670 if ( activeView().IsNull() )
673 int x = width()/2, y = height()/2;
675 activeView()->Convert( x, y, X, Y, Z );
676 activeView()->Rotate( 0, 0, degrees * M_PI / 180., X, Y, Z );
677 emit vpTransformed( this );
681 Set axial scale to the view
683 void OCCViewer_ViewPort3d::setAxialScale( double xScale, double yScale, double zScale )
685 if ( activeView().IsNull() )
688 activeView()->SetAxialScale( xScale, yScale, zScale );
689 emit vpTransformed( this );
693 Passed the handle of native window of the component to CASCADE view. [ private ]
695 bool OCCViewer_ViewPort3d::setWindow( const Handle(V3d_View)& view )
697 if ( !myWindow.IsNull() )
703 attachWindow( view, OCCViewer_VService::CreateWindow( view, winId() ) );
705 myWindow = view->Window();
706 return !myWindow.IsNull();
709 void OCCViewer_ViewPort3d::attachWindow( const Handle(V3d_View)& view,
710 const Handle(Aspect_Window)& window)
712 if (!view.IsNull()) {
713 view->SetWindow( window );
719 Returns the current active view. [ private ]
721 Handle(V3d_View) OCCViewer_ViewPort3d::activeView() const
727 Returns the current inactive view [ private ]
729 /*Handle(V3d_View) OCCViewer_ViewPort3d::inactiveView() const
731 return ( activeView() == myOrthoView ? myPerspView : myOrthoView );
735 Returns 'true' if the given view is mapped to window. [ private ]
737 bool OCCViewer_ViewPort3d::mapped( const Handle(V3d_View)& view ) const
739 return ( !view.IsNull() && view->View()->IsDefined() );
743 Performs synchronization of view parameters with the specified view.
744 Returns \c true if synchronization is done successfully or \c false otherwise.
745 Default implementation does nothing (return \c false)
747 bool OCCViewer_ViewPort3d::synchronize( OCCViewer_ViewPort* view )
750 OCCViewer_ViewPort3d* vp3d = qobject_cast<OCCViewer_ViewPort3d*>( view );
752 bool blocked = blockSignals( false );
753 Handle(V3d_View) aView3d = getView();
754 Handle(V3d_View) aRefView3d = vp3d->getView();
755 aView3d->SetImmediateUpdate( Standard_False );
756 #if OCC_VERSION_LARGE > 0x06070100
757 aView3d->Camera()->Copy( aRefView3d->Camera() );
759 aView3d->SetViewMapping( aRefView3d->ViewMapping() );
760 aView3d->SetViewOrientation( aRefView3d->ViewOrientation() );
763 aView3d->SetImmediateUpdate( Standard_True );
765 blockSignals( blocked );
772 * Show/Hide static triedron
774 void OCCViewer_ViewPort3d::showStaticTrihedron( bool on )
776 Handle(V3d_View) aView = activeView();
777 if ( !aView ) return;
780 aView->ZBufferTriedronSetup();
781 aView->TriedronDisplay( Aspect_TOTP_LEFT_LOWER, Quantity_NOC_WHITE, 0.05, V3d_ZBUFFER );
783 aView->TriedronErase();
789 * Create default cursor with a specific shape
791 void OCCViewer_ViewPort3d::setDefaultCursor( Qt::CursorShape theCursorShape )
794 myCursor = new QCursor();
796 myCursor->setShape( theCursorShape );
800 * Get default cursor with a specific shape
802 QCursor* OCCViewer_ViewPort3d::getDefaultCursor() const