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