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