Salome HOME
refs #1329 (draft)
[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 // KERNEL includes
31 #include <Basics_OCCTVersion.hxx>
32
33 // OCC includes
34 #include <V3d_View.hxx>
35 #include <Graphic3d_MapIteratorOfMapOfStructure.hxx>
36 #if OCC_VERSION_LARGE < 0x07000000
37 #include <Visual3d_View.hxx>
38 #endif
39
40 // QT includes
41 #include <QImage>
42 #include <QAction>
43 #include <QDialog>
44
45 Handle(Image_PixMap) OCCViewer_Utilities::imageToPixmap( const QImage& anImage )
46 {
47   Handle(Image_PixMap) aPixmap = new Image_PixMap();
48   if ( !anImage.isNull() ) {
49     aPixmap->InitTrash( Image_PixMap::ImgBGRA, anImage.width(), anImage.height() );
50     aPixmap->SetTopDown( Standard_True );
51
52     const uchar* aImageBytes = anImage.bits();
53       
54     for ( int aLine = anImage.height() - 1; aLine >= 0; --aLine ) {
55 #if OCC_VERSION_LARGE > 0x06070100
56       // convert pixels from ARGB to renderer-compatible RGBA
57       for ( int aByte = 0; aByte < anImage.width(); ++aByte ) {
58             Image_ColorBGRA& aPixmapBytes = aPixmap->ChangeValue<Image_ColorBGRA>(aLine, aByte);
59
60             aPixmapBytes.b() = (Standard_Byte) *aImageBytes++;
61             aPixmapBytes.g() = (Standard_Byte) *aImageBytes++;
62             aPixmapBytes.r() = (Standard_Byte) *aImageBytes++;
63             aPixmapBytes.a() = (Standard_Byte) *aImageBytes++;
64           }
65 #else
66           Image_ColorBGRA* aPixmapBytes = aPixmap->EditData<Image_ColorBGRA>().ChangeRow(aLine);
67         
68       // convert pixels from ARGB to renderer-compatible RGBA
69       for ( int aByte = 0; aByte < anImage.width(); ++aByte ) {
70             aPixmapBytes->b() = (Standard_Byte) *aImageBytes++;
71             aPixmapBytes->g() = (Standard_Byte) *aImageBytes++;
72             aPixmapBytes->r() = (Standard_Byte) *aImageBytes++;
73             aPixmapBytes->a() = (Standard_Byte) *aImageBytes++;
74             aPixmapBytes++;
75       }
76 #endif
77     }
78   }
79   return aPixmap;
80 }
81
82 OCCViewer_ViewWindow::Mode2dType OCCViewer_Utilities::setViewer2DMode
83                                          ( OCCViewer_Viewer* theViewer,
84                                            const OCCViewer_ViewWindow::Mode2dType& theMode )
85 {
86   OCCViewer_ViewWindow::Mode2dType anOldMode = OCCViewer_ViewWindow::No2dMode;
87   OCCViewer_ViewFrame* aFrame = dynamic_cast<OCCViewer_ViewFrame*>
88                                      ( theViewer->getViewManager()->getActiveView() );
89   OCCViewer_ViewWindow* aView = aFrame ? aFrame->getView( OCCViewer_ViewFrame::MAIN_VIEW ) : 0;
90   if ( !aView )
91     return anOldMode;
92
93   // set a view mode
94   anOldMode = aView->get2dMode();
95   aView->set2dMode( theMode );
96   bool is2dMode = theMode != OCCViewer_ViewWindow::No2dMode;
97
98   // enable/disable view actions
99   QList<int> aNo2dActions;
100   aNo2dActions << OCCViewer_ViewWindow::ChangeRotationPointId
101                << OCCViewer_ViewWindow::RotationId
102                << OCCViewer_ViewWindow::FrontId
103                << OCCViewer_ViewWindow::BackId
104                //<< OCCViewer_ViewWindow::TopId
105                << OCCViewer_ViewWindow::BottomId
106                << OCCViewer_ViewWindow::LeftId
107                << OCCViewer_ViewWindow::RightId
108                << OCCViewer_ViewWindow::AntiClockWiseId
109                << OCCViewer_ViewWindow::ClockWiseId
110                << OCCViewer_ViewWindow::OrthographicId
111                << OCCViewer_ViewWindow::PerspectiveId
112                << OCCViewer_ViewWindow::ResetId;
113
114   QtxActionToolMgr* aToolMgr = aView->toolMgr();
115   QAction* anAction;
116   for ( int i = 0, aNb = aNo2dActions.size(); i < aNb; i++ ) {
117     anAction = aToolMgr->action( aNo2dActions[i] );
118     if ( anAction )
119       anAction->setEnabled( !is2dMode );
120   }
121   QAction* aTop = aToolMgr->action( OCCViewer_ViewWindow::TopId );
122   QtxMultiAction* aMulti = dynamic_cast<QtxMultiAction*>( aTop->parent() );
123   aMulti->setActiveAction( aTop );
124
125   // change view position
126   Handle(V3d_View) aView3d = aView->getViewPort()->getView();
127   if ( !aView3d.IsNull() ) {
128     switch ( theMode ) {
129       case OCCViewer_ViewWindow::XYPlane:
130         aView3d->SetProj (V3d_Zpos);
131         break;
132       case OCCViewer_ViewWindow::XZPlane:
133         aView3d->SetProj (V3d_Yneg);
134         break;
135       case OCCViewer_ViewWindow::YZPlane:
136         aView3d->SetProj (V3d_Xpos);
137         break;
138     }
139   }
140
141   return anOldMode;
142 }
143
144 bool OCCViewer_Utilities::isDialogOpened( OCCViewer_ViewWindow* theView, const QString& theName )
145 {
146   bool isFound = false;
147   OCCViewer_ViewFrame* aViewFrame = dynamic_cast<OCCViewer_ViewFrame*>( theView->parent()->parent() );
148   QList<QDialog*> allDialogs = aViewFrame->findChildren<QDialog*>();
149   foreach ( QDialog* d, allDialogs )
150     if ( d->objectName() == theName )
151       isFound = true;
152   return isFound;
153 }
154
155 bool OCCViewer_Utilities::computeVisibleBounds( const Handle(V3d_View) theView,
156                                                 double theBounds[6] )
157 {
158   bool isAny = false;
159
160   theBounds[0] = theBounds[2] = theBounds[4] = DBL_MAX;
161   theBounds[1] = theBounds[3] = theBounds[5] = -DBL_MAX;
162
163   Graphic3d_MapOfStructure aSetOfStructures;
164   theView->View()->DisplayedStructures( aSetOfStructures );
165   Graphic3d_MapIteratorOfMapOfStructure aStructureIt( aSetOfStructures );
166
167   for( ; aStructureIt.More(); aStructureIt.Next() ) {
168     const Handle(Graphic3d_Structure)& aStructure = aStructureIt.Key();
169     if ( aStructure->IsEmpty() || !aStructure->IsVisible() ||
170          aStructure->IsInfinite() || aStructure->CStructure()->IsForHighlight )
171       continue;
172     double aBounds[6];
173 #if OCC_VERSION_LARGE > 0x06070100
174     Bnd_Box aBox = aStructure->MinMaxValues();
175     aBounds[0] = aBox.IsVoid() ? RealFirst() : aBox.CornerMin().X();
176     aBounds[2] = aBox.IsVoid() ? RealFirst() : aBox.CornerMin().Y();
177     aBounds[4] = aBox.IsVoid() ? RealFirst() : aBox.CornerMin().Z();
178     aBounds[1] = aBox.IsVoid() ? RealLast()  : aBox.CornerMax().X();
179     aBounds[3] = aBox.IsVoid() ? RealLast()  : aBox.CornerMax().Y();
180     aBounds[5] = aBox.IsVoid() ? RealLast()  : aBox.CornerMax().Z();
181 #else
182     aStructure->MinMaxValues( aBounds[0], aBounds[2], aBounds[4],
183                               aBounds[1], aBounds[3], aBounds[5] );
184 #endif
185
186     if ( aBounds[0] > -DBL_MAX && aBounds[1] < DBL_MAX &&
187          aBounds[2] > -DBL_MAX && aBounds[3] < DBL_MAX &&
188          aBounds[4] > -DBL_MAX && aBounds[5] < DBL_MAX )
189     {
190       isAny = true;
191       for ( int i = 0; i < 5; i = i + 2 ) {
192         theBounds[i] = std::min( theBounds[i], aBounds[i] );
193         theBounds[i+1] = std::max( theBounds[i+1], aBounds[i+1] );
194       }
195     }
196   }
197   return isAny;
198 }
199
200 bool OCCViewer_Utilities::computeVisibleBBCenter( const Handle(V3d_View) theView,
201                                                   double& theX, double& theY, double& theZ )
202 {
203   double aBounds[6];
204   if ( !computeVisibleBounds( theView, aBounds ) )
205   {
206     // null bounding box => the center is (0,0,0)
207     theX = 0.0;
208     theY = 0.0;
209     theZ = 0.0;
210     return true;
211   }
212
213   static double aMinDistance = 1.0 / DBL_MAX;
214
215   double aLength = aBounds[1]-aBounds[0];
216   aLength = std::max( ( aBounds[3]-aBounds[2]), aLength );
217   aLength = std::max( ( aBounds[5]-aBounds[4]), aLength );
218
219   if ( aLength < aMinDistance )
220     return false;
221
222   double aWidth = sqrt( ( aBounds[1] - aBounds[0] ) * ( aBounds[1] - aBounds[0] ) +
223                         ( aBounds[3] - aBounds[2] ) * ( aBounds[3] - aBounds[2] ) +
224                         ( aBounds[5] - aBounds[4] ) * ( aBounds[5] - aBounds[4] ) );
225
226   if(aWidth < aMinDistance)
227     return false;
228
229   theX = (aBounds[0] + aBounds[1])/2.0;
230   theY = (aBounds[2] + aBounds[3])/2.0;
231   theZ = (aBounds[4] + aBounds[5])/2.0;
232
233   return true;
234 }
235
236 bool OCCViewer_Utilities::computeSceneBBCenter( const Handle(V3d_View) theView,
237                                                 double& theX, double& theY, double& theZ )
238 {
239   theX = 0, theY = 0, theZ = 0;
240   Bnd_Box aBox = theView->View()->MinMaxValues();
241   if (!aBox.IsVoid())
242   {
243     double Xmin, Ymin, Zmin, Xmax, Ymax, Zmax;
244     aBox.Get (Xmin, Ymin, Zmin, Xmax, Ymax, Zmax);
245     gp_Pnt aPnts[8] =
246     {
247       gp_Pnt (Xmin, Ymin, Zmin), gp_Pnt (Xmin, Ymin, Zmax),
248       gp_Pnt (Xmin, Ymax, Zmin), gp_Pnt (Xmin, Ymax, Zmax),
249       gp_Pnt (Xmax, Ymin, Zmin), gp_Pnt (Xmax, Ymin, Zmax),
250       gp_Pnt (Xmax, Ymax, Zmin), gp_Pnt (Xmax, Ymax, Zmax)
251     };
252
253     for (Standard_Integer i = 0; i < 8; i++)
254     {
255       const gp_Pnt& aCornPnt = aPnts[i];
256       theX += aCornPnt.X();
257       theY += aCornPnt.Y();
258       theZ += aCornPnt.Z();
259     }
260
261     theX /= 8;
262     theY /= 8;
263     theZ /= 8;
264     return true;
265   }
266   return false;
267 }