Salome HOME
Merge branch 'V8_3_BR' into V8_4_BR
[modules/gui.git] / src / OCCViewer / OCCViewer_Utilities.cxx
1 // Copyright (C) 2014-2016  CEA/DEN, EDF R&D, OPEN CASCADE
2 //
3 // This library is free software; you can redistribute it and/or
4 // modify it under the terms of the GNU Lesser General Public
5 // License as published by the Free Software Foundation; either
6 // version 2.1 of the License, or (at your option) any later version.
7 //
8 // This library is distributed in the hope that it will be useful,
9 // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
11 // Lesser General Public License for more details.
12 //
13 // You should have received a copy of the GNU Lesser General Public
14 // License along with this library; if not, write to the Free Software
15 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
16 //
17 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
18 //
19
20 // internal includes
21 #include "OCCViewer_Utilities.h"
22 #include "OCCViewer_ViewFrame.h"
23 #include "OCCViewer_ViewModel.h"
24 #include "OCCViewer_ViewPort3d.h"
25
26 #include "SUIT_ViewManager.h"
27 #include "QtxActionToolMgr.h"
28 #include "QtxMultiAction.h"
29
30 // OCC includes
31 #include <V3d_View.hxx>
32 #include <Graphic3d_MapIteratorOfMapOfStructure.hxx>
33
34 // QT includes
35 #include <QImage>
36 #include <QAction>
37 #include <QDialog>
38
39 Handle(Image_PixMap) OCCViewer_Utilities::imageToPixmap( const QImage& anImage )
40 {
41   Handle(Image_PixMap) aPixmap = new Image_PixMap();
42   if ( !anImage.isNull() ) {
43     aPixmap->InitTrash( Image_PixMap::ImgBGRA, anImage.width(), anImage.height() );
44     aPixmap->SetTopDown( Standard_True );
45
46     const uchar* aImageBytes = anImage.bits();
47       
48     for ( int aLine = anImage.height() - 1; aLine >= 0; --aLine ) {
49       // convert pixels from ARGB to renderer-compatible RGBA
50       for ( int aByte = 0; aByte < anImage.width(); ++aByte ) {
51             Image_ColorBGRA& aPixmapBytes = aPixmap->ChangeValue<Image_ColorBGRA>(aLine, aByte);
52
53             aPixmapBytes.b() = (Standard_Byte) *aImageBytes++;
54             aPixmapBytes.g() = (Standard_Byte) *aImageBytes++;
55             aPixmapBytes.r() = (Standard_Byte) *aImageBytes++;
56             aPixmapBytes.a() = (Standard_Byte) *aImageBytes++;
57           }
58     }
59   }
60   return aPixmap;
61 }
62
63 OCCViewer_ViewWindow::Mode2dType OCCViewer_Utilities::setViewer2DMode
64                                          ( OCCViewer_Viewer* theViewer,
65                                            const OCCViewer_ViewWindow::Mode2dType& theMode )
66 {
67   OCCViewer_ViewWindow::Mode2dType anOldMode = OCCViewer_ViewWindow::No2dMode;
68   OCCViewer_ViewFrame* aFrame = dynamic_cast<OCCViewer_ViewFrame*>
69                                      ( theViewer->getViewManager()->getActiveView() );
70   OCCViewer_ViewWindow* aView = aFrame ? aFrame->getView( OCCViewer_ViewFrame::MAIN_VIEW ) : 0;
71   if ( !aView )
72     return anOldMode;
73
74   // set a view mode
75   anOldMode = aView->get2dMode();
76   aView->set2dMode( theMode );
77   bool is2dMode = theMode != OCCViewer_ViewWindow::No2dMode;
78
79   // enable/disable view actions
80   QList<int> aNo2dActions;
81   aNo2dActions << OCCViewer_ViewWindow::ChangeRotationPointId
82                << OCCViewer_ViewWindow::RotationId
83                << OCCViewer_ViewWindow::FrontId
84                << OCCViewer_ViewWindow::BackId
85                //<< OCCViewer_ViewWindow::TopId
86                << OCCViewer_ViewWindow::BottomId
87                << OCCViewer_ViewWindow::LeftId
88                << OCCViewer_ViewWindow::RightId
89                << OCCViewer_ViewWindow::AntiClockWiseId
90                << OCCViewer_ViewWindow::ClockWiseId
91                << OCCViewer_ViewWindow::OrthographicId
92                << OCCViewer_ViewWindow::PerspectiveId
93                << OCCViewer_ViewWindow::ResetId;
94
95   QtxActionToolMgr* aToolMgr = aView->toolMgr();
96   QAction* anAction;
97   for ( int i = 0, aNb = aNo2dActions.size(); i < aNb; i++ ) {
98     anAction = aToolMgr->action( aNo2dActions[i] );
99     if ( anAction )
100       anAction->setEnabled( !is2dMode );
101   }
102   QAction* aTop = aToolMgr->action( OCCViewer_ViewWindow::TopId );
103   QtxMultiAction* aMulti = dynamic_cast<QtxMultiAction*>( aTop->parent() );
104   aMulti->setActiveAction( aTop );
105
106   // change view position
107   Handle(V3d_View) aView3d = aView->getViewPort()->getView();
108   if ( !aView3d.IsNull() ) {
109     switch ( theMode ) {
110       case OCCViewer_ViewWindow::XYPlane:
111         aView3d->SetProj (V3d_Zpos);
112         break;
113       case OCCViewer_ViewWindow::XZPlane:
114         aView3d->SetProj (V3d_Yneg);
115         break;
116       case OCCViewer_ViewWindow::YZPlane:
117         aView3d->SetProj (V3d_Xpos);
118         break;
119     }
120   }
121
122   return anOldMode;
123 }
124
125 bool OCCViewer_Utilities::isDialogOpened( OCCViewer_ViewWindow* theView, const QString& theName )
126 {
127   bool isFound = false;
128   OCCViewer_ViewFrame* aViewFrame = dynamic_cast<OCCViewer_ViewFrame*>( theView->parent()->parent() );
129   QList<QDialog*> allDialogs = aViewFrame->findChildren<QDialog*>();
130   foreach ( QDialog* d, allDialogs )
131     if ( d->objectName() == theName )
132       isFound = true;
133   return isFound;
134 }
135
136 bool OCCViewer_Utilities::computeVisibleBounds( const Handle(V3d_View) theView,
137                                                 double theBounds[6] )
138 {
139   bool isAny = false;
140
141   theBounds[0] = theBounds[2] = theBounds[4] = DBL_MAX;
142   theBounds[1] = theBounds[3] = theBounds[5] = -DBL_MAX;
143
144   Graphic3d_MapOfStructure aSetOfStructures;
145   theView->View()->DisplayedStructures( aSetOfStructures );
146   Graphic3d_MapIteratorOfMapOfStructure aStructureIt( aSetOfStructures );
147
148   for( ; aStructureIt.More(); aStructureIt.Next() ) {
149     const Handle(Graphic3d_Structure)& aStructure = aStructureIt.Key();
150     if ( aStructure->IsEmpty() || !aStructure->IsVisible() ||
151          aStructure->IsInfinite() || aStructure->CStructure()->IsForHighlight )
152       continue;
153     double aBounds[6];
154     Bnd_Box aBox = aStructure->MinMaxValues();
155     aBounds[0] = aBox.IsVoid() ? RealFirst() : aBox.CornerMin().X();
156     aBounds[2] = aBox.IsVoid() ? RealFirst() : aBox.CornerMin().Y();
157     aBounds[4] = aBox.IsVoid() ? RealFirst() : aBox.CornerMin().Z();
158     aBounds[1] = aBox.IsVoid() ? RealLast()  : aBox.CornerMax().X();
159     aBounds[3] = aBox.IsVoid() ? RealLast()  : aBox.CornerMax().Y();
160     aBounds[5] = aBox.IsVoid() ? RealLast()  : aBox.CornerMax().Z();
161
162     if ( aBounds[0] > -DBL_MAX && aBounds[1] < DBL_MAX &&
163          aBounds[2] > -DBL_MAX && aBounds[3] < DBL_MAX &&
164          aBounds[4] > -DBL_MAX && aBounds[5] < DBL_MAX )
165     {
166       isAny = true;
167       for ( int i = 0; i < 5; i = i + 2 ) {
168         theBounds[i] = std::min( theBounds[i], aBounds[i] );
169         theBounds[i+1] = std::max( theBounds[i+1], aBounds[i+1] );
170       }
171     }
172   }
173   return isAny;
174 }
175
176 bool OCCViewer_Utilities::computeVisibleBBCenter( const Handle(V3d_View) theView,
177                                                   double& theX, double& theY, double& theZ )
178 {
179   double aBounds[6];
180   if ( !computeVisibleBounds( theView, aBounds ) )
181   {
182     // null bounding box => the center is (0,0,0)
183     theX = 0.0;
184     theY = 0.0;
185     theZ = 0.0;
186     return true;
187   }
188
189   static double aMinDistance = 1.0 / DBL_MAX;
190
191   double aLength = aBounds[1]-aBounds[0];
192   aLength = std::max( ( aBounds[3]-aBounds[2]), aLength );
193   aLength = std::max( ( aBounds[5]-aBounds[4]), aLength );
194
195   if ( aLength < aMinDistance )
196     return false;
197
198   double aWidth = sqrt( ( aBounds[1] - aBounds[0] ) * ( aBounds[1] - aBounds[0] ) +
199                         ( aBounds[3] - aBounds[2] ) * ( aBounds[3] - aBounds[2] ) +
200                         ( aBounds[5] - aBounds[4] ) * ( aBounds[5] - aBounds[4] ) );
201
202   if(aWidth < aMinDistance)
203     return false;
204
205   theX = (aBounds[0] + aBounds[1])/2.0;
206   theY = (aBounds[2] + aBounds[3])/2.0;
207   theZ = (aBounds[4] + aBounds[5])/2.0;
208
209   return true;
210 }