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