Salome HOME
Cange std::hash_map on NCollection data map
[modules/smesh.git] / src / SMESHDS / SMESHDS_Mesh.cxx
1 //  SMESH SMESHDS : management of mesh data and SMESH document
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 //
23 //
24 //  File   : SMESH_Mesh.cxx
25 //  Author : Yves FRICAUD, OCC
26 //  Module : SMESH
27 //  $Header: 
28
29 #include "SMESHDS_Mesh.hxx"
30
31 #include "SMESHDS_Group.hxx"
32 #include "SMDS_VertexPosition.hxx"
33 #include "SMDS_EdgePosition.hxx"
34 #include "SMDS_FacePosition.hxx"
35 #include "SMESHDS_GroupOnGeom.hxx"
36 #include <TopExp_Explorer.hxx>
37 #include <TopExp.hxx>
38 #include <TopoDS_Iterator.hxx>
39
40 #include "utilities.h"
41
42 using namespace std;
43
44 /*Standard_Boolean IsEqual( const TopoDS_Shape& S1, const TopoDS_Shape& S2 ) 
45   {
46     return S1.IsSame( S2 );
47   }*/
48
49 //=======================================================================
50 //function : Create
51 //purpose  : 
52 //=======================================================================
53 SMESHDS_Mesh::SMESHDS_Mesh(int MeshID):myMeshID(MeshID)
54 {
55         myScript = new SMESHDS_Script();
56 }
57
58 //=======================================================================
59 //function : ShapeToMesh
60 //purpose  : 
61 //=======================================================================
62 void SMESHDS_Mesh::ShapeToMesh(const TopoDS_Shape & S)
63 {
64   if ( !myShape.IsNull() && S.IsNull() )
65   {
66     // removal of a shape to mesh, delete ...
67     // - hypotheses
68     myShapeToHypothesis.Clear();
69     // - shape indices in SMDS_Position of nodes
70     map<int,SMESHDS_SubMesh*>::iterator i_sub = myShapeIndexToSubMesh.begin();
71     for ( ; i_sub != myShapeIndexToSubMesh.end(); i_sub++ ) {
72       if ( !i_sub->second->IsComplexSubmesh() ) {
73         SMDS_NodeIteratorPtr nIt = i_sub->second->GetNodes();
74         while ( nIt->more() )
75           nIt->next()->GetPosition()->SetShapeId( 0 );
76       }
77     }
78     // - sub-meshes
79     myIndexToShape.Clear();
80     myShapeIndexToSubMesh.clear();
81     // - groups on geometry
82     set<SMESHDS_GroupBase*>::iterator gr = myGroups.begin();
83     while ( gr != myGroups.end() ) {
84       if ( dynamic_cast<SMESHDS_GroupOnGeom*>( *gr ))
85         myGroups.erase( gr++ );
86       else
87         gr++;
88     }
89   }
90   else {
91     myShape = S;
92     if ( !S.IsNull() )
93       TopExp::MapShapes(myShape, myIndexToShape);
94   }
95 }
96
97 //=======================================================================
98 //function : AddHypothesis
99 //purpose  : 
100 //=======================================================================
101
102 bool SMESHDS_Mesh::AddHypothesis(const TopoDS_Shape & SS,
103         const SMESHDS_Hypothesis * H)
104 {
105         //list<const SMESHDS_Hypothesis *>& alist=myShapeToHypothesis[SS];
106   
107   if ( !myShapeToHypothesis.IsBound( SS ) )
108     myShapeToHypothesis.Bind( SS, list<const SMESHDS_Hypothesis *>() );
109
110   list<const SMESHDS_Hypothesis *>& alist = myShapeToHypothesis.ChangeFind( SS );
111
112     
113
114         //Check if the Hypothesis is still present
115         list<const SMESHDS_Hypothesis*>::iterator ith=alist.begin();
116
117         for (; ith!=alist.end(); ith++)
118                 if (H == *ith) return false;
119
120         alist.push_back(H);
121         return true;
122 }
123
124 //=======================================================================
125 //function : RemoveHypothesis
126 //purpose  : 
127 //=======================================================================
128
129 bool SMESHDS_Mesh::RemoveHypothesis(const TopoDS_Shape & S,
130         const SMESHDS_Hypothesis * H)
131 {
132         /*ShapeToHypothesis::iterator its=myShapeToHypothesis.find(S);
133         if(its!=myShapeToHypothesis.end())
134         {
135                 list<const SMESHDS_Hypothesis*>::iterator ith=(*its).second.begin();
136
137                 for (; ith!=(*its).second.end(); ith++)
138                         if (H == *ith)
139                         {
140                                 (*its).second.erase(ith);
141                                 return true;
142                         }
143         }*/
144   if ( myShapeToHypothesis.IsBound( S ) )
145   {
146     list<const SMESHDS_Hypothesis *>& alist = myShapeToHypothesis.ChangeFind( S );
147     list<const SMESHDS_Hypothesis*>::iterator ith = alist.begin();
148
149                 for (; ith != alist.end(); ith++)
150                         if (H == *ith)
151                         {
152                                 alist.erase(ith);
153                                 return true;
154                         }
155   }
156         return false;
157 }
158
159 //=======================================================================
160 //function : AddNode
161 //purpose  : 
162 //=======================================================================
163 SMDS_MeshNode* SMESHDS_Mesh::AddNode(double x, double y, double z){
164   SMDS_MeshNode* node = SMDS_Mesh::AddNode(x, y, z);
165   if(node!=NULL) myScript->AddNode(node->GetID(), x, y, z);
166   return node;
167 }
168
169 SMDS_MeshNode* SMESHDS_Mesh::AddNodeWithID(double x, double y, double z, int ID){
170   SMDS_MeshNode* node = SMDS_Mesh::AddNodeWithID(x,y,z,ID);
171   if(node!=NULL) myScript->AddNode(node->GetID(), x, y, z);
172   return node;
173 }
174
175 //=======================================================================
176 //function : MoveNode
177 //purpose  : 
178 //=======================================================================
179 void SMESHDS_Mesh::MoveNode(const SMDS_MeshNode *n, double x, double y, double z)
180 {
181   SMDS_MeshNode * node=const_cast<SMDS_MeshNode*>(n);
182   node->setXYZ(x,y,z);
183   myScript->MoveNode(n->GetID(), x, y, z);
184 }
185
186 //=======================================================================
187 //function : ChangeElementNodes
188 //purpose  : 
189 //=======================================================================
190
191 bool SMESHDS_Mesh::ChangeElementNodes(const SMDS_MeshElement * elem,
192                                       const SMDS_MeshNode    * nodes[],
193                                       const int                nbnodes)
194 {
195   if ( ! SMDS_Mesh::ChangeElementNodes( elem, nodes, nbnodes ))
196     return false;
197
198   vector<int> IDs( nbnodes );
199   for ( int i = 0; i < nbnodes; i++ )
200     IDs [ i ] = nodes[ i ]->GetID();
201   myScript->ChangeElementNodes( elem->GetID(), &IDs[0], nbnodes);
202
203   return true;
204 }
205
206 //=======================================================================
207 //function : ChangePolygonNodes
208 //purpose  : 
209 //=======================================================================
210 bool SMESHDS_Mesh::ChangePolygonNodes
211                    (const SMDS_MeshElement *     elem,
212                     vector<const SMDS_MeshNode*> nodes)
213 {
214   ASSERT(nodes.size() > 3);
215
216   return ChangeElementNodes(elem, &nodes[0], nodes.size());
217 }
218
219 //=======================================================================
220 //function : ChangePolyhedronNodes
221 //purpose  : 
222 //=======================================================================
223 bool SMESHDS_Mesh::ChangePolyhedronNodes
224                    (const SMDS_MeshElement * elem,
225                     std::vector<const SMDS_MeshNode*> nodes,
226                     std::vector<int>                  quantities)
227 {
228   ASSERT(nodes.size() > 3);
229
230   if (!SMDS_Mesh::ChangePolyhedronNodes(elem, nodes, quantities))
231     return false;
232
233   int i, len = nodes.size();
234   std::vector<int> nodes_ids (len);
235   for (i = 0; i < len; i++) {
236     nodes_ids[i] = nodes[i]->GetID();
237   }
238   myScript->ChangePolyhedronNodes(elem->GetID(), nodes_ids, quantities);
239
240   return true;
241 }
242
243 //=======================================================================
244 //function : Renumber
245 //purpose  : 
246 //=======================================================================
247
248 void SMESHDS_Mesh::Renumber (const bool isNodes, const int startID, const int deltaID)
249 {
250   SMDS_Mesh::Renumber( isNodes, startID, deltaID );
251   myScript->Renumber( isNodes, startID, deltaID );
252 }
253
254 //=======================================================================
255 //function :AddEdgeWithID
256 //purpose  : 
257 //=======================================================================
258 SMDS_MeshEdge* SMESHDS_Mesh::AddEdgeWithID(int n1, int n2, int ID)
259 {
260   SMDS_MeshEdge* anElem = SMDS_Mesh::AddEdgeWithID(n1,n2,ID);
261   if(anElem) myScript->AddEdge(ID,n1,n2);
262   return anElem;
263 }
264
265 SMDS_MeshEdge* SMESHDS_Mesh::AddEdgeWithID(const SMDS_MeshNode * n1,
266                                            const SMDS_MeshNode * n2, 
267                                            int ID)
268 {
269   return AddEdgeWithID(n1->GetID(),
270                        n2->GetID(),
271                        ID);
272 }
273
274 SMDS_MeshEdge* SMESHDS_Mesh::AddEdge(const SMDS_MeshNode * n1,
275                                      const SMDS_MeshNode * n2)
276 {
277   SMDS_MeshEdge* anElem = SMDS_Mesh::AddEdge(n1,n2);
278   if(anElem) myScript->AddEdge(anElem->GetID(), 
279                                n1->GetID(), 
280                                n2->GetID());
281   return anElem;
282 }
283
284 //=======================================================================
285 //function :AddFace
286 //purpose  : 
287 //=======================================================================
288 SMDS_MeshFace* SMESHDS_Mesh::AddFaceWithID(int n1, int n2, int n3, int ID)
289 {
290   SMDS_MeshFace *anElem = SMDS_Mesh::AddFaceWithID(n1, n2, n3, ID);
291   if(anElem) myScript->AddFace(ID,n1,n2,n3);
292   return anElem;
293 }
294
295 SMDS_MeshFace* SMESHDS_Mesh::AddFaceWithID(const SMDS_MeshNode * n1,
296                                            const SMDS_MeshNode * n2,
297                                            const SMDS_MeshNode * n3, 
298                                            int ID)
299 {
300   return AddFaceWithID(n1->GetID(),
301                        n2->GetID(),
302                        n3->GetID(),
303                        ID);
304 }
305
306 SMDS_MeshFace* SMESHDS_Mesh::AddFace( const SMDS_MeshNode * n1,
307                                       const SMDS_MeshNode * n2,
308                                       const SMDS_MeshNode * n3)
309 {
310   SMDS_MeshFace *anElem = SMDS_Mesh::AddFace(n1, n2, n3);
311   if(anElem) myScript->AddFace(anElem->GetID(), 
312                                n1->GetID(), 
313                                n2->GetID(),
314                                n3->GetID());
315   return anElem;
316 }
317
318 //=======================================================================
319 //function :AddFace
320 //purpose  : 
321 //=======================================================================
322 SMDS_MeshFace* SMESHDS_Mesh::AddFaceWithID(int n1, int n2, int n3, int n4, int ID)
323 {
324   SMDS_MeshFace *anElem = SMDS_Mesh::AddFaceWithID(n1, n2, n3, n4, ID);
325   if(anElem) myScript->AddFace(ID, n1, n2, n3, n4);
326   return anElem;
327 }
328
329 SMDS_MeshFace* SMESHDS_Mesh::AddFaceWithID(const SMDS_MeshNode * n1,
330                                            const SMDS_MeshNode * n2,
331                                            const SMDS_MeshNode * n3,
332                                            const SMDS_MeshNode * n4, 
333                                            int ID)
334 {
335   return AddFaceWithID(n1->GetID(),
336                        n2->GetID(),
337                        n3->GetID(),
338                        n4->GetID(),
339                        ID);
340 }
341
342 SMDS_MeshFace* SMESHDS_Mesh::AddFace(const SMDS_MeshNode * n1,
343                                      const SMDS_MeshNode * n2,
344                                      const SMDS_MeshNode * n3,
345                                      const SMDS_MeshNode * n4)
346 {
347   SMDS_MeshFace *anElem = SMDS_Mesh::AddFace(n1, n2, n3, n4);
348   if(anElem) myScript->AddFace(anElem->GetID(), 
349                                n1->GetID(), 
350                                n2->GetID(), 
351                                n3->GetID(),
352                                n4->GetID());
353   return anElem;
354 }
355
356 //=======================================================================
357 //function :AddVolume
358 //purpose  : 
359 //=======================================================================
360 SMDS_MeshVolume* SMESHDS_Mesh::AddVolumeWithID(int n1, int n2, int n3, int n4, int ID)
361 {
362   SMDS_MeshVolume *anElem = SMDS_Mesh::AddVolumeWithID(n1, n2, n3, n4, ID);
363   if(anElem) myScript->AddVolume(ID, n1, n2, n3, n4);
364   return anElem;
365 }
366
367 SMDS_MeshVolume* SMESHDS_Mesh::AddVolumeWithID(const SMDS_MeshNode * n1,
368                                                const SMDS_MeshNode * n2,
369                                                const SMDS_MeshNode * n3,
370                                                const SMDS_MeshNode * n4, 
371                                                int ID)
372 {
373   return AddVolumeWithID(n1->GetID(), 
374                          n2->GetID(), 
375                          n3->GetID(),
376                          n4->GetID(),
377                          ID);
378 }
379
380 SMDS_MeshVolume* SMESHDS_Mesh::AddVolume(const SMDS_MeshNode * n1,
381                                          const SMDS_MeshNode * n2,
382                                          const SMDS_MeshNode * n3,
383                                          const SMDS_MeshNode * n4)
384 {
385   SMDS_MeshVolume *anElem = SMDS_Mesh::AddVolume(n1, n2, n3, n4);
386   if(anElem) myScript->AddVolume(anElem->GetID(), 
387                                  n1->GetID(), 
388                                  n2->GetID(), 
389                                  n3->GetID(),
390                                  n4->GetID());
391   return anElem;
392 }
393
394 //=======================================================================
395 //function :AddVolume
396 //purpose  : 
397 //=======================================================================
398 SMDS_MeshVolume* SMESHDS_Mesh::AddVolumeWithID(int n1, int n2, int n3, int n4, int n5, int ID)
399 {
400   SMDS_MeshVolume *anElem = SMDS_Mesh::AddVolumeWithID(n1, n2, n3, n4, n5, ID);
401   if(anElem) myScript->AddVolume(ID, n1, n2, n3, n4, n5);
402   return anElem;
403 }
404
405 SMDS_MeshVolume* SMESHDS_Mesh::AddVolumeWithID(const SMDS_MeshNode * n1,
406                                                const SMDS_MeshNode * n2,
407                                                const SMDS_MeshNode * n3,
408                                                const SMDS_MeshNode * n4,
409                                                const SMDS_MeshNode * n5, 
410                                                int ID)
411 {
412   return AddVolumeWithID(n1->GetID(), 
413                          n2->GetID(), 
414                          n3->GetID(),
415                          n4->GetID(), 
416                          n5->GetID(),
417                          ID);
418 }
419
420 SMDS_MeshVolume* SMESHDS_Mesh::AddVolume(const SMDS_MeshNode * n1,
421                                          const SMDS_MeshNode * n2,
422                                          const SMDS_MeshNode * n3,
423                                          const SMDS_MeshNode * n4,
424                                          const SMDS_MeshNode * n5)
425 {
426   SMDS_MeshVolume *anElem = SMDS_Mesh::AddVolume(n1, n2, n3, n4, n5);
427   if(anElem) myScript->AddVolume(anElem->GetID(), 
428                                  n1->GetID(), 
429                                  n2->GetID(), 
430                                  n3->GetID(),
431                                  n4->GetID(), 
432                                  n5->GetID());
433   return anElem;
434 }
435
436 //=======================================================================
437 //function :AddVolume
438 //purpose  : 
439 //=======================================================================
440 SMDS_MeshVolume* SMESHDS_Mesh::AddVolumeWithID(int n1, int n2, int n3, int n4, int n5, int n6, int ID)
441 {
442   SMDS_MeshVolume *anElem= SMDS_Mesh::AddVolumeWithID(n1, n2, n3, n4, n5, n6, ID);
443   if(anElem) myScript->AddVolume(ID, n1, n2, n3, n4, n5, n6);
444   return anElem;
445 }
446
447 SMDS_MeshVolume* SMESHDS_Mesh::AddVolumeWithID(const SMDS_MeshNode * n1,
448                                                const SMDS_MeshNode * n2,
449                                                const SMDS_MeshNode * n3,
450                                                const SMDS_MeshNode * n4,
451                                                const SMDS_MeshNode * n5,
452                                                const SMDS_MeshNode * n6, 
453                                                int ID)
454 {
455   return AddVolumeWithID(n1->GetID(), 
456                          n2->GetID(), 
457                          n3->GetID(),
458                          n4->GetID(), 
459                          n5->GetID(), 
460                          n6->GetID(),
461                          ID);
462 }
463
464 SMDS_MeshVolume* SMESHDS_Mesh::AddVolume(const SMDS_MeshNode * n1,
465                                          const SMDS_MeshNode * n2,
466                                          const SMDS_MeshNode * n3,
467                                          const SMDS_MeshNode * n4,
468                                          const SMDS_MeshNode * n5,
469                                          const SMDS_MeshNode * n6)
470 {
471   SMDS_MeshVolume *anElem = SMDS_Mesh::AddVolume(n1, n2, n3, n4, n5, n6);
472   if(anElem) myScript->AddVolume(anElem->GetID(), 
473                                  n1->GetID(), 
474                                  n2->GetID(), 
475                                  n3->GetID(),
476                                  n4->GetID(), 
477                                  n5->GetID(), 
478                                  n6->GetID());
479   return anElem;
480 }
481
482 //=======================================================================
483 //function :AddVolume
484 //purpose  : 
485 //=======================================================================
486 SMDS_MeshVolume* SMESHDS_Mesh::AddVolumeWithID(int n1, int n2, int n3, int n4, int n5, int n6, int n7, int n8, int ID)
487 {
488   SMDS_MeshVolume *anElem= SMDS_Mesh::AddVolumeWithID(n1, n2, n3, n4, n5, n6, n7, n8, ID);
489   if(anElem) myScript->AddVolume(ID, n1, n2, n3, n4, n5, n6, n7, n8);
490   return anElem;
491 }
492
493 SMDS_MeshVolume* SMESHDS_Mesh::AddVolumeWithID(const SMDS_MeshNode * n1,
494                                                const SMDS_MeshNode * n2,
495                                                const SMDS_MeshNode * n3,
496                                                const SMDS_MeshNode * n4,
497                                                const SMDS_MeshNode * n5,
498                                                const SMDS_MeshNode * n6,
499                                                const SMDS_MeshNode * n7,
500                                                const SMDS_MeshNode * n8, 
501                                                int ID)
502 {
503   return AddVolumeWithID(n1->GetID(), 
504                          n2->GetID(), 
505                          n3->GetID(),
506                          n4->GetID(), 
507                          n5->GetID(), 
508                          n6->GetID(), 
509                          n7->GetID(), 
510                          n8->GetID(),
511                          ID);
512 }
513
514 SMDS_MeshVolume* SMESHDS_Mesh::AddVolume(const SMDS_MeshNode * n1,
515                                          const SMDS_MeshNode * n2,
516                                          const SMDS_MeshNode * n3,
517                                          const SMDS_MeshNode * n4,
518                                          const SMDS_MeshNode * n5,
519                                          const SMDS_MeshNode * n6,
520                                          const SMDS_MeshNode * n7,
521                                          const SMDS_MeshNode * n8)
522 {
523   SMDS_MeshVolume *anElem = SMDS_Mesh::AddVolume(n1, n2, n3, n4, n5, n6, n7, n8);
524   if(anElem) myScript->AddVolume(anElem->GetID(), 
525                                  n1->GetID(), 
526                                  n2->GetID(), 
527                                  n3->GetID(),
528                                  n4->GetID(), 
529                                  n5->GetID(), 
530                                  n6->GetID(), 
531                                  n7->GetID(), 
532                                  n8->GetID());
533   return anElem;
534 }
535
536 //=======================================================================
537 //function : AddPolygonalFace
538 //purpose  : 
539 //=======================================================================
540 SMDS_MeshFace* SMESHDS_Mesh::AddPolygonalFaceWithID (std::vector<int> nodes_ids,
541                                                      const int        ID)
542 {
543   SMDS_MeshFace *anElem = SMDS_Mesh::AddPolygonalFaceWithID(nodes_ids, ID);
544   if (anElem) {
545     myScript->AddPolygonalFace(ID, nodes_ids);
546   }
547   return anElem;
548 }
549
550 SMDS_MeshFace* SMESHDS_Mesh::AddPolygonalFaceWithID
551                              (std::vector<const SMDS_MeshNode*> nodes,
552                               const int                         ID)
553 {
554   SMDS_MeshFace *anElem = SMDS_Mesh::AddPolygonalFaceWithID(nodes, ID);
555   if (anElem) {
556     int i, len = nodes.size();
557     std::vector<int> nodes_ids (len);
558     for (i = 0; i < len; i++) {
559       nodes_ids[i] = nodes[i]->GetID();
560     }
561     myScript->AddPolygonalFace(ID, nodes_ids);
562   }
563   return anElem;
564 }
565
566 SMDS_MeshFace* SMESHDS_Mesh::AddPolygonalFace
567                              (std::vector<const SMDS_MeshNode*> nodes)
568 {
569   SMDS_MeshFace *anElem = SMDS_Mesh::AddPolygonalFace(nodes);
570   if (anElem) {
571     int i, len = nodes.size();
572     std::vector<int> nodes_ids (len);
573     for (i = 0; i < len; i++) {
574       nodes_ids[i] = nodes[i]->GetID();
575     }
576     myScript->AddPolygonalFace(anElem->GetID(), nodes_ids);
577   }
578   return anElem;
579 }
580
581 //=======================================================================
582 //function : AddPolyhedralVolume
583 //purpose  : 
584 //=======================================================================
585 SMDS_MeshVolume* SMESHDS_Mesh::AddPolyhedralVolumeWithID (std::vector<int> nodes_ids,
586                                                           std::vector<int> quantities,
587                                                           const int        ID)
588 {
589   SMDS_MeshVolume *anElem = SMDS_Mesh::AddPolyhedralVolumeWithID(nodes_ids, quantities, ID);
590   if (anElem) {
591     myScript->AddPolyhedralVolume(ID, nodes_ids, quantities);
592   }
593   return anElem;
594 }
595
596 SMDS_MeshVolume* SMESHDS_Mesh::AddPolyhedralVolumeWithID
597                                (std::vector<const SMDS_MeshNode*> nodes,
598                                 std::vector<int>                  quantities,
599                                 const int                         ID)
600 {
601   SMDS_MeshVolume *anElem = SMDS_Mesh::AddPolyhedralVolumeWithID(nodes, quantities, ID);
602   if (anElem) {
603     int i, len = nodes.size();
604     std::vector<int> nodes_ids (len);
605     for (i = 0; i < len; i++) {
606       nodes_ids[i] = nodes[i]->GetID();
607     }
608     myScript->AddPolyhedralVolume(ID, nodes_ids, quantities);
609   }
610   return anElem;
611 }
612
613 SMDS_MeshVolume* SMESHDS_Mesh::AddPolyhedralVolume
614                                (std::vector<const SMDS_MeshNode*> nodes,
615                                 std::vector<int>                  quantities)
616 {
617   SMDS_MeshVolume *anElem = SMDS_Mesh::AddPolyhedralVolume(nodes, quantities);
618   if (anElem) {
619     int i, len = nodes.size();
620     std::vector<int> nodes_ids (len);
621     for (i = 0; i < len; i++) {
622       nodes_ids[i] = nodes[i]->GetID();
623     }
624     myScript->AddPolyhedralVolume(anElem->GetID(), nodes_ids, quantities);
625   }
626   return anElem;
627 }
628
629 //=======================================================================
630 //function : removeFromContainers
631 //purpose  : 
632 //=======================================================================
633
634 static void removeFromContainers (map<int,SMESHDS_SubMesh*> &      theSubMeshes,
635                                   set<SMESHDS_GroupBase*>&             theGroups,
636                                   list<const SMDS_MeshElement *> & theElems,
637                                   const bool                       isNode)
638 {
639   if ( theElems.empty() )
640     return;
641
642   // Rm from group
643   // Element can belong to several groups
644   if ( !theGroups.empty() )
645   {
646     set<SMESHDS_GroupBase*>::iterator GrIt = theGroups.begin();
647     for ( ; GrIt != theGroups.end(); GrIt++ )
648     {
649       SMESHDS_Group* group = dynamic_cast<SMESHDS_Group*>( *GrIt );
650       if ( !group || group->IsEmpty() ) continue;
651
652       list<const SMDS_MeshElement *>::iterator elIt = theElems.begin();
653       for ( ; elIt != theElems.end(); elIt++ )
654       {
655         group->SMDSGroup().Remove( *elIt );
656         if ( group->IsEmpty() ) break;
657       }
658     }
659   }
660
661   // Rm from sub-meshes
662   // Element should belong to only one sub-mesh
663   map<int,SMESHDS_SubMesh*>::iterator SubIt = theSubMeshes.begin();
664   for ( ; SubIt != theSubMeshes.end(); SubIt++ )
665   {
666     int size = isNode ? (*SubIt).second->NbNodes() : (*SubIt).second->NbElements();
667     if ( size == 0 ) continue;
668
669     list<const SMDS_MeshElement *>::iterator elIt = theElems.begin();
670     while ( elIt != theElems.end() )
671     {
672       bool removed = false;
673       if ( isNode )
674         removed = (*SubIt).second->RemoveNode( static_cast<const SMDS_MeshNode*> (*elIt) );
675       else
676         removed = (*SubIt).second->RemoveElement( *elIt );
677
678       if (removed)
679       {
680         elIt = theElems.erase( elIt );
681         if ( theElems.empty() )
682           return; // all elements are found and removed
683       }
684       else
685       {
686         elIt++ ;
687       }
688     }
689   }
690 }
691   
692 //=======================================================================
693 //function : RemoveNode
694 //purpose  : 
695 //=======================================================================
696 void SMESHDS_Mesh::RemoveNode(const SMDS_MeshNode * n)
697 {
698   myScript->RemoveNode(n->GetID());
699   
700   list<const SMDS_MeshElement *> removedElems;
701   list<const SMDS_MeshElement *> removedNodes;
702
703   SMDS_Mesh::RemoveElement( n, removedElems, removedNodes, true );
704
705   removeFromContainers( myShapeIndexToSubMesh, myGroups, removedElems, false );
706   removeFromContainers( myShapeIndexToSubMesh, myGroups, removedNodes, true );
707 }
708
709 //=======================================================================
710 //function : RemoveElement
711 //purpose  : 
712 //========================================================================
713 void SMESHDS_Mesh::RemoveElement(const SMDS_MeshElement * elt)
714 {
715   if (elt->GetType() == SMDSAbs_Node)
716   {
717     RemoveNode( static_cast<const SMDS_MeshNode*>( elt ));
718     return;
719   }
720
721   myScript->RemoveElement(elt->GetID());
722
723   list<const SMDS_MeshElement *> removedElems;
724   list<const SMDS_MeshElement *> removedNodes;
725
726   SMDS_Mesh::RemoveElement(elt, removedElems, removedNodes, false);
727   
728   removeFromContainers( myShapeIndexToSubMesh, myGroups, removedElems, false );
729 }
730
731 //=======================================================================
732 //function : SetNodeOnVolume
733 //purpose  : 
734 //=======================================================================
735 void SMESHDS_Mesh::SetNodeInVolume(SMDS_MeshNode *      aNode,
736                                    const TopoDS_Shell & S)
737 {
738   SetNodeInVolume( aNode, myIndexToShape.FindIndex(S) );
739 }
740 //=======================================================================
741 //function : SetNodeOnVolume
742 //purpose  : 
743 //=======================================================================
744 void SMESHDS_Mesh::SetNodeInVolume(SMDS_MeshNode *      aNode,
745                                    const TopoDS_Solid & S)
746 {
747   SetNodeInVolume( aNode, myIndexToShape.FindIndex(S) );
748 }
749
750 //=======================================================================
751 //function : SetNodeOnFace
752 //purpose  : 
753 //=======================================================================
754 void SMESHDS_Mesh::SetNodeOnFace(SMDS_MeshNode *     aNode,
755                                  const TopoDS_Face & S,
756                                  double              u,
757                                  double              v)
758 {
759   SetNodeOnFace( aNode, myIndexToShape.FindIndex(S), u, v );
760 }
761
762 //=======================================================================
763 //function : SetNodeOnEdge
764 //purpose  : 
765 //=======================================================================
766 void SMESHDS_Mesh::SetNodeOnEdge(SMDS_MeshNode *     aNode,
767                                  const TopoDS_Edge & S,
768                                  double              u)
769 {
770   SetNodeOnEdge( aNode, myIndexToShape.FindIndex(S), u );
771 }
772
773 //=======================================================================
774 //function : SetNodeOnVertex
775 //purpose  : 
776 //=======================================================================
777 void SMESHDS_Mesh::SetNodeOnVertex(SMDS_MeshNode *       aNode,
778                                    const TopoDS_Vertex & S)
779 {
780   SetNodeOnVertex( aNode, myIndexToShape.FindIndex(S));
781 }
782
783 //=======================================================================
784 //function : UnSetNodeOnShape
785 //purpose  : 
786 //=======================================================================
787 void SMESHDS_Mesh::UnSetNodeOnShape(const SMDS_MeshNode* aNode)
788 {
789         MESSAGE("not implemented");
790 }
791
792 //=======================================================================
793 //function : SetMeshElementOnShape
794 //purpose  : 
795 //=======================================================================
796 void SMESHDS_Mesh::SetMeshElementOnShape(const SMDS_MeshElement * anElement,
797         const TopoDS_Shape & S)
798 {
799         if (myShape.IsNull()) MESSAGE("myShape is NULL");
800
801         int Index = myIndexToShape.FindIndex(S);
802
803         if (myShapeIndexToSubMesh.find(Index)==myShapeIndexToSubMesh.end())
804                 myShapeIndexToSubMesh[Index]=new SMESHDS_SubMesh();
805
806         myShapeIndexToSubMesh[Index]->AddElement(anElement);
807 }
808
809 //=======================================================================
810 //function : UnSetMeshElementOnShape
811 //purpose  : 
812 //=======================================================================
813 void SMESHDS_Mesh::
814 UnSetMeshElementOnShape(const SMDS_MeshElement * anElement,
815         const TopoDS_Shape & S)
816 {
817         if (myShape.IsNull()) MESSAGE("myShape is NULL");
818
819         int Index = myIndexToShape.FindIndex(S);
820
821         if (myShapeIndexToSubMesh.find(Index)!=myShapeIndexToSubMesh.end())
822                 myShapeIndexToSubMesh[Index]->RemoveElement(anElement);
823 }
824
825 //=======================================================================
826 //function : ShapeToMesh
827 //purpose  : 
828 //=======================================================================
829 TopoDS_Shape SMESHDS_Mesh::ShapeToMesh() const
830 {
831         return myShape;
832 }
833
834 //=======================================================================
835 //function : IsGroupOfSubShapes
836 //purpose  : return true if at least one subshape of theShape is a subshape
837 //           of myShape or theShape == myShape
838 //=======================================================================
839
840 bool SMESHDS_Mesh::IsGroupOfSubShapes (const TopoDS_Shape& theShape) const
841 {
842   if ( myShape.IsSame( theShape ))
843     return true;
844
845   for ( TopoDS_Iterator it( theShape ); it.More(); it.Next() ) {
846     if (myIndexToShape.Contains( it.Value() ) ||
847         IsGroupOfSubShapes( it.Value() ))
848       return true;
849   }
850   
851   return false;
852 }
853
854 ///////////////////////////////////////////////////////////////////////////////
855 /// Return the sub mesh linked to the a given TopoDS_Shape or NULL if the given
856 /// TopoDS_Shape is unknown
857 ///////////////////////////////////////////////////////////////////////////////
858 SMESHDS_SubMesh * SMESHDS_Mesh::MeshElements(const TopoDS_Shape & S) const
859 {
860   if (myShape.IsNull()) MESSAGE("myShape is NULL");
861
862   int Index = ShapeToIndex(S);
863   TShapeIndexToSubMesh::const_iterator anIter = myShapeIndexToSubMesh.find(Index);
864   if (anIter != myShapeIndexToSubMesh.end())
865     return anIter->second;
866   else
867     return NULL;
868 }
869
870 ///////////////////////////////////////////////////////////////////////////////
871 /// Return the sub mesh by Id of shape it is linked to
872 ///////////////////////////////////////////////////////////////////////////////
873 SMESHDS_SubMesh * SMESHDS_Mesh::MeshElements(const int Index)
874 {
875   if (myShape.IsNull()) MESSAGE("myShape is NULL");
876
877   if (myShapeIndexToSubMesh.find(Index)!=myShapeIndexToSubMesh.end())
878     return myShapeIndexToSubMesh[Index];
879   else
880     return NULL;
881 }
882
883 //=======================================================================
884 //function : SubMeshIndices
885 //purpose  : 
886 //=======================================================================
887 list<int> SMESHDS_Mesh::SubMeshIndices()
888 {
889   list<int> anIndices;
890   std::map<int,SMESHDS_SubMesh*>::iterator anIter = myShapeIndexToSubMesh.begin();
891   for (; anIter != myShapeIndexToSubMesh.end(); anIter++) {
892     anIndices.push_back((*anIter).first);
893   }
894   return anIndices;
895 }
896
897 //=======================================================================
898 //function : GetHypothesis
899 //purpose  : 
900 //=======================================================================
901
902 const list<const SMESHDS_Hypothesis*>& SMESHDS_Mesh::GetHypothesis(
903         const TopoDS_Shape & S) const
904 {
905         if ( myShapeToHypothesis.IsBound(S) )
906                 return myShapeToHypothesis.Find(S);
907
908         static list<const SMESHDS_Hypothesis*> empty;
909         return empty;
910 }
911
912 //=======================================================================
913 //function : GetScript
914 //purpose  : 
915 //=======================================================================
916 SMESHDS_Script* SMESHDS_Mesh::GetScript()
917 {
918         return myScript;
919 }
920
921 //=======================================================================
922 //function : ClearScript
923 //purpose  : 
924 //=======================================================================
925 void SMESHDS_Mesh::ClearScript()
926 {
927         myScript->Clear();
928 }
929
930 //=======================================================================
931 //function : HasMeshElements
932 //purpose  : 
933 //=======================================================================
934 bool SMESHDS_Mesh::HasMeshElements(const TopoDS_Shape & S)
935 {
936         if (myShape.IsNull()) MESSAGE("myShape is NULL");
937         int Index = myIndexToShape.FindIndex(S);
938         return myShapeIndexToSubMesh.find(Index)!=myShapeIndexToSubMesh.end();
939 }
940
941 //=======================================================================
942 //function : HasHypothesis
943 //purpose  : 
944 //=======================================================================
945 bool SMESHDS_Mesh::HasHypothesis(const TopoDS_Shape & S)
946 {
947         return myShapeToHypothesis.IsBound(S);
948 }
949
950 //=======================================================================
951 //function : NewSubMesh 
952 //purpose  : 
953 //=======================================================================
954 SMESHDS_SubMesh * SMESHDS_Mesh::NewSubMesh(int Index)
955 {
956   SMESHDS_SubMesh* SM = 0;
957   TShapeIndexToSubMesh::iterator anIter = myShapeIndexToSubMesh.find(Index);
958   if (anIter == myShapeIndexToSubMesh.end())
959   {
960     SM = new SMESHDS_SubMesh();
961     myShapeIndexToSubMesh[Index]=SM;
962   }
963   else
964     SM = anIter->second;
965   return SM;
966 }
967
968 //=======================================================================
969 //function : AddCompoundSubmesh
970 //purpose  : 
971 //=======================================================================
972
973 int SMESHDS_Mesh::AddCompoundSubmesh(const TopoDS_Shape& S,
974                                      TopAbs_ShapeEnum    type)
975 {
976   int aMainIndex = 0;
977   if ( IsGroupOfSubShapes( S ) || (S.ShapeType() == TopAbs_VERTEX && myIndexToShape.Contains(S)) )
978   {
979     aMainIndex = myIndexToShape.Add( S );
980     bool all = ( type == TopAbs_SHAPE );
981     if ( all ) // corresponding simple submesh may exist
982       aMainIndex = -aMainIndex;
983     //MESSAGE("AddCompoundSubmesh index = " << aMainIndex );
984     SMESHDS_SubMesh * aNewSub = NewSubMesh( aMainIndex );
985     if ( !aNewSub->IsComplexSubmesh() ) // is empty
986     {
987       int shapeType = all ? myShape.ShapeType() : type;
988       int typeLimit = all ? TopAbs_VERTEX : type;
989       for ( ; shapeType <= typeLimit; shapeType++ )
990       {
991         TopExp_Explorer exp( S, TopAbs_ShapeEnum( shapeType ));
992         for ( ; exp.More(); exp.Next() )
993         {
994           int index = myIndexToShape.FindIndex( exp.Current() );
995           if ( index )
996             aNewSub->AddSubMesh( NewSubMesh( index ));
997         }
998       }
999     }
1000   }
1001   return aMainIndex;
1002 }
1003
1004 //=======================================================================
1005 //function : IndexToShape
1006 //purpose  : 
1007 //=======================================================================
1008 TopoDS_Shape SMESHDS_Mesh::IndexToShape(int ShapeIndex)
1009 {
1010         return myIndexToShape.FindKey(ShapeIndex);
1011 }
1012
1013 //=======================================================================
1014 //function : ShapeToIndex
1015 //purpose  : 
1016 //=======================================================================
1017 int SMESHDS_Mesh::ShapeToIndex(const TopoDS_Shape & S) const
1018 {
1019   if (myShape.IsNull())
1020     MESSAGE("myShape is NULL");
1021
1022   int index = myIndexToShape.FindIndex(S);
1023   
1024   return index;
1025 }
1026
1027 //=======================================================================
1028 //function : SetNodeOnVolume
1029 //purpose  : 
1030 //=======================================================================
1031 void SMESHDS_Mesh::SetNodeInVolume(const SMDS_MeshNode* aNode, int Index)
1032 {
1033   addNodeToSubmesh( aNode, Index );
1034 }
1035
1036 //=======================================================================
1037 //function : SetNodeOnFace
1038 //purpose  : 
1039 //=======================================================================
1040 void SMESHDS_Mesh::SetNodeOnFace(SMDS_MeshNode* aNode, int Index, double u, double v)
1041 {
1042   //Set Position on Node
1043   aNode->SetPosition(SMDS_PositionPtr(new SMDS_FacePosition(Index, u, v)));
1044
1045   addNodeToSubmesh( aNode, Index );
1046 }
1047
1048 //=======================================================================
1049 //function : SetNodeOnEdge
1050 //purpose  : 
1051 //=======================================================================
1052 void SMESHDS_Mesh::SetNodeOnEdge(SMDS_MeshNode* aNode,
1053                                  int            Index,
1054                                  double         u)
1055 {
1056   //Set Position on Node
1057   aNode->SetPosition(SMDS_PositionPtr(new SMDS_EdgePosition(Index, u)));
1058
1059   addNodeToSubmesh( aNode, Index );
1060 }
1061
1062 //=======================================================================
1063 //function : SetNodeOnVertex
1064 //purpose  : 
1065 //=======================================================================
1066 void SMESHDS_Mesh::SetNodeOnVertex(SMDS_MeshNode* aNode, int Index)
1067 {
1068   //Set Position on Node
1069   aNode->SetPosition(SMDS_PositionPtr(new SMDS_VertexPosition(Index)));
1070
1071   addNodeToSubmesh( aNode, Index );
1072 }
1073
1074 //=======================================================================
1075 //function : SetMeshElementOnShape
1076 //purpose  : 
1077 //=======================================================================
1078 void SMESHDS_Mesh::SetMeshElementOnShape(const SMDS_MeshElement* anElement,
1079         int Index)
1080 {
1081         if (myShapeIndexToSubMesh.find(Index)==myShapeIndexToSubMesh.end())
1082                 myShapeIndexToSubMesh[Index]=new SMESHDS_SubMesh();
1083
1084         myShapeIndexToSubMesh[Index]->AddElement(anElement);
1085 }
1086
1087 SMESHDS_Mesh::~SMESHDS_Mesh()
1088 {
1089 }