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