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