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