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