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