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