Salome HOME
Optimize performance of mesh deletion upon hyp modification
[modules/smesh.git] / src / SMDS / SMDS_Mesh.cxx
1 // Copyright (C) 2007-2016  CEA/DEN, EDF R&D, OPEN CASCADE
2 //
3 // Copyright (C) 2003-2007  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
4 // CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
5 //
6 // This library is free software; you can redistribute it and/or
7 // modify it under the terms of the GNU Lesser General Public
8 // License as published by the Free Software Foundation; either
9 // version 2.1 of the License, or (at your option) any later version.
10 //
11 // This library is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 // Lesser General Public License for more details.
15 //
16 // You should have received a copy of the GNU Lesser General Public
17 // License along with this library; if not, write to the Free Software
18 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
19 //
20 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
21 //
22
23 //  SMESH SMDS : implementation of Salome mesh data structure
24 //
25 #ifdef _MSC_VER
26 #pragma warning(disable:4786)
27 #endif
28
29 #include "SMDS_FaceOfEdges.hxx"
30 #include "SMDS_FaceOfNodes.hxx"
31 #include "SMDS_Mesh.hxx"
32 #include "SMDS_PolygonalFaceOfNodes.hxx"
33 #include "SMDS_PolyhedralVolumeOfNodes.hxx"
34 #include "SMDS_QuadraticEdge.hxx"
35 #include "SMDS_QuadraticFaceOfNodes.hxx"
36 #include "SMDS_QuadraticVolumeOfNodes.hxx"
37 #include "SMDS_SetIterator.hxx"
38 #include "SMDS_SpacePosition.hxx"
39 #include "SMDS_UnstructuredGrid.hxx"
40 #include "SMDS_VolumeOfFaces.hxx"
41 #include "SMDS_VolumeOfNodes.hxx"
42
43 #include "utilities.h"
44
45 #include <vtkUnstructuredGrid.h>
46 #include <vtkUnstructuredGridWriter.h>
47 #include <vtkUnsignedCharArray.h>
48 #include <vtkCell.h>
49 #include <vtkCellLinks.h>
50 #include <vtkIdList.h>
51
52 #include <algorithm>
53 #include <map>
54 #include <iostream>
55 #include <fstream>
56 #include <iterator>
57 using namespace std;
58
59 #ifndef WIN32
60 #include <sys/sysinfo.h>
61 #endif
62
63 // number of added entities to check memory after
64 #define CHECKMEMORY_INTERVAL 100000
65
66 vector<SMDS_Mesh*> SMDS_Mesh::_meshList = vector<SMDS_Mesh*>();
67 int SMDS_Mesh::chunkSize = 1024;
68
69
70 //================================================================================
71 /*!
72  * \brief Raise an exception if free memory (ram+swap) too low
73  * \param doNotRaise - if true, suppres exception, just return free memory size
74  * \retval int - amount of available memory in MB or negative number in failure case
75  */
76 //================================================================================
77
78 int SMDS_Mesh::CheckMemory(const bool doNotRaise) throw (std::bad_alloc)
79 {
80 #ifndef WIN32
81   struct sysinfo si;
82   int err = sysinfo( &si );
83   if ( err )
84     return -1;
85
86   const unsigned long Mbyte = 1024 * 1024;
87
88   static int limit = -1;
89   if ( limit < 0 ) {
90     int status = system("SMDS_MemoryLimit"); // it returns lower limit of free RAM
91     if (status >= 0 ) {
92       limit = WEXITSTATUS(status);
93     }
94     else {
95       double factor = ( si.totalswap == 0 ) ? 0.1 : 0.2;
96       limit = int(( factor * si.totalram * si.mem_unit ) / Mbyte );
97     }
98     if ( limit < 20 )
99       limit = 20;
100     else
101       limit = int ( limit * 1.5 );
102     MESSAGE ( "SMDS_Mesh::CheckMemory() memory limit = " << limit << " MB" );
103   }
104
105   // compute separately to avoid overflow
106   int freeMb =
107     ( si.freeram  * si.mem_unit ) / Mbyte +
108     ( si.freeswap * si.mem_unit ) / Mbyte;
109   //cout << "freeMb = " << freeMb << " limit = " << limit << endl;
110
111   if ( freeMb > limit )
112     return freeMb - limit;
113
114   if ( doNotRaise )
115     return 0;
116
117   MESSAGE ("SMDS_Mesh::CheckMemory() throws as free memory too low: " << freeMb <<" MB" );
118   throw std::bad_alloc();
119 #else
120   return -1;
121 #endif
122 }
123
124 ///////////////////////////////////////////////////////////////////////////////
125 /// Create a new mesh object
126 ///////////////////////////////////////////////////////////////////////////////
127 SMDS_Mesh::SMDS_Mesh():
128   myNodePool(0), myVolumePool(0), myFacePool(0), myEdgePool(0), myBallPool(0),
129   myParent(NULL),
130   myNodeIDFactory(new SMDS_MeshNodeIDFactory()),
131   myElementIDFactory(new SMDS_MeshElementIDFactory()),
132   myModified(false), myModifTime(0), myCompactTime(0),
133   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   // --- retreive 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 //function : DumpNodes
2463 //purpose  :
2464 //=======================================================================
2465
2466 void SMDS_Mesh::DumpNodes() const
2467 {
2468   SMDS_NodeIteratorPtr itnode=nodesIterator();
2469   while(itnode->more()) ; //MESSAGE(itnode->next());
2470 }
2471
2472 //=======================================================================
2473 //function : Dump0DElements
2474 //purpose  :
2475 //=======================================================================
2476 void SMDS_Mesh::Dump0DElements() const
2477 {
2478   SMDS_ElemIteratorPtr it0d = elementsIterator(SMDSAbs_0DElement);
2479   while(it0d->more()) ; //MESSAGE(it0d->next());
2480 }
2481
2482 //=======================================================================
2483 //function : DumpEdges
2484 //purpose  :
2485 //=======================================================================
2486
2487 void SMDS_Mesh::DumpEdges() const
2488 {
2489   SMDS_EdgeIteratorPtr itedge=edgesIterator();
2490   while(itedge->more()) ; //MESSAGE(itedge->next());
2491 }
2492
2493 //=======================================================================
2494 //function : DumpFaces
2495 //purpose  :
2496 //=======================================================================
2497
2498 void SMDS_Mesh::DumpFaces() const
2499 {
2500   SMDS_FaceIteratorPtr itface=facesIterator();
2501   while(itface->more()) ; //MESSAGE(itface->next());
2502 }
2503
2504 //=======================================================================
2505 //function : DumpVolumes
2506 //purpose  :
2507 //=======================================================================
2508
2509 void SMDS_Mesh::DumpVolumes() const
2510 {
2511   SMDS_VolumeIteratorPtr itvol=volumesIterator();
2512   while(itvol->more()) ; //MESSAGE(itvol->next());
2513 }
2514
2515 //=======================================================================
2516 //function : DebugStats
2517 //purpose  :
2518 //=======================================================================
2519
2520 void SMDS_Mesh::DebugStats() const
2521 {
2522   MESSAGE("Debug stats of mesh : ");
2523
2524   MESSAGE("===== NODES ====="<<NbNodes());
2525   MESSAGE("===== 0DELEMS ====="<<Nb0DElements());
2526   MESSAGE("===== EDGES ====="<<NbEdges());
2527   MESSAGE("===== FACES ====="<<NbFaces());
2528   MESSAGE("===== VOLUMES ====="<<NbVolumes());
2529
2530   MESSAGE("End Debug stats of mesh ");
2531
2532   //#ifdef DEB
2533
2534   SMDS_NodeIteratorPtr itnode=nodesIterator();
2535   int sizeofnodes = 0;
2536   int sizeoffaces = 0;
2537
2538   while(itnode->more())
2539   {
2540     const SMDS_MeshNode *node = itnode->next();
2541
2542     sizeofnodes += sizeof(*node);
2543
2544     SMDS_ElemIteratorPtr it = node->GetInverseElementIterator();
2545     while(it->more())
2546     {
2547       const SMDS_MeshElement *me = it->next();
2548       sizeofnodes += sizeof(me);
2549     }
2550   }
2551
2552   SMDS_FaceIteratorPtr itface=facesIterator();
2553   while(itface->more())
2554   {
2555     const SMDS_MeshElement *face = itface->next();
2556     sizeoffaces += sizeof(*face);
2557   }
2558
2559   MESSAGE("total size of node elements = " << sizeofnodes);;
2560   MESSAGE("total size of face elements = " << sizeoffaces);;
2561
2562   //#endif
2563 }
2564
2565 ///////////////////////////////////////////////////////////////////////////////
2566 /// Return the number of nodes
2567 ///////////////////////////////////////////////////////////////////////////////
2568 int SMDS_Mesh::NbNodes() const
2569 {
2570   return myInfo.NbNodes();
2571 }
2572
2573 ///////////////////////////////////////////////////////////////////////////////
2574 /// Return the number of 0D elements
2575 ///////////////////////////////////////////////////////////////////////////////
2576 int SMDS_Mesh::Nb0DElements() const
2577 {
2578   return myInfo.Nb0DElements();
2579 }
2580
2581 ///////////////////////////////////////////////////////////////////////////////
2582 /// Return the number of 0D elements
2583 ///////////////////////////////////////////////////////////////////////////////
2584 int SMDS_Mesh::NbBalls() const
2585 {
2586   return myInfo.NbBalls();
2587 }
2588
2589 ///////////////////////////////////////////////////////////////////////////////
2590 /// Return the number of edges (including construction edges)
2591 ///////////////////////////////////////////////////////////////////////////////
2592 int SMDS_Mesh::NbEdges() const
2593 {
2594   return myInfo.NbEdges();
2595 }
2596
2597 ///////////////////////////////////////////////////////////////////////////////
2598 /// Return the number of faces (including construction faces)
2599 ///////////////////////////////////////////////////////////////////////////////
2600 int SMDS_Mesh::NbFaces() const
2601 {
2602   return myInfo.NbFaces();
2603 }
2604
2605 ///////////////////////////////////////////////////////////////////////////////
2606 /// Return the number of volumes
2607 ///////////////////////////////////////////////////////////////////////////////
2608 int SMDS_Mesh::NbVolumes() const
2609 {
2610   return myInfo.NbVolumes();
2611 }
2612
2613 ///////////////////////////////////////////////////////////////////////////////
2614 /// Return the number of child mesh of this mesh.
2615 /// Note that the tree structure of SMDS_Mesh is unused in SMESH
2616 ///////////////////////////////////////////////////////////////////////////////
2617 int SMDS_Mesh::NbSubMesh() const
2618 {
2619   return myChildren.size();
2620 }
2621
2622 ///////////////////////////////////////////////////////////////////////////////
2623 /// Destroy the mesh and all its elements
2624 /// All pointer on elements owned by this mesh become illegals.
2625 ///////////////////////////////////////////////////////////////////////////////
2626 SMDS_Mesh::~SMDS_Mesh()
2627 {
2628   list<SMDS_Mesh*>::iterator itc=myChildren.begin();
2629   while(itc!=myChildren.end())
2630   {
2631     delete *itc;
2632     itc++;
2633   }
2634
2635   if(myParent==NULL)
2636   {
2637     delete myNodeIDFactory;
2638     delete myElementIDFactory;
2639   }
2640   else
2641   {
2642     SMDS_ElemIteratorPtr eIt = elementsIterator();
2643     while ( eIt->more() )
2644       {
2645         const SMDS_MeshElement *elem = eIt->next();
2646         myElementIDFactory->ReleaseID(elem->GetID(), elem->getVtkId());
2647       }
2648     SMDS_NodeIteratorPtr itn = nodesIterator();
2649     while (itn->more())
2650       {
2651         const SMDS_MeshNode *node = itn->next();
2652         ((SMDS_MeshNode*)node)->SetPosition(SMDS_SpacePosition::originSpacePosition());
2653         myNodeIDFactory->ReleaseID(node->GetID(), node->getVtkId());
2654       }
2655   }
2656   myGrid->Delete();
2657
2658   delete myNodePool;
2659   delete myVolumePool;
2660   delete myFacePool;
2661   delete myEdgePool;
2662   delete myBallPool;
2663 }
2664
2665 //================================================================================
2666 /*!
2667  * \brief Clear all data
2668  */
2669 //================================================================================
2670
2671 void SMDS_Mesh::Clear()
2672 {
2673   if (myParent!=NULL)
2674     {
2675     SMDS_ElemIteratorPtr eIt = elementsIterator();
2676     while ( eIt->more() )
2677       {
2678         const SMDS_MeshElement *elem = eIt->next();
2679         myElementIDFactory->ReleaseID(elem->GetID(), elem->getVtkId());
2680       }
2681     SMDS_NodeIteratorPtr itn = nodesIterator();
2682     while (itn->more())
2683       {
2684         const SMDS_MeshNode *node = itn->next();
2685         myNodeIDFactory->ReleaseID(node->GetID(), node->getVtkId());
2686       }
2687     }
2688   else
2689     {
2690     myNodeIDFactory->Clear();
2691     myElementIDFactory->Clear();
2692     }
2693
2694   // SMDS_ElemIteratorPtr itv = elementsIterator();
2695   // while (itv->more())
2696   //   {
2697   //     SMDS_MeshElement* elem = (SMDS_MeshElement*)(itv->next());
2698   //     SMDSAbs_ElementType aType = elem->GetType();
2699   //     switch (aType)
2700   //     {
2701   //       case SMDSAbs_0DElement:
2702   //         delete elem;
2703   //         break;
2704   //       case SMDSAbs_Edge:
2705   //          myEdgePool->destroy(static_cast<SMDS_VtkEdge*>(elem));
2706   //         break;
2707   //       case SMDSAbs_Face:
2708   //         myFacePool->destroy(static_cast<SMDS_VtkFace*>(elem));
2709   //         break;
2710   //       case SMDSAbs_Volume:
2711   //         myVolumePool->destroy(static_cast<SMDS_VtkVolume*>(elem));
2712   //         break;
2713   //       case SMDSAbs_Ball:
2714   //         myBallPool->destroy(static_cast<SMDS_BallElement*>(elem));
2715   //         break;
2716   //       default:
2717   //         break;
2718   //     }
2719   //   }
2720   myVolumePool->clear();
2721   myFacePool->clear();
2722   myEdgePool->clear();
2723   myBallPool->clear();
2724
2725   clearVector( myCells );
2726   clearVector( myCellIdVtkToSmds );
2727
2728   SMDS_NodeIteratorPtr itn = nodesIterator();
2729   while (itn->more())
2730     {
2731       SMDS_MeshNode *node = (SMDS_MeshNode*)(itn->next());
2732       node->SetPosition(SMDS_SpacePosition::originSpacePosition());
2733       //myNodePool->destroy(node);
2734     }
2735   myNodePool->clear();
2736   clearVector( myNodes );
2737
2738   list<SMDS_Mesh*>::iterator itc=myChildren.begin();
2739   while(itc!=myChildren.end())
2740     (*itc)->Clear();
2741
2742   myModified = false;
2743   myModifTime++;
2744   xmin = 0; xmax = 0;
2745   ymin = 0; ymax = 0;
2746   zmin = 0; zmax = 0;
2747
2748   myInfo.Clear();
2749
2750   myGrid->Initialize();
2751   myGrid->Allocate();
2752   vtkPoints* points = vtkPoints::New();
2753   // rnv: to fix bug "21125: EDF 1233 SMESH: Degrardation of precision in a test case for quadratic conversion"
2754   // using double type for storing coordinates of nodes instead float.
2755   points->SetDataType(VTK_DOUBLE);
2756   points->SetNumberOfPoints(0 /*SMDS_Mesh::chunkSize*/);
2757   myGrid->SetPoints( points );
2758   points->Delete();
2759   myGrid->DeleteLinks();
2760 }
2761
2762 ///////////////////////////////////////////////////////////////////////////////
2763 /// Return true if this mesh create faces with edges.
2764 /// A false returned value mean that faces are created with nodes. A concequence
2765 /// is, iteration on edges (SMDS_Element::edgesIterator) will be unavailable.
2766 ///////////////////////////////////////////////////////////////////////////////
2767 bool SMDS_Mesh::hasConstructionEdges()
2768 {
2769         return myHasConstructionEdges;
2770 }
2771
2772 ///////////////////////////////////////////////////////////////////////////////
2773 /// Return true if this mesh create volumes with faces
2774 /// A false returned value mean that volumes are created with nodes or edges.
2775 /// (see hasConstructionEdges)
2776 /// A concequence is, iteration on faces (SMDS_Element::facesIterator) will be
2777 /// unavailable.
2778 ///////////////////////////////////////////////////////////////////////////////
2779 bool SMDS_Mesh::hasConstructionFaces()
2780 {
2781         return myHasConstructionFaces;
2782 }
2783
2784 ///////////////////////////////////////////////////////////////////////////////
2785 /// Return true if nodes are linked to the finit elements, they are belonging to.
2786 /// Currently, It always return true.
2787 ///////////////////////////////////////////////////////////////////////////////
2788 bool SMDS_Mesh::hasInverseElements()
2789 {
2790         return myHasInverseElements;
2791 }
2792
2793 ///////////////////////////////////////////////////////////////////////////////
2794 /// Make this mesh creating construction edges (see hasConstructionEdges)
2795 /// @param b true to have construction edges, else false.
2796 ///////////////////////////////////////////////////////////////////////////////
2797 void SMDS_Mesh::setConstructionEdges(bool b)
2798 {
2799         myHasConstructionEdges=b;
2800 }
2801
2802 ///////////////////////////////////////////////////////////////////////////////
2803 /// Make this mesh creating construction faces (see hasConstructionFaces)
2804 /// @param b true to have construction faces, else false.
2805 ///////////////////////////////////////////////////////////////////////////////
2806 void SMDS_Mesh::setConstructionFaces(bool b)
2807 {
2808          myHasConstructionFaces=b;
2809 }
2810
2811 ///////////////////////////////////////////////////////////////////////////////
2812 /// Make this mesh creating link from nodes to elements (see hasInverseElements)
2813 /// @param b true to link nodes to elements, else false.
2814 ///////////////////////////////////////////////////////////////////////////////
2815 void SMDS_Mesh::setInverseElements(bool b)
2816 {
2817   if(!b) MESSAGE("Error : inverseElement=false not implemented");
2818   myHasInverseElements=b;
2819 }
2820
2821 namespace {
2822
2823   //================================================================================
2824   /*!
2825    * \brief Iterator on elements in id increasing order
2826    */
2827   //================================================================================
2828
2829   template <typename ELEM=const SMDS_MeshElement*>
2830   class IdSortedIterator : public SMDS_Iterator<ELEM>
2831   {
2832     SMDS_MeshElementIDFactory&       myIDFact;
2833     int                              myID, myMaxID, myNbFound, myTotalNb;
2834     SMDSAbs_ElementType              myType;
2835     ELEM                             myElem;
2836
2837   public:
2838     IdSortedIterator(const SMDS_MeshElementIDFactory& fact,
2839                      const SMDSAbs_ElementType        type, // SMDSAbs_All NOT allowed!!! 
2840                      const int                        totalNb)
2841       :myIDFact( fact ),
2842        myID(1), myMaxID( myIDFact.GetMaxID() ),myNbFound(0), myTotalNb( totalNb ),
2843        myType( type ),
2844        myElem(0)
2845     {
2846       next();
2847     }
2848     bool more()
2849     {
2850       return myElem;
2851     }
2852     ELEM next()
2853     {
2854       ELEM current = myElem;
2855
2856       for ( myElem = 0;  !myElem && myNbFound < myTotalNb && myID <= myMaxID; ++myID )
2857         if ((myElem = (ELEM) myIDFact.MeshElement( myID ))
2858             && myElem->GetType() != myType )
2859           myElem = 0;
2860
2861       myNbFound += bool(myElem);
2862
2863       return current;
2864     }
2865   };
2866
2867   //================================================================================
2868   /*!
2869    * \brief Iterator on vector of elements, possibly being resized while iteration
2870    */
2871   //================================================================================
2872
2873   template<typename RETURN_VALUE,
2874            typename VECTOR_VALUE=SMDS_MeshCell*,
2875            typename VALUE_FILTER=SMDS::NonNullFilter<VECTOR_VALUE> >
2876   class ElemVecIterator: public SMDS_Iterator<RETURN_VALUE>
2877   {
2878     const std::vector<VECTOR_VALUE>& _vector;
2879     size_t                           _index;
2880     bool                             _more;
2881     VALUE_FILTER                     _filter;
2882   public:
2883     ElemVecIterator(const std::vector<VECTOR_VALUE>& vec,
2884                     const VALUE_FILTER&              filter=VALUE_FILTER() )
2885       :_vector( vec ), _index(0), _more( !vec.empty() ), _filter( filter )
2886     {
2887       if ( _more && !_filter( _vector[ _index ]))
2888         next();
2889     }
2890     virtual bool more()
2891     {
2892       return _more;
2893     }
2894     virtual RETURN_VALUE next()
2895     {
2896       if ( !_more ) return NULL;
2897       VECTOR_VALUE current = _vector[ _index ];
2898       _more = 0;
2899       while ( !_more && ++_index < _vector.size() )
2900         _more = _filter( _vector[ _index ]);
2901       return (RETURN_VALUE) current;
2902     }
2903   };
2904 }
2905
2906 ///////////////////////////////////////////////////////////////////////////////
2907 /// Return an iterator on nodes of the current mesh factory
2908 ///////////////////////////////////////////////////////////////////////////////
2909
2910 SMDS_NodeIteratorPtr SMDS_Mesh::nodesIterator(bool idInceasingOrder) const
2911 {
2912   // naturally always sorted by ID
2913   typedef ElemVecIterator<const SMDS_MeshNode*, SMDS_MeshNode*> TIterator;
2914   return SMDS_NodeIteratorPtr( new TIterator(myNodes));
2915 }
2916
2917 SMDS_ElemIteratorPtr SMDS_Mesh::elementGeomIterator(SMDSAbs_GeometryType type) const
2918 {
2919   // naturally always sorted by ID
2920   typedef ElemVecIterator
2921     < const SMDS_MeshElement*, SMDS_MeshCell*, SMDS_MeshElement::GeomFilter > TIterator;
2922   return SMDS_ElemIteratorPtr
2923     (new TIterator(myCells, SMDS_MeshElement::GeomFilter( type )));
2924 }
2925
2926 SMDS_ElemIteratorPtr SMDS_Mesh::elementEntityIterator(SMDSAbs_EntityType type) const
2927 {
2928   if ( type == SMDSEntity_Node )
2929   {
2930     typedef ElemVecIterator<const SMDS_MeshElement*, SMDS_MeshNode*> TIterator;
2931     return SMDS_ElemIteratorPtr( new TIterator(myNodes));
2932   }
2933   // naturally always sorted by ID
2934   typedef ElemVecIterator
2935     < const SMDS_MeshElement*, SMDS_MeshCell*, SMDS_MeshElement::EntityFilter > TIterator;
2936   return SMDS_ElemIteratorPtr
2937     (new TIterator(myCells, SMDS_MeshElement::EntityFilter( type )));
2938 }
2939
2940 ///////////////////////////////////////////////////////////////////////////////
2941 /// Return an iterator on elements of the current mesh factory
2942 ///////////////////////////////////////////////////////////////////////////////
2943 SMDS_ElemIteratorPtr SMDS_Mesh::elementsIterator(SMDSAbs_ElementType type) const
2944 {
2945   // naturally always sorted by ID
2946   switch ( type ) {
2947
2948   case SMDSAbs_All:
2949     return SMDS_ElemIteratorPtr (new ElemVecIterator<const SMDS_MeshElement*>(myCells));
2950
2951   case SMDSAbs_Node:
2952     return SMDS_ElemIteratorPtr
2953       ( new ElemVecIterator<const SMDS_MeshElement*, SMDS_MeshNode*>( myNodes ));
2954
2955   default:
2956     typedef ElemVecIterator
2957       < const SMDS_MeshElement*, SMDS_MeshCell*, SMDS_MeshElement::TypeFilter > TIterator;
2958     return SMDS_ElemIteratorPtr (new TIterator(myCells, SMDS_MeshElement::TypeFilter( type )));
2959   }
2960   return SMDS_ElemIteratorPtr();
2961 }
2962
2963 ///////////////////////////////////////////////////////////////////////////////
2964 ///Return an iterator on edges of the current mesh.
2965 ///////////////////////////////////////////////////////////////////////////////
2966
2967 SMDS_EdgeIteratorPtr SMDS_Mesh::edgesIterator(bool idInceasingOrder) const
2968 {
2969   // naturally always sorted by ID
2970   typedef ElemVecIterator
2971     < const SMDS_MeshEdge*, SMDS_MeshCell*, SMDS_MeshElement::TypeFilter > TIterator;
2972   return SMDS_EdgeIteratorPtr
2973     (new TIterator(myCells, SMDS_MeshElement::TypeFilter( SMDSAbs_Edge )));
2974 }
2975
2976 ///////////////////////////////////////////////////////////////////////////////
2977 ///Return an iterator on faces of the current mesh.
2978 ///////////////////////////////////////////////////////////////////////////////
2979
2980 SMDS_FaceIteratorPtr SMDS_Mesh::facesIterator(bool idInceasingOrder) const
2981 {
2982   // naturally always sorted by ID
2983   typedef ElemVecIterator
2984     < const SMDS_MeshFace*, SMDS_MeshCell*, SMDS_MeshElement::TypeFilter > TIterator;
2985   return SMDS_FaceIteratorPtr
2986     (new TIterator(myCells, SMDS_MeshElement::TypeFilter( SMDSAbs_Face )));
2987 }
2988
2989 ///////////////////////////////////////////////////////////////////////////////
2990 ///Return an iterator on volumes of the current mesh.
2991 ///////////////////////////////////////////////////////////////////////////////
2992
2993 SMDS_VolumeIteratorPtr SMDS_Mesh::volumesIterator(bool idInceasingOrder) const
2994 {
2995   // naturally always sorted by ID
2996   typedef ElemVecIterator
2997     < const SMDS_MeshVolume*, SMDS_MeshCell*, SMDS_MeshElement::TypeFilter > TIterator;
2998   return SMDS_VolumeIteratorPtr
2999     (new TIterator(myCells, SMDS_MeshElement::TypeFilter( SMDSAbs_Volume )));
3000 }
3001
3002 ///////////////////////////////////////////////////////////////////////////////
3003 /// Do intersection of sets (more than 2)
3004 ///////////////////////////////////////////////////////////////////////////////
3005 static set<const SMDS_MeshElement*> * intersectionOfSets(
3006         set<const SMDS_MeshElement*> vs[], int numberOfSets)
3007 {
3008         set<const SMDS_MeshElement*>* rsetA=new set<const SMDS_MeshElement*>(vs[0]);
3009         set<const SMDS_MeshElement*>* rsetB;
3010
3011         for(int i=0; i<numberOfSets-1; i++)
3012         {
3013                 rsetB=new set<const SMDS_MeshElement*>();
3014                 set_intersection(
3015                         rsetA->begin(), rsetA->end(),
3016                         vs[i+1].begin(), vs[i+1].end(),
3017                         inserter(*rsetB, rsetB->begin()));
3018                 delete rsetA;
3019                 rsetA=rsetB;
3020         }
3021         return rsetA;
3022 }
3023
3024 ///////////////////////////////////////////////////////////////////////////////
3025 /// Return the list of finite elements owning the given element: elements
3026 /// containing all the nodes of the given element, for instance faces and
3027 /// volumes containing a given edge.
3028 ///////////////////////////////////////////////////////////////////////////////
3029 static set<const SMDS_MeshElement*> * getFinitElements(const SMDS_MeshElement * element)
3030 {
3031   int numberOfSets=element->NbNodes();
3032   set<const SMDS_MeshElement*> *initSet = new set<const SMDS_MeshElement*>[numberOfSets];
3033
3034   SMDS_ElemIteratorPtr itNodes=element->nodesIterator();
3035
3036   int i = 0;
3037   while ( itNodes->more() )
3038   {
3039     const SMDS_MeshElement* node = itNodes->next();
3040     MYASSERT(node);
3041     const SMDS_MeshNode * n=static_cast<const SMDS_MeshNode*>(node);
3042     SMDS_ElemIteratorPtr itFe = n->GetInverseElementIterator();
3043
3044     while ( itFe->more() )
3045     {
3046       const SMDS_MeshElement* elem = itFe->next();
3047       MYASSERT(elem);
3048       initSet[i].insert(elem);
3049     }
3050
3051     i++;
3052   }
3053   set<const SMDS_MeshElement*> *retSet = intersectionOfSets( initSet, numberOfSets );
3054   delete [] initSet;
3055   return retSet;
3056 }
3057
3058 ///////////////////////////////////////////////////////////////////////////////
3059 /// Return the list of nodes used only by the given elements
3060 ///////////////////////////////////////////////////////////////////////////////
3061 static set<const SMDS_MeshElement*> * getExclusiveNodes(set<const SMDS_MeshElement*>& elements)
3062 {
3063   set<const SMDS_MeshElement*> * toReturn=new set<const SMDS_MeshElement*>();
3064   set<const SMDS_MeshElement*>::iterator itElements=elements.begin();
3065
3066   while(itElements!=elements.end())
3067   {
3068     SMDS_ElemIteratorPtr itNodes = (*itElements)->nodesIterator();
3069     itElements++;
3070
3071     while(itNodes->more())
3072     {
3073       const SMDS_MeshNode * n=static_cast<const SMDS_MeshNode*>(itNodes->next());
3074       SMDS_ElemIteratorPtr itFe = n->GetInverseElementIterator();
3075       set<const SMDS_MeshElement*> s;
3076       while(itFe->more())
3077         s.insert(itFe->next());
3078       if(s==elements) toReturn->insert(n);
3079     }
3080   }
3081   return toReturn;
3082 }
3083
3084 ///////////////////////////////////////////////////////////////////////////////
3085 ///Find the children of an element that are made of given nodes
3086 ///@param setOfChildren The set in which matching children will be inserted
3087 ///@param element The element were to search matching children
3088 ///@param nodes The nodes that the children must have to be selected
3089 ///////////////////////////////////////////////////////////////////////////////
3090 void SMDS_Mesh::addChildrenWithNodes(set<const SMDS_MeshElement*>& setOfChildren,
3091                                      const SMDS_MeshElement *      element,
3092                                      set<const SMDS_MeshElement*>& nodes)
3093 {
3094   switch(element->GetType())
3095   {
3096   case SMDSAbs_Node:
3097     MESSAGE("Internal Error: This should not happen");
3098     break;
3099   case SMDSAbs_0DElement:
3100   case SMDSAbs_Ball:
3101   {
3102   }
3103   break;
3104   case SMDSAbs_Edge:
3105   {
3106     SMDS_ElemIteratorPtr itn=element->nodesIterator();
3107     while(itn->more())
3108     {
3109       const SMDS_MeshElement * e=itn->next();
3110       if(nodes.find(e)!=nodes.end())
3111       {
3112         setOfChildren.insert(element);
3113         break;
3114       }
3115     }
3116   } break;
3117   case SMDSAbs_Face:
3118   {
3119     SMDS_ElemIteratorPtr itn=element->nodesIterator();
3120     while(itn->more())
3121     {
3122       const SMDS_MeshElement * e=itn->next();
3123       if(nodes.find(e)!=nodes.end())
3124       {
3125         setOfChildren.insert(element);
3126         break;
3127       }
3128     }
3129     if(hasConstructionEdges())
3130     {
3131       SMDS_ElemIteratorPtr ite=element->edgesIterator();
3132       while(ite->more())
3133         addChildrenWithNodes(setOfChildren, ite->next(), nodes);
3134     }
3135   } break;
3136   case SMDSAbs_Volume:
3137   {
3138     if(hasConstructionFaces())
3139     {
3140       SMDS_ElemIteratorPtr ite=element->facesIterator();
3141       while(ite->more())
3142         addChildrenWithNodes(setOfChildren, ite->next(), nodes);
3143     }
3144     else if(hasConstructionEdges())
3145     {
3146       SMDS_ElemIteratorPtr ite=element->edgesIterator();
3147       while(ite->more())
3148         addChildrenWithNodes(setOfChildren, ite->next(), nodes);
3149     }
3150   }
3151   case SMDSAbs_NbElementTypes:
3152   case SMDSAbs_All: break;
3153   }
3154 }
3155
3156 ///////////////////////////////////////////////////////////////////////////////
3157 ///@param elem The element to delete
3158 ///@param removenodes if true remaining nodes will be removed
3159 ///////////////////////////////////////////////////////////////////////////////
3160 void SMDS_Mesh::RemoveElement(const SMDS_MeshElement * elem,
3161                               const bool removenodes)
3162 {
3163   list<const SMDS_MeshElement *> removedElems;
3164   list<const SMDS_MeshElement *> removedNodes;
3165   RemoveElement( elem, removedElems, removedNodes, removenodes );
3166 }
3167
3168 ///////////////////////////////////////////////////////////////////////////////
3169 ///@param elem The element to delete
3170 ///@param removedElems to be filled with all removed elements
3171 ///@param removedNodes to be filled with all removed nodes
3172 ///@param removenodes if true remaining nodes will be removed
3173 ///////////////////////////////////////////////////////////////////////////////
3174 void SMDS_Mesh::RemoveElement(const SMDS_MeshElement *        elem,
3175                               list<const SMDS_MeshElement *>& removedElems,
3176                               list<const SMDS_MeshElement *>& removedNodes,
3177                               bool                            removenodes)
3178 {
3179   // get finite elements built on elem
3180   set<const SMDS_MeshElement*> * s1;
3181   if (    (elem->GetType() == SMDSAbs_0DElement)
3182       || ((elem->GetType() == SMDSAbs_Edge) && !hasConstructionEdges())
3183       || ((elem->GetType() == SMDSAbs_Face) && !hasConstructionFaces())
3184       ||  (elem->GetType() == SMDSAbs_Volume) )
3185     {
3186       s1 = new set<const SMDS_MeshElement*> ();
3187       s1->insert(elem);
3188     }
3189   else
3190     s1 = getFinitElements(elem);
3191
3192   // get exclusive nodes (which would become free afterwards)
3193   set<const SMDS_MeshElement*> * s2;
3194   if (elem->GetType() == SMDSAbs_Node) // a node is removed
3195     {
3196       // do not remove nodes except elem
3197       s2 = new set<const SMDS_MeshElement*> ();
3198       s2->insert(elem);
3199       removenodes = true;
3200     }
3201   else
3202     s2 = getExclusiveNodes(*s1);
3203
3204   // form the set of finite and construction elements to remove
3205   set<const SMDS_MeshElement*> s3;
3206   set<const SMDS_MeshElement*>::iterator it = s1->begin();
3207   while (it != s1->end())
3208     {
3209       addChildrenWithNodes(s3, *it, *s2);
3210       s3.insert(*it);
3211       it++;
3212     }
3213   if (elem->GetType() != SMDSAbs_Node)
3214     s3.insert(elem);
3215
3216   // remove finite and construction elements
3217   it = s3.begin();
3218   while (it != s3.end())
3219     {
3220       // Remove element from <InverseElements> of its nodes
3221       SMDS_ElemIteratorPtr itn = (*it)->nodesIterator();
3222       while (itn->more())
3223       {
3224         SMDS_MeshNode * n = static_cast<SMDS_MeshNode *> (const_cast<SMDS_MeshElement *> (itn->next()));
3225         n->RemoveInverseElement((*it));
3226       }
3227       int IdToRemove = (*it)->GetID();
3228       int vtkid = (*it)->getVtkId();
3229       switch ((*it)->GetType())
3230       {
3231         case SMDSAbs_Node:
3232           MYASSERT("Internal Error: This should not happen");
3233           break;
3234         case SMDSAbs_0DElement:
3235           if (IdToRemove >= 0)
3236             {
3237               myCells[IdToRemove] = 0; // -PR- ici ou dans myElementIDFactory->ReleaseID ?
3238               myInfo.remove(*it);
3239             }
3240           removedElems.push_back((*it));
3241           myElementIDFactory->ReleaseID(IdToRemove, vtkid);
3242           delete (*it);
3243           break;
3244         case SMDSAbs_Edge:
3245           if (IdToRemove >= 0)
3246             {
3247               myCells[IdToRemove] = 0;
3248               myInfo.RemoveEdge(*it);
3249             }
3250           removedElems.push_back((*it));
3251           myElementIDFactory->ReleaseID(IdToRemove, vtkid);
3252           if (const SMDS_VtkEdge* vtkElem = dynamic_cast<const SMDS_VtkEdge*>(*it))
3253             myEdgePool->destroy((SMDS_VtkEdge*) vtkElem);
3254           else {
3255             ((SMDS_MeshElement*) *it)->init( -1, -1, -1 ); // avoid reuse
3256             delete (*it);
3257           }
3258           break;
3259         case SMDSAbs_Face:
3260           if (IdToRemove >= 0)
3261             {
3262               myCells[IdToRemove] = 0;
3263               myInfo.RemoveFace(*it);
3264             }
3265           removedElems.push_back((*it));
3266           myElementIDFactory->ReleaseID(IdToRemove, vtkid);
3267           if (const SMDS_VtkFace* vtkElem = dynamic_cast<const SMDS_VtkFace*>(*it))
3268             myFacePool->destroy((SMDS_VtkFace*) vtkElem);
3269           else {
3270             ((SMDS_MeshElement*) *it)->init( -1, -1, -1 ); // avoid reuse
3271             delete (*it);
3272           }
3273           break;
3274         case SMDSAbs_Volume:
3275           if (IdToRemove >= 0)
3276             {
3277               myCells[IdToRemove] = 0;
3278               myInfo.RemoveVolume(*it);
3279             }
3280           removedElems.push_back((*it));
3281           myElementIDFactory->ReleaseID(IdToRemove, vtkid);
3282           if (const SMDS_VtkVolume* vtkElem = dynamic_cast<const SMDS_VtkVolume*>(*it))
3283             myVolumePool->destroy((SMDS_VtkVolume*) vtkElem);
3284           else {
3285             ((SMDS_MeshElement*) *it)->init( -1, -1, -1 ); // avoid reuse
3286             delete (*it);
3287           }
3288           break;
3289         case SMDSAbs_Ball:
3290           if (IdToRemove >= 0)
3291             {
3292               myCells[IdToRemove] = 0;
3293               myInfo.remove(*it);
3294             }
3295           removedElems.push_back((*it));
3296           myElementIDFactory->ReleaseID(IdToRemove, vtkid);
3297           if (const SMDS_BallElement* vtkElem = dynamic_cast<const SMDS_BallElement*>(*it))
3298             myBallPool->destroy(const_cast<SMDS_BallElement*>( vtkElem ));
3299           else {
3300             ((SMDS_MeshElement*) *it)->init( -1, -1, -1 ); // avoid reuse
3301             delete (*it);
3302           }
3303           break;
3304
3305         case SMDSAbs_All: // avoid compilation warning
3306         case SMDSAbs_NbElementTypes: break;
3307       }
3308       if (vtkid >= 0)
3309       {
3310         this->myGrid->GetCellTypesArray()->SetValue(vtkid, VTK_EMPTY_CELL);
3311       }
3312       it++;
3313     }
3314
3315   // remove exclusive (free) nodes
3316   if (removenodes)
3317   {
3318     it = s2->begin();
3319     while (it != s2->end())
3320     {
3321       int IdToRemove = (*it)->GetID();
3322       if (IdToRemove >= 0)
3323       {
3324         myNodes[IdToRemove] = 0;
3325         myInfo.myNbNodes--;
3326       }
3327       myNodeIDFactory->ReleaseID((*it)->GetID(), (*it)->getVtkId());
3328       removedNodes.push_back((*it));
3329       if (const SMDS_MeshNode* vtkElem = dynamic_cast<const SMDS_MeshNode*>(*it))
3330       {
3331         ((SMDS_MeshNode*)vtkElem)->SetPosition(SMDS_SpacePosition::originSpacePosition());
3332         myNodePool->destroy((SMDS_MeshNode*) vtkElem);
3333       }
3334       else
3335         delete (*it);
3336       it++;
3337     }
3338   }
3339
3340   delete s2;
3341   delete s1;
3342 }
3343
3344
3345 ///////////////////////////////////////////////////////////////////////////////
3346 ///@param elem The element to delete
3347 ///////////////////////////////////////////////////////////////////////////////
3348 void SMDS_Mesh::RemoveFreeElement(const SMDS_MeshElement * elem)
3349 {
3350   int elemId = elem->GetID();
3351   int vtkId = elem->getVtkId();
3352   SMDSAbs_ElementType aType = elem->GetType();
3353   SMDS_MeshElement* todest = (SMDS_MeshElement*)(elem);
3354   if (aType == SMDSAbs_Node) {
3355     // only free node can be removed by this method
3356     const SMDS_MeshNode* n = static_cast<SMDS_MeshNode*>(todest);
3357     SMDS_ElemIteratorPtr itFe = n->GetInverseElementIterator();
3358     if (!itFe->more()) { // free node
3359       myNodes[elemId] = 0;
3360       myInfo.myNbNodes--;
3361       ((SMDS_MeshNode*) n)->SetPosition(SMDS_SpacePosition::originSpacePosition());
3362       ((SMDS_MeshNode*) n)->SMDS_MeshElement::init( -1, -1, -1 ); // avoid reuse
3363       myNodePool->destroy(static_cast<SMDS_MeshNode*>(todest));
3364       myNodeIDFactory->ReleaseID(elemId, vtkId);
3365     }
3366   } else {
3367     if (hasConstructionEdges() || hasConstructionFaces())
3368       // this methods is only for meshes without descendants
3369       return;
3370
3371     // Remove element from <InverseElements> of its nodes
3372     SMDS_ElemIteratorPtr itn = elem->nodesIterator();
3373     while (itn->more()) {
3374       SMDS_MeshNode * n = static_cast<SMDS_MeshNode *>
3375         (const_cast<SMDS_MeshElement *>(itn->next()));
3376       n->RemoveInverseElement(elem);
3377     }
3378
3379     // in meshes without descendants elements are always free
3380     switch (aType) {
3381     case SMDSAbs_0DElement:
3382       myCells[elemId] = 0;
3383       myInfo.remove(elem);
3384       delete elem;
3385       elem = 0;
3386       break;
3387     case SMDSAbs_Edge:
3388       myCells[elemId] = 0;
3389       myInfo.RemoveEdge(elem);
3390       myEdgePool->destroy(static_cast<SMDS_VtkEdge*>(todest));
3391       break;
3392     case SMDSAbs_Face:
3393       myCells[elemId] = 0;
3394       myInfo.RemoveFace(elem);
3395       myFacePool->destroy(static_cast<SMDS_VtkFace*>(todest));
3396       break;
3397     case SMDSAbs_Volume:
3398       myCells[elemId] = 0;
3399       myInfo.RemoveVolume(elem);
3400       myVolumePool->destroy(static_cast<SMDS_VtkVolume*>(todest));
3401       break;
3402     case SMDSAbs_Ball:
3403       myCells[elemId] = 0;
3404       myInfo.remove(elem);
3405       myBallPool->destroy(static_cast<SMDS_BallElement*>(todest));
3406       break;
3407     default:
3408       break;
3409     }
3410     myElementIDFactory->ReleaseID(elemId, vtkId);
3411
3412     this->myGrid->GetCellTypesArray()->SetValue(vtkId, VTK_EMPTY_CELL);
3413     // --- to do: keep vtkid in a list of reusable cells
3414
3415     if ( elem )
3416       ((SMDS_MeshElement*) elem)->init( -1, -1, -1 ); // avoid reuse
3417   }
3418 }
3419
3420 /*!
3421  * Checks if the element is present in mesh.
3422  * Useful to determine dead pointers.
3423  */
3424 bool SMDS_Mesh::Contains (const SMDS_MeshElement* elem) const
3425 {
3426   // we should not rely on validity of *elem, so iterate on containers
3427   // of all types in the hope of finding <elem> somewhere there
3428   SMDS_NodeIteratorPtr itn = nodesIterator();
3429   while (itn->more())
3430     if (elem == itn->next())
3431       return true;
3432   SMDS_ElemIteratorPtr ite = elementsIterator();
3433   while (ite->more())
3434     if (elem == ite->next())
3435       return true;
3436   return false;
3437 }
3438
3439 //=======================================================================
3440 //function : MaxNodeID
3441 //purpose  :
3442 //=======================================================================
3443
3444 int SMDS_Mesh::MaxNodeID() const
3445 {
3446   return myNodeIDFactory->GetMaxID();
3447 }
3448
3449 //=======================================================================
3450 //function : MinNodeID
3451 //purpose  :
3452 //=======================================================================
3453
3454 int SMDS_Mesh::MinNodeID() const
3455 {
3456   return myNodeIDFactory->GetMinID();
3457 }
3458
3459 //=======================================================================
3460 //function : MaxElementID
3461 //purpose  :
3462 //=======================================================================
3463
3464 int SMDS_Mesh::MaxElementID() const
3465 {
3466   return myElementIDFactory->GetMaxID();
3467 }
3468
3469 //=======================================================================
3470 //function : MinElementID
3471 //purpose  :
3472 //=======================================================================
3473
3474 int SMDS_Mesh::MinElementID() const
3475 {
3476   return myElementIDFactory->GetMinID();
3477 }
3478
3479 //=======================================================================
3480 //function : Renumber
3481 //purpose  : Renumber all nodes or elements.
3482 //=======================================================================
3483
3484 void SMDS_Mesh::Renumber (const bool isNodes, const int  startID, const int  deltaID)
3485 {
3486   if ( deltaID == 0 )
3487     return;
3488
3489   SMDS_MeshNodeIDFactory * idFactory =
3490     isNodes ? myNodeIDFactory : myElementIDFactory;
3491
3492   // get existing elements in the order of ID increasing
3493   map<int,SMDS_MeshElement*> elemMap;
3494   SMDS_ElemIteratorPtr idElemIt = idFactory->elementsIterator();
3495   while ( idElemIt->more() ) {
3496     SMDS_MeshElement* elem = const_cast<SMDS_MeshElement*>(idElemIt->next());
3497     int id = elem->GetID();
3498     elemMap.insert(map<int,SMDS_MeshElement*>::value_type(id, elem));
3499   }
3500   // release their ids
3501   map<int,SMDS_MeshElement*>::iterator elemIt = elemMap.begin();
3502   idFactory->Clear();
3503 //   for ( ; elemIt != elemMap.end(); elemIt++ )
3504 //   {
3505 //     int id = (*elemIt).first;
3506 //     idFactory->ReleaseID( id );
3507 //   }
3508   // set new IDs
3509   int ID = startID;
3510   elemIt = elemMap.begin();
3511   for ( ; elemIt != elemMap.end(); elemIt++ )
3512   {
3513     idFactory->BindID( ID, (*elemIt).second );
3514     ID += deltaID;
3515   }
3516 }
3517
3518 //=======================================================================
3519 //function : GetElementType
3520 //purpose  : Return type of element or node with id
3521 //=======================================================================
3522
3523 SMDSAbs_ElementType SMDS_Mesh::GetElementType( const int id, const bool iselem ) const
3524 {
3525   SMDS_MeshElement* elem = 0;
3526   if( iselem )
3527     elem = myElementIDFactory->MeshElement( id );
3528   else
3529     elem = myNodeIDFactory->MeshElement( id );
3530
3531   if( !elem )
3532   {
3533     //throw SALOME_Exception(LOCALIZED ("this element isn't exist"));
3534     return SMDSAbs_All;
3535   }
3536   else
3537     return elem->GetType();
3538 }
3539
3540
3541
3542 //********************************************************************
3543 //********************************************************************
3544 //********                                                   *********
3545 //*****       Methods for addition of quadratic elements        ******
3546 //********                                                   *********
3547 //********************************************************************
3548 //********************************************************************
3549
3550 //=======================================================================
3551 //function : AddEdgeWithID
3552 //purpose  :
3553 //=======================================================================
3554 SMDS_MeshEdge* SMDS_Mesh::AddEdgeWithID(int n1, int n2, int n12, int ID)
3555 {
3556   return SMDS_Mesh::AddEdgeWithID
3557     ((SMDS_MeshNode*) myNodeIDFactory->MeshElement(n1),
3558      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n2),
3559      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n12),
3560      ID);
3561 }
3562
3563 //=======================================================================
3564 //function : AddEdge
3565 //purpose  :
3566 //=======================================================================
3567 SMDS_MeshEdge* SMDS_Mesh::AddEdge(const SMDS_MeshNode* n1,
3568                                   const SMDS_MeshNode* n2,
3569                                   const SMDS_MeshNode* n12)
3570 {
3571   return SMDS_Mesh::AddEdgeWithID(n1, n2, n12, myElementIDFactory->GetFreeID());
3572 }
3573
3574 //=======================================================================
3575 //function : AddEdgeWithID
3576 //purpose  :
3577 //=======================================================================
3578 SMDS_MeshEdge* SMDS_Mesh::AddEdgeWithID(const SMDS_MeshNode * n1,
3579                                         const SMDS_MeshNode * n2,
3580                                         const SMDS_MeshNode * n12,
3581                                         int ID)
3582 {
3583   if ( !n1 || !n2 || !n12 ) return 0;
3584
3585   // --- retrieve nodes ID
3586   myNodeIds.resize(3);
3587   myNodeIds[0] = n1->getVtkId();
3588   myNodeIds[1] = n2->getVtkId();
3589   myNodeIds[2] = n12->getVtkId();
3590
3591   SMDS_MeshEdge * edge = 0;
3592   SMDS_VtkEdge *edgevtk = myEdgePool->getNew();
3593   edgevtk->init(myNodeIds, this);
3594   if (!this->registerElement(ID,edgevtk))
3595   {
3596     this->myGrid->GetCellTypesArray()->SetValue(edgevtk->getVtkId(), VTK_EMPTY_CELL);
3597     myEdgePool->destroy(edgevtk);
3598     return 0;
3599   }
3600   edge = edgevtk;
3601   adjustmyCellsCapacity(ID);
3602   myCells[ID] = edge;
3603   myInfo.myNbQuadEdges++;
3604
3605   //  if (!registerElement(ID, edge)) {
3606   //        RemoveElement(edge, false);
3607   //        edge = NULL;
3608   //  }
3609   return edge;
3610
3611 }
3612
3613
3614 //=======================================================================
3615 //function : AddFace
3616 //purpose  :
3617 //=======================================================================
3618 SMDS_MeshFace* SMDS_Mesh::AddFace(const SMDS_MeshNode * n1,
3619                                   const SMDS_MeshNode * n2,
3620                                   const SMDS_MeshNode * n3,
3621                                   const SMDS_MeshNode * n12,
3622                                   const SMDS_MeshNode * n23,
3623                                   const SMDS_MeshNode * n31)
3624 {
3625   return SMDS_Mesh::AddFaceWithID(n1,n2,n3,n12,n23,n31,
3626                                   myElementIDFactory->GetFreeID());
3627 }
3628
3629 //=======================================================================
3630 //function : AddFaceWithID
3631 //purpose  :
3632 //=======================================================================
3633 SMDS_MeshFace* SMDS_Mesh::AddFaceWithID(int n1, int n2, int n3,
3634                                         int n12,int n23,int n31, int ID)
3635 {
3636   return SMDS_Mesh::AddFaceWithID
3637     ((SMDS_MeshNode *)myNodeIDFactory->MeshElement(n1) ,
3638      (SMDS_MeshNode *)myNodeIDFactory->MeshElement(n2) ,
3639      (SMDS_MeshNode *)myNodeIDFactory->MeshElement(n3) ,
3640      (SMDS_MeshNode *)myNodeIDFactory->MeshElement(n12),
3641      (SMDS_MeshNode *)myNodeIDFactory->MeshElement(n23),
3642      (SMDS_MeshNode *)myNodeIDFactory->MeshElement(n31),
3643      ID);
3644 }
3645
3646 //=======================================================================
3647 //function : AddFaceWithID
3648 //purpose  :
3649 //=======================================================================
3650 SMDS_MeshFace* SMDS_Mesh::AddFaceWithID(const SMDS_MeshNode * n1,
3651                                         const SMDS_MeshNode * n2,
3652                                         const SMDS_MeshNode * n3,
3653                                         const SMDS_MeshNode * n12,
3654                                         const SMDS_MeshNode * n23,
3655                                         const SMDS_MeshNode * n31,
3656                                         int ID)
3657 {
3658   if ( !n1 || !n2 || !n3 || !n12 || !n23 || !n31) return 0;
3659   if(hasConstructionEdges()) {
3660     // creation quadratic edges - not implemented
3661     return 0;
3662   }
3663   else
3664   {
3665     // --- retrieve nodes ID
3666     myNodeIds.resize(6);
3667     myNodeIds[0] = n1->getVtkId();
3668     myNodeIds[1] = n2->getVtkId();
3669     myNodeIds[2] = n3->getVtkId();
3670     myNodeIds[3] = n12->getVtkId();
3671     myNodeIds[4] = n23->getVtkId();
3672     myNodeIds[5] = n31->getVtkId();
3673
3674     SMDS_MeshFace * face = 0;
3675     SMDS_VtkFace *facevtk = myFacePool->getNew();
3676     facevtk->init(myNodeIds, this);
3677     if (!this->registerElement(ID,facevtk))
3678     {
3679       this->myGrid->GetCellTypesArray()->SetValue(facevtk->getVtkId(), VTK_EMPTY_CELL);
3680       myFacePool->destroy(facevtk);
3681       return 0;
3682     }
3683     face = facevtk;
3684     adjustmyCellsCapacity(ID);
3685     myCells[ID] = face;
3686     myInfo.myNbQuadTriangles++;
3687
3688     //    if (!registerElement(ID, face)) {
3689     //      RemoveElement(face, false);
3690     //      face = NULL;
3691     //    }
3692     return face;
3693   }
3694 }
3695
3696
3697 //=======================================================================
3698 //function : AddFace
3699 //purpose  :
3700 //=======================================================================
3701 SMDS_MeshFace* SMDS_Mesh::AddFace(const SMDS_MeshNode * n1,
3702                                   const SMDS_MeshNode * n2,
3703                                   const SMDS_MeshNode * n3,
3704                                   const SMDS_MeshNode * n12,
3705                                   const SMDS_MeshNode * n23,
3706                                   const SMDS_MeshNode * n31,
3707                                   const SMDS_MeshNode * nCenter)
3708 {
3709   return SMDS_Mesh::AddFaceWithID(n1,n2,n3,n12,n23,n31,nCenter,
3710                                   myElementIDFactory->GetFreeID());
3711 }
3712
3713 //=======================================================================
3714 //function : AddFaceWithID
3715 //purpose  :
3716 //=======================================================================
3717 SMDS_MeshFace* SMDS_Mesh::AddFaceWithID(int n1, int n2, int n3,
3718                                         int n12,int n23,int n31, int nCenter, int ID)
3719 {
3720   return SMDS_Mesh::AddFaceWithID
3721     ((SMDS_MeshNode *)myNodeIDFactory->MeshElement(n1) ,
3722      (SMDS_MeshNode *)myNodeIDFactory->MeshElement(n2) ,
3723      (SMDS_MeshNode *)myNodeIDFactory->MeshElement(n3) ,
3724      (SMDS_MeshNode *)myNodeIDFactory->MeshElement(n12),
3725      (SMDS_MeshNode *)myNodeIDFactory->MeshElement(n23),
3726      (SMDS_MeshNode *)myNodeIDFactory->MeshElement(n31),
3727      (SMDS_MeshNode *)myNodeIDFactory->MeshElement(nCenter),
3728      ID);
3729 }
3730
3731 //=======================================================================
3732 //function : AddFaceWithID
3733 //purpose  :
3734 //=======================================================================
3735 SMDS_MeshFace* SMDS_Mesh::AddFaceWithID(const SMDS_MeshNode * n1,
3736                                         const SMDS_MeshNode * n2,
3737                                         const SMDS_MeshNode * n3,
3738                                         const SMDS_MeshNode * n12,
3739                                         const SMDS_MeshNode * n23,
3740                                         const SMDS_MeshNode * n31,
3741                                         const SMDS_MeshNode * nCenter,
3742                                         int ID)
3743 {
3744   if ( !n1 || !n2 || !n3 || !n12 || !n23 || !n31 || !nCenter) return 0;
3745   if(hasConstructionEdges()) {
3746     // creation quadratic edges - not implemented
3747     return 0;
3748   }
3749   else
3750   {
3751     // --- retrieve nodes ID
3752     myNodeIds.resize(7);
3753     myNodeIds[0] = n1->getVtkId();
3754     myNodeIds[1] = n2->getVtkId();
3755     myNodeIds[2] = n3->getVtkId();
3756     myNodeIds[3] = n12->getVtkId();
3757     myNodeIds[4] = n23->getVtkId();
3758     myNodeIds[5] = n31->getVtkId();
3759     myNodeIds[6] = nCenter->getVtkId();
3760
3761     SMDS_MeshFace * face = 0;
3762     SMDS_VtkFace *facevtk = myFacePool->getNew();
3763     facevtk->init(myNodeIds, this);
3764     if (!this->registerElement(ID,facevtk))
3765     {
3766       this->myGrid->GetCellTypesArray()->SetValue(facevtk->getVtkId(), VTK_EMPTY_CELL);
3767       myFacePool->destroy(facevtk);
3768       return 0;
3769     }
3770     face = facevtk;
3771     adjustmyCellsCapacity(ID);
3772     myCells[ID] = face;
3773     myInfo.myNbBiQuadTriangles++;
3774
3775     //    if (!registerElement(ID, face)) {
3776     //      RemoveElement(face, false);
3777     //      face = NULL;
3778     //    }
3779     return face;
3780   }
3781 }
3782
3783
3784 //=======================================================================
3785 //function : AddFace
3786 //purpose  :
3787 //=======================================================================
3788 SMDS_MeshFace* SMDS_Mesh::AddFace(const SMDS_MeshNode * n1,
3789                                   const SMDS_MeshNode * n2,
3790                                   const SMDS_MeshNode * n3,
3791                                   const SMDS_MeshNode * n4,
3792                                   const SMDS_MeshNode * n12,
3793                                   const SMDS_MeshNode * n23,
3794                                   const SMDS_MeshNode * n34,
3795                                   const SMDS_MeshNode * n41)
3796 {
3797   return SMDS_Mesh::AddFaceWithID(n1,n2,n3,n4,n12,n23,n34,n41,
3798                                   myElementIDFactory->GetFreeID());
3799 }
3800
3801 //=======================================================================
3802 //function : AddFaceWithID
3803 //purpose  :
3804 //=======================================================================
3805 SMDS_MeshFace* SMDS_Mesh::AddFaceWithID(int n1, int n2, int n3, int n4,
3806                                         int n12,int n23,int n34,int n41, int ID)
3807 {
3808   return SMDS_Mesh::AddFaceWithID
3809     ((SMDS_MeshNode *)myNodeIDFactory->MeshElement(n1) ,
3810      (SMDS_MeshNode *)myNodeIDFactory->MeshElement(n2) ,
3811      (SMDS_MeshNode *)myNodeIDFactory->MeshElement(n3) ,
3812      (SMDS_MeshNode *)myNodeIDFactory->MeshElement(n4) ,
3813      (SMDS_MeshNode *)myNodeIDFactory->MeshElement(n12),
3814      (SMDS_MeshNode *)myNodeIDFactory->MeshElement(n23),
3815      (SMDS_MeshNode *)myNodeIDFactory->MeshElement(n34),
3816      (SMDS_MeshNode *)myNodeIDFactory->MeshElement(n41),
3817      ID);
3818 }
3819
3820 //=======================================================================
3821 //function : AddFaceWithID
3822 //purpose  :
3823 //=======================================================================
3824 SMDS_MeshFace* SMDS_Mesh::AddFaceWithID(const SMDS_MeshNode * n1,
3825                                         const SMDS_MeshNode * n2,
3826                                         const SMDS_MeshNode * n3,
3827                                         const SMDS_MeshNode * n4,
3828                                         const SMDS_MeshNode * n12,
3829                                         const SMDS_MeshNode * n23,
3830                                         const SMDS_MeshNode * n34,
3831                                         const SMDS_MeshNode * n41,
3832                                         int ID)
3833 {
3834   if ( !n1 || !n2 || !n3 || !n4 || !n12 || !n23 || !n34 || !n41) return 0;
3835   if(hasConstructionEdges()) {
3836     // creation quadratic edges - not implemented
3837     return 0;
3838   }
3839   else
3840   {
3841     // --- retrieve nodes ID
3842     myNodeIds.resize(8);
3843     myNodeIds[0] = n1->getVtkId();
3844     myNodeIds[1] = n2->getVtkId();
3845     myNodeIds[2] = n3->getVtkId();
3846     myNodeIds[3] = n4->getVtkId();
3847     myNodeIds[4] = n12->getVtkId();
3848     myNodeIds[5] = n23->getVtkId();
3849     myNodeIds[6] = n34->getVtkId();
3850     myNodeIds[7] = n41->getVtkId();
3851
3852     SMDS_MeshFace * face = 0;
3853     SMDS_VtkFace *facevtk = myFacePool->getNew();
3854     facevtk->init(myNodeIds, this);
3855     if (!this->registerElement(ID,facevtk))
3856     {
3857       this->myGrid->GetCellTypesArray()->SetValue(facevtk->getVtkId(), VTK_EMPTY_CELL);
3858       myFacePool->destroy(facevtk);
3859       return 0;
3860     }
3861     face = facevtk;
3862     adjustmyCellsCapacity(ID);
3863     myCells[ID] = face;
3864     myInfo.myNbQuadQuadrangles++;
3865
3866     //    if (!registerElement(ID, face)) {
3867     //      RemoveElement(face, false);
3868     //      face = NULL;
3869     //    }
3870     return face;
3871   }
3872 }
3873
3874 //=======================================================================
3875 //function : AddFace
3876 //purpose  :
3877 //=======================================================================
3878 SMDS_MeshFace* SMDS_Mesh::AddFace(const SMDS_MeshNode * n1,
3879                                   const SMDS_MeshNode * n2,
3880                                   const SMDS_MeshNode * n3,
3881                                   const SMDS_MeshNode * n4,
3882                                   const SMDS_MeshNode * n12,
3883                                   const SMDS_MeshNode * n23,
3884                                   const SMDS_MeshNode * n34,
3885                                   const SMDS_MeshNode * n41,
3886                                   const SMDS_MeshNode * nCenter)
3887 {
3888   return SMDS_Mesh::AddFaceWithID(n1,n2,n3,n4,n12,n23,n34,n41,nCenter,
3889                                   myElementIDFactory->GetFreeID());
3890 }
3891
3892 //=======================================================================
3893 //function : AddFaceWithID
3894 //purpose  :
3895 //=======================================================================
3896 SMDS_MeshFace* SMDS_Mesh::AddFaceWithID(int n1, int n2, int n3, int n4,
3897                                         int n12,int n23,int n34,int n41, int nCenter, int ID)
3898 {
3899   return SMDS_Mesh::AddFaceWithID
3900     ((SMDS_MeshNode *)myNodeIDFactory->MeshElement(n1) ,
3901      (SMDS_MeshNode *)myNodeIDFactory->MeshElement(n2) ,
3902      (SMDS_MeshNode *)myNodeIDFactory->MeshElement(n3) ,
3903      (SMDS_MeshNode *)myNodeIDFactory->MeshElement(n4) ,
3904      (SMDS_MeshNode *)myNodeIDFactory->MeshElement(n12),
3905      (SMDS_MeshNode *)myNodeIDFactory->MeshElement(n23),
3906      (SMDS_MeshNode *)myNodeIDFactory->MeshElement(n34),
3907      (SMDS_MeshNode *)myNodeIDFactory->MeshElement(n41),
3908      (SMDS_MeshNode *)myNodeIDFactory->MeshElement(nCenter),
3909      ID);
3910 }
3911
3912 //=======================================================================
3913 //function : AddFaceWithID
3914 //purpose  :
3915 //=======================================================================
3916 SMDS_MeshFace* SMDS_Mesh::AddFaceWithID(const SMDS_MeshNode * n1,
3917                                         const SMDS_MeshNode * n2,
3918                                         const SMDS_MeshNode * n3,
3919                                         const SMDS_MeshNode * n4,
3920                                         const SMDS_MeshNode * n12,
3921                                         const SMDS_MeshNode * n23,
3922                                         const SMDS_MeshNode * n34,
3923                                         const SMDS_MeshNode * n41,
3924                                         const SMDS_MeshNode * nCenter,
3925                                         int ID)
3926 {
3927   if ( !n1 || !n2 || !n3 || !n4 || !n12 || !n23 || !n34 || !n41 || !nCenter) return 0;
3928   if(hasConstructionEdges()) {
3929     // creation quadratic edges - not implemented
3930     return 0;
3931   }
3932   else
3933   {
3934     // --- retrieve nodes ID
3935     myNodeIds.resize(9);
3936     myNodeIds[0] = n1->getVtkId();
3937     myNodeIds[1] = n2->getVtkId();
3938     myNodeIds[2] = n3->getVtkId();
3939     myNodeIds[3] = n4->getVtkId();
3940     myNodeIds[4] = n12->getVtkId();
3941     myNodeIds[5] = n23->getVtkId();
3942     myNodeIds[6] = n34->getVtkId();
3943     myNodeIds[7] = n41->getVtkId();
3944     myNodeIds[8] = nCenter->getVtkId();
3945
3946     SMDS_MeshFace * face = 0;
3947     SMDS_VtkFace *facevtk = myFacePool->getNew();
3948     facevtk->init(myNodeIds, this);
3949     if (!this->registerElement(ID,facevtk))
3950     {
3951       this->myGrid->GetCellTypesArray()->SetValue(facevtk->getVtkId(), VTK_EMPTY_CELL);
3952       myFacePool->destroy(facevtk);
3953       return 0;
3954     }
3955     face = facevtk;
3956     adjustmyCellsCapacity(ID);
3957     myCells[ID] = face;
3958     myInfo.myNbBiQuadQuadrangles++;
3959
3960     //    if (!registerElement(ID, face)) {
3961     //      RemoveElement(face, false);
3962     //      face = NULL;
3963     //    }
3964     return face;
3965   }
3966 }
3967
3968
3969 //=======================================================================
3970 //function : AddVolume
3971 //purpose  :
3972 //=======================================================================
3973 SMDS_MeshVolume* SMDS_Mesh::AddVolume(const SMDS_MeshNode * n1,
3974                                       const SMDS_MeshNode * n2,
3975                                       const SMDS_MeshNode * n3,
3976                                       const SMDS_MeshNode * n4,
3977                                       const SMDS_MeshNode * n12,
3978                                       const SMDS_MeshNode * n23,
3979                                       const SMDS_MeshNode * n31,
3980                                       const SMDS_MeshNode * n14,
3981                                       const SMDS_MeshNode * n24,
3982                                       const SMDS_MeshNode * n34)
3983 {
3984   int ID = myElementIDFactory->GetFreeID();
3985   SMDS_MeshVolume * v = SMDS_Mesh::AddVolumeWithID(n1, n2, n3, n4, n12, n23,
3986                                                    n31, n14, n24, n34, ID);
3987   if(v==NULL) myElementIDFactory->ReleaseID(ID);
3988   return v;
3989 }
3990
3991 //=======================================================================
3992 //function : AddVolumeWithID
3993 //purpose  :
3994 //=======================================================================
3995 SMDS_MeshVolume* SMDS_Mesh::AddVolumeWithID(int n1, int n2, int n3, int n4,
3996                                             int n12,int n23,int n31,
3997                                             int n14,int n24,int n34, int ID)
3998 {
3999   return SMDS_Mesh::AddVolumeWithID
4000     ((SMDS_MeshNode*) myNodeIDFactory->MeshElement(n1) ,
4001      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n2) ,
4002      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n3) ,
4003      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n4) ,
4004      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n12),
4005      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n23),
4006      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n31),
4007      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n14),
4008      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n24),
4009      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n34),
4010      ID);
4011 }
4012
4013 //=======================================================================
4014 //function : AddVolumeWithID
4015 //purpose  : 2d order tetrahedron of 10 nodes
4016 //=======================================================================
4017 SMDS_MeshVolume* SMDS_Mesh::AddVolumeWithID(const SMDS_MeshNode * n1,
4018                                             const SMDS_MeshNode * n2,
4019                                             const SMDS_MeshNode * n3,
4020                                             const SMDS_MeshNode * n4,
4021                                             const SMDS_MeshNode * n12,
4022                                             const SMDS_MeshNode * n23,
4023                                             const SMDS_MeshNode * n31,
4024                                             const SMDS_MeshNode * n14,
4025                                             const SMDS_MeshNode * n24,
4026                                             const SMDS_MeshNode * n34,
4027                                             int ID)
4028 {
4029   if ( !n1 || !n2 || !n3 || !n4 || !n12 || !n23 || !n31 || !n14 || !n24 || !n34)
4030     return 0;
4031   if(hasConstructionFaces()) {
4032     // creation quadratic faces - not implemented
4033     return 0;
4034   }
4035   // --- retrieve nodes ID
4036   myNodeIds.resize(10);
4037   myNodeIds[0] = n1->getVtkId();
4038   myNodeIds[1] = n3->getVtkId();
4039   myNodeIds[2] = n2->getVtkId();
4040   myNodeIds[3] = n4->getVtkId();
4041
4042   myNodeIds[4] = n31->getVtkId();
4043   myNodeIds[5] = n23->getVtkId();
4044   myNodeIds[6] = n12->getVtkId();
4045
4046   myNodeIds[7] = n14->getVtkId();
4047   myNodeIds[8] = n34->getVtkId();
4048   myNodeIds[9] = n24->getVtkId();
4049
4050   SMDS_VtkVolume *volvtk = myVolumePool->getNew();
4051   volvtk->init(myNodeIds, this);
4052   if (!this->registerElement(ID,volvtk))
4053   {
4054     this->myGrid->GetCellTypesArray()->SetValue(volvtk->getVtkId(), VTK_EMPTY_CELL);
4055     myVolumePool->destroy(volvtk);
4056     return 0;
4057   }
4058   adjustmyCellsCapacity(ID);
4059   myCells[ID] = volvtk;
4060   myInfo.myNbQuadTetras++;
4061
4062   //  if (!registerElement(ID, volvtk)) {
4063   //    RemoveElement(volvtk, false);
4064   //    volvtk = NULL;
4065   //  }
4066   return volvtk;
4067 }
4068
4069
4070 //=======================================================================
4071 //function : AddVolume
4072 //purpose  :
4073 //=======================================================================
4074 SMDS_MeshVolume* SMDS_Mesh::AddVolume(const SMDS_MeshNode * n1,
4075                                       const SMDS_MeshNode * n2,
4076                                       const SMDS_MeshNode * n3,
4077                                       const SMDS_MeshNode * n4,
4078                                       const SMDS_MeshNode * n5,
4079                                       const SMDS_MeshNode * n12,
4080                                       const SMDS_MeshNode * n23,
4081                                       const SMDS_MeshNode * n34,
4082                                       const SMDS_MeshNode * n41,
4083                                       const SMDS_MeshNode * n15,
4084                                       const SMDS_MeshNode * n25,
4085                                       const SMDS_MeshNode * n35,
4086                                       const SMDS_MeshNode * n45)
4087 {
4088   int ID = myElementIDFactory->GetFreeID();
4089   SMDS_MeshVolume * v =
4090     SMDS_Mesh::AddVolumeWithID(n1, n2, n3, n4, n5, n12, n23, n34, n41,
4091                                n15, n25, n35, n45, ID);
4092   if(v==NULL) myElementIDFactory->ReleaseID(ID);
4093   return v;
4094 }
4095
4096 //=======================================================================
4097 //function : AddVolumeWithID
4098 //purpose  :
4099 //=======================================================================
4100 SMDS_MeshVolume* SMDS_Mesh::AddVolumeWithID(int n1, int n2, int n3, int n4, int n5,
4101                                             int n12,int n23,int n34,int n41,
4102                                             int n15,int n25,int n35,int n45, int ID)
4103 {
4104   return SMDS_Mesh::AddVolumeWithID
4105     ((SMDS_MeshNode*) myNodeIDFactory->MeshElement(n1) ,
4106      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n2) ,
4107      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n3) ,
4108      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n4) ,
4109      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n5) ,
4110      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n12),
4111      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n23),
4112      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n34),
4113      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n41),
4114      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n15),
4115      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n25),
4116      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n35),
4117      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n45),
4118      ID);
4119 }
4120
4121 //=======================================================================
4122 //function : AddVolumeWithID
4123 //purpose  : 2d order pyramid of 13 nodes
4124 //=======================================================================
4125 SMDS_MeshVolume* SMDS_Mesh::AddVolumeWithID(const SMDS_MeshNode * n1,
4126                                             const SMDS_MeshNode * n2,
4127                                             const SMDS_MeshNode * n3,
4128                                             const SMDS_MeshNode * n4,
4129                                             const SMDS_MeshNode * n5,
4130                                             const SMDS_MeshNode * n12,
4131                                             const SMDS_MeshNode * n23,
4132                                             const SMDS_MeshNode * n34,
4133                                             const SMDS_MeshNode * n41,
4134                                             const SMDS_MeshNode * n15,
4135                                             const SMDS_MeshNode * n25,
4136                                             const SMDS_MeshNode * n35,
4137                                             const SMDS_MeshNode * n45,
4138                                             int ID)
4139 {
4140   if (!n1 || !n2 || !n3 || !n4 || !n5 || !n12 || !n23 ||
4141       !n34 || !n41 || !n15 || !n25 || !n35 || !n45)
4142     return 0;
4143   if(hasConstructionFaces()) {
4144     // creation quadratic faces - not implemented
4145     return 0;
4146   }
4147   // --- retrieve nodes ID
4148   myNodeIds.resize(13);
4149   myNodeIds[0] = n1->getVtkId();
4150   myNodeIds[1] = n4->getVtkId();
4151   myNodeIds[2] = n3->getVtkId();
4152   myNodeIds[3] = n2->getVtkId();
4153   myNodeIds[4] = n5->getVtkId();
4154
4155   myNodeIds[5] = n41->getVtkId();
4156   myNodeIds[6] = n34->getVtkId();
4157   myNodeIds[7] = n23->getVtkId();
4158   myNodeIds[8] = n12->getVtkId();
4159
4160   myNodeIds[9] = n15->getVtkId();
4161   myNodeIds[10] = n45->getVtkId();
4162   myNodeIds[11] = n35->getVtkId();
4163   myNodeIds[12] = n25->getVtkId();
4164
4165   SMDS_VtkVolume *volvtk = myVolumePool->getNew();
4166   volvtk->init(myNodeIds, this);
4167   if (!this->registerElement(ID,volvtk))
4168   {
4169     this->myGrid->GetCellTypesArray()->SetValue(volvtk->getVtkId(), VTK_EMPTY_CELL);
4170     myVolumePool->destroy(volvtk);
4171     return 0;
4172   }
4173   adjustmyCellsCapacity(ID);
4174   myCells[ID] = volvtk;
4175   myInfo.myNbQuadPyramids++;
4176
4177   //  if (!registerElement(ID, volvtk)) {
4178   //    RemoveElement(volvtk, false);
4179   //    volvtk = NULL;
4180   //  }
4181   return volvtk;
4182 }
4183
4184
4185 //=======================================================================
4186 //function : AddVolume
4187 //purpose  :
4188 //=======================================================================
4189 SMDS_MeshVolume* SMDS_Mesh::AddVolume(const SMDS_MeshNode * n1,
4190                                       const SMDS_MeshNode * n2,
4191                                       const SMDS_MeshNode * n3,
4192                                       const SMDS_MeshNode * n4,
4193                                       const SMDS_MeshNode * n5,
4194                                       const SMDS_MeshNode * n6,
4195                                       const SMDS_MeshNode * n12,
4196                                       const SMDS_MeshNode * n23,
4197                                       const SMDS_MeshNode * n31,
4198                                       const SMDS_MeshNode * n45,
4199                                       const SMDS_MeshNode * n56,
4200                                       const SMDS_MeshNode * n64,
4201                                       const SMDS_MeshNode * n14,
4202                                       const SMDS_MeshNode * n25,
4203                                       const SMDS_MeshNode * n36)
4204 {
4205   int ID = myElementIDFactory->GetFreeID();
4206   SMDS_MeshVolume * v =
4207     SMDS_Mesh::AddVolumeWithID(n1, n2, n3, n4, n5, n6, n12, n23, n31,
4208                                n45, n56, n64, n14, n25, n36, ID);
4209   if(v==NULL) myElementIDFactory->ReleaseID(ID);
4210   return v;
4211 }
4212
4213 //=======================================================================
4214 //function : AddVolumeWithID
4215 //purpose  :
4216 //=======================================================================
4217 SMDS_MeshVolume* SMDS_Mesh::AddVolumeWithID(int n1, int n2, int n3,
4218                                             int n4, int n5, int n6,
4219                                             int n12,int n23,int n31,
4220                                             int n45,int n56,int n64,
4221                                             int n14,int n25,int n36, int ID)
4222 {
4223   return SMDS_Mesh::AddVolumeWithID
4224     ((SMDS_MeshNode*) myNodeIDFactory->MeshElement(n1) ,
4225      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n2) ,
4226      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n3) ,
4227      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n4) ,
4228      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n5) ,
4229      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n6) ,
4230      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n12),
4231      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n23),
4232      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n31),
4233      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n45),
4234      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n56),
4235      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n64),
4236      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n14),
4237      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n25),
4238      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n36),
4239      ID);
4240 }
4241
4242 //=======================================================================
4243 //function : AddVolumeWithID
4244 //purpose  : 2d order Pentahedron with 15 nodes
4245 //=======================================================================
4246 SMDS_MeshVolume* SMDS_Mesh::AddVolumeWithID(const SMDS_MeshNode * n1,
4247                                             const SMDS_MeshNode * n2,
4248                                             const SMDS_MeshNode * n3,
4249                                             const SMDS_MeshNode * n4,
4250                                             const SMDS_MeshNode * n5,
4251                                             const SMDS_MeshNode * n6,
4252                                             const SMDS_MeshNode * n12,
4253                                             const SMDS_MeshNode * n23,
4254                                             const SMDS_MeshNode * n31,
4255                                             const SMDS_MeshNode * n45,
4256                                             const SMDS_MeshNode * n56,
4257                                             const SMDS_MeshNode * n64,
4258                                             const SMDS_MeshNode * n14,
4259                                             const SMDS_MeshNode * n25,
4260                                             const SMDS_MeshNode * n36,
4261                                             int ID)
4262 {
4263   if (!n1 || !n2 || !n3 || !n4 || !n5 || !n6 || !n12 || !n23 ||
4264       !n31 || !n45 || !n56 || !n64 || !n14 || !n25 || !n36)
4265     return 0;
4266   if(hasConstructionFaces()) {
4267     // creation quadratic faces - not implemented
4268     return 0;
4269   }
4270   // --- retrieve nodes ID
4271   myNodeIds.resize(15);
4272   myNodeIds[0] = n1->getVtkId();
4273   myNodeIds[1] = n2->getVtkId();
4274   myNodeIds[2] = n3->getVtkId();
4275
4276   myNodeIds[3] = n4->getVtkId();
4277   myNodeIds[4] = n5->getVtkId();
4278   myNodeIds[5] = n6->getVtkId();
4279
4280   myNodeIds[6] = n12->getVtkId();
4281   myNodeIds[7] = n23->getVtkId();
4282   myNodeIds[8] = n31->getVtkId();
4283
4284   myNodeIds[9] = n45->getVtkId();
4285   myNodeIds[10] = n56->getVtkId();
4286   myNodeIds[11] = n64->getVtkId();
4287
4288   myNodeIds[12] = n14->getVtkId();
4289   myNodeIds[13] = n25->getVtkId();
4290   myNodeIds[14] = n36->getVtkId();
4291
4292   SMDS_VtkVolume *volvtk = myVolumePool->getNew();
4293   volvtk->init(myNodeIds, this);
4294   if (!this->registerElement(ID,volvtk))
4295   {
4296     this->myGrid->GetCellTypesArray()->SetValue(volvtk->getVtkId(), VTK_EMPTY_CELL);
4297     myVolumePool->destroy(volvtk);
4298     return 0;
4299   }
4300   adjustmyCellsCapacity(ID);
4301   myCells[ID] = volvtk;
4302   myInfo.myNbQuadPrisms++;
4303
4304   //  if (!registerElement(ID, volvtk)) {
4305   //    RemoveElement(volvtk, false);
4306   //    volvtk = NULL;
4307   //  }
4308   return volvtk;
4309 }
4310
4311
4312 //=======================================================================
4313 //function : AddVolume
4314 //purpose  :
4315 //=======================================================================
4316 SMDS_MeshVolume* SMDS_Mesh::AddVolume(const SMDS_MeshNode * n1,
4317                                       const SMDS_MeshNode * n2,
4318                                       const SMDS_MeshNode * n3,
4319                                       const SMDS_MeshNode * n4,
4320                                       const SMDS_MeshNode * n5,
4321                                       const SMDS_MeshNode * n6,
4322                                       const SMDS_MeshNode * n7,
4323                                       const SMDS_MeshNode * n8,
4324                                       const SMDS_MeshNode * n12,
4325                                       const SMDS_MeshNode * n23,
4326                                       const SMDS_MeshNode * n34,
4327                                       const SMDS_MeshNode * n41,
4328                                       const SMDS_MeshNode * n56,
4329                                       const SMDS_MeshNode * n67,
4330                                       const SMDS_MeshNode * n78,
4331                                       const SMDS_MeshNode * n85,
4332                                       const SMDS_MeshNode * n15,
4333                                       const SMDS_MeshNode * n26,
4334                                       const SMDS_MeshNode * n37,
4335                                       const SMDS_MeshNode * n48)
4336 {
4337   int ID = myElementIDFactory->GetFreeID();
4338   SMDS_MeshVolume * v =
4339     SMDS_Mesh::AddVolumeWithID(n1, n2, n3, n4, n5, n6, n7, n8, n12, n23, n34, n41,
4340                                n56, n67, n78, n85, n15, n26, n37, n48, ID);
4341   if(v==NULL) myElementIDFactory->ReleaseID(ID);
4342   return v;
4343 }
4344
4345 //=======================================================================
4346 //function : AddVolumeWithID
4347 //purpose  :
4348 //=======================================================================
4349 SMDS_MeshVolume* SMDS_Mesh::AddVolumeWithID(int n1, int n2, int n3, int n4,
4350                                             int n5, int n6, int n7, int n8,
4351                                             int n12,int n23,int n34,int n41,
4352                                             int n56,int n67,int n78,int n85,
4353                                             int n15,int n26,int n37,int n48, int ID)
4354 {
4355   return SMDS_Mesh::AddVolumeWithID
4356     ((SMDS_MeshNode*) myNodeIDFactory->MeshElement(n1),
4357      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n2),
4358      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n3),
4359      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n4),
4360      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n5),
4361      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n6),
4362      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n7),
4363      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n8),
4364      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n12),
4365      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n23),
4366      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n34),
4367      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n41),
4368      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n56),
4369      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n67),
4370      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n78),
4371      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n85),
4372      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n15),
4373      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n26),
4374      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n37),
4375      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n48),
4376      ID);
4377 }
4378
4379 //=======================================================================
4380 //function : AddVolumeWithID
4381 //purpose  : 2d order Hexahedrons with 20 nodes
4382 //=======================================================================
4383 SMDS_MeshVolume* SMDS_Mesh::AddVolumeWithID(const SMDS_MeshNode * n1,
4384                                             const SMDS_MeshNode * n2,
4385                                             const SMDS_MeshNode * n3,
4386                                             const SMDS_MeshNode * n4,
4387                                             const SMDS_MeshNode * n5,
4388                                             const SMDS_MeshNode * n6,
4389                                             const SMDS_MeshNode * n7,
4390                                             const SMDS_MeshNode * n8,
4391                                             const SMDS_MeshNode * n12,
4392                                             const SMDS_MeshNode * n23,
4393                                             const SMDS_MeshNode * n34,
4394                                             const SMDS_MeshNode * n41,
4395                                             const SMDS_MeshNode * n56,
4396                                             const SMDS_MeshNode * n67,
4397                                             const SMDS_MeshNode * n78,
4398                                             const SMDS_MeshNode * n85,
4399                                             const SMDS_MeshNode * n15,
4400                                             const SMDS_MeshNode * n26,
4401                                             const SMDS_MeshNode * n37,
4402                                             const SMDS_MeshNode * n48,
4403                                             int ID)
4404 {
4405   if (!n1 || !n2 || !n3 || !n4 || !n5 || !n6 || !n7 || !n8 || !n12 || !n23 ||
4406       !n34 || !n41 || !n56 || !n67 || !n78 || !n85 || !n15 || !n26 || !n37 || !n48)
4407     return 0;
4408   if(hasConstructionFaces()) {
4409     return 0;
4410     // creation quadratic faces - not implemented
4411   }
4412   // --- retrieve nodes ID
4413   myNodeIds.resize(20);
4414   myNodeIds[0] = n1->getVtkId();
4415   myNodeIds[1] = n4->getVtkId();
4416   myNodeIds[2] = n3->getVtkId();
4417   myNodeIds[3] = n2->getVtkId();
4418
4419   myNodeIds[4] = n5->getVtkId();
4420   myNodeIds[5] = n8->getVtkId();
4421   myNodeIds[6] = n7->getVtkId();
4422   myNodeIds[7] = n6->getVtkId();
4423
4424   myNodeIds[8] = n41->getVtkId();
4425   myNodeIds[9] = n34->getVtkId();
4426   myNodeIds[10] = n23->getVtkId();
4427   myNodeIds[11] = n12->getVtkId();
4428
4429   myNodeIds[12] = n85->getVtkId();
4430   myNodeIds[13] = n78->getVtkId();
4431   myNodeIds[14] = n67->getVtkId();
4432   myNodeIds[15] = n56->getVtkId();
4433
4434   myNodeIds[16] = n15->getVtkId();
4435   myNodeIds[17] = n48->getVtkId();
4436   myNodeIds[18] = n37->getVtkId();
4437   myNodeIds[19] = n26->getVtkId();
4438
4439   SMDS_VtkVolume *volvtk = myVolumePool->getNew();
4440   volvtk->init(myNodeIds, this);
4441   if (!this->registerElement(ID,volvtk))
4442   {
4443     this->myGrid->GetCellTypesArray()->SetValue(volvtk->getVtkId(), VTK_EMPTY_CELL);
4444     myVolumePool->destroy(volvtk);
4445     return 0;
4446   }
4447   adjustmyCellsCapacity(ID);
4448   myCells[ID] = volvtk;
4449   myInfo.myNbQuadHexas++;
4450
4451   //  if (!registerElement(ID, volvtk)) {
4452   //    RemoveElement(volvtk, false);
4453   //    volvtk = NULL;
4454   //  }
4455   return volvtk;
4456 }
4457
4458 //=======================================================================
4459 //function : AddVolume
4460 //purpose  :
4461 //=======================================================================
4462 SMDS_MeshVolume* SMDS_Mesh::AddVolume(const SMDS_MeshNode * n1,
4463                                       const SMDS_MeshNode * n2,
4464                                       const SMDS_MeshNode * n3,
4465                                       const SMDS_MeshNode * n4,
4466                                       const SMDS_MeshNode * n5,
4467                                       const SMDS_MeshNode * n6,
4468                                       const SMDS_MeshNode * n7,
4469                                       const SMDS_MeshNode * n8,
4470                                       const SMDS_MeshNode * n12,
4471                                       const SMDS_MeshNode * n23,
4472                                       const SMDS_MeshNode * n34,
4473                                       const SMDS_MeshNode * n41,
4474                                       const SMDS_MeshNode * n56,
4475                                       const SMDS_MeshNode * n67,
4476                                       const SMDS_MeshNode * n78,
4477                                       const SMDS_MeshNode * n85,
4478                                       const SMDS_MeshNode * n15,
4479                                       const SMDS_MeshNode * n26,
4480                                       const SMDS_MeshNode * n37,
4481                                       const SMDS_MeshNode * n48,
4482                                       const SMDS_MeshNode * n1234,
4483                                       const SMDS_MeshNode * n1256,
4484                                       const SMDS_MeshNode * n2367,
4485                                       const SMDS_MeshNode * n3478,
4486                                       const SMDS_MeshNode * n1458,
4487                                       const SMDS_MeshNode * n5678,
4488                                       const SMDS_MeshNode * nCenter)
4489 {
4490   int ID = myElementIDFactory->GetFreeID();
4491   SMDS_MeshVolume * v =
4492     SMDS_Mesh::AddVolumeWithID(n1, n2, n3, n4, n5, n6, n7, n8, n12, n23, n34, n41,
4493                                n56, n67, n78, n85, n15, n26, n37, n48,
4494                                n1234, n1256, n2367, n3478, n1458, n5678, nCenter,
4495                                ID);
4496   if(v==NULL) myElementIDFactory->ReleaseID(ID);
4497   return v;
4498 }
4499
4500 //=======================================================================
4501 //function : AddVolumeWithID
4502 //purpose  :
4503 //=======================================================================
4504 SMDS_MeshVolume* SMDS_Mesh::AddVolumeWithID(int n1, int n2, int n3, int n4,
4505                                             int n5, int n6, int n7, int n8,
4506                                             int n12,int n23,int n34,int n41,
4507                                             int n56,int n67,int n78,int n85,
4508                                             int n15,int n26,int n37,int n48,
4509                                             int n1234,int n1256,int n2367,int n3478,
4510                                             int n1458,int n5678,int nCenter, int ID)
4511 {
4512   return SMDS_Mesh::AddVolumeWithID
4513     ((SMDS_MeshNode*) myNodeIDFactory->MeshElement(n1),
4514      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n2),
4515      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n3),
4516      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n4),
4517      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n5),
4518      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n6),
4519      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n7),
4520      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n8),
4521      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n12),
4522      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n23),
4523      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n34),
4524      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n41),
4525      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n56),
4526      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n67),
4527      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n78),
4528      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n85),
4529      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n15),
4530      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n26),
4531      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n37),
4532      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n48),
4533      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n1234),
4534      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n1256),
4535      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n2367),
4536      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n3478),
4537      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n1458),
4538      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n5678),
4539      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(nCenter),
4540      ID);
4541 }
4542
4543 //=======================================================================
4544 //function : AddVolumeWithID
4545 //purpose  : 2d order Hexahedrons with 20 nodes
4546 //=======================================================================
4547 SMDS_MeshVolume* SMDS_Mesh::AddVolumeWithID(const SMDS_MeshNode * n1,
4548                                             const SMDS_MeshNode * n2,
4549                                             const SMDS_MeshNode * n3,
4550                                             const SMDS_MeshNode * n4,
4551                                             const SMDS_MeshNode * n5,
4552                                             const SMDS_MeshNode * n6,
4553                                             const SMDS_MeshNode * n7,
4554                                             const SMDS_MeshNode * n8,
4555                                             const SMDS_MeshNode * n12,
4556                                             const SMDS_MeshNode * n23,
4557                                             const SMDS_MeshNode * n34,
4558                                             const SMDS_MeshNode * n41,
4559                                             const SMDS_MeshNode * n56,
4560                                             const SMDS_MeshNode * n67,
4561                                             const SMDS_MeshNode * n78,
4562                                             const SMDS_MeshNode * n85,
4563                                             const SMDS_MeshNode * n15,
4564                                             const SMDS_MeshNode * n26,
4565                                             const SMDS_MeshNode * n37,
4566                                             const SMDS_MeshNode * n48,
4567                                             const SMDS_MeshNode * n1234,
4568                                             const SMDS_MeshNode * n1256,
4569                                             const SMDS_MeshNode * n2367,
4570                                             const SMDS_MeshNode * n3478,
4571                                             const SMDS_MeshNode * n1458,
4572                                             const SMDS_MeshNode * n5678,
4573                                             const SMDS_MeshNode * nCenter,
4574                                             int ID)
4575 {
4576   if (!n1 || !n2 || !n3 || !n4 || !n5 || !n6 || !n7 || !n8 || !n12 || !n23 ||
4577       !n34 || !n41 || !n56 || !n67 || !n78 || !n85 || !n15 || !n26 || !n37 || !n48 ||
4578       !n1234 || !n1256 || !n2367 || !n3478 || !n1458 || !n5678 || !nCenter )
4579     return 0;
4580   if(hasConstructionFaces()) {
4581     return 0;
4582     // creation quadratic faces - not implemented
4583   }
4584   // --- retrieve nodes ID
4585   myNodeIds.resize(27);
4586   myNodeIds[0] = n1->getVtkId();
4587   myNodeIds[1] = n4->getVtkId();
4588   myNodeIds[2] = n3->getVtkId();
4589   myNodeIds[3] = n2->getVtkId();
4590
4591   myNodeIds[4] = n5->getVtkId();
4592   myNodeIds[5] = n8->getVtkId();
4593   myNodeIds[6] = n7->getVtkId();
4594   myNodeIds[7] = n6->getVtkId();
4595
4596   myNodeIds[8] = n41->getVtkId();
4597   myNodeIds[9] = n34->getVtkId();
4598   myNodeIds[10] = n23->getVtkId();
4599   myNodeIds[11] = n12->getVtkId();
4600
4601   myNodeIds[12] = n85->getVtkId();
4602   myNodeIds[13] = n78->getVtkId();
4603   myNodeIds[14] = n67->getVtkId();
4604   myNodeIds[15] = n56->getVtkId();
4605
4606   myNodeIds[16] = n15->getVtkId();
4607   myNodeIds[17] = n48->getVtkId();
4608   myNodeIds[18] = n37->getVtkId();
4609   myNodeIds[19] = n26->getVtkId();
4610
4611   myNodeIds[20] = n1256->getVtkId();
4612   myNodeIds[21] = n3478->getVtkId();
4613   myNodeIds[22] = n1458->getVtkId();
4614   myNodeIds[23] = n2367->getVtkId();
4615   myNodeIds[24] = n1234->getVtkId();
4616   myNodeIds[25] = n5678->getVtkId();
4617   myNodeIds[26] = nCenter->getVtkId();
4618
4619   SMDS_VtkVolume *volvtk = myVolumePool->getNew();
4620   volvtk->init(myNodeIds, this);
4621   if (!this->registerElement(ID,volvtk))
4622   {
4623     this->myGrid->GetCellTypesArray()->SetValue(volvtk->getVtkId(), VTK_EMPTY_CELL);
4624     myVolumePool->destroy(volvtk);
4625     return 0;
4626   }
4627   adjustmyCellsCapacity(ID);
4628   myCells[ID] = volvtk;
4629   myInfo.myNbTriQuadHexas++;
4630
4631   return volvtk;
4632 }
4633
4634 void SMDS_Mesh::dumpGrid(string ficdump)
4635 {
4636   //  vtkUnstructuredGridWriter* aWriter = vtkUnstructuredGridWriter::New();
4637   //  aWriter->SetFileName(ficdump.c_str());
4638   //  aWriter->SetInput(myGrid);
4639   //  if(myGrid->GetNumberOfCells())
4640   //  {
4641   //    aWriter->Write();
4642   //  }
4643   //  aWriter->Delete();
4644   ficdump = ficdump + "_connectivity";
4645   ofstream ficcon(ficdump.c_str(), ios::out);
4646   int nbPoints = myGrid->GetNumberOfPoints();
4647   ficcon << "-------------------------------- points " <<  nbPoints << endl;
4648   for (int i=0; i<nbPoints; i++)
4649   {
4650     ficcon << i << " " << *(myGrid->GetPoint(i)) << " " << *(myGrid->GetPoint(i)+1) << " " << " " << *(myGrid->GetPoint(i)+2) << endl;
4651   }
4652   int nbCells = myGrid->GetNumberOfCells();
4653   ficcon << "-------------------------------- cells " <<  nbCells << endl;
4654   for (int i=0; i<nbCells; i++)
4655   {
4656     ficcon << i << " - " << myGrid->GetCell(i)->GetCellType() << " -";
4657     int nbptcell = myGrid->GetCell(i)->GetNumberOfPoints();
4658     vtkIdList *listid = myGrid->GetCell(i)->GetPointIds();
4659     for (int j=0; j<nbptcell; j++)
4660     {
4661       ficcon << " " <<  listid->GetId(j);
4662     }
4663     ficcon << endl;
4664   }
4665   ficcon << "-------------------------------- connectivity " <<  nbPoints << endl;
4666   vtkCellLinks *links = myGrid->GetLinks();
4667   for (int i=0; i<nbPoints; i++)
4668   {
4669     int ncells = links->GetNcells(i);
4670     vtkIdType *cells = links->GetCells(i);
4671     ficcon << i << " - " << ncells << " -";
4672     for (int j=0; j<ncells; j++)
4673     {
4674       ficcon << " " << cells[j];
4675     }
4676     ficcon << endl;
4677   }
4678   ficcon.close();
4679
4680 }
4681
4682 void SMDS_Mesh::compactMesh()
4683 {
4684   this->myCompactTime = this->myModifTime;
4685 }
4686
4687 int SMDS_Mesh::fromVtkToSmds(int vtkid)
4688 {
4689   if (vtkid >= 0 && vtkid < (int)myCellIdVtkToSmds.size())
4690     return myCellIdVtkToSmds[vtkid];
4691   throw SALOME_Exception(LOCALIZED ("vtk id out of bounds"));
4692 }
4693
4694 // void SMDS_Mesh::updateBoundingBox()
4695 // {
4696 //   xmin = 0; xmax = 0;
4697 //   ymin = 0; ymax = 0;
4698 //   zmin = 0; zmax = 0;
4699 //   vtkPoints *points = myGrid->GetPoints();
4700 //   int myNodesSize = this->myNodes.size();
4701 //   for (int i = 0; i < myNodesSize; i++)
4702 //     {
4703 //       if (SMDS_MeshNode *n = myNodes[i])
4704 //         {
4705 //           double coords[3];
4706 //           points->GetPoint(n->myVtkID, coords);
4707 //           if (coords[0] < xmin) xmin = coords[0];
4708 //           else if (coords[0] > xmax) xmax = coords[0];
4709 //           if (coords[1] < ymin) ymin = coords[1];
4710 //           else if (coords[1] > ymax) ymax = coords[1];
4711 //           if (coords[2] < zmin) zmin = coords[2];
4712 //           else if (coords[2] > zmax) zmax = coords[2];
4713 //         }
4714 //     }
4715 // }
4716
4717 double SMDS_Mesh::getMaxDim()
4718 {
4719   double dmax = 1.e-3;
4720   if ((xmax - xmin) > dmax) dmax = xmax -xmin;
4721   if ((ymax - ymin) > dmax) dmax = ymax -ymin;
4722   if ((zmax - zmin) > dmax) dmax = zmax -zmin;
4723   return dmax;
4724 }
4725
4726 //! modification that needs compact structure and redraw
4727 void SMDS_Mesh::Modified()
4728 {
4729   if (this->myModified)
4730   {
4731     this->myModifTime++;
4732     myModified = false;
4733   }
4734 }
4735
4736 //! get last modification timeStamp
4737 unsigned long SMDS_Mesh::GetMTime() const
4738 {
4739   return this->myModifTime;
4740 }
4741
4742 bool SMDS_Mesh::isCompacted()
4743 {
4744   return this->myCompactTime == this->myModifTime;
4745 }