Salome HOME
[SALOME platform 0019943] Pb with projection 2d
[modules/smesh.git] / src / SMDS / SMDS_Mesh.cxx
1 //  SMESH SMDS : implementaion of Salome mesh data structure
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.salome-platform.org/ or email : webmaster.salome@opencascade.com
21
22 #ifdef _MSC_VER
23 #pragma warning(disable:4786)
24 #endif
25
26 #include "utilities.h"
27 #include "SMDS_Mesh.hxx"
28 #include "SMDS_VolumeOfNodes.hxx"
29 #include "SMDS_VolumeOfFaces.hxx"
30 #include "SMDS_FaceOfNodes.hxx"
31 #include "SMDS_FaceOfEdges.hxx"
32 #include "SMDS_PolyhedralVolumeOfNodes.hxx"
33 #include "SMDS_PolygonalFaceOfNodes.hxx"
34 #include "SMDS_QuadraticEdge.hxx"
35 #include "SMDS_QuadraticFaceOfNodes.hxx"
36 #include "SMDS_QuadraticVolumeOfNodes.hxx"
37
38 #include <algorithm>
39 #include <map>
40 using namespace std;
41
42 #ifndef WIN32
43 #include <sys/sysinfo.h>
44 #endif
45
46 // number of added entitis to check memory after
47 #define CHECKMEMORY_INTERVAL 1000
48
49 //================================================================================
50 /*!
51  * \brief Raise an exception if free memory (ram+swap) too low
52  * \param doNotRaise - if true, suppres exception, just return free memory size
53  * \retval int - amount of available memory in MB or negative number in failure case
54  */
55 //================================================================================
56
57 int SMDS_Mesh::CheckMemory(const bool doNotRaise) throw (std::bad_alloc)
58 {
59 #ifndef WIN32
60   struct sysinfo si;
61   int err = sysinfo( &si );
62   if ( err )
63     return -1;
64
65   static int limit = -1;
66   if ( limit < 0 ) {
67     int status = system("SMDS_MemoryLimit"); // it returns lower limit of free RAM
68     if (status >= 0 ) {
69       limit = WEXITSTATUS(status);
70     }
71     if ( limit < 20 )
72       limit = 20;
73     else
74       limit = int( limit * 1.5 );
75 #ifdef _DEBUG_
76     MESSAGE ( "SMDS_Mesh::CheckMemory() memory limit = " << limit << " MB" );
77 #endif
78   }
79
80   const unsigned long Mbyte = 1024 * 1024;
81   // compute separately to avoid overflow
82   int freeMb =
83     ( si.freeram  * si.mem_unit ) / Mbyte +
84     ( si.freeswap * si.mem_unit ) / Mbyte;
85
86   if ( freeMb > limit )
87     return freeMb - limit;
88
89   if ( doNotRaise )
90     return 0;
91 #ifdef _DEBUG_
92   MESSAGE ("SMDS_Mesh::CheckMemory() throws as free memory too low: " << freeMb <<" MB" );
93 #endif
94   throw std::bad_alloc();
95 #else
96   return -1;
97 #endif
98 }
99
100 ///////////////////////////////////////////////////////////////////////////////
101 /// Create a new mesh object
102 ///////////////////////////////////////////////////////////////////////////////
103 SMDS_Mesh::SMDS_Mesh()
104         :myParent(NULL),
105         myNodeIDFactory(new SMDS_MeshElementIDFactory()),
106         myElementIDFactory(new SMDS_MeshElementIDFactory()),
107         myHasConstructionEdges(false), myHasConstructionFaces(false),
108         myHasInverseElements(true)
109 {
110 }
111
112 ///////////////////////////////////////////////////////////////////////////////
113 /// Create a new child mesh
114 /// Note that the tree structure of SMDS_Mesh seems to be unused in this version
115 /// (2003-09-08) of SMESH
116 ///////////////////////////////////////////////////////////////////////////////
117 SMDS_Mesh::SMDS_Mesh(SMDS_Mesh * parent)
118         :myParent(parent), myNodeIDFactory(parent->myNodeIDFactory),
119         myElementIDFactory(parent->myElementIDFactory),
120         myHasConstructionEdges(false), myHasConstructionFaces(false),
121         myHasInverseElements(true)
122 {
123 }
124
125 ///////////////////////////////////////////////////////////////////////////////
126 ///Create a submesh and add it to the current mesh
127 ///////////////////////////////////////////////////////////////////////////////
128
129 SMDS_Mesh *SMDS_Mesh::AddSubMesh()
130 {
131         SMDS_Mesh *submesh = new SMDS_Mesh(this);
132         myChildren.insert(myChildren.end(), submesh);
133         return submesh;
134 }
135
136 ///////////////////////////////////////////////////////////////////////////////
137 ///create a MeshNode and add it to the current Mesh
138 ///An ID is automatically assigned to the node.
139 ///@return : The created node
140 ///////////////////////////////////////////////////////////////////////////////
141
142 SMDS_MeshNode * SMDS_Mesh::AddNode(double x, double y, double z)
143 {
144   return SMDS_Mesh::AddNodeWithID(x,y,z,myNodeIDFactory->GetFreeID());
145 }
146
147 ///////////////////////////////////////////////////////////////////////////////
148 ///create a MeshNode and add it to the current Mesh
149 ///@param ID : The ID of the MeshNode to create
150 ///@return : The created node or NULL if a node with this ID already exists
151 ///////////////////////////////////////////////////////////////////////////////
152 SMDS_MeshNode * SMDS_Mesh::AddNodeWithID(double x, double y, double z, int ID)
153 {
154   // find the MeshNode corresponding to ID
155   const SMDS_MeshElement *node = myNodeIDFactory->MeshElement(ID);
156   if(!node){
157     if ( myNodes.Extent() % CHECKMEMORY_INTERVAL == 0 ) CheckMemory();
158     SMDS_MeshNode * node=new SMDS_MeshNode(x, y, z);
159     myNodes.Add(node);
160     myNodeIDFactory->BindID(ID,node);
161     myInfo.myNbNodes++;
162     return node;
163   }else
164     return NULL;
165 }
166
167 ///////////////////////////////////////////////////////////////////////////////
168 /// create a MeshEdge and add it to the current Mesh
169 /// @return : The created MeshEdge
170 ///////////////////////////////////////////////////////////////////////////////
171
172 SMDS_MeshEdge* SMDS_Mesh::AddEdgeWithID(int idnode1, int idnode2, int ID) 
173 {
174   SMDS_MeshNode * node1 = (SMDS_MeshNode *)myNodeIDFactory->MeshElement(idnode1);
175   SMDS_MeshNode * node2 = (SMDS_MeshNode *)myNodeIDFactory->MeshElement(idnode2);
176   if(!node1 || !node2) return NULL;
177   return SMDS_Mesh::AddEdgeWithID(node1, node2, ID);
178 }
179
180 ///////////////////////////////////////////////////////////////////////////////
181 /// create a MeshEdge and add it to the current Mesh
182 /// @return : The created MeshEdge
183 ///////////////////////////////////////////////////////////////////////////////
184
185 SMDS_MeshEdge* SMDS_Mesh::AddEdge(const SMDS_MeshNode * node1,
186                                   const SMDS_MeshNode * node2)
187 {
188   return SMDS_Mesh::AddEdgeWithID(node1, node2, myElementIDFactory->GetFreeID());
189 }
190
191 ///////////////////////////////////////////////////////////////////////////////
192 /// Create a new edge and at it to the mesh
193 /// @param idnode1 ID of the first node
194 /// @param idnode2 ID of the second node
195 /// @param ID ID of the edge to create
196 /// @return The created edge or NULL if an element with this ID already exists or
197 /// if input nodes are not found.
198 ///////////////////////////////////////////////////////////////////////////////
199
200 SMDS_MeshEdge* SMDS_Mesh::AddEdgeWithID(const SMDS_MeshNode * n1,
201                                         const SMDS_MeshNode * n2, 
202                                         int ID)
203 {
204   if ( !n1 || !n2 ) return 0;
205
206   if ( myEdges.Extent() % CHECKMEMORY_INTERVAL == 0 ) CheckMemory();
207
208   SMDS_MeshEdge * edge=new SMDS_MeshEdge(n1,n2);
209   if(myElementIDFactory->BindID(ID, edge)) {
210     SMDS_MeshNode *node1,*node2;
211     node1=const_cast<SMDS_MeshNode*>(n1);
212     node2=const_cast<SMDS_MeshNode*>(n2);
213     node1->AddInverseElement(edge);
214     node2->AddInverseElement(edge);             
215     myEdges.Add(edge);
216     myInfo.myNbEdges++;
217     return edge;
218   } 
219   else {
220     delete edge;
221     return NULL;
222   }
223 }
224
225 ///////////////////////////////////////////////////////////////////////////////
226 /// Add a triangle defined by its nodes. An ID is automatically affected to the
227 /// Created face
228 ///////////////////////////////////////////////////////////////////////////////
229
230 SMDS_MeshFace* SMDS_Mesh::AddFace(const SMDS_MeshNode * n1,
231                                   const SMDS_MeshNode * n2,
232                                   const SMDS_MeshNode * n3)
233 {
234   return SMDS_Mesh::AddFaceWithID(n1,n2,n3, myElementIDFactory->GetFreeID());
235 }
236
237 ///////////////////////////////////////////////////////////////////////////////
238 /// Add a triangle defined by its nodes IDs
239 ///////////////////////////////////////////////////////////////////////////////
240
241 SMDS_MeshFace* SMDS_Mesh::AddFaceWithID(int idnode1, int idnode2, int idnode3, int ID)
242 {
243   SMDS_MeshNode * node1 = (SMDS_MeshNode *)myNodeIDFactory->MeshElement(idnode1);
244   SMDS_MeshNode * node2 = (SMDS_MeshNode *)myNodeIDFactory->MeshElement(idnode2);
245   SMDS_MeshNode * node3 = (SMDS_MeshNode *)myNodeIDFactory->MeshElement(idnode3);
246   if(!node1 || !node2 || !node3) return NULL;
247   return SMDS_Mesh::AddFaceWithID(node1, node2, node3, ID);     
248 }
249
250 ///////////////////////////////////////////////////////////////////////////////
251 /// Add a triangle defined by its nodes
252 ///////////////////////////////////////////////////////////////////////////////
253
254 SMDS_MeshFace* SMDS_Mesh::AddFaceWithID(const SMDS_MeshNode * n1,
255                                         const SMDS_MeshNode * n2,
256                                         const SMDS_MeshNode * n3,
257                                         int ID)
258 {
259   SMDS_MeshFace * face=createTriangle(n1, n2, n3);
260
261   if (face && !registerElement(ID, face)) {
262     RemoveElement(face, false);
263     face = NULL;
264   }
265   return face;
266 }
267
268 ///////////////////////////////////////////////////////////////////////////////
269 /// Add a quadrangle defined by its nodes. An ID is automatically affected to the
270 /// created face
271 ///////////////////////////////////////////////////////////////////////////////
272
273 SMDS_MeshFace* SMDS_Mesh::AddFace(const SMDS_MeshNode * n1,
274                                   const SMDS_MeshNode * n2,
275                                   const SMDS_MeshNode * n3,
276                                   const SMDS_MeshNode * n4)
277 {
278   return SMDS_Mesh::AddFaceWithID(n1,n2,n3, n4, myElementIDFactory->GetFreeID());
279 }
280
281 ///////////////////////////////////////////////////////////////////////////////
282 /// Add a quadrangle defined by its nodes IDs
283 ///////////////////////////////////////////////////////////////////////////////
284
285 SMDS_MeshFace* SMDS_Mesh::AddFaceWithID(int idnode1, 
286                                         int idnode2, 
287                                         int idnode3,
288                                         int idnode4, 
289                                         int ID)
290 {
291   SMDS_MeshNode *node1, *node2, *node3, *node4;
292   node1 = (SMDS_MeshNode *)myNodeIDFactory->MeshElement(idnode1);
293   node2 = (SMDS_MeshNode *)myNodeIDFactory->MeshElement(idnode2);
294   node3 = (SMDS_MeshNode *)myNodeIDFactory->MeshElement(idnode3);
295   node4 = (SMDS_MeshNode *)myNodeIDFactory->MeshElement(idnode4);
296   if(!node1 || !node2 || !node3 || !node4) return NULL;
297   return SMDS_Mesh::AddFaceWithID(node1, node2, node3, node4, ID);      
298 }
299
300 ///////////////////////////////////////////////////////////////////////////////
301 /// Add a quadrangle defined by its nodes
302 ///////////////////////////////////////////////////////////////////////////////
303
304 SMDS_MeshFace* SMDS_Mesh::AddFaceWithID(const SMDS_MeshNode * n1,
305                                         const SMDS_MeshNode * n2,
306                                         const SMDS_MeshNode * n3,
307                                         const SMDS_MeshNode * n4,
308                                         int ID)
309 {
310   SMDS_MeshFace * face=createQuadrangle(n1, n2, n3, n4);
311
312   if (face && !registerElement(ID, face)) {
313     RemoveElement(face, false);
314     face = NULL;
315   }
316   return face;
317 }
318
319 ///////////////////////////////////////////////////////////////////////////////
320 /// Add a triangle defined by its edges. An ID is automatically assigned to the
321 /// Created face
322 ///////////////////////////////////////////////////////////////////////////////
323
324 SMDS_MeshFace* SMDS_Mesh::AddFace(const SMDS_MeshEdge * e1,
325                                   const SMDS_MeshEdge * e2,
326                                   const SMDS_MeshEdge * e3)
327 {
328   if (!hasConstructionEdges())
329     return NULL;
330   return AddFaceWithID(e1,e2,e3, myElementIDFactory->GetFreeID());
331 }
332
333 ///////////////////////////////////////////////////////////////////////////////
334 /// Add a triangle defined by its edges
335 ///////////////////////////////////////////////////////////////////////////////
336
337 SMDS_MeshFace* SMDS_Mesh::AddFaceWithID(const SMDS_MeshEdge * e1,
338                                         const SMDS_MeshEdge * e2,
339                                         const SMDS_MeshEdge * e3,
340                                         int ID)
341 {
342   if (!hasConstructionEdges())
343     return NULL;
344   if ( !e1 || !e2 || !e3 ) return 0;
345
346   if ( myFaces.Extent() % CHECKMEMORY_INTERVAL == 0 ) CheckMemory();
347
348   SMDS_MeshFace * face = new SMDS_FaceOfEdges(e1,e2,e3);
349   myFaces.Add(face);
350   myInfo.myNbTriangles++;
351
352   if (!registerElement(ID, face)) {
353     RemoveElement(face, false);
354     face = NULL;
355   }
356   return face;
357 }
358
359 ///////////////////////////////////////////////////////////////////////////////
360 /// Add a quadrangle defined by its edges. An ID is automatically assigned to the
361 /// Created face
362 ///////////////////////////////////////////////////////////////////////////////
363
364 SMDS_MeshFace* SMDS_Mesh::AddFace(const SMDS_MeshEdge * e1,
365                                   const SMDS_MeshEdge * e2,
366                                   const SMDS_MeshEdge * e3,
367                                   const SMDS_MeshEdge * e4)
368 {
369   if (!hasConstructionEdges())
370     return NULL;
371   return AddFaceWithID(e1,e2,e3,e4, myElementIDFactory->GetFreeID());
372 }
373
374 ///////////////////////////////////////////////////////////////////////////////
375 /// Add a quadrangle defined by its edges
376 ///////////////////////////////////////////////////////////////////////////////
377
378 SMDS_MeshFace* SMDS_Mesh::AddFaceWithID(const SMDS_MeshEdge * e1,
379                                         const SMDS_MeshEdge * e2,
380                                         const SMDS_MeshEdge * e3,
381                                         const SMDS_MeshEdge * e4,
382                                         int ID)
383 {
384   if (!hasConstructionEdges())
385     return NULL;
386   if ( !e1 || !e2 || !e3 || !e4 ) return 0;
387   if ( myFaces.Extent() % CHECKMEMORY_INTERVAL == 0 ) CheckMemory();
388   SMDS_MeshFace * face = new SMDS_FaceOfEdges(e1,e2,e3,e4);
389   myFaces.Add(face);
390   myInfo.myNbQuadrangles++;
391
392   if (!registerElement(ID, face))
393   {
394     RemoveElement(face, false);
395     face = NULL;
396   }
397   return face;
398 }
399
400 ///////////////////////////////////////////////////////////////////////////////
401 ///Create a new tetrahedron and add it to the mesh. 
402 ///@return The created tetrahedron 
403 ///////////////////////////////////////////////////////////////////////////////
404
405 SMDS_MeshVolume* SMDS_Mesh::AddVolume(const SMDS_MeshNode * n1,
406                                       const SMDS_MeshNode * n2, 
407                                       const SMDS_MeshNode * n3,
408                                       const SMDS_MeshNode * n4)
409 {
410   int ID = myElementIDFactory->GetFreeID();
411   SMDS_MeshVolume * v = SMDS_Mesh::AddVolumeWithID(n1, n2, n3, n4, ID);
412   if(v==NULL) myElementIDFactory->ReleaseID(ID);
413   return v;
414 }
415
416 ///////////////////////////////////////////////////////////////////////////////
417 ///Create a new tetrahedron and add it to the mesh. 
418 ///@param ID The ID of the new volume
419 ///@return The created tetrahedron or NULL if an element with this ID already exists
420 ///or if input nodes are not found.
421 ///////////////////////////////////////////////////////////////////////////////
422
423 SMDS_MeshVolume * SMDS_Mesh::AddVolumeWithID(int idnode1, 
424                                              int idnode2,
425                                              int idnode3, 
426                                              int idnode4, 
427                                              int ID)
428 {
429   SMDS_MeshNode *node1, *node2, *node3, *node4;
430   node1 = (SMDS_MeshNode *)myNodeIDFactory->MeshElement(idnode1);
431   node2 = (SMDS_MeshNode *)myNodeIDFactory->MeshElement(idnode2);
432   node3 = (SMDS_MeshNode *)myNodeIDFactory->MeshElement(idnode3);
433   node4 = (SMDS_MeshNode *)myNodeIDFactory->MeshElement(idnode4);
434   if(!node1 || !node2 || !node3 || !node4) return NULL;
435   return SMDS_Mesh::AddVolumeWithID(node1, node2, node3, node4, ID);
436 }
437         
438 ///////////////////////////////////////////////////////////////////////////////
439 ///Create a new tetrahedron and add it to the mesh. 
440 ///@param ID The ID of the new volume
441 ///@return The created tetrahedron 
442 ///////////////////////////////////////////////////////////////////////////////
443
444 SMDS_MeshVolume* SMDS_Mesh::AddVolumeWithID(const SMDS_MeshNode * n1,
445                                             const SMDS_MeshNode * n2,
446                                             const SMDS_MeshNode * n3,
447                                             const SMDS_MeshNode * n4,
448                                             int ID)
449 {
450   SMDS_MeshVolume* volume = 0;
451   if ( !n1 || !n2 || !n3 || !n4) return volume;
452   if ( myVolumes.Extent() % CHECKMEMORY_INTERVAL == 0 ) CheckMemory();
453   if(hasConstructionFaces()) {
454     SMDS_MeshFace * f1=FindFaceOrCreate(n1,n2,n3);
455     SMDS_MeshFace * f2=FindFaceOrCreate(n1,n2,n4);
456     SMDS_MeshFace * f3=FindFaceOrCreate(n1,n3,n4);
457     SMDS_MeshFace * f4=FindFaceOrCreate(n2,n3,n4);
458     volume=new SMDS_VolumeOfFaces(f1,f2,f3,f4);
459     myVolumes.Add(volume);
460     myInfo.myNbTetras++;
461   }
462   else if(hasConstructionEdges()) {
463     MESSAGE("Error : Not implemented");
464     return NULL;
465   }
466   else {
467     volume=new SMDS_VolumeOfNodes(n1,n2,n3,n4);
468     myVolumes.Add(volume);
469     myInfo.myNbTetras++;
470   }
471
472   if (!registerElement(ID, volume)) {
473     RemoveElement(volume, false);
474     volume = NULL;
475   }
476   return volume;
477 }
478
479 ///////////////////////////////////////////////////////////////////////////////
480 ///Create a new pyramid and add it to the mesh. 
481 ///Nodes 1,2,3 and 4 define the base of the pyramid
482 ///@return The created pyramid 
483 ///////////////////////////////////////////////////////////////////////////////
484
485 SMDS_MeshVolume* SMDS_Mesh::AddVolume(const SMDS_MeshNode * n1,
486                                       const SMDS_MeshNode * n2, 
487                                       const SMDS_MeshNode * n3,
488                                       const SMDS_MeshNode * n4, 
489                                       const SMDS_MeshNode * n5)
490 {
491   int ID = myElementIDFactory->GetFreeID();
492   SMDS_MeshVolume * v = SMDS_Mesh::AddVolumeWithID(n1, n2, n3, n4, n5, ID);
493   if(v==NULL) myElementIDFactory->ReleaseID(ID);
494   return v;
495 }
496
497 ///////////////////////////////////////////////////////////////////////////////
498 ///Create a new pyramid and add it to the mesh. 
499 ///Nodes 1,2,3 and 4 define the base of the pyramid
500 ///@param ID The ID of the new volume
501 ///@return The created pyramid or NULL if an element with this ID already exists
502 ///or if input nodes are not found.
503 ///////////////////////////////////////////////////////////////////////////////
504
505 SMDS_MeshVolume * SMDS_Mesh::AddVolumeWithID(int idnode1, 
506                                              int idnode2,
507                                              int idnode3, 
508                                              int idnode4, 
509                                              int idnode5, 
510                                              int ID)
511 {
512   SMDS_MeshNode *node1, *node2, *node3, *node4, *node5;
513   node1 = (SMDS_MeshNode *)myNodeIDFactory->MeshElement(idnode1);
514   node2 = (SMDS_MeshNode *)myNodeIDFactory->MeshElement(idnode2);
515   node3 = (SMDS_MeshNode *)myNodeIDFactory->MeshElement(idnode3);
516   node4 = (SMDS_MeshNode *)myNodeIDFactory->MeshElement(idnode4);
517   node5 = (SMDS_MeshNode *)myNodeIDFactory->MeshElement(idnode5);
518   if(!node1 || !node2 || !node3 || !node4 || !node5) return NULL;
519   return SMDS_Mesh::AddVolumeWithID(node1, node2, node3, node4, node5, ID);
520 }
521         
522 ///////////////////////////////////////////////////////////////////////////////
523 ///Create a new pyramid and add it to the mesh.
524 ///Nodes 1,2,3 and 4 define the base of the pyramid
525 ///@param ID The ID of the new volume
526 ///@return The created pyramid
527 ///////////////////////////////////////////////////////////////////////////////
528
529 SMDS_MeshVolume* SMDS_Mesh::AddVolumeWithID(const SMDS_MeshNode * n1,
530                                             const SMDS_MeshNode * n2,
531                                             const SMDS_MeshNode * n3,
532                                             const SMDS_MeshNode * n4,
533                                             const SMDS_MeshNode * n5,
534                                             int ID)
535 {
536   SMDS_MeshVolume* volume = 0;
537   if ( !n1 || !n2 || !n3 || !n4 || !n5) return volume;
538   if ( myVolumes.Extent() % CHECKMEMORY_INTERVAL == 0 ) CheckMemory();
539   if(hasConstructionFaces()) {
540     SMDS_MeshFace * f1=FindFaceOrCreate(n1,n2,n3,n4);
541     SMDS_MeshFace * f2=FindFaceOrCreate(n1,n2,n5);
542     SMDS_MeshFace * f3=FindFaceOrCreate(n2,n3,n5);
543     SMDS_MeshFace * f4=FindFaceOrCreate(n3,n4,n5);
544     volume=new SMDS_VolumeOfFaces(f1,f2,f3,f4);
545     myVolumes.Add(volume);
546     myInfo.myNbPyramids++;
547   }
548   else if(hasConstructionEdges()) {
549     MESSAGE("Error : Not implemented");
550     return NULL;
551   }
552   else {
553     volume=new SMDS_VolumeOfNodes(n1,n2,n3,n4,n5);
554     myVolumes.Add(volume);
555     myInfo.myNbPyramids++;
556   }
557
558   if (!registerElement(ID, volume)) {
559     RemoveElement(volume, false);
560     volume = NULL;
561   }
562   return volume;
563 }
564
565 ///////////////////////////////////////////////////////////////////////////////
566 ///Create a new prism and add it to the mesh. 
567 ///Nodes 1,2,3 is a triangle and 1,2,5,4 a quadrangle.
568 ///@return The created prism 
569 ///////////////////////////////////////////////////////////////////////////////
570
571 SMDS_MeshVolume* SMDS_Mesh::AddVolume(const SMDS_MeshNode * n1,
572                                       const SMDS_MeshNode * n2, 
573                                       const SMDS_MeshNode * n3,
574                                       const SMDS_MeshNode * n4, 
575                                       const SMDS_MeshNode * n5,
576                                       const SMDS_MeshNode * n6)
577 {
578   int ID = myElementIDFactory->GetFreeID();
579   SMDS_MeshVolume * v = SMDS_Mesh::AddVolumeWithID(n1, n2, n3, n4, n5, n6, ID);
580   if(v==NULL) myElementIDFactory->ReleaseID(ID);
581   return v;
582 }
583
584 ///////////////////////////////////////////////////////////////////////////////
585 ///Create a new prism and add it to the mesh. 
586 ///Nodes 1,2,3 is a triangle and 1,2,5,4 a quadrangle.
587 ///@param ID The ID of the new volume
588 ///@return The created prism or NULL if an element with this ID already exists
589 ///or if input nodes are not found.
590 ///////////////////////////////////////////////////////////////////////////////
591
592 SMDS_MeshVolume * SMDS_Mesh::AddVolumeWithID(int idnode1, 
593                                              int idnode2,
594                                              int idnode3, 
595                                              int idnode4, 
596                                              int idnode5, 
597                                              int idnode6, 
598                                              int ID)
599 {
600   SMDS_MeshNode *node1, *node2, *node3, *node4, *node5, *node6;
601   node1 = (SMDS_MeshNode *)myNodeIDFactory->MeshElement(idnode1);
602   node2 = (SMDS_MeshNode *)myNodeIDFactory->MeshElement(idnode2);
603   node3 = (SMDS_MeshNode *)myNodeIDFactory->MeshElement(idnode3);
604   node4 = (SMDS_MeshNode *)myNodeIDFactory->MeshElement(idnode4);
605   node5 = (SMDS_MeshNode *)myNodeIDFactory->MeshElement(idnode5);
606   node6 = (SMDS_MeshNode *)myNodeIDFactory->MeshElement(idnode6);
607   if(!node1 || !node2 || !node3 || !node4 || !node5 || !node6) return NULL;
608   return SMDS_Mesh::AddVolumeWithID(node1, node2, node3, node4, node5, node6, ID);
609 }
610         
611 ///////////////////////////////////////////////////////////////////////////////
612 ///Create a new prism and add it to the mesh.
613 ///Nodes 1,2,3 is a triangle and 1,2,5,4 a quadrangle.
614 ///@param ID The ID of the new volume
615 ///@return The created prism
616 ///////////////////////////////////////////////////////////////////////////////
617
618 SMDS_MeshVolume* SMDS_Mesh::AddVolumeWithID(const SMDS_MeshNode * n1,
619                                             const SMDS_MeshNode * n2,
620                                             const SMDS_MeshNode * n3,
621                                             const SMDS_MeshNode * n4,
622                                             const SMDS_MeshNode * n5,
623                                             const SMDS_MeshNode * n6,
624                                             int ID)
625 {
626   SMDS_MeshVolume* volume = 0;
627   if ( !n1 || !n2 || !n3 || !n4 || !n5 || !n6) return volume;
628   if ( myVolumes.Extent() % CHECKMEMORY_INTERVAL == 0 ) CheckMemory();
629   if(hasConstructionFaces()) {
630     SMDS_MeshFace * f1=FindFaceOrCreate(n1,n2,n3);
631     SMDS_MeshFace * f2=FindFaceOrCreate(n4,n5,n6);
632     SMDS_MeshFace * f3=FindFaceOrCreate(n1,n4,n5,n2);
633     SMDS_MeshFace * f4=FindFaceOrCreate(n2,n5,n6,n3);
634     SMDS_MeshFace * f5=FindFaceOrCreate(n3,n6,n4,n1);
635     volume=new SMDS_VolumeOfFaces(f1,f2,f3,f4,f5);
636     myVolumes.Add(volume);
637     myInfo.myNbPrisms++;
638   }
639   else if(hasConstructionEdges()) {
640     MESSAGE("Error : Not implemented");
641     return NULL;
642   }
643   else {
644     volume=new SMDS_VolumeOfNodes(n1,n2,n3,n4,n5,n6);
645     myVolumes.Add(volume);
646     myInfo.myNbPrisms++;
647   }
648
649   if (!registerElement(ID, volume)) {
650     RemoveElement(volume, false);
651     volume = NULL;
652   }
653   return volume;
654 }
655
656 ///////////////////////////////////////////////////////////////////////////////
657 ///Create a new hexahedron and add it to the mesh. 
658 ///Nodes 1,2,3,4 and 5,6,7,8 are quadrangle and 5,1 and 7,3 are an edges.
659 ///@return The created hexahedron 
660 ///////////////////////////////////////////////////////////////////////////////
661
662 SMDS_MeshVolume* SMDS_Mesh::AddVolume(const SMDS_MeshNode * n1,
663                                       const SMDS_MeshNode * n2, 
664                                       const SMDS_MeshNode * n3,
665                                       const SMDS_MeshNode * n4, 
666                                       const SMDS_MeshNode * n5,
667                                       const SMDS_MeshNode * n6, 
668                                       const SMDS_MeshNode * n7,
669                                       const SMDS_MeshNode * n8)
670 {
671   int ID = myElementIDFactory->GetFreeID();
672   SMDS_MeshVolume * v = SMDS_Mesh::AddVolumeWithID(n1, n2, n3, n4, n5, n6, n7, n8, ID);
673   if(v==NULL) myElementIDFactory->ReleaseID(ID);
674   return v;
675 }
676
677 ///////////////////////////////////////////////////////////////////////////////
678 ///Create a new hexahedron and add it to the mesh. 
679 ///Nodes 1,2,3,4 and 5,6,7,8 are quadrangle and 5,1 and 7,3 are an edges.
680 ///@param ID The ID of the new volume
681 ///@return The created hexahedron or NULL if an element with this ID already
682 ///exists or if input nodes are not found.
683 ///////////////////////////////////////////////////////////////////////////////
684
685 SMDS_MeshVolume * SMDS_Mesh::AddVolumeWithID(int idnode1, 
686                                              int idnode2,
687                                              int idnode3, 
688                                              int idnode4, 
689                                              int idnode5, 
690                                              int idnode6, 
691                                              int idnode7,
692                                              int idnode8, 
693                                              int ID)
694 {
695   SMDS_MeshNode *node1, *node2, *node3, *node4, *node5, *node6, *node7, *node8;
696   node1 = (SMDS_MeshNode *)myNodeIDFactory->MeshElement(idnode1);
697   node2 = (SMDS_MeshNode *)myNodeIDFactory->MeshElement(idnode2);
698   node3 = (SMDS_MeshNode *)myNodeIDFactory->MeshElement(idnode3);
699   node4 = (SMDS_MeshNode *)myNodeIDFactory->MeshElement(idnode4);
700   node5 = (SMDS_MeshNode *)myNodeIDFactory->MeshElement(idnode5);
701   node6 = (SMDS_MeshNode *)myNodeIDFactory->MeshElement(idnode6);
702   node7 = (SMDS_MeshNode *)myNodeIDFactory->MeshElement(idnode7);
703   node8 = (SMDS_MeshNode *)myNodeIDFactory->MeshElement(idnode8);
704   if(!node1 || !node2 || !node3 || !node4 || !node5 || !node6 || !node7 || !node8)
705     return NULL;
706   return SMDS_Mesh::AddVolumeWithID(node1, node2, node3, node4, node5, node6,
707                                     node7, node8, ID);
708 }
709         
710 ///////////////////////////////////////////////////////////////////////////////
711 ///Create a new hexahedron and add it to the mesh.
712 ///Nodes 1,2,3,4 and 5,6,7,8 are quadrangle and 5,1 and 7,3 are an edges.
713 ///@param ID The ID of the new volume
714 ///@return The created prism or NULL if an element with this ID already exists
715 ///or if input nodes are not found.
716 ///////////////////////////////////////////////////////////////////////////////
717
718 SMDS_MeshVolume* SMDS_Mesh::AddVolumeWithID(const SMDS_MeshNode * n1,
719                                             const SMDS_MeshNode * n2,
720                                             const SMDS_MeshNode * n3,
721                                             const SMDS_MeshNode * n4,
722                                             const SMDS_MeshNode * n5,
723                                             const SMDS_MeshNode * n6,
724                                             const SMDS_MeshNode * n7,
725                                             const SMDS_MeshNode * n8,
726                                             int ID)
727 {
728   SMDS_MeshVolume* volume = 0;
729   if ( !n1 || !n2 || !n3 || !n4 || !n5 || !n6 || !n7 || !n8) return volume;
730   if ( myVolumes.Extent() % CHECKMEMORY_INTERVAL == 0 ) CheckMemory();
731   if(hasConstructionFaces()) {
732     SMDS_MeshFace * f1=FindFaceOrCreate(n1,n2,n3,n4);
733     SMDS_MeshFace * f2=FindFaceOrCreate(n5,n6,n7,n8);
734     SMDS_MeshFace * f3=FindFaceOrCreate(n1,n4,n8,n5);
735     SMDS_MeshFace * f4=FindFaceOrCreate(n1,n2,n6,n5);
736     SMDS_MeshFace * f5=FindFaceOrCreate(n2,n3,n7,n6);
737     SMDS_MeshFace * f6=FindFaceOrCreate(n3,n4,n8,n7);
738     volume=new SMDS_VolumeOfFaces(f1,f2,f3,f4,f5,f6);
739     myVolumes.Add(volume);
740     myInfo.myNbHexas++;
741   }
742   else if(hasConstructionEdges()) {
743     MESSAGE("Error : Not implemented");
744     return NULL;
745   }
746   else {
747 //    volume=new SMDS_HexahedronOfNodes(n1,n2,n3,n4,n5,n6,n7,n8);
748     volume=new SMDS_VolumeOfNodes(n1,n2,n3,n4,n5,n6,n7,n8);
749     myVolumes.Add(volume);
750     myInfo.myNbHexas++;
751   }
752
753   if (!registerElement(ID, volume)) {
754     RemoveElement(volume, false);
755     volume = NULL;
756   }
757   return volume;
758 }
759
760 ///////////////////////////////////////////////////////////////////////////////
761 ///Create a new tetrahedron defined by its faces and add it to the mesh.
762 ///@return The created tetrahedron
763 ///////////////////////////////////////////////////////////////////////////////
764
765 SMDS_MeshVolume* SMDS_Mesh::AddVolume(const SMDS_MeshFace * f1,
766                                       const SMDS_MeshFace * f2,
767                                       const SMDS_MeshFace * f3,
768                                       const SMDS_MeshFace * f4)
769 {
770   if (!hasConstructionFaces())
771     return NULL;
772   return AddVolumeWithID(f1,f2,f3,f4, myElementIDFactory->GetFreeID());
773 }
774
775 ///////////////////////////////////////////////////////////////////////////////
776 ///Create a new tetrahedron defined by its faces and add it to the mesh.
777 ///@param ID The ID of the new volume
778 ///@return The created tetrahedron 
779 ///////////////////////////////////////////////////////////////////////////////
780
781 SMDS_MeshVolume* SMDS_Mesh::AddVolumeWithID(const SMDS_MeshFace * f1,
782                                             const SMDS_MeshFace * f2,
783                                             const SMDS_MeshFace * f3,
784                                             const SMDS_MeshFace * f4,
785                                             int ID)
786 {
787   if (!hasConstructionFaces())
788     return NULL;
789   if ( !f1 || !f2 || !f3 || !f4) return 0;
790   if ( myVolumes.Extent() % CHECKMEMORY_INTERVAL == 0 ) CheckMemory();
791   SMDS_MeshVolume * volume = new SMDS_VolumeOfFaces(f1,f2,f3,f4);
792   myVolumes.Add(volume);
793   myInfo.myNbTetras++;
794
795   if (!registerElement(ID, volume)) {
796     RemoveElement(volume, false);
797     volume = NULL;
798   }
799   return volume;
800 }
801
802 ///////////////////////////////////////////////////////////////////////////////
803 ///Create a new pyramid defined by its faces and add it to the mesh.
804 ///@return The created pyramid
805 ///////////////////////////////////////////////////////////////////////////////
806
807 SMDS_MeshVolume* SMDS_Mesh::AddVolume(const SMDS_MeshFace * f1,
808                                       const SMDS_MeshFace * f2,
809                                       const SMDS_MeshFace * f3,
810                                       const SMDS_MeshFace * f4,
811                                       const SMDS_MeshFace * f5)
812 {
813   if (!hasConstructionFaces())
814     return NULL;
815   return AddVolumeWithID(f1,f2,f3,f4,f5, myElementIDFactory->GetFreeID());
816 }
817
818 ///////////////////////////////////////////////////////////////////////////////
819 ///Create a new pyramid defined by its faces and add it to the mesh.
820 ///@param ID The ID of the new volume
821 ///@return The created pyramid 
822 ///////////////////////////////////////////////////////////////////////////////
823
824 SMDS_MeshVolume* SMDS_Mesh::AddVolumeWithID(const SMDS_MeshFace * f1,
825                                             const SMDS_MeshFace * f2,
826                                             const SMDS_MeshFace * f3,
827                                             const SMDS_MeshFace * f4,
828                                             const SMDS_MeshFace * f5,
829                                             int ID)
830 {
831   if (!hasConstructionFaces())
832     return NULL;
833   if ( !f1 || !f2 || !f3 || !f4 || !f5) return 0;
834   if ( myVolumes.Extent() % CHECKMEMORY_INTERVAL == 0 ) CheckMemory();
835   SMDS_MeshVolume * volume = new SMDS_VolumeOfFaces(f1,f2,f3,f4,f5);
836   myVolumes.Add(volume);
837   myInfo.myNbPyramids++;
838
839   if (!registerElement(ID, volume)) {
840     RemoveElement(volume, false);
841     volume = NULL;
842   }
843   return volume;
844 }
845
846 ///////////////////////////////////////////////////////////////////////////////
847 ///Create a new prism defined by its faces and add it to the mesh.
848 ///@return The created prism
849 ///////////////////////////////////////////////////////////////////////////////
850
851 SMDS_MeshVolume* SMDS_Mesh::AddVolume(const SMDS_MeshFace * f1,
852                                       const SMDS_MeshFace * f2,
853                                       const SMDS_MeshFace * f3,
854                                       const SMDS_MeshFace * f4,
855                                       const SMDS_MeshFace * f5,
856                                       const SMDS_MeshFace * f6)
857 {
858   if (!hasConstructionFaces())
859     return NULL;
860   return AddVolumeWithID(f1,f2,f3,f4,f5,f6, myElementIDFactory->GetFreeID());
861 }
862
863 ///////////////////////////////////////////////////////////////////////////////
864 ///Create a new prism defined by its faces and add it to the mesh.
865 ///@param ID The ID of the new volume
866 ///@return The created prism 
867 ///////////////////////////////////////////////////////////////////////////////
868
869 SMDS_MeshVolume* SMDS_Mesh::AddVolumeWithID(const SMDS_MeshFace * f1,
870                                             const SMDS_MeshFace * f2,
871                                             const SMDS_MeshFace * f3,
872                                             const SMDS_MeshFace * f4,
873                                             const SMDS_MeshFace * f5,
874                                             const SMDS_MeshFace * f6,
875                                             int ID)
876 {
877   if (!hasConstructionFaces())
878     return NULL;
879   if ( !f1 || !f2 || !f3 || !f4 || !f5 || !f6) return 0;
880   if ( myVolumes.Extent() % CHECKMEMORY_INTERVAL == 0 ) CheckMemory();
881   SMDS_MeshVolume * volume = new SMDS_VolumeOfFaces(f1,f2,f3,f4,f5,f6);
882   myVolumes.Add(volume);
883   myInfo.myNbPrisms++;
884
885   if (!registerElement(ID, volume)) {
886     RemoveElement(volume, false);
887     volume = NULL;
888   }
889   return volume;
890 }
891
892 ///////////////////////////////////////////////////////////////////////////////
893 /// Add a polygon defined by its nodes IDs
894 ///////////////////////////////////////////////////////////////////////////////
895
896 SMDS_MeshFace* SMDS_Mesh::AddPolygonalFaceWithID (std::vector<int> nodes_ids,
897                                                   const int        ID)
898 {
899   int nbNodes = nodes_ids.size();
900   std::vector<const SMDS_MeshNode*> nodes (nbNodes);
901   for (int i = 0; i < nbNodes; i++) {
902     nodes[i] = (SMDS_MeshNode *)myNodeIDFactory->MeshElement(nodes_ids[i]);
903     if (!nodes[i]) return NULL;
904   }
905   return SMDS_Mesh::AddPolygonalFaceWithID(nodes, ID);  
906 }
907
908 ///////////////////////////////////////////////////////////////////////////////
909 /// Add a polygon defined by its nodes
910 ///////////////////////////////////////////////////////////////////////////////
911
912 SMDS_MeshFace* SMDS_Mesh::AddPolygonalFaceWithID
913                           (std::vector<const SMDS_MeshNode*> nodes,
914                            const int                         ID)
915 {
916   SMDS_MeshFace * face;
917
918   if ( myFaces.Extent() % CHECKMEMORY_INTERVAL == 0 ) CheckMemory();
919   if (hasConstructionEdges())
920   {
921     MESSAGE("Error : Not implemented");
922     return NULL;
923   }
924   else
925   {
926     for ( int i = 0; i < nodes.size(); ++i )
927       if ( !nodes[ i ] ) return 0;
928     face = new SMDS_PolygonalFaceOfNodes(nodes);
929     myFaces.Add(face);
930     myInfo.myNbPolygons++;
931   }
932
933   if (!registerElement(ID, face)) {
934     RemoveElement(face, false);
935     face = NULL;
936   }
937   return face;
938 }
939
940 ///////////////////////////////////////////////////////////////////////////////
941 /// Add a polygon defined by its nodes.
942 /// An ID is automatically affected to the created face.
943 ///////////////////////////////////////////////////////////////////////////////
944
945 SMDS_MeshFace* SMDS_Mesh::AddPolygonalFace (std::vector<const SMDS_MeshNode*> nodes)
946 {
947   return SMDS_Mesh::AddPolygonalFaceWithID(nodes, myElementIDFactory->GetFreeID());
948 }
949
950 ///////////////////////////////////////////////////////////////////////////////
951 /// Create a new polyhedral volume and add it to the mesh. 
952 /// @param ID The ID of the new volume
953 /// @return The created volume or NULL if an element with this ID already exists
954 /// or if input nodes are not found.
955 ///////////////////////////////////////////////////////////////////////////////
956
957 SMDS_MeshVolume * SMDS_Mesh::AddPolyhedralVolumeWithID
958                              (std::vector<int> nodes_ids,
959                               std::vector<int> quantities,
960                               const int        ID)
961 {
962   int nbNodes = nodes_ids.size();
963   std::vector<const SMDS_MeshNode*> nodes (nbNodes);
964   for (int i = 0; i < nbNodes; i++) {
965     nodes[i] = (SMDS_MeshNode *)myNodeIDFactory->MeshElement(nodes_ids[i]);
966     if (!nodes[i]) return NULL;
967   }
968   return SMDS_Mesh::AddPolyhedralVolumeWithID(nodes, quantities, ID);
969 }
970
971 ///////////////////////////////////////////////////////////////////////////////
972 /// Create a new polyhedral volume and add it to the mesh. 
973 /// @param ID The ID of the new volume
974 /// @return The created  volume
975 ///////////////////////////////////////////////////////////////////////////////
976
977 SMDS_MeshVolume* SMDS_Mesh::AddPolyhedralVolumeWithID
978                             (std::vector<const SMDS_MeshNode*> nodes,
979                              std::vector<int>                  quantities,
980                              const int                         ID)
981 {
982   SMDS_MeshVolume* volume;
983   if ( myVolumes.Extent() % CHECKMEMORY_INTERVAL == 0 ) CheckMemory();
984   if (hasConstructionFaces()) {
985     MESSAGE("Error : Not implemented");
986     return NULL;
987   } else if (hasConstructionEdges()) {
988     MESSAGE("Error : Not implemented");
989     return NULL;
990   } else {
991     for ( int i = 0; i < nodes.size(); ++i )
992       if ( !nodes[ i ] ) return 0;
993     volume = new SMDS_PolyhedralVolumeOfNodes(nodes, quantities);
994     myVolumes.Add(volume);
995     myInfo.myNbPolyhedrons++;
996   }
997
998   if (!registerElement(ID, volume)) {
999     RemoveElement(volume, false);
1000     volume = NULL;
1001   }
1002   return volume;
1003 }
1004
1005 ///////////////////////////////////////////////////////////////////////////////
1006 /// Create a new polyhedral volume and add it to the mesh. 
1007 /// @return The created  volume
1008 ///////////////////////////////////////////////////////////////////////////////
1009
1010 SMDS_MeshVolume* SMDS_Mesh::AddPolyhedralVolume
1011                             (std::vector<const SMDS_MeshNode*> nodes,
1012                              std::vector<int>                  quantities)
1013 {
1014   int ID = myElementIDFactory->GetFreeID();
1015   SMDS_MeshVolume * v = SMDS_Mesh::AddPolyhedralVolumeWithID(nodes, quantities, ID);
1016   if (v == NULL) myElementIDFactory->ReleaseID(ID);
1017   return v;
1018 }
1019
1020 ///////////////////////////////////////////////////////////////////////////////
1021 /// Registers element with the given ID, maintains inverse connections
1022 ///////////////////////////////////////////////////////////////////////////////
1023 bool SMDS_Mesh::registerElement(int ID, SMDS_MeshElement * element)
1024 {
1025   if (myElementIDFactory->BindID(ID, element)) {
1026     SMDS_ElemIteratorPtr it = element->nodesIterator();
1027     while (it->more()) {
1028       SMDS_MeshNode *node = static_cast<SMDS_MeshNode*>
1029         (const_cast<SMDS_MeshElement*>(it->next()));
1030       node->AddInverseElement(element);
1031     }
1032     return true;
1033   }
1034   return false;
1035 }
1036
1037 ///////////////////////////////////////////////////////////////////////////////
1038 /// Return the node whose ID is 'ID'.
1039 ///////////////////////////////////////////////////////////////////////////////
1040 const SMDS_MeshNode * SMDS_Mesh::FindNode(int ID) const
1041 {
1042   return (const SMDS_MeshNode *)myNodeIDFactory->MeshElement(ID);
1043 }
1044
1045 ///////////////////////////////////////////////////////////////////////////////
1046 ///Create a triangle and add it to the current mesh. This methode do not bind a
1047 ///ID to the create triangle.
1048 ///////////////////////////////////////////////////////////////////////////////
1049 SMDS_MeshFace * SMDS_Mesh::createTriangle(const SMDS_MeshNode * node1,
1050                                           const SMDS_MeshNode * node2,
1051                                           const SMDS_MeshNode * node3)
1052 {
1053   if ( !node1 || !node2 || !node3) return 0;
1054   if ( myFaces.Extent() % CHECKMEMORY_INTERVAL == 0 ) CheckMemory();
1055   if(hasConstructionEdges())
1056   {
1057     SMDS_MeshEdge *edge1, *edge2, *edge3;
1058     edge1=FindEdgeOrCreate(node1,node2);
1059     edge2=FindEdgeOrCreate(node2,node3);
1060     edge3=FindEdgeOrCreate(node3,node1);
1061
1062     SMDS_MeshFace * face = new SMDS_FaceOfEdges(edge1,edge2,edge3);
1063     myFaces.Add(face);
1064     myInfo.myNbTriangles++;
1065     return face;
1066   }
1067   else
1068   {
1069     SMDS_MeshFace * face = new SMDS_FaceOfNodes(node1,node2,node3);
1070     myFaces.Add(face);
1071     myInfo.myNbTriangles++;
1072     return face;
1073   }
1074 }
1075
1076 ///////////////////////////////////////////////////////////////////////////////
1077 ///Create a quadrangle and add it to the current mesh. This methode do not bind
1078 ///a ID to the create triangle.
1079 ///////////////////////////////////////////////////////////////////////////////
1080 SMDS_MeshFace * SMDS_Mesh::createQuadrangle(const SMDS_MeshNode * node1,
1081                                             const SMDS_MeshNode * node2,
1082                                             const SMDS_MeshNode * node3,
1083                                             const SMDS_MeshNode * node4)
1084 {
1085   if ( !node1 || !node2 || !node3 || !node4 ) return 0;
1086   if ( myFaces.Extent() % CHECKMEMORY_INTERVAL == 0 ) CheckMemory();
1087   if(hasConstructionEdges())
1088   {
1089     SMDS_MeshEdge *edge1, *edge2, *edge3, *edge4;
1090     edge1=FindEdgeOrCreate(node1,node2);
1091     edge2=FindEdgeOrCreate(node2,node3);
1092     edge3=FindEdgeOrCreate(node3,node4);
1093     edge4=FindEdgeOrCreate(node4,node1);
1094
1095     SMDS_MeshFace * face = new SMDS_FaceOfEdges(edge1,edge2,edge3,edge4);
1096     myFaces.Add(face);
1097     myInfo.myNbQuadrangles++;
1098     return face;
1099   }
1100   else
1101   {
1102     SMDS_MeshFace * face = new SMDS_FaceOfNodes(node1,node2,node3,node4);
1103     myFaces.Add(face);
1104     myInfo.myNbQuadrangles++;
1105     return face;
1106   }
1107 }
1108
1109 ///////////////////////////////////////////////////////////////////////////////
1110 /// Remove a node and all the elements which own this node
1111 ///////////////////////////////////////////////////////////////////////////////
1112
1113 void SMDS_Mesh::RemoveNode(const SMDS_MeshNode * node)
1114 {
1115         RemoveElement(node, true);
1116 }
1117
1118 ///////////////////////////////////////////////////////////////////////////////
1119 /// Remove an edge and all the elements which own this edge
1120 ///////////////////////////////////////////////////////////////////////////////
1121
1122 void SMDS_Mesh::RemoveEdge(const SMDS_MeshEdge * edge)
1123 {
1124         RemoveElement(edge,true);
1125 }
1126
1127 ///////////////////////////////////////////////////////////////////////////////
1128 /// Remove an face and all the elements which own this face
1129 ///////////////////////////////////////////////////////////////////////////////
1130
1131 void SMDS_Mesh::RemoveFace(const SMDS_MeshFace * face)
1132 {
1133         RemoveElement(face, true);
1134 }
1135
1136 ///////////////////////////////////////////////////////////////////////////////
1137 /// Remove a volume
1138 ///////////////////////////////////////////////////////////////////////////////
1139
1140 void SMDS_Mesh::RemoveVolume(const SMDS_MeshVolume * volume)
1141 {
1142         RemoveElement(volume, true);
1143 }
1144
1145 //=======================================================================
1146 //function : RemoveFromParent
1147 //purpose  :
1148 //=======================================================================
1149
1150 bool SMDS_Mesh::RemoveFromParent()
1151 {
1152         if (myParent==NULL) return false;
1153         else return (myParent->RemoveSubMesh(this));
1154 }
1155
1156 //=======================================================================
1157 //function : RemoveSubMesh
1158 //purpose  :
1159 //=======================================================================
1160
1161 bool SMDS_Mesh::RemoveSubMesh(const SMDS_Mesh * aMesh)
1162 {
1163         bool found = false;
1164
1165         list<SMDS_Mesh *>::iterator itmsh=myChildren.begin();
1166         for (; itmsh!=myChildren.end() && !found; itmsh++)
1167         {
1168                 SMDS_Mesh * submesh = *itmsh;
1169                 if (submesh == aMesh)
1170                 {
1171                         found = true;
1172                         myChildren.erase(itmsh);
1173                 }
1174         }
1175
1176         return found;
1177 }
1178
1179 //=======================================================================
1180 //function : ChangeElementNodes
1181 //purpose  : 
1182 //=======================================================================
1183
1184 bool SMDS_Mesh::ChangeElementNodes(const SMDS_MeshElement * element,
1185                                    const SMDS_MeshNode    * nodes[],
1186                                    const int                nbnodes)
1187 {
1188   // keep current nodes of elem
1189   set<const SMDS_MeshElement*> oldNodes;
1190   SMDS_ElemIteratorPtr itn = element->nodesIterator();
1191   while(itn->more())
1192     oldNodes.insert(  itn->next() );
1193
1194   if ( !element->IsPoly() )
1195     myInfo.remove( element ); // element may change type
1196
1197   // change nodes
1198   bool Ok = false;
1199   SMDS_MeshElement* elem = const_cast<SMDS_MeshElement*>(element);
1200   switch ( elem->GetType() )
1201   {
1202   case SMDSAbs_Edge: {
1203     if ( nbnodes == 2 ) {
1204       if ( SMDS_MeshEdge* edge = dynamic_cast<SMDS_MeshEdge*>( elem ))
1205         Ok = edge->ChangeNodes( nodes[0], nodes[1] );
1206     }
1207     else if ( nbnodes == 3 ) {
1208       if ( SMDS_QuadraticEdge* edge = dynamic_cast<SMDS_QuadraticEdge*>( elem ))
1209         Ok = edge->ChangeNodes( nodes[0], nodes[1], nodes[2] );
1210     }
1211     break;
1212   }
1213   case SMDSAbs_Face: {
1214     if ( SMDS_FaceOfNodes* face = dynamic_cast<SMDS_FaceOfNodes*>( elem ))
1215       Ok = face->ChangeNodes( nodes, nbnodes );
1216     else
1217       if ( SMDS_QuadraticFaceOfNodes* QF = dynamic_cast<SMDS_QuadraticFaceOfNodes*>( elem ))
1218         Ok = QF->ChangeNodes( nodes, nbnodes );
1219       else
1220         if (SMDS_PolygonalFaceOfNodes* face = dynamic_cast<SMDS_PolygonalFaceOfNodes*>(elem))
1221           Ok = face->ChangeNodes(nodes, nbnodes);
1222     break;
1223   }
1224   case SMDSAbs_Volume: {
1225     if ( SMDS_VolumeOfNodes* vol = dynamic_cast<SMDS_VolumeOfNodes*>( elem ))
1226       Ok = vol->ChangeNodes( nodes, nbnodes );
1227     else 
1228       if ( SMDS_QuadraticVolumeOfNodes* QV = dynamic_cast<SMDS_QuadraticVolumeOfNodes*>( elem ))
1229         Ok = QV->ChangeNodes( nodes, nbnodes );
1230     break;
1231   }
1232   default:
1233     MESSAGE ( "WRONG ELEM TYPE");
1234   }
1235
1236   if ( Ok ) { // update InverseElements
1237
1238     set<const SMDS_MeshElement*>::iterator it;
1239
1240     // AddInverseElement to new nodes
1241     for ( int i = 0; i < nbnodes; i++ ) {
1242       it = oldNodes.find( nodes[i] );
1243       if ( it == oldNodes.end() )
1244         // new node
1245         const_cast<SMDS_MeshNode*>( nodes[i] )->AddInverseElement( elem );
1246       else
1247         // remove from oldNodes a node that remains in elem
1248         oldNodes.erase( it );
1249     }
1250     // RemoveInverseElement from the nodes removed from elem
1251     for ( it = oldNodes.begin(); it != oldNodes.end(); it++ )
1252     {
1253       SMDS_MeshNode * n = static_cast<SMDS_MeshNode *>
1254         (const_cast<SMDS_MeshElement *>( *it ));
1255       n->RemoveInverseElement( elem );
1256     }
1257   }
1258
1259   if ( !element->IsPoly() )
1260     myInfo.add( element ); // element may change type
1261
1262   return Ok;
1263 }
1264
1265 //=======================================================================
1266 //function : ChangePolyhedronNodes
1267 //purpose  : to change nodes of polyhedral volume
1268 //=======================================================================
1269 bool SMDS_Mesh::ChangePolyhedronNodes (const SMDS_MeshElement *            elem,
1270                                        const vector<const SMDS_MeshNode*>& nodes,
1271                                        const vector<int>                 & quantities)
1272 {
1273   if (elem->GetType() != SMDSAbs_Volume) {
1274     MESSAGE("WRONG ELEM TYPE");
1275     return false;
1276   }
1277
1278   const SMDS_PolyhedralVolumeOfNodes* vol = dynamic_cast<const SMDS_PolyhedralVolumeOfNodes*>(elem);
1279   if (!vol) {
1280     return false;
1281   }
1282
1283   // keep current nodes of elem
1284   set<const SMDS_MeshElement*> oldNodes;
1285   SMDS_ElemIteratorPtr itn = elem->nodesIterator();
1286   while (itn->more()) {
1287     oldNodes.insert(itn->next());
1288   }
1289
1290   // change nodes
1291   bool Ok = const_cast<SMDS_PolyhedralVolumeOfNodes*>(vol)->ChangeNodes(nodes, quantities);
1292   if (!Ok) {
1293     return false;
1294   }
1295
1296   // update InverseElements
1297
1298   // AddInverseElement to new nodes
1299   int nbnodes = nodes.size();
1300   set<const SMDS_MeshElement*>::iterator it;
1301   for (int i = 0; i < nbnodes; i++) {
1302     it = oldNodes.find(nodes[i]);
1303     if (it == oldNodes.end()) {
1304       // new node
1305       const_cast<SMDS_MeshNode*>(nodes[i])->AddInverseElement(elem);
1306     } else {
1307       // remove from oldNodes a node that remains in elem
1308       oldNodes.erase(it);
1309     }
1310   }
1311
1312   // RemoveInverseElement from the nodes removed from elem
1313   for (it = oldNodes.begin(); it != oldNodes.end(); it++) {
1314     SMDS_MeshNode * n = static_cast<SMDS_MeshNode *>
1315       (const_cast<SMDS_MeshElement *>( *it ));
1316     n->RemoveInverseElement(elem);
1317   }
1318
1319   return Ok;
1320 }
1321
1322
1323 //=======================================================================
1324 //function : FindEdge
1325 //purpose  :
1326 //=======================================================================
1327
1328 const SMDS_MeshEdge* SMDS_Mesh::FindEdge(int idnode1, int idnode2) const
1329 {
1330   const SMDS_MeshNode * node1=FindNode(idnode1);
1331   const SMDS_MeshNode * node2=FindNode(idnode2);
1332   if((node1==NULL)||(node2==NULL)) return NULL;
1333   return FindEdge(node1,node2);
1334 }
1335
1336 //#include "Profiler.h"
1337 const SMDS_MeshEdge* SMDS_Mesh::FindEdge(const SMDS_MeshNode * node1,
1338                                          const SMDS_MeshNode * node2)
1339 {
1340   if ( !node1 ) return 0;
1341   const SMDS_MeshEdge * toReturn=NULL;
1342   //PROFILER_Init();
1343   //PROFILER_Set();
1344   SMDS_ElemIteratorPtr it1=node1->GetInverseElementIterator(SMDSAbs_Edge);
1345   //PROFILER_Get(0);
1346   //PROFILER_Set();
1347   while(it1->more()) {
1348     const SMDS_MeshElement * e = it1->next();
1349     if ( e->NbNodes() == 2 && e->GetNodeIndex( node2 ) >= 0 ) {
1350       toReturn = static_cast<const SMDS_MeshEdge*>( e );
1351       break;
1352     }
1353   }
1354   //PROFILER_Get(1);
1355   return toReturn;
1356 }
1357
1358
1359 //=======================================================================
1360 //function : FindEdgeOrCreate
1361 //purpose  :
1362 //=======================================================================
1363
1364 SMDS_MeshEdge* SMDS_Mesh::FindEdgeOrCreate(const SMDS_MeshNode * node1,
1365                                            const SMDS_MeshNode * node2) 
1366 {
1367   if ( !node1 || !node2) return 0;
1368   SMDS_MeshEdge * toReturn=NULL;
1369   toReturn=const_cast<SMDS_MeshEdge*>(FindEdge(node1,node2));
1370   if(toReturn==NULL) {
1371     if ( myEdges.Extent() % CHECKMEMORY_INTERVAL == 0 ) CheckMemory();
1372     toReturn=new SMDS_MeshEdge(node1,node2);
1373     myEdges.Add(toReturn);
1374     myInfo.myNbEdges++;
1375   }
1376   return toReturn;
1377 }
1378
1379
1380 //=======================================================================
1381 //function : FindEdge
1382 //purpose  :
1383 //=======================================================================
1384
1385 const SMDS_MeshEdge* SMDS_Mesh::FindEdge(int idnode1, int idnode2,
1386                                          int idnode3) const
1387 {
1388   const SMDS_MeshNode * node1=FindNode(idnode1);
1389   const SMDS_MeshNode * node2=FindNode(idnode2);
1390   const SMDS_MeshNode * node3=FindNode(idnode3);
1391   return FindEdge(node1,node2,node3);
1392 }
1393
1394 const SMDS_MeshEdge* SMDS_Mesh::FindEdge(const SMDS_MeshNode * node1,
1395                                          const SMDS_MeshNode * node2,
1396                                          const SMDS_MeshNode * node3)
1397 {
1398   if ( !node1 ) return 0;
1399   SMDS_ElemIteratorPtr it1 = node1->GetInverseElementIterator(SMDSAbs_Edge);
1400   while(it1->more()) {
1401     const SMDS_MeshElement * e = it1->next();
1402     if ( e->NbNodes() == 3 ) {
1403       SMDS_ElemIteratorPtr it2 = e->nodesIterator();
1404       while(it2->more()) {
1405         const SMDS_MeshElement* n = it2->next();
1406         if( n!=node1 &&
1407             n!=node2 &&
1408             n!=node3 )
1409         {
1410           e = 0;
1411           break;
1412         }
1413       }
1414       if ( e )
1415         return static_cast<const SMDS_MeshEdge *> (e);
1416     }
1417   }
1418   return 0;
1419 }
1420
1421
1422 //=======================================================================
1423 //function : FindFace
1424 //purpose  :
1425 //=======================================================================
1426
1427 const SMDS_MeshFace* SMDS_Mesh::FindFace(int idnode1, int idnode2,
1428         int idnode3) const
1429 {
1430   const SMDS_MeshNode * node1=FindNode(idnode1);
1431   const SMDS_MeshNode * node2=FindNode(idnode2);
1432   const SMDS_MeshNode * node3=FindNode(idnode3);
1433   return FindFace(node1, node2, node3);
1434 }
1435
1436 const SMDS_MeshFace* SMDS_Mesh::FindFace(const SMDS_MeshNode *node1,
1437                                          const SMDS_MeshNode *node2,
1438                                          const SMDS_MeshNode *node3)
1439 {
1440   if ( !node1 ) return 0;
1441   SMDS_ElemIteratorPtr it1 = node1->GetInverseElementIterator(SMDSAbs_Face);
1442   while(it1->more()) {
1443     const SMDS_MeshElement * e = it1->next();
1444     if ( e->NbNodes() == 3 ) {
1445       SMDS_ElemIteratorPtr it2 = e->nodesIterator();
1446       while(it2->more()) {
1447         const SMDS_MeshElement* n = it2->next();
1448         if( n!=node1 &&
1449             n!=node2 &&
1450             n!=node3 )
1451         {
1452           e = 0;
1453           break;
1454         }
1455       }
1456       if ( e )
1457         return static_cast<const SMDS_MeshFace *> (e);
1458     }
1459   }
1460   return 0;
1461 }
1462
1463 SMDS_MeshFace* SMDS_Mesh::FindFaceOrCreate(const SMDS_MeshNode *node1,
1464                                            const SMDS_MeshNode *node2,
1465                                            const SMDS_MeshNode *node3)
1466 {
1467   SMDS_MeshFace * toReturn=NULL;
1468   toReturn = const_cast<SMDS_MeshFace*>(FindFace(node1,node2,node3));
1469   if(toReturn==NULL) {
1470     toReturn = createTriangle(node1,node2,node3);
1471   }
1472   return toReturn;
1473 }
1474
1475
1476 //=======================================================================
1477 //function : FindFace
1478 //purpose  :
1479 //=======================================================================
1480
1481 const SMDS_MeshFace* SMDS_Mesh::FindFace(int idnode1, int idnode2,
1482                                          int idnode3, int idnode4) const
1483 {
1484   const SMDS_MeshNode * node1=FindNode(idnode1);
1485   const SMDS_MeshNode * node2=FindNode(idnode2);
1486   const SMDS_MeshNode * node3=FindNode(idnode3);
1487   const SMDS_MeshNode * node4=FindNode(idnode4);
1488   return FindFace(node1, node2, node3, node4);
1489 }
1490
1491 const SMDS_MeshFace* SMDS_Mesh::FindFace(const SMDS_MeshNode *node1,
1492                                          const SMDS_MeshNode *node2,
1493                                          const SMDS_MeshNode *node3,
1494                                          const SMDS_MeshNode *node4)
1495 {
1496   if ( !node1 ) return 0;
1497   SMDS_ElemIteratorPtr it1 = node1->GetInverseElementIterator(SMDSAbs_Face);
1498   while(it1->more()) {
1499     const SMDS_MeshElement * e = it1->next();
1500     if ( e->NbNodes() == 4 ) {
1501       SMDS_ElemIteratorPtr it2 = e->nodesIterator();
1502       while(it2->more()) {
1503         const SMDS_MeshElement* n = it2->next();
1504         if( n!=node1 &&
1505             n!=node2 &&
1506             n!=node3 &&
1507             n!=node4 )
1508         {
1509           e = 0;
1510           break;
1511         }
1512       }
1513       if ( e )
1514         return static_cast<const SMDS_MeshFace *> (e);
1515     }
1516   }
1517   return 0;
1518 }
1519
1520 SMDS_MeshFace* SMDS_Mesh::FindFaceOrCreate(const SMDS_MeshNode *node1,
1521                                            const SMDS_MeshNode *node2,
1522                                            const SMDS_MeshNode *node3,
1523                                            const SMDS_MeshNode *node4)
1524 {
1525   SMDS_MeshFace * toReturn=NULL;
1526   toReturn=const_cast<SMDS_MeshFace*>(FindFace(node1,node2,node3,node4));
1527   if(toReturn==NULL) {
1528     toReturn=createQuadrangle(node1,node2,node3,node4);
1529   }
1530   return toReturn;
1531 }
1532
1533
1534 //=======================================================================
1535 //function : FindFace
1536 //purpose  :quadratic triangle
1537 //=======================================================================
1538
1539 const SMDS_MeshFace* SMDS_Mesh::FindFace(int idnode1, int idnode2,
1540                                          int idnode3, int idnode4,
1541                                          int idnode5, int idnode6) const
1542 {
1543   const SMDS_MeshNode * node1 = FindNode(idnode1);
1544   const SMDS_MeshNode * node2 = FindNode(idnode2);
1545   const SMDS_MeshNode * node3 = FindNode(idnode3);
1546   const SMDS_MeshNode * node4 = FindNode(idnode4);
1547   const SMDS_MeshNode * node5 = FindNode(idnode5);
1548   const SMDS_MeshNode * node6 = FindNode(idnode6);
1549   return FindFace(node1, node2, node3, node4, node5, node6);
1550 }
1551
1552 const SMDS_MeshFace* SMDS_Mesh::FindFace(const SMDS_MeshNode *node1,
1553                                          const SMDS_MeshNode *node2,
1554                                          const SMDS_MeshNode *node3,
1555                                          const SMDS_MeshNode *node4,
1556                                          const SMDS_MeshNode *node5,
1557                                          const SMDS_MeshNode *node6)
1558 {
1559   if ( !node1 ) return 0;
1560   SMDS_ElemIteratorPtr it1 = node1->GetInverseElementIterator(SMDSAbs_Face);
1561   while(it1->more()) {
1562     const SMDS_MeshElement * e = it1->next();
1563     if ( e->NbNodes() == 6 ) {
1564       SMDS_ElemIteratorPtr it2 = e->nodesIterator();
1565       while(it2->more()) {
1566         const SMDS_MeshElement* n = it2->next();
1567         if( n!=node1 &&
1568             n!=node2 &&
1569             n!=node3 &&
1570             n!=node4 &&
1571             n!=node5 &&
1572             n!=node6 )
1573         {
1574           e = 0;
1575           break;
1576         }
1577       }
1578       if ( e )
1579         return static_cast<const SMDS_MeshFace *> (e);
1580     }
1581   }
1582   return 0;
1583 }
1584
1585
1586 //=======================================================================
1587 //function : FindFace
1588 //purpose  : quadratic quadrangle
1589 //=======================================================================
1590
1591 const SMDS_MeshFace* SMDS_Mesh::FindFace(int idnode1, int idnode2,
1592                                          int idnode3, int idnode4,
1593                                          int idnode5, int idnode6,
1594                                          int idnode7, int idnode8) const
1595 {
1596   const SMDS_MeshNode * node1 = FindNode(idnode1);
1597   const SMDS_MeshNode * node2 = FindNode(idnode2);
1598   const SMDS_MeshNode * node3 = FindNode(idnode3);
1599   const SMDS_MeshNode * node4 = FindNode(idnode4);
1600   const SMDS_MeshNode * node5 = FindNode(idnode5);
1601   const SMDS_MeshNode * node6 = FindNode(idnode6);
1602   const SMDS_MeshNode * node7 = FindNode(idnode7);
1603   const SMDS_MeshNode * node8 = FindNode(idnode8);
1604   return FindFace(node1, node2, node3, node4, node5, node6, node7, node8);
1605 }
1606
1607 const SMDS_MeshFace* SMDS_Mesh::FindFace(const SMDS_MeshNode *node1,
1608                                          const SMDS_MeshNode *node2,
1609                                          const SMDS_MeshNode *node3,
1610                                          const SMDS_MeshNode *node4,
1611                                          const SMDS_MeshNode *node5,
1612                                          const SMDS_MeshNode *node6,
1613                                          const SMDS_MeshNode *node7,
1614                                          const SMDS_MeshNode *node8)
1615 {
1616   if ( !node1 ) return 0;
1617   SMDS_ElemIteratorPtr it1 = node1->GetInverseElementIterator(SMDSAbs_Face);
1618   while(it1->more()) {
1619     const SMDS_MeshElement * e = it1->next();
1620     if ( e->NbNodes() == 8 ) {
1621       SMDS_ElemIteratorPtr it2 = e->nodesIterator();
1622       while(it2->more()) {
1623         const SMDS_MeshElement* n = it2->next();
1624         if( n!=node1 &&
1625             n!=node2 &&
1626             n!=node3 &&
1627             n!=node4 &&
1628             n!=node5 &&
1629             n!=node6 &&
1630             n!=node7 &&
1631             n!=node8 )
1632         {
1633           e = 0;
1634           break;
1635         }
1636       }
1637       if ( e )
1638         return static_cast<const SMDS_MeshFace *> (e);
1639     }
1640   }
1641   return 0;
1642 }
1643
1644
1645 //=======================================================================
1646 //function : FindElement
1647 //purpose  :
1648 //=======================================================================
1649
1650 const SMDS_MeshElement* SMDS_Mesh::FindElement(int IDelem) const
1651 {
1652   return myElementIDFactory->MeshElement(IDelem);
1653 }
1654
1655 //=======================================================================
1656 //function : FindFace
1657 //purpose  : find polygon
1658 //=======================================================================
1659
1660 const SMDS_MeshFace* SMDS_Mesh::FindFace (std::vector<int> nodes_ids) const
1661 {
1662   int nbnodes = nodes_ids.size();
1663   std::vector<const SMDS_MeshNode *> poly_nodes (nbnodes);
1664   for (int inode = 0; inode < nbnodes; inode++) {
1665     const SMDS_MeshNode * node = FindNode(nodes_ids[inode]);
1666     if (node == NULL) return NULL;
1667   }
1668   return FindFace(poly_nodes);
1669 }
1670
1671 const SMDS_MeshFace* SMDS_Mesh::FindFace (std::vector<const SMDS_MeshNode *> nodes)
1672 {
1673   if ( nodes.size() > 2 && nodes[0] ) {
1674     SMDS_ElemIteratorPtr itF = nodes[0]->GetInverseElementIterator(SMDSAbs_Face);
1675     while (itF->more()) {
1676       const SMDS_MeshElement* f = itF->next();
1677       if ( f->NbNodes() == nodes.size() ) {
1678         SMDS_ElemIteratorPtr it2 = f->nodesIterator();
1679         while(it2->more()) {
1680           if ( find( nodes.begin(), nodes.end(), it2->next() ) == nodes.end() ) {
1681             f = 0;
1682             break;
1683           }
1684         }
1685         if ( f )
1686           return static_cast<const SMDS_MeshFace *> (f);
1687       }
1688     }
1689   }
1690   return NULL;
1691 }
1692
1693 //=======================================================================
1694 //function : DumpNodes
1695 //purpose  : 
1696 //=======================================================================
1697
1698 void SMDS_Mesh::DumpNodes() const
1699 {
1700         MESSAGE("dump nodes of mesh : ");
1701         SMDS_NodeIteratorPtr itnode=nodesIterator();
1702         while(itnode->more()) MESSAGE(itnode->next());
1703 }
1704
1705 //=======================================================================
1706 //function : DumpEdges
1707 //purpose  : 
1708 //=======================================================================
1709
1710 void SMDS_Mesh::DumpEdges() const
1711 {
1712         MESSAGE("dump edges of mesh : ");
1713         SMDS_EdgeIteratorPtr itedge=edgesIterator();
1714         while(itedge->more()) MESSAGE(itedge->next());
1715 }
1716
1717 //=======================================================================
1718 //function : DumpFaces
1719 //purpose  : 
1720 //=======================================================================
1721
1722 void SMDS_Mesh::DumpFaces() const
1723 {
1724         MESSAGE("dump faces of mesh : ");
1725         SMDS_FaceIteratorPtr itface=facesIterator();
1726         while(itface->more()) MESSAGE(itface->next());
1727 }
1728
1729 //=======================================================================
1730 //function : DumpVolumes
1731 //purpose  : 
1732 //=======================================================================
1733
1734 void SMDS_Mesh::DumpVolumes() const
1735 {
1736         MESSAGE("dump volumes of mesh : ");
1737         SMDS_VolumeIteratorPtr itvol=volumesIterator();
1738         while(itvol->more()) MESSAGE(itvol->next());
1739 }
1740
1741 //=======================================================================
1742 //function : DebugStats
1743 //purpose  : 
1744 //=======================================================================
1745
1746 void SMDS_Mesh::DebugStats() const
1747 {
1748         MESSAGE("Debug stats of mesh : ");
1749
1750         MESSAGE("===== NODES ====="<<NbNodes());
1751         MESSAGE("===== EDGES ====="<<NbEdges());
1752         MESSAGE("===== FACES ====="<<NbFaces());
1753         MESSAGE("===== VOLUMES ====="<<NbVolumes());
1754
1755         MESSAGE("End Debug stats of mesh ");
1756
1757         //#ifdef DEB
1758         
1759         SMDS_NodeIteratorPtr itnode=nodesIterator();
1760         int sizeofnodes = 0;
1761         int sizeoffaces = 0;
1762
1763         while(itnode->more())
1764         {
1765                 const SMDS_MeshNode *node = itnode->next();
1766
1767                 sizeofnodes += sizeof(*node);
1768                 
1769                 SMDS_ElemIteratorPtr it = node->GetInverseElementIterator();
1770                 while(it->more())
1771                 {
1772                         const SMDS_MeshElement *me = it->next();
1773                         sizeofnodes += sizeof(me);
1774                 }
1775
1776         }
1777
1778         SMDS_FaceIteratorPtr itface=facesIterator();
1779         while(itface->more())
1780         {
1781                 const SMDS_MeshElement *face = itface->next();          
1782                 sizeoffaces += sizeof(*face);
1783
1784         }
1785         MESSAGE("total size of node elements = " << sizeofnodes);;
1786         MESSAGE("total size of face elements = " << sizeoffaces);;
1787
1788         //#endif
1789 }
1790
1791 ///////////////////////////////////////////////////////////////////////////////
1792 /// Return the number of nodes
1793 ///////////////////////////////////////////////////////////////////////////////
1794 int SMDS_Mesh::NbNodes() const
1795 {
1796         return myNodes.Size();
1797 }
1798
1799 ///////////////////////////////////////////////////////////////////////////////
1800 /// Return the number of edges (including construction edges)
1801 ///////////////////////////////////////////////////////////////////////////////
1802 int SMDS_Mesh::NbEdges() const
1803 {
1804         return myEdges.Size();
1805 }
1806
1807 ///////////////////////////////////////////////////////////////////////////////
1808 /// Return the number of faces (including construction faces)
1809 ///////////////////////////////////////////////////////////////////////////////
1810 int SMDS_Mesh::NbFaces() const
1811 {
1812         return myFaces.Size();
1813 }
1814
1815 ///////////////////////////////////////////////////////////////////////////////
1816 /// Return the number of volumes
1817 ///////////////////////////////////////////////////////////////////////////////
1818 int SMDS_Mesh::NbVolumes() const
1819 {
1820         return myVolumes.Size();
1821 }
1822
1823 ///////////////////////////////////////////////////////////////////////////////
1824 /// Return the number of child mesh of this mesh.
1825 /// Note that the tree structure of SMDS_Mesh seems to be unused in this version
1826 /// (2003-09-08) of SMESH
1827 ///////////////////////////////////////////////////////////////////////////////
1828 int SMDS_Mesh::NbSubMesh() const
1829 {
1830         return myChildren.size();
1831 }
1832
1833 ///////////////////////////////////////////////////////////////////////////////
1834 /// Destroy the mesh and all its elements
1835 /// All pointer on elements owned by this mesh become illegals.
1836 ///////////////////////////////////////////////////////////////////////////////
1837 SMDS_Mesh::~SMDS_Mesh()
1838 {
1839   list<SMDS_Mesh*>::iterator itc=myChildren.begin();
1840   while(itc!=myChildren.end())
1841   {
1842     delete *itc;
1843     itc++;
1844   }
1845
1846   SetOfNodes::Iterator itn(myNodes);
1847   for (; itn.More(); itn.Next())
1848     delete itn.Value();
1849
1850   SetOfEdges::Iterator ite(myEdges);
1851   for (; ite.More(); ite.Next())
1852   {
1853     SMDS_MeshElement* elem = ite.Value();
1854     if(myParent!=NULL)
1855       myElementIDFactory->ReleaseID(elem->GetID());
1856     delete elem;
1857   }
1858
1859   SetOfFaces::Iterator itf(myFaces);
1860   for (; itf.More(); itf.Next())
1861   {
1862     SMDS_MeshElement* elem = itf.Value();
1863     if(myParent!=NULL)
1864       myElementIDFactory->ReleaseID(elem->GetID());
1865     delete elem;
1866   }
1867
1868   SetOfVolumes::Iterator itv(myVolumes);
1869   for (; itv.More(); itv.Next())
1870   {
1871     SMDS_MeshElement* elem = itv.Value();
1872     if(myParent!=NULL)
1873       myElementIDFactory->ReleaseID(elem->GetID());
1874     delete elem;
1875   }
1876
1877   if(myParent==NULL)
1878   {
1879     delete myNodeIDFactory;
1880     delete myElementIDFactory;
1881   }
1882 }
1883
1884 ///////////////////////////////////////////////////////////////////////////////
1885 /// Return true if this mesh create faces with edges.
1886 /// A false returned value mean that faces are created with nodes. A concequence
1887 /// is, iteration on edges (SMDS_Element::edgesIterator) will be unavailable.
1888 ///////////////////////////////////////////////////////////////////////////////
1889 bool SMDS_Mesh::hasConstructionEdges()
1890 {
1891         return myHasConstructionEdges;
1892 }
1893
1894 ///////////////////////////////////////////////////////////////////////////////
1895 /// Return true if this mesh create volumes with faces
1896 /// A false returned value mean that volumes are created with nodes or edges.
1897 /// (see hasConstructionEdges)
1898 /// A concequence is, iteration on faces (SMDS_Element::facesIterator) will be
1899 /// unavailable.
1900 ///////////////////////////////////////////////////////////////////////////////
1901 bool SMDS_Mesh::hasConstructionFaces()
1902 {
1903         return myHasConstructionFaces;
1904 }
1905
1906 ///////////////////////////////////////////////////////////////////////////////
1907 /// Return true if nodes are linked to the finit elements, they are belonging to.
1908 /// Currently, It always return true.
1909 ///////////////////////////////////////////////////////////////////////////////
1910 bool SMDS_Mesh::hasInverseElements()
1911 {
1912         return myHasInverseElements;
1913 }
1914
1915 ///////////////////////////////////////////////////////////////////////////////
1916 /// Make this mesh creating construction edges (see hasConstructionEdges)
1917 /// @param b true to have construction edges, else false.
1918 ///////////////////////////////////////////////////////////////////////////////
1919 void SMDS_Mesh::setConstructionEdges(bool b)
1920 {
1921         myHasConstructionEdges=b;
1922 }
1923
1924 ///////////////////////////////////////////////////////////////////////////////
1925 /// Make this mesh creating construction faces (see hasConstructionFaces)
1926 /// @param b true to have construction faces, else false.
1927 ///////////////////////////////////////////////////////////////////////////////
1928 void SMDS_Mesh::setConstructionFaces(bool b)
1929 {
1930          myHasConstructionFaces=b;
1931 }
1932
1933 ///////////////////////////////////////////////////////////////////////////////
1934 /// Make this mesh creating link from nodes to elements (see hasInverseElements)
1935 /// @param b true to link nodes to elements, else false.
1936 ///////////////////////////////////////////////////////////////////////////////
1937 void SMDS_Mesh::setInverseElements(bool b)
1938 {
1939         if(!b) MESSAGE("Error : inverseElement=false not implemented");
1940         myHasInverseElements=b;
1941 }
1942
1943 ///////////////////////////////////////////////////////////////////////////////
1944 /// Return an iterator on nodes of the current mesh factory
1945 ///////////////////////////////////////////////////////////////////////////////
1946 class SMDS_Mesh_MyNodeIterator:public SMDS_NodeIterator
1947 {
1948   SMDS_ElemIteratorPtr myIterator;
1949  public:
1950   SMDS_Mesh_MyNodeIterator(const SMDS_ElemIteratorPtr& it):myIterator(it)
1951   {}
1952
1953   bool more()
1954   {
1955     return myIterator->more();
1956   }
1957
1958   const SMDS_MeshNode* next()
1959   {
1960     return static_cast<const SMDS_MeshNode*>(myIterator->next());
1961   }
1962 };
1963
1964 SMDS_NodeIteratorPtr SMDS_Mesh::nodesIterator() const
1965 {
1966   return SMDS_NodeIteratorPtr
1967     (new SMDS_Mesh_MyNodeIterator(myNodeIDFactory->elementsIterator()));
1968 }
1969
1970 ///////////////////////////////////////////////////////////////////////////////
1971 /// Return an iterator on elements of the current mesh factory
1972 ///////////////////////////////////////////////////////////////////////////////
1973 SMDS_ElemIteratorPtr SMDS_Mesh::elementsIterator() const
1974 {
1975   return myElementIDFactory->elementsIterator();
1976 }
1977
1978 ///////////////////////////////////////////////////////////////////////////////
1979 ///Return an iterator on edges of the current mesh.
1980 ///////////////////////////////////////////////////////////////////////////////
1981 class SMDS_Mesh_MyEdgeIterator:public SMDS_EdgeIterator
1982 {
1983   typedef SMDS_Mesh::SetOfEdges SetOfEdges;
1984   SetOfEdges::Iterator myIterator;
1985  public:
1986   SMDS_Mesh_MyEdgeIterator(const SetOfEdges& s):myIterator(s)
1987   {}
1988
1989   bool more()
1990   {
1991     while(myIterator.More())
1992     {
1993       if(myIterator.Value()->GetID()!=-1)
1994         return true;
1995       myIterator.Next();
1996     }
1997     return false;
1998   }
1999
2000   const SMDS_MeshEdge* next()
2001   {
2002     const SMDS_MeshEdge* current = myIterator.Value();
2003     myIterator.Next();
2004     return current;
2005   }
2006 };
2007
2008 SMDS_EdgeIteratorPtr SMDS_Mesh::edgesIterator() const
2009 {
2010   return SMDS_EdgeIteratorPtr(new SMDS_Mesh_MyEdgeIterator(myEdges));
2011 }
2012
2013 ///////////////////////////////////////////////////////////////////////////////
2014 ///Return an iterator on faces of the current mesh.
2015 ///////////////////////////////////////////////////////////////////////////////
2016 class SMDS_Mesh_MyFaceIterator:public SMDS_FaceIterator
2017 {
2018   typedef SMDS_Mesh::SetOfFaces SetOfFaces;
2019   SetOfFaces::Iterator myIterator;
2020  public:
2021   SMDS_Mesh_MyFaceIterator(const SetOfFaces& s):myIterator(s)
2022   {}
2023
2024   bool more()
2025   {
2026     while(myIterator.More())
2027     {
2028       if(myIterator.Value()->GetID()!=-1)
2029         return true;
2030       myIterator.Next();
2031     }
2032     return false;
2033   }
2034
2035   const SMDS_MeshFace* next()
2036   {
2037     const SMDS_MeshFace* current = myIterator.Value();
2038     myIterator.Next();
2039     return current;
2040   }
2041 };
2042
2043 SMDS_FaceIteratorPtr SMDS_Mesh::facesIterator() const
2044 {
2045   return SMDS_FaceIteratorPtr(new SMDS_Mesh_MyFaceIterator(myFaces));
2046 }
2047
2048 ///////////////////////////////////////////////////////////////////////////////
2049 ///Return an iterator on volumes of the current mesh.
2050 ///////////////////////////////////////////////////////////////////////////////
2051 class SMDS_Mesh_MyVolumeIterator:public SMDS_VolumeIterator
2052 {
2053   typedef SMDS_Mesh::SetOfVolumes SetOfVolumes;
2054   SetOfVolumes::Iterator myIterator;
2055  public:
2056   SMDS_Mesh_MyVolumeIterator(const SetOfVolumes& s):myIterator(s)
2057   {}
2058
2059   bool more()
2060   {
2061     return myIterator.More() != Standard_False;
2062   }
2063
2064   const SMDS_MeshVolume* next()
2065   {
2066     const SMDS_MeshVolume* current = myIterator.Value();
2067     myIterator.Next();
2068     return current;
2069   }
2070 };
2071
2072 SMDS_VolumeIteratorPtr SMDS_Mesh::volumesIterator() const
2073 {
2074   return SMDS_VolumeIteratorPtr(new SMDS_Mesh_MyVolumeIterator(myVolumes));
2075 }
2076
2077 ///////////////////////////////////////////////////////////////////////////////
2078 /// Do intersection of sets (more than 2)
2079 ///////////////////////////////////////////////////////////////////////////////
2080 static set<const SMDS_MeshElement*> * intersectionOfSets(
2081         set<const SMDS_MeshElement*> vs[], int numberOfSets)
2082 {
2083         set<const SMDS_MeshElement*>* rsetA=new set<const SMDS_MeshElement*>(vs[0]);
2084         set<const SMDS_MeshElement*>* rsetB;
2085
2086         for(int i=0; i<numberOfSets-1; i++)
2087         {
2088                 rsetB=new set<const SMDS_MeshElement*>();
2089                 set_intersection(
2090                         rsetA->begin(), rsetA->end(),
2091                         vs[i+1].begin(), vs[i+1].end(),
2092                         inserter(*rsetB, rsetB->begin()));
2093                 delete rsetA;
2094                 rsetA=rsetB;
2095         }
2096         return rsetA;
2097 }
2098
2099 ///////////////////////////////////////////////////////////////////////////////
2100 /// Return the list of finit elements owning the given element
2101 ///////////////////////////////////////////////////////////////////////////////
2102 static set<const SMDS_MeshElement*> * getFinitElements(const SMDS_MeshElement * element)
2103 {
2104         int numberOfSets=element->NbNodes();
2105         set<const SMDS_MeshElement*> *initSet = new set<const SMDS_MeshElement*>[numberOfSets];
2106
2107         SMDS_ElemIteratorPtr itNodes=element->nodesIterator();
2108
2109         int i=0;
2110         while(itNodes->more())
2111         {
2112                 const SMDS_MeshNode * n=static_cast<const SMDS_MeshNode*>(itNodes->next());
2113                 SMDS_ElemIteratorPtr itFe = n->GetInverseElementIterator();
2114
2115                 //initSet[i]=set<const SMDS_MeshElement*>();
2116                 while(itFe->more())
2117                   initSet[i].insert(itFe->next());
2118
2119                 i++;
2120         }
2121         set<const SMDS_MeshElement*> *retSet=intersectionOfSets(initSet, numberOfSets);
2122         delete [] initSet;
2123         return retSet;
2124 }
2125
2126 ///////////////////////////////////////////////////////////////////////////////
2127 /// Return the list of nodes used only by the given elements
2128 ///////////////////////////////////////////////////////////////////////////////
2129 static set<const SMDS_MeshElement*> * getExclusiveNodes(
2130         set<const SMDS_MeshElement*>& elements)
2131 {
2132         set<const SMDS_MeshElement*> * toReturn=new set<const SMDS_MeshElement*>();
2133         set<const SMDS_MeshElement*>::iterator itElements=elements.begin();
2134
2135         while(itElements!=elements.end())
2136         {
2137                 SMDS_ElemIteratorPtr itNodes = (*itElements)->nodesIterator();
2138                 itElements++;
2139         
2140                 while(itNodes->more())
2141                 {
2142                         const SMDS_MeshNode * n=static_cast<const SMDS_MeshNode*>(itNodes->next());
2143                         SMDS_ElemIteratorPtr itFe = n->GetInverseElementIterator();
2144                         set<const SMDS_MeshElement*> s;
2145                         while(itFe->more())
2146                           s.insert(itFe->next());
2147                         if(s==elements) toReturn->insert(n);
2148                 }
2149         }
2150         return toReturn;        
2151 }
2152
2153 ///////////////////////////////////////////////////////////////////////////////
2154 ///Find the children of an element that are made of given nodes 
2155 ///@param setOfChildren The set in which matching children will be inserted
2156 ///@param element The element were to search matching children
2157 ///@param nodes The nodes that the children must have to be selected
2158 ///////////////////////////////////////////////////////////////////////////////
2159 void SMDS_Mesh::addChildrenWithNodes(set<const SMDS_MeshElement*>&      setOfChildren, 
2160         const SMDS_MeshElement * element, set<const SMDS_MeshElement*>& nodes)
2161 {
2162         
2163         switch(element->GetType())
2164         {
2165         case SMDSAbs_Node:
2166                 MESSAGE("Internal Error: This should not append");
2167                 break;
2168         case SMDSAbs_Edge:
2169         {
2170                 SMDS_ElemIteratorPtr itn=element->nodesIterator();
2171                 while(itn->more())
2172                 {
2173                         const SMDS_MeshElement * e=itn->next();
2174                         if(nodes.find(e)!=nodes.end())
2175                         {
2176                           setOfChildren.insert(element);
2177                           break;
2178                         }
2179                 }
2180         } break;
2181         case SMDSAbs_Face:
2182         {
2183                 SMDS_ElemIteratorPtr itn=element->nodesIterator();
2184                 while(itn->more())
2185                 {
2186                         const SMDS_MeshElement * e=itn->next();
2187                         if(nodes.find(e)!=nodes.end())
2188                         {
2189                           setOfChildren.insert(element);
2190                           break;
2191                         }
2192                 }
2193                 if(hasConstructionEdges())
2194                 {
2195                         SMDS_ElemIteratorPtr ite=element->edgesIterator();
2196                         while(ite->more())
2197                                 addChildrenWithNodes(setOfChildren, ite->next(), nodes);
2198                 }
2199         } break;        
2200         case SMDSAbs_Volume:
2201         {
2202                 if(hasConstructionFaces())
2203                 {
2204                         SMDS_ElemIteratorPtr ite=element->facesIterator();
2205                         while(ite->more())
2206                                 addChildrenWithNodes(setOfChildren, ite->next(), nodes);
2207                 }
2208                 else if(hasConstructionEdges())
2209                 {
2210                         SMDS_ElemIteratorPtr ite=element->edgesIterator();
2211                         while(ite->more())
2212                                 addChildrenWithNodes(setOfChildren, ite->next(), nodes);
2213                 }
2214         }
2215         }
2216 }
2217
2218 ///////////////////////////////////////////////////////////////////////////////
2219 ///@param elem The element to delete
2220 ///@param removenodes if true remaining nodes will be removed
2221 ///////////////////////////////////////////////////////////////////////////////
2222 void SMDS_Mesh::RemoveElement(const SMDS_MeshElement * elem,
2223         const bool removenodes)
2224 {
2225   list<const SMDS_MeshElement *> removedElems;
2226   list<const SMDS_MeshElement *> removedNodes;
2227   RemoveElement( elem, removedElems, removedNodes, removenodes );
2228 }
2229   
2230 ///////////////////////////////////////////////////////////////////////////////
2231 ///@param elem The element to delete
2232 ///@param removedElems contains all removed elements
2233 ///@param removedNodes contains all removed nodes
2234 ///@param removenodes if true remaining nodes will be removed
2235 ///////////////////////////////////////////////////////////////////////////////
2236 void SMDS_Mesh::RemoveElement(const SMDS_MeshElement *        elem,
2237                               list<const SMDS_MeshElement *>& removedElems,
2238                               list<const SMDS_MeshElement *>& removedNodes,
2239                               bool                            removenodes)
2240 {
2241   // get finite elements built on elem
2242   set<const SMDS_MeshElement*> * s1;
2243   if (!hasConstructionEdges() && elem->GetType() == SMDSAbs_Edge ||
2244       !hasConstructionFaces() && elem->GetType() == SMDSAbs_Face ||
2245       elem->GetType() == SMDSAbs_Volume)
2246   {
2247     s1 = new set<const SMDS_MeshElement*>();
2248     s1->insert(elem);
2249   }
2250   else
2251     s1 = getFinitElements(elem);
2252
2253   // get exclusive nodes (which would become free afterwards)
2254   set<const SMDS_MeshElement*> * s2;
2255   if (elem->GetType() == SMDSAbs_Node) // a node is removed
2256   {
2257     // do not remove nodes except elem
2258     s2 = new set<const SMDS_MeshElement*>();
2259     s2->insert(elem);
2260     removenodes = true;
2261   }
2262   else
2263     s2 = getExclusiveNodes(*s1);
2264
2265   // form the set of finite and construction elements to remove
2266   set<const SMDS_MeshElement*> s3;
2267   set<const SMDS_MeshElement*>::iterator it=s1->begin();
2268   while(it!=s1->end())
2269   {
2270     addChildrenWithNodes(s3, *it ,*s2);
2271     s3.insert(*it);
2272     it++;
2273   }
2274   if(elem->GetType()!=SMDSAbs_Node) s3.insert(elem);
2275
2276   // remove finite and construction elements
2277   it=s3.begin();
2278   while(it!=s3.end())
2279   {
2280     // Remove element from <InverseElements> of its nodes
2281     SMDS_ElemIteratorPtr itn=(*it)->nodesIterator();
2282     while(itn->more())
2283     {
2284       SMDS_MeshNode * n = static_cast<SMDS_MeshNode *>
2285         (const_cast<SMDS_MeshElement *>(itn->next()));
2286       n->RemoveInverseElement( (*it) );
2287     }
2288
2289     switch((*it)->GetType())
2290     {
2291     case SMDSAbs_Node:
2292       MESSAGE("Internal Error: This should not happen");
2293       break;
2294     case SMDSAbs_Edge:
2295       myEdges.Remove(static_cast<SMDS_MeshEdge*>
2296                     (const_cast<SMDS_MeshElement*>(*it)));
2297       myInfo.RemoveEdge(*it);
2298       break;
2299     case SMDSAbs_Face:
2300       myFaces.Remove(static_cast<SMDS_MeshFace*>
2301                     (const_cast<SMDS_MeshElement*>(*it)));
2302       myInfo.RemoveFace(*it);
2303       break;
2304     case SMDSAbs_Volume:
2305       myVolumes.Remove(static_cast<SMDS_MeshVolume*>
2306                       (const_cast<SMDS_MeshElement*>(*it)));
2307       myInfo.RemoveVolume(*it);
2308       break;
2309     }
2310     //MESSAGE( "SMDS: RM elem " << (*it)->GetID() );
2311     removedElems.push_back( (*it) );
2312     myElementIDFactory->ReleaseID((*it)->GetID());
2313     delete (*it);
2314     it++;
2315   }
2316
2317   // remove exclusive (free) nodes
2318   if(removenodes)
2319   {
2320     it=s2->begin();
2321     while(it!=s2->end())
2322     {
2323       //MESSAGE( "SMDS: RM node " << (*it)->GetID() );
2324       myNodes.Remove(static_cast<SMDS_MeshNode*>
2325                     (const_cast<SMDS_MeshElement*>(*it)));
2326       myInfo.myNbNodes--;
2327       myNodeIDFactory->ReleaseID((*it)->GetID());
2328       removedNodes.push_back( (*it) );
2329       delete *it;
2330       it++;
2331     }
2332   }
2333
2334   delete s2;
2335   delete s1;
2336 }
2337
2338   
2339 ///////////////////////////////////////////////////////////////////////////////
2340 ///@param elem The element to delete
2341 ///////////////////////////////////////////////////////////////////////////////
2342 void SMDS_Mesh::RemoveFreeElement(const SMDS_MeshElement * elem)
2343 {
2344   SMDSAbs_ElementType aType = elem->GetType();
2345   if (aType == SMDSAbs_Node) {
2346     // only free node can be removed by this method
2347     const SMDS_MeshNode* n = static_cast<const SMDS_MeshNode*>(elem);
2348     SMDS_ElemIteratorPtr itFe = n->GetInverseElementIterator();
2349     if (!itFe->more()) { // free node
2350       myNodes.Remove(const_cast<SMDS_MeshNode*>(n));
2351       myInfo.myNbNodes--;
2352       myNodeIDFactory->ReleaseID(elem->GetID());
2353       delete elem;
2354     }
2355   } else {
2356     if (hasConstructionEdges() || hasConstructionFaces())
2357       // this methods is only for meshes without descendants
2358       return;
2359
2360     // Remove element from <InverseElements> of its nodes
2361     SMDS_ElemIteratorPtr itn = elem->nodesIterator();
2362     while (itn->more()) {
2363       SMDS_MeshNode * n = static_cast<SMDS_MeshNode *>
2364         (const_cast<SMDS_MeshElement *>(itn->next()));
2365       n->RemoveInverseElement(elem);
2366     }
2367
2368     // in meshes without descendants elements are always free
2369     switch (aType) {
2370     case SMDSAbs_Edge:
2371       myEdges.Remove(static_cast<SMDS_MeshEdge*>
2372                      (const_cast<SMDS_MeshElement*>(elem)));
2373       myInfo.RemoveEdge(elem);
2374       break;
2375     case SMDSAbs_Face:
2376       myFaces.Remove(static_cast<SMDS_MeshFace*>
2377                      (const_cast<SMDS_MeshElement*>(elem)));
2378       myInfo.RemoveFace(elem);
2379       break;
2380     case SMDSAbs_Volume:
2381       myVolumes.Remove(static_cast<SMDS_MeshVolume*>
2382                        (const_cast<SMDS_MeshElement*>(elem)));
2383       myInfo.RemoveVolume(elem);
2384       break;
2385     default:
2386       break;
2387     }
2388     myElementIDFactory->ReleaseID(elem->GetID());
2389     delete elem;
2390   }
2391 }
2392
2393 /*!
2394  * Checks if the element is present in mesh.
2395  * Useful to determine dead pointers.
2396  */
2397 bool SMDS_Mesh::Contains (const SMDS_MeshElement* elem) const
2398 {
2399   // we should not imply on validity of *elem, so iterate on containers
2400   // of all types in the hope of finding <elem> somewhere there
2401   SMDS_NodeIteratorPtr itn = nodesIterator();
2402   while (itn->more())
2403     if (elem == itn->next())
2404       return true;
2405   SMDS_EdgeIteratorPtr ite = edgesIterator();
2406   while (ite->more())
2407     if (elem == ite->next())
2408       return true;
2409   SMDS_FaceIteratorPtr itf = facesIterator();
2410   while (itf->more())
2411     if (elem == itf->next())
2412       return true;
2413   SMDS_VolumeIteratorPtr itv = volumesIterator();
2414   while (itv->more())
2415     if (elem == itv->next())
2416       return true;
2417   return false;
2418 }
2419
2420 //=======================================================================
2421 //function : MaxNodeID
2422 //purpose  : 
2423 //=======================================================================
2424
2425 int SMDS_Mesh::MaxNodeID() const
2426 {
2427   return myNodeIDFactory->GetMaxID();
2428 }
2429
2430 //=======================================================================
2431 //function : MinNodeID
2432 //purpose  : 
2433 //=======================================================================
2434
2435 int SMDS_Mesh::MinNodeID() const
2436 {
2437   return myNodeIDFactory->GetMinID();
2438 }
2439
2440 //=======================================================================
2441 //function : MaxElementID
2442 //purpose  : 
2443 //=======================================================================
2444
2445 int SMDS_Mesh::MaxElementID() const
2446 {
2447   return myElementIDFactory->GetMaxID();
2448 }
2449
2450 //=======================================================================
2451 //function : MinElementID
2452 //purpose  : 
2453 //=======================================================================
2454
2455 int SMDS_Mesh::MinElementID() const
2456 {
2457   return myElementIDFactory->GetMinID();
2458 }
2459
2460 //=======================================================================
2461 //function : Renumber
2462 //purpose  : Renumber all nodes or elements.
2463 //=======================================================================
2464
2465 void SMDS_Mesh::Renumber (const bool isNodes, const int  startID, const int  deltaID)
2466 {
2467   if ( deltaID == 0 )
2468     return;
2469
2470   SMDS_MeshElementIDFactory * idFactory =
2471     isNodes ? myNodeIDFactory : myElementIDFactory;
2472
2473   // get existing elements in the order of ID increasing
2474   map<int,SMDS_MeshElement*> elemMap;
2475   SMDS_ElemIteratorPtr idElemIt = idFactory->elementsIterator();
2476   while ( idElemIt->more() ) {
2477     SMDS_MeshElement* elem = const_cast<SMDS_MeshElement*>(idElemIt->next());
2478     int id = elem->GetID();
2479     elemMap.insert(map<int,SMDS_MeshElement*>::value_type(id, elem));
2480   }
2481   // release their ids
2482   map<int,SMDS_MeshElement*>::iterator elemIt = elemMap.begin();
2483   for ( ; elemIt != elemMap.end(); elemIt++ )
2484   {
2485     int id = (*elemIt).first;
2486     idFactory->ReleaseID( id );
2487   }
2488   // set new IDs
2489   int ID = startID;
2490   elemIt = elemMap.begin();
2491   for ( ; elemIt != elemMap.end(); elemIt++ )
2492   {
2493     idFactory->BindID( ID, (*elemIt).second );
2494     ID += deltaID;
2495   }
2496 }
2497
2498 //=======================================================================
2499 //function : GetElementType
2500 //purpose  : Return type of element or node with id
2501 //=======================================================================
2502
2503 SMDSAbs_ElementType SMDS_Mesh::GetElementType( const int id, const bool iselem ) const
2504 {
2505   SMDS_MeshElement* elem = 0;
2506   if( iselem )
2507     elem = myElementIDFactory->MeshElement( id );
2508   else
2509     elem = myNodeIDFactory->MeshElement( id );
2510
2511   if( !elem )
2512   {
2513     //throw SALOME_Exception(LOCALIZED ("this element isn't exist"));
2514     return SMDSAbs_All;
2515   }
2516   else
2517     return elem->GetType();
2518 }
2519
2520
2521
2522 //********************************************************************
2523 //********************************************************************
2524 //********                                                   *********
2525 //*****       Methods for addition of quadratic elements        ******
2526 //********                                                   *********
2527 //********************************************************************
2528 //********************************************************************
2529
2530 //=======================================================================
2531 //function : AddEdgeWithID
2532 //purpose  : 
2533 //=======================================================================
2534 SMDS_MeshEdge* SMDS_Mesh::AddEdgeWithID(int n1, int n2, int n12, int ID) 
2535 {
2536   return SMDS_Mesh::AddEdgeWithID
2537     ((SMDS_MeshNode*) myNodeIDFactory->MeshElement(n1),
2538      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n2),
2539      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n12),
2540      ID);
2541 }
2542
2543 //=======================================================================
2544 //function : AddEdge
2545 //purpose  : 
2546 //=======================================================================
2547 SMDS_MeshEdge* SMDS_Mesh::AddEdge(const SMDS_MeshNode* n1,
2548                                   const SMDS_MeshNode* n2,
2549                                   const SMDS_MeshNode* n12)
2550 {
2551   return SMDS_Mesh::AddEdgeWithID(n1, n2, n12, myElementIDFactory->GetFreeID());
2552 }
2553
2554 //=======================================================================
2555 //function : AddEdgeWithID
2556 //purpose  : 
2557 //=======================================================================
2558 SMDS_MeshEdge* SMDS_Mesh::AddEdgeWithID(const SMDS_MeshNode * n1,
2559                                         const SMDS_MeshNode * n2, 
2560                                         const SMDS_MeshNode * n12, 
2561                                         int ID)
2562 {
2563   if ( !n1 || !n2 || !n12 ) return 0;
2564   SMDS_QuadraticEdge* edge = new SMDS_QuadraticEdge(n1,n2,n12);
2565   if(myElementIDFactory->BindID(ID, edge)) {
2566     SMDS_MeshNode *node1,*node2, *node12;
2567     node1 = const_cast<SMDS_MeshNode*>(n1);
2568     node2 = const_cast<SMDS_MeshNode*>(n2);
2569     node12 = const_cast<SMDS_MeshNode*>(n12);
2570     node1->AddInverseElement(edge);
2571     node2->AddInverseElement(edge);
2572     node12->AddInverseElement(edge);
2573     myEdges.Add(edge);
2574     myInfo.myNbQuadEdges++;
2575     return edge;
2576   } 
2577   else {
2578     delete edge;
2579     return NULL;
2580   }
2581 }
2582
2583
2584 //=======================================================================
2585 //function : AddFace
2586 //purpose  : 
2587 //=======================================================================
2588 SMDS_MeshFace* SMDS_Mesh::AddFace(const SMDS_MeshNode * n1,
2589                                   const SMDS_MeshNode * n2,
2590                                   const SMDS_MeshNode * n3,
2591                                   const SMDS_MeshNode * n12,
2592                                   const SMDS_MeshNode * n23,
2593                                   const SMDS_MeshNode * n31)
2594 {
2595   return SMDS_Mesh::AddFaceWithID(n1,n2,n3,n12,n23,n31,
2596                                   myElementIDFactory->GetFreeID());
2597 }
2598
2599 //=======================================================================
2600 //function : AddFaceWithID
2601 //purpose  : 
2602 //=======================================================================
2603 SMDS_MeshFace* SMDS_Mesh::AddFaceWithID(int n1, int n2, int n3,
2604                                         int n12,int n23,int n31, int ID)
2605 {
2606   return SMDS_Mesh::AddFaceWithID
2607     ((SMDS_MeshNode *)myNodeIDFactory->MeshElement(n1) ,
2608      (SMDS_MeshNode *)myNodeIDFactory->MeshElement(n2) ,
2609      (SMDS_MeshNode *)myNodeIDFactory->MeshElement(n3) ,
2610      (SMDS_MeshNode *)myNodeIDFactory->MeshElement(n12),
2611      (SMDS_MeshNode *)myNodeIDFactory->MeshElement(n23),
2612      (SMDS_MeshNode *)myNodeIDFactory->MeshElement(n31),
2613      ID);
2614 }
2615
2616 //=======================================================================
2617 //function : AddFaceWithID
2618 //purpose  : 
2619 //=======================================================================
2620 SMDS_MeshFace* SMDS_Mesh::AddFaceWithID(const SMDS_MeshNode * n1,
2621                                         const SMDS_MeshNode * n2,
2622                                         const SMDS_MeshNode * n3,
2623                                         const SMDS_MeshNode * n12,
2624                                         const SMDS_MeshNode * n23,
2625                                         const SMDS_MeshNode * n31, 
2626                                         int ID)
2627 {
2628   if ( !n1 || !n2 || !n3 || !n12 || !n23 || !n31) return 0;
2629   if(hasConstructionEdges()) {
2630     // creation quadratic edges - not implemented
2631     return 0;
2632   }
2633   SMDS_QuadraticFaceOfNodes* face =
2634     new SMDS_QuadraticFaceOfNodes(n1,n2,n3,n12,n23,n31);
2635   myFaces.Add(face);
2636   myInfo.myNbQuadTriangles++;
2637
2638   if (!registerElement(ID, face)) {
2639     RemoveElement(face, false);
2640     face = NULL;
2641   }
2642   return face;
2643 }
2644
2645
2646 //=======================================================================
2647 //function : AddFace
2648 //purpose  : 
2649 //=======================================================================
2650 SMDS_MeshFace* SMDS_Mesh::AddFace(const SMDS_MeshNode * n1,
2651                                   const SMDS_MeshNode * n2,
2652                                   const SMDS_MeshNode * n3,
2653                                   const SMDS_MeshNode * n4,
2654                                   const SMDS_MeshNode * n12,
2655                                   const SMDS_MeshNode * n23,
2656                                   const SMDS_MeshNode * n34,
2657                                   const SMDS_MeshNode * n41)
2658 {
2659   return SMDS_Mesh::AddFaceWithID(n1,n2,n3,n4,n12,n23,n34,n41,
2660                                   myElementIDFactory->GetFreeID());
2661 }
2662
2663 //=======================================================================
2664 //function : AddFaceWithID
2665 //purpose  : 
2666 //=======================================================================
2667 SMDS_MeshFace* SMDS_Mesh::AddFaceWithID(int n1, int n2, int n3, int n4,
2668                                         int n12,int n23,int n34,int n41, int ID)
2669 {
2670   return SMDS_Mesh::AddFaceWithID
2671     ((SMDS_MeshNode *)myNodeIDFactory->MeshElement(n1) ,
2672      (SMDS_MeshNode *)myNodeIDFactory->MeshElement(n2) ,
2673      (SMDS_MeshNode *)myNodeIDFactory->MeshElement(n3) ,
2674      (SMDS_MeshNode *)myNodeIDFactory->MeshElement(n4) ,
2675      (SMDS_MeshNode *)myNodeIDFactory->MeshElement(n12),
2676      (SMDS_MeshNode *)myNodeIDFactory->MeshElement(n23),
2677      (SMDS_MeshNode *)myNodeIDFactory->MeshElement(n34),
2678      (SMDS_MeshNode *)myNodeIDFactory->MeshElement(n41),
2679      ID);
2680 }
2681
2682 //=======================================================================
2683 //function : AddFaceWithID
2684 //purpose  : 
2685 //=======================================================================
2686 SMDS_MeshFace* SMDS_Mesh::AddFaceWithID(const SMDS_MeshNode * n1,
2687                                         const SMDS_MeshNode * n2,
2688                                         const SMDS_MeshNode * n3,
2689                                         const SMDS_MeshNode * n4,
2690                                         const SMDS_MeshNode * n12,
2691                                         const SMDS_MeshNode * n23,
2692                                         const SMDS_MeshNode * n34, 
2693                                         const SMDS_MeshNode * n41, 
2694                                         int ID)
2695 {
2696   if ( !n1 || !n2 || !n3 || !n4 || !n12 || !n23 || !n34 || !n41) return 0;
2697   if(hasConstructionEdges()) {
2698     // creation quadratic edges - not implemented
2699   }
2700   SMDS_QuadraticFaceOfNodes* face =
2701     new SMDS_QuadraticFaceOfNodes(n1,n2,n3,n4,n12,n23,n34,n41);
2702   myFaces.Add(face);
2703   myInfo.myNbQuadQuadrangles++;
2704
2705   if (!registerElement(ID, face)) {
2706     RemoveElement(face, false);
2707     face = NULL;
2708   }
2709   return face;
2710 }
2711
2712
2713 //=======================================================================
2714 //function : AddVolume
2715 //purpose  : 
2716 //=======================================================================
2717 SMDS_MeshVolume* SMDS_Mesh::AddVolume(const SMDS_MeshNode * n1,
2718                                       const SMDS_MeshNode * n2, 
2719                                       const SMDS_MeshNode * n3,
2720                                       const SMDS_MeshNode * n4,
2721                                       const SMDS_MeshNode * n12,
2722                                       const SMDS_MeshNode * n23,
2723                                       const SMDS_MeshNode * n31,
2724                                       const SMDS_MeshNode * n14, 
2725                                       const SMDS_MeshNode * n24,
2726                                       const SMDS_MeshNode * n34)
2727 {
2728   int ID = myElementIDFactory->GetFreeID();
2729   SMDS_MeshVolume * v = SMDS_Mesh::AddVolumeWithID(n1, n2, n3, n4, n12, n23,
2730                                                    n31, n14, n24, n34, ID);
2731   if(v==NULL) myElementIDFactory->ReleaseID(ID);
2732   return v;
2733 }
2734
2735 //=======================================================================
2736 //function : AddVolumeWithID
2737 //purpose  : 
2738 //=======================================================================
2739 SMDS_MeshVolume* SMDS_Mesh::AddVolumeWithID(int n1, int n2, int n3, int n4,
2740                                             int n12,int n23,int n31,
2741                                             int n14,int n24,int n34, int ID)
2742 {
2743   return SMDS_Mesh::AddVolumeWithID
2744     ((SMDS_MeshNode*) myNodeIDFactory->MeshElement(n1) ,
2745      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n2) ,
2746      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n3) ,
2747      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n4) ,
2748      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n12),
2749      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n23),
2750      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n31),
2751      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n14),
2752      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n24),
2753      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n34),
2754      ID);
2755 }
2756
2757 //=======================================================================
2758 //function : AddVolumeWithID
2759 //purpose  : 2d order tetrahedron of 10 nodes
2760 //=======================================================================
2761 SMDS_MeshVolume* SMDS_Mesh::AddVolumeWithID(const SMDS_MeshNode * n1,
2762                                             const SMDS_MeshNode * n2,
2763                                             const SMDS_MeshNode * n3,
2764                                             const SMDS_MeshNode * n4,
2765                                             const SMDS_MeshNode * n12,
2766                                             const SMDS_MeshNode * n23,
2767                                             const SMDS_MeshNode * n31,
2768                                             const SMDS_MeshNode * n14, 
2769                                             const SMDS_MeshNode * n24,
2770                                             const SMDS_MeshNode * n34,
2771                                             int ID)
2772 {
2773   if ( !n1 || !n2 || !n3 || !n4 || !n12 || !n23 || !n31 || !n14 || !n24 || !n34)
2774     return 0;
2775   if(hasConstructionFaces()) {
2776     // creation quadratic faces - not implemented
2777     return 0;
2778   }
2779   SMDS_QuadraticVolumeOfNodes * volume =
2780     new SMDS_QuadraticVolumeOfNodes(n1,n2,n3,n4,n12,n23,n31,n14,n24,n34);
2781   myVolumes.Add(volume);
2782   myInfo.myNbQuadTetras++;
2783
2784   if (!registerElement(ID, volume)) {
2785     RemoveElement(volume, false);
2786     volume = NULL;
2787   }
2788   return volume;
2789 }
2790
2791
2792 //=======================================================================
2793 //function : AddVolume
2794 //purpose  : 
2795 //=======================================================================
2796 SMDS_MeshVolume* SMDS_Mesh::AddVolume(const SMDS_MeshNode * n1,
2797                                       const SMDS_MeshNode * n2, 
2798                                       const SMDS_MeshNode * n3,
2799                                       const SMDS_MeshNode * n4,
2800                                       const SMDS_MeshNode * n5, 
2801                                       const SMDS_MeshNode * n12,
2802                                       const SMDS_MeshNode * n23,
2803                                       const SMDS_MeshNode * n34,
2804                                       const SMDS_MeshNode * n41,
2805                                       const SMDS_MeshNode * n15, 
2806                                       const SMDS_MeshNode * n25,
2807                                       const SMDS_MeshNode * n35,
2808                                       const SMDS_MeshNode * n45)
2809 {
2810   int ID = myElementIDFactory->GetFreeID();
2811   SMDS_MeshVolume * v =
2812     SMDS_Mesh::AddVolumeWithID(n1, n2, n3, n4, n5, n12, n23, n34, n41,
2813                                n15, n25, n35, n45, ID);
2814   if(v==NULL) myElementIDFactory->ReleaseID(ID);
2815   return v;
2816 }
2817
2818 //=======================================================================
2819 //function : AddVolumeWithID
2820 //purpose  : 
2821 //=======================================================================
2822 SMDS_MeshVolume* SMDS_Mesh::AddVolumeWithID(int n1, int n2, int n3, int n4, int n5,
2823                                             int n12,int n23,int n34,int n41,
2824                                             int n15,int n25,int n35,int n45, int ID)
2825 {
2826   return SMDS_Mesh::AddVolumeWithID
2827     ((SMDS_MeshNode*) myNodeIDFactory->MeshElement(n1) ,
2828      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n2) ,
2829      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n3) ,
2830      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n4) ,
2831      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n5) ,
2832      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n12),
2833      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n23),
2834      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n34),
2835      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n41),
2836      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n15),
2837      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n25),
2838      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n35),
2839      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n45),
2840      ID);
2841 }
2842
2843 //=======================================================================
2844 //function : AddVolumeWithID
2845 //purpose  : 2d order pyramid of 13 nodes
2846 //=======================================================================
2847 SMDS_MeshVolume* SMDS_Mesh::AddVolumeWithID(const SMDS_MeshNode * n1,
2848                                             const SMDS_MeshNode * n2,
2849                                             const SMDS_MeshNode * n3,
2850                                             const SMDS_MeshNode * n4,
2851                                             const SMDS_MeshNode * n5, 
2852                                             const SMDS_MeshNode * n12,
2853                                             const SMDS_MeshNode * n23,
2854                                             const SMDS_MeshNode * n34,
2855                                             const SMDS_MeshNode * n41,
2856                                             const SMDS_MeshNode * n15, 
2857                                             const SMDS_MeshNode * n25,
2858                                             const SMDS_MeshNode * n35,
2859                                             const SMDS_MeshNode * n45,
2860                                             int ID)
2861 {
2862   if (!n1 || !n2 || !n3 || !n4 || !n5 || !n12 || !n23 ||
2863       !n34 || !n41 || !n15 || !n25 || !n35 || !n45)
2864     return 0;
2865   if(hasConstructionFaces()) {
2866     // creation quadratic faces - not implemented
2867     return 0;
2868   }
2869   SMDS_QuadraticVolumeOfNodes * volume =
2870     new SMDS_QuadraticVolumeOfNodes(n1,n2,n3,n4,n5,n12,n23,
2871                                     n34,n41,n15,n25,n35,n45);
2872   myVolumes.Add(volume);
2873   myInfo.myNbQuadPyramids++;
2874
2875   if (!registerElement(ID, volume)) {
2876     RemoveElement(volume, false);
2877     volume = NULL;
2878   }
2879   return volume;
2880 }
2881
2882
2883 //=======================================================================
2884 //function : AddVolume
2885 //purpose  : 
2886 //=======================================================================
2887 SMDS_MeshVolume* SMDS_Mesh::AddVolume(const SMDS_MeshNode * n1,
2888                                       const SMDS_MeshNode * n2, 
2889                                       const SMDS_MeshNode * n3,
2890                                       const SMDS_MeshNode * n4,
2891                                       const SMDS_MeshNode * n5, 
2892                                       const SMDS_MeshNode * n6, 
2893                                       const SMDS_MeshNode * n12,
2894                                       const SMDS_MeshNode * n23,
2895                                       const SMDS_MeshNode * n31, 
2896                                       const SMDS_MeshNode * n45,
2897                                       const SMDS_MeshNode * n56,
2898                                       const SMDS_MeshNode * n64, 
2899                                       const SMDS_MeshNode * n14,
2900                                       const SMDS_MeshNode * n25,
2901                                       const SMDS_MeshNode * n36)
2902 {
2903   int ID = myElementIDFactory->GetFreeID();
2904   SMDS_MeshVolume * v =
2905     SMDS_Mesh::AddVolumeWithID(n1, n2, n3, n4, n5, n6, n12, n23, n31,
2906                                n45, n56, n64, n14, n25, n36, ID);
2907   if(v==NULL) myElementIDFactory->ReleaseID(ID);
2908   return v;
2909 }
2910
2911 //=======================================================================
2912 //function : AddVolumeWithID
2913 //purpose  : 
2914 //=======================================================================
2915 SMDS_MeshVolume* SMDS_Mesh::AddVolumeWithID(int n1, int n2, int n3,
2916                                             int n4, int n5, int n6,
2917                                             int n12,int n23,int n31,
2918                                             int n45,int n56,int n64,
2919                                             int n14,int n25,int n36, int ID)
2920 {
2921   return SMDS_Mesh::AddVolumeWithID
2922     ((SMDS_MeshNode*) myNodeIDFactory->MeshElement(n1) ,
2923      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n2) ,
2924      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n3) ,
2925      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n4) ,
2926      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n5) ,
2927      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n6) ,
2928      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n12),
2929      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n23),
2930      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n31),
2931      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n45),
2932      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n56),
2933      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n64),
2934      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n14),
2935      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n25),
2936      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n36),
2937      ID);
2938 }
2939
2940 //=======================================================================
2941 //function : AddVolumeWithID
2942 //purpose  : 2d order Pentahedron with 15 nodes
2943 //=======================================================================
2944 SMDS_MeshVolume* SMDS_Mesh::AddVolumeWithID(const SMDS_MeshNode * n1,
2945                                             const SMDS_MeshNode * n2,
2946                                             const SMDS_MeshNode * n3,
2947                                             const SMDS_MeshNode * n4,
2948                                             const SMDS_MeshNode * n5, 
2949                                             const SMDS_MeshNode * n6, 
2950                                             const SMDS_MeshNode * n12,
2951                                             const SMDS_MeshNode * n23,
2952                                             const SMDS_MeshNode * n31, 
2953                                             const SMDS_MeshNode * n45,
2954                                             const SMDS_MeshNode * n56,
2955                                             const SMDS_MeshNode * n64, 
2956                                             const SMDS_MeshNode * n14,
2957                                             const SMDS_MeshNode * n25,
2958                                             const SMDS_MeshNode * n36,
2959                                             int ID)
2960 {
2961   if (!n1 || !n2 || !n3 || !n4 || !n5 || !n6 || !n12 || !n23 ||
2962       !n31 || !n45 || !n56 || !n64 || !n14 || !n25 || !n36)
2963     return 0;
2964   if(hasConstructionFaces()) {
2965     // creation quadratic faces - not implemented
2966     return 0;
2967   }
2968   SMDS_QuadraticVolumeOfNodes * volume =
2969     new SMDS_QuadraticVolumeOfNodes(n1,n2,n3,n4,n5,n6,n12,n23,n31,
2970                                     n45,n56,n64,n14,n25,n36);
2971   myVolumes.Add(volume);
2972   myInfo.myNbQuadPrisms++;
2973
2974   if (!registerElement(ID, volume)) {
2975     RemoveElement(volume, false);
2976     volume = NULL;
2977   }
2978   return volume;
2979 }
2980
2981
2982 //=======================================================================
2983 //function : AddVolume
2984 //purpose  : 
2985 //=======================================================================
2986 SMDS_MeshVolume* SMDS_Mesh::AddVolume(const SMDS_MeshNode * n1,
2987                                       const SMDS_MeshNode * n2, 
2988                                       const SMDS_MeshNode * n3,
2989                                       const SMDS_MeshNode * n4,
2990                                       const SMDS_MeshNode * n5, 
2991                                       const SMDS_MeshNode * n6, 
2992                                       const SMDS_MeshNode * n7,
2993                                       const SMDS_MeshNode * n8, 
2994                                       const SMDS_MeshNode * n12,
2995                                       const SMDS_MeshNode * n23,
2996                                       const SMDS_MeshNode * n34,
2997                                       const SMDS_MeshNode * n41, 
2998                                       const SMDS_MeshNode * n56,
2999                                       const SMDS_MeshNode * n67,
3000                                       const SMDS_MeshNode * n78,
3001                                       const SMDS_MeshNode * n85, 
3002                                       const SMDS_MeshNode * n15,
3003                                       const SMDS_MeshNode * n26,
3004                                       const SMDS_MeshNode * n37,
3005                                       const SMDS_MeshNode * n48)
3006 {
3007   int ID = myElementIDFactory->GetFreeID();
3008   SMDS_MeshVolume * v =
3009     SMDS_Mesh::AddVolumeWithID(n1, n2, n3, n4, n5, n6, n7, n8, n12, n23, n34, n41,
3010                                n56, n67, n78, n85, n15, n26, n37, n48, ID);
3011   if(v==NULL) myElementIDFactory->ReleaseID(ID);
3012   return v;
3013 }
3014
3015 //=======================================================================
3016 //function : AddVolumeWithID
3017 //purpose  : 
3018 //=======================================================================
3019 SMDS_MeshVolume* SMDS_Mesh::AddVolumeWithID(int n1, int n2, int n3, int n4,
3020                                             int n5, int n6, int n7, int n8,
3021                                             int n12,int n23,int n34,int n41,
3022                                             int n56,int n67,int n78,int n85,
3023                                             int n15,int n26,int n37,int n48, int ID)
3024 {
3025   return SMDS_Mesh::AddVolumeWithID
3026     ((SMDS_MeshNode*) myNodeIDFactory->MeshElement(n1),
3027      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n2),
3028      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n3),
3029      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n4),
3030      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n5),
3031      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n6),
3032      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n7),
3033      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n8),
3034      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n12),
3035      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n23),
3036      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n34),
3037      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n41),
3038      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n56),
3039      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n67),
3040      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n78),
3041      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n85),
3042      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n15),
3043      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n26),
3044      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n37),
3045      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n48),
3046      ID);
3047 }
3048
3049 //=======================================================================
3050 //function : AddVolumeWithID
3051 //purpose  : 2d order Hexahedrons with 20 nodes
3052 //=======================================================================
3053 SMDS_MeshVolume* SMDS_Mesh::AddVolumeWithID(const SMDS_MeshNode * n1,
3054                                             const SMDS_MeshNode * n2,
3055                                             const SMDS_MeshNode * n3,
3056                                             const SMDS_MeshNode * n4,
3057                                             const SMDS_MeshNode * n5, 
3058                                             const SMDS_MeshNode * n6, 
3059                                             const SMDS_MeshNode * n7,
3060                                             const SMDS_MeshNode * n8, 
3061                                             const SMDS_MeshNode * n12,
3062                                             const SMDS_MeshNode * n23,
3063                                             const SMDS_MeshNode * n34,
3064                                             const SMDS_MeshNode * n41, 
3065                                             const SMDS_MeshNode * n56,
3066                                             const SMDS_MeshNode * n67,
3067                                             const SMDS_MeshNode * n78,
3068                                             const SMDS_MeshNode * n85, 
3069                                             const SMDS_MeshNode * n15,
3070                                             const SMDS_MeshNode * n26,
3071                                             const SMDS_MeshNode * n37,
3072                                             const SMDS_MeshNode * n48,
3073                                             int ID)
3074 {
3075   if (!n1 || !n2 || !n3 || !n4 || !n5 || !n6 || !n7 || !n8 || !n12 || !n23 ||
3076       !n34 || !n41 || !n56 || !n67 || !n78 || !n85 || !n15 || !n26 || !n37 || !n48)
3077     return 0;
3078   if(hasConstructionFaces()) {
3079     return 0;
3080     // creation quadratic faces - not implemented
3081   }
3082   SMDS_QuadraticVolumeOfNodes * volume =
3083     new SMDS_QuadraticVolumeOfNodes(n1,n2,n3,n4,n5,n6,n7,n8,n12,n23,n34,n41,
3084                                     n56,n67,n78,n85,n15,n26,n37,n48);
3085   myVolumes.Add(volume);
3086   myInfo.myNbQuadHexas++;
3087
3088   if (!registerElement(ID, volume)) {
3089     RemoveElement(volume, false);
3090     volume = NULL;
3091   }
3092   return volume;
3093 }