1 // Copyright (C) 2007-2008 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.
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
22 // Author : OPEN CASCADE
23 // File: GLViewer_ViewPort2d.cxx
24 // Created: November, 2004
26 /* GLViewer_ViewPort2d Source File */
28 //#include <GLViewerAfx.h>
29 #include "GLViewer_ViewPort2d.h"
30 #include "GLViewer_Viewer2d.h"
31 #include "GLViewer_ViewFrame.h"
32 #include "GLViewer_MimeData.h"
33 #include "GLViewer_Context.h"
34 #include "GLViewer_Compass.h"
35 #include "GLViewer_Grid.h"
36 #include "GLViewer_Drawer.h"
38 // TODO: Porting to Qt4
39 //#include <QtxToolTip.h>
41 #include <QHBoxLayout>
42 #include <QMouseEvent>
46 #include <QApplication>
51 #include <QRubberBand>
57 #define GRID_XSIZE 100
58 #define GRID_YSIZE 100
60 int static aLastViewPostId = 0;
62 void rotate_point( float& theX, float& theY, float theAngle )
64 float aTempX = theX * cos(theAngle) - theY * sin(theAngle);
65 float aTempY = theX * sin(theAngle) + theY * cos(theAngle);
73 GLViewer_ViewPort2d::GLViewer_ViewPort2d( QWidget* parent, GLViewer_ViewFrame* theViewFrame )
74 : GLViewer_ViewPort( parent ),
75 myMargin( MARGIN ), myWidth( WIDTH ), myHeight( HEIGHT ),
76 myXScale( 1.0 ), myYScale( 1.0 ), myXOldScale( 1.0 ), myYOldScale( 1.0 ),
77 myXPan( 0.0 ), myYPan( 0.0 ),
78 myIsMouseReleaseBlock( false ),
82 myViewFrame = (GLViewer_ViewFrame*)parent;
84 myViewFrame = theViewFrame;
88 myBorder = new GLViewer_Rect();
90 QBoxLayout* qbl = new QHBoxLayout( this );
94 myGLWidget = new GLViewer_Widget( this, 0 ) ;
95 qbl->addWidget( myGLWidget );
96 myGLWidget->setFocusProxy( this );
97 setMouseTracking( TRUE );
99 myIsDragProcess = noDrag;
100 //myCurDragMousePos = QPoint();
101 myCurDragPosX = NULL;
102 myCurDragPosY = NULL;
106 myViewPortId = aLastViewPostId;
109 mypFirstPoint = NULL;
112 // TODO: Porting to Qt4
113 /*myObjectTip = new QtxToolTip( myGLWidget );///GLViewer_ObjectTip( this );
114 myObjectTip->setShowDelayTime( 60000 );
115 connect( myObjectTip, SIGNAL( maybeTip( QPoint, QString&, QFont&, QRect&, QRect& ) ),
116 this, SLOT( onMaybeTip( QPoint, QString&, QFont&, QRect&, QRect& ) ) );*/
117 // myGLWidget->installEventFilter( myObjectTip );
123 GLViewer_ViewPort2d::~GLViewer_ViewPort2d()
134 if ( myRectBand ) myRectBand->hide();
139 SLOT: initializes drag process
141 void GLViewer_ViewPort2d::onStartDragObject( )
143 if( myIsDragProcess == noDrag )
145 myIsDragProcess = initDrag;
146 QCursor::setPos( (int)(*myCurDragPosX), (int)(*myCurDragPosY) );
147 //myCurDragMousePos = QPoint( 0, 0 );
148 delete myCurDragPosX;
149 delete myCurDragPosY;
150 myCurDragPosX = NULL;
151 myCurDragPosY = NULL;
157 SLOT: cuts object to clipboard
159 void GLViewer_ViewPort2d::onCutObject()
161 /*GLViewer_Object* aMovingObject = ((GLViewer_Viewer2d*)getViewFrame()->getViewer())->getGLContext()->getCurrentObject();
164 GLViewer_MimeSource* aMimeSource = new GLViewer_MimeSource();
165 aMimeSource->setObject( aMovingObject );
167 QClipboard *aClipboard = QApplication::clipboard();
169 aClipboard->setData( aMimeSource );
171 ((GLViewer_Viewer2d*)getViewFrame()->getViewer())->getGLContext()->deleteObject( aMovingObject );
173 GLViewer_Context* aContext = ((GLViewer_Viewer2d*)getViewFrame()->getViewer())->getGLContext();
174 int aObjNum = aContext->NbSelected();
177 QList<GLViewer_Object*> aObjects;
178 GLViewer_MimeData* aMimeData = new GLViewer_MimeData();
179 aContext->InitSelected();
180 for( ; aContext->MoreSelected(); aContext->NextSelected() )
181 aObjects.append( aContext->SelectedObject() );
183 //aMimeData->setObjects( aObjects ); ouv 6.05.04
185 QClipboard *aClipboard = QApplication::clipboard();
187 aClipboard->setMimeData( aMimeData );
189 for( int i = 0; i < aObjNum; i++ )
190 aContext->deleteObject( aObjects[i] );
195 SLOT: copies object to clipboard
197 void GLViewer_ViewPort2d::onCopyObject()
199 /*GLViewer_Object* aMovingObject = ((GLViewer_Viewer2d*)getViewFrame()->getViewer())->getGLContext()->getCurrentObject();
202 GLViewer_MimeSource* aMimeSource = new GLViewer_MimeSource();
203 aMimeSource->setObject( aMovingObject );
205 QClipboard *aClipboard = QApplication::clipboard();
207 aClipboard->setData( aMimeSource );
210 GLViewer_Context* aContext = ((GLViewer_Viewer2d*)getViewFrame()->getViewer())->getGLContext();
211 int aObjNum = aContext->NbSelected();
214 QList<GLViewer_Object*> aObjects;
215 GLViewer_MimeData* aMimeData = new GLViewer_MimeData();
216 aContext->InitSelected();
217 for( ; aContext->MoreSelected(); aContext->NextSelected() )
218 aObjects.append( aContext->SelectedObject() );
220 //aMimeData->setObjects( aObjects ); ouv 6.05.04
222 QClipboard *aClipboard = QApplication::clipboard();
224 aClipboard->setMimeData( aMimeData );
229 SLOT: pastes object from clipboard
231 void GLViewer_ViewPort2d::onPasteObject()
233 /*QClipboard *aClipboard = QApplication::clipboard();
234 QMimeSource* aMimeSource = aClipboard->data();
235 if( aMimeSource->provides( "GLViewer_Object" ) )
242 aType = aMimeSource->format( i );
243 anArray = aMimeSource->encodedData( aType );
244 if( anArray.size() != 0 )
249 if( anArray.size() == 0 )
252 GLViewer_Object* aObject = GLViewer_MimeSource::getObject( anArray, aType );
256 ((GLViewer_Viewer2d*)getViewFrame()->getViewer())->getGLContext()->insertObject( aObject, true );
260 QClipboard *aClipboard = QApplication::clipboard();
262 QMimeSource* aMimeSource = aClipboard->data();
263 if( aMimeSource->provides( "GLViewer_Objects" ) )
265 QByteArray anArray = aMimeSource->encodedData( "GLViewer_Objects" );
266 QList<GLViewer_Object*> aObjects = GLViewer_MimeSource::getObjects( anArray, "GLViewer_Objects" );
267 if( aObjects.empty() )
269 GLViewer_Context* aContext = ((GLViewer_Viewer2d*)getViewFrame()->getViewer())->getGLContext();
270 for( int i = 0; i < aObjects.count(); i++ )
271 aContext->insertObject( aObjects[i], true );
277 SLOT: called when object is being dragged
279 void GLViewer_ViewPort2d::onDragObject( QMouseEvent* e )
281 //cout << "---GLViewer_ViewPort2d::onDragObject()---" << endl;
282 GLViewer_Viewer2d* aViewer = (GLViewer_Viewer2d*)getViewFrame()->getViewer();
283 GLViewer_Context* aContext = aViewer->getGLContext();
284 GLViewer_Object* anObject = aContext->getCurrentObject();
289 float aX = e->pos().x();
290 float anY = e->pos().y();
291 aViewer->transPoint( aX, anY );
293 if( myCurDragPosX == NULL && myCurDragPosY == NULL )
295 myCurDragPosX = new float(aX);
296 myCurDragPosY = new float(anY);
300 //QPoint aNewPos = e->pos();
301 //GLViewer_Viewer2d* aViewer = (GLViewer_Viewer2d*)getViewFrame()->getViewer();
303 if( anObject && (e->buttons() & Qt::LeftButton ) )
305 if( aContext->isSelected( anObject ) )
307 for( aContext->InitSelected(); aContext->MoreSelected(); aContext->NextSelected() )
309 GLViewer_Object* aMovingObject = aContext->SelectedObject();
311 aMovingObject->moveObject( aX - *myCurDragPosX, anY - *myCurDragPosY);
315 anObject->moveObject( aX - *myCurDragPosX, anY - *myCurDragPosY);
317 else if( aContext->NbSelected() && (e->buttons() & Qt::MidButton ) )
318 for( aContext->InitSelected(); aContext->MoreSelected(); aContext->NextSelected() )
319 (aContext->SelectedObject())->moveObject( aX - *myCurDragPosX, anY - *myCurDragPosY);
321 delete myCurDragPosX;
322 delete myCurDragPosY;
323 myCurDragPosX = new float(aX);
324 myCurDragPosY = new float(anY);
326 myGLWidget->updateGL();
330 Emits 'mouseEvent' signal. [ virtual protected ]
332 void GLViewer_ViewPort2d::mousePressEvent( QMouseEvent* e )
334 emit vpMouseEvent( e );
336 GLViewer_Viewer2d* aViewer = (GLViewer_Viewer2d*)getViewFrame()->getViewer();
337 GLViewer_Context* aContext = aViewer->getGLContext();
339 GLViewer_Object* anObject = NULL;
341 anObject = aContext->getCurrentObject();
343 bool accel = e->modifiers() & GLViewer_ViewTransformer::accelKey();
344 if( ( anObject && !( accel || e->button() == Qt::RightButton ) ) ||
345 ( aContext->NbSelected() && !accel && e->button() == Qt::MidButton ) )
347 myIsDragProcess = inDrag;
352 Emits 'mouseEvent' signal. [ virtual protected ]
354 void GLViewer_ViewPort2d::mouseMoveEvent( QMouseEvent* e )
356 emit vpMouseEvent( e );
358 if( myIsDragProcess == inDrag )
361 /*GLViewer_Viewer2d* aViewer = (GLViewer_Viewer2d*)getViewFrame()->getViewer();
362 GLViewer_Context* aContext = aViewer->getGLContext();
364 GLViewer_Object* anObj = aContext->getCurrentObject();
365 if( anObj && aContext->currentObjectIsChanged() )
367 //cout << "GLViewer_ViewPort2d::mouseMoveEvent{QToolTip::add}" << endl;
368 //QToolTip::remove( myGLWidget );
369 QRect* aRect = (aViewer->getWinObjectRect(anObj));
370 //QToolTip::add( myGLWidget, *aRect, anObj->getToolTipText() );
371 myGLWidget->addToolTip( anObj->getToolTipText(), *aRect );
375 //cout << "GLViewer_ViewPort2d::mouseMoveEvent{QToolTip::remove}" << endl;
376 //QRect* aRect = (aViewer->getWinObjectRect(anObj));
377 //QToolTip::remove( myGLWidget, *aRect );
378 myGLWidget->removeToolTip();
383 Emits 'mouseEvent' signal. [ virtual protected ]
385 void GLViewer_ViewPort2d::mouseReleaseEvent( QMouseEvent* e )
387 if ( myIsMouseReleaseBlock )
389 // skip mouse release after double click
390 myIsMouseReleaseBlock = false;
394 /* show popup menu */
395 if ( e->button() == Qt::RightButton )
397 //QPopupMenu* popup = createPopup();
398 //if ( popup && popup->count() )
399 // popup->exec( QCursor::pos() );
400 //destroyPopup( /*popup*/ );
402 emit vpMouseEvent( e );
404 if( myIsDragProcess == inDrag )
406 bool isAnyMoved = false;
407 GLViewer_Viewer2d* aViewer = (GLViewer_Viewer2d*)getViewFrame()->getViewer();
408 GLViewer_Context* aContext = aViewer->getGLContext();
409 GLViewer_Object* aMovingObject;
410 for( aContext->InitSelected(); aContext->MoreSelected(); aContext->NextSelected() )
412 aMovingObject = aContext->SelectedObject();
414 isAnyMoved = aMovingObject->finishMove() || isAnyMoved;
417 aMovingObject = aContext->getCurrentObject();
419 isAnyMoved = aMovingObject->finishMove() || isAnyMoved;
421 myIsDragProcess = noDrag;
422 //myCurDragMousePos.setX( 0 );
423 //myCurDragMousePos.setY( 0 );
424 delete myCurDragPosX;
425 delete myCurDragPosY;
426 myCurDragPosX = NULL;
427 myCurDragPosY = NULL;
432 aViewer->updateBorders();
438 Custom mouse double click event handler
440 void GLViewer_ViewPort2d::mouseDoubleClickEvent( QMouseEvent * e )
442 //redefined to block mouse release after mouse double click
443 myIsMouseReleaseBlock = true;
444 // invoke base implementation
445 GLViewer_ViewPort::mouseDoubleClickEvent( e );
449 Creates or deletes compass
450 \param on - if it is true, then to create
452 void GLViewer_ViewPort2d::turnCompass( GLboolean on )
455 myCompass = new GLViewer_Compass( Qt::green, 30, GLViewer_Compass::TopRight, 10, 5, 12, 3 );
461 Creates or deletes grid
462 \param on - if it is true, then to create
464 void GLViewer_ViewPort2d::turnGrid( GLboolean on )
468 myGrid = new GLViewer_Grid( 2*WIDTH, 2*HEIGHT,
470 GRID_XSIZE, GRID_YSIZE,
472 myXScale, myYScale );
480 \param gridColor - new grid color
481 \param axisColor - new axis color
483 void GLViewer_ViewPort2d::setGridColor( const QColor gridColor, const QColor axisColor )
487 myGrid->setGridColor( ( GLfloat )gridColor.red() / 255,
488 ( GLfloat )gridColor.green() / 255,
489 ( GLfloat )gridColor.blue() / 255 );
490 myGrid->setAxisColor( ( GLfloat )axisColor.red() / 255,
491 ( GLfloat )axisColor.green() / 255,
492 ( GLfloat )axisColor.blue() / 255 );
497 Changes background color
498 \param color - new background color
500 void GLViewer_ViewPort2d::setBackgroundColor( const QColor& color )
502 GLViewer_ViewPort::setBackgroundColor( color );
503 myGLWidget->makeCurrent();
504 glClearColor( ( GLfloat )color.red() / 255,
505 ( GLfloat )color.green() / 255,
506 ( GLfloat )color.blue() / 255, 1.0 );
507 myGLWidget->repaint();
511 \return background color
513 QColor GLViewer_ViewPort2d::backgroundColor() const
515 return GLViewer_ViewPort::backgroundColor();
521 void GLViewer_ViewPort2d::initResize( int x, int y )
523 float xa, xb, ya, yb;
524 xa = myBorder->left() - myMargin;
525 xb = myBorder->right() + myMargin;
526 ya = myBorder->top() - myMargin;
527 yb = myBorder->bottom() + myMargin;
529 GLfloat zoom, xzoom, yzoom;
534 xzoom = (GLfloat)x / myWidth;
535 yzoom = (GLfloat)y / myHeight;
537 if ( ( xzoom < yzoom ) && ( xzoom < 1 ) )
539 else if ( ( yzoom < xzoom ) && ( yzoom < 1 ) )
544 zoom = xzoom > yzoom ? xzoom : yzoom;
547 if ( !max && ( ! ( ( ( myXPan + w/2 ) < xb * myXScale * zoom ) ||
548 ( ( myXPan - w/2 ) > xa * myXScale * zoom ) ||
549 ( ( myYPan + h/2 ) < yb * myYScale * zoom ) ||
550 ( ( myYPan - h/2 ) > ya * myYScale * zoom ) ) ) )
553 if ( max && ( ( ( myXPan + w/2 ) < xb * myXScale * zoom ) ||
554 ( ( myXPan - w/2 ) > xa * myXScale * zoom ) ||
555 ( ( myYPan + h/2 ) < yb * myYScale * zoom ) ||
556 ( ( myYPan - h/2 ) > ya * myYScale * zoom ) ) )
566 myGrid->setResize( 2*x, 2*y, zoom );
568 myGLWidget->setScale( myXScale, myYScale, 1.0 );
572 Custom paint event handler
574 void GLViewer_ViewPort2d::paintEvent( QPaintEvent* e )
576 //cout << "GLViewer_ViewPort2d::paintEvent" << endl;
577 myGLWidget->updateGL();
578 GLViewer_ViewPort::paintEvent( e );
582 Custom resize event handler
584 void GLViewer_ViewPort2d::resizeEvent( QResizeEvent* e )
586 //cout << "GLViewer_ViewPort2d::resizeEvent" << endl;
587 GLViewer_ViewPort::resizeEvent( e );
591 Resets view to start state
593 void GLViewer_ViewPort2d::reset()
595 //cout << "GLViewer_ViewPort2d::reset" << endl;
598 GLint vpWidth, vpHeight;
600 myGLWidget->makeCurrent();
601 glGetIntegerv( GL_VIEWPORT, val );
605 GLint w = myGLWidget->getWidth();
606 GLint h = myGLWidget->getHeight();
607 GLfloat zoom = vpWidth / ( GLfloat )w < vpHeight / ( GLfloat )h ?
608 vpWidth / ( GLfloat )w : vpHeight / ( GLfloat )h;
612 myGrid->setPan( 0.0, 0.0 );
613 myGrid->setZoom( zoom / myXScale );
621 myGLWidget->setPan( myXPan, myYPan, 0.0 );
622 myGLWidget->setScale( myXScale, myYScale, 1.0 );
623 myGLWidget->setRotationAngle( 0.0 );
624 myGLWidget->setRotation( 0.0, 0.0, 0.0, 1.0 );
625 myGLWidget->updateGL();
633 void GLViewer_ViewPort2d::pan( int dx, int dy )
635 //cout << "GLViewer_ViewPort2d::pan " << dx << " " << dy << endl;
637 /*myXPan += dx / myXScale;
638 myYPan += dy / myYScale;
640 float ra, rx, ry, rz;
641 myGLWidget->getRotation( ra, rx, ry, rz );
642 GLfloat angle = ra * PI / 180.;
645 myGrid->setPan( myXPan*cos(angle) + myYPan*sin(angle),
646 -myXPan*sin(angle) + myYPan*cos(angle) );
649 float ra, rx, ry, rz;
650 myGLWidget->getRotation( ra, rx, ry, rz );
651 GLfloat angle = ra * PI / 180.;
653 myXPan += (dx*cos(angle) + dy*sin(angle)) / myXScale;
654 myYPan += (-dx*sin(angle) + dy*cos(angle)) / myXScale;
657 myGrid->setPan( myXPan, myYPan );
659 myGLWidget->setPan( myXPan, myYPan, 0.0 );
660 myGLWidget->setScale( myXScale, myYScale, 1.0 );
661 myGLWidget->updateGL();
665 Sets view center in global coords
666 \param x, y - global co-ordinates of center
668 void GLViewer_ViewPort2d::setCenter( int x, int y )
670 //cout << "GLViewer_ViewPort2d::setCenter" << endl;
673 GLint vpWidth, vpHeight;
675 myGLWidget->makeCurrent();
676 glGetIntegerv( GL_VIEWPORT, val );
680 myXPan -= ( x - vpWidth/2 ) / myXScale;
681 myYPan += ( y - vpHeight/2 ) / myYScale;
685 myGrid->setPan( myXPan, myYPan );
686 myGrid->setZoom( myXOldScale / myXScale );
689 myXScale = myXOldScale;
690 myYScale = myYOldScale;
692 myGLWidget->setPan( myXPan, myYPan, 0.0 );
693 myGLWidget->setScale( myXScale, myYScale, 1.0 );
694 myGLWidget->updateGL();
698 Process zoming transformation with mouse tracking from ( x0, y0 ) to ( x1, y1 )
700 void GLViewer_ViewPort2d::zoom( int x0, int y0, int x, int y )
702 //cout << "GLViewer_ViewPort2d::zoom" << endl;
708 if ( dx == 0. && dy == 0. )
711 zm = sqrt(dx * dx + dy * dy) / 100. + 1;
712 zm = (dx > 0.) ? zm : 1. / zm;
722 if( myGrid->setZoom( zm ) )
724 myGLWidget->setPan( myXPan, myYPan, 0.0 );
725 myGLWidget->setScale( myXScale, myYScale, 1.0 );
726 myGLWidget->updateGL();
736 myGLWidget->setPan( myXPan, myYPan, 0.0 );
737 myGLWidget->setScale( myXScale, myYScale, 1.0 );
738 myGLWidget->updateGL();
743 Transforms view by rectangle
744 \param rect - rectangle
746 void GLViewer_ViewPort2d::fitRect( const QRect& rect )
748 float x0, x1, y0, y1;
749 float dx, dy, zm, centerX, centerY;
752 GLint vpWidth, vpHeight;
754 myGLWidget->makeCurrent();
755 glGetIntegerv( GL_VIEWPORT, val );
764 dx = fabs( x1 - x0 );
765 dy = fabs( y1 - y0 );
766 centerX = ( x0 + x1 ) / 2.;
767 centerY = ( y0 + y1 ) / 2.;
769 if ( dx == 0. || dy == 0. )
772 zm = vpWidth / dx < vpHeight / dy ? vpWidth / dx : vpHeight / dy;
774 float aDX = ( vpWidth / 2. - centerX ) / myXScale;
775 float aDY = ( vpHeight / 2. - centerY ) / myYScale;
777 float ra, rx, ry, rz;
778 myGLWidget->getRotation( ra, rx, ry, rz );
779 GLfloat angle = ra * PI / 180.;
781 myXPan += (aDX*cos(angle) - aDY*sin(angle));
782 myYPan -= (aDX*sin(angle) + aDY*cos(angle));
785 myGrid->setPan( myXPan, myYPan );
791 myGrid->setZoom( zm );
793 myGLWidget->setPan( myXPan, myYPan, 0.0 );
794 myGLWidget->setScale( myXScale, myYScale, 1.0 );
795 myGLWidget->updateGL();
799 Transforms view by selection
801 void GLViewer_ViewPort2d::fitSelect()
803 GLViewer_Viewer2d* aViewer = (GLViewer_Viewer2d*)getViewFrame()->getViewer();
804 GLViewer_Context* aContext = aViewer->getGLContext();
809 for( aContext->InitSelected(); aContext->MoreSelected(); aContext->NextSelected() )
810 aSelRect |= *(aViewer->getWinObjectRect( aContext->SelectedObject() ));
812 if( aSelRect.isValid() )
814 aSelRect.setTop( aSelRect.top() - SELECTION_RECT_GAP );
815 aSelRect.setBottom( aSelRect.bottom() + SELECTION_RECT_GAP );
816 aSelRect.setLeft( aSelRect.left() - SELECTION_RECT_GAP );
817 aSelRect.setRight( aSelRect.right() + SELECTION_RECT_GAP );
823 Transform view by view borders
824 \param keepScale - if it is true, zoom does not change
826 void GLViewer_ViewPort2d::fitAll( bool keepScale, bool withZ )
828 //cout << "GLViewer_ViewPort2d::fitAll" << endl;
830 float xa, xb, ya, yb;
832 float xScale, yScale;
834 myMargin = qMax( myBorder->width(), myBorder->height() ) / 5;
836 xa = myBorder->left() - myMargin;
837 xb = myBorder->right() + myMargin;
838 ya = myBorder->bottom() - myMargin;
839 yb = myBorder->top() + myMargin;
841 float aPoints[8] = { xa, ya, xb, ya, xa, yb, xb, yb };
843 float ra, rx, ry, rz;
844 myGLWidget->getRotation( ra, rx, ry, rz );
845 float angle = ra * PI / 180.;
848 for( i = 0; i < 7; i = i + 2 )
849 rotate_point( aPoints[i], aPoints[i+1], angle );
851 float aBorders[4] = { aPoints[0], aPoints[0], aPoints[1], aPoints[1] };
853 for( i = 2; i < 7; i = i + 2 )
855 if( aBorders[0] < aPoints[i] )
856 aBorders[0] = aPoints[i];
857 if( aBorders[1] > aPoints[i] )
858 aBorders[1] = aPoints[i];
860 if( aBorders[2] < aPoints[i+1] )
861 aBorders[2] = aPoints[i+1];
862 if( aBorders[3] > aPoints[i+1] )
863 aBorders[3] = aPoints[i+1];
867 GLint vpWidth, vpHeight;
869 myGLWidget->makeCurrent();
870 glGetIntegerv( GL_VIEWPORT, val );
874 dx = fabs( aBorders[1] - aBorders[0] );
875 dy = fabs( aBorders[3] - aBorders[2] );
877 myXPan = -( aBorders[0] + aBorders[1] ) / 2;
878 myYPan = -( aBorders[2] + aBorders[3] ) / 2;
883 myXOldScale = myXScale;
884 myYOldScale = myYScale;
890 zm = vpWidth / dx < vpHeight / dy ? vpWidth / dx : vpHeight / dy;
899 myGrid->setPan( myXPan, myYPan );
901 myGrid->setZoom( zm / xScale );
903 myGrid->setZoom( zm / yScale );
906 myGLWidget->setPan( myXPan, myYPan, 0.0 );
907 myGLWidget->setScale( myXScale, myYScale, 1.0 );
908 myGLWidget->updateGL();
911 emit vpUpdateValues();
916 \param x, y - start point
918 void GLViewer_ViewPort2d::startRotation( int x, int y )
920 myGLWidget->setRotationStart( x, y, 1.0 );
925 \param intX, intY - current point
927 void GLViewer_ViewPort2d::rotate( int intX, int intY )
930 GLint vpWidth, vpHeight;
932 myGLWidget->makeCurrent();
933 glGetIntegerv( GL_VIEWPORT, val );
937 float x = intX, y = intY;
938 float x0 = vpWidth/2;
939 float y0 = vpHeight/2;
941 float xs, ys, zs, dx, dy;
942 myGLWidget->getRotationStart( xs, ys, zs );
951 float l1 = pow( double( xs*xs + ys*ys ), 0.5 );
952 float l2 = pow( double( x*x + y*y ), 0.5 );
953 float l = pow( double( dx*dx + dy*dy ), 0.5 );
955 double mult = xs * y - x * ys;
957 if( mult > 0 ) sign = 1;
958 else if( mult < 0 ) sign = -1;
961 float anglePrev = myGLWidget->getRotationAngle();
962 float angleNew = sign * acos( ( l1*l1 + l2*l2 - l*l ) / ( 2 * l1 * l2 )) * 180. / PI;
963 float angle = anglePrev + angleNew;
965 // GLfloat anAngle = angle * PI / 180.; unused
967 float ra, rx, ry, rz;
968 myGLWidget->getRotation( ra, rx, ry, rz );
969 myGLWidget->setRotation( angle, rx, ry, rz );
970 myGLWidget->updateGL();
976 void GLViewer_ViewPort2d::endRotation()
978 float ra, rx, ry, rz;
979 myGLWidget->getRotation( ra, rx, ry, rz );
980 myGLWidget->setRotationAngle( ra );
986 void GLViewer_ViewPort2d::drawCompass()
988 if( !myCompass->getVisible() )
991 GLfloat xScale, yScale, xPan, yPan;
993 int xPos = getWidth();
994 int yPos = getHeight();
996 int cPos = myCompass->getPos();
997 int cSize = myCompass->getSize();
998 QColor cCol = myCompass->getColor();
999 int cWidthTop = myCompass->getArrowWidthTop();
1000 int cWidthBot = myCompass->getArrowWidthBottom();
1001 int cHeightTop = myCompass->getArrowHeightTop();
1002 int cHeightBot = myCompass->getArrowHeightBottom();
1004 GLfloat colorR = (cCol.red())/255;
1005 GLfloat colorG = (cCol.green())/255;
1006 GLfloat colorB = (cCol.blue())/255;
1008 float delX = cSize * 0.5;
1009 float delY = cSize * 0.5;
1011 getScale( xScale, yScale );
1012 getPan( xPan, yPan);
1014 float centerX = (xPos/2 - delX - cSize)/xScale;
1015 float centerY = (yPos/2 - delY - cSize)/yScale;
1019 case GLViewer_Compass::TopLeft:
1022 case GLViewer_Compass::BottomLeft:
1026 case GLViewer_Compass::BottomRight:
1032 float ra, rx, ry, rz;
1033 myGLWidget->getRotation( ra, rx, ry, rz );
1034 GLfloat angle = ra * PI / 180.;
1035 GLfloat /*r = 0.0,*/ x = 0.0 , y = 0.0;
1037 rotate_point( centerX, centerY, -angle );
1042 glColor3f( colorR, colorG, colorB );
1043 glBegin( GL_POLYGON );
1045 x = centerX; y = centerY + cSize / yScale;
1048 x = centerX + cWidthTop / xScale; y = centerY + ( cSize - cHeightTop ) / yScale ;
1051 x = centerX + cWidthBot / xScale; y = centerY + ( cSize - cHeightTop ) / yScale ;
1054 x = centerX + cWidthBot / xScale; y = centerY - cSize/yScale;
1057 x = centerX; y = centerY - (cSize - cHeightBot) / yScale ;
1060 x = centerX - cWidthBot / xScale; y = centerY - cSize/yScale;
1063 x = centerX - cWidthBot / xScale; y = centerY + ( cSize - cHeightTop ) / yScale ;
1066 x = centerX - cWidthTop / xScale; y = centerY + ( cSize - cHeightTop ) / yScale ;
1070 glEnable( GL_LINE_SMOOTH );
1071 glBegin(GL_LINE_LOOP);
1073 float aCircAngle = 0;
1074 for ( int i = 0; i < 20 * SEGMENTS + 1; i++ )
1076 x = centerX + cos(aCircAngle) * cSize / xScale;
1077 y = centerY + sin(aCircAngle) * cSize / yScale;
1079 aCircAngle += float( STEP ) / 2;
1083 GLdouble modelMatrix[16], projMatrix[16];
1085 GLdouble winxN, winyN, winz;
1086 GLdouble winxE, winyE;
1087 GLdouble winxS, winyS;
1088 GLdouble winxW, winyW;
1091 GLViewer_TexFont* aFont = myCompass->getFont();
1092 float widN = (float)aFont->getStringWidth( "N" );
1093 float widW = (float)aFont->getStringWidth( "W" );
1094 float widS = (float)aFont->getStringWidth( "S" );
1095 float widE = (float)aFont->getStringWidth( "E" );
1096 float heightL = (float)aFont->getStringHeight();
1098 float xGapN = - widN/2 *( 1.0 + sin(angle) );
1099 float xGapS = - widS/2 *( 1.0 - sin(angle) );
1100 float xGapW = - widW/2 *( 1.0 + cos(angle) );
1101 float xGapE = - widE/2 *( 1.0 - cos(angle) );
1103 float yGapN = - heightL/2 *( 1.0 - cos(angle) ) * 0.75;
1104 float yGapS = - heightL/2 *( 1.0 + cos(angle) ) * 0.75;
1105 float yGapW = - heightL/2 *( 1.0 + sin(angle) ) * 0.75;
1106 float yGapE = - heightL/2 *( 1.0 - sin(angle) ) * 0.75;
1108 glGetIntegerv (GL_VIEWPORT, viewport);
1109 glGetDoublev (GL_MODELVIEW_MATRIX, modelMatrix);
1110 glGetDoublev (GL_PROJECTION_MATRIX, projMatrix);
1112 gluProject (centerX, centerY + cSize / yScale, 0, modelMatrix, projMatrix, viewport, &winxN, &winyN, &winz);
1113 gluProject (centerX + cSize / xScale, centerY, 0, modelMatrix, projMatrix, viewport, &winxE, &winyE, &winz);
1114 gluProject (centerX, centerY - cSize / yScale, 0, modelMatrix, projMatrix, viewport, &winxS, &winyS, &winz);
1115 gluProject (centerX - cSize / xScale, centerY, 0, modelMatrix, projMatrix, viewport, &winxW, &winyW, &winz);
1117 glColor3f( 1.0, 1.0, 1.0 );
1119 aTextList = glGenLists( 1 );
1120 glNewList( aTextList, GL_COMPILE );
1122 glMatrixMode(GL_PROJECTION);
1125 glOrtho(0,viewport[2],0,viewport[3],-100,100);
1126 glMatrixMode(GL_MODELVIEW);
1130 aFont->drawString( "N", winxN + xGapN, winyN + yGapN );
1131 aFont->drawString( "E", winxE + xGapE, winyE + yGapE );
1132 aFont->drawString( "S", winxS + xGapS, winyS + yGapS );
1133 aFont->drawString( "W", winxW + xGapW, winyW + yGapW );
1135 glMatrixMode(GL_PROJECTION);
1137 glMatrixMode(GL_MODELVIEW);
1142 if ( aTextList != -1 )
1143 glCallList( aTextList );
1147 \return blocking status for current started operations
1149 BlockStatus GLViewer_ViewPort2d::currentBlock()
1151 if( myIsDragProcess == inDrag && myCurDragPosX != NULL && myCurDragPosY != NULL)
1152 return BlockStatus(BS_Highlighting | BS_Selection);
1154 if( mypFirstPoint && mypLastPoint )
1155 return BlockStatus(BS_Highlighting | BS_Selection);
1161 Initializes rectangle selection
1162 \param x, y - start point
1164 void GLViewer_ViewPort2d::startSelectByRect( int x, int y )
1166 if( !mypFirstPoint && !mypLastPoint )
1168 mypFirstPoint = new QPoint( x, y );
1169 mypLastPoint = new QPoint( x, y );
1172 if ( !myRectBand ) {
1173 myRectBand = new QRubberBand( QRubberBand::Rectangle, this );
1175 palette.setColor(myRectBand->foregroundRole(), Qt::white);
1176 myRectBand->setPalette(palette);
1182 Draws rectangle selection
1183 \param x, y - current point
1185 void GLViewer_ViewPort2d::drawSelectByRect( int x, int y )
1187 if( mypFirstPoint && mypLastPoint )
1189 myRectBand->hide(); /* erase */
1191 mypLastPoint->setX( x );
1192 mypLastPoint->setY( y );
1194 QRect aRect = selectionRect();
1195 myRectBand->setGeometry( aRect ); /* draw */
1196 myRectBand->setVisible( aRect.isValid() );
1202 Finishes rectangle selection
1204 void GLViewer_ViewPort2d::finishSelectByRect()
1206 if( mypFirstPoint && mypLastPoint )
1210 if ( myRectBand ) myRectBand->hide(); /* erase */
1212 delete mypFirstPoint;
1213 delete mypLastPoint;
1215 mypFirstPoint = NULL;
1216 mypLastPoint = NULL;
1224 \return rectangle selection
1226 QRect GLViewer_ViewPort2d::selectionRect()
1229 if( mypFirstPoint && mypLastPoint )
1231 aRect.setLeft( qMin( mypFirstPoint->x(), mypLastPoint->x() ) );
1232 aRect.setTop( qMin( mypFirstPoint->y(), mypLastPoint->y() ) );
1233 aRect.setRight( qMax( mypFirstPoint->x(), mypLastPoint->x() ) );
1234 aRect.setBottom( qMax( mypFirstPoint->y(), mypLastPoint->y() ) );
1242 bool GLViewer_ViewPort2d::startPulling( GLViewer_Pnt point )
1244 GLViewer_Viewer2d* aViewer = (GLViewer_Viewer2d*)getViewFrame()->getViewer();
1245 GLViewer_Context* aContext = aViewer->getGLContext();
1246 ObjList anObjects = aContext->getObjects();
1248 for( ObjList::Iterator it = anObjects.begin(); it != anObjects.end(); ++it )
1250 GLViewer_Object* anObject = *it;
1251 GLViewer_Rect aRect = anObject->getPullingRect();
1253 if( aRect.contains( point ) && anObject->startPulling( point ) )
1256 myPullingObject = anObject;
1257 setCursor( *getHandCursor() );
1267 void GLViewer_ViewPort2d::drawPulling( GLViewer_Pnt point )
1269 GLViewer_Viewer2d* aViewer = (GLViewer_Viewer2d*)getViewFrame()->getViewer();
1270 GLViewer_Context* aContext = aViewer->getGLContext();
1271 ObjList anObjects = aContext->getObjects();
1273 GLViewer_Object* aLockedObject = 0;
1274 for( ObjList::Iterator it = anObjects.begin(); it != anObjects.end(); ++it )
1276 GLViewer_Object* anObject = *it;
1277 if( !anObject->getVisible() )
1280 GLViewer_Rect aRect = anObject->getPullingRect();
1282 if( aRect.contains( point ) && anObject->portContains( point ) )
1284 aLockedObject = anObject;
1289 myPullingObject->pull( point, aLockedObject );
1294 void GLViewer_ViewPort2d::finishPulling()
1296 myIsPulling = false;
1297 myPullingObject->finishPulling();
1298 setCursor( *getDefaultCursor() );
1302 Convert rectangle in window co-ordinates to GL co-ordinates
1303 \return converted rectangle
1305 GLViewer_Rect GLViewer_ViewPort2d::win2GLV( const QRect& theRect ) const
1307 GLViewer_Rect aRect;
1309 GLdouble modelMatrix[16], projMatrix[16];
1312 GLdouble objx1, objy1;
1313 GLdouble objx2, objy2;
1316 glGetIntegerv (GL_VIEWPORT, viewport);
1317 glGetDoublev (GL_MODELVIEW_MATRIX, modelMatrix);
1318 glGetDoublev (GL_PROJECTION_MATRIX, projMatrix);
1320 gluUnProject( theRect.left(), viewport[3] - theRect.top(), 0, modelMatrix, projMatrix, viewport, &objx1, &objy1, &objz );
1321 gluUnProject( theRect.right(), viewport[3] - theRect.bottom(), 0, modelMatrix, projMatrix, viewport, &objx2, &objy2, &objz );
1323 aRect.setLeft( objx1 );
1324 aRect.setTop( objy1 );
1325 aRect.setRight( objx2 );
1326 aRect.setBottom( objy2 );
1332 Convert rectangle in GL co-ordinates to window co-ordinates
1333 \return converted rectangle
1335 QRect GLViewer_ViewPort2d::GLV2win( const GLViewer_Rect& theRect ) const
1339 GLdouble modelMatrix[16], projMatrix[16];
1342 GLdouble winx1, winy1;
1343 GLdouble winx2, winy2;
1346 glGetIntegerv (GL_VIEWPORT, viewport);
1347 glGetDoublev (GL_MODELVIEW_MATRIX, modelMatrix);
1348 glGetDoublev (GL_PROJECTION_MATRIX, projMatrix);
1350 gluProject( theRect.left(), theRect.top(), 0, modelMatrix, projMatrix, viewport, &winx1, &winy1, &winz );
1351 gluProject( theRect.right(), theRect.bottom(), 0, modelMatrix, projMatrix, viewport, &winx2, &winy2, &winz );
1353 aRect.setLeft( (int)winx1 );
1354 aRect.setTop( viewport[3] - (int)winy1 );
1355 aRect.setRight( (int)winx2 );
1356 aRect.setBottom( viewport[3] - (int)winy2 );
1362 SLOT: called when tooltip should be shown
1364 void GLViewer_ViewPort2d::onMaybeTip( QPoint thePoint, QString& theText, QFont& theFont, QRect& theTextReg, QRect& theRegion )
1366 GLViewer_Context* aContext = ((GLViewer_Viewer2d*)getViewFrame()->getViewer())->getGLContext();
1368 GLViewer_Object* anObj = aContext->getCurrentObject();
1371 theText = anObj->getToolTipText();
1372 if( theText.isEmpty() )
1373 theText = anObj->getName();
1376 if( anObj->isTooTipHTML() )
1377 aList = theText.split( "<br>", QString::SkipEmptyParts );
1379 aList = theText.split( "\n", QString::SkipEmptyParts );
1381 if( !aList.isEmpty() )
1384 int str_size = aList.first().length();
1385 for( int i = 1, size = aList.count(); i < size; i++ )
1387 if ( str_size < (int)aList[i].length() )
1390 str_size = aList[i].length();
1394 int cur_height = 24;
1395 QCursor* aCursor = QApplication::overrideCursor();
1398 const QBitmap* aBitmap = aCursor->bitmap();
1400 cur_height = aBitmap->height();
1404 QSize aSize = QLabel( theText, 0 ).sizeHint();
1405 theTextReg = QRect( thePoint.x(), thePoint.y() + cur_height,
1406 aSize.width(), aSize.height() );
1407 theRegion = QRect( thePoint.x(), thePoint.y(), 1, 1 );