CR23683: Geom_BSplineSurface incorrectly determines continuity for periodic cases
[occt.git] / src / Geom / Geom_BSplineSurface.cxx
1 // Created on: 1993-03-09
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 // 14-Mar-96 : xab  portage hp
23 // pmn : 28-Jun-96 Distinction entre la continuite en U et V (bug PRO4625)
24 // pmn : 07-Jan-97 Centralisation des verif rational (PRO6834)
25 //       et ajout des InvalideCache() dans les SetWeight*(PRO6833)
26 // RBD : 15-10-98 ; Le cache est maintenant calcule sur [-1,1] (pro15537).
27 // jct : 19-01-99 ; permutation de urational et vrational dans Rational.
28 #define No_Standard_OutOfRange
29
30 #include <Geom_BSplineSurface.ixx>
31
32 #include <gp.hxx>
33 #include <BSplCLib.hxx>
34 #include <BSplSLib.hxx>
35
36 #include <Standard_ConstructionError.hxx>
37 #include <Standard_NotImplemented.hxx>
38 #include <Standard_OutOfRange.hxx>
39 #include <Precision.hxx>
40
41 //=======================================================================
42 //function : CheckSurfaceData
43 //purpose  : Internal use only.
44 //=======================================================================
45
46 static void CheckSurfaceData
47 (const TColgp_Array2OfPnt&      SPoles,
48  const TColStd_Array1OfReal&    SUKnots,
49  const TColStd_Array1OfReal&    SVKnots,
50  const TColStd_Array1OfInteger& SUMults,
51  const TColStd_Array1OfInteger& SVMults,
52  const Standard_Integer         UDegree,
53  const Standard_Integer         VDegree,
54  const Standard_Boolean         UPeriodic,
55  const Standard_Boolean         VPeriodic)
56 {
57   if (UDegree < 1 || UDegree > Geom_BSplineSurface::MaxDegree () || 
58       VDegree < 1 || VDegree > Geom_BSplineSurface::MaxDegree ()) {
59     Standard_ConstructionError::Raise("Geom_BSplineSurface");
60   }
61   if (SPoles.ColLength () < 2 || SPoles.RowLength () < 2) {
62     Standard_ConstructionError::Raise("Geom_BSplineSurface");
63   }
64
65   if (SUKnots.Length() != SUMults.Length() ||
66       SVKnots.Length() != SVMults.Length()) {
67     Standard_ConstructionError::Raise("Geom_BSplineSurface");
68   }
69
70   Standard_Integer i;
71   for (i = SUKnots.Lower(); i < SUKnots.Upper(); i++) {
72     if (SUKnots(i+1) - SUKnots(i) <= Epsilon(Abs(SUKnots(i)))) {
73       Standard_ConstructionError::Raise("Geom_BSplineSurface");
74     }
75   }
76
77   for (i = SVKnots.Lower(); i < SVKnots.Upper(); i++) {
78     if (SVKnots(i+1) - SVKnots(i) <= Epsilon(Abs(SVKnots(i)))) {
79       Standard_ConstructionError::Raise("Geom_BSplineSurface");
80     }
81   }
82   
83   if (SPoles.ColLength() != BSplCLib::NbPoles(UDegree,UPeriodic,SUMults))
84     Standard_ConstructionError::Raise("Geom_BSplineSurface");
85
86   if (SPoles.RowLength() != BSplCLib::NbPoles(VDegree,VPeriodic,SVMults))
87     Standard_ConstructionError::Raise("Geom_BSplineSurface");
88 }
89
90 //=======================================================================
91 //function : Rational
92 //purpose  : Internal use only.
93 //=======================================================================
94
95 static void Rational(const TColStd_Array2OfReal& Weights,
96                      Standard_Boolean& Urational,
97                      Standard_Boolean& Vrational)
98 {
99   Standard_Integer I,J;
100   J = Weights.LowerCol ();
101   Vrational = Standard_False;
102   while (!Vrational && J <= Weights.UpperCol()) {
103     I = Weights.LowerRow();
104     while (!Vrational && I <= Weights.UpperRow() - 1) {
105       Vrational = (Abs(Weights (I, J) - Weights (I+1, J)) 
106                    > Epsilon (Abs(Weights (I, J))));
107       I++;
108     }
109     J++;
110   }
111
112   I = Weights.LowerRow ();
113   Urational = Standard_False;
114   while (!Urational && I <= Weights.UpperRow()) {
115     J = Weights.LowerCol();
116     while (!Urational && J <= Weights.UpperCol() - 1) {
117       Urational = (Abs(Weights (I, J) - Weights (I, J+1))
118                    > Epsilon (Abs(Weights (I, J))));
119       J++;
120     }
121     I++;
122   }
123 }
124
125 //=======================================================================
126 //function : Copy
127 //purpose  : 
128 //=======================================================================
129
130 Handle(Geom_Geometry) Geom_BSplineSurface::Copy () const
131 {
132   Handle(Geom_BSplineSurface) S;
133   if (urational || vrational) 
134     S = new Geom_BSplineSurface (poles->Array2() , weights->Array2(), 
135                                  uknots->Array1(), vknots->Array1(), 
136                                  umults->Array1(), vmults->Array1(), 
137                                  udeg     , vdeg, 
138                                  uperiodic, vperiodic);
139   else
140     S = new Geom_BSplineSurface (poles->Array2(),
141                                  uknots->Array1(), vknots->Array1(), 
142                                  umults->Array1(), vmults->Array1(), 
143                                  udeg     , vdeg, 
144                                  uperiodic, vperiodic);
145   return S;
146 }
147
148 //=======================================================================
149 //function : Geom_BSplineSurface
150 //purpose  : 
151 //=======================================================================
152
153 Geom_BSplineSurface::Geom_BSplineSurface
154 (const TColgp_Array2OfPnt&      Poles, 
155  const TColStd_Array1OfReal&    UKnots, 
156  const TColStd_Array1OfReal&    VKnots,
157  const TColStd_Array1OfInteger& UMults, 
158  const TColStd_Array1OfInteger& VMults,
159  const Standard_Integer         UDegree, 
160  const Standard_Integer         VDegree,
161  const Standard_Boolean         UPeriodic,
162  const Standard_Boolean         VPeriodic
163  ) :
164  urational(Standard_False),
165  vrational(Standard_False),
166  uperiodic(UPeriodic),
167  vperiodic(VPeriodic),
168  udeg(UDegree),
169  vdeg(VDegree),
170  maxderivinvok(0)
171
172 {
173   Standard_Integer MinDegree,
174   MaxDegree ;
175
176   // check
177   
178   CheckSurfaceData(Poles,
179                    UKnots   , VKnots,
180                    UMults   , VMults,
181                    UDegree  , VDegree,
182                    UPeriodic, VPeriodic);
183
184   // copy arrays
185
186   poles   = new TColgp_HArray2OfPnt(1,Poles.ColLength(),
187                                     1,Poles.RowLength());
188   poles->ChangeArray2() = Poles;
189
190   weights = new TColStd_HArray2OfReal (1,Poles.ColLength(),
191                                        1,Poles.RowLength(), 1.0);
192
193   uknots  = new TColStd_HArray1OfReal    (1,UKnots.Length());
194   uknots->ChangeArray1() = UKnots;
195
196   umults  = new TColStd_HArray1OfInteger (1,UMults.Length());
197   umults->ChangeArray1() = UMults;
198
199   vknots  = new TColStd_HArray1OfReal    (1,VKnots.Length());
200   vknots->ChangeArray1() = VKnots;
201
202   vmults  = new TColStd_HArray1OfInteger (1,VMults.Length());
203   vmults->ChangeArray1() = VMults;
204   MinDegree = Min(udeg,vdeg) ;
205   MaxDegree = Max(udeg,vdeg) ;
206   cachepoles = new TColgp_HArray2OfPnt(1,MaxDegree + 1,
207                                        1,MinDegree + 1) ;
208   
209   cacheweights.Nullify() ;
210   ucacheparameter = 0.0e0 ;
211   vcacheparameter = 0.0e0 ;
212   ucachespanlenght = 1.0e0 ;
213   vcachespanlenght = 1.0e0 ;
214   ucachespanindex = 0 ;
215   vcachespanindex = 0 ;
216   validcache = 0 ;
217
218   UpdateUKnots();
219   UpdateVKnots();
220 }
221
222 //=======================================================================
223 //function : Geom_BSplineSurface
224 //purpose  : 
225 //=======================================================================
226
227 Geom_BSplineSurface::Geom_BSplineSurface
228 (const TColgp_Array2OfPnt&      Poles,
229  const TColStd_Array2OfReal&    Weights,
230  const TColStd_Array1OfReal&    UKnots,
231  const TColStd_Array1OfReal&    VKnots,
232  const TColStd_Array1OfInteger& UMults, 
233  const TColStd_Array1OfInteger& VMults,
234  const Standard_Integer         UDegree,
235  const Standard_Integer         VDegree,
236  const Standard_Boolean         UPeriodic,
237  const Standard_Boolean         VPeriodic) :
238  urational(Standard_False),
239  vrational(Standard_False),
240  uperiodic(UPeriodic),
241  vperiodic(VPeriodic),
242  udeg(UDegree),
243  vdeg(VDegree),
244  maxderivinvok(0)
245 {
246   Standard_Integer MinDegree,
247   MaxDegree ;
248   // check weights
249
250   if (Weights.ColLength() != Poles.ColLength())
251     Standard_ConstructionError::Raise("Geom_BSplineSurface");
252
253   if (Weights.RowLength() != Poles.RowLength())
254     Standard_ConstructionError::Raise("Geom_BSplineSurface");
255
256   Standard_Integer i,j;
257   for (i = Weights.LowerRow(); i <= Weights.UpperRow(); i++) {
258     for (j = Weights.LowerCol(); j <= Weights.UpperCol(); j++) {
259       if (Weights(i,j) <= gp::Resolution())  
260         Standard_ConstructionError::Raise("Geom_BSplineSurface");
261     }
262   }
263   
264   // check really rational
265   
266   Rational(Weights, urational, vrational);
267
268   // check
269   
270   CheckSurfaceData(Poles,
271                    UKnots   , VKnots,
272                    UMults   , VMults,
273                    UDegree  , VDegree,
274                    UPeriodic, VPeriodic);
275
276   // copy arrays
277
278   poles   = new TColgp_HArray2OfPnt(1,Poles.ColLength(),
279                                     1,Poles.RowLength());
280   poles->ChangeArray2() = Poles;
281
282   weights = new TColStd_HArray2OfReal (1,Poles.ColLength(),
283                                        1,Poles.RowLength());
284   weights->ChangeArray2() = Weights;
285
286   uknots  = new TColStd_HArray1OfReal    (1,UKnots.Length());
287   uknots->ChangeArray1() = UKnots;
288
289   umults  = new TColStd_HArray1OfInteger (1,UMults.Length());
290   umults->ChangeArray1() = UMults;
291
292   vknots  = new TColStd_HArray1OfReal    (1,VKnots.Length());
293   vknots->ChangeArray1() = VKnots;
294
295   vmults  = new TColStd_HArray1OfInteger (1,VMults.Length());
296   vmults->ChangeArray1() = VMults;
297   MinDegree = Min(udeg,vdeg) ;
298   MaxDegree = Max(udeg,vdeg) ;
299   cachepoles = new TColgp_HArray2OfPnt(1,MaxDegree + 1,
300                                        1,MinDegree + 1) ;
301   if (urational || vrational) {
302     cacheweights = new TColStd_HArray2OfReal (1,MaxDegree + 1,
303                                               1,MinDegree + 1);
304   }
305   ucacheparameter = 0.0e0 ;
306   vcacheparameter = 0.0e0 ;
307   ucachespanlenght = 1.0e0 ;
308   vcachespanlenght = 1.0e0 ;
309   ucachespanindex = 0 ;
310   vcachespanindex = 0 ;
311   validcache = 0 ;
312
313   UpdateUKnots();
314   UpdateVKnots();
315 }
316
317 //=======================================================================
318 //function : ExchangeUV
319 //purpose  : 
320 //=======================================================================
321
322 void Geom_BSplineSurface::ExchangeUV ()
323 {
324   Standard_Integer LC = poles->LowerCol();
325   Standard_Integer UC = poles->UpperCol();
326   Standard_Integer LR = poles->LowerRow();
327   Standard_Integer UR = poles->UpperRow();
328
329   Handle(TColgp_HArray2OfPnt)   npoles   = 
330     new TColgp_HArray2OfPnt  (LC, UC, LR, UR);
331   Handle(TColStd_HArray2OfReal) nweights = 
332     new TColStd_HArray2OfReal (LC, UC, LR, UR);
333
334   const TColgp_Array2OfPnt   & spoles   = poles->Array2();
335   const TColStd_Array2OfReal & sweights = weights->Array2();
336   
337   TColgp_Array2OfPnt&   snpoles   = npoles->ChangeArray2();
338   TColStd_Array2OfReal& snweights = nweights->ChangeArray2();
339   
340   Standard_Integer i, j;
341   for (i = LC; i <= UC; i++) {
342     for (j = LR; j <= UR; j++) {
343       snpoles   (i,j) = spoles   (j,i);
344       snweights (i,j) = sweights (j,i);
345     }
346   }
347
348   poles   = npoles;
349   weights = nweights;
350
351   Standard_Boolean temp = urational;
352   urational = vrational;
353   vrational = temp;
354
355   temp = uperiodic;
356   uperiodic = vperiodic;
357   vperiodic = temp;
358
359   Standard_Integer tempdeg = udeg;
360   udeg = vdeg;
361   vdeg = tempdeg;
362   
363
364   Handle(TColStd_HArray1OfReal) tempknots = uknots;
365   uknots = vknots;
366   vknots = tempknots;
367
368   Handle(TColStd_HArray1OfInteger) tempmults = umults;
369   umults = vmults;
370   vmults = tempmults;
371
372   UpdateUKnots();
373   UpdateVKnots();
374 }
375
376 //=======================================================================
377 //function : IncreaseDegree
378 //purpose  : 
379 //=======================================================================
380
381 void Geom_BSplineSurface::IncreaseDegree (const Standard_Integer UDegree,
382                                           const Standard_Integer VDegree)
383
384   if (UDegree != udeg) {
385     if ( UDegree < udeg || UDegree > Geom_BSplineSurface::MaxDegree())
386       Standard_ConstructionError::Raise();
387     
388     Standard_Integer FromK1 = FirstUKnotIndex();
389     Standard_Integer ToK2   = LastUKnotIndex();
390
391     Standard_Integer Step   = UDegree - udeg;
392
393     Handle(TColgp_HArray2OfPnt) npoles = new
394       TColgp_HArray2OfPnt( 1, poles->ColLength() + Step * (ToK2 - FromK1),
395                           1, poles->RowLength());
396
397     Standard_Integer nbknots = BSplCLib::IncreaseDegreeCountKnots
398       (udeg,UDegree,uperiodic,umults->Array1());
399
400     Handle(TColStd_HArray1OfReal) nknots = 
401       new TColStd_HArray1OfReal(1,nbknots);
402     
403     Handle(TColStd_HArray1OfInteger) nmults = 
404       new TColStd_HArray1OfInteger(1,nbknots);
405
406     Handle(TColStd_HArray2OfReal) nweights 
407       = new TColStd_HArray2OfReal(1,npoles->ColLength(),
408                                   1,npoles->RowLength(), 1.);
409
410     if (urational || vrational) {
411       
412       BSplSLib::IncreaseDegree
413         (Standard_True, udeg, UDegree, uperiodic,
414          poles->Array2(),weights->Array2(),
415          uknots->Array1(),umults->Array1(),
416          npoles->ChangeArray2(),nweights->ChangeArray2(),
417          nknots->ChangeArray1(),nmults->ChangeArray1());
418     }
419     else {
420
421       BSplSLib::IncreaseDegree
422         (Standard_True, udeg, UDegree, uperiodic,
423          poles->Array2(),BSplSLib::NoWeights(),
424          uknots->Array1(),umults->Array1(),
425          npoles->ChangeArray2(),*((TColStd_Array2OfReal*) NULL),
426          nknots->ChangeArray1(),nmults->ChangeArray1());
427     }
428     udeg    = UDegree;
429     poles   = npoles;
430     weights = nweights;
431     uknots  = nknots;
432     umults  = nmults;
433     UpdateUKnots();
434   }
435
436   if (VDegree != vdeg) {
437     if ( VDegree < vdeg || VDegree > Geom_BSplineSurface::MaxDegree())
438       Standard_ConstructionError::Raise();
439     
440     Standard_Integer FromK1 = FirstVKnotIndex();
441     Standard_Integer ToK2   = LastVKnotIndex();
442
443     Standard_Integer Step   = VDegree - vdeg;
444
445     Handle(TColgp_HArray2OfPnt) npoles = new
446       TColgp_HArray2OfPnt( 1, poles->ColLength(),
447                           1, poles->RowLength() + Step * (ToK2 - FromK1));
448
449     Standard_Integer nbknots = BSplCLib::IncreaseDegreeCountKnots
450       (vdeg,VDegree,vperiodic,vmults->Array1());
451
452     Handle(TColStd_HArray1OfReal) nknots = 
453       new TColStd_HArray1OfReal(1,nbknots);
454     
455     Handle(TColStd_HArray1OfInteger) nmults = 
456       new TColStd_HArray1OfInteger(1,nbknots);
457
458     Handle(TColStd_HArray2OfReal) nweights
459       = new TColStd_HArray2OfReal(1,npoles->ColLength(),
460                                   1,npoles->RowLength(), 1.);
461
462     if (urational || vrational) {
463       
464       BSplSLib::IncreaseDegree
465         (Standard_False, vdeg, VDegree, vperiodic,
466          poles->Array2(),weights->Array2(),
467          vknots->Array1(),vmults->Array1(),
468          npoles->ChangeArray2(),nweights->ChangeArray2(),
469          nknots->ChangeArray1(),nmults->ChangeArray1());
470     }
471     else {
472
473       BSplSLib::IncreaseDegree
474         (Standard_False, vdeg, VDegree, vperiodic,
475          poles->Array2(),BSplSLib::NoWeights(),
476          vknots->Array1(),vmults->Array1(),
477          npoles->ChangeArray2(),*((TColStd_Array2OfReal*) NULL),
478          nknots->ChangeArray1(),nmults->ChangeArray1());
479     }
480     vdeg    = VDegree;
481     poles   = npoles;
482     weights = nweights;
483     vknots  = nknots;
484     vmults  = nmults;
485     UpdateVKnots();
486   }
487 }
488
489 //=======================================================================
490 //function : IncreaseUMultiplicity
491 //purpose  : 
492 //=======================================================================
493
494 void Geom_BSplineSurface::IncreaseUMultiplicity
495 (const Standard_Integer UIndex, 
496  const Standard_Integer M)
497 {
498   TColStd_Array1OfReal k(1,1);
499   k(1) = uknots->Value(UIndex);
500   TColStd_Array1OfInteger m(1,1);
501   m(1) = M - umults->Value(UIndex);
502   InsertUKnots(k,m,Epsilon(1.),Standard_True);
503 }
504
505 //=======================================================================
506 //function : IncreaseUMultiplicity
507 //purpose  : 
508 //=======================================================================
509
510 void Geom_BSplineSurface::IncreaseUMultiplicity
511 (const Standard_Integer FromI1, 
512  const Standard_Integer ToI2,
513  const Standard_Integer M)
514 {
515   Handle(TColStd_HArray1OfReal) tk = uknots;
516   TColStd_Array1OfReal k((uknots->Array1())(FromI1),FromI1,ToI2);
517   TColStd_Array1OfInteger m(FromI1, ToI2);
518   for (Standard_Integer i = FromI1; i <= ToI2; i++) 
519     m(i) = M - umults->Value(i);
520   InsertUKnots(k,m,Epsilon(1.),Standard_True);
521 }
522
523 //=======================================================================
524 //function : IncreaseVMultiplicity
525 //purpose  : 
526 //=======================================================================
527
528 void Geom_BSplineSurface::IncreaseVMultiplicity
529 (const Standard_Integer VIndex, 
530  const Standard_Integer M)
531 {
532   TColStd_Array1OfReal k(1,1);
533   k(1) = vknots->Value(VIndex);
534   TColStd_Array1OfInteger m(1,1);
535   m(1) = M - vmults->Value(VIndex);
536   InsertVKnots(k,m,Epsilon(1.),Standard_True);
537 }
538
539 //=======================================================================
540 //function : IncreaseVMultiplicity
541 //purpose  : 
542 //=======================================================================
543
544 void Geom_BSplineSurface::IncreaseVMultiplicity
545 (const Standard_Integer FromI1,
546  const Standard_Integer ToI2,
547  const Standard_Integer M)
548 {
549   Handle(TColStd_HArray1OfReal) tk = vknots;
550   TColStd_Array1OfReal k((vknots->Array1())(FromI1),FromI1,ToI2);
551   TColStd_Array1OfInteger m(FromI1,ToI2);
552   for (Standard_Integer i = FromI1; i <= ToI2; i++)
553     m(i) = M - vmults->Value(i);
554   InsertVKnots(k,m,Epsilon(1.),Standard_True);
555 }
556
557 //=======================================================================
558 //function : Segment
559 //purpose  : 
560 //=======================================================================
561
562 void Geom_BSplineSurface::Segment(const Standard_Real U1, 
563                                   const Standard_Real U2,
564                                   const Standard_Real V1,
565                                   const Standard_Real V2) 
566 {
567
568   Standard_DomainError_Raise_if ( (U2 < U1) || (V2 < V1),
569                                  "Geom_BSplineCurve::Segment");
570   Standard_Real deltaU = Max(Abs(U2),Abs(U1));
571   Standard_Real EpsU = Epsilon(deltaU);
572   deltaU = U2 - U1;
573   
574   Standard_Real deltaV = Max(Abs(V2),Abs(V1));
575   Standard_Real EpsV = Epsilon(deltaV);
576   deltaV = V2 - V1;
577
578   Standard_Real NewU1, NewU2, NewV1, NewV2;
579   Standard_Real U,V;
580   Standard_Integer indexU, indexV;
581
582   // inserting the UKnots
583   TColStd_Array1OfReal    UKnots(1,2);
584   TColStd_Array1OfInteger UMults(1,2);
585
586   indexU = 0;
587   BSplCLib::LocateParameter(udeg,uknots->Array1(),umults->Array1(),
588                             U1,uperiodic,uknots->Lower(),uknots->Upper(),
589                             indexU,NewU1);
590   indexU = 0;
591   BSplCLib::LocateParameter(udeg,uknots->Array1(),umults->Array1(),
592                             U2,uperiodic,uknots->Lower(),uknots->Upper(),
593                             indexU,NewU2);
594   UKnots( 1) = Min( NewU1, NewU2);
595   UKnots( 2) = Max( NewU1, NewU2);
596   UMults( 1) = UMults( 2) = udeg;
597   InsertUKnots( UKnots, UMults, EpsU);
598
599   // Inserting the VKnots
600   TColStd_Array1OfReal    VKnots(1,2);
601   TColStd_Array1OfInteger VMults(1,2);
602
603   indexV = 0;
604   BSplCLib::LocateParameter(vdeg,vknots->Array1(),vmults->Array1(),
605                             V1,vperiodic,vknots->Lower(),vknots->Upper(),
606                             indexV,NewV1);
607   indexV = 0;
608   BSplCLib::LocateParameter(vdeg,vknots->Array1(),vmults->Array1(),
609                             V2,vperiodic,vknots->Lower(),vknots->Upper(),
610                             indexV,NewV2);
611   VKnots( 1) = Min( NewV1, NewV2);
612   VKnots( 2) = Max( NewV1, NewV2);
613   VMults( 1) = VMults( 2) = vdeg;
614   InsertVKnots( VKnots, VMults, EpsV);
615
616
617   if (uperiodic) { // set the origine at NewU1
618     Standard_Integer index = 0;
619     BSplCLib::LocateParameter(udeg,uknots->Array1(),umults->Array1(),
620                               U1,uperiodic,uknots->Lower(),uknots->Upper(),
621                               index,U);
622     if ( Abs(uknots->Value(index+1)-U) <= EpsU)
623       index++;
624     SetUOrigin(index);
625     SetUNotPeriodic();
626   }
627
628   // compute index1 and index2 to set the new knots and mults 
629   Standard_Integer index1U = 0, index2U = 0;
630   Standard_Integer FromU1 = uknots->Lower();
631   Standard_Integer ToU2   = uknots->Upper();
632   BSplCLib::LocateParameter(udeg,uknots->Array1(),umults->Array1(),
633                             NewU1,uperiodic,FromU1,ToU2,index1U,U);
634   BSplCLib::LocateParameter(udeg,uknots->Array1(),umults->Array1(),
635                             NewU1 + deltaU,uperiodic,FromU1,ToU2,index2U,U);
636   if ( Abs(uknots->Value(index2U+1)-U) <= EpsU)
637     index2U++;
638   
639   Standard_Integer nbuknots = index2U - index1U + 1;
640
641   Handle(TColStd_HArray1OfReal) 
642     nuknots = new TColStd_HArray1OfReal(1,nbuknots);
643   Handle(TColStd_HArray1OfInteger) 
644     numults = new TColStd_HArray1OfInteger(1,nbuknots);
645
646   Standard_Integer i , k = 1;
647   for ( i = index1U; i<= index2U; i++) {
648     nuknots->SetValue(k, uknots->Value(i));
649     numults->SetValue(k, umults->Value(i));
650     k++;
651   }
652   numults->SetValue(       1, udeg + 1);
653   numults->SetValue(nbuknots, udeg + 1);
654
655
656   if (vperiodic) { // set the origine at NewV1
657     Standard_Integer index = 0;
658     BSplCLib::LocateParameter(vdeg,vknots->Array1(),vmults->Array1(),
659                               V1,vperiodic,vknots->Lower(),vknots->Upper(),
660                               index,V);
661     if ( Abs(vknots->Value(index+1)-V) <= EpsV)
662       index++;
663     SetVOrigin(index);
664     SetVNotPeriodic();
665   }
666
667   // compute index1 and index2 to set the new knots and mults 
668   Standard_Integer index1V = 0, index2V = 0;
669   Standard_Integer FromV1 = vknots->Lower();
670   Standard_Integer ToV2   = vknots->Upper();
671   BSplCLib::LocateParameter(vdeg,vknots->Array1(),vmults->Array1(),
672                             NewV1,vperiodic,FromV1,ToV2,index1V,V);
673   BSplCLib::LocateParameter(vdeg,vknots->Array1(),vmults->Array1(),
674                             NewV1 + deltaV,vperiodic,FromV1,ToV2,index2V,V);
675   if ( Abs(vknots->Value(index2V+1)-V) <= EpsV)
676     index2V++;
677   
678   Standard_Integer nbvknots = index2V - index1V + 1;
679
680   Handle(TColStd_HArray1OfReal) 
681     nvknots = new TColStd_HArray1OfReal(1,nbvknots);
682   Handle(TColStd_HArray1OfInteger) 
683     nvmults = new TColStd_HArray1OfInteger(1,nbvknots);
684
685   k = 1;
686   for ( i = index1V; i<= index2V; i++) {
687     nvknots->SetValue(k, vknots->Value(i));
688     nvmults->SetValue(k, vmults->Value(i));
689     k++;
690   }
691   nvmults->SetValue(       1, vdeg + 1);
692   nvmults->SetValue(nbvknots, vdeg + 1);
693
694
695   // compute index1 and index2 to set the new poles and weights
696   Standard_Integer pindex1U 
697     = BSplCLib::PoleIndex(udeg,index1U,uperiodic,umults->Array1());
698   Standard_Integer pindex2U 
699     = BSplCLib::PoleIndex(udeg,index2U,uperiodic,umults->Array1());
700
701   pindex1U++;
702   pindex2U = Min( pindex2U+1, poles->ColLength());
703
704   Standard_Integer nbupoles  = pindex2U - pindex1U + 1;
705
706   // compute index1 and index2 to set the new poles and weights
707   Standard_Integer pindex1V 
708     = BSplCLib::PoleIndex(vdeg,index1V,vperiodic,vmults->Array1());
709   Standard_Integer pindex2V 
710     = BSplCLib::PoleIndex(vdeg,index2V,vperiodic,vmults->Array1());
711
712   pindex1V++;
713   pindex2V = Min( pindex2V+1, poles->RowLength());
714
715   Standard_Integer nbvpoles  = pindex2V - pindex1V + 1;
716
717
718   Handle(TColStd_HArray2OfReal) nweights; 
719
720   Handle(TColgp_HArray2OfPnt)
721     npoles = new TColgp_HArray2OfPnt(1,nbupoles,1,nbvpoles);
722
723   k = 1;
724   Standard_Integer j, l;
725   if ( urational || vrational) {
726     nweights = new TColStd_HArray2OfReal( 1,nbupoles,1,nbvpoles);
727     for ( i = pindex1U; i <= pindex2U; i++) {
728       l = 1;
729       for ( j = pindex1V; j <= pindex2V; j++) {
730         npoles->SetValue(k,l, poles->Value(i,j));
731         nweights->SetValue(k,l, weights->Value(i,j));
732         l++;
733       }
734       k++;
735     }
736   }
737   else {
738     for ( i = pindex1U; i <= pindex2U; i++) {
739       l = 1;
740       for ( j = pindex1V; j <= pindex2V; j++) {
741         npoles->SetValue(k,l, poles->Value(i,j));
742         l++;
743       }
744       k++;
745     }
746   }
747
748   uknots = nuknots;
749   umults = numults;
750   vknots = nvknots;
751   vmults = nvmults;
752   poles = npoles;
753   if ( urational || vrational) 
754     weights = nweights;
755   else 
756     weights = new TColStd_HArray2OfReal (1,poles->ColLength(),
757                                          1,poles->RowLength(), 1.0);
758
759   maxderivinvok = 0;
760   UpdateUKnots();
761   UpdateVKnots();
762
763 }
764
765 //=======================================================================
766 //function : CheckAndSegment
767 //purpose  : 
768 //=======================================================================
769
770 void Geom_BSplineSurface::CheckAndSegment(const Standard_Real U1, 
771                                           const Standard_Real U2,
772                                           const Standard_Real V1,
773                                           const Standard_Real V2) 
774 {
775
776   Standard_DomainError_Raise_if ( (U2 < U1) || (V2 < V1),
777                                  "Geom_BSplineCurve::Segment");
778   Standard_Real deltaU = Max(Abs(U2),Abs(U1));
779   Standard_Real EpsU = Epsilon(deltaU);
780   deltaU = U2 - U1;
781   
782   Standard_Real deltaV = Max(Abs(V2),Abs(V1));
783   Standard_Real EpsV = Epsilon(deltaV);
784   deltaV = V2 - V1;
785
786   Standard_Real NewU1, NewU2, NewV1, NewV2;
787   Standard_Real U,V;
788   Standard_Integer indexU, indexV;
789
790   Standard_Boolean segment_in_U = Standard_True;
791   Standard_Boolean segment_in_V = Standard_True;
792   segment_in_U = ( Abs(U1 - uknots->Value(uknots->Lower())) > EpsU )
793                         || ( Abs(U2 - uknots->Value(uknots->Upper())) > EpsU );
794   segment_in_V = ( Abs(V1 - vknots->Value(vknots->Lower())) > EpsV )
795                         || ( Abs(V2 - vknots->Value(vknots->Upper())) > EpsV );
796
797   indexU = 0;
798   BSplCLib::LocateParameter(udeg,uknots->Array1(),umults->Array1(),
799                             U1,uperiodic,uknots->Lower(),uknots->Upper(),
800                             indexU,NewU1);
801   indexU = 0;
802   BSplCLib::LocateParameter(udeg,uknots->Array1(),umults->Array1(),
803                             U2,uperiodic,uknots->Lower(),uknots->Upper(),
804                             indexU,NewU2);
805   if (segment_in_U) {
806     // inserting the UKnots
807     TColStd_Array1OfReal    UKnots(1,2);
808     TColStd_Array1OfInteger UMults(1,2);
809     UKnots( 1) = Min( NewU1, NewU2);
810     UKnots( 2) = Max( NewU1, NewU2);
811     UMults( 1) = UMults( 2) = udeg;
812     
813     InsertUKnots( UKnots, UMults, EpsU);
814   }
815
816   indexV = 0;
817   BSplCLib::LocateParameter(vdeg,vknots->Array1(),vmults->Array1(),
818                             V1,vperiodic,vknots->Lower(),vknots->Upper(),
819                             indexV,NewV1);
820   indexV = 0;
821   BSplCLib::LocateParameter(vdeg,vknots->Array1(),vmults->Array1(),
822                             V2,vperiodic,vknots->Lower(),vknots->Upper(),
823                             indexV,NewV2);
824   if (segment_in_V) {
825     // Inserting the VKnots
826     TColStd_Array1OfReal    VKnots(1,2);
827     TColStd_Array1OfInteger VMults(1,2);
828     
829     VKnots( 1) = Min( NewV1, NewV2);
830     VKnots( 2) = Max( NewV1, NewV2);
831     VMults( 1) = VMults( 2) = vdeg;
832     InsertVKnots( VKnots, VMults, EpsV);
833   }
834
835   if (uperiodic && segment_in_U) { // set the origine at NewU1
836     Standard_Integer index = 0;
837     BSplCLib::LocateParameter(udeg,uknots->Array1(),umults->Array1(),
838                               U1,uperiodic,uknots->Lower(),uknots->Upper(),
839                               index,U);
840     if ( Abs(uknots->Value(index+1)-U) <= EpsU)
841       index++;
842     SetUOrigin(index);
843     SetUNotPeriodic();
844   }
845
846   // compute index1 and index2 to set the new knots and mults 
847   Standard_Integer index1U = 0, index2U = 0;
848   Standard_Integer FromU1 = uknots->Lower();
849   Standard_Integer ToU2   = uknots->Upper();
850   BSplCLib::LocateParameter(udeg,uknots->Array1(),umults->Array1(),
851                             NewU1,uperiodic,FromU1,ToU2,index1U,U);
852   BSplCLib::LocateParameter(udeg,uknots->Array1(),umults->Array1(),
853                             NewU1 + deltaU,uperiodic,FromU1,ToU2,index2U,U);
854   if ( Abs(uknots->Value(index2U+1)-U) <= EpsU)
855     index2U++;
856   
857   Standard_Integer nbuknots = index2U - index1U + 1;
858
859   Handle(TColStd_HArray1OfReal) 
860     nuknots = new TColStd_HArray1OfReal(1,nbuknots);
861   Handle(TColStd_HArray1OfInteger) 
862     numults = new TColStd_HArray1OfInteger(1,nbuknots);
863
864   Standard_Integer i , k = 1;
865   for ( i = index1U; i<= index2U; i++) {
866     nuknots->SetValue(k, uknots->Value(i));
867     numults->SetValue(k, umults->Value(i));
868     k++;
869   }
870   if (segment_in_U) {
871     numults->SetValue(       1, udeg + 1);
872     numults->SetValue(nbuknots, udeg + 1);
873   }
874
875   if (vperiodic&& segment_in_V) { // set the origine at NewV1
876     Standard_Integer index = 0;
877     BSplCLib::LocateParameter(vdeg,vknots->Array1(),vmults->Array1(),
878                               V1,vperiodic,vknots->Lower(),vknots->Upper(),
879                               index,V);
880     if ( Abs(vknots->Value(index+1)-V) <= EpsV)
881       index++;
882     SetVOrigin(index);
883     SetVNotPeriodic();
884   }
885
886   // compute index1 and index2 to set the new knots and mults 
887   Standard_Integer index1V = 0, index2V = 0;
888   Standard_Integer FromV1 = vknots->Lower();
889   Standard_Integer ToV2   = vknots->Upper();
890   BSplCLib::LocateParameter(vdeg,vknots->Array1(),vmults->Array1(),
891                             NewV1,vperiodic,FromV1,ToV2,index1V,V);
892   BSplCLib::LocateParameter(vdeg,vknots->Array1(),vmults->Array1(),
893                             NewV1 + deltaV,vperiodic,FromV1,ToV2,index2V,V);
894   if ( Abs(vknots->Value(index2V+1)-V) <= EpsV)
895     index2V++;
896   
897   Standard_Integer nbvknots = index2V - index1V + 1;
898
899   Handle(TColStd_HArray1OfReal) 
900     nvknots = new TColStd_HArray1OfReal(1,nbvknots);
901   Handle(TColStd_HArray1OfInteger) 
902     nvmults = new TColStd_HArray1OfInteger(1,nbvknots);
903
904   k = 1;
905   for ( i = index1V; i<= index2V; i++) {
906     nvknots->SetValue(k, vknots->Value(i));
907     nvmults->SetValue(k, vmults->Value(i));
908     k++;
909   }
910   if (segment_in_V) {
911     nvmults->SetValue(       1, vdeg + 1);
912     nvmults->SetValue(nbvknots, vdeg + 1);
913   }
914
915   // compute index1 and index2 to set the new poles and weights
916   Standard_Integer pindex1U 
917     = BSplCLib::PoleIndex(udeg,index1U,uperiodic,umults->Array1());
918   Standard_Integer pindex2U 
919     = BSplCLib::PoleIndex(udeg,index2U,uperiodic,umults->Array1());
920
921   pindex1U++;
922   pindex2U = Min( pindex2U+1, poles->ColLength());
923
924   Standard_Integer nbupoles  = pindex2U - pindex1U + 1;
925
926   // compute index1 and index2 to set the new poles and weights
927   Standard_Integer pindex1V 
928     = BSplCLib::PoleIndex(vdeg,index1V,vperiodic,vmults->Array1());
929   Standard_Integer pindex2V 
930     = BSplCLib::PoleIndex(vdeg,index2V,vperiodic,vmults->Array1());
931
932   pindex1V++;
933   pindex2V = Min( pindex2V+1, poles->RowLength());
934
935   Standard_Integer nbvpoles  = pindex2V - pindex1V + 1;
936
937
938   Handle(TColStd_HArray2OfReal) nweights; 
939
940   Handle(TColgp_HArray2OfPnt)
941     npoles = new TColgp_HArray2OfPnt(1,nbupoles,1,nbvpoles);
942
943   k = 1;
944   Standard_Integer j, l;
945   if ( urational || vrational) {
946     nweights = new TColStd_HArray2OfReal( 1,nbupoles,1,nbvpoles);
947     for ( i = pindex1U; i <= pindex2U; i++) {
948       l = 1;
949       for ( j = pindex1V; j <= pindex2V; j++) {
950         npoles->SetValue(k,l, poles->Value(i,j));
951         nweights->SetValue(k,l, weights->Value(i,j));
952         l++;
953       }
954       k++;
955     }
956   }
957   else {
958     for ( i = pindex1U; i <= pindex2U; i++) {
959       l = 1;
960       for ( j = pindex1V; j <= pindex2V; j++) {
961         npoles->SetValue(k,l, poles->Value(i,j));
962         l++;
963       }
964       k++;
965     }
966   }
967
968   uknots = nuknots;
969   umults = numults;
970   vknots = nvknots;
971   vmults = nvmults;
972   poles = npoles;
973   if ( urational || vrational) 
974     weights = nweights;
975   else 
976     weights = new TColStd_HArray2OfReal (1,poles->ColLength(),
977                                          1,poles->RowLength(), 1.0);
978
979   maxderivinvok = 0;
980   UpdateUKnots();
981   UpdateVKnots();
982
983 }
984
985 //=======================================================================
986 //function : SetUKnot
987 //purpose  : 
988 //=======================================================================
989
990 void Geom_BSplineSurface::SetUKnot
991 (const Standard_Integer UIndex,
992  const Standard_Real    K      )
993 {
994   if (UIndex < 1 || UIndex > uknots->Length()) Standard_OutOfRange::Raise();
995
996   Standard_Integer NewIndex = UIndex;
997   Standard_Real DU = Abs(Epsilon (K));
998   if (UIndex == 1) {
999     if (K >= uknots->Value (2) - DU) Standard_ConstructionError::Raise();
1000   }
1001   else if (UIndex == uknots->Length()) {
1002     if (K <= uknots->Value (uknots->Length()-1) + DU)  {
1003       Standard_ConstructionError::Raise();
1004     }
1005   }
1006   else {
1007     if (K <= uknots->Value (NewIndex-1) + DU || 
1008         K >= uknots->Value (NewIndex+1) - DU ) { 
1009       Standard_ConstructionError::Raise();
1010     } 
1011   }
1012   
1013   if (K != uknots->Value (NewIndex)) {
1014     uknots->SetValue (NewIndex, K);
1015     maxderivinvok = 0;
1016     UpdateUKnots();
1017   }
1018 }
1019
1020 //=======================================================================
1021 //function : SetUKnots
1022 //purpose  : 
1023 //=======================================================================
1024
1025 void Geom_BSplineSurface::SetUKnots (const TColStd_Array1OfReal& UK) {
1026
1027   Standard_Integer Lower = UK.Lower();
1028   Standard_Integer Upper = UK.Upper();
1029   if (Lower < 1 || Lower > uknots->Length() ||
1030       Upper < 1 || Upper > uknots->Length() ) {
1031     Standard_OutOfRange::Raise();
1032   }
1033   Standard_Real Eps;
1034   if (Lower > 1) {
1035     Eps = Abs (Epsilon (uknots->Value (Lower-1)));
1036     if (Abs (UK (Lower) - uknots->Value (Lower-1)) <= gp::Resolution()) {
1037       Standard_ConstructionError::Raise();
1038     }
1039   }
1040   if (Upper < uknots->Length ()) {
1041     Eps = Abs (Epsilon (uknots->Value (Upper+1)));
1042     if (Abs (UK (Upper) - uknots->Value (Upper+1)) <= gp::Resolution()) {
1043       Standard_ConstructionError::Raise();
1044     }
1045   }
1046   Standard_Real K1 = UK (Lower);
1047   for (Standard_Integer i = Lower; i <= Upper; i++) {
1048     uknots->SetValue (i, UK(i));
1049     if (i != Lower) {
1050       Eps = Abs (Epsilon (K1));
1051       if (Abs (UK(i) - K1) <= gp::Resolution()) {
1052         Standard_ConstructionError::Raise();
1053       }
1054       K1 = UK (i);
1055     }
1056   }
1057
1058   maxderivinvok = 0;
1059   UpdateUKnots();
1060 }
1061
1062 //=======================================================================
1063 //function : SetUKnot
1064 //purpose  : 
1065 //=======================================================================
1066
1067 void Geom_BSplineSurface::SetUKnot
1068 (const Standard_Integer UIndex,
1069  const Standard_Real    K,
1070  const Standard_Integer M)
1071 {
1072   IncreaseUMultiplicity (UIndex, M);
1073   SetUKnot (UIndex, K);
1074 }
1075
1076 //=======================================================================
1077 //function : SetVKnot
1078 //purpose  : 
1079 //=======================================================================
1080
1081 void Geom_BSplineSurface::SetVKnot
1082 (const Standard_Integer VIndex,
1083  const Standard_Real    K)
1084 {
1085   if (VIndex < 1 || VIndex > vknots->Length())  Standard_OutOfRange::Raise();
1086   Standard_Integer NewIndex = VIndex + vknots->Lower() - 1;
1087   Standard_Real DV = Abs(Epsilon (K));
1088   if (VIndex == 1) {
1089     if (K >=  vknots->Value (2) - DV) {
1090       Standard_ConstructionError::Raise();
1091     }
1092   }
1093   else if (VIndex == vknots->Length()) {
1094     if (K <= vknots->Value (vknots->Length()-1) + DV)  {
1095       Standard_ConstructionError::Raise();
1096     }
1097   }
1098   else {
1099     if (K <= vknots->Value (NewIndex-1) + DV || 
1100         K >= vknots->Value (NewIndex+1) - DV ) { 
1101       Standard_ConstructionError::Raise();
1102     } 
1103   }
1104   
1105   maxderivinvok = 0;
1106   UpdateVKnots();
1107 }
1108
1109 //=======================================================================
1110 //function : SetVKnots
1111 //purpose  : 
1112 //=======================================================================
1113
1114 void Geom_BSplineSurface::SetVKnots (const TColStd_Array1OfReal& VK) {
1115
1116   Standard_Integer Lower = VK.Lower();
1117   Standard_Integer Upper = VK.Upper();
1118   if (Lower < 1 || Lower > vknots->Length() ||
1119       Upper < 1 || Upper > vknots->Length() ) {
1120     Standard_OutOfRange::Raise();
1121   }
1122   Standard_Real Eps;
1123   if (Lower > 1) {
1124     Eps = Abs (Epsilon (vknots->Value (Lower-1)));
1125     if (Abs (VK (Lower) - vknots->Value (Lower-1)) <= gp::Resolution()) {
1126       Standard_ConstructionError::Raise();
1127     }
1128   }
1129   if (Upper < vknots->Length ()) {
1130     Eps = Abs (Epsilon (vknots->Value (Upper+1)));
1131     if (Abs (VK (Upper) - vknots->Value (Upper+1)) <= gp::Resolution()) {
1132       Standard_ConstructionError::Raise();
1133     }
1134   }
1135   Standard_Real K1 = VK (Lower);
1136   for (Standard_Integer i = Lower; i <= Upper; i++) {
1137     vknots->SetValue (i, VK(i));
1138     if (i != Lower) {
1139       Eps = Abs (Epsilon (K1));
1140       if (Abs (VK(i) - K1) <= gp::Resolution()) {
1141         Standard_ConstructionError::Raise();
1142       }
1143       K1 = VK (i);
1144     }
1145   }
1146
1147   maxderivinvok = 0;
1148   UpdateVKnots();
1149 }
1150
1151 //=======================================================================
1152 //function : SetVKnot
1153 //purpose  : 
1154 //=======================================================================
1155
1156 void Geom_BSplineSurface::SetVKnot
1157 (const Standard_Integer VIndex,
1158  const Standard_Real    K,
1159  const Standard_Integer M)
1160 {
1161   IncreaseVMultiplicity (VIndex, M);
1162   SetVKnot (VIndex, K);
1163 }
1164
1165 //=======================================================================
1166 //function : InsertUKnot
1167 //purpose  : 
1168 //=======================================================================
1169
1170 void Geom_BSplineSurface::InsertUKnot
1171 (const Standard_Real    U,
1172  const Standard_Integer M,
1173  const Standard_Real    ParametricTolerance,
1174  const Standard_Boolean Add)
1175 {
1176   TColStd_Array1OfReal k(1,1);
1177   k(1) = U;
1178   TColStd_Array1OfInteger m(1,1);
1179   m(1) = M;
1180   InsertUKnots(k,m,ParametricTolerance,Add);
1181 }
1182
1183 //=======================================================================
1184 //function : InsertVKnot
1185 //purpose  : 
1186 //=======================================================================
1187
1188 void Geom_BSplineSurface::InsertVKnot
1189 (const Standard_Real    V,
1190  const Standard_Integer M,
1191  const Standard_Real    ParametricTolerance,
1192  const Standard_Boolean Add)
1193 {
1194   TColStd_Array1OfReal k(1,1);
1195   k(1) = V;
1196   TColStd_Array1OfInteger m(1,1);
1197   m(1) = M;
1198   InsertVKnots(k,m,ParametricTolerance,Add);
1199 }
1200
1201 //=======================================================================
1202 //function : IncrementUMultiplicity
1203 //purpose  : 
1204 //=======================================================================
1205
1206 void  Geom_BSplineSurface::IncrementUMultiplicity
1207 (const Standard_Integer FromI1,
1208  const Standard_Integer ToI2,
1209  const Standard_Integer Step)
1210 {
1211   Handle(TColStd_HArray1OfReal) tk = uknots;
1212   TColStd_Array1OfReal k( (uknots->Array1())(FromI1), FromI1, ToI2);
1213   TColStd_Array1OfInteger m( FromI1, ToI2) ;
1214   m.Init(Step);
1215   InsertUKnots( k, m, Epsilon(1.));
1216 }
1217
1218 //=======================================================================
1219 //function : IncrementVMultiplicity
1220 //purpose  : 
1221 //=======================================================================
1222
1223 void  Geom_BSplineSurface::IncrementVMultiplicity
1224 (const Standard_Integer FromI1,
1225  const Standard_Integer ToI2,
1226  const Standard_Integer Step)
1227 {
1228   Handle(TColStd_HArray1OfReal) tk = vknots;
1229   TColStd_Array1OfReal k( (vknots->Array1())(FromI1), FromI1, ToI2);
1230
1231   TColStd_Array1OfInteger m( FromI1, ToI2) ;
1232   m.Init(Step);
1233   
1234   InsertVKnots( k, m, Epsilon(1.));
1235 }
1236
1237 //=======================================================================
1238 //function : UpdateUKnots
1239 //purpose  : 
1240 //=======================================================================
1241
1242 void Geom_BSplineSurface::UpdateUKnots()
1243 {
1244
1245   Standard_Integer MaxKnotMult = 0;
1246   BSplCLib::KnotAnalysis (udeg, uperiodic,
1247                 uknots->Array1(), 
1248                 umults->Array1(), 
1249                 uknotSet, MaxKnotMult);
1250   
1251   if (uknotSet == GeomAbs_Uniform && !uperiodic)  {
1252     ufknots = uknots;
1253   }
1254   else {
1255     ufknots = new TColStd_HArray1OfReal 
1256       (1, BSplCLib::KnotSequenceLength(umults->Array1(),udeg,uperiodic));
1257
1258     BSplCLib::KnotSequence (uknots->Array1(), 
1259                             umults->Array1(),
1260                             udeg,uperiodic,
1261                             ufknots->ChangeArray1());
1262   }
1263   
1264   if (MaxKnotMult == 0)  Usmooth = GeomAbs_CN;
1265   else {
1266     switch (udeg - MaxKnotMult) {
1267     case 0 :   Usmooth = GeomAbs_C0;   break;
1268     case 1 :   Usmooth = GeomAbs_C1;   break;
1269     case 2 :   Usmooth = GeomAbs_C2;   break;
1270     case 3 :   Usmooth = GeomAbs_C3;   break;
1271       default :  Usmooth = GeomAbs_C3;   break;
1272     }
1273   }
1274
1275   InvalidateCache() ;
1276 }
1277
1278 //=======================================================================
1279 //function : UpdateVKnots
1280 //purpose  : 
1281 //=======================================================================
1282
1283 void Geom_BSplineSurface::UpdateVKnots()
1284 {
1285   Standard_Integer MaxKnotMult = 0;
1286   BSplCLib::KnotAnalysis (vdeg, vperiodic,
1287                 vknots->Array1(), 
1288                 vmults->Array1(), 
1289                 vknotSet, MaxKnotMult);
1290   
1291   if (vknotSet == GeomAbs_Uniform && !vperiodic)  {
1292     vfknots = vknots;
1293   }
1294   else {
1295     vfknots = new TColStd_HArray1OfReal 
1296       (1, BSplCLib::KnotSequenceLength(vmults->Array1(),vdeg,vperiodic));
1297
1298     BSplCLib::KnotSequence (vknots->Array1(), 
1299                             vmults->Array1(),
1300                             vdeg,vperiodic,
1301                             vfknots->ChangeArray1());
1302   }
1303   
1304   if (MaxKnotMult == 0)  Vsmooth = GeomAbs_CN;
1305   else {
1306     switch (vdeg - MaxKnotMult) {
1307     case 0 :   Vsmooth = GeomAbs_C0;   break;
1308     case 1 :   Vsmooth = GeomAbs_C1;   break;
1309     case 2 :   Vsmooth = GeomAbs_C2;   break;
1310     case 3 :   Vsmooth = GeomAbs_C3;   break;
1311       default :  Vsmooth = GeomAbs_C3;   break;
1312     }
1313   }
1314   InvalidateCache() ;
1315 }
1316
1317 //=======================================================================
1318 //function :  InvalidateCache
1319 //purpose  : Invalidates the Cache of the surface
1320 //=======================================================================
1321
1322 void Geom_BSplineSurface::InvalidateCache()
1323 {
1324   validcache = 0 ;
1325 }
1326
1327 //=======================================================================
1328 //function : Normalizes the parameters if the curve is periodic
1329 //purpose  : that is compute the cache so that it is valid
1330 //=======================================================================
1331
1332 void Geom_BSplineSurface::PeriodicNormalization
1333 (Standard_Real&  Uparameter, 
1334  Standard_Real&  Vparameter) const 
1335 {
1336   Standard_Real Period, aMaxVal, aMinVal;
1337   
1338   if (uperiodic) {
1339     aMaxVal = ufknots->Value(ufknots->Upper() - udeg);
1340     aMinVal = ufknots->Value (udeg + 1);
1341     Standard_Real eps = Abs(Epsilon(Uparameter));
1342     Period =  aMaxVal - aMinVal;
1343
1344     if(Period <= eps) 
1345       Standard_OutOfRange::Raise("Geom_BSplineSurface::PeriodicNormalization: Uparameter is too great number");
1346
1347     while (Uparameter > aMaxVal) {
1348       Uparameter -= Period ;
1349     }
1350       
1351     while (Uparameter < aMinVal) {
1352       Uparameter +=  Period ;
1353     }
1354   }
1355   if (vperiodic) {
1356     aMaxVal = vfknots->Value(vfknots->Upper() - vdeg);
1357     aMinVal = vfknots->Value (vdeg + 1);
1358     Standard_Real eps = Abs(Epsilon(Vparameter));
1359     Period = aMaxVal - aMinVal;
1360
1361     if(Period <= eps) 
1362       Standard_OutOfRange::Raise("Geom_BSplineSurface::PeriodicNormalization: Vparameter is too great number");
1363
1364     while (Vparameter > aMaxVal) {
1365       Vparameter -= Period ;
1366     }
1367     while (Vparameter < aMinVal) {
1368       Vparameter +=  Period ;
1369     }
1370   }
1371 }
1372
1373 //=======================================================================
1374 //function : ValidateCache
1375 //purpose  : function that validates the cache of the surface
1376 //=======================================================================
1377
1378 void Geom_BSplineSurface::ValidateCache(const Standard_Real  Uparameter,
1379                                         const Standard_Real  Vparameter) 
1380 {
1381   Standard_Real NewParameter  ;
1382   Standard_Integer LocalIndex = 0  ;
1383   Standard_Integer MinDegree,
1384   MaxDegree ;
1385   //
1386   // check if the degree did not change
1387   //
1388
1389   MinDegree = Min(udeg,vdeg) ;
1390   MaxDegree = Max(udeg,vdeg) ;
1391   if (cachepoles->ColLength() < MaxDegree + 1 ||
1392       cachepoles->RowLength() < MinDegree + 1) {
1393     cachepoles = new TColgp_HArray2OfPnt(1,MaxDegree + 1,
1394                                          1,MinDegree + 1);
1395   }
1396   //
1397   // Verif + poussee pour les poids
1398   //
1399   if (urational || vrational) {
1400     if (cacheweights.IsNull()) {
1401       cacheweights  = new TColStd_HArray2OfReal(1,MaxDegree + 1,
1402                                                 1,MinDegree + 1);
1403     }
1404     else {
1405       if (cacheweights->ColLength() < MaxDegree + 1 ||
1406           cacheweights->RowLength() < MinDegree + 1) {
1407         cacheweights  = new TColStd_HArray2OfReal(1,MaxDegree + 1,
1408                                                   1,MinDegree + 1);
1409       }
1410     }
1411   }
1412
1413   BSplCLib::LocateParameter(udeg,
1414                             (ufknots->Array1()),
1415                             (BSplCLib::NoMults()),
1416                             Uparameter,
1417                             uperiodic,
1418                             LocalIndex,
1419                             NewParameter);
1420   ucachespanindex = LocalIndex ;
1421   if (Uparameter == ufknots->Value(LocalIndex + 1)) {
1422     
1423     LocalIndex += 1 ;
1424     ucacheparameter = ufknots->Value(LocalIndex) ;
1425     if (LocalIndex == ufknots->Upper() - udeg) {
1426       //
1427       // for the last span if the parameter is outside of 
1428       // the domain of the curve than use the last knot
1429       // and normalize with the last span Still set the
1430       // cachespanindex to flatknots->Upper() - deg so that
1431       // the IsCacheValid will know for sure we are extending
1432       // the Bspline 
1433       //
1434       
1435       ucachespanlenght = ufknots->Value(LocalIndex - 1) - ucacheparameter ;
1436     }
1437     else {
1438         ucachespanlenght = ufknots->Value(LocalIndex + 1) - ucacheparameter ;
1439       }
1440   }
1441   else {
1442       ucacheparameter = ufknots->Value(LocalIndex) ;
1443       ucachespanlenght = ufknots->Value(LocalIndex + 1) - ucacheparameter ;
1444     }
1445
1446   LocalIndex = 0 ;   
1447   BSplCLib::LocateParameter(vdeg,
1448                             (vfknots->Array1()),
1449                             (BSplCLib::NoMults()),
1450                             Vparameter,
1451                             vperiodic,
1452                             LocalIndex,
1453                             NewParameter);
1454   vcachespanindex = LocalIndex ;
1455   if (Vparameter == vfknots->Value(LocalIndex + 1)) {
1456     LocalIndex += 1 ;
1457     vcacheparameter = vfknots->Value(LocalIndex) ;
1458     if (LocalIndex == vfknots->Upper() - vdeg) {
1459       //
1460       // for the last span if the parameter is outside of 
1461       // the domain of the curve than use the last knot
1462       // and normalize with the last span Still set the
1463       // cachespanindex to flatknots->Upper() - deg so that
1464       // the IsCacheValid will know for sure we are extending
1465       // the Bspline 
1466       //
1467       
1468       vcachespanlenght = vfknots->Value(LocalIndex - 1) - vcacheparameter ;
1469     }
1470     else {
1471       vcachespanlenght = vfknots->Value(LocalIndex + 1) - vcacheparameter ;
1472     }
1473   }
1474   else {
1475     vcacheparameter = vfknots->Value(LocalIndex) ;
1476     vcachespanlenght = vfknots->Value(LocalIndex + 1) - vcacheparameter ;
1477   }
1478   
1479   Standard_Real uparameter_11 = (2*ucacheparameter + ucachespanlenght)/2,
1480                 uspanlenght_11 = ucachespanlenght/2,
1481                 vparameter_11 = (2*vcacheparameter + vcachespanlenght)/2,
1482                 vspanlenght_11 = vcachespanlenght/2 ;
1483   if (urational || vrational) {
1484     BSplSLib::BuildCache(uparameter_11,
1485                          vparameter_11,
1486                          uspanlenght_11,
1487                          vspanlenght_11,
1488                          uperiodic,
1489                          vperiodic,
1490                          udeg,
1491                          vdeg,
1492                          ucachespanindex,
1493                          vcachespanindex,
1494                          (ufknots->Array1()),
1495                          (vfknots->Array1()),
1496                          poles->Array2(),
1497                          weights->Array2(),
1498                          cachepoles->ChangeArray2(),
1499                          cacheweights->ChangeArray2()) ;
1500   }
1501   else {
1502     BSplSLib::BuildCache(uparameter_11,
1503                          vparameter_11,
1504                          uspanlenght_11,
1505                          vspanlenght_11,
1506                          uperiodic,
1507                          vperiodic,
1508                          udeg,
1509                          vdeg,
1510                          ucachespanindex,
1511                          vcachespanindex,
1512                          (ufknots->Array1()),
1513                          (vfknots->Array1()),
1514                          poles->Array2(),
1515                          *((TColStd_Array2OfReal*) NULL),
1516                          cachepoles->ChangeArray2(),
1517                          *((TColStd_Array2OfReal*) NULL)) ;
1518   }
1519   validcache = 1 ;
1520 }
1521
1522 //=======================================================================
1523 //function : IsCacheValid
1524 //purpose  : function that checks for the validity of the cache of the
1525 //           surface
1526 //=======================================================================
1527 Standard_Boolean Geom_BSplineSurface::IsCacheValid
1528 (const Standard_Real  U,
1529  const Standard_Real  V)  const 
1530 {
1531   //Roman Lygin 26.12.08, see comments in Geom_BSplineCurve::IsCacheValid()
1532   Standard_Real aDeltaU = U - ucacheparameter;
1533   Standard_Real aDeltaV = V - vcacheparameter;
1534
1535   return ( validcache &&
1536       (aDeltaU >= 0.0e0) &&
1537       ((aDeltaU < ucachespanlenght) || (ucachespanindex == ufknots->Upper() - udeg)) &&
1538       (aDeltaV >= 0.0e0) &&
1539       ((aDeltaV < vcachespanlenght) || (vcachespanindex == vfknots->Upper() - vdeg)) );
1540 }
1541
1542 //=======================================================================
1543 //function : SetWeight
1544 //purpose  : 
1545 //=======================================================================
1546
1547 void Geom_BSplineSurface::SetWeight (const Standard_Integer UIndex,
1548                                      const Standard_Integer VIndex,
1549                                      const Standard_Real    Weight)
1550 {
1551   if (Weight <= gp::Resolution())  Standard_ConstructionError::Raise(); 
1552   TColStd_Array2OfReal & Weights = weights->ChangeArray2();
1553   if (UIndex < 1 || UIndex > Weights.ColLength() ||
1554       VIndex < 1 || VIndex > Weights.RowLength() ) {
1555     Standard_OutOfRange::Raise();
1556   }
1557   Weights (UIndex+Weights.LowerRow()-1, VIndex+Weights.LowerCol()-1) = Weight;
1558   Rational(Weights, urational, vrational);
1559   InvalidateCache();
1560 }
1561
1562 //=======================================================================
1563 //function : SetWeightCol
1564 //purpose  : 
1565 //=======================================================================
1566
1567 void Geom_BSplineSurface::SetWeightCol
1568 (const Standard_Integer       VIndex, 
1569  const TColStd_Array1OfReal&  CPoleWeights)
1570 {
1571   TColStd_Array2OfReal & Weights = weights->ChangeArray2();   
1572   if (VIndex < 1 || VIndex > Weights.RowLength()) {
1573     Standard_OutOfRange::Raise();
1574   }
1575   if (CPoleWeights.Lower() < 1 || 
1576       CPoleWeights.Lower() > Weights.ColLength() ||
1577       CPoleWeights.Upper() < 1 ||
1578       CPoleWeights.Upper() > Weights.ColLength()  ) {
1579     Standard_ConstructionError::Raise();
1580   }
1581   Standard_Integer I = CPoleWeights.Lower();
1582   while (I <= CPoleWeights.Upper()) {
1583     if (CPoleWeights(I) <= gp::Resolution()) { 
1584       Standard_ConstructionError::Raise();
1585     }
1586     Weights (I+Weights.LowerRow()-1, VIndex+Weights.LowerCol()-1) = 
1587       CPoleWeights (I);
1588     I++;
1589   }
1590   // Verifie si c'est rationnel
1591   Rational(Weights, urational, vrational);
1592
1593   InvalidateCache();
1594 }
1595
1596 //=======================================================================
1597 //function : SetWeightRow
1598 //purpose  : 
1599 //=======================================================================
1600
1601 void Geom_BSplineSurface::SetWeightRow
1602 (const Standard_Integer       UIndex, 
1603  const TColStd_Array1OfReal&  CPoleWeights)
1604 {
1605   TColStd_Array2OfReal & Weights = weights->ChangeArray2();   
1606   if (UIndex < 1 || UIndex > Weights.ColLength()) {
1607     Standard_OutOfRange::Raise();
1608   }
1609   if (CPoleWeights.Lower() < 1 ||
1610       CPoleWeights.Lower() > Weights.RowLength() ||
1611       CPoleWeights.Upper() < 1 ||
1612       CPoleWeights.Upper() > Weights.RowLength()  ) {
1613     
1614     Standard_ConstructionError::Raise();
1615   }
1616   Standard_Integer I = CPoleWeights.Lower();
1617
1618   while (I <= CPoleWeights.Upper()) {
1619     if (CPoleWeights(I)<=gp::Resolution()) {
1620       Standard_ConstructionError::Raise();
1621     }
1622     Weights (UIndex+Weights.LowerRow()-1, I+Weights.LowerCol()-1) = 
1623       CPoleWeights (I);
1624     I++;
1625   }
1626   // Verifie si c'est rationnel
1627   Rational(Weights, urational, vrational);
1628   InvalidateCache();
1629 }
1630