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 <OCCViewer_ViewModel.h>
23 #include <OCCViewer_ViewManager.h>
24 #include <QtxRubberBand.h>
25 #include <QApplication>
27 #include <QMouseEvent>
31 #include "HYDRO_trace.hxx"
33 class HYDROGUI_OverviewBand : public QtxPolyRubberBand
36 HYDROGUI_OverviewBand( HYDROGUI_Overview* theOverview );
37 virtual ~HYDROGUI_OverviewBand();
39 void initGeometry( const QPolygon& );
40 void update( bool isFromMain );
41 QPoint center() const;
44 void drag( const QPoint&, bool isStart );
46 void dragging( const QPoint& );
47 bool contains( const QPoint& ) const;
48 QRect boundingRect() const;
51 virtual void paintEvent( QPaintEvent* );
54 HYDROGUI_Overview* myOverview;
56 QPolygon myStartPoints;
61 HYDROGUI_OverviewBand::HYDROGUI_OverviewBand( HYDROGUI_Overview* theOverview )
62 : QtxPolyRubberBand( theOverview->getViewPort( false ) ),
63 myOverview( theOverview ), myIsDrag( false )
67 HYDROGUI_OverviewBand::~HYDROGUI_OverviewBand()
71 bool isEmpty( const QPolygon& thePoly )
73 QSize s = thePoly.boundingRect().size();
74 if( s.width() < 2 || s.height() < 2 )
80 void HYDROGUI_OverviewBand::initGeometry( const QPolygon& thePoly )
82 int w2 = myOverview->width()*2;
83 int h2 = myOverview->height()*2;
86 for( int i=0, n=thePoly.size(); i<n; i++ )
88 QPoint p = thePoly.point( i );
99 QtxPolyRubberBand::initGeometry( thePoly );
100 if( isEmpty( thePoly ) )
106 QRect HYDROGUI_OverviewBand::boundingRect() const
108 return myPoints.boundingRect();
111 QPoint HYDROGUI_OverviewBand::center() const
114 int n = myPoints.size()-1;
118 for( int i=0; i<n; i++ )
119 c += myPoints.point( i );
125 void HYDROGUI_OverviewBand::drag( const QPoint& thePoint, bool isStart )
128 if( myIsDrag==isStart )
133 myStartPoints = myPoints;
134 /*if( contains( thePoint ) )
135 myStartPnt = thePoint;
137 myStartPnt = center();
139 dragging( thePoint );
143 dragging( thePoint );
148 bool HYDROGUI_OverviewBand::isDrag() const
153 void HYDROGUI_OverviewBand::dragging( const QPoint& thePoint )
155 DEBTRACE("dragging");
156 int n = myPoints.size();
157 QPoint delta = thePoint - myStartPnt;
158 for( int i=0; i<n; i++ )
159 myPoints.setPoint( i, myStartPoints.point( i ) + delta );
160 initGeometry( myPoints );
164 bool HYDROGUI_OverviewBand::contains( const QPoint& thePoint ) const
166 return myPoints.containsPoint( thePoint, Qt::OddEvenFill );
169 int HYDROGUI_OverviewBand::count() const
171 return myPoints.size();
174 void HYDROGUI_OverviewBand::update( bool isFromMain )
176 OCCViewer_ViewPort3d* main = myOverview->getViewPort( true );
179 int w = main->width();
180 int h = main->height();
183 QPoint p1 = myOverview->fromMain( 0, 0 );
184 QPoint p2 = myOverview->fromMain( w, 0 );
185 QPoint p3 = myOverview->fromMain( w, h );
186 QPoint p4 = myOverview->fromMain( 0, h );
192 initGeometry( poly );
196 OCCViewer_ViewPort3d* overview = myOverview->getViewPort( false );
198 double x1, y1, z1, x2, y2, z2;
199 main->getView()->Convert( main->width()/2, main->height()/2, x1, y1, z1 );
200 DEBTRACE("x1, y1, z1 " << x1 << " " << y1 << " " << z1);
201 // Patch for OCCT 6.9.1, on 7.0.0 the moving of point to plane XY is not necessary
202 // gp_Dir dm = main->getView()->Camera()->Direction();
203 // double t1 = -z1/dm.Z();
207 // DEBTRACE("x1, y1, z1 " << x1 << " " << y1 << " " << z1);
209 overview->getView()->Convert( c.x(), c.y(), x2, y2, z2 );
210 gp_Dir dov = overview->getView()->Camera()->Direction();
211 double t2 = -z2/dov.Z();
215 DEBTRACE("x2, y2, z2 " << x2 << " " << y2 << " " << z2);
218 aTrsf.SetTranslation( gp_Pnt( x1, y1, z1 ), gp_Pnt( x2, y2, z2 ) );
220 // Temporary patch for bug in OCCT 6.9.1
221 // Handle(Graphic3d_Camera) cam = main->getView()->Camera();
222 // gp_Dir u = cam->Up(), nu = u.Transformed (aTrsf);
223 // gp_Pnt e = cam->Eye(), ne = e.Transformed (aTrsf);
224 // gp_Pnt cen = cam->Center(), ncen = cen.Transformed (aTrsf);
226 // if (!nu.IsEqual (u, 0.0))
229 // DEBTRACE("nu " << nu.X() << " " << nu.Y() << " " << nu.Z());
232 // if (!ne.IsEqual (e, 0.0))
235 // DEBTRACE("ne " << ne.X() << " " << ne.Y() << " " << ne.Z())
238 // if (!ncen.IsEqual(cen, 0.0))
240 // cam->SetCenter (ncen);
241 // DEBTRACE("ncen " << ncen.X() << " " << ncen.Y() << " " << ncen.Z())
244 //version for new OCCT:
245 main->getView()->Camera()->Transform( aTrsf );
250 void HYDROGUI_OverviewBand::paintEvent( QPaintEvent* thePaintEvent )
252 QPainter painter( this );
253 painter.setRenderHint( QPainter::Antialiasing );
255 static QColor aColor = Qt::red;
256 static int aWidth = 2;
257 static QPen aPen( QBrush( aColor ), aWidth, Qt::DashDotLine );
259 painter.setPen( aPen );
260 painter.drawPolygon( myPoints );
265 HYDROGUI_Overview::HYDROGUI_Overview( const QString& theTitle, int theMargin, QWidget* theParent )
266 : QFrame( theParent ), myMargin( theMargin ),
267 myMainView( 0 ), myViewPort( 0 ), myBand( 0 )
269 setWindowTitle( theTitle );
270 myLayout = new QGridLayout( this );
271 myLayout->setMargin( 0 );
272 myLayout->setSpacing( 0 );
273 myLayout->setRowStretch( 0, 1 );
274 myLayout->setColumnStretch( 0, 1 );
277 HYDROGUI_Overview::~HYDROGUI_Overview()
282 QImage HYDROGUI_Overview::dump() const
287 Handle(V3d_View) view = myViewPort->getView();
291 int aWidth = myViewPort->width();
292 int aHeight = myViewPort->height();
296 #if OCC_VERSION_LARGE >= 0x07020000
297 view->ToPixMap( aPix,aWidth, aHeight,Graphic3d_BT_RGBA );
298 QImage anImage( aPix.Data(), aWidth, aHeight, QImage::Format_ARGB32 );
299 anImage = anImage.mirrored();
300 anImage = anImage.rgbSwapped();
302 view->ToPixMap(aPix, aWidth, aHeight, Graphic3d_BT_RGB);
303 QImage anImage( aWidth, aHeight, QImage::Format_ARGB32 );
304 for ( int i = 0; i < aWidth; i++ ) {
305 for ( int j = 0; j < aHeight; j++ ) {
306 Quantity_Color pixel = aPix.PixelColor( i, j ).GetRGB();
307 QColor color = QColor::fromRgbF( pixel.Red(), pixel.Green(), pixel.Blue() );
308 anImage.setPixelColor( i, j, color );
311 if ( aPix.IsTopDown() )
312 anImage = anImage.mirrored();
314 if( myBand && myBand->isVisible() )
316 QPixmap aPixmap = QPixmap::fromImage( anImage );
317 QPoint p = myBand->boundingRect().topLeft();
318 myBand->render( &aPixmap, p );
319 anImage = aPixmap.toImage();
324 OCCViewer_ViewPort3d* HYDROGUI_Overview::getViewPort( bool isMain ) const
328 if (myMainView!=NULL)
329 return myMainView->getViewPort();
337 void HYDROGUI_Overview::setMainView( OCCViewer_ViewFrame* theMainView )
339 myMainView = theMainView;
342 DEBTRACE("setMainView");
344 OCCViewer_ViewWindow* aMainView = myMainView->getView( OCCViewer_ViewFrame::MAIN_VIEW );
345 connect( aMainView, SIGNAL( vpTransformationFinished( OCCViewer_ViewWindow::OperationType ) ),
346 this, SLOT( OnTransformationAfterOp( OCCViewer_ViewWindow::OperationType ) ) );
347 connect( aMainView->getViewPort(), SIGNAL( vpResizeEvent( QResizeEvent* ) ),
348 this, SLOT( OnResizeEvent( QResizeEvent* ) ) );
349 connect( aMainView->getViewPort(), SIGNAL( vpTransformed( OCCViewer_ViewPort* ) ),
350 this, SLOT( OnTransformation() ) );
352 connect( myMainView, SIGNAL(destroyed()), this, SLOT( onMainViewDestr() ) );
356 myViewPort = new OCCViewer_ViewPort3d( this, myMainView->getViewPort()->getViewer(), V3d_ORTHOGRAPHIC );
360 myViewPort->setBackgroundColor( myMainView->getViewPort()->backgroundColor() );
362 connect( myViewPort, SIGNAL(destroyed()), this, SLOT( onViewPortDestr() ) );
363 connect( myViewPort, SIGNAL( vpMouseEvent( QMouseEvent* ) ),
364 this, SLOT( OnMouseEvent( QMouseEvent* ) ) );
365 connect( myViewPort, SIGNAL( vpResizeEvent( QResizeEvent* ) ),
366 this, SLOT( OnResizeEvent( QResizeEvent* ) ) );
368 myLayout->addWidget( myViewPort, 0, 0 );
372 //#if defined(TEST_MODE) || defined(_DEBUG)
373 //qApp->installEventFilter( this );
376 qApp->processEvents();
380 qApp->processEvents();
383 myBand = new HYDROGUI_OverviewBand( this );
385 myBand->update( true );
388 void HYDROGUI_Overview::setTopView()
393 Handle(V3d_View) aView3d = myViewPort->getView();
394 if( !aView3d.IsNull() )
395 aView3d->SetProj( V3d_Zpos );
396 myViewPort->fitAll();
398 // Apply margins for internal area in the view port
401 QRect aRect( -myMargin, -myMargin, myViewPort->width()+2*myMargin, myViewPort->height()+2*myMargin );
402 myViewPort->fitRect( aRect );
406 myBand->update( true );
409 void HYDROGUI_Overview::OnTransformationAfterOp( OCCViewer_ViewWindow::OperationType theOp )
411 if( myViewPort && theOp>=OCCViewer_ViewWindow::WINDOWFIT )
413 myViewPort->fitAll();
415 if( theOp==OCCViewer_ViewWindow::FITSELECTION )
417 CustomFitSelection();
422 void HYDROGUI_Overview::OnTransformation()
425 myBand->update( true );
428 QPoint HYDROGUI_Overview::fromMain( int xp, int yp ) const
430 if( !myMainView || !myViewPort || !myViewPort->isVisible() )
433 const double EPS = 1E-2;
435 Handle(V3d_View) aMain = myMainView->getViewPort()->getView();
436 Handle(V3d_View) aXY = myViewPort->getView();
438 // View coordinates to 3d (world) coordinates
440 aMain->Convert( xp, yp, x, y, z );
442 // Moving to the XY plane
443 gp_Vec aDir = aMain->Camera()->Direction();
444 if( fabs( aDir.Z() )<EPS )
447 double t = -z/aDir.Z();
452 // 3d (world) coordinates to view coordinates in the overview
453 aXY->Convert( x, y, z, xp, yp );
455 return QPoint( xp, yp );
458 void HYDROGUI_Overview::OnMouseEvent( QMouseEvent* theEvent )
460 QPoint mp = theEvent->pos();
464 switch( theEvent->type() )
466 case QEvent::MouseButtonPress:
467 myBand->drag( mp, true );
470 case QEvent::MouseButtonRelease:
471 myBand->drag( mp, false );
474 case QEvent::MouseMove:
475 if( myBand->isDrag() )
476 myBand->dragging( mp );
481 bool HYDROGUI_Overview::eventFilter( QObject* theObject, QEvent* theEvent )
483 //#if defined(TEST_MODE) || defined(_DEBUG)
484 if (theEvent->type() == 12) // paint
486 DEBTRACE("eventFilter " << theEvent->type() << " object " << theObject << " " << theObject->objectName().toStdString());
489 // switch( theEvent->type() )
491 // case QEvent::MouseMove:
493 // QPoint mp = ((QMouseEvent*)theEvent)->pos();
494 // //mp = getViewPort(false)->mapFromGlobal(mp);
495 // QString coords = QString( "(%0, %1)" ).arg( mp.x() ).arg( mp.y() );
496 // std::string scoords = coords.toStdString();
497 // qDebug( scoords.c_str() );
502 return QFrame::eventFilter( theObject, theEvent );
505 void HYDROGUI_Overview::OnResizeEvent( QResizeEvent* )
508 myBand->update( true );
512 void HYDROGUI_Overview::onMainViewDestr()
515 if (myViewPort == NULL)
517 Handle(V3d_View) ov = myViewPort->getView();
518 ov->View()->Deactivate();
519 delete myViewPort; //this will delete myBand
524 void HYDROGUI_Overview::onViewPortDestr()
530 void HYDROGUI_Overview::CustomFitSelection() const
532 DEBTRACE("CustomFitSelection");
533 OCCViewer_ViewPort3d* main = getViewPort( true );
537 int w = main->width();
538 int h = main->height();
540 Bnd_Box bounding = BoundingForSelection();
541 if( bounding.IsVoid() )
544 Standard_Real xmin, ymin, zmin, xmax, ymax, zmax;
545 bounding.Get( xmin, ymin, zmin, xmax, ymax, zmax );
547 QList<QPoint> points;
548 Standard_Integer xp, yp;
549 main->getView()->Convert( xmin, ymin, zmin, xp, yp ); points.append( QPoint( xp, yp ) );
550 main->getView()->Convert( xmax, ymin, zmin, xp, yp ); points.append( QPoint( xp, yp ) );
551 main->getView()->Convert( xmin, ymax, zmin, xp, yp ); points.append( QPoint( xp, yp ) );
552 main->getView()->Convert( xmax, ymax, zmin, xp, yp ); points.append( QPoint( xp, yp ) );
553 main->getView()->Convert( xmin, ymin, zmax, xp, yp ); points.append( QPoint( xp, yp ) );
554 main->getView()->Convert( xmax, ymin, zmax, xp, yp ); points.append( QPoint( xp, yp ) );
555 main->getView()->Convert( xmin, ymax, zmax, xp, yp ); points.append( QPoint( xp, yp ) );
556 main->getView()->Convert( xmax, ymax, zmax, xp, yp ); points.append( QPoint( xp, yp ) );
558 int xpmin, ypmin, xpmax, ypmax;
560 foreach( QPoint p, points )
562 int x = p.x(), y = p.y();
563 if( isFirst || x<xpmin )
565 if( isFirst || x>xpmax )
567 if( isFirst || y<ypmin )
569 if( isFirst || y>ypmax )
575 const int margin = 5;
576 QRect r( xpmin-margin, ypmin-margin, xpmax-xpmin+2*margin, ypmax-ypmin+2*margin );
580 Handle(AIS_InteractiveContext) HYDROGUI_Overview::context() const
584 SUIT_ViewModel* vm = myMainView->getViewManager()->getViewModel();
585 OCCViewer_Viewer* viewer = dynamic_cast<OCCViewer_Viewer*>( vm );
587 return viewer->getAISContext();
589 return Handle(AIS_InteractiveContext)();
592 typedef NCollection_DataMap<Handle(SelectMgr_SelectableObject), Handle(SelectMgr_IndexedMapOfOwner)> AIS_MapOfObjectOwners1;
593 typedef NCollection_DataMap<Handle(SelectMgr_SelectableObject), Handle(SelectMgr_IndexedMapOfOwner)>::Iterator AIS_MapIteratorOfMapOfObjectOwners1;
594 Bnd_Box HYDROGUI_Overview::BoundingForSelection() const
596 DEBTRACE("BoundingForSelection");
597 Handle(AIS_InteractiveContext) c = context();
599 Bnd_Box aBndSelected;
601 AIS_MapOfObjectOwners1 anObjectOwnerMap;
602 for (c->InitSelected(); c->MoreSelected(); c->NextSelected())
604 const Handle(SelectMgr_EntityOwner)& anOwner = c->SelectedOwner();
605 Handle(AIS_InteractiveObject) anObj = Handle(AIS_InteractiveObject)::DownCast(anOwner->Selectable());
606 if (anObj->IsInfinite())
611 if (anOwner == anObj->GlobalSelOwner())
614 anObj->BoundingBox (aTmpBnd);
615 aBndSelected.Add (aTmpBnd);
619 Handle(SelectMgr_IndexedMapOfOwner) anOwnerMap;
620 if (!anObjectOwnerMap.Find (anOwner->Selectable(), anOwnerMap))
622 anOwnerMap = new SelectMgr_IndexedMapOfOwner();
623 anObjectOwnerMap.Bind (anOwner->Selectable(), anOwnerMap);
626 anOwnerMap->Add (anOwner);
630 for (AIS_MapIteratorOfMapOfObjectOwners1 anIter (anObjectOwnerMap); anIter.More(); anIter.Next())
632 const Handle(SelectMgr_SelectableObject) anObject = anIter.Key();
633 Bnd_Box aTmpBox = anObject->BndBoxOfSelected (anIter.ChangeValue());
634 aBndSelected.Add (aTmpBox);
637 anObjectOwnerMap.Clear();