f4dbe4f15077aab48e2ff5860633972d444af42d
[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-2014 OPEN CASCADE SAS
5 //
6 // This file is part of Open CASCADE Technology software library.
7 //
8 // This library is free software; you can redistribute it and/or modify it under
9 // the terms of the GNU Lesser General Public License version 2.1 as published
10 // by the Free Software Foundation, with special exception defined in the file
11 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
12 // distribution for complete text of the license and disclaimer of any warranty.
13 //
14 // Alternatively, this file may be used under the terms of Open CASCADE
15 // commercial license or contractual agreement.
16
17 // 14-Mar-96 : xab  portage hp
18 // pmn : 28-Jun-96 Distinction entre la continuite en U et V (bug PRO4625)
19 // pmn : 07-Jan-97 Centralisation des verif rational (PRO6834)
20 //       et ajout des InvalideCache() dans les SetWeight*(PRO6833)
21 // RBD : 15-10-98 ; Le cache est maintenant calcule sur [-1,1] (pro15537).
22 // jct : 19-01-99 ; permutation de urational et vrational dans Rational.
23 #define No_Standard_OutOfRange
24
25
26 #include <BSplCLib.hxx>
27 #include <BSplSLib.hxx>
28 #include <Geom_BSplineSurface.hxx>
29 #include <Geom_Curve.hxx>
30 #include <Geom_Geometry.hxx>
31 #include <Geom_UndefinedDerivative.hxx>
32 #include <gp.hxx>
33 #include <gp_Pnt.hxx>
34 #include <gp_Trsf.hxx>
35 #include <gp_Vec.hxx>
36 #include <Precision.hxx>
37 #include <Standard_ConstructionError.hxx>
38 #include <Standard_DimensionError.hxx>
39 #include <Standard_DomainError.hxx>
40 #include <Standard_NoSuchObject.hxx>
41 #include <Standard_NotImplemented.hxx>
42 #include <Standard_OutOfRange.hxx>
43 #include <Standard_RangeError.hxx>
44 #include <Standard_Type.hxx>
45
46 IMPLEMENT_STANDARD_RTTIEXT(Geom_BSplineSurface,Geom_BoundedSurface)
47
48 //=======================================================================
49 //function : CheckSurfaceData
50 //purpose  : Internal use only.
51 //=======================================================================
52 static void CheckSurfaceData
53 (const TColgp_Array2OfPnt&      SPoles,
54  const TColStd_Array1OfReal&    SUKnots,
55  const TColStd_Array1OfReal&    SVKnots,
56  const TColStd_Array1OfInteger& SUMults,
57  const TColStd_Array1OfInteger& SVMults,
58  const Standard_Integer         UDegree,
59  const Standard_Integer         VDegree,
60  const Standard_Boolean         UPeriodic,
61  const Standard_Boolean         VPeriodic)
62 {
63   if (UDegree < 1 || UDegree > Geom_BSplineSurface::MaxDegree () || 
64       VDegree < 1 || VDegree > Geom_BSplineSurface::MaxDegree ()) {
65     throw Standard_ConstructionError("Geom_BSplineSurface: invalid degree");
66   }
67   if (SPoles.ColLength () < 2 || SPoles.RowLength () < 2) {
68     throw Standard_ConstructionError("Geom_BSplineSurface: at least 2 poles required");
69   }
70
71   if (SUKnots.Length() != SUMults.Length() ||
72       SVKnots.Length() != SVMults.Length()) {
73     throw Standard_ConstructionError("Geom_BSplineSurface: Knot and Mult array size mismatch");
74   }
75
76   Standard_Integer i;
77   for (i = SUKnots.Lower(); i < SUKnots.Upper(); i++) {
78     if (SUKnots(i+1) - SUKnots(i) <= Epsilon(Abs(SUKnots(i)))) {
79       throw Standard_ConstructionError("Geom_BSplineSurface: UKnots interval values too close");
80     }
81   }
82
83   for (i = SVKnots.Lower(); i < SVKnots.Upper(); i++) {
84     if (SVKnots(i+1) - SVKnots(i) <= Epsilon(Abs(SVKnots(i)))) {
85       throw Standard_ConstructionError("Geom_BSplineSurface: VKnots interval values too close");
86     }
87   }
88   
89   if (SPoles.ColLength() != BSplCLib::NbPoles(UDegree,UPeriodic,SUMults))
90     throw Standard_ConstructionError("Geom_BSplineSurface: # U Poles and degree mismatch");
91
92   if (SPoles.RowLength() != BSplCLib::NbPoles(VDegree,VPeriodic,SVMults))
93     throw Standard_ConstructionError("Geom_BSplineSurface: # V Poles and degree mismatch");
94 }
95
96 //=======================================================================
97 //function : Rational
98 //purpose  : Internal use only.
99 //=======================================================================
100
101 static void Rational(const TColStd_Array2OfReal& Weights,
102                      Standard_Boolean& Urational,
103                      Standard_Boolean& Vrational)
104 {
105   Standard_Integer I,J;
106   J = Weights.LowerCol ();
107   Vrational = Standard_False;
108   while (!Vrational && J <= Weights.UpperCol()) {
109     I = Weights.LowerRow();
110     while (!Vrational && I <= Weights.UpperRow() - 1) {
111       Vrational = (Abs(Weights (I, J) - Weights (I+1, J)) 
112                    > Epsilon (Abs(Weights (I, J))));
113       I++;
114     }
115     J++;
116   }
117
118   I = Weights.LowerRow ();
119   Urational = Standard_False;
120   while (!Urational && I <= Weights.UpperRow()) {
121     J = Weights.LowerCol();
122     while (!Urational && J <= Weights.UpperCol() - 1) {
123       Urational = (Abs(Weights (I, J) - Weights (I, J+1))
124                    > Epsilon (Abs(Weights (I, J))));
125       J++;
126     }
127     I++;
128   }
129 }
130
131 //=======================================================================
132 //function : Copy
133 //purpose  : 
134 //=======================================================================
135
136 Handle(Geom_Geometry) Geom_BSplineSurface::Copy () const
137 {
138   Handle(Geom_BSplineSurface) S;
139   if (urational || vrational) 
140     S = new Geom_BSplineSurface (poles->Array2() , weights->Array2(), 
141                                  uknots->Array1(), vknots->Array1(), 
142                                  umults->Array1(), vmults->Array1(), 
143                                  udeg     , vdeg, 
144                                  uperiodic, vperiodic);
145   else
146     S = new Geom_BSplineSurface (poles->Array2(),
147                                  uknots->Array1(), vknots->Array1(), 
148                                  umults->Array1(), vmults->Array1(), 
149                                  udeg     , vdeg, 
150                                  uperiodic, vperiodic);
151   return S;
152 }
153
154 //=======================================================================
155 //function : Geom_BSplineSurface
156 //purpose  : 
157 //=======================================================================
158
159 Geom_BSplineSurface::Geom_BSplineSurface
160 (const TColgp_Array2OfPnt&      Poles, 
161  const TColStd_Array1OfReal&    UKnots, 
162  const TColStd_Array1OfReal&    VKnots,
163  const TColStd_Array1OfInteger& UMults, 
164  const TColStd_Array1OfInteger& VMults,
165  const Standard_Integer         UDegree, 
166  const Standard_Integer         VDegree,
167  const Standard_Boolean         UPeriodic,
168  const Standard_Boolean         VPeriodic
169  ) :
170  urational(Standard_False),
171  vrational(Standard_False),
172  uperiodic(UPeriodic),
173  vperiodic(VPeriodic),
174  udeg(UDegree),
175  vdeg(VDegree),
176  maxderivinvok(0)
177
178 {
179
180   // check
181   
182   CheckSurfaceData(Poles,
183                    UKnots   , VKnots,
184                    UMults   , VMults,
185                    UDegree  , VDegree,
186                    UPeriodic, VPeriodic);
187
188   // copy arrays
189
190   poles   = new TColgp_HArray2OfPnt(1,Poles.ColLength(),
191                                     1,Poles.RowLength());
192   poles->ChangeArray2() = Poles;
193
194   weights = new TColStd_HArray2OfReal (1,Poles.ColLength(),
195                                        1,Poles.RowLength(), 1.0);
196
197   uknots  = new TColStd_HArray1OfReal    (1,UKnots.Length());
198   uknots->ChangeArray1() = UKnots;
199
200   umults  = new TColStd_HArray1OfInteger (1,UMults.Length());
201   umults->ChangeArray1() = UMults;
202
203   vknots  = new TColStd_HArray1OfReal    (1,VKnots.Length());
204   vknots->ChangeArray1() = VKnots;
205
206   vmults  = new TColStd_HArray1OfInteger (1,VMults.Length());
207   vmults->ChangeArray1() = VMults;
208
209   UpdateUKnots();
210   UpdateVKnots();
211 }
212
213 //=======================================================================
214 //function : Geom_BSplineSurface
215 //purpose  : 
216 //=======================================================================
217
218 Geom_BSplineSurface::Geom_BSplineSurface
219 (const TColgp_Array2OfPnt&      Poles,
220  const TColStd_Array2OfReal&    Weights,
221  const TColStd_Array1OfReal&    UKnots,
222  const TColStd_Array1OfReal&    VKnots,
223  const TColStd_Array1OfInteger& UMults, 
224  const TColStd_Array1OfInteger& VMults,
225  const Standard_Integer         UDegree,
226  const Standard_Integer         VDegree,
227  const Standard_Boolean         UPeriodic,
228  const Standard_Boolean         VPeriodic) :
229  urational(Standard_False),
230  vrational(Standard_False),
231  uperiodic(UPeriodic),
232  vperiodic(VPeriodic),
233  udeg(UDegree),
234  vdeg(VDegree),
235  maxderivinvok(0)
236 {
237   // check weights
238
239   if (Weights.ColLength() != Poles.ColLength())
240     throw Standard_ConstructionError("Geom_BSplineSurface: U Weights and Poles array size mismatch");
241
242   if (Weights.RowLength() != Poles.RowLength())
243     throw Standard_ConstructionError("Geom_BSplineSurface: V Weights and Poles array size mismatch");
244
245   Standard_Integer i,j;
246   for (i = Weights.LowerRow(); i <= Weights.UpperRow(); i++) {
247     for (j = Weights.LowerCol(); j <= Weights.UpperCol(); j++) {
248       if (Weights(i,j) <= gp::Resolution())  
249         throw Standard_ConstructionError("Geom_BSplineSurface: Weights values too small");
250     }
251   }
252   
253   // check really rational
254   
255   Rational(Weights, urational, vrational);
256
257   // check
258   
259   CheckSurfaceData(Poles,
260                    UKnots   , VKnots,
261                    UMults   , VMults,
262                    UDegree  , VDegree,
263                    UPeriodic, VPeriodic);
264
265   // copy arrays
266
267   poles   = new TColgp_HArray2OfPnt(1,Poles.ColLength(),
268                                     1,Poles.RowLength());
269   poles->ChangeArray2() = Poles;
270
271   weights = new TColStd_HArray2OfReal (1,Poles.ColLength(),
272                                        1,Poles.RowLength());
273   weights->ChangeArray2() = Weights;
274
275   uknots  = new TColStd_HArray1OfReal    (1,UKnots.Length());
276   uknots->ChangeArray1() = UKnots;
277
278   umults  = new TColStd_HArray1OfInteger (1,UMults.Length());
279   umults->ChangeArray1() = UMults;
280
281   vknots  = new TColStd_HArray1OfReal    (1,VKnots.Length());
282   vknots->ChangeArray1() = VKnots;
283
284   vmults  = new TColStd_HArray1OfInteger (1,VMults.Length());
285   vmults->ChangeArray1() = VMults;
286
287   UpdateUKnots();
288   UpdateVKnots();
289 }
290
291 //=======================================================================
292 //function : ExchangeUV
293 //purpose  : 
294 //=======================================================================
295
296 void Geom_BSplineSurface::ExchangeUV ()
297 {
298   Standard_Integer LC = poles->LowerCol();
299   Standard_Integer UC = poles->UpperCol();
300   Standard_Integer LR = poles->LowerRow();
301   Standard_Integer UR = poles->UpperRow();
302
303   Handle(TColgp_HArray2OfPnt)   npoles   = 
304     new TColgp_HArray2OfPnt  (LC, UC, LR, UR);
305   Handle(TColStd_HArray2OfReal) nweights = 
306     new TColStd_HArray2OfReal (LC, UC, LR, UR);
307
308   const TColgp_Array2OfPnt   & spoles   = poles->Array2();
309   const TColStd_Array2OfReal & sweights = weights->Array2();
310   
311   TColgp_Array2OfPnt&   snpoles   = npoles->ChangeArray2();
312   TColStd_Array2OfReal& snweights = nweights->ChangeArray2();
313   
314   Standard_Integer i, j;
315   for (i = LC; i <= UC; i++) {
316     for (j = LR; j <= UR; j++) {
317       snpoles   (i,j) = spoles   (j,i);
318       snweights (i,j) = sweights (j,i);
319     }
320   }
321
322   poles   = npoles;
323   weights = nweights;
324
325   Standard_Boolean temp = urational;
326   urational = vrational;
327   vrational = temp;
328
329   temp = uperiodic;
330   uperiodic = vperiodic;
331   vperiodic = temp;
332
333   Standard_Integer tempdeg = udeg;
334   udeg = vdeg;
335   vdeg = tempdeg;
336   
337
338   Handle(TColStd_HArray1OfReal) tempknots = uknots;
339   uknots = vknots;
340   vknots = tempknots;
341
342   Handle(TColStd_HArray1OfInteger) tempmults = umults;
343   umults = vmults;
344   vmults = tempmults;
345
346   UpdateUKnots();
347   UpdateVKnots();
348 }
349
350 //=======================================================================
351 //function : IncreaseDegree
352 //purpose  : 
353 //=======================================================================
354
355 void Geom_BSplineSurface::IncreaseDegree (const Standard_Integer UDegree,
356                                           const Standard_Integer VDegree)
357
358   if (UDegree != udeg) {
359     if ( UDegree < udeg || UDegree > Geom_BSplineSurface::MaxDegree())
360       throw Standard_ConstructionError("Geom_BSplineSurface::IncreaseDegree: bad U degree value");
361     
362     Standard_Integer FromK1 = FirstUKnotIndex();
363     Standard_Integer ToK2   = LastUKnotIndex();
364
365     Standard_Integer Step   = UDegree - udeg;
366
367     Handle(TColgp_HArray2OfPnt) npoles = new
368       TColgp_HArray2OfPnt( 1, poles->ColLength() + Step * (ToK2 - FromK1),
369                           1, poles->RowLength());
370
371     Standard_Integer nbknots = BSplCLib::IncreaseDegreeCountKnots
372       (udeg,UDegree,uperiodic,umults->Array1());
373
374     Handle(TColStd_HArray1OfReal) nknots = 
375       new TColStd_HArray1OfReal(1,nbknots);
376     
377     Handle(TColStd_HArray1OfInteger) nmults = 
378       new TColStd_HArray1OfInteger(1,nbknots);
379
380     Handle(TColStd_HArray2OfReal) nweights 
381       = new TColStd_HArray2OfReal(1,npoles->ColLength(),
382                                   1,npoles->RowLength(), 1.);
383
384     if (urational || vrational) {
385       
386       BSplSLib::IncreaseDegree
387         (Standard_True, udeg, UDegree, uperiodic,
388          poles->Array2(),&weights->Array2(),
389          uknots->Array1(),umults->Array1(),
390          npoles->ChangeArray2(),&nweights->ChangeArray2(),
391          nknots->ChangeArray1(),nmults->ChangeArray1());
392     }
393     else {
394
395       BSplSLib::IncreaseDegree
396         (Standard_True, udeg, UDegree, uperiodic,
397          poles->Array2(),BSplSLib::NoWeights(),
398          uknots->Array1(),umults->Array1(),
399          npoles->ChangeArray2(),BSplSLib::NoWeights(),
400          nknots->ChangeArray1(),nmults->ChangeArray1());
401     }
402     udeg    = UDegree;
403     poles   = npoles;
404     weights = nweights;
405     uknots  = nknots;
406     umults  = nmults;
407     UpdateUKnots();
408   }
409
410   if (VDegree != vdeg) {
411     if ( VDegree < vdeg || VDegree > Geom_BSplineSurface::MaxDegree())
412       throw Standard_ConstructionError("Geom_BSplineSurface::IncreaseDegree: bad V degree value");
413     
414     Standard_Integer FromK1 = FirstVKnotIndex();
415     Standard_Integer ToK2   = LastVKnotIndex();
416
417     Standard_Integer Step   = VDegree - vdeg;
418
419     Handle(TColgp_HArray2OfPnt) npoles = new
420       TColgp_HArray2OfPnt( 1, poles->ColLength(),
421                           1, poles->RowLength() + Step * (ToK2 - FromK1));
422
423     Standard_Integer nbknots = BSplCLib::IncreaseDegreeCountKnots
424       (vdeg,VDegree,vperiodic,vmults->Array1());
425
426     Handle(TColStd_HArray1OfReal) nknots = 
427       new TColStd_HArray1OfReal(1,nbknots);
428     
429     Handle(TColStd_HArray1OfInteger) nmults = 
430       new TColStd_HArray1OfInteger(1,nbknots);
431
432     Handle(TColStd_HArray2OfReal) nweights
433       = new TColStd_HArray2OfReal(1,npoles->ColLength(),
434                                   1,npoles->RowLength(), 1.);
435
436     if (urational || vrational) {
437       
438       BSplSLib::IncreaseDegree
439         (Standard_False, vdeg, VDegree, vperiodic,
440          poles->Array2(),&weights->Array2(),
441          vknots->Array1(),vmults->Array1(),
442          npoles->ChangeArray2(),&nweights->ChangeArray2(),
443          nknots->ChangeArray1(),nmults->ChangeArray1());
444     }
445     else {
446
447       BSplSLib::IncreaseDegree
448         (Standard_False, vdeg, VDegree, vperiodic,
449          poles->Array2(),BSplSLib::NoWeights(),
450          vknots->Array1(),vmults->Array1(),
451          npoles->ChangeArray2(),BSplSLib::NoWeights(),
452          nknots->ChangeArray1(),nmults->ChangeArray1());
453     }
454     vdeg    = VDegree;
455     poles   = npoles;
456     weights = nweights;
457     vknots  = nknots;
458     vmults  = nmults;
459     UpdateVKnots();
460   }
461 }
462
463 //=======================================================================
464 //function : IncreaseUMultiplicity
465 //purpose  : 
466 //=======================================================================
467
468 void Geom_BSplineSurface::IncreaseUMultiplicity
469 (const Standard_Integer UIndex, 
470  const Standard_Integer M)
471 {
472   TColStd_Array1OfReal k(1,1);
473   k(1) = uknots->Value(UIndex);
474   TColStd_Array1OfInteger m(1,1);
475   m(1) = M - umults->Value(UIndex);
476   InsertUKnots(k,m,Epsilon(1.),Standard_True);
477 }
478
479 //=======================================================================
480 //function : IncreaseUMultiplicity
481 //purpose  : 
482 //=======================================================================
483
484 void Geom_BSplineSurface::IncreaseUMultiplicity
485 (const Standard_Integer FromI1, 
486  const Standard_Integer ToI2,
487  const Standard_Integer M)
488 {
489   Handle(TColStd_HArray1OfReal) tk = uknots;
490   TColStd_Array1OfReal k((uknots->Array1())(FromI1),FromI1,ToI2);
491   TColStd_Array1OfInteger m(FromI1, ToI2);
492   for (Standard_Integer i = FromI1; i <= ToI2; i++) 
493     m(i) = M - umults->Value(i);
494   InsertUKnots(k,m,Epsilon(1.),Standard_True);
495 }
496
497 //=======================================================================
498 //function : IncreaseVMultiplicity
499 //purpose  : 
500 //=======================================================================
501
502 void Geom_BSplineSurface::IncreaseVMultiplicity
503 (const Standard_Integer VIndex, 
504  const Standard_Integer M)
505 {
506   TColStd_Array1OfReal k(1,1);
507   k(1) = vknots->Value(VIndex);
508   TColStd_Array1OfInteger m(1,1);
509   m(1) = M - vmults->Value(VIndex);
510   InsertVKnots(k,m,Epsilon(1.),Standard_True);
511 }
512
513 //=======================================================================
514 //function : IncreaseVMultiplicity
515 //purpose  : 
516 //=======================================================================
517
518 void Geom_BSplineSurface::IncreaseVMultiplicity
519 (const Standard_Integer FromI1,
520  const Standard_Integer ToI2,
521  const Standard_Integer M)
522 {
523   Handle(TColStd_HArray1OfReal) tk = vknots;
524   TColStd_Array1OfReal k((vknots->Array1())(FromI1),FromI1,ToI2);
525   TColStd_Array1OfInteger m(FromI1,ToI2);
526   for (Standard_Integer i = FromI1; i <= ToI2; i++)
527     m(i) = M - vmults->Value(i);
528   InsertVKnots(k,m,Epsilon(1.),Standard_True);
529 }
530
531 //=======================================================================
532 //function : segment
533 //purpose  : 
534 //=======================================================================
535
536 void Geom_BSplineSurface::segment(const Standard_Real U1,
537                                   const Standard_Real U2,
538                                   const Standard_Real V1,
539                                   const Standard_Real V2,
540                                   const Standard_Real EpsU,
541                                   const Standard_Real EpsV,
542                                   const Standard_Boolean SegmentInU,
543                                   const Standard_Boolean SegmentInV)
544 {
545   Standard_Real deltaU = U2 - U1;
546   if (uperiodic) {
547     Standard_Real aUPeriod = uknots->Last() - uknots->First();
548     if (deltaU - aUPeriod > Precision::PConfusion())
549       throw Standard_DomainError("Geom_BSplineSurface::Segment");
550     if (deltaU > aUPeriod)
551       deltaU = aUPeriod;
552   }
553
554   Standard_Real deltaV = V2 - V1;
555   if (vperiodic) {
556     Standard_Real aVPeriod = vknots->Last() - vknots->First();
557     if (deltaV - aVPeriod > Precision::PConfusion())
558       throw Standard_DomainError("Geom_BSplineSurface::Segment");
559     if (deltaV > aVPeriod)
560       deltaV = aVPeriod;
561   }
562
563   Standard_Real NewU1, NewU2, NewV1, NewV2;
564   Standard_Real U, V;
565   Standard_Integer indexU, indexV;
566
567   indexU = 0;
568   BSplCLib::LocateParameter(udeg, uknots->Array1(), umults->Array1(),
569                             U1, uperiodic, uknots->Lower(), uknots->Upper(),
570                             indexU, NewU1);
571   indexU = 0;
572   BSplCLib::LocateParameter(udeg, uknots->Array1(), umults->Array1(),
573                             U2, uperiodic, uknots->Lower(), uknots->Upper(),
574                             indexU, NewU2);
575   if (SegmentInU) {
576     // inserting the UKnots
577     TColStd_Array1OfReal    UKnots(1, 2);
578     TColStd_Array1OfInteger UMults(1, 2);
579     UKnots(1) = Min(NewU1, NewU2);
580     UKnots(2) = Max(NewU1, NewU2);
581     UMults(1) = UMults(2) = udeg;
582
583     InsertUKnots(UKnots, UMults, EpsU);
584   }
585
586   indexV = 0;
587   BSplCLib::LocateParameter(vdeg, vknots->Array1(), vmults->Array1(),
588                             V1, vperiodic, vknots->Lower(), vknots->Upper(),
589                             indexV, NewV1);
590   indexV = 0;
591   BSplCLib::LocateParameter(vdeg, vknots->Array1(), vmults->Array1(),
592                             V2, vperiodic, vknots->Lower(), vknots->Upper(),
593                             indexV, NewV2);
594   if (SegmentInV) {
595     // Inserting the VKnots
596     TColStd_Array1OfReal    VKnots(1, 2);
597     TColStd_Array1OfInteger VMults(1, 2);
598
599     VKnots(1) = Min(NewV1, NewV2);
600     VKnots(2) = Max(NewV1, NewV2);
601     VMults(1) = VMults(2) = vdeg;
602     InsertVKnots(VKnots, VMults, EpsV);
603   }
604
605   if (uperiodic && SegmentInU) { // set the origine at NewU1
606     Standard_Integer index = 0;
607     BSplCLib::LocateParameter(udeg, uknots->Array1(), umults->Array1(),
608       U1, uperiodic, uknots->Lower(), uknots->Upper(),
609       index, U);
610     if (Abs(uknots->Value(index + 1) - U) <= EpsU)
611       index++;
612     SetUOrigin(index);
613     SetUNotPeriodic();
614   }
615
616   // compute index1 and index2 to set the new knots and mults 
617   Standard_Integer index1U = 0, index2U = 0;
618   Standard_Integer FromU1 = uknots->Lower();
619   Standard_Integer ToU2 = uknots->Upper();
620   BSplCLib::LocateParameter(udeg, uknots->Array1(), umults->Array1(),
621                             NewU1, uperiodic, FromU1, ToU2, index1U, U);
622   BSplCLib::LocateParameter(udeg, uknots->Array1(), umults->Array1(),
623                             NewU1 + deltaU, uperiodic, FromU1, ToU2, index2U, U);
624   if (Abs(uknots->Value(index2U + 1) - U) <= EpsU)
625     index2U++;
626
627   Standard_Integer nbuknots = index2U - index1U + 1;
628
629   Handle(TColStd_HArray1OfReal)
630     nuknots = new TColStd_HArray1OfReal(1, nbuknots);
631   Handle(TColStd_HArray1OfInteger)
632     numults = new TColStd_HArray1OfInteger(1, nbuknots);
633
634   Standard_Integer i, k = 1;
635   for (i = index1U; i <= index2U; i++) {
636     nuknots->SetValue(k, uknots->Value(i));
637     numults->SetValue(k, umults->Value(i));
638     k++;
639   }
640   if (SegmentInU) {
641     numults->SetValue(1, udeg + 1);
642     numults->SetValue(nbuknots, udeg + 1);
643   }
644
645   if (vperiodic&& SegmentInV) { // set the origine at NewV1
646     Standard_Integer index = 0;
647     BSplCLib::LocateParameter(vdeg, vknots->Array1(), vmults->Array1(),
648       V1, vperiodic, vknots->Lower(), vknots->Upper(),
649       index, V);
650     if (Abs(vknots->Value(index + 1) - V) <= EpsV)
651       index++;
652     SetVOrigin(index);
653     SetVNotPeriodic();
654   }
655
656   // compute index1 and index2 to set the new knots and mults 
657   Standard_Integer index1V = 0, index2V = 0;
658   Standard_Integer FromV1 = vknots->Lower();
659   Standard_Integer ToV2 = vknots->Upper();
660   BSplCLib::LocateParameter(vdeg, vknots->Array1(), vmults->Array1(),
661                             NewV1, vperiodic, FromV1, ToV2, index1V, V);
662   BSplCLib::LocateParameter(vdeg, vknots->Array1(), vmults->Array1(),
663                             NewV1 + deltaV, vperiodic, FromV1, ToV2, index2V, V);
664   if (Abs(vknots->Value(index2V + 1) - V) <= EpsV)
665     index2V++;
666
667   Standard_Integer nbvknots = index2V - index1V + 1;
668
669   Handle(TColStd_HArray1OfReal)
670     nvknots = new TColStd_HArray1OfReal(1, nbvknots);
671   Handle(TColStd_HArray1OfInteger)
672     nvmults = new TColStd_HArray1OfInteger(1, nbvknots);
673
674   k = 1;
675   for (i = index1V; i <= index2V; i++) {
676     nvknots->SetValue(k, vknots->Value(i));
677     nvmults->SetValue(k, vmults->Value(i));
678     k++;
679   }
680   if (SegmentInV) {
681     nvmults->SetValue(1, vdeg + 1);
682     nvmults->SetValue(nbvknots, vdeg + 1);
683   }
684
685
686   // compute index1 and index2 to set the new poles and weights
687   Standard_Integer pindex1U
688     = BSplCLib::PoleIndex(udeg, index1U, uperiodic, umults->Array1());
689   Standard_Integer pindex2U
690     = BSplCLib::PoleIndex(udeg, index2U, uperiodic, umults->Array1());
691
692   pindex1U++;
693   pindex2U = Min(pindex2U + 1, poles->ColLength());
694
695   Standard_Integer nbupoles = pindex2U - pindex1U + 1;
696
697   // compute index1 and index2 to set the new poles and weights
698   Standard_Integer pindex1V
699     = BSplCLib::PoleIndex(vdeg, index1V, vperiodic, vmults->Array1());
700   Standard_Integer pindex2V
701     = BSplCLib::PoleIndex(vdeg, index2V, vperiodic, vmults->Array1());
702
703   pindex1V++;
704   pindex2V = Min(pindex2V + 1, poles->RowLength());
705
706   Standard_Integer nbvpoles = pindex2V - pindex1V + 1;
707
708
709   Handle(TColStd_HArray2OfReal) nweights;
710
711   Handle(TColgp_HArray2OfPnt)
712     npoles = new TColgp_HArray2OfPnt(1, nbupoles, 1, nbvpoles);
713   k = 1;
714   Standard_Integer j, l;
715   if (urational || vrational) {
716     nweights = new TColStd_HArray2OfReal(1, nbupoles, 1, nbvpoles);
717     for (i = pindex1U; i <= pindex2U; i++) {
718       l = 1;
719       for (j = pindex1V; j <= pindex2V; j++) {
720         npoles->SetValue(k, l, poles->Value(i, j));
721         nweights->SetValue(k, l, weights->Value(i, j));
722         l++;
723       }
724       k++;
725     }
726   }
727   else {
728     for (i = pindex1U; i <= pindex2U; i++) {
729       l = 1;
730       for (j = pindex1V; j <= pindex2V; j++) {
731         npoles->SetValue(k, l, poles->Value(i, j));
732         l++;
733       }
734       k++;
735     }
736   }
737
738   uknots = nuknots;
739   umults = numults;
740   vknots = nvknots;
741   vmults = nvmults;
742   poles = npoles;
743   if (urational || vrational)
744     weights = nweights;
745   else
746     weights = new TColStd_HArray2OfReal(1, poles->ColLength(),
747                                         1, poles->RowLength(), 1.0);
748
749   maxderivinvok = 0;
750   UpdateUKnots();
751   UpdateVKnots();
752 }
753
754 //=======================================================================
755 //function : Segment
756 //purpose  : 
757 //=======================================================================
758
759 void Geom_BSplineSurface::Segment(const Standard_Real U1, 
760                                   const Standard_Real U2,
761                                   const Standard_Real V1,
762                                   const Standard_Real V2,
763                                   const Standard_Real theUTolerance,
764                                   const Standard_Real theVTolerance)
765 {
766   if ((U2 < U1) || (V2 < V1))
767     throw Standard_DomainError("Geom_BSplineSurface::Segment");
768
769   Standard_Real aMaxU = Max(Abs(U2), Abs(U1));
770   Standard_Real EpsU = Max(Epsilon(aMaxU), theUTolerance);
771   
772   Standard_Real aMaxV = Max(Abs(V2), Abs(V1));
773   Standard_Real EpsV = Max(Epsilon(aMaxV), theVTolerance);
774
775   segment(U1, U2, V1, V2, EpsU, EpsV, Standard_True, Standard_True);
776 }
777
778 //=======================================================================
779 //function : CheckAndSegment
780 //purpose  : 
781 //=======================================================================
782
783 void Geom_BSplineSurface::CheckAndSegment(const Standard_Real U1, 
784                                           const Standard_Real U2,
785                                           const Standard_Real V1,
786                                           const Standard_Real V2,
787                                           const Standard_Real theUTolerance,
788                                           const Standard_Real theVTolerance)
789 {
790
791   if ((U2 < U1) || (V2 < V1))
792     throw Standard_DomainError("Geom_BSplineSurface::CheckAndSegment");
793
794   Standard_Real aMaxU = Max(Abs(U2), Abs(U1));
795   Standard_Real EpsU = Max(Epsilon(aMaxU), theUTolerance);
796   
797   Standard_Real aMaxV = Max(Abs(V2), Abs(V1));
798   Standard_Real EpsV = Max(Epsilon(aMaxV), theVTolerance);
799
800   Standard_Boolean segment_in_U = Standard_True;
801   Standard_Boolean segment_in_V = Standard_True;
802   segment_in_U = ( Abs(U1 - uknots->Value(uknots->Lower())) > EpsU )
803                         || ( Abs(U2 - uknots->Value(uknots->Upper())) > EpsU );
804   segment_in_V = ( Abs(V1 - vknots->Value(vknots->Lower())) > EpsV )
805                         || ( Abs(V2 - vknots->Value(vknots->Upper())) > EpsV );
806
807   segment(U1, U2, V1, V2, EpsU, EpsV, segment_in_U, segment_in_V);
808 }
809
810 //=======================================================================
811 //function : SetUKnot
812 //purpose  : 
813 //=======================================================================
814
815 void Geom_BSplineSurface::SetUKnot
816 (const Standard_Integer UIndex,
817  const Standard_Real    K      )
818 {
819   if (UIndex < 1 || UIndex > uknots->Length())
820     throw Standard_OutOfRange("Geom_BSplineSurface::SetUKnot: Index and #knots mismatch");
821
822   Standard_Integer NewIndex = UIndex;
823   Standard_Real DU = Abs(Epsilon (K));
824   if (UIndex == 1) {
825     if (K >= uknots->Value (2) - DU)
826       throw Standard_ConstructionError("Geom_BSplineSurface::SetUKnot: K out of range");
827   }
828   else if (UIndex == uknots->Length()) {
829     if (K <= uknots->Value (uknots->Length()-1) + DU)  {
830       throw Standard_ConstructionError("Geom_BSplineSurface::SetUKnot: K out of range");
831     }
832   }
833   else {
834     if (K <= uknots->Value (NewIndex-1) + DU || 
835         K >= uknots->Value (NewIndex+1) - DU ) { 
836       throw Standard_ConstructionError("Geom_BSplineSurface::SetUKnot: K out of range");
837     } 
838   }
839   
840   if (K != uknots->Value (NewIndex)) {
841     uknots->SetValue (NewIndex, K);
842     maxderivinvok = 0;
843     UpdateUKnots();
844   }
845 }
846
847 //=======================================================================
848 //function : SetUKnots
849 //purpose  : 
850 //=======================================================================
851
852 void Geom_BSplineSurface::SetUKnots (const TColStd_Array1OfReal& UK) {
853
854   Standard_Integer Lower = UK.Lower();
855   Standard_Integer Upper = UK.Upper();
856   if (Lower < 1 || Lower > uknots->Length() ||
857       Upper < 1 || Upper > uknots->Length() ) {
858     throw Standard_OutOfRange("Geom_BSplineSurface::SetUKnots: invalid array dimension");
859   }
860   if (Lower > 1) {
861     if (Abs (UK (Lower) - uknots->Value (Lower-1)) <= gp::Resolution()) {
862       throw Standard_ConstructionError("Geom_BSplineSurface::SetUKnots: invalid knot value");
863     }
864   }
865   if (Upper < uknots->Length ()) {
866     if (Abs (UK (Upper) - uknots->Value (Upper+1)) <= gp::Resolution()) {
867       throw Standard_ConstructionError("Geom_BSplineSurface::SetUKnots: invalid knot value");
868     }
869   }
870   Standard_Real K1 = UK (Lower);
871   for (Standard_Integer i = Lower; i <= Upper; i++) {
872     uknots->SetValue (i, UK(i));
873     if (i != Lower) {
874       if (Abs (UK(i) - K1) <= gp::Resolution()) {
875         throw Standard_ConstructionError("Geom_BSplineSurface::SetUKnots: invalid knot value");
876       }
877       K1 = UK (i);
878     }
879   }
880
881   maxderivinvok = 0;
882   UpdateUKnots();
883 }
884
885 //=======================================================================
886 //function : SetUKnot
887 //purpose  : 
888 //=======================================================================
889
890 void Geom_BSplineSurface::SetUKnot
891 (const Standard_Integer UIndex,
892  const Standard_Real    K,
893  const Standard_Integer M)
894 {
895   IncreaseUMultiplicity (UIndex, M);
896   SetUKnot (UIndex, K);
897 }
898
899 //=======================================================================
900 //function : SetVKnot
901 //purpose  : 
902 //=======================================================================
903
904 void Geom_BSplineSurface::SetVKnot
905 (const Standard_Integer VIndex,
906  const Standard_Real    K)
907 {
908   if (VIndex < 1 || VIndex > vknots->Length())
909     throw Standard_OutOfRange("Geom_BSplineSurface::SetVKnot: Index and #knots mismatch");
910   Standard_Integer NewIndex = VIndex + vknots->Lower() - 1;
911   Standard_Real DV = Abs(Epsilon (K));
912   if (VIndex == 1) {
913     if (K >=  vknots->Value (2) - DV) {
914       throw Standard_ConstructionError("Geom_BSplineSurface::SetVKnot: K out of range");
915     }
916   }
917   else if (VIndex == vknots->Length()) {
918     if (K <= vknots->Value (vknots->Length()-1) + DV)  {
919       throw Standard_ConstructionError("Geom_BSplineSurface::SetVKnot: K out of range");
920     }
921   }
922   else {
923     if (K <= vknots->Value (NewIndex-1) + DV || 
924         K >= vknots->Value (NewIndex+1) - DV ) { 
925       throw Standard_ConstructionError("Geom_BSplineSurface::SetVKnot: K out of range");
926     } 
927   }
928   
929   if (K != vknots->Value (NewIndex)) {
930     vknots->SetValue (NewIndex, K);
931     maxderivinvok = 0;
932     UpdateVKnots();
933   }
934 }
935
936 //=======================================================================
937 //function : SetVKnots
938 //purpose  : 
939 //=======================================================================
940
941 void Geom_BSplineSurface::SetVKnots (const TColStd_Array1OfReal& VK) {
942
943   Standard_Integer Lower = VK.Lower();
944   Standard_Integer Upper = VK.Upper();
945   if (Lower < 1 || Lower > vknots->Length() ||
946       Upper < 1 || Upper > vknots->Length() ) {
947     throw Standard_OutOfRange("Geom_BSplineSurface::SetVKnots: invalid array dimension");
948   }
949   if (Lower > 1) {
950     if (Abs (VK (Lower) - vknots->Value (Lower-1)) <= gp::Resolution()) {
951       throw Standard_ConstructionError("Geom_BSplineSurface::SetVKnots: invalid knot value");
952     }
953   }
954   if (Upper < vknots->Length ()) {
955     if (Abs (VK (Upper) - vknots->Value (Upper+1)) <= gp::Resolution()) {
956       throw Standard_ConstructionError("Geom_BSplineSurface::SetVKnots: invalid knot value");
957     }
958   }
959   Standard_Real K1 = VK (Lower);
960   for (Standard_Integer i = Lower; i <= Upper; i++) {
961     vknots->SetValue (i, VK(i));
962     if (i != Lower) {
963       if (Abs (VK(i) - K1) <= gp::Resolution()) {
964         throw Standard_ConstructionError("Geom_BSplineSurface::SetVKnots: invalid knot value");
965       }
966       K1 = VK (i);
967     }
968   }
969
970   maxderivinvok = 0;
971   UpdateVKnots();
972 }
973
974 //=======================================================================
975 //function : SetVKnot
976 //purpose  : 
977 //=======================================================================
978
979 void Geom_BSplineSurface::SetVKnot
980 (const Standard_Integer VIndex,
981  const Standard_Real    K,
982  const Standard_Integer M)
983 {
984   IncreaseVMultiplicity (VIndex, M);
985   SetVKnot (VIndex, K);
986 }
987
988 //=======================================================================
989 //function : InsertUKnot
990 //purpose  : 
991 //=======================================================================
992
993 void Geom_BSplineSurface::InsertUKnot
994 (const Standard_Real    U,
995  const Standard_Integer M,
996  const Standard_Real    ParametricTolerance,
997  const Standard_Boolean Add)
998 {
999   TColStd_Array1OfReal k(1,1);
1000   k(1) = U;
1001   TColStd_Array1OfInteger m(1,1);
1002   m(1) = M;
1003   InsertUKnots(k,m,ParametricTolerance,Add);
1004 }
1005
1006 //=======================================================================
1007 //function : InsertVKnot
1008 //purpose  : 
1009 //=======================================================================
1010
1011 void Geom_BSplineSurface::InsertVKnot
1012 (const Standard_Real    V,
1013  const Standard_Integer M,
1014  const Standard_Real    ParametricTolerance,
1015  const Standard_Boolean Add)
1016 {
1017   TColStd_Array1OfReal k(1,1);
1018   k(1) = V;
1019   TColStd_Array1OfInteger m(1,1);
1020   m(1) = M;
1021   InsertVKnots(k,m,ParametricTolerance,Add);
1022 }
1023
1024 //=======================================================================
1025 //function : IncrementUMultiplicity
1026 //purpose  : 
1027 //=======================================================================
1028
1029 void  Geom_BSplineSurface::IncrementUMultiplicity
1030 (const Standard_Integer FromI1,
1031  const Standard_Integer ToI2,
1032  const Standard_Integer Step)
1033 {
1034   Handle(TColStd_HArray1OfReal) tk = uknots;
1035   TColStd_Array1OfReal k( (uknots->Array1())(FromI1), FromI1, ToI2);
1036   TColStd_Array1OfInteger m( FromI1, ToI2) ;
1037   m.Init(Step);
1038   InsertUKnots( k, m, Epsilon(1.));
1039 }
1040
1041 //=======================================================================
1042 //function : IncrementVMultiplicity
1043 //purpose  : 
1044 //=======================================================================
1045
1046 void  Geom_BSplineSurface::IncrementVMultiplicity
1047 (const Standard_Integer FromI1,
1048  const Standard_Integer ToI2,
1049  const Standard_Integer Step)
1050 {
1051   Handle(TColStd_HArray1OfReal) tk = vknots;
1052   TColStd_Array1OfReal k( (vknots->Array1())(FromI1), FromI1, ToI2);
1053
1054   TColStd_Array1OfInteger m( FromI1, ToI2) ;
1055   m.Init(Step);
1056   
1057   InsertVKnots( k, m, Epsilon(1.));
1058 }
1059
1060 //=======================================================================
1061 //function : UpdateUKnots
1062 //purpose  : 
1063 //=======================================================================
1064
1065 void Geom_BSplineSurface::UpdateUKnots()
1066 {
1067
1068   Standard_Integer MaxKnotMult = 0;
1069   BSplCLib::KnotAnalysis (udeg, uperiodic,
1070                 uknots->Array1(), 
1071                 umults->Array1(), 
1072                 uknotSet, MaxKnotMult);
1073   
1074   if (uknotSet == GeomAbs_Uniform && !uperiodic)  {
1075     ufknots = uknots;
1076   }
1077   else {
1078     ufknots = new TColStd_HArray1OfReal 
1079       (1, BSplCLib::KnotSequenceLength(umults->Array1(),udeg,uperiodic));
1080
1081     BSplCLib::KnotSequence (uknots->Array1(), 
1082                             umults->Array1(),
1083                             udeg,uperiodic,
1084                             ufknots->ChangeArray1());
1085   }
1086   
1087   if (MaxKnotMult == 0)  Usmooth = GeomAbs_CN;
1088   else {
1089     switch (udeg - MaxKnotMult) {
1090     case 0 :   Usmooth = GeomAbs_C0;   break;
1091     case 1 :   Usmooth = GeomAbs_C1;   break;
1092     case 2 :   Usmooth = GeomAbs_C2;   break;
1093     case 3 :   Usmooth = GeomAbs_C3;   break;
1094       default :  Usmooth = GeomAbs_C3;   break;
1095     }
1096   }
1097 }
1098
1099 //=======================================================================
1100 //function : UpdateVKnots
1101 //purpose  : 
1102 //=======================================================================
1103
1104 void Geom_BSplineSurface::UpdateVKnots()
1105 {
1106   Standard_Integer MaxKnotMult = 0;
1107   BSplCLib::KnotAnalysis (vdeg, vperiodic,
1108                 vknots->Array1(), 
1109                 vmults->Array1(), 
1110                 vknotSet, MaxKnotMult);
1111   
1112   if (vknotSet == GeomAbs_Uniform && !vperiodic)  {
1113     vfknots = vknots;
1114   }
1115   else {
1116     vfknots = new TColStd_HArray1OfReal 
1117       (1, BSplCLib::KnotSequenceLength(vmults->Array1(),vdeg,vperiodic));
1118
1119     BSplCLib::KnotSequence (vknots->Array1(), 
1120                             vmults->Array1(),
1121                             vdeg,vperiodic,
1122                             vfknots->ChangeArray1());
1123   }
1124   
1125   if (MaxKnotMult == 0)  Vsmooth = GeomAbs_CN;
1126   else {
1127     switch (vdeg - MaxKnotMult) {
1128     case 0 :   Vsmooth = GeomAbs_C0;   break;
1129     case 1 :   Vsmooth = GeomAbs_C1;   break;
1130     case 2 :   Vsmooth = GeomAbs_C2;   break;
1131     case 3 :   Vsmooth = GeomAbs_C3;   break;
1132       default :  Vsmooth = GeomAbs_C3;   break;
1133     }
1134   }
1135 }
1136
1137
1138 //=======================================================================
1139 //function : Normalizes the parameters if the curve is periodic
1140 //purpose  : that is compute the cache so that it is valid
1141 //=======================================================================
1142
1143 void Geom_BSplineSurface::PeriodicNormalization
1144 (Standard_Real&  Uparameter, 
1145  Standard_Real&  Vparameter) const 
1146 {
1147   Standard_Real Period, aMaxVal, aMinVal;
1148   
1149   if (uperiodic) {
1150     aMaxVal = ufknots->Value(ufknots->Upper() - udeg);
1151     aMinVal = ufknots->Value (udeg + 1);
1152     Standard_Real eps = Abs(Epsilon(Uparameter));
1153     Period =  aMaxVal - aMinVal;
1154
1155     if(Period <= eps) 
1156       throw Standard_OutOfRange("Geom_BSplineSurface::PeriodicNormalization: Uparameter is too great number");
1157
1158     Standard_Boolean isLess, isGreater;
1159     isLess = aMinVal - Uparameter > 0;
1160     isGreater = Uparameter - aMaxVal > 0;
1161     if (isLess || isGreater) {
1162       Standard_Real aDPar, aNbPer;
1163       aDPar = (isLess) ? (aMaxVal - Uparameter) : (aMinVal - Uparameter);
1164       modf(aDPar / Period, &aNbPer);
1165       Uparameter += aNbPer * Period;
1166     }
1167   }
1168   if (vperiodic) {
1169     aMaxVal = vfknots->Value(vfknots->Upper() - vdeg);
1170     aMinVal = vfknots->Value (vdeg + 1);
1171     Standard_Real eps = Abs(Epsilon(Vparameter));
1172     Period = aMaxVal - aMinVal;
1173
1174     if(Period <= eps) 
1175       throw Standard_OutOfRange("Geom_BSplineSurface::PeriodicNormalization: Vparameter is too great number");
1176
1177     Standard_Boolean isLess, isGreater;
1178     isLess = aMinVal - Vparameter > 0;
1179     isGreater = Vparameter - aMaxVal > 0;
1180     if (isLess || isGreater) {
1181       Standard_Real aDPar, aNbPer;
1182       aDPar = (isLess) ? (aMaxVal - Vparameter) : (aMinVal - Vparameter);
1183       modf(aDPar / Period, &aNbPer);
1184       Vparameter += aNbPer * Period;
1185     }
1186   }
1187 }
1188
1189 //=======================================================================
1190 //function : SetWeight
1191 //purpose  : 
1192 //=======================================================================
1193
1194 void Geom_BSplineSurface::SetWeight (const Standard_Integer UIndex,
1195                                      const Standard_Integer VIndex,
1196                                      const Standard_Real    Weight)
1197 {
1198   if (Weight <= gp::Resolution())
1199     throw Standard_ConstructionError("Geom_BSplineSurface::SetWeight: Weight too small");
1200   TColStd_Array2OfReal & Weights = weights->ChangeArray2();
1201   if (UIndex < 1 || UIndex > Weights.ColLength() ||
1202       VIndex < 1 || VIndex > Weights.RowLength() ) {
1203     throw Standard_OutOfRange("Geom_BSplineSurface::SetWeight: Index and #pole mismatch");
1204   }
1205   Weights (UIndex+Weights.LowerRow()-1, VIndex+Weights.LowerCol()-1) = Weight;
1206   Rational(Weights, urational, vrational);
1207 }
1208
1209 //=======================================================================
1210 //function : SetWeightCol
1211 //purpose  : 
1212 //=======================================================================
1213
1214 void Geom_BSplineSurface::SetWeightCol
1215 (const Standard_Integer       VIndex, 
1216  const TColStd_Array1OfReal&  CPoleWeights)
1217 {
1218   TColStd_Array2OfReal & Weights = weights->ChangeArray2();   
1219   if (VIndex < 1 || VIndex > Weights.RowLength()) {
1220     throw Standard_OutOfRange("Geom_BSplineSurface::SetWeightCol: Index and #pole mismatch");
1221   }
1222   if (CPoleWeights.Lower() < 1 || 
1223       CPoleWeights.Lower() > Weights.ColLength() ||
1224       CPoleWeights.Upper() < 1 ||
1225       CPoleWeights.Upper() > Weights.ColLength()  ) {
1226     throw Standard_ConstructionError("Geom_BSplineSurface::SetWeightCol: invalid array dimension");
1227   }
1228   Standard_Integer I = CPoleWeights.Lower();
1229   while (I <= CPoleWeights.Upper()) {
1230     if (CPoleWeights(I) <= gp::Resolution()) { 
1231       throw Standard_ConstructionError("Geom_BSplineSurface::SetWeightCol: Weight too small");
1232     }
1233     Weights (I+Weights.LowerRow()-1, VIndex+Weights.LowerCol()-1) = 
1234       CPoleWeights (I);
1235     I++;
1236   }
1237   // Verifie si c'est rationnel
1238   Rational(Weights, urational, vrational);
1239 }
1240
1241 //=======================================================================
1242 //function : SetWeightRow
1243 //purpose  : 
1244 //=======================================================================
1245
1246 void Geom_BSplineSurface::SetWeightRow
1247 (const Standard_Integer       UIndex, 
1248  const TColStd_Array1OfReal&  CPoleWeights)
1249 {
1250   TColStd_Array2OfReal & Weights = weights->ChangeArray2();   
1251   if (UIndex < 1 || UIndex > Weights.ColLength()) {
1252     throw Standard_OutOfRange("Geom_BSplineSurface::SetWeightRow: Index and #pole mismatch");
1253   }
1254   if (CPoleWeights.Lower() < 1 ||
1255       CPoleWeights.Lower() > Weights.RowLength() ||
1256       CPoleWeights.Upper() < 1 ||
1257       CPoleWeights.Upper() > Weights.RowLength()  ) {
1258     
1259     throw Standard_ConstructionError("Geom_BSplineSurface::SetWeightRow: invalid array dimension");
1260   }
1261   Standard_Integer I = CPoleWeights.Lower();
1262
1263   while (I <= CPoleWeights.Upper()) {
1264     if (CPoleWeights(I)<=gp::Resolution()) {
1265       throw Standard_ConstructionError("Geom_BSplineSurface::SetWeightRow: Weight too small");
1266     }
1267     Weights (UIndex+Weights.LowerRow()-1, I+Weights.LowerCol()-1) = 
1268       CPoleWeights (I);
1269     I++;
1270   }
1271   // Verifie si c'est rationnel
1272   Rational(Weights, urational, vrational);
1273 }
1274