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