+//=======================================================================
+//function : GetSubShapeOri
+//purpose : Return orientation of sub-shape in the main shape
+//=======================================================================
+
+TopAbs_Orientation SMESH_MesherHelper::GetSubShapeOri(const TopoDS_Shape& shape,
+ const TopoDS_Shape& subShape)
+{
+ TopAbs_Orientation ori = TopAbs_Orientation(-1);
+ if ( !shape.IsNull() && !subShape.IsNull() )
+ {
+ TopExp_Explorer e( shape, subShape.ShapeType() );
+ if ( shape.Orientation() >= TopAbs_INTERNAL ) // TopAbs_INTERNAL or TopAbs_EXTERNAL
+ e.Init( shape.Oriented(TopAbs_FORWARD), subShape.ShapeType() );
+ for ( ; e.More(); e.Next())
+ if ( subShape.IsSame( e.Current() ))
+ break;
+ if ( e.More() )
+ ori = e.Current().Orientation();
+ }
+ return ori;
+}
+
+//=======================================================================
+//function : IsSubShape
+//purpose :
+//=======================================================================
+
+bool SMESH_MesherHelper::IsSubShape( const TopoDS_Shape& shape,
+ const TopoDS_Shape& mainShape )
+{
+ if ( !shape.IsNull() && !mainShape.IsNull() )
+ {
+ for ( TopExp_Explorer exp( mainShape, shape.ShapeType());
+ exp.More();
+ exp.Next() )
+ if ( shape.IsSame( exp.Current() ))
+ return true;
+ }
+ SCRUTE((shape.IsNull()));
+ SCRUTE((mainShape.IsNull()));
+ return false;
+}
+
+//=======================================================================
+//function : IsSubShape
+//purpose :
+//=======================================================================
+
+bool SMESH_MesherHelper::IsSubShape( const TopoDS_Shape& shape, SMESH_Mesh* aMesh )
+{
+ if ( shape.IsNull() || !aMesh )
+ return false;
+ return
+ aMesh->GetMeshDS()->ShapeToIndex( shape ) ||
+ // PAL16202
+ (shape.ShapeType() == TopAbs_COMPOUND && aMesh->GetMeshDS()->IsGroupOfSubShapes( shape ));
+}
+
+//================================================================================
+/*!
+ * \brief Return maximal tolerance of shape
+ */
+//================================================================================
+
+double SMESH_MesherHelper::MaxTolerance( const TopoDS_Shape& shape )
+{
+ double tol = Precision::Confusion();
+ TopExp_Explorer exp;
+ for ( exp.Init( shape, TopAbs_FACE ); exp.More(); exp.Next() )
+ tol = Max( tol, BRep_Tool::Tolerance( TopoDS::Face( exp.Current())));
+ for ( exp.Init( shape, TopAbs_EDGE ); exp.More(); exp.Next() )
+ tol = Max( tol, BRep_Tool::Tolerance( TopoDS::Edge( exp.Current())));
+ for ( exp.Init( shape, TopAbs_VERTEX ); exp.More(); exp.Next() )
+ tol = Max( tol, BRep_Tool::Tolerance( TopoDS::Vertex( exp.Current())));
+
+ return tol;
+}
+
+//================================================================================
+/*!
+ * \brief Check if the first and last vertices of an edge are the same
+ * \param anEdge - the edge to check
+ * \retval bool - true if same
+ */
+//================================================================================
+
+bool SMESH_MesherHelper::IsClosedEdge( const TopoDS_Edge& anEdge )
+{
+ if ( anEdge.Orientation() >= TopAbs_INTERNAL )
+ return IsClosedEdge( TopoDS::Edge( anEdge.Oriented( TopAbs_FORWARD )));
+ return TopExp::FirstVertex( anEdge ).IsSame( TopExp::LastVertex( anEdge ));
+}
+
+//================================================================================
+/*!
+ * \brief Wrapper over TopExp::FirstVertex() and TopExp::LastVertex() fixing them
+ * in the case of INTERNAL edge
+ */
+//================================================================================
+
+TopoDS_Vertex SMESH_MesherHelper::IthVertex( const bool is2nd,
+ TopoDS_Edge anEdge,
+ const bool CumOri )
+{
+ if ( anEdge.Orientation() >= TopAbs_INTERNAL )
+ anEdge.Orientation( TopAbs_FORWARD );
+
+ const TopAbs_Orientation tgtOri = is2nd ? TopAbs_REVERSED : TopAbs_FORWARD;
+ TopoDS_Iterator vIt( anEdge, CumOri );
+ while ( vIt.More() && vIt.Value().Orientation() != tgtOri )
+ vIt.Next();
+
+ return ( vIt.More() ? TopoDS::Vertex(vIt.Value()) : TopoDS_Vertex() );
+}
+