Salome HOME
Update of CheckDone
[modules/smesh.git] / src / SMESHGUI / SMESHGUI_Make2DFrom3DOp.cxx
1 // Copyright (C) 2007-2024  CEA, EDF, 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 // 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 #include "SMESHGUI_VTKUtils.h"
30 #include "SMESH_Actor.h"
31
32 // SALOME GUI includes
33 #include <LightApp_Application.h>
34 #include <LightApp_SelectionMgr.h>
35 #include <LightApp_UpdateFlags.h>
36 #include <SALOME_ListIO.hxx>
37 #include <SUIT_Desktop.h>
38 #include <SUIT_MessageBox.h>
39 #include <SUIT_OverrideCursor.h>
40 #include <SUIT_Session.h>
41 #include <SVTK_ViewModel.h>
42 //#include <SVTK_ViewWindow.h>
43 #include <SalomeApp_Study.h>
44 #include <SalomeApp_Tools.h>
45
46 // IDL includes
47 #include <SALOMEconfig.h>
48 #include CORBA_SERVER_HEADER(SMESH_Group)
49
50 // Qt includes
51 #include <QGroupBox>
52 #include <QRadioButton>
53 #include <QLineEdit>
54 #include <QCheckBox>
55 #include <QHBoxLayout>
56 #include <QGridLayout>
57 #include <QToolButton>
58
59 #include <Standard_ErrorHandler.hxx>
60
61 #define SPACING 6
62 #define MARGIN  11
63
64 /*!
65   \class SMESHGUI_Make2DFrom3DDlg
66   \brief Copy Mesh dialog box
67 */
68
69 SMESHGUI_Make2DFrom3DDlg::SMESHGUI_Make2DFrom3DDlg( QWidget* parent )
70   : SMESHGUI_Dialog( parent, false, true, OK | Apply | Close | Help )
71 {
72   // title
73   setWindowTitle( tr("CAPTION") );
74
75   // mode
76   myModeGrp = new QGroupBox( tr( "MODE" ), mainFrame() );
77   QHBoxLayout* aModeGrpLayout = new QHBoxLayout( myModeGrp );
78   aModeGrpLayout->setMargin( MARGIN );
79   aModeGrpLayout->setSpacing( SPACING );
80   my2dFrom3dRB = new QRadioButton( tr( "2D_FROM_3D" ), myModeGrp );
81   my1dFrom2dRB = new QRadioButton( tr( "1D_FROM_2D" ), myModeGrp );
82   //my1dFrom3dRB = new QRadioButton( tr( "1D_FROM_3D" ), aModeGrp );
83   aModeGrpLayout->addWidget( my2dFrom3dRB );
84   aModeGrpLayout->addWidget( my1dFrom2dRB );
85   //aModeGrpLayout->addWidget( my1dFrom3dRB );
86 //   // Groups of mesh faces
87 //   setObjectPixmap( "SMESH", tr( "ICON_SELECT" ) );
88 //   createObject( tr( "Groups" ), mainFrame(), Groups );
89 //   setNameIndication( Groups, ListOfNames );
90 //   objectWg( Groups, Btn )->hide();
91
92   // Mesh or Groups
93   //setObjectPixmap( "SMESH", tr( "ICON_SELECT" ) );
94   createObject( tr( "Groups" ), mainFrame(), MeshOrGroups );
95   setNameIndication( MeshOrGroups, ListOfNames );
96   objectWg( MeshOrGroups, Btn )->hide();
97
98   // target
99   QGroupBox* aTargetGrp = new QGroupBox( tr( "TARGET" ), mainFrame() );
100   QGridLayout* aTargetGrpLayout = new QGridLayout( aTargetGrp );
101   aTargetGrpLayout->setMargin( MARGIN );
102   aTargetGrpLayout->setSpacing( SPACING );
103   myThisMeshRB   = new QRadioButton( tr( "THIS_MESH" ), aTargetGrp );
104   myNewMeshRB    = new QRadioButton( tr( "NEW_MESH" ),  aTargetGrp );
105   myMeshName     = new QLineEdit( aTargetGrp );
106   myCopyCheck    = new QCheckBox( tr( "COPY_SRC" ),     aTargetGrp );
107   aTargetGrpLayout->addWidget( myThisMeshRB,    0, 0 );
108   aTargetGrpLayout->addWidget( myNewMeshRB,     1, 0 );
109   aTargetGrpLayout->addWidget( myMeshName,     1, 1 );
110   aTargetGrpLayout->addWidget( myCopyCheck,    2, 0 );
111   myGroupCheck = new QCheckBox( tr( "CREATE_GROUP" ), mainFrame() );
112   myGroupName  = new QLineEdit( mainFrame() );
113
114   // layout
115   QGridLayout* aDlgLay = new QGridLayout( mainFrame() );
116   aDlgLay->setMargin( 0 );
117   aDlgLay->setSpacing( SPACING );
118   aDlgLay->addWidget( myModeGrp,     0, 0, 1, 3 );
119   aDlgLay->addWidget( objectWg( MeshOrGroups,  Label ),   1, 0 );
120   aDlgLay->addWidget( objectWg( MeshOrGroups,  Control ), 1, 1 );
121   aDlgLay->addWidget( aTargetGrp,   2, 0, 1, 3 );
122   aDlgLay->addWidget( myGroupCheck, 3, 0 );
123   aDlgLay->addWidget( myGroupName,  3, 1, 1, 2 );
124
125   // connect signals  
126   connect( myThisMeshRB, SIGNAL( clicked() ), this, SLOT( onTargetChanged() ) );
127   connect( myNewMeshRB,  SIGNAL( clicked() ), this, SLOT( onTargetChanged() ) );
128   connect( myGroupCheck, SIGNAL( clicked() ), this, SLOT( onGroupChecked() ) );
129
130   // init dlg
131   my2dFrom3dRB->setChecked( true );
132   myThisMeshRB->setChecked( true );
133   onTargetChanged();
134   onGroupChecked();
135 }
136
137 SMESHGUI_Make2DFrom3DDlg::~SMESHGUI_Make2DFrom3DDlg()
138 {
139 }
140
141 SMESH::Bnd_Dimension SMESHGUI_Make2DFrom3DDlg::mode() const
142 {
143   if ( my2dFrom3dRB->isChecked() )
144     return SMESH::BND_2DFROM3D;
145   else if ( my1dFrom2dRB->isChecked() )
146     return SMESH::BND_1DFROM2D;
147   else
148     return SMESH::BND_1DFROM3D;
149 }
150
151 bool SMESHGUI_Make2DFrom3DDlg::needNewMesh() const
152 {
153   return myNewMeshRB->isChecked();
154 }
155
156 QString SMESHGUI_Make2DFrom3DDlg::getNewMeshName() const
157 {
158   return myMeshName->text().trimmed();
159 }
160
161 void SMESHGUI_Make2DFrom3DDlg::setNewMeshName( const QString& name )
162 {
163   myMeshName->setText( name );
164 }
165
166 void SMESHGUI_Make2DFrom3DDlg::setNewMeshEnabled( bool enable )
167 {
168   if ( !enable )
169     myThisMeshRB->setChecked( true );
170
171   myNewMeshRB->setEnabled( enable );
172
173   onTargetChanged();
174 }
175
176 bool SMESHGUI_Make2DFrom3DDlg::getNewMeshEnabled() const
177 {
178   return myNewMeshRB->isEnabled();
179 }
180
181 bool SMESHGUI_Make2DFrom3DDlg::needGroup() const
182 {
183   return myGroupCheck->isChecked();
184 }
185
186 QString SMESHGUI_Make2DFrom3DDlg::getGroupName() const
187 {
188   return myGroupName->text().trimmed();
189 }
190
191 void SMESHGUI_Make2DFrom3DDlg::setGroupName( const QString& name )
192 {
193   myGroupName->setText( name );
194 }
195
196 bool SMESHGUI_Make2DFrom3DDlg::copySource() const
197 {
198   return myCopyCheck->isChecked();
199 }
200
201 void SMESHGUI_Make2DFrom3DDlg::onTargetChanged()
202 {
203   myMeshName->setEnabled( myNewMeshRB->isChecked() );
204   myCopyCheck->setEnabled( myNewMeshRB->isChecked() );
205 }
206
207 void SMESHGUI_Make2DFrom3DDlg::onGroupChecked()
208 {
209   myGroupName->setEnabled( myGroupCheck->isChecked() );
210 }
211
212 /*!
213   \class SMESHGUI_Make2DFrom3DOp
214   \brief Copy Mesh operation class
215 */
216
217 SMESHGUI_Make2DFrom3DOp::SMESHGUI_Make2DFrom3DOp()
218   : SMESHGUI_SelectionOp(),
219     myMeshFilter(SMESH::MESH),
220     myGroupFilter(SMESH::GROUP)
221 {
222 }
223
224 SMESHGUI_Make2DFrom3DOp::~SMESHGUI_Make2DFrom3DOp()
225 {
226   if ( myDlg )
227     delete myDlg;
228 }
229
230 LightApp_Dialog* SMESHGUI_Make2DFrom3DOp::dlg() const
231 {
232   return myDlg;
233 }
234
235 void SMESHGUI_Make2DFrom3DOp::startOperation()
236 {
237   if( !myDlg )
238     myDlg = new SMESHGUI_Make2DFrom3DDlg( desktop() );
239
240   myHelpFileName = "make_2dmesh_from_3d.html";
241
242   SMESHGUI_SelectionOp::startOperation();
243
244   myDlg->setNewMeshName( SMESH::UniqueName( "Mesh_1" ) );
245   myDlg->setGroupName( SMESH::UniqueName( "Group" ) );
246   myDlg->show();
247
248   connect( myDlg->my2dFrom3dRB, SIGNAL( toggled(bool) ), this, SLOT( onModeChanged() ) );
249   connect( myDlg->my1dFrom2dRB, SIGNAL( toggled(bool) ), this, SLOT( onModeChanged() ) );
250   //connect( myDlg->my1dFrom3dRB, SIGNAL( toggled(bool) ), this, SLOT( onModeChanged() ) );
251
252   //onModeChanged();
253
254   myDlg->activateObject( SMESHGUI_Make2DFrom3DDlg::MeshOrGroups );
255   selectionDone();
256 }
257
258 //================================================================================
259 /*!
260  * \brief Set filter corresponding to dimension
261  */
262 //================================================================================
263
264 void SMESHGUI_Make2DFrom3DOp::onModeChanged()
265 {
266 //   QRadioButton* b = dynamic_cast<QRadioButton*>( sender());
267 //   if ( b && !b->isChecked() )
268 //     return;
269
270 //   // enable "2D groups" field
271 //   bool enableGroups = ( myDlg->mode() == SMESH::BND_1DFROM3D );
272 //   myDlg->setObjectEnabled( SMESHGUI_Make2DFrom3DDlg::Groups, enableGroups );
273 //   ((QToolButton*) myDlg->objectWg( SMESHGUI_Make2DFrom3DDlg::Groups,
274 //                                    SMESHGUI_Make2DFrom3DDlg::Btn ))->setChecked( enableGroups );
275   
276 //   // install filter
277 //   int id =  enableGroups ? SMESHGUI_Make2DFrom3DDlg::Groups : SMESHGUI_Make2DFrom3DDlg::Mesh;
278 //   onDeactivateObject( SMESHGUI_Make2DFrom3DDlg::MeshOrGroups );
279 //   onActivateObject  ( SMESHGUI_Make2DFrom3DDlg::MeshOrGroups );
280 //   selectionDone();
281 }
282
283 void SMESHGUI_Make2DFrom3DOp::selectionDone()
284 {
285   myDlg->clearSelection( SMESHGUI_Make2DFrom3DDlg::MeshOrGroups );
286   mySrcMesh = SMESH::SMESH_Mesh::_nil();
287
288   if ( !dlg() ) return;
289
290   
291   if ( dlg()->isVisible() ) {
292     try {
293       QStringList names, ids;
294       LightApp_Dialog::TypesList types;
295       selected( names, types, ids );
296       for ( int i = 0; i < names.count(); ++i )
297         names[i] = names[i].trimmed();
298       myDlg->selectObject( names, types, ids );
299
300       // enable/desable "new mesh" button
301       bool isMesh = true;
302       for ( int i = 0; i < ids.count() && isMesh; ++i )
303       {
304         _PTR(SObject) sobj = SMESH::getStudy()->FindObjectID( ids[i].toUtf8().constData() );
305         mySrcMesh = SMESH::SObjectToInterface<SMESH::SMESH_Mesh>( sobj );  
306         //isMesh = !mySrcMesh->_is_nil(); // EAP - it's sometimes necessary to copy to a new mesh
307       }
308       myDlg->setNewMeshEnabled( isMesh );
309     }
310     catch ( const SALOME::SALOME_Exception& S_ex ) {
311       SalomeApp_Tools::QtCatchCorbaException( S_ex );
312     }
313     catch ( ... ) {
314     }
315   }
316 }
317
318 SUIT_SelectionFilter* SMESHGUI_Make2DFrom3DOp::createFilter( const int /*theId*/ ) const
319 {
320   SMESHGUI_Make2DFrom3DOp* me = (SMESHGUI_Make2DFrom3DOp*) this;
321
322   QList<SUIT_SelectionFilter*> subFilters;
323   subFilters.append( & me->myMeshFilter );
324   subFilters.append( & me->myGroupFilter );
325
326   SUIT_SelectionFilter* f = new SMESH_LogicalFilter( subFilters, SMESH_LogicalFilter::LO_OR );
327   return f;
328 }
329
330 bool SMESHGUI_Make2DFrom3DOp::isValid( QString& msg ) const
331 {
332   if ( !dlg() ) return false;
333
334   // check if a mesh is selected
335   if ( !myDlg->hasSelection( SMESHGUI_Make2DFrom3DDlg::MeshOrGroups ))
336   {
337     msg = tr( "SMESH_ERR_NO_INPUT_MESH" );
338     return false;
339   }
340   QStringList entries;
341   dlg()->selectedObject( SMESHGUI_Make2DFrom3DDlg::MeshOrGroups, entries );
342   const bool isMeshSelected = ( !mySrcMesh->_is_nil() );
343   if ( isMeshSelected )
344   {
345     // only one mesh is allowed
346     if ( entries.size() > 1 ) {
347       msg = tr( "SMESH_TOO_MANY_MESHES" );
348       return false;
349     }
350   }
351   else
352   {
353     // check if only groups are selected
354     for ( int i = 0; i < entries.count(); ++i )
355     {
356       SMESH::SMESH_GroupBase_var grp;
357       if ( _PTR(SObject) sobj = SMESH::getStudy()->FindObjectID( entries[i].toUtf8().constData() ))
358         grp = SMESH::SObjectToInterface<SMESH::SMESH_GroupBase>( sobj );
359       if ( grp->_is_nil() ) {
360         msg = tr( "SMESH_NOT_ONLY_GROUPS" );
361         return false;
362       }
363     }
364   }
365   // check if the selected objects contains elements of required type
366   bool hasFaces = false, hasVolumes = false;
367   SMESH::Bnd_Dimension mode = myDlg->mode();
368   for ( int i = 0; i < entries.count(); ++i )
369   {
370     SMESH::SMESH_IDSource_var idSource;
371     if ( _PTR(SObject) sobj = SMESH::getStudy()->FindObjectID( entries[i].toUtf8().constData() ))
372       idSource = SMESH::SObjectToInterface<SMESH::SMESH_IDSource>( sobj );
373     if ( !idSource->_is_nil() ) {
374       SMESH::array_of_ElementType_var types = idSource->GetTypes();
375       for ( int j = 0; j < (int) types->length(); ++j )
376         if ( types[j] == SMESH::VOLUME )
377           hasVolumes = true;
378         else if ( types[j] == SMESH::FACE )
379           hasFaces = true;
380     }
381   }
382   if ( mode == SMESH::BND_2DFROM3D && !hasVolumes ) {
383     msg = tr( "SMESH_ERR_NO_3D_ELEMENTS" );
384     return false;
385   }
386   else if ( mode == SMESH::BND_1DFROM2D && !hasFaces  ) {
387     msg = tr( "SMESH_ERR_NO_2D_ELEMENTS" );
388     return false;
389   }
390
391   // check if new mesh name is specified
392   if ( myDlg->needNewMesh() && myDlg->getNewMeshName().isEmpty() ) {
393     msg = tr( "SMESH_ERR_MESH_NAME_NOT_SPECIFIED" );
394     return false;
395   }
396
397   // check if group name is specified
398   if ( myDlg->needGroup() && myDlg->getGroupName().isEmpty() ) {
399     msg = tr( "SMESH_ERR_GRP_NAME_NOT_SPECIFIED" );
400     return false;
401   }
402
403   return true;
404 }
405
406 bool SMESHGUI_Make2DFrom3DOp::compute2DMesh( QStringList& theEntryList )
407 {
408   SUIT_OverrideCursor wc;
409
410   bool ok = false;
411   bool toCreateAllElements = false;
412   try {
413     SMESH::Bnd_Dimension mode = myDlg->mode();
414     QString meshName          = myDlg->needNewMesh() ? myDlg->getNewMeshName() : QString();
415     QString groupName         = myDlg->needGroup()   ? myDlg->getGroupName()   : QString();
416     bool copyAll              = myDlg->copySource();
417
418     QStringList entries;
419     dlg()->selectedObject( SMESHGUI_Make2DFrom3DDlg::MeshOrGroups, entries );
420     SMESH::ListOfIDSources_var groups = new SMESH::ListOfIDSources;
421     QString wrongGroups = "";
422
423     if ( mySrcMesh->_is_nil() ) // get selected groups, find groups of wrong type
424     {
425       int nbGroups = 0;
426       int goodType = ( mode == SMESH::BND_2DFROM3D ? SMESH::VOLUME : SMESH::FACE );
427       groups->length( entries.count() );
428       for ( int i = 0; i < entries.count(); ++i )
429       {
430         _PTR(SObject) sobj = SMESH::getStudy()->FindObjectID( entries[i].toUtf8().constData() );
431         SMESH::SMESH_IDSource_var grp = SMESH::SObjectToInterface<SMESH::SMESH_IDSource>( sobj );  
432         SMESH::array_of_ElementType_var types = grp->GetTypes();
433         if ( types->length() < 1 || types[0] != goodType )
434         {
435           if ( !wrongGroups.isEmpty() )
436             wrongGroups += ", ";
437           wrongGroups += sobj->GetName().c_str();
438         }
439         else
440         {
441           groups[ nbGroups++ ] = grp;
442         }
443       }
444       groups->length( nbGroups );
445       mySrcMesh = groups[0]->GetMesh();
446     }
447
448     if ( !CORBA::is_nil( mySrcMesh ) ) {
449       SMESH::SMESH_MeshEditor_var aMeshEditor = mySrcMesh->GetMeshEditor();
450       SMESH::SMESH_Group_var newGrp;
451       SMESH::SMESH_Mesh_var newMesh;
452       CORBA::Long nbAdded = aMeshEditor->MakeBoundaryElements( mode,
453                                                                groupName.toUtf8().constData(),
454                                                                meshName.toUtf8().constData(),
455                                                                copyAll,
456                                                                toCreateAllElements,
457                                                                groups,
458                                                                newMesh.out(),
459                                                                newGrp.out() );
460       QString msg = tr("NB_ADDED").arg( nbAdded );
461       if ( !wrongGroups.isEmpty() )
462         msg += ".\n" + tr("WRONG_GROUPS").arg( wrongGroups );
463       SUIT_MessageBox::information( myDlg, tr("SMESH_INFORMATION"), msg);
464
465       if ( !newMesh->_is_nil() ) {
466         if( _PTR(SObject) aSObject = SMESH::ObjectToSObject( newMesh ) )
467           theEntryList.append( aSObject->GetID().c_str() );
468       }
469       ok = true;
470
471       for ( int i = 0; i < entries.count(); ++i )
472         if ( SMESH_Actor* actor = SMESH::FindActorByEntry( entries[i].toUtf8().constData() ))
473         {
474           actor->SetEntityMode( actor->GetEntityMode() | SMESH_Actor::eFaces );
475           SMESH::Update( actor->getIO(), actor->GetVisibility() );
476         }
477       SMESH::RepaintCurrentView();
478     }
479   }
480   catch ( ... ) {
481   }
482   return ok;
483 }
484
485 bool SMESHGUI_Make2DFrom3DOp::onApply()
486 {
487   if ( SMESHGUI::isStudyLocked() )
488     return false;
489
490   QString msg;
491   if ( !isValid( msg ) ) {
492     dlg()->show();
493     if ( msg != "" )
494       SUIT_MessageBox::warning( myDlg, tr( "SMESH_ERROR" ), msg );
495     return false;
496   }
497
498   QStringList anEntryList;
499   bool res = false;
500   try {
501     res = compute2DMesh( anEntryList );
502   }
503   catch ( const SALOME::SALOME_Exception& S_ex ) {
504     SalomeApp_Tools::QtCatchCorbaException( S_ex );
505   }
506   catch ( ... ) {
507   }
508
509   if ( res ) {
510     SMESHGUI::Modified();
511     update( UF_ObjBrowser | UF_Model );
512     if( LightApp_Application* anApp =
513         dynamic_cast<LightApp_Application*>( SUIT_Session::session()->activeApplication() ) )
514       anApp->browseObjects( anEntryList, isApplyAndClose() );
515     myDlg->setNewMeshName( SMESH::UniqueName( "Mesh_1" ) );
516     myDlg->setGroupName( SMESH::UniqueName( "Group" ) );
517   }
518   else {
519     SUIT_MessageBox::warning( myDlg, tr( "SMESH_ERROR" ), tr( "SMESH_OPERATION_FAILED" ) );
520   }
521
522   return res;
523 }