0025701: Problem with the symmetry of fillet on two perpendicular cylinders
authorjgv <jgv@opencascade.com>
Thu, 19 Feb 2015 13:09:37 +0000 (16:09 +0300)
committerbugmaster <bugmaster@opencascade.com>
Thu, 19 Feb 2015 13:10:25 +0000 (16:10 +0300)
Test case for issue CR25701

13 files changed:
src/Blend/Blend_Point.cdl
src/Blend/Blend_Point.lxx
src/Blend/Blend_Walking.cdl
src/Blend/Blend_Walking_1.gxx
src/Blend/Blend_Walking_4.gxx
src/ChFi3d/ChFi3d_Builder_0.cxx
src/ChFi3d/ChFi3d_Builder_6.cxx
src/ChFi3d/ChFi3d_ChBuilder.cxx
src/ChFi3d/ChFi3d_FilBuilder.cxx
src/ChFiDS/ChFiDS_ElSpine.cdl
src/ChFiDS/ChFiDS_ElSpine.cxx
src/TColgp/TColgp.cdl
tests/bugs/modalg_5/bug25701 [new file with mode: 0644]

index 20a86b9..1179ac7 100644 (file)
@@ -160,6 +160,11 @@ is
             PC1,PC2       : Real from Standard);
     ---Purpose: Creates a point on two curves.
        
+    SetParameter(me            : in out;
+                Param         : Real from Standard);
+    ---C++: inline
+    ---Purpose: Changes parameter on existing point
+            
     Parameter(me)
     returns Real from Standard
     ---C++: inline
index 3836ebe..fa1a431 100644 (file)
 #include <Standard_DomainError.hxx>
 #include <gp_Vec2d.hxx>
 
+inline void Blend_Point::SetParameter(const Standard_Real Param)
+{
+  prm = Param;
+}
+
 inline const gp_Pnt& Blend_Point::PointOnS1 () const
 {
   return pt1;
index c27137b..3f23cf8 100644 (file)
@@ -54,8 +54,9 @@ raises NotDone from StdFail
 
 is
 
-    Create(Surf1,Surf2: TheSurface; Domain1,Domain2: TheTopolTool)
-    
+    Create(Surf1,Surf2: TheSurface;
+          Domain1,Domain2: TheTopolTool;
+          HGuide  : HElSpine from ChFiDS)
     returns Walking from Blend;
     
     
@@ -67,7 +68,6 @@ is
 
     Perform(me: in out; F       : in out Function from Blend;
                         FInv    : in out FuncInv  from Blend;
-                       HGuide  : HElSpine from ChFiDS;
                         Pdep    : Real from Standard;
                         Pmax    : Real from Standard;
                        MaxStep : Real from Standard;
@@ -166,11 +166,22 @@ is
 
     InternalPerform (me: in out;F       : in out Function from Blend;
                                 FInv    : in out FuncInv  from Blend;
-                               HGuide  : HElSpine from ChFiDS;
                                 Bound   : Real from Standard)
                        
     is static private;
 
+    CorrectExtremityOnOneRst (me; IndexOfRst  : Integer from Standard;
+                                 theU        : Real from Standard;
+                                 theV        : Real from Standard;
+                                 theParam    : Real from Standard;
+                                 thePntOnRst : Pnt from gp;
+                                 NewU : out Real from Standard;
+                                 NewV : out Real from Standard;
+                                 NewPoint : out Pnt from gp;
+                                 NewParam : out Real from Standard)
+    returns Boolean from Standard                      
+    is static private;
+
 
     IsDone(me)
     
@@ -266,6 +277,10 @@ fields
     domain2      : TheTopolTool;
     recdomain1   : TheTopolTool;
     recdomain2   : TheTopolTool;
+    hguide       : HElSpine         from ChFiDS;
+    ToCorrectOnRst1 : Boolean from Standard;
+    ToCorrectOnRst2 : Boolean from Standard;
+    CorrectedParam  : Real    from Standard;
 
     tolesp       : Real             from Standard;
     tolgui       : Real             from Standard;
index e1455a0..44f18d3 100644 (file)
 Blend_Walking::Blend_Walking(const TheSurface& Surf1,
                             const TheSurface& Surf2,
                             const Handle(TheTopolTool)& Domain1,
-                            const Handle(TheTopolTool)& Domain2):
+                            const Handle(TheTopolTool)& Domain2,
+                             const Handle(ChFiDS_HElSpine)& HGuide):
        sol(1,4),surf1(Surf1),surf2(Surf2),
+       ToCorrectOnRst1(Standard_False),ToCorrectOnRst2(Standard_False),
        done(Standard_False),
        clasonS1(Standard_True),clasonS2(Standard_True),
        check2d(Standard_True),check(Standard_True),
@@ -26,7 +28,8 @@ Blend_Walking::Blend_Walking(const TheSurface& Surf1,
   domain1 = Domain1;
   domain2 = Domain2;
   recdomain1 = Domain1;
-  recdomain2 = Domain2;  
+  recdomain2 = Domain2;
+  hguide = HGuide;
 }
 
 void Blend_Walking::SetDomainsToRecadre(const Handle(TheTopolTool)& Domain1,
@@ -56,7 +59,6 @@ void Blend_Walking::AddSingularPoint(const Blend_Point& P)
 
 void Blend_Walking::Perform(Blend_Function& Func,
                            Blend_FuncInv& FuncInv,
-                            const Handle(ChFiDS_HElSpine)& HGuide,
                            const Standard_Real Pdep,   
                            const Standard_Real Pmax,
                            const Standard_Real MaxStep,
@@ -135,6 +137,9 @@ void Blend_Walking::Perform(Blend_Function& Func,
   nbcomputedsection = 1;
 #endif
   // Mettre a jour la ligne.
+  //Correct first parameter if needed
+  if (ToCorrectOnRst1 || ToCorrectOnRst2)
+    previousP.SetParameter(CorrectedParam);
   line->Append(previousP);
 
   if(doextremities){
@@ -155,7 +160,7 @@ void Blend_Walking::Perform(Blend_Function& Func,
     }
   }
 
-  InternalPerform(Func,FuncInv,HGuide,Pmax);
+  InternalPerform(Func,FuncInv,Pmax);
 
   done = Standard_True;
 }
@@ -255,6 +260,8 @@ Standard_Boolean Blend_Walking::PerformFirstSection (Blend_Function& Func,
   Standard_Boolean Isvtx1 = Standard_False, Isvtx2 = Standard_False;
   TheVertex Vtx1, Vtx2;
   gp_Pnt2d p2d;
+  Standard_Real CorrectedU = 0., CorrectedV = 0.;
+  gp_Pnt CorrectedPnt;
 
   Func.GetTolerance(tolerance, tolesp);
   Func.GetBounds(infbound, supbound);
@@ -358,6 +365,10 @@ Standard_Boolean Blend_Walking::PerformFirstSection (Blend_Function& Func,
     ParSol(2) = p2d.Y();
     ParSol(3) = solrst1(3);
     ParSol(4) = solrst1(4);
+    gp_Pnt thePntOnRst = TheSurfaceTool::Value(surf1,ParSol(1),ParSol(2));
+    if (CorrectExtremityOnOneRst(1, ParSol(3), ParSol(4), param, thePntOnRst,
+                                 CorrectedU,CorrectedV,CorrectedPnt,CorrectedParam))
+      ToCorrectOnRst1 = Standard_True;
   }
   else
   { //if (recad2) {
@@ -377,6 +388,10 @@ Standard_Boolean Blend_Walking::PerformFirstSection (Blend_Function& Func,
     ParSol(2) = solrst2(4);
     ParSol(3) = p2d.X();
     ParSol(4) = p2d.Y();
+    gp_Pnt thePntOnRst = TheSurfaceTool::Value(surf2,ParSol(3),ParSol(4));
+    if (CorrectExtremityOnOneRst(2, ParSol(1), ParSol(2), param, thePntOnRst,
+                                 CorrectedU,CorrectedV,CorrectedPnt,CorrectedParam))
+      ToCorrectOnRst2 = Standard_True;
   }
 
   Psol = param;
@@ -387,26 +402,32 @@ Standard_Boolean Blend_Walking::PerformFirstSection (Blend_Function& Func,
   {
   case Blend_OnRst1:
     {
-      #ifdef OCCT_DEBUG
-        if (Blend_GettraceDRAWSECT())
-        {
-          Drawsect(surf1, surf2, sol, param, Func);
-        }
-      #endif
+#ifdef OCCT_DEBUG
+      if (Blend_GettraceDRAWSECT())
+      {
+        Drawsect(surf1, surf2, sol, param, Func);
+      }
+#endif
       MakeExtremity(Ext1, Standard_True, Index1, solrst1(1), Isvtx1, Vtx1);
-      Ext2.SetValue(previousP.PointOnS2(), sol(3), sol(4), tolesp);
+      if (ToCorrectOnRst1)
+        Ext2.SetValue(CorrectedPnt, CorrectedU, CorrectedV, tolesp);
+      else
+        Ext2.SetValue(previousP.PointOnS2(), sol(3), sol(4), tolesp);
     }
     break;
 
   case Blend_OnRst2:
     {
-      #ifdef OCCT_DEBUG
-        if (Blend_GettraceDRAWSECT())
-        {
-          Drawsect(surf1, surf2, sol, param, Func);
-        }
-      #endif
-      Ext1.SetValue(previousP.PointOnS1(), sol(1), sol(2), tolesp);
+#ifdef OCCT_DEBUG
+      if (Blend_GettraceDRAWSECT())
+      {
+        Drawsect(surf1, surf2, sol, param, Func);
+      }
+#endif
+      if (ToCorrectOnRst2)
+        Ext1.SetValue(CorrectedPnt, CorrectedU, CorrectedV, tolesp);
+      else
+        Ext1.SetValue(previousP.PointOnS1(), sol(1), sol(2), tolesp);
       MakeExtremity(Ext2, Standard_False, Index2, solrst2(1), Isvtx2, Vtx2);
     }
     break;
@@ -462,8 +483,7 @@ Standard_Boolean Blend_Walking::Continu(Blend_Function& Func,
   previousP.ParametersOnS1(sol(1),sol(2));
   previousP.ParametersOnS2(sol(3),sol(4));
 
-  Handle(ChFiDS_HElSpine) anHGuide;
-  InternalPerform(Func,FuncInv,anHGuide,P);
+  InternalPerform(Func,FuncInv,P);
   return Standard_True;
 }
 
@@ -504,8 +524,7 @@ Standard_Boolean Blend_Walking::Continu(Blend_Function& Func,
   if(OnS1) clasonS1 = Standard_False;
   else clasonS2 = Standard_False;
 
-  Handle(ChFiDS_HElSpine) anHGuide;
-  InternalPerform(Func,FuncInv,anHGuide,P);
+  InternalPerform(Func,FuncInv,P);
 
   clasonS1 = Standard_True;
   clasonS2 = Standard_True;
@@ -551,8 +570,7 @@ Standard_Boolean Blend_Walking::Complete(Blend_Function& Func,
   previousP.ParametersOnS1(sol(1),sol(2));
   previousP.ParametersOnS2(sol(3),sol(4));
 
-  Handle(ChFiDS_HElSpine) anHGuide;
-  InternalPerform(Func,FuncInv,anHGuide,Pmin);
+  InternalPerform(Func,FuncInv,Pmin);
 
   iscomplete = Standard_True;
   return Standard_True;
index 26b4a3b..6d31e16 100644 (file)
 // commercial license or contractual agreement.
 
 #include <gce_MakePln.hxx>
+#include <Extrema_ExtPS.hxx>
+#include <Extrema_ExtPC.hxx>
+
+static void RecadreIfPeriodic(Standard_Real& NewU,
+                              Standard_Real& NewV,
+                              const Standard_Real OldU,
+                              const Standard_Real OldV,
+                              const Standard_Real UPeriod,
+                              const Standard_Real VPeriod)
+{
+  if (UPeriod > 0.)
+  {
+    Standard_Real sign = (NewU < OldU)? 1 : -1;
+    while (Abs(NewU - OldU) > UPeriod/2)
+      NewU += sign * UPeriod;
+  }
+  if (VPeriod > 0.)
+  {
+    Standard_Real sign = (NewV < OldV)? 1 : -1;
+    while (Abs(NewV - OldV) > VPeriod/2)
+      NewV += sign * VPeriod;
+  }
+}
 
 static void evalpinit(math_Vector& parinit,
                      const Blend_Point& previousP,
@@ -67,7 +90,6 @@ static void evalpinit(math_Vector& parinit,
 
 void Blend_Walking::InternalPerform(Blend_Function& Func,
                                    Blend_FuncInv& FuncInv,
-                                    const Handle(ChFiDS_HElSpine)& HGuide,
                                    const Standard_Real Bound)
 {
 
@@ -263,55 +285,62 @@ void Blend_Walking::InternalPerform(Blend_Function& Func,
          sol(3) = p2d.X();
          sol(4) = p2d.Y();
           Pnt2 = TheSurfaceTool::Value(surf2,sol(3),sol(4));
-          if (!HGuide.IsNull())
+          const Standard_Real TolProd = 1.e-5;
+          Standard_Real SavedParams [2];
+          Standard_Boolean SameDirs [2] = {Standard_False, Standard_False};
+          ChFiDS_ElSpine& theElSpine = hguide->ChangeCurve();
+          SavedParams[0] = theElSpine.GetSavedFirstParameter();
+          SavedParams[1] = theElSpine.GetSavedLastParameter();
+          for (Standard_Integer ind = 0; ind < 2; ind++)
           {
-            const Standard_Real TolProd = 1.e-5;
-            Standard_Real SavedParams [2];
-            Standard_Boolean SameDirs [2] = {Standard_False, Standard_False};
-            ChFiDS_ElSpine& theElSpine = HGuide->ChangeCurve();
-            SavedParams[0] = theElSpine.GetSavedFirstParameter();
-            SavedParams[1] = theElSpine.GetSavedLastParameter();
-            for (Standard_Integer ind = 0; ind < 2; ind++)
+            if (!Precision::IsInfinite(SavedParams[ind]))
             {
-              if (!Precision::IsInfinite(SavedParams[ind]))
-              {
-                //Check the original first and last parameters of guide curve
-                //for equality to found parameter <param>:
-                //check equality of tangent to guide curve and
-                //normal to plane built on 3 points:
-                //point on guide curve and points on restrictions of adjacent
-                //surfaces.
-                gp_Pnt Pnt0;
-                gp_Vec Dir0;
-                HGuide->D1(SavedParams[ind], Pnt0, Dir0);
-                Standard_Real Length = Dir0.Magnitude();
-                if (Length <= gp::Resolution())
-                  continue;
-                Dir0 /= Length;
-                gce_MakePln PlaneBuilder(Pnt0, Pnt1, Pnt2);
-                if (!PlaneBuilder.IsDone())
-                  continue;
-                gp_Pln thePlane = PlaneBuilder.Value();
-                gp_Dir DirPlane = thePlane.Axis().Direction();
-                gp_Vec theProd = Dir0 ^ DirPlane;
-                Standard_Real ProdMod = theProd.Magnitude();
-                if (ProdMod <= TolProd)
-                  SameDirs[ind] = Standard_True;
-              }
+              //Check the original first and last parameters of guide curve
+              //for equality to found parameter <param>:
+              //check equality of tangent to guide curve and
+              //normal to plane built on 3 points:
+              //point on guide curve and points on restrictions of adjacent
+              //surfaces.
+              gp_Pnt Pnt0;
+              gp_Vec Dir0;
+              hguide->D1(SavedParams[ind], Pnt0, Dir0);
+              Standard_Real Length = Dir0.Magnitude();
+              if (Length <= gp::Resolution())
+                continue;
+              Dir0 /= Length;
+              gce_MakePln PlaneBuilder(Pnt0, Pnt1, Pnt2);
+              if (!PlaneBuilder.IsDone())
+                continue;
+              gp_Pln thePlane = PlaneBuilder.Value();
+              gp_Dir DirPlane = thePlane.Axis().Direction();
+              gp_Vec theProd = Dir0 ^ DirPlane;
+              Standard_Real ProdMod = theProd.Magnitude();
+              if (ProdMod <= TolProd)
+                SameDirs[ind] = Standard_True;
             }
-            Standard_Real theParam = Precision::Infinite();
-            //Choose the closest parameter
-            if (SameDirs[0] && SameDirs[1])
-              theParam = (Abs(param - SavedParams[0]) < Abs(param - SavedParams[1]))?
-                SavedParams[0] : SavedParams[1];
-            else if (SameDirs[0])
-              theParam = SavedParams[0];
-            else if (SameDirs[1])
-              theParam = SavedParams[1];
-            
-            if (!Precision::IsInfinite(theParam))
-              param = theParam;
           }
+          Standard_Real theParam = Precision::Infinite();
+          //Choose the closest parameter
+          if (SameDirs[0] && SameDirs[1])
+            theParam = (Abs(param - SavedParams[0]) < Abs(param - SavedParams[1]))?
+              SavedParams[0] : SavedParams[1];
+          else if (SameDirs[0])
+            theParam = SavedParams[0];
+          else if (SameDirs[1])
+            theParam = SavedParams[1];
+
+          Standard_Real NewU, NewV, NewParam;
+          gp_Pnt NewPnt;
+          Standard_Boolean Corrected = CorrectExtremityOnOneRst(1, sol(3), sol(4), param, Pnt1,
+                                                                NewU, NewV, NewPnt, NewParam);
+          if (Corrected)
+          {
+            if (Abs(param - NewParam) < Abs(param - theParam))
+              theParam = NewParam;
+          }
+          
+          if (!Precision::IsInfinite(theParam))
+            param = theParam;
        }
        else if (recad1) {
          // sol sur 1
@@ -328,6 +357,17 @@ void Blend_Walking::InternalPerform(Blend_Function& Func,
          sol(2) = p2d.Y();
          sol(3) = solrst1(3);
          sol(4) = solrst1(4);
+          gp_Pnt thePntOnRst = TheSurfaceTool::Value(surf1,sol(1),sol(2));
+          Standard_Real NewU, NewV, NewParam;
+          gp_Pnt NewPnt;
+          Standard_Boolean Corrected = CorrectExtremityOnOneRst(1, sol(3), sol(4), param, thePntOnRst,
+                                                                NewU, NewV, NewPnt, NewParam);
+          if (Corrected)
+          {
+            param = NewParam;
+            sol(3) = NewU;
+            sol(4) = NewV;
+          }
        }
        else if (recad2) {
          //sol sur 2
@@ -345,6 +385,17 @@ void Blend_Walking::InternalPerform(Blend_Function& Func,
          sol(2) = solrst2(4);
          sol(3) = p2d.X();
          sol(4) = p2d.Y();
+          gp_Pnt thePntOnRst = TheSurfaceTool::Value(surf2,sol(3),sol(4));
+          Standard_Real NewU, NewV, NewParam;
+          gp_Pnt NewPnt;
+          Standard_Boolean Corrected = CorrectExtremityOnOneRst(2, sol(1), sol(2), param, thePntOnRst,
+                                                                NewU, NewV, NewPnt, NewParam);
+          if (Corrected)
+          {
+            param = NewParam;
+            sol(1) = NewU;
+            sol(2) = NewV;
+          }
        }
        else {
          State = Blend_OK;
@@ -610,3 +661,146 @@ void Blend_Walking::InternalPerform(Blend_Function& Func,
   }
 
 }
+
+Standard_Boolean Blend_Walking::CorrectExtremityOnOneRst(const Standard_Integer IndexOfRst,
+                                                         const Standard_Real theU,
+                                                         const Standard_Real theV,
+                                                         const Standard_Real theParam,
+                                                         const gp_Pnt& thePntOnRst,
+                                                         Standard_Real& NewU,
+                                                         Standard_Real& NewV,
+                                                         gp_Pnt& NewPoint,
+                                                         Standard_Real& NewParam) const
+{
+  const Standard_Real TolAng = 0.001; //bug OCC25701
+  
+  ChFiDS_ElSpine& theElSpine = hguide->ChangeCurve();
+  if (theElSpine.NbVertices() == 0)
+    return Standard_False;
+  
+  Handle(TheTopolTool) DomainOfRst = (IndexOfRst == 1)? recdomain1 : recdomain2;
+  TheSurface SurfOfRst = (IndexOfRst == 1)? surf1 : surf2;
+  TheSurface AnotherSurf = (IndexOfRst == 1)? surf2 : surf1;
+  
+  //Correct point on surface 2
+  //First we find right <param>
+  Standard_Real Ends [2];
+  Ends[0] = TheArcTool::FirstParameter(DomainOfRst->Value());
+  Ends[1] = TheArcTool::LastParameter(DomainOfRst->Value());
+  Standard_Real GlobalMinSqDist = Precision::Infinite();
+  Standard_Real ParamOnGuide = 0;
+  gp_Pnt PointOnGuide;
+  for (Standard_Integer k = 0; k < 2; k++)
+  {
+    gp_Pnt2d P2dOnEnd = TheArcTool::Value(DomainOfRst->Value(), Ends[k]);
+    gp_Pnt PntOnEnd = TheSurfaceTool::Value(SurfOfRst, P2dOnEnd.X(), P2dOnEnd.Y());
+    Extrema_ExtPC projoncurv(PntOnEnd, theElSpine);
+    if (!projoncurv.IsDone())
+      continue;
+    Standard_Real MinSqDist = Precision::Infinite();
+    Standard_Integer imin = 0;
+    for (Standard_Integer ind = 1; ind <= projoncurv.NbExt(); ind++)
+    {
+      Standard_Real aSqDist = projoncurv.SquareDistance(ind);
+      if (aSqDist < MinSqDist)
+      {
+        MinSqDist = aSqDist;
+        imin = ind;
+      }
+    }
+    if (MinSqDist < GlobalMinSqDist)
+    {
+      GlobalMinSqDist = MinSqDist;
+      ParamOnGuide = projoncurv.Point(imin).Parameter();
+      PointOnGuide = projoncurv.Point(imin).Value();
+    }
+  }
+  NewParam = ParamOnGuide;
+  if (hguide->IsPeriodic())
+  {
+    Standard_Real Period = hguide->Period();
+    Standard_Real sign = (NewParam < theParam)? 1 : -1;
+    while (Abs(NewParam - theParam) > Period/2)
+      NewParam += sign *Period;
+  }
+
+  //Second we find right point and tangent on guide
+  GlobalMinSqDist = Precision::Infinite();
+  gp_Ax1 theAx1;
+  for (Standard_Integer ind = 1; ind <= theElSpine.NbVertices(); ind++)
+  {
+    const gp_Ax1& anAx1 = theElSpine.VertexWithTangent(ind);
+    gp_Pnt aPnt = anAx1.Location();
+    Standard_Real aSqDist = PointOnGuide.SquareDistance(aPnt);
+    if (aSqDist < GlobalMinSqDist)
+    {
+      GlobalMinSqDist = aSqDist;
+      theAx1 = anAx1;
+    }
+  }
+  const gp_Pnt& Pnt0 = theAx1.Location();
+  const gp_Dir& Dir0 = theAx1.Direction();
+  //Check new point: is it real solution?
+  gp_Pnt OldPonGuide = hguide->Value(theParam);
+  gp_Pnt PntOnSurf2 = TheSurfaceTool::Value(AnotherSurf,theU,theV); //old point
+  gce_MakePln PlaneBuilder(thePntOnRst, OldPonGuide, PntOnSurf2);
+  if (!PlaneBuilder.IsDone())
+    return Standard_False;
+  gp_Pln OldPlane = PlaneBuilder.Value();
+  gp_Dir OldDir = OldPlane.Axis().Direction();
+  Standard_Real Angle = OldDir.Angle(Dir0);
+  if (Angle > M_PI/2)
+    Angle = M_PI - Angle;
+  if (Angle > TolAng)
+    return Standard_False;
+  ///////////////////////////////////////
+  //Project the point(theU,theV) on the plane(Pnt0,Dir0)
+  gp_Vec aVec(Pnt0, PntOnSurf2);
+  gp_Vec aTranslation( (aVec.XYZ() * Dir0.XYZ()) * Dir0.XYZ() );
+  gp_Pnt PntOnPlane = PntOnSurf2.Translated(-aTranslation);
+
+  //Check new point again: does point on restriction belong to the plane?
+  PlaneBuilder = gce_MakePln(thePntOnRst, Pnt0, PntOnPlane);
+  if (!PlaneBuilder.IsDone())
+    return Standard_False;
+  gp_Pln NewPlane = PlaneBuilder.Value();
+  const gp_Dir& DirOfNewPlane = NewPlane.Axis().Direction();
+  Angle = Dir0.Angle(DirOfNewPlane);
+  if (Angle > M_PI/2)
+    Angle = M_PI - Angle;
+  if (Angle > TolAng)
+    return Standard_False;
+  ////////////////////////////////////////////////////////////////////////
+  
+  //Project the point <PntOnPlane> on the surface 2
+  Extrema_ExtPS projonsurf(PntOnPlane, AnotherSurf->Surface(),
+                           Precision::PConfusion(), Precision::PConfusion(),
+                           Extrema_ExtFlag_MIN);
+  if (projonsurf.IsDone())
+  {
+    Standard_Real MinSqDist = Precision::Infinite();
+    Standard_Integer imin = 0;
+    for (Standard_Integer ind = 1; ind <= projonsurf.NbExt(); ind++)
+    {
+      Standard_Real aSqDist = projonsurf.SquareDistance(ind);
+      if (aSqDist < MinSqDist)
+      {
+        MinSqDist = aSqDist;
+        imin = ind;
+      }
+    }
+    if (imin)
+    {
+      Extrema_POnSurf NewPOnSurf2 = projonsurf.Point(imin);
+      NewPoint = NewPOnSurf2.Value();
+      NewPOnSurf2.Parameter(NewU, NewV);
+      Standard_Real uperiod = (AnotherSurf->IsUPeriodic())? AnotherSurf->UPeriod() : 0.;
+      Standard_Real vperiod = (AnotherSurf->IsVPeriodic())? AnotherSurf->VPeriod() : 0.;
+      RecadreIfPeriodic(NewU, NewV, theU, theV,
+                        uperiod, vperiod);
+      return Standard_True;
+    }
+  }
+
+  return Standard_False;
+}
index a57c2e3..2ea8423 100644 (file)
@@ -3954,6 +3954,16 @@ Standard_EXPORT
   const BRepAdaptor_Curve& edc = Spine->CurrentElementarySpine(IF);
   tolpared = edc.Resolution(tol);
   Cv = BRep_Tool::Curve(E, First, Last);
+  //Add vertex with tangent
+  if (ES.IsPeriodic())
+  {
+    Standard_Real ParForElSpine = (E.Orientation() == TopAbs_FORWARD)? First : Last;
+    gp_Pnt PntForElSpine;
+    gp_Vec DirForElSpine;
+    Cv->D1(ParForElSpine, PntForElSpine, DirForElSpine);
+    ES.AddVertexWithTangent(gp_Ax1(PntForElSpine, DirForElSpine));
+  }
+  /////////////////////////
   urefdeb = Spine->FirstParameter(IF);
   checkdeb = (nwf > urefdeb);
   if(checkdeb) {
@@ -4080,6 +4090,13 @@ Standard_EXPORT
     }
     //
     Cv = BRep_Tool::Curve(E, First, Last);
+    //Add vertex with tangent
+    Standard_Real ParForElSpine = (E.Orientation() == TopAbs_FORWARD)? First : Last;
+    gp_Pnt PntForElSpine;
+    gp_Vec DirForElSpine;
+    Cv->D1(ParForElSpine, PntForElSpine, DirForElSpine);
+    ES.AddVertexWithTangent(gp_Ax1(PntForElSpine, DirForElSpine));
+    /////////////////////////
     if(IEdge == IL) {
       Standard_Real ureffin = Spine->LastParameter(iloc);
       Standard_Boolean checkfin = (nwl < ureffin);
index 78fc8c0..0135f06 100644 (file)
@@ -684,6 +684,24 @@ Standard_Boolean ChFi3d_Builder::StoreData(Handle(ChFiDS_SurfData)& Data,
   if (length2 >  Precision::Confusion())
     GeomLib::ExtendSurfByLength(Surf,length2,1,Standard_False,Standard_True);
 
+  //Correction of surface on extremities
+  if (length1 <= Precision::Confusion())
+  {
+    gp_Pnt P11, P21;
+    P11 = lin->StartPointOnFirst().Value();
+    P21 = lin->StartPointOnSecond().Value();
+    Surf->SetPole(1, 1, P11);
+    Surf->SetPole(Surf->NbUPoles(), 1, P21);
+  }
+  if (length2 <= Precision::Confusion())
+  {
+    gp_Pnt P12, P22;
+    P12 = lin->EndPointOnFirst().Value();
+    P22 = lin->EndPointOnSecond().Value();
+    Surf->SetPole(1, Surf->NbVPoles(), P12);
+    Surf->SetPole(Surf->NbUPoles(), Surf->NbVPoles(), P22);
+  }
+
   Data->ChangeSurf(DStr.AddSurface(TopOpeBRepDS_Surface(Surf,tolget3d)));
 
 #ifdef DRAW
@@ -1475,7 +1493,7 @@ Standard_Boolean ChFi3d_Builder::ComputeData
   Standard_Real TolGuide=tolguide, TolEsp = tolesp;
   Standard_Integer nbptmin = 4;
 
-  BRepBlend_Walking TheWalk(S1,S2,I1,I2);
+  BRepBlend_Walking TheWalk(S1,S2,I1,I2,HGuide);
 
   //Start of removal, 2D path controls 
   //that qui s'accomodent mal des surfaces a parametrages non homogenes
@@ -1573,7 +1591,7 @@ Standard_Boolean ChFi3d_Builder::ComputeData
       if (5*TolGuide > MS) TolGuide = MS/5;
       if (5*TolEsp > MS) TolEsp = MS/5;
     }
-    TheWalk.Perform(Func,FInv,HGuide,NewFirst,Target,MS,TolGuide,
+    TheWalk.Perform(Func,FInv,NewFirst,Target,MS,TolGuide,
                    ParSol,TolEsp,Fleche,Appro);
     if (!TheWalk.IsDone()) {
 #ifdef OCCT_DEBUG
@@ -2068,7 +2086,7 @@ Standard_Boolean ChFi3d_Builder::SimulData
  const Standard_Boolean RecOnS1,
  const Standard_Boolean RecOnS2)
 {
-  BRepBlend_Walking TheWalk(S1,S2,I1,I2);
+  BRepBlend_Walking TheWalk(S1,S2,I1,I2,HGuide);
   TheWalk.Check2d(Standard_False);
   
   Standard_Real MS = MaxStep;
@@ -2113,7 +2131,7 @@ Standard_Boolean ChFi3d_Builder::SimulData
       if (5*TolEsp > MS) TolEsp = MS/5;
     }
       
-    TheWalk.Perform(Func,FInv,HGuide,NewFirst,Target,MS,TolGuide,
+    TheWalk.Perform(Func,FInv,NewFirst,Target,MS,TolGuide,
                    ParSol,TolEsp,Fleche,Appro);
     
     if (!TheWalk.IsDone()) {
index 9acabb7..04ceed1 100644 (file)
@@ -1289,7 +1289,7 @@ Standard_Boolean ChFi3d_ChBuilder::PerformFirstSection
     
     BRepBlend_Chamfer Func(S1,S2,HGuide);
     Func.Set(dis,dis,Choix);
-    BRepBlend_Walking TheWalk(S1,S2,I1,I2);
+    BRepBlend_Walking TheWalk(S1,S2,I1,I2,HGuide);
     
     //calculate an approximate starting solution
     gp_Vec TgF, TgL, tmp1, tmp2, d1gui;
@@ -1346,7 +1346,7 @@ Standard_Boolean ChFi3d_ChBuilder::PerformFirstSection
     
     BRepBlend_Chamfer Func(S1,S2,HGuide);
     Func.Set(dis1,dis2,Choix);
-    BRepBlend_Walking TheWalk(S1,S2,I1,I2);
+    BRepBlend_Walking TheWalk(S1,S2,I1,I2,HGuide);
     
     //calculate an approximate starting solution
     gp_Vec TgF, TgL, tmp1, tmp2, d1gui;
@@ -1407,7 +1407,7 @@ Standard_Boolean ChFi3d_ChBuilder::PerformFirstSection
     if (disonF1)  {
       BRepBlend_ChAsym Func(S1,S2,HGuide);
       Func.Set(dis1, angle, Ch);
-      BRepBlend_Walking TheWalk(S1,S2,I1,I2);
+      BRepBlend_Walking TheWalk(S1,S2,I1,I2,HGuide);
     
     //calculate an approximate starting solution
       gp_Vec TgF, TgL, tmp1, tmp2, d1gui;
@@ -1469,7 +1469,7 @@ Standard_Boolean ChFi3d_ChBuilder::PerformFirstSection
       Standard_Real Rtemp;
       BRepBlend_ChAsym Func(S2,S1,HGuide);
       Func.Set(dis1, angle, Ch);
-      BRepBlend_Walking TheWalk(S2,S1,I2,I1);
+      BRepBlend_Walking TheWalk(S2,S1,I2,I1,HGuide);
     
     //calculate an approximate starting solution
       gp_Vec TgF, TgL, tmp1, tmp2, d1gui;
index b0a1ddc..98aaf95 100644 (file)
@@ -1198,7 +1198,7 @@ Standard_Boolean ChFi3d_FilBuilder::PerformFirstSection
     BRepBlend_ConstRad Func(S1,S2,HGuide);
     Func.Set(fsp->Radius(),Choix);
     Func.Set(myShape);
-    BRepBlend_Walking TheWalk(S1,S2,I1,I2);
+    BRepBlend_Walking TheWalk(S1,S2,I1,I2,HGuide);
     return TheWalk.PerformFirstSection(Func,Par,SolDep,
                                       tolesp,TolGuide,Pos1,Pos2);
   }
@@ -1206,7 +1206,7 @@ Standard_Boolean ChFi3d_FilBuilder::PerformFirstSection
     BRepBlend_EvolRad Func(S1,S2,HGuide,fsp->Law(HGuide));
     Func.Set(Choix);
     Func.Set(myShape);
-    BRepBlend_Walking TheWalk(S1,S2,I1,I2);
+    BRepBlend_Walking TheWalk(S1,S2,I1,I2,HGuide);
     return TheWalk.PerformFirstSection(Func,Par,SolDep,
                                       tolesp,TolGuide,Pos1,Pos2);
   }
index 6b5483e..4253ff1 100644 (file)
@@ -26,9 +26,11 @@ uses
     Elips        from gp,  
     Hypr         from gp,  
     Parab        from gp,   
+    Ax1          from gp,
     BezierCurve  from Geom,  
     BSplineCurve from Geom, 
     Array1OfReal from TColStd,
+    SequenceOfAx1 from TColgp,
     SurfData     from ChFiDS,
     Shape        from GeomAbs,
     CurveType    from GeomAbs,
@@ -116,9 +118,17 @@ is
 
     LastPointAndTgt(me; P : out Pnt from gp; T : out Vec from gp);
 
+    NbVertices(me) returns Integer from Standard;
+
+    VertexWithTangent(me; Index : Integer from Standard)
+    returns Ax1 from gp;
+    ---C++: return const &
+
     SetFirstPointAndTgt(me : in out; P : Pnt from gp; T : Vec from gp);
 
     SetLastPointAndTgt(me : in out; P : Pnt from gp; T : Vec from gp);
+    
+    AddVertexWithTangent(me : in out; anAx1 : Ax1 from gp);
 
     SetCurve(me : in out; C : Curve from Geom);
 
@@ -187,6 +197,7 @@ ptfirst   : Pnt      from gp;
 ptlast    : Pnt      from gp;
 tgfirst   : Vec      from gp;
 tglast    : Vec      from gp;
+VerticesWithTangents : SequenceOfAx1 from TColgp;
 
 previous  : SurfData from ChFiDS;
 next      : SurfData from ChFiDS; 
index a7d47fa..d404427 100644 (file)
@@ -312,6 +312,16 @@ void ChFiDS_ElSpine::SetLastPointAndTgt(const gp_Pnt& P,
 }
 
 //=======================================================================
+//function : AddVertexWithTangent
+//purpose  : 
+//=======================================================================
+
+void ChFiDS_ElSpine::AddVertexWithTangent(const gp_Ax1& anAx1)
+{
+  VerticesWithTangents.Append(anAx1);
+}
+
+//=======================================================================
 //function : FirstPointAndTgt
 //purpose  : 
 //=======================================================================
@@ -336,6 +346,26 @@ void ChFiDS_ElSpine::LastPointAndTgt(gp_Pnt& P,
 }
 
 //=======================================================================
+//function : NbVertices
+//purpose  : 
+//=======================================================================
+
+Standard_Integer ChFiDS_ElSpine::NbVertices() const
+{
+  return VerticesWithTangents.Length();
+}
+
+//=======================================================================
+//function : VertexWithTangent
+//purpose  : 
+//=======================================================================
+
+const gp_Ax1& ChFiDS_ElSpine::VertexWithTangent(const Standard_Integer Index) const
+{
+  return VerticesWithTangents(Index);
+}
+
+//=======================================================================
 //function : SetCurve
 //purpose  : 
 //=======================================================================
index 1dbef3c..f7ecfcb 100644 (file)
@@ -169,6 +169,8 @@ is
        instantiates Sequence  from TCollection (Vec from gp);
   class SequenceOfXYZ
        instantiates Sequence  from TCollection (XYZ from gp);
+  class SequenceOfAx1
+       instantiates Sequence  from TCollection (Ax1 from gp);
 
 
     -- HSequences of 3D objects.
diff --git a/tests/bugs/modalg_5/bug25701 b/tests/bugs/modalg_5/bug25701
new file mode 100644 (file)
index 0000000..c24eb00
--- /dev/null
@@ -0,0 +1,42 @@
+puts "==========="
+puts "OCC25701"
+puts "==========="
+puts ""
+######################################################
+# Problem with the symmetry of fillet on two perpendicular cylinders
+######################################################
+
+restore [locate_data_file bug25701_rx.brep] rx
+
+explode rx e
+smallview
+donly rx rx_2 rx_5
+compound rx_2 rx_5 q
+
+fillet x rx 2.5 q
+explode x e
+donly x x_9
+fit
+
+mkcurve cx_9 x_9
+
+set log [dump cx_9]
+
+regexp {Degree +([-0-9.+eE]+), +([-0-9.+eE]+) Poles, +([-0-9.+eE]+)} ${log} full Degree Poles KnotsPoles
+puts "Degree=${Degree}"
+puts "Poles=${Poles}"
+puts "KnotsPoles=${KnotsPoles}"
+puts ""
+
+set tol_abs 1.e-11
+set tol_rel 0.01
+set expected_V 0.
+
+for {set i 1} {${i} <= ${Poles}} {incr i} {
+   set exp_string " +${i} : +(\[-0-9.+eE\]+), +(\[-0-9.+eE\]+)"
+   regexp ${exp_string} ${log} full U_i V_i
+   puts "i=${i} U_i=${U_i} V_i=${V_i}"
+   checkreal "V_$i" ${V_i} ${expected_V} ${tol_abs} ${tol_rel}
+}
+
+set only_screen_axo 1