Salome HOME
23080: [CEA 1497] Do not merge a middle node in quadratic with the extreme nodes...
[modules/smesh.git] / src / SMDS / SMDS_Mesh.cxx
1 // Copyright (C) 2007-2015  CEA/DEN, EDF R&D, OPEN CASCADE
2 //
3 // Copyright (C) 2003-2007  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
4 // CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
5 //
6 // This library is free software; you can redistribute it and/or
7 // modify it under the terms of the GNU Lesser General Public
8 // License as published by the Free Software Foundation; either
9 // version 2.1 of the License, or (at your option) any later version.
10 //
11 // This library is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 // Lesser General Public License for more details.
15 //
16 // You should have received a copy of the GNU Lesser General Public
17 // License along with this library; if not, write to the Free Software
18 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
19 //
20 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
21 //
22
23 //  SMESH SMDS : implementation of Salome mesh data structure
24 //
25 #ifdef _MSC_VER
26 #pragma warning(disable:4786)
27 #endif
28
29 #include "SMDS_FaceOfEdges.hxx"
30 #include "SMDS_FaceOfNodes.hxx"
31 #include "SMDS_Mesh.hxx"
32 #include "SMDS_PolygonalFaceOfNodes.hxx"
33 #include "SMDS_PolyhedralVolumeOfNodes.hxx"
34 #include "SMDS_QuadraticEdge.hxx"
35 #include "SMDS_QuadraticFaceOfNodes.hxx"
36 #include "SMDS_QuadraticVolumeOfNodes.hxx"
37 #include "SMDS_SetIterator.hxx"
38 #include "SMDS_SpacePosition.hxx"
39 #include "SMDS_UnstructuredGrid.hxx"
40 #include "SMDS_VolumeOfFaces.hxx"
41 #include "SMDS_VolumeOfNodes.hxx"
42
43 #include "utilities.h"
44
45 #include <vtkUnstructuredGrid.h>
46 #include <vtkUnstructuredGridWriter.h>
47 #include <vtkUnsignedCharArray.h>
48 #include <vtkCell.h>
49 #include <vtkCellLinks.h>
50 #include <vtkIdList.h>
51
52 #include <algorithm>
53 #include <map>
54 #include <iostream>
55 #include <fstream>
56 #include <iterator>
57 using namespace std;
58
59 #ifndef WIN32
60 #include <sys/sysinfo.h>
61 #endif
62
63 // number of added entities to check memory after
64 #define CHECKMEMORY_INTERVAL 100000
65
66 vector<SMDS_Mesh*> SMDS_Mesh::_meshList = vector<SMDS_Mesh*>();
67 int SMDS_Mesh::chunkSize = 1024;
68
69
70 //================================================================================
71 /*!
72  * \brief Raise an exception if free memory (ram+swap) too low
73  * \param doNotRaise - if true, suppres exception, just return free memory size
74  * \retval int - amount of available memory in MB or negative number in failure case
75  */
76 //================================================================================
77
78 int SMDS_Mesh::CheckMemory(const bool doNotRaise) throw (std::bad_alloc)
79 {
80 #ifndef WIN32
81   struct sysinfo si;
82   int err = sysinfo( &si );
83   if ( err )
84     return -1;
85
86   const unsigned long Mbyte = 1024 * 1024;
87
88   static int limit = -1;
89   if ( limit < 0 ) {
90     int status = system("SMDS_MemoryLimit"); // it returns lower limit of free RAM
91     if (status >= 0 ) {
92       limit = WEXITSTATUS(status);
93     }
94     else {
95       double factor = ( si.totalswap == 0 ) ? 0.1 : 0.2;
96       limit = int(( factor * si.totalram * si.mem_unit ) / Mbyte );
97     }
98     if ( limit < 20 )
99       limit = 20;
100     else
101       limit = int ( limit * 1.5 );
102     MESSAGE ( "SMDS_Mesh::CheckMemory() memory limit = " << limit << " MB" );
103   }
104
105   // compute separately to avoid overflow
106   int freeMb =
107     ( si.freeram  * si.mem_unit ) / Mbyte +
108     ( si.freeswap * si.mem_unit ) / Mbyte;
109   //cout << "freeMb = " << freeMb << " limit = " << limit << endl;
110
111   if ( freeMb > limit )
112     return freeMb - limit;
113
114   if ( doNotRaise )
115     return 0;
116
117   MESSAGE ("SMDS_Mesh::CheckMemory() throws as free memory too low: " << freeMb <<" MB" );
118   throw std::bad_alloc();
119 #else
120   return -1;
121 #endif
122 }
123
124 ///////////////////////////////////////////////////////////////////////////////
125 /// Create a new mesh object
126 ///////////////////////////////////////////////////////////////////////////////
127 SMDS_Mesh::SMDS_Mesh()
128   :myParent(NULL),
129    myNodeIDFactory(new SMDS_MeshNodeIDFactory()),
130    myElementIDFactory(new SMDS_MeshElementIDFactory()),
131    myHasConstructionEdges(false), myHasConstructionFaces(false),
132    myHasInverseElements(true),
133    myNodeMin(0), myNodeMax(0),
134    myNodePool(0), myEdgePool(0), myFacePool(0), myVolumePool(0),myBallPool(0),
135    myModified(false), myModifTime(0), myCompactTime(0),
136    xmin(0), xmax(0), ymin(0), ymax(0), zmin(0), zmax(0)
137 {
138   myMeshId = _meshList.size();         // --- index of the mesh to push back in the vector
139   myNodeIDFactory->SetMesh(this);
140   myElementIDFactory->SetMesh(this);
141   _meshList.push_back(this);
142   myNodePool = new ObjectPool<SMDS_MeshNode>(SMDS_Mesh::chunkSize);
143   myEdgePool = new ObjectPool<SMDS_VtkEdge>(SMDS_Mesh::chunkSize);
144   myFacePool = new ObjectPool<SMDS_VtkFace>(SMDS_Mesh::chunkSize);
145   myVolumePool = new ObjectPool<SMDS_VtkVolume>(SMDS_Mesh::chunkSize);
146   myBallPool = new ObjectPool<SMDS_BallElement>(SMDS_Mesh::chunkSize);
147
148   myNodes.clear();
149   myCells.clear();
150   //myCellIdSmdsToVtk.clear();
151   myCellIdVtkToSmds.clear();
152   myGrid = SMDS_UnstructuredGrid::New();
153   myGrid->setSMDS_mesh(this);
154   myGrid->Initialize();
155   myGrid->Allocate();
156   vtkPoints* points = vtkPoints::New();
157   // bug "21125: EDF 1233 SMESH: Degrardation of precision in a test case for quadratic conversion"
158   // Use double type for storing coordinates of nodes instead of float.
159   points->SetDataType(VTK_DOUBLE);
160   points->SetNumberOfPoints(0 /*SMDS_Mesh::chunkSize*/);
161   myGrid->SetPoints( points );
162   points->Delete();
163   myGrid->BuildLinks();
164   this->Modified();
165 }
166
167 ///////////////////////////////////////////////////////////////////////////////
168 /// Create a new child mesh
169 /// Note that the tree structure of SMDS_Mesh seems to be unused in this version
170 /// (2003-09-08) of SMESH
171 ///////////////////////////////////////////////////////////////////////////////
172 SMDS_Mesh::SMDS_Mesh(SMDS_Mesh * parent)
173         :myParent(parent), myNodeIDFactory(parent->myNodeIDFactory),
174          myElementIDFactory(parent->myElementIDFactory),
175          myHasConstructionEdges(false), myHasConstructionFaces(false),
176          myHasInverseElements(true),
177          myNodePool(parent->myNodePool),
178          myEdgePool(parent->myEdgePool),
179          myFacePool(parent->myFacePool),
180          myVolumePool(parent->myVolumePool),
181          myBallPool(parent->myBallPool)
182 {
183 }
184
185 ///////////////////////////////////////////////////////////////////////////////
186 ///Create a submesh and add it to the current mesh
187 ///////////////////////////////////////////////////////////////////////////////
188
189 SMDS_Mesh *SMDS_Mesh::AddSubMesh()
190 {
191         SMDS_Mesh *submesh = new SMDS_Mesh(this);
192         myChildren.insert(myChildren.end(), submesh);
193         return submesh;
194 }
195
196 ///////////////////////////////////////////////////////////////////////////////
197 ///create a MeshNode and add it to the current Mesh
198 ///An ID is automatically assigned to the node.
199 ///@return : The created node
200 ///////////////////////////////////////////////////////////////////////////////
201
202 SMDS_MeshNode * SMDS_Mesh::AddNode(double x, double y, double z)
203 {
204   return SMDS_Mesh::AddNodeWithID(x,y,z,myNodeIDFactory->GetFreeID());
205 }
206
207 ///////////////////////////////////////////////////////////////////////////////
208 ///create a MeshNode and add it to the current Mesh
209 ///@param ID : The ID of the MeshNode to create
210 ///@return : The created node or NULL if a node with this ID already exists
211 ///////////////////////////////////////////////////////////////////////////////
212 SMDS_MeshNode * SMDS_Mesh::AddNodeWithID(double x, double y, double z, int ID)
213 {
214   // find the MeshNode corresponding to ID
215   const SMDS_MeshElement *node = myNodeIDFactory->MeshElement(ID);
216   if(!node){
217     if (ID < 1)
218       {
219         MESSAGE("=============>  Bad Node Id: " << ID);
220         ID = myNodeIDFactory->GetFreeID();
221       }
222     myNodeIDFactory->adjustMaxId(ID);
223     SMDS_MeshNode * node = myNodePool->getNew();
224     node->init(ID, myMeshId, 0, x, y, z);
225
226     if (ID >= myNodes.size())
227     {
228         myNodes.resize(ID+SMDS_Mesh::chunkSize, 0);
229 //         MESSAGE(" ------------------ myNodes resize " << ID << " --> " << ID+SMDS_Mesh::chunkSize);
230     }
231     myNodes[ID] = node;
232     myNodeIDFactory->BindID(ID,node);
233     myInfo.myNbNodes++;
234     myModified = true;
235     this->adjustBoundingBox(x, y, z);
236     return node;
237   }else
238     return NULL;
239 }
240
241 ///////////////////////////////////////////////////////////////////////////////
242 /// create a Mesh0DElement and add it to the current Mesh
243 /// @return : The created Mesh0DElement
244 ///////////////////////////////////////////////////////////////////////////////
245 SMDS_Mesh0DElement* SMDS_Mesh::Add0DElementWithID(int idnode, int ID)
246 {
247   SMDS_MeshNode * node = (SMDS_MeshNode *)myNodeIDFactory->MeshElement(idnode);
248   if (!node) return NULL;
249   return SMDS_Mesh::Add0DElementWithID(node, ID);
250 }
251
252 ///////////////////////////////////////////////////////////////////////////////
253 /// create a Mesh0DElement and add it to the current Mesh
254 /// @return : The created Mesh0DElement
255 ///////////////////////////////////////////////////////////////////////////////
256 SMDS_Mesh0DElement* SMDS_Mesh::Add0DElement(const SMDS_MeshNode * node)
257 {
258   return SMDS_Mesh::Add0DElementWithID(node, myElementIDFactory->GetFreeID());
259 }
260
261 ///////////////////////////////////////////////////////////////////////////////
262 /// Create a new Mesh0DElement and at it to the mesh
263 /// @param idnode ID of the node
264 /// @param ID ID of the 0D element to create
265 /// @return The created 0D element or NULL if an element with this
266 ///         ID already exists or if input node is not found.
267 ///////////////////////////////////////////////////////////////////////////////
268 SMDS_Mesh0DElement* SMDS_Mesh::Add0DElementWithID(const SMDS_MeshNode * n, int ID)
269 {
270   if (!n) return 0;
271
272   if (Nb0DElements() % CHECKMEMORY_INTERVAL == 0) CheckMemory();
273   //MESSAGE("Add0DElementWithID" << ID)
274   SMDS_Mesh0DElement * el0d = new SMDS_Mesh0DElement(n);
275   if (myElementIDFactory->BindID(ID, el0d)) {
276     //SMDS_MeshNode *node = const_cast<SMDS_MeshNode*>(n);
277     //node->AddInverseElement(el0d);// --- fait avec BindID
278     adjustmyCellsCapacity(ID);
279     myCells[ID] = el0d;
280     myInfo.myNb0DElements++;
281     return el0d;
282   }
283
284   delete el0d;
285   return NULL;
286 }
287
288 ///////////////////////////////////////////////////////////////////////////////
289 /// create a Ball and add it to the current Mesh
290 /// @return : The created Ball
291 ///////////////////////////////////////////////////////////////////////////////
292 SMDS_BallElement* SMDS_Mesh::AddBallWithID(int idnode, double diameter, int ID)
293 {
294   SMDS_MeshNode * node = (SMDS_MeshNode *)myNodeIDFactory->MeshElement(idnode);
295   if (!node) return NULL;
296   return SMDS_Mesh::AddBallWithID(node, diameter, ID);
297 }
298
299 ///////////////////////////////////////////////////////////////////////////////
300 /// create a Ball and add it to the current Mesh
301 /// @return : The created Ball
302 ///////////////////////////////////////////////////////////////////////////////
303 SMDS_BallElement* SMDS_Mesh::AddBall(const SMDS_MeshNode * node, double diameter)
304 {
305   return SMDS_Mesh::AddBallWithID(node, diameter, myElementIDFactory->GetFreeID());
306 }
307
308 ///////////////////////////////////////////////////////////////////////////////
309 /// Create a new Ball and at it to the mesh
310 /// @param idnode ID of the node
311 //  @param diameter ball diameter
312 /// @param ID ID of the 0D element to create
313 /// @return The created 0D element or NULL if an element with this
314 ///         ID already exists or if input node is not found.
315 ///////////////////////////////////////////////////////////////////////////////
316 SMDS_BallElement* SMDS_Mesh::AddBallWithID(const SMDS_MeshNode * n, double diameter, int ID)
317 {
318   if (!n) return 0;
319
320   if (NbBalls() % CHECKMEMORY_INTERVAL == 0) CheckMemory();
321
322   SMDS_BallElement *ball = myBallPool->getNew();
323   ball->init(n->getVtkId(), diameter, this);
324   if (!this->registerElement(ID,ball))
325     {
326       this->myGrid->GetCellTypesArray()->SetValue(ball->getVtkId(), VTK_EMPTY_CELL);
327       myBallPool->destroy(ball);
328       return 0;
329     }
330   adjustmyCellsCapacity(ID);
331   myCells[ID] = ball;
332   myInfo.myNbBalls++;
333   return ball;
334 }
335
336 ///////////////////////////////////////////////////////////////////////////////
337 /// create a MeshEdge and add it to the current Mesh
338 /// @return : The created MeshEdge
339 ///////////////////////////////////////////////////////////////////////////////
340
341 SMDS_MeshEdge* SMDS_Mesh::AddEdgeWithID(int idnode1, int idnode2, int ID)
342 {
343   SMDS_MeshNode * node1 = (SMDS_MeshNode *)myNodeIDFactory->MeshElement(idnode1);
344   SMDS_MeshNode * node2 = (SMDS_MeshNode *)myNodeIDFactory->MeshElement(idnode2);
345   if(!node1 || !node2) return NULL;
346   return SMDS_Mesh::AddEdgeWithID(node1, node2, ID);
347 }
348
349 ///////////////////////////////////////////////////////////////////////////////
350 /// create a MeshEdge and add it to the current Mesh
351 /// @return : The created MeshEdge
352 ///////////////////////////////////////////////////////////////////////////////
353
354 SMDS_MeshEdge* SMDS_Mesh::AddEdge(const SMDS_MeshNode * node1,
355                                   const SMDS_MeshNode * node2)
356 {
357   return SMDS_Mesh::AddEdgeWithID(node1, node2, myElementIDFactory->GetFreeID());
358 }
359
360 ///////////////////////////////////////////////////////////////////////////////
361 /// Create a new edge and at it to the mesh
362 /// @param idnode1 ID of the first node
363 /// @param idnode2 ID of the second node
364 /// @param ID ID of the edge to create
365 /// @return The created edge or NULL if an element with this ID already exists or
366 /// if input nodes are not found.
367 ///////////////////////////////////////////////////////////////////////////////
368
369 SMDS_MeshEdge* SMDS_Mesh::AddEdgeWithID(const SMDS_MeshNode * n1,
370                                         const SMDS_MeshNode * n2,
371                                         int ID)
372 {
373   if ( !n1 || !n2 ) return 0;
374   SMDS_MeshEdge * edge = 0;
375
376   // --- retreive nodes ID
377   vector<vtkIdType> nodeIds;
378   nodeIds.clear();
379   nodeIds.push_back(n1->getVtkId());
380   nodeIds.push_back(n2->getVtkId());
381
382   SMDS_VtkEdge *edgevtk = myEdgePool->getNew();
383   edgevtk->init(nodeIds, this);
384   if (!this->registerElement(ID,edgevtk))
385     {
386       this->myGrid->GetCellTypesArray()->SetValue(edgevtk->getVtkId(), VTK_EMPTY_CELL);
387       myEdgePool->destroy(edgevtk);
388       return 0;
389     }
390   edge = edgevtk;
391   adjustmyCellsCapacity(ID);
392   myCells[ID] = edge;
393   myInfo.myNbEdges++;
394
395 //  if (edge && !registerElement(ID, edge))
396 //  {
397 //    RemoveElement(edge, false);
398 //    edge = NULL;
399 //  }
400   return edge;
401 }
402
403 ///////////////////////////////////////////////////////////////////////////////
404 /// Add a triangle defined by its nodes. An ID is automatically affected to the
405 /// Created face
406 ///////////////////////////////////////////////////////////////////////////////
407
408 SMDS_MeshFace* SMDS_Mesh::AddFace(const SMDS_MeshNode * n1,
409                                   const SMDS_MeshNode * n2,
410                                   const SMDS_MeshNode * n3)
411 {
412   return SMDS_Mesh::AddFaceWithID(n1,n2,n3, myElementIDFactory->GetFreeID());
413 }
414
415 ///////////////////////////////////////////////////////////////////////////////
416 /// Add a triangle defined by its nodes IDs
417 ///////////////////////////////////////////////////////////////////////////////
418
419 SMDS_MeshFace* SMDS_Mesh::AddFaceWithID(int idnode1, int idnode2, int idnode3, int ID)
420 {
421   SMDS_MeshNode * node1 = (SMDS_MeshNode *)myNodeIDFactory->MeshElement(idnode1);
422   SMDS_MeshNode * node2 = (SMDS_MeshNode *)myNodeIDFactory->MeshElement(idnode2);
423   SMDS_MeshNode * node3 = (SMDS_MeshNode *)myNodeIDFactory->MeshElement(idnode3);
424   if(!node1 || !node2 || !node3) return NULL;
425   return SMDS_Mesh::AddFaceWithID(node1, node2, node3, ID);
426 }
427
428 ///////////////////////////////////////////////////////////////////////////////
429 /// Add a triangle defined by its nodes
430 ///////////////////////////////////////////////////////////////////////////////
431
432 SMDS_MeshFace* SMDS_Mesh::AddFaceWithID(const SMDS_MeshNode * n1,
433                                         const SMDS_MeshNode * n2,
434                                         const SMDS_MeshNode * n3,
435                                         int ID)
436 {
437   //MESSAGE("AddFaceWithID " << ID)
438   SMDS_MeshFace * face=createTriangle(n1, n2, n3, ID);
439
440 //  if (face && !registerElement(ID, face)) {
441 //    RemoveElement(face, false);
442 //    face = NULL;
443 //  }
444   return face;
445 }
446
447 ///////////////////////////////////////////////////////////////////////////////
448 /// Add a quadrangle defined by its nodes. An ID is automatically affected to the
449 /// created face
450 ///////////////////////////////////////////////////////////////////////////////
451
452 SMDS_MeshFace* SMDS_Mesh::AddFace(const SMDS_MeshNode * n1,
453                                   const SMDS_MeshNode * n2,
454                                   const SMDS_MeshNode * n3,
455                                   const SMDS_MeshNode * n4)
456 {
457   return SMDS_Mesh::AddFaceWithID(n1,n2,n3, n4, myElementIDFactory->GetFreeID());
458 }
459
460 ///////////////////////////////////////////////////////////////////////////////
461 /// Add a quadrangle defined by its nodes IDs
462 ///////////////////////////////////////////////////////////////////////////////
463
464 SMDS_MeshFace* SMDS_Mesh::AddFaceWithID(int idnode1,
465                                         int idnode2,
466                                         int idnode3,
467                                         int idnode4,
468                                         int ID)
469 {
470   SMDS_MeshNode *node1, *node2, *node3, *node4;
471   node1 = (SMDS_MeshNode *)myNodeIDFactory->MeshElement(idnode1);
472   node2 = (SMDS_MeshNode *)myNodeIDFactory->MeshElement(idnode2);
473   node3 = (SMDS_MeshNode *)myNodeIDFactory->MeshElement(idnode3);
474   node4 = (SMDS_MeshNode *)myNodeIDFactory->MeshElement(idnode4);
475   if(!node1 || !node2 || !node3 || !node4) return NULL;
476   return SMDS_Mesh::AddFaceWithID(node1, node2, node3, node4, ID);
477 }
478
479 ///////////////////////////////////////////////////////////////////////////////
480 /// Add a quadrangle defined by its nodes
481 ///////////////////////////////////////////////////////////////////////////////
482
483 SMDS_MeshFace* SMDS_Mesh::AddFaceWithID(const SMDS_MeshNode * n1,
484                                         const SMDS_MeshNode * n2,
485                                         const SMDS_MeshNode * n3,
486                                         const SMDS_MeshNode * n4,
487                                         int ID)
488 {
489   //MESSAGE("AddFaceWithID " << ID);
490   SMDS_MeshFace * face=createQuadrangle(n1, n2, n3, n4, ID);
491
492 //  if (face && !registerElement(ID, face)) {
493 //    RemoveElement(face, false);
494 //    face = NULL;
495 //  }
496   return face;
497 }
498
499 ///////////////////////////////////////////////////////////////////////////////
500 /// Add a triangle defined by its edges. An ID is automatically assigned to the
501 /// Created face
502 ///////////////////////////////////////////////////////////////////////////////
503
504 SMDS_MeshFace* SMDS_Mesh::AddFace(const SMDS_MeshEdge * e1,
505                                   const SMDS_MeshEdge * e2,
506                                   const SMDS_MeshEdge * e3)
507 {
508   if (!hasConstructionEdges())
509     return NULL;
510      //MESSAGE("AddFaceWithID");
511  return AddFaceWithID(e1,e2,e3, myElementIDFactory->GetFreeID());
512 }
513
514 ///////////////////////////////////////////////////////////////////////////////
515 /// Add a triangle defined by its edges
516 ///////////////////////////////////////////////////////////////////////////////
517
518 SMDS_MeshFace* SMDS_Mesh::AddFaceWithID(const SMDS_MeshEdge * e1,
519                                         const SMDS_MeshEdge * e2,
520                                         const SMDS_MeshEdge * e3,
521                                         int ID)
522 {
523   if (!hasConstructionEdges())
524     return NULL;
525   if ( !e1 || !e2 || !e3 ) return 0;
526
527   if ( NbFaces() % CHECKMEMORY_INTERVAL == 0 ) CheckMemory();
528   MESSAGE("AddFaceWithID" << ID);
529
530   SMDS_MeshFace * face = new SMDS_FaceOfEdges(e1,e2,e3);
531   adjustmyCellsCapacity(ID);
532   myCells[ID] = face;
533   myInfo.myNbTriangles++;
534
535   if (!registerElement(ID, face)) {
536     registerElement(myElementIDFactory->GetFreeID(), face);
537     //RemoveElement(face, false);
538     //face = NULL;
539   }
540   return face;
541 }
542
543 ///////////////////////////////////////////////////////////////////////////////
544 /// Add a quadrangle defined by its edges. An ID is automatically assigned to the
545 /// Created face
546 ///////////////////////////////////////////////////////////////////////////////
547
548 SMDS_MeshFace* SMDS_Mesh::AddFace(const SMDS_MeshEdge * e1,
549                                   const SMDS_MeshEdge * e2,
550                                   const SMDS_MeshEdge * e3,
551                                   const SMDS_MeshEdge * e4)
552 {
553   if (!hasConstructionEdges())
554     return NULL;
555      //MESSAGE("AddFaceWithID" );
556  return AddFaceWithID(e1,e2,e3,e4, myElementIDFactory->GetFreeID());
557 }
558
559 ///////////////////////////////////////////////////////////////////////////////
560 /// Add a quadrangle defined by its edges
561 ///////////////////////////////////////////////////////////////////////////////
562
563 SMDS_MeshFace* SMDS_Mesh::AddFaceWithID(const SMDS_MeshEdge * e1,
564                                         const SMDS_MeshEdge * e2,
565                                         const SMDS_MeshEdge * e3,
566                                         const SMDS_MeshEdge * e4,
567                                         int ID)
568 {
569   if (!hasConstructionEdges())
570     return NULL;
571   MESSAGE("AddFaceWithID" << ID);
572   if ( !e1 || !e2 || !e3 || !e4 ) return 0;
573   if ( NbFaces() % CHECKMEMORY_INTERVAL == 0 ) CheckMemory();
574   SMDS_MeshFace * face = new SMDS_FaceOfEdges(e1,e2,e3,e4);
575   adjustmyCellsCapacity(ID);
576   myCells[ID] = face;
577   myInfo.myNbQuadrangles++;
578
579   if (!registerElement(ID, face))
580   {
581     registerElement(myElementIDFactory->GetFreeID(), face);
582     //RemoveElement(face, false);
583     //face = NULL;
584   }
585   return face;
586 }
587
588 ///////////////////////////////////////////////////////////////////////////////
589 ///Create a new tetrahedron and add it to the mesh.
590 ///@return The created tetrahedron
591 ///////////////////////////////////////////////////////////////////////////////
592
593 SMDS_MeshVolume* SMDS_Mesh::AddVolume(const SMDS_MeshNode * n1,
594                                       const SMDS_MeshNode * n2,
595                                       const SMDS_MeshNode * n3,
596                                       const SMDS_MeshNode * n4)
597 {
598   int ID = myElementIDFactory->GetFreeID();
599     //MESSAGE("AddVolumeWithID " << ID);
600   SMDS_MeshVolume * v = SMDS_Mesh::AddVolumeWithID(n1, n2, n3, n4, ID);
601   if(v==NULL) myElementIDFactory->ReleaseID(ID);
602   return v;
603 }
604
605 ///////////////////////////////////////////////////////////////////////////////
606 ///Create a new tetrahedron and add it to the mesh.
607 ///@param ID The ID of the new volume
608 ///@return The created tetrahedron or NULL if an element with this ID already exists
609 ///or if input nodes are not found.
610 ///////////////////////////////////////////////////////////////////////////////
611
612 SMDS_MeshVolume * SMDS_Mesh::AddVolumeWithID(int idnode1,
613                                              int idnode2,
614                                              int idnode3,
615                                              int idnode4,
616                                              int ID)
617 {
618     //MESSAGE("AddVolumeWithID" << ID);
619   SMDS_MeshNode *node1, *node2, *node3, *node4;
620   node1 = (SMDS_MeshNode *)myNodeIDFactory->MeshElement(idnode1);
621   node2 = (SMDS_MeshNode *)myNodeIDFactory->MeshElement(idnode2);
622   node3 = (SMDS_MeshNode *)myNodeIDFactory->MeshElement(idnode3);
623   node4 = (SMDS_MeshNode *)myNodeIDFactory->MeshElement(idnode4);
624   if(!node1 || !node2 || !node3 || !node4) return NULL;
625   return SMDS_Mesh::AddVolumeWithID(node1, node2, node3, node4, ID);
626 }
627
628 ///////////////////////////////////////////////////////////////////////////////
629 ///Create a new tetrahedron and add it to the mesh.
630 ///@param ID The ID of the new volume
631 ///@return The created tetrahedron
632 ///////////////////////////////////////////////////////////////////////////////
633
634 SMDS_MeshVolume* SMDS_Mesh::AddVolumeWithID(const SMDS_MeshNode * n1,
635                                             const SMDS_MeshNode * n2,
636                                             const SMDS_MeshNode * n3,
637                                             const SMDS_MeshNode * n4,
638                                             int ID)
639 {
640   //MESSAGE("AddVolumeWithID " << ID);
641   SMDS_MeshVolume* volume = 0;
642   if ( !n1 || !n2 || !n3 || !n4) return volume;
643   if ( NbVolumes() % CHECKMEMORY_INTERVAL == 0 ) CheckMemory();
644   if(hasConstructionFaces()) {
645     SMDS_MeshFace * f1=FindFaceOrCreate(n1,n2,n3);
646     SMDS_MeshFace * f2=FindFaceOrCreate(n1,n2,n4);
647     SMDS_MeshFace * f3=FindFaceOrCreate(n1,n3,n4);
648     SMDS_MeshFace * f4=FindFaceOrCreate(n2,n3,n4);
649     volume=new SMDS_VolumeOfFaces(f1,f2,f3,f4);
650     adjustmyCellsCapacity(ID);
651     myCells[ID] = volume;
652     myInfo.myNbTetras++;
653   }
654   else if(hasConstructionEdges()) {
655     MESSAGE("Error : Not implemented");
656     return NULL;
657   }
658   else {
659     // --- retrieve nodes ID
660     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 < 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 >= 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 >= 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 >= (myNodes.size() -1))
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 >= 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 == nodes.size() )
2486       {
2487         for ( int 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(
3114         set<const SMDS_MeshElement*>& elements)
3115 {
3116         set<const SMDS_MeshElement*> * toReturn=new set<const SMDS_MeshElement*>();
3117         set<const SMDS_MeshElement*>::iterator itElements=elements.begin();
3118
3119         while(itElements!=elements.end())
3120         {
3121                 SMDS_ElemIteratorPtr itNodes = (*itElements)->nodesIterator();
3122                 itElements++;
3123
3124                 while(itNodes->more())
3125                 {
3126                         const SMDS_MeshNode * n=static_cast<const SMDS_MeshNode*>(itNodes->next());
3127                         SMDS_ElemIteratorPtr itFe = n->GetInverseElementIterator();
3128                         set<const SMDS_MeshElement*> s;
3129                         while(itFe->more())
3130                           s.insert(itFe->next());
3131                         if(s==elements) toReturn->insert(n);
3132                 }
3133         }
3134         return toReturn;
3135 }
3136
3137 ///////////////////////////////////////////////////////////////////////////////
3138 ///Find the children of an element that are made of given nodes
3139 ///@param setOfChildren The set in which matching children will be inserted
3140 ///@param element The element were to search matching children
3141 ///@param nodes The nodes that the children must have to be selected
3142 ///////////////////////////////////////////////////////////////////////////////
3143 void SMDS_Mesh::addChildrenWithNodes(set<const SMDS_MeshElement*>& setOfChildren,
3144                                      const SMDS_MeshElement *      element,
3145                                      set<const SMDS_MeshElement*>& nodes)
3146 {
3147   switch(element->GetType())
3148     {
3149     case SMDSAbs_Node:
3150       MESSAGE("Internal Error: This should not happen");
3151       break;
3152     case SMDSAbs_0DElement:
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     }
3204 }
3205
3206 ///////////////////////////////////////////////////////////////////////////////
3207 ///@param elem The element to delete
3208 ///@param removenodes if true remaining nodes will be removed
3209 ///////////////////////////////////////////////////////////////////////////////
3210 void SMDS_Mesh::RemoveElement(const SMDS_MeshElement * elem,
3211                               const bool removenodes)
3212 {
3213   list<const SMDS_MeshElement *> removedElems;
3214   list<const SMDS_MeshElement *> removedNodes;
3215   RemoveElement( elem, removedElems, removedNodes, removenodes );
3216 }
3217
3218 ///////////////////////////////////////////////////////////////////////////////
3219 ///@param elem The element to delete
3220 ///@param removedElems to be filled with all removed elements
3221 ///@param removedNodes to be filled with all removed nodes
3222 ///@param removenodes if true remaining nodes will be removed
3223 ///////////////////////////////////////////////////////////////////////////////
3224 void SMDS_Mesh::RemoveElement(const SMDS_MeshElement *        elem,
3225                               list<const SMDS_MeshElement *>& removedElems,
3226                               list<const SMDS_MeshElement *>& removedNodes,
3227                               bool                            removenodes)
3228 {
3229   //MESSAGE("SMDS_Mesh::RemoveElement " << elem->getVtkId() << " " << removenodes);
3230   // get finite elements built on elem
3231   set<const SMDS_MeshElement*> * s1;
3232   if (    (elem->GetType() == SMDSAbs_0DElement)
3233       || ((elem->GetType() == SMDSAbs_Edge) && !hasConstructionEdges())
3234       || ((elem->GetType() == SMDSAbs_Face) && !hasConstructionFaces())
3235       ||  (elem->GetType() == SMDSAbs_Volume) )
3236     {
3237       s1 = new set<const SMDS_MeshElement*> ();
3238       s1->insert(elem);
3239     }
3240   else
3241     s1 = getFinitElements(elem);
3242
3243   // get exclusive nodes (which would become free afterwards)
3244   set<const SMDS_MeshElement*> * s2;
3245   if (elem->GetType() == SMDSAbs_Node) // a node is removed
3246     {
3247       // do not remove nodes except elem
3248       s2 = new set<const SMDS_MeshElement*> ();
3249       s2->insert(elem);
3250       removenodes = true;
3251     }
3252   else
3253     s2 = getExclusiveNodes(*s1);
3254
3255   // form the set of finite and construction elements to remove
3256   set<const SMDS_MeshElement*> s3;
3257   set<const SMDS_MeshElement*>::iterator it = s1->begin();
3258   while (it != s1->end())
3259     {
3260       addChildrenWithNodes(s3, *it, *s2);
3261       s3.insert(*it);
3262       it++;
3263     }
3264   if (elem->GetType() != SMDSAbs_Node)
3265     s3.insert(elem);
3266
3267   // remove finite and construction elements
3268   it = s3.begin();
3269   while (it != s3.end())
3270     {
3271       // Remove element from <InverseElements> of its nodes
3272       SMDS_ElemIteratorPtr itn = (*it)->nodesIterator();
3273       while (itn->more())
3274         {
3275           SMDS_MeshNode * n = static_cast<SMDS_MeshNode *> (const_cast<SMDS_MeshElement *> (itn->next()));
3276           n->RemoveInverseElement((*it));
3277         }
3278       int IdToRemove = (*it)->GetID();
3279       int vtkid = (*it)->getVtkId();
3280       //MESSAGE("elem Id to remove " << IdToRemove << " vtkid " << vtkid <<
3281       //        " vtktype " << (*it)->GetVtkType() << " type " << (*it)->GetType());
3282       switch ((*it)->GetType())
3283       {
3284         case SMDSAbs_Node:
3285           MYASSERT("Internal Error: This should not happen")
3286           ;
3287           break;
3288         case SMDSAbs_0DElement:
3289           if (IdToRemove >= 0)
3290             {
3291               myCells[IdToRemove] = 0; // -PR- ici ou dans myElementIDFactory->ReleaseID ?
3292               myInfo.remove(*it);
3293             }
3294           removedElems.push_back((*it));
3295           myElementIDFactory->ReleaseID(IdToRemove, vtkid);
3296           delete (*it);
3297           break;
3298         case SMDSAbs_Edge:
3299           if (IdToRemove >= 0)
3300             {
3301               myCells[IdToRemove] = 0;
3302               myInfo.RemoveEdge(*it);
3303             }
3304           removedElems.push_back((*it));
3305           myElementIDFactory->ReleaseID(IdToRemove, vtkid);
3306           if (const SMDS_VtkEdge* vtkElem = dynamic_cast<const SMDS_VtkEdge*>(*it))
3307             myEdgePool->destroy((SMDS_VtkEdge*) vtkElem);
3308           else
3309             delete (*it);
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             delete (*it);
3323           break;
3324         case SMDSAbs_Volume:
3325           if (IdToRemove >= 0)
3326             {
3327               myCells[IdToRemove] = 0;
3328               myInfo.RemoveVolume(*it);
3329             }
3330           removedElems.push_back((*it));
3331           myElementIDFactory->ReleaseID(IdToRemove, vtkid);
3332           if (const SMDS_VtkVolume* vtkElem = dynamic_cast<const SMDS_VtkVolume*>(*it))
3333             myVolumePool->destroy((SMDS_VtkVolume*) vtkElem);
3334           else
3335             delete (*it);
3336           break;
3337         case SMDSAbs_Ball:
3338           if (IdToRemove >= 0)
3339             {
3340               myCells[IdToRemove] = 0;
3341               myInfo.remove(*it);
3342             }
3343           removedElems.push_back((*it));
3344           myElementIDFactory->ReleaseID(IdToRemove, vtkid);
3345           if (const SMDS_BallElement* vtkElem = dynamic_cast<const SMDS_BallElement*>(*it))
3346             myBallPool->destroy(const_cast<SMDS_BallElement*>( vtkElem ));
3347           else
3348             delete (*it);
3349           break;
3350       }
3351       if (vtkid >= 0)
3352         {
3353           //MESSAGE("VTK_EMPTY_CELL in " << vtkid);
3354           this->myGrid->GetCellTypesArray()->SetValue(vtkid, VTK_EMPTY_CELL);
3355         }
3356       it++;
3357     }
3358
3359   // remove exclusive (free) nodes
3360   if (removenodes)
3361     {
3362       it = s2->begin();
3363       while (it != s2->end())
3364         {
3365           int IdToRemove = (*it)->GetID();
3366           //MESSAGE( "SMDS: RM node " << IdToRemove);
3367           if (IdToRemove >= 0)
3368             {
3369               myNodes[IdToRemove] = 0;
3370               myInfo.myNbNodes--;
3371             }
3372           myNodeIDFactory->ReleaseID((*it)->GetID(), (*it)->getVtkId());
3373           removedNodes.push_back((*it));
3374           if (const SMDS_MeshNode* vtkElem = dynamic_cast<const SMDS_MeshNode*>(*it))
3375           {
3376             ((SMDS_MeshNode*)vtkElem)->SetPosition(SMDS_SpacePosition::originSpacePosition());
3377             myNodePool->destroy((SMDS_MeshNode*) vtkElem);
3378           }
3379           else
3380             delete (*it);
3381           it++;
3382         }
3383     }
3384
3385   delete s2;
3386   delete s1;
3387 }
3388
3389
3390 ///////////////////////////////////////////////////////////////////////////////
3391 ///@param elem The element to delete
3392 ///////////////////////////////////////////////////////////////////////////////
3393 void SMDS_Mesh::RemoveFreeElement(const SMDS_MeshElement * elem)
3394 {
3395   int elemId = elem->GetID();
3396   int vtkId = elem->getVtkId();
3397   //MESSAGE("RemoveFreeElement " << elemId);
3398   SMDSAbs_ElementType aType = elem->GetType();
3399   SMDS_MeshElement* todest = (SMDS_MeshElement*)(elem);
3400   if (aType == SMDSAbs_Node) {
3401     //MESSAGE("Remove free node " << elemId);
3402     // only free node can be removed by this method
3403     const SMDS_MeshNode* n = static_cast<SMDS_MeshNode*>(todest);
3404     SMDS_ElemIteratorPtr itFe = n->GetInverseElementIterator();
3405     if (!itFe->more()) { // free node
3406       myNodes[elemId] = 0;
3407       myInfo.myNbNodes--;
3408       ((SMDS_MeshNode*) n)->SetPosition(SMDS_SpacePosition::originSpacePosition());
3409       ((SMDS_MeshNode*) n)->SMDS_MeshElement::init( -1, -1, -1 ); // avoid reuse
3410       myNodePool->destroy(static_cast<SMDS_MeshNode*>(todest));
3411       myNodeIDFactory->ReleaseID(elemId, vtkId);
3412     }
3413   } else {
3414     if (hasConstructionEdges() || hasConstructionFaces())
3415       // this methods is only for meshes without descendants
3416       return;
3417
3418     //MESSAGE("Remove free element " << elemId);
3419     // Remove element from <InverseElements> of its nodes
3420     SMDS_ElemIteratorPtr itn = elem->nodesIterator();
3421     while (itn->more()) {
3422       SMDS_MeshNode * n = static_cast<SMDS_MeshNode *>
3423         (const_cast<SMDS_MeshElement *>(itn->next()));
3424       n->RemoveInverseElement(elem);
3425     }
3426
3427     // in meshes without descendants elements are always free
3428      switch (aType) {
3429     case SMDSAbs_0DElement:
3430       myCells[elemId] = 0;
3431       myInfo.remove(elem);
3432       delete elem;
3433       break;
3434     case SMDSAbs_Edge:
3435       myCells[elemId] = 0;
3436       myInfo.RemoveEdge(elem);
3437       myEdgePool->destroy(static_cast<SMDS_VtkEdge*>(todest));
3438       break;
3439     case SMDSAbs_Face:
3440       myCells[elemId] = 0;
3441       myInfo.RemoveFace(elem);
3442       myFacePool->destroy(static_cast<SMDS_VtkFace*>(todest));
3443       break;
3444     case SMDSAbs_Volume:
3445       myCells[elemId] = 0;
3446       myInfo.RemoveVolume(elem);
3447       myVolumePool->destroy(static_cast<SMDS_VtkVolume*>(todest));
3448       break;
3449     case SMDSAbs_Ball:
3450       myCells[elemId] = 0;
3451       myInfo.remove(elem);
3452       myBallPool->destroy(static_cast<SMDS_BallElement*>(todest));
3453       break;
3454     default:
3455       break;
3456     }
3457     myElementIDFactory->ReleaseID(elemId, vtkId);
3458
3459     this->myGrid->GetCellTypesArray()->SetValue(vtkId, VTK_EMPTY_CELL);
3460     // --- to do: keep vtkid in a list of reusable cells
3461   }
3462 }
3463
3464 /*!
3465  * Checks if the element is present in mesh.
3466  * Useful to determine dead pointers.
3467  */
3468 bool SMDS_Mesh::Contains (const SMDS_MeshElement* elem) const
3469 {
3470   // we should not imply on validity of *elem, so iterate on containers
3471   // of all types in the hope of finding <elem> somewhere there
3472   SMDS_NodeIteratorPtr itn = nodesIterator();
3473   while (itn->more())
3474     if (elem == itn->next())
3475       return true;
3476   SMDS_ElemIteratorPtr ite = elementsIterator();
3477   while (ite->more())
3478     if (elem == ite->next())
3479       return true;
3480   return false;
3481 }
3482
3483 //=======================================================================
3484 //function : MaxNodeID
3485 //purpose  :
3486 //=======================================================================
3487
3488 int SMDS_Mesh::MaxNodeID() const
3489 {
3490   return myNodeMax;
3491 }
3492
3493 //=======================================================================
3494 //function : MinNodeID
3495 //purpose  :
3496 //=======================================================================
3497
3498 int SMDS_Mesh::MinNodeID() const
3499 {
3500   return myNodeMin;
3501 }
3502
3503 //=======================================================================
3504 //function : MaxElementID
3505 //purpose  :
3506 //=======================================================================
3507
3508 int SMDS_Mesh::MaxElementID() const
3509 {
3510   return myElementIDFactory->GetMaxID();
3511 }
3512
3513 //=======================================================================
3514 //function : MinElementID
3515 //purpose  :
3516 //=======================================================================
3517
3518 int SMDS_Mesh::MinElementID() const
3519 {
3520   return myElementIDFactory->GetMinID();
3521 }
3522
3523 //=======================================================================
3524 //function : Renumber
3525 //purpose  : Renumber all nodes or elements.
3526 //=======================================================================
3527
3528 void SMDS_Mesh::Renumber (const bool isNodes, const int  startID, const int  deltaID)
3529 {
3530     MESSAGE("Renumber");
3531   if ( deltaID == 0 )
3532     return;
3533
3534   SMDS_MeshNodeIDFactory * idFactory =
3535     isNodes ? myNodeIDFactory : myElementIDFactory;
3536
3537   // get existing elements in the order of ID increasing
3538   map<int,SMDS_MeshElement*> elemMap;
3539   SMDS_ElemIteratorPtr idElemIt = idFactory->elementsIterator();
3540   while ( idElemIt->more() ) {
3541     SMDS_MeshElement* elem = const_cast<SMDS_MeshElement*>(idElemIt->next());
3542     int id = elem->GetID();
3543     elemMap.insert(map<int,SMDS_MeshElement*>::value_type(id, elem));
3544   }
3545   // release their ids
3546   map<int,SMDS_MeshElement*>::iterator elemIt = elemMap.begin();
3547   idFactory->Clear();
3548 //   for ( ; elemIt != elemMap.end(); elemIt++ )
3549 //   {
3550 //     int id = (*elemIt).first;
3551 //     idFactory->ReleaseID( id );
3552 //   }
3553   // set new IDs
3554   int ID = startID;
3555   elemIt = elemMap.begin();
3556   for ( ; elemIt != elemMap.end(); elemIt++ )
3557   {
3558     idFactory->BindID( ID, (*elemIt).second );
3559     ID += deltaID;
3560   }
3561 }
3562
3563 //=======================================================================
3564 //function : GetElementType
3565 //purpose  : Return type of element or node with id
3566 //=======================================================================
3567
3568 SMDSAbs_ElementType SMDS_Mesh::GetElementType( const int id, const bool iselem ) const
3569 {
3570   SMDS_MeshElement* elem = 0;
3571   if( iselem )
3572     elem = myElementIDFactory->MeshElement( id );
3573   else
3574     elem = myNodeIDFactory->MeshElement( id );
3575
3576   if( !elem )
3577   {
3578     //throw SALOME_Exception(LOCALIZED ("this element isn't exist"));
3579     return SMDSAbs_All;
3580   }
3581   else
3582     return elem->GetType();
3583 }
3584
3585
3586
3587 //********************************************************************
3588 //********************************************************************
3589 //********                                                   *********
3590 //*****       Methods for addition of quadratic elements        ******
3591 //********                                                   *********
3592 //********************************************************************
3593 //********************************************************************
3594
3595 //=======================================================================
3596 //function : AddEdgeWithID
3597 //purpose  :
3598 //=======================================================================
3599 SMDS_MeshEdge* SMDS_Mesh::AddEdgeWithID(int n1, int n2, int n12, int ID)
3600 {
3601   return SMDS_Mesh::AddEdgeWithID
3602     ((SMDS_MeshNode*) myNodeIDFactory->MeshElement(n1),
3603      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n2),
3604      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n12),
3605      ID);
3606 }
3607
3608 //=======================================================================
3609 //function : AddEdge
3610 //purpose  :
3611 //=======================================================================
3612 SMDS_MeshEdge* SMDS_Mesh::AddEdge(const SMDS_MeshNode* n1,
3613                                   const SMDS_MeshNode* n2,
3614                                   const SMDS_MeshNode* n12)
3615 {
3616   return SMDS_Mesh::AddEdgeWithID(n1, n2, n12, myElementIDFactory->GetFreeID());
3617 }
3618
3619 //=======================================================================
3620 //function : AddEdgeWithID
3621 //purpose  :
3622 //=======================================================================
3623 SMDS_MeshEdge* SMDS_Mesh::AddEdgeWithID(const SMDS_MeshNode * n1,
3624                                         const SMDS_MeshNode * n2,
3625                                         const SMDS_MeshNode * n12,
3626                                         int ID)
3627 {
3628   if ( !n1 || !n2 || !n12 ) return 0;
3629
3630   // --- retrieve nodes ID
3631   myNodeIds.resize(3);
3632   myNodeIds[0] = n1->getVtkId();
3633   myNodeIds[1] = n2->getVtkId();
3634   myNodeIds[2] = n12->getVtkId();
3635
3636   SMDS_MeshEdge * edge = 0;
3637   SMDS_VtkEdge *edgevtk = myEdgePool->getNew();
3638   edgevtk->init(myNodeIds, this);
3639   if (!this->registerElement(ID,edgevtk))
3640   {
3641     this->myGrid->GetCellTypesArray()->SetValue(edgevtk->getVtkId(), VTK_EMPTY_CELL);
3642     myEdgePool->destroy(edgevtk);
3643     return 0;
3644   }
3645   edge = edgevtk;
3646   adjustmyCellsCapacity(ID);
3647   myCells[ID] = edge;
3648   myInfo.myNbQuadEdges++;
3649
3650   //  if (!registerElement(ID, edge)) {
3651   //        RemoveElement(edge, false);
3652   //        edge = NULL;
3653   //  }
3654   return edge;
3655
3656 }
3657
3658
3659 //=======================================================================
3660 //function : AddFace
3661 //purpose  :
3662 //=======================================================================
3663 SMDS_MeshFace* SMDS_Mesh::AddFace(const SMDS_MeshNode * n1,
3664                                   const SMDS_MeshNode * n2,
3665                                   const SMDS_MeshNode * n3,
3666                                   const SMDS_MeshNode * n12,
3667                                   const SMDS_MeshNode * n23,
3668                                   const SMDS_MeshNode * n31)
3669 {
3670   return SMDS_Mesh::AddFaceWithID(n1,n2,n3,n12,n23,n31,
3671                                   myElementIDFactory->GetFreeID());
3672 }
3673
3674 //=======================================================================
3675 //function : AddFaceWithID
3676 //purpose  :
3677 //=======================================================================
3678 SMDS_MeshFace* SMDS_Mesh::AddFaceWithID(int n1, int n2, int n3,
3679                                         int n12,int n23,int n31, int ID)
3680 {
3681   return SMDS_Mesh::AddFaceWithID
3682     ((SMDS_MeshNode *)myNodeIDFactory->MeshElement(n1) ,
3683      (SMDS_MeshNode *)myNodeIDFactory->MeshElement(n2) ,
3684      (SMDS_MeshNode *)myNodeIDFactory->MeshElement(n3) ,
3685      (SMDS_MeshNode *)myNodeIDFactory->MeshElement(n12),
3686      (SMDS_MeshNode *)myNodeIDFactory->MeshElement(n23),
3687      (SMDS_MeshNode *)myNodeIDFactory->MeshElement(n31),
3688      ID);
3689 }
3690
3691 //=======================================================================
3692 //function : AddFaceWithID
3693 //purpose  :
3694 //=======================================================================
3695 SMDS_MeshFace* SMDS_Mesh::AddFaceWithID(const SMDS_MeshNode * n1,
3696                                         const SMDS_MeshNode * n2,
3697                                         const SMDS_MeshNode * n3,
3698                                         const SMDS_MeshNode * n12,
3699                                         const SMDS_MeshNode * n23,
3700                                         const SMDS_MeshNode * n31,
3701                                         int ID)
3702 {
3703   if ( !n1 || !n2 || !n3 || !n12 || !n23 || !n31) return 0;
3704   if(hasConstructionEdges()) {
3705     // creation quadratic edges - not implemented
3706     return 0;
3707   }
3708   else
3709   {
3710     // --- retrieve nodes ID
3711     myNodeIds.resize(6);
3712     myNodeIds[0] = n1->getVtkId();
3713     myNodeIds[1] = n2->getVtkId();
3714     myNodeIds[2] = n3->getVtkId();
3715     myNodeIds[3] = n12->getVtkId();
3716     myNodeIds[4] = n23->getVtkId();
3717     myNodeIds[5] = n31->getVtkId();
3718
3719     SMDS_MeshFace * face = 0;
3720     SMDS_VtkFace *facevtk = myFacePool->getNew();
3721     facevtk->init(myNodeIds, this);
3722     if (!this->registerElement(ID,facevtk))
3723     {
3724       this->myGrid->GetCellTypesArray()->SetValue(facevtk->getVtkId(), VTK_EMPTY_CELL);
3725       myFacePool->destroy(facevtk);
3726       return 0;
3727     }
3728     face = facevtk;
3729     adjustmyCellsCapacity(ID);
3730     myCells[ID] = face;
3731     myInfo.myNbQuadTriangles++;
3732
3733     //    if (!registerElement(ID, face)) {
3734     //      RemoveElement(face, false);
3735     //      face = NULL;
3736     //    }
3737     return face;
3738   }
3739 }
3740
3741
3742 //=======================================================================
3743 //function : AddFace
3744 //purpose  :
3745 //=======================================================================
3746 SMDS_MeshFace* SMDS_Mesh::AddFace(const SMDS_MeshNode * n1,
3747                                   const SMDS_MeshNode * n2,
3748                                   const SMDS_MeshNode * n3,
3749                                   const SMDS_MeshNode * n12,
3750                                   const SMDS_MeshNode * n23,
3751                                   const SMDS_MeshNode * n31,
3752                                   const SMDS_MeshNode * nCenter)
3753 {
3754   return SMDS_Mesh::AddFaceWithID(n1,n2,n3,n12,n23,n31,nCenter,
3755                                   myElementIDFactory->GetFreeID());
3756 }
3757
3758 //=======================================================================
3759 //function : AddFaceWithID
3760 //purpose  :
3761 //=======================================================================
3762 SMDS_MeshFace* SMDS_Mesh::AddFaceWithID(int n1, int n2, int n3,
3763                                         int n12,int n23,int n31, int nCenter, int ID)
3764 {
3765   return SMDS_Mesh::AddFaceWithID
3766     ((SMDS_MeshNode *)myNodeIDFactory->MeshElement(n1) ,
3767      (SMDS_MeshNode *)myNodeIDFactory->MeshElement(n2) ,
3768      (SMDS_MeshNode *)myNodeIDFactory->MeshElement(n3) ,
3769      (SMDS_MeshNode *)myNodeIDFactory->MeshElement(n12),
3770      (SMDS_MeshNode *)myNodeIDFactory->MeshElement(n23),
3771      (SMDS_MeshNode *)myNodeIDFactory->MeshElement(n31),
3772      (SMDS_MeshNode *)myNodeIDFactory->MeshElement(nCenter),
3773      ID);
3774 }
3775
3776 //=======================================================================
3777 //function : AddFaceWithID
3778 //purpose  :
3779 //=======================================================================
3780 SMDS_MeshFace* SMDS_Mesh::AddFaceWithID(const SMDS_MeshNode * n1,
3781                                         const SMDS_MeshNode * n2,
3782                                         const SMDS_MeshNode * n3,
3783                                         const SMDS_MeshNode * n12,
3784                                         const SMDS_MeshNode * n23,
3785                                         const SMDS_MeshNode * n31,
3786                                         const SMDS_MeshNode * nCenter,
3787                                         int ID)
3788 {
3789   if ( !n1 || !n2 || !n3 || !n12 || !n23 || !n31 || !nCenter) return 0;
3790   if(hasConstructionEdges()) {
3791     // creation quadratic edges - not implemented
3792     return 0;
3793   }
3794   else
3795   {
3796     // --- retrieve nodes ID
3797     myNodeIds.resize(7);
3798     myNodeIds[0] = n1->getVtkId();
3799     myNodeIds[1] = n2->getVtkId();
3800     myNodeIds[2] = n3->getVtkId();
3801     myNodeIds[3] = n12->getVtkId();
3802     myNodeIds[4] = n23->getVtkId();
3803     myNodeIds[5] = n31->getVtkId();
3804     myNodeIds[6] = nCenter->getVtkId();
3805
3806     SMDS_MeshFace * face = 0;
3807     SMDS_VtkFace *facevtk = myFacePool->getNew();
3808     facevtk->init(myNodeIds, this);
3809     if (!this->registerElement(ID,facevtk))
3810     {
3811       this->myGrid->GetCellTypesArray()->SetValue(facevtk->getVtkId(), VTK_EMPTY_CELL);
3812       myFacePool->destroy(facevtk);
3813       return 0;
3814     }
3815     face = facevtk;
3816     adjustmyCellsCapacity(ID);
3817     myCells[ID] = face;
3818     myInfo.myNbBiQuadTriangles++;
3819
3820     //    if (!registerElement(ID, face)) {
3821     //      RemoveElement(face, false);
3822     //      face = NULL;
3823     //    }
3824     return face;
3825   }
3826 }
3827
3828
3829 //=======================================================================
3830 //function : AddFace
3831 //purpose  :
3832 //=======================================================================
3833 SMDS_MeshFace* SMDS_Mesh::AddFace(const SMDS_MeshNode * n1,
3834                                   const SMDS_MeshNode * n2,
3835                                   const SMDS_MeshNode * n3,
3836                                   const SMDS_MeshNode * n4,
3837                                   const SMDS_MeshNode * n12,
3838                                   const SMDS_MeshNode * n23,
3839                                   const SMDS_MeshNode * n34,
3840                                   const SMDS_MeshNode * n41)
3841 {
3842   return SMDS_Mesh::AddFaceWithID(n1,n2,n3,n4,n12,n23,n34,n41,
3843                                   myElementIDFactory->GetFreeID());
3844 }
3845
3846 //=======================================================================
3847 //function : AddFaceWithID
3848 //purpose  :
3849 //=======================================================================
3850 SMDS_MeshFace* SMDS_Mesh::AddFaceWithID(int n1, int n2, int n3, int n4,
3851                                         int n12,int n23,int n34,int n41, int ID)
3852 {
3853   return SMDS_Mesh::AddFaceWithID
3854     ((SMDS_MeshNode *)myNodeIDFactory->MeshElement(n1) ,
3855      (SMDS_MeshNode *)myNodeIDFactory->MeshElement(n2) ,
3856      (SMDS_MeshNode *)myNodeIDFactory->MeshElement(n3) ,
3857      (SMDS_MeshNode *)myNodeIDFactory->MeshElement(n4) ,
3858      (SMDS_MeshNode *)myNodeIDFactory->MeshElement(n12),
3859      (SMDS_MeshNode *)myNodeIDFactory->MeshElement(n23),
3860      (SMDS_MeshNode *)myNodeIDFactory->MeshElement(n34),
3861      (SMDS_MeshNode *)myNodeIDFactory->MeshElement(n41),
3862      ID);
3863 }
3864
3865 //=======================================================================
3866 //function : AddFaceWithID
3867 //purpose  :
3868 //=======================================================================
3869 SMDS_MeshFace* SMDS_Mesh::AddFaceWithID(const SMDS_MeshNode * n1,
3870                                         const SMDS_MeshNode * n2,
3871                                         const SMDS_MeshNode * n3,
3872                                         const SMDS_MeshNode * n4,
3873                                         const SMDS_MeshNode * n12,
3874                                         const SMDS_MeshNode * n23,
3875                                         const SMDS_MeshNode * n34,
3876                                         const SMDS_MeshNode * n41,
3877                                         int ID)
3878 {
3879   if ( !n1 || !n2 || !n3 || !n4 || !n12 || !n23 || !n34 || !n41) return 0;
3880   if(hasConstructionEdges()) {
3881     // creation quadratic edges - not implemented
3882     return 0;
3883   }
3884   else
3885   {
3886     // --- retrieve nodes ID
3887     myNodeIds.resize(8);
3888     myNodeIds[0] = n1->getVtkId();
3889     myNodeIds[1] = n2->getVtkId();
3890     myNodeIds[2] = n3->getVtkId();
3891     myNodeIds[3] = n4->getVtkId();
3892     myNodeIds[4] = n12->getVtkId();
3893     myNodeIds[5] = n23->getVtkId();
3894     myNodeIds[6] = n34->getVtkId();
3895     myNodeIds[7] = n41->getVtkId();
3896
3897     SMDS_MeshFace * face = 0;
3898     SMDS_VtkFace *facevtk = myFacePool->getNew();
3899     facevtk->init(myNodeIds, this);
3900     if (!this->registerElement(ID,facevtk))
3901     {
3902       this->myGrid->GetCellTypesArray()->SetValue(facevtk->getVtkId(), VTK_EMPTY_CELL);
3903       myFacePool->destroy(facevtk);
3904       return 0;
3905     }
3906     face = facevtk;
3907     adjustmyCellsCapacity(ID);
3908     myCells[ID] = face;
3909     myInfo.myNbQuadQuadrangles++;
3910
3911     //    if (!registerElement(ID, face)) {
3912     //      RemoveElement(face, false);
3913     //      face = NULL;
3914     //    }
3915     return face;
3916   }
3917 }
3918
3919 //=======================================================================
3920 //function : AddFace
3921 //purpose  :
3922 //=======================================================================
3923 SMDS_MeshFace* SMDS_Mesh::AddFace(const SMDS_MeshNode * n1,
3924                                   const SMDS_MeshNode * n2,
3925                                   const SMDS_MeshNode * n3,
3926                                   const SMDS_MeshNode * n4,
3927                                   const SMDS_MeshNode * n12,
3928                                   const SMDS_MeshNode * n23,
3929                                   const SMDS_MeshNode * n34,
3930                                   const SMDS_MeshNode * n41,
3931                                   const SMDS_MeshNode * nCenter)
3932 {
3933   return SMDS_Mesh::AddFaceWithID(n1,n2,n3,n4,n12,n23,n34,n41,nCenter,
3934                                   myElementIDFactory->GetFreeID());
3935 }
3936
3937 //=======================================================================
3938 //function : AddFaceWithID
3939 //purpose  :
3940 //=======================================================================
3941 SMDS_MeshFace* SMDS_Mesh::AddFaceWithID(int n1, int n2, int n3, int n4,
3942                                         int n12,int n23,int n34,int n41, int nCenter, int ID)
3943 {
3944   return SMDS_Mesh::AddFaceWithID
3945     ((SMDS_MeshNode *)myNodeIDFactory->MeshElement(n1) ,
3946      (SMDS_MeshNode *)myNodeIDFactory->MeshElement(n2) ,
3947      (SMDS_MeshNode *)myNodeIDFactory->MeshElement(n3) ,
3948      (SMDS_MeshNode *)myNodeIDFactory->MeshElement(n4) ,
3949      (SMDS_MeshNode *)myNodeIDFactory->MeshElement(n12),
3950      (SMDS_MeshNode *)myNodeIDFactory->MeshElement(n23),
3951      (SMDS_MeshNode *)myNodeIDFactory->MeshElement(n34),
3952      (SMDS_MeshNode *)myNodeIDFactory->MeshElement(n41),
3953      (SMDS_MeshNode *)myNodeIDFactory->MeshElement(nCenter),
3954      ID);
3955 }
3956
3957 //=======================================================================
3958 //function : AddFaceWithID
3959 //purpose  :
3960 //=======================================================================
3961 SMDS_MeshFace* SMDS_Mesh::AddFaceWithID(const SMDS_MeshNode * n1,
3962                                         const SMDS_MeshNode * n2,
3963                                         const SMDS_MeshNode * n3,
3964                                         const SMDS_MeshNode * n4,
3965                                         const SMDS_MeshNode * n12,
3966                                         const SMDS_MeshNode * n23,
3967                                         const SMDS_MeshNode * n34,
3968                                         const SMDS_MeshNode * n41,
3969                                         const SMDS_MeshNode * nCenter,
3970                                         int ID)
3971 {
3972   if ( !n1 || !n2 || !n3 || !n4 || !n12 || !n23 || !n34 || !n41 || !nCenter) return 0;
3973   if(hasConstructionEdges()) {
3974     // creation quadratic edges - not implemented
3975     return 0;
3976   }
3977   else
3978   {
3979     // --- retrieve nodes ID
3980     myNodeIds.resize(9);
3981     myNodeIds[0] = n1->getVtkId();
3982     myNodeIds[1] = n2->getVtkId();
3983     myNodeIds[2] = n3->getVtkId();
3984     myNodeIds[3] = n4->getVtkId();
3985     myNodeIds[4] = n12->getVtkId();
3986     myNodeIds[5] = n23->getVtkId();
3987     myNodeIds[6] = n34->getVtkId();
3988     myNodeIds[7] = n41->getVtkId();
3989     myNodeIds[8] = nCenter->getVtkId();
3990
3991     SMDS_MeshFace * face = 0;
3992     SMDS_VtkFace *facevtk = myFacePool->getNew();
3993     facevtk->init(myNodeIds, this);
3994     if (!this->registerElement(ID,facevtk))
3995     {
3996       this->myGrid->GetCellTypesArray()->SetValue(facevtk->getVtkId(), VTK_EMPTY_CELL);
3997       myFacePool->destroy(facevtk);
3998       return 0;
3999     }
4000     face = facevtk;
4001     adjustmyCellsCapacity(ID);
4002     myCells[ID] = face;
4003     myInfo.myNbBiQuadQuadrangles++;
4004
4005     //    if (!registerElement(ID, face)) {
4006     //      RemoveElement(face, false);
4007     //      face = NULL;
4008     //    }
4009     return face;
4010   }
4011 }
4012
4013
4014 //=======================================================================
4015 //function : AddVolume
4016 //purpose  :
4017 //=======================================================================
4018 SMDS_MeshVolume* SMDS_Mesh::AddVolume(const SMDS_MeshNode * n1,
4019                                       const SMDS_MeshNode * n2,
4020                                       const SMDS_MeshNode * n3,
4021                                       const SMDS_MeshNode * n4,
4022                                       const SMDS_MeshNode * n12,
4023                                       const SMDS_MeshNode * n23,
4024                                       const SMDS_MeshNode * n31,
4025                                       const SMDS_MeshNode * n14,
4026                                       const SMDS_MeshNode * n24,
4027                                       const SMDS_MeshNode * n34)
4028 {
4029   int ID = myElementIDFactory->GetFreeID();
4030   SMDS_MeshVolume * v = SMDS_Mesh::AddVolumeWithID(n1, n2, n3, n4, n12, n23,
4031                                                    n31, n14, n24, n34, ID);
4032   if(v==NULL) myElementIDFactory->ReleaseID(ID);
4033   return v;
4034 }
4035
4036 //=======================================================================
4037 //function : AddVolumeWithID
4038 //purpose  :
4039 //=======================================================================
4040 SMDS_MeshVolume* SMDS_Mesh::AddVolumeWithID(int n1, int n2, int n3, int n4,
4041                                             int n12,int n23,int n31,
4042                                             int n14,int n24,int n34, int ID)
4043 {
4044   return SMDS_Mesh::AddVolumeWithID
4045     ((SMDS_MeshNode*) myNodeIDFactory->MeshElement(n1) ,
4046      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n2) ,
4047      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n3) ,
4048      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n4) ,
4049      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n12),
4050      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n23),
4051      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n31),
4052      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n14),
4053      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n24),
4054      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n34),
4055      ID);
4056 }
4057
4058 //=======================================================================
4059 //function : AddVolumeWithID
4060 //purpose  : 2d order tetrahedron of 10 nodes
4061 //=======================================================================
4062 SMDS_MeshVolume* SMDS_Mesh::AddVolumeWithID(const SMDS_MeshNode * n1,
4063                                             const SMDS_MeshNode * n2,
4064                                             const SMDS_MeshNode * n3,
4065                                             const SMDS_MeshNode * n4,
4066                                             const SMDS_MeshNode * n12,
4067                                             const SMDS_MeshNode * n23,
4068                                             const SMDS_MeshNode * n31,
4069                                             const SMDS_MeshNode * n14,
4070                                             const SMDS_MeshNode * n24,
4071                                             const SMDS_MeshNode * n34,
4072                                             int ID)
4073 {
4074   if ( !n1 || !n2 || !n3 || !n4 || !n12 || !n23 || !n31 || !n14 || !n24 || !n34)
4075     return 0;
4076   if(hasConstructionFaces()) {
4077     // creation quadratic faces - not implemented
4078     return 0;
4079   }
4080   // --- retrieve nodes ID
4081   myNodeIds.resize(10);
4082   myNodeIds[0] = n1->getVtkId();
4083   myNodeIds[1] = n3->getVtkId();
4084   myNodeIds[2] = n2->getVtkId();
4085   myNodeIds[3] = n4->getVtkId();
4086
4087   myNodeIds[4] = n31->getVtkId();
4088   myNodeIds[5] = n23->getVtkId();
4089   myNodeIds[6] = n12->getVtkId();
4090
4091   myNodeIds[7] = n14->getVtkId();
4092   myNodeIds[8] = n34->getVtkId();
4093   myNodeIds[9] = n24->getVtkId();
4094
4095   SMDS_VtkVolume *volvtk = myVolumePool->getNew();
4096   volvtk->init(myNodeIds, this);
4097   if (!this->registerElement(ID,volvtk))
4098   {
4099     this->myGrid->GetCellTypesArray()->SetValue(volvtk->getVtkId(), VTK_EMPTY_CELL);
4100     myVolumePool->destroy(volvtk);
4101     return 0;
4102   }
4103   adjustmyCellsCapacity(ID);
4104   myCells[ID] = volvtk;
4105   myInfo.myNbQuadTetras++;
4106
4107   //  if (!registerElement(ID, volvtk)) {
4108   //    RemoveElement(volvtk, false);
4109   //    volvtk = NULL;
4110   //  }
4111   return volvtk;
4112 }
4113
4114
4115 //=======================================================================
4116 //function : AddVolume
4117 //purpose  :
4118 //=======================================================================
4119 SMDS_MeshVolume* SMDS_Mesh::AddVolume(const SMDS_MeshNode * n1,
4120                                       const SMDS_MeshNode * n2,
4121                                       const SMDS_MeshNode * n3,
4122                                       const SMDS_MeshNode * n4,
4123                                       const SMDS_MeshNode * n5,
4124                                       const SMDS_MeshNode * n12,
4125                                       const SMDS_MeshNode * n23,
4126                                       const SMDS_MeshNode * n34,
4127                                       const SMDS_MeshNode * n41,
4128                                       const SMDS_MeshNode * n15,
4129                                       const SMDS_MeshNode * n25,
4130                                       const SMDS_MeshNode * n35,
4131                                       const SMDS_MeshNode * n45)
4132 {
4133   int ID = myElementIDFactory->GetFreeID();
4134   SMDS_MeshVolume * v =
4135     SMDS_Mesh::AddVolumeWithID(n1, n2, n3, n4, n5, n12, n23, n34, n41,
4136                                n15, n25, n35, n45, ID);
4137   if(v==NULL) myElementIDFactory->ReleaseID(ID);
4138   return v;
4139 }
4140
4141 //=======================================================================
4142 //function : AddVolumeWithID
4143 //purpose  :
4144 //=======================================================================
4145 SMDS_MeshVolume* SMDS_Mesh::AddVolumeWithID(int n1, int n2, int n3, int n4, int n5,
4146                                             int n12,int n23,int n34,int n41,
4147                                             int n15,int n25,int n35,int n45, int ID)
4148 {
4149   return SMDS_Mesh::AddVolumeWithID
4150     ((SMDS_MeshNode*) myNodeIDFactory->MeshElement(n1) ,
4151      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n2) ,
4152      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n3) ,
4153      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n4) ,
4154      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n5) ,
4155      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n12),
4156      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n23),
4157      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n34),
4158      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n41),
4159      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n15),
4160      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n25),
4161      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n35),
4162      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n45),
4163      ID);
4164 }
4165
4166 //=======================================================================
4167 //function : AddVolumeWithID
4168 //purpose  : 2d order pyramid of 13 nodes
4169 //=======================================================================
4170 SMDS_MeshVolume* SMDS_Mesh::AddVolumeWithID(const SMDS_MeshNode * n1,
4171                                             const SMDS_MeshNode * n2,
4172                                             const SMDS_MeshNode * n3,
4173                                             const SMDS_MeshNode * n4,
4174                                             const SMDS_MeshNode * n5,
4175                                             const SMDS_MeshNode * n12,
4176                                             const SMDS_MeshNode * n23,
4177                                             const SMDS_MeshNode * n34,
4178                                             const SMDS_MeshNode * n41,
4179                                             const SMDS_MeshNode * n15,
4180                                             const SMDS_MeshNode * n25,
4181                                             const SMDS_MeshNode * n35,
4182                                             const SMDS_MeshNode * n45,
4183                                             int ID)
4184 {
4185   if (!n1 || !n2 || !n3 || !n4 || !n5 || !n12 || !n23 ||
4186       !n34 || !n41 || !n15 || !n25 || !n35 || !n45)
4187     return 0;
4188   if(hasConstructionFaces()) {
4189     // creation quadratic faces - not implemented
4190     return 0;
4191   }
4192   // --- retrieve nodes ID
4193   myNodeIds.resize(13);
4194   myNodeIds[0] = n1->getVtkId();
4195   myNodeIds[1] = n4->getVtkId();
4196   myNodeIds[2] = n3->getVtkId();
4197   myNodeIds[3] = n2->getVtkId();
4198   myNodeIds[4] = n5->getVtkId();
4199
4200   myNodeIds[5] = n41->getVtkId();
4201   myNodeIds[6] = n34->getVtkId();
4202   myNodeIds[7] = n23->getVtkId();
4203   myNodeIds[8] = n12->getVtkId();
4204
4205   myNodeIds[9] = n15->getVtkId();
4206   myNodeIds[10] = n45->getVtkId();
4207   myNodeIds[11] = n35->getVtkId();
4208   myNodeIds[12] = n25->getVtkId();
4209
4210   SMDS_VtkVolume *volvtk = myVolumePool->getNew();
4211   volvtk->init(myNodeIds, this);
4212   if (!this->registerElement(ID,volvtk))
4213   {
4214     this->myGrid->GetCellTypesArray()->SetValue(volvtk->getVtkId(), VTK_EMPTY_CELL);
4215     myVolumePool->destroy(volvtk);
4216     return 0;
4217   }
4218   adjustmyCellsCapacity(ID);
4219   myCells[ID] = volvtk;
4220   myInfo.myNbQuadPyramids++;
4221
4222   //  if (!registerElement(ID, volvtk)) {
4223   //    RemoveElement(volvtk, false);
4224   //    volvtk = NULL;
4225   //  }
4226   return volvtk;
4227 }
4228
4229
4230 //=======================================================================
4231 //function : AddVolume
4232 //purpose  :
4233 //=======================================================================
4234 SMDS_MeshVolume* SMDS_Mesh::AddVolume(const SMDS_MeshNode * n1,
4235                                       const SMDS_MeshNode * n2,
4236                                       const SMDS_MeshNode * n3,
4237                                       const SMDS_MeshNode * n4,
4238                                       const SMDS_MeshNode * n5,
4239                                       const SMDS_MeshNode * n6,
4240                                       const SMDS_MeshNode * n12,
4241                                       const SMDS_MeshNode * n23,
4242                                       const SMDS_MeshNode * n31,
4243                                       const SMDS_MeshNode * n45,
4244                                       const SMDS_MeshNode * n56,
4245                                       const SMDS_MeshNode * n64,
4246                                       const SMDS_MeshNode * n14,
4247                                       const SMDS_MeshNode * n25,
4248                                       const SMDS_MeshNode * n36)
4249 {
4250   int ID = myElementIDFactory->GetFreeID();
4251   SMDS_MeshVolume * v =
4252     SMDS_Mesh::AddVolumeWithID(n1, n2, n3, n4, n5, n6, n12, n23, n31,
4253                                n45, n56, n64, n14, n25, n36, ID);
4254   if(v==NULL) myElementIDFactory->ReleaseID(ID);
4255   return v;
4256 }
4257
4258 //=======================================================================
4259 //function : AddVolumeWithID
4260 //purpose  :
4261 //=======================================================================
4262 SMDS_MeshVolume* SMDS_Mesh::AddVolumeWithID(int n1, int n2, int n3,
4263                                             int n4, int n5, int n6,
4264                                             int n12,int n23,int n31,
4265                                             int n45,int n56,int n64,
4266                                             int n14,int n25,int n36, int ID)
4267 {
4268   return SMDS_Mesh::AddVolumeWithID
4269     ((SMDS_MeshNode*) myNodeIDFactory->MeshElement(n1) ,
4270      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n2) ,
4271      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n3) ,
4272      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n4) ,
4273      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n5) ,
4274      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n6) ,
4275      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n12),
4276      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n23),
4277      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n31),
4278      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n45),
4279      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n56),
4280      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n64),
4281      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n14),
4282      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n25),
4283      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n36),
4284      ID);
4285 }
4286
4287 //=======================================================================
4288 //function : AddVolumeWithID
4289 //purpose  : 2d order Pentahedron with 15 nodes
4290 //=======================================================================
4291 SMDS_MeshVolume* SMDS_Mesh::AddVolumeWithID(const SMDS_MeshNode * n1,
4292                                             const SMDS_MeshNode * n2,
4293                                             const SMDS_MeshNode * n3,
4294                                             const SMDS_MeshNode * n4,
4295                                             const SMDS_MeshNode * n5,
4296                                             const SMDS_MeshNode * n6,
4297                                             const SMDS_MeshNode * n12,
4298                                             const SMDS_MeshNode * n23,
4299                                             const SMDS_MeshNode * n31,
4300                                             const SMDS_MeshNode * n45,
4301                                             const SMDS_MeshNode * n56,
4302                                             const SMDS_MeshNode * n64,
4303                                             const SMDS_MeshNode * n14,
4304                                             const SMDS_MeshNode * n25,
4305                                             const SMDS_MeshNode * n36,
4306                                             int ID)
4307 {
4308   if (!n1 || !n2 || !n3 || !n4 || !n5 || !n6 || !n12 || !n23 ||
4309       !n31 || !n45 || !n56 || !n64 || !n14 || !n25 || !n36)
4310     return 0;
4311   if(hasConstructionFaces()) {
4312     // creation quadratic faces - not implemented
4313     return 0;
4314   }
4315   // --- retrieve nodes ID
4316   myNodeIds.resize(15);
4317   myNodeIds[0] = n1->getVtkId();
4318   myNodeIds[1] = n2->getVtkId();
4319   myNodeIds[2] = n3->getVtkId();
4320
4321   myNodeIds[3] = n4->getVtkId();
4322   myNodeIds[4] = n5->getVtkId();
4323   myNodeIds[5] = n6->getVtkId();
4324
4325   myNodeIds[6] = n12->getVtkId();
4326   myNodeIds[7] = n23->getVtkId();
4327   myNodeIds[8] = n31->getVtkId();
4328
4329   myNodeIds[9] = n45->getVtkId();
4330   myNodeIds[10] = n56->getVtkId();
4331   myNodeIds[11] = n64->getVtkId();
4332
4333   myNodeIds[12] = n14->getVtkId();
4334   myNodeIds[13] = n25->getVtkId();
4335   myNodeIds[14] = n36->getVtkId();
4336
4337   SMDS_VtkVolume *volvtk = myVolumePool->getNew();
4338   volvtk->init(myNodeIds, this);
4339   if (!this->registerElement(ID,volvtk))
4340   {
4341     this->myGrid->GetCellTypesArray()->SetValue(volvtk->getVtkId(), VTK_EMPTY_CELL);
4342     myVolumePool->destroy(volvtk);
4343     return 0;
4344   }
4345   adjustmyCellsCapacity(ID);
4346   myCells[ID] = volvtk;
4347   myInfo.myNbQuadPrisms++;
4348
4349   //  if (!registerElement(ID, volvtk)) {
4350   //    RemoveElement(volvtk, false);
4351   //    volvtk = NULL;
4352   //  }
4353   return volvtk;
4354 }
4355
4356
4357 //=======================================================================
4358 //function : AddVolume
4359 //purpose  :
4360 //=======================================================================
4361 SMDS_MeshVolume* SMDS_Mesh::AddVolume(const SMDS_MeshNode * n1,
4362                                       const SMDS_MeshNode * n2,
4363                                       const SMDS_MeshNode * n3,
4364                                       const SMDS_MeshNode * n4,
4365                                       const SMDS_MeshNode * n5,
4366                                       const SMDS_MeshNode * n6,
4367                                       const SMDS_MeshNode * n7,
4368                                       const SMDS_MeshNode * n8,
4369                                       const SMDS_MeshNode * n12,
4370                                       const SMDS_MeshNode * n23,
4371                                       const SMDS_MeshNode * n34,
4372                                       const SMDS_MeshNode * n41,
4373                                       const SMDS_MeshNode * n56,
4374                                       const SMDS_MeshNode * n67,
4375                                       const SMDS_MeshNode * n78,
4376                                       const SMDS_MeshNode * n85,
4377                                       const SMDS_MeshNode * n15,
4378                                       const SMDS_MeshNode * n26,
4379                                       const SMDS_MeshNode * n37,
4380                                       const SMDS_MeshNode * n48)
4381 {
4382   int ID = myElementIDFactory->GetFreeID();
4383   SMDS_MeshVolume * v =
4384     SMDS_Mesh::AddVolumeWithID(n1, n2, n3, n4, n5, n6, n7, n8, n12, n23, n34, n41,
4385                                n56, n67, n78, n85, n15, n26, n37, n48, ID);
4386   if(v==NULL) myElementIDFactory->ReleaseID(ID);
4387   return v;
4388 }
4389
4390 //=======================================================================
4391 //function : AddVolumeWithID
4392 //purpose  :
4393 //=======================================================================
4394 SMDS_MeshVolume* SMDS_Mesh::AddVolumeWithID(int n1, int n2, int n3, int n4,
4395                                             int n5, int n6, int n7, int n8,
4396                                             int n12,int n23,int n34,int n41,
4397                                             int n56,int n67,int n78,int n85,
4398                                             int n15,int n26,int n37,int n48, int ID)
4399 {
4400   return SMDS_Mesh::AddVolumeWithID
4401     ((SMDS_MeshNode*) myNodeIDFactory->MeshElement(n1),
4402      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n2),
4403      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n3),
4404      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n4),
4405      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n5),
4406      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n6),
4407      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n7),
4408      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n8),
4409      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n12),
4410      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n23),
4411      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n34),
4412      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n41),
4413      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n56),
4414      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n67),
4415      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n78),
4416      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n85),
4417      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n15),
4418      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n26),
4419      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n37),
4420      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n48),
4421      ID);
4422 }
4423
4424 //=======================================================================
4425 //function : AddVolumeWithID
4426 //purpose  : 2d order Hexahedrons with 20 nodes
4427 //=======================================================================
4428 SMDS_MeshVolume* SMDS_Mesh::AddVolumeWithID(const SMDS_MeshNode * n1,
4429                                             const SMDS_MeshNode * n2,
4430                                             const SMDS_MeshNode * n3,
4431                                             const SMDS_MeshNode * n4,
4432                                             const SMDS_MeshNode * n5,
4433                                             const SMDS_MeshNode * n6,
4434                                             const SMDS_MeshNode * n7,
4435                                             const SMDS_MeshNode * n8,
4436                                             const SMDS_MeshNode * n12,
4437                                             const SMDS_MeshNode * n23,
4438                                             const SMDS_MeshNode * n34,
4439                                             const SMDS_MeshNode * n41,
4440                                             const SMDS_MeshNode * n56,
4441                                             const SMDS_MeshNode * n67,
4442                                             const SMDS_MeshNode * n78,
4443                                             const SMDS_MeshNode * n85,
4444                                             const SMDS_MeshNode * n15,
4445                                             const SMDS_MeshNode * n26,
4446                                             const SMDS_MeshNode * n37,
4447                                             const SMDS_MeshNode * n48,
4448                                             int ID)
4449 {
4450   if (!n1 || !n2 || !n3 || !n4 || !n5 || !n6 || !n7 || !n8 || !n12 || !n23 ||
4451       !n34 || !n41 || !n56 || !n67 || !n78 || !n85 || !n15 || !n26 || !n37 || !n48)
4452     return 0;
4453   if(hasConstructionFaces()) {
4454     return 0;
4455     // creation quadratic faces - not implemented
4456   }
4457   // --- retrieve nodes ID
4458   myNodeIds.resize(20);
4459   myNodeIds[0] = n1->getVtkId();
4460   myNodeIds[1] = n4->getVtkId();
4461   myNodeIds[2] = n3->getVtkId();
4462   myNodeIds[3] = n2->getVtkId();
4463
4464   myNodeIds[4] = n5->getVtkId();
4465   myNodeIds[5] = n8->getVtkId();
4466   myNodeIds[6] = n7->getVtkId();
4467   myNodeIds[7] = n6->getVtkId();
4468
4469   myNodeIds[8] = n41->getVtkId();
4470   myNodeIds[9] = n34->getVtkId();
4471   myNodeIds[10] = n23->getVtkId();
4472   myNodeIds[11] = n12->getVtkId();
4473
4474   myNodeIds[12] = n85->getVtkId();
4475   myNodeIds[13] = n78->getVtkId();
4476   myNodeIds[14] = n67->getVtkId();
4477   myNodeIds[15] = n56->getVtkId();
4478
4479   myNodeIds[16] = n15->getVtkId();
4480   myNodeIds[17] = n48->getVtkId();
4481   myNodeIds[18] = n37->getVtkId();
4482   myNodeIds[19] = n26->getVtkId();
4483
4484   SMDS_VtkVolume *volvtk = myVolumePool->getNew();
4485   volvtk->init(myNodeIds, this);
4486   if (!this->registerElement(ID,volvtk))
4487   {
4488     this->myGrid->GetCellTypesArray()->SetValue(volvtk->getVtkId(), VTK_EMPTY_CELL);
4489     myVolumePool->destroy(volvtk);
4490     return 0;
4491   }
4492   adjustmyCellsCapacity(ID);
4493   myCells[ID] = volvtk;
4494   myInfo.myNbQuadHexas++;
4495
4496   //  if (!registerElement(ID, volvtk)) {
4497   //    RemoveElement(volvtk, false);
4498   //    volvtk = NULL;
4499   //  }
4500   return volvtk;
4501 }
4502
4503 //=======================================================================
4504 //function : AddVolume
4505 //purpose  :
4506 //=======================================================================
4507 SMDS_MeshVolume* SMDS_Mesh::AddVolume(const SMDS_MeshNode * n1,
4508                                       const SMDS_MeshNode * n2,
4509                                       const SMDS_MeshNode * n3,
4510                                       const SMDS_MeshNode * n4,
4511                                       const SMDS_MeshNode * n5,
4512                                       const SMDS_MeshNode * n6,
4513                                       const SMDS_MeshNode * n7,
4514                                       const SMDS_MeshNode * n8,
4515                                       const SMDS_MeshNode * n12,
4516                                       const SMDS_MeshNode * n23,
4517                                       const SMDS_MeshNode * n34,
4518                                       const SMDS_MeshNode * n41,
4519                                       const SMDS_MeshNode * n56,
4520                                       const SMDS_MeshNode * n67,
4521                                       const SMDS_MeshNode * n78,
4522                                       const SMDS_MeshNode * n85,
4523                                       const SMDS_MeshNode * n15,
4524                                       const SMDS_MeshNode * n26,
4525                                       const SMDS_MeshNode * n37,
4526                                       const SMDS_MeshNode * n48,
4527                                       const SMDS_MeshNode * n1234,
4528                                       const SMDS_MeshNode * n1256,
4529                                       const SMDS_MeshNode * n2367,
4530                                       const SMDS_MeshNode * n3478,
4531                                       const SMDS_MeshNode * n1458,
4532                                       const SMDS_MeshNode * n5678,
4533                                       const SMDS_MeshNode * nCenter)
4534 {
4535   int ID = myElementIDFactory->GetFreeID();
4536   SMDS_MeshVolume * v =
4537     SMDS_Mesh::AddVolumeWithID(n1, n2, n3, n4, n5, n6, n7, n8, n12, n23, n34, n41,
4538                                n56, n67, n78, n85, n15, n26, n37, n48,
4539                                n1234, n1256, n2367, n3478, n1458, n5678, nCenter,
4540                                ID);
4541   if(v==NULL) myElementIDFactory->ReleaseID(ID);
4542   return v;
4543 }
4544
4545 //=======================================================================
4546 //function : AddVolumeWithID
4547 //purpose  :
4548 //=======================================================================
4549 SMDS_MeshVolume* SMDS_Mesh::AddVolumeWithID(int n1, int n2, int n3, int n4,
4550                                             int n5, int n6, int n7, int n8,
4551                                             int n12,int n23,int n34,int n41,
4552                                             int n56,int n67,int n78,int n85,
4553                                             int n15,int n26,int n37,int n48,
4554                                             int n1234,int n1256,int n2367,int n3478,
4555                                             int n1458,int n5678,int nCenter, int ID)
4556 {
4557   return SMDS_Mesh::AddVolumeWithID
4558     ((SMDS_MeshNode*) myNodeIDFactory->MeshElement(n1),
4559      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n2),
4560      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n3),
4561      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n4),
4562      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n5),
4563      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n6),
4564      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n7),
4565      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n8),
4566      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n12),
4567      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n23),
4568      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n34),
4569      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n41),
4570      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n56),
4571      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n67),
4572      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n78),
4573      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n85),
4574      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n15),
4575      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n26),
4576      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n37),
4577      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n48),
4578      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n1234),
4579      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n1256),
4580      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n2367),
4581      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n3478),
4582      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n1458),
4583      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n5678),
4584      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(nCenter),
4585      ID);
4586 }
4587
4588 //=======================================================================
4589 //function : AddVolumeWithID
4590 //purpose  : 2d order Hexahedrons with 20 nodes
4591 //=======================================================================
4592 SMDS_MeshVolume* SMDS_Mesh::AddVolumeWithID(const SMDS_MeshNode * n1,
4593                                             const SMDS_MeshNode * n2,
4594                                             const SMDS_MeshNode * n3,
4595                                             const SMDS_MeshNode * n4,
4596                                             const SMDS_MeshNode * n5,
4597                                             const SMDS_MeshNode * n6,
4598                                             const SMDS_MeshNode * n7,
4599                                             const SMDS_MeshNode * n8,
4600                                             const SMDS_MeshNode * n12,
4601                                             const SMDS_MeshNode * n23,
4602                                             const SMDS_MeshNode * n34,
4603                                             const SMDS_MeshNode * n41,
4604                                             const SMDS_MeshNode * n56,
4605                                             const SMDS_MeshNode * n67,
4606                                             const SMDS_MeshNode * n78,
4607                                             const SMDS_MeshNode * n85,
4608                                             const SMDS_MeshNode * n15,
4609                                             const SMDS_MeshNode * n26,
4610                                             const SMDS_MeshNode * n37,
4611                                             const SMDS_MeshNode * n48,
4612                                             const SMDS_MeshNode * n1234,
4613                                             const SMDS_MeshNode * n1256,
4614                                             const SMDS_MeshNode * n2367,
4615                                             const SMDS_MeshNode * n3478,
4616                                             const SMDS_MeshNode * n1458,
4617                                             const SMDS_MeshNode * n5678,
4618                                             const SMDS_MeshNode * nCenter,
4619                                             int ID)
4620 {
4621   if (!n1 || !n2 || !n3 || !n4 || !n5 || !n6 || !n7 || !n8 || !n12 || !n23 ||
4622       !n34 || !n41 || !n56 || !n67 || !n78 || !n85 || !n15 || !n26 || !n37 || !n48 ||
4623       !n1234 || !n1256 || !n2367 || !n3478 || !n1458 || !n5678 || !nCenter )
4624     return 0;
4625   if(hasConstructionFaces()) {
4626     return 0;
4627     // creation quadratic faces - not implemented
4628   }
4629   // --- retrieve nodes ID
4630   myNodeIds.resize(27);
4631   myNodeIds[0] = n1->getVtkId();
4632   myNodeIds[1] = n4->getVtkId();
4633   myNodeIds[2] = n3->getVtkId();
4634   myNodeIds[3] = n2->getVtkId();
4635
4636   myNodeIds[4] = n5->getVtkId();
4637   myNodeIds[5] = n8->getVtkId();
4638   myNodeIds[6] = n7->getVtkId();
4639   myNodeIds[7] = n6->getVtkId();
4640
4641   myNodeIds[8] = n41->getVtkId();
4642   myNodeIds[9] = n34->getVtkId();
4643   myNodeIds[10] = n23->getVtkId();
4644   myNodeIds[11] = n12->getVtkId();
4645
4646   myNodeIds[12] = n85->getVtkId();
4647   myNodeIds[13] = n78->getVtkId();
4648   myNodeIds[14] = n67->getVtkId();
4649   myNodeIds[15] = n56->getVtkId();
4650
4651   myNodeIds[16] = n15->getVtkId();
4652   myNodeIds[17] = n48->getVtkId();
4653   myNodeIds[18] = n37->getVtkId();
4654   myNodeIds[19] = n26->getVtkId();
4655
4656   myNodeIds[20] = n1256->getVtkId();
4657   myNodeIds[21] = n3478->getVtkId();
4658   myNodeIds[22] = n1458->getVtkId();
4659   myNodeIds[23] = n2367->getVtkId();
4660   myNodeIds[24] = n1234->getVtkId();
4661   myNodeIds[25] = n5678->getVtkId();
4662   myNodeIds[26] = nCenter->getVtkId();
4663
4664   SMDS_VtkVolume *volvtk = myVolumePool->getNew();
4665   volvtk->init(myNodeIds, this);
4666   if (!this->registerElement(ID,volvtk))
4667   {
4668     this->myGrid->GetCellTypesArray()->SetValue(volvtk->getVtkId(), VTK_EMPTY_CELL);
4669     myVolumePool->destroy(volvtk);
4670     return 0;
4671   }
4672   adjustmyCellsCapacity(ID);
4673   myCells[ID] = volvtk;
4674   myInfo.myNbTriQuadHexas++;
4675
4676   return volvtk;
4677 }
4678
4679
4680 void SMDS_Mesh::updateNodeMinMax()
4681 {
4682   myNodeMin = 0;
4683   if (myNodes.size() == 0)
4684   {
4685     myNodeMax=0;
4686     return;
4687   }
4688   while (!myNodes[myNodeMin] && (myNodeMin<myNodes.size()))
4689     myNodeMin++;
4690   myNodeMax=myNodes.size()-1;
4691   while (!myNodes[myNodeMax] && (myNodeMin>=0))
4692     myNodeMin--;
4693 }
4694
4695 void SMDS_Mesh::incrementNodesCapacity(int nbNodes)
4696 {
4697 //  int val = myCellIdSmdsToVtk.size();
4698 //  MESSAGE(" ------------------- resize myCellIdSmdsToVtk " << val << " --> " << val + nbNodes);
4699 //  myCellIdSmdsToVtk.resize(val + nbNodes, -1); // fill new elements with -1
4700   int val = myNodes.size();
4701   MESSAGE(" ------------------- resize myNodes " << val << " --> " << val + nbNodes);
4702   myNodes.resize(val +nbNodes, 0);
4703 }
4704
4705 void SMDS_Mesh::incrementCellsCapacity(int nbCells)
4706 {
4707   int val = myCellIdVtkToSmds.size();
4708   MESSAGE(" ------------------- resize myCellIdVtkToSmds " << val << " --> " << val + nbCells);
4709   myCellIdVtkToSmds.resize(val + nbCells, -1); // fill new elements with -1
4710   val = myCells.size();
4711   MESSAGE(" ------------------- resize myCells " << val << " --> " << val + nbCells);
4712   myNodes.resize(val +nbCells, 0);
4713 }
4714
4715 void SMDS_Mesh::adjustStructure()
4716 {
4717   myGrid->GetPoints()->GetData()->SetNumberOfTuples(myNodeIDFactory->GetMaxID());
4718 }
4719
4720 void SMDS_Mesh::dumpGrid(string ficdump)
4721 {
4722         MESSAGE("SMDS_Mesh::dumpGrid " << ficdump);
4723 //  vtkUnstructuredGridWriter* aWriter = vtkUnstructuredGridWriter::New();
4724 //  aWriter->SetFileName(ficdump.c_str());
4725 //  aWriter->SetInput(myGrid);
4726 //  if(myGrid->GetNumberOfCells())
4727 //  {
4728 //    aWriter->Write();
4729 //  }
4730 //  aWriter->Delete();
4731   ficdump = ficdump + "_connectivity";
4732   ofstream ficcon(ficdump.c_str(), ios::out);
4733   int nbPoints = myGrid->GetNumberOfPoints();
4734   ficcon << "-------------------------------- points " <<  nbPoints << endl;
4735   for (int i=0; i<nbPoints; i++)
4736   {
4737         ficcon << i << " " << *(myGrid->GetPoint(i)) << " " << *(myGrid->GetPoint(i)+1) << " " << " " << *(myGrid->GetPoint(i)+2) << endl;
4738   }
4739   int nbCells = myGrid->GetNumberOfCells();
4740   ficcon << "-------------------------------- cells " <<  nbCells << endl;
4741   for (int i=0; i<nbCells; i++)
4742   {
4743 //      MESSAGE(i << " " << myGrid->GetCell(i));
4744 //      MESSAGE("  " << myGrid->GetCell(i)->GetCellType());
4745         ficcon << i << " - " << myGrid->GetCell(i)->GetCellType() << " -";
4746         int nbptcell = myGrid->GetCell(i)->GetNumberOfPoints();
4747         vtkIdList *listid = myGrid->GetCell(i)->GetPointIds();
4748         for (int j=0; j<nbptcell; j++)
4749         {
4750                 ficcon << " " <<  listid->GetId(j);
4751         }
4752         ficcon << endl;
4753   }
4754   ficcon << "-------------------------------- connectivity " <<  nbPoints << endl;
4755         vtkCellLinks *links = myGrid->GetCellLinks();
4756   for (int i=0; i<nbPoints; i++)
4757   {
4758         int ncells = links->GetNcells(i);
4759         vtkIdType *cells = links->GetCells(i);
4760         ficcon << i << " - " << ncells << " -";
4761         for (int j=0; j<ncells; j++)
4762         {
4763                 ficcon << " " << cells[j];
4764         }
4765         ficcon << endl;
4766   }
4767   ficcon.close();
4768
4769 }
4770
4771 void SMDS_Mesh::compactMesh()
4772 {
4773   MESSAGE("SMDS_Mesh::compactMesh do nothing!");
4774 }
4775
4776 int SMDS_Mesh::fromVtkToSmds(int vtkid)
4777 {
4778   if (vtkid >= 0 && vtkid < myCellIdVtkToSmds.size())
4779     return myCellIdVtkToSmds[vtkid];
4780   throw SALOME_Exception(LOCALIZED ("vtk id out of bounds"));
4781 }
4782
4783 void SMDS_Mesh::updateBoundingBox()
4784 {
4785   xmin = 0; xmax = 0;
4786   ymin = 0; ymax = 0;
4787   zmin = 0; zmax = 0;
4788   vtkPoints *points = myGrid->GetPoints();
4789   int myNodesSize = this->myNodes.size();
4790   for (int i = 0; i < myNodesSize; i++)
4791     {
4792       if (SMDS_MeshNode *n = myNodes[i])
4793         {
4794           double coords[3];
4795           points->GetPoint(n->myVtkID, coords);
4796           if (coords[0] < xmin) xmin = coords[0];
4797           else if (coords[0] > xmax) xmax = coords[0];
4798           if (coords[1] < ymin) ymin = coords[1];
4799           else if (coords[1] > ymax) ymax = coords[1];
4800           if (coords[2] < zmin) zmin = coords[2];
4801           else if (coords[2] > zmax) zmax = coords[2];
4802         }
4803     }
4804 }
4805
4806 double SMDS_Mesh::getMaxDim()
4807 {
4808   double dmax = 1.e-3;
4809   if ((xmax - xmin) > dmax) dmax = xmax -xmin;
4810   if ((ymax - ymin) > dmax) dmax = ymax -ymin;
4811   if ((zmax - zmin) > dmax) dmax = zmax -zmin;
4812   MESSAGE("getMaxDim " << dmax);
4813   return dmax;
4814 }
4815
4816 //! modification that needs compact structure and redraw
4817 void SMDS_Mesh::Modified()
4818 {
4819   if (this->myModified)
4820     {
4821       this->myModifTime++;
4822       MESSAGE("modified");
4823       myModified = false;
4824     }
4825 }
4826
4827 //! get last modification timeStamp
4828 unsigned long SMDS_Mesh::GetMTime() const
4829 {
4830   return this->myModifTime;
4831 }
4832
4833 bool SMDS_Mesh::isCompacted()
4834 {
4835   if (this->myModifTime > this->myCompactTime)
4836     {
4837       MESSAGE(" *** isCompacted " << myCompactTime << " < " << myModifTime);
4838       this->myCompactTime = this->myModifTime;
4839       return false;
4840     }
4841   return true;
4842 }