]> OCCT Git - occt-copy.git/commitdiff
0027299: Incorrect result of the normal projection algorithm CR0-690-FixCD
authoraml <aml@opencascade.com>
Fri, 25 Mar 2016 10:10:12 +0000 (13:10 +0300)
committerbugmaster <bugmaster@opencascade.com>
Thu, 7 Apr 2016 08:10:58 +0000 (11:10 +0300)
Curve splitting is added to handle seam passing by initial curve.
test cases are added.

Minor corrections.

0026044: Optimize math_GlobOptMin class to enter options for solutions of some specified problems

Possibility to search single optimum added.

Additional backporting to improve performance.

12 files changed:
src/Extrema/Extrema_ExtCC.cdl
src/Extrema/Extrema_ExtCC.cxx
src/Extrema/Extrema_ExtCC2d.cdl
src/Extrema/Extrema_ExtCC2d.cxx
src/Extrema/Extrema_GenExtCC.cdl
src/Extrema/Extrema_GenExtCC.gxx
src/ProjLib/ProjLib_CompProjectedCurve.cxx
src/math/math_GlobOptMin.cxx
src/math/math_GlobOptMin.hxx
tests/bugs/moddata_3/bug27299_1 [new file with mode: 0644]
tests/bugs/moddata_3/bug27299_2 [new file with mode: 0644]
tests/bugs/moddata_3/bug27299_3 [new file with mode: 0644]

index 2990897d15a226d2e6916e2cdcc604def470cf9e..1f8b8b6a3c7c3f73c35d2144cc5bf3745d2a457c 100644 (file)
@@ -131,6 +131,15 @@ is
            Ut11, Ut12, Ut21, Ut22: Real)
 
     is static protected;
+    
+    GetSingleSolutionFlag (me) returns Boolean
+    ---Purpose: Returns single solution flag value.
+    is static;
+    
+    SetSingleSolutionFlag (me: in out;
+                           theFlag: Boolean)
+    ---Purpose: Sets single solution flag value.
+    is static;
 
 
     
@@ -139,6 +148,7 @@ fields
     myECC:    ECC from Extrema;
     myDone:   Boolean;
     myIsPar:  Boolean;
+    myIsFindSingleSolution: Boolean;
     mypoints: SequenceOfPOnCurv from Extrema;
     mySqDist: SequenceOfReal    from TColStd;
     mynbext:  Integer;
index 5ee9d5bb30ac90e5df50ed12a6e09ec8f5221c0d..131d410696df8cad18a07f588728f2c48c29744c 100644 (file)
 
 #include <Adaptor3d_Curve.hxx>
 #include <Extrema_CurveTool.hxx>
-
 //=======================================================================
 //function : Extrema_ExtCC
 //purpose  : 
 //=======================================================================
-
 Extrema_ExtCC::Extrema_ExtCC (const Standard_Real TolC1,
-                                           const Standard_Real TolC2) :
-                                             myDone (Standard_False)
+                              const Standard_Real TolC2)
+: myIsFindSingleSolution(Standard_False),
+  myDone (Standard_False)
 {
   myC[0] = 0; myC[1] = 0;
   myTol[0] = TolC1; myTol[1] = TolC2;
@@ -64,15 +63,16 @@ Extrema_ExtCC::Extrema_ExtCC (const Standard_Real TolC1,
 //purpose  : 
 //=======================================================================
 
-Extrema_ExtCC::Extrema_ExtCC(const Adaptor3d_Curve& C1, 
-                              const Adaptor3d_Curve& C2,
-                              const Standard_Real      U1,
-                              const Standard_Real      U2,
-                              const Standard_Real      V1,
-                              const Standard_Real      V2,
-                              const Standard_Real      TolC1,
-                              const Standard_Real      TolC2)
-: myECC(C1, C2, U1, U2, V1, V2),
+Extrema_ExtCC::Extrema_ExtCC(const Adaptor3d_Curve& C1,
+                             const Adaptor3d_Curve& C2,
+                             const Standard_Real      U1,
+                             const Standard_Real      U2,
+                             const Standard_Real      V1,
+                             const Standard_Real      V2,
+                             const Standard_Real      TolC1,
+                             const Standard_Real      TolC2)
+: myIsFindSingleSolution(Standard_False),
+  myECC(C1, C2, U1, U2, V1, V2),
   myDone (Standard_False)
 {
   SetCurve (1, C1, U1, U2);
@@ -89,10 +89,11 @@ Extrema_ExtCC::Extrema_ExtCC(const Adaptor3d_Curve& C1,
 //=======================================================================
 
 Extrema_ExtCC::Extrema_ExtCC(const Adaptor3d_Curve& C1, 
-                              const Adaptor3d_Curve& C2,
-                              const Standard_Real      TolC1,
-                              const Standard_Real      TolC2)
-: myECC(C1, C2),
+                             const Adaptor3d_Curve& C2,
+                             const Standard_Real      TolC1,
+                             const Standard_Real      TolC2)
+: myIsFindSingleSolution(Standard_False),
+  myECC(C1, C2),
   myDone (Standard_False)
 {
   SetCurve (1, C1, C1.FirstParameter(), C1.LastParameter());
@@ -164,6 +165,7 @@ void Extrema_ExtCC::Perform()
   myECC.SetParams(*((Adaptor3d_Curve*)myC[0]), 
                   *((Adaptor3d_Curve*)myC[1]), myInf[0], mySup[0], myInf[1], mySup[1]);
   myECC.SetTolerance(Min(myTol[0], myTol[1]));
+  myECC.SetSingleSolutionFlag(GetSingleSolutionFlag());
   myDone = Standard_False;
   mypoints.Clear();
   mySqDist.Clear();
@@ -725,3 +727,21 @@ void Extrema_ExtCC::Results(const Extrema_ECC&   AlgExt,
     }
   }  
 }
+
+//=======================================================================
+//function : SetSingleSolutionFlag
+//purpose  : 
+//=======================================================================
+void Extrema_ExtCC::SetSingleSolutionFlag(const Standard_Boolean theFlag)
+{
+  myIsFindSingleSolution = theFlag;
+}
+
+//=======================================================================
+//function : GetSingleSolutionFlag
+//purpose  : 
+//=======================================================================
+Standard_Boolean Extrema_ExtCC::GetSingleSolutionFlag() const
+{
+  return myIsFindSingleSolution;
+}
index b156e6bd427679b0a2a4f13afb135a84b4dea8cb..342abd8800bd9bc69d329a2ed391bb837d23774d 100644 (file)
@@ -131,11 +131,21 @@ is
             Period2 : Real from Standard = 0.0)
 
     is static protected;
+    
+    GetSingleSolutionFlag (me) returns Boolean
+    ---Purpose: Returns single solution flag value.
+    is static;
+    
+    SetSingleSolutionFlag (me: in out;
+                           theFlag: Boolean)
+    ---Purpose: Sets single solution flag value.
+    is static;
 
 
 fields
     myDone:   Boolean;
     myIsPar:  Boolean;
+    myIsFindSingleSolution: Boolean;
     mypoints: SequenceOfPOnCurv2d from Extrema;
     mySqDist:  SequenceOfReal      from TColStd;
     mynbext:  Integer;
index 8448867d9ee19dddfce263750ac79e6ac41543a1..585c02c7e68e1eb12e3c0515133ba9ade2578322 100644 (file)
 
 
 Extrema_ExtCC2d::Extrema_ExtCC2d()
+: myIsFindSingleSolution(Standard_False)
 {
 }
 
 
-Extrema_ExtCC2d::Extrema_ExtCC2d(const Adaptor2d_Curve2d&       C1, 
-                                  const Adaptor2d_Curve2d&       C2,
-                                  const Standard_Real TolC1, 
-                                  const Standard_Real TolC2)
+Extrema_ExtCC2d::Extrema_ExtCC2d(const Adaptor2d_Curve2d&       C1,
+                                 const Adaptor2d_Curve2d&       C2,
+                                 const Standard_Real TolC1,
+                                 const Standard_Real TolC2)
+: myIsFindSingleSolution(Standard_False)
 {
   Initialize(C2, Extrema_Curve2dTool::FirstParameter(C2), Extrema_Curve2dTool::LastParameter(C2), TolC1, TolC2);
   Perform(C1, Extrema_Curve2dTool::FirstParameter(C1), Extrema_Curve2dTool::LastParameter(C1));
 }
 
 Extrema_ExtCC2d::Extrema_ExtCC2d(const Adaptor2d_Curve2d&        C1, 
-                                  const Adaptor2d_Curve2d&        C2,
-                                  const Standard_Real  U1,
-                                  const Standard_Real  U2,
-                                  const Standard_Real  V1,
-                                  const Standard_Real  V2,
-                                  const Standard_Real  TolC1,
-                                  const Standard_Real  TolC2)
+                                 const Adaptor2d_Curve2d&        C2,
+                                 const Standard_Real  U1,
+                                 const Standard_Real  U2,
+                                 const Standard_Real  V1,
+                                 const Standard_Real  V2,
+                                 const Standard_Real  TolC1,
+                                 const Standard_Real  TolC2)
+: myIsFindSingleSolution(Standard_False)
 {
   Initialize(C2, V1, V2, TolC1, TolC2);
   Perform(C1, U1, U2);
@@ -135,11 +138,12 @@ void Extrema_ExtCC2d::Perform (const Adaptor2d_Curve2d&       C1,
       case GeomAbs_BezierCurve:
       case GeomAbs_OtherCurve:
       case GeomAbs_BSplineCurve: {
-       Extrema_ECC2d Xtrem(C1, *((Adaptor2d_Curve2d*)myC));
-                       Xtrem.Perform();
-       Standard_Real Period2 = 0.;
-       if (Extrema_Curve2dTool::IsPeriodic(*((Adaptor2d_Curve2d*)myC))) Period2 = Extrema_Curve2dTool::Period(*((Adaptor2d_Curve2d*)myC));
-       Results(Xtrem, U11, U12, U21, U22, 2*M_PI,Period2);
+          Extrema_ECC2d aParamSolver(C1, *((Adaptor2d_Curve2d*)myC));
+          aParamSolver.SetSingleSolutionFlag(GetSingleSolutionFlag());
+          aParamSolver.Perform();
+          Standard_Real Period2 = 0.;
+          if (Extrema_Curve2dTool::IsPeriodic(*((Adaptor2d_Curve2d*)myC))) Period2 = Extrema_Curve2dTool::Period(*((Adaptor2d_Curve2d*)myC));
+          Results(aParamSolver, U11, U12, U21, U22, 2*M_PI,Period2);
         }
        break;
       case GeomAbs_Line: {
@@ -164,35 +168,39 @@ void Extrema_ExtCC2d::Perform (const Adaptor2d_Curve2d&       C1,
        Results(Xtrem, U11, U12, U21, U22, 2*M_PI, 2*M_PI);
         }
        break;
-      case GeomAbs_Ellipse: {
-       //Extrema_ExtElC2d Xtrem(Extrema_Curve2dTool::Ellipse(C1), Extrema_Curve2dTool::Ellipse(*((Adaptor2d_Curve2d*)myC)));
-       Extrema_ECC2d Xtrem(C1, *((Adaptor2d_Curve2d*)myC));
-                       Xtrem.Perform();
-       Results(Xtrem, U11, U12, U21, U22,2*M_PI, 2*M_PI);
+      case GeomAbs_Ellipse:
+        {
+       Extrema_ECC2d aParamSolver(C1, *((Adaptor2d_Curve2d*)myC));
+        aParamSolver.SetSingleSolutionFlag(GetSingleSolutionFlag());
+        aParamSolver.Perform();
+       Results(aParamSolver, U11, U12, U21, U22,2*M_PI, 2*M_PI);
         }
        break;
       case GeomAbs_Parabola: {
        //Extrema_ExtElC2d Xtrem(Extrema_Curve2dTool::Ellipse(C1), Extrema_Curve2dTool::Parabola(*((Adaptor2d_Curve2d*)myC)));
-       Extrema_ECC2d Xtrem(C1, *((Adaptor2d_Curve2d*)myC));
-                       Xtrem.Perform();
-       Results(Xtrem, U11, U12, U21, U22, 2*M_PI, 0.);
+       Extrema_ECC2d aParamSolver(C1, *((Adaptor2d_Curve2d*)myC));
+        aParamSolver.SetSingleSolutionFlag(GetSingleSolutionFlag());
+        aParamSolver.Perform();
+       Results(aParamSolver, U11, U12, U21, U22, 2*M_PI, 0.);
       }
        break;
       case GeomAbs_Hyperbola: {
        //Extrema_ExtElC2d Xtrem(Extrema_Curve2dTool::Ellipse(C1), Extrema_Curve2dTool::Hyperbola(*((Adaptor2d_Curve2d*)myC)));
-       Extrema_ECC2d Xtrem(C1, *((Adaptor2d_Curve2d*)myC));
-                       Xtrem.Perform();
-       Results(Xtrem, U11, U12, U21, U22, 2*M_PI, 0.);
+       Extrema_ECC2d aParamSolver(C1, *((Adaptor2d_Curve2d*)myC));
+        aParamSolver.SetSingleSolutionFlag(GetSingleSolutionFlag());
+        aParamSolver.Perform();
+       Results(aParamSolver, U11, U12, U21, U22, 2*M_PI, 0.);
       }
        break;
       case GeomAbs_BezierCurve:
       case GeomAbs_OtherCurve:
       case GeomAbs_BSplineCurve: {
-       Extrema_ECC2d Xtrem(C1, *((Adaptor2d_Curve2d*)myC));
-                       Xtrem.Perform();        
+       Extrema_ECC2d aParamSolver(C1, *((Adaptor2d_Curve2d*)myC));
+        aParamSolver.SetSingleSolutionFlag(GetSingleSolutionFlag());
+        aParamSolver.Perform();
        Standard_Real Period2 = 0.;
        if (Extrema_Curve2dTool::IsPeriodic(*((Adaptor2d_Curve2d*)myC))) Period2 = Extrema_Curve2dTool::Period(*((Adaptor2d_Curve2d*)myC));
-       Results(Xtrem, U11, U12, U21, U22, 2*M_PI,Period2);
+       Results(aParamSolver, U11, U12, U21, U22, 2*M_PI,Period2);
         }
        break;
       case GeomAbs_Line: {
@@ -220,34 +228,38 @@ void Extrema_ExtCC2d::Perform (const Adaptor2d_Curve2d&       C1,
       case GeomAbs_Ellipse: {
        //inverse = Standard_True;
        //Extrema_ExtElC2d Xtrem(Extrema_Curve2dTool::Ellipse(*((Adaptor2d_Curve2d*)myC)), Extrema_Curve2dTool::Parabola(C1));
-       Extrema_ECC2d Xtrem(C1, *((Adaptor2d_Curve2d*)myC));
-                       Xtrem.Perform();
-       Results(Xtrem, U11, U12, U21, U22, 0., 2*M_PI);
+       Extrema_ECC2d aParamSolver(C1, *((Adaptor2d_Curve2d*)myC));
+        aParamSolver.SetSingleSolutionFlag(GetSingleSolutionFlag());
+        aParamSolver.Perform();
+       Results(aParamSolver, U11, U12, U21, U22, 0., 2*M_PI);
         }
        break;
       case GeomAbs_Parabola: {
        //Extrema_ExtElC2d Xtrem(Extrema_Curve2dTool::Parabola(C1), Extrema_Curve2dTool::Parabola(*((Adaptor2d_Curve2d*)myC)));
-       Extrema_ECC2d Xtrem(C1, *((Adaptor2d_Curve2d*)myC));
-                       Xtrem.Perform();
-       Results(Xtrem, U11, U12, U21, U22, 0., 0.);
+       Extrema_ECC2d aParamSolver(C1, *((Adaptor2d_Curve2d*)myC));
+        aParamSolver.SetSingleSolutionFlag(GetSingleSolutionFlag());
+        aParamSolver.Perform();
+       Results(aParamSolver, U11, U12, U21, U22, 0., 0.);
       }
        break;
       case GeomAbs_Hyperbola: {
        //inverse = Standard_True;
        //Extrema_ExtElC2d Xtrem(Extrema_Curve2dTool::Hyperbola(*((Adaptor2d_Curve2d*)myC)), Extrema_Curve2dTool::Parabola(C1));
-       Extrema_ECC2d Xtrem(C1, *((Adaptor2d_Curve2d*)myC));
-                       Xtrem.Perform();
-       Results(Xtrem, U11, U12, U21, U22, 0., 0.);
+       Extrema_ECC2d aParamSolver(C1, *((Adaptor2d_Curve2d*)myC));
+        aParamSolver.SetSingleSolutionFlag(GetSingleSolutionFlag());
+        aParamSolver.Perform();
+       Results(aParamSolver, U11, U12, U21, U22, 0., 0.);
       }
        break;
       case GeomAbs_BezierCurve:
       case GeomAbs_OtherCurve:
       case GeomAbs_BSplineCurve: {
-       Extrema_ECC2d Xtrem(C1, *((Adaptor2d_Curve2d*)myC));
-                       Xtrem.Perform();
+       Extrema_ECC2d aParamSolver(C1, *((Adaptor2d_Curve2d*)myC));
+        aParamSolver.SetSingleSolutionFlag(GetSingleSolutionFlag());
+        aParamSolver.Perform();
        Standard_Real Period2 = 0.;
        if (Extrema_Curve2dTool::IsPeriodic(*((Adaptor2d_Curve2d*)myC))) Period2 = Extrema_Curve2dTool::Period(*((Adaptor2d_Curve2d*)myC));
-       Results(Xtrem, U11, U12, U21, U22, 0., Period2);
+       Results(aParamSolver, U11, U12, U21, U22, 0., Period2);
         }
        break;
       case GeomAbs_Line: {
@@ -275,33 +287,37 @@ void Extrema_ExtCC2d::Perform (const Adaptor2d_Curve2d&       C1,
       case GeomAbs_Ellipse: {
        //inverse = Standard_True;
        //Extrema_ExtElC2d Xtrem(Extrema_Curve2dTool::Ellipse(*((Adaptor2d_Curve2d*)myC)), Extrema_Curve2dTool::Hyperbola(C1));
-       Extrema_ECC2d Xtrem(C1, *((Adaptor2d_Curve2d*)myC));
-                       Xtrem.Perform();
-       Results(Xtrem, U11, U12, U21, U22, 0., 2*M_PI );
+       Extrema_ECC2d aParamSolver(C1, *((Adaptor2d_Curve2d*)myC));
+        aParamSolver.SetSingleSolutionFlag(GetSingleSolutionFlag());
+        aParamSolver.Perform();
+       Results(aParamSolver, U11, U12, U21, U22, 0., 2*M_PI );
         }
        break;
       case GeomAbs_Parabola: {
        //Extrema_ExtElC2d Xtrem(Extrema_Curve2dTool::Hyperbola(C1), Extrema_Curve2dTool::Parabola(*((Adaptor2d_Curve2d*)myC)));
-       Extrema_ECC2d Xtrem(C1, *((Adaptor2d_Curve2d*)myC));
-                       Xtrem.Perform();
-       Results(Xtrem, U11, U12, U21, U22, 0., 0.);
+       Extrema_ECC2d aParamSolver(C1, *((Adaptor2d_Curve2d*)myC));
+        aParamSolver.SetSingleSolutionFlag(GetSingleSolutionFlag());
+        aParamSolver.Perform();
+       Results(aParamSolver, U11, U12, U21, U22, 0., 0.);
       }
        break;
       case GeomAbs_Hyperbola: {
        //Extrema_ExtElC2d Xtrem(Extrema_Curve2dTool::Hyperbola(C1), Extrema_Curve2dTool::Hyperbola(*((Adaptor2d_Curve2d*)myC)));
-       Extrema_ECC2d Xtrem(C1, *((Adaptor2d_Curve2d*)myC));
-                       Xtrem.Perform();
-       Results(Xtrem, U11, U12, U21, U22, 0., 0.);
+       Extrema_ECC2d aParamSolver(C1, *((Adaptor2d_Curve2d*)myC));
+        aParamSolver.SetSingleSolutionFlag(GetSingleSolutionFlag());
+        aParamSolver.Perform();
+       Results(aParamSolver, U11, U12, U21, U22, 0., 0.);
       }
        break;
       case GeomAbs_OtherCurve:
       case GeomAbs_BezierCurve:
       case GeomAbs_BSplineCurve: {
-       Extrema_ECC2d Xtrem(C1, *((Adaptor2d_Curve2d*)myC));
-  Xtrem.Perform();
+       Extrema_ECC2d aParamSolver(C1, *((Adaptor2d_Curve2d*)myC));
+        aParamSolver.SetSingleSolutionFlag(GetSingleSolutionFlag());
+        aParamSolver.Perform();
        Standard_Real Period2 = 0.;
        if (Extrema_Curve2dTool::IsPeriodic(*((Adaptor2d_Curve2d*)myC))) Period2 = Extrema_Curve2dTool::Period(*((Adaptor2d_Curve2d*)myC));
-       Results(Xtrem, U11, U12, U21, U22, 0., Period2);
+       Results(aParamSolver, U11, U12, U21, U22, 0., Period2);
         }
        break;
       case GeomAbs_Line: {
@@ -320,13 +336,14 @@ void Extrema_ExtCC2d::Perform (const Adaptor2d_Curve2d&       C1,
   case GeomAbs_BezierCurve:
   case GeomAbs_OtherCurve:
   case GeomAbs_BSplineCurve: {
-    Extrema_ECC2d Xtrem(C1, *((Adaptor2d_Curve2d*)myC));
-    Xtrem.Perform();
+    Extrema_ECC2d aParamSolver(C1, *((Adaptor2d_Curve2d*)myC));
+    aParamSolver.SetSingleSolutionFlag(GetSingleSolutionFlag());
+    aParamSolver.Perform();
     Standard_Real Period1 = 0.;
     if (Extrema_Curve2dTool::IsPeriodic(C1)) Period1 = Extrema_Curve2dTool::Period(C1);
     Standard_Real Period2 = 0.;
     if (Extrema_Curve2dTool::IsPeriodic(*((Adaptor2d_Curve2d*)myC))) Period2 = Extrema_Curve2dTool::Period(*((Adaptor2d_Curve2d*)myC));
-    Results(Xtrem, U11, U12, U21, U22, Period1, Period2);
+    Results(aParamSolver, U11, U12, U21, U22, Period1, Period2);
   }
   break;
 
@@ -359,11 +376,12 @@ void Extrema_ExtCC2d::Perform (const Adaptor2d_Curve2d&       C1,
       case GeomAbs_BezierCurve:
       case GeomAbs_OtherCurve:
       case GeomAbs_BSplineCurve: {
-       Extrema_ECC2d Xtrem(C1, *((Adaptor2d_Curve2d*)myC));
-                       Xtrem.Perform();
+       Extrema_ECC2d aParamSolver(C1, *((Adaptor2d_Curve2d*)myC));
+        aParamSolver.SetSingleSolutionFlag(GetSingleSolutionFlag());
+        aParamSolver.Perform();
        Standard_Real Period2 = 0.;
        if (Extrema_Curve2dTool::IsPeriodic(*((Adaptor2d_Curve2d*)myC))) Period2 = Extrema_Curve2dTool::Period(*((Adaptor2d_Curve2d*)myC));
-       Results(Xtrem, U11, U12, U21, U22, 0., Period2);
+       Results(aParamSolver, U11, U12, U21, U22, 0., Period2);
         }
        break;
       case GeomAbs_Line: {
@@ -555,3 +573,21 @@ Standard_Boolean Extrema_ExtCC2d::IsParallel() const
   if (!myDone) StdFail_NotDone::Raise();
   return myIsPar;
 }
+
+//=======================================================================
+//function : SetSingleSolutionFlag
+//purpose  : 
+//=======================================================================
+void Extrema_ExtCC2d::SetSingleSolutionFlag(const Standard_Boolean theFlag)
+{
+  myIsFindSingleSolution = theFlag;
+}
+
+//=======================================================================
+//function : GetSingleSolutionFlag
+//purpose  : 
+//=======================================================================
+Standard_Boolean Extrema_ExtCC2d::GetSingleSolutionFlag() const
+{
+  return myIsFindSingleSolution;
+}
index a126b92ecf21bf9cee3892c24fde1c09b940278f..e5e9c166c8a7aea88dde51c7f3e5e6157be86efa 100644 (file)
@@ -94,8 +94,18 @@ is
                OutOfRange
                -- if N < 1 or N > NbExt(me)
        is static;
+        
+    GetSingleSolutionFlag (me) returns Boolean
+    ---Purpose: Returns single solution flag value.
+    is static;
+    
+    SetSingleSolutionFlag (me: in out;
+                           theFlag: Boolean)
+    ---Purpose: Sets single solution flag value.
+    is static;
 
 fields
+  myIsFindSingleSolution: Boolean;
   myCurveMinTol : Real from Standard;
   myLowBorder : Vector from math;
   myUppBorder : Vector from math;
@@ -103,5 +113,6 @@ fields
   myPoints2 : SequenceOfReal from TColStd;
   myC : Address from Standard [2];
   myDone : Boolean;
+  
 
 end GenExtCC;
index ba07b737814ba4b5c6b0a427a8e7d716bfacf8f2..61441e40cd39f98b9b9b598882dcc9d533424bd1 100644 (file)
@@ -27,7 +27,8 @@
 //purpose  : 
 //=======================================================================
 Extrema_GenExtCC::Extrema_GenExtCC()
-: myCurveMinTol(Precision::PConfusion()),
+: myIsFindSingleSolution(Standard_False),
+  myCurveMinTol(Precision::PConfusion()),
   myLowBorder(1,2),
   myUppBorder(1,2),
   myDone(Standard_False)
@@ -41,7 +42,8 @@ Extrema_GenExtCC::Extrema_GenExtCC()
 //=======================================================================
 Extrema_GenExtCC::Extrema_GenExtCC(const Curve1& C1,
                                    const Curve2& C2)
-: myCurveMinTol(Precision::PConfusion()),
+: myIsFindSingleSolution(Standard_False),
+  myCurveMinTol(Precision::PConfusion()),
   myLowBorder(1,2),
   myUppBorder(1,2),
   myDone(Standard_False)
@@ -64,7 +66,8 @@ Extrema_GenExtCC::Extrema_GenExtCC(const Curve1& C1,
                                    const Standard_Real Usup,
                                    const Standard_Real Vinf,
                                    const Standard_Real Vsup)
-: myCurveMinTol(Precision::PConfusion()),
+: myIsFindSingleSolution(Standard_False),
+  myCurveMinTol(Precision::PConfusion()),
   myLowBorder(1,2),
   myUppBorder(1,2),
   myDone(Standard_False)
@@ -117,15 +120,25 @@ void Extrema_GenExtCC::Perform()
   Curve2 &C2 = *(Curve2*)myC[1];
 
   Standard_Integer aNbInter[2];
-  aNbInter[0] = C1.NbIntervals(GeomAbs_C2);
-  aNbInter[1] = C2.NbIntervals(GeomAbs_C2);
+  GeomAbs_Shape aContinuity = GeomAbs_C2;
+  aNbInter[0] = C1.NbIntervals(aContinuity);
+  aNbInter[1] = C2.NbIntervals(aContinuity);
+
+  if (aNbInter[0] * aNbInter[1] > 100)
+  {
+    aContinuity = GeomAbs_C1;
+    aNbInter[0] = C1.NbIntervals(aContinuity);
+    aNbInter[1] = C2.NbIntervals(aContinuity);
+  }
+
   TColStd_Array1OfReal anIntervals1(1, aNbInter[0] + 1);
   TColStd_Array1OfReal anIntervals2(1, aNbInter[1] + 1);
-  C1.Intervals(anIntervals1, GeomAbs_C2);
-  C2.Intervals(anIntervals2, GeomAbs_C2);
+  C1.Intervals(anIntervals1, aContinuity);
+  C2.Intervals(anIntervals2, aContinuity);
 
   Extrema_GlobOptFuncCCC2 aFunc (C1, C2);
   math_GlobOptMin aFinder(&aFunc, myLowBorder, myUppBorder);
+  aFinder.SetContinuity(aContinuity == GeomAbs_C2 ? 2 : 1);
   Standard_Real aDiscTol = 1.0e-2;
   Standard_Real aValueTol = 1.0e-2;
   Standard_Real aSameTol = myCurveMinTol / (aDiscTol);
@@ -149,7 +162,7 @@ void Extrema_GenExtCC::Perform()
       aSecondBorderInterval(2) = anIntervals2(j + 1);
 
       aFinder.SetLocalParams(aFirstBorderInterval, aSecondBorderInterval);
-      aFinder.Perform();
+      aFinder.Perform(GetSingleSolutionFlag());
 
       // check that solution found on current interval is not worse than previous
       aCurrF = aFinder.GetF();
@@ -242,4 +255,22 @@ void Extrema_GenExtCC::Points(const Standard_Integer N,
 
   P1.SetValues(myPoints1(N), Tool1::Value(*((Curve1*)myC[0]), myPoints1(N)));
   P2.SetValues(myPoints2(N), Tool2::Value(*((Curve2*)myC[1]), myPoints2(N)));
-}
\ No newline at end of file
+}
+
+//=======================================================================
+//function : SetSingleSolutionFlag
+//purpose  : 
+//=======================================================================
+void Extrema_GenExtCC::SetSingleSolutionFlag(const Standard_Boolean theFlag)
+{
+  myIsFindSingleSolution = theFlag;
+}
+
+//=======================================================================
+//function : GetSingleSolutionFlag
+//purpose  : 
+//=======================================================================
+Standard_Boolean Extrema_GenExtCC::GetSingleSolutionFlag() const
+{
+  return myIsFindSingleSolution;
+}
index 1d5cc6e470602c7dfcd7c528e22f1df4d28457fe..b4f785b68a94ab1754ec1b7c5416d7d195409ca3 100644 (file)
 // Alternatively, this file may be used under the terms of Open CASCADE
 // commercial license or contractual agreement.
 
+
+#include <algorithm>
+
 #include <ProjLib_CompProjectedCurve.ixx>
 #include <ProjLib_HCompProjectedCurve.hxx>
 #include <gp_XY.hxx>
+#include <Adaptor2d_HCurve2d.hxx>
+#include <Adaptor3d_HCurve.hxx>
+#include <Adaptor3d_HSurface.hxx>
 #include <gp_Mat2d.hxx>
 #include <Extrema_ExtPS.hxx>
 #include <Precision.hxx>
 #include <ProjLib_PrjResolve.hxx>
 #include <GeomAbs_CurveType.hxx>
 #include <GeomLib.hxx>
+#include <Adaptor3d_CurveOnSurface.hxx>
+#include <Geom2d_Line.hxx>
+#include <Geom2dAdaptor_HCurve.hxx>
+#include <Extrema_ExtCC.hxx>
+#include <NCollection_Vector.hxx>
 
 #define FuncTol 1.e-10
 
@@ -54,6 +65,59 @@ static void ResultChron( OSD_Chronometer & ch, Standard_Real & time)
 }
 #endif
 
+// Structure to perform splits computation.
+// This structure is not thread-safe since operations under mySplits should be performed in a critical section.
+// myPeriodicDir - 0 for U periodicity and 1 for V periodicity.
+struct SplitDS
+{
+  SplitDS(const Handle(Adaptor3d_HCurve)   &theCurve,
+          const Handle(Adaptor3d_HSurface) &theSurface,
+          NCollection_Vector<Standard_Real> &theSplits)
+  : myCurve(theCurve),
+    mySurface(theSurface),
+    mySplits(theSplits)
+  { }
+
+  // Assignment operator is forbidden.
+  void operator=(const SplitDS &theSplitDS);
+
+  const Handle(Adaptor3d_HCurve) myCurve;
+  const Handle(Adaptor3d_HSurface) mySurface;
+  NCollection_Vector<Standard_Real> &mySplits;
+
+  Standard_Real myPerMinParam;
+  Standard_Real myPerMaxParam;
+  Standard_Integer myPeriodicDir;
+
+  Extrema_ExtCC *myExtCC;
+  Extrema_ExtPS *myExtPS;
+};
+
+  //! Compute split points in the parameter space of the curve.
+  static void BuildCurveSplits(const Handle(Adaptor3d_HCurve)   &theCurve,
+                               const Handle(Adaptor3d_HSurface) &theSurface,
+                               const Standard_Real theTolU,
+                               const Standard_Real theTolV,
+                               NCollection_Vector<Standard_Real> &theSplits);
+
+  //! Perform splitting on a specified direction. Sub-method in BuildCurveSplits.
+  static void SplitOnDirection(SplitDS & theSplitDS);
+
+  //! Perform recursive search of the split points.
+  static void FindSplitPoint(SplitDS & theSplitDS,
+                             const Standard_Real theMinParam,
+                             const Standard_Real theMaxParam);
+
+
+//=======================================================================
+//function : Comparator
+//purpose  : used in sort algorithm
+//=======================================================================
+inline Standard_Boolean Comparator(const Standard_Real theA,
+                                   const Standard_Real theB)
+{
+  return theA < theB;
+}
 
 //=======================================================================
 //function : d1
@@ -554,34 +618,36 @@ ProjLib_CompProjectedCurve::ProjLib_CompProjectedCurve
 void ProjLib_CompProjectedCurve::Init() 
 {
   myTabInt.Nullify();
+  NCollection_Vector<Standard_Real> aSplits;
 
   Standard_Real Tol;// Tolerance for ExactBound
-  Standard_Integer i, Nend = 0;
-  Standard_Boolean FromLastU=Standard_False;
-
-  //new part (to discard far solutions)
-  Standard_Real TolC = Precision::Confusion(), TolS = Precision::Confusion();
-  Extrema_ExtCS CExt(myCurve->Curve(),
-    mySurface->Surface(),
-    TolC,
-    TolS);
-  if (CExt.IsDone() && CExt.NbExt()) 
+  Standard_Integer i, Nend = 0, aSplitIdx = 0;
+  Standard_Boolean FromLastU = Standard_False,
+                   isSplitsComputed = Standard_False;
+
+  const Standard_Real aTol3D = Precision::Confusion();
+  Extrema_ExtCS CExt(myCurve->Curve(), mySurface->Surface(), aTol3D, aTol3D);
+  if (CExt.IsDone() && CExt.NbExt())
   {
-    // Search for the minimum solution
-    Nend = CExt.NbExt();
+    // Search for the minimum solution.
+    // Avoid usage of extrema result that can be wrong for extrusion.
     if(myMaxDist > 0 &&
-       // Avoid usage of extrema result that can be wrong for extrusion
+
        mySurface->GetType() != GeomAbs_SurfaceOfExtrusion)
     {
       Standard_Real min_val2;
       min_val2 = CExt.SquareDistance(1);
+
+      Nend = CExt.NbExt();
       for(i = 2; i <= Nend; i++)
-        if (CExt.SquareDistance(i) < min_val2) min_val2 = CExt.SquareDistance(i);
+      {
+        if (CExt.SquareDistance(i) < min_val2) 
+          min_val2 = CExt.SquareDistance(i);
+      }
       if (min_val2 > myMaxDist * myMaxDist)
-        return;
+        return; // No near solution -> exit.
     }
   }
-  // end of new part
 
   Standard_Real FirstU, LastU, Step, SearchStep, WalkStep, t;
 
@@ -595,12 +661,9 @@ void ProjLib_CompProjectedCurve::Init()
   SearchStep = 10*MinStep;
   Step = SearchStep;
 
-  //Initialization of aPrjPS
-  Standard_Real Uinf = mySurface->FirstUParameter();
-  Standard_Real Usup = mySurface->LastUParameter();
-  Standard_Real Vinf = mySurface->FirstVParameter();
-  Standard_Real Vsup = mySurface->LastVParameter();
-
+  gp_Pnt2d aLowBorder(mySurface->FirstUParameter(),mySurface->FirstVParameter());
+  gp_Pnt2d aUppBorder(mySurface->LastUParameter(), mySurface->LastVParameter());
+  gp_Pnt2d aTol(myTolU, myTolV);
   ProjLib_PrjResolve aPrjPS(myCurve->Curve(), mySurface->Surface(), 1);
 
   t = FirstU;
@@ -638,10 +701,8 @@ void ProjLib_CompProjectedCurve::Init()
           ParT=P1.Parameter();
           P2.Parameter(ParU, ParV);
 
-          aPrjPS.Perform(ParT, ParU, ParV, gp_Pnt2d(myTolU, myTolV), 
-            gp_Pnt2d(mySurface->FirstUParameter(),mySurface->FirstVParameter()), 
-            gp_Pnt2d(mySurface->LastUParameter(), mySurface->LastVParameter()), 
-            FuncTol, Standard_True);           
+          aPrjPS.Perform(ParT, ParU, ParV, aTol, aLowBorder, aUppBorder, FuncTol, Standard_True);
+
           if ( aPrjPS.IsDone() && P1.Parameter() > Max(FirstU,t-Step+Precision::PConfusion()) 
             && P1.Parameter() <= t) 
           {
@@ -655,7 +716,7 @@ void ProjLib_CompProjectedCurve::Init()
         }
       }
       if (!initpoint) 
-      {        
+      {
         myCurve->D0(t,CPoint);
 #ifdef OCCT_DEBUG_CHRONO
         InitChron(chr_init_point);
@@ -674,38 +735,37 @@ void ProjLib_CompProjectedCurve::Init()
         gp_Vec2d D;
 
         if ((mySurface->IsUPeriodic() &&
-            Abs(Usup - Uinf - mySurface->UPeriod()) < Precision::Confusion()) ||
+            Abs(aUppBorder.X() - aLowBorder.X() - mySurface->UPeriod()) < Precision::Confusion()) ||
             (mySurface->IsVPeriodic() && 
-            Abs(Vsup - Vinf - mySurface->VPeriod()) < Precision::Confusion()))
+            Abs(aUppBorder.Y() - aLowBorder.Y() - mySurface->VPeriod()) < Precision::Confusion()))
         {
-          if((Abs(U - Uinf) < mySurface->UResolution(Precision::PConfusion())) &&
+          if((Abs(U - aLowBorder.X()) < mySurface->UResolution(Precision::PConfusion())) &&
             mySurface->IsUPeriodic())
           { 
             d1(t, U, V, D, myCurve, mySurface);
-            if (D.X() < 0 ) U = Usup;
+            if (D.X() < 0 ) U = aUppBorder.X();
           }
-          else if((Abs(U - Usup) < mySurface->UResolution(Precision::PConfusion())) &&
+          else if((Abs(U - aUppBorder.X()) < mySurface->UResolution(Precision::PConfusion())) &&
             mySurface->IsUPeriodic())
           {
             d1(t, U, V, D, myCurve, mySurface);
-            if (D.X() > 0) U = Uinf;
+            if (D.X() > 0) U = aLowBorder.X();
           }
 
-          if((Abs(V - Vinf) < mySurface->VResolution(Precision::PConfusion())) && 
+          if((Abs(V - aLowBorder.Y()) < mySurface->VResolution(Precision::PConfusion())) && 
             mySurface->IsVPeriodic()) 
           {
             d1(t, U, V, D, myCurve, mySurface);
-            if (D.Y() < 0) V = Vsup;
+            if (D.Y() < 0) V = aUppBorder.Y();
           }
-          else if((Abs(V - Vsup) <= mySurface->VResolution(Precision::PConfusion())) &&
+          else if((Abs(V - aUppBorder.Y()) <= mySurface->VResolution(Precision::PConfusion())) &&
             mySurface->IsVPeriodic())
           {
             d1(t, U, V, D, myCurve, mySurface);
-            if (D.Y() > 0) V = Vinf;
+            if (D.Y() > 0) V = aLowBorder.Y();
           }
         }
 
-
         if (myMaxDist > 0) 
         {
           // Here we are going to stop if the distance between projection and 
@@ -755,7 +815,6 @@ void ProjLib_CompProjectedCurve::Init()
     }
     if (!new_part) break;
 
-
     //We have found a new continuous part
     Handle(TColgp_HSequenceOfPnt) hSeq = new TColgp_HSequenceOfPnt();    
     mySequence->Append(hSeq);
@@ -780,9 +839,7 @@ void ProjLib_CompProjectedCurve::Init()
     if (t > LastU) t = LastU;
     Standard_Real prevStep = Step;
     Standard_Real U0, V0;
-    gp_Pnt2d aLowBorder(mySurface->FirstUParameter(),mySurface->FirstVParameter());
-    gp_Pnt2d aUppBorder(mySurface->LastUParameter(), mySurface->LastVParameter());
-    gp_Pnt2d aTol(myTolU, myTolV);
+
     //Here we are trying to prolong continuous part
     while (t <= LastU && new_part) 
     {
@@ -869,6 +926,33 @@ void ProjLib_CompProjectedCurve::Init()
           Triple.SetZ(V);
         }
 
+        // Protection from case when the whole curve lies on a seam.
+        if (!isSplitsComputed)
+        {
+          Standard_Boolean isUPossible = Standard_False;
+          if (mySurface->IsUPeriodic() &&
+             (Abs(Triple.Y() - mySurface->FirstUParameter() ) > Precision::PConfusion() &&
+              Abs(Triple.Y() - mySurface->LastUParameter()  ) > Precision::PConfusion()))
+          {
+            isUPossible = Standard_True;
+          }
+
+          Standard_Boolean isVPossible = Standard_False;
+          if (mySurface->IsVPeriodic() &&
+             (Abs(Triple.Z() - mySurface->FirstVParameter() ) > Precision::PConfusion() &&
+              Abs(Triple.Z() - mySurface->LastVParameter()  ) > Precision::PConfusion()))
+          {
+            isVPossible = Standard_True;
+          }
+
+          if (isUPossible || isVPossible)
+          {
+            // When point is good conditioned.
+            BuildCurveSplits(myCurve, mySurface, myTolU, myTolV, aSplits);
+            isSplitsComputed = Standard_True;
+          }
+        }
+
         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;
@@ -882,15 +966,38 @@ void ProjLib_CompProjectedCurve::Init()
 
         Step = WalkStep;
         t += Step;
-        if (t > (LastU-MinStep/2) ) 
+        if (t > (LastU-MinStep/2))
         {
-          Step =Step+LastU-t;
+          Step = Step + LastU - t;
           t = LastU;
-        }      
+        }
+
+        // We assume at least one point of cache inside of a split.
+        const Standard_Integer aSize = aSplits.Size();
+        for(Standard_Integer anIdx = aSplitIdx; anIdx < aSize; ++anIdx)
+        {
+          const Standard_Real aParam = aSplits(anIdx);
+          if (Abs(aParam - Triple.X() ) < Precision::PConfusion())
+          {
+            // The current point is equal to a split point.
+            new_part = Standard_False;
+
+            // Move split index to avoid check of the whole list.
+            ++aSplitIdx;
+            break;
+          }
+          else if (aParam < t + Precision::PConfusion() )
+          {
+            // The next point crosses the split point.
+            t = aParam;
+            Step = t - prevTriple.X();
+          }
+        } // for(Standard_Integer anIdx = aSplitIdx; anIdx < aSize; ++anIdx)
       }
     }
   }
-  // Sequence postproceeding
+
+  // Sequence post-proceeding.
   Standard_Integer j;
 
   // 1. Removing poor parts
@@ -1613,3 +1720,161 @@ GeomAbs_CurveType ProjLib_CompProjectedCurve::GetType() const
 {
   return GeomAbs_OtherCurve;
 }
+
+//=======================================================================
+//function : BuildCurveSplits
+//purpose  : 
+//=======================================================================
+void BuildCurveSplits(const Handle(Adaptor3d_HCurve)   &theCurve,
+                      const Handle(Adaptor3d_HSurface) &theSurface,
+                      const Standard_Real theTolU,
+                      const Standard_Real theTolV,
+                      NCollection_Vector<Standard_Real> &theSplits)
+{
+  SplitDS aDS(theCurve, theSurface, theSplits);
+
+  Extrema_ExtPS anExtPS;
+  anExtPS.Initialize(theSurface->Surface(),
+                     theSurface->FirstUParameter(), theSurface->LastUParameter(),
+                     theSurface->FirstVParameter(), theSurface->LastVParameter(),
+                     theTolU, theTolV);
+  aDS.myExtPS = &anExtPS;
+
+  if (theSurface->IsUPeriodic())
+  {
+    aDS.myPeriodicDir = 0;
+    SplitOnDirection(aDS);
+  }
+  if (theSurface->IsVPeriodic())
+  {
+    aDS.myPeriodicDir = 1;
+    SplitOnDirection(aDS);
+  }
+
+  std::sort(aDS.mySplits.begin(), aDS.mySplits.end(), Comparator);
+}
+
+//=======================================================================
+//function : SplitOnDirection
+//purpose  : This method compute points in the parameter space of the curve
+//           on which curve should be split since period jump is happen.
+//=======================================================================
+void SplitOnDirection(SplitDS & theSplitDS)
+{
+  // Algorithm:
+  // Create 3D curve which is correspond to the periodic bound in 2d space.
+  // Run curve / curve extrema and run extrema point / surface to check that
+  // the point will be projected to the periodic bound.
+  // In this method assumed that the points cannot be closer to each other that 1% of the parameter space.
+
+  gp_Pnt2d aStartPnt(theSplitDS.mySurface->FirstUParameter(), theSplitDS.mySurface->FirstVParameter());
+  gp_Dir2d aDir(theSplitDS.myPeriodicDir, (Standard_Integer)!theSplitDS.myPeriodicDir);
+
+  theSplitDS.myPerMinParam = !theSplitDS.myPeriodicDir ? theSplitDS.mySurface->FirstUParameter():
+                                                         theSplitDS.mySurface->FirstVParameter();
+  theSplitDS.myPerMaxParam = !theSplitDS.myPeriodicDir ? theSplitDS.mySurface->LastUParameter():
+                                                         theSplitDS.mySurface->LastVParameter();
+  Standard_Real aLast2DParam = theSplitDS.myPeriodicDir ? 
+                               theSplitDS.mySurface->LastUParameter() - theSplitDS.mySurface->FirstUParameter():
+                               theSplitDS.mySurface->LastVParameter() - theSplitDS.mySurface->FirstVParameter();
+
+  // Create line which is represent periodic border.
+  Handle(Geom2d_Curve) aC2GC = new Geom2d_Line(aStartPnt, aDir);
+  Handle(Geom2dAdaptor_HCurve) aC = new Geom2dAdaptor_HCurve(aC2GC, 0, aLast2DParam);
+  Adaptor3d_CurveOnSurface  aCOnS(aC, theSplitDS.mySurface);
+
+  Extrema_ExtCC anExtCC;
+  anExtCC.SetCurve(1, aCOnS);
+  anExtCC.SetCurve(2, theSplitDS.myCurve->Curve());
+  anExtCC.SetRange(1, 0, aLast2DParam);
+  anExtCC.SetSingleSolutionFlag(Standard_True);
+  theSplitDS.myExtCC = &anExtCC;
+
+  FindSplitPoint(theSplitDS,
+                 theSplitDS.myCurve->FirstParameter(), // Initial curve range.
+                 theSplitDS.myCurve->LastParameter());
+}
+
+
+//=======================================================================
+//function : FindSplitPoint
+//purpose  : 
+//=======================================================================
+void FindSplitPoint(SplitDS &theSplitDS,
+                    const Standard_Real theMinParam,
+                    const Standard_Real theMaxParam)
+{
+  // Make extrema copy to avoid dependencies between different levels of the recursion.
+  Extrema_ExtCC anExtCC(*theSplitDS.myExtCC);
+  anExtCC.SetRange(2, theMinParam, theMaxParam);
+  anExtCC.Perform();
+
+  if (anExtCC.IsDone())
+  {
+    const Standard_Integer aNbExt = anExtCC.NbExt();
+    for (Standard_Integer anIdx = 1; anIdx <= aNbExt; ++anIdx)
+    {
+      Extrema_POnCurv aPOnC1, aPOnC2;
+      anExtCC.Points(anIdx, aPOnC1, aPOnC2);
+
+      theSplitDS.myExtPS->Perform(aPOnC2.Value());
+      if (!theSplitDS.myExtPS->IsDone())
+        return;
+
+      // Find point with the minimal Euclidean distance to avoid
+      // false positive points detection.
+      Standard_Integer aMinIdx = -1;
+      Standard_Real aMinSqDist = RealLast();
+      const Standard_Integer aNbPext = theSplitDS.myExtPS->NbExt();
+      for(Standard_Integer aPIdx = 1; aPIdx <= aNbPext; ++aPIdx)
+      {
+        const Standard_Real aCurrSqDist = theSplitDS.myExtPS->SquareDistance(aPIdx);
+
+        if (aCurrSqDist < aMinSqDist)
+        {
+          aMinSqDist = aCurrSqDist;
+          aMinIdx = aPIdx;
+        }
+      }
+
+      // Check that is point will be projected to the periodic border.
+      const Extrema_POnSurf &aPOnS = theSplitDS.myExtPS->Point(aMinIdx);
+      Standard_Real U, V, aProjParam;
+      aPOnS.Parameter(U, V);
+      aProjParam = theSplitDS.myPeriodicDir ? V : U;
+
+
+      if (Abs(aProjParam - theSplitDS.myPerMinParam) < Precision::PConfusion() ||
+          Abs(aProjParam - theSplitDS.myPerMaxParam) < Precision::PConfusion() )
+      {
+        const Standard_Real aParam = aPOnC2.Parameter();
+        const Standard_Real aCFParam = theSplitDS.myCurve->FirstParameter();
+        const Standard_Real aCLParam = theSplitDS.myCurve->LastParameter();
+
+        if (aParam > aCFParam + Precision::PConfusion() &&
+            aParam < aCLParam  - Precision::PConfusion() )
+        {
+          // Add only inner points.
+          theSplitDS.mySplits.Append(aParam);
+        }
+
+        const Standard_Real aDeltaCoeff = 0.01;
+        const Standard_Real aDelta = (theMaxParam - theMinParam + 
+                                      aCLParam - aCFParam) * aDeltaCoeff;
+
+        if (aParam - aDelta > theMinParam + Precision::PConfusion())
+        {
+          FindSplitPoint(theSplitDS,
+                         theMinParam, aParam - aDelta); // Curve parameters.
+        }
+
+        if (aParam + aDelta < theMaxParam - Precision::PConfusion())
+        {
+          FindSplitPoint(theSplitDS,
+                         aParam + aDelta, theMaxParam); // Curve parameters.
+        }
+      }
+
+    } // for (Standard_Integer anIdx = 1; anIdx <= aNbExt; ++anIdx)
+  }
+}
index ce474511f384eb9d25f127dea03656b76aba4b4c..0ada2da500bde207dc438ad99993771835b04d11 100644 (file)
@@ -45,12 +45,14 @@ math_GlobOptMin::math_GlobOptMin(math_MultipleVarFunction* theFunc,
   myTmp(1, myN),
   myV(1, myN),
   myMaxV(1, myN),
-  myExpandCoeff(1, myN)
+  myExpandCoeff(1, myN),
+  myCont(2)
 {
   Standard_Integer i;
 
   myFunc = theFunc;
   myC = theC;
+  myIsFindSingleSolution = Standard_False;
   myZ = -1;
   mySolCount = 0;
 
@@ -191,7 +193,7 @@ math_GlobOptMin::~math_GlobOptMin()
 //purpose  : Compute Global extremum point
 //=======================================================================
 // In this algo indexes started from 1, not from 0.
-void math_GlobOptMin::Perform()
+void math_GlobOptMin::Perform(const Standard_Boolean isFindSingleSolution)
 {
   Standard_Integer i;
 
@@ -221,10 +223,21 @@ void math_GlobOptMin::Perform()
 
   myE1 = minLength * myTol;
   myE2 = maxLength * myTol;
-  if (myC > 1.0)
-    myE3 = - maxLength * myTol / 4.0;
+
+  myIsFindSingleSolution = isFindSingleSolution;
+  if (isFindSingleSolution)
+  {
+    // Run local optimization 
+    // if current value better than optimal.
+    myE3 = 0.0;
+  }
   else
-    myE3 = - maxLength * myTol * myC / 4.0;
+  {
+    if (myC > 1.0)
+      myE3 = - maxLength * myTol / 4.0;
+    else
+      myE3 = - maxLength * myTol * myC / 4.0;
+  }
 
   computeGlobalExtremum(myN);
 
@@ -242,7 +255,8 @@ Standard_Boolean math_GlobOptMin::computeLocalExtremum(const math_Vector& thePnt
   Standard_Integer i;
 
   //Newton method
-  if (dynamic_cast<math_MultipleVarFunctionWithHessian*>(myFunc))
+  if (myCont >= 2 &&
+      dynamic_cast<math_MultipleVarFunctionWithHessian*>(myFunc))
   {
     math_MultipleVarFunctionWithHessian* myTmp = 
       dynamic_cast<math_MultipleVarFunctionWithHessian*> (myFunc);
@@ -259,7 +273,8 @@ Standard_Boolean math_GlobOptMin::computeLocalExtremum(const math_Vector& thePnt
   } else
 
   // BFGS method used.
-  if (dynamic_cast<math_MultipleVarFunctionWithGradient*>(myFunc))
+  if (myCont >= 1 &&
+      dynamic_cast<math_MultipleVarFunctionWithGradient*>(myFunc))
   {
     math_MultipleVarFunctionWithGradient* myTmp = 
       dynamic_cast<math_MultipleVarFunctionWithGradient*> (myFunc);
@@ -404,8 +419,10 @@ void math_GlobOptMin::computeGlobalExtremum(Standard_Integer j)
       aStepBestValue = (isInside && (val < d))? val : d;
       aStepBestPoint = (isInside && (val < d))? myTmp : myX;
 
-      // Solutions are close to each other.
-      if (Abs(aStepBestValue - myF) < mySameTol * 0.01)
+      // Solutions are close to each other 
+      // and it is allowed to have more than one solution.
+      if (Abs(aStepBestValue - myF) < mySameTol * 0.01 &&
+          !myIsFindSingleSolution)
       {
         if (!isStored(aStepBestPoint))
         {
@@ -417,8 +434,12 @@ void math_GlobOptMin::computeGlobalExtremum(Standard_Integer j)
         }
       }
 
-      // New best solution.
-      if ((aStepBestValue - myF) * myZ > mySameTol * 0.01)
+      // New best solution:
+      // new point is out of (mySameTol * 0.01) surrounding or
+      // new point is better than old + single point search.
+      Standard_Real aFunctionalDelta = (aStepBestValue - myF) * myZ;
+      if (aFunctionalDelta > mySameTol * 0.01 ||
+         (aFunctionalDelta > 0.0 && myIsFindSingleSolution))
       {
         mySolCount = 0;
         myF = aStepBestValue;
index 27d483471804395d47f02fb5d04280e5a780f3b5..b18f93de88366ede04882e8ad4edb84b02718de3 100644 (file)
@@ -53,7 +53,8 @@ public:
 
   Standard_EXPORT ~math_GlobOptMin();
 
-  Standard_EXPORT void Perform();
+  //! @param isFindSingleSolution - defines whether to find single solution or all solutions.
+  Standard_EXPORT void Perform(const Standard_Boolean isFindSingleSolution = Standard_False);
 
   //! Get best functional value.
   Standard_EXPORT Standard_Real GetF();
@@ -66,6 +67,12 @@ public:
 
   Standard_Boolean isDone();
 
+  //! Get continuity of local borders splits.
+  inline Standard_Integer GetContinuity() const { return myCont; }
+
+  //! Set continuity of local borders splits.
+  inline void SetContinuity(const Standard_Integer theCont) { myCont = theCont; }
+
 private:
 
   math_GlobOptMin & operator = (const math_GlobOptMin & theOther);
@@ -99,6 +106,7 @@ private:
                            // function values |val1 - val2| * 0.01 < mySameTol is equal,
                            // default value is 1.0e-7.
   Standard_Real myC; //Lipschitz constant, default 9
+  Standard_Boolean myIsFindSingleSolution; // Default value is false.
 
   // Output.
   Standard_Boolean myDone;
@@ -117,6 +125,9 @@ private:
   math_Vector myMaxV; // Max Steps array.
   math_Vector myExpandCoeff; // Define expand coefficient between neighboring indiced dimensions.
 
+  // Continuity of local borders.
+  Standard_Integer myCont;
+
   Standard_Real myF; // Current value of Global optimum.
 };
 
diff --git a/tests/bugs/moddata_3/bug27299_1 b/tests/bugs/moddata_3/bug27299_1
new file mode 100644 (file)
index 0000000..8e50765
--- /dev/null
@@ -0,0 +1,20 @@
+puts "================"
+puts "0027299"
+puts "================"
+puts ""
+##############################################################
+# Incorrect result of the normal projection algorithm
+# Exception during the exectuion
+##############################################################
+
+restore [locate_data_file bug27299_1.brep] aShape
+explode aShape
+
+nproject result aShape_1 aShape_2
+
+# Visual check.
+donly result
+smallview
+fit
+display aShape_2
+xwd ${imagedir}/${test_image}.png
diff --git a/tests/bugs/moddata_3/bug27299_2 b/tests/bugs/moddata_3/bug27299_2
new file mode 100644 (file)
index 0000000..7f49d5c
--- /dev/null
@@ -0,0 +1,23 @@
+puts "================"
+puts "0027299"
+puts "================"
+puts ""
+##############################################################
+# Incorrect result of the normal projection algorithm
+# Exception during the exectuion
+##############################################################
+
+restore [locate_data_file bug27299_1.brep] aShape
+explode aShape
+
+# To make task non-symmetry.
+ttranslate aShape_1 0 0 135.123
+
+nproject result aShape_1 aShape_2
+
+# Visual check.
+donly result
+smallview
+fit
+display aShape_2
+xwd ${imagedir}/${test_image}.png
diff --git a/tests/bugs/moddata_3/bug27299_3 b/tests/bugs/moddata_3/bug27299_3
new file mode 100644 (file)
index 0000000..703d8c8
--- /dev/null
@@ -0,0 +1,20 @@
+puts "================"
+puts "0027299"
+puts "================"
+puts ""
+##############################################################
+# Incorrect result of the normal projection algorithm
+# Exception during the exectuion
+##############################################################
+
+restore [locate_data_file bug27299_2.brep] aShape
+explode aShape
+
+nproject result aShape_1 aShape_2
+
+# Visual check.
+donly result
+smallview
+fit
+display aShape_2
+xwd ${imagedir}/${test_image}.png