0025024: BSplCLib::PrepareInsertKnots reports incorrect number of poles
[occt.git] / src / BSplCLib / BSplCLib.cxx
old mode 100755 (executable)
new mode 100644 (file)
index e230eb2..f41a893
@@ -1,10 +1,20 @@
-// File:       BSplCLib.cxx
-// Created:    Fri Aug  9 16:32:46 1991
-// Author:      JCV
-
+// Created on: 1991-08-09
+// Created by: JCV
+// Copyright (c) 1991-1999 Matra Datavision
+// Copyright (c) 1999-2014 OPEN CASCADE SAS
 //
-// Modified RLE 9 Sep 1993
+// This file is part of Open CASCADE Technology software library.
+//
+// This library is free software; you can redistribute it and/or modify it under
+// the terms of the GNU Lesser General Public License version 2.1 as published
+// by the Free Software Foundation, with special exception defined in the file
+// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
+// distribution for complete text of the license and disclaimer of any warranty.
 //
+// Alternatively, this file may be used under the terms of Open CASCADE
+// commercial license or contractual agreement.
+
+// Modified RLE 9 Sep 1993
 // pmn : modified 28-01-97  : fixed a mistake in LocateParameter (PRO6973)
 // pmn : modified 4-11-96   : fixed a mistake in BuildKnots (PRO6124)
 // pmn : modified 28-Jun-96 : fixed a mistake in AntiBoorScheme
 // jct : 15-Apr-97 : added TangExtendToConstraint
 // jct : 24-Apr-97 : correction on computation of Tbord and NewFlatKnots
 //                   in TangExtendToConstraint; Continuity can be equal to 0
-//
 
 #include <BSplCLib.ixx>
 #include <PLib.hxx>
-#include <PLib_LocalArray.hxx>
+#include <NCollection_LocalArray.hxx>
 #include <Precision.hxx>
 #include <Standard_NotImplemented.hxx>
 
@@ -53,8 +62,6 @@ public:
   Standard_Real myBuffer[27*27];
 };
 
-typedef PLib_LocalArray BSplCLib_LocalArray;
-
 //=======================================================================
 //function : Hunt
 //purpose  : 
@@ -635,6 +642,62 @@ BSplCLib_MultDistribution BSplCLib::MultForm
   return MForm;
 }
 
+//=======================================================================
+//function : KnotAnalysis
+//purpose  : 
+//=======================================================================
+
+void BSplCLib::KnotAnalysis (const Standard_Integer         Degree,
+                             const Standard_Boolean         Periodic,
+                             const TColStd_Array1OfReal&    CKnots,
+                             const TColStd_Array1OfInteger& CMults,
+                             GeomAbs_BSplKnotDistribution&  KnotForm,
+                             Standard_Integer&              MaxKnotMult)
+{
+  KnotForm = GeomAbs_NonUniform;
+
+  BSplCLib_KnotDistribution KSet = 
+    BSplCLib::KnotForm (CKnots, 1, CKnots.Length());
+  
+
+  if (KSet == BSplCLib_Uniform) {
+    BSplCLib_MultDistribution MSet =
+      BSplCLib::MultForm (CMults, 1, CMults.Length());
+    switch (MSet) {
+    case BSplCLib_NonConstant   :       
+      break;
+    case BSplCLib_Constant      : 
+      if (CKnots.Length() == 2) {
+        KnotForm = GeomAbs_PiecewiseBezier;
+      }
+      else {
+        if (CMults (1) == 1)  KnotForm = GeomAbs_Uniform;   
+      }
+      break;
+    case BSplCLib_QuasiConstant :   
+      if (CMults (1) == Degree + 1) {
+        Standard_Real M = CMults (2);
+        if (M == Degree )   KnotForm = GeomAbs_PiecewiseBezier;
+        else if  (M == 1)   KnotForm = GeomAbs_QuasiUniform;
+      }
+      break;
+    }
+  }
+
+  Standard_Integer FirstKM = 
+    Periodic ? CKnots.Lower() :  BSplCLib::FirstUKnotIndex (Degree,CMults);
+  Standard_Integer LastKM =
+    Periodic ? CKnots.Upper() :  BSplCLib::LastUKnotIndex (Degree,CMults);
+  MaxKnotMult = 0;
+  if (LastKM - FirstKM != 1) {
+    Standard_Integer Multi;
+    for (Standard_Integer i = FirstKM + 1; i < LastKM; i++) {
+      Multi = CMults (i);
+      MaxKnotMult = Max (MaxKnotMult, Multi);
+    }
+  }
+}
+
 //=======================================================================
 //function : Reparametrize
 //purpose  : 
@@ -1625,7 +1688,7 @@ Standard_Boolean  BSplCLib::PrepareInsertKnots
   if (adeltaK1 > Tolerance) return Standard_False;
   if (adeltaK2  > Tolerance) return Standard_False;
   
-  Standard_Integer sigma = 0, mult, amult, lastmult = 0;
+  Standard_Integer sigma = 0, mult, amult;
   NbKnots = 0;
   Standard_Integer  k  = Knots.Lower() - 1;
   Standard_Integer  ak = AddKnots.Lower();
@@ -1639,6 +1702,7 @@ Standard_Boolean  BSplCLib::PrepareInsertKnots
       ak++;
   }
   
+  Standard_Integer aLastKnotMult = Mults (Knots.Upper());
   Standard_Real au,oldau = AddKnots(ak),Eps;
   
   while (ak <= AddKnots.Upper()) {
@@ -1670,18 +1734,23 @@ Standard_Boolean  BSplCLib::PrepareInsertKnots
     if (Abs(au - Knots(k)) <= Eps) {
       // identic to existing knot
       mult = Mults(k);
-      lastmult = mult;//gka 
       if (Add) {
        if (mult + amult > Degree)
          amult = Max(0,Degree - mult);
        sigma += amult;
-        //lastmult = mult + amult;
        
       }
       else if (amult > mult) {
        if (amult > Degree) amult = Degree;
-       sigma += amult - mult;
-       //lastmult = amult;//gka modified
+        if (k == Knots.Upper () && Periodic)
+        {
+          aLastKnotMult = Max (amult, mult);
+          sigma += 2 * (aLastKnotMult - mult);
+        }
+        else
+        {
+         sigma += amult - mult;
+        }
       }
       /*
       // on periodic curves if this is the last knot
@@ -1699,7 +1768,6 @@ Standard_Boolean  BSplCLib::PrepareInsertKnots
       if (amult > 0) {
        if (amult > Degree) amult = Degree;
        NbKnots++;
-       //lastmult = amult;
        sigma += amult;
       }
     }
@@ -1708,9 +1776,6 @@ Standard_Boolean  BSplCLib::PrepareInsertKnots
   }
   
   // count the last knots
-  if (lastmult == 0)// || k < Knots.Upper())
-    lastmult = Mults(Knots.Upper());
-
   while (k < Knots.Upper()) {
     k++;
     NbKnots++;
@@ -1718,7 +1783,12 @@ Standard_Boolean  BSplCLib::PrepareInsertKnots
   }
 
   if (Periodic) {
-    NbPoles = sigma - lastmult;
+    //for periodic B-Spline the requirement is that multiplicites of the first
+    //and last knots must be equal (see Geom_BSplineCurve constructor for
+    //instance);
+    //respectively AddMults() must meet this requirement if AddKnots() contains
+    //knot(s) coincident with first or last
+    NbPoles = sigma - aLastKnotMult;
   }
   else {
     NbPoles = sigma - Degree - 1;
@@ -1907,7 +1977,8 @@ void BSplCLib::InsertKnots
       if (Periodic) {
        // on periodic curve the first and last knot are delayed to the end
        if (curk == Knots.Lower() || (curk == Knots.Upper())) {
-         firstmult += depth;
+          if (firstmult == 0) // do that only once
+            firstmult += depth;
          depth = 0;
        }
       }
@@ -3049,7 +3120,6 @@ void  BSplCLib::Eval
   NewRequest,
   ExtrapolatingFlag[2],
   ErrorCode,
-  ReturnCode,
   Order = Degree + 1,
   FirstNonZeroBsplineIndex,
   LocalRequest = DerivativeRequest ;
@@ -3119,7 +3189,6 @@ void  BSplCLib::Eval
                               FirstNonZeroBsplineIndex,
                               BsplineBasis) ;
   if (ErrorCode != 0) {
-    ReturnCode = 1 ;
     goto FINISH ;
   }
   if (ExtrapolatingFlag[0] == 0 && ExtrapolatingFlag[1] == 0) {
@@ -3158,7 +3227,7 @@ void  BSplCLib::Eval
     if (NewRequest > Degree) {
       NewRequest = Degree ;
     }
-    BSplCLib_LocalArray LocalRealArray((LocalRequest + 1)*ArrayDimension);
+    NCollection_LocalArray<Standard_Real> LocalRealArray((LocalRequest + 1)*ArrayDimension);
     Index = 0 ;
     Inverse = 1.0e0 ;
 
@@ -3250,7 +3319,6 @@ void  BSplCLib::Eval
   NewRequest,
   ExtrapolatingFlag[2],
   ErrorCode,
-  ReturnCode,
   Order = Degree + 1,
   FirstNonZeroBsplineIndex,
   LocalRequest = DerivativeRequest ;
@@ -3320,7 +3388,6 @@ void  BSplCLib::Eval
                               FirstNonZeroBsplineIndex,
                               BsplineBasis);
   if (ErrorCode != 0) {
-    ReturnCode = 1 ;
     goto FINISH ;
   }
   if (ExtrapolatingFlag[0] == 0 && ExtrapolatingFlag[1] == 0) {
@@ -3353,7 +3420,7 @@ void  BSplCLib::Eval
     if (NewRequest > Degree) {
       NewRequest = Degree ;
     }
-    BSplCLib_LocalArray LocalRealArray((LocalRequest + 1)*ArrayDimension);
+    NCollection_LocalArray<Standard_Real> LocalRealArray((LocalRequest + 1)*ArrayDimension);
 
     Index = 0 ;
     Inverse = 1.0e0 ;