]> SALOME platform Git repositories - modules/smesh.git/blob - src/SMDS/SMDS_Mesh.cxx
Salome HOME
PAL8238 - improvement for hypothesis "number of segments"
[modules/smesh.git] / src / SMDS / SMDS_Mesh.cxx
1 //  SMESH SMDS : implementaion of Salome mesh data structure
2 //
3 //  Copyright (C) 2003  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.opencascade.org/SALOME/ or email : webmaster.salome@opencascade.org 
21
22 #ifdef _MSC_VER
23 #pragma warning(disable:4786)
24 #endif
25
26 #include "utilities.h"
27 #include "SMDS_Mesh.hxx"
28 #include "SMDS_VolumeOfNodes.hxx"
29 #include "SMDS_VolumeOfFaces.hxx"
30 #include "SMDS_FaceOfNodes.hxx"
31 #include "SMDS_FaceOfEdges.hxx"
32 #include "SMDS_PolyhedralVolumeOfNodes.hxx"
33 #include "SMDS_PolygonalFaceOfNodes.hxx"
34
35 #include <algorithm>
36 #include <map>
37 using namespace std;
38
39 ///////////////////////////////////////////////////////////////////////////////
40 /// Create a new mesh object
41 ///////////////////////////////////////////////////////////////////////////////
42 SMDS_Mesh::SMDS_Mesh()
43         :myParent(NULL),
44         myNodeIDFactory(new SMDS_MeshElementIDFactory()),
45         myElementIDFactory(new SMDS_MeshElementIDFactory()),
46         myHasConstructionEdges(false), myHasConstructionFaces(false),
47         myHasInverseElements(true)
48 {
49 }
50
51 ///////////////////////////////////////////////////////////////////////////////
52 /// Create a new child mesh
53 /// Note that the tree structure of SMDS_Mesh seems to be unused in this version
54 /// (2003-09-08) of SMESH
55 ///////////////////////////////////////////////////////////////////////////////
56 SMDS_Mesh::SMDS_Mesh(SMDS_Mesh * parent)
57         :myParent(parent), myNodeIDFactory(parent->myNodeIDFactory),
58         myElementIDFactory(parent->myElementIDFactory),
59         myHasConstructionEdges(false), myHasConstructionFaces(false),
60         myHasInverseElements(true)
61 {
62 }
63
64 ///////////////////////////////////////////////////////////////////////////////
65 ///Create a submesh and add it to the current mesh
66 ///////////////////////////////////////////////////////////////////////////////
67
68 SMDS_Mesh *SMDS_Mesh::AddSubMesh()
69 {
70         SMDS_Mesh *submesh = new SMDS_Mesh(this);
71         myChildren.insert(myChildren.end(), submesh);
72         return submesh;
73 }
74
75 ///////////////////////////////////////////////////////////////////////////////
76 ///create a MeshNode and add it to the current Mesh
77 ///An ID is automatically assigned to the node.
78 ///@return : The created node
79 ///////////////////////////////////////////////////////////////////////////////
80
81 SMDS_MeshNode * SMDS_Mesh::AddNode(double x, double y, double z)
82 {
83   return SMDS_Mesh::AddNodeWithID(x,y,z,myNodeIDFactory->GetFreeID());
84 }
85
86 ///////////////////////////////////////////////////////////////////////////////
87 ///create a MeshNode and add it to the current Mesh
88 ///@param ID : The ID of the MeshNode to create
89 ///@return : The created node or NULL if a node with this ID already exists
90 ///////////////////////////////////////////////////////////////////////////////
91 SMDS_MeshNode * SMDS_Mesh::AddNodeWithID(double x, double y, double z, int ID)
92 {
93   // find the MeshNode corresponding to ID
94   const SMDS_MeshElement *node = myNodeIDFactory->MeshElement(ID);
95   if(!node){
96     SMDS_MeshNode * node=new SMDS_MeshNode(x, y, z);
97     myNodes.Add(node);
98     myNodeIDFactory->BindID(ID,node);
99     return node;
100   }else
101     return NULL;
102 }
103
104 ///////////////////////////////////////////////////////////////////////////////
105 /// create a MeshEdge and add it to the current Mesh
106 /// @return : The created MeshEdge
107 ///////////////////////////////////////////////////////////////////////////////
108
109 SMDS_MeshEdge* SMDS_Mesh::AddEdgeWithID(int idnode1, int idnode2, int ID) 
110 {
111   SMDS_MeshNode * node1 = (SMDS_MeshNode *)myNodeIDFactory->MeshElement(idnode1);
112   SMDS_MeshNode * node2 = (SMDS_MeshNode *)myNodeIDFactory->MeshElement(idnode2);
113   if(!node1 || !node2) return NULL;
114   return SMDS_Mesh::AddEdgeWithID(node1, node2, ID);
115 }
116
117 ///////////////////////////////////////////////////////////////////////////////
118 /// create a MeshEdge and add it to the current Mesh
119 /// @return : The created MeshEdge
120 ///////////////////////////////////////////////////////////////////////////////
121
122 SMDS_MeshEdge* SMDS_Mesh::AddEdge(const SMDS_MeshNode * node1,
123                                   const SMDS_MeshNode * node2)
124 {
125   return SMDS_Mesh::AddEdgeWithID(node1, node2, myElementIDFactory->GetFreeID());
126 }
127
128 ///////////////////////////////////////////////////////////////////////////////
129 /// Create a new edge and at it to the mesh
130 /// @param idnode1 ID of the first node
131 /// @param idnode2 ID of the second node
132 /// @param ID ID of the edge to create
133 /// @return The created edge or NULL if an element with this ID already exists or
134 /// if input nodes are not found.
135 ///////////////////////////////////////////////////////////////////////////////
136
137 SMDS_MeshEdge* SMDS_Mesh::AddEdgeWithID(const SMDS_MeshNode * n1,
138                                         const SMDS_MeshNode * n2, 
139                                         int ID)
140 {
141   SMDS_MeshEdge * edge=new SMDS_MeshEdge(n1,n2);
142   if(myElementIDFactory->BindID(ID, edge)) {
143     SMDS_MeshNode *node1,*node2;
144     node1=const_cast<SMDS_MeshNode*>(n1);
145     node2=const_cast<SMDS_MeshNode*>(n2);
146     node1->AddInverseElement(edge);
147     node2->AddInverseElement(edge);             
148     myEdges.Add(edge);
149     return edge;
150   } 
151   else {
152     delete edge;
153     return NULL;
154   }
155 }
156
157 ///////////////////////////////////////////////////////////////////////////////
158 /// Add a triangle defined by its nodes. An ID is automatically affected to the
159 /// Created face
160 ///////////////////////////////////////////////////////////////////////////////
161
162 SMDS_MeshFace* SMDS_Mesh::AddFace(const SMDS_MeshNode * n1,
163                                   const SMDS_MeshNode * n2,
164                                   const SMDS_MeshNode * n3)
165 {
166   return SMDS_Mesh::AddFaceWithID(n1,n2,n3, myElementIDFactory->GetFreeID());
167 }
168
169 ///////////////////////////////////////////////////////////////////////////////
170 /// Add a triangle defined by its nodes IDs
171 ///////////////////////////////////////////////////////////////////////////////
172
173 SMDS_MeshFace* SMDS_Mesh::AddFaceWithID(int idnode1, int idnode2, int idnode3, int ID)
174 {
175   SMDS_MeshNode * node1 = (SMDS_MeshNode *)myNodeIDFactory->MeshElement(idnode1);
176   SMDS_MeshNode * node2 = (SMDS_MeshNode *)myNodeIDFactory->MeshElement(idnode2);
177   SMDS_MeshNode * node3 = (SMDS_MeshNode *)myNodeIDFactory->MeshElement(idnode3);
178   if(!node1 || !node2 || !node3) return NULL;
179   return SMDS_Mesh::AddFaceWithID(node1, node2, node3, ID);     
180 }
181
182 ///////////////////////////////////////////////////////////////////////////////
183 /// Add a triangle defined by its nodes
184 ///////////////////////////////////////////////////////////////////////////////
185
186 SMDS_MeshFace* SMDS_Mesh::AddFaceWithID(const SMDS_MeshNode * n1,
187                                         const SMDS_MeshNode * n2,
188                                         const SMDS_MeshNode * n3,
189                                         int ID)
190 {
191   SMDS_MeshFace * face=createTriangle(n1, n2, n3);
192
193   if (!registerElement(ID, face)) {
194     RemoveElement(face, false);
195     face = NULL;
196   }
197   return face;
198 }
199
200 ///////////////////////////////////////////////////////////////////////////////
201 /// Add a quadrangle defined by its nodes. An ID is automatically affected to the
202 /// created face
203 ///////////////////////////////////////////////////////////////////////////////
204
205 SMDS_MeshFace* SMDS_Mesh::AddFace(const SMDS_MeshNode * n1,
206                                   const SMDS_MeshNode * n2,
207                                   const SMDS_MeshNode * n3,
208                                   const SMDS_MeshNode * n4)
209 {
210   return SMDS_Mesh::AddFaceWithID(n1,n2,n3, n4, myElementIDFactory->GetFreeID());
211 }
212
213 ///////////////////////////////////////////////////////////////////////////////
214 /// Add a quadrangle defined by its nodes IDs
215 ///////////////////////////////////////////////////////////////////////////////
216
217 SMDS_MeshFace* SMDS_Mesh::AddFaceWithID(int idnode1, 
218                                         int idnode2, 
219                                         int idnode3,
220                                         int idnode4, 
221                                         int ID)
222 {
223   SMDS_MeshNode *node1, *node2, *node3, *node4;
224   node1 = (SMDS_MeshNode *)myNodeIDFactory->MeshElement(idnode1);
225   node2 = (SMDS_MeshNode *)myNodeIDFactory->MeshElement(idnode2);
226   node3 = (SMDS_MeshNode *)myNodeIDFactory->MeshElement(idnode3);
227   node4 = (SMDS_MeshNode *)myNodeIDFactory->MeshElement(idnode4);
228   if(!node1 || !node2 || !node3 || !node4) return NULL;
229   return SMDS_Mesh::AddFaceWithID(node1, node2, node3, node4, ID);      
230 }
231
232 ///////////////////////////////////////////////////////////////////////////////
233 /// Add a quadrangle defined by its nodes
234 ///////////////////////////////////////////////////////////////////////////////
235
236 SMDS_MeshFace* SMDS_Mesh::AddFaceWithID(const SMDS_MeshNode * n1,
237                                         const SMDS_MeshNode * n2,
238                                         const SMDS_MeshNode * n3,
239                                         const SMDS_MeshNode * n4,
240                                         int ID)
241 {
242   SMDS_MeshFace * face=createQuadrangle(n1, n2, n3, n4);
243
244   if (!registerElement(ID, face)) {
245     RemoveElement(face, false);
246     face = NULL;
247   }
248   return face;
249 }
250
251 ///////////////////////////////////////////////////////////////////////////////
252 /// Add a triangle defined by its edges. An ID is automatically assigned to the
253 /// Created face
254 ///////////////////////////////////////////////////////////////////////////////
255
256 SMDS_MeshFace* SMDS_Mesh::AddFace(const SMDS_MeshEdge * e1,
257                                   const SMDS_MeshEdge * e2,
258                                   const SMDS_MeshEdge * e3)
259 {
260   if (!hasConstructionEdges())
261     return NULL;
262   return AddFaceWithID(e1,e2,e3, myElementIDFactory->GetFreeID());
263 }
264
265 ///////////////////////////////////////////////////////////////////////////////
266 /// Add a triangle defined by its edges
267 ///////////////////////////////////////////////////////////////////////////////
268
269 SMDS_MeshFace* SMDS_Mesh::AddFaceWithID(const SMDS_MeshEdge * e1,
270                                         const SMDS_MeshEdge * e2,
271                                         const SMDS_MeshEdge * e3,
272                                         int ID)
273 {
274   if (!hasConstructionEdges())
275     return NULL;
276   SMDS_MeshFace * face = new SMDS_FaceOfEdges(e1,e2,e3);
277   myFaces.Add(face);
278
279   if (!registerElement(ID, face)) {
280     RemoveElement(face, false);
281     face = NULL;
282   }
283   return face;
284 }
285
286 ///////////////////////////////////////////////////////////////////////////////
287 /// Add a quadrangle defined by its edges. An ID is automatically assigned to the
288 /// Created face
289 ///////////////////////////////////////////////////////////////////////////////
290
291 SMDS_MeshFace* SMDS_Mesh::AddFace(const SMDS_MeshEdge * e1,
292                                   const SMDS_MeshEdge * e2,
293                                   const SMDS_MeshEdge * e3,
294                                   const SMDS_MeshEdge * e4)
295 {
296   if (!hasConstructionEdges())
297     return NULL;
298   return AddFaceWithID(e1,e2,e3,e4, myElementIDFactory->GetFreeID());
299 }
300
301 ///////////////////////////////////////////////////////////////////////////////
302 /// Add a quadrangle defined by its edges
303 ///////////////////////////////////////////////////////////////////////////////
304
305 SMDS_MeshFace* SMDS_Mesh::AddFaceWithID(const SMDS_MeshEdge * e1,
306                                         const SMDS_MeshEdge * e2,
307                                         const SMDS_MeshEdge * e3,
308                                         const SMDS_MeshEdge * e4,
309                                         int ID)
310 {
311   if (!hasConstructionEdges())
312     return NULL;
313   SMDS_MeshFace * face = new SMDS_FaceOfEdges(e1,e2,e3,e4);
314   myFaces.Add(face);
315
316   if (!registerElement(ID, face))
317   {
318     RemoveElement(face, false);
319     face = NULL;
320   }
321   return face;
322 }
323
324 ///////////////////////////////////////////////////////////////////////////////
325 ///Create a new tetrahedron and add it to the mesh. 
326 ///@return The created tetrahedron 
327 ///////////////////////////////////////////////////////////////////////////////
328
329 SMDS_MeshVolume* SMDS_Mesh::AddVolume(const SMDS_MeshNode * n1,
330                                       const SMDS_MeshNode * n2, 
331                                       const SMDS_MeshNode * n3,
332                                       const SMDS_MeshNode * n4)
333 {
334   int ID = myElementIDFactory->GetFreeID();
335   SMDS_MeshVolume * v = SMDS_Mesh::AddVolumeWithID(n1, n2, n3, n4, ID);
336   if(v==NULL) myElementIDFactory->ReleaseID(ID);
337   return v;
338 }
339
340 ///////////////////////////////////////////////////////////////////////////////
341 ///Create a new tetrahedron and add it to the mesh. 
342 ///@param ID The ID of the new volume
343 ///@return The created tetrahedron or NULL if an element with this ID already exists
344 ///or if input nodes are not found.
345 ///////////////////////////////////////////////////////////////////////////////
346
347 SMDS_MeshVolume * SMDS_Mesh::AddVolumeWithID(int idnode1, 
348                                              int idnode2,
349                                              int idnode3, 
350                                              int idnode4, 
351                                              int ID)
352 {
353   SMDS_MeshNode *node1, *node2, *node3, *node4;
354   node1 = (SMDS_MeshNode *)myNodeIDFactory->MeshElement(idnode1);
355   node2 = (SMDS_MeshNode *)myNodeIDFactory->MeshElement(idnode2);
356   node3 = (SMDS_MeshNode *)myNodeIDFactory->MeshElement(idnode3);
357   node4 = (SMDS_MeshNode *)myNodeIDFactory->MeshElement(idnode4);
358   if(!node1 || !node2 || !node3 || !node4) return NULL;
359   return SMDS_Mesh::AddVolumeWithID(node1, node2, node3, node4, ID);
360 }
361         
362 ///////////////////////////////////////////////////////////////////////////////
363 ///Create a new tetrahedron and add it to the mesh. 
364 ///@param ID The ID of the new volume
365 ///@return The created tetrahedron 
366 ///////////////////////////////////////////////////////////////////////////////
367
368 SMDS_MeshVolume* SMDS_Mesh::AddVolumeWithID(const SMDS_MeshNode * n1,
369                                             const SMDS_MeshNode * n2,
370                                             const SMDS_MeshNode * n3,
371                                             const SMDS_MeshNode * n4,
372                                             int ID)
373 {
374   SMDS_MeshVolume* volume;
375   if(hasConstructionFaces()) {
376     SMDS_MeshFace * f1=FindFaceOrCreate(n1,n2,n3);
377     SMDS_MeshFace * f2=FindFaceOrCreate(n1,n2,n4);
378     SMDS_MeshFace * f3=FindFaceOrCreate(n1,n3,n4);
379     SMDS_MeshFace * f4=FindFaceOrCreate(n2,n3,n4);
380     volume=new SMDS_VolumeOfFaces(f1,f2,f3,f4);
381     myVolumes.Add(volume);
382   }
383   else if(hasConstructionEdges()) {
384     MESSAGE("Error : Not implemented");
385     return NULL;
386   }
387   else {
388     volume=new SMDS_VolumeOfNodes(n1,n2,n3,n4);
389     myVolumes.Add(volume);
390   }
391
392   if (!registerElement(ID, volume)) {
393     RemoveElement(volume, false);
394     volume = NULL;
395   }
396   return volume;
397 }
398
399 ///////////////////////////////////////////////////////////////////////////////
400 ///Create a new pyramid and add it to the mesh. 
401 ///Nodes 1,2,3 and 4 define the base of the pyramid
402 ///@return The created pyramid 
403 ///////////////////////////////////////////////////////////////////////////////
404
405 SMDS_MeshVolume* SMDS_Mesh::AddVolume(const SMDS_MeshNode * n1,
406                                       const SMDS_MeshNode * n2, 
407                                       const SMDS_MeshNode * n3,
408                                       const SMDS_MeshNode * n4, 
409                                       const SMDS_MeshNode * n5)
410 {
411   int ID = myElementIDFactory->GetFreeID();
412   SMDS_MeshVolume * v = SMDS_Mesh::AddVolumeWithID(n1, n2, n3, n4, n5, ID);
413   if(v==NULL) myElementIDFactory->ReleaseID(ID);
414   return v;
415 }
416
417 ///////////////////////////////////////////////////////////////////////////////
418 ///Create a new pyramid and add it to the mesh. 
419 ///Nodes 1,2,3 and 4 define the base of the pyramid
420 ///@param ID The ID of the new volume
421 ///@return The created pyramid or NULL if an element with this ID already exists
422 ///or if input nodes are not found.
423 ///////////////////////////////////////////////////////////////////////////////
424
425 SMDS_MeshVolume * SMDS_Mesh::AddVolumeWithID(int idnode1, 
426                                              int idnode2,
427                                              int idnode3, 
428                                              int idnode4, 
429                                              int idnode5, 
430                                              int ID)
431 {
432   SMDS_MeshNode *node1, *node2, *node3, *node4, *node5;
433   node1 = (SMDS_MeshNode *)myNodeIDFactory->MeshElement(idnode1);
434   node2 = (SMDS_MeshNode *)myNodeIDFactory->MeshElement(idnode2);
435   node3 = (SMDS_MeshNode *)myNodeIDFactory->MeshElement(idnode3);
436   node4 = (SMDS_MeshNode *)myNodeIDFactory->MeshElement(idnode4);
437   node5 = (SMDS_MeshNode *)myNodeIDFactory->MeshElement(idnode5);
438   if(!node1 || !node2 || !node3 || !node4 || !node5) return NULL;
439   return SMDS_Mesh::AddVolumeWithID(node1, node2, node3, node4, node5, ID);
440 }
441         
442 ///////////////////////////////////////////////////////////////////////////////
443 ///Create a new pyramid and add it to the mesh.
444 ///Nodes 1,2,3 and 4 define the base of the pyramid
445 ///@param ID The ID of the new volume
446 ///@return The created pyramid
447 ///////////////////////////////////////////////////////////////////////////////
448
449 SMDS_MeshVolume* SMDS_Mesh::AddVolumeWithID(const SMDS_MeshNode * n1,
450                                             const SMDS_MeshNode * n2,
451                                             const SMDS_MeshNode * n3,
452                                             const SMDS_MeshNode * n4,
453                                             const SMDS_MeshNode * n5,
454                                             int ID)
455 {
456   SMDS_MeshVolume* volume;
457   if(hasConstructionFaces()) {
458     SMDS_MeshFace * f1=FindFaceOrCreate(n1,n2,n3,n4);
459     SMDS_MeshFace * f2=FindFaceOrCreate(n1,n2,n5);
460     SMDS_MeshFace * f3=FindFaceOrCreate(n2,n3,n5);
461     SMDS_MeshFace * f4=FindFaceOrCreate(n3,n4,n5);
462     volume=new SMDS_VolumeOfFaces(f1,f2,f3,f4);
463     myVolumes.Add(volume);
464   }
465   else if(hasConstructionEdges()) {
466     MESSAGE("Error : Not implemented");
467     return NULL;
468   }
469   else {
470     volume=new SMDS_VolumeOfNodes(n1,n2,n3,n4,n5);
471     myVolumes.Add(volume);
472   }
473
474   if (!registerElement(ID, volume)) {
475     RemoveElement(volume, false);
476     volume = NULL;
477   }
478   return volume;
479 }
480
481 ///////////////////////////////////////////////////////////////////////////////
482 ///Create a new prism and add it to the mesh. 
483 ///Nodes 1,2,3 is a triangle and 1,2,5,4 a quadrangle.
484 ///@return The created prism 
485 ///////////////////////////////////////////////////////////////////////////////
486
487 SMDS_MeshVolume* SMDS_Mesh::AddVolume(const SMDS_MeshNode * n1,
488                                       const SMDS_MeshNode * n2, 
489                                       const SMDS_MeshNode * n3,
490                                       const SMDS_MeshNode * n4, 
491                                       const SMDS_MeshNode * n5,
492                                       const SMDS_MeshNode * n6)
493 {
494   int ID = myElementIDFactory->GetFreeID();
495   SMDS_MeshVolume * v = SMDS_Mesh::AddVolumeWithID(n1, n2, n3, n4, n5, n6, ID);
496   if(v==NULL) myElementIDFactory->ReleaseID(ID);
497   return v;
498 }
499
500 ///////////////////////////////////////////////////////////////////////////////
501 ///Create a new prism and add it to the mesh. 
502 ///Nodes 1,2,3 is a triangle and 1,2,5,4 a quadrangle.
503 ///@param ID The ID of the new volume
504 ///@return The created prism or NULL if an element with this ID already exists
505 ///or if input nodes are not found.
506 ///////////////////////////////////////////////////////////////////////////////
507
508 SMDS_MeshVolume * SMDS_Mesh::AddVolumeWithID(int idnode1, 
509                                              int idnode2,
510                                              int idnode3, 
511                                              int idnode4, 
512                                              int idnode5, 
513                                              int idnode6, 
514                                              int ID)
515 {
516   SMDS_MeshNode *node1, *node2, *node3, *node4, *node5, *node6;
517   node1 = (SMDS_MeshNode *)myNodeIDFactory->MeshElement(idnode1);
518   node2 = (SMDS_MeshNode *)myNodeIDFactory->MeshElement(idnode2);
519   node3 = (SMDS_MeshNode *)myNodeIDFactory->MeshElement(idnode3);
520   node4 = (SMDS_MeshNode *)myNodeIDFactory->MeshElement(idnode4);
521   node5 = (SMDS_MeshNode *)myNodeIDFactory->MeshElement(idnode5);
522   node6 = (SMDS_MeshNode *)myNodeIDFactory->MeshElement(idnode6);
523   if(!node1 || !node2 || !node3 || !node4 || !node5 || !node6) return NULL;
524   return SMDS_Mesh::AddVolumeWithID(node1, node2, node3, node4, node5, node6, ID);
525 }
526         
527 ///////////////////////////////////////////////////////////////////////////////
528 ///Create a new prism and add it to the mesh.
529 ///Nodes 1,2,3 is a triangle and 1,2,5,4 a quadrangle.
530 ///@param ID The ID of the new volume
531 ///@return The created prism
532 ///////////////////////////////////////////////////////////////////////////////
533
534 SMDS_MeshVolume* SMDS_Mesh::AddVolumeWithID(const SMDS_MeshNode * n1,
535                                             const SMDS_MeshNode * n2,
536                                             const SMDS_MeshNode * n3,
537                                             const SMDS_MeshNode * n4,
538                                             const SMDS_MeshNode * n5,
539                                             const SMDS_MeshNode * n6,
540                                             int ID)
541 {
542   SMDS_MeshVolume* volume;
543   if(hasConstructionFaces()) {
544     SMDS_MeshFace * f1=FindFaceOrCreate(n1,n2,n3);
545     SMDS_MeshFace * f2=FindFaceOrCreate(n4,n5,n6);
546     SMDS_MeshFace * f3=FindFaceOrCreate(n1,n4,n5,n2);
547     SMDS_MeshFace * f4=FindFaceOrCreate(n2,n5,n6,n3);
548     SMDS_MeshFace * f5=FindFaceOrCreate(n3,n6,n4,n1);
549     volume=new SMDS_VolumeOfFaces(f1,f2,f3,f4,f5);
550     myVolumes.Add(volume);
551   }
552   else if(hasConstructionEdges()) {
553     MESSAGE("Error : Not implemented");
554     return NULL;
555   }
556   else {
557     volume=new SMDS_VolumeOfNodes(n1,n2,n3,n4,n5,n6);
558     myVolumes.Add(volume);
559   }
560
561   if (!registerElement(ID, volume)) {
562     RemoveElement(volume, false);
563     volume = NULL;
564   }
565   return volume;
566 }
567
568 ///////////////////////////////////////////////////////////////////////////////
569 ///Create a new hexahedron and add it to the mesh. 
570 ///Nodes 1,2,3,4 and 5,6,7,8 are quadrangle and 5,1 and 7,3 are an edges.
571 ///@return The created hexahedron 
572 ///////////////////////////////////////////////////////////////////////////////
573
574 SMDS_MeshVolume* SMDS_Mesh::AddVolume(const SMDS_MeshNode * n1,
575                                       const SMDS_MeshNode * n2, 
576                                       const SMDS_MeshNode * n3,
577                                       const SMDS_MeshNode * n4, 
578                                       const SMDS_MeshNode * n5,
579                                       const SMDS_MeshNode * n6, 
580                                       const SMDS_MeshNode * n7,
581                                       const SMDS_MeshNode * n8)
582 {
583   int ID = myElementIDFactory->GetFreeID();
584   SMDS_MeshVolume * v = SMDS_Mesh::AddVolumeWithID(n1, n2, n3, n4, n5, n6, n7, n8, ID);
585   if(v==NULL) myElementIDFactory->ReleaseID(ID);
586   return v;
587 }
588
589 ///////////////////////////////////////////////////////////////////////////////
590 ///Create a new hexahedron and add it to the mesh. 
591 ///Nodes 1,2,3,4 and 5,6,7,8 are quadrangle and 5,1 and 7,3 are an edges.
592 ///@param ID The ID of the new volume
593 ///@return The created hexahedron or NULL if an element with this ID already
594 ///exists or if input nodes are not found.
595 ///////////////////////////////////////////////////////////////////////////////
596
597 SMDS_MeshVolume * SMDS_Mesh::AddVolumeWithID(int idnode1, 
598                                              int idnode2,
599                                              int idnode3, 
600                                              int idnode4, 
601                                              int idnode5, 
602                                              int idnode6, 
603                                              int idnode7,
604                                              int idnode8, 
605                                              int ID)
606 {
607   SMDS_MeshNode *node1, *node2, *node3, *node4, *node5, *node6, *node7, *node8;
608   node1 = (SMDS_MeshNode *)myNodeIDFactory->MeshElement(idnode1);
609   node2 = (SMDS_MeshNode *)myNodeIDFactory->MeshElement(idnode2);
610   node3 = (SMDS_MeshNode *)myNodeIDFactory->MeshElement(idnode3);
611   node4 = (SMDS_MeshNode *)myNodeIDFactory->MeshElement(idnode4);
612   node5 = (SMDS_MeshNode *)myNodeIDFactory->MeshElement(idnode5);
613   node6 = (SMDS_MeshNode *)myNodeIDFactory->MeshElement(idnode6);
614   node7 = (SMDS_MeshNode *)myNodeIDFactory->MeshElement(idnode7);
615   node8 = (SMDS_MeshNode *)myNodeIDFactory->MeshElement(idnode8);
616   if(!node1 || !node2 || !node3 || !node4 || !node5 || !node6 || !node7 || !node8)
617     return NULL;
618   return SMDS_Mesh::AddVolumeWithID(node1, node2, node3, node4, node5, node6,
619                                     node7, node8, ID);
620 }
621         
622 ///////////////////////////////////////////////////////////////////////////////
623 ///Create a new hexahedron and add it to the mesh.
624 ///Nodes 1,2,3,4 and 5,6,7,8 are quadrangle and 5,1 and 7,3 are an edges.
625 ///@param ID The ID of the new volume
626 ///@return The created prism or NULL if an element with this ID already exists
627 ///or if input nodes are not found.
628 ///////////////////////////////////////////////////////////////////////////////
629
630 SMDS_MeshVolume* SMDS_Mesh::AddVolumeWithID(const SMDS_MeshNode * n1,
631                                             const SMDS_MeshNode * n2,
632                                             const SMDS_MeshNode * n3,
633                                             const SMDS_MeshNode * n4,
634                                             const SMDS_MeshNode * n5,
635                                             const SMDS_MeshNode * n6,
636                                             const SMDS_MeshNode * n7,
637                                             const SMDS_MeshNode * n8,
638                                             int ID)
639 {
640   SMDS_MeshVolume* volume;
641   if(hasConstructionFaces()) {
642     SMDS_MeshFace * f1=FindFaceOrCreate(n1,n2,n3,n4);
643     SMDS_MeshFace * f2=FindFaceOrCreate(n5,n6,n7,n8);
644     SMDS_MeshFace * f3=FindFaceOrCreate(n1,n4,n8,n5);
645     SMDS_MeshFace * f4=FindFaceOrCreate(n1,n2,n6,n5);
646     SMDS_MeshFace * f5=FindFaceOrCreate(n2,n3,n7,n6);
647     SMDS_MeshFace * f6=FindFaceOrCreate(n3,n4,n8,n7);
648     volume=new SMDS_VolumeOfFaces(f1,f2,f3,f4,f5,f6);
649     myVolumes.Add(volume);
650   }
651   else if(hasConstructionEdges()) {
652     MESSAGE("Error : Not implemented");
653     return NULL;
654   }
655   else {
656 //    volume=new SMDS_HexahedronOfNodes(n1,n2,n3,n4,n5,n6,n7,n8);
657     volume=new SMDS_VolumeOfNodes(n1,n2,n3,n4,n5,n6,n7,n8);
658     myVolumes.Add(volume);
659   }
660
661   if (!registerElement(ID, volume)) {
662     RemoveElement(volume, false);
663     volume = NULL;
664   }
665   return volume;
666 }
667
668 ///////////////////////////////////////////////////////////////////////////////
669 ///Create a new tetrahedron defined by its faces and add it to the mesh.
670 ///@return The created tetrahedron
671 ///////////////////////////////////////////////////////////////////////////////
672
673 SMDS_MeshVolume* SMDS_Mesh::AddVolume(const SMDS_MeshFace * f1,
674                                       const SMDS_MeshFace * f2,
675                                       const SMDS_MeshFace * f3,
676                                       const SMDS_MeshFace * f4)
677 {
678   if (!hasConstructionFaces())
679     return NULL;
680   return AddVolumeWithID(f1,f2,f3,f4, myElementIDFactory->GetFreeID());
681 }
682
683 ///////////////////////////////////////////////////////////////////////////////
684 ///Create a new tetrahedron defined by its faces and add it to the mesh.
685 ///@param ID The ID of the new volume
686 ///@return The created tetrahedron 
687 ///////////////////////////////////////////////////////////////////////////////
688
689 SMDS_MeshVolume* SMDS_Mesh::AddVolumeWithID(const SMDS_MeshFace * f1,
690                                             const SMDS_MeshFace * f2,
691                                             const SMDS_MeshFace * f3,
692                                             const SMDS_MeshFace * f4,
693                                             int ID)
694 {
695   if (!hasConstructionFaces())
696     return NULL;
697   SMDS_MeshVolume * volume = new SMDS_VolumeOfFaces(f1,f2,f3,f4);
698   myVolumes.Add(volume);
699
700   if (!registerElement(ID, volume)) {
701     RemoveElement(volume, false);
702     volume = NULL;
703   }
704   return volume;
705 }
706
707 ///////////////////////////////////////////////////////////////////////////////
708 ///Create a new pyramid defined by its faces and add it to the mesh.
709 ///@return The created pyramid
710 ///////////////////////////////////////////////////////////////////////////////
711
712 SMDS_MeshVolume* SMDS_Mesh::AddVolume(const SMDS_MeshFace * f1,
713                                       const SMDS_MeshFace * f2,
714                                       const SMDS_MeshFace * f3,
715                                       const SMDS_MeshFace * f4,
716                                       const SMDS_MeshFace * f5)
717 {
718   if (!hasConstructionFaces())
719     return NULL;
720   return AddVolumeWithID(f1,f2,f3,f4,f5, myElementIDFactory->GetFreeID());
721 }
722
723 ///////////////////////////////////////////////////////////////////////////////
724 ///Create a new pyramid defined by its faces and add it to the mesh.
725 ///@param ID The ID of the new volume
726 ///@return The created pyramid 
727 ///////////////////////////////////////////////////////////////////////////////
728
729 SMDS_MeshVolume* SMDS_Mesh::AddVolumeWithID(const SMDS_MeshFace * f1,
730                                             const SMDS_MeshFace * f2,
731                                             const SMDS_MeshFace * f3,
732                                             const SMDS_MeshFace * f4,
733                                             const SMDS_MeshFace * f5,
734                                             int ID)
735 {
736   if (!hasConstructionFaces())
737     return NULL;
738   SMDS_MeshVolume * volume = new SMDS_VolumeOfFaces(f1,f2,f3,f4,f5);
739   myVolumes.Add(volume);
740
741   if (!registerElement(ID, volume)) {
742     RemoveElement(volume, false);
743     volume = NULL;
744   }
745   return volume;
746 }
747
748 ///////////////////////////////////////////////////////////////////////////////
749 ///Create a new prism defined by its faces and add it to the mesh.
750 ///@return The created prism
751 ///////////////////////////////////////////////////////////////////////////////
752
753 SMDS_MeshVolume* SMDS_Mesh::AddVolume(const SMDS_MeshFace * f1,
754                                       const SMDS_MeshFace * f2,
755                                       const SMDS_MeshFace * f3,
756                                       const SMDS_MeshFace * f4,
757                                       const SMDS_MeshFace * f5,
758                                       const SMDS_MeshFace * f6)
759 {
760   if (!hasConstructionFaces())
761     return NULL;
762   return AddVolumeWithID(f1,f2,f3,f4,f5,f6, myElementIDFactory->GetFreeID());
763 }
764
765 ///////////////////////////////////////////////////////////////////////////////
766 ///Create a new prism defined by its faces and add it to the mesh.
767 ///@param ID The ID of the new volume
768 ///@return The created prism 
769 ///////////////////////////////////////////////////////////////////////////////
770
771 SMDS_MeshVolume* SMDS_Mesh::AddVolumeWithID(const SMDS_MeshFace * f1,
772                                             const SMDS_MeshFace * f2,
773                                             const SMDS_MeshFace * f3,
774                                             const SMDS_MeshFace * f4,
775                                             const SMDS_MeshFace * f5,
776                                             const SMDS_MeshFace * f6,
777                                             int ID)
778 {
779   if (!hasConstructionFaces())
780     return NULL;
781   SMDS_MeshVolume * volume = new SMDS_VolumeOfFaces(f1,f2,f3,f4,f5,f6);
782   myVolumes.Add(volume);
783
784   if (!registerElement(ID, volume)) {
785     RemoveElement(volume, false);
786     volume = NULL;
787   }
788   return volume;
789 }
790
791 ///////////////////////////////////////////////////////////////////////////////
792 /// Add a polygon defined by its nodes IDs
793 ///////////////////////////////////////////////////////////////////////////////
794
795 SMDS_MeshFace* SMDS_Mesh::AddPolygonalFaceWithID (std::vector<int> nodes_ids,
796                                                   const int        ID)
797 {
798   int nbNodes = nodes_ids.size();
799   std::vector<const SMDS_MeshNode*> nodes (nbNodes);
800   for (int i = 0; i < nbNodes; i++) {
801     nodes[i] = (SMDS_MeshNode *)myNodeIDFactory->MeshElement(nodes_ids[i]);
802     if (!nodes[i]) return NULL;
803   }
804   return SMDS_Mesh::AddPolygonalFaceWithID(nodes, ID);  
805 }
806
807 ///////////////////////////////////////////////////////////////////////////////
808 /// Add a polygon defined by its nodes
809 ///////////////////////////////////////////////////////////////////////////////
810
811 SMDS_MeshFace* SMDS_Mesh::AddPolygonalFaceWithID
812                           (std::vector<const SMDS_MeshNode*> nodes,
813                            const int                         ID)
814 {
815   SMDS_MeshFace * face;
816
817   if (hasConstructionEdges())
818   {
819     MESSAGE("Error : Not implemented");
820     return NULL;
821   }
822   else
823   {
824     face = new SMDS_PolygonalFaceOfNodes(nodes);
825     myFaces.Add(face);
826   }
827
828   if (!registerElement(ID, face)) {
829     RemoveElement(face, false);
830     face = NULL;
831   }
832   return face;
833 }
834
835 ///////////////////////////////////////////////////////////////////////////////
836 /// Add a polygon defined by its nodes.
837 /// An ID is automatically affected to the created face.
838 ///////////////////////////////////////////////////////////////////////////////
839
840 SMDS_MeshFace* SMDS_Mesh::AddPolygonalFace (std::vector<const SMDS_MeshNode*> nodes)
841 {
842   return SMDS_Mesh::AddPolygonalFaceWithID(nodes, myElementIDFactory->GetFreeID());
843 }
844
845 ///////////////////////////////////////////////////////////////////////////////
846 /// Create a new polyhedral volume and add it to the mesh. 
847 /// @param ID The ID of the new volume
848 /// @return The created volume or NULL if an element with this ID already exists
849 /// or if input nodes are not found.
850 ///////////////////////////////////////////////////////////////////////////////
851
852 SMDS_MeshVolume * SMDS_Mesh::AddPolyhedralVolumeWithID
853                              (std::vector<int> nodes_ids,
854                               std::vector<int> quantities,
855                               const int        ID)
856 {
857   int nbNodes = nodes_ids.size();
858   std::vector<const SMDS_MeshNode*> nodes (nbNodes);
859   for (int i = 0; i < nbNodes; i++) {
860     nodes[i] = (SMDS_MeshNode *)myNodeIDFactory->MeshElement(nodes_ids[i]);
861     if (!nodes[i]) return NULL;
862   }
863   return SMDS_Mesh::AddPolyhedralVolumeWithID(nodes, quantities, ID);
864 }
865
866 ///////////////////////////////////////////////////////////////////////////////
867 /// Create a new polyhedral volume and add it to the mesh. 
868 /// @param ID The ID of the new volume
869 /// @return The created  volume
870 ///////////////////////////////////////////////////////////////////////////////
871
872 SMDS_MeshVolume* SMDS_Mesh::AddPolyhedralVolumeWithID
873                             (std::vector<const SMDS_MeshNode*> nodes,
874                              std::vector<int>                  quantities,
875                              const int                         ID)
876 {
877   SMDS_MeshVolume* volume;
878   if (hasConstructionFaces()) {
879     MESSAGE("Error : Not implemented");
880     return NULL;
881   } else if (hasConstructionEdges()) {
882     MESSAGE("Error : Not implemented");
883     return NULL;
884   } else {
885     volume = new SMDS_PolyhedralVolumeOfNodes(nodes, quantities);
886     myVolumes.Add(volume);
887   }
888
889   if (!registerElement(ID, volume)) {
890     RemoveElement(volume, false);
891     volume = NULL;
892   }
893   return volume;
894 }
895
896 ///////////////////////////////////////////////////////////////////////////////
897 /// Create a new polyhedral volume and add it to the mesh. 
898 /// @return The created  volume
899 ///////////////////////////////////////////////////////////////////////////////
900
901 SMDS_MeshVolume* SMDS_Mesh::AddPolyhedralVolume
902                             (std::vector<const SMDS_MeshNode*> nodes,
903                              std::vector<int>                  quantities)
904 {
905   int ID = myElementIDFactory->GetFreeID();
906   SMDS_MeshVolume * v = SMDS_Mesh::AddPolyhedralVolumeWithID(nodes, quantities, ID);
907   if (v == NULL) myElementIDFactory->ReleaseID(ID);
908   return v;
909 }
910
911 ///////////////////////////////////////////////////////////////////////////////
912 /// Registers element with the given ID, maintains inverse connections
913 ///////////////////////////////////////////////////////////////////////////////
914 bool SMDS_Mesh::registerElement(int ID, SMDS_MeshElement * element)
915 {
916   if (myElementIDFactory->BindID(ID, element)) {
917     SMDS_ElemIteratorPtr it = element->nodesIterator();
918     while (it->more()) {
919       SMDS_MeshNode *node = static_cast<SMDS_MeshNode*>
920         (const_cast<SMDS_MeshElement*>(it->next()));
921       node->AddInverseElement(element);
922     }
923     return true;
924   }
925   return false;
926 }
927
928 ///////////////////////////////////////////////////////////////////////////////
929 /// Return the node whose ID is 'ID'.
930 ///////////////////////////////////////////////////////////////////////////////
931 const SMDS_MeshNode * SMDS_Mesh::FindNode(int ID) const
932 {
933   return (const SMDS_MeshNode *)myNodeIDFactory->MeshElement(ID);
934 }
935
936 ///////////////////////////////////////////////////////////////////////////////
937 ///Create a triangle and add it to the current mesh. This methode do not bind a
938 ///ID to the create triangle.
939 ///////////////////////////////////////////////////////////////////////////////
940 SMDS_MeshFace * SMDS_Mesh::createTriangle(const SMDS_MeshNode * node1,
941                                           const SMDS_MeshNode * node2,
942                                           const SMDS_MeshNode * node3)
943 {
944         if(hasConstructionEdges())
945         {
946                 SMDS_MeshEdge *edge1, *edge2, *edge3;
947                 edge1=FindEdgeOrCreate(node1,node2);
948                 edge2=FindEdgeOrCreate(node2,node3);
949                 edge3=FindEdgeOrCreate(node3,node1);
950
951                 SMDS_MeshFace * face = new SMDS_FaceOfEdges(edge1,edge2,edge3);
952                 myFaces.Add(face);
953                 return face;
954         }
955         else
956         {
957                 SMDS_MeshFace * face = new SMDS_FaceOfNodes(node1,node2,node3);
958                 myFaces.Add(face);
959                 return face;
960         }
961 }
962
963 ///////////////////////////////////////////////////////////////////////////////
964 ///Create a quadrangle and add it to the current mesh. This methode do not bind
965 ///a ID to the create triangle.
966 ///////////////////////////////////////////////////////////////////////////////
967 SMDS_MeshFace * SMDS_Mesh::createQuadrangle(const SMDS_MeshNode * node1,
968                                             const SMDS_MeshNode * node2,
969                                             const SMDS_MeshNode * node3,
970                                             const SMDS_MeshNode * node4)
971 {
972         if(hasConstructionEdges())
973         {
974                 SMDS_MeshEdge *edge1, *edge2, *edge3, *edge4;
975                 edge1=FindEdgeOrCreate(node1,node2);
976                 edge2=FindEdgeOrCreate(node2,node3);
977                 edge3=FindEdgeOrCreate(node3,node4);
978                 edge4=FindEdgeOrCreate(node4,node1);
979
980                 SMDS_MeshFace * face = new SMDS_FaceOfEdges(edge1,edge2,edge3,edge4);
981                 myFaces.Add(face);
982                 return face;
983         }
984         else
985         {
986                 SMDS_MeshFace * face = new SMDS_FaceOfNodes(node1,node2,node3,node4);
987                 myFaces.Add(face);
988                 return face;
989         }
990 }
991
992 ///////////////////////////////////////////////////////////////////////////////
993 /// Remove a node and all the elements which own this node
994 ///////////////////////////////////////////////////////////////////////////////
995
996 void SMDS_Mesh::RemoveNode(const SMDS_MeshNode * node)
997 {
998         RemoveElement(node, true);
999 }
1000
1001 ///////////////////////////////////////////////////////////////////////////////
1002 /// Remove an edge and all the elements which own this edge
1003 ///////////////////////////////////////////////////////////////////////////////
1004
1005 void SMDS_Mesh::RemoveEdge(const SMDS_MeshEdge * edge)
1006 {
1007         RemoveElement(edge,true);
1008 }
1009
1010 ///////////////////////////////////////////////////////////////////////////////
1011 /// Remove an face and all the elements which own this face
1012 ///////////////////////////////////////////////////////////////////////////////
1013
1014 void SMDS_Mesh::RemoveFace(const SMDS_MeshFace * face)
1015 {
1016         RemoveElement(face, true);
1017 }
1018
1019 ///////////////////////////////////////////////////////////////////////////////
1020 /// Remove a volume
1021 ///////////////////////////////////////////////////////////////////////////////
1022
1023 void SMDS_Mesh::RemoveVolume(const SMDS_MeshVolume * volume)
1024 {
1025         RemoveElement(volume, true);
1026 }
1027
1028 //=======================================================================
1029 //function : RemoveFromParent
1030 //purpose  :
1031 //=======================================================================
1032
1033 bool SMDS_Mesh::RemoveFromParent()
1034 {
1035         if (myParent==NULL) return false;
1036         else return (myParent->RemoveSubMesh(this));
1037 }
1038
1039 //=======================================================================
1040 //function : RemoveSubMesh
1041 //purpose  :
1042 //=======================================================================
1043
1044 bool SMDS_Mesh::RemoveSubMesh(const SMDS_Mesh * aMesh)
1045 {
1046         bool found = false;
1047
1048         list<SMDS_Mesh *>::iterator itmsh=myChildren.begin();
1049         for (; itmsh!=myChildren.end() && !found; itmsh++)
1050         {
1051                 SMDS_Mesh * submesh = *itmsh;
1052                 if (submesh == aMesh)
1053                 {
1054                         found = true;
1055                         myChildren.erase(itmsh);
1056                 }
1057         }
1058
1059         return found;
1060 }
1061
1062 //=======================================================================
1063 //function : ChangeElementNodes
1064 //purpose  : 
1065 //=======================================================================
1066
1067 bool SMDS_Mesh::ChangeElementNodes(const SMDS_MeshElement * elem,
1068                                    const SMDS_MeshNode    * nodes[],
1069                                    const int                nbnodes)
1070 {
1071   // keep current nodes of elem
1072   set<const SMDS_MeshElement*> oldNodes;
1073   SMDS_ElemIteratorPtr itn = elem->nodesIterator();
1074   while(itn->more())
1075     oldNodes.insert(  itn->next() );
1076
1077   // change nodes
1078   bool Ok = false;
1079   switch ( elem->GetType() )
1080   {
1081   case SMDSAbs_Edge: {
1082     if ( nbnodes == 2 ) {
1083       const SMDS_MeshEdge* edge = dynamic_cast<const SMDS_MeshEdge*>( elem );
1084       if ( edge )
1085         Ok = const_cast<SMDS_MeshEdge*>( edge )->ChangeNodes( nodes[0], nodes[1] );
1086     }
1087     break;
1088   }
1089   case SMDSAbs_Face: {
1090     const SMDS_FaceOfNodes* face = dynamic_cast<const SMDS_FaceOfNodes*>( elem );
1091     if ( face ) {
1092       Ok = const_cast<SMDS_FaceOfNodes*>( face )->ChangeNodes( nodes, nbnodes );
1093     } else {
1094       /// ??? begin
1095       const SMDS_PolygonalFaceOfNodes* face = dynamic_cast<const SMDS_PolygonalFaceOfNodes*>(elem);
1096       if (face) {
1097         Ok = const_cast<SMDS_PolygonalFaceOfNodes*>(face)->ChangeNodes(nodes, nbnodes);
1098       }
1099       /// ??? end
1100     }
1101     break;
1102   }
1103   //case SMDSAbs_PolygonalFace: {
1104   //  const SMDS_PolygonalFaceOfNodes* face = dynamic_cast<const SMDS_PolygonalFaceOfNodes*>(elem);
1105   //  if (face) {
1106   //    Ok = const_cast<SMDS_PolygonalFaceOfNodes*>(face)->ChangeNodes(nodes, nbnodes);
1107   //  }
1108   //  break;
1109   //}
1110   case SMDSAbs_Volume: {
1111     const SMDS_VolumeOfNodes* vol = dynamic_cast<const SMDS_VolumeOfNodes*>( elem );
1112     if ( vol )
1113       Ok = const_cast<SMDS_VolumeOfNodes*>( vol )->ChangeNodes( nodes, nbnodes );
1114     break;
1115   }
1116   default:
1117     MESSAGE ( "WRONG ELEM TYPE");
1118   }
1119
1120   if ( Ok ) { // update InverseElements
1121
1122     // AddInverseElement to new nodes
1123     for ( int i = 0; i < nbnodes; i++ )
1124       if ( oldNodes.find( nodes[i] ) == oldNodes.end() )
1125         // new node
1126         const_cast<SMDS_MeshNode*>( nodes[i] )->AddInverseElement( elem );
1127       else
1128         // remove from oldNodes a node that remains in elem
1129         oldNodes.erase( nodes[i] );
1130
1131
1132     // RemoveInverseElement from the nodes removed from elem
1133     set<const SMDS_MeshElement*>::iterator it;
1134     for ( it = oldNodes.begin(); it != oldNodes.end(); it++ )
1135     {
1136       SMDS_MeshNode * n = static_cast<SMDS_MeshNode *>
1137         (const_cast<SMDS_MeshElement *>( *it ));
1138       n->RemoveInverseElement( elem );
1139     }
1140   }
1141
1142   //MESSAGE ( "::ChangeNodes() Ok = " << Ok);
1143
1144   return Ok;
1145 }
1146
1147 //=======================================================================
1148 //function : ChangePolyhedronNodes
1149 //purpose  : to change nodes of polyhedral volume
1150 //=======================================================================
1151 bool SMDS_Mesh::ChangePolyhedronNodes (const SMDS_MeshElement * elem,
1152                                        std::vector<const SMDS_MeshNode*> nodes,
1153                                        std::vector<int>                  quantities)
1154 {
1155   if (elem->GetType() != SMDSAbs_Volume) {
1156     MESSAGE("WRONG ELEM TYPE");
1157     return false;
1158   }
1159
1160   const SMDS_PolyhedralVolumeOfNodes* vol = dynamic_cast<const SMDS_PolyhedralVolumeOfNodes*>(elem);
1161   if (!vol) {
1162     return false;
1163   }
1164
1165   // keep current nodes of elem
1166   set<const SMDS_MeshElement*> oldNodes;
1167   SMDS_ElemIteratorPtr itn = elem->nodesIterator();
1168   while (itn->more()) {
1169     oldNodes.insert(itn->next());
1170   }
1171
1172   // change nodes
1173   bool Ok = const_cast<SMDS_PolyhedralVolumeOfNodes*>(vol)->ChangeNodes(nodes, quantities);
1174   if (!Ok) {
1175     return false;
1176   }
1177
1178   // update InverseElements
1179
1180   // AddInverseElement to new nodes
1181   int nbnodes = nodes.size();
1182   for (int i = 0; i < nbnodes; i++) {
1183     if (oldNodes.find(nodes[i]) == oldNodes.end()) {
1184       // new node
1185       const_cast<SMDS_MeshNode*>(nodes[i])->AddInverseElement(elem);
1186     } else {
1187       // remove from oldNodes a node that remains in elem
1188       oldNodes.erase(nodes[i]);
1189     }
1190   }
1191
1192   // RemoveInverseElement from the nodes removed from elem
1193   set<const SMDS_MeshElement*>::iterator it;
1194   for (it = oldNodes.begin(); it != oldNodes.end(); it++) {
1195     SMDS_MeshNode * n = static_cast<SMDS_MeshNode *>
1196       (const_cast<SMDS_MeshElement *>( *it ));
1197     n->RemoveInverseElement(elem);
1198   }
1199
1200   return Ok;
1201 }
1202
1203 //=======================================================================
1204 //function : FindEdge
1205 //purpose  :
1206 //=======================================================================
1207
1208 const SMDS_MeshEdge* SMDS_Mesh::FindEdge(int idnode1, int idnode2) const
1209 {
1210         const SMDS_MeshNode * node1=FindNode(idnode1);
1211         const SMDS_MeshNode * node2=FindNode(idnode2);
1212         if((node1==NULL)||(node2==NULL)) return NULL;
1213         return FindEdge(node1,node2);
1214 }
1215
1216 //#include "Profiler.h"
1217 const SMDS_MeshEdge* SMDS_Mesh::FindEdge(const SMDS_MeshNode * node1,
1218                                          const SMDS_MeshNode * node2)
1219 {
1220         const SMDS_MeshEdge * toReturn=NULL;
1221         //PROFILER_Init();
1222         //PROFILER_Set();
1223         SMDS_ElemIteratorPtr it1=node1->edgesIterator();
1224         //PROFILER_Get(0);
1225         //PROFILER_Set();
1226         while(it1->more())
1227         {
1228                 const SMDS_MeshEdge * e=static_cast<const SMDS_MeshEdge *>
1229                         (it1->next());
1230                 SMDS_ElemIteratorPtr it2=e->nodesIterator();
1231                 while(it2->more())
1232                 {
1233                         if(it2->next()->GetID()==node2->GetID())
1234                         {
1235                                 toReturn=e;
1236                                 break;
1237                         }
1238                 }
1239         }
1240         //PROFILER_Get(1);
1241         return toReturn;
1242 }
1243
1244
1245 SMDS_MeshEdge* SMDS_Mesh::FindEdgeOrCreate(const SMDS_MeshNode * node1,
1246         const SMDS_MeshNode * node2) 
1247 {
1248         SMDS_MeshEdge * toReturn=NULL;
1249         toReturn=const_cast<SMDS_MeshEdge*>(FindEdge(node1,node2));
1250         if(toReturn==NULL)      
1251         {
1252           toReturn=new SMDS_MeshEdge(node1,node2);
1253           myEdges.Add(toReturn);
1254         } 
1255         return toReturn;
1256 }
1257
1258 //=======================================================================
1259 //function : FindFace
1260 //purpose  :
1261 //=======================================================================
1262
1263 const SMDS_MeshFace* SMDS_Mesh::FindFace(int idnode1, int idnode2,
1264         int idnode3) const
1265 {
1266         const SMDS_MeshNode * node1=FindNode(idnode1);
1267         const SMDS_MeshNode * node2=FindNode(idnode2);
1268         const SMDS_MeshNode * node3=FindNode(idnode3);
1269         if((node1==NULL)||(node2==NULL)||(node3==NULL)) return NULL;
1270         return FindFace(node1, node2, node3);
1271 }
1272
1273 const SMDS_MeshFace* SMDS_Mesh::FindFace(
1274                 const SMDS_MeshNode *node1,
1275                 const SMDS_MeshNode *node2,
1276                 const SMDS_MeshNode *node3)
1277 {
1278         const SMDS_MeshFace * face;
1279         const SMDS_MeshElement * node;
1280         bool node2found, node3found;
1281
1282         SMDS_ElemIteratorPtr it1=node1->facesIterator();
1283         while(it1->more())
1284         {
1285                 face=static_cast<const SMDS_MeshFace*>(it1->next());
1286                 if(face->NbNodes()!=3) continue;
1287                 SMDS_ElemIteratorPtr it2=face->nodesIterator();
1288                 node2found=false;
1289                 node3found=false;
1290                 while(it2->more())
1291                 {
1292                         node=it2->next();
1293                         if(node->GetID()==node2->GetID()) node2found=true;
1294                         if(node->GetID()==node3->GetID()) node3found=true;
1295                 }
1296                 if(node2found&&node3found)
1297                         return face;
1298         }
1299         return NULL;
1300 }
1301
1302 SMDS_MeshFace* SMDS_Mesh::FindFaceOrCreate(
1303                 const SMDS_MeshNode *node1,
1304                 const SMDS_MeshNode *node2,
1305                 const SMDS_MeshNode *node3)
1306 {
1307         SMDS_MeshFace * toReturn=NULL;
1308         toReturn=const_cast<SMDS_MeshFace*>(FindFace(node1,node2,node3));
1309         if(toReturn==NULL)
1310         {
1311           toReturn=createTriangle(node1,node2,node3);
1312         }
1313         return toReturn;
1314 }
1315
1316 //=======================================================================
1317 //function : FindFace
1318 //purpose  :
1319 //=======================================================================
1320
1321 const SMDS_MeshFace* SMDS_Mesh::FindFace(int idnode1, int idnode2, int idnode3,
1322         int idnode4) const
1323 {
1324         const SMDS_MeshNode * node1=FindNode(idnode1);
1325         const SMDS_MeshNode * node2=FindNode(idnode2);
1326         const SMDS_MeshNode * node3=FindNode(idnode3);
1327         const SMDS_MeshNode * node4=FindNode(idnode4);
1328         if((node1==NULL)||(node2==NULL)||(node3==NULL)||(node4==NULL)) return NULL;
1329         return FindFace(node1, node2, node3, node4);
1330 }
1331
1332 const SMDS_MeshFace* SMDS_Mesh::FindFace(
1333                 const SMDS_MeshNode *node1,
1334                 const SMDS_MeshNode *node2,
1335                 const SMDS_MeshNode *node3,
1336                 const SMDS_MeshNode *node4)
1337 {
1338         const SMDS_MeshFace * face;
1339         const SMDS_MeshElement * node;
1340         bool node2found, node3found, node4found;
1341         SMDS_ElemIteratorPtr it1=node1->facesIterator();
1342         while(it1->more())
1343         {
1344                 face=static_cast<const SMDS_MeshFace *>(it1->next());
1345                 if(face->NbNodes()!=4) continue;
1346                 SMDS_ElemIteratorPtr it2=face->nodesIterator();
1347                 node2found=false;
1348                 node3found=false;
1349                 node4found=false;
1350                 while(it2->more())
1351                 {
1352                         node=it2->next();
1353                         if(node->GetID()==node2->GetID()) node2found=true;
1354                         if(node->GetID()==node3->GetID()) node3found=true;
1355                         if(node->GetID()==node4->GetID()) node4found=true;
1356                 }
1357                 if(node2found&&node3found&&node4found)
1358                         return face;
1359         }
1360         return NULL;
1361 }
1362
1363 SMDS_MeshFace* SMDS_Mesh::FindFaceOrCreate(
1364                 const SMDS_MeshNode *node1,
1365                 const SMDS_MeshNode *node2,
1366                 const SMDS_MeshNode *node3,
1367                 const SMDS_MeshNode *node4)
1368 {
1369         SMDS_MeshFace * toReturn=NULL;
1370         toReturn=const_cast<SMDS_MeshFace*>(FindFace(node1,node2,node3,node4));
1371         if(toReturn==NULL)
1372         {
1373           toReturn=createQuadrangle(node1,node2,node3,node4);
1374         }
1375         return toReturn;
1376 }
1377
1378 //=======================================================================
1379 //function : FindElement
1380 //purpose  :
1381 //=======================================================================
1382
1383 const SMDS_MeshElement* SMDS_Mesh::FindElement(int IDelem) const
1384 {
1385         return myElementIDFactory->MeshElement(IDelem);
1386 }
1387
1388 //=======================================================================
1389 //function : FindFace
1390 //purpose  : find polygon
1391 //=======================================================================
1392
1393 const SMDS_MeshFace* SMDS_Mesh::FindFace (std::vector<int> nodes_ids) const
1394 {
1395   int nbnodes = nodes_ids.size();
1396   std::vector<const SMDS_MeshNode *> poly_nodes (nbnodes);
1397   for (int inode = 0; inode < nbnodes; inode++) {
1398     const SMDS_MeshNode * node = FindNode(nodes_ids[inode]);
1399     if (node == NULL) return NULL;
1400   }
1401   return FindFace(poly_nodes);
1402 }
1403
1404 const SMDS_MeshFace* SMDS_Mesh::FindFace (std::vector<const SMDS_MeshNode *> nodes)
1405 {
1406   int nbNodes = nodes.size();
1407   if (nbNodes < 1) return NULL;
1408
1409   bool isFound = true;
1410   const SMDS_MeshFace * face;
1411   set<const SMDS_MeshFace *> faces;
1412
1413   for (int inode = 0; inode < nbNodes && isFound; inode++) {
1414     set<const SMDS_MeshFace *> new_faces;
1415
1416     SMDS_ElemIteratorPtr itF = nodes[inode]->facesIterator();
1417     while (itF->more()) {
1418       face = static_cast<const SMDS_MeshFace *>(itF->next());
1419       if (face->NbNodes() == nbNodes) {
1420         if (inode == 0 || faces.find(face) != faces.end()) {
1421           new_faces.insert(face);
1422         }
1423       }
1424     }
1425     faces = new_faces;
1426     if (new_faces.size() == 0) {
1427       isFound = false;
1428     }
1429   }
1430
1431   if (isFound)
1432     return face;
1433
1434   return NULL;
1435 }
1436
1437 //=======================================================================
1438 //function : DumpNodes
1439 //purpose  : 
1440 //=======================================================================
1441
1442 void SMDS_Mesh::DumpNodes() const
1443 {
1444         MESSAGE("dump nodes of mesh : ");
1445         SMDS_NodeIteratorPtr itnode=nodesIterator();
1446         while(itnode->more()) MESSAGE(itnode->next());
1447 }
1448
1449 //=======================================================================
1450 //function : DumpEdges
1451 //purpose  : 
1452 //=======================================================================
1453
1454 void SMDS_Mesh::DumpEdges() const
1455 {
1456         MESSAGE("dump edges of mesh : ");
1457         SMDS_EdgeIteratorPtr itedge=edgesIterator();
1458         while(itedge->more()) MESSAGE(itedge->next());
1459 }
1460
1461 //=======================================================================
1462 //function : DumpFaces
1463 //purpose  : 
1464 //=======================================================================
1465
1466 void SMDS_Mesh::DumpFaces() const
1467 {
1468         MESSAGE("dump faces of mesh : ");
1469         SMDS_FaceIteratorPtr itface=facesIterator();
1470         while(itface->more()) MESSAGE(itface->next());
1471 }
1472
1473 //=======================================================================
1474 //function : DumpVolumes
1475 //purpose  : 
1476 //=======================================================================
1477
1478 void SMDS_Mesh::DumpVolumes() const
1479 {
1480         MESSAGE("dump volumes of mesh : ");
1481         SMDS_VolumeIteratorPtr itvol=volumesIterator();
1482         while(itvol->more()) MESSAGE(itvol->next());
1483 }
1484
1485 //=======================================================================
1486 //function : DebugStats
1487 //purpose  : 
1488 //=======================================================================
1489
1490 void SMDS_Mesh::DebugStats() const
1491 {
1492         MESSAGE("Debug stats of mesh : ");
1493
1494         MESSAGE("===== NODES ====="<<NbNodes());
1495         MESSAGE("===== EDGES ====="<<NbEdges());
1496         MESSAGE("===== FACES ====="<<NbFaces());
1497         MESSAGE("===== VOLUMES ====="<<NbVolumes());
1498
1499         MESSAGE("End Debug stats of mesh ");
1500
1501         //#ifdef DEB
1502         
1503         SMDS_NodeIteratorPtr itnode=nodesIterator();
1504         int sizeofnodes = 0;
1505         int sizeoffaces = 0;
1506
1507         while(itnode->more())
1508         {
1509                 const SMDS_MeshNode *node = itnode->next();
1510
1511                 sizeofnodes += sizeof(*node);
1512                 
1513                 SMDS_ElemIteratorPtr it = node->GetInverseElementIterator();
1514                 while(it->more())
1515                 {
1516                         const SMDS_MeshElement *me = it->next();
1517                         sizeofnodes += sizeof(me);
1518                 }
1519
1520         }
1521
1522         SMDS_FaceIteratorPtr itface=facesIterator();
1523         while(itface->more())
1524         {
1525                 const SMDS_MeshElement *face = itface->next();          
1526                 sizeoffaces += sizeof(*face);
1527
1528         }
1529         MESSAGE("total size of node elements = " << sizeofnodes);;
1530         MESSAGE("total size of face elements = " << sizeoffaces);;
1531
1532         //#endif
1533 }
1534
1535 ///////////////////////////////////////////////////////////////////////////////
1536 /// Return the number of nodes
1537 ///////////////////////////////////////////////////////////////////////////////
1538 int SMDS_Mesh::NbNodes() const
1539 {
1540         return myNodes.Size();
1541 }
1542
1543 ///////////////////////////////////////////////////////////////////////////////
1544 /// Return the number of edges (including construction edges)
1545 ///////////////////////////////////////////////////////////////////////////////
1546 int SMDS_Mesh::NbEdges() const
1547 {
1548         return myEdges.Size();
1549 }
1550
1551 ///////////////////////////////////////////////////////////////////////////////
1552 /// Return the number of faces (including construction faces)
1553 ///////////////////////////////////////////////////////////////////////////////
1554 int SMDS_Mesh::NbFaces() const
1555 {
1556         return myFaces.Size();
1557 }
1558
1559 ///////////////////////////////////////////////////////////////////////////////
1560 /// Return the number of volumes
1561 ///////////////////////////////////////////////////////////////////////////////
1562 int SMDS_Mesh::NbVolumes() const
1563 {
1564         return myVolumes.Size();
1565 }
1566
1567 ///////////////////////////////////////////////////////////////////////////////
1568 /// Return the number of child mesh of this mesh.
1569 /// Note that the tree structure of SMDS_Mesh seems to be unused in this version
1570 /// (2003-09-08) of SMESH
1571 ///////////////////////////////////////////////////////////////////////////////
1572 int SMDS_Mesh::NbSubMesh() const
1573 {
1574         return myChildren.size();
1575 }
1576
1577 ///////////////////////////////////////////////////////////////////////////////
1578 /// Destroy the mesh and all its elements
1579 /// All pointer on elements owned by this mesh become illegals.
1580 ///////////////////////////////////////////////////////////////////////////////
1581 SMDS_Mesh::~SMDS_Mesh()
1582 {
1583   list<SMDS_Mesh*>::iterator itc=myChildren.begin();
1584   while(itc!=myChildren.end())
1585   {
1586     delete *itc;
1587     itc++;
1588   }
1589
1590   SetOfNodes::Iterator itn(myNodes);
1591   for (; itn.More(); itn.Next())
1592     delete itn.Value();
1593
1594   SetOfEdges::Iterator ite(myEdges);
1595   for (; ite.More(); ite.Next())
1596   {
1597     SMDS_MeshElement* elem = ite.Value();
1598     if(myParent!=NULL)
1599       myElementIDFactory->ReleaseID(elem->GetID());
1600     delete elem;
1601   }
1602
1603   SetOfFaces::Iterator itf(myFaces);
1604   for (; itf.More(); itf.Next())
1605   {
1606     SMDS_MeshElement* elem = itf.Value();
1607     if(myParent!=NULL)
1608       myElementIDFactory->ReleaseID(elem->GetID());
1609     delete elem;
1610   }
1611
1612   SetOfVolumes::Iterator itv(myVolumes);
1613   for (; itv.More(); itv.Next())
1614   {
1615     SMDS_MeshElement* elem = itv.Value();
1616     if(myParent!=NULL)
1617       myElementIDFactory->ReleaseID(elem->GetID());
1618     delete elem;
1619   }
1620
1621   if(myParent==NULL)
1622   {
1623     delete myNodeIDFactory;
1624     delete myElementIDFactory;
1625   }
1626 }
1627
1628 ///////////////////////////////////////////////////////////////////////////////
1629 /// Return true if this mesh create faces with edges.
1630 /// A false returned value mean that faces are created with nodes. A concequence
1631 /// is, iteration on edges (SMDS_Element::edgesIterator) will be unavailable.
1632 ///////////////////////////////////////////////////////////////////////////////
1633 bool SMDS_Mesh::hasConstructionEdges()
1634 {
1635         return myHasConstructionEdges;
1636 }
1637
1638 ///////////////////////////////////////////////////////////////////////////////
1639 /// Return true if this mesh create volumes with faces
1640 /// A false returned value mean that volumes are created with nodes or edges.
1641 /// (see hasConstructionEdges)
1642 /// A concequence is, iteration on faces (SMDS_Element::facesIterator) will be
1643 /// unavailable.
1644 ///////////////////////////////////////////////////////////////////////////////
1645 bool SMDS_Mesh::hasConstructionFaces()
1646 {
1647         return myHasConstructionFaces;
1648 }
1649
1650 ///////////////////////////////////////////////////////////////////////////////
1651 /// Return true if nodes are linked to the finit elements, they are belonging to.
1652 /// Currently, It always return true.
1653 ///////////////////////////////////////////////////////////////////////////////
1654 bool SMDS_Mesh::hasInverseElements()
1655 {
1656         return myHasInverseElements;
1657 }
1658
1659 ///////////////////////////////////////////////////////////////////////////////
1660 /// Make this mesh creating construction edges (see hasConstructionEdges)
1661 /// @param b true to have construction edges, else false.
1662 ///////////////////////////////////////////////////////////////////////////////
1663 void SMDS_Mesh::setConstructionEdges(bool b)
1664 {
1665         myHasConstructionEdges=b;
1666 }
1667
1668 ///////////////////////////////////////////////////////////////////////////////
1669 /// Make this mesh creating construction faces (see hasConstructionFaces)
1670 /// @param b true to have construction faces, else false.
1671 ///////////////////////////////////////////////////////////////////////////////
1672 void SMDS_Mesh::setConstructionFaces(bool b)
1673 {
1674          myHasConstructionFaces=b;
1675 }
1676
1677 ///////////////////////////////////////////////////////////////////////////////
1678 /// Make this mesh creating link from nodes to elements (see hasInverseElements)
1679 /// @param b true to link nodes to elements, else false.
1680 ///////////////////////////////////////////////////////////////////////////////
1681 void SMDS_Mesh::setInverseElements(bool b)
1682 {
1683         if(!b) MESSAGE("Error : inverseElement=false not implemented");
1684         myHasInverseElements=b;
1685 }
1686
1687 ///////////////////////////////////////////////////////////////////////////////
1688 /// Return an iterator on nodes of the current mesh factory
1689 ///////////////////////////////////////////////////////////////////////////////
1690 class SMDS_Mesh_MyNodeIterator:public SMDS_NodeIterator
1691 {
1692   SMDS_ElemIteratorPtr myIterator;
1693  public:
1694   SMDS_Mesh_MyNodeIterator(const SMDS_ElemIteratorPtr& it):myIterator(it)
1695   {}
1696
1697   bool more()
1698   {
1699     return myIterator->more();
1700   }
1701
1702   const SMDS_MeshNode* next()
1703   {
1704     return static_cast<const SMDS_MeshNode*>(myIterator->next());
1705   }
1706 };
1707
1708 SMDS_NodeIteratorPtr SMDS_Mesh::nodesIterator() const
1709 {
1710   return SMDS_NodeIteratorPtr
1711     (new SMDS_Mesh_MyNodeIterator(myNodeIDFactory->elementsIterator()));
1712 }
1713
1714 ///////////////////////////////////////////////////////////////////////////////
1715 /// Return an iterator on elements of the current mesh factory
1716 ///////////////////////////////////////////////////////////////////////////////
1717 SMDS_ElemIteratorPtr SMDS_Mesh::elementsIterator() const
1718 {
1719   return myElementIDFactory->elementsIterator();
1720 }
1721
1722 ///////////////////////////////////////////////////////////////////////////////
1723 ///Return an iterator on edges of the current mesh.
1724 ///////////////////////////////////////////////////////////////////////////////
1725 class SMDS_Mesh_MyEdgeIterator:public SMDS_EdgeIterator
1726 {
1727   typedef SMDS_Mesh::SetOfEdges SetOfEdges;
1728   SetOfEdges::Iterator myIterator;
1729  public:
1730   SMDS_Mesh_MyEdgeIterator(const SetOfEdges& s):myIterator(s)
1731   {}
1732
1733   bool more()
1734   {
1735     while(myIterator.More())
1736     {
1737       if(myIterator.Value()->GetID()!=-1)
1738         return true;
1739       myIterator.Next();
1740     }
1741     return false;
1742   }
1743
1744   const SMDS_MeshEdge* next()
1745   {
1746     const SMDS_MeshEdge* current = myIterator.Value();
1747     myIterator.Next();
1748     return current;
1749   }
1750 };
1751
1752 SMDS_EdgeIteratorPtr SMDS_Mesh::edgesIterator() const
1753 {
1754   return SMDS_EdgeIteratorPtr(new SMDS_Mesh_MyEdgeIterator(myEdges));
1755 }
1756
1757 ///////////////////////////////////////////////////////////////////////////////
1758 ///Return an iterator on faces of the current mesh.
1759 ///////////////////////////////////////////////////////////////////////////////
1760 class SMDS_Mesh_MyFaceIterator:public SMDS_FaceIterator
1761 {
1762   typedef SMDS_Mesh::SetOfFaces SetOfFaces;
1763   SetOfFaces::Iterator myIterator;
1764  public:
1765   SMDS_Mesh_MyFaceIterator(const SetOfFaces& s):myIterator(s)
1766   {}
1767
1768   bool more()
1769   {
1770     while(myIterator.More())
1771     {
1772       if(myIterator.Value()->GetID()!=-1)
1773         return true;
1774       myIterator.Next();
1775     }
1776     return false;
1777   }
1778
1779   const SMDS_MeshFace* next()
1780   {
1781     const SMDS_MeshFace* current = myIterator.Value();
1782     myIterator.Next();
1783     return current;
1784   }
1785 };
1786
1787 SMDS_FaceIteratorPtr SMDS_Mesh::facesIterator() const
1788 {
1789   return SMDS_FaceIteratorPtr(new SMDS_Mesh_MyFaceIterator(myFaces));
1790 }
1791
1792 ///////////////////////////////////////////////////////////////////////////////
1793 ///Return an iterator on volumes of the current mesh.
1794 ///////////////////////////////////////////////////////////////////////////////
1795 class SMDS_Mesh_MyVolumeIterator:public SMDS_VolumeIterator
1796 {
1797   typedef SMDS_Mesh::SetOfVolumes SetOfVolumes;
1798   SetOfVolumes::Iterator myIterator;
1799  public:
1800   SMDS_Mesh_MyVolumeIterator(const SetOfVolumes& s):myIterator(s)
1801   {}
1802
1803   bool more()
1804   {
1805     return myIterator.More() != Standard_False;
1806   }
1807
1808   const SMDS_MeshVolume* next()
1809   {
1810     const SMDS_MeshVolume* current = myIterator.Value();
1811     myIterator.Next();
1812     return current;
1813   }
1814 };
1815
1816 SMDS_VolumeIteratorPtr SMDS_Mesh::volumesIterator() const
1817 {
1818   return SMDS_VolumeIteratorPtr(new SMDS_Mesh_MyVolumeIterator(myVolumes));
1819 }
1820
1821 ///////////////////////////////////////////////////////////////////////////////
1822 /// Do intersection of sets (more than 2)
1823 ///////////////////////////////////////////////////////////////////////////////
1824 static set<const SMDS_MeshElement*> * intersectionOfSets(
1825         set<const SMDS_MeshElement*> vs[], int numberOfSets)
1826 {
1827         set<const SMDS_MeshElement*>* rsetA=new set<const SMDS_MeshElement*>(vs[0]);
1828         set<const SMDS_MeshElement*>* rsetB;
1829
1830         for(int i=0; i<numberOfSets-1; i++)
1831         {
1832                 rsetB=new set<const SMDS_MeshElement*>();
1833                 set_intersection(
1834                         rsetA->begin(), rsetA->end(),
1835                         vs[i+1].begin(), vs[i+1].end(),
1836                         inserter(*rsetB, rsetB->begin()));
1837                 delete rsetA;
1838                 rsetA=rsetB;
1839         }
1840         return rsetA;
1841 }
1842
1843 ///////////////////////////////////////////////////////////////////////////////
1844 /// Return the list of finit elements owning the given element
1845 ///////////////////////////////////////////////////////////////////////////////
1846 static set<const SMDS_MeshElement*> * getFinitElements(const SMDS_MeshElement * element)
1847 {
1848         int numberOfSets=element->NbNodes();
1849         set<const SMDS_MeshElement*> *initSet = new set<const SMDS_MeshElement*>[numberOfSets];
1850
1851         SMDS_ElemIteratorPtr itNodes=element->nodesIterator();
1852
1853         int i=0;
1854         while(itNodes->more())
1855         {
1856                 const SMDS_MeshNode * n=static_cast<const SMDS_MeshNode*>(itNodes->next());
1857                 SMDS_ElemIteratorPtr itFe = n->GetInverseElementIterator();
1858
1859                 //initSet[i]=set<const SMDS_MeshElement*>();
1860                 while(itFe->more())
1861                   initSet[i].insert(itFe->next());
1862
1863                 i++;
1864         }
1865         set<const SMDS_MeshElement*> *retSet=intersectionOfSets(initSet, numberOfSets);
1866         delete [] initSet;
1867         return retSet;
1868 }
1869
1870 ///////////////////////////////////////////////////////////////////////////////
1871 /// Return the list of nodes used only by the given elements
1872 ///////////////////////////////////////////////////////////////////////////////
1873 static set<const SMDS_MeshElement*> * getExclusiveNodes(
1874         set<const SMDS_MeshElement*>& elements)
1875 {
1876         set<const SMDS_MeshElement*> * toReturn=new set<const SMDS_MeshElement*>();
1877         set<const SMDS_MeshElement*>::iterator itElements=elements.begin();
1878
1879         while(itElements!=elements.end())
1880         {
1881                 SMDS_ElemIteratorPtr itNodes = (*itElements)->nodesIterator();
1882                 itElements++;
1883         
1884                 while(itNodes->more())
1885                 {
1886                         const SMDS_MeshNode * n=static_cast<const SMDS_MeshNode*>(itNodes->next());
1887                         SMDS_ElemIteratorPtr itFe = n->GetInverseElementIterator();
1888                         set<const SMDS_MeshElement*> s;
1889                         while(itFe->more())
1890                           s.insert(itFe->next());
1891                         if(s==elements) toReturn->insert(n);
1892                 }
1893         }
1894         return toReturn;        
1895 }
1896
1897 ///////////////////////////////////////////////////////////////////////////////
1898 ///Find the children of an element that are made of given nodes 
1899 ///@param setOfChildren The set in which matching children will be inserted
1900 ///@param element The element were to search matching children
1901 ///@param nodes The nodes that the children must have to be selected
1902 ///////////////////////////////////////////////////////////////////////////////
1903 void SMDS_Mesh::addChildrenWithNodes(set<const SMDS_MeshElement*>&      setOfChildren, 
1904         const SMDS_MeshElement * element, set<const SMDS_MeshElement*>& nodes)
1905 {
1906         
1907         switch(element->GetType())
1908         {
1909         case SMDSAbs_Node:
1910                 MESSAGE("Internal Error: This should not append");
1911                 break;
1912         case SMDSAbs_Edge:
1913         {
1914                 SMDS_ElemIteratorPtr itn=element->nodesIterator();
1915                 while(itn->more())
1916                 {
1917                         const SMDS_MeshElement * e=itn->next();
1918                         if(nodes.find(e)!=nodes.end())
1919                         {
1920                           setOfChildren.insert(element);
1921                           break;
1922                         }
1923                 }
1924         } break;
1925         case SMDSAbs_Face:
1926         {
1927                 SMDS_ElemIteratorPtr itn=element->nodesIterator();
1928                 while(itn->more())
1929                 {
1930                         const SMDS_MeshElement * e=itn->next();
1931                         if(nodes.find(e)!=nodes.end())
1932                         {
1933                           setOfChildren.insert(element);
1934                           break;
1935                         }
1936                 }
1937                 if(hasConstructionEdges())
1938                 {
1939                         SMDS_ElemIteratorPtr ite=element->edgesIterator();
1940                         while(ite->more())
1941                                 addChildrenWithNodes(setOfChildren, ite->next(), nodes);
1942                 }
1943         } break;        
1944         case SMDSAbs_Volume:
1945         {
1946                 if(hasConstructionFaces())
1947                 {
1948                         SMDS_ElemIteratorPtr ite=element->facesIterator();
1949                         while(ite->more())
1950                                 addChildrenWithNodes(setOfChildren, ite->next(), nodes);
1951                 }
1952                 else if(hasConstructionEdges())
1953                 {
1954                         SMDS_ElemIteratorPtr ite=element->edgesIterator();
1955                         while(ite->more())
1956                                 addChildrenWithNodes(setOfChildren, ite->next(), nodes);
1957                 }
1958         }
1959         }
1960 }
1961
1962 ///////////////////////////////////////////////////////////////////////////////
1963 ///@param elem The element to delete
1964 ///@param removenodes if true remaining nodes will be removed
1965 ///////////////////////////////////////////////////////////////////////////////
1966 void SMDS_Mesh::RemoveElement(const SMDS_MeshElement * elem,
1967         const bool removenodes)
1968 {
1969   list<const SMDS_MeshElement *> removedElems;
1970   list<const SMDS_MeshElement *> removedNodes;
1971   RemoveElement( elem, removedElems, removedNodes, removenodes );
1972 }
1973   
1974 ///////////////////////////////////////////////////////////////////////////////
1975 ///@param elem The element to delete
1976 ///@param removedElems contains all removed elements
1977 ///@param removedNodes contains all removed nodes
1978 ///@param removenodes if true remaining nodes will be removed
1979 ///////////////////////////////////////////////////////////////////////////////
1980 void SMDS_Mesh::RemoveElement(const SMDS_MeshElement *        elem,
1981                               list<const SMDS_MeshElement *>& removedElems,
1982                               list<const SMDS_MeshElement *>& removedNodes,
1983                               bool                            removenodes)
1984 {
1985   // get finite elements built on elem
1986   set<const SMDS_MeshElement*> * s1;
1987   if (!hasConstructionEdges() && elem->GetType() == SMDSAbs_Edge ||
1988       !hasConstructionFaces() && elem->GetType() == SMDSAbs_Face ||
1989       elem->GetType() == SMDSAbs_Volume)
1990   {
1991     s1 = new set<const SMDS_MeshElement*>();
1992     s1->insert(elem);
1993   }
1994   else
1995     s1 = getFinitElements(elem);
1996
1997   // get exclusive nodes (which would become free afterwards)
1998   set<const SMDS_MeshElement*> * s2;
1999   if (elem->GetType() == SMDSAbs_Node) // a node is removed
2000   {
2001     // do not remove nodes except elem
2002     s2 = new set<const SMDS_MeshElement*>();
2003     s2->insert(elem);
2004     removenodes = true;
2005   }
2006   else
2007     s2 = getExclusiveNodes(*s1);
2008
2009   // form the set of finite and construction elements to remove
2010   set<const SMDS_MeshElement*> s3;
2011   set<const SMDS_MeshElement*>::iterator it=s1->begin();
2012   while(it!=s1->end())
2013   {
2014     addChildrenWithNodes(s3, *it ,*s2);
2015     s3.insert(*it);
2016     it++;
2017   }
2018   if(elem->GetType()!=SMDSAbs_Node) s3.insert(elem);
2019
2020   // remove finite and construction elements
2021   it=s3.begin();
2022   while(it!=s3.end())
2023   {
2024     // Remove element from <InverseElements> of its nodes
2025     SMDS_ElemIteratorPtr itn=(*it)->nodesIterator();
2026     while(itn->more())
2027     {
2028       SMDS_MeshNode * n = static_cast<SMDS_MeshNode *>
2029         (const_cast<SMDS_MeshElement *>(itn->next()));
2030       n->RemoveInverseElement( (*it) );
2031     }
2032
2033     switch((*it)->GetType())
2034     {
2035     case SMDSAbs_Node:
2036       MESSAGE("Internal Error: This should not happen");
2037       break;
2038     case SMDSAbs_Edge:
2039       myEdges.Remove(static_cast<SMDS_MeshEdge*>
2040                     (const_cast<SMDS_MeshElement*>(*it)));
2041       break;
2042     case SMDSAbs_Face:
2043       myFaces.Remove(static_cast<SMDS_MeshFace*>
2044                     (const_cast<SMDS_MeshElement*>(*it)));
2045       break;
2046     case SMDSAbs_Volume:
2047       myVolumes.Remove(static_cast<SMDS_MeshVolume*>
2048                       (const_cast<SMDS_MeshElement*>(*it)));
2049       break;
2050     }
2051     //MESSAGE( "SMDS: RM elem " << (*it)->GetID() );
2052     removedElems.push_back( (*it) );
2053     myElementIDFactory->ReleaseID((*it)->GetID());
2054     delete (*it);
2055     it++;
2056   }
2057
2058   // remove exclusive (free) nodes
2059   if(removenodes)
2060   {
2061     it=s2->begin();
2062     while(it!=s2->end())
2063     {
2064       //MESSAGE( "SMDS: RM node " << (*it)->GetID() );
2065       myNodes.Remove(static_cast<SMDS_MeshNode*>
2066                     (const_cast<SMDS_MeshElement*>(*it)));
2067       myNodeIDFactory->ReleaseID((*it)->GetID());
2068       removedNodes.push_back( (*it) );
2069       delete *it;
2070       it++;
2071     }
2072   }
2073
2074   delete s2;
2075   delete s1;
2076 }
2077
2078 /*!
2079  * Checks if the element is present in mesh.
2080  * Useful to determine dead pointers.
2081  */
2082 bool SMDS_Mesh::Contains (const SMDS_MeshElement* elem) const
2083 {
2084   // we should not imply on validity of *elem, so iterate on containers
2085   // of all types in the hope of finding <elem> somewhere there
2086   SMDS_NodeIteratorPtr itn = nodesIterator();
2087   while (itn->more())
2088     if (elem == itn->next())
2089       return true;
2090   SMDS_EdgeIteratorPtr ite = edgesIterator();
2091   while (ite->more())
2092     if (elem == ite->next())
2093       return true;
2094   SMDS_FaceIteratorPtr itf = facesIterator();
2095   while (itf->more())
2096     if (elem == itf->next())
2097       return true;
2098   SMDS_VolumeIteratorPtr itv = volumesIterator();
2099   while (itv->more())
2100     if (elem == itv->next())
2101       return true;
2102   return false;
2103 }
2104
2105 //=======================================================================
2106 //function : MaxNodeID
2107 //purpose  : 
2108 //=======================================================================
2109
2110 int SMDS_Mesh::MaxNodeID() const
2111 {
2112   return myNodeIDFactory->GetMaxID();
2113 }
2114
2115 //=======================================================================
2116 //function : MinNodeID
2117 //purpose  : 
2118 //=======================================================================
2119
2120 int SMDS_Mesh::MinNodeID() const
2121 {
2122   return myNodeIDFactory->GetMinID();
2123 }
2124
2125 //=======================================================================
2126 //function : MaxElementID
2127 //purpose  : 
2128 //=======================================================================
2129
2130 int SMDS_Mesh::MaxElementID() const
2131 {
2132   return myElementIDFactory->GetMaxID();
2133 }
2134
2135 //=======================================================================
2136 //function : MinElementID
2137 //purpose  : 
2138 //=======================================================================
2139
2140 int SMDS_Mesh::MinElementID() const
2141 {
2142   return myElementIDFactory->GetMinID();
2143 }
2144
2145 //=======================================================================
2146 //function : Renumber
2147 //purpose  : Renumber all nodes or elements.
2148 //=======================================================================
2149
2150 void SMDS_Mesh::Renumber (const bool isNodes, const int  startID, const int  deltaID)
2151 {
2152   if ( deltaID == 0 )
2153     return;
2154
2155   SMDS_MeshElementIDFactory * idFactory =
2156     isNodes ? myNodeIDFactory : myElementIDFactory;
2157
2158   // get existing elements in the order of ID increasing
2159   map<int,SMDS_MeshElement*> elemMap;
2160   SMDS_ElemIteratorPtr idElemIt = idFactory->elementsIterator();
2161   while ( idElemIt->more() ) {
2162     SMDS_MeshElement* elem = const_cast<SMDS_MeshElement*>(idElemIt->next());
2163     int id = elem->GetID();
2164     elemMap.insert(map<int,SMDS_MeshElement*>::value_type(id, elem));
2165   }
2166   // release their ids
2167   map<int,SMDS_MeshElement*>::iterator elemIt = elemMap.begin();
2168   for ( ; elemIt != elemMap.end(); elemIt++ )
2169   {
2170     int id = (*elemIt).first;
2171     idFactory->ReleaseID( id );
2172   }
2173   // set new IDs
2174   int ID = startID;
2175   elemIt = elemMap.begin();
2176   for ( ; elemIt != elemMap.end(); elemIt++ )
2177   {
2178     idFactory->BindID( ID, (*elemIt).second );
2179     ID += deltaID;
2180   }
2181 }
2182
2183 //=======================================================================
2184 //function : GetElementType
2185 //purpose  : Return type of element or node with id
2186 //=======================================================================
2187
2188 SMDSAbs_ElementType SMDS_Mesh::GetElementType( const int id, const bool iselem ) const
2189 {
2190   SMDS_MeshElement* elem = 0;
2191   if( iselem )
2192     elem = myElementIDFactory->MeshElement( id );
2193   else
2194     elem = myNodeIDFactory->MeshElement( id );
2195
2196   if( !elem )
2197   {
2198     //throw SALOME_Exception(LOCALIZED ("this element isn't exist"));
2199     return SMDSAbs_All;
2200   }
2201   else
2202     return elem->GetType();
2203 }