5316b0c385e7986362381838fc112094c5c5043d
[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   if (Abs(uknots->Value(index1U + 1) - U) <= EpsU)
623     index1U++;
624   BSplCLib::LocateParameter(udeg, uknots->Array1(), umults->Array1(),
625                             NewU1 + deltaU, uperiodic, FromU1, ToU2, index2U, U);
626   if (Abs(uknots->Value(index2U + 1) - U) <= EpsU || index2U == index1U)
627     index2U++;
628
629   Standard_Integer nbuknots = index2U - index1U + 1;
630
631   Handle(TColStd_HArray1OfReal)
632     nuknots = new TColStd_HArray1OfReal(1, nbuknots);
633   Handle(TColStd_HArray1OfInteger)
634     numults = new TColStd_HArray1OfInteger(1, nbuknots);
635
636   Standard_Integer i, k = 1;
637   for (i = index1U; i <= index2U; i++) {
638     nuknots->SetValue(k, uknots->Value(i));
639     numults->SetValue(k, umults->Value(i));
640     k++;
641   }
642   if (SegmentInU) {
643     numults->SetValue(1, udeg + 1);
644     numults->SetValue(nbuknots, udeg + 1);
645   }
646
647   if (vperiodic&& SegmentInV) { // set the origine at NewV1
648     Standard_Integer index = 0;
649     BSplCLib::LocateParameter(vdeg, vknots->Array1(), vmults->Array1(),
650       V1, vperiodic, vknots->Lower(), vknots->Upper(),
651       index, V);
652     if (Abs(vknots->Value(index + 1) - V) <= EpsV)
653       index++;
654     SetVOrigin(index);
655     SetVNotPeriodic();
656   }
657
658   // compute index1 and index2 to set the new knots and mults 
659   Standard_Integer index1V = 0, index2V = 0;
660   Standard_Integer FromV1 = vknots->Lower();
661   Standard_Integer ToV2 = vknots->Upper();
662   BSplCLib::LocateParameter(vdeg, vknots->Array1(), vmults->Array1(),
663                             NewV1, vperiodic, FromV1, ToV2, index1V, V);
664   if (Abs(vknots->Value(index1V + 1) - V) <= EpsV)
665     index1V++;
666   BSplCLib::LocateParameter(vdeg, vknots->Array1(), vmults->Array1(),
667                             NewV1 + deltaV, vperiodic, FromV1, ToV2, index2V, V);
668   if (Abs(vknots->Value(index2V + 1) - V) <= EpsV || index2V == index1V)
669     index2V++;
670
671   Standard_Integer nbvknots = index2V - index1V + 1;
672
673   Handle(TColStd_HArray1OfReal)
674     nvknots = new TColStd_HArray1OfReal(1, nbvknots);
675   Handle(TColStd_HArray1OfInteger)
676     nvmults = new TColStd_HArray1OfInteger(1, nbvknots);
677
678   k = 1;
679   for (i = index1V; i <= index2V; i++) {
680     nvknots->SetValue(k, vknots->Value(i));
681     nvmults->SetValue(k, vmults->Value(i));
682     k++;
683   }
684   if (SegmentInV) {
685     nvmults->SetValue(1, vdeg + 1);
686     nvmults->SetValue(nbvknots, vdeg + 1);
687   }
688
689
690   // compute index1 and index2 to set the new poles and weights
691   Standard_Integer pindex1U
692     = BSplCLib::PoleIndex(udeg, index1U, uperiodic, umults->Array1());
693   Standard_Integer pindex2U
694     = BSplCLib::PoleIndex(udeg, index2U, uperiodic, umults->Array1());
695
696   pindex1U++;
697   pindex2U = Min(pindex2U + 1, poles->ColLength());
698
699   Standard_Integer nbupoles = pindex2U - pindex1U + 1;
700
701   // compute index1 and index2 to set the new poles and weights
702   Standard_Integer pindex1V
703     = BSplCLib::PoleIndex(vdeg, index1V, vperiodic, vmults->Array1());
704   Standard_Integer pindex2V
705     = BSplCLib::PoleIndex(vdeg, index2V, vperiodic, vmults->Array1());
706
707   pindex1V++;
708   pindex2V = Min(pindex2V + 1, poles->RowLength());
709
710   Standard_Integer nbvpoles = pindex2V - pindex1V + 1;
711
712
713   Handle(TColStd_HArray2OfReal) nweights;
714
715   Handle(TColgp_HArray2OfPnt)
716     npoles = new TColgp_HArray2OfPnt(1, nbupoles, 1, nbvpoles);
717   k = 1;
718   Standard_Integer j, l;
719   if (urational || vrational) {
720     nweights = new TColStd_HArray2OfReal(1, nbupoles, 1, nbvpoles);
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         nweights->SetValue(k, l, weights->Value(i, j));
726         l++;
727       }
728       k++;
729     }
730   }
731   else {
732     for (i = pindex1U; i <= pindex2U; i++) {
733       l = 1;
734       for (j = pindex1V; j <= pindex2V; j++) {
735         npoles->SetValue(k, l, poles->Value(i, j));
736         l++;
737       }
738       k++;
739     }
740   }
741
742   uknots = nuknots;
743   umults = numults;
744   vknots = nvknots;
745   vmults = nvmults;
746   poles = npoles;
747   if (urational || vrational)
748     weights = nweights;
749   else
750     weights = new TColStd_HArray2OfReal(1, poles->ColLength(),
751                                         1, poles->RowLength(), 1.0);
752
753   maxderivinvok = 0;
754   UpdateUKnots();
755   UpdateVKnots();
756 }
757
758 //=======================================================================
759 //function : Segment
760 //purpose  : 
761 //=======================================================================
762
763 void Geom_BSplineSurface::Segment(const Standard_Real U1, 
764                                   const Standard_Real U2,
765                                   const Standard_Real V1,
766                                   const Standard_Real V2,
767                                   const Standard_Real theUTolerance,
768                                   const Standard_Real theVTolerance)
769 {
770   if ((U2 < U1) || (V2 < V1))
771     throw Standard_DomainError("Geom_BSplineSurface::Segment");
772
773   Standard_Real aMaxU = Max(Abs(U2), Abs(U1));
774   Standard_Real EpsU = Max(Epsilon(aMaxU), theUTolerance);
775   
776   Standard_Real aMaxV = Max(Abs(V2), Abs(V1));
777   Standard_Real EpsV = Max(Epsilon(aMaxV), theVTolerance);
778
779   segment(U1, U2, V1, V2, EpsU, EpsV, Standard_True, Standard_True);
780 }
781
782 //=======================================================================
783 //function : CheckAndSegment
784 //purpose  : 
785 //=======================================================================
786
787 void Geom_BSplineSurface::CheckAndSegment(const Standard_Real U1, 
788                                           const Standard_Real U2,
789                                           const Standard_Real V1,
790                                           const Standard_Real V2,
791                                           const Standard_Real theUTolerance,
792                                           const Standard_Real theVTolerance)
793 {
794
795   if ((U2 < U1) || (V2 < V1))
796     throw Standard_DomainError("Geom_BSplineSurface::CheckAndSegment");
797
798   Standard_Real aMaxU = Max(Abs(U2), Abs(U1));
799   Standard_Real EpsU = Max(Epsilon(aMaxU), theUTolerance);
800   
801   Standard_Real aMaxV = Max(Abs(V2), Abs(V1));
802   Standard_Real EpsV = Max(Epsilon(aMaxV), theVTolerance);
803
804   Standard_Boolean segment_in_U = Standard_True;
805   Standard_Boolean segment_in_V = Standard_True;
806   segment_in_U = ( Abs(U1 - uknots->Value(uknots->Lower())) > EpsU )
807                         || ( Abs(U2 - uknots->Value(uknots->Upper())) > EpsU );
808   segment_in_V = ( Abs(V1 - vknots->Value(vknots->Lower())) > EpsV )
809                         || ( Abs(V2 - vknots->Value(vknots->Upper())) > EpsV );
810
811   segment(U1, U2, V1, V2, EpsU, EpsV, segment_in_U, segment_in_V);
812 }
813
814 //=======================================================================
815 //function : SetUKnot
816 //purpose  : 
817 //=======================================================================
818
819 void Geom_BSplineSurface::SetUKnot
820 (const Standard_Integer UIndex,
821  const Standard_Real    K      )
822 {
823   if (UIndex < 1 || UIndex > uknots->Length())
824     throw Standard_OutOfRange("Geom_BSplineSurface::SetUKnot: Index and #knots mismatch");
825
826   Standard_Integer NewIndex = UIndex;
827   Standard_Real DU = Abs(Epsilon (K));
828   if (UIndex == 1) {
829     if (K >= uknots->Value (2) - DU)
830       throw Standard_ConstructionError("Geom_BSplineSurface::SetUKnot: K out of range");
831   }
832   else if (UIndex == uknots->Length()) {
833     if (K <= uknots->Value (uknots->Length()-1) + DU)  {
834       throw Standard_ConstructionError("Geom_BSplineSurface::SetUKnot: K out of range");
835     }
836   }
837   else {
838     if (K <= uknots->Value (NewIndex-1) + DU || 
839         K >= uknots->Value (NewIndex+1) - DU ) { 
840       throw Standard_ConstructionError("Geom_BSplineSurface::SetUKnot: K out of range");
841     } 
842   }
843   
844   if (K != uknots->Value (NewIndex)) {
845     uknots->SetValue (NewIndex, K);
846     maxderivinvok = 0;
847     UpdateUKnots();
848   }
849 }
850
851 //=======================================================================
852 //function : SetUKnots
853 //purpose  : 
854 //=======================================================================
855
856 void Geom_BSplineSurface::SetUKnots (const TColStd_Array1OfReal& UK) {
857
858   Standard_Integer Lower = UK.Lower();
859   Standard_Integer Upper = UK.Upper();
860   if (Lower < 1 || Lower > uknots->Length() ||
861       Upper < 1 || Upper > uknots->Length() ) {
862     throw Standard_OutOfRange("Geom_BSplineSurface::SetUKnots: invalid array dimension");
863   }
864   if (Lower > 1) {
865     if (Abs (UK (Lower) - uknots->Value (Lower-1)) <= gp::Resolution()) {
866       throw Standard_ConstructionError("Geom_BSplineSurface::SetUKnots: invalid knot value");
867     }
868   }
869   if (Upper < uknots->Length ()) {
870     if (Abs (UK (Upper) - uknots->Value (Upper+1)) <= gp::Resolution()) {
871       throw Standard_ConstructionError("Geom_BSplineSurface::SetUKnots: invalid knot value");
872     }
873   }
874   Standard_Real K1 = UK (Lower);
875   for (Standard_Integer i = Lower; i <= Upper; i++) {
876     uknots->SetValue (i, UK(i));
877     if (i != Lower) {
878       if (Abs (UK(i) - K1) <= gp::Resolution()) {
879         throw Standard_ConstructionError("Geom_BSplineSurface::SetUKnots: invalid knot value");
880       }
881       K1 = UK (i);
882     }
883   }
884
885   maxderivinvok = 0;
886   UpdateUKnots();
887 }
888
889 //=======================================================================
890 //function : SetUKnot
891 //purpose  : 
892 //=======================================================================
893
894 void Geom_BSplineSurface::SetUKnot
895 (const Standard_Integer UIndex,
896  const Standard_Real    K,
897  const Standard_Integer M)
898 {
899   IncreaseUMultiplicity (UIndex, M);
900   SetUKnot (UIndex, K);
901 }
902
903 //=======================================================================
904 //function : SetVKnot
905 //purpose  : 
906 //=======================================================================
907
908 void Geom_BSplineSurface::SetVKnot
909 (const Standard_Integer VIndex,
910  const Standard_Real    K)
911 {
912   if (VIndex < 1 || VIndex > vknots->Length())
913     throw Standard_OutOfRange("Geom_BSplineSurface::SetVKnot: Index and #knots mismatch");
914   Standard_Integer NewIndex = VIndex + vknots->Lower() - 1;
915   Standard_Real DV = Abs(Epsilon (K));
916   if (VIndex == 1) {
917     if (K >=  vknots->Value (2) - DV) {
918       throw Standard_ConstructionError("Geom_BSplineSurface::SetVKnot: K out of range");
919     }
920   }
921   else if (VIndex == vknots->Length()) {
922     if (K <= vknots->Value (vknots->Length()-1) + DV)  {
923       throw Standard_ConstructionError("Geom_BSplineSurface::SetVKnot: K out of range");
924     }
925   }
926   else {
927     if (K <= vknots->Value (NewIndex-1) + DV || 
928         K >= vknots->Value (NewIndex+1) - DV ) { 
929       throw Standard_ConstructionError("Geom_BSplineSurface::SetVKnot: K out of range");
930     } 
931   }
932   
933   if (K != vknots->Value (NewIndex)) {
934     vknots->SetValue (NewIndex, K);
935     maxderivinvok = 0;
936     UpdateVKnots();
937   }
938 }
939
940 //=======================================================================
941 //function : SetVKnots
942 //purpose  : 
943 //=======================================================================
944
945 void Geom_BSplineSurface::SetVKnots (const TColStd_Array1OfReal& VK) {
946
947   Standard_Integer Lower = VK.Lower();
948   Standard_Integer Upper = VK.Upper();
949   if (Lower < 1 || Lower > vknots->Length() ||
950       Upper < 1 || Upper > vknots->Length() ) {
951     throw Standard_OutOfRange("Geom_BSplineSurface::SetVKnots: invalid array dimension");
952   }
953   if (Lower > 1) {
954     if (Abs (VK (Lower) - vknots->Value (Lower-1)) <= gp::Resolution()) {
955       throw Standard_ConstructionError("Geom_BSplineSurface::SetVKnots: invalid knot value");
956     }
957   }
958   if (Upper < vknots->Length ()) {
959     if (Abs (VK (Upper) - vknots->Value (Upper+1)) <= gp::Resolution()) {
960       throw Standard_ConstructionError("Geom_BSplineSurface::SetVKnots: invalid knot value");
961     }
962   }
963   Standard_Real K1 = VK (Lower);
964   for (Standard_Integer i = Lower; i <= Upper; i++) {
965     vknots->SetValue (i, VK(i));
966     if (i != Lower) {
967       if (Abs (VK(i) - K1) <= gp::Resolution()) {
968         throw Standard_ConstructionError("Geom_BSplineSurface::SetVKnots: invalid knot value");
969       }
970       K1 = VK (i);
971     }
972   }
973
974   maxderivinvok = 0;
975   UpdateVKnots();
976 }
977
978 //=======================================================================
979 //function : SetVKnot
980 //purpose  : 
981 //=======================================================================
982
983 void Geom_BSplineSurface::SetVKnot
984 (const Standard_Integer VIndex,
985  const Standard_Real    K,
986  const Standard_Integer M)
987 {
988   IncreaseVMultiplicity (VIndex, M);
989   SetVKnot (VIndex, K);
990 }
991
992 //=======================================================================
993 //function : InsertUKnot
994 //purpose  : 
995 //=======================================================================
996
997 void Geom_BSplineSurface::InsertUKnot
998 (const Standard_Real    U,
999  const Standard_Integer M,
1000  const Standard_Real    ParametricTolerance,
1001  const Standard_Boolean Add)
1002 {
1003   TColStd_Array1OfReal k(1,1);
1004   k(1) = U;
1005   TColStd_Array1OfInteger m(1,1);
1006   m(1) = M;
1007   InsertUKnots(k,m,ParametricTolerance,Add);
1008 }
1009
1010 //=======================================================================
1011 //function : InsertVKnot
1012 //purpose  : 
1013 //=======================================================================
1014
1015 void Geom_BSplineSurface::InsertVKnot
1016 (const Standard_Real    V,
1017  const Standard_Integer M,
1018  const Standard_Real    ParametricTolerance,
1019  const Standard_Boolean Add)
1020 {
1021   TColStd_Array1OfReal k(1,1);
1022   k(1) = V;
1023   TColStd_Array1OfInteger m(1,1);
1024   m(1) = M;
1025   InsertVKnots(k,m,ParametricTolerance,Add);
1026 }
1027
1028 //=======================================================================
1029 //function : IncrementUMultiplicity
1030 //purpose  : 
1031 //=======================================================================
1032
1033 void  Geom_BSplineSurface::IncrementUMultiplicity
1034 (const Standard_Integer FromI1,
1035  const Standard_Integer ToI2,
1036  const Standard_Integer Step)
1037 {
1038   Handle(TColStd_HArray1OfReal) tk = uknots;
1039   TColStd_Array1OfReal k( (uknots->Array1())(FromI1), FromI1, ToI2);
1040   TColStd_Array1OfInteger m( FromI1, ToI2) ;
1041   m.Init(Step);
1042   InsertUKnots( k, m, Epsilon(1.));
1043 }
1044
1045 //=======================================================================
1046 //function : IncrementVMultiplicity
1047 //purpose  : 
1048 //=======================================================================
1049
1050 void  Geom_BSplineSurface::IncrementVMultiplicity
1051 (const Standard_Integer FromI1,
1052  const Standard_Integer ToI2,
1053  const Standard_Integer Step)
1054 {
1055   Handle(TColStd_HArray1OfReal) tk = vknots;
1056   TColStd_Array1OfReal k( (vknots->Array1())(FromI1), FromI1, ToI2);
1057
1058   TColStd_Array1OfInteger m( FromI1, ToI2) ;
1059   m.Init(Step);
1060   
1061   InsertVKnots( k, m, Epsilon(1.));
1062 }
1063
1064 //=======================================================================
1065 //function : UpdateUKnots
1066 //purpose  : 
1067 //=======================================================================
1068
1069 void Geom_BSplineSurface::UpdateUKnots()
1070 {
1071
1072   Standard_Integer MaxKnotMult = 0;
1073   BSplCLib::KnotAnalysis (udeg, uperiodic,
1074                 uknots->Array1(), 
1075                 umults->Array1(), 
1076                 uknotSet, MaxKnotMult);
1077   
1078   if (uknotSet == GeomAbs_Uniform && !uperiodic)  {
1079     ufknots = uknots;
1080   }
1081   else {
1082     ufknots = new TColStd_HArray1OfReal 
1083       (1, BSplCLib::KnotSequenceLength(umults->Array1(),udeg,uperiodic));
1084
1085     BSplCLib::KnotSequence (uknots->Array1(), 
1086                             umults->Array1(),
1087                             udeg,uperiodic,
1088                             ufknots->ChangeArray1());
1089   }
1090   
1091   if (MaxKnotMult == 0)  Usmooth = GeomAbs_CN;
1092   else {
1093     switch (udeg - MaxKnotMult) {
1094     case 0 :   Usmooth = GeomAbs_C0;   break;
1095     case 1 :   Usmooth = GeomAbs_C1;   break;
1096     case 2 :   Usmooth = GeomAbs_C2;   break;
1097     case 3 :   Usmooth = GeomAbs_C3;   break;
1098       default :  Usmooth = GeomAbs_C3;   break;
1099     }
1100   }
1101 }
1102
1103 //=======================================================================
1104 //function : UpdateVKnots
1105 //purpose  : 
1106 //=======================================================================
1107
1108 void Geom_BSplineSurface::UpdateVKnots()
1109 {
1110   Standard_Integer MaxKnotMult = 0;
1111   BSplCLib::KnotAnalysis (vdeg, vperiodic,
1112                 vknots->Array1(), 
1113                 vmults->Array1(), 
1114                 vknotSet, MaxKnotMult);
1115   
1116   if (vknotSet == GeomAbs_Uniform && !vperiodic)  {
1117     vfknots = vknots;
1118   }
1119   else {
1120     vfknots = new TColStd_HArray1OfReal 
1121       (1, BSplCLib::KnotSequenceLength(vmults->Array1(),vdeg,vperiodic));
1122
1123     BSplCLib::KnotSequence (vknots->Array1(), 
1124                             vmults->Array1(),
1125                             vdeg,vperiodic,
1126                             vfknots->ChangeArray1());
1127   }
1128   
1129   if (MaxKnotMult == 0)  Vsmooth = GeomAbs_CN;
1130   else {
1131     switch (vdeg - MaxKnotMult) {
1132     case 0 :   Vsmooth = GeomAbs_C0;   break;
1133     case 1 :   Vsmooth = GeomAbs_C1;   break;
1134     case 2 :   Vsmooth = GeomAbs_C2;   break;
1135     case 3 :   Vsmooth = GeomAbs_C3;   break;
1136       default :  Vsmooth = GeomAbs_C3;   break;
1137     }
1138   }
1139 }
1140
1141
1142 //=======================================================================
1143 //function : Normalizes the parameters if the curve is periodic
1144 //purpose  : that is compute the cache so that it is valid
1145 //=======================================================================
1146
1147 void Geom_BSplineSurface::PeriodicNormalization
1148 (Standard_Real&  Uparameter, 
1149  Standard_Real&  Vparameter) const 
1150 {
1151   Standard_Real Period, aMaxVal, aMinVal;
1152   
1153   if (uperiodic) {
1154     aMaxVal = ufknots->Value(ufknots->Upper() - udeg);
1155     aMinVal = ufknots->Value (udeg + 1);
1156     Standard_Real eps = Abs(Epsilon(Uparameter));
1157     Period =  aMaxVal - aMinVal;
1158
1159     if(Period <= eps) 
1160       throw Standard_OutOfRange("Geom_BSplineSurface::PeriodicNormalization: Uparameter is too great number");
1161
1162     Standard_Boolean isLess, isGreater;
1163     isLess = aMinVal - Uparameter > 0;
1164     isGreater = Uparameter - aMaxVal > 0;
1165     if (isLess || isGreater) {
1166       Standard_Real aDPar, aNbPer;
1167       aDPar = (isLess) ? (aMaxVal - Uparameter) : (aMinVal - Uparameter);
1168       modf(aDPar / Period, &aNbPer);
1169       Uparameter += aNbPer * Period;
1170     }
1171   }
1172   if (vperiodic) {
1173     aMaxVal = vfknots->Value(vfknots->Upper() - vdeg);
1174     aMinVal = vfknots->Value (vdeg + 1);
1175     Standard_Real eps = Abs(Epsilon(Vparameter));
1176     Period = aMaxVal - aMinVal;
1177
1178     if(Period <= eps) 
1179       throw Standard_OutOfRange("Geom_BSplineSurface::PeriodicNormalization: Vparameter is too great number");
1180
1181     Standard_Boolean isLess, isGreater;
1182     isLess = aMinVal - Vparameter > 0;
1183     isGreater = Vparameter - aMaxVal > 0;
1184     if (isLess || isGreater) {
1185       Standard_Real aDPar, aNbPer;
1186       aDPar = (isLess) ? (aMaxVal - Vparameter) : (aMinVal - Vparameter);
1187       modf(aDPar / Period, &aNbPer);
1188       Vparameter += aNbPer * Period;
1189     }
1190   }
1191 }
1192
1193 //=======================================================================
1194 //function : SetWeight
1195 //purpose  : 
1196 //=======================================================================
1197
1198 void Geom_BSplineSurface::SetWeight (const Standard_Integer UIndex,
1199                                      const Standard_Integer VIndex,
1200                                      const Standard_Real    Weight)
1201 {
1202   if (Weight <= gp::Resolution())
1203     throw Standard_ConstructionError("Geom_BSplineSurface::SetWeight: Weight too small");
1204   TColStd_Array2OfReal & Weights = weights->ChangeArray2();
1205   if (UIndex < 1 || UIndex > Weights.ColLength() ||
1206       VIndex < 1 || VIndex > Weights.RowLength() ) {
1207     throw Standard_OutOfRange("Geom_BSplineSurface::SetWeight: Index and #pole mismatch");
1208   }
1209   Weights (UIndex+Weights.LowerRow()-1, VIndex+Weights.LowerCol()-1) = Weight;
1210   Rational(Weights, urational, vrational);
1211 }
1212
1213 //=======================================================================
1214 //function : SetWeightCol
1215 //purpose  : 
1216 //=======================================================================
1217
1218 void Geom_BSplineSurface::SetWeightCol
1219 (const Standard_Integer       VIndex, 
1220  const TColStd_Array1OfReal&  CPoleWeights)
1221 {
1222   TColStd_Array2OfReal & Weights = weights->ChangeArray2();   
1223   if (VIndex < 1 || VIndex > Weights.RowLength()) {
1224     throw Standard_OutOfRange("Geom_BSplineSurface::SetWeightCol: Index and #pole mismatch");
1225   }
1226   if (CPoleWeights.Lower() < 1 || 
1227       CPoleWeights.Lower() > Weights.ColLength() ||
1228       CPoleWeights.Upper() < 1 ||
1229       CPoleWeights.Upper() > Weights.ColLength()  ) {
1230     throw Standard_ConstructionError("Geom_BSplineSurface::SetWeightCol: invalid array dimension");
1231   }
1232   Standard_Integer I = CPoleWeights.Lower();
1233   while (I <= CPoleWeights.Upper()) {
1234     if (CPoleWeights(I) <= gp::Resolution()) { 
1235       throw Standard_ConstructionError("Geom_BSplineSurface::SetWeightCol: Weight too small");
1236     }
1237     Weights (I+Weights.LowerRow()-1, VIndex+Weights.LowerCol()-1) = 
1238       CPoleWeights (I);
1239     I++;
1240   }
1241   // Verifie si c'est rationnel
1242   Rational(Weights, urational, vrational);
1243 }
1244
1245 //=======================================================================
1246 //function : SetWeightRow
1247 //purpose  : 
1248 //=======================================================================
1249
1250 void Geom_BSplineSurface::SetWeightRow
1251 (const Standard_Integer       UIndex, 
1252  const TColStd_Array1OfReal&  CPoleWeights)
1253 {
1254   TColStd_Array2OfReal & Weights = weights->ChangeArray2();   
1255   if (UIndex < 1 || UIndex > Weights.ColLength()) {
1256     throw Standard_OutOfRange("Geom_BSplineSurface::SetWeightRow: Index and #pole mismatch");
1257   }
1258   if (CPoleWeights.Lower() < 1 ||
1259       CPoleWeights.Lower() > Weights.RowLength() ||
1260       CPoleWeights.Upper() < 1 ||
1261       CPoleWeights.Upper() > Weights.RowLength()  ) {
1262     
1263     throw Standard_ConstructionError("Geom_BSplineSurface::SetWeightRow: invalid array dimension");
1264   }
1265   Standard_Integer I = CPoleWeights.Lower();
1266
1267   while (I <= CPoleWeights.Upper()) {
1268     if (CPoleWeights(I)<=gp::Resolution()) {
1269       throw Standard_ConstructionError("Geom_BSplineSurface::SetWeightRow: Weight too small");
1270     }
1271     Weights (UIndex+Weights.LowerRow()-1, I+Weights.LowerCol()-1) = 
1272       CPoleWeights (I);
1273     I++;
1274   }
1275   // Verifie si c'est rationnel
1276   Rational(Weights, urational, vrational);
1277 }
1278
1279 //=======================================================================
1280 //function : DumpJson
1281 //purpose  : 
1282 //=======================================================================
1283 void Geom_BSplineSurface::DumpJson (Standard_OStream& theOStream, Standard_Integer theDepth) const
1284 {
1285   OCCT_DUMP_TRANSIENT_CLASS_BEGIN (theOStream)
1286   OCCT_DUMP_BASE_CLASS (theOStream, theDepth, Geom_BoundedSurface)
1287
1288   OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, urational)
1289   OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, vrational)
1290   OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, uperiodic)
1291   OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, vperiodic)
1292   OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, uknotSet)
1293   OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, vknotSet)
1294
1295   OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, Usmooth)
1296   OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, Vsmooth)
1297   OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, udeg)
1298   OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, vdeg)
1299
1300   if (!poles.IsNull())
1301     OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, poles->Size())
1302   if (!weights.IsNull())
1303     OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, weights->Size())
1304   if (!ufknots.IsNull())
1305     OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, ufknots->Size())
1306   if (!vfknots.IsNull())
1307     OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, vfknots->Size())
1308
1309   if (!uknots.IsNull())
1310     OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, uknots->Size())
1311   if (!vknots.IsNull())
1312     OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, vknots->Size())
1313   if (!umults.IsNull())
1314     OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, umults->Size())
1315   if (!vmults.IsNull())
1316     OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, vmults->Size())
1317
1318   OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, umaxderivinv)
1319   OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, vmaxderivinv)
1320   OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, maxderivinvok)
1321 }