//=======================================================================
//function : CorrectWires
//purpose  :
//=======================================================================
  Standard_Boolean GEOMAlgo_Tools::CorrectWires(const TopoDS_Shape& aShape)
{
  Standard_Boolean bRet;
  TopoDS_Iterator aItF;
  TopExp_Explorer aExp;
  TopTools_MapOfShape aMF;
  GeomAdaptor_Surface aGAS;
  GeomAbs_SurfaceType aTS;
  TopLoc_Location aLoc;
  //
  bRet=Standard_False;
  //
  aExp.Init(aShape, TopAbs_FACE);
  for (; aExp.More(); aExp.Next()) {
    const TopoDS_Face& aF=*((TopoDS_Face*)&aExp.Current());
    if (aMF.Add(aF)) {
      const Handle(Geom_Surface)& aS=BRep_Tool::Surface(aF, aLoc);
      aGAS.Load(aS);
      aTS=aGAS.GetType();
      if (aTS==GeomAbs_Cylinder || aTS==GeomAbs_Plane) {
	aItF.Initialize(aF);
	for (; aItF.More(); aItF.Next()) {
	  const TopoDS_Wire& aW=*((TopoDS_Wire*)&aItF.Value());
	  if (CorrectWire(aW, aF)) {
	   bRet=Standard_True;
	  }
	}
      }
    }
  }
  return bRet;
}
//=======================================================================
// function:  Tolerance2D
// purpose:
//=======================================================================
 Standard_Real Tolerance2D (const TopoDS_Vertex& aV,
			    const GeomAdaptor_Surface& aGAS)		     
{
  Standard_Real aTol2D, anUr, aVr, aTolV3D;
  GeomAbs_SurfaceType aType;
  //
  aType=aGAS.GetType();
  aTolV3D=BRep_Tool::Tolerance(aV);

  anUr=aGAS.UResolution(aTolV3D);
  aVr =aGAS.VResolution(aTolV3D);
  aTol2D=(aVr>anUr) ? aVr : anUr;
  //
  if (aType==GeomAbs_BSplineSurface||
      aType==GeomAbs_Sphere||
      GeomAbs_SurfaceOfRevolution) {
    if (aTol2D < aTolV3D) {
      aTol2D=aTolV3D;
    }
  }
  if (aType==GeomAbs_BSplineSurface) {
    aTol2D=1.1*aTol2D;
  }
  //
  return aTol2D;
}
//=======================================================================
//function : GetApproxNormalToFaceOnEdge
//purpose  : 
//=======================================================================
void GetApproxNormalToFaceOnEdge (const TopoDS_Edge& aEx, 
                                  const TopoDS_Face& aFx, 
                                  Standard_Real aT, 
                                  gp_Pnt& aPF, 
                                  gp_Dir& aDNF,
                                  IntTools_Context& aCtx)
{
  Standard_Boolean bReverse;
  Standard_Real aT1, aT2, dT, aU, aV;
  gp_Dir aDTT, aDNFT, aDBT;
  gp_Pnt aPFT, aPFx;
  Handle(Geom_Curve) aC3D;
  Handle(Geom_Surface) aS;
  GeomAdaptor_Surface aGAS;
  GeomAbs_SurfaceType aTS;
  TopoDS_Face aF;
  TopoDS_Edge aE;
  //
  bReverse=Standard_False;
  aF=aFx;
  aE=aEx;
  if (aF.Orientation()==TopAbs_REVERSED){
    bReverse=!bReverse;
    aE.Reverse();
    //
    aF.Orientation(TopAbs_FORWARD);
  }
  //
  // Point at aT
  aC3D =BRep_Tool::Curve(aE, aT1, aT2);
  aC3D->D0(aT, aPFT);
  //
  // Normal at aT
  BOPTools_Tools3D::GetNormalToFaceOnEdge (aE, aF, aT, aDNFT);
  
  // Tangent at aT
  BOPTools_Tools3D::GetTangentToEdge(aE, aT, aDTT);
  //
  // Binormal at aT
  aDBT=aDNFT^aDTT;
  //
  dT=BOPTools_Tools3D::MinStepIn2d();//~1.e-5;
  dT=10.*dT;
  //----------------------------------------------
  {
    aS=BRep_Tool::Surface(aF);
    aGAS.Load(aS);
    aTS=aGAS.GetType();
    if (aTS==GeomAbs_BSplineSurface ||
        aTS==GeomAbs_BezierSurface ||
        aTS==GeomAbs_Plane) {
      Standard_Real aTolEx, aTolFx, aTol, dUR, dVR, dR;
      //
      aTolEx=BRep_Tool::Tolerance(aEx);
      aTolFx=BRep_Tool::Tolerance(aFx);
      aTol=2.*aTolEx+aTolFx;
      dUR=aGAS.UResolution(aTol);
      dVR=aGAS.VResolution(aTol);
      dR=(dUR>dVR)? dUR : dVR;
      if (dR>dT) {
        dT=dR;
      }
    }
    //modified by NIZNHY-PKV Thu Dec 02 10:39:09 2010f
    else if (GeomAbs_Torus ||
             aTS==GeomAbs_Cylinder){
      Standard_Real aTolEx, aTolFx, aTol;
      //
      aTolEx=BRep_Tool::Tolerance(aEx);
      aTolFx=BRep_Tool::Tolerance(aFx);
      aTol=2.*aTolEx+aTolFx;
      if (aTol>dT) {
        dT=aTol;
      }
    }
    //modified by NIZNHY-PKV Thu Dec 02 10:39:13 2010t
  }
  //----------------------------------------------
  //
  aPFx.SetXYZ(aPFT.XYZ()+dT*aDBT.XYZ());
  //
  aPF=aPFx;
  aDNF=aDNFT;
  if (bReverse) {
    aDNF.Reverse();
  }
  //
  GeomAPI_ProjectPointOnSurf& aProjector=aCtx.ProjPS(aF);
  //
  aProjector.Perform(aPFx);
  if(aProjector.IsDone()) {
    aProjector.LowerDistanceParameters (aU, aV);
    aS->D0(aU, aV, aPF);
    BOPTools_Tools3D::GetNormalToSurface (aS, aU, aV, aDNF);
    if (bReverse){
      aDNF.Reverse();
    }
  }
}