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