0027322: geom/revolution_00/A1: Incorrect pcurve creation
[occt.git] / src / ProjLib / ProjLib_ComputeApprox.cxx
index c94977c..75966fe 100644 (file)
@@ -48,7 +48,7 @@
 #include <DrawTrSurf.hxx>
 #endif
 #ifdef OCCT_DEBUG
-static Standard_Boolean AffichValue = Standard_False;
+//static Standard_Boolean AffichValue = Standard_False;
 #endif    
 
 //=======================================================================
@@ -137,7 +137,7 @@ static gp_Pnt2d Function_Value(const Standard_Real U,
     if(T < V1 || T > V2)
       T = ElCLib::InPeriod(T, V1, V2);
   }
-  
+
   return gp_Pnt2d(S, T);
 }
 //=======================================================================
@@ -225,8 +225,28 @@ static void Function_SetUVBounds(Standard_Real& myU1,
   switch ( mySurface->GetType()) {
 
     case GeomAbs_Cone:    {
+      Standard_Real tol = Epsilon(1.);
+      Standard_Real ptol = Precision::PConfusion();
       gp_Cone Cone = mySurface->Cone();
       VCouture = Standard_False;
+      //Calculation of cone parameters for P == ConeApex often produces wrong
+      //values of U
+      gp_Pnt ConeApex = Cone.Apex();
+      if(ConeApex.XYZ().IsEqual(P1.XYZ(), tol))
+      {
+        W1 += ptol;
+        P1 = myCurve->Value(W1);
+      }
+      if(ConeApex.XYZ().IsEqual(P2.XYZ(), tol))
+      {
+        W2 -= ptol;
+        P2 = myCurve->Value(W2);
+      }
+      if(ConeApex.XYZ().IsEqual(P.XYZ(), tol))
+      {
+        W += ptol;
+        P = myCurve->Value(W);
+      }
 
       switch( myCurve->GetType() ){
       case GeomAbs_Parabola:
@@ -255,26 +275,54 @@ static void Function_SetUVBounds(Standard_Real& myU1,
         myU1 = U1; myU2 = U1; Uf = U1; 
         Standard_Real Step = .1;
         Standard_Integer nbp = (Standard_Integer)((W2 - W1) / Step + 1);
+        if(myCurve->GetType() == GeomAbs_Line)
+        {
+          nbp = 3;
+        }
         nbp = Max(nbp, 3);
         Step = (W2 - W1) / (nbp - 1);
         Standard_Boolean isclandper = (!(myCurve->IsClosed()) && !(myCurve->IsPeriodic()));
-        for(Standard_Real par = W1 + Step; par <= W2; par += Step) {
+        Standard_Boolean isFirst = Standard_True;
+        for(Standard_Real par = W1 + Step; par <= W2; par += Step)
+        {
           if(!isclandper) par += Step;
           P = myCurve->Value(par);
           ElSLib::Parameters( Cone, P, U, V);
           U += Delta;
           d = U - U1;
-          if(d > M_PI)  {
+          if(d > M_PI)
+          {
             if( ( (IsEqual(U,(2*M_PI),1.e-10) && (U1 >= 0. && U1 <= M_PI)) && 
-              (IsEqual(U,Ul,1.e-10) && !IsEqual(Uf,0.,1.e-10)) ) && isclandper ) U = 0.;
-            else Delta -= 2*M_PI;
+              (IsEqual(U,Ul,1.e-10) && !IsEqual(Uf,0.,1.e-10)) ) && isclandper )
+              U = 0.0;
+            else
+            {
+              // Protection against first-last point on seam.
+              if (isFirst)
+                U1 = 2*M_PI;
+              else if (par + Step >= W2)
+                U = 0.0;
+              else
+                Delta -= 2*M_PI;
+            }
             U += Delta;
             d = U - U1;
           }
-          else if(d < -M_PI)     {
+          else if(d < -M_PI)
+          {
             if( ( (IsEqual(U,0.,1.e-10) && (U1 >= M_PI && U1 <= (2*M_PI))) &&
-              (IsEqual(U,Ul,1.e-10) && !IsEqual(Uf,(2*M_PI),1.e-10)) ) && isclandper ) U = 2*M_PI;
-            else Delta += 2*M_PI;
+              (IsEqual(U,Ul,1.e-10) && !IsEqual(Uf,(2*M_PI),1.e-10)) ) && isclandper )
+              U = 2*M_PI;
+            else
+            {
+              // Protection against first-last point on seam.
+              if (isFirst)
+                U1 = 0.0;
+              else if (par + Step >= W2)
+                U = 2*M_PI;
+              else
+                Delta += 2*M_PI;
+            }
             U += Delta;
             d = U - U1;
           }
@@ -282,7 +330,8 @@ static void Function_SetUVBounds(Standard_Real& myU1,
           if(U < myU1) {myU1 = U; pmin = par;}
           if(U > myU2) {myU2 = U; pmax = par;}
           U1 = U;
-        }
+          isFirst = Standard_False;
+        } // for(Standard_Real par = W1 + Step; par <= W2; par += Step)
 
         if(!(Abs(pmin - W1) <= Precision::PConfusion() || Abs(pmin - W2) <= Precision::PConfusion()) ) myU1 -= dmax*.5;
         if(!(Abs(pmax - W1) <= Precision::PConfusion() || Abs(pmax - W2) <= Precision::PConfusion()) ) myU2 += dmax*.5;
@@ -516,9 +565,11 @@ static void Function_SetUVBounds(Standard_Real& myU1,
       }
       //
       ElSLib::Parameters(SP, P, UU, V1);
-      Standard_Real UUmi = Min(Min(U1,UU),Min(UU,U2));
-      Standard_Real UUma = Max(Max(U1,UU),Max(UU,U2));
-      Standard_Boolean reCalc = ((UUmi >= 0. && UUmi <= M_PI) && (UUma >= 0. && UUma <= M_PI));
+      //+This fragment was the reason of bug # 26008.
+      //+It has been deleted on April, 03 2015.
+      //Standard_Real UUmi = Min(Min(U1,UU),Min(UU,U2));
+      //Standard_Real UUma = Max(Max(U1,UU),Max(UU,U2));
+      //Standard_Boolean reCalc = ((UUmi >= 0. && UUmi <= M_PI) && (UUma >= 0. && UUma <= M_PI));
       // box+sphere <<
       P2 = myCurve->Value(W1+M_PI/8);
       ElSLib::Parameters(SP,P2,U2,V2);
@@ -585,15 +636,18 @@ static void Function_SetUVBounds(Standard_Real& myU1,
 
       // box+sphere >>
       myV1 = -1.e+100; myV2 = 1.e+100;
-      Standard_Real UU1 = myU1, UU2 = myU2;
-      if((Abs(UU1) <= (2.*M_PI) && Abs(UU2) <= (2.*M_PI)) && NbSolutions == 1 && reCalc) {
-        gp_Pnt Center = Circle.Location();
-        Standard_Real U,V;
-        ElSLib::SphereParameters(gp_Ax3(gp::XOY()),1,Center, U, V);
-        myU1 = U-M_PI;
-        myU1 = Min(UU1,myU1);
-        myU2 = myU1 + 2.*M_PI;
-      }
+      
+      //+This fragment was the reason of bug # 26008.
+      //+It has been deleted on April, 03 2015.
+      //Standard_Real UU1 = myU1, UU2 = myU2;
+      //if((Abs(UU1) <= (2.*M_PI) && Abs(UU2) <= (2.*M_PI)) && NbSolutions == 1 && reCalc) {
+      //  gp_Pnt Center = Circle.Location();
+      //  Standard_Real U,V;
+      //  ElSLib::SphereParameters(gp_Ax3(gp::XOY()),1,Center, U, V);
+      //  myU1 = U-M_PI;
+      //  myU1 = Min(UU1,myU1);
+      //  myU2 = myU1 + 2.*M_PI;
+      //}
       // box+sphere <<
 
     }//if ( myCurve->GetType() == GeomAbs_Circle)
@@ -863,6 +917,7 @@ ProjLib_ComputeApprox::ProjLib_ComputeApprox
 
   Standard_Boolean CurvIsAnal = (CType != GeomAbs_BSplineCurve) &&
                                 (CType != GeomAbs_BezierCurve)  &&
+                                (CType != GeomAbs_OffsetCurve)  &&
                                 (CType != GeomAbs_OtherCurve)     ;
 
   Standard_Boolean simplecase = SurfIsAnal && CurvIsAnal;
@@ -939,30 +994,30 @@ ProjLib_ComputeApprox::ProjLib_ComputeApprox
     ProjLib_Function F( C, S);
 
 #ifdef OCCT_DEBUG
-    if ( AffichValue) {
-      Standard_Integer Nb = 20;
-      Standard_Real U1, U2, dU, U;
-      U1 = F.FirstParameter();
-      U2 = F.LastParameter();
-      dU = ( U2 - U1) / Nb;
-      TColStd_Array1OfInteger Mults(1,Nb+1);
-      TColStd_Array1OfReal    Knots(1,Nb+1);
-      TColgp_Array1OfPnt2d    Poles(1,Nb+1);
-      for ( Standard_Integer i = 1; i <= Nb+1; i++) {
-             U = U1 + (i-1)*dU;
-             Poles(i) = F.Value(U);
-             Knots(i) = i;
-             Mults(i) = 1;
-      }
-      Mults(1)    = 2;
-      Mults(Nb+1) = 2;
-#ifdef DRAW
-// POP pour NT
-      char* ResultName = "Result";
-      DrawTrSurf::Set(ResultName,new Geom2d_BSplineCurve(Poles,Knots,Mults,1));
-//      DrawTrSurf::Set("Result",new Geom2d_BSplineCurve(Poles,Knots,Mults,1));
-#endif
-    }
+    //if ( AffichValue) {
+    //  Standard_Integer Nb = 20;
+    //  Standard_Real U1, U2, dU, U;
+    //  U1 = F.FirstParameter();
+    //  U2 = F.LastParameter();
+    //  dU = ( U2 - U1) / Nb;
+    //  TColStd_Array1OfInteger Mults(1,Nb+1);
+    //  TColStd_Array1OfReal    Knots(1,Nb+1);
+    //  TColgp_Array1OfPnt2d    Poles(1,Nb+1);
+    //  for ( Standard_Integer i = 1; i <= Nb+1; i++) {
+    //   U = U1 + (i-1)*dU;
+    //   Poles(i) = F.Value(U);
+    //   cout << "i = " << i << ": U = " << U << 
+    //      ", p(" << Poles(i).X() << ", " << Poles(i).Y() << ");" << endl;
+    //   Knots(i) = i;
+    //   Mults(i) = 1;
+    //  }
+    //  Mults(1)    = 2;
+    //  Mults(Nb+1) = 2;
+
+    //2D-curve for showing in DRAW
+    //  Handle(Geom2d_Curve) aCC = new Geom2d_BSplineCurve(Poles,Knots,Mults,1);
+    //  AffichValue = Standard_False;
+    //}
 #endif    
 
 //-----------