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