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