0029968: Modeling Algorithms - BRepAlgoAPI_Cut produces an empty result with half...
[occt.git] / src / IntTools / IntTools_Context.cxx
old mode 100755 (executable)
new mode 100644 (file)
index 75c0fa6..4d90a58
-// File:       IntTools_Context.cxx
-// Created:    Wed Apr  3 16:57:54 2002
-// Author:     Peter KURNEV
-//             <pkv@irinox>
+// Created by: Peter KURNEV
+// Copyright (c) 1999-2014 OPEN CASCADE SAS
+//
+// This file is part of Open CASCADE Technology software library.
+//
+// This library is free software; you can redistribute it and/or modify it under
+// the terms of the GNU Lesser General Public License version 2.1 as published
+// by the Free Software Foundation, with special exception defined in the file
+// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
+// distribution for complete text of the license and disclaimer of any warranty.
+//
+// Alternatively, this file may be used under the terms of Open CASCADE
+// commercial license or contractual agreement.
 
 
-#include <IntTools_Context.ixx>
-
-#include <Precision.hxx>
-
-#include <Geom_Curve.hxx>
+#include <Bnd_Box.hxx>
+#include <Bnd_OBB.hxx>
+#include <BRep_Tool.hxx>
+#include <BRepAdaptor_Surface.hxx>
+#include <BRepBndLib.hxx>
+#include <BRepClass3d_SolidClassifier.hxx>
+#include <Extrema_LocateExtPC.hxx>
+#include <Geom2d_Curve.hxx>
+#include <Geom2d_TrimmedCurve.hxx>
+#include <Geom2dHatch_Hatcher.hxx>
+#include <Geom2dHatch_Intersector.hxx>
 #include <Geom_BoundedCurve.hxx>
+#include <Geom_Curve.hxx>
+#include <GeomAdaptor_Curve.hxx>
 #include <GeomAPI_ProjectPointOnCurve.hxx>
 #include <GeomAPI_ProjectPointOnSurf.hxx>
-#include <GeomAdaptor_Curve.hxx>
-
+#include <gp_Pnt.hxx>
+#include <gp_Pnt2d.hxx>
+#include <IntTools_Context.hxx>
+#include <IntTools_Curve.hxx>
+#include <IntTools_FClass2d.hxx>
+#include <IntTools_SurfaceRangeLocalizeData.hxx>
+#include <IntTools_Tools.hxx>
+#include <Precision.hxx>
+#include <Standard_Type.hxx>
 #include <TopAbs_State.hxx>
-#include <TopoDS.hxx>
 #include <TopExp_Explorer.hxx>
+#include <TopoDS.hxx>
+#include <TopoDS_Edge.hxx>
+#include <TopoDS_Face.hxx>
+#include <TopoDS_Shape.hxx>
+#include <TopoDS_Solid.hxx>
+#include <TopoDS_Vertex.hxx>
 
-#include <BRep_Tool.hxx>
-#include <BRepAdaptor_Surface.hxx>
+IMPLEMENT_STANDARD_RTTIEXT(IntTools_Context,Standard_Transient)
 
-#include <IntTools_Tools.hxx>
-#include <IntTools_FClass2d.hxx>
 // 
-#include <Extrema_LocateExtPC.hxx>
-
-#include <Geom2d_Curve.hxx>
-
 //=======================================================================
 //function : 
 //purpose  : 
 //=======================================================================
-  IntTools_Context::IntTools_Context()
+IntTools_Context::IntTools_Context()
+:
+  myAllocator(NCollection_BaseAllocator::CommonBaseAllocator()),
+  myFClass2dMap(100, myAllocator),
+  myProjPSMap(100, myAllocator),
+  myProjPCMap(100, myAllocator),
+  mySClassMap(100, myAllocator),
+  myProjPTMap(100, myAllocator),
+  myHatcherMap(100, myAllocator),
+  myProjSDataMap(100, myAllocator),
+  myBndBoxDataMap(100, myAllocator),
+  mySurfAdaptorMap(100, myAllocator),
+  myOBBMap(100, myAllocator),
+  myCreateFlag(0),
+  myPOnSTolerance(1.e-12)
+{
+}
+//=======================================================================
+//function : 
+//purpose  : 
+//=======================================================================
+IntTools_Context::IntTools_Context
+  (const Handle(NCollection_BaseAllocator)& theAllocator)
+:
+  myAllocator(theAllocator),
+  myFClass2dMap(100, myAllocator),
+  myProjPSMap(100, myAllocator),
+  myProjPCMap(100, myAllocator),
+  mySClassMap(100, myAllocator),
+  myProjPTMap(100, myAllocator),
+  myHatcherMap(100, myAllocator),
+  myProjSDataMap(100, myAllocator),
+  myBndBoxDataMap(100, myAllocator),
+  mySurfAdaptorMap(100, myAllocator),
+  myOBBMap(100, myAllocator),
+  myCreateFlag(1),
+  myPOnSTolerance(1.e-12)
 {
 }
 //=======================================================================
 //function : ~
 //purpose  : 
 //=======================================================================
-  IntTools_Context::~IntTools_Context()
+IntTools_Context::~IntTools_Context()
 {
   Standard_Address anAdr;
-  Standard_Integer i, aNb;
+  DataMapOfShapeAddress::Iterator aIt;
+  DataMapOfTransientAddress::Iterator aIt1;
   //
   IntTools_FClass2d* pFClass2d;
-  aNb=myFClass2dMap.Extent();
-  for (i=1; i<=aNb; ++i) {
-    anAdr=myFClass2dMap(i);
+  //
+  aIt.Initialize(myFClass2dMap);
+  for (; aIt.More(); aIt.Next()) {
+    anAdr=aIt.Value();
     pFClass2d=(IntTools_FClass2d*)anAdr;
-    delete pFClass2d;
+    (*pFClass2d).~IntTools_FClass2d();
+    myAllocator->Free(anAdr); 
   }
   myFClass2dMap.Clear();
   //
-  GeomAPI_ProjectPointOnSurf* pProjPS;
-  aNb=myProjPSMap.Extent();
-  for (i=1; i<=aNb; ++i) {
-    anAdr=myProjPSMap(i);
-    pProjPS=(GeomAPI_ProjectPointOnSurf*)anAdr;
-    delete pProjPS;
-  }
-  myProjPSMap.Clear();
+  clearCachedPOnSProjectors();
   //
   GeomAPI_ProjectPointOnCurve* pProjPC;
-  aNb=myProjPCMap.Extent();
-  for (i=1; i<=aNb; ++i) {
-    anAdr=myProjPCMap(i);
+  aIt.Initialize(myProjPCMap);
+  for (; aIt.More(); aIt.Next()) {
+    anAdr=aIt.Value();
     pProjPC=(GeomAPI_ProjectPointOnCurve*)anAdr;
-    delete pProjPC;
+    (*pProjPC).~GeomAPI_ProjectPointOnCurve();
+    myAllocator->Free(anAdr); 
   }
   myProjPCMap.Clear();
   //
+  //
+  BRepClass3d_SolidClassifier* pSC;
+  aIt.Initialize(mySClassMap);
+  for (; aIt.More(); aIt.Next()) {
+    anAdr=aIt.Value();
+    pSC=(BRepClass3d_SolidClassifier*)anAdr;
+    (*pSC).~BRepClass3d_SolidClassifier();
+    myAllocator->Free(anAdr); 
+  }
+  mySClassMap.Clear();
+  //
   GeomAPI_ProjectPointOnCurve* pProjPT;
-  aNb=myProjPTMap.Extent();
-  for (i=1; i<=aNb; ++i) {
-    anAdr=myProjPTMap(i);
+  aIt1.Initialize(myProjPTMap);
+  for (; aIt1.More(); aIt1.Next()) {
+    anAdr=aIt1.Value();
     pProjPT=(GeomAPI_ProjectPointOnCurve*)anAdr;
-    delete pProjPT;
+    (*pProjPT).~GeomAPI_ProjectPointOnCurve();
+    myAllocator->Free(anAdr); 
   }
   myProjPTMap.Clear();
   //
-  BRepClass3d_SolidClassifier* pSC;
-  aNb=mySClassMap.Extent();
-  for (i=1; i<=aNb; ++i) {
-    anAdr=mySClassMap(i);
-    pSC=(BRepClass3d_SolidClassifier*)anAdr;
-    delete pSC;
+  Geom2dHatch_Hatcher* pHatcher;
+  aIt.Initialize(myHatcherMap);
+  for (; aIt.More(); aIt.Next()) {
+    anAdr=aIt.Value();
+    pHatcher=(Geom2dHatch_Hatcher*)anAdr;
+    (*pHatcher).~Geom2dHatch_Hatcher();
+    myAllocator->Free(anAdr);
   }
-  mySClassMap.Clear();
+  myHatcherMap.Clear();
   //
   IntTools_SurfaceRangeLocalizeData* pSData = NULL;
-  aNb = myProjSDataMap.Extent();
-  for (i=1; i<=aNb; ++i) {
-    anAdr=myProjSDataMap(i);
+  aIt.Initialize(myProjSDataMap);
+  for (; aIt.More(); aIt.Next()) {
+    anAdr=aIt.Value();
     pSData = (IntTools_SurfaceRangeLocalizeData*)anAdr;
-    if(pSData)
-      delete pSData;
-    pSData = NULL;
+    (*pSData).~IntTools_SurfaceRangeLocalizeData();
+    myAllocator->Free(anAdr);
   }
   myProjSDataMap.Clear();
+  //
+  Bnd_Box* pBox;
+  aIt.Initialize(myBndBoxDataMap);
+  for (; aIt.More(); aIt.Next()) {
+    anAdr=aIt.Value();
+    pBox=(Bnd_Box*)anAdr;
+    (*pBox).~Bnd_Box();
+    myAllocator->Free(anAdr); 
+  }
+  myBndBoxDataMap.Clear();
+  //
+  BRepAdaptor_Surface* pSurfAdaptor;
+  aIt.Initialize(mySurfAdaptorMap);
+  for (; aIt.More(); aIt.Next()) {
+    anAdr=aIt.Value();
+    pSurfAdaptor=(BRepAdaptor_Surface*)anAdr;
+    (*pSurfAdaptor).~BRepAdaptor_Surface();
+    myAllocator->Free(anAdr);
+  }
+  mySurfAdaptorMap.Clear();
+  //
+  Bnd_OBB* pOBB;
+  aIt.Initialize(myOBBMap);
+  for (; aIt.More(); aIt.Next()) {
+    anAdr=aIt.Value();
+    pOBB=(Bnd_OBB*)anAdr;
+    (*pOBB).~Bnd_OBB();
+    myAllocator->Free(anAdr);
+  }
+  myOBBMap.Clear();
+}
+//=======================================================================
+//function : BndBox
+//purpose  : 
+//=======================================================================
+Bnd_Box& IntTools_Context::BndBox(const TopoDS_Shape& aS)
+{
+  Standard_Address anAdr;
+  Bnd_Box* pBox;
+  //
+  if (!myBndBoxDataMap.IsBound(aS)) {
+    //
+    pBox=(Bnd_Box*)myAllocator->Allocate(sizeof(Bnd_Box));
+    new (pBox) Bnd_Box();
+    //
+    Bnd_Box &aBox=*pBox;
+    BRepBndLib::Add(aS, aBox);
+    //
+    anAdr=(Standard_Address)pBox;
+    myBndBoxDataMap.Bind(aS, anAdr);
+  }
+  else {
+    anAdr=myBndBoxDataMap.Find(aS);
+    pBox=(Bnd_Box*)anAdr;
+  }
+  return *pBox;
+}
+//=======================================================================
+//function : IsInfiniteFace
+//purpose  : 
+//=======================================================================
+Standard_Boolean IntTools_Context::IsInfiniteFace
+  (const TopoDS_Face& aFace)
+{
+  const Bnd_Box& aBox = BndBox(aFace);
+  return aBox.IsOpenXmax() ||
+         aBox.IsOpenXmin() ||
+         aBox.IsOpenYmax() ||
+         aBox.IsOpenYmin() ||
+         aBox.IsOpenZmax() ||
+         aBox.IsOpenZmin();
 }
 //=======================================================================
 //function : FClass2d
 //purpose  : 
 //=======================================================================
-  IntTools_FClass2d& IntTools_Context::FClass2d(const TopoDS_Face& aF)
+IntTools_FClass2d& IntTools_Context::FClass2d(const TopoDS_Face& aF)
 {
   Standard_Address anAdr;
   IntTools_FClass2d* pFClass2d;
-  if (!myFClass2dMap.Contains(aF)) {
+  //
+  if (!myFClass2dMap.IsBound(aF)) {
     Standard_Real aTolF;
-    TopoDS_Face aFF=aF;
+    TopoDS_Face aFF;
+    //
+    aFF=aF;
     aFF.Orientation(TopAbs_FORWARD);
     aTolF=BRep_Tool::Tolerance(aFF);
     //
-    pFClass2d=new IntTools_FClass2d(aFF, aTolF);
+    pFClass2d=(IntTools_FClass2d*)myAllocator->Allocate(sizeof(IntTools_FClass2d));
+    new (pFClass2d) IntTools_FClass2d(aFF, aTolF);
     //
     anAdr=(Standard_Address)pFClass2d;
-    myFClass2dMap.Add(aFF, anAdr);
+    myFClass2dMap.Bind(aFF, anAdr);
   }
-
   else {
-    anAdr=myFClass2dMap.FindFromKey(aF);
+    anAdr=myFClass2dMap.Find(aF);
     pFClass2d=(IntTools_FClass2d*)anAdr;
   }
-
   return *pFClass2d;
 }
 //=======================================================================
 //function : ProjPS
 //purpose  : 
 //=======================================================================
-  GeomAPI_ProjectPointOnSurf& IntTools_Context::ProjPS(const TopoDS_Face& aF)
+GeomAPI_ProjectPointOnSurf& IntTools_Context::ProjPS(const TopoDS_Face& aF)
 {
   Standard_Address anAdr;
   GeomAPI_ProjectPointOnSurf* pProjPS;
  
-  if (!myProjPSMap.Contains(aF)) {
-    Standard_Real Umin, Usup, Vmin, Vsup, anEpsT=1.e-12 ;
-    BRepAdaptor_Surface aBAS;
-    //
+  if (!myProjPSMap.IsBound(aF)) {
+    Standard_Real Umin, Usup, Vmin, Vsup;
+    UVBounds(aF, Umin, Usup, Vmin, Vsup);
     const Handle(Geom_Surface)& aS=BRep_Tool::Surface(aF);
-    aBAS.Initialize (aF, Standard_True);
     //
-    Umin=aBAS.FirstUParameter();
-    Usup=aBAS.LastUParameter ();
-    Vmin=aBAS.FirstVParameter();
-    Vsup=aBAS.LastVParameter ();
-    //
-    pProjPS=new GeomAPI_ProjectPointOnSurf;
-    pProjPS->Init(aS ,Umin, Usup, Vmin, Vsup, anEpsT);
+    pProjPS=(GeomAPI_ProjectPointOnSurf*)myAllocator->Allocate(sizeof(GeomAPI_ProjectPointOnSurf));
+    new (pProjPS) GeomAPI_ProjectPointOnSurf();
+    pProjPS->Init(aS ,Umin, Usup, Vmin, Vsup, myPOnSTolerance);
+    pProjPS->SetExtremaFlag(Extrema_ExtFlag_MIN);
     //
     anAdr=(Standard_Address)pProjPS;
-    myProjPSMap.Add(aF, anAdr);
+    myProjPSMap.Bind(aF, anAdr);
   }
   
   else {
-    anAdr=myProjPSMap.FindFromKey(aF);
+    anAdr=myProjPSMap.Find(aF);
     pProjPS=(GeomAPI_ProjectPointOnSurf*)anAdr;
   }
   return *pProjPS;
 //function : ProjPC
 //purpose  : 
 //=======================================================================
-  GeomAPI_ProjectPointOnCurve& IntTools_Context::ProjPC(const TopoDS_Edge& aE)
+GeomAPI_ProjectPointOnCurve& IntTools_Context::ProjPC(const TopoDS_Edge& aE)
 {
   Standard_Address anAdr;
   GeomAPI_ProjectPointOnCurve* pProjPC;
  
-  if (!myProjPCMap.Contains(aE)) {
+  if (!myProjPCMap.IsBound(aE)) {
     Standard_Real f, l;
     //
     Handle(Geom_Curve)aC3D=BRep_Tool::Curve (aE, f, l);
     //
-    pProjPC=new GeomAPI_ProjectPointOnCurve;
+    pProjPC=(GeomAPI_ProjectPointOnCurve*)myAllocator->Allocate(sizeof(GeomAPI_ProjectPointOnCurve));
+    new (pProjPC) GeomAPI_ProjectPointOnCurve();
     pProjPC->Init(aC3D, f, l);
     //
     anAdr=(Standard_Address)pProjPC;
-    myProjPCMap.Add(aE, anAdr);
+    myProjPCMap.Bind(aE, anAdr);
   }
   
   else {
-    anAdr=myProjPCMap.FindFromKey(aE);
+    anAdr=myProjPCMap.Find(aE);
     pProjPC=(GeomAPI_ProjectPointOnCurve*)anAdr;
   }
   return *pProjPC;
 }
+
 //=======================================================================
 //function : ProjPT
 //purpose  : 
 //=======================================================================
-  GeomAPI_ProjectPointOnCurve& IntTools_Context::ProjPT(const Handle(Geom_Curve)& aC3D)
-                                                       
+GeomAPI_ProjectPointOnCurve& IntTools_Context::ProjPT
+  (const Handle(Geom_Curve)& aC3D)
+
 {
   Standard_Address anAdr;
   GeomAPI_ProjectPointOnCurve* pProjPT;
  
-  if (!myProjPTMap.Contains(aC3D)) {
+  if (!myProjPTMap.IsBound(aC3D)) {
     Standard_Real f, l;
     f=aC3D->FirstParameter();
     l=aC3D->LastParameter();
     //
-    pProjPT=new GeomAPI_ProjectPointOnCurve;
+    pProjPT=(GeomAPI_ProjectPointOnCurve*)myAllocator->Allocate(sizeof(GeomAPI_ProjectPointOnCurve));
+    new (pProjPT) GeomAPI_ProjectPointOnCurve();
     pProjPT->Init(aC3D, f, l);
     //
     anAdr=(Standard_Address)pProjPT;
-    myProjPTMap.Add(aC3D, anAdr);
+    myProjPTMap.Bind(aC3D, anAdr);
   }
   
   else {
-    anAdr=myProjPTMap.FindFromKey(aC3D);
+    anAdr=myProjPTMap.Find(aC3D);
     pProjPT=(GeomAPI_ProjectPointOnCurve*)anAdr;
   }
   return *pProjPT;
 }
 //=======================================================================
-//function : SurfaceData
+//function : SolidClassifier
 //purpose  : 
 //=======================================================================
-  IntTools_SurfaceRangeLocalizeData& IntTools_Context::SurfaceData(const TopoDS_Face& aF) 
+BRepClass3d_SolidClassifier& IntTools_Context::SolidClassifier
+  (const TopoDS_Solid& aSolid)
 {
   Standard_Address anAdr;
-  IntTools_SurfaceRangeLocalizeData* pSData;
+  BRepClass3d_SolidClassifier* pSC;
  
-  if (!myProjSDataMap.Contains(aF)) {
+  if (!mySClassMap.IsBound(aSolid)) {
     //
-    pSData=new IntTools_SurfaceRangeLocalizeData(3, 
-                                                3, 
-                                                10. * Precision::PConfusion(), 
-                                                10. * Precision::PConfusion());
+    pSC=(BRepClass3d_SolidClassifier*)myAllocator->Allocate(sizeof(BRepClass3d_SolidClassifier));
+    new (pSC) BRepClass3d_SolidClassifier(aSolid);
     //
-    anAdr=(Standard_Address)pSData;
-    myProjSDataMap.Add(aF, anAdr);
+    anAdr=(Standard_Address)pSC;
+    mySClassMap.Bind(aSolid, anAdr);
   }
   
   else {
-    anAdr=myProjSDataMap.FindFromKey(aF);
-    pSData=(IntTools_SurfaceRangeLocalizeData*)anAdr;
+    anAdr=mySClassMap.Find(aSolid);
+    pSC =(BRepClass3d_SolidClassifier*)anAdr;
   }
-  return *pSData;
-
+  return *pSC;
 }
+
 //=======================================================================
-//function : SolidClassifier
+//function : SurfaceAdaptor
 //purpose  : 
 //=======================================================================
-  BRepClass3d_SolidClassifier& IntTools_Context::SolidClassifier(const TopoDS_Solid& aSolid)
+BRepAdaptor_Surface& IntTools_Context::SurfaceAdaptor
+  (const TopoDS_Face& theFace)
 {
   Standard_Address anAdr;
-  BRepClass3d_SolidClassifier* pSC;
+  BRepAdaptor_Surface* pBAS;
  
-  if (!mySClassMap.Contains(aSolid)) {
+  if (!mySurfAdaptorMap.IsBound(theFace)) {
     //
-    pSC=new BRepClass3d_SolidClassifier(aSolid);
+    pBAS=(BRepAdaptor_Surface*)myAllocator->Allocate(sizeof(BRepAdaptor_Surface));
+    new (pBAS) BRepAdaptor_Surface(theFace, Standard_True);
     //
-    anAdr=(Standard_Address)pSC;
-    mySClassMap.Add(aSolid, anAdr);
+    anAdr=(Standard_Address)pBAS;
+    mySurfAdaptorMap.Bind(theFace, anAdr);
   }
   
   else {
-    anAdr=mySClassMap.FindFromKey(aSolid);
-    pSC =(BRepClass3d_SolidClassifier*)anAdr;
+    anAdr=mySurfAdaptorMap.Find(theFace);
+    pBAS =(BRepAdaptor_Surface*)anAdr;
   }
-  return *pSC;
+  return *pBAS;
 }
 
-
-//modified by NIZNHY-PKV Tue Feb  2 08:33:16 2010f
 //=======================================================================
-//function : ComputeVE
+//function : Hatcher
 //purpose  : 
 //=======================================================================
-  Standard_Integer IntTools_Context::ComputeVE(const TopoDS_Vertex& aV1, 
-                                              const TopoDS_Edge&   aE2,
-                                              Standard_Real& aT)
+Geom2dHatch_Hatcher& IntTools_Context::Hatcher(const TopoDS_Face& aF)
 {
-  Standard_Boolean bToUpdate;
-  Standard_Integer iFlag;
-  Standard_Real aDist;
+  Standard_Address anAdr;
+  Geom2dHatch_Hatcher* pHatcher;
   //
-  iFlag= IntTools_Context::ComputeVE(aV1, aE2, aT, bToUpdate, aDist);
+  if (!myHatcherMap.IsBound(aF)) {
+    Standard_Real aTolArcIntr, aTolTangfIntr, aTolHatch2D, aTolHatch3D;
+    Standard_Real aU1, aU2, aEpsT;
+    TopAbs_Orientation aOrE;
+    Handle(Geom_Surface) aS;
+    Handle(Geom2d_Curve) aC2D;
+    Handle(Geom2d_TrimmedCurve) aCT2D;
+    TopoDS_Face aFF;
+    TopExp_Explorer aExp;
+    //
+    aTolHatch2D=1.e-8;
+    aTolHatch3D=1.e-8;
+    aTolArcIntr=1.e-10;
+    aTolTangfIntr=1.e-10;
+    aEpsT=Precision::PConfusion();
+    //
+    Geom2dHatch_Intersector aIntr(aTolArcIntr, aTolTangfIntr);
+    pHatcher=(Geom2dHatch_Hatcher*)
+      myAllocator->Allocate(sizeof(Geom2dHatch_Hatcher));
+    new (pHatcher) Geom2dHatch_Hatcher(aIntr,
+                                       aTolHatch2D, aTolHatch3D,
+                                       Standard_True, Standard_False);
+    //
+    aFF=aF;
+    aFF.Orientation(TopAbs_FORWARD);
+    aS=BRep_Tool::Surface(aFF);
+
+    aExp.Init (aFF, TopAbs_EDGE);
+    for (; aExp.More() ; aExp.Next()) {
+      const TopoDS_Edge& aE=*((TopoDS_Edge*)&aExp.Current());
+      aOrE=aE.Orientation();
+      //
+      aC2D=BRep_Tool::CurveOnSurface (aE, aFF, aU1, aU2);
+      if (aC2D.IsNull() ) {
+        continue;
+      }
+      if (fabs(aU1-aU2) < aEpsT) {
+        continue;
+      }
+      //
+      aCT2D=new Geom2d_TrimmedCurve(aC2D, aU1, aU2);
+      Geom2dAdaptor_Curve aGAC (aCT2D);
+      pHatcher->AddElement(aGAC, aOrE);
+    }// for (; aExp.More() ; aExp.Next()) {
+    //
+    anAdr=(Standard_Address)pHatcher;
+    myHatcherMap.Bind(aFF, anAdr);
+  }//if (!myHatcherMap.IsBound(aF)) {
   //
-  return iFlag;
+  else {
+    anAdr=myHatcherMap.Find(aF);
+    pHatcher=(Geom2dHatch_Hatcher*)anAdr;
+  }
+
+  return *pHatcher;
 }
+
 //=======================================================================
-//function : ComputeVE
+//function : OBB
 //purpose  : 
 //=======================================================================
-  Standard_Integer IntTools_Context::ComputeVE(const TopoDS_Vertex& aV1, 
-                                              const TopoDS_Edge&   aE2,
-                                              Standard_Real& aT,
-                                              Standard_Boolean& bToUpdateVertex, 
-                                              Standard_Real& aDist)
+Bnd_OBB& IntTools_Context::OBB(const TopoDS_Shape& aS,
+                               const Standard_Real theGap)
 {
-  bToUpdateVertex=Standard_False;
-  aDist=0.;
+  Standard_Address anAdr;
+  Bnd_OBB* pBox;
   //
-  if (BRep_Tool::Degenerated(aE2)) {
-    return -1;
+  if (!myOBBMap.IsBound(aS))
+  {
+    pBox = (Bnd_OBB*)myAllocator->Allocate(sizeof(Bnd_OBB));
+    new (pBox) Bnd_OBB();
+    //
+    Bnd_OBB &aBox = *pBox;
+    BRepBndLib::AddOBB(aS, aBox);
+    aBox.Enlarge(theGap);
+    //
+    anAdr = (Standard_Address)pBox;
+    myOBBMap.Bind(aS, anAdr);
+  }
+  else
+  {
+    anAdr = myOBBMap.Find(aS);
+    pBox = (Bnd_OBB*)anAdr;
   }
+  return *pBox;
+}
+
+//=======================================================================
+//function : SurfaceData
+//purpose  : 
+//=======================================================================
+IntTools_SurfaceRangeLocalizeData& IntTools_Context::SurfaceData
+  (const TopoDS_Face& aF) 
+{
+  Standard_Address anAdr;
+  IntTools_SurfaceRangeLocalizeData* pSData;
+  //
+  if (!myProjSDataMap.IsBound(aF)) {
+    pSData=(IntTools_SurfaceRangeLocalizeData*)
+      myAllocator->Allocate(sizeof(IntTools_SurfaceRangeLocalizeData));
+    new (pSData) IntTools_SurfaceRangeLocalizeData
+      (3, 
+       3, 
+       10. * Precision::PConfusion(), 
+       10. * Precision::PConfusion());
+    //
+    anAdr=(Standard_Address)pSData;
+    myProjSDataMap.Bind(aF, anAdr);
+  }
+  
+  else {
+    anAdr=myProjSDataMap.Find(aF);
+    pSData=(IntTools_SurfaceRangeLocalizeData*)anAdr;
+  }
+  return *pSData;
+
+}
+
+//=======================================================================
+//function : ComputePE
+//purpose  : 
+//=======================================================================
+Standard_Integer IntTools_Context::ComputePE
+  (const gp_Pnt& aP1,
+   const Standard_Real aTolP1,
+   const TopoDS_Edge& aE2,
+   Standard_Real& aT,
+   Standard_Real& aDist)
+{
   if (!BRep_Tool::IsGeometric(aE2)) { 
     return -2;
   }
+  Standard_Real aTolE2, aTolSum;
+  Standard_Integer aNbProj;
   //
-  Standard_Real aTolV1, aTolE2, aTolSum, aTolVx;
+  GeomAPI_ProjectPointOnCurve& aProjector=ProjPC(aE2);
+  aProjector.Perform(aP1);
+
+  aNbProj=aProjector.NbPoints();
+  if (aNbProj)
+  {
+    // point falls on the curve
+    aDist = aProjector.LowerDistance();
+    //
+    aTolE2 = BRep_Tool::Tolerance(aE2);
+    aTolSum = aTolP1 + aTolE2 + Precision::Confusion();
+    //
+    aT = aProjector.LowerDistanceParameter();
+    if (aDist > aTolSum) {
+      return -4;
+    }
+  }
+  else
+  {
+    // point falls out of the curve, check distance to vertices
+    TopoDS_Edge aEFwd = TopoDS::Edge(aE2.Oriented(TopAbs_FORWARD));
+    TopoDS_Iterator itV(aEFwd);
+    aDist = RealLast();
+    for (; itV.More(); itV.Next())
+    {
+      const TopoDS_Vertex& aV = TopoDS::Vertex(itV.Value());
+      if (aV.Orientation() == TopAbs_FORWARD || aV.Orientation() == TopAbs_REVERSED)
+      {
+        gp_Pnt aPV = BRep_Tool::Pnt(aV);
+        aTolSum = aTolP1 + BRep_Tool::Tolerance(aV) + Precision::Confusion();
+        Standard_Real aDist1 = aP1.SquareDistance(aPV);
+        if (aDist1 < aDist && aDist1 < Square(aTolSum))
+        {
+          aDist = aDist1;
+          aT = BRep_Tool::Parameter(aV, aEFwd);
+        }
+      }
+    }
+    if (Precision::IsInfinite(aDist)) {
+      return -3;
+    }
+  }
+  return 0;
+}
+//=======================================================================
+//function : ComputeVE
+//purpose  : 
+//=======================================================================
+Standard_Integer IntTools_Context::ComputeVE
+  (const TopoDS_Vertex& theV, 
+   const TopoDS_Edge&   theE,
+   Standard_Real& theT,
+   Standard_Real& theTol,
+   const Standard_Real theFuzz)
+{
+  if (BRep_Tool::Degenerated(theE)) {
+    return -1;
+  }
+  if (!BRep_Tool::IsGeometric(theE)) { 
+    return -2;
+  }
+  Standard_Real aDist, aTolV, aTolE, aTolSum;
   Standard_Integer aNbProj;
   gp_Pnt aP;
   //
-  aP=BRep_Tool::Pnt(aV1);
+  aP=BRep_Tool::Pnt(theV);
   //
-  GeomAPI_ProjectPointOnCurve& aProjector=ProjPC(aE2);
+  GeomAPI_ProjectPointOnCurve& aProjector=ProjPC(theE);
   aProjector.Perform(aP);
+
   aNbProj=aProjector.NbPoints();
   if (!aNbProj) {
     return -3;
   }
   //
   aDist=aProjector.LowerDistance();
-  aTolV1=BRep_Tool::Tolerance(aV1);
-  aTolE2=BRep_Tool::Tolerance(aE2);
-  aTolSum=aTolV1+aTolE2;
   //
-  aT=aProjector.LowerDistanceParameter();
+  aTolV=BRep_Tool::Tolerance(theV);
+  aTolE=BRep_Tool::Tolerance(theE);
+  aTolSum = aTolV + aTolE + Max(theFuzz, Precision::Confusion());
+  //
+  theTol = aDist + aTolE;
+  theT = aProjector.LowerDistanceParameter();
   if (aDist > aTolSum) {
     return -4;
   }
-  //
-  aTolVx=aDist+aTolE2;
-  if (aTolVx>aTolV1) {
-    bToUpdateVertex=!bToUpdateVertex;
-    aDist=aTolVx;
-  }
-  //
   return 0;
 }
-//modified by NIZNHY-PKV Tue Feb  2 08:33:21 2010t
 //=======================================================================
-//function : ComputeVS
+//function : ComputeVF
 //purpose  : 
 //=======================================================================
-  Standard_Integer IntTools_Context::ComputeVS(const TopoDS_Vertex& aV1, 
-                                              const TopoDS_Face&   aF2,
-                                              Standard_Real& U,
-                                              Standard_Real& V)
+Standard_Integer IntTools_Context::ComputeVF
+  (const TopoDS_Vertex& theVertex, 
+   const TopoDS_Face&   theFace,
+   Standard_Real& theU,
+   Standard_Real& theV,
+   Standard_Real& theTol,
+   const Standard_Real theFuzz)
 {
-  Standard_Real aTolV1, aTolF2, aTolSum, aDist;
+  Standard_Real aTolV, aTolF, aTolSum, aDist;
   gp_Pnt aP;
 
-  aP=BRep_Tool::Pnt(aV1);
+  aP = BRep_Tool::Pnt(theVertex);
   //
   // 1. Check if the point is projectable on the surface
-  GeomAPI_ProjectPointOnSurf& aProjector=ProjPS(aF2);
+  GeomAPI_ProjectPointOnSurf& aProjector=ProjPS(theFace);
   aProjector.Perform(aP);
   //
-  if (!aProjector.IsDone()) {
-    // the point is not  projectable on the surface
+  if (!aProjector.IsDone()) { // the point is not  projectable on the surface
     return -1;
   }
   //
   // 2. Check the distance between the projection point and 
   //    the original point
-  aDist=aProjector.LowerDistance();
-
-  aTolV1=BRep_Tool::Tolerance(aV1);
-  aTolF2=BRep_Tool::Tolerance(aF2);
-  aTolSum=aTolV1+aTolF2;
+  aDist = aProjector.LowerDistance();
+  //
+  aTolV = BRep_Tool::Tolerance(theVertex);
+  aTolF = BRep_Tool::Tolerance(theFace);
+  //
+  aTolSum = aTolV + aTolF + Max(theFuzz, Precision::Confusion());
+  theTol = aDist + aTolF;
+  aProjector.LowerDistanceParameters(theU, theV);
+  //
   if (aDist > aTolSum) {
     // the distance is too large
     return -2;
   }
-  aProjector.LowerDistanceParameters(U, V);
   //
-  gp_Pnt2d aP2d(U, V);
-  Standard_Boolean pri=IsPointInFace (aF2, aP2d);
-  if (!pri) {
-    //  the point lays on the surface but out of the face 
+  gp_Pnt2d aP2d(theU, theV);
+  Standard_Boolean pri = IsPointInFace (theFace, aP2d);
+  if (!pri) {//  the point lays on the surface but out of the face 
     return -3;
   }
   return 0;
 //function : StatePointFace
 //purpose  : 
 //=======================================================================
-  TopAbs_State IntTools_Context::StatePointFace(const TopoDS_Face& aF,
-                                               const gp_Pnt2d& aP2d)
+TopAbs_State IntTools_Context::StatePointFace
+  (const TopoDS_Face& aF,
+   const gp_Pnt2d& aP2d)
 {
   TopAbs_State aState;
   IntTools_FClass2d& aClass2d=FClass2d(aF);
 //function : IsPointInFace
 //purpose  : 
 //=======================================================================
-  Standard_Boolean IntTools_Context::IsPointInFace(const TopoDS_Face& aF,
-                                                  const gp_Pnt2d& aP2d)
+Standard_Boolean IntTools_Context::IsPointInFace
+  (const TopoDS_Face& aF,
+   const gp_Pnt2d& aP2d)
 {
   TopAbs_State aState=StatePointFace(aF, aP2d);
   if (aState==TopAbs_OUT || aState==TopAbs_ON) {
   return Standard_True;
 }
 //=======================================================================
+//function : IsPointInFace
+//purpose  : 
+//=======================================================================
+Standard_Boolean IntTools_Context::IsPointInFace
+  (const gp_Pnt& aP,
+   const TopoDS_Face& aF,
+   const Standard_Real aTol) 
+{
+  Standard_Boolean bIn;
+  Standard_Real aDist;
+  //
+  GeomAPI_ProjectPointOnSurf& aProjector=ProjPS(aF);
+  aProjector.Perform(aP);
+  //
+  bIn = aProjector.IsDone();
+  if (bIn) {
+    aDist = aProjector.LowerDistance();
+    if (aDist < aTol) {
+      Standard_Real U, V;
+      //
+      aProjector.LowerDistanceParameters(U, V);
+      gp_Pnt2d aP2D(U, V);
+      bIn = IsPointInFace(aF, aP2D);
+    }
+  }
+  //
+  return bIn;
+}
+//=======================================================================
 //function : IsPointInOnFace
 //purpose  : 
 //=======================================================================
   Standard_Boolean IntTools_Context::IsPointInOnFace(const TopoDS_Face& aF,
-                                                    const gp_Pnt2d& aP2d)
+                                                   const gp_Pnt2d& aP2d)
 { 
   TopAbs_State aState=StatePointFace(aF, aP2d);
   if (aState==TopAbs_OUT) {
 //function : IsValidPointForFace
 //purpose  : 
 //=======================================================================
-  Standard_Boolean IntTools_Context::IsValidPointForFace(const gp_Pnt& aP,
-                                                        const TopoDS_Face& aF,
-                                                        const Standard_Real aTol) 
+Standard_Boolean IntTools_Context::IsValidPointForFace
+  (const gp_Pnt& aP,
+   const TopoDS_Face& aF,
+   const Standard_Real aTol) 
 {
   Standard_Boolean bFlag;
-  Standard_Real Umin, myEpsT, U, V;
-  myEpsT=1.e-12;
+  Standard_Real Umin, U, V;
 
   GeomAPI_ProjectPointOnSurf& aProjector=ProjPS(aF);
   aProjector.Perform(aP);
 //function : IsValidPointForFaces
 //purpose  : 
 //=======================================================================
-  Standard_Boolean IntTools_Context::IsValidPointForFaces (const gp_Pnt& aP,
-                                                          const TopoDS_Face& aF1,
-                                                          const TopoDS_Face& aF2,
-                                                          const Standard_Real aTol) 
+Standard_Boolean IntTools_Context::IsValidPointForFaces 
+  (const gp_Pnt& aP,
+   const TopoDS_Face& aF1,
+   const TopoDS_Face& aF2,
+   const Standard_Real aTol) 
 {
   Standard_Boolean bFlag1, bFlag2;
 
 //function : IsValidBlockForFace
 //purpose  : 
 //=======================================================================
-  Standard_Boolean IntTools_Context::IsValidBlockForFace (const Standard_Real aT1,
-                                                         const Standard_Real aT2,
-                                                         const IntTools_Curve& aC, 
-                                                         const TopoDS_Face& aF,
-                                                         const Standard_Real aTol) 
+Standard_Boolean IntTools_Context::IsValidBlockForFace 
+  (const Standard_Real aT1,
+   const Standard_Real aT2,
+   const IntTools_Curve& aC, 
+   const TopoDS_Face& aF,
+   const Standard_Real aTol) 
 {
   Standard_Boolean bFlag;
-  Standard_Real aTInterm, aFirst, aLast;
+  Standard_Real aTInterm;
   gp_Pnt aPInterm;
 
   aTInterm=IntTools_Tools::IntermediatePoint(aT1, aT2);
 
   Handle(Geom_Curve) aC3D=aC.Curve();
-  aFirst=aC3D->FirstParameter();
-  aLast =aC3D->LastParameter();
   // point 3D
   aC3D->D0(aTInterm, aPInterm);
   //
 //function : IsValidBlockForFaces
 //purpose  : 
 //=======================================================================
-  Standard_Boolean IntTools_Context::IsValidBlockForFaces (const Standard_Real aT1,
-                                                          const Standard_Real aT2,
-                                                          const IntTools_Curve& aC, 
-                                                          const TopoDS_Face& aF1,
-                                                          const TopoDS_Face& aF2,
-                                                          const Standard_Real aTol) 
+Standard_Boolean IntTools_Context::IsValidBlockForFaces(const Standard_Real theT1,
+                                                        const Standard_Real theT2,
+                                                        const IntTools_Curve& theC, 
+                                                        const TopoDS_Face& theF1,
+                                                        const TopoDS_Face& theF2,
+                                                        const Standard_Real theTol) 
 {
-  Standard_Boolean bFlag1, bFlag2;
-  //
-  Handle(Geom2d_Curve) aPC1 = aC.FirstCurve2d();
-  Handle(Geom2d_Curve) aPC2 = aC.SecondCurve2d();
-  if( !aPC1.IsNull() && !aPC2.IsNull() ) {
-    Standard_Real aMidPar = IntTools_Tools::IntermediatePoint(aT1, aT2);
-    gp_Pnt2d aPnt2D;
+  const Standard_Integer aNbElem = 2;
+  const Handle(Geom2d_Curve) &aPC1 = theC.FirstCurve2d();
+  const Handle(Geom2d_Curve) &aPC2 = theC.SecondCurve2d();
+  const Handle(Geom_Curve)   &aC3D = theC.Curve();
+  
+  const Handle(Geom2d_Curve)* anArrPC[aNbElem] = { &aPC1, &aPC2 };
+  const TopoDS_Face* anArrF[aNbElem] = { &theF1, &theF2 };
 
+  const Standard_Real aMidPar = IntTools_Tools::IntermediatePoint(theT1, theT2);
+  const gp_Pnt aP(aC3D->Value(aMidPar));
 
-    aPC1->D0(aMidPar, aPnt2D);
-    bFlag1 = IsPointInOnFace(aF1, aPnt2D);
+  Standard_Boolean bFlag = Standard_True;  
+  gp_Pnt2d aPnt2D;  
 
-    if( !bFlag1 )
-      return bFlag1;
+  for (Standard_Integer i = 0; (i < 2) && bFlag; ++i)
+  {
+    const Handle(Geom2d_Curve) &aPC = *anArrPC[i];
+    const TopoDS_Face &aF           = *anArrF[i];
 
-    aPC2->D0(aMidPar, aPnt2D);
-    bFlag2 = IsPointInOnFace(aF2, aPnt2D);
-    return bFlag2;
+    if (!aPC.IsNull())
+    {
+      aPC->D0(aMidPar, aPnt2D);
+      bFlag = IsPointInOnFace(aF, aPnt2D);
+    }
+    else
+    {
+      bFlag = IsValidPointForFace(aP, aF, theTol);
+    }
   }
-  //
 
-  bFlag1=IsValidBlockForFace (aT1, aT2, aC, aF1, aTol);
-  if (!bFlag1) {
-    return bFlag1;
-  }
-  bFlag2=IsValidBlockForFace (aT1, aT2, aC, aF2, aTol);
-  return bFlag2;
+  return bFlag;
 }
 //=======================================================================
 //function : IsVertexOnLine
 //purpose  : 
 //=======================================================================
-  Standard_Boolean IntTools_Context::IsVertexOnLine (const TopoDS_Vertex& aV,
-                                                    const IntTools_Curve& aC, 
-                                                    const Standard_Real aTolC,
-                                                    Standard_Real& aT)
+Standard_Boolean IntTools_Context::IsVertexOnLine 
+  (const TopoDS_Vertex& aV,
+   const IntTools_Curve& aC, 
+   const Standard_Real aTolC,
+   Standard_Real& aT)
 {
   Standard_Boolean bRet;
   Standard_Real aTolV;
 //function : IsVertexOnLine
 //purpose  : 
 //=======================================================================
-  Standard_Boolean IntTools_Context::IsVertexOnLine (const TopoDS_Vertex& aV,
-                                                    const Standard_Real aTolV,
-                                                    const IntTools_Curve& aC, 
-                                                    const Standard_Real aTolC,
-                                                    Standard_Real& aT)
+Standard_Boolean IntTools_Context::IsVertexOnLine 
+  (const TopoDS_Vertex& aV,
+   const Standard_Real aTolV,
+   const IntTools_Curve& aC, 
+   const Standard_Real aTolC,
+   Standard_Real& aT)
 {
   Standard_Real aFirst, aLast, aDist, aTolSum;
   Standard_Integer aNbProj;
   aFirst=aC3D->FirstParameter();
   aLast =aC3D->LastParameter();
   //
-  //Checking extermities first
+  // Checking extermities first
+  // It is necessary to chose the closest bound to the point
+  Standard_Boolean bFirstValid = Standard_False;
+  Standard_Real aFirstDist = Precision::Infinite();
+  //
   if (!Precision::IsInfinite(aFirst)) {
     gp_Pnt aPCFirst=aC3D->Value(aFirst);
-    aDist=aPv.Distance(aPCFirst);
-    if (aDist < aTolSum) {
+    aFirstDist = aPv.Distance(aPCFirst);
+    if (aFirstDist < aTolSum) {
+      bFirstValid = Standard_True;
       aT=aFirst;
       //
-      if(aDist > aTolV) {
-       Extrema_LocateExtPC anExt(aPv, aGAC, aFirst, 1.e-10);
+      if (aFirstDist > aTolV) {
+        Extrema_LocateExtPC anExt(aPv, aGAC, aFirst, 1.e-10);
+        
+        if(anExt.IsDone()) {
+          Extrema_POnCurv aPOncurve = anExt.Point();
+          aT = aPOncurve.Parameter();
+          
+          if((aT > (aLast + aFirst) * 0.5) ||
+             (aPv.Distance(aPOncurve.Value()) > aTolSum) ||
+             (aPCFirst.Distance(aPOncurve.Value()) < Precision::Confusion()))
+            aT = aFirst;
+        }
+        else
+        {
+          // Local search may fail. Try to use more precise algo.
+          Extrema_ExtPC anExt2(aPv, aGAC, 1.e-10);
+          Standard_Real aMinDist = RealLast();
+          Standard_Integer aMinIdx = -1;
+          if (anExt2.IsDone()) {
+            for (Standard_Integer anIdx = 1; anIdx <= anExt2.NbExt(); anIdx++)
+            {
+              if ( anExt2.IsMin(anIdx) &&
+                   anExt2.SquareDistance(anIdx) < aMinDist )
+              {
+                aMinDist = anExt2.SquareDistance(anIdx);
+                aMinIdx = anIdx;
+              }
+            }
+          }
+          if (aMinIdx != -1)
+          {
+            const Extrema_POnCurv& aPOncurve = anExt2.Point(aMinIdx);
+            aT = aPOncurve.Parameter();
 
-       if(anExt.IsDone()) {
-         Extrema_POnCurv aPOncurve = anExt.Point();
-         aT = aPOncurve.Parameter();
+            if((aT > (aLast + aFirst) * 0.5) ||
+              (aPv.Distance(aPOncurve.Value()) > aTolSum) ||
+              (aPCFirst.Distance(aPOncurve.Value()) < Precision::Confusion()))
+              aT = aFirst;
+          }
+        }
 
-         if((aT > (aLast + aFirst) * 0.5) ||
-            (aPv.Distance(aPOncurve.Value()) > aTolSum) ||
-            (aPCFirst.Distance(aPOncurve.Value()) < Precision::Confusion()))
-           aT = aFirst;
-       }
       }
-      //
-      return Standard_True;
     }
   }
   //
   if (!Precision::IsInfinite(aLast)) {
     gp_Pnt aPCLast=aC3D->Value(aLast);
     aDist=aPv.Distance(aPCLast);
+    if (bFirstValid && (aFirstDist < aDist)) {
+      return Standard_True;
+    }
+    //
     if (aDist < aTolSum) {
       aT=aLast;
       //
       if(aDist > aTolV) {
-       Extrema_LocateExtPC anExt(aPv, aGAC, aLast, 1.e-10);
+        Extrema_LocateExtPC anExt(aPv, aGAC, aLast, 1.e-10);
+        
+        if(anExt.IsDone()) {
+          Extrema_POnCurv aPOncurve = anExt.Point();
+          aT = aPOncurve.Parameter();
+          
+          if((aT < (aLast + aFirst) * 0.5) ||
+             (aPv.Distance(aPOncurve.Value()) > aTolSum) ||
+             (aPCLast.Distance(aPOncurve.Value()) < Precision::Confusion()))
+            aT = aLast;
+        }
+        else
+        {
+          // Local search may fail. Try to use more precise algo.
+          Extrema_ExtPC anExt2(aPv, aGAC, 1.e-10);
+          Standard_Real aMinDist = RealLast();
+          Standard_Integer aMinIdx = -1;
+          if (anExt2.IsDone()) {
+            for (Standard_Integer anIdx = 1; anIdx <= anExt2.NbExt(); anIdx++)
+            {
+              if ( anExt2.IsMin(anIdx) &&
+                   anExt2.SquareDistance(anIdx) < aMinDist )
+              {
+                aMinDist = anExt2.SquareDistance(anIdx);
+                aMinIdx = anIdx;
+              }
+            }
+          }
+          if (aMinIdx != -1)
+          {
+            const Extrema_POnCurv& aPOncurve = anExt2.Point(aMinIdx);
+            aT = aPOncurve.Parameter();
 
-       if(anExt.IsDone()) {
-         Extrema_POnCurv aPOncurve = anExt.Point();
-         aT = aPOncurve.Parameter();
-
-         if((aT < (aLast + aFirst) * 0.5) ||
-            (aPv.Distance(aPOncurve.Value()) > aTolSum) ||
-            (aPCLast.Distance(aPOncurve.Value()) < Precision::Confusion()))
-           aT = aLast;
-       }
+            if((aT < (aLast + aFirst) * 0.5) ||
+              (aPv.Distance(aPOncurve.Value()) > aTolSum) ||
+              (aPCLast.Distance(aPOncurve.Value()) < Precision::Confusion()))
+              aT = aLast;
+          }
+        }
       }
       //
       return Standard_True;
     }
   }
+  else if (bFirstValid) {
+    return Standard_True;
+  }
   //
   GeomAPI_ProjectPointOnCurve& aProjector=ProjPT(aC3D);
   aProjector.Perform(aPv);
       
       aDist=aPv.Distance(aPStart);
       if (aDist < aTolSum) {
-       aT=aFirst;
-       return Standard_True;
+        aT=aFirst;
+        return Standard_True;
       }
       
       aDist=aPv.Distance(aPEnd);
       if (aDist < aTolSum) {
-       aT=aLast;
-       return Standard_True;
+        aT=aLast;
+        return Standard_True;
       }
     }
     
 //function : ProjectPointOnEdge
 //purpose  : 
 //=======================================================================
-  Standard_Boolean IntTools_Context::ProjectPointOnEdge(const gp_Pnt& aP,
-                                                       const TopoDS_Edge& anEdge,
-                                                       Standard_Real& aT)
+Standard_Boolean IntTools_Context::ProjectPointOnEdge
+  (const gp_Pnt& aP,
+   const TopoDS_Edge& anEdge,
+   Standard_Real& aT)
 {
   Standard_Integer aNbPoints;
 
   return Standard_False;
 }
 
+//=======================================================================
+//function : SetPOnSProjectionTolerance
+//purpose  : 
+//=======================================================================
+void IntTools_Context::SetPOnSProjectionTolerance(const Standard_Real theValue)
+{
+  myPOnSTolerance = theValue;
+  clearCachedPOnSProjectors();
+}
+
+//=======================================================================
+//function : clearCachedPOnSProjectors
+//purpose  : 
+//=======================================================================
+void IntTools_Context::clearCachedPOnSProjectors()
+{
+  GeomAPI_ProjectPointOnSurf* pProjPS;
+  DataMapOfShapeAddress::Iterator aIt(myProjPSMap);
+  for (; aIt.More(); aIt.Next()) {
+    Standard_Address anAdr=aIt.Value();
+    pProjPS=(GeomAPI_ProjectPointOnSurf*)anAdr;
+    (*pProjPS).~GeomAPI_ProjectPointOnSurf();
+    myAllocator->Free(anAdr); 
+  }
+  myProjPSMap.Clear();
+}
+
+//=======================================================================
+//function : UVBounds
+//purpose  : 
+//=======================================================================
+void IntTools_Context::UVBounds(const TopoDS_Face& theFace,
+                                Standard_Real& UMin,
+                                Standard_Real& UMax,
+                                Standard_Real& VMin,
+                                Standard_Real& VMax)
+{
+  const BRepAdaptor_Surface& aBAS = SurfaceAdaptor(theFace);
+  UMin = aBAS.FirstUParameter();
+  UMax = aBAS.LastUParameter ();
+  VMin = aBAS.FirstVParameter();
+  VMax = aBAS.LastVParameter ();
+}
\ No newline at end of file