0030731: Modeling Data - B-Spline should have explicit data check error messages
[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: surface is not U periodic");
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: Index out of range");
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: surface is not V periodic");
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: Index out of range");
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   {
1499     throw Standard_OutOfRange("Geom_BSplineSurface::SetPoleCol: VIndex out of range");
1500   }
1501   if (CPoles.Lower() < 1 || CPoles.Lower() > poles->ColLength() || 
1502       CPoles.Upper() < 1 || CPoles.Upper() > poles->ColLength())
1503   {
1504     throw Standard_ConstructionError("Geom_BSplineSurface::SetPoleCol: invalid array dimension");
1505   }
1506
1507   TColgp_Array2OfPnt & Poles = poles->ChangeArray2();
1508
1509   for (Standard_Integer I = CPoles.Lower(); I <= CPoles.Upper(); I++) {
1510     Poles (I+Poles.LowerRow()-1, VIndex+Poles.LowerCol()-1) = CPoles(I);
1511   }
1512 }
1513
1514 //=======================================================================
1515 //function : SetPoleCol
1516 //purpose  : 
1517 //=======================================================================
1518
1519 void Geom_BSplineSurface::SetPoleCol (const Standard_Integer      VIndex,
1520                                       const TColgp_Array1OfPnt&   CPoles,
1521                                       const TColStd_Array1OfReal& CPoleWeights)
1522 {
1523   SetPoleCol  (VIndex, CPoles);
1524   SetWeightCol(VIndex, CPoleWeights); 
1525 }
1526
1527 //=======================================================================
1528 //function : SetPoleRow
1529 //purpose  : 
1530 //=======================================================================
1531
1532 void Geom_BSplineSurface::SetPoleRow (const Standard_Integer    UIndex,
1533                                       const TColgp_Array1OfPnt& CPoles)
1534 {
1535   if (UIndex < 1 || UIndex > poles->ColLength())
1536   {
1537     throw Standard_OutOfRange("Geom_BSplineSurface::SetPoleRow: UIndex out of range");
1538   }
1539   if (CPoles.Lower() < 1 || CPoles.Lower() > poles->RowLength() || 
1540       CPoles.Upper() < 1 || CPoles.Upper() > poles->RowLength())
1541   {
1542     throw Standard_ConstructionError("Geom_BSplineSurface::SetPoleRow: invalid array dimension");
1543   }
1544
1545   TColgp_Array2OfPnt & Poles = poles->ChangeArray2();
1546
1547   for (Standard_Integer I = CPoles.Lower(); I <= CPoles.Upper(); I++) {
1548     Poles (UIndex+Poles.LowerRow()-1, I+Poles.LowerCol()-1) = CPoles (I);
1549   }
1550 }
1551
1552 //=======================================================================
1553 //function : SetPoleRow
1554 //purpose  : 
1555 //=======================================================================
1556
1557 void Geom_BSplineSurface::SetPoleRow(const Standard_Integer      UIndex,
1558                                      const TColgp_Array1OfPnt &  CPoles,
1559                                      const TColStd_Array1OfReal& CPoleWeights)
1560 {
1561   SetPoleRow  (UIndex, CPoles);
1562   SetWeightRow(UIndex, CPoleWeights);  
1563 }
1564
1565 //=======================================================================
1566 //function : SetPole
1567 //purpose  : 
1568 //=======================================================================
1569
1570 void Geom_BSplineSurface::SetPole (const Standard_Integer UIndex,
1571                                    const Standard_Integer VIndex,
1572                                    const gp_Pnt&          P)
1573 {
1574   poles->SetValue (UIndex+poles->LowerRow()-1, VIndex+poles->LowerCol()-1, P);
1575 }
1576
1577 //=======================================================================
1578 //function : SetPole
1579 //purpose  : 
1580 //=======================================================================
1581
1582 void Geom_BSplineSurface::SetPole (const Standard_Integer UIndex,
1583                                    const Standard_Integer VIndex,
1584                                    const gp_Pnt&          P, 
1585                                    const Standard_Real    Weight)
1586 {
1587   SetWeight(UIndex, VIndex, Weight);
1588   SetPole  (UIndex, VIndex, P);
1589 }
1590
1591 //=======================================================================
1592 //function : MovePoint
1593 //purpose  : 
1594 //=======================================================================
1595
1596 void Geom_BSplineSurface::MovePoint(const Standard_Real U,
1597                                     const Standard_Real V,
1598                                     const gp_Pnt& P,
1599                                     const Standard_Integer UIndex1,
1600                                     const Standard_Integer UIndex2,
1601                                     const Standard_Integer VIndex1,
1602                                     const Standard_Integer VIndex2,
1603                                     Standard_Integer& UFirstModifiedPole,
1604                                     Standard_Integer& ULastmodifiedPole,
1605                                     Standard_Integer& VFirstModifiedPole,
1606                                     Standard_Integer& VLastmodifiedPole)
1607 {
1608   if (UIndex1 < 1 || UIndex1 > poles->UpperRow() || 
1609       UIndex2 < 1 || UIndex2 > poles->UpperRow() || UIndex1 > UIndex2 ||
1610       VIndex1 < 1 || VIndex1 > poles->UpperCol() || 
1611       VIndex2 < 1 || VIndex2 > poles->UpperCol() || VIndex1 > VIndex2)
1612   {
1613     throw Standard_OutOfRange ("Geom_BSplineSurface::MovePoint: Index and #pole mismatch");
1614   }
1615
1616   TColgp_Array2OfPnt npoles(1, poles->UpperRow(), 1, poles->UpperCol());
1617   gp_Pnt P0;
1618   D0(U, V, P0);
1619   gp_Vec Displ(P0, P);
1620   Standard_Boolean rational = (urational || vrational);
1621   BSplSLib::MovePoint(U, V, Displ, UIndex1, UIndex2, VIndex1, VIndex2, udeg, vdeg,
1622                       rational, poles->Array2(), weights->Array2(),
1623                       ufknots->Array1(), vfknots->Array1(), 
1624                       UFirstModifiedPole, ULastmodifiedPole,
1625                       VFirstModifiedPole, VLastmodifiedPole,
1626                       npoles);
1627   if (UFirstModifiedPole) {
1628     poles->ChangeArray2() = npoles;
1629   }
1630   maxderivinvok = 0;
1631 }
1632
1633 //=======================================================================
1634 //function : Bounds
1635 //purpose  : 
1636 //=======================================================================
1637
1638 void Geom_BSplineSurface::Bounds (Standard_Real& U1,
1639                                   Standard_Real& U2,
1640                                   Standard_Real& V1,
1641                                   Standard_Real& V2) const
1642 {
1643   U1 = ufknots->Value (udeg+1);
1644   U2 = ufknots->Value (ufknots->Upper()-udeg);
1645   V1 = vfknots->Value (vdeg+1);
1646   V2 = vfknots->Value (vfknots->Upper()-vdeg);
1647 }
1648
1649 //=======================================================================
1650 //function : MaxDegree
1651 //purpose  : 
1652 //=======================================================================
1653
1654 Standard_Integer Geom_BSplineSurface::MaxDegree () 
1655
1656   return BSplCLib::MaxDegree(); 
1657 }
1658
1659 //=======================================================================
1660 //function : IsURational
1661 //purpose  : 
1662 //=======================================================================
1663
1664 Standard_Boolean Geom_BSplineSurface::IsURational () const 
1665 {
1666   return urational; 
1667 }
1668
1669 //=======================================================================
1670 //function : IsVRational
1671 //purpose  : 
1672 //=======================================================================
1673
1674 Standard_Boolean Geom_BSplineSurface::IsVRational () const 
1675 {
1676   return vrational; 
1677 }
1678
1679 //=======================================================================
1680 //function : Continuity
1681 //purpose  : 
1682 //=======================================================================
1683
1684 GeomAbs_Shape Geom_BSplineSurface::Continuity () const 
1685 {
1686   return ((Usmooth < Vsmooth) ? Usmooth : Vsmooth) ; 
1687 }
1688
1689 //=======================================================================
1690 //function : NbUKnots
1691 //purpose  : 
1692 //=======================================================================
1693
1694 Standard_Integer Geom_BSplineSurface::NbUKnots () const 
1695 {
1696   return uknots->Length(); 
1697 }
1698
1699 //=======================================================================
1700 //function : NbUPoles
1701 //purpose  : 
1702 //=======================================================================
1703
1704 Standard_Integer Geom_BSplineSurface::NbUPoles () const 
1705 {
1706   return poles->ColLength(); 
1707 }
1708
1709 //=======================================================================
1710 //function : NbVKnots
1711 //purpose  : 
1712 //=======================================================================
1713
1714 Standard_Integer Geom_BSplineSurface::NbVKnots () const 
1715 {
1716   return vknots->Length(); 
1717 }
1718
1719 //=======================================================================
1720 //function : NbVPoles
1721 //purpose  : 
1722 //=======================================================================
1723
1724 Standard_Integer Geom_BSplineSurface::NbVPoles () const 
1725 {
1726   return poles->RowLength(); 
1727 }
1728
1729 //=======================================================================
1730 //function : UDegree
1731 //purpose  : 
1732 //=======================================================================
1733
1734 Standard_Integer Geom_BSplineSurface::UDegree () const 
1735 {
1736   return udeg; 
1737 }
1738
1739 //=======================================================================
1740 //function : VDegree
1741 //purpose  : 
1742 //=======================================================================
1743
1744 Standard_Integer Geom_BSplineSurface::VDegree () const 
1745 {
1746   return vdeg; 
1747 }
1748
1749 //=======================================================================
1750 //function : UKnotDistribution
1751 //purpose  : 
1752 //=======================================================================
1753
1754 GeomAbs_BSplKnotDistribution Geom_BSplineSurface::UKnotDistribution() const 
1755
1756   return uknotSet; 
1757 }
1758
1759
1760 //=======================================================================
1761 //function : VKnotDistribution
1762 //purpose  : 
1763 //=======================================================================
1764
1765 GeomAbs_BSplKnotDistribution Geom_BSplineSurface::VKnotDistribution() const 
1766 {
1767   return vknotSet; 
1768 }
1769
1770 //=======================================================================
1771 //function : InsertUKnots
1772 //purpose  : 
1773 //=======================================================================
1774
1775 void  Geom_BSplineSurface::InsertUKnots
1776   (const TColStd_Array1OfReal&    Knots, 
1777    const TColStd_Array1OfInteger& Mults,
1778    const Standard_Real            ParametricTolerance,
1779    const Standard_Boolean         Add)
1780 {
1781   // Check and compute new sizes
1782   Standard_Integer nbpoles, nbknots;
1783
1784   if ( !BSplCLib::PrepareInsertKnots(udeg,uperiodic,
1785                                      uknots->Array1(),umults->Array1(),
1786                                      Knots,&Mults,nbpoles,nbknots,
1787                                      ParametricTolerance,Add))
1788     throw Standard_ConstructionError("Geom_BSplineSurface::InsertUKnots");
1789   
1790   if ( nbpoles == poles->ColLength()) return;
1791
1792   Handle(TColgp_HArray2OfPnt) npoles
1793     = new TColgp_HArray2OfPnt(1,nbpoles, 1,poles->RowLength());
1794   Handle(TColStd_HArray2OfReal) nweights =
1795     new TColStd_HArray2OfReal(1,nbpoles, 
1796                               1,poles->RowLength(),
1797                               1.0);
1798   Handle(TColStd_HArray1OfReal)    nknots = uknots;
1799   Handle(TColStd_HArray1OfInteger) nmults = umults;
1800
1801   if ( nbknots != uknots->Length()) {
1802     nknots = new TColStd_HArray1OfReal(1,nbknots);
1803     nmults = new TColStd_HArray1OfInteger(1,nbknots);
1804   }
1805
1806   if ( urational || vrational) {
1807     BSplSLib::InsertKnots(Standard_True,
1808                           udeg, uperiodic,
1809                           poles->Array2() , &weights->Array2(),
1810                           uknots->Array1(), umults->Array1(),
1811                           Knots, &Mults,
1812                           npoles->ChangeArray2(),
1813                           &nweights->ChangeArray2(),
1814                           nknots->ChangeArray1(), nmults->ChangeArray1(),
1815                           ParametricTolerance, Add);
1816   }
1817   else {
1818     BSplSLib::InsertKnots(Standard_True,
1819                           udeg, uperiodic,
1820                           poles->Array2() , BSplSLib::NoWeights(),
1821                           uknots->Array1(), umults->Array1(),
1822                           Knots, &Mults,
1823                           npoles->ChangeArray2(),
1824                           BSplSLib::NoWeights(),
1825                           nknots->ChangeArray1(), nmults->ChangeArray1(),
1826                           ParametricTolerance, Add);
1827   }
1828
1829   poles = npoles;
1830   weights = nweights;
1831   uknots = nknots;
1832   umults = nmults;
1833   UpdateUKnots();
1834                                      
1835 }
1836
1837 //=======================================================================
1838 //function : InsertVKnots
1839 //purpose  : 
1840 //=======================================================================
1841
1842 void  Geom_BSplineSurface::InsertVKnots
1843   (const TColStd_Array1OfReal& Knots, 
1844    const TColStd_Array1OfInteger& Mults, 
1845    const Standard_Real ParametricTolerance,
1846    const Standard_Boolean Add)
1847 {
1848   // Check and compute new sizes
1849   Standard_Integer nbpoles, nbknots;
1850
1851   if ( !BSplCLib::PrepareInsertKnots(vdeg,vperiodic,
1852                                      vknots->Array1(),vmults->Array1(),
1853                                      Knots,&Mults,nbpoles,nbknots,
1854                                      ParametricTolerance, Add))
1855     throw Standard_ConstructionError("Geom_BSplineSurface::InsertVKnots");
1856   
1857   if ( nbpoles == poles->RowLength()) return;
1858
1859   Handle(TColgp_HArray2OfPnt) npoles
1860     = new TColgp_HArray2OfPnt(1,poles->ColLength(), 1,nbpoles);
1861   Handle(TColStd_HArray2OfReal) nweights =
1862     new TColStd_HArray2OfReal(1,poles->ColLength(),
1863                               1,nbpoles,
1864                               1.0);
1865   Handle(TColStd_HArray1OfReal)    nknots = vknots;
1866   Handle(TColStd_HArray1OfInteger) nmults = vmults;
1867
1868   if ( nbknots != vknots->Length()) {
1869     nknots = new TColStd_HArray1OfReal(1,nbknots);
1870     nmults = new TColStd_HArray1OfInteger(1,nbknots);
1871   }
1872
1873   if ( urational || vrational) {
1874     BSplSLib::InsertKnots(Standard_False,
1875                           vdeg, vperiodic,
1876                           poles->Array2() , &weights->Array2(),
1877                           vknots->Array1(), vmults->Array1(),
1878                           Knots, &Mults,
1879                           npoles->ChangeArray2(),
1880                           &nweights->ChangeArray2(),
1881                           nknots->ChangeArray1(), nmults->ChangeArray1(),
1882                           ParametricTolerance, Add);
1883   }
1884   else {
1885     BSplSLib::InsertKnots(Standard_False,
1886                           vdeg, vperiodic,
1887                           poles->Array2() , BSplSLib::NoWeights(),
1888                           vknots->Array1(), vmults->Array1(),
1889                           Knots, &Mults,
1890                           npoles->ChangeArray2(),
1891                           BSplSLib::NoWeights(),
1892                           nknots->ChangeArray1(), nmults->ChangeArray1(),
1893                           ParametricTolerance, Add);
1894   }
1895
1896   poles = npoles;
1897   weights = nweights;
1898   vknots = nknots;
1899   vmults = nmults;
1900   UpdateVKnots();
1901                                      
1902 }
1903
1904 //=======================================================================
1905 //function : RemoveUKnot
1906 //purpose  : 
1907 //=======================================================================
1908
1909 Standard_Boolean  Geom_BSplineSurface::RemoveUKnot
1910   (const Standard_Integer Index, 
1911    const Standard_Integer M, 
1912    const Standard_Real Tolerance)
1913 {
1914   if ( M < 0 ) return Standard_True;
1915   
1916   Standard_Integer I1 = FirstUKnotIndex ();
1917   Standard_Integer I2 = LastUKnotIndex  ();
1918   
1919   if ( !uperiodic && (Index <= I1 || Index >= I2) )
1920   {
1921     throw Standard_OutOfRange("Geom_BSplineSurface::RemoveUKnot: invalid Index");
1922   }
1923   else if ( uperiodic  && (Index < I1 || Index > I2))
1924   {
1925     throw Standard_OutOfRange("Geom_BSplineSurface::RemoveUKnot: invalid Index for periodic case");
1926   }
1927   
1928   const TColgp_Array2OfPnt   & oldpoles = poles->Array2();
1929
1930   Standard_Integer step = umults->Value(Index) - M;
1931   if (step <= 0 ) return Standard_True;
1932
1933   Handle(TColgp_HArray2OfPnt) npoles = 
1934     new TColgp_HArray2OfPnt( 1, oldpoles.ColLength() - step,
1935                              1, oldpoles.RowLength());
1936   Handle(TColStd_HArray1OfReal)    nknots = uknots;
1937   Handle(TColStd_HArray1OfInteger) nmults = umults;
1938
1939   if ( M == 0) {
1940     nknots = new TColStd_HArray1OfReal(1,uknots->Length()-1);
1941     nmults = new TColStd_HArray1OfInteger(1,uknots->Length()-1);
1942   }
1943   Handle(TColStd_HArray2OfReal) nweights ;
1944   if (urational || vrational) {
1945     nweights = 
1946       new TColStd_HArray2OfReal( 1, npoles->ColLength(),
1947                                 1, npoles->RowLength());
1948     if (!BSplSLib::RemoveKnot(Standard_True,
1949                               Index,M,udeg,uperiodic,
1950                               poles->Array2(),&weights->Array2(),
1951                               uknots->Array1(),umults->Array1(),
1952                               npoles->ChangeArray2(),
1953                               &nweights->ChangeArray2(),
1954                               nknots->ChangeArray1(),nmults->ChangeArray1(),
1955                               Tolerance))
1956       return Standard_False;
1957   }
1958   else {
1959 //
1960 // sync the size of the weights
1961 //
1962     nweights = 
1963       new TColStd_HArray2OfReal(1, npoles->ColLength(),
1964                                 1, npoles->RowLength(),
1965                                 1.0e0 );
1966     if (!BSplSLib::RemoveKnot(Standard_True,
1967                               Index,M,udeg,uperiodic,
1968                               poles->Array2(),BSplSLib::NoWeights(),
1969                               uknots->Array1(),umults->Array1(),
1970                               npoles->ChangeArray2(),
1971                               BSplSLib::NoWeights(),
1972                               nknots->ChangeArray1(),nmults->ChangeArray1(),
1973                               Tolerance))
1974       return Standard_False;
1975   }
1976   
1977   poles = npoles;
1978   weights = nweights;
1979   uknots = nknots;
1980   umults = nmults;
1981
1982   maxderivinvok = 0;
1983   UpdateUKnots();
1984   return Standard_True;
1985 }
1986
1987 //=======================================================================
1988 //function : RemoveVKnot
1989 //purpose  : 
1990 //=======================================================================
1991
1992 Standard_Boolean  Geom_BSplineSurface::RemoveVKnot
1993   (const Standard_Integer Index, 
1994    const Standard_Integer M,
1995    const Standard_Real Tolerance)
1996 {
1997   if ( M < 0 ) return Standard_True;
1998   
1999   Standard_Integer I1 = FirstVKnotIndex ();
2000   Standard_Integer I2 = LastVKnotIndex  ();
2001   
2002   if ( !vperiodic && (Index <= I1 || Index >= I2) )
2003   {
2004     throw Standard_OutOfRange("Geom_BSplineSurface::RemoveVKnot: invalid Index");
2005   }
2006   else if ( vperiodic  && (Index < I1 || Index > I2)) {
2007     throw Standard_OutOfRange("Geom_BSplineSurface::RemoveVKnot: invalid Index for periodic case");
2008   }
2009   
2010   const TColgp_Array2OfPnt   & oldpoles = poles->Array2();
2011
2012   Standard_Integer step = vmults->Value(Index) - M;
2013   if (step <= 0 ) return Standard_True;
2014
2015   Handle(TColgp_HArray2OfPnt) npoles = 
2016     new TColgp_HArray2OfPnt( 1, oldpoles.ColLength(),
2017                              1, oldpoles.RowLength() - step);
2018   Handle(TColStd_HArray1OfReal)    nknots = vknots;
2019   Handle(TColStd_HArray1OfInteger) nmults = vmults;
2020
2021   if ( M == 0) {
2022     nknots = new TColStd_HArray1OfReal(1,vknots->Length()-1);
2023     nmults = new TColStd_HArray1OfInteger(1,vknots->Length()-1);
2024   }
2025   Handle(TColStd_HArray2OfReal) nweights ;
2026   if (urational || vrational) {
2027     nweights = 
2028       new TColStd_HArray2OfReal( 1, npoles->ColLength(),
2029                                  1, npoles->RowLength()) ;
2030
2031
2032     if (!BSplSLib::RemoveKnot(Standard_False,
2033                               Index,M,vdeg,vperiodic,
2034                               poles->Array2(),&weights->Array2(),
2035                               vknots->Array1(),vmults->Array1(),
2036                               npoles->ChangeArray2(),
2037                               &nweights->ChangeArray2(),
2038                               nknots->ChangeArray1(),nmults->ChangeArray1(),
2039                               Tolerance))
2040       return Standard_False;
2041   }
2042   else {
2043 //
2044 // sync the size of the weights array
2045 //
2046     nweights = 
2047       new TColStd_HArray2OfReal(1, npoles->ColLength(),
2048                                 1, npoles->RowLength(),
2049                                 1.0e0 );
2050     if (!BSplSLib::RemoveKnot(Standard_False,
2051                               Index,M,vdeg,vperiodic,
2052                               poles->Array2(),BSplSLib::NoWeights(),
2053                               vknots->Array1(),vmults->Array1(),
2054                               npoles->ChangeArray2(),
2055                               BSplSLib::NoWeights(),
2056                               nknots->ChangeArray1(),nmults->ChangeArray1(),
2057                               Tolerance))
2058       return Standard_False;
2059   }
2060   
2061   poles = npoles;
2062   vknots = nknots;
2063   vmults = nmults;
2064   weights = nweights;
2065   maxderivinvok = 0;
2066   UpdateVKnots();
2067   return Standard_True;
2068 }
2069
2070 //=======================================================================
2071 //function : Resolution
2072 //purpose  : 
2073 //=======================================================================
2074
2075 void   Geom_BSplineSurface::Resolution( const Standard_Real  Tolerance3D,
2076                                        Standard_Real&        UTolerance,
2077                                        Standard_Real&        VTolerance)
2078 {
2079   if(!maxderivinvok){
2080     BSplSLib::Resolution(poles  ->Array2(),
2081                          &weights->Array2(),
2082                          uknots ->Array1(),
2083                          vknots ->Array1(),
2084                          umults ->Array1(),
2085                          vmults ->Array1(),
2086                          udeg,
2087                          vdeg,
2088                          urational,
2089                          vrational,
2090                          uperiodic,
2091                          vperiodic,
2092                          1.,
2093                          umaxderivinv,
2094                          vmaxderivinv) ;
2095     maxderivinvok = 1;
2096   }
2097   UTolerance = Tolerance3D * umaxderivinv;
2098   VTolerance = Tolerance3D * vmaxderivinv;
2099 }
2100                        
2101
2102
2103