qocc3dwidget.cpp

Go to the documentation of this file.
00001 /************************************************************************************
00002 **
00003 ** This file is part of the QtOPENCASCADE Toolkit.
00004 **
00005 ** Copyright (C) 2006, 2007, 2008 QtOCC Team Members
00006 **               Peter Dolbey, Marc Britten, Stephane Routelous
00007 **               Stefan Boeykens, Pawel Dobrolowski, Walter Steffe
00008 **               Álvaro Castro Castilla, Dirk Burski, Fotis Sioutis
00009 **
00010 ** This library is free software; you can redistribute it and/or
00011 ** modify it under the terms of the GNU Lesser General Public
00012 ** License as published by the Free Software Foundation; either
00013 ** version 2.1 of the License, or (at your option) any later version.
00014 ** 
00015 ** This library is distributed in the hope that it will be useful,
00016 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
00017 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00018 ** Lesser General Public License for more details.
00019 ** 
00020 ** You should have received a copy of the GNU Lesser General Public
00021 ** License along with this library; if not, write to the Free Software
00022 ** Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
00023 **
00024 ***********************************************************************************/
00025 
00026 /*!
00027 \class  Qocc3dWidget
00028 \brief  This class provides the view element of the QtOpenCascade Toolkit.
00029                 This class provides a Widget to view OpenCASCADE objects within a Qt4
00030                 hosted application.
00031 \author Peter C. Dolbey
00032 */
00033 #include <cmath>
00034 #include <iostream>
00035 #include <GL/gl.h>
00036 #include <GL/glu.h>
00037 
00038 #include <V3d_Plane.hxx>
00039 #include <V3d_TypeOfZclipping.hxx>
00040 
00041 #include <QtGui/QApplication>
00042 #include <QtGui/QBitmap>
00043 #include <QtGui/QPainter>
00044 #include <QtGui/QInputEvent>
00045 #include <QtGui/QColorDialog>
00046 #include <QtGui/QPlastiqueStyle>
00047 #include <QtCore/QTextStream>
00048 
00049 #include "qocc3dwidget.h"
00050 #include "qoccinternal.h"
00051 
00052 QString Qocc3dWidget::myStatusMessage = QObject::tr("");
00053 
00054 /*!
00055 \brief  Constructor for Qocc3dWidget.
00056                 This constructor creates an uninitialised window for rendering a
00057                 Handle_V3d_View based OpenCASCADE 3D viewer.
00058 \param  aContext The widget's Qocc context
00059 \param  parent The widget's parent widget
00060 \param  wflags The widget's window configuration flags
00061 \see    initialize
00062 */
00063 Qocc3dWidget::Qocc3dWidget( const QoccController* aController,
00064                                                         QWidget *parent, Qt::WindowFlags f )
00065 : QWidget( parent, f | Qt::MSWindowsOwnDC )
00066 {
00067         // Intialise mamber variables,
00068         // gcc should stop complaining!
00069         myView            = NULL;
00070         myRubberBand      = NULL;
00071         myMode            = CurAction3d_Undefined;
00072         myGridSnap        = Standard_False;
00073         myViewResized     = Standard_False;
00074         myViewInitialized = Standard_False;
00075         myPrecision       = INITIAL_PRECISION;
00076         myViewPrecision   = 0.0;
00077         myDetection       = AIS_SOD_Nothing;
00078         myKeyboardFlags   = Qt::NoModifier;
00079         myMouseFlags     = Qt::NoButton;
00080 
00081         myController = (QoccController *) aController;
00082 
00083         myView    = myController->getViewer()->CreateView();
00084         myView->SetScale( 2 );
00085 
00086         // Needed to generate mouse events
00087         setMouseTracking( true );
00088 
00089         // Avoid Qt background clears to improve resizing speed,
00090         // along with a couple of other attributes
00091         setAutoFillBackground( false );
00092         setAttribute( Qt::WA_NoSystemBackground );
00093 
00094         // This next attribute seems to be the secret of allowing OCC on Win32
00095         // to "own" the window, even though its only supposed to work on X11.
00096         setAttribute( Qt::WA_PaintOnScreen );
00097 
00098         // Here's a modified pick point cursor from AutoQ3D
00099         QBitmap curb1( 48, 48 );
00100         QBitmap curb2( 48, 48 );
00101         curb1.fill( QColor( 255, 255, 255 ) );
00102         curb2.fill( QColor( 255, 255, 255 ) );
00103         QPainter p;
00104 
00105         p.begin( &curb1 );
00106                 p.drawLine( 24,  0, 24, 47 );
00107                 p.drawLine(  0, 24, 47, 24 );
00108                 p.setBrush( Qt::NoBrush );
00109                 p.drawRect( 18, 18, 12, 12 );
00110         p.end();
00111         myCrossCursor = QCursor( curb2, curb1, 24, 24 );
00112 
00113         // Create a rubber band box for later mouse activity
00114         myRubberBand = new QRubberBand( QRubberBand::Rectangle, this );
00115         if (myRubberBand)
00116         {
00117                 // If you don't set a style, QRubberBand doesn't work properly
00118                 // take this line out if you don't believe me.
00119                 myRubberBand->setStyle( (QStyle*) new QPlastiqueStyle() );
00120         }
00121 }
00122 
00123 /*!
00124 \brief  Default destructor for Qocc3dWidget.
00125                 This should delete any memory and release any resources. No parameters
00126                 required.
00127 */
00128 Qocc3dWidget::~Qocc3dWidget()
00129 {
00130         if ( myRubberBand )
00131         {
00132                 delete myRubberBand;
00133         }
00134 }
00135 
00136 /*!
00137 \brief  The initializeOCC() procedure.
00138                 This function creates the widget's view using the interactive context
00139                 provided. Currently it also creates a trihedron object in the lower left
00140                 corner - this will eventually be managed by an external system setting.
00141 \param  aContext Handle to the AIS Interactive Context managing the view
00142 \return nothing
00143 */
00144 void Qocc3dWidget::initializeOCC()
00145 {
00146         Aspect_RenderingContext rc = 0;
00147         //myController = aContext;
00148 
00149         int windowHandle = (int) winId();
00150     short lo = (short)   windowHandle;
00151     short hi = (short) ( windowHandle >> 16 );
00152 
00153 #ifdef WNT
00154         // rc = (Aspect_RenderingContext) wglGetCurrentContext();
00155     myWindow = new WNT_Window( Handle(Graphic3d_WNTGraphicDevice)
00156                                                            ::DownCast( myController->getViewer()->Device() ) ,
00157                                                            (int) hi, (int) lo );
00158         // Turn off background erasing in OCC's window
00159         myWindow->SetFlags( WDF_NOERASEBKGRND );
00160 #else
00161         // rc = (Aspect_RenderingContext) glXGetCurrentContext(); // Untested!
00162     myWindow = new Xw_Window( Handle(Graphic3d_GraphicDevice)
00163                                                                         ::DownCast( myController->getViewer()->Device() ),
00164                                                           (int) hi, (int) lo, Xw_WQ_SAMEQUALITY, Quantity_NOC_BLACK );
00165 #endif // WNT
00166 
00167         if (!myView.IsNull())
00168         {
00169                 myVisual = myView->View();
00170                 // Set my window (Hwnd) into the OCC view
00171             myView->SetWindow( myWindow, rc , paintCallBack, this  );
00172                 // Choose a "nicer" intial scale
00173         // myView->SetScale( 2 );
00174 
00175                 // Set up axes (Trihedron) in lower left corner.
00176 #ifdef OCC_PATCHED
00177                 myView->TriedronDisplay( Aspect_TOTP_LEFT_LOWER, Quantity_NOC_WHITE, 0.1, V3d_ZBUFFER );
00178 #else
00179                 myView->TriedronDisplay( Aspect_TOTP_LEFT_LOWER, Quantity_NOC_WHITE, 0.1, V3d_WIREFRAME );
00180 #endif
00181                 // For testing OCC patches
00182                 // myView->ColorScaleDisplay();
00183                 // Map the window
00184                 if (!myWindow->IsMapped())
00185                 {
00186                         myWindow->Map();
00187                 }
00188                 // Force a redraw to the new window on next paint event
00189                 myViewResized = Standard_True;
00190 
00191                 // This is to signal any connected slots that the view is ready.
00192                 myViewInitialized = Standard_True;
00193 
00194                 // Set default cursor as a cross
00195                 setMode( CurAction3d_Nothing );
00196                 
00197                 emit initialized();
00198         }
00199 }
00200 
00201 gp_Dir Qocc3dWidget::getDirection()
00202 {
00203         return myController->getViewer()->PrivilegedPlane().Direction();
00204 }
00205 
00206 gp_Pln Qocc3dWidget::getPlane()
00207 {
00208         return myController->getViewer()->PrivilegedPlane();
00209 }
00210 
00211 gp_Pnt Qocc3dWidget::getPoint()
00212 {
00213         gp_Pnt thePoint( x(), y(), z() );
00214         return thePoint;
00215 }
00216 
00217 /*!
00218 \brief  Returns a NULL QPaintEngine
00219                 This should result in a minor performance benefit.
00220 */
00221 QPaintEngine* Qocc3dWidget::paintEngine() const
00222 {
00223         return NULL;
00224 }
00225 
00226 /*!
00227 \brief  Paint Event
00228                 Called when the Widget needs to repaint itself
00229 \param  e The event data.
00230 */
00231 void Qocc3dWidget::paintEvent ( QPaintEvent * /* e */)
00232 {
00233         if ( !myViewInitialized )
00234         {
00235                 if ( winId() )
00236                 {
00237                         initializeOCC( );
00238                 }
00239         }
00240         if ( !myView.IsNull() )
00241         {
00242                 redraw( true );
00243         }
00244 }
00245 
00246 /*!
00247 \brief  Resize event.
00248                 Called when the Widget needs to resize itself, but seeing as a paint
00249                 event always follows a resize event, we'll move the work into the
00250                 paint event.
00251 \param  e The event data.
00252 */
00253 void Qocc3dWidget::resizeEvent ( QResizeEvent * /* e */ )
00254 {
00255         myViewResized = Standard_True;
00256 }
00257 
00258 /*!
00259 \brief  Mouse press event
00260 \param  e The event data.
00261 */
00262 void Qocc3dWidget::mousePressEvent( QMouseEvent* e )
00263 {
00264         myMouseFlags = e->button();
00265         myMouseState = e->buttons();
00266 
00267         // Cache the keyboard flags for the whole gesture
00268         myKeyboardFlags = e->modifiers();
00269 
00270         // The button mappings can be used as a mask. This code prevents conflicts
00271         // when more than one button pressed simutaneously.
00272         if ( e->button() & Qt::LeftButton )
00273         {
00274                 onLeftButtonDown  ( myKeyboardFlags, e->pos() );
00275         }
00276         else if ( e->button() & Qt::RightButton )
00277         {
00278                 onRightButtonDown ( myKeyboardFlags, e->pos() );
00279         }
00280         else if ( e->button() & Qt::MidButton )
00281         {
00282                 onMiddleButtonDown( myKeyboardFlags, e->pos() );
00283         }
00284 }
00285 
00286 /*!
00287 \brief  Mouse release event
00288 \param  e The event data.
00289 */
00290 void Qocc3dWidget::mouseReleaseEvent(QMouseEvent* e)
00291 {
00292         myMouseFlags = e->button();
00293         myMouseState = e->buttons();
00294         redraw();                                                       // Clears up screen when menu selected but not used.
00295         hideRubberBand();
00296         if ( e->button() & Qt::LeftButton )
00297         {
00298                 onLeftButtonUp  ( myKeyboardFlags, e->pos() );
00299         }
00300         else if ( e->button() & Qt::RightButton )
00301         {
00302                 onRightButtonUp ( myKeyboardFlags, e->pos() );
00303         }
00304         else if ( e->button() & Qt::MidButton )
00305         {
00306                 onMiddleButtonUp( myKeyboardFlags, e->pos() );
00307         }
00308 
00309         if ( !(myKeyboardFlags & CASCADESHORTCUTKEY) )
00310         {
00311                 emit mouseClicked( this, e );
00312         }
00313 }
00314 
00315 /*!
00316 \brief  Mouse move event, driven from application message loop
00317 \param  e The event data.
00318 */
00319 void Qocc3dWidget::mouseMoveEvent( QMouseEvent* e )
00320 {
00321         Standard_Real X, Y, Z;
00322 
00323         myMouseFlags = e->button();
00324         myMouseState = e->buttons();
00325 
00326         myCurrentPoint = e->pos();
00327         //Check if the grid is active and that we're snapping to it
00328         if( myController->getViewer()->Grid()->IsActive() && myGridSnap )
00329         {
00330                 myView->ConvertToGrid( myCurrentPoint.x(), myCurrentPoint.y(), myCurrentX, myCurrentY, myCurrentZ );
00331                 sendStatusLocation();
00332                 emit mouseMoved( this, e );
00333         }
00334         else // this is the standard case
00335         {
00336                 if ( convertToPlane( myCurrentPoint.x(), myCurrentPoint.y(), X, Y, Z ) )
00337                 {
00338                         myCurrentX = precision( X );
00339                         myCurrentY = precision( Y );
00340                         myCurrentZ = precision( Z );
00341                         sendStatusLocation();
00342                         emit mouseMoved( this, e );
00343                 }
00344                 else
00345                 {
00346                         emit sendStatus ( tr("Indeterminate Point") );
00347                 }
00348         }
00349         if ( !myController->isDrawing() )
00350         {
00351                 onMouseMove( e->buttons(), myKeyboardFlags, e->pos() );
00352         }
00353 }
00354 
00355 /*!
00356 \brief  A leave event is sent to the widget when the mouse cursor leaves
00357                 the widget.
00358                 This sub-classed event handler fixes redraws when gestures are interrupted
00359                 by use of parent menus etc. (Candidate for change)
00360 \param  e       The event data
00361 */
00362 void Qocc3dWidget::leaveEvent ( QEvent* )
00363 {
00364         myMouseFlags = Qt::NoButton;
00365 }
00366 
00367 /*!
00368 \brief  The QWheelEvent class contains parameters that describe a wheel event.
00369 */
00370 void Qocc3dWidget::wheelEvent ( QWheelEvent* e )
00371 {
00372         if ( !myView.IsNull() )
00373         {
00374                 Standard_Real currentScale = myView->Scale();
00375                 if ( e->delta() > 0 )
00376                 {
00377                         currentScale *= 1.10; // +10%
00378                 }
00379                 else
00380                 {
00381                         currentScale /= 1.10; // -10%
00382                 }
00383                 myView->SetScale( currentScale );
00384                 viewPrecision( true );
00385 
00386         }
00387         else
00388         {
00389                 e->ignore();
00390         }
00391 }
00392 
00393 /*!
00394 \brief  Go idle
00395                 This called from various locations, and also exposed as a slot.
00396 */
00397 void Qocc3dWidget::idle( )
00398 {
00399         setMode( CurAction3d_Nothing );
00400 }
00401 /*!
00402 \brief  The main redraw function
00403                 This called from various locations.
00404 */
00405 void Qocc3dWidget::redraw( bool isPainting )
00406 {
00407         if ( !myView.IsNull() )                                 // Defensive test.
00408         {
00409                 if ( myViewResized )
00410                 {
00411                         myView->MustBeResized();
00412                         viewPrecision( true );
00413                 }
00414                 else
00415                 {
00416                         // Don't repaint if we are already redrawing
00417                         // elsewhere due to a keypress or mouse gesture
00418                         if ( !isPainting || ( isPainting && myMouseFlags == Qt::NoButton ) )
00419                         {
00420                                 myView->Redraw();
00421                         }
00422                 }
00423         }
00424         myViewResized = Standard_False;
00425 }
00426 
00427 /*!
00428 \brief  Just fits the current window
00429                 This function just fits the current objects to the window, without
00430                 either reducing or increasing the Z extents. This can cause clipping
00431                 of the objects after rotation.
00432 \return Nothing
00433 */
00434 void Qocc3dWidget::fitExtents( void )
00435 {
00436         if (!myView.IsNull())
00437         {
00438                 myView->FitAll();
00439                 viewPrecision( true );
00440         }
00441 }
00442 
00443 /*!
00444 \brief  Fits the model to view extents
00445                 This function fits the current objects to the window,
00446                 reducing or increasing the Z extents as needed.
00447 \return Nothing
00448 */
00449 void Qocc3dWidget::fitAll( void )
00450 {
00451         if (!myView.IsNull())
00452         {
00453                 myView->ZFitAll();
00454                 myView->FitAll();
00455                 viewPrecision( true );
00456         }
00457 }
00458 
00459 //-----------------------------------------------------------------------------
00460 /*!
00461 \brief  Sets up the view for a rubberband window zoom
00462 \return Nothing
00463 */
00464 void Qocc3dWidget::fitArea( void )
00465 {
00466     setMode( CurAction3d_WindowZooming );
00467 }
00468 
00469 /*!
00470 \brief  Sets up the view for a dynamic zoom
00471 \return Nothing
00472 */
00473 void Qocc3dWidget::zoom( void )
00474 {
00475     setMode( CurAction3d_DynamicZooming );
00476 }
00477 
00478 /*!
00479 \brief  Sets up the view for panning
00480 \return Nothing
00481 */
00482 void Qocc3dWidget::pan( void )
00483 {
00484     setMode( CurAction3d_DynamicPanning );
00485 }
00486 
00487 /*!
00488 \brief  Sets up the view for dynamic rotation
00489 \return Nothing
00490 */
00491 void Qocc3dWidget::rotation( void )
00492 {
00493     setMode( CurAction3d_DynamicRotation );
00494 }
00495 
00496 /*!
00497 \brief  Sets up the view for global panning, whatever that is!
00498 \return Nothing
00499 */
00500 void Qocc3dWidget::globalPan()
00501 {
00502         if ( !myView.IsNull() )
00503         {
00504                 // save the current zoom value
00505                 myCurZoom = myView->Scale();
00506                 // Do a Global Zoom
00507                 myView->FitAll();
00508                 viewPrecision( true );
00509                 // Set the mode
00510                 setMode( CurAction3d_GlobalPanning );
00511         }
00512 }
00513 
00514 /*!
00515 \brief  This aligns the view to the current privilege plane.
00516                 Not so interesting at the moment, but wait until custom
00517                 grid planes are implemented!
00518 \return Nothing
00519 */
00520 void Qocc3dWidget::viewGrid()
00521 {
00522         if( !myView.IsNull() )
00523         {
00524                 myView->SetFront();
00525         }
00526 }
00527 
00528 /*!
00529 \brief  View from canonical "front".
00530 \return Nothing
00531 */
00532 void Qocc3dWidget::viewFront()
00533 {
00534         setProjection( V3d_Yneg );
00535 }
00536 /*!
00537 \brief  View from canonical "back".
00538 \return Nothing
00539 */
00540 void Qocc3dWidget::viewBack()
00541 {
00542         setProjection( V3d_Ypos );
00543 }
00544 /*!
00545 \brief  View from canonical "top".
00546                 This is traditional XOY axis.
00547 \return Nothing
00548 */
00549 void Qocc3dWidget::viewTop()
00550 {
00551         setProjection( V3d_Zpos );
00552 }
00553 
00554 /*!
00555 \brief  View from canonical "bottom".
00556 \return Nothing
00557 */
00558 void Qocc3dWidget::viewBottom()
00559 {
00560         setProjection( V3d_Zneg );
00561 }
00562 /*!
00563 \brief  View from canonical "left".
00564 \return Nothing
00565 */
00566 void Qocc3dWidget::viewLeft()
00567 {
00568         setProjection( V3d_Xneg );
00569 }
00570 /*!
00571 \brief  View from canonical "right".
00572 \return Nothing
00573 */
00574 void Qocc3dWidget::viewRight()
00575 {
00576         setProjection( V3d_Xpos );
00577 }
00578 /*!
00579 \brief  View using axonometric projection.
00580 \return Nothing
00581 */
00582 void Qocc3dWidget::viewAxo()
00583 {
00584         setProjection( V3d_XnegYnegZpos );
00585 }
00586 
00587 void Qocc3dWidget::viewTopFront()
00588 {
00589         setProjection( V3d_YnegZpos );
00590 }
00591 
00592 void Qocc3dWidget::viewReset()
00593 {
00594         if( !myView.IsNull() )
00595         {
00596             myView->Reset();
00597         }
00598 }
00599 
00600 void Qocc3dWidget::hiddenLineOff()
00601 {
00602         if( !myView.IsNull() )
00603         {
00604             QApplication::setOverrideCursor( Qt::WaitCursor );
00605                 myView->SetComputedMode( Standard_False );
00606                 QApplication::restoreOverrideCursor();
00607         }
00608 }
00609 
00610 void Qocc3dWidget::hiddenLineOn()
00611 {
00612         if( !myView.IsNull() )
00613         {
00614             QApplication::setOverrideCursor( Qt::WaitCursor );
00615                 myView->SetComputedMode( Standard_True );
00616                 QApplication::restoreOverrideCursor();
00617         }
00618 }
00619 
00620 void Qocc3dWidget::background()
00621 {
00622     QColor aColor ;
00623     Standard_Real R1;
00624     Standard_Real G1;
00625     Standard_Real B1;
00626     myView->BackgroundColor(Quantity_TOC_RGB,R1,G1,B1);
00627     aColor.setRgb(( int )R1*255, ( int )G1*255, ( int )B1*255);
00628 
00629     QColor aRetColor = QColorDialog::getColor(aColor);
00630 
00631     if( aRetColor.isValid() )
00632         {
00633         R1 = aRetColor.red()/255.;
00634         G1 = aRetColor.green()/255.;
00635         B1 = aRetColor.blue()/255.;
00636         myView->SetBackgroundColor(Quantity_TOC_RGB,R1,G1,B1);
00637     }
00638     redraw();
00639 }
00640 
00641 void Qocc3dWidget::setReset ()
00642 {
00643         if( !myView.IsNull() )
00644         {
00645                 myView->SetViewOrientationDefault() ;
00646                 viewPrecision( true );
00647         }
00648 }
00649 
00650 /*!
00651 \brief  This function handles left button down events from the mouse.
00652 */
00653 void Qocc3dWidget::onLeftButtonDown(  Qt::KeyboardModifiers nFlags, const QPoint point )
00654 {
00655     myStartPoint = point;
00656     if ( nFlags & CASCADESHORTCUTKEY )
00657     {
00658                 setMode( CurAction3d_DynamicZooming );
00659     }
00660     else
00661     {
00662         switch ( myMode )
00663         {
00664             case CurAction3d_Nothing:
00665                                 // emit pointClicked( myCurrentX, myCurrentY, myCurrentZ );
00666                                 break;
00667 
00668                         case CurAction3d_Picking:
00669                                 break;
00670 
00671             case CurAction3d_DynamicZooming:
00672                                 break;
00673 
00674             case CurAction3d_WindowZooming:
00675                                 break;
00676 
00677             case CurAction3d_DynamicPanning:
00678                                 break;
00679 
00680             case CurAction3d_GlobalPanning:
00681                 break;
00682 
00683             case CurAction3d_DynamicRotation:
00684                 myView->StartRotation( myStartPoint.x(), myStartPoint.y() );
00685                 break;
00686 
00687             default:
00688                     Standard_Failure::Raise( "Incompatible Current Mode" );
00689                 break;
00690         }
00691     }
00692 }
00693 
00694 /*!
00695 \brief  This function handles middle button down events from the mouse.
00696 */
00697 void Qocc3dWidget::onMiddleButtonDown(  Qt::KeyboardModifiers nFlags, const QPoint point )
00698 {
00699         myStartPoint = point;
00700     if ( nFlags & CASCADESHORTCUTKEY )
00701         {
00702                 setMode( CurAction3d_DynamicPanning );
00703         }
00704 }
00705 
00706 /*!
00707 \brief  This function handles right button down events from the mouse.
00708 */
00709 void Qocc3dWidget::onRightButtonDown(  Qt::KeyboardModifiers nFlags, const QPoint point )
00710 {
00711         myStartPoint = point;
00712     if ( nFlags & CASCADESHORTCUTKEY )
00713     {
00714                 setMode( CurAction3d_DynamicRotation );
00715                 myView->StartRotation( point.x(), point.y() );
00716     }
00717     else
00718     {
00719         emit popupMenu ( this, point );
00720     }
00721 }
00722 
00723 /*!
00724 \brief  This function handles left button up events from the mouse.
00725                 This marks the end of the gesture.
00726 */
00727 void Qocc3dWidget::onLeftButtonUp(  Qt::KeyboardModifiers nFlags, const QPoint point )
00728 {
00729         myCurrentPoint = point;
00730         if ( nFlags & CASCADESHORTCUTKEY )
00731     {
00732                 // Deactivates dynamic zooming
00733                 setMode( CurAction3d_Nothing );
00734         }
00735         else
00736         {
00737                 switch( myMode )
00738                 {
00739 
00740                         case CurAction3d_Nothing:
00741                                 //break;
00742 
00743                         case CurAction3d_Picking:
00744                                 // Shouldn't get here yet
00745                                 if ( myCurrentPoint == myStartPoint )
00746                                 {
00747                                         inputEvent( nFlags & MULTISELECTIONKEY );
00748                                 }
00749                                 else
00750                                 {
00751                                         dragEvent( myStartPoint, myCurrentPoint, nFlags & MULTISELECTIONKEY );
00752                                 }
00753                                 break;
00754 
00755                         case CurAction3d_DynamicZooming:
00756                                 viewPrecision( true );
00757                                 break;
00758 
00759                         case CurAction3d_WindowZooming:
00760                                 if ( (abs( myCurrentPoint.x() - myStartPoint.x() ) > ValZWMin ) ||
00761                                          (abs( myCurrentPoint.y() - myStartPoint.y() ) > ValZWMin ) )
00762                                 {
00763                                         myView->WindowFitAll( myStartPoint.x(),
00764                                                                                   myStartPoint.y(),
00765                                                                                   myCurrentPoint.x(),
00766                                                                                   myCurrentPoint.y() );
00767                                 }
00768                                 viewPrecision( true );
00769                                 break;
00770 
00771                         case CurAction3d_DynamicPanning:
00772                                 break;
00773 
00774                         case CurAction3d_GlobalPanning :
00775                                 myView->Place( myCurrentPoint.x(), myCurrentPoint.y(), myCurZoom );
00776                                 break;
00777 
00778                         case CurAction3d_DynamicRotation:
00779                                 break;
00780 
00781                         default:
00782                                 Standard_Failure::Raise(" Incompatible Current Mode ");
00783                                 break;
00784                 }
00785         }
00786     emit selectionChanged();
00787 }
00788 /*!
00789 \brief  Middle button up event handler.
00790                 This marks the end of the gesture.
00791 */
00792 void Qocc3dWidget::onMiddleButtonUp(  Qt::KeyboardModifiers /* nFlags */, const QPoint /* point */ )
00793 {
00794     setMode( CurAction3d_Nothing );
00795 }
00796 
00797 /*!
00798 \brief  Right button up event handler.
00799                 This marks the end of the gesture.
00800 */
00801 void Qocc3dWidget::onRightButtonUp(  Qt::KeyboardModifiers nFlags, const QPoint point )
00802 {
00803         myCurrentPoint = point;
00804         if ( nFlags & CASCADESHORTCUTKEY )
00805     {
00806                 setMode( CurAction3d_Nothing );
00807         }
00808         else
00809         {
00810                 if ( myMode == CurAction3d_Nothing )
00811                 {
00812                         emit popupMenu ( this, point );
00813                 }
00814                 else
00815                 {
00816                         setMode( CurAction3d_Nothing );
00817                 }
00818         }
00819 }
00820 
00821 /*!
00822 \brief  Mouse move event handler.
00823 \param  buttons
00824 \param  nFlags
00825 \param  point
00826 \return Nothing
00827 */
00828 void Qocc3dWidget::onMouseMove( Qt::MouseButtons buttons,
00829                                                                 Qt::KeyboardModifiers nFlags,
00830                                                                 const QPoint point )
00831 {
00832         myCurrentPoint = point;
00833 
00834         if ( buttons & Qt::LeftButton  || buttons & Qt::RightButton || buttons & Qt::MidButton )
00835         {
00836                 switch ( myMode )
00837                 {
00838                         case CurAction3d_Nothing:
00839                                 // break;
00840 
00841                         case CurAction3d_Picking:
00842                                 // Shouldn't get here yet
00843                                 drawRubberBand ( myStartPoint, myCurrentPoint );
00844                                 dragEvent( myStartPoint, myCurrentPoint, nFlags & MULTISELECTIONKEY );
00845                                 break;
00846 
00847                         case CurAction3d_DynamicZooming:
00848                                 myView->Zoom(   myStartPoint.x(),
00849                                                                 myStartPoint.y(),
00850                                                                 myCurrentPoint.x(),
00851                                                                 myCurrentPoint.y() );
00852                                 viewPrecision( true );
00853                                 myStartPoint = myCurrentPoint;
00854                                 break;
00855 
00856                         case CurAction3d_WindowZooming:
00857                                 drawRubberBand ( myStartPoint, myCurrentPoint );
00858                                 break;
00859 
00860                         case CurAction3d_DynamicPanning:
00861                                 myView->Pan( myCurrentPoint.x() - myStartPoint.x(),
00862                                                      myStartPoint.y() - myCurrentPoint.y() );
00863                                 myStartPoint = myCurrentPoint;
00864                                 break;
00865 
00866                         case CurAction3d_GlobalPanning:
00867                                 break;
00868 
00869                         case CurAction3d_DynamicRotation:
00870                                 myView->Rotation( myCurrentPoint.x(), myCurrentPoint.y() );
00871                                 break;
00872 
00873                         default:
00874                                 Standard_Failure::Raise( "Incompatible Current Mode" );
00875                                 break;
00876                 }
00877         }
00878         else
00879         {
00880         moveEvent( myCurrentPoint );
00881     }
00882 }
00883 /*!
00884 \brief  Move event detection handler
00885 */
00886 AIS_StatusOfDetection Qocc3dWidget::moveEvent( QPoint point )
00887 {
00888         AIS_StatusOfDetection status;
00889         status = myController->getContext()->MoveTo( point.x(), point.y(), myView );
00890         return status;
00891 }
00892 
00893 /*!
00894 \brief  Drag event handler.
00895 \param  startPoint      The gesture start point.
00896 \param  endPoint        The gesture end point.
00897 \param  multi           Allows selection of multiple objects.
00898 \return The status of pick.
00899 */
00900 AIS_StatusOfPick Qocc3dWidget::dragEvent( const QPoint startPoint, const QPoint endPoint, const bool multi )
00901 {
00902         AIS_StatusOfPick pick = AIS_SOP_NothingSelected;
00903         if (multi)
00904         {
00905                 pick = myController->getContext()->ShiftSelect( min (startPoint.x(), endPoint.x()),
00906                                                                                                          min (startPoint.y(), endPoint.y()),
00907                                                                                                          max (startPoint.x(), endPoint.x()),
00908                                                                                                          max (startPoint.y(), endPoint.y()),
00909                                                                                                          myView );
00910         }
00911         else
00912         {
00913                 pick = myController->getContext()->Select( min (startPoint.x(), endPoint.x()),
00914                                                                                                 min (startPoint.y(), endPoint.y()),
00915                                                                                                 max (startPoint.x(), endPoint.x()),
00916                                                                                                 max (startPoint.y(), endPoint.y()),
00917                                                                                                 myView );
00918         }
00919     emit selectionChanged();
00920         return pick;
00921 }
00922 /*!
00923 \brief  This handles object highlighting during movement of the mouse across the view.
00924 \param  multi   Selects multiple objects if true (default false).
00925 \return The status of the objects under the cursor
00926 */
00927 AIS_StatusOfPick Qocc3dWidget::inputEvent( bool multi )
00928 {
00929         AIS_StatusOfPick pick = AIS_SOP_NothingSelected;
00930 
00931         if (multi)
00932         {
00933                 pick = myController->getContext()->ShiftSelect();
00934         }
00935         else
00936         {
00937             pick = myController->getContext()->Select();
00938         }
00939         if ( pick != AIS_SOP_NothingSelected )
00940         {
00941                 emit selectionChanged();
00942         }
00943         return pick;
00944 }
00945 
00946 bool Qocc3dWidget::dump(Standard_CString theFile)
00947 {
00948   redraw();
00949   return myView->Dump(theFile);
00950 }
00951 
00952 /*!
00953         \brief This function sets the current cursor for the given interraction mode.
00954         \param mode             The interraction mode
00955 */
00956 void Qocc3dWidget::setMode( const CurrentAction3d mode )
00957 {
00958         if ( mode != myMode )
00959         {
00960                 switch( mode )
00961                 {
00962                         case CurAction3d_DynamicPanning:
00963                                 setCursor( Qt::SizeAllCursor );
00964                                 break;
00965                         case CurAction3d_DynamicZooming:
00966                                 setCursor( Qt::CrossCursor );
00967                                 break;
00968                         case CurAction3d_DynamicRotation:
00969                                 setCursor( Qt::CrossCursor );
00970                                 break;
00971                         case CurAction3d_GlobalPanning:
00972                                 setCursor( Qt::CrossCursor );
00973                                 break;
00974                         case CurAction3d_WindowZooming:
00975                                 setCursor( Qt::PointingHandCursor );
00976                                 break;
00977                         case CurAction3d_Nothing:
00978                                 //setCursor( myCrossCursor );
00979                                 setCursor( Qt::CrossCursor );
00980                                 break;
00981                         default:
00982                                 setCursor( Qt::ArrowCursor );
00983                                 break;
00984                 }
00985                 myMode = mode;
00986         }
00987 }
00988 
00989 /*!
00990         \brief This is a Utility function for rounding the input value to a specific DP
00991 */
00992 Standard_Real Qocc3dWidget::precision( Standard_Real aReal )
00993 {
00994         Standard_Real preciseReal;
00995         Standard_Real thePrecision = max (myPrecision, viewPrecision());
00996 
00997         if ( myPrecision != 0.0 )
00998         {
00999                 preciseReal =  SIGN(aReal) * floor((std::abs(aReal) + thePrecision * 0.5) / thePrecision) * thePrecision;
01000         }
01001         else
01002         {
01003                 preciseReal = aReal;
01004         }
01005         return preciseReal;
01006 }
01007 
01008 /*! ------------------------------------------------------------------------------------
01009 \brief  ConvertToPlane convert 2d window position to 3d point on priviledged plane.
01010                 This routine was provided by Matra Datavision during Foundation training.
01011                 There still appears to be a pixel error in y co-ordinate transforms.
01012 \param  Xs                              The screen's x co-ordinate (in)
01013 \param  Ys                              The screen's y co-ordinate (in)
01014 \param  X                               The output x position on the privileged plane (out)
01015 \param  Y                               The output y position on the privileged plane (out)
01016 \param  Z                               The output z position on the privileged plane (out)
01017 \return Standard_Boolean indicating success or failure
01018 */
01019 Standard_Boolean Qocc3dWidget::convertToPlane(const Standard_Integer Xs,
01020                                                                                              const Standard_Integer Ys,
01021                                                                                                  Standard_Real& X,
01022                                                                                                  Standard_Real& Y,
01023                                                                                                  Standard_Real& Z)
01024 {
01025         Standard_Real Xv, Yv, Zv;
01026         Standard_Real Vx, Vy, Vz;
01027         gp_Pln aPlane(myView->Viewer()->PrivilegedPlane());
01028 
01029 #ifdef OCC_PATCHED
01030         myView->Convert( Xs, Ys, Xv, Yv, Zv );
01031 #else
01032         // The + 1 overcomes a fault in OCC, in "OpenGl_togl_unproject_raster.c",
01033         // which transforms the Y axis ordinate. The function uses the height of the
01034         // window, not the Y maximum which is (height - 1).
01035         myView->Convert( Xs, Ys + 1, Xv, Yv, Zv );
01036 #endif
01037 
01038         myView->Proj( Vx, Vy, Vz );
01039         gp_Lin aLine(gp_Pnt(Xv, Yv, Zv), gp_Dir(Vx, Vy, Vz));
01040         IntAna_IntConicQuad theIntersection( aLine, aPlane, Precision::Angular() );
01041         if (theIntersection.IsDone())
01042         {
01043                 if (!theIntersection.IsParallel())
01044                 {
01045                         if (theIntersection.NbPoints() > 0)
01046                         {
01047                                 gp_Pnt theSolution(theIntersection.Point(1));
01048                                 X = theSolution.X();
01049                                 Y = theSolution.Y();
01050                                 Z = theSolution.Z();
01051                                 return Standard_True;
01052                         }
01053                 }
01054         }
01055         return Standard_False;
01056 }
01057 /*!
01058 \brief  Draws the rubberband box
01059                 This function is designed to reduce "flicker" as the box is redrawn,
01060                 especially when the origin in the bottom corner of the window
01061 \param  origin          A QPoint defining the screen origin
01062 \param  position        A QPoint defining the current cursor screen location
01063 */
01064 void Qocc3dWidget::drawRubberBand( const QPoint origin, const QPoint position )
01065 {
01066         if ( myRubberBand )
01067         {
01068                 redraw();
01069                 hideRubberBand();
01070                 myRubberBand->setGeometry( QRect( origin, position ).normalized() );
01071                 showRubberBand();
01072         }
01073 }
01074 /*!
01075 \brief  Shows the rubberband box
01076 */
01077 void Qocc3dWidget::showRubberBand( void )
01078 {
01079         if ( myRubberBand )
01080         {
01081                 myRubberBand->show();
01082         }
01083 }
01084 /*!
01085 \brief  Hides the rubberband box
01086 */
01087 void Qocc3dWidget::hideRubberBand( void )
01088 {
01089         if ( myRubberBand )
01090         {
01091                 myRubberBand->hide();
01092         }
01093 }
01094 /*!
01095 \brief  Static OpenCascade callback proxy
01096 */
01097 int Qocc3dWidget::paintCallBack (Aspect_Drawable /* drawable */,
01098                                   void* aPointer,
01099                                   Aspect_GraphicCallbackStruct* /* data */)
01100 {
01101   Qocc3dWidget *aWidget = (Qocc3dWidget *) aPointer;
01102   aWidget->paintOCC();
01103   return 0;
01104 }
01105 
01106 /*!
01107 \brief  The OpenGL paint routine in the callback.
01108 */
01109 void Qocc3dWidget::paintOCC( void )
01110 {
01111         GLboolean isPlaneActive[GL_MAX_CLIP_PLANES];
01112         int i;
01113 
01114         glDisable( GL_LIGHTING );
01115         glMatrixMode( GL_MODELVIEW );
01116         glPushMatrix();
01117         glLoadIdentity();
01118     glMatrixMode( GL_PROJECTION );
01119         glPushMatrix();
01120     glLoadIdentity();
01121 
01122         GLfloat left   = -1.0f;
01123         GLfloat right  =  1.0f;
01124         GLfloat bottom = -1.0f;
01125         GLfloat top    =  1.0f;
01126         GLfloat depth  =  1.0f;
01127 
01128         for (i = 0; i < GL_MAX_CLIP_PLANES; i++)
01129         {
01130                 isPlaneActive[i] = glIsEnabled(GL_CLIP_PLANE0 + i);
01131                 glDisable(GL_CLIP_PLANE0 + i);
01132         }
01133 
01134     glOrtho( left, right, bottom, top, 1.0, -1.0 );
01135         glEnable( GL_BLEND );
01136         glBlendFunc( GL_ONE, GL_ONE_MINUS_SRC_COLOR );
01137                 
01138     glBegin( GL_QUADS );
01139     {
01140       glColor4f  (  0.1f, 0.1f, 0.1f, 0.0f );
01141       glVertex3d (  left, bottom, depth );
01142       glVertex3d ( right, bottom, depth );
01143       glColor4f  (  0.9f, 0.9f, 0.9f, 0.0f );
01144       glVertex3d ( right,    top, depth );
01145       glVertex3d (  left,    top, depth );
01146     }
01147     glEnd();
01148 
01149         glDisable(GL_BLEND);
01150         glPopMatrix();
01151         glMatrixMode( GL_MODELVIEW );
01152         glPopMatrix();
01153 
01154         for (i = 0; i < GL_MAX_CLIP_PLANES; i++)
01155         {
01156                 if (isPlaneActive[i])
01157                 { 
01158                         glEnable(GL_CLIP_PLANE0 + i);
01159                 }
01160         }
01161 }
01162 
01163 /*!
01164 \brief  This routine calculates the minimum sensible precision for the point
01165         selection routines, by setting an minumum resolution to a decade one
01166                 higher than the equivalent pixel width.
01167 \param  resized         Indicates that recaculation os required due to state
01168                     changes in the view.
01169 */
01170 Standard_Real Qocc3dWidget::viewPrecision( bool resized )
01171 {
01172 
01173         Standard_Real X1, Y1, Z1;
01174         Standard_Real X2, Y2, Z2;
01175         if (!myWindow.IsNull())
01176         {
01177                 if (resized || myViewPrecision == 0.0)
01178                 {
01179                         myView->Convert( 0, 0, X1, Y1, Z1 );
01180                         myView->Convert( 1, 0, X2, Y2, Z2 );
01181                         Standard_Real pixWidth = std::sqrt(  std::pow( X2 - X1, 2 )
01182                                                                                   + std::pow( Y2 - Y1, 2 )
01183                                                                                   + std::pow( Z2 - Z1, 2 ) ) ;
01184                         if ( pixWidth != 0.0 )
01185                         {
01186                                 // Return the precision as the next highest decade above the pixel width
01187                                 myViewPrecision = std::pow( 10.0, std::floor( std::log10( pixWidth ) + 1.0 ) );
01188                         }
01189                         else
01190                         {
01191                                 // Return the user precision if window not defined
01192                                 myViewPrecision = myPrecision;
01193                         }
01194                 }
01195         }
01196         return myViewPrecision;
01197 }
01198 
01199 void Qocc3dWidget::newShape()
01200 {
01201         // Model changed
01202         fitAll();
01203 }
01204 
01205 void Qocc3dWidget::refresh()
01206 {
01207         // Model changed
01208         redraw( false );
01209 }
01210 
01211 void Qocc3dWidget::setStatusMessage (const QString& aString)
01212 {
01213         myStatusMessage = aString;
01214         emit sendStatus(aString);
01215 }
01216 
01217 void Qocc3dWidget::sendStatusLocation ()
01218 {
01219         QString aString;
01220         QTextStream ts(&aString);
01221         ts << myStatusMessage << "(" << x() << "," << y() << "," << z() << ")";
01222         emit sendStatus(aString);
01223 }
01224 
01225 
01226 void Qocc3dWidget::setProjection( V3d_TypeOfOrientation orientation )
01227 {
01228         // This doubling of projections fixes rendering problems when
01229         // clipping planes are active - a test should be devloped
01230         // for only doing this when necessary (to do list!)
01231         if( !myView.IsNull() )
01232         {
01233                 for (int i = 0; i < 2; i++)
01234                 {
01235                         myView->SetProj( orientation );
01236                 }
01237         }       
01238 }

Generated on Sat Feb 23 21:22:15 2008 for QtGEOM by  doxygen 1.4.7