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