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