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