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