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                &