Salome HOME
Changes for working with quadratic elements
[modules/smesh.git] / src / OBJECT / SMESH_Object.cxx
1 //  SMESH OBJECT : interactive object for SMESH visualization
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   : SMESH_Grid.cxx
25 //  Author : Nicolas REJNERI
26 //  Module : SMESH
27
28 #include "SMESH_ObjectDef.h"
29 #include "SMESH_ActorUtils.h"
30
31 #include "SMDS_Mesh.hxx"
32 #include "SMESH_Actor.h"
33 #include "SMESH_ControlsDef.hxx"
34 #include <VTKViewer_ExtractUnstructuredGrid.h>
35
36 #include CORBA_SERVER_HEADER(SALOME_Exception)
37
38 #include <vtkCell.h>
39 #include <vtkIdList.h>
40 #include <vtkIntArray.h>
41 #include <vtkCellArray.h>
42 #include <vtkUnsignedCharArray.h>
43
44 #include <vtkUnstructuredGrid.h>
45
46 #include <memory>
47 #include <sstream>      
48 #include <stdexcept>
49 #include <set>
50
51 #include "utilities.h"
52
53 using namespace std;
54
55 #ifndef EXCEPTION
56 #define EXCEPTION(TYPE, MSG) {\
57   std::ostringstream aStream;\
58   aStream<<__FILE__<<"["<<__LINE__<<"]::"<<MSG;\
59   throw TYPE(aStream.str());\
60 }
61 #endif
62
63 #ifdef _DEBUG_
64 static int MYDEBUG = 0;
65 static int MYDEBUGWITHFILES = 0;
66 #else
67 static int MYDEBUG = 0;
68 static int MYDEBUGWITHFILES = 0;
69 #endif
70
71
72 namespace{
73
74   //=======================================================================
75   //function : FindNode
76   //=======================================================================
77   inline const SMDS_MeshNode* FindNode(const SMDS_Mesh* theMesh, int theId){
78     if(const SMDS_MeshNode* anElem = theMesh->FindNode(theId)) return anElem;
79     EXCEPTION(runtime_error,"SMDS_Mesh::FindNode - cannot find a SMDS_MeshNode for ID = "<<theId);
80   }
81
82
83   //=======================================================================
84   //function : FindElement
85   //=======================================================================
86   inline const SMDS_MeshElement* FindElement(const SMDS_Mesh* theMesh, int theId){
87     if(const SMDS_MeshElement* anElem = theMesh->FindElement(theId)) return anElem;
88     EXCEPTION(runtime_error,"SMDS_Mesh::FindElement - cannot find a SMDS_MeshElement for ID = "<<theId);
89   }
90
91
92   //=======================================================================
93   //function : AddNodesWithID
94   //=======================================================================
95   inline void AddNodesWithID(SMDS_Mesh* theMesh, 
96                              SMESH::log_array_var& theSeq,
97                              CORBA::Long theId)
98   {
99     const SMESH::double_array& aCoords = theSeq[theId].coords;
100     const SMESH::long_array& anIndexes = theSeq[theId].indexes;
101     CORBA::Long anElemId = 0, aNbElems = theSeq[theId].number;
102     if(3*aNbElems != aCoords.length())
103       EXCEPTION(runtime_error,"AddNodesWithID - 3*aNbElems != aCoords.length()");
104     for(CORBA::Long aCoordId = 0; anElemId < aNbElems; anElemId++, aCoordId+=3){
105       SMDS_MeshElement* anElem = theMesh->AddNodeWithID(aCoords[aCoordId],
106                                                         aCoords[aCoordId+1],
107                                                         aCoords[aCoordId+2],
108                                                         anIndexes[anElemId]);
109       if(!anElem)
110         EXCEPTION(runtime_error,"SMDS_Mesh::FindElement - cannot AddNodeWithID for ID = "<<anElemId);
111     }
112   }
113
114
115   //=======================================================================
116   //function : AddEdgesWithID
117   //=======================================================================
118   inline void AddEdgesWithID(SMDS_Mesh* theMesh, 
119                              SMESH::log_array_var& theSeq,
120                              CORBA::Long theId)
121   {
122     const SMESH::long_array& anIndexes = theSeq[theId].indexes;
123     CORBA::Long anElemId = 0, aNbElems = theSeq[theId].number;
124     if(3*aNbElems != anIndexes.length())
125       EXCEPTION(runtime_error,"AddEdgeWithID - 3*aNbElems != aCoords.length()");
126     for(CORBA::Long anIndexId = 0; anElemId < aNbElems; anElemId++, anIndexId+=3){
127       SMDS_MeshElement* anElem = theMesh->AddEdgeWithID(anIndexes[anIndexId+1],
128                                                         anIndexes[anIndexId+2],
129                                                         anIndexes[anIndexId]);
130       if(!anElem)
131         EXCEPTION(runtime_error,"SMDS_Mesh::FindElement - cannot AddEdgeWithID for ID = "<<anElemId);
132     }
133   }
134
135
136   //=======================================================================
137   //function : AddTriasWithID
138   //=======================================================================
139   inline void AddTriasWithID(SMDS_Mesh* theMesh, 
140                              SMESH::log_array_var& theSeq,
141                              CORBA::Long theId)
142   {
143     const SMESH::long_array& anIndexes = theSeq[theId].indexes;
144     CORBA::Long anElemId = 0, aNbElems = theSeq[theId].number;
145     if(4*aNbElems != anIndexes.length())
146       EXCEPTION(runtime_error,"AddTriasWithID - 4*aNbElems != anIndexes.length()");
147     for(CORBA::Long anIndexId = 0; anElemId < aNbElems; anElemId++, anIndexId+=4){
148       SMDS_MeshElement* anElem = theMesh->AddFaceWithID(anIndexes[anIndexId+1],
149                                                         anIndexes[anIndexId+2],
150                                                         anIndexes[anIndexId+3],
151                                                         anIndexes[anIndexId]);
152       if(!anElem)
153         EXCEPTION(runtime_error,"SMDS_Mesh::FindElement - cannot AddFaceWithID for ID = "<<anElemId);
154     }
155   }
156
157
158   //=======================================================================
159   //function : AddQuadsWithID
160   //=======================================================================
161   inline void AddQuadsWithID(SMDS_Mesh* theMesh, 
162                              SMESH::log_array_var theSeq,
163                              CORBA::Long theId)
164   {
165     const SMESH::long_array& anIndexes = theSeq[theId].indexes;
166     CORBA::Long anElemId = 0, aNbElems = theSeq[theId].number;
167     if(5*aNbElems != anIndexes.length())
168       EXCEPTION(runtime_error,"AddQuadsWithID - 4*aNbElems != anIndexes.length()");
169     for(CORBA::Long anIndexId = 0; anElemId < aNbElems; anElemId++, anIndexId+=5){
170       SMDS_MeshElement* anElem = theMesh->AddFaceWithID(anIndexes[anIndexId+1],
171                                                         anIndexes[anIndexId+2],
172                                                         anIndexes[anIndexId+3],
173                                                         anIndexes[anIndexId+4],
174                                                         anIndexes[anIndexId]);
175       if(!anElem)
176         EXCEPTION(runtime_error,"SMDS_Mesh::FindElement - cannot AddFaceWithID for ID = "<<anElemId);
177     }
178   }
179
180
181   //=======================================================================
182   //function : AddPolygonsWithID
183   //=======================================================================
184   inline void AddPolygonsWithID(SMDS_Mesh* theMesh, 
185                                 SMESH::log_array_var& theSeq,
186                                 CORBA::Long theId)
187   {
188     const SMESH::long_array& anIndexes = theSeq[theId].indexes;
189     CORBA::Long anIndexId = 0, aNbElems = theSeq[theId].number;
190
191     for (CORBA::Long anElemId = 0; anElemId < aNbElems; anElemId++) {
192       int aFaceId = anIndexes[anIndexId++];
193
194       int aNbNodes = anIndexes[anIndexId++];
195       std::vector<int> nodes_ids (aNbNodes);
196       for (int i = 0; i < aNbNodes; i++) {
197         nodes_ids[i] = anIndexes[anIndexId++];
198       }
199
200       SMDS_MeshElement* anElem = theMesh->AddPolygonalFaceWithID(nodes_ids, aFaceId);
201       if (!anElem)
202         EXCEPTION(runtime_error, "SMDS_Mesh::FindElement - cannot AddPolygonalFaceWithID for ID = "
203                   << anElemId);
204     }
205   }
206
207
208   //=======================================================================
209   //function : AddTetrasWithID
210   //=======================================================================
211   inline void AddTetrasWithID(SMDS_Mesh* theMesh, 
212                               SMESH::log_array_var& theSeq,
213                               CORBA::Long theId)
214   {
215     const SMESH::long_array& anIndexes = theSeq[theId].indexes;
216     CORBA::Long anElemId = 0, aNbElems = theSeq[theId].number;
217     if(5*aNbElems != anIndexes.length())
218       EXCEPTION(runtime_error,"AddTetrasWithID - 5*aNbElems != anIndexes.length()");
219     for(CORBA::Long anIndexId = 0; anElemId < aNbElems; anElemId++, anIndexId+=5){
220       SMDS_MeshElement* anElem = theMesh->AddVolumeWithID(anIndexes[anIndexId+1],
221                                                           anIndexes[anIndexId+2],
222                                                           anIndexes[anIndexId+3],
223                                                           anIndexes[anIndexId+4],
224                                                           anIndexes[anIndexId]);
225       if(!anElem)
226         EXCEPTION(runtime_error,"SMDS_Mesh::FindElement - cannot AddVolumeWithID for ID = "<<anElemId);
227     }
228   }
229
230
231   //=======================================================================
232   //function : AddPiramidsWithID
233   //=======================================================================
234   inline void AddPiramidsWithID(SMDS_Mesh* theMesh, 
235                                 SMESH::log_array_var& theSeq,
236                                 CORBA::Long theId)
237   {
238     const SMESH::long_array& anIndexes = theSeq[theId].indexes;
239     CORBA::Long anElemId = 0, aNbElems = theSeq[theId].number;
240     if(6*aNbElems != anIndexes.length())
241       EXCEPTION(runtime_error,"AddPiramidsWithID - 6*aNbElems != anIndexes.length()");
242     for(CORBA::Long anIndexId = 0; anElemId < aNbElems; anElemId++, anIndexId+=6){
243       SMDS_MeshElement* anElem = theMesh->AddVolumeWithID(anIndexes[anIndexId+1],
244                                                           anIndexes[anIndexId+2],
245                                                           anIndexes[anIndexId+3],
246                                                           anIndexes[anIndexId+4],
247                                                           anIndexes[anIndexId+5],
248                                                           anIndexes[anIndexId]);
249       if(!anElem)
250         EXCEPTION(runtime_error,"SMDS_Mesh::FindElement - cannot AddVolumeWithID for ID = "<<anElemId);
251     }
252   }
253
254
255   //=======================================================================
256   //function : AddPrismsWithID
257   //=======================================================================
258   inline void AddPrismsWithID(SMDS_Mesh* theMesh, 
259                               SMESH::log_array_var& theSeq,
260                               CORBA::Long theId)
261   {
262     const SMESH::long_array& anIndexes = theSeq[theId].indexes;
263     CORBA::Long anElemId = 0, aNbElems = theSeq[theId].number;
264     if(7*aNbElems != anIndexes.length())
265       EXCEPTION(runtime_error,"AddPrismsWithID - 7*aNbElems != anIndexes.length()");
266     for(CORBA::Long anIndexId = 0; anElemId < aNbElems; anElemId++, anIndexId+=7){
267       SMDS_MeshElement* anElem = theMesh->AddVolumeWithID(anIndexes[anIndexId+1],
268                                                           anIndexes[anIndexId+2],
269                                                           anIndexes[anIndexId+3],
270                                                           anIndexes[anIndexId+4],
271                                                           anIndexes[anIndexId+5],
272                                                           anIndexes[anIndexId+6],
273                                                           anIndexes[anIndexId]);
274       if(!anElem)
275         EXCEPTION(runtime_error,"SMDS_Mesh::FindElement - cannot AddVolumeWithID for ID = "<<anElemId);
276     }
277   }
278
279
280   //=======================================================================
281   //function : AddHexasWithID
282   //=======================================================================
283   inline void AddHexasWithID(SMDS_Mesh* theMesh, 
284                              SMESH::log_array_var& theSeq,
285                              CORBA::Long theId)
286   {
287     const SMESH::long_array& anIndexes = theSeq[theId].indexes;
288     CORBA::Long anElemId = 0, aNbElems = theSeq[theId].number;
289     if(9*aNbElems != anIndexes.length())
290       EXCEPTION(runtime_error,"AddHexasWithID - 9*aNbElems != anIndexes.length()");
291     for(CORBA::Long anIndexId = 0; anElemId < aNbElems; anElemId++, anIndexId+=9){
292       SMDS_MeshElement* anElem = theMesh->AddVolumeWithID(anIndexes[anIndexId+1],
293                                                           anIndexes[anIndexId+2],
294                                                           anIndexes[anIndexId+3],
295                                                           anIndexes[anIndexId+4],
296                                                           anIndexes[anIndexId+5],
297                                                           anIndexes[anIndexId+6],
298                                                           anIndexes[anIndexId+7],
299                                                           anIndexes[anIndexId+8],
300                                                           anIndexes[anIndexId]);
301       if(!anElem)
302         EXCEPTION(runtime_error,"SMDS_Mesh::FindElement - cannot AddVolumeWithID for ID = "<<anElemId);
303     }
304   }
305
306
307   //=======================================================================
308   //function : AddPolyhedronsWithID
309   //=======================================================================
310   inline void AddPolyhedronsWithID (SMDS_Mesh* theMesh, 
311                                     SMESH::log_array_var& theSeq,
312                                     CORBA::Long theId)
313   {
314     const SMESH::long_array& anIndexes = theSeq[theId].indexes;
315     CORBA::Long anIndexId = 0, aNbElems = theSeq[theId].number;
316
317     for (CORBA::Long anElemId = 0; anElemId < aNbElems; anElemId++) {
318       int aFaceId = anIndexes[anIndexId++];
319
320       int aNbNodes = anIndexes[anIndexId++];
321       std::vector<int> nodes_ids (aNbNodes);
322       for (int i = 0; i < aNbNodes; i++) {
323         nodes_ids[i] = anIndexes[anIndexId++];
324       }
325
326       int aNbFaces = anIndexes[anIndexId++];
327       std::vector<int> quantities (aNbFaces);
328       for (int i = 0; i < aNbFaces; i++) {
329         quantities[i] = anIndexes[anIndexId++];
330       }
331
332       SMDS_MeshElement* anElem =
333         theMesh->AddPolyhedralVolumeWithID(nodes_ids, quantities, aFaceId);
334       if (!anElem)
335         EXCEPTION(runtime_error, "SMDS_Mesh::FindElement - cannot AddPolyhedralVolumeWithID for ID = "
336                   << anElemId);
337     }
338   }
339
340
341   //=======================================================================
342   //function : AddQuadEdgesWithID
343   //=======================================================================
344   inline void AddQuadEdgesWithID(SMDS_Mesh* theMesh, 
345                                  SMESH::log_array_var& theSeq,
346                                  CORBA::Long theId)
347   {
348     const SMESH::long_array& anIndexes = theSeq[theId].indexes;
349     CORBA::Long anElemId = 0, aNbElems = theSeq[theId].number;
350     if(4*aNbElems != anIndexes.length())
351       EXCEPTION(runtime_error,"AddQuadEdgeWithID - 4*aNbElems != aCoords.length()");
352     for(CORBA::Long anIndexId = 0; anElemId < aNbElems; anElemId++, anIndexId+=4){
353       SMDS_MeshElement* anElem = theMesh->AddEdgeWithID(anIndexes[anIndexId+1],
354                                                         anIndexes[anIndexId+2],
355                                                         anIndexes[anIndexId+3],
356                                                         anIndexes[anIndexId]);
357       if(!anElem)
358         EXCEPTION(runtime_error,"SMDS_Mesh::FindElement - cannot AddEdgeWithID for ID = "<<anElemId);
359     }
360   }
361
362
363   //=======================================================================
364   //function : AddQuadTriasWithID
365   //=======================================================================
366   inline void AddQuadTriasWithID(SMDS_Mesh* theMesh, 
367                                  SMESH::log_array_var& theSeq,
368                                  CORBA::Long theId)
369   {
370     const SMESH::long_array& anIndexes = theSeq[theId].indexes;
371     CORBA::Long anElemId = 0, aNbElems = theSeq[theId].number;
372     if(7*aNbElems != anIndexes.length())
373       EXCEPTION(runtime_error,"AddQuadTriasWithID - 7*aNbElems != anIndexes.length()");
374     for(CORBA::Long anIndexId = 0; anElemId < aNbElems; anElemId++, anIndexId+=7){
375       SMDS_MeshElement* anElem = theMesh->AddFaceWithID(anIndexes[anIndexId+1],
376                                                         anIndexes[anIndexId+2],
377                                                         anIndexes[anIndexId+3],
378                                                         anIndexes[anIndexId+4],
379                                                         anIndexes[anIndexId+5],
380                                                         anIndexes[anIndexId+6],
381                                                         anIndexes[anIndexId]);
382       if(!anElem)
383         EXCEPTION(runtime_error,"SMDS_Mesh::FindElement - cannot AddFaceWithID for ID = "<<anElemId);
384     }
385   }
386
387
388   //=======================================================================
389   //function : AddQuadQuadsWithID
390   //=======================================================================
391   inline void AddQuadQuadsWithID(SMDS_Mesh* theMesh, 
392                                  SMESH::log_array_var theSeq,
393                                  CORBA::Long theId)
394   {
395     const SMESH::long_array& anIndexes = theSeq[theId].indexes;
396     CORBA::Long anElemId = 0, aNbElems = theSeq[theId].number;
397     if(9*aNbElems != anIndexes.length())
398       EXCEPTION(runtime_error,"AddQuadQuadsWithID - 9*aNbElems != anIndexes.length()");
399     for(CORBA::Long anIndexId = 0; anElemId < aNbElems; anElemId++, anIndexId+=9){
400       SMDS_MeshElement* anElem = theMesh->AddFaceWithID(anIndexes[anIndexId+1],
401                                                         anIndexes[anIndexId+2],
402                                                         anIndexes[anIndexId+3],
403                                                         anIndexes[anIndexId+4],
404                                                         anIndexes[anIndexId+5],
405                                                         anIndexes[anIndexId+6],
406                                                         anIndexes[anIndexId+7],
407                                                         anIndexes[anIndexId+8],
408                                                         anIndexes[anIndexId]);
409       if(!anElem)
410         EXCEPTION(runtime_error,"SMDS_Mesh::FindElement - cannot AddFaceWithID for ID = "<<anElemId);
411     }
412   }
413
414
415   //=======================================================================
416   //function : AddQuadTetrasWithID
417   //=======================================================================
418   inline void AddQuadTetrasWithID(SMDS_Mesh* theMesh, 
419                                   SMESH::log_array_var& theSeq,
420                                   CORBA::Long theId)
421   {
422     const SMESH::long_array& anIndexes = theSeq[theId].indexes;
423     CORBA::Long anElemId = 0, aNbElems = theSeq[theId].number;
424     if(11*aNbElems != anIndexes.length())
425       EXCEPTION(runtime_error,"AddQuadTetrasWithID - 11*aNbElems != anIndexes.length()");
426     for(CORBA::Long anIndexId = 0; anElemId < aNbElems; anElemId++, anIndexId+=11){
427       SMDS_MeshElement* anElem = theMesh->AddVolumeWithID(anIndexes[anIndexId+1],
428                                                           anIndexes[anIndexId+2],
429                                                           anIndexes[anIndexId+3],
430                                                           anIndexes[anIndexId+4],
431                                                           anIndexes[anIndexId+5],
432                                                           anIndexes[anIndexId+6],
433                                                           anIndexes[anIndexId+7],
434                                                           anIndexes[anIndexId+8],
435                                                           anIndexes[anIndexId+9],
436                                                           anIndexes[anIndexId+10],
437                                                           anIndexes[anIndexId]);
438       if(!anElem)
439         EXCEPTION(runtime_error,"SMDS_Mesh::FindElement - cannot AddVolumeWithID for ID = "<<anElemId);
440     }
441   }
442
443
444   //=======================================================================
445   //function : AddQuadPiramidsWithID
446   //=======================================================================
447   inline void AddQuadPiramidsWithID(SMDS_Mesh* theMesh, 
448                                     SMESH::log_array_var& theSeq,
449                                     CORBA::Long theId)
450   {
451     const SMESH::long_array& anIndexes = theSeq[theId].indexes;
452     CORBA::Long anElemId = 0, aNbElems = theSeq[theId].number;
453     if(14*aNbElems != anIndexes.length())
454       EXCEPTION(runtime_error,"AddQuadPiramidsWithID - 14*aNbElems != anIndexes.length()");
455     for(CORBA::Long anIndexId = 0; anElemId < aNbElems; anElemId++, anIndexId+=14){
456       SMDS_MeshElement* anElem = theMesh->AddVolumeWithID(anIndexes[anIndexId+1],
457                                                           anIndexes[anIndexId+2],
458                                                           anIndexes[anIndexId+3],
459                                                           anIndexes[anIndexId+4],
460                                                           anIndexes[anIndexId+5],
461                                                           anIndexes[anIndexId+6],
462                                                           anIndexes[anIndexId+7],
463                                                           anIndexes[anIndexId+8],
464                                                           anIndexes[anIndexId+9],
465                                                           anIndexes[anIndexId+10],
466                                                           anIndexes[anIndexId+11],
467                                                           anIndexes[anIndexId+12],
468                                                           anIndexes[anIndexId+13],
469                                                           anIndexes[anIndexId]);
470       if(!anElem)
471         EXCEPTION(runtime_error,"SMDS_Mesh::FindElement - cannot AddVolumeWithID for ID = "<<anElemId);
472     }
473   }
474
475
476   //=======================================================================
477   //function : AddQuadPentasWithID
478   //=======================================================================
479   inline void AddQuadPentasWithID(SMDS_Mesh* theMesh, 
480                                   SMESH::log_array_var& theSeq,
481                                   CORBA::Long theId)
482   {
483     const SMESH::long_array& anIndexes = theSeq[theId].indexes;
484     CORBA::Long anElemId = 0, aNbElems = theSeq[theId].number;
485     if(16*aNbElems != anIndexes.length())
486       EXCEPTION(runtime_error,"AddQuadPentasWithID - 16*aNbElems != anIndexes.length()");
487     for(CORBA::Long anIndexId = 0; anElemId < aNbElems; anElemId++, anIndexId+=16){
488       SMDS_MeshElement* anElem = theMesh->AddVolumeWithID(anIndexes[anIndexId+1],
489                                                           anIndexes[anIndexId+2],
490                                                           anIndexes[anIndexId+3],
491                                                           anIndexes[anIndexId+4],
492                                                           anIndexes[anIndexId+5],
493                                                           anIndexes[anIndexId+6],
494                                                           anIndexes[anIndexId+7],
495                                                           anIndexes[anIndexId+8],
496                                                           anIndexes[anIndexId+9],
497                                                           anIndexes[anIndexId+10],
498                                                           anIndexes[anIndexId+11],
499                                                           anIndexes[anIndexId+12],
500                                                           anIndexes[anIndexId+13],
501                                                           anIndexes[anIndexId+14],
502                                                           anIndexes[anIndexId+15],
503                                                           anIndexes[anIndexId]);
504       if(!anElem)
505         EXCEPTION(runtime_error,"SMDS_Mesh::FindElement - cannot AddVolumeWithID for ID = "<<anElemId);
506     }
507   }
508
509
510   //=======================================================================
511   //function : AddQuadHexasWithID
512   //=======================================================================
513   inline void AddQuadHexasWithID(SMDS_Mesh* theMesh, 
514                                  SMESH::log_array_var& theSeq,
515                                  CORBA::Long theId)
516   {
517     const SMESH::long_array& anIndexes = theSeq[theId].indexes;
518     CORBA::Long anElemId = 0, aNbElems = theSeq[theId].number;
519     if(21*aNbElems != anIndexes.length())
520       EXCEPTION(runtime_error,"AddQuadHexasWithID - 21*aNbElems != anIndexes.length()");
521     for(CORBA::Long anIndexId = 0; anElemId < aNbElems; anElemId++, anIndexId+=21){
522       SMDS_MeshElement* anElem = theMesh->AddVolumeWithID(anIndexes[anIndexId+1],
523                                                           anIndexes[anIndexId+2],
524                                                           anIndexes[anIndexId+3],
525                                                           anIndexes[anIndexId+4],
526                                                           anIndexes[anIndexId+5],
527                                                           anIndexes[anIndexId+6],
528                                                           anIndexes[anIndexId+7],
529                                                           anIndexes[anIndexId+8],
530                                                           anIndexes[anIndexId+9],
531                                                           anIndexes[anIndexId+10],
532                                                           anIndexes[anIndexId+11],
533                                                           anIndexes[anIndexId+12],
534                                                           anIndexes[anIndexId+13],
535                                                           anIndexes[anIndexId+14],
536                                                           anIndexes[anIndexId+15],
537                                                           anIndexes[anIndexId+16],
538                                                           anIndexes[anIndexId+17],
539                                                           anIndexes[anIndexId+18],
540                                                           anIndexes[anIndexId+19],
541                                                           anIndexes[anIndexId+20],
542                                                           anIndexes[anIndexId]);
543       if(!anElem)
544         EXCEPTION(runtime_error,"SMDS_Mesh::FindElement - cannot AddVolumeWithID for ID = "<<anElemId);
545     }
546   }
547
548
549   //=======================================================================
550   //function : ChangePolyhedronNodes
551   //=======================================================================
552   inline void ChangePolyhedronNodes (SMDS_Mesh* theMesh, 
553                                      SMESH::log_array_var& theSeq,
554                                      CORBA::Long theId)
555   {
556     const SMESH::long_array& anIndexes = theSeq[theId].indexes;
557     CORBA::Long iind = 0, aNbElems = theSeq[theId].number;
558
559     for (CORBA::Long anElemId = 0; anElemId < aNbElems; anElemId++)
560     {
561       // find element
562       const SMDS_MeshElement* elem = FindElement(theMesh, anIndexes[iind++]);
563       // nb nodes
564       int nbNodes = anIndexes[iind++];
565       // nodes
566       std::vector<const SMDS_MeshNode*> aNodes (nbNodes);
567       for (int iNode = 0; iNode < nbNodes; iNode++) {
568         aNodes[iNode] = FindNode(theMesh, anIndexes[iind++]);
569       }
570       // nb faces
571       int nbFaces = anIndexes[iind++];
572       // quantities
573       std::vector<int> quantities (nbFaces);
574       for (int iFace = 0; iFace < nbFaces; iFace++) {
575         quantities[iFace] = anIndexes[iind++];
576       }
577       // change
578       theMesh->ChangePolyhedronNodes(elem, aNodes, quantities);
579     }
580   }
581
582
583 }
584 /*
585   Class       : SMESH_VisualObjDef
586   Description : Base class for all mesh objects to be visuilised
587 */
588
589 //=================================================================================
590 // function : getCellType
591 // purpose  : Get type of VTK cell
592 //=================================================================================
593 static inline vtkIdType getCellType( const SMDSAbs_ElementType theType,
594                                      const bool thePoly,
595                                      const int theNbNodes )
596 {
597   switch( theType )
598   {
599     case SMDSAbs_Edge: 
600       if( theNbNodes == 2 )         return VTK_LINE;
601       else if ( theNbNodes == 3 )   return VTK_QUADRATIC_EDGE;
602       else return VTK_EMPTY_CELL;
603
604     case SMDSAbs_Face  :
605       if (thePoly && theNbNodes>2 ) return VTK_POLYGON;
606       else if ( theNbNodes == 3 )   return VTK_TRIANGLE;
607       else if ( theNbNodes == 4 )   return VTK_QUAD;
608       else if ( theNbNodes == 6 )   return VTK_QUADRATIC_TRIANGLE;
609       else if ( theNbNodes == 8 )   return VTK_QUADRATIC_QUAD;
610       else return VTK_EMPTY_CELL;
611       
612     case SMDSAbs_Volume:
613       if (thePoly && theNbNodes>3 ) return VTK_CONVEX_POINT_SET;
614       else if ( theNbNodes == 4 )   return VTK_TETRA;
615       else if ( theNbNodes == 5 )   return VTK_PYRAMID;
616       else if ( theNbNodes == 6 )   return VTK_WEDGE;
617       else if ( theNbNodes == 8 )   return VTK_HEXAHEDRON;
618       else if ( theNbNodes == 10 )  {
619         cout<<"QUADRATIC_TETRA"<<endl;
620         return VTK_QUADRATIC_TETRA;
621       }
622       else if ( theNbNodes == 20 )  {
623         cout<<"QUADRATIC_HEXAHEDRON"<<endl;
624         return VTK_QUADRATIC_HEXAHEDRON;
625       }
626       else if ( theNbNodes==13 || theNbNodes==15 )  {
627         cout<<"QUADRATIC - CONVEX_POINT_SET"<<endl;
628         return VTK_CONVEX_POINT_SET;
629       }
630       else return VTK_EMPTY_CELL;
631
632     default: return VTK_EMPTY_CELL;
633   }
634 }
635
636 //=================================================================================
637 // functions : SMESH_VisualObjDef
638 // purpose   : Constructor
639 //=================================================================================
640 SMESH_VisualObjDef::SMESH_VisualObjDef()
641 {
642   myGrid = vtkUnstructuredGrid::New();
643 }
644 SMESH_VisualObjDef::~SMESH_VisualObjDef()
645 {
646   if ( MYDEBUG )
647     MESSAGE( "~SMESH_MeshObj - myGrid->GetReferenceCount() = " << myGrid->GetReferenceCount() );
648   myGrid->Delete();
649 }
650
651 //=================================================================================
652 // functions : GetNodeObjId, GetNodeVTKId, GetElemObjId, GetElemVTKId
653 // purpose   : Methods for retrieving VTK IDs by SMDS IDs and  vice versa
654 //=================================================================================
655 vtkIdType SMESH_VisualObjDef::GetNodeObjId( int theVTKID )
656 {
657   return myVTK2SMDSNodes.find(theVTKID) == myVTK2SMDSNodes.end() ? -1 : myVTK2SMDSNodes[theVTKID];
658 }
659
660 vtkIdType SMESH_VisualObjDef::GetNodeVTKId( int theObjID )
661 {
662   return mySMDS2VTKNodes.find(theObjID) == mySMDS2VTKNodes.end() ? -1 : mySMDS2VTKNodes[theObjID];
663 }
664
665 vtkIdType SMESH_VisualObjDef::GetElemObjId( int theVTKID )
666 {
667   return myVTK2SMDSElems.find(theVTKID) == myVTK2SMDSElems.end() ? -1 : myVTK2SMDSElems[theVTKID];
668 }
669
670 vtkIdType SMESH_VisualObjDef::GetElemVTKId( int theObjID )
671 {
672   return mySMDS2VTKElems.find(theObjID) == mySMDS2VTKElems.end() ? -1 : mySMDS2VTKElems[theObjID];
673 }
674
675 //=================================================================================
676 // function : SMESH_VisualObjDef::createPoints
677 // purpose  : Create points from nodes
678 //=================================================================================
679 void SMESH_VisualObjDef::createPoints( vtkPoints* thePoints )
680 {
681   if ( thePoints == 0 )
682     return;
683
684   TEntityList aNodes;
685   vtkIdType nbNodes = GetEntities( SMDSAbs_Node, aNodes );
686   thePoints->SetNumberOfPoints( nbNodes );
687   
688   int nbPoints = 0;
689
690   TEntityList::const_iterator anIter;
691   for ( anIter = aNodes.begin(); anIter != aNodes.end(); ++anIter )
692   {
693     const SMDS_MeshNode* aNode = ( const SMDS_MeshNode* )(*anIter);
694     if ( aNode != 0 )
695     {
696       thePoints->SetPoint( nbPoints, aNode->X(), aNode->Y(), aNode->Z() );
697       int anId = aNode->GetID();
698       mySMDS2VTKNodes.insert( TMapOfIds::value_type( anId, nbPoints ) );
699       myVTK2SMDSNodes.insert( TMapOfIds::value_type( nbPoints, anId ) );
700       nbPoints++;
701     }
702   }
703
704   if ( nbPoints != nbNodes )
705     thePoints->SetNumberOfPoints( nbPoints );
706 }
707
708 //=================================================================================
709 // function : buildPrs
710 // purpose  : create VTK cells( fill unstructured grid )
711 //=================================================================================
712 void SMESH_VisualObjDef::buildPrs()
713 {
714   try
715   {
716     mySMDS2VTKNodes.clear();
717     myVTK2SMDSNodes.clear();
718     mySMDS2VTKElems.clear();
719     myVTK2SMDSElems.clear();
720     
721     if ( IsNodePrs() )
722       buildNodePrs();
723     else
724       buildElemPrs();
725   }
726   catch( const std::exception& exc )
727   {
728     INFOS("Follow exception was cought:\n\t"<<exc.what());
729   }
730   catch(...)
731   {
732     INFOS("Unknown exception was cought !!!");
733   }
734   
735   if( MYDEBUG ) MESSAGE( "Update - myGrid->GetNumberOfCells() = "<<myGrid->GetNumberOfCells() );
736   if( MYDEBUGWITHFILES ) SMESH::WriteUnstructuredGrid( myGrid,"/tmp/buildPrs" );
737 }
738
739 //=================================================================================
740 // function : buildNodePrs
741 // purpose  : create VTK cells for nodes
742 //=================================================================================
743 void SMESH_VisualObjDef::buildNodePrs()
744 {
745   vtkPoints* aPoints = vtkPoints::New();
746   createPoints( aPoints );
747   myGrid->SetPoints( aPoints );
748   aPoints->Delete();
749
750   myGrid->SetCells( 0, 0, 0 );
751
752   // Create cells
753   /*
754   int nbPoints = aPoints->GetNumberOfPoints();
755   vtkIdList *anIdList = vtkIdList::New();
756   anIdList->SetNumberOfIds( 1 );
757
758   vtkCellArray *aCells = vtkCellArray::New();
759   aCells->Allocate( 2 * nbPoints, 0 );
760
761   vtkUnsignedCharArray* aCellTypesArray = vtkUnsignedCharArray::New();
762   aCellTypesArray->SetNumberOfComponents( 1 );
763   aCellTypesArray->Allocate( nbPoints );
764
765   for( vtkIdType aCellId = 0; aCellId < nbPoints; aCellId++ )
766   {
767     anIdList->SetId( 0, aCellId );
768     aCells->InsertNextCell( anIdList );
769     aCellTypesArray->InsertNextValue( VTK_VERTEX );
770   }
771
772   vtkIntArray* aCellLocationsArray = vtkIntArray::New();
773   aCellLocationsArray->SetNumberOfComponents( 1 );
774   aCellLocationsArray->SetNumberOfTuples( nbPoints );
775
776   aCells->InitTraversal();
777   for( vtkIdType i = 0, *pts, npts; aCells->GetNextCell( npts, pts ); i++ )
778     aCellLocationsArray->SetValue( i, aCells->GetTraversalLocation( npts ) );
779
780   myGrid->SetCells( aCellTypesArray, aCellLocationsArray, aCells );
781
782   aCellLocationsArray->Delete();
783   aCellTypesArray->Delete();
784   aCells->Delete();
785   anIdList->Delete(); 
786   */
787 }
788
789 //=================================================================================
790 // function : buildElemPrs
791 // purpose  : Create VTK cells for elements
792 //=================================================================================
793
794 namespace{
795   typedef std::vector<const SMDS_MeshElement*> TConnect;
796
797   int GetConnect(const SMDS_ElemIteratorPtr& theNodesIter, 
798                  TConnect& theConnect)
799   {
800     theConnect.clear();
801     for(; theNodesIter->more();)
802       theConnect.push_back(theNodesIter->next());
803     return theConnect.size();
804   }
805   
806   inline 
807   void SetId(vtkIdList *theIdList, 
808              const SMESH_VisualObjDef::TMapOfIds& theSMDS2VTKNodes, 
809              const TConnect& theConnect, 
810              int thePosition,
811              int theId)
812   {
813     theIdList->SetId(thePosition,theSMDS2VTKNodes.find(theConnect[theId]->GetID())->second);
814   }
815
816 }
817
818
819 void SMESH_VisualObjDef::buildElemPrs()
820 {
821   // Create points
822   
823   vtkPoints* aPoints = vtkPoints::New();
824   createPoints( aPoints );
825   myGrid->SetPoints( aPoints );
826   aPoints->Delete();
827     
828   if ( MYDEBUG )
829     MESSAGE("Update - myGrid->GetNumberOfPoints() = "<<myGrid->GetNumberOfPoints());
830
831   // Calculate cells size
832
833   static SMDSAbs_ElementType aTypes[ 3 ] = { SMDSAbs_Edge, SMDSAbs_Face, SMDSAbs_Volume };
834
835   // get entity data
836   map<SMDSAbs_ElementType,int> nbEnts;
837   map<SMDSAbs_ElementType,TEntityList> anEnts;
838
839   for ( int i = 0; i <= 2; i++ )
840     nbEnts[ aTypes[ i ] ] = GetEntities( aTypes[ i ], anEnts[ aTypes[ i ] ] );
841
842   vtkIdType aCellsSize =  3 * nbEnts[ SMDSAbs_Edge ];
843
844   for ( int i = 1; i <= 2; i++ ) // iterate through faces and volumes
845   {
846     if ( nbEnts[ aTypes[ i ] ] )
847     {
848       const TEntityList& aList = anEnts[ aTypes[ i ] ];
849       TEntityList::const_iterator anIter;
850       for ( anIter = aList.begin(); anIter != aList.end(); ++anIter )
851         aCellsSize += (*anIter)->NbNodes() + 1;
852     }
853   }
854
855   vtkIdType aNbCells = nbEnts[ SMDSAbs_Edge ] + nbEnts[ SMDSAbs_Face ] + nbEnts[ SMDSAbs_Volume ];
856   
857   if ( MYDEBUG )
858     MESSAGE( "Update - aNbCells = "<<aNbCells<<"; aCellsSize = "<<aCellsSize );
859
860   // Create cells
861   
862   vtkCellArray* aConnectivity = vtkCellArray::New();
863   aConnectivity->Allocate( aCellsSize, 0 );
864   
865   vtkUnsignedCharArray* aCellTypesArray = vtkUnsignedCharArray::New();
866   aCellTypesArray->SetNumberOfComponents( 1 );
867   aCellTypesArray->Allocate( aNbCells * aCellTypesArray->GetNumberOfComponents() );
868   
869   vtkIdList *anIdList = vtkIdList::New();
870   vtkIdType iElem = 0;
871
872   TConnect aConnect;
873   aConnect.reserve(VTK_CELL_SIZE);
874
875   for ( int i = 0; i <= 2; i++ ) // iterate through edges, faces and volumes
876   {
877     if( nbEnts[ aTypes[ i ] ] > 0 )
878     {
879       const SMDSAbs_ElementType& aType = aTypes[ i ];
880       const TEntityList& aList = anEnts[ aType ];
881       TEntityList::const_iterator anIter;
882       for ( anIter = aList.begin(); anIter != aList.end(); ++anIter )
883       {
884         const SMDS_MeshElement* anElem = *anIter;
885         
886         vtkIdType aNbNodes = anElem->NbNodes();
887         anIdList->SetNumberOfIds( aNbNodes );
888
889         int anId = anElem->GetID();
890
891         mySMDS2VTKElems.insert( TMapOfIds::value_type( anId, iElem ) );
892         myVTK2SMDSElems.insert( TMapOfIds::value_type( iElem, anId ) );
893
894         SMDS_ElemIteratorPtr aNodesIter = anElem->nodesIterator();
895         switch(aType){
896         case SMDSAbs_Volume:{
897           std::vector<int> aConnectivities;
898           GetConnect(aNodesIter,aConnect);
899           // Convertions connectivities from SMDS to VTK
900           if (anElem->IsPoly() && aNbNodes > 3) { // POLYEDRE
901             for (int k = 0; k < aNbNodes; k++) {
902               aConnectivities.push_back(k);
903             }
904
905           } else if (aNbNodes == 4) {
906             static int anIds[] = {0,2,1,3};
907             for (int k = 0; k < aNbNodes; k++) aConnectivities.push_back(anIds[k]);
908
909           } else if (aNbNodes == 5) {
910             static int anIds[] = {0,3,2,1,4};
911             for (int k = 0; k < aNbNodes; k++) aConnectivities.push_back(anIds[k]);
912
913           } else if (aNbNodes == 6) {
914             static int anIds[] = {0,1,2,3,4,5};
915             for (int k = 0; k < aNbNodes; k++) aConnectivities.push_back(anIds[k]);
916
917           }
918           else if (aNbNodes == 8) {
919             static int anIds[] = {0,3,2,1,4,7,6,5};
920             for (int k = 0; k < aNbNodes; k++) aConnectivities.push_back(anIds[k]);
921
922           }
923           else if (aNbNodes == 10) {
924             static int anIds[] = {0,2,1,3,6,5,4,7,9,8};
925             for (int k = 0; k < aNbNodes; k++) aConnectivities.push_back(anIds[k]);
926           }
927           else if (aNbNodes == 13) {
928             static int anIds[] = {0,3,2,1,4,8,7,6,5,9,12,11,10};
929             for (int k = 0; k < aNbNodes; k++) aConnectivities.push_back(anIds[k]);
930           }
931           else if (aNbNodes == 15) {
932             static int anIds[] = {0,2,1,3,5,4,8,7,6,11,10,9,12,14,13};
933             for (int k = 0; k < aNbNodes; k++) aConnectivities.push_back(anIds[k]);
934             //for (int k = 0; k < aNbNodes; k++) {
935             //  int nn = aConnectivities[k];
936             //  const SMDS_MeshNode* N = static_cast<const SMDS_MeshNode*> (aConnect[nn]);
937             //  cout<<"k="<<k<<"  N("<<N->X()<<","<<N->Y()<<","<<N->Z()<<")"<<endl;
938             //}
939           }
940           else if (aNbNodes == 20) {
941             static int anIds[] = {0,3,2,1,4,7,6,5,11,10,9,8,15,14,13,12,16,19,18,17};
942             for (int k = 0; k < aNbNodes; k++) aConnectivities.push_back(anIds[k]);
943           }
944           else {
945           }
946
947           if (aConnectivities.size() > 0) {
948             for (vtkIdType aNodeId = 0; aNodeId < aNbNodes; aNodeId++)
949               SetId(anIdList,mySMDS2VTKNodes,aConnect,aNodeId,aConnectivities[aNodeId]);
950           }
951           break;
952         }
953         default:
954           for( vtkIdType aNodeId = 0; aNodesIter->more(); aNodeId++ ){
955             const SMDS_MeshElement* aNode = aNodesIter->next();
956             anIdList->SetId( aNodeId, mySMDS2VTKNodes[aNode->GetID()] );
957           }
958         }
959
960         aConnectivity->InsertNextCell( anIdList );
961         aCellTypesArray->InsertNextValue( getCellType( aType, anElem->IsPoly(), aNbNodes ) );
962
963         iElem++;
964       }
965     }
966   }
967
968   // Insert cells in grid
969   
970   vtkIntArray* aCellLocationsArray = vtkIntArray::New();
971   aCellLocationsArray->SetNumberOfComponents( 1 );
972   aCellLocationsArray->SetNumberOfTuples( aNbCells );
973   
974   aConnectivity->InitTraversal();
975   for( vtkIdType idType = 0, *pts, npts; aConnectivity->GetNextCell( npts, pts ); idType++ )
976     aCellLocationsArray->SetValue( idType, aConnectivity->GetTraversalLocation( npts ) );
977
978   myGrid->SetCells( aCellTypesArray, aCellLocationsArray,aConnectivity );
979   
980   aCellLocationsArray->Delete();
981   aCellTypesArray->Delete();
982   aConnectivity->Delete();
983   anIdList->Delete();
984 }
985
986 //=================================================================================
987 // function : GetEdgeNodes
988 // purpose  : Retrieve ids of nodes from edge of elements ( edge is numbered from 1 )
989 //=================================================================================
990 bool SMESH_VisualObjDef::GetEdgeNodes( const int theElemId,
991                                        const int theEdgeNum,
992                                        int&      theNodeId1,
993                                        int&      theNodeId2 ) const
994 {
995   const SMDS_Mesh* aMesh = GetMesh();
996   if ( aMesh == 0 )
997     return false;
998     
999   const SMDS_MeshElement* anElem = aMesh->FindElement( theElemId );
1000   if ( anElem == 0 )
1001     return false;
1002     
1003   int nbNodes = anElem->NbNodes();
1004
1005   if ( theEdgeNum < 0 || theEdgeNum > 3 || nbNodes != 3 && nbNodes != 4 || theEdgeNum > nbNodes )
1006     return false;
1007
1008   int anIds[ nbNodes ];
1009   SMDS_ElemIteratorPtr anIter = anElem->nodesIterator();
1010   int i = 0;
1011   while( anIter->more() )
1012     anIds[ i++ ] = anIter->next()->GetID();
1013
1014   if ( theEdgeNum < nbNodes - 1 )
1015   {
1016     theNodeId1 = anIds[ theEdgeNum ];
1017     theNodeId2 = anIds[ theEdgeNum + 1 ];
1018   }
1019   else
1020   {
1021     theNodeId1 = anIds[ nbNodes - 1 ];
1022     theNodeId2 = anIds[ 0 ];
1023   }
1024
1025   return true;
1026 }
1027
1028 /*
1029   Class       : SMESH_MeshObj
1030   Description : Class for visualisation of mesh
1031 */
1032
1033 //=================================================================================
1034 // function : SMESH_MeshObj
1035 // purpose  : Constructor
1036 //=================================================================================
1037 SMESH_MeshObj::SMESH_MeshObj(SMESH::SMESH_Mesh_ptr theMesh)
1038 {
1039   if ( MYDEBUG ) 
1040     MESSAGE("SMESH_MeshObj - theMesh->_is_nil() = "<<theMesh->_is_nil());
1041     
1042   myMeshServer = SMESH::SMESH_Mesh::_duplicate( theMesh );
1043   myMeshServer->Register();
1044   myMesh = new SMDS_Mesh();
1045 }
1046
1047 //=================================================================================
1048 // function : ~SMESH_MeshObj
1049 // purpose  : Destructor
1050 //=================================================================================
1051 SMESH_MeshObj::~SMESH_MeshObj()
1052 {
1053   myMeshServer->Destroy();
1054   delete myMesh;
1055 }
1056
1057 //=================================================================================
1058 // function : Update
1059 // purpose  : Update mesh and fill grid with new values if necessary 
1060 //=================================================================================
1061 void SMESH_MeshObj::Update( int theIsClear )
1062 {
1063   // Update SMDS_Mesh on client part
1064   
1065   try
1066   {
1067     SMESH::log_array_var aSeq = myMeshServer->GetLog( theIsClear );
1068     CORBA::Long aLength = aSeq->length();
1069     
1070     if( MYDEBUG ) MESSAGE( "Update: length of the script is "<<aLength );
1071     
1072     if( !aLength )
1073       return;
1074
1075     for ( CORBA::Long anId = 0; anId < aLength; anId++)
1076     {
1077       const SMESH::double_array& aCoords = aSeq[anId].coords;
1078       const SMESH::long_array& anIndexes = aSeq[anId].indexes;
1079       CORBA::Long anElemId = 0, aNbElems = aSeq[anId].number;
1080       CORBA::Long aCommand = aSeq[anId].commandType;
1081
1082       switch(aCommand)
1083       {
1084         case SMESH::ADD_NODE       : AddNodesWithID      ( myMesh, aSeq, anId ); break;
1085         case SMESH::ADD_EDGE       : AddEdgesWithID      ( myMesh, aSeq, anId ); break;
1086         case SMESH::ADD_TRIANGLE   : AddTriasWithID      ( myMesh, aSeq, anId ); break;
1087         case SMESH::ADD_QUADRANGLE : AddQuadsWithID      ( myMesh, aSeq, anId ); break;
1088         case SMESH::ADD_POLYGON    : AddPolygonsWithID   ( myMesh, aSeq, anId ); break;
1089         case SMESH::ADD_TETRAHEDRON: AddTetrasWithID     ( myMesh, aSeq, anId ); break;
1090         case SMESH::ADD_PYRAMID    : AddPiramidsWithID   ( myMesh, aSeq, anId ); break;
1091         case SMESH::ADD_PRISM      : AddPrismsWithID     ( myMesh, aSeq, anId ); break;
1092         case SMESH::ADD_HEXAHEDRON : AddHexasWithID      ( myMesh, aSeq, anId ); break;
1093         case SMESH::ADD_POLYHEDRON : AddPolyhedronsWithID( myMesh, aSeq, anId ); break;
1094
1095         case SMESH::ADD_QUADEDGE       : AddQuadEdgesWithID   ( myMesh, aSeq, anId ); break;
1096         case SMESH::ADD_QUADTRIANGLE   : AddQuadTriasWithID   ( myMesh, aSeq, anId ); break;
1097         case SMESH::ADD_QUADQUADRANGLE : AddQuadQuadsWithID   ( myMesh, aSeq, anId ); break;
1098         case SMESH::ADD_QUADTETRAHEDRON: AddQuadTetrasWithID  ( myMesh, aSeq, anId ); break;
1099         case SMESH::ADD_QUADPYRAMID    : AddQuadPiramidsWithID( myMesh, aSeq, anId ); break;
1100         case SMESH::ADD_QUADPENTAHEDRON: AddQuadPentasWithID  ( myMesh, aSeq, anId ); break;
1101         case SMESH::ADD_QUADHEXAHEDRON : AddQuadHexasWithID   ( myMesh, aSeq, anId ); break;
1102
1103         case SMESH::REMOVE_NODE:
1104           for( ; anElemId < aNbElems; anElemId++ )
1105             myMesh->RemoveNode( FindNode( myMesh, anIndexes[anElemId] ) );
1106         break;
1107         
1108         case SMESH::REMOVE_ELEMENT:
1109           for( ; anElemId < aNbElems; anElemId++ )
1110             myMesh->RemoveElement( FindElement( myMesh, anIndexes[anElemId] ) );
1111         break;
1112
1113         case SMESH::MOVE_NODE:
1114           for(CORBA::Long aCoordId=0; anElemId < aNbElems; anElemId++, aCoordId+=3)
1115           {
1116             SMDS_MeshNode* node =
1117               const_cast<SMDS_MeshNode*>( FindNode( myMesh, anIndexes[anElemId] ));
1118             node->setXYZ( aCoords[aCoordId], aCoords[aCoordId+1], aCoords[aCoordId+2] );
1119           }
1120         break;
1121
1122         case SMESH::CHANGE_ELEMENT_NODES:
1123           for ( CORBA::Long i = 0; anElemId < aNbElems; anElemId++ )
1124           {
1125             // find element
1126             const SMDS_MeshElement* elem = FindElement( myMesh, anIndexes[i++] );
1127             // nb nodes
1128             int nbNodes = anIndexes[i++];
1129             // nodes
1130             //ASSERT( nbNodes < 9 );
1131             const SMDS_MeshNode* aNodes[ nbNodes ];
1132             for ( int iNode = 0; iNode < nbNodes; iNode++ )
1133               aNodes[ iNode ] = FindNode( myMesh, anIndexes[i++] );
1134             // change
1135             myMesh->ChangeElementNodes( elem, aNodes, nbNodes );
1136           }
1137           break;
1138
1139         case SMESH::CHANGE_POLYHEDRON_NODES:
1140           ChangePolyhedronNodes(myMesh, aSeq, anId);
1141           break;
1142         case SMESH::RENUMBER:
1143           for(CORBA::Long i=0; anElemId < aNbElems; anElemId++, i+=3)
1144           {
1145             myMesh->Renumber( anIndexes[i], anIndexes[i+1], anIndexes[i+2] );
1146           }
1147           break;
1148           
1149         default:;
1150       }
1151     }
1152   }
1153   catch ( SALOME::SALOME_Exception& exc )
1154   {
1155     INFOS("Following exception was cought:\n\t"<<exc.details.text);
1156   }
1157   catch( const std::exception& exc)
1158   {
1159     INFOS("Following exception was cought:\n\t"<<exc.what());
1160   }
1161   catch(...)
1162   {
1163     INFOS("Unknown exception was cought !!!");
1164   }
1165   
1166   if ( MYDEBUG )
1167   {
1168     MESSAGE("Update - myMesh->NbNodes() = "<<myMesh->NbNodes());
1169     MESSAGE("Update - myMesh->NbEdges() = "<<myMesh->NbEdges());
1170     MESSAGE("Update - myMesh->NbFaces() = "<<myMesh->NbFaces());
1171     MESSAGE("Update - myMesh->NbVolumes() = "<<myMesh->NbVolumes());
1172   }
1173
1174   // Fill unstructured grid
1175   buildPrs();
1176 }
1177
1178 //=================================================================================
1179 // function : GetElemDimension
1180 // purpose  : Get dimension of element
1181 //=================================================================================
1182 int SMESH_MeshObj::GetElemDimension( const int theObjId )
1183 {
1184   const SMDS_MeshElement* anElem = myMesh->FindElement( theObjId );
1185   if ( anElem == 0 )
1186     return 0;
1187
1188   int aType = anElem->GetType();
1189   switch ( aType )
1190   {
1191     case SMDSAbs_Edge  : return 1;
1192     case SMDSAbs_Face  : return 2;
1193     case SMDSAbs_Volume: return 3;
1194     default            : return 0;
1195   }
1196 }
1197
1198 //=================================================================================
1199 // function : GetEntities
1200 // purpose  : Get entities of specified type. Return number of entities
1201 //=================================================================================
1202 int SMESH_MeshObj::GetNbEntities( const SMDSAbs_ElementType theType) const
1203 {
1204   switch ( theType )
1205   {
1206     case SMDSAbs_Node:
1207     {
1208       return myMesh->NbNodes();
1209     }
1210     break;
1211     case SMDSAbs_Edge:
1212     {
1213       return myMesh->NbEdges();
1214     }
1215     break;
1216     case SMDSAbs_Face:
1217     {
1218       return myMesh->NbFaces();
1219     }
1220     break;
1221     case SMDSAbs_Volume:
1222     {
1223       return myMesh->NbVolumes();
1224     }
1225     break;
1226     default:
1227       return 0;
1228     break;
1229   }
1230 }
1231
1232 int SMESH_MeshObj::GetEntities( const SMDSAbs_ElementType theType, TEntityList& theObjs ) const
1233 {
1234   theObjs.clear();
1235
1236   switch ( theType )
1237   {
1238     case SMDSAbs_Node:
1239     {
1240       SMDS_NodeIteratorPtr anIter = myMesh->nodesIterator();
1241       while ( anIter->more() ) theObjs.push_back( anIter->next() );
1242     }
1243     break;
1244     case SMDSAbs_Edge:
1245     {
1246       SMDS_EdgeIteratorPtr anIter = myMesh->edgesIterator();
1247       while ( anIter->more() ) theObjs.push_back( anIter->next() );
1248     }
1249     break;
1250     case SMDSAbs_Face:
1251     {
1252       SMDS_FaceIteratorPtr anIter = myMesh->facesIterator();
1253       while ( anIter->more() ) theObjs.push_back( anIter->next() );
1254     }
1255     break;
1256     case SMDSAbs_Volume:
1257     {
1258       SMDS_VolumeIteratorPtr anIter = myMesh->volumesIterator();
1259       while ( anIter->more() ) theObjs.push_back( anIter->next() );
1260     }
1261     break;
1262     default:
1263     break;
1264   }
1265
1266   return theObjs.size();
1267 }
1268
1269 //=================================================================================
1270 // function : UpdateFunctor
1271 // purpose  : Update functor in accordance with current mesh
1272 //=================================================================================
1273 void SMESH_MeshObj::UpdateFunctor( const SMESH::Controls::FunctorPtr& theFunctor )
1274 {
1275   theFunctor->SetMesh( GetMesh() );
1276 }
1277
1278 //=================================================================================
1279 // function : IsNodePrs
1280 // purpose  : Return true if node presentation is used
1281 //=================================================================================
1282 bool SMESH_MeshObj::IsNodePrs() const
1283 {
1284   return myMesh->NbEdges() == 0 &&myMesh->NbFaces() == 0 &&myMesh->NbVolumes() == 0 ;
1285 }
1286
1287
1288 /*
1289   Class       : SMESH_SubMeshObj
1290   Description : Base class for visualisation of submeshes and groups
1291 */
1292
1293 //=================================================================================
1294 // function : SMESH_SubMeshObj
1295 // purpose  : Constructor
1296 //=================================================================================
1297 SMESH_SubMeshObj::SMESH_SubMeshObj( SMESH_MeshObj* theMeshObj )
1298 {
1299   if ( MYDEBUG ) MESSAGE( "SMESH_SubMeshObj - theMeshObj = " << theMeshObj );
1300   
1301   myMeshObj = theMeshObj;
1302 }
1303
1304 SMESH_SubMeshObj::~SMESH_SubMeshObj()
1305 {
1306 }
1307
1308 //=================================================================================
1309 // function : GetElemDimension
1310 // purpose  : Get dimension of element
1311 //=================================================================================
1312 int SMESH_SubMeshObj::GetElemDimension( const int theObjId )
1313 {
1314   return myMeshObj == 0 ? 0 : myMeshObj->GetElemDimension( theObjId );
1315 }
1316
1317 //=================================================================================
1318 // function : UpdateFunctor
1319 // purpose  : Update functor in accordance with current mesh
1320 //=================================================================================
1321 void SMESH_SubMeshObj::UpdateFunctor( const SMESH::Controls::FunctorPtr& theFunctor )
1322 {
1323   theFunctor->SetMesh( myMeshObj->GetMesh() );
1324 }
1325
1326 //=================================================================================
1327 // function : Update
1328 // purpose  : Update mesh object and fill grid with new values 
1329 //=================================================================================
1330 void SMESH_SubMeshObj::Update( int theIsClear )
1331 {
1332   myMeshObj->Update( theIsClear );
1333   buildPrs();
1334 }
1335
1336
1337 /*
1338   Class       : SMESH_GroupObj
1339   Description : Class for visualisation of groups
1340 */
1341
1342 //=================================================================================
1343 // function : SMESH_GroupObj
1344 // purpose  : Constructor
1345 //=================================================================================
1346 SMESH_GroupObj::SMESH_GroupObj( SMESH::SMESH_GroupBase_ptr theGroup, 
1347                                 SMESH_MeshObj*             theMeshObj )
1348 : SMESH_SubMeshObj( theMeshObj ),
1349   myGroupServer( SMESH::SMESH_GroupBase::_duplicate(theGroup) )
1350 {
1351   if ( MYDEBUG ) MESSAGE("SMESH_GroupObj - theGroup->_is_nil() = "<<theGroup->_is_nil());
1352   myGroupServer->Register();
1353 }
1354
1355 SMESH_GroupObj::~SMESH_GroupObj()
1356 {
1357   if ( MYDEBUG ) MESSAGE("~SMESH_GroupObj");
1358   myGroupServer->Destroy();
1359 }
1360
1361 //=================================================================================
1362 // function : IsNodePrs
1363 // purpose  : Return true if node presentation is used
1364 //=================================================================================
1365 bool SMESH_GroupObj::IsNodePrs() const
1366 {
1367   return myGroupServer->GetType() == SMESH::NODE;
1368 }
1369
1370 //=================================================================================
1371 // function : getNodesFromElems
1372 // purpose  : Retrieve nodes from elements
1373 //=================================================================================
1374 static int getNodesFromElems( SMESH::long_array_var&              theElemIds,
1375                               const SMDS_Mesh*                    theMesh,
1376                               std::list<const SMDS_MeshElement*>& theResList )
1377 {
1378   set<const SMDS_MeshElement*> aNodeSet;
1379
1380   for ( CORBA::Long i = 0, n = theElemIds->length(); i < n; i++ )
1381   {
1382     const SMDS_MeshElement* anElem = theMesh->FindElement( theElemIds[ i ] );
1383     if ( anElem != 0 )
1384     {
1385       SMDS_ElemIteratorPtr anIter = anElem->nodesIterator();
1386       while ( anIter->more() )
1387       {
1388         const SMDS_MeshElement* aNode = anIter->next();
1389         if ( aNode != 0 )
1390           aNodeSet.insert( aNode );
1391       }
1392     }
1393   }
1394
1395   set<const SMDS_MeshElement*>::const_iterator anIter;
1396   for ( anIter = aNodeSet.begin(); anIter != aNodeSet.end(); ++anIter )
1397     theResList.push_back( *anIter );
1398
1399   return theResList.size();    
1400 }
1401
1402 //=================================================================================
1403 // function : getPointers
1404 // purpose  : Get std::list<const SMDS_MeshElement*> from list of IDs
1405 //=================================================================================
1406 static int getPointers( const SMDSAbs_ElementType            theRequestType,
1407                         SMESH::long_array_var&              theElemIds,
1408                         const SMDS_Mesh*                    theMesh,
1409                         std::list<const SMDS_MeshElement*>& theResList )
1410 {
1411   for ( CORBA::Long i = 0, n = theElemIds->length(); i < n; i++ )
1412   {
1413     const SMDS_MeshElement* anElem = theRequestType == SMDSAbs_Node
1414       ? theMesh->FindNode( theElemIds[ i ] ) : theMesh->FindElement( theElemIds[ i ] );
1415
1416     if ( anElem != 0 )
1417       theResList.push_back( anElem );
1418   }
1419
1420   return theResList.size();
1421 }
1422
1423
1424 //=================================================================================
1425 // function : GetEntities
1426 // purpose  : Get entities of specified type. Return number of entities
1427 //=================================================================================
1428 int SMESH_GroupObj::GetNbEntities( const SMDSAbs_ElementType theType) const
1429 {
1430   if(SMDSAbs_ElementType(myGroupServer->GetType()) == theType){
1431     return myGroupServer->Size();
1432   }
1433   return 0;
1434 }
1435
1436 int SMESH_GroupObj::GetEntities( const SMDSAbs_ElementType theType, TEntityList& theResList ) const
1437 {
1438   theResList.clear();
1439   SMDS_Mesh* aMesh = myMeshObj->GetMesh();
1440   
1441   if ( myGroupServer->Size() == 0 || aMesh == 0 )
1442     return 0;
1443
1444   SMDSAbs_ElementType aGrpType = SMDSAbs_ElementType(myGroupServer->GetType());
1445   SMESH::long_array_var anIds = myGroupServer->GetListOfID();
1446
1447   if ( aGrpType == theType )
1448     return getPointers( theType, anIds, aMesh, theResList );
1449   else if ( theType == SMDSAbs_Node )
1450     return getNodesFromElems( anIds, aMesh, theResList );
1451   else
1452     return 0;
1453 }    
1454
1455
1456
1457 /*
1458   Class       : SMESH_subMeshObj
1459   Description : Class for visualisation of submeshes
1460 */
1461
1462 //=================================================================================
1463 // function : SMESH_subMeshObj
1464 // purpose  : Constructor
1465 //=================================================================================
1466 SMESH_subMeshObj::SMESH_subMeshObj( SMESH::SMESH_subMesh_ptr theSubMesh,
1467                                     SMESH_MeshObj*           theMeshObj )
1468 : SMESH_SubMeshObj( theMeshObj ),
1469   mySubMeshServer( SMESH::SMESH_subMesh::_duplicate( theSubMesh ) )
1470 {
1471   if ( MYDEBUG ) MESSAGE( "SMESH_subMeshObj - theSubMesh->_is_nil() = " << theSubMesh->_is_nil() );
1472   
1473   mySubMeshServer->Register();
1474 }
1475
1476 SMESH_subMeshObj::~SMESH_subMeshObj()
1477 {
1478   if ( MYDEBUG ) MESSAGE( "~SMESH_subMeshObj" );
1479   mySubMeshServer->Destroy();
1480 }
1481
1482 //=================================================================================
1483 // function : GetEntities
1484 // purpose  : Get entities of specified type. Return number of entities
1485 //=================================================================================
1486 int SMESH_subMeshObj::GetNbEntities( const SMDSAbs_ElementType theType) const
1487 {
1488   switch ( theType )
1489   {
1490     case SMDSAbs_Node:
1491     {
1492       return mySubMeshServer->GetNumberOfNodes( false );
1493     }
1494     break;
1495     case SMDSAbs_Edge:
1496     case SMDSAbs_Face:
1497     case SMDSAbs_Volume:
1498     {
1499       SMESH::long_array_var anIds = 
1500         mySubMeshServer->GetElementsByType( SMESH::ElementType(theType) );
1501       return anIds->length();
1502     }
1503     default:
1504       return 0;
1505     break;
1506   }
1507 }
1508
1509 int SMESH_subMeshObj::GetEntities( const SMDSAbs_ElementType theType, TEntityList& theResList ) const
1510 {
1511   theResList.clear();
1512
1513   SMDS_Mesh* aMesh = myMeshObj->GetMesh();
1514   if ( aMesh == 0 )
1515     return 0;
1516
1517   bool isNodal = IsNodePrs();
1518
1519   if ( isNodal )
1520   {
1521     if ( theType == SMDSAbs_Node )
1522     {
1523       SMESH::long_array_var anIds = mySubMeshServer->GetNodesId();
1524       return getPointers( SMDSAbs_Node, anIds, aMesh, theResList );
1525     }
1526   }
1527   else
1528   {
1529     if ( theType == SMDSAbs_Node )
1530     {
1531       SMESH::long_array_var anIds = mySubMeshServer->GetElementsId();
1532       return getNodesFromElems( anIds, aMesh, theResList );
1533     }
1534     else
1535     {
1536       SMESH::long_array_var anIds = 
1537         mySubMeshServer->GetElementsByType( SMESH::ElementType(theType) );
1538       return getPointers( theType, anIds, aMesh, theResList );
1539     }
1540   }
1541
1542   return 0;
1543 }
1544
1545 //=================================================================================
1546 // function : IsNodePrs
1547 // purpose  : Return true if node presentation is used
1548 //=================================================================================
1549 bool SMESH_subMeshObj::IsNodePrs() const
1550 {
1551   return mySubMeshServer->GetNumberOfElements() == 0;
1552 }
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562
1563
1564