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