Salome HOME
New DS implementation
[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 #include "utilities.h"
23 #include "SMDS_Mesh.hxx"
24 #include "SMDS_VolumeOfNodes.hxx"
25 #include "SMDS_VolumeOfFaces.hxx"
26 #include "SMDS_FaceOfNodes.hxx"
27 #include "SMDS_FaceOfEdges.hxx"
28
29 ///////////////////////////////////////////////////////////////////////////////
30 /// Create a new mesh object
31 ///////////////////////////////////////////////////////////////////////////////
32 SMDS_Mesh::SMDS_Mesh()
33         :myNodeIDFactory(new SMDS_MeshElementIDFactory()),
34         myElementIDFactory(new SMDS_MeshElementIDFactory()),
35         myHasConstructionEdges(false), myHasConstructionFaces(false),
36         myHasInverseElements(true)
37 {
38 }
39
40 ///////////////////////////////////////////////////////////////////////////////
41 ///////////////////////////////////////////////////////////////////////////////
42 SMDS_Mesh::SMDS_Mesh(SMDS_Mesh * parent)
43         :myParent(parent), myNodeIDFactory(parent->myNodeIDFactory),
44         myElementIDFactory(parent->myElementIDFactory),
45         myHasConstructionEdges(false), myHasConstructionFaces(false),
46         myHasInverseElements(true)
47 {
48 }
49
50 ///////////////////////////////////////////////////////////////////////////////
51 ///Create a submesh and add it to the current mesh
52 ///////////////////////////////////////////////////////////////////////////////
53
54 SMDS_Mesh *SMDS_Mesh::AddSubMesh()
55 {
56         SMDS_Mesh *submesh = new SMDS_Mesh(this);
57         myChildren.insert(myChildren.end(), submesh);
58         return submesh;
59 }
60
61 ///////////////////////////////////////////////////////////////////////////////
62 ///create a MeshNode and add it to the current Mesh
63 ///@return : The created node
64 ///////////////////////////////////////////////////////////////////////////////
65
66 SMDS_MeshNode * SMDS_Mesh::AddNode(double x, double y, double z)
67 {
68         return AddNodeWithID(x,y,z,myNodeIDFactory->GetFreeID());
69 }
70
71 ///////////////////////////////////////////////////////////////////////////////
72 ///create a MeshNode and add it to the current Mesh
73 ///@param ID : The ID of the MeshNode to create
74 ///@return : The created node or NULL if a node with this ID already exists
75 ///////////////////////////////////////////////////////////////////////////////
76 SMDS_MeshNode * SMDS_Mesh::AddNodeWithID(double x, double y, double z, int ID)
77 {
78         // find the MeshNode corresponding to ID
79         const SMDS_MeshElement *node = myNodeIDFactory->MeshElement(ID);
80
81         if (node == NULL)
82         {
83                 SMDS_MeshNode * node=new SMDS_MeshNode(x, y, z);
84                 myNodes.insert(node);
85                 myNodeIDFactory->BindID(ID,node);
86                 return node;
87         }
88         else
89                 return NULL;
90 }
91
92 ///////////////////////////////////////////////////////////////////////////////
93 ///create a MeshEdge and add it to the current Mesh
94 ///@return : The created MeshEdge
95 ///////////////////////////////////////////////////////////////////////////////
96
97 SMDS_MeshEdge* SMDS_Mesh::AddEdge(int idnode1, int idnode2)
98 {
99         return AddEdgeWithID(idnode1, idnode2, myElementIDFactory->GetFreeID());
100 }
101
102 ///////////////////////////////////////////////////////////////////////////////
103 ///Create a new edge and at it to the mesh
104 ///@param idnode1 ID of the first node
105 ///@param idnode2 ID of the second node
106 ///@param ID ID of the edge to create
107 ///@return The created edge or NULL if an edge with this ID already exists or
108 ///if input nodes are not found.
109 ///////////////////////////////////////////////////////////////////////////////
110
111 SMDS_MeshEdge* SMDS_Mesh::AddEdgeWithID(int idnode1, int idnode2, int ID)
112 {
113         SMDS_MeshNode * node1 = (SMDS_MeshNode *)myNodeIDFactory->MeshElement(idnode1);
114         SMDS_MeshNode * node2 = (SMDS_MeshNode *)myNodeIDFactory->MeshElement(idnode2);
115         if((node1==NULL)||(node2==NULL)) return NULL;
116         SMDS_MeshEdge * edge=new SMDS_MeshEdge(node1, node2);
117         if(myElementIDFactory->BindID(ID, edge))
118         {
119                 node1->AddInverseElement(edge);
120                 node2->AddInverseElement(edge);         
121                 myEdges.insert(edge);
122                 return edge;
123         } 
124         else
125         {
126                 delete edge;
127                 return NULL;
128         }
129 }
130
131 ///////////////////////////////////////////////////////////////////////////////
132 /// Add a triangle defined by its nodes IDs
133 ///////////////////////////////////////////////////////////////////////////////
134
135 SMDS_MeshFace* SMDS_Mesh::AddFace(int idnode1, int idnode2, int idnode3)
136 {
137         return AddFaceWithID(idnode1,idnode2,idnode3,
138                 myElementIDFactory->GetFreeID());
139 }
140
141 ///////////////////////////////////////////////////////////////////////////////
142 /// Add a quandrangle defined by its nodes IDs
143 ///////////////////////////////////////////////////////////////////////////////
144
145 SMDS_MeshFace* SMDS_Mesh::AddFaceWithID(int idnode1, int idnode2, int idnode3, int ID)
146 {
147         SMDS_MeshNode * node1 = (SMDS_MeshNode *)myNodeIDFactory->MeshElement(idnode1);
148         SMDS_MeshNode * node2 = (SMDS_MeshNode *)myNodeIDFactory->MeshElement(idnode2);
149         SMDS_MeshNode * node3 = (SMDS_MeshNode *)myNodeIDFactory->MeshElement(idnode3);
150
151         if((node1==NULL)||(node2==NULL)||(node3==NULL)) return NULL;
152     SMDS_MeshFace * face=createTriangle(node1,node2,node3);
153
154         if(myElementIDFactory->BindID(ID, face))
155         {
156                 node1->AddInverseElement(face);
157                 node2->AddInverseElement(face);
158         node3->AddInverseElement(face);
159                 return face;
160         }       
161         else
162         {
163                 RemoveFace(face);
164                 return NULL;
165         }
166 }
167
168 //=======================================================================
169 //function : AddFace
170 //purpose  :
171 //=======================================================================
172
173 SMDS_MeshFace* SMDS_Mesh::AddFace(int idnode1,
174         int idnode2, int idnode3, int idnode4)
175 {
176         int ID=myElementIDFactory->GetFreeID();
177         SMDS_MeshFace* f= AddFaceWithID(idnode1, idnode2, idnode3, idnode4, ID);
178         if(f==NULL) myElementIDFactory->ReleaseID(ID);
179 }
180
181 //=======================================================================
182 //function : AddFace
183 //purpose  :
184 //=======================================================================
185
186 SMDS_MeshFace* SMDS_Mesh::AddFaceWithID(int idnode1,
187         int idnode2, int idnode3, int idnode4, int ID)
188 {
189         SMDS_MeshNode * node1 = (SMDS_MeshNode *)myNodeIDFactory->MeshElement(idnode1);
190         SMDS_MeshNode * node2 = (SMDS_MeshNode *)myNodeIDFactory->MeshElement(idnode2);
191         SMDS_MeshNode * node3 = (SMDS_MeshNode *)myNodeIDFactory->MeshElement(idnode3);
192         SMDS_MeshNode * node4 = (SMDS_MeshNode *)myNodeIDFactory->MeshElement(idnode4);
193
194         if((node1==NULL)||(node2==NULL)||(node3==NULL)||(node4==NULL)) return NULL;
195     SMDS_MeshFace * face=createQuadrangle(node1,node2,node3,node4);
196
197         if(myElementIDFactory->BindID(ID, face))
198         {
199                 node1->AddInverseElement(face);
200                 node2->AddInverseElement(face);
201         node3->AddInverseElement(face);
202                 node4->AddInverseElement(face);
203                 return face;
204         }       
205         else
206         {
207                 RemoveFace(face);
208                 return NULL;
209         }
210 }
211
212 //=======================================================================
213 //function : AddVolume
214 //purpose  : Tetrahedra
215 //=======================================================================
216
217 SMDS_MeshVolume * SMDS_Mesh::AddVolume(int idnode1, int idnode2, int idnode3,
218         int idnode4)
219 {
220         int ID = myElementIDFactory->GetFreeID();
221         SMDS_MeshVolume * v=
222                 AddVolumeWithID(idnode1, idnode2, idnode3, idnode4, ID);
223         if(v==NULL) myElementIDFactory->ReleaseID(ID);
224 }
225
226
227 ///////////////////////////////////////////////////////////////////////////////
228 ///Create a new tetrahedron and add it to the mesh. 
229 ///@return The created tetrahedron or NULL if an edge with this ID already exists
230 ///or if input nodes are not found.
231 ///////////////////////////////////////////////////////////////////////////////
232
233 SMDS_MeshVolume * SMDS_Mesh::AddVolumeWithID(int idnode1, int idnode2,
234         int idnode3, int idnode4, int ID)
235 {
236         SMDS_MeshNode * node1 = (SMDS_MeshNode *)myNodeIDFactory->MeshElement(idnode1);
237         SMDS_MeshNode * node2 = (SMDS_MeshNode *)myNodeIDFactory->MeshElement(idnode2);
238         SMDS_MeshNode * node3 = (SMDS_MeshNode *)myNodeIDFactory->MeshElement(idnode3);
239         SMDS_MeshNode * node4 = (SMDS_MeshNode *)myNodeIDFactory->MeshElement(idnode4);
240
241         if((node1==NULL)||(node2==NULL)||(node3==NULL)||(node4=NULL)) return NULL;
242         
243         SMDS_MeshVolume* volume;
244         if(hasConstructionFaces())
245         {
246                 SMDS_MeshFace * f1=createTriangle(node1,node2,node3);
247                 SMDS_MeshFace * f2=createTriangle(node1,node2,node4);
248                 SMDS_MeshFace * f3=createTriangle(node1,node3,node4);
249                 SMDS_MeshFace * f4=createTriangle(node2,node3,node4);
250                 SMDS_MeshVolume* volume=
251                         new SMDS_VolumeOfFaces(f1,f2,f3,f4);
252                 myVolumes.insert(volume);
253         }
254         else if(hasConstructionEdges())
255         {
256                 /** @todo */
257         }
258         else
259         {
260                 /** @todo */
261         }
262
263         if(myElementIDFactory->BindID(ID, volume))
264         {
265                 node1->AddInverseElement(volume);
266                 node2->AddInverseElement(volume);
267         node3->AddInverseElement(volume);
268                 node4->AddInverseElement(volume);
269                 return volume;
270         }       
271         else
272         {
273                 RemoveVolume(volume);
274                 return NULL;
275         }
276 }
277
278 ///////////////////////////////////////////////////////////////////////////////
279 /// Add a pyramid to the mesh. node 1,2,3 and 4 define the base of the pyramid
280 ///////////////////////////////////////////////////////////////////////////////
281 SMDS_MeshVolume * SMDS_Mesh::AddVolume(int idnode1,
282         int idnode2, int idnode3, int idnode4, int idnode5)
283 {
284         int ID = myElementIDFactory->GetFreeID();
285         SMDS_MeshVolume * v=
286                 AddVolumeWithID(idnode1, idnode2, idnode3, idnode4, idnode5, ID);
287         if(v==NULL) myElementIDFactory->ReleaseID(ID);
288 }
289
290 ///////////////////////////////////////////////////////////////////////////////
291 /// Add a pyramid to the mesh. node 1,2,3 and 4 define the base of the pyramid
292 ///////////////////////////////////////////////////////////////////////////////
293 SMDS_MeshVolume* SMDS_Mesh::AddVolumeWithID(int idnode1, int idnode2,
294         int idnode3, int idnode4, int idnode5, int ID)
295 {
296         SMDS_MeshNode * node1 = (SMDS_MeshNode *)myNodeIDFactory->MeshElement(idnode1);
297         SMDS_MeshNode * node2 = (SMDS_MeshNode *)myNodeIDFactory->MeshElement(idnode2);
298         SMDS_MeshNode * node3 = (SMDS_MeshNode *)myNodeIDFactory->MeshElement(idnode3);
299         SMDS_MeshNode * node4 = (SMDS_MeshNode *)myNodeIDFactory->MeshElement(idnode4);
300         SMDS_MeshNode * node5 = (SMDS_MeshNode *)myNodeIDFactory->MeshElement(idnode5);
301
302         if((node1==NULL)||(node2==NULL)||(node3==NULL)||(node4==NULL)||(node5==NULL))
303                 return NULL;
304         
305         SMDS_MeshVolume* volume;
306         if(hasConstructionFaces())
307         {
308                 SMDS_MeshFace * f1=createQuadrangle(node1,node2,node3,node4);
309                 SMDS_MeshFace * f2=createTriangle(node1,node2,node5);
310                 SMDS_MeshFace * f3=createTriangle(node2,node3,node5);
311                 SMDS_MeshFace * f4=createTriangle(node3,node4,node5);
312                 SMDS_MeshFace * f5=createTriangle(node4,node1,node4);
313                 SMDS_MeshVolume* volume=new SMDS_VolumeOfFaces(f1,f2,f3,f4,f5);
314                 myVolumes.insert(volume);
315         }
316         else if(hasConstructionEdges())
317         {
318                 /** @todo */
319         }
320         else
321         {
322                 /** @todo */
323         }
324
325         if(myElementIDFactory->BindID(ID, volume))
326         {
327                 node1->AddInverseElement(volume);
328                 node2->AddInverseElement(volume);
329         node3->AddInverseElement(volume);
330                 node4->AddInverseElement(volume);
331                 node5->AddInverseElement(volume);
332                 return volume;
333         }       
334         else
335         {
336                 RemoveVolume(volume);
337                 return NULL;
338         }
339 }
340
341 ///////////////////////////////////////////////////////////////////////////////
342 /// Add a prism. Nodes 1,2,3 is a triangle and 1,2,5,4 a quadrangle.
343 ///////////////////////////////////////////////////////////////////////////////
344 SMDS_MeshVolume* SMDS_Mesh::AddVolume(int idnode1, int idnode2, int idnode3,
345         int idnode4, int idnode5, int idnode6)
346 {
347         int ID = myElementIDFactory->GetFreeID();
348         SMDS_MeshVolume * v=
349                 AddVolumeWithID(idnode1, idnode2, idnode3, idnode4, idnode5, idnode6,
350                 ID);
351         if(v==NULL) myElementIDFactory->ReleaseID(ID);
352 }
353
354 //=======================================================================
355 //function : AddVolume
356 //purpose  : Prism
357 //=======================================================================
358
359 SMDS_MeshVolume* SMDS_Mesh::AddVolumeWithID(int idnode1, int idnode2, int idnode3,
360         int idnode4, int idnode5, int idnode6, int ID)
361 {
362         SMDS_MeshNode * node1 = (SMDS_MeshNode *)myNodeIDFactory->MeshElement(idnode1);
363         SMDS_MeshNode * node2 = (SMDS_MeshNode *)myNodeIDFactory->MeshElement(idnode2);
364         SMDS_MeshNode * node3 = (SMDS_MeshNode *)myNodeIDFactory->MeshElement(idnode3);
365         SMDS_MeshNode * node4 = (SMDS_MeshNode *)myNodeIDFactory->MeshElement(idnode4);
366         SMDS_MeshNode * node5 = (SMDS_MeshNode *)myNodeIDFactory->MeshElement(idnode5);
367         SMDS_MeshNode * node6 = (SMDS_MeshNode *)myNodeIDFactory->MeshElement(idnode6);
368
369         if((node1==NULL)||(node2==NULL)||(node3==NULL)||(node4==NULL)||(node5==NULL)||
370                 (node6==NULL)) return NULL;
371         
372         SMDS_MeshVolume* volume;
373         if(hasConstructionFaces())
374
375         {
376                 SMDS_MeshFace * f1=createTriangle(node1,node2,node3);
377                 SMDS_MeshFace * f2=createTriangle(node4,node5,node6);
378                 SMDS_MeshFace * f3=createQuadrangle(node1,node4,node5,node2);
379                 SMDS_MeshFace * f4=createQuadrangle(node2,node5,node6,node3);
380                 SMDS_MeshFace * f5=createQuadrangle(node3,node6,node4,node1);
381                 
382                 SMDS_MeshVolume* volume=new SMDS_VolumeOfFaces(f1,f2,f3,f4,f5);
383                 myVolumes.insert(volume);
384         }
385         else if(hasConstructionEdges())
386         {
387                 /** @todo */
388         }
389         else
390         {
391                 /** @todo */
392         }
393
394         if(myElementIDFactory->BindID(ID, volume))
395         {
396                 node1->AddInverseElement(volume);
397                 node2->AddInverseElement(volume);
398         node3->AddInverseElement(volume);
399                 node4->AddInverseElement(volume);
400                 node5->AddInverseElement(volume);
401                 node6->AddInverseElement(volume);
402                 return volume;
403         }       
404         else
405         {
406                 RemoveVolume(volume);
407                 return NULL;
408         }
409 }
410
411 //=======================================================================
412 //function : AddVolume
413 //purpose  : Hexahedra
414 //=======================================================================
415
416 SMDS_MeshVolume* SMDS_Mesh::AddVolume(int idnode1, int idnode2, int idnode3,
417         int idnode4, int idnode5, int idnode6, int idnode7, int idnode8)
418 {
419         int ID = myElementIDFactory->GetFreeID();
420         SMDS_MeshVolume * v=
421                 AddVolumeWithID(idnode1, idnode2, idnode3, idnode4, idnode5, idnode6,
422                 idnode7, idnode8, ID);
423         if(v==NULL) myElementIDFactory->ReleaseID(ID);
424 }
425
426 ///////////////////////////////////////////////////////////////////////////////
427 /// Add an hexahedron to the mesh. node 1,2,3,4 and 5,6,7,8 are quadrangle and
428 /// 5,1 and 7,3 are an edges.
429 ///////////////////////////////////////////////////////////////////////////////
430 SMDS_MeshVolume*  SMDS_Mesh::AddVolumeWithID(int idnode1, int idnode2, int idnode3,
431         int idnode4, int idnode5, int idnode6, int idnode7, int idnode8, int ID)
432 {
433         SMDS_MeshNode * node1 = (SMDS_MeshNode *)myNodeIDFactory->MeshElement(idnode1);
434         SMDS_MeshNode * node2 = (SMDS_MeshNode *)myNodeIDFactory->MeshElement(idnode2);
435         SMDS_MeshNode * node3 = (SMDS_MeshNode *)myNodeIDFactory->MeshElement(idnode3);
436         SMDS_MeshNode * node4 = (SMDS_MeshNode *)myNodeIDFactory->MeshElement(idnode4);
437         SMDS_MeshNode * node5 = (SMDS_MeshNode *)myNodeIDFactory->MeshElement(idnode5);
438         SMDS_MeshNode * node6 = (SMDS_MeshNode *)myNodeIDFactory->MeshElement(idnode6);
439         SMDS_MeshNode * node7 = (SMDS_MeshNode *)myNodeIDFactory->MeshElement(idnode7);
440         SMDS_MeshNode * node8 = (SMDS_MeshNode *)myNodeIDFactory->MeshElement(idnode8);
441
442         if((node1==NULL)||(node2==NULL)||(node3==NULL)||(node4==NULL)||(node5==NULL)||
443                 (node6==NULL)||(node7==NULL)||(node8==NULL)) return NULL;
444         
445         SMDS_MeshVolume* volume;
446         if(hasConstructionFaces())
447         {
448                 SMDS_MeshFace * f1=FindFaceOrCreate(node1,node2,node3,node4);
449                 SMDS_MeshFace * f2=FindFaceOrCreate(node5,node6,node7,node8);
450                 SMDS_MeshFace * f3=FindFaceOrCreate(node1,node4,node8,node5);
451                 SMDS_MeshFace * f4=FindFaceOrCreate(node1,node2,node6,node5);
452                 SMDS_MeshFace * f5=FindFaceOrCreate(node2,node3,node7,node6);
453                 SMDS_MeshFace * f6=FindFaceOrCreate(node3,node4,node8,node7);
454                 volume=new SMDS_VolumeOfFaces(f1,f2,f3,f4,f5,f6);
455                 myVolumes.insert(volume);
456         }
457         else if(hasConstructionEdges())
458         {
459                 MESSAGE("Error : Not Implemented");
460         }
461         else
462         {
463                 volume=new SMDS_VolumeOfNodes(node1,node2,node3,node4,node5,node6,node7,node8);
464                 myVolumes.insert(volume);
465         }
466
467         if(myElementIDFactory->BindID(ID, volume))
468         {
469                 //MESSAGE("SMDS_Mesh::AddVolumeWithID: update inverse elements");
470                 node1->AddInverseElement(volume);
471                 node2->AddInverseElement(volume);
472         node3->AddInverseElement(volume);
473                 node4->AddInverseElement(volume);
474                 node5->AddInverseElement(volume);
475                 node6->AddInverseElement(volume);
476                 node7->AddInverseElement(volume);
477                 node8->AddInverseElement(volume);
478                 return volume;
479         }       
480         else
481         {
482                 RemoveVolume(volume);
483                 return NULL;
484         }
485 }
486
487 //=======================================================================
488 //function : FindNode
489 //purpose  :
490 //=======================================================================
491
492 const SMDS_MeshNode * SMDS_Mesh::FindNode(int ID) const
493 {
494         return (const SMDS_MeshNode *)myNodeIDFactory->MeshElement(ID);
495 }
496
497 ///////////////////////////////////////////////////////////////////////////////
498 ///Create a triangle and add it to the current mesh. This methode do not bind a
499 ///ID to the create triangle.
500 ///////////////////////////////////////////////////////////////////////////////
501 SMDS_MeshFace * SMDS_Mesh::createTriangle(SMDS_MeshNode * node1,
502         SMDS_MeshNode * node2, SMDS_MeshNode * node3)
503 {
504         if(hasConstructionEdges())
505         {
506                 SMDS_MeshEdge *edge1, *edge2, *edge3;
507                 edge1=FindEdgeOrCreate(node1,node2);
508                 edge2=FindEdgeOrCreate(node2,node3);
509                 edge3=FindEdgeOrCreate(node3,node1);
510
511                 SMDS_MeshFace * face = new SMDS_FaceOfEdges(edge1,edge2,edge3);
512                 myFaces.insert(face);
513                 return face;
514         }
515         else
516         {
517                 SMDS_MeshFace * face = new SMDS_FaceOfNodes(node1,node2,node3);
518                 myFaces.insert(face);
519                 return face;
520         }
521 }
522
523 ///////////////////////////////////////////////////////////////////////////////
524 ///Create a quadrangle and add it to the current mesh. This methode do not bind
525 ///a ID to the create triangle.
526 ///////////////////////////////////////////////////////////////////////////////
527 SMDS_MeshFace * SMDS_Mesh::createQuadrangle(SMDS_MeshNode * node1,
528         SMDS_MeshNode * node2, SMDS_MeshNode * node3, SMDS_MeshNode * node4)
529 {
530         if(hasConstructionEdges())
531         {
532                 SMDS_MeshEdge *edge1, *edge2, *edge3, *edge4;
533                 edge1=FindEdgeOrCreate(node1,node2);
534                 edge2=FindEdgeOrCreate(node2,node3);
535                 edge3=FindEdgeOrCreate(node3,node4);
536                 edge4=FindEdgeOrCreate(node4,node1);
537
538                 SMDS_MeshFace * face = new SMDS_FaceOfEdges(edge1,edge2,edge3,edge4);
539                 myFaces.insert(face);
540                 return face;
541         }
542         else
543         {
544                 SMDS_MeshFace * face = new SMDS_FaceOfNodes(node1,node2,node3,node4);
545                 myFaces.insert(face);
546                 return face;
547         }
548 }
549
550 //=======================================================================
551 //function : RemoveNode
552 //purpose  :
553 //=======================================================================
554
555 void SMDS_Mesh::RemoveNode(int IDnode)
556 {
557         RemoveNode(FindNode(IDnode));
558 }
559
560 //=======================================================================
561 //function : RemoveNode
562 //purpose  :
563 //=======================================================================
564
565 bool SMDS_Mesh::RemoveNode(const SMDS_MeshNode * node)
566 {
567         SMDS_Iterator<const SMDS_MeshElement *> * it=
568                 node->GetInverseElementIterator();
569         while(it->more()) RemoveElement(it->next(),true);
570         myNodeIDFactory->ReleaseID(node->GetID());
571         myNodes.erase(const_cast<SMDS_MeshNode*>(node));
572 }
573
574 //=======================================================================
575 //function : RemoveEdge
576 //purpose  :
577 //=======================================================================
578
579 void SMDS_Mesh::RemoveEdge(int idnode1, int idnode2)
580 {
581         RemoveEdge(FindEdge(idnode1, idnode2));
582 }
583
584 //=======================================================================
585 //function : RemoveEdge
586 //purpose  :
587 //=======================================================================
588
589 void SMDS_Mesh::RemoveEdge(const SMDS_MeshEdge * edge)
590 {
591         /** @todo to be fix */
592         myEdges.erase(const_cast<SMDS_MeshEdge*>(edge));
593         //removeElementDependencies(edge);
594         delete edge;
595 }
596
597 //=======================================================================
598 //function : RemoveFace
599 //purpose  :
600 //=======================================================================
601
602 void SMDS_Mesh::RemoveFace(int idnode1, int idnode2, int idnode3)
603 {
604         RemoveFace(FindFace(idnode1, idnode2, idnode3));
605 }
606
607 //=======================================================================
608 //function : RemoveFace
609 //purpose  :
610 //=======================================================================
611
612 void SMDS_Mesh::RemoveFace(int idnode1, int idnode2, int idnode3, int idnode4)
613 {
614         RemoveFace(FindFace(idnode1, idnode2, idnode3, idnode4));
615 }
616
617 //=======================================================================
618 //function : RemoveFace
619 //purpose  :
620 //=======================================================================
621
622 void SMDS_Mesh::RemoveFace(const SMDS_MeshFace * face)
623 {
624         /** @todo to be fix */
625         myFaces.erase(const_cast<SMDS_MeshFace*>(face));
626         //removeElementDependencies(face);
627         delete face;
628 }
629
630 //=======================================================================
631 //function : RemoveVolume
632 //purpose  :
633 //=======================================================================
634
635 void SMDS_Mesh::RemoveVolume(const SMDS_MeshVolume * volume)
636 {
637         /** @todo to be fix */
638         myVolumes.erase(const_cast<SMDS_MeshVolume*>(volume));
639         //removeElementDependencies(volume);
640         delete volume;
641 }
642 ///////////////////////////////////////////////////////////////////////////////
643 /// Remove no longer used sub element of an element. Unbind the element ID
644 ///////////////////////////////////////////////////////////////////////////////
645 void SMDS_Mesh::removeElementDependencies(SMDS_MeshElement * element)
646 {
647         /** @todo to be fix */
648         myElementIDFactory->ReleaseID(element->GetID());
649         SMDS_Iterator<const SMDS_MeshElement*> * it=element->nodesIterator();
650         while(it->more())
651         {
652                 SMDS_MeshNode * node=static_cast<SMDS_MeshNode*>(
653                         const_cast<SMDS_MeshElement*>(it->next()));
654                 node->RemoveInverseElement(element);
655                 if(node->emptyInverseElements()) RemoveNode(node);
656         }
657 }
658 //=======================================================================
659 //function : RemoveElement
660 //purpose  :
661 //=======================================================================
662
663 void SMDS_Mesh::RemoveElement(int IDelem, const bool removenodes)
664 {
665         RemoveElement(myElementIDFactory->MeshElement(IDelem), removenodes);
666 }
667
668 //=======================================================================
669 //function : RemoveElement
670 //purpose  :
671 //=======================================================================
672
673 void SMDS_Mesh::RemoveElement(const SMDS_MeshElement * elem,
674         const bool removenodes)
675 {
676         /** @todo to be fix */
677         switch(elem->GetType())
678         {
679     case SMDSAbs_Node:
680                 RemoveNode((const SMDS_MeshNode*)elem);
681                 return;
682     case SMDSAbs_Edge:
683                 RemoveEdge((const SMDS_MeshEdge*)elem);
684                 break;
685     case SMDSAbs_Face:
686                 RemoveFace((const SMDS_MeshFace*)elem);
687                 break;
688     case SMDSAbs_Volume:
689                 RemoveVolume((const SMDS_MeshVolume*)elem);
690                 break;
691     default :
692                 MESSAGE("remove function : unknown type");
693                 return;
694         }
695 /*      
696         SMDS_Iterator<const SMDS_MeshNode*> * it=elem->nodesIterator();
697         while(it->more())
698         {
699                 const SMDS_MeshNode * node=it->next();
700                 
701         }*/
702 }
703
704 //=======================================================================
705 //function : RemoveFromParent
706 //purpose  :
707 //=======================================================================
708
709 bool SMDS_Mesh::RemoveFromParent()
710 {
711         if (myParent==NULL) return false;
712         else return (myParent->RemoveSubMesh(this));
713 }
714
715 //=======================================================================
716 //function : RemoveSubMesh
717 //purpose  :
718 //=======================================================================
719
720 bool SMDS_Mesh::RemoveSubMesh(const SMDS_Mesh * aMesh)
721 {
722         bool found = false;
723
724         list<SMDS_Mesh *>::iterator itmsh=myChildren.begin();
725         for (; itmsh!=myChildren.end() && !found; itmsh++)
726         {
727                 SMDS_Mesh * submesh = *itmsh;
728                 if (submesh == aMesh)
729                 {
730                         found = true;
731                         myChildren.erase(itmsh);
732                 }
733         }
734
735         return found;
736 }
737
738
739 //=======================================================================
740 //function : FindEdge
741 //purpose  :
742 //=======================================================================
743
744 const SMDS_MeshEdge* SMDS_Mesh::FindEdge(int idnode1, int idnode2) const
745 {
746         const SMDS_MeshNode * node1=FindNode(idnode1);
747         const SMDS_MeshNode * node2=FindNode(idnode2);
748         if((node1==NULL)||(node2==NULL)) return NULL;
749         return FindEdge(node1,node2);
750 }
751
752 ///////////////////////////////////////////////////////////////////////////////
753 ///
754 ///////////////////////////////////////////////////////////////////////////////
755 //#include "Profiler.h"
756 const SMDS_MeshEdge* SMDS_Mesh::FindEdge(const SMDS_MeshNode * node1,
757         const SMDS_MeshNode * node2) const
758 {
759         const SMDS_MeshEdge * toReturn=NULL;
760         //PROFILER_Init();
761         //PROFILER_Set();
762         SMDS_Iterator<const SMDS_MeshElement *>*  it1=node1->edgesIterator();
763         //PROFILER_Get(0);
764         //PROFILER_Set();
765         while(it1->more())
766         {
767                 const SMDS_MeshEdge * e=static_cast<const SMDS_MeshEdge *>
768                         (it1->next());
769                 SMDS_Iterator<const SMDS_MeshElement *>* it2=e->nodesIterator();
770                 while(it2->more())
771                 {
772                         if(it2->next()->GetID()==node2->GetID())
773                         {
774                                 toReturn=e;
775                                 break;
776                         }
777                 }
778                 delete it2;
779         }
780         //PROFILER_Get(1);
781         delete it1;
782         return toReturn;
783 }
784
785
786 SMDS_MeshEdge* SMDS_Mesh::FindEdgeOrCreate(const SMDS_MeshNode * node1,
787         const SMDS_MeshNode * node2) 
788 {
789         SMDS_MeshEdge * toReturn=NULL;
790         toReturn=const_cast<SMDS_MeshEdge*>(FindEdge(node1,node2));
791         if(toReturn==NULL)      
792         {
793                 toReturn=new SMDS_MeshEdge(const_cast<SMDS_MeshNode*>(node1),
794                         const_cast<SMDS_MeshNode*>(node2));
795                 myEdges.insert(toReturn);
796         } 
797         return toReturn;
798 }
799
800 //=======================================================================
801 //function : FindFace
802 //purpose  :
803 //=======================================================================
804
805 const SMDS_MeshFace* SMDS_Mesh::FindFace(int idnode1, int idnode2,
806         int idnode3) const
807 {
808         const SMDS_MeshNode * node1=FindNode(idnode1);
809         const SMDS_MeshNode * node2=FindNode(idnode2);
810         const SMDS_MeshNode * node3=FindNode(idnode3);
811         const SMDS_MeshFace * face;
812         const SMDS_MeshElement * node;
813         bool node2found, node3found;
814         if((node1==NULL)||(node2==NULL)||(node3==NULL)) return NULL;
815
816         SMDS_Iterator<const SMDS_MeshElement *>*  it1=node1->facesIterator();
817         while(it1->more())
818         {
819                 face=static_cast<const SMDS_MeshFace*>(it1->next());
820                 if(face->NbNodes()!=3) continue;
821                 SMDS_Iterator<const SMDS_MeshElement *>* it2=face->nodesIterator();
822                 node2found=false;
823                 node3found=false;
824                 while(it2->more())
825                 {
826                         node=it2->next();
827                         if(node->GetID()==idnode2) node2found=true;
828                         if(node->GetID()==idnode3) node3found=true;
829                 }
830                 delete it2;
831                 if(node2found&&node3found)
832                 {
833                         delete it1;
834                         return face;
835                 }
836         }
837         delete it1;
838         return NULL;
839 }
840
841 //=======================================================================
842 //function : FindFace
843 //purpose  :
844 //=======================================================================
845
846 const SMDS_MeshFace* SMDS_Mesh::FindFace(int idnode1, int idnode2, int idnode3,
847         int idnode4) const
848 {
849         const SMDS_MeshNode * node1=FindNode(idnode1);
850         const SMDS_MeshNode * node2=FindNode(idnode2);
851         const SMDS_MeshNode * node3=FindNode(idnode3);
852         const SMDS_MeshNode * node4=FindNode(idnode4);
853         if((node1==NULL)||(node2==NULL)||(node3==NULL)||(node4==NULL)) return NULL;
854         return FindFace(node1, node2, node3, node4);
855 }
856
857 const SMDS_MeshFace* SMDS_Mesh::FindFace(
858                 const SMDS_MeshNode *node1,
859                 const SMDS_MeshNode *node2,
860                 const SMDS_MeshNode *node3,
861                 const SMDS_MeshNode *node4) const
862 {
863         const SMDS_MeshFace * face;
864         const SMDS_MeshElement * node;
865         bool node2found, node3found, node4found;
866         SMDS_Iterator<const SMDS_MeshElement *>*  it1=node1->facesIterator();
867         while(it1->more())
868         {
869                 face=static_cast<const SMDS_MeshFace *>(it1->next());
870                 if(face->NbNodes()!=4) continue;
871                 SMDS_Iterator<const SMDS_MeshElement *>* it2=face->nodesIterator();
872                 node2found=false;
873                 node3found=false;
874                 node4found=false;
875                 while(it2->more())
876                 {
877                         node=it2->next();
878                         if(node->GetID()==node2->GetID()) node2found=true;
879                         if(node->GetID()==node3->GetID()) node3found=true;
880                         if(node->GetID()==node4->GetID()) node4found=true;
881                 }
882                 delete it2;
883                 if(node2found&&node3found&&node4found)
884                 {
885                         delete it1;
886                         return face;
887                 }
888         }
889         delete it1;
890         return NULL;
891 }
892
893 SMDS_MeshFace* SMDS_Mesh::FindFaceOrCreate(
894                 const SMDS_MeshNode *node1,
895                 const SMDS_MeshNode *node2,
896                 const SMDS_MeshNode *node3,
897                 const SMDS_MeshNode *node4)
898 {
899         SMDS_MeshFace * toReturn=NULL;
900         toReturn=const_cast<SMDS_MeshFace*>(FindFace(node1,node2,node3,node4));
901         if(toReturn==NULL)      
902         {
903                 toReturn=createQuadrangle(
904                         const_cast<SMDS_MeshNode *>(node1),
905                         const_cast<SMDS_MeshNode *>(node2),
906                         const_cast<SMDS_MeshNode *>(node3),
907                         const_cast<SMDS_MeshNode *>(node4)
908                 );
909         } 
910         return toReturn;
911 }
912
913 //=======================================================================
914 //function : FindElement
915 //purpose  :
916 //=======================================================================
917
918 const SMDS_MeshElement* SMDS_Mesh::FindElement(int IDelem) const
919 {
920         return myElementIDFactory->MeshElement(IDelem);
921 }
922
923 //=======================================================================
924 //function : DumpNodes
925 //purpose  : 
926 //=======================================================================
927
928 void SMDS_Mesh::DumpNodes() const
929 {
930         MESSAGE("dump nodes of mesh : ");
931         SMDS_Iterator<const SMDS_MeshNode *> * itnode=nodesIterator();
932         while(itnode->more()) MESSAGE(itnode->next());
933         delete itnode;
934 }
935
936 //=======================================================================
937 //function : DumpEdges
938 //purpose  : 
939 //=======================================================================
940
941 void SMDS_Mesh::DumpEdges() const
942 {
943         MESSAGE("dump edges of mesh : ");
944         SMDS_Iterator<const SMDS_MeshEdge *> * itedge=edgesIterator();
945         while(itedge->more()) MESSAGE(itedge->next());
946         delete itedge;
947 }
948
949 //=======================================================================
950 //function : DumpFaces
951 //purpose  : 
952 //=======================================================================
953
954 void SMDS_Mesh::DumpFaces() const
955 {
956         MESSAGE("dump faces of mesh : ");
957         SMDS_Iterator<const SMDS_MeshFace *> * itface=facesIterator();
958         while(itface->more()) MESSAGE(itface->next());
959         delete itface;
960 }
961
962 //=======================================================================
963 //function : DumpVolumes
964 //purpose  : 
965 //=======================================================================
966
967 void SMDS_Mesh::DumpVolumes() const
968 {
969         MESSAGE("dump volumes of mesh : ");
970         SMDS_Iterator<const SMDS_MeshVolume *> * itvol=volumesIterator();
971         while(itvol->more()) MESSAGE(itvol->next());
972         delete itvol;
973 }
974
975 //=======================================================================
976 //function : DebugStats
977 //purpose  : 
978 //=======================================================================
979
980 void SMDS_Mesh::DebugStats() const
981 {
982         MESSAGE("Debug stats of mesh : ");
983
984         MESSAGE("===== NODES ====="<<NbNodes());
985         MESSAGE("===== EDGES ====="<<NbEdges());
986         MESSAGE("===== FACES ====="<<NbFaces());
987         MESSAGE("===== VOLUMES ====="<<NbVolumes());
988
989         MESSAGE("End Debug stats of mesh ");
990
991         //#ifdef DEB
992         
993         SMDS_Iterator<const SMDS_MeshNode *> * itnode=nodesIterator();
994         int sizeofnodes = 0;
995         int sizeoffaces = 0;
996
997         while(itnode->more())
998         {
999                 const SMDS_MeshNode *node = itnode->next();
1000
1001                 sizeofnodes += sizeof(*node);
1002                 
1003                 SMDS_Iterator<const SMDS_MeshElement *> * it=
1004                         node->GetInverseElementIterator();
1005                 while(it->more())
1006                 {
1007                         const SMDS_MeshElement *me = it->next();
1008                         sizeofnodes += sizeof(me);
1009                 }
1010                 delete it;
1011
1012         }
1013         delete itnode;
1014         SMDS_Iterator<const SMDS_MeshFace*>* itface=facesIterator();
1015         
1016         while(itface->more())
1017         {
1018                 const SMDS_MeshElement *face = itface->next();          
1019                 sizeoffaces += sizeof(*face);
1020
1021         }
1022         MESSAGE("total size of node elements = " << sizeofnodes);;
1023         MESSAGE("total size of face elements = " << sizeoffaces);;
1024
1025         //#endif
1026
1027 }
1028
1029 int SMDS_Mesh::NbNodes() const
1030 {
1031         myNodes.size();
1032 }
1033
1034 int SMDS_Mesh::NbEdges() const
1035 {
1036         return myEdges.size();
1037 }
1038
1039 int SMDS_Mesh::NbFaces() const
1040 {
1041         return myFaces.size();
1042 }
1043
1044 int SMDS_Mesh::NbVolumes() const
1045 {
1046         return myVolumes.size();
1047 }
1048
1049 int SMDS_Mesh::NbSubMesh() const
1050 {
1051         return myChildren.size();
1052 }
1053
1054 SMDS_Mesh::~SMDS_Mesh()
1055 {
1056         if(myParent==NULL)
1057         {
1058                 delete myNodeIDFactory;
1059                 delete myElementIDFactory;
1060         }
1061
1062         list<SMDS_Mesh*>::iterator itc=myChildren.begin();
1063         while(itc!=myChildren.end())
1064         {
1065                 delete *itc;
1066                 itc++;
1067         }
1068         
1069         SMDS_Iterator<const SMDS_MeshNode*> * itn=nodesIterator();
1070         while(itn->more())
1071         {
1072                 delete itn->next();
1073         }
1074         delete itn;
1075
1076         set<SMDS_MeshEdge*>::iterator ite=myEdges.begin();
1077         while(ite!=myEdges.end())
1078         {
1079                 delete *ite;
1080                 ite++;
1081         }
1082
1083         set<SMDS_MeshFace*>::iterator itf=myFaces.begin();
1084         while(itf!=myFaces.end())
1085         {
1086                 delete *itf;
1087                 itf++;
1088         }
1089
1090         set<SMDS_MeshVolume*>::iterator itv=myVolumes.begin();
1091         while(itv!=myVolumes.end())
1092         {
1093                 delete *itv;
1094                 itv++;
1095         }
1096
1097 }
1098
1099 bool SMDS_Mesh::hasConstructionEdges()
1100 {
1101         return myHasConstructionEdges;
1102 }
1103
1104 bool SMDS_Mesh::hasConstructionFaces()
1105 {
1106         return myHasConstructionFaces;
1107 }
1108
1109 bool SMDS_Mesh::hasInverseElements()
1110 {
1111         return myHasInverseElements;
1112 }
1113
1114 void SMDS_Mesh::setConstructionEdges(bool b)
1115 {
1116         myHasConstructionEdges=b;
1117 }
1118
1119 void SMDS_Mesh::setConstructionFaces(bool b)
1120 {
1121          myHasConstructionFaces=b;
1122 }
1123
1124 void SMDS_Mesh::setInverseElements(bool b)
1125 {
1126         if(!b) MESSAGE("Error : inverseElement=false not implemented");
1127         myHasInverseElements=b;
1128 }
1129
1130 ///////////////////////////////////////////////////////////////////////////////
1131 ///Return an iterator on nodes of the current mesh. Once used this iterator
1132 ///must be free by the caller
1133 ///////////////////////////////////////////////////////////////////////////////
1134 SMDS_Iterator<const SMDS_MeshNode *> * SMDS_Mesh::nodesIterator() const
1135 {
1136         class MyIterator:public SMDS_Iterator<const SMDS_MeshNode*>
1137         {
1138                 const SetOfNodes& mySet;
1139                 SetOfNodes::iterator myIterator;
1140           public:
1141                 MyIterator(const SetOfNodes& s):mySet(s)
1142                 {
1143                         myIterator=mySet.begin();
1144                 }
1145
1146                 bool more()
1147                 {
1148                         myIterator!=mySet.end();
1149                 }
1150
1151                 const SMDS_MeshNode* next()
1152                 {
1153                         const SMDS_MeshNode* current=*myIterator;
1154                         myIterator++;
1155                         return current; 
1156                 }       
1157         };
1158         return new MyIterator(myNodes);
1159 }
1160
1161 ///////////////////////////////////////////////////////////////////////////////
1162 ///Return an iterator on volumes of the current mesh. Once used this iterator
1163 ///must be free by the caller
1164 ///////////////////////////////////////////////////////////////////////////////
1165 SMDS_Iterator<const SMDS_MeshEdge *> * SMDS_Mesh::edgesIterator() const
1166 {
1167         class MyIterator:public SMDS_Iterator<const SMDS_MeshEdge*>
1168         {
1169                 const SetOfEdges& mySet;
1170                 const SMDS_MeshEdge * myEdge;
1171                 SetOfEdges::iterator myIterator;
1172           public:
1173                 MyIterator(const SetOfEdges& s):mySet(s)
1174                 {
1175                         myIterator=mySet.begin();
1176                 }
1177
1178                 bool more()
1179                 {
1180                         while((myIterator!=mySet.end()))
1181                         {
1182                                 if((*myIterator)->GetID()!=-1)
1183                                         return true;
1184                                 myIterator++;
1185                         }
1186                         return false;
1187                 }
1188
1189                 const SMDS_MeshEdge* next()
1190                 {
1191                         const SMDS_MeshEdge* current=*myIterator;
1192                         myIterator++;
1193                         return current; 
1194                 }       
1195         };
1196         return new MyIterator(myEdges);
1197 }
1198
1199 ///////////////////////////////////////////////////////////////////////////////
1200 ///Return an iterator on faces of the current mesh. Once used this iterator
1201 ///must be free by the caller
1202 ///////////////////////////////////////////////////////////////////////////////
1203 SMDS_Iterator<const SMDS_MeshFace *> * SMDS_Mesh::facesIterator() const
1204 {
1205         class MyIterator:public SMDS_Iterator<const SMDS_MeshFace*>
1206         {
1207                 const SetOfFaces& mySet;
1208                 set<SMDS_MeshFace*>::iterator myIterator;
1209           public:
1210                 MyIterator(const SetOfFaces& s):mySet(s)
1211                 {
1212                         myIterator=mySet.begin();
1213                 }
1214
1215                 bool more()
1216                 {
1217                         while((myIterator!=mySet.end()))
1218                         {
1219                                 if((*myIterator)->GetID()!=-1)
1220                                         return true;
1221                                 myIterator++;
1222                         }
1223                         return false;
1224                 }
1225
1226                 const SMDS_MeshFace* next()
1227                 {
1228                         const SMDS_MeshFace* current=*myIterator;
1229                         myIterator++;
1230                         return current; 
1231                 }       
1232         };
1233         return new MyIterator(myFaces);
1234 }
1235
1236 ///////////////////////////////////////////////////////////////////////////////
1237 ///Return an iterator on volumes of the current mesh. Once used this iterator
1238 ///must be free by the caller
1239 ///////////////////////////////////////////////////////////////////////////////
1240 SMDS_Iterator<const SMDS_MeshVolume *> * SMDS_Mesh::volumesIterator() const
1241 {
1242         class MyIterator:public SMDS_Iterator<const SMDS_MeshVolume*>
1243         {
1244                 const SetOfVolumes& mySet;
1245                 SetOfVolumes::iterator myIterator;
1246           public:
1247                 MyIterator(const SetOfVolumes& s):mySet(s)
1248                 {
1249                         myIterator=mySet.begin();
1250                 }
1251
1252                 bool more()
1253                 {
1254                         myIterator!=mySet.end();
1255                 }
1256
1257                 const SMDS_MeshVolume* next()
1258                 {
1259                         const SMDS_MeshVolume* current=*myIterator;
1260                         myIterator++;
1261                         return current; 
1262                 }       
1263         };
1264         return new MyIterator(myVolumes);
1265 }
1266