Salome HOME
43a48eb37f23095e4f666dd64df2ed7c84a93487
[modules/smesh.git] / src / SMDS / SMDS_Mesh.cxx
1 // Copyright (C) 2007-2016  CEA/DEN, EDF R&D, OPEN CASCADE
2 //
3 // Copyright (C) 2003-2007  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
4 // CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
5 //
6 // This library is free software; you can redistribute it and/or
7 // modify it under the terms of the GNU Lesser General Public
8 // License as published by the Free Software Foundation; either
9 // version 2.1 of the License, or (at your option) any later version.
10 //
11 // This library is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 // Lesser General Public License for more details.
15 //
16 // You should have received a copy of the GNU Lesser General Public
17 // License along with this library; if not, write to the Free Software
18 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
19 //
20 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
21 //
22
23 //  SMESH SMDS : implementation of Salome mesh data structure
24 //
25 #ifdef _MSC_VER
26 #pragma warning(disable:4786)
27 #endif
28
29 #include "SMDS_Mesh.hxx"
30
31 #include "SMDS_ElementFactory.hxx"
32 #include "SMDS_ElementHolder.hxx"
33 #include "SMDS_SetIterator.hxx"
34 #include "SMDS_SpacePosition.hxx"
35 #include "SMDS_UnstructuredGrid.hxx"
36
37 #include <utilities.h>
38
39 #include <vtkUnstructuredGrid.h>
40 //#include <vtkUnstructuredGridWriter.h>
41 #include <vtkCell.h>
42 #include <vtkUnsignedCharArray.h>
43 #include <vtkCellLinks.h>
44 #include <vtkIdList.h>
45
46 #include <algorithm>
47 #include <iostream>
48 #include <fstream>
49
50 #include <boost/make_shared.hpp>
51
52 #if !defined WIN32 && !defined __APPLE__
53 #include <sys/sysinfo.h>
54 #endif
55
56 // number of added entities to check memory after
57 #define CHECKMEMORY_INTERVAL 100000
58
59 #define MYASSERT(val) if (!(val)) throw SALOME_Exception(LOCALIZED("assertion not verified"));
60
61 int SMDS_Mesh::chunkSize = 1024;
62
63 //================================================================================
64 /*!
65  * \brief Raise an exception if free memory (ram+swap) too low
66  * \param doNotRaise - if true, suppres exception, just return free memory size
67  * \retval int - amount of available memory in MB or negative number in failure case
68  */
69 //================================================================================
70
71 int SMDS_Mesh::CheckMemory(const bool doNotRaise) throw (std::bad_alloc)
72 {
73   return -1;
74 #if !defined WIN32 && !defined __APPLE__
75   struct sysinfo si;
76   int err = sysinfo( &si );
77   if ( err )
78     return -1;
79
80   const unsigned long Mbyte = 1024 * 1024;
81
82   static int limit = -1;
83   if ( limit < 0 ) {
84     if ( si.totalswap == 0 )
85     {
86       int status = system("SMDS_MemoryLimit"); // it returns lower limit of free RAM
87       if (status >= 0 ) {
88         limit = WEXITSTATUS(status);
89       }
90       else {
91         double factor = ( si.totalswap == 0 ) ? 0.1 : 0.2;
92         limit = int(( factor * si.totalram * si.mem_unit ) / Mbyte );
93       }
94     }
95     if ( limit < 20 )
96       limit = 20;
97     else
98       limit = int ( limit * 1.5 );
99     MESSAGE ( "SMDS_Mesh::CheckMemory() memory limit = " << limit << " MB" );
100   }
101
102   // compute separately to avoid overflow
103   int freeMb =
104     ( si.freeram  * si.mem_unit ) / Mbyte +
105     ( si.freeswap * si.mem_unit ) / Mbyte;
106
107   if ( freeMb > limit )
108     return freeMb - limit;
109
110   if ( doNotRaise )
111     return 0;
112
113   MESSAGE ("SMDS_Mesh::CheckMemory() throws as free memory too low: " << freeMb <<" MB" );
114   throw std::bad_alloc();
115 #else
116   return -1;
117 #endif
118 }
119
120 ///////////////////////////////////////////////////////////////////////////////
121 /// Create a new mesh object
122 ///////////////////////////////////////////////////////////////////////////////
123 SMDS_Mesh::SMDS_Mesh():
124   myNodeFactory( new SMDS_NodeFactory( this )),
125   myCellFactory( new SMDS_ElementFactory( this )),
126   myParent(NULL),
127   myModified(false), myModifTime(0), myCompactTime(0),
128   xmin(0), xmax(0), ymin(0), ymax(0), zmin(0), zmax(0)
129 {
130   myGrid = SMDS_UnstructuredGrid::New();
131   myGrid->setSMDS_mesh(this);
132   myGrid->Initialize();
133   myGrid->Allocate();
134   vtkPoints* points = vtkPoints::New();
135   // bug "21125: EDF 1233 SMESH: Degrardation of precision in a test case for quadratic conversion"
136   // Use double type for storing coordinates of nodes instead of float.
137   points->SetDataType(VTK_DOUBLE);
138   points->SetNumberOfPoints( 0 );
139   myGrid->SetPoints( points );
140   points->Delete();
141   this->Modified();
142
143   // initialize static maps in SMDS_MeshCell, to be thread-safe
144   SMDS_MeshCell::InitStaticMembers();
145 }
146
147 ///////////////////////////////////////////////////////////////////////////////
148 /// Create a new child mesh
149 /// Note that the tree structure of SMDS_Mesh seems to be unused in this version
150 /// (2003-09-08) of SMESH
151 ///////////////////////////////////////////////////////////////////////////////
152 SMDS_Mesh::SMDS_Mesh(SMDS_Mesh * parent):
153   myNodeFactory( new SMDS_NodeFactory( this )),
154   myCellFactory( new SMDS_ElementFactory( this )),
155   myParent(parent)
156 {
157 }
158
159 ///////////////////////////////////////////////////////////////////////////////
160 ///Create a submesh and add it to the current mesh
161 ///////////////////////////////////////////////////////////////////////////////
162
163 SMDS_Mesh *SMDS_Mesh::AddSubMesh()
164 {
165   SMDS_Mesh *submesh = new SMDS_Mesh(this);
166   myChildren.insert(myChildren.end(), submesh);
167   return submesh;
168 }
169
170 ///////////////////////////////////////////////////////////////////////////////
171 ///create a MeshNode and add it to the current Mesh
172 ///An ID is automatically assigned to the node.
173 ///@return : The created node
174 ///////////////////////////////////////////////////////////////////////////////
175
176 SMDS_MeshNode * SMDS_Mesh::AddNode(double x, double y, double z)
177 {
178   return SMDS_Mesh::AddNodeWithID( x,y,z, myNodeFactory->GetFreeID() );
179 }
180
181 ///////////////////////////////////////////////////////////////////////////////
182 ///create a MeshNode and add it to the current Mesh
183 ///@param ID : The ID of the MeshNode to create
184 ///@return : The created node or NULL if a node with this ID already exists
185 ///////////////////////////////////////////////////////////////////////////////
186 SMDS_MeshNode * SMDS_Mesh::AddNodeWithID( double x, double y, double z, int ID )
187 {
188   // find the MeshNode corresponding to ID
189   SMDS_MeshNode *node = myNodeFactory->NewNode( ID );
190   if ( node )
191   {
192     node->init( x, y, z );
193     myInfo.myNbNodes++;
194     myModified = true;
195     this->adjustBoundingBox(x, y, z);
196   }
197   return node;
198 }
199
200 ///////////////////////////////////////////////////////////////////////////////
201 /// create a Mesh0DElement and add it to the current Mesh
202 /// @return : The created Mesh0DElement
203 ///////////////////////////////////////////////////////////////////////////////
204 SMDS_Mesh0DElement* SMDS_Mesh::Add0DElementWithID(int idnode, int ID)
205 {
206   const SMDS_MeshNode * node = myNodeFactory->FindNode(idnode);
207   if (!node) return NULL;
208   return SMDS_Mesh::Add0DElementWithID(node, ID);
209 }
210
211 ///////////////////////////////////////////////////////////////////////////////
212 /// create a Mesh0DElement and add it to the current Mesh
213 /// @return : The created Mesh0DElement
214 ///////////////////////////////////////////////////////////////////////////////
215 SMDS_Mesh0DElement* SMDS_Mesh::Add0DElement(const SMDS_MeshNode * node)
216 {
217   return SMDS_Mesh::Add0DElementWithID( node, myCellFactory->GetFreeID() );
218 }
219
220 ///////////////////////////////////////////////////////////////////////////////
221 /// Create a new Mesh0DElement and at it to the mesh
222 /// @param idnode ID of the node
223 /// @param ID ID of the 0D element to create
224 /// @return The created 0D element or NULL if an element with this
225 ///         ID already exists or if input node is not found.
226 ///////////////////////////////////////////////////////////////////////////////
227 SMDS_Mesh0DElement* SMDS_Mesh::Add0DElementWithID(const SMDS_MeshNode * n, int ID)
228 {
229   if (!n) return 0;
230
231   if (Nb0DElements() % CHECKMEMORY_INTERVAL == 0) CheckMemory();
232
233   if ( SMDS_MeshCell * cell = myCellFactory->NewCell( ID ))
234   {
235     cell->init( SMDSEntity_0D, /*nbNodes=*/1, n );
236     myInfo.myNb0DElements++;
237     return static_cast< SMDS_Mesh0DElement*> ( cell );
238   }
239
240   return 0;
241 }
242
243 ///////////////////////////////////////////////////////////////////////////////
244 /// create a Ball and add it to the current Mesh
245 /// @return : The created Ball
246 ///////////////////////////////////////////////////////////////////////////////
247 SMDS_BallElement* SMDS_Mesh::AddBallWithID( int idnode, double diameter, int ID )
248 {
249   const SMDS_MeshNode * node = myNodeFactory->FindNode( idnode );
250   if (!node) return NULL;
251   return SMDS_Mesh::AddBallWithID( node, diameter, ID );
252 }
253
254 ///////////////////////////////////////////////////////////////////////////////
255 /// create a Ball and add it to the current Mesh
256 /// @return : The created Ball
257 ///////////////////////////////////////////////////////////////////////////////
258 SMDS_BallElement* SMDS_Mesh::AddBall(const SMDS_MeshNode * node, double diameter)
259 {
260   return SMDS_Mesh::AddBallWithID(node, diameter, myCellFactory->GetFreeID());
261 }
262
263 ///////////////////////////////////////////////////////////////////////////////
264 /// Create a new Ball and at it to the mesh
265 /// @param idnode ID of the node
266 //  @param diameter ball diameter
267 /// @param ID ID of the 0D element to create
268 /// @return The created 0D element or NULL if an element with this
269 ///         ID already exists or if input node is not found.
270 ///////////////////////////////////////////////////////////////////////////////
271 SMDS_BallElement* SMDS_Mesh::AddBallWithID(const SMDS_MeshNode * n, double diameter, int ID)
272 {
273   if (!n) return 0;
274
275   if (NbBalls() % CHECKMEMORY_INTERVAL == 0) CheckMemory();
276
277   SMDS_BallElement* ball = static_cast< SMDS_BallElement*>( myCellFactory->NewElement( ID ));
278   if ( ball )
279   {
280     ball->init( n, diameter );
281     myInfo.myNbBalls++;
282   }
283   return ball;
284 }
285
286 ///////////////////////////////////////////////////////////////////////////////
287 /// create a MeshEdge and add it to the current Mesh
288 /// @return : The created MeshEdge
289 ///////////////////////////////////////////////////////////////////////////////
290
291 SMDS_MeshEdge* SMDS_Mesh::AddEdgeWithID(int idnode1, int idnode2, int ID)
292 {
293   const SMDS_MeshNode * node1 = myNodeFactory->FindNode(idnode1);
294   const SMDS_MeshNode * node2 = myNodeFactory->FindNode(idnode2);
295   if(!node1 || !node2) return NULL;
296   return SMDS_Mesh::AddEdgeWithID(node1, node2, ID);
297 }
298
299 ///////////////////////////////////////////////////////////////////////////////
300 /// create a MeshEdge and add it to the current Mesh
301 /// @return : The created MeshEdge
302 ///////////////////////////////////////////////////////////////////////////////
303
304 SMDS_MeshEdge* SMDS_Mesh::AddEdge(const SMDS_MeshNode * node1,
305                                   const SMDS_MeshNode * node2)
306 {
307   return SMDS_Mesh::AddEdgeWithID(node1, node2, myCellFactory->GetFreeID());
308 }
309
310 ///////////////////////////////////////////////////////////////////////////////
311 /// Create a new edge and at it to the mesh
312 /// @param idnode1 ID of the first node
313 /// @param idnode2 ID of the second node
314 /// @param ID ID of the edge to create
315 /// @return The created edge or NULL if an element with this ID already exists or
316 /// if input nodes are not found.
317 ///////////////////////////////////////////////////////////////////////////////
318
319 SMDS_MeshEdge* SMDS_Mesh::AddEdgeWithID(const SMDS_MeshNode * n1,
320                                         const SMDS_MeshNode * n2,
321                                         int                   ID)
322 {
323   if ( !n1 || !n2 ) return 0;
324
325   if ( SMDS_MeshCell* cell = myCellFactory->NewCell( ID ))
326   {
327     cell->init( SMDSEntity_Edge, /*nbNodes=*/2, n1, n2 );
328     myInfo.myNbEdges++;
329     return static_cast<SMDS_MeshEdge*>( cell );
330   }
331   return 0;
332 }
333
334 ///////////////////////////////////////////////////////////////////////////////
335 /// Add a triangle defined by its nodes. An ID is automatically affected to the
336 /// Created face
337 ///////////////////////////////////////////////////////////////////////////////
338
339 SMDS_MeshFace* SMDS_Mesh::AddFace(const SMDS_MeshNode * n1,
340                                   const SMDS_MeshNode * n2,
341                                   const SMDS_MeshNode * n3)
342 {
343   return SMDS_Mesh::AddFaceWithID(n1,n2,n3, myCellFactory->GetFreeID());
344 }
345
346 ///////////////////////////////////////////////////////////////////////////////
347 /// Add a triangle defined by its nodes IDs
348 ///////////////////////////////////////////////////////////////////////////////
349
350 SMDS_MeshFace* SMDS_Mesh::AddFaceWithID(int idnode1, int idnode2, int idnode3, int ID)
351 {
352   const SMDS_MeshNode * node1 = myNodeFactory->FindNode(idnode1);
353   const SMDS_MeshNode * node2 = myNodeFactory->FindNode(idnode2);
354   const SMDS_MeshNode * node3 = myNodeFactory->FindNode(idnode3);
355   if(!node1 || !node2 || !node3) return NULL;
356   return SMDS_Mesh::AddFaceWithID(node1, node2, node3, ID);
357 }
358
359 ///////////////////////////////////////////////////////////////////////////////
360 /// Add a triangle defined by its nodes
361 ///////////////////////////////////////////////////////////////////////////////
362
363 SMDS_MeshFace* SMDS_Mesh::AddFaceWithID(const SMDS_MeshNode * n1,
364                                         const SMDS_MeshNode * n2,
365                                         const SMDS_MeshNode * n3,
366                                         int ID)
367 {
368   if ( !n1 || !n2 || !n3 ) return 0;
369   if ( NbFaces() % CHECKMEMORY_INTERVAL == 0 ) CheckMemory();
370
371   if ( SMDS_MeshCell* cell = myCellFactory->NewCell( ID ))
372   {
373     cell->init( SMDSEntity_Triangle, /*nbNodes=*/3, n1, n2, n3 );
374     myInfo.myNbTriangles++;
375     return static_cast<SMDS_MeshFace*>( cell );
376   }
377   return 0;
378 }
379
380 ///////////////////////////////////////////////////////////////////////////////
381 /// Add a quadrangle defined by its nodes. An ID is automatically affected to the
382 /// created face
383 ///////////////////////////////////////////////////////////////////////////////
384
385 SMDS_MeshFace* SMDS_Mesh::AddFace(const SMDS_MeshNode * n1,
386                                   const SMDS_MeshNode * n2,
387                                   const SMDS_MeshNode * n3,
388                                   const SMDS_MeshNode * n4)
389 {
390   return SMDS_Mesh::AddFaceWithID(n1,n2,n3, n4, myCellFactory->GetFreeID());
391 }
392
393 ///////////////////////////////////////////////////////////////////////////////
394 /// Add a quadrangle defined by its nodes IDs
395 ///////////////////////////////////////////////////////////////////////////////
396
397 SMDS_MeshFace* SMDS_Mesh::AddFaceWithID(int idnode1,
398                                         int idnode2,
399                                         int idnode3,
400                                         int idnode4,
401                                         int ID)
402 {
403   const SMDS_MeshNode *node1, *node2, *node3, *node4;
404   node1 = myNodeFactory->FindNode(idnode1);
405   node2 = myNodeFactory->FindNode(idnode2);
406   node3 = myNodeFactory->FindNode(idnode3);
407   node4 = myNodeFactory->FindNode(idnode4);
408   if ( !node1 || !node2 || !node3 || !node4 ) return NULL;
409   return SMDS_Mesh::AddFaceWithID(node1, node2, node3, node4, ID);
410 }
411
412 ///////////////////////////////////////////////////////////////////////////////
413 /// Add a quadrangle defined by its nodes
414 ///////////////////////////////////////////////////////////////////////////////
415
416 SMDS_MeshFace* SMDS_Mesh::AddFaceWithID(const SMDS_MeshNode * n1,
417                                         const SMDS_MeshNode * n2,
418                                         const SMDS_MeshNode * n3,
419                                         const SMDS_MeshNode * n4,
420                                         int ID)
421 {
422   if ( !n1 || !n2 || !n3 || !n4 ) return 0;
423   if ( NbFaces() % CHECKMEMORY_INTERVAL == 0 ) CheckMemory();
424
425   if ( SMDS_MeshCell* cell = myCellFactory->NewCell( ID ))
426   {
427     cell->init( SMDSEntity_Quadrangle, /*nbNodes=*/4, n1, n2, n3, n4 );
428     myInfo.myNbQuadrangles++;
429     return static_cast<SMDS_MeshFace*>( cell );
430   }
431   return 0;
432 }
433
434 ///////////////////////////////////////////////////////////////////////////////
435 ///Create a new tetrahedron and add it to the mesh.
436 ///@return The created tetrahedron
437 ///////////////////////////////////////////////////////////////////////////////
438
439 SMDS_MeshVolume* SMDS_Mesh::AddVolume(const SMDS_MeshNode * n1,
440                                       const SMDS_MeshNode * n2,
441                                       const SMDS_MeshNode * n3,
442                                       const SMDS_MeshNode * n4)
443 {
444   return SMDS_Mesh::AddVolumeWithID(n1, n2, n3, n4, myCellFactory->GetFreeID() );
445 }
446
447 ///////////////////////////////////////////////////////////////////////////////
448 ///Create a new tetrahedron and add it to the mesh.
449 ///@param ID The ID of the new volume
450 ///@return The created tetrahedron or NULL if an element with this ID already exists
451 ///or if input nodes are not found.
452 ///////////////////////////////////////////////////////////////////////////////
453
454 SMDS_MeshVolume * SMDS_Mesh::AddVolumeWithID(int idnode1,
455                                              int idnode2,
456                                              int idnode3,
457                                              int idnode4,
458                                              int ID)
459 {
460   const SMDS_MeshNode *node1, *node2, *node3, *node4;
461   node1 = myNodeFactory->FindNode(idnode1);
462   node2 = myNodeFactory->FindNode(idnode2);
463   node3 = myNodeFactory->FindNode(idnode3);
464   node4 = myNodeFactory->FindNode(idnode4);
465   if(!node1 || !node2 || !node3 || !node4) return NULL;
466   return SMDS_Mesh::AddVolumeWithID(node1, node2, node3, node4, ID);
467 }
468
469 ///////////////////////////////////////////////////////////////////////////////
470 ///Create a new tetrahedron and add it to the mesh.
471 ///@param ID The ID of the new volume
472 ///@return The created tetrahedron
473 ///////////////////////////////////////////////////////////////////////////////
474
475 SMDS_MeshVolume* SMDS_Mesh::AddVolumeWithID(const SMDS_MeshNode * n1,
476                                             const SMDS_MeshNode * n2,
477                                             const SMDS_MeshNode * n3,
478                                             const SMDS_MeshNode * n4,
479                                             int ID)
480 {
481   if ( !n1 || !n2 || !n3 || !n4 ) return 0;
482   if ( NbVolumes() % CHECKMEMORY_INTERVAL == 0 ) CheckMemory();
483
484   if ( SMDS_MeshCell* cell = myCellFactory->NewCell( ID ))
485   {
486     cell->init( SMDSEntity_Tetra, /*nbNodes=*/4, n1, n2, n3, n4 );
487     myInfo.myNbTetras++;
488     return static_cast<SMDS_MeshVolume*>( cell );
489   }
490   return 0;
491 }
492
493 ///////////////////////////////////////////////////////////////////////////////
494 ///Create a new pyramid and add it to the mesh.
495 ///Nodes 1,2,3 and 4 define the base of the pyramid
496 ///@return The created pyramid
497 ///////////////////////////////////////////////////////////////////////////////
498
499 SMDS_MeshVolume* SMDS_Mesh::AddVolume(const SMDS_MeshNode * n1,
500                                       const SMDS_MeshNode * n2,
501                                       const SMDS_MeshNode * n3,
502                                       const SMDS_MeshNode * n4,
503                                       const SMDS_MeshNode * n5)
504 {
505   return SMDS_Mesh::AddVolumeWithID(n1, n2, n3, n4, n5, myCellFactory->GetFreeID() );
506 }
507
508 ///////////////////////////////////////////////////////////////////////////////
509 ///Create a new pyramid and add it to the mesh.
510 ///Nodes 1,2,3 and 4 define the base of the pyramid
511 ///@param ID The ID of the new volume
512 ///@return The created pyramid or NULL if an element with this ID already exists
513 ///or if input nodes are not found.
514 ///////////////////////////////////////////////////////////////////////////////
515
516 SMDS_MeshVolume * SMDS_Mesh::AddVolumeWithID(int idnode1,
517                                              int idnode2,
518                                              int idnode3,
519                                              int idnode4,
520                                              int idnode5,
521                                              int ID)
522 {
523   const SMDS_MeshNode *node1, *node2, *node3, *node4, *node5;
524   node1 = myNodeFactory->FindNode(idnode1);
525   node2 = myNodeFactory->FindNode(idnode2);
526   node3 = myNodeFactory->FindNode(idnode3);
527   node4 = myNodeFactory->FindNode(idnode4);
528   node5 = myNodeFactory->FindNode(idnode5);
529   if(!node1 || !node2 || !node3 || !node4 || !node5) return NULL;
530   return SMDS_Mesh::AddVolumeWithID(node1, node2, node3, node4, node5, ID);
531 }
532
533 ///////////////////////////////////////////////////////////////////////////////
534 ///Create a new pyramid and add it to the mesh.
535 ///Nodes 1,2,3 and 4 define the base of the pyramid
536 ///@param ID The ID of the new volume
537 ///@return The created pyramid
538 ///////////////////////////////////////////////////////////////////////////////
539
540 SMDS_MeshVolume* SMDS_Mesh::AddVolumeWithID(const SMDS_MeshNode * n1,
541                                             const SMDS_MeshNode * n2,
542                                             const SMDS_MeshNode * n3,
543                                             const SMDS_MeshNode * n4,
544                                             const SMDS_MeshNode * n5,
545                                             int ID)
546 {
547   if ( !n1 || !n2 || !n3 || !n4 || !n5 ) return 0;
548   if ( NbVolumes() % CHECKMEMORY_INTERVAL == 0 ) CheckMemory();
549
550   if ( SMDS_MeshCell* cell = myCellFactory->NewCell( ID ))
551   {
552     cell->init( SMDSEntity_Pyramid, /*nbNodes=*/5, n1, n2, n3, n4, n5 );
553     myInfo.myNbPyramids++;
554     return static_cast<SMDS_MeshVolume*>( cell );
555   }
556   return 0;
557 }
558
559 ///////////////////////////////////////////////////////////////////////////////
560 ///Create a new prism and add it to the mesh.
561 ///Nodes 1,2,3 is a triangle and 1,2,5,4 a quadrangle.
562 ///@return The created prism
563 ///////////////////////////////////////////////////////////////////////////////
564
565 SMDS_MeshVolume* SMDS_Mesh::AddVolume(const SMDS_MeshNode * n1,
566                                       const SMDS_MeshNode * n2,
567                                       const SMDS_MeshNode * n3,
568                                       const SMDS_MeshNode * n4,
569                                       const SMDS_MeshNode * n5,
570                                       const SMDS_MeshNode * n6)
571 {
572   int ID = myCellFactory->GetFreeID();
573   return SMDS_Mesh::AddVolumeWithID(n1, n2, n3, n4, n5, n6, ID);
574 }
575
576 ///////////////////////////////////////////////////////////////////////////////
577 ///Create a new prism and add it to the mesh.
578 ///Nodes 1,2,3 is a triangle and 1,2,5,4 a quadrangle.
579 ///@param ID The ID of the new volume
580 ///@return The created prism or NULL if an element with this ID already exists
581 ///or if input nodes are not found.
582 ///////////////////////////////////////////////////////////////////////////////
583
584 SMDS_MeshVolume * SMDS_Mesh::AddVolumeWithID(int idnode1,
585                                              int idnode2,
586                                              int idnode3,
587                                              int idnode4,
588                                              int idnode5,
589                                              int idnode6,
590                                              int ID)
591 {
592   const SMDS_MeshNode *node1, *node2, *node3, *node4, *node5, *node6;
593   node1 = myNodeFactory->FindNode(idnode1);
594   node2 = myNodeFactory->FindNode(idnode2);
595   node3 = myNodeFactory->FindNode(idnode3);
596   node4 = myNodeFactory->FindNode(idnode4);
597   node5 = myNodeFactory->FindNode(idnode5);
598   node6 = myNodeFactory->FindNode(idnode6);
599   return SMDS_Mesh::AddVolumeWithID(node1, node2, node3, node4, node5, node6, ID);
600 }
601
602 ///////////////////////////////////////////////////////////////////////////////
603 ///Create a new prism and add it to the mesh.
604 ///Nodes 1,2,3 is a triangle and 1,2,5,4 a quadrangle.
605 ///@param ID The ID of the new volume
606 ///@return The created prism
607 ///////////////////////////////////////////////////////////////////////////////
608
609 SMDS_MeshVolume* SMDS_Mesh::AddVolumeWithID(const SMDS_MeshNode * n1,
610                                             const SMDS_MeshNode * n2,
611                                             const SMDS_MeshNode * n3,
612                                             const SMDS_MeshNode * n4,
613                                             const SMDS_MeshNode * n5,
614                                             const SMDS_MeshNode * n6,
615                                             int ID)
616 {
617   if ( !n1 || !n2 || !n3 || !n4 || !n5 || !n6 ) return 0;
618   if ( NbVolumes() % CHECKMEMORY_INTERVAL == 0 ) CheckMemory();
619
620   if ( SMDS_MeshCell* cell = myCellFactory->NewCell( ID ))
621   {
622     cell->init( SMDSEntity_Penta, /*nbNodes=*/6, n1, n2, n3, n4, n5, n6 );
623     myInfo.myNbPrisms++;
624     return static_cast<SMDS_MeshVolume*>( cell );
625   }
626   return 0;
627 }
628
629 ///////////////////////////////////////////////////////////////////////////////
630 ///Create a new hexagonal prism and add it to the mesh.
631 ///@return The created prism
632 ///////////////////////////////////////////////////////////////////////////////
633
634 SMDS_MeshVolume* SMDS_Mesh::AddVolume(const SMDS_MeshNode * n1,
635                                       const SMDS_MeshNode * n2,
636                                       const SMDS_MeshNode * n3,
637                                       const SMDS_MeshNode * n4,
638                                       const SMDS_MeshNode * n5,
639                                       const SMDS_MeshNode * n6,
640                                       const SMDS_MeshNode * n7,
641                                       const SMDS_MeshNode * n8,
642                                       const SMDS_MeshNode * n9,
643                                       const SMDS_MeshNode * n10,
644                                       const SMDS_MeshNode * n11,
645                                       const SMDS_MeshNode * n12)
646 {
647   return SMDS_Mesh::AddVolumeWithID(n1, n2, n3, n4, n5, n6,
648                                     n7, n8, n9, n10, n11, n12,
649                                     myCellFactory->GetFreeID() );
650 }
651
652 ///////////////////////////////////////////////////////////////////////////////
653 ///Create a new hexagonal prism and add it to the mesh.
654 ///@param ID The ID of the new volume
655 ///@return The created prism or NULL if an element with this ID already exists
656 ///or if input nodes are not found.
657 ///////////////////////////////////////////////////////////////////////////////
658
659 SMDS_MeshVolume * SMDS_Mesh::AddVolumeWithID(int idnode1,
660                                              int idnode2,
661                                              int idnode3,
662                                              int idnode4,
663                                              int idnode5,
664                                              int idnode6,
665                                              int idnode7,
666                                              int idnode8,
667                                              int idnode9,
668                                              int idnode10,
669                                              int idnode11,
670                                              int idnode12,
671                                              int ID)
672 {
673   const SMDS_MeshNode *node1 = myNodeFactory->FindNode(idnode1);
674   const SMDS_MeshNode *node2 = myNodeFactory->FindNode(idnode2);
675   const SMDS_MeshNode *node3 = myNodeFactory->FindNode(idnode3);
676   const SMDS_MeshNode *node4 = myNodeFactory->FindNode(idnode4);
677   const SMDS_MeshNode *node5 = myNodeFactory->FindNode(idnode5);
678   const SMDS_MeshNode *node6 = myNodeFactory->FindNode(idnode6);
679   const SMDS_MeshNode *node7 = myNodeFactory->FindNode(idnode7);
680   const SMDS_MeshNode *node8 = myNodeFactory->FindNode(idnode8);
681   const SMDS_MeshNode *node9 = myNodeFactory->FindNode(idnode9);
682   const SMDS_MeshNode *node10 = myNodeFactory->FindNode(idnode10);
683   const SMDS_MeshNode *node11 = myNodeFactory->FindNode(idnode11);
684   const SMDS_MeshNode *node12 = myNodeFactory->FindNode(idnode12);
685   return SMDS_Mesh::AddVolumeWithID(node1, node2, node3, node4, node5, node6,
686                                     node7, node8, node9, node10, node11, node12,
687                                     ID);
688 }
689
690 ///////////////////////////////////////////////////////////////////////////////
691 ///Create a new hexagonal prism and add it to the mesh.
692 ///@param ID The ID of the new volume
693 ///@return The created prism
694 ///////////////////////////////////////////////////////////////////////////////
695
696 SMDS_MeshVolume* SMDS_Mesh::AddVolumeWithID(const SMDS_MeshNode * n1,
697                                             const SMDS_MeshNode * n2,
698                                             const SMDS_MeshNode * n3,
699                                             const SMDS_MeshNode * n4,
700                                             const SMDS_MeshNode * n5,
701                                             const SMDS_MeshNode * n6,
702                                             const SMDS_MeshNode * n7,
703                                             const SMDS_MeshNode * n8,
704                                             const SMDS_MeshNode * n9,
705                                             const SMDS_MeshNode * n10,
706                                             const SMDS_MeshNode * n11,
707                                             const SMDS_MeshNode * n12,
708                                             int ID)
709 {
710   SMDS_MeshVolume* volume = 0;
711   if(!n1 || !n2 || !n3 || !n4 || !n5 || !n6 ||
712      !n7 || !n8 || !n9 || !n10 || !n11 || !n12 )
713     return volume;
714   if ( NbVolumes() % CHECKMEMORY_INTERVAL == 0 ) CheckMemory();
715
716   if ( SMDS_MeshCell* cell = myCellFactory->NewCell( ID ))
717   {
718     cell->init( SMDSEntity_Hexagonal_Prism,
719                 /*nbNodes=*/12, n1, n2, n3, n4, n5, n6, n7, n8, n9, n10, n11, n12 );
720     myInfo.myNbHexPrism++;
721     return static_cast<SMDS_MeshVolume*>( cell );
722   }
723   return 0;
724 }
725
726 ///////////////////////////////////////////////////////////////////////////////
727 ///Create a new hexahedron and add it to the mesh.
728 ///Nodes 1,2,3,4 and 5,6,7,8 are quadrangle and 5,1 and 7,3 are an edges.
729 ///@return The created hexahedron
730 ///////////////////////////////////////////////////////////////////////////////
731
732 SMDS_MeshVolume* SMDS_Mesh::AddVolume(const SMDS_MeshNode * n1,
733                                       const SMDS_MeshNode * n2,
734                                       const SMDS_MeshNode * n3,
735                                       const SMDS_MeshNode * n4,
736                                       const SMDS_MeshNode * n5,
737                                       const SMDS_MeshNode * n6,
738                                       const SMDS_MeshNode * n7,
739                                       const SMDS_MeshNode * n8)
740 {
741   int ID = myCellFactory->GetFreeID();
742   return SMDS_Mesh::AddVolumeWithID(n1, n2, n3, n4, n5, n6, n7, n8, ID);
743 }
744
745 ///////////////////////////////////////////////////////////////////////////////
746 ///Create a new hexahedron and add it to the mesh.
747 ///Nodes 1,2,3,4 and 5,6,7,8 are quadrangle and 5,1 and 7,3 are an edges.
748 ///@param ID The ID of the new volume
749 ///@return The created hexahedron or NULL if an element with this ID already
750 ///exists or if input nodes are not found.
751 ///////////////////////////////////////////////////////////////////////////////
752
753 SMDS_MeshVolume * SMDS_Mesh::AddVolumeWithID(int idnode1,
754                                              int idnode2,
755                                              int idnode3,
756                                              int idnode4,
757                                              int idnode5,
758                                              int idnode6,
759                                              int idnode7,
760                                              int idnode8,
761                                              int ID)
762 {
763   const SMDS_MeshNode *node1, *node2, *node3, *node4, *node5, *node6, *node7, *node8;
764   node1 = myNodeFactory->FindNode(idnode1);
765   node2 = myNodeFactory->FindNode(idnode2);
766   node3 = myNodeFactory->FindNode(idnode3);
767   node4 = myNodeFactory->FindNode(idnode4);
768   node5 = myNodeFactory->FindNode(idnode5);
769   node6 = myNodeFactory->FindNode(idnode6);
770   node7 = myNodeFactory->FindNode(idnode7);
771   node8 = myNodeFactory->FindNode(idnode8);
772   return SMDS_Mesh::AddVolumeWithID(node1, node2, node3, node4, node5, node6,
773                                     node7, node8, ID);
774 }
775
776 ///////////////////////////////////////////////////////////////////////////////
777 ///Create a new hexahedron and add it to the mesh.
778 ///Nodes 1,2,3,4 and 5,6,7,8 are quadrangle and 5,1 and 7,3 are an edges.
779 ///@param ID The ID of the new volume
780 ///@return The created prism or NULL if an element with this ID already exists
781 ///or if input nodes are not found.
782 ///////////////////////////////////////////////////////////////////////////////
783
784 SMDS_MeshVolume* SMDS_Mesh::AddVolumeWithID(const SMDS_MeshNode * n1,
785                                             const SMDS_MeshNode * n2,
786                                             const SMDS_MeshNode * n3,
787                                             const SMDS_MeshNode * n4,
788                                             const SMDS_MeshNode * n5,
789                                             const SMDS_MeshNode * n6,
790                                             const SMDS_MeshNode * n7,
791                                             const SMDS_MeshNode * n8,
792                                             int ID)
793 {
794   SMDS_MeshVolume* volume = 0;
795   if ( !n1 || !n2 || !n3 || !n4 || !n5 || !n6 || !n7 || !n8) return volume;
796   if ( NbVolumes() % CHECKMEMORY_INTERVAL == 0 ) CheckMemory();
797
798   if ( SMDS_MeshCell* cell = myCellFactory->NewCell( ID ))
799   {
800     cell->init( SMDSEntity_Hexa,
801                 /*nbNodes=*/8, n1, n2, n3, n4, n5, n6, n7, n8 );
802     myInfo.myNbHexas++;
803     return static_cast<SMDS_MeshVolume*>( cell );
804   }
805   return 0;
806 }
807
808 ///////////////////////////////////////////////////////////////////////////////
809 /// Add a polygon defined by its nodes IDs
810 ///////////////////////////////////////////////////////////////////////////////
811
812 SMDS_MeshFace* SMDS_Mesh::AddPolygonalFaceWithID (const std::vector<int> & nodes_ids,
813                                                   const int               ID)
814 {
815   int nbNodes = nodes_ids.size();
816   std::vector<const SMDS_MeshNode*> nodes (nbNodes);
817   for (int i = 0; i < nbNodes; i++) {
818     nodes[i] = myNodeFactory->FindNode( nodes_ids[i] );
819     if (!nodes[i]) return NULL;
820   }
821   return SMDS_Mesh::AddPolygonalFaceWithID(nodes, ID);
822 }
823
824 ///////////////////////////////////////////////////////////////////////////////
825 /// Add a polygon defined by its nodes
826 ///////////////////////////////////////////////////////////////////////////////
827
828 SMDS_MeshFace*
829 SMDS_Mesh::AddPolygonalFaceWithID (const std::vector<const SMDS_MeshNode*> & nodes,
830                                    const int                                 ID)
831 {
832   if ( NbFaces() % CHECKMEMORY_INTERVAL == 0 ) CheckMemory();
833
834   if ( SMDS_MeshCell* cell = myCellFactory->NewCell( ID ))
835   {
836     cell->init( SMDSEntity_Polygon, nodes );
837     myInfo.myNbPolygons++;
838     return static_cast<SMDS_MeshFace*>( cell );
839   }
840   return 0;
841 }
842
843 ///////////////////////////////////////////////////////////////////////////////
844 /// Add a polygon defined by its nodes.
845 /// An ID is automatically affected to the created face.
846 ///////////////////////////////////////////////////////////////////////////////
847
848 SMDS_MeshFace* SMDS_Mesh::AddPolygonalFace (const std::vector<const SMDS_MeshNode*> & nodes)
849 {
850   return SMDS_Mesh::AddPolygonalFaceWithID(nodes, myCellFactory->GetFreeID());
851 }
852
853 ///////////////////////////////////////////////////////////////////////////////
854 /// Add a quadratic polygon defined by its nodes IDs
855 ///////////////////////////////////////////////////////////////////////////////
856
857 SMDS_MeshFace* SMDS_Mesh::AddQuadPolygonalFaceWithID (const std::vector<int> & nodes_ids,
858                                                       const int                ID)
859 {
860   std::vector<const SMDS_MeshNode*> nodes( nodes_ids.size() );
861   for ( size_t i = 0; i < nodes.size(); i++) {
862     nodes[i] = myNodeFactory->FindNode(nodes_ids[i]);
863     if (!nodes[i]) return NULL;
864   }
865   return SMDS_Mesh::AddQuadPolygonalFaceWithID(nodes, ID);
866 }
867
868 ///////////////////////////////////////////////////////////////////////////////
869 /// Add a quadratic polygon defined by its nodes
870 ///////////////////////////////////////////////////////////////////////////////
871
872 SMDS_MeshFace*
873 SMDS_Mesh::AddQuadPolygonalFaceWithID (const std::vector<const SMDS_MeshNode*> & nodes,
874                                        const int                                 ID)
875 {
876   if ( NbFaces() % CHECKMEMORY_INTERVAL == 0 ) CheckMemory();
877   if ( SMDS_MeshCell* cell = myCellFactory->NewCell( ID ))
878   {
879     cell->init( SMDSEntity_Quad_Polygon, nodes );
880     myInfo.myNbQuadPolygons++;
881     return static_cast<SMDS_MeshFace*>( cell );
882   }
883   return 0;
884 }
885
886 ///////////////////////////////////////////////////////////////////////////////
887 /// Add a quadratic polygon defined by its nodes.
888 /// An ID is automatically affected to the created face.
889 ///////////////////////////////////////////////////////////////////////////////
890
891 SMDS_MeshFace* SMDS_Mesh::AddQuadPolygonalFace (const std::vector<const SMDS_MeshNode*> & nodes)
892 {
893   return SMDS_Mesh::AddQuadPolygonalFaceWithID(nodes, myCellFactory->GetFreeID());
894 }
895
896 ///////////////////////////////////////////////////////////////////////////////
897 /// Create a new polyhedral volume and add it to the mesh.
898 /// @param ID The ID of the new volume
899 /// @return The created volume or NULL if an element with this ID already exists
900 /// or if input nodes are not found.
901 ///////////////////////////////////////////////////////////////////////////////
902
903 SMDS_MeshVolume * SMDS_Mesh::AddPolyhedralVolumeWithID (const std::vector<int> & nodes_ids,
904                                                         const std::vector<int> & quantities,
905                                                         const int                ID)
906 {
907   int nbNodes = nodes_ids.size();
908   std::vector<const SMDS_MeshNode*> nodes (nbNodes);
909   for (int i = 0; i < nbNodes; i++) {
910     nodes[i] = myNodeFactory->FindNode(nodes_ids[i]);
911     if (!nodes[i]) return NULL;
912   }
913   return SMDS_Mesh::AddPolyhedralVolumeWithID(nodes, quantities, ID);
914 }
915
916 ///////////////////////////////////////////////////////////////////////////////
917 /// Create a new polyhedral volume and add it to the mesh.
918 /// @param ID The ID of the new volume
919 /// @return The created  volume
920 ///////////////////////////////////////////////////////////////////////////////
921
922 SMDS_MeshVolume*
923 SMDS_Mesh::AddPolyhedralVolumeWithID (const std::vector<const SMDS_MeshNode*>& nodes,
924                                       const std::vector<int>                 & quantities,
925                                       const int                           ID)
926 {
927   if ( nodes.empty() || quantities.empty() )
928     return NULL;
929   if ( NbVolumes() % CHECKMEMORY_INTERVAL == 0 ) CheckMemory();
930
931   if ( SMDS_MeshCell* cell = myCellFactory->NewCell( ID ))
932   {
933     SMDS_MeshVolume* volume = static_cast<SMDS_MeshVolume*>( cell );
934     volume->init( nodes, quantities );
935     myInfo.myNbPolyhedrons++;
936     return volume;
937   }
938   return 0;
939 }
940
941 ///////////////////////////////////////////////////////////////////////////////
942 /// Create a new polyhedral volume and add it to the mesh.
943 /// @return The created  volume
944 ///////////////////////////////////////////////////////////////////////////////
945
946 SMDS_MeshVolume* SMDS_Mesh::AddPolyhedralVolume
947 (const std::vector<const SMDS_MeshNode*> & nodes,
948  const std::vector<int>                  & quantities)
949 {
950   int ID = myCellFactory->GetFreeID();
951   return SMDS_Mesh::AddPolyhedralVolumeWithID(nodes, quantities, ID);
952 }
953
954 SMDS_MeshVolume* SMDS_Mesh::AddVolumeFromVtkIds(const std::vector<vtkIdType>& vtkNodeIds)
955 {
956   SMDS_MeshCell*   cell = myCellFactory->NewCell( myCellFactory->GetFreeID() );
957   SMDS_MeshVolume * vol = static_cast<SMDS_MeshVolume*>( cell );
958   vol->init( vtkNodeIds );
959   myInfo.add( cell );
960   return vol;
961 }
962
963 SMDS_MeshFace* SMDS_Mesh::AddFaceFromVtkIds(const std::vector<vtkIdType>& vtkNodeIds)
964 {
965   SMDS_MeshCell* cell = myCellFactory->NewCell( myCellFactory->GetFreeID() );
966   SMDS_MeshFace *   f = static_cast<SMDS_MeshFace*>( cell );
967   f->init( vtkNodeIds );
968   myInfo.add( cell );
969   return f;
970 }
971
972 //=======================================================================
973 //function : MoveNode
974 //purpose  : 
975 //=======================================================================
976
977 void SMDS_Mesh::MoveNode(const SMDS_MeshNode *n, double x, double y, double z)
978 {
979   SMDS_MeshNode * node=const_cast<SMDS_MeshNode*>(n);
980   node->setXYZ(x,y,z);
981 }
982
983 ///////////////////////////////////////////////////////////////////////////////
984 /// Return the node whose SMDS ID is 'ID'.
985 ///////////////////////////////////////////////////////////////////////////////
986 const SMDS_MeshNode * SMDS_Mesh::FindNode(int ID) const
987 {
988   return myNodeFactory->FindNode( ID );
989 }
990
991 ///////////////////////////////////////////////////////////////////////////////
992 /// Return the node whose VTK ID is 'vtkId'.
993 ///////////////////////////////////////////////////////////////////////////////
994 const SMDS_MeshNode * SMDS_Mesh::FindNodeVtk(int vtkId) const
995 {
996   return myNodeFactory->FindNode( vtkId + 1 );
997 }
998
999 const SMDS_MeshElement * SMDS_Mesh::FindElementVtk(int IDelem) const
1000 {
1001   return myCellFactory->FindElement( FromVtkToSmds( IDelem ));
1002 }
1003
1004 ///////////////////////////////////////////////////////////////////////////////
1005 /// Remove a node and all the elements which own this node
1006 ///////////////////////////////////////////////////////////////////////////////
1007
1008 void SMDS_Mesh::RemoveNode(const SMDS_MeshNode * node)
1009 {
1010   RemoveElement(node, true);
1011 }
1012
1013 //=======================================================================
1014 //function : RemoveFromParent
1015 //purpose  :
1016 //=======================================================================
1017
1018 bool SMDS_Mesh::RemoveFromParent()
1019 {
1020   if (myParent==NULL) return false;
1021   else return (myParent->RemoveSubMesh(this));
1022 }
1023
1024 //=======================================================================
1025 //function : RemoveSubMesh
1026 //purpose  :
1027 //=======================================================================
1028
1029 bool SMDS_Mesh::RemoveSubMesh(const SMDS_Mesh * aMesh)
1030 {
1031   bool found = false;
1032
1033   std::list<SMDS_Mesh *>::iterator itmsh=myChildren.begin();
1034   for (; itmsh!=myChildren.end() && !found; itmsh++)
1035   {
1036     SMDS_Mesh * submesh = *itmsh;
1037     if (submesh == aMesh)
1038     {
1039       found = true;
1040       myChildren.erase(itmsh);
1041     }
1042   }
1043
1044   return found;
1045 }
1046
1047 //=======================================================================
1048 //function : ChangeElementNodes
1049 //purpose  :
1050 //=======================================================================
1051
1052 bool SMDS_Mesh::ChangeElementNodes(const SMDS_MeshElement * element,
1053                                    const SMDS_MeshNode    * nodes[],
1054                                    const int                nbnodes)
1055 {
1056   // keep current nodes of element
1057   std::set<const SMDS_MeshNode*> oldNodes( element->begin_nodes(), element->end_nodes() );
1058
1059   // change nodes
1060   bool Ok = false;
1061   if ( SMDS_MeshCell* cell = dynamic_cast<SMDS_MeshCell*>((SMDS_MeshElement*) element))
1062     Ok = cell->ChangeNodes(nodes, nbnodes);
1063
1064   if ( Ok )
1065     setMyModified();
1066
1067   if ( Ok && GetGrid()->HasLinks() ) // update InverseElements
1068   {
1069     std::set<const SMDS_MeshNode*>::iterator it;
1070
1071     // AddInverseElement to new nodes
1072     for ( int i = 0; i < nbnodes; i++ ) {
1073       it = oldNodes.find( nodes[i] );
1074       if ( it == oldNodes.end() )
1075         // new node
1076         const_cast<SMDS_MeshNode*>( nodes[i] )->AddInverseElement( element );
1077       else
1078         // remove from oldNodes a node that remains in elem
1079         oldNodes.erase( it );
1080     }
1081     // RemoveInverseElement from the nodes removed from elem
1082     for ( it = oldNodes.begin(); it != oldNodes.end(); it++ )
1083     {
1084       SMDS_MeshNode * n = const_cast<SMDS_MeshNode *>( *it );
1085       n->RemoveInverseElement( element );
1086     }
1087   }
1088
1089   return Ok;
1090 }
1091
1092 const SMDS_Mesh0DElement* SMDS_Mesh::Find0DElement(const SMDS_MeshNode * node)
1093 {
1094   if (!node) return 0;
1095   const SMDS_Mesh0DElement* toReturn = NULL;
1096   SMDS_ElemIteratorPtr it1 = node->GetInverseElementIterator(SMDSAbs_0DElement);
1097   while (it1->more() && (toReturn == NULL)) {
1098     const SMDS_MeshElement* e = it1->next();
1099     if (e->NbNodes() == 1) {
1100       toReturn = static_cast<const SMDS_Mesh0DElement*>(e);
1101     }
1102   }
1103   return toReturn;
1104 }
1105
1106 const SMDS_BallElement* SMDS_Mesh::FindBall(const SMDS_MeshNode * node)
1107 {
1108   if (!node) return 0;
1109   const SMDS_BallElement* toReturn = NULL;
1110   SMDS_ElemIteratorPtr it1 = node->GetInverseElementIterator(SMDSAbs_Ball);
1111   while (it1->more() && (toReturn == NULL)) {
1112     const SMDS_MeshElement* e = it1->next();
1113     if (e->GetGeomType() == SMDSGeom_BALL)
1114       toReturn = static_cast<const SMDS_BallElement*>(e);
1115   }
1116   return toReturn;
1117 }
1118
1119 const SMDS_MeshEdge* SMDS_Mesh::FindEdge(const SMDS_MeshNode * node1,
1120                                          const SMDS_MeshNode * node2)
1121 {
1122   if ( !node1 ) return 0;
1123   const SMDS_MeshEdge * toReturn=NULL;
1124   SMDS_ElemIteratorPtr it1=node1->GetInverseElementIterator(SMDSAbs_Edge);
1125   while(it1->more()) {
1126     const SMDS_MeshElement * e = it1->next();
1127     if ( e->NbNodes() == 2 && e->GetNodeIndex( node2 ) >= 0 ) {
1128       toReturn = static_cast<const SMDS_MeshEdge*>( e );
1129       break;
1130     }
1131   }
1132   return toReturn;
1133 }
1134
1135 const SMDS_MeshEdge* SMDS_Mesh::FindEdge(const SMDS_MeshNode * node1,
1136                                          const SMDS_MeshNode * node2,
1137                                          const SMDS_MeshNode * node3)
1138 {
1139   if ( !node1 ) return 0;
1140   SMDS_ElemIteratorPtr it1 = node1->GetInverseElementIterator(SMDSAbs_Edge);
1141   while(it1->more()) {
1142     const SMDS_MeshElement * e = it1->next();
1143     if ( e->NbNodes() == 3 ) {
1144       SMDS_ElemIteratorPtr it2 = e->nodesIterator();
1145       while(it2->more()) {
1146         const SMDS_MeshElement* n = it2->next();
1147         if( n!=node1 &&
1148             n!=node2 &&
1149             n!=node3 )
1150         {
1151           e = 0;
1152           break;
1153         }
1154       }
1155       if ( e )
1156         return static_cast<const SMDS_MeshEdge *> (e);
1157     }
1158   }
1159   return 0;
1160 }
1161
1162 //=======================================================================
1163 //function : FindFace
1164 //purpose  :
1165 //=======================================================================
1166
1167 const SMDS_MeshFace* SMDS_Mesh::FindFace(const SMDS_MeshNode *node1,
1168                                          const SMDS_MeshNode *node2,
1169                                          const SMDS_MeshNode *node3)
1170 {
1171   if ( !node1 ) return 0;
1172   SMDS_ElemIteratorPtr it1 = node1->GetInverseElementIterator(SMDSAbs_Face);
1173   while(it1->more()) {
1174     const SMDS_MeshElement * e = it1->next();
1175     if ( e->NbNodes() == 3 ) {
1176       SMDS_ElemIteratorPtr it2 = e->nodesIterator();
1177       while(it2->more()) {
1178         const SMDS_MeshElement* n = it2->next();
1179         if( n!=node1 &&
1180             n!=node2 &&
1181             n!=node3 )
1182         {
1183           e = 0;
1184           break;
1185         }
1186       }
1187       if ( e )
1188         return static_cast<const SMDS_MeshFace *> (e);
1189     }
1190   }
1191   return 0;
1192 }
1193
1194 //=======================================================================
1195 //function : FindFace
1196 //purpose  :
1197 //=======================================================================
1198
1199 const SMDS_MeshFace* SMDS_Mesh::FindFace(const SMDS_MeshNode *node1,
1200                                          const SMDS_MeshNode *node2,
1201                                          const SMDS_MeshNode *node3,
1202                                          const SMDS_MeshNode *node4)
1203 {
1204   if ( !node1 ) return 0;
1205   SMDS_ElemIteratorPtr it1 = node1->GetInverseElementIterator(SMDSAbs_Face);
1206   while(it1->more()) {
1207     const SMDS_MeshElement * e = it1->next();
1208     if ( e->NbNodes() == 4 ) {
1209       SMDS_ElemIteratorPtr it2 = e->nodesIterator();
1210       while(it2->more()) {
1211         const SMDS_MeshElement* n = it2->next();
1212         if( n!=node1 &&
1213             n!=node2 &&
1214             n!=node3 &&
1215             n!=node4 )
1216         {
1217           e = 0;
1218           break;
1219         }
1220       }
1221       if ( e )
1222         return static_cast<const SMDS_MeshFace *> (e);
1223     }
1224   }
1225   return 0;
1226 }
1227
1228 //=======================================================================
1229 //function : FindFace
1230 //purpose  :quadratic triangle
1231 //=======================================================================
1232
1233 const SMDS_MeshFace* SMDS_Mesh::FindFace(const SMDS_MeshNode *node1,
1234                                          const SMDS_MeshNode *node2,
1235                                          const SMDS_MeshNode *node3,
1236                                          const SMDS_MeshNode *node4,
1237                                          const SMDS_MeshNode *node5,
1238                                          const SMDS_MeshNode *node6)
1239 {
1240   if ( !node1 ) return 0;
1241   SMDS_ElemIteratorPtr it1 = node1->GetInverseElementIterator(SMDSAbs_Face);
1242   while(it1->more()) {
1243     const SMDS_MeshElement * e = it1->next();
1244     if ( e->NbNodes() == 6 ) {
1245       SMDS_ElemIteratorPtr it2 = e->nodesIterator();
1246       while(it2->more()) {
1247         const SMDS_MeshElement* n = it2->next();
1248         if( n!=node1 &&
1249             n!=node2 &&
1250             n!=node3 &&
1251             n!=node4 &&
1252             n!=node5 &&
1253             n!=node6 )
1254         {
1255           e = 0;
1256           break;
1257         }
1258       }
1259       if ( e )
1260         return static_cast<const SMDS_MeshFace *> (e);
1261     }
1262   }
1263   return 0;
1264 }
1265
1266
1267 //=======================================================================
1268 //function : FindFace
1269 //purpose  : quadratic quadrangle
1270 //=======================================================================
1271
1272 const SMDS_MeshFace* SMDS_Mesh::FindFace(const SMDS_MeshNode *node1,
1273                                          const SMDS_MeshNode *node2,
1274                                          const SMDS_MeshNode *node3,
1275                                          const SMDS_MeshNode *node4,
1276                                          const SMDS_MeshNode *node5,
1277                                          const SMDS_MeshNode *node6,
1278                                          const SMDS_MeshNode *node7,
1279                                          const SMDS_MeshNode *node8)
1280 {
1281   if ( !node1 ) return 0;
1282   SMDS_ElemIteratorPtr it1 = node1->GetInverseElementIterator(SMDSAbs_Face);
1283   while(it1->more()) {
1284     const SMDS_MeshElement * e = it1->next();
1285     if ( e->NbNodes() == 8 ) {
1286       SMDS_ElemIteratorPtr it2 = e->nodesIterator();
1287       while(it2->more()) {
1288         const SMDS_MeshElement* n = it2->next();
1289         if( n!=node1 &&
1290             n!=node2 &&
1291             n!=node3 &&
1292             n!=node4 &&
1293             n!=node5 &&
1294             n!=node6 &&
1295             n!=node7 &&
1296             n!=node8 )
1297         {
1298           e = 0;
1299           break;
1300         }
1301       }
1302       if ( e )
1303         return static_cast<const SMDS_MeshFace *> (e);
1304     }
1305   }
1306   return 0;
1307 }
1308
1309
1310 //=======================================================================
1311 //function : FindElement
1312 //purpose  :
1313 //=======================================================================
1314
1315 const SMDS_MeshElement* SMDS_Mesh::FindElement(int IDelem) const
1316 {
1317   return myCellFactory->FindElement( IDelem );
1318 }
1319
1320 //=======================================================================
1321 //function : FindFace
1322 //purpose  : find polygon
1323 //=======================================================================
1324
1325
1326 const SMDS_MeshFace* SMDS_Mesh::FindFace (const std::vector<const SMDS_MeshNode *>& nodes)
1327 {
1328   return (const SMDS_MeshFace*) FindElement( nodes, SMDSAbs_Face );
1329 }
1330
1331
1332 //================================================================================
1333 /*!
1334  * \brief Return element based on all given nodes
1335  *  \param nodes - node of element
1336  *  \param type - type of element
1337  *  \param noMedium - true if medium nodes of quadratic element are not included in <nodes>
1338  *  \retval const SMDS_MeshElement* - found element or NULL
1339  */
1340 //================================================================================
1341
1342 const SMDS_MeshElement* SMDS_Mesh::FindElement (const std::vector<const SMDS_MeshNode *>& nodes,
1343                                                 const SMDSAbs_ElementType            type,
1344                                                 const bool                           noMedium)
1345 {
1346   if ( nodes.size() > 0 && nodes[0] )
1347   {
1348     SMDS_ElemIteratorPtr itF = nodes[0]->GetInverseElementIterator(type);
1349     while (itF->more())
1350     {
1351       const SMDS_MeshElement* e = itF->next();
1352       int nbNodesToCheck = noMedium ? e->NbCornerNodes() : e->NbNodes();
1353       if ( nbNodesToCheck == (int)nodes.size() )
1354       {
1355         for ( size_t i = 1; e && i < nodes.size(); ++i )
1356         {
1357           int nodeIndex = e->GetNodeIndex( nodes[ i ]);
1358           if ( nodeIndex < 0 || nodeIndex >= nbNodesToCheck )
1359             e = 0;
1360         }
1361         if ( e )
1362           return e;
1363       }
1364     }
1365   }
1366   return NULL;
1367 }
1368
1369 //================================================================================
1370 /*!
1371  * \brief Return elements including all given nodes
1372  *  \param [in] nodes - nodes to find elements around
1373  *  \param [out] foundElems - the found elements
1374  *  \param [in] type - type of elements to find
1375  *  \return int - a number of found elements
1376  */
1377 //================================================================================
1378
1379 int SMDS_Mesh::GetElementsByNodes(const std::vector<const SMDS_MeshNode *>& nodes,
1380                                   std::vector<const SMDS_MeshElement *>&    foundElems,
1381                                   const SMDSAbs_ElementType                 type)
1382 {
1383   // chose a node with minimal number of inverse elements
1384   const SMDS_MeshNode* n0 = nodes[0];
1385   int minNbInverse = n0 ? n0->NbInverseElements( type ) : 1000;
1386   for ( size_t i = 1; i < nodes.size(); ++i )
1387     if ( nodes[i] && nodes[i]->NbInverseElements( type ) < minNbInverse )
1388     {
1389       n0 = nodes[i];
1390       minNbInverse = n0->NbInverseElements( type );
1391     }
1392
1393   foundElems.clear();
1394   if ( n0 )
1395   {
1396     foundElems.reserve( minNbInverse );
1397     SMDS_ElemIteratorPtr eIt = n0->GetInverseElementIterator( type );
1398     while ( eIt->more() )
1399     {
1400       const SMDS_MeshElement* e = eIt->next();
1401       bool includeAll = true;
1402       for ( size_t i = 0; i < nodes.size() &&  includeAll; ++i )
1403         if ( nodes[i] != n0 && e->GetNodeIndex( nodes[i] ) < 0 )
1404           includeAll = false;
1405       if ( includeAll )
1406         foundElems.push_back( e );
1407     }
1408   }
1409   return foundElems.size();
1410 }
1411
1412 ///////////////////////////////////////////////////////////////////////////////
1413 /// Return the number of nodes
1414 ///////////////////////////////////////////////////////////////////////////////
1415 int SMDS_Mesh::NbNodes() const
1416 {
1417   return myInfo.NbNodes();
1418 }
1419
1420 ///////////////////////////////////////////////////////////////////////////////
1421 /// Return the number of elements
1422 ///////////////////////////////////////////////////////////////////////////////
1423 int SMDS_Mesh::NbElements() const
1424 {
1425   return myInfo.NbElements();
1426 }
1427 ///////////////////////////////////////////////////////////////////////////////
1428 /// Return the number of 0D elements
1429 ///////////////////////////////////////////////////////////////////////////////
1430 int SMDS_Mesh::Nb0DElements() const
1431 {
1432   return myInfo.Nb0DElements();
1433 }
1434
1435 ///////////////////////////////////////////////////////////////////////////////
1436 /// Return the number of 0D elements
1437 ///////////////////////////////////////////////////////////////////////////////
1438 int SMDS_Mesh::NbBalls() const
1439 {
1440   return myInfo.NbBalls();
1441 }
1442
1443 ///////////////////////////////////////////////////////////////////////////////
1444 /// Return the number of edges (including construction edges)
1445 ///////////////////////////////////////////////////////////////////////////////
1446 int SMDS_Mesh::NbEdges() const
1447 {
1448   return myInfo.NbEdges();
1449 }
1450
1451 ///////////////////////////////////////////////////////////////////////////////
1452 /// Return the number of faces (including construction faces)
1453 ///////////////////////////////////////////////////////////////////////////////
1454 int SMDS_Mesh::NbFaces() const
1455 {
1456   return myInfo.NbFaces();
1457 }
1458
1459 ///////////////////////////////////////////////////////////////////////////////
1460 /// Return the number of volumes
1461 ///////////////////////////////////////////////////////////////////////////////
1462 int SMDS_Mesh::NbVolumes() const
1463 {
1464   return myInfo.NbVolumes();
1465 }
1466
1467 ///////////////////////////////////////////////////////////////////////////////
1468 /// Return the number of child mesh of this mesh.
1469 /// Note that the tree structure of SMDS_Mesh is unused in SMESH
1470 ///////////////////////////////////////////////////////////////////////////////
1471 int SMDS_Mesh::NbSubMesh() const
1472 {
1473   return myChildren.size();
1474 }
1475
1476 ///////////////////////////////////////////////////////////////////////////////
1477 /// Destroy the mesh and all its elements
1478 /// All pointer on elements owned by this mesh become illegals.
1479 ///////////////////////////////////////////////////////////////////////////////
1480 SMDS_Mesh::~SMDS_Mesh()
1481 {
1482   std::list<SMDS_Mesh*>::iterator itc=myChildren.begin();
1483   while(itc!=myChildren.end())
1484   {
1485     delete *itc;
1486     itc++;
1487   }
1488
1489   delete myNodeFactory;
1490   delete myCellFactory;
1491
1492   myGrid->Delete();
1493 }
1494
1495 //================================================================================
1496 /*!
1497  * \brief Clear all data
1498  */
1499 //================================================================================
1500
1501 void SMDS_Mesh::Clear()
1502 {
1503   std::set< SMDS_ElementHolder* >::iterator holder = myElemHolders.begin();
1504   for ( ; holder != myElemHolders.end(); ++holder )
1505     (*holder)->clear();
1506
1507   myNodeFactory->Clear();
1508   myCellFactory->Clear();
1509
1510   std::list<SMDS_Mesh*>::iterator itc=myChildren.begin();
1511   while(itc!=myChildren.end())
1512     (*itc)->Clear();
1513
1514   myModified = false;
1515   myModifTime++;
1516   xmin = 0; xmax = 0;
1517   ymin = 0; ymax = 0;
1518   zmin = 0; zmax = 0;
1519
1520   myInfo.Clear();
1521
1522   myGrid->Initialize();
1523   myGrid->Allocate();
1524   vtkPoints* points = vtkPoints::New();
1525   // rnv: to fix bug "21125: EDF 1233 SMESH: Degrardation of precision in a test case for quadratic conversion"
1526   // using double type for storing coordinates of nodes instead float.
1527   points->SetDataType(VTK_DOUBLE);
1528   points->SetNumberOfPoints( 0 );
1529   myGrid->SetPoints( points );
1530   points->Delete();
1531   myGrid->DeleteLinks();
1532 }
1533
1534 ///////////////////////////////////////////////////////////////////////////////
1535 /// Return an iterator on nodes of the current mesh factory
1536 ///////////////////////////////////////////////////////////////////////////////
1537
1538 SMDS_NodeIteratorPtr SMDS_Mesh::nodesIterator() const
1539 {
1540   return myNodeFactory->GetIterator< SMDS_NodeIterator >( new SMDS_MeshElement::NonNullFilter );
1541 }
1542
1543 SMDS_ElemIteratorPtr SMDS_Mesh::elementGeomIterator(SMDSAbs_GeometryType type) const
1544 {
1545   return myCellFactory->GetIterator< SMDS_ElemIterator >( new SMDS_MeshElement::GeomFilter( type ),
1546                                                           myInfo.NbElements( type ));
1547 }
1548
1549 SMDS_ElemIteratorPtr SMDS_Mesh::elementEntityIterator(SMDSAbs_EntityType type) const
1550 {
1551   if ( type == SMDSEntity_Node )
1552   {
1553     return myNodeFactory->GetIterator< SMDS_ElemIterator >( new SMDS_MeshElement::NonNullFilter );
1554   }
1555   return myCellFactory->GetIterator<SMDS_ElemIterator>( new SMDS_MeshElement::EntityFilter( type ),
1556                                                         myInfo.NbElements( type ));
1557 }
1558
1559 ///////////////////////////////////////////////////////////////////////////////
1560 /// Return an iterator on elements of the current mesh factory
1561 ///////////////////////////////////////////////////////////////////////////////
1562 SMDS_ElemIteratorPtr SMDS_Mesh::elementsIterator(SMDSAbs_ElementType type) const
1563 {
1564   typedef SMDS_ElemIterator TIterator;
1565   switch ( type ) {
1566
1567   case SMDSAbs_All:
1568     return myCellFactory->GetIterator< TIterator >( new SMDS_MeshElement::NonNullFilter );
1569
1570   case SMDSAbs_Node:
1571     return myNodeFactory->GetIterator< TIterator >( new SMDS_MeshElement::NonNullFilter );
1572
1573   default:
1574     return myCellFactory->GetIterator< TIterator >( new SMDS_MeshElement::TypeFilter( type ),
1575                                                     myInfo.NbElements( type ));
1576   }
1577   return SMDS_ElemIteratorPtr();
1578 }
1579
1580 ///////////////////////////////////////////////////////////////////////////////
1581 ///Return an iterator on edges of the current mesh.
1582 ///////////////////////////////////////////////////////////////////////////////
1583
1584 SMDS_EdgeIteratorPtr SMDS_Mesh::edgesIterator() const
1585 {
1586   typedef SMDS_EdgeIterator TIterator;
1587   return myCellFactory->GetIterator< TIterator >( new SMDS_MeshElement::TypeFilter( SMDSAbs_Edge ),
1588                                                   myInfo.NbEdges());
1589 }
1590
1591 ///////////////////////////////////////////////////////////////////////////////
1592 ///Return an iterator on faces of the current mesh.
1593 ///////////////////////////////////////////////////////////////////////////////
1594
1595 SMDS_FaceIteratorPtr SMDS_Mesh::facesIterator() const
1596 {
1597   typedef SMDS_FaceIterator TIterator;
1598   return myCellFactory->GetIterator< TIterator >( new SMDS_MeshElement::TypeFilter( SMDSAbs_Face ),
1599                                                   myInfo.NbFaces());
1600 }
1601
1602 ///////////////////////////////////////////////////////////////////////////////
1603 ///Return an iterator on volumes of the current mesh.
1604 ///////////////////////////////////////////////////////////////////////////////
1605
1606 SMDS_VolumeIteratorPtr SMDS_Mesh::volumesIterator() const
1607 {
1608   typedef SMDS_VolumeIterator TIterator;
1609   return
1610     myCellFactory->GetIterator< TIterator >( new SMDS_MeshElement::TypeFilter( SMDSAbs_Volume ),
1611                                              myInfo.NbVolumes());
1612 }
1613
1614 SMDS_NodeIteratorPtr SMDS_Mesh::shapeNodesIterator(int shapeID, size_t nbElemsToReturn) const
1615 {
1616   return myNodeFactory->GetShapeIterator< SMDS_NodeIterator >( shapeID, nbElemsToReturn );
1617 }
1618
1619 SMDS_ElemIteratorPtr SMDS_Mesh::shapeElementsIterator(int shapeID, size_t nbElemsToReturn) const
1620 {
1621   return myCellFactory->GetShapeIterator< SMDS_ElemIterator >( shapeID, nbElemsToReturn );
1622 }
1623
1624 ///////////////////////////////////////////////////////////////////////////////
1625 /// Do intersection of sets (more than 2)
1626 ///////////////////////////////////////////////////////////////////////////////
1627 static std::set<const SMDS_MeshElement*> *
1628 intersectionOfSets( std::set<const SMDS_MeshElement*> vs[], int numberOfSets )
1629 {
1630   std::set<const SMDS_MeshElement*>* rsetA = new std::set<const SMDS_MeshElement*>(vs[0]);
1631   std::set<const SMDS_MeshElement*>* rsetB;
1632
1633   for(int i=0; i<numberOfSets-1; i++)
1634   {
1635     rsetB = new std::set<const SMDS_MeshElement*>();
1636     set_intersection(rsetA->begin(), rsetA->end(),
1637                      vs[i+1].begin(), vs[i+1].end(),
1638                      inserter(*rsetB, rsetB->begin()));
1639     delete rsetA;
1640     rsetA=rsetB;
1641   }
1642   return rsetA;
1643 }
1644 ///////////////////////////////////////////////////////////////////////////////
1645 /// Return the list of finite elements owning the given element: elements
1646 /// containing all the nodes of the given element, for instance faces and
1647 /// volumes containing a given edge.
1648 ///////////////////////////////////////////////////////////////////////////////
1649 static std::set<const SMDS_MeshElement*> * getFinitElements(const SMDS_MeshElement * element)
1650 {
1651   int numberOfSets=element->NbNodes();
1652   std::set<const SMDS_MeshElement*> *initSet = new std::set<const SMDS_MeshElement*>[numberOfSets];
1653
1654   SMDS_NodeIteratorPtr itNodes = element->nodeIterator();
1655
1656   int i = 0;
1657   while ( itNodes->more() )
1658   {
1659     const SMDS_MeshNode *   n = itNodes->next();
1660     for ( SMDS_ElemIteratorPtr itFe = n->GetInverseElementIterator(); itFe->more(); )
1661       initSet[i].insert( itFe->next() );
1662     i++;
1663   }
1664   std::set<const SMDS_MeshElement*> *retSet = intersectionOfSets( initSet, numberOfSets );
1665   delete [] initSet;
1666   return retSet;
1667 }
1668
1669 ///////////////////////////////////////////////////////////////////////////////
1670 /// Return the std::list of nodes used only by the given elements
1671 ///////////////////////////////////////////////////////////////////////////////
1672 static
1673 std::set<const SMDS_MeshElement*> *getExclusiveNodes(std::set<const SMDS_MeshElement*>& elements)
1674 {
1675   std::set<const SMDS_MeshElement*> *           toReturn = new std::set<const SMDS_MeshElement*>();
1676   std::set<const SMDS_MeshElement*>::iterator itElements = elements.begin();
1677
1678   while( itElements != elements.end() )
1679   {
1680     SMDS_NodeIteratorPtr itNodes = (*itElements)->nodeIterator();
1681     itElements++;
1682
1683     while( itNodes->more() )
1684     {
1685       const SMDS_MeshNode *   n = itNodes->next();
1686       SMDS_ElemIteratorPtr itFe = n->GetInverseElementIterator();
1687       std::set<const SMDS_MeshElement*> s;
1688       while ( itFe->more() )
1689         s.insert( itFe->next() );
1690       if ( s == elements ) toReturn->insert(n);
1691     }
1692   }
1693   return toReturn;
1694 }
1695
1696 ///////////////////////////////////////////////////////////////////////////////
1697 ///Find the children of an element that are made of given nodes
1698 ///@param setOfChildren The set in which matching children will be inserted
1699 ///@param element The element were to search matching children
1700 ///@param nodes The nodes that the children must have to be selected
1701 ///////////////////////////////////////////////////////////////////////////////
1702 void SMDS_Mesh::addChildrenWithNodes(std::set<const SMDS_MeshElement*>& setOfChildren,
1703                                      const SMDS_MeshElement *           element,
1704                                      std::set<const SMDS_MeshElement*>& nodes)
1705 {
1706   switch(element->GetType())
1707   {
1708   case SMDSAbs_Node:
1709     throw SALOME_Exception("Internal Error: This should not happen");
1710     break;
1711   case SMDSAbs_0DElement:
1712   case SMDSAbs_Ball:
1713   {
1714   }
1715   break;
1716   case SMDSAbs_Edge:
1717   {
1718     SMDS_ElemIteratorPtr itn=element->nodesIterator();
1719     while(itn->more())
1720     {
1721       const SMDS_MeshElement * e=itn->next();
1722       if(nodes.find(e)!=nodes.end())
1723       {
1724         setOfChildren.insert(element);
1725         break;
1726       }
1727     }
1728   } break;
1729   case SMDSAbs_Face:
1730   {
1731     SMDS_ElemIteratorPtr itn=element->nodesIterator();
1732     while(itn->more())
1733     {
1734       const SMDS_MeshElement * e=itn->next();
1735       if(nodes.find(e)!=nodes.end())
1736       {
1737         setOfChildren.insert(element);
1738         break;
1739       }
1740     }
1741   } break;
1742   case SMDSAbs_Volume:
1743   case SMDSAbs_NbElementTypes:
1744   case SMDSAbs_All: break;
1745   }
1746 }
1747
1748 ///////////////////////////////////////////////////////////////////////////////
1749 ///@param elem The element to delete
1750 ///@param removenodes if true remaining nodes will be removed
1751 ///////////////////////////////////////////////////////////////////////////////
1752 void SMDS_Mesh::RemoveElement(const SMDS_MeshElement * elem,
1753                               const bool               removenodes)
1754 {
1755   std::vector<const SMDS_MeshElement *> removedElems;
1756   std::vector<const SMDS_MeshElement *> removedNodes;
1757   RemoveElement( elem, removedElems, removedNodes, removenodes );
1758 }
1759
1760 ///////////////////////////////////////////////////////////////////////////////
1761 ///@param elem The element to delete
1762 ///@param removedElems to be filled with all removed elements
1763 ///@param removedNodes to be filled with all removed nodes
1764 ///@param removenodes if true remaining nodes will be removed
1765 ///////////////////////////////////////////////////////////////////////////////
1766 void SMDS_Mesh::RemoveElement(const SMDS_MeshElement *               elem,
1767                               std::vector<const SMDS_MeshElement *>& removedElems,
1768                               std::vector<const SMDS_MeshElement *>& removedNodes,
1769                               bool                                   removenodes)
1770 {
1771   // get finite elements built on elem
1772   std::set<const SMDS_MeshElement*> * s1;
1773   if (    (elem->GetType() == SMDSAbs_0DElement)
1774           ||  (elem->GetType() == SMDSAbs_Ball)
1775           ||  (elem->GetType() == SMDSAbs_Edge)
1776           ||  (elem->GetType() == SMDSAbs_Face)
1777           ||  (elem->GetType() == SMDSAbs_Volume) )
1778   {
1779     s1 = new std::set<const SMDS_MeshElement*> ();
1780     s1->insert(elem);
1781   }
1782   else
1783     s1 = getFinitElements(elem);
1784
1785   // get exclusive nodes (which would become free afterwards)
1786   std::set<const SMDS_MeshElement*> * s2;
1787   if (elem->GetType() == SMDSAbs_Node) // a node is removed
1788   {
1789     // do not remove nodes except elem
1790     s2 = new std::set<const SMDS_MeshElement*> ();
1791     s2->insert(elem);
1792     removenodes = true;
1793   }
1794   else
1795     s2 = getExclusiveNodes(*s1);
1796
1797   // form the set of finite and construction elements to remove
1798   std::set<const SMDS_MeshElement*> s3;
1799   std::set<const SMDS_MeshElement*>::iterator it = s1->begin();
1800   while (it != s1->end())
1801   {
1802     addChildrenWithNodes(s3, *it, *s2);
1803     s3.insert(*it);
1804     it++;
1805   }
1806   if (elem->GetType() != SMDSAbs_Node)
1807     s3.insert(elem);
1808
1809   // remove finite and construction elements
1810   for( it = s3.begin();it != s3.end(); ++it )
1811   {
1812     // Remove element from <InverseElements> of its nodes
1813     SMDS_NodeIteratorPtr itn = (*it)->nodeIterator();
1814     while (itn->more())
1815     {
1816       SMDS_MeshNode * n = const_cast<SMDS_MeshNode *> (itn->next());
1817       n->RemoveInverseElement((*it));
1818     }
1819
1820     int vtkid = (*it)->GetVtkID();
1821
1822     switch ((*it)->GetType()) {
1823     case SMDSAbs_Node:
1824       throw SALOME_Exception(LOCALIZED("Internal Error: This should not happen"));
1825       break;
1826     case SMDSAbs_Edge:      myInfo.RemoveEdge(*it);   break;
1827     case SMDSAbs_Face:      myInfo.RemoveFace(*it);   break;
1828     case SMDSAbs_Volume:    myInfo.RemoveVolume(*it); break;
1829     case SMDSAbs_Ball:      myInfo.myNbBalls--;       break;
1830     case SMDSAbs_0DElement: myInfo.myNb0DElements--;  break;
1831     case SMDSAbs_All: // avoid compilation warning
1832     case SMDSAbs_NbElementTypes: break;
1833     }
1834
1835     myCellFactory->Free( static_cast< const SMDS_MeshCell*>( *it ));
1836
1837     if (vtkid >= 0)
1838     {
1839       this->myGrid->GetCellTypesArray()->SetValue(vtkid, VTK_EMPTY_CELL);
1840     }
1841   }
1842
1843   // remove exclusive (free) nodes
1844   if (removenodes)
1845   {
1846     for ( it = s2->begin(); it != s2->end(); ++it )
1847     {
1848       myInfo.myNbNodes--;
1849       myNodeFactory->Free( (*it) );
1850       removedNodes.push_back((*it));
1851     }
1852   }
1853
1854   delete s2;
1855   delete s1;
1856 }
1857
1858
1859 ///////////////////////////////////////////////////////////////////////////////
1860 ///@param elem The element to delete
1861 ///////////////////////////////////////////////////////////////////////////////
1862 void SMDS_Mesh::RemoveFreeElement(const SMDS_MeshElement * elem)
1863 {
1864   const int           vtkId = elem->GetVtkID();
1865   SMDSAbs_ElementType aType = elem->GetType();
1866   if ( aType == SMDSAbs_Node )
1867   {
1868     // only free node can be removed by this method
1869     const SMDS_MeshNode* n = static_cast<const SMDS_MeshNode*>( elem );
1870     if ( n->NbInverseElements() == 0 ) { // free node
1871       myInfo.myNbNodes--;
1872       myNodeFactory->Free( n );
1873     }
1874     else
1875     {
1876       throw SALOME_Exception( LOCALIZED( "RemoveFreeElement: not a free node" ));
1877     }
1878   }
1879   else
1880   {
1881     // Remove element from <InverseElements> of its nodes
1882     SMDS_NodeIteratorPtr itn = elem->nodeIterator();
1883     while (itn->more()) {
1884       SMDS_MeshNode * n = const_cast<SMDS_MeshNode *>(itn->next());
1885       n->RemoveInverseElement(elem);
1886     }
1887
1888     // in meshes without descendants elements are always free
1889     switch (aType) {
1890     case SMDSAbs_0DElement: myInfo.remove(elem);       break;
1891     case SMDSAbs_Edge:      myInfo.RemoveEdge(elem);   break;
1892     case SMDSAbs_Face:      myInfo.RemoveFace(elem);   break;
1893     case SMDSAbs_Volume:    myInfo.RemoveVolume(elem); break;
1894     case SMDSAbs_Ball:      myInfo.remove(elem);       break;
1895     default: break;
1896     }
1897     myCellFactory->Free( elem );
1898
1899     this->myGrid->GetCellTypesArray()->SetValue(vtkId, VTK_EMPTY_CELL);
1900   }
1901 }
1902
1903 //=======================================================================
1904 /*!
1905  * Checks if the element is present in mesh.
1906  */
1907 //=======================================================================
1908
1909 bool SMDS_Mesh::Contains (const SMDS_MeshElement* elem) const
1910 {
1911   if ( !elem || elem->IsNull() )
1912     return false;
1913
1914   if ( elem->GetType() == SMDSAbs_Node )
1915     return ( elem == myNodeFactory->FindElement( elem->GetID() ));
1916
1917   return ( elem == myCellFactory->FindElement( elem->GetID() ));
1918 }
1919
1920 //=======================================================================
1921 //function : MaxNodeID
1922 //purpose  :
1923 //=======================================================================
1924
1925 int SMDS_Mesh::MaxNodeID() const
1926 {
1927   return myNodeFactory->GetMaxID();
1928 }
1929
1930 //=======================================================================
1931 //function : MinNodeID
1932 //purpose  :
1933 //=======================================================================
1934
1935 int SMDS_Mesh::MinNodeID() const
1936 {
1937   return myNodeFactory->GetMinID();
1938 }
1939
1940 //=======================================================================
1941 //function : MaxElementID
1942 //purpose  :
1943 //=======================================================================
1944
1945 int SMDS_Mesh::MaxElementID() const
1946 {
1947   return myCellFactory->GetMaxID();
1948 }
1949
1950 //=======================================================================
1951 //function : MinElementID
1952 //purpose  :
1953 //=======================================================================
1954
1955 int SMDS_Mesh::MinElementID() const
1956 {
1957   return myCellFactory->GetMinID();
1958 }
1959
1960 //=======================================================================
1961 //function : Renumber
1962 //purpose  : Renumber all nodes or elements.
1963 //=======================================================================
1964
1965 // void SMDS_Mesh::Renumber (const bool isNodes, const int  startID, const int  deltaID)
1966 // {
1967 //   if ( deltaID == 0 )
1968 //     return;
1969
1970 // }
1971
1972 //=======================================================================
1973 //function : GetElementType
1974 //purpose  : Return type of element or node with id
1975 //=======================================================================
1976
1977 SMDSAbs_ElementType SMDS_Mesh::GetElementType( const int id, const bool iselem ) const
1978 {
1979   const SMDS_MeshElement* elem = 0;
1980   if( iselem )
1981     elem = myCellFactory->FindElement( id );
1982   else
1983     elem = myNodeFactory->FindElement( id );
1984
1985   return elem ? elem->GetType() : SMDSAbs_All;
1986 }
1987
1988
1989
1990 //********************************************************************
1991 //********************************************************************
1992 //********                                                   *********
1993 //*****       Methods for addition of quadratic elements        ******
1994 //********                                                   *********
1995 //********************************************************************
1996 //********************************************************************
1997
1998 //=======================================================================
1999 //function : AddEdgeWithID
2000 //purpose  :
2001 //=======================================================================
2002 SMDS_MeshEdge* SMDS_Mesh::AddEdgeWithID(int n1, int n2, int n12, int ID)
2003 {
2004   return SMDS_Mesh::AddEdgeWithID (myNodeFactory->FindNode(n1),
2005                                    myNodeFactory->FindNode(n2),
2006                                    myNodeFactory->FindNode(n12),
2007                                    ID);
2008 }
2009
2010 //=======================================================================
2011 //function : AddEdge
2012 //purpose  :
2013 //=======================================================================
2014 SMDS_MeshEdge* SMDS_Mesh::AddEdge(const SMDS_MeshNode* n1,
2015                                   const SMDS_MeshNode* n2,
2016                                   const SMDS_MeshNode* n12)
2017 {
2018   return SMDS_Mesh::AddEdgeWithID(n1, n2, n12, myCellFactory->GetFreeID());
2019 }
2020
2021 //=======================================================================
2022 //function : AddEdgeWithID
2023 //purpose  :
2024 //=======================================================================
2025 SMDS_MeshEdge* SMDS_Mesh::AddEdgeWithID(const SMDS_MeshNode * n1,
2026                                         const SMDS_MeshNode * n2,
2027                                         const SMDS_MeshNode * n12,
2028                                         int                   ID)
2029 {
2030   if ( !n1 || !n2 || !n12 ) return 0;
2031
2032   if ( SMDS_MeshCell* cell = myCellFactory->NewCell( ID ))
2033   {
2034     cell->init( SMDSEntity_Quad_Edge, /*nbNodes=*/3, n1, n2, n12 );
2035     myInfo.myNbQuadEdges++;
2036     return static_cast<SMDS_MeshEdge*>( cell );
2037   }
2038   return 0;
2039 }
2040
2041
2042 //=======================================================================
2043 //function : AddFace
2044 //purpose  :
2045 //=======================================================================
2046 SMDS_MeshFace* SMDS_Mesh::AddFace(const SMDS_MeshNode * n1,
2047                                   const SMDS_MeshNode * n2,
2048                                   const SMDS_MeshNode * n3,
2049                                   const SMDS_MeshNode * n12,
2050                                   const SMDS_MeshNode * n23,
2051                                   const SMDS_MeshNode * n31)
2052 {
2053   return SMDS_Mesh::AddFaceWithID(n1,n2,n3,n12,n23,n31,
2054                                   myCellFactory->GetFreeID());
2055 }
2056
2057 //=======================================================================
2058 //function : AddFaceWithID
2059 //purpose  :
2060 //=======================================================================
2061 SMDS_MeshFace* SMDS_Mesh::AddFaceWithID(int n1, int n2, int n3,
2062                                         int n12,int n23,int n31, int ID)
2063 {
2064   return SMDS_Mesh::AddFaceWithID (myNodeFactory->FindNode(n1) ,
2065                                    myNodeFactory->FindNode(n2) ,
2066                                    myNodeFactory->FindNode(n3) ,
2067                                    myNodeFactory->FindNode(n12),
2068                                    myNodeFactory->FindNode(n23),
2069                                    myNodeFactory->FindNode(n31),
2070                                    ID);
2071 }
2072
2073 //=======================================================================
2074 //function : AddFaceWithID
2075 //purpose  :
2076 //=======================================================================
2077 SMDS_MeshFace* SMDS_Mesh::AddFaceWithID(const SMDS_MeshNode * n1,
2078                                         const SMDS_MeshNode * n2,
2079                                         const SMDS_MeshNode * n3,
2080                                         const SMDS_MeshNode * n12,
2081                                         const SMDS_MeshNode * n23,
2082                                         const SMDS_MeshNode * n31,
2083                                         int ID)
2084 {
2085   if ( !n1 || !n2 || !n3 || !n12 || !n23 || !n31 ) return 0;
2086   if ( NbFaces() % CHECKMEMORY_INTERVAL == 0 ) CheckMemory();
2087
2088   if ( SMDS_MeshCell* cell = myCellFactory->NewCell( ID ))
2089   {
2090     cell->init( SMDSEntity_Quad_Triangle, /*nbNodes=*/6, n1, n2, n3, n12, n23, n31 );
2091     myInfo.myNbQuadTriangles++;
2092     return static_cast<SMDS_MeshFace*>( cell );
2093   }
2094   return 0;
2095 }
2096
2097
2098 //=======================================================================
2099 //function : AddFace
2100 //purpose  :
2101 //=======================================================================
2102 SMDS_MeshFace* SMDS_Mesh::AddFace(const SMDS_MeshNode * n1,
2103                                   const SMDS_MeshNode * n2,
2104                                   const SMDS_MeshNode * n3,
2105                                   const SMDS_MeshNode * n12,
2106                                   const SMDS_MeshNode * n23,
2107                                   const SMDS_MeshNode * n31,
2108                                   const SMDS_MeshNode * nCenter)
2109 {
2110   return SMDS_Mesh::AddFaceWithID(n1,n2,n3,n12,n23,n31,nCenter,
2111                                   myCellFactory->GetFreeID());
2112 }
2113
2114 //=======================================================================
2115 //function : AddFaceWithID
2116 //purpose  :
2117 //=======================================================================
2118 SMDS_MeshFace* SMDS_Mesh::AddFaceWithID(int n1, int n2, int n3,
2119                                         int n12,int n23,int n31, int nCenter, int ID)
2120 {
2121   return SMDS_Mesh::AddFaceWithID (myNodeFactory->FindNode(n1) ,
2122                                    myNodeFactory->FindNode(n2) ,
2123                                    myNodeFactory->FindNode(n3) ,
2124                                    myNodeFactory->FindNode(n12),
2125                                    myNodeFactory->FindNode(n23),
2126                                    myNodeFactory->FindNode(n31),
2127                                    myNodeFactory->FindNode(nCenter),
2128                                    ID);
2129 }
2130
2131 //=======================================================================
2132 //function : AddFaceWithID
2133 //purpose  :
2134 //=======================================================================
2135 SMDS_MeshFace* SMDS_Mesh::AddFaceWithID(const SMDS_MeshNode * n1,
2136                                         const SMDS_MeshNode * n2,
2137                                         const SMDS_MeshNode * n3,
2138                                         const SMDS_MeshNode * n12,
2139                                         const SMDS_MeshNode * n23,
2140                                         const SMDS_MeshNode * n31,
2141                                         const SMDS_MeshNode * nCenter,
2142                                         int ID)
2143 {
2144   if ( !n1 || !n2 || !n3 || !n12 || !n23 || !n31 || !nCenter) return 0;
2145   if ( NbFaces() % CHECKMEMORY_INTERVAL == 0 ) CheckMemory();
2146
2147   if ( SMDS_MeshCell* cell = myCellFactory->NewCell( ID ))
2148   {
2149     cell->init( SMDSEntity_BiQuad_Triangle, /*nbNodes=*/7, n1, n2, n3, n12, n23, n31, nCenter );
2150     myInfo.myNbBiQuadTriangles++;
2151     return static_cast<SMDS_MeshFace*>( cell );
2152   }
2153   return 0;
2154 }
2155
2156
2157 //=======================================================================
2158 //function : AddFace
2159 //purpose  :
2160 //=======================================================================
2161 SMDS_MeshFace* SMDS_Mesh::AddFace(const SMDS_MeshNode * n1,
2162                                   const SMDS_MeshNode * n2,
2163                                   const SMDS_MeshNode * n3,
2164                                   const SMDS_MeshNode * n4,
2165                                   const SMDS_MeshNode * n12,
2166                                   const SMDS_MeshNode * n23,
2167                                   const SMDS_MeshNode * n34,
2168                                   const SMDS_MeshNode * n41)
2169 {
2170   return SMDS_Mesh::AddFaceWithID(n1,n2,n3,n4,n12,n23,n34,n41,
2171                                   myCellFactory->GetFreeID());
2172 }
2173
2174 //=======================================================================
2175 //function : AddFaceWithID
2176 //purpose  :
2177 //=======================================================================
2178 SMDS_MeshFace* SMDS_Mesh::AddFaceWithID(int n1, int n2, int n3, int n4,
2179                                         int n12,int n23,int n34,int n41, int ID)
2180 {
2181   return SMDS_Mesh::AddFaceWithID (myNodeFactory->FindNode(n1) ,
2182                                    myNodeFactory->FindNode(n2) ,
2183                                    myNodeFactory->FindNode(n3) ,
2184                                    myNodeFactory->FindNode(n4) ,
2185                                    myNodeFactory->FindNode(n12),
2186                                    myNodeFactory->FindNode(n23),
2187                                    myNodeFactory->FindNode(n34),
2188                                    myNodeFactory->FindNode(n41),
2189                                    ID);
2190 }
2191
2192 //=======================================================================
2193 //function : AddFaceWithID
2194 //purpose  :
2195 //=======================================================================
2196 SMDS_MeshFace* SMDS_Mesh::AddFaceWithID(const SMDS_MeshNode * n1,
2197                                         const SMDS_MeshNode * n2,
2198                                         const SMDS_MeshNode * n3,
2199                                         const SMDS_MeshNode * n4,
2200                                         const SMDS_MeshNode * n12,
2201                                         const SMDS_MeshNode * n23,
2202                                         const SMDS_MeshNode * n34,
2203                                         const SMDS_MeshNode * n41,
2204                                         int ID)
2205 {
2206   if ( !n1 || !n2 || !n3 || !n4 || !n12 || !n23 || !n34 || !n41) return 0;
2207   if ( NbFaces() % CHECKMEMORY_INTERVAL == 0 ) CheckMemory();
2208
2209   if ( SMDS_MeshCell* cell = myCellFactory->NewCell( ID ))
2210   {
2211     cell->init( SMDSEntity_Quad_Quadrangle, /*nbNodes=*/8, n1, n2, n3, n4, n12, n23, n34, n41 );
2212     myInfo.myNbQuadQuadrangles++;
2213     return static_cast<SMDS_MeshFace*>( cell );
2214   }
2215   return 0;
2216 }
2217
2218 //=======================================================================
2219 //function : AddFace
2220 //purpose  :
2221 //=======================================================================
2222 SMDS_MeshFace* SMDS_Mesh::AddFace(const SMDS_MeshNode * n1,
2223                                   const SMDS_MeshNode * n2,
2224                                   const SMDS_MeshNode * n3,
2225                                   const SMDS_MeshNode * n4,
2226                                   const SMDS_MeshNode * n12,
2227                                   const SMDS_MeshNode * n23,
2228                                   const SMDS_MeshNode * n34,
2229                                   const SMDS_MeshNode * n41,
2230                                   const SMDS_MeshNode * nCenter)
2231 {
2232   return SMDS_Mesh::AddFaceWithID(n1,n2,n3,n4,n12,n23,n34,n41,nCenter,
2233                                   myCellFactory->GetFreeID());
2234 }
2235
2236 //=======================================================================
2237 //function : AddFaceWithID
2238 //purpose  :
2239 //=======================================================================
2240 SMDS_MeshFace* SMDS_Mesh::AddFaceWithID(int n1, int n2, int n3, int n4,
2241                                         int n12,int n23,int n34,int n41, int nCenter, int ID)
2242 {
2243   return SMDS_Mesh::AddFaceWithID (myNodeFactory->FindNode(n1) ,
2244                                    myNodeFactory->FindNode(n2) ,
2245                                    myNodeFactory->FindNode(n3) ,
2246                                    myNodeFactory->FindNode(n4) ,
2247                                    myNodeFactory->FindNode(n12),
2248                                    myNodeFactory->FindNode(n23),
2249                                    myNodeFactory->FindNode(n34),
2250                                    myNodeFactory->FindNode(n41),
2251                                    myNodeFactory->FindNode(nCenter),
2252                                    ID);
2253 }
2254
2255 //=======================================================================
2256 //function : AddFaceWithID
2257 //purpose  :
2258 //=======================================================================
2259 SMDS_MeshFace* SMDS_Mesh::AddFaceWithID(const SMDS_MeshNode * n1,
2260                                         const SMDS_MeshNode * n2,
2261                                         const SMDS_MeshNode * n3,
2262                                         const SMDS_MeshNode * n4,
2263                                         const SMDS_MeshNode * n12,
2264                                         const SMDS_MeshNode * n23,
2265                                         const SMDS_MeshNode * n34,
2266                                         const SMDS_MeshNode * n41,
2267                                         const SMDS_MeshNode * nCenter,
2268                                         int ID)
2269 {
2270   if ( !n1 || !n2 || !n3 || !n4 || !n12 || !n23 || !n34 || !n41 || !nCenter) return 0;
2271   if ( NbFaces() % CHECKMEMORY_INTERVAL == 0 ) CheckMemory();
2272
2273   if ( SMDS_MeshCell* cell = myCellFactory->NewCell( ID ))
2274   {
2275     cell->init( SMDSEntity_BiQuad_Quadrangle,
2276                 /*nbNodes=*/9, n1, n2, n3, n4, n12, n23, n34, n41, nCenter );
2277     myInfo.myNbBiQuadQuadrangles++;
2278     return static_cast<SMDS_MeshFace*>( cell );
2279   }
2280   return 0;
2281 }
2282
2283
2284 //=======================================================================
2285 //function : AddVolume
2286 //purpose  :
2287 //=======================================================================
2288 SMDS_MeshVolume* SMDS_Mesh::AddVolume(const SMDS_MeshNode * n1,
2289                                       const SMDS_MeshNode * n2,
2290                                       const SMDS_MeshNode * n3,
2291                                       const SMDS_MeshNode * n4,
2292                                       const SMDS_MeshNode * n12,
2293                                       const SMDS_MeshNode * n23,
2294                                       const SMDS_MeshNode * n31,
2295                                       const SMDS_MeshNode * n14,
2296                                       const SMDS_MeshNode * n24,
2297                                       const SMDS_MeshNode * n34)
2298 {
2299   return SMDS_Mesh::AddVolumeWithID(n1, n2, n3, n4, n12, n23,
2300                                     n31, n14, n24, n34, myCellFactory->GetFreeID());
2301 }
2302
2303 //=======================================================================
2304 //function : AddVolumeWithID
2305 //purpose  :
2306 //=======================================================================
2307 SMDS_MeshVolume* SMDS_Mesh::AddVolumeWithID(int n1, int n2, int n3, int n4,
2308                                             int n12,int n23,int n31,
2309                                             int n14,int n24,int n34, int ID)
2310 {
2311   return SMDS_Mesh::AddVolumeWithID (myNodeFactory->FindNode(n1) ,
2312                                      myNodeFactory->FindNode(n2) ,
2313                                      myNodeFactory->FindNode(n3) ,
2314                                      myNodeFactory->FindNode(n4) ,
2315                                      myNodeFactory->FindNode(n12),
2316                                      myNodeFactory->FindNode(n23),
2317                                      myNodeFactory->FindNode(n31),
2318                                      myNodeFactory->FindNode(n14),
2319                                      myNodeFactory->FindNode(n24),
2320                                      myNodeFactory->FindNode(n34),
2321                                      ID);
2322 }
2323
2324 //=======================================================================
2325 //function : AddVolumeWithID
2326 //purpose  : 2d order tetrahedron of 10 nodes
2327 //=======================================================================
2328 SMDS_MeshVolume* SMDS_Mesh::AddVolumeWithID(const SMDS_MeshNode * n1,
2329                                             const SMDS_MeshNode * n2,
2330                                             const SMDS_MeshNode * n3,
2331                                             const SMDS_MeshNode * n4,
2332                                             const SMDS_MeshNode * n12,
2333                                             const SMDS_MeshNode * n23,
2334                                             const SMDS_MeshNode * n31,
2335                                             const SMDS_MeshNode * n14,
2336                                             const SMDS_MeshNode * n24,
2337                                             const SMDS_MeshNode * n34,
2338                                             int ID)
2339 {
2340   if ( !n1 || !n2 || !n3 || !n4 || !n12 || !n23 || !n31 || !n14 || !n24 || !n34)
2341     return 0;
2342   if ( NbVolumes() % CHECKMEMORY_INTERVAL == 0 ) CheckMemory();
2343
2344   if ( SMDS_MeshCell* cell = myCellFactory->NewCell( ID ))
2345   {
2346     cell->init( SMDSEntity_Quad_Tetra,
2347                 /*nbNodes=*/10, n1, n2, n3, n4, n12, n23, n31, n14, n24, n34 );
2348     myInfo.myNbQuadTetras++;
2349     return static_cast<SMDS_MeshVolume*>( cell );
2350   }
2351   return 0;
2352 }
2353
2354
2355 //=======================================================================
2356 //function : AddVolume
2357 //purpose  :
2358 //=======================================================================
2359 SMDS_MeshVolume* SMDS_Mesh::AddVolume(const SMDS_MeshNode * n1,
2360                                       const SMDS_MeshNode * n2,
2361                                       const SMDS_MeshNode * n3,
2362                                       const SMDS_MeshNode * n4,
2363                                       const SMDS_MeshNode * n5,
2364                                       const SMDS_MeshNode * n12,
2365                                       const SMDS_MeshNode * n23,
2366                                       const SMDS_MeshNode * n34,
2367                                       const SMDS_MeshNode * n41,
2368                                       const SMDS_MeshNode * n15,
2369                                       const SMDS_MeshNode * n25,
2370                                       const SMDS_MeshNode * n35,
2371                                       const SMDS_MeshNode * n45)
2372 {
2373   return SMDS_Mesh::AddVolumeWithID(n1, n2, n3, n4, n5, n12, n23, n34, n41,
2374                                     n15, n25, n35, n45, myCellFactory->GetFreeID());
2375 }
2376
2377 //=======================================================================
2378 //function : AddVolumeWithID
2379 //purpose  :
2380 //=======================================================================
2381 SMDS_MeshVolume* SMDS_Mesh::AddVolumeWithID(int n1, int n2, int n3, int n4, int n5,
2382                                             int n12,int n23,int n34,int n41,
2383                                             int n15,int n25,int n35,int n45, int ID)
2384 {
2385   return SMDS_Mesh::AddVolumeWithID (myNodeFactory->FindNode(n1) ,
2386                                      myNodeFactory->FindNode(n2) ,
2387                                      myNodeFactory->FindNode(n3) ,
2388                                      myNodeFactory->FindNode(n4) ,
2389                                      myNodeFactory->FindNode(n5) ,
2390                                      myNodeFactory->FindNode(n12),
2391                                      myNodeFactory->FindNode(n23),
2392                                      myNodeFactory->FindNode(n34),
2393                                      myNodeFactory->FindNode(n41),
2394                                      myNodeFactory->FindNode(n15),
2395                                      myNodeFactory->FindNode(n25),
2396                                      myNodeFactory->FindNode(n35),
2397                                      myNodeFactory->FindNode(n45),
2398                                      ID);
2399 }
2400
2401 //=======================================================================
2402 //function : AddVolumeWithID
2403 //purpose  : 2d order pyramid of 13 nodes
2404 //=======================================================================
2405 SMDS_MeshVolume* SMDS_Mesh::AddVolumeWithID(const SMDS_MeshNode * n1,
2406                                             const SMDS_MeshNode * n2,
2407                                             const SMDS_MeshNode * n3,
2408                                             const SMDS_MeshNode * n4,
2409                                             const SMDS_MeshNode * n5,
2410                                             const SMDS_MeshNode * n12,
2411                                             const SMDS_MeshNode * n23,
2412                                             const SMDS_MeshNode * n34,
2413                                             const SMDS_MeshNode * n41,
2414                                             const SMDS_MeshNode * n15,
2415                                             const SMDS_MeshNode * n25,
2416                                             const SMDS_MeshNode * n35,
2417                                             const SMDS_MeshNode * n45,
2418                                             int ID)
2419 {
2420   if (!n1 || !n2 || !n3 || !n4 || !n5 || !n12 || !n23 ||
2421       !n34 || !n41 || !n15 || !n25 || !n35 || !n45)
2422     return 0;
2423   if ( NbVolumes() % CHECKMEMORY_INTERVAL == 0 ) CheckMemory();
2424
2425   if ( SMDS_MeshCell* cell = myCellFactory->NewCell( ID ))
2426   {
2427     cell->init( SMDSEntity_Quad_Pyramid,
2428                 /*nbNodes=*/13, n1, n2, n3, n4, n5, n12, n23, n34, n41, n15, n25, n35, n45);
2429     myInfo.myNbQuadPyramids++;
2430     return static_cast<SMDS_MeshVolume*>( cell );
2431   }
2432   return 0;
2433 }
2434
2435
2436 //=======================================================================
2437 //function : AddVolume
2438 //purpose  : 2d order Pentahedron (prism) with 15 nodes
2439 //=======================================================================
2440 SMDS_MeshVolume* SMDS_Mesh::AddVolume(const SMDS_MeshNode * n1,
2441                                       const SMDS_MeshNode * n2,
2442                                       const SMDS_MeshNode * n3,
2443                                       const SMDS_MeshNode * n4,
2444                                       const SMDS_MeshNode * n5,
2445                                       const SMDS_MeshNode * n6,
2446                                       const SMDS_MeshNode * n12,
2447                                       const SMDS_MeshNode * n23,
2448                                       const SMDS_MeshNode * n31,
2449                                       const SMDS_MeshNode * n45,
2450                                       const SMDS_MeshNode * n56,
2451                                       const SMDS_MeshNode * n64,
2452                                       const SMDS_MeshNode * n14,
2453                                       const SMDS_MeshNode * n25,
2454                                       const SMDS_MeshNode * n36)
2455 {
2456   return SMDS_Mesh::AddVolumeWithID(n1, n2, n3, n4, n5, n6, n12, n23, n31,
2457                                     n45, n56, n64, n14, n25, n36, myCellFactory->GetFreeID());
2458 }
2459
2460 //=======================================================================
2461 //function : AddVolumeWithID
2462 //purpose  : 2d order Pentahedron (prism) with 15 nodes
2463 //=======================================================================
2464 SMDS_MeshVolume* SMDS_Mesh::AddVolumeWithID(int n1, int n2, int n3,
2465                                             int n4, int n5, int n6,
2466                                             int n12,int n23,int n31,
2467                                             int n45,int n56,int n64,
2468                                             int n14,int n25,int n36, int ID)
2469 {
2470   return SMDS_Mesh::AddVolumeWithID (myNodeFactory->FindNode(n1) ,
2471                                      myNodeFactory->FindNode(n2) ,
2472                                      myNodeFactory->FindNode(n3) ,
2473                                      myNodeFactory->FindNode(n4) ,
2474                                      myNodeFactory->FindNode(n5) ,
2475                                      myNodeFactory->FindNode(n6) ,
2476                                      myNodeFactory->FindNode(n12),
2477                                      myNodeFactory->FindNode(n23),
2478                                      myNodeFactory->FindNode(n31),
2479                                      myNodeFactory->FindNode(n45),
2480                                      myNodeFactory->FindNode(n56),
2481                                      myNodeFactory->FindNode(n64),
2482                                      myNodeFactory->FindNode(n14),
2483                                      myNodeFactory->FindNode(n25),
2484                                      myNodeFactory->FindNode(n36),
2485                                      ID);
2486 }
2487
2488 //=======================================================================
2489 //function : AddVolumeWithID
2490 //purpose  : 2d order Pentahedron (prism) with 15 nodes
2491 //=======================================================================
2492 SMDS_MeshVolume* SMDS_Mesh::AddVolumeWithID(const SMDS_MeshNode * n1,
2493                                             const SMDS_MeshNode * n2,
2494                                             const SMDS_MeshNode * n3,
2495                                             const SMDS_MeshNode * n4,
2496                                             const SMDS_MeshNode * n5,
2497                                             const SMDS_MeshNode * n6,
2498                                             const SMDS_MeshNode * n12,
2499                                             const SMDS_MeshNode * n23,
2500                                             const SMDS_MeshNode * n31,
2501                                             const SMDS_MeshNode * n45,
2502                                             const SMDS_MeshNode * n56,
2503                                             const SMDS_MeshNode * n64,
2504                                             const SMDS_MeshNode * n14,
2505                                             const SMDS_MeshNode * n25,
2506                                             const SMDS_MeshNode * n36,
2507                                             int ID)
2508 {
2509   if (!n1 || !n2 || !n3 || !n4 || !n5 || !n6 || !n12 || !n23 ||
2510       !n31 || !n45 || !n56 || !n64 || !n14 || !n25 || !n36)
2511     return 0;
2512   if ( NbVolumes() % CHECKMEMORY_INTERVAL == 0 ) CheckMemory();
2513
2514   if ( SMDS_MeshCell* cell = myCellFactory->NewCell( ID ))
2515   {
2516     cell->init( SMDSEntity_Quad_Penta, /*nbNodes=*/15,
2517                 n1, n2, n3, n4, n5, n6, n12, n23, n31, n45, n56, n64, n14, n25, n36 );
2518     myInfo.myNbQuadPrisms++;
2519     return static_cast<SMDS_MeshVolume*>( cell );
2520   }
2521   return 0;
2522 }
2523
2524 //=======================================================================
2525 //function : AddVolume
2526 //purpose  : 2d order Pentahedron (prism) with 18 nodes
2527 //=======================================================================
2528 SMDS_MeshVolume* SMDS_Mesh::AddVolume(const SMDS_MeshNode * n1,
2529                                       const SMDS_MeshNode * n2,
2530                                       const SMDS_MeshNode * n3,
2531                                       const SMDS_MeshNode * n4,
2532                                       const SMDS_MeshNode * n5,
2533                                       const SMDS_MeshNode * n6,
2534                                       const SMDS_MeshNode * n12,
2535                                       const SMDS_MeshNode * n23,
2536                                       const SMDS_MeshNode * n31,
2537                                       const SMDS_MeshNode * n45,
2538                                       const SMDS_MeshNode * n56,
2539                                       const SMDS_MeshNode * n64,
2540                                       const SMDS_MeshNode * n14,
2541                                       const SMDS_MeshNode * n25,
2542                                       const SMDS_MeshNode * n36,
2543                                       const SMDS_MeshNode * n1245,
2544                                       const SMDS_MeshNode * n2356,
2545                                       const SMDS_MeshNode * n1346)
2546 {
2547   return SMDS_Mesh::AddVolumeWithID(n1, n2, n3, n4, n5, n6, n12, n23, n31,
2548                                     n45, n56, n64, n14, n25, n36, n1245, n2356, n1346,
2549                                     myCellFactory->GetFreeID());
2550 }
2551
2552 //=======================================================================
2553 //function : AddVolumeWithID
2554 //purpose  : 2d order Pentahedron (prism) with 18 nodes
2555 //=======================================================================
2556 SMDS_MeshVolume* SMDS_Mesh::AddVolumeWithID(int n1, int n2, int n3,
2557                                             int n4, int n5, int n6,
2558                                             int n12,int n23,int n31,
2559                                             int n45,int n56,int n64,
2560                                             int n14,int n25,int n36,
2561                                             int n1245, int n2356, int n1346, int ID)
2562 {
2563   return SMDS_Mesh::AddVolumeWithID (myNodeFactory->FindNode(n1) ,
2564                                      myNodeFactory->FindNode(n2) ,
2565                                      myNodeFactory->FindNode(n3) ,
2566                                      myNodeFactory->FindNode(n4) ,
2567                                      myNodeFactory->FindNode(n5) ,
2568                                      myNodeFactory->FindNode(n6) ,
2569                                      myNodeFactory->FindNode(n12),
2570                                      myNodeFactory->FindNode(n23),
2571                                      myNodeFactory->FindNode(n31),
2572                                      myNodeFactory->FindNode(n45),
2573                                      myNodeFactory->FindNode(n56),
2574                                      myNodeFactory->FindNode(n64),
2575                                      myNodeFactory->FindNode(n14),
2576                                      myNodeFactory->FindNode(n25),
2577                                      myNodeFactory->FindNode(n36),
2578                                      myNodeFactory->FindNode(n1245),
2579                                      myNodeFactory->FindNode(n2356),
2580                                      myNodeFactory->FindNode(n1346),
2581                                      ID);
2582 }
2583
2584 //=======================================================================
2585 //function : AddVolumeWithID
2586 //purpose  : 2d order Pentahedron (prism) with 18 nodes
2587 //=======================================================================
2588 SMDS_MeshVolume* SMDS_Mesh::AddVolumeWithID(const SMDS_MeshNode * n1,
2589                                             const SMDS_MeshNode * n2,
2590                                             const SMDS_MeshNode * n3,
2591                                             const SMDS_MeshNode * n4,
2592                                             const SMDS_MeshNode * n5,
2593                                             const SMDS_MeshNode * n6,
2594                                             const SMDS_MeshNode * n12,
2595                                             const SMDS_MeshNode * n23,
2596                                             const SMDS_MeshNode * n31,
2597                                             const SMDS_MeshNode * n45,
2598                                             const SMDS_MeshNode * n56,
2599                                             const SMDS_MeshNode * n64,
2600                                             const SMDS_MeshNode * n14,
2601                                             const SMDS_MeshNode * n25,
2602                                             const SMDS_MeshNode * n36,
2603                                             const SMDS_MeshNode * n1245,
2604                                             const SMDS_MeshNode * n2356,
2605                                             const SMDS_MeshNode * n1346,
2606                                             int ID)
2607 {
2608   //MESSAGE("AddVolumeWithID penta18 "<< ID);
2609   if (!n1 || !n2 || !n3 || !n4 || !n5 || !n6 || !n12 || !n23 ||
2610       !n31 || !n45 || !n56 || !n64 || !n14 || !n25 || !n36 || !n1245 || !n2356 || !n1346)
2611     return 0;
2612   if ( NbVolumes() % CHECKMEMORY_INTERVAL == 0 ) CheckMemory();
2613
2614   if ( SMDS_MeshCell* cell = myCellFactory->NewCell( ID ))
2615   {
2616     cell->init( SMDSEntity_BiQuad_Penta, /*nbNodes=*/18, n1, n2, n3, n4, n5, n6,
2617                 n12, n23, n31, n45, n56, n64, n14, n25, n36, n1245, n2356, n1346 );
2618     myInfo.myNbBiQuadPrisms++;
2619     return static_cast<SMDS_MeshVolume*>( cell );
2620   }
2621   return 0;
2622 }
2623
2624
2625 //=======================================================================
2626 //function : AddVolume
2627 //purpose  :
2628 //=======================================================================
2629 SMDS_MeshVolume* SMDS_Mesh::AddVolume(const SMDS_MeshNode * n1,
2630                                       const SMDS_MeshNode * n2,
2631                                       const SMDS_MeshNode * n3,
2632                                       const SMDS_MeshNode * n4,
2633                                       const SMDS_MeshNode * n5,
2634                                       const SMDS_MeshNode * n6,
2635                                       const SMDS_MeshNode * n7,
2636                                       const SMDS_MeshNode * n8,
2637                                       const SMDS_MeshNode * n12,
2638                                       const SMDS_MeshNode * n23,
2639                                       const SMDS_MeshNode * n34,
2640                                       const SMDS_MeshNode * n41,
2641                                       const SMDS_MeshNode * n56,
2642                                       const SMDS_MeshNode * n67,
2643                                       const SMDS_MeshNode * n78,
2644                                       const SMDS_MeshNode * n85,
2645                                       const SMDS_MeshNode * n15,
2646                                       const SMDS_MeshNode * n26,
2647                                       const SMDS_MeshNode * n37,
2648                                       const SMDS_MeshNode * n48)
2649 {
2650   return SMDS_Mesh::AddVolumeWithID(n1, n2, n3, n4, n5, n6, n7, n8, n12, n23, n34, n41,
2651                                     n56, n67, n78, n85, n15, n26, n37, n48,
2652                                     myCellFactory->GetFreeID());
2653 }
2654
2655 //=======================================================================
2656 //function : AddVolumeWithID
2657 //purpose  :
2658 //=======================================================================
2659 SMDS_MeshVolume* SMDS_Mesh::AddVolumeWithID(int n1, int n2, int n3, int n4,
2660                                             int n5, int n6, int n7, int n8,
2661                                             int n12,int n23,int n34,int n41,
2662                                             int n56,int n67,int n78,int n85,
2663                                             int n15,int n26,int n37,int n48, int ID)
2664 {
2665   return SMDS_Mesh::AddVolumeWithID (myNodeFactory->FindNode(n1),
2666                                      myNodeFactory->FindNode(n2),
2667                                      myNodeFactory->FindNode(n3),
2668                                      myNodeFactory->FindNode(n4),
2669                                      myNodeFactory->FindNode(n5),
2670                                      myNodeFactory->FindNode(n6),
2671                                      myNodeFactory->FindNode(n7),
2672                                      myNodeFactory->FindNode(n8),
2673                                      myNodeFactory->FindNode(n12),
2674                                      myNodeFactory->FindNode(n23),
2675                                      myNodeFactory->FindNode(n34),
2676                                      myNodeFactory->FindNode(n41),
2677                                      myNodeFactory->FindNode(n56),
2678                                      myNodeFactory->FindNode(n67),
2679                                      myNodeFactory->FindNode(n78),
2680                                      myNodeFactory->FindNode(n85),
2681                                      myNodeFactory->FindNode(n15),
2682                                      myNodeFactory->FindNode(n26),
2683                                      myNodeFactory->FindNode(n37),
2684                                      myNodeFactory->FindNode(n48),
2685                                      ID);
2686 }
2687
2688 //=======================================================================
2689 //function : AddVolumeWithID
2690 //purpose  : 2d order Hexahedrons with 20 nodes
2691 //=======================================================================
2692 SMDS_MeshVolume* SMDS_Mesh::AddVolumeWithID(const SMDS_MeshNode * n1,
2693                                             const SMDS_MeshNode * n2,
2694                                             const SMDS_MeshNode * n3,
2695                                             const SMDS_MeshNode * n4,
2696                                             const SMDS_MeshNode * n5,
2697                                             const SMDS_MeshNode * n6,
2698                                             const SMDS_MeshNode * n7,
2699                                             const SMDS_MeshNode * n8,
2700                                             const SMDS_MeshNode * n12,
2701                                             const SMDS_MeshNode * n23,
2702                                             const SMDS_MeshNode * n34,
2703                                             const SMDS_MeshNode * n41,
2704                                             const SMDS_MeshNode * n56,
2705                                             const SMDS_MeshNode * n67,
2706                                             const SMDS_MeshNode * n78,
2707                                             const SMDS_MeshNode * n85,
2708                                             const SMDS_MeshNode * n15,
2709                                             const SMDS_MeshNode * n26,
2710                                             const SMDS_MeshNode * n37,
2711                                             const SMDS_MeshNode * n48,
2712                                             int ID)
2713 {
2714   if (!n1 || !n2 || !n3 || !n4 || !n5 || !n6 || !n7 || !n8 || !n12 || !n23 ||
2715       !n34 || !n41 || !n56 || !n67 || !n78 || !n85 || !n15 || !n26 || !n37 || !n48)
2716     return 0;
2717   if ( NbVolumes() % CHECKMEMORY_INTERVAL == 0 ) CheckMemory();
2718
2719   if ( SMDS_MeshCell* cell = myCellFactory->NewCell( ID ))
2720   {
2721     cell->init( SMDSEntity_Quad_Hexa, /*nbNodes=*/20, n1, n2, n3, n4, n5, n6, n7, n8,
2722                 n12, n23, n34, n41, n56, n67, n78, n85, n15, n26, n37, n48 );
2723     myInfo.myNbQuadHexas++;
2724     return static_cast<SMDS_MeshVolume*>( cell );
2725   }
2726   return 0;
2727 }
2728
2729 //=======================================================================
2730 //function : AddVolume
2731 //purpose  :
2732 //=======================================================================
2733 SMDS_MeshVolume* SMDS_Mesh::AddVolume(const SMDS_MeshNode * n1,
2734                                       const SMDS_MeshNode * n2,
2735                                       const SMDS_MeshNode * n3,
2736                                       const SMDS_MeshNode * n4,
2737                                       const SMDS_MeshNode * n5,
2738                                       const SMDS_MeshNode * n6,
2739                                       const SMDS_MeshNode * n7,
2740                                       const SMDS_MeshNode * n8,
2741                                       const SMDS_MeshNode * n12,
2742                                       const SMDS_MeshNode * n23,
2743                                       const SMDS_MeshNode * n34,
2744                                       const SMDS_MeshNode * n41,
2745                                       const SMDS_MeshNode * n56,
2746                                       const SMDS_MeshNode * n67,
2747                                       const SMDS_MeshNode * n78,
2748                                       const SMDS_MeshNode * n85,
2749                                       const SMDS_MeshNode * n15,
2750                                       const SMDS_MeshNode * n26,
2751                                       const SMDS_MeshNode * n37,
2752                                       const SMDS_MeshNode * n48,
2753                                       const SMDS_MeshNode * n1234,
2754                                       const SMDS_MeshNode * n1256,
2755                                       const SMDS_MeshNode * n2367,
2756                                       const SMDS_MeshNode * n3478,
2757                                       const SMDS_MeshNode * n1458,
2758                                       const SMDS_MeshNode * n5678,
2759                                       const SMDS_MeshNode * nCenter)
2760 {
2761   return SMDS_Mesh::AddVolumeWithID(n1, n2, n3, n4, n5, n6, n7, n8, n12, n23, n34, n41,
2762                                     n56, n67, n78, n85, n15, n26, n37, n48,
2763                                     n1234, n1256, n2367, n3478, n1458, n5678, nCenter,
2764                                     myCellFactory->GetFreeID());
2765 }
2766
2767 //=======================================================================
2768 //function : AddVolumeWithID
2769 //purpose  :
2770 //=======================================================================
2771 SMDS_MeshVolume* SMDS_Mesh::AddVolumeWithID(int n1, int n2, int n3, int n4,
2772                                             int n5, int n6, int n7, int n8,
2773                                             int n12,int n23,int n34,int n41,
2774                                             int n56,int n67,int n78,int n85,
2775                                             int n15,int n26,int n37,int n48,
2776                                             int n1234,int n1256,int n2367,int n3478,
2777                                             int n1458,int n5678,int nCenter, int ID)
2778 {
2779   return SMDS_Mesh::AddVolumeWithID (myNodeFactory->FindNode(n1),
2780                                      myNodeFactory->FindNode(n2),
2781                                      myNodeFactory->FindNode(n3),
2782                                      myNodeFactory->FindNode(n4),
2783                                      myNodeFactory->FindNode(n5),
2784                                      myNodeFactory->FindNode(n6),
2785                                      myNodeFactory->FindNode(n7),
2786                                      myNodeFactory->FindNode(n8),
2787                                      myNodeFactory->FindNode(n12),
2788                                      myNodeFactory->FindNode(n23),
2789                                      myNodeFactory->FindNode(n34),
2790                                      myNodeFactory->FindNode(n41),
2791                                      myNodeFactory->FindNode(n56),
2792                                      myNodeFactory->FindNode(n67),
2793                                      myNodeFactory->FindNode(n78),
2794                                      myNodeFactory->FindNode(n85),
2795                                      myNodeFactory->FindNode(n15),
2796                                      myNodeFactory->FindNode(n26),
2797                                      myNodeFactory->FindNode(n37),
2798                                      myNodeFactory->FindNode(n48),
2799                                      myNodeFactory->FindNode(n1234),
2800                                      myNodeFactory->FindNode(n1256),
2801                                      myNodeFactory->FindNode(n2367),
2802                                      myNodeFactory->FindNode(n3478),
2803                                      myNodeFactory->FindNode(n1458),
2804                                      myNodeFactory->FindNode(n5678),
2805                                      myNodeFactory->FindNode(nCenter),
2806                                      ID);
2807 }
2808
2809 //=======================================================================
2810 //function : AddVolumeWithID
2811 //purpose  : 2d order Hexahedrons with 27 nodes
2812 //=======================================================================
2813 SMDS_MeshVolume* SMDS_Mesh::AddVolumeWithID(const SMDS_MeshNode * n1,
2814                                             const SMDS_MeshNode * n2,
2815                                             const SMDS_MeshNode * n3,
2816                                             const SMDS_MeshNode * n4,
2817                                             const SMDS_MeshNode * n5,
2818                                             const SMDS_MeshNode * n6,
2819                                             const SMDS_MeshNode * n7,
2820                                             const SMDS_MeshNode * n8,
2821                                             const SMDS_MeshNode * n12,
2822                                             const SMDS_MeshNode * n23,
2823                                             const SMDS_MeshNode * n34,
2824                                             const SMDS_MeshNode * n41,
2825                                             const SMDS_MeshNode * n56,
2826                                             const SMDS_MeshNode * n67,
2827                                             const SMDS_MeshNode * n78,
2828                                             const SMDS_MeshNode * n85,
2829                                             const SMDS_MeshNode * n15,
2830                                             const SMDS_MeshNode * n26,
2831                                             const SMDS_MeshNode * n37,
2832                                             const SMDS_MeshNode * n48,
2833                                             const SMDS_MeshNode * n1234,
2834                                             const SMDS_MeshNode * n1256,
2835                                             const SMDS_MeshNode * n2367,
2836                                             const SMDS_MeshNode * n3478,
2837                                             const SMDS_MeshNode * n1458,
2838                                             const SMDS_MeshNode * n5678,
2839                                             const SMDS_MeshNode * nCenter,
2840                                             int ID)
2841 {
2842   if (!n1 || !n2 || !n3 || !n4 || !n5 || !n6 || !n7 || !n8 || !n12 || !n23 ||
2843       !n34 || !n41 || !n56 || !n67 || !n78 || !n85 || !n15 || !n26 || !n37 || !n48 ||
2844       !n1234 || !n1256 || !n2367 || !n3478 || !n1458 || !n5678 || !nCenter )
2845     return 0;
2846   if ( NbVolumes() % CHECKMEMORY_INTERVAL == 0 ) CheckMemory();
2847
2848   if ( SMDS_MeshCell* cell = myCellFactory->NewCell( ID ))
2849   {
2850     cell->init( SMDSEntity_TriQuad_Hexa, /*nbNodes=*/27, n1, n2, n3, n4, n5, n6, n7, n8,
2851                 n12, n23, n34, n41, n56, n67, n78, n85, n15, n26, n37, n48,
2852                 n1234, n1256, n2367, n3478, n1458, n5678, nCenter);
2853     myInfo.myNbTriQuadHexas++;
2854     return static_cast<SMDS_MeshVolume*>( cell );
2855   }
2856   return 0;
2857 }
2858
2859 void SMDS_Mesh::dumpGrid(std::string ficdump)
2860 {
2861   //  vtkUnstructuredGridWriter* aWriter = vtkUnstructuredGridWriter::New();
2862   //  aWriter->SetFileName(ficdump.c_str());
2863   //  aWriter->SetInput(myGrid);
2864   //  if(myGrid->GetNumberOfCells())
2865   //  {
2866   //    aWriter->Write();
2867   //  }
2868   //  aWriter->Delete();
2869   ficdump = ficdump + "_connectivity";
2870   std::ofstream ficcon(ficdump.c_str(), ios::out);
2871   int nbPoints = myGrid->GetNumberOfPoints();
2872   ficcon << "-------------------------------- points " <<  nbPoints << endl;
2873   for (int i=0; i<nbPoints; i++)
2874   {
2875     ficcon << i << " " << *(myGrid->GetPoint(i)) << " " << *(myGrid->GetPoint(i)+1) << " " << " " << *(myGrid->GetPoint(i)+2) << endl;
2876   }
2877   int nbCells = myGrid->GetNumberOfCells();
2878   ficcon << "-------------------------------- cells " <<  nbCells << endl;
2879   for (int i=0; i<nbCells; i++)
2880   {
2881     ficcon << i << " - " << myGrid->GetCell(i)->GetCellType() << " -";
2882     int nbptcell = myGrid->GetCell(i)->GetNumberOfPoints();
2883     vtkIdList *listid = myGrid->GetCell(i)->GetPointIds();
2884     for (int j=0; j<nbptcell; j++)
2885     {
2886       ficcon << " " <<  listid->GetId(j);
2887     }
2888     ficcon << endl;
2889   }
2890   ficcon << "-------------------------------- connectivity " <<  nbPoints << endl;
2891   vtkCellLinks *links = myGrid->GetLinks();
2892   for (int i=0; i<nbPoints; i++)
2893   {
2894     int ncells = links->GetNcells(i);
2895     vtkIdType *cells = links->GetCells(i);
2896     ficcon << i << " - " << ncells << " -";
2897     for (int j=0; j<ncells; j++)
2898     {
2899       ficcon << " " << cells[j];
2900     }
2901     ficcon << endl;
2902   }
2903   ficcon.close();
2904
2905 }
2906
2907 void SMDS_Mesh::CompactMesh()
2908 {
2909   this->myCompactTime = this->myModifTime;
2910
2911   bool idsChange = ( myNodeFactory->CompactChangePointers() ||
2912                      myCellFactory->CompactChangePointers() );
2913   if ( idsChange )
2914   {
2915     std::set< SMDS_ElementHolder* >::iterator holder = myElemHolders.begin();
2916     for ( ; holder != myElemHolders.end(); ++holder )
2917       (*holder)->beforeCompacting();
2918   }
2919   int oldCellSize = myCellFactory->GetMaxID();
2920
2921   // remove "holes" in SMDS numeration
2922   std::vector<int> idNodesOldToNew, idCellsNewToOld, idCellsOldToNew;
2923   myNodeFactory->Compact( idNodesOldToNew );
2924   myCellFactory->Compact( idCellsNewToOld );
2925
2926   // make VTK IDs correspond to SMDS IDs
2927   int newNodeSize = myNodeFactory->NbUsedElements();
2928   int newCellSize = myCellFactory->NbUsedElements();
2929   myGrid->compactGrid( idNodesOldToNew, newNodeSize, idCellsNewToOld, newCellSize );
2930
2931   if ( idsChange && !myElemHolders.empty() )
2932   {
2933     // idCellsNewToOld -> idCellsOldToNew
2934     idCellsOldToNew.resize( oldCellSize, oldCellSize );
2935     for ( size_t iNew = 0; iNew < idCellsNewToOld.size(); ++iNew )
2936     {
2937       if ( idCellsNewToOld[ iNew ] >= (int) idCellsOldToNew.size() )
2938         idCellsOldToNew.resize( ( 1 + idCellsNewToOld[ iNew ]) * 1.5, oldCellSize );
2939       idCellsOldToNew[ idCellsNewToOld[ iNew ]] = iNew;
2940     }
2941   }
2942
2943   std::set< SMDS_ElementHolder* >::iterator holder = myElemHolders.begin();
2944   for ( ; holder != myElemHolders.end(); ++holder )
2945     if ( idsChange )
2946       (*holder)->restoreElements( idNodesOldToNew, idCellsOldToNew );
2947     else
2948       (*holder)->compact();
2949
2950   return;
2951 }
2952
2953 int SMDS_Mesh::FromVtkToSmds( int vtkid ) const
2954 {
2955   return myCellFactory->FromVtkToSmds( vtkid );
2956 }
2957
2958 double SMDS_Mesh::getMaxDim()
2959 {
2960   double dmax = 1.e-3;
2961   if ((xmax - xmin) > dmax) dmax = xmax -xmin;
2962   if ((ymax - ymin) > dmax) dmax = ymax -ymin;
2963   if ((zmax - zmin) > dmax) dmax = zmax -zmin;
2964   return dmax;
2965 }
2966
2967 //! modification that needs compact structure and redraw
2968 void SMDS_Mesh::Modified()
2969 {
2970   if (this->myModified)
2971   {
2972     this->myModifTime++;
2973     myModified = false;
2974   }
2975 }
2976
2977 //! get last modification timeStamp
2978 vtkMTimeType SMDS_Mesh::GetMTime() const
2979 {
2980   return this->myModifTime;
2981 }
2982
2983 bool SMDS_Mesh::IsCompacted()
2984 {
2985   return ( this->myCompactTime == this->myModifTime );
2986 }
2987
2988 void SMDS_Mesh::setNbShapes( size_t nbShapes )
2989 {
2990   myNodeFactory->SetNbShapes( nbShapes );
2991 }