From a0b4fff17a6ad88f569052733d24723dd53e0919 Mon Sep 17 00:00:00 2001 From: ifv Date: Sun, 17 Apr 2022 15:38:34 +0300 Subject: [PATCH] 0028866: Modeling Data - Problem with GeomAPI_ProjectPointOnSurf Extrema/Extrema_GenExtPS.cxx - adaptive setting of sample points is implemented bugs/moddata_3/bug28866 - test case added --- src/Extrema/Extrema_GenExtPS.cxx | 115 +++++++++++++++++++++++++++---- tests/bugs/moddata_3/bug28866 | 28 ++++++++ 2 files changed, 131 insertions(+), 12 deletions(-) create mode 100644 tests/bugs/moddata_3/bug28866 diff --git a/src/Extrema/Extrema_GenExtPS.cxx b/src/Extrema/Extrema_GenExtPS.cxx index 3770bb1b64..ed2b6373bc 100644 --- a/src/Extrema/Extrema_GenExtPS.cxx +++ b/src/Extrema/Extrema_GenExtPS.cxx @@ -715,23 +715,114 @@ void Extrema_GenExtPS::BuildGrid(const gp_Pnt &thePoint) } } -// Parametrization of the sample +static Standard_Real LengthOfIso(const Adaptor3d_Surface& theS, const GeomAbs_IsoType theIso, + const Standard_Real thePar1, const Standard_Real thePar2, + const Standard_Integer theNbPnts, const Standard_Real thePar) +{ + Standard_Real aLen = 0.; + Standard_Integer i; + Standard_Real dPar = (thePar2 - thePar1) / (theNbPnts - 1); + gp_Pnt aP1, aP2; + Standard_Real aPar = thePar1 + dPar; + if(theIso == GeomAbs_IsoU) + { + aP1 = theS.Value(thePar, thePar1); + } + else + { + aP1 = theS.Value(thePar1, thePar); + } + + for (i = 2; i <= theNbPnts; ++i) + { + if (theIso == GeomAbs_IsoU) + { + aP2 = theS.Value(thePar, aPar); + } + else + { + aP2 = theS.Value(aPar, thePar); + } + aLen += aP1.Distance(aP2); + aP1 = aP2; + aPar += dPar; + } + return aLen; +} +static void CorrectNbSamples(const Adaptor3d_Surface& theS, + const Standard_Real theU1, const Standard_Real theU2, Standard_Integer& theNbU, + const Standard_Real theV1, const Standard_Real theV2, Standard_Integer& theNbV) +{ + Standard_Real aMinLen = 1.e-3; + Standard_Integer nbp = Min(23, theNbV); + Standard_Real aLenU1 = LengthOfIso(theS, GeomAbs_IsoU, theV1, theV2, nbp, theU1); + if (aLenU1 <= aMinLen) + { + Standard_Real aL = LengthOfIso(theS, GeomAbs_IsoU, theV1, theV2, nbp, .7*theU1 + 0.3*theU2); + aLenU1 = Max(aL, aLenU1); + } + Standard_Real aLenU2 = LengthOfIso(theS, GeomAbs_IsoU, theV1, theV2, nbp, theU2); + if (aLenU2 <= aMinLen) + { + Standard_Real aL = LengthOfIso(theS, GeomAbs_IsoU, theV1, theV2, nbp, .3*theU1 + 0.7*theU2); + aLenU2 = Max(aL, aLenU2); + } + nbp = Min(23, theNbV); + Standard_Real aLenV1 = LengthOfIso(theS, GeomAbs_IsoV, theU1, theU2, nbp, theV1); + if (aLenV1 <= aMinLen) + { + Standard_Real aL = LengthOfIso(theS, GeomAbs_IsoV, theU1, theU2, nbp, .7*theV1 + 0.3*theV2); + aLenV1 = Max(aL, aLenV1); + } + Standard_Real aLenV2 = LengthOfIso(theS, GeomAbs_IsoV, theU1, theU2, nbp, theV2); + if (aLenV2 <= aMinLen) + { + Standard_Real aL = LengthOfIso(theS, GeomAbs_IsoV, theU1, theU2, nbp, .3*theV1 + 0.7*theV2); + aLenV2 = Max(aL, aLenV2); + } + // + Standard_Real aStepV1 = aLenU1 / theNbV; + Standard_Real aStepV2 = aLenU2 / theNbV; + Standard_Real aStepU1 = aLenV1 / theNbU; + Standard_Real aStepU2 = aLenV2 / theNbU; + + Standard_Real aMaxStepV = Max(aStepV1, aStepV2); + Standard_Real aMaxStepU = Max(aStepU1, aStepU2); + // + Standard_Real aRatio = aMaxStepV / aMaxStepU; + if (aRatio > 10.) + { + Standard_Integer aMult = RealToInt(Log(aRatio) ); + if(aMult > 1) + theNbV *= aMult; + } + else if (aRatio < 0.1) + { + Standard_Integer aMult = RealToInt( - Log(aRatio)); + if(aMult > 1) + theNbV *= aMult; + } + +} void Extrema_GenExtPS::BuildTree() { // if tree already exists, assume it is already correctly filled - if ( ! mySphereUBTree.IsNull() ) + if (!mySphereUBTree.IsNull()) return; - if (myS->GetType() == GeomAbs_BSplineSurface) { - Handle(Geom_BSplineSurface) aBspl = myS->BSpline(); - Standard_Integer aUValue = aBspl->UDegree() * aBspl->NbUKnots(); - Standard_Integer aVValue = aBspl->VDegree() * aBspl->NbVKnots(); - if (aUValue > myusample) - myusample = aUValue; - if (aVValue > myvsample) - myvsample = aVValue; - } - + if (myS->GetType() == GeomAbs_BSplineSurface) { + Handle(Geom_BSplineSurface) aBspl = myS->BSpline(); + Standard_Integer aUValue = aBspl->UDegree() * aBspl->NbUKnots(); + Standard_Integer aVValue = aBspl->VDegree() * aBspl->NbVKnots(); + // 300 is value, which is used for singular points (see Extrema_ExtPS.cxx::Initialize(...)) + if (aUValue > myusample) + myusample = Min(aUValue, 300); + if (aVValue > myvsample) + myvsample = Min(aVValue, 300); + } + // + CorrectNbSamples(*myS, myumin, myusup, myusample, myvmin, myvsup, myvsample); + // Standard_Real PasU = myusup - myumin; Standard_Real PasV = myvsup - myvmin; Standard_Real U0 = PasU / myusample / 100.; diff --git a/tests/bugs/moddata_3/bug28866 b/tests/bugs/moddata_3/bug28866 new file mode 100644 index 0000000000..ab59a6b276 --- /dev/null +++ b/tests/bugs/moddata_3/bug28866 @@ -0,0 +1,28 @@ +puts "========" +puts "0028866: Modeling Data - Problem with GeomAPI_ProjectPointOnSurf" +puts "========" +puts "" + +restore [locate_data_file bug28866.brep] f + +set CMP_TOL 5.0e-7 + +point p1 -0.028128 -0.836810 -0.019004 +point p2 -0.028128 0.836810 -0.019004 +point p3 -0.040434 -0.836810 -0.019022 +point p4 -0.040434 0.836810 -0.019022 +point p5 -0.031644 -0.819230 -0.018362 +point p6 -0.045708 0.835050 -0.018969 +point p7 0.086142 -0.606510 -0.009508 + +set pnts {"p1" "p2" "p3" "p4" "p5" "p6" "p7"} + +foreach pnt ${pnts} { + set log [projponf f $pnt -min -t] + regexp {proj dist = ([-0-9.+eE]+)} ${log} full distmax + if { ${distmax} > ${CMP_TOL} } { + puts "Error: Wrong distanse ($pnt)" + } else { + puts "OK: Good distanse ($pnt)" + } +}