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