e36e06563ae103d224c39b3fd65d0375adfc92ad
[occt.git] / src / Geom / Geom_BSplineSurface_1.cxx
1 // Created on: 1993-03-09
2 // Created by: JCV
3 // Copyright (c) 1993-1999 Matra Datavision
4 // Copyright (c) 1999-2012 OPEN CASCADE SAS
5 //
6 // The content of this file is subject to the Open CASCADE Technology Public
7 // License Version 6.5 (the "License"). You may not use the content of this file
8 // except in compliance with the License. Please obtain a copy of the License
9 // at http://www.opencascade.org and read it completely before using this file.
10 //
11 // The Initial Developer of the Original Code is Open CASCADE S.A.S., having its
12 // main offices at: 1, place des Freres Montgolfier, 78280 Guyancourt, France.
13 //
14 // The Original Code and all software distributed under the License is
15 // distributed on an "AS IS" basis, without warranty of any kind, and the
16 // Initial Developer hereby disclaims all such warranties, including without
17 // limitation, any warranties of merchantability, fitness for a particular
18 // purpose or non-infringement. Please see the License for the specific terms
19 // and conditions governing the rights and limitations under the License.
20
21
22 // xab : 30-Mar-95 introduced cache mechanism for surfaces
23 // xab : 21-Jun-95 in remove knots sync size of weights and poles
24 // pmn : 28-Jun-96 Distinction entre la continuite en U et V (bug PRO4625)
25 // pmn : 07-Jan-97 Centralisation des verif rational (PRO6834)
26 //       et ajout des InvalideCache() dans les SetPole* (PRO6833)
27 // pmn : 03-Feb-97 Prise en compte de la periode dans Locate(U/V) (PRO6963)
28 //                 + bon appel a LocateParameter (PRO6973).
29 // RBD : 15/10/98 ; Le cache est desormais defini sur [-1,1] (pro15537).
30
31 #define No_Standard_OutOfRange
32 #define No_Standard_DimensionError
33
34 #include <Geom_BSplineSurface.jxx>
35
36 #include <gp.hxx>
37 #include <BSplSLib.hxx>
38 #include <BSplCLib.hxx>
39 #include <Precision.hxx>
40 #include <TColgp_Array1OfXYZ.hxx>
41
42 #include <Geom_BSplineCurve.hxx>
43
44 #include <Geom_UndefinedDerivative.hxx>
45 #include <Standard_OutOfRange.hxx>
46 #include <Standard_RangeError.hxx>
47 #include <Standard_DomainError.hxx>
48 #include <Standard_DimensionError.hxx>
49 #include <Standard_ConstructionError.hxx>
50 #include <Standard_NotImplemented.hxx>
51
52 #define  POLES    (poles->Array2())
53 #define  WEIGHTS  (weights->Array2())
54 #define  UKNOTS   (uknots->Array1())
55 #define  VKNOTS   (vknots->Array1())
56 #define  UFKNOTS  (ufknots->Array1())
57 #define  VFKNOTS  (vfknots->Array1())
58 #define  FMULTS   (BSplCLib::NoMults())
59
60 //=======================================================================
61 //function : IsCNu
62 //purpose  : 
63 //=======================================================================
64
65 Standard_Boolean Geom_BSplineSurface::IsCNu
66   (const Standard_Integer N) const
67 {
68   Standard_RangeError_Raise_if (N < 0, " ");
69   switch (Usmooth) {
70   case GeomAbs_CN : return Standard_True;
71   case GeomAbs_C0 : return N <= 0;
72   case GeomAbs_G1 : return N <= 0;
73   case GeomAbs_C1 : return N <= 1;
74   case GeomAbs_G2 : return N <= 1;
75   case GeomAbs_C2 : return N <= 2;
76   case GeomAbs_C3 :
77     return N <= 3 ? Standard_True :
78            N <= udeg - BSplCLib::MaxKnotMult (umults->Array1(), umults->Lower() + 1, umults->Upper() - 1);
79   default:
80     return Standard_False;
81   }
82 }
83
84 //=======================================================================
85 //function : IsCNv
86 //purpose  : 
87 //=======================================================================
88
89 Standard_Boolean Geom_BSplineSurface::IsCNv
90   (const Standard_Integer N) const
91 {
92   Standard_RangeError_Raise_if (N < 0, " ");
93   
94   switch (Vsmooth) {
95   case GeomAbs_CN : return Standard_True;
96   case GeomAbs_C0 : return N <= 0;
97   case GeomAbs_G1 : return N <= 0;
98   case GeomAbs_C1 : return N <= 1;
99   case GeomAbs_G2 : return N <= 1;
100   case GeomAbs_C2 : return N <= 2;
101   case GeomAbs_C3 :
102     return N <= 3 ? Standard_True :
103            N <= vdeg - BSplCLib::MaxKnotMult (vmults->Array1(), vmults->Lower() + 1, vmults->Upper() - 1);
104   default:
105     return Standard_False;
106   }
107 }
108
109 //=======================================================================
110 //function : D0
111 //purpose  : 
112 //=======================================================================
113
114 void Geom_BSplineSurface::D0 (const Standard_Real U, 
115                               const Standard_Real V, 
116                                     gp_Pnt&       P ) const 
117 {
118   Standard_Real  new_u = U,
119                  new_v = V ;
120   PeriodicNormalization(new_u,
121                         new_v) ;
122   if (!IsCacheValid(new_u,
123                     new_v))
124     {
125      Geom_BSplineSurface * my_surface = (Geom_BSplineSurface *) this ;
126      my_surface->ValidateCache(new_u,
127                                new_v) ;
128    }
129  Standard_Real uparameter_11 = (2*ucacheparameter + ucachespanlenght)/2,
130                uspanlenght_11 = ucachespanlenght/2,
131                vparameter_11 = (2*vcacheparameter + vcachespanlenght)/2,
132                vspanlenght_11 = vcachespanlenght/2 ; 
133  if (cacheweights.IsNull()) {
134       
135    BSplSLib::CacheD0(new_u,
136                      new_v,
137                      udeg,
138                      vdeg,
139                      uparameter_11,
140                      vparameter_11,
141                      uspanlenght_11,
142                      vspanlenght_11,
143                      cachepoles->Array2(),
144                      *((TColStd_Array2OfReal*) NULL),
145                      P) ;
146  }
147  else {
148    BSplSLib::CacheD0(new_u,
149                      new_v,
150                      udeg,
151                      vdeg,
152                      uparameter_11,
153                      vparameter_11,
154                      uspanlenght_11,
155                      vspanlenght_11,
156                      cachepoles->Array2(),
157                      cacheweights->Array2(),
158                      P) ;
159  }
160 }
161
162 //=======================================================================
163 //function : D1
164 //purpose  : 
165 //=======================================================================
166
167 void Geom_BSplineSurface::D1 (const Standard_Real U, 
168                               const Standard_Real V, 
169                                     gp_Pnt&       P,
170                                     gp_Vec&       D1U,
171                                     gp_Vec&       D1V) const
172 {
173   Standard_Real  new_u = U,
174                  new_v = V ;
175   PeriodicNormalization(new_u,
176                         new_v) ;
177   if (!IsCacheValid(new_u,
178                     new_v))
179     {
180      Geom_BSplineSurface * my_surface = (Geom_BSplineSurface *) this ;
181      my_surface->ValidateCache(new_u,
182                                new_v) ;
183    }
184
185   Standard_Real uparameter_11 = (2*ucacheparameter + ucachespanlenght)/2,
186                 uspanlenght_11 = ucachespanlenght/2,
187                 vparameter_11 = (2*vcacheparameter + vcachespanlenght)/2,
188                 vspanlenght_11 = vcachespanlenght/2 ;
189
190   if (cacheweights.IsNull()) {
191     
192     BSplSLib::CacheD1(new_u,
193                       new_v,
194                       udeg,
195                       vdeg,
196                       uparameter_11,
197                       vparameter_11,
198                       uspanlenght_11,
199                       vspanlenght_11,
200                       cachepoles->Array2(),
201                       *((TColStd_Array2OfReal*) NULL),
202                       P,
203                       D1U,
204                       D1V) ;
205   }
206   else {
207     
208     BSplSLib::CacheD1(new_u,
209                       new_v,
210                       udeg,
211                       vdeg,
212                       uparameter_11,
213                       vparameter_11,
214                       uspanlenght_11,
215                       vspanlenght_11,
216                       cachepoles->Array2(),
217                       cacheweights->Array2(),
218                       P,
219                       D1U,
220                       D1V) ;
221   }
222 }
223
224 //=======================================================================
225 //function : D2
226 //purpose  : 
227 //=======================================================================
228
229 void Geom_BSplineSurface::D2 (const Standard_Real U, 
230                               const Standard_Real V,
231                                     gp_Pnt&       P,
232                                     gp_Vec&       D1U,
233                                     gp_Vec&       D1V,
234                                     gp_Vec&       D2U,
235                                     gp_Vec&       D2V,
236                                     gp_Vec&       D2UV) const
237 {
238
239     Standard_Real  new_u = U,
240                    new_v = V ;
241   PeriodicNormalization(new_u,
242                         new_v) ;
243   if (!IsCacheValid(new_u,
244                     new_v))
245     {
246      Geom_BSplineSurface * my_surface = (Geom_BSplineSurface *) this ;
247      my_surface->ValidateCache(new_u,
248                                new_v) ;
249    }
250
251   Standard_Real uparameter_11 = (2*ucacheparameter + ucachespanlenght)/2,
252                 uspanlenght_11 = ucachespanlenght/2,
253                 vparameter_11 = (2*vcacheparameter + vcachespanlenght)/2,
254                 vspanlenght_11 = vcachespanlenght/2 ;
255   if (cacheweights.IsNull()) {
256       BSplSLib::CacheD2(new_u,
257                         new_v,
258                         udeg,
259                         vdeg,
260                         uparameter_11,
261                         vparameter_11,
262                         uspanlenght_11,
263                         vspanlenght_11,
264                         cachepoles->Array2(),
265                         *((TColStd_Array2OfReal*) NULL),
266                         P,
267                         D1U,
268                         D1V,
269                         D2U,
270                         D2UV,
271                         D2V); 
272     }
273     else {
274       BSplSLib::CacheD2(new_u,
275                         new_v,
276                         udeg,
277                         vdeg,
278                         uparameter_11,
279                         vparameter_11,
280                         uspanlenght_11,
281                         vspanlenght_11,
282                         cachepoles->Array2(),
283                         cacheweights->Array2(),
284                         P,
285                         D1U,
286                         D1V,
287                         D2U,
288                         D2UV,
289                         D2V); 
290     }
291   }
292
293 //=======================================================================
294 //function : D3
295 //purpose  : 
296 //=======================================================================
297
298 void Geom_BSplineSurface::D3 (const Standard_Real U, 
299                               const Standard_Real V,
300                                     gp_Pnt&       P,
301                                     gp_Vec&       D1U,
302                                     gp_Vec&       D1V, 
303                                     gp_Vec&       D2U,
304                                     gp_Vec&       D2V,
305                                     gp_Vec&       D2UV,
306                                     gp_Vec&       D3U,
307                                     gp_Vec&       D3V,
308                                     gp_Vec&       D3UUV,
309                                     gp_Vec&       D3UVV) const
310 {
311   BSplSLib::D3(U,V,0,0,POLES,WEIGHTS,UFKNOTS,VFKNOTS,FMULTS,FMULTS,
312                udeg,vdeg,urational,vrational,uperiodic,vperiodic,
313                P,D1U,D1V,D2U,D2V,D2UV,D3U,D3V,D3UUV,D3UVV);
314   }
315
316 //=======================================================================
317 //function : DN
318 //purpose  : 
319 //=======================================================================
320
321 gp_Vec Geom_BSplineSurface::DN (const Standard_Real    U,
322                                 const Standard_Real    V,
323                                 const Standard_Integer Nu,
324                                 const Standard_Integer Nv ) const
325 {
326   gp_Vec Vn;
327   BSplSLib::DN(U,V,Nu,Nv,0,0,POLES,WEIGHTS,UFKNOTS,VFKNOTS,FMULTS,FMULTS,
328                udeg,vdeg,urational,vrational,uperiodic,vperiodic,
329                Vn);
330   return Vn;
331 }
332
333 //=======================================================================
334 //function : LocalValue
335 //purpose  : 
336 //=======================================================================
337
338 gp_Pnt Geom_BSplineSurface::LocalValue (const Standard_Real    U,
339                                         const Standard_Real    V, 
340                                         const Standard_Integer FromUK1,
341                                         const Standard_Integer ToUK2,
342                                         const Standard_Integer FromVK1, 
343                                         const Standard_Integer ToVK2)  const
344 {
345   gp_Pnt P;
346   LocalD0(U,V,FromUK1,ToUK2,FromVK1,ToVK2,P);
347   return P;
348 }
349
350 //=======================================================================
351 //function : LocalD0
352 //purpose  : 
353 //=======================================================================
354
355 void Geom_BSplineSurface::LocalD0 (const Standard_Real    U,
356                                    const Standard_Real    V, 
357                                    const Standard_Integer FromUK1,
358                                    const Standard_Integer ToUK2,
359                                    const Standard_Integer FromVK1, 
360                                    const Standard_Integer ToVK2,
361                                          gp_Pnt&          P     )  const
362 {
363   Standard_DomainError_Raise_if (FromUK1 == ToUK2 || FromVK1 == ToVK2, 
364                                  "Geom_BSplineSurface::LocalD0");
365
366   Standard_Real u = U, v = V;
367   Standard_Integer uindex = 0, vindex = 0;
368
369   BSplCLib::LocateParameter(udeg, UFKNOTS, U, uperiodic,FromUK1,ToUK2,
370                             uindex,u);
371   uindex = BSplCLib::FlatIndex(udeg,uindex,umults->Array1(),uperiodic);
372
373   BSplCLib::LocateParameter(vdeg, VFKNOTS, V, vperiodic,FromVK1,ToVK2,
374                             vindex,v);
375   vindex = BSplCLib::FlatIndex(vdeg,vindex,vmults->Array1(),vperiodic);
376
377 //  BSplSLib::D0(U,V,uindex,vindex,POLES,WEIGHTS,UFKNOTS,VFKNOTS,FMULTS,FMULTS,
378   BSplSLib::D0(u,v,uindex,vindex,POLES,WEIGHTS,UFKNOTS,VFKNOTS,FMULTS,FMULTS,
379                udeg,vdeg,urational,vrational,uperiodic,vperiodic,
380                P);
381 }
382
383 //=======================================================================
384 //function : LocalD1
385 //purpose  : 
386 //=======================================================================
387
388 void Geom_BSplineSurface::LocalD1 (const Standard_Real    U, 
389                                    const Standard_Real    V,
390                                    const Standard_Integer FromUK1, 
391                                    const Standard_Integer ToUK2,
392                                    const Standard_Integer FromVK1, 
393                                    const Standard_Integer ToVK2,
394                                          gp_Pnt&          P,
395                                          gp_Vec&          D1U, 
396                                          gp_Vec&          D1V)     const
397 {
398   Standard_DomainError_Raise_if (FromUK1 == ToUK2 || FromVK1 == ToVK2, 
399                                  "Geom_BSplineSurface::LocalD1");
400
401   Standard_Real u = U, v = V;
402   Standard_Integer uindex = 0, vindex = 0;
403
404   BSplCLib::LocateParameter(udeg, UFKNOTS, U, uperiodic,FromUK1,ToUK2,
405                             uindex,u);
406   uindex = BSplCLib::FlatIndex(udeg,uindex,umults->Array1(),uperiodic);
407
408   BSplCLib::LocateParameter(vdeg, VFKNOTS, V, vperiodic,FromVK1,ToVK2,
409                             vindex,v);
410   vindex = BSplCLib::FlatIndex(vdeg,vindex,vmults->Array1(),vperiodic);
411
412   BSplSLib::D1(u,v,uindex,vindex,POLES,WEIGHTS,UFKNOTS,VFKNOTS,FMULTS,FMULTS,
413                udeg,vdeg,urational,vrational,uperiodic,vperiodic,
414                P,D1U,D1V);
415 }
416
417 //=======================================================================
418 //function : LocalD2
419 //purpose  : 
420 //=======================================================================
421
422 void Geom_BSplineSurface::LocalD2 (const Standard_Real    U,
423                                    const Standard_Real    V,
424                                    const Standard_Integer FromUK1,
425                                    const Standard_Integer ToUK2,
426                                    const Standard_Integer FromVK1, 
427                                    const Standard_Integer ToVK2,
428                                          gp_Pnt&          P,
429                                          gp_Vec&          D1U,
430                                          gp_Vec&          D1V,
431                                          gp_Vec&          D2U,
432                                          gp_Vec&          D2V,
433                                          gp_Vec&          D2UV) const
434 {
435   Standard_DomainError_Raise_if (FromUK1 == ToUK2 || FromVK1 == ToVK2, 
436                                  "Geom_BSplineSurface::LocalD2");
437
438   Standard_Real u = U, v = V;
439   Standard_Integer uindex = 0, vindex = 0;
440
441   BSplCLib::LocateParameter(udeg, UFKNOTS, U, uperiodic,FromUK1,ToUK2,
442                             uindex,u);
443   uindex = BSplCLib::FlatIndex(udeg,uindex,umults->Array1(),uperiodic);
444
445   BSplCLib::LocateParameter(vdeg, VFKNOTS, V, vperiodic,FromVK1,ToVK2,
446                             vindex,v);
447   vindex = BSplCLib::FlatIndex(vdeg,vindex,vmults->Array1(),vperiodic);
448
449   BSplSLib::D2(u,v,uindex,vindex,POLES,WEIGHTS,UFKNOTS,VFKNOTS,FMULTS,FMULTS,
450                udeg,vdeg,urational,vrational,uperiodic,vperiodic,
451                P,D1U,D1V,D2U,D2V,D2UV);
452 }
453
454 //=======================================================================
455 //function : LocalD3
456 //purpose  : 
457 //=======================================================================
458
459 void Geom_BSplineSurface::LocalD3 (const Standard_Real    U, 
460                                    const Standard_Real    V,
461                                    const Standard_Integer FromUK1, 
462                                    const Standard_Integer ToUK2,
463                                    const Standard_Integer FromVK1, 
464                                    const Standard_Integer ToVK2,
465                                          gp_Pnt&          P,
466                                          gp_Vec&          D1U,
467                                          gp_Vec&          D1V, 
468                                          gp_Vec&          D2U, 
469                                          gp_Vec&          D2V, 
470                                          gp_Vec&          D2UV, 
471                                          gp_Vec&          D3U,
472                                          gp_Vec&          D3V,
473                                          gp_Vec&          D3UUV,
474                                          gp_Vec&          D3UVV) const
475 {
476   Standard_DomainError_Raise_if (FromUK1 == ToUK2 || FromVK1 == ToVK2, 
477                                  "Geom_BSplineSurface::LocalD3");
478
479   Standard_Real u = U, v = V;
480   Standard_Integer uindex = 0, vindex = 0;
481
482   BSplCLib::LocateParameter(udeg, UFKNOTS, U, uperiodic,FromUK1,ToUK2,
483                             uindex,u);
484   uindex = BSplCLib::FlatIndex(udeg,uindex,umults->Array1(),uperiodic);
485
486   BSplCLib::LocateParameter(vdeg, VFKNOTS, V, vperiodic,FromVK1,ToVK2,
487                             vindex,v);
488   vindex = BSplCLib::FlatIndex(vdeg,vindex,vmults->Array1(),vperiodic);
489
490   BSplSLib::D3(u,v,uindex,vindex,POLES,WEIGHTS,UFKNOTS,VFKNOTS,FMULTS,FMULTS,
491                udeg,vdeg,urational,vrational,uperiodic,vperiodic,
492                P,D1U,D1V,D2U,D2V,D2UV,D3U,D3V,D3UUV,D3UVV);
493 }
494
495 //=======================================================================
496 //function : LocalDN
497 //purpose  : 
498 //=======================================================================
499
500 gp_Vec Geom_BSplineSurface::LocalDN  (const Standard_Real    U, 
501                                       const Standard_Real    V,
502                                       const Standard_Integer FromUK1,
503                                       const Standard_Integer ToUK2,
504                                       const Standard_Integer FromVK1,
505                                       const Standard_Integer ToVK2,
506                                       const Standard_Integer Nu,
507                                       const Standard_Integer Nv) const
508 {
509   Standard_DomainError_Raise_if (FromUK1 == ToUK2 || FromVK1 == ToVK2, 
510                                  "Geom_BSplineSurface::LocalDN");
511
512   Standard_Real u = U, v = V;
513   Standard_Integer uindex = 0, vindex = 0;
514
515   BSplCLib::LocateParameter(udeg, UFKNOTS, U, uperiodic,FromUK1,ToUK2,
516                             uindex,u);
517   uindex = BSplCLib::FlatIndex(udeg,uindex,umults->Array1(),uperiodic);
518
519   BSplCLib::LocateParameter(vdeg, VFKNOTS, V, vperiodic,FromVK1,ToVK2,
520                             vindex,v);
521   vindex = BSplCLib::FlatIndex(vdeg,vindex,vmults->Array1(),vperiodic);
522
523   gp_Vec Vn;
524   BSplSLib::DN(u,v,Nu,Nv,uindex,vindex,
525                POLES,WEIGHTS,UFKNOTS,VFKNOTS,FMULTS,FMULTS,
526                udeg,vdeg,urational,vrational,uperiodic,vperiodic,
527                Vn);
528   return Vn;
529 }
530
531 //=======================================================================
532 //function : Pole
533 //purpose  : 
534 //=======================================================================
535
536 gp_Pnt Geom_BSplineSurface::Pole (const Standard_Integer UIndex,
537                                   const Standard_Integer VIndex) const
538 {
539   Standard_OutOfRange_Raise_if
540     (UIndex < 1 || UIndex > poles->ColLength() ||
541      VIndex < 1 || VIndex > poles->RowLength(), " ");
542   return poles->Value (UIndex, VIndex);
543 }
544
545 //=======================================================================
546 //function : Poles
547 //purpose  : 
548 //=======================================================================
549
550 void Geom_BSplineSurface::Poles (TColgp_Array2OfPnt& P) const
551 {
552   Standard_DimensionError_Raise_if
553     (P.ColLength() != poles->ColLength() ||
554      P.RowLength() != poles->RowLength(), " ");
555   P = poles->Array2();
556 }
557
558 //=======================================================================
559 //function : UIso
560 //purpose  : 
561 //=======================================================================
562
563 Handle(Geom_Curve) Geom_BSplineSurface::UIso (const Standard_Real U) const
564 {
565   TColgp_Array1OfPnt   cpoles(1,poles->RowLength());
566   TColStd_Array1OfReal cweights(1,poles->RowLength());
567
568   Handle(Geom_BSplineCurve) C;
569
570   if ( urational || vrational) {
571     BSplSLib::Iso(U,Standard_True,POLES,WEIGHTS,UFKNOTS,FMULTS,udeg,uperiodic,
572                   cpoles,cweights);
573     C = new Geom_BSplineCurve(cpoles,cweights,
574                               vknots->Array1(),
575                               vmults->Array1(),
576                               vdeg,vperiodic);
577   }
578   else {
579     BSplSLib::Iso(U,Standard_True,POLES,
580                   *((TColStd_Array2OfReal*) NULL),
581                   UFKNOTS,FMULTS,udeg,uperiodic,
582                   cpoles,cweights);
583     C = new Geom_BSplineCurve(cpoles,
584                               vknots->Array1(),
585                               vmults->Array1(),
586                               vdeg,vperiodic);
587   }
588
589   return C;
590 }
591
592 //=======================================================================
593 //function : UIso
594 //purpose  : If CheckRational=False, no try to make it non-rational
595 //=======================================================================
596
597 Handle(Geom_Curve) Geom_BSplineSurface::UIso (const Standard_Real U,
598                                               const Standard_Boolean CheckRational) const
599 {
600   TColgp_Array1OfPnt   cpoles(1,poles->RowLength());
601   TColStd_Array1OfReal cweights(1,poles->RowLength());
602
603   Handle(Geom_BSplineCurve) C;
604
605   if ( urational || vrational) {
606     BSplSLib::Iso(U,Standard_True,POLES,WEIGHTS,UFKNOTS,FMULTS,udeg,uperiodic,
607                   cpoles,cweights);
608     C = new Geom_BSplineCurve(cpoles,cweights,
609                               vknots->Array1(),
610                               vmults->Array1(),
611                               vdeg,vperiodic,
612                               CheckRational);
613   }
614   else {
615     BSplSLib::Iso(U,Standard_True,POLES,
616                   *((TColStd_Array2OfReal*) NULL),
617                   UFKNOTS,FMULTS,udeg,uperiodic,
618                   cpoles,cweights);
619     C = new Geom_BSplineCurve(cpoles,
620                               vknots->Array1(),
621                               vmults->Array1(),
622                               vdeg,vperiodic);
623   }
624
625   return C;
626 }
627
628 //=======================================================================
629 //function : UKnot
630 //purpose  : 
631 //=======================================================================
632
633 Standard_Real Geom_BSplineSurface::UKnot(const Standard_Integer UIndex) const
634 {
635   Standard_OutOfRange_Raise_if (UIndex < 1 || UIndex > uknots->Length(), " ");
636   return uknots->Value (UIndex);
637 }
638
639 //=======================================================================
640 //function : VKnot
641 //purpose  : 
642 //=======================================================================
643
644 Standard_Real Geom_BSplineSurface::VKnot(const Standard_Integer VIndex) const
645 {
646   Standard_OutOfRange_Raise_if (VIndex < 1 || VIndex > vknots->Length(), " ");
647   return vknots->Value (VIndex);
648 }
649
650 //=======================================================================
651 //function : UKnots
652 //purpose  : 
653 //=======================================================================
654
655 void Geom_BSplineSurface::UKnots (TColStd_Array1OfReal& Ku) const
656 {
657   Standard_DimensionError_Raise_if (Ku.Length() != uknots->Length(), " ");
658   Ku = uknots->Array1();
659 }
660
661 //=======================================================================
662 //function : VKnots
663 //purpose  : 
664 //=======================================================================
665
666 void Geom_BSplineSurface::VKnots (TColStd_Array1OfReal& Kv) const
667 {
668   Standard_DimensionError_Raise_if (Kv.Length() != vknots->Length(), " ");
669   Kv = vknots->Array1();
670 }
671
672 //=======================================================================
673 //function : UKnotSequence
674 //purpose  : 
675 //=======================================================================
676
677 void Geom_BSplineSurface::UKnotSequence (TColStd_Array1OfReal& Ku) const
678 {
679   Standard_DimensionError_Raise_if (Ku.Length() != ufknots->Length(), " ");
680   Ku = ufknots->Array1();
681 }
682
683 //=======================================================================
684 //function : VKnotSequence
685 //purpose  : 
686 //=======================================================================
687
688 void Geom_BSplineSurface::VKnotSequence (TColStd_Array1OfReal& Kv) const
689 {
690   Standard_DimensionError_Raise_if (Kv.Length() != vfknots->Length(), " ");
691   Kv = vfknots->Array1();
692 }
693
694 //=======================================================================
695 //function : UMultiplicity
696 //purpose  : 
697 //=======================================================================
698
699 Standard_Integer Geom_BSplineSurface::UMultiplicity 
700   (const Standard_Integer UIndex) const
701 {
702   Standard_OutOfRange_Raise_if (UIndex < 1 || UIndex > umults->Length()," ");
703   return umults->Value (UIndex);
704 }
705
706 //=======================================================================
707 //function : UMultiplicities
708 //purpose  : 
709 //=======================================================================
710
711 void Geom_BSplineSurface::UMultiplicities (TColStd_Array1OfInteger& Mu) const
712 {
713   Standard_DimensionError_Raise_if (Mu.Length() != umults->Length(), " ");
714   Mu = umults->Array1();
715 }
716
717 //=======================================================================
718 //function : VIso
719 //purpose  : 
720 //=======================================================================
721
722 Handle(Geom_Curve) Geom_BSplineSurface::VIso (const Standard_Real V) const
723 {
724   TColgp_Array1OfPnt   cpoles(1,poles->ColLength());
725   TColStd_Array1OfReal cweights(1,poles->ColLength());
726
727   Handle(Geom_BSplineCurve) C;
728
729   if ( urational || vrational) {
730     BSplSLib::Iso(V,Standard_False,POLES,
731                   WEIGHTS,
732                   VFKNOTS,FMULTS,vdeg,vperiodic,
733                   cpoles,cweights);
734     C = new Geom_BSplineCurve(cpoles,cweights,
735                               uknots->Array1(),
736                               umults->Array1(),
737                               udeg,uperiodic);
738   }
739   else {
740     BSplSLib::Iso(V,Standard_False,POLES,
741                   *((TColStd_Array2OfReal*) NULL),
742                   VFKNOTS,FMULTS,vdeg,vperiodic,
743                   cpoles,cweights);
744     C = new Geom_BSplineCurve(cpoles,
745                               uknots->Array1(),
746                               umults->Array1(),
747                               udeg,uperiodic);
748   }
749
750   return C;
751 }
752
753 //=======================================================================
754 //function : VIso
755 //purpose  : If CheckRational=False, no try to make it non-rational
756 //=======================================================================
757
758 Handle(Geom_Curve) Geom_BSplineSurface::VIso (const Standard_Real V,
759                                               const Standard_Boolean CheckRational) const
760 {
761   TColgp_Array1OfPnt   cpoles(1,poles->ColLength());
762   TColStd_Array1OfReal cweights(1,poles->ColLength());
763
764   Handle(Geom_BSplineCurve) C;
765
766   if ( urational || vrational) {
767     BSplSLib::Iso(V,Standard_False,POLES,
768                   WEIGHTS,
769                   VFKNOTS,FMULTS,vdeg,vperiodic,
770                   cpoles,cweights);
771     C = new Geom_BSplineCurve(cpoles,cweights,
772                               uknots->Array1(),
773                               umults->Array1(),
774                               udeg,uperiodic,
775                               CheckRational);
776   }
777   else {
778     BSplSLib::Iso(V,Standard_False,POLES,
779                   *((TColStd_Array2OfReal*) NULL),
780                   VFKNOTS,FMULTS,vdeg,vperiodic,
781                   cpoles,cweights);
782     C = new Geom_BSplineCurve(cpoles,
783                               uknots->Array1(),
784                               umults->Array1(),
785                               udeg,uperiodic);
786   }
787
788   return C;
789 }
790
791 //=======================================================================
792 //function : VMultiplicity
793 //purpose  : 
794 //=======================================================================
795
796 Standard_Integer Geom_BSplineSurface::VMultiplicity 
797   (const Standard_Integer VIndex) const
798 {
799   Standard_OutOfRange_Raise_if (VIndex < 1 || VIndex > vmults->Length()," ");
800   return vmults->Value (VIndex);
801 }
802
803 //=======================================================================
804 //function : VMultiplicities
805 //purpose  : 
806 //=======================================================================
807
808 void Geom_BSplineSurface::VMultiplicities (TColStd_Array1OfInteger& Mv) const
809 {
810   Standard_DimensionError_Raise_if (Mv.Length() != vmults->Length(), " ");
811   Mv = vmults->Array1();
812 }
813
814 //=======================================================================
815 //function : Weight
816 //purpose  : 
817 //=======================================================================
818
819 Standard_Real Geom_BSplineSurface::Weight 
820   (const Standard_Integer UIndex,
821    const Standard_Integer VIndex ) const
822 {
823   Standard_OutOfRange_Raise_if
824     (UIndex < 1 || UIndex > weights->ColLength() ||
825      VIndex < 1 || VIndex > weights->RowLength(), " ");
826   return weights->Value (UIndex, VIndex);
827 }
828
829 //=======================================================================
830 //function : Weights
831 //purpose  : 
832 //=======================================================================
833
834 void Geom_BSplineSurface::Weights (TColStd_Array2OfReal& W) const
835 {
836   Standard_DimensionError_Raise_if
837     (W.ColLength() != weights->ColLength() ||
838      W.RowLength() != weights->RowLength(), " ");
839   W = weights->Array2();
840 }
841
842 //=======================================================================
843 //function : Transform
844 //purpose  : 
845 //=======================================================================
846
847 void Geom_BSplineSurface::Transform (const gp_Trsf& T)
848 {
849   TColgp_Array2OfPnt & VPoles = poles->ChangeArray2();
850   for (Standard_Integer j = VPoles.LowerCol(); j <= VPoles.UpperCol(); j++) {
851     for (Standard_Integer i = VPoles.LowerRow(); i <= VPoles.UpperRow(); i++) {
852       VPoles (i, j).Transform (T);
853     }
854   }
855
856   InvalidateCache();
857 }
858
859 //=======================================================================
860 //function : SetUPeriodic
861 //purpose  : 
862 //=======================================================================
863
864 void Geom_BSplineSurface::SetUPeriodic ()
865 {
866   Standard_Integer i,j;
867
868   Standard_Integer first = FirstUKnotIndex();
869   Standard_Integer last  = LastUKnotIndex();
870   
871   Handle(TColStd_HArray1OfReal) tk = uknots;
872   TColStd_Array1OfReal cknots((uknots->Array1())(first),first,last);
873   uknots = new TColStd_HArray1OfReal(1,cknots.Length());
874   uknots->ChangeArray1() = cknots;
875
876   Handle(TColStd_HArray1OfInteger) tm = umults;
877   TColStd_Array1OfInteger cmults((umults->Array1())(first),first,last);
878 //  Modified by Sergey KHROMOV - Mon Feb 10 10:59:00 2003 Begin
879 //   cmults(first) = cmults(last) = Max( cmults(first), cmults(last));
880   cmults(first) = cmults(last) = Min(udeg, Max( cmults(first), cmults(last)));
881 //  Modified by Sergey KHROMOV - Mon Feb 10 10:59:00 2003 End
882   umults = new TColStd_HArray1OfInteger(1,cmults.Length());
883   umults->ChangeArray1() = cmults;
884
885   // compute new number of poles;
886   Standard_Integer nbp = BSplCLib::NbPoles(udeg,Standard_True,cmults);
887   
888   TColgp_Array2OfPnt cpoles(1,nbp,poles->LowerCol(),poles->UpperCol());
889   for (i = 1; i <= nbp; i++) {
890     for (j = poles->LowerCol(); j <= poles->UpperCol(); j++) {
891       cpoles(i,j) = poles->Value(i,j);
892     }
893   }
894   poles = 
895     new TColgp_HArray2OfPnt(1,nbp,cpoles.LowerCol(),cpoles.UpperCol());
896   poles->ChangeArray2() = cpoles;
897
898   TColStd_Array2OfReal 
899     cweights(1,nbp,weights->LowerCol(),weights->UpperCol());
900   if (urational || vrational) {
901     for (i = 1; i <= nbp; i++) {
902       for (j = weights->LowerCol(); j <= weights->UpperCol(); j++) {
903         cweights(i,j) = weights->Value(i,j);
904       }
905     }
906   }
907   else { 
908     for (i = 1; i <= nbp; i++) {
909       for (j = weights->LowerCol(); j <= weights->UpperCol(); j++) {
910         cweights(i,j) = 1;
911       }
912     }
913   }
914   weights = new 
915     TColStd_HArray2OfReal(1,nbp,cweights.LowerCol(),cweights.UpperCol());
916   weights->ChangeArray2() = cweights;
917   
918
919   uperiodic = Standard_True;
920
921   maxderivinvok = 0;
922   UpdateUKnots();
923 }
924
925 //=======================================================================
926 //function : SetVPeriodic
927 //purpose  : 
928 //=======================================================================
929
930 void Geom_BSplineSurface::SetVPeriodic ()
931 {
932   Standard_Integer i,j;
933
934   Standard_Integer first = FirstVKnotIndex();
935   Standard_Integer last  = LastVKnotIndex();
936   
937   Handle(TColStd_HArray1OfReal) tk = vknots;
938   TColStd_Array1OfReal cknots((vknots->Array1())(first),first,last);
939   vknots = new TColStd_HArray1OfReal(1,cknots.Length());
940   vknots->ChangeArray1() = cknots;
941
942
943   Handle(TColStd_HArray1OfInteger) tm = vmults;
944   TColStd_Array1OfInteger cmults((vmults->Array1())(first),first,last);
945 //  Modified by Sergey KHROMOV - Mon Feb 10 11:00:33 2003 Begin
946 //   cmults(first) = cmults(last) = Max( cmults(first), cmults(last));
947   cmults(first) = cmults(last) = Min(vdeg, Max( cmults(first), cmults(last)));
948 //  Modified by Sergey KHROMOV - Mon Feb 10 11:00:34 2003 End
949   vmults = new TColStd_HArray1OfInteger(1,cmults.Length());
950   vmults->ChangeArray1() = cmults;
951
952   // compute new number of poles;
953   Standard_Integer nbp = BSplCLib::NbPoles(vdeg,Standard_True,cmults);
954   
955   TColgp_Array2OfPnt cpoles(poles->LowerRow(),poles->UpperRow(),1,nbp);
956   for (i = poles->LowerRow(); i <= poles->UpperRow(); i++) {
957     for (j = 1; j <= nbp; j++) {
958       cpoles(i,j) = poles->Value(i,j);
959     }
960   }
961   poles =
962     new TColgp_HArray2OfPnt(cpoles.LowerRow(),cpoles.UpperRow(),1,nbp);
963   poles->ChangeArray2() = cpoles;
964
965   if (urational || vrational) {
966     TColStd_Array2OfReal 
967       cweights(weights->LowerRow(),weights->UpperRow(),1,nbp);
968     for (i = weights->LowerRow(); i <= weights->UpperRow(); i++) {
969       for (j = 1; j <= nbp; j++) {
970         cweights(i,j) = weights->Value(i,j);
971       }
972     }
973     weights = new 
974       TColStd_HArray2OfReal(cweights.LowerRow(),cweights.UpperRow(),1,nbp);
975     weights->ChangeArray2() = cweights;
976   }
977
978   vperiodic = Standard_True;
979
980   maxderivinvok = 0;
981   UpdateVKnots();
982 }
983
984 //=======================================================================
985 //function : SetUOrigin
986 //purpose  : 
987 //=======================================================================
988
989 void Geom_BSplineSurface::SetUOrigin(const Standard_Integer Index)
990 {
991   Standard_NoSuchObject_Raise_if( !uperiodic,
992                                  "Geom_BSplineSurface::SetUOrigin");
993
994   Standard_Integer i,j,k;
995   Standard_Integer first = FirstUKnotIndex();
996   Standard_Integer last  = LastUKnotIndex();
997
998   Standard_DomainError_Raise_if( (Index < first) || (Index > last),
999                                 "Geom_BSplineCurve::SetUOrigine");
1000
1001   Standard_Integer nbknots = uknots->Length();
1002   Standard_Integer nbpoles = poles->ColLength();
1003
1004   Handle(TColStd_HArray1OfReal) nknots = 
1005     new TColStd_HArray1OfReal(1,nbknots);
1006   TColStd_Array1OfReal& newknots = nknots->ChangeArray1();
1007
1008   Handle(TColStd_HArray1OfInteger) nmults =
1009     new TColStd_HArray1OfInteger(1,nbknots);
1010   TColStd_Array1OfInteger& newmults = nmults->ChangeArray1();
1011
1012   // set the knots and mults
1013   Standard_Real period = uknots->Value(last) - uknots->Value(first);
1014   k = 1;
1015   for ( i = Index; i <= last ; i++) {
1016     newknots(k) = uknots->Value(i);
1017     newmults(k) = umults->Value(i);
1018     k++;
1019   }
1020   for ( i = first+1; i <= Index; i++) {
1021     newknots(k) = uknots->Value(i) + period;
1022     newmults(k) = umults->Value(i);
1023     k++;
1024   }
1025
1026   Standard_Integer index = 1;
1027   for (i = first+1; i <= Index; i++) 
1028     index += umults->Value(i);
1029
1030   // set the poles and weights
1031   Standard_Integer nbvp = poles->RowLength();
1032   Handle(TColgp_HArray2OfPnt) npoles =
1033     new TColgp_HArray2OfPnt(1,nbpoles,1,nbvp);
1034   Handle(TColStd_HArray2OfReal) nweights =
1035     new TColStd_HArray2OfReal(1,nbpoles,1,nbvp);
1036   TColgp_Array2OfPnt   & newpoles   = npoles->ChangeArray2();
1037   TColStd_Array2OfReal & newweights = nweights->ChangeArray2();
1038   first = poles->LowerRow();
1039   last  = poles->UpperRow();
1040   if ( urational || vrational) {
1041     k = 1;
1042     for ( i = index; i <= last; i++) {
1043       for ( j = 1; j <= nbvp; j++) {
1044         newpoles(k,j)   = poles->Value(i,j);
1045         newweights(k,j) = weights->Value(i,j);
1046       }
1047       k++;
1048     }
1049     for ( i = first; i < index; i++) {
1050       for ( j = 1; j <= nbvp; j++) {
1051         newpoles(k,j)   = poles->Value(i,j);
1052         newweights(k,j) = weights->Value(i,j);
1053       }
1054       k++;
1055     }
1056   }
1057   else {
1058     k = 1;
1059     for ( i = index; i <= last; i++) {
1060       for ( j = 1; j <= nbvp; j++) {
1061         newpoles(k,j) = poles->Value(i,j);
1062       }
1063       k++;
1064     }
1065     for ( i = first; i < index; i++) {
1066       for ( j = 1; j <= nbvp; j++) {
1067         newpoles(k,j) = poles->Value(i,j);
1068       }
1069       k++;
1070     }
1071   }
1072
1073   poles  = npoles;
1074   uknots = nknots;
1075   umults = nmults;
1076   if (urational || vrational) 
1077     weights = nweights;
1078   UpdateUKnots();
1079   
1080 }
1081
1082 //=======================================================================
1083 //function : SetVOrigin
1084 //purpose  : 
1085 //=======================================================================
1086
1087 void Geom_BSplineSurface::SetVOrigin(const Standard_Integer Index)
1088 {
1089   Standard_NoSuchObject_Raise_if( !vperiodic,
1090                                  "Geom_BSplineSurface::SetVOrigin");
1091
1092   Standard_Integer i,j,k;
1093   Standard_Integer first = FirstVKnotIndex();
1094   Standard_Integer last  = LastVKnotIndex();
1095
1096   Standard_DomainError_Raise_if( (Index < first) || (Index > last),
1097                                 "Geom_BSplineCurve::SetVOrigine");
1098
1099   Standard_Integer nbknots = vknots->Length();
1100   Standard_Integer nbpoles = poles->RowLength();
1101
1102   Handle(TColStd_HArray1OfReal) nknots = 
1103     new TColStd_HArray1OfReal(1,nbknots);
1104   TColStd_Array1OfReal& newknots = nknots->ChangeArray1();
1105
1106   Handle(TColStd_HArray1OfInteger) nmults =
1107     new TColStd_HArray1OfInteger(1,nbknots);
1108   TColStd_Array1OfInteger& newmults = nmults->ChangeArray1();
1109
1110   // set the knots and mults
1111   Standard_Real period = vknots->Value(last) - vknots->Value(first);
1112   k = 1;
1113   for ( i = Index; i <= last ; i++) {
1114     newknots(k) = vknots->Value(i);
1115     newmults(k) = vmults->Value(i);
1116     k++;
1117   }
1118   for ( i = first+1; i <= Index; i++) {
1119     newknots(k) = vknots->Value(i) + period;
1120     newmults(k) = vmults->Value(i);
1121     k++;
1122   }
1123
1124   Standard_Integer index = 1;
1125   for (i = first+1; i <= Index; i++) 
1126     index += vmults->Value(i);
1127
1128   // set the poles and weights
1129   Standard_Integer nbup = poles->ColLength();
1130   Handle(TColgp_HArray2OfPnt) npoles =
1131     new TColgp_HArray2OfPnt(1,nbup,1,nbpoles);
1132   Handle(TColStd_HArray2OfReal) nweights =
1133     new TColStd_HArray2OfReal(1,nbup,1,nbpoles);
1134   TColgp_Array2OfPnt   & newpoles   = npoles->ChangeArray2();
1135   TColStd_Array2OfReal & newweights = nweights->ChangeArray2();
1136   first = poles->LowerCol();
1137   last  = poles->UpperCol();
1138   if ( urational || vrational) {
1139     k = 1;
1140     for ( j = index; j <= last; j++) {
1141       for ( i = 1; i <= nbup; i++) {
1142         newpoles(i,k)   = poles->Value(i,j);
1143         newweights(i,k) = weights->Value(i,j);
1144       }
1145       k++;
1146     }
1147     for ( j = first; j < index; j++) {
1148       for ( i = 1; i <= nbup; i++) {
1149         newpoles(i,k)   = poles->Value(i,j);
1150         newweights(i,k) = weights->Value(i,j);
1151       }
1152       k++;
1153     }
1154   }
1155   else {
1156     k = 1;
1157     for ( j = index; j <= last; j++) {
1158       for ( i = 1; i <= nbup; i++) {
1159         newpoles(i,k)   = poles->Value(i,j);
1160       }
1161       k++;
1162     }
1163     for ( j = first; j < index; j++) {
1164       for ( i = 1; i <= nbup; i++) {
1165         newpoles(i,k)   = poles->Value(i,j);
1166       }
1167       k++;
1168     }
1169   }
1170
1171   poles  = npoles;
1172   vknots = nknots;
1173   vmults = nmults;
1174   if (urational || vrational) 
1175     weights = nweights;
1176   UpdateVKnots();
1177   
1178 }
1179
1180 //=======================================================================
1181 //function : SetUNotPeriodic
1182 //purpose  : 
1183 //=======================================================================
1184
1185 void Geom_BSplineSurface::SetUNotPeriodic () 
1186
1187   if ( uperiodic) {
1188     Standard_Integer NbKnots, NbPoles;
1189     BSplCLib::PrepareUnperiodize( udeg, umults->Array1(), NbKnots, NbPoles);
1190
1191     Handle(TColgp_HArray2OfPnt) npoles = 
1192       new TColgp_HArray2OfPnt(1,NbPoles, 1, poles->RowLength());
1193     
1194     Handle(TColStd_HArray1OfReal) nknots 
1195       = new TColStd_HArray1OfReal(1,NbKnots);
1196
1197     Handle(TColStd_HArray1OfInteger) nmults
1198       = new TColStd_HArray1OfInteger(1,NbKnots);
1199
1200     Handle(TColStd_HArray2OfReal) nweights = new TColStd_HArray2OfReal(1,NbPoles, 1, poles->RowLength(), 0);
1201
1202     if ( urational || vrational) {
1203
1204       BSplSLib::Unperiodize(Standard_True         , udeg, 
1205                             umults->Array1()      , uknots->Array1(),
1206                             poles->Array2()       , weights->Array2(),
1207                             nmults->ChangeArray1(), nknots->ChangeArray1(),
1208                             npoles->ChangeArray2(),
1209                             nweights->ChangeArray2());
1210     }
1211     else {
1212
1213       BSplSLib::Unperiodize(Standard_True         , udeg, 
1214                             umults->Array1()      , uknots->Array1(),
1215                             poles->Array2()       , BSplSLib::NoWeights(),
1216                             nmults->ChangeArray1(), nknots->ChangeArray1(),
1217                             npoles->ChangeArray2(),
1218                             *((TColStd_Array2OfReal*) NULL));
1219     }
1220     poles     = npoles;
1221     weights   = nweights;
1222     umults    = nmults;
1223     uknots    = nknots;
1224     uperiodic = Standard_False;
1225     
1226     maxderivinvok = 0;
1227     UpdateUKnots();
1228     
1229   }
1230 }
1231
1232 //=======================================================================
1233 //function : SetVNotPeriodic
1234 //purpose  : 
1235 //=======================================================================
1236
1237 void Geom_BSplineSurface::SetVNotPeriodic ()
1238 {
1239   if ( vperiodic) {
1240     Standard_Integer NbKnots, NbPoles;
1241     BSplCLib::PrepareUnperiodize( vdeg, vmults->Array1(), NbKnots, NbPoles);
1242
1243     Handle(TColgp_HArray2OfPnt) npoles = 
1244       new TColgp_HArray2OfPnt(1, poles->ColLength(), 1, NbPoles);
1245     
1246     Handle(TColStd_HArray1OfReal) nknots 
1247       = new TColStd_HArray1OfReal(1,NbKnots);
1248
1249     Handle(TColStd_HArray1OfInteger) nmults
1250       = new TColStd_HArray1OfInteger(1,NbKnots) ;
1251
1252     Handle(TColStd_HArray2OfReal) nweights = new TColStd_HArray2OfReal(1, poles->ColLength(), 1, NbPoles, 0);
1253
1254     if ( urational || vrational) {
1255
1256       BSplSLib::Unperiodize(Standard_False        , vdeg, 
1257                             vmults->Array1()      , vknots->Array1(),
1258                             poles->Array2()       , weights->Array2(),
1259                             nmults->ChangeArray1(), nknots->ChangeArray1(),
1260                             npoles->ChangeArray2(),
1261                             nweights->ChangeArray2());
1262     }
1263     else {
1264
1265       BSplSLib::Unperiodize(Standard_False        , vdeg, 
1266                             vmults->Array1()      , vknots->Array1(),
1267                             poles->Array2()       , BSplSLib::NoWeights(),
1268                             nmults->ChangeArray1(), nknots->ChangeArray1(),
1269                             npoles->ChangeArray2(),
1270                             *((TColStd_Array2OfReal*) NULL));
1271     }
1272     poles     = npoles;
1273     weights   = nweights;
1274     vmults    = nmults;
1275     vknots    = nknots;
1276     vperiodic = Standard_False;
1277     
1278     maxderivinvok = 0;
1279     UpdateVKnots();
1280     
1281   }
1282 }
1283
1284 //=======================================================================
1285 //function : IsUClosed
1286 //purpose  : 
1287 //=======================================================================
1288
1289 Standard_Boolean Geom_BSplineSurface::IsUClosed () const
1290 {   
1291   if (uperiodic)
1292     return Standard_True;
1293
1294   Standard_Boolean Closed     = Standard_True;
1295   TColgp_Array2OfPnt & VPoles = poles->ChangeArray2();
1296   Standard_Integer PLower     = VPoles.LowerRow();
1297   Standard_Integer PUpper     = VPoles.UpperRow();
1298   Standard_Integer PLength    = VPoles.RowLength();
1299   Standard_Integer j = VPoles.LowerCol();
1300   if ( urational || vrational) {
1301     TColStd_Array2OfReal & VWeights = weights->ChangeArray2();
1302     Standard_Integer WLower = VWeights.LowerRow();
1303     Standard_Integer WUpper = VWeights.UpperRow();
1304     Standard_Real    Alfa = VWeights(WLower,VWeights.LowerCol());
1305     Alfa /= VWeights(WUpper,VWeights.LowerCol());
1306
1307     Standard_Integer k = VWeights.LowerCol();
1308     while (Closed && j <= PLength) {
1309       Closed = 
1310         (VPoles (PLower, j).Distance (VPoles (PUpper, j)) <= Precision::Confusion());
1311       j++;
1312       Closed = (Closed &&
1313                ((VWeights(WLower,k) / VWeights(WUpper,k)) - Alfa) 
1314                  < Epsilon(Alfa));
1315       k++;
1316     }
1317   }
1318   else {
1319     while (Closed && j <= PLength) {
1320       Closed = 
1321         (VPoles (PLower, j).Distance (VPoles (PUpper, j)) <= Precision::Confusion());
1322       j++;
1323     }
1324   }
1325   return Closed; 
1326 }
1327
1328 //=======================================================================
1329 //function : IsVClosed
1330 //purpose  : 
1331 //=======================================================================
1332
1333 Standard_Boolean Geom_BSplineSurface::IsVClosed () const
1334 {
1335   if (vperiodic)
1336     return Standard_True;
1337
1338   Standard_Boolean Closed     = Standard_True;
1339   TColgp_Array2OfPnt & VPoles = poles->ChangeArray2();
1340   Standard_Integer PLower     = VPoles.LowerCol();
1341   Standard_Integer PUpper     = VPoles.UpperCol();
1342   Standard_Integer PLength    = VPoles.ColLength();
1343   Standard_Integer i = VPoles.LowerRow();
1344   if ( urational || vrational) {
1345     TColStd_Array2OfReal & VWeights = weights->ChangeArray2();
1346     Standard_Integer WLower = VWeights.LowerCol();
1347     Standard_Integer WUpper = VWeights.UpperCol();
1348     Standard_Real    Alfa = VWeights(VWeights.LowerRow(),WLower);
1349     Alfa /= VWeights(VWeights.LowerRow(),WUpper);
1350
1351     Standard_Integer k = VWeights.LowerRow();
1352     while (Closed && i <= PLength) {
1353       Closed = 
1354         (VPoles (i, PLower).Distance (VPoles (i, PUpper)) <= Precision::Confusion());
1355       i++;
1356       Closed = (Closed &&
1357                ((VWeights(k,WLower) / VWeights(k,WUpper)) - Alfa) 
1358                  < Epsilon(Alfa));
1359       k++;
1360     }
1361   }
1362   else {
1363     while (Closed && i <= PLength) {
1364       Closed = 
1365         (VPoles (i, PLower).Distance (VPoles (i, PUpper)) <= Precision::Confusion());
1366       i++;
1367     }
1368   }
1369   return Closed; 
1370 }
1371
1372 //=======================================================================
1373 //function : IsUPeriodic
1374 //purpose  : 
1375 //=======================================================================
1376
1377 Standard_Boolean Geom_BSplineSurface::IsUPeriodic () const 
1378 {
1379   return uperiodic; 
1380 }
1381
1382 //=======================================================================
1383 //function : IsVPeriodic
1384 //purpose  : 
1385 //=======================================================================
1386
1387 Standard_Boolean Geom_BSplineSurface::IsVPeriodic () const 
1388
1389   return vperiodic; 
1390 }
1391
1392 //=======================================================================
1393 //function : FirstUKnotIndex
1394 //purpose  : 
1395 //=======================================================================
1396
1397 Standard_Integer Geom_BSplineSurface::FirstUKnotIndex () const 
1398
1399   if (uperiodic) return 1;
1400   else return BSplCLib::FirstUKnotIndex(udeg,umults->Array1()); 
1401 }
1402
1403 //=======================================================================
1404 //function : FirstVKnotIndex
1405 //purpose  : 
1406 //=======================================================================
1407
1408 Standard_Integer Geom_BSplineSurface::FirstVKnotIndex () const 
1409
1410   if (vperiodic) return 1;
1411   else return BSplCLib::FirstUKnotIndex(vdeg,vmults->Array1()); 
1412 }
1413
1414 //=======================================================================
1415 //function : LastUKnotIndex
1416 //purpose  : 
1417 //=======================================================================
1418
1419 Standard_Integer Geom_BSplineSurface::LastUKnotIndex() const 
1420 {
1421   if (uperiodic) return uknots->Length();
1422   else return BSplCLib::LastUKnotIndex(udeg,umults->Array1()); 
1423 }
1424
1425 //=======================================================================
1426 //function : LastVKnotIndex
1427 //purpose  : 
1428 //=======================================================================
1429
1430 Standard_Integer Geom_BSplineSurface::LastVKnotIndex() const 
1431 {
1432   if (vperiodic) return vknots->Length();
1433   else return BSplCLib::LastUKnotIndex(vdeg,vmults->Array1()); 
1434 }
1435
1436 //=======================================================================
1437 //function : LocateU
1438 //purpose  : 
1439 //=======================================================================
1440
1441 void Geom_BSplineSurface::LocateU
1442   (const Standard_Real     U, 
1443    const Standard_Real     ParametricTolerance, 
1444          Standard_Integer& I1,
1445          Standard_Integer& I2,
1446    const Standard_Boolean  WithKnotRepetition ) const
1447 {
1448   Standard_Real NewU =U, vbid = vknots->Value(1);
1449   Handle(TColStd_HArray1OfReal) TheKnots;
1450   if (WithKnotRepetition) TheKnots = ufknots;
1451   else                    TheKnots = uknots;
1452
1453   PeriodicNormalization(NewU, vbid); //Attention a la periode
1454   
1455   const TColStd_Array1OfReal & Knots = TheKnots->Array1();
1456   Standard_Real UFirst = Knots (1);
1457   Standard_Real ULast  = Knots (Knots.Length());
1458   Standard_Real PParametricTolerance = Abs(ParametricTolerance);
1459   if (Abs (NewU - UFirst) <= PParametricTolerance) { 
1460     I1 = I2 = 1; 
1461   }
1462   else if (Abs (NewU - ULast) <= PParametricTolerance) { 
1463     I1 = I2 = Knots.Length();
1464   }
1465   else if (NewU < UFirst) {
1466     I2 = 1;
1467     I1 = 0;
1468   }
1469   else if (NewU > ULast) {
1470     I1 = Knots.Length();
1471     I2 = I1 + 1;
1472   }
1473   else {
1474     I1 = 1;
1475     BSplCLib::Hunt (Knots, NewU, I1);
1476     while ( Abs( Knots(I1+1) - NewU) <= PParametricTolerance) I1++;
1477     if ( Abs( Knots(I1) - NewU) <= PParametricTolerance) {
1478       I2 = I1;
1479     }
1480     else {
1481       I2 = I1 + 1;
1482     }
1483   }
1484 }
1485
1486 //=======================================================================
1487 //function : LocateV
1488 //purpose  : 
1489 //=======================================================================
1490
1491 void Geom_BSplineSurface::LocateV
1492   (const Standard_Real     V, 
1493    const Standard_Real     ParametricTolerance, 
1494          Standard_Integer& I1,
1495          Standard_Integer& I2,
1496    const Standard_Boolean  WithKnotRepetition ) const
1497 {
1498   Standard_Real NewV =V, ubid = uknots->Value(1);  
1499   Handle(TColStd_HArray1OfReal) TheKnots;
1500   if (WithKnotRepetition) TheKnots = vfknots;
1501   else                    TheKnots = vknots;
1502
1503   PeriodicNormalization(ubid, NewV); //Attention a la periode
1504   
1505   const TColStd_Array1OfReal & Knots = TheKnots->Array1();
1506   Standard_Real VFirst = Knots (1);
1507   Standard_Real VLast  = Knots (Knots.Length());
1508   Standard_Real PParametricTolerance = Abs(ParametricTolerance);
1509   if (Abs (NewV - VFirst) <= PParametricTolerance) { I1 = I2 = 1; }
1510   else if (Abs (NewV - VLast) <= PParametricTolerance) { 
1511     I1 = I2 = Knots.Length();
1512   }
1513   else if (NewV < VFirst - PParametricTolerance) {
1514     I2 = 1;
1515     I1 = 0;
1516   }
1517   else if (NewV > VLast + PParametricTolerance) {
1518     I1 = Knots.Length();
1519     I2 = I1 + 1;
1520   }
1521   else {
1522     I1 = 1;
1523     BSplCLib::Hunt (Knots, NewV, I1);
1524     while ( Abs( Knots(I1+1) - NewV) <= PParametricTolerance) I1++;
1525     if ( Abs( Knots(I1) - NewV) <= PParametricTolerance) {
1526       I2 = I1;
1527     }
1528     else {
1529       I2 = I1 + 1;
1530     }
1531   }
1532 }
1533
1534 //=======================================================================
1535 //function : UReverse
1536 //purpose  : 
1537 //=======================================================================
1538
1539 void Geom_BSplineSurface::UReverse ()
1540 {
1541   BSplCLib::Reverse(umults->ChangeArray1());
1542   BSplCLib::Reverse(uknots->ChangeArray1());
1543   Standard_Integer last;
1544   if (uperiodic)
1545     last = ufknots->Upper() - udeg -1;
1546   else
1547     last = poles->UpperRow();
1548   BSplSLib::Reverse(poles->ChangeArray2(),last,Standard_True);
1549   if (urational || vrational)
1550     BSplSLib::Reverse(weights->ChangeArray2(),last,Standard_True);
1551   UpdateUKnots();
1552 }
1553
1554 //=======================================================================
1555 //function : UReversedParameter
1556 //purpose  : 
1557 //=======================================================================
1558
1559 Standard_Real Geom_BSplineSurface::UReversedParameter
1560   ( const Standard_Real U) const 
1561 {
1562   return ( uknots->Value( 1) + uknots->Value( uknots->Length()) - U);
1563 }
1564
1565 //=======================================================================
1566 //function : VReverse
1567 //purpose  : 
1568 //=======================================================================
1569
1570 void Geom_BSplineSurface::VReverse ()
1571 {
1572   BSplCLib::Reverse(vmults->ChangeArray1());
1573   BSplCLib::Reverse(vknots->ChangeArray1());
1574   Standard_Integer last;
1575   if (vperiodic)
1576     last = vfknots->Upper() - vdeg -1;
1577   else
1578     last = poles->UpperCol();
1579   BSplSLib::Reverse(poles->ChangeArray2(),last,Standard_False);
1580   if (urational || vrational)
1581     BSplSLib::Reverse(weights->ChangeArray2(),last,Standard_False);
1582   UpdateVKnots();
1583 }
1584
1585 //=======================================================================
1586 //function : VReversedParameter
1587 //purpose  : 
1588 //=======================================================================
1589
1590 Standard_Real Geom_BSplineSurface::VReversedParameter
1591   ( const Standard_Real V) const 
1592 {
1593   return ( vknots->Value( 1) + vknots->Value( vknots->Length()) - V);
1594 }
1595
1596 //=======================================================================
1597 //function : SetPoleCol
1598 //purpose  : 
1599 //=======================================================================
1600
1601 void Geom_BSplineSurface::SetPoleCol (const Standard_Integer      VIndex,
1602                                       const TColgp_Array1OfPnt&   CPoles)
1603 {
1604   if (VIndex < 1 || VIndex > poles->RowLength()) {
1605     Standard_OutOfRange::Raise();
1606     }
1607   if (CPoles.Lower() < 1 || CPoles.Lower() > poles->ColLength() || 
1608       CPoles.Upper() < 1 || CPoles.Upper() > poles->ColLength()) {
1609     Standard_ConstructionError::Raise();
1610     }
1611
1612   TColgp_Array2OfPnt & Poles = poles->ChangeArray2();
1613
1614   for (Standard_Integer I = CPoles.Lower(); I <= CPoles.Upper(); I++) {
1615     Poles (I+Poles.LowerRow()-1, VIndex+Poles.LowerCol()-1) = CPoles(I);
1616   }
1617
1618   InvalidateCache();
1619 }
1620
1621 //=======================================================================
1622 //function : SetPoleCol
1623 //purpose  : 
1624 //=======================================================================
1625
1626 void Geom_BSplineSurface::SetPoleCol (const Standard_Integer      VIndex,
1627                                       const TColgp_Array1OfPnt&   CPoles,
1628                                       const TColStd_Array1OfReal& CPoleWeights)
1629 {
1630   SetPoleCol  (VIndex, CPoles);
1631   SetWeightCol(VIndex, CPoleWeights); 
1632 }
1633
1634 //=======================================================================
1635 //function : SetPoleRow
1636 //purpose  : 
1637 //=======================================================================
1638
1639 void Geom_BSplineSurface::SetPoleRow (const Standard_Integer    UIndex,
1640                                       const TColgp_Array1OfPnt& CPoles)
1641 {
1642   if (UIndex < 1 || UIndex > poles->ColLength()  ) {
1643     Standard_OutOfRange::Raise();
1644     }
1645   if (CPoles.Lower() < 1 || CPoles.Lower() > poles->RowLength() || 
1646       CPoles.Upper() < 1 || CPoles.Upper() > poles->RowLength() ) {
1647     Standard_ConstructionError::Raise();
1648     }
1649
1650   TColgp_Array2OfPnt & Poles = poles->ChangeArray2();
1651
1652   for (Standard_Integer I = CPoles.Lower(); I <= CPoles.Upper(); I++) {
1653     Poles (UIndex+Poles.LowerRow()-1, I+Poles.LowerCol()-1) = CPoles (I);
1654   }
1655
1656   InvalidateCache();
1657 }
1658
1659 //=======================================================================
1660 //function : SetPoleRow
1661 //purpose  : 
1662 //=======================================================================
1663
1664 void Geom_BSplineSurface::SetPoleRow(const Standard_Integer      UIndex,
1665                                      const TColgp_Array1OfPnt &  CPoles,
1666                                      const TColStd_Array1OfReal& CPoleWeights)
1667 {
1668   SetPoleRow  (UIndex, CPoles);
1669   SetWeightRow(UIndex, CPoleWeights);  
1670 }
1671
1672 //=======================================================================
1673 //function : SetPole
1674 //purpose  : 
1675 //=======================================================================
1676
1677 void Geom_BSplineSurface::SetPole (const Standard_Integer UIndex,
1678                                    const Standard_Integer VIndex,
1679                                    const gp_Pnt&          P)
1680 {
1681   poles->SetValue (UIndex+poles->LowerRow()-1, VIndex+poles->LowerCol()-1, P);
1682   InvalidateCache();
1683 }
1684
1685 //=======================================================================
1686 //function : SetPole
1687 //purpose  : 
1688 //=======================================================================
1689
1690 void Geom_BSplineSurface::SetPole (const Standard_Integer UIndex,
1691                                    const Standard_Integer VIndex,
1692                                    const gp_Pnt&          P, 
1693                                    const Standard_Real    Weight)
1694 {
1695   SetWeight(UIndex, VIndex, Weight);
1696   SetPole  (UIndex, VIndex, P);
1697 }
1698
1699 //=======================================================================
1700 //function : MovePoint
1701 //purpose  : 
1702 //=======================================================================
1703
1704 void Geom_BSplineSurface::MovePoint(const Standard_Real U,
1705                                     const Standard_Real V,
1706                                     const gp_Pnt& P,
1707                                     const Standard_Integer UIndex1,
1708                                     const Standard_Integer UIndex2,
1709                                     const Standard_Integer VIndex1,
1710                                     const Standard_Integer VIndex2,
1711                                     Standard_Integer& UFirstModifiedPole,
1712                                     Standard_Integer& ULastmodifiedPole,
1713                                     Standard_Integer& VFirstModifiedPole,
1714                                     Standard_Integer& VLastmodifiedPole)
1715 {
1716   if (UIndex1 < 1 || UIndex1 > poles->UpperRow() || 
1717       UIndex2 < 1 || UIndex2 > poles->UpperRow() || UIndex1 > UIndex2 ||
1718       VIndex1 < 1 || VIndex1 > poles->UpperCol() || 
1719       VIndex2 < 1 || VIndex2 > poles->UpperCol() || VIndex1 > VIndex2) {
1720     Standard_OutOfRange::Raise();
1721   }
1722
1723   TColgp_Array2OfPnt npoles(1, poles->UpperRow(), 1, poles->UpperCol());
1724   gp_Pnt P0;
1725   D0(U, V, P0);
1726   gp_Vec Displ(P0, P);
1727   Standard_Boolean rational = (urational || vrational);
1728   BSplSLib::MovePoint(U, V, Displ, UIndex1, UIndex2, VIndex1, VIndex2, udeg, vdeg,
1729                       rational, poles->Array2(), weights->Array2(),
1730                       ufknots->Array1(), vfknots->Array1(), 
1731                       UFirstModifiedPole, ULastmodifiedPole,
1732                       VFirstModifiedPole, VLastmodifiedPole,
1733                       npoles);
1734   if (UFirstModifiedPole) {
1735     poles->ChangeArray2() = npoles;
1736   }
1737   maxderivinvok = 0;
1738   InvalidateCache() ;
1739 }
1740
1741 //=======================================================================
1742 //function : Bounds
1743 //purpose  : 
1744 //=======================================================================
1745
1746 void Geom_BSplineSurface::Bounds (Standard_Real& U1,
1747                                   Standard_Real& U2,
1748                                   Standard_Real& V1,
1749                                   Standard_Real& V2) const
1750 {
1751   U1 = ufknots->Value (udeg+1);
1752   U2 = ufknots->Value (ufknots->Upper()-udeg);
1753   V1 = vfknots->Value (vdeg+1);
1754   V2 = vfknots->Value (vfknots->Upper()-vdeg);
1755 }
1756
1757 //=======================================================================
1758 //function : MaxDegree
1759 //purpose  : 
1760 //=======================================================================
1761
1762 Standard_Integer Geom_BSplineSurface::MaxDegree () 
1763
1764   return BSplCLib::MaxDegree(); 
1765 }
1766
1767 //=======================================================================
1768 //function : IsURational
1769 //purpose  : 
1770 //=======================================================================
1771
1772 Standard_Boolean Geom_BSplineSurface::IsURational () const 
1773 {
1774   return urational; 
1775 }
1776
1777 //=======================================================================
1778 //function : IsVRational
1779 //purpose  : 
1780 //=======================================================================
1781
1782 Standard_Boolean Geom_BSplineSurface::IsVRational () const 
1783 {
1784   return vrational; 
1785 }
1786
1787 //=======================================================================
1788 //function : Continuity
1789 //purpose  : 
1790 //=======================================================================
1791
1792 GeomAbs_Shape Geom_BSplineSurface::Continuity () const 
1793 {
1794   return ((Usmooth < Vsmooth) ? Usmooth : Vsmooth) ; 
1795 }
1796
1797 //=======================================================================
1798 //function : NbUKnots
1799 //purpose  : 
1800 //=======================================================================
1801
1802 Standard_Integer Geom_BSplineSurface::NbUKnots () const 
1803 {
1804   return uknots->Length(); 
1805 }
1806
1807 //=======================================================================
1808 //function : NbUPoles
1809 //purpose  : 
1810 //=======================================================================
1811
1812 Standard_Integer Geom_BSplineSurface::NbUPoles () const 
1813 {
1814   return poles->ColLength(); 
1815 }
1816
1817 //=======================================================================
1818 //function : NbVKnots
1819 //purpose  : 
1820 //=======================================================================
1821
1822 Standard_Integer Geom_BSplineSurface::NbVKnots () const 
1823 {
1824   return vknots->Length(); 
1825 }
1826
1827 //=======================================================================
1828 //function : NbVPoles
1829 //purpose  : 
1830 //=======================================================================
1831
1832 Standard_Integer Geom_BSplineSurface::NbVPoles () const 
1833 {
1834   return poles->RowLength(); 
1835 }
1836
1837 //=======================================================================
1838 //function : UDegree
1839 //purpose  : 
1840 //=======================================================================
1841
1842 Standard_Integer Geom_BSplineSurface::UDegree () const 
1843 {
1844   return udeg; 
1845 }
1846
1847 //=======================================================================
1848 //function : VDegree
1849 //purpose  : 
1850 //=======================================================================
1851
1852 Standard_Integer Geom_BSplineSurface::VDegree () const 
1853 {
1854   return vdeg; 
1855 }
1856
1857 //=======================================================================
1858 //function : UKnotDistribution
1859 //purpose  : 
1860 //=======================================================================
1861
1862 GeomAbs_BSplKnotDistribution Geom_BSplineSurface::UKnotDistribution() const 
1863
1864   return uknotSet; 
1865 }
1866
1867
1868 //=======================================================================
1869 //function : VKnotDistribution
1870 //purpose  : 
1871 //=======================================================================
1872
1873 GeomAbs_BSplKnotDistribution Geom_BSplineSurface::VKnotDistribution() const 
1874 {
1875   return vknotSet; 
1876 }
1877
1878 //=======================================================================
1879 //function : InsertUKnots
1880 //purpose  : 
1881 //=======================================================================
1882
1883 void  Geom_BSplineSurface::InsertUKnots
1884   (const TColStd_Array1OfReal&    Knots, 
1885    const TColStd_Array1OfInteger& Mults,
1886    const Standard_Real            ParametricTolerance,
1887    const Standard_Boolean         Add)
1888 {
1889   // Check and compute new sizes
1890   Standard_Integer nbpoles, nbknots;
1891
1892   if ( !BSplCLib::PrepareInsertKnots(udeg,uperiodic,
1893                                      uknots->Array1(),umults->Array1(),
1894                                      Knots,Mults,nbpoles,nbknots,
1895                                      ParametricTolerance,Add))
1896     Standard_ConstructionError::Raise("Geom_BSplineSurface::InsertUKnots");
1897   
1898   if ( nbpoles == poles->ColLength()) return;
1899
1900   Handle(TColgp_HArray2OfPnt) npoles
1901     = new TColgp_HArray2OfPnt(1,nbpoles, 1,poles->RowLength());
1902   Handle(TColStd_HArray2OfReal) nweights =
1903     new TColStd_HArray2OfReal(1,nbpoles, 
1904                               1,poles->RowLength(),
1905                               1.0);
1906   Handle(TColStd_HArray1OfReal)    nknots = uknots;
1907   Handle(TColStd_HArray1OfInteger) nmults = umults;
1908
1909   if ( nbknots != uknots->Length()) {
1910     nknots = new TColStd_HArray1OfReal(1,nbknots);
1911     nmults = new TColStd_HArray1OfInteger(1,nbknots);
1912   }
1913
1914   if ( urational || vrational) {
1915     BSplSLib::InsertKnots(Standard_True,
1916                           udeg, uperiodic,
1917                           poles->Array2() , weights->Array2(),
1918                           uknots->Array1(), umults->Array1(),
1919                           Knots, Mults,
1920                           npoles->ChangeArray2(),
1921                           nweights->ChangeArray2(),
1922                           nknots->ChangeArray1(), nmults->ChangeArray1(),
1923                           ParametricTolerance, Add);
1924   }
1925   else {
1926     BSplSLib::InsertKnots(Standard_True,
1927                           udeg, uperiodic,
1928                           poles->Array2() , BSplSLib::NoWeights(),
1929                           uknots->Array1(), umults->Array1(),
1930                           Knots, Mults,
1931                           npoles->ChangeArray2(),
1932                           *((TColStd_Array2OfReal*) NULL),
1933                           nknots->ChangeArray1(), nmults->ChangeArray1(),
1934                           ParametricTolerance, Add);
1935   }
1936
1937   poles = npoles;
1938   weights = nweights;
1939   uknots = nknots;
1940   umults = nmults;
1941   UpdateUKnots();
1942                                      
1943 }
1944
1945 //=======================================================================
1946 //function : InsertVKnots
1947 //purpose  : 
1948 //=======================================================================
1949
1950 void  Geom_BSplineSurface::InsertVKnots
1951   (const TColStd_Array1OfReal& Knots, 
1952    const TColStd_Array1OfInteger& Mults, 
1953    const Standard_Real ParametricTolerance,
1954    const Standard_Boolean Add)
1955 {
1956   // Check and compute new sizes
1957   Standard_Integer nbpoles, nbknots;
1958
1959   if ( !BSplCLib::PrepareInsertKnots(vdeg,vperiodic,
1960                                      vknots->Array1(),vmults->Array1(),
1961                                      Knots,Mults,nbpoles,nbknots,
1962                                      ParametricTolerance, Add))
1963     Standard_ConstructionError::Raise("Geom_BSplineSurface::InsertVKnots");
1964   
1965   if ( nbpoles == poles->RowLength()) return;
1966
1967   Handle(TColgp_HArray2OfPnt) npoles
1968     = new TColgp_HArray2OfPnt(1,poles->ColLength(), 1,nbpoles);
1969   Handle(TColStd_HArray2OfReal) nweights =
1970     new TColStd_HArray2OfReal(1,poles->ColLength(),
1971                               1,nbpoles,
1972                               1.0);
1973   Handle(TColStd_HArray1OfReal)    nknots = vknots;
1974   Handle(TColStd_HArray1OfInteger) nmults = vmults;
1975
1976   if ( nbknots != vknots->Length()) {
1977     nknots = new TColStd_HArray1OfReal(1,nbknots);
1978     nmults = new TColStd_HArray1OfInteger(1,nbknots);
1979   }
1980
1981   if ( urational || vrational) {
1982     BSplSLib::InsertKnots(Standard_False,
1983                           vdeg, vperiodic,
1984                           poles->Array2() , weights->Array2(),
1985                           vknots->Array1(), vmults->Array1(),
1986                           Knots, Mults,
1987                           npoles->ChangeArray2(),
1988                           nweights->ChangeArray2(),
1989                           nknots->ChangeArray1(), nmults->ChangeArray1(),
1990                           ParametricTolerance, Add);
1991   }
1992   else {
1993     BSplSLib::InsertKnots(Standard_False,
1994                           vdeg, vperiodic,
1995                           poles->Array2() , BSplSLib::NoWeights(),
1996                           vknots->Array1(), vmults->Array1(),
1997                           Knots, Mults,
1998                           npoles->ChangeArray2(),
1999                           *((TColStd_Array2OfReal*) NULL),
2000                           nknots->ChangeArray1(), nmults->ChangeArray1(),
2001                           ParametricTolerance, Add);
2002   }
2003
2004   poles = npoles;
2005   weights = nweights;
2006   vknots = nknots;
2007   vmults = nmults;
2008   UpdateVKnots();
2009                                      
2010 }
2011
2012 //=======================================================================
2013 //function : RemoveUKnot
2014 //purpose  : 
2015 //=======================================================================
2016
2017 Standard_Boolean  Geom_BSplineSurface::RemoveUKnot
2018   (const Standard_Integer Index, 
2019    const Standard_Integer M, 
2020    const Standard_Real Tolerance)
2021 {
2022   if ( M < 0 ) return Standard_True;
2023   
2024   Standard_Integer I1 = FirstUKnotIndex ();
2025   Standard_Integer I2 = LastUKnotIndex  ();
2026   
2027   if ( !uperiodic && (Index <= I1 || Index >= I2) ) {
2028     Standard_OutOfRange::Raise();
2029   }
2030   else if ( uperiodic  && (Index < I1 || Index > I2)) {
2031     Standard_OutOfRange::Raise();
2032   }
2033   
2034   const TColgp_Array2OfPnt   & oldpoles = poles->Array2();
2035
2036   Standard_Integer step = umults->Value(Index) - M;
2037   if (step <= 0 ) return Standard_True;
2038
2039   Handle(TColgp_HArray2OfPnt) npoles = 
2040     new TColgp_HArray2OfPnt( 1, oldpoles.ColLength() - step,
2041                              1, oldpoles.RowLength());
2042   Handle(TColStd_HArray1OfReal)    nknots = uknots;
2043   Handle(TColStd_HArray1OfInteger) nmults = umults;
2044
2045   if ( M == 0) {
2046     nknots = new TColStd_HArray1OfReal(1,uknots->Length()-1);
2047     nmults = new TColStd_HArray1OfInteger(1,uknots->Length()-1);
2048   }
2049   Handle(TColStd_HArray2OfReal) nweights ;
2050   if (urational || vrational) {
2051     nweights = 
2052       new TColStd_HArray2OfReal( 1, npoles->ColLength(),
2053                                 1, npoles->RowLength());
2054     if (!BSplSLib::RemoveKnot(Standard_True,
2055                               Index,M,udeg,uperiodic,
2056                               poles->Array2(),weights->Array2(),
2057                               uknots->Array1(),umults->Array1(),
2058                               npoles->ChangeArray2(),
2059                               nweights->ChangeArray2(),
2060                               nknots->ChangeArray1(),nmults->ChangeArray1(),
2061                               Tolerance))
2062       return Standard_False;
2063   }
2064   else {
2065 //
2066 // sync the size of the weights
2067 //
2068     nweights = 
2069       new TColStd_HArray2OfReal(1, npoles->ColLength(),
2070                                 1, npoles->RowLength(),
2071                                 1.0e0 );
2072     if (!BSplSLib::RemoveKnot(Standard_True,
2073                               Index,M,udeg,uperiodic,
2074                               poles->Array2(),BSplSLib::NoWeights(),
2075                               uknots->Array1(),umults->Array1(),
2076                               npoles->ChangeArray2(),
2077                               *((TColStd_Array2OfReal*) NULL),
2078                               nknots->ChangeArray1(),nmults->ChangeArray1(),
2079                               Tolerance))
2080       return Standard_False;
2081   }
2082   
2083   poles = npoles;
2084   weights = nweights;
2085   uknots = nknots;
2086   umults = nmults;
2087
2088   maxderivinvok = 0;
2089   UpdateUKnots();
2090   return Standard_True;
2091 }
2092
2093 //=======================================================================
2094 //function : RemoveVKnot
2095 //purpose  : 
2096 //=======================================================================
2097
2098 Standard_Boolean  Geom_BSplineSurface::RemoveVKnot
2099   (const Standard_Integer Index, 
2100    const Standard_Integer M,
2101    const Standard_Real Tolerance)
2102 {
2103   if ( M < 0 ) return Standard_True;
2104   
2105   Standard_Integer I1 = FirstVKnotIndex ();
2106   Standard_Integer I2 = LastVKnotIndex  ();
2107   
2108   if ( !vperiodic && (Index <= I1 || Index >= I2) ) {
2109     Standard_OutOfRange::Raise();
2110   }
2111   else if ( vperiodic  && (Index < I1 || Index > I2)) {
2112     Standard_OutOfRange::Raise();
2113   }
2114   
2115   const TColgp_Array2OfPnt   & oldpoles = poles->Array2();
2116
2117   Standard_Integer step = vmults->Value(Index) - M;
2118   if (step <= 0 ) return Standard_True;
2119
2120   Handle(TColgp_HArray2OfPnt) npoles = 
2121     new TColgp_HArray2OfPnt( 1, oldpoles.ColLength(),
2122                              1, oldpoles.RowLength() - step);
2123   Handle(TColStd_HArray1OfReal)    nknots = vknots;
2124   Handle(TColStd_HArray1OfInteger) nmults = vmults;
2125
2126   if ( M == 0) {
2127     nknots = new TColStd_HArray1OfReal(1,vknots->Length()-1);
2128     nmults = new TColStd_HArray1OfInteger(1,vknots->Length()-1);
2129   }
2130   Handle(TColStd_HArray2OfReal) nweights ;
2131   if (urational || vrational) {
2132     nweights = 
2133       new TColStd_HArray2OfReal( 1, npoles->ColLength(),
2134                                  1, npoles->RowLength()) ;
2135
2136
2137     if (!BSplSLib::RemoveKnot(Standard_False,
2138                               Index,M,vdeg,vperiodic,
2139                               poles->Array2(),weights->Array2(),
2140                               vknots->Array1(),vmults->Array1(),
2141                               npoles->ChangeArray2(),
2142                               nweights->ChangeArray2(),
2143                               nknots->ChangeArray1(),nmults->ChangeArray1(),
2144                               Tolerance))
2145       return Standard_False;
2146   }
2147   else {
2148 //
2149 // sync the size of the weights array
2150 //
2151     nweights = 
2152       new TColStd_HArray2OfReal(1, npoles->ColLength(),
2153                                 1, npoles->RowLength(),
2154                                 1.0e0 );
2155     if (!BSplSLib::RemoveKnot(Standard_False,
2156                               Index,M,vdeg,vperiodic,
2157                               poles->Array2(),BSplSLib::NoWeights(),
2158                               vknots->Array1(),vmults->Array1(),
2159                               npoles->ChangeArray2(),
2160                               *((TColStd_Array2OfReal*) NULL),
2161                               nknots->ChangeArray1(),nmults->ChangeArray1(),
2162                               Tolerance))
2163       return Standard_False;
2164   }
2165   
2166   poles = npoles;
2167   vknots = nknots;
2168   vmults = nmults;
2169   weights = nweights;
2170   maxderivinvok = 0;
2171   UpdateVKnots();
2172   return Standard_True;
2173 }
2174
2175 //=======================================================================
2176 //function : Resolution
2177 //purpose  : 
2178 //=======================================================================
2179
2180 void   Geom_BSplineSurface::Resolution( const Standard_Real  Tolerance3D,
2181                                        Standard_Real&        UTolerance,
2182                                        Standard_Real&        VTolerance)
2183 {
2184   if(!maxderivinvok){
2185     BSplSLib::Resolution(poles  ->Array2(),
2186                          weights->Array2(),
2187                          uknots ->Array1(),
2188                          vknots ->Array1(),
2189                          umults ->Array1(),
2190                          vmults ->Array1(),
2191                          udeg,
2192                          vdeg,
2193                          urational,
2194                          vrational,
2195                          uperiodic,
2196                          vperiodic,
2197                          1.,
2198                          umaxderivinv,
2199                          vmaxderivinv) ;
2200     maxderivinvok = 1;
2201   }
2202   UTolerance = Tolerance3D * umaxderivinv;
2203   VTolerance = Tolerance3D * vmaxderivinv;
2204 }
2205                        
2206
2207
2208