0027135: Incorrect result of the normal projection algorithm
authoraml <aml@opencascade.com>
Thu, 11 Feb 2016 10:38:55 +0000 (13:38 +0300)
committerabv <abv@opencascade.com>
Sat, 20 Feb 2016 16:13:11 +0000 (19:13 +0300)
New check for possible local traps was added to build correct projection cache.

src/ProjLib/ProjLib_CompProjectedCurve.cxx
src/ProjLib/ProjLib_CompProjectedCurve.hxx
tests/bugs/moddata_3/bug27135 [new file with mode: 0644]

index 3f9f2ca..cca8a61 100644 (file)
@@ -624,8 +624,8 @@ void ProjLib_CompProjectedCurve::Init()
   //Basic loop  
   while(t <= LastU) 
   {
-    //Search for the begining a new continuous part
-    //To avoid infinite computation in some difficult cases
+    // Search for the beginning of a new continuous part
+    // to avoid infinite computation in some difficult cases.
     new_part = Standard_False;
     if(t > FirstU && Abs(t-prevDeb) <= Precision::PConfusion()) SameDeb=Standard_True;
     while(t <= LastU && !new_part && !FromLastU && !SameDeb)
@@ -637,7 +637,7 @@ void ProjLib_CompProjectedCurve::Init()
       gp_Pnt CPoint;
       Standard_Real ParT,ParU,ParV; 
 
-      // Search an initpoint in the list of Extrema Curve-Surface
+      // Search an initial point in the list of Extrema Curve-Surface
       if(Nend != 0 && !CExt.IsParallel()) 
       {
         for (i=1;i<=Nend;i++)
@@ -861,27 +861,12 @@ void ProjLib_CompProjectedCurve::Init()
         prevStep = Step;
         Triple = gp_Pnt(t, aPrjPS.Solution().X(), aPrjPS.Solution().Y());
 
-        if (mySurface->GetType() == GeomAbs_SurfaceOfRevolution &&
-           (Abs (Triple.Z() - mySurface->FirstVParameter()) < Precision::Confusion() ||
-            Abs (Triple.Z() - mySurface->LastVParameter() ) < Precision::Confusion() ))
-        {
-          // Go out from possible attraktor.
-
-          Standard_Real U,V;
-          InitialPoint(myCurve->Value(t), t, myCurve, mySurface, myTolU, myTolV, U, V);
-          if (Abs (Abs(U - Triple.Y()) - mySurface->UPeriod()) < Precision::Confusion())
-          {
-            // Handle period jump.
-            U = Triple.Y();
-          }
-          Triple.SetY(U);
-          Triple.SetZ(V);
-        }
+        // Check for possible local traps.
+        UpdateTripleByTrapCriteria(Triple);
 
         if((Triple.X() - mySequence->Value(myNbCurves)->Value(mySequence->Value(myNbCurves)->Length()).X()) > 1.e-10)
           mySequence->Value(myNbCurves)->Append(Triple);
         if (t == LastU) {t = LastU + 1; break;}//return;
-
         //Computation of WalkStep
         d2CurvOnSurf(Triple.X(), Triple.Y(), Triple.Z(), D1, D2, myCurve, mySurface);
         MagnD1 = D1.Magnitude();
@@ -899,7 +884,7 @@ void ProjLib_CompProjectedCurve::Init()
       }
     }
   }
-  // Sequence postproceeding
+  // Sequence post-proceeding.
   Standard_Integer j;
 
   // 1. Removing poor parts
@@ -1622,3 +1607,57 @@ GeomAbs_CurveType ProjLib_CompProjectedCurve::GetType() const
 {
   return GeomAbs_OtherCurve;
 }
+
+//=======================================================================
+//function : UpdateTripleByTrapCriteria
+//purpose  :
+//=======================================================================
+void ProjLib_CompProjectedCurve::UpdateTripleByTrapCriteria(gp_Pnt &thePoint) const
+{
+  Standard_Boolean isProblemsPossible = Standard_False;
+  // Check possible traps cases:
+
+  // 25892 bug.
+  if (mySurface->GetType() == GeomAbs_SurfaceOfRevolution)
+  {
+    // Compute maximal deviation from 3D and choose the biggest one.
+    Standard_Real aVRes = mySurface->VResolution(Precision::Confusion());
+    Standard_Real aMaxTol = Max(Precision::PConfusion(), aVRes);
+
+    if (Abs (thePoint.Z() - mySurface->FirstVParameter()) < aMaxTol ||
+        Abs (thePoint.Z() - mySurface->LastVParameter() ) < aMaxTol )
+    {
+      isProblemsPossible = Standard_True;
+    }
+  }
+
+  // 27135 bug. Trap on degenerated edge.
+  if (mySurface->GetType() == GeomAbs_Sphere &&
+     (Abs (thePoint.Z() - mySurface->FirstVParameter()) < Precision::PConfusion() ||
+      Abs (thePoint.Z() - mySurface->LastVParameter() ) < Precision::PConfusion() ||
+      Abs (thePoint.Y() - mySurface->FirstUParameter()) < Precision::PConfusion() ||
+      Abs (thePoint.Y() - mySurface->LastUParameter() ) < Precision::PConfusion() ))
+  {
+    isProblemsPossible = Standard_True;
+  }
+
+  if (!isProblemsPossible)
+    return;
+
+  Standard_Real U,V;
+  InitialPoint(myCurve->Value(thePoint.X()), thePoint.X(), myCurve, mySurface, myTolU, myTolV, U, V);
+
+  // Restore original position in case of period jump.
+  if (mySurface->IsUPeriodic() &&
+      Abs (Abs(U - thePoint.Y()) - mySurface->UPeriod()) < Precision::PConfusion())
+  {
+    U = thePoint.Y();
+  }
+  if (mySurface->IsVPeriodic() &&
+      Abs (Abs(V - thePoint.Z()) - mySurface->VPeriod()) < Precision::PConfusion())
+  {
+    V = thePoint.Z();
+  }
+  thePoint.SetY(U);
+  thePoint.SetZ(V);
+}
index 69f1501..bb98d42 100644 (file)
@@ -56,7 +56,7 @@ public:
   Standard_EXPORT ProjLib_CompProjectedCurve(const Handle(Adaptor3d_HSurface)& S, const Handle(Adaptor3d_HCurve)& C, const Standard_Real TolU, const Standard_Real TolV);
   
   //! this constructor tries to optimize the search using the
-  //! assamption that maximum distance between surface and curve less or
+  //! assumption that maximum distance between surface and curve less or
   //! equal then MaxDist.
   //! if MaxDist < 0 then algorithm works as above.
   Standard_EXPORT ProjLib_CompProjectedCurve(const Handle(Adaptor3d_HSurface)& S, const Handle(Adaptor3d_HCurve)& C, const Standard_Real TolU, const Standard_Real TolV, const Standard_Real MaxDist);
@@ -85,7 +85,7 @@ public:
   //! returns the bounds of the continuous part corresponding to Index
   Standard_EXPORT void Bounds (const Standard_Integer Index, Standard_Real& Udeb, Standard_Real& Ufin) const;
   
-  //! returns  True  if  part  of  projection with  number  Index is  a  single  point  and  writes  its  coordinats in  P
+  //! returns  True  if  part  of  projection with  number  Index is  a  single  point  and  writes  its  coordinates in  P
   Standard_EXPORT Standard_Boolean IsSinglePnt (const Standard_Integer Index, gp_Pnt2d& P) const;
   
   //! returns  True  if  part  of  projection with  number  Index is  an  u-isoparametric curve  of  input  surface
@@ -167,7 +167,10 @@ protected:
 
 private:
 
-  
+  // This method performs check possibility of optimization traps and tries to go out from them.
+  //@return thePoint - input / corrected point.
+  Standard_EXPORT void UpdateTripleByTrapCriteria(gp_Pnt &thePoint) const;
+
   Standard_EXPORT void BuildIntervals (const GeomAbs_Shape S) const;
 
 
diff --git a/tests/bugs/moddata_3/bug27135 b/tests/bugs/moddata_3/bug27135
new file mode 100644 (file)
index 0000000..0376155
--- /dev/null
@@ -0,0 +1,23 @@
+puts "================"
+puts "0027135"
+puts "================"
+puts ""
+##############################################################
+# Incorrect result of the normal projection algorithm
+# Degenerated edge in result
+##############################################################
+
+restore [locate_data_file bug27135.brep] aShape
+explode aShape
+
+nproject result aShape_1 aShape_2
+
+# Result length check.
+checkprops result -l 5.74501
+
+# Visual check.
+donly result
+smallview
+fit
+display aShape_2
+checkview -screenshot -2d -path ${imagedir}/${test_image}.png