Salome HOME
PAL14858 (The Mesh Info Dialog Box is too slow)
[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     myInfo.myNbTriangles++;
1061     return face;
1062   }
1063   else
1064   {
1065     SMDS_MeshFace * face = new SMDS_FaceOfNodes(node1,node2,node3);
1066     myFaces.Add(face);
1067     myInfo.myNbTriangles++;
1068     return face;
1069   }
1070 }
1071
1072 ///////////////////////////////////////////////////////////////////////////////
1073 ///Create a quadrangle and add it to the current mesh. This methode do not bind
1074 ///a ID to the create triangle.
1075 ///////////////////////////////////////////////////////////////////////////////
1076 SMDS_MeshFace * SMDS_Mesh::createQuadrangle(const SMDS_MeshNode * node1,
1077                                             const SMDS_MeshNode * node2,
1078                                             const SMDS_MeshNode * node3,
1079                                             const SMDS_MeshNode * node4)
1080 {
1081   if ( !node1 || !node2 || !node3 || !node4 ) return 0;
1082   CheckMemory();
1083   if(hasConstructionEdges())
1084   {
1085     SMDS_MeshEdge *edge1, *edge2, *edge3, *edge4;
1086     edge1=FindEdgeOrCreate(node1,node2);
1087     edge2=FindEdgeOrCreate(node2,node3);
1088     edge3=FindEdgeOrCreate(node3,node4);
1089     edge4=FindEdgeOrCreate(node4,node1);
1090
1091     SMDS_MeshFace * face = new SMDS_FaceOfEdges(edge1,edge2,edge3,edge4);
1092     myFaces.Add(face);
1093     myInfo.myNbQuadrangles++;
1094     return face;
1095   }
1096   else
1097   {
1098     SMDS_MeshFace * face = new SMDS_FaceOfNodes(node1,node2,node3,node4);
1099     myFaces.Add(face);
1100     myInfo.myNbQuadrangles++;
1101     return face;
1102   }
1103 }
1104
1105 ///////////////////////////////////////////////////////////////////////////////
1106 /// Remove a node and all the elements which own this node
1107 ///////////////////////////////////////////////////////////////////////////////
1108
1109 void SMDS_Mesh::RemoveNode(const SMDS_MeshNode * node)
1110 {
1111         RemoveElement(node, true);
1112 }
1113
1114 ///////////////////////////////////////////////////////////////////////////////
1115 /// Remove an edge and all the elements which own this edge
1116 ///////////////////////////////////////////////////////////////////////////////
1117
1118 void SMDS_Mesh::RemoveEdge(const SMDS_MeshEdge * edge)
1119 {
1120         RemoveElement(edge,true);
1121 }
1122
1123 ///////////////////////////////////////////////////////////////////////////////
1124 /// Remove an face and all the elements which own this face
1125 ///////////////////////////////////////////////////////////////////////////////
1126
1127 void SMDS_Mesh::RemoveFace(const SMDS_MeshFace * face)
1128 {
1129         RemoveElement(face, true);
1130 }
1131
1132 ///////////////////////////////////////////////////////////////////////////////
1133 /// Remove a volume
1134 ///////////////////////////////////////////////////////////////////////////////
1135
1136 void SMDS_Mesh::RemoveVolume(const SMDS_MeshVolume * volume)
1137 {
1138         RemoveElement(volume, true);
1139 }
1140
1141 //=======================================================================
1142 //function : RemoveFromParent
1143 //purpose  :
1144 //=======================================================================
1145
1146 bool SMDS_Mesh::RemoveFromParent()
1147 {
1148         if (myParent==NULL) return false;
1149         else return (myParent->RemoveSubMesh(this));
1150 }
1151
1152 //=======================================================================
1153 //function : RemoveSubMesh
1154 //purpose  :
1155 //=======================================================================
1156
1157 bool SMDS_Mesh::RemoveSubMesh(const SMDS_Mesh * aMesh)
1158 {
1159         bool found = false;
1160
1161         list<SMDS_Mesh *>::iterator itmsh=myChildren.begin();
1162         for (; itmsh!=myChildren.end() && !found; itmsh++)
1163         {
1164                 SMDS_Mesh * submesh = *itmsh;
1165                 if (submesh == aMesh)
1166                 {
1167                         found = true;
1168                         myChildren.erase(itmsh);
1169                 }
1170         }
1171
1172         return found;
1173 }
1174
1175 //=======================================================================
1176 //function : ChangeElementNodes
1177 //purpose  : 
1178 //=======================================================================
1179
1180 bool SMDS_Mesh::ChangeElementNodes(const SMDS_MeshElement * elem,
1181                                    const SMDS_MeshNode    * nodes[],
1182                                    const int                nbnodes)
1183 {
1184   // keep current nodes of elem
1185   set<const SMDS_MeshElement*> oldNodes;
1186   SMDS_ElemIteratorPtr itn = elem->nodesIterator();
1187   while(itn->more())
1188     oldNodes.insert(  itn->next() );
1189
1190   // change nodes
1191   bool Ok = false;
1192   switch ( elem->GetType() )
1193   {
1194   case SMDSAbs_Edge: {
1195     if ( nbnodes == 2 ) {
1196       const SMDS_MeshEdge* edge = dynamic_cast<const SMDS_MeshEdge*>( elem );
1197       if ( edge )
1198         Ok = const_cast<SMDS_MeshEdge*>( edge )->ChangeNodes( nodes[0], nodes[1] );
1199     }
1200     else if ( nbnodes == 3 ) {
1201       const SMDS_QuadraticEdge* edge = dynamic_cast<const SMDS_QuadraticEdge*>( elem );
1202       if ( edge )
1203         Ok = const_cast<SMDS_QuadraticEdge*>( edge )->ChangeNodes( nodes[0], nodes[1], nodes[2] );
1204     }
1205     break;
1206   }
1207   case SMDSAbs_Face: {
1208     const SMDS_FaceOfNodes* face = dynamic_cast<const SMDS_FaceOfNodes*>( elem );
1209     if ( face ) {
1210       Ok = const_cast<SMDS_FaceOfNodes*>( face )->ChangeNodes( nodes, nbnodes );
1211     }
1212     else {
1213       const SMDS_QuadraticFaceOfNodes* QF =
1214         dynamic_cast<const SMDS_QuadraticFaceOfNodes*>( elem );
1215       if ( QF ) {
1216         Ok = const_cast<SMDS_QuadraticFaceOfNodes*>( QF )->ChangeNodes( nodes, nbnodes );
1217       }
1218       else {
1219         /// ??? begin
1220         const SMDS_PolygonalFaceOfNodes* face = dynamic_cast<const SMDS_PolygonalFaceOfNodes*>(elem);
1221         if (face) {
1222           Ok = const_cast<SMDS_PolygonalFaceOfNodes*>(face)->ChangeNodes(nodes, nbnodes);
1223         }
1224         /// ??? end
1225       }
1226     }
1227     break;
1228   }
1229   //case SMDSAbs_PolygonalFace: {
1230   //  const SMDS_PolygonalFaceOfNodes* face = dynamic_cast<const SMDS_PolygonalFaceOfNodes*>(elem);
1231   //  if (face) {
1232   //    Ok = const_cast<SMDS_PolygonalFaceOfNodes*>(face)->ChangeNodes(nodes, nbnodes);
1233   //  }
1234   //  break;
1235   //}
1236   case SMDSAbs_Volume: {
1237     const SMDS_VolumeOfNodes* vol = dynamic_cast<const SMDS_VolumeOfNodes*>( elem );
1238     if ( vol ) {
1239       Ok = const_cast<SMDS_VolumeOfNodes*>( vol )->ChangeNodes( nodes, nbnodes );
1240     }
1241     else {
1242       const SMDS_QuadraticVolumeOfNodes* QV = dynamic_cast<const SMDS_QuadraticVolumeOfNodes*>( elem );
1243       if ( QV ) {
1244         Ok = const_cast<SMDS_QuadraticVolumeOfNodes*>( QV )->ChangeNodes( nodes, nbnodes );
1245       }
1246     }
1247     break;
1248   }
1249   default:
1250     MESSAGE ( "WRONG ELEM TYPE");
1251   }
1252
1253   if ( Ok ) { // update InverseElements
1254
1255     // AddInverseElement to new nodes
1256     for ( int i = 0; i < nbnodes; i++ )
1257       if ( oldNodes.find( nodes[i] ) == oldNodes.end() )
1258         // new node
1259         const_cast<SMDS_MeshNode*>( nodes[i] )->AddInverseElement( elem );
1260       else
1261         // remove from oldNodes a node that remains in elem
1262         oldNodes.erase( nodes[i] );
1263
1264
1265     // RemoveInverseElement from the nodes removed from elem
1266     set<const SMDS_MeshElement*>::iterator it;
1267     for ( it = oldNodes.begin(); it != oldNodes.end(); it++ )
1268     {
1269       SMDS_MeshNode * n = static_cast<SMDS_MeshNode *>
1270         (const_cast<SMDS_MeshElement *>( *it ));
1271       n->RemoveInverseElement( elem );
1272     }
1273   }
1274
1275   //MESSAGE ( "::ChangeNodes() Ok = " << Ok);
1276
1277   return Ok;
1278 }
1279
1280 //=======================================================================
1281 //function : ChangePolyhedronNodes
1282 //purpose  : to change nodes of polyhedral volume
1283 //=======================================================================
1284 bool SMDS_Mesh::ChangePolyhedronNodes (const SMDS_MeshElement * elem,
1285                                        std::vector<const SMDS_MeshNode*> nodes,
1286                                        std::vector<int>                  quantities)
1287 {
1288   if (elem->GetType() != SMDSAbs_Volume) {
1289     MESSAGE("WRONG ELEM TYPE");
1290     return false;
1291   }
1292
1293   const SMDS_PolyhedralVolumeOfNodes* vol = dynamic_cast<const SMDS_PolyhedralVolumeOfNodes*>(elem);
1294   if (!vol) {
1295     return false;
1296   }
1297
1298   // keep current nodes of elem
1299   set<const SMDS_MeshElement*> oldNodes;
1300   SMDS_ElemIteratorPtr itn = elem->nodesIterator();
1301   while (itn->more()) {
1302     oldNodes.insert(itn->next());
1303   }
1304
1305   // change nodes
1306   bool Ok = const_cast<SMDS_PolyhedralVolumeOfNodes*>(vol)->ChangeNodes(nodes, quantities);
1307   if (!Ok) {
1308     return false;
1309   }
1310
1311   // update InverseElements
1312
1313   // AddInverseElement to new nodes
1314   int nbnodes = nodes.size();
1315   for (int i = 0; i < nbnodes; i++) {
1316     if (oldNodes.find(nodes[i]) == oldNodes.end()) {
1317       // new node
1318       const_cast<SMDS_MeshNode*>(nodes[i])->AddInverseElement(elem);
1319     } else {
1320       // remove from oldNodes a node that remains in elem
1321       oldNodes.erase(nodes[i]);
1322     }
1323   }
1324
1325   // RemoveInverseElement from the nodes removed from elem
1326   set<const SMDS_MeshElement*>::iterator it;
1327   for (it = oldNodes.begin(); it != oldNodes.end(); it++) {
1328     SMDS_MeshNode * n = static_cast<SMDS_MeshNode *>
1329       (const_cast<SMDS_MeshElement *>( *it ));
1330     n->RemoveInverseElement(elem);
1331   }
1332
1333   return Ok;
1334 }
1335
1336
1337 //=======================================================================
1338 //function : FindEdge
1339 //purpose  :
1340 //=======================================================================
1341
1342 const SMDS_MeshEdge* SMDS_Mesh::FindEdge(int idnode1, int idnode2) const
1343 {
1344   const SMDS_MeshNode * node1=FindNode(idnode1);
1345   const SMDS_MeshNode * node2=FindNode(idnode2);
1346   if((node1==NULL)||(node2==NULL)) return NULL;
1347   return FindEdge(node1,node2);
1348 }
1349
1350 //#include "Profiler.h"
1351 const SMDS_MeshEdge* SMDS_Mesh::FindEdge(const SMDS_MeshNode * node1,
1352                                          const SMDS_MeshNode * node2)
1353 {
1354   if ( !node1 ) return 0;
1355   const SMDS_MeshEdge * toReturn=NULL;
1356   //PROFILER_Init();
1357   //PROFILER_Set();
1358   SMDS_ElemIteratorPtr it1=node1->GetInverseElementIterator(SMDSAbs_Edge);
1359   //PROFILER_Get(0);
1360   //PROFILER_Set();
1361   while(it1->more()) {
1362     const SMDS_MeshElement * e = it1->next();
1363     if ( e->NbNodes() == 2 && e->GetNodeIndex( node2 ) >= 0 ) {
1364       toReturn = static_cast<const SMDS_MeshEdge*>( e );
1365       break;
1366     }
1367   }
1368   //PROFILER_Get(1);
1369   return toReturn;
1370 }
1371
1372
1373 //=======================================================================
1374 //function : FindEdgeOrCreate
1375 //purpose  :
1376 //=======================================================================
1377
1378 SMDS_MeshEdge* SMDS_Mesh::FindEdgeOrCreate(const SMDS_MeshNode * node1,
1379                                            const SMDS_MeshNode * node2) 
1380 {
1381   if ( !node1 || !node2) return 0;
1382   SMDS_MeshEdge * toReturn=NULL;
1383   toReturn=const_cast<SMDS_MeshEdge*>(FindEdge(node1,node2));
1384   if(toReturn==NULL) {
1385     CheckMemory();
1386     toReturn=new SMDS_MeshEdge(node1,node2);
1387     myEdges.Add(toReturn);
1388     myInfo.myNbEdges++;
1389   }
1390   return toReturn;
1391 }
1392
1393
1394 //=======================================================================
1395 //function : FindEdge
1396 //purpose  :
1397 //=======================================================================
1398
1399 const SMDS_MeshEdge* SMDS_Mesh::FindEdge(int idnode1, int idnode2,
1400                                          int idnode3) const
1401 {
1402   const SMDS_MeshNode * node1=FindNode(idnode1);
1403   const SMDS_MeshNode * node2=FindNode(idnode2);
1404   const SMDS_MeshNode * node3=FindNode(idnode3);
1405   return FindEdge(node1,node2,node3);
1406 }
1407
1408 const SMDS_MeshEdge* SMDS_Mesh::FindEdge(const SMDS_MeshNode * node1,
1409                                          const SMDS_MeshNode * node2,
1410                                          const SMDS_MeshNode * node3)
1411 {
1412   if ( !node1 ) return 0;
1413   SMDS_ElemIteratorPtr it1 = node1->GetInverseElementIterator(SMDSAbs_Edge);
1414   while(it1->more()) {
1415     const SMDS_MeshElement * e = it1->next();
1416     if ( e->NbNodes() == 3 ) {
1417       SMDS_ElemIteratorPtr it2 = e->nodesIterator();
1418       while(it2->more()) {
1419         const SMDS_MeshElement* n = it2->next();
1420         if( n!=node1 &&
1421             n!=node2 &&
1422             n!=node3 )
1423         {
1424           e = 0;
1425           break;
1426         }
1427       }
1428       if ( e )
1429         return static_cast<const SMDS_MeshEdge *> (e);
1430     }
1431   }
1432   return 0;
1433 }
1434
1435
1436 //=======================================================================
1437 //function : FindFace
1438 //purpose  :
1439 //=======================================================================
1440
1441 const SMDS_MeshFace* SMDS_Mesh::FindFace(int idnode1, int idnode2,
1442         int idnode3) const
1443 {
1444   const SMDS_MeshNode * node1=FindNode(idnode1);
1445   const SMDS_MeshNode * node2=FindNode(idnode2);
1446   const SMDS_MeshNode * node3=FindNode(idnode3);
1447   return FindFace(node1, node2, node3);
1448 }
1449
1450 const SMDS_MeshFace* SMDS_Mesh::FindFace(const SMDS_MeshNode *node1,
1451                                          const SMDS_MeshNode *node2,
1452                                          const SMDS_MeshNode *node3)
1453 {
1454   if ( !node1 ) return 0;
1455   SMDS_ElemIteratorPtr it1 = node1->GetInverseElementIterator(SMDSAbs_Face);
1456   while(it1->more()) {
1457     const SMDS_MeshElement * e = it1->next();
1458     if ( e->NbNodes() == 3 ) {
1459       SMDS_ElemIteratorPtr it2 = e->nodesIterator();
1460       while(it2->more()) {
1461         const SMDS_MeshElement* n = it2->next();
1462         if( n!=node1 &&
1463             n!=node2 &&
1464             n!=node3 )
1465         {
1466           e = 0;
1467           break;
1468         }
1469       }
1470       if ( e )
1471         return static_cast<const SMDS_MeshFace *> (e);
1472     }
1473   }
1474   return 0;
1475 }
1476
1477 SMDS_MeshFace* SMDS_Mesh::FindFaceOrCreate(const SMDS_MeshNode *node1,
1478                                            const SMDS_MeshNode *node2,
1479                                            const SMDS_MeshNode *node3)
1480 {
1481   SMDS_MeshFace * toReturn=NULL;
1482   toReturn = const_cast<SMDS_MeshFace*>(FindFace(node1,node2,node3));
1483   if(toReturn==NULL) {
1484     toReturn = createTriangle(node1,node2,node3);
1485   }
1486   return toReturn;
1487 }
1488
1489
1490 //=======================================================================
1491 //function : FindFace
1492 //purpose  :
1493 //=======================================================================
1494
1495 const SMDS_MeshFace* SMDS_Mesh::FindFace(int idnode1, int idnode2,
1496                                          int idnode3, int idnode4) const
1497 {
1498   const SMDS_MeshNode * node1=FindNode(idnode1);
1499   const SMDS_MeshNode * node2=FindNode(idnode2);
1500   const SMDS_MeshNode * node3=FindNode(idnode3);
1501   const SMDS_MeshNode * node4=FindNode(idnode4);
1502   return FindFace(node1, node2, node3, node4);
1503 }
1504
1505 const SMDS_MeshFace* SMDS_Mesh::FindFace(const SMDS_MeshNode *node1,
1506                                          const SMDS_MeshNode *node2,
1507                                          const SMDS_MeshNode *node3,
1508                                          const SMDS_MeshNode *node4)
1509 {
1510   if ( !node1 ) return 0;
1511   SMDS_ElemIteratorPtr it1 = node1->GetInverseElementIterator(SMDSAbs_Face);
1512   while(it1->more()) {
1513     const SMDS_MeshElement * e = it1->next();
1514     if ( e->NbNodes() == 4 ) {
1515       SMDS_ElemIteratorPtr it2 = e->nodesIterator();
1516       while(it2->more()) {
1517         const SMDS_MeshElement* n = it2->next();
1518         if( n!=node1 &&
1519             n!=node2 &&
1520             n!=node3 &&
1521             n!=node4 )
1522         {
1523           e = 0;
1524           break;
1525         }
1526       }
1527       if ( e )
1528         return static_cast<const SMDS_MeshFace *> (e);
1529     }
1530   }
1531   return 0;
1532 }
1533
1534 SMDS_MeshFace* SMDS_Mesh::FindFaceOrCreate(const SMDS_MeshNode *node1,
1535                                            const SMDS_MeshNode *node2,
1536                                            const SMDS_MeshNode *node3,
1537                                            const SMDS_MeshNode *node4)
1538 {
1539   SMDS_MeshFace * toReturn=NULL;
1540   toReturn=const_cast<SMDS_MeshFace*>(FindFace(node1,node2,node3,node4));
1541   if(toReturn==NULL) {
1542     toReturn=createQuadrangle(node1,node2,node3,node4);
1543   }
1544   return toReturn;
1545 }
1546
1547
1548 //=======================================================================
1549 //function : FindFace
1550 //purpose  :quadratic triangle
1551 //=======================================================================
1552
1553 const SMDS_MeshFace* SMDS_Mesh::FindFace(int idnode1, int idnode2,
1554                                          int idnode3, int idnode4,
1555                                          int idnode5, int idnode6) const
1556 {
1557   const SMDS_MeshNode * node1 = FindNode(idnode1);
1558   const SMDS_MeshNode * node2 = FindNode(idnode2);
1559   const SMDS_MeshNode * node3 = FindNode(idnode3);
1560   const SMDS_MeshNode * node4 = FindNode(idnode4);
1561   const SMDS_MeshNode * node5 = FindNode(idnode5);
1562   const SMDS_MeshNode * node6 = FindNode(idnode6);
1563   return FindFace(node1, node2, node3, node4, node5, node6);
1564 }
1565
1566 const SMDS_MeshFace* SMDS_Mesh::FindFace(const SMDS_MeshNode *node1,
1567                                          const SMDS_MeshNode *node2,
1568                                          const SMDS_MeshNode *node3,
1569                                          const SMDS_MeshNode *node4,
1570                                          const SMDS_MeshNode *node5,
1571                                          const SMDS_MeshNode *node6)
1572 {
1573   if ( !node1 ) return 0;
1574   SMDS_ElemIteratorPtr it1 = node1->GetInverseElementIterator(SMDSAbs_Face);
1575   while(it1->more()) {
1576     const SMDS_MeshElement * e = it1->next();
1577     if ( e->NbNodes() == 6 ) {
1578       SMDS_ElemIteratorPtr it2 = e->nodesIterator();
1579       while(it2->more()) {
1580         const SMDS_MeshElement* n = it2->next();
1581         if( n!=node1 &&
1582             n!=node2 &&
1583             n!=node3 &&
1584             n!=node4 &&
1585             n!=node5 &&
1586             n!=node6 )
1587         {
1588           e = 0;
1589           break;
1590         }
1591       }
1592       if ( e )
1593         return static_cast<const SMDS_MeshFace *> (e);
1594     }
1595   }
1596   return 0;
1597 }
1598
1599
1600 //=======================================================================
1601 //function : FindFace
1602 //purpose  : quadratic quadrangle
1603 //=======================================================================
1604
1605 const SMDS_MeshFace* SMDS_Mesh::FindFace(int idnode1, int idnode2,
1606                                          int idnode3, int idnode4,
1607                                          int idnode5, int idnode6,
1608                                          int idnode7, int idnode8) const
1609 {
1610   const SMDS_MeshNode * node1 = FindNode(idnode1);
1611   const SMDS_MeshNode * node2 = FindNode(idnode2);
1612   const SMDS_MeshNode * node3 = FindNode(idnode3);
1613   const SMDS_MeshNode * node4 = FindNode(idnode4);
1614   const SMDS_MeshNode * node5 = FindNode(idnode5);
1615   const SMDS_MeshNode * node6 = FindNode(idnode6);
1616   const SMDS_MeshNode * node7 = FindNode(idnode7);
1617   const SMDS_MeshNode * node8 = FindNode(idnode8);
1618   return FindFace(node1, node2, node3, node4, node5, node6, node7, node8);
1619 }
1620
1621 const SMDS_MeshFace* SMDS_Mesh::FindFace(const SMDS_MeshNode *node1,
1622                                          const SMDS_MeshNode *node2,
1623                                          const SMDS_MeshNode *node3,
1624                                          const SMDS_MeshNode *node4,
1625                                          const SMDS_MeshNode *node5,
1626                                          const SMDS_MeshNode *node6,
1627                                          const SMDS_MeshNode *node7,
1628                                          const SMDS_MeshNode *node8)
1629 {
1630   if ( !node1 ) return 0;
1631   SMDS_ElemIteratorPtr it1 = node1->GetInverseElementIterator(SMDSAbs_Face);
1632   while(it1->more()) {
1633     const SMDS_MeshElement * e = it1->next();
1634     if ( e->NbNodes() == 8 ) {
1635       SMDS_ElemIteratorPtr it2 = e->nodesIterator();
1636       while(it2->more()) {
1637         const SMDS_MeshElement* n = it2->next();
1638         if( n!=node1 &&
1639             n!=node2 &&
1640             n!=node3 &&
1641             n!=node4 &&
1642             n!=node5 &&
1643             n!=node6 &&
1644             n!=node7 &&
1645             n!=node8 )
1646         {
1647           e = 0;
1648           break;
1649         }
1650       }
1651       if ( e )
1652         return static_cast<const SMDS_MeshFace *> (e);
1653     }
1654   }
1655   return 0;
1656 }
1657
1658
1659 //=======================================================================
1660 //function : FindElement
1661 //purpose  :
1662 //=======================================================================
1663
1664 const SMDS_MeshElement* SMDS_Mesh::FindElement(int IDelem) const
1665 {
1666   return myElementIDFactory->MeshElement(IDelem);
1667 }
1668
1669 //=======================================================================
1670 //function : FindFace
1671 //purpose  : find polygon
1672 //=======================================================================
1673
1674 const SMDS_MeshFace* SMDS_Mesh::FindFace (std::vector<int> nodes_ids) const
1675 {
1676   int nbnodes = nodes_ids.size();
1677   std::vector<const SMDS_MeshNode *> poly_nodes (nbnodes);
1678   for (int inode = 0; inode < nbnodes; inode++) {
1679     const SMDS_MeshNode * node = FindNode(nodes_ids[inode]);
1680     if (node == NULL) return NULL;
1681   }
1682   return FindFace(poly_nodes);
1683 }
1684
1685 const SMDS_MeshFace* SMDS_Mesh::FindFace (std::vector<const SMDS_MeshNode *> nodes)
1686 {
1687   if ( nodes.size() > 2 && nodes[0] ) {
1688     SMDS_ElemIteratorPtr itF = nodes[0]->GetInverseElementIterator(SMDSAbs_Face);
1689     while (itF->more()) {
1690       const SMDS_MeshElement* f = itF->next();
1691       if ( f->NbNodes() == nodes.size() ) {
1692         SMDS_ElemIteratorPtr it2 = f->nodesIterator();
1693         while(it2->more()) {
1694           if ( find( nodes.begin(), nodes.end(), it2->next() ) == nodes.end() ) {
1695             f = 0;
1696             break;
1697           }
1698         }
1699         if ( f )
1700           return static_cast<const SMDS_MeshFace *> (f);
1701       }
1702     }
1703   }
1704   return NULL;
1705 }
1706
1707 //=======================================================================
1708 //function : DumpNodes
1709 //purpose  : 
1710 //=======================================================================
1711
1712 void SMDS_Mesh::DumpNodes() const
1713 {
1714         MESSAGE("dump nodes of mesh : ");
1715         SMDS_NodeIteratorPtr itnode=nodesIterator();
1716         while(itnode->more()) MESSAGE(itnode->next());
1717 }
1718
1719 //=======================================================================
1720 //function : DumpEdges
1721 //purpose  : 
1722 //=======================================================================
1723
1724 void SMDS_Mesh::DumpEdges() const
1725 {
1726         MESSAGE("dump edges of mesh : ");
1727         SMDS_EdgeIteratorPtr itedge=edgesIterator();
1728         while(itedge->more()) MESSAGE(itedge->next());
1729 }
1730
1731 //=======================================================================
1732 //function : DumpFaces
1733 //purpose  : 
1734 //=======================================================================
1735
1736 void SMDS_Mesh::DumpFaces() const
1737 {
1738         MESSAGE("dump faces of mesh : ");
1739         SMDS_FaceIteratorPtr itface=facesIterator();
1740         while(itface->more()) MESSAGE(itface->next());
1741 }
1742
1743 //=======================================================================
1744 //function : DumpVolumes
1745 //purpose  : 
1746 //=======================================================================
1747
1748 void SMDS_Mesh::DumpVolumes() const
1749 {
1750         MESSAGE("dump volumes of mesh : ");
1751         SMDS_VolumeIteratorPtr itvol=volumesIterator();
1752         while(itvol->more()) MESSAGE(itvol->next());
1753 }
1754
1755 //=======================================================================
1756 //function : DebugStats
1757 //purpose  : 
1758 //=======================================================================
1759
1760 void SMDS_Mesh::DebugStats() const
1761 {
1762         MESSAGE("Debug stats of mesh : ");
1763
1764         MESSAGE("===== NODES ====="<<NbNodes());
1765         MESSAGE("===== EDGES ====="<<NbEdges());
1766         MESSAGE("===== FACES ====="<<NbFaces());
1767         MESSAGE("===== VOLUMES ====="<<NbVolumes());
1768
1769         MESSAGE("End Debug stats of mesh ");
1770
1771         //#ifdef DEB
1772         
1773         SMDS_NodeIteratorPtr itnode=nodesIterator();
1774         int sizeofnodes = 0;
1775         int sizeoffaces = 0;
1776
1777         while(itnode->more())
1778         {
1779                 const SMDS_MeshNode *node = itnode->next();
1780
1781                 sizeofnodes += sizeof(*node);
1782                 
1783                 SMDS_ElemIteratorPtr it = node->GetInverseElementIterator();
1784                 while(it->more())
1785                 {
1786                         const SMDS_MeshElement *me = it->next();
1787                         sizeofnodes += sizeof(me);
1788                 }
1789
1790         }
1791
1792         SMDS_FaceIteratorPtr itface=facesIterator();
1793         while(itface->more())
1794         {
1795                 const SMDS_MeshElement *face = itface->next();          
1796                 sizeoffaces += sizeof(*face);
1797
1798         }
1799         MESSAGE("total size of node elements = " << sizeofnodes);;
1800         MESSAGE("total size of face elements = " << sizeoffaces);;
1801
1802         //#endif
1803 }
1804
1805 ///////////////////////////////////////////////////////////////////////////////
1806 /// Return the number of nodes
1807 ///////////////////////////////////////////////////////////////////////////////
1808 int SMDS_Mesh::NbNodes() const
1809 {
1810         return myNodes.Size();
1811 }
1812
1813 ///////////////////////////////////////////////////////////////////////////////
1814 /// Return the number of edges (including construction edges)
1815 ///////////////////////////////////////////////////////////////////////////////
1816 int SMDS_Mesh::NbEdges() const
1817 {
1818         return myEdges.Size();
1819 }
1820
1821 ///////////////////////////////////////////////////////////////////////////////
1822 /// Return the number of faces (including construction faces)
1823 ///////////////////////////////////////////////////////////////////////////////
1824 int SMDS_Mesh::NbFaces() const
1825 {
1826         return myFaces.Size();
1827 }
1828
1829 ///////////////////////////////////////////////////////////////////////////////
1830 /// Return the number of volumes
1831 ///////////////////////////////////////////////////////////////////////////////
1832 int SMDS_Mesh::NbVolumes() const
1833 {
1834         return myVolumes.Size();
1835 }
1836
1837 ///////////////////////////////////////////////////////////////////////////////
1838 /// Return the number of child mesh of this mesh.
1839 /// Note that the tree structure of SMDS_Mesh seems to be unused in this version
1840 /// (2003-09-08) of SMESH
1841 ///////////////////////////////////////////////////////////////////////////////
1842 int SMDS_Mesh::NbSubMesh() const
1843 {
1844         return myChildren.size();
1845 }
1846
1847 ///////////////////////////////////////////////////////////////////////////////
1848 /// Destroy the mesh and all its elements
1849 /// All pointer on elements owned by this mesh become illegals.
1850 ///////////////////////////////////////////////////////////////////////////////
1851 SMDS_Mesh::~SMDS_Mesh()
1852 {
1853   list<SMDS_Mesh*>::iterator itc=myChildren.begin();
1854   while(itc!=myChildren.end())
1855   {
1856     delete *itc;
1857     itc++;
1858   }
1859
1860   SetOfNodes::Iterator itn(myNodes);
1861   for (; itn.More(); itn.Next())
1862     delete itn.Value();
1863
1864   SetOfEdges::Iterator ite(myEdges);
1865   for (; ite.More(); ite.Next())
1866   {
1867     SMDS_MeshElement* elem = ite.Value();
1868     if(myParent!=NULL)
1869       myElementIDFactory->ReleaseID(elem->GetID());
1870     delete elem;
1871   }
1872
1873   SetOfFaces::Iterator itf(myFaces);
1874   for (; itf.More(); itf.Next())
1875   {
1876     SMDS_MeshElement* elem = itf.Value();
1877     if(myParent!=NULL)
1878       myElementIDFactory->ReleaseID(elem->GetID());
1879     delete elem;
1880   }
1881
1882   SetOfVolumes::Iterator itv(myVolumes);
1883   for (; itv.More(); itv.Next())
1884   {
1885     SMDS_MeshElement* elem = itv.Value();
1886     if(myParent!=NULL)
1887       myElementIDFactory->ReleaseID(elem->GetID());
1888     delete elem;
1889   }
1890
1891   if(myParent==NULL)
1892   {
1893     delete myNodeIDFactory;
1894     delete myElementIDFactory;
1895   }
1896 }
1897
1898 ///////////////////////////////////////////////////////////////////////////////
1899 /// Return true if this mesh create faces with edges.
1900 /// A false returned value mean that faces are created with nodes. A concequence
1901 /// is, iteration on edges (SMDS_Element::edgesIterator) will be unavailable.
1902 ///////////////////////////////////////////////////////////////////////////////
1903 bool SMDS_Mesh::hasConstructionEdges()
1904 {
1905         return myHasConstructionEdges;
1906 }
1907
1908 ///////////////////////////////////////////////////////////////////////////////
1909 /// Return true if this mesh create volumes with faces
1910 /// A false returned value mean that volumes are created with nodes or edges.
1911 /// (see hasConstructionEdges)
1912 /// A concequence is, iteration on faces (SMDS_Element::facesIterator) will be
1913 /// unavailable.
1914 ///////////////////////////////////////////////////////////////////////////////
1915 bool SMDS_Mesh::hasConstructionFaces()
1916 {
1917         return myHasConstructionFaces;
1918 }
1919
1920 ///////////////////////////////////////////////////////////////////////////////
1921 /// Return true if nodes are linked to the finit elements, they are belonging to.
1922 /// Currently, It always return true.
1923 ///////////////////////////////////////////////////////////////////////////////
1924 bool SMDS_Mesh::hasInverseElements()
1925 {
1926         return myHasInverseElements;
1927 }
1928
1929 ///////////////////////////////////////////////////////////////////////////////
1930 /// Make this mesh creating construction edges (see hasConstructionEdges)
1931 /// @param b true to have construction edges, else false.
1932 ///////////////////////////////////////////////////////////////////////////////
1933 void SMDS_Mesh::setConstructionEdges(bool b)
1934 {
1935         myHasConstructionEdges=b;
1936 }
1937
1938 ///////////////////////////////////////////////////////////////////////////////
1939 /// Make this mesh creating construction faces (see hasConstructionFaces)
1940 /// @param b true to have construction faces, else false.
1941 ///////////////////////////////////////////////////////////////////////////////
1942 void SMDS_Mesh::setConstructionFaces(bool b)
1943 {
1944          myHasConstructionFaces=b;
1945 }
1946
1947 ///////////////////////////////////////////////////////////////////////////////
1948 /// Make this mesh creating link from nodes to elements (see hasInverseElements)
1949 /// @param b true to link nodes to elements, else false.
1950 ///////////////////////////////////////////////////////////////////////////////
1951 void SMDS_Mesh::setInverseElements(bool b)
1952 {
1953         if(!b) MESSAGE("Error : inverseElement=false not implemented");
1954         myHasInverseElements=b;
1955 }
1956
1957 ///////////////////////////////////////////////////////////////////////////////
1958 /// Return an iterator on nodes of the current mesh factory
1959 ///////////////////////////////////////////////////////////////////////////////
1960 class SMDS_Mesh_MyNodeIterator:public SMDS_NodeIterator
1961 {
1962   SMDS_ElemIteratorPtr myIterator;
1963  public:
1964   SMDS_Mesh_MyNodeIterator(const SMDS_ElemIteratorPtr& it):myIterator(it)
1965   {}
1966
1967   bool more()
1968   {
1969     return myIterator->more();
1970   }
1971
1972   const SMDS_MeshNode* next()
1973   {
1974     return static_cast<const SMDS_MeshNode*>(myIterator->next());
1975   }
1976 };
1977
1978 SMDS_NodeIteratorPtr SMDS_Mesh::nodesIterator() const
1979 {
1980   return SMDS_NodeIteratorPtr
1981     (new SMDS_Mesh_MyNodeIterator(myNodeIDFactory->elementsIterator()));
1982 }
1983
1984 ///////////////////////////////////////////////////////////////////////////////
1985 /// Return an iterator on elements of the current mesh factory
1986 ///////////////////////////////////////////////////////////////////////////////
1987 SMDS_ElemIteratorPtr SMDS_Mesh::elementsIterator() const
1988 {
1989   return myElementIDFactory->elementsIterator();
1990 }
1991
1992 ///////////////////////////////////////////////////////////////////////////////
1993 ///Return an iterator on edges of the current mesh.
1994 ///////////////////////////////////////////////////////////////////////////////
1995 class SMDS_Mesh_MyEdgeIterator:public SMDS_EdgeIterator
1996 {
1997   typedef SMDS_Mesh::SetOfEdges SetOfEdges;
1998   SetOfEdges::Iterator myIterator;
1999  public:
2000   SMDS_Mesh_MyEdgeIterator(const SetOfEdges& s):myIterator(s)
2001   {}
2002
2003   bool more()
2004   {
2005     while(myIterator.More())
2006     {
2007       if(myIterator.Value()->GetID()!=-1)
2008         return true;
2009       myIterator.Next();
2010     }
2011     return false;
2012   }
2013
2014   const SMDS_MeshEdge* next()
2015   {
2016     const SMDS_MeshEdge* current = myIterator.Value();
2017     myIterator.Next();
2018     return current;
2019   }
2020 };
2021
2022 SMDS_EdgeIteratorPtr SMDS_Mesh::edgesIterator() const
2023 {
2024   return SMDS_EdgeIteratorPtr(new SMDS_Mesh_MyEdgeIterator(myEdges));
2025 }
2026
2027 ///////////////////////////////////////////////////////////////////////////////
2028 ///Return an iterator on faces of the current mesh.
2029 ///////////////////////////////////////////////////////////////////////////////
2030 class SMDS_Mesh_MyFaceIterator:public SMDS_FaceIterator
2031 {
2032   typedef SMDS_Mesh::SetOfFaces SetOfFaces;
2033   SetOfFaces::Iterator myIterator;
2034  public:
2035   SMDS_Mesh_MyFaceIterator(const SetOfFaces& s):myIterator(s)
2036   {}
2037
2038   bool more()
2039   {
2040     while(myIterator.More())
2041     {
2042       if(myIterator.Value()->GetID()!=-1)
2043         return true;
2044       myIterator.Next();
2045     }
2046     return false;
2047   }
2048
2049   const SMDS_MeshFace* next()
2050   {
2051     const SMDS_MeshFace* current = myIterator.Value();
2052     myIterator.Next();
2053     return current;
2054   }
2055 };
2056
2057 SMDS_FaceIteratorPtr SMDS_Mesh::facesIterator() const
2058 {
2059   return SMDS_FaceIteratorPtr(new SMDS_Mesh_MyFaceIterator(myFaces));
2060 }
2061
2062 ///////////////////////////////////////////////////////////////////////////////
2063 ///Return an iterator on volumes of the current mesh.
2064 ///////////////////////////////////////////////////////////////////////////////
2065 class SMDS_Mesh_MyVolumeIterator:public SMDS_VolumeIterator
2066 {
2067   typedef SMDS_Mesh::SetOfVolumes SetOfVolumes;
2068   SetOfVolumes::Iterator myIterator;
2069  public:
2070   SMDS_Mesh_MyVolumeIterator(const SetOfVolumes& s):myIterator(s)
2071   {}
2072
2073   bool more()
2074   {
2075     return myIterator.More() != Standard_False;
2076   }
2077
2078   const SMDS_MeshVolume* next()
2079   {
2080     const SMDS_MeshVolume* current = myIterator.Value();
2081     myIterator.Next();
2082     return current;
2083   }
2084 };
2085
2086 SMDS_VolumeIteratorPtr SMDS_Mesh::volumesIterator() const
2087 {
2088   return SMDS_VolumeIteratorPtr(new SMDS_Mesh_MyVolumeIterator(myVolumes));
2089 }
2090
2091 ///////////////////////////////////////////////////////////////////////////////
2092 /// Do intersection of sets (more than 2)
2093 ///////////////////////////////////////////////////////////////////////////////
2094 static set<const SMDS_MeshElement*> * intersectionOfSets(
2095         set<const SMDS_MeshElement*> vs[], int numberOfSets)
2096 {
2097         set<const SMDS_MeshElement*>* rsetA=new set<const SMDS_MeshElement*>(vs[0]);
2098         set<const SMDS_MeshElement*>* rsetB;
2099
2100         for(int i=0; i<numberOfSets-1; i++)
2101         {
2102                 rsetB=new set<const SMDS_MeshElement*>();
2103                 set_intersection(
2104                         rsetA->begin(), rsetA->end(),
2105                         vs[i+1].begin(), vs[i+1].end(),
2106                         inserter(*rsetB, rsetB->begin()));
2107                 delete rsetA;
2108                 rsetA=rsetB;
2109         }
2110         return rsetA;
2111 }
2112
2113 ///////////////////////////////////////////////////////////////////////////////
2114 /// Return the list of finit elements owning the given element
2115 ///////////////////////////////////////////////////////////////////////////////
2116 static set<const SMDS_MeshElement*> * getFinitElements(const SMDS_MeshElement * element)
2117 {
2118         int numberOfSets=element->NbNodes();
2119         set<const SMDS_MeshElement*> *initSet = new set<const SMDS_MeshElement*>[numberOfSets];
2120
2121         SMDS_ElemIteratorPtr itNodes=element->nodesIterator();
2122
2123         int i=0;
2124         while(itNodes->more())
2125         {
2126                 const SMDS_MeshNode * n=static_cast<const SMDS_MeshNode*>(itNodes->next());
2127                 SMDS_ElemIteratorPtr itFe = n->GetInverseElementIterator();
2128
2129                 //initSet[i]=set<const SMDS_MeshElement*>();
2130                 while(itFe->more())
2131                   initSet[i].insert(itFe->next());
2132
2133                 i++;
2134         }
2135         set<const SMDS_MeshElement*> *retSet=intersectionOfSets(initSet, numberOfSets);
2136         delete [] initSet;
2137         return retSet;
2138 }
2139
2140 ///////////////////////////////////////////////////////////////////////////////
2141 /// Return the list of nodes used only by the given elements
2142 ///////////////////////////////////////////////////////////////////////////////
2143 static set<const SMDS_MeshElement*> * getExclusiveNodes(
2144         set<const SMDS_MeshElement*>& elements)
2145 {
2146         set<const SMDS_MeshElement*> * toReturn=new set<const SMDS_MeshElement*>();
2147         set<const SMDS_MeshElement*>::iterator itElements=elements.begin();
2148
2149         while(itElements!=elements.end())
2150         {
2151                 SMDS_ElemIteratorPtr itNodes = (*itElements)->nodesIterator();
2152                 itElements++;
2153         
2154                 while(itNodes->more())
2155                 {
2156                         const SMDS_MeshNode * n=static_cast<const SMDS_MeshNode*>(itNodes->next());
2157                         SMDS_ElemIteratorPtr itFe = n->GetInverseElementIterator();
2158                         set<const SMDS_MeshElement*> s;
2159                         while(itFe->more())
2160                           s.insert(itFe->next());
2161                         if(s==elements) toReturn->insert(n);
2162                 }
2163         }
2164         return toReturn;        
2165 }
2166
2167 ///////////////////////////////////////////////////////////////////////////////
2168 ///Find the children of an element that are made of given nodes 
2169 ///@param setOfChildren The set in which matching children will be inserted
2170 ///@param element The element were to search matching children
2171 ///@param nodes The nodes that the children must have to be selected
2172 ///////////////////////////////////////////////////////////////////////////////
2173 void SMDS_Mesh::addChildrenWithNodes(set<const SMDS_MeshElement*>&      setOfChildren, 
2174         const SMDS_MeshElement * element, set<const SMDS_MeshElement*>& nodes)
2175 {
2176         
2177         switch(element->GetType())
2178         {
2179         case SMDSAbs_Node:
2180                 MESSAGE("Internal Error: This should not append");
2181                 break;
2182         case SMDSAbs_Edge:
2183         {
2184                 SMDS_ElemIteratorPtr itn=element->nodesIterator();
2185                 while(itn->more())
2186                 {
2187                         const SMDS_MeshElement * e=itn->next();
2188                         if(nodes.find(e)!=nodes.end())
2189                         {
2190                           setOfChildren.insert(element);
2191                           break;
2192                         }
2193                 }
2194         } break;
2195         case SMDSAbs_Face:
2196         {
2197                 SMDS_ElemIteratorPtr itn=element->nodesIterator();
2198                 while(itn->more())
2199                 {
2200                         const SMDS_MeshElement * e=itn->next();
2201                         if(nodes.find(e)!=nodes.end())
2202                         {
2203                           setOfChildren.insert(element);
2204                           break;
2205                         }
2206                 }
2207                 if(hasConstructionEdges())
2208                 {
2209                         SMDS_ElemIteratorPtr ite=element->edgesIterator();
2210                         while(ite->more())
2211                                 addChildrenWithNodes(setOfChildren, ite->next(), nodes);
2212                 }
2213         } break;        
2214         case SMDSAbs_Volume:
2215         {
2216                 if(hasConstructionFaces())
2217                 {
2218                         SMDS_ElemIteratorPtr ite=element->facesIterator();
2219                         while(ite->more())
2220                                 addChildrenWithNodes(setOfChildren, ite->next(), nodes);
2221                 }
2222                 else if(hasConstructionEdges())
2223                 {
2224                         SMDS_ElemIteratorPtr ite=element->edgesIterator();
2225                         while(ite->more())
2226                                 addChildrenWithNodes(setOfChildren, ite->next(), nodes);
2227                 }
2228         }
2229         }
2230 }
2231
2232 ///////////////////////////////////////////////////////////////////////////////
2233 ///@param elem The element to delete
2234 ///@param removenodes if true remaining nodes will be removed
2235 ///////////////////////////////////////////////////////////////////////////////
2236 void SMDS_Mesh::RemoveElement(const SMDS_MeshElement * elem,
2237         const bool removenodes)
2238 {
2239   list<const SMDS_MeshElement *> removedElems;
2240   list<const SMDS_MeshElement *> removedNodes;
2241   RemoveElement( elem, removedElems, removedNodes, removenodes );
2242 }
2243   
2244 ///////////////////////////////////////////////////////////////////////////////
2245 ///@param elem The element to delete
2246 ///@param removedElems contains all removed elements
2247 ///@param removedNodes contains all removed nodes
2248 ///@param removenodes if true remaining nodes will be removed
2249 ///////////////////////////////////////////////////////////////////////////////
2250 void SMDS_Mesh::RemoveElement(const SMDS_MeshElement *        elem,
2251                               list<const SMDS_MeshElement *>& removedElems,
2252                               list<const SMDS_MeshElement *>& removedNodes,
2253                               bool                            removenodes)
2254 {
2255   // get finite elements built on elem
2256   set<const SMDS_MeshElement*> * s1;
2257   if (!hasConstructionEdges() && elem->GetType() == SMDSAbs_Edge ||
2258       !hasConstructionFaces() && elem->GetType() == SMDSAbs_Face ||
2259       elem->GetType() == SMDSAbs_Volume)
2260   {
2261     s1 = new set<const SMDS_MeshElement*>();
2262     s1->insert(elem);
2263   }
2264   else
2265     s1 = getFinitElements(elem);
2266
2267   // get exclusive nodes (which would become free afterwards)
2268   set<const SMDS_MeshElement*> * s2;
2269   if (elem->GetType() == SMDSAbs_Node) // a node is removed
2270   {
2271     // do not remove nodes except elem
2272     s2 = new set<const SMDS_MeshElement*>();
2273     s2->insert(elem);
2274     removenodes = true;
2275   }
2276   else
2277     s2 = getExclusiveNodes(*s1);
2278
2279   // form the set of finite and construction elements to remove
2280   set<const SMDS_MeshElement*> s3;
2281   set<const SMDS_MeshElement*>::iterator it=s1->begin();
2282   while(it!=s1->end())
2283   {
2284     addChildrenWithNodes(s3, *it ,*s2);
2285     s3.insert(*it);
2286     it++;
2287   }
2288   if(elem->GetType()!=SMDSAbs_Node) s3.insert(elem);
2289
2290   // remove finite and construction elements
2291   it=s3.begin();
2292   while(it!=s3.end())
2293   {
2294     // Remove element from <InverseElements> of its nodes
2295     SMDS_ElemIteratorPtr itn=(*it)->nodesIterator();
2296     while(itn->more())
2297     {
2298       SMDS_MeshNode * n = static_cast<SMDS_MeshNode *>
2299         (const_cast<SMDS_MeshElement *>(itn->next()));
2300       n->RemoveInverseElement( (*it) );
2301     }
2302
2303     switch((*it)->GetType())
2304     {
2305     case SMDSAbs_Node:
2306       MESSAGE("Internal Error: This should not happen");
2307       break;
2308     case SMDSAbs_Edge:
2309       myEdges.Remove(static_cast<SMDS_MeshEdge*>
2310                     (const_cast<SMDS_MeshElement*>(*it)));
2311       myInfo.RemoveEdge(*it);
2312       break;
2313     case SMDSAbs_Face:
2314       myFaces.Remove(static_cast<SMDS_MeshFace*>
2315                     (const_cast<SMDS_MeshElement*>(*it)));
2316       myInfo.RemoveFace(*it);
2317       break;
2318     case SMDSAbs_Volume:
2319       myVolumes.Remove(static_cast<SMDS_MeshVolume*>
2320                       (const_cast<SMDS_MeshElement*>(*it)));
2321       myInfo.RemoveVolume(*it);
2322       break;
2323     }
2324     //MESSAGE( "SMDS: RM elem " << (*it)->GetID() );
2325     removedElems.push_back( (*it) );
2326     myElementIDFactory->ReleaseID((*it)->GetID());
2327     delete (*it);
2328     it++;
2329   }
2330
2331   // remove exclusive (free) nodes
2332   if(removenodes)
2333   {
2334     it=s2->begin();
2335     while(it!=s2->end())
2336     {
2337       //MESSAGE( "SMDS: RM node " << (*it)->GetID() );
2338       myNodes.Remove(static_cast<SMDS_MeshNode*>
2339                     (const_cast<SMDS_MeshElement*>(*it)));
2340       myInfo.myNbNodes--;
2341       myNodeIDFactory->ReleaseID((*it)->GetID());
2342       removedNodes.push_back( (*it) );
2343       delete *it;
2344       it++;
2345     }
2346   }
2347
2348   delete s2;
2349   delete s1;
2350 }
2351
2352   
2353 ///////////////////////////////////////////////////////////////////////////////
2354 ///@param elem The element to delete
2355 ///////////////////////////////////////////////////////////////////////////////
2356 void SMDS_Mesh::RemoveFreeElement(const SMDS_MeshElement * elem)
2357 {
2358   SMDSAbs_ElementType aType = elem->GetType();
2359   if (aType == SMDSAbs_Node) {
2360     // only free node can be removed by this method
2361     const SMDS_MeshNode* n = static_cast<const SMDS_MeshNode*>(elem);
2362     SMDS_ElemIteratorPtr itFe = n->GetInverseElementIterator();
2363     if (!itFe->more()) { // free node
2364       myNodes.Remove(const_cast<SMDS_MeshNode*>(n));
2365       myInfo.myNbNodes--;
2366       myNodeIDFactory->ReleaseID(elem->GetID());
2367       delete elem;
2368     }
2369   } else {
2370     if (hasConstructionEdges() || hasConstructionFaces())
2371       // this methods is only for meshes without descendants
2372       return;
2373
2374     // Remove element from <InverseElements> of its nodes
2375     SMDS_ElemIteratorPtr itn = elem->nodesIterator();
2376     while (itn->more()) {
2377       SMDS_MeshNode * n = static_cast<SMDS_MeshNode *>
2378         (const_cast<SMDS_MeshElement *>(itn->next()));
2379       n->RemoveInverseElement(elem);
2380     }
2381
2382     // in meshes without descendants elements are always free
2383     switch (aType) {
2384     case SMDSAbs_Edge:
2385       myEdges.Remove(static_cast<SMDS_MeshEdge*>
2386                      (const_cast<SMDS_MeshElement*>(elem)));
2387       myInfo.RemoveEdge(elem);
2388       break;
2389     case SMDSAbs_Face:
2390       myFaces.Remove(static_cast<SMDS_MeshFace*>
2391                      (const_cast<SMDS_MeshElement*>(elem)));
2392       myInfo.RemoveFace(elem);
2393       break;
2394     case SMDSAbs_Volume:
2395       myVolumes.Remove(static_cast<SMDS_MeshVolume*>
2396                        (const_cast<SMDS_MeshElement*>(elem)));
2397       myInfo.RemoveVolume(elem);
2398       break;
2399     default:
2400       break;
2401     }
2402     myElementIDFactory->ReleaseID(elem->GetID());
2403     delete elem;
2404   }
2405 }
2406
2407 /*!
2408  * Checks if the element is present in mesh.
2409  * Useful to determine dead pointers.
2410  */
2411 bool SMDS_Mesh::Contains (const SMDS_MeshElement* elem) const
2412 {
2413   // we should not imply on validity of *elem, so iterate on containers
2414   // of all types in the hope of finding <elem> somewhere there
2415   SMDS_NodeIteratorPtr itn = nodesIterator();
2416   while (itn->more())
2417     if (elem == itn->next())
2418       return true;
2419   SMDS_EdgeIteratorPtr ite = edgesIterator();
2420   while (ite->more())
2421     if (elem == ite->next())
2422       return true;
2423   SMDS_FaceIteratorPtr itf = facesIterator();
2424   while (itf->more())
2425     if (elem == itf->next())
2426       return true;
2427   SMDS_VolumeIteratorPtr itv = volumesIterator();
2428   while (itv->more())
2429     if (elem == itv->next())
2430       return true;
2431   return false;
2432 }
2433
2434 //=======================================================================
2435 //function : MaxNodeID
2436 //purpose  : 
2437 //=======================================================================
2438
2439 int SMDS_Mesh::MaxNodeID() const
2440 {
2441   return myNodeIDFactory->GetMaxID();
2442 }
2443
2444 //=======================================================================
2445 //function : MinNodeID
2446 //purpose  : 
2447 //=======================================================================
2448
2449 int SMDS_Mesh::MinNodeID() const
2450 {
2451   return myNodeIDFactory->GetMinID();
2452 }
2453
2454 //=======================================================================
2455 //function : MaxElementID
2456 //purpose  : 
2457 //=======================================================================
2458
2459 int SMDS_Mesh::MaxElementID() const
2460 {
2461   return myElementIDFactory->GetMaxID();
2462 }
2463
2464 //=======================================================================
2465 //function : MinElementID
2466 //purpose  : 
2467 //=======================================================================
2468
2469 int SMDS_Mesh::MinElementID() const
2470 {
2471   return myElementIDFactory->GetMinID();
2472 }
2473
2474 //=======================================================================
2475 //function : Renumber
2476 //purpose  : Renumber all nodes or elements.
2477 //=======================================================================
2478
2479 void SMDS_Mesh::Renumber (const bool isNodes, const int  startID, const int  deltaID)
2480 {
2481   if ( deltaID == 0 )
2482     return;
2483
2484   SMDS_MeshElementIDFactory * idFactory =
2485     isNodes ? myNodeIDFactory : myElementIDFactory;
2486
2487   // get existing elements in the order of ID increasing
2488   map<int,SMDS_MeshElement*> elemMap;
2489   SMDS_ElemIteratorPtr idElemIt = idFactory->elementsIterator();
2490   while ( idElemIt->more() ) {
2491     SMDS_MeshElement* elem = const_cast<SMDS_MeshElement*>(idElemIt->next());
2492     int id = elem->GetID();
2493     elemMap.insert(map<int,SMDS_MeshElement*>::value_type(id, elem));
2494   }
2495   // release their ids
2496   map<int,SMDS_MeshElement*>::iterator elemIt = elemMap.begin();
2497   for ( ; elemIt != elemMap.end(); elemIt++ )
2498   {
2499     int id = (*elemIt).first;
2500     idFactory->ReleaseID( id );
2501   }
2502   // set new IDs
2503   int ID = startID;
2504   elemIt = elemMap.begin();
2505   for ( ; elemIt != elemMap.end(); elemIt++ )
2506   {
2507     idFactory->BindID( ID, (*elemIt).second );
2508     ID += deltaID;
2509   }
2510 }
2511
2512 //=======================================================================
2513 //function : GetElementType
2514 //purpose  : Return type of element or node with id
2515 //=======================================================================
2516
2517 SMDSAbs_ElementType SMDS_Mesh::GetElementType( const int id, const bool iselem ) const
2518 {
2519   SMDS_MeshElement* elem = 0;
2520   if( iselem )
2521     elem = myElementIDFactory->MeshElement( id );
2522   else
2523     elem = myNodeIDFactory->MeshElement( id );
2524
2525   if( !elem )
2526   {
2527     //throw SALOME_Exception(LOCALIZED ("this element isn't exist"));
2528     return SMDSAbs_All;
2529   }
2530   else
2531     return elem->GetType();
2532 }
2533
2534
2535
2536 //********************************************************************
2537 //********************************************************************
2538 //********                                                   *********
2539 //*****       Methods for addition of quadratic elements        ******
2540 //********                                                   *********
2541 //********************************************************************
2542 //********************************************************************
2543
2544 //=======================================================================
2545 //function : AddEdgeWithID
2546 //purpose  : 
2547 //=======================================================================
2548 SMDS_MeshEdge* SMDS_Mesh::AddEdgeWithID(int n1, int n2, int n12, int ID) 
2549 {
2550   return SMDS_Mesh::AddEdgeWithID
2551     ((SMDS_MeshNode*) myNodeIDFactory->MeshElement(n1),
2552      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n2),
2553      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n12),
2554      ID);
2555 }
2556
2557 //=======================================================================
2558 //function : AddEdge
2559 //purpose  : 
2560 //=======================================================================
2561 SMDS_MeshEdge* SMDS_Mesh::AddEdge(const SMDS_MeshNode* n1,
2562                                   const SMDS_MeshNode* n2,
2563                                   const SMDS_MeshNode* n12)
2564 {
2565   return SMDS_Mesh::AddEdgeWithID(n1, n2, n12, myElementIDFactory->GetFreeID());
2566 }
2567
2568 //=======================================================================
2569 //function : AddEdgeWithID
2570 //purpose  : 
2571 //=======================================================================
2572 SMDS_MeshEdge* SMDS_Mesh::AddEdgeWithID(const SMDS_MeshNode * n1,
2573                                         const SMDS_MeshNode * n2, 
2574                                         const SMDS_MeshNode * n12, 
2575                                         int ID)
2576 {
2577   if ( !n1 || !n2 || !n12 ) return 0;
2578   SMDS_QuadraticEdge* edge = new SMDS_QuadraticEdge(n1,n2,n12);
2579   if(myElementIDFactory->BindID(ID, edge)) {
2580     SMDS_MeshNode *node1,*node2, *node12;
2581     node1 = const_cast<SMDS_MeshNode*>(n1);
2582     node2 = const_cast<SMDS_MeshNode*>(n2);
2583     node12 = const_cast<SMDS_MeshNode*>(n12);
2584     node1->AddInverseElement(edge);
2585     node2->AddInverseElement(edge);
2586     node12->AddInverseElement(edge);
2587     myEdges.Add(edge);
2588     myInfo.myNbQuadEdges++;
2589     return edge;
2590   } 
2591   else {
2592     delete edge;
2593     return NULL;
2594   }
2595 }
2596
2597
2598 //=======================================================================
2599 //function : AddFace
2600 //purpose  : 
2601 //=======================================================================
2602 SMDS_MeshFace* SMDS_Mesh::AddFace(const SMDS_MeshNode * n1,
2603                                   const SMDS_MeshNode * n2,
2604                                   const SMDS_MeshNode * n3,
2605                                   const SMDS_MeshNode * n12,
2606                                   const SMDS_MeshNode * n23,
2607                                   const SMDS_MeshNode * n31)
2608 {
2609   return SMDS_Mesh::AddFaceWithID(n1,n2,n3,n12,n23,n31,
2610                                   myElementIDFactory->GetFreeID());
2611 }
2612
2613 //=======================================================================
2614 //function : AddFaceWithID
2615 //purpose  : 
2616 //=======================================================================
2617 SMDS_MeshFace* SMDS_Mesh::AddFaceWithID(int n1, int n2, int n3,
2618                                         int n12,int n23,int n31, int ID)
2619 {
2620   return SMDS_Mesh::AddFaceWithID
2621     ((SMDS_MeshNode *)myNodeIDFactory->MeshElement(n1) ,
2622      (SMDS_MeshNode *)myNodeIDFactory->MeshElement(n2) ,
2623      (SMDS_MeshNode *)myNodeIDFactory->MeshElement(n3) ,
2624      (SMDS_MeshNode *)myNodeIDFactory->MeshElement(n12),
2625      (SMDS_MeshNode *)myNodeIDFactory->MeshElement(n23),
2626      (SMDS_MeshNode *)myNodeIDFactory->MeshElement(n31),
2627      ID);
2628 }
2629
2630 //=======================================================================
2631 //function : AddFaceWithID
2632 //purpose  : 
2633 //=======================================================================
2634 SMDS_MeshFace* SMDS_Mesh::AddFaceWithID(const SMDS_MeshNode * n1,
2635                                         const SMDS_MeshNode * n2,
2636                                         const SMDS_MeshNode * n3,
2637                                         const SMDS_MeshNode * n12,
2638                                         const SMDS_MeshNode * n23,
2639                                         const SMDS_MeshNode * n31, 
2640                                         int ID)
2641 {
2642   if ( !n1 || !n2 || !n3 || !n12 || !n23 || !n31) return 0;
2643   if(hasConstructionEdges()) {
2644     // creation quadratic edges - not implemented
2645     return 0;
2646   }
2647   SMDS_QuadraticFaceOfNodes* face =
2648     new SMDS_QuadraticFaceOfNodes(n1,n2,n3,n12,n23,n31);
2649   myFaces.Add(face);
2650   myInfo.myNbQuadTriangles++;
2651
2652   if (!registerElement(ID, face)) {
2653     RemoveElement(face, false);
2654     face = NULL;
2655   }
2656   return face;
2657 }
2658
2659
2660 //=======================================================================
2661 //function : AddFace
2662 //purpose  : 
2663 //=======================================================================
2664 SMDS_MeshFace* SMDS_Mesh::AddFace(const SMDS_MeshNode * n1,
2665                                   const SMDS_MeshNode * n2,
2666                                   const SMDS_MeshNode * n3,
2667                                   const SMDS_MeshNode * n4,
2668                                   const SMDS_MeshNode * n12,
2669                                   const SMDS_MeshNode * n23,
2670                                   const SMDS_MeshNode * n34,
2671                                   const SMDS_MeshNode * n41)
2672 {
2673   return SMDS_Mesh::AddFaceWithID(n1,n2,n3,n4,n12,n23,n34,n41,
2674                                   myElementIDFactory->GetFreeID());
2675 }
2676
2677 //=======================================================================
2678 //function : AddFaceWithID
2679 //purpose  : 
2680 //=======================================================================
2681 SMDS_MeshFace* SMDS_Mesh::AddFaceWithID(int n1, int n2, int n3, int n4,
2682                                         int n12,int n23,int n34,int n41, int ID)
2683 {
2684   return SMDS_Mesh::AddFaceWithID
2685     ((SMDS_MeshNode *)myNodeIDFactory->MeshElement(n1) ,
2686      (SMDS_MeshNode *)myNodeIDFactory->MeshElement(n2) ,
2687      (SMDS_MeshNode *)myNodeIDFactory->MeshElement(n3) ,
2688      (SMDS_MeshNode *)myNodeIDFactory->MeshElement(n4) ,
2689      (SMDS_MeshNode *)myNodeIDFactory->MeshElement(n12),
2690      (SMDS_MeshNode *)myNodeIDFactory->MeshElement(n23),
2691      (SMDS_MeshNode *)myNodeIDFactory->MeshElement(n34),
2692      (SMDS_MeshNode *)myNodeIDFactory->MeshElement(n41),
2693      ID);
2694 }
2695
2696 //=======================================================================
2697 //function : AddFaceWithID
2698 //purpose  : 
2699 //=======================================================================
2700 SMDS_MeshFace* SMDS_Mesh::AddFaceWithID(const SMDS_MeshNode * n1,
2701                                         const SMDS_MeshNode * n2,
2702                                         const SMDS_MeshNode * n3,
2703                                         const SMDS_MeshNode * n4,
2704                                         const SMDS_MeshNode * n12,
2705                                         const SMDS_MeshNode * n23,
2706                                         const SMDS_MeshNode * n34, 
2707                                         const SMDS_MeshNode * n41, 
2708                                         int ID)
2709 {
2710   if ( !n1 || !n2 || !n3 || !n4 || !n12 || !n23 || !n34 || !n41) return 0;
2711   if(hasConstructionEdges()) {
2712     // creation quadratic edges - not implemented
2713   }
2714   SMDS_QuadraticFaceOfNodes* face =
2715     new SMDS_QuadraticFaceOfNodes(n1,n2,n3,n4,n12,n23,n34,n41);
2716   myFaces.Add(face);
2717   myInfo.myNbQuadQuadrangles++;
2718
2719   if (!registerElement(ID, face)) {
2720     RemoveElement(face, false);
2721     face = NULL;
2722   }
2723   return face;
2724 }
2725
2726
2727 //=======================================================================
2728 //function : AddVolume
2729 //purpose  : 
2730 //=======================================================================
2731 SMDS_MeshVolume* SMDS_Mesh::AddVolume(const SMDS_MeshNode * n1,
2732                                       const SMDS_MeshNode * n2, 
2733                                       const SMDS_MeshNode * n3,
2734                                       const SMDS_MeshNode * n4,
2735                                       const SMDS_MeshNode * n12,
2736                                       const SMDS_MeshNode * n23,
2737                                       const SMDS_MeshNode * n31,
2738                                       const SMDS_MeshNode * n14, 
2739                                       const SMDS_MeshNode * n24,
2740                                       const SMDS_MeshNode * n34)
2741 {
2742   int ID = myElementIDFactory->GetFreeID();
2743   SMDS_MeshVolume * v = SMDS_Mesh::AddVolumeWithID(n1, n2, n3, n4, n12, n23,
2744                                                    n31, n14, n24, n34, ID);
2745   if(v==NULL) myElementIDFactory->ReleaseID(ID);
2746   return v;
2747 }
2748
2749 //=======================================================================
2750 //function : AddVolumeWithID
2751 //purpose  : 
2752 //=======================================================================
2753 SMDS_MeshVolume* SMDS_Mesh::AddVolumeWithID(int n1, int n2, int n3, int n4,
2754                                             int n12,int n23,int n31,
2755                                             int n14,int n24,int n34, int ID)
2756 {
2757   return SMDS_Mesh::AddVolumeWithID
2758     ((SMDS_MeshNode*) myNodeIDFactory->MeshElement(n1) ,
2759      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n2) ,
2760      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n3) ,
2761      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n4) ,
2762      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n12),
2763      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n23),
2764      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n31),
2765      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n14),
2766      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n24),
2767      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n34),
2768      ID);
2769 }
2770
2771 //=======================================================================
2772 //function : AddVolumeWithID
2773 //purpose  : 2d order tetrahedron of 10 nodes
2774 //=======================================================================
2775 SMDS_MeshVolume* SMDS_Mesh::AddVolumeWithID(const SMDS_MeshNode * n1,
2776                                             const SMDS_MeshNode * n2,
2777                                             const SMDS_MeshNode * n3,
2778                                             const SMDS_MeshNode * n4,
2779                                             const SMDS_MeshNode * n12,
2780                                             const SMDS_MeshNode * n23,
2781                                             const SMDS_MeshNode * n31,
2782                                             const SMDS_MeshNode * n14, 
2783                                             const SMDS_MeshNode * n24,
2784                                             const SMDS_MeshNode * n34,
2785                                             int ID)
2786 {
2787   if ( !n1 || !n2 || !n3 || !n4 || !n12 || !n23 || !n31 || !n14 || !n24 || !n34)
2788     return 0;
2789   if(hasConstructionFaces()) {
2790     // creation quadratic faces - not implemented
2791     return 0;
2792   }
2793   SMDS_QuadraticVolumeOfNodes * volume =
2794     new SMDS_QuadraticVolumeOfNodes(n1,n2,n3,n4,n12,n23,n31,n14,n24,n34);
2795   myVolumes.Add(volume);
2796   myInfo.myNbQuadTetras++;
2797
2798   if (!registerElement(ID, volume)) {
2799     RemoveElement(volume, false);
2800     volume = NULL;
2801   }
2802   return volume;
2803 }
2804
2805
2806 //=======================================================================
2807 //function : AddVolume
2808 //purpose  : 
2809 //=======================================================================
2810 SMDS_MeshVolume* SMDS_Mesh::AddVolume(const SMDS_MeshNode * n1,
2811                                       const SMDS_MeshNode * n2, 
2812                                       const SMDS_MeshNode * n3,
2813                                       const SMDS_MeshNode * n4,
2814                                       const SMDS_MeshNode * n5, 
2815                                       const SMDS_MeshNode * n12,
2816                                       const SMDS_MeshNode * n23,
2817                                       const SMDS_MeshNode * n34,
2818                                       const SMDS_MeshNode * n41,
2819                                       const SMDS_MeshNode * n15, 
2820                                       const SMDS_MeshNode * n25,
2821                                       const SMDS_MeshNode * n35,
2822                                       const SMDS_MeshNode * n45)
2823 {
2824   int ID = myElementIDFactory->GetFreeID();
2825   SMDS_MeshVolume * v =
2826     SMDS_Mesh::AddVolumeWithID(n1, n2, n3, n4, n5, n12, n23, n34, n41,
2827                                n15, n25, n35, n45, ID);
2828   if(v==NULL) myElementIDFactory->ReleaseID(ID);
2829   return v;
2830 }
2831
2832 //=======================================================================
2833 //function : AddVolumeWithID
2834 //purpose  : 
2835 //=======================================================================
2836 SMDS_MeshVolume* SMDS_Mesh::AddVolumeWithID(int n1, int n2, int n3, int n4, int n5,
2837                                             int n12,int n23,int n34,int n41,
2838                                             int n15,int n25,int n35,int n45, int ID)
2839 {
2840   return SMDS_Mesh::AddVolumeWithID
2841     ((SMDS_MeshNode*) myNodeIDFactory->MeshElement(n1) ,
2842      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n2) ,
2843      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n3) ,
2844      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n4) ,
2845      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n5) ,
2846      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n12),
2847      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n23),
2848      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n34),
2849      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n41),
2850      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n15),
2851      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n25),
2852      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n35),
2853      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n45),
2854      ID);
2855 }
2856
2857 //=======================================================================
2858 //function : AddVolumeWithID
2859 //purpose  : 2d order pyramid of 13 nodes
2860 //=======================================================================
2861 SMDS_MeshVolume* SMDS_Mesh::AddVolumeWithID(const SMDS_MeshNode * n1,
2862                                             const SMDS_MeshNode * n2,
2863                                             const SMDS_MeshNode * n3,
2864                                             const SMDS_MeshNode * n4,
2865                                             const SMDS_MeshNode * n5, 
2866                                             const SMDS_MeshNode * n12,
2867                                             const SMDS_MeshNode * n23,
2868                                             const SMDS_MeshNode * n34,
2869                                             const SMDS_MeshNode * n41,
2870                                             const SMDS_MeshNode * n15, 
2871                                             const SMDS_MeshNode * n25,
2872                                             const SMDS_MeshNode * n35,
2873                                             const SMDS_MeshNode * n45,
2874                                             int ID)
2875 {
2876   if (!n1 || !n2 || !n3 || !n4 || !n5 || !n12 || !n23 ||
2877       !n34 || !n41 || !n15 || !n25 || !n35 || !n45)
2878     return 0;
2879   if(hasConstructionFaces()) {
2880     // creation quadratic faces - not implemented
2881     return 0;
2882   }
2883   SMDS_QuadraticVolumeOfNodes * volume =
2884     new SMDS_QuadraticVolumeOfNodes(n1,n2,n3,n4,n5,n12,n23,
2885                                     n34,n41,n15,n25,n35,n45);
2886   myVolumes.Add(volume);
2887   myInfo.myNbQuadPyramids++;
2888
2889   if (!registerElement(ID, volume)) {
2890     RemoveElement(volume, false);
2891     volume = NULL;
2892   }
2893   return volume;
2894 }
2895
2896
2897 //=======================================================================
2898 //function : AddVolume
2899 //purpose  : 
2900 //=======================================================================
2901 SMDS_MeshVolume* SMDS_Mesh::AddVolume(const SMDS_MeshNode * n1,
2902                                       const SMDS_MeshNode * n2, 
2903                                       const SMDS_MeshNode * n3,
2904                                       const SMDS_MeshNode * n4,
2905                                       const SMDS_MeshNode * n5, 
2906                                       const SMDS_MeshNode * n6, 
2907                                       const SMDS_MeshNode * n12,
2908                                       const SMDS_MeshNode * n23,
2909                                       const SMDS_MeshNode * n31, 
2910                                       const SMDS_MeshNode * n45,
2911                                       const SMDS_MeshNode * n56,
2912                                       const SMDS_MeshNode * n64, 
2913                                       const SMDS_MeshNode * n14,
2914                                       const SMDS_MeshNode * n25,
2915                                       const SMDS_MeshNode * n36)
2916 {
2917   int ID = myElementIDFactory->GetFreeID();
2918   SMDS_MeshVolume * v =
2919     SMDS_Mesh::AddVolumeWithID(n1, n2, n3, n4, n5, n6, n12, n23, n31,
2920                                n45, n56, n64, n14, n25, n36, ID);
2921   if(v==NULL) myElementIDFactory->ReleaseID(ID);
2922   return v;
2923 }
2924
2925 //=======================================================================
2926 //function : AddVolumeWithID
2927 //purpose  : 
2928 //=======================================================================
2929 SMDS_MeshVolume* SMDS_Mesh::AddVolumeWithID(int n1, int n2, int n3,
2930                                             int n4, int n5, int n6,
2931                                             int n12,int n23,int n31,
2932                                             int n45,int n56,int n64,
2933                                             int n14,int n25,int n36, int ID)
2934 {
2935   return SMDS_Mesh::AddVolumeWithID
2936     ((SMDS_MeshNode*) myNodeIDFactory->MeshElement(n1) ,
2937      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n2) ,
2938      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n3) ,
2939      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n4) ,
2940      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n5) ,
2941      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n6) ,
2942      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n12),
2943      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n23),
2944      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n31),
2945      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n45),
2946      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n56),
2947      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n64),
2948      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n14),
2949      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n25),
2950      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n36),
2951      ID);
2952 }
2953
2954 //=======================================================================
2955 //function : AddVolumeWithID
2956 //purpose  : 2d order Pentahedron with 15 nodes
2957 //=======================================================================
2958 SMDS_MeshVolume* SMDS_Mesh::AddVolumeWithID(const SMDS_MeshNode * n1,
2959                                             const SMDS_MeshNode * n2,
2960                                             const SMDS_MeshNode * n3,
2961                                             const SMDS_MeshNode * n4,
2962                                             const SMDS_MeshNode * n5, 
2963                                             const SMDS_MeshNode * n6, 
2964                                             const SMDS_MeshNode * n12,
2965                                             const SMDS_MeshNode * n23,
2966                                             const SMDS_MeshNode * n31, 
2967                                             const SMDS_MeshNode * n45,
2968                                             const SMDS_MeshNode * n56,
2969                                             const SMDS_MeshNode * n64, 
2970                                             const SMDS_MeshNode * n14,
2971                                             const SMDS_MeshNode * n25,
2972                                             const SMDS_MeshNode * n36,
2973                                             int ID)
2974 {
2975   if (!n1 || !n2 || !n3 || !n4 || !n5 || !n6 || !n12 || !n23 ||
2976       !n31 || !n45 || !n56 || !n64 || !n14 || !n25 || !n36)
2977     return 0;
2978   if(hasConstructionFaces()) {
2979     // creation quadratic faces - not implemented
2980     return 0;
2981   }
2982   SMDS_QuadraticVolumeOfNodes * volume =
2983     new SMDS_QuadraticVolumeOfNodes(n1,n2,n3,n4,n5,n6,n12,n23,n31,
2984                                     n45,n56,n64,n14,n25,n36);
2985   myVolumes.Add(volume);
2986   myInfo.myNbQuadPrisms++;
2987
2988   if (!registerElement(ID, volume)) {
2989     RemoveElement(volume, false);
2990     volume = NULL;
2991   }
2992   return volume;
2993 }
2994
2995
2996 //=======================================================================
2997 //function : AddVolume
2998 //purpose  : 
2999 //=======================================================================
3000 SMDS_MeshVolume* SMDS_Mesh::AddVolume(const SMDS_MeshNode * n1,
3001                                       const SMDS_MeshNode * n2, 
3002                                       const SMDS_MeshNode * n3,
3003                                       const SMDS_MeshNode * n4,
3004                                       const SMDS_MeshNode * n5, 
3005                                       const SMDS_MeshNode * n6, 
3006                                       const SMDS_MeshNode * n7,
3007                                       const SMDS_MeshNode * n8, 
3008                                       const SMDS_MeshNode * n12,
3009                                       const SMDS_MeshNode * n23,
3010                                       const SMDS_MeshNode * n34,
3011                                       const SMDS_MeshNode * n41, 
3012                                       const SMDS_MeshNode * n56,
3013                                       const SMDS_MeshNode * n67,
3014                                       const SMDS_MeshNode * n78,
3015                                       const SMDS_MeshNode * n85, 
3016                                       const SMDS_MeshNode * n15,
3017                                       const SMDS_MeshNode * n26,
3018                                       const SMDS_MeshNode * n37,
3019                                       const SMDS_MeshNode * n48)
3020 {
3021   int ID = myElementIDFactory->GetFreeID();
3022   SMDS_MeshVolume * v =
3023     SMDS_Mesh::AddVolumeWithID(n1, n2, n3, n4, n5, n6, n7, n8, n12, n23, n34, n41,
3024                                n56, n67, n78, n85, n15, n26, n37, n48, ID);
3025   if(v==NULL) myElementIDFactory->ReleaseID(ID);
3026   return v;
3027 }
3028
3029 //=======================================================================
3030 //function : AddVolumeWithID
3031 //purpose  : 
3032 //=======================================================================
3033 SMDS_MeshVolume* SMDS_Mesh::AddVolumeWithID(int n1, int n2, int n3, int n4,
3034                                             int n5, int n6, int n7, int n8,
3035                                             int n12,int n23,int n34,int n41,
3036                                             int n56,int n67,int n78,int n85,
3037                                             int n15,int n26,int n37,int n48, int ID)
3038 {
3039   return SMDS_Mesh::AddVolumeWithID
3040     ((SMDS_MeshNode*) myNodeIDFactory->MeshElement(n1),
3041      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n2),
3042      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n3),
3043      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n4),
3044      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n5),
3045      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n6),
3046      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n7),
3047      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n8),
3048      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n12),
3049      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n23),
3050      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n34),
3051      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n41),
3052      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n56),
3053      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n67),
3054      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n78),
3055      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n85),
3056      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n15),
3057      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n26),
3058      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n37),
3059      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n48),
3060      ID);
3061 }
3062
3063 //=======================================================================
3064 //function : AddVolumeWithID
3065 //purpose  : 2d order Hexahedrons with 20 nodes
3066 //=======================================================================
3067 SMDS_MeshVolume* SMDS_Mesh::AddVolumeWithID(const SMDS_MeshNode * n1,
3068                                             const SMDS_MeshNode * n2,
3069                                             const SMDS_MeshNode * n3,
3070                                             const SMDS_MeshNode * n4,
3071                                             const SMDS_MeshNode * n5, 
3072                                             const SMDS_MeshNode * n6, 
3073                                             const SMDS_MeshNode * n7,
3074                                             const SMDS_MeshNode * n8, 
3075                                             const SMDS_MeshNode * n12,
3076                                             const SMDS_MeshNode * n23,
3077                                             const SMDS_MeshNode * n34,
3078                                             const SMDS_MeshNode * n41, 
3079                                             const SMDS_MeshNode * n56,
3080                                             const SMDS_MeshNode * n67,
3081                                             const SMDS_MeshNode * n78,
3082                                             const SMDS_MeshNode * n85, 
3083                                             const SMDS_MeshNode * n15,
3084                                             const SMDS_MeshNode * n26,
3085                                             const SMDS_MeshNode * n37,
3086                                             const SMDS_MeshNode * n48,
3087                                             int ID)
3088 {
3089   if (!n1 || !n2 || !n3 || !n4 || !n5 || !n6 || !n7 || !n8 || !n12 || !n23 ||
3090       !n34 || !n41 || !n56 || !n67 || !n78 || !n85 || !n15 || !n26 || !n37 || !n48)
3091     return 0;
3092   if(hasConstructionFaces()) {
3093     return 0;
3094     // creation quadratic faces - not implemented
3095   }
3096   SMDS_QuadraticVolumeOfNodes * volume =
3097     new SMDS_QuadraticVolumeOfNodes(n1,n2,n3,n4,n5,n6,n7,n8,n12,n23,n34,n41,
3098                                     n56,n67,n78,n85,n15,n26,n37,n48);
3099   myVolumes.Add(volume);
3100   myInfo.myNbQuadHexas++;
3101
3102   if (!registerElement(ID, volume)) {
3103     RemoveElement(volume, false);
3104     volume = NULL;
3105   }
3106   return volume;
3107 }