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