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