Salome HOME
f378874828aa7a91101a0d9e6742be1915878d14
[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   case SMDSAbs_Ball:
3153   {
3154   }
3155   break;
3156   case SMDSAbs_Edge:
3157   {
3158     SMDS_ElemIteratorPtr itn=element->nodesIterator();
3159     while(itn->more())
3160     {
3161       const SMDS_MeshElement * e=itn->next();
3162       if(nodes.find(e)!=nodes.end())
3163       {
3164         setOfChildren.insert(element);
3165         break;
3166       }
3167     }
3168   } break;
3169   case SMDSAbs_Face:
3170   {
3171     SMDS_ElemIteratorPtr itn=element->nodesIterator();
3172     while(itn->more())
3173     {
3174       const SMDS_MeshElement * e=itn->next();
3175       if(nodes.find(e)!=nodes.end())
3176       {
3177         setOfChildren.insert(element);
3178         break;
3179       }
3180     }
3181     if(hasConstructionEdges())
3182     {
3183       SMDS_ElemIteratorPtr ite=element->edgesIterator();
3184       while(ite->more())
3185         addChildrenWithNodes(setOfChildren, ite->next(), nodes);
3186     }
3187   } break;
3188   case SMDSAbs_Volume:
3189   {
3190     if(hasConstructionFaces())
3191     {
3192       SMDS_ElemIteratorPtr ite=element->facesIterator();
3193       while(ite->more())
3194         addChildrenWithNodes(setOfChildren, ite->next(), nodes);
3195     }
3196     else if(hasConstructionEdges())
3197     {
3198       SMDS_ElemIteratorPtr ite=element->edgesIterator();
3199       while(ite->more())
3200         addChildrenWithNodes(setOfChildren, ite->next(), nodes);
3201     }
3202   }
3203   case SMDSAbs_NbElementTypes:
3204   case SMDSAbs_All: break;
3205   }
3206 }
3207
3208 ///////////////////////////////////////////////////////////////////////////////
3209 ///@param elem The element to delete
3210 ///@param removenodes if true remaining nodes will be removed
3211 ///////////////////////////////////////////////////////////////////////////////
3212 void SMDS_Mesh::RemoveElement(const SMDS_MeshElement * elem,
3213                               const bool removenodes)
3214 {
3215   list<const SMDS_MeshElement *> removedElems;
3216   list<const SMDS_MeshElement *> removedNodes;
3217   RemoveElement( elem, removedElems, removedNodes, removenodes );
3218 }
3219
3220 ///////////////////////////////////////////////////////////////////////////////
3221 ///@param elem The element to delete
3222 ///@param removedElems to be filled with all removed elements
3223 ///@param removedNodes to be filled with all removed nodes
3224 ///@param removenodes if true remaining nodes will be removed
3225 ///////////////////////////////////////////////////////////////////////////////
3226 void SMDS_Mesh::RemoveElement(const SMDS_MeshElement *        elem,
3227                               list<const SMDS_MeshElement *>& removedElems,
3228                               list<const SMDS_MeshElement *>& removedNodes,
3229                               bool                            removenodes)
3230 {
3231   //MESSAGE("SMDS_Mesh::RemoveElement " << elem->getVtkId() << " " << removenodes);
3232   // get finite elements built on elem
3233   set<const SMDS_MeshElement*> * s1;
3234   if (    (elem->GetType() == SMDSAbs_0DElement)
3235       || ((elem->GetType() == SMDSAbs_Edge) && !hasConstructionEdges())
3236       || ((elem->GetType() == SMDSAbs_Face) && !hasConstructionFaces())
3237       ||  (elem->GetType() == SMDSAbs_Volume) )
3238     {
3239       s1 = new set<const SMDS_MeshElement*> ();
3240       s1->insert(elem);
3241     }
3242   else
3243     s1 = getFinitElements(elem);
3244
3245   // get exclusive nodes (which would become free afterwards)
3246   set<const SMDS_MeshElement*> * s2;
3247   if (elem->GetType() == SMDSAbs_Node) // a node is removed
3248     {
3249       // do not remove nodes except elem
3250       s2 = new set<const SMDS_MeshElement*> ();
3251       s2->insert(elem);
3252       removenodes = true;
3253     }
3254   else
3255     s2 = getExclusiveNodes(*s1);
3256
3257   // form the set of finite and construction elements to remove
3258   set<const SMDS_MeshElement*> s3;
3259   set<const SMDS_MeshElement*>::iterator it = s1->begin();
3260   while (it != s1->end())
3261     {
3262       addChildrenWithNodes(s3, *it, *s2);
3263       s3.insert(*it);
3264       it++;
3265     }
3266   if (elem->GetType() != SMDSAbs_Node)
3267     s3.insert(elem);
3268
3269   // remove finite and construction elements
3270   it = s3.begin();
3271   while (it != s3.end())
3272     {
3273       // Remove element from <InverseElements> of its nodes
3274       SMDS_ElemIteratorPtr itn = (*it)->nodesIterator();
3275       while (itn->more())
3276         {
3277           SMDS_MeshNode * n = static_cast<SMDS_MeshNode *> (const_cast<SMDS_MeshElement *> (itn->next()));
3278           n->RemoveInverseElement((*it));
3279         }
3280       int IdToRemove = (*it)->GetID();
3281       int vtkid = (*it)->getVtkId();
3282       //MESSAGE("elem Id to remove " << IdToRemove << " vtkid " << vtkid <<
3283       //        " vtktype " << (*it)->GetVtkType() << " type " << (*it)->GetType());
3284       switch ((*it)->GetType())
3285       {
3286         case SMDSAbs_Node:
3287           MYASSERT("Internal Error: This should not happen")
3288           ;
3289           break;
3290         case SMDSAbs_0DElement:
3291           if (IdToRemove >= 0)
3292             {
3293               myCells[IdToRemove] = 0; // -PR- ici ou dans myElementIDFactory->ReleaseID ?
3294               myInfo.remove(*it);
3295             }
3296           removedElems.push_back((*it));
3297           myElementIDFactory->ReleaseID(IdToRemove, vtkid);
3298           delete (*it);
3299           break;
3300         case SMDSAbs_Edge:
3301           if (IdToRemove >= 0)
3302             {
3303               myCells[IdToRemove] = 0;
3304               myInfo.RemoveEdge(*it);
3305             }
3306           removedElems.push_back((*it));
3307           myElementIDFactory->ReleaseID(IdToRemove, vtkid);
3308           if (const SMDS_VtkEdge* vtkElem = dynamic_cast<const SMDS_VtkEdge*>(*it))
3309             myEdgePool->destroy((SMDS_VtkEdge*) vtkElem);
3310           else
3311             delete (*it);
3312           break;
3313         case SMDSAbs_Face:
3314           if (IdToRemove >= 0)
3315             {
3316               myCells[IdToRemove] = 0;
3317               myInfo.RemoveFace(*it);
3318             }
3319           removedElems.push_back((*it));
3320           myElementIDFactory->ReleaseID(IdToRemove, vtkid);
3321           if (const SMDS_VtkFace* vtkElem = dynamic_cast<const SMDS_VtkFace*>(*it))
3322             myFacePool->destroy((SMDS_VtkFace*) vtkElem);
3323           else
3324             delete (*it);
3325           break;
3326         case SMDSAbs_Volume:
3327           if (IdToRemove >= 0)
3328             {
3329               myCells[IdToRemove] = 0;
3330               myInfo.RemoveVolume(*it);
3331             }
3332           removedElems.push_back((*it));
3333           myElementIDFactory->ReleaseID(IdToRemove, vtkid);
3334           if (const SMDS_VtkVolume* vtkElem = dynamic_cast<const SMDS_VtkVolume*>(*it))
3335             myVolumePool->destroy((SMDS_VtkVolume*) vtkElem);
3336           else
3337             delete (*it);
3338           break;
3339         case SMDSAbs_Ball:
3340           if (IdToRemove >= 0)
3341             {
3342               myCells[IdToRemove] = 0;
3343               myInfo.remove(*it);
3344             }
3345           removedElems.push_back((*it));
3346           myElementIDFactory->ReleaseID(IdToRemove, vtkid);
3347           if (const SMDS_BallElement* vtkElem = dynamic_cast<const SMDS_BallElement*>(*it))
3348             myBallPool->destroy(const_cast<SMDS_BallElement*>( vtkElem ));
3349           else
3350             delete (*it);
3351           break;
3352
3353         case SMDSAbs_All:
3354         case SMDSAbs_NbElementTypes: break;
3355       }
3356       if (vtkid >= 0)
3357         {
3358           //MESSAGE("VTK_EMPTY_CELL in " << vtkid);
3359           this->myGrid->GetCellTypesArray()->SetValue(vtkid, VTK_EMPTY_CELL);
3360         }
3361       it++;
3362     }
3363
3364   // remove exclusive (free) nodes
3365   if (removenodes)
3366     {
3367       it = s2->begin();
3368       while (it != s2->end())
3369         {
3370           int IdToRemove = (*it)->GetID();
3371           //MESSAGE( "SMDS: RM node " << IdToRemove);
3372           if (IdToRemove >= 0)
3373             {
3374               myNodes[IdToRemove] = 0;
3375               myInfo.myNbNodes--;
3376             }
3377           myNodeIDFactory->ReleaseID((*it)->GetID(), (*it)->getVtkId());
3378           removedNodes.push_back((*it));
3379           if (const SMDS_MeshNode* vtkElem = dynamic_cast<const SMDS_MeshNode*>(*it))
3380           {
3381             ((SMDS_MeshNode*)vtkElem)->SetPosition(SMDS_SpacePosition::originSpacePosition());
3382             myNodePool->destroy((SMDS_MeshNode*) vtkElem);
3383           }
3384           else
3385             delete (*it);
3386           it++;
3387         }
3388     }
3389
3390   delete s2;
3391   delete s1;
3392 }
3393
3394
3395 ///////////////////////////////////////////////////////////////////////////////
3396 ///@param elem The element to delete
3397 ///////////////////////////////////////////////////////////////////////////////
3398 void SMDS_Mesh::RemoveFreeElement(const SMDS_MeshElement * elem)
3399 {
3400   int elemId = elem->GetID();
3401   int vtkId = elem->getVtkId();
3402   //MESSAGE("RemoveFreeElement " << elemId);
3403   SMDSAbs_ElementType aType = elem->GetType();
3404   SMDS_MeshElement* todest = (SMDS_MeshElement*)(elem);
3405   if (aType == SMDSAbs_Node) {
3406     //MESSAGE("Remove free node " << elemId);
3407     // only free node can be removed by this method
3408     const SMDS_MeshNode* n = static_cast<SMDS_MeshNode*>(todest);
3409     SMDS_ElemIteratorPtr itFe = n->GetInverseElementIterator();
3410     if (!itFe->more()) { // free node
3411       myNodes[elemId] = 0;
3412       myInfo.myNbNodes--;
3413       ((SMDS_MeshNode*) n)->SetPosition(SMDS_SpacePosition::originSpacePosition());
3414       ((SMDS_MeshNode*) n)->SMDS_MeshElement::init( -1, -1, -1 ); // avoid reuse
3415       myNodePool->destroy(static_cast<SMDS_MeshNode*>(todest));
3416       myNodeIDFactory->ReleaseID(elemId, vtkId);
3417     }
3418   } else {
3419     if (hasConstructionEdges() || hasConstructionFaces())
3420       // this methods is only for meshes without descendants
3421       return;
3422
3423     //MESSAGE("Remove free element " << elemId);
3424     // Remove element from <InverseElements> of its nodes
3425     SMDS_ElemIteratorPtr itn = elem->nodesIterator();
3426     while (itn->more()) {
3427       SMDS_MeshNode * n = static_cast<SMDS_MeshNode *>
3428         (const_cast<SMDS_MeshElement *>(itn->next()));
3429       n->RemoveInverseElement(elem);
3430     }
3431
3432     // in meshes without descendants elements are always free
3433      switch (aType) {
3434     case SMDSAbs_0DElement:
3435       myCells[elemId] = 0;
3436       myInfo.remove(elem);
3437       delete elem;
3438       break;
3439     case SMDSAbs_Edge:
3440       myCells[elemId] = 0;
3441       myInfo.RemoveEdge(elem);
3442       myEdgePool->destroy(static_cast<SMDS_VtkEdge*>(todest));
3443       break;
3444     case SMDSAbs_Face:
3445       myCells[elemId] = 0;
3446       myInfo.RemoveFace(elem);
3447       myFacePool->destroy(static_cast<SMDS_VtkFace*>(todest));
3448       break;
3449     case SMDSAbs_Volume:
3450       myCells[elemId] = 0;
3451       myInfo.RemoveVolume(elem);
3452       myVolumePool->destroy(static_cast<SMDS_VtkVolume*>(todest));
3453       break;
3454     case SMDSAbs_Ball:
3455       myCells[elemId] = 0;
3456       myInfo.remove(elem);
3457       myBallPool->destroy(static_cast<SMDS_BallElement*>(todest));
3458       break;
3459     default:
3460       break;
3461     }
3462     myElementIDFactory->ReleaseID(elemId, vtkId);
3463
3464     this->myGrid->GetCellTypesArray()->SetValue(vtkId, VTK_EMPTY_CELL);
3465     // --- to do: keep vtkid in a list of reusable cells
3466   }
3467 }
3468
3469 /*!
3470  * Checks if the element is present in mesh.
3471  * Useful to determine dead pointers.
3472  */
3473 bool SMDS_Mesh::Contains (const SMDS_MeshElement* elem) const
3474 {
3475   // we should not imply on validity of *elem, so iterate on containers
3476   // of all types in the hope of finding <elem> somewhere there
3477   SMDS_NodeIteratorPtr itn = nodesIterator();
3478   while (itn->more())
3479     if (elem == itn->next())
3480       return true;
3481   SMDS_ElemIteratorPtr ite = elementsIterator();
3482   while (ite->more())
3483     if (elem == ite->next())
3484       return true;
3485   return false;
3486 }
3487
3488 //=======================================================================
3489 //function : MaxNodeID
3490 //purpose  :
3491 //=======================================================================
3492
3493 int SMDS_Mesh::MaxNodeID() const
3494 {
3495   return myNodeMax;
3496 }
3497
3498 //=======================================================================
3499 //function : MinNodeID
3500 //purpose  :
3501 //=======================================================================
3502
3503 int SMDS_Mesh::MinNodeID() const
3504 {
3505   return myNodeMin;
3506 }
3507
3508 //=======================================================================
3509 //function : MaxElementID
3510 //purpose  :
3511 //=======================================================================
3512
3513 int SMDS_Mesh::MaxElementID() const
3514 {
3515   return myElementIDFactory->GetMaxID();
3516 }
3517
3518 //=======================================================================
3519 //function : MinElementID
3520 //purpose  :
3521 //=======================================================================
3522
3523 int SMDS_Mesh::MinElementID() const
3524 {
3525   return myElementIDFactory->GetMinID();
3526 }
3527
3528 //=======================================================================
3529 //function : Renumber
3530 //purpose  : Renumber all nodes or elements.
3531 //=======================================================================
3532
3533 void SMDS_Mesh::Renumber (const bool isNodes, const int  startID, const int  deltaID)
3534 {
3535     MESSAGE("Renumber");
3536   if ( deltaID == 0 )
3537     return;
3538
3539   SMDS_MeshNodeIDFactory * idFactory =
3540     isNodes ? myNodeIDFactory : myElementIDFactory;
3541
3542   // get existing elements in the order of ID increasing
3543   map<int,SMDS_MeshElement*> elemMap;
3544   SMDS_ElemIteratorPtr idElemIt = idFactory->elementsIterator();
3545   while ( idElemIt->more() ) {
3546     SMDS_MeshElement* elem = const_cast<SMDS_MeshElement*>(idElemIt->next());
3547     int id = elem->GetID();
3548     elemMap.insert(map<int,SMDS_MeshElement*>::value_type(id, elem));
3549   }
3550   // release their ids
3551   map<int,SMDS_MeshElement*>::iterator elemIt = elemMap.begin();
3552   idFactory->Clear();
3553 //   for ( ; elemIt != elemMap.end(); elemIt++ )
3554 //   {
3555 //     int id = (*elemIt).first;
3556 //     idFactory->ReleaseID( id );
3557 //   }
3558   // set new IDs
3559   int ID = startID;
3560   elemIt = elemMap.begin();
3561   for ( ; elemIt != elemMap.end(); elemIt++ )
3562   {
3563     idFactory->BindID( ID, (*elemIt).second );
3564     ID += deltaID;
3565   }
3566 }
3567
3568 //=======================================================================
3569 //function : GetElementType
3570 //purpose  : Return type of element or node with id
3571 //=======================================================================
3572
3573 SMDSAbs_ElementType SMDS_Mesh::GetElementType( const int id, const bool iselem ) const
3574 {
3575   SMDS_MeshElement* elem = 0;
3576   if( iselem )
3577     elem = myElementIDFactory->MeshElement( id );
3578   else
3579     elem = myNodeIDFactory->MeshElement( id );
3580
3581   if( !elem )
3582   {
3583     //throw SALOME_Exception(LOCALIZED ("this element isn't exist"));
3584     return SMDSAbs_All;
3585   }
3586   else
3587     return elem->GetType();
3588 }
3589
3590
3591
3592 //********************************************************************
3593 //********************************************************************
3594 //********                                                   *********
3595 //*****       Methods for addition of quadratic elements        ******
3596 //********                                                   *********
3597 //********************************************************************
3598 //********************************************************************
3599
3600 //=======================================================================
3601 //function : AddEdgeWithID
3602 //purpose  :
3603 //=======================================================================
3604 SMDS_MeshEdge* SMDS_Mesh::AddEdgeWithID(int n1, int n2, int n12, int ID)
3605 {
3606   return SMDS_Mesh::AddEdgeWithID
3607     ((SMDS_MeshNode*) myNodeIDFactory->MeshElement(n1),
3608      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n2),
3609      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n12),
3610      ID);
3611 }
3612
3613 //=======================================================================
3614 //function : AddEdge
3615 //purpose  :
3616 //=======================================================================
3617 SMDS_MeshEdge* SMDS_Mesh::AddEdge(const SMDS_MeshNode* n1,
3618                                   const SMDS_MeshNode* n2,
3619                                   const SMDS_MeshNode* n12)
3620 {
3621   return SMDS_Mesh::AddEdgeWithID(n1, n2, n12, myElementIDFactory->GetFreeID());
3622 }
3623
3624 //=======================================================================
3625 //function : AddEdgeWithID
3626 //purpose  :
3627 //=======================================================================
3628 SMDS_MeshEdge* SMDS_Mesh::AddEdgeWithID(const SMDS_MeshNode * n1,
3629                                         const SMDS_MeshNode * n2,
3630                                         const SMDS_MeshNode * n12,
3631                                         int ID)
3632 {
3633   if ( !n1 || !n2 || !n12 ) return 0;
3634
3635   // --- retrieve nodes ID
3636   myNodeIds.resize(3);
3637   myNodeIds[0] = n1->getVtkId();
3638   myNodeIds[1] = n2->getVtkId();
3639   myNodeIds[2] = n12->getVtkId();
3640
3641   SMDS_MeshEdge * edge = 0;
3642   SMDS_VtkEdge *edgevtk = myEdgePool->getNew();
3643   edgevtk->init(myNodeIds, this);
3644   if (!this->registerElement(ID,edgevtk))
3645   {
3646     this->myGrid->GetCellTypesArray()->SetValue(edgevtk->getVtkId(), VTK_EMPTY_CELL);
3647     myEdgePool->destroy(edgevtk);
3648     return 0;
3649   }
3650   edge = edgevtk;
3651   adjustmyCellsCapacity(ID);
3652   myCells[ID] = edge;
3653   myInfo.myNbQuadEdges++;
3654
3655   //  if (!registerElement(ID, edge)) {
3656   //        RemoveElement(edge, false);
3657   //        edge = NULL;
3658   //  }
3659   return edge;
3660
3661 }
3662
3663
3664 //=======================================================================
3665 //function : AddFace
3666 //purpose  :
3667 //=======================================================================
3668 SMDS_MeshFace* SMDS_Mesh::AddFace(const SMDS_MeshNode * n1,
3669                                   const SMDS_MeshNode * n2,
3670                                   const SMDS_MeshNode * n3,
3671                                   const SMDS_MeshNode * n12,
3672                                   const SMDS_MeshNode * n23,
3673                                   const SMDS_MeshNode * n31)
3674 {
3675   return SMDS_Mesh::AddFaceWithID(n1,n2,n3,n12,n23,n31,
3676                                   myElementIDFactory->GetFreeID());
3677 }
3678
3679 //=======================================================================
3680 //function : AddFaceWithID
3681 //purpose  :
3682 //=======================================================================
3683 SMDS_MeshFace* SMDS_Mesh::AddFaceWithID(int n1, int n2, int n3,
3684                                         int n12,int n23,int n31, int ID)
3685 {
3686   return SMDS_Mesh::AddFaceWithID
3687     ((SMDS_MeshNode *)myNodeIDFactory->MeshElement(n1) ,
3688      (SMDS_MeshNode *)myNodeIDFactory->MeshElement(n2) ,
3689      (SMDS_MeshNode *)myNodeIDFactory->MeshElement(n3) ,
3690      (SMDS_MeshNode *)myNodeIDFactory->MeshElement(n12),
3691      (SMDS_MeshNode *)myNodeIDFactory->MeshElement(n23),
3692      (SMDS_MeshNode *)myNodeIDFactory->MeshElement(n31),
3693      ID);
3694 }
3695
3696 //=======================================================================
3697 //function : AddFaceWithID
3698 //purpose  :
3699 //=======================================================================
3700 SMDS_MeshFace* SMDS_Mesh::AddFaceWithID(const SMDS_MeshNode * n1,
3701                                         const SMDS_MeshNode * n2,
3702                                         const SMDS_MeshNode * n3,
3703                                         const SMDS_MeshNode * n12,
3704                                         const SMDS_MeshNode * n23,
3705                                         const SMDS_MeshNode * n31,
3706                                         int ID)
3707 {
3708   if ( !n1 || !n2 || !n3 || !n12 || !n23 || !n31) return 0;
3709   if(hasConstructionEdges()) {
3710     // creation quadratic edges - not implemented
3711     return 0;
3712   }
3713   else
3714   {
3715     // --- retrieve nodes ID
3716     myNodeIds.resize(6);
3717     myNodeIds[0] = n1->getVtkId();
3718     myNodeIds[1] = n2->getVtkId();
3719     myNodeIds[2] = n3->getVtkId();
3720     myNodeIds[3] = n12->getVtkId();
3721     myNodeIds[4] = n23->getVtkId();
3722     myNodeIds[5] = n31->getVtkId();
3723
3724     SMDS_MeshFace * face = 0;
3725     SMDS_VtkFace *facevtk = myFacePool->getNew();
3726     facevtk->init(myNodeIds, this);
3727     if (!this->registerElement(ID,facevtk))
3728     {
3729       this->myGrid->GetCellTypesArray()->SetValue(facevtk->getVtkId(), VTK_EMPTY_CELL);
3730       myFacePool->destroy(facevtk);
3731       return 0;
3732     }
3733     face = facevtk;
3734     adjustmyCellsCapacity(ID);
3735     myCells[ID] = face;
3736     myInfo.myNbQuadTriangles++;
3737
3738     //    if (!registerElement(ID, face)) {
3739     //      RemoveElement(face, false);
3740     //      face = NULL;
3741     //    }
3742     return face;
3743   }
3744 }
3745
3746
3747 //=======================================================================
3748 //function : AddFace
3749 //purpose  :
3750 //=======================================================================
3751 SMDS_MeshFace* SMDS_Mesh::AddFace(const SMDS_MeshNode * n1,
3752                                   const SMDS_MeshNode * n2,
3753                                   const SMDS_MeshNode * n3,
3754                                   const SMDS_MeshNode * n12,
3755                                   const SMDS_MeshNode * n23,
3756                                   const SMDS_MeshNode * n31,
3757                                   const SMDS_MeshNode * nCenter)
3758 {
3759   return SMDS_Mesh::AddFaceWithID(n1,n2,n3,n12,n23,n31,nCenter,
3760                                   myElementIDFactory->GetFreeID());
3761 }
3762
3763 //=======================================================================
3764 //function : AddFaceWithID
3765 //purpose  :
3766 //=======================================================================
3767 SMDS_MeshFace* SMDS_Mesh::AddFaceWithID(int n1, int n2, int n3,
3768                                         int n12,int n23,int n31, int nCenter, int ID)
3769 {
3770   return SMDS_Mesh::AddFaceWithID
3771     ((SMDS_MeshNode *)myNodeIDFactory->MeshElement(n1) ,
3772      (SMDS_MeshNode *)myNodeIDFactory->MeshElement(n2) ,
3773      (SMDS_MeshNode *)myNodeIDFactory->MeshElement(n3) ,
3774      (SMDS_MeshNode *)myNodeIDFactory->MeshElement(n12),
3775      (SMDS_MeshNode *)myNodeIDFactory->MeshElement(n23),
3776      (SMDS_MeshNode *)myNodeIDFactory->MeshElement(n31),
3777      (SMDS_MeshNode *)myNodeIDFactory->MeshElement(nCenter),
3778      ID);
3779 }
3780
3781 //=======================================================================
3782 //function : AddFaceWithID
3783 //purpose  :
3784 //=======================================================================
3785 SMDS_MeshFace* SMDS_Mesh::AddFaceWithID(const SMDS_MeshNode * n1,
3786                                         const SMDS_MeshNode * n2,
3787                                         const SMDS_MeshNode * n3,
3788                                         const SMDS_MeshNode * n12,
3789                                         const SMDS_MeshNode * n23,
3790                                         const SMDS_MeshNode * n31,
3791                                         const SMDS_MeshNode * nCenter,
3792                                         int ID)
3793 {
3794   if ( !n1 || !n2 || !n3 || !n12 || !n23 || !n31 || !nCenter) return 0;
3795   if(hasConstructionEdges()) {
3796     // creation quadratic edges - not implemented
3797     return 0;
3798   }
3799   else
3800   {
3801     // --- retrieve nodes ID
3802     myNodeIds.resize(7);
3803     myNodeIds[0] = n1->getVtkId();
3804     myNodeIds[1] = n2->getVtkId();
3805     myNodeIds[2] = n3->getVtkId();
3806     myNodeIds[3] = n12->getVtkId();
3807     myNodeIds[4] = n23->getVtkId();
3808     myNodeIds[5] = n31->getVtkId();
3809     myNodeIds[6] = nCenter->getVtkId();
3810
3811     SMDS_MeshFace * face = 0;
3812     SMDS_VtkFace *facevtk = myFacePool->getNew();
3813     facevtk->init(myNodeIds, this);
3814     if (!this->registerElement(ID,facevtk))
3815     {
3816       this->myGrid->GetCellTypesArray()->SetValue(facevtk->getVtkId(), VTK_EMPTY_CELL);
3817       myFacePool->destroy(facevtk);
3818       return 0;
3819     }
3820     face = facevtk;
3821     adjustmyCellsCapacity(ID);
3822     myCells[ID] = face;
3823     myInfo.myNbBiQuadTriangles++;
3824
3825     //    if (!registerElement(ID, face)) {
3826     //      RemoveElement(face, false);
3827     //      face = NULL;
3828     //    }
3829     return face;
3830   }
3831 }
3832
3833
3834 //=======================================================================
3835 //function : AddFace
3836 //purpose  :
3837 //=======================================================================
3838 SMDS_MeshFace* SMDS_Mesh::AddFace(const SMDS_MeshNode * n1,
3839                                   const SMDS_MeshNode * n2,
3840                                   const SMDS_MeshNode * n3,
3841                                   const SMDS_MeshNode * n4,
3842                                   const SMDS_MeshNode * n12,
3843                                   const SMDS_MeshNode * n23,
3844                                   const SMDS_MeshNode * n34,
3845                                   const SMDS_MeshNode * n41)
3846 {
3847   return SMDS_Mesh::AddFaceWithID(n1,n2,n3,n4,n12,n23,n34,n41,
3848                                   myElementIDFactory->GetFreeID());
3849 }
3850
3851 //=======================================================================
3852 //function : AddFaceWithID
3853 //purpose  :
3854 //=======================================================================
3855 SMDS_MeshFace* SMDS_Mesh::AddFaceWithID(int n1, int n2, int n3, int n4,
3856                                         int n12,int n23,int n34,int n41, int ID)
3857 {
3858   return SMDS_Mesh::AddFaceWithID
3859     ((SMDS_MeshNode *)myNodeIDFactory->MeshElement(n1) ,
3860      (SMDS_MeshNode *)myNodeIDFactory->MeshElement(n2) ,
3861      (SMDS_MeshNode *)myNodeIDFactory->MeshElement(n3) ,
3862      (SMDS_MeshNode *)myNodeIDFactory->MeshElement(n4) ,
3863      (SMDS_MeshNode *)myNodeIDFactory->MeshElement(n12),
3864      (SMDS_MeshNode *)myNodeIDFactory->MeshElement(n23),
3865      (SMDS_MeshNode *)myNodeIDFactory->MeshElement(n34),
3866      (SMDS_MeshNode *)myNodeIDFactory->MeshElement(n41),
3867      ID);
3868 }
3869
3870 //=======================================================================
3871 //function : AddFaceWithID
3872 //purpose  :
3873 //=======================================================================
3874 SMDS_MeshFace* SMDS_Mesh::AddFaceWithID(const SMDS_MeshNode * n1,
3875                                         const SMDS_MeshNode * n2,
3876                                         const SMDS_MeshNode * n3,
3877                                         const SMDS_MeshNode * n4,
3878                                         const SMDS_MeshNode * n12,
3879                                         const SMDS_MeshNode * n23,
3880                                         const SMDS_MeshNode * n34,
3881                                         const SMDS_MeshNode * n41,
3882                                         int ID)
3883 {
3884   if ( !n1 || !n2 || !n3 || !n4 || !n12 || !n23 || !n34 || !n41) return 0;
3885   if(hasConstructionEdges()) {
3886     // creation quadratic edges - not implemented
3887     return 0;
3888   }
3889   else
3890   {
3891     // --- retrieve nodes ID
3892     myNodeIds.resize(8);
3893     myNodeIds[0] = n1->getVtkId();
3894     myNodeIds[1] = n2->getVtkId();
3895     myNodeIds[2] = n3->getVtkId();
3896     myNodeIds[3] = n4->getVtkId();
3897     myNodeIds[4] = n12->getVtkId();
3898     myNodeIds[5] = n23->getVtkId();
3899     myNodeIds[6] = n34->getVtkId();
3900     myNodeIds[7] = n41->getVtkId();
3901
3902     SMDS_MeshFace * face = 0;
3903     SMDS_VtkFace *facevtk = myFacePool->getNew();
3904     facevtk->init(myNodeIds, this);
3905     if (!this->registerElement(ID,facevtk))
3906     {
3907       this->myGrid->GetCellTypesArray()->SetValue(facevtk->getVtkId(), VTK_EMPTY_CELL);
3908       myFacePool->destroy(facevtk);
3909       return 0;
3910     }
3911     face = facevtk;
3912     adjustmyCellsCapacity(ID);
3913     myCells[ID] = face;
3914     myInfo.myNbQuadQuadrangles++;
3915
3916     //    if (!registerElement(ID, face)) {
3917     //      RemoveElement(face, false);
3918     //      face = NULL;
3919     //    }
3920     return face;
3921   }
3922 }
3923
3924 //=======================================================================
3925 //function : AddFace
3926 //purpose  :
3927 //=======================================================================
3928 SMDS_MeshFace* SMDS_Mesh::AddFace(const SMDS_MeshNode * n1,
3929                                   const SMDS_MeshNode * n2,
3930                                   const SMDS_MeshNode * n3,
3931                                   const SMDS_MeshNode * n4,
3932                                   const SMDS_MeshNode * n12,
3933                                   const SMDS_MeshNode * n23,
3934                                   const SMDS_MeshNode * n34,
3935                                   const SMDS_MeshNode * n41,
3936                                   const SMDS_MeshNode * nCenter)
3937 {
3938   return SMDS_Mesh::AddFaceWithID(n1,n2,n3,n4,n12,n23,n34,n41,nCenter,
3939                                   myElementIDFactory->GetFreeID());
3940 }
3941
3942 //=======================================================================
3943 //function : AddFaceWithID
3944 //purpose  :
3945 //=======================================================================
3946 SMDS_MeshFace* SMDS_Mesh::AddFaceWithID(int n1, int n2, int n3, int n4,
3947                                         int n12,int n23,int n34,int n41, int nCenter, int ID)
3948 {
3949   return SMDS_Mesh::AddFaceWithID
3950     ((SMDS_MeshNode *)myNodeIDFactory->MeshElement(n1) ,
3951      (SMDS_MeshNode *)myNodeIDFactory->MeshElement(n2) ,
3952      (SMDS_MeshNode *)myNodeIDFactory->MeshElement(n3) ,
3953      (SMDS_MeshNode *)myNodeIDFactory->MeshElement(n4) ,
3954      (SMDS_MeshNode *)myNodeIDFactory->MeshElement(n12),
3955      (SMDS_MeshNode *)myNodeIDFactory->MeshElement(n23),
3956      (SMDS_MeshNode *)myNodeIDFactory->MeshElement(n34),
3957      (SMDS_MeshNode *)myNodeIDFactory->MeshElement(n41),
3958      (SMDS_MeshNode *)myNodeIDFactory->MeshElement(nCenter),
3959      ID);
3960 }
3961
3962 //=======================================================================
3963 //function : AddFaceWithID
3964 //purpose  :
3965 //=======================================================================
3966 SMDS_MeshFace* SMDS_Mesh::AddFaceWithID(const SMDS_MeshNode * n1,
3967                                         const SMDS_MeshNode * n2,
3968                                         const SMDS_MeshNode * n3,
3969                                         const SMDS_MeshNode * n4,
3970                                         const SMDS_MeshNode * n12,
3971                                         const SMDS_MeshNode * n23,
3972                                         const SMDS_MeshNode * n34,
3973                                         const SMDS_MeshNode * n41,
3974                                         const SMDS_MeshNode * nCenter,
3975                                         int ID)
3976 {
3977   if ( !n1 || !n2 || !n3 || !n4 || !n12 || !n23 || !n34 || !n41 || !nCenter) return 0;
3978   if(hasConstructionEdges()) {
3979     // creation quadratic edges - not implemented
3980     return 0;
3981   }
3982   else
3983   {
3984     // --- retrieve nodes ID
3985     myNodeIds.resize(9);
3986     myNodeIds[0] = n1->getVtkId();
3987     myNodeIds[1] = n2->getVtkId();
3988     myNodeIds[2] = n3->getVtkId();
3989     myNodeIds[3] = n4->getVtkId();
3990     myNodeIds[4] = n12->getVtkId();
3991     myNodeIds[5] = n23->getVtkId();
3992     myNodeIds[6] = n34->getVtkId();
3993     myNodeIds[7] = n41->getVtkId();
3994     myNodeIds[8] = nCenter->getVtkId();
3995
3996     SMDS_MeshFace * face = 0;
3997     SMDS_VtkFace *facevtk = myFacePool->getNew();
3998     facevtk->init(myNodeIds, this);
3999     if (!this->registerElement(ID,facevtk))
4000     {
4001       this->myGrid->GetCellTypesArray()->SetValue(facevtk->getVtkId(), VTK_EMPTY_CELL);
4002       myFacePool->destroy(facevtk);
4003       return 0;
4004     }
4005     face = facevtk;
4006     adjustmyCellsCapacity(ID);
4007     myCells[ID] = face;
4008     myInfo.myNbBiQuadQuadrangles++;
4009
4010     //    if (!registerElement(ID, face)) {
4011     //      RemoveElement(face, false);
4012     //      face = NULL;
4013     //    }
4014     return face;
4015   }
4016 }
4017
4018
4019 //=======================================================================
4020 //function : AddVolume
4021 //purpose  :
4022 //=======================================================================
4023 SMDS_MeshVolume* SMDS_Mesh::AddVolume(const SMDS_MeshNode * n1,
4024                                       const SMDS_MeshNode * n2,
4025                                       const SMDS_MeshNode * n3,
4026                                       const SMDS_MeshNode * n4,
4027                                       const SMDS_MeshNode * n12,
4028                                       const SMDS_MeshNode * n23,
4029                                       const SMDS_MeshNode * n31,
4030                                       const SMDS_MeshNode * n14,
4031                                       const SMDS_MeshNode * n24,
4032                                       const SMDS_MeshNode * n34)
4033 {
4034   int ID = myElementIDFactory->GetFreeID();
4035   SMDS_MeshVolume * v = SMDS_Mesh::AddVolumeWithID(n1, n2, n3, n4, n12, n23,
4036                                                    n31, n14, n24, n34, ID);
4037   if(v==NULL) myElementIDFactory->ReleaseID(ID);
4038   return v;
4039 }
4040
4041 //=======================================================================
4042 //function : AddVolumeWithID
4043 //purpose  :
4044 //=======================================================================
4045 SMDS_MeshVolume* SMDS_Mesh::AddVolumeWithID(int n1, int n2, int n3, int n4,
4046                                             int n12,int n23,int n31,
4047                                             int n14,int n24,int n34, int ID)
4048 {
4049   return SMDS_Mesh::AddVolumeWithID
4050     ((SMDS_MeshNode*) myNodeIDFactory->MeshElement(n1) ,
4051      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n2) ,
4052      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n3) ,
4053      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n4) ,
4054      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n12),
4055      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n23),
4056      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n31),
4057      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n14),
4058      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n24),
4059      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n34),
4060      ID);
4061 }
4062
4063 //=======================================================================
4064 //function : AddVolumeWithID
4065 //purpose  : 2d order tetrahedron of 10 nodes
4066 //=======================================================================
4067 SMDS_MeshVolume* SMDS_Mesh::AddVolumeWithID(const SMDS_MeshNode * n1,
4068                                             const SMDS_MeshNode * n2,
4069                                             const SMDS_MeshNode * n3,
4070                                             const SMDS_MeshNode * n4,
4071                                             const SMDS_MeshNode * n12,
4072                                             const SMDS_MeshNode * n23,
4073                                             const SMDS_MeshNode * n31,
4074                                             const SMDS_MeshNode * n14,
4075                                             const SMDS_MeshNode * n24,
4076                                             const SMDS_MeshNode * n34,
4077                                             int ID)
4078 {
4079   if ( !n1 || !n2 || !n3 || !n4 || !n12 || !n23 || !n31 || !n14 || !n24 || !n34)
4080     return 0;
4081   if(hasConstructionFaces()) {
4082     // creation quadratic faces - not implemented
4083     return 0;
4084   }
4085   // --- retrieve nodes ID
4086   myNodeIds.resize(10);
4087   myNodeIds[0] = n1->getVtkId();
4088   myNodeIds[1] = n3->getVtkId();
4089   myNodeIds[2] = n2->getVtkId();
4090   myNodeIds[3] = n4->getVtkId();
4091
4092   myNodeIds[4] = n31->getVtkId();
4093   myNodeIds[5] = n23->getVtkId();
4094   myNodeIds[6] = n12->getVtkId();
4095
4096   myNodeIds[7] = n14->getVtkId();
4097   myNodeIds[8] = n34->getVtkId();
4098   myNodeIds[9] = n24->getVtkId();
4099
4100   SMDS_VtkVolume *volvtk = myVolumePool->getNew();
4101   volvtk->init(myNodeIds, this);
4102   if (!this->registerElement(ID,volvtk))
4103   {
4104     this->myGrid->GetCellTypesArray()->SetValue(volvtk->getVtkId(), VTK_EMPTY_CELL);
4105     myVolumePool->destroy(volvtk);
4106     return 0;
4107   }
4108   adjustmyCellsCapacity(ID);
4109   myCells[ID] = volvtk;
4110   myInfo.myNbQuadTetras++;
4111
4112   //  if (!registerElement(ID, volvtk)) {
4113   //    RemoveElement(volvtk, false);
4114   //    volvtk = NULL;
4115   //  }
4116   return volvtk;
4117 }
4118
4119
4120 //=======================================================================
4121 //function : AddVolume
4122 //purpose  :
4123 //=======================================================================
4124 SMDS_MeshVolume* SMDS_Mesh::AddVolume(const SMDS_MeshNode * n1,
4125                                       const SMDS_MeshNode * n2,
4126                                       const SMDS_MeshNode * n3,
4127                                       const SMDS_MeshNode * n4,
4128                                       const SMDS_MeshNode * n5,
4129                                       const SMDS_MeshNode * n12,
4130                                       const SMDS_MeshNode * n23,
4131                                       const SMDS_MeshNode * n34,
4132                                       const SMDS_MeshNode * n41,
4133                                       const SMDS_MeshNode * n15,
4134                                       const SMDS_MeshNode * n25,
4135                                       const SMDS_MeshNode * n35,
4136                                       const SMDS_MeshNode * n45)
4137 {
4138   int ID = myElementIDFactory->GetFreeID();
4139   SMDS_MeshVolume * v =
4140     SMDS_Mesh::AddVolumeWithID(n1, n2, n3, n4, n5, n12, n23, n34, n41,
4141                                n15, n25, n35, n45, ID);
4142   if(v==NULL) myElementIDFactory->ReleaseID(ID);
4143   return v;
4144 }
4145
4146 //=======================================================================
4147 //function : AddVolumeWithID
4148 //purpose  :
4149 //=======================================================================
4150 SMDS_MeshVolume* SMDS_Mesh::AddVolumeWithID(int n1, int n2, int n3, int n4, int n5,
4151                                             int n12,int n23,int n34,int n41,
4152                                             int n15,int n25,int n35,int n45, int ID)
4153 {
4154   return SMDS_Mesh::AddVolumeWithID
4155     ((SMDS_MeshNode*) myNodeIDFactory->MeshElement(n1) ,
4156      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n2) ,
4157      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n3) ,
4158      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n4) ,
4159      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n5) ,
4160      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n12),
4161      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n23),
4162      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n34),
4163      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n41),
4164      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n15),
4165      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n25),
4166      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n35),
4167      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n45),
4168      ID);
4169 }
4170
4171 //=======================================================================
4172 //function : AddVolumeWithID
4173 //purpose  : 2d order pyramid of 13 nodes
4174 //=======================================================================
4175 SMDS_MeshVolume* SMDS_Mesh::AddVolumeWithID(const SMDS_MeshNode * n1,
4176                                             const SMDS_MeshNode * n2,
4177                                             const SMDS_MeshNode * n3,
4178                                             const SMDS_MeshNode * n4,
4179                                             const SMDS_MeshNode * n5,
4180                                             const SMDS_MeshNode * n12,
4181                                             const SMDS_MeshNode * n23,
4182                                             const SMDS_MeshNode * n34,
4183                                             const SMDS_MeshNode * n41,
4184                                             const SMDS_MeshNode * n15,
4185                                             const SMDS_MeshNode * n25,
4186                                             const SMDS_MeshNode * n35,
4187                                             const SMDS_MeshNode * n45,
4188                                             int ID)
4189 {
4190   if (!n1 || !n2 || !n3 || !n4 || !n5 || !n12 || !n23 ||
4191       !n34 || !n41 || !n15 || !n25 || !n35 || !n45)
4192     return 0;
4193   if(hasConstructionFaces()) {
4194     // creation quadratic faces - not implemented
4195     return 0;
4196   }
4197   // --- retrieve nodes ID
4198   myNodeIds.resize(13);
4199   myNodeIds[0] = n1->getVtkId();
4200   myNodeIds[1] = n4->getVtkId();
4201   myNodeIds[2] = n3->getVtkId();
4202   myNodeIds[3] = n2->getVtkId();
4203   myNodeIds[4] = n5->getVtkId();
4204
4205   myNodeIds[5] = n41->getVtkId();
4206   myNodeIds[6] = n34->getVtkId();
4207   myNodeIds[7] = n23->getVtkId();
4208   myNodeIds[8] = n12->getVtkId();
4209
4210   myNodeIds[9] = n15->getVtkId();
4211   myNodeIds[10] = n45->getVtkId();
4212   myNodeIds[11] = n35->getVtkId();
4213   myNodeIds[12] = n25->getVtkId();
4214
4215   SMDS_VtkVolume *volvtk = myVolumePool->getNew();
4216   volvtk->init(myNodeIds, this);
4217   if (!this->registerElement(ID,volvtk))
4218   {
4219     this->myGrid->GetCellTypesArray()->SetValue(volvtk->getVtkId(), VTK_EMPTY_CELL);
4220     myVolumePool->destroy(volvtk);
4221     return 0;
4222   }
4223   adjustmyCellsCapacity(ID);
4224   myCells[ID] = volvtk;
4225   myInfo.myNbQuadPyramids++;
4226
4227   //  if (!registerElement(ID, volvtk)) {
4228   //    RemoveElement(volvtk, false);
4229   //    volvtk = NULL;
4230   //  }
4231   return volvtk;
4232 }
4233
4234
4235 //=======================================================================
4236 //function : AddVolume
4237 //purpose  :
4238 //=======================================================================
4239 SMDS_MeshVolume* SMDS_Mesh::AddVolume(const SMDS_MeshNode * n1,
4240                                       const SMDS_MeshNode * n2,
4241                                       const SMDS_MeshNode * n3,
4242                                       const SMDS_MeshNode * n4,
4243                                       const SMDS_MeshNode * n5,
4244                                       const SMDS_MeshNode * n6,
4245                                       const SMDS_MeshNode * n12,
4246                                       const SMDS_MeshNode * n23,
4247                                       const SMDS_MeshNode * n31,
4248                                       const SMDS_MeshNode * n45,
4249                                       const SMDS_MeshNode * n56,
4250                                       const SMDS_MeshNode * n64,
4251                                       const SMDS_MeshNode * n14,
4252                                       const SMDS_MeshNode * n25,
4253                                       const SMDS_MeshNode * n36)
4254 {
4255   int ID = myElementIDFactory->GetFreeID();
4256   SMDS_MeshVolume * v =
4257     SMDS_Mesh::AddVolumeWithID(n1, n2, n3, n4, n5, n6, n12, n23, n31,
4258                                n45, n56, n64, n14, n25, n36, ID);
4259   if(v==NULL) myElementIDFactory->ReleaseID(ID);
4260   return v;
4261 }
4262
4263 //=======================================================================
4264 //function : AddVolumeWithID
4265 //purpose  :
4266 //=======================================================================
4267 SMDS_MeshVolume* SMDS_Mesh::AddVolumeWithID(int n1, int n2, int n3,
4268                                             int n4, int n5, int n6,
4269                                             int n12,int n23,int n31,
4270                                             int n45,int n56,int n64,
4271                                             int n14,int n25,int n36, int ID)
4272 {
4273   return SMDS_Mesh::AddVolumeWithID
4274     ((SMDS_MeshNode*) myNodeIDFactory->MeshElement(n1) ,
4275      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n2) ,
4276      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n3) ,
4277      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n4) ,
4278      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n5) ,
4279      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n6) ,
4280      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n12),
4281      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n23),
4282      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n31),
4283      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n45),
4284      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n56),
4285      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n64),
4286      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n14),
4287      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n25),
4288      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n36),
4289      ID);
4290 }
4291
4292 //=======================================================================
4293 //function : AddVolumeWithID
4294 //purpose  : 2d order Pentahedron with 15 nodes
4295 //=======================================================================
4296 SMDS_MeshVolume* SMDS_Mesh::AddVolumeWithID(const SMDS_MeshNode * n1,
4297                                             const SMDS_MeshNode * n2,
4298                                             const SMDS_MeshNode * n3,
4299                                             const SMDS_MeshNode * n4,
4300                                             const SMDS_MeshNode * n5,
4301                                             const SMDS_MeshNode * n6,
4302                                             const SMDS_MeshNode * n12,
4303                                             const SMDS_MeshNode * n23,
4304                                             const SMDS_MeshNode * n31,
4305                                             const SMDS_MeshNode * n45,
4306                                             const SMDS_MeshNode * n56,
4307                                             const SMDS_MeshNode * n64,
4308                                             const SMDS_MeshNode * n14,
4309                                             const SMDS_MeshNode * n25,
4310                                             const SMDS_MeshNode * n36,
4311                                             int ID)
4312 {
4313   if (!n1 || !n2 || !n3 || !n4 || !n5 || !n6 || !n12 || !n23 ||
4314       !n31 || !n45 || !n56 || !n64 || !n14 || !n25 || !n36)
4315     return 0;
4316   if(hasConstructionFaces()) {
4317     // creation quadratic faces - not implemented
4318     return 0;
4319   }
4320   // --- retrieve nodes ID
4321   myNodeIds.resize(15);
4322   myNodeIds[0] = n1->getVtkId();
4323   myNodeIds[1] = n2->getVtkId();
4324   myNodeIds[2] = n3->getVtkId();
4325
4326   myNodeIds[3] = n4->getVtkId();
4327   myNodeIds[4] = n5->getVtkId();
4328   myNodeIds[5] = n6->getVtkId();
4329
4330   myNodeIds[6] = n12->getVtkId();
4331   myNodeIds[7] = n23->getVtkId();
4332   myNodeIds[8] = n31->getVtkId();
4333
4334   myNodeIds[9] = n45->getVtkId();
4335   myNodeIds[10] = n56->getVtkId();
4336   myNodeIds[11] = n64->getVtkId();
4337
4338   myNodeIds[12] = n14->getVtkId();
4339   myNodeIds[13] = n25->getVtkId();
4340   myNodeIds[14] = n36->getVtkId();
4341
4342   SMDS_VtkVolume *volvtk = myVolumePool->getNew();
4343   volvtk->init(myNodeIds, this);
4344   if (!this->registerElement(ID,volvtk))
4345   {
4346     this->myGrid->GetCellTypesArray()->SetValue(volvtk->getVtkId(), VTK_EMPTY_CELL);
4347     myVolumePool->destroy(volvtk);
4348     return 0;
4349   }
4350   adjustmyCellsCapacity(ID);
4351   myCells[ID] = volvtk;
4352   myInfo.myNbQuadPrisms++;
4353
4354   //  if (!registerElement(ID, volvtk)) {
4355   //    RemoveElement(volvtk, false);
4356   //    volvtk = NULL;
4357   //  }
4358   return volvtk;
4359 }
4360
4361
4362 //=======================================================================
4363 //function : AddVolume
4364 //purpose  :
4365 //=======================================================================
4366 SMDS_MeshVolume* SMDS_Mesh::AddVolume(const SMDS_MeshNode * n1,
4367                                       const SMDS_MeshNode * n2,
4368                                       const SMDS_MeshNode * n3,
4369                                       const SMDS_MeshNode * n4,
4370                                       const SMDS_MeshNode * n5,
4371                                       const SMDS_MeshNode * n6,
4372                                       const SMDS_MeshNode * n7,
4373                                       const SMDS_MeshNode * n8,
4374                                       const SMDS_MeshNode * n12,
4375                                       const SMDS_MeshNode * n23,
4376                                       const SMDS_MeshNode * n34,
4377                                       const SMDS_MeshNode * n41,
4378                                       const SMDS_MeshNode * n56,
4379                                       const SMDS_MeshNode * n67,
4380                                       const SMDS_MeshNode * n78,
4381                                       const SMDS_MeshNode * n85,
4382                                       const SMDS_MeshNode * n15,
4383                                       const SMDS_MeshNode * n26,
4384                                       const SMDS_MeshNode * n37,
4385                                       const SMDS_MeshNode * n48)
4386 {
4387   int ID = myElementIDFactory->GetFreeID();
4388   SMDS_MeshVolume * v =
4389     SMDS_Mesh::AddVolumeWithID(n1, n2, n3, n4, n5, n6, n7, n8, n12, n23, n34, n41,
4390                                n56, n67, n78, n85, n15, n26, n37, n48, ID);
4391   if(v==NULL) myElementIDFactory->ReleaseID(ID);
4392   return v;
4393 }
4394
4395 //=======================================================================
4396 //function : AddVolumeWithID
4397 //purpose  :
4398 //=======================================================================
4399 SMDS_MeshVolume* SMDS_Mesh::AddVolumeWithID(int n1, int n2, int n3, int n4,
4400                                             int n5, int n6, int n7, int n8,
4401                                             int n12,int n23,int n34,int n41,
4402                                             int n56,int n67,int n78,int n85,
4403                                             int n15,int n26,int n37,int n48, int ID)
4404 {
4405   return SMDS_Mesh::AddVolumeWithID
4406     ((SMDS_MeshNode*) myNodeIDFactory->MeshElement(n1),
4407      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n2),
4408      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n3),
4409      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n4),
4410      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n5),
4411      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n6),
4412      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n7),
4413      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n8),
4414      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n12),
4415      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n23),
4416      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n34),
4417      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n41),
4418      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n56),
4419      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n67),
4420      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n78),
4421      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n85),
4422      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n15),
4423      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n26),
4424      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n37),
4425      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n48),
4426      ID);
4427 }
4428
4429 //=======================================================================
4430 //function : AddVolumeWithID
4431 //purpose  : 2d order Hexahedrons with 20 nodes
4432 //=======================================================================
4433 SMDS_MeshVolume* SMDS_Mesh::AddVolumeWithID(const SMDS_MeshNode * n1,
4434                                             const SMDS_MeshNode * n2,
4435                                             const SMDS_MeshNode * n3,
4436                                             const SMDS_MeshNode * n4,
4437                                             const SMDS_MeshNode * n5,
4438                                             const SMDS_MeshNode * n6,
4439                                             const SMDS_MeshNode * n7,
4440                                             const SMDS_MeshNode * n8,
4441                                             const SMDS_MeshNode * n12,
4442                                             const SMDS_MeshNode * n23,
4443                                             const SMDS_MeshNode * n34,
4444                                             const SMDS_MeshNode * n41,
4445                                             const SMDS_MeshNode * n56,
4446                                             const SMDS_MeshNode * n67,
4447                                             const SMDS_MeshNode * n78,
4448                                             const SMDS_MeshNode * n85,
4449                                             const SMDS_MeshNode * n15,
4450                                             const SMDS_MeshNode * n26,
4451                                             const SMDS_MeshNode * n37,
4452                                             const SMDS_MeshNode * n48,
4453                                             int ID)
4454 {
4455   if (!n1 || !n2 || !n3 || !n4 || !n5 || !n6 || !n7 || !n8 || !n12 || !n23 ||
4456       !n34 || !n41 || !n56 || !n67 || !n78 || !n85 || !n15 || !n26 || !n37 || !n48)
4457     return 0;
4458   if(hasConstructionFaces()) {
4459     return 0;
4460     // creation quadratic faces - not implemented
4461   }
4462   // --- retrieve nodes ID
4463   myNodeIds.resize(20);
4464   myNodeIds[0] = n1->getVtkId();
4465   myNodeIds[1] = n4->getVtkId();
4466   myNodeIds[2] = n3->getVtkId();
4467   myNodeIds[3] = n2->getVtkId();
4468
4469   myNodeIds[4] = n5->getVtkId();
4470   myNodeIds[5] = n8->getVtkId();
4471   myNodeIds[6] = n7->getVtkId();
4472   myNodeIds[7] = n6->getVtkId();
4473
4474   myNodeIds[8] = n41->getVtkId();
4475   myNodeIds[9] = n34->getVtkId();
4476   myNodeIds[10] = n23->getVtkId();
4477   myNodeIds[11] = n12->getVtkId();
4478
4479   myNodeIds[12] = n85->getVtkId();
4480   myNodeIds[13] = n78->getVtkId();
4481   myNodeIds[14] = n67->getVtkId();
4482   myNodeIds[15] = n56->getVtkId();
4483
4484   myNodeIds[16] = n15->getVtkId();
4485   myNodeIds[17] = n48->getVtkId();
4486   myNodeIds[18] = n37->getVtkId();
4487   myNodeIds[19] = n26->getVtkId();
4488
4489   SMDS_VtkVolume *volvtk = myVolumePool->getNew();
4490   volvtk->init(myNodeIds, this);
4491   if (!this->registerElement(ID,volvtk))
4492   {
4493     this->myGrid->GetCellTypesArray()->SetValue(volvtk->getVtkId(), VTK_EMPTY_CELL);
4494     myVolumePool->destroy(volvtk);
4495     return 0;
4496   }
4497   adjustmyCellsCapacity(ID);
4498   myCells[ID] = volvtk;
4499   myInfo.myNbQuadHexas++;
4500
4501   //  if (!registerElement(ID, volvtk)) {
4502   //    RemoveElement(volvtk, false);
4503   //    volvtk = NULL;
4504   //  }
4505   return volvtk;
4506 }
4507
4508 //=======================================================================
4509 //function : AddVolume
4510 //purpose  :
4511 //=======================================================================
4512 SMDS_MeshVolume* SMDS_Mesh::AddVolume(const SMDS_MeshNode * n1,
4513                                       const SMDS_MeshNode * n2,
4514                                       const SMDS_MeshNode * n3,
4515                                       const SMDS_MeshNode * n4,
4516                                       const SMDS_MeshNode * n5,
4517                                       const SMDS_MeshNode * n6,
4518                                       const SMDS_MeshNode * n7,
4519                                       const SMDS_MeshNode * n8,
4520                                       const SMDS_MeshNode * n12,
4521                                       const SMDS_MeshNode * n23,
4522                                       const SMDS_MeshNode * n34,
4523                                       const SMDS_MeshNode * n41,
4524                                       const SMDS_MeshNode * n56,
4525                                       const SMDS_MeshNode * n67,
4526                                       const SMDS_MeshNode * n78,
4527                                       const SMDS_MeshNode * n85,
4528                                       const SMDS_MeshNode * n15,
4529                                       const SMDS_MeshNode * n26,
4530                                       const SMDS_MeshNode * n37,
4531                                       const SMDS_MeshNode * n48,
4532                                       const SMDS_MeshNode * n1234,
4533                                       const SMDS_MeshNode * n1256,
4534                                       const SMDS_MeshNode * n2367,
4535                                       const SMDS_MeshNode * n3478,
4536                                       const SMDS_MeshNode * n1458,
4537                                       const SMDS_MeshNode * n5678,
4538                                       const SMDS_MeshNode * nCenter)
4539 {
4540   int ID = myElementIDFactory->GetFreeID();
4541   SMDS_MeshVolume * v =
4542     SMDS_Mesh::AddVolumeWithID(n1, n2, n3, n4, n5, n6, n7, n8, n12, n23, n34, n41,
4543                                n56, n67, n78, n85, n15, n26, n37, n48,
4544                                n1234, n1256, n2367, n3478, n1458, n5678, nCenter,
4545                                ID);
4546   if(v==NULL) myElementIDFactory->ReleaseID(ID);
4547   return v;
4548 }
4549
4550 //=======================================================================
4551 //function : AddVolumeWithID
4552 //purpose  :
4553 //=======================================================================
4554 SMDS_MeshVolume* SMDS_Mesh::AddVolumeWithID(int n1, int n2, int n3, int n4,
4555                                             int n5, int n6, int n7, int n8,
4556                                             int n12,int n23,int n34,int n41,
4557                                             int n56,int n67,int n78,int n85,
4558                                             int n15,int n26,int n37,int n48,
4559                                             int n1234,int n1256,int n2367,int n3478,
4560                                             int n1458,int n5678,int nCenter, int ID)
4561 {
4562   return SMDS_Mesh::AddVolumeWithID
4563     ((SMDS_MeshNode*) myNodeIDFactory->MeshElement(n1),
4564      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n2),
4565      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n3),
4566      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n4),
4567      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n5),
4568      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n6),
4569      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n7),
4570      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n8),
4571      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n12),
4572      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n23),
4573      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n34),
4574      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n41),
4575      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n56),
4576      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n67),
4577      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n78),
4578      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n85),
4579      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n15),
4580      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n26),
4581      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n37),
4582      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n48),
4583      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n1234),
4584      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n1256),
4585      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n2367),
4586      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n3478),
4587      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n1458),
4588      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n5678),
4589      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(nCenter),
4590      ID);
4591 }
4592
4593 //=======================================================================
4594 //function : AddVolumeWithID
4595 //purpose  : 2d order Hexahedrons with 20 nodes
4596 //=======================================================================
4597 SMDS_MeshVolume* SMDS_Mesh::AddVolumeWithID(const SMDS_MeshNode * n1,
4598                                             const SMDS_MeshNode * n2,
4599                                             const SMDS_MeshNode * n3,
4600                                             const SMDS_MeshNode * n4,
4601                                             const SMDS_MeshNode * n5,
4602                                             const SMDS_MeshNode * n6,
4603                                             const SMDS_MeshNode * n7,
4604                                             const SMDS_MeshNode * n8,
4605                                             const SMDS_MeshNode * n12,
4606                                             const SMDS_MeshNode * n23,
4607                                             const SMDS_MeshNode * n34,
4608                                             const SMDS_MeshNode * n41,
4609                                             const SMDS_MeshNode * n56,
4610                                             const SMDS_MeshNode * n67,
4611                                             const SMDS_MeshNode * n78,
4612                                             const SMDS_MeshNode * n85,
4613                                             const SMDS_MeshNode * n15,
4614                                             const SMDS_MeshNode * n26,
4615                                             const SMDS_MeshNode * n37,
4616                                             const SMDS_MeshNode * n48,
4617                                             const SMDS_MeshNode * n1234,
4618                                             const SMDS_MeshNode * n1256,
4619                                             const SMDS_MeshNode * n2367,
4620                                             const SMDS_MeshNode * n3478,
4621                                             const SMDS_MeshNode * n1458,
4622                                             const SMDS_MeshNode * n5678,
4623                                             const SMDS_MeshNode * nCenter,
4624                                             int ID)
4625 {
4626   if (!n1 || !n2 || !n3 || !n4 || !n5 || !n6 || !n7 || !n8 || !n12 || !n23 ||
4627       !n34 || !n41 || !n56 || !n67 || !n78 || !n85 || !n15 || !n26 || !n37 || !n48 ||
4628       !n1234 || !n1256 || !n2367 || !n3478 || !n1458 || !n5678 || !nCenter )
4629     return 0;
4630   if(hasConstructionFaces()) {
4631     return 0;
4632     // creation quadratic faces - not implemented
4633   }
4634   // --- retrieve nodes ID
4635   myNodeIds.resize(27);
4636   myNodeIds[0] = n1->getVtkId();
4637   myNodeIds[1] = n4->getVtkId();
4638   myNodeIds[2] = n3->getVtkId();
4639   myNodeIds[3] = n2->getVtkId();
4640
4641   myNodeIds[4] = n5->getVtkId();
4642   myNodeIds[5] = n8->getVtkId();
4643   myNodeIds[6] = n7->getVtkId();
4644   myNodeIds[7] = n6->getVtkId();
4645
4646   myNodeIds[8] = n41->getVtkId();
4647   myNodeIds[9] = n34->getVtkId();
4648   myNodeIds[10] = n23->getVtkId();
4649   myNodeIds[11] = n12->getVtkId();
4650
4651   myNodeIds[12] = n85->getVtkId();
4652   myNodeIds[13] = n78->getVtkId();
4653   myNodeIds[14] = n67->getVtkId();
4654   myNodeIds[15] = n56->getVtkId();
4655
4656   myNodeIds[16] = n15->getVtkId();
4657   myNodeIds[17] = n48->getVtkId();
4658   myNodeIds[18] = n37->getVtkId();
4659   myNodeIds[19] = n26->getVtkId();
4660
4661   myNodeIds[20] = n1256->getVtkId();
4662   myNodeIds[21] = n3478->getVtkId();
4663   myNodeIds[22] = n1458->getVtkId();
4664   myNodeIds[23] = n2367->getVtkId();
4665   myNodeIds[24] = n1234->getVtkId();
4666   myNodeIds[25] = n5678->getVtkId();
4667   myNodeIds[26] = nCenter->getVtkId();
4668
4669   SMDS_VtkVolume *volvtk = myVolumePool->getNew();
4670   volvtk->init(myNodeIds, this);
4671   if (!this->registerElement(ID,volvtk))
4672   {
4673     this->myGrid->GetCellTypesArray()->SetValue(volvtk->getVtkId(), VTK_EMPTY_CELL);
4674     myVolumePool->destroy(volvtk);
4675     return 0;
4676   }
4677   adjustmyCellsCapacity(ID);
4678   myCells[ID] = volvtk;
4679   myInfo.myNbTriQuadHexas++;
4680
4681   return volvtk;
4682 }
4683
4684
4685 void SMDS_Mesh::updateNodeMinMax()
4686 {
4687   myNodeMin = 0;
4688   if (myNodes.size() == 0)
4689   {
4690     myNodeMax=0;
4691     return;
4692   }
4693   while ( !myNodes[myNodeMin] && myNodeMin < (int)myNodes.size() )
4694     myNodeMin++;
4695   myNodeMax=myNodes.size()-1;
4696   while (!myNodes[myNodeMax] && (myNodeMin>=0))
4697     myNodeMin--;
4698 }
4699
4700 void SMDS_Mesh::incrementNodesCapacity(int nbNodes)
4701 {
4702 //  int val = myCellIdSmdsToVtk.size();
4703 //  MESSAGE(" ------------------- resize myCellIdSmdsToVtk " << val << " --> " << val + nbNodes);
4704 //  myCellIdSmdsToVtk.resize(val + nbNodes, -1); // fill new elements with -1
4705   int val = myNodes.size();
4706   MESSAGE(" ------------------- resize myNodes " << val << " --> " << val + nbNodes);
4707   myNodes.resize(val +nbNodes, 0);
4708 }
4709
4710 void SMDS_Mesh::incrementCellsCapacity(int nbCells)
4711 {
4712   int val = myCellIdVtkToSmds.size();
4713   MESSAGE(" ------------------- resize myCellIdVtkToSmds " << val << " --> " << val + nbCells);
4714   myCellIdVtkToSmds.resize(val + nbCells, -1); // fill new elements with -1
4715   val = myCells.size();
4716   MESSAGE(" ------------------- resize myCells " << val << " --> " << val + nbCells);
4717   myNodes.resize(val +nbCells, 0);
4718 }
4719
4720 void SMDS_Mesh::adjustStructure()
4721 {
4722   myGrid->GetPoints()->GetData()->SetNumberOfTuples(myNodeIDFactory->GetMaxID());
4723 }
4724
4725 void SMDS_Mesh::dumpGrid(string ficdump)
4726 {
4727         MESSAGE("SMDS_Mesh::dumpGrid " << ficdump);
4728 //  vtkUnstructuredGridWriter* aWriter = vtkUnstructuredGridWriter::New();
4729 //  aWriter->SetFileName(ficdump.c_str());
4730 //  aWriter->SetInput(myGrid);
4731 //  if(myGrid->GetNumberOfCells())
4732 //  {
4733 //    aWriter->Write();
4734 //  }
4735 //  aWriter->Delete();
4736   ficdump = ficdump + "_connectivity";
4737   ofstream ficcon(ficdump.c_str(), ios::out);
4738   int nbPoints = myGrid->GetNumberOfPoints();
4739   ficcon << "-------------------------------- points " <<  nbPoints << endl;
4740   for (int i=0; i<nbPoints; i++)
4741   {
4742         ficcon << i << " " << *(myGrid->GetPoint(i)) << " " << *(myGrid->GetPoint(i)+1) << " " << " " << *(myGrid->GetPoint(i)+2) << endl;
4743   }
4744   int nbCells = myGrid->GetNumberOfCells();
4745   ficcon << "-------------------------------- cells " <<  nbCells << endl;
4746   for (int i=0; i<nbCells; i++)
4747   {
4748 //      MESSAGE(i << " " << myGrid->GetCell(i));
4749 //      MESSAGE("  " << myGrid->GetCell(i)->GetCellType());
4750         ficcon << i << " - " << myGrid->GetCell(i)->GetCellType() << " -";
4751         int nbptcell = myGrid->GetCell(i)->GetNumberOfPoints();
4752         vtkIdList *listid = myGrid->GetCell(i)->GetPointIds();
4753         for (int j=0; j<nbptcell; j++)
4754         {
4755                 ficcon << " " <<  listid->GetId(j);
4756         }
4757         ficcon << endl;
4758   }
4759   ficcon << "-------------------------------- connectivity " <<  nbPoints << endl;
4760         vtkCellLinks *links = myGrid->GetCellLinks();
4761   for (int i=0; i<nbPoints; i++)
4762   {
4763         int ncells = links->GetNcells(i);
4764         vtkIdType *cells = links->GetCells(i);
4765         ficcon << i << " - " << ncells << " -";
4766         for (int j=0; j<ncells; j++)
4767         {
4768                 ficcon << " " << cells[j];
4769         }
4770         ficcon << endl;
4771   }
4772   ficcon.close();
4773
4774 }
4775
4776 void SMDS_Mesh::compactMesh()
4777 {
4778   MESSAGE("SMDS_Mesh::compactMesh do nothing!");
4779 }
4780
4781 int SMDS_Mesh::fromVtkToSmds(int vtkid)
4782 {
4783   if (vtkid >= 0 && vtkid < (int)myCellIdVtkToSmds.size())
4784     return myCellIdVtkToSmds[vtkid];
4785   throw SALOME_Exception(LOCALIZED ("vtk id out of bounds"));
4786 }
4787
4788 void SMDS_Mesh::updateBoundingBox()
4789 {
4790   xmin = 0; xmax = 0;
4791   ymin = 0; ymax = 0;
4792   zmin = 0; zmax = 0;
4793   vtkPoints *points = myGrid->GetPoints();
4794   int myNodesSize = this->myNodes.size();
4795   for (int i = 0; i < myNodesSize; i++)
4796     {
4797       if (SMDS_MeshNode *n = myNodes[i])
4798         {
4799           double coords[3];
4800           points->GetPoint(n->myVtkID, coords);
4801           if (coords[0] < xmin) xmin = coords[0];
4802           else if (coords[0] > xmax) xmax = coords[0];
4803           if (coords[1] < ymin) ymin = coords[1];
4804           else if (coords[1] > ymax) ymax = coords[1];
4805           if (coords[2] < zmin) zmin = coords[2];
4806           else if (coords[2] > zmax) zmax = coords[2];
4807         }
4808     }
4809 }
4810
4811 double SMDS_Mesh::getMaxDim()
4812 {
4813   double dmax = 1.e-3;
4814   if ((xmax - xmin) > dmax) dmax = xmax -xmin;
4815   if ((ymax - ymin) > dmax) dmax = ymax -ymin;
4816   if ((zmax - zmin) > dmax) dmax = zmax -zmin;
4817   MESSAGE("getMaxDim " << dmax);
4818   return dmax;
4819 }
4820
4821 //! modification that needs compact structure and redraw
4822 void SMDS_Mesh::Modified()
4823 {
4824   if (this->myModified)
4825     {
4826       this->myModifTime++;
4827       MESSAGE("modified");
4828       myModified = false;
4829     }
4830 }
4831
4832 //! get last modification timeStamp
4833 unsigned long SMDS_Mesh::GetMTime() const
4834 {
4835   return this->myModifTime;
4836 }
4837
4838 bool SMDS_Mesh::isCompacted()
4839 {
4840   if (this->myModifTime > this->myCompactTime)
4841     {
4842       MESSAGE(" *** isCompacted " << myCompactTime << " < " << myModifTime);
4843       this->myCompactTime = this->myModifTime;
4844       return false;
4845     }
4846   return true;
4847 }