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