1 // Copyright (C) 2014-2015 EDF-R&D
2 // This library is free software; you can redistribute it and/or
3 // modify it under the terms of the GNU Lesser General Public
4 // License as published by the Free Software Foundation; either
5 // version 2.1 of the License, or (at your option) any later version.
7 // This library is distributed in the hope that it will be useful,
8 // but WITHOUT ANY WARRANTY; without even the implied warranty of
9 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
10 // Lesser General Public License for more details.
12 // You should have received a copy of the GNU Lesser General Public
13 // License along with this library; if not, write to the Free Software
14 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
16 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
19 #include <HYDROGUI_Overview.h>
20 #include <OCCViewer_ViewPort3d.h>
21 #include <OCCViewer_ViewFrame.h>
22 #include <QtxRubberBand.h>
23 #include <QApplication>
25 #include <QMouseEvent>
28 class HYDROGUI_OverviewBand : public QtxPolyRubberBand
31 HYDROGUI_OverviewBand( HYDROGUI_Overview* theOverview );
32 virtual ~HYDROGUI_OverviewBand();
34 void initGeometry( const QPolygon& );
35 void update( bool isFromMain );
36 QPoint center() const;
39 void drag( const QPoint&, bool isStart );
41 void dragging( const QPoint& );
42 bool contains( const QPoint& ) const;
43 QRect boundingRect() const;
46 virtual void paintEvent( QPaintEvent* );
49 HYDROGUI_Overview* myOverview;
51 QPolygon myStartPoints;
56 HYDROGUI_OverviewBand::HYDROGUI_OverviewBand( HYDROGUI_Overview* theOverview )
57 : QtxPolyRubberBand( theOverview->getViewPort( false ) ),
58 myOverview( theOverview ), myIsDrag( false )
62 HYDROGUI_OverviewBand::~HYDROGUI_OverviewBand()
66 bool isEmpty( const QPolygon& thePoly )
68 QSize s = thePoly.boundingRect().size();
69 if( s.width() < 2 || s.height() < 2 )
75 void HYDROGUI_OverviewBand::initGeometry( const QPolygon& thePoly )
77 int w2 = myOverview->width()*2;
78 int h2 = myOverview->height()*2;
81 for( int i=0, n=thePoly.size(); i<n; i++ )
83 QPoint p = thePoly.point( i );
94 QtxPolyRubberBand::initGeometry( thePoly );
95 if( isEmpty( thePoly ) )
101 QRect HYDROGUI_OverviewBand::boundingRect() const
103 return myPoints.boundingRect();
106 QPoint HYDROGUI_OverviewBand::center() const
109 int n = myPoints.size()-1;
113 for( int i=0; i<n; i++ )
114 c += myPoints.point( i );
120 void HYDROGUI_OverviewBand::drag( const QPoint& thePoint, bool isStart )
122 if( myIsDrag==isStart )
127 myStartPoints = myPoints;
128 /*if( contains( thePoint ) )
129 myStartPnt = thePoint;
131 myStartPnt = center();
133 dragging( thePoint );
137 dragging( thePoint );
142 bool HYDROGUI_OverviewBand::isDrag() const
147 void HYDROGUI_OverviewBand::dragging( const QPoint& thePoint )
149 int n = myPoints.size();
150 QPoint delta = thePoint - myStartPnt;
151 for( int i=0; i<n; i++ )
152 myPoints.setPoint( i, myStartPoints.point( i ) + delta );
153 initGeometry( myPoints );
157 bool HYDROGUI_OverviewBand::contains( const QPoint& thePoint ) const
159 return myPoints.containsPoint( thePoint, Qt::OddEvenFill );
162 int HYDROGUI_OverviewBand::count() const
164 return myPoints.size();
167 void HYDROGUI_OverviewBand::update( bool isFromMain )
169 OCCViewer_ViewPort3d* main = myOverview->getViewPort( true );
172 int w = main->width();
173 int h = main->height();
176 QPoint p1 = myOverview->fromMain( 0, 0 );
177 QPoint p2 = myOverview->fromMain( w, 0 );
178 QPoint p3 = myOverview->fromMain( w, h );
179 QPoint p4 = myOverview->fromMain( 0, h );
185 initGeometry( poly );
189 OCCViewer_ViewPort3d* overview = myOverview->getViewPort( false );
191 double x1, y1, z1, x2, y2, z2;
192 main->getView()->Convert( main->width()/2, main->height()/2, x1, y1, z1 );
194 // Patch for OCCT 6.9.1, on 7.0.0 the moving of point to plane XY is not necessary
195 gp_Dir dm = main->getView()->Camera()->Direction();
196 double t1 = -z1/dm.Z();
201 overview->getView()->Convert( c.x(), c.y(), x2, y2, z2 );
202 gp_Dir dov = overview->getView()->Camera()->Direction();
203 double t2 = -z2/dov.Z();
209 aTrsf.SetTranslation( gp_Pnt( x1, y1, z1 ), gp_Pnt( x2, y2, z2 ) );
211 // Temporary patch for bug in OCCT 6.9.1
212 Handle(Graphic3d_Camera) cam = main->getView()->Camera();
213 gp_Dir u = cam->Up(), nu = u.Transformed (aTrsf);
214 gp_Pnt e = cam->Eye(), ne = e.Transformed (aTrsf);
215 gp_Pnt cen = cam->Center(), ncen = cen.Transformed (aTrsf);
217 if (!nu.IsEqual (u, 0.0))
220 if (!ne.IsEqual (e, 0.0))
223 if (!ncen.IsEqual(cen, 0.0))
224 cam->SetCenter (ncen);
226 //version for new OCCT:
227 //main->getView()->Camera()->Transform( aTrsf );
232 void HYDROGUI_OverviewBand::paintEvent( QPaintEvent* thePaintEvent )
234 QPainter painter( this );
235 painter.setRenderHint( QPainter::Antialiasing );
237 static QColor aColor = Qt::red;
238 static int aWidth = 2;
239 static QPen aPen( QBrush( aColor ), aWidth, Qt::DashDotLine );
241 painter.setPen( aPen );
242 painter.drawPolygon( myPoints );
250 HYDROGUI_Overview::HYDROGUI_Overview( const QString& theTitle, int theMargin, QWidget* theParent )
251 : QFrame( theParent ), myMargin( theMargin ),
252 myMainView( 0 ), myViewPort( 0 ), myBand( 0 )
254 setWindowTitle( theTitle );
255 myLayout = new QGridLayout( this );
256 myLayout->setMargin( 0 );
257 myLayout->setSpacing( 0 );
258 myLayout->setRowStretch( 0, 1 );
259 myLayout->setColumnStretch( 0, 1 );
262 HYDROGUI_Overview::~HYDROGUI_Overview()
266 QImage HYDROGUI_Overview::dump() const
271 Handle(V3d_View) view = myViewPort->getView();
275 int aWidth = myViewPort->width();
276 int aHeight = myViewPort->height();
279 view->ToPixMap( aPix,aWidth, aHeight,Graphic3d_BT_RGBA );
281 QImage anImage( aPix.Data(), aWidth, aHeight, QImage::Format_ARGB32 );
282 anImage = anImage.mirrored();
283 anImage = anImage.rgbSwapped();
285 if( myBand && myBand->isVisible() )
287 QPixmap aPixmap = QPixmap::fromImage( anImage );
288 QPoint p = myBand->boundingRect().topLeft();
289 myBand->render( &aPixmap, p );
290 anImage = aPixmap.toImage();
296 OCCViewer_ViewPort3d* HYDROGUI_Overview::getViewPort( bool isMain ) const
298 return isMain ? myMainView->getViewPort() : myViewPort;
301 void HYDROGUI_Overview::setMainView( OCCViewer_ViewFrame* theMainView )
303 myMainView = theMainView;
307 OCCViewer_ViewWindow* aMainView = myMainView->getView( OCCViewer_ViewFrame::MAIN_VIEW );
308 connect( aMainView, SIGNAL( vpTransformationFinished( OCCViewer_ViewWindow::OperationType ) ),
309 this, SLOT( OnTransformationAfterOp( OCCViewer_ViewWindow::OperationType ) ) );
310 connect( aMainView->getViewPort(), SIGNAL( vpResizeEvent( QResizeEvent* ) ),
311 this, SLOT( OnResizeEvent( QResizeEvent* ) ) );
312 connect( aMainView->getViewPort(), SIGNAL( vpTransformed( OCCViewer_ViewPort* ) ),
313 this, SLOT( OnTransformation() ) );
317 myViewPort = new OCCViewer_ViewPort3d( this, myMainView->getViewPort()->getViewer(), V3d_ORTHOGRAPHIC );
318 myViewPort->setBackgroundColor( myMainView->getViewPort()->backgroundColor() );
320 connect( myViewPort, SIGNAL( vpMouseEvent( QMouseEvent* ) ),
321 this, SLOT( OnMouseEvent( QMouseEvent* ) ) );
322 connect( myViewPort, SIGNAL( vpResizeEvent( QResizeEvent* ) ),
323 this, SLOT( OnResizeEvent( QResizeEvent* ) ) );
325 myLayout->addWidget( myViewPort, 0, 0 );
328 #if defined(TEST_MODE) || defined(_DEBUG)
329 //qApp->installEventFilter( this );
332 qApp->processEvents();
336 qApp->processEvents();
339 myBand = new HYDROGUI_OverviewBand( this );
341 myBand->update( true );
344 void HYDROGUI_Overview::setTopView()
346 Handle(V3d_View) aView3d = myViewPort->getView();
347 if( !aView3d.IsNull() )
348 aView3d->SetProj( V3d_Zpos );
349 myViewPort->fitAll();
351 // Apply margins for internal area in the view port
354 QRect aRect( -myMargin, -myMargin, myViewPort->width()+2*myMargin, myViewPort->height()+2*myMargin );
355 myViewPort->fitRect( aRect );
359 myBand->update( true );
362 void HYDROGUI_Overview::OnTransformationAfterOp( OCCViewer_ViewWindow::OperationType theOp )
364 if( theOp>=OCCViewer_ViewWindow::WINDOWFIT )
366 myViewPort->fitAll();
371 void HYDROGUI_Overview::OnTransformation()
374 myBand->update( true );
377 QPoint HYDROGUI_Overview::fromMain( int xp, int yp ) const
379 const double EPS = 1E-2;
381 Handle(V3d_View) aMain = myMainView->getViewPort()->getView();
382 Handle(V3d_View) aXY = myViewPort->getView();
384 // View coordinates to 3d (world) coordinates
386 aMain->Convert( xp, yp, x, y, z );
388 // Moving to the XY plane
389 gp_Vec aDir = aMain->Camera()->Direction();
390 if( fabs( aDir.Z() )<EPS )
393 double t = -z/aDir.Z();
398 // 3d (world) coordinates to view coordinates in the overview
399 aXY->Convert( x, y, z, xp, yp );
401 return QPoint( xp, yp );
404 void HYDROGUI_Overview::OnMouseEvent( QMouseEvent* theEvent )
406 QPoint mp = theEvent->pos();
410 switch( theEvent->type() )
412 case QEvent::MouseButtonPress:
413 myBand->drag( mp, true );
416 case QEvent::MouseButtonRelease:
417 myBand->drag( mp, false );
420 case QEvent::MouseMove:
421 if( myBand->isDrag() )
422 myBand->dragging( mp );
427 bool HYDROGUI_Overview::eventFilter( QObject* theObject, QEvent* theEvent )
429 #if defined(TEST_MODE) || defined(_DEBUG)
430 /*switch( theEvent->type() )
432 case QEvent::MouseMove:
434 QPoint mp = ((QMouseEvent*)theEvent)->pos();
435 //mp = getViewPort(false)->mapFromGlobal(mp);
436 QString coords = QString( "(%0, %1)" ).arg( mp.x() ).arg( mp.y() );
437 std::string scoords = coords.toStdString();
438 qDebug( scoords.c_str() );
443 return QFrame::eventFilter( theObject, theEvent );
446 void HYDROGUI_Overview::OnResizeEvent( QResizeEvent* )
449 myBand->update( true );