Salome HOME
*** empty log message ***
[modules/smesh.git] / src / SMESHGUI / SMESHGUI_AddMeshElementOp.cxx
1 //  SMESH SMESHGUI : GUI for SMESH component
2 //
3 //  Copyright (C) 2003  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.
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.opencascade.org/SALOME/ or email : webmaster.salome@opencascade.org
21 //
22 //
23 //
24 //  File   : SMESHGUI_AddMeshElementOp.cxx
25 //  Author : Alexander SOLOVYOV
26 //  Module : SMESH
27 //  $Header$
28
29 #include "SMESHGUI_AddMeshElementOp.h"
30 #include <SMESHGUI_AddMeshElementDlg.h>
31 #include <SMESHGUI.h>
32
33 #include <SalomeApp_SelectionMgr.h>
34
35 #include <SVTK_ViewWindow.h>
36 #include <SVTK_ViewModel.h>
37 #include <SVTK_Selector.h>
38 #include <SMESH_Actor.h>
39 #include <SMESH_ActorUtils.h>
40 #include <SMESHGUI_Utils.h>
41 #include <SMESHGUI_VTKUtils.h>
42 #include <SMESHGUI_MeshUtils.h>
43
44 #include <SALOME_ListIO.hxx>
45
46 #include <vtkCell.h>
47 #include <vtkDataSetMapper.h>
48 #include <vtkUnstructuredGrid.h>
49 #include <vtkIdList.h>
50
51 #include <TColStd_MapOfInteger.hxx>
52
53 #include <SMDS_Mesh.hxx>
54 #include <SMDS_MeshNode.hxx>
55
56 namespace SMESH {
57
58   class TElementSimulation {
59     SVTK_ViewWindow* myVTKViewWindow;
60     SALOME_Actor* myPreviewActor;
61     vtkDataSetMapper* myMapper;
62     vtkUnstructuredGrid* myGrid;
63
64   public:
65     TElementSimulation( SVTK_ViewWindow* wnd )
66     {
67       myVTKViewWindow = wnd;
68
69       myGrid = vtkUnstructuredGrid::New();
70
71       // Create and display actor
72       myMapper = vtkDataSetMapper::New();
73       myMapper->SetInput(myGrid);
74
75       myPreviewActor = SALOME_Actor::New();
76       myPreviewActor->PickableOff();
77       myPreviewActor->VisibilityOff();
78       myPreviewActor->SetMapper(myMapper);
79
80       float anRGB[3];
81       vtkProperty* aProp = vtkProperty::New();
82       GetColor( "SMESH", "fill_color", anRGB[0], anRGB[1], anRGB[2], QColor( 0, 170, 255 ) );
83       aProp->SetColor( anRGB[0], anRGB[1], anRGB[2] );
84       myPreviewActor->SetProperty( aProp );
85       aProp->Delete();
86
87       vtkProperty* aBackProp = vtkProperty::New();
88       GetColor( "SMESH", "backface_color", anRGB[0], anRGB[1], anRGB[2], QColor( 0, 0, 255 ) );
89       aBackProp->SetColor( anRGB[0], anRGB[1], anRGB[2] );
90       myPreviewActor->SetBackfaceProperty( aBackProp );
91       aBackProp->Delete();
92
93       myVTKViewWindow->AddActor(myPreviewActor);
94     }
95
96     typedef std::vector<vtkIdType> TVTKIds;
97     void SetPosition (SMESH_Actor* theActor,
98                       vtkIdType theType,
99                       const TVTKIds& theIds)
100     {
101       vtkUnstructuredGrid *aGrid = theActor->GetUnstructuredGrid();
102       myGrid->SetPoints(aGrid->GetPoints());
103
104       const int* aConn = NULL;
105       switch (theType) {
106       case VTK_TETRA:
107         {
108           static int anIds[] = {0,2,1,3};
109           aConn = anIds;
110           break;
111         }
112       case VTK_PYRAMID:
113         {
114           static int anIds[] = {0,3,2,1,4};
115           aConn = anIds;
116           break;
117         }
118       case VTK_HEXAHEDRON:
119         {
120           static int anIds[] = {0,3,2,1,4,7,6,5};
121           aConn = anIds;
122           break;
123         }
124       }
125
126       myGrid->Reset();
127       vtkIdList *anIds = vtkIdList::New();
128
129       if(aConn)
130         for (int i = 0, iEnd = theIds.size(); i < iEnd; i++)
131           anIds->InsertId(i,theIds[aConn[i]]);
132       else
133         for (int i = 0, iEnd = theIds.size(); i < iEnd; i++)
134           anIds->InsertId(i,theIds[i]);
135
136       myGrid->InsertNextCell(theType,anIds);
137       anIds->Delete();
138
139       myGrid->Modified();
140
141       SetVisibility(true);
142     }
143
144
145     void SetVisibility (bool theVisibility)
146     {
147       myPreviewActor->SetVisibility(theVisibility);
148       RepaintCurrentView();
149     }
150
151
152     ~TElementSimulation()
153     {
154       SetVisibility( false );
155       if( myVTKViewWindow )
156         myVTKViewWindow->RemoveActor(myPreviewActor);
157         
158       myPreviewActor->Delete();
159
160       myMapper->RemoveAllInputs();
161       myMapper->Delete();
162
163       myGrid->Delete();
164     }
165   };
166 }
167
168 //=================================================================================
169 // function : SMESHGUI_AddMeshElementDlg()
170 // purpose  : constructor
171 //=================================================================================
172 SMESHGUI_AddMeshElementOp::SMESHGUI_AddMeshElementOp( const SMDSAbs_ElementType t, const int nbNodes )
173 : SMESHGUI_SelectionOp( NodeSelection ),
174   myElementType( t ),
175   myNbNodes( nbNodes ),
176   myIsPoly( myElementType==SMDSAbs_Face && myNbNodes==5 ),
177   mySimulation( 0 ),
178   myDlg( 0 )
179 {
180 }
181
182 //=================================================================================
183 // function : ~SMESHGUI_AddMeshElementDlg()
184 // purpose  : destructor
185 //=================================================================================
186 SMESHGUI_AddMeshElementOp::~SMESHGUI_AddMeshElementOp()
187 {
188   if( myDlg )
189     delete myDlg;
190 }
191
192 //=================================================================================
193 // function : dlg()
194 // purpose  : 
195 //=================================================================================
196 SalomeApp_Dialog* SMESHGUI_AddMeshElementOp::dlg() const
197 {
198   return myDlg;
199 }
200
201 //=================================================================================
202 // function : startOperation()
203 // purpose  :
204 //=================================================================================
205 void SMESHGUI_AddMeshElementOp::startOperation()
206 {
207   if( !myDlg )
208   {
209     QString elemName;
210     switch( myNbNodes )
211     {
212       case 2: elemName = "EDGE"; break;
213       case 3: elemName = "TRIANGLE"; break;
214       case 4: if (myElementType == SMDSAbs_Face)
215                 elemName = "QUADRANGLE";
216               else
217                 elemName = "TETRAS";
218               break;
219       case 5: elemName = "POLYGON"; break;
220       case 8: elemName = "HEXAS"; break;
221     }
222     
223     myDlg = new SMESHGUI_AddMeshElementDlg( elemName, myElementType == SMDSAbs_Face );
224     connect( myDlg, SIGNAL( objectChanged( int, const QStringList& ) ),
225              this,  SLOT( onTextChanged( int, const QStringList& ) ) );
226     connect( myDlg, SIGNAL( dlgClose() ), this, SLOT( onCancel() ) );
227     connect( myDlg, SIGNAL( reverse( int ) ), this, SLOT( onReverse( int ) ) );
228   }
229
230   SMESHGUI_SelectionOp::startOperation();
231
232   mySimulation = new SMESH::TElementSimulation( viewWindow() );
233   updateDialog();
234   myDlg->show();
235 }
236
237 //=================================================================================
238 // function : selectionDone()
239 // purpose  :
240 //=================================================================================
241 void SMESHGUI_AddMeshElementOp::selectionDone()
242 {
243   if( !mySimulation )
244     return;
245     
246   mySimulation->SetVisibility(false);
247
248   // get selected mesh
249   SALOME_ListIO aList;
250   selectionMgr()->selectedObjects(aList,SVTK_Viewer::Type());
251
252   if( aList.Extent() != 1)
253     return;
254
255   Handle(SALOME_InteractiveObject) anIO = aList.First();
256   myMesh = SMESH::GetMeshByIO(anIO);
257
258   QStringList names, ids; SalomeApp_Dialog::TypesList types;
259   selected( names, types, ids );
260   myDlg->selectObject( names, types, ids );
261
262   updateDialog();
263   displaySimulation();
264 }
265
266 //=================================================================================
267 // function : commitOperation()
268 // purpose  :
269 //=================================================================================
270 void SMESHGUI_AddMeshElementOp::commitOperation()
271 {
272   if( mySimulation )
273     delete mySimulation;
274   mySimulation = 0;
275   SMESHGUI_SelectionOp::commitOperation();
276 }
277
278 //=================================================================================
279 // function : abortOperation()
280 // purpose  :
281 //=================================================================================
282 void SMESHGUI_AddMeshElementOp::abortOperation()
283 {
284   if( mySimulation )
285     delete mySimulation;
286   mySimulation = 0;
287   SMESHGUI_SelectionOp::abortOperation();
288 }
289
290 //=================================================================================
291 // function : onApply()
292 // purpose  :
293 //=================================================================================
294 bool SMESHGUI_AddMeshElementOp::onApply()
295 {
296   if( !mySimulation )
297     return false;
298
299   QStringList ids; myDlg->selectedObject( 0, ids );
300   if( ids.count()>=myNbNodes && !getSMESHGUI()->isActiveStudyLocked() ) {
301     //myBusy = true;
302     SMESH::long_array_var anArrayOfIdeces = new SMESH::long_array;
303     anArrayOfIdeces->length(myNbNodes);
304     bool reverse = myDlg->isReverse();
305     
306     for (int i = 0; i < myNbNodes; i++)
307     {
308       QString id_str = ids[ i ];
309       int pos = id_str.find( idChar() );
310       int id = -1;
311       if( pos>=0 )
312         id = id_str.mid( pos+1 ).toInt();
313
314       if( id==-1 )
315       {
316         printf( "SMESHGUI_AddMeshElementOp::onApply(): Error!!!\n" );
317         return false;
318       }
319       
320       if (reverse)
321         anArrayOfIdeces[ myNbNodes - i - 1 ] = id;
322       else
323         anArrayOfIdeces[i] = id;
324     }
325
326     SMESH::SMESH_MeshEditor_var aMeshEditor = myMesh->GetMeshEditor();
327     switch (myElementType) {
328     case SMDSAbs_Edge:
329       aMeshEditor->AddEdge(anArrayOfIdeces.inout()); break;
330     case SMDSAbs_Face:
331       aMeshEditor->AddFace(anArrayOfIdeces.inout()); break;
332     case SMDSAbs_Volume:
333       aMeshEditor->AddVolume(anArrayOfIdeces.inout()); break;
334     default:;
335     }
336
337     //SALOME_ListIO aList; aList.Append( myActor->getIO() );
338     //mySelectionMgr->setSelectedObjects( aList, false );
339
340     SMESH::UpdateView();
341     mySimulation->SetVisibility(false);
342
343     initDialog();
344     updateDialog();
345
346     return true;
347   }
348   return false;
349 }
350
351 //=================================================================================
352 // function : onTextChanged()
353 // purpose  :
354 //=================================================================================
355 void SMESHGUI_AddMeshElementOp::onTextChanged( int, const QStringList& aListId )
356 {
357     myDlg->setBusy( true );
358     TColStd_MapOfInteger newIndices;
359     SALOME_ListIO list; selectionMgr()->selectedObjects( list );
360     if( list.Extent()==0 )
361       return;
362
363     SMESH_Actor* anActor = SMESH::FindActorByObject( myMesh.in() );
364     if( !anActor )
365       return;
366       
367     SMDS_Mesh* aMesh = anActor->GetObject()->GetMesh();
368
369     for (int i = 0; i < aListId.count(); i++)
370       if( const SMDS_MeshNode * n = aMesh->FindNode( aListId[ i ].toInt() ) )
371         newIndices.Add( n->GetID() );
372
373     selector()->AddOrRemoveIndex( list.First(), newIndices, false );
374     highlight( list.First(), true, true );
375
376     selectionDone();
377     myDlg->setBusy( false );
378 }
379
380 //=================================================================================
381 // function : displaySimulation()
382 // purpose  :
383 //=================================================================================
384 void SMESHGUI_AddMeshElementOp::displaySimulation()
385 {
386   QStringList ids; myDlg->selectedObject( 0, ids );
387   if( ids.count()>=myNbNodes ) {
388     SMESH::TElementSimulation::TVTKIds anIds;
389
390     SMESH_Actor* anActor = SMESH::FindActorByObject( myMesh.in() );
391     if( !anActor )
392       return;
393     
394     for (int i = 0; i < myNbNodes; i++)
395     {
396       QString id_str = ids[ i ];
397       int pos = id_str.find( idChar() );
398       int id = -1;
399       if( pos>=0 )
400         id = id_str.mid( pos+1 ).toInt();
401
402       if( id==-1 )
403       {
404         printf( "SMESHGUI_AddMeshElementOp::displaySimulation(): Error!!!\n" );
405         return;
406       }
407       
408       anIds.push_back( anActor->GetObject()->GetNodeVTKId( id ) );
409     }
410
411     if( myDlg->isReverse() )
412       reverse( anIds.begin(), anIds.end() );
413
414     vtkIdType aType = 0;
415     if (myIsPoly)
416       switch ( myElementType ) {
417       case SMDSAbs_Face  : aType = VTK_POLYGON; break;
418       default: return;
419       }
420     else {
421       switch (myNbNodes) {
422       case 2: aType = VTK_LINE; break;
423       case 3: aType = VTK_TRIANGLE; break;
424       case 4: aType = myElementType == SMDSAbs_Face ? VTK_QUAD : VTK_TETRA; break;
425       case 8: aType = VTK_HEXAHEDRON; break;
426       default: return;
427       }
428     }
429
430     mySimulation->SetPosition( anActor, aType, anIds );
431     SMESH::UpdateView();
432   }  
433 }
434
435 //=================================================================================
436 // function : onReverse()
437 // purpose  :
438 //=================================================================================
439 void SMESHGUI_AddMeshElementOp::onReverse( int )
440 {
441   if( mySimulation )
442   {
443     mySimulation->SetVisibility( false );
444     displaySimulation();
445   }
446 }
447
448 //=================================================================================
449 // function : updateDialog()
450 // purpose  :
451 //=================================================================================
452 void SMESHGUI_AddMeshElementOp::updateDialog()
453 {
454   if( myDlg )
455   {
456     QStringList ids; myDlg->selectedObject( 0, ids );
457     myDlg->setButtonEnabled( ids.count()>=myNbNodes, QtxDialog::OK | QtxDialog::Apply );
458   }
459 }