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