Salome HOME
bos #32735 [CEA] Create 2D Mesh from 3D elements.
[modules/smesh.git] / src / SMESHGUI / SMESHGUI_MakeFull2DFrom3DOp.cxx
1 // Copyright (C) 2007-2023  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_MakeFull2DFrom3DOp.cxx
20 // Author : Cesar Conopoima, Open CASCADE S.A.S. (cesar.conopoima@opencascade.com)
21
22 #include "SMESHGUI_MakeFull2DFrom3DOp.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
53 #include <Standard_ErrorHandler.hxx>
54
55 /*!
56   \class SMESHGUI_Make2DFrom3DDlg
57   \brief Copy Mesh dialog box
58 */
59
60 SMESHGUI_MakeFull2DFrom3DDlg::SMESHGUI_MakeFull2DFrom3DDlg( QWidget* parent )
61   : SMESHGUI_Make2DFrom3DDlg( parent )
62 {
63   // title
64   setWindowTitle( tr("CAPTION") );
65   myModeGrp->setVisible(false);
66 }
67
68 SMESHGUI_MakeFull2DFrom3DDlg::~SMESHGUI_MakeFull2DFrom3DDlg()
69 {
70 }
71
72
73 /*!
74   \class SMESHGUI_MakeFull2DFrom3DOp
75   \brief Copy Mesh operation class
76 */
77 SMESHGUI_MakeFull2DFrom3DOp::SMESHGUI_MakeFull2DFrom3DOp()
78    : SMESHGUI_SelectionOp(),
79     myMeshFilter(SMESH::MESH),
80     myGroupFilter(SMESH::GROUP)
81 {
82 }
83
84 SMESHGUI_MakeFull2DFrom3DOp::~SMESHGUI_MakeFull2DFrom3DOp()
85 {
86 }
87
88 LightApp_Dialog* SMESHGUI_MakeFull2DFrom3DOp::dlg() const
89 {
90   return myDlg;
91 }
92
93 void SMESHGUI_MakeFull2DFrom3DOp::startOperation()
94 {
95   if( !myDlg )
96     myDlg = new SMESHGUI_MakeFull2DFrom3DDlg( desktop() );
97
98
99   myHelpFileName = "make_2dmesh_from_3d_elements.html";
100
101   SMESHGUI_SelectionOp::startOperation();
102
103   myDlg->setNewMeshName( SMESH::UniqueName( "Mesh_1" ) );
104   myDlg->setGroupName( SMESH::UniqueName( "Group" ) );
105   myDlg->show();
106
107   myDlg->activateObject( SMESHGUI_MakeFull2DFrom3DDlg::MeshOrGroups );
108   selectionDone();
109 }
110
111 void SMESHGUI_MakeFull2DFrom3DOp::selectionDone()
112 {
113   myDlg->clearSelection( SMESHGUI_MakeFull2DFrom3DDlg::MeshOrGroups );
114   mySrcMesh = SMESH::SMESH_Mesh::_nil();
115
116   if ( !dlg() ) return;
117   if ( dlg()->isVisible() ) {
118     try {
119       QStringList names, ids;
120       LightApp_Dialog::TypesList types;
121       selected( names, types, ids );
122       for ( int i = 0; i < names.count(); ++i )
123         names[i] = names[i].trimmed();
124       myDlg->selectObject( names, types, ids );
125
126       // enable/desable "new mesh" button
127       bool isMesh = true;
128       for ( int i = 0; i < ids.count() && isMesh; ++i )
129       {
130         _PTR(SObject) sobj = SMESH::getStudy()->FindObjectID( ids[i].toUtf8().constData() );
131         mySrcMesh = SMESH::SObjectToInterface<SMESH::SMESH_Mesh>( sobj );  
132       }
133       myDlg->setNewMeshEnabled( isMesh );
134     }
135     catch ( const SALOME::SALOME_Exception& S_ex ) {
136       SalomeApp_Tools::QtCatchCorbaException( S_ex );
137     }
138     catch ( ... ) {
139     }
140   }
141 }
142
143 SUIT_SelectionFilter* SMESHGUI_MakeFull2DFrom3DOp::createFilter( const int /*theId*/ ) const
144 {
145   SMESHGUI_MakeFull2DFrom3DOp* me = (SMESHGUI_MakeFull2DFrom3DOp*) this;
146
147   QList<SUIT_SelectionFilter*> subFilters;
148   subFilters.append( & me->myMeshFilter );
149   subFilters.append( & me->myGroupFilter );
150
151   SUIT_SelectionFilter* f = new SMESH_LogicalFilter( subFilters, SMESH_LogicalFilter::LO_OR );
152   return f;
153 }
154
155 bool SMESHGUI_MakeFull2DFrom3DOp::isValid( QString& msg ) const
156 {
157   if ( !dlg() ) return false;
158   
159   // check if a mesh is selected
160   if ( !myDlg->hasSelection( SMESHGUI_MakeFull2DFrom3DDlg::MeshOrGroups ))
161   {
162     msg = tr( "SMESH_ERR_NO_INPUT_MESH" );
163     return false;
164   }
165
166   QStringList entries;
167   dlg()->selectedObject( SMESHGUI_MakeFull2DFrom3DDlg::MeshOrGroups, entries );
168   const bool isMeshSelected = ( !mySrcMesh->_is_nil() );
169   if ( isMeshSelected )
170   {
171     // only one mesh is allowed
172     if ( entries.size() > 1 ) {
173       msg = tr( "SMESH_TOO_MANY_MESHES" );
174       return false;
175     }
176   }
177   else
178   {
179     // check if only groups are selected
180     for ( int i = 0; i < entries.count(); ++i )
181     {
182       SMESH::SMESH_GroupBase_var grp;
183       if ( _PTR(SObject) sobj = SMESH::getStudy()->FindObjectID( entries[i].toUtf8().constData() ))
184         grp = SMESH::SObjectToInterface<SMESH::SMESH_GroupBase>( sobj );
185       if ( grp->_is_nil() ) {
186         msg = tr( "SMESH_NOT_ONLY_GROUPS" );
187         return false;
188       }
189     }
190   }
191   // check if the selected objects contains elements of required type
192   bool hasVolumes = false;
193   
194   for ( int i = 0; i < entries.count(); ++i )
195   {
196     SMESH::SMESH_IDSource_var idSource;
197     if ( _PTR(SObject) sobj = SMESH::getStudy()->FindObjectID( entries[i].toUtf8().constData() ))
198       idSource = SMESH::SObjectToInterface<SMESH::SMESH_IDSource>( sobj );
199     if ( !idSource->_is_nil() ) {
200       SMESH::array_of_ElementType_var types = idSource->GetTypes();
201       for ( int j = 0; j < (int) types->length(); ++j )
202         if ( types[j] == SMESH::VOLUME )
203           hasVolumes = true;
204     }
205   }
206   if ( !hasVolumes ) {
207     msg = tr( "SMESH_ERR_NO_3D_ELEMENTS" );
208     return false;
209   } 
210
211   // check if new mesh name is specified
212   if ( myDlg->needNewMesh() && myDlg->getNewMeshName().isEmpty() ) {
213     msg = tr( "SMESH_ERR_MESH_NAME_NOT_SPECIFIED" );
214     return false;
215   }
216
217   // check if group name is specified
218   if ( myDlg->needGroup() && myDlg->getGroupName().isEmpty() ) {
219     msg = tr( "SMESH_ERR_GRP_NAME_NOT_SPECIFIED" );
220     return false;
221   }
222
223   return true;
224 }
225
226 bool SMESHGUI_MakeFull2DFrom3DOp::compute2DMesh( QStringList& theEntryList )
227 {
228   SUIT_OverrideCursor wc;
229
230   bool ok = false;
231   try {
232     QString meshName          = myDlg->needNewMesh() ? myDlg->getNewMeshName() : QString();
233     QString groupName         = myDlg->needGroup()   ? myDlg->getGroupName()   : QString();
234     bool copyAll              = myDlg->copySource();
235
236     QStringList entries;
237     dlg()->selectedObject( SMESHGUI_MakeFull2DFrom3DDlg::MeshOrGroups, entries );
238     SMESH::ListOfIDSources_var groups = new SMESH::ListOfIDSources;
239     QString wrongGroups = "";
240
241     if ( mySrcMesh->_is_nil() ) // get selected groups, find groups of wrong type
242     {
243       int nbGroups = 0;      
244       groups->length( entries.count() );
245       for ( int i = 0; i < entries.count(); ++i )
246       {
247         _PTR(SObject) sobj = SMESH::getStudy()->FindObjectID( entries[i].toUtf8().constData() );
248         SMESH::SMESH_IDSource_var grp = SMESH::SObjectToInterface<SMESH::SMESH_IDSource>( sobj );  
249         SMESH::array_of_ElementType_var types = grp->GetTypes();
250         if ( types->length() < 1 || types[0] != SMESH::VOLUME )
251         {
252           if ( !wrongGroups.isEmpty() )
253             wrongGroups += ", ";
254           wrongGroups += sobj->GetName().c_str();
255         }
256         else
257         {
258           groups[ nbGroups++ ] = grp;
259         }
260       }
261       groups->length( nbGroups );
262       mySrcMesh = groups[0]->GetMesh();
263     }
264
265     if ( !CORBA::is_nil( mySrcMesh ) ) {
266       SMESH::SMESH_MeshEditor_var aMeshEditor = mySrcMesh->GetMeshEditor();
267       SMESH::SMESH_Group_var newGrp;
268       SMESH::SMESH_Mesh_var newMesh;
269       CORBA::Long nbAdded = aMeshEditor->MakeBoundaryElements( SMESH::BND_2DFROM3D,
270                                                                groupName.toUtf8().constData(),
271                                                                meshName.toUtf8().constData(),
272                                                                copyAll,
273                                                                true,
274                                                                groups,
275                                                                newMesh.out(),
276                                                                newGrp.out() );
277       QString msg = tr("NB_ADDED").arg( nbAdded );
278       if ( !wrongGroups.isEmpty() )
279         msg += ".\n" + tr("WRONG_GROUPS").arg( wrongGroups );
280       SUIT_MessageBox::information( myDlg, tr("SMESH_INFORMATION"), msg);
281
282       if ( !newMesh->_is_nil() ) {
283         if( _PTR(SObject) aSObject = SMESH::ObjectToSObject( newMesh ) )
284           theEntryList.append( aSObject->GetID().c_str() );
285       }
286       ok = true;
287
288       for ( int i = 0; i < entries.count(); ++i )
289         if ( SMESH_Actor* actor = SMESH::FindActorByEntry( entries[i].toUtf8().constData() ))
290         {
291           actor->SetEntityMode( actor->GetEntityMode() | SMESH_Actor::eFaces );
292           SMESH::Update( actor->getIO(), actor->GetVisibility() );
293         }
294       SMESH::RepaintCurrentView();
295     }
296   }
297   catch ( ... ) {
298   }
299   return ok;
300 }
301
302 bool SMESHGUI_MakeFull2DFrom3DOp::onApply()
303 {
304   if ( SMESHGUI::isStudyLocked() )
305     return false;
306
307   QString msg;
308   if ( !isValid( msg ) ) {
309     dlg()->show();
310     if ( msg != "" )
311       SUIT_MessageBox::warning( myDlg, tr( "SMESH_ERROR" ), msg );
312     return false;
313   }
314
315   QStringList anEntryList;
316   bool res = false;
317   try {
318     res = compute2DMesh( anEntryList );
319   }
320   catch ( const SALOME::SALOME_Exception& S_ex ) {
321     SalomeApp_Tools::QtCatchCorbaException( S_ex );
322   }
323   catch ( ... ) {
324   }
325
326   if ( res ) {
327     SMESHGUI::Modified();
328     update( UF_ObjBrowser | UF_Model );
329     if( LightApp_Application* anApp =
330         dynamic_cast<LightApp_Application*>( SUIT_Session::session()->activeApplication() ) )
331       anApp->browseObjects( anEntryList, isApplyAndClose() );
332     myDlg->setNewMeshName( SMESH::UniqueName( "Mesh_1" ) );
333     myDlg->setGroupName( SMESH::UniqueName( "Group" ) );
334   }
335   else {
336     SUIT_MessageBox::warning( myDlg, tr( "SMESH_ERROR" ), tr( "SMESH_OPERATION_FAILED" ) );
337   }
338
339   return res;
340 }