Salome HOME
23315: [CEA 1929] Too much memory used to display a mesh in shading and wireframe
[modules/smesh.git] / src / SMDS / SMDS_Mesh.cxx
1 // Copyright (C) 2007-2016  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, or (at your option) any later version.
10 //
11 // This library is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 // Lesser General Public License for more details.
15 //
16 // You should have received a copy of the GNU Lesser General Public
17 // License along with this library; if not, write to the Free Software
18 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
19 //
20 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
21 //
22
23 //  SMESH SMDS : implementation of Salome mesh data structure
24 //
25 #ifdef _MSC_VER
26 #pragma warning(disable:4786)
27 #endif
28
29 #include "SMDS_FaceOfEdges.hxx"
30 #include "SMDS_FaceOfNodes.hxx"
31 #include "SMDS_Mesh.hxx"
32 #include "SMDS_PolygonalFaceOfNodes.hxx"
33 #include "SMDS_PolyhedralVolumeOfNodes.hxx"
34 #include "SMDS_QuadraticEdge.hxx"
35 #include "SMDS_QuadraticFaceOfNodes.hxx"
36 #include "SMDS_QuadraticVolumeOfNodes.hxx"
37 #include "SMDS_SetIterator.hxx"
38 #include "SMDS_SpacePosition.hxx"
39 #include "SMDS_UnstructuredGrid.hxx"
40 #include "SMDS_VolumeOfFaces.hxx"
41 #include "SMDS_VolumeOfNodes.hxx"
42
43 #include "utilities.h"
44
45 #include <vtkUnstructuredGrid.h>
46 #include <vtkUnstructuredGridWriter.h>
47 #include <vtkUnsignedCharArray.h>
48 #include <vtkCell.h>
49 #include <vtkCellLinks.h>
50 #include <vtkIdList.h>
51
52 #include <algorithm>
53 #include <map>
54 #include <iostream>
55 #include <fstream>
56 #include <iterator>
57 using namespace std;
58
59 #ifndef WIN32
60 #include <sys/sysinfo.h>
61 #endif
62
63 // number of added entities to check memory after
64 #define CHECKMEMORY_INTERVAL 100000
65
66 vector<SMDS_Mesh*> SMDS_Mesh::_meshList = vector<SMDS_Mesh*>();
67 int SMDS_Mesh::chunkSize = 1024;
68
69
70 //================================================================================
71 /*!
72  * \brief Raise an exception if free memory (ram+swap) too low
73  * \param doNotRaise - if true, suppres exception, just return free memory size
74  * \retval int - amount of available memory in MB or negative number in failure case
75  */
76 //================================================================================
77
78 int SMDS_Mesh::CheckMemory(const bool doNotRaise) throw (std::bad_alloc)
79 {
80 #ifndef WIN32
81   struct sysinfo si;
82   int err = sysinfo( &si );
83   if ( err )
84     return -1;
85
86   const unsigned long Mbyte = 1024 * 1024;
87
88   static int limit = -1;
89   if ( limit < 0 ) {
90     int status = system("SMDS_MemoryLimit"); // it returns lower limit of free RAM
91     if (status >= 0 ) {
92       limit = WEXITSTATUS(status);
93     }
94     else {
95       double factor = ( si.totalswap == 0 ) ? 0.1 : 0.2;
96       limit = int(( factor * si.totalram * si.mem_unit ) / Mbyte );
97     }
98     if ( limit < 20 )
99       limit = 20;
100     else
101       limit = int ( limit * 1.5 );
102     MESSAGE ( "SMDS_Mesh::CheckMemory() memory limit = " << limit << " MB" );
103   }
104
105   // compute separately to avoid overflow
106   int freeMb =
107     ( si.freeram  * si.mem_unit ) / Mbyte +
108     ( si.freeswap * si.mem_unit ) / Mbyte;
109   //cout << "freeMb = " << freeMb << " limit = " << limit << endl;
110
111   if ( freeMb > limit )
112     return freeMb - limit;
113
114   if ( doNotRaise )
115     return 0;
116
117   MESSAGE ("SMDS_Mesh::CheckMemory() throws as free memory too low: " << freeMb <<" MB" );
118   throw std::bad_alloc();
119 #else
120   return -1;
121 #endif
122 }
123
124 ///////////////////////////////////////////////////////////////////////////////
125 /// Create a new mesh object
126 ///////////////////////////////////////////////////////////////////////////////
127 SMDS_Mesh::SMDS_Mesh():
128   myNodePool(0), myVolumePool(0), myFacePool(0), myEdgePool(0), myBallPool(0),
129   myParent(NULL),
130   myNodeIDFactory(new SMDS_MeshNodeIDFactory()),
131   myElementIDFactory(new SMDS_MeshElementIDFactory()),
132   myModified(false), myModifTime(0), myCompactTime(0),
133   myNodeMin(0), myNodeMax(0),
134   myHasConstructionEdges(false), myHasConstructionFaces(false),
135   myHasInverseElements(true),
136   xmin(0), xmax(0), ymin(0), ymax(0), zmin(0), zmax(0)
137 {
138   myMeshId = _meshList.size();         // --- index of the mesh to push back in the vector
139   myNodeIDFactory->SetMesh(this);
140   myElementIDFactory->SetMesh(this);
141   _meshList.push_back(this);
142   myNodePool = new ObjectPool<SMDS_MeshNode>(SMDS_Mesh::chunkSize);
143   myEdgePool = new ObjectPool<SMDS_VtkEdge>(SMDS_Mesh::chunkSize);
144   myFacePool = new ObjectPool<SMDS_VtkFace>(SMDS_Mesh::chunkSize);
145   myVolumePool = new ObjectPool<SMDS_VtkVolume>(SMDS_Mesh::chunkSize);
146   myBallPool = new ObjectPool<SMDS_BallElement>(SMDS_Mesh::chunkSize);
147
148   myNodes.clear();
149   myCells.clear();
150   //myCellIdSmdsToVtk.clear();
151   myCellIdVtkToSmds.clear();
152   myGrid = SMDS_UnstructuredGrid::New();
153   myGrid->setSMDS_mesh(this);
154   myGrid->Initialize();
155   myGrid->Allocate();
156   vtkPoints* points = vtkPoints::New();
157   // bug "21125: EDF 1233 SMESH: Degrardation of precision in a test case for quadratic conversion"
158   // Use double type for storing coordinates of nodes instead of float.
159   points->SetDataType(VTK_DOUBLE);
160   points->SetNumberOfPoints(0 /*SMDS_Mesh::chunkSize*/);
161   myGrid->SetPoints( points );
162   points->Delete();
163   //myGrid->BuildLinks();
164   this->Modified();
165
166   // initialize static maps in SMDS_MeshCell, to be thread-safe
167   if ( myMeshId == 0 )
168   {
169     SMDS_MeshCell::toVtkType( SMDSEntity_Node );
170     SMDS_MeshCell::toVtkOrder( SMDSEntity_Node );
171     SMDS_MeshCell::reverseSmdsOrder( SMDSEntity_Node );
172     SMDS_MeshCell::interlacedSmdsOrder( SMDSEntity_Node );
173     SMDS_MeshCell::toSmdsType( VTK_VERTEX );
174     SMDS_MeshCell::fromVtkOrder( SMDSEntity_Node );
175   }
176 }
177
178 ///////////////////////////////////////////////////////////////////////////////
179 /// Create a new child mesh
180 /// Note that the tree structure of SMDS_Mesh seems to be unused in this version
181 /// (2003-09-08) of SMESH
182 ///////////////////////////////////////////////////////////////////////////////
183 SMDS_Mesh::SMDS_Mesh(SMDS_Mesh * parent):
184   myNodePool(parent->myNodePool),
185   myVolumePool(parent->myVolumePool),
186   myFacePool(parent->myFacePool),
187   myEdgePool(parent->myEdgePool),
188   myBallPool(parent->myBallPool),
189   myParent(parent), myNodeIDFactory(parent->myNodeIDFactory),
190   myElementIDFactory(parent->myElementIDFactory),
191   myHasConstructionEdges(false), myHasConstructionFaces(false),
192   myHasInverseElements(true)
193 {
194 }
195
196 ///////////////////////////////////////////////////////////////////////////////
197 ///Create a submesh and add it to the current mesh
198 ///////////////////////////////////////////////////////////////////////////////
199
200 SMDS_Mesh *SMDS_Mesh::AddSubMesh()
201 {
202   SMDS_Mesh *submesh = new SMDS_Mesh(this);
203   myChildren.insert(myChildren.end(), submesh);
204   return submesh;
205 }
206
207 ///////////////////////////////////////////////////////////////////////////////
208 ///create a MeshNode and add it to the current Mesh
209 ///An ID is automatically assigned to the node.
210 ///@return : The created node
211 ///////////////////////////////////////////////////////////////////////////////
212
213 SMDS_MeshNode * SMDS_Mesh::AddNode(double x, double y, double z)
214 {
215   return SMDS_Mesh::AddNodeWithID(x,y,z,myNodeIDFactory->GetFreeID());
216 }
217
218 ///////////////////////////////////////////////////////////////////////////////
219 ///create a MeshNode and add it to the current Mesh
220 ///@param ID : The ID of the MeshNode to create
221 ///@return : The created node or NULL if a node with this ID already exists
222 ///////////////////////////////////////////////////////////////////////////////
223 SMDS_MeshNode * SMDS_Mesh::AddNodeWithID(double x, double y, double z, int ID)
224 {
225   // find the MeshNode corresponding to ID
226   const SMDS_MeshElement *node = myNodeIDFactory->MeshElement(ID);
227   if(!node){
228     if (ID < 1)
229       {
230         MESSAGE("=============>  Bad Node Id: " << ID);
231         ID = myNodeIDFactory->GetFreeID();
232       }
233     myNodeIDFactory->adjustMaxId(ID);
234     SMDS_MeshNode * node = myNodePool->getNew();
235     node->init(ID, myMeshId, 0, x, y, z);
236
237     if (ID >= (int)myNodes.size())
238     {
239         myNodes.resize(ID+SMDS_Mesh::chunkSize, 0);
240 //         MESSAGE(" ------------------ myNodes resize " << ID << " --> " << ID+SMDS_Mesh::chunkSize);
241     }
242     myNodes[ID] = node;
243     myNodeIDFactory->BindID(ID,node);
244     myInfo.myNbNodes++;
245     myModified = true;
246     this->adjustBoundingBox(x, y, z);
247     return node;
248   }else
249     return NULL;
250 }
251
252 ///////////////////////////////////////////////////////////////////////////////
253 /// create a Mesh0DElement and add it to the current Mesh
254 /// @return : The created Mesh0DElement
255 ///////////////////////////////////////////////////////////////////////////////
256 SMDS_Mesh0DElement* SMDS_Mesh::Add0DElementWithID(int idnode, int ID)
257 {
258   SMDS_MeshNode * node = (SMDS_MeshNode *)myNodeIDFactory->MeshElement(idnode);
259   if (!node) return NULL;
260   return SMDS_Mesh::Add0DElementWithID(node, ID);
261 }
262
263 ///////////////////////////////////////////////////////////////////////////////
264 /// create a Mesh0DElement and add it to the current Mesh
265 /// @return : The created Mesh0DElement
266 ///////////////////////////////////////////////////////////////////////////////
267 SMDS_Mesh0DElement* SMDS_Mesh::Add0DElement(const SMDS_MeshNode * node)
268 {
269   return SMDS_Mesh::Add0DElementWithID(node, myElementIDFactory->GetFreeID());
270 }
271
272 ///////////////////////////////////////////////////////////////////////////////
273 /// Create a new Mesh0DElement and at it to the mesh
274 /// @param idnode ID of the node
275 /// @param ID ID of the 0D element to create
276 /// @return The created 0D element or NULL if an element with this
277 ///         ID already exists or if input node is not found.
278 ///////////////////////////////////////////////////////////////////////////////
279 SMDS_Mesh0DElement* SMDS_Mesh::Add0DElementWithID(const SMDS_MeshNode * n, int ID)
280 {
281   if (!n) return 0;
282
283   if (Nb0DElements() % CHECKMEMORY_INTERVAL == 0) CheckMemory();
284   //MESSAGE("Add0DElementWithID" << ID)
285   SMDS_Mesh0DElement * el0d = new SMDS_Mesh0DElement(n);
286   if (myElementIDFactory->BindID(ID, el0d)) {
287     //SMDS_MeshNode *node = const_cast<SMDS_MeshNode*>(n);
288     //node->AddInverseElement(el0d);// --- fait avec BindID
289     adjustmyCellsCapacity(ID);
290     myCells[ID] = el0d;
291     myInfo.myNb0DElements++;
292     return el0d;
293   }
294
295   delete el0d;
296   return NULL;
297 }
298
299 ///////////////////////////////////////////////////////////////////////////////
300 /// create a Ball and add it to the current Mesh
301 /// @return : The created Ball
302 ///////////////////////////////////////////////////////////////////////////////
303 SMDS_BallElement* SMDS_Mesh::AddBallWithID(int idnode, double diameter, int ID)
304 {
305   SMDS_MeshNode * node = (SMDS_MeshNode *)myNodeIDFactory->MeshElement(idnode);
306   if (!node) return NULL;
307   return SMDS_Mesh::AddBallWithID(node, diameter, ID);
308 }
309
310 ///////////////////////////////////////////////////////////////////////////////
311 /// create a Ball and add it to the current Mesh
312 /// @return : The created Ball
313 ///////////////////////////////////////////////////////////////////////////////
314 SMDS_BallElement* SMDS_Mesh::AddBall(const SMDS_MeshNode * node, double diameter)
315 {
316   return SMDS_Mesh::AddBallWithID(node, diameter, myElementIDFactory->GetFreeID());
317 }
318
319 ///////////////////////////////////////////////////////////////////////////////
320 /// Create a new Ball and at it to the mesh
321 /// @param idnode ID of the node
322 //  @param diameter ball diameter
323 /// @param ID ID of the 0D element to create
324 /// @return The created 0D element or NULL if an element with this
325 ///         ID already exists or if input node is not found.
326 ///////////////////////////////////////////////////////////////////////////////
327 SMDS_BallElement* SMDS_Mesh::AddBallWithID(const SMDS_MeshNode * n, double diameter, int ID)
328 {
329   if (!n) return 0;
330
331   if (NbBalls() % CHECKMEMORY_INTERVAL == 0) CheckMemory();
332
333   SMDS_BallElement *ball = myBallPool->getNew();
334   ball->init(n->getVtkId(), diameter, this);
335   if (!this->registerElement(ID,ball))
336   {
337     this->myGrid->GetCellTypesArray()->SetValue(ball->getVtkId(), VTK_EMPTY_CELL);
338     myBallPool->destroy(ball);
339     return 0;
340   }
341   adjustmyCellsCapacity(ID);
342   myCells[ID] = ball;
343   myInfo.myNbBalls++;
344   return ball;
345 }
346
347 ///////////////////////////////////////////////////////////////////////////////
348 /// create a MeshEdge and add it to the current Mesh
349 /// @return : The created MeshEdge
350 ///////////////////////////////////////////////////////////////////////////////
351
352 SMDS_MeshEdge* SMDS_Mesh::AddEdgeWithID(int idnode1, int idnode2, int ID)
353 {
354   SMDS_MeshNode * node1 = (SMDS_MeshNode *)myNodeIDFactory->MeshElement(idnode1);
355   SMDS_MeshNode * node2 = (SMDS_MeshNode *)myNodeIDFactory->MeshElement(idnode2);
356   if(!node1 || !node2) return NULL;
357   return SMDS_Mesh::AddEdgeWithID(node1, node2, ID);
358 }
359
360 ///////////////////////////////////////////////////////////////////////////////
361 /// create a MeshEdge and add it to the current Mesh
362 /// @return : The created MeshEdge
363 ///////////////////////////////////////////////////////////////////////////////
364
365 SMDS_MeshEdge* SMDS_Mesh::AddEdge(const SMDS_MeshNode * node1,
366                                   const SMDS_MeshNode * node2)
367 {
368   return SMDS_Mesh::AddEdgeWithID(node1, node2, myElementIDFactory->GetFreeID());
369 }
370
371 ///////////////////////////////////////////////////////////////////////////////
372 /// Create a new edge and at it to the mesh
373 /// @param idnode1 ID of the first node
374 /// @param idnode2 ID of the second node
375 /// @param ID ID of the edge to create
376 /// @return The created edge or NULL if an element with this ID already exists or
377 /// if input nodes are not found.
378 ///////////////////////////////////////////////////////////////////////////////
379
380 SMDS_MeshEdge* SMDS_Mesh::AddEdgeWithID(const SMDS_MeshNode * n1,
381                                         const SMDS_MeshNode * n2,
382                                         int ID)
383 {
384   if ( !n1 || !n2 ) return 0;
385   SMDS_MeshEdge * edge = 0;
386
387   // --- retreive nodes ID
388   vector<vtkIdType> nodeIds;
389   nodeIds.clear();
390   nodeIds.push_back(n1->getVtkId());
391   nodeIds.push_back(n2->getVtkId());
392
393   SMDS_VtkEdge *edgevtk = myEdgePool->getNew();
394   edgevtk->init(nodeIds, this);
395   if (!this->registerElement(ID,edgevtk))
396     {
397       this->myGrid->GetCellTypesArray()->SetValue(edgevtk->getVtkId(), VTK_EMPTY_CELL);
398       myEdgePool->destroy(edgevtk);
399       return 0;
400     }
401   edge = edgevtk;
402   adjustmyCellsCapacity(ID);
403   myCells[ID] = edge;
404   myInfo.myNbEdges++;
405
406 //  if (edge && !registerElement(ID, edge))
407 //  {
408 //    RemoveElement(edge, false);
409 //    edge = NULL;
410 //  }
411   return edge;
412 }
413
414 ///////////////////////////////////////////////////////////////////////////////
415 /// Add a triangle defined by its nodes. An ID is automatically affected to the
416 /// Created face
417 ///////////////////////////////////////////////////////////////////////////////
418
419 SMDS_MeshFace* SMDS_Mesh::AddFace(const SMDS_MeshNode * n1,
420                                   const SMDS_MeshNode * n2,
421                                   const SMDS_MeshNode * n3)
422 {
423   return SMDS_Mesh::AddFaceWithID(n1,n2,n3, myElementIDFactory->GetFreeID());
424 }
425
426 ///////////////////////////////////////////////////////////////////////////////
427 /// Add a triangle defined by its nodes IDs
428 ///////////////////////////////////////////////////////////////////////////////
429
430 SMDS_MeshFace* SMDS_Mesh::AddFaceWithID(int idnode1, int idnode2, int idnode3, int ID)
431 {
432   SMDS_MeshNode * node1 = (SMDS_MeshNode *)myNodeIDFactory->MeshElement(idnode1);
433   SMDS_MeshNode * node2 = (SMDS_MeshNode *)myNodeIDFactory->MeshElement(idnode2);
434   SMDS_MeshNode * node3 = (SMDS_MeshNode *)myNodeIDFactory->MeshElement(idnode3);
435   if(!node1 || !node2 || !node3) return NULL;
436   return SMDS_Mesh::AddFaceWithID(node1, node2, node3, ID);
437 }
438
439 ///////////////////////////////////////////////////////////////////////////////
440 /// Add a triangle defined by its nodes
441 ///////////////////////////////////////////////////////////////////////////////
442
443 SMDS_MeshFace* SMDS_Mesh::AddFaceWithID(const SMDS_MeshNode * n1,
444                                         const SMDS_MeshNode * n2,
445                                         const SMDS_MeshNode * n3,
446                                         int ID)
447 {
448   //MESSAGE("AddFaceWithID " << ID)
449   SMDS_MeshFace * face=createTriangle(n1, n2, n3, ID);
450
451 //  if (face && !registerElement(ID, face)) {
452 //    RemoveElement(face, false);
453 //    face = NULL;
454 //  }
455   return face;
456 }
457
458 ///////////////////////////////////////////////////////////////////////////////
459 /// Add a quadrangle defined by its nodes. An ID is automatically affected to the
460 /// created face
461 ///////////////////////////////////////////////////////////////////////////////
462
463 SMDS_MeshFace* SMDS_Mesh::AddFace(const SMDS_MeshNode * n1,
464                                   const SMDS_MeshNode * n2,
465                                   const SMDS_MeshNode * n3,
466                                   const SMDS_MeshNode * n4)
467 {
468   return SMDS_Mesh::AddFaceWithID(n1,n2,n3, n4, myElementIDFactory->GetFreeID());
469 }
470
471 ///////////////////////////////////////////////////////////////////////////////
472 /// Add a quadrangle defined by its nodes IDs
473 ///////////////////////////////////////////////////////////////////////////////
474
475 SMDS_MeshFace* SMDS_Mesh::AddFaceWithID(int idnode1,
476                                         int idnode2,
477                                         int idnode3,
478                                         int idnode4,
479                                         int ID)
480 {
481   SMDS_MeshNode *node1, *node2, *node3, *node4;
482   node1 = (SMDS_MeshNode *)myNodeIDFactory->MeshElement(idnode1);
483   node2 = (SMDS_MeshNode *)myNodeIDFactory->MeshElement(idnode2);
484   node3 = (SMDS_MeshNode *)myNodeIDFactory->MeshElement(idnode3);
485   node4 = (SMDS_MeshNode *)myNodeIDFactory->MeshElement(idnode4);
486   if(!node1 || !node2 || !node3 || !node4) return NULL;
487   return SMDS_Mesh::AddFaceWithID(node1, node2, node3, node4, ID);
488 }
489
490 ///////////////////////////////////////////////////////////////////////////////
491 /// Add a quadrangle defined by its nodes
492 ///////////////////////////////////////////////////////////////////////////////
493
494 SMDS_MeshFace* SMDS_Mesh::AddFaceWithID(const SMDS_MeshNode * n1,
495                                         const SMDS_MeshNode * n2,
496                                         const SMDS_MeshNode * n3,
497                                         const SMDS_MeshNode * n4,
498                                         int ID)
499 {
500   //MESSAGE("AddFaceWithID " << ID);
501   SMDS_MeshFace * face=createQuadrangle(n1, n2, n3, n4, ID);
502
503 //  if (face && !registerElement(ID, face)) {
504 //    RemoveElement(face, false);
505 //    face = NULL;
506 //  }
507   return face;
508 }
509
510 ///////////////////////////////////////////////////////////////////////////////
511 /// Add a triangle defined by its edges. An ID is automatically assigned to the
512 /// Created face
513 ///////////////////////////////////////////////////////////////////////////////
514
515 SMDS_MeshFace* SMDS_Mesh::AddFace(const SMDS_MeshEdge * e1,
516                                   const SMDS_MeshEdge * e2,
517                                   const SMDS_MeshEdge * e3)
518 {
519   if (!hasConstructionEdges())
520     return NULL;
521      //MESSAGE("AddFaceWithID");
522  return AddFaceWithID(e1,e2,e3, myElementIDFactory->GetFreeID());
523 }
524
525 ///////////////////////////////////////////////////////////////////////////////
526 /// Add a triangle defined by its edges
527 ///////////////////////////////////////////////////////////////////////////////
528
529 SMDS_MeshFace* SMDS_Mesh::AddFaceWithID(const SMDS_MeshEdge * e1,
530                                         const SMDS_MeshEdge * e2,
531                                         const SMDS_MeshEdge * e3,
532                                         int ID)
533 {
534   if (!hasConstructionEdges())
535     return NULL;
536   if ( !e1 || !e2 || !e3 ) return 0;
537
538   if ( NbFaces() % CHECKMEMORY_INTERVAL == 0 ) CheckMemory();
539
540   SMDS_MeshFace * face = new SMDS_FaceOfEdges(e1,e2,e3);
541   adjustmyCellsCapacity(ID);
542   myCells[ID] = face;
543   myInfo.myNbTriangles++;
544
545   if (!registerElement(ID, face)) {
546     registerElement(myElementIDFactory->GetFreeID(), face);
547     //RemoveElement(face, false);
548     //face = NULL;
549   }
550   return face;
551 }
552
553 ///////////////////////////////////////////////////////////////////////////////
554 /// Add a quadrangle defined by its edges. An ID is automatically assigned to the
555 /// Created face
556 ///////////////////////////////////////////////////////////////////////////////
557
558 SMDS_MeshFace* SMDS_Mesh::AddFace(const SMDS_MeshEdge * e1,
559                                   const SMDS_MeshEdge * e2,
560                                   const SMDS_MeshEdge * e3,
561                                   const SMDS_MeshEdge * e4)
562 {
563   if (!hasConstructionEdges())
564     return NULL;
565  return AddFaceWithID(e1,e2,e3,e4, myElementIDFactory->GetFreeID());
566 }
567
568 ///////////////////////////////////////////////////////////////////////////////
569 /// Add a quadrangle defined by its edges
570 ///////////////////////////////////////////////////////////////////////////////
571
572 SMDS_MeshFace* SMDS_Mesh::AddFaceWithID(const SMDS_MeshEdge * e1,
573                                         const SMDS_MeshEdge * e2,
574                                         const SMDS_MeshEdge * e3,
575                                         const SMDS_MeshEdge * e4,
576                                         int ID)
577 {
578   if (!hasConstructionEdges())
579     return NULL;
580   if ( !e1 || !e2 || !e3 || !e4 ) return 0;
581   if ( NbFaces() % CHECKMEMORY_INTERVAL == 0 ) CheckMemory();
582   SMDS_MeshFace * face = new SMDS_FaceOfEdges(e1,e2,e3,e4);
583   adjustmyCellsCapacity(ID);
584   myCells[ID] = face;
585   myInfo.myNbQuadrangles++;
586
587   if (!registerElement(ID, face))
588   {
589     registerElement(myElementIDFactory->GetFreeID(), face);
590     //RemoveElement(face, false);
591     //face = NULL;
592   }
593   return face;
594 }
595
596 ///////////////////////////////////////////////////////////////////////////////
597 ///Create a new tetrahedron and add it to the mesh.
598 ///@return The created tetrahedron
599 ///////////////////////////////////////////////////////////////////////////////
600
601 SMDS_MeshVolume* SMDS_Mesh::AddVolume(const SMDS_MeshNode * n1,
602                                       const SMDS_MeshNode * n2,
603                                       const SMDS_MeshNode * n3,
604                                       const SMDS_MeshNode * n4)
605 {
606   int ID = myElementIDFactory->GetFreeID();
607   SMDS_MeshVolume * v = SMDS_Mesh::AddVolumeWithID(n1, n2, n3, n4, ID);
608   if(v==NULL) myElementIDFactory->ReleaseID(ID);
609   return v;
610 }
611
612 ///////////////////////////////////////////////////////////////////////////////
613 ///Create a new tetrahedron and add it to the mesh.
614 ///@param ID The ID of the new volume
615 ///@return The created tetrahedron or NULL if an element with this ID already exists
616 ///or if input nodes are not found.
617 ///////////////////////////////////////////////////////////////////////////////
618
619 SMDS_MeshVolume * SMDS_Mesh::AddVolumeWithID(int idnode1,
620                                              int idnode2,
621                                              int idnode3,
622                                              int idnode4,
623                                              int ID)
624 {
625   SMDS_MeshNode *node1, *node2, *node3, *node4;
626   node1 = (SMDS_MeshNode *)myNodeIDFactory->MeshElement(idnode1);
627   node2 = (SMDS_MeshNode *)myNodeIDFactory->MeshElement(idnode2);
628   node3 = (SMDS_MeshNode *)myNodeIDFactory->MeshElement(idnode3);
629   node4 = (SMDS_MeshNode *)myNodeIDFactory->MeshElement(idnode4);
630   if(!node1 || !node2 || !node3 || !node4) return NULL;
631   return SMDS_Mesh::AddVolumeWithID(node1, node2, node3, node4, ID);
632 }
633
634 ///////////////////////////////////////////////////////////////////////////////
635 ///Create a new tetrahedron and add it to the mesh.
636 ///@param ID The ID of the new volume
637 ///@return The created tetrahedron
638 ///////////////////////////////////////////////////////////////////////////////
639
640 SMDS_MeshVolume* SMDS_Mesh::AddVolumeWithID(const SMDS_MeshNode * n1,
641                                             const SMDS_MeshNode * n2,
642                                             const SMDS_MeshNode * n3,
643                                             const SMDS_MeshNode * n4,
644                                             int ID)
645 {
646   SMDS_MeshVolume* volume = 0;
647   if ( !n1 || !n2 || !n3 || !n4) return volume;
648   if ( NbVolumes() % CHECKMEMORY_INTERVAL == 0 ) CheckMemory();
649   if(hasConstructionFaces()) {
650     SMDS_MeshFace * f1=FindFaceOrCreate(n1,n2,n3);
651     SMDS_MeshFace * f2=FindFaceOrCreate(n1,n2,n4);
652     SMDS_MeshFace * f3=FindFaceOrCreate(n1,n3,n4);
653     SMDS_MeshFace * f4=FindFaceOrCreate(n2,n3,n4);
654     volume=new SMDS_VolumeOfFaces(f1,f2,f3,f4);
655     adjustmyCellsCapacity(ID);
656     myCells[ID] = volume;
657     myInfo.myNbTetras++;
658   }
659   else if(hasConstructionEdges()) {
660     return NULL;
661   }
662   else {
663     // --- retrieve nodes ID
664     myNodeIds.resize(4);
665     myNodeIds[0] = n1->getVtkId();
666     myNodeIds[1] = n3->getVtkId(); // order SMDS-->VTK
667     myNodeIds[2] = n2->getVtkId();
668     myNodeIds[3] = n4->getVtkId();
669
670     SMDS_VtkVolume *volvtk = myVolumePool->getNew();
671     volvtk->init(myNodeIds, this);
672     if (!this->registerElement(ID,volvtk))
673     {
674       this->myGrid->GetCellTypesArray()->SetValue(volvtk->getVtkId(), VTK_EMPTY_CELL);
675       myVolumePool->destroy(volvtk);
676       return 0;
677     }
678     volume = volvtk;
679     adjustmyCellsCapacity(ID);
680     myCells[ID] = volume;
681     myInfo.myNbTetras++;
682   }
683
684   //  if (!registerElement(ID, volume)) {
685   //    RemoveElement(volume, false);
686   //    volume = NULL;
687   //  }
688   return volume;
689 }
690
691 ///////////////////////////////////////////////////////////////////////////////
692 ///Create a new pyramid and add it to the mesh.
693 ///Nodes 1,2,3 and 4 define the base of the pyramid
694 ///@return The created pyramid
695 ///////////////////////////////////////////////////////////////////////////////
696
697 SMDS_MeshVolume* SMDS_Mesh::AddVolume(const SMDS_MeshNode * n1,
698                                       const SMDS_MeshNode * n2,
699                                       const SMDS_MeshNode * n3,
700                                       const SMDS_MeshNode * n4,
701                                       const SMDS_MeshNode * n5)
702 {
703   int ID = myElementIDFactory->GetFreeID();
704   SMDS_MeshVolume * v = SMDS_Mesh::AddVolumeWithID(n1, n2, n3, n4, n5, ID);
705   if(v==NULL) myElementIDFactory->ReleaseID(ID);
706   return v;
707 }
708
709 ///////////////////////////////////////////////////////////////////////////////
710 ///Create a new pyramid and add it to the mesh.
711 ///Nodes 1,2,3 and 4 define the base of the pyramid
712 ///@param ID The ID of the new volume
713 ///@return The created pyramid or NULL if an element with this ID already exists
714 ///or if input nodes are not found.
715 ///////////////////////////////////////////////////////////////////////////////
716
717 SMDS_MeshVolume * SMDS_Mesh::AddVolumeWithID(int idnode1,
718                                              int idnode2,
719                                              int idnode3,
720                                              int idnode4,
721                                              int idnode5,
722                                              int ID)
723 {
724   SMDS_MeshNode *node1, *node2, *node3, *node4, *node5;
725   node1 = (SMDS_MeshNode *)myNodeIDFactory->MeshElement(idnode1);
726   node2 = (SMDS_MeshNode *)myNodeIDFactory->MeshElement(idnode2);
727   node3 = (SMDS_MeshNode *)myNodeIDFactory->MeshElement(idnode3);
728   node4 = (SMDS_MeshNode *)myNodeIDFactory->MeshElement(idnode4);
729   node5 = (SMDS_MeshNode *)myNodeIDFactory->MeshElement(idnode5);
730   if(!node1 || !node2 || !node3 || !node4 || !node5) return NULL;
731   return SMDS_Mesh::AddVolumeWithID(node1, node2, node3, node4, node5, ID);
732 }
733
734 ///////////////////////////////////////////////////////////////////////////////
735 ///Create a new pyramid and add it to the mesh.
736 ///Nodes 1,2,3 and 4 define the base of the pyramid
737 ///@param ID The ID of the new volume
738 ///@return The created pyramid
739 ///////////////////////////////////////////////////////////////////////////////
740
741 SMDS_MeshVolume* SMDS_Mesh::AddVolumeWithID(const SMDS_MeshNode * n1,
742                                             const SMDS_MeshNode * n2,
743                                             const SMDS_MeshNode * n3,
744                                             const SMDS_MeshNode * n4,
745                                             const SMDS_MeshNode * n5,
746                                             int ID)
747 {
748   SMDS_MeshVolume* volume = 0;
749   if ( !n1 || !n2 || !n3 || !n4 || !n5) return volume;
750   if ( NbVolumes() % CHECKMEMORY_INTERVAL == 0 ) CheckMemory();
751   if(hasConstructionFaces()) {
752     SMDS_MeshFace * f1=FindFaceOrCreate(n1,n2,n3,n4);
753     SMDS_MeshFace * f2=FindFaceOrCreate(n1,n2,n5);
754     SMDS_MeshFace * f3=FindFaceOrCreate(n2,n3,n5);
755     SMDS_MeshFace * f4=FindFaceOrCreate(n3,n4,n5);
756     volume=new SMDS_VolumeOfFaces(f1,f2,f3,f4);
757     adjustmyCellsCapacity(ID);
758     myCells[ID] = volume;
759     myInfo.myNbPyramids++;
760   }
761   else if(hasConstructionEdges()) {
762     return NULL;
763   }
764   else {
765     // --- retrieve nodes ID
766     myNodeIds.resize(5);
767     myNodeIds[0] = n1->getVtkId();
768     myNodeIds[1] = n4->getVtkId();
769     myNodeIds[2] = n3->getVtkId();
770     myNodeIds[3] = n2->getVtkId();
771     myNodeIds[4] = n5->getVtkId();
772
773     SMDS_VtkVolume *volvtk = myVolumePool->getNew();
774     volvtk->init(myNodeIds, this);
775     if (!this->registerElement(ID,volvtk))
776     {
777       this->myGrid->GetCellTypesArray()->SetValue(volvtk->getVtkId(), VTK_EMPTY_CELL);
778       myVolumePool->destroy(volvtk);
779       return 0;
780     }
781     volume = volvtk;
782     adjustmyCellsCapacity(ID);
783     myCells[ID] = volume;
784     myInfo.myNbPyramids++;
785   }
786
787   //  if (!registerElement(ID, volume)) {
788   //    RemoveElement(volume, false);
789   //    volume = NULL;
790   //  }
791   return volume;
792 }
793
794 ///////////////////////////////////////////////////////////////////////////////
795 ///Create a new prism and add it to the mesh.
796 ///Nodes 1,2,3 is a triangle and 1,2,5,4 a quadrangle.
797 ///@return The created prism
798 ///////////////////////////////////////////////////////////////////////////////
799
800 SMDS_MeshVolume* SMDS_Mesh::AddVolume(const SMDS_MeshNode * n1,
801                                       const SMDS_MeshNode * n2,
802                                       const SMDS_MeshNode * n3,
803                                       const SMDS_MeshNode * n4,
804                                       const SMDS_MeshNode * n5,
805                                       const SMDS_MeshNode * n6)
806 {
807   int ID = myElementIDFactory->GetFreeID();
808   SMDS_MeshVolume * v = SMDS_Mesh::AddVolumeWithID(n1, n2, n3, n4, n5, n6, ID);
809   if(v==NULL) myElementIDFactory->ReleaseID(ID);
810   return v;
811 }
812
813 ///////////////////////////////////////////////////////////////////////////////
814 ///Create a new prism and add it to the mesh.
815 ///Nodes 1,2,3 is a triangle and 1,2,5,4 a quadrangle.
816 ///@param ID The ID of the new volume
817 ///@return The created prism or NULL if an element with this ID already exists
818 ///or if input nodes are not found.
819 ///////////////////////////////////////////////////////////////////////////////
820
821 SMDS_MeshVolume * SMDS_Mesh::AddVolumeWithID(int idnode1,
822                                              int idnode2,
823                                              int idnode3,
824                                              int idnode4,
825                                              int idnode5,
826                                              int idnode6,
827                                              int ID)
828 {
829   SMDS_MeshNode *node1, *node2, *node3, *node4, *node5, *node6;
830   node1 = (SMDS_MeshNode *)myNodeIDFactory->MeshElement(idnode1);
831   node2 = (SMDS_MeshNode *)myNodeIDFactory->MeshElement(idnode2);
832   node3 = (SMDS_MeshNode *)myNodeIDFactory->MeshElement(idnode3);
833   node4 = (SMDS_MeshNode *)myNodeIDFactory->MeshElement(idnode4);
834   node5 = (SMDS_MeshNode *)myNodeIDFactory->MeshElement(idnode5);
835   node6 = (SMDS_MeshNode *)myNodeIDFactory->MeshElement(idnode6);
836   if(!node1 || !node2 || !node3 || !node4 || !node5 || !node6) return NULL;
837   return SMDS_Mesh::AddVolumeWithID(node1, node2, node3, node4, node5, node6, ID);
838 }
839
840 ///////////////////////////////////////////////////////////////////////////////
841 ///Create a new prism and add it to the mesh.
842 ///Nodes 1,2,3 is a triangle and 1,2,5,4 a quadrangle.
843 ///@param ID The ID of the new volume
844 ///@return The created prism
845 ///////////////////////////////////////////////////////////////////////////////
846
847 SMDS_MeshVolume* SMDS_Mesh::AddVolumeWithID(const SMDS_MeshNode * n1,
848                                             const SMDS_MeshNode * n2,
849                                             const SMDS_MeshNode * n3,
850                                             const SMDS_MeshNode * n4,
851                                             const SMDS_MeshNode * n5,
852                                             const SMDS_MeshNode * n6,
853                                             int ID)
854 {
855   SMDS_MeshVolume* volume = 0;
856   if ( !n1 || !n2 || !n3 || !n4 || !n5 || !n6) return volume;
857   if ( NbVolumes() % CHECKMEMORY_INTERVAL == 0 ) CheckMemory();
858   if(hasConstructionFaces()) {
859     SMDS_MeshFace * f1=FindFaceOrCreate(n1,n2,n3);
860     SMDS_MeshFace * f2=FindFaceOrCreate(n4,n5,n6);
861     SMDS_MeshFace * f3=FindFaceOrCreate(n1,n4,n5,n2);
862     SMDS_MeshFace * f4=FindFaceOrCreate(n2,n5,n6,n3);
863     SMDS_MeshFace * f5=FindFaceOrCreate(n3,n6,n4,n1);
864     volume=new SMDS_VolumeOfFaces(f1,f2,f3,f4,f5);
865     adjustmyCellsCapacity(ID);
866     myCells[ID] = volume;
867     myInfo.myNbPrisms++;
868   }
869   else if(hasConstructionEdges()) {
870     return NULL;
871   }
872   else {
873     // --- retrieve nodes ID
874     myNodeIds.resize(6);
875     myNodeIds[0] = n1->getVtkId();
876     myNodeIds[1] = n2->getVtkId();
877     myNodeIds[2] = n3->getVtkId();
878     myNodeIds[3] = n4->getVtkId();
879     myNodeIds[4] = n5->getVtkId();
880     myNodeIds[5] = n6->getVtkId();
881
882     SMDS_VtkVolume *volvtk = myVolumePool->getNew();
883     volvtk->init(myNodeIds, this);
884     if (!this->registerElement(ID,volvtk))
885     {
886       this->myGrid->GetCellTypesArray()->SetValue(volvtk->getVtkId(), VTK_EMPTY_CELL);
887       myVolumePool->destroy(volvtk);
888       return 0;
889     }
890     volume = volvtk;
891     adjustmyCellsCapacity(ID);
892     myCells[ID] = volume;
893     myInfo.myNbPrisms++;
894   }
895
896   //  if (!registerElement(ID, volume)) {
897   //    RemoveElement(volume, false);
898   //    volume = NULL;
899   //  }
900   return volume;
901 }
902
903 ///////////////////////////////////////////////////////////////////////////////
904 ///Create a new hexagonal prism and add it to the mesh.
905 ///@return The created prism
906 ///////////////////////////////////////////////////////////////////////////////
907
908 SMDS_MeshVolume* SMDS_Mesh::AddVolume(const SMDS_MeshNode * n1,
909                                       const SMDS_MeshNode * n2,
910                                       const SMDS_MeshNode * n3,
911                                       const SMDS_MeshNode * n4,
912                                       const SMDS_MeshNode * n5,
913                                       const SMDS_MeshNode * n6,
914                                       const SMDS_MeshNode * n7,
915                                       const SMDS_MeshNode * n8,
916                                       const SMDS_MeshNode * n9,
917                                       const SMDS_MeshNode * n10,
918                                       const SMDS_MeshNode * n11,
919                                       const SMDS_MeshNode * n12)
920 {
921   int ID = myElementIDFactory->GetFreeID();
922   SMDS_MeshVolume * v = SMDS_Mesh::AddVolumeWithID(n1, n2, n3, n4, n5, n6,
923                                                    n7, n8, n9, n10, n11, n12,
924                                                    ID);
925   if(v==NULL) myElementIDFactory->ReleaseID(ID);
926   return v;
927 }
928
929 ///////////////////////////////////////////////////////////////////////////////
930 ///Create a new hexagonal prism and add it to the mesh.
931 ///@param ID The ID of the new volume
932 ///@return The created prism or NULL if an element with this ID already exists
933 ///or if input nodes are not found.
934 ///////////////////////////////////////////////////////////////////////////////
935
936 SMDS_MeshVolume * SMDS_Mesh::AddVolumeWithID(int idnode1,
937                                              int idnode2,
938                                              int idnode3,
939                                              int idnode4,
940                                              int idnode5,
941                                              int idnode6,
942                                              int idnode7,
943                                              int idnode8,
944                                              int idnode9,
945                                              int idnode10,
946                                              int idnode11,
947                                              int idnode12,
948                                              int ID)
949 {
950   SMDS_MeshNode *node1 = (SMDS_MeshNode *)myNodeIDFactory->MeshElement(idnode1);
951   SMDS_MeshNode *node2 = (SMDS_MeshNode *)myNodeIDFactory->MeshElement(idnode2);
952   SMDS_MeshNode *node3 = (SMDS_MeshNode *)myNodeIDFactory->MeshElement(idnode3);
953   SMDS_MeshNode *node4 = (SMDS_MeshNode *)myNodeIDFactory->MeshElement(idnode4);
954   SMDS_MeshNode *node5 = (SMDS_MeshNode *)myNodeIDFactory->MeshElement(idnode5);
955   SMDS_MeshNode *node6 = (SMDS_MeshNode *)myNodeIDFactory->MeshElement(idnode6);
956   SMDS_MeshNode *node7 = (SMDS_MeshNode *)myNodeIDFactory->MeshElement(idnode7);
957   SMDS_MeshNode *node8 = (SMDS_MeshNode *)myNodeIDFactory->MeshElement(idnode8);
958   SMDS_MeshNode *node9 = (SMDS_MeshNode *)myNodeIDFactory->MeshElement(idnode9);
959   SMDS_MeshNode *node10 = (SMDS_MeshNode *)myNodeIDFactory->MeshElement(idnode10);
960   SMDS_MeshNode *node11 = (SMDS_MeshNode *)myNodeIDFactory->MeshElement(idnode11);
961   SMDS_MeshNode *node12 = (SMDS_MeshNode *)myNodeIDFactory->MeshElement(idnode12);
962   return SMDS_Mesh::AddVolumeWithID(node1, node2, node3, node4, node5, node6,
963                                     node7, node8, node9, node10, node11, node12,
964                                     ID);
965 }
966
967 ///////////////////////////////////////////////////////////////////////////////
968 ///Create a new hexagonal prism and add it to the mesh.
969 ///@param ID The ID of the new volume
970 ///@return The created prism
971 ///////////////////////////////////////////////////////////////////////////////
972
973 SMDS_MeshVolume* SMDS_Mesh::AddVolumeWithID(const SMDS_MeshNode * n1,
974                                             const SMDS_MeshNode * n2,
975                                             const SMDS_MeshNode * n3,
976                                             const SMDS_MeshNode * n4,
977                                             const SMDS_MeshNode * n5,
978                                             const SMDS_MeshNode * n6,
979                                             const SMDS_MeshNode * n7,
980                                             const SMDS_MeshNode * n8,
981                                             const SMDS_MeshNode * n9,
982                                             const SMDS_MeshNode * n10,
983                                             const SMDS_MeshNode * n11,
984                                             const SMDS_MeshNode * n12,
985                                             int ID)
986 {
987   SMDS_MeshVolume* volume = 0;
988   if(!n1 || !n2 || !n3 || !n4 || !n5 || !n6 ||
989      !n7 || !n8 || !n9 || !n10 || !n11 || !n12 )
990     return volume;
991   if ( NbVolumes() % CHECKMEMORY_INTERVAL == 0 ) CheckMemory();
992   if(hasConstructionFaces()) {
993     return NULL;
994   }
995   else if(hasConstructionEdges()) {
996     return NULL;
997   }
998   else {
999     // --- retrieve nodes ID
1000     myNodeIds.resize(12);
1001     myNodeIds[0] = n1->getVtkId();
1002     myNodeIds[1] = n6->getVtkId();
1003     myNodeIds[2] = n5->getVtkId();
1004     myNodeIds[3] = n4->getVtkId();
1005     myNodeIds[4] = n3->getVtkId();
1006     myNodeIds[5] = n2->getVtkId();
1007
1008     myNodeIds[6] = n7->getVtkId();
1009     myNodeIds[7] = n12->getVtkId();
1010     myNodeIds[8] = n11->getVtkId();
1011     myNodeIds[9] = n10->getVtkId();
1012     myNodeIds[10] = n9->getVtkId();
1013     myNodeIds[11] = n8->getVtkId();
1014
1015     SMDS_VtkVolume *volvtk = myVolumePool->getNew();
1016     volvtk->init(myNodeIds, this);
1017     if (!this->registerElement(ID,volvtk))
1018     {
1019       this->myGrid->GetCellTypesArray()->SetValue(volvtk->getVtkId(), VTK_EMPTY_CELL);
1020       myVolumePool->destroy(volvtk);
1021       return 0;
1022     }
1023     volume = volvtk;
1024     adjustmyCellsCapacity(ID);
1025     myCells[ID] = volume;
1026     myInfo.myNbHexPrism++;
1027   }
1028
1029   return volume;
1030 }
1031
1032 ///////////////////////////////////////////////////////////////////////////////
1033 ///Create a new hexahedron and add it to the mesh.
1034 ///Nodes 1,2,3,4 and 5,6,7,8 are quadrangle and 5,1 and 7,3 are an edges.
1035 ///@return The created hexahedron
1036 ///////////////////////////////////////////////////////////////////////////////
1037
1038 SMDS_MeshVolume* SMDS_Mesh::AddVolume(const SMDS_MeshNode * n1,
1039                                       const SMDS_MeshNode * n2,
1040                                       const SMDS_MeshNode * n3,
1041                                       const SMDS_MeshNode * n4,
1042                                       const SMDS_MeshNode * n5,
1043                                       const SMDS_MeshNode * n6,
1044                                       const SMDS_MeshNode * n7,
1045                                       const SMDS_MeshNode * n8)
1046 {
1047   int ID = myElementIDFactory->GetFreeID();
1048  SMDS_MeshVolume * v = SMDS_Mesh::AddVolumeWithID(n1, n2, n3, n4, n5, n6, n7, n8, ID);
1049   if(v==NULL) myElementIDFactory->ReleaseID(ID);
1050   return v;
1051 }
1052
1053 ///////////////////////////////////////////////////////////////////////////////
1054 ///Create a new hexahedron and add it to the mesh.
1055 ///Nodes 1,2,3,4 and 5,6,7,8 are quadrangle and 5,1 and 7,3 are an edges.
1056 ///@param ID The ID of the new volume
1057 ///@return The created hexahedron or NULL if an element with this ID already
1058 ///exists or if input nodes are not found.
1059 ///////////////////////////////////////////////////////////////////////////////
1060
1061 SMDS_MeshVolume * SMDS_Mesh::AddVolumeWithID(int idnode1,
1062                                              int idnode2,
1063                                              int idnode3,
1064                                              int idnode4,
1065                                              int idnode5,
1066                                              int idnode6,
1067                                              int idnode7,
1068                                              int idnode8,
1069                                              int ID)
1070 {
1071   SMDS_MeshNode *node1, *node2, *node3, *node4, *node5, *node6, *node7, *node8;
1072   node1 = (SMDS_MeshNode *)myNodeIDFactory->MeshElement(idnode1);
1073   node2 = (SMDS_MeshNode *)myNodeIDFactory->MeshElement(idnode2);
1074   node3 = (SMDS_MeshNode *)myNodeIDFactory->MeshElement(idnode3);
1075   node4 = (SMDS_MeshNode *)myNodeIDFactory->MeshElement(idnode4);
1076   node5 = (SMDS_MeshNode *)myNodeIDFactory->MeshElement(idnode5);
1077   node6 = (SMDS_MeshNode *)myNodeIDFactory->MeshElement(idnode6);
1078   node7 = (SMDS_MeshNode *)myNodeIDFactory->MeshElement(idnode7);
1079   node8 = (SMDS_MeshNode *)myNodeIDFactory->MeshElement(idnode8);
1080   if(!node1 || !node2 || !node3 || !node4 || !node5 || !node6 || !node7 || !node8)
1081     return NULL;
1082   return SMDS_Mesh::AddVolumeWithID(node1, node2, node3, node4, node5, node6,
1083                                     node7, node8, ID);
1084 }
1085
1086 ///////////////////////////////////////////////////////////////////////////////
1087 ///Create a new hexahedron and add it to the mesh.
1088 ///Nodes 1,2,3,4 and 5,6,7,8 are quadrangle and 5,1 and 7,3 are an edges.
1089 ///@param ID The ID of the new volume
1090 ///@return The created prism or NULL if an element with this ID already exists
1091 ///or if input nodes are not found.
1092 ///////////////////////////////////////////////////////////////////////////////
1093
1094 SMDS_MeshVolume* SMDS_Mesh::AddVolumeWithID(const SMDS_MeshNode * n1,
1095                                             const SMDS_MeshNode * n2,
1096                                             const SMDS_MeshNode * n3,
1097                                             const SMDS_MeshNode * n4,
1098                                             const SMDS_MeshNode * n5,
1099                                             const SMDS_MeshNode * n6,
1100                                             const SMDS_MeshNode * n7,
1101                                             const SMDS_MeshNode * n8,
1102                                             int ID)
1103 {
1104   SMDS_MeshVolume* volume = 0;
1105   if ( !n1 || !n2 || !n3 || !n4 || !n5 || !n6 || !n7 || !n8) return volume;
1106   if ( NbVolumes() % CHECKMEMORY_INTERVAL == 0 ) CheckMemory();
1107   if(hasConstructionFaces()) {
1108     SMDS_MeshFace * f1=FindFaceOrCreate(n1,n2,n3,n4);
1109     SMDS_MeshFace * f2=FindFaceOrCreate(n5,n6,n7,n8);
1110     SMDS_MeshFace * f3=FindFaceOrCreate(n1,n4,n8,n5);
1111     SMDS_MeshFace * f4=FindFaceOrCreate(n1,n2,n6,n5);
1112     SMDS_MeshFace * f5=FindFaceOrCreate(n2,n3,n7,n6);
1113     SMDS_MeshFace * f6=FindFaceOrCreate(n3,n4,n8,n7);
1114     volume=new SMDS_VolumeOfFaces(f1,f2,f3,f4,f5,f6);
1115     adjustmyCellsCapacity(ID);
1116     myCells[ID] = volume;
1117     myInfo.myNbHexas++;
1118   }
1119   else if(hasConstructionEdges()) {
1120     return NULL;
1121   }
1122   else {
1123     // --- retrieve nodes ID
1124     myNodeIds.resize(8);
1125     myNodeIds[0] = n1->getVtkId();
1126     myNodeIds[1] = n4->getVtkId();
1127     myNodeIds[2] = n3->getVtkId();
1128     myNodeIds[3] = n2->getVtkId();
1129     myNodeIds[4] = n5->getVtkId();
1130     myNodeIds[5] = n8->getVtkId();
1131     myNodeIds[6] = n7->getVtkId();
1132     myNodeIds[7] = n6->getVtkId();
1133
1134     SMDS_VtkVolume *volvtk = myVolumePool->getNew();
1135     volvtk->init(myNodeIds, this);
1136     if (!this->registerElement(ID,volvtk))
1137     {
1138       this->myGrid->GetCellTypesArray()->SetValue(volvtk->getVtkId(), VTK_EMPTY_CELL);
1139       myVolumePool->destroy(volvtk);
1140       return 0;
1141     }
1142     volume = volvtk;
1143     adjustmyCellsCapacity(ID);
1144     myCells[ID] = volume;
1145     myInfo.myNbHexas++;
1146   }
1147
1148   //  if (!registerElement(ID, volume)) {
1149   //    RemoveElement(volume, false);
1150   //    volume = NULL;
1151   //  }
1152   return volume;
1153 }
1154
1155 ///////////////////////////////////////////////////////////////////////////////
1156 ///Create a new tetrahedron defined by its faces and add it to the mesh.
1157 ///@return The created tetrahedron
1158 ///////////////////////////////////////////////////////////////////////////////
1159
1160 SMDS_MeshVolume* SMDS_Mesh::AddVolume(const SMDS_MeshFace * f1,
1161                                       const SMDS_MeshFace * f2,
1162                                       const SMDS_MeshFace * f3,
1163                                       const SMDS_MeshFace * f4)
1164 {
1165   if (!hasConstructionFaces())
1166     return NULL;
1167   return AddVolumeWithID(f1,f2,f3,f4, myElementIDFactory->GetFreeID());
1168 }
1169
1170 ///////////////////////////////////////////////////////////////////////////////
1171 ///Create a new tetrahedron defined by its faces and add it to the mesh.
1172 ///@param ID The ID of the new volume
1173 ///@return The created tetrahedron
1174 ///////////////////////////////////////////////////////////////////////////////
1175
1176 SMDS_MeshVolume* SMDS_Mesh::AddVolumeWithID(const SMDS_MeshFace * f1,
1177                                             const SMDS_MeshFace * f2,
1178                                             const SMDS_MeshFace * f3,
1179                                             const SMDS_MeshFace * f4,
1180                                             int ID)
1181 {
1182   if (!hasConstructionFaces())
1183     return NULL;
1184   if ( !f1 || !f2 || !f3 || !f4) return 0;
1185   if ( NbVolumes() % CHECKMEMORY_INTERVAL == 0 ) CheckMemory();
1186   SMDS_MeshVolume * volume = new SMDS_VolumeOfFaces(f1,f2,f3,f4);
1187   adjustmyCellsCapacity(ID);
1188   myCells[ID] = volume;
1189   myInfo.myNbTetras++;
1190
1191   if (!registerElement(ID, volume)) {
1192     registerElement(myElementIDFactory->GetFreeID(), volume);
1193     //RemoveElement(volume, false);
1194     //volume = NULL;
1195   }
1196   return volume;
1197 }
1198
1199 ///////////////////////////////////////////////////////////////////////////////
1200 ///Create a new pyramid defined by its faces and add it to the mesh.
1201 ///@return The created pyramid
1202 ///////////////////////////////////////////////////////////////////////////////
1203
1204 SMDS_MeshVolume* SMDS_Mesh::AddVolume(const SMDS_MeshFace * f1,
1205                                       const SMDS_MeshFace * f2,
1206                                       const SMDS_MeshFace * f3,
1207                                       const SMDS_MeshFace * f4,
1208                                       const SMDS_MeshFace * f5)
1209 {
1210  if (!hasConstructionFaces())
1211     return NULL;
1212   return AddVolumeWithID(f1,f2,f3,f4,f5, myElementIDFactory->GetFreeID());
1213 }
1214
1215 ///////////////////////////////////////////////////////////////////////////////
1216 ///Create a new pyramid defined by its faces and add it to the mesh.
1217 ///@param ID The ID of the new volume
1218 ///@return The created pyramid
1219 ///////////////////////////////////////////////////////////////////////////////
1220
1221 SMDS_MeshVolume* SMDS_Mesh::AddVolumeWithID(const SMDS_MeshFace * f1,
1222                                             const SMDS_MeshFace * f2,
1223                                             const SMDS_MeshFace * f3,
1224                                             const SMDS_MeshFace * f4,
1225                                             const SMDS_MeshFace * f5,
1226                                             int ID)
1227 {
1228   if (!hasConstructionFaces())
1229     return NULL;
1230   if ( !f1 || !f2 || !f3 || !f4 || !f5) return 0;
1231   if ( NbVolumes() % CHECKMEMORY_INTERVAL == 0 ) CheckMemory();
1232   SMDS_MeshVolume * volume = new SMDS_VolumeOfFaces(f1,f2,f3,f4,f5);
1233   adjustmyCellsCapacity(ID);
1234   myCells[ID] = volume;
1235   myInfo.myNbPyramids++;
1236
1237   if (!registerElement(ID, volume)) {
1238     registerElement(myElementIDFactory->GetFreeID(), volume);
1239     //RemoveElement(volume, false);
1240     //volume = NULL;
1241   }
1242   return volume;
1243 }
1244
1245 ///////////////////////////////////////////////////////////////////////////////
1246 ///Create a new prism defined by its faces and add it to the mesh.
1247 ///@return The created prism
1248 ///////////////////////////////////////////////////////////////////////////////
1249
1250 SMDS_MeshVolume* SMDS_Mesh::AddVolume(const SMDS_MeshFace * f1,
1251                                       const SMDS_MeshFace * f2,
1252                                       const SMDS_MeshFace * f3,
1253                                       const SMDS_MeshFace * f4,
1254                                       const SMDS_MeshFace * f5,
1255                                       const SMDS_MeshFace * f6)
1256 {
1257  if (!hasConstructionFaces())
1258     return NULL;
1259   return AddVolumeWithID(f1,f2,f3,f4,f5,f6, myElementIDFactory->GetFreeID());
1260 }
1261
1262 ///////////////////////////////////////////////////////////////////////////////
1263 ///Create a new prism defined by its faces and add it to the mesh.
1264 ///@param ID The ID of the new volume
1265 ///@return The created prism
1266 ///////////////////////////////////////////////////////////////////////////////
1267
1268 SMDS_MeshVolume* SMDS_Mesh::AddVolumeWithID(const SMDS_MeshFace * f1,
1269                                             const SMDS_MeshFace * f2,
1270                                             const SMDS_MeshFace * f3,
1271                                             const SMDS_MeshFace * f4,
1272                                             const SMDS_MeshFace * f5,
1273                                             const SMDS_MeshFace * f6,
1274                                             int ID)
1275 {
1276   if (!hasConstructionFaces())
1277     return NULL;
1278   if ( !f1 || !f2 || !f3 || !f4 || !f5 || !f6) return 0;
1279   if ( NbVolumes() % CHECKMEMORY_INTERVAL == 0 ) CheckMemory();
1280   SMDS_MeshVolume * volume = new SMDS_VolumeOfFaces(f1,f2,f3,f4,f5,f6);
1281   adjustmyCellsCapacity(ID);
1282   myCells[ID] = volume;
1283   myInfo.myNbPrisms++;
1284
1285   if (!registerElement(ID, volume)) {
1286     registerElement(myElementIDFactory->GetFreeID(), volume);
1287     //RemoveElement(volume, false);
1288     //volume = NULL;
1289   }
1290   return volume;
1291 }
1292
1293 ///////////////////////////////////////////////////////////////////////////////
1294 /// Add a polygon defined by its nodes IDs
1295 ///////////////////////////////////////////////////////////////////////////////
1296
1297 SMDS_MeshFace* SMDS_Mesh::AddPolygonalFaceWithID (const vector<int> & nodes_ids,
1298                                                   const int           ID)
1299 {
1300   int nbNodes = nodes_ids.size();
1301   vector<const SMDS_MeshNode*> nodes (nbNodes);
1302   for (int i = 0; i < nbNodes; i++) {
1303     nodes[i] = (SMDS_MeshNode *)myNodeIDFactory->MeshElement(nodes_ids[i]);
1304     if (!nodes[i]) return NULL;
1305   }
1306   return SMDS_Mesh::AddPolygonalFaceWithID(nodes, ID);
1307 }
1308
1309 ///////////////////////////////////////////////////////////////////////////////
1310 /// Add a polygon defined by its nodes
1311 ///////////////////////////////////////////////////////////////////////////////
1312
1313 SMDS_MeshFace*
1314 SMDS_Mesh::AddPolygonalFaceWithID (const vector<const SMDS_MeshNode*> & nodes,
1315                                    const int                            ID)
1316 {
1317   SMDS_MeshFace * face;
1318
1319   if ( NbFaces() % CHECKMEMORY_INTERVAL == 0 ) CheckMemory();
1320   if (hasConstructionEdges())
1321   {
1322     return NULL;
1323   }
1324   else
1325   {
1326     myNodeIds.resize( nodes.size() );
1327     for ( size_t i = 0; i < nodes.size(); ++i )
1328       myNodeIds[i] = nodes[i]->getVtkId();
1329
1330     SMDS_VtkFace *facevtk = myFacePool->getNew();
1331     facevtk->initPoly(myNodeIds, this);
1332     if (!this->registerElement(ID,facevtk))
1333     {
1334       this->myGrid->GetCellTypesArray()->SetValue(facevtk->getVtkId(), VTK_EMPTY_CELL);
1335       myFacePool->destroy(facevtk);
1336       return 0;
1337     }
1338     face = facevtk;
1339
1340     adjustmyCellsCapacity(ID);
1341     myCells[ID] = face;
1342     myInfo.myNbPolygons++;
1343   }
1344
1345   return face;
1346 }
1347
1348 ///////////////////////////////////////////////////////////////////////////////
1349 /// Add a polygon defined by its nodes.
1350 /// An ID is automatically affected to the created face.
1351 ///////////////////////////////////////////////////////////////////////////////
1352
1353 SMDS_MeshFace* SMDS_Mesh::AddPolygonalFace (const vector<const SMDS_MeshNode*> & nodes)
1354 {
1355   return SMDS_Mesh::AddPolygonalFaceWithID(nodes, myElementIDFactory->GetFreeID());
1356 }
1357
1358 ///////////////////////////////////////////////////////////////////////////////
1359 /// Add a quadratic polygon defined by its nodes IDs
1360 ///////////////////////////////////////////////////////////////////////////////
1361
1362 SMDS_MeshFace* SMDS_Mesh::AddQuadPolygonalFaceWithID (const vector<int> & nodes_ids,
1363                                                       const int           ID)
1364 {
1365   vector<const SMDS_MeshNode*> nodes( nodes_ids.size() );
1366   for ( size_t i = 0; i < nodes.size(); i++) {
1367     nodes[i] = (SMDS_MeshNode *)myNodeIDFactory->MeshElement(nodes_ids[i]);
1368     if (!nodes[i]) return NULL;
1369   }
1370   return SMDS_Mesh::AddQuadPolygonalFaceWithID(nodes, ID);
1371 }
1372
1373 ///////////////////////////////////////////////////////////////////////////////
1374 /// Add a quadratic polygon defined by its nodes
1375 ///////////////////////////////////////////////////////////////////////////////
1376
1377 SMDS_MeshFace*
1378 SMDS_Mesh::AddQuadPolygonalFaceWithID (const vector<const SMDS_MeshNode*> & nodes,
1379                                        const int                            ID)
1380 {
1381   SMDS_MeshFace * face;
1382
1383   if ( NbFaces() % CHECKMEMORY_INTERVAL == 0 ) CheckMemory();
1384   if (hasConstructionEdges())
1385   {
1386     return NULL;
1387   }
1388   else
1389   {
1390     myNodeIds.resize( nodes.size() );
1391     for ( size_t i = 0; i < nodes.size(); ++i )
1392       myNodeIds[i] = nodes[i]->getVtkId();
1393
1394     SMDS_VtkFace *facevtk = myFacePool->getNew();
1395     facevtk->initQuadPoly(myNodeIds, this);
1396     if (!this->registerElement(ID,facevtk))
1397     {
1398       this->myGrid->GetCellTypesArray()->SetValue(facevtk->getVtkId(), VTK_EMPTY_CELL);
1399       myFacePool->destroy(facevtk);
1400       return 0;
1401     }
1402     face = facevtk;
1403     adjustmyCellsCapacity(ID);
1404     myCells[ID] = face;
1405     myInfo.myNbQuadPolygons++;
1406   }
1407   return face;
1408 }
1409
1410 ///////////////////////////////////////////////////////////////////////////////
1411 /// Add a quadratic polygon defined by its nodes.
1412 /// An ID is automatically affected to the created face.
1413 ///////////////////////////////////////////////////////////////////////////////
1414
1415 SMDS_MeshFace* SMDS_Mesh::AddQuadPolygonalFace (const vector<const SMDS_MeshNode*> & nodes)
1416 {
1417   return SMDS_Mesh::AddQuadPolygonalFaceWithID(nodes, myElementIDFactory->GetFreeID());
1418 }
1419
1420 ///////////////////////////////////////////////////////////////////////////////
1421 /// Create a new polyhedral volume and add it to the mesh.
1422 /// @param ID The ID of the new volume
1423 /// @return The created volume or NULL if an element with this ID already exists
1424 /// or if input nodes are not found.
1425 ///////////////////////////////////////////////////////////////////////////////
1426
1427 SMDS_MeshVolume * SMDS_Mesh::AddPolyhedralVolumeWithID
1428                              (const vector<int> & nodes_ids,
1429                               const vector<int> & quantities,
1430                               const int           ID)
1431 {
1432   int nbNodes = nodes_ids.size();
1433   vector<const SMDS_MeshNode*> nodes (nbNodes);
1434   for (int i = 0; i < nbNodes; i++) {
1435     nodes[i] = (SMDS_MeshNode *)myNodeIDFactory->MeshElement(nodes_ids[i]);
1436     if (!nodes[i]) return NULL;
1437   }
1438   return SMDS_Mesh::AddPolyhedralVolumeWithID(nodes, quantities, ID);
1439 }
1440
1441 ///////////////////////////////////////////////////////////////////////////////
1442 /// Create a new polyhedral volume and add it to the mesh.
1443 /// @param ID The ID of the new volume
1444 /// @return The created  volume
1445 ///////////////////////////////////////////////////////////////////////////////
1446
1447 SMDS_MeshVolume*
1448 SMDS_Mesh::AddPolyhedralVolumeWithID (const vector<const SMDS_MeshNode*>& nodes,
1449                                       const vector<int>                 & quantities,
1450                                       const int                           ID)
1451 {
1452   SMDS_MeshVolume* volume = 0;
1453   if ( nodes.empty() || quantities.empty() )
1454     return NULL;
1455   if ( NbVolumes() % CHECKMEMORY_INTERVAL == 0 ) CheckMemory();
1456   if (hasConstructionFaces())
1457   {
1458     return NULL;
1459   }
1460   else if (hasConstructionEdges())
1461   {
1462     return NULL;
1463   }
1464   else
1465   {
1466     //#ifdef VTK_HAVE_POLYHEDRON
1467     myNodeIds.resize( nodes.size() );
1468     for ( size_t i = 0; i < nodes.size(); ++i )
1469       myNodeIds[i] = nodes[i]->getVtkId();
1470
1471     SMDS_VtkVolume *volvtk = myVolumePool->getNew();
1472     volvtk->initPoly(myNodeIds, quantities, this);
1473     if (!this->registerElement(ID, volvtk))
1474     {
1475       this->myGrid->GetCellTypesArray()->SetValue(volvtk->getVtkId(), VTK_EMPTY_CELL);
1476       myVolumePool->destroy(volvtk);
1477       return 0;
1478     }
1479     volume = volvtk;
1480     //#else
1481     //      for ( int i = 0; i < nodes.size(); ++i )
1482     //      if ( !nodes[ i ] ) return 0;
1483     //      volume = new SMDS_PolyhedralVolumeOfNodes(nodes, quantities);
1484     //#endif
1485     adjustmyCellsCapacity(ID);
1486     myCells[ID] = volume;
1487     myInfo.myNbPolyhedrons++;
1488   }
1489
1490   //#ifndef VTK_HAVE_POLYHEDRON
1491   //  if (!registerElement(ID, volume))
1492   //    {
1493   //      registerElement(myElementIDFactory->GetFreeID(), volume);
1494   //      //RemoveElement(volume, false);
1495   //      //volume = NULL;
1496   //    }
1497   //#endif
1498   return volume;
1499 }
1500
1501 ///////////////////////////////////////////////////////////////////////////////
1502 /// Create a new polyhedral volume and add it to the mesh.
1503 /// @return The created  volume
1504 ///////////////////////////////////////////////////////////////////////////////
1505
1506 SMDS_MeshVolume* SMDS_Mesh::AddPolyhedralVolume
1507                             (const vector<const SMDS_MeshNode*> & nodes,
1508                              const vector<int>                  & quantities)
1509 {
1510   int ID = myElementIDFactory->GetFreeID();
1511   SMDS_MeshVolume * v = SMDS_Mesh::AddPolyhedralVolumeWithID(nodes, quantities, ID);
1512   if (v == NULL) myElementIDFactory->ReleaseID(ID);
1513   return v;
1514 }
1515
1516 SMDS_MeshVolume* SMDS_Mesh::AddVolumeFromVtkIds(const std::vector<vtkIdType>& vtkNodeIds)
1517 {
1518   int ID = myElementIDFactory->GetFreeID();
1519   SMDS_MeshVolume * v = SMDS_Mesh::AddVolumeFromVtkIdsWithID(vtkNodeIds, ID);
1520   if (v == NULL) myElementIDFactory->ReleaseID(ID);
1521   return v;
1522 }
1523
1524 SMDS_MeshVolume* SMDS_Mesh::AddVolumeFromVtkIdsWithID(const std::vector<vtkIdType>& vtkNodeIds, const int ID)
1525 {
1526   SMDS_VtkVolume *volvtk = myVolumePool->getNew();
1527   volvtk->init(vtkNodeIds, this);
1528   if (!this->registerElement(ID,volvtk))
1529     {
1530       this->myGrid->GetCellTypesArray()->SetValue(volvtk->getVtkId(), VTK_EMPTY_CELL);
1531       myVolumePool->destroy(volvtk);
1532       return 0;
1533     }
1534   adjustmyCellsCapacity(ID);
1535   myCells[ID] = volvtk;
1536   vtkIdType aVtkType = volvtk->GetVtkType();
1537   switch (aVtkType)
1538   {
1539     case VTK_TETRA:
1540       myInfo.myNbTetras++;
1541       break;
1542     case VTK_PYRAMID:
1543       myInfo.myNbPyramids++;
1544       break;
1545     case VTK_WEDGE:
1546       myInfo.myNbPrisms++;
1547       break;
1548     case VTK_HEXAHEDRON:
1549       myInfo.myNbHexas++;
1550       break;
1551     case VTK_QUADRATIC_TETRA:
1552       myInfo.myNbQuadTetras++;
1553       break;
1554     case VTK_QUADRATIC_PYRAMID:
1555       myInfo.myNbQuadPyramids++;
1556       break;
1557     case VTK_QUADRATIC_WEDGE:
1558       myInfo.myNbQuadPrisms++;
1559       break;
1560     case VTK_QUADRATIC_HEXAHEDRON:
1561       myInfo.myNbQuadHexas++;
1562       break;
1563 //#ifdef VTK_HAVE_POLYHEDRON
1564     case VTK_POLYHEDRON:
1565       myInfo.myNbPolyhedrons++;
1566       break;
1567 //#endif
1568     default:
1569       myInfo.myNbPolyhedrons++;
1570       break;
1571   }
1572   return volvtk;
1573 }
1574
1575 SMDS_MeshFace* SMDS_Mesh::AddFaceFromVtkIds(const std::vector<vtkIdType>& vtkNodeIds)
1576 {
1577   int ID = myElementIDFactory->GetFreeID();
1578   SMDS_MeshFace * f = SMDS_Mesh::AddFaceFromVtkIdsWithID(vtkNodeIds, ID);
1579   if (f == NULL) myElementIDFactory->ReleaseID(ID);
1580   return f;
1581 }
1582
1583 SMDS_MeshFace* SMDS_Mesh::AddFaceFromVtkIdsWithID(const std::vector<vtkIdType>& vtkNodeIds, const int ID)
1584 {
1585   SMDS_VtkFace *facevtk = myFacePool->getNew();
1586   facevtk->init(vtkNodeIds, this);
1587   if (!this->registerElement(ID,facevtk))
1588     {
1589       this->myGrid->GetCellTypesArray()->SetValue(facevtk->getVtkId(), VTK_EMPTY_CELL);
1590       myFacePool->destroy(facevtk);
1591       return 0;
1592     }
1593   adjustmyCellsCapacity(ID);
1594   myCells[ID] = facevtk;
1595   vtkIdType aVtkType = facevtk->GetVtkType();
1596   switch (aVtkType)
1597   {
1598     case VTK_TRIANGLE:
1599       myInfo.myNbTriangles++;
1600       break;
1601     case VTK_QUAD:
1602       myInfo.myNbQuadrangles++;
1603       break;
1604     case VTK_QUADRATIC_TRIANGLE:
1605       myInfo.myNbQuadTriangles++;
1606       break;
1607     case VTK_QUADRATIC_QUAD:
1608       myInfo.myNbQuadQuadrangles++;
1609       break;
1610     case VTK_BIQUADRATIC_QUAD:
1611       myInfo.myNbBiQuadQuadrangles++;
1612       break;
1613     case VTK_BIQUADRATIC_TRIANGLE:
1614       myInfo.myNbBiQuadTriangles++;
1615       break;
1616     case VTK_POLYGON:
1617       myInfo.myNbPolygons++;
1618       break;
1619      default:
1620       myInfo.myNbPolygons++;
1621   }
1622   return facevtk;
1623 }
1624
1625 ///////////////////////////////////////////////////////////////////////////////
1626 /// Registers element with the given ID, maintains inverse connections
1627 ///////////////////////////////////////////////////////////////////////////////
1628 bool SMDS_Mesh::registerElement(int ID, SMDS_MeshElement* element)
1629 {
1630   if ((ID >=0) && (ID < (int)myCells.size()) && myCells[ID]) // --- already bound
1631   {
1632     MESSAGE(" ------------------ already bound "<< ID << " " << myCells[ID]->getVtkId());
1633     return false;
1634   }
1635
1636   element->myID = ID;
1637   element->myMeshId = myMeshId;
1638
1639   SMDS_MeshCell *cell = dynamic_cast<SMDS_MeshCell*>(element);
1640   MYASSERT(cell);
1641   int vtkId = cell->getVtkId();  
1642   if (vtkId == -1)
1643     vtkId = myElementIDFactory->SetInVtkGrid(element);
1644
1645   if (vtkId >= (int)myCellIdVtkToSmds.size()) // --- resize local vector
1646   {
1647     myCellIdVtkToSmds.resize(vtkId + SMDS_Mesh::chunkSize, -1);
1648   }
1649   myCellIdVtkToSmds[vtkId] = ID;
1650
1651   myElementIDFactory->updateMinMax(ID);
1652   return true;
1653 }
1654
1655 //=======================================================================
1656 //function : MoveNode
1657 //purpose  : 
1658 //=======================================================================
1659
1660 void SMDS_Mesh::MoveNode(const SMDS_MeshNode *n, double x, double y, double z)
1661 {
1662   SMDS_MeshNode * node=const_cast<SMDS_MeshNode*>(n);
1663   node->setXYZ(x,y,z);
1664 }
1665
1666 ///////////////////////////////////////////////////////////////////////////////
1667 /// Return the node whose SMDS ID is 'ID'.
1668 ///////////////////////////////////////////////////////////////////////////////
1669 const SMDS_MeshNode * SMDS_Mesh::FindNode(int ID) const
1670 {
1671   if (ID < 1 || ID >= (int)myNodes.size())
1672   {
1673     return 0;
1674   }
1675   return (const SMDS_MeshNode *)myNodes[ID];
1676 }
1677
1678 ///////////////////////////////////////////////////////////////////////////////
1679 /// Return the node whose VTK ID is 'vtkId'.
1680 ///////////////////////////////////////////////////////////////////////////////
1681 const SMDS_MeshNode * SMDS_Mesh::FindNodeVtk(int vtkId) const
1682 {
1683   // TODO if needed use mesh->nodeIdFromVtkToSmds
1684   if ( vtkId < 0 || vtkId+1 >= (int) myNodes.size() )
1685   {
1686     MESSAGE("------------------------------------------------------------------------- ");
1687     MESSAGE("---------------------------- bad VTK ID " << vtkId << " " << myNodes.size());
1688     MESSAGE("------------------------------------------------------------------------- ");
1689     return 0;
1690   }
1691   return (const SMDS_MeshNode *)myNodes[vtkId+1];
1692 }
1693
1694 ///////////////////////////////////////////////////////////////////////////////
1695 ///Create a triangle and add it to the current mesh. This method do not bind an
1696 ///ID to the create triangle.
1697 ///////////////////////////////////////////////////////////////////////////////
1698 SMDS_MeshFace * SMDS_Mesh::createTriangle(const SMDS_MeshNode * node1,
1699                                           const SMDS_MeshNode * node2,
1700                                           const SMDS_MeshNode * node3,
1701                                           int ID)
1702 {
1703   if ( !node1 || !node2 || !node3) return 0;
1704   if ( NbFaces() % CHECKMEMORY_INTERVAL == 0 ) CheckMemory();
1705   if(hasConstructionEdges())
1706   {
1707     SMDS_MeshEdge *edge1, *edge2, *edge3;
1708     edge1=FindEdgeOrCreate(node1,node2);
1709     edge2=FindEdgeOrCreate(node2,node3);
1710     edge3=FindEdgeOrCreate(node3,node1);
1711
1712     //int ID = myElementIDFactory->GetFreeID(); // -PR- voir si on range cet element
1713     SMDS_MeshFace * face = new SMDS_FaceOfEdges(edge1,edge2,edge3);
1714     adjustmyCellsCapacity(ID);
1715     myCells[ID] = face;
1716     myInfo.myNbTriangles++;
1717     return face;
1718   }
1719   else
1720   {
1721     // --- retrieve nodes ID
1722     myNodeIds.resize(3);
1723     myNodeIds[0] = node1->getVtkId();
1724     myNodeIds[1] = node2->getVtkId();
1725     myNodeIds[2] = node3->getVtkId();
1726
1727     SMDS_MeshFace * face = 0;
1728     SMDS_VtkFace *facevtk = myFacePool->getNew();
1729     facevtk->init(myNodeIds, this); // put in vtkUnstructuredGrid
1730     if (!this->registerElement(ID,facevtk))
1731     {
1732       this->myGrid->GetCellTypesArray()->SetValue(facevtk->getVtkId(), VTK_EMPTY_CELL);
1733       myFacePool->destroy(facevtk);
1734       return 0;
1735     }
1736     face = facevtk;
1737     adjustmyCellsCapacity(ID);
1738     myCells[ID] = face;
1739     myInfo.myNbTriangles++;
1740     return face;
1741   }
1742 }
1743
1744 ///////////////////////////////////////////////////////////////////////////////
1745 ///Create a quadrangle and add it to the current mesh. This methode do not bind
1746 ///a ID to the create triangle.
1747 ///////////////////////////////////////////////////////////////////////////////
1748 SMDS_MeshFace * SMDS_Mesh::createQuadrangle(const SMDS_MeshNode * node1,
1749                                             const SMDS_MeshNode * node2,
1750                                             const SMDS_MeshNode * node3,
1751                                             const SMDS_MeshNode * node4,
1752                                             int ID)
1753 {
1754   if ( !node1 || !node2 || !node3 || !node4 ) return 0;
1755   if ( NbFaces() % CHECKMEMORY_INTERVAL == 0 ) CheckMemory();
1756   if(hasConstructionEdges())
1757   {
1758     SMDS_MeshEdge *edge1, *edge2, *edge3, *edge4;
1759     edge1=FindEdgeOrCreate(node1,node2);
1760     edge2=FindEdgeOrCreate(node2,node3);
1761     edge3=FindEdgeOrCreate(node3,node4);
1762     edge4=FindEdgeOrCreate(node4,node1);
1763
1764     SMDS_MeshFace * face = new SMDS_FaceOfEdges(edge1,edge2,edge3,edge4);
1765     adjustmyCellsCapacity(ID);
1766     myCells[ID] = face;
1767     myInfo.myNbQuadrangles++;
1768     return face;
1769   }
1770   else
1771   {
1772     // --- retrieve nodes ID
1773     myNodeIds.resize(4);
1774     myNodeIds[0] = node1->getVtkId();
1775     myNodeIds[1] = node2->getVtkId();
1776     myNodeIds[2] = node3->getVtkId();
1777     myNodeIds[3] = node4->getVtkId();
1778
1779     SMDS_MeshFace * face = 0;
1780     SMDS_VtkFace *facevtk = myFacePool->getNew();
1781     facevtk->init(myNodeIds, this);
1782     if (!this->registerElement(ID,facevtk))
1783     {
1784       this->myGrid->GetCellTypesArray()->SetValue(facevtk->getVtkId(), VTK_EMPTY_CELL);
1785       myFacePool->destroy(facevtk);
1786       return 0;
1787     }
1788     face = facevtk;
1789     adjustmyCellsCapacity(ID);
1790     myCells[ID] = face;
1791     myInfo.myNbQuadrangles++;
1792     return face;
1793   }
1794 }
1795
1796 ///////////////////////////////////////////////////////////////////////////////
1797 /// Remove a node and all the elements which own this node
1798 ///////////////////////////////////////////////////////////////////////////////
1799
1800 void SMDS_Mesh::RemoveNode(const SMDS_MeshNode * node)
1801 {
1802   RemoveElement(node, true);
1803 }
1804
1805 ///////////////////////////////////////////////////////////////////////////////
1806 /// Remove an edge and all the elements which own this edge
1807 ///////////////////////////////////////////////////////////////////////////////
1808
1809 void SMDS_Mesh::Remove0DElement(const SMDS_Mesh0DElement * elem0d)
1810 {
1811   RemoveElement(elem0d,true);
1812 }
1813
1814 ///////////////////////////////////////////////////////////////////////////////
1815 /// Remove an edge and all the elements which own this edge
1816 ///////////////////////////////////////////////////////////////////////////////
1817
1818 void SMDS_Mesh::RemoveEdge(const SMDS_MeshEdge * edge)
1819 {
1820   RemoveElement(edge,true);
1821 }
1822
1823 ///////////////////////////////////////////////////////////////////////////////
1824 /// Remove an face and all the elements which own this face
1825 ///////////////////////////////////////////////////////////////////////////////
1826
1827 void SMDS_Mesh::RemoveFace(const SMDS_MeshFace * face)
1828 {
1829   RemoveElement(face, true);
1830 }
1831
1832 ///////////////////////////////////////////////////////////////////////////////
1833 /// Remove a volume
1834 ///////////////////////////////////////////////////////////////////////////////
1835
1836 void SMDS_Mesh::RemoveVolume(const SMDS_MeshVolume * volume)
1837 {
1838   RemoveElement(volume, true);
1839 }
1840
1841 //=======================================================================
1842 //function : RemoveFromParent
1843 //purpose  :
1844 //=======================================================================
1845
1846 bool SMDS_Mesh::RemoveFromParent()
1847 {
1848   if (myParent==NULL) return false;
1849   else return (myParent->RemoveSubMesh(this));
1850 }
1851
1852 //=======================================================================
1853 //function : RemoveSubMesh
1854 //purpose  :
1855 //=======================================================================
1856
1857 bool SMDS_Mesh::RemoveSubMesh(const SMDS_Mesh * aMesh)
1858 {
1859   bool found = false;
1860
1861   list<SMDS_Mesh *>::iterator itmsh=myChildren.begin();
1862   for (; itmsh!=myChildren.end() && !found; itmsh++)
1863   {
1864     SMDS_Mesh * submesh = *itmsh;
1865     if (submesh == aMesh)
1866     {
1867       found = true;
1868       myChildren.erase(itmsh);
1869     }
1870   }
1871
1872   return found;
1873 }
1874
1875 //=======================================================================
1876 //function : ChangeElementNodes
1877 //purpose  :
1878 //=======================================================================
1879
1880 bool SMDS_Mesh::ChangeElementNodes(const SMDS_MeshElement * element,
1881                                    const SMDS_MeshNode    * nodes[],
1882                                    const int                nbnodes)
1883 {
1884   // keep current nodes of elem
1885   set<const SMDS_MeshNode*> oldNodes( element->begin_nodes(), element->end_nodes() );
1886
1887   // change nodes
1888   bool Ok = false;
1889   SMDS_MeshCell* cell = dynamic_cast<SMDS_MeshCell*>((SMDS_MeshElement*) element);
1890   if (cell)
1891   {
1892     Ok = cell->vtkOrder(nodes, nbnodes);
1893     Ok = cell->ChangeNodes(nodes, nbnodes);
1894   }
1895
1896   if ( Ok ) { // update InverseElements
1897
1898     set<const SMDS_MeshNode*>::iterator it;
1899
1900     // AddInverseElement to new nodes
1901     for ( int i = 0; i < nbnodes; i++ ) {
1902       it = oldNodes.find( nodes[i] );
1903       if ( it == oldNodes.end() )
1904         // new node
1905         const_cast<SMDS_MeshNode*>( nodes[i] )->AddInverseElement( cell );
1906       else
1907         // remove from oldNodes a node that remains in elem
1908         oldNodes.erase( it );
1909     }
1910     // RemoveInverseElement from the nodes removed from elem
1911     for ( it = oldNodes.begin(); it != oldNodes.end(); it++ )
1912     {
1913       SMDS_MeshNode * n = const_cast<SMDS_MeshNode *>( *it );
1914       n->RemoveInverseElement( cell );
1915     }
1916   }
1917
1918   return Ok;
1919 }
1920
1921 //=======================================================================
1922 //function : ChangePolyhedronNodes
1923 //purpose  : to change nodes of polyhedral volume
1924 //=======================================================================
1925 bool SMDS_Mesh::ChangePolyhedronNodes (const SMDS_MeshElement *            elem,
1926                                        const vector<const SMDS_MeshNode*>& nodes,
1927                                        const vector<int>                 & quantities)
1928 {
1929   if (elem->GetType() != SMDSAbs_Volume) {
1930     MESSAGE("WRONG ELEM TYPE");
1931     return false;
1932   }
1933
1934   const SMDS_VtkVolume* vol = dynamic_cast<const SMDS_VtkVolume*>(elem);
1935   if (!vol) {
1936     return false;
1937   }
1938
1939   // keep current nodes of elem
1940   set<const SMDS_MeshElement*> oldNodes;
1941   SMDS_ElemIteratorPtr itn = elem->nodesIterator();
1942   while (itn->more()) {
1943     oldNodes.insert(itn->next());
1944   }
1945
1946   // change nodes
1947   // TODO remove this function
1948   //bool Ok = const_cast<SMDS_VtkVolume*>(vol)->ChangeNodes(nodes, quantities);
1949   bool Ok = false;
1950   if (!Ok) {
1951     return false;
1952   }
1953
1954   // update InverseElements
1955
1956   // AddInverseElement to new nodes
1957   int nbnodes = nodes.size();
1958   set<const SMDS_MeshElement*>::iterator it;
1959   for (int i = 0; i < nbnodes; i++) {
1960     it = oldNodes.find(nodes[i]);
1961     if (it == oldNodes.end()) {
1962       // new node
1963       const_cast<SMDS_MeshNode*>(nodes[i])->AddInverseElement(elem);
1964     } else {
1965       // remove from oldNodes a node that remains in elem
1966       oldNodes.erase(it);
1967     }
1968   }
1969
1970   // RemoveInverseElement from the nodes removed from elem
1971   for (it = oldNodes.begin(); it != oldNodes.end(); it++) {
1972     SMDS_MeshNode * n = static_cast<SMDS_MeshNode *>
1973       (const_cast<SMDS_MeshElement *>( *it ));
1974     n->RemoveInverseElement(elem);
1975   }
1976
1977   return Ok;
1978 }
1979
1980
1981 //=======================================================================
1982 //function : Find0DElement
1983 //purpose  :
1984 //=======================================================================
1985 const SMDS_Mesh0DElement* SMDS_Mesh::Find0DElement(int idnode) const
1986 {
1987   const SMDS_MeshNode * node = FindNode(idnode);
1988   if(node == NULL) return NULL;
1989   return Find0DElement(node);
1990 }
1991
1992 const SMDS_Mesh0DElement* SMDS_Mesh::Find0DElement(const SMDS_MeshNode * node)
1993 {
1994   if (!node) return 0;
1995   const SMDS_Mesh0DElement* toReturn = NULL;
1996   SMDS_ElemIteratorPtr it1 = node->GetInverseElementIterator(SMDSAbs_0DElement);
1997   while (it1->more() && (toReturn == NULL)) {
1998     const SMDS_MeshElement* e = it1->next();
1999     if (e->NbNodes() == 1) {
2000       toReturn = static_cast<const SMDS_Mesh0DElement*>(e);
2001     }
2002   }
2003   return toReturn;
2004 }
2005
2006 //=======================================================================
2007 //function : FindBall
2008 //purpose  :
2009 //=======================================================================
2010
2011 const SMDS_BallElement* SMDS_Mesh::FindBall(int idnode) const
2012 {
2013   const SMDS_MeshNode * node = FindNode(idnode);
2014   if(node == NULL) return NULL;
2015   return FindBall(node);
2016 }
2017
2018 const SMDS_BallElement* SMDS_Mesh::FindBall(const SMDS_MeshNode * node)
2019 {
2020   if (!node) return 0;
2021   const SMDS_BallElement* toReturn = NULL;
2022   SMDS_ElemIteratorPtr it1 = node->GetInverseElementIterator(SMDSAbs_Ball);
2023   while (it1->more() && (toReturn == NULL)) {
2024     const SMDS_MeshElement* e = it1->next();
2025     if (e->GetGeomType() == SMDSGeom_BALL)
2026       toReturn = static_cast<const SMDS_BallElement*>(e);
2027   }
2028   return toReturn;
2029 }
2030
2031 //=======================================================================
2032 //function : Find0DElementOrCreate
2033 //purpose  :
2034 //=======================================================================
2035 //SMDS_Mesh0DElement* SMDS_Mesh::Find0DElementOrCreate(const SMDS_MeshNode * node)
2036 //{
2037 //  if (!node) return 0;
2038 //  SMDS_Mesh0DElement * toReturn = NULL;
2039 //  toReturn = const_cast<SMDS_Mesh0DElement*>(Find0DElement(node));
2040 //  if (toReturn == NULL) {
2041 //    //if (my0DElements.Extent() % CHECKMEMORY_INTERVAL == 0) CheckMemory();
2042 //    toReturn = new SMDS_Mesh0DElement(node);
2043 //    my0DElements.Add(toReturn);
2044 //    myInfo.myNb0DElements++;
2045 //  }
2046 //  return toReturn;
2047 //}
2048
2049
2050 //=======================================================================
2051 //function : FindEdge
2052 //purpose  :
2053 //=======================================================================
2054
2055 const SMDS_MeshEdge* SMDS_Mesh::FindEdge(int idnode1, int idnode2) const
2056 {
2057   const SMDS_MeshNode * node1=FindNode(idnode1);
2058   const SMDS_MeshNode * node2=FindNode(idnode2);
2059   if((node1==NULL)||(node2==NULL)) return NULL;
2060   return FindEdge(node1,node2);
2061 }
2062
2063 //#include "Profiler.h"
2064 const SMDS_MeshEdge* SMDS_Mesh::FindEdge(const SMDS_MeshNode * node1,
2065                                          const SMDS_MeshNode * node2)
2066 {
2067   if ( !node1 ) return 0;
2068   const SMDS_MeshEdge * toReturn=NULL;
2069   //PROFILER_Init();
2070   //PROFILER_Set();
2071   SMDS_ElemIteratorPtr it1=node1->GetInverseElementIterator(SMDSAbs_Edge);
2072   //PROFILER_Get(0);
2073   //PROFILER_Set();
2074   while(it1->more()) {
2075     const SMDS_MeshElement * e = it1->next();
2076     if ( e->NbNodes() == 2 && e->GetNodeIndex( node2 ) >= 0 ) {
2077       toReturn = static_cast<const SMDS_MeshEdge*>( e );
2078       break;
2079     }
2080   }
2081   //PROFILER_Get(1);
2082   return toReturn;
2083 }
2084
2085
2086 //=======================================================================
2087 //function : FindEdgeOrCreate
2088 //purpose  :
2089 //=======================================================================
2090
2091 SMDS_MeshEdge* SMDS_Mesh::FindEdgeOrCreate(const SMDS_MeshNode * node1,
2092                                            const SMDS_MeshNode * node2)
2093 {
2094   if ( !node1 || !node2) return 0;
2095   SMDS_MeshEdge * toReturn=NULL;
2096   toReturn=const_cast<SMDS_MeshEdge*>(FindEdge(node1,node2));
2097   if(toReturn==NULL) {
2098     if ( NbEdges() % CHECKMEMORY_INTERVAL == 0 ) CheckMemory();
2099     int ID = myElementIDFactory->GetFreeID(); // -PR- voir si on range cet element
2100     adjustmyCellsCapacity(ID);
2101     myNodeIds.resize(2);
2102     myNodeIds[0] = node1->getVtkId();
2103     myNodeIds[1] = node2->getVtkId();
2104
2105     SMDS_VtkEdge *edgevtk = myEdgePool->getNew();
2106     edgevtk->init(myNodeIds, this);
2107     if (!this->registerElement(ID,edgevtk))
2108     {
2109       this->myGrid->GetCellTypesArray()->SetValue(edgevtk->getVtkId(), VTK_EMPTY_CELL);
2110       myEdgePool->destroy(edgevtk);
2111       return 0;
2112     }
2113     toReturn = edgevtk;
2114     myCells[ID] = toReturn;
2115     myInfo.myNbEdges++;
2116   }
2117   return toReturn;
2118 }
2119
2120
2121 //=======================================================================
2122 //function : FindEdge
2123 //purpose  :
2124 //=======================================================================
2125
2126 const SMDS_MeshEdge* SMDS_Mesh::FindEdge(int idnode1, int idnode2,
2127                                          int idnode3) const
2128 {
2129   const SMDS_MeshNode * node1=FindNode(idnode1);
2130   const SMDS_MeshNode * node2=FindNode(idnode2);
2131   const SMDS_MeshNode * node3=FindNode(idnode3);
2132   return FindEdge(node1,node2,node3);
2133 }
2134
2135 const SMDS_MeshEdge* SMDS_Mesh::FindEdge(const SMDS_MeshNode * node1,
2136                                          const SMDS_MeshNode * node2,
2137                                          const SMDS_MeshNode * node3)
2138 {
2139   if ( !node1 ) return 0;
2140   SMDS_ElemIteratorPtr it1 = node1->GetInverseElementIterator(SMDSAbs_Edge);
2141   while(it1->more()) {
2142     const SMDS_MeshElement * e = it1->next();
2143     if ( e->NbNodes() == 3 ) {
2144       SMDS_ElemIteratorPtr it2 = e->nodesIterator();
2145       while(it2->more()) {
2146         const SMDS_MeshElement* n = it2->next();
2147         if( n!=node1 &&
2148             n!=node2 &&
2149             n!=node3 )
2150         {
2151           e = 0;
2152           break;
2153         }
2154       }
2155       if ( e )
2156         return static_cast<const SMDS_MeshEdge *> (e);
2157     }
2158   }
2159   return 0;
2160 }
2161
2162
2163 //=======================================================================
2164 //function : FindFace
2165 //purpose  :
2166 //=======================================================================
2167
2168 const SMDS_MeshFace* SMDS_Mesh::FindFace(int idnode1, int idnode2,
2169         int idnode3) const
2170 {
2171   const SMDS_MeshNode * node1=FindNode(idnode1);
2172   const SMDS_MeshNode * node2=FindNode(idnode2);
2173   const SMDS_MeshNode * node3=FindNode(idnode3);
2174   return FindFace(node1, node2, node3);
2175 }
2176
2177 const SMDS_MeshFace* SMDS_Mesh::FindFace(const SMDS_MeshNode *node1,
2178                                          const SMDS_MeshNode *node2,
2179                                          const SMDS_MeshNode *node3)
2180 {
2181   if ( !node1 ) return 0;
2182   SMDS_ElemIteratorPtr it1 = node1->GetInverseElementIterator(SMDSAbs_Face);
2183   while(it1->more()) {
2184     const SMDS_MeshElement * e = it1->next();
2185     if ( e->NbNodes() == 3 ) {
2186       SMDS_ElemIteratorPtr it2 = e->nodesIterator();
2187       while(it2->more()) {
2188         const SMDS_MeshElement* n = it2->next();
2189         if( n!=node1 &&
2190             n!=node2 &&
2191             n!=node3 )
2192         {
2193           e = 0;
2194           break;
2195         }
2196       }
2197       if ( e )
2198         return static_cast<const SMDS_MeshFace *> (e);
2199     }
2200   }
2201   return 0;
2202 }
2203
2204 SMDS_MeshFace* SMDS_Mesh::FindFaceOrCreate(const SMDS_MeshNode *node1,
2205                                            const SMDS_MeshNode *node2,
2206                                            const SMDS_MeshNode *node3)
2207 {
2208   SMDS_MeshFace * toReturn=NULL;
2209   toReturn = const_cast<SMDS_MeshFace*>(FindFace(node1,node2,node3));
2210   if(toReturn==NULL) {
2211     int ID = myElementIDFactory->GetFreeID();
2212     toReturn = createTriangle(node1,node2,node3, ID);
2213   }
2214   return toReturn;
2215 }
2216
2217
2218 //=======================================================================
2219 //function : FindFace
2220 //purpose  :
2221 //=======================================================================
2222
2223 const SMDS_MeshFace* SMDS_Mesh::FindFace(int idnode1, int idnode2,
2224                                          int idnode3, int idnode4) const
2225 {
2226   const SMDS_MeshNode * node1=FindNode(idnode1);
2227   const SMDS_MeshNode * node2=FindNode(idnode2);
2228   const SMDS_MeshNode * node3=FindNode(idnode3);
2229   const SMDS_MeshNode * node4=FindNode(idnode4);
2230   return FindFace(node1, node2, node3, node4);
2231 }
2232
2233 const SMDS_MeshFace* SMDS_Mesh::FindFace(const SMDS_MeshNode *node1,
2234                                          const SMDS_MeshNode *node2,
2235                                          const SMDS_MeshNode *node3,
2236                                          const SMDS_MeshNode *node4)
2237 {
2238   if ( !node1 ) return 0;
2239   SMDS_ElemIteratorPtr it1 = node1->GetInverseElementIterator(SMDSAbs_Face);
2240   while(it1->more()) {
2241     const SMDS_MeshElement * e = it1->next();
2242     if ( e->NbNodes() == 4 ) {
2243       SMDS_ElemIteratorPtr it2 = e->nodesIterator();
2244       while(it2->more()) {
2245         const SMDS_MeshElement* n = it2->next();
2246         if( n!=node1 &&
2247             n!=node2 &&
2248             n!=node3 &&
2249             n!=node4 )
2250         {
2251           e = 0;
2252           break;
2253         }
2254       }
2255       if ( e )
2256         return static_cast<const SMDS_MeshFace *> (e);
2257     }
2258   }
2259   return 0;
2260 }
2261
2262 SMDS_MeshFace* SMDS_Mesh::FindFaceOrCreate(const SMDS_MeshNode *node1,
2263                                            const SMDS_MeshNode *node2,
2264                                            const SMDS_MeshNode *node3,
2265                                            const SMDS_MeshNode *node4)
2266 {
2267   SMDS_MeshFace * toReturn=NULL;
2268   toReturn=const_cast<SMDS_MeshFace*>(FindFace(node1,node2,node3,node4));
2269   if(toReturn==NULL) {
2270     int ID = myElementIDFactory->GetFreeID();
2271     toReturn=createQuadrangle(node1,node2,node3,node4,ID);
2272   }
2273   return toReturn;
2274 }
2275
2276
2277 //=======================================================================
2278 //function : FindFace
2279 //purpose  :quadratic triangle
2280 //=======================================================================
2281
2282 const SMDS_MeshFace* SMDS_Mesh::FindFace(int idnode1, int idnode2,
2283                                          int idnode3, int idnode4,
2284                                          int idnode5, int idnode6) const
2285 {
2286   const SMDS_MeshNode * node1 = FindNode(idnode1);
2287   const SMDS_MeshNode * node2 = FindNode(idnode2);
2288   const SMDS_MeshNode * node3 = FindNode(idnode3);
2289   const SMDS_MeshNode * node4 = FindNode(idnode4);
2290   const SMDS_MeshNode * node5 = FindNode(idnode5);
2291   const SMDS_MeshNode * node6 = FindNode(idnode6);
2292   return FindFace(node1, node2, node3, node4, node5, node6);
2293 }
2294
2295 const SMDS_MeshFace* SMDS_Mesh::FindFace(const SMDS_MeshNode *node1,
2296                                          const SMDS_MeshNode *node2,
2297                                          const SMDS_MeshNode *node3,
2298                                          const SMDS_MeshNode *node4,
2299                                          const SMDS_MeshNode *node5,
2300                                          const SMDS_MeshNode *node6)
2301 {
2302   if ( !node1 ) return 0;
2303   SMDS_ElemIteratorPtr it1 = node1->GetInverseElementIterator(SMDSAbs_Face);
2304   while(it1->more()) {
2305     const SMDS_MeshElement * e = it1->next();
2306     if ( e->NbNodes() == 6 ) {
2307       SMDS_ElemIteratorPtr it2 = e->nodesIterator();
2308       while(it2->more()) {
2309         const SMDS_MeshElement* n = it2->next();
2310         if( n!=node1 &&
2311             n!=node2 &&
2312             n!=node3 &&
2313             n!=node4 &&
2314             n!=node5 &&
2315             n!=node6 )
2316         {
2317           e = 0;
2318           break;
2319         }
2320       }
2321       if ( e )
2322         return static_cast<const SMDS_MeshFace *> (e);
2323     }
2324   }
2325   return 0;
2326 }
2327
2328
2329 //=======================================================================
2330 //function : FindFace
2331 //purpose  : quadratic quadrangle
2332 //=======================================================================
2333
2334 const SMDS_MeshFace* SMDS_Mesh::FindFace(int idnode1, int idnode2,
2335                                          int idnode3, int idnode4,
2336                                          int idnode5, int idnode6,
2337                                          int idnode7, int idnode8) const
2338 {
2339   const SMDS_MeshNode * node1 = FindNode(idnode1);
2340   const SMDS_MeshNode * node2 = FindNode(idnode2);
2341   const SMDS_MeshNode * node3 = FindNode(idnode3);
2342   const SMDS_MeshNode * node4 = FindNode(idnode4);
2343   const SMDS_MeshNode * node5 = FindNode(idnode5);
2344   const SMDS_MeshNode * node6 = FindNode(idnode6);
2345   const SMDS_MeshNode * node7 = FindNode(idnode7);
2346   const SMDS_MeshNode * node8 = FindNode(idnode8);
2347   return FindFace(node1, node2, node3, node4, node5, node6, node7, node8);
2348 }
2349
2350 const SMDS_MeshFace* SMDS_Mesh::FindFace(const SMDS_MeshNode *node1,
2351                                          const SMDS_MeshNode *node2,
2352                                          const SMDS_MeshNode *node3,
2353                                          const SMDS_MeshNode *node4,
2354                                          const SMDS_MeshNode *node5,
2355                                          const SMDS_MeshNode *node6,
2356                                          const SMDS_MeshNode *node7,
2357                                          const SMDS_MeshNode *node8)
2358 {
2359   if ( !node1 ) return 0;
2360   SMDS_ElemIteratorPtr it1 = node1->GetInverseElementIterator(SMDSAbs_Face);
2361   while(it1->more()) {
2362     const SMDS_MeshElement * e = it1->next();
2363     if ( e->NbNodes() == 8 ) {
2364       SMDS_ElemIteratorPtr it2 = e->nodesIterator();
2365       while(it2->more()) {
2366         const SMDS_MeshElement* n = it2->next();
2367         if( n!=node1 &&
2368             n!=node2 &&
2369             n!=node3 &&
2370             n!=node4 &&
2371             n!=node5 &&
2372             n!=node6 &&
2373             n!=node7 &&
2374             n!=node8 )
2375         {
2376           e = 0;
2377           break;
2378         }
2379       }
2380       if ( e )
2381         return static_cast<const SMDS_MeshFace *> (e);
2382     }
2383   }
2384   return 0;
2385 }
2386
2387
2388 //=======================================================================
2389 //function : FindElement
2390 //purpose  :
2391 //=======================================================================
2392
2393 const SMDS_MeshElement* SMDS_Mesh::FindElement(int IDelem) const
2394 {
2395   if ( IDelem <= 0 || IDelem >= (int)myCells.size() )
2396   {
2397     return 0;
2398   }
2399   return myCells[IDelem];
2400 }
2401
2402 //=======================================================================
2403 //function : FindFace
2404 //purpose  : find polygon
2405 //=======================================================================
2406
2407 const SMDS_MeshFace* SMDS_Mesh::FindFace (const vector<int>& nodes_ids) const
2408 {
2409   int nbnodes = nodes_ids.size();
2410   vector<const SMDS_MeshNode *> poly_nodes (nbnodes);
2411   for (int inode = 0; inode < nbnodes; inode++) {
2412     const SMDS_MeshNode * node = FindNode(nodes_ids[inode]);
2413     if (node == NULL) return NULL;
2414     poly_nodes[inode] = node;
2415   }
2416   return FindFace(poly_nodes);
2417 }
2418
2419 const SMDS_MeshFace* SMDS_Mesh::FindFace (const vector<const SMDS_MeshNode *>& nodes)
2420 {
2421   return (const SMDS_MeshFace*) FindElement( nodes, SMDSAbs_Face );
2422 }
2423
2424
2425 //================================================================================
2426 /*!
2427  * \brief Return element based on all given nodes
2428  *  \param nodes - node of element
2429  *  \param type - type of element
2430  *  \param noMedium - true if medium nodes of quadratic element are not included in <nodes>
2431  *  \retval const SMDS_MeshElement* - found element or NULL
2432  */
2433 //================================================================================
2434
2435 const SMDS_MeshElement* SMDS_Mesh::FindElement (const vector<const SMDS_MeshNode *>& nodes,
2436                                                 const SMDSAbs_ElementType            type,
2437                                                 const bool                           noMedium)
2438 {
2439   if ( nodes.size() > 0 && nodes[0] )
2440   {
2441     SMDS_ElemIteratorPtr itF = nodes[0]->GetInverseElementIterator(type);
2442     while (itF->more())
2443     {
2444       const SMDS_MeshElement* e = itF->next();
2445       int nbNodesToCheck = noMedium ? e->NbCornerNodes() : e->NbNodes();
2446       if ( nbNodesToCheck == (int)nodes.size() )
2447       {
2448         for ( size_t i = 1; e && i < nodes.size(); ++i )
2449         {
2450           int nodeIndex = e->GetNodeIndex( nodes[ i ]);
2451           if ( nodeIndex < 0 || nodeIndex >= nbNodesToCheck )
2452             e = 0;
2453         }
2454         if ( e )
2455           return e;
2456       }
2457     }
2458   }
2459   return NULL;
2460 }
2461
2462 //=======================================================================
2463 //function : DumpNodes
2464 //purpose  :
2465 //=======================================================================
2466
2467 void SMDS_Mesh::DumpNodes() const
2468 {
2469   SMDS_NodeIteratorPtr itnode=nodesIterator();
2470   while(itnode->more()) ; //MESSAGE(itnode->next());
2471 }
2472
2473 //=======================================================================
2474 //function : Dump0DElements
2475 //purpose  :
2476 //=======================================================================
2477 void SMDS_Mesh::Dump0DElements() const
2478 {
2479   SMDS_ElemIteratorPtr it0d = elementsIterator(SMDSAbs_0DElement);
2480   while(it0d->more()) ; //MESSAGE(it0d->next());
2481 }
2482
2483 //=======================================================================
2484 //function : DumpEdges
2485 //purpose  :
2486 //=======================================================================
2487
2488 void SMDS_Mesh::DumpEdges() const
2489 {
2490   SMDS_EdgeIteratorPtr itedge=edgesIterator();
2491   while(itedge->more()) ; //MESSAGE(itedge->next());
2492 }
2493
2494 //=======================================================================
2495 //function : DumpFaces
2496 //purpose  :
2497 //=======================================================================
2498
2499 void SMDS_Mesh::DumpFaces() const
2500 {
2501   SMDS_FaceIteratorPtr itface=facesIterator();
2502   while(itface->more()) ; //MESSAGE(itface->next());
2503 }
2504
2505 //=======================================================================
2506 //function : DumpVolumes
2507 //purpose  :
2508 //=======================================================================
2509
2510 void SMDS_Mesh::DumpVolumes() const
2511 {
2512   SMDS_VolumeIteratorPtr itvol=volumesIterator();
2513   while(itvol->more()) ; //MESSAGE(itvol->next());
2514 }
2515
2516 //=======================================================================
2517 //function : DebugStats
2518 //purpose  :
2519 //=======================================================================
2520
2521 void SMDS_Mesh::DebugStats() const
2522 {
2523   MESSAGE("Debug stats of mesh : ");
2524
2525   MESSAGE("===== NODES ====="<<NbNodes());
2526   MESSAGE("===== 0DELEMS ====="<<Nb0DElements());
2527   MESSAGE("===== EDGES ====="<<NbEdges());
2528   MESSAGE("===== FACES ====="<<NbFaces());
2529   MESSAGE("===== VOLUMES ====="<<NbVolumes());
2530
2531   MESSAGE("End Debug stats of mesh ");
2532
2533   //#ifdef DEB
2534
2535   SMDS_NodeIteratorPtr itnode=nodesIterator();
2536   int sizeofnodes = 0;
2537   int sizeoffaces = 0;
2538
2539   while(itnode->more())
2540   {
2541     const SMDS_MeshNode *node = itnode->next();
2542
2543     sizeofnodes += sizeof(*node);
2544
2545     SMDS_ElemIteratorPtr it = node->GetInverseElementIterator();
2546     while(it->more())
2547     {
2548       const SMDS_MeshElement *me = it->next();
2549       sizeofnodes += sizeof(me);
2550     }
2551   }
2552
2553   SMDS_FaceIteratorPtr itface=facesIterator();
2554   while(itface->more())
2555   {
2556     const SMDS_MeshElement *face = itface->next();
2557     sizeoffaces += sizeof(*face);
2558   }
2559
2560   MESSAGE("total size of node elements = " << sizeofnodes);;
2561   MESSAGE("total size of face elements = " << sizeoffaces);;
2562
2563   //#endif
2564 }
2565
2566 ///////////////////////////////////////////////////////////////////////////////
2567 /// Return the number of nodes
2568 ///////////////////////////////////////////////////////////////////////////////
2569 int SMDS_Mesh::NbNodes() const
2570 {
2571   return myInfo.NbNodes();
2572 }
2573
2574 ///////////////////////////////////////////////////////////////////////////////
2575 /// Return the number of 0D elements
2576 ///////////////////////////////////////////////////////////////////////////////
2577 int SMDS_Mesh::Nb0DElements() const
2578 {
2579   return myInfo.Nb0DElements();
2580 }
2581
2582 ///////////////////////////////////////////////////////////////////////////////
2583 /// Return the number of 0D elements
2584 ///////////////////////////////////////////////////////////////////////////////
2585 int SMDS_Mesh::NbBalls() const
2586 {
2587   return myInfo.NbBalls();
2588 }
2589
2590 ///////////////////////////////////////////////////////////////////////////////
2591 /// Return the number of edges (including construction edges)
2592 ///////////////////////////////////////////////////////////////////////////////
2593 int SMDS_Mesh::NbEdges() const
2594 {
2595   return myInfo.NbEdges();
2596 }
2597
2598 ///////////////////////////////////////////////////////////////////////////////
2599 /// Return the number of faces (including construction faces)
2600 ///////////////////////////////////////////////////////////////////////////////
2601 int SMDS_Mesh::NbFaces() const
2602 {
2603   return myInfo.NbFaces();
2604 }
2605
2606 ///////////////////////////////////////////////////////////////////////////////
2607 /// Return the number of volumes
2608 ///////////////////////////////////////////////////////////////////////////////
2609 int SMDS_Mesh::NbVolumes() const
2610 {
2611   return myInfo.NbVolumes();
2612 }
2613
2614 ///////////////////////////////////////////////////////////////////////////////
2615 /// Return the number of child mesh of this mesh.
2616 /// Note that the tree structure of SMDS_Mesh is unused in SMESH
2617 ///////////////////////////////////////////////////////////////////////////////
2618 int SMDS_Mesh::NbSubMesh() const
2619 {
2620   return myChildren.size();
2621 }
2622
2623 ///////////////////////////////////////////////////////////////////////////////
2624 /// Destroy the mesh and all its elements
2625 /// All pointer on elements owned by this mesh become illegals.
2626 ///////////////////////////////////////////////////////////////////////////////
2627 SMDS_Mesh::~SMDS_Mesh()
2628 {
2629   list<SMDS_Mesh*>::iterator itc=myChildren.begin();
2630   while(itc!=myChildren.end())
2631   {
2632     delete *itc;
2633     itc++;
2634   }
2635
2636   if(myParent==NULL)
2637   {
2638     delete myNodeIDFactory;
2639     delete myElementIDFactory;
2640   }
2641   else
2642   {
2643     SMDS_ElemIteratorPtr eIt = elementsIterator();
2644     while ( eIt->more() )
2645       {
2646         const SMDS_MeshElement *elem = eIt->next();
2647         myElementIDFactory->ReleaseID(elem->GetID(), elem->getVtkId());
2648       }
2649     SMDS_NodeIteratorPtr itn = nodesIterator();
2650     while (itn->more())
2651       {
2652         const SMDS_MeshNode *node = itn->next();
2653         ((SMDS_MeshNode*)node)->SetPosition(SMDS_SpacePosition::originSpacePosition());
2654         myNodeIDFactory->ReleaseID(node->GetID(), node->getVtkId());
2655       }
2656   }
2657   myGrid->Delete();
2658
2659   delete myNodePool;
2660   delete myVolumePool;
2661   delete myFacePool;
2662   delete myEdgePool;
2663   delete myBallPool;
2664 }
2665
2666 //================================================================================
2667 /*!
2668  * \brief Clear all data
2669  */
2670 //================================================================================
2671
2672 void SMDS_Mesh::Clear()
2673 {
2674   if (myParent!=NULL)
2675     {
2676     SMDS_ElemIteratorPtr eIt = elementsIterator();
2677     while ( eIt->more() )
2678       {
2679         const SMDS_MeshElement *elem = eIt->next();
2680         myElementIDFactory->ReleaseID(elem->GetID(), elem->getVtkId());
2681       }
2682     SMDS_NodeIteratorPtr itn = nodesIterator();
2683     while (itn->more())
2684       {
2685         const SMDS_MeshNode *node = itn->next();
2686         myNodeIDFactory->ReleaseID(node->GetID(), node->getVtkId());
2687       }
2688     }
2689   else
2690     {
2691     myNodeIDFactory->Clear();
2692     myElementIDFactory->Clear();
2693     }
2694
2695   // SMDS_ElemIteratorPtr itv = elementsIterator();
2696   // while (itv->more())
2697   //   {
2698   //     SMDS_MeshElement* elem = (SMDS_MeshElement*)(itv->next());
2699   //     SMDSAbs_ElementType aType = elem->GetType();
2700   //     switch (aType)
2701   //     {
2702   //       case SMDSAbs_0DElement:
2703   //         delete elem;
2704   //         break;
2705   //       case SMDSAbs_Edge:
2706   //          myEdgePool->destroy(static_cast<SMDS_VtkEdge*>(elem));
2707   //         break;
2708   //       case SMDSAbs_Face:
2709   //         myFacePool->destroy(static_cast<SMDS_VtkFace*>(elem));
2710   //         break;
2711   //       case SMDSAbs_Volume:
2712   //         myVolumePool->destroy(static_cast<SMDS_VtkVolume*>(elem));
2713   //         break;
2714   //       case SMDSAbs_Ball:
2715   //         myBallPool->destroy(static_cast<SMDS_BallElement*>(elem));
2716   //         break;
2717   //       default:
2718   //         break;
2719   //     }
2720   //   }
2721   myVolumePool->clear();
2722   myFacePool->clear();
2723   myEdgePool->clear();
2724   myBallPool->clear();
2725
2726   clearVector( myCells );
2727   clearVector( myCellIdVtkToSmds );
2728
2729   SMDS_NodeIteratorPtr itn = nodesIterator();
2730   while (itn->more())
2731     {
2732       SMDS_MeshNode *node = (SMDS_MeshNode*)(itn->next());
2733       node->SetPosition(SMDS_SpacePosition::originSpacePosition());
2734       //myNodePool->destroy(node);
2735     }
2736   myNodePool->clear();
2737   clearVector( myNodes );
2738
2739   list<SMDS_Mesh*>::iterator itc=myChildren.begin();
2740   while(itc!=myChildren.end())
2741     (*itc)->Clear();
2742
2743   myModified = false;
2744   myModifTime++;
2745   xmin = 0; xmax = 0;
2746   ymin = 0; ymax = 0;
2747   zmin = 0; zmax = 0;
2748
2749   myInfo.Clear();
2750
2751   myGrid->Initialize();
2752   myGrid->Allocate();
2753   vtkPoints* points = vtkPoints::New();
2754   // rnv: to fix bug "21125: EDF 1233 SMESH: Degrardation of precision in a test case for quadratic conversion"
2755   // using double type for storing coordinates of nodes instead float.
2756   points->SetDataType(VTK_DOUBLE);
2757   points->SetNumberOfPoints(0 /*SMDS_Mesh::chunkSize*/);
2758   myGrid->SetPoints( points );
2759   points->Delete();
2760   myGrid->DeleteLinks();
2761 }
2762
2763 ///////////////////////////////////////////////////////////////////////////////
2764 /// Return true if this mesh create faces with edges.
2765 /// A false returned value mean that faces are created with nodes. A concequence
2766 /// is, iteration on edges (SMDS_Element::edgesIterator) will be unavailable.
2767 ///////////////////////////////////////////////////////////////////////////////
2768 bool SMDS_Mesh::hasConstructionEdges()
2769 {
2770         return myHasConstructionEdges;
2771 }
2772
2773 ///////////////////////////////////////////////////////////////////////////////
2774 /// Return true if this mesh create volumes with faces
2775 /// A false returned value mean that volumes are created with nodes or edges.
2776 /// (see hasConstructionEdges)
2777 /// A concequence is, iteration on faces (SMDS_Element::facesIterator) will be
2778 /// unavailable.
2779 ///////////////////////////////////////////////////////////////////////////////
2780 bool SMDS_Mesh::hasConstructionFaces()
2781 {
2782         return myHasConstructionFaces;
2783 }
2784
2785 ///////////////////////////////////////////////////////////////////////////////
2786 /// Return true if nodes are linked to the finit elements, they are belonging to.
2787 /// Currently, It always return true.
2788 ///////////////////////////////////////////////////////////////////////////////
2789 bool SMDS_Mesh::hasInverseElements()
2790 {
2791         return myHasInverseElements;
2792 }
2793
2794 ///////////////////////////////////////////////////////////////////////////////
2795 /// Make this mesh creating construction edges (see hasConstructionEdges)
2796 /// @param b true to have construction edges, else false.
2797 ///////////////////////////////////////////////////////////////////////////////
2798 void SMDS_Mesh::setConstructionEdges(bool b)
2799 {
2800         myHasConstructionEdges=b;
2801 }
2802
2803 ///////////////////////////////////////////////////////////////////////////////
2804 /// Make this mesh creating construction faces (see hasConstructionFaces)
2805 /// @param b true to have construction faces, else false.
2806 ///////////////////////////////////////////////////////////////////////////////
2807 void SMDS_Mesh::setConstructionFaces(bool b)
2808 {
2809          myHasConstructionFaces=b;
2810 }
2811
2812 ///////////////////////////////////////////////////////////////////////////////
2813 /// Make this mesh creating link from nodes to elements (see hasInverseElements)
2814 /// @param b true to link nodes to elements, else false.
2815 ///////////////////////////////////////////////////////////////////////////////
2816 void SMDS_Mesh::setInverseElements(bool b)
2817 {
2818   if(!b) MESSAGE("Error : inverseElement=false not implemented");
2819   myHasInverseElements=b;
2820 }
2821
2822 namespace {
2823
2824   //================================================================================
2825   /*!
2826    * \brief Iterator on elements in id increasing order
2827    */
2828   //================================================================================
2829
2830   template <typename ELEM=const SMDS_MeshElement*>
2831   class IdSortedIterator : public SMDS_Iterator<ELEM>
2832   {
2833     SMDS_MeshElementIDFactory&       myIDFact;
2834     int                              myID, myMaxID, myNbFound, myTotalNb;
2835     SMDSAbs_ElementType              myType;
2836     ELEM                             myElem;
2837
2838   public:
2839     IdSortedIterator(const SMDS_MeshElementIDFactory& fact,
2840                      const SMDSAbs_ElementType        type, // SMDSAbs_All NOT allowed!!! 
2841                      const int                        totalNb)
2842       :myIDFact( fact ),
2843        myID(1), myMaxID( myIDFact.GetMaxID() ),myNbFound(0), myTotalNb( totalNb ),
2844        myType( type ),
2845        myElem(0)
2846     {
2847       next();
2848     }
2849     bool more()
2850     {
2851       return myElem;
2852     }
2853     ELEM next()
2854     {
2855       ELEM current = myElem;
2856
2857       for ( myElem = 0;  !myElem && myNbFound < myTotalNb && myID <= myMaxID; ++myID )
2858         if ((myElem = (ELEM) myIDFact.MeshElement( myID ))
2859             && myElem->GetType() != myType )
2860           myElem = 0;
2861
2862       myNbFound += bool(myElem);
2863
2864       return current;
2865     }
2866   };
2867
2868   //================================================================================
2869   /*!
2870    * \brief Iterator on vector of elements, possibly being resized while iteration
2871    */
2872   //================================================================================
2873
2874   template<typename RETURN_VALUE,
2875            typename VECTOR_VALUE=SMDS_MeshCell*,
2876            typename VALUE_FILTER=SMDS::NonNullFilter<VECTOR_VALUE> >
2877   class ElemVecIterator: public SMDS_Iterator<RETURN_VALUE>
2878   {
2879     const std::vector<VECTOR_VALUE>& _vector;
2880     size_t                           _index;
2881     bool                             _more;
2882     VALUE_FILTER                     _filter;
2883   public:
2884     ElemVecIterator(const std::vector<VECTOR_VALUE>& vec,
2885                     const VALUE_FILTER&              filter=VALUE_FILTER() )
2886       :_vector( vec ), _index(0), _more( !vec.empty() ), _filter( filter )
2887     {
2888       if ( _more && !_filter( _vector[ _index ]))
2889         next();
2890     }
2891     virtual bool more()
2892     {
2893       return _more;
2894     }
2895     virtual RETURN_VALUE next()
2896     {
2897       if ( !_more ) return NULL;
2898       VECTOR_VALUE current = _vector[ _index ];
2899       _more = 0;
2900       while ( !_more && ++_index < _vector.size() )
2901         _more = _filter( _vector[ _index ]);
2902       return (RETURN_VALUE) current;
2903     }
2904   };
2905 }
2906
2907 ///////////////////////////////////////////////////////////////////////////////
2908 /// Return an iterator on nodes of the current mesh factory
2909 ///////////////////////////////////////////////////////////////////////////////
2910
2911 SMDS_NodeIteratorPtr SMDS_Mesh::nodesIterator(bool idInceasingOrder) const
2912 {
2913   // naturally always sorted by ID
2914   typedef ElemVecIterator<const SMDS_MeshNode*, SMDS_MeshNode*> TIterator;
2915   return SMDS_NodeIteratorPtr( new TIterator(myNodes));
2916 }
2917
2918 SMDS_ElemIteratorPtr SMDS_Mesh::elementGeomIterator(SMDSAbs_GeometryType type) const
2919 {
2920   // naturally always sorted by ID
2921   typedef ElemVecIterator
2922     < const SMDS_MeshElement*, SMDS_MeshCell*, SMDS_MeshElement::GeomFilter > TIterator;
2923   return SMDS_ElemIteratorPtr
2924     (new TIterator(myCells, SMDS_MeshElement::GeomFilter( type )));
2925 }
2926
2927 SMDS_ElemIteratorPtr SMDS_Mesh::elementEntityIterator(SMDSAbs_EntityType type) const
2928 {
2929   if ( type == SMDSEntity_Node )
2930   {
2931     typedef ElemVecIterator<const SMDS_MeshElement*, SMDS_MeshNode*> TIterator;
2932     return SMDS_ElemIteratorPtr( new TIterator(myNodes));
2933   }
2934   // naturally always sorted by ID
2935   typedef ElemVecIterator
2936     < const SMDS_MeshElement*, SMDS_MeshCell*, SMDS_MeshElement::EntityFilter > TIterator;
2937   return SMDS_ElemIteratorPtr
2938     (new TIterator(myCells, SMDS_MeshElement::EntityFilter( type )));
2939 }
2940
2941 ///////////////////////////////////////////////////////////////////////////////
2942 /// Return an iterator on elements of the current mesh factory
2943 ///////////////////////////////////////////////////////////////////////////////
2944 SMDS_ElemIteratorPtr SMDS_Mesh::elementsIterator(SMDSAbs_ElementType type) const
2945 {
2946   // naturally always sorted by ID
2947   switch ( type ) {
2948
2949   case SMDSAbs_All:
2950     return SMDS_ElemIteratorPtr (new ElemVecIterator<const SMDS_MeshElement*>(myCells));
2951
2952   case SMDSAbs_Node:
2953     return SMDS_ElemIteratorPtr
2954       ( new ElemVecIterator<const SMDS_MeshElement*, SMDS_MeshNode*>( myNodes ));
2955
2956   default:
2957     typedef ElemVecIterator
2958       < const SMDS_MeshElement*, SMDS_MeshCell*, SMDS_MeshElement::TypeFilter > TIterator;
2959     return SMDS_ElemIteratorPtr (new TIterator(myCells, SMDS_MeshElement::TypeFilter( type )));
2960   }
2961   return SMDS_ElemIteratorPtr();
2962 }
2963
2964 ///////////////////////////////////////////////////////////////////////////////
2965 ///Return an iterator on edges of the current mesh.
2966 ///////////////////////////////////////////////////////////////////////////////
2967
2968 SMDS_EdgeIteratorPtr SMDS_Mesh::edgesIterator(bool idInceasingOrder) const
2969 {
2970   // naturally always sorted by ID
2971   typedef ElemVecIterator
2972     < const SMDS_MeshEdge*, SMDS_MeshCell*, SMDS_MeshElement::TypeFilter > TIterator;
2973   return SMDS_EdgeIteratorPtr
2974     (new TIterator(myCells, SMDS_MeshElement::TypeFilter( SMDSAbs_Edge )));
2975 }
2976
2977 ///////////////////////////////////////////////////////////////////////////////
2978 ///Return an iterator on faces of the current mesh.
2979 ///////////////////////////////////////////////////////////////////////////////
2980
2981 SMDS_FaceIteratorPtr SMDS_Mesh::facesIterator(bool idInceasingOrder) const
2982 {
2983   // naturally always sorted by ID
2984   typedef ElemVecIterator
2985     < const SMDS_MeshFace*, SMDS_MeshCell*, SMDS_MeshElement::TypeFilter > TIterator;
2986   return SMDS_FaceIteratorPtr
2987     (new TIterator(myCells, SMDS_MeshElement::TypeFilter( SMDSAbs_Face )));
2988 }
2989
2990 ///////////////////////////////////////////////////////////////////////////////
2991 ///Return an iterator on volumes of the current mesh.
2992 ///////////////////////////////////////////////////////////////////////////////
2993
2994 SMDS_VolumeIteratorPtr SMDS_Mesh::volumesIterator(bool idInceasingOrder) const
2995 {
2996   // naturally always sorted by ID
2997   typedef ElemVecIterator
2998     < const SMDS_MeshVolume*, SMDS_MeshCell*, SMDS_MeshElement::TypeFilter > TIterator;
2999   return SMDS_VolumeIteratorPtr
3000     (new TIterator(myCells, SMDS_MeshElement::TypeFilter( SMDSAbs_Volume )));
3001 }
3002
3003 ///////////////////////////////////////////////////////////////////////////////
3004 /// Do intersection of sets (more than 2)
3005 ///////////////////////////////////////////////////////////////////////////////
3006 static set<const SMDS_MeshElement*> * intersectionOfSets(
3007         set<const SMDS_MeshElement*> vs[], int numberOfSets)
3008 {
3009         set<const SMDS_MeshElement*>* rsetA=new set<const SMDS_MeshElement*>(vs[0]);
3010         set<const SMDS_MeshElement*>* rsetB;
3011
3012         for(int i=0; i<numberOfSets-1; i++)
3013         {
3014                 rsetB=new set<const SMDS_MeshElement*>();
3015                 set_intersection(
3016                         rsetA->begin(), rsetA->end(),
3017                         vs[i+1].begin(), vs[i+1].end(),
3018                         inserter(*rsetB, rsetB->begin()));
3019                 delete rsetA;
3020                 rsetA=rsetB;
3021         }
3022         return rsetA;
3023 }
3024
3025 ///////////////////////////////////////////////////////////////////////////////
3026 /// Return the list of finite elements owning the given element: elements
3027 /// containing all the nodes of the given element, for instance faces and
3028 /// volumes containing a given edge.
3029 ///////////////////////////////////////////////////////////////////////////////
3030 static set<const SMDS_MeshElement*> * getFinitElements(const SMDS_MeshElement * element)
3031 {
3032   int numberOfSets=element->NbNodes();
3033   set<const SMDS_MeshElement*> *initSet = new set<const SMDS_MeshElement*>[numberOfSets];
3034
3035   SMDS_ElemIteratorPtr itNodes=element->nodesIterator();
3036
3037   int i = 0;
3038   while ( itNodes->more() )
3039   {
3040     const SMDS_MeshElement* node = itNodes->next();
3041     MYASSERT(node);
3042     const SMDS_MeshNode * n=static_cast<const SMDS_MeshNode*>(node);
3043     SMDS_ElemIteratorPtr itFe = n->GetInverseElementIterator();
3044
3045     while ( itFe->more() )
3046     {
3047       const SMDS_MeshElement* elem = itFe->next();
3048       MYASSERT(elem);
3049       initSet[i].insert(elem);
3050     }
3051
3052     i++;
3053   }
3054   set<const SMDS_MeshElement*> *retSet = intersectionOfSets( initSet, numberOfSets );
3055   delete [] initSet;
3056   return retSet;
3057 }
3058
3059 ///////////////////////////////////////////////////////////////////////////////
3060 /// Return the list of nodes used only by the given elements
3061 ///////////////////////////////////////////////////////////////////////////////
3062 static set<const SMDS_MeshElement*> * getExclusiveNodes(set<const SMDS_MeshElement*>& elements)
3063 {
3064   set<const SMDS_MeshElement*> * toReturn=new set<const SMDS_MeshElement*>();
3065   set<const SMDS_MeshElement*>::iterator itElements=elements.begin();
3066
3067   while(itElements!=elements.end())
3068   {
3069     SMDS_ElemIteratorPtr itNodes = (*itElements)->nodesIterator();
3070     itElements++;
3071
3072     while(itNodes->more())
3073     {
3074       const SMDS_MeshNode * n=static_cast<const SMDS_MeshNode*>(itNodes->next());
3075       SMDS_ElemIteratorPtr itFe = n->GetInverseElementIterator();
3076       set<const SMDS_MeshElement*> s;
3077       while(itFe->more())
3078         s.insert(itFe->next());
3079       if(s==elements) toReturn->insert(n);
3080     }
3081   }
3082   return toReturn;
3083 }
3084
3085 ///////////////////////////////////////////////////////////////////////////////
3086 ///Find the children of an element that are made of given nodes
3087 ///@param setOfChildren The set in which matching children will be inserted
3088 ///@param element The element were to search matching children
3089 ///@param nodes The nodes that the children must have to be selected
3090 ///////////////////////////////////////////////////////////////////////////////
3091 void SMDS_Mesh::addChildrenWithNodes(set<const SMDS_MeshElement*>& setOfChildren,
3092                                      const SMDS_MeshElement *      element,
3093                                      set<const SMDS_MeshElement*>& nodes)
3094 {
3095   switch(element->GetType())
3096   {
3097   case SMDSAbs_Node:
3098     MESSAGE("Internal Error: This should not happen");
3099     break;
3100   case SMDSAbs_0DElement:
3101   case SMDSAbs_Ball:
3102   {
3103   }
3104   break;
3105   case SMDSAbs_Edge:
3106   {
3107     SMDS_ElemIteratorPtr itn=element->nodesIterator();
3108     while(itn->more())
3109     {
3110       const SMDS_MeshElement * e=itn->next();
3111       if(nodes.find(e)!=nodes.end())
3112       {
3113         setOfChildren.insert(element);
3114         break;
3115       }
3116     }
3117   } break;
3118   case SMDSAbs_Face:
3119   {
3120     SMDS_ElemIteratorPtr itn=element->nodesIterator();
3121     while(itn->more())
3122     {
3123       const SMDS_MeshElement * e=itn->next();
3124       if(nodes.find(e)!=nodes.end())
3125       {
3126         setOfChildren.insert(element);
3127         break;
3128       }
3129     }
3130     if(hasConstructionEdges())
3131     {
3132       SMDS_ElemIteratorPtr ite=element->edgesIterator();
3133       while(ite->more())
3134         addChildrenWithNodes(setOfChildren, ite->next(), nodes);
3135     }
3136   } break;
3137   case SMDSAbs_Volume:
3138   {
3139     if(hasConstructionFaces())
3140     {
3141       SMDS_ElemIteratorPtr ite=element->facesIterator();
3142       while(ite->more())
3143         addChildrenWithNodes(setOfChildren, ite->next(), nodes);
3144     }
3145     else if(hasConstructionEdges())
3146     {
3147       SMDS_ElemIteratorPtr ite=element->edgesIterator();
3148       while(ite->more())
3149         addChildrenWithNodes(setOfChildren, ite->next(), nodes);
3150     }
3151   }
3152   case SMDSAbs_NbElementTypes:
3153   case SMDSAbs_All: break;
3154   }
3155 }
3156
3157 ///////////////////////////////////////////////////////////////////////////////
3158 ///@param elem The element to delete
3159 ///@param removenodes if true remaining nodes will be removed
3160 ///////////////////////////////////////////////////////////////////////////////
3161 void SMDS_Mesh::RemoveElement(const SMDS_MeshElement * elem,
3162                               const bool removenodes)
3163 {
3164   list<const SMDS_MeshElement *> removedElems;
3165   list<const SMDS_MeshElement *> removedNodes;
3166   RemoveElement( elem, removedElems, removedNodes, removenodes );
3167 }
3168
3169 ///////////////////////////////////////////////////////////////////////////////
3170 ///@param elem The element to delete
3171 ///@param removedElems to be filled with all removed elements
3172 ///@param removedNodes to be filled with all removed nodes
3173 ///@param removenodes if true remaining nodes will be removed
3174 ///////////////////////////////////////////////////////////////////////////////
3175 void SMDS_Mesh::RemoveElement(const SMDS_MeshElement *        elem,
3176                               list<const SMDS_MeshElement *>& removedElems,
3177                               list<const SMDS_MeshElement *>& removedNodes,
3178                               bool                            removenodes)
3179 {
3180   // get finite elements built on elem
3181   set<const SMDS_MeshElement*> * s1;
3182   if (    (elem->GetType() == SMDSAbs_0DElement)
3183       || ((elem->GetType() == SMDSAbs_Edge) && !hasConstructionEdges())
3184       || ((elem->GetType() == SMDSAbs_Face) && !hasConstructionFaces())
3185       ||  (elem->GetType() == SMDSAbs_Volume) )
3186     {
3187       s1 = new set<const SMDS_MeshElement*> ();
3188       s1->insert(elem);
3189     }
3190   else
3191     s1 = getFinitElements(elem);
3192
3193   // get exclusive nodes (which would become free afterwards)
3194   set<const SMDS_MeshElement*> * s2;
3195   if (elem->GetType() == SMDSAbs_Node) // a node is removed
3196     {
3197       // do not remove nodes except elem
3198       s2 = new set<const SMDS_MeshElement*> ();
3199       s2->insert(elem);
3200       removenodes = true;
3201     }
3202   else
3203     s2 = getExclusiveNodes(*s1);
3204
3205   // form the set of finite and construction elements to remove
3206   set<const SMDS_MeshElement*> s3;
3207   set<const SMDS_MeshElement*>::iterator it = s1->begin();
3208   while (it != s1->end())
3209     {
3210       addChildrenWithNodes(s3, *it, *s2);
3211       s3.insert(*it);
3212       it++;
3213     }
3214   if (elem->GetType() != SMDSAbs_Node)
3215     s3.insert(elem);
3216
3217   // remove finite and construction elements
3218   it = s3.begin();
3219   while (it != s3.end())
3220     {
3221       // Remove element from <InverseElements> of its nodes
3222       SMDS_ElemIteratorPtr itn = (*it)->nodesIterator();
3223       while (itn->more())
3224       {
3225         SMDS_MeshNode * n = static_cast<SMDS_MeshNode *> (const_cast<SMDS_MeshElement *> (itn->next()));
3226         n->RemoveInverseElement((*it));
3227       }
3228       int IdToRemove = (*it)->GetID();
3229       int vtkid = (*it)->getVtkId();
3230       switch ((*it)->GetType())
3231       {
3232         case SMDSAbs_Node:
3233           MYASSERT("Internal Error: This should not happen");
3234           break;
3235         case SMDSAbs_0DElement:
3236           if (IdToRemove >= 0)
3237             {
3238               myCells[IdToRemove] = 0; // -PR- ici ou dans myElementIDFactory->ReleaseID ?
3239               myInfo.remove(*it);
3240             }
3241           removedElems.push_back((*it));
3242           myElementIDFactory->ReleaseID(IdToRemove, vtkid);
3243           delete (*it);
3244           break;
3245         case SMDSAbs_Edge:
3246           if (IdToRemove >= 0)
3247             {
3248               myCells[IdToRemove] = 0;
3249               myInfo.RemoveEdge(*it);
3250             }
3251           removedElems.push_back((*it));
3252           myElementIDFactory->ReleaseID(IdToRemove, vtkid);
3253           if (const SMDS_VtkEdge* vtkElem = dynamic_cast<const SMDS_VtkEdge*>(*it))
3254             myEdgePool->destroy((SMDS_VtkEdge*) vtkElem);
3255           else {
3256             ((SMDS_MeshElement*) *it)->init( -1, -1, -1 ); // avoid reuse
3257             delete (*it);
3258           }
3259           break;
3260         case SMDSAbs_Face:
3261           if (IdToRemove >= 0)
3262             {
3263               myCells[IdToRemove] = 0;
3264               myInfo.RemoveFace(*it);
3265             }
3266           removedElems.push_back((*it));
3267           myElementIDFactory->ReleaseID(IdToRemove, vtkid);
3268           if (const SMDS_VtkFace* vtkElem = dynamic_cast<const SMDS_VtkFace*>(*it))
3269             myFacePool->destroy((SMDS_VtkFace*) vtkElem);
3270           else {
3271             ((SMDS_MeshElement*) *it)->init( -1, -1, -1 ); // avoid reuse
3272             delete (*it);
3273           }
3274           break;
3275         case SMDSAbs_Volume:
3276           if (IdToRemove >= 0)
3277             {
3278               myCells[IdToRemove] = 0;
3279               myInfo.RemoveVolume(*it);
3280             }
3281           removedElems.push_back((*it));
3282           myElementIDFactory->ReleaseID(IdToRemove, vtkid);
3283           if (const SMDS_VtkVolume* vtkElem = dynamic_cast<const SMDS_VtkVolume*>(*it))
3284             myVolumePool->destroy((SMDS_VtkVolume*) vtkElem);
3285           else {
3286             ((SMDS_MeshElement*) *it)->init( -1, -1, -1 ); // avoid reuse
3287             delete (*it);
3288           }
3289           break;
3290         case SMDSAbs_Ball:
3291           if (IdToRemove >= 0)
3292             {
3293               myCells[IdToRemove] = 0;
3294               myInfo.remove(*it);
3295             }
3296           removedElems.push_back((*it));
3297           myElementIDFactory->ReleaseID(IdToRemove, vtkid);
3298           if (const SMDS_BallElement* vtkElem = dynamic_cast<const SMDS_BallElement*>(*it))
3299             myBallPool->destroy(const_cast<SMDS_BallElement*>( vtkElem ));
3300           else {
3301             ((SMDS_MeshElement*) *it)->init( -1, -1, -1 ); // avoid reuse
3302             delete (*it);
3303           }
3304           break;
3305
3306         case SMDSAbs_All: // avoid compilation warning
3307         case SMDSAbs_NbElementTypes: break;
3308       }
3309       if (vtkid >= 0)
3310       {
3311         this->myGrid->GetCellTypesArray()->SetValue(vtkid, VTK_EMPTY_CELL);
3312       }
3313       it++;
3314     }
3315
3316   // remove exclusive (free) nodes
3317   if (removenodes)
3318   {
3319     it = s2->begin();
3320     while (it != s2->end())
3321     {
3322       int IdToRemove = (*it)->GetID();
3323       if (IdToRemove >= 0)
3324       {
3325         myNodes[IdToRemove] = 0;
3326         myInfo.myNbNodes--;
3327       }
3328       myNodeIDFactory->ReleaseID((*it)->GetID(), (*it)->getVtkId());
3329       removedNodes.push_back((*it));
3330       if (const SMDS_MeshNode* vtkElem = dynamic_cast<const SMDS_MeshNode*>(*it))
3331       {
3332         ((SMDS_MeshNode*)vtkElem)->SetPosition(SMDS_SpacePosition::originSpacePosition());
3333         myNodePool->destroy((SMDS_MeshNode*) vtkElem);
3334       }
3335       else
3336         delete (*it);
3337       it++;
3338     }
3339   }
3340
3341   delete s2;
3342   delete s1;
3343 }
3344
3345
3346 ///////////////////////////////////////////////////////////////////////////////
3347 ///@param elem The element to delete
3348 ///////////////////////////////////////////////////////////////////////////////
3349 void SMDS_Mesh::RemoveFreeElement(const SMDS_MeshElement * elem)
3350 {
3351   int elemId = elem->GetID();
3352   int vtkId = elem->getVtkId();
3353   SMDSAbs_ElementType aType = elem->GetType();
3354   SMDS_MeshElement* todest = (SMDS_MeshElement*)(elem);
3355   if (aType == SMDSAbs_Node) {
3356     // only free node can be removed by this method
3357     const SMDS_MeshNode* n = static_cast<SMDS_MeshNode*>(todest);
3358     SMDS_ElemIteratorPtr itFe = n->GetInverseElementIterator();
3359     if (!itFe->more()) { // free node
3360       myNodes[elemId] = 0;
3361       myInfo.myNbNodes--;
3362       ((SMDS_MeshNode*) n)->SetPosition(SMDS_SpacePosition::originSpacePosition());
3363       ((SMDS_MeshNode*) n)->SMDS_MeshElement::init( -1, -1, -1 ); // avoid reuse
3364       myNodePool->destroy(static_cast<SMDS_MeshNode*>(todest));
3365       myNodeIDFactory->ReleaseID(elemId, vtkId);
3366     }
3367   } else {
3368     if (hasConstructionEdges() || hasConstructionFaces())
3369       // this methods is only for meshes without descendants
3370       return;
3371
3372     // Remove element from <InverseElements> of its nodes
3373     SMDS_ElemIteratorPtr itn = elem->nodesIterator();
3374     while (itn->more()) {
3375       SMDS_MeshNode * n = static_cast<SMDS_MeshNode *>
3376         (const_cast<SMDS_MeshElement *>(itn->next()));
3377       n->RemoveInverseElement(elem);
3378     }
3379
3380     // in meshes without descendants elements are always free
3381     switch (aType) {
3382     case SMDSAbs_0DElement:
3383       myCells[elemId] = 0;
3384       myInfo.remove(elem);
3385       delete elem;
3386       elem = 0;
3387       break;
3388     case SMDSAbs_Edge:
3389       myCells[elemId] = 0;
3390       myInfo.RemoveEdge(elem);
3391       myEdgePool->destroy(static_cast<SMDS_VtkEdge*>(todest));
3392       break;
3393     case SMDSAbs_Face:
3394       myCells[elemId] = 0;
3395       myInfo.RemoveFace(elem);
3396       myFacePool->destroy(static_cast<SMDS_VtkFace*>(todest));
3397       break;
3398     case SMDSAbs_Volume:
3399       myCells[elemId] = 0;
3400       myInfo.RemoveVolume(elem);
3401       myVolumePool->destroy(static_cast<SMDS_VtkVolume*>(todest));
3402       break;
3403     case SMDSAbs_Ball:
3404       myCells[elemId] = 0;
3405       myInfo.remove(elem);
3406       myBallPool->destroy(static_cast<SMDS_BallElement*>(todest));
3407       break;
3408     default:
3409       break;
3410     }
3411     myElementIDFactory->ReleaseID(elemId, vtkId);
3412
3413     this->myGrid->GetCellTypesArray()->SetValue(vtkId, VTK_EMPTY_CELL);
3414     // --- to do: keep vtkid in a list of reusable cells
3415
3416     if ( elem )
3417       ((SMDS_MeshElement*) elem)->init( -1, -1, -1 ); // avoid reuse
3418   }
3419 }
3420
3421 /*!
3422  * Checks if the element is present in mesh.
3423  * Useful to determine dead pointers.
3424  */
3425 bool SMDS_Mesh::Contains (const SMDS_MeshElement* elem) const
3426 {
3427   // we should not imply on validity of *elem, so iterate on containers
3428   // of all types in the hope of finding <elem> somewhere there
3429   SMDS_NodeIteratorPtr itn = nodesIterator();
3430   while (itn->more())
3431     if (elem == itn->next())
3432       return true;
3433   SMDS_ElemIteratorPtr ite = elementsIterator();
3434   while (ite->more())
3435     if (elem == ite->next())
3436       return true;
3437   return false;
3438 }
3439
3440 //=======================================================================
3441 //function : MaxNodeID
3442 //purpose  :
3443 //=======================================================================
3444
3445 int SMDS_Mesh::MaxNodeID() const
3446 {
3447   return myNodeMax;
3448 }
3449
3450 //=======================================================================
3451 //function : MinNodeID
3452 //purpose  :
3453 //=======================================================================
3454
3455 int SMDS_Mesh::MinNodeID() const
3456 {
3457   return myNodeMin;
3458 }
3459
3460 //=======================================================================
3461 //function : MaxElementID
3462 //purpose  :
3463 //=======================================================================
3464
3465 int SMDS_Mesh::MaxElementID() const
3466 {
3467   return myElementIDFactory->GetMaxID();
3468 }
3469
3470 //=======================================================================
3471 //function : MinElementID
3472 //purpose  :
3473 //=======================================================================
3474
3475 int SMDS_Mesh::MinElementID() const
3476 {
3477   return myElementIDFactory->GetMinID();
3478 }
3479
3480 //=======================================================================
3481 //function : Renumber
3482 //purpose  : Renumber all nodes or elements.
3483 //=======================================================================
3484
3485 void SMDS_Mesh::Renumber (const bool isNodes, const int  startID, const int  deltaID)
3486 {
3487   if ( deltaID == 0 )
3488     return;
3489
3490   SMDS_MeshNodeIDFactory * idFactory =
3491     isNodes ? myNodeIDFactory : myElementIDFactory;
3492
3493   // get existing elements in the order of ID increasing
3494   map<int,SMDS_MeshElement*> elemMap;
3495   SMDS_ElemIteratorPtr idElemIt = idFactory->elementsIterator();
3496   while ( idElemIt->more() ) {
3497     SMDS_MeshElement* elem = const_cast<SMDS_MeshElement*>(idElemIt->next());
3498     int id = elem->GetID();
3499     elemMap.insert(map<int,SMDS_MeshElement*>::value_type(id, elem));
3500   }
3501   // release their ids
3502   map<int,SMDS_MeshElement*>::iterator elemIt = elemMap.begin();
3503   idFactory->Clear();
3504 //   for ( ; elemIt != elemMap.end(); elemIt++ )
3505 //   {
3506 //     int id = (*elemIt).first;
3507 //     idFactory->ReleaseID( id );
3508 //   }
3509   // set new IDs
3510   int ID = startID;
3511   elemIt = elemMap.begin();
3512   for ( ; elemIt != elemMap.end(); elemIt++ )
3513   {
3514     idFactory->BindID( ID, (*elemIt).second );
3515     ID += deltaID;
3516   }
3517 }
3518
3519 //=======================================================================
3520 //function : GetElementType
3521 //purpose  : Return type of element or node with id
3522 //=======================================================================
3523
3524 SMDSAbs_ElementType SMDS_Mesh::GetElementType( const int id, const bool iselem ) const
3525 {
3526   SMDS_MeshElement* elem = 0;
3527   if( iselem )
3528     elem = myElementIDFactory->MeshElement( id );
3529   else
3530     elem = myNodeIDFactory->MeshElement( id );
3531
3532   if( !elem )
3533   {
3534     //throw SALOME_Exception(LOCALIZED ("this element isn't exist"));
3535     return SMDSAbs_All;
3536   }
3537   else
3538     return elem->GetType();
3539 }
3540
3541
3542
3543 //********************************************************************
3544 //********************************************************************
3545 //********                                                   *********
3546 //*****       Methods for addition of quadratic elements        ******
3547 //********                                                   *********
3548 //********************************************************************
3549 //********************************************************************
3550
3551 //=======================================================================
3552 //function : AddEdgeWithID
3553 //purpose  :
3554 //=======================================================================
3555 SMDS_MeshEdge* SMDS_Mesh::AddEdgeWithID(int n1, int n2, int n12, int ID)
3556 {
3557   return SMDS_Mesh::AddEdgeWithID
3558     ((SMDS_MeshNode*) myNodeIDFactory->MeshElement(n1),
3559      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n2),
3560      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n12),
3561      ID);
3562 }
3563
3564 //=======================================================================
3565 //function : AddEdge
3566 //purpose  :
3567 //=======================================================================
3568 SMDS_MeshEdge* SMDS_Mesh::AddEdge(const SMDS_MeshNode* n1,
3569                                   const SMDS_MeshNode* n2,
3570                                   const SMDS_MeshNode* n12)
3571 {
3572   return SMDS_Mesh::AddEdgeWithID(n1, n2, n12, myElementIDFactory->GetFreeID());
3573 }
3574
3575 //=======================================================================
3576 //function : AddEdgeWithID
3577 //purpose  :
3578 //=======================================================================
3579 SMDS_MeshEdge* SMDS_Mesh::AddEdgeWithID(const SMDS_MeshNode * n1,
3580                                         const SMDS_MeshNode * n2,
3581                                         const SMDS_MeshNode * n12,
3582                                         int ID)
3583 {
3584   if ( !n1 || !n2 || !n12 ) return 0;
3585
3586   // --- retrieve nodes ID
3587   myNodeIds.resize(3);
3588   myNodeIds[0] = n1->getVtkId();
3589   myNodeIds[1] = n2->getVtkId();
3590   myNodeIds[2] = n12->getVtkId();
3591
3592   SMDS_MeshEdge * edge = 0;
3593   SMDS_VtkEdge *edgevtk = myEdgePool->getNew();
3594   edgevtk->init(myNodeIds, this);
3595   if (!this->registerElement(ID,edgevtk))
3596   {
3597     this->myGrid->GetCellTypesArray()->SetValue(edgevtk->getVtkId(), VTK_EMPTY_CELL);
3598     myEdgePool->destroy(edgevtk);
3599     return 0;
3600   }
3601   edge = edgevtk;
3602   adjustmyCellsCapacity(ID);
3603   myCells[ID] = edge;
3604   myInfo.myNbQuadEdges++;
3605
3606   //  if (!registerElement(ID, edge)) {
3607   //        RemoveElement(edge, false);
3608   //        edge = NULL;
3609   //  }
3610   return edge;
3611
3612 }
3613
3614
3615 //=======================================================================
3616 //function : AddFace
3617 //purpose  :
3618 //=======================================================================
3619 SMDS_MeshFace* SMDS_Mesh::AddFace(const SMDS_MeshNode * n1,
3620                                   const SMDS_MeshNode * n2,
3621                                   const SMDS_MeshNode * n3,
3622                                   const SMDS_MeshNode * n12,
3623                                   const SMDS_MeshNode * n23,
3624                                   const SMDS_MeshNode * n31)
3625 {
3626   return SMDS_Mesh::AddFaceWithID(n1,n2,n3,n12,n23,n31,
3627                                   myElementIDFactory->GetFreeID());
3628 }
3629
3630 //=======================================================================
3631 //function : AddFaceWithID
3632 //purpose  :
3633 //=======================================================================
3634 SMDS_MeshFace* SMDS_Mesh::AddFaceWithID(int n1, int n2, int n3,
3635                                         int n12,int n23,int n31, int ID)
3636 {
3637   return SMDS_Mesh::AddFaceWithID
3638     ((SMDS_MeshNode *)myNodeIDFactory->MeshElement(n1) ,
3639      (SMDS_MeshNode *)myNodeIDFactory->MeshElement(n2) ,
3640      (SMDS_MeshNode *)myNodeIDFactory->MeshElement(n3) ,
3641      (SMDS_MeshNode *)myNodeIDFactory->MeshElement(n12),
3642      (SMDS_MeshNode *)myNodeIDFactory->MeshElement(n23),
3643      (SMDS_MeshNode *)myNodeIDFactory->MeshElement(n31),
3644      ID);
3645 }
3646
3647 //=======================================================================
3648 //function : AddFaceWithID
3649 //purpose  :
3650 //=======================================================================
3651 SMDS_MeshFace* SMDS_Mesh::AddFaceWithID(const SMDS_MeshNode * n1,
3652                                         const SMDS_MeshNode * n2,
3653                                         const SMDS_MeshNode * n3,
3654                                         const SMDS_MeshNode * n12,
3655                                         const SMDS_MeshNode * n23,
3656                                         const SMDS_MeshNode * n31,
3657                                         int ID)
3658 {
3659   if ( !n1 || !n2 || !n3 || !n12 || !n23 || !n31) return 0;
3660   if(hasConstructionEdges()) {
3661     // creation quadratic edges - not implemented
3662     return 0;
3663   }
3664   else
3665   {
3666     // --- retrieve nodes ID
3667     myNodeIds.resize(6);
3668     myNodeIds[0] = n1->getVtkId();
3669     myNodeIds[1] = n2->getVtkId();
3670     myNodeIds[2] = n3->getVtkId();
3671     myNodeIds[3] = n12->getVtkId();
3672     myNodeIds[4] = n23->getVtkId();
3673     myNodeIds[5] = n31->getVtkId();
3674
3675     SMDS_MeshFace * face = 0;
3676     SMDS_VtkFace *facevtk = myFacePool->getNew();
3677     facevtk->init(myNodeIds, this);
3678     if (!this->registerElement(ID,facevtk))
3679     {
3680       this->myGrid->GetCellTypesArray()->SetValue(facevtk->getVtkId(), VTK_EMPTY_CELL);
3681       myFacePool->destroy(facevtk);
3682       return 0;
3683     }
3684     face = facevtk;
3685     adjustmyCellsCapacity(ID);
3686     myCells[ID] = face;
3687     myInfo.myNbQuadTriangles++;
3688
3689     //    if (!registerElement(ID, face)) {
3690     //      RemoveElement(face, false);
3691     //      face = NULL;
3692     //    }
3693     return face;
3694   }
3695 }
3696
3697
3698 //=======================================================================
3699 //function : AddFace
3700 //purpose  :
3701 //=======================================================================
3702 SMDS_MeshFace* SMDS_Mesh::AddFace(const SMDS_MeshNode * n1,
3703                                   const SMDS_MeshNode * n2,
3704                                   const SMDS_MeshNode * n3,
3705                                   const SMDS_MeshNode * n12,
3706                                   const SMDS_MeshNode * n23,
3707                                   const SMDS_MeshNode * n31,
3708                                   const SMDS_MeshNode * nCenter)
3709 {
3710   return SMDS_Mesh::AddFaceWithID(n1,n2,n3,n12,n23,n31,nCenter,
3711                                   myElementIDFactory->GetFreeID());
3712 }
3713
3714 //=======================================================================
3715 //function : AddFaceWithID
3716 //purpose  :
3717 //=======================================================================
3718 SMDS_MeshFace* SMDS_Mesh::AddFaceWithID(int n1, int n2, int n3,
3719                                         int n12,int n23,int n31, int nCenter, int ID)
3720 {
3721   return SMDS_Mesh::AddFaceWithID
3722     ((SMDS_MeshNode *)myNodeIDFactory->MeshElement(n1) ,
3723      (SMDS_MeshNode *)myNodeIDFactory->MeshElement(n2) ,
3724      (SMDS_MeshNode *)myNodeIDFactory->MeshElement(n3) ,
3725      (SMDS_MeshNode *)myNodeIDFactory->MeshElement(n12),
3726      (SMDS_MeshNode *)myNodeIDFactory->MeshElement(n23),
3727      (SMDS_MeshNode *)myNodeIDFactory->MeshElement(n31),
3728      (SMDS_MeshNode *)myNodeIDFactory->MeshElement(nCenter),
3729      ID);
3730 }
3731
3732 //=======================================================================
3733 //function : AddFaceWithID
3734 //purpose  :
3735 //=======================================================================
3736 SMDS_MeshFace* SMDS_Mesh::AddFaceWithID(const SMDS_MeshNode * n1,
3737                                         const SMDS_MeshNode * n2,
3738                                         const SMDS_MeshNode * n3,
3739                                         const SMDS_MeshNode * n12,
3740                                         const SMDS_MeshNode * n23,
3741                                         const SMDS_MeshNode * n31,
3742                                         const SMDS_MeshNode * nCenter,
3743                                         int ID)
3744 {
3745   if ( !n1 || !n2 || !n3 || !n12 || !n23 || !n31 || !nCenter) return 0;
3746   if(hasConstructionEdges()) {
3747     // creation quadratic edges - not implemented
3748     return 0;
3749   }
3750   else
3751   {
3752     // --- retrieve nodes ID
3753     myNodeIds.resize(7);
3754     myNodeIds[0] = n1->getVtkId();
3755     myNodeIds[1] = n2->getVtkId();
3756     myNodeIds[2] = n3->getVtkId();
3757     myNodeIds[3] = n12->getVtkId();
3758     myNodeIds[4] = n23->getVtkId();
3759     myNodeIds[5] = n31->getVtkId();
3760     myNodeIds[6] = nCenter->getVtkId();
3761
3762     SMDS_MeshFace * face = 0;
3763     SMDS_VtkFace *facevtk = myFacePool->getNew();
3764     facevtk->init(myNodeIds, this);
3765     if (!this->registerElement(ID,facevtk))
3766     {
3767       this->myGrid->GetCellTypesArray()->SetValue(facevtk->getVtkId(), VTK_EMPTY_CELL);
3768       myFacePool->destroy(facevtk);
3769       return 0;
3770     }
3771     face = facevtk;
3772     adjustmyCellsCapacity(ID);
3773     myCells[ID] = face;
3774     myInfo.myNbBiQuadTriangles++;
3775
3776     //    if (!registerElement(ID, face)) {
3777     //      RemoveElement(face, false);
3778     //      face = NULL;
3779     //    }
3780     return face;
3781   }
3782 }
3783
3784
3785 //=======================================================================
3786 //function : AddFace
3787 //purpose  :
3788 //=======================================================================
3789 SMDS_MeshFace* SMDS_Mesh::AddFace(const SMDS_MeshNode * n1,
3790                                   const SMDS_MeshNode * n2,
3791                                   const SMDS_MeshNode * n3,
3792                                   const SMDS_MeshNode * n4,
3793                                   const SMDS_MeshNode * n12,
3794                                   const SMDS_MeshNode * n23,
3795                                   const SMDS_MeshNode * n34,
3796                                   const SMDS_MeshNode * n41)
3797 {
3798   return SMDS_Mesh::AddFaceWithID(n1,n2,n3,n4,n12,n23,n34,n41,
3799                                   myElementIDFactory->GetFreeID());
3800 }
3801
3802 //=======================================================================
3803 //function : AddFaceWithID
3804 //purpose  :
3805 //=======================================================================
3806 SMDS_MeshFace* SMDS_Mesh::AddFaceWithID(int n1, int n2, int n3, int n4,
3807                                         int n12,int n23,int n34,int n41, int ID)
3808 {
3809   return SMDS_Mesh::AddFaceWithID
3810     ((SMDS_MeshNode *)myNodeIDFactory->MeshElement(n1) ,
3811      (SMDS_MeshNode *)myNodeIDFactory->MeshElement(n2) ,
3812      (SMDS_MeshNode *)myNodeIDFactory->MeshElement(n3) ,
3813      (SMDS_MeshNode *)myNodeIDFactory->MeshElement(n4) ,
3814      (SMDS_MeshNode *)myNodeIDFactory->MeshElement(n12),
3815      (SMDS_MeshNode *)myNodeIDFactory->MeshElement(n23),
3816      (SMDS_MeshNode *)myNodeIDFactory->MeshElement(n34),
3817      (SMDS_MeshNode *)myNodeIDFactory->MeshElement(n41),
3818      ID);
3819 }
3820
3821 //=======================================================================
3822 //function : AddFaceWithID
3823 //purpose  :
3824 //=======================================================================
3825 SMDS_MeshFace* SMDS_Mesh::AddFaceWithID(const SMDS_MeshNode * n1,
3826                                         const SMDS_MeshNode * n2,
3827                                         const SMDS_MeshNode * n3,
3828                                         const SMDS_MeshNode * n4,
3829                                         const SMDS_MeshNode * n12,
3830                                         const SMDS_MeshNode * n23,
3831                                         const SMDS_MeshNode * n34,
3832                                         const SMDS_MeshNode * n41,
3833                                         int ID)
3834 {
3835   if ( !n1 || !n2 || !n3 || !n4 || !n12 || !n23 || !n34 || !n41) return 0;
3836   if(hasConstructionEdges()) {
3837     // creation quadratic edges - not implemented
3838     return 0;
3839   }
3840   else
3841   {
3842     // --- retrieve nodes ID
3843     myNodeIds.resize(8);
3844     myNodeIds[0] = n1->getVtkId();
3845     myNodeIds[1] = n2->getVtkId();
3846     myNodeIds[2] = n3->getVtkId();
3847     myNodeIds[3] = n4->getVtkId();
3848     myNodeIds[4] = n12->getVtkId();
3849     myNodeIds[5] = n23->getVtkId();
3850     myNodeIds[6] = n34->getVtkId();
3851     myNodeIds[7] = n41->getVtkId();
3852
3853     SMDS_MeshFace * face = 0;
3854     SMDS_VtkFace *facevtk = myFacePool->getNew();
3855     facevtk->init(myNodeIds, this);
3856     if (!this->registerElement(ID,facevtk))
3857     {
3858       this->myGrid->GetCellTypesArray()->SetValue(facevtk->getVtkId(), VTK_EMPTY_CELL);
3859       myFacePool->destroy(facevtk);
3860       return 0;
3861     }
3862     face = facevtk;
3863     adjustmyCellsCapacity(ID);
3864     myCells[ID] = face;
3865     myInfo.myNbQuadQuadrangles++;
3866
3867     //    if (!registerElement(ID, face)) {
3868     //      RemoveElement(face, false);
3869     //      face = NULL;
3870     //    }
3871     return face;
3872   }
3873 }
3874
3875 //=======================================================================
3876 //function : AddFace
3877 //purpose  :
3878 //=======================================================================
3879 SMDS_MeshFace* SMDS_Mesh::AddFace(const SMDS_MeshNode * n1,
3880                                   const SMDS_MeshNode * n2,
3881                                   const SMDS_MeshNode * n3,
3882                                   const SMDS_MeshNode * n4,
3883                                   const SMDS_MeshNode * n12,
3884                                   const SMDS_MeshNode * n23,
3885                                   const SMDS_MeshNode * n34,
3886                                   const SMDS_MeshNode * n41,
3887                                   const SMDS_MeshNode * nCenter)
3888 {
3889   return SMDS_Mesh::AddFaceWithID(n1,n2,n3,n4,n12,n23,n34,n41,nCenter,
3890                                   myElementIDFactory->GetFreeID());
3891 }
3892
3893 //=======================================================================
3894 //function : AddFaceWithID
3895 //purpose  :
3896 //=======================================================================
3897 SMDS_MeshFace* SMDS_Mesh::AddFaceWithID(int n1, int n2, int n3, int n4,
3898                                         int n12,int n23,int n34,int n41, int nCenter, int ID)
3899 {
3900   return SMDS_Mesh::AddFaceWithID
3901     ((SMDS_MeshNode *)myNodeIDFactory->MeshElement(n1) ,
3902      (SMDS_MeshNode *)myNodeIDFactory->MeshElement(n2) ,
3903      (SMDS_MeshNode *)myNodeIDFactory->MeshElement(n3) ,
3904      (SMDS_MeshNode *)myNodeIDFactory->MeshElement(n4) ,
3905      (SMDS_MeshNode *)myNodeIDFactory->MeshElement(n12),
3906      (SMDS_MeshNode *)myNodeIDFactory->MeshElement(n23),
3907      (SMDS_MeshNode *)myNodeIDFactory->MeshElement(n34),
3908      (SMDS_MeshNode *)myNodeIDFactory->MeshElement(n41),
3909      (SMDS_MeshNode *)myNodeIDFactory->MeshElement(nCenter),
3910      ID);
3911 }
3912
3913 //=======================================================================
3914 //function : AddFaceWithID
3915 //purpose  :
3916 //=======================================================================
3917 SMDS_MeshFace* SMDS_Mesh::AddFaceWithID(const SMDS_MeshNode * n1,
3918                                         const SMDS_MeshNode * n2,
3919                                         const SMDS_MeshNode * n3,
3920                                         const SMDS_MeshNode * n4,
3921                                         const SMDS_MeshNode * n12,
3922                                         const SMDS_MeshNode * n23,
3923                                         const SMDS_MeshNode * n34,
3924                                         const SMDS_MeshNode * n41,
3925                                         const SMDS_MeshNode * nCenter,
3926                                         int ID)
3927 {
3928   if ( !n1 || !n2 || !n3 || !n4 || !n12 || !n23 || !n34 || !n41 || !nCenter) return 0;
3929   if(hasConstructionEdges()) {
3930     // creation quadratic edges - not implemented
3931     return 0;
3932   }
3933   else
3934   {
3935     // --- retrieve nodes ID
3936     myNodeIds.resize(9);
3937     myNodeIds[0] = n1->getVtkId();
3938     myNodeIds[1] = n2->getVtkId();
3939     myNodeIds[2] = n3->getVtkId();
3940     myNodeIds[3] = n4->getVtkId();
3941     myNodeIds[4] = n12->getVtkId();
3942     myNodeIds[5] = n23->getVtkId();
3943     myNodeIds[6] = n34->getVtkId();
3944     myNodeIds[7] = n41->getVtkId();
3945     myNodeIds[8] = nCenter->getVtkId();
3946
3947     SMDS_MeshFace * face = 0;
3948     SMDS_VtkFace *facevtk = myFacePool->getNew();
3949     facevtk->init(myNodeIds, this);
3950     if (!this->registerElement(ID,facevtk))
3951     {
3952       this->myGrid->GetCellTypesArray()->SetValue(facevtk->getVtkId(), VTK_EMPTY_CELL);
3953       myFacePool->destroy(facevtk);
3954       return 0;
3955     }
3956     face = facevtk;
3957     adjustmyCellsCapacity(ID);
3958     myCells[ID] = face;
3959     myInfo.myNbBiQuadQuadrangles++;
3960
3961     //    if (!registerElement(ID, face)) {
3962     //      RemoveElement(face, false);
3963     //      face = NULL;
3964     //    }
3965     return face;
3966   }
3967 }
3968
3969
3970 //=======================================================================
3971 //function : AddVolume
3972 //purpose  :
3973 //=======================================================================
3974 SMDS_MeshVolume* SMDS_Mesh::AddVolume(const SMDS_MeshNode * n1,
3975                                       const SMDS_MeshNode * n2,
3976                                       const SMDS_MeshNode * n3,
3977                                       const SMDS_MeshNode * n4,
3978                                       const SMDS_MeshNode * n12,
3979                                       const SMDS_MeshNode * n23,
3980                                       const SMDS_MeshNode * n31,
3981                                       const SMDS_MeshNode * n14,
3982                                       const SMDS_MeshNode * n24,
3983                                       const SMDS_MeshNode * n34)
3984 {
3985   int ID = myElementIDFactory->GetFreeID();
3986   SMDS_MeshVolume * v = SMDS_Mesh::AddVolumeWithID(n1, n2, n3, n4, n12, n23,
3987                                                    n31, n14, n24, n34, ID);
3988   if(v==NULL) myElementIDFactory->ReleaseID(ID);
3989   return v;
3990 }
3991
3992 //=======================================================================
3993 //function : AddVolumeWithID
3994 //purpose  :
3995 //=======================================================================
3996 SMDS_MeshVolume* SMDS_Mesh::AddVolumeWithID(int n1, int n2, int n3, int n4,
3997                                             int n12,int n23,int n31,
3998                                             int n14,int n24,int n34, int ID)
3999 {
4000   return SMDS_Mesh::AddVolumeWithID
4001     ((SMDS_MeshNode*) myNodeIDFactory->MeshElement(n1) ,
4002      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n2) ,
4003      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n3) ,
4004      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n4) ,
4005      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n12),
4006      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n23),
4007      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n31),
4008      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n14),
4009      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n24),
4010      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n34),
4011      ID);
4012 }
4013
4014 //=======================================================================
4015 //function : AddVolumeWithID
4016 //purpose  : 2d order tetrahedron of 10 nodes
4017 //=======================================================================
4018 SMDS_MeshVolume* SMDS_Mesh::AddVolumeWithID(const SMDS_MeshNode * n1,
4019                                             const SMDS_MeshNode * n2,
4020                                             const SMDS_MeshNode * n3,
4021                                             const SMDS_MeshNode * n4,
4022                                             const SMDS_MeshNode * n12,
4023                                             const SMDS_MeshNode * n23,
4024                                             const SMDS_MeshNode * n31,
4025                                             const SMDS_MeshNode * n14,
4026                                             const SMDS_MeshNode * n24,
4027                                             const SMDS_MeshNode * n34,
4028                                             int ID)
4029 {
4030   if ( !n1 || !n2 || !n3 || !n4 || !n12 || !n23 || !n31 || !n14 || !n24 || !n34)
4031     return 0;
4032   if(hasConstructionFaces()) {
4033     // creation quadratic faces - not implemented
4034     return 0;
4035   }
4036   // --- retrieve nodes ID
4037   myNodeIds.resize(10);
4038   myNodeIds[0] = n1->getVtkId();
4039   myNodeIds[1] = n3->getVtkId();
4040   myNodeIds[2] = n2->getVtkId();
4041   myNodeIds[3] = n4->getVtkId();
4042
4043   myNodeIds[4] = n31->getVtkId();
4044   myNodeIds[5] = n23->getVtkId();
4045   myNodeIds[6] = n12->getVtkId();
4046
4047   myNodeIds[7] = n14->getVtkId();
4048   myNodeIds[8] = n34->getVtkId();
4049   myNodeIds[9] = n24->getVtkId();
4050
4051   SMDS_VtkVolume *volvtk = myVolumePool->getNew();
4052   volvtk->init(myNodeIds, this);
4053   if (!this->registerElement(ID,volvtk))
4054   {
4055     this->myGrid->GetCellTypesArray()->SetValue(volvtk->getVtkId(), VTK_EMPTY_CELL);
4056     myVolumePool->destroy(volvtk);
4057     return 0;
4058   }
4059   adjustmyCellsCapacity(ID);
4060   myCells[ID] = volvtk;
4061   myInfo.myNbQuadTetras++;
4062
4063   //  if (!registerElement(ID, volvtk)) {
4064   //    RemoveElement(volvtk, false);
4065   //    volvtk = NULL;
4066   //  }
4067   return volvtk;
4068 }
4069
4070
4071 //=======================================================================
4072 //function : AddVolume
4073 //purpose  :
4074 //=======================================================================
4075 SMDS_MeshVolume* SMDS_Mesh::AddVolume(const SMDS_MeshNode * n1,
4076                                       const SMDS_MeshNode * n2,
4077                                       const SMDS_MeshNode * n3,
4078                                       const SMDS_MeshNode * n4,
4079                                       const SMDS_MeshNode * n5,
4080                                       const SMDS_MeshNode * n12,
4081                                       const SMDS_MeshNode * n23,
4082                                       const SMDS_MeshNode * n34,
4083                                       const SMDS_MeshNode * n41,
4084                                       const SMDS_MeshNode * n15,
4085                                       const SMDS_MeshNode * n25,
4086                                       const SMDS_MeshNode * n35,
4087                                       const SMDS_MeshNode * n45)
4088 {
4089   int ID = myElementIDFactory->GetFreeID();
4090   SMDS_MeshVolume * v =
4091     SMDS_Mesh::AddVolumeWithID(n1, n2, n3, n4, n5, n12, n23, n34, n41,
4092                                n15, n25, n35, n45, ID);
4093   if(v==NULL) myElementIDFactory->ReleaseID(ID);
4094   return v;
4095 }
4096
4097 //=======================================================================
4098 //function : AddVolumeWithID
4099 //purpose  :
4100 //=======================================================================
4101 SMDS_MeshVolume* SMDS_Mesh::AddVolumeWithID(int n1, int n2, int n3, int n4, int n5,
4102                                             int n12,int n23,int n34,int n41,
4103                                             int n15,int n25,int n35,int n45, int ID)
4104 {
4105   return SMDS_Mesh::AddVolumeWithID
4106     ((SMDS_MeshNode*) myNodeIDFactory->MeshElement(n1) ,
4107      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n2) ,
4108      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n3) ,
4109      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n4) ,
4110      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n5) ,
4111      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n12),
4112      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n23),
4113      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n34),
4114      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n41),
4115      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n15),
4116      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n25),
4117      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n35),
4118      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n45),
4119      ID);
4120 }
4121
4122 //=======================================================================
4123 //function : AddVolumeWithID
4124 //purpose  : 2d order pyramid of 13 nodes
4125 //=======================================================================
4126 SMDS_MeshVolume* SMDS_Mesh::AddVolumeWithID(const SMDS_MeshNode * n1,
4127                                             const SMDS_MeshNode * n2,
4128                                             const SMDS_MeshNode * n3,
4129                                             const SMDS_MeshNode * n4,
4130                                             const SMDS_MeshNode * n5,
4131                                             const SMDS_MeshNode * n12,
4132                                             const SMDS_MeshNode * n23,
4133                                             const SMDS_MeshNode * n34,
4134                                             const SMDS_MeshNode * n41,
4135                                             const SMDS_MeshNode * n15,
4136                                             const SMDS_MeshNode * n25,
4137                                             const SMDS_MeshNode * n35,
4138                                             const SMDS_MeshNode * n45,
4139                                             int ID)
4140 {
4141   if (!n1 || !n2 || !n3 || !n4 || !n5 || !n12 || !n23 ||
4142       !n34 || !n41 || !n15 || !n25 || !n35 || !n45)
4143     return 0;
4144   if(hasConstructionFaces()) {
4145     // creation quadratic faces - not implemented
4146     return 0;
4147   }
4148   // --- retrieve nodes ID
4149   myNodeIds.resize(13);
4150   myNodeIds[0] = n1->getVtkId();
4151   myNodeIds[1] = n4->getVtkId();
4152   myNodeIds[2] = n3->getVtkId();
4153   myNodeIds[3] = n2->getVtkId();
4154   myNodeIds[4] = n5->getVtkId();
4155
4156   myNodeIds[5] = n41->getVtkId();
4157   myNodeIds[6] = n34->getVtkId();
4158   myNodeIds[7] = n23->getVtkId();
4159   myNodeIds[8] = n12->getVtkId();
4160
4161   myNodeIds[9] = n15->getVtkId();
4162   myNodeIds[10] = n45->getVtkId();
4163   myNodeIds[11] = n35->getVtkId();
4164   myNodeIds[12] = n25->getVtkId();
4165
4166   SMDS_VtkVolume *volvtk = myVolumePool->getNew();
4167   volvtk->init(myNodeIds, this);
4168   if (!this->registerElement(ID,volvtk))
4169   {
4170     this->myGrid->GetCellTypesArray()->SetValue(volvtk->getVtkId(), VTK_EMPTY_CELL);
4171     myVolumePool->destroy(volvtk);
4172     return 0;
4173   }
4174   adjustmyCellsCapacity(ID);
4175   myCells[ID] = volvtk;
4176   myInfo.myNbQuadPyramids++;
4177
4178   //  if (!registerElement(ID, volvtk)) {
4179   //    RemoveElement(volvtk, false);
4180   //    volvtk = NULL;
4181   //  }
4182   return volvtk;
4183 }
4184
4185
4186 //=======================================================================
4187 //function : AddVolume
4188 //purpose  :
4189 //=======================================================================
4190 SMDS_MeshVolume* SMDS_Mesh::AddVolume(const SMDS_MeshNode * n1,
4191                                       const SMDS_MeshNode * n2,
4192                                       const SMDS_MeshNode * n3,
4193                                       const SMDS_MeshNode * n4,
4194                                       const SMDS_MeshNode * n5,
4195                                       const SMDS_MeshNode * n6,
4196                                       const SMDS_MeshNode * n12,
4197                                       const SMDS_MeshNode * n23,
4198                                       const SMDS_MeshNode * n31,
4199                                       const SMDS_MeshNode * n45,
4200                                       const SMDS_MeshNode * n56,
4201                                       const SMDS_MeshNode * n64,
4202                                       const SMDS_MeshNode * n14,
4203                                       const SMDS_MeshNode * n25,
4204                                       const SMDS_MeshNode * n36)
4205 {
4206   int ID = myElementIDFactory->GetFreeID();
4207   SMDS_MeshVolume * v =
4208     SMDS_Mesh::AddVolumeWithID(n1, n2, n3, n4, n5, n6, n12, n23, n31,
4209                                n45, n56, n64, n14, n25, n36, ID);
4210   if(v==NULL) myElementIDFactory->ReleaseID(ID);
4211   return v;
4212 }
4213
4214 //=======================================================================
4215 //function : AddVolumeWithID
4216 //purpose  :
4217 //=======================================================================
4218 SMDS_MeshVolume* SMDS_Mesh::AddVolumeWithID(int n1, int n2, int n3,
4219                                             int n4, int n5, int n6,
4220                                             int n12,int n23,int n31,
4221                                             int n45,int n56,int n64,
4222                                             int n14,int n25,int n36, int ID)
4223 {
4224   return SMDS_Mesh::AddVolumeWithID
4225     ((SMDS_MeshNode*) myNodeIDFactory->MeshElement(n1) ,
4226      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n2) ,
4227      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n3) ,
4228      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n4) ,
4229      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n5) ,
4230      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n6) ,
4231      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n12),
4232      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n23),
4233      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n31),
4234      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n45),
4235      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n56),
4236      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n64),
4237      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n14),
4238      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n25),
4239      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n36),
4240      ID);
4241 }
4242
4243 //=======================================================================
4244 //function : AddVolumeWithID
4245 //purpose  : 2d order Pentahedron with 15 nodes
4246 //=======================================================================
4247 SMDS_MeshVolume* SMDS_Mesh::AddVolumeWithID(const SMDS_MeshNode * n1,
4248                                             const SMDS_MeshNode * n2,
4249                                             const SMDS_MeshNode * n3,
4250                                             const SMDS_MeshNode * n4,
4251                                             const SMDS_MeshNode * n5,
4252                                             const SMDS_MeshNode * n6,
4253                                             const SMDS_MeshNode * n12,
4254                                             const SMDS_MeshNode * n23,
4255                                             const SMDS_MeshNode * n31,
4256                                             const SMDS_MeshNode * n45,
4257                                             const SMDS_MeshNode * n56,
4258                                             const SMDS_MeshNode * n64,
4259                                             const SMDS_MeshNode * n14,
4260                                             const SMDS_MeshNode * n25,
4261                                             const SMDS_MeshNode * n36,
4262                                             int ID)
4263 {
4264   if (!n1 || !n2 || !n3 || !n4 || !n5 || !n6 || !n12 || !n23 ||
4265       !n31 || !n45 || !n56 || !n64 || !n14 || !n25 || !n36)
4266     return 0;
4267   if(hasConstructionFaces()) {
4268     // creation quadratic faces - not implemented
4269     return 0;
4270   }
4271   // --- retrieve nodes ID
4272   myNodeIds.resize(15);
4273   myNodeIds[0] = n1->getVtkId();
4274   myNodeIds[1] = n2->getVtkId();
4275   myNodeIds[2] = n3->getVtkId();
4276
4277   myNodeIds[3] = n4->getVtkId();
4278   myNodeIds[4] = n5->getVtkId();
4279   myNodeIds[5] = n6->getVtkId();
4280
4281   myNodeIds[6] = n12->getVtkId();
4282   myNodeIds[7] = n23->getVtkId();
4283   myNodeIds[8] = n31->getVtkId();
4284
4285   myNodeIds[9] = n45->getVtkId();
4286   myNodeIds[10] = n56->getVtkId();
4287   myNodeIds[11] = n64->getVtkId();
4288
4289   myNodeIds[12] = n14->getVtkId();
4290   myNodeIds[13] = n25->getVtkId();
4291   myNodeIds[14] = n36->getVtkId();
4292
4293   SMDS_VtkVolume *volvtk = myVolumePool->getNew();
4294   volvtk->init(myNodeIds, this);
4295   if (!this->registerElement(ID,volvtk))
4296   {
4297     this->myGrid->GetCellTypesArray()->SetValue(volvtk->getVtkId(), VTK_EMPTY_CELL);
4298     myVolumePool->destroy(volvtk);
4299     return 0;
4300   }
4301   adjustmyCellsCapacity(ID);
4302   myCells[ID] = volvtk;
4303   myInfo.myNbQuadPrisms++;
4304
4305   //  if (!registerElement(ID, volvtk)) {
4306   //    RemoveElement(volvtk, false);
4307   //    volvtk = NULL;
4308   //  }
4309   return volvtk;
4310 }
4311
4312
4313 //=======================================================================
4314 //function : AddVolume
4315 //purpose  :
4316 //=======================================================================
4317 SMDS_MeshVolume* SMDS_Mesh::AddVolume(const SMDS_MeshNode * n1,
4318                                       const SMDS_MeshNode * n2,
4319                                       const SMDS_MeshNode * n3,
4320                                       const SMDS_MeshNode * n4,
4321                                       const SMDS_MeshNode * n5,
4322                                       const SMDS_MeshNode * n6,
4323                                       const SMDS_MeshNode * n7,
4324                                       const SMDS_MeshNode * n8,
4325                                       const SMDS_MeshNode * n12,
4326                                       const SMDS_MeshNode * n23,
4327                                       const SMDS_MeshNode * n34,
4328                                       const SMDS_MeshNode * n41,
4329                                       const SMDS_MeshNode * n56,
4330                                       const SMDS_MeshNode * n67,
4331                                       const SMDS_MeshNode * n78,
4332                                       const SMDS_MeshNode * n85,
4333                                       const SMDS_MeshNode * n15,
4334                                       const SMDS_MeshNode * n26,
4335                                       const SMDS_MeshNode * n37,
4336                                       const SMDS_MeshNode * n48)
4337 {
4338   int ID = myElementIDFactory->GetFreeID();
4339   SMDS_MeshVolume * v =
4340     SMDS_Mesh::AddVolumeWithID(n1, n2, n3, n4, n5, n6, n7, n8, n12, n23, n34, n41,
4341                                n56, n67, n78, n85, n15, n26, n37, n48, ID);
4342   if(v==NULL) myElementIDFactory->ReleaseID(ID);
4343   return v;
4344 }
4345
4346 //=======================================================================
4347 //function : AddVolumeWithID
4348 //purpose  :
4349 //=======================================================================
4350 SMDS_MeshVolume* SMDS_Mesh::AddVolumeWithID(int n1, int n2, int n3, int n4,
4351                                             int n5, int n6, int n7, int n8,
4352                                             int n12,int n23,int n34,int n41,
4353                                             int n56,int n67,int n78,int n85,
4354                                             int n15,int n26,int n37,int n48, int ID)
4355 {
4356   return SMDS_Mesh::AddVolumeWithID
4357     ((SMDS_MeshNode*) myNodeIDFactory->MeshElement(n1),
4358      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n2),
4359      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n3),
4360      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n4),
4361      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n5),
4362      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n6),
4363      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n7),
4364      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n8),
4365      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n12),
4366      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n23),
4367      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n34),
4368      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n41),
4369      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n56),
4370      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n67),
4371      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n78),
4372      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n85),
4373      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n15),
4374      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n26),
4375      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n37),
4376      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n48),
4377      ID);
4378 }
4379
4380 //=======================================================================
4381 //function : AddVolumeWithID
4382 //purpose  : 2d order Hexahedrons with 20 nodes
4383 //=======================================================================
4384 SMDS_MeshVolume* SMDS_Mesh::AddVolumeWithID(const SMDS_MeshNode * n1,
4385                                             const SMDS_MeshNode * n2,
4386                                             const SMDS_MeshNode * n3,
4387                                             const SMDS_MeshNode * n4,
4388                                             const SMDS_MeshNode * n5,
4389                                             const SMDS_MeshNode * n6,
4390                                             const SMDS_MeshNode * n7,
4391                                             const SMDS_MeshNode * n8,
4392                                             const SMDS_MeshNode * n12,
4393                                             const SMDS_MeshNode * n23,
4394                                             const SMDS_MeshNode * n34,
4395                                             const SMDS_MeshNode * n41,
4396                                             const SMDS_MeshNode * n56,
4397                                             const SMDS_MeshNode * n67,
4398                                             const SMDS_MeshNode * n78,
4399                                             const SMDS_MeshNode * n85,
4400                                             const SMDS_MeshNode * n15,
4401                                             const SMDS_MeshNode * n26,
4402                                             const SMDS_MeshNode * n37,
4403                                             const SMDS_MeshNode * n48,
4404                                             int ID)
4405 {
4406   if (!n1 || !n2 || !n3 || !n4 || !n5 || !n6 || !n7 || !n8 || !n12 || !n23 ||
4407       !n34 || !n41 || !n56 || !n67 || !n78 || !n85 || !n15 || !n26 || !n37 || !n48)
4408     return 0;
4409   if(hasConstructionFaces()) {
4410     return 0;
4411     // creation quadratic faces - not implemented
4412   }
4413   // --- retrieve nodes ID
4414   myNodeIds.resize(20);
4415   myNodeIds[0] = n1->getVtkId();
4416   myNodeIds[1] = n4->getVtkId();
4417   myNodeIds[2] = n3->getVtkId();
4418   myNodeIds[3] = n2->getVtkId();
4419
4420   myNodeIds[4] = n5->getVtkId();
4421   myNodeIds[5] = n8->getVtkId();
4422   myNodeIds[6] = n7->getVtkId();
4423   myNodeIds[7] = n6->getVtkId();
4424
4425   myNodeIds[8] = n41->getVtkId();
4426   myNodeIds[9] = n34->getVtkId();
4427   myNodeIds[10] = n23->getVtkId();
4428   myNodeIds[11] = n12->getVtkId();
4429
4430   myNodeIds[12] = n85->getVtkId();
4431   myNodeIds[13] = n78->getVtkId();
4432   myNodeIds[14] = n67->getVtkId();
4433   myNodeIds[15] = n56->getVtkId();
4434
4435   myNodeIds[16] = n15->getVtkId();
4436   myNodeIds[17] = n48->getVtkId();
4437   myNodeIds[18] = n37->getVtkId();
4438   myNodeIds[19] = n26->getVtkId();
4439
4440   SMDS_VtkVolume *volvtk = myVolumePool->getNew();
4441   volvtk->init(myNodeIds, this);
4442   if (!this->registerElement(ID,volvtk))
4443   {
4444     this->myGrid->GetCellTypesArray()->SetValue(volvtk->getVtkId(), VTK_EMPTY_CELL);
4445     myVolumePool->destroy(volvtk);
4446     return 0;
4447   }
4448   adjustmyCellsCapacity(ID);
4449   myCells[ID] = volvtk;
4450   myInfo.myNbQuadHexas++;
4451
4452   //  if (!registerElement(ID, volvtk)) {
4453   //    RemoveElement(volvtk, false);
4454   //    volvtk = NULL;
4455   //  }
4456   return volvtk;
4457 }
4458
4459 //=======================================================================
4460 //function : AddVolume
4461 //purpose  :
4462 //=======================================================================
4463 SMDS_MeshVolume* SMDS_Mesh::AddVolume(const SMDS_MeshNode * n1,
4464                                       const SMDS_MeshNode * n2,
4465                                       const SMDS_MeshNode * n3,
4466                                       const SMDS_MeshNode * n4,
4467                                       const SMDS_MeshNode * n5,
4468                                       const SMDS_MeshNode * n6,
4469                                       const SMDS_MeshNode * n7,
4470                                       const SMDS_MeshNode * n8,
4471                                       const SMDS_MeshNode * n12,
4472                                       const SMDS_MeshNode * n23,
4473                                       const SMDS_MeshNode * n34,
4474                                       const SMDS_MeshNode * n41,
4475                                       const SMDS_MeshNode * n56,
4476                                       const SMDS_MeshNode * n67,
4477                                       const SMDS_MeshNode * n78,
4478                                       const SMDS_MeshNode * n85,
4479                                       const SMDS_MeshNode * n15,
4480                                       const SMDS_MeshNode * n26,
4481                                       const SMDS_MeshNode * n37,
4482                                       const SMDS_MeshNode * n48,
4483                                       const SMDS_MeshNode * n1234,
4484                                       const SMDS_MeshNode * n1256,
4485                                       const SMDS_MeshNode * n2367,
4486                                       const SMDS_MeshNode * n3478,
4487                                       const SMDS_MeshNode * n1458,
4488                                       const SMDS_MeshNode * n5678,
4489                                       const SMDS_MeshNode * nCenter)
4490 {
4491   int ID = myElementIDFactory->GetFreeID();
4492   SMDS_MeshVolume * v =
4493     SMDS_Mesh::AddVolumeWithID(n1, n2, n3, n4, n5, n6, n7, n8, n12, n23, n34, n41,
4494                                n56, n67, n78, n85, n15, n26, n37, n48,
4495                                n1234, n1256, n2367, n3478, n1458, n5678, nCenter,
4496                                ID);
4497   if(v==NULL) myElementIDFactory->ReleaseID(ID);
4498   return v;
4499 }
4500
4501 //=======================================================================
4502 //function : AddVolumeWithID
4503 //purpose  :
4504 //=======================================================================
4505 SMDS_MeshVolume* SMDS_Mesh::AddVolumeWithID(int n1, int n2, int n3, int n4,
4506                                             int n5, int n6, int n7, int n8,
4507                                             int n12,int n23,int n34,int n41,
4508                                             int n56,int n67,int n78,int n85,
4509                                             int n15,int n26,int n37,int n48,
4510                                             int n1234,int n1256,int n2367,int n3478,
4511                                             int n1458,int n5678,int nCenter, int ID)
4512 {
4513   return SMDS_Mesh::AddVolumeWithID
4514     ((SMDS_MeshNode*) myNodeIDFactory->MeshElement(n1),
4515      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n2),
4516      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n3),
4517      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n4),
4518      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n5),
4519      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n6),
4520      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n7),
4521      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n8),
4522      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n12),
4523      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n23),
4524      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n34),
4525      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n41),
4526      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n56),
4527      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n67),
4528      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n78),
4529      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n85),
4530      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n15),
4531      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n26),
4532      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n37),
4533      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n48),
4534      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n1234),
4535      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n1256),
4536      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n2367),
4537      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n3478),
4538      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n1458),
4539      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n5678),
4540      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(nCenter),
4541      ID);
4542 }
4543
4544 //=======================================================================
4545 //function : AddVolumeWithID
4546 //purpose  : 2d order Hexahedrons with 20 nodes
4547 //=======================================================================
4548 SMDS_MeshVolume* SMDS_Mesh::AddVolumeWithID(const SMDS_MeshNode * n1,
4549                                             const SMDS_MeshNode * n2,
4550                                             const SMDS_MeshNode * n3,
4551                                             const SMDS_MeshNode * n4,
4552                                             const SMDS_MeshNode * n5,
4553                                             const SMDS_MeshNode * n6,
4554                                             const SMDS_MeshNode * n7,
4555                                             const SMDS_MeshNode * n8,
4556                                             const SMDS_MeshNode * n12,
4557                                             const SMDS_MeshNode * n23,
4558                                             const SMDS_MeshNode * n34,
4559                                             const SMDS_MeshNode * n41,
4560                                             const SMDS_MeshNode * n56,
4561                                             const SMDS_MeshNode * n67,
4562                                             const SMDS_MeshNode * n78,
4563                                             const SMDS_MeshNode * n85,
4564                                             const SMDS_MeshNode * n15,
4565                                             const SMDS_MeshNode * n26,
4566                                             const SMDS_MeshNode * n37,
4567                                             const SMDS_MeshNode * n48,
4568                                             const SMDS_MeshNode * n1234,
4569                                             const SMDS_MeshNode * n1256,
4570                                             const SMDS_MeshNode * n2367,
4571                                             const SMDS_MeshNode * n3478,
4572                                             const SMDS_MeshNode * n1458,
4573                                             const SMDS_MeshNode * n5678,
4574                                             const SMDS_MeshNode * nCenter,
4575                                             int ID)
4576 {
4577   if (!n1 || !n2 || !n3 || !n4 || !n5 || !n6 || !n7 || !n8 || !n12 || !n23 ||
4578       !n34 || !n41 || !n56 || !n67 || !n78 || !n85 || !n15 || !n26 || !n37 || !n48 ||
4579       !n1234 || !n1256 || !n2367 || !n3478 || !n1458 || !n5678 || !nCenter )
4580     return 0;
4581   if(hasConstructionFaces()) {
4582     return 0;
4583     // creation quadratic faces - not implemented
4584   }
4585   // --- retrieve nodes ID
4586   myNodeIds.resize(27);
4587   myNodeIds[0] = n1->getVtkId();
4588   myNodeIds[1] = n4->getVtkId();
4589   myNodeIds[2] = n3->getVtkId();
4590   myNodeIds[3] = n2->getVtkId();
4591
4592   myNodeIds[4] = n5->getVtkId();
4593   myNodeIds[5] = n8->getVtkId();
4594   myNodeIds[6] = n7->getVtkId();
4595   myNodeIds[7] = n6->getVtkId();
4596
4597   myNodeIds[8] = n41->getVtkId();
4598   myNodeIds[9] = n34->getVtkId();
4599   myNodeIds[10] = n23->getVtkId();
4600   myNodeIds[11] = n12->getVtkId();
4601
4602   myNodeIds[12] = n85->getVtkId();
4603   myNodeIds[13] = n78->getVtkId();
4604   myNodeIds[14] = n67->getVtkId();
4605   myNodeIds[15] = n56->getVtkId();
4606
4607   myNodeIds[16] = n15->getVtkId();
4608   myNodeIds[17] = n48->getVtkId();
4609   myNodeIds[18] = n37->getVtkId();
4610   myNodeIds[19] = n26->getVtkId();
4611
4612   myNodeIds[20] = n1256->getVtkId();
4613   myNodeIds[21] = n3478->getVtkId();
4614   myNodeIds[22] = n1458->getVtkId();
4615   myNodeIds[23] = n2367->getVtkId();
4616   myNodeIds[24] = n1234->getVtkId();
4617   myNodeIds[25] = n5678->getVtkId();
4618   myNodeIds[26] = nCenter->getVtkId();
4619
4620   SMDS_VtkVolume *volvtk = myVolumePool->getNew();
4621   volvtk->init(myNodeIds, this);
4622   if (!this->registerElement(ID,volvtk))
4623   {
4624     this->myGrid->GetCellTypesArray()->SetValue(volvtk->getVtkId(), VTK_EMPTY_CELL);
4625     myVolumePool->destroy(volvtk);
4626     return 0;
4627   }
4628   adjustmyCellsCapacity(ID);
4629   myCells[ID] = volvtk;
4630   myInfo.myNbTriQuadHexas++;
4631
4632   return volvtk;
4633 }
4634
4635
4636 void SMDS_Mesh::updateNodeMinMax()
4637 {
4638   myNodeMin = 0;
4639   if (myNodes.size() == 0)
4640   {
4641     myNodeMax=0;
4642     return;
4643   }
4644   while ( !myNodes[myNodeMin] && myNodeMin < (int)myNodes.size() )
4645     myNodeMin++;
4646   myNodeMax=myNodes.size()-1;
4647   while (!myNodes[myNodeMax] && (myNodeMin>=0))
4648     myNodeMin--;
4649 }
4650
4651 void SMDS_Mesh::incrementNodesCapacity(int nbNodes)
4652 {
4653 //  int val = myCellIdSmdsToVtk.size();
4654 //  MESSAGE(" ------------------- resize myCellIdSmdsToVtk " << val << " --> " << val + nbNodes);
4655 //  myCellIdSmdsToVtk.resize(val + nbNodes, -1); // fill new elements with -1
4656   int val = myNodes.size();
4657   myNodes.resize(val +nbNodes, 0);
4658 }
4659
4660 void SMDS_Mesh::incrementCellsCapacity(int nbCells)
4661 {
4662   int val = myCellIdVtkToSmds.size();
4663   myCellIdVtkToSmds.resize(val + nbCells, -1); // fill new elements with -1
4664   val = myCells.size();
4665   myNodes.resize(val +nbCells, 0);
4666 }
4667
4668 void SMDS_Mesh::adjustStructure()
4669 {
4670   myGrid->GetPoints()->GetData()->SetNumberOfTuples(myNodeIDFactory->GetMaxID());
4671 }
4672
4673 void SMDS_Mesh::dumpGrid(string ficdump)
4674 {
4675   //  vtkUnstructuredGridWriter* aWriter = vtkUnstructuredGridWriter::New();
4676   //  aWriter->SetFileName(ficdump.c_str());
4677   //  aWriter->SetInput(myGrid);
4678   //  if(myGrid->GetNumberOfCells())
4679   //  {
4680   //    aWriter->Write();
4681   //  }
4682   //  aWriter->Delete();
4683   ficdump = ficdump + "_connectivity";
4684   ofstream ficcon(ficdump.c_str(), ios::out);
4685   int nbPoints = myGrid->GetNumberOfPoints();
4686   ficcon << "-------------------------------- points " <<  nbPoints << endl;
4687   for (int i=0; i<nbPoints; i++)
4688   {
4689     ficcon << i << " " << *(myGrid->GetPoint(i)) << " " << *(myGrid->GetPoint(i)+1) << " " << " " << *(myGrid->GetPoint(i)+2) << endl;
4690   }
4691   int nbCells = myGrid->GetNumberOfCells();
4692   ficcon << "-------------------------------- cells " <<  nbCells << endl;
4693   for (int i=0; i<nbCells; i++)
4694   {
4695     ficcon << i << " - " << myGrid->GetCell(i)->GetCellType() << " -";
4696     int nbptcell = myGrid->GetCell(i)->GetNumberOfPoints();
4697     vtkIdList *listid = myGrid->GetCell(i)->GetPointIds();
4698     for (int j=0; j<nbptcell; j++)
4699     {
4700       ficcon << " " <<  listid->GetId(j);
4701     }
4702     ficcon << endl;
4703   }
4704   ficcon << "-------------------------------- connectivity " <<  nbPoints << endl;
4705   vtkCellLinks *links = myGrid->GetLinks();
4706   for (int i=0; i<nbPoints; i++)
4707   {
4708     int ncells = links->GetNcells(i);
4709     vtkIdType *cells = links->GetCells(i);
4710     ficcon << i << " - " << ncells << " -";
4711     for (int j=0; j<ncells; j++)
4712     {
4713       ficcon << " " << cells[j];
4714     }
4715     ficcon << endl;
4716   }
4717   ficcon.close();
4718
4719 }
4720
4721 void SMDS_Mesh::compactMesh()
4722 {
4723   this->myCompactTime = this->myModifTime;
4724 }
4725
4726 int SMDS_Mesh::fromVtkToSmds(int vtkid)
4727 {
4728   if (vtkid >= 0 && vtkid < (int)myCellIdVtkToSmds.size())
4729     return myCellIdVtkToSmds[vtkid];
4730   throw SALOME_Exception(LOCALIZED ("vtk id out of bounds"));
4731 }
4732
4733 void SMDS_Mesh::updateBoundingBox()
4734 {
4735   xmin = 0; xmax = 0;
4736   ymin = 0; ymax = 0;
4737   zmin = 0; zmax = 0;
4738   vtkPoints *points = myGrid->GetPoints();
4739   int myNodesSize = this->myNodes.size();
4740   for (int i = 0; i < myNodesSize; i++)
4741     {
4742       if (SMDS_MeshNode *n = myNodes[i])
4743         {
4744           double coords[3];
4745           points->GetPoint(n->myVtkID, coords);
4746           if (coords[0] < xmin) xmin = coords[0];
4747           else if (coords[0] > xmax) xmax = coords[0];
4748           if (coords[1] < ymin) ymin = coords[1];
4749           else if (coords[1] > ymax) ymax = coords[1];
4750           if (coords[2] < zmin) zmin = coords[2];
4751           else if (coords[2] > zmax) zmax = coords[2];
4752         }
4753     }
4754 }
4755
4756 double SMDS_Mesh::getMaxDim()
4757 {
4758   double dmax = 1.e-3;
4759   if ((xmax - xmin) > dmax) dmax = xmax -xmin;
4760   if ((ymax - ymin) > dmax) dmax = ymax -ymin;
4761   if ((zmax - zmin) > dmax) dmax = zmax -zmin;
4762   return dmax;
4763 }
4764
4765 //! modification that needs compact structure and redraw
4766 void SMDS_Mesh::Modified()
4767 {
4768   if (this->myModified)
4769   {
4770     this->myModifTime++;
4771     myModified = false;
4772   }
4773 }
4774
4775 //! get last modification timeStamp
4776 unsigned long SMDS_Mesh::GetMTime() const
4777 {
4778   return this->myModifTime;
4779 }
4780
4781 bool SMDS_Mesh::isCompacted()
4782 {
4783   return this->myCompactTime == this->myModifTime;
4784 }