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