Salome HOME
020749: EDF 1291 SMESH : Create 2D Mesh from 3D improvement
[modules/smesh.git] / src / SMESHGUI / SMESHGUI_Make2DFrom3DOp.cxx
1 //  Copyright (C) 2007-2010  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.
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 // File   : SMESHGUI_Make2DFrom3D.cxx
20 // Author : Vadim SANDLER, Open CASCADE S.A.S. (vadim.sandler@opencascade.com)
21
22 #include "SMESHGUI_Make2DFrom3DOp.h"
23
24 #include "SMESHGUI.h"
25 #include "SMESHGUI_Utils.h"
26 #include "SMESHGUI_MeshUtils.h"
27 #include "SMESH_TypeFilter.hxx"
28 #include "SMESH_LogicalFilter.hxx"
29
30 // SALOME GUI includes
31 #include <LightApp_SelectionMgr.h>
32 #include <LightApp_UpdateFlags.h>
33 #include <SALOME_ListIO.hxx>
34 #include <SUIT_Desktop.h>
35 #include <SUIT_MessageBox.h>
36 #include <SUIT_OverrideCursor.h>
37 #include <SVTK_ViewModel.h>
38 #include <SalomeApp_Study.h>
39 #include <SalomeApp_Tools.h>
40
41 // IDL includes
42 #include <SALOMEconfig.h>
43 #include CORBA_SERVER_HEADER(SMESH_Group)
44
45 // Qt includes
46 #include <QGroupBox>
47 #include <QRadioButton>
48 #include <QLineEdit>
49 #include <QCheckBox>
50 #include <QHBoxLayout>
51 #include <QGridLayout>
52 #include <QToolButton>
53
54 #define SPACING 6
55 #define MARGIN  11
56
57 /*!
58   \class SMESHGUI_Make2DFrom3DDlg
59   \brief Copy Mesh dialog box
60 */
61
62 SMESHGUI_Make2DFrom3DDlg::SMESHGUI_Make2DFrom3DDlg( QWidget* parent )
63   : SMESHGUI_Dialog( parent, false, true, OK | Apply | Close | Help )
64 {
65   // title
66   setWindowTitle( tr("CAPTION") );
67
68   // mode
69   QGroupBox* aModeGrp = new QGroupBox( tr( "MODE" ), mainFrame() );
70   QHBoxLayout* aModeGrpLayout = new QHBoxLayout( aModeGrp );
71   aModeGrpLayout->setMargin( MARGIN );
72   aModeGrpLayout->setSpacing( SPACING );
73   my2dFrom3dRB = new QRadioButton( tr( "2D_FROM_3D" ), aModeGrp );
74   my1dFrom2dRB = new QRadioButton( tr( "1D_FROM_2D" ), aModeGrp );
75   my1dFrom3dRB = new QRadioButton( tr( "1D_FROM_3D" ), aModeGrp );
76   aModeGrpLayout->addWidget( my2dFrom3dRB );
77   aModeGrpLayout->addWidget( my1dFrom2dRB );
78   aModeGrpLayout->addWidget( my1dFrom3dRB );
79
80   // Groups of mesh faces
81   setObjectPixmap( "SMESH", tr( "ICON_SELECT" ) );
82   createObject( tr( "Groups" ), mainFrame(), Groups );
83   setNameIndication( Groups, ListOfNames );
84   objectWg( Groups, Btn )->hide();
85
86   // target
87   QGroupBox* aTargetGrp = new QGroupBox( tr( "TARGET" ), mainFrame() );
88   QGridLayout* aTargetGrpLayout = new QGridLayout( aTargetGrp );
89   aTargetGrpLayout->setMargin( MARGIN );
90   aTargetGrpLayout->setSpacing( SPACING );
91   myThisMeshRB   = new QRadioButton( tr( "THIS_MESH" ), aTargetGrp );
92   myNewMeshRB    = new QRadioButton( tr( "NEW_MESH" ),  aTargetGrp );
93   myMeshName     = new QLineEdit( aTargetGrp );
94   myCopyCheck    = new QCheckBox( tr( "COPY_SRC" ),     aTargetGrp );
95   aTargetGrpLayout->addWidget( myThisMeshRB,    0, 0 );
96   aTargetGrpLayout->addWidget( myNewMeshRB,     1, 0 );
97   aTargetGrpLayout->addWidget( myMeshName,     1, 1 );
98   aTargetGrpLayout->addWidget( myCopyCheck,    2, 0 );
99   myGroupCheck = new QCheckBox( tr( "CREATE_GROUP" ), mainFrame() );
100   myGroupName  = new QLineEdit( mainFrame() );
101
102   // layout
103   QGridLayout* aDlgLay = new QGridLayout( mainFrame() );
104   aDlgLay->setMargin( 0 );
105   aDlgLay->setSpacing( SPACING );
106   aDlgLay->addWidget( aModeGrp,     0, 0, 1, 3 );
107   aDlgLay->addWidget( objectWg( Groups,  Label ),   1, 0 );
108   aDlgLay->addWidget( objectWg( Groups,  Control ), 1, 1 );
109   aDlgLay->addWidget( aTargetGrp,   2, 0, 1, 3 );
110   aDlgLay->addWidget( myGroupCheck, 3, 0 );
111   aDlgLay->addWidget( myGroupName,  3, 1, 1, 2 );
112
113   // connect signals  
114   connect( myThisMeshRB, SIGNAL( clicked() ), this, SLOT( onTargetChanged() ) );
115   connect( myNewMeshRB,  SIGNAL( clicked() ), this, SLOT( onTargetChanged() ) );
116   connect( myGroupCheck, SIGNAL( clicked() ), this, SLOT( onGroupChecked() ) );
117
118   // init dlg
119   my2dFrom3dRB->setChecked( true );
120   myThisMeshRB->setChecked( true );
121   onTargetChanged();
122   onGroupChecked();
123 }
124
125 SMESHGUI_Make2DFrom3DDlg::~SMESHGUI_Make2DFrom3DDlg()
126 {
127 }
128
129 SMESH::Bnd_Dimension SMESHGUI_Make2DFrom3DDlg::mode() const
130 {
131   if ( my2dFrom3dRB->isChecked() )
132     return SMESH::BND_2DFROM3D;
133   else if ( my1dFrom2dRB->isChecked() )
134     return SMESH::BND_1DFROM2D;
135   else
136     return SMESH::BND_1DFROM3D;
137 }
138
139 bool SMESHGUI_Make2DFrom3DDlg::needNewMesh() const
140 {
141   return myNewMeshRB->isChecked();
142 }
143
144 QString SMESHGUI_Make2DFrom3DDlg::getNewMeshName() const
145 {
146   return myMeshName->text().trimmed();
147 }
148
149 void SMESHGUI_Make2DFrom3DDlg::setNewMeshName( const QString& name )
150 {
151   myMeshName->setText( name );
152 }
153
154 bool SMESHGUI_Make2DFrom3DDlg::needGroup() const
155 {
156   return myGroupCheck->isChecked();
157 }
158
159 QString SMESHGUI_Make2DFrom3DDlg::getGroupName() const
160 {
161   return myGroupName->text().trimmed();
162 }
163
164 void SMESHGUI_Make2DFrom3DDlg::setGroupName( const QString& name )
165 {
166   myGroupName->setText( name );
167 }
168
169 bool SMESHGUI_Make2DFrom3DDlg::copySource() const
170 {
171   return myCopyCheck->isChecked();
172 }
173
174 void SMESHGUI_Make2DFrom3DDlg::onTargetChanged()
175 {
176   myMeshName->setEnabled( myNewMeshRB->isChecked() );
177   myCopyCheck->setEnabled( myNewMeshRB->isChecked() );
178 }
179
180 void SMESHGUI_Make2DFrom3DDlg::onGroupChecked()
181 {
182   myGroupName->setEnabled( myGroupCheck->isChecked() );
183 }
184
185 /*!
186   \class SMESHGUI_Make2DFrom3DOp
187   \brief Copy Mesh operation class
188 */
189
190 SMESHGUI_Make2DFrom3DOp::SMESHGUI_Make2DFrom3DOp()
191  : SMESHGUI_SelectionOp()
192 {
193 }
194
195 SMESHGUI_Make2DFrom3DOp::~SMESHGUI_Make2DFrom3DOp()
196 {
197   if ( myDlg )
198     delete myDlg;
199 }
200
201 LightApp_Dialog* SMESHGUI_Make2DFrom3DOp::dlg() const
202 {
203   return myDlg;
204 }
205
206 void SMESHGUI_Make2DFrom3DOp::startOperation()
207 {
208   if( !myDlg )
209     myDlg = new SMESHGUI_Make2DFrom3DDlg( desktop() );
210
211   myHelpFileName = "make_2dmesh_from_3d_page.html";
212
213   SMESHGUI_SelectionOp::startOperation();
214
215   myDlg->setNewMeshName( SMESH::UniqueName( "Mesh_1" ) );
216   myDlg->setGroupName( SMESH::UniqueName( "Group" ) );
217   myDlg->show();
218
219   connect( myDlg->my2dFrom3dRB, SIGNAL( toggled(bool) ), this, SLOT( onModeChanged() ) );
220   connect( myDlg->my1dFrom2dRB, SIGNAL( toggled(bool) ), this, SLOT( onModeChanged() ) );
221   connect( myDlg->my1dFrom3dRB, SIGNAL( toggled(bool) ), this, SLOT( onModeChanged() ) );
222
223   onModeChanged();
224 }
225
226 void SMESHGUI_Make2DFrom3DOp::onModeChanged()
227 {
228   QRadioButton* b = dynamic_cast<QRadioButton*>( sender());
229   if ( b && !b->isChecked() )
230     return;
231
232   // enable "2D groups" field
233   bool enableGroups = ( myDlg->mode() == SMESH::BND_1DFROM3D );
234   myDlg->setObjectEnabled( SMESHGUI_Make2DFrom3DDlg::Groups, enableGroups );
235   ((QToolButton*) myDlg->objectWg( SMESHGUI_Make2DFrom3DDlg::Groups,
236                                    SMESHGUI_Make2DFrom3DDlg::Btn ))->setChecked( enableGroups );
237   
238   // install filter
239   int id =  enableGroups ? SMESHGUI_Make2DFrom3DDlg::Groups : SMESHGUI_Make2DFrom3DDlg::Mesh;
240   onDeactivateObject( id );
241   onActivateObject( id );
242 }
243
244 void SMESHGUI_Make2DFrom3DOp::selectionDone()
245 {
246   mySrcMesh = SMESH::SMESH_Mesh::_nil();
247   myDlg->clearSelection( SMESHGUI_Make2DFrom3DDlg::Groups );
248
249   if ( !dlg() ) return;
250
251   
252   if ( dlg()->isVisible() ) {
253     try {
254       QStringList names, ids;
255       LightApp_Dialog::TypesList types;
256       selected( names, types, ids );
257       myDlg->selectObject( names, types, ids );
258
259       SALOME_ListIO sel; selectionMgr()->selectedObjects( sel, SVTK_Viewer::Type() );
260       if ( !sel.IsEmpty() )
261       {
262         SMESH::SMESH_IDSource_var IS = SMESH::IObjectToInterface<SMESH::SMESH_IDSource>(sel.First());
263         if(!CORBA::is_nil(IS))
264           mySrcMesh = IS->GetMesh();
265       }
266     }
267     catch ( const SALOME::SALOME_Exception& S_ex ) {
268       SalomeApp_Tools::QtCatchCorbaException( S_ex );
269     }
270     catch ( ... ) {
271     }
272   }
273 }
274
275 SUIT_SelectionFilter* SMESHGUI_Make2DFrom3DOp::createFilter( const int theId ) const
276 {
277   MeshObjectType type = ( theId == SMESHGUI_Make2DFrom3DDlg::Groups ? GROUP_FACE : MESH );
278   SUIT_SelectionFilter* f = new SMESH_TypeFilter( type );
279   return f;
280 }
281
282 bool SMESHGUI_Make2DFrom3DOp::isValid( QString& msg ) const
283 {
284   if ( !dlg() ) return false;
285
286   // check if a mesh is selected
287   if ( mySrcMesh->_is_nil() )
288   {
289     msg = tr( "SMESH_ERR_NO_INPUT_MESH" );
290     return false;
291   }
292   // check if groups are selected
293   SMESH::Bnd_Dimension mode = myDlg->mode();
294   if ( mode == SMESH::BND_1DFROM3D )
295   {
296     SMESH::SMESH_GroupBase_var grp;
297     QStringList entries;
298     dlg()->selectedObject( SMESHGUI_Make2DFrom3DDlg::Groups, entries );
299     if ( !entries.isEmpty() )
300     {
301       _PTR(SObject) sobj = SMESHGUI::activeStudy()->studyDS()->FindObjectID( entries[0].toLatin1().constData() );
302       if ( sobj )
303         grp = SMESH::SObjectToInterface<SMESH::SMESH_GroupBase>( sobj );
304     }
305     if ( grp->_is_nil() ) {
306       msg = tr( "SMESH_ERR_NO_INPUT_GROUP" );
307       return false;
308     }
309   }
310   else
311   {
312     // check if mesh contains elements of required type
313     SMESH::Bnd_Dimension mode = myDlg->mode();
314
315     if ( mode == SMESH::BND_2DFROM3D && mySrcMesh->NbVolumes() == 0 ) {
316       msg = tr( "SMESH_ERR_NO_3D_ELEMENTS" );
317       return false;
318     }
319     else if ( mode == SMESH::BND_1DFROM2D && mySrcMesh->NbFaces() == 0  ) {
320       msg = tr( "SMESH_ERR_NO_2D_ELEMENTS" );
321       return false;
322     }
323   }
324
325   // check if new mesh name is specified
326   if ( myDlg->needNewMesh() && myDlg->getNewMeshName().isEmpty() ) {
327     msg = tr( "SMESH_ERR_MESH_NAME_NOT_SPECIFIED" );
328     return false;
329   }
330
331   // check if group name is specified
332   if ( myDlg->needGroup() && myDlg->getGroupName().isEmpty() ) {
333     msg = tr( "SMESH_ERR_GRP_NAME_NOT_SPECIFIED" );
334     return false;
335   }
336     
337   return true;
338 }
339
340 bool SMESHGUI_Make2DFrom3DOp::compute2DMesh()
341 {
342   SUIT_OverrideCursor wc;
343
344   bool ok = false;
345   try {
346     QStringList entries;
347     dlg()->selectedObject( SMESHGUI_Make2DFrom3DDlg::Groups, entries );
348     SMESH::ListOfIDSources_var groups = new SMESH::ListOfIDSources;
349     groups->length( entries.count() );
350     for ( int i = 0; i < entries.count(); ++i )
351     {
352       _PTR(SObject) sobj = SMESHGUI::activeStudy()->studyDS()->FindObjectID( entries[i].toLatin1().constData() );
353       SMESH::SMESH_IDSource_var grp = SMESH::SObjectToInterface<SMESH::SMESH_IDSource>( sobj );  
354       groups[i] = grp;
355     }
356     SMESH::Bnd_Dimension mode = myDlg->mode();
357     QString meshName  = myDlg->needNewMesh() ? myDlg->getNewMeshName() : QString();
358     QString groupName = myDlg->needGroup()   ? myDlg->getGroupName()   : QString();
359     bool copyAll = myDlg->copySource();
360
361     if ( !CORBA::is_nil( mySrcMesh ) ) {
362       SMESH::SMESH_MeshEditor_var aMeshEditor = mySrcMesh->GetMeshEditor();
363       SMESH::SMESH_Group_var newGrp;
364       SMESH::SMESH_Mesh_var newMesh;
365       CORBA::Long nbAdded = aMeshEditor->MakeBoundaryElements( mode,
366                                                                groupName.toLatin1().constData(),
367                                                                meshName.toLatin1().constData(),
368                                                                copyAll,
369                                                                groups,
370                                                                newMesh.out(),
371                                                                newGrp.out() );
372       SUIT_MessageBox::information( myDlg,
373                                     tr("SMESH_INFORMATION"),
374                                     tr("NB_ADDED").arg( nbAdded ));
375       if ( !newMesh->_is_nil() ) {
376 #ifdef WITHGENERICOBJ
377         newMesh->UnRegister();
378 #endif
379       }
380       if ( !newGrp->_is_nil() ) {
381 #ifdef WITHGENERICOBJ
382         newGrp->UnRegister();
383 #endif
384       }
385       ok = true;
386     }
387   }
388   catch ( ... ) {
389   }
390   return ok;
391 }
392
393 bool SMESHGUI_Make2DFrom3DOp::onApply()
394 {
395   if ( isStudyLocked() )
396     return false;
397
398   QString msg;
399   if ( !isValid( msg ) ) {
400     dlg()->show();
401     if ( msg != "" )
402       SUIT_MessageBox::warning( myDlg, tr( "SMESH_ERROR" ), msg );
403     return false;
404   }
405
406   bool res = false;
407   try {
408     res = compute2DMesh();
409   }
410   catch ( const SALOME::SALOME_Exception& S_ex ) {
411     SalomeApp_Tools::QtCatchCorbaException( S_ex );
412   }
413   catch ( ... ) {
414   }
415
416   if ( res ) {
417     SMESHGUI::Modified();
418     update( UF_ObjBrowser | UF_Model );
419     myDlg->setNewMeshName( SMESH::UniqueName( "Mesh_1" ) );
420     myDlg->setGroupName( SMESH::UniqueName( "Group" ) );
421   }
422   else {
423     SUIT_MessageBox::warning( myDlg, tr( "SMESH_ERROR" ), tr( "SMESH_OPERATION_FAILED" ) );
424   }
425
426   return res;
427 }