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