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