Salome HOME
Merge from V6_main 11/02/2013
[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   myGrid->Delete();
2660
2661   delete myNodePool;
2662   delete myVolumePool;
2663   delete myFacePool;
2664   delete myEdgePool;
2665   delete myBallPool;
2666 }
2667
2668 //================================================================================
2669 /*!
2670  * \brief Clear all data
2671  */
2672 //================================================================================
2673
2674 void SMDS_Mesh::Clear()
2675 {
2676   MESSAGE("SMDS_Mesh::Clear");
2677   if (myParent!=NULL)
2678     {
2679     SMDS_ElemIteratorPtr eIt = elementsIterator();
2680     while ( eIt->more() )
2681       {
2682         const SMDS_MeshElement *elem = eIt->next();
2683         myElementIDFactory->ReleaseID(elem->GetID(), elem->getVtkId());
2684       }
2685     SMDS_NodeIteratorPtr itn = nodesIterator();
2686     while (itn->more())
2687       {
2688         const SMDS_MeshNode *node = itn->next();
2689         myNodeIDFactory->ReleaseID(node->GetID(), node->getVtkId());
2690       }
2691     }
2692   else
2693     {
2694     myNodeIDFactory->Clear();
2695     myElementIDFactory->Clear();
2696     }
2697
2698   // SMDS_ElemIteratorPtr itv = elementsIterator();
2699   // while (itv->more())
2700   //   {
2701   //     SMDS_MeshElement* elem = (SMDS_MeshElement*)(itv->next());
2702   //     SMDSAbs_ElementType aType = elem->GetType();
2703   //     switch (aType)
2704   //     {
2705   //       case SMDSAbs_0DElement:
2706   //         delete elem;
2707   //         break;
2708   //       case SMDSAbs_Edge:
2709   //          myEdgePool->destroy(static_cast<SMDS_VtkEdge*>(elem));
2710   //         break;
2711   //       case SMDSAbs_Face:
2712   //         myFacePool->destroy(static_cast<SMDS_VtkFace*>(elem));
2713   //         break;
2714   //       case SMDSAbs_Volume:
2715   //         myVolumePool->destroy(static_cast<SMDS_VtkVolume*>(elem));
2716   //         break;
2717   //       case SMDSAbs_Ball:
2718   //         myBallPool->destroy(static_cast<SMDS_BallElement*>(elem));
2719   //         break;
2720   //       default:
2721   //         break;
2722   //     }
2723   //   }
2724   myVolumePool->clear();
2725   myFacePool->clear();
2726   myEdgePool->clear();
2727   myBallPool->clear();
2728
2729   clearVector( myCells );
2730   clearVector( myCellIdVtkToSmds );
2731
2732   SMDS_NodeIteratorPtr itn = nodesIterator();
2733   while (itn->more())
2734     {
2735       SMDS_MeshNode *node = (SMDS_MeshNode*)(itn->next());
2736       node->SetPosition(SMDS_SpacePosition::originSpacePosition());
2737       //myNodePool->destroy(node);
2738     }
2739   myNodePool->clear();
2740   clearVector( myNodes );
2741
2742   list<SMDS_Mesh*>::iterator itc=myChildren.begin();
2743   while(itc!=myChildren.end())
2744     (*itc)->Clear();
2745
2746   myModified = false;
2747   myModifTime++;
2748   xmin = 0; xmax = 0;
2749   ymin = 0; ymax = 0;
2750   zmin = 0; zmax = 0;
2751
2752   myInfo.Clear();
2753
2754   myGrid->Initialize();
2755   myGrid->Allocate();
2756   vtkPoints* points = vtkPoints::New();
2757   // rnv: to fix bug "21125: EDF 1233 SMESH: Degrardation of precision in a test case for quadratic conversion"
2758   // using double type for storing coordinates of nodes instead float.
2759   points->SetDataType(VTK_DOUBLE);
2760   points->SetNumberOfPoints(0 /*SMDS_Mesh::chunkSize*/);
2761   myGrid->SetPoints( points );
2762   points->Delete();
2763   myGrid->BuildLinks();
2764 }
2765
2766 ///////////////////////////////////////////////////////////////////////////////
2767 /// Return true if this mesh create faces with edges.
2768 /// A false returned value mean that faces are created with nodes. A concequence
2769 /// is, iteration on edges (SMDS_Element::edgesIterator) will be unavailable.
2770 ///////////////////////////////////////////////////////////////////////////////
2771 bool SMDS_Mesh::hasConstructionEdges()
2772 {
2773         return myHasConstructionEdges;
2774 }
2775
2776 ///////////////////////////////////////////////////////////////////////////////
2777 /// Return true if this mesh create volumes with faces
2778 /// A false returned value mean that volumes are created with nodes or edges.
2779 /// (see hasConstructionEdges)
2780 /// A concequence is, iteration on faces (SMDS_Element::facesIterator) will be
2781 /// unavailable.
2782 ///////////////////////////////////////////////////////////////////////////////
2783 bool SMDS_Mesh::hasConstructionFaces()
2784 {
2785         return myHasConstructionFaces;
2786 }
2787
2788 ///////////////////////////////////////////////////////////////////////////////
2789 /// Return true if nodes are linked to the finit elements, they are belonging to.
2790 /// Currently, It always return true.
2791 ///////////////////////////////////////////////////////////////////////////////
2792 bool SMDS_Mesh::hasInverseElements()
2793 {
2794         return myHasInverseElements;
2795 }
2796
2797 ///////////////////////////////////////////////////////////////////////////////
2798 /// Make this mesh creating construction edges (see hasConstructionEdges)
2799 /// @param b true to have construction edges, else false.
2800 ///////////////////////////////////////////////////////////////////////////////
2801 void SMDS_Mesh::setConstructionEdges(bool b)
2802 {
2803         myHasConstructionEdges=b;
2804 }
2805
2806 ///////////////////////////////////////////////////////////////////////////////
2807 /// Make this mesh creating construction faces (see hasConstructionFaces)
2808 /// @param b true to have construction faces, else false.
2809 ///////////////////////////////////////////////////////////////////////////////
2810 void SMDS_Mesh::setConstructionFaces(bool b)
2811 {
2812          myHasConstructionFaces=b;
2813 }
2814
2815 ///////////////////////////////////////////////////////////////////////////////
2816 /// Make this mesh creating link from nodes to elements (see hasInverseElements)
2817 /// @param b true to link nodes to elements, else false.
2818 ///////////////////////////////////////////////////////////////////////////////
2819 void SMDS_Mesh::setInverseElements(bool b)
2820 {
2821   if(!b) MESSAGE("Error : inverseElement=false not implemented");
2822   myHasInverseElements=b;
2823 }
2824
2825 namespace {
2826
2827   //================================================================================
2828   /*!
2829    * \brief Iterator on elements in id increasing order
2830    */
2831   //================================================================================
2832
2833   template <typename ELEM=const SMDS_MeshElement*>
2834   class IdSortedIterator : public SMDS_Iterator<ELEM>
2835   {
2836     SMDS_MeshElementIDFactory&       myIDFact;
2837     int                              myID, myMaxID, myNbFound, myTotalNb;
2838     SMDSAbs_ElementType              myType;
2839     ELEM                             myElem;
2840
2841   public:
2842     IdSortedIterator(const SMDS_MeshElementIDFactory& fact,
2843                      const SMDSAbs_ElementType        type, // SMDSAbs_All NOT allowed!!! 
2844                      const int                        totalNb)
2845       :myIDFact( fact ),
2846        myID(1), myMaxID( myIDFact.GetMaxID() ),myNbFound(0), myTotalNb( totalNb ),
2847        myType( type ),
2848        myElem(0)
2849     {
2850       next();
2851     }
2852     bool more()
2853     {
2854       return myElem;
2855     }
2856     ELEM next()
2857     {
2858       ELEM current = myElem;
2859
2860       for ( myElem = 0;  !myElem && myNbFound < myTotalNb && myID <= myMaxID; ++myID )
2861         if ((myElem = (ELEM) myIDFact.MeshElement( myID ))
2862             && myElem->GetType() != myType )
2863           myElem = 0;
2864
2865       myNbFound += bool(myElem);
2866
2867       return current;
2868     }
2869   };
2870
2871   //================================================================================
2872   /*!
2873    * \brief Iterator on vector of elements, possibly being resized while iteration
2874    */
2875   //================================================================================
2876
2877   template<typename RETURN_VALUE,
2878            typename VECTOR_VALUE=SMDS_MeshCell*,
2879            typename VALUE_FILTER=SMDS::NonNullFilter<VECTOR_VALUE> >
2880   class ElemVecIterator: public SMDS_Iterator<RETURN_VALUE>
2881   {
2882     const std::vector<VECTOR_VALUE>& _vector;
2883     size_t                           _index;
2884     bool                             _more;
2885     VALUE_FILTER                     _filter;
2886   public:
2887     ElemVecIterator(const std::vector<VECTOR_VALUE>& vec,
2888                     const VALUE_FILTER&              filter=VALUE_FILTER() )
2889       :_vector( vec ), _index(0), _more( !vec.empty() ), _filter( filter )
2890     {
2891       if ( _more && !_filter( _vector[ _index ]))
2892         next();
2893     }
2894     virtual bool more()
2895     {
2896       return _more;
2897     }
2898     virtual RETURN_VALUE next()
2899     {
2900       if ( !_more ) return NULL;
2901       VECTOR_VALUE current = _vector[ _index ];
2902       _more = 0;
2903       while ( !_more && ++_index < _vector.size() )
2904         _more = _filter( _vector[ _index ]);
2905       return (RETURN_VALUE) current;
2906     }
2907   };
2908 }
2909
2910 ///////////////////////////////////////////////////////////////////////////////
2911 /// Return an iterator on nodes of the current mesh factory
2912 ///////////////////////////////////////////////////////////////////////////////
2913
2914 SMDS_NodeIteratorPtr SMDS_Mesh::nodesIterator(bool idInceasingOrder) const
2915 {
2916   // naturally always sorted by ID
2917   typedef ElemVecIterator<const SMDS_MeshNode*, SMDS_MeshNode*> TIterator;
2918   return SMDS_NodeIteratorPtr( new TIterator(myNodes));
2919 }
2920
2921 SMDS_ElemIteratorPtr SMDS_Mesh::elementGeomIterator(SMDSAbs_GeometryType type) const
2922 {
2923   // naturally always sorted by ID
2924   typedef ElemVecIterator
2925     < const SMDS_MeshElement*, SMDS_MeshCell*, SMDS_MeshElement::GeomFilter > TIterator;
2926   return SMDS_ElemIteratorPtr
2927     (new TIterator(myCells, SMDS_MeshElement::GeomFilter( type )));
2928 }
2929
2930 SMDS_ElemIteratorPtr SMDS_Mesh::elementEntityIterator(SMDSAbs_EntityType type) const
2931 {
2932   // naturally always sorted by ID
2933   typedef ElemVecIterator
2934     < const SMDS_MeshElement*, SMDS_MeshCell*, SMDS_MeshElement::EntityFilter > TIterator;
2935   return SMDS_ElemIteratorPtr
2936     (new TIterator(myCells, SMDS_MeshElement::EntityFilter( type )));
2937 }
2938
2939 ///////////////////////////////////////////////////////////////////////////////
2940 /// Return an iterator on elements of the current mesh factory
2941 ///////////////////////////////////////////////////////////////////////////////
2942 SMDS_ElemIteratorPtr SMDS_Mesh::elementsIterator(SMDSAbs_ElementType type) const
2943 {
2944   // naturally always sorted by ID
2945   switch ( type ) {
2946
2947   case SMDSAbs_All:
2948     return SMDS_ElemIteratorPtr (new ElemVecIterator<const SMDS_MeshElement*>(myCells));
2949
2950   case SMDSAbs_Node:
2951     return SMDS_ElemIteratorPtr
2952       ( new ElemVecIterator<const SMDS_MeshElement*, SMDS_MeshNode*>( myNodes ));
2953
2954   default:
2955     typedef ElemVecIterator
2956       < const SMDS_MeshElement*, SMDS_MeshCell*, SMDS_MeshElement::TypeFilter > TIterator;
2957     return SMDS_ElemIteratorPtr (new TIterator(myCells, SMDS_MeshElement::TypeFilter( type )));
2958   }
2959   return SMDS_ElemIteratorPtr();
2960 }
2961
2962 ///////////////////////////////////////////////////////////////////////////////
2963 ///Return an iterator on edges of the current mesh.
2964 ///////////////////////////////////////////////////////////////////////////////
2965
2966 SMDS_EdgeIteratorPtr SMDS_Mesh::edgesIterator(bool idInceasingOrder) const
2967 {
2968   // naturally always sorted by ID
2969   typedef ElemVecIterator
2970     < const SMDS_MeshEdge*, SMDS_MeshCell*, SMDS_MeshElement::TypeFilter > TIterator;
2971   return SMDS_EdgeIteratorPtr
2972     (new TIterator(myCells, SMDS_MeshElement::TypeFilter( SMDSAbs_Edge )));
2973 }
2974
2975 ///////////////////////////////////////////////////////////////////////////////
2976 ///Return an iterator on faces of the current mesh.
2977 ///////////////////////////////////////////////////////////////////////////////
2978
2979 SMDS_FaceIteratorPtr SMDS_Mesh::facesIterator(bool idInceasingOrder) const
2980 {
2981   // naturally always sorted by ID
2982   typedef ElemVecIterator
2983     < const SMDS_MeshFace*, SMDS_MeshCell*, SMDS_MeshElement::TypeFilter > TIterator;
2984   return SMDS_FaceIteratorPtr
2985     (new TIterator(myCells, SMDS_MeshElement::TypeFilter( SMDSAbs_Face )));
2986 }
2987
2988 ///////////////////////////////////////////////////////////////////////////////
2989 ///Return an iterator on volumes of the current mesh.
2990 ///////////////////////////////////////////////////////////////////////////////
2991
2992 SMDS_VolumeIteratorPtr SMDS_Mesh::volumesIterator(bool idInceasingOrder) const
2993 {
2994   // naturally always sorted by ID
2995   typedef ElemVecIterator
2996     < const SMDS_MeshVolume*, SMDS_MeshCell*, SMDS_MeshElement::TypeFilter > TIterator;
2997   return SMDS_VolumeIteratorPtr
2998     (new TIterator(myCells, SMDS_MeshElement::TypeFilter( SMDSAbs_Volume )));
2999 }
3000
3001 ///////////////////////////////////////////////////////////////////////////////
3002 /// Do intersection of sets (more than 2)
3003 ///////////////////////////////////////////////////////////////////////////////
3004 static set<const SMDS_MeshElement*> * intersectionOfSets(
3005         set<const SMDS_MeshElement*> vs[], int numberOfSets)
3006 {
3007         set<const SMDS_MeshElement*>* rsetA=new set<const SMDS_MeshElement*>(vs[0]);
3008         set<const SMDS_MeshElement*>* rsetB;
3009
3010         for(int i=0; i<numberOfSets-1; i++)
3011         {
3012                 rsetB=new set<const SMDS_MeshElement*>();
3013                 set_intersection(
3014                         rsetA->begin(), rsetA->end(),
3015                         vs[i+1].begin(), vs[i+1].end(),
3016                         inserter(*rsetB, rsetB->begin()));
3017                 delete rsetA;
3018                 rsetA=rsetB;
3019         }
3020         return rsetA;
3021 }
3022
3023 ///////////////////////////////////////////////////////////////////////////////
3024 /// Return the list of finite elements owning the given element: elements
3025 /// containing all the nodes of the given element, for instance faces and
3026 /// volumes containing a given edge.
3027 ///////////////////////////////////////////////////////////////////////////////
3028 static set<const SMDS_MeshElement*> * getFinitElements(const SMDS_MeshElement * element)
3029 {
3030         int numberOfSets=element->NbNodes();
3031         set<const SMDS_MeshElement*> *initSet = new set<const SMDS_MeshElement*>[numberOfSets];
3032
3033         SMDS_ElemIteratorPtr itNodes=element->nodesIterator();
3034
3035         int i=0;
3036         while(itNodes->more())
3037         {
3038           const SMDS_MeshElement* node = itNodes->next();
3039           MYASSERT(node);
3040                 const SMDS_MeshNode * n=static_cast<const SMDS_MeshNode*>(node);
3041                 SMDS_ElemIteratorPtr itFe = n->GetInverseElementIterator();
3042
3043                 //initSet[i]=set<const SMDS_MeshElement*>();
3044                 while(itFe->more())
3045                 {
3046                   const SMDS_MeshElement* elem = itFe->next();
3047                   MYASSERT(elem);
3048                   initSet[i].insert(elem);
3049
3050                 }
3051
3052                 i++;
3053         }
3054         set<const SMDS_MeshElement*> *retSet=intersectionOfSets(initSet, numberOfSets);
3055 //         MESSAGE("nb elems " << i << " intersection " << retSet->size());
3056         delete [] initSet;
3057         return retSet;
3058 }
3059
3060 ///////////////////////////////////////////////////////////////////////////////
3061 /// Return the list of nodes used only by the given elements
3062 ///////////////////////////////////////////////////////////////////////////////
3063 static set<const SMDS_MeshElement*> * getExclusiveNodes(
3064         set<const SMDS_MeshElement*>& elements)
3065 {
3066         set<const SMDS_MeshElement*> * toReturn=new set<const SMDS_MeshElement*>();
3067         set<const SMDS_MeshElement*>::iterator itElements=elements.begin();
3068
3069         while(itElements!=elements.end())
3070         {
3071                 SMDS_ElemIteratorPtr itNodes = (*itElements)->nodesIterator();
3072                 itElements++;
3073
3074                 while(itNodes->more())
3075                 {
3076                         const SMDS_MeshNode * n=static_cast<const SMDS_MeshNode*>(itNodes->next());
3077                         SMDS_ElemIteratorPtr itFe = n->GetInverseElementIterator();
3078                         set<const SMDS_MeshElement*> s;
3079                         while(itFe->more())
3080                           s.insert(itFe->next());
3081                         if(s==elements) toReturn->insert(n);
3082                 }
3083         }
3084         return toReturn;
3085 }
3086
3087 ///////////////////////////////////////////////////////////////////////////////
3088 ///Find the children of an element that are made of given nodes
3089 ///@param setOfChildren The set in which matching children will be inserted
3090 ///@param element The element were to search matching children
3091 ///@param nodes The nodes that the children must have to be selected
3092 ///////////////////////////////////////////////////////////////////////////////
3093 void SMDS_Mesh::addChildrenWithNodes(set<const SMDS_MeshElement*>& setOfChildren,
3094                                      const SMDS_MeshElement *      element,
3095                                      set<const SMDS_MeshElement*>& nodes)
3096 {
3097   switch(element->GetType())
3098     {
3099     case SMDSAbs_Node:
3100       MESSAGE("Internal Error: This should not happen");
3101       break;
3102     case SMDSAbs_0DElement:
3103       {
3104       }
3105       break;
3106     case SMDSAbs_Edge:
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         } break;
3119     case SMDSAbs_Face:
3120         {
3121                 SMDS_ElemIteratorPtr itn=element->nodesIterator();
3122                 while(itn->more())
3123                 {
3124                         const SMDS_MeshElement * e=itn->next();
3125                         if(nodes.find(e)!=nodes.end())
3126                         {
3127                           setOfChildren.insert(element);
3128                           break;
3129                         }
3130                 }
3131                 if(hasConstructionEdges())
3132                 {
3133                         SMDS_ElemIteratorPtr ite=element->edgesIterator();
3134                         while(ite->more())
3135                                 addChildrenWithNodes(setOfChildren, ite->next(), nodes);
3136                 }
3137         } break;
3138     case SMDSAbs_Volume:
3139         {
3140                 if(hasConstructionFaces())
3141                 {
3142                         SMDS_ElemIteratorPtr ite=element->facesIterator();
3143                         while(ite->more())
3144                                 addChildrenWithNodes(setOfChildren, ite->next(), nodes);
3145                 }
3146                 else if(hasConstructionEdges())
3147                 {
3148                         SMDS_ElemIteratorPtr ite=element->edgesIterator();
3149                         while(ite->more())
3150                                 addChildrenWithNodes(setOfChildren, ite->next(), nodes);
3151                 }
3152         }
3153     }
3154 }
3155
3156 ///////////////////////////////////////////////////////////////////////////////
3157 ///@param elem The element to delete
3158 ///@param removenodes if true remaining nodes will be removed
3159 ///////////////////////////////////////////////////////////////////////////////
3160 void SMDS_Mesh::RemoveElement(const SMDS_MeshElement * elem,
3161                               const bool removenodes)
3162 {
3163   list<const SMDS_MeshElement *> removedElems;
3164   list<const SMDS_MeshElement *> removedNodes;
3165   RemoveElement( elem, removedElems, removedNodes, removenodes );
3166 }
3167
3168 ///////////////////////////////////////////////////////////////////////////////
3169 ///@param elem The element to delete
3170 ///@param removedElems to be filled with all removed elements
3171 ///@param removedNodes to be filled with all removed nodes
3172 ///@param removenodes if true remaining nodes will be removed
3173 ///////////////////////////////////////////////////////////////////////////////
3174 void SMDS_Mesh::RemoveElement(const SMDS_MeshElement *        elem,
3175                               list<const SMDS_MeshElement *>& removedElems,
3176                               list<const SMDS_MeshElement *>& removedNodes,
3177                               bool                            removenodes)
3178 {
3179   //MESSAGE("SMDS_Mesh::RemoveElement " << elem->getVtkId() << " " << removenodes);
3180   // get finite elements built on elem
3181   set<const SMDS_MeshElement*> * s1;
3182   if (    (elem->GetType() == SMDSAbs_0DElement)
3183       || ((elem->GetType() == SMDSAbs_Edge) && !hasConstructionEdges())
3184       || ((elem->GetType() == SMDSAbs_Face) && !hasConstructionFaces())
3185       ||  (elem->GetType() == SMDSAbs_Volume) )
3186     {
3187       s1 = new set<const SMDS_MeshElement*> ();
3188       s1->insert(elem);
3189     }
3190   else
3191     s1 = getFinitElements(elem);
3192
3193   // get exclusive nodes (which would become free afterwards)
3194   set<const SMDS_MeshElement*> * s2;
3195   if (elem->GetType() == SMDSAbs_Node) // a node is removed
3196     {
3197       // do not remove nodes except elem
3198       s2 = new set<const SMDS_MeshElement*> ();
3199       s2->insert(elem);
3200       removenodes = true;
3201     }
3202   else
3203     s2 = getExclusiveNodes(*s1);
3204
3205   // form the set of finite and construction elements to remove
3206   set<const SMDS_MeshElement*> s3;
3207   set<const SMDS_MeshElement*>::iterator it = s1->begin();
3208   while (it != s1->end())
3209     {
3210       addChildrenWithNodes(s3, *it, *s2);
3211       s3.insert(*it);
3212       it++;
3213     }
3214   if (elem->GetType() != SMDSAbs_Node)
3215     s3.insert(elem);
3216
3217   // remove finite and construction elements
3218   it = s3.begin();
3219   while (it != s3.end())
3220     {
3221       // Remove element from <InverseElements> of its nodes
3222       SMDS_ElemIteratorPtr itn = (*it)->nodesIterator();
3223       while (itn->more())
3224         {
3225           SMDS_MeshNode * n = static_cast<SMDS_MeshNode *> (const_cast<SMDS_MeshElement *> (itn->next()));
3226           n->RemoveInverseElement((*it));
3227         }
3228       int IdToRemove = (*it)->GetID();
3229       int vtkid = (*it)->getVtkId();
3230       //MESSAGE("elem Id to remove " << IdToRemove << " vtkid " << vtkid <<
3231       //        " vtktype " << (*it)->GetVtkType() << " type " << (*it)->GetType());
3232       switch ((*it)->GetType())
3233       {
3234         case SMDSAbs_Node:
3235           MYASSERT("Internal Error: This should not happen")
3236           ;
3237           break;
3238         case SMDSAbs_0DElement:
3239           if (IdToRemove >= 0)
3240             {
3241               myCells[IdToRemove] = 0; // -PR- ici ou dans myElementIDFactory->ReleaseID ?
3242               myInfo.remove(*it);
3243             }
3244           removedElems.push_back((*it));
3245           myElementIDFactory->ReleaseID(IdToRemove, vtkid);
3246           delete (*it);
3247           break;
3248         case SMDSAbs_Edge:
3249           if (IdToRemove >= 0)
3250             {
3251               myCells[IdToRemove] = 0;
3252               myInfo.RemoveEdge(*it);
3253             }
3254           removedElems.push_back((*it));
3255           myElementIDFactory->ReleaseID(IdToRemove, vtkid);
3256           if (const SMDS_VtkEdge* vtkElem = dynamic_cast<const SMDS_VtkEdge*>(*it))
3257             myEdgePool->destroy((SMDS_VtkEdge*) vtkElem);
3258           else
3259             delete (*it);
3260           break;
3261         case SMDSAbs_Face:
3262           if (IdToRemove >= 0)
3263             {
3264               myCells[IdToRemove] = 0;
3265               myInfo.RemoveFace(*it);
3266             }
3267           removedElems.push_back((*it));
3268           myElementIDFactory->ReleaseID(IdToRemove, vtkid);
3269           if (const SMDS_VtkFace* vtkElem = dynamic_cast<const SMDS_VtkFace*>(*it))
3270             myFacePool->destroy((SMDS_VtkFace*) vtkElem);
3271           else
3272             delete (*it);
3273           break;
3274         case SMDSAbs_Volume:
3275           if (IdToRemove >= 0)
3276             {
3277               myCells[IdToRemove] = 0;
3278               myInfo.RemoveVolume(*it);
3279             }
3280           removedElems.push_back((*it));
3281           myElementIDFactory->ReleaseID(IdToRemove, vtkid);
3282           if (const SMDS_VtkVolume* vtkElem = dynamic_cast<const SMDS_VtkVolume*>(*it))
3283             myVolumePool->destroy((SMDS_VtkVolume*) vtkElem);
3284           else
3285             delete (*it);
3286           break;
3287         case SMDSAbs_Ball:
3288           if (IdToRemove >= 0)
3289             {
3290               myCells[IdToRemove] = 0;
3291               myInfo.remove(*it);
3292             }
3293           removedElems.push_back((*it));
3294           myElementIDFactory->ReleaseID(IdToRemove, vtkid);
3295           if (const SMDS_BallElement* vtkElem = dynamic_cast<const SMDS_BallElement*>(*it))
3296             myBallPool->destroy(const_cast<SMDS_BallElement*>( vtkElem ));
3297           else
3298             delete (*it);
3299           break;
3300       }
3301       if (vtkid >= 0)
3302         {
3303           //MESSAGE("VTK_EMPTY_CELL in " << vtkid);
3304           this->myGrid->GetCellTypesArray()->SetValue(vtkid, VTK_EMPTY_CELL);
3305         }
3306       it++;
3307     }
3308
3309   // remove exclusive (free) nodes
3310   if (removenodes)
3311     {
3312       it = s2->begin();
3313       while (it != s2->end())
3314         {
3315           int IdToRemove = (*it)->GetID();
3316           //MESSAGE( "SMDS: RM node " << IdToRemove);
3317           if (IdToRemove >= 0)
3318             {
3319               myNodes[IdToRemove] = 0;
3320               myInfo.myNbNodes--;
3321             }
3322           myNodeIDFactory->ReleaseID((*it)->GetID(), (*it)->getVtkId());
3323           removedNodes.push_back((*it));
3324           if (const SMDS_MeshNode* vtkElem = dynamic_cast<const SMDS_MeshNode*>(*it))
3325           {
3326             ((SMDS_MeshNode*)vtkElem)->SetPosition(SMDS_SpacePosition::originSpacePosition());
3327             myNodePool->destroy((SMDS_MeshNode*) vtkElem);
3328           }
3329           else
3330             delete (*it);
3331           it++;
3332         }
3333     }
3334
3335   delete s2;
3336   delete s1;
3337 }
3338
3339
3340 ///////////////////////////////////////////////////////////////////////////////
3341 ///@param elem The element to delete
3342 ///////////////////////////////////////////////////////////////////////////////
3343 void SMDS_Mesh::RemoveFreeElement(const SMDS_MeshElement * elem)
3344 {
3345   int elemId = elem->GetID();
3346   int vtkId = elem->getVtkId();
3347   //MESSAGE("RemoveFreeElement " << elemId);
3348   SMDSAbs_ElementType aType = elem->GetType();
3349   SMDS_MeshElement* todest = (SMDS_MeshElement*)(elem);
3350   if (aType == SMDSAbs_Node) {
3351     //MESSAGE("Remove free node " << elemId);
3352     // only free node can be removed by this method
3353     const SMDS_MeshNode* n = static_cast<SMDS_MeshNode*>(todest);
3354     SMDS_ElemIteratorPtr itFe = n->GetInverseElementIterator();
3355     if (!itFe->more()) { // free node
3356       myNodes[elemId] = 0;
3357       myInfo.myNbNodes--;
3358       ((SMDS_MeshNode*) n)->SetPosition(SMDS_SpacePosition::originSpacePosition());
3359       myNodePool->destroy(static_cast<SMDS_MeshNode*>(todest));
3360       myNodeIDFactory->ReleaseID(elemId, vtkId);
3361     }
3362   } else {
3363     if (hasConstructionEdges() || hasConstructionFaces())
3364       // this methods is only for meshes without descendants
3365       return;
3366
3367     //MESSAGE("Remove free element " << elemId);
3368     // Remove element from <InverseElements> of its nodes
3369     SMDS_ElemIteratorPtr itn = elem->nodesIterator();
3370     while (itn->more()) {
3371       SMDS_MeshNode * n = static_cast<SMDS_MeshNode *>
3372         (const_cast<SMDS_MeshElement *>(itn->next()));
3373       n->RemoveInverseElement(elem);
3374     }
3375
3376     // in meshes without descendants elements are always free
3377      switch (aType) {
3378     case SMDSAbs_0DElement:
3379       myCells[elemId] = 0;
3380       myInfo.remove(elem);
3381       delete elem;
3382       break;
3383     case SMDSAbs_Edge:
3384       myCells[elemId] = 0;
3385       myInfo.RemoveEdge(elem);
3386       myEdgePool->destroy(static_cast<SMDS_VtkEdge*>(todest));
3387       break;
3388     case SMDSAbs_Face:
3389       myCells[elemId] = 0;
3390       myInfo.RemoveFace(elem);
3391       myFacePool->destroy(static_cast<SMDS_VtkFace*>(todest));
3392       break;
3393     case SMDSAbs_Volume:
3394       myCells[elemId] = 0;
3395       myInfo.RemoveVolume(elem);
3396       myVolumePool->destroy(static_cast<SMDS_VtkVolume*>(todest));
3397       break;
3398     case SMDSAbs_Ball:
3399       myCells[elemId] = 0;
3400       myInfo.remove(elem);
3401       myBallPool->destroy(static_cast<SMDS_BallElement*>(todest));
3402       break;
3403     default:
3404       break;
3405     }
3406     myElementIDFactory->ReleaseID(elemId, vtkId);
3407
3408     this->myGrid->GetCellTypesArray()->SetValue(vtkId, VTK_EMPTY_CELL);
3409     // --- to do: keep vtkid in a list of reusable cells
3410   }
3411 }
3412
3413 /*!
3414  * Checks if the element is present in mesh.
3415  * Useful to determine dead pointers.
3416  */
3417 bool SMDS_Mesh::Contains (const SMDS_MeshElement* elem) const
3418 {
3419   // we should not imply on validity of *elem, so iterate on containers
3420   // of all types in the hope of finding <elem> somewhere there
3421   SMDS_NodeIteratorPtr itn = nodesIterator();
3422   while (itn->more())
3423     if (elem == itn->next())
3424       return true;
3425   SMDS_ElemIteratorPtr ite = elementsIterator();
3426   while (ite->more())
3427     if (elem == ite->next())
3428       return true;
3429   return false;
3430 }
3431
3432 //=======================================================================
3433 //function : MaxNodeID
3434 //purpose  :
3435 //=======================================================================
3436
3437 int SMDS_Mesh::MaxNodeID() const
3438 {
3439   return myNodeMax;
3440 }
3441
3442 //=======================================================================
3443 //function : MinNodeID
3444 //purpose  :
3445 //=======================================================================
3446
3447 int SMDS_Mesh::MinNodeID() const
3448 {
3449   return myNodeMin;
3450 }
3451
3452 //=======================================================================
3453 //function : MaxElementID
3454 //purpose  :
3455 //=======================================================================
3456
3457 int SMDS_Mesh::MaxElementID() const
3458 {
3459   return myElementIDFactory->GetMaxID();
3460 }
3461
3462 //=======================================================================
3463 //function : MinElementID
3464 //purpose  :
3465 //=======================================================================
3466
3467 int SMDS_Mesh::MinElementID() const
3468 {
3469   return myElementIDFactory->GetMinID();
3470 }
3471
3472 //=======================================================================
3473 //function : Renumber
3474 //purpose  : Renumber all nodes or elements.
3475 //=======================================================================
3476
3477 void SMDS_Mesh::Renumber (const bool isNodes, const int  startID, const int  deltaID)
3478 {
3479     MESSAGE("Renumber");
3480   if ( deltaID == 0 )
3481     return;
3482
3483   SMDS_MeshNodeIDFactory * idFactory =
3484     isNodes ? myNodeIDFactory : myElementIDFactory;
3485
3486   // get existing elements in the order of ID increasing
3487   map<int,SMDS_MeshElement*> elemMap;
3488   SMDS_ElemIteratorPtr idElemIt = idFactory->elementsIterator();
3489   while ( idElemIt->more() ) {
3490     SMDS_MeshElement* elem = const_cast<SMDS_MeshElement*>(idElemIt->next());
3491     int id = elem->GetID();
3492     elemMap.insert(map<int,SMDS_MeshElement*>::value_type(id, elem));
3493   }
3494   // release their ids
3495   map<int,SMDS_MeshElement*>::iterator elemIt = elemMap.begin();
3496   idFactory->Clear();
3497 //   for ( ; elemIt != elemMap.end(); elemIt++ )
3498 //   {
3499 //     int id = (*elemIt).first;
3500 //     idFactory->ReleaseID( id );
3501 //   }
3502   // set new IDs
3503   int ID = startID;
3504   elemIt = elemMap.begin();
3505   for ( ; elemIt != elemMap.end(); elemIt++ )
3506   {
3507     idFactory->BindID( ID, (*elemIt).second );
3508     ID += deltaID;
3509   }
3510 }
3511
3512 //=======================================================================
3513 //function : GetElementType
3514 //purpose  : Return type of element or node with id
3515 //=======================================================================
3516
3517 SMDSAbs_ElementType SMDS_Mesh::GetElementType( const int id, const bool iselem ) const
3518 {
3519   SMDS_MeshElement* elem = 0;
3520   if( iselem )
3521     elem = myElementIDFactory->MeshElement( id );
3522   else
3523     elem = myNodeIDFactory->MeshElement( id );
3524
3525   if( !elem )
3526   {
3527     //throw SALOME_Exception(LOCALIZED ("this element isn't exist"));
3528     return SMDSAbs_All;
3529   }
3530   else
3531     return elem->GetType();
3532 }
3533
3534
3535
3536 //********************************************************************
3537 //********************************************************************
3538 //********                                                   *********
3539 //*****       Methods for addition of quadratic elements        ******
3540 //********                                                   *********
3541 //********************************************************************
3542 //********************************************************************
3543
3544 //=======================================================================
3545 //function : AddEdgeWithID
3546 //purpose  :
3547 //=======================================================================
3548 SMDS_MeshEdge* SMDS_Mesh::AddEdgeWithID(int n1, int n2, int n12, int ID)
3549 {
3550   return SMDS_Mesh::AddEdgeWithID
3551     ((SMDS_MeshNode*) myNodeIDFactory->MeshElement(n1),
3552      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n2),
3553      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n12),
3554      ID);
3555 }
3556
3557 //=======================================================================
3558 //function : AddEdge
3559 //purpose  :
3560 //=======================================================================
3561 SMDS_MeshEdge* SMDS_Mesh::AddEdge(const SMDS_MeshNode* n1,
3562                                   const SMDS_MeshNode* n2,
3563                                   const SMDS_MeshNode* n12)
3564 {
3565   return SMDS_Mesh::AddEdgeWithID(n1, n2, n12, myElementIDFactory->GetFreeID());
3566 }
3567
3568 //=======================================================================
3569 //function : AddEdgeWithID
3570 //purpose  :
3571 //=======================================================================
3572 SMDS_MeshEdge* SMDS_Mesh::AddEdgeWithID(const SMDS_MeshNode * n1,
3573                                         const SMDS_MeshNode * n2,
3574                                         const SMDS_MeshNode * n12,
3575                                         int ID)
3576 {
3577   if ( !n1 || !n2 || !n12 ) return 0;
3578
3579   // --- retrieve nodes ID
3580   vector<vtkIdType> nodeIds;
3581   nodeIds.clear();
3582   nodeIds.push_back(n1->getVtkId());
3583   nodeIds.push_back(n2->getVtkId());
3584   nodeIds.push_back(n12->getVtkId());
3585
3586   SMDS_MeshEdge * edge = 0;
3587   SMDS_VtkEdge *edgevtk = myEdgePool->getNew();
3588   edgevtk->init(nodeIds, this);
3589   if (!this->registerElement(ID,edgevtk))
3590     {
3591       this->myGrid->GetCellTypesArray()->SetValue(edgevtk->getVtkId(), VTK_EMPTY_CELL);
3592       myEdgePool->destroy(edgevtk);
3593       return 0;
3594     }
3595   edge = edgevtk;
3596   adjustmyCellsCapacity(ID);
3597   myCells[ID] = edge;
3598   myInfo.myNbQuadEdges++;
3599
3600 //  if (!registerElement(ID, edge)) {
3601 //        RemoveElement(edge, false);
3602 //        edge = NULL;
3603 //  }
3604   return edge;
3605
3606 }
3607
3608
3609 //=======================================================================
3610 //function : AddFace
3611 //purpose  :
3612 //=======================================================================
3613 SMDS_MeshFace* SMDS_Mesh::AddFace(const SMDS_MeshNode * n1,
3614                                   const SMDS_MeshNode * n2,
3615                                   const SMDS_MeshNode * n3,
3616                                   const SMDS_MeshNode * n12,
3617                                   const SMDS_MeshNode * n23,
3618                                   const SMDS_MeshNode * n31)
3619 {
3620   return SMDS_Mesh::AddFaceWithID(n1,n2,n3,n12,n23,n31,
3621                                   myElementIDFactory->GetFreeID());
3622 }
3623
3624 //=======================================================================
3625 //function : AddFaceWithID
3626 //purpose  :
3627 //=======================================================================
3628 SMDS_MeshFace* SMDS_Mesh::AddFaceWithID(int n1, int n2, int n3,
3629                                         int n12,int n23,int n31, int ID)
3630 {
3631   return SMDS_Mesh::AddFaceWithID
3632     ((SMDS_MeshNode *)myNodeIDFactory->MeshElement(n1) ,
3633      (SMDS_MeshNode *)myNodeIDFactory->MeshElement(n2) ,
3634      (SMDS_MeshNode *)myNodeIDFactory->MeshElement(n3) ,
3635      (SMDS_MeshNode *)myNodeIDFactory->MeshElement(n12),
3636      (SMDS_MeshNode *)myNodeIDFactory->MeshElement(n23),
3637      (SMDS_MeshNode *)myNodeIDFactory->MeshElement(n31),
3638      ID);
3639 }
3640
3641 //=======================================================================
3642 //function : AddFaceWithID
3643 //purpose  :
3644 //=======================================================================
3645 SMDS_MeshFace* SMDS_Mesh::AddFaceWithID(const SMDS_MeshNode * n1,
3646                                         const SMDS_MeshNode * n2,
3647                                         const SMDS_MeshNode * n3,
3648                                         const SMDS_MeshNode * n12,
3649                                         const SMDS_MeshNode * n23,
3650                                         const SMDS_MeshNode * n31,
3651                                         int ID)
3652 {
3653   if ( !n1 || !n2 || !n3 || !n12 || !n23 || !n31) return 0;
3654   if(hasConstructionEdges()) {
3655     // creation quadratic edges - not implemented
3656     return 0;
3657   }
3658   else
3659   {
3660     // --- retrieve nodes ID
3661     vector<vtkIdType> nodeIds;
3662     nodeIds.clear();
3663     nodeIds.push_back(n1->getVtkId());
3664     nodeIds.push_back(n2->getVtkId());
3665     nodeIds.push_back(n3->getVtkId());
3666     nodeIds.push_back(n12->getVtkId());
3667     nodeIds.push_back(n23->getVtkId());
3668     nodeIds.push_back(n31->getVtkId());
3669
3670     SMDS_MeshFace * face = 0;
3671     SMDS_VtkFace *facevtk = myFacePool->getNew();
3672     facevtk->init(nodeIds, this);
3673     if (!this->registerElement(ID,facevtk))
3674       {
3675         this->myGrid->GetCellTypesArray()->SetValue(facevtk->getVtkId(), VTK_EMPTY_CELL);
3676         myFacePool->destroy(facevtk);
3677         return 0;
3678       }
3679     face = facevtk;
3680     adjustmyCellsCapacity(ID);
3681     myCells[ID] = face;
3682     myInfo.myNbQuadTriangles++;
3683
3684 //    if (!registerElement(ID, face)) {
3685 //      RemoveElement(face, false);
3686 //      face = NULL;
3687 //    }
3688     return face;
3689   }
3690 }
3691
3692
3693 //=======================================================================
3694 //function : AddFace
3695 //purpose  :
3696 //=======================================================================
3697 SMDS_MeshFace* SMDS_Mesh::AddFace(const SMDS_MeshNode * n1,
3698                                   const SMDS_MeshNode * n2,
3699                                   const SMDS_MeshNode * n3,
3700                                   const SMDS_MeshNode * n4,
3701                                   const SMDS_MeshNode * n12,
3702                                   const SMDS_MeshNode * n23,
3703                                   const SMDS_MeshNode * n34,
3704                                   const SMDS_MeshNode * n41)
3705 {
3706   return SMDS_Mesh::AddFaceWithID(n1,n2,n3,n4,n12,n23,n34,n41,
3707                                   myElementIDFactory->GetFreeID());
3708 }
3709
3710 //=======================================================================
3711 //function : AddFaceWithID
3712 //purpose  :
3713 //=======================================================================
3714 SMDS_MeshFace* SMDS_Mesh::AddFaceWithID(int n1, int n2, int n3, int n4,
3715                                         int n12,int n23,int n34,int n41, int ID)
3716 {
3717   return SMDS_Mesh::AddFaceWithID
3718     ((SMDS_MeshNode *)myNodeIDFactory->MeshElement(n1) ,
3719      (SMDS_MeshNode *)myNodeIDFactory->MeshElement(n2) ,
3720      (SMDS_MeshNode *)myNodeIDFactory->MeshElement(n3) ,
3721      (SMDS_MeshNode *)myNodeIDFactory->MeshElement(n4) ,
3722      (SMDS_MeshNode *)myNodeIDFactory->MeshElement(n12),
3723      (SMDS_MeshNode *)myNodeIDFactory->MeshElement(n23),
3724      (SMDS_MeshNode *)myNodeIDFactory->MeshElement(n34),
3725      (SMDS_MeshNode *)myNodeIDFactory->MeshElement(n41),
3726      ID);
3727 }
3728
3729 //=======================================================================
3730 //function : AddFaceWithID
3731 //purpose  :
3732 //=======================================================================
3733 SMDS_MeshFace* SMDS_Mesh::AddFaceWithID(const SMDS_MeshNode * n1,
3734                                         const SMDS_MeshNode * n2,
3735                                         const SMDS_MeshNode * n3,
3736                                         const SMDS_MeshNode * n4,
3737                                         const SMDS_MeshNode * n12,
3738                                         const SMDS_MeshNode * n23,
3739                                         const SMDS_MeshNode * n34,
3740                                         const SMDS_MeshNode * n41,
3741                                         int ID)
3742 {
3743   if ( !n1 || !n2 || !n3 || !n4 || !n12 || !n23 || !n34 || !n41) return 0;
3744   if(hasConstructionEdges()) {
3745     // creation quadratic edges - not implemented
3746         return 0;
3747   }
3748   else
3749   {
3750     // --- retrieve nodes ID
3751     vector<vtkIdType> nodeIds;
3752     nodeIds.clear();
3753     nodeIds.push_back(n1->getVtkId());
3754     nodeIds.push_back(n2->getVtkId());
3755     nodeIds.push_back(n3->getVtkId());
3756     nodeIds.push_back(n4->getVtkId());
3757     nodeIds.push_back(n12->getVtkId());
3758     nodeIds.push_back(n23->getVtkId());
3759     nodeIds.push_back(n34->getVtkId());
3760     nodeIds.push_back(n41->getVtkId());
3761
3762     SMDS_MeshFace * face = 0;
3763     SMDS_VtkFace *facevtk = myFacePool->getNew();
3764     facevtk->init(nodeIds, this);
3765     if (!this->registerElement(ID,facevtk))
3766       {
3767         this->myGrid->GetCellTypesArray()->SetValue(facevtk->getVtkId(), VTK_EMPTY_CELL);
3768         myFacePool->destroy(facevtk);
3769         return 0;
3770       }
3771     face = facevtk;
3772     adjustmyCellsCapacity(ID);
3773     myCells[ID] = face;
3774     myInfo.myNbQuadQuadrangles++;
3775
3776 //    if (!registerElement(ID, face)) {
3777 //      RemoveElement(face, false);
3778 //      face = NULL;
3779 //    }
3780     return face;
3781   }
3782 }
3783
3784 //=======================================================================
3785 //function : AddFace
3786 //purpose  :
3787 //=======================================================================
3788 SMDS_MeshFace* SMDS_Mesh::AddFace(const SMDS_MeshNode * n1,
3789                                   const SMDS_MeshNode * n2,
3790                                   const SMDS_MeshNode * n3,
3791                                   const SMDS_MeshNode * n4,
3792                                   const SMDS_MeshNode * n12,
3793                                   const SMDS_MeshNode * n23,
3794                                   const SMDS_MeshNode * n34,
3795                                   const SMDS_MeshNode * n41,
3796                                   const SMDS_MeshNode * nCenter)
3797 {
3798   return SMDS_Mesh::AddFaceWithID(n1,n2,n3,n4,n12,n23,n34,n41,nCenter,
3799                                   myElementIDFactory->GetFreeID());
3800 }
3801
3802 //=======================================================================
3803 //function : AddFaceWithID
3804 //purpose  :
3805 //=======================================================================
3806 SMDS_MeshFace* SMDS_Mesh::AddFaceWithID(int n1, int n2, int n3, int n4,
3807                                         int n12,int n23,int n34,int n41, int nCenter, int ID)
3808 {
3809   return SMDS_Mesh::AddFaceWithID
3810     ((SMDS_MeshNode *)myNodeIDFactory->MeshElement(n1) ,
3811      (SMDS_MeshNode *)myNodeIDFactory->MeshElement(n2) ,
3812      (SMDS_MeshNode *)myNodeIDFactory->MeshElement(n3) ,
3813      (SMDS_MeshNode *)myNodeIDFactory->MeshElement(n4) ,
3814      (SMDS_MeshNode *)myNodeIDFactory->MeshElement(n12),
3815      (SMDS_MeshNode *)myNodeIDFactory->MeshElement(n23),
3816      (SMDS_MeshNode *)myNodeIDFactory->MeshElement(n34),
3817      (SMDS_MeshNode *)myNodeIDFactory->MeshElement(n41),
3818      (SMDS_MeshNode *)myNodeIDFactory->MeshElement(nCenter),
3819      ID);
3820 }
3821
3822 //=======================================================================
3823 //function : AddFaceWithID
3824 //purpose  :
3825 //=======================================================================
3826 SMDS_MeshFace* SMDS_Mesh::AddFaceWithID(const SMDS_MeshNode * n1,
3827                                         const SMDS_MeshNode * n2,
3828                                         const SMDS_MeshNode * n3,
3829                                         const SMDS_MeshNode * n4,
3830                                         const SMDS_MeshNode * n12,
3831                                         const SMDS_MeshNode * n23,
3832                                         const SMDS_MeshNode * n34,
3833                                         const SMDS_MeshNode * n41,
3834                                         const SMDS_MeshNode * nCenter,
3835                                         int ID)
3836 {
3837   if ( !n1 || !n2 || !n3 || !n4 || !n12 || !n23 || !n34 || !n41 || !nCenter) return 0;
3838   if(hasConstructionEdges()) {
3839     // creation quadratic edges - not implemented
3840         return 0;
3841   }
3842   else
3843   {
3844     // --- retrieve nodes ID
3845     vector<vtkIdType> nodeIds;
3846     nodeIds.clear();
3847     nodeIds.push_back(n1->getVtkId());
3848     nodeIds.push_back(n2->getVtkId());
3849     nodeIds.push_back(n3->getVtkId());
3850     nodeIds.push_back(n4->getVtkId());
3851     nodeIds.push_back(n12->getVtkId());
3852     nodeIds.push_back(n23->getVtkId());
3853     nodeIds.push_back(n34->getVtkId());
3854     nodeIds.push_back(n41->getVtkId());
3855     nodeIds.push_back(nCenter->getVtkId());
3856
3857     SMDS_MeshFace * face = 0;
3858     SMDS_VtkFace *facevtk = myFacePool->getNew();
3859     facevtk->init(nodeIds, this);
3860     if (!this->registerElement(ID,facevtk))
3861       {
3862         this->myGrid->GetCellTypesArray()->SetValue(facevtk->getVtkId(), VTK_EMPTY_CELL);
3863         myFacePool->destroy(facevtk);
3864         return 0;
3865       }
3866     face = facevtk;
3867     adjustmyCellsCapacity(ID);
3868     myCells[ID] = face;
3869     myInfo.myNbBiQuadQuadrangles++;
3870
3871 //    if (!registerElement(ID, face)) {
3872 //      RemoveElement(face, false);
3873 //      face = NULL;
3874 //    }
3875     return face;
3876   }
3877 }
3878
3879
3880 //=======================================================================
3881 //function : AddVolume
3882 //purpose  :
3883 //=======================================================================
3884 SMDS_MeshVolume* SMDS_Mesh::AddVolume(const SMDS_MeshNode * n1,
3885                                       const SMDS_MeshNode * n2,
3886                                       const SMDS_MeshNode * n3,
3887                                       const SMDS_MeshNode * n4,
3888                                       const SMDS_MeshNode * n12,
3889                                       const SMDS_MeshNode * n23,
3890                                       const SMDS_MeshNode * n31,
3891                                       const SMDS_MeshNode * n14,
3892                                       const SMDS_MeshNode * n24,
3893                                       const SMDS_MeshNode * n34)
3894 {
3895   int ID = myElementIDFactory->GetFreeID();
3896   SMDS_MeshVolume * v = SMDS_Mesh::AddVolumeWithID(n1, n2, n3, n4, n12, n23,
3897                                                    n31, n14, n24, n34, ID);
3898   if(v==NULL) myElementIDFactory->ReleaseID(ID);
3899   return v;
3900 }
3901
3902 //=======================================================================
3903 //function : AddVolumeWithID
3904 //purpose  :
3905 //=======================================================================
3906 SMDS_MeshVolume* SMDS_Mesh::AddVolumeWithID(int n1, int n2, int n3, int n4,
3907                                             int n12,int n23,int n31,
3908                                             int n14,int n24,int n34, int ID)
3909 {
3910   return SMDS_Mesh::AddVolumeWithID
3911     ((SMDS_MeshNode*) myNodeIDFactory->MeshElement(n1) ,
3912      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n2) ,
3913      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n3) ,
3914      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n4) ,
3915      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n12),
3916      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n23),
3917      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n31),
3918      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n14),
3919      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n24),
3920      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n34),
3921      ID);
3922 }
3923
3924 //=======================================================================
3925 //function : AddVolumeWithID
3926 //purpose  : 2d order tetrahedron of 10 nodes
3927 //=======================================================================
3928 SMDS_MeshVolume* SMDS_Mesh::AddVolumeWithID(const SMDS_MeshNode * n1,
3929                                             const SMDS_MeshNode * n2,
3930                                             const SMDS_MeshNode * n3,
3931                                             const SMDS_MeshNode * n4,
3932                                             const SMDS_MeshNode * n12,
3933                                             const SMDS_MeshNode * n23,
3934                                             const SMDS_MeshNode * n31,
3935                                             const SMDS_MeshNode * n14,
3936                                             const SMDS_MeshNode * n24,
3937                                             const SMDS_MeshNode * n34,
3938                                             int ID)
3939 {
3940   if ( !n1 || !n2 || !n3 || !n4 || !n12 || !n23 || !n31 || !n14 || !n24 || !n34)
3941     return 0;
3942   if(hasConstructionFaces()) {
3943     // creation quadratic faces - not implemented
3944     return 0;
3945   }
3946   // --- retrieve nodes ID
3947   vector<vtkIdType> nodeIds;
3948   nodeIds.clear();
3949   nodeIds.push_back(n1->getVtkId());
3950   nodeIds.push_back(n3->getVtkId());
3951   nodeIds.push_back(n2->getVtkId());
3952   nodeIds.push_back(n4->getVtkId());
3953
3954   nodeIds.push_back(n31->getVtkId());
3955   nodeIds.push_back(n23->getVtkId());
3956   nodeIds.push_back(n12->getVtkId());
3957
3958   nodeIds.push_back(n14->getVtkId());
3959   nodeIds.push_back(n34->getVtkId());
3960   nodeIds.push_back(n24->getVtkId());
3961
3962   SMDS_VtkVolume *volvtk = myVolumePool->getNew();
3963   volvtk->init(nodeIds, this);
3964   if (!this->registerElement(ID,volvtk))
3965     {
3966       this->myGrid->GetCellTypesArray()->SetValue(volvtk->getVtkId(), VTK_EMPTY_CELL);
3967       myVolumePool->destroy(volvtk);
3968       return 0;
3969     }
3970   adjustmyCellsCapacity(ID);
3971   myCells[ID] = volvtk;
3972   myInfo.myNbQuadTetras++;
3973
3974 //  if (!registerElement(ID, volvtk)) {
3975 //    RemoveElement(volvtk, false);
3976 //    volvtk = NULL;
3977 //  }
3978   return volvtk;
3979 }
3980
3981
3982 //=======================================================================
3983 //function : AddVolume
3984 //purpose  :
3985 //=======================================================================
3986 SMDS_MeshVolume* SMDS_Mesh::AddVolume(const SMDS_MeshNode * n1,
3987                                       const SMDS_MeshNode * n2,
3988                                       const SMDS_MeshNode * n3,
3989                                       const SMDS_MeshNode * n4,
3990                                       const SMDS_MeshNode * n5,
3991                                       const SMDS_MeshNode * n12,
3992                                       const SMDS_MeshNode * n23,
3993                                       const SMDS_MeshNode * n34,
3994                                       const SMDS_MeshNode * n41,
3995                                       const SMDS_MeshNode * n15,
3996                                       const SMDS_MeshNode * n25,
3997                                       const SMDS_MeshNode * n35,
3998                                       const SMDS_MeshNode * n45)
3999 {
4000   int ID = myElementIDFactory->GetFreeID();
4001   SMDS_MeshVolume * v =
4002     SMDS_Mesh::AddVolumeWithID(n1, n2, n3, n4, n5, n12, n23, n34, n41,
4003                                n15, n25, n35, n45, ID);
4004   if(v==NULL) myElementIDFactory->ReleaseID(ID);
4005   return v;
4006 }
4007
4008 //=======================================================================
4009 //function : AddVolumeWithID
4010 //purpose  :
4011 //=======================================================================
4012 SMDS_MeshVolume* SMDS_Mesh::AddVolumeWithID(int n1, int n2, int n3, int n4, int n5,
4013                                             int n12,int n23,int n34,int n41,
4014                                             int n15,int n25,int n35,int n45, int ID)
4015 {
4016   return SMDS_Mesh::AddVolumeWithID
4017     ((SMDS_MeshNode*) myNodeIDFactory->MeshElement(n1) ,
4018      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n2) ,
4019      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n3) ,
4020      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n4) ,
4021      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n5) ,
4022      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n12),
4023      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n23),
4024      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n34),
4025      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n41),
4026      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n15),
4027      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n25),
4028      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n35),
4029      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n45),
4030      ID);
4031 }
4032
4033 //=======================================================================
4034 //function : AddVolumeWithID
4035 //purpose  : 2d order pyramid of 13 nodes
4036 //=======================================================================
4037 SMDS_MeshVolume* SMDS_Mesh::AddVolumeWithID(const SMDS_MeshNode * n1,
4038                                             const SMDS_MeshNode * n2,
4039                                             const SMDS_MeshNode * n3,
4040                                             const SMDS_MeshNode * n4,
4041                                             const SMDS_MeshNode * n5,
4042                                             const SMDS_MeshNode * n12,
4043                                             const SMDS_MeshNode * n23,
4044                                             const SMDS_MeshNode * n34,
4045                                             const SMDS_MeshNode * n41,
4046                                             const SMDS_MeshNode * n15,
4047                                             const SMDS_MeshNode * n25,
4048                                             const SMDS_MeshNode * n35,
4049                                             const SMDS_MeshNode * n45,
4050                                             int ID)
4051 {
4052   if (!n1 || !n2 || !n3 || !n4 || !n5 || !n12 || !n23 ||
4053       !n34 || !n41 || !n15 || !n25 || !n35 || !n45)
4054     return 0;
4055   if(hasConstructionFaces()) {
4056     // creation quadratic faces - not implemented
4057     return 0;
4058   }
4059   // --- retrieve nodes ID
4060   vector<vtkIdType> nodeIds;
4061   nodeIds.clear();
4062   nodeIds.push_back(n1->getVtkId());
4063   nodeIds.push_back(n4->getVtkId());
4064   nodeIds.push_back(n3->getVtkId());
4065   nodeIds.push_back(n2->getVtkId());
4066   nodeIds.push_back(n5->getVtkId());
4067
4068   nodeIds.push_back(n41->getVtkId());
4069   nodeIds.push_back(n34->getVtkId());
4070   nodeIds.push_back(n23->getVtkId());
4071   nodeIds.push_back(n12->getVtkId());
4072
4073   nodeIds.push_back(n15->getVtkId());
4074   nodeIds.push_back(n45->getVtkId());
4075   nodeIds.push_back(n35->getVtkId());
4076   nodeIds.push_back(n25->getVtkId());
4077
4078   SMDS_VtkVolume *volvtk = myVolumePool->getNew();
4079   volvtk->init(nodeIds, this);
4080   if (!this->registerElement(ID,volvtk))
4081     {
4082       this->myGrid->GetCellTypesArray()->SetValue(volvtk->getVtkId(), VTK_EMPTY_CELL);
4083       myVolumePool->destroy(volvtk);
4084       return 0;
4085     }
4086   adjustmyCellsCapacity(ID);
4087   myCells[ID] = volvtk;
4088   myInfo.myNbQuadPyramids++;
4089
4090 //  if (!registerElement(ID, volvtk)) {
4091 //    RemoveElement(volvtk, false);
4092 //    volvtk = NULL;
4093 //  }
4094   return volvtk;
4095 }
4096
4097
4098 //=======================================================================
4099 //function : AddVolume
4100 //purpose  :
4101 //=======================================================================
4102 SMDS_MeshVolume* SMDS_Mesh::AddVolume(const SMDS_MeshNode * n1,
4103                                       const SMDS_MeshNode * n2,
4104                                       const SMDS_MeshNode * n3,
4105                                       const SMDS_MeshNode * n4,
4106                                       const SMDS_MeshNode * n5,
4107                                       const SMDS_MeshNode * n6,
4108                                       const SMDS_MeshNode * n12,
4109                                       const SMDS_MeshNode * n23,
4110                                       const SMDS_MeshNode * n31,
4111                                       const SMDS_MeshNode * n45,
4112                                       const SMDS_MeshNode * n56,
4113                                       const SMDS_MeshNode * n64,
4114                                       const SMDS_MeshNode * n14,
4115                                       const SMDS_MeshNode * n25,
4116                                       const SMDS_MeshNode * n36)
4117 {
4118   int ID = myElementIDFactory->GetFreeID();
4119   SMDS_MeshVolume * v =
4120     SMDS_Mesh::AddVolumeWithID(n1, n2, n3, n4, n5, n6, n12, n23, n31,
4121                                n45, n56, n64, n14, n25, n36, ID);
4122   if(v==NULL) myElementIDFactory->ReleaseID(ID);
4123   return v;
4124 }
4125
4126 //=======================================================================
4127 //function : AddVolumeWithID
4128 //purpose  :
4129 //=======================================================================
4130 SMDS_MeshVolume* SMDS_Mesh::AddVolumeWithID(int n1, int n2, int n3,
4131                                             int n4, int n5, int n6,
4132                                             int n12,int n23,int n31,
4133                                             int n45,int n56,int n64,
4134                                             int n14,int n25,int n36, int ID)
4135 {
4136   return SMDS_Mesh::AddVolumeWithID
4137     ((SMDS_MeshNode*) myNodeIDFactory->MeshElement(n1) ,
4138      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n2) ,
4139      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n3) ,
4140      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n4) ,
4141      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n5) ,
4142      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n6) ,
4143      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n12),
4144      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n23),
4145      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n31),
4146      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n45),
4147      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n56),
4148      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n64),
4149      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n14),
4150      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n25),
4151      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n36),
4152      ID);
4153 }
4154
4155 //=======================================================================
4156 //function : AddVolumeWithID
4157 //purpose  : 2d order Pentahedron with 15 nodes
4158 //=======================================================================
4159 SMDS_MeshVolume* SMDS_Mesh::AddVolumeWithID(const SMDS_MeshNode * n1,
4160                                             const SMDS_MeshNode * n2,
4161                                             const SMDS_MeshNode * n3,
4162                                             const SMDS_MeshNode * n4,
4163                                             const SMDS_MeshNode * n5,
4164                                             const SMDS_MeshNode * n6,
4165                                             const SMDS_MeshNode * n12,
4166                                             const SMDS_MeshNode * n23,
4167                                             const SMDS_MeshNode * n31,
4168                                             const SMDS_MeshNode * n45,
4169                                             const SMDS_MeshNode * n56,
4170                                             const SMDS_MeshNode * n64,
4171                                             const SMDS_MeshNode * n14,
4172                                             const SMDS_MeshNode * n25,
4173                                             const SMDS_MeshNode * n36,
4174                                             int ID)
4175 {
4176   if (!n1 || !n2 || !n3 || !n4 || !n5 || !n6 || !n12 || !n23 ||
4177       !n31 || !n45 || !n56 || !n64 || !n14 || !n25 || !n36)
4178     return 0;
4179   if(hasConstructionFaces()) {
4180     // creation quadratic faces - not implemented
4181     return 0;
4182   }
4183   // --- retrieve nodes ID
4184   vector<vtkIdType> nodeIds;
4185   nodeIds.clear();
4186   nodeIds.push_back(n1->getVtkId());
4187   nodeIds.push_back(n2->getVtkId());
4188   nodeIds.push_back(n3->getVtkId());
4189
4190   nodeIds.push_back(n4->getVtkId());
4191   nodeIds.push_back(n5->getVtkId());
4192   nodeIds.push_back(n6->getVtkId());
4193
4194   nodeIds.push_back(n12->getVtkId());
4195   nodeIds.push_back(n23->getVtkId());
4196   nodeIds.push_back(n31->getVtkId());
4197
4198   nodeIds.push_back(n45->getVtkId());
4199   nodeIds.push_back(n56->getVtkId());
4200   nodeIds.push_back(n64->getVtkId());
4201
4202   nodeIds.push_back(n14->getVtkId());
4203   nodeIds.push_back(n25->getVtkId());
4204   nodeIds.push_back(n36->getVtkId());
4205
4206   SMDS_VtkVolume *volvtk = myVolumePool->getNew();
4207   volvtk->init(nodeIds, this);
4208   if (!this->registerElement(ID,volvtk))
4209     {
4210       this->myGrid->GetCellTypesArray()->SetValue(volvtk->getVtkId(), VTK_EMPTY_CELL);
4211       myVolumePool->destroy(volvtk);
4212       return 0;
4213     }
4214   adjustmyCellsCapacity(ID);
4215   myCells[ID] = volvtk;
4216   myInfo.myNbQuadPrisms++;
4217
4218 //  if (!registerElement(ID, volvtk)) {
4219 //    RemoveElement(volvtk, false);
4220 //    volvtk = NULL;
4221 //  }
4222   return volvtk;
4223 }
4224
4225
4226 //=======================================================================
4227 //function : AddVolume
4228 //purpose  :
4229 //=======================================================================
4230 SMDS_MeshVolume* SMDS_Mesh::AddVolume(const SMDS_MeshNode * n1,
4231                                       const SMDS_MeshNode * n2,
4232                                       const SMDS_MeshNode * n3,
4233                                       const SMDS_MeshNode * n4,
4234                                       const SMDS_MeshNode * n5,
4235                                       const SMDS_MeshNode * n6,
4236                                       const SMDS_MeshNode * n7,
4237                                       const SMDS_MeshNode * n8,
4238                                       const SMDS_MeshNode * n12,
4239                                       const SMDS_MeshNode * n23,
4240                                       const SMDS_MeshNode * n34,
4241                                       const SMDS_MeshNode * n41,
4242                                       const SMDS_MeshNode * n56,
4243                                       const SMDS_MeshNode * n67,
4244                                       const SMDS_MeshNode * n78,
4245                                       const SMDS_MeshNode * n85,
4246                                       const SMDS_MeshNode * n15,
4247                                       const SMDS_MeshNode * n26,
4248                                       const SMDS_MeshNode * n37,
4249                                       const SMDS_MeshNode * n48)
4250 {
4251   int ID = myElementIDFactory->GetFreeID();
4252   SMDS_MeshVolume * v =
4253     SMDS_Mesh::AddVolumeWithID(n1, n2, n3, n4, n5, n6, n7, n8, n12, n23, n34, n41,
4254                                n56, n67, n78, n85, n15, n26, n37, n48, ID);
4255   if(v==NULL) myElementIDFactory->ReleaseID(ID);
4256   return v;
4257 }
4258
4259 //=======================================================================
4260 //function : AddVolumeWithID
4261 //purpose  :
4262 //=======================================================================
4263 SMDS_MeshVolume* SMDS_Mesh::AddVolumeWithID(int n1, int n2, int n3, int n4,
4264                                             int n5, int n6, int n7, int n8,
4265                                             int n12,int n23,int n34,int n41,
4266                                             int n56,int n67,int n78,int n85,
4267                                             int n15,int n26,int n37,int n48, int ID)
4268 {
4269   return SMDS_Mesh::AddVolumeWithID
4270     ((SMDS_MeshNode*) myNodeIDFactory->MeshElement(n1),
4271      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n2),
4272      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n3),
4273      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n4),
4274      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n5),
4275      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n6),
4276      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n7),
4277      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n8),
4278      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n12),
4279      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n23),
4280      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n34),
4281      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n41),
4282      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n56),
4283      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n67),
4284      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n78),
4285      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n85),
4286      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n15),
4287      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n26),
4288      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n37),
4289      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n48),
4290      ID);
4291 }
4292
4293 //=======================================================================
4294 //function : AddVolumeWithID
4295 //purpose  : 2d order Hexahedrons with 20 nodes
4296 //=======================================================================
4297 SMDS_MeshVolume* SMDS_Mesh::AddVolumeWithID(const SMDS_MeshNode * n1,
4298                                             const SMDS_MeshNode * n2,
4299                                             const SMDS_MeshNode * n3,
4300                                             const SMDS_MeshNode * n4,
4301                                             const SMDS_MeshNode * n5,
4302                                             const SMDS_MeshNode * n6,
4303                                             const SMDS_MeshNode * n7,
4304                                             const SMDS_MeshNode * n8,
4305                                             const SMDS_MeshNode * n12,
4306                                             const SMDS_MeshNode * n23,
4307                                             const SMDS_MeshNode * n34,
4308                                             const SMDS_MeshNode * n41,
4309                                             const SMDS_MeshNode * n56,
4310                                             const SMDS_MeshNode * n67,
4311                                             const SMDS_MeshNode * n78,
4312                                             const SMDS_MeshNode * n85,
4313                                             const SMDS_MeshNode * n15,
4314                                             const SMDS_MeshNode * n26,
4315                                             const SMDS_MeshNode * n37,
4316                                             const SMDS_MeshNode * n48,
4317                                             int ID)
4318 {
4319   if (!n1 || !n2 || !n3 || !n4 || !n5 || !n6 || !n7 || !n8 || !n12 || !n23 ||
4320       !n34 || !n41 || !n56 || !n67 || !n78 || !n85 || !n15 || !n26 || !n37 || !n48)
4321     return 0;
4322   if(hasConstructionFaces()) {
4323     return 0;
4324     // creation quadratic faces - not implemented
4325   }
4326   // --- retrieve nodes ID
4327   vector<vtkIdType> nodeIds;
4328   nodeIds.clear();
4329   nodeIds.push_back(n1->getVtkId());
4330   nodeIds.push_back(n4->getVtkId());
4331   nodeIds.push_back(n3->getVtkId());
4332   nodeIds.push_back(n2->getVtkId());
4333
4334   nodeIds.push_back(n5->getVtkId());
4335   nodeIds.push_back(n8->getVtkId());
4336   nodeIds.push_back(n7->getVtkId());
4337   nodeIds.push_back(n6->getVtkId());
4338
4339   nodeIds.push_back(n41->getVtkId());
4340   nodeIds.push_back(n34->getVtkId());
4341   nodeIds.push_back(n23->getVtkId());
4342   nodeIds.push_back(n12->getVtkId());
4343
4344   nodeIds.push_back(n85->getVtkId());
4345   nodeIds.push_back(n78->getVtkId());
4346   nodeIds.push_back(n67->getVtkId());
4347   nodeIds.push_back(n56->getVtkId());
4348
4349   nodeIds.push_back(n15->getVtkId());
4350   nodeIds.push_back(n48->getVtkId());
4351   nodeIds.push_back(n37->getVtkId());
4352   nodeIds.push_back(n26->getVtkId());
4353
4354   SMDS_VtkVolume *volvtk = myVolumePool->getNew();
4355   volvtk->init(nodeIds, this);
4356   if (!this->registerElement(ID,volvtk))
4357     {
4358       this->myGrid->GetCellTypesArray()->SetValue(volvtk->getVtkId(), VTK_EMPTY_CELL);
4359       myVolumePool->destroy(volvtk);
4360       return 0;
4361     }
4362   adjustmyCellsCapacity(ID);
4363   myCells[ID] = volvtk;
4364   myInfo.myNbQuadHexas++;
4365
4366 //  if (!registerElement(ID, volvtk)) {
4367 //    RemoveElement(volvtk, false);
4368 //    volvtk = NULL;
4369 //  }
4370   return volvtk;
4371 }
4372
4373 //=======================================================================
4374 //function : AddVolume
4375 //purpose  :
4376 //=======================================================================
4377 SMDS_MeshVolume* SMDS_Mesh::AddVolume(const SMDS_MeshNode * n1,
4378                                       const SMDS_MeshNode * n2,
4379                                       const SMDS_MeshNode * n3,
4380                                       const SMDS_MeshNode * n4,
4381                                       const SMDS_MeshNode * n5,
4382                                       const SMDS_MeshNode * n6,
4383                                       const SMDS_MeshNode * n7,
4384                                       const SMDS_MeshNode * n8,
4385                                       const SMDS_MeshNode * n12,
4386                                       const SMDS_MeshNode * n23,
4387                                       const SMDS_MeshNode * n34,
4388                                       const SMDS_MeshNode * n41,
4389                                       const SMDS_MeshNode * n56,
4390                                       const SMDS_MeshNode * n67,
4391                                       const SMDS_MeshNode * n78,
4392                                       const SMDS_MeshNode * n85,
4393                                       const SMDS_MeshNode * n15,
4394                                       const SMDS_MeshNode * n26,
4395                                       const SMDS_MeshNode * n37,
4396                                       const SMDS_MeshNode * n48,
4397                                       const SMDS_MeshNode * n1234,
4398                                       const SMDS_MeshNode * n1256,
4399                                       const SMDS_MeshNode * n2367,
4400                                       const SMDS_MeshNode * n3478,
4401                                       const SMDS_MeshNode * n1458,
4402                                       const SMDS_MeshNode * n5678,
4403                                       const SMDS_MeshNode * nCenter)
4404 {
4405   int ID = myElementIDFactory->GetFreeID();
4406   SMDS_MeshVolume * v =
4407     SMDS_Mesh::AddVolumeWithID(n1, n2, n3, n4, n5, n6, n7, n8, n12, n23, n34, n41,
4408                                n56, n67, n78, n85, n15, n26, n37, n48,
4409                                n1234, n1256, n2367, n3478, n1458, n5678, nCenter,
4410                                ID);
4411   if(v==NULL) myElementIDFactory->ReleaseID(ID);
4412   return v;
4413 }
4414
4415 //=======================================================================
4416 //function : AddVolumeWithID
4417 //purpose  :
4418 //=======================================================================
4419 SMDS_MeshVolume* SMDS_Mesh::AddVolumeWithID(int n1, int n2, int n3, int n4,
4420                                             int n5, int n6, int n7, int n8,
4421                                             int n12,int n23,int n34,int n41,
4422                                             int n56,int n67,int n78,int n85,
4423                                             int n15,int n26,int n37,int n48,
4424                                             int n1234,int n1256,int n2367,int n3478,
4425                                             int n1458,int n5678,int nCenter, int ID)
4426 {
4427   return SMDS_Mesh::AddVolumeWithID
4428     ((SMDS_MeshNode*) myNodeIDFactory->MeshElement(n1),
4429      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n2),
4430      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n3),
4431      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n4),
4432      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n5),
4433      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n6),
4434      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n7),
4435      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n8),
4436      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n12),
4437      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n23),
4438      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n34),
4439      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n41),
4440      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n56),
4441      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n67),
4442      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n78),
4443      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n85),
4444      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n15),
4445      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n26),
4446      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n37),
4447      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n48),
4448      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n1234),
4449      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n1256),
4450      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n2367),
4451      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n3478),
4452      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n1458),
4453      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(n5678),
4454      (SMDS_MeshNode*) myNodeIDFactory->MeshElement(nCenter),
4455      ID);
4456 }
4457
4458 //=======================================================================
4459 //function : AddVolumeWithID
4460 //purpose  : 2d order Hexahedrons with 20 nodes
4461 //=======================================================================
4462 SMDS_MeshVolume* SMDS_Mesh::AddVolumeWithID(const SMDS_MeshNode * n1,
4463                                             const SMDS_MeshNode * n2,
4464                                             const SMDS_MeshNode * n3,
4465                                             const SMDS_MeshNode * n4,
4466                                             const SMDS_MeshNode * n5,
4467                                             const SMDS_MeshNode * n6,
4468                                             const SMDS_MeshNode * n7,
4469                                             const SMDS_MeshNode * n8,
4470                                             const SMDS_MeshNode * n12,
4471                                             const SMDS_MeshNode * n23,
4472                                             const SMDS_MeshNode * n34,
4473                                             const SMDS_MeshNode * n41,
4474                                             const SMDS_MeshNode * n56,
4475                                             const SMDS_MeshNode * n67,
4476                                             const SMDS_MeshNode * n78,
4477                                             const SMDS_MeshNode * n85,
4478                                             const SMDS_MeshNode * n15,
4479                                             const SMDS_MeshNode * n26,
4480                                             const SMDS_MeshNode * n37,
4481                                             const SMDS_MeshNode * n48,
4482                                             const SMDS_MeshNode * n1234,
4483                                             const SMDS_MeshNode * n1256,
4484                                             const SMDS_MeshNode * n2367,
4485                                             const SMDS_MeshNode * n3478,
4486                                             const SMDS_MeshNode * n1458,
4487                                             const SMDS_MeshNode * n5678,
4488                                             const SMDS_MeshNode * nCenter,
4489                                             int ID)
4490 {
4491   if (!n1 || !n2 || !n3 || !n4 || !n5 || !n6 || !n7 || !n8 || !n12 || !n23 ||
4492       !n34 || !n41 || !n56 || !n67 || !n78 || !n85 || !n15 || !n26 || !n37 || !n48 ||
4493       !n1234 || !n1256 || !n2367 || !n3478 || !n1458 || !n5678 || !nCenter )
4494     return 0;
4495   if(hasConstructionFaces()) {
4496     return 0;
4497     // creation quadratic faces - not implemented
4498   }
4499   // --- retrieve nodes ID
4500   vector<vtkIdType> nodeIds;
4501   nodeIds.clear();
4502   nodeIds.push_back(n1->getVtkId());
4503   nodeIds.push_back(n4->getVtkId());
4504   nodeIds.push_back(n3->getVtkId());
4505   nodeIds.push_back(n2->getVtkId());
4506
4507   nodeIds.push_back(n5->getVtkId());
4508   nodeIds.push_back(n8->getVtkId());
4509   nodeIds.push_back(n7->getVtkId());
4510   nodeIds.push_back(n6->getVtkId());
4511
4512   nodeIds.push_back(n41->getVtkId());
4513   nodeIds.push_back(n34->getVtkId());
4514   nodeIds.push_back(n23->getVtkId());
4515   nodeIds.push_back(n12->getVtkId());
4516
4517   nodeIds.push_back(n85->getVtkId());
4518   nodeIds.push_back(n78->getVtkId());
4519   nodeIds.push_back(n67->getVtkId());
4520   nodeIds.push_back(n56->getVtkId());
4521
4522   nodeIds.push_back(n15->getVtkId());
4523   nodeIds.push_back(n48->getVtkId());
4524   nodeIds.push_back(n37->getVtkId());
4525   nodeIds.push_back(n26->getVtkId());
4526
4527   nodeIds.push_back(n1256->getVtkId());
4528   nodeIds.push_back(n3478->getVtkId());
4529   nodeIds.push_back(n1458->getVtkId());
4530   nodeIds.push_back(n2367->getVtkId());
4531   nodeIds.push_back(n1234->getVtkId());
4532   nodeIds.push_back(n5678->getVtkId());
4533   nodeIds.push_back(nCenter->getVtkId());
4534
4535   SMDS_VtkVolume *volvtk = myVolumePool->getNew();
4536   volvtk->init(nodeIds, this);
4537   if (!this->registerElement(ID,volvtk))
4538     {
4539       this->myGrid->GetCellTypesArray()->SetValue(volvtk->getVtkId(), VTK_EMPTY_CELL);
4540       myVolumePool->destroy(volvtk);
4541       return 0;
4542     }
4543   adjustmyCellsCapacity(ID);
4544   myCells[ID] = volvtk;
4545   myInfo.myNbTriQuadHexas++;
4546
4547   return volvtk;
4548 }
4549
4550
4551 void SMDS_Mesh::updateNodeMinMax()
4552 {
4553   myNodeMin = 0;
4554   if (myNodes.size() == 0)
4555   {
4556         myNodeMax=0;
4557         return;
4558   }
4559   while (!myNodes[myNodeMin] && (myNodeMin<myNodes.size()))
4560     myNodeMin++;
4561   myNodeMax=myNodes.size()-1;
4562   while (!myNodes[myNodeMax] && (myNodeMin>=0))
4563     myNodeMin--;
4564 }
4565
4566 void SMDS_Mesh::incrementNodesCapacity(int nbNodes)
4567 {
4568 //  int val = myCellIdSmdsToVtk.size();
4569 //  MESSAGE(" ------------------- resize myCellIdSmdsToVtk " << val << " --> " << val + nbNodes);
4570 //  myCellIdSmdsToVtk.resize(val + nbNodes, -1); // fill new elements with -1
4571   int val = myNodes.size();
4572   MESSAGE(" ------------------- resize myNodes " << val << " --> " << val + nbNodes);
4573   myNodes.resize(val +nbNodes, 0);
4574 }
4575
4576 void SMDS_Mesh::incrementCellsCapacity(int nbCells)
4577 {
4578   int val = myCellIdVtkToSmds.size();
4579   MESSAGE(" ------------------- resize myCellIdVtkToSmds " << val << " --> " << val + nbCells);
4580   myCellIdVtkToSmds.resize(val + nbCells, -1); // fill new elements with -1
4581   val = myCells.size();
4582   MESSAGE(" ------------------- resize myCells " << val << " --> " << val + nbCells);
4583   myNodes.resize(val +nbCells, 0);
4584 }
4585
4586 void SMDS_Mesh::adjustStructure()
4587 {
4588   myGrid->GetPoints()->GetData()->SetNumberOfTuples(myNodeIDFactory->GetMaxID());
4589 }
4590
4591 void SMDS_Mesh::dumpGrid(string ficdump)
4592 {
4593         MESSAGE("SMDS_Mesh::dumpGrid " << ficdump);
4594 //  vtkUnstructuredGridWriter* aWriter = vtkUnstructuredGridWriter::New();
4595 //  aWriter->SetFileName(ficdump.c_str());
4596 //  aWriter->SetInput(myGrid);
4597 //  if(myGrid->GetNumberOfCells())
4598 //  {
4599 //    aWriter->Write();
4600 //  }
4601 //  aWriter->Delete();
4602   ficdump = ficdump + "_connectivity";
4603   ofstream ficcon(ficdump.c_str(), ios::out);
4604   int nbPoints = myGrid->GetNumberOfPoints();
4605   ficcon << "-------------------------------- points " <<  nbPoints << endl;
4606   for (int i=0; i<nbPoints; i++)
4607   {
4608         ficcon << i << " " << *(myGrid->GetPoint(i)) << " " << *(myGrid->GetPoint(i)+1) << " " << " " << *(myGrid->GetPoint(i)+2) << endl;
4609   }
4610   int nbCells = myGrid->GetNumberOfCells();
4611   ficcon << "-------------------------------- cells " <<  nbCells << endl;
4612   for (int i=0; i<nbCells; i++)
4613   {
4614 //      MESSAGE(i << " " << myGrid->GetCell(i));
4615 //      MESSAGE("  " << myGrid->GetCell(i)->GetCellType());
4616         ficcon << i << " - " << myGrid->GetCell(i)->GetCellType() << " -";
4617         int nbptcell = myGrid->GetCell(i)->GetNumberOfPoints();
4618         vtkIdList *listid = myGrid->GetCell(i)->GetPointIds();
4619         for (int j=0; j<nbptcell; j++)
4620         {
4621                 ficcon << " " <<  listid->GetId(j);
4622         }
4623         ficcon << endl;
4624   }
4625   ficcon << "-------------------------------- connectivity " <<  nbPoints << endl;
4626         vtkCellLinks *links = myGrid->GetCellLinks();
4627   for (int i=0; i<nbPoints; i++)
4628   {
4629         int ncells = links->GetNcells(i);
4630         vtkIdType *cells = links->GetCells(i);
4631         ficcon << i << " - " << ncells << " -";
4632         for (int j=0; j<ncells; j++)
4633         {
4634                 ficcon << " " << cells[j];
4635         }
4636         ficcon << endl;
4637   }
4638   ficcon.close();
4639
4640 }
4641
4642 void SMDS_Mesh::compactMesh()
4643 {
4644   MESSAGE("SMDS_Mesh::compactMesh do nothing!");
4645 }
4646
4647 int SMDS_Mesh::fromVtkToSmds(int vtkid)
4648 {
4649   if (vtkid >= 0 && vtkid < myCellIdVtkToSmds.size())
4650     return myCellIdVtkToSmds[vtkid];
4651   throw SALOME_Exception(LOCALIZED ("vtk id out of bounds"));
4652 }
4653
4654 void SMDS_Mesh::updateBoundingBox()
4655 {
4656   xmin = 0; xmax = 0;
4657   ymin = 0; ymax = 0;
4658   zmin = 0; zmax = 0;
4659   vtkPoints *points = myGrid->GetPoints();
4660   int myNodesSize = this->myNodes.size();
4661   for (int i = 0; i < myNodesSize; i++)
4662     {
4663       if (SMDS_MeshNode *n = myNodes[i])
4664         {
4665           double coords[3];
4666           points->GetPoint(n->myVtkID, coords);
4667           if (coords[0] < xmin) xmin = coords[0];
4668           else if (coords[0] > xmax) xmax = coords[0];
4669           if (coords[1] < ymin) ymin = coords[1];
4670           else if (coords[1] > ymax) ymax = coords[1];
4671           if (coords[2] < zmin) zmin = coords[2];
4672           else if (coords[2] > zmax) zmax = coords[2];
4673         }
4674     }
4675 }
4676
4677 double SMDS_Mesh::getMaxDim()
4678 {
4679   double dmax = 1.e-3;
4680   if ((xmax - xmin) > dmax) dmax = xmax -xmin;
4681   if ((ymax - ymin) > dmax) dmax = ymax -ymin;
4682   if ((zmax - zmin) > dmax) dmax = zmax -zmin;
4683   MESSAGE("getMaxDim " << dmax);
4684   return dmax;
4685 }
4686
4687 //! modification that needs compact structure and redraw
4688 void SMDS_Mesh::Modified()
4689 {
4690   if (this->myModified)
4691     {
4692       this->myModifTime++;
4693       MESSAGE("modified");
4694       myModified = false;
4695     }
4696 }
4697
4698 //! get last modification timeStamp
4699 unsigned long SMDS_Mesh::GetMTime() const
4700 {
4701   return this->myModifTime;
4702 }
4703
4704 bool SMDS_Mesh::isCompacted()
4705 {
4706   if (this->myModifTime > this->myCompactTime)
4707     {
4708       MESSAGE(" *** isCompacted " << myCompactTime << " < " << myModifTime);
4709       this->myCompactTime = this->myModifTime;
4710       return false;
4711     }
4712   return true;
4713 }