]> OCCT Git - occt.git/commitdiff
0029745: Modeling Data - GeomAdaptor_Surface::VIntervals fails on periodic surfaces
authorabulyche <abulyche@opencascade.com>
Tue, 14 Dec 2021 22:58:57 +0000 (01:58 +0300)
committersmoskvin <smoskvin@opencascade.com>
Thu, 31 Mar 2022 18:47:58 +0000 (21:47 +0300)
Fixed GeomAdaptor_Curve::LocalContinuity() for periodic curves.
Fixed GeomAdaptor_Curve::NbIntervals() for periodic curves.
Fixed GeomAdaptor_Curve::Intervals() for periodic curves.
Improved definition of length in tests.
Update Geom2dAdaptor_Curve to the same behavior.

src/Geom2dAdaptor/Geom2dAdaptor_Curve.cxx
src/GeomAdaptor/GeomAdaptor_Curve.cxx
src/QABugs/QABugs_20.cxx
tests/bugs/modalg_6/bug25908
tests/bugs/modalg_6/bug27884
tests/bugs/moddata_3/bug29745 [new file with mode: 0644]
tests/hlr/exact_hlr/A1
tests/hlr/exact_hlr/C20
tests/hlr/exact_hlr/D4
tests/hlr/exact_hlr/D5

index 80d97ed1fbc75f2be953332c2ff88a40ed32ad97..f6727ca8e70222a849d27dc4374d0c31488ca01b 100644 (file)
@@ -58,6 +58,65 @@ static const Standard_Real PosTol = Precision::PConfusion() / 2;
 
 IMPLEMENT_STANDARD_RTTIEXT(Geom2dAdaptor_Curve, Adaptor2d_Curve2d)
 
+static void DefinFPeriod(const Standard_Real theLower,
+  const Standard_Real theUpper,
+  const Standard_Real theEps,
+  const Standard_Real thePeriod,
+  Standard_Real &theCurFirst,
+  Standard_Integer &theFPer);
+
+static void DefinLPeriod(const Standard_Real theLower,
+  const Standard_Real theUpper,
+  const Standard_Real theEps,
+  const Standard_Real thePeriod,
+  Standard_Real &theCurLast,
+  Standard_Integer &theLPer);
+
+static Standard_Integer LocalNbIntervals(const TColStd_Array1OfReal& theTK,
+  const TColStd_Array1OfInteger& theTM,
+  const TColStd_Array1OfInteger& theInter,
+  const Standard_Integer theCurDegree,
+  const Standard_Integer theNb,
+  const Standard_Integer theNbInt,
+  const Standard_Real theFirst,
+  const Standard_Real theLast,
+  const Standard_Real theEps,
+  const Standard_Boolean thePeriodicCur,
+  Standard_Integer theNbIntervals,
+  Standard_Real theLower = 0,
+  Standard_Real thePeriod = 0,
+  Standard_Integer theIndex1 = 0,
+  Standard_Integer theIndex2 = 0);
+
+static void WriteIntervals(const TColStd_Array1OfReal &theTK,
+  const TColStd_Array1OfInteger &theInter,
+  const Standard_Integer theNbInt,
+  const Standard_Integer theIndex1,
+  const Standard_Integer theIndex2,
+  const Standard_Real theCurPeriod,
+  const Standard_Boolean theFlagForFirst,
+  TColStd_Array1OfReal &theT,
+  TColStd_Array1OfInteger &theFinalIntervals,
+  Standard_Integer &theNbIntervals,
+  Standard_Integer &theCurInt);
+
+static void SpreadInt(const TColStd_Array1OfReal &theTK,
+  const TColStd_Array1OfInteger &theTM,
+  const TColStd_Array1OfInteger &theInter,
+  const Standard_Integer theCurDegree,
+  const Standard_Integer theNb,
+  const Standard_Integer theFPer,
+  const Standard_Integer theLPer,
+  const Standard_Integer theNbInt,
+  const Standard_Real theLower,
+  const Standard_Real theFirst,
+  const Standard_Real theLast,
+  const Standard_Real thePeriod,
+  const Standard_Real theLastParam,
+  const Standard_Real theEps,
+  TColStd_Array1OfReal &theT,
+  Standard_Integer &theNbIntervals);
+
 //=======================================================================
 //function : ShallowCopy
 //purpose  : 
@@ -115,7 +174,7 @@ GeomAbs_Shape Geom2dAdaptor_Curve::LocalContinuity(const Standard_Real U1,
        if ( myBSplineCurve->IsPeriodic() && Index1 == Nb )
         Index1 = 1;
 
-       if ( Index2 - Index1 <= 0) {
+       if ((Index2 - Index1 <= 0) && (!myBSplineCurve->IsPeriodic())) {
         MultMax = 100;  // CN entre 2 Noeuds consecutifs
        }
        else {
@@ -295,6 +354,158 @@ GeomAbs_Shape Geom2dAdaptor_Curve::Continuity() const
   }
 }
 
+//=======================================================================
+//function : DefinFPeriod
+//purpose  :
+//=======================================================================
+
+void DefinFPeriod(const Standard_Real theLower,
+  const Standard_Real theUpper,
+  const Standard_Real theEps,
+  const Standard_Real thePeriod,
+  Standard_Real &theCurFirst,
+  Standard_Integer &theFPer)
+{
+  if (theCurFirst >= theLower)
+  {
+    while (theCurFirst >= theUpper)
+    {
+      theCurFirst = theCurFirst - thePeriod;
+      theFPer++;
+    }
+    if (Abs(theUpper - theCurFirst) <= theEps)
+    {
+      theFPer++;
+      theCurFirst = theLower;
+    }
+  }
+  else
+  {
+    while (theCurFirst < theLower)
+    {
+      theCurFirst = theCurFirst + thePeriod;
+      if (Abs(theLower - theCurFirst) > theEps)
+      {
+        theFPer--;
+      }
+    }
+
+    if (Abs(theUpper - theCurFirst) <= theEps)
+    {
+      theCurFirst = theLower;
+    }
+  }
+}
+
+//=======================================================================
+//function : DefinLPeriod
+//purpose  :
+//=======================================================================
+
+void DefinLPeriod(const Standard_Real theLower,
+  const Standard_Real theUpper,
+  const Standard_Real theEps,
+  const Standard_Real thePeriod,
+  Standard_Real &theCurLast,
+  Standard_Integer &theLPer)
+{
+  if (theCurLast >= theLower)
+  {
+    if ((theCurLast >= theUpper) && (Abs(theCurLast - theUpper) <= theEps))
+    {
+      theCurLast = theUpper;
+    }
+    else
+    {
+      while (theCurLast >= theUpper)
+      {
+        theCurLast = theCurLast - thePeriod;
+        theLPer++;
+      }
+      if (Abs(theUpper - theCurLast) <= theEps)
+      {
+        theCurLast = theLower;
+      }
+    }
+  }
+  else
+  {
+    while (theCurLast < theLower)
+    {
+      theCurLast = theCurLast + thePeriod;
+      if (Abs(theLower - theCurLast) > theEps)
+      {
+        theLPer--;
+      }
+    }
+    if (Abs(theUpper - theCurLast) <= theEps)
+    {
+      theCurLast = theLower;
+    }
+  }
+}
+
+//=======================================================================
+//function : LocalNbIntervals
+//purpose  :
+//=======================================================================
+
+Standard_Integer LocalNbIntervals(const TColStd_Array1OfReal& theTK,
+  const TColStd_Array1OfInteger& theTM,
+  const TColStd_Array1OfInteger& theInter,
+  const Standard_Integer theCurDegree,
+  const Standard_Integer theNb,
+  const Standard_Integer theNbInt,
+  const Standard_Real theFirst,
+  const Standard_Real theLast,
+  const Standard_Real theEps,
+  const Standard_Boolean thePeriodicCur,
+  Standard_Integer theNbIntervals,
+  Standard_Real theLower,
+  Standard_Real thePeriod,
+  Standard_Integer theIndex1,
+  Standard_Integer theIndex2)
+{
+  Standard_Real aNewFirst = theFirst;
+  Standard_Real aNewLast = theLast;
+  if (theIndex1 == 0)
+  {
+    BSplCLib::LocateParameter(theCurDegree, theTK, theTM, theFirst,
+      thePeriodicCur, 1, theNb, theIndex1, aNewFirst);
+  }
+  if (theIndex2 == 0)
+  {
+    BSplCLib::LocateParameter(theCurDegree, theTK, theTM, theLast,
+      thePeriodicCur, 1, theNb, theIndex2, aNewLast);
+  }
+  // Protection against theFirst = UFirst - eps, which located as ULast - eps
+  if (thePeriodicCur && ((aNewLast - aNewFirst) < Precision::PConfusion()))
+  {
+    if (Abs(aNewLast - theLower) < Precision::PConfusion())
+    {
+      aNewLast += thePeriod;
+    }
+    else
+    {
+      aNewFirst -= thePeriod;
+    }
+  }
+
+  if (Abs(aNewFirst - theTK(theIndex1 + 1)) < theEps)
+  {
+    theIndex1++;
+  }
+  if ((aNewLast - theTK(theIndex2)) > theEps)
+  {
+    theIndex2++;
+  }
+  for (Standard_Integer i = 1; i <= theNbInt; i++)
+  {
+    if (theInter(i) > theIndex1 && theInter(i) < theIndex2) theNbIntervals++;
+  }
+  return theNbIntervals;
+}
+
 //=======================================================================
 //function : NbIntervals
 //purpose  : 
@@ -306,77 +517,179 @@ Standard_Integer Geom2dAdaptor_Curve::NbIntervals(const GeomAbs_Shape S) const
   Standard_Integer NbSplit;
   if (myTypeCurve == GeomAbs_BSplineCurve) {
     Standard_Integer FirstIndex = myBSplineCurve->FirstUKnotIndex();
-    Standard_Integer LastIndex  = myBSplineCurve->LastUKnotIndex();
-    TColStd_Array1OfInteger Inter (1, LastIndex-FirstIndex+1);
-    if ( S > Continuity()) {
+    Standard_Integer LastIndex = myBSplineCurve->LastUKnotIndex();
+    TColStd_Array1OfInteger Inter(1, LastIndex - FirstIndex + 1);
+    Standard_Boolean aContPer = (S >= Continuity()) && myBSplineCurve->IsPeriodic();
+    Standard_Boolean aContNotPer = (S > Continuity()) && !myBSplineCurve->IsPeriodic();
+    if (aContPer || aContNotPer) {
       Standard_Integer Cont;
-      switch ( S) {
+      switch (S) {
       case GeomAbs_G1:
       case GeomAbs_G2:
-       throw Standard_DomainError("Geom2dAdaptor_Curve::NbIntervals");
-       break;
+        throw Standard_DomainError("Geom2dAdaptor_Curve::NbIntervals");
+        break;
       case GeomAbs_C0:
-       myNbIntervals = 1;
-       break;
+        myNbIntervals = 1;
+        break;
       case GeomAbs_C1:
       case GeomAbs_C2:
-      case GeomAbs_C3: 
-      case GeomAbs_CN: 
-       {
-         if      ( S == GeomAbs_C1) Cont = 1;
-         else if ( S == GeomAbs_C2) Cont = 2;
-         else if ( S == GeomAbs_C3) Cont = 3;
-         else                       Cont = myBSplineCurve->Degree();
-          Standard_Integer Degree = myBSplineCurve->Degree();
-          Standard_Integer NbKnots = myBSplineCurve->NbKnots();
-          TColStd_Array1OfInteger Mults (1, NbKnots);
-          myBSplineCurve->Multiplicities (Mults);
-          NbSplit = 1;
-          Standard_Integer Index   = FirstIndex;
-          Inter (NbSplit) = Index;
+      case GeomAbs_C3:
+      case GeomAbs_CN:
+      {
+        if (S == GeomAbs_C1) Cont = 1;
+        else if (S == GeomAbs_C2) Cont = 2;
+        else if (S == GeomAbs_C3) Cont = 3;
+        else                       Cont = myBSplineCurve->Degree();
+        Standard_Integer Degree = myBSplineCurve->Degree();
+        Standard_Integer NbKnots = myBSplineCurve->NbKnots();
+        TColStd_Array1OfInteger Mults(1, NbKnots);
+        myBSplineCurve->Multiplicities(Mults);
+        NbSplit = 1;
+        Standard_Integer Index = FirstIndex;
+        Inter(NbSplit) = Index;
+        Index++;
+        NbSplit++;
+        while (Index < LastIndex)
+        {
+          if (Degree - Mults(Index) < Cont)
+          {
+            Inter(NbSplit) = Index;
+            NbSplit++;
+          }
           Index++;
-          NbSplit++;
-          while (Index < LastIndex) 
+        }
+        Inter(NbSplit) = Index;
+
+        Standard_Integer NbInt = NbSplit - 1;
+
+        Standard_Integer Nb = myBSplineCurve->NbKnots();
+        TColStd_Array1OfReal    TK(1, Nb);
+        TColStd_Array1OfInteger TM(1, Nb);
+        myBSplineCurve->Knots(TK);
+        myBSplineCurve->Multiplicities(TM);
+        Standard_Real Eps = Min(Resolution(Precision::Confusion()),
+          Precision::PConfusion());
+
+        myNbIntervals = 1;
+
+        if (!myBSplineCurve->IsPeriodic())
+        {
+          myNbIntervals = LocalNbIntervals(TK, TM, Inter, Degree, Nb, NbInt,
+            myFirst, myLast, Eps, Standard_False, myNbIntervals);
+        }
+        else
+        {
+          Standard_Real aCurFirst = myFirst;
+          Standard_Real aCurLast = myLast;
+
+          Standard_Real aLower = myBSplineCurve->FirstParameter();
+          Standard_Real anUpper = myBSplineCurve->LastParameter();
+
+          if ((Abs(aCurFirst - aLower) < Eps) && (aCurFirst < aLower))
+          {
+            aCurFirst = aLower;
+          }
+          if ((Abs(aCurLast - anUpper) < Eps) && (aCurLast < anUpper))
+          {
+            aCurLast = anUpper;
+          }
+
+          Standard_Real aPeriod = myBSplineCurve->Period();
+          Standard_Integer aLPer = 1; Standard_Integer aFPer = 1;
+          
+          if ((Abs(aLower - myFirst) < Eps) && (aCurFirst < aLower))
+          {
+            aCurFirst = aLower;
+          }
+          else
+          {
+            DefinFPeriod(aLower, anUpper,
+              Eps, aPeriod, aCurFirst, aFPer);
+          }
+          DefinLPeriod(aLower, anUpper,
+            Eps, aPeriod, aCurLast, aLPer);
+
+          if ((Abs(aLower - myFirst) < Eps) && (Abs(anUpper - myLast) < Eps))
+          {
+            myNbIntervals = NbInt;
+          }
+          else
+          {
+            Standard_Integer aSumPer = Abs(aLPer - aFPer);
+            
+            Standard_Real aFirst = 0;
+            if (aLower < 0 && anUpper == 0)
+            {
+              if (Abs(aCurLast) < Eps)
+              {
+                aCurLast = 0;
+              }
+              aFirst = aLower;
+            }
+
+            if (aSumPer <= 1)
+            {
+              if ((Abs(myFirst - TK(Nb) - aPeriod * (aFPer - 1)) <= Eps) && (myLast < (TK(Nb) + aPeriod * (aLPer - 1))))
+              {
+                myNbIntervals = LocalNbIntervals(TK, TM, Inter, Degree, Nb, NbInt,
+                  myFirst, myLast, Eps, Standard_True, myNbIntervals, aLower, aPeriod);
+                return myNbIntervals;
+              }
+              if ((Abs(myFirst - aLower) < Eps) && (Abs(myLast - anUpper) < Eps))
+              {
+                myNbIntervals = LocalNbIntervals(TK, TM, Inter, Degree, Nb, NbInt,
+                  myFirst, myLast, Eps, Standard_True, myNbIntervals, aLower, aPeriod);
+                return myNbIntervals;
+              }
+            }
+
+            if (aSumPer != 0)
             {
-             if (Degree - Mults (Index) < Cont) 
-               {
-                 Inter (NbSplit) = Index;
-                 NbSplit++;
-               }
-             Index++;
-           }
-          Inter (NbSplit) = Index;
-
-          Standard_Integer NbInt = NbSplit-1;
-         
-         Standard_Integer Nb = myBSplineCurve->NbKnots();
-         Standard_Integer Index1 = 0;
-         Standard_Integer Index2 = 0;
-         Standard_Real newFirst, newLast;
-         TColStd_Array1OfReal    TK(1,Nb);
-         TColStd_Array1OfInteger TM(1,Nb);
-         myBSplineCurve->Knots(TK);
-         myBSplineCurve->Multiplicities(TM);
-         BSplCLib::LocateParameter(myBSplineCurve->Degree(),TK,TM,myFirst,
-                                   myBSplineCurve->IsPeriodic(),
-                                   1,Nb,Index1,newFirst);
-         BSplCLib::LocateParameter(myBSplineCurve->Degree(),TK,TM,myLast,
-                                   myBSplineCurve->IsPeriodic(),
-                                   1,Nb,Index2,newLast);
-
-         // On decale eventuellement les indices  
-         // On utilise une "petite" tolerance, la resolution ne doit 
-          // servir que pour les tres longue courbes....(PRO9248)
-          Standard_Real Eps = Min(Resolution(Precision::Confusion()),
-                                 Precision::PConfusion()); 
-         if ( Abs(newFirst-TK(Index1+1))< Eps) Index1++;
-         if ( newLast-TK(Index2)> Eps) Index2++;
-         
-         myNbIntervals = 1;
-         for ( Standard_Integer i=1; i<=NbInt; i++)
-           if (Inter(i)>Index1 && Inter(i)<Index2) myNbIntervals++;
+              Standard_Integer aFInt = 0;
+              Standard_Integer aLInt = 0;
+              Standard_Integer aPInt = NbInt;
+
+              if ((aCurFirst != aPeriod) || ((aCurFirst != anUpper) && (Abs(myFirst) < Eps)))
+              {
+              aFInt = 1;
+              }
+              if ((aCurLast != 0) && (aCurLast != anUpper))
+              {
+                aLInt = 1;
+              }
+
+              aFInt = LocalNbIntervals(TK, TM, Inter, Degree, Nb, NbInt,
+                aCurFirst, anUpper, Eps, Standard_True, aFInt, aLower, aPeriod);
+
+              if (aCurLast == anUpper)
+              {
+                aLInt = NbInt;
+              }
+              else
+              {
+                if (Abs(aCurLast - aFirst) > Eps)
+                {
+                  aLInt = LocalNbIntervals(TK, TM, Inter, Degree, Nb, NbInt,
+                    aFirst, aCurLast, Eps, Standard_True, aLInt, aLower, aPeriod, 1);
+                }
+                else
+                {
+                  aLInt = LocalNbIntervals(TK, TM, Inter, Degree, Nb, NbInt,
+                    aFirst, aCurLast, Eps, Standard_True, aLInt, aLower, aPeriod);
+                }
+              }
+
+              myNbIntervals = aFInt + aLInt + aPInt * (aSumPer - 1);
+            }
+            else
+            {
+              myNbIntervals = LocalNbIntervals(TK, TM, Inter, Degree, Nb, NbInt,
+                aCurFirst, aCurLast, Eps, Standard_True, myNbIntervals, aLower, aPeriod);
+            }
+          }
         }
-       break;
+      }
+      break;
       }
     }
   }
@@ -399,6 +712,204 @@ Standard_Integer Geom2dAdaptor_Curve::NbIntervals(const GeomAbs_Shape S) const
   return myNbIntervals;
 }
 
+//=======================================================================
+//function : WriteIntervals
+//purpose  :
+//=======================================================================
+
+void WriteIntervals(const TColStd_Array1OfReal &theTK,
+  const TColStd_Array1OfInteger &theInter,
+  const Standard_Integer theNbInt,
+  const Standard_Integer theIndex1,
+  const Standard_Integer theIndex2,
+  const Standard_Real theCurPeriod,
+  const Standard_Boolean theFlagForFirst,
+  TColStd_Array1OfReal &theT,
+  TColStd_Array1OfInteger &theFinalIntervals,
+  Standard_Integer &theNbIntervals,
+  Standard_Integer &theCurInt)
+{
+  if (theFlagForFirst)
+  {
+    for (Standard_Integer anId = 1; anId <= theNbInt; anId++)
+    {
+      if (theInter(anId) > theIndex1 && theInter(anId) <= theIndex2)
+      {
+        theNbIntervals++;
+        theFinalIntervals(theNbIntervals) = theInter(anId);
+      }
+    }
+  }
+  else
+  {
+    for (Standard_Integer anId = 1; anId <= theNbInt; anId++)
+    {
+      if (theInter(anId) > theIndex1 && theInter(anId) < theIndex2)
+      {
+        theNbIntervals++;
+        theFinalIntervals(theNbIntervals) = theInter(anId);
+      }
+    }
+  }
+
+  theFinalIntervals(theNbIntervals + 1) = theIndex2;
+
+  for (Standard_Integer anId = theCurInt; anId <= theNbIntervals + 1; anId++)
+  {
+    theT(anId) = theTK(theFinalIntervals(anId)) + theCurPeriod;
+    theCurInt++;
+  }
+}
+
+//=======================================================================
+//function : SpreadInt
+//purpose  :
+//=======================================================================
+void SpreadInt(const TColStd_Array1OfReal &theTK,
+  const TColStd_Array1OfInteger &theTM,
+  const TColStd_Array1OfInteger &theInter,
+  const Standard_Integer theCurDegree,
+  const Standard_Integer theNb,
+  const Standard_Integer theFPer,
+  const Standard_Integer theLPer,
+  const Standard_Integer theNbInt,
+  const Standard_Real theLower,
+  const Standard_Real theFirst,
+  const Standard_Real theLast,
+  const Standard_Real thePeriod,
+  const Standard_Real theLastParam,
+  const Standard_Real theEps,
+  TColStd_Array1OfReal &theT,
+  Standard_Integer &theNbIntervals)
+{
+  Standard_Integer anIndex1 = 0;
+  Standard_Integer anIndex2 = 0;
+  Standard_Real aNewFirst, aNewLast;
+  Standard_Integer anUpper;
+  BSplCLib::LocateParameter(theCurDegree, theTK, theTM, theFirst,
+    Standard_True, 1, theNb, anIndex1, aNewFirst);
+  BSplCLib::LocateParameter(theCurDegree, theTK, theTM, theLastParam,
+    Standard_True, 1, theNb, anIndex2, aNewLast);
+
+  if (Abs(aNewFirst - theTK(anIndex1 + 1)) < theEps)
+  {
+    anIndex1++;
+  }
+  if ((aNewLast - theTK(anIndex2)) > theEps)
+  {
+    anIndex2++;
+  }
+  theNbIntervals = 1;
+
+  if (anIndex1 == theNb)
+  {
+    anIndex1 = 1;
+  }
+  
+  // Count the max number of boundaries of intervals
+  if (Abs(theLPer - theFPer) > 1)
+  {
+    anUpper = theNb - anIndex1 + anIndex2 + (theLPer - theFPer - 1) * theNb + 1;
+  }
+  else
+  {
+    anUpper = theNb - anIndex1 + anIndex2 + 1;
+  }
+
+  if (theLPer == theFPer)
+  {
+    anUpper = theInter.Upper();
+  }
+  TColStd_Array1OfInteger aFinalIntervals(1, anUpper);
+  aFinalIntervals(1) = anIndex1;
+
+  // If first and last are in the same period
+  if ((Abs(theLPer - theFPer) == 0))
+  {
+    Standard_Integer aCurInt = 1;
+    Standard_Real aCurPeriod = theFPer * thePeriod;
+
+    if (theFirst == aNewFirst && theLast == aNewLast)
+    {
+      aCurPeriod = 0;
+    }
+    WriteIntervals(theTK, theInter, theNbInt, anIndex1,
+      anIndex2, aCurPeriod, Standard_False, theT, aFinalIntervals, theNbIntervals, aCurInt);
+    return;
+  }
+
+  // If the first and the last are in neighboring periods
+  if (Abs(theLPer - theFPer) == 1)
+  {
+    Standard_Integer aCurInt = 1;
+
+    if (Abs(theLastParam - theLower) < theEps)
+    {
+      WriteIntervals(theTK, theInter, theNbInt, anIndex1,
+        theNb, theFPer * thePeriod, Standard_True, theT, aFinalIntervals, theNbIntervals, aCurInt);
+      return;
+    }
+    else
+    {
+      // For period with first
+      WriteIntervals(theTK, theInter, theNbInt, anIndex1,
+        theNb, theFPer * thePeriod, Standard_True, theT, aFinalIntervals, theNbIntervals, aCurInt);
+      // For period with last
+      theNbIntervals++;
+      WriteIntervals(theTK, theInter, theNbInt, 1,
+        anIndex2, theLPer * thePeriod, Standard_False, theT, aFinalIntervals, theNbIntervals, aCurInt);
+      return;
+    }
+  }
+  // If the first and the last are far apart
+  if (Abs(theLPer - theFPer) > 1)
+  {
+    Standard_Integer aCurInt = 1;
+    if (Abs(theLastParam - theLower) < theEps)
+    {
+      WriteIntervals(theTK, theInter, theNbInt, anIndex1,
+        theNb, theFPer * thePeriod, Standard_True, theT, aFinalIntervals, theNbIntervals, aCurInt);
+
+      Standard_Integer aNbPer = Abs(theLPer - theFPer);
+      Standard_Integer aCurPer = theFPer + 1;
+
+      while (aNbPer > 1)
+      {
+        theNbIntervals++;
+        WriteIntervals(theTK, theInter, theNbInt, 1,
+          theNb, aCurPer * thePeriod, Standard_True, theT, aFinalIntervals, theNbIntervals, aCurInt);
+
+        aNbPer--;
+        aCurPer++;
+      }
+      return;
+    }
+    else
+    {
+      // For period with first
+      WriteIntervals(theTK, theInter, theNbInt, anIndex1,
+        theNb, theFPer * thePeriod, Standard_True, theT, aFinalIntervals, theNbIntervals, aCurInt);
+
+      Standard_Integer aNbPer = Abs(theLPer - theFPer);
+      Standard_Integer aCurPer = theFPer + 1;
+      while (aNbPer > 1)
+      {
+        theNbIntervals++;
+        WriteIntervals(theTK, theInter, theNbInt, 1,
+          theNb, aCurPer * thePeriod, Standard_True, theT, aFinalIntervals, theNbIntervals, aCurInt);
+
+        aNbPer--;
+        aCurPer++;
+      }
+      // For period with last
+      theNbIntervals++;
+      WriteIntervals(theTK, theInter, theNbInt, 1,
+        anIndex2, theLPer * thePeriod, Standard_False, theT, aFinalIntervals, theNbIntervals, aCurInt);
+      return;
+    }
+  }
+}
+
 //=======================================================================
 //function : Intervals
 //purpose  : 
@@ -413,7 +924,9 @@ void Geom2dAdaptor_Curve::Intervals(TColStd_Array1OfReal& T,
     Standard_Integer FirstIndex = myBSplineCurve->FirstUKnotIndex();
     Standard_Integer LastIndex  = myBSplineCurve->LastUKnotIndex();
     TColStd_Array1OfInteger Inter (1, LastIndex-FirstIndex+1);
-    if ( S > Continuity()) {
+    Standard_Boolean aContPer = (S >= Continuity()) && myBSplineCurve->IsPeriodic();
+    Standard_Boolean aContNotPer = (S > Continuity()) && !myBSplineCurve->IsPeriodic();
+    if (aContPer || aContNotPer) {
       Standard_Integer Cont;
       switch ( S) {
       case GeomAbs_G1:
@@ -427,72 +940,127 @@ void Geom2dAdaptor_Curve::Intervals(TColStd_Array1OfReal& T,
       case GeomAbs_C2:
       case GeomAbs_C3: 
       case GeomAbs_CN: 
-       {
-         if      ( S == GeomAbs_C1) Cont = 1;
-         else if ( S == GeomAbs_C2) Cont = 2;
-         else if ( S == GeomAbs_C3) Cont = 3;
-         else                       Cont = myBSplineCurve->Degree();
-          Standard_Integer Degree = myBSplineCurve->Degree();
-          Standard_Integer NbKnots = myBSplineCurve->NbKnots();
-          TColStd_Array1OfInteger Mults (1, NbKnots);
-          myBSplineCurve->Multiplicities (Mults);
-          NbSplit = 1;
-          Standard_Integer Index   = FirstIndex;
-          Inter (NbSplit) = Index;
+      {
+        if (S == GeomAbs_C1) Cont = 1;
+        else if (S == GeomAbs_C2) Cont = 2;
+        else if (S == GeomAbs_C3) Cont = 3;
+        else                       Cont = myBSplineCurve->Degree();
+        Standard_Integer Degree = myBSplineCurve->Degree();
+        Standard_Integer NbKnots = myBSplineCurve->NbKnots();
+        TColStd_Array1OfInteger Mults(1, NbKnots);
+        myBSplineCurve->Multiplicities(Mults);
+        NbSplit = 1;
+        Standard_Integer Index = FirstIndex;
+        Inter(NbSplit) = Index;
+        Index++;
+        NbSplit++;
+        while (Index < LastIndex)
+        {
+          if (Degree - Mults(Index) < Cont)
+          {
+            Inter(NbSplit) = Index;
+            NbSplit++;
+          }
           Index++;
-          NbSplit++;
-          while (Index < LastIndex) 
-            {
-             if (Degree - Mults (Index) < Cont) 
-               {
-                 Inter (NbSplit) = Index;
-                 NbSplit++;
-               }
-             Index++;
-           }
-         Inter (NbSplit) = Index;
-          Standard_Integer NbInt = NbSplit-1;
-         
-         Standard_Integer Nb = myBSplineCurve->NbKnots();
-         Standard_Integer Index1 = 0;
-         Standard_Integer Index2 = 0;
-         Standard_Real newFirst, newLast;
-         TColStd_Array1OfReal    TK(1,Nb);
-         TColStd_Array1OfInteger TM(1,Nb);
-         myBSplineCurve->Knots(TK);
-         myBSplineCurve->Multiplicities(TM);
-         BSplCLib::LocateParameter(myBSplineCurve->Degree(),TK,TM,myFirst,
-                                   myBSplineCurve->IsPeriodic(),
-                                   1,Nb,Index1,newFirst);
-         BSplCLib::LocateParameter(myBSplineCurve->Degree(),TK,TM,myLast,
-                                   myBSplineCurve->IsPeriodic(),
-                                   1,Nb,Index2,newLast);
-
-
-         // On decale eventuellement les indices  
-         // On utilise une "petite" tolerance, la resolution ne doit 
-          // servir que pour les tres longue courbes....(PRO9248)
-          Standard_Real Eps = Min(Resolution(Precision::Confusion()),
-                                 Precision::PConfusion()); 
-         if ( Abs(newFirst-TK(Index1+1))< Eps) Index1++;
-         if ( newLast-TK(Index2)> Eps) Index2++;
-         
-         Inter( 1) = Index1;
-         myNbIntervals = 1;
-         for ( Standard_Integer i=1; i<=NbInt; i++) {
-           if (Inter(i) > Index1 && Inter(i)<Index2 ) {
-             myNbIntervals++;
-             Inter(myNbIntervals) = Inter(i);
-           }
-         }
-         Inter(myNbIntervals+1) = Index2;
-         
-         Standard_Integer ii = T.Lower() - 1;
-         for (Standard_Integer I=1;I<=myNbIntervals+1;I++) {
-           T(ii + I) = TK(Inter(I));
-         }
-       }
-       break;
+        }
+        Inter(NbSplit) = Index;
+        Standard_Integer NbInt = NbSplit - 1;
+
+        Standard_Integer Nb = myBSplineCurve->NbKnots();
+        Standard_Integer Index1 = 0;
+        Standard_Integer Index2 = 0;
+        Standard_Real newFirst, newLast;
+        TColStd_Array1OfReal    TK(1, Nb);
+        TColStd_Array1OfInteger TM(1, Nb);
+        myBSplineCurve->Knots(TK);
+        myBSplineCurve->Multiplicities(TM);
+        Standard_Real Eps = Min(Resolution(Precision::Confusion()),
+          Precision::PConfusion());
+
+        if (!myBSplineCurve->IsPeriodic())
+        {
+          BSplCLib::LocateParameter(myBSplineCurve->Degree(), TK, TM, myFirst,
+            myBSplineCurve->IsPeriodic(),
+            1, Nb, Index1, newFirst);
+          BSplCLib::LocateParameter(myBSplineCurve->Degree(), TK, TM, myLast,
+            myBSplineCurve->IsPeriodic(),
+            1, Nb, Index2, newLast);
+
+
+          // On decale eventuellement les indices  
+          // On utilise une "petite" tolerance, la resolution ne doit 
+                // servir que pour les tres longue courbes....(PRO9248)
+          if (Abs(newFirst - TK(Index1 + 1)) < Eps) Index1++;
+          if (newLast - TK(Index2) > Eps) Index2++;
+
+          Inter(1) = Index1;
+          myNbIntervals = 1;
+          for (Standard_Integer i = 1; i <= NbInt; i++) {
+            if (Inter(i) > Index1 && Inter(i) < Index2) {
+              myNbIntervals++;
+              Inter(myNbIntervals) = Inter(i);
+            }
+          }
+          Inter(myNbIntervals + 1) = Index2;
+
+          Standard_Integer ii = T.Lower() - 1;
+          for (Standard_Integer I = 1; I <= myNbIntervals + 1; I++) {
+            T(ii + I) = TK(Inter(I));
+          }
+        }
+        else
+        {
+          Standard_Real aFirst = myFirst;
+          Standard_Real aLast = myLast;
+
+          Standard_Real aCurFirst = aFirst;
+          Standard_Real aCurLast = aLast;
+
+          Standard_Real aPeriod = myBSplineCurve->Period();
+          Standard_Real aLower = myBSplineCurve->FirstParameter();
+          Standard_Real anUpper = myBSplineCurve->LastParameter();
+
+          Standard_Integer aLPer = 0; Standard_Integer aFPer = 0;
+
+          if (Abs(myFirst - aLower) <= Eps)
+          {
+            aCurFirst = aLower;
+            aFirst = aCurFirst;
+          }
+          if (Abs(myLast - anUpper) <= Eps)
+          {
+            aCurLast = anUpper;
+            aLast = aCurLast;
+          }
+
+          if ((Abs(aLower - myFirst) < Eps) && (aCurFirst < aLower))
+          {
+            aCurFirst = aLower;
+          }
+          else
+          {
+            DefinFPeriod(aLower, anUpper,
+              Eps, aPeriod, aCurFirst, aFPer);
+          }
+          DefinLPeriod(aLower, anUpper,
+            Eps, aPeriod, aCurLast, aLPer);
+
+          if (myFirst == aLower)
+          {
+            aFPer = 0;
+          }
+
+          SpreadInt(TK, TM, Inter, myBSplineCurve->Degree(), Nb, aFPer, aLPer, NbInt, aLower, myFirst, myLast, aPeriod,
+            aCurLast, Eps, T, myNbIntervals);
+          T(T.Lower()) = aFirst;
+          T(T.Lower() + myNbIntervals) = aLast;
+          return;
+
+        }
+      }
+      T(T.Lower()) = myFirst;
+      T(T.Lower() + myNbIntervals) = myLast;
+      return;
       }
     }
   }
index c1ed8ab27765405b2864031e68b71d3da12f73a5..24aacacb7757037e22077818d1bf3099658f978c 100644 (file)
@@ -58,6 +58,65 @@ static const Standard_Real PosTol = Precision::PConfusion() / 2;
 
 IMPLEMENT_STANDARD_RTTIEXT(GeomAdaptor_Curve, Adaptor3d_Curve)
 
+static void DefinFPeriod(const Standard_Real theLower,
+  const Standard_Real theUpper,
+  const Standard_Real theEps,
+  const Standard_Real thePeriod,
+  Standard_Real &theCurFirst,
+  Standard_Integer &theFPer);
+
+static void DefinLPeriod(const Standard_Real theLower,
+  const Standard_Real theUpper,
+  const Standard_Real theEps,
+  const Standard_Real thePeriod,
+  Standard_Real &theCurLast,
+  Standard_Integer &theLPer);
+
+static Standard_Integer LocalNbIntervals(const TColStd_Array1OfReal& theTK,
+  const TColStd_Array1OfInteger& theTM,
+  const TColStd_Array1OfInteger& theInter,
+  const Standard_Integer theCurDegree,
+  const Standard_Integer theNb,
+  const Standard_Integer theNbInt,
+  const Standard_Real theFirst,
+  const Standard_Real theLast,
+  const Standard_Real theEps,
+  const Standard_Boolean thePeriodicCur,
+  Standard_Integer theNbIntervals,
+  Standard_Real theLower = 0,
+  Standard_Real thePeriod = 0,
+  Standard_Integer theIndex1 = 0,
+  Standard_Integer theIndex2 = 0);
+
+static void WriteIntervals(const TColStd_Array1OfReal &theTK,
+  const TColStd_Array1OfInteger &theInter,
+  const Standard_Integer theNbInt,
+  const Standard_Integer theIndex1,
+  const Standard_Integer theIndex2,
+  const Standard_Real theCurPeriod,
+  const Standard_Boolean theFlagForFirst,
+  TColStd_Array1OfReal &theT,
+  TColStd_Array1OfInteger &theFinalIntervals,
+  Standard_Integer &theNbIntervals,
+  Standard_Integer &theCurInt);
+
+static void SpreadInt(const TColStd_Array1OfReal &theTK,
+  const TColStd_Array1OfInteger &theTM,
+  const TColStd_Array1OfInteger &theInter,
+  const Standard_Integer theCurDegree,
+  const Standard_Integer theNb,
+  const Standard_Integer theFPer,
+  const Standard_Integer theLPer,
+  const Standard_Integer theNbInt,
+  const Standard_Real theLower,
+  const Standard_Real theFirst,
+  const Standard_Real theLast,
+  const Standard_Real thePeriod,
+  const Standard_Real theLastParam,
+  const Standard_Real theEps,
+  TColStd_Array1OfReal &theT,
+  Standard_Integer &theNbIntervals);
+
 //=======================================================================
 //function : ShallowCopy
 //purpose  : 
@@ -114,7 +173,7 @@ GeomAbs_Shape GeomAdaptor_Curve::LocalContinuity(const Standard_Real U1,
   if ( (myBSplineCurve->IsPeriodic()) && (Index1 == Nb) )
     Index1 = 1;
 
-  if ( Index2 - Index1 <= 0) {
+  if ((Index2 - Index1 <= 0) && (!myBSplineCurve->IsPeriodic())) {
     MultMax = 100;  // CN entre 2 Noeuds consecutifs
   }
   else {
@@ -251,6 +310,159 @@ GeomAbs_Shape GeomAdaptor_Curve::Continuity() const
   return GeomAbs_CN;
 }
 
+//=======================================================================
+//function : DefinFPeriod
+//purpose  :
+//=======================================================================
+
+void DefinFPeriod(const Standard_Real theLower,
+  const Standard_Real theUpper,
+  const Standard_Real theEps,
+  const Standard_Real thePeriod,
+  Standard_Real &theCurFirst,
+  Standard_Integer &theFPer)
+{
+  if (theCurFirst >= theLower)
+  {
+    while (theCurFirst >= theUpper)
+    {
+      theCurFirst = theCurFirst - thePeriod;
+      theFPer++;
+    }
+    if (Abs(theUpper - theCurFirst) <= theEps)
+    {
+      theFPer++;
+      theCurFirst = theLower;
+    }
+  }
+  else
+  {
+    while (theCurFirst < theLower)
+    {
+      theCurFirst = theCurFirst + thePeriod;
+      if ((Abs(theLower - theCurFirst)) > theEps)
+      {
+        theFPer--;
+      }
+    }
+
+    if (Abs(theUpper - theCurFirst) <= theEps)
+    {
+      theCurFirst = theLower;
+    }
+  }
+}
+
+//=======================================================================
+//function : DefinLPeriod
+//purpose  :
+//=======================================================================
+
+void DefinLPeriod(const Standard_Real theLower,
+  const Standard_Real theUpper,
+  const Standard_Real theEps,
+  const Standard_Real thePeriod,
+  Standard_Real &theCurLast,
+  Standard_Integer &theLPer)
+{
+  if (theCurLast >= theLower)
+  {
+    if ((theCurLast >= theUpper) && (Abs(theCurLast - theUpper) <= theEps))
+    {
+      theCurLast = theUpper;
+    }
+    else
+    {
+      while (theCurLast >= theUpper)
+      {
+        theCurLast = theCurLast - thePeriod;
+        theLPer++;
+      }
+      if (Abs(theUpper - theCurLast) <= theEps)
+      {
+        theCurLast = theLower;
+      }
+    }
+  }
+  else
+  {
+    while (theCurLast < theLower)
+    {
+      theCurLast = theCurLast + thePeriod;
+      if (Abs(theLower - theCurLast) > theEps)
+      {
+        theLPer--;
+      }
+    }
+    if ((theUpper - theCurLast) <= theEps)
+    {
+      theCurLast = theLower;
+    }
+  }
+}
+
+//=======================================================================
+//function : LocalNbIntervals
+//purpose  :
+//=======================================================================
+
+Standard_Integer LocalNbIntervals(const TColStd_Array1OfReal& theTK,
+  const TColStd_Array1OfInteger& theTM,
+  const TColStd_Array1OfInteger& theInter,
+  const Standard_Integer theCurDegree,
+  const Standard_Integer theNb,
+  const Standard_Integer theNbInt,
+  const Standard_Real theFirst,
+  const Standard_Real theLast,
+  const Standard_Real theEps,
+  const Standard_Boolean thePeriodicCur,
+  Standard_Integer theNbIntervals,
+  Standard_Real theLower,
+  Standard_Real thePeriod,
+  Standard_Integer theIndex1,
+  Standard_Integer theIndex2)
+{
+  Standard_Real aNewFirst = theFirst;
+  Standard_Real aNewLast = theLast;
+  if (theIndex1 == 0)
+  {
+    BSplCLib::LocateParameter(theCurDegree, theTK, theTM, theFirst,
+      thePeriodicCur, 1, theNb, theIndex1, aNewFirst);
+  }
+  if (theIndex2 == 0)
+  {
+    BSplCLib::LocateParameter(theCurDegree, theTK, theTM, theLast,
+      thePeriodicCur, 1, theNb, theIndex2, aNewLast);
+  }
+  // Protection against theFirst = UFirst - eps, which located as ULast - eps
+  if (thePeriodicCur && ((aNewLast - aNewFirst) < Precision::PConfusion()))
+  {
+    if (Abs(aNewLast - theLower) < Precision::PConfusion())
+    {
+      aNewLast += thePeriod;
+    }
+    else
+    {
+      aNewFirst -= thePeriod;
+    }
+  }
+
+  if (Abs(aNewFirst - theTK(theIndex1 + 1)) < theEps)
+  {
+    theIndex1++;
+  }
+  if ((aNewLast - theTK(theIndex2)) > theEps)
+  {
+    theIndex2++;
+  }
+  for (Standard_Integer i = 1; i <= theNbInt; i++)
+  {
+    if (theInter(i) > theIndex1 && theInter(i) < theIndex2) theNbIntervals++;
+  }
+  return theNbIntervals;
+}
+
+
 //=======================================================================
 //function : NbIntervals
 //purpose  : 
@@ -262,11 +474,14 @@ Standard_Integer GeomAdaptor_Curve::NbIntervals(const GeomAbs_Shape S) const
   Standard_Integer NbSplit;
   if (myTypeCurve == GeomAbs_BSplineCurve) {
     Standard_Integer FirstIndex = myBSplineCurve->FirstUKnotIndex();
-    Standard_Integer LastIndex  = myBSplineCurve->LastUKnotIndex();
-    TColStd_Array1OfInteger Inter (1, LastIndex-FirstIndex+1);
-    if ( S > Continuity()) {
+    Standard_Integer LastIndex = myBSplineCurve->LastUKnotIndex();
+    TColStd_Array1OfInteger Inter(1, LastIndex - FirstIndex + 1);
+    Standard_Boolean aContPer = (S >= Continuity()) && myBSplineCurve->IsPeriodic();
+    Standard_Boolean aContNotPer = (S > Continuity()) && !myBSplineCurve->IsPeriodic();
+
+    if(aContPer || aContNotPer) {
       Standard_Integer Cont;
-      switch ( S) {
+      switch (S) {
       case GeomAbs_G1:
       case GeomAbs_G2:
         throw Standard_DomainError("GeomAdaptor_Curve::NbIntervals");
@@ -276,68 +491,168 @@ Standard_Integer GeomAdaptor_Curve::NbIntervals(const GeomAbs_Shape S) const
         break;
       case GeomAbs_C1:
       case GeomAbs_C2:
-      case GeomAbs_C3: 
-      case GeomAbs_CN: 
+      case GeomAbs_C3:
+      case GeomAbs_CN:
+      {
+        if (S == GeomAbs_C1) Cont = 1;
+        else if (S == GeomAbs_C2) Cont = 2;
+        else if (S == GeomAbs_C3) Cont = 3;
+        else                       Cont = myBSplineCurve->Degree();
+        Standard_Integer Degree = myBSplineCurve->Degree();
+        Standard_Integer NbKnots = myBSplineCurve->NbKnots();
+        TColStd_Array1OfInteger Mults(1, NbKnots);
+        myBSplineCurve->Multiplicities(Mults);
+        NbSplit = 1;
+        Standard_Integer Index = FirstIndex;
+        Inter(NbSplit) = Index;
+        Index++;
+        NbSplit++;
+        while (Index < LastIndex)
         {
-          if      ( S == GeomAbs_C1) Cont = 1;
-          else if ( S == GeomAbs_C2) Cont = 2;
-          else if ( S == GeomAbs_C3) Cont = 3;
-          else                       Cont = myBSplineCurve->Degree();
-          Standard_Integer Degree = myBSplineCurve->Degree();
-          Standard_Integer NbKnots = myBSplineCurve->NbKnots();
-          TColStd_Array1OfInteger Mults (1, NbKnots);
-          myBSplineCurve->Multiplicities (Mults);
-          NbSplit = 1;
-          Standard_Integer Index   = FirstIndex;
-          Inter (NbSplit) = Index;
+          if (Degree - Mults(Index) < Cont)
+          {
+            Inter(NbSplit) = Index;
+            NbSplit++;
+          }
           Index++;
-          NbSplit++;
-          while (Index < LastIndex) 
-            {
-             if (Degree - Mults (Index) < Cont) 
-               {
-                 Inter (NbSplit) = Index;
-                 NbSplit++;
-               }
-             Index++;
-           }
-          Inter (NbSplit) = Index;
-
-          Standard_Integer NbInt = NbSplit-1;
-          
-          Standard_Integer Nb = myBSplineCurve->NbKnots();
-          Standard_Integer Index1 = 0;
-          Standard_Integer Index2 = 0;
-          Standard_Real newFirst, newLast;
-          const TColStd_Array1OfReal& TK = myBSplineCurve->Knots();
-          const TColStd_Array1OfInteger& TM = myBSplineCurve->Multiplicities();
-          BSplCLib::LocateParameter(myBSplineCurve->Degree(),TK,TM,myFirst,
-                                    myBSplineCurve->IsPeriodic(),
-                                    1,Nb,Index1,newFirst);
-          BSplCLib::LocateParameter(myBSplineCurve->Degree(),TK,TM,myLast,
-                                    myBSplineCurve->IsPeriodic(),
-                                    1,Nb,Index2,newLast);
-          // Protection against myFirst = UFirst - eps, which located as ULast - eps
-          if (myBSplineCurve->IsPeriodic() && (newLast - newFirst) < Precision::PConfusion())
+        }
+        Inter(NbSplit) = Index;
+
+        Standard_Integer NbInt = NbSplit - 1;
+
+        Standard_Integer Nb = myBSplineCurve->NbKnots();
+        Standard_Integer Index1 = 0;
+        Standard_Integer Index2 = 0;
+        const TColStd_Array1OfReal& TK = myBSplineCurve->Knots();
+        const TColStd_Array1OfInteger& TM = myBSplineCurve->Multiplicities();
+        Standard_Real Eps = Min(Resolution(Precision::Confusion()),
+          Precision::PConfusion());
+
+        myNbIntervals = 1;
+
+        if (!myBSplineCurve->IsPeriodic())
+        {
+          myNbIntervals = LocalNbIntervals(TK, TM, Inter, Degree, Nb, NbInt,
+            myFirst, myLast, Eps, Standard_False, myNbIntervals);
+        }
+        else
+        {
+          Standard_Real aCurFirst = myFirst;
+          Standard_Real aCurLast = myLast;
+          Standard_Real aLower = myBSplineCurve->FirstParameter();
+          Standard_Real anUpper = myBSplineCurve->LastParameter();
+
+          if ((Abs(aCurFirst - aLower) < Eps) && (aCurFirst < aLower))
+          {
+            aCurFirst = aLower;
+          }
+          if ((Abs(aCurLast - anUpper) < Eps) && (aCurLast < anUpper))
+          {
+            aCurLast = anUpper;
+          }
+
+          Standard_Real aPeriod = myBSplineCurve->Period();
+          Standard_Integer aLPer = 1; Standard_Integer aFPer = 1;
+          if ((Abs(aLower - myFirst) < Eps) && (aCurFirst < aLower))
           {
-            if (Abs(newLast - myBSplineCurve->FirstParameter()) < Precision::PConfusion())
-              newLast += myBSplineCurve->Period();
+            aCurFirst = aLower;
+          }
+          else
+          {
+            DefinFPeriod(aLower, anUpper,
+              Eps, aPeriod, aCurFirst, aFPer);
+          }
+          DefinLPeriod(aLower, anUpper,
+            Eps, aPeriod, aCurLast, aLPer);
+
+          Standard_Real aNewFirst;
+          Standard_Real aNewLast;
+          BSplCLib::LocateParameter(myBSplineCurve->Degree(), TK, TM, myFirst,
+            Standard_True, 1, Nb, Index1, aNewFirst);
+          BSplCLib::LocateParameter(myBSplineCurve->Degree(), TK, TM, myLast,
+            Standard_True, 1, Nb, Index2, aNewLast);
+          if ((aNewFirst == myFirst && aNewLast == myLast) && (aFPer != aLPer))
+          {
+            myNbIntervals = LocalNbIntervals(TK, TM, Inter, Degree, Nb, NbInt,
+              myFirst, myLast, Eps, Standard_True, myNbIntervals, aLower, aPeriod);
+          }
+          else
+          {
+            Standard_Integer aSumPer = Abs(aLPer - aFPer);
+            
+            Standard_Real aFirst = 0;
+            if (aLower < 0 && anUpper == 0)
+            {
+              if (Abs(aCurLast) < Eps)
+              {
+                aCurLast = 0;
+              }
+              aFirst = aLower;
+            }
+
+            if (aSumPer <= 1)
+            {
+              if ((Abs(myFirst - TK(Nb) - aPeriod * (aFPer - 1)) <= Eps) && (myLast < (TK(Nb) + aPeriod * (aLPer - 1))))
+              {
+                myNbIntervals = LocalNbIntervals(TK, TM, Inter, Degree, Nb, NbInt,
+                  myFirst, myLast, Eps, Standard_True, myNbIntervals, aLower, aPeriod);
+                return myNbIntervals;
+              }
+              if ((Abs(myFirst - aLower) < Eps) && (Abs(myLast - anUpper) < Eps))
+              {
+                myNbIntervals = LocalNbIntervals(TK, TM, Inter, Degree, Nb, NbInt,
+                  myFirst, myLast, Eps, Standard_True, myNbIntervals, aLower, aPeriod);
+                return myNbIntervals;
+              }
+            }
+
+            if (aSumPer != 0)
+            {
+              Standard_Integer aFInt = 0;
+              Standard_Integer aLInt = 0;
+              Standard_Integer aPInt = NbInt;
+
+              if ((aCurFirst != aPeriod) || ((aCurFirst != anUpper) && (Abs(myFirst) < Eps)))
+              {
+                aFInt = 1;
+              }
+              if ((aCurLast != aLower) && (aCurLast != anUpper))
+              {
+                aLInt = 1;
+              }
+
+              aFInt = LocalNbIntervals(TK, TM, Inter, Degree, Nb, NbInt,
+                aCurFirst, anUpper, Eps, Standard_True, aFInt, aLower, aPeriod);
+
+              if (aCurLast == anUpper)
+              {
+                aLInt = NbInt;
+              }
+              else
+              {
+                if (Abs(aCurLast - aFirst) > Eps)
+                {
+                  aLInt = LocalNbIntervals(TK, TM, Inter, Degree, Nb, NbInt,
+                    aFirst, aCurLast, Eps, Standard_True, aLInt, aLower, aPeriod, 1);
+                }
+                else
+                {
+                  aLInt = LocalNbIntervals(TK, TM, Inter, Degree, Nb, NbInt,
+                    aFirst, aCurLast, Eps, Standard_True, aLInt, aLower, aPeriod);
+                }
+              }
+
+              myNbIntervals = aFInt + aLInt + aPInt * (aSumPer - 1);
+            }
             else
-              newFirst -= myBSplineCurve->Period();
+            {
+              myNbIntervals = LocalNbIntervals(TK, TM, Inter, Degree, Nb, NbInt,
+                aCurFirst, aCurLast, Eps, Standard_True, myNbIntervals, aLower, aPeriod);
+            }
           }
-          // On decale eventuellement les indices  
-          // On utilise une "petite" tolerance, la resolution ne doit 
-          // servir que pour les tres longue courbes....(PRO9248)
-          Standard_Real Eps = Min(Resolution(Precision::Confusion()),
-                                  Precision::PConfusion()); 
-          if ( Abs(newFirst-TK(Index1+1))< Eps) Index1++;
-          if ( newLast-TK(Index2)> Eps) Index2++;
-          
-          myNbIntervals = 1;
-          for ( Standard_Integer i=1; i<=NbInt; i++)
-            if (Inter(i)>Index1 && Inter(i)<Index2) myNbIntervals++;
         }
-        break;
+      }
+      break;
       }
     }
   }
@@ -373,6 +688,206 @@ Standard_Integer GeomAdaptor_Curve::NbIntervals(const GeomAbs_Shape S) const
   return myNbIntervals;
 }
 
+//=======================================================================
+//function : WriteIntervals
+//purpose  :
+//=======================================================================
+
+static void WriteIntervals(const TColStd_Array1OfReal &theTK,
+  const TColStd_Array1OfInteger &theInter,
+  const Standard_Integer theNbInt,
+  const Standard_Integer theIndex1,
+  const Standard_Integer theIndex2,
+  const Standard_Real theCurPeriod,
+  const Standard_Boolean theFlagForFirst,
+  TColStd_Array1OfReal &theT,
+  TColStd_Array1OfInteger &theFinalIntervals,
+  Standard_Integer &theNbIntervals,
+  Standard_Integer &theCurInt)
+{
+  if (theFlagForFirst)
+  {
+    for (Standard_Integer anId = 1; anId <= theNbInt; anId++)
+    {
+      if (theInter(anId) > theIndex1 && theInter(anId) <= theIndex2)
+      {
+        theNbIntervals++;
+        theFinalIntervals(theNbIntervals) = theInter(anId);
+      }
+    }
+  }
+  else
+  {
+    for (Standard_Integer anId = 1; anId <= theNbInt; anId++)
+    {
+      if (theInter(anId) > theIndex1 && theInter(anId) < theIndex2)
+      {
+        theNbIntervals++;
+        theFinalIntervals(theNbIntervals) = theInter(anId);
+      }
+    }
+  }
+  theFinalIntervals(theNbIntervals + 1) = theIndex2;
+
+  for (Standard_Integer anId = theCurInt; anId <= theNbIntervals + 1; anId++)
+  {
+    theT(anId) = theTK(theFinalIntervals(anId)) + theCurPeriod;
+    theCurInt++;
+  }
+}
+
+//=======================================================================
+//function : SpreadInt
+//purpose  :
+//=======================================================================
+
+void SpreadInt(const TColStd_Array1OfReal &theTK,
+  const TColStd_Array1OfInteger &theTM,
+  const TColStd_Array1OfInteger &theInter,
+  const Standard_Integer theCurDegree,
+  const Standard_Integer theNb,
+  const Standard_Integer theFPer,
+  const Standard_Integer theLPer,
+  const Standard_Integer theNbInt,
+  const Standard_Real theLower,
+  const Standard_Real theFirst,
+  const Standard_Real theLast,
+  const Standard_Real thePeriod,
+  const Standard_Real theLastParam,
+  const Standard_Real theEps,
+  TColStd_Array1OfReal &theT,
+  Standard_Integer &theNbIntervals)
+{
+  Standard_Integer anIndex1 = 0;
+  Standard_Integer anIndex2 = 0;
+  Standard_Real aNewFirst, aNewLast;
+  Standard_Integer anUpper;
+  BSplCLib::LocateParameter(theCurDegree, theTK, theTM, theFirst,
+    Standard_True, 1, theNb, anIndex1, aNewFirst);
+  BSplCLib::LocateParameter(theCurDegree, theTK, theTM, theLastParam,
+    Standard_True, 1, theNb, anIndex2, aNewLast);
+
+  if (Abs(aNewFirst - theTK(anIndex1 + 1)) < theEps)
+  {
+    anIndex1++;
+  }
+  if ((aNewLast - theTK(anIndex2)) > theEps)
+  {
+    anIndex2++;
+  }
+  theNbIntervals = 1;
+
+  if (anIndex1 == theNb)
+  {
+    anIndex1 = 1;
+  }
+
+  // Count the max number of boundaries of intervals
+  if (Abs(theLPer - theFPer) > 1)
+  {
+    anUpper = theNb - anIndex1 + anIndex2 + (theLPer - theFPer - 1) * theNb + 1;
+  }
+  else
+  {
+    anUpper = theNb - anIndex1 + anIndex2 + 1;
+  }
+
+  if (theLPer == theFPer)
+  {
+    anUpper = theInter.Upper();
+  }
+  TColStd_Array1OfInteger aFinalIntervals(1, anUpper);
+  aFinalIntervals(1) = anIndex1;
+
+  // If first and last are in the same period
+  if ((Abs(theLPer - theFPer) == 0))
+  {
+    Standard_Integer aCurInt = 1;
+    Standard_Real aCurPeriod = theFPer * thePeriod;
+
+    if (theFirst == aNewFirst && theLast == aNewLast)
+    {
+      aCurPeriod = 0;
+    }
+    WriteIntervals(theTK, theInter, theNbInt, anIndex1,
+      anIndex2, aCurPeriod, Standard_False, theT, aFinalIntervals, theNbIntervals, aCurInt);
+    return;
+  }
+
+  // If the first and the last are in neighboring periods
+  if (Abs(theLPer - theFPer) == 1)
+  {
+    Standard_Integer aCurInt = 1;
+
+    if (Abs(theLastParam - theLower) < theEps)
+    {
+      WriteIntervals(theTK, theInter, theNbInt, anIndex1,
+        theNb, theFPer * thePeriod, Standard_True, theT, aFinalIntervals, theNbIntervals, aCurInt);
+      return;
+    }
+    else
+    {
+      // For period with first
+      WriteIntervals(theTK, theInter, theNbInt, anIndex1,
+        theNb, theFPer * thePeriod, Standard_True, theT, aFinalIntervals, theNbIntervals, aCurInt);
+      // For period with last
+      theNbIntervals++;
+      WriteIntervals(theTK, theInter, theNbInt, 1,
+        anIndex2, theLPer * thePeriod, Standard_False, theT, aFinalIntervals, theNbIntervals, aCurInt);
+      return;
+    }
+  }
+  // If the first and the last are far apart
+  if (Abs(theLPer - theFPer) > 1)
+  {
+    Standard_Integer aCurInt = 1;
+
+    if (Abs(theLastParam - theLower) < theEps)
+    {
+      WriteIntervals(theTK, theInter, theNbInt, anIndex1,
+        theNb, theFPer * thePeriod, Standard_True, theT, aFinalIntervals, theNbIntervals, aCurInt);
+
+      Standard_Integer aNbPer = Abs(theLPer - theFPer);
+      Standard_Integer aCurPer = theFPer + 1;
+
+      while (aNbPer > 1)
+      {
+        theNbIntervals++;
+        WriteIntervals(theTK, theInter, theNbInt, 1,
+          theNb, aCurPer * thePeriod, Standard_True, theT, aFinalIntervals, theNbIntervals, aCurInt);
+        
+        aNbPer--;
+        aCurPer++;
+      }
+      return;
+    }
+    else
+    {
+      // For period with first
+      WriteIntervals(theTK, theInter, theNbInt, anIndex1,
+        theNb, theFPer * thePeriod, Standard_True, theT, aFinalIntervals, theNbIntervals, aCurInt);
+      
+      Standard_Integer aNbPer = Abs(theLPer - theFPer);
+      Standard_Integer aCurPer = theFPer + 1;
+      while (aNbPer > 1)
+      {
+        theNbIntervals++;
+        WriteIntervals(theTK, theInter, theNbInt, 1,
+          theNb, aCurPer * thePeriod, Standard_True, theT, aFinalIntervals, theNbIntervals, aCurInt);
+
+        aNbPer--;
+        aCurPer++;
+      }
+      // For period with last
+      theNbIntervals++;
+      WriteIntervals(theTK, theInter, theNbInt, 1,
+        anIndex2, theLPer * thePeriod, Standard_False, theT, aFinalIntervals, theNbIntervals, aCurInt);
+      return;
+    }
+  }
+}
+
 //=======================================================================
 //function : Intervals
 //purpose  : 
@@ -385,106 +900,166 @@ void GeomAdaptor_Curve::Intervals(TColStd_Array1OfReal& T,
   Standard_Integer NbSplit;
   Standard_Real FirstParam = myFirst, LastParam = myLast;
 
-  if (myTypeCurve == GeomAbs_BSplineCurve) 
-    {
-      Standard_Integer FirstIndex = myBSplineCurve->FirstUKnotIndex();
-      Standard_Integer LastIndex  = myBSplineCurve->LastUKnotIndex();
-      TColStd_Array1OfInteger Inter (1, LastIndex-FirstIndex+1);
-      
-      if ( S > Continuity()) {
-       Standard_Integer Cont;
-       switch ( S) {
-       case GeomAbs_G1:
-       case GeomAbs_G2:
-         throw Standard_DomainError("Geom2dAdaptor_Curve::NbIntervals");
-         break;
-       case GeomAbs_C0:
-         myNbIntervals = 1;
-         break;
-       case GeomAbs_C1:
-       case GeomAbs_C2:
-       case GeomAbs_C3: 
-       case GeomAbs_CN: 
-         {
-           if      ( S == GeomAbs_C1) Cont = 1;
-           else if ( S == GeomAbs_C2) Cont = 2;
-           else if ( S == GeomAbs_C3) Cont = 3;
-           else                       Cont = myBSplineCurve->Degree();
-           Standard_Integer Degree = myBSplineCurve->Degree();
-           Standard_Integer NbKnots = myBSplineCurve->NbKnots();
-           TColStd_Array1OfInteger Mults (1, NbKnots);
-           myBSplineCurve->Multiplicities (Mults);
-           NbSplit = 1;
-           Standard_Integer Index   = FirstIndex;
-           Inter (NbSplit) = Index;
-           Index++;
-           NbSplit++;
-           while (Index < LastIndex) 
-             {
-               if (Degree - Mults (Index) < Cont) 
-                 {
-                    Inter (NbSplit) = Index;
-                    NbSplit++;
-                 }
-               Index++;
-             }
-            Inter (NbSplit) = Index;
-           Standard_Integer NbInt = NbSplit-1;
-           //        GeomConvert_BSplineCurveKnotSplitting Convector(myBspl, Cont);
-           //        Standard_Integer NbInt = Convector.NbSplits()-1;
-           //        TColStd_Array1OfInteger Inter(1,NbInt+1);
-           //        Convector.Splitting( Inter);
-           
-           Standard_Integer Nb = myBSplineCurve->NbKnots();
-           Standard_Integer Index1 = 0;
-           Standard_Integer Index2 = 0;
-           Standard_Real newFirst, newLast;
-            const TColStd_Array1OfReal& TK = myBSplineCurve->Knots();
-            const TColStd_Array1OfInteger& TM = myBSplineCurve->Multiplicities();
-           BSplCLib::LocateParameter(myBSplineCurve->Degree(),TK,TM,myFirst,
-                                     myBSplineCurve->IsPeriodic(),
-                                     1,Nb,Index1,newFirst);
-           BSplCLib::LocateParameter(myBSplineCurve->Degree(),TK,TM,myLast,
-                                     myBSplineCurve->IsPeriodic(),
-                                     1,Nb,Index2,newLast);
-            FirstParam = newFirst;
-            LastParam = newLast;
-            // Protection against myFirst = UFirst - eps, which located as ULast - eps
-            if (myBSplineCurve->IsPeriodic() && (LastParam - FirstParam) < Precision::PConfusion())
-            {
-              if (Abs(LastParam - myBSplineCurve->FirstParameter()) < Precision::PConfusion())
-                LastParam += myBSplineCurve->Period();
-              else
-                FirstParam -= myBSplineCurve->Period();
+  if (myTypeCurve == GeomAbs_BSplineCurve)
+  {
+    Standard_Integer FirstIndex = myBSplineCurve->FirstUKnotIndex();
+    Standard_Integer LastIndex = myBSplineCurve->LastUKnotIndex();
+    TColStd_Array1OfInteger Inter(1, LastIndex - FirstIndex + 1);
+    Standard_Boolean aContPer = (S >= Continuity()) && myBSplineCurve->IsPeriodic();
+    Standard_Boolean aContNotPer = (S > Continuity()) && !myBSplineCurve->IsPeriodic();
+
+    if (aContPer || aContNotPer) {
+      Standard_Integer Cont;
+      switch (S) {
+      case GeomAbs_G1:
+      case GeomAbs_G2:
+        throw Standard_DomainError("Geom2dAdaptor_Curve::NbIntervals");
+        break;
+      case GeomAbs_C0:
+        myNbIntervals = 1;
+        break;
+      case GeomAbs_C1:
+      case GeomAbs_C2:
+      case GeomAbs_C3:
+      case GeomAbs_CN:
+      {
+        if (S == GeomAbs_C1) Cont = 1;
+        else if (S == GeomAbs_C2) Cont = 2;
+        else if (S == GeomAbs_C3) Cont = 3;
+        else                       Cont = myBSplineCurve->Degree();
+        Standard_Integer Degree = myBSplineCurve->Degree();
+        Standard_Integer NbKnots = myBSplineCurve->NbKnots();
+        TColStd_Array1OfInteger Mults(1, NbKnots);
+        myBSplineCurve->Multiplicities(Mults);
+        NbSplit = 1;
+        Standard_Integer Index = FirstIndex;
+        Inter(NbSplit) = Index;
+        Index++;
+        NbSplit++;
+        while (Index < LastIndex)
+        {
+          if (Degree - Mults(Index) < Cont)
+          {
+            Inter(NbSplit) = Index;
+            NbSplit++;
+          }
+          Index++;
+        }
+        Inter(NbSplit) = Index;
+        Standard_Integer NbInt = NbSplit - 1;
+        //        GeomConvert_BSplineCurveKnotSplitting Convector(myBspl, Cont);
+        //        Standard_Integer NbInt = Convector.NbSplits()-1;
+        //        TColStd_Array1OfInteger Inter(1,NbInt+1);
+        //        Convector.Splitting( Inter);
+
+        Standard_Integer Nb = myBSplineCurve->NbKnots();
+        Standard_Integer Index1 = 0;
+        Standard_Integer Index2 = 0;
+        Standard_Real newFirst, newLast;
+        const TColStd_Array1OfReal& TK = myBSplineCurve->Knots();
+        const TColStd_Array1OfInteger& TM = myBSplineCurve->Multiplicities();
+        Standard_Real Eps = Min(Resolution(Precision::Confusion()),
+          Precision::PConfusion());
+
+        if (!myBSplineCurve->IsPeriodic() || ((Abs(myFirst - myBSplineCurve->FirstParameter()) < Eps) &&
+          (Abs(myLast - myBSplineCurve->LastParameter()) < Eps)))
+        {
+          BSplCLib::LocateParameter(myBSplineCurve->Degree(), TK, TM, myFirst,
+            myBSplineCurve->IsPeriodic(),
+            1, Nb, Index1, newFirst);
+          BSplCLib::LocateParameter(myBSplineCurve->Degree(), TK, TM, myLast,
+            myBSplineCurve->IsPeriodic(),
+            1, Nb, Index2, newLast);
+          FirstParam = newFirst;
+          LastParam = newLast;
+          // Protection against myFirst = UFirst - eps, which located as ULast - eps
+          if (myBSplineCurve->IsPeriodic() && (LastParam - FirstParam) < Precision::PConfusion())
+          {
+            if (Abs(LastParam - myBSplineCurve->FirstParameter()) < Precision::PConfusion())
+              LastParam += myBSplineCurve->Period();
+            else
+              FirstParam -= myBSplineCurve->Period();
+          }
+          // On decale eventuellement les indices  
+          // On utilise une "petite" tolerance, la resolution ne doit 
+          // servir que pour les tres longue courbes....(PRO9248)
+
+          if (Abs(FirstParam - TK(Index1 + 1)) < Eps) Index1++;
+          if (LastParam - TK(Index2) > Eps) Index2++;
+
+          myNbIntervals = 1;
+
+          TColStd_Array1OfInteger aFinalIntervals(1, Inter.Upper());
+          aFinalIntervals(1) = Index1;
+          for (Standard_Integer i = 1; i <= NbInt; i++) {
+            if (Inter(i) > Index1 && Inter(i) < Index2) {
+              myNbIntervals++;
+              aFinalIntervals(myNbIntervals) = Inter(i);
             }
-           // On decale eventuellement les indices  
-           // On utilise une "petite" tolerance, la resolution ne doit 
-           // servir que pour les tres longue courbes....(PRO9248)
-           Standard_Real Eps = Min(Resolution(Precision::Confusion()),
-                                   Precision::PConfusion()); 
-           if ( Abs(FirstParam-TK(Index1+1))< Eps) Index1++;
-           if ( LastParam-TK(Index2)> Eps) Index2++;
-           
-           myNbIntervals = 1;
-
-            TColStd_Array1OfInteger aFinalIntervals(1, Inter.Upper());
-            aFinalIntervals(1) = Index1;
-           for ( Standard_Integer i=1; i<=NbInt; i++) {
-             if (Inter(i) > Index1 && Inter(i)<Index2 ) {
-               myNbIntervals++;
-                aFinalIntervals(myNbIntervals) = Inter(i);
-             }
-           }
-            aFinalIntervals(myNbIntervals + 1) = Index2;
-           
-           for (Standard_Integer I=1;I<=myNbIntervals+1;I++) {
-              T(I) = TK(aFinalIntervals(I));
-           }
-         }
-         break;
-       }
+          }
+          aFinalIntervals(myNbIntervals + 1) = Index2;
+
+          for (Standard_Integer I = 1; I <= myNbIntervals + 1; I++) {
+            T(I) = TK(aFinalIntervals(I));
+          }
+        }
+        else
+        {
+          Standard_Real aFirst = myFirst;
+          Standard_Real aLast = myLast;
+
+          Standard_Real aCurFirst = aFirst;
+          Standard_Real aCurLast = aLast;
+
+          Standard_Real aPeriod = myBSplineCurve->Period();
+          Standard_Real aLower = myBSplineCurve->FirstParameter();
+          Standard_Real anUpper = myBSplineCurve->LastParameter();
+
+          Standard_Integer aLPer = 0; Standard_Integer aFPer = 0;
+
+          if (Abs(myFirst - aLower) <= Eps)
+          {
+            aCurFirst = aLower;
+            aFirst = aCurFirst;
+          }
+
+          if (Abs(myLast - anUpper) <= Eps)
+          {
+            aCurLast = anUpper;
+            aLast = aCurLast;
+          }
+
+          if ((Abs(aLower - myFirst) < Eps) && (aCurFirst < aLower))
+          {
+            aCurFirst = aLower;
+          }
+          else
+          {
+            DefinFPeriod(aLower, anUpper,
+              Eps, aPeriod, aCurFirst, aFPer);
+          }
+          DefinLPeriod(aLower, anUpper,
+            Eps, aPeriod, aCurLast, aLPer);
+
+          if (myFirst == aLower)
+          {
+            aFPer = 0;
+          }
+
+          SpreadInt(TK, TM, Inter, myBSplineCurve->Degree(), Nb, aFPer, aLPer, NbInt, aLower, myFirst, myLast, aPeriod,
+            aCurLast, Eps, T, myNbIntervals);
+
+          T(T.Lower()) = aFirst;
+          T(T.Lower() + myNbIntervals) = aLast;
+          return;
+        }
+      }
+      T(T.Lower()) = myFirst;
+      T(T.Lower() + myNbIntervals) = myLast;
+      return;
       }
     }
+  }
 
   else if (myTypeCurve == GeomAbs_OffsetCurve){
     GeomAbs_Shape BaseS=GeomAbs_C0;
index d31af7ef8b23006715e84f7cb6958e1219c450b3..59b2ab1db4c25281dcaf61ad7f8ea2b9641f8cb4 100644 (file)
@@ -3093,6 +3093,80 @@ static Standard_Integer OCC30391(Draw_Interpretor& theDI,
   return 0;
 }
 
+//=======================================================================
+//function : OCC29745
+//purpose  :
+//=======================================================================
+static Standard_Integer OCC29745(Draw_Interpretor& theDI, Standard_Integer theArgc, const char** theArgv)
+{
+  if (theArgc != 5)
+  {
+    theDI << "Usage : OCC29745 curve2d/3d continuity t1 t2";
+    return 1;
+  }
+
+  Handle(Geom_Curve) aC3d;
+  Handle(Geom2d_Curve) aC2d;
+
+  aC3d = DrawTrSurf::GetCurve(theArgv[1]);
+  if (aC3d.IsNull())
+  {
+    aC2d = DrawTrSurf::GetCurve2d(theArgv[1]);
+    if (aC2d.IsNull())
+    {
+      theDI << "Null curve" << "\n";
+      return 1;
+    }
+  }
+
+  Standard_Integer i = Draw::Atoi(theArgv[2]);
+  GeomAbs_Shape aCont = GeomAbs_C0;
+  if (i <= 0)
+    aCont = GeomAbs_C0;
+  else if (i == 1)
+    aCont = GeomAbs_C1;
+  else if (i == 2)
+    aCont = GeomAbs_C2;
+  else if (i == 3)
+    aCont = GeomAbs_C3;
+  else if (i >= 4)
+    aCont = GeomAbs_CN;
+
+  Standard_Real t1 = Draw::Atof(theArgv[3]);
+  Standard_Real t2 = Draw::Atof(theArgv[4]);
+
+  GeomAdaptor_Curve aGAC3d;
+  Geom2dAdaptor_Curve aGAC2d;
+  Standard_Integer aNbInts;
+  if (aC2d.IsNull())
+  {
+    aGAC3d.Load(aC3d, t1, t2);
+    aNbInts = aGAC3d.NbIntervals(aCont);
+  }
+  else
+  {
+    aGAC2d.Load(aC2d, t1, t2);
+    aNbInts = aGAC2d.NbIntervals(aCont);
+  }
+
+  TColStd_HArray1OfReal anInters(1, aNbInts + 1);
+  if (aC2d.IsNull())
+  {
+    aGAC3d.Intervals(anInters, aCont);
+  }
+  else
+  {
+    aGAC2d.Intervals(anInters, aCont);
+  }
+
+  theDI << "NbIntervals: " << aNbInts << "; ";
+  for (i = anInters.Lower(); i <= anInters.Upper(); ++i)
+  {
+    theDI << anInters(i) << " ";
+  }
+  return 0;
+}
+
 #include <Standard_Mutex.hxx>
 #include <NCollection_Sequence.hxx>
 #include <BinLDrivers.hxx>
@@ -4298,6 +4372,8 @@ void QABugs::Commands_20(Draw_Interpretor& theCommands) {
   theCommands.Add("OCC29807", "OCC29807 surface1 surface2 u1 v1 u2 v2", __FILE__, OCC29807, group);
   theCommands.Add("OCC29311", "OCC29311 shape counter nbiter: check performance of OBB calculation", __FILE__, OCC29311, group);
   theCommands.Add("OCC30391", "OCC30391 result face LenBeforeUfirst LenAfterUlast LenBeforeVfirst LenAfterVlast", __FILE__, OCC30391, group);
+  theCommands.Add("OCC29745", "OCC29745 spreading of intervals of continuity on periodic curves",
+    __FILE__, OCC29745, group);
   theCommands.Add("OCC29195", "OCC29195 [nbRep] doc1 [doc2 [doc3 [doc4]]]", __FILE__, OCC29195, group);
   theCommands.Add("OCC30435", "OCC30435 result curve inverse nbit", __FILE__, OCC30435, group);
   theCommands.Add("OCC30747", "OCC30747: create a closed curve", __FILE__, OCC30747, group);
index c39131f747b051014421ee022d3762af12630554..1794cd0c53bf5292d97a94f510b2ef81902982c4 100755 (executable)
@@ -20,15 +20,15 @@ compound vl v1l vnl vol vil result
 
 set nbshapes_expected "
 Number of shapes in shape
- VERTEX    : 103
- EDGE      : 52
+ VERTEX    : 109
+ EDGE      : 55
  WIRE      : 0
  FACE      : 0
  SHELL     : 0
  SOLID     : 0
  COMPSOLID : 0
  COMPOUND  : 1
- SHAPE     : 156
+ SHAPE     : 165
 "
 
 checknbshapes result -ref ${nbshapes_expected} -t -m "HLRToShape"
index 0127894c0529baf58dd8d181355de6430aab3642..e8bf7ec226da60a2a188e18e424da6ff4a053370 100644 (file)
@@ -11,7 +11,7 @@ circle c 1 0 0 150
 set res1 [OCC27884 c 400 0]
 regexp {Improving time: +([-0-9.+eE]+) %} $res1 full time1
 
-if { $time1 <= 5 } {
+if { $time1 <= 4 } {
   puts "Error: algorithm slowed down"
 }
 
@@ -19,7 +19,7 @@ if { $time1 <= 5 } {
 set res2 [OCC27884 c 250 1]
 regexp {Improving time: +([-0-9.+eE]+) %} $res2 full time2
 
-if { $time2 <= 5 } {
+if { $time2 <= 3 } {
   puts "Error: algorithm slowed down"
 }
 
diff --git a/tests/bugs/moddata_3/bug29745 b/tests/bugs/moddata_3/bug29745
new file mode 100644 (file)
index 0000000..3420378
--- /dev/null
@@ -0,0 +1,37 @@
+puts "================================================================="
+puts "OCC29745: Modeling Data - GeomAdaptor_Surface::VIntervals fails on periodic surfaces"
+puts "================================================================="
+puts ""
+
+pload QAcommands
+
+restore [locate_data_file bug29745_1] bc
+restore [locate_data_file bug29745_2] bc1
+
+
+set ref1 {NbIntervals: 2; 0 0.5 1 }
+set data1 [OCC29745 bc1 1 0 1]
+   
+if  {[string compare $ref1 $data1] == 0} {
+  puts "OCC29745 OK"
+} else {      
+    puts "OCC29745 Faulty"        
+}
+
+set ref2 {NbIntervals: 3; 0.10000000000000001 0.5 1 1.1000000000000001 }
+set data2 [OCC29745 bc1 1 0.1 1.1]
+   
+if  {[string compare $ref2 $data2] == 0} {
+  puts "OCC29745 OK"
+} else {      
+    puts "OCC29745 Faulty"        
+}
+
+set ref3 {NbIntervals: 3; 0 4.1887902047863896 6.2831853071795898 7 }
+set data3 [OCC29745 bc 1 0 7]
+   
+if  {[string compare $ref3 $data3] == 0} {
+  puts "OCC29745 OK"
+} else {      
+    puts "OCC29745 Faulty"        
+}
index f3f8d3c64e88fceac6d8fecb297e380d06f01827..cd1893cef8e1560ed6958d4963184c18d0092683 100644 (file)
@@ -4,7 +4,7 @@ puts "====================================="
 puts ""
 
 set viewname ""
-set length 6.34984
+set length 6.34983
 
 restore [locate_data_file bug27341_hlrsave.brep] a
 COMPUTE_HLR $viewname $algotype
index 741d9a04e63ff1192047e029e911623d7cc4cf56..e99fad93e3edfdf070ce6c1493f72e6ec9cddd7e 100644 (file)
@@ -1,4 +1,4 @@
-puts "TODO OCC30286 ALL: Error : The length of result shape is 1736.91, expected 1704.87"
+puts "TODO OCC30286 ALL: Error : The length of result shape is 1736.86, expected 1704.87"
 
 set viewname "vright"
 set length 1704.87
index e76af23e101e91c5d8d0e7db8b5a16dd0e67b6dc..7564077b920152bd47340f1ef2e6c4a008c96c39 100644 (file)
@@ -4,7 +4,7 @@ puts "============"
 puts ""
 
 set viewname "vfront"
-set length 484.485
+set length 484.427
 
 restore [locate_data_file bug25908_hlr-bspline-clone2-tcl-h1.brep] a
 COMPUTE_HLR $viewname $algotype
index 072138288b019c2cd1dacc8d877fa103ee1e1446..d1c7497ba1c09c6344ac6b0dcc241d7966139ccd 100644 (file)
@@ -4,7 +4,7 @@ puts "============"
 puts ""
 
 set viewname "vback"
-set length 544.616
+set length 544.507
 
 restore [locate_data_file bug25908_hlr-bspline-clone2-tcl-h1.brep] a
 COMPUTE_HLR $viewname $algotype