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