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