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