7b5c9f5ef3e97d19d6b63c103b4003a70ee2234a
[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 = new TColgp_HArray2OfPnt (LC, UC, LR, UR);
304   Handle(TColStd_HArray2OfReal) nweights;
305   if (!weights.IsNull())
306   {
307     nweights = new TColStd_HArray2OfReal (LC, UC, LR, UR);
308   }
309
310   const TColgp_Array2OfPnt& spoles = poles->Array2();
311   const TColStd_Array2OfReal* sweights = !weights.IsNull() ? &weights->Array2() : NULL;
312   
313   TColgp_Array2OfPnt& snpoles = npoles->ChangeArray2();
314   TColStd_Array2OfReal* snweights = !nweights.IsNull() ? &nweights->ChangeArray2() : NULL;
315   for (Standard_Integer i = LC; i <= UC; i++)
316   {
317     for (Standard_Integer j = LR; j <= UR; j++)
318     {
319       snpoles (i, j) = spoles (j, i);
320       if (snweights != NULL)
321       {
322         snweights->ChangeValue (i, j) = sweights->Value (j, i);
323       }
324     }
325   }
326   poles   = npoles;
327   weights = nweights;
328
329   std::swap (urational, vrational);
330   std::swap (uperiodic, vperiodic);
331   std::swap (udeg,   vdeg);
332   std::swap (uknots, vknots);
333   std::swap (umults, vmults);
334
335   UpdateUKnots();
336   UpdateVKnots();
337 }
338
339 //=======================================================================
340 //function : IncreaseDegree
341 //purpose  : 
342 //=======================================================================
343
344 void Geom_BSplineSurface::IncreaseDegree (const Standard_Integer UDegree,
345                                           const Standard_Integer VDegree)
346
347   if (UDegree != udeg) {
348     if ( UDegree < udeg || UDegree > Geom_BSplineSurface::MaxDegree())
349       throw Standard_ConstructionError("Geom_BSplineSurface::IncreaseDegree: bad U degree value");
350     
351     Standard_Integer FromK1 = FirstUKnotIndex();
352     Standard_Integer ToK2   = LastUKnotIndex();
353
354     Standard_Integer Step   = UDegree - udeg;
355
356     Handle(TColgp_HArray2OfPnt) npoles = new
357       TColgp_HArray2OfPnt( 1, poles->ColLength() + Step * (ToK2 - FromK1),
358                           1, poles->RowLength());
359
360     Standard_Integer nbknots = BSplCLib::IncreaseDegreeCountKnots
361       (udeg,UDegree,uperiodic,umults->Array1());
362
363     Handle(TColStd_HArray1OfReal) nknots = 
364       new TColStd_HArray1OfReal(1,nbknots);
365     
366     Handle(TColStd_HArray1OfInteger) nmults = 
367       new TColStd_HArray1OfInteger(1,nbknots);
368
369     Handle(TColStd_HArray2OfReal) nweights 
370       = new TColStd_HArray2OfReal(1,npoles->ColLength(),
371                                   1,npoles->RowLength(), 1.);
372
373     if (urational || vrational) {
374       
375       BSplSLib::IncreaseDegree
376         (Standard_True, udeg, UDegree, uperiodic,
377          poles->Array2(),&weights->Array2(),
378          uknots->Array1(),umults->Array1(),
379          npoles->ChangeArray2(),&nweights->ChangeArray2(),
380          nknots->ChangeArray1(),nmults->ChangeArray1());
381     }
382     else {
383
384       BSplSLib::IncreaseDegree
385         (Standard_True, udeg, UDegree, uperiodic,
386          poles->Array2(),BSplSLib::NoWeights(),
387          uknots->Array1(),umults->Array1(),
388          npoles->ChangeArray2(),BSplSLib::NoWeights(),
389          nknots->ChangeArray1(),nmults->ChangeArray1());
390     }
391     udeg    = UDegree;
392     poles   = npoles;
393     weights = nweights;
394     uknots  = nknots;
395     umults  = nmults;
396     UpdateUKnots();
397   }
398
399   if (VDegree != vdeg) {
400     if ( VDegree < vdeg || VDegree > Geom_BSplineSurface::MaxDegree())
401       throw Standard_ConstructionError("Geom_BSplineSurface::IncreaseDegree: bad V degree value");
402     
403     Standard_Integer FromK1 = FirstVKnotIndex();
404     Standard_Integer ToK2   = LastVKnotIndex();
405
406     Standard_Integer Step   = VDegree - vdeg;
407
408     Handle(TColgp_HArray2OfPnt) npoles = new
409       TColgp_HArray2OfPnt( 1, poles->ColLength(),
410                           1, poles->RowLength() + Step * (ToK2 - FromK1));
411
412     Standard_Integer nbknots = BSplCLib::IncreaseDegreeCountKnots
413       (vdeg,VDegree,vperiodic,vmults->Array1());
414
415     Handle(TColStd_HArray1OfReal) nknots = 
416       new TColStd_HArray1OfReal(1,nbknots);
417     
418     Handle(TColStd_HArray1OfInteger) nmults = 
419       new TColStd_HArray1OfInteger(1,nbknots);
420
421     Handle(TColStd_HArray2OfReal) nweights
422       = new TColStd_HArray2OfReal(1,npoles->ColLength(),
423                                   1,npoles->RowLength(), 1.);
424
425     if (urational || vrational) {
426       
427       BSplSLib::IncreaseDegree
428         (Standard_False, vdeg, VDegree, vperiodic,
429          poles->Array2(),&weights->Array2(),
430          vknots->Array1(),vmults->Array1(),
431          npoles->ChangeArray2(),&nweights->ChangeArray2(),
432          nknots->ChangeArray1(),nmults->ChangeArray1());
433     }
434     else {
435
436       BSplSLib::IncreaseDegree
437         (Standard_False, vdeg, VDegree, vperiodic,
438          poles->Array2(),BSplSLib::NoWeights(),
439          vknots->Array1(),vmults->Array1(),
440          npoles->ChangeArray2(),BSplSLib::NoWeights(),
441          nknots->ChangeArray1(),nmults->ChangeArray1());
442     }
443     vdeg    = VDegree;
444     poles   = npoles;
445     weights = nweights;
446     vknots  = nknots;
447     vmults  = nmults;
448     UpdateVKnots();
449   }
450 }
451
452 //=======================================================================
453 //function : IncreaseUMultiplicity
454 //purpose  : 
455 //=======================================================================
456
457 void Geom_BSplineSurface::IncreaseUMultiplicity
458 (const Standard_Integer UIndex, 
459  const Standard_Integer M)
460 {
461   TColStd_Array1OfReal k(1,1);
462   k(1) = uknots->Value(UIndex);
463   TColStd_Array1OfInteger m(1,1);
464   m(1) = M - umults->Value(UIndex);
465   InsertUKnots(k,m,Epsilon(1.),Standard_True);
466 }
467
468 //=======================================================================
469 //function : IncreaseUMultiplicity
470 //purpose  : 
471 //=======================================================================
472
473 void Geom_BSplineSurface::IncreaseUMultiplicity
474 (const Standard_Integer FromI1, 
475  const Standard_Integer ToI2,
476  const Standard_Integer M)
477 {
478   Handle(TColStd_HArray1OfReal) tk = uknots;
479   TColStd_Array1OfReal k((uknots->Array1())(FromI1),FromI1,ToI2);
480   TColStd_Array1OfInteger m(FromI1, ToI2);
481   for (Standard_Integer i = FromI1; i <= ToI2; i++) 
482     m(i) = M - umults->Value(i);
483   InsertUKnots(k,m,Epsilon(1.),Standard_True);
484 }
485
486 //=======================================================================
487 //function : IncreaseVMultiplicity
488 //purpose  : 
489 //=======================================================================
490
491 void Geom_BSplineSurface::IncreaseVMultiplicity
492 (const Standard_Integer VIndex, 
493  const Standard_Integer M)
494 {
495   TColStd_Array1OfReal k(1,1);
496   k(1) = vknots->Value(VIndex);
497   TColStd_Array1OfInteger m(1,1);
498   m(1) = M - vmults->Value(VIndex);
499   InsertVKnots(k,m,Epsilon(1.),Standard_True);
500 }
501
502 //=======================================================================
503 //function : IncreaseVMultiplicity
504 //purpose  : 
505 //=======================================================================
506
507 void Geom_BSplineSurface::IncreaseVMultiplicity
508 (const Standard_Integer FromI1,
509  const Standard_Integer ToI2,
510  const Standard_Integer M)
511 {
512   Handle(TColStd_HArray1OfReal) tk = vknots;
513   TColStd_Array1OfReal k((vknots->Array1())(FromI1),FromI1,ToI2);
514   TColStd_Array1OfInteger m(FromI1,ToI2);
515   for (Standard_Integer i = FromI1; i <= ToI2; i++)
516     m(i) = M - vmults->Value(i);
517   InsertVKnots(k,m,Epsilon(1.),Standard_True);
518 }
519
520 //=======================================================================
521 //function : segment
522 //purpose  : 
523 //=======================================================================
524
525 void Geom_BSplineSurface::segment(const Standard_Real U1,
526                                   const Standard_Real U2,
527                                   const Standard_Real V1,
528                                   const Standard_Real V2,
529                                   const Standard_Real EpsU,
530                                   const Standard_Real EpsV,
531                                   const Standard_Boolean SegmentInU,
532                                   const Standard_Boolean SegmentInV)
533 {
534   Standard_Real deltaU = U2 - U1;
535   if (uperiodic) {
536     Standard_Real aUPeriod = uknots->Last() - uknots->First();
537     if (deltaU - aUPeriod > Precision::PConfusion())
538       throw Standard_DomainError("Geom_BSplineSurface::Segment");
539     if (deltaU > aUPeriod)
540       deltaU = aUPeriod;
541   }
542
543   Standard_Real deltaV = V2 - V1;
544   if (vperiodic) {
545     Standard_Real aVPeriod = vknots->Last() - vknots->First();
546     if (deltaV - aVPeriod > Precision::PConfusion())
547       throw Standard_DomainError("Geom_BSplineSurface::Segment");
548     if (deltaV > aVPeriod)
549       deltaV = aVPeriod;
550   }
551
552   Standard_Real NewU1, NewU2, NewV1, NewV2;
553   Standard_Real U, V;
554   Standard_Integer indexU, indexV;
555
556   indexU = 0;
557   BSplCLib::LocateParameter(udeg, uknots->Array1(), umults->Array1(),
558                             U1, uperiodic, uknots->Lower(), uknots->Upper(),
559                             indexU, NewU1);
560   indexU = 0;
561   BSplCLib::LocateParameter(udeg, uknots->Array1(), umults->Array1(),
562                             U2, uperiodic, uknots->Lower(), uknots->Upper(),
563                             indexU, NewU2);
564   if (SegmentInU) {
565     // inserting the UKnots
566     TColStd_Array1OfReal    UKnots(1, 2);
567     TColStd_Array1OfInteger UMults(1, 2);
568     UKnots(1) = Min(NewU1, NewU2);
569     UKnots(2) = Max(NewU1, NewU2);
570     UMults(1) = UMults(2) = udeg;
571
572     InsertUKnots(UKnots, UMults, EpsU);
573   }
574
575   indexV = 0;
576   BSplCLib::LocateParameter(vdeg, vknots->Array1(), vmults->Array1(),
577                             V1, vperiodic, vknots->Lower(), vknots->Upper(),
578                             indexV, NewV1);
579   indexV = 0;
580   BSplCLib::LocateParameter(vdeg, vknots->Array1(), vmults->Array1(),
581                             V2, vperiodic, vknots->Lower(), vknots->Upper(),
582                             indexV, NewV2);
583   if (SegmentInV) {
584     // Inserting the VKnots
585     TColStd_Array1OfReal    VKnots(1, 2);
586     TColStd_Array1OfInteger VMults(1, 2);
587
588     VKnots(1) = Min(NewV1, NewV2);
589     VKnots(2) = Max(NewV1, NewV2);
590     VMults(1) = VMults(2) = vdeg;
591     InsertVKnots(VKnots, VMults, EpsV);
592   }
593
594   if (uperiodic && SegmentInU) { // set the origine at NewU1
595     Standard_Integer index = 0;
596     BSplCLib::LocateParameter(udeg, uknots->Array1(), umults->Array1(),
597       U1, uperiodic, uknots->Lower(), uknots->Upper(),
598       index, U);
599     if (Abs(uknots->Value(index + 1) - U) <= EpsU)
600       index++;
601     SetUOrigin(index);
602     SetUNotPeriodic();
603   }
604
605   // compute index1 and index2 to set the new knots and mults 
606   Standard_Integer index1U = 0, index2U = 0;
607   Standard_Integer FromU1 = uknots->Lower();
608   Standard_Integer ToU2 = uknots->Upper();
609   BSplCLib::LocateParameter(udeg, uknots->Array1(), umults->Array1(),
610                             NewU1, uperiodic, FromU1, ToU2, index1U, U);
611   if (Abs(uknots->Value(index1U + 1) - U) <= EpsU)
612     index1U++;
613   BSplCLib::LocateParameter(udeg, uknots->Array1(), umults->Array1(),
614                             NewU1 + deltaU, uperiodic, FromU1, ToU2, index2U, U);
615   if (Abs(uknots->Value(index2U + 1) - U) <= EpsU || index2U == index1U)
616     index2U++;
617
618   Standard_Integer nbuknots = index2U - index1U + 1;
619
620   Handle(TColStd_HArray1OfReal)
621     nuknots = new TColStd_HArray1OfReal(1, nbuknots);
622   Handle(TColStd_HArray1OfInteger)
623     numults = new TColStd_HArray1OfInteger(1, nbuknots);
624
625   Standard_Integer i, k = 1;
626   for (i = index1U; i <= index2U; i++) {
627     nuknots->SetValue(k, uknots->Value(i));
628     numults->SetValue(k, umults->Value(i));
629     k++;
630   }
631   if (SegmentInU) {
632     numults->SetValue(1, udeg + 1);
633     numults->SetValue(nbuknots, udeg + 1);
634   }
635
636   if (vperiodic&& SegmentInV) { // set the origine at NewV1
637     Standard_Integer index = 0;
638     BSplCLib::LocateParameter(vdeg, vknots->Array1(), vmults->Array1(),
639       V1, vperiodic, vknots->Lower(), vknots->Upper(),
640       index, V);
641     if (Abs(vknots->Value(index + 1) - V) <= EpsV)
642       index++;
643     SetVOrigin(index);
644     SetVNotPeriodic();
645   }
646
647   // compute index1 and index2 to set the new knots and mults 
648   Standard_Integer index1V = 0, index2V = 0;
649   Standard_Integer FromV1 = vknots->Lower();
650   Standard_Integer ToV2 = vknots->Upper();
651   BSplCLib::LocateParameter(vdeg, vknots->Array1(), vmults->Array1(),
652                             NewV1, vperiodic, FromV1, ToV2, index1V, V);
653   if (Abs(vknots->Value(index1V + 1) - V) <= EpsV)
654     index1V++;
655   BSplCLib::LocateParameter(vdeg, vknots->Array1(), vmults->Array1(),
656                             NewV1 + deltaV, vperiodic, FromV1, ToV2, index2V, V);
657   if (Abs(vknots->Value(index2V + 1) - V) <= EpsV || index2V == index1V)
658     index2V++;
659
660   Standard_Integer nbvknots = index2V - index1V + 1;
661
662   Handle(TColStd_HArray1OfReal)
663     nvknots = new TColStd_HArray1OfReal(1, nbvknots);
664   Handle(TColStd_HArray1OfInteger)
665     nvmults = new TColStd_HArray1OfInteger(1, nbvknots);
666
667   k = 1;
668   for (i = index1V; i <= index2V; i++) {
669     nvknots->SetValue(k, vknots->Value(i));
670     nvmults->SetValue(k, vmults->Value(i));
671     k++;
672   }
673   if (SegmentInV) {
674     nvmults->SetValue(1, vdeg + 1);
675     nvmults->SetValue(nbvknots, vdeg + 1);
676   }
677
678
679   // compute index1 and index2 to set the new poles and weights
680   Standard_Integer pindex1U
681     = BSplCLib::PoleIndex(udeg, index1U, uperiodic, umults->Array1());
682   Standard_Integer pindex2U
683     = BSplCLib::PoleIndex(udeg, index2U, uperiodic, umults->Array1());
684
685   pindex1U++;
686   pindex2U = Min(pindex2U + 1, poles->ColLength());
687
688   Standard_Integer nbupoles = pindex2U - pindex1U + 1;
689
690   // compute index1 and index2 to set the new poles and weights
691   Standard_Integer pindex1V
692     = BSplCLib::PoleIndex(vdeg, index1V, vperiodic, vmults->Array1());
693   Standard_Integer pindex2V
694     = BSplCLib::PoleIndex(vdeg, index2V, vperiodic, vmults->Array1());
695
696   pindex1V++;
697   pindex2V = Min(pindex2V + 1, poles->RowLength());
698
699   Standard_Integer nbvpoles = pindex2V - pindex1V + 1;
700
701
702   Handle(TColStd_HArray2OfReal) nweights;
703
704   Handle(TColgp_HArray2OfPnt)
705     npoles = new TColgp_HArray2OfPnt(1, nbupoles, 1, nbvpoles);
706   k = 1;
707   Standard_Integer j, l;
708   if (urational || vrational) {
709     nweights = new TColStd_HArray2OfReal(1, nbupoles, 1, nbvpoles);
710     for (i = pindex1U; i <= pindex2U; i++) {
711       l = 1;
712       for (j = pindex1V; j <= pindex2V; j++) {
713         npoles->SetValue(k, l, poles->Value(i, j));
714         nweights->SetValue(k, l, weights->Value(i, j));
715         l++;
716       }
717       k++;
718     }
719   }
720   else {
721     for (i = pindex1U; i <= pindex2U; i++) {
722       l = 1;
723       for (j = pindex1V; j <= pindex2V; j++) {
724         npoles->SetValue(k, l, poles->Value(i, j));
725         l++;
726       }
727       k++;
728     }
729   }
730
731   uknots = nuknots;
732   umults = numults;
733   vknots = nvknots;
734   vmults = nvmults;
735   poles = npoles;
736   if (urational || vrational)
737     weights = nweights;
738   else
739     weights = new TColStd_HArray2OfReal(1, poles->ColLength(),
740                                         1, poles->RowLength(), 1.0);
741
742   maxderivinvok = 0;
743   UpdateUKnots();
744   UpdateVKnots();
745 }
746
747 //=======================================================================
748 //function : Segment
749 //purpose  : 
750 //=======================================================================
751
752 void Geom_BSplineSurface::Segment(const Standard_Real U1, 
753                                   const Standard_Real U2,
754                                   const Standard_Real V1,
755                                   const Standard_Real V2,
756                                   const Standard_Real theUTolerance,
757                                   const Standard_Real theVTolerance)
758 {
759   if ((U2 < U1) || (V2 < V1))
760     throw Standard_DomainError("Geom_BSplineSurface::Segment");
761
762   Standard_Real aMaxU = Max(Abs(U2), Abs(U1));
763   Standard_Real EpsU = Max(Epsilon(aMaxU), theUTolerance);
764   
765   Standard_Real aMaxV = Max(Abs(V2), Abs(V1));
766   Standard_Real EpsV = Max(Epsilon(aMaxV), theVTolerance);
767
768   segment(U1, U2, V1, V2, EpsU, EpsV, Standard_True, Standard_True);
769 }
770
771 //=======================================================================
772 //function : CheckAndSegment
773 //purpose  : 
774 //=======================================================================
775
776 void Geom_BSplineSurface::CheckAndSegment(const Standard_Real U1, 
777                                           const Standard_Real U2,
778                                           const Standard_Real V1,
779                                           const Standard_Real V2,
780                                           const Standard_Real theUTolerance,
781                                           const Standard_Real theVTolerance)
782 {
783
784   if ((U2 < U1) || (V2 < V1))
785     throw Standard_DomainError("Geom_BSplineSurface::CheckAndSegment");
786
787   Standard_Real aMaxU = Max(Abs(U2), Abs(U1));
788   Standard_Real EpsU = Max(Epsilon(aMaxU), theUTolerance);
789   
790   Standard_Real aMaxV = Max(Abs(V2), Abs(V1));
791   Standard_Real EpsV = Max(Epsilon(aMaxV), theVTolerance);
792
793   Standard_Boolean segment_in_U = Standard_True;
794   Standard_Boolean segment_in_V = Standard_True;
795   segment_in_U = ( Abs(U1 - uknots->Value(uknots->Lower())) > EpsU )
796                         || ( Abs(U2 - uknots->Value(uknots->Upper())) > EpsU );
797   segment_in_V = ( Abs(V1 - vknots->Value(vknots->Lower())) > EpsV )
798                         || ( Abs(V2 - vknots->Value(vknots->Upper())) > EpsV );
799
800   segment(U1, U2, V1, V2, EpsU, EpsV, segment_in_U, segment_in_V);
801 }
802
803 //=======================================================================
804 //function : SetUKnot
805 //purpose  : 
806 //=======================================================================
807
808 void Geom_BSplineSurface::SetUKnot
809 (const Standard_Integer UIndex,
810  const Standard_Real    K      )
811 {
812   if (UIndex < 1 || UIndex > uknots->Length())
813     throw Standard_OutOfRange("Geom_BSplineSurface::SetUKnot: Index and #knots mismatch");
814
815   Standard_Integer NewIndex = UIndex;
816   Standard_Real DU = Abs(Epsilon (K));
817   if (UIndex == 1) {
818     if (K >= uknots->Value (2) - DU)
819       throw Standard_ConstructionError("Geom_BSplineSurface::SetUKnot: K out of range");
820   }
821   else if (UIndex == uknots->Length()) {
822     if (K <= uknots->Value (uknots->Length()-1) + DU)  {
823       throw Standard_ConstructionError("Geom_BSplineSurface::SetUKnot: K out of range");
824     }
825   }
826   else {
827     if (K <= uknots->Value (NewIndex-1) + DU || 
828         K >= uknots->Value (NewIndex+1) - DU ) { 
829       throw Standard_ConstructionError("Geom_BSplineSurface::SetUKnot: K out of range");
830     } 
831   }
832   
833   if (K != uknots->Value (NewIndex)) {
834     uknots->SetValue (NewIndex, K);
835     maxderivinvok = 0;
836     UpdateUKnots();
837   }
838 }
839
840 //=======================================================================
841 //function : SetUKnots
842 //purpose  : 
843 //=======================================================================
844
845 void Geom_BSplineSurface::SetUKnots (const TColStd_Array1OfReal& UK) {
846
847   Standard_Integer Lower = UK.Lower();
848   Standard_Integer Upper = UK.Upper();
849   if (Lower < 1 || Lower > uknots->Length() ||
850       Upper < 1 || Upper > uknots->Length() ) {
851     throw Standard_OutOfRange("Geom_BSplineSurface::SetUKnots: invalid array dimension");
852   }
853   if (Lower > 1) {
854     if (Abs (UK (Lower) - uknots->Value (Lower-1)) <= gp::Resolution()) {
855       throw Standard_ConstructionError("Geom_BSplineSurface::SetUKnots: invalid knot value");
856     }
857   }
858   if (Upper < uknots->Length ()) {
859     if (Abs (UK (Upper) - uknots->Value (Upper+1)) <= gp::Resolution()) {
860       throw Standard_ConstructionError("Geom_BSplineSurface::SetUKnots: invalid knot value");
861     }
862   }
863   Standard_Real K1 = UK (Lower);
864   for (Standard_Integer i = Lower; i <= Upper; i++) {
865     uknots->SetValue (i, UK(i));
866     if (i != Lower) {
867       if (Abs (UK(i) - K1) <= gp::Resolution()) {
868         throw Standard_ConstructionError("Geom_BSplineSurface::SetUKnots: invalid knot value");
869       }
870       K1 = UK (i);
871     }
872   }
873
874   maxderivinvok = 0;
875   UpdateUKnots();
876 }
877
878 //=======================================================================
879 //function : SetUKnot
880 //purpose  : 
881 //=======================================================================
882
883 void Geom_BSplineSurface::SetUKnot
884 (const Standard_Integer UIndex,
885  const Standard_Real    K,
886  const Standard_Integer M)
887 {
888   IncreaseUMultiplicity (UIndex, M);
889   SetUKnot (UIndex, K);
890 }
891
892 //=======================================================================
893 //function : SetVKnot
894 //purpose  : 
895 //=======================================================================
896
897 void Geom_BSplineSurface::SetVKnot
898 (const Standard_Integer VIndex,
899  const Standard_Real    K)
900 {
901   if (VIndex < 1 || VIndex > vknots->Length())
902     throw Standard_OutOfRange("Geom_BSplineSurface::SetVKnot: Index and #knots mismatch");
903   Standard_Integer NewIndex = VIndex + vknots->Lower() - 1;
904   Standard_Real DV = Abs(Epsilon (K));
905   if (VIndex == 1) {
906     if (K >=  vknots->Value (2) - DV) {
907       throw Standard_ConstructionError("Geom_BSplineSurface::SetVKnot: K out of range");
908     }
909   }
910   else if (VIndex == vknots->Length()) {
911     if (K <= vknots->Value (vknots->Length()-1) + DV)  {
912       throw Standard_ConstructionError("Geom_BSplineSurface::SetVKnot: K out of range");
913     }
914   }
915   else {
916     if (K <= vknots->Value (NewIndex-1) + DV || 
917         K >= vknots->Value (NewIndex+1) - DV ) { 
918       throw Standard_ConstructionError("Geom_BSplineSurface::SetVKnot: K out of range");
919     } 
920   }
921   
922   if (K != vknots->Value (NewIndex)) {
923     vknots->SetValue (NewIndex, K);
924     maxderivinvok = 0;
925     UpdateVKnots();
926   }
927 }
928
929 //=======================================================================
930 //function : SetVKnots
931 //purpose  : 
932 //=======================================================================
933
934 void Geom_BSplineSurface::SetVKnots (const TColStd_Array1OfReal& VK) {
935
936   Standard_Integer Lower = VK.Lower();
937   Standard_Integer Upper = VK.Upper();
938   if (Lower < 1 || Lower > vknots->Length() ||
939       Upper < 1 || Upper > vknots->Length() ) {
940     throw Standard_OutOfRange("Geom_BSplineSurface::SetVKnots: invalid array dimension");
941   }
942   if (Lower > 1) {
943     if (Abs (VK (Lower) - vknots->Value (Lower-1)) <= gp::Resolution()) {
944       throw Standard_ConstructionError("Geom_BSplineSurface::SetVKnots: invalid knot value");
945     }
946   }
947   if (Upper < vknots->Length ()) {
948     if (Abs (VK (Upper) - vknots->Value (Upper+1)) <= gp::Resolution()) {
949       throw Standard_ConstructionError("Geom_BSplineSurface::SetVKnots: invalid knot value");
950     }
951   }
952   Standard_Real K1 = VK (Lower);
953   for (Standard_Integer i = Lower; i <= Upper; i++) {
954     vknots->SetValue (i, VK(i));
955     if (i != Lower) {
956       if (Abs (VK(i) - K1) <= gp::Resolution()) {
957         throw Standard_ConstructionError("Geom_BSplineSurface::SetVKnots: invalid knot value");
958       }
959       K1 = VK (i);
960     }
961   }
962
963   maxderivinvok = 0;
964   UpdateVKnots();
965 }
966
967 //=======================================================================
968 //function : SetVKnot
969 //purpose  : 
970 //=======================================================================
971
972 void Geom_BSplineSurface::SetVKnot
973 (const Standard_Integer VIndex,
974  const Standard_Real    K,
975  const Standard_Integer M)
976 {
977   IncreaseVMultiplicity (VIndex, M);
978   SetVKnot (VIndex, K);
979 }
980
981 //=======================================================================
982 //function : InsertUKnot
983 //purpose  : 
984 //=======================================================================
985
986 void Geom_BSplineSurface::InsertUKnot
987 (const Standard_Real    U,
988  const Standard_Integer M,
989  const Standard_Real    ParametricTolerance,
990  const Standard_Boolean Add)
991 {
992   TColStd_Array1OfReal k(1,1);
993   k(1) = U;
994   TColStd_Array1OfInteger m(1,1);
995   m(1) = M;
996   InsertUKnots(k,m,ParametricTolerance,Add);
997 }
998
999 //=======================================================================
1000 //function : InsertVKnot
1001 //purpose  : 
1002 //=======================================================================
1003
1004 void Geom_BSplineSurface::InsertVKnot
1005 (const Standard_Real    V,
1006  const Standard_Integer M,
1007  const Standard_Real    ParametricTolerance,
1008  const Standard_Boolean Add)
1009 {
1010   TColStd_Array1OfReal k(1,1);
1011   k(1) = V;
1012   TColStd_Array1OfInteger m(1,1);
1013   m(1) = M;
1014   InsertVKnots(k,m,ParametricTolerance,Add);
1015 }
1016
1017 //=======================================================================
1018 //function : IncrementUMultiplicity
1019 //purpose  : 
1020 //=======================================================================
1021
1022 void  Geom_BSplineSurface::IncrementUMultiplicity
1023 (const Standard_Integer FromI1,
1024  const Standard_Integer ToI2,
1025  const Standard_Integer Step)
1026 {
1027   Handle(TColStd_HArray1OfReal) tk = uknots;
1028   TColStd_Array1OfReal k( (uknots->Array1())(FromI1), FromI1, ToI2);
1029   TColStd_Array1OfInteger m( FromI1, ToI2) ;
1030   m.Init(Step);
1031   InsertUKnots( k, m, Epsilon(1.));
1032 }
1033
1034 //=======================================================================
1035 //function : IncrementVMultiplicity
1036 //purpose  : 
1037 //=======================================================================
1038
1039 void  Geom_BSplineSurface::IncrementVMultiplicity
1040 (const Standard_Integer FromI1,
1041  const Standard_Integer ToI2,
1042  const Standard_Integer Step)
1043 {
1044   Handle(TColStd_HArray1OfReal) tk = vknots;
1045   TColStd_Array1OfReal k( (vknots->Array1())(FromI1), FromI1, ToI2);
1046
1047   TColStd_Array1OfInteger m( FromI1, ToI2) ;
1048   m.Init(Step);
1049   
1050   InsertVKnots( k, m, Epsilon(1.));
1051 }
1052
1053 //=======================================================================
1054 //function : UpdateUKnots
1055 //purpose  : 
1056 //=======================================================================
1057
1058 void Geom_BSplineSurface::UpdateUKnots()
1059 {
1060
1061   Standard_Integer MaxKnotMult = 0;
1062   BSplCLib::KnotAnalysis (udeg, uperiodic,
1063                 uknots->Array1(), 
1064                 umults->Array1(), 
1065                 uknotSet, MaxKnotMult);
1066   
1067   if (uknotSet == GeomAbs_Uniform && !uperiodic)  {
1068     ufknots = uknots;
1069   }
1070   else {
1071     ufknots = new TColStd_HArray1OfReal 
1072       (1, BSplCLib::KnotSequenceLength(umults->Array1(),udeg,uperiodic));
1073
1074     BSplCLib::KnotSequence (uknots->Array1(), 
1075                             umults->Array1(),
1076                             udeg,uperiodic,
1077                             ufknots->ChangeArray1());
1078   }
1079   
1080   if (MaxKnotMult == 0)  Usmooth = GeomAbs_CN;
1081   else {
1082     switch (udeg - MaxKnotMult) {
1083     case 0 :   Usmooth = GeomAbs_C0;   break;
1084     case 1 :   Usmooth = GeomAbs_C1;   break;
1085     case 2 :   Usmooth = GeomAbs_C2;   break;
1086     case 3 :   Usmooth = GeomAbs_C3;   break;
1087       default :  Usmooth = GeomAbs_C3;   break;
1088     }
1089   }
1090 }
1091
1092 //=======================================================================
1093 //function : UpdateVKnots
1094 //purpose  : 
1095 //=======================================================================
1096
1097 void Geom_BSplineSurface::UpdateVKnots()
1098 {
1099   Standard_Integer MaxKnotMult = 0;
1100   BSplCLib::KnotAnalysis (vdeg, vperiodic,
1101                 vknots->Array1(), 
1102                 vmults->Array1(), 
1103                 vknotSet, MaxKnotMult);
1104   
1105   if (vknotSet == GeomAbs_Uniform && !vperiodic)  {
1106     vfknots = vknots;
1107   }
1108   else {
1109     vfknots = new TColStd_HArray1OfReal 
1110       (1, BSplCLib::KnotSequenceLength(vmults->Array1(),vdeg,vperiodic));
1111
1112     BSplCLib::KnotSequence (vknots->Array1(), 
1113                             vmults->Array1(),
1114                             vdeg,vperiodic,
1115                             vfknots->ChangeArray1());
1116   }
1117   
1118   if (MaxKnotMult == 0)  Vsmooth = GeomAbs_CN;
1119   else {
1120     switch (vdeg - MaxKnotMult) {
1121     case 0 :   Vsmooth = GeomAbs_C0;   break;
1122     case 1 :   Vsmooth = GeomAbs_C1;   break;
1123     case 2 :   Vsmooth = GeomAbs_C2;   break;
1124     case 3 :   Vsmooth = GeomAbs_C3;   break;
1125       default :  Vsmooth = GeomAbs_C3;   break;
1126     }
1127   }
1128 }
1129
1130
1131 //=======================================================================
1132 //function : Normalizes the parameters if the curve is periodic
1133 //purpose  : that is compute the cache so that it is valid
1134 //=======================================================================
1135
1136 void Geom_BSplineSurface::PeriodicNormalization
1137 (Standard_Real&  Uparameter, 
1138  Standard_Real&  Vparameter) const 
1139 {
1140   Standard_Real Period, aMaxVal, aMinVal;
1141   
1142   if (uperiodic) {
1143     aMaxVal = ufknots->Value(ufknots->Upper() - udeg);
1144     aMinVal = ufknots->Value (udeg + 1);
1145     Standard_Real eps = Abs(Epsilon(Uparameter));
1146     Period =  aMaxVal - aMinVal;
1147
1148     if(Period <= eps) 
1149       throw Standard_OutOfRange("Geom_BSplineSurface::PeriodicNormalization: Uparameter is too great number");
1150
1151     Standard_Boolean isLess, isGreater;
1152     isLess = aMinVal - Uparameter > 0;
1153     isGreater = Uparameter - aMaxVal > 0;
1154     if (isLess || isGreater) {
1155       Standard_Real aDPar, aNbPer;
1156       aDPar = (isLess) ? (aMaxVal - Uparameter) : (aMinVal - Uparameter);
1157       modf(aDPar / Period, &aNbPer);
1158       Uparameter += aNbPer * Period;
1159     }
1160   }
1161   if (vperiodic) {
1162     aMaxVal = vfknots->Value(vfknots->Upper() - vdeg);
1163     aMinVal = vfknots->Value (vdeg + 1);
1164     Standard_Real eps = Abs(Epsilon(Vparameter));
1165     Period = aMaxVal - aMinVal;
1166
1167     if(Period <= eps) 
1168       throw Standard_OutOfRange("Geom_BSplineSurface::PeriodicNormalization: Vparameter is too great number");
1169
1170     Standard_Boolean isLess, isGreater;
1171     isLess = aMinVal - Vparameter > 0;
1172     isGreater = Vparameter - aMaxVal > 0;
1173     if (isLess || isGreater) {
1174       Standard_Real aDPar, aNbPer;
1175       aDPar = (isLess) ? (aMaxVal - Vparameter) : (aMinVal - Vparameter);
1176       modf(aDPar / Period, &aNbPer);
1177       Vparameter += aNbPer * Period;
1178     }
1179   }
1180 }
1181
1182 //=======================================================================
1183 //function : SetWeight
1184 //purpose  : 
1185 //=======================================================================
1186
1187 void Geom_BSplineSurface::SetWeight (const Standard_Integer UIndex,
1188                                      const Standard_Integer VIndex,
1189                                      const Standard_Real    Weight)
1190 {
1191   if (Weight <= gp::Resolution())
1192     throw Standard_ConstructionError("Geom_BSplineSurface::SetWeight: Weight too small");
1193   TColStd_Array2OfReal & Weights = weights->ChangeArray2();
1194   if (UIndex < 1 || UIndex > Weights.ColLength() ||
1195       VIndex < 1 || VIndex > Weights.RowLength() ) {
1196     throw Standard_OutOfRange("Geom_BSplineSurface::SetWeight: Index and #pole mismatch");
1197   }
1198   Weights (UIndex+Weights.LowerRow()-1, VIndex+Weights.LowerCol()-1) = Weight;
1199   Rational(Weights, urational, vrational);
1200 }
1201
1202 //=======================================================================
1203 //function : SetWeightCol
1204 //purpose  : 
1205 //=======================================================================
1206
1207 void Geom_BSplineSurface::SetWeightCol
1208 (const Standard_Integer       VIndex, 
1209  const TColStd_Array1OfReal&  CPoleWeights)
1210 {
1211   TColStd_Array2OfReal & Weights = weights->ChangeArray2();   
1212   if (VIndex < 1 || VIndex > Weights.RowLength()) {
1213     throw Standard_OutOfRange("Geom_BSplineSurface::SetWeightCol: Index and #pole mismatch");
1214   }
1215   if (CPoleWeights.Lower() < 1 || 
1216       CPoleWeights.Lower() > Weights.ColLength() ||
1217       CPoleWeights.Upper() < 1 ||
1218       CPoleWeights.Upper() > Weights.ColLength()  ) {
1219     throw Standard_ConstructionError("Geom_BSplineSurface::SetWeightCol: invalid array dimension");
1220   }
1221   Standard_Integer I = CPoleWeights.Lower();
1222   while (I <= CPoleWeights.Upper()) {
1223     if (CPoleWeights(I) <= gp::Resolution()) { 
1224       throw Standard_ConstructionError("Geom_BSplineSurface::SetWeightCol: Weight too small");
1225     }
1226     Weights (I+Weights.LowerRow()-1, VIndex+Weights.LowerCol()-1) = 
1227       CPoleWeights (I);
1228     I++;
1229   }
1230   // Verifie si c'est rationnel
1231   Rational(Weights, urational, vrational);
1232 }
1233
1234 //=======================================================================
1235 //function : SetWeightRow
1236 //purpose  : 
1237 //=======================================================================
1238
1239 void Geom_BSplineSurface::SetWeightRow
1240 (const Standard_Integer       UIndex, 
1241  const TColStd_Array1OfReal&  CPoleWeights)
1242 {
1243   TColStd_Array2OfReal & Weights = weights->ChangeArray2();   
1244   if (UIndex < 1 || UIndex > Weights.ColLength()) {
1245     throw Standard_OutOfRange("Geom_BSplineSurface::SetWeightRow: Index and #pole mismatch");
1246   }
1247   if (CPoleWeights.Lower() < 1 ||
1248       CPoleWeights.Lower() > Weights.RowLength() ||
1249       CPoleWeights.Upper() < 1 ||
1250       CPoleWeights.Upper() > Weights.RowLength()  ) {
1251     
1252     throw Standard_ConstructionError("Geom_BSplineSurface::SetWeightRow: invalid array dimension");
1253   }
1254   Standard_Integer I = CPoleWeights.Lower();
1255
1256   while (I <= CPoleWeights.Upper()) {
1257     if (CPoleWeights(I)<=gp::Resolution()) {
1258       throw Standard_ConstructionError("Geom_BSplineSurface::SetWeightRow: Weight too small");
1259     }
1260     Weights (UIndex+Weights.LowerRow()-1, I+Weights.LowerCol()-1) = 
1261       CPoleWeights (I);
1262     I++;
1263   }
1264   // Verifie si c'est rationnel
1265   Rational(Weights, urational, vrational);
1266 }
1267
1268 //=======================================================================
1269 //function : DumpJson
1270 //purpose  : 
1271 //=======================================================================
1272 void Geom_BSplineSurface::DumpJson (Standard_OStream& theOStream, Standard_Integer theDepth) const
1273 {
1274   OCCT_DUMP_TRANSIENT_CLASS_BEGIN (theOStream)
1275   OCCT_DUMP_BASE_CLASS (theOStream, theDepth, Geom_BoundedSurface)
1276
1277   OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, urational)
1278   OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, vrational)
1279   OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, uperiodic)
1280   OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, vperiodic)
1281   OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, uknotSet)
1282   OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, vknotSet)
1283
1284   OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, Usmooth)
1285   OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, Vsmooth)
1286   OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, udeg)
1287   OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, vdeg)
1288
1289   if (!poles.IsNull())
1290     OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, poles->Size())
1291   if (!weights.IsNull())
1292     OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, weights->Size())
1293   if (!ufknots.IsNull())
1294     OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, ufknots->Size())
1295   if (!vfknots.IsNull())
1296     OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, vfknots->Size())
1297
1298   if (!uknots.IsNull())
1299     OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, uknots->Size())
1300   if (!vknots.IsNull())
1301     OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, vknots->Size())
1302   if (!umults.IsNull())
1303     OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, umults->Size())
1304   if (!vmults.IsNull())
1305     OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, vmults->Size())
1306
1307   OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, umaxderivinv)
1308   OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, vmaxderivinv)
1309   OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, maxderivinvok)
1310 }