0025981: Wrong result obtained by projection algorithm.
authoraml <aml@opencascade.com>
Thu, 18 Jun 2015 10:39:46 +0000 (13:39 +0300)
committerbugmaster <bugmaster@opencascade.com>
Thu, 18 Jun 2015 10:42:31 +0000 (13:42 +0300)
Adjust periodic added.

processing of V parameter periodicity added.

Test case for issue CR25981

src/ProjLib/ProjLib_ProjectedCurve.cxx
tests/bugs/moddata_3/bug25981 [new file with mode: 0755]
tests/draft/angle/G8
tests/draft/angle/K7

index a446bad..dd42945 100644 (file)
@@ -54,6 +54,7 @@
 #include <ElCLib.hxx>
 #include <GeomLib.hxx>
 #include <Extrema_ExtPC.hxx>
+#include <NCollection_DataMap.hxx>
 
 //=======================================================================
 //function : IsoIsDeg
@@ -613,129 +614,96 @@ void ProjLib_ProjectedCurve::Load(const Handle(Adaptor3d_HCurve)& C)
     }
     myTolerance = Comp.Tolerance();
   }
-  else if (myResult.IsDone())
+
+  Standard_Boolean isPeriodic[] = {mySurface->IsUPeriodic(),
+                                   mySurface->IsVPeriodic()};
+  if (myResult.IsDone() &&
+     (isPeriodic[0] || isPeriodic[1]))
   {
-    // On remet arbitrairement la tol atteinte a une valeur
-    // petite en attendant mieux. dub lbo 11/03/97
-    myTolerance = Min(myTolerance,Precision::Confusion());
-    
-    // Translate the projected curve to keep the first point
-    // In the canonical boundaries of periodic surfaces.
-    if (mySurface->IsUPeriodic())
+    // Check result curve to be in params space.
+
+    // U and V parameters space correspondingly.
+    const Standard_Real aSurfFirstPar[2] = {mySurface->FirstUParameter(),
+                                            mySurface->FirstVParameter()};
+    Standard_Real aSurfPeriod[2] = {0.0, 0.0};
+    if (isPeriodic[0])
+      aSurfPeriod[0] = mySurface->UPeriod();
+    if (isPeriodic[1])
+      aSurfPeriod[1] = mySurface->VPeriod();
+
+    for(Standard_Integer anIdx = 1; anIdx <= 2; anIdx++)
     {
-      // xf
-      Standard_Real aT1, aT2, aU1, aU2, aUPeriod, aUr, aUm, aUmid, dUm, dUr;
-      GeomAbs_CurveType aTypeR;
-      ProjLib_Projector aResult;
-      //
-      aT1 = myCurve->FirstParameter();
-      aT2 = myCurve->LastParameter();
-      aU1 = mySurface->FirstUParameter();
-      aU2 = mySurface->LastUParameter();
-      aUPeriod = mySurface->UPeriod();
-      //
-      aTypeR = myResult.GetType();
-      if ((aU2 - aU1) < (aUPeriod - myTolerance) && aTypeR == GeomAbs_Line)
-      {
-        aResult = myResult;
-        aResult.UFrame(aT1, aT2, aU1, aUPeriod);
-        //
-        gp_Lin2d &aLr = (gp_Lin2d &) aResult.Line();
-        aUr=aLr.Location().X();
-        gp_Lin2d &aLm = (gp_Lin2d &) myResult.Line();
-        aUm=aLm.Location().X();
-        //
-        aUmid = 0.5 * (aU2 + aU1);
-        dUm = fabs(aUm - aUmid);
-        dUr = fabs(aUr - aUmid);
-        if (dUr < dUm)
-        {
-          myResult = aResult;
-        }
-      }
-      else
-      {
-        myResult.UFrame(aT1, aT2, aU1, aUPeriod);
-      }
-      //
-      /*
-      myResult.UFrame(myCurve->FirstParameter(),
-      myCurve->LastParameter(),
-      mySurface->FirstUParameter(),
-      mySurface->UPeriod());
-      */
-      //xt
-      //  Modified by skv - Wed Aug 11 15:45:58 2004 OCC6272 Begin
-      //  Correct the U isoline in periodical surface
-      // to be inside restriction boundaries.
-      if (myResult.GetType() == GeomAbs_Line)
-      {
-        gp_Lin2d &aLine = (gp_Lin2d &) myResult.Line();
+      if (!isPeriodic[anIdx - 1])
+        continue;
 
-        Standard_Real aPeriod = mySurface->UPeriod();
-        Standard_Real aFUPar  = mySurface->FirstUParameter();
-        Standard_Real aLUPar  = mySurface->LastUParameter();
+      if (myResult.GetType() == GeomAbs_BSplineCurve)
+      {
+        NCollection_DataMap<Standard_Integer, Standard_Integer> aMap; 
+        Handle(Geom2d_BSplineCurve) aRes = myResult.BSpline();
+        const Standard_Integer aDeg = aRes->Degree();
 
-        // Check if the parametric range is lower then the period.
-        if (aLUPar - aFUPar < aPeriod - myTolerance)
+        for(Standard_Integer aKnotIdx = aRes->FirstUKnotIndex();
+                             aKnotIdx < aRes->LastUKnotIndex();
+                             aKnotIdx++)
         {
-          Standard_Real aU = aLine.Location().X();
+          const Standard_Real aFirstParam = aRes->Knot(aKnotIdx);
+          const Standard_Real aLastParam  = aRes->Knot(aKnotIdx + 1);
 
-          if (Abs(aU + aPeriod - aFUPar) < myTolerance ||
-              Abs(aU - aPeriod - aFUPar) < myTolerance)
+          for(Standard_Integer anIntIdx = 0; anIntIdx <= aDeg; anIntIdx++)
           {
-              gp_Pnt2d aNewLoc(aFUPar, aLine.Location().Y());
+            const Standard_Real aCurrParam = aFirstParam + (aLastParam - aFirstParam) * anIntIdx / (aDeg + 1.0);
+            gp_Pnt2d aPnt2d;
+            aRes->D0(aCurrParam, aPnt2d);
+
+            Standard_Integer aMapKey = Standard_Integer ((aPnt2d.Coord(anIdx) - aSurfFirstPar[anIdx - 1]) / aSurfPeriod[anIdx - 1]);
 
-              aLine.SetLocation(aNewLoc);
+            if (aPnt2d.Coord(anIdx) - aSurfFirstPar[anIdx - 1] < 0.0)
+              aMapKey--;
+
+            if (aMap.IsBound(aMapKey))
+              aMap.ChangeFind(aMapKey)++;
+            else
+              aMap.Bind(aMapKey, 1);
           }
-          else if (Abs(aU + aPeriod - aLUPar) < myTolerance ||
-                   Abs(aU - aPeriod - aLUPar) < myTolerance)
+        }
+
+        Standard_Integer aMaxPoints = 0, aMaxIdx = 0;
+        NCollection_DataMap<Standard_Integer, Standard_Integer>::Iterator aMapIter(aMap);
+        for( ; aMapIter.More(); aMapIter.Next())
+        {
+          if (aMapIter.Value() > aMaxPoints)
           {
-              gp_Pnt2d aNewLoc(aLUPar, aLine.Location().Y());
-              aLine.SetLocation(aNewLoc);
+            aMaxPoints = aMapIter.Value();
+            aMaxIdx = aMapIter.Key();
           }
         }
+        if (aMaxIdx != 0)
+        {
+          gp_Pnt2d aFirstPnt = aRes->Value(aRes->FirstParameter());
+          gp_Pnt2d aSecondPnt = aFirstPnt;
+          aSecondPnt.SetCoord(anIdx, aFirstPnt.Coord(anIdx) - aSurfPeriod[anIdx - 1] * aMaxIdx);
+          aRes->Translate(gp_Vec2d(aFirstPnt, aSecondPnt));
+        }
       }
-    }
-    //  Modified by skv - Wed Aug 11 15:45:58 2004 OCC6272 End
 
-    if (mySurface->IsVPeriodic())
-    {
-      myResult.VFrame(myCurve->FirstParameter(), myCurve->LastParameter(),
-        mySurface->FirstVParameter(), mySurface->VPeriod());
-      //  Modified by skv - Wed Aug 11 15:45:58 2004 OCC6272 Begin
-      //  Correct the V isoline in a periodical surface
-      // to be inside restriction boundaries.
       if (myResult.GetType() == GeomAbs_Line)
       {
-        gp_Lin2d &aLine = (gp_Lin2d &) myResult.Line();
+        Standard_Real aT1 = myCurve->FirstParameter();
+        Standard_Real aT2 = myCurve->LastParameter();
 
-        Standard_Real aPeriod = mySurface->VPeriod();
-        Standard_Real aFVPar  = mySurface->FirstVParameter();
-        Standard_Real aLVPar  = mySurface->LastVParameter();
-
-        // Check if the parametric range is lower then the period.
-        if (aLVPar - aFVPar < aPeriod - myTolerance)
+        if (anIdx == 1)
         {
-          Standard_Real aV = aLine.Location().Y();
-
-          if (Abs(aV + aPeriod - aFVPar) < myTolerance ||
-              Abs(aV - aPeriod - aFVPar) < myTolerance)
-          {
-            gp_Pnt2d aNewLoc(aLine.Location().X(), aFVPar);
-            aLine.SetLocation(aNewLoc);
-          }
-          else if (Abs(aV + aPeriod - aLVPar) < myTolerance ||
-                   Abs(aV - aPeriod - aLVPar) < myTolerance)
-          {
-            gp_Pnt2d aNewLoc(aLine.Location().X(), aLVPar);
-            aLine.SetLocation(aNewLoc);
-          }
+          // U param space.
+          myResult.UFrame(aT1, aT2, aSurfFirstPar[anIdx - 1], aSurfPeriod[anIdx - 1]);
+        }
+        else
+        {
+          // V param space.
+          myResult.VFrame(aT1, aT2, aSurfFirstPar[anIdx - 1], aSurfPeriod[anIdx - 1]);
         }
       }
     }
-    //  Modified by skv - Wed Aug 11 15:45:58 2004 OCC6272 End
-  } 
+  }
 }
 
 
diff --git a/tests/bugs/moddata_3/bug25981 b/tests/bugs/moddata_3/bug25981
new file mode 100755 (executable)
index 0000000..822f9a0
--- /dev/null
@@ -0,0 +1,27 @@
+puts "========"
+puts "OCC25981"
+puts "========"
+puts ""
+#################################################
+# Wrong result obtained by projection algorithm.
+#################################################
+
+restore [locate_data_file bug25981_cb1_4.draw] c
+restore [locate_data_file bug25981_b2f.brep] f
+mksurface s f
+project x c s
+
+2dcvalue x 0 firstX firstY
+set log [dump firstX]
+regexp {([-0-9.+eE]+)} ${log} x1
+
+set tol_abs 1.e-7
+if {abs($x1) > $tol_abs} {
+  puts "Error: Bad start position of projected curve"
+}
+
+view 1 -2D- 465 20 400 400
+2dfit
+pcurve f
+
+xwd ${imagedir}/${casename}.png
index 8f059eb..86c36c4 100644 (file)
@@ -1,8 +1,8 @@
 #F6----------------------------------------------
-puts "TODO OCC22803 Linux: Error in depouille"
-puts "TODO OCC22803 Linux: Error : The skin cannot be built."
-puts "TODO OCC22803 Windows: Faulty shapes in variables faulty_1 to faulty_"
-puts "TODO OCC22803 Windows: Error : The area of the resulting shape is"
+#puts "TODO OCC22803 Linux: Error in depouille"
+#puts "TODO OCC22803 Linux: Error : The skin cannot be built."
+puts "TODO OCC22803 Linux Windows: Faulty shapes in variables faulty_1 to faulty_"
+puts "TODO OCC22803 Linux Windows: Error : The area of the resulting shape is"
 polyline p 0 0 3  0 0 0  10 0 0  10 0 3  
 beziercurve bc 4 10 0 3  7 0 2  3 0 3  0 0 3
 mkedge bc bc
@@ -18,4 +18,4 @@ if { [catch { depouille result f 0 0 1 f_4 3 0 0 10 0 0 1 } ] != 0 } {
   puts "Error in depouille"
 }
 
-set square 492.768
\ No newline at end of file
+set square 492.768
index 9f0420c..7d5a335 100644 (file)
@@ -1,5 +1,6 @@
 #D3---------------------------------------------
 puts "TODO OCC22803 All:Faulty shapes in variables faulty_1 to faulty_6"
+puts "TODO OCC22803 Linux Windows: Error : The area of the resulting shape is"
 
 plane pt 0 0 0 1 0 0
 ptorus pt pt 9 7