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