Salome HOME
Speed up "Clear mesh data"
[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   if(myParent==NULL)
1847   {
1848     delete myNodeIDFactory;
1849     delete myElementIDFactory;
1850   }
1851   else
1852   {
1853     SMDS_ElemIteratorPtr eIt = elementsIterator();
1854     while ( eIt->more() )
1855       myElementIDFactory->ReleaseID(eIt->next()->GetID());
1856     SMDS_NodeIteratorPtr itn = nodesIterator();
1857     while (itn->more())
1858       myNodeIDFactory->ReleaseID(itn->next()->GetID());
1859   }
1860   SetOfNodes::Iterator itn(myNodes);
1861   for (; itn.More(); itn.Next())
1862     delete itn.Value();
1863
1864   SetOfEdges::Iterator ite(myEdges);
1865   for (; ite.More(); ite.Next())
1866   {
1867     SMDS_MeshElement* elem = ite.Value();
1868     delete elem;
1869   }
1870
1871   SetOfFaces::Iterator itf(myFaces);
1872   for (; itf.More(); itf.Next())
1873   {
1874     SMDS_MeshElement* elem = itf.Value();
1875     delete elem;
1876   }
1877
1878   SetOfVolumes::Iterator itv(myVolumes);
1879   for (; itv.More(); itv.Next())
1880   {
1881     SMDS_MeshElement* elem = itv.Value();
1882     delete elem;
1883   }
1884
1885 }
1886
1887 //================================================================================
1888 /*!
1889  * \brief Clear all data
1890  */
1891 //================================================================================
1892
1893 void SMDS_Mesh::Clear()
1894 {
1895   if (myParent!=NULL) {
1896     SMDS_ElemIteratorPtr eIt = elementsIterator();
1897     while ( eIt->more() )
1898       myElementIDFactory->ReleaseID(eIt->next()->GetID());
1899     SMDS_NodeIteratorPtr itn = nodesIterator();
1900     while (itn->more())
1901       myNodeIDFactory->ReleaseID(itn->next()->GetID());
1902   }
1903   else {
1904     myNodeIDFactory->Clear();
1905     myElementIDFactory->Clear();
1906   }
1907   SMDS_VolumeIteratorPtr itv = volumesIterator();
1908   while (itv->more())
1909     delete itv->next();
1910   myVolumes.Clear();
1911
1912   SMDS_FaceIteratorPtr itf = facesIterator();
1913   while (itf->more())
1914     delete itf->next();
1915   myFaces.Clear();
1916       
1917   SMDS_EdgeIteratorPtr ite = edgesIterator();
1918   while (ite->more())
1919     delete ite->next();
1920   myEdges.Clear();
1921
1922   SMDS_NodeIteratorPtr itn = nodesIterator();
1923   while (itn->more())
1924     delete itn->next();
1925   myNodes.Clear();
1926
1927   list<SMDS_Mesh*>::iterator itc=myChildren.begin();
1928   while(itc!=myChildren.end())
1929     (*itc)->Clear();
1930
1931   myInfo = SMDS_MeshInfo();
1932 }
1933
1934 ///////////////////////////////////////////////////////////////////////////////
1935 /// Return true if this mesh create faces with edges.
1936 /// A false returned value mean that faces are created with nodes. A concequence
1937 /// is, iteration on edges (SMDS_Element::edgesIterator) will be unavailable.
1938 ///////////////////////////////////////////////////////////////////////////////
1939 bool SMDS_Mesh::hasConstructionEdges()
1940 {
1941         return myHasConstructionEdges;
1942 }
1943
1944 ///////////////////////////////////////////////////////////////////////////////
1945 /// Return true if this mesh create volumes with faces
1946 /// A false returned value mean that volumes are created with nodes or edges.
1947 /// (see hasConstructionEdges)
1948 /// A concequence is, iteration on faces (SMDS_Element::facesIterator) will be
1949 /// unavailable.
1950 ///////////////////////////////////////////////////////////////////////////////
1951 bool SMDS_Mesh::hasConstructionFaces()
1952 {
1953         return myHasConstructionFaces;
1954 }
1955
1956 ///////////////////////////////////////////////////////////////////////////////
1957 /// Return true if nodes are linked to the finit elements, they are belonging to.
1958 /// Currently, It always return true.
1959 ///////////////////////////////////////////////////////////////////////////////
1960 bool SMDS_Mesh::hasInverseElements()
1961 {
1962         return myHasInverseElements;
1963 }
1964
1965 ///////////////////////////////////////////////////////////////////////////////
1966 /// Make this mesh creating construction edges (see hasConstructionEdges)
1967 /// @param b true to have construction edges, else false.
1968 ///////////////////////////////////////////////////////////////////////////////
1969 void SMDS_Mesh::setConstructionEdges(bool b)
1970 {
1971         myHasConstructionEdges=b;
1972 }
1973
1974 ///////////////////////////////////////////////////////////////////////////////
1975 /// Make this mesh creating construction faces (see hasConstructionFaces)
1976 /// @param b true to have construction faces, else false.
1977 ///////////////////////////////////////////////////////////////////////////////
1978 void SMDS_Mesh::setConstructionFaces(bool b)
1979 {
1980          myHasConstructionFaces=b;
1981 }
1982
1983 ///////////////////////////////////////////////////////////////////////////////
1984 /// Make this mesh creating link from nodes to elements (see hasInverseElements)
1985 /// @param b true to link nodes to elements, else false.
1986 ///////////////////////////////////////////////////////////////////////////////
1987 void SMDS_Mesh::setInverseElements(bool b)
1988 {
1989         if(!b) MESSAGE("Error : inverseElement=false not implemented");
1990         myHasInverseElements=b;
1991 }
1992
1993 ///////////////////////////////////////////////////////////////////////////////
1994 /// Return an iterator on nodes of the current mesh factory
1995 ///////////////////////////////////////////////////////////////////////////////
1996 class SMDS_Mesh_MyNodeIterator:public SMDS_NodeIterator
1997 {
1998   SMDS_ElemIteratorPtr myIterator;
1999  public:
2000   SMDS_Mesh_MyNodeIterator(const SMDS_ElemIteratorPtr& it):myIterator(it)
2001   {}
2002
2003   bool more()
2004   {
2005     return myIterator->more();
2006   }
2007
2008   const SMDS_MeshNode* next()
2009   {
2010     return static_cast<const SMDS_MeshNode*>(myIterator->next());
2011   }
2012 };
2013
2014 SMDS_NodeIteratorPtr SMDS_Mesh::nodesIterator() const
2015 {
2016   return SMDS_NodeIteratorPtr
2017     (new SMDS_Mesh_MyNodeIterator(myNodeIDFactory->elementsIterator()));
2018 }
2019
2020 ///////////////////////////////////////////////////////////////////////////////
2021 /// Return an iterator on elements of the current mesh factory
2022 ///////////////////////////////////////////////////////////////////////////////
2023 SMDS_ElemIteratorPtr SMDS_Mesh::elementsIterator() const
2024 {
2025   return myElementIDFactory->elementsIterator();
2026 }
2027
2028 ///////////////////////////////////////////////////////////////////////////////
2029 ///Return an iterator on edges of the current mesh.
2030 ///////////////////////////////////////////////////////////////////////////////
2031 class SMDS_Mesh_MyEdgeIterator:public SMDS_EdgeIterator
2032 {
2033   typedef SMDS_Mesh::SetOfEdges SetOfEdges;
2034   SetOfEdges::Iterator myIterator;
2035  public:
2036   SMDS_Mesh_MyEdgeIterator(const SetOfEdges& s):myIterator(s)
2037   {}
2038
2039   bool more()
2040   {
2041     while(myIterator.More())
2042     {
2043       if(myIterator.Value()->GetID()!=-1)
2044         return true;
2045       myIterator.Next();
2046     }
2047     return false;
2048   }
2049
2050   const SMDS_MeshEdge* next()
2051   {
2052     const SMDS_MeshEdge* current = myIterator.Value();
2053     myIterator.Next();
2054     return current;
2055   }
2056 };
2057
2058 SMDS_EdgeIteratorPtr SMDS_Mesh::edgesIterator() const
2059 {
2060   return SMDS_EdgeIteratorPtr(new SMDS_Mesh_MyEdgeIterator(myEdges));
2061 }
2062
2063 ///////////////////////////////////////////////////////////////////////////////
2064 ///Return an iterator on faces of the current mesh.
2065 ///////////////////////////////////////////////////////////////////////////////
2066 class SMDS_Mesh_MyFaceIterator:public SMDS_FaceIterator
2067 {
2068   typedef SMDS_Mesh::SetOfFaces SetOfFaces;
2069   SetOfFaces::Iterator myIterator;
2070  public:
2071   SMDS_Mesh_MyFaceIterator(const SetOfFaces& s):myIterator(s)
2072   {}
2073
2074   bool more()
2075   {
2076     while(myIterator.More())
2077     {
2078       if(myIterator.Value()->GetID()!=-1)
2079         return true;
2080       myIterator.Next();
2081     }
2082     return false;
2083   }
2084
2085   const SMDS_MeshFace* next()
2086   {
2087     const SMDS_MeshFace* current = myIterator.Value();
2088     myIterator.Next();
2089     return current;
2090   }
2091 };
2092
2093 SMDS_FaceIteratorPtr SMDS_Mesh::facesIterator() const
2094 {
2095   return SMDS_FaceIteratorPtr(new SMDS_Mesh_MyFaceIterator(myFaces));
2096 }
2097
2098 ///////////////////////////////////////////////////////////////////////////////
2099 ///Return an iterator on volumes of the current mesh.
2100 ///////////////////////////////////////////////////////////////////////////////
2101 class SMDS_Mesh_MyVolumeIterator:public SMDS_VolumeIterator
2102 {
2103   typedef SMDS_Mesh::SetOfVolumes SetOfVolumes;
2104   SetOfVolumes::Iterator myIterator;
2105  public:
2106   SMDS_Mesh_MyVolumeIterator(const SetOfVolumes& s):myIterator(s)
2107   {}
2108
2109   bool more()
2110   {
2111     return myIterator.More() != Standard_False;
2112   }
2113
2114   const SMDS_MeshVolume* next()
2115   {
2116     const SMDS_MeshVolume* current = myIterator.Value();
2117     myIterator.Next();
2118     return current;
2119   }
2120 };
2121
2122 SMDS_VolumeIteratorPtr SMDS_Mesh::volumesIterator() const
2123 {
2124   return SMDS_VolumeIteratorPtr(new SMDS_Mesh_MyVolumeIterator(myVolumes));
2125 }
2126
2127 ///////////////////////////////////////////////////////////////////////////////
2128 /// Do intersection of sets (more than 2)
2129 ///////////////////////////////////////////////////////////////////////////////
2130 static set<const SMDS_MeshElement*> * intersectionOfSets(
2131         set<const SMDS_MeshElement*> vs[], int numberOfSets)
2132 {
2133         set<const SMDS_MeshElement*>* rsetA=new set<const SMDS_MeshElement*>(vs[0]);
2134         set<const SMDS_MeshElement*>* rsetB;
2135
2136         for(int i=0; i<numberOfSets-1; i++)
2137         {
2138                 rsetB=new set<const SMDS_MeshElement*>();
2139                 set_intersection(
2140                         rsetA->begin(), rsetA->end(),
2141                         vs[i+1].begin(), vs[i+1].end(),
2142                         inserter(*rsetB, rsetB->begin()));
2143                 delete rsetA;
2144                 rsetA=rsetB;
2145         }
2146         return rsetA;
2147 }
2148
2149 ///////////////////////////////////////////////////////////////////////////////
2150 /// Return the list of finit elements owning the given element
2151 ///////////////////////////////////////////////////////////////////////////////
2152 static set<const SMDS_MeshElement*> * getFinitElements(const SMDS_MeshElement * element)
2153 {
2154         int numberOfSets=element->NbNodes();
2155         set<const SMDS_MeshElement*> *initSet = new set<const SMDS_MeshElement*>[numberOfSets];
2156
2157         SMDS_ElemIteratorPtr itNodes=element->nodesIterator();
2158
2159         int i=0;
2160         while(itNodes->more())
2161         {
2162                 const SMDS_MeshNode * n=static_cast<const SMDS_MeshNode*>(itNodes->next());
2163                 SMDS_ElemIteratorPtr itFe = n->GetInverseElementIterator();
2164
2165                 //initSet[i]=set<const SMDS_MeshElement*>();
2166                 while(itFe->more())
2167                   initSet[i].insert(itFe->next());
2168
2169                 i++;
2170         }
2171         set<const SMDS_MeshElement*> *retSet=intersectionOfSets(initSet, numberOfSets);
2172         delete [] initSet;
2173         return retSet;
2174 }
2175
2176 ///////////////////////////////////////////////////////////////////////////////
2177 /// Return the list of nodes used only by the given elements
2178 ///////////////////////////////////////////////////////////////////////////////
2179 static set<const SMDS_MeshElement*> * getExclusiveNodes(
2180         set<const SMDS_MeshElement*>& elements)
2181 {
2182         set<const SMDS_MeshElement*> * toReturn=new set<const SMDS_MeshElement*>();
2183         set<const SMDS_MeshElement*>::iterator itElements=elements.begin();
2184
2185         while(itElements!=elements.end())
2186         {
2187                 SMDS_ElemIteratorPtr itNodes = (*itElements)->nodesIterator();
2188                 itElements++;
2189         
2190                 while(itNodes->more())
2191                 {
2192                         const SMDS_MeshNode * n=static_cast<const SMDS_MeshNode*>(itNodes->next());
2193                         SMDS_ElemIteratorPtr itFe = n->GetInverseElementIterator();
2194                         set<const SMDS_MeshElement*> s;
2195                         while(itFe->more())
2196                           s.insert(itFe->next());
2197                         if(s==elements) toReturn->insert(n);
2198                 }
2199         }
2200         return toReturn;        
2201 }
2202
2203 ///////////////////////////////////////////////////////////////////////////////
2204 ///Find the children of an element that are made of given nodes 
2205 ///@param setOfChildren The set in which matching children will be inserted
2206 ///@param element The element were to search matching children
2207 ///@param nodes The nodes that the children must have to be selected
2208 ///////////////////////////////////////////////////////////////////////////////
2209 void SMDS_Mesh::addChildrenWithNodes(set<const SMDS_MeshElement*>&      setOfChildren, 
2210         const SMDS_MeshElement * element, set<const SMDS_MeshElement*>& nodes)
2211 {
2212         
2213         switch(element->GetType())
2214         {
2215         case SMDSAbs_Node:
2216                 MESSAGE("Internal Error: This should not append");
2217                 break;
2218         case SMDSAbs_Edge:
2219         {
2220                 SMDS_ElemIteratorPtr itn=element->nodesIterator();
2221                 while(itn->more())
2222                 {
2223                         const SMDS_MeshElement * e=itn->next();
2224                         if(nodes.find(e)!=nodes.end())
2225                         {
2226                           setOfChildren.insert(element);
2227                           break;
2228                         }
2229                 }
2230         } break;
2231         case SMDSAbs_Face:
2232         {
2233                 SMDS_ElemIteratorPtr itn=element->nodesIterator();
2234                 while(itn->more())
2235                 {
2236                         const SMDS_MeshElement * e=itn->next();
2237                         if(nodes.find(e)!=nodes.end())
2238                         {
2239                           setOfChildren.insert(element);
2240                           break;
2241                         }
2242                 }
2243                 if(hasConstructionEdges())
2244                 {
2245                         SMDS_ElemIteratorPtr ite=element->edgesIterator();
2246                         while(ite->more())
2247                                 addChildrenWithNodes(setOfChildren, ite->next(), nodes);
2248                 }
2249         } break;        
2250         case SMDSAbs_Volume:
2251         {
2252                 if(hasConstructionFaces())
2253                 {
2254                         SMDS_ElemIteratorPtr ite=element->facesIterator();
2255                         while(ite->more())
2256                                 addChildrenWithNodes(setOfChildren, ite->next(), nodes);
2257                 }
2258                 else if(hasConstructionEdges())
2259                 {
2260                         SMDS_ElemIteratorPtr ite=element->edgesIterator();
2261                         while(ite->more())
2262                                 addChildrenWithNodes(setOfChildren, ite->next(), nodes);
2263                 }
2264         }
2265         }
2266 }
2267
2268 ///////////////////////////////////////////////////////////////////////////////
2269 ///@param elem The element to delete
2270 ///@param removenodes if true remaining nodes will be removed
2271 ///////////////////////////////////////////////////////////////////////////////
2272 void SMDS_Mesh::RemoveElement(const SMDS_MeshElement * elem,
2273         const bool removenodes)
2274 {
2275   list<const SMDS_MeshElement *> removedElems;
2276   list<const SMDS_MeshElement *> removedNodes;
2277   RemoveElement( elem, removedElems, removedNodes, removenodes );
2278 }
2279   
2280 ///////////////////////////////////////////////////////////////////////////////
2281 ///@param elem The element to delete
2282 ///@param removedElems contains all removed elements
2283 ///@param removedNodes contains all removed nodes
2284 ///@param removenodes if true remaining nodes will be removed
2285 ///////////////////////////////////////////////////////////////////////////////
2286 void SMDS_Mesh::RemoveElement(const SMDS_MeshElement *        elem,
2287                               list<const SMDS_MeshElement *>& removedElems,
2288                               list<const SMDS_MeshElement *>& removedNodes,
2289                               bool                            removenodes)
2290 {
2291   // get finite elements built on elem
2292   set<const SMDS_MeshElement*> * s1;
2293   if (!hasConstructionEdges() && elem->GetType() == SMDSAbs_Edge ||
2294       !hasConstructionFaces() && elem->GetType() == SMDSAbs_Face ||
2295       elem->GetType() == SMDSAbs_Volume)
2296   {
2297     s1 = new set<const SMDS_MeshElement*>();
2298     s1->insert(elem);
2299   }
2300   else
2301     s1 = getFinitElements(elem);
2302
2303   // get exclusive nodes (which would become free afterwards)
2304   set<const SMDS_MeshElement*> * s2;
2305   if (elem->GetType() == SMDSAbs_Node) // a node is removed
2306   {
2307     // do not remove nodes except elem
2308     s2 = new set<const SMDS_MeshElement*>();
2309     s2->insert(elem);
2310     removenodes = true;
2311   }
2312   else
2313     s2 = getExclusiveNodes(*s1);
2314
2315   // form the set of finite and construction elements to remove
2316   set<const SMDS_MeshElement*> s3;
2317   set<const SMDS_MeshElement*>::iterator it=s1->begin();
2318   while(it!=s1->end())
2319   {
2320     addChildrenWithNodes(s3, *it ,*s2);
2321     s3.insert(*it);
2322     it++;
2323   }
2324   if(elem->GetType()!=SMDSAbs_Node) s3.insert(elem);
2325
2326   // remove finite and construction elements
2327   it=s3.begin();
2328   while(it!=s3.end())
2329   {
2330     // Remove element from <InverseElements> of its nodes
2331     SMDS_ElemIteratorPtr itn=(*it)->nodesIterator();
2332     while(itn->more())
2333     {
2334       SMDS_MeshNode * n = static_cast<SMDS_MeshNode *>
2335         (const_cast<SMDS_MeshElement *>(itn->next()));
2336       n->RemoveInverseElement( (*it) );
2337     }
2338
2339     switch((*it)->GetType())
2340     {
2341     case SMDSAbs_Node:
2342       MESSAGE("Internal Error: This should not happen");
2343       break;
2344     case SMDSAbs_Edge:
2345       myEdges.Remove(static_cast<SMDS_MeshEdge*>
2346                     (const_cast<SMDS_MeshElement*>(*it)));
2347       myInfo.RemoveEdge(*it);
2348       break;
2349     case SMDSAbs_Face:
2350       myFaces.Remove(static_cast<SMDS_MeshFace*>
2351                     (const_cast<SMDS_MeshElement*>(*it)));
2352       myInfo.RemoveFace(*it);
2353       break;
2354     case SMDSAbs_Volume:
2355       myVolumes.Remove(static_cast<SMDS_MeshVolume*>
2356                       (const_cast<SMDS_MeshElement*>(*it)));
2357       myInfo.RemoveVolume(*it);
2358       break;
2359     }
2360     //MESSAGE( "SMDS: RM elem " << (*it)->GetID() );
2361     removedElems.push_back( (*it) );
2362     myElementIDFactory->ReleaseID((*it)->GetID());
2363     delete (*it);
2364     it++;
2365   }
2366
2367   // remove exclusive (free) nodes
2368   if(removenodes)
2369   {
2370     it=s2->begin();
2371     while(it!=s2->end())
2372     {
2373       //MESSAGE( "SMDS: RM node " << (*it)->GetID() );
2374       myNodes.Remove(static_cast<SMDS_MeshNode*>
2375                     (const_cast<SMDS_MeshElement*>(*it)));
2376       myInfo.myNbNodes--;
2377       myNodeIDFactory->ReleaseID((*it)->GetID());
2378       removedNodes.push_back( (*it) );
2379       delete *it;
2380       it++;
2381     }
2382   }
2383
2384   delete s2;
2385   delete s1;
2386 }
2387
2388   
2389 ///////////////////////////////////////////////////////////////////////////////
2390 ///@param elem The element to delete
2391 ///////////////////////////////////////////////////////////////////////////////
2392 void SMDS_Mesh::RemoveFreeElement(const SMDS_MeshElement * elem)
2393 {
2394   SMDSAbs_ElementType aType = elem->GetType();
2395   if (aType == SMDSAbs_Node) {
2396     // only free node can be removed by this method
2397     const SMDS_MeshNode* n = static_cast<const SMDS_MeshNode*>(elem);
2398     SMDS_ElemIteratorPtr itFe = n->GetInverseElementIterator();
2399     if (!itFe->more()) { // free node
2400       myNodes.Remove(const_cast<SMDS_MeshNode*>(n));
2401       myInfo.myNbNodes--;
2402       myNodeIDFactory->ReleaseID(elem->GetID());
2403       delete elem;
2404     }
2405   } else {
2406     if (hasConstructionEdges() || hasConstructionFaces())
2407       // this methods is only for meshes without descendants
2408       return;
2409
2410     // Remove element from <InverseElements> of its nodes
2411     SMDS_ElemIteratorPtr itn = elem->nodesIterator();
2412     while (itn->more()) {
2413       SMDS_MeshNode * n = static_cast<SMDS_MeshNode *>
2414         (const_cast<SMDS_MeshElement *>(itn->next()));
2415       n->RemoveInverseElement(elem);
2416     }
2417
2418     // in meshes without descendants elements are always free
2419     switch (aType) {
2420     case SMDSAbs_Edge:
2421       myEdges.Remove(static_cast<SMDS_MeshEdge*>
2422                      (const_cast<SMDS_MeshElement*>(elem)));
2423       myInfo.RemoveEdge(elem);
2424       break;
2425     case SMDSAbs_Face:
2426       myFaces.Remove(static_cast<SMDS_MeshFace*>
2427                      (const_cast<SMDS_MeshElement*>(elem)));
2428       myInfo.RemoveFace(elem);
2429       break;
2430     case SMDSAbs_Volume:
2431       myVolumes.Remove(static_cast<SMDS_MeshVolume*>
2432                        (const_cast<SMDS_MeshElement*>(elem)));
2433       myInfo.RemoveVolume(elem);
2434       break;
2435     default:
2436       break;
2437     }
2438     myElementIDFactory->ReleaseID(elem->GetID());
2439     delete elem;
2440   }
2441 }
2442
2443 /*!
2444  * Checks if the element is present in mesh.
2445  * Useful to determine dead pointers.
2446  */
2447 bool SMDS_Mesh::Contains (const SMDS_MeshElement* elem) const
2448 {
2449   // we should not imply on validity of *elem, so iterate on containers
2450   // of all types in the hope of finding <elem> somewhere there
2451   SMDS_NodeIteratorPtr itn = nodesIterator();
2452   while (itn->more())
2453     if (elem == itn->next())
2454       return true;
2455   SMDS_EdgeIteratorPtr ite = edgesIterator();
2456   while (ite->more())
2457     if (elem == ite->next())
2458       return true;
2459   SMDS_FaceIteratorPtr itf = facesIterator();
2460   while (itf->more())
2461     if (elem == itf->next())
2462       return true;
2463   SMDS_VolumeIteratorPtr itv = volumesIterator();
2464   while (itv->more())
2465     if (elem == itv->next())
2466       return true;
2467   return false;
2468 }
2469
2470 //=======================================================================
2471 //function : MaxNodeID
2472 //purpose  : 
2473 //=======================================================================
2474
2475 int SMDS_Mesh::MaxNodeID() const
2476 {
2477   return myNodeIDFactory->GetMaxID();
2478 }
2479
2480 //=======================================================================
2481 //function : MinNodeID
2482 //purpose  : 
2483 //=======================================================================
2484
2485 int SMDS_Mesh::MinNodeID() const
2486 {
2487   return myNodeIDFactory->GetMinID();
2488 }
2489
2490 //=======================================================================
2491 //function : MaxElementID
2492 //purpose  : 
2493 //=======================================================================
2494
2495 int SMDS_Mesh::MaxElementID() const
2496 {
2497   return myElementIDFactory->GetMaxID();
2498 }
2499
2500 //=======================================================================
2501 //function : MinElementID
2502 //purpose  : 
2503 //=======================================================================
2504
2505 int SMDS_Mesh::MinElementID() const
2506 {
2507   return myElementIDFactory->GetMinID();
2508 }
2509
2510 //=======================================================================
2511 //function : Renumber
2512 //purpose  : Renumber all nodes or elements.
2513 //=======================================================================
2514
2515 void SMDS_Mesh::Renumber (const bool isNodes, const int  startID, const int  deltaID)
2516 {
2517   if ( deltaID == 0 )
2518     return;
2519
2520   SMDS_MeshElementIDFactory * idFactory =
2521     isNodes ? myNodeIDFactory : myElementIDFactory;
2522
2523   // get existing elements in the order of ID increasing
2524   map<int,SMDS_MeshElement*> elemMap;
2525   SMDS_ElemIteratorPtr idElemIt = idFactory->elementsIterator();
2526   while ( idElemIt->more() ) {
2527     SMDS_MeshElement* elem = const_cast<SMDS_MeshElement*>(idElemIt->next());
2528     int id = elem->GetID();
2529     elemMap.insert(map<int,SMDS_MeshElement*>::value_type(id, elem));
2530   }
2531   // release their ids
2532   map<int,SMDS_MeshElement*>::iterator elemIt = elemMap.begin();
2533   for ( ; elemIt != elemMap.end(); elemIt++ )
2534   {
2535     int id = (*elemIt).first;
2536     idFactory->ReleaseID( id );
2537   }
2538   // set new IDs
2539   int ID = startID;
2540   elemIt = elemMap.begin();
2541   for ( ; elemIt != elemMap.end(); elemIt++ )
2542   {
2543     idFactory->BindID( ID, (*elemIt).second );
2544     ID += deltaID;
2545   }
2546 }
2547
2548 //=======================================================================
2549 //function : GetElementType
2550 //purpose  : Return type of element or node with id
2551 //=======================================================================
2552
2553 SMDSAbs_ElementType SMDS_Mesh::GetElementType( const int id, const bool iselem ) const
2554 {
2555   SMDS_MeshElement* elem = 0;
2556   if( iselem )
2557     elem = myElementIDFactory->MeshElement( id );
2558   else
2559     elem = myNodeIDFactory->MeshElement( id );
2560
2561   if( !elem )
2562   {
2563     //throw SALOME_Exception(LOCALIZED ("this element isn't exist"));
2564     return SMDSAbs_All;
2565   }
2566   else
2567     return elem->GetType();
2568 }
2569
2570
2571
2572 //********************************************************************
2573 //********************************************************************
2574 //********                                                   *********
2575 //*****       Methods for addition of quadratic elements        ******
2576 //********                                                   *********
2577 //********************************************************************
2578 //********************************************************************
2579
2580 //=======================================================================
2581 //function : AddEdgeWithID
2582 //purpose  : 
2583 //=======================================================================
2584 SMDS_MeshEdge* SMDS_Mesh::AddEdgeWithID(int n1, int n2, int n12, int ID) 
2585 {
2586   return SMDS_Mesh::AddEdgeWithID
2587     ((SMDS_MeshNode*) myNodeIDFactory->MeshElement(n1),
2588      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n2),
2589      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n12),
2590      ID);
2591 }
2592
2593 //=======================================================================
2594 //function : AddEdge
2595 //purpose  : 
2596 //=======================================================================
2597 SMDS_MeshEdge* SMDS_Mesh::AddEdge(const SMDS_MeshNode* n1,
2598                                   const SMDS_MeshNode* n2,
2599                                   const SMDS_MeshNode* n12)
2600 {
2601   return SMDS_Mesh::AddEdgeWithID(n1, n2, n12, myElementIDFactory->GetFreeID());
2602 }
2603
2604 //=======================================================================
2605 //function : AddEdgeWithID
2606 //purpose  : 
2607 //=======================================================================
2608 SMDS_MeshEdge* SMDS_Mesh::AddEdgeWithID(const SMDS_MeshNode * n1,
2609                                         const SMDS_MeshNode * n2, 
2610                                         const SMDS_MeshNode * n12, 
2611                                         int ID)
2612 {
2613   if ( !n1 || !n2 || !n12 ) return 0;
2614   SMDS_QuadraticEdge* edge = new SMDS_QuadraticEdge(n1,n2,n12);
2615   if(myElementIDFactory->BindID(ID, edge)) {
2616     SMDS_MeshNode *node1,*node2, *node12;
2617     node1 = const_cast<SMDS_MeshNode*>(n1);
2618     node2 = const_cast<SMDS_MeshNode*>(n2);
2619     node12 = const_cast<SMDS_MeshNode*>(n12);
2620     node1->AddInverseElement(edge);
2621     node2->AddInverseElement(edge);
2622     node12->AddInverseElement(edge);
2623     myEdges.Add(edge);
2624     myInfo.myNbQuadEdges++;
2625     return edge;
2626   } 
2627   else {
2628     delete edge;
2629     return NULL;
2630   }
2631 }
2632
2633
2634 //=======================================================================
2635 //function : AddFace
2636 //purpose  : 
2637 //=======================================================================
2638 SMDS_MeshFace* SMDS_Mesh::AddFace(const SMDS_MeshNode * n1,
2639                                   const SMDS_MeshNode * n2,
2640                                   const SMDS_MeshNode * n3,
2641                                   const SMDS_MeshNode * n12,
2642                                   const SMDS_MeshNode * n23,
2643                                   const SMDS_MeshNode * n31)
2644 {
2645   return SMDS_Mesh::AddFaceWithID(n1,n2,n3,n12,n23,n31,
2646                                   myElementIDFactory->GetFreeID());
2647 }
2648
2649 //=======================================================================
2650 //function : AddFaceWithID
2651 //purpose  : 
2652 //=======================================================================
2653 SMDS_MeshFace* SMDS_Mesh::AddFaceWithID(int n1, int n2, int n3,
2654                                         int n12,int n23,int n31, int ID)
2655 {
2656   return SMDS_Mesh::AddFaceWithID
2657     ((SMDS_MeshNode *)myNodeIDFactory->MeshElement(n1) ,
2658      (SMDS_MeshNode *)myNodeIDFactory->MeshElement(n2) ,
2659      (SMDS_MeshNode *)myNodeIDFactory->MeshElement(n3) ,
2660      (SMDS_MeshNode *)myNodeIDFactory->MeshElement(n12),
2661      (SMDS_MeshNode *)myNodeIDFactory->MeshElement(n23),
2662      (SMDS_MeshNode *)myNodeIDFactory->MeshElement(n31),
2663      ID);
2664 }
2665
2666 //=======================================================================
2667 //function : AddFaceWithID
2668 //purpose  : 
2669 //=======================================================================
2670 SMDS_MeshFace* SMDS_Mesh::AddFaceWithID(const SMDS_MeshNode * n1,
2671                                         const SMDS_MeshNode * n2,
2672                                         const SMDS_MeshNode * n3,
2673                                         const SMDS_MeshNode * n12,
2674                                         const SMDS_MeshNode * n23,
2675                                         const SMDS_MeshNode * n31, 
2676                                         int ID)
2677 {
2678   if ( !n1 || !n2 || !n3 || !n12 || !n23 || !n31) return 0;
2679   if(hasConstructionEdges()) {
2680     // creation quadratic edges - not implemented
2681     return 0;
2682   }
2683   SMDS_QuadraticFaceOfNodes* face =
2684     new SMDS_QuadraticFaceOfNodes(n1,n2,n3,n12,n23,n31);
2685   myFaces.Add(face);
2686   myInfo.myNbQuadTriangles++;
2687
2688   if (!registerElement(ID, face)) {
2689     RemoveElement(face, false);
2690     face = NULL;
2691   }
2692   return face;
2693 }
2694
2695
2696 //=======================================================================
2697 //function : AddFace
2698 //purpose  : 
2699 //=======================================================================
2700 SMDS_MeshFace* SMDS_Mesh::AddFace(const SMDS_MeshNode * n1,
2701                                   const SMDS_MeshNode * n2,
2702                                   const SMDS_MeshNode * n3,
2703                                   const SMDS_MeshNode * n4,
2704                                   const SMDS_MeshNode * n12,
2705                                   const SMDS_MeshNode * n23,
2706                                   const SMDS_MeshNode * n34,
2707                                   const SMDS_MeshNode * n41)
2708 {
2709   return SMDS_Mesh::AddFaceWithID(n1,n2,n3,n4,n12,n23,n34,n41,
2710                                   myElementIDFactory->GetFreeID());
2711 }
2712
2713 //=======================================================================
2714 //function : AddFaceWithID
2715 //purpose  : 
2716 //=======================================================================
2717 SMDS_MeshFace* SMDS_Mesh::AddFaceWithID(int n1, int n2, int n3, int n4,
2718                                         int n12,int n23,int n34,int n41, int ID)
2719 {
2720   return SMDS_Mesh::AddFaceWithID
2721     ((SMDS_MeshNode *)myNodeIDFactory->MeshElement(n1) ,
2722      (SMDS_MeshNode *)myNodeIDFactory->MeshElement(n2) ,
2723      (SMDS_MeshNode *)myNodeIDFactory->MeshElement(n3) ,
2724      (SMDS_MeshNode *)myNodeIDFactory->MeshElement(n4) ,
2725      (SMDS_MeshNode *)myNodeIDFactory->MeshElement(n12),
2726      (SMDS_MeshNode *)myNodeIDFactory->MeshElement(n23),
2727      (SMDS_MeshNode *)myNodeIDFactory->MeshElement(n34),
2728      (SMDS_MeshNode *)myNodeIDFactory->MeshElement(n41),
2729      ID);
2730 }
2731
2732 //=======================================================================
2733 //function : AddFaceWithID
2734 //purpose  : 
2735 //=======================================================================
2736 SMDS_MeshFace* SMDS_Mesh::AddFaceWithID(const SMDS_MeshNode * n1,
2737                                         const SMDS_MeshNode * n2,
2738                                         const SMDS_MeshNode * n3,
2739                                         const SMDS_MeshNode * n4,
2740                                         const SMDS_MeshNode * n12,
2741                                         const SMDS_MeshNode * n23,
2742                                         const SMDS_MeshNode * n34, 
2743                                         const SMDS_MeshNode * n41, 
2744                                         int ID)
2745 {
2746   if ( !n1 || !n2 || !n3 || !n4 || !n12 || !n23 || !n34 || !n41) return 0;
2747   if(hasConstructionEdges()) {
2748     // creation quadratic edges - not implemented
2749   }
2750   SMDS_QuadraticFaceOfNodes* face =
2751     new SMDS_QuadraticFaceOfNodes(n1,n2,n3,n4,n12,n23,n34,n41);
2752   myFaces.Add(face);
2753   myInfo.myNbQuadQuadrangles++;
2754
2755   if (!registerElement(ID, face)) {
2756     RemoveElement(face, false);
2757     face = NULL;
2758   }
2759   return face;
2760 }
2761
2762
2763 //=======================================================================
2764 //function : AddVolume
2765 //purpose  : 
2766 //=======================================================================
2767 SMDS_MeshVolume* SMDS_Mesh::AddVolume(const SMDS_MeshNode * n1,
2768                                       const SMDS_MeshNode * n2, 
2769                                       const SMDS_MeshNode * n3,
2770                                       const SMDS_MeshNode * n4,
2771                                       const SMDS_MeshNode * n12,
2772                                       const SMDS_MeshNode * n23,
2773                                       const SMDS_MeshNode * n31,
2774                                       const SMDS_MeshNode * n14, 
2775                                       const SMDS_MeshNode * n24,
2776                                       const SMDS_MeshNode * n34)
2777 {
2778   int ID = myElementIDFactory->GetFreeID();
2779   SMDS_MeshVolume * v = SMDS_Mesh::AddVolumeWithID(n1, n2, n3, n4, n12, n23,
2780                                                    n31, n14, n24, n34, ID);
2781   if(v==NULL) myElementIDFactory->ReleaseID(ID);
2782   return v;
2783 }
2784
2785 //=======================================================================
2786 //function : AddVolumeWithID
2787 //purpose  : 
2788 //=======================================================================
2789 SMDS_MeshVolume* SMDS_Mesh::AddVolumeWithID(int n1, int n2, int n3, int n4,
2790                                             int n12,int n23,int n31,
2791                                             int n14,int n24,int n34, int ID)
2792 {
2793   return SMDS_Mesh::AddVolumeWithID
2794     ((SMDS_MeshNode*) myNodeIDFactory->MeshElement(n1) ,
2795      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n2) ,
2796      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n3) ,
2797      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n4) ,
2798      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n12),
2799      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n23),
2800      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n31),
2801      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n14),
2802      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n24),
2803      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n34),
2804      ID);
2805 }
2806
2807 //=======================================================================
2808 //function : AddVolumeWithID
2809 //purpose  : 2d order tetrahedron of 10 nodes
2810 //=======================================================================
2811 SMDS_MeshVolume* SMDS_Mesh::AddVolumeWithID(const SMDS_MeshNode * n1,
2812                                             const SMDS_MeshNode * n2,
2813                                             const SMDS_MeshNode * n3,
2814                                             const SMDS_MeshNode * n4,
2815                                             const SMDS_MeshNode * n12,
2816                                             const SMDS_MeshNode * n23,
2817                                             const SMDS_MeshNode * n31,
2818                                             const SMDS_MeshNode * n14, 
2819                                             const SMDS_MeshNode * n24,
2820                                             const SMDS_MeshNode * n34,
2821                                             int ID)
2822 {
2823   if ( !n1 || !n2 || !n3 || !n4 || !n12 || !n23 || !n31 || !n14 || !n24 || !n34)
2824     return 0;
2825   if(hasConstructionFaces()) {
2826     // creation quadratic faces - not implemented
2827     return 0;
2828   }
2829   SMDS_QuadraticVolumeOfNodes * volume =
2830     new SMDS_QuadraticVolumeOfNodes(n1,n2,n3,n4,n12,n23,n31,n14,n24,n34);
2831   myVolumes.Add(volume);
2832   myInfo.myNbQuadTetras++;
2833
2834   if (!registerElement(ID, volume)) {
2835     RemoveElement(volume, false);
2836     volume = NULL;
2837   }
2838   return volume;
2839 }
2840
2841
2842 //=======================================================================
2843 //function : AddVolume
2844 //purpose  : 
2845 //=======================================================================
2846 SMDS_MeshVolume* SMDS_Mesh::AddVolume(const SMDS_MeshNode * n1,
2847                                       const SMDS_MeshNode * n2, 
2848                                       const SMDS_MeshNode * n3,
2849                                       const SMDS_MeshNode * n4,
2850                                       const SMDS_MeshNode * n5, 
2851                                       const SMDS_MeshNode * n12,
2852                                       const SMDS_MeshNode * n23,
2853                                       const SMDS_MeshNode * n34,
2854                                       const SMDS_MeshNode * n41,
2855                                       const SMDS_MeshNode * n15, 
2856                                       const SMDS_MeshNode * n25,
2857                                       const SMDS_MeshNode * n35,
2858                                       const SMDS_MeshNode * n45)
2859 {
2860   int ID = myElementIDFactory->GetFreeID();
2861   SMDS_MeshVolume * v =
2862     SMDS_Mesh::AddVolumeWithID(n1, n2, n3, n4, n5, n12, n23, n34, n41,
2863                                n15, n25, n35, n45, ID);
2864   if(v==NULL) myElementIDFactory->ReleaseID(ID);
2865   return v;
2866 }
2867
2868 //=======================================================================
2869 //function : AddVolumeWithID
2870 //purpose  : 
2871 //=======================================================================
2872 SMDS_MeshVolume* SMDS_Mesh::AddVolumeWithID(int n1, int n2, int n3, int n4, int n5,
2873                                             int n12,int n23,int n34,int n41,
2874                                             int n15,int n25,int n35,int n45, int ID)
2875 {
2876   return SMDS_Mesh::AddVolumeWithID
2877     ((SMDS_MeshNode*) myNodeIDFactory->MeshElement(n1) ,
2878      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n2) ,
2879      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n3) ,
2880      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n4) ,
2881      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n5) ,
2882      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n12),
2883      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n23),
2884      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n34),
2885      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n41),
2886      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n15),
2887      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n25),
2888      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n35),
2889      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n45),
2890      ID);
2891 }
2892
2893 //=======================================================================
2894 //function : AddVolumeWithID
2895 //purpose  : 2d order pyramid of 13 nodes
2896 //=======================================================================
2897 SMDS_MeshVolume* SMDS_Mesh::AddVolumeWithID(const SMDS_MeshNode * n1,
2898                                             const SMDS_MeshNode * n2,
2899                                             const SMDS_MeshNode * n3,
2900                                             const SMDS_MeshNode * n4,
2901                                             const SMDS_MeshNode * n5, 
2902                                             const SMDS_MeshNode * n12,
2903                                             const SMDS_MeshNode * n23,
2904                                             const SMDS_MeshNode * n34,
2905                                             const SMDS_MeshNode * n41,
2906                                             const SMDS_MeshNode * n15, 
2907                                             const SMDS_MeshNode * n25,
2908                                             const SMDS_MeshNode * n35,
2909                                             const SMDS_MeshNode * n45,
2910                                             int ID)
2911 {
2912   if (!n1 || !n2 || !n3 || !n4 || !n5 || !n12 || !n23 ||
2913       !n34 || !n41 || !n15 || !n25 || !n35 || !n45)
2914     return 0;
2915   if(hasConstructionFaces()) {
2916     // creation quadratic faces - not implemented
2917     return 0;
2918   }
2919   SMDS_QuadraticVolumeOfNodes * volume =
2920     new SMDS_QuadraticVolumeOfNodes(n1,n2,n3,n4,n5,n12,n23,
2921                                     n34,n41,n15,n25,n35,n45);
2922   myVolumes.Add(volume);
2923   myInfo.myNbQuadPyramids++;
2924
2925   if (!registerElement(ID, volume)) {
2926     RemoveElement(volume, false);
2927     volume = NULL;
2928   }
2929   return volume;
2930 }
2931
2932
2933 //=======================================================================
2934 //function : AddVolume
2935 //purpose  : 
2936 //=======================================================================
2937 SMDS_MeshVolume* SMDS_Mesh::AddVolume(const SMDS_MeshNode * n1,
2938                                       const SMDS_MeshNode * n2, 
2939                                       const SMDS_MeshNode * n3,
2940                                       const SMDS_MeshNode * n4,
2941                                       const SMDS_MeshNode * n5, 
2942                                       const SMDS_MeshNode * n6, 
2943                                       const SMDS_MeshNode * n12,
2944                                       const SMDS_MeshNode * n23,
2945                                       const SMDS_MeshNode * n31, 
2946                                       const SMDS_MeshNode * n45,
2947                                       const SMDS_MeshNode * n56,
2948                                       const SMDS_MeshNode * n64, 
2949                                       const SMDS_MeshNode * n14,
2950                                       const SMDS_MeshNode * n25,
2951                                       const SMDS_MeshNode * n36)
2952 {
2953   int ID = myElementIDFactory->GetFreeID();
2954   SMDS_MeshVolume * v =
2955     SMDS_Mesh::AddVolumeWithID(n1, n2, n3, n4, n5, n6, n12, n23, n31,
2956                                n45, n56, n64, n14, n25, n36, ID);
2957   if(v==NULL) myElementIDFactory->ReleaseID(ID);
2958   return v;
2959 }
2960
2961 //=======================================================================
2962 //function : AddVolumeWithID
2963 //purpose  : 
2964 //=======================================================================
2965 SMDS_MeshVolume* SMDS_Mesh::AddVolumeWithID(int n1, int n2, int n3,
2966                                             int n4, int n5, int n6,
2967                                             int n12,int n23,int n31,
2968                                             int n45,int n56,int n64,
2969                                             int n14,int n25,int n36, int ID)
2970 {
2971   return SMDS_Mesh::AddVolumeWithID
2972     ((SMDS_MeshNode*) myNodeIDFactory->MeshElement(n1) ,
2973      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n2) ,
2974      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n3) ,
2975      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n4) ,
2976      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n5) ,
2977      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n6) ,
2978      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n12),
2979      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n23),
2980      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n31),
2981      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n45),
2982      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n56),
2983      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n64),
2984      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n14),
2985      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n25),
2986      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n36),
2987      ID);
2988 }
2989
2990 //=======================================================================
2991 //function : AddVolumeWithID
2992 //purpose  : 2d order Pentahedron with 15 nodes
2993 //=======================================================================
2994 SMDS_MeshVolume* SMDS_Mesh::AddVolumeWithID(const SMDS_MeshNode * n1,
2995                                             const SMDS_MeshNode * n2,
2996                                             const SMDS_MeshNode * n3,
2997                                             const SMDS_MeshNode * n4,
2998                                             const SMDS_MeshNode * n5, 
2999                                             const SMDS_MeshNode * n6, 
3000                                             const SMDS_MeshNode * n12,
3001                                             const SMDS_MeshNode * n23,
3002                                             const SMDS_MeshNode * n31, 
3003                                             const SMDS_MeshNode * n45,
3004                                             const SMDS_MeshNode * n56,
3005                                             const SMDS_MeshNode * n64, 
3006                                             const SMDS_MeshNode * n14,
3007                                             const SMDS_MeshNode * n25,
3008                                             const SMDS_MeshNode * n36,
3009                                             int ID)
3010 {
3011   if (!n1 || !n2 || !n3 || !n4 || !n5 || !n6 || !n12 || !n23 ||
3012       !n31 || !n45 || !n56 || !n64 || !n14 || !n25 || !n36)
3013     return 0;
3014   if(hasConstructionFaces()) {
3015     // creation quadratic faces - not implemented
3016     return 0;
3017   }
3018   SMDS_QuadraticVolumeOfNodes * volume =
3019     new SMDS_QuadraticVolumeOfNodes(n1,n2,n3,n4,n5,n6,n12,n23,n31,
3020                                     n45,n56,n64,n14,n25,n36);
3021   myVolumes.Add(volume);
3022   myInfo.myNbQuadPrisms++;
3023
3024   if (!registerElement(ID, volume)) {
3025     RemoveElement(volume, false);
3026     volume = NULL;
3027   }
3028   return volume;
3029 }
3030
3031
3032 //=======================================================================
3033 //function : AddVolume
3034 //purpose  : 
3035 //=======================================================================
3036 SMDS_MeshVolume* SMDS_Mesh::AddVolume(const SMDS_MeshNode * n1,
3037                                       const SMDS_MeshNode * n2, 
3038                                       const SMDS_MeshNode * n3,
3039                                       const SMDS_MeshNode * n4,
3040                                       const SMDS_MeshNode * n5, 
3041                                       const SMDS_MeshNode * n6, 
3042                                       const SMDS_MeshNode * n7,
3043                                       const SMDS_MeshNode * n8, 
3044                                       const SMDS_MeshNode * n12,
3045                                       const SMDS_MeshNode * n23,
3046                                       const SMDS_MeshNode * n34,
3047                                       const SMDS_MeshNode * n41, 
3048                                       const SMDS_MeshNode * n56,
3049                                       const SMDS_MeshNode * n67,
3050                                       const SMDS_MeshNode * n78,
3051                                       const SMDS_MeshNode * n85, 
3052                                       const SMDS_MeshNode * n15,
3053                                       const SMDS_MeshNode * n26,
3054                                       const SMDS_MeshNode * n37,
3055                                       const SMDS_MeshNode * n48)
3056 {
3057   int ID = myElementIDFactory->GetFreeID();
3058   SMDS_MeshVolume * v =
3059     SMDS_Mesh::AddVolumeWithID(n1, n2, n3, n4, n5, n6, n7, n8, n12, n23, n34, n41,
3060                                n56, n67, n78, n85, n15, n26, n37, n48, ID);
3061   if(v==NULL) myElementIDFactory->ReleaseID(ID);
3062   return v;
3063 }
3064
3065 //=======================================================================
3066 //function : AddVolumeWithID
3067 //purpose  : 
3068 //=======================================================================
3069 SMDS_MeshVolume* SMDS_Mesh::AddVolumeWithID(int n1, int n2, int n3, int n4,
3070                                             int n5, int n6, int n7, int n8,
3071                                             int n12,int n23,int n34,int n41,
3072                                             int n56,int n67,int n78,int n85,
3073                                             int n15,int n26,int n37,int n48, int ID)
3074 {
3075   return SMDS_Mesh::AddVolumeWithID
3076     ((SMDS_MeshNode*) myNodeIDFactory->MeshElement(n1),
3077      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n2),
3078      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n3),
3079      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n4),
3080      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n5),
3081      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n6),
3082      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n7),
3083      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n8),
3084      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n12),
3085      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n23),
3086      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n34),
3087      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n41),
3088      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n56),
3089      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n67),
3090      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n78),
3091      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n85),
3092      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n15),
3093      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n26),
3094      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n37),
3095      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n48),
3096      ID);
3097 }
3098
3099 //=======================================================================
3100 //function : AddVolumeWithID
3101 //purpose  : 2d order Hexahedrons with 20 nodes
3102 //=======================================================================
3103 SMDS_MeshVolume* SMDS_Mesh::AddVolumeWithID(const SMDS_MeshNode * n1,
3104                                             const SMDS_MeshNode * n2,
3105                                             const SMDS_MeshNode * n3,
3106                                             const SMDS_MeshNode * n4,
3107                                             const SMDS_MeshNode * n5, 
3108                                             const SMDS_MeshNode * n6, 
3109                                             const SMDS_MeshNode * n7,
3110                                             const SMDS_MeshNode * n8, 
3111                                             const SMDS_MeshNode * n12,
3112                                             const SMDS_MeshNode * n23,
3113                                             const SMDS_MeshNode * n34,
3114                                             const SMDS_MeshNode * n41, 
3115                                             const SMDS_MeshNode * n56,
3116                                             const SMDS_MeshNode * n67,
3117                                             const SMDS_MeshNode * n78,
3118                                             const SMDS_MeshNode * n85, 
3119                                             const SMDS_MeshNode * n15,
3120                                             const SMDS_MeshNode * n26,
3121                                             const SMDS_MeshNode * n37,
3122                                             const SMDS_MeshNode * n48,
3123                                             int ID)
3124 {
3125   if (!n1 || !n2 || !n3 || !n4 || !n5 || !n6 || !n7 || !n8 || !n12 || !n23 ||
3126       !n34 || !n41 || !n56 || !n67 || !n78 || !n85 || !n15 || !n26 || !n37 || !n48)
3127     return 0;
3128   if(hasConstructionFaces()) {
3129     return 0;
3130     // creation quadratic faces - not implemented
3131   }
3132   SMDS_QuadraticVolumeOfNodes * volume =
3133     new SMDS_QuadraticVolumeOfNodes(n1,n2,n3,n4,n5,n6,n7,n8,n12,n23,n34,n41,
3134                                     n56,n67,n78,n85,n15,n26,n37,n48);
3135   myVolumes.Add(volume);
3136   myInfo.myNbQuadHexas++;
3137
3138   if (!registerElement(ID, volume)) {
3139     RemoveElement(volume, false);
3140     volume = NULL;
3141   }
3142   return volume;
3143 }