0026196: Wrong result obtained by projection algorithm.
authoraml <aml@opencascade.com>
Thu, 17 Sep 2015 14:09:20 +0000 (17:09 +0300)
committerbugmaster <bugmaster@opencascade.com>
Thu, 17 Sep 2015 14:11:34 +0000 (17:11 +0300)
Improved periodicity handling when trimmed parameters became unclosed or nonperiodic, but underlying geometry closed or periodic.
Added possibility to not perform trim in GeomAdaptor::MakeSurface.

Minor corrections.

Test-case for issue #26196

Correction of comments

src/GeomAdaptor/GeomAdaptor.cxx
src/GeomAdaptor/GeomAdaptor.hxx
src/ProjLib/ProjLib_ComputeApproxOnPolarSurface.cxx
tests/bugs/modalg_6/bug26196 [new file with mode: 0644]

index 4378e5d..7880502 100644 (file)
@@ -101,8 +101,8 @@ Handle(Geom_Curve) GeomAdaptor::MakeCurve (const Adaptor3d_Curve& HC)
 //function : MakeSurface
 //purpose  : 
 //=======================================================================
-
-Handle(Geom_Surface) GeomAdaptor::MakeSurface(const Adaptor3d_Surface& HS)
+Handle(Geom_Surface) GeomAdaptor::MakeSurface(const Adaptor3d_Surface& HS,
+                                              const Standard_Boolean theTrimFlag)
 {
   Handle(Geom_Surface) S;
 
@@ -148,7 +148,7 @@ Handle(Geom_Surface) GeomAdaptor::MakeSurface(const Adaptor3d_Surface& HS)
 
   case GeomAbs_OffsetSurface:
     S = new Geom_OffsetSurface(GeomAdaptor::MakeSurface(HS.BasisSurface()->Surface()),
-                              HS.OffsetValue());
+                               HS.OffsetValue());
     break;
 
   case GeomAbs_OtherSurface:
@@ -156,7 +156,7 @@ Handle(Geom_Surface) GeomAdaptor::MakeSurface(const Adaptor3d_Surface& HS)
     break;
   }
 
-  if ( S.IsNull() )
+  if ( S.IsNull() || !theTrimFlag)
     return S;
 
   // trim the surface if necassary.
index b27a5c2..d1797b5 100644 (file)
@@ -48,9 +48,11 @@ public:
   //! Curve from Adaptor3d
   Standard_EXPORT static Handle(Geom_Curve) MakeCurve (const Adaptor3d_Curve& C);
   
-  //! Build a Geom_Surface using the informations from the
-  //! Surface from Adaptor3d
-  Standard_EXPORT static Handle(Geom_Surface) MakeSurface (const Adaptor3d_Surface& S);
+  //! Build a Geom_Surface using the informations from the Surface from Adaptor3d
+  //! @param theS - Surface adaptor to convert.
+  //! @param theTrimFlag - True if perform trim surface values by adaptor and false otherwise.
+  Standard_EXPORT static Handle(Geom_Surface) MakeSurface (const Adaptor3d_Surface& theS,
+                                                           const Standard_Boolean theTrimFlag = Standard_True);
 
 
 
index fa90489..07d2aef 100644 (file)
@@ -94,6 +94,65 @@ struct aFuncStruct
 };
 
 //=======================================================================
+//function : computePeriodicity
+//purpose  : Compute period information on adaptor.
+//=======================================================================
+static void computePeriodicity(const Handle(Adaptor3d_HSurface)& theSurf,
+                               Standard_Real &theUPeriod,
+                               Standard_Real &theVPeriod)
+{
+  theUPeriod = 0.0;
+  theVPeriod = 0.0;
+
+  // Compute once information about periodicity.
+  // Param space may be reduced in case of rectangular trimmed surface,
+  // in this case really trimmed bounds should be set as unperiodic.
+  Standard_Real aTrimF, aTrimL, aBaseF, aBaseL, aDummyF, aDummyL;
+  Handle(Geom_Surface) aS = GeomAdaptor::MakeSurface(theSurf->Surface(), Standard_False); // Not trim.
+  // U param space.
+  if (theSurf->IsUPeriodic())
+  {
+    theUPeriod = theSurf->UPeriod();
+  }
+  else if(theSurf->IsUClosed())
+  {
+    theUPeriod = theSurf->LastUParameter() - theSurf->FirstUParameter();
+  }
+  if (theUPeriod != 0.0)
+  {
+    aTrimF = theSurf->FirstUParameter(); // Trimmed first
+    aTrimL = theSurf->LastUParameter(); // Trimmed last
+    aS->Bounds(aBaseF, aBaseL, aDummyF, aDummyL); // Non-trimmed values.
+    if (Abs (aBaseF - aTrimF) + Abs (aBaseL - aTrimL) > Precision::PConfusion())
+    {
+      // Param space reduced.
+      theUPeriod = 0.0;
+    }
+  }
+
+  // V param space.
+  if (theSurf->IsVPeriodic())
+  {
+    theVPeriod = theSurf->VPeriod();
+  }
+  else if(theSurf->IsVClosed())
+  {
+    theVPeriod = theSurf->LastVParameter() - theSurf->FirstVParameter();
+  }
+  if (theVPeriod != 0.0)
+  {
+    aTrimF = theSurf->FirstVParameter(); // Trimmed first
+    aTrimL = theSurf->LastVParameter(); // Trimmed last
+    aS->Bounds(aDummyF, aDummyL, aBaseF, aBaseL); // Non-trimmed values.
+    if (Abs (aBaseF - aTrimF) + Abs (aBaseL - aTrimL) > Precision::PConfusion())
+    {
+      // Param space reduced.
+      theVPeriod = 0.0;
+    }
+  }
+}
+
+//=======================================================================
 //function : aFuncValue
 //purpose  : compute functional value in (theU,theV) point
 //=======================================================================
@@ -128,7 +187,6 @@ static Standard_Real anOrthogSqValue(const gp_Pnt& aBasePnt,
 //purpose  : (OCC217 - apo)- Compute Point2d that project on polar surface(<Surf>) 3D<Curve>
 //            <InitCurve2d> use for calculate start 2D point.
 //=======================================================================
-
 static gp_Pnt2d Function_Value(const Standard_Real theU,
                                const aFuncStruct& theData)
 {
@@ -236,10 +294,8 @@ static gp_Pnt2d Function_Value(const Standard_Real theU,
   Standard_Real uperiod = theData.myPeriod[0],
                 vperiod = theData.myPeriod[1],
                 u, v;
-  // U0 and V0 are the points within the initialized period 
-  // (periode with u and v),
-  // U1 and V1 are the points for construction of tops
-  
+
+  // U0 and V0 are the points within the initialized period.
   if(U0 < Uinf)
   {
     if(!uperiod)
@@ -280,8 +336,8 @@ static gp_Pnt2d Function_Value(const Standard_Real theU,
       V0 += decalV*vperiod;
     }
   }
-  
-  // The surface around U0 is reduced.
+
+  // The surface around (U0,V0) is reduced.
   Standard_Real uLittle = (Usup - Uinf)/10, vLittle = (Vsup - Vinf)/10;
   Standard_Real uInfLi = 0, vInfLi = 0,uSupLi = 0, vSupLi = 0;
   if((U0 - Uinf) > uLittle) uInfLi = U0 - uLittle; else uInfLi = Uinf;
@@ -372,18 +428,7 @@ class ProjLib_PolarFunction : public AppCont_Function
     myNbPnt = 0;
     myNbPnt2d = 1;
 
-    myStruct.myPeriod[0] = 0.0;
-    myStruct.myPeriod[1] = 0.0;
-
-    // Compute once information about periodicity.
-    if(Surf->IsUPeriodic() || Surf->IsUClosed())
-    {
-      myStruct.myPeriod[0] =  Surf->LastUParameter() - Surf->FirstUParameter();
-    }
-    if(Surf->IsVPeriodic() || Surf->IsVClosed())
-    {
-      myStruct.myPeriod[1] = Surf->LastVParameter() - Surf->FirstVParameter();
-    }
+    computePeriodicity(Surf, myStruct.myPeriod[0], myStruct.myPeriod[1]);
 
     myStruct.myCurve = C;
     myStruct.myInitCurve2d = InitialCurve2d;
@@ -766,6 +811,8 @@ Handle(Geom2d_BSplineCurve) ProjLib_ComputeApproxOnPolarSurface::Perform
        }
       }
 
+      Standard_Real anUPeriod, anVPeriod;
+      computePeriodicity(S, anUPeriod, anVPeriod);
       Standard_Integer NbC = LOfBSpline2d.Extent();
       Handle(Geom2d_BSplineCurve) CurBS;
       CurBS = Handle(Geom2d_BSplineCurve)::DownCast(LOfBSpline2d.First());
@@ -780,22 +827,18 @@ Handle(Geom2d_BSplineCurve) ProjLib_ComputeApproxOnPolarSurface::Perform
         gp_Pnt2d aC2Beg = BS->Pole(1); // Beginning of C2.
         Standard_Real anUJump = 0.0, anVJump = 0.0;
 
-        if (S->IsUPeriodic() || S->IsUClosed())
+        if (anUPeriod > 0.0 &&
+            Abs (aC1End.X() - aC2Beg.X()) > (anUPeriod ) / 2.01)
         {
-          if (Abs (aC1End.X() - aC2Beg.X()) > (S->LastUParameter() - S->FirstUParameter() ) / 2.01)
-          {
-            Standard_Real aMultCoeff =  aC2Beg.X() < aC1End.X() ? 1.0 : -1.0;
-            anUJump = (S->LastUParameter() - S->FirstUParameter() ) * aMultCoeff;
-          }
+          Standard_Real aMultCoeff =  aC2Beg.X() < aC1End.X() ? 1.0 : -1.0;
+          anUJump = (anUPeriod) * aMultCoeff;
         }
 
-        if (S->IsVPeriodic() || S->IsVClosed())
+        if (anVPeriod &&
+            Abs (aC1End.Y() - aC2Beg.Y()) > (anVPeriod) / 2.01)
         {
-          if (Abs (aC1End.Y() - aC2Beg.Y()) > (S->LastVParameter() - S->FirstVParameter() ) / 2.01)
-          {
-            Standard_Real aMultCoeff =  aC2Beg.Y() < aC1End.Y() ? 1.0 : -1.0;
-            anVJump = (S->LastVParameter() - S->FirstVParameter() ) * aMultCoeff;
-          }
+          Standard_Real aMultCoeff =  aC2Beg.Y() < aC1End.Y() ? 1.0 : -1.0;
+          anVJump = (anVPeriod) * aMultCoeff;
         }
 
         CurBS = Concat(CurBS,BS, anUJump, anVJump);
@@ -832,14 +875,9 @@ Handle(Adaptor2d_HCurve2d)
   Standard_Real TolU = Surf->UResolution(Tol3d), TolV = Surf->VResolution(Tol3d);
   Standard_Real DistTol3d = 100.0*Tol3d;
 
-  Standard_Real uperiod = 0., vperiod = 0.;
-  if(Surf->IsUPeriodic() || Surf->IsUClosed())
-    uperiod = Surf->LastUParameter() - Surf->FirstUParameter(); 
-  
-  if(Surf->IsVPeriodic() || Surf->IsVClosed())
-    vperiod = Surf->LastVParameter() - Surf->FirstVParameter(); 
+  Standard_Real uperiod = 0.0, vperiod = 0.0;
+  computePeriodicity(Surf, uperiod, vperiod);
 
-  
   // NO myTol is Tol2d !!!!
   //Standard_Real TolU = myTolerance, TolV = myTolerance;
   //Standard_Real Tol3d = 100*myTolerance; // At random Balthazar.
diff --git a/tests/bugs/modalg_6/bug26196 b/tests/bugs/modalg_6/bug26196
new file mode 100644 (file)
index 0000000..b5f433b
--- /dev/null
@@ -0,0 +1,43 @@
+puts "========"
+puts "OCC26196"
+puts "========"
+puts ""
+#################################################
+# Wrong result obtained by projection algorithm
+#################################################
+
+restore [locate_data_file OCC26196-Face.brep] f
+
+explode f e
+mkcurve c f_1
+mksurface s f
+trim st s 1.33305 4.31185 -1.56174 0.415831
+project c2d c st
+
+set bug_info [dump c2d]
+set bug_info [string trim [string range $bug_info [expr {[string first "KnotsPoles :" $bug_info] + 12}] [string length $bug_info]]]
+set bug_info [string trim [string range $bug_info 0 [expr {[string first "Knots :" $bug_info] - 1}]]]
+set bug_info_length [llength $bug_info]
+
+set beg_X [lindex $bug_info 2]
+set beg_X [string range $beg_X 0 [expr {[string length $beg_X] - 2}]]
+set beg_Y [lindex $bug_info 3]
+
+set end_X [lindex $bug_info [expr {$bug_info_length - 2}]]
+set end_X [string range $end_X 0 [expr {[string length $end_X] - 2}]]
+set end_Y [lindex $bug_info [expr {$bug_info_length - 1}]]
+
+if {$beg_X > $end_X} {
+  set diff_X [expr {$beg_X - $end_X}]
+} else {
+  set diff_X [expr {$end_X - $beg_X}]
+}
+if {$beg_Y > $end_Y} {
+  set diff_Y [expr {$beg_Y - $end_Y}]
+} else {
+  set diff_Y [expr {$end_Y - $beg_Y}]
+}
+
+if {$diff_X > 1.e-06 || $diff_Y > 1.e-06} {
+  puts "ERROR: OCC26196 is reproduced. Projection is wrong."
+}