]> SALOME platform Git repositories - modules/smesh.git/blob - src/SMESH/SMESH_MesherHelper.cxx
Salome HOME
Use SetSubShape() in IsQuadraticSubMesh(). Fix SIGSEGV in AddFace() on sphere and...
[modules/smesh.git] / src / SMESH / SMESH_MesherHelper.cxx
1 // File:      SMESH_MesherHelper.cxx
2 // Created:   15.02.06 15:22:41
3 // Author:    Sergey KUUL
4 // Copyright: Open CASCADE 2006
5
6
7 #include "SMESH_MesherHelper.hxx"
8
9 #include "SMDS_FacePosition.hxx" 
10 #include "SMDS_EdgePosition.hxx"
11 #include "SMESH_MeshEditor.hxx"
12
13 #include <BRepAdaptor_Surface.hxx>
14 #include <BRepTools.hxx>
15 #include <BRep_Tool.hxx>
16 #include <Geom2d_Curve.hxx>
17 #include <Geom_Curve.hxx>
18 #include <Geom_Surface.hxx>
19 #include <TopExp_Explorer.hxx>
20 #include <TopTools_MapOfShape.hxx>
21 #include <gp_Pnt2d.hxx>
22 #include <ShapeAnalysis.hxx>
23
24 //=======================================================================
25 //function : CheckShape
26 //purpose  : 
27 //=======================================================================
28
29 bool SMESH_MesherHelper::IsQuadraticSubMesh(const TopoDS_Shape& aSh)
30 {
31   SMESHDS_Mesh* meshDS = GetMesh()->GetMeshDS();
32   myShapeID = meshDS->ShapeToIndex(aSh);
33   // we can create quadratic elements only if all elements
34   // created on subshapes of given shape are quadratic
35   // also we have to fill myNLinkNodeMap
36   myCreateQuadratic = true;
37   mySeamShapeIds.clear();
38   TopAbs_ShapeEnum subType( aSh.ShapeType()==TopAbs_FACE ? TopAbs_EDGE : TopAbs_FACE );
39   SMDSAbs_ElementType elemType( subType==TopAbs_FACE ? SMDSAbs_Face : SMDSAbs_Edge );
40
41   TopExp_Explorer exp( aSh, subType );
42   for (; exp.More() && myCreateQuadratic; exp.Next()) {
43     if ( SMESHDS_SubMesh * subMesh = meshDS->MeshElements( exp.Current() )) {
44       if ( SMDS_ElemIteratorPtr it = subMesh->GetElements() ) {
45         while(it->more()) {
46           const SMDS_MeshElement* e = it->next();
47           if ( e->GetType() != elemType || !e->IsQuadratic() ) {
48             myCreateQuadratic = false;
49             break;
50           }
51           else {
52             // fill NLinkNodeMap
53             switch ( e->NbNodes() ) {
54             case 3:
55               AddNLinkNode(e->GetNode(0),e->GetNode(1),e->GetNode(2)); break;
56             case 6:
57               AddNLinkNode(e->GetNode(0),e->GetNode(1),e->GetNode(3));
58               AddNLinkNode(e->GetNode(1),e->GetNode(2),e->GetNode(4));
59               AddNLinkNode(e->GetNode(2),e->GetNode(0),e->GetNode(5)); break;
60             case 8:
61               AddNLinkNode(e->GetNode(0),e->GetNode(1),e->GetNode(4));
62               AddNLinkNode(e->GetNode(1),e->GetNode(2),e->GetNode(5));
63               AddNLinkNode(e->GetNode(2),e->GetNode(3),e->GetNode(6));
64               AddNLinkNode(e->GetNode(3),e->GetNode(0),e->GetNode(7));
65               break;
66             default:
67               myCreateQuadratic = false;
68               break;
69             }
70           }
71         }
72       }
73     }
74   }
75
76   if(!myCreateQuadratic) {
77     myNLinkNodeMap.clear();
78   }
79   else {
80     SetSubShape( aSh );
81   }
82   return myCreateQuadratic;
83 }
84
85 //================================================================================
86 /*!
87  * \brief Set geomerty to make elements on
88   * \param aSh - geomertic shape
89  */
90 //================================================================================
91
92 void SMESH_MesherHelper::SetSubShape(const TopoDS_Shape& aSh)
93 {
94   myShape = aSh;
95
96   // treatment of periodic faces
97   if ( aSh.ShapeType() == TopAbs_FACE )
98   {
99     const TopoDS_Face& face = TopoDS::Face( aSh );
100     BRepAdaptor_Surface surface( face );
101     if ( surface.IsUPeriodic() || surface.IsVPeriodic() )
102     {
103       SMESHDS_Mesh* meshDS = GetMesh()->GetMeshDS();
104       // look for a seam edge
105       for ( TopExp_Explorer exp( face, TopAbs_EDGE ); exp.More(); exp.Next()) {
106         const TopoDS_Edge& edge = TopoDS::Edge( exp.Current() );
107         if ( BRep_Tool::IsClosed( edge, face )) {
108           // initialize myPar1, myPar2 and myParIndex
109           if ( mySeamShapeIds.empty() ) {
110             gp_Pnt2d uv1, uv2;
111             BRep_Tool::UVPoints( edge, face, uv1, uv2 );
112             if ( Abs( uv1.Coord(1) - uv2.Coord(1) ) < Abs( uv1.Coord(2) - uv2.Coord(2) ))
113             {
114               myParIndex = 1; // U periodic
115               myPar1 = surface.FirstUParameter();
116               myPar2 = surface.LastUParameter();
117             }
118             else {
119               myParIndex = 2;  // V periodic
120               myPar1 = surface.FirstVParameter();
121               myPar2 = surface.LastVParameter();
122             }
123           }
124           // store shapes indices
125           mySeamShapeIds.insert( meshDS->ShapeToIndex( exp.Current() ));
126           for ( TopExp_Explorer v( exp.Current(), TopAbs_VERTEX ); v.More(); v.Next() )
127             mySeamShapeIds.insert( meshDS->ShapeToIndex( v.Current() ));
128         }
129       }
130     }
131   }
132 }
133
134
135 //=======================================================================
136 //function : IsMedium
137 //purpose  : 
138 //=======================================================================
139
140 bool SMESH_MesherHelper::IsMedium(const SMDS_MeshNode*      node,
141                                  const SMDSAbs_ElementType typeToCheck)
142 {
143   return SMESH_MeshEditor::IsMedium( node, typeToCheck );
144 }
145
146 //=======================================================================
147 //function : AddNLinkNode
148 //purpose  : 
149 //=======================================================================
150 /*!
151  * Auxilary function for filling myNLinkNodeMap
152  */
153 void SMESH_MesherHelper::AddNLinkNode(const SMDS_MeshNode* n1,
154                                      const SMDS_MeshNode* n2,
155                                      const SMDS_MeshNode* n12)
156 {
157   NLink link( n1, n2 );
158   if ( n1 > n2 ) link = NLink( n2, n1 );
159   // add new record to map
160   myNLinkNodeMap.insert( make_pair(link,n12));
161 }
162
163 //=======================================================================
164 /*!
165  * \brief Select UV on either of 2 pcurves of a seam edge, closest to the given UV
166  * \param uv1 - UV on the seam
167  * \param uv2 - UV within a face
168  * \retval gp_Pnt2d - selected UV
169  */
170 //=======================================================================
171
172 gp_Pnt2d SMESH_MesherHelper::GetUVOnSeam( const gp_Pnt2d& uv1, const gp_Pnt2d& uv2 ) const
173 {
174   double p1 = uv1.Coord( myParIndex );
175   double p2 = uv2.Coord( myParIndex );
176   double p3 = ( Abs( p1 - myPar1 ) < Abs( p1 - myPar2 )) ? myPar2 : myPar1;
177   if ( Abs( p2 - p1 ) > Abs( p2 - p3 ))
178     p1 = p3;
179   gp_Pnt2d result = uv1;
180   result.SetCoord( myParIndex, p1 );
181   return result;
182 }
183
184 //=======================================================================
185 /*!
186  * \brief Return node UV on face
187  * \param F - the face
188  * \param n - the node
189  * \param n2 - a medium node will be placed between n and n2
190  * \retval gp_XY - resulting UV
191  * 
192  * Auxilary function called form GetMediumNode()
193  */
194 //=======================================================================
195
196 gp_XY SMESH_MesherHelper::GetNodeUV(const TopoDS_Face&   F,
197                                     const SMDS_MeshNode* n,
198                                     const SMDS_MeshNode* n2)
199 {
200   gp_Pnt2d uv;
201   const SMDS_PositionPtr Pos = n->GetPosition();
202   if(Pos->GetTypeOfPosition()==SMDS_TOP_FACE) {
203     // node has position on face
204     const SMDS_FacePosition* fpos =
205       static_cast<const SMDS_FacePosition*>(n->GetPosition().get());
206     uv = gp_Pnt2d(fpos->GetUParameter(),fpos->GetVParameter());
207   }
208   else if(Pos->GetTypeOfPosition()==SMDS_TOP_EDGE) {
209     // node has position on edge => it is needed to find
210     // corresponding edge from face, get pcurve for this
211     // edge and recieve value from this pcurve
212     const SMDS_EdgePosition* epos =
213       static_cast<const SMDS_EdgePosition*>(n->GetPosition().get());
214     SMESHDS_Mesh* meshDS = GetMesh()->GetMeshDS();
215     int edgeID = Pos->GetShapeId();
216     TopoDS_Edge E = TopoDS::Edge(meshDS->IndexToShape(edgeID));
217     double f, l;
218     TopLoc_Location loc;
219     Handle(Geom2d_Curve) C2d = BRep_Tool::CurveOnSurface(E, F, f, l);
220     uv = C2d->Value( epos->GetUParameter() );
221     // for a node on a seam edge select one of UVs on 2 pcurves
222     if ( n2 && mySeamShapeIds.find( edgeID ) != mySeamShapeIds.end() )
223       uv = GetUVOnSeam( uv, GetNodeUV( F, n2, 0 ));
224   }
225   else if(Pos->GetTypeOfPosition()==SMDS_TOP_VERTEX) {
226     SMESHDS_Mesh * meshDS = GetMesh()->GetMeshDS();
227     int vertexID = n->GetPosition()->GetShapeId();
228     const TopoDS_Vertex& V = TopoDS::Vertex(meshDS->IndexToShape(vertexID));
229     uv = BRep_Tool::Parameters( V, F );
230     if ( n2 && mySeamShapeIds.find( vertexID ) != mySeamShapeIds.end() )
231       uv = GetUVOnSeam( uv, GetNodeUV( F, n2, 0 ));
232   }
233   return uv.XY();
234 }
235
236 //=======================================================================
237 /*!
238  * \brief Return node U on edge
239  * \param E - the Edge
240  * \param n - the node
241  * \retval double - resulting U
242  * 
243  * Auxilary function called form GetMediumNode()
244  */
245 //=======================================================================
246
247 double SMESH_MesherHelper::GetNodeU(const TopoDS_Edge&   E,
248                                     const SMDS_MeshNode* n)
249 {
250   double param = 0;
251   const SMDS_PositionPtr Pos = n->GetPosition();
252   if(Pos->GetTypeOfPosition()==SMDS_TOP_EDGE) {
253     const SMDS_EdgePosition* epos =
254       static_cast<const SMDS_EdgePosition*>(n->GetPosition().get());
255     param =  epos->GetUParameter();
256   }
257   else if(Pos->GetTypeOfPosition()==SMDS_TOP_VERTEX) {
258     SMESHDS_Mesh * meshDS = GetMesh()->GetMeshDS();
259     int vertexID = n->GetPosition()->GetShapeId();
260     const TopoDS_Vertex& V = TopoDS::Vertex(meshDS->IndexToShape(vertexID));
261     param =  BRep_Tool::Parameter( V, E );
262   }
263   return param;
264 }
265
266 //=======================================================================
267 //function : GetMediumNode
268 //purpose  : 
269 //=======================================================================
270 /*!
271  * Special function for search or creation medium node
272  */
273 const SMDS_MeshNode* SMESH_MesherHelper::GetMediumNode(const SMDS_MeshNode* n1,
274                                                        const SMDS_MeshNode* n2,
275                                                        bool force3d)
276 {
277   TopAbs_ShapeEnum shapeType = myShape.IsNull() ? TopAbs_SHAPE : myShape.ShapeType();
278
279   NLink link(( n1 < n2 ? n1 : n2 ), ( n1 < n2 ? n2 : n1 ));
280   ItNLinkNode itLN = myNLinkNodeMap.find( link );
281   if ( itLN != myNLinkNodeMap.end() ) {
282     return (*itLN).second;
283   }
284   else {
285     // create medium node
286     SMDS_MeshNode* n12;
287     SMESHDS_Mesh* meshDS = GetMesh()->GetMeshDS();
288     int faceID = -1, edgeID = -1;
289     const SMDS_PositionPtr Pos1 = n1->GetPosition();
290     const SMDS_PositionPtr Pos2 = n2->GetPosition();
291   
292     if( myShape.IsNull() )
293     {
294       if( Pos1->GetTypeOfPosition()==SMDS_TOP_FACE ) {
295         faceID = Pos1->GetShapeId();
296       }
297       else if( Pos2->GetTypeOfPosition()==SMDS_TOP_FACE ) {
298         faceID = Pos2->GetShapeId();
299       }
300
301       if( Pos1->GetTypeOfPosition()==SMDS_TOP_EDGE ) {
302         edgeID = Pos1->GetShapeId();
303       }
304       if( Pos2->GetTypeOfPosition()==SMDS_TOP_EDGE ) {
305         edgeID = Pos2->GetShapeId();
306       }
307     }
308
309     if(!force3d) {
310       // we try to create medium node using UV parameters of
311       // nodes, else - medium between corresponding 3d points
312       if(faceID>-1 || shapeType == TopAbs_FACE) {
313         // obtaining a face and 2d points for nodes
314         TopoDS_Face F;
315         if( myShape.IsNull() )
316           F = TopoDS::Face(meshDS->IndexToShape(faceID));
317         else
318           F = TopoDS::Face(myShape);
319
320         gp_XY p1 = GetNodeUV(F,n1,n2);
321         gp_XY p2 = GetNodeUV(F,n2,n1);
322
323         //checking if surface is periodic
324         Handle(Geom_Surface) S = BRep_Tool::Surface(F);
325         Standard_Real UF,UL,VF,VL;
326         S->Bounds(UF,UL,VF,VL);
327
328         Standard_Real u,v;
329         Standard_Boolean isUPeriodic = S->IsUPeriodic();
330         if(isUPeriodic) {
331           Standard_Real UPeriod = S->UPeriod();
332           Standard_Real p2x = p2.X()+ShapeAnalysis::AdjustByPeriod(p2.X(),p1.X(),UPeriod);
333           Standard_Real pmid = (p1.X()+p2x)/2.;
334           u = pmid+ShapeAnalysis::AdjustToPeriod(pmid,UF,UL);
335         }
336         else 
337           u= (p1.X()+p2.X())/2.;
338
339         Standard_Boolean isVPeriodic = S->IsVPeriodic();
340         if(isVPeriodic) {
341           Standard_Real VPeriod = S->VPeriod();
342           Standard_Real p2y = p2.Y()+ShapeAnalysis::AdjustByPeriod(p2.Y(),p1.Y(),VPeriod);
343           Standard_Real pmid = (p1.Y()+p2y)/2.;
344           v = pmid+ShapeAnalysis::AdjustToPeriod(pmid,VF,VL);
345         }
346         else
347           v = (p1.Y()+p2.Y())/2.;
348
349         gp_Pnt P = S->Value(u, v);
350         n12 = meshDS->AddNode(P.X(), P.Y(), P.Z());
351         meshDS->SetNodeOnFace(n12, faceID, u, v);
352         myNLinkNodeMap.insert(NLinkNodeMap::value_type(link,n12));
353         return n12;
354       }
355       if (edgeID>-1 || shapeType == TopAbs_EDGE) {
356
357         TopoDS_Edge E;
358         if( myShape.IsNull() )
359           E = TopoDS::Edge(meshDS->IndexToShape(edgeID));
360         else
361           E = TopoDS::Edge(myShape);
362
363         double p1 = GetNodeU(E,n1);
364         double p2 = GetNodeU(E,n2);
365
366         double f,l;
367         Handle(Geom_Curve) C = BRep_Tool::Curve(E, f, l);
368         if(!C.IsNull()) {
369
370           Standard_Boolean isPeriodic = C->IsPeriodic();
371           double u;
372           if(isPeriodic) {
373             Standard_Real Period = C->Period();
374             Standard_Real p = p2+ShapeAnalysis::AdjustByPeriod(p2,p1,Period);
375             Standard_Real pmid = (p1+p)/2.;
376             u = pmid+ShapeAnalysis::AdjustToPeriod(pmid,C->FirstParameter(),C->LastParameter());
377           }
378           else
379             u = (p1+p2)/2.;
380
381           gp_Pnt P = C->Value( u );
382           n12 = meshDS->AddNode(P.X(), P.Y(), P.Z());
383           meshDS->SetNodeOnEdge(n12, edgeID, u);
384           myNLinkNodeMap.insert(NLinkNodeMap::value_type(link,n12));
385           return n12;
386         }
387       }
388     }
389     // 3d variant
390     double x = ( n1->X() + n2->X() )/2.;
391     double y = ( n1->Y() + n2->Y() )/2.;
392     double z = ( n1->Z() + n2->Z() )/2.;
393     n12 = meshDS->AddNode(x,y,z);
394     if(edgeID>-1)
395         meshDS->SetNodeOnEdge(n12, edgeID);
396     else if(faceID>-1)
397         meshDS->SetNodeOnFace(n12, faceID);
398     else
399       meshDS->SetNodeInVolume(n12, myShapeID);
400     myNLinkNodeMap.insert(NLinkNodeMap::value_type(link,n12));
401     return n12;
402   }
403 }
404
405 //=======================================================================
406 //function : AddQuadraticEdge
407 //purpose  : 
408 //=======================================================================
409 /**
410  * Special function for creation quadratic edge
411  */
412 SMDS_QuadraticEdge* SMESH_MesherHelper::AddQuadraticEdge(const SMDS_MeshNode* n1,
413                                                          const SMDS_MeshNode* n2,
414                                                          const int id,
415                                                          const bool force3d)
416 {
417   SMESHDS_Mesh * meshDS = GetMesh()->GetMeshDS();
418   
419   const SMDS_MeshNode* n12 = GetMediumNode(n1,n2,force3d);
420   
421   myCreateQuadratic = true;
422
423   if(id)
424     return  (SMDS_QuadraticEdge*)(meshDS->AddEdgeWithID(n1, n2, n12, id));
425   else
426     return  (SMDS_QuadraticEdge*)(meshDS->AddEdge(n1, n2, n12));
427 }
428
429 //=======================================================================
430 //function : AddFace
431 //purpose  : 
432 //=======================================================================
433 /*!
434  * Special function for creation quadratic triangle
435  */
436 SMDS_MeshFace* SMESH_MesherHelper::AddFace(const SMDS_MeshNode* n1,
437                                            const SMDS_MeshNode* n2,
438                                            const SMDS_MeshNode* n3,
439                                            const int id,
440                                            const bool force3d)
441 {
442   SMESHDS_Mesh * meshDS = GetMesh()->GetMeshDS();
443   if(!myCreateQuadratic) {
444     if(id)
445       return  meshDS->AddFaceWithID(n1, n2, n3, id);
446     else
447       return  meshDS->AddFace(n1, n2, n3);
448   }
449
450   const SMDS_MeshNode* n12 = GetMediumNode(n1,n2,force3d);
451   const SMDS_MeshNode* n23 = GetMediumNode(n2,n3,force3d);
452   const SMDS_MeshNode* n31 = GetMediumNode(n3,n1,force3d);
453
454   if(id)
455     return  meshDS->AddFaceWithID(n1, n2, n3, n12, n23, n31, id);
456   else
457     return  meshDS->AddFace(n1, n2, n3, n12, n23, n31);
458 }
459
460
461 //=======================================================================
462 //function : AddFace
463 //purpose  : 
464 //=======================================================================
465 /*!
466  * Special function for creation quadratic quadrangle
467  */
468 SMDS_MeshFace* SMESH_MesherHelper::AddFace(const SMDS_MeshNode* n1,
469                                            const SMDS_MeshNode* n2,
470                                            const SMDS_MeshNode* n3,
471                                            const SMDS_MeshNode* n4,
472                                            const int id,
473                                            const bool force3d)
474 {
475   SMESHDS_Mesh * meshDS = GetMesh()->GetMeshDS();
476   if(!myCreateQuadratic) {
477     if(id)
478       return  meshDS->AddFaceWithID(n1, n2, n3, n4, id);
479     else
480       return  meshDS->AddFace(n1, n2, n3, n4);
481   }
482
483   const SMDS_MeshNode* n12 = GetMediumNode(n1,n2,force3d);
484   const SMDS_MeshNode* n23 = GetMediumNode(n2,n3,force3d);
485   const SMDS_MeshNode* n34 = GetMediumNode(n3,n4,force3d);
486   const SMDS_MeshNode* n41 = GetMediumNode(n4,n1,force3d);
487
488   if(id)
489     return  meshDS->AddFaceWithID(n1, n2, n3, n4, n12, n23, n34, n41, id);
490   else
491     return  meshDS->AddFace(n1, n2, n3, n4, n12, n23, n34, n41);
492 }
493
494
495 //=======================================================================
496 //function : AddVolume
497 //purpose  : 
498 //=======================================================================
499 /*!
500  * Special function for creation quadratic volume
501  */
502 SMDS_MeshVolume* SMESH_MesherHelper::AddVolume(const SMDS_MeshNode* n1,
503                                                const SMDS_MeshNode* n2,
504                                                const SMDS_MeshNode* n3,
505                                                const SMDS_MeshNode* n4,
506                                                const SMDS_MeshNode* n5,
507                                                const SMDS_MeshNode* n6,
508                                                const int id,
509                                                const bool force3d)
510 {
511   SMESHDS_Mesh * meshDS = GetMesh()->GetMeshDS();
512   if(!myCreateQuadratic) {
513     if(id)
514       return meshDS->AddVolumeWithID(n1, n2, n3, n4, n5, n6, id);
515     else
516       return meshDS->AddVolume(n1, n2, n3, n4, n5, n6);
517   }
518
519   const SMDS_MeshNode* n12 = GetMediumNode(n1,n2,force3d);
520   const SMDS_MeshNode* n23 = GetMediumNode(n2,n3,force3d);
521   const SMDS_MeshNode* n31 = GetMediumNode(n3,n1,force3d);
522
523   const SMDS_MeshNode* n45 = GetMediumNode(n4,n5,force3d);
524   const SMDS_MeshNode* n56 = GetMediumNode(n5,n6,force3d);
525   const SMDS_MeshNode* n64 = GetMediumNode(n6,n4,force3d);
526
527   const SMDS_MeshNode* n14 = GetMediumNode(n1,n4,force3d);
528   const SMDS_MeshNode* n25 = GetMediumNode(n2,n5,force3d);
529   const SMDS_MeshNode* n36 = GetMediumNode(n3,n6,force3d);
530
531   if(id)
532     return meshDS->AddVolumeWithID(n1, n2, n3, n4, n5, n6, 
533                                    n12, n23, n31, n45, n56, n64, n14, n25, n36, id);
534   else
535     return meshDS->AddVolume(n1, n2, n3, n4, n5, n6,
536                              n12, n23, n31, n45, n56, n64, n14, n25, n36);
537 }
538
539
540 //=======================================================================
541 //function : AddVolume
542 //purpose  : 
543 //=======================================================================
544 /*!
545  * Special function for creation quadratic volume
546  */
547 SMDS_MeshVolume* SMESH_MesherHelper::AddVolume(const SMDS_MeshNode* n1,
548                                                const SMDS_MeshNode* n2,
549                                                const SMDS_MeshNode* n3,
550                                                const SMDS_MeshNode* n4,
551                                                const int id, 
552                                                const bool force3d)
553 {
554   SMESHDS_Mesh * meshDS = GetMesh()->GetMeshDS();
555   if(!myCreateQuadratic) {
556     if(id)
557       return meshDS->AddVolumeWithID(n1, n2, n3, n4, id);
558     else
559       return meshDS->AddVolume(n1, n2, n3, n4);
560   }
561
562   const SMDS_MeshNode* n12 = GetMediumNode(n1,n2,force3d);
563   const SMDS_MeshNode* n23 = GetMediumNode(n2,n3,force3d);
564   const SMDS_MeshNode* n31 = GetMediumNode(n3,n1,force3d);
565
566   const SMDS_MeshNode* n14 = GetMediumNode(n1,n4,force3d);
567   const SMDS_MeshNode* n24 = GetMediumNode(n2,n4,force3d);
568   const SMDS_MeshNode* n34 = GetMediumNode(n3,n4,force3d);
569
570   if(id)
571     return meshDS->AddVolumeWithID(n1, n2, n3, n4, n12, n23, n31, n14, n24, n34, id);
572   else
573     return meshDS->AddVolume(n1, n2, n3, n4, n12, n23, n31, n14, n24, n34);
574 }
575
576
577 //=======================================================================
578 //function : AddVolume
579 //purpose  : 
580 //=======================================================================
581 /*!
582  * Special function for creation quadratic volume
583  */
584 SMDS_MeshVolume* SMESH_MesherHelper::AddVolume(const SMDS_MeshNode* n1,
585                                                const SMDS_MeshNode* n2,
586                                                const SMDS_MeshNode* n3,
587                                                const SMDS_MeshNode* n4,
588                                                const SMDS_MeshNode* n5,
589                                                const SMDS_MeshNode* n6,
590                                                const SMDS_MeshNode* n7,
591                                                const SMDS_MeshNode* n8,
592                                                const int id,
593                                                const bool force3d)
594 {
595   SMESHDS_Mesh * meshDS = GetMesh()->GetMeshDS();
596   if(!myCreateQuadratic) {
597     if(id)
598       return meshDS->AddVolumeWithID(n1, n2, n3, n4, n5, n6, n7, n8, id);
599     else
600       return meshDS->AddVolume(n1, n2, n3, n4, n5, n6, n7, n8);
601   }
602
603   const SMDS_MeshNode* n12 = GetMediumNode(n1,n2,force3d);
604   const SMDS_MeshNode* n23 = GetMediumNode(n2,n3,force3d);
605   const SMDS_MeshNode* n34 = GetMediumNode(n3,n4,force3d);
606   const SMDS_MeshNode* n41 = GetMediumNode(n4,n1,force3d);
607
608   const SMDS_MeshNode* n56 = GetMediumNode(n5,n6,force3d);
609   const SMDS_MeshNode* n67 = GetMediumNode(n6,n7,force3d);
610   const SMDS_MeshNode* n78 = GetMediumNode(n7,n8,force3d);
611   const SMDS_MeshNode* n85 = GetMediumNode(n8,n5,force3d);
612
613   const SMDS_MeshNode* n15 = GetMediumNode(n1,n5,force3d);
614   const SMDS_MeshNode* n26 = GetMediumNode(n2,n6,force3d);
615   const SMDS_MeshNode* n37 = GetMediumNode(n3,n7,force3d);
616   const SMDS_MeshNode* n48 = GetMediumNode(n4,n8,force3d);
617
618   if(id)
619     return meshDS->AddVolumeWithID(n1, n2, n3, n4, n5, n6, n7, n8,
620                                    n12, n23, n34, n41, n56, n67,
621                                    n78, n85, n15, n26, n37, n48, id);
622   else
623     return meshDS->AddVolume(n1, n2, n3, n4, n5, n6, n7, n8,
624                              n12, n23, n34, n41, n56, n67,
625                              n78, n85, n15, n26, n37, n48);
626 }
627
628