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