Salome HOME
056509ffe419d7defdf50172e4a306f7a07c9a09
[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     //#ifdef VTK_HAVE_POLYHEDRON
1343     //MESSAGE("AddPolygonalFaceWithID vtk " << ID);
1344     myNodeIds.resize( nodes.size() );
1345     for ( size_t i = 0; i < nodes.size(); ++i )
1346       myNodeIds[i] = nodes[i]->getVtkId();
1347
1348     SMDS_VtkFace *facevtk = myFacePool->getNew();
1349     facevtk->initPoly(myNodeIds, this);
1350     if (!this->registerElement(ID,facevtk))
1351     {
1352       this->myGrid->GetCellTypesArray()->SetValue(facevtk->getVtkId(), VTK_EMPTY_CELL);
1353       myFacePool->destroy(facevtk);
1354       return 0;
1355     }
1356     face = facevtk;
1357     //#else
1358     //    MESSAGE("AddPolygonalFaceWithID smds " << ID);
1359     //     for ( int i = 0; i < nodes.size(); ++i )
1360     //      if ( !nodes[ i ] ) return 0;
1361     //      face = new SMDS_PolygonalFaceOfNodes(nodes);
1362     //#endif
1363     adjustmyCellsCapacity(ID);
1364     myCells[ID] = face;
1365     myInfo.myNbPolygons++;
1366   }
1367
1368   //#ifndef VTK_HAVE_POLYHEDRON
1369   //  if (!registerElement(ID, face))
1370   //    {
1371   //      registerElement(myElementIDFactory->GetFreeID(), face);
1372   //      //RemoveElement(face, false);
1373   //      //face = NULL;
1374   //    }
1375   //#endif
1376   return face;
1377 }
1378
1379 ///////////////////////////////////////////////////////////////////////////////
1380 /// Add a polygon defined by its nodes.
1381 /// An ID is automatically affected to the created face.
1382 ///////////////////////////////////////////////////////////////////////////////
1383
1384 SMDS_MeshFace* SMDS_Mesh::AddPolygonalFace (const vector<const SMDS_MeshNode*> & nodes)
1385 {
1386   return SMDS_Mesh::AddPolygonalFaceWithID(nodes, myElementIDFactory->GetFreeID());
1387 }
1388
1389 ///////////////////////////////////////////////////////////////////////////////
1390 /// Create a new polyhedral volume and add it to the mesh.
1391 /// @param ID The ID of the new volume
1392 /// @return The created volume or NULL if an element with this ID already exists
1393 /// or if input nodes are not found.
1394 ///////////////////////////////////////////////////////////////////////////////
1395
1396 SMDS_MeshVolume * SMDS_Mesh::AddPolyhedralVolumeWithID
1397                              (const vector<int> & nodes_ids,
1398                               const vector<int> & quantities,
1399                               const int           ID)
1400 {
1401   int nbNodes = nodes_ids.size();
1402   vector<const SMDS_MeshNode*> nodes (nbNodes);
1403   for (int i = 0; i < nbNodes; i++) {
1404     nodes[i] = (SMDS_MeshNode *)myNodeIDFactory->MeshElement(nodes_ids[i]);
1405     if (!nodes[i]) return NULL;
1406   }
1407   return SMDS_Mesh::AddPolyhedralVolumeWithID(nodes, quantities, ID);
1408 }
1409
1410 ///////////////////////////////////////////////////////////////////////////////
1411 /// Create a new polyhedral volume and add it to the mesh.
1412 /// @param ID The ID of the new volume
1413 /// @return The created  volume
1414 ///////////////////////////////////////////////////////////////////////////////
1415
1416 SMDS_MeshVolume*
1417 SMDS_Mesh::AddPolyhedralVolumeWithID (const vector<const SMDS_MeshNode*>& nodes,
1418                                       const vector<int>                 & quantities,
1419                                       const int                           ID)
1420 {
1421   SMDS_MeshVolume* volume = 0;
1422   if ( nodes.empty() || quantities.empty() )
1423     return NULL;
1424   if ( NbVolumes() % CHECKMEMORY_INTERVAL == 0 ) CheckMemory();
1425   if (hasConstructionFaces())
1426   {
1427     MESSAGE("Error : Not implemented");
1428     return NULL;
1429   }
1430   else if (hasConstructionEdges())
1431   {
1432     MESSAGE("Error : Not implemented");
1433     return NULL;
1434   }
1435   else
1436   {
1437     //#ifdef VTK_HAVE_POLYHEDRON
1438     //MESSAGE("AddPolyhedralVolumeWithID vtk " << ID);
1439     myNodeIds.resize( nodes.size() );
1440     for ( size_t i = 0; i < nodes.size(); ++i )
1441       myNodeIds[i] = nodes[i]->getVtkId();
1442
1443     SMDS_VtkVolume *volvtk = myVolumePool->getNew();
1444     volvtk->initPoly(myNodeIds, quantities, this);
1445     if (!this->registerElement(ID, volvtk))
1446     {
1447       this->myGrid->GetCellTypesArray()->SetValue(volvtk->getVtkId(), VTK_EMPTY_CELL);
1448       myVolumePool->destroy(volvtk);
1449       return 0;
1450     }
1451     volume = volvtk;
1452     //#else
1453     //      MESSAGE("AddPolyhedralVolumeWithID smds " << ID);
1454     //      for ( int i = 0; i < nodes.size(); ++i )
1455     //      if ( !nodes[ i ] ) return 0;
1456     //      volume = new SMDS_PolyhedralVolumeOfNodes(nodes, quantities);
1457     //#endif
1458     adjustmyCellsCapacity(ID);
1459     myCells[ID] = volume;
1460     myInfo.myNbPolyhedrons++;
1461   }
1462
1463   //#ifndef VTK_HAVE_POLYHEDRON
1464   //  if (!registerElement(ID, volume))
1465   //    {
1466   //      registerElement(myElementIDFactory->GetFreeID(), volume);
1467   //      //RemoveElement(volume, false);
1468   //      //volume = NULL;
1469   //    }
1470   //#endif
1471   return volume;
1472 }
1473
1474 ///////////////////////////////////////////////////////////////////////////////
1475 /// Create a new polyhedral volume and add it to the mesh.
1476 /// @return The created  volume
1477 ///////////////////////////////////////////////////////////////////////////////
1478
1479 SMDS_MeshVolume* SMDS_Mesh::AddPolyhedralVolume
1480                             (const vector<const SMDS_MeshNode*> & nodes,
1481                              const vector<int>                  & quantities)
1482 {
1483   int ID = myElementIDFactory->GetFreeID();
1484   SMDS_MeshVolume * v = SMDS_Mesh::AddPolyhedralVolumeWithID(nodes, quantities, ID);
1485   if (v == NULL) myElementIDFactory->ReleaseID(ID);
1486   return v;
1487 }
1488
1489 SMDS_MeshVolume* SMDS_Mesh::AddVolumeFromVtkIds(const std::vector<vtkIdType>& vtkNodeIds)
1490 {
1491   int ID = myElementIDFactory->GetFreeID();
1492   SMDS_MeshVolume * v = SMDS_Mesh::AddVolumeFromVtkIdsWithID(vtkNodeIds, ID);
1493   if (v == NULL) myElementIDFactory->ReleaseID(ID);
1494   return v;
1495 }
1496
1497 SMDS_MeshVolume* SMDS_Mesh::AddVolumeFromVtkIdsWithID(const std::vector<vtkIdType>& vtkNodeIds, const int ID)
1498 {
1499   SMDS_VtkVolume *volvtk = myVolumePool->getNew();
1500   volvtk->init(vtkNodeIds, this);
1501   if (!this->registerElement(ID,volvtk))
1502     {
1503       this->myGrid->GetCellTypesArray()->SetValue(volvtk->getVtkId(), VTK_EMPTY_CELL);
1504       myVolumePool->destroy(volvtk);
1505       return 0;
1506     }
1507   adjustmyCellsCapacity(ID);
1508   myCells[ID] = volvtk;
1509   vtkIdType aVtkType = volvtk->GetVtkType();
1510   switch (aVtkType)
1511   {
1512     case VTK_TETRA:
1513       myInfo.myNbTetras++;
1514       break;
1515     case VTK_PYRAMID:
1516       myInfo.myNbPyramids++;
1517       break;
1518     case VTK_WEDGE:
1519       myInfo.myNbPrisms++;
1520       break;
1521     case VTK_HEXAHEDRON:
1522       myInfo.myNbHexas++;
1523       break;
1524     case VTK_QUADRATIC_TETRA:
1525       myInfo.myNbQuadTetras++;
1526       break;
1527     case VTK_QUADRATIC_PYRAMID:
1528       myInfo.myNbQuadPyramids++;
1529       break;
1530     case VTK_QUADRATIC_WEDGE:
1531       myInfo.myNbQuadPrisms++;
1532       break;
1533     case VTK_QUADRATIC_HEXAHEDRON:
1534       myInfo.myNbQuadHexas++;
1535       break;
1536 //#ifdef VTK_HAVE_POLYHEDRON
1537     case VTK_POLYHEDRON:
1538       myInfo.myNbPolyhedrons++;
1539       break;
1540 //#endif
1541     default:
1542       myInfo.myNbPolyhedrons++;
1543       break;
1544   }
1545   return volvtk;
1546 }
1547
1548 SMDS_MeshFace* SMDS_Mesh::AddFaceFromVtkIds(const std::vector<vtkIdType>& vtkNodeIds)
1549 {
1550   int ID = myElementIDFactory->GetFreeID();
1551   SMDS_MeshFace * f = SMDS_Mesh::AddFaceFromVtkIdsWithID(vtkNodeIds, ID);
1552   if (f == NULL) myElementIDFactory->ReleaseID(ID);
1553   return f;
1554 }
1555
1556 SMDS_MeshFace* SMDS_Mesh::AddFaceFromVtkIdsWithID(const std::vector<vtkIdType>& vtkNodeIds, const int ID)
1557 {
1558   SMDS_VtkFace *facevtk = myFacePool->getNew();
1559   facevtk->init(vtkNodeIds, this);
1560   if (!this->registerElement(ID,facevtk))
1561     {
1562       this->myGrid->GetCellTypesArray()->SetValue(facevtk->getVtkId(), VTK_EMPTY_CELL);
1563       myFacePool->destroy(facevtk);
1564       return 0;
1565     }
1566   adjustmyCellsCapacity(ID);
1567   myCells[ID] = facevtk;
1568   vtkIdType aVtkType = facevtk->GetVtkType();
1569   switch (aVtkType)
1570   {
1571     case VTK_TRIANGLE:
1572       myInfo.myNbTriangles++;
1573       break;
1574     case VTK_QUAD:
1575       myInfo.myNbQuadrangles++;
1576       break;
1577     case VTK_QUADRATIC_TRIANGLE:
1578       myInfo.myNbQuadTriangles++;
1579       break;
1580     case VTK_QUADRATIC_QUAD:
1581       myInfo.myNbQuadQuadrangles++;
1582       break;
1583     case VTK_BIQUADRATIC_QUAD:
1584       myInfo.myNbBiQuadQuadrangles++;
1585       break;
1586     case VTK_BIQUADRATIC_TRIANGLE:
1587       myInfo.myNbBiQuadTriangles++;
1588       break;
1589     case VTK_POLYGON:
1590       myInfo.myNbPolygons++;
1591       break;
1592      default:
1593       myInfo.myNbPolygons++;
1594   }
1595   return facevtk;
1596 }
1597
1598 ///////////////////////////////////////////////////////////////////////////////
1599 /// Registers element with the given ID, maintains inverse connections
1600 ///////////////////////////////////////////////////////////////////////////////
1601 bool SMDS_Mesh::registerElement(int ID, SMDS_MeshElement* element)
1602 {
1603   //MESSAGE("registerElement " << ID);
1604   if ((ID >=0) && (ID < myCells.size()) && myCells[ID]) // --- already bound
1605   {
1606     MESSAGE(" ------------------ already bound "<< ID << " " << myCells[ID]->getVtkId());
1607     return false;
1608   }
1609
1610   element->myID = ID;
1611   element->myMeshId = myMeshId;
1612
1613   SMDS_MeshCell *cell = dynamic_cast<SMDS_MeshCell*>(element);
1614   MYASSERT(cell);
1615   int vtkId = cell->getVtkId();  
1616   if (vtkId == -1)
1617     vtkId = myElementIDFactory->SetInVtkGrid(element);
1618
1619   if (vtkId >= myCellIdVtkToSmds.size()) // --- resize local vector
1620   {
1621 //     MESSAGE(" --------------------- resize myCellIdVtkToSmds " << vtkId << " --> " << vtkId + SMDS_Mesh::chunkSize);
1622     myCellIdVtkToSmds.resize(vtkId + SMDS_Mesh::chunkSize, -1);
1623   }
1624   myCellIdVtkToSmds[vtkId] = ID;
1625
1626   myElementIDFactory->updateMinMax(ID);
1627   return true;
1628 }
1629
1630 //=======================================================================
1631 //function : MoveNode
1632 //purpose  : 
1633 //=======================================================================
1634
1635 void SMDS_Mesh::MoveNode(const SMDS_MeshNode *n, double x, double y, double z)
1636 {
1637   SMDS_MeshNode * node=const_cast<SMDS_MeshNode*>(n);
1638   node->setXYZ(x,y,z);
1639 }
1640
1641 ///////////////////////////////////////////////////////////////////////////////
1642 /// Return the node whose SMDS ID is 'ID'.
1643 ///////////////////////////////////////////////////////////////////////////////
1644 const SMDS_MeshNode * SMDS_Mesh::FindNode(int ID) const
1645 {
1646   if (ID < 1 || ID >= myNodes.size())
1647   {
1648 //     MESSAGE("------------------------------------------------------------------------- ");
1649 //     MESSAGE("----------------------------------- bad ID " << ID << " " << myNodes.size());
1650 //     MESSAGE("------------------------------------------------------------------------- ");
1651     return 0;
1652   }
1653   return (const SMDS_MeshNode *)myNodes[ID];
1654 }
1655
1656 ///////////////////////////////////////////////////////////////////////////////
1657 /// Return the node whose VTK ID is 'vtkId'.
1658 ///////////////////////////////////////////////////////////////////////////////
1659 const SMDS_MeshNode * SMDS_Mesh::FindNodeVtk(int vtkId) const
1660 {
1661   // TODO if needed use mesh->nodeIdFromVtkToSmds
1662   if (vtkId < 0 || vtkId >= (myNodes.size() -1))
1663   {
1664     MESSAGE("------------------------------------------------------------------------- ");
1665     MESSAGE("---------------------------- bad VTK ID " << vtkId << " " << myNodes.size());
1666     MESSAGE("------------------------------------------------------------------------- ");
1667     return 0;
1668   }
1669   return (const SMDS_MeshNode *)myNodes[vtkId+1];
1670 }
1671
1672 ///////////////////////////////////////////////////////////////////////////////
1673 ///Create a triangle and add it to the current mesh. This method do not bind an
1674 ///ID to the create triangle.
1675 ///////////////////////////////////////////////////////////////////////////////
1676 SMDS_MeshFace * SMDS_Mesh::createTriangle(const SMDS_MeshNode * node1,
1677                                           const SMDS_MeshNode * node2,
1678                                           const SMDS_MeshNode * node3,
1679                                           int ID)
1680 {
1681   if ( !node1 || !node2 || !node3) return 0;
1682   if ( NbFaces() % CHECKMEMORY_INTERVAL == 0 ) CheckMemory();
1683   if(hasConstructionEdges())
1684   {
1685     SMDS_MeshEdge *edge1, *edge2, *edge3;
1686     edge1=FindEdgeOrCreate(node1,node2);
1687     edge2=FindEdgeOrCreate(node2,node3);
1688     edge3=FindEdgeOrCreate(node3,node1);
1689
1690     //int ID = myElementIDFactory->GetFreeID(); // -PR- voir si on range cet element
1691     SMDS_MeshFace * face = new SMDS_FaceOfEdges(edge1,edge2,edge3);
1692     adjustmyCellsCapacity(ID);
1693     myCells[ID] = face;
1694     myInfo.myNbTriangles++;
1695     return face;
1696   }
1697   else
1698   {
1699     // --- retrieve nodes ID
1700     myNodeIds.resize(3);
1701     myNodeIds[0] = node1->getVtkId();
1702     myNodeIds[1] = node2->getVtkId();
1703     myNodeIds[2] = node3->getVtkId();
1704
1705     SMDS_MeshFace * face = 0;
1706     SMDS_VtkFace *facevtk = myFacePool->getNew();
1707     facevtk->init(myNodeIds, this); // put in vtkUnstructuredGrid
1708     if (!this->registerElement(ID,facevtk))
1709     {
1710       this->myGrid->GetCellTypesArray()->SetValue(facevtk->getVtkId(), VTK_EMPTY_CELL);
1711       myFacePool->destroy(facevtk);
1712       return 0;
1713     }
1714     face = facevtk;
1715     adjustmyCellsCapacity(ID);
1716     myCells[ID] = face;
1717     //MESSAGE("createTriangle " << ID << " " << face);
1718     myInfo.myNbTriangles++;
1719     return face;
1720   }
1721 }
1722
1723 ///////////////////////////////////////////////////////////////////////////////
1724 ///Create a quadrangle and add it to the current mesh. This methode do not bind
1725 ///a ID to the create triangle.
1726 ///////////////////////////////////////////////////////////////////////////////
1727 SMDS_MeshFace * SMDS_Mesh::createQuadrangle(const SMDS_MeshNode * node1,
1728                                             const SMDS_MeshNode * node2,
1729                                             const SMDS_MeshNode * node3,
1730                                             const SMDS_MeshNode * node4,
1731                                             int ID)
1732 {
1733   if ( !node1 || !node2 || !node3 || !node4 ) return 0;
1734   if ( NbFaces() % CHECKMEMORY_INTERVAL == 0 ) CheckMemory();
1735   if(hasConstructionEdges())
1736   {
1737     //MESSAGE("createQuadrangle hasConstructionEdges "<< ID);
1738     SMDS_MeshEdge *edge1, *edge2, *edge3, *edge4;
1739     edge1=FindEdgeOrCreate(node1,node2);
1740     edge2=FindEdgeOrCreate(node2,node3);
1741     edge3=FindEdgeOrCreate(node3,node4);
1742     edge4=FindEdgeOrCreate(node4,node1);
1743
1744     SMDS_MeshFace * face = new SMDS_FaceOfEdges(edge1,edge2,edge3,edge4);
1745     adjustmyCellsCapacity(ID);
1746     myCells[ID] = face;
1747     myInfo.myNbQuadrangles++;
1748     return face;
1749   }
1750   else
1751   {
1752     // --- retrieve nodes ID
1753     myNodeIds.resize(4);
1754     myNodeIds[0] = node1->getVtkId();
1755     myNodeIds[1] = node2->getVtkId();
1756     myNodeIds[2] = node3->getVtkId();
1757     myNodeIds[3] = node4->getVtkId();
1758
1759     SMDS_MeshFace * face = 0;
1760     SMDS_VtkFace *facevtk = myFacePool->getNew();
1761     facevtk->init(myNodeIds, this);
1762     if (!this->registerElement(ID,facevtk))
1763     {
1764       this->myGrid->GetCellTypesArray()->SetValue(facevtk->getVtkId(), VTK_EMPTY_CELL);
1765       myFacePool->destroy(facevtk);
1766       return 0;
1767     }
1768     face = facevtk;
1769     adjustmyCellsCapacity(ID);
1770     myCells[ID] = face;
1771     myInfo.myNbQuadrangles++;
1772     return face;
1773   }
1774 }
1775
1776 ///////////////////////////////////////////////////////////////////////////////
1777 /// Remove a node and all the elements which own this node
1778 ///////////////////////////////////////////////////////////////////////////////
1779
1780 void SMDS_Mesh::RemoveNode(const SMDS_MeshNode * node)
1781 {
1782     MESSAGE("RemoveNode");
1783         RemoveElement(node, true);
1784 }
1785
1786 ///////////////////////////////////////////////////////////////////////////////
1787 /// Remove an edge and all the elements which own this edge
1788 ///////////////////////////////////////////////////////////////////////////////
1789
1790 void SMDS_Mesh::Remove0DElement(const SMDS_Mesh0DElement * elem0d)
1791 {
1792     MESSAGE("Remove0DElement");
1793   RemoveElement(elem0d,true);
1794 }
1795
1796 ///////////////////////////////////////////////////////////////////////////////
1797 /// Remove an edge and all the elements which own this edge
1798 ///////////////////////////////////////////////////////////////////////////////
1799
1800 void SMDS_Mesh::RemoveEdge(const SMDS_MeshEdge * edge)
1801 {
1802     MESSAGE("RemoveEdge");
1803         RemoveElement(edge,true);
1804 }
1805
1806 ///////////////////////////////////////////////////////////////////////////////
1807 /// Remove an face and all the elements which own this face
1808 ///////////////////////////////////////////////////////////////////////////////
1809
1810 void SMDS_Mesh::RemoveFace(const SMDS_MeshFace * face)
1811 {
1812     MESSAGE("RemoveFace");
1813         RemoveElement(face, true);
1814 }
1815
1816 ///////////////////////////////////////////////////////////////////////////////
1817 /// Remove a volume
1818 ///////////////////////////////////////////////////////////////////////////////
1819
1820 void SMDS_Mesh::RemoveVolume(const SMDS_MeshVolume * volume)
1821 {
1822     MESSAGE("RemoveVolume");
1823         RemoveElement(volume, true);
1824 }
1825
1826 //=======================================================================
1827 //function : RemoveFromParent
1828 //purpose  :
1829 //=======================================================================
1830
1831 bool SMDS_Mesh::RemoveFromParent()
1832 {
1833         if (myParent==NULL) return false;
1834         else return (myParent->RemoveSubMesh(this));
1835 }
1836
1837 //=======================================================================
1838 //function : RemoveSubMesh
1839 //purpose  :
1840 //=======================================================================
1841
1842 bool SMDS_Mesh::RemoveSubMesh(const SMDS_Mesh * aMesh)
1843 {
1844         bool found = false;
1845
1846         list<SMDS_Mesh *>::iterator itmsh=myChildren.begin();
1847         for (; itmsh!=myChildren.end() && !found; itmsh++)
1848         {
1849                 SMDS_Mesh * submesh = *itmsh;
1850                 if (submesh == aMesh)
1851                 {
1852                         found = true;
1853                         myChildren.erase(itmsh);
1854                 }
1855         }
1856
1857         return found;
1858 }
1859
1860 //=======================================================================
1861 //function : ChangeElementNodes
1862 //purpose  :
1863 //=======================================================================
1864
1865 bool SMDS_Mesh::ChangeElementNodes(const SMDS_MeshElement * element,
1866                                    const SMDS_MeshNode    * nodes[],
1867                                    const int                nbnodes)
1868 {
1869   MESSAGE("SMDS_Mesh::ChangeElementNodes");
1870   // keep current nodes of elem
1871   set<const SMDS_MeshNode*> oldNodes( element->begin_nodes(), element->end_nodes() );
1872
1873   // change nodes
1874   bool Ok = false;
1875   SMDS_MeshCell* cell = dynamic_cast<SMDS_MeshCell*>((SMDS_MeshElement*) element);
1876   if (cell)
1877     {
1878       Ok = cell->vtkOrder(nodes, nbnodes);
1879       Ok = cell->ChangeNodes(nodes, nbnodes);
1880     }
1881
1882   if ( Ok ) { // update InverseElements
1883
1884     set<const SMDS_MeshNode*>::iterator it;
1885
1886     // AddInverseElement to new nodes
1887     for ( int i = 0; i < nbnodes; i++ ) {
1888       it = oldNodes.find( nodes[i] );
1889       if ( it == oldNodes.end() )
1890         // new node
1891         const_cast<SMDS_MeshNode*>( nodes[i] )->AddInverseElement( cell );
1892       else
1893         // remove from oldNodes a node that remains in elem
1894         oldNodes.erase( it );
1895     }
1896     // RemoveInverseElement from the nodes removed from elem
1897     for ( it = oldNodes.begin(); it != oldNodes.end(); it++ )
1898     {
1899       SMDS_MeshNode * n = const_cast<SMDS_MeshNode *>( *it );
1900       n->RemoveInverseElement( cell );
1901     }
1902   }
1903
1904   return Ok;
1905 }
1906
1907 //=======================================================================
1908 //function : ChangePolyhedronNodes
1909 //purpose  : to change nodes of polyhedral volume
1910 //=======================================================================
1911 bool SMDS_Mesh::ChangePolyhedronNodes (const SMDS_MeshElement *            elem,
1912                                        const vector<const SMDS_MeshNode*>& nodes,
1913                                        const vector<int>                 & quantities)
1914 {
1915   if (elem->GetType() != SMDSAbs_Volume) {
1916     MESSAGE("WRONG ELEM TYPE");
1917     return false;
1918   }
1919
1920   const SMDS_VtkVolume* vol = dynamic_cast<const SMDS_VtkVolume*>(elem);
1921   if (!vol) {
1922     return false;
1923   }
1924
1925   // keep current nodes of elem
1926   set<const SMDS_MeshElement*> oldNodes;
1927   SMDS_ElemIteratorPtr itn = elem->nodesIterator();
1928   while (itn->more()) {
1929     oldNodes.insert(itn->next());
1930   }
1931
1932   // change nodes
1933   // TODO remove this function
1934   //bool Ok = const_cast<SMDS_VtkVolume*>(vol)->ChangeNodes(nodes, quantities);
1935   bool Ok = false;
1936   if (!Ok) {
1937     return false;
1938   }
1939
1940   // update InverseElements
1941
1942   // AddInverseElement to new nodes
1943   int nbnodes = nodes.size();
1944   set<const SMDS_MeshElement*>::iterator it;
1945   for (int i = 0; i < nbnodes; i++) {
1946     it = oldNodes.find(nodes[i]);
1947     if (it == oldNodes.end()) {
1948       // new node
1949       const_cast<SMDS_MeshNode*>(nodes[i])->AddInverseElement(elem);
1950     } else {
1951       // remove from oldNodes a node that remains in elem
1952       oldNodes.erase(it);
1953     }
1954   }
1955
1956   // RemoveInverseElement from the nodes removed from elem
1957   for (it = oldNodes.begin(); it != oldNodes.end(); it++) {
1958     SMDS_MeshNode * n = static_cast<SMDS_MeshNode *>
1959       (const_cast<SMDS_MeshElement *>( *it ));
1960     n->RemoveInverseElement(elem);
1961   }
1962
1963   return Ok;
1964 }
1965
1966
1967 //=======================================================================
1968 //function : Find0DElement
1969 //purpose  :
1970 //=======================================================================
1971 const SMDS_Mesh0DElement* SMDS_Mesh::Find0DElement(int idnode) const
1972 {
1973   const SMDS_MeshNode * node = FindNode(idnode);
1974   if(node == NULL) return NULL;
1975   return Find0DElement(node);
1976 }
1977
1978 const SMDS_Mesh0DElement* SMDS_Mesh::Find0DElement(const SMDS_MeshNode * node)
1979 {
1980   if (!node) return 0;
1981   const SMDS_Mesh0DElement* toReturn = NULL;
1982   SMDS_ElemIteratorPtr it1 = node->GetInverseElementIterator(SMDSAbs_0DElement);
1983   while (it1->more() && (toReturn == NULL)) {
1984     const SMDS_MeshElement* e = it1->next();
1985     if (e->NbNodes() == 1) {
1986       toReturn = static_cast<const SMDS_Mesh0DElement*>(e);
1987     }
1988   }
1989   return toReturn;
1990 }
1991
1992 //=======================================================================
1993 //function : FindBall
1994 //purpose  :
1995 //=======================================================================
1996
1997 const SMDS_BallElement* SMDS_Mesh::FindBall(int idnode) const
1998 {
1999   const SMDS_MeshNode * node = FindNode(idnode);
2000   if(node == NULL) return NULL;
2001   return FindBall(node);
2002 }
2003
2004 const SMDS_BallElement* SMDS_Mesh::FindBall(const SMDS_MeshNode * node)
2005 {
2006   if (!node) return 0;
2007   const SMDS_BallElement* toReturn = NULL;
2008   SMDS_ElemIteratorPtr it1 = node->GetInverseElementIterator(SMDSAbs_Ball);
2009   while (it1->more() && (toReturn == NULL)) {
2010     const SMDS_MeshElement* e = it1->next();
2011     if (e->GetGeomType() == SMDSGeom_BALL)
2012       toReturn = static_cast<const SMDS_BallElement*>(e);
2013   }
2014   return toReturn;
2015 }
2016
2017 //=======================================================================
2018 //function : Find0DElementOrCreate
2019 //purpose  :
2020 //=======================================================================
2021 //SMDS_Mesh0DElement* SMDS_Mesh::Find0DElementOrCreate(const SMDS_MeshNode * node)
2022 //{
2023 //  if (!node) return 0;
2024 //  SMDS_Mesh0DElement * toReturn = NULL;
2025 //  toReturn = const_cast<SMDS_Mesh0DElement*>(Find0DElement(node));
2026 //  if (toReturn == NULL) {
2027 //    //if (my0DElements.Extent() % CHECKMEMORY_INTERVAL == 0) CheckMemory();
2028 //    toReturn = new SMDS_Mesh0DElement(node);
2029 //    my0DElements.Add(toReturn);
2030 //    myInfo.myNb0DElements++;
2031 //  }
2032 //  return toReturn;
2033 //}
2034
2035
2036 //=======================================================================
2037 //function : FindEdge
2038 //purpose  :
2039 //=======================================================================
2040
2041 const SMDS_MeshEdge* SMDS_Mesh::FindEdge(int idnode1, int idnode2) const
2042 {
2043   const SMDS_MeshNode * node1=FindNode(idnode1);
2044   const SMDS_MeshNode * node2=FindNode(idnode2);
2045   if((node1==NULL)||(node2==NULL)) return NULL;
2046   return FindEdge(node1,node2);
2047 }
2048
2049 //#include "Profiler.h"
2050 const SMDS_MeshEdge* SMDS_Mesh::FindEdge(const SMDS_MeshNode * node1,
2051                                          const SMDS_MeshNode * node2)
2052 {
2053   if ( !node1 ) return 0;
2054   const SMDS_MeshEdge * toReturn=NULL;
2055   //PROFILER_Init();
2056   //PROFILER_Set();
2057   SMDS_ElemIteratorPtr it1=node1->GetInverseElementIterator(SMDSAbs_Edge);
2058   //PROFILER_Get(0);
2059   //PROFILER_Set();
2060   while(it1->more()) {
2061     const SMDS_MeshElement * e = it1->next();
2062     if ( e->NbNodes() == 2 && e->GetNodeIndex( node2 ) >= 0 ) {
2063       toReturn = static_cast<const SMDS_MeshEdge*>( e );
2064       break;
2065     }
2066   }
2067   //PROFILER_Get(1);
2068   return toReturn;
2069 }
2070
2071
2072 //=======================================================================
2073 //function : FindEdgeOrCreate
2074 //purpose  :
2075 //=======================================================================
2076
2077 SMDS_MeshEdge* SMDS_Mesh::FindEdgeOrCreate(const SMDS_MeshNode * node1,
2078                                            const SMDS_MeshNode * node2)
2079 {
2080   if ( !node1 || !node2) return 0;
2081   SMDS_MeshEdge * toReturn=NULL;
2082   toReturn=const_cast<SMDS_MeshEdge*>(FindEdge(node1,node2));
2083   if(toReturn==NULL) {
2084     if ( NbEdges() % CHECKMEMORY_INTERVAL == 0 ) CheckMemory();
2085     int ID = myElementIDFactory->GetFreeID(); // -PR- voir si on range cet element
2086     adjustmyCellsCapacity(ID);
2087     myNodeIds.resize(2);
2088     myNodeIds[0] = node1->getVtkId();
2089     myNodeIds[1] = node2->getVtkId();
2090
2091     SMDS_VtkEdge *edgevtk = myEdgePool->getNew();
2092     edgevtk->init(myNodeIds, this);
2093     if (!this->registerElement(ID,edgevtk))
2094     {
2095       this->myGrid->GetCellTypesArray()->SetValue(edgevtk->getVtkId(), VTK_EMPTY_CELL);
2096       myEdgePool->destroy(edgevtk);
2097       return 0;
2098     }
2099     toReturn = edgevtk;
2100     myCells[ID] = toReturn;
2101     myInfo.myNbEdges++;
2102   }
2103   return toReturn;
2104 }
2105
2106
2107 //=======================================================================
2108 //function : FindEdge
2109 //purpose  :
2110 //=======================================================================
2111
2112 const SMDS_MeshEdge* SMDS_Mesh::FindEdge(int idnode1, int idnode2,
2113                                          int idnode3) const
2114 {
2115   const SMDS_MeshNode * node1=FindNode(idnode1);
2116   const SMDS_MeshNode * node2=FindNode(idnode2);
2117   const SMDS_MeshNode * node3=FindNode(idnode3);
2118   return FindEdge(node1,node2,node3);
2119 }
2120
2121 const SMDS_MeshEdge* SMDS_Mesh::FindEdge(const SMDS_MeshNode * node1,
2122                                          const SMDS_MeshNode * node2,
2123                                          const SMDS_MeshNode * node3)
2124 {
2125   if ( !node1 ) return 0;
2126   SMDS_ElemIteratorPtr it1 = node1->GetInverseElementIterator(SMDSAbs_Edge);
2127   while(it1->more()) {
2128     const SMDS_MeshElement * e = it1->next();
2129     if ( e->NbNodes() == 3 ) {
2130       SMDS_ElemIteratorPtr it2 = e->nodesIterator();
2131       while(it2->more()) {
2132         const SMDS_MeshElement* n = it2->next();
2133         if( n!=node1 &&
2134             n!=node2 &&
2135             n!=node3 )
2136         {
2137           e = 0;
2138           break;
2139         }
2140       }
2141       if ( e )
2142         return static_cast<const SMDS_MeshEdge *> (e);
2143     }
2144   }
2145   return 0;
2146 }
2147
2148
2149 //=======================================================================
2150 //function : FindFace
2151 //purpose  :
2152 //=======================================================================
2153
2154 const SMDS_MeshFace* SMDS_Mesh::FindFace(int idnode1, int idnode2,
2155         int idnode3) const
2156 {
2157   const SMDS_MeshNode * node1=FindNode(idnode1);
2158   const SMDS_MeshNode * node2=FindNode(idnode2);
2159   const SMDS_MeshNode * node3=FindNode(idnode3);
2160   return FindFace(node1, node2, node3);
2161 }
2162
2163 const SMDS_MeshFace* SMDS_Mesh::FindFace(const SMDS_MeshNode *node1,
2164                                          const SMDS_MeshNode *node2,
2165                                          const SMDS_MeshNode *node3)
2166 {
2167   if ( !node1 ) return 0;
2168   SMDS_ElemIteratorPtr it1 = node1->GetInverseElementIterator(SMDSAbs_Face);
2169   while(it1->more()) {
2170     const SMDS_MeshElement * e = it1->next();
2171     if ( e->NbNodes() == 3 ) {
2172       SMDS_ElemIteratorPtr it2 = e->nodesIterator();
2173       while(it2->more()) {
2174         const SMDS_MeshElement* n = it2->next();
2175         if( n!=node1 &&
2176             n!=node2 &&
2177             n!=node3 )
2178         {
2179           e = 0;
2180           break;
2181         }
2182       }
2183       if ( e )
2184         return static_cast<const SMDS_MeshFace *> (e);
2185     }
2186   }
2187   return 0;
2188 }
2189
2190 SMDS_MeshFace* SMDS_Mesh::FindFaceOrCreate(const SMDS_MeshNode *node1,
2191                                            const SMDS_MeshNode *node2,
2192                                            const SMDS_MeshNode *node3)
2193 {
2194   SMDS_MeshFace * toReturn=NULL;
2195   toReturn = const_cast<SMDS_MeshFace*>(FindFace(node1,node2,node3));
2196   if(toReturn==NULL) {
2197     int ID = myElementIDFactory->GetFreeID();
2198     toReturn = createTriangle(node1,node2,node3, ID);
2199   }
2200   return toReturn;
2201 }
2202
2203
2204 //=======================================================================
2205 //function : FindFace
2206 //purpose  :
2207 //=======================================================================
2208
2209 const SMDS_MeshFace* SMDS_Mesh::FindFace(int idnode1, int idnode2,
2210                                          int idnode3, int idnode4) const
2211 {
2212   const SMDS_MeshNode * node1=FindNode(idnode1);
2213   const SMDS_MeshNode * node2=FindNode(idnode2);
2214   const SMDS_MeshNode * node3=FindNode(idnode3);
2215   const SMDS_MeshNode * node4=FindNode(idnode4);
2216   return FindFace(node1, node2, node3, node4);
2217 }
2218
2219 const SMDS_MeshFace* SMDS_Mesh::FindFace(const SMDS_MeshNode *node1,
2220                                          const SMDS_MeshNode *node2,
2221                                          const SMDS_MeshNode *node3,
2222                                          const SMDS_MeshNode *node4)
2223 {
2224   if ( !node1 ) return 0;
2225   SMDS_ElemIteratorPtr it1 = node1->GetInverseElementIterator(SMDSAbs_Face);
2226   while(it1->more()) {
2227     const SMDS_MeshElement * e = it1->next();
2228     if ( e->NbNodes() == 4 ) {
2229       SMDS_ElemIteratorPtr it2 = e->nodesIterator();
2230       while(it2->more()) {
2231         const SMDS_MeshElement* n = it2->next();
2232         if( n!=node1 &&
2233             n!=node2 &&
2234             n!=node3 &&
2235             n!=node4 )
2236         {
2237           e = 0;
2238           break;
2239         }
2240       }
2241       if ( e )
2242         return static_cast<const SMDS_MeshFace *> (e);
2243     }
2244   }
2245   return 0;
2246 }
2247
2248 SMDS_MeshFace* SMDS_Mesh::FindFaceOrCreate(const SMDS_MeshNode *node1,
2249                                            const SMDS_MeshNode *node2,
2250                                            const SMDS_MeshNode *node3,
2251                                            const SMDS_MeshNode *node4)
2252 {
2253   SMDS_MeshFace * toReturn=NULL;
2254   toReturn=const_cast<SMDS_MeshFace*>(FindFace(node1,node2,node3,node4));
2255   if(toReturn==NULL) {
2256     int ID = myElementIDFactory->GetFreeID();
2257     toReturn=createQuadrangle(node1,node2,node3,node4,ID);
2258   }
2259   return toReturn;
2260 }
2261
2262
2263 //=======================================================================
2264 //function : FindFace
2265 //purpose  :quadratic triangle
2266 //=======================================================================
2267
2268 const SMDS_MeshFace* SMDS_Mesh::FindFace(int idnode1, int idnode2,
2269                                          int idnode3, int idnode4,
2270                                          int idnode5, int idnode6) const
2271 {
2272   const SMDS_MeshNode * node1 = FindNode(idnode1);
2273   const SMDS_MeshNode * node2 = FindNode(idnode2);
2274   const SMDS_MeshNode * node3 = FindNode(idnode3);
2275   const SMDS_MeshNode * node4 = FindNode(idnode4);
2276   const SMDS_MeshNode * node5 = FindNode(idnode5);
2277   const SMDS_MeshNode * node6 = FindNode(idnode6);
2278   return FindFace(node1, node2, node3, node4, node5, node6);
2279 }
2280
2281 const SMDS_MeshFace* SMDS_Mesh::FindFace(const SMDS_MeshNode *node1,
2282                                          const SMDS_MeshNode *node2,
2283                                          const SMDS_MeshNode *node3,
2284                                          const SMDS_MeshNode *node4,
2285                                          const SMDS_MeshNode *node5,
2286                                          const SMDS_MeshNode *node6)
2287 {
2288   if ( !node1 ) return 0;
2289   SMDS_ElemIteratorPtr it1 = node1->GetInverseElementIterator(SMDSAbs_Face);
2290   while(it1->more()) {
2291     const SMDS_MeshElement * e = it1->next();
2292     if ( e->NbNodes() == 6 ) {
2293       SMDS_ElemIteratorPtr it2 = e->nodesIterator();
2294       while(it2->more()) {
2295         const SMDS_MeshElement* n = it2->next();
2296         if( n!=node1 &&
2297             n!=node2 &&
2298             n!=node3 &&
2299             n!=node4 &&
2300             n!=node5 &&
2301             n!=node6 )
2302         {
2303           e = 0;
2304           break;
2305         }
2306       }
2307       if ( e )
2308         return static_cast<const SMDS_MeshFace *> (e);
2309     }
2310   }
2311   return 0;
2312 }
2313
2314
2315 //=======================================================================
2316 //function : FindFace
2317 //purpose  : quadratic quadrangle
2318 //=======================================================================
2319
2320 const SMDS_MeshFace* SMDS_Mesh::FindFace(int idnode1, int idnode2,
2321                                          int idnode3, int idnode4,
2322                                          int idnode5, int idnode6,
2323                                          int idnode7, int idnode8) const
2324 {
2325   const SMDS_MeshNode * node1 = FindNode(idnode1);
2326   const SMDS_MeshNode * node2 = FindNode(idnode2);
2327   const SMDS_MeshNode * node3 = FindNode(idnode3);
2328   const SMDS_MeshNode * node4 = FindNode(idnode4);
2329   const SMDS_MeshNode * node5 = FindNode(idnode5);
2330   const SMDS_MeshNode * node6 = FindNode(idnode6);
2331   const SMDS_MeshNode * node7 = FindNode(idnode7);
2332   const SMDS_MeshNode * node8 = FindNode(idnode8);
2333   return FindFace(node1, node2, node3, node4, node5, node6, node7, node8);
2334 }
2335
2336 const SMDS_MeshFace* SMDS_Mesh::FindFace(const SMDS_MeshNode *node1,
2337                                          const SMDS_MeshNode *node2,
2338                                          const SMDS_MeshNode *node3,
2339                                          const SMDS_MeshNode *node4,
2340                                          const SMDS_MeshNode *node5,
2341                                          const SMDS_MeshNode *node6,
2342                                          const SMDS_MeshNode *node7,
2343                                          const SMDS_MeshNode *node8)
2344 {
2345   if ( !node1 ) return 0;
2346   SMDS_ElemIteratorPtr it1 = node1->GetInverseElementIterator(SMDSAbs_Face);
2347   while(it1->more()) {
2348     const SMDS_MeshElement * e = it1->next();
2349     if ( e->NbNodes() == 8 ) {
2350       SMDS_ElemIteratorPtr it2 = e->nodesIterator();
2351       while(it2->more()) {
2352         const SMDS_MeshElement* n = it2->next();
2353         if( n!=node1 &&
2354             n!=node2 &&
2355             n!=node3 &&
2356             n!=node4 &&
2357             n!=node5 &&
2358             n!=node6 &&
2359             n!=node7 &&
2360             n!=node8 )
2361         {
2362           e = 0;
2363           break;
2364         }
2365       }
2366       if ( e )
2367         return static_cast<const SMDS_MeshFace *> (e);
2368     }
2369   }
2370   return 0;
2371 }
2372
2373
2374 //=======================================================================
2375 //function : FindElement
2376 //purpose  :
2377 //=======================================================================
2378
2379 const SMDS_MeshElement* SMDS_Mesh::FindElement(int IDelem) const
2380 {
2381   if ((IDelem <= 0) || IDelem >= myCells.size())
2382   {
2383     MESSAGE("--------------------------------------------------------------------------------- ");
2384     MESSAGE("----------------------------------- bad IDelem " << IDelem << " " << myCells.size());
2385     MESSAGE("--------------------------------------------------------------------------------- ");
2386     // TODO raise an exception
2387     //assert(0);
2388     return 0;
2389   }
2390   return myCells[IDelem];
2391 }
2392
2393 //=======================================================================
2394 //function : FindFace
2395 //purpose  : find polygon
2396 //=======================================================================
2397
2398 const SMDS_MeshFace* SMDS_Mesh::FindFace (const vector<int>& nodes_ids) const
2399 {
2400   int nbnodes = nodes_ids.size();
2401   vector<const SMDS_MeshNode *> poly_nodes (nbnodes);
2402   for (int inode = 0; inode < nbnodes; inode++) {
2403     const SMDS_MeshNode * node = FindNode(nodes_ids[inode]);
2404     if (node == NULL) return NULL;
2405     poly_nodes[inode] = node;
2406   }
2407   return FindFace(poly_nodes);
2408 }
2409
2410 const SMDS_MeshFace* SMDS_Mesh::FindFace (const vector<const SMDS_MeshNode *>& nodes)
2411 {
2412   return (const SMDS_MeshFace*) FindElement( nodes, SMDSAbs_Face );
2413 }
2414
2415
2416 //================================================================================
2417 /*!
2418  * \brief Return element based on all given nodes
2419  *  \param nodes - node of element
2420  *  \param type - type of element
2421  *  \param noMedium - true if medium nodes of quadratic element are not included in <nodes>
2422  *  \retval const SMDS_MeshElement* - found element or NULL
2423  */
2424 //================================================================================
2425
2426 const SMDS_MeshElement* SMDS_Mesh::FindElement (const vector<const SMDS_MeshNode *>& nodes,
2427                                                 const SMDSAbs_ElementType            type,
2428                                                 const bool                           noMedium)
2429 {
2430   if ( nodes.size() > 0 && nodes[0] )
2431   {
2432     SMDS_ElemIteratorPtr itF = nodes[0]->GetInverseElementIterator(type);
2433     while (itF->more())
2434     {
2435       const SMDS_MeshElement* e = itF->next();
2436       int nbNodesToCheck = noMedium ? e->NbCornerNodes() : e->NbNodes();
2437       if ( nbNodesToCheck == nodes.size() )
2438       {
2439         for ( int i = 1; e && i < nodes.size(); ++ i )
2440         {
2441           int nodeIndex = e->GetNodeIndex( nodes[ i ]);
2442           if ( nodeIndex < 0 || nodeIndex >= nbNodesToCheck )
2443             e = 0;
2444         }
2445         if ( e )
2446           return e;
2447       }
2448     }
2449   }
2450   return NULL;
2451 }
2452
2453 //=======================================================================
2454 //function : DumpNodes
2455 //purpose  :
2456 //=======================================================================
2457
2458 void SMDS_Mesh::DumpNodes() const
2459 {
2460         MESSAGE("dump nodes of mesh : ");
2461         SMDS_NodeIteratorPtr itnode=nodesIterator();
2462         while(itnode->more()) ; //MESSAGE(itnode->next());
2463 }
2464
2465 //=======================================================================
2466 //function : Dump0DElements
2467 //purpose  :
2468 //=======================================================================
2469 void SMDS_Mesh::Dump0DElements() const
2470 {
2471   MESSAGE("dump 0D elements of mesh : ");
2472   SMDS_ElemIteratorPtr it0d = elementsIterator(SMDSAbs_0DElement);
2473   while(it0d->more()) ; //MESSAGE(it0d->next());
2474 }
2475
2476 //=======================================================================
2477 //function : DumpEdges
2478 //purpose  :
2479 //=======================================================================
2480
2481 void SMDS_Mesh::DumpEdges() const
2482 {
2483         MESSAGE("dump edges of mesh : ");
2484         SMDS_EdgeIteratorPtr itedge=edgesIterator();
2485         while(itedge->more()) ; //MESSAGE(itedge->next());
2486 }
2487
2488 //=======================================================================
2489 //function : DumpFaces
2490 //purpose  :
2491 //=======================================================================
2492
2493 void SMDS_Mesh::DumpFaces() const
2494 {
2495         MESSAGE("dump faces of mesh : ");
2496         SMDS_FaceIteratorPtr itface=facesIterator();
2497         while(itface->more()) ; //MESSAGE(itface->next());
2498 }
2499
2500 //=======================================================================
2501 //function : DumpVolumes
2502 //purpose  :
2503 //=======================================================================
2504
2505 void SMDS_Mesh::DumpVolumes() const
2506 {
2507         MESSAGE("dump volumes of mesh : ");
2508         SMDS_VolumeIteratorPtr itvol=volumesIterator();
2509         while(itvol->more()) ; //MESSAGE(itvol->next());
2510 }
2511
2512 //=======================================================================
2513 //function : DebugStats
2514 //purpose  :
2515 //=======================================================================
2516
2517 void SMDS_Mesh::DebugStats() const
2518 {
2519   MESSAGE("Debug stats of mesh : ");
2520
2521   MESSAGE("===== NODES ====="<<NbNodes());
2522   MESSAGE("===== 0DELEMS ====="<<Nb0DElements());
2523   MESSAGE("===== EDGES ====="<<NbEdges());
2524   MESSAGE("===== FACES ====="<<NbFaces());
2525   MESSAGE("===== VOLUMES ====="<<NbVolumes());
2526
2527   MESSAGE("End Debug stats of mesh ");
2528
2529   //#ifdef DEB
2530
2531   SMDS_NodeIteratorPtr itnode=nodesIterator();
2532   int sizeofnodes = 0;
2533   int sizeoffaces = 0;
2534
2535   while(itnode->more())
2536   {
2537     const SMDS_MeshNode *node = itnode->next();
2538
2539     sizeofnodes += sizeof(*node);
2540
2541     SMDS_ElemIteratorPtr it = node->GetInverseElementIterator();
2542     while(it->more())
2543     {
2544       const SMDS_MeshElement *me = it->next();
2545       sizeofnodes += sizeof(me);
2546     }
2547   }
2548
2549   SMDS_FaceIteratorPtr itface=facesIterator();
2550   while(itface->more())
2551   {
2552     const SMDS_MeshElement *face = itface->next();
2553     sizeoffaces += sizeof(*face);
2554   }
2555
2556   MESSAGE("total size of node elements = " << sizeofnodes);;
2557   MESSAGE("total size of face elements = " << sizeoffaces);;
2558
2559   //#endif
2560 }
2561
2562 ///////////////////////////////////////////////////////////////////////////////
2563 /// Return the number of nodes
2564 ///////////////////////////////////////////////////////////////////////////////
2565 int SMDS_Mesh::NbNodes() const
2566 {
2567         //MESSAGE(myGrid->GetNumberOfPoints());
2568         //MESSAGE(myInfo.NbNodes());
2569         //MESSAGE(myNodeMax);
2570     return myInfo.NbNodes();
2571 }
2572
2573 ///////////////////////////////////////////////////////////////////////////////
2574 /// Return the number of 0D elements
2575 ///////////////////////////////////////////////////////////////////////////////
2576 int SMDS_Mesh::Nb0DElements() const
2577 {
2578   return myInfo.Nb0DElements();
2579 }
2580
2581 ///////////////////////////////////////////////////////////////////////////////
2582 /// Return the number of 0D elements
2583 ///////////////////////////////////////////////////////////////////////////////
2584 int SMDS_Mesh::NbBalls() const
2585 {
2586   return myInfo.NbBalls();
2587 }
2588
2589 ///////////////////////////////////////////////////////////////////////////////
2590 /// Return the number of edges (including construction edges)
2591 ///////////////////////////////////////////////////////////////////////////////
2592 int SMDS_Mesh::NbEdges() const
2593 {
2594   return myInfo.NbEdges();
2595 }
2596
2597 ///////////////////////////////////////////////////////////////////////////////
2598 /// Return the number of faces (including construction faces)
2599 ///////////////////////////////////////////////////////////////////////////////
2600 int SMDS_Mesh::NbFaces() const
2601 {
2602   return myInfo.NbFaces();
2603 }
2604
2605 ///////////////////////////////////////////////////////////////////////////////
2606 /// Return the number of volumes
2607 ///////////////////////////////////////////////////////////////////////////////
2608 int SMDS_Mesh::NbVolumes() const
2609 {
2610   return myInfo.NbVolumes();
2611 }
2612
2613 ///////////////////////////////////////////////////////////////////////////////
2614 /// Return the number of child mesh of this mesh.
2615 /// Note that the tree structure of SMDS_Mesh is unused in SMESH
2616 ///////////////////////////////////////////////////////////////////////////////
2617 int SMDS_Mesh::NbSubMesh() const
2618 {
2619   return myChildren.size();
2620 }
2621
2622 ///////////////////////////////////////////////////////////////////////////////
2623 /// Destroy the mesh and all its elements
2624 /// All pointer on elements owned by this mesh become illegals.
2625 ///////////////////////////////////////////////////////////////////////////////
2626 SMDS_Mesh::~SMDS_Mesh()
2627 {
2628   list<SMDS_Mesh*>::iterator itc=myChildren.begin();
2629   while(itc!=myChildren.end())
2630   {
2631     delete *itc;
2632     itc++;
2633   }
2634
2635   if(myParent==NULL)
2636   {
2637     delete myNodeIDFactory;
2638     delete myElementIDFactory;
2639   }
2640   else
2641   {
2642     SMDS_ElemIteratorPtr eIt = elementsIterator();
2643     while ( eIt->more() )
2644       {
2645         const SMDS_MeshElement *elem = eIt->next();
2646         myElementIDFactory->ReleaseID(elem->GetID(), elem->getVtkId());
2647       }
2648     SMDS_NodeIteratorPtr itn = nodesIterator();
2649     while (itn->more())
2650       {
2651         const SMDS_MeshNode *node = itn->next();
2652         ((SMDS_MeshNode*)node)->SetPosition(SMDS_SpacePosition::originSpacePosition());
2653         myNodeIDFactory->ReleaseID(node->GetID(), node->getVtkId());
2654       }
2655   }
2656   myGrid->Delete();
2657
2658   delete myNodePool;
2659   delete myVolumePool;
2660   delete myFacePool;
2661   delete myEdgePool;
2662   delete myBallPool;
2663 }
2664
2665 //================================================================================
2666 /*!
2667  * \brief Clear all data
2668  */
2669 //================================================================================
2670
2671 void SMDS_Mesh::Clear()
2672 {
2673   MESSAGE("SMDS_Mesh::Clear");
2674   if (myParent!=NULL)
2675     {
2676     SMDS_ElemIteratorPtr eIt = elementsIterator();
2677     while ( eIt->more() )
2678       {
2679         const SMDS_MeshElement *elem = eIt->next();
2680         myElementIDFactory->ReleaseID(elem->GetID(), elem->getVtkId());
2681       }
2682     SMDS_NodeIteratorPtr itn = nodesIterator();
2683     while (itn->more())
2684       {
2685         const SMDS_MeshNode *node = itn->next();
2686         myNodeIDFactory->ReleaseID(node->GetID(), node->getVtkId());
2687       }
2688     }
2689   else
2690     {
2691     myNodeIDFactory->Clear();
2692     myElementIDFactory->Clear();
2693     }
2694
2695   // SMDS_ElemIteratorPtr itv = elementsIterator();
2696   // while (itv->more())
2697   //   {
2698   //     SMDS_MeshElement* elem = (SMDS_MeshElement*)(itv->next());
2699   //     SMDSAbs_ElementType aType = elem->GetType();
2700   //     switch (aType)
2701   //     {
2702   //       case SMDSAbs_0DElement:
2703   //         delete elem;
2704   //         break;
2705   //       case SMDSAbs_Edge:
2706   //          myEdgePool->destroy(static_cast<SMDS_VtkEdge*>(elem));
2707   //         break;
2708   //       case SMDSAbs_Face:
2709   //         myFacePool->destroy(static_cast<SMDS_VtkFace*>(elem));
2710   //         break;
2711   //       case SMDSAbs_Volume:
2712   //         myVolumePool->destroy(static_cast<SMDS_VtkVolume*>(elem));
2713   //         break;
2714   //       case SMDSAbs_Ball:
2715   //         myBallPool->destroy(static_cast<SMDS_BallElement*>(elem));
2716   //         break;
2717   //       default:
2718   //         break;
2719   //     }
2720   //   }
2721   myVolumePool->clear();
2722   myFacePool->clear();
2723   myEdgePool->clear();
2724   myBallPool->clear();
2725
2726   clearVector( myCells );
2727   clearVector( myCellIdVtkToSmds );
2728
2729   SMDS_NodeIteratorPtr itn = nodesIterator();
2730   while (itn->more())
2731     {
2732       SMDS_MeshNode *node = (SMDS_MeshNode*)(itn->next());
2733       node->SetPosition(SMDS_SpacePosition::originSpacePosition());
2734       //myNodePool->destroy(node);
2735     }
2736   myNodePool->clear();
2737   clearVector( myNodes );
2738
2739   list<SMDS_Mesh*>::iterator itc=myChildren.begin();
2740   while(itc!=myChildren.end())
2741     (*itc)->Clear();
2742
2743   myModified = false;
2744   myModifTime++;
2745   xmin = 0; xmax = 0;
2746   ymin = 0; ymax = 0;
2747   zmin = 0; zmax = 0;
2748
2749   myInfo.Clear();
2750
2751   myGrid->Initialize();
2752   myGrid->Allocate();
2753   vtkPoints* points = vtkPoints::New();
2754   // rnv: to fix bug "21125: EDF 1233 SMESH: Degrardation of precision in a test case for quadratic conversion"
2755   // using double type for storing coordinates of nodes instead float.
2756   points->SetDataType(VTK_DOUBLE);
2757   points->SetNumberOfPoints(0 /*SMDS_Mesh::chunkSize*/);
2758   myGrid->SetPoints( points );
2759   points->Delete();
2760   myGrid->BuildLinks();
2761 }
2762
2763 ///////////////////////////////////////////////////////////////////////////////
2764 /// Return true if this mesh create faces with edges.
2765 /// A false returned value mean that faces are created with nodes. A concequence
2766 /// is, iteration on edges (SMDS_Element::edgesIterator) will be unavailable.
2767 ///////////////////////////////////////////////////////////////////////////////
2768 bool SMDS_Mesh::hasConstructionEdges()
2769 {
2770         return myHasConstructionEdges;
2771 }
2772
2773 ///////////////////////////////////////////////////////////////////////////////
2774 /// Return true if this mesh create volumes with faces
2775 /// A false returned value mean that volumes are created with nodes or edges.
2776 /// (see hasConstructionEdges)
2777 /// A concequence is, iteration on faces (SMDS_Element::facesIterator) will be
2778 /// unavailable.
2779 ///////////////////////////////////////////////////////////////////////////////
2780 bool SMDS_Mesh::hasConstructionFaces()
2781 {
2782         return myHasConstructionFaces;
2783 }
2784
2785 ///////////////////////////////////////////////////////////////////////////////
2786 /// Return true if nodes are linked to the finit elements, they are belonging to.
2787 /// Currently, It always return true.
2788 ///////////////////////////////////////////////////////////////////////////////
2789 bool SMDS_Mesh::hasInverseElements()
2790 {
2791         return myHasInverseElements;
2792 }
2793
2794 ///////////////////////////////////////////////////////////////////////////////
2795 /// Make this mesh creating construction edges (see hasConstructionEdges)
2796 /// @param b true to have construction edges, else false.
2797 ///////////////////////////////////////////////////////////////////////////////
2798 void SMDS_Mesh::setConstructionEdges(bool b)
2799 {
2800         myHasConstructionEdges=b;
2801 }
2802
2803 ///////////////////////////////////////////////////////////////////////////////
2804 /// Make this mesh creating construction faces (see hasConstructionFaces)
2805 /// @param b true to have construction faces, else false.
2806 ///////////////////////////////////////////////////////////////////////////////
2807 void SMDS_Mesh::setConstructionFaces(bool b)
2808 {
2809          myHasConstructionFaces=b;
2810 }
2811
2812 ///////////////////////////////////////////////////////////////////////////////
2813 /// Make this mesh creating link from nodes to elements (see hasInverseElements)
2814 /// @param b true to link nodes to elements, else false.
2815 ///////////////////////////////////////////////////////////////////////////////
2816 void SMDS_Mesh::setInverseElements(bool b)
2817 {
2818   if(!b) MESSAGE("Error : inverseElement=false not implemented");
2819   myHasInverseElements=b;
2820 }
2821
2822 namespace {
2823
2824   //================================================================================
2825   /*!
2826    * \brief Iterator on elements in id increasing order
2827    */
2828   //================================================================================
2829
2830   template <typename ELEM=const SMDS_MeshElement*>
2831   class IdSortedIterator : public SMDS_Iterator<ELEM>
2832   {
2833     SMDS_MeshElementIDFactory&       myIDFact;
2834     int                              myID, myMaxID, myNbFound, myTotalNb;
2835     SMDSAbs_ElementType              myType;
2836     ELEM                             myElem;
2837
2838   public:
2839     IdSortedIterator(const SMDS_MeshElementIDFactory& fact,
2840                      const SMDSAbs_ElementType        type, // SMDSAbs_All NOT allowed!!! 
2841                      const int                        totalNb)
2842       :myIDFact( fact ),
2843        myID(1), myMaxID( myIDFact.GetMaxID() ),myNbFound(0), myTotalNb( totalNb ),
2844        myType( type ),
2845        myElem(0)
2846     {
2847       next();
2848     }
2849     bool more()
2850     {
2851       return myElem;
2852     }
2853     ELEM next()
2854     {
2855       ELEM current = myElem;
2856
2857       for ( myElem = 0;  !myElem && myNbFound < myTotalNb && myID <= myMaxID; ++myID )
2858         if ((myElem = (ELEM) myIDFact.MeshElement( myID ))
2859             && myElem->GetType() != myType )
2860           myElem = 0;
2861
2862       myNbFound += bool(myElem);
2863
2864       return current;
2865     }
2866   };
2867
2868   //================================================================================
2869   /*!
2870    * \brief Iterator on vector of elements, possibly being resized while iteration
2871    */
2872   //================================================================================
2873
2874   template<typename RETURN_VALUE,
2875            typename VECTOR_VALUE=SMDS_MeshCell*,
2876            typename VALUE_FILTER=SMDS::NonNullFilter<VECTOR_VALUE> >
2877   class ElemVecIterator: public SMDS_Iterator<RETURN_VALUE>
2878   {
2879     const std::vector<VECTOR_VALUE>& _vector;
2880     size_t                           _index;
2881     bool                             _more;
2882     VALUE_FILTER                     _filter;
2883   public:
2884     ElemVecIterator(const std::vector<VECTOR_VALUE>& vec,
2885                     const VALUE_FILTER&              filter=VALUE_FILTER() )
2886       :_vector( vec ), _index(0), _more( !vec.empty() ), _filter( filter )
2887     {
2888       if ( _more && !_filter( _vector[ _index ]))
2889         next();
2890     }
2891     virtual bool more()
2892     {
2893       return _more;
2894     }
2895     virtual RETURN_VALUE next()
2896     {
2897       if ( !_more ) return NULL;
2898       VECTOR_VALUE current = _vector[ _index ];
2899       _more = 0;
2900       while ( !_more && ++_index < _vector.size() )
2901         _more = _filter( _vector[ _index ]);
2902       return (RETURN_VALUE) current;
2903     }
2904   };
2905 }
2906
2907 ///////////////////////////////////////////////////////////////////////////////
2908 /// Return an iterator on nodes of the current mesh factory
2909 ///////////////////////////////////////////////////////////////////////////////
2910
2911 SMDS_NodeIteratorPtr SMDS_Mesh::nodesIterator(bool idInceasingOrder) const
2912 {
2913   // naturally always sorted by ID
2914   typedef ElemVecIterator<const SMDS_MeshNode*, SMDS_MeshNode*> TIterator;
2915   return SMDS_NodeIteratorPtr( new TIterator(myNodes));
2916 }
2917
2918 SMDS_ElemIteratorPtr SMDS_Mesh::elementGeomIterator(SMDSAbs_GeometryType type) const
2919 {
2920   // naturally always sorted by ID
2921   typedef ElemVecIterator
2922     < const SMDS_MeshElement*, SMDS_MeshCell*, SMDS_MeshElement::GeomFilter > TIterator;
2923   return SMDS_ElemIteratorPtr
2924     (new TIterator(myCells, SMDS_MeshElement::GeomFilter( type )));
2925 }
2926
2927 SMDS_ElemIteratorPtr SMDS_Mesh::elementEntityIterator(SMDSAbs_EntityType type) const
2928 {
2929   if ( type == SMDSEntity_Node )
2930   {
2931     typedef ElemVecIterator<const SMDS_MeshElement*, SMDS_MeshNode*> TIterator;
2932     return SMDS_ElemIteratorPtr( new TIterator(myNodes));
2933   }
2934   // naturally always sorted by ID
2935   typedef ElemVecIterator
2936     < const SMDS_MeshElement*, SMDS_MeshCell*, SMDS_MeshElement::EntityFilter > TIterator;
2937   return SMDS_ElemIteratorPtr
2938     (new TIterator(myCells, SMDS_MeshElement::EntityFilter( type )));
2939 }
2940
2941 ///////////////////////////////////////////////////////////////////////////////
2942 /// Return an iterator on elements of the current mesh factory
2943 ///////////////////////////////////////////////////////////////////////////////
2944 SMDS_ElemIteratorPtr SMDS_Mesh::elementsIterator(SMDSAbs_ElementType type) const
2945 {
2946   // naturally always sorted by ID
2947   switch ( type ) {
2948
2949   case SMDSAbs_All:
2950     return SMDS_ElemIteratorPtr (new ElemVecIterator<const SMDS_MeshElement*>(myCells));
2951
2952   case SMDSAbs_Node:
2953     return SMDS_ElemIteratorPtr
2954       ( new ElemVecIterator<const SMDS_MeshElement*, SMDS_MeshNode*>( myNodes ));
2955
2956   default:
2957     typedef ElemVecIterator
2958       < const SMDS_MeshElement*, SMDS_MeshCell*, SMDS_MeshElement::TypeFilter > TIterator;
2959     return SMDS_ElemIteratorPtr (new TIterator(myCells, SMDS_MeshElement::TypeFilter( type )));
2960   }
2961   return SMDS_ElemIteratorPtr();
2962 }
2963
2964 ///////////////////////////////////////////////////////////////////////////////
2965 ///Return an iterator on edges of the current mesh.
2966 ///////////////////////////////////////////////////////////////////////////////
2967
2968 SMDS_EdgeIteratorPtr SMDS_Mesh::edgesIterator(bool idInceasingOrder) const
2969 {
2970   // naturally always sorted by ID
2971   typedef ElemVecIterator
2972     < const SMDS_MeshEdge*, SMDS_MeshCell*, SMDS_MeshElement::TypeFilter > TIterator;
2973   return SMDS_EdgeIteratorPtr
2974     (new TIterator(myCells, SMDS_MeshElement::TypeFilter( SMDSAbs_Edge )));
2975 }
2976
2977 ///////////////////////////////////////////////////////////////////////////////
2978 ///Return an iterator on faces of the current mesh.
2979 ///////////////////////////////////////////////////////////////////////////////
2980
2981 SMDS_FaceIteratorPtr SMDS_Mesh::facesIterator(bool idInceasingOrder) const
2982 {
2983   // naturally always sorted by ID
2984   typedef ElemVecIterator
2985     < const SMDS_MeshFace*, SMDS_MeshCell*, SMDS_MeshElement::TypeFilter > TIterator;
2986   return SMDS_FaceIteratorPtr
2987     (new TIterator(myCells, SMDS_MeshElement::TypeFilter( SMDSAbs_Face )));
2988 }
2989
2990 ///////////////////////////////////////////////////////////////////////////////
2991 ///Return an iterator on volumes of the current mesh.
2992 ///////////////////////////////////////////////////////////////////////////////
2993
2994 SMDS_VolumeIteratorPtr SMDS_Mesh::volumesIterator(bool idInceasingOrder) const
2995 {
2996   // naturally always sorted by ID
2997   typedef ElemVecIterator
2998     < const SMDS_MeshVolume*, SMDS_MeshCell*, SMDS_MeshElement::TypeFilter > TIterator;
2999   return SMDS_VolumeIteratorPtr
3000     (new TIterator(myCells, SMDS_MeshElement::TypeFilter( SMDSAbs_Volume )));
3001 }
3002
3003 ///////////////////////////////////////////////////////////////////////////////
3004 /// Do intersection of sets (more than 2)
3005 ///////////////////////////////////////////////////////////////////////////////
3006 static set<const SMDS_MeshElement*> * intersectionOfSets(
3007         set<const SMDS_MeshElement*> vs[], int numberOfSets)
3008 {
3009         set<const SMDS_MeshElement*>* rsetA=new set<const SMDS_MeshElement*>(vs[0]);
3010         set<const SMDS_MeshElement*>* rsetB;
3011
3012         for(int i=0; i<numberOfSets-1; i++)
3013         {
3014                 rsetB=new set<const SMDS_MeshElement*>();
3015                 set_intersection(
3016                         rsetA->begin(), rsetA->end(),
3017                         vs[i+1].begin(), vs[i+1].end(),
3018                         inserter(*rsetB, rsetB->begin()));
3019                 delete rsetA;
3020                 rsetA=rsetB;
3021         }
3022         return rsetA;
3023 }
3024
3025 ///////////////////////////////////////////////////////////////////////////////
3026 /// Return the list of finite elements owning the given element: elements
3027 /// containing all the nodes of the given element, for instance faces and
3028 /// volumes containing a given edge.
3029 ///////////////////////////////////////////////////////////////////////////////
3030 static set<const SMDS_MeshElement*> * getFinitElements(const SMDS_MeshElement * element)
3031 {
3032         int numberOfSets=element->NbNodes();
3033         set<const SMDS_MeshElement*> *initSet = new set<const SMDS_MeshElement*>[numberOfSets];
3034
3035         SMDS_ElemIteratorPtr itNodes=element->nodesIterator();
3036
3037         int i=0;
3038         while(itNodes->more())
3039         {
3040           const SMDS_MeshElement* node = itNodes->next();
3041           MYASSERT(node);
3042                 const SMDS_MeshNode * n=static_cast<const SMDS_MeshNode*>(node);
3043                 SMDS_ElemIteratorPtr itFe = n->GetInverseElementIterator();
3044
3045                 //initSet[i]=set<const SMDS_MeshElement*>();
3046                 while(itFe->more())
3047                 {
3048                   const SMDS_MeshElement* elem = itFe->next();
3049                   MYASSERT(elem);
3050                   initSet[i].insert(elem);
3051
3052                 }
3053
3054                 i++;
3055         }
3056         set<const SMDS_MeshElement*> *retSet=intersectionOfSets(initSet, numberOfSets);
3057 //         MESSAGE("nb elems " << i << " intersection " << retSet->size());
3058         delete [] initSet;
3059         return retSet;
3060 }
3061
3062 ///////////////////////////////////////////////////////////////////////////////
3063 /// Return the list of nodes used only by the given elements
3064 ///////////////////////////////////////////////////////////////////////////////
3065 static set<const SMDS_MeshElement*> * getExclusiveNodes(
3066         set<const SMDS_MeshElement*>& elements)
3067 {
3068         set<const SMDS_MeshElement*> * toReturn=new set<const SMDS_MeshElement*>();
3069         set<const SMDS_MeshElement*>::iterator itElements=elements.begin();
3070
3071         while(itElements!=elements.end())
3072         {
3073                 SMDS_ElemIteratorPtr itNodes = (*itElements)->nodesIterator();
3074                 itElements++;
3075
3076                 while(itNodes->more())
3077                 {
3078                         const SMDS_MeshNode * n=static_cast<const SMDS_MeshNode*>(itNodes->next());
3079                         SMDS_ElemIteratorPtr itFe = n->GetInverseElementIterator();
3080                         set<const SMDS_MeshElement*> s;
3081                         while(itFe->more())
3082                           s.insert(itFe->next());
3083                         if(s==elements) toReturn->insert(n);
3084                 }
3085         }
3086         return toReturn;
3087 }
3088
3089 ///////////////////////////////////////////////////////////////////////////////
3090 ///Find the children of an element that are made of given nodes
3091 ///@param setOfChildren The set in which matching children will be inserted
3092 ///@param element The element were to search matching children
3093 ///@param nodes The nodes that the children must have to be selected
3094 ///////////////////////////////////////////////////////////////////////////////
3095 void SMDS_Mesh::addChildrenWithNodes(set<const SMDS_MeshElement*>& setOfChildren,
3096                                      const SMDS_MeshElement *      element,
3097                                      set<const SMDS_MeshElement*>& nodes)
3098 {
3099   switch(element->GetType())
3100     {
3101     case SMDSAbs_Node:
3102       MESSAGE("Internal Error: This should not happen");
3103       break;
3104     case SMDSAbs_0DElement:
3105       {
3106       }
3107       break;
3108     case SMDSAbs_Edge:
3109         {
3110                 SMDS_ElemIteratorPtr itn=element->nodesIterator();
3111                 while(itn->more())
3112                 {
3113                         const SMDS_MeshElement * e=itn->next();
3114                         if(nodes.find(e)!=nodes.end())
3115                         {
3116                           setOfChildren.insert(element);
3117                           break;
3118                         }
3119                 }
3120         } break;
3121     case SMDSAbs_Face:
3122         {
3123                 SMDS_ElemIteratorPtr itn=element->nodesIterator();
3124                 while(itn->more())
3125                 {
3126                         const SMDS_MeshElement * e=itn->next();
3127                         if(nodes.find(e)!=nodes.end())
3128                         {
3129                           setOfChildren.insert(element);
3130                           break;
3131                         }
3132                 }
3133                 if(hasConstructionEdges())
3134                 {
3135                         SMDS_ElemIteratorPtr ite=element->edgesIterator();
3136                         while(ite->more())
3137                                 addChildrenWithNodes(setOfChildren, ite->next(), nodes);
3138                 }
3139         } break;
3140     case SMDSAbs_Volume:
3141         {
3142                 if(hasConstructionFaces())
3143                 {
3144                         SMDS_ElemIteratorPtr ite=element->facesIterator();
3145                         while(ite->more())
3146                                 addChildrenWithNodes(setOfChildren, ite->next(), nodes);
3147                 }
3148                 else if(hasConstructionEdges())
3149                 {
3150                         SMDS_ElemIteratorPtr ite=element->edgesIterator();
3151                         while(ite->more())
3152                                 addChildrenWithNodes(setOfChildren, ite->next(), nodes);
3153                 }
3154         }
3155     }
3156 }
3157
3158 ///////////////////////////////////////////////////////////////////////////////
3159 ///@param elem The element to delete
3160 ///@param removenodes if true remaining nodes will be removed
3161 ///////////////////////////////////////////////////////////////////////////////
3162 void SMDS_Mesh::RemoveElement(const SMDS_MeshElement * elem,
3163                               const bool removenodes)
3164 {
3165   list<const SMDS_MeshElement *> removedElems;
3166   list<const SMDS_MeshElement *> removedNodes;
3167   RemoveElement( elem, removedElems, removedNodes, removenodes );
3168 }
3169
3170 ///////////////////////////////////////////////////////////////////////////////
3171 ///@param elem The element to delete
3172 ///@param removedElems to be filled with all removed elements
3173 ///@param removedNodes to be filled with all removed nodes
3174 ///@param removenodes if true remaining nodes will be removed
3175 ///////////////////////////////////////////////////////////////////////////////
3176 void SMDS_Mesh::RemoveElement(const SMDS_MeshElement *        elem,
3177                               list<const SMDS_MeshElement *>& removedElems,
3178                               list<const SMDS_MeshElement *>& removedNodes,
3179                               bool                            removenodes)
3180 {
3181   //MESSAGE("SMDS_Mesh::RemoveElement " << elem->getVtkId() << " " << removenodes);
3182   // get finite elements built on elem
3183   set<const SMDS_MeshElement*> * s1;
3184   if (    (elem->GetType() == SMDSAbs_0DElement)
3185       || ((elem->GetType() == SMDSAbs_Edge) && !hasConstructionEdges())
3186       || ((elem->GetType() == SMDSAbs_Face) && !hasConstructionFaces())
3187       ||  (elem->GetType() == SMDSAbs_Volume) )
3188     {
3189       s1 = new set<const SMDS_MeshElement*> ();
3190       s1->insert(elem);
3191     }
3192   else
3193     s1 = getFinitElements(elem);
3194
3195   // get exclusive nodes (which would become free afterwards)
3196   set<const SMDS_MeshElement*> * s2;
3197   if (elem->GetType() == SMDSAbs_Node) // a node is removed
3198     {
3199       // do not remove nodes except elem
3200       s2 = new set<const SMDS_MeshElement*> ();
3201       s2->insert(elem);
3202       removenodes = true;
3203     }
3204   else
3205     s2 = getExclusiveNodes(*s1);
3206
3207   // form the set of finite and construction elements to remove
3208   set<const SMDS_MeshElement*> s3;
3209   set<const SMDS_MeshElement*>::iterator it = s1->begin();
3210   while (it != s1->end())
3211     {
3212       addChildrenWithNodes(s3, *it, *s2);
3213       s3.insert(*it);
3214       it++;
3215     }
3216   if (elem->GetType() != SMDSAbs_Node)
3217     s3.insert(elem);
3218
3219   // remove finite and construction elements
3220   it = s3.begin();
3221   while (it != s3.end())
3222     {
3223       // Remove element from <InverseElements> of its nodes
3224       SMDS_ElemIteratorPtr itn = (*it)->nodesIterator();
3225       while (itn->more())
3226         {
3227           SMDS_MeshNode * n = static_cast<SMDS_MeshNode *> (const_cast<SMDS_MeshElement *> (itn->next()));
3228           n->RemoveInverseElement((*it));
3229         }
3230       int IdToRemove = (*it)->GetID();
3231       int vtkid = (*it)->getVtkId();
3232       //MESSAGE("elem Id to remove " << IdToRemove << " vtkid " << vtkid <<
3233       //        " vtktype " << (*it)->GetVtkType() << " type " << (*it)->GetType());
3234       switch ((*it)->GetType())
3235       {
3236         case SMDSAbs_Node:
3237           MYASSERT("Internal Error: This should not happen")
3238           ;
3239           break;
3240         case SMDSAbs_0DElement:
3241           if (IdToRemove >= 0)
3242             {
3243               myCells[IdToRemove] = 0; // -PR- ici ou dans myElementIDFactory->ReleaseID ?
3244               myInfo.remove(*it);
3245             }
3246           removedElems.push_back((*it));
3247           myElementIDFactory->ReleaseID(IdToRemove, vtkid);
3248           delete (*it);
3249           break;
3250         case SMDSAbs_Edge:
3251           if (IdToRemove >= 0)
3252             {
3253               myCells[IdToRemove] = 0;
3254               myInfo.RemoveEdge(*it);
3255             }
3256           removedElems.push_back((*it));
3257           myElementIDFactory->ReleaseID(IdToRemove, vtkid);
3258           if (const SMDS_VtkEdge* vtkElem = dynamic_cast<const SMDS_VtkEdge*>(*it))
3259             myEdgePool->destroy((SMDS_VtkEdge*) vtkElem);
3260           else
3261             delete (*it);
3262           break;
3263         case SMDSAbs_Face:
3264           if (IdToRemove >= 0)
3265             {
3266               myCells[IdToRemove] = 0;
3267               myInfo.RemoveFace(*it);
3268             }
3269           removedElems.push_back((*it));
3270           myElementIDFactory->ReleaseID(IdToRemove, vtkid);
3271           if (const SMDS_VtkFace* vtkElem = dynamic_cast<const SMDS_VtkFace*>(*it))
3272             myFacePool->destroy((SMDS_VtkFace*) vtkElem);
3273           else
3274             delete (*it);
3275           break;
3276         case SMDSAbs_Volume:
3277           if (IdToRemove >= 0)
3278             {
3279               myCells[IdToRemove] = 0;
3280               myInfo.RemoveVolume(*it);
3281             }
3282           removedElems.push_back((*it));
3283           myElementIDFactory->ReleaseID(IdToRemove, vtkid);
3284           if (const SMDS_VtkVolume* vtkElem = dynamic_cast<const SMDS_VtkVolume*>(*it))
3285             myVolumePool->destroy((SMDS_VtkVolume*) vtkElem);
3286           else
3287             delete (*it);
3288           break;
3289         case SMDSAbs_Ball:
3290           if (IdToRemove >= 0)
3291             {
3292               myCells[IdToRemove] = 0;
3293               myInfo.remove(*it);
3294             }
3295           removedElems.push_back((*it));
3296           myElementIDFactory->ReleaseID(IdToRemove, vtkid);
3297           if (const SMDS_BallElement* vtkElem = dynamic_cast<const SMDS_BallElement*>(*it))
3298             myBallPool->destroy(const_cast<SMDS_BallElement*>( vtkElem ));
3299           else
3300             delete (*it);
3301           break;
3302       }
3303       if (vtkid >= 0)
3304         {
3305           //MESSAGE("VTK_EMPTY_CELL in " << vtkid);
3306           this->myGrid->GetCellTypesArray()->SetValue(vtkid, VTK_EMPTY_CELL);
3307         }
3308       it++;
3309     }
3310
3311   // remove exclusive (free) nodes
3312   if (removenodes)
3313     {
3314       it = s2->begin();
3315       while (it != s2->end())
3316         {
3317           int IdToRemove = (*it)->GetID();
3318           //MESSAGE( "SMDS: RM node " << IdToRemove);
3319           if (IdToRemove >= 0)
3320             {
3321               myNodes[IdToRemove] = 0;
3322               myInfo.myNbNodes--;
3323             }
3324           myNodeIDFactory->ReleaseID((*it)->GetID(), (*it)->getVtkId());
3325           removedNodes.push_back((*it));
3326           if (const SMDS_MeshNode* vtkElem = dynamic_cast<const SMDS_MeshNode*>(*it))
3327           {
3328             ((SMDS_MeshNode*)vtkElem)->SetPosition(SMDS_SpacePosition::originSpacePosition());
3329             myNodePool->destroy((SMDS_MeshNode*) vtkElem);
3330           }
3331           else
3332             delete (*it);
3333           it++;
3334         }
3335     }
3336
3337   delete s2;
3338   delete s1;
3339 }
3340
3341
3342 ///////////////////////////////////////////////////////////////////////////////
3343 ///@param elem The element to delete
3344 ///////////////////////////////////////////////////////////////////////////////
3345 void SMDS_Mesh::RemoveFreeElement(const SMDS_MeshElement * elem)
3346 {
3347   int elemId = elem->GetID();
3348   int vtkId = elem->getVtkId();
3349   //MESSAGE("RemoveFreeElement " << elemId);
3350   SMDSAbs_ElementType aType = elem->GetType();
3351   SMDS_MeshElement* todest = (SMDS_MeshElement*)(elem);
3352   if (aType == SMDSAbs_Node) {
3353     //MESSAGE("Remove free node " << elemId);
3354     // only free node can be removed by this method
3355     const SMDS_MeshNode* n = static_cast<SMDS_MeshNode*>(todest);
3356     SMDS_ElemIteratorPtr itFe = n->GetInverseElementIterator();
3357     if (!itFe->more()) { // free node
3358       myNodes[elemId] = 0;
3359       myInfo.myNbNodes--;
3360       ((SMDS_MeshNode*) n)->SetPosition(SMDS_SpacePosition::originSpacePosition());
3361       ((SMDS_MeshNode*) n)->SMDS_MeshElement::init( -1, -1, -1 ); // avoid reuse
3362       myNodePool->destroy(static_cast<SMDS_MeshNode*>(todest));
3363       myNodeIDFactory->ReleaseID(elemId, vtkId);
3364     }
3365   } else {
3366     if (hasConstructionEdges() || hasConstructionFaces())
3367       // this methods is only for meshes without descendants
3368       return;
3369
3370     //MESSAGE("Remove free element " << elemId);
3371     // Remove element from <InverseElements> of its nodes
3372     SMDS_ElemIteratorPtr itn = elem->nodesIterator();
3373     while (itn->more()) {
3374       SMDS_MeshNode * n = static_cast<SMDS_MeshNode *>
3375         (const_cast<SMDS_MeshElement *>(itn->next()));
3376       n->RemoveInverseElement(elem);
3377     }
3378
3379     // in meshes without descendants elements are always free
3380      switch (aType) {
3381     case SMDSAbs_0DElement:
3382       myCells[elemId] = 0;
3383       myInfo.remove(elem);
3384       delete elem;
3385       break;
3386     case SMDSAbs_Edge:
3387       myCells[elemId] = 0;
3388       myInfo.RemoveEdge(elem);
3389       myEdgePool->destroy(static_cast<SMDS_VtkEdge*>(todest));
3390       break;
3391     case SMDSAbs_Face:
3392       myCells[elemId] = 0;
3393       myInfo.RemoveFace(elem);
3394       myFacePool->destroy(static_cast<SMDS_VtkFace*>(todest));
3395       break;
3396     case SMDSAbs_Volume:
3397       myCells[elemId] = 0;
3398       myInfo.RemoveVolume(elem);
3399       myVolumePool->destroy(static_cast<SMDS_VtkVolume*>(todest));
3400       break;
3401     case SMDSAbs_Ball:
3402       myCells[elemId] = 0;
3403       myInfo.remove(elem);
3404       myBallPool->destroy(static_cast<SMDS_BallElement*>(todest));
3405       break;
3406     default:
3407       break;
3408     }
3409     myElementIDFactory->ReleaseID(elemId, vtkId);
3410
3411     this->myGrid->GetCellTypesArray()->SetValue(vtkId, VTK_EMPTY_CELL);
3412     // --- to do: keep vtkid in a list of reusable cells
3413   }
3414 }
3415
3416 /*!
3417  * Checks if the element is present in mesh.
3418  * Useful to determine dead pointers.
3419  */
3420 bool SMDS_Mesh::Contains (const SMDS_MeshElement* elem) const
3421 {
3422   // we should not imply on validity of *elem, so iterate on containers
3423   // of all types in the hope of finding <elem> somewhere there
3424   SMDS_NodeIteratorPtr itn = nodesIterator();
3425   while (itn->more())
3426     if (elem == itn->next())
3427       return true;
3428   SMDS_ElemIteratorPtr ite = elementsIterator();
3429   while (ite->more())
3430     if (elem == ite->next())
3431       return true;
3432   return false;
3433 }
3434
3435 //=======================================================================
3436 //function : MaxNodeID
3437 //purpose  :
3438 //=======================================================================
3439
3440 int SMDS_Mesh::MaxNodeID() const
3441 {
3442   return myNodeMax;
3443 }
3444
3445 //=======================================================================
3446 //function : MinNodeID
3447 //purpose  :
3448 //=======================================================================
3449
3450 int SMDS_Mesh::MinNodeID() const
3451 {
3452   return myNodeMin;
3453 }
3454
3455 //=======================================================================
3456 //function : MaxElementID
3457 //purpose  :
3458 //=======================================================================
3459
3460 int SMDS_Mesh::MaxElementID() const
3461 {
3462   return myElementIDFactory->GetMaxID();
3463 }
3464
3465 //=======================================================================
3466 //function : MinElementID
3467 //purpose  :
3468 //=======================================================================
3469
3470 int SMDS_Mesh::MinElementID() const
3471 {
3472   return myElementIDFactory->GetMinID();
3473 }
3474
3475 //=======================================================================
3476 //function : Renumber
3477 //purpose  : Renumber all nodes or elements.
3478 //=======================================================================
3479
3480 void SMDS_Mesh::Renumber (const bool isNodes, const int  startID, const int  deltaID)
3481 {
3482     MESSAGE("Renumber");
3483   if ( deltaID == 0 )
3484     return;
3485
3486   SMDS_MeshNodeIDFactory * idFactory =
3487     isNodes ? myNodeIDFactory : myElementIDFactory;
3488
3489   // get existing elements in the order of ID increasing
3490   map<int,SMDS_MeshElement*> elemMap;
3491   SMDS_ElemIteratorPtr idElemIt = idFactory->elementsIterator();
3492   while ( idElemIt->more() ) {
3493     SMDS_MeshElement* elem = const_cast<SMDS_MeshElement*>(idElemIt->next());
3494     int id = elem->GetID();
3495     elemMap.insert(map<int,SMDS_MeshElement*>::value_type(id, elem));
3496   }
3497   // release their ids
3498   map<int,SMDS_MeshElement*>::iterator elemIt = elemMap.begin();
3499   idFactory->Clear();
3500 //   for ( ; elemIt != elemMap.end(); elemIt++ )
3501 //   {
3502 //     int id = (*elemIt).first;
3503 //     idFactory->ReleaseID( id );
3504 //   }
3505   // set new IDs
3506   int ID = startID;
3507   elemIt = elemMap.begin();
3508   for ( ; elemIt != elemMap.end(); elemIt++ )
3509   {
3510     idFactory->BindID( ID, (*elemIt).second );
3511     ID += deltaID;
3512   }
3513 }
3514
3515 //=======================================================================
3516 //function : GetElementType
3517 //purpose  : Return type of element or node with id
3518 //=======================================================================
3519
3520 SMDSAbs_ElementType SMDS_Mesh::GetElementType( const int id, const bool iselem ) const
3521 {
3522   SMDS_MeshElement* elem = 0;
3523   if( iselem )
3524     elem = myElementIDFactory->MeshElement( id );
3525   else
3526     elem = myNodeIDFactory->MeshElement( id );
3527
3528   if( !elem )
3529   {
3530     //throw SALOME_Exception(LOCALIZED ("this element isn't exist"));
3531     return SMDSAbs_All;
3532   }
3533   else
3534     return elem->GetType();
3535 }
3536
3537
3538
3539 //********************************************************************
3540 //********************************************************************
3541 //********                                                   *********
3542 //*****       Methods for addition of quadratic elements        ******
3543 //********                                                   *********
3544 //********************************************************************
3545 //********************************************************************
3546
3547 //=======================================================================
3548 //function : AddEdgeWithID
3549 //purpose  :
3550 //=======================================================================
3551 SMDS_MeshEdge* SMDS_Mesh::AddEdgeWithID(int n1, int n2, int n12, int ID)
3552 {
3553   return SMDS_Mesh::AddEdgeWithID
3554     ((SMDS_MeshNode*) myNodeIDFactory->MeshElement(n1),
3555      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n2),
3556      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n12),
3557      ID);
3558 }
3559
3560 //=======================================================================
3561 //function : AddEdge
3562 //purpose  :
3563 //=======================================================================
3564 SMDS_MeshEdge* SMDS_Mesh::AddEdge(const SMDS_MeshNode* n1,
3565                                   const SMDS_MeshNode* n2,
3566                                   const SMDS_MeshNode* n12)
3567 {
3568   return SMDS_Mesh::AddEdgeWithID(n1, n2, n12, myElementIDFactory->GetFreeID());
3569 }
3570
3571 //=======================================================================
3572 //function : AddEdgeWithID
3573 //purpose  :
3574 //=======================================================================
3575 SMDS_MeshEdge* SMDS_Mesh::AddEdgeWithID(const SMDS_MeshNode * n1,
3576                                         const SMDS_MeshNode * n2,
3577                                         const SMDS_MeshNode * n12,
3578                                         int ID)
3579 {
3580   if ( !n1 || !n2 || !n12 ) return 0;
3581
3582   // --- retrieve nodes ID
3583   myNodeIds.resize(3);
3584   myNodeIds[0] = n1->getVtkId();
3585   myNodeIds[1] = n2->getVtkId();
3586   myNodeIds[2] = n12->getVtkId();
3587
3588   SMDS_MeshEdge * edge = 0;
3589   SMDS_VtkEdge *edgevtk = myEdgePool->getNew();
3590   edgevtk->init(myNodeIds, this);
3591   if (!this->registerElement(ID,edgevtk))
3592   {
3593     this->myGrid->GetCellTypesArray()->SetValue(edgevtk->getVtkId(), VTK_EMPTY_CELL);
3594     myEdgePool->destroy(edgevtk);
3595     return 0;
3596   }
3597   edge = edgevtk;
3598   adjustmyCellsCapacity(ID);
3599   myCells[ID] = edge;
3600   myInfo.myNbQuadEdges++;
3601
3602   //  if (!registerElement(ID, edge)) {
3603   //        RemoveElement(edge, false);
3604   //        edge = NULL;
3605   //  }
3606   return edge;
3607
3608 }
3609
3610
3611 //=======================================================================
3612 //function : AddFace
3613 //purpose  :
3614 //=======================================================================
3615 SMDS_MeshFace* SMDS_Mesh::AddFace(const SMDS_MeshNode * n1,
3616                                   const SMDS_MeshNode * n2,
3617                                   const SMDS_MeshNode * n3,
3618                                   const SMDS_MeshNode * n12,
3619                                   const SMDS_MeshNode * n23,
3620                                   const SMDS_MeshNode * n31)
3621 {
3622   return SMDS_Mesh::AddFaceWithID(n1,n2,n3,n12,n23,n31,
3623                                   myElementIDFactory->GetFreeID());
3624 }
3625
3626 //=======================================================================
3627 //function : AddFaceWithID
3628 //purpose  :
3629 //=======================================================================
3630 SMDS_MeshFace* SMDS_Mesh::AddFaceWithID(int n1, int n2, int n3,
3631                                         int n12,int n23,int n31, int ID)
3632 {
3633   return SMDS_Mesh::AddFaceWithID
3634     ((SMDS_MeshNode *)myNodeIDFactory->MeshElement(n1) ,
3635      (SMDS_MeshNode *)myNodeIDFactory->MeshElement(n2) ,
3636      (SMDS_MeshNode *)myNodeIDFactory->MeshElement(n3) ,
3637      (SMDS_MeshNode *)myNodeIDFactory->MeshElement(n12),
3638      (SMDS_MeshNode *)myNodeIDFactory->MeshElement(n23),
3639      (SMDS_MeshNode *)myNodeIDFactory->MeshElement(n31),
3640      ID);
3641 }
3642
3643 //=======================================================================
3644 //function : AddFaceWithID
3645 //purpose  :
3646 //=======================================================================
3647 SMDS_MeshFace* SMDS_Mesh::AddFaceWithID(const SMDS_MeshNode * n1,
3648                                         const SMDS_MeshNode * n2,
3649                                         const SMDS_MeshNode * n3,
3650                                         const SMDS_MeshNode * n12,
3651                                         const SMDS_MeshNode * n23,
3652                                         const SMDS_MeshNode * n31,
3653                                         int ID)
3654 {
3655   if ( !n1 || !n2 || !n3 || !n12 || !n23 || !n31) return 0;
3656   if(hasConstructionEdges()) {
3657     // creation quadratic edges - not implemented
3658     return 0;
3659   }
3660   else
3661   {
3662     // --- retrieve nodes ID
3663     myNodeIds.resize(6);
3664     myNodeIds[0] = n1->getVtkId();
3665     myNodeIds[1] = n2->getVtkId();
3666     myNodeIds[2] = n3->getVtkId();
3667     myNodeIds[3] = n12->getVtkId();
3668     myNodeIds[4] = n23->getVtkId();
3669     myNodeIds[5] = n31->getVtkId();
3670
3671     SMDS_MeshFace * face = 0;
3672     SMDS_VtkFace *facevtk = myFacePool->getNew();
3673     facevtk->init(myNodeIds, this);
3674     if (!this->registerElement(ID,facevtk))
3675     {
3676       this->myGrid->GetCellTypesArray()->SetValue(facevtk->getVtkId(), VTK_EMPTY_CELL);
3677       myFacePool->destroy(facevtk);
3678       return 0;
3679     }
3680     face = facevtk;
3681     adjustmyCellsCapacity(ID);
3682     myCells[ID] = face;
3683     myInfo.myNbQuadTriangles++;
3684
3685     //    if (!registerElement(ID, face)) {
3686     //      RemoveElement(face, false);
3687     //      face = NULL;
3688     //    }
3689     return face;
3690   }
3691 }
3692
3693
3694 //=======================================================================
3695 //function : AddFace
3696 //purpose  :
3697 //=======================================================================
3698 SMDS_MeshFace* SMDS_Mesh::AddFace(const SMDS_MeshNode * n1,
3699                                   const SMDS_MeshNode * n2,
3700                                   const SMDS_MeshNode * n3,
3701                                   const SMDS_MeshNode * n12,
3702                                   const SMDS_MeshNode * n23,
3703                                   const SMDS_MeshNode * n31,
3704                                   const SMDS_MeshNode * nCenter)
3705 {
3706   return SMDS_Mesh::AddFaceWithID(n1,n2,n3,n12,n23,n31,nCenter,
3707                                   myElementIDFactory->GetFreeID());
3708 }
3709
3710 //=======================================================================
3711 //function : AddFaceWithID
3712 //purpose  :
3713 //=======================================================================
3714 SMDS_MeshFace* SMDS_Mesh::AddFaceWithID(int n1, int n2, int n3,
3715                                         int n12,int n23,int n31, int nCenter, int ID)
3716 {
3717   return SMDS_Mesh::AddFaceWithID
3718     ((SMDS_MeshNode *)myNodeIDFactory->MeshElement(n1) ,
3719      (SMDS_MeshNode *)myNodeIDFactory->MeshElement(n2) ,
3720      (SMDS_MeshNode *)myNodeIDFactory->MeshElement(n3) ,
3721      (SMDS_MeshNode *)myNodeIDFactory->MeshElement(n12),
3722      (SMDS_MeshNode *)myNodeIDFactory->MeshElement(n23),
3723      (SMDS_MeshNode *)myNodeIDFactory->MeshElement(n31),
3724      (SMDS_MeshNode *)myNodeIDFactory->MeshElement(nCenter),
3725      ID);
3726 }
3727
3728 //=======================================================================
3729 //function : AddFaceWithID
3730 //purpose  :
3731 //=======================================================================
3732 SMDS_MeshFace* SMDS_Mesh::AddFaceWithID(const SMDS_MeshNode * n1,
3733                                         const SMDS_MeshNode * n2,
3734                                         const SMDS_MeshNode * n3,
3735                                         const SMDS_MeshNode * n12,
3736                                         const SMDS_MeshNode * n23,
3737                                         const SMDS_MeshNode * n31,
3738                                         const SMDS_MeshNode * nCenter,
3739                                         int ID)
3740 {
3741   if ( !n1 || !n2 || !n3 || !n12 || !n23 || !n31 || !nCenter) return 0;
3742   if(hasConstructionEdges()) {
3743     // creation quadratic edges - not implemented
3744     return 0;
3745   }
3746   else
3747   {
3748     // --- retrieve nodes ID
3749     myNodeIds.resize(7);
3750     myNodeIds[0] = n1->getVtkId();
3751     myNodeIds[1] = n2->getVtkId();
3752     myNodeIds[2] = n3->getVtkId();
3753     myNodeIds[3] = n12->getVtkId();
3754     myNodeIds[4] = n23->getVtkId();
3755     myNodeIds[5] = n31->getVtkId();
3756     myNodeIds[6] = nCenter->getVtkId();
3757
3758     SMDS_MeshFace * face = 0;
3759     SMDS_VtkFace *facevtk = myFacePool->getNew();
3760     facevtk->init(myNodeIds, this);
3761     if (!this->registerElement(ID,facevtk))
3762     {
3763       this->myGrid->GetCellTypesArray()->SetValue(facevtk->getVtkId(), VTK_EMPTY_CELL);
3764       myFacePool->destroy(facevtk);
3765       return 0;
3766     }
3767     face = facevtk;
3768     adjustmyCellsCapacity(ID);
3769     myCells[ID] = face;
3770     myInfo.myNbBiQuadTriangles++;
3771
3772     //    if (!registerElement(ID, face)) {
3773     //      RemoveElement(face, false);
3774     //      face = NULL;
3775     //    }
3776     return face;
3777   }
3778 }
3779
3780
3781 //=======================================================================
3782 //function : AddFace
3783 //purpose  :
3784 //=======================================================================
3785 SMDS_MeshFace* SMDS_Mesh::AddFace(const SMDS_MeshNode * n1,
3786                                   const SMDS_MeshNode * n2,
3787                                   const SMDS_MeshNode * n3,
3788                                   const SMDS_MeshNode * n4,
3789                                   const SMDS_MeshNode * n12,
3790                                   const SMDS_MeshNode * n23,
3791                                   const SMDS_MeshNode * n34,
3792                                   const SMDS_MeshNode * n41)
3793 {
3794   return SMDS_Mesh::AddFaceWithID(n1,n2,n3,n4,n12,n23,n34,n41,
3795                                   myElementIDFactory->GetFreeID());
3796 }
3797
3798 //=======================================================================
3799 //function : AddFaceWithID
3800 //purpose  :
3801 //=======================================================================
3802 SMDS_MeshFace* SMDS_Mesh::AddFaceWithID(int n1, int n2, int n3, int n4,
3803                                         int n12,int n23,int n34,int n41, int ID)
3804 {
3805   return SMDS_Mesh::AddFaceWithID
3806     ((SMDS_MeshNode *)myNodeIDFactory->MeshElement(n1) ,
3807      (SMDS_MeshNode *)myNodeIDFactory->MeshElement(n2) ,
3808      (SMDS_MeshNode *)myNodeIDFactory->MeshElement(n3) ,
3809      (SMDS_MeshNode *)myNodeIDFactory->MeshElement(n4) ,
3810      (SMDS_MeshNode *)myNodeIDFactory->MeshElement(n12),
3811      (SMDS_MeshNode *)myNodeIDFactory->MeshElement(n23),
3812      (SMDS_MeshNode *)myNodeIDFactory->MeshElement(n34),
3813      (SMDS_MeshNode *)myNodeIDFactory->MeshElement(n41),
3814      ID);
3815 }
3816
3817 //=======================================================================
3818 //function : AddFaceWithID
3819 //purpose  :
3820 //=======================================================================
3821 SMDS_MeshFace* SMDS_Mesh::AddFaceWithID(const SMDS_MeshNode * n1,
3822                                         const SMDS_MeshNode * n2,
3823                                         const SMDS_MeshNode * n3,
3824                                         const SMDS_MeshNode * n4,
3825                                         const SMDS_MeshNode * n12,
3826                                         const SMDS_MeshNode * n23,
3827                                         const SMDS_MeshNode * n34,
3828                                         const SMDS_MeshNode * n41,
3829                                         int ID)
3830 {
3831   if ( !n1 || !n2 || !n3 || !n4 || !n12 || !n23 || !n34 || !n41) return 0;
3832   if(hasConstructionEdges()) {
3833     // creation quadratic edges - not implemented
3834     return 0;
3835   }
3836   else
3837   {
3838     // --- retrieve nodes ID
3839     myNodeIds.resize(8);
3840     myNodeIds[0] = n1->getVtkId();
3841     myNodeIds[1] = n2->getVtkId();
3842     myNodeIds[2] = n3->getVtkId();
3843     myNodeIds[3] = n4->getVtkId();
3844     myNodeIds[4] = n12->getVtkId();
3845     myNodeIds[5] = n23->getVtkId();
3846     myNodeIds[6] = n34->getVtkId();
3847     myNodeIds[7] = n41->getVtkId();
3848
3849     SMDS_MeshFace * face = 0;
3850     SMDS_VtkFace *facevtk = myFacePool->getNew();
3851     facevtk->init(myNodeIds, this);
3852     if (!this->registerElement(ID,facevtk))
3853     {
3854       this->myGrid->GetCellTypesArray()->SetValue(facevtk->getVtkId(), VTK_EMPTY_CELL);
3855       myFacePool->destroy(facevtk);
3856       return 0;
3857     }
3858     face = facevtk;
3859     adjustmyCellsCapacity(ID);
3860     myCells[ID] = face;
3861     myInfo.myNbQuadQuadrangles++;
3862
3863     //    if (!registerElement(ID, face)) {
3864     //      RemoveElement(face, false);
3865     //      face = NULL;
3866     //    }
3867     return face;
3868   }
3869 }
3870
3871 //=======================================================================
3872 //function : AddFace
3873 //purpose  :
3874 //=======================================================================
3875 SMDS_MeshFace* SMDS_Mesh::AddFace(const SMDS_MeshNode * n1,
3876                                   const SMDS_MeshNode * n2,
3877                                   const SMDS_MeshNode * n3,
3878                                   const SMDS_MeshNode * n4,
3879                                   const SMDS_MeshNode * n12,
3880                                   const SMDS_MeshNode * n23,
3881                                   const SMDS_MeshNode * n34,
3882                                   const SMDS_MeshNode * n41,
3883                                   const SMDS_MeshNode * nCenter)
3884 {
3885   return SMDS_Mesh::AddFaceWithID(n1,n2,n3,n4,n12,n23,n34,n41,nCenter,
3886                                   myElementIDFactory->GetFreeID());
3887 }
3888
3889 //=======================================================================
3890 //function : AddFaceWithID
3891 //purpose  :
3892 //=======================================================================
3893 SMDS_MeshFace* SMDS_Mesh::AddFaceWithID(int n1, int n2, int n3, int n4,
3894                                         int n12,int n23,int n34,int n41, int nCenter, int ID)
3895 {
3896   return SMDS_Mesh::AddFaceWithID
3897     ((SMDS_MeshNode *)myNodeIDFactory->MeshElement(n1) ,
3898      (SMDS_MeshNode *)myNodeIDFactory->MeshElement(n2) ,
3899      (SMDS_MeshNode *)myNodeIDFactory->MeshElement(n3) ,
3900      (SMDS_MeshNode *)myNodeIDFactory->MeshElement(n4) ,
3901      (SMDS_MeshNode *)myNodeIDFactory->MeshElement(n12),
3902      (SMDS_MeshNode *)myNodeIDFactory->MeshElement(n23),
3903      (SMDS_MeshNode *)myNodeIDFactory->MeshElement(n34),
3904      (SMDS_MeshNode *)myNodeIDFactory->MeshElement(n41),
3905      (SMDS_MeshNode *)myNodeIDFactory->MeshElement(nCenter),
3906      ID);
3907 }
3908
3909 //=======================================================================
3910 //function : AddFaceWithID
3911 //purpose  :
3912 //=======================================================================
3913 SMDS_MeshFace* SMDS_Mesh::AddFaceWithID(const SMDS_MeshNode * n1,
3914                                         const SMDS_MeshNode * n2,
3915                                         const SMDS_MeshNode * n3,
3916                                         const SMDS_MeshNode * n4,
3917                                         const SMDS_MeshNode * n12,
3918                                         const SMDS_MeshNode * n23,
3919                                         const SMDS_MeshNode * n34,
3920                                         const SMDS_MeshNode * n41,
3921                                         const SMDS_MeshNode * nCenter,
3922                                         int ID)
3923 {
3924   if ( !n1 || !n2 || !n3 || !n4 || !n12 || !n23 || !n34 || !n41 || !nCenter) return 0;
3925   if(hasConstructionEdges()) {
3926     // creation quadratic edges - not implemented
3927     return 0;
3928   }
3929   else
3930   {
3931     // --- retrieve nodes ID
3932     myNodeIds.resize(9);
3933     myNodeIds[0] = n1->getVtkId();
3934     myNodeIds[1] = n2->getVtkId();
3935     myNodeIds[2] = n3->getVtkId();
3936     myNodeIds[3] = n4->getVtkId();
3937     myNodeIds[4] = n12->getVtkId();
3938     myNodeIds[5] = n23->getVtkId();
3939     myNodeIds[6] = n34->getVtkId();
3940     myNodeIds[7] = n41->getVtkId();
3941     myNodeIds[8] = nCenter->getVtkId();
3942
3943     SMDS_MeshFace * face = 0;
3944     SMDS_VtkFace *facevtk = myFacePool->getNew();
3945     facevtk->init(myNodeIds, this);
3946     if (!this->registerElement(ID,facevtk))
3947     {
3948       this->myGrid->GetCellTypesArray()->SetValue(facevtk->getVtkId(), VTK_EMPTY_CELL);
3949       myFacePool->destroy(facevtk);
3950       return 0;
3951     }
3952     face = facevtk;
3953     adjustmyCellsCapacity(ID);
3954     myCells[ID] = face;
3955     myInfo.myNbBiQuadQuadrangles++;
3956
3957     //    if (!registerElement(ID, face)) {
3958     //      RemoveElement(face, false);
3959     //      face = NULL;
3960     //    }
3961     return face;
3962   }
3963 }
3964
3965
3966 //=======================================================================
3967 //function : AddVolume
3968 //purpose  :
3969 //=======================================================================
3970 SMDS_MeshVolume* SMDS_Mesh::AddVolume(const SMDS_MeshNode * n1,
3971                                       const SMDS_MeshNode * n2,
3972                                       const SMDS_MeshNode * n3,
3973                                       const SMDS_MeshNode * n4,
3974                                       const SMDS_MeshNode * n12,
3975                                       const SMDS_MeshNode * n23,
3976                                       const SMDS_MeshNode * n31,
3977                                       const SMDS_MeshNode * n14,
3978                                       const SMDS_MeshNode * n24,
3979                                       const SMDS_MeshNode * n34)
3980 {
3981   int ID = myElementIDFactory->GetFreeID();
3982   SMDS_MeshVolume * v = SMDS_Mesh::AddVolumeWithID(n1, n2, n3, n4, n12, n23,
3983                                                    n31, n14, n24, n34, ID);
3984   if(v==NULL) myElementIDFactory->ReleaseID(ID);
3985   return v;
3986 }
3987
3988 //=======================================================================
3989 //function : AddVolumeWithID
3990 //purpose  :
3991 //=======================================================================
3992 SMDS_MeshVolume* SMDS_Mesh::AddVolumeWithID(int n1, int n2, int n3, int n4,
3993                                             int n12,int n23,int n31,
3994                                             int n14,int n24,int n34, int ID)
3995 {
3996   return SMDS_Mesh::AddVolumeWithID
3997     ((SMDS_MeshNode*) myNodeIDFactory->MeshElement(n1) ,
3998      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n2) ,
3999      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n3) ,
4000      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n4) ,
4001      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n12),
4002      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n23),
4003      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n31),
4004      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n14),
4005      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n24),
4006      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n34),
4007      ID);
4008 }
4009
4010 //=======================================================================
4011 //function : AddVolumeWithID
4012 //purpose  : 2d order tetrahedron of 10 nodes
4013 //=======================================================================
4014 SMDS_MeshVolume* SMDS_Mesh::AddVolumeWithID(const SMDS_MeshNode * n1,
4015                                             const SMDS_MeshNode * n2,
4016                                             const SMDS_MeshNode * n3,
4017                                             const SMDS_MeshNode * n4,
4018                                             const SMDS_MeshNode * n12,
4019                                             const SMDS_MeshNode * n23,
4020                                             const SMDS_MeshNode * n31,
4021                                             const SMDS_MeshNode * n14,
4022                                             const SMDS_MeshNode * n24,
4023                                             const SMDS_MeshNode * n34,
4024                                             int ID)
4025 {
4026   if ( !n1 || !n2 || !n3 || !n4 || !n12 || !n23 || !n31 || !n14 || !n24 || !n34)
4027     return 0;
4028   if(hasConstructionFaces()) {
4029     // creation quadratic faces - not implemented
4030     return 0;
4031   }
4032   // --- retrieve nodes ID
4033   myNodeIds.resize(10);
4034   myNodeIds[0] = n1->getVtkId();
4035   myNodeIds[1] = n3->getVtkId();
4036   myNodeIds[2] = n2->getVtkId();
4037   myNodeIds[3] = n4->getVtkId();
4038
4039   myNodeIds[4] = n31->getVtkId();
4040   myNodeIds[5] = n23->getVtkId();
4041   myNodeIds[6] = n12->getVtkId();
4042
4043   myNodeIds[7] = n14->getVtkId();
4044   myNodeIds[8] = n34->getVtkId();
4045   myNodeIds[9] = n24->getVtkId();
4046
4047   SMDS_VtkVolume *volvtk = myVolumePool->getNew();
4048   volvtk->init(myNodeIds, this);
4049   if (!this->registerElement(ID,volvtk))
4050   {
4051     this->myGrid->GetCellTypesArray()->SetValue(volvtk->getVtkId(), VTK_EMPTY_CELL);
4052     myVolumePool->destroy(volvtk);
4053     return 0;
4054   }
4055   adjustmyCellsCapacity(ID);
4056   myCells[ID] = volvtk;
4057   myInfo.myNbQuadTetras++;
4058
4059   //  if (!registerElement(ID, volvtk)) {
4060   //    RemoveElement(volvtk, false);
4061   //    volvtk = NULL;
4062   //  }
4063   return volvtk;
4064 }
4065
4066
4067 //=======================================================================
4068 //function : AddVolume
4069 //purpose  :
4070 //=======================================================================
4071 SMDS_MeshVolume* SMDS_Mesh::AddVolume(const SMDS_MeshNode * n1,
4072                                       const SMDS_MeshNode * n2,
4073                                       const SMDS_MeshNode * n3,
4074                                       const SMDS_MeshNode * n4,
4075                                       const SMDS_MeshNode * n5,
4076                                       const SMDS_MeshNode * n12,
4077                                       const SMDS_MeshNode * n23,
4078                                       const SMDS_MeshNode * n34,
4079                                       const SMDS_MeshNode * n41,
4080                                       const SMDS_MeshNode * n15,
4081                                       const SMDS_MeshNode * n25,
4082                                       const SMDS_MeshNode * n35,
4083                                       const SMDS_MeshNode * n45)
4084 {
4085   int ID = myElementIDFactory->GetFreeID();
4086   SMDS_MeshVolume * v =
4087     SMDS_Mesh::AddVolumeWithID(n1, n2, n3, n4, n5, n12, n23, n34, n41,
4088                                n15, n25, n35, n45, ID);
4089   if(v==NULL) myElementIDFactory->ReleaseID(ID);
4090   return v;
4091 }
4092
4093 //=======================================================================
4094 //function : AddVolumeWithID
4095 //purpose  :
4096 //=======================================================================
4097 SMDS_MeshVolume* SMDS_Mesh::AddVolumeWithID(int n1, int n2, int n3, int n4, int n5,
4098                                             int n12,int n23,int n34,int n41,
4099                                             int n15,int n25,int n35,int n45, int ID)
4100 {
4101   return SMDS_Mesh::AddVolumeWithID
4102     ((SMDS_MeshNode*) myNodeIDFactory->MeshElement(n1) ,
4103      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n2) ,
4104      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n3) ,
4105      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n4) ,
4106      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n5) ,
4107      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n12),
4108      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n23),
4109      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n34),
4110      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n41),
4111      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n15),
4112      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n25),
4113      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n35),
4114      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n45),
4115      ID);
4116 }
4117
4118 //=======================================================================
4119 //function : AddVolumeWithID
4120 //purpose  : 2d order pyramid of 13 nodes
4121 //=======================================================================
4122 SMDS_MeshVolume* SMDS_Mesh::AddVolumeWithID(const SMDS_MeshNode * n1,
4123                                             const SMDS_MeshNode * n2,
4124                                             const SMDS_MeshNode * n3,
4125                                             const SMDS_MeshNode * n4,
4126                                             const SMDS_MeshNode * n5,
4127                                             const SMDS_MeshNode * n12,
4128                                             const SMDS_MeshNode * n23,
4129                                             const SMDS_MeshNode * n34,
4130                                             const SMDS_MeshNode * n41,
4131                                             const SMDS_MeshNode * n15,
4132                                             const SMDS_MeshNode * n25,
4133                                             const SMDS_MeshNode * n35,
4134                                             const SMDS_MeshNode * n45,
4135                                             int ID)
4136 {
4137   if (!n1 || !n2 || !n3 || !n4 || !n5 || !n12 || !n23 ||
4138       !n34 || !n41 || !n15 || !n25 || !n35 || !n45)
4139     return 0;
4140   if(hasConstructionFaces()) {
4141     // creation quadratic faces - not implemented
4142     return 0;
4143   }
4144   // --- retrieve nodes ID
4145   myNodeIds.resize(13);
4146   myNodeIds[0] = n1->getVtkId();
4147   myNodeIds[1] = n4->getVtkId();
4148   myNodeIds[2] = n3->getVtkId();
4149   myNodeIds[3] = n2->getVtkId();
4150   myNodeIds[4] = n5->getVtkId();
4151
4152   myNodeIds[5] = n41->getVtkId();
4153   myNodeIds[6] = n34->getVtkId();
4154   myNodeIds[7] = n23->getVtkId();
4155   myNodeIds[8] = n12->getVtkId();
4156
4157   myNodeIds[9] = n15->getVtkId();
4158   myNodeIds[10] = n45->getVtkId();
4159   myNodeIds[11] = n35->getVtkId();
4160   myNodeIds[12] = n25->getVtkId();
4161
4162   SMDS_VtkVolume *volvtk = myVolumePool->getNew();
4163   volvtk->init(myNodeIds, this);
4164   if (!this->registerElement(ID,volvtk))
4165   {
4166     this->myGrid->GetCellTypesArray()->SetValue(volvtk->getVtkId(), VTK_EMPTY_CELL);
4167     myVolumePool->destroy(volvtk);
4168     return 0;
4169   }
4170   adjustmyCellsCapacity(ID);
4171   myCells[ID] = volvtk;
4172   myInfo.myNbQuadPyramids++;
4173
4174   //  if (!registerElement(ID, volvtk)) {
4175   //    RemoveElement(volvtk, false);
4176   //    volvtk = NULL;
4177   //  }
4178   return volvtk;
4179 }
4180
4181
4182 //=======================================================================
4183 //function : AddVolume
4184 //purpose  :
4185 //=======================================================================
4186 SMDS_MeshVolume* SMDS_Mesh::AddVolume(const SMDS_MeshNode * n1,
4187                                       const SMDS_MeshNode * n2,
4188                                       const SMDS_MeshNode * n3,
4189                                       const SMDS_MeshNode * n4,
4190                                       const SMDS_MeshNode * n5,
4191                                       const SMDS_MeshNode * n6,
4192                                       const SMDS_MeshNode * n12,
4193                                       const SMDS_MeshNode * n23,
4194                                       const SMDS_MeshNode * n31,
4195                                       const SMDS_MeshNode * n45,
4196                                       const SMDS_MeshNode * n56,
4197                                       const SMDS_MeshNode * n64,
4198                                       const SMDS_MeshNode * n14,
4199                                       const SMDS_MeshNode * n25,
4200                                       const SMDS_MeshNode * n36)
4201 {
4202   int ID = myElementIDFactory->GetFreeID();
4203   SMDS_MeshVolume * v =
4204     SMDS_Mesh::AddVolumeWithID(n1, n2, n3, n4, n5, n6, n12, n23, n31,
4205                                n45, n56, n64, n14, n25, n36, ID);
4206   if(v==NULL) myElementIDFactory->ReleaseID(ID);
4207   return v;
4208 }
4209
4210 //=======================================================================
4211 //function : AddVolumeWithID
4212 //purpose  :
4213 //=======================================================================
4214 SMDS_MeshVolume* SMDS_Mesh::AddVolumeWithID(int n1, int n2, int n3,
4215                                             int n4, int n5, int n6,
4216                                             int n12,int n23,int n31,
4217                                             int n45,int n56,int n64,
4218                                             int n14,int n25,int n36, int ID)
4219 {
4220   return SMDS_Mesh::AddVolumeWithID
4221     ((SMDS_MeshNode*) myNodeIDFactory->MeshElement(n1) ,
4222      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n2) ,
4223      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n3) ,
4224      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n4) ,
4225      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n5) ,
4226      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n6) ,
4227      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n12),
4228      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n23),
4229      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n31),
4230      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n45),
4231      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n56),
4232      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n64),
4233      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n14),
4234      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n25),
4235      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n36),
4236      ID);
4237 }
4238
4239 //=======================================================================
4240 //function : AddVolumeWithID
4241 //purpose  : 2d order Pentahedron with 15 nodes
4242 //=======================================================================
4243 SMDS_MeshVolume* SMDS_Mesh::AddVolumeWithID(const SMDS_MeshNode * n1,
4244                                             const SMDS_MeshNode * n2,
4245                                             const SMDS_MeshNode * n3,
4246                                             const SMDS_MeshNode * n4,
4247                                             const SMDS_MeshNode * n5,
4248                                             const SMDS_MeshNode * n6,
4249                                             const SMDS_MeshNode * n12,
4250                                             const SMDS_MeshNode * n23,
4251                                             const SMDS_MeshNode * n31,
4252                                             const SMDS_MeshNode * n45,
4253                                             const SMDS_MeshNode * n56,
4254                                             const SMDS_MeshNode * n64,
4255                                             const SMDS_MeshNode * n14,
4256                                             const SMDS_MeshNode * n25,
4257                                             const SMDS_MeshNode * n36,
4258                                             int ID)
4259 {
4260   if (!n1 || !n2 || !n3 || !n4 || !n5 || !n6 || !n12 || !n23 ||
4261       !n31 || !n45 || !n56 || !n64 || !n14 || !n25 || !n36)
4262     return 0;
4263   if(hasConstructionFaces()) {
4264     // creation quadratic faces - not implemented
4265     return 0;
4266   }
4267   // --- retrieve nodes ID
4268   myNodeIds.resize(15);
4269   myNodeIds[0] = n1->getVtkId();
4270   myNodeIds[1] = n2->getVtkId();
4271   myNodeIds[2] = n3->getVtkId();
4272
4273   myNodeIds[3] = n4->getVtkId();
4274   myNodeIds[4] = n5->getVtkId();
4275   myNodeIds[5] = n6->getVtkId();
4276
4277   myNodeIds[6] = n12->getVtkId();
4278   myNodeIds[7] = n23->getVtkId();
4279   myNodeIds[8] = n31->getVtkId();
4280
4281   myNodeIds[9] = n45->getVtkId();
4282   myNodeIds[10] = n56->getVtkId();
4283   myNodeIds[11] = n64->getVtkId();
4284
4285   myNodeIds[12] = n14->getVtkId();
4286   myNodeIds[13] = n25->getVtkId();
4287   myNodeIds[14] = n36->getVtkId();
4288
4289   SMDS_VtkVolume *volvtk = myVolumePool->getNew();
4290   volvtk->init(myNodeIds, this);
4291   if (!this->registerElement(ID,volvtk))
4292   {
4293     this->myGrid->GetCellTypesArray()->SetValue(volvtk->getVtkId(), VTK_EMPTY_CELL);
4294     myVolumePool->destroy(volvtk);
4295     return 0;
4296   }
4297   adjustmyCellsCapacity(ID);
4298   myCells[ID] = volvtk;
4299   myInfo.myNbQuadPrisms++;
4300
4301   //  if (!registerElement(ID, volvtk)) {
4302   //    RemoveElement(volvtk, false);
4303   //    volvtk = NULL;
4304   //  }
4305   return volvtk;
4306 }
4307
4308
4309 //=======================================================================
4310 //function : AddVolume
4311 //purpose  :
4312 //=======================================================================
4313 SMDS_MeshVolume* SMDS_Mesh::AddVolume(const SMDS_MeshNode * n1,
4314                                       const SMDS_MeshNode * n2,
4315                                       const SMDS_MeshNode * n3,
4316                                       const SMDS_MeshNode * n4,
4317                                       const SMDS_MeshNode * n5,
4318                                       const SMDS_MeshNode * n6,
4319                                       const SMDS_MeshNode * n7,
4320                                       const SMDS_MeshNode * n8,
4321                                       const SMDS_MeshNode * n12,
4322                                       const SMDS_MeshNode * n23,
4323                                       const SMDS_MeshNode * n34,
4324                                       const SMDS_MeshNode * n41,
4325                                       const SMDS_MeshNode * n56,
4326                                       const SMDS_MeshNode * n67,
4327                                       const SMDS_MeshNode * n78,
4328                                       const SMDS_MeshNode * n85,
4329                                       const SMDS_MeshNode * n15,
4330                                       const SMDS_MeshNode * n26,
4331                                       const SMDS_MeshNode * n37,
4332                                       const SMDS_MeshNode * n48)
4333 {
4334   int ID = myElementIDFactory->GetFreeID();
4335   SMDS_MeshVolume * v =
4336     SMDS_Mesh::AddVolumeWithID(n1, n2, n3, n4, n5, n6, n7, n8, n12, n23, n34, n41,
4337                                n56, n67, n78, n85, n15, n26, n37, n48, ID);
4338   if(v==NULL) myElementIDFactory->ReleaseID(ID);
4339   return v;
4340 }
4341
4342 //=======================================================================
4343 //function : AddVolumeWithID
4344 //purpose  :
4345 //=======================================================================
4346 SMDS_MeshVolume* SMDS_Mesh::AddVolumeWithID(int n1, int n2, int n3, int n4,
4347                                             int n5, int n6, int n7, int n8,
4348                                             int n12,int n23,int n34,int n41,
4349                                             int n56,int n67,int n78,int n85,
4350                                             int n15,int n26,int n37,int n48, int ID)
4351 {
4352   return SMDS_Mesh::AddVolumeWithID
4353     ((SMDS_MeshNode*) myNodeIDFactory->MeshElement(n1),
4354      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n2),
4355      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n3),
4356      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n4),
4357      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n5),
4358      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n6),
4359      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n7),
4360      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n8),
4361      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n12),
4362      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n23),
4363      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n34),
4364      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n41),
4365      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n56),
4366      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n67),
4367      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n78),
4368      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n85),
4369      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n15),
4370      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n26),
4371      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n37),
4372      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n48),
4373      ID);
4374 }
4375
4376 //=======================================================================
4377 //function : AddVolumeWithID
4378 //purpose  : 2d order Hexahedrons with 20 nodes
4379 //=======================================================================
4380 SMDS_MeshVolume* SMDS_Mesh::AddVolumeWithID(const SMDS_MeshNode * n1,
4381                                             const SMDS_MeshNode * n2,
4382                                             const SMDS_MeshNode * n3,
4383                                             const SMDS_MeshNode * n4,
4384                                             const SMDS_MeshNode * n5,
4385                                             const SMDS_MeshNode * n6,
4386                                             const SMDS_MeshNode * n7,
4387                                             const SMDS_MeshNode * n8,
4388                                             const SMDS_MeshNode * n12,
4389                                             const SMDS_MeshNode * n23,
4390                                             const SMDS_MeshNode * n34,
4391                                             const SMDS_MeshNode * n41,
4392                                             const SMDS_MeshNode * n56,
4393                                             const SMDS_MeshNode * n67,
4394                                             const SMDS_MeshNode * n78,
4395                                             const SMDS_MeshNode * n85,
4396                                             const SMDS_MeshNode * n15,
4397                                             const SMDS_MeshNode * n26,
4398                                             const SMDS_MeshNode * n37,
4399                                             const SMDS_MeshNode * n48,
4400                                             int ID)
4401 {
4402   if (!n1 || !n2 || !n3 || !n4 || !n5 || !n6 || !n7 || !n8 || !n12 || !n23 ||
4403       !n34 || !n41 || !n56 || !n67 || !n78 || !n85 || !n15 || !n26 || !n37 || !n48)
4404     return 0;
4405   if(hasConstructionFaces()) {
4406     return 0;
4407     // creation quadratic faces - not implemented
4408   }
4409   // --- retrieve nodes ID
4410   myNodeIds.resize(20);
4411   myNodeIds[0] = n1->getVtkId();
4412   myNodeIds[1] = n4->getVtkId();
4413   myNodeIds[2] = n3->getVtkId();
4414   myNodeIds[3] = n2->getVtkId();
4415
4416   myNodeIds[4] = n5->getVtkId();
4417   myNodeIds[5] = n8->getVtkId();
4418   myNodeIds[6] = n7->getVtkId();
4419   myNodeIds[7] = n6->getVtkId();
4420
4421   myNodeIds[8] = n41->getVtkId();
4422   myNodeIds[9] = n34->getVtkId();
4423   myNodeIds[10] = n23->getVtkId();
4424   myNodeIds[11] = n12->getVtkId();
4425
4426   myNodeIds[12] = n85->getVtkId();
4427   myNodeIds[13] = n78->getVtkId();
4428   myNodeIds[14] = n67->getVtkId();
4429   myNodeIds[15] = n56->getVtkId();
4430
4431   myNodeIds[16] = n15->getVtkId();
4432   myNodeIds[17] = n48->getVtkId();
4433   myNodeIds[18] = n37->getVtkId();
4434   myNodeIds[19] = n26->getVtkId();
4435
4436   SMDS_VtkVolume *volvtk = myVolumePool->getNew();
4437   volvtk->init(myNodeIds, this);
4438   if (!this->registerElement(ID,volvtk))
4439   {
4440     this->myGrid->GetCellTypesArray()->SetValue(volvtk->getVtkId(), VTK_EMPTY_CELL);
4441     myVolumePool->destroy(volvtk);
4442     return 0;
4443   }
4444   adjustmyCellsCapacity(ID);
4445   myCells[ID] = volvtk;
4446   myInfo.myNbQuadHexas++;
4447
4448   //  if (!registerElement(ID, volvtk)) {
4449   //    RemoveElement(volvtk, false);
4450   //    volvtk = NULL;
4451   //  }
4452   return volvtk;
4453 }
4454
4455 //=======================================================================
4456 //function : AddVolume
4457 //purpose  :
4458 //=======================================================================
4459 SMDS_MeshVolume* SMDS_Mesh::AddVolume(const SMDS_MeshNode * n1,
4460                                       const SMDS_MeshNode * n2,
4461                                       const SMDS_MeshNode * n3,
4462                                       const SMDS_MeshNode * n4,
4463                                       const SMDS_MeshNode * n5,
4464                                       const SMDS_MeshNode * n6,
4465                                       const SMDS_MeshNode * n7,
4466                                       const SMDS_MeshNode * n8,
4467                                       const SMDS_MeshNode * n12,
4468                                       const SMDS_MeshNode * n23,
4469                                       const SMDS_MeshNode * n34,
4470                                       const SMDS_MeshNode * n41,
4471                                       const SMDS_MeshNode * n56,
4472                                       const SMDS_MeshNode * n67,
4473                                       const SMDS_MeshNode * n78,
4474                                       const SMDS_MeshNode * n85,
4475                                       const SMDS_MeshNode * n15,
4476                                       const SMDS_MeshNode * n26,
4477                                       const SMDS_MeshNode * n37,
4478                                       const SMDS_MeshNode * n48,
4479                                       const SMDS_MeshNode * n1234,
4480                                       const SMDS_MeshNode * n1256,
4481                                       const SMDS_MeshNode * n2367,
4482                                       const SMDS_MeshNode * n3478,
4483                                       const SMDS_MeshNode * n1458,
4484                                       const SMDS_MeshNode * n5678,
4485                                       const SMDS_MeshNode * nCenter)
4486 {
4487   int ID = myElementIDFactory->GetFreeID();
4488   SMDS_MeshVolume * v =
4489     SMDS_Mesh::AddVolumeWithID(n1, n2, n3, n4, n5, n6, n7, n8, n12, n23, n34, n41,
4490                                n56, n67, n78, n85, n15, n26, n37, n48,
4491                                n1234, n1256, n2367, n3478, n1458, n5678, nCenter,
4492                                ID);
4493   if(v==NULL) myElementIDFactory->ReleaseID(ID);
4494   return v;
4495 }
4496
4497 //=======================================================================
4498 //function : AddVolumeWithID
4499 //purpose  :
4500 //=======================================================================
4501 SMDS_MeshVolume* SMDS_Mesh::AddVolumeWithID(int n1, int n2, int n3, int n4,
4502                                             int n5, int n6, int n7, int n8,
4503                                             int n12,int n23,int n34,int n41,
4504                                             int n56,int n67,int n78,int n85,
4505                                             int n15,int n26,int n37,int n48,
4506                                             int n1234,int n1256,int n2367,int n3478,
4507                                             int n1458,int n5678,int nCenter, int ID)
4508 {
4509   return SMDS_Mesh::AddVolumeWithID
4510     ((SMDS_MeshNode*) myNodeIDFactory->MeshElement(n1),
4511      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n2),
4512      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n3),
4513      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n4),
4514      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n5),
4515      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n6),
4516      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n7),
4517      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n8),
4518      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n12),
4519      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n23),
4520      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n34),
4521      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n41),
4522      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n56),
4523      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n67),
4524      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n78),
4525      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n85),
4526      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n15),
4527      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n26),
4528      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n37),
4529      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n48),
4530      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n1234),
4531      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n1256),
4532      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n2367),
4533      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n3478),
4534      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n1458),
4535      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n5678),
4536      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(nCenter),
4537      ID);
4538 }
4539
4540 //=======================================================================
4541 //function : AddVolumeWithID
4542 //purpose  : 2d order Hexahedrons with 20 nodes
4543 //=======================================================================
4544 SMDS_MeshVolume* SMDS_Mesh::AddVolumeWithID(const SMDS_MeshNode * n1,
4545                                             const SMDS_MeshNode * n2,
4546                                             const SMDS_MeshNode * n3,
4547                                             const SMDS_MeshNode * n4,
4548                                             const SMDS_MeshNode * n5,
4549                                             const SMDS_MeshNode * n6,
4550                                             const SMDS_MeshNode * n7,
4551                                             const SMDS_MeshNode * n8,
4552                                             const SMDS_MeshNode * n12,
4553                                             const SMDS_MeshNode * n23,
4554                                             const SMDS_MeshNode * n34,
4555                                             const SMDS_MeshNode * n41,
4556                                             const SMDS_MeshNode * n56,
4557                                             const SMDS_MeshNode * n67,
4558                                             const SMDS_MeshNode * n78,
4559                                             const SMDS_MeshNode * n85,
4560                                             const SMDS_MeshNode * n15,
4561                                             const SMDS_MeshNode * n26,
4562                                             const SMDS_MeshNode * n37,
4563                                             const SMDS_MeshNode * n48,
4564                                             const SMDS_MeshNode * n1234,
4565                                             const SMDS_MeshNode * n1256,
4566                                             const SMDS_MeshNode * n2367,
4567                                             const SMDS_MeshNode * n3478,
4568                                             const SMDS_MeshNode * n1458,
4569                                             const SMDS_MeshNode * n5678,
4570                                             const SMDS_MeshNode * nCenter,
4571                                             int ID)
4572 {
4573   if (!n1 || !n2 || !n3 || !n4 || !n5 || !n6 || !n7 || !n8 || !n12 || !n23 ||
4574       !n34 || !n41 || !n56 || !n67 || !n78 || !n85 || !n15 || !n26 || !n37 || !n48 ||
4575       !n1234 || !n1256 || !n2367 || !n3478 || !n1458 || !n5678 || !nCenter )
4576     return 0;
4577   if(hasConstructionFaces()) {
4578     return 0;
4579     // creation quadratic faces - not implemented
4580   }
4581   // --- retrieve nodes ID
4582   myNodeIds.resize(27);
4583   myNodeIds[0] = n1->getVtkId();
4584   myNodeIds[1] = n4->getVtkId();
4585   myNodeIds[2] = n3->getVtkId();
4586   myNodeIds[3] = n2->getVtkId();
4587
4588   myNodeIds[4] = n5->getVtkId();
4589   myNodeIds[5] = n8->getVtkId();
4590   myNodeIds[6] = n7->getVtkId();
4591   myNodeIds[7] = n6->getVtkId();
4592
4593   myNodeIds[8] = n41->getVtkId();
4594   myNodeIds[9] = n34->getVtkId();
4595   myNodeIds[10] = n23->getVtkId();
4596   myNodeIds[11] = n12->getVtkId();
4597
4598   myNodeIds[12] = n85->getVtkId();
4599   myNodeIds[13] = n78->getVtkId();
4600   myNodeIds[14] = n67->getVtkId();
4601   myNodeIds[15] = n56->getVtkId();
4602
4603   myNodeIds[16] = n15->getVtkId();
4604   myNodeIds[17] = n48->getVtkId();
4605   myNodeIds[18] = n37->getVtkId();
4606   myNodeIds[19] = n26->getVtkId();
4607
4608   myNodeIds[20] = n1256->getVtkId();
4609   myNodeIds[21] = n3478->getVtkId();
4610   myNodeIds[22] = n1458->getVtkId();
4611   myNodeIds[23] = n2367->getVtkId();
4612   myNodeIds[24] = n1234->getVtkId();
4613   myNodeIds[25] = n5678->getVtkId();
4614   myNodeIds[26] = nCenter->getVtkId();
4615
4616   SMDS_VtkVolume *volvtk = myVolumePool->getNew();
4617   volvtk->init(myNodeIds, this);
4618   if (!this->registerElement(ID,volvtk))
4619   {
4620     this->myGrid->GetCellTypesArray()->SetValue(volvtk->getVtkId(), VTK_EMPTY_CELL);
4621     myVolumePool->destroy(volvtk);
4622     return 0;
4623   }
4624   adjustmyCellsCapacity(ID);
4625   myCells[ID] = volvtk;
4626   myInfo.myNbTriQuadHexas++;
4627
4628   return volvtk;
4629 }
4630
4631
4632 void SMDS_Mesh::updateNodeMinMax()
4633 {
4634   myNodeMin = 0;
4635   if (myNodes.size() == 0)
4636   {
4637     myNodeMax=0;
4638     return;
4639   }
4640   while (!myNodes[myNodeMin] && (myNodeMin<myNodes.size()))
4641     myNodeMin++;
4642   myNodeMax=myNodes.size()-1;
4643   while (!myNodes[myNodeMax] && (myNodeMin>=0))
4644     myNodeMin--;
4645 }
4646
4647 void SMDS_Mesh::incrementNodesCapacity(int nbNodes)
4648 {
4649 //  int val = myCellIdSmdsToVtk.size();
4650 //  MESSAGE(" ------------------- resize myCellIdSmdsToVtk " << val << " --> " << val + nbNodes);
4651 //  myCellIdSmdsToVtk.resize(val + nbNodes, -1); // fill new elements with -1
4652   int val = myNodes.size();
4653   MESSAGE(" ------------------- resize myNodes " << val << " --> " << val + nbNodes);
4654   myNodes.resize(val +nbNodes, 0);
4655 }
4656
4657 void SMDS_Mesh::incrementCellsCapacity(int nbCells)
4658 {
4659   int val = myCellIdVtkToSmds.size();
4660   MESSAGE(" ------------------- resize myCellIdVtkToSmds " << val << " --> " << val + nbCells);
4661   myCellIdVtkToSmds.resize(val + nbCells, -1); // fill new elements with -1
4662   val = myCells.size();
4663   MESSAGE(" ------------------- resize myCells " << val << " --> " << val + nbCells);
4664   myNodes.resize(val +nbCells, 0);
4665 }
4666
4667 void SMDS_Mesh::adjustStructure()
4668 {
4669   myGrid->GetPoints()->GetData()->SetNumberOfTuples(myNodeIDFactory->GetMaxID());
4670 }
4671
4672 void SMDS_Mesh::dumpGrid(string ficdump)
4673 {
4674         MESSAGE("SMDS_Mesh::dumpGrid " << ficdump);
4675 //  vtkUnstructuredGridWriter* aWriter = vtkUnstructuredGridWriter::New();
4676 //  aWriter->SetFileName(ficdump.c_str());
4677 //  aWriter->SetInput(myGrid);
4678 //  if(myGrid->GetNumberOfCells())
4679 //  {
4680 //    aWriter->Write();
4681 //  }
4682 //  aWriter->Delete();
4683   ficdump = ficdump + "_connectivity";
4684   ofstream ficcon(ficdump.c_str(), ios::out);
4685   int nbPoints = myGrid->GetNumberOfPoints();
4686   ficcon << "-------------------------------- points " <<  nbPoints << endl;
4687   for (int i=0; i<nbPoints; i++)
4688   {
4689         ficcon << i << " " << *(myGrid->GetPoint(i)) << " " << *(myGrid->GetPoint(i)+1) << " " << " " << *(myGrid->GetPoint(i)+2) << endl;
4690   }
4691   int nbCells = myGrid->GetNumberOfCells();
4692   ficcon << "-------------------------------- cells " <<  nbCells << endl;
4693   for (int i=0; i<nbCells; i++)
4694   {
4695 //      MESSAGE(i << " " << myGrid->GetCell(i));
4696 //      MESSAGE("  " << myGrid->GetCell(i)->GetCellType());
4697         ficcon << i << " - " << myGrid->GetCell(i)->GetCellType() << " -";
4698         int nbptcell = myGrid->GetCell(i)->GetNumberOfPoints();
4699         vtkIdList *listid = myGrid->GetCell(i)->GetPointIds();
4700         for (int j=0; j<nbptcell; j++)
4701         {
4702                 ficcon << " " <<  listid->GetId(j);
4703         }
4704         ficcon << endl;
4705   }
4706   ficcon << "-------------------------------- connectivity " <<  nbPoints << endl;
4707         vtkCellLinks *links = myGrid->GetCellLinks();
4708   for (int i=0; i<nbPoints; i++)
4709   {
4710         int ncells = links->GetNcells(i);
4711         vtkIdType *cells = links->GetCells(i);
4712         ficcon << i << " - " << ncells << " -";
4713         for (int j=0; j<ncells; j++)
4714         {
4715                 ficcon << " " << cells[j];
4716         }
4717         ficcon << endl;
4718   }
4719   ficcon.close();
4720
4721 }
4722
4723 void SMDS_Mesh::compactMesh()
4724 {
4725   MESSAGE("SMDS_Mesh::compactMesh do nothing!");
4726 }
4727
4728 int SMDS_Mesh::fromVtkToSmds(int vtkid)
4729 {
4730   if (vtkid >= 0 && vtkid < myCellIdVtkToSmds.size())
4731     return myCellIdVtkToSmds[vtkid];
4732   throw SALOME_Exception(LOCALIZED ("vtk id out of bounds"));
4733 }
4734
4735 void SMDS_Mesh::updateBoundingBox()
4736 {
4737   xmin = 0; xmax = 0;
4738   ymin = 0; ymax = 0;
4739   zmin = 0; zmax = 0;
4740   vtkPoints *points = myGrid->GetPoints();
4741   int myNodesSize = this->myNodes.size();
4742   for (int i = 0; i < myNodesSize; i++)
4743     {
4744       if (SMDS_MeshNode *n = myNodes[i])
4745         {
4746           double coords[3];
4747           points->GetPoint(n->myVtkID, coords);
4748           if (coords[0] < xmin) xmin = coords[0];
4749           else if (coords[0] > xmax) xmax = coords[0];
4750           if (coords[1] < ymin) ymin = coords[1];
4751           else if (coords[1] > ymax) ymax = coords[1];
4752           if (coords[2] < zmin) zmin = coords[2];
4753           else if (coords[2] > zmax) zmax = coords[2];
4754         }
4755     }
4756 }
4757
4758 double SMDS_Mesh::getMaxDim()
4759 {
4760   double dmax = 1.e-3;
4761   if ((xmax - xmin) > dmax) dmax = xmax -xmin;
4762   if ((ymax - ymin) > dmax) dmax = ymax -ymin;
4763   if ((zmax - zmin) > dmax) dmax = zmax -zmin;
4764   MESSAGE("getMaxDim " << dmax);
4765   return dmax;
4766 }
4767
4768 //! modification that needs compact structure and redraw
4769 void SMDS_Mesh::Modified()
4770 {
4771   if (this->myModified)
4772     {
4773       this->myModifTime++;
4774       MESSAGE("modified");
4775       myModified = false;
4776     }
4777 }
4778
4779 //! get last modification timeStamp
4780 unsigned long SMDS_Mesh::GetMTime() const
4781 {
4782   return this->myModifTime;
4783 }
4784
4785 bool SMDS_Mesh::isCompacted()
4786 {
4787   if (this->myModifTime > this->myCompactTime)
4788     {
4789       MESSAGE(" *** isCompacted " << myCompactTime << " < " << myModifTime);
4790       this->myCompactTime = this->myModifTime;
4791       return false;
4792     }
4793   return true;
4794 }