+//=======================================================================
+//function : preciseU
+//purpose : find u such that the 3D point on theE is just out of tolerance
+// of theV
+//=======================================================================
+
+static Standard_Real preciseU (const BRepAdaptor_Surface& theSurf,
+ const TopoDS_Edge& theE,
+ const TopoDS_Vertex& theV,
+ const Handle(Geom2d_Curve)& theC,
+ const Standard_Boolean theFirstEnd)
+{
+ Standard_Boolean isForward = ( theE.Orientation () == TopAbs_FORWARD );
+ if (theFirstEnd) isForward = !isForward;
+
+ // find the first point in 2d and 3d
+ Standard_Real f,l;
+ BRep_Tool::Range( theE, f, l );
+ Standard_Real u0 = isForward ? l : f;
+ gp_Pnt2d aP2d0 = theC->Value( u0 );
+ gp_Pnt aPnt0 = theSurf.Value( aP2d0.X(), aP2d0.Y() );
+
+ // shift in 2d and 3d
+ Standard_Real du = ( l - f ) / 100, du3d = 0;
+ if (isForward)
+ du = -du;
+
+ // target parameter
+ Standard_Real u;
+
+ while (du3d < ::RealSmall())
+ {
+ // u for test
+ u = u0 + du;
+ du *= 10; // for the next iteration: increase du untill du3d is large enough
+
+ // find out how u is far from u0 in 3D
+ gp_Pnt2d aP2d = theC->Value( u );
+ gp_Pnt aPnt = theSurf.Value( aP2d.X(), aP2d.Y() );
+ du3d = aPnt0.Distance( aPnt );
+ }
+
+ // find u such that the 3D point is just out of tolerance of theV
+ Standard_Real tolV = BRep_Tool::Tolerance( theV ) + Precision::Confusion();
+ u = u0 + du * tolV / du3d;
+
+ // check that u is within the range
+ if ( isForward ? (u < f) : (u > l) )
+ u = u0 + du;
+
+ return u;
+}
+