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