]> OCCT Git - occt.git/commitdiff
0028866: Modeling Data - Problem with GeomAPI_ProjectPointOnSurf IR-2022-04-22
authorifv <ifv@opencascade.com>
Sun, 17 Apr 2022 12:38:34 +0000 (15:38 +0300)
committersmoskvin <smoskvin@opencascade.com>
Fri, 22 Apr 2022 15:51:27 +0000 (18:51 +0300)
Extrema/Extrema_GenExtPS.cxx - adaptive setting of sample points is implemented
bugs/moddata_3/bug28866 - test case added

src/Extrema/Extrema_GenExtPS.cxx
tests/bugs/moddata_3/bug28866 [new file with mode: 0644]

index 3770bb1b64885a9d8b3bbb2cd070eeb2500f2133..ed2b6373bcfce3744b6622c6af8ea5d2d54b4d93 100644 (file)
@@ -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 (file)
index 0000000..ab59a6b
--- /dev/null
@@ -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)"
+ }
+}