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