Salome HOME
d720fb6311d73edbead6bea1abe31b4e216df7b7
[modules/smesh.git] / src / SMDS / SMDS_Mesh.cxx
1 // Copyright (C) 2007-2019  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, suppress 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   int nbElems = myCellFactory->CompactChangePointers() ? -1 : myInfo.NbElements( type );
1546   return myCellFactory->GetIterator< SMDS_ElemIterator >( new SMDS_MeshElement::GeomFilter( type ),
1547                                                           nbElems);
1548 }
1549
1550 SMDS_ElemIteratorPtr SMDS_Mesh::elementEntityIterator(SMDSAbs_EntityType type) const
1551 {
1552   if ( type == SMDSEntity_Node )
1553   {
1554     return myNodeFactory->GetIterator< SMDS_ElemIterator >( new SMDS_MeshElement::NonNullFilter );
1555   }
1556   int nbElems = myCellFactory->CompactChangePointers() ? -1 : myInfo.NbElements( type );
1557   return myCellFactory->GetIterator<SMDS_ElemIterator>( new SMDS_MeshElement::EntityFilter( type ),
1558                                                         nbElems);
1559 }
1560
1561 ///////////////////////////////////////////////////////////////////////////////
1562 /// Return an iterator on elements of the current mesh factory
1563 ///////////////////////////////////////////////////////////////////////////////
1564 SMDS_ElemIteratorPtr SMDS_Mesh::elementsIterator(SMDSAbs_ElementType type) const
1565 {
1566   typedef SMDS_ElemIterator TIterator;
1567   switch ( type ) {
1568
1569   case SMDSAbs_All:
1570     return myCellFactory->GetIterator< TIterator >( new SMDS_MeshElement::NonNullFilter );
1571
1572   case SMDSAbs_Node:
1573     return myNodeFactory->GetIterator< TIterator >( new SMDS_MeshElement::NonNullFilter );
1574
1575   default:
1576     int nbElems = myCellFactory->CompactChangePointers() ? -1 : myInfo.NbElements( type );
1577     return myCellFactory->GetIterator< TIterator >( new SMDS_MeshElement::TypeFilter( type ),
1578                                                     nbElems);
1579   }
1580   return SMDS_ElemIteratorPtr();
1581 }
1582
1583 ///////////////////////////////////////////////////////////////////////////////
1584 ///Return an iterator on edges of the current mesh.
1585 ///////////////////////////////////////////////////////////////////////////////
1586
1587 SMDS_EdgeIteratorPtr SMDS_Mesh::edgesIterator() const
1588 {
1589   typedef SMDS_EdgeIterator TIterator;
1590   int nbElems = myCellFactory->CompactChangePointers() ? -1 : myInfo.NbEdges();
1591   return myCellFactory->GetIterator< TIterator >( new SMDS_MeshElement::TypeFilter( SMDSAbs_Edge ),
1592                                                   nbElems);
1593 }
1594
1595 ///////////////////////////////////////////////////////////////////////////////
1596 ///Return an iterator on faces of the current mesh.
1597 ///////////////////////////////////////////////////////////////////////////////
1598
1599 SMDS_FaceIteratorPtr SMDS_Mesh::facesIterator() const
1600 {
1601   typedef SMDS_FaceIterator TIterator;
1602   int nbElems = myCellFactory->CompactChangePointers() ? -1 : myInfo.NbFaces();
1603   return myCellFactory->GetIterator< TIterator >( new SMDS_MeshElement::TypeFilter( SMDSAbs_Face ),
1604                                                   nbElems);
1605 }
1606
1607 ///////////////////////////////////////////////////////////////////////////////
1608 ///Return an iterator on volumes of the current mesh.
1609 ///////////////////////////////////////////////////////////////////////////////
1610
1611 SMDS_VolumeIteratorPtr SMDS_Mesh::volumesIterator() const
1612 {
1613   typedef SMDS_VolumeIterator TIterator;
1614   int nbElems = myCellFactory->CompactChangePointers() ? -1 : myInfo.NbVolumes();
1615   return
1616     myCellFactory->GetIterator< TIterator >( new SMDS_MeshElement::TypeFilter( SMDSAbs_Volume ),
1617                                              nbElems );
1618 }
1619
1620 SMDS_NodeIteratorPtr SMDS_Mesh::shapeNodesIterator(int                  shapeID,
1621                                                    size_t               nbElemsToReturn,
1622                                                    const SMDS_MeshNode* sm1stNode) const
1623 {
1624   return myNodeFactory->GetShapeIterator< SMDS_NodeIterator >( shapeID, nbElemsToReturn, sm1stNode );
1625 }
1626
1627 SMDS_ElemIteratorPtr SMDS_Mesh::shapeElementsIterator(int                     shapeID,
1628                                                       size_t                  nbElemsToReturn,
1629                                                       const SMDS_MeshElement* sm1stElem) const
1630 {
1631   return myCellFactory->GetShapeIterator< SMDS_ElemIterator >( shapeID, nbElemsToReturn, sm1stElem );
1632 }
1633
1634 ///////////////////////////////////////////////////////////////////////////////
1635 /// Do intersection of sets (more than 2)
1636 ///////////////////////////////////////////////////////////////////////////////
1637 static std::set<const SMDS_MeshElement*> *
1638 intersectionOfSets( std::set<const SMDS_MeshElement*> vs[], int numberOfSets )
1639 {
1640   std::set<const SMDS_MeshElement*>* rsetA = new std::set<const SMDS_MeshElement*>(vs[0]);
1641   std::set<const SMDS_MeshElement*>* rsetB;
1642
1643   for(int i=0; i<numberOfSets-1; i++)
1644   {
1645     rsetB = new std::set<const SMDS_MeshElement*>();
1646     set_intersection(rsetA->begin(), rsetA->end(),
1647                      vs[i+1].begin(), vs[i+1].end(),
1648                      inserter(*rsetB, rsetB->begin()));
1649     delete rsetA;
1650     rsetA=rsetB;
1651   }
1652   return rsetA;
1653 }
1654 ///////////////////////////////////////////////////////////////////////////////
1655 /// Return the list of finite elements owning the given element: elements
1656 /// containing all the nodes of the given element, for instance faces and
1657 /// volumes containing a given edge.
1658 ///////////////////////////////////////////////////////////////////////////////
1659 static std::set<const SMDS_MeshElement*> * getFinitElements(const SMDS_MeshElement * element)
1660 {
1661   int numberOfSets=element->NbNodes();
1662   std::set<const SMDS_MeshElement*> *initSet = new std::set<const SMDS_MeshElement*>[numberOfSets];
1663
1664   SMDS_NodeIteratorPtr itNodes = element->nodeIterator();
1665
1666   int i = 0;
1667   while ( itNodes->more() )
1668   {
1669     const SMDS_MeshNode *   n = itNodes->next();
1670     for ( SMDS_ElemIteratorPtr itFe = n->GetInverseElementIterator(); itFe->more(); )
1671       initSet[i].insert( itFe->next() );
1672     i++;
1673   }
1674   std::set<const SMDS_MeshElement*> *retSet = intersectionOfSets( initSet, numberOfSets );
1675   delete [] initSet;
1676   return retSet;
1677 }
1678
1679 ///////////////////////////////////////////////////////////////////////////////
1680 /// Return the std::list of nodes used only by the given elements
1681 ///////////////////////////////////////////////////////////////////////////////
1682 static
1683 std::set<const SMDS_MeshElement*> *getExclusiveNodes(std::set<const SMDS_MeshElement*>& elements)
1684 {
1685   std::set<const SMDS_MeshElement*> *           toReturn = new std::set<const SMDS_MeshElement*>();
1686   std::set<const SMDS_MeshElement*>::iterator itElements = elements.begin();
1687
1688   while( itElements != elements.end() )
1689   {
1690     SMDS_NodeIteratorPtr itNodes = (*itElements)->nodeIterator();
1691     itElements++;
1692
1693     while( itNodes->more() )
1694     {
1695       const SMDS_MeshNode *   n = itNodes->next();
1696       SMDS_ElemIteratorPtr itFe = n->GetInverseElementIterator();
1697       std::set<const SMDS_MeshElement*> s;
1698       while ( itFe->more() )
1699         s.insert( itFe->next() );
1700       if ( s == elements ) toReturn->insert(n);
1701     }
1702   }
1703   return toReturn;
1704 }
1705
1706 ///////////////////////////////////////////////////////////////////////////////
1707 ///Find the children of an element that are made of given nodes
1708 ///@param setOfChildren The set in which matching children will be inserted
1709 ///@param element The element were to search matching children
1710 ///@param nodes The nodes that the children must have to be selected
1711 ///////////////////////////////////////////////////////////////////////////////
1712 void SMDS_Mesh::addChildrenWithNodes(std::set<const SMDS_MeshElement*>& setOfChildren,
1713                                      const SMDS_MeshElement *           element,
1714                                      std::set<const SMDS_MeshElement*>& nodes)
1715 {
1716   switch(element->GetType())
1717   {
1718   case SMDSAbs_Node:
1719     throw SALOME_Exception("Internal Error: This should not happen");
1720     break;
1721   case SMDSAbs_0DElement:
1722   case SMDSAbs_Ball:
1723   {
1724   }
1725   break;
1726   case SMDSAbs_Edge:
1727   {
1728     SMDS_ElemIteratorPtr itn=element->nodesIterator();
1729     while(itn->more())
1730     {
1731       const SMDS_MeshElement * e=itn->next();
1732       if(nodes.find(e)!=nodes.end())
1733       {
1734         setOfChildren.insert(element);
1735         break;
1736       }
1737     }
1738   } break;
1739   case SMDSAbs_Face:
1740   {
1741     SMDS_ElemIteratorPtr itn=element->nodesIterator();
1742     while(itn->more())
1743     {
1744       const SMDS_MeshElement * e=itn->next();
1745       if(nodes.find(e)!=nodes.end())
1746       {
1747         setOfChildren.insert(element);
1748         break;
1749       }
1750     }
1751   } break;
1752   case SMDSAbs_Volume:
1753   case SMDSAbs_NbElementTypes:
1754   case SMDSAbs_All: break;
1755   }
1756 }
1757
1758 ///////////////////////////////////////////////////////////////////////////////
1759 ///@param elem The element to delete
1760 ///@param removenodes if true remaining nodes will be removed
1761 ///////////////////////////////////////////////////////////////////////////////
1762 void SMDS_Mesh::RemoveElement(const SMDS_MeshElement * elem,
1763                               const bool               removenodes)
1764 {
1765   std::vector<const SMDS_MeshElement *> removedElems;
1766   std::vector<const SMDS_MeshElement *> removedNodes;
1767   RemoveElement( elem, removedElems, removedNodes, removenodes );
1768 }
1769
1770 ///////////////////////////////////////////////////////////////////////////////
1771 ///@param elem The element to delete
1772 ///@param removedElems to be filled with all removed elements
1773 ///@param removedNodes to be filled with all removed nodes
1774 ///@param removenodes if true remaining nodes will be removed
1775 ///////////////////////////////////////////////////////////////////////////////
1776 void SMDS_Mesh::RemoveElement(const SMDS_MeshElement *               elem,
1777                               std::vector<const SMDS_MeshElement *>& removedElems,
1778                               std::vector<const SMDS_MeshElement *>& removedNodes,
1779                               bool                                   removenodes)
1780 {
1781   // get finite elements built on elem
1782   std::set<const SMDS_MeshElement*> * s1;
1783   if (    (elem->GetType() == SMDSAbs_0DElement)
1784           ||  (elem->GetType() == SMDSAbs_Ball)
1785           ||  (elem->GetType() == SMDSAbs_Edge)
1786           ||  (elem->GetType() == SMDSAbs_Face)
1787           ||  (elem->GetType() == SMDSAbs_Volume) )
1788   {
1789     s1 = new std::set<const SMDS_MeshElement*> ();
1790     s1->insert(elem);
1791   }
1792   else
1793     s1 = getFinitElements(elem);
1794
1795   // get exclusive nodes (which would become free afterwards)
1796   std::set<const SMDS_MeshElement*> * s2;
1797   if (elem->GetType() == SMDSAbs_Node) // a node is removed
1798   {
1799     // do not remove nodes except elem
1800     s2 = new std::set<const SMDS_MeshElement*> ();
1801     s2->insert(elem);
1802     removenodes = true;
1803   }
1804   else
1805     s2 = getExclusiveNodes(*s1);
1806
1807   // form the set of finite and construction elements to remove
1808   std::set<const SMDS_MeshElement*> s3;
1809   std::set<const SMDS_MeshElement*>::iterator it = s1->begin();
1810   while (it != s1->end())
1811   {
1812     addChildrenWithNodes(s3, *it, *s2);
1813     s3.insert(*it);
1814     it++;
1815   }
1816   if (elem->GetType() != SMDSAbs_Node)
1817     s3.insert(elem);
1818
1819   // remove finite and construction elements
1820   for( it = s3.begin();it != s3.end(); ++it )
1821   {
1822     // Remove element from <InverseElements> of its nodes
1823     SMDS_NodeIteratorPtr itn = (*it)->nodeIterator();
1824     while (itn->more())
1825     {
1826       SMDS_MeshNode * n = const_cast<SMDS_MeshNode *> (itn->next());
1827       n->RemoveInverseElement((*it));
1828     }
1829
1830     int vtkid = (*it)->GetVtkID();
1831
1832     switch ((*it)->GetType()) {
1833     case SMDSAbs_Node:
1834       throw SALOME_Exception(LOCALIZED("Internal Error: This should not happen"));
1835       break;
1836     case SMDSAbs_Edge:      myInfo.RemoveEdge(*it);   break;
1837     case SMDSAbs_Face:      myInfo.RemoveFace(*it);   break;
1838     case SMDSAbs_Volume:    myInfo.RemoveVolume(*it); break;
1839     case SMDSAbs_Ball:      myInfo.myNbBalls--;       break;
1840     case SMDSAbs_0DElement: myInfo.myNb0DElements--;  break;
1841     case SMDSAbs_All: // avoid compilation warning
1842     case SMDSAbs_NbElementTypes: break;
1843     }
1844     removedElems.push_back( *it);
1845
1846     myCellFactory->Free( static_cast< const SMDS_MeshCell*>( *it ));
1847
1848     if (vtkid >= 0)
1849     {
1850       this->myGrid->GetCellTypesArray()->SetValue(vtkid, VTK_EMPTY_CELL);
1851     }
1852   }
1853
1854   // remove exclusive (free) nodes
1855   if (removenodes)
1856   {
1857     for ( it = s2->begin(); it != s2->end(); ++it )
1858     {
1859       myInfo.myNbNodes--;
1860       myNodeFactory->Free( (*it) );
1861       removedNodes.push_back((*it));
1862     }
1863   }
1864
1865   delete s2;
1866   delete s1;
1867 }
1868
1869
1870 ///////////////////////////////////////////////////////////////////////////////
1871 ///@param elem The element to delete
1872 ///////////////////////////////////////////////////////////////////////////////
1873 void SMDS_Mesh::RemoveFreeElement(const SMDS_MeshElement * elem)
1874 {
1875   const int           vtkId = elem->GetVtkID();
1876   SMDSAbs_ElementType aType = elem->GetType();
1877   if ( aType == SMDSAbs_Node )
1878   {
1879     // only free node can be removed by this method
1880     const SMDS_MeshNode* n = static_cast<const SMDS_MeshNode*>( elem );
1881     if ( n->NbInverseElements() == 0 ) { // free node
1882       myInfo.myNbNodes--;
1883       myNodeFactory->Free( n );
1884     }
1885     else
1886     {
1887       throw SALOME_Exception( LOCALIZED( "RemoveFreeElement: not a free node" ));
1888     }
1889   }
1890   else
1891   {
1892     // Remove element from <InverseElements> of its nodes
1893     SMDS_NodeIteratorPtr itn = elem->nodeIterator();
1894     while (itn->more()) {
1895       SMDS_MeshNode * n = const_cast<SMDS_MeshNode *>(itn->next());
1896       n->RemoveInverseElement(elem);
1897     }
1898
1899     // in meshes without descendants elements are always free
1900     switch (aType) {
1901     case SMDSAbs_0DElement: myInfo.remove(elem);       break;
1902     case SMDSAbs_Edge:      myInfo.RemoveEdge(elem);   break;
1903     case SMDSAbs_Face:      myInfo.RemoveFace(elem);   break;
1904     case SMDSAbs_Volume:    myInfo.RemoveVolume(elem); break;
1905     case SMDSAbs_Ball:      myInfo.remove(elem);       break;
1906     default: break;
1907     }
1908     myCellFactory->Free( elem );
1909
1910     this->myGrid->GetCellTypesArray()->SetValue(vtkId, VTK_EMPTY_CELL);
1911   }
1912 }
1913
1914 //=======================================================================
1915 /*!
1916  * Checks if the element is present in mesh.
1917  */
1918 //=======================================================================
1919
1920 bool SMDS_Mesh::Contains (const SMDS_MeshElement* elem) const
1921 {
1922   if ( !elem || elem->IsNull() )
1923     return false;
1924
1925   if ( elem->GetType() == SMDSAbs_Node )
1926     return ( elem == myNodeFactory->FindElement( elem->GetID() ));
1927
1928   return ( elem == myCellFactory->FindElement( elem->GetID() ));
1929 }
1930
1931 //=======================================================================
1932 //function : MaxNodeID
1933 //purpose  :
1934 //=======================================================================
1935
1936 int SMDS_Mesh::MaxNodeID() const
1937 {
1938   return myNodeFactory->GetMaxID();
1939 }
1940
1941 //=======================================================================
1942 //function : MinNodeID
1943 //purpose  :
1944 //=======================================================================
1945
1946 int SMDS_Mesh::MinNodeID() const
1947 {
1948   return myNodeFactory->GetMinID();
1949 }
1950
1951 //=======================================================================
1952 //function : MaxElementID
1953 //purpose  :
1954 //=======================================================================
1955
1956 int SMDS_Mesh::MaxElementID() const
1957 {
1958   return myCellFactory->GetMaxID();
1959 }
1960
1961 //=======================================================================
1962 //function : MinElementID
1963 //purpose  :
1964 //=======================================================================
1965
1966 int SMDS_Mesh::MinElementID() const
1967 {
1968   return myCellFactory->GetMinID();
1969 }
1970
1971 //=======================================================================
1972 //function : Renumber
1973 //purpose  : Renumber all nodes or elements.
1974 //=======================================================================
1975
1976 // void SMDS_Mesh::Renumber (const bool isNodes, const int  startID, const int  deltaID)
1977 // {
1978 //   if ( deltaID == 0 )
1979 //     return;
1980
1981 // }
1982
1983 //=======================================================================
1984 //function : GetElementType
1985 //purpose  : Return type of element or node with id
1986 //=======================================================================
1987
1988 SMDSAbs_ElementType SMDS_Mesh::GetElementType( const int id, const bool iselem ) const
1989 {
1990   const SMDS_MeshElement* elem = 0;
1991   if( iselem )
1992     elem = myCellFactory->FindElement( id );
1993   else
1994     elem = myNodeFactory->FindElement( id );
1995
1996   return elem ? elem->GetType() : SMDSAbs_All;
1997 }
1998
1999
2000
2001 //********************************************************************
2002 //********************************************************************
2003 //********                                                   *********
2004 //*****       Methods for addition of quadratic elements        ******
2005 //********                                                   *********
2006 //********************************************************************
2007 //********************************************************************
2008
2009 //=======================================================================
2010 //function : AddEdgeWithID
2011 //purpose  :
2012 //=======================================================================
2013 SMDS_MeshEdge* SMDS_Mesh::AddEdgeWithID(int n1, int n2, int n12, int ID)
2014 {
2015   return SMDS_Mesh::AddEdgeWithID (myNodeFactory->FindNode(n1),
2016                                    myNodeFactory->FindNode(n2),
2017                                    myNodeFactory->FindNode(n12),
2018                                    ID);
2019 }
2020
2021 //=======================================================================
2022 //function : AddEdge
2023 //purpose  :
2024 //=======================================================================
2025 SMDS_MeshEdge* SMDS_Mesh::AddEdge(const SMDS_MeshNode* n1,
2026                                   const SMDS_MeshNode* n2,
2027                                   const SMDS_MeshNode* n12)
2028 {
2029   return SMDS_Mesh::AddEdgeWithID(n1, n2, n12, myCellFactory->GetFreeID());
2030 }
2031
2032 //=======================================================================
2033 //function : AddEdgeWithID
2034 //purpose  :
2035 //=======================================================================
2036 SMDS_MeshEdge* SMDS_Mesh::AddEdgeWithID(const SMDS_MeshNode * n1,
2037                                         const SMDS_MeshNode * n2,
2038                                         const SMDS_MeshNode * n12,
2039                                         int                   ID)
2040 {
2041   if ( !n1 || !n2 || !n12 ) return 0;
2042
2043   if ( SMDS_MeshCell* cell = myCellFactory->NewCell( ID ))
2044   {
2045     cell->init( SMDSEntity_Quad_Edge, /*nbNodes=*/3, n1, n2, n12 );
2046     myInfo.myNbQuadEdges++;
2047     return static_cast<SMDS_MeshEdge*>( cell );
2048   }
2049   return 0;
2050 }
2051
2052
2053 //=======================================================================
2054 //function : AddFace
2055 //purpose  :
2056 //=======================================================================
2057 SMDS_MeshFace* SMDS_Mesh::AddFace(const SMDS_MeshNode * n1,
2058                                   const SMDS_MeshNode * n2,
2059                                   const SMDS_MeshNode * n3,
2060                                   const SMDS_MeshNode * n12,
2061                                   const SMDS_MeshNode * n23,
2062                                   const SMDS_MeshNode * n31)
2063 {
2064   return SMDS_Mesh::AddFaceWithID(n1,n2,n3,n12,n23,n31,
2065                                   myCellFactory->GetFreeID());
2066 }
2067
2068 //=======================================================================
2069 //function : AddFaceWithID
2070 //purpose  :
2071 //=======================================================================
2072 SMDS_MeshFace* SMDS_Mesh::AddFaceWithID(int n1, int n2, int n3,
2073                                         int n12,int n23,int n31, int ID)
2074 {
2075   return SMDS_Mesh::AddFaceWithID (myNodeFactory->FindNode(n1) ,
2076                                    myNodeFactory->FindNode(n2) ,
2077                                    myNodeFactory->FindNode(n3) ,
2078                                    myNodeFactory->FindNode(n12),
2079                                    myNodeFactory->FindNode(n23),
2080                                    myNodeFactory->FindNode(n31),
2081                                    ID);
2082 }
2083
2084 //=======================================================================
2085 //function : AddFaceWithID
2086 //purpose  :
2087 //=======================================================================
2088 SMDS_MeshFace* SMDS_Mesh::AddFaceWithID(const SMDS_MeshNode * n1,
2089                                         const SMDS_MeshNode * n2,
2090                                         const SMDS_MeshNode * n3,
2091                                         const SMDS_MeshNode * n12,
2092                                         const SMDS_MeshNode * n23,
2093                                         const SMDS_MeshNode * n31,
2094                                         int ID)
2095 {
2096   if ( !n1 || !n2 || !n3 || !n12 || !n23 || !n31 ) return 0;
2097   if ( NbFaces() % CHECKMEMORY_INTERVAL == 0 ) CheckMemory();
2098
2099   if ( SMDS_MeshCell* cell = myCellFactory->NewCell( ID ))
2100   {
2101     cell->init( SMDSEntity_Quad_Triangle, /*nbNodes=*/6, n1, n2, n3, n12, n23, n31 );
2102     myInfo.myNbQuadTriangles++;
2103     return static_cast<SMDS_MeshFace*>( cell );
2104   }
2105   return 0;
2106 }
2107
2108
2109 //=======================================================================
2110 //function : AddFace
2111 //purpose  :
2112 //=======================================================================
2113 SMDS_MeshFace* SMDS_Mesh::AddFace(const SMDS_MeshNode * n1,
2114                                   const SMDS_MeshNode * n2,
2115                                   const SMDS_MeshNode * n3,
2116                                   const SMDS_MeshNode * n12,
2117                                   const SMDS_MeshNode * n23,
2118                                   const SMDS_MeshNode * n31,
2119                                   const SMDS_MeshNode * nCenter)
2120 {
2121   return SMDS_Mesh::AddFaceWithID(n1,n2,n3,n12,n23,n31,nCenter,
2122                                   myCellFactory->GetFreeID());
2123 }
2124
2125 //=======================================================================
2126 //function : AddFaceWithID
2127 //purpose  :
2128 //=======================================================================
2129 SMDS_MeshFace* SMDS_Mesh::AddFaceWithID(int n1, int n2, int n3,
2130                                         int n12,int n23,int n31, int nCenter, int ID)
2131 {
2132   return SMDS_Mesh::AddFaceWithID (myNodeFactory->FindNode(n1) ,
2133                                    myNodeFactory->FindNode(n2) ,
2134                                    myNodeFactory->FindNode(n3) ,
2135                                    myNodeFactory->FindNode(n12),
2136                                    myNodeFactory->FindNode(n23),
2137                                    myNodeFactory->FindNode(n31),
2138                                    myNodeFactory->FindNode(nCenter),
2139                                    ID);
2140 }
2141
2142 //=======================================================================
2143 //function : AddFaceWithID
2144 //purpose  :
2145 //=======================================================================
2146 SMDS_MeshFace* SMDS_Mesh::AddFaceWithID(const SMDS_MeshNode * n1,
2147                                         const SMDS_MeshNode * n2,
2148                                         const SMDS_MeshNode * n3,
2149                                         const SMDS_MeshNode * n12,
2150                                         const SMDS_MeshNode * n23,
2151                                         const SMDS_MeshNode * n31,
2152                                         const SMDS_MeshNode * nCenter,
2153                                         int ID)
2154 {
2155   if ( !n1 || !n2 || !n3 || !n12 || !n23 || !n31 || !nCenter) return 0;
2156   if ( NbFaces() % CHECKMEMORY_INTERVAL == 0 ) CheckMemory();
2157
2158   if ( SMDS_MeshCell* cell = myCellFactory->NewCell( ID ))
2159   {
2160     cell->init( SMDSEntity_BiQuad_Triangle, /*nbNodes=*/7, n1, n2, n3, n12, n23, n31, nCenter );
2161     myInfo.myNbBiQuadTriangles++;
2162     return static_cast<SMDS_MeshFace*>( cell );
2163   }
2164   return 0;
2165 }
2166
2167
2168 //=======================================================================
2169 //function : AddFace
2170 //purpose  :
2171 //=======================================================================
2172 SMDS_MeshFace* SMDS_Mesh::AddFace(const SMDS_MeshNode * n1,
2173                                   const SMDS_MeshNode * n2,
2174                                   const SMDS_MeshNode * n3,
2175                                   const SMDS_MeshNode * n4,
2176                                   const SMDS_MeshNode * n12,
2177                                   const SMDS_MeshNode * n23,
2178                                   const SMDS_MeshNode * n34,
2179                                   const SMDS_MeshNode * n41)
2180 {
2181   return SMDS_Mesh::AddFaceWithID(n1,n2,n3,n4,n12,n23,n34,n41,
2182                                   myCellFactory->GetFreeID());
2183 }
2184
2185 //=======================================================================
2186 //function : AddFaceWithID
2187 //purpose  :
2188 //=======================================================================
2189 SMDS_MeshFace* SMDS_Mesh::AddFaceWithID(int n1, int n2, int n3, int n4,
2190                                         int n12,int n23,int n34,int n41, int ID)
2191 {
2192   return SMDS_Mesh::AddFaceWithID (myNodeFactory->FindNode(n1) ,
2193                                    myNodeFactory->FindNode(n2) ,
2194                                    myNodeFactory->FindNode(n3) ,
2195                                    myNodeFactory->FindNode(n4) ,
2196                                    myNodeFactory->FindNode(n12),
2197                                    myNodeFactory->FindNode(n23),
2198                                    myNodeFactory->FindNode(n34),
2199                                    myNodeFactory->FindNode(n41),
2200                                    ID);
2201 }
2202
2203 //=======================================================================
2204 //function : AddFaceWithID
2205 //purpose  :
2206 //=======================================================================
2207 SMDS_MeshFace* SMDS_Mesh::AddFaceWithID(const SMDS_MeshNode * n1,
2208                                         const SMDS_MeshNode * n2,
2209                                         const SMDS_MeshNode * n3,
2210                                         const SMDS_MeshNode * n4,
2211                                         const SMDS_MeshNode * n12,
2212                                         const SMDS_MeshNode * n23,
2213                                         const SMDS_MeshNode * n34,
2214                                         const SMDS_MeshNode * n41,
2215                                         int ID)
2216 {
2217   if ( !n1 || !n2 || !n3 || !n4 || !n12 || !n23 || !n34 || !n41) return 0;
2218   if ( NbFaces() % CHECKMEMORY_INTERVAL == 0 ) CheckMemory();
2219
2220   if ( SMDS_MeshCell* cell = myCellFactory->NewCell( ID ))
2221   {
2222     cell->init( SMDSEntity_Quad_Quadrangle, /*nbNodes=*/8, n1, n2, n3, n4, n12, n23, n34, n41 );
2223     myInfo.myNbQuadQuadrangles++;
2224     return static_cast<SMDS_MeshFace*>( cell );
2225   }
2226   return 0;
2227 }
2228
2229 //=======================================================================
2230 //function : AddFace
2231 //purpose  :
2232 //=======================================================================
2233 SMDS_MeshFace* SMDS_Mesh::AddFace(const SMDS_MeshNode * n1,
2234                                   const SMDS_MeshNode * n2,
2235                                   const SMDS_MeshNode * n3,
2236                                   const SMDS_MeshNode * n4,
2237                                   const SMDS_MeshNode * n12,
2238                                   const SMDS_MeshNode * n23,
2239                                   const SMDS_MeshNode * n34,
2240                                   const SMDS_MeshNode * n41,
2241                                   const SMDS_MeshNode * nCenter)
2242 {
2243   return SMDS_Mesh::AddFaceWithID(n1,n2,n3,n4,n12,n23,n34,n41,nCenter,
2244                                   myCellFactory->GetFreeID());
2245 }
2246
2247 //=======================================================================
2248 //function : AddFaceWithID
2249 //purpose  :
2250 //=======================================================================
2251 SMDS_MeshFace* SMDS_Mesh::AddFaceWithID(int n1, int n2, int n3, int n4,
2252                                         int n12,int n23,int n34,int n41, int nCenter, int ID)
2253 {
2254   return SMDS_Mesh::AddFaceWithID (myNodeFactory->FindNode(n1) ,
2255                                    myNodeFactory->FindNode(n2) ,
2256                                    myNodeFactory->FindNode(n3) ,
2257                                    myNodeFactory->FindNode(n4) ,
2258                                    myNodeFactory->FindNode(n12),
2259                                    myNodeFactory->FindNode(n23),
2260                                    myNodeFactory->FindNode(n34),
2261                                    myNodeFactory->FindNode(n41),
2262                                    myNodeFactory->FindNode(nCenter),
2263                                    ID);
2264 }
2265
2266 //=======================================================================
2267 //function : AddFaceWithID
2268 //purpose  :
2269 //=======================================================================
2270 SMDS_MeshFace* SMDS_Mesh::AddFaceWithID(const SMDS_MeshNode * n1,
2271                                         const SMDS_MeshNode * n2,
2272                                         const SMDS_MeshNode * n3,
2273                                         const SMDS_MeshNode * n4,
2274                                         const SMDS_MeshNode * n12,
2275                                         const SMDS_MeshNode * n23,
2276                                         const SMDS_MeshNode * n34,
2277                                         const SMDS_MeshNode * n41,
2278                                         const SMDS_MeshNode * nCenter,
2279                                         int ID)
2280 {
2281   if ( !n1 || !n2 || !n3 || !n4 || !n12 || !n23 || !n34 || !n41 || !nCenter) return 0;
2282   if ( NbFaces() % CHECKMEMORY_INTERVAL == 0 ) CheckMemory();
2283
2284   if ( SMDS_MeshCell* cell = myCellFactory->NewCell( ID ))
2285   {
2286     cell->init( SMDSEntity_BiQuad_Quadrangle,
2287                 /*nbNodes=*/9, n1, n2, n3, n4, n12, n23, n34, n41, nCenter );
2288     myInfo.myNbBiQuadQuadrangles++;
2289     return static_cast<SMDS_MeshFace*>( cell );
2290   }
2291   return 0;
2292 }
2293
2294
2295 //=======================================================================
2296 //function : AddVolume
2297 //purpose  :
2298 //=======================================================================
2299 SMDS_MeshVolume* SMDS_Mesh::AddVolume(const SMDS_MeshNode * n1,
2300                                       const SMDS_MeshNode * n2,
2301                                       const SMDS_MeshNode * n3,
2302                                       const SMDS_MeshNode * n4,
2303                                       const SMDS_MeshNode * n12,
2304                                       const SMDS_MeshNode * n23,
2305                                       const SMDS_MeshNode * n31,
2306                                       const SMDS_MeshNode * n14,
2307                                       const SMDS_MeshNode * n24,
2308                                       const SMDS_MeshNode * n34)
2309 {
2310   return SMDS_Mesh::AddVolumeWithID(n1, n2, n3, n4, n12, n23,
2311                                     n31, n14, n24, n34, myCellFactory->GetFreeID());
2312 }
2313
2314 //=======================================================================
2315 //function : AddVolumeWithID
2316 //purpose  :
2317 //=======================================================================
2318 SMDS_MeshVolume* SMDS_Mesh::AddVolumeWithID(int n1, int n2, int n3, int n4,
2319                                             int n12,int n23,int n31,
2320                                             int n14,int n24,int n34, int ID)
2321 {
2322   return SMDS_Mesh::AddVolumeWithID (myNodeFactory->FindNode(n1) ,
2323                                      myNodeFactory->FindNode(n2) ,
2324                                      myNodeFactory->FindNode(n3) ,
2325                                      myNodeFactory->FindNode(n4) ,
2326                                      myNodeFactory->FindNode(n12),
2327                                      myNodeFactory->FindNode(n23),
2328                                      myNodeFactory->FindNode(n31),
2329                                      myNodeFactory->FindNode(n14),
2330                                      myNodeFactory->FindNode(n24),
2331                                      myNodeFactory->FindNode(n34),
2332                                      ID);
2333 }
2334
2335 //=======================================================================
2336 //function : AddVolumeWithID
2337 //purpose  : 2d order tetrahedron of 10 nodes
2338 //=======================================================================
2339 SMDS_MeshVolume* SMDS_Mesh::AddVolumeWithID(const SMDS_MeshNode * n1,
2340                                             const SMDS_MeshNode * n2,
2341                                             const SMDS_MeshNode * n3,
2342                                             const SMDS_MeshNode * n4,
2343                                             const SMDS_MeshNode * n12,
2344                                             const SMDS_MeshNode * n23,
2345                                             const SMDS_MeshNode * n31,
2346                                             const SMDS_MeshNode * n14,
2347                                             const SMDS_MeshNode * n24,
2348                                             const SMDS_MeshNode * n34,
2349                                             int ID)
2350 {
2351   if ( !n1 || !n2 || !n3 || !n4 || !n12 || !n23 || !n31 || !n14 || !n24 || !n34)
2352     return 0;
2353   if ( NbVolumes() % CHECKMEMORY_INTERVAL == 0 ) CheckMemory();
2354
2355   if ( SMDS_MeshCell* cell = myCellFactory->NewCell( ID ))
2356   {
2357     cell->init( SMDSEntity_Quad_Tetra,
2358                 /*nbNodes=*/10, n1, n2, n3, n4, n12, n23, n31, n14, n24, n34 );
2359     myInfo.myNbQuadTetras++;
2360     return static_cast<SMDS_MeshVolume*>( cell );
2361   }
2362   return 0;
2363 }
2364
2365
2366 //=======================================================================
2367 //function : AddVolume
2368 //purpose  :
2369 //=======================================================================
2370 SMDS_MeshVolume* SMDS_Mesh::AddVolume(const SMDS_MeshNode * n1,
2371                                       const SMDS_MeshNode * n2,
2372                                       const SMDS_MeshNode * n3,
2373                                       const SMDS_MeshNode * n4,
2374                                       const SMDS_MeshNode * n5,
2375                                       const SMDS_MeshNode * n12,
2376                                       const SMDS_MeshNode * n23,
2377                                       const SMDS_MeshNode * n34,
2378                                       const SMDS_MeshNode * n41,
2379                                       const SMDS_MeshNode * n15,
2380                                       const SMDS_MeshNode * n25,
2381                                       const SMDS_MeshNode * n35,
2382                                       const SMDS_MeshNode * n45)
2383 {
2384   return SMDS_Mesh::AddVolumeWithID(n1, n2, n3, n4, n5, n12, n23, n34, n41,
2385                                     n15, n25, n35, n45, myCellFactory->GetFreeID());
2386 }
2387
2388 //=======================================================================
2389 //function : AddVolumeWithID
2390 //purpose  :
2391 //=======================================================================
2392 SMDS_MeshVolume* SMDS_Mesh::AddVolumeWithID(int n1, int n2, int n3, int n4, int n5,
2393                                             int n12,int n23,int n34,int n41,
2394                                             int n15,int n25,int n35,int n45, int ID)
2395 {
2396   return SMDS_Mesh::AddVolumeWithID (myNodeFactory->FindNode(n1) ,
2397                                      myNodeFactory->FindNode(n2) ,
2398                                      myNodeFactory->FindNode(n3) ,
2399                                      myNodeFactory->FindNode(n4) ,
2400                                      myNodeFactory->FindNode(n5) ,
2401                                      myNodeFactory->FindNode(n12),
2402                                      myNodeFactory->FindNode(n23),
2403                                      myNodeFactory->FindNode(n34),
2404                                      myNodeFactory->FindNode(n41),
2405                                      myNodeFactory->FindNode(n15),
2406                                      myNodeFactory->FindNode(n25),
2407                                      myNodeFactory->FindNode(n35),
2408                                      myNodeFactory->FindNode(n45),
2409                                      ID);
2410 }
2411
2412 //=======================================================================
2413 //function : AddVolumeWithID
2414 //purpose  : 2d order pyramid of 13 nodes
2415 //=======================================================================
2416 SMDS_MeshVolume* SMDS_Mesh::AddVolumeWithID(const SMDS_MeshNode * n1,
2417                                             const SMDS_MeshNode * n2,
2418                                             const SMDS_MeshNode * n3,
2419                                             const SMDS_MeshNode * n4,
2420                                             const SMDS_MeshNode * n5,
2421                                             const SMDS_MeshNode * n12,
2422                                             const SMDS_MeshNode * n23,
2423                                             const SMDS_MeshNode * n34,
2424                                             const SMDS_MeshNode * n41,
2425                                             const SMDS_MeshNode * n15,
2426                                             const SMDS_MeshNode * n25,
2427                                             const SMDS_MeshNode * n35,
2428                                             const SMDS_MeshNode * n45,
2429                                             int ID)
2430 {
2431   if (!n1 || !n2 || !n3 || !n4 || !n5 || !n12 || !n23 ||
2432       !n34 || !n41 || !n15 || !n25 || !n35 || !n45)
2433     return 0;
2434   if ( NbVolumes() % CHECKMEMORY_INTERVAL == 0 ) CheckMemory();
2435
2436   if ( SMDS_MeshCell* cell = myCellFactory->NewCell( ID ))
2437   {
2438     cell->init( SMDSEntity_Quad_Pyramid,
2439                 /*nbNodes=*/13, n1, n2, n3, n4, n5, n12, n23, n34, n41, n15, n25, n35, n45);
2440     myInfo.myNbQuadPyramids++;
2441     return static_cast<SMDS_MeshVolume*>( cell );
2442   }
2443   return 0;
2444 }
2445
2446
2447 //=======================================================================
2448 //function : AddVolume
2449 //purpose  : 2d order Pentahedron (prism) with 15 nodes
2450 //=======================================================================
2451 SMDS_MeshVolume* SMDS_Mesh::AddVolume(const SMDS_MeshNode * n1,
2452                                       const SMDS_MeshNode * n2,
2453                                       const SMDS_MeshNode * n3,
2454                                       const SMDS_MeshNode * n4,
2455                                       const SMDS_MeshNode * n5,
2456                                       const SMDS_MeshNode * n6,
2457                                       const SMDS_MeshNode * n12,
2458                                       const SMDS_MeshNode * n23,
2459                                       const SMDS_MeshNode * n31,
2460                                       const SMDS_MeshNode * n45,
2461                                       const SMDS_MeshNode * n56,
2462                                       const SMDS_MeshNode * n64,
2463                                       const SMDS_MeshNode * n14,
2464                                       const SMDS_MeshNode * n25,
2465                                       const SMDS_MeshNode * n36)
2466 {
2467   return SMDS_Mesh::AddVolumeWithID(n1, n2, n3, n4, n5, n6, n12, n23, n31,
2468                                     n45, n56, n64, n14, n25, n36, myCellFactory->GetFreeID());
2469 }
2470
2471 //=======================================================================
2472 //function : AddVolumeWithID
2473 //purpose  : 2d order Pentahedron (prism) with 15 nodes
2474 //=======================================================================
2475 SMDS_MeshVolume* SMDS_Mesh::AddVolumeWithID(int n1, int n2, int n3,
2476                                             int n4, int n5, int n6,
2477                                             int n12,int n23,int n31,
2478                                             int n45,int n56,int n64,
2479                                             int n14,int n25,int n36, int ID)
2480 {
2481   return SMDS_Mesh::AddVolumeWithID (myNodeFactory->FindNode(n1) ,
2482                                      myNodeFactory->FindNode(n2) ,
2483                                      myNodeFactory->FindNode(n3) ,
2484                                      myNodeFactory->FindNode(n4) ,
2485                                      myNodeFactory->FindNode(n5) ,
2486                                      myNodeFactory->FindNode(n6) ,
2487                                      myNodeFactory->FindNode(n12),
2488                                      myNodeFactory->FindNode(n23),
2489                                      myNodeFactory->FindNode(n31),
2490                                      myNodeFactory->FindNode(n45),
2491                                      myNodeFactory->FindNode(n56),
2492                                      myNodeFactory->FindNode(n64),
2493                                      myNodeFactory->FindNode(n14),
2494                                      myNodeFactory->FindNode(n25),
2495                                      myNodeFactory->FindNode(n36),
2496                                      ID);
2497 }
2498
2499 //=======================================================================
2500 //function : AddVolumeWithID
2501 //purpose  : 2d order Pentahedron (prism) with 15 nodes
2502 //=======================================================================
2503 SMDS_MeshVolume* SMDS_Mesh::AddVolumeWithID(const SMDS_MeshNode * n1,
2504                                             const SMDS_MeshNode * n2,
2505                                             const SMDS_MeshNode * n3,
2506                                             const SMDS_MeshNode * n4,
2507                                             const SMDS_MeshNode * n5,
2508                                             const SMDS_MeshNode * n6,
2509                                             const SMDS_MeshNode * n12,
2510                                             const SMDS_MeshNode * n23,
2511                                             const SMDS_MeshNode * n31,
2512                                             const SMDS_MeshNode * n45,
2513                                             const SMDS_MeshNode * n56,
2514                                             const SMDS_MeshNode * n64,
2515                                             const SMDS_MeshNode * n14,
2516                                             const SMDS_MeshNode * n25,
2517                                             const SMDS_MeshNode * n36,
2518                                             int ID)
2519 {
2520   if (!n1 || !n2 || !n3 || !n4 || !n5 || !n6 || !n12 || !n23 ||
2521       !n31 || !n45 || !n56 || !n64 || !n14 || !n25 || !n36)
2522     return 0;
2523   if ( NbVolumes() % CHECKMEMORY_INTERVAL == 0 ) CheckMemory();
2524
2525   if ( SMDS_MeshCell* cell = myCellFactory->NewCell( ID ))
2526   {
2527     cell->init( SMDSEntity_Quad_Penta, /*nbNodes=*/15,
2528                 n1, n2, n3, n4, n5, n6, n12, n23, n31, n45, n56, n64, n14, n25, n36 );
2529     myInfo.myNbQuadPrisms++;
2530     return static_cast<SMDS_MeshVolume*>( cell );
2531   }
2532   return 0;
2533 }
2534
2535 //=======================================================================
2536 //function : AddVolume
2537 //purpose  : 2d order Pentahedron (prism) with 18 nodes
2538 //=======================================================================
2539 SMDS_MeshVolume* SMDS_Mesh::AddVolume(const SMDS_MeshNode * n1,
2540                                       const SMDS_MeshNode * n2,
2541                                       const SMDS_MeshNode * n3,
2542                                       const SMDS_MeshNode * n4,
2543                                       const SMDS_MeshNode * n5,
2544                                       const SMDS_MeshNode * n6,
2545                                       const SMDS_MeshNode * n12,
2546                                       const SMDS_MeshNode * n23,
2547                                       const SMDS_MeshNode * n31,
2548                                       const SMDS_MeshNode * n45,
2549                                       const SMDS_MeshNode * n56,
2550                                       const SMDS_MeshNode * n64,
2551                                       const SMDS_MeshNode * n14,
2552                                       const SMDS_MeshNode * n25,
2553                                       const SMDS_MeshNode * n36,
2554                                       const SMDS_MeshNode * n1245,
2555                                       const SMDS_MeshNode * n2356,
2556                                       const SMDS_MeshNode * n1346)
2557 {
2558   return SMDS_Mesh::AddVolumeWithID(n1, n2, n3, n4, n5, n6, n12, n23, n31,
2559                                     n45, n56, n64, n14, n25, n36, n1245, n2356, n1346,
2560                                     myCellFactory->GetFreeID());
2561 }
2562
2563 //=======================================================================
2564 //function : AddVolumeWithID
2565 //purpose  : 2d order Pentahedron (prism) with 18 nodes
2566 //=======================================================================
2567 SMDS_MeshVolume* SMDS_Mesh::AddVolumeWithID(int n1, int n2, int n3,
2568                                             int n4, int n5, int n6,
2569                                             int n12,int n23,int n31,
2570                                             int n45,int n56,int n64,
2571                                             int n14,int n25,int n36,
2572                                             int n1245, int n2356, int n1346, int ID)
2573 {
2574   return SMDS_Mesh::AddVolumeWithID (myNodeFactory->FindNode(n1) ,
2575                                      myNodeFactory->FindNode(n2) ,
2576                                      myNodeFactory->FindNode(n3) ,
2577                                      myNodeFactory->FindNode(n4) ,
2578                                      myNodeFactory->FindNode(n5) ,
2579                                      myNodeFactory->FindNode(n6) ,
2580                                      myNodeFactory->FindNode(n12),
2581                                      myNodeFactory->FindNode(n23),
2582                                      myNodeFactory->FindNode(n31),
2583                                      myNodeFactory->FindNode(n45),
2584                                      myNodeFactory->FindNode(n56),
2585                                      myNodeFactory->FindNode(n64),
2586                                      myNodeFactory->FindNode(n14),
2587                                      myNodeFactory->FindNode(n25),
2588                                      myNodeFactory->FindNode(n36),
2589                                      myNodeFactory->FindNode(n1245),
2590                                      myNodeFactory->FindNode(n2356),
2591                                      myNodeFactory->FindNode(n1346),
2592                                      ID);
2593 }
2594
2595 //=======================================================================
2596 //function : AddVolumeWithID
2597 //purpose  : 2d order Pentahedron (prism) with 18 nodes
2598 //=======================================================================
2599 SMDS_MeshVolume* SMDS_Mesh::AddVolumeWithID(const SMDS_MeshNode * n1,
2600                                             const SMDS_MeshNode * n2,
2601                                             const SMDS_MeshNode * n3,
2602                                             const SMDS_MeshNode * n4,
2603                                             const SMDS_MeshNode * n5,
2604                                             const SMDS_MeshNode * n6,
2605                                             const SMDS_MeshNode * n12,
2606                                             const SMDS_MeshNode * n23,
2607                                             const SMDS_MeshNode * n31,
2608                                             const SMDS_MeshNode * n45,
2609                                             const SMDS_MeshNode * n56,
2610                                             const SMDS_MeshNode * n64,
2611                                             const SMDS_MeshNode * n14,
2612                                             const SMDS_MeshNode * n25,
2613                                             const SMDS_MeshNode * n36,
2614                                             const SMDS_MeshNode * n1245,
2615                                             const SMDS_MeshNode * n2356,
2616                                             const SMDS_MeshNode * n1346,
2617                                             int ID)
2618 {
2619   //MESSAGE("AddVolumeWithID penta18 "<< ID);
2620   if (!n1 || !n2 || !n3 || !n4 || !n5 || !n6 || !n12 || !n23 ||
2621       !n31 || !n45 || !n56 || !n64 || !n14 || !n25 || !n36 || !n1245 || !n2356 || !n1346)
2622     return 0;
2623   if ( NbVolumes() % CHECKMEMORY_INTERVAL == 0 ) CheckMemory();
2624
2625   if ( SMDS_MeshCell* cell = myCellFactory->NewCell( ID ))
2626   {
2627     cell->init( SMDSEntity_BiQuad_Penta, /*nbNodes=*/18, n1, n2, n3, n4, n5, n6,
2628                 n12, n23, n31, n45, n56, n64, n14, n25, n36, n1245, n2356, n1346 );
2629     myInfo.myNbBiQuadPrisms++;
2630     return static_cast<SMDS_MeshVolume*>( cell );
2631   }
2632   return 0;
2633 }
2634
2635
2636 //=======================================================================
2637 //function : AddVolume
2638 //purpose  :
2639 //=======================================================================
2640 SMDS_MeshVolume* SMDS_Mesh::AddVolume(const SMDS_MeshNode * n1,
2641                                       const SMDS_MeshNode * n2,
2642                                       const SMDS_MeshNode * n3,
2643                                       const SMDS_MeshNode * n4,
2644                                       const SMDS_MeshNode * n5,
2645                                       const SMDS_MeshNode * n6,
2646                                       const SMDS_MeshNode * n7,
2647                                       const SMDS_MeshNode * n8,
2648                                       const SMDS_MeshNode * n12,
2649                                       const SMDS_MeshNode * n23,
2650                                       const SMDS_MeshNode * n34,
2651                                       const SMDS_MeshNode * n41,
2652                                       const SMDS_MeshNode * n56,
2653                                       const SMDS_MeshNode * n67,
2654                                       const SMDS_MeshNode * n78,
2655                                       const SMDS_MeshNode * n85,
2656                                       const SMDS_MeshNode * n15,
2657                                       const SMDS_MeshNode * n26,
2658                                       const SMDS_MeshNode * n37,
2659                                       const SMDS_MeshNode * n48)
2660 {
2661   return SMDS_Mesh::AddVolumeWithID(n1, n2, n3, n4, n5, n6, n7, n8, n12, n23, n34, n41,
2662                                     n56, n67, n78, n85, n15, n26, n37, n48,
2663                                     myCellFactory->GetFreeID());
2664 }
2665
2666 //=======================================================================
2667 //function : AddVolumeWithID
2668 //purpose  :
2669 //=======================================================================
2670 SMDS_MeshVolume* SMDS_Mesh::AddVolumeWithID(int n1, int n2, int n3, int n4,
2671                                             int n5, int n6, int n7, int n8,
2672                                             int n12,int n23,int n34,int n41,
2673                                             int n56,int n67,int n78,int n85,
2674                                             int n15,int n26,int n37,int n48, int ID)
2675 {
2676   return SMDS_Mesh::AddVolumeWithID (myNodeFactory->FindNode(n1),
2677                                      myNodeFactory->FindNode(n2),
2678                                      myNodeFactory->FindNode(n3),
2679                                      myNodeFactory->FindNode(n4),
2680                                      myNodeFactory->FindNode(n5),
2681                                      myNodeFactory->FindNode(n6),
2682                                      myNodeFactory->FindNode(n7),
2683                                      myNodeFactory->FindNode(n8),
2684                                      myNodeFactory->FindNode(n12),
2685                                      myNodeFactory->FindNode(n23),
2686                                      myNodeFactory->FindNode(n34),
2687                                      myNodeFactory->FindNode(n41),
2688                                      myNodeFactory->FindNode(n56),
2689                                      myNodeFactory->FindNode(n67),
2690                                      myNodeFactory->FindNode(n78),
2691                                      myNodeFactory->FindNode(n85),
2692                                      myNodeFactory->FindNode(n15),
2693                                      myNodeFactory->FindNode(n26),
2694                                      myNodeFactory->FindNode(n37),
2695                                      myNodeFactory->FindNode(n48),
2696                                      ID);
2697 }
2698
2699 //=======================================================================
2700 //function : AddVolumeWithID
2701 //purpose  : 2d order Hexahedrons with 20 nodes
2702 //=======================================================================
2703 SMDS_MeshVolume* SMDS_Mesh::AddVolumeWithID(const SMDS_MeshNode * n1,
2704                                             const SMDS_MeshNode * n2,
2705                                             const SMDS_MeshNode * n3,
2706                                             const SMDS_MeshNode * n4,
2707                                             const SMDS_MeshNode * n5,
2708                                             const SMDS_MeshNode * n6,
2709                                             const SMDS_MeshNode * n7,
2710                                             const SMDS_MeshNode * n8,
2711                                             const SMDS_MeshNode * n12,
2712                                             const SMDS_MeshNode * n23,
2713                                             const SMDS_MeshNode * n34,
2714                                             const SMDS_MeshNode * n41,
2715                                             const SMDS_MeshNode * n56,
2716                                             const SMDS_MeshNode * n67,
2717                                             const SMDS_MeshNode * n78,
2718                                             const SMDS_MeshNode * n85,
2719                                             const SMDS_MeshNode * n15,
2720                                             const SMDS_MeshNode * n26,
2721                                             const SMDS_MeshNode * n37,
2722                                             const SMDS_MeshNode * n48,
2723                                             int ID)
2724 {
2725   if (!n1 || !n2 || !n3 || !n4 || !n5 || !n6 || !n7 || !n8 || !n12 || !n23 ||
2726       !n34 || !n41 || !n56 || !n67 || !n78 || !n85 || !n15 || !n26 || !n37 || !n48)
2727     return 0;
2728   if ( NbVolumes() % CHECKMEMORY_INTERVAL == 0 ) CheckMemory();
2729
2730   if ( SMDS_MeshCell* cell = myCellFactory->NewCell( ID ))
2731   {
2732     cell->init( SMDSEntity_Quad_Hexa, /*nbNodes=*/20, n1, n2, n3, n4, n5, n6, n7, n8,
2733                 n12, n23, n34, n41, n56, n67, n78, n85, n15, n26, n37, n48 );
2734     myInfo.myNbQuadHexas++;
2735     return static_cast<SMDS_MeshVolume*>( cell );
2736   }
2737   return 0;
2738 }
2739
2740 //=======================================================================
2741 //function : AddVolume
2742 //purpose  :
2743 //=======================================================================
2744 SMDS_MeshVolume* SMDS_Mesh::AddVolume(const SMDS_MeshNode * n1,
2745                                       const SMDS_MeshNode * n2,
2746                                       const SMDS_MeshNode * n3,
2747                                       const SMDS_MeshNode * n4,
2748                                       const SMDS_MeshNode * n5,
2749                                       const SMDS_MeshNode * n6,
2750                                       const SMDS_MeshNode * n7,
2751                                       const SMDS_MeshNode * n8,
2752                                       const SMDS_MeshNode * n12,
2753                                       const SMDS_MeshNode * n23,
2754                                       const SMDS_MeshNode * n34,
2755                                       const SMDS_MeshNode * n41,
2756                                       const SMDS_MeshNode * n56,
2757                                       const SMDS_MeshNode * n67,
2758                                       const SMDS_MeshNode * n78,
2759                                       const SMDS_MeshNode * n85,
2760                                       const SMDS_MeshNode * n15,
2761                                       const SMDS_MeshNode * n26,
2762                                       const SMDS_MeshNode * n37,
2763                                       const SMDS_MeshNode * n48,
2764                                       const SMDS_MeshNode * n1234,
2765                                       const SMDS_MeshNode * n1256,
2766                                       const SMDS_MeshNode * n2367,
2767                                       const SMDS_MeshNode * n3478,
2768                                       const SMDS_MeshNode * n1458,
2769                                       const SMDS_MeshNode * n5678,
2770                                       const SMDS_MeshNode * nCenter)
2771 {
2772   return SMDS_Mesh::AddVolumeWithID(n1, n2, n3, n4, n5, n6, n7, n8, n12, n23, n34, n41,
2773                                     n56, n67, n78, n85, n15, n26, n37, n48,
2774                                     n1234, n1256, n2367, n3478, n1458, n5678, nCenter,
2775                                     myCellFactory->GetFreeID());
2776 }
2777
2778 //=======================================================================
2779 //function : AddVolumeWithID
2780 //purpose  :
2781 //=======================================================================
2782 SMDS_MeshVolume* SMDS_Mesh::AddVolumeWithID(int n1, int n2, int n3, int n4,
2783                                             int n5, int n6, int n7, int n8,
2784                                             int n12,int n23,int n34,int n41,
2785                                             int n56,int n67,int n78,int n85,
2786                                             int n15,int n26,int n37,int n48,
2787                                             int n1234,int n1256,int n2367,int n3478,
2788                                             int n1458,int n5678,int nCenter, int ID)
2789 {
2790   return SMDS_Mesh::AddVolumeWithID (myNodeFactory->FindNode(n1),
2791                                      myNodeFactory->FindNode(n2),
2792                                      myNodeFactory->FindNode(n3),
2793                                      myNodeFactory->FindNode(n4),
2794                                      myNodeFactory->FindNode(n5),
2795                                      myNodeFactory->FindNode(n6),
2796                                      myNodeFactory->FindNode(n7),
2797                                      myNodeFactory->FindNode(n8),
2798                                      myNodeFactory->FindNode(n12),
2799                                      myNodeFactory->FindNode(n23),
2800                                      myNodeFactory->FindNode(n34),
2801                                      myNodeFactory->FindNode(n41),
2802                                      myNodeFactory->FindNode(n56),
2803                                      myNodeFactory->FindNode(n67),
2804                                      myNodeFactory->FindNode(n78),
2805                                      myNodeFactory->FindNode(n85),
2806                                      myNodeFactory->FindNode(n15),
2807                                      myNodeFactory->FindNode(n26),
2808                                      myNodeFactory->FindNode(n37),
2809                                      myNodeFactory->FindNode(n48),
2810                                      myNodeFactory->FindNode(n1234),
2811                                      myNodeFactory->FindNode(n1256),
2812                                      myNodeFactory->FindNode(n2367),
2813                                      myNodeFactory->FindNode(n3478),
2814                                      myNodeFactory->FindNode(n1458),
2815                                      myNodeFactory->FindNode(n5678),
2816                                      myNodeFactory->FindNode(nCenter),
2817                                      ID);
2818 }
2819
2820 //=======================================================================
2821 //function : AddVolumeWithID
2822 //purpose  : 2d order Hexahedrons with 27 nodes
2823 //=======================================================================
2824 SMDS_MeshVolume* SMDS_Mesh::AddVolumeWithID(const SMDS_MeshNode * n1,
2825                                             const SMDS_MeshNode * n2,
2826                                             const SMDS_MeshNode * n3,
2827                                             const SMDS_MeshNode * n4,
2828                                             const SMDS_MeshNode * n5,
2829                                             const SMDS_MeshNode * n6,
2830                                             const SMDS_MeshNode * n7,
2831                                             const SMDS_MeshNode * n8,
2832                                             const SMDS_MeshNode * n12,
2833                                             const SMDS_MeshNode * n23,
2834                                             const SMDS_MeshNode * n34,
2835                                             const SMDS_MeshNode * n41,
2836                                             const SMDS_MeshNode * n56,
2837                                             const SMDS_MeshNode * n67,
2838                                             const SMDS_MeshNode * n78,
2839                                             const SMDS_MeshNode * n85,
2840                                             const SMDS_MeshNode * n15,
2841                                             const SMDS_MeshNode * n26,
2842                                             const SMDS_MeshNode * n37,
2843                                             const SMDS_MeshNode * n48,
2844                                             const SMDS_MeshNode * n1234,
2845                                             const SMDS_MeshNode * n1256,
2846                                             const SMDS_MeshNode * n2367,
2847                                             const SMDS_MeshNode * n3478,
2848                                             const SMDS_MeshNode * n1458,
2849                                             const SMDS_MeshNode * n5678,
2850                                             const SMDS_MeshNode * nCenter,
2851                                             int ID)
2852 {
2853   if (!n1 || !n2 || !n3 || !n4 || !n5 || !n6 || !n7 || !n8 || !n12 || !n23 ||
2854       !n34 || !n41 || !n56 || !n67 || !n78 || !n85 || !n15 || !n26 || !n37 || !n48 ||
2855       !n1234 || !n1256 || !n2367 || !n3478 || !n1458 || !n5678 || !nCenter )
2856     return 0;
2857   if ( NbVolumes() % CHECKMEMORY_INTERVAL == 0 ) CheckMemory();
2858
2859   if ( SMDS_MeshCell* cell = myCellFactory->NewCell( ID ))
2860   {
2861     cell->init( SMDSEntity_TriQuad_Hexa, /*nbNodes=*/27, n1, n2, n3, n4, n5, n6, n7, n8,
2862                 n12, n23, n34, n41, n56, n67, n78, n85, n15, n26, n37, n48,
2863                 n1234, n1256, n2367, n3478, n1458, n5678, nCenter);
2864     myInfo.myNbTriQuadHexas++;
2865     return static_cast<SMDS_MeshVolume*>( cell );
2866   }
2867   return 0;
2868 }
2869
2870 void SMDS_Mesh::dumpGrid(std::string ficdump)
2871 {
2872   //  vtkUnstructuredGridWriter* aWriter = vtkUnstructuredGridWriter::New();
2873   //  aWriter->SetFileName(ficdump.c_str());
2874   //  aWriter->SetInput(myGrid);
2875   //  if(myGrid->GetNumberOfCells())
2876   //  {
2877   //    aWriter->Write();
2878   //  }
2879   //  aWriter->Delete();
2880   ficdump = ficdump + "_connectivity";
2881   std::ofstream ficcon(ficdump.c_str(), ios::out);
2882   int nbPoints = myGrid->GetNumberOfPoints();
2883   ficcon << "-------------------------------- points " <<  nbPoints << endl;
2884   for (int i=0; i<nbPoints; i++)
2885   {
2886     ficcon << i << " " << *(myGrid->GetPoint(i)) << " " << *(myGrid->GetPoint(i)+1) << " " << " " << *(myGrid->GetPoint(i)+2) << endl;
2887   }
2888   int nbCells = myGrid->GetNumberOfCells();
2889   ficcon << "-------------------------------- cells " <<  nbCells << endl;
2890   for (int i=0; i<nbCells; i++)
2891   {
2892     ficcon << i << " - " << myGrid->GetCell(i)->GetCellType() << " -";
2893     int nbptcell = myGrid->GetCell(i)->GetNumberOfPoints();
2894     vtkIdList *listid = myGrid->GetCell(i)->GetPointIds();
2895     for (int j=0; j<nbptcell; j++)
2896     {
2897       ficcon << " " <<  listid->GetId(j);
2898     }
2899     ficcon << endl;
2900   }
2901   ficcon << "-------------------------------- connectivity " <<  nbPoints << endl;
2902   vtkCellLinks *links = myGrid->GetLinks();
2903   for (int i=0; i<nbPoints; i++)
2904   {
2905     int ncells = links->GetNcells(i);
2906     vtkIdType *cells = links->GetCells(i);
2907     ficcon << i << " - " << ncells << " -";
2908     for (int j=0; j<ncells; j++)
2909     {
2910       ficcon << " " << cells[j];
2911     }
2912     ficcon << endl;
2913   }
2914   ficcon.close();
2915
2916 }
2917
2918 void SMDS_Mesh::CompactMesh()
2919 {
2920   this->myCompactTime = this->myModifTime;
2921
2922   bool idsChange = ( myNodeFactory->CompactChangePointers() ||
2923                      myCellFactory->CompactChangePointers() );
2924   if ( idsChange )
2925   {
2926     std::set< SMDS_ElementHolder* >::iterator holder = myElemHolders.begin();
2927     for ( ; holder != myElemHolders.end(); ++holder )
2928       (*holder)->beforeCompacting();
2929   }
2930   int oldCellSize = myCellFactory->GetMaxID();
2931
2932   // remove "holes" in SMDS numeration
2933   std::vector<int> idNodesOldToNew, idCellsNewToOld, idCellsOldToNew;
2934   myNodeFactory->Compact( idNodesOldToNew );
2935   myCellFactory->Compact( idCellsNewToOld );
2936
2937   // make VTK IDs correspond to SMDS IDs
2938   int newNodeSize = myNodeFactory->NbUsedElements();
2939   int newCellSize = myCellFactory->NbUsedElements();
2940   myGrid->compactGrid( idNodesOldToNew, newNodeSize, idCellsNewToOld, newCellSize );
2941
2942   if ( idsChange && !myElemHolders.empty() )
2943   {
2944     // idCellsNewToOld -> idCellsOldToNew
2945     idCellsOldToNew.resize( oldCellSize, oldCellSize );
2946     for ( size_t iNew = 0; iNew < idCellsNewToOld.size(); ++iNew )
2947     {
2948       if ( idCellsNewToOld[ iNew ] >= (int) idCellsOldToNew.size() )
2949         idCellsOldToNew.resize( ( 1 + idCellsNewToOld[ iNew ]) * 1.5, oldCellSize );
2950       idCellsOldToNew[ idCellsNewToOld[ iNew ]] = iNew;
2951     }
2952   }
2953
2954   std::set< SMDS_ElementHolder* >::iterator holder = myElemHolders.begin();
2955   for ( ; holder != myElemHolders.end(); ++holder )
2956     if ( idsChange )
2957       (*holder)->restoreElements( idNodesOldToNew, idCellsOldToNew );
2958     else
2959       (*holder)->compact();
2960
2961   return;
2962 }
2963
2964 int SMDS_Mesh::FromVtkToSmds( int vtkid ) const
2965 {
2966   return myCellFactory->FromVtkToSmds( vtkid );
2967 }
2968
2969 double SMDS_Mesh::getMaxDim()
2970 {
2971   double dmax = 1.e-3;
2972   if ((xmax - xmin) > dmax) dmax = xmax -xmin;
2973   if ((ymax - ymin) > dmax) dmax = ymax -ymin;
2974   if ((zmax - zmin) > dmax) dmax = zmax -zmin;
2975   return dmax;
2976 }
2977
2978 //! modification that needs compact structure and redraw
2979 void SMDS_Mesh::Modified()
2980 {
2981   if (this->myModified)
2982   {
2983     this->myModifTime++;
2984     myModified = false;
2985   }
2986 }
2987
2988 //! get last modification timeStamp
2989 vtkMTimeType SMDS_Mesh::GetMTime() const
2990 {
2991   return this->myModifTime;
2992 }
2993
2994 bool SMDS_Mesh::IsCompacted()
2995 {
2996   return ( this->myCompactTime == this->myModifTime );
2997 }
2998
2999 void SMDS_Mesh::setNbShapes( size_t nbShapes )
3000 {
3001   myNodeFactory->SetNbShapes( nbShapes );
3002 }