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