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