Salome HOME
022484: EDF 2304 SMESH: Reorient a group of faces regarding to a volume
[modules/smesh.git] / src / SMESHGUI / SMESHGUI_ReorientFacesDlg.cxx
1 // Copyright (C) 2007-2014  CEA/DEN, EDF R&D, OPEN CASCADE
2 //
3 // Copyright (C) 2003-2007  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
4 // CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
5 //
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.
10 //
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.
15 //
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
19 //
20 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
21 //
22
23 // File   : SMESHGUI_ReorientFacesDlg.cxx
24 // Author : Edward AGAPOV, Open CASCADE S.A.S.
25 // SMESH includes
26 //
27 #include "SMESHGUI_ReorientFacesDlg.h"
28
29 #include "SMESHGUI.h"
30 #include "SMESHGUI_IdValidator.h"
31 #include "SMESHGUI_MeshUtils.h"
32 #include "SMESHGUI_VTKUtils.h"
33 #include "SMESHGUI_SpinBox.h"
34 #include "SMESHGUI_MeshEditPreview.h"
35
36 #include <SMDS_Mesh.hxx>
37 #include <SMESH_Actor.h>
38 #include <SMESH_ActorUtils.h>
39 #include <SMESH_NumberFilter.hxx>
40 #include <SMESH_LogicalFilter.hxx>
41 #include <SMESH_TypeFilter.hxx>
42
43 // SALOME GEOM includes
44 #include <GEOMBase.h>
45
46 // SALOME GUI includes
47 #include <LightApp_SelectionMgr.h>
48 #include <SALOME_ListIO.hxx>
49 #include <SALOME_ListIteratorOfListIO.hxx>
50 #include <SUIT_Desktop.h>
51 #include <SUIT_MessageBox.h>
52 #include <SUIT_OverrideCursor.h>
53 #include <SUIT_ResourceMgr.h>
54 #include <SVTK_ViewModel.h>
55 #include <SVTK_ViewWindow.h>
56 #include <SalomeApp_Tools.h>
57 #include <SalomeApp_TypeFilter.h>
58
59 // SALOME KERNEL includes
60 #include <SALOMEDS_SObject.hxx>
61
62 // OCCT includes
63 #include <BRep_Tool.hxx>
64 #include <TColStd_MapOfInteger.hxx>
65 #include <TColgp_SequenceOfXYZ.hxx>
66 #include <TopoDS_Vertex.hxx>
67 #include <gp_Pnt.hxx>
68
69 // Qt includes
70 #include <QGroupBox>
71 #include <QGridLayout>
72 #include <QHBoxLayout>
73 #include <QVBoxLayout>
74 #include <QLineEdit>
75 #include <QPushButton>
76 #include <QLabel>
77 #include <QRadioButton>
78 #include <QCheckBox>
79 #include <QButtonGroup>
80
81 // VTK includes
82 #include <vtkProperty.h>
83
84 // IDL includes
85 #include <SALOMEconfig.h>
86 #include CORBA_SERVER_HEADER(SMESH_Mesh)
87 #include CORBA_SERVER_HEADER(SMESH_MeshEditor)
88
89 // std
90 #include <limits>
91
92 #define SPACING 6
93 #define MARGIN  11
94
95 enum { CONSTRUCTOR_POINT=0, CONSTRUCTOR_FACE, CONSTRUCTOR_VOLUME,
96        EObject, EPoint, EFace, EDirection, EVolumes };
97
98 //=======================================================================
99 /*!
100  * \brief Dialog to reorient faces acoording to vector
101  */
102 //=======================================================================
103
104 SMESHGUI_ReorientFacesDlg::SMESHGUI_ReorientFacesDlg()
105   : SMESHGUI_Dialog( 0, false, true )
106 {
107   setWindowTitle(tr("CAPTION"));
108
109   QVBoxLayout* aDlgLay = new QVBoxLayout (mainFrame());
110   aDlgLay->setMargin(0);
111   aDlgLay->setSpacing(SPACING);
112
113   QWidget* aMainFrame = createMainFrame  (mainFrame());
114
115   aDlgLay->addWidget(aMainFrame);
116
117   aDlgLay->setStretchFactor(aMainFrame, 1);
118 }
119
120 //================================================================================
121 /*!
122  * \brief Create frame containing dialog's input fields
123  */
124 //================================================================================
125
126 QWidget* SMESHGUI_ReorientFacesDlg::createMainFrame (QWidget* theParent)
127 {
128   QWidget* aFrame = new QWidget(theParent);
129
130   // constructors
131
132   QPixmap iconReoriPoint (resMgr()->loadPixmap("SMESH", tr("ICON_DLG_REORIENT2D_POINT")));
133   QPixmap iconReoriFace  (resMgr()->loadPixmap("SMESH", tr("ICON_DLG_REORIENT2D_FACE")));
134   QPixmap iconReoriVolum (resMgr()->loadPixmap("SMESH", tr("ICON_DLG_REORIENT2D_VOLUME")));
135
136   QGroupBox* aConstructorBox = new QGroupBox(tr("REORIENT_FACES"), aFrame);
137   myConstructorGrp = new QButtonGroup(aConstructorBox);
138   QHBoxLayout* aConstructorGrpLayout = new QHBoxLayout(aConstructorBox);
139   aConstructorGrpLayout->setMargin(MARGIN);
140   aConstructorGrpLayout->setSpacing(SPACING);
141
142   QRadioButton* aPntBut = new QRadioButton(aConstructorBox);
143   aPntBut->setIcon(iconReoriPoint);
144   aPntBut->setChecked(true);
145   aConstructorGrpLayout->addWidget(aPntBut);
146   myConstructorGrp->addButton(aPntBut, CONSTRUCTOR_POINT);
147
148   QRadioButton* aFaceBut= new QRadioButton(aConstructorBox);
149   aFaceBut->setIcon(iconReoriFace);
150   aConstructorGrpLayout->addWidget(aFaceBut);
151   myConstructorGrp->addButton(aFaceBut, CONSTRUCTOR_FACE);
152
153   QRadioButton* aVolBut= new QRadioButton(aConstructorBox);
154   aVolBut->setIcon(iconReoriVolum);
155   aConstructorGrpLayout->addWidget(aVolBut);
156   myConstructorGrp->addButton(aVolBut, CONSTRUCTOR_VOLUME);
157
158   // Create other controls
159
160   setObjectPixmap( "SMESH", tr( "ICON_SELECT" ) );
161
162   createObject( tr("OBJECT")   , aFrame, EObject );
163   createObject( tr("POINT")    , aFrame, EPoint );
164   createObject( tr("FACE")     , aFrame, EFace );
165   createObject( tr("DIRECTION"), aFrame, EDirection );
166   createObject( tr("VOLUMES"),   aFrame, EVolumes );
167   setNameIndication( EObject, OneName );
168   setNameIndication( EFace, OneName );
169   setReadOnly( EFace, false );
170   if ( QLineEdit* le = qobject_cast<QLineEdit*>( objectWg( EFace, Control ) ))
171     le->setValidator( new SMESHGUI_IdValidator( this,1 ));
172
173   int width = aFaceBut->fontMetrics().width( tr("DIRECTION"));
174   objectWg( EDirection, Label )->setFixedWidth( width );
175   objectWg( EObject   , Label )->setFixedWidth( width );
176   objectWg( EPoint    , Label )->setFixedWidth( width );
177   objectWg( EFace     , Label )->setFixedWidth( width );
178   objectWg( EVolumes  , Label )->setFixedWidth( width );
179
180   myOutsideChk = new QCheckBox( tr("OUTSIDE_VOLUME_NORMAL"), aFrame);
181   myOutsideChk->setChecked( true );
182
183   QLabel* aXLabel = new QLabel(tr("SMESH_X"), aFrame);
184   myX = new SMESHGUI_SpinBox(aFrame);
185   QLabel* aYLabel = new QLabel(tr("SMESH_Y"), aFrame);
186   myY = new SMESHGUI_SpinBox(aFrame);
187   QLabel* aZLabel = new QLabel(tr("SMESH_Z"), aFrame);
188   myZ = new SMESHGUI_SpinBox(aFrame);
189
190   myX->RangeStepAndValidator(COORD_MIN, COORD_MAX, 10.0, "length_precision");
191   myY->RangeStepAndValidator(COORD_MIN, COORD_MAX, 10.0, "length_precision");
192   myZ->RangeStepAndValidator(COORD_MIN, COORD_MAX, 10.0, "length_precision");
193   myX->SetValue(0);
194   myY->SetValue(0);
195   myZ->SetValue(0);
196
197   QLabel* aDXLabel = new QLabel(tr("SMESH_DX"), aFrame);
198   myDX = new SMESHGUI_SpinBox(aFrame);
199   QLabel* aDYLabel = new QLabel(tr("SMESH_DY"), aFrame);
200   myDY = new SMESHGUI_SpinBox(aFrame);
201   QLabel* aDZLabel = new QLabel(tr("SMESH_DZ"), aFrame);
202   myDZ = new SMESHGUI_SpinBox(aFrame);
203   myDX->SetValue(1);
204   myDY->SetValue(0);
205   myDZ->SetValue(0);
206
207   myDX->RangeStepAndValidator(COORD_MIN, COORD_MAX, 10.0, "length_precision");
208   myDY->RangeStepAndValidator(COORD_MIN, COORD_MAX, 10.0, "length_precision");
209   myDZ->RangeStepAndValidator(COORD_MIN, COORD_MAX, 10.0, "length_precision");
210
211   width = Max( aFaceBut->fontMetrics().width( tr("SMESH_X")),
212                aFaceBut->fontMetrics().width( tr("SMESH_DX")));
213   aXLabel->setFixedWidth( width );
214   aYLabel->setFixedWidth( width );
215   aZLabel->setFixedWidth( width );
216   aDXLabel->setFixedWidth( width );
217   aDYLabel->setFixedWidth( width );
218   aDZLabel->setFixedWidth( width );
219
220   // Layouting
221
222   QGroupBox* anObjectGrp = new QGroupBox(tr("FACES"), aFrame);
223   QHBoxLayout* anObjectGrpLayout = new QHBoxLayout(anObjectGrp);
224   anObjectGrpLayout->setMargin(MARGIN);
225   anObjectGrpLayout->setSpacing(SPACING);
226   anObjectGrpLayout->addWidget( objectWg( EObject, Label ));
227   anObjectGrpLayout->addWidget( objectWg( EObject, Btn ));
228   anObjectGrpLayout->addWidget( objectWg( EObject, Control ));
229
230   myPointFrm = new QFrame(aFrame);
231   QHBoxLayout* aPointGrpLayout = new QHBoxLayout(myPointFrm);
232   aPointGrpLayout->setMargin(0);
233   objectWg( EPoint, Control )->hide();
234   aPointGrpLayout->addWidget( objectWg( EPoint, Label ) );
235   aPointGrpLayout->addWidget( objectWg( EPoint, Btn ) );
236   aPointGrpLayout->addWidget( aXLabel, 0 );
237   aPointGrpLayout->addWidget( myX,     1 );
238   aPointGrpLayout->addWidget( aYLabel, 0 );
239   aPointGrpLayout->addWidget( myY,     1 );
240   aPointGrpLayout->addWidget( aZLabel, 0 );
241   aPointGrpLayout->addWidget( myZ,     1 );
242
243   myFaceFrm = new QFrame(aFrame);
244   QHBoxLayout* aFaceGrpLayout = new QHBoxLayout(myFaceFrm);
245   aFaceGrpLayout->setMargin(0);
246   aFaceGrpLayout->addWidget( objectWg( EFace, Label ) );
247   aFaceGrpLayout->addWidget( objectWg( EFace, Btn ) );
248   aFaceGrpLayout->addWidget( objectWg( EFace, Control ) );
249
250   myVolumFrm = new QFrame(aFrame);
251   QGridLayout* aVolumGrpLayout = new QGridLayout(myVolumFrm);
252   aVolumGrpLayout->setMargin(0);
253   aVolumGrpLayout->setSpacing(SPACING);
254   aVolumGrpLayout->addWidget( objectWg( EVolumes, Label ),   0, 0 );
255   aVolumGrpLayout->addWidget( objectWg( EVolumes, Btn ),     0, 1 );
256   aVolumGrpLayout->addWidget( objectWg( EVolumes, Control ), 0, 2 );
257   aVolumGrpLayout->addWidget( myOutsideChk,                  1, 0, 1, 3 );
258
259   myDirFrm = new QFrame(aFrame);
260   QHBoxLayout* aDirectGrpLayout = new QHBoxLayout(myDirFrm);
261   aDirectGrpLayout->setMargin(0);
262   objectWg( EDirection, Control )->hide();
263   aDirectGrpLayout->addWidget( objectWg( EDirection, Label ) );
264   aDirectGrpLayout->addWidget( objectWg( EDirection, Btn ) );
265   aDirectGrpLayout->addWidget( aDXLabel, 0 );
266   aDirectGrpLayout->addWidget( myDX,     1 );
267   aDirectGrpLayout->addWidget( aDYLabel, 0 );
268   aDirectGrpLayout->addWidget( myDY,     1 );
269   aDirectGrpLayout->addWidget( aDZLabel, 0 );
270   aDirectGrpLayout->addWidget( myDZ,     1 );
271   
272
273   QGroupBox* anOrientGrp = new QGroupBox(tr("ORIENTATION"), aFrame);
274   QVBoxLayout* anOrientGrpLayout = new QVBoxLayout ( anOrientGrp );
275   anOrientGrpLayout->addWidget(myPointFrm);
276   anOrientGrpLayout->addWidget(myFaceFrm);
277   anOrientGrpLayout->addWidget(myVolumFrm);
278   anOrientGrpLayout->addWidget(myDirFrm);
279   
280
281   QVBoxLayout* aLay = new QVBoxLayout(aFrame);
282   aLay->addWidget(aConstructorBox);
283   aLay->addWidget(anObjectGrp);
284   aLay->addWidget(anOrientGrp);
285
286   connect( myConstructorGrp, SIGNAL(buttonClicked (int)), this, SLOT(constructorChange(int)));
287
288   return aFrame;
289 }
290
291 //================================================================================
292 /*!
293  * \brief Show point or face
294  */
295 //================================================================================
296
297 void SMESHGUI_ReorientFacesDlg::constructorChange(int id)
298 {
299   if ( id == CONSTRUCTOR_FACE )
300   {
301     myPointFrm->hide();
302     myVolumFrm->hide();
303     myFaceFrm->show();
304     myDirFrm->show();
305     activateObject( EFace );
306   }
307   else if ( id == CONSTRUCTOR_POINT )
308   {
309     myFaceFrm->hide();
310     myVolumFrm->hide();
311     myPointFrm->show();
312     myDirFrm->show();
313     activateObject( EPoint );
314   }
315   else // CONSTRUCTOR_VOLUME
316   {
317     myFaceFrm->hide();
318     myPointFrm->hide();
319     myDirFrm->hide();
320     myVolumFrm->show();
321     activateObject( EVolumes );
322   }
323 }
324
325 //================================================================================
326 /*!
327  * \brief Constructor
328 */
329 //================================================================================
330
331 SMESHGUI_ReorientFacesOp::SMESHGUI_ReorientFacesOp()
332   :SMESHGUI_SelectionOp( ActorSelection )
333 {
334   //myVectorPreview = 0;
335   myHelpFileName = "reorient_faces_page.html";
336
337   myDlg = new SMESHGUI_ReorientFacesDlg;
338   myDlg->constructorChange( CONSTRUCTOR_POINT );
339
340   // connect signals and slots
341   connect( myDlg->objectWg( EFace, LightApp_Dialog::Control ), SIGNAL(textChanged(const QString&)),
342            this, SLOT(onTextChange(const QString&)));
343   // connect(myDlg->myX, SIGNAL (valueChanged(double)), this, SLOT(redisplayPreview()));
344   // connect(myDlg->myY, SIGNAL (valueChanged(double)), this, SLOT(redisplayPreview()));
345   // connect(myDlg->myZ, SIGNAL (valueChanged(double)), this, SLOT(redisplayPreview()));
346   // connect(myDlg->myDX, SIGNAL (valueChanged(double)), this, SLOT(redisplayPreview()));
347   // connect(myDlg->myDY, SIGNAL (valueChanged(double)), this, SLOT(redisplayPreview()));
348   // connect(myDlg->myDZ, SIGNAL (valueChanged(double)), this, SLOT(redisplayPreview()));
349
350 }
351
352 //=======================================================================
353 // function : startOperation()
354 // purpose  : Init dialog fields, connect signals and slots, show dialog
355 //=======================================================================
356
357 void SMESHGUI_ReorientFacesOp::startOperation()
358 {
359   myObjectActor = 0;
360
361   // init simulation with a current View
362   //if ( myVectorPreview ) delete myVectorPreview;
363   // myVectorPreview = new SMESHGUI_MeshEditPreview(SMESH::GetViewWindow( getSMESHGUI() ));
364   // vtkProperty* aProp = vtkProperty::New();
365   // aProp->SetRepresentationToWireframe();
366   // aProp->SetColor(250, 0, 250);
367   // aProp->SetPointSize(5);
368   // aProp->SetLineWidth( SMESH::GetFloat("SMESH:element_width",1) + 1);
369   // myVectorPreview->GetActor()->SetProperty(aProp);
370   // aProp->Delete();
371
372   SMESHGUI_SelectionOp::startOperation();
373
374   myDlg->show();
375
376   mySelectionMode = 0;
377   myDlg->activateObject( EObject );
378 }
379
380 //================================================================================
381 /*!
382  * \brief Stops operation
383  */
384 //================================================================================
385
386 void SMESHGUI_ReorientFacesOp::stopOperation()
387 {
388   //myVectorPreview->SetVisibility(false);
389   if ( myObjectActor ) {
390     myObjectActor->SetPointRepresentation(false);
391     SMESH::RepaintCurrentView();
392     myObjectActor = 0;
393   }
394   SMESHGUI_SelectionOp::stopOperation();
395   myDlg->deactivateAll();
396 }
397
398 //================================================================================
399 /*!
400  * \brief Set selection mode corresponding to a pressed selection button
401  */
402 //================================================================================
403
404 void SMESHGUI_ReorientFacesOp::onActivateObject( int what )
405 {
406   if ( what == mySelectionMode )
407     return;
408   mySelectionMode = what;
409   switch ( mySelectionMode )
410   {
411   case EPoint:
412   case EDirection:
413     SMESH::SetPointRepresentation(true);
414     setSelectionMode( NodeSelection );
415     SMESH::SetPickable();
416     break;
417   case EObject:
418   case EVolumes:
419     SMESH::SetPointRepresentation(false);
420     setSelectionMode( ActorSelection );
421     break;
422   case EFace:
423     SMESH::SetPointRepresentation(false);
424     setSelectionMode( FaceSelection );
425     if ( myObjectActor )
426       SMESH::SetPickable( myObjectActor );
427     else
428       SMESH::SetPickable();
429     break;
430   }
431   SMESHGUI_SelectionOp::onActivateObject( what );
432 }
433
434 //================================================================================
435 /*!
436  * \brief Creates a filter corresponding to a pressed selection button
437  */
438 //================================================================================
439
440 SUIT_SelectionFilter* SMESHGUI_ReorientFacesOp::createFilter( const int what ) const
441 {
442   switch ( what )
443   {
444   case EObject:
445     {
446       QList<SUIT_SelectionFilter*> filters;
447       filters.append( new SMESH_TypeFilter( SMESH::MESH ));
448       filters.append( new SMESH_TypeFilter( SMESH::SUBMESH_FACE ));
449       filters.append( new SMESH_TypeFilter( SMESH::GROUP_FACE ));
450       return new SMESH_LogicalFilter( filters, SMESH_LogicalFilter::LO_OR );
451     }
452   case EVolumes:
453     {
454       QList<SUIT_SelectionFilter*> filters;
455       filters.append( new SMESH_TypeFilter( SMESH::MESH ));
456       filters.append( new SMESH_TypeFilter( SMESH::SUBMESH_SOLID ));
457       filters.append( new SMESH_TypeFilter( SMESH::GROUP_VOLUME ));
458       return new SMESH_LogicalFilter( filters, SMESH_LogicalFilter::LO_OR );
459     }
460   case EPoint:
461     {
462       QList<SUIT_SelectionFilter*> filters;
463       filters.append( new SMESH_TypeFilter( SMESH::IDSOURCE ));
464       filters.append( new SMESH_NumberFilter( "GEOM",TopAbs_VERTEX, 1, TopAbs_VERTEX ));
465       return new SMESH_LogicalFilter( filters, SMESH_LogicalFilter::LO_OR );
466     }
467   case EFace:
468   case EDirection:
469     {
470       return new SMESH_TypeFilter( SMESH::IDSOURCE );
471     }
472   }
473   return NULL;
474 }
475
476 //================================================================================
477 /*!
478  * \brief get data from selection
479  */
480 //================================================================================
481
482 void SMESHGUI_ReorientFacesOp::selectionDone()
483 {
484   if ( !myDlg->isVisible() || !myDlg->isEnabled() )
485     return;
486
487   if ( mySelectionMode == EVolumes )
488   {
489     SMESHGUI_SelectionOp::selectionDone();
490     return;
491   }
492
493   myDlg->clearSelection( mySelectionMode );
494
495   SALOME_ListIO aList;
496   selectionMgr()->selectedObjects(aList);
497   const int nbSelected = aList.Extent();
498   if ( nbSelected == 0 )
499     return;
500
501   Handle(SALOME_InteractiveObject) anIO = aList.First();
502
503   try
504   {
505     switch ( mySelectionMode )
506     {
507     case EObject: { // get an actor of object
508
509       if ( nbSelected == 1 )
510       {
511         myDlg->selectObject( EObject, anIO->getName(), 0, anIO->getEntry(), true );
512         // typeById( aList.First()->getEntry(),
513         //           SMESHGUI_SelectionOp::Object ),
514         myObjectActor = SMESH::FindActorByEntry( anIO->getEntry() );
515       }
516       break;
517     }
518     case EFace: {  // get a face ID
519
520       if ( nbSelected == 1 )
521       {
522         TColStd_IndexedMapOfInteger faceIndices;
523         selector()->GetIndex( anIO, faceIndices );
524         if ( faceIndices.Extent() == 1 )
525         {
526           SMESH_Actor* savedActor = myObjectActor;
527           myObjectActor = 0; // to prevent work of onTextChange()
528           myDlg->setObjectText( EFace, QString("%1").arg( faceIndices(1) ));
529           myObjectActor = savedActor;
530
531           if ( !myObjectActor )
532           {
533             myDlg->selectObject( EObject, anIO->getName(), 0, anIO->getEntry(), true );
534             // typeById( aList.First()->getEntry(),
535             //           SMESHGUI_SelectionOp::Object ),
536             myObjectActor = SMESH::FindActorByEntry( anIO->getEntry() );
537           }
538         }
539       }
540       break;
541     }
542     case EPoint:
543     case EDirection: {  // set XYZ by selected nodes or vertices
544
545       if ( mySelectionMode == EPoint && aList.Extent() > 1 )
546         return;
547
548       TColgp_SequenceOfXYZ points;
549       for( SALOME_ListIteratorOfListIO anIt( aList ); anIt.More(); anIt.Next() )
550       {
551         anIO = anIt.Value();
552         GEOM::GEOM_Object_var geom = SMESH::IObjectToInterface<GEOM::GEOM_Object>(anIO);
553         if ( !geom->_is_nil() ) {
554           TopoDS_Vertex aShape;
555           if ( GEOMBase::GetShape(geom, aShape) && aShape.ShapeType() == TopAbs_VERTEX ) {
556             gp_Pnt P = BRep_Tool::Pnt(aShape);
557             points.Append( P.XYZ() );
558           }
559         }
560         else
561         {
562           TColStd_IndexedMapOfInteger nodeIndices;
563           selector()->GetIndex( anIO, nodeIndices );
564           if ( nodeIndices.Extent() > 0 && nodeIndices.Extent() <=2 )
565           {
566             if ( SMESH_Actor* aMeshActor = SMESH::FindActorByEntry(anIO->getEntry()))
567               if (SMDS_Mesh* aMesh = aMeshActor->GetObject()->GetMesh())
568               {
569                 if (const SMDS_MeshNode* aNode = aMesh->FindNode( nodeIndices(1)))
570                   points.Append( gp_XYZ( aNode->X(), aNode->Y(), aNode->Z()));
571                 if ( nodeIndices.Extent() == 2 )
572                   if (const SMDS_MeshNode* aNode = aMesh->FindNode( nodeIndices(2)))
573                     points.Append( gp_XYZ( aNode->X(), aNode->Y(), aNode->Z()));
574               }
575           }
576         }
577       }
578       gp_XYZ xyz;
579       if ( points.Length() == 1 )
580         xyz = points(1);
581       else if ( points.Length() == 2 )
582         xyz = points(2) - points(1);
583       else
584         return;
585       if ( points.Length() == 1 && mySelectionMode == EPoint )
586       {
587         myDlg->myX->SetValue( xyz.X() );
588         myDlg->myY->SetValue( xyz.Y() );
589         myDlg->myZ->SetValue( xyz.Z() );
590         redisplayPreview();
591       }
592       if ( mySelectionMode == EDirection )
593       {
594         myDlg->myDX->SetValue( xyz.X() );
595         myDlg->myDY->SetValue( xyz.Y() );
596         myDlg->myDZ->SetValue( xyz.Z() );
597         redisplayPreview();
598       }
599       break;
600     } // case EPoint || EDirection
601     } // switch
602   }
603   catch (...)
604   {
605   }
606 }
607
608 //================================================================================
609 /*!
610  * \brief SLOT called when the face id is changed
611  */
612 //================================================================================
613
614 void SMESHGUI_ReorientFacesOp::onTextChange( const QString& theText )
615 {
616   if( myObjectActor )
617   {
618     sender()->blockSignals( true );
619     if ( mySelectionMode != EFace )
620     {
621       myDlg->activateObject( EFace );
622       myDlg->setObjectText( EFace, theText );
623     }
624     TColStd_MapOfInteger ids;
625     if ( !theText.isEmpty() && theText.toInt() > 0 )
626       ids.Add( theText.toInt() );
627
628     SMESHGUI_SelectionOp::addOrRemoveIndex( myObjectActor->getIO(), ids, false );
629     SMESHGUI_SelectionOp::highlight( myObjectActor->getIO(), true, true );
630     sender()->blockSignals( false );
631   }
632 }
633
634 //================================================================================
635 /*!
636  * \brief perform it's intention action: reorient faces of myObject
637  */
638 //================================================================================
639
640 bool SMESHGUI_ReorientFacesOp::onApply()
641 {
642   if( isStudyLocked() )
643     return false;
644
645   QString msg;
646   if ( !isValid( msg ) ) { // node id is invalid
647     if( !msg.isEmpty() )
648       SUIT_MessageBox::warning( dlg(), tr( "SMESH_WRN_WARNING" ), msg );
649     dlg()->show();
650     return false;
651   }
652
653   QStringList aParameters;
654   aParameters << myDlg->myDX->text();
655   aParameters << myDlg->myDY->text();
656   aParameters << myDlg->myDZ->text();
657   aParameters << myDlg->myX->text();
658   aParameters << myDlg->myY->text();
659   aParameters << myDlg->myZ->text();
660
661   try {
662     SUIT_OverrideCursor wc;
663
664     SMESH::SMESH_Mesh_var aMesh = myObject->GetMesh();
665     if ( aMesh->_is_nil() ) return false;
666
667     SMESH::SMESH_MeshEditor_var aMeshEditor = aMesh->GetMeshEditor();
668     if (aMeshEditor->_is_nil()) return false;
669
670     int aResult = 0;
671     if ( myDlg->myConstructorGrp->checkedId() == CONSTRUCTOR_VOLUME )
672     {
673       SMESH::ListOfIDSources_var faceGroups = new SMESH::ListOfIDSources;
674       faceGroups->length(1);
675       faceGroups[0] = myObject;
676
677       bool outsideNormal = myDlg->myOutsideChk->isChecked();
678
679       aResult = aMeshEditor->Reorient2DBy3D( faceGroups, myVolumeObj, outsideNormal );
680     }
681     else
682     {
683       SMESH::DirStruct direction;
684       direction.PS.x = myDlg->myDX->GetValue();
685       direction.PS.y = myDlg->myDY->GetValue();
686       direction.PS.z = myDlg->myDZ->GetValue();
687
688       long face = myDlg->objectText( EFace ).toInt();
689       if ( myDlg->myConstructorGrp->checkedId() == CONSTRUCTOR_POINT )
690         face = -1;
691
692       SMESH::PointStruct point;
693       point.x = myDlg->myX->GetValue();
694       point.y = myDlg->myY->GetValue();
695       point.z = myDlg->myZ->GetValue();
696
697       aMesh->SetParameters( aParameters.join(":").toLatin1().constData() );
698
699       aResult = aMeshEditor->Reorient2D( myObject, direction, face, point );
700     }
701
702     if (aResult)
703     {
704       SALOME_ListIO aList;
705       selectionMgr()->setSelectedObjects(aList,false);
706       SMESH::UpdateView();
707       SMESHGUI::Modified();
708     }
709     wc.suspend();
710     SUIT_MessageBox::information(SMESHGUI::desktop(), tr("SMESH_INFORMATION"),
711                                  tr("NB_REORIENTED").arg(aResult));
712   }
713   catch (const SALOME::SALOME_Exception& S_ex) {
714     SalomeApp_Tools::QtCatchCorbaException(S_ex);
715   }
716   catch (...) {
717   }
718
719   return true;
720 }
721
722 //================================================================================
723 /*!
724  * \brief Check data validity
725  */
726 //================================================================================
727
728 bool SMESHGUI_ReorientFacesOp::isValid( QString& msg )
729 {
730   // check object
731   QString objectEntry = myDlg->selectedObject( EObject );
732   _PTR(SObject) pSObject = studyDS()->FindObjectID( objectEntry.toLatin1().data() );
733   myObject = SMESH::SMESH_IDSource::_narrow( _CAST( SObject,pSObject )->GetObject() );
734   if ( myObject->_is_nil() )
735   {
736     msg = tr("NO_OBJECT_SELECTED");
737     return false;
738   }
739   bool hasFaces = false;
740   SMESH::array_of_ElementType_var types = myObject->GetTypes();
741   for ( size_t i = 0; i < types->length() && !hasFaces; ++i )
742     hasFaces = ( types[i] == SMESH::FACE );
743   if ( !hasFaces )
744   {
745     msg = tr("NO_FACES");
746     return false;
747   }
748
749   // check volume object
750   if ( myDlg->myConstructorGrp->checkedId() == CONSTRUCTOR_VOLUME )
751   {
752     objectEntry = myDlg->selectedObject( EVolumes );
753     _PTR(SObject) pSObject = studyDS()->FindObjectID( objectEntry.toLatin1().data() );
754     myVolumeObj = SMESH::SObjectToInterface< SMESH::SMESH_IDSource>( pSObject );
755     if ( myVolumeObj->_is_nil() )
756     {
757       msg = tr("NO_VOLUME_OBJECT_SELECTED");
758       return false;
759     }
760     bool hasVolumes = false;
761     types = myVolumeObj->GetTypes();
762     for ( size_t i = 0; i < types->length() && !hasVolumes; ++i )
763       hasVolumes = ( types[i] == SMESH::VOLUME );
764     if ( !hasVolumes )
765     {
766       msg = tr("NO_VOLUMES");
767       return false;
768     }
769   }
770   // check vector
771   gp_Vec vec( myDlg->myDX->GetValue(),
772               myDlg->myDY->GetValue(),
773               myDlg->myDZ->GetValue() );
774   if ( vec.Magnitude() < std::numeric_limits<double>::min() )
775   {
776     msg = tr("ZERO_SIZE_VECTOR");
777     return false;
778   }
779
780   // check face ID
781   if ( myDlg->myConstructorGrp->checkedId() == CONSTRUCTOR_FACE )
782   {
783     int faceID = myDlg->objectText( EFace ).toInt();
784     bool faceOK = ( faceID > 0 );
785     if ( faceOK )
786     {
787       if ( myObjectActor )
788       {
789         faceOK = ( myObjectActor->GetObject()->GetElemDimension( faceID ) == 2 );
790       }
791       else
792       {
793         SMESH::SMESH_Mesh_var aMesh = myObject->GetMesh();
794         if ( !aMesh->_is_nil() ) 
795           faceOK = ( aMesh->GetElementType( faceID, true ) == SMESH::FACE );
796       }
797     }
798     if ( !faceOK )
799     {
800       msg = tr("INVALID_FACE");
801       return false;
802     }
803   }
804
805   return true;
806 }
807
808 //================================================================================
809 /*!
810  * \brief Destructor
811 */
812 //================================================================================
813
814 SMESHGUI_ReorientFacesOp::~SMESHGUI_ReorientFacesOp()
815 {
816   if ( myDlg )        delete myDlg;
817   //if ( myVectorPreview ) delete myVectorPreview;
818 }
819
820 //================================================================================
821 /*!
822  * \brief Gets dialog of this operation
823  * \retval LightApp_Dialog* - pointer to dialog of this operation
824  */
825 //================================================================================
826
827 LightApp_Dialog* SMESHGUI_ReorientFacesOp::dlg() const
828 {
829   return myDlg;
830 }
831
832 //================================================================================
833 /*!
834  * \brief update preview
835  */
836 //================================================================================
837
838 void SMESHGUI_ReorientFacesOp::redisplayPreview()
839 {
840 //   SMESH::MeshPreviewStruct_var aMeshPreviewStruct;
841
842 //   bool moveShown = false;
843 //   if ( myObjectActor)
844 //   {
845 //     const bool autoSearch = myDlg->myAutoSearchChkBox->isChecked();
846 //     const bool preview    = myDlg->myPreviewChkBox->isChecked();
847 //     if ( autoSearch )
848 //     {
849 //       myDlg->myCurrentX->SetValue(0);
850 //       myDlg->myCurrentY->SetValue(0);
851 //       myDlg->myCurrentZ->SetValue(0);
852 //       myDlg->myDX->SetValue(0);
853 //       myDlg->myDY->SetValue(0);
854 //       myDlg->myDZ->SetValue(0);
855 //       myDlg->myId->setText("");
856 //     }
857 //     QString msg;
858 //     if ( autoSearch || isValid( msg ) )
859 //     {
860 //       try {
861 //         SMESH::SMESH_Mesh_var aMesh = SMESH::GetMeshByIO(myObjectActor->getIO());
862 //         if (!aMesh->_is_nil()) {
863 //           SMESH::SMESH_MeshEditor_var aPreviewer = aMesh->GetMeshEditPreviewer();
864 //           if (!aPreviewer->_is_nil())
865 //           {
866 //             SUIT_OverrideCursor aWaitCursor;
867
868 //             int anId = 0;
869 //             if ( autoSearch )
870 //               anId = aPreviewer->FindNodeClosestTo(myDlg->myX->GetValue(),
871 //                                                    myDlg->myY->GetValue(),
872 //                                                    myDlg->myZ->GetValue());
873 //             else
874 //               anId = myDlg->myId->text().toInt();
875
876 //             // find id and/or just compute preview
877 //             aPreviewer->MoveNode(anId,
878 //                                  myDlg->myX->GetValue(),
879 //                                  myDlg->myY->GetValue(),
880 //                                  myDlg->myZ->GetValue());
881 //             if ( autoSearch ) { // set found id
882 //               QString idTxt("%1");
883 //               if ( anId > 0 )
884 //                 idTxt = idTxt.arg( anId );
885 //               else
886 //                 idTxt = "";
887 //               myDlg->myId->setText( idTxt );
888 //             }
889
890 //             SMESH::double_array* aXYZ = aMesh->GetNodeXYZ( anId );
891 //             if( aXYZ && aXYZ->length() >= 3 )
892 //             {
893 //               double x = aXYZ->operator[](0);
894 //               double y = aXYZ->operator[](1);
895 //               double z = aXYZ->operator[](2);
896 //               double dx = myDlg->myX->GetValue() - x;
897 //               double dy = myDlg->myY->GetValue() - y;
898 //               double dz = myDlg->myZ->GetValue() - z;
899 //               myDlg->myCurrentX->SetValue(x);
900 //               myDlg->myCurrentY->SetValue(y);
901 //               myDlg->myCurrentZ->SetValue(z);
902 //               myDlg->myDX->SetValue(dx);
903 //               myDlg->myDY->SetValue(dy);
904 //               myDlg->myDZ->SetValue(dz);
905 //             }
906
907 //             if ( preview ) { // fill preview data
908 //               aMeshPreviewStruct = aPreviewer->GetPreviewData();
909 //               moveShown = ( anId > 0 );
910 //             }
911 //           }
912 //         }
913 //       }catch (...) {
914 //       }
915 //     }
916 //   }
917
918 //   if ( !moveShown )
919 //   {
920 //     aMeshPreviewStruct = new SMESH::MeshPreviewStruct();
921
922 //     aMeshPreviewStruct->nodesXYZ.length(1);
923 //     aMeshPreviewStruct->nodesXYZ[0].x = myDlg->myX->GetValue();
924 //     aMeshPreviewStruct->nodesXYZ[0].y = myDlg->myY->GetValue();
925 //     aMeshPreviewStruct->nodesXYZ[0].z = myDlg->myZ->GetValue();
926
927 //     aMeshPreviewStruct->elementTypes.length(1);
928 //     aMeshPreviewStruct->elementTypes[0].SMDS_ElementType = SMESH::NODE;
929 //     aMeshPreviewStruct->elementTypes[0].isPoly = false;
930 //     aMeshPreviewStruct->elementTypes[0].nbNodesInElement = 1;
931
932 //     aMeshPreviewStruct->elementConnectivities.length(1);
933 //     aMeshPreviewStruct->elementConnectivities[0] = 0;
934 //   }
935
936 //   // display data
937 //   if ( aMeshPreviewStruct.operator->() )
938 //   {
939 //     myVectorPreview->SetData(aMeshPreviewStruct._retn());
940 //   }
941 //   else
942 //   {
943 //     myVectorPreview->SetVisibility(false);
944 //   }
945
946 }