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