Salome HOME
#18963 Minimize compiler warnings
[modules/smesh.git] / src / SMDS / SMDS_Mesh.cxx
1 // Copyright (C) 2007-2020  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)
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 ( nodes.empty() )
835     throw std::invalid_argument("Polygon without nodes is forbidden");
836   if ( SMDS_MeshCell* cell = myCellFactory->NewCell( ID ))
837   {
838     cell->init( SMDSEntity_Polygon, nodes );
839     myInfo.myNbPolygons++;
840     return static_cast<SMDS_MeshFace*>( cell );
841   }
842   return 0;
843 }
844
845 ///////////////////////////////////////////////////////////////////////////////
846 /// Add a polygon defined by its nodes.
847 /// An ID is automatically affected to the created face.
848 ///////////////////////////////////////////////////////////////////////////////
849
850 SMDS_MeshFace* SMDS_Mesh::AddPolygonalFace (const std::vector<const SMDS_MeshNode*> & nodes)
851 {
852   return SMDS_Mesh::AddPolygonalFaceWithID(nodes, myCellFactory->GetFreeID());
853 }
854
855 ///////////////////////////////////////////////////////////////////////////////
856 /// Add a quadratic polygon defined by its nodes IDs
857 ///////////////////////////////////////////////////////////////////////////////
858
859 SMDS_MeshFace* SMDS_Mesh::AddQuadPolygonalFaceWithID (const std::vector<int> & nodes_ids,
860                                                       const int                ID)
861 {
862   std::vector<const SMDS_MeshNode*> nodes( nodes_ids.size() );
863   for ( size_t i = 0; i < nodes.size(); i++) {
864     nodes[i] = myNodeFactory->FindNode(nodes_ids[i]);
865     if (!nodes[i]) return NULL;
866   }
867   return SMDS_Mesh::AddQuadPolygonalFaceWithID(nodes, ID);
868 }
869
870 ///////////////////////////////////////////////////////////////////////////////
871 /// Add a quadratic polygon defined by its nodes
872 ///////////////////////////////////////////////////////////////////////////////
873
874 SMDS_MeshFace*
875 SMDS_Mesh::AddQuadPolygonalFaceWithID (const std::vector<const SMDS_MeshNode*> & nodes,
876                                        const int                                 ID)
877 {
878   if ( NbFaces() % CHECKMEMORY_INTERVAL == 0 ) CheckMemory();
879   if ( nodes.empty() )
880     throw std::invalid_argument("Polygon without nodes is forbidden");
881   if ( SMDS_MeshCell* cell = myCellFactory->NewCell( ID ))
882   {
883     cell->init( SMDSEntity_Quad_Polygon, nodes );
884     myInfo.myNbQuadPolygons++;
885     return static_cast<SMDS_MeshFace*>( cell );
886   }
887   return 0;
888 }
889
890 ///////////////////////////////////////////////////////////////////////////////
891 /// Add a quadratic polygon defined by its nodes.
892 /// An ID is automatically affected to the created face.
893 ///////////////////////////////////////////////////////////////////////////////
894
895 SMDS_MeshFace* SMDS_Mesh::AddQuadPolygonalFace (const std::vector<const SMDS_MeshNode*> & nodes)
896 {
897   return SMDS_Mesh::AddQuadPolygonalFaceWithID(nodes, myCellFactory->GetFreeID());
898 }
899
900 ///////////////////////////////////////////////////////////////////////////////
901 /// Create a new polyhedral volume and add it to the mesh.
902 /// @param ID The ID of the new volume
903 /// @return The created volume or NULL if an element with this ID already exists
904 /// or if input nodes are not found.
905 ///////////////////////////////////////////////////////////////////////////////
906
907 SMDS_MeshVolume * SMDS_Mesh::AddPolyhedralVolumeWithID (const std::vector<int> & nodes_ids,
908                                                         const std::vector<int> & quantities,
909                                                         const int                ID)
910 {
911   int nbNodes = nodes_ids.size();
912   std::vector<const SMDS_MeshNode*> nodes (nbNodes);
913   for (int i = 0; i < nbNodes; i++) {
914     nodes[i] = myNodeFactory->FindNode(nodes_ids[i]);
915     if (!nodes[i]) return NULL;
916   }
917   return SMDS_Mesh::AddPolyhedralVolumeWithID(nodes, quantities, ID);
918 }
919
920 ///////////////////////////////////////////////////////////////////////////////
921 /// Create a new polyhedral volume and add it to the mesh.
922 /// @param ID The ID of the new volume
923 /// @return The created  volume
924 ///////////////////////////////////////////////////////////////////////////////
925
926 SMDS_MeshVolume*
927 SMDS_Mesh::AddPolyhedralVolumeWithID (const std::vector<const SMDS_MeshNode*>& nodes,
928                                       const std::vector<int>                 & quantities,
929                                       const int                           ID)
930 {
931   if ( nodes.empty() || quantities.empty() )
932     return NULL;
933   if ( NbVolumes() % CHECKMEMORY_INTERVAL == 0 ) CheckMemory();
934
935   if ( SMDS_MeshCell* cell = myCellFactory->NewCell( ID ))
936   {
937     SMDS_MeshVolume* volume = static_cast<SMDS_MeshVolume*>( cell );
938     volume->init( nodes, quantities );
939     myInfo.myNbPolyhedrons++;
940     return volume;
941   }
942   return 0;
943 }
944
945 ///////////////////////////////////////////////////////////////////////////////
946 /// Create a new polyhedral volume and add it to the mesh.
947 /// @return The created  volume
948 ///////////////////////////////////////////////////////////////////////////////
949
950 SMDS_MeshVolume* SMDS_Mesh::AddPolyhedralVolume
951 (const std::vector<const SMDS_MeshNode*> & nodes,
952  const std::vector<int>                  & quantities)
953 {
954   int ID = myCellFactory->GetFreeID();
955   return SMDS_Mesh::AddPolyhedralVolumeWithID(nodes, quantities, ID);
956 }
957
958 SMDS_MeshVolume* SMDS_Mesh::AddVolumeFromVtkIds(const std::vector<vtkIdType>& vtkNodeIds)
959 {
960   SMDS_MeshCell*   cell = myCellFactory->NewCell( myCellFactory->GetFreeID() );
961   SMDS_MeshVolume * vol = static_cast<SMDS_MeshVolume*>( cell );
962   vol->init( vtkNodeIds );
963   myInfo.add( cell );
964   return vol;
965 }
966
967 SMDS_MeshFace* SMDS_Mesh::AddFaceFromVtkIds(const std::vector<vtkIdType>& vtkNodeIds)
968 {
969   SMDS_MeshCell* cell = myCellFactory->NewCell( myCellFactory->GetFreeID() );
970   SMDS_MeshFace *   f = static_cast<SMDS_MeshFace*>( cell );
971   f->init( vtkNodeIds );
972   myInfo.add( cell );
973   return f;
974 }
975
976 //=======================================================================
977 //function : MoveNode
978 //purpose  : 
979 //=======================================================================
980
981 void SMDS_Mesh::MoveNode(const SMDS_MeshNode *n, double x, double y, double z)
982 {
983   SMDS_MeshNode * node=const_cast<SMDS_MeshNode*>(n);
984   node->setXYZ(x,y,z);
985 }
986
987 ///////////////////////////////////////////////////////////////////////////////
988 /// Return the node whose SMDS ID is 'ID'.
989 ///////////////////////////////////////////////////////////////////////////////
990 const SMDS_MeshNode * SMDS_Mesh::FindNode(int ID) const
991 {
992   return myNodeFactory->FindNode( ID );
993 }
994
995 ///////////////////////////////////////////////////////////////////////////////
996 /// Return the node whose VTK ID is 'vtkId'.
997 ///////////////////////////////////////////////////////////////////////////////
998 const SMDS_MeshNode * SMDS_Mesh::FindNodeVtk(int vtkId) const
999 {
1000   return myNodeFactory->FindNode( vtkId + 1 );
1001 }
1002
1003 const SMDS_MeshElement * SMDS_Mesh::FindElementVtk(int IDelem) const
1004 {
1005   return myCellFactory->FindElement( FromVtkToSmds( IDelem ));
1006 }
1007
1008 ///////////////////////////////////////////////////////////////////////////////
1009 /// Remove a node and all the elements which own this node
1010 ///////////////////////////////////////////////////////////////////////////////
1011
1012 void SMDS_Mesh::RemoveNode(const SMDS_MeshNode * node)
1013 {
1014   RemoveElement(node, true);
1015 }
1016
1017 //=======================================================================
1018 //function : RemoveFromParent
1019 //purpose  :
1020 //=======================================================================
1021
1022 bool SMDS_Mesh::RemoveFromParent()
1023 {
1024   if (myParent==NULL) return false;
1025   else return (myParent->RemoveSubMesh(this));
1026 }
1027
1028 //=======================================================================
1029 //function : RemoveSubMesh
1030 //purpose  :
1031 //=======================================================================
1032
1033 bool SMDS_Mesh::RemoveSubMesh(const SMDS_Mesh * aMesh)
1034 {
1035   bool found = false;
1036
1037   std::list<SMDS_Mesh *>::iterator itmsh=myChildren.begin();
1038   for (; itmsh!=myChildren.end() && !found; itmsh++)
1039   {
1040     SMDS_Mesh * submesh = *itmsh;
1041     if (submesh == aMesh)
1042     {
1043       found = true;
1044       myChildren.erase(itmsh);
1045     }
1046   }
1047
1048   return found;
1049 }
1050
1051 //=======================================================================
1052 //function : ChangePolyhedronNodes
1053 //purpose  :
1054 //=======================================================================
1055
1056 bool SMDS_Mesh::ChangePolyhedronNodes(const SMDS_MeshElement *                 element,
1057                                       const std::vector<const SMDS_MeshNode*>& nodes,
1058                                       const std::vector<int>&                  quantities)
1059 {
1060   // keep current nodes of element
1061   std::set<const SMDS_MeshNode*> oldNodes( element->begin_nodes(), element->end_nodes() );
1062
1063   // change nodes
1064   bool Ok = false;
1065   if ( const SMDS_MeshVolume* vol = DownCast<SMDS_MeshVolume>( element ))
1066     Ok = vol->ChangeNodes( nodes, quantities );
1067
1068   if ( Ok )
1069   {
1070     setMyModified();
1071     updateInverseElements( element, &nodes[0], nodes.size(), oldNodes );
1072   }
1073   return Ok;
1074 }
1075
1076 //=======================================================================
1077 //function : ChangeElementNodes
1078 //purpose  :
1079 //=======================================================================
1080
1081 bool SMDS_Mesh::ChangeElementNodes(const SMDS_MeshElement * element,
1082                                    const SMDS_MeshNode    * nodes[],
1083                                    const int                nbnodes)
1084 {
1085   // keep current nodes of element
1086   std::set<const SMDS_MeshNode*> oldNodes( element->begin_nodes(), element->end_nodes() );
1087
1088   // change nodes
1089   bool Ok = false;
1090   if ( SMDS_MeshCell* cell = dynamic_cast<SMDS_MeshCell*>((SMDS_MeshElement*) element))
1091     Ok = cell->ChangeNodes(nodes, nbnodes);
1092
1093   if ( Ok )
1094   {
1095     setMyModified();
1096     updateInverseElements( element, nodes, nbnodes, oldNodes );
1097   }
1098   return Ok;
1099 }
1100
1101 //=======================================================================
1102 //function : updateInverseElements
1103 //purpose  : update InverseElements when element changes node
1104 //=======================================================================
1105
1106 void SMDS_Mesh::updateInverseElements( const SMDS_MeshElement *        element,
1107                                        const SMDS_MeshNode* const*     nodes,
1108                                        const int                       nbnodes,
1109                                        std::set<const SMDS_MeshNode*>& oldNodes )
1110 {
1111   if ( GetGrid()->HasLinks() ) // update InverseElements
1112   {
1113     std::set<const SMDS_MeshNode*>::iterator it;
1114
1115     // AddInverseElement to new nodes
1116     for ( int i = 0; i < nbnodes; i++ )
1117     {
1118       it = oldNodes.find( nodes[i] );
1119       if ( it == oldNodes.end() )
1120         // new node
1121         const_cast<SMDS_MeshNode*>( nodes[i] )->AddInverseElement( element );
1122       else
1123         // remove from oldNodes a node that remains in elem
1124         oldNodes.erase( it );
1125     }
1126     // RemoveInverseElement from the nodes removed from elem
1127     for ( it = oldNodes.begin(); it != oldNodes.end(); it++ )
1128     {
1129       SMDS_MeshNode * n = const_cast<SMDS_MeshNode *>( *it );
1130       n->RemoveInverseElement( element );
1131     }
1132   }
1133
1134 }
1135
1136 const SMDS_Mesh0DElement* SMDS_Mesh::Find0DElement(const SMDS_MeshNode * node)
1137 {
1138   if (!node) return 0;
1139   const SMDS_Mesh0DElement* toReturn = NULL;
1140   SMDS_ElemIteratorPtr it1 = node->GetInverseElementIterator(SMDSAbs_0DElement);
1141   while (it1->more() && (toReturn == NULL)) {
1142     const SMDS_MeshElement* e = it1->next();
1143     if (e->NbNodes() == 1) {
1144       toReturn = static_cast<const SMDS_Mesh0DElement*>(e);
1145     }
1146   }
1147   return toReturn;
1148 }
1149
1150 const SMDS_BallElement* SMDS_Mesh::FindBall(const SMDS_MeshNode * node)
1151 {
1152   if (!node) return 0;
1153   const SMDS_BallElement* toReturn = NULL;
1154   SMDS_ElemIteratorPtr it1 = node->GetInverseElementIterator(SMDSAbs_Ball);
1155   while (it1->more() && (toReturn == NULL)) {
1156     const SMDS_MeshElement* e = it1->next();
1157     if (e->GetGeomType() == SMDSGeom_BALL)
1158       toReturn = static_cast<const SMDS_BallElement*>(e);
1159   }
1160   return toReturn;
1161 }
1162
1163 const SMDS_MeshEdge* SMDS_Mesh::FindEdge(const SMDS_MeshNode * node1,
1164                                          const SMDS_MeshNode * node2)
1165 {
1166   if ( !node1 ) return 0;
1167   const SMDS_MeshEdge * toReturn=NULL;
1168   SMDS_ElemIteratorPtr it1=node1->GetInverseElementIterator(SMDSAbs_Edge);
1169   while(it1->more()) {
1170     const SMDS_MeshElement * e = it1->next();
1171     if ( e->NbNodes() == 2 && e->GetNodeIndex( node2 ) >= 0 ) {
1172       toReturn = static_cast<const SMDS_MeshEdge*>( e );
1173       break;
1174     }
1175   }
1176   return toReturn;
1177 }
1178
1179 const SMDS_MeshEdge* SMDS_Mesh::FindEdge(const SMDS_MeshNode * node1,
1180                                          const SMDS_MeshNode * node2,
1181                                          const SMDS_MeshNode * node3)
1182 {
1183   if ( !node1 ) return 0;
1184   SMDS_ElemIteratorPtr it1 = node1->GetInverseElementIterator(SMDSAbs_Edge);
1185   while(it1->more()) {
1186     const SMDS_MeshElement * e = it1->next();
1187     if ( e->NbNodes() == 3 ) {
1188       SMDS_ElemIteratorPtr it2 = e->nodesIterator();
1189       while(it2->more()) {
1190         const SMDS_MeshElement* n = it2->next();
1191         if( n!=node1 &&
1192             n!=node2 &&
1193             n!=node3 )
1194         {
1195           e = 0;
1196           break;
1197         }
1198       }
1199       if ( e )
1200         return static_cast<const SMDS_MeshEdge *> (e);
1201     }
1202   }
1203   return 0;
1204 }
1205
1206 //=======================================================================
1207 //function : FindFace
1208 //purpose  :
1209 //=======================================================================
1210
1211 const SMDS_MeshFace* SMDS_Mesh::FindFace(const SMDS_MeshNode *node1,
1212                                          const SMDS_MeshNode *node2,
1213                                          const SMDS_MeshNode *node3)
1214 {
1215   if ( !node1 ) return 0;
1216   SMDS_ElemIteratorPtr it1 = node1->GetInverseElementIterator(SMDSAbs_Face);
1217   while(it1->more()) {
1218     const SMDS_MeshElement * e = it1->next();
1219     if ( e->NbNodes() == 3 ) {
1220       SMDS_ElemIteratorPtr it2 = e->nodesIterator();
1221       while(it2->more()) {
1222         const SMDS_MeshElement* n = it2->next();
1223         if( n!=node1 &&
1224             n!=node2 &&
1225             n!=node3 )
1226         {
1227           e = 0;
1228           break;
1229         }
1230       }
1231       if ( e )
1232         return static_cast<const SMDS_MeshFace *> (e);
1233     }
1234   }
1235   return 0;
1236 }
1237
1238 //=======================================================================
1239 //function : FindFace
1240 //purpose  :
1241 //=======================================================================
1242
1243 const SMDS_MeshFace* SMDS_Mesh::FindFace(const SMDS_MeshNode *node1,
1244                                          const SMDS_MeshNode *node2,
1245                                          const SMDS_MeshNode *node3,
1246                                          const SMDS_MeshNode *node4)
1247 {
1248   if ( !node1 ) return 0;
1249   SMDS_ElemIteratorPtr it1 = node1->GetInverseElementIterator(SMDSAbs_Face);
1250   while(it1->more()) {
1251     const SMDS_MeshElement * e = it1->next();
1252     if ( e->NbNodes() == 4 ) {
1253       SMDS_ElemIteratorPtr it2 = e->nodesIterator();
1254       while(it2->more()) {
1255         const SMDS_MeshElement* n = it2->next();
1256         if( n!=node1 &&
1257             n!=node2 &&
1258             n!=node3 &&
1259             n!=node4 )
1260         {
1261           e = 0;
1262           break;
1263         }
1264       }
1265       if ( e )
1266         return static_cast<const SMDS_MeshFace *> (e);
1267     }
1268   }
1269   return 0;
1270 }
1271
1272 //=======================================================================
1273 //function : FindFace
1274 //purpose  :quadratic triangle
1275 //=======================================================================
1276
1277 const SMDS_MeshFace* SMDS_Mesh::FindFace(const SMDS_MeshNode *node1,
1278                                          const SMDS_MeshNode *node2,
1279                                          const SMDS_MeshNode *node3,
1280                                          const SMDS_MeshNode *node4,
1281                                          const SMDS_MeshNode *node5,
1282                                          const SMDS_MeshNode *node6)
1283 {
1284   if ( !node1 ) return 0;
1285   SMDS_ElemIteratorPtr it1 = node1->GetInverseElementIterator(SMDSAbs_Face);
1286   while(it1->more()) {
1287     const SMDS_MeshElement * e = it1->next();
1288     if ( e->NbNodes() == 6 ) {
1289       SMDS_ElemIteratorPtr it2 = e->nodesIterator();
1290       while(it2->more()) {
1291         const SMDS_MeshElement* n = it2->next();
1292         if( n!=node1 &&
1293             n!=node2 &&
1294             n!=node3 &&
1295             n!=node4 &&
1296             n!=node5 &&
1297             n!=node6 )
1298         {
1299           e = 0;
1300           break;
1301         }
1302       }
1303       if ( e )
1304         return static_cast<const SMDS_MeshFace *> (e);
1305     }
1306   }
1307   return 0;
1308 }
1309
1310
1311 //=======================================================================
1312 //function : FindFace
1313 //purpose  : quadratic quadrangle
1314 //=======================================================================
1315
1316 const SMDS_MeshFace* SMDS_Mesh::FindFace(const SMDS_MeshNode *node1,
1317                                          const SMDS_MeshNode *node2,
1318                                          const SMDS_MeshNode *node3,
1319                                          const SMDS_MeshNode *node4,
1320                                          const SMDS_MeshNode *node5,
1321                                          const SMDS_MeshNode *node6,
1322                                          const SMDS_MeshNode *node7,
1323                                          const SMDS_MeshNode *node8)
1324 {
1325   if ( !node1 ) return 0;
1326   SMDS_ElemIteratorPtr it1 = node1->GetInverseElementIterator(SMDSAbs_Face);
1327   while(it1->more()) {
1328     const SMDS_MeshElement * e = it1->next();
1329     if ( e->NbNodes() == 8 ) {
1330       SMDS_ElemIteratorPtr it2 = e->nodesIterator();
1331       while(it2->more()) {
1332         const SMDS_MeshElement* n = it2->next();
1333         if( n!=node1 &&
1334             n!=node2 &&
1335             n!=node3 &&
1336             n!=node4 &&
1337             n!=node5 &&
1338             n!=node6 &&
1339             n!=node7 &&
1340             n!=node8 )
1341         {
1342           e = 0;
1343           break;
1344         }
1345       }
1346       if ( e )
1347         return static_cast<const SMDS_MeshFace *> (e);
1348     }
1349   }
1350   return 0;
1351 }
1352
1353
1354 //=======================================================================
1355 //function : FindElement
1356 //purpose  :
1357 //=======================================================================
1358
1359 const SMDS_MeshElement* SMDS_Mesh::FindElement(int IDelem) const
1360 {
1361   return myCellFactory->FindElement( IDelem );
1362 }
1363
1364 //=======================================================================
1365 //function : FindFace
1366 //purpose  : find polygon
1367 //=======================================================================
1368
1369
1370 const SMDS_MeshFace* SMDS_Mesh::FindFace (const std::vector<const SMDS_MeshNode *>& nodes)
1371 {
1372   return (const SMDS_MeshFace*) FindElement( nodes, SMDSAbs_Face );
1373 }
1374
1375
1376 //================================================================================
1377 /*!
1378  * \brief Return element based on all given nodes
1379  *  \param nodes - node of element
1380  *  \param type - type of element
1381  *  \param noMedium - true if medium nodes of quadratic element are not included in <nodes>
1382  *  \retval const SMDS_MeshElement* - found element or NULL
1383  */
1384 //================================================================================
1385
1386 const SMDS_MeshElement* SMDS_Mesh::FindElement (const std::vector<const SMDS_MeshNode *>& nodes,
1387                                                 const SMDSAbs_ElementType            type,
1388                                                 const bool                           noMedium)
1389 {
1390   if ( nodes.size() > 0 && nodes[0] )
1391   {
1392     SMDS_ElemIteratorPtr itF = nodes[0]->GetInverseElementIterator(type);
1393     while (itF->more())
1394     {
1395       const SMDS_MeshElement* e = itF->next();
1396       int nbNodesToCheck = noMedium ? e->NbCornerNodes() : e->NbNodes();
1397       if ( nbNodesToCheck == (int)nodes.size() )
1398       {
1399         for ( size_t i = 1; e && i < nodes.size(); ++i )
1400         {
1401           int nodeIndex = e->GetNodeIndex( nodes[ i ]);
1402           if ( nodeIndex < 0 || nodeIndex >= nbNodesToCheck )
1403             e = 0;
1404         }
1405         if ( e )
1406           return e;
1407       }
1408     }
1409   }
1410   return NULL;
1411 }
1412
1413 //================================================================================
1414 /*!
1415  * \brief Return elements including all given nodes
1416  *  \param [in] nodes - nodes to find elements around
1417  *  \param [out] foundElems - the found elements
1418  *  \param [in] type - type of elements to find
1419  *  \return int - a number of found elements
1420  */
1421 //================================================================================
1422
1423 int SMDS_Mesh::GetElementsByNodes(const std::vector<const SMDS_MeshNode *>& nodes,
1424                                   std::vector<const SMDS_MeshElement *>&    foundElems,
1425                                   const SMDSAbs_ElementType                 type)
1426 {
1427   // chose a node with minimal number of inverse elements
1428   const SMDS_MeshNode* n0 = nodes[0];
1429   int minNbInverse = n0 ? n0->NbInverseElements( type ) : 1000;
1430   for ( size_t i = 1; i < nodes.size(); ++i )
1431     if ( nodes[i] && nodes[i]->NbInverseElements( type ) < minNbInverse )
1432     {
1433       n0 = nodes[i];
1434       minNbInverse = n0->NbInverseElements( type );
1435     }
1436
1437   foundElems.clear();
1438   if ( n0 )
1439   {
1440     foundElems.reserve( minNbInverse );
1441     SMDS_ElemIteratorPtr eIt = n0->GetInverseElementIterator( type );
1442     while ( eIt->more() )
1443     {
1444       const SMDS_MeshElement* e = eIt->next();
1445       bool includeAll = true;
1446       for ( size_t i = 0; i < nodes.size() &&  includeAll; ++i )
1447         if ( nodes[i] != n0 && e->GetNodeIndex( nodes[i] ) < 0 )
1448           includeAll = false;
1449       if ( includeAll )
1450         foundElems.push_back( e );
1451     }
1452   }
1453   return foundElems.size();
1454 }
1455
1456 ///////////////////////////////////////////////////////////////////////////////
1457 /// Return the number of nodes
1458 ///////////////////////////////////////////////////////////////////////////////
1459 int SMDS_Mesh::NbNodes() const
1460 {
1461   return myInfo.NbNodes();
1462 }
1463
1464 ///////////////////////////////////////////////////////////////////////////////
1465 /// Return the number of elements
1466 ///////////////////////////////////////////////////////////////////////////////
1467 int SMDS_Mesh::NbElements() const
1468 {
1469   return myInfo.NbElements();
1470 }
1471 ///////////////////////////////////////////////////////////////////////////////
1472 /// Return the number of 0D elements
1473 ///////////////////////////////////////////////////////////////////////////////
1474 int SMDS_Mesh::Nb0DElements() const
1475 {
1476   return myInfo.Nb0DElements();
1477 }
1478
1479 ///////////////////////////////////////////////////////////////////////////////
1480 /// Return the number of 0D elements
1481 ///////////////////////////////////////////////////////////////////////////////
1482 int SMDS_Mesh::NbBalls() const
1483 {
1484   return myInfo.NbBalls();
1485 }
1486
1487 ///////////////////////////////////////////////////////////////////////////////
1488 /// Return the number of edges (including construction edges)
1489 ///////////////////////////////////////////////////////////////////////////////
1490 int SMDS_Mesh::NbEdges() const
1491 {
1492   return myInfo.NbEdges();
1493 }
1494
1495 ///////////////////////////////////////////////////////////////////////////////
1496 /// Return the number of faces (including construction faces)
1497 ///////////////////////////////////////////////////////////////////////////////
1498 int SMDS_Mesh::NbFaces() const
1499 {
1500   return myInfo.NbFaces();
1501 }
1502
1503 ///////////////////////////////////////////////////////////////////////////////
1504 /// Return the number of volumes
1505 ///////////////////////////////////////////////////////////////////////////////
1506 int SMDS_Mesh::NbVolumes() const
1507 {
1508   return myInfo.NbVolumes();
1509 }
1510
1511 ///////////////////////////////////////////////////////////////////////////////
1512 /// Return the number of child mesh of this mesh.
1513 /// Note that the tree structure of SMDS_Mesh is unused in SMESH
1514 ///////////////////////////////////////////////////////////////////////////////
1515 int SMDS_Mesh::NbSubMesh() const
1516 {
1517   return myChildren.size();
1518 }
1519
1520 ///////////////////////////////////////////////////////////////////////////////
1521 /// Destroy the mesh and all its elements
1522 /// All pointer on elements owned by this mesh become illegals.
1523 ///////////////////////////////////////////////////////////////////////////////
1524 SMDS_Mesh::~SMDS_Mesh()
1525 {
1526   std::list<SMDS_Mesh*>::iterator itc=myChildren.begin();
1527   while(itc!=myChildren.end())
1528   {
1529     delete *itc;
1530     itc++;
1531   }
1532
1533   delete myNodeFactory;
1534   delete myCellFactory;
1535
1536   myGrid->Delete();
1537 }
1538
1539 //================================================================================
1540 /*!
1541  * \brief Clear all data
1542  */
1543 //================================================================================
1544
1545 void SMDS_Mesh::Clear()
1546 {
1547   std::set< SMDS_ElementHolder* >::iterator holder = myElemHolders.begin();
1548   for ( ; holder != myElemHolders.end(); ++holder )
1549     (*holder)->clear();
1550
1551   myNodeFactory->Clear();
1552   myCellFactory->Clear();
1553
1554   std::list<SMDS_Mesh*>::iterator itc=myChildren.begin();
1555   while(itc!=myChildren.end())
1556     (*itc)->Clear();
1557
1558   myModified = false;
1559   myModifTime++;
1560   xmin = 0; xmax = 0;
1561   ymin = 0; ymax = 0;
1562   zmin = 0; zmax = 0;
1563
1564   myInfo.Clear();
1565
1566   myGrid->Initialize();
1567   myGrid->Allocate();
1568   vtkPoints* points = vtkPoints::New();
1569   // rnv: to fix bug "21125: EDF 1233 SMESH: Degrardation of precision in a test case for quadratic conversion"
1570   // using double type for storing coordinates of nodes instead float.
1571   points->SetDataType(VTK_DOUBLE);
1572   points->SetNumberOfPoints( 0 );
1573   myGrid->SetPoints( points );
1574   points->Delete();
1575   myGrid->DeleteLinks();
1576 }
1577
1578 ///////////////////////////////////////////////////////////////////////////////
1579 /// Return an iterator on nodes of the current mesh factory
1580 ///////////////////////////////////////////////////////////////////////////////
1581
1582 SMDS_NodeIteratorPtr SMDS_Mesh::nodesIterator() const
1583 {
1584   return myNodeFactory->GetIterator< SMDS_NodeIterator >( new SMDS_MeshElement::NonNullFilter );
1585 }
1586
1587 SMDS_ElemIteratorPtr SMDS_Mesh::elementGeomIterator(SMDSAbs_GeometryType type) const
1588 {
1589   int nbElems = myCellFactory->CompactChangePointers() ? -1 : myInfo.NbElements( type );
1590   return myCellFactory->GetIterator< SMDS_ElemIterator >( new SMDS_MeshElement::GeomFilter( type ),
1591                                                           nbElems);
1592 }
1593
1594 SMDS_ElemIteratorPtr SMDS_Mesh::elementEntityIterator(SMDSAbs_EntityType type) const
1595 {
1596   if ( type == SMDSEntity_Node )
1597   {
1598     return myNodeFactory->GetIterator< SMDS_ElemIterator >( new SMDS_MeshElement::NonNullFilter );
1599   }
1600   int nbElems = myCellFactory->CompactChangePointers() ? -1 : myInfo.NbElements( type );
1601   return myCellFactory->GetIterator<SMDS_ElemIterator>( new SMDS_MeshElement::EntityFilter( type ),
1602                                                         nbElems);
1603 }
1604
1605 ///////////////////////////////////////////////////////////////////////////////
1606 /// Return an iterator on elements of the current mesh factory
1607 ///////////////////////////////////////////////////////////////////////////////
1608 SMDS_ElemIteratorPtr SMDS_Mesh::elementsIterator(SMDSAbs_ElementType type) const
1609 {
1610   typedef SMDS_ElemIterator TIterator;
1611   switch ( type ) {
1612
1613   case SMDSAbs_All:
1614     return myCellFactory->GetIterator< TIterator >( new SMDS_MeshElement::NonNullFilter );
1615
1616   case SMDSAbs_Node:
1617     return myNodeFactory->GetIterator< TIterator >( new SMDS_MeshElement::NonNullFilter );
1618
1619   default:
1620     int nbElems = myCellFactory->CompactChangePointers() ? -1 : myInfo.NbElements( type );
1621     return myCellFactory->GetIterator< TIterator >( new SMDS_MeshElement::TypeFilter( type ),
1622                                                     nbElems);
1623   }
1624   return SMDS_ElemIteratorPtr();
1625 }
1626
1627 ///////////////////////////////////////////////////////////////////////////////
1628 ///Return an iterator on edges of the current mesh.
1629 ///////////////////////////////////////////////////////////////////////////////
1630
1631 SMDS_EdgeIteratorPtr SMDS_Mesh::edgesIterator() const
1632 {
1633   typedef SMDS_EdgeIterator TIterator;
1634   int nbElems = myCellFactory->CompactChangePointers() ? -1 : myInfo.NbEdges();
1635   return myCellFactory->GetIterator< TIterator >( new SMDS_MeshElement::TypeFilter( SMDSAbs_Edge ),
1636                                                   nbElems);
1637 }
1638
1639 ///////////////////////////////////////////////////////////////////////////////
1640 ///Return an iterator on faces of the current mesh.
1641 ///////////////////////////////////////////////////////////////////////////////
1642
1643 SMDS_FaceIteratorPtr SMDS_Mesh::facesIterator() const
1644 {
1645   typedef SMDS_FaceIterator TIterator;
1646   int nbElems = myCellFactory->CompactChangePointers() ? -1 : myInfo.NbFaces();
1647   return myCellFactory->GetIterator< TIterator >( new SMDS_MeshElement::TypeFilter( SMDSAbs_Face ),
1648                                                   nbElems);
1649 }
1650
1651 ///////////////////////////////////////////////////////////////////////////////
1652 ///Return an iterator on volumes of the current mesh.
1653 ///////////////////////////////////////////////////////////////////////////////
1654
1655 SMDS_VolumeIteratorPtr SMDS_Mesh::volumesIterator() const
1656 {
1657   typedef SMDS_VolumeIterator TIterator;
1658   int nbElems = myCellFactory->CompactChangePointers() ? -1 : myInfo.NbVolumes();
1659   return
1660     myCellFactory->GetIterator< TIterator >( new SMDS_MeshElement::TypeFilter( SMDSAbs_Volume ),
1661                                              nbElems );
1662 }
1663
1664 SMDS_NodeIteratorPtr SMDS_Mesh::shapeNodesIterator(int                  shapeID,
1665                                                    size_t               nbElemsToReturn,
1666                                                    const SMDS_MeshNode* sm1stNode) const
1667 {
1668   return myNodeFactory->GetShapeIterator< SMDS_NodeIterator >( shapeID, nbElemsToReturn, sm1stNode );
1669 }
1670
1671 SMDS_ElemIteratorPtr SMDS_Mesh::shapeElementsIterator(int                     shapeID,
1672                                                       size_t                  nbElemsToReturn,
1673                                                       const SMDS_MeshElement* sm1stElem) const
1674 {
1675   return myCellFactory->GetShapeIterator< SMDS_ElemIterator >( shapeID, nbElemsToReturn, sm1stElem );
1676 }
1677
1678 ///////////////////////////////////////////////////////////////////////////////
1679 /// Do intersection of sets (more than 2)
1680 ///////////////////////////////////////////////////////////////////////////////
1681 static std::set<const SMDS_MeshElement*> *
1682 intersectionOfSets( std::set<const SMDS_MeshElement*> vs[], int numberOfSets )
1683 {
1684   std::set<const SMDS_MeshElement*>* rsetA = new std::set<const SMDS_MeshElement*>(vs[0]);
1685   std::set<const SMDS_MeshElement*>* rsetB;
1686
1687   for(int i=0; i<numberOfSets-1; i++)
1688   {
1689     rsetB = new std::set<const SMDS_MeshElement*>();
1690     set_intersection(rsetA->begin(), rsetA->end(),
1691                      vs[i+1].begin(), vs[i+1].end(),
1692                      inserter(*rsetB, rsetB->begin()));
1693     delete rsetA;
1694     rsetA=rsetB;
1695   }
1696   return rsetA;
1697 }
1698 ///////////////////////////////////////////////////////////////////////////////
1699 /// Return the list of finite elements owning the given element: elements
1700 /// containing all the nodes of the given element, for instance faces and
1701 /// volumes containing a given edge.
1702 ///////////////////////////////////////////////////////////////////////////////
1703 static std::set<const SMDS_MeshElement*> * getFinitElements(const SMDS_MeshElement * element)
1704 {
1705   int numberOfSets=element->NbNodes();
1706   std::set<const SMDS_MeshElement*> *initSet = new std::set<const SMDS_MeshElement*>[numberOfSets];
1707
1708   SMDS_NodeIteratorPtr itNodes = element->nodeIterator();
1709
1710   int i = 0;
1711   while ( itNodes->more() )
1712   {
1713     const SMDS_MeshNode *   n = itNodes->next();
1714     for ( SMDS_ElemIteratorPtr itFe = n->GetInverseElementIterator(); itFe->more(); )
1715       initSet[i].insert( itFe->next() );
1716     i++;
1717   }
1718   std::set<const SMDS_MeshElement*> *retSet = intersectionOfSets( initSet, numberOfSets );
1719   delete [] initSet;
1720   return retSet;
1721 }
1722
1723 ///////////////////////////////////////////////////////////////////////////////
1724 /// Return the std::list of nodes used only by the given elements
1725 ///////////////////////////////////////////////////////////////////////////////
1726 static
1727 std::set<const SMDS_MeshElement*> *getExclusiveNodes(std::set<const SMDS_MeshElement*>& elements)
1728 {
1729   std::set<const SMDS_MeshElement*> *           toReturn = new std::set<const SMDS_MeshElement*>();
1730   std::set<const SMDS_MeshElement*>::iterator itElements = elements.begin();
1731
1732   while( itElements != elements.end() )
1733   {
1734     SMDS_NodeIteratorPtr itNodes = (*itElements)->nodeIterator();
1735     itElements++;
1736
1737     while( itNodes->more() )
1738     {
1739       const SMDS_MeshNode *   n = itNodes->next();
1740       SMDS_ElemIteratorPtr itFe = n->GetInverseElementIterator();
1741       std::set<const SMDS_MeshElement*> s;
1742       while ( itFe->more() )
1743         s.insert( itFe->next() );
1744       if ( s == elements ) toReturn->insert(n);
1745     }
1746   }
1747   return toReturn;
1748 }
1749
1750 ///////////////////////////////////////////////////////////////////////////////
1751 ///Find the children of an element that are made of given nodes
1752 ///@param setOfChildren The set in which matching children will be inserted
1753 ///@param element The element were to search matching children
1754 ///@param nodes The nodes that the children must have to be selected
1755 ///////////////////////////////////////////////////////////////////////////////
1756 void SMDS_Mesh::addChildrenWithNodes(std::set<const SMDS_MeshElement*>& setOfChildren,
1757                                      const SMDS_MeshElement *           element,
1758                                      std::set<const SMDS_MeshElement*>& nodes)
1759 {
1760   switch(element->GetType())
1761   {
1762   case SMDSAbs_Node:
1763     throw SALOME_Exception("Internal Error: This should not happen");
1764     break;
1765   case SMDSAbs_0DElement:
1766   case SMDSAbs_Ball:
1767   {
1768   }
1769   break;
1770   case SMDSAbs_Edge:
1771   {
1772     SMDS_ElemIteratorPtr itn=element->nodesIterator();
1773     while(itn->more())
1774     {
1775       const SMDS_MeshElement * e=itn->next();
1776       if(nodes.find(e)!=nodes.end())
1777       {
1778         setOfChildren.insert(element);
1779         break;
1780       }
1781     }
1782   } break;
1783   case SMDSAbs_Face:
1784   {
1785     SMDS_ElemIteratorPtr itn=element->nodesIterator();
1786     while(itn->more())
1787     {
1788       const SMDS_MeshElement * e=itn->next();
1789       if(nodes.find(e)!=nodes.end())
1790       {
1791         setOfChildren.insert(element);
1792         break;
1793       }
1794     }
1795   } break;
1796   case SMDSAbs_Volume:
1797   case SMDSAbs_NbElementTypes:
1798   case SMDSAbs_All: break;
1799   }
1800 }
1801
1802 ///////////////////////////////////////////////////////////////////////////////
1803 ///@param elem The element to delete
1804 ///@param removenodes if true remaining nodes will be removed
1805 ///////////////////////////////////////////////////////////////////////////////
1806 void SMDS_Mesh::RemoveElement(const SMDS_MeshElement * elem,
1807                               const bool               removenodes)
1808 {
1809   std::vector<const SMDS_MeshElement *> removedElems;
1810   std::vector<const SMDS_MeshElement *> removedNodes;
1811   RemoveElement( elem, removedElems, removedNodes, removenodes );
1812 }
1813
1814 ///////////////////////////////////////////////////////////////////////////////
1815 ///@param elem The element to delete
1816 ///@param removedElems to be filled with all removed elements
1817 ///@param removedNodes to be filled with all removed nodes
1818 ///@param removenodes if true remaining nodes will be removed
1819 ///////////////////////////////////////////////////////////////////////////////
1820 void SMDS_Mesh::RemoveElement(const SMDS_MeshElement *               elem,
1821                               std::vector<const SMDS_MeshElement *>& removedElems,
1822                               std::vector<const SMDS_MeshElement *>& removedNodes,
1823                               bool                                   removenodes)
1824 {
1825   // get finite elements built on elem
1826   std::set<const SMDS_MeshElement*> * s1;
1827   if (    (elem->GetType() == SMDSAbs_0DElement)
1828           ||  (elem->GetType() == SMDSAbs_Ball)
1829           ||  (elem->GetType() == SMDSAbs_Edge)
1830           ||  (elem->GetType() == SMDSAbs_Face)
1831           ||  (elem->GetType() == SMDSAbs_Volume) )
1832   {
1833     s1 = new std::set<const SMDS_MeshElement*> ();
1834     s1->insert(elem);
1835   }
1836   else
1837     s1 = getFinitElements(elem);
1838
1839   // get exclusive nodes (which would become free afterwards)
1840   std::set<const SMDS_MeshElement*> * s2;
1841   if (elem->GetType() == SMDSAbs_Node) // a node is removed
1842   {
1843     // do not remove nodes except elem
1844     s2 = new std::set<const SMDS_MeshElement*> ();
1845     s2->insert(elem);
1846     removenodes = true;
1847   }
1848   else
1849     s2 = getExclusiveNodes(*s1);
1850
1851   // form the set of finite and construction elements to remove
1852   std::set<const SMDS_MeshElement*> s3;
1853   std::set<const SMDS_MeshElement*>::iterator it = s1->begin();
1854   while (it != s1->end())
1855   {
1856     addChildrenWithNodes(s3, *it, *s2);
1857     s3.insert(*it);
1858     it++;
1859   }
1860   if (elem->GetType() != SMDSAbs_Node)
1861     s3.insert(elem);
1862
1863   // remove finite and construction elements
1864   for( it = s3.begin();it != s3.end(); ++it )
1865   {
1866     // Remove element from <InverseElements> of its nodes
1867     SMDS_NodeIteratorPtr itn = (*it)->nodeIterator();
1868     while (itn->more())
1869     {
1870       SMDS_MeshNode * n = const_cast<SMDS_MeshNode *> (itn->next());
1871       n->RemoveInverseElement((*it));
1872     }
1873
1874     int vtkid = (*it)->GetVtkID();
1875
1876     switch ((*it)->GetType()) {
1877     case SMDSAbs_Node:
1878       throw SALOME_Exception(LOCALIZED("Internal Error: This should not happen"));
1879       break;
1880     case SMDSAbs_Edge:      myInfo.RemoveEdge(*it);   break;
1881     case SMDSAbs_Face:      myInfo.RemoveFace(*it);   break;
1882     case SMDSAbs_Volume:    myInfo.RemoveVolume(*it); break;
1883     case SMDSAbs_Ball:      myInfo.myNbBalls--;       break;
1884     case SMDSAbs_0DElement: myInfo.myNb0DElements--;  break;
1885     case SMDSAbs_All: // avoid compilation warning
1886     case SMDSAbs_NbElementTypes: break;
1887     }
1888     removedElems.push_back( *it);
1889
1890     myCellFactory->Free( static_cast< const SMDS_MeshCell*>( *it ));
1891
1892     if (vtkid >= 0)
1893     {
1894       this->myGrid->GetCellTypesArray()->SetValue(vtkid, VTK_EMPTY_CELL);
1895     }
1896   }
1897
1898   // remove exclusive (free) nodes
1899   if (removenodes)
1900   {
1901     for ( it = s2->begin(); it != s2->end(); ++it )
1902     {
1903       myInfo.myNbNodes--;
1904       myNodeFactory->Free( (*it) );
1905       removedNodes.push_back((*it));
1906     }
1907   }
1908
1909   delete s2;
1910   delete s1;
1911 }
1912
1913
1914 ///////////////////////////////////////////////////////////////////////////////
1915 ///@param elem The element to delete
1916 ///////////////////////////////////////////////////////////////////////////////
1917 void SMDS_Mesh::RemoveFreeElement(const SMDS_MeshElement * elem)
1918 {
1919   const int           vtkId = elem->GetVtkID();
1920   SMDSAbs_ElementType aType = elem->GetType();
1921   if ( aType == SMDSAbs_Node )
1922   {
1923     // only free node can be removed by this method
1924     const SMDS_MeshNode* n = static_cast<const SMDS_MeshNode*>( elem );
1925     if ( n->NbInverseElements() == 0 ) { // free node
1926       myInfo.myNbNodes--;
1927       myNodeFactory->Free( n );
1928     }
1929     else
1930     {
1931       throw SALOME_Exception( LOCALIZED( "RemoveFreeElement: not a free node" ));
1932     }
1933   }
1934   else
1935   {
1936     // Remove element from <InverseElements> of its nodes
1937     SMDS_NodeIteratorPtr itn = elem->nodeIterator();
1938     while (itn->more()) {
1939       SMDS_MeshNode * n = const_cast<SMDS_MeshNode *>(itn->next());
1940       n->RemoveInverseElement(elem);
1941     }
1942
1943     // in meshes without descendants elements are always free
1944     switch (aType) {
1945     case SMDSAbs_0DElement: myInfo.remove(elem);       break;
1946     case SMDSAbs_Edge:      myInfo.RemoveEdge(elem);   break;
1947     case SMDSAbs_Face:      myInfo.RemoveFace(elem);   break;
1948     case SMDSAbs_Volume:    myInfo.RemoveVolume(elem); break;
1949     case SMDSAbs_Ball:      myInfo.remove(elem);       break;
1950     default: break;
1951     }
1952     myCellFactory->Free( elem );
1953
1954     this->myGrid->GetCellTypesArray()->SetValue(vtkId, VTK_EMPTY_CELL);
1955   }
1956 }
1957
1958 //=======================================================================
1959 /*!
1960  * Checks if the element is present in mesh.
1961  */
1962 //=======================================================================
1963
1964 bool SMDS_Mesh::Contains (const SMDS_MeshElement* elem) const
1965 {
1966   if ( !elem || elem->IsNull() )
1967     return false;
1968
1969   if ( elem->GetType() == SMDSAbs_Node )
1970     return ( elem == myNodeFactory->FindElement( elem->GetID() ));
1971
1972   return ( elem == myCellFactory->FindElement( elem->GetID() ));
1973 }
1974
1975 //=======================================================================
1976 //function : MaxNodeID
1977 //purpose  :
1978 //=======================================================================
1979
1980 int SMDS_Mesh::MaxNodeID() const
1981 {
1982   return myNodeFactory->GetMaxID();
1983 }
1984
1985 //=======================================================================
1986 //function : MinNodeID
1987 //purpose  :
1988 //=======================================================================
1989
1990 int SMDS_Mesh::MinNodeID() const
1991 {
1992   return myNodeFactory->GetMinID();
1993 }
1994
1995 //=======================================================================
1996 //function : MaxElementID
1997 //purpose  :
1998 //=======================================================================
1999
2000 int SMDS_Mesh::MaxElementID() const
2001 {
2002   return myCellFactory->GetMaxID();
2003 }
2004
2005 //=======================================================================
2006 //function : MinElementID
2007 //purpose  :
2008 //=======================================================================
2009
2010 int SMDS_Mesh::MinElementID() const
2011 {
2012   return myCellFactory->GetMinID();
2013 }
2014
2015 //=======================================================================
2016 //function : Renumber
2017 //purpose  : Renumber all nodes or elements.
2018 //=======================================================================
2019
2020 // void SMDS_Mesh::Renumber (const bool isNodes, const int  startID, const int  deltaID)
2021 // {
2022 //   if ( deltaID == 0 )
2023 //     return;
2024
2025 // }
2026
2027 //=======================================================================
2028 //function : GetElementType
2029 //purpose  : Return type of element or node with id
2030 //=======================================================================
2031
2032 SMDSAbs_ElementType SMDS_Mesh::GetElementType( const int id, const bool iselem ) const
2033 {
2034   const SMDS_MeshElement* elem = 0;
2035   if( iselem )
2036     elem = myCellFactory->FindElement( id );
2037   else
2038     elem = myNodeFactory->FindElement( id );
2039
2040   return elem ? elem->GetType() : SMDSAbs_All;
2041 }
2042
2043
2044
2045 //********************************************************************
2046 //********************************************************************
2047 //********                                                   *********
2048 //*****       Methods for addition of quadratic elements        ******
2049 //********                                                   *********
2050 //********************************************************************
2051 //********************************************************************
2052
2053 //=======================================================================
2054 //function : AddEdgeWithID
2055 //purpose  :
2056 //=======================================================================
2057 SMDS_MeshEdge* SMDS_Mesh::AddEdgeWithID(int n1, int n2, int n12, int ID)
2058 {
2059   return SMDS_Mesh::AddEdgeWithID (myNodeFactory->FindNode(n1),
2060                                    myNodeFactory->FindNode(n2),
2061                                    myNodeFactory->FindNode(n12),
2062                                    ID);
2063 }
2064
2065 //=======================================================================
2066 //function : AddEdge
2067 //purpose  :
2068 //=======================================================================
2069 SMDS_MeshEdge* SMDS_Mesh::AddEdge(const SMDS_MeshNode* n1,
2070                                   const SMDS_MeshNode* n2,
2071                                   const SMDS_MeshNode* n12)
2072 {
2073   return SMDS_Mesh::AddEdgeWithID(n1, n2, n12, myCellFactory->GetFreeID());
2074 }
2075
2076 //=======================================================================
2077 //function : AddEdgeWithID
2078 //purpose  :
2079 //=======================================================================
2080 SMDS_MeshEdge* SMDS_Mesh::AddEdgeWithID(const SMDS_MeshNode * n1,
2081                                         const SMDS_MeshNode * n2,
2082                                         const SMDS_MeshNode * n12,
2083                                         int                   ID)
2084 {
2085   if ( !n1 || !n2 || !n12 ) return 0;
2086
2087   if ( SMDS_MeshCell* cell = myCellFactory->NewCell( ID ))
2088   {
2089     cell->init( SMDSEntity_Quad_Edge, /*nbNodes=*/3, n1, n2, n12 );
2090     myInfo.myNbQuadEdges++;
2091     return static_cast<SMDS_MeshEdge*>( cell );
2092   }
2093   return 0;
2094 }
2095
2096
2097 //=======================================================================
2098 //function : AddFace
2099 //purpose  :
2100 //=======================================================================
2101 SMDS_MeshFace* SMDS_Mesh::AddFace(const SMDS_MeshNode * n1,
2102                                   const SMDS_MeshNode * n2,
2103                                   const SMDS_MeshNode * n3,
2104                                   const SMDS_MeshNode * n12,
2105                                   const SMDS_MeshNode * n23,
2106                                   const SMDS_MeshNode * n31)
2107 {
2108   return SMDS_Mesh::AddFaceWithID(n1,n2,n3,n12,n23,n31,
2109                                   myCellFactory->GetFreeID());
2110 }
2111
2112 //=======================================================================
2113 //function : AddFaceWithID
2114 //purpose  :
2115 //=======================================================================
2116 SMDS_MeshFace* SMDS_Mesh::AddFaceWithID(int n1, int n2, int n3,
2117                                         int n12,int n23,int n31, int ID)
2118 {
2119   return SMDS_Mesh::AddFaceWithID (myNodeFactory->FindNode(n1) ,
2120                                    myNodeFactory->FindNode(n2) ,
2121                                    myNodeFactory->FindNode(n3) ,
2122                                    myNodeFactory->FindNode(n12),
2123                                    myNodeFactory->FindNode(n23),
2124                                    myNodeFactory->FindNode(n31),
2125                                    ID);
2126 }
2127
2128 //=======================================================================
2129 //function : AddFaceWithID
2130 //purpose  :
2131 //=======================================================================
2132 SMDS_MeshFace* SMDS_Mesh::AddFaceWithID(const SMDS_MeshNode * n1,
2133                                         const SMDS_MeshNode * n2,
2134                                         const SMDS_MeshNode * n3,
2135                                         const SMDS_MeshNode * n12,
2136                                         const SMDS_MeshNode * n23,
2137                                         const SMDS_MeshNode * n31,
2138                                         int ID)
2139 {
2140   if ( !n1 || !n2 || !n3 || !n12 || !n23 || !n31 ) return 0;
2141   if ( NbFaces() % CHECKMEMORY_INTERVAL == 0 ) CheckMemory();
2142
2143   if ( SMDS_MeshCell* cell = myCellFactory->NewCell( ID ))
2144   {
2145     cell->init( SMDSEntity_Quad_Triangle, /*nbNodes=*/6, n1, n2, n3, n12, n23, n31 );
2146     myInfo.myNbQuadTriangles++;
2147     return static_cast<SMDS_MeshFace*>( cell );
2148   }
2149   return 0;
2150 }
2151
2152
2153 //=======================================================================
2154 //function : AddFace
2155 //purpose  :
2156 //=======================================================================
2157 SMDS_MeshFace* SMDS_Mesh::AddFace(const SMDS_MeshNode * n1,
2158                                   const SMDS_MeshNode * n2,
2159                                   const SMDS_MeshNode * n3,
2160                                   const SMDS_MeshNode * n12,
2161                                   const SMDS_MeshNode * n23,
2162                                   const SMDS_MeshNode * n31,
2163                                   const SMDS_MeshNode * nCenter)
2164 {
2165   return SMDS_Mesh::AddFaceWithID(n1,n2,n3,n12,n23,n31,nCenter,
2166                                   myCellFactory->GetFreeID());
2167 }
2168
2169 //=======================================================================
2170 //function : AddFaceWithID
2171 //purpose  :
2172 //=======================================================================
2173 SMDS_MeshFace* SMDS_Mesh::AddFaceWithID(int n1, int n2, int n3,
2174                                         int n12,int n23,int n31, int nCenter, int ID)
2175 {
2176   return SMDS_Mesh::AddFaceWithID (myNodeFactory->FindNode(n1) ,
2177                                    myNodeFactory->FindNode(n2) ,
2178                                    myNodeFactory->FindNode(n3) ,
2179                                    myNodeFactory->FindNode(n12),
2180                                    myNodeFactory->FindNode(n23),
2181                                    myNodeFactory->FindNode(n31),
2182                                    myNodeFactory->FindNode(nCenter),
2183                                    ID);
2184 }
2185
2186 //=======================================================================
2187 //function : AddFaceWithID
2188 //purpose  :
2189 //=======================================================================
2190 SMDS_MeshFace* SMDS_Mesh::AddFaceWithID(const SMDS_MeshNode * n1,
2191                                         const SMDS_MeshNode * n2,
2192                                         const SMDS_MeshNode * n3,
2193                                         const SMDS_MeshNode * n12,
2194                                         const SMDS_MeshNode * n23,
2195                                         const SMDS_MeshNode * n31,
2196                                         const SMDS_MeshNode * nCenter,
2197                                         int ID)
2198 {
2199   if ( !n1 || !n2 || !n3 || !n12 || !n23 || !n31 || !nCenter) return 0;
2200   if ( NbFaces() % CHECKMEMORY_INTERVAL == 0 ) CheckMemory();
2201
2202   if ( SMDS_MeshCell* cell = myCellFactory->NewCell( ID ))
2203   {
2204     cell->init( SMDSEntity_BiQuad_Triangle, /*nbNodes=*/7, n1, n2, n3, n12, n23, n31, nCenter );
2205     myInfo.myNbBiQuadTriangles++;
2206     return static_cast<SMDS_MeshFace*>( cell );
2207   }
2208   return 0;
2209 }
2210
2211
2212 //=======================================================================
2213 //function : AddFace
2214 //purpose  :
2215 //=======================================================================
2216 SMDS_MeshFace* SMDS_Mesh::AddFace(const SMDS_MeshNode * n1,
2217                                   const SMDS_MeshNode * n2,
2218                                   const SMDS_MeshNode * n3,
2219                                   const SMDS_MeshNode * n4,
2220                                   const SMDS_MeshNode * n12,
2221                                   const SMDS_MeshNode * n23,
2222                                   const SMDS_MeshNode * n34,
2223                                   const SMDS_MeshNode * n41)
2224 {
2225   return SMDS_Mesh::AddFaceWithID(n1,n2,n3,n4,n12,n23,n34,n41,
2226                                   myCellFactory->GetFreeID());
2227 }
2228
2229 //=======================================================================
2230 //function : AddFaceWithID
2231 //purpose  :
2232 //=======================================================================
2233 SMDS_MeshFace* SMDS_Mesh::AddFaceWithID(int n1, int n2, int n3, int n4,
2234                                         int n12,int n23,int n34,int n41, int ID)
2235 {
2236   return SMDS_Mesh::AddFaceWithID (myNodeFactory->FindNode(n1) ,
2237                                    myNodeFactory->FindNode(n2) ,
2238                                    myNodeFactory->FindNode(n3) ,
2239                                    myNodeFactory->FindNode(n4) ,
2240                                    myNodeFactory->FindNode(n12),
2241                                    myNodeFactory->FindNode(n23),
2242                                    myNodeFactory->FindNode(n34),
2243                                    myNodeFactory->FindNode(n41),
2244                                    ID);
2245 }
2246
2247 //=======================================================================
2248 //function : AddFaceWithID
2249 //purpose  :
2250 //=======================================================================
2251 SMDS_MeshFace* SMDS_Mesh::AddFaceWithID(const SMDS_MeshNode * n1,
2252                                         const SMDS_MeshNode * n2,
2253                                         const SMDS_MeshNode * n3,
2254                                         const SMDS_MeshNode * n4,
2255                                         const SMDS_MeshNode * n12,
2256                                         const SMDS_MeshNode * n23,
2257                                         const SMDS_MeshNode * n34,
2258                                         const SMDS_MeshNode * n41,
2259                                         int ID)
2260 {
2261   if ( !n1 || !n2 || !n3 || !n4 || !n12 || !n23 || !n34 || !n41) return 0;
2262   if ( NbFaces() % CHECKMEMORY_INTERVAL == 0 ) CheckMemory();
2263
2264   if ( SMDS_MeshCell* cell = myCellFactory->NewCell( ID ))
2265   {
2266     cell->init( SMDSEntity_Quad_Quadrangle, /*nbNodes=*/8, n1, n2, n3, n4, n12, n23, n34, n41 );
2267     myInfo.myNbQuadQuadrangles++;
2268     return static_cast<SMDS_MeshFace*>( cell );
2269   }
2270   return 0;
2271 }
2272
2273 //=======================================================================
2274 //function : AddFace
2275 //purpose  :
2276 //=======================================================================
2277 SMDS_MeshFace* SMDS_Mesh::AddFace(const SMDS_MeshNode * n1,
2278                                   const SMDS_MeshNode * n2,
2279                                   const SMDS_MeshNode * n3,
2280                                   const SMDS_MeshNode * n4,
2281                                   const SMDS_MeshNode * n12,
2282                                   const SMDS_MeshNode * n23,
2283                                   const SMDS_MeshNode * n34,
2284                                   const SMDS_MeshNode * n41,
2285                                   const SMDS_MeshNode * nCenter)
2286 {
2287   return SMDS_Mesh::AddFaceWithID(n1,n2,n3,n4,n12,n23,n34,n41,nCenter,
2288                                   myCellFactory->GetFreeID());
2289 }
2290
2291 //=======================================================================
2292 //function : AddFaceWithID
2293 //purpose  :
2294 //=======================================================================
2295 SMDS_MeshFace* SMDS_Mesh::AddFaceWithID(int n1, int n2, int n3, int n4,
2296                                         int n12,int n23,int n34,int n41, int nCenter, int ID)
2297 {
2298   return SMDS_Mesh::AddFaceWithID (myNodeFactory->FindNode(n1) ,
2299                                    myNodeFactory->FindNode(n2) ,
2300                                    myNodeFactory->FindNode(n3) ,
2301                                    myNodeFactory->FindNode(n4) ,
2302                                    myNodeFactory->FindNode(n12),
2303                                    myNodeFactory->FindNode(n23),
2304                                    myNodeFactory->FindNode(n34),
2305                                    myNodeFactory->FindNode(n41),
2306                                    myNodeFactory->FindNode(nCenter),
2307                                    ID);
2308 }
2309
2310 //=======================================================================
2311 //function : AddFaceWithID
2312 //purpose  :
2313 //=======================================================================
2314 SMDS_MeshFace* SMDS_Mesh::AddFaceWithID(const SMDS_MeshNode * n1,
2315                                         const SMDS_MeshNode * n2,
2316                                         const SMDS_MeshNode * n3,
2317                                         const SMDS_MeshNode * n4,
2318                                         const SMDS_MeshNode * n12,
2319                                         const SMDS_MeshNode * n23,
2320                                         const SMDS_MeshNode * n34,
2321                                         const SMDS_MeshNode * n41,
2322                                         const SMDS_MeshNode * nCenter,
2323                                         int ID)
2324 {
2325   if ( !n1 || !n2 || !n3 || !n4 || !n12 || !n23 || !n34 || !n41 || !nCenter) return 0;
2326   if ( NbFaces() % CHECKMEMORY_INTERVAL == 0 ) CheckMemory();
2327
2328   if ( SMDS_MeshCell* cell = myCellFactory->NewCell( ID ))
2329   {
2330     cell->init( SMDSEntity_BiQuad_Quadrangle,
2331                 /*nbNodes=*/9, n1, n2, n3, n4, n12, n23, n34, n41, nCenter );
2332     myInfo.myNbBiQuadQuadrangles++;
2333     return static_cast<SMDS_MeshFace*>( cell );
2334   }
2335   return 0;
2336 }
2337
2338
2339 //=======================================================================
2340 //function : AddVolume
2341 //purpose  :
2342 //=======================================================================
2343 SMDS_MeshVolume* SMDS_Mesh::AddVolume(const SMDS_MeshNode * n1,
2344                                       const SMDS_MeshNode * n2,
2345                                       const SMDS_MeshNode * n3,
2346                                       const SMDS_MeshNode * n4,
2347                                       const SMDS_MeshNode * n12,
2348                                       const SMDS_MeshNode * n23,
2349                                       const SMDS_MeshNode * n31,
2350                                       const SMDS_MeshNode * n14,
2351                                       const SMDS_MeshNode * n24,
2352                                       const SMDS_MeshNode * n34)
2353 {
2354   return SMDS_Mesh::AddVolumeWithID(n1, n2, n3, n4, n12, n23,
2355                                     n31, n14, n24, n34, myCellFactory->GetFreeID());
2356 }
2357
2358 //=======================================================================
2359 //function : AddVolumeWithID
2360 //purpose  :
2361 //=======================================================================
2362 SMDS_MeshVolume* SMDS_Mesh::AddVolumeWithID(int n1, int n2, int n3, int n4,
2363                                             int n12,int n23,int n31,
2364                                             int n14,int n24,int n34, int ID)
2365 {
2366   return SMDS_Mesh::AddVolumeWithID (myNodeFactory->FindNode(n1) ,
2367                                      myNodeFactory->FindNode(n2) ,
2368                                      myNodeFactory->FindNode(n3) ,
2369                                      myNodeFactory->FindNode(n4) ,
2370                                      myNodeFactory->FindNode(n12),
2371                                      myNodeFactory->FindNode(n23),
2372                                      myNodeFactory->FindNode(n31),
2373                                      myNodeFactory->FindNode(n14),
2374                                      myNodeFactory->FindNode(n24),
2375                                      myNodeFactory->FindNode(n34),
2376                                      ID);
2377 }
2378
2379 //=======================================================================
2380 //function : AddVolumeWithID
2381 //purpose  : 2d order tetrahedron of 10 nodes
2382 //=======================================================================
2383 SMDS_MeshVolume* SMDS_Mesh::AddVolumeWithID(const SMDS_MeshNode * n1,
2384                                             const SMDS_MeshNode * n2,
2385                                             const SMDS_MeshNode * n3,
2386                                             const SMDS_MeshNode * n4,
2387                                             const SMDS_MeshNode * n12,
2388                                             const SMDS_MeshNode * n23,
2389                                             const SMDS_MeshNode * n31,
2390                                             const SMDS_MeshNode * n14,
2391                                             const SMDS_MeshNode * n24,
2392                                             const SMDS_MeshNode * n34,
2393                                             int ID)
2394 {
2395   if ( !n1 || !n2 || !n3 || !n4 || !n12 || !n23 || !n31 || !n14 || !n24 || !n34)
2396     return 0;
2397   if ( NbVolumes() % CHECKMEMORY_INTERVAL == 0 ) CheckMemory();
2398
2399   if ( SMDS_MeshCell* cell = myCellFactory->NewCell( ID ))
2400   {
2401     cell->init( SMDSEntity_Quad_Tetra,
2402                 /*nbNodes=*/10, n1, n2, n3, n4, n12, n23, n31, n14, n24, n34 );
2403     myInfo.myNbQuadTetras++;
2404     return static_cast<SMDS_MeshVolume*>( cell );
2405   }
2406   return 0;
2407 }
2408
2409
2410 //=======================================================================
2411 //function : AddVolume
2412 //purpose  :
2413 //=======================================================================
2414 SMDS_MeshVolume* SMDS_Mesh::AddVolume(const SMDS_MeshNode * n1,
2415                                       const SMDS_MeshNode * n2,
2416                                       const SMDS_MeshNode * n3,
2417                                       const SMDS_MeshNode * n4,
2418                                       const SMDS_MeshNode * n5,
2419                                       const SMDS_MeshNode * n12,
2420                                       const SMDS_MeshNode * n23,
2421                                       const SMDS_MeshNode * n34,
2422                                       const SMDS_MeshNode * n41,
2423                                       const SMDS_MeshNode * n15,
2424                                       const SMDS_MeshNode * n25,
2425                                       const SMDS_MeshNode * n35,
2426                                       const SMDS_MeshNode * n45)
2427 {
2428   return SMDS_Mesh::AddVolumeWithID(n1, n2, n3, n4, n5, n12, n23, n34, n41,
2429                                     n15, n25, n35, n45, myCellFactory->GetFreeID());
2430 }
2431
2432 //=======================================================================
2433 //function : AddVolumeWithID
2434 //purpose  :
2435 //=======================================================================
2436 SMDS_MeshVolume* SMDS_Mesh::AddVolumeWithID(int n1, int n2, int n3, int n4, int n5,
2437                                             int n12,int n23,int n34,int n41,
2438                                             int n15,int n25,int n35,int n45, int ID)
2439 {
2440   return SMDS_Mesh::AddVolumeWithID (myNodeFactory->FindNode(n1) ,
2441                                      myNodeFactory->FindNode(n2) ,
2442                                      myNodeFactory->FindNode(n3) ,
2443                                      myNodeFactory->FindNode(n4) ,
2444                                      myNodeFactory->FindNode(n5) ,
2445                                      myNodeFactory->FindNode(n12),
2446                                      myNodeFactory->FindNode(n23),
2447                                      myNodeFactory->FindNode(n34),
2448                                      myNodeFactory->FindNode(n41),
2449                                      myNodeFactory->FindNode(n15),
2450                                      myNodeFactory->FindNode(n25),
2451                                      myNodeFactory->FindNode(n35),
2452                                      myNodeFactory->FindNode(n45),
2453                                      ID);
2454 }
2455
2456 //=======================================================================
2457 //function : AddVolumeWithID
2458 //purpose  : 2d order pyramid of 13 nodes
2459 //=======================================================================
2460 SMDS_MeshVolume* SMDS_Mesh::AddVolumeWithID(const SMDS_MeshNode * n1,
2461                                             const SMDS_MeshNode * n2,
2462                                             const SMDS_MeshNode * n3,
2463                                             const SMDS_MeshNode * n4,
2464                                             const SMDS_MeshNode * n5,
2465                                             const SMDS_MeshNode * n12,
2466                                             const SMDS_MeshNode * n23,
2467                                             const SMDS_MeshNode * n34,
2468                                             const SMDS_MeshNode * n41,
2469                                             const SMDS_MeshNode * n15,
2470                                             const SMDS_MeshNode * n25,
2471                                             const SMDS_MeshNode * n35,
2472                                             const SMDS_MeshNode * n45,
2473                                             int ID)
2474 {
2475   if (!n1 || !n2 || !n3 || !n4 || !n5 || !n12 || !n23 ||
2476       !n34 || !n41 || !n15 || !n25 || !n35 || !n45)
2477     return 0;
2478   if ( NbVolumes() % CHECKMEMORY_INTERVAL == 0 ) CheckMemory();
2479
2480   if ( SMDS_MeshCell* cell = myCellFactory->NewCell( ID ))
2481   {
2482     cell->init( SMDSEntity_Quad_Pyramid,
2483                 /*nbNodes=*/13, n1, n2, n3, n4, n5, n12, n23, n34, n41, n15, n25, n35, n45);
2484     myInfo.myNbQuadPyramids++;
2485     return static_cast<SMDS_MeshVolume*>( cell );
2486   }
2487   return 0;
2488 }
2489
2490
2491 //=======================================================================
2492 //function : AddVolume
2493 //purpose  : 2d order Pentahedron (prism) with 15 nodes
2494 //=======================================================================
2495 SMDS_MeshVolume* SMDS_Mesh::AddVolume(const SMDS_MeshNode * n1,
2496                                       const SMDS_MeshNode * n2,
2497                                       const SMDS_MeshNode * n3,
2498                                       const SMDS_MeshNode * n4,
2499                                       const SMDS_MeshNode * n5,
2500                                       const SMDS_MeshNode * n6,
2501                                       const SMDS_MeshNode * n12,
2502                                       const SMDS_MeshNode * n23,
2503                                       const SMDS_MeshNode * n31,
2504                                       const SMDS_MeshNode * n45,
2505                                       const SMDS_MeshNode * n56,
2506                                       const SMDS_MeshNode * n64,
2507                                       const SMDS_MeshNode * n14,
2508                                       const SMDS_MeshNode * n25,
2509                                       const SMDS_MeshNode * n36)
2510 {
2511   return SMDS_Mesh::AddVolumeWithID(n1, n2, n3, n4, n5, n6, n12, n23, n31,
2512                                     n45, n56, n64, n14, n25, n36, myCellFactory->GetFreeID());
2513 }
2514
2515 //=======================================================================
2516 //function : AddVolumeWithID
2517 //purpose  : 2d order Pentahedron (prism) with 15 nodes
2518 //=======================================================================
2519 SMDS_MeshVolume* SMDS_Mesh::AddVolumeWithID(int n1, int n2, int n3,
2520                                             int n4, int n5, int n6,
2521                                             int n12,int n23,int n31,
2522                                             int n45,int n56,int n64,
2523                                             int n14,int n25,int n36, int ID)
2524 {
2525   return SMDS_Mesh::AddVolumeWithID (myNodeFactory->FindNode(n1) ,
2526                                      myNodeFactory->FindNode(n2) ,
2527                                      myNodeFactory->FindNode(n3) ,
2528                                      myNodeFactory->FindNode(n4) ,
2529                                      myNodeFactory->FindNode(n5) ,
2530                                      myNodeFactory->FindNode(n6) ,
2531                                      myNodeFactory->FindNode(n12),
2532                                      myNodeFactory->FindNode(n23),
2533                                      myNodeFactory->FindNode(n31),
2534                                      myNodeFactory->FindNode(n45),
2535                                      myNodeFactory->FindNode(n56),
2536                                      myNodeFactory->FindNode(n64),
2537                                      myNodeFactory->FindNode(n14),
2538                                      myNodeFactory->FindNode(n25),
2539                                      myNodeFactory->FindNode(n36),
2540                                      ID);
2541 }
2542
2543 //=======================================================================
2544 //function : AddVolumeWithID
2545 //purpose  : 2d order Pentahedron (prism) with 15 nodes
2546 //=======================================================================
2547 SMDS_MeshVolume* SMDS_Mesh::AddVolumeWithID(const SMDS_MeshNode * n1,
2548                                             const SMDS_MeshNode * n2,
2549                                             const SMDS_MeshNode * n3,
2550                                             const SMDS_MeshNode * n4,
2551                                             const SMDS_MeshNode * n5,
2552                                             const SMDS_MeshNode * n6,
2553                                             const SMDS_MeshNode * n12,
2554                                             const SMDS_MeshNode * n23,
2555                                             const SMDS_MeshNode * n31,
2556                                             const SMDS_MeshNode * n45,
2557                                             const SMDS_MeshNode * n56,
2558                                             const SMDS_MeshNode * n64,
2559                                             const SMDS_MeshNode * n14,
2560                                             const SMDS_MeshNode * n25,
2561                                             const SMDS_MeshNode * n36,
2562                                             int ID)
2563 {
2564   if (!n1 || !n2 || !n3 || !n4 || !n5 || !n6 || !n12 || !n23 ||
2565       !n31 || !n45 || !n56 || !n64 || !n14 || !n25 || !n36)
2566     return 0;
2567   if ( NbVolumes() % CHECKMEMORY_INTERVAL == 0 ) CheckMemory();
2568
2569   if ( SMDS_MeshCell* cell = myCellFactory->NewCell( ID ))
2570   {
2571     cell->init( SMDSEntity_Quad_Penta, /*nbNodes=*/15,
2572                 n1, n2, n3, n4, n5, n6, n12, n23, n31, n45, n56, n64, n14, n25, n36 );
2573     myInfo.myNbQuadPrisms++;
2574     return static_cast<SMDS_MeshVolume*>( cell );
2575   }
2576   return 0;
2577 }
2578
2579 //=======================================================================
2580 //function : AddVolume
2581 //purpose  : 2d order Pentahedron (prism) with 18 nodes
2582 //=======================================================================
2583 SMDS_MeshVolume* SMDS_Mesh::AddVolume(const SMDS_MeshNode * n1,
2584                                       const SMDS_MeshNode * n2,
2585                                       const SMDS_MeshNode * n3,
2586                                       const SMDS_MeshNode * n4,
2587                                       const SMDS_MeshNode * n5,
2588                                       const SMDS_MeshNode * n6,
2589                                       const SMDS_MeshNode * n12,
2590                                       const SMDS_MeshNode * n23,
2591                                       const SMDS_MeshNode * n31,
2592                                       const SMDS_MeshNode * n45,
2593                                       const SMDS_MeshNode * n56,
2594                                       const SMDS_MeshNode * n64,
2595                                       const SMDS_MeshNode * n14,
2596                                       const SMDS_MeshNode * n25,
2597                                       const SMDS_MeshNode * n36,
2598                                       const SMDS_MeshNode * n1245,
2599                                       const SMDS_MeshNode * n2356,
2600                                       const SMDS_MeshNode * n1346)
2601 {
2602   return SMDS_Mesh::AddVolumeWithID(n1, n2, n3, n4, n5, n6, n12, n23, n31,
2603                                     n45, n56, n64, n14, n25, n36, n1245, n2356, n1346,
2604                                     myCellFactory->GetFreeID());
2605 }
2606
2607 //=======================================================================
2608 //function : AddVolumeWithID
2609 //purpose  : 2d order Pentahedron (prism) with 18 nodes
2610 //=======================================================================
2611 SMDS_MeshVolume* SMDS_Mesh::AddVolumeWithID(int n1, int n2, int n3,
2612                                             int n4, int n5, int n6,
2613                                             int n12,int n23,int n31,
2614                                             int n45,int n56,int n64,
2615                                             int n14,int n25,int n36,
2616                                             int n1245, int n2356, int n1346, int ID)
2617 {
2618   return SMDS_Mesh::AddVolumeWithID (myNodeFactory->FindNode(n1) ,
2619                                      myNodeFactory->FindNode(n2) ,
2620                                      myNodeFactory->FindNode(n3) ,
2621                                      myNodeFactory->FindNode(n4) ,
2622                                      myNodeFactory->FindNode(n5) ,
2623                                      myNodeFactory->FindNode(n6) ,
2624                                      myNodeFactory->FindNode(n12),
2625                                      myNodeFactory->FindNode(n23),
2626                                      myNodeFactory->FindNode(n31),
2627                                      myNodeFactory->FindNode(n45),
2628                                      myNodeFactory->FindNode(n56),
2629                                      myNodeFactory->FindNode(n64),
2630                                      myNodeFactory->FindNode(n14),
2631                                      myNodeFactory->FindNode(n25),
2632                                      myNodeFactory->FindNode(n36),
2633                                      myNodeFactory->FindNode(n1245),
2634                                      myNodeFactory->FindNode(n2356),
2635                                      myNodeFactory->FindNode(n1346),
2636                                      ID);
2637 }
2638
2639 //=======================================================================
2640 //function : AddVolumeWithID
2641 //purpose  : 2d order Pentahedron (prism) with 18 nodes
2642 //=======================================================================
2643 SMDS_MeshVolume* SMDS_Mesh::AddVolumeWithID(const SMDS_MeshNode * n1,
2644                                             const SMDS_MeshNode * n2,
2645                                             const SMDS_MeshNode * n3,
2646                                             const SMDS_MeshNode * n4,
2647                                             const SMDS_MeshNode * n5,
2648                                             const SMDS_MeshNode * n6,
2649                                             const SMDS_MeshNode * n12,
2650                                             const SMDS_MeshNode * n23,
2651                                             const SMDS_MeshNode * n31,
2652                                             const SMDS_MeshNode * n45,
2653                                             const SMDS_MeshNode * n56,
2654                                             const SMDS_MeshNode * n64,
2655                                             const SMDS_MeshNode * n14,
2656                                             const SMDS_MeshNode * n25,
2657                                             const SMDS_MeshNode * n36,
2658                                             const SMDS_MeshNode * n1245,
2659                                             const SMDS_MeshNode * n2356,
2660                                             const SMDS_MeshNode * n1346,
2661                                             int ID)
2662 {
2663   //MESSAGE("AddVolumeWithID penta18 "<< ID);
2664   if (!n1 || !n2 || !n3 || !n4 || !n5 || !n6 || !n12 || !n23 ||
2665       !n31 || !n45 || !n56 || !n64 || !n14 || !n25 || !n36 || !n1245 || !n2356 || !n1346)
2666     return 0;
2667   if ( NbVolumes() % CHECKMEMORY_INTERVAL == 0 ) CheckMemory();
2668
2669   if ( SMDS_MeshCell* cell = myCellFactory->NewCell( ID ))
2670   {
2671     cell->init( SMDSEntity_BiQuad_Penta, /*nbNodes=*/18, n1, n2, n3, n4, n5, n6,
2672                 n12, n23, n31, n45, n56, n64, n14, n25, n36, n1245, n2356, n1346 );
2673     myInfo.myNbBiQuadPrisms++;
2674     return static_cast<SMDS_MeshVolume*>( cell );
2675   }
2676   return 0;
2677 }
2678
2679
2680 //=======================================================================
2681 //function : AddVolume
2682 //purpose  :
2683 //=======================================================================
2684 SMDS_MeshVolume* SMDS_Mesh::AddVolume(const SMDS_MeshNode * n1,
2685                                       const SMDS_MeshNode * n2,
2686                                       const SMDS_MeshNode * n3,
2687                                       const SMDS_MeshNode * n4,
2688                                       const SMDS_MeshNode * n5,
2689                                       const SMDS_MeshNode * n6,
2690                                       const SMDS_MeshNode * n7,
2691                                       const SMDS_MeshNode * n8,
2692                                       const SMDS_MeshNode * n12,
2693                                       const SMDS_MeshNode * n23,
2694                                       const SMDS_MeshNode * n34,
2695                                       const SMDS_MeshNode * n41,
2696                                       const SMDS_MeshNode * n56,
2697                                       const SMDS_MeshNode * n67,
2698                                       const SMDS_MeshNode * n78,
2699                                       const SMDS_MeshNode * n85,
2700                                       const SMDS_MeshNode * n15,
2701                                       const SMDS_MeshNode * n26,
2702                                       const SMDS_MeshNode * n37,
2703                                       const SMDS_MeshNode * n48)
2704 {
2705   return SMDS_Mesh::AddVolumeWithID(n1, n2, n3, n4, n5, n6, n7, n8, n12, n23, n34, n41,
2706                                     n56, n67, n78, n85, n15, n26, n37, n48,
2707                                     myCellFactory->GetFreeID());
2708 }
2709
2710 //=======================================================================
2711 //function : AddVolumeWithID
2712 //purpose  :
2713 //=======================================================================
2714 SMDS_MeshVolume* SMDS_Mesh::AddVolumeWithID(int n1, int n2, int n3, int n4,
2715                                             int n5, int n6, int n7, int n8,
2716                                             int n12,int n23,int n34,int n41,
2717                                             int n56,int n67,int n78,int n85,
2718                                             int n15,int n26,int n37,int n48, int ID)
2719 {
2720   return SMDS_Mesh::AddVolumeWithID (myNodeFactory->FindNode(n1),
2721                                      myNodeFactory->FindNode(n2),
2722                                      myNodeFactory->FindNode(n3),
2723                                      myNodeFactory->FindNode(n4),
2724                                      myNodeFactory->FindNode(n5),
2725                                      myNodeFactory->FindNode(n6),
2726                                      myNodeFactory->FindNode(n7),
2727                                      myNodeFactory->FindNode(n8),
2728                                      myNodeFactory->FindNode(n12),
2729                                      myNodeFactory->FindNode(n23),
2730                                      myNodeFactory->FindNode(n34),
2731                                      myNodeFactory->FindNode(n41),
2732                                      myNodeFactory->FindNode(n56),
2733                                      myNodeFactory->FindNode(n67),
2734                                      myNodeFactory->FindNode(n78),
2735                                      myNodeFactory->FindNode(n85),
2736                                      myNodeFactory->FindNode(n15),
2737                                      myNodeFactory->FindNode(n26),
2738                                      myNodeFactory->FindNode(n37),
2739                                      myNodeFactory->FindNode(n48),
2740                                      ID);
2741 }
2742
2743 //=======================================================================
2744 //function : AddVolumeWithID
2745 //purpose  : 2d order Hexahedrons with 20 nodes
2746 //=======================================================================
2747 SMDS_MeshVolume* SMDS_Mesh::AddVolumeWithID(const SMDS_MeshNode * n1,
2748                                             const SMDS_MeshNode * n2,
2749                                             const SMDS_MeshNode * n3,
2750                                             const SMDS_MeshNode * n4,
2751                                             const SMDS_MeshNode * n5,
2752                                             const SMDS_MeshNode * n6,
2753                                             const SMDS_MeshNode * n7,
2754                                             const SMDS_MeshNode * n8,
2755                                             const SMDS_MeshNode * n12,
2756                                             const SMDS_MeshNode * n23,
2757                                             const SMDS_MeshNode * n34,
2758                                             const SMDS_MeshNode * n41,
2759                                             const SMDS_MeshNode * n56,
2760                                             const SMDS_MeshNode * n67,
2761                                             const SMDS_MeshNode * n78,
2762                                             const SMDS_MeshNode * n85,
2763                                             const SMDS_MeshNode * n15,
2764                                             const SMDS_MeshNode * n26,
2765                                             const SMDS_MeshNode * n37,
2766                                             const SMDS_MeshNode * n48,
2767                                             int ID)
2768 {
2769   if (!n1 || !n2 || !n3 || !n4 || !n5 || !n6 || !n7 || !n8 || !n12 || !n23 ||
2770       !n34 || !n41 || !n56 || !n67 || !n78 || !n85 || !n15 || !n26 || !n37 || !n48)
2771     return 0;
2772   if ( NbVolumes() % CHECKMEMORY_INTERVAL == 0 ) CheckMemory();
2773
2774   if ( SMDS_MeshCell* cell = myCellFactory->NewCell( ID ))
2775   {
2776     cell->init( SMDSEntity_Quad_Hexa, /*nbNodes=*/20, n1, n2, n3, n4, n5, n6, n7, n8,
2777                 n12, n23, n34, n41, n56, n67, n78, n85, n15, n26, n37, n48 );
2778     myInfo.myNbQuadHexas++;
2779     return static_cast<SMDS_MeshVolume*>( cell );
2780   }
2781   return 0;
2782 }
2783
2784 //=======================================================================
2785 //function : AddVolume
2786 //purpose  :
2787 //=======================================================================
2788 SMDS_MeshVolume* SMDS_Mesh::AddVolume(const SMDS_MeshNode * n1,
2789                                       const SMDS_MeshNode * n2,
2790                                       const SMDS_MeshNode * n3,
2791                                       const SMDS_MeshNode * n4,
2792                                       const SMDS_MeshNode * n5,
2793                                       const SMDS_MeshNode * n6,
2794                                       const SMDS_MeshNode * n7,
2795                                       const SMDS_MeshNode * n8,
2796                                       const SMDS_MeshNode * n12,
2797                                       const SMDS_MeshNode * n23,
2798                                       const SMDS_MeshNode * n34,
2799                                       const SMDS_MeshNode * n41,
2800                                       const SMDS_MeshNode * n56,
2801                                       const SMDS_MeshNode * n67,
2802                                       const SMDS_MeshNode * n78,
2803                                       const SMDS_MeshNode * n85,
2804                                       const SMDS_MeshNode * n15,
2805                                       const SMDS_MeshNode * n26,
2806                                       const SMDS_MeshNode * n37,
2807                                       const SMDS_MeshNode * n48,
2808                                       const SMDS_MeshNode * n1234,
2809                                       const SMDS_MeshNode * n1256,
2810                                       const SMDS_MeshNode * n2367,
2811                                       const SMDS_MeshNode * n3478,
2812                                       const SMDS_MeshNode * n1458,
2813                                       const SMDS_MeshNode * n5678,
2814                                       const SMDS_MeshNode * nCenter)
2815 {
2816   return SMDS_Mesh::AddVolumeWithID(n1, n2, n3, n4, n5, n6, n7, n8, n12, n23, n34, n41,
2817                                     n56, n67, n78, n85, n15, n26, n37, n48,
2818                                     n1234, n1256, n2367, n3478, n1458, n5678, nCenter,
2819                                     myCellFactory->GetFreeID());
2820 }
2821
2822 //=======================================================================
2823 //function : AddVolumeWithID
2824 //purpose  :
2825 //=======================================================================
2826 SMDS_MeshVolume* SMDS_Mesh::AddVolumeWithID(int n1, int n2, int n3, int n4,
2827                                             int n5, int n6, int n7, int n8,
2828                                             int n12,int n23,int n34,int n41,
2829                                             int n56,int n67,int n78,int n85,
2830                                             int n15,int n26,int n37,int n48,
2831                                             int n1234,int n1256,int n2367,int n3478,
2832                                             int n1458,int n5678,int nCenter, int ID)
2833 {
2834   return SMDS_Mesh::AddVolumeWithID (myNodeFactory->FindNode(n1),
2835                                      myNodeFactory->FindNode(n2),
2836                                      myNodeFactory->FindNode(n3),
2837                                      myNodeFactory->FindNode(n4),
2838                                      myNodeFactory->FindNode(n5),
2839                                      myNodeFactory->FindNode(n6),
2840                                      myNodeFactory->FindNode(n7),
2841                                      myNodeFactory->FindNode(n8),
2842                                      myNodeFactory->FindNode(n12),
2843                                      myNodeFactory->FindNode(n23),
2844                                      myNodeFactory->FindNode(n34),
2845                                      myNodeFactory->FindNode(n41),
2846                                      myNodeFactory->FindNode(n56),
2847                                      myNodeFactory->FindNode(n67),
2848                                      myNodeFactory->FindNode(n78),
2849                                      myNodeFactory->FindNode(n85),
2850                                      myNodeFactory->FindNode(n15),
2851                                      myNodeFactory->FindNode(n26),
2852                                      myNodeFactory->FindNode(n37),
2853                                      myNodeFactory->FindNode(n48),
2854                                      myNodeFactory->FindNode(n1234),
2855                                      myNodeFactory->FindNode(n1256),
2856                                      myNodeFactory->FindNode(n2367),
2857                                      myNodeFactory->FindNode(n3478),
2858                                      myNodeFactory->FindNode(n1458),
2859                                      myNodeFactory->FindNode(n5678),
2860                                      myNodeFactory->FindNode(nCenter),
2861                                      ID);
2862 }
2863
2864 //=======================================================================
2865 //function : AddVolumeWithID
2866 //purpose  : 2d order Hexahedrons with 27 nodes
2867 //=======================================================================
2868 SMDS_MeshVolume* SMDS_Mesh::AddVolumeWithID(const SMDS_MeshNode * n1,
2869                                             const SMDS_MeshNode * n2,
2870                                             const SMDS_MeshNode * n3,
2871                                             const SMDS_MeshNode * n4,
2872                                             const SMDS_MeshNode * n5,
2873                                             const SMDS_MeshNode * n6,
2874                                             const SMDS_MeshNode * n7,
2875                                             const SMDS_MeshNode * n8,
2876                                             const SMDS_MeshNode * n12,
2877                                             const SMDS_MeshNode * n23,
2878                                             const SMDS_MeshNode * n34,
2879                                             const SMDS_MeshNode * n41,
2880                                             const SMDS_MeshNode * n56,
2881                                             const SMDS_MeshNode * n67,
2882                                             const SMDS_MeshNode * n78,
2883                                             const SMDS_MeshNode * n85,
2884                                             const SMDS_MeshNode * n15,
2885                                             const SMDS_MeshNode * n26,
2886                                             const SMDS_MeshNode * n37,
2887                                             const SMDS_MeshNode * n48,
2888                                             const SMDS_MeshNode * n1234,
2889                                             const SMDS_MeshNode * n1256,
2890                                             const SMDS_MeshNode * n2367,
2891                                             const SMDS_MeshNode * n3478,
2892                                             const SMDS_MeshNode * n1458,
2893                                             const SMDS_MeshNode * n5678,
2894                                             const SMDS_MeshNode * nCenter,
2895                                             int ID)
2896 {
2897   if (!n1 || !n2 || !n3 || !n4 || !n5 || !n6 || !n7 || !n8 || !n12 || !n23 ||
2898       !n34 || !n41 || !n56 || !n67 || !n78 || !n85 || !n15 || !n26 || !n37 || !n48 ||
2899       !n1234 || !n1256 || !n2367 || !n3478 || !n1458 || !n5678 || !nCenter )
2900     return 0;
2901   if ( NbVolumes() % CHECKMEMORY_INTERVAL == 0 ) CheckMemory();
2902
2903   if ( SMDS_MeshCell* cell = myCellFactory->NewCell( ID ))
2904   {
2905     cell->init( SMDSEntity_TriQuad_Hexa, /*nbNodes=*/27, n1, n2, n3, n4, n5, n6, n7, n8,
2906                 n12, n23, n34, n41, n56, n67, n78, n85, n15, n26, n37, n48,
2907                 n1234, n1256, n2367, n3478, n1458, n5678, nCenter);
2908     myInfo.myNbTriQuadHexas++;
2909     return static_cast<SMDS_MeshVolume*>( cell );
2910   }
2911   return 0;
2912 }
2913
2914 void SMDS_Mesh::dumpGrid(std::string ficdump)
2915 {
2916   //  vtkUnstructuredGridWriter* aWriter = vtkUnstructuredGridWriter::New();
2917   //  aWriter->SetFileName(ficdump.c_str());
2918   //  aWriter->SetInput(myGrid);
2919   //  if(myGrid->GetNumberOfCells())
2920   //  {
2921   //    aWriter->Write();
2922   //  }
2923   //  aWriter->Delete();
2924   ficdump = ficdump + "_connectivity";
2925   std::ofstream ficcon(ficdump.c_str(), ios::out);
2926   int nbPoints = myGrid->GetNumberOfPoints();
2927   ficcon << "-------------------------------- points " <<  nbPoints << endl;
2928   for (int i=0; i<nbPoints; i++)
2929   {
2930     ficcon << i << " " << *(myGrid->GetPoint(i)) << " " << *(myGrid->GetPoint(i)+1) << " " << " " << *(myGrid->GetPoint(i)+2) << endl;
2931   }
2932   int nbCells = myGrid->GetNumberOfCells();
2933   ficcon << "-------------------------------- cells " <<  nbCells << endl;
2934   for (int i=0; i<nbCells; i++)
2935   {
2936     ficcon << i << " - " << myGrid->GetCell(i)->GetCellType() << " -";
2937     int nbptcell = myGrid->GetCell(i)->GetNumberOfPoints();
2938     vtkIdList *listid = myGrid->GetCell(i)->GetPointIds();
2939     for (int j=0; j<nbptcell; j++)
2940     {
2941       ficcon << " " <<  listid->GetId(j);
2942     }
2943     ficcon << endl;
2944   }
2945   ficcon << "-------------------------------- connectivity " <<  nbPoints << endl;
2946   vtkCellLinks *links = myGrid->GetLinks();
2947   for (int i=0; i<nbPoints; i++)
2948   {
2949     int ncells = links->GetNcells(i);
2950     vtkIdType *cells = links->GetCells(i);
2951     ficcon << i << " - " << ncells << " -";
2952     for (int j=0; j<ncells; j++)
2953     {
2954       ficcon << " " << cells[j];
2955     }
2956     ficcon << endl;
2957   }
2958   ficcon.close();
2959
2960 }
2961
2962 void SMDS_Mesh::CompactMesh()
2963 {
2964   this->myCompactTime = this->myModifTime;
2965
2966   bool idsChange = HasNumerationHoles();
2967   if ( idsChange )
2968   {
2969     std::set< SMDS_ElementHolder* >::iterator holder = myElemHolders.begin();
2970     for ( ; holder != myElemHolders.end(); ++holder )
2971       (*holder)->beforeCompacting();
2972   }
2973   int oldCellSize = myCellFactory->GetMaxID();
2974
2975   // remove "holes" in SMDS numeration
2976   std::vector<int> idNodesOldToNew, idCellsNewToOld, idCellsOldToNew;
2977   myNodeFactory->Compact( idNodesOldToNew );
2978   myCellFactory->Compact( idCellsNewToOld );
2979
2980   // make VTK IDs correspond to SMDS IDs
2981   int newNodeSize = myNodeFactory->NbUsedElements();
2982   int newCellSize = myCellFactory->NbUsedElements();
2983   myGrid->compactGrid( idNodesOldToNew, newNodeSize, idCellsNewToOld, newCellSize );
2984
2985   if ( idsChange && !myElemHolders.empty() )
2986   {
2987     // idCellsNewToOld -> idCellsOldToNew
2988     idCellsOldToNew.resize( oldCellSize, oldCellSize );
2989     for ( size_t iNew = 0; iNew < idCellsNewToOld.size(); ++iNew )
2990     {
2991       if ( idCellsNewToOld[ iNew ] >= (int) idCellsOldToNew.size() )
2992         idCellsOldToNew.resize( ( 1 + idCellsNewToOld[ iNew ]) * 1.5, oldCellSize );
2993       idCellsOldToNew[ idCellsNewToOld[ iNew ]] = iNew;
2994     }
2995   }
2996
2997   std::set< SMDS_ElementHolder* >::iterator holder = myElemHolders.begin();
2998   for ( ; holder != myElemHolders.end(); ++holder )
2999     if ( idsChange )
3000       (*holder)->restoreElements( idNodesOldToNew, idCellsOldToNew );
3001     else
3002       (*holder)->compact();
3003
3004   return;
3005 }
3006
3007 int SMDS_Mesh::FromVtkToSmds( int vtkid ) const
3008 {
3009   return myCellFactory->FromVtkToSmds( vtkid );
3010 }
3011
3012 double SMDS_Mesh::getMaxDim()
3013 {
3014   double dmax = 1.e-3;
3015   if ((xmax - xmin) > dmax) dmax = xmax -xmin;
3016   if ((ymax - ymin) > dmax) dmax = ymax -ymin;
3017   if ((zmax - zmin) > dmax) dmax = zmax -zmin;
3018   return dmax;
3019 }
3020
3021 //! modification that needs compact structure and redraw
3022 void SMDS_Mesh::Modified()
3023 {
3024   if (this->myModified)
3025   {
3026     myGrid->Modified();
3027     this->myModifTime++;
3028     myModified = false;
3029   }
3030 }
3031
3032 //! get last modification timeStamp
3033 vtkMTimeType SMDS_Mesh::GetMTime() const
3034 {
3035   return this->myModifTime;
3036 }
3037
3038 bool SMDS_Mesh::IsCompacted()
3039 {
3040   return ( this->myCompactTime == this->myModifTime );
3041 }
3042
3043 //! are there holes in elements or nodes numeration
3044 bool SMDS_Mesh::HasNumerationHoles()
3045 {
3046   return ( myNodeFactory->CompactChangePointers() ||
3047            myCellFactory->CompactChangePointers() );
3048 }
3049
3050 void SMDS_Mesh::setNbShapes( size_t nbShapes )
3051 {
3052   myNodeFactory->SetNbShapes( nbShapes );
3053 }