0024428: Implementation of LGPL license
[occt.git] / src / Geom2d / Geom2d_BSplineCurve.cxx
1 // Created on: 1993-03-25
2 // Created by: JCV
3 // Copyright (c) 1993-1999 Matra Datavision
4 // Copyright (c) 1999-2014 OPEN CASCADE SAS
5 //
6 // This file is part of Open CASCADE Technology software library.
7 //
8 // This library is free software; you can redistribute it and / or modify it
9 // under the terms of the GNU Lesser General Public version 2.1 as published
10 // by the Free Software Foundation, with special exception defined in the file
11 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
12 // distribution for complete text of the license and disclaimer of any warranty.
13 //
14 // Alternatively, this file may be used under the terms of Open CASCADE
15 // commercial license or contractual agreement.
16
17 //Avril 1991 : constructeurs + methodes de lecture.
18 //Mai 1991   : revue des specifs + debut de realisation des classes tool =>
19 //             implementation des methodes Set et calcul du point courant.
20 //Juillet 1991 : voir egalement File Geom2d_BSplineCurve_1.cxx
21 //Juin    1992 : mise a plat des valeurs nodales - amelioration des
22 //               performances sur calcul du point courant
23
24 //RLE Aug 1993  Remove Swaps, Init methods, Remove typedefs
25 //  14-Mar-96 : xab implemented MovePointAndTangent
26
27 //SAMTECH Jan 2002 : add text to Raise()
28
29 #define No_Standard_OutOfRange
30
31 #include <Geom2d_BSplineCurve.ixx>
32 #include <gp.hxx>
33 #include <BSplCLib.hxx>
34 #include <BSplCLib_KnotDistribution.hxx>
35 #include <BSplCLib_MultDistribution.hxx>
36 #include <Standard_NotImplemented.hxx>
37 #include <Standard_ConstructionError.hxx>
38 #include <Standard_OutOfRange.hxx>
39
40 //=======================================================================
41 //function : CheckCurveData
42 //purpose  : Internal use only
43 //=======================================================================
44
45 static void CheckCurveData
46 (const TColgp_Array1OfPnt2d&         CPoles,
47  const TColStd_Array1OfReal&       CKnots,
48  const TColStd_Array1OfInteger&    CMults,
49  const Standard_Integer            Degree,
50  const Standard_Boolean            Periodic)
51 {
52   if (Degree < 1 || Degree > Geom2d_BSplineCurve::MaxDegree()) {
53     Standard_ConstructionError::Raise("BSpline curve : invalid degree");  
54   }
55   
56   if (CPoles.Length() < 2)                Standard_ConstructionError::Raise("BSpline curve : at least 2 poles required");
57   if (CKnots.Length() != CMults.Length()) Standard_ConstructionError::Raise("BSpline curve : Knot and Mult array size mismatch");
58   
59   for (Standard_Integer I = CKnots.Lower(); I < CKnots.Upper(); I++) {
60     if (CKnots (I+1) - CKnots (I) <= Epsilon (Abs(CKnots (I)))) {
61       Standard_ConstructionError::Raise("BSpline curve : Knots interval values too close");
62     }
63   }
64   
65   if (CPoles.Length() != BSplCLib::NbPoles(Degree,Periodic,CMults))
66     Standard_ConstructionError::Raise("BSpline curve : # Poles and degree mismatch");
67 }
68
69 //=======================================================================
70 //function : Rational
71 //purpose  : check rationality of an array of weights
72 //=======================================================================
73
74 static Standard_Boolean Rational(const TColStd_Array1OfReal& W)
75 {
76   Standard_Integer i, n = W.Length();
77   Standard_Boolean rat = Standard_False;
78   for (i = 1; i < n; i++) {
79     rat =  Abs(W(i) - W(i+1)) > gp::Resolution();
80     if (rat) break;
81   }
82   return rat;
83 }
84
85 //=======================================================================
86 //function : Copy
87 //purpose  : 
88 //=======================================================================
89
90 Handle(Geom2d_Geometry) Geom2d_BSplineCurve::Copy() const
91 {
92   Handle(Geom2d_BSplineCurve) C;
93   if (IsRational()) 
94     C = new Geom2d_BSplineCurve(poles->Array1(),
95                                 weights->Array1(),
96                                 knots->Array1(),
97                                 mults->Array1(),
98                                 deg,periodic);
99   else
100     C = new Geom2d_BSplineCurve(poles->Array1(),
101                                 knots->Array1(),
102                                 mults->Array1(),
103                                 deg,periodic);
104   return C;
105 }
106
107 //=======================================================================
108 //function : Geom2d_BSplineCurve
109 //purpose  : 
110 //=======================================================================
111
112 Geom2d_BSplineCurve::Geom2d_BSplineCurve
113 (const TColgp_Array1OfPnt2d&     Poles,
114  const TColStd_Array1OfReal&     Knots,
115  const TColStd_Array1OfInteger&  Mults,
116  const Standard_Integer          Degree,
117  const Standard_Boolean          Periodic) :
118  rational(Standard_False),
119  periodic(Periodic),
120  deg(Degree),
121  maxderivinvok(Standard_False)
122 {
123   // check
124   
125   CheckCurveData (Poles,
126                   Knots,
127                   Mults,
128                   Degree,
129                   Periodic);
130
131
132   // copy arrays
133
134   poles =  new TColgp_HArray1OfPnt2d(1,Poles.Length());
135   poles->ChangeArray1() = Poles;
136
137   knots = new TColStd_HArray1OfReal(1,Knots.Length());
138   knots->ChangeArray1() = Knots;
139
140   mults = new TColStd_HArray1OfInteger(1,Mults.Length());
141   mults->ChangeArray1() = Mults;
142
143   UpdateKnots();
144   cachepoles = new TColgp_HArray1OfPnt2d(1,Degree + 1);
145   parametercache = 0.0e0 ;
146   spanlenghtcache = 0.0e0 ;
147   spanindexcache = 0 ;
148 }
149
150 //=======================================================================
151 //function : Geom2d_BSplineCurve
152 //purpose  : 
153 //=======================================================================
154
155 Geom2d_BSplineCurve::Geom2d_BSplineCurve
156 (const TColgp_Array1OfPnt2d&      Poles,
157  const TColStd_Array1OfReal&    Weights,
158  const TColStd_Array1OfReal&    Knots,
159  const TColStd_Array1OfInteger& Mults,
160  const Standard_Integer         Degree,
161  const Standard_Boolean         Periodic)  :
162  rational(Standard_True),
163  periodic(Periodic),
164  deg(Degree),
165  maxderivinvok(Standard_False)
166
167 {
168
169   // check
170   
171   CheckCurveData (Poles,
172                   Knots,
173                   Mults,
174                   Degree,
175                   Periodic);
176
177   if (Weights.Length() != Poles.Length())
178     Standard_ConstructionError::Raise("Geom2d_BSplineCurve :Weights and Poles array size mismatch");
179
180   Standard_Integer i;
181   for (i = Weights.Lower(); i <= Weights.Upper(); i++) {
182     if (Weights(i) <= gp::Resolution()) {
183       Standard_ConstructionError::Raise("Geom2d_BSplineCurve: Weights values too small");
184     }
185   }
186   
187   // check really rational
188   rational = Rational(Weights);
189   
190   // copy arrays
191   
192   poles =  new TColgp_HArray1OfPnt2d(1,Poles.Length());
193   poles->ChangeArray1() = Poles;
194   cachepoles = new TColgp_HArray1OfPnt2d(1,Degree + 1);
195   if (rational) {
196     weights =  new TColStd_HArray1OfReal(1,Weights.Length());
197     weights->ChangeArray1() = Weights;
198     cacheweights  = new TColStd_HArray1OfReal(1,Degree + 1);
199   }
200
201   knots = new TColStd_HArray1OfReal(1,Knots.Length());
202   knots->ChangeArray1() = Knots;
203
204   mults = new TColStd_HArray1OfInteger(1,Mults.Length());
205   mults->ChangeArray1() = Mults;
206
207   UpdateKnots();
208
209   parametercache = 0.0e0 ;
210   spanlenghtcache = 0.0e0 ;
211   spanindexcache = 0 ;
212 }
213
214 //=======================================================================
215 //function : MaxDegree
216 //purpose  : 
217 //=======================================================================
218
219 Standard_Integer Geom2d_BSplineCurve::MaxDegree () 
220
221   return BSplCLib::MaxDegree(); 
222 }
223
224 //=======================================================================
225 //function : IncreaseDegree
226 //purpose  : 
227 //=======================================================================
228
229 void Geom2d_BSplineCurve::IncreaseDegree
230 (const Standard_Integer Degree)
231 {
232   if (Degree == deg) return;
233
234   if (Degree < deg || Degree > Geom2d_BSplineCurve::MaxDegree()) {
235     Standard_ConstructionError::Raise("BSpline curve : IncreaseDegree : bad degree value");
236   }
237
238   Standard_Integer FromK1 = FirstUKnotIndex ();
239   Standard_Integer ToK2   = LastUKnotIndex  ();
240   
241   Standard_Integer Step   = Degree - deg;
242   
243   Handle(TColgp_HArray1OfPnt2d) npoles = new
244     TColgp_HArray1OfPnt2d(1,poles->Length() + Step * (ToK2-FromK1));
245
246   Standard_Integer nbknots = BSplCLib::IncreaseDegreeCountKnots
247     (deg,Degree,periodic,mults->Array1());
248
249   Handle(TColStd_HArray1OfReal) nknots = 
250     new TColStd_HArray1OfReal(1,nbknots);
251
252   Handle(TColStd_HArray1OfInteger) nmults = 
253     new TColStd_HArray1OfInteger(1,nbknots);
254   
255   Handle(TColStd_HArray1OfReal) nweights;
256   
257   if (IsRational()) {
258     
259     nweights = new TColStd_HArray1OfReal(1,npoles->Upper());
260     
261     BSplCLib::IncreaseDegree
262       (deg,Degree, periodic,
263        poles->Array1(),weights->Array1(),
264        knots->Array1(),mults->Array1(),
265        npoles->ChangeArray1(),nweights->ChangeArray1(),
266        nknots->ChangeArray1(),nmults->ChangeArray1());
267   }
268   else {
269
270     BSplCLib::IncreaseDegree
271       (deg,Degree, periodic,
272        poles->Array1(),
273        *((TColStd_Array1OfReal*) NULL),
274        knots->Array1(),mults->Array1(),
275        npoles->ChangeArray1(),
276        *((TColStd_Array1OfReal*) NULL),
277        nknots->ChangeArray1(),nmults->ChangeArray1());
278   }
279
280   deg     = Degree;
281   poles   = npoles;
282   weights = nweights;
283   knots   = nknots;
284   mults   = nmults;
285   UpdateKnots();
286 }
287
288 //=======================================================================
289 //function : IncreaseMultiplicity
290 //purpose  : 
291 //=======================================================================
292
293 void Geom2d_BSplineCurve::IncreaseMultiplicity
294 (const Standard_Integer Index,
295  const Standard_Integer M)
296 {
297   TColStd_Array1OfReal k(1,1);
298   k(1) = knots->Value(Index);
299   TColStd_Array1OfInteger m(1,1);
300   m(1) = M - mults->Value(Index);
301   InsertKnots(k,m,Epsilon(1.),Standard_True);
302 }
303
304 //=======================================================================
305 //function : IncreaseMultiplicity
306 //purpose  : 
307 //=======================================================================
308
309 void Geom2d_BSplineCurve::IncreaseMultiplicity
310 (const Standard_Integer I1,
311  const Standard_Integer I2,
312  const Standard_Integer M)
313 {
314   Handle(TColStd_HArray1OfReal) tk = knots;
315   TColStd_Array1OfReal k((knots->Array1())(I1),I1,I2);
316   TColStd_Array1OfInteger m(I1,I2);
317   Standard_Integer i;
318   for (i = I1; i <= I2; i++)
319     m(i) = M - mults->Value(i);
320   InsertKnots(k,m,Epsilon(1.),Standard_True);
321 }
322
323 //=======================================================================
324 //function : IncrementMultiplicity
325 //purpose  : 
326 //=======================================================================
327
328 void Geom2d_BSplineCurve::IncrementMultiplicity
329 (const Standard_Integer I1,
330  const Standard_Integer I2,
331  const Standard_Integer Step)
332 {
333   Handle(TColStd_HArray1OfReal) tk = knots;
334   TColStd_Array1OfReal    k((knots->Array1())(I1),I1,I2);
335   TColStd_Array1OfInteger m(I1,I2);
336   m.Init(Step);
337   InsertKnots(k,m,Epsilon(1.),Standard_True);
338 }
339
340 //=======================================================================
341 //function : InsertKnot
342 //purpose  : 
343 //=======================================================================
344
345 void Geom2d_BSplineCurve::InsertKnot
346 (const Standard_Real U, 
347  const Standard_Integer M, 
348  const Standard_Real ParametricTolerance)
349 {
350   TColStd_Array1OfReal k(1,1);
351   k(1) = U;
352   TColStd_Array1OfInteger m(1,1);
353   m(1) = M;
354   InsertKnots(k,m,ParametricTolerance);
355 }
356
357 //=======================================================================
358 //function : InsertKnots
359 //purpose  : 
360 //=======================================================================
361 void  Geom2d_BSplineCurve::InsertKnots(const TColStd_Array1OfReal& Knots, 
362                                        const TColStd_Array1OfInteger& Mults,
363                                        const Standard_Real Epsilon,
364                                        const Standard_Boolean Add)
365 {
366   // Check and compute new sizes
367   Standard_Integer nbpoles,nbknots;
368
369   if (!BSplCLib::PrepareInsertKnots(deg,periodic,
370                                     knots->Array1(),mults->Array1(),
371                                     Knots,Mults,nbpoles,nbknots,Epsilon,Add))
372     Standard_ConstructionError::Raise("Geom2d_BSplineCurve::InsertKnots");
373
374   if (nbpoles == poles->Length()) return;
375
376   Handle(TColgp_HArray1OfPnt2d)      npoles = new TColgp_HArray1OfPnt2d(1,nbpoles);
377   Handle(TColStd_HArray1OfReal)    nknots = knots;
378   Handle(TColStd_HArray1OfInteger) nmults = mults;
379
380   if (nbknots != knots->Length()) {
381     nknots  = new TColStd_HArray1OfReal(1,nbknots);
382     nmults = new TColStd_HArray1OfInteger(1,nbknots);
383   }
384
385   if (rational) {
386     Handle(TColStd_HArray1OfReal) nweights = 
387       new TColStd_HArray1OfReal(1,nbpoles);
388     BSplCLib::InsertKnots(deg,periodic,
389                           poles->Array1(), weights->Array1(),
390                           knots->Array1(), mults->Array1(),
391                           Knots, Mults,
392                           npoles->ChangeArray1(), nweights->ChangeArray1(),
393                           nknots->ChangeArray1(), nmults->ChangeArray1(),
394                           Epsilon,Add);
395     weights = nweights;
396   }
397   else {
398     BSplCLib::InsertKnots(deg,periodic,
399                           poles->Array1(),
400                           *((TColStd_Array1OfReal*) NULL),
401                           knots->Array1(), mults->Array1(),
402                           Knots, Mults,
403                           npoles->ChangeArray1(),
404                           *((TColStd_Array1OfReal*) NULL),
405                           nknots->ChangeArray1(), nmults->ChangeArray1(),
406                           Epsilon,Add);
407   }
408
409   poles = npoles;
410   knots = nknots;
411   mults = nmults;
412   UpdateKnots();
413
414 }
415
416 //=======================================================================
417 //function : RemoveKnot
418 //purpose  : 
419 //=======================================================================
420
421 Standard_Boolean  Geom2d_BSplineCurve::RemoveKnot
422 (const Standard_Integer Index,
423  const Standard_Integer M, 
424  const Standard_Real Tolerance)
425 {
426   if (M < 0) return Standard_True;
427
428   Standard_Integer I1  = FirstUKnotIndex ();
429   Standard_Integer I2  = LastUKnotIndex  ();
430
431   if (Index < I1 || Index > I2)  {
432     Standard_OutOfRange::Raise("BSpline curve : RemoveKnot : index out of range");
433   }
434   
435   const TColgp_Array1OfPnt2d & oldpoles   = poles->Array1();
436   
437   Standard_Integer step = mults->Value(Index) - M;
438   if (step <= 0) return Standard_True;
439   
440   Handle(TColgp_HArray1OfPnt2d) npoles =
441     new TColgp_HArray1OfPnt2d(1,oldpoles.Length()-step);
442   
443   Handle(TColStd_HArray1OfReal)    nknots  = knots;
444   Handle(TColStd_HArray1OfInteger) nmults  = mults;
445   
446   if (M == 0) {
447     nknots = new TColStd_HArray1OfReal(1,knots->Length()-1);
448     nmults = new TColStd_HArray1OfInteger(1,knots->Length()-1);
449   }
450   
451   if (IsRational()) {
452     Handle(TColStd_HArray1OfReal) nweights = 
453       new TColStd_HArray1OfReal(1,npoles->Length());
454     if (!BSplCLib::RemoveKnot
455         (Index, M, deg, periodic,
456          poles->Array1(),weights->Array1(), 
457          knots->Array1(),mults->Array1(),
458          npoles->ChangeArray1(), nweights->ChangeArray1(),
459          nknots->ChangeArray1(),nmults->ChangeArray1(),
460          Tolerance))
461       return Standard_False;
462     weights = nweights;
463   }
464   else {
465     if (!BSplCLib::RemoveKnot
466         (Index, M, deg, periodic,
467          poles->Array1(),
468          *((TColStd_Array1OfReal*) NULL),
469          knots->Array1(),mults->Array1(),
470          npoles->ChangeArray1(),
471          *((TColStd_Array1OfReal*) NULL),
472          nknots->ChangeArray1(),nmults->ChangeArray1(),
473          Tolerance))
474       return Standard_False;
475   }
476   
477   poles = npoles;
478   knots = nknots;
479   mults = nmults;
480   
481   UpdateKnots();
482   maxderivinvok = 0;
483   return Standard_True;
484 }
485
486 //=======================================================================
487 //function : InsertPoleAfter
488 //purpose  : 
489 //=======================================================================
490
491 void Geom2d_BSplineCurve::InsertPoleAfter
492 (const Standard_Integer Index,
493  const gp_Pnt2d& P,
494  const Standard_Real Weight)
495 {
496   if (Index < 0 || Index > poles->Length())  Standard_OutOfRange::Raise("BSpline curve : InsertPoleAfter: Index and #pole mismatch");
497
498   if (Weight <= gp::Resolution())     Standard_ConstructionError::Raise("BSpline curve : InsertPoleAfter: Weight too small");
499
500   if (knotSet == GeomAbs_NonUniform || knotSet == GeomAbs_PiecewiseBezier) {
501     Standard_ConstructionError::Raise("BSpline curve : InsertPoleAfter : bad knotSet type");
502   }
503
504   const TColStd_Array1OfReal& cknots   = knots->Array1();
505   Standard_Integer nbknots = cknots.Length();
506
507   Handle(TColStd_HArray1OfReal) nknots =  
508     new TColStd_HArray1OfReal(1,nbknots+1);
509
510   TColStd_Array1OfReal& newknots = nknots->ChangeArray1();
511
512   Standard_Integer i;
513   for (i = 1; i < nbknots; i++) {
514     newknots (i) = cknots(i);
515   }
516   
517   newknots (nbknots+1) = 2 * newknots (nbknots) - newknots(nbknots-1);
518   
519   Handle(TColStd_HArray1OfInteger) nmults =
520     new TColStd_HArray1OfInteger(1,nbknots+1);
521
522   TColStd_Array1OfInteger& newmults     = nmults->ChangeArray1();
523   const TColStd_Array1OfInteger& cmults = mults->Array1();
524
525   for (i = 2; i <= nbknots; i++) newmults (i) = 1;
526   newmults (1)         =  cmults(1);
527   newmults (nbknots+1) =  cmults(nbknots+1);
528   
529   const TColgp_Array1OfPnt2d& cpoles = poles->Array1();
530   Standard_Integer nbpoles = cpoles.Length();
531   Handle(TColgp_HArray1OfPnt2d) npoles = 
532     new TColgp_HArray1OfPnt2d(1, nbpoles+1);
533   TColgp_Array1OfPnt2d& newpoles = npoles->ChangeArray1();
534
535   // insert the pole
536
537   for (i = 1; i <= Index; i++)
538     newpoles(i) = cpoles(i);
539
540   newpoles(Index+1) = P;
541
542   for (i = Index+1; i <= nbpoles; i++)
543     newpoles(i+1) = cpoles(i);
544
545   // Insert the weight
546
547   Handle(TColStd_HArray1OfReal) nweights;
548   Standard_Boolean rat = IsRational() || Abs(Weight-1.) > gp::Resolution();
549   
550   if (rat) {
551     nweights = new TColStd_HArray1OfReal(1,nbpoles+1);
552     TColStd_Array1OfReal& newweights = nweights->ChangeArray1();
553
554     for (i = 1; i <= Index; i++)
555       if (IsRational())
556         newweights(i) = weights->Value(i);
557       else
558         newweights(i) = 1.;
559     
560     newweights(Index+1) = Weight;
561
562     for (i = Index+1; i <= nbpoles; i++)
563       if (IsRational())
564         newweights(i+1) = weights->Value(i);
565       else
566         newweights(i+1) = 1.;
567   }
568   
569   poles   = npoles;
570   weights = nweights;
571   knots   = nknots;
572   mults   = nmults;
573   maxderivinvok = 0;
574   UpdateKnots();
575 }
576
577 //=======================================================================
578 //function : InsertPoleBefore
579 //purpose  : 
580 //=======================================================================
581
582 void Geom2d_BSplineCurve::InsertPoleBefore
583 (const Standard_Integer Index,
584  const gp_Pnt2d& P,
585  const Standard_Real Weight)
586 {
587   InsertPoleAfter(Index-1,P,Weight);
588 }
589
590 //=======================================================================
591 //function : RemovePole
592 //purpose  : 
593 //=======================================================================
594
595 void Geom2d_BSplineCurve::RemovePole
596 (const Standard_Integer Index)
597 {
598   if (Index < 1 || Index > poles->Length())  Standard_OutOfRange::Raise("BSpline curve :RemovePole : Index and #pole mismatch");
599
600   if (poles->Length() <= 2)           Standard_ConstructionError::Raise("BSpline curve : RemovePole : #pole is already minimum");
601
602   if (knotSet == GeomAbs_NonUniform || knotSet == GeomAbs_PiecewiseBezier) 
603     Standard_ConstructionError::Raise("BSpline curve : RemovePole: bad knotSet type");
604
605   Standard_Integer i;
606   Handle(TColStd_HArray1OfReal) nknots =
607     new TColStd_HArray1OfReal(1,knots->Length()-1);
608   TColStd_Array1OfReal& newknots = nknots->ChangeArray1();
609
610   Handle(TColStd_HArray1OfInteger) nmults =
611     new TColStd_HArray1OfInteger(1,mults->Length()-1);
612   TColStd_Array1OfInteger& newmults = nmults->ChangeArray1();
613
614   for (i = 1; i < newknots.Length(); i++) {
615     newknots (i) = knots->Value (i);
616     newmults (i) = 1;
617   }
618   newmults(1) = mults->Value(1);
619   newknots(newknots.Upper()) = knots->Value (knots->Upper());
620   newmults(newmults.Upper()) = mults->Value (mults->Upper());
621
622
623   Handle(TColgp_HArray1OfPnt2d) npoles =
624     new TColgp_HArray1OfPnt2d(1, poles->Upper()-1);
625   TColgp_Array1OfPnt2d& newpoles = npoles->ChangeArray1();
626
627   for (i = 1; i < Index; i++)
628     newpoles(i) = poles->Value(i);
629   for (i = Index; i < newpoles.Length(); i++)
630     newpoles(i) = poles->Value(i+1);
631
632   Handle(TColStd_HArray1OfReal) nweights;
633   if (IsRational()) {
634     nweights = new TColStd_HArray1OfReal(1,newpoles.Length());
635     TColStd_Array1OfReal& newweights = nweights->ChangeArray1();
636     for (i = 1; i < Index; i++)
637       newweights(i) = weights->Value(i);
638     for (i = Index; i < newweights.Length(); i++)
639       newweights(i) = weights->Value(i+1);
640   }
641
642   poles   = npoles;
643   weights = nweights;
644   knots   = nknots;
645   mults   = nmults;
646   UpdateKnots();
647 }
648
649 //=======================================================================
650 //function : Reverse
651 //purpose  : 
652 //=======================================================================
653
654 void Geom2d_BSplineCurve::Reverse ()
655
656   BSplCLib::Reverse(knots->ChangeArray1());
657   BSplCLib::Reverse(mults->ChangeArray1());
658   Standard_Integer last;
659   if (periodic)
660     last = flatknots->Upper() - deg - 1;
661   else
662     last = poles->Upper();
663   BSplCLib::Reverse(poles->ChangeArray1(),last);
664   if (rational)
665     BSplCLib::Reverse(weights->ChangeArray1(),last);
666   UpdateKnots();
667 }
668
669 //=======================================================================
670 //function : ReversedParameter
671 //purpose  : 
672 //=======================================================================
673
674 Standard_Real Geom2d_BSplineCurve::ReversedParameter( const Standard_Real U) const
675 {
676   return (FirstParameter() + LastParameter() - U);
677 }
678
679 //=======================================================================
680 //function : Segment
681 //purpose  : 
682 //=======================================================================
683 void Geom2d_BSplineCurve::Segment(const Standard_Real aU1,
684                                   const Standard_Real aU2)
685 {
686   Standard_DomainError_Raise_if ( aU2 < aU1, "Geom2d_BSplineCurve::Segment");
687   //
688   Standard_Real AbsUMax = Max(Abs(FirstParameter()),Abs(LastParameter()));
689   Standard_Real Eps = Epsilon(AbsUMax);
690   Standard_Real NewU1, NewU2;
691   Standard_Real U, DU=0;
692   Standard_Integer i, k, index;
693   //
694   //f
695   // Checking the input bounds aUj (j=1,2). 
696   // For the case when aUj==knot(i), 
697   // in order to prevent the insertion of a new knot that will be too closed 
698   // to the existing knot,  
699   // we assign Uj=knot(i)
700   Standard_Integer n1, n2;
701   Standard_Real U1, U2;
702   //
703   U1=aU1;
704   U2=aU2;
705   n1=knots->Lower();
706   n2=knots->Upper();
707   for (i=n1; i<=n2; ++i) {
708     U=knots->Value(i);
709     if (Abs(U-aU1)<=Eps) {
710       U1=U;
711     }
712     else if (Abs(U-aU2)<=Eps) {
713       U2=U;
714     }
715   }
716   // Henceforward we use U1, U2 as bounds of the segment
717   //t
718   // 
719   TColStd_Array1OfReal    Knots(1,2);
720   TColStd_Array1OfInteger Mults(1,2);
721   //
722   // define param ditance to keep (eap, Apr 18 2002, occ311)
723   if (periodic) {
724     Standard_Real Period = LastParameter() - FirstParameter();
725     DU = U2 - U1;
726     while (DU > Period) {
727       DU -= Period;
728     }
729     if (DU <= Epsilon(Period)) {
730       DU = Period;
731     }
732   }
733   //
734   index = 0;
735   BSplCLib::LocateParameter(deg,knots->Array1(),mults->Array1(),
736                             U1,periodic,knots->Lower(),knots->Upper(),
737                             index,NewU1);
738   index = 0;
739   BSplCLib::LocateParameter(deg,knots->Array1(),mults->Array1(),
740                             U2,periodic,knots->Lower(),knots->Upper(),
741                             index,NewU2);
742   Knots(1) = Min( NewU1, NewU2);
743   Knots(2) = Max( NewU1, NewU2);
744   Mults(1) = Mults( 2) = deg;
745   InsertKnots(Knots, Mults, Eps);
746   
747   if (periodic) { // set the origine at NewU1
748     index = 0;
749     BSplCLib::LocateParameter(deg,knots->Array1(),mults->Array1(),
750                               U1,periodic,knots->Lower(),knots->Upper(),
751                               index,U);
752     // Eps = Epsilon(knots->Value(index+1));
753     if ( Abs(knots->Value(index+1)-U) <= Eps) {
754       index++;
755     }
756     SetOrigin(index);
757     SetNotPeriodic();
758     NewU2 = NewU1 + DU;
759   }
760
761   // compute index1 and index2 to set the new knots and mults 
762   Standard_Integer index1 = 0, index2 = 0;
763   Standard_Integer FromU1 = knots->Lower();
764   Standard_Integer ToU2   = knots->Upper();
765   BSplCLib::LocateParameter(deg,knots->Array1(),mults->Array1(),
766                             NewU1,periodic,FromU1,ToU2,index1,U);
767   BSplCLib::LocateParameter(deg,knots->Array1(),mults->Array1(),
768                             NewU2,periodic,FromU1,ToU2,index2,U);
769   // Eps = Epsilon(knots->Value(index2+1));
770   if ( Abs(knots->Value(index2+1)-U) <= Eps){
771     index2++;
772   }
773   
774   Standard_Integer nbknots = index2 - index1 + 1;
775
776   Handle(TColStd_HArray1OfReal) 
777     nknots = new TColStd_HArray1OfReal(1,nbknots);
778   Handle(TColStd_HArray1OfInteger) 
779     nmults = new TColStd_HArray1OfInteger(1,nbknots);
780
781   // to restore changed U1
782   if (DU > 0) {// if was periodic
783     DU = NewU1 - U1;
784   }
785   //
786   k = 1;
787   //
788   for ( i = index1; i<= index2; i++) {
789     nknots->SetValue(k, knots->Value(i) - DU);
790     nmults->SetValue(k, mults->Value(i));
791     k++;
792   }
793   nmults->SetValue(      1, deg + 1);
794   nmults->SetValue(nbknots, deg + 1);
795
796
797   // compute index1 and index2 to set the new poles and weights
798   Standard_Integer pindex1 
799     = BSplCLib::PoleIndex(deg,index1,periodic,mults->Array1());
800   Standard_Integer pindex2 
801     = BSplCLib::PoleIndex(deg,index2,periodic,mults->Array1());
802
803   pindex1++;
804   pindex2 = Min( pindex2+1, poles->Length());
805
806   Standard_Integer nbpoles  = pindex2 - pindex1 + 1;
807
808   Handle(TColStd_HArray1OfReal) 
809     nweights = new TColStd_HArray1OfReal(1,nbpoles);
810   Handle(TColgp_HArray1OfPnt2d)
811     npoles = new TColgp_HArray1OfPnt2d(1,nbpoles);
812
813   k = 1;
814   if ( rational) {
815     nweights = new TColStd_HArray1OfReal( 1, nbpoles);
816     for ( i = pindex1; i <= pindex2; i++) {
817       npoles->SetValue(k, poles->Value(i));
818       nweights->SetValue(k, weights->Value(i));
819       k++;
820     }
821   }
822   else {
823     for ( i = pindex1; i <= pindex2; i++) {
824       npoles->SetValue(k, poles->Value(i));
825       k++;
826     }
827   }
828
829   knots = nknots;
830   mults = nmults;
831   poles = npoles;
832   if (rational){ 
833     weights = nweights;
834   }
835   UpdateKnots();
836 }
837
838 //=======================================================================
839 //function : SetKnot
840 //purpose  : 
841 //=======================================================================
842
843 void Geom2d_BSplineCurve::SetKnot
844 (const Standard_Integer Index,
845  const Standard_Real K)
846 {
847   if (Index < 1 || Index > knots->Length())     Standard_OutOfRange::Raise("BSpline curve : SetKnot:  Index and #pole mismatch");
848   Standard_Real DK = Abs(Epsilon (K));
849   if (Index == 1) { 
850     if (K >= knots->Value(2) - DK) Standard_ConstructionError::Raise("BSpline curve :SetKnot :K out of range");
851   }
852   else if (Index == knots->Length()) {
853     if (K <= knots->Value (knots->Length()-1) + DK)  {
854       Standard_ConstructionError::Raise("BSpline curve : SetKnot : K out of range");
855     }
856   }
857   else {
858     if (K <= knots->Value(Index-1) + DK ||
859         K >= knots->Value(Index+1) - DK ) {
860       Standard_ConstructionError::Raise("BSpline curve : SetKnot: K out of range");
861     }
862   }
863   if (K != knots->Value (Index)) {
864     knots->SetValue (Index, K);
865     maxderivinvok = 0;
866     UpdateKnots();
867   }
868 }
869
870 //=======================================================================
871 //function : SetKnots
872 //purpose  : 
873 //=======================================================================
874
875 void Geom2d_BSplineCurve::SetKnots
876 (const TColStd_Array1OfReal& K)
877 {
878   CheckCurveData(poles->Array1(),K,mults->Array1(),deg,periodic);
879   knots->ChangeArray1() = K;
880   maxderivinvok = 0;
881   UpdateKnots();
882 }
883
884 //=======================================================================
885 //function : SetKnot
886 //purpose  : 
887 //=======================================================================
888
889 void Geom2d_BSplineCurve::SetKnot
890 (const Standard_Integer Index,
891  const Standard_Real K,
892  const Standard_Integer M)
893 {
894   IncreaseMultiplicity (Index, M);
895   SetKnot (Index, K);
896 }
897
898 //=======================================================================
899 //function : SetPeriodic
900 //purpose  : 
901 //=======================================================================
902
903 void Geom2d_BSplineCurve::SetPeriodic ()
904 {
905   Standard_Integer first = FirstUKnotIndex();
906   Standard_Integer last  = LastUKnotIndex();
907
908   Handle(TColStd_HArray1OfReal) tk = knots;
909   TColStd_Array1OfReal    cknots((knots->Array1())(first),first,last);
910   knots = new TColStd_HArray1OfReal(1,cknots.Length());
911   knots->ChangeArray1() = cknots;
912
913   Handle(TColStd_HArray1OfInteger) tm = mults;
914   TColStd_Array1OfInteger cmults((mults->Array1())(first),first,last);
915   cmults(first) = cmults(last) = Min(deg, Max( cmults(first), cmults(last)));
916   mults = new TColStd_HArray1OfInteger(1,cmults.Length());
917   mults->ChangeArray1() = cmults;
918
919   // compute new number of poles;
920   Standard_Integer nbp = BSplCLib::NbPoles(deg,Standard_True,cmults);
921   
922   Handle(TColgp_HArray1OfPnt2d) tp = poles;
923   TColgp_Array1OfPnt2d cpoles((poles->Array1())(1),1,nbp);
924   poles = new TColgp_HArray1OfPnt2d(1,nbp);
925   poles->ChangeArray1() = cpoles;
926   
927   if (rational) {
928     Handle(TColStd_HArray1OfReal) tw = weights;
929     TColStd_Array1OfReal cweights((weights->Array1())(1),1,nbp);
930     weights = new TColStd_HArray1OfReal(1,nbp);
931     weights->ChangeArray1() = cweights;
932   }
933
934   periodic = Standard_True;
935   
936   maxderivinvok = 0;
937   UpdateKnots();
938 }
939
940 //=======================================================================
941 //function : SetOrigin
942 //purpose  : 
943 //=======================================================================
944
945 void Geom2d_BSplineCurve::SetOrigin(const Standard_Integer Index)
946 {
947   Standard_NoSuchObject_Raise_if( !periodic,
948                                  "Geom2d_BSplineCurve::SetOrigin");
949   Standard_Integer i,k;
950   Standard_Integer first = FirstUKnotIndex();
951   Standard_Integer last  = LastUKnotIndex();
952
953   Standard_DomainError_Raise_if( (Index < first) || (Index > last),
954                                 "Geom2d_BSplineCurve::SetOrigine");
955
956   Standard_Integer nbknots = knots->Length();
957   Standard_Integer nbpoles = poles->Length();
958
959   Handle(TColStd_HArray1OfReal) nknots = 
960     new TColStd_HArray1OfReal(1,nbknots);
961   TColStd_Array1OfReal& newknots = nknots->ChangeArray1();
962
963   Handle(TColStd_HArray1OfInteger) nmults =
964     new TColStd_HArray1OfInteger(1,nbknots);
965   TColStd_Array1OfInteger& newmults = nmults->ChangeArray1();
966
967   // set the knots and mults
968   Standard_Real period = knots->Value(last) - knots->Value(first);
969   k = 1;
970   for ( i = Index; i <= last ; i++) {
971     newknots(k) = knots->Value(i);
972     newmults(k) = mults->Value(i);
973     k++;
974   }
975   for ( i = first+1; i <= Index; i++) {
976     newknots(k) = knots->Value(i) + period;
977     newmults(k) = mults->Value(i);
978     k++;
979   }
980
981   Standard_Integer index = 1;
982   for (i = first+1; i <= Index; i++) 
983     index += mults->Value(i);
984
985   // set the poles and weights
986   Handle(TColgp_HArray1OfPnt2d) npoles =
987     new TColgp_HArray1OfPnt2d(1,nbpoles);
988   Handle(TColStd_HArray1OfReal) nweights =
989     new TColStd_HArray1OfReal(1,nbpoles);
990   TColgp_Array1OfPnt2d & newpoles   = npoles->ChangeArray1();
991   TColStd_Array1OfReal & newweights = nweights->ChangeArray1();
992   first = poles->Lower();
993   last  = poles->Upper();
994   if ( rational) {
995     k = 1;
996     for ( i = index; i <= last; i++) {
997       newpoles(k)   = poles->Value(i);
998       newweights(k) = weights->Value(i);
999       k++;
1000     }
1001     for ( i = first; i < index; i++) {
1002       newpoles(k)   = poles->Value(i);
1003       newweights(k) = weights->Value(i);
1004       k++;
1005     }
1006   }
1007   else {
1008     k = 1;
1009     for ( i = index; i <= last; i++) {
1010       newpoles(k) = poles->Value(i);
1011       k++;
1012     }
1013     for ( i = first; i < index; i++) {
1014       newpoles(k) = poles->Value(i);
1015       k++;
1016     }
1017   }
1018
1019   poles = npoles;
1020   knots = nknots;
1021   mults = nmults;
1022   if (rational) 
1023     weights = nweights;
1024   maxderivinvok = 0;
1025   UpdateKnots();
1026 }
1027
1028 //=======================================================================
1029 //function : SetNotPeriodic
1030 //purpose  : 
1031 //=======================================================================
1032
1033 void Geom2d_BSplineCurve::SetNotPeriodic () 
1034
1035   if (periodic) {
1036     Standard_Integer NbKnots, NbPoles;
1037     BSplCLib::PrepareUnperiodize( deg, mults->Array1(),NbKnots,NbPoles);
1038     
1039     Handle(TColgp_HArray1OfPnt2d) npoles 
1040       = new TColgp_HArray1OfPnt2d(1,NbPoles);
1041     
1042     Handle(TColStd_HArray1OfReal) nknots 
1043       = new TColStd_HArray1OfReal(1,NbKnots);
1044     
1045     Handle(TColStd_HArray1OfInteger) nmults
1046       = new TColStd_HArray1OfInteger(1,NbKnots);
1047     
1048     Handle(TColStd_HArray1OfReal) nweights;
1049     
1050     if (IsRational()) {
1051       
1052       nweights = new TColStd_HArray1OfReal(1,NbPoles);
1053       
1054       BSplCLib::Unperiodize
1055         (deg,mults->Array1(),knots->Array1(),poles->Array1(),
1056          weights->Array1(),nmults->ChangeArray1(),
1057          nknots->ChangeArray1(),npoles->ChangeArray1(),
1058          nweights->ChangeArray1());
1059       
1060     }
1061     else {
1062       
1063       BSplCLib::Unperiodize
1064         (deg,mults->Array1(),knots->Array1(),poles->Array1(),
1065          *((TColStd_Array1OfReal*) NULL),nmults->ChangeArray1(),
1066          nknots->ChangeArray1(),npoles->ChangeArray1(),
1067          *((TColStd_Array1OfReal*) NULL));
1068       
1069     }
1070     poles   = npoles;
1071     weights = nweights;
1072     mults   = nmults;
1073     knots   = nknots;
1074     periodic = Standard_False;
1075     maxderivinvok = 0;
1076     UpdateKnots();
1077   }
1078 }
1079
1080 //=======================================================================
1081 //function : SetPole
1082 //purpose  : 
1083 //=======================================================================
1084
1085 void Geom2d_BSplineCurve::SetPole
1086 (const Standard_Integer Index,
1087  const gp_Pnt2d& P)
1088 {
1089   if (Index < 1 || Index > poles->Length()) Standard_OutOfRange::Raise("BSpline curve : SetPole : index and #pole mismatch");
1090   poles->SetValue (Index, P);
1091   maxderivinvok = 0;
1092   InvalidateCache();
1093 }
1094
1095 //=======================================================================
1096 //function : SetPole
1097 //purpose  : 
1098 //=======================================================================
1099
1100 void Geom2d_BSplineCurve::SetPole
1101 (const Standard_Integer Index,
1102  const gp_Pnt2d& P,
1103  const Standard_Real W)
1104 {
1105   SetPole(Index,P);
1106   SetWeight(Index,W);
1107 }
1108
1109 //=======================================================================
1110 //function : SetWeight
1111 //purpose  : 
1112 //=======================================================================
1113
1114 void Geom2d_BSplineCurve::SetWeight
1115 (const Standard_Integer Index,
1116  const Standard_Real W)
1117 {
1118   if (Index < 1 || Index > poles->Length())   Standard_OutOfRange::Raise("BSpline curve : SetWeight: Index and #pole mismatch");
1119
1120   if (W <= gp::Resolution ())     Standard_ConstructionError::Raise("BSpline curve : SetWeight: Weight too small");
1121
1122
1123   Standard_Boolean rat = IsRational() || (Abs(W - 1.) > gp::Resolution());
1124
1125   if ( rat) { 
1126     if (rat && !IsRational()) {
1127       weights = new TColStd_HArray1OfReal(1,poles->Length());
1128       weights->Init(1.);
1129     }
1130     
1131     weights->SetValue (Index, W);
1132     
1133     if (IsRational()) {
1134       rat = Rational(weights->Array1());
1135       if (!rat) weights.Nullify();
1136     }
1137     
1138     rational = !weights.IsNull();
1139   }
1140   
1141   maxderivinvok = 0;
1142   InvalidateCache() ;
1143 }
1144
1145 //=======================================================================
1146 //function : MovePoint
1147 //purpose  : 
1148 //=======================================================================
1149
1150 void Geom2d_BSplineCurve::MovePoint(const Standard_Real U,
1151                                     const gp_Pnt2d& P,
1152                                     const Standard_Integer Index1,
1153                                     const Standard_Integer Index2,
1154                                     Standard_Integer& FirstModifiedPole,
1155                                     Standard_Integer& LastmodifiedPole)
1156 {
1157   if (Index1 < 1 || Index1 > poles->Length() || 
1158       Index2 < 1 || Index2 > poles->Length() || Index1 > Index2) {
1159     Standard_OutOfRange::Raise("BSpline curve :  MovePoint: Index and #pole mismatch");
1160   }
1161   TColgp_Array1OfPnt2d npoles(1, poles->Length());
1162   gp_Pnt2d P0;
1163   D0(U, P0);
1164   gp_Vec2d Displ(P0, P);
1165   BSplCLib::MovePoint(U, Displ, Index1, Index2, deg, rational, poles->Array1(), 
1166                       weights->Array1(), flatknots->Array1(), 
1167                       FirstModifiedPole, LastmodifiedPole, npoles);
1168   if (FirstModifiedPole) {
1169     poles->ChangeArray1() = npoles;
1170     maxderivinvok = 0;
1171     InvalidateCache() ;
1172   }
1173 }
1174
1175 //=======================================================================
1176 //function : MovePointAndTangent
1177 //purpose  : 
1178 //=======================================================================
1179
1180 void Geom2d_BSplineCurve::
1181 MovePointAndTangent(const Standard_Real    U,
1182                     const gp_Pnt2d&        P,
1183                     const gp_Vec2d&        Tangent,
1184                     const Standard_Real    Tolerance,
1185                     const Standard_Integer StartingCondition,
1186                     const Standard_Integer EndingCondition,
1187                     Standard_Integer&      ErrorStatus) 
1188 {
1189   Standard_Integer ii ;
1190   if (IsPeriodic()) {
1191     //
1192     // for the time being do not deal with periodic curves
1193     //
1194     SetNotPeriodic() ;
1195   }
1196   TColgp_Array1OfPnt2d new_poles(1, poles->Length());
1197   gp_Pnt2d P0;
1198   
1199
1200   gp_Vec2d delta_derivative;
1201   D1(U, P0,
1202      delta_derivative) ;
1203   gp_Vec2d delta(P0, P);
1204   for (ii = 1 ; ii <= 2 ; ii++) {
1205     delta_derivative.SetCoord(ii, 
1206                               Tangent.Coord(ii)- delta_derivative.Coord(ii)) ;
1207   }
1208   BSplCLib::MovePointAndTangent(U,
1209                                 delta,
1210                                 delta_derivative,
1211                                 Tolerance,
1212                                 deg,
1213                                 rational,
1214                                 StartingCondition,
1215                                 EndingCondition,
1216                                 poles->Array1(), 
1217                                 weights->Array1(), 
1218                                 flatknots->Array1(), 
1219                                 new_poles,
1220                                 ErrorStatus) ;
1221   if (!ErrorStatus) {
1222     poles->ChangeArray1() = new_poles;
1223     maxderivinvok = 0;
1224     InvalidateCache() ;
1225   }
1226 }
1227
1228 //=======================================================================
1229 //function : UpdateKnots
1230 //purpose  : 
1231 //=======================================================================
1232
1233 void Geom2d_BSplineCurve::UpdateKnots()
1234 {
1235
1236   rational = !weights.IsNull();
1237
1238   Standard_Integer MaxKnotMult = 0;
1239   BSplCLib::KnotAnalysis (deg,
1240                 periodic,
1241                 knots->Array1(), 
1242                 mults->Array1(), 
1243                 knotSet, MaxKnotMult);
1244   
1245   if (knotSet == GeomAbs_Uniform && !periodic)  {
1246     flatknots = knots;
1247   }
1248   else {
1249     flatknots = new TColStd_HArray1OfReal 
1250       (1, BSplCLib::KnotSequenceLength(mults->Array1(),deg,periodic));
1251
1252     BSplCLib::KnotSequence (knots->Array1(), 
1253                             mults->Array1(),
1254                             deg,periodic,
1255                             flatknots->ChangeArray1());
1256   }
1257   
1258   if (MaxKnotMult == 0)  smooth = GeomAbs_CN;
1259   else {
1260     switch (deg - MaxKnotMult) {
1261     case 0 :   smooth = GeomAbs_C0;   break;
1262     case 1 :   smooth = GeomAbs_C1;   break;
1263     case 2 :   smooth = GeomAbs_C2;   break;
1264     case 3 :   smooth = GeomAbs_C3;   break;
1265       default :  smooth = GeomAbs_C3;   break;
1266     }
1267   }
1268   InvalidateCache() ;
1269 }
1270
1271 //=======================================================================
1272 //function : Invalidate the Cache
1273 //purpose  : as the name says
1274 //=======================================================================
1275
1276 void Geom2d_BSplineCurve::InvalidateCache() 
1277 {
1278   validcache = 0 ;
1279 }
1280
1281 //=======================================================================
1282 //function : check if the Cache is valid
1283 //purpose  : as the name says
1284 //=======================================================================
1285
1286 Standard_Boolean Geom2d_BSplineCurve::IsCacheValid
1287 (const Standard_Real  U)  const 
1288 {
1289   //Roman Lygin 26.12.08, see comments in Geom_BSplineCurve::IsCacheValid()
1290   Standard_Real aDelta = U - parametercache;
1291
1292   return ( validcache &&
1293       (aDelta >= 0.0e0) &&
1294       ((aDelta < spanlenghtcache) || (spanindexcache == flatknots->Upper() - deg)) );
1295 }
1296
1297 //=======================================================================
1298 //function : Normalizes the parameters if the curve is periodic
1299 //purpose  : that is compute the cache so that it is valid
1300 //=======================================================================
1301
1302 void Geom2d_BSplineCurve::PeriodicNormalization(Standard_Real&  Parameter) const 
1303 {
1304   Standard_Real Period ;
1305
1306   if (periodic) {
1307     Period = flatknots->Value(flatknots->Upper() - deg) - flatknots->Value (deg + 1) ;
1308     while (Parameter > flatknots->Value(flatknots->Upper()-deg)) {
1309       Parameter -= Period ;
1310     }
1311     while (Parameter < flatknots->Value((deg + 1))) {
1312       Parameter +=  Period ;
1313     }
1314   }
1315 }
1316
1317 //=======================================================================
1318 //function : Validate the Cache
1319 //purpose  : that is compute the cache so that it is valid
1320 //=======================================================================
1321
1322 void Geom2d_BSplineCurve::ValidateCache(const Standard_Real  Parameter) 
1323 {
1324   Standard_Real NewParameter ;
1325   Standard_Integer LocalIndex = 0 ;
1326   //
1327   // check if the degree did not change
1328   //
1329   if (cachepoles->Upper() < deg + 1) {
1330     cachepoles = new TColgp_HArray1OfPnt2d(1,deg + 1);
1331     if (rational) {
1332       cacheweights  = new TColStd_HArray1OfReal(1,deg + 1);
1333     }
1334   }
1335
1336   BSplCLib::LocateParameter(deg,
1337                             (flatknots->Array1()),
1338                             (BSplCLib::NoMults()),
1339                             Parameter,
1340                             periodic,
1341                             LocalIndex,
1342                             NewParameter);
1343   spanindexcache = LocalIndex ;
1344   if (Parameter == flatknots->Value(LocalIndex + 1)) {
1345     
1346     LocalIndex += 1 ;
1347     parametercache = flatknots->Value(LocalIndex) ;
1348     if (LocalIndex == flatknots->Upper() - deg) {
1349       //
1350       // for the last span if the parameter is outside of 
1351       // the domain of the curve than use the last knot
1352       // and normalize with the last span Still set the
1353       // spanindexcache to flatknots->Upper() - deg so that
1354       // the IsCacheValid will know for sure we are extending
1355       // the Bspline 
1356       //
1357       
1358       spanlenghtcache = flatknots->Value(LocalIndex - 1) - parametercache ;
1359     }
1360     else {
1361       spanlenghtcache = flatknots->Value(LocalIndex + 1) - parametercache ;
1362     }
1363   }
1364   else {
1365     parametercache = flatknots->Value(LocalIndex) ;
1366     spanlenghtcache = flatknots->Value(LocalIndex + 1) - parametercache ;
1367   }
1368   
1369   if  (rational) {
1370     BSplCLib::BuildCache(parametercache,
1371                          spanlenghtcache,
1372                          periodic,
1373                          deg,
1374                          (flatknots->Array1()),
1375                          poles->Array1(),
1376                          weights->Array1(),
1377                          cachepoles->ChangeArray1(),
1378                          cacheweights->ChangeArray1()) ;
1379   }
1380   else {
1381     BSplCLib::BuildCache(parametercache,
1382                          spanlenghtcache,
1383                          periodic,
1384                          deg,
1385                          (flatknots->Array1()),
1386                          poles->Array1(),
1387                          *((TColStd_Array1OfReal*) NULL),
1388                          cachepoles->ChangeArray1(),
1389                          *((TColStd_Array1OfReal*) NULL)) ;
1390   }
1391   validcache = 1 ;
1392 }
1393