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