1 // Copyright (C) 2007-2023 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 // Author : OPEN CASCADE
24 // File: GLViewer_ViewPort2d.cxx
25 // Created: November, 2004
27 /* GLViewer_ViewPort2d Source File */
29 //#include <GLViewerAfx.h>
30 #include "GLViewer_ViewPort2d.h"
31 #include "GLViewer_Viewer2d.h"
32 #include "GLViewer_ViewFrame.h"
33 #include "GLViewer_MimeData.h"
34 #include "GLViewer_Context.h"
35 #include "GLViewer_Compass.h"
36 #include "GLViewer_Grid.h"
37 #include "GLViewer_Drawer.h"
39 // TODO: Porting to Qt4
40 //#include <QtxToolTip.h>
42 #include <QHBoxLayout>
43 #include <QMouseEvent>
47 #include <QApplication>
52 #include <QRubberBand>
58 #define GRID_XSIZE 100
59 #define GRID_YSIZE 100
61 int static aLastViewPostId = 0;
63 void rotate_point( float& theX, float& theY, float theAngle )
65 float aTempX = theX * cos(theAngle) - theY * sin(theAngle);
66 float aTempY = theX * sin(theAngle) + theY * cos(theAngle);
74 GLViewer_ViewPort2d::GLViewer_ViewPort2d( QWidget* parent, GLViewer_ViewFrame* theViewFrame )
75 : GLViewer_ViewPort( parent ),
76 myMargin( MARGIN ), myHeight( HEIGHT ), myWidth( WIDTH ),
77 myXScale( 1.0 ), myYScale( 1.0 ), myXOldScale( 1.0 ), myYOldScale( 1.0 ),
78 myXPan( 0.0 ), myYPan( 0.0 ),
79 myIsMouseReleaseBlock( false ),
83 myViewFrame = (GLViewer_ViewFrame*)parent;
85 myViewFrame = theViewFrame;
89 myBorder = new GLViewer_Rect();
91 QBoxLayout* qbl = new QHBoxLayout( this );
95 myGLWidget = new GLViewer_Widget( this, 0 ) ;
96 qbl->addWidget( myGLWidget );
97 myGLWidget->setFocusProxy( this );
98 setMouseTracking( true );
100 myIsDragProcess = noDrag;
101 //myCurDragMousePos = QPoint();
102 myCurDragPosX = NULL;
103 myCurDragPosY = NULL;
107 myViewPortId = aLastViewPostId;
110 mypFirstPoint = NULL;
113 // TODO: Porting to Qt4
114 /*myObjectTip = new QtxToolTip( myGLWidget );///GLViewer_ObjectTip( this );
115 myObjectTip->setShowDelayTime( 60000 );
116 connect( myObjectTip, SIGNAL( maybeTip( QPoint, QString&, QFont&, QRect&, QRect& ) ),
117 this, SLOT( onMaybeTip( QPoint, QString&, QFont&, QRect&, QRect& ) ) );*/
118 // myGLWidget->installEventFilter( myObjectTip );
124 GLViewer_ViewPort2d::~GLViewer_ViewPort2d()
135 if ( myRectBand ) myRectBand->hide();
140 SLOT: initializes drag process
142 void GLViewer_ViewPort2d::onStartDragObject( )
144 if( myIsDragProcess == noDrag )
146 myIsDragProcess = initDrag;
147 QCursor::setPos( (int)(*myCurDragPosX), (int)(*myCurDragPosY) );
148 //myCurDragMousePos = QPoint( 0, 0 );
149 delete myCurDragPosX;
150 delete myCurDragPosY;
151 myCurDragPosX = NULL;
152 myCurDragPosY = NULL;
158 SLOT: cuts object to clipboard
160 void GLViewer_ViewPort2d::onCutObject()
162 /*GLViewer_Object* aMovingObject = ((GLViewer_Viewer2d*)getViewFrame()->getViewer())->getGLContext()->getCurrentObject();
165 GLViewer_MimeSource* aMimeSource = new GLViewer_MimeSource();
166 aMimeSource->setObject( aMovingObject );
168 QClipboard *aClipboard = QApplication::clipboard();
170 aClipboard->setData( aMimeSource );
172 ((GLViewer_Viewer2d*)getViewFrame()->getViewer())->getGLContext()->deleteObject( aMovingObject );
174 GLViewer_Context* aContext = ((GLViewer_Viewer2d*)getViewFrame()->getViewer())->getGLContext();
175 int aObjNum = aContext->NbSelected();
178 QList<GLViewer_Object*> aObjects;
179 GLViewer_MimeData* aMimeData = new GLViewer_MimeData();
180 aContext->InitSelected();
181 for( ; aContext->MoreSelected(); aContext->NextSelected() )
182 aObjects.append( aContext->SelectedObject() );
184 //aMimeData->setObjects( aObjects ); ouv 6.05.04
186 QClipboard *aClipboard = QApplication::clipboard();
188 aClipboard->setMimeData( aMimeData );
190 for( int i = 0; i < aObjNum; i++ )
191 aContext->deleteObject( aObjects[i] );
196 SLOT: copies object to clipboard
198 void GLViewer_ViewPort2d::onCopyObject()
200 /*GLViewer_Object* aMovingObject = ((GLViewer_Viewer2d*)getViewFrame()->getViewer())->getGLContext()->getCurrentObject();
203 GLViewer_MimeSource* aMimeSource = new GLViewer_MimeSource();
204 aMimeSource->setObject( aMovingObject );
206 QClipboard *aClipboard = QApplication::clipboard();
208 aClipboard->setData( aMimeSource );
211 GLViewer_Context* aContext = ((GLViewer_Viewer2d*)getViewFrame()->getViewer())->getGLContext();
212 int aObjNum = aContext->NbSelected();
215 QList<GLViewer_Object*> aObjects;
216 GLViewer_MimeData* aMimeData = new GLViewer_MimeData();
217 aContext->InitSelected();
218 for( ; aContext->MoreSelected(); aContext->NextSelected() )
219 aObjects.append( aContext->SelectedObject() );
221 //aMimeData->setObjects( aObjects ); ouv 6.05.04
223 QClipboard *aClipboard = QApplication::clipboard();
225 aClipboard->setMimeData( aMimeData );
230 SLOT: pastes object from clipboard
232 void GLViewer_ViewPort2d::onPasteObject()
234 /*QClipboard *aClipboard = QApplication::clipboard();
235 QMimeSource* aMimeSource = aClipboard->data();
236 if( aMimeSource->provides( "GLViewer_Object" ) )
243 aType = aMimeSource->format( i );
244 anArray = aMimeSource->encodedData( aType );
245 if( anArray.size() != 0 )
250 if( anArray.size() == 0 )
253 GLViewer_Object* aObject = GLViewer_MimeSource::getObject( anArray, aType );
257 ((GLViewer_Viewer2d*)getViewFrame()->getViewer())->getGLContext()->insertObject( aObject, true );
261 QClipboard *aClipboard = QApplication::clipboard();
263 QMimeSource* aMimeSource = aClipboard->data();
264 if( aMimeSource->provides( "GLViewer_Objects" ) )
266 QByteArray anArray = aMimeSource->encodedData( "GLViewer_Objects" );
267 QList<GLViewer_Object*> aObjects = GLViewer_MimeSource::getObjects( anArray, "GLViewer_Objects" );
268 if( aObjects.empty() )
270 GLViewer_Context* aContext = ((GLViewer_Viewer2d*)getViewFrame()->getViewer())->getGLContext();
271 for( int i = 0; i < aObjects.count(); i++ )
272 aContext->insertObject( aObjects[i], true );
278 SLOT: called when object is being dragged
280 void GLViewer_ViewPort2d::onDragObject( QMouseEvent* e )
282 //cout << "---GLViewer_ViewPort2d::onDragObject()---" << endl;
283 GLViewer_Viewer2d* aViewer = (GLViewer_Viewer2d*)getViewFrame()->getViewer();
284 GLViewer_Context* aContext = aViewer->getGLContext();
285 GLViewer_Object* anObject = aContext->getCurrentObject();
290 float aX = e->pos().x();
291 float anY = e->pos().y();
292 aViewer->transPoint( aX, anY );
294 if( myCurDragPosX == NULL && myCurDragPosY == NULL )
296 myCurDragPosX = new float(aX);
297 myCurDragPosY = new float(anY);
301 //QPoint aNewPos = e->pos();
302 //GLViewer_Viewer2d* aViewer = (GLViewer_Viewer2d*)getViewFrame()->getViewer();
304 if( anObject && (e->buttons() & Qt::LeftButton ) )
306 if( aContext->isSelected( anObject ) )
308 for( aContext->InitSelected(); aContext->MoreSelected(); aContext->NextSelected() )
310 GLViewer_Object* aMovingObject = aContext->SelectedObject();
312 aMovingObject->moveObject( aX - *myCurDragPosX, anY - *myCurDragPosY);
316 anObject->moveObject( aX - *myCurDragPosX, anY - *myCurDragPosY);
318 else if( aContext->NbSelected() && (e->buttons() & Qt::MidButton ) )
319 for( aContext->InitSelected(); aContext->MoreSelected(); aContext->NextSelected() )
320 (aContext->SelectedObject())->moveObject( aX - *myCurDragPosX, anY - *myCurDragPosY);
322 delete myCurDragPosX;
323 delete myCurDragPosY;
324 myCurDragPosX = new float(aX);
325 myCurDragPosY = new float(anY);
327 myGLWidget->updateGL();
331 Emits 'mouseEvent' signal. [ virtual protected ]
333 void GLViewer_ViewPort2d::mousePressEvent( QMouseEvent* e )
335 emit vpMouseEvent( e );
337 GLViewer_Viewer2d* aViewer = (GLViewer_Viewer2d*)getViewFrame()->getViewer();
338 GLViewer_Context* aContext = aViewer->getGLContext();
340 GLViewer_Object* anObject = NULL;
342 anObject = aContext->getCurrentObject();
344 bool accel = e->modifiers() & GLViewer_ViewTransformer::accelKey();
345 if( ( anObject && !( accel || e->button() == Qt::RightButton ) ) ||
346 ( aContext->NbSelected() && !accel && e->button() == Qt::MidButton ) )
348 myIsDragProcess = inDrag;
353 Emits 'mouseEvent' signal. [ virtual protected ]
355 void GLViewer_ViewPort2d::mouseMoveEvent( QMouseEvent* e )
357 emit vpMouseEvent( e );
359 if( myIsDragProcess == inDrag )
362 /*GLViewer_Viewer2d* aViewer = (GLViewer_Viewer2d*)getViewFrame()->getViewer();
363 GLViewer_Context* aContext = aViewer->getGLContext();
365 GLViewer_Object* anObj = aContext->getCurrentObject();
366 if( anObj && aContext->currentObjectIsChanged() )
368 //cout << "GLViewer_ViewPort2d::mouseMoveEvent{QToolTip::add}" << endl;
369 //QToolTip::remove( myGLWidget );
370 QRect* aRect = (aViewer->getWinObjectRect(anObj));
371 //QToolTip::add( myGLWidget, *aRect, anObj->getToolTipText() );
372 myGLWidget->addToolTip( anObj->getToolTipText(), *aRect );
376 //cout << "GLViewer_ViewPort2d::mouseMoveEvent{QToolTip::remove}" << endl;
377 //QRect* aRect = (aViewer->getWinObjectRect(anObj));
378 //QToolTip::remove( myGLWidget, *aRect );
379 myGLWidget->removeToolTip();
384 Emits 'mouseEvent' signal. [ virtual protected ]
386 void GLViewer_ViewPort2d::mouseReleaseEvent( QMouseEvent* e )
388 if ( myIsMouseReleaseBlock )
390 // skip mouse release after double click
391 myIsMouseReleaseBlock = false;
395 /* show popup menu */
396 if ( e->button() == Qt::RightButton )
398 //QPopupMenu* popup = createPopup();
399 //if ( popup && popup->count() )
400 // popup->exec( QCursor::pos() );
401 //destroyPopup( /*popup*/ );
403 emit vpMouseEvent( e );
405 if( myIsDragProcess == inDrag )
407 bool isAnyMoved = false;
408 GLViewer_Viewer2d* aViewer = (GLViewer_Viewer2d*)getViewFrame()->getViewer();
409 GLViewer_Context* aContext = aViewer->getGLContext();
410 GLViewer_Object* aMovingObject;
411 for( aContext->InitSelected(); aContext->MoreSelected(); aContext->NextSelected() )
413 aMovingObject = aContext->SelectedObject();
415 isAnyMoved = aMovingObject->finishMove() || isAnyMoved;
418 aMovingObject = aContext->getCurrentObject();
420 isAnyMoved = aMovingObject->finishMove() || isAnyMoved;
422 myIsDragProcess = noDrag;
423 //myCurDragMousePos.setX( 0 );
424 //myCurDragMousePos.setY( 0 );
425 delete myCurDragPosX;
426 delete myCurDragPosY;
427 myCurDragPosX = NULL;
428 myCurDragPosY = NULL;
433 aViewer->updateBorders();
439 Custom mouse double click event handler
441 void GLViewer_ViewPort2d::mouseDoubleClickEvent( QMouseEvent * e )
443 //redefined to block mouse release after mouse double click
444 myIsMouseReleaseBlock = true;
445 // invoke base implementation
446 GLViewer_ViewPort::mouseDoubleClickEvent( e );
450 Creates or deletes compass
451 \param on - if it is true, then to create
453 void GLViewer_ViewPort2d::turnCompass( GLboolean on )
456 myCompass = new GLViewer_Compass( Qt::green, 30, GLViewer_Compass::TopRight, 10, 5, 12, 3 );
462 Creates or deletes grid
463 \param on - if it is true, then to create
465 void GLViewer_ViewPort2d::turnGrid( GLboolean on )
469 myGrid = new GLViewer_Grid( 2*WIDTH, 2*HEIGHT,
471 GRID_XSIZE, GRID_YSIZE,
473 myXScale, myYScale );
481 \param gridColor - new grid color
482 \param axisColor - new axis color
484 void GLViewer_ViewPort2d::setGridColor( const QColor gridColor, const QColor axisColor )
488 myGrid->setGridColor( ( GLfloat )gridColor.red() / 255,
489 ( GLfloat )gridColor.green() / 255,
490 ( GLfloat )gridColor.blue() / 255 );
491 myGrid->setAxisColor( ( GLfloat )axisColor.red() / 255,
492 ( GLfloat )axisColor.green() / 255,
493 ( GLfloat )axisColor.blue() / 255 );
498 Changes background color
499 \param color - new background color
501 void GLViewer_ViewPort2d::setBackgroundColor( const QColor& color )
503 GLViewer_ViewPort::setBackgroundColor( color );
504 myGLWidget->makeCurrent();
505 glClearColor( ( GLfloat )color.red() / 255,
506 ( GLfloat )color.green() / 255,
507 ( GLfloat )color.blue() / 255, 1.0 );
508 myGLWidget->repaint();
512 \return background color
514 QColor GLViewer_ViewPort2d::backgroundColor() const
516 return GLViewer_ViewPort::backgroundColor();
522 void GLViewer_ViewPort2d::initResize( int x, int y )
524 float xa, xb, ya, yb;
525 xa = myBorder->left() - myMargin;
526 xb = myBorder->right() + myMargin;
527 ya = myBorder->top() - myMargin;
528 yb = myBorder->bottom() + myMargin;
530 GLfloat zoom, xzoom, yzoom;
535 xzoom = (GLfloat)x / myWidth;
536 yzoom = (GLfloat)y / myHeight;
538 if ( ( xzoom < yzoom ) && ( xzoom < 1 ) )
540 else if ( ( yzoom < xzoom ) && ( yzoom < 1 ) )
545 zoom = xzoom > yzoom ? xzoom : yzoom;
548 if ( !max && ( ! ( ( ( myXPan + w/2 ) < xb * myXScale * zoom ) ||
549 ( ( myXPan - w/2 ) > xa * myXScale * zoom ) ||
550 ( ( myYPan + h/2 ) < yb * myYScale * zoom ) ||
551 ( ( myYPan - h/2 ) > ya * myYScale * zoom ) ) ) )
554 if ( max && ( ( ( myXPan + w/2 ) < xb * myXScale * zoom ) ||
555 ( ( myXPan - w/2 ) > xa * myXScale * zoom ) ||
556 ( ( myYPan + h/2 ) < yb * myYScale * zoom ) ||
557 ( ( myYPan - h/2 ) > ya * myYScale * zoom ) ) )
567 myGrid->setResize( 2*x, 2*y, zoom );
569 myGLWidget->setScale( myXScale, myYScale, 1.0 );
573 Custom paint event handler
575 void GLViewer_ViewPort2d::paintEvent( QPaintEvent* e )
577 //cout << "GLViewer_ViewPort2d::paintEvent" << endl;
578 myGLWidget->updateGL();
579 GLViewer_ViewPort::paintEvent( e );
583 Custom resize event handler
585 void GLViewer_ViewPort2d::resizeEvent( QResizeEvent* e )
587 //cout << "GLViewer_ViewPort2d::resizeEvent" << endl;
588 GLViewer_ViewPort::resizeEvent( e );
592 Resets view to start state
594 void GLViewer_ViewPort2d::reset()
596 //cout << "GLViewer_ViewPort2d::reset" << endl;
599 GLint vpWidth, vpHeight;
601 myGLWidget->makeCurrent();
602 glGetIntegerv( GL_VIEWPORT, val );
606 GLint w = myGLWidget->getWidth();
607 GLint h = myGLWidget->getHeight();
608 GLfloat zoom = vpWidth / ( GLfloat )w < vpHeight / ( GLfloat )h ?
609 vpWidth / ( GLfloat )w : vpHeight / ( GLfloat )h;
613 myGrid->setPan( 0.0, 0.0 );
614 myGrid->setZoom( zoom / myXScale );
622 myGLWidget->setPan( myXPan, myYPan, 0.0 );
623 myGLWidget->setScale( myXScale, myYScale, 1.0 );
624 myGLWidget->setRotationAngle( 0.0 );
625 myGLWidget->setRotation( 0.0, 0.0, 0.0, 1.0 );
626 myGLWidget->updateGL();
634 void GLViewer_ViewPort2d::pan( int dx, int dy )
636 //cout << "GLViewer_ViewPort2d::pan " << dx << " " << dy << endl;
638 /*myXPan += dx / myXScale;
639 myYPan += dy / myYScale;
641 float ra, rx, ry, rz;
642 myGLWidget->getRotation( ra, rx, ry, rz );
643 GLfloat angle = ra * PI / 180.;
646 myGrid->setPan( myXPan*cos(angle) + myYPan*sin(angle),
647 -myXPan*sin(angle) + myYPan*cos(angle) );
650 float ra, rx, ry, rz;
651 myGLWidget->getRotation( ra, rx, ry, rz );
652 GLfloat angle = ra * PI / 180.;
654 myXPan += (dx*cos(angle) + dy*sin(angle)) / myXScale;
655 myYPan += (-dx*sin(angle) + dy*cos(angle)) / myXScale;
658 myGrid->setPan( myXPan, myYPan );
660 myGLWidget->setPan( myXPan, myYPan, 0.0 );
661 myGLWidget->setScale( myXScale, myYScale, 1.0 );
662 myGLWidget->updateGL();
666 Sets view center in global coords
667 \param x, y - global co-ordinates of center
669 void GLViewer_ViewPort2d::setCenter( int x, int y )
671 //cout << "GLViewer_ViewPort2d::setCenter" << endl;
674 GLint vpWidth, vpHeight;
676 myGLWidget->makeCurrent();
677 glGetIntegerv( GL_VIEWPORT, val );
681 myXPan -= ( x - vpWidth/2 ) / myXScale;
682 myYPan += ( y - vpHeight/2 ) / myYScale;
686 myGrid->setPan( myXPan, myYPan );
687 myGrid->setZoom( myXOldScale / myXScale );
690 myXScale = myXOldScale;
691 myYScale = myYOldScale;
693 myGLWidget->setPan( myXPan, myYPan, 0.0 );
694 myGLWidget->setScale( myXScale, myYScale, 1.0 );
695 myGLWidget->updateGL();
699 Process zoming transformation with mouse tracking from ( x0, y0 ) to ( x1, y1 )
701 void GLViewer_ViewPort2d::zoom( int x0, int y0, int x, int y )
703 //cout << "GLViewer_ViewPort2d::zoom" << endl;
709 if ( dx == 0. && dy == 0. )
712 zm = sqrt(dx * dx + dy * dy) / 100. + 1;
713 zm = (dx > 0.) ? zm : 1. / zm;
723 if( myGrid->setZoom( zm ) )
725 myGLWidget->setPan( myXPan, myYPan, 0.0 );
726 myGLWidget->setScale( myXScale, myYScale, 1.0 );
727 myGLWidget->updateGL();
737 myGLWidget->setPan( myXPan, myYPan, 0.0 );
738 myGLWidget->setScale( myXScale, myYScale, 1.0 );
739 myGLWidget->updateGL();
744 Transforms view by rectangle
745 \param rect - rectangle
747 void GLViewer_ViewPort2d::fitRect( const QRect& rect )
749 float x0, x1, y0, y1;
750 float dx, dy, zm, centerX, centerY;
753 GLint vpWidth, vpHeight;
755 myGLWidget->makeCurrent();
756 glGetIntegerv( GL_VIEWPORT, val );
765 dx = fabs( x1 - x0 );
766 dy = fabs( y1 - y0 );
767 centerX = ( x0 + x1 ) / 2.;
768 centerY = ( y0 + y1 ) / 2.;
770 if ( dx == 0. || dy == 0. )
773 zm = vpWidth / dx < vpHeight / dy ? vpWidth / dx : vpHeight / dy;
775 float aDX = ( vpWidth / 2. - centerX ) / myXScale;
776 float aDY = ( vpHeight / 2. - centerY ) / myYScale;
778 float ra, rx, ry, rz;
779 myGLWidget->getRotation( ra, rx, ry, rz );
780 GLfloat angle = ra * PI / 180.;
782 myXPan += (aDX*cos(angle) - aDY*sin(angle));
783 myYPan -= (aDX*sin(angle) + aDY*cos(angle));
786 myGrid->setPan( myXPan, myYPan );
792 myGrid->setZoom( zm );
794 myGLWidget->setPan( myXPan, myYPan, 0.0 );
795 myGLWidget->setScale( myXScale, myYScale, 1.0 );
796 myGLWidget->updateGL();
800 Transforms view by selection
802 void GLViewer_ViewPort2d::fitSelect()
804 GLViewer_Viewer2d* aViewer = (GLViewer_Viewer2d*)getViewFrame()->getViewer();
805 GLViewer_Context* aContext = aViewer->getGLContext();
810 for( aContext->InitSelected(); aContext->MoreSelected(); aContext->NextSelected() )
811 aSelRect |= *(aViewer->getWinObjectRect( aContext->SelectedObject() ));
813 if( aSelRect.isValid() )
815 aSelRect.setTop( aSelRect.top() - SELECTION_RECT_GAP );
816 aSelRect.setBottom( aSelRect.bottom() + SELECTION_RECT_GAP );
817 aSelRect.setLeft( aSelRect.left() - SELECTION_RECT_GAP );
818 aSelRect.setRight( aSelRect.right() + SELECTION_RECT_GAP );
824 Transform view by view borders
825 \param keepScale - if it is true, zoom does not change
827 void GLViewer_ViewPort2d::fitAll( bool keepScale, bool /*withZ*/ )
829 //cout << "GLViewer_ViewPort2d::fitAll" << endl;
831 float xa, xb, ya, yb;
833 float xScale, yScale;
835 myMargin = qMax( myBorder->width(), myBorder->height() ) / 5;
837 xa = myBorder->left() - myMargin;
838 xb = myBorder->right() + myMargin;
839 ya = myBorder->bottom() - myMargin;
840 yb = myBorder->top() + myMargin;
842 float aPoints[8] = { xa, ya, xb, ya, xa, yb, xb, yb };
844 float ra, rx, ry, rz;
845 myGLWidget->getRotation( ra, rx, ry, rz );
846 float angle = ra * PI / 180.;
849 for( i = 0; i < 7; i = i + 2 )
850 rotate_point( aPoints[i], aPoints[i+1], angle );
852 float aBorders[4] = { aPoints[0], aPoints[0], aPoints[1], aPoints[1] };
854 for( i = 2; i < 7; i = i + 2 )
856 if( aBorders[0] < aPoints[i] )
857 aBorders[0] = aPoints[i];
858 if( aBorders[1] > aPoints[i] )
859 aBorders[1] = aPoints[i];
861 if( aBorders[2] < aPoints[i+1] )
862 aBorders[2] = aPoints[i+1];
863 if( aBorders[3] > aPoints[i+1] )
864 aBorders[3] = aPoints[i+1];
868 GLint vpWidth, vpHeight;
870 myGLWidget->makeCurrent();
871 glGetIntegerv( GL_VIEWPORT, val );
875 dx = fabs( aBorders[1] - aBorders[0] );
876 dy = fabs( aBorders[3] - aBorders[2] );
878 myXPan = -( aBorders[0] + aBorders[1] ) / 2;
879 myYPan = -( aBorders[2] + aBorders[3] ) / 2;
884 myXOldScale = myXScale;
885 myYOldScale = myYScale;
891 zm = vpWidth / dx < vpHeight / dy ? vpWidth / dx : vpHeight / dy;
900 myGrid->setPan( myXPan, myYPan );
902 myGrid->setZoom( zm / xScale );
904 myGrid->setZoom( zm / yScale );
907 myGLWidget->setPan( myXPan, myYPan, 0.0 );
908 myGLWidget->setScale( myXScale, myYScale, 1.0 );
909 myGLWidget->updateGL();
912 emit vpUpdateValues();
917 \param x, y - start point
919 void GLViewer_ViewPort2d::startRotation( int x, int y )
921 myGLWidget->setRotationStart( x, y, 1.0 );
926 \param intX, intY - current point
928 void GLViewer_ViewPort2d::rotate( int intX, int intY )
931 GLint vpWidth, vpHeight;
933 myGLWidget->makeCurrent();
934 glGetIntegerv( GL_VIEWPORT, val );
938 float x = intX, y = intY;
939 float x0 = vpWidth/2;
940 float y0 = vpHeight/2;
942 float xs, ys, zs, dx, dy;
943 myGLWidget->getRotationStart( xs, ys, zs );
952 float l1 = pow( double( xs*xs + ys*ys ), 0.5 );
953 float l2 = pow( double( x*x + y*y ), 0.5 );
954 float l = pow( double( dx*dx + dy*dy ), 0.5 );
956 double mult = xs * y - x * ys;
958 if( mult > 0 ) sign = 1;
959 else if( mult < 0 ) sign = -1;
962 float anglePrev = myGLWidget->getRotationAngle();
963 float angleNew = sign * acos( ( l1*l1 + l2*l2 - l*l ) / ( 2 * l1 * l2 )) * 180. / PI;
964 float angle = anglePrev + angleNew;
966 // GLfloat anAngle = angle * PI / 180.; unused
968 float ra, rx, ry, rz;
969 myGLWidget->getRotation( ra, rx, ry, rz );
970 myGLWidget->setRotation( angle, rx, ry, rz );
971 myGLWidget->updateGL();
977 void GLViewer_ViewPort2d::endRotation()
979 float ra, rx, ry, rz;
980 myGLWidget->getRotation( ra, rx, ry, rz );
981 myGLWidget->setRotationAngle( ra );
987 void GLViewer_ViewPort2d::drawCompass()
989 if( !myCompass->getVisible() )
992 GLfloat xScale, yScale, xPan, yPan;
994 int xPos = getWidth();
995 int yPos = getHeight();
997 int cPos = myCompass->getPos();
998 int cSize = myCompass->getSize();
999 QColor cCol = myCompass->getColor();
1000 int cWidthTop = myCompass->getArrowWidthTop();
1001 int cWidthBot = myCompass->getArrowWidthBottom();
1002 int cHeightTop = myCompass->getArrowHeightTop();
1003 int cHeightBot = myCompass->getArrowHeightBottom();
1005 GLfloat colorR = (cCol.red())/255;
1006 GLfloat colorG = (cCol.green())/255;
1007 GLfloat colorB = (cCol.blue())/255;
1009 float delX = cSize * 0.5;
1010 float delY = cSize * 0.5;
1012 getScale( xScale, yScale );
1013 getPan( xPan, yPan);
1015 float centerX = (xPos/2 - delX - cSize)/xScale;
1016 float centerY = (yPos/2 - delY - cSize)/yScale;
1020 case GLViewer_Compass::TopLeft:
1023 case GLViewer_Compass::BottomLeft:
1027 case GLViewer_Compass::BottomRight:
1033 float ra, rx, ry, rz;
1034 myGLWidget->getRotation( ra, rx, ry, rz );
1035 GLfloat angle = ra * PI / 180.;
1036 GLfloat /*r = 0.0,*/ x = 0.0 , y = 0.0;
1038 rotate_point( centerX, centerY, -angle );
1043 glColor3f( colorR, colorG, colorB );
1044 glBegin( GL_POLYGON );
1046 x = centerX; y = centerY + cSize / yScale;
1049 x = centerX + cWidthTop / xScale; y = centerY + ( cSize - cHeightTop ) / yScale ;
1052 x = centerX + cWidthBot / xScale; y = centerY + ( cSize - cHeightTop ) / yScale ;
1055 x = centerX + cWidthBot / xScale; y = centerY - cSize/yScale;
1058 x = centerX; y = centerY - (cSize - cHeightBot) / yScale ;
1061 x = centerX - cWidthBot / xScale; y = centerY - cSize/yScale;
1064 x = centerX - cWidthBot / xScale; y = centerY + ( cSize - cHeightTop ) / yScale ;
1067 x = centerX - cWidthTop / xScale; y = centerY + ( cSize - cHeightTop ) / yScale ;
1071 glEnable( GL_LINE_SMOOTH );
1072 glBegin(GL_LINE_LOOP);
1074 float aCircAngle = 0;
1075 for ( int i = 0; i < 20 * SEGMENTS + 1; i++ )
1077 x = centerX + cos(aCircAngle) * cSize / xScale;
1078 y = centerY + sin(aCircAngle) * cSize / yScale;
1080 aCircAngle += float( STEP ) / 2;
1084 GLdouble modelMatrix[16], projMatrix[16];
1086 GLdouble winxN, winyN, winz;
1087 GLdouble winxE, winyE;
1088 GLdouble winxS, winyS;
1089 GLdouble winxW, winyW;
1092 GLViewer_TexFont* aFont = myCompass->getFont();
1093 float widN = (float)aFont->getStringWidth( "N" );
1094 float widW = (float)aFont->getStringWidth( "W" );
1095 float widS = (float)aFont->getStringWidth( "S" );
1096 float widE = (float)aFont->getStringWidth( "E" );
1097 float heightL = (float)aFont->getStringHeight();
1099 float xGapN = - widN/2 *( 1.0 + sin(angle) );
1100 float xGapS = - widS/2 *( 1.0 - sin(angle) );
1101 float xGapW = - widW/2 *( 1.0 + cos(angle) );
1102 float xGapE = - widE/2 *( 1.0 - cos(angle) );
1104 float yGapN = - heightL/2 *( 1.0 - cos(angle) ) * 0.75;
1105 float yGapS = - heightL/2 *( 1.0 + cos(angle) ) * 0.75;
1106 float yGapW = - heightL/2 *( 1.0 + sin(angle) ) * 0.75;
1107 float yGapE = - heightL/2 *( 1.0 - sin(angle) ) * 0.75;
1109 glGetIntegerv (GL_VIEWPORT, viewport);
1110 glGetDoublev (GL_MODELVIEW_MATRIX, modelMatrix);
1111 glGetDoublev (GL_PROJECTION_MATRIX, projMatrix);
1113 gluProject (centerX, centerY + cSize / yScale, 0, modelMatrix, projMatrix, viewport, &winxN, &winyN, &winz);
1114 gluProject (centerX + cSize / xScale, centerY, 0, modelMatrix, projMatrix, viewport, &winxE, &winyE, &winz);
1115 gluProject (centerX, centerY - cSize / yScale, 0, modelMatrix, projMatrix, viewport, &winxS, &winyS, &winz);
1116 gluProject (centerX - cSize / xScale, centerY, 0, modelMatrix, projMatrix, viewport, &winxW, &winyW, &winz);
1118 glColor3f( 1.0, 1.0, 1.0 );
1120 aTextList = glGenLists( 1 );
1121 glNewList( aTextList, GL_COMPILE );
1123 glMatrixMode(GL_PROJECTION);
1126 glOrtho(0,viewport[2],0,viewport[3],-100,100);
1127 glMatrixMode(GL_MODELVIEW);
1131 aFont->drawString( "N", winxN + xGapN, winyN + yGapN );
1132 aFont->drawString( "E", winxE + xGapE, winyE + yGapE );
1133 aFont->drawString( "S", winxS + xGapS, winyS + yGapS );
1134 aFont->drawString( "W", winxW + xGapW, winyW + yGapW );
1136 glMatrixMode(GL_PROJECTION);
1138 glMatrixMode(GL_MODELVIEW);
1143 if ( (int)aTextList != -1 )
1144 glCallList( aTextList );
1148 \return blocking status for current started operations
1150 BlockStatus GLViewer_ViewPort2d::currentBlock()
1152 if( myIsDragProcess == inDrag && myCurDragPosX != NULL && myCurDragPosY != NULL)
1153 return BlockStatus(BS_Highlighting | BS_Selection);
1155 if( mypFirstPoint && mypLastPoint )
1156 return BlockStatus(BS_Highlighting | BS_Selection);
1162 Initializes rectangle selection
1163 \param x, y - start point
1165 void GLViewer_ViewPort2d::startSelectByRect( int x, int y )
1167 if( !mypFirstPoint && !mypLastPoint )
1169 mypFirstPoint = new QPoint( x, y );
1170 mypLastPoint = new QPoint( x, y );
1173 if ( !myRectBand ) {
1174 myRectBand = new QRubberBand( QRubberBand::Rectangle, this );
1176 palette.setColor(myRectBand->foregroundRole(), Qt::white);
1177 myRectBand->setPalette(palette);
1183 Draws rectangle selection
1184 \param x, y - current point
1186 void GLViewer_ViewPort2d::drawSelectByRect( int x, int y )
1188 if( mypFirstPoint && mypLastPoint )
1190 myRectBand->hide(); /* erase */
1192 mypLastPoint->setX( x );
1193 mypLastPoint->setY( y );
1195 QRect aRect = selectionRect();
1196 myRectBand->setGeometry( aRect ); /* draw */
1197 myRectBand->setVisible( aRect.isValid() );
1203 Finishes rectangle selection
1205 void GLViewer_ViewPort2d::finishSelectByRect()
1207 if( mypFirstPoint && mypLastPoint )
1211 if ( myRectBand ) myRectBand->hide(); /* erase */
1213 delete mypFirstPoint;
1214 delete mypLastPoint;
1216 mypFirstPoint = NULL;
1217 mypLastPoint = NULL;
1225 \return rectangle selection
1227 QRect GLViewer_ViewPort2d::selectionRect()
1230 if( mypFirstPoint && mypLastPoint )
1232 aRect.setLeft( qMin( mypFirstPoint->x(), mypLastPoint->x() ) );
1233 aRect.setTop( qMin( mypFirstPoint->y(), mypLastPoint->y() ) );
1234 aRect.setRight( qMax( mypFirstPoint->x(), mypLastPoint->x() ) );
1235 aRect.setBottom( qMax( mypFirstPoint->y(), mypLastPoint->y() ) );
1243 bool GLViewer_ViewPort2d::startPulling( GLViewer_Pnt point )
1245 GLViewer_Viewer2d* aViewer = (GLViewer_Viewer2d*)getViewFrame()->getViewer();
1246 GLViewer_Context* aContext = aViewer->getGLContext();
1247 ObjList anObjects = aContext->getObjects();
1249 for( ObjList::Iterator it = anObjects.begin(); it != anObjects.end(); ++it )
1251 GLViewer_Object* anObject = *it;
1252 GLViewer_Rect aRect = anObject->getPullingRect();
1254 if( aRect.contains( point ) && anObject->startPulling( point ) )
1257 myPullingObject = anObject;
1258 setCursor( *getHandCursor() );
1268 void GLViewer_ViewPort2d::drawPulling( GLViewer_Pnt point )
1270 GLViewer_Viewer2d* aViewer = (GLViewer_Viewer2d*)getViewFrame()->getViewer();
1271 GLViewer_Context* aContext = aViewer->getGLContext();
1272 ObjList anObjects = aContext->getObjects();
1274 GLViewer_Object* aLockedObject = 0;
1275 for( ObjList::Iterator it = anObjects.begin(); it != anObjects.end(); ++it )
1277 GLViewer_Object* anObject = *it;
1278 if( !anObject->getVisible() )
1281 GLViewer_Rect aRect = anObject->getPullingRect();
1283 if( aRect.contains( point ) && anObject->portContains( point ) )
1285 aLockedObject = anObject;
1290 myPullingObject->pull( point, aLockedObject );
1295 void GLViewer_ViewPort2d::finishPulling()
1297 myIsPulling = false;
1298 myPullingObject->finishPulling();
1299 setCursor( *getDefaultCursor() );
1303 Convert rectangle in window co-ordinates to GL co-ordinates
1304 \return converted rectangle
1306 GLViewer_Rect GLViewer_ViewPort2d::win2GLV( const QRect& theRect ) const
1308 GLViewer_Rect aRect;
1310 GLdouble modelMatrix[16], projMatrix[16];
1313 GLdouble objx1, objy1;
1314 GLdouble objx2, objy2;
1317 glGetIntegerv (GL_VIEWPORT, viewport);
1318 glGetDoublev (GL_MODELVIEW_MATRIX, modelMatrix);
1319 glGetDoublev (GL_PROJECTION_MATRIX, projMatrix);
1321 gluUnProject( theRect.left(), viewport[3] - theRect.top(), 0, modelMatrix, projMatrix, viewport, &objx1, &objy1, &objz );
1322 gluUnProject( theRect.right(), viewport[3] - theRect.bottom(), 0, modelMatrix, projMatrix, viewport, &objx2, &objy2, &objz );
1324 aRect.setLeft( objx1 );
1325 aRect.setTop( objy1 );
1326 aRect.setRight( objx2 );
1327 aRect.setBottom( objy2 );
1333 Convert rectangle in GL co-ordinates to window co-ordinates
1334 \return converted rectangle
1336 QRect GLViewer_ViewPort2d::GLV2win( const GLViewer_Rect& theRect ) const
1340 GLdouble modelMatrix[16], projMatrix[16];
1343 GLdouble winx1, winy1;
1344 GLdouble winx2, winy2;
1347 glGetIntegerv (GL_VIEWPORT, viewport);
1348 glGetDoublev (GL_MODELVIEW_MATRIX, modelMatrix);
1349 glGetDoublev (GL_PROJECTION_MATRIX, projMatrix);
1351 gluProject( theRect.left(), theRect.top(), 0, modelMatrix, projMatrix, viewport, &winx1, &winy1, &winz );
1352 gluProject( theRect.right(), theRect.bottom(), 0, modelMatrix, projMatrix, viewport, &winx2, &winy2, &winz );
1354 aRect.setLeft( (int)winx1 );
1355 aRect.setTop( viewport[3] - (int)winy1 );
1356 aRect.setRight( (int)winx2 );
1357 aRect.setBottom( viewport[3] - (int)winy2 );
1363 SLOT: called when tooltip should be shown
1365 void GLViewer_ViewPort2d::onMaybeTip( QPoint thePoint, QString& theText, QFont& theFont, QRect& theTextReg, QRect& theRegion )
1367 GLViewer_Context* aContext = ((GLViewer_Viewer2d*)getViewFrame()->getViewer())->getGLContext();
1369 GLViewer_Object* anObj = aContext->getCurrentObject();
1372 theText = anObj->getToolTipText();
1373 if( theText.isEmpty() )
1374 theText = anObj->getName();
1377 if( anObj->isTooTipHTML() )
1378 aList = theText.split( "<br>", QString::SkipEmptyParts );
1380 aList = theText.split( "\n", QString::SkipEmptyParts );
1382 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() )
1389 str_size = aList[i].length();
1393 int cur_height = 24;
1394 QCursor* aCursor = QApplication::overrideCursor();
1397 const QBitmap* aBitmap = aCursor->bitmap();
1399 cur_height = aBitmap->height();
1403 QSize aSize = QLabel( theText, 0 ).sizeHint();
1404 theTextReg = QRect( thePoint.x(), thePoint.y() + cur_height,
1405 aSize.width(), aSize.height() );
1406 theRegion = QRect( thePoint.x(), thePoint.y(), 1, 1 );