0027961: Visualization - remove unused and no more working OpenGl_AVIWriter
[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     Standard_ConstructionError::Raise("Geom_BSplineSurface");
66   }
67   if (SPoles.ColLength () < 2 || SPoles.RowLength () < 2) {
68     Standard_ConstructionError::Raise("Geom_BSplineSurface");
69   }
70
71   if (SUKnots.Length() != SUMults.Length() ||
72       SVKnots.Length() != SVMults.Length()) {
73     Standard_ConstructionError::Raise("Geom_BSplineSurface");
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       Standard_ConstructionError::Raise("Geom_BSplineSurface");
80     }
81   }
82
83   for (i = SVKnots.Lower(); i < SVKnots.Upper(); i++) {
84     if (SVKnots(i+1) - SVKnots(i) <= Epsilon(Abs(SVKnots(i)))) {
85       Standard_ConstructionError::Raise("Geom_BSplineSurface");
86     }
87   }
88   
89   if (SPoles.ColLength() != BSplCLib::NbPoles(UDegree,UPeriodic,SUMults))
90     Standard_ConstructionError::Raise("Geom_BSplineSurface");
91
92   if (SPoles.RowLength() != BSplCLib::NbPoles(VDegree,VPeriodic,SVMults))
93     Standard_ConstructionError::Raise("Geom_BSplineSurface");
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     Standard_ConstructionError::Raise("Geom_BSplineSurface");
241
242   if (Weights.RowLength() != Poles.RowLength())
243     Standard_ConstructionError::Raise("Geom_BSplineSurface");
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         Standard_ConstructionError::Raise("Geom_BSplineSurface");
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       Standard_ConstructionError::Raise();
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       Standard_ConstructionError::Raise();
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 {
541   if ((U2 < U1) || (V2 < V1))
542     Standard_DomainError::Raise("Geom_BSplineSurface::Segment");
543   Standard_Real deltaU = Max(Abs(U2),Abs(U1));
544   Standard_Real EpsU = Epsilon(deltaU);
545   deltaU = U2 - U1;
546   if (uperiodic) {
547     Standard_Real aUPeriod = uknots->Last() - uknots->First();
548     if (deltaU - aUPeriod > Precision::PConfusion())
549       Standard_DomainError::Raise("Geom_BSplineSurface::Segment");
550     if (deltaU > aUPeriod)
551       deltaU = aUPeriod;
552   }
553   
554   Standard_Real deltaV = Max(Abs(V2),Abs(V1));
555   Standard_Real EpsV = Epsilon(deltaV);
556   deltaV = V2 - V1;
557   if (vperiodic) {
558     Standard_Real aVPeriod = vknots->Last() - vknots->First();
559     if (deltaV - aVPeriod > Precision::PConfusion())
560       Standard_DomainError::Raise("Geom_BSplineSurface::Segment");
561     if (deltaV > aVPeriod)
562       deltaV = aVPeriod;
563   }
564
565   Standard_Real NewU1, NewU2, NewV1, NewV2;
566   Standard_Real U,V;
567   Standard_Integer indexU, indexV;
568
569   // inserting the UKnots
570   TColStd_Array1OfReal    UKnots(1,2);
571   TColStd_Array1OfInteger UMults(1,2);
572
573   indexU = 0;
574   BSplCLib::LocateParameter(udeg,uknots->Array1(),umults->Array1(),
575                             U1,uperiodic,uknots->Lower(),uknots->Upper(),
576                             indexU,NewU1);
577   indexU = 0;
578   BSplCLib::LocateParameter(udeg,uknots->Array1(),umults->Array1(),
579                             U2,uperiodic,uknots->Lower(),uknots->Upper(),
580                             indexU,NewU2);
581   UKnots( 1) = Min( NewU1, NewU2);
582   UKnots( 2) = Max( NewU1, NewU2);
583   UMults( 1) = UMults( 2) = udeg;
584   InsertUKnots( UKnots, UMults, EpsU);
585
586   // Inserting the VKnots
587   TColStd_Array1OfReal    VKnots(1,2);
588   TColStd_Array1OfInteger VMults(1,2);
589
590   indexV = 0;
591   BSplCLib::LocateParameter(vdeg,vknots->Array1(),vmults->Array1(),
592                             V1,vperiodic,vknots->Lower(),vknots->Upper(),
593                             indexV,NewV1);
594   indexV = 0;
595   BSplCLib::LocateParameter(vdeg,vknots->Array1(),vmults->Array1(),
596                             V2,vperiodic,vknots->Lower(),vknots->Upper(),
597                             indexV,NewV2);
598   VKnots( 1) = Min( NewV1, NewV2);
599   VKnots( 2) = Max( NewV1, NewV2);
600   VMults( 1) = VMults( 2) = vdeg;
601   InsertVKnots( VKnots, VMults, EpsV);
602
603
604   if (uperiodic) { // set the origine at NewU1
605     Standard_Integer index = 0;
606     BSplCLib::LocateParameter(udeg,uknots->Array1(),umults->Array1(),
607                               U1,uperiodic,uknots->Lower(),uknots->Upper(),
608                               index,U);
609     if ( Abs(uknots->Value(index+1)-U) <= EpsU)
610       index++;
611     SetUOrigin(index);
612     SetUNotPeriodic();
613   }
614
615   // compute index1 and index2 to set the new knots and mults 
616   Standard_Integer index1U = 0, index2U = 0;
617   Standard_Integer FromU1 = uknots->Lower();
618   Standard_Integer ToU2   = uknots->Upper();
619   BSplCLib::LocateParameter(udeg,uknots->Array1(),umults->Array1(),
620                             NewU1,uperiodic,FromU1,ToU2,index1U,U);
621   BSplCLib::LocateParameter(udeg,uknots->Array1(),umults->Array1(),
622                             NewU1 + deltaU,uperiodic,FromU1,ToU2,index2U,U);
623   if ( Abs(uknots->Value(index2U+1)-U) <= EpsU)
624     index2U++;
625   
626   Standard_Integer nbuknots = index2U - index1U + 1;
627
628   Handle(TColStd_HArray1OfReal) 
629     nuknots = new TColStd_HArray1OfReal(1,nbuknots);
630   Handle(TColStd_HArray1OfInteger) 
631     numults = new TColStd_HArray1OfInteger(1,nbuknots);
632
633   Standard_Integer i , k = 1;
634   for ( i = index1U; i<= index2U; i++) {
635     nuknots->SetValue(k, uknots->Value(i));
636     numults->SetValue(k, umults->Value(i));
637     k++;
638   }
639   numults->SetValue(       1, udeg + 1);
640   numults->SetValue(nbuknots, udeg + 1);
641
642
643   if (vperiodic) { // set the origine at NewV1
644     Standard_Integer index = 0;
645     BSplCLib::LocateParameter(vdeg,vknots->Array1(),vmults->Array1(),
646                               V1,vperiodic,vknots->Lower(),vknots->Upper(),
647                               index,V);
648     if ( Abs(vknots->Value(index+1)-V) <= EpsV)
649       index++;
650     SetVOrigin(index);
651     SetVNotPeriodic();
652   }
653
654   // compute index1 and index2 to set the new knots and mults 
655   Standard_Integer index1V = 0, index2V = 0;
656   Standard_Integer FromV1 = vknots->Lower();
657   Standard_Integer ToV2   = vknots->Upper();
658   BSplCLib::LocateParameter(vdeg,vknots->Array1(),vmults->Array1(),
659                             NewV1,vperiodic,FromV1,ToV2,index1V,V);
660   BSplCLib::LocateParameter(vdeg,vknots->Array1(),vmults->Array1(),
661                             NewV1 + deltaV,vperiodic,FromV1,ToV2,index2V,V);
662   if ( Abs(vknots->Value(index2V+1)-V) <= EpsV)
663     index2V++;
664   
665   Standard_Integer nbvknots = index2V - index1V + 1;
666
667   Handle(TColStd_HArray1OfReal) 
668     nvknots = new TColStd_HArray1OfReal(1,nbvknots);
669   Handle(TColStd_HArray1OfInteger) 
670     nvmults = new TColStd_HArray1OfInteger(1,nbvknots);
671
672   k = 1;
673   for ( i = index1V; i<= index2V; i++) {
674     nvknots->SetValue(k, vknots->Value(i));
675     nvmults->SetValue(k, vmults->Value(i));
676     k++;
677   }
678   nvmults->SetValue(       1, vdeg + 1);
679   nvmults->SetValue(nbvknots, vdeg + 1);
680
681
682   // compute index1 and index2 to set the new poles and weights
683   Standard_Integer pindex1U 
684     = BSplCLib::PoleIndex(udeg,index1U,uperiodic,umults->Array1());
685   Standard_Integer pindex2U 
686     = BSplCLib::PoleIndex(udeg,index2U,uperiodic,umults->Array1());
687
688   pindex1U++;
689   pindex2U = Min( pindex2U+1, poles->ColLength());
690
691   Standard_Integer nbupoles  = pindex2U - pindex1U + 1;
692
693   // compute index1 and index2 to set the new poles and weights
694   Standard_Integer pindex1V 
695     = BSplCLib::PoleIndex(vdeg,index1V,vperiodic,vmults->Array1());
696   Standard_Integer pindex2V 
697     = BSplCLib::PoleIndex(vdeg,index2V,vperiodic,vmults->Array1());
698
699   pindex1V++;
700   pindex2V = Min( pindex2V+1, poles->RowLength());
701
702   Standard_Integer nbvpoles  = pindex2V - pindex1V + 1;
703
704
705   Handle(TColStd_HArray2OfReal) nweights; 
706
707   Handle(TColgp_HArray2OfPnt)
708     npoles = new TColgp_HArray2OfPnt(1,nbupoles,1,nbvpoles);
709
710   k = 1;
711   Standard_Integer j, l;
712   if ( urational || vrational) {
713     nweights = new TColStd_HArray2OfReal( 1,nbupoles,1,nbvpoles);
714     for ( i = pindex1U; i <= pindex2U; i++) {
715       l = 1;
716       for ( j = pindex1V; j <= pindex2V; j++) {
717         npoles->SetValue(k,l, poles->Value(i,j));
718         nweights->SetValue(k,l, weights->Value(i,j));
719         l++;
720       }
721       k++;
722     }
723   }
724   else {
725     for ( i = pindex1U; i <= pindex2U; i++) {
726       l = 1;
727       for ( j = pindex1V; j <= pindex2V; j++) {
728         npoles->SetValue(k,l, poles->Value(i,j));
729         l++;
730       }
731       k++;
732     }
733   }
734
735   uknots = nuknots;
736   umults = numults;
737   vknots = nvknots;
738   vmults = nvmults;
739   poles = npoles;
740   if ( urational || vrational) 
741     weights = nweights;
742   else 
743     weights = new TColStd_HArray2OfReal (1,poles->ColLength(),
744                                          1,poles->RowLength(), 1.0);
745
746   maxderivinvok = 0;
747   UpdateUKnots();
748   UpdateVKnots();
749
750 }
751
752 //=======================================================================
753 //function : CheckAndSegment
754 //purpose  : 
755 //=======================================================================
756
757 void Geom_BSplineSurface::CheckAndSegment(const Standard_Real U1, 
758                                           const Standard_Real U2,
759                                           const Standard_Real V1,
760                                           const Standard_Real V2) 
761 {
762
763   if ((U2 < U1) || (V2 < V1))
764     Standard_DomainError::Raise("Geom_BSplineSurface::CheckAndSegment");
765   Standard_Real deltaU = Max(Abs(U2),Abs(U1));
766   Standard_Real EpsU = Epsilon(deltaU);
767   deltaU = U2 - U1;
768   if (uperiodic) {
769     Standard_Real aUPeriod = uknots->Last() - uknots->First();
770     if (deltaU - aUPeriod > Precision::PConfusion())
771       Standard_DomainError::Raise("Geom_BSplineSurface::CheckAndSegment");
772     if (deltaU > aUPeriod)
773       deltaU = aUPeriod;
774   }
775   
776   Standard_Real deltaV = Max(Abs(V2),Abs(V1));
777   Standard_Real EpsV = Epsilon(deltaV);
778   deltaV = V2 - V1;
779   if (vperiodic) {
780     Standard_Real aVPeriod = vknots->Last() - vknots->First();
781     if (deltaV - aVPeriod > Precision::PConfusion())
782       Standard_DomainError::Raise("Geom_BSplineSurface::CheckAndSegment");
783     if (deltaV > aVPeriod)
784       deltaV = aVPeriod;
785   }
786
787   Standard_Real NewU1, NewU2, NewV1, NewV2;
788   Standard_Real U,V;
789   Standard_Integer indexU, indexV;
790
791   Standard_Boolean segment_in_U = Standard_True;
792   Standard_Boolean segment_in_V = Standard_True;
793   segment_in_U = ( Abs(U1 - uknots->Value(uknots->Lower())) > EpsU )
794                         || ( Abs(U2 - uknots->Value(uknots->Upper())) > EpsU );
795   segment_in_V = ( Abs(V1 - vknots->Value(vknots->Lower())) > EpsV )
796                         || ( Abs(V2 - vknots->Value(vknots->Upper())) > EpsV );
797
798   indexU = 0;
799   BSplCLib::LocateParameter(udeg,uknots->Array1(),umults->Array1(),
800                             U1,uperiodic,uknots->Lower(),uknots->Upper(),
801                             indexU,NewU1);
802   indexU = 0;
803   BSplCLib::LocateParameter(udeg,uknots->Array1(),umults->Array1(),
804                             U2,uperiodic,uknots->Lower(),uknots->Upper(),
805                             indexU,NewU2);
806   if (segment_in_U) {
807     // inserting the UKnots
808     TColStd_Array1OfReal    UKnots(1,2);
809     TColStd_Array1OfInteger UMults(1,2);
810     UKnots( 1) = Min( NewU1, NewU2);
811     UKnots( 2) = Max( NewU1, NewU2);
812     UMults( 1) = UMults( 2) = udeg;
813     
814     InsertUKnots( UKnots, UMults, EpsU);
815   }
816
817   indexV = 0;
818   BSplCLib::LocateParameter(vdeg,vknots->Array1(),vmults->Array1(),
819                             V1,vperiodic,vknots->Lower(),vknots->Upper(),
820                             indexV,NewV1);
821   indexV = 0;
822   BSplCLib::LocateParameter(vdeg,vknots->Array1(),vmults->Array1(),
823                             V2,vperiodic,vknots->Lower(),vknots->Upper(),
824                             indexV,NewV2);
825   if (segment_in_V) {
826     // Inserting the VKnots
827     TColStd_Array1OfReal    VKnots(1,2);
828     TColStd_Array1OfInteger VMults(1,2);
829     
830     VKnots( 1) = Min( NewV1, NewV2);
831     VKnots( 2) = Max( NewV1, NewV2);
832     VMults( 1) = VMults( 2) = vdeg;
833     InsertVKnots( VKnots, VMults, EpsV);
834   }
835
836   if (uperiodic && segment_in_U) { // set the origine at NewU1
837     Standard_Integer index = 0;
838     BSplCLib::LocateParameter(udeg,uknots->Array1(),umults->Array1(),
839                               U1,uperiodic,uknots->Lower(),uknots->Upper(),
840                               index,U);
841     if ( Abs(uknots->Value(index+1)-U) <= EpsU)
842       index++;
843     SetUOrigin(index);
844     SetUNotPeriodic();
845   }
846
847   // compute index1 and index2 to set the new knots and mults 
848   Standard_Integer index1U = 0, index2U = 0;
849   Standard_Integer FromU1 = uknots->Lower();
850   Standard_Integer ToU2   = uknots->Upper();
851   BSplCLib::LocateParameter(udeg,uknots->Array1(),umults->Array1(),
852                             NewU1,uperiodic,FromU1,ToU2,index1U,U);
853   BSplCLib::LocateParameter(udeg,uknots->Array1(),umults->Array1(),
854                             NewU1 + deltaU,uperiodic,FromU1,ToU2,index2U,U);
855   if ( Abs(uknots->Value(index2U+1)-U) <= EpsU)
856     index2U++;
857   
858   Standard_Integer nbuknots = index2U - index1U + 1;
859
860   Handle(TColStd_HArray1OfReal) 
861     nuknots = new TColStd_HArray1OfReal(1,nbuknots);
862   Handle(TColStd_HArray1OfInteger) 
863     numults = new TColStd_HArray1OfInteger(1,nbuknots);
864
865   Standard_Integer i , k = 1;
866   for ( i = index1U; i<= index2U; i++) {
867     nuknots->SetValue(k, uknots->Value(i));
868     numults->SetValue(k, umults->Value(i));
869     k++;
870   }
871   if (segment_in_U) {
872     numults->SetValue(       1, udeg + 1);
873     numults->SetValue(nbuknots, udeg + 1);
874   }
875
876   if (vperiodic&& segment_in_V) { // set the origine at NewV1
877     Standard_Integer index = 0;
878     BSplCLib::LocateParameter(vdeg,vknots->Array1(),vmults->Array1(),
879                               V1,vperiodic,vknots->Lower(),vknots->Upper(),
880                               index,V);
881     if ( Abs(vknots->Value(index+1)-V) <= EpsV)
882       index++;
883     SetVOrigin(index);
884     SetVNotPeriodic();
885   }
886
887   // compute index1 and index2 to set the new knots and mults 
888   Standard_Integer index1V = 0, index2V = 0;
889   Standard_Integer FromV1 = vknots->Lower();
890   Standard_Integer ToV2   = vknots->Upper();
891   BSplCLib::LocateParameter(vdeg,vknots->Array1(),vmults->Array1(),
892                             NewV1,vperiodic,FromV1,ToV2,index1V,V);
893   BSplCLib::LocateParameter(vdeg,vknots->Array1(),vmults->Array1(),
894                             NewV1 + deltaV,vperiodic,FromV1,ToV2,index2V,V);
895   if ( Abs(vknots->Value(index2V+1)-V) <= EpsV)
896     index2V++;
897   
898   Standard_Integer nbvknots = index2V - index1V + 1;
899
900   Handle(TColStd_HArray1OfReal) 
901     nvknots = new TColStd_HArray1OfReal(1,nbvknots);
902   Handle(TColStd_HArray1OfInteger) 
903     nvmults = new TColStd_HArray1OfInteger(1,nbvknots);
904
905   k = 1;
906   for ( i = index1V; i<= index2V; i++) {
907     nvknots->SetValue(k, vknots->Value(i));
908     nvmults->SetValue(k, vmults->Value(i));
909     k++;
910   }
911   if (segment_in_V) {
912     nvmults->SetValue(       1, vdeg + 1);
913     nvmults->SetValue(nbvknots, vdeg + 1);
914   }
915
916   // compute index1 and index2 to set the new poles and weights
917   Standard_Integer pindex1U 
918     = BSplCLib::PoleIndex(udeg,index1U,uperiodic,umults->Array1());
919   Standard_Integer pindex2U 
920     = BSplCLib::PoleIndex(udeg,index2U,uperiodic,umults->Array1());
921
922   pindex1U++;
923   pindex2U = Min( pindex2U+1, poles->ColLength());
924
925   Standard_Integer nbupoles  = pindex2U - pindex1U + 1;
926
927   // compute index1 and index2 to set the new poles and weights
928   Standard_Integer pindex1V 
929     = BSplCLib::PoleIndex(vdeg,index1V,vperiodic,vmults->Array1());
930   Standard_Integer pindex2V 
931     = BSplCLib::PoleIndex(vdeg,index2V,vperiodic,vmults->Array1());
932
933   pindex1V++;
934   pindex2V = Min( pindex2V+1, poles->RowLength());
935
936   Standard_Integer nbvpoles  = pindex2V - pindex1V + 1;
937
938
939   Handle(TColStd_HArray2OfReal) nweights; 
940
941   Handle(TColgp_HArray2OfPnt)
942     npoles = new TColgp_HArray2OfPnt(1,nbupoles,1,nbvpoles);
943
944   k = 1;
945   Standard_Integer j, l;
946   if ( urational || vrational) {
947     nweights = new TColStd_HArray2OfReal( 1,nbupoles,1,nbvpoles);
948     for ( i = pindex1U; i <= pindex2U; i++) {
949       l = 1;
950       for ( j = pindex1V; j <= pindex2V; j++) {
951         npoles->SetValue(k,l, poles->Value(i,j));
952         nweights->SetValue(k,l, weights->Value(i,j));
953         l++;
954       }
955       k++;
956     }
957   }
958   else {
959     for ( i = pindex1U; i <= pindex2U; i++) {
960       l = 1;
961       for ( j = pindex1V; j <= pindex2V; j++) {
962         npoles->SetValue(k,l, poles->Value(i,j));
963         l++;
964       }
965       k++;
966     }
967   }
968
969   uknots = nuknots;
970   umults = numults;
971   vknots = nvknots;
972   vmults = nvmults;
973   poles = npoles;
974   if ( urational || vrational) 
975     weights = nweights;
976   else 
977     weights = new TColStd_HArray2OfReal (1,poles->ColLength(),
978                                          1,poles->RowLength(), 1.0);
979
980   maxderivinvok = 0;
981   UpdateUKnots();
982   UpdateVKnots();
983
984 }
985
986 //=======================================================================
987 //function : SetUKnot
988 //purpose  : 
989 //=======================================================================
990
991 void Geom_BSplineSurface::SetUKnot
992 (const Standard_Integer UIndex,
993  const Standard_Real    K      )
994 {
995   if (UIndex < 1 || UIndex > uknots->Length()) Standard_OutOfRange::Raise();
996
997   Standard_Integer NewIndex = UIndex;
998   Standard_Real DU = Abs(Epsilon (K));
999   if (UIndex == 1) {
1000     if (K >= uknots->Value (2) - DU) Standard_ConstructionError::Raise();
1001   }
1002   else if (UIndex == uknots->Length()) {
1003     if (K <= uknots->Value (uknots->Length()-1) + DU)  {
1004       Standard_ConstructionError::Raise();
1005     }
1006   }
1007   else {
1008     if (K <= uknots->Value (NewIndex-1) + DU || 
1009         K >= uknots->Value (NewIndex+1) - DU ) { 
1010       Standard_ConstructionError::Raise();
1011     } 
1012   }
1013   
1014   if (K != uknots->Value (NewIndex)) {
1015     uknots->SetValue (NewIndex, K);
1016     maxderivinvok = 0;
1017     UpdateUKnots();
1018   }
1019 }
1020
1021 //=======================================================================
1022 //function : SetUKnots
1023 //purpose  : 
1024 //=======================================================================
1025
1026 void Geom_BSplineSurface::SetUKnots (const TColStd_Array1OfReal& UK) {
1027
1028   Standard_Integer Lower = UK.Lower();
1029   Standard_Integer Upper = UK.Upper();
1030   if (Lower < 1 || Lower > uknots->Length() ||
1031       Upper < 1 || Upper > uknots->Length() ) {
1032     Standard_OutOfRange::Raise();
1033   }
1034   if (Lower > 1) {
1035     if (Abs (UK (Lower) - uknots->Value (Lower-1)) <= gp::Resolution()) {
1036       Standard_ConstructionError::Raise();
1037     }
1038   }
1039   if (Upper < uknots->Length ()) {
1040     if (Abs (UK (Upper) - uknots->Value (Upper+1)) <= gp::Resolution()) {
1041       Standard_ConstructionError::Raise();
1042     }
1043   }
1044   Standard_Real K1 = UK (Lower);
1045   for (Standard_Integer i = Lower; i <= Upper; i++) {
1046     uknots->SetValue (i, UK(i));
1047     if (i != Lower) {
1048       if (Abs (UK(i) - K1) <= gp::Resolution()) {
1049         Standard_ConstructionError::Raise();
1050       }
1051       K1 = UK (i);
1052     }
1053   }
1054
1055   maxderivinvok = 0;
1056   UpdateUKnots();
1057 }
1058
1059 //=======================================================================
1060 //function : SetUKnot
1061 //purpose  : 
1062 //=======================================================================
1063
1064 void Geom_BSplineSurface::SetUKnot
1065 (const Standard_Integer UIndex,
1066  const Standard_Real    K,
1067  const Standard_Integer M)
1068 {
1069   IncreaseUMultiplicity (UIndex, M);
1070   SetUKnot (UIndex, K);
1071 }
1072
1073 //=======================================================================
1074 //function : SetVKnot
1075 //purpose  : 
1076 //=======================================================================
1077
1078 void Geom_BSplineSurface::SetVKnot
1079 (const Standard_Integer VIndex,
1080  const Standard_Real    K)
1081 {
1082   if (VIndex < 1 || VIndex > vknots->Length())  Standard_OutOfRange::Raise();
1083   Standard_Integer NewIndex = VIndex + vknots->Lower() - 1;
1084   Standard_Real DV = Abs(Epsilon (K));
1085   if (VIndex == 1) {
1086     if (K >=  vknots->Value (2) - DV) {
1087       Standard_ConstructionError::Raise();
1088     }
1089   }
1090   else if (VIndex == vknots->Length()) {
1091     if (K <= vknots->Value (vknots->Length()-1) + DV)  {
1092       Standard_ConstructionError::Raise();
1093     }
1094   }
1095   else {
1096     if (K <= vknots->Value (NewIndex-1) + DV || 
1097         K >= vknots->Value (NewIndex+1) - DV ) { 
1098       Standard_ConstructionError::Raise();
1099     } 
1100   }
1101   
1102   if (K != vknots->Value (NewIndex)) {
1103     vknots->SetValue (NewIndex, K);
1104     maxderivinvok = 0;
1105     UpdateVKnots();
1106   }
1107 }
1108
1109 //=======================================================================
1110 //function : SetVKnots
1111 //purpose  : 
1112 //=======================================================================
1113
1114 void Geom_BSplineSurface::SetVKnots (const TColStd_Array1OfReal& VK) {
1115
1116   Standard_Integer Lower = VK.Lower();
1117   Standard_Integer Upper = VK.Upper();
1118   if (Lower < 1 || Lower > vknots->Length() ||
1119       Upper < 1 || Upper > vknots->Length() ) {
1120     Standard_OutOfRange::Raise();
1121   }
1122   if (Lower > 1) {
1123     if (Abs (VK (Lower) - vknots->Value (Lower-1)) <= gp::Resolution()) {
1124       Standard_ConstructionError::Raise();
1125     }
1126   }
1127   if (Upper < vknots->Length ()) {
1128     if (Abs (VK (Upper) - vknots->Value (Upper+1)) <= gp::Resolution()) {
1129       Standard_ConstructionError::Raise();
1130     }
1131   }
1132   Standard_Real K1 = VK (Lower);
1133   for (Standard_Integer i = Lower; i <= Upper; i++) {
1134     vknots->SetValue (i, VK(i));
1135     if (i != Lower) {
1136       if (Abs (VK(i) - K1) <= gp::Resolution()) {
1137         Standard_ConstructionError::Raise();
1138       }
1139       K1 = VK (i);
1140     }
1141   }
1142
1143   maxderivinvok = 0;
1144   UpdateVKnots();
1145 }
1146
1147 //=======================================================================
1148 //function : SetVKnot
1149 //purpose  : 
1150 //=======================================================================
1151
1152 void Geom_BSplineSurface::SetVKnot
1153 (const Standard_Integer VIndex,
1154  const Standard_Real    K,
1155  const Standard_Integer M)
1156 {
1157   IncreaseVMultiplicity (VIndex, M);
1158   SetVKnot (VIndex, K);
1159 }
1160
1161 //=======================================================================
1162 //function : InsertUKnot
1163 //purpose  : 
1164 //=======================================================================
1165
1166 void Geom_BSplineSurface::InsertUKnot
1167 (const Standard_Real    U,
1168  const Standard_Integer M,
1169  const Standard_Real    ParametricTolerance,
1170  const Standard_Boolean Add)
1171 {
1172   TColStd_Array1OfReal k(1,1);
1173   k(1) = U;
1174   TColStd_Array1OfInteger m(1,1);
1175   m(1) = M;
1176   InsertUKnots(k,m,ParametricTolerance,Add);
1177 }
1178
1179 //=======================================================================
1180 //function : InsertVKnot
1181 //purpose  : 
1182 //=======================================================================
1183
1184 void Geom_BSplineSurface::InsertVKnot
1185 (const Standard_Real    V,
1186  const Standard_Integer M,
1187  const Standard_Real    ParametricTolerance,
1188  const Standard_Boolean Add)
1189 {
1190   TColStd_Array1OfReal k(1,1);
1191   k(1) = V;
1192   TColStd_Array1OfInteger m(1,1);
1193   m(1) = M;
1194   InsertVKnots(k,m,ParametricTolerance,Add);
1195 }
1196
1197 //=======================================================================
1198 //function : IncrementUMultiplicity
1199 //purpose  : 
1200 //=======================================================================
1201
1202 void  Geom_BSplineSurface::IncrementUMultiplicity
1203 (const Standard_Integer FromI1,
1204  const Standard_Integer ToI2,
1205  const Standard_Integer Step)
1206 {
1207   Handle(TColStd_HArray1OfReal) tk = uknots;
1208   TColStd_Array1OfReal k( (uknots->Array1())(FromI1), FromI1, ToI2);
1209   TColStd_Array1OfInteger m( FromI1, ToI2) ;
1210   m.Init(Step);
1211   InsertUKnots( k, m, Epsilon(1.));
1212 }
1213
1214 //=======================================================================
1215 //function : IncrementVMultiplicity
1216 //purpose  : 
1217 //=======================================================================
1218
1219 void  Geom_BSplineSurface::IncrementVMultiplicity
1220 (const Standard_Integer FromI1,
1221  const Standard_Integer ToI2,
1222  const Standard_Integer Step)
1223 {
1224   Handle(TColStd_HArray1OfReal) tk = vknots;
1225   TColStd_Array1OfReal k( (vknots->Array1())(FromI1), FromI1, ToI2);
1226
1227   TColStd_Array1OfInteger m( FromI1, ToI2) ;
1228   m.Init(Step);
1229   
1230   InsertVKnots( k, m, Epsilon(1.));
1231 }
1232
1233 //=======================================================================
1234 //function : UpdateUKnots
1235 //purpose  : 
1236 //=======================================================================
1237
1238 void Geom_BSplineSurface::UpdateUKnots()
1239 {
1240
1241   Standard_Integer MaxKnotMult = 0;
1242   BSplCLib::KnotAnalysis (udeg, uperiodic,
1243                 uknots->Array1(), 
1244                 umults->Array1(), 
1245                 uknotSet, MaxKnotMult);
1246   
1247   if (uknotSet == GeomAbs_Uniform && !uperiodic)  {
1248     ufknots = uknots;
1249   }
1250   else {
1251     ufknots = new TColStd_HArray1OfReal 
1252       (1, BSplCLib::KnotSequenceLength(umults->Array1(),udeg,uperiodic));
1253
1254     BSplCLib::KnotSequence (uknots->Array1(), 
1255                             umults->Array1(),
1256                             udeg,uperiodic,
1257                             ufknots->ChangeArray1());
1258   }
1259   
1260   if (MaxKnotMult == 0)  Usmooth = GeomAbs_CN;
1261   else {
1262     switch (udeg - MaxKnotMult) {
1263     case 0 :   Usmooth = GeomAbs_C0;   break;
1264     case 1 :   Usmooth = GeomAbs_C1;   break;
1265     case 2 :   Usmooth = GeomAbs_C2;   break;
1266     case 3 :   Usmooth = GeomAbs_C3;   break;
1267       default :  Usmooth = GeomAbs_C3;   break;
1268     }
1269   }
1270 }
1271
1272 //=======================================================================
1273 //function : UpdateVKnots
1274 //purpose  : 
1275 //=======================================================================
1276
1277 void Geom_BSplineSurface::UpdateVKnots()
1278 {
1279   Standard_Integer MaxKnotMult = 0;
1280   BSplCLib::KnotAnalysis (vdeg, vperiodic,
1281                 vknots->Array1(), 
1282                 vmults->Array1(), 
1283                 vknotSet, MaxKnotMult);
1284   
1285   if (vknotSet == GeomAbs_Uniform && !vperiodic)  {
1286     vfknots = vknots;
1287   }
1288   else {
1289     vfknots = new TColStd_HArray1OfReal 
1290       (1, BSplCLib::KnotSequenceLength(vmults->Array1(),vdeg,vperiodic));
1291
1292     BSplCLib::KnotSequence (vknots->Array1(), 
1293                             vmults->Array1(),
1294                             vdeg,vperiodic,
1295                             vfknots->ChangeArray1());
1296   }
1297   
1298   if (MaxKnotMult == 0)  Vsmooth = GeomAbs_CN;
1299   else {
1300     switch (vdeg - MaxKnotMult) {
1301     case 0 :   Vsmooth = GeomAbs_C0;   break;
1302     case 1 :   Vsmooth = GeomAbs_C1;   break;
1303     case 2 :   Vsmooth = GeomAbs_C2;   break;
1304     case 3 :   Vsmooth = GeomAbs_C3;   break;
1305       default :  Vsmooth = GeomAbs_C3;   break;
1306     }
1307   }
1308 }
1309
1310
1311 //=======================================================================
1312 //function : Normalizes the parameters if the curve is periodic
1313 //purpose  : that is compute the cache so that it is valid
1314 //=======================================================================
1315
1316 void Geom_BSplineSurface::PeriodicNormalization
1317 (Standard_Real&  Uparameter, 
1318  Standard_Real&  Vparameter) const 
1319 {
1320   Standard_Real Period, aMaxVal, aMinVal;
1321   
1322   if (uperiodic) {
1323     aMaxVal = ufknots->Value(ufknots->Upper() - udeg);
1324     aMinVal = ufknots->Value (udeg + 1);
1325     Standard_Real eps = Abs(Epsilon(Uparameter));
1326     Period =  aMaxVal - aMinVal;
1327
1328     if(Period <= eps) 
1329       Standard_OutOfRange::Raise("Geom_BSplineSurface::PeriodicNormalization: Uparameter is too great number");
1330
1331     Standard_Boolean isLess, isGreater;
1332     isLess = aMinVal - Uparameter > 0;
1333     isGreater = Uparameter - aMaxVal > 0;
1334     if (isLess || isGreater) {
1335       Standard_Real aDPar, aNbPer;
1336       aDPar = (isLess) ? (aMaxVal - Uparameter) : (aMinVal - Uparameter);
1337       modf(aDPar / Period, &aNbPer);
1338       Uparameter += aNbPer * Period;
1339     }
1340   }
1341   if (vperiodic) {
1342     aMaxVal = vfknots->Value(vfknots->Upper() - vdeg);
1343     aMinVal = vfknots->Value (vdeg + 1);
1344     Standard_Real eps = Abs(Epsilon(Vparameter));
1345     Period = aMaxVal - aMinVal;
1346
1347     if(Period <= eps) 
1348       Standard_OutOfRange::Raise("Geom_BSplineSurface::PeriodicNormalization: Vparameter is too great number");
1349
1350     Standard_Boolean isLess, isGreater;
1351     isLess = aMinVal - Vparameter > 0;
1352     isGreater = Vparameter - aMaxVal > 0;
1353     if (isLess || isGreater) {
1354       Standard_Real aDPar, aNbPer;
1355       aDPar = (isLess) ? (aMaxVal - Vparameter) : (aMinVal - Vparameter);
1356       modf(aDPar / Period, &aNbPer);
1357       Vparameter += aNbPer * Period;
1358     }
1359   }
1360 }
1361
1362 //=======================================================================
1363 //function : SetWeight
1364 //purpose  : 
1365 //=======================================================================
1366
1367 void Geom_BSplineSurface::SetWeight (const Standard_Integer UIndex,
1368                                      const Standard_Integer VIndex,
1369                                      const Standard_Real    Weight)
1370 {
1371   if (Weight <= gp::Resolution())  Standard_ConstructionError::Raise(); 
1372   TColStd_Array2OfReal & Weights = weights->ChangeArray2();
1373   if (UIndex < 1 || UIndex > Weights.ColLength() ||
1374       VIndex < 1 || VIndex > Weights.RowLength() ) {
1375     Standard_OutOfRange::Raise();
1376   }
1377   Weights (UIndex+Weights.LowerRow()-1, VIndex+Weights.LowerCol()-1) = Weight;
1378   Rational(Weights, urational, vrational);
1379 }
1380
1381 //=======================================================================
1382 //function : SetWeightCol
1383 //purpose  : 
1384 //=======================================================================
1385
1386 void Geom_BSplineSurface::SetWeightCol
1387 (const Standard_Integer       VIndex, 
1388  const TColStd_Array1OfReal&  CPoleWeights)
1389 {
1390   TColStd_Array2OfReal & Weights = weights->ChangeArray2();   
1391   if (VIndex < 1 || VIndex > Weights.RowLength()) {
1392     Standard_OutOfRange::Raise();
1393   }
1394   if (CPoleWeights.Lower() < 1 || 
1395       CPoleWeights.Lower() > Weights.ColLength() ||
1396       CPoleWeights.Upper() < 1 ||
1397       CPoleWeights.Upper() > Weights.ColLength()  ) {
1398     Standard_ConstructionError::Raise();
1399   }
1400   Standard_Integer I = CPoleWeights.Lower();
1401   while (I <= CPoleWeights.Upper()) {
1402     if (CPoleWeights(I) <= gp::Resolution()) { 
1403       Standard_ConstructionError::Raise();
1404     }
1405     Weights (I+Weights.LowerRow()-1, VIndex+Weights.LowerCol()-1) = 
1406       CPoleWeights (I);
1407     I++;
1408   }
1409   // Verifie si c'est rationnel
1410   Rational(Weights, urational, vrational);
1411 }
1412
1413 //=======================================================================
1414 //function : SetWeightRow
1415 //purpose  : 
1416 //=======================================================================
1417
1418 void Geom_BSplineSurface::SetWeightRow
1419 (const Standard_Integer       UIndex, 
1420  const TColStd_Array1OfReal&  CPoleWeights)
1421 {
1422   TColStd_Array2OfReal & Weights = weights->ChangeArray2();   
1423   if (UIndex < 1 || UIndex > Weights.ColLength()) {
1424     Standard_OutOfRange::Raise();
1425   }
1426   if (CPoleWeights.Lower() < 1 ||
1427       CPoleWeights.Lower() > Weights.RowLength() ||
1428       CPoleWeights.Upper() < 1 ||
1429       CPoleWeights.Upper() > Weights.RowLength()  ) {
1430     
1431     Standard_ConstructionError::Raise();
1432   }
1433   Standard_Integer I = CPoleWeights.Lower();
1434
1435   while (I <= CPoleWeights.Upper()) {
1436     if (CPoleWeights(I)<=gp::Resolution()) {
1437       Standard_ConstructionError::Raise();
1438     }
1439     Weights (UIndex+Weights.LowerRow()-1, I+Weights.LowerCol()-1) = 
1440       CPoleWeights (I);
1441     I++;
1442   }
1443   // Verifie si c'est rationnel
1444   Rational(Weights, urational, vrational);
1445 }
1446