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