CR23683: Geom_BSplineSurface incorrectly determines continuity for periodic cases
[occt.git] / src / Geom / Geom_BSplineSurface.cxx
... / ...
CommitLineData
1// Created on: 1993-03-09
2// Created by: JCV
3// Copyright (c) 1993-1999 Matra Datavision
4// Copyright (c) 1999-2012 OPEN CASCADE SAS
5//
6// The content of this file is subject to the Open CASCADE Technology Public
7// License Version 6.5 (the "License"). You may not use the content of this file
8// except in compliance with the License. Please obtain a copy of the License
9// at http://www.opencascade.org and read it completely before using this file.
10//
11// The Initial Developer of the Original Code is Open CASCADE S.A.S., having its
12// main offices at: 1, place des Freres Montgolfier, 78280 Guyancourt, France.
13//
14// The Original Code and all software distributed under the License is
15// distributed on an "AS IS" basis, without warranty of any kind, and the
16// Initial Developer hereby disclaims all such warranties, including without
17// limitation, any warranties of merchantability, fitness for a particular
18// purpose or non-infringement. Please see the License for the specific terms
19// and conditions governing the rights and limitations under the License.
20
21
22// 14-Mar-96 : xab portage hp
23// pmn : 28-Jun-96 Distinction entre la continuite en U et V (bug PRO4625)
24// pmn : 07-Jan-97 Centralisation des verif rational (PRO6834)
25// et ajout des InvalideCache() dans les SetWeight*(PRO6833)
26// RBD : 15-10-98 ; Le cache est maintenant calcule sur [-1,1] (pro15537).
27// jct : 19-01-99 ; permutation de urational et vrational dans Rational.
28#define No_Standard_OutOfRange
29
30#include <Geom_BSplineSurface.ixx>
31
32#include <gp.hxx>
33#include <BSplCLib.hxx>
34#include <BSplSLib.hxx>
35
36#include <Standard_ConstructionError.hxx>
37#include <Standard_NotImplemented.hxx>
38#include <Standard_OutOfRange.hxx>
39#include <Precision.hxx>
40
41//=======================================================================
42//function : CheckSurfaceData
43//purpose : Internal use only.
44//=======================================================================
45
46static void CheckSurfaceData
47(const TColgp_Array2OfPnt& SPoles,
48 const TColStd_Array1OfReal& SUKnots,
49 const TColStd_Array1OfReal& SVKnots,
50 const TColStd_Array1OfInteger& SUMults,
51 const TColStd_Array1OfInteger& SVMults,
52 const Standard_Integer UDegree,
53 const Standard_Integer VDegree,
54 const Standard_Boolean UPeriodic,
55 const Standard_Boolean VPeriodic)
56{
57 if (UDegree < 1 || UDegree > Geom_BSplineSurface::MaxDegree () ||
58 VDegree < 1 || VDegree > Geom_BSplineSurface::MaxDegree ()) {
59 Standard_ConstructionError::Raise("Geom_BSplineSurface");
60 }
61 if (SPoles.ColLength () < 2 || SPoles.RowLength () < 2) {
62 Standard_ConstructionError::Raise("Geom_BSplineSurface");
63 }
64
65 if (SUKnots.Length() != SUMults.Length() ||
66 SVKnots.Length() != SVMults.Length()) {
67 Standard_ConstructionError::Raise("Geom_BSplineSurface");
68 }
69
70 Standard_Integer i;
71 for (i = SUKnots.Lower(); i < SUKnots.Upper(); i++) {
72 if (SUKnots(i+1) - SUKnots(i) <= Epsilon(Abs(SUKnots(i)))) {
73 Standard_ConstructionError::Raise("Geom_BSplineSurface");
74 }
75 }
76
77 for (i = SVKnots.Lower(); i < SVKnots.Upper(); i++) {
78 if (SVKnots(i+1) - SVKnots(i) <= Epsilon(Abs(SVKnots(i)))) {
79 Standard_ConstructionError::Raise("Geom_BSplineSurface");
80 }
81 }
82
83 if (SPoles.ColLength() != BSplCLib::NbPoles(UDegree,UPeriodic,SUMults))
84 Standard_ConstructionError::Raise("Geom_BSplineSurface");
85
86 if (SPoles.RowLength() != BSplCLib::NbPoles(VDegree,VPeriodic,SVMults))
87 Standard_ConstructionError::Raise("Geom_BSplineSurface");
88}
89
90//=======================================================================
91//function : Rational
92//purpose : Internal use only.
93//=======================================================================
94
95static void Rational(const TColStd_Array2OfReal& Weights,
96 Standard_Boolean& Urational,
97 Standard_Boolean& Vrational)
98{
99 Standard_Integer I,J;
100 J = Weights.LowerCol ();
101 Vrational = Standard_False;
102 while (!Vrational && J <= Weights.UpperCol()) {
103 I = Weights.LowerRow();
104 while (!Vrational && I <= Weights.UpperRow() - 1) {
105 Vrational = (Abs(Weights (I, J) - Weights (I+1, J))
106 > Epsilon (Abs(Weights (I, J))));
107 I++;
108 }
109 J++;
110 }
111
112 I = Weights.LowerRow ();
113 Urational = Standard_False;
114 while (!Urational && I <= Weights.UpperRow()) {
115 J = Weights.LowerCol();
116 while (!Urational && J <= Weights.UpperCol() - 1) {
117 Urational = (Abs(Weights (I, J) - Weights (I, J+1))
118 > Epsilon (Abs(Weights (I, J))));
119 J++;
120 }
121 I++;
122 }
123}
124
125//=======================================================================
126//function : Copy
127//purpose :
128//=======================================================================
129
130Handle(Geom_Geometry) Geom_BSplineSurface::Copy () const
131{
132 Handle(Geom_BSplineSurface) S;
133 if (urational || vrational)
134 S = new Geom_BSplineSurface (poles->Array2() , weights->Array2(),
135 uknots->Array1(), vknots->Array1(),
136 umults->Array1(), vmults->Array1(),
137 udeg , vdeg,
138 uperiodic, vperiodic);
139 else
140 S = new Geom_BSplineSurface (poles->Array2(),
141 uknots->Array1(), vknots->Array1(),
142 umults->Array1(), vmults->Array1(),
143 udeg , vdeg,
144 uperiodic, vperiodic);
145 return S;
146}
147
148//=======================================================================
149//function : Geom_BSplineSurface
150//purpose :
151//=======================================================================
152
153Geom_BSplineSurface::Geom_BSplineSurface
154(const TColgp_Array2OfPnt& Poles,
155 const TColStd_Array1OfReal& UKnots,
156 const TColStd_Array1OfReal& VKnots,
157 const TColStd_Array1OfInteger& UMults,
158 const TColStd_Array1OfInteger& VMults,
159 const Standard_Integer UDegree,
160 const Standard_Integer VDegree,
161 const Standard_Boolean UPeriodic,
162 const Standard_Boolean VPeriodic
163 ) :
164 urational(Standard_False),
165 vrational(Standard_False),
166 uperiodic(UPeriodic),
167 vperiodic(VPeriodic),
168 udeg(UDegree),
169 vdeg(VDegree),
170 maxderivinvok(0)
171
172{
173 Standard_Integer MinDegree,
174 MaxDegree ;
175
176 // check
177
178 CheckSurfaceData(Poles,
179 UKnots , VKnots,
180 UMults , VMults,
181 UDegree , VDegree,
182 UPeriodic, VPeriodic);
183
184 // copy arrays
185
186 poles = new TColgp_HArray2OfPnt(1,Poles.ColLength(),
187 1,Poles.RowLength());
188 poles->ChangeArray2() = Poles;
189
190 weights = new TColStd_HArray2OfReal (1,Poles.ColLength(),
191 1,Poles.RowLength(), 1.0);
192
193 uknots = new TColStd_HArray1OfReal (1,UKnots.Length());
194 uknots->ChangeArray1() = UKnots;
195
196 umults = new TColStd_HArray1OfInteger (1,UMults.Length());
197 umults->ChangeArray1() = UMults;
198
199 vknots = new TColStd_HArray1OfReal (1,VKnots.Length());
200 vknots->ChangeArray1() = VKnots;
201
202 vmults = new TColStd_HArray1OfInteger (1,VMults.Length());
203 vmults->ChangeArray1() = VMults;
204 MinDegree = Min(udeg,vdeg) ;
205 MaxDegree = Max(udeg,vdeg) ;
206 cachepoles = new TColgp_HArray2OfPnt(1,MaxDegree + 1,
207 1,MinDegree + 1) ;
208
209 cacheweights.Nullify() ;
210 ucacheparameter = 0.0e0 ;
211 vcacheparameter = 0.0e0 ;
212 ucachespanlenght = 1.0e0 ;
213 vcachespanlenght = 1.0e0 ;
214 ucachespanindex = 0 ;
215 vcachespanindex = 0 ;
216 validcache = 0 ;
217
218 UpdateUKnots();
219 UpdateVKnots();
220}
221
222//=======================================================================
223//function : Geom_BSplineSurface
224//purpose :
225//=======================================================================
226
227Geom_BSplineSurface::Geom_BSplineSurface
228(const TColgp_Array2OfPnt& Poles,
229 const TColStd_Array2OfReal& Weights,
230 const TColStd_Array1OfReal& UKnots,
231 const TColStd_Array1OfReal& VKnots,
232 const TColStd_Array1OfInteger& UMults,
233 const TColStd_Array1OfInteger& VMults,
234 const Standard_Integer UDegree,
235 const Standard_Integer VDegree,
236 const Standard_Boolean UPeriodic,
237 const Standard_Boolean VPeriodic) :
238 urational(Standard_False),
239 vrational(Standard_False),
240 uperiodic(UPeriodic),
241 vperiodic(VPeriodic),
242 udeg(UDegree),
243 vdeg(VDegree),
244 maxderivinvok(0)
245{
246 Standard_Integer MinDegree,
247 MaxDegree ;
248 // check weights
249
250 if (Weights.ColLength() != Poles.ColLength())
251 Standard_ConstructionError::Raise("Geom_BSplineSurface");
252
253 if (Weights.RowLength() != Poles.RowLength())
254 Standard_ConstructionError::Raise("Geom_BSplineSurface");
255
256 Standard_Integer i,j;
257 for (i = Weights.LowerRow(); i <= Weights.UpperRow(); i++) {
258 for (j = Weights.LowerCol(); j <= Weights.UpperCol(); j++) {
259 if (Weights(i,j) <= gp::Resolution())
260 Standard_ConstructionError::Raise("Geom_BSplineSurface");
261 }
262 }
263
264 // check really rational
265
266 Rational(Weights, urational, vrational);
267
268 // check
269
270 CheckSurfaceData(Poles,
271 UKnots , VKnots,
272 UMults , VMults,
273 UDegree , VDegree,
274 UPeriodic, VPeriodic);
275
276 // copy arrays
277
278 poles = new TColgp_HArray2OfPnt(1,Poles.ColLength(),
279 1,Poles.RowLength());
280 poles->ChangeArray2() = Poles;
281
282 weights = new TColStd_HArray2OfReal (1,Poles.ColLength(),
283 1,Poles.RowLength());
284 weights->ChangeArray2() = Weights;
285
286 uknots = new TColStd_HArray1OfReal (1,UKnots.Length());
287 uknots->ChangeArray1() = UKnots;
288
289 umults = new TColStd_HArray1OfInteger (1,UMults.Length());
290 umults->ChangeArray1() = UMults;
291
292 vknots = new TColStd_HArray1OfReal (1,VKnots.Length());
293 vknots->ChangeArray1() = VKnots;
294
295 vmults = new TColStd_HArray1OfInteger (1,VMults.Length());
296 vmults->ChangeArray1() = VMults;
297 MinDegree = Min(udeg,vdeg) ;
298 MaxDegree = Max(udeg,vdeg) ;
299 cachepoles = new TColgp_HArray2OfPnt(1,MaxDegree + 1,
300 1,MinDegree + 1) ;
301 if (urational || vrational) {
302 cacheweights = new TColStd_HArray2OfReal (1,MaxDegree + 1,
303 1,MinDegree + 1);
304 }
305 ucacheparameter = 0.0e0 ;
306 vcacheparameter = 0.0e0 ;
307 ucachespanlenght = 1.0e0 ;
308 vcachespanlenght = 1.0e0 ;
309 ucachespanindex = 0 ;
310 vcachespanindex = 0 ;
311 validcache = 0 ;
312
313 UpdateUKnots();
314 UpdateVKnots();
315}
316
317//=======================================================================
318//function : ExchangeUV
319//purpose :
320//=======================================================================
321
322void Geom_BSplineSurface::ExchangeUV ()
323{
324 Standard_Integer LC = poles->LowerCol();
325 Standard_Integer UC = poles->UpperCol();
326 Standard_Integer LR = poles->LowerRow();
327 Standard_Integer UR = poles->UpperRow();
328
329 Handle(TColgp_HArray2OfPnt) npoles =
330 new TColgp_HArray2OfPnt (LC, UC, LR, UR);
331 Handle(TColStd_HArray2OfReal) nweights =
332 new TColStd_HArray2OfReal (LC, UC, LR, UR);
333
334 const TColgp_Array2OfPnt & spoles = poles->Array2();
335 const TColStd_Array2OfReal & sweights = weights->Array2();
336
337 TColgp_Array2OfPnt& snpoles = npoles->ChangeArray2();
338 TColStd_Array2OfReal& snweights = nweights->ChangeArray2();
339
340 Standard_Integer i, j;
341 for (i = LC; i <= UC; i++) {
342 for (j = LR; j <= UR; j++) {
343 snpoles (i,j) = spoles (j,i);
344 snweights (i,j) = sweights (j,i);
345 }
346 }
347
348 poles = npoles;
349 weights = nweights;
350
351 Standard_Boolean temp = urational;
352 urational = vrational;
353 vrational = temp;
354
355 temp = uperiodic;
356 uperiodic = vperiodic;
357 vperiodic = temp;
358
359 Standard_Integer tempdeg = udeg;
360 udeg = vdeg;
361 vdeg = tempdeg;
362
363
364 Handle(TColStd_HArray1OfReal) tempknots = uknots;
365 uknots = vknots;
366 vknots = tempknots;
367
368 Handle(TColStd_HArray1OfInteger) tempmults = umults;
369 umults = vmults;
370 vmults = tempmults;
371
372 UpdateUKnots();
373 UpdateVKnots();
374}
375
376//=======================================================================
377//function : IncreaseDegree
378//purpose :
379//=======================================================================
380
381void Geom_BSplineSurface::IncreaseDegree (const Standard_Integer UDegree,
382 const Standard_Integer VDegree)
383{
384 if (UDegree != udeg) {
385 if ( UDegree < udeg || UDegree > Geom_BSplineSurface::MaxDegree())
386 Standard_ConstructionError::Raise();
387
388 Standard_Integer FromK1 = FirstUKnotIndex();
389 Standard_Integer ToK2 = LastUKnotIndex();
390
391 Standard_Integer Step = UDegree - udeg;
392
393 Handle(TColgp_HArray2OfPnt) npoles = new
394 TColgp_HArray2OfPnt( 1, poles->ColLength() + Step * (ToK2 - FromK1),
395 1, poles->RowLength());
396
397 Standard_Integer nbknots = BSplCLib::IncreaseDegreeCountKnots
398 (udeg,UDegree,uperiodic,umults->Array1());
399
400 Handle(TColStd_HArray1OfReal) nknots =
401 new TColStd_HArray1OfReal(1,nbknots);
402
403 Handle(TColStd_HArray1OfInteger) nmults =
404 new TColStd_HArray1OfInteger(1,nbknots);
405
406 Handle(TColStd_HArray2OfReal) nweights
407 = new TColStd_HArray2OfReal(1,npoles->ColLength(),
408 1,npoles->RowLength(), 1.);
409
410 if (urational || vrational) {
411
412 BSplSLib::IncreaseDegree
413 (Standard_True, udeg, UDegree, uperiodic,
414 poles->Array2(),weights->Array2(),
415 uknots->Array1(),umults->Array1(),
416 npoles->ChangeArray2(),nweights->ChangeArray2(),
417 nknots->ChangeArray1(),nmults->ChangeArray1());
418 }
419 else {
420
421 BSplSLib::IncreaseDegree
422 (Standard_True, udeg, UDegree, uperiodic,
423 poles->Array2(),BSplSLib::NoWeights(),
424 uknots->Array1(),umults->Array1(),
425 npoles->ChangeArray2(),*((TColStd_Array2OfReal*) NULL),
426 nknots->ChangeArray1(),nmults->ChangeArray1());
427 }
428 udeg = UDegree;
429 poles = npoles;
430 weights = nweights;
431 uknots = nknots;
432 umults = nmults;
433 UpdateUKnots();
434 }
435
436 if (VDegree != vdeg) {
437 if ( VDegree < vdeg || VDegree > Geom_BSplineSurface::MaxDegree())
438 Standard_ConstructionError::Raise();
439
440 Standard_Integer FromK1 = FirstVKnotIndex();
441 Standard_Integer ToK2 = LastVKnotIndex();
442
443 Standard_Integer Step = VDegree - vdeg;
444
445 Handle(TColgp_HArray2OfPnt) npoles = new
446 TColgp_HArray2OfPnt( 1, poles->ColLength(),
447 1, poles->RowLength() + Step * (ToK2 - FromK1));
448
449 Standard_Integer nbknots = BSplCLib::IncreaseDegreeCountKnots
450 (vdeg,VDegree,vperiodic,vmults->Array1());
451
452 Handle(TColStd_HArray1OfReal) nknots =
453 new TColStd_HArray1OfReal(1,nbknots);
454
455 Handle(TColStd_HArray1OfInteger) nmults =
456 new TColStd_HArray1OfInteger(1,nbknots);
457
458 Handle(TColStd_HArray2OfReal) nweights
459 = new TColStd_HArray2OfReal(1,npoles->ColLength(),
460 1,npoles->RowLength(), 1.);
461
462 if (urational || vrational) {
463
464 BSplSLib::IncreaseDegree
465 (Standard_False, vdeg, VDegree, vperiodic,
466 poles->Array2(),weights->Array2(),
467 vknots->Array1(),vmults->Array1(),
468 npoles->ChangeArray2(),nweights->ChangeArray2(),
469 nknots->ChangeArray1(),nmults->ChangeArray1());
470 }
471 else {
472
473 BSplSLib::IncreaseDegree
474 (Standard_False, vdeg, VDegree, vperiodic,
475 poles->Array2(),BSplSLib::NoWeights(),
476 vknots->Array1(),vmults->Array1(),
477 npoles->ChangeArray2(),*((TColStd_Array2OfReal*) NULL),
478 nknots->ChangeArray1(),nmults->ChangeArray1());
479 }
480 vdeg = VDegree;
481 poles = npoles;
482 weights = nweights;
483 vknots = nknots;
484 vmults = nmults;
485 UpdateVKnots();
486 }
487}
488
489//=======================================================================
490//function : IncreaseUMultiplicity
491//purpose :
492//=======================================================================
493
494void Geom_BSplineSurface::IncreaseUMultiplicity
495(const Standard_Integer UIndex,
496 const Standard_Integer M)
497{
498 TColStd_Array1OfReal k(1,1);
499 k(1) = uknots->Value(UIndex);
500 TColStd_Array1OfInteger m(1,1);
501 m(1) = M - umults->Value(UIndex);
502 InsertUKnots(k,m,Epsilon(1.),Standard_True);
503}
504
505//=======================================================================
506//function : IncreaseUMultiplicity
507//purpose :
508//=======================================================================
509
510void Geom_BSplineSurface::IncreaseUMultiplicity
511(const Standard_Integer FromI1,
512 const Standard_Integer ToI2,
513 const Standard_Integer M)
514{
515 Handle(TColStd_HArray1OfReal) tk = uknots;
516 TColStd_Array1OfReal k((uknots->Array1())(FromI1),FromI1,ToI2);
517 TColStd_Array1OfInteger m(FromI1, ToI2);
518 for (Standard_Integer i = FromI1; i <= ToI2; i++)
519 m(i) = M - umults->Value(i);
520 InsertUKnots(k,m,Epsilon(1.),Standard_True);
521}
522
523//=======================================================================
524//function : IncreaseVMultiplicity
525//purpose :
526//=======================================================================
527
528void Geom_BSplineSurface::IncreaseVMultiplicity
529(const Standard_Integer VIndex,
530 const Standard_Integer M)
531{
532 TColStd_Array1OfReal k(1,1);
533 k(1) = vknots->Value(VIndex);
534 TColStd_Array1OfInteger m(1,1);
535 m(1) = M - vmults->Value(VIndex);
536 InsertVKnots(k,m,Epsilon(1.),Standard_True);
537}
538
539//=======================================================================
540//function : IncreaseVMultiplicity
541//purpose :
542//=======================================================================
543
544void Geom_BSplineSurface::IncreaseVMultiplicity
545(const Standard_Integer FromI1,
546 const Standard_Integer ToI2,
547 const Standard_Integer M)
548{
549 Handle(TColStd_HArray1OfReal) tk = vknots;
550 TColStd_Array1OfReal k((vknots->Array1())(FromI1),FromI1,ToI2);
551 TColStd_Array1OfInteger m(FromI1,ToI2);
552 for (Standard_Integer i = FromI1; i <= ToI2; i++)
553 m(i) = M - vmults->Value(i);
554 InsertVKnots(k,m,Epsilon(1.),Standard_True);
555}
556
557//=======================================================================
558//function : Segment
559//purpose :
560//=======================================================================
561
562void Geom_BSplineSurface::Segment(const Standard_Real U1,
563 const Standard_Real U2,
564 const Standard_Real V1,
565 const Standard_Real V2)
566{
567
568 Standard_DomainError_Raise_if ( (U2 < U1) || (V2 < V1),
569 "Geom_BSplineCurve::Segment");
570 Standard_Real deltaU = Max(Abs(U2),Abs(U1));
571 Standard_Real EpsU = Epsilon(deltaU);
572 deltaU = U2 - U1;
573
574 Standard_Real deltaV = Max(Abs(V2),Abs(V1));
575 Standard_Real EpsV = Epsilon(deltaV);
576 deltaV = V2 - V1;
577
578 Standard_Real NewU1, NewU2, NewV1, NewV2;
579 Standard_Real U,V;
580 Standard_Integer indexU, indexV;
581
582 // inserting the UKnots
583 TColStd_Array1OfReal UKnots(1,2);
584 TColStd_Array1OfInteger UMults(1,2);
585
586 indexU = 0;
587 BSplCLib::LocateParameter(udeg,uknots->Array1(),umults->Array1(),
588 U1,uperiodic,uknots->Lower(),uknots->Upper(),
589 indexU,NewU1);
590 indexU = 0;
591 BSplCLib::LocateParameter(udeg,uknots->Array1(),umults->Array1(),
592 U2,uperiodic,uknots->Lower(),uknots->Upper(),
593 indexU,NewU2);
594 UKnots( 1) = Min( NewU1, NewU2);
595 UKnots( 2) = Max( NewU1, NewU2);
596 UMults( 1) = UMults( 2) = udeg;
597 InsertUKnots( UKnots, UMults, EpsU);
598
599 // Inserting the VKnots
600 TColStd_Array1OfReal VKnots(1,2);
601 TColStd_Array1OfInteger VMults(1,2);
602
603 indexV = 0;
604 BSplCLib::LocateParameter(vdeg,vknots->Array1(),vmults->Array1(),
605 V1,vperiodic,vknots->Lower(),vknots->Upper(),
606 indexV,NewV1);
607 indexV = 0;
608 BSplCLib::LocateParameter(vdeg,vknots->Array1(),vmults->Array1(),
609 V2,vperiodic,vknots->Lower(),vknots->Upper(),
610 indexV,NewV2);
611 VKnots( 1) = Min( NewV1, NewV2);
612 VKnots( 2) = Max( NewV1, NewV2);
613 VMults( 1) = VMults( 2) = vdeg;
614 InsertVKnots( VKnots, VMults, EpsV);
615
616
617 if (uperiodic) { // set the origine at NewU1
618 Standard_Integer index = 0;
619 BSplCLib::LocateParameter(udeg,uknots->Array1(),umults->Array1(),
620 U1,uperiodic,uknots->Lower(),uknots->Upper(),
621 index,U);
622 if ( Abs(uknots->Value(index+1)-U) <= EpsU)
623 index++;
624 SetUOrigin(index);
625 SetUNotPeriodic();
626 }
627
628 // compute index1 and index2 to set the new knots and mults
629 Standard_Integer index1U = 0, index2U = 0;
630 Standard_Integer FromU1 = uknots->Lower();
631 Standard_Integer ToU2 = uknots->Upper();
632 BSplCLib::LocateParameter(udeg,uknots->Array1(),umults->Array1(),
633 NewU1,uperiodic,FromU1,ToU2,index1U,U);
634 BSplCLib::LocateParameter(udeg,uknots->Array1(),umults->Array1(),
635 NewU1 + deltaU,uperiodic,FromU1,ToU2,index2U,U);
636 if ( Abs(uknots->Value(index2U+1)-U) <= EpsU)
637 index2U++;
638
639 Standard_Integer nbuknots = index2U - index1U + 1;
640
641 Handle(TColStd_HArray1OfReal)
642 nuknots = new TColStd_HArray1OfReal(1,nbuknots);
643 Handle(TColStd_HArray1OfInteger)
644 numults = new TColStd_HArray1OfInteger(1,nbuknots);
645
646 Standard_Integer i , k = 1;
647 for ( i = index1U; i<= index2U; i++) {
648 nuknots->SetValue(k, uknots->Value(i));
649 numults->SetValue(k, umults->Value(i));
650 k++;
651 }
652 numults->SetValue( 1, udeg + 1);
653 numults->SetValue(nbuknots, udeg + 1);
654
655
656 if (vperiodic) { // set the origine at NewV1
657 Standard_Integer index = 0;
658 BSplCLib::LocateParameter(vdeg,vknots->Array1(),vmults->Array1(),
659 V1,vperiodic,vknots->Lower(),vknots->Upper(),
660 index,V);
661 if ( Abs(vknots->Value(index+1)-V) <= EpsV)
662 index++;
663 SetVOrigin(index);
664 SetVNotPeriodic();
665 }
666
667 // compute index1 and index2 to set the new knots and mults
668 Standard_Integer index1V = 0, index2V = 0;
669 Standard_Integer FromV1 = vknots->Lower();
670 Standard_Integer ToV2 = vknots->Upper();
671 BSplCLib::LocateParameter(vdeg,vknots->Array1(),vmults->Array1(),
672 NewV1,vperiodic,FromV1,ToV2,index1V,V);
673 BSplCLib::LocateParameter(vdeg,vknots->Array1(),vmults->Array1(),
674 NewV1 + deltaV,vperiodic,FromV1,ToV2,index2V,V);
675 if ( Abs(vknots->Value(index2V+1)-V) <= EpsV)
676 index2V++;
677
678 Standard_Integer nbvknots = index2V - index1V + 1;
679
680 Handle(TColStd_HArray1OfReal)
681 nvknots = new TColStd_HArray1OfReal(1,nbvknots);
682 Handle(TColStd_HArray1OfInteger)
683 nvmults = new TColStd_HArray1OfInteger(1,nbvknots);
684
685 k = 1;
686 for ( i = index1V; i<= index2V; i++) {
687 nvknots->SetValue(k, vknots->Value(i));
688 nvmults->SetValue(k, vmults->Value(i));
689 k++;
690 }
691 nvmults->SetValue( 1, vdeg + 1);
692 nvmults->SetValue(nbvknots, vdeg + 1);
693
694
695 // compute index1 and index2 to set the new poles and weights
696 Standard_Integer pindex1U
697 = BSplCLib::PoleIndex(udeg,index1U,uperiodic,umults->Array1());
698 Standard_Integer pindex2U
699 = BSplCLib::PoleIndex(udeg,index2U,uperiodic,umults->Array1());
700
701 pindex1U++;
702 pindex2U = Min( pindex2U+1, poles->ColLength());
703
704 Standard_Integer nbupoles = pindex2U - pindex1U + 1;
705
706 // compute index1 and index2 to set the new poles and weights
707 Standard_Integer pindex1V
708 = BSplCLib::PoleIndex(vdeg,index1V,vperiodic,vmults->Array1());
709 Standard_Integer pindex2V
710 = BSplCLib::PoleIndex(vdeg,index2V,vperiodic,vmults->Array1());
711
712 pindex1V++;
713 pindex2V = Min( pindex2V+1, poles->RowLength());
714
715 Standard_Integer nbvpoles = pindex2V - pindex1V + 1;
716
717
718 Handle(TColStd_HArray2OfReal) nweights;
719
720 Handle(TColgp_HArray2OfPnt)
721 npoles = new TColgp_HArray2OfPnt(1,nbupoles,1,nbvpoles);
722
723 k = 1;
724 Standard_Integer j, l;
725 if ( urational || vrational) {
726 nweights = new TColStd_HArray2OfReal( 1,nbupoles,1,nbvpoles);
727 for ( i = pindex1U; i <= pindex2U; i++) {
728 l = 1;
729 for ( j = pindex1V; j <= pindex2V; j++) {
730 npoles->SetValue(k,l, poles->Value(i,j));
731 nweights->SetValue(k,l, weights->Value(i,j));
732 l++;
733 }
734 k++;
735 }
736 }
737 else {
738 for ( i = pindex1U; i <= pindex2U; i++) {
739 l = 1;
740 for ( j = pindex1V; j <= pindex2V; j++) {
741 npoles->SetValue(k,l, poles->Value(i,j));
742 l++;
743 }
744 k++;
745 }
746 }
747
748 uknots = nuknots;
749 umults = numults;
750 vknots = nvknots;
751 vmults = nvmults;
752 poles = npoles;
753 if ( urational || vrational)
754 weights = nweights;
755 else
756 weights = new TColStd_HArray2OfReal (1,poles->ColLength(),
757 1,poles->RowLength(), 1.0);
758
759 maxderivinvok = 0;
760 UpdateUKnots();
761 UpdateVKnots();
762
763}
764
765//=======================================================================
766//function : CheckAndSegment
767//purpose :
768//=======================================================================
769
770void Geom_BSplineSurface::CheckAndSegment(const Standard_Real U1,
771 const Standard_Real U2,
772 const Standard_Real V1,
773 const Standard_Real V2)
774{
775
776 Standard_DomainError_Raise_if ( (U2 < U1) || (V2 < V1),
777 "Geom_BSplineCurve::Segment");
778 Standard_Real deltaU = Max(Abs(U2),Abs(U1));
779 Standard_Real EpsU = Epsilon(deltaU);
780 deltaU = U2 - U1;
781
782 Standard_Real deltaV = Max(Abs(V2),Abs(V1));
783 Standard_Real EpsV = Epsilon(deltaV);
784 deltaV = V2 - V1;
785
786 Standard_Real NewU1, NewU2, NewV1, NewV2;
787 Standard_Real U,V;
788 Standard_Integer indexU, indexV;
789
790 Standard_Boolean segment_in_U = Standard_True;
791 Standard_Boolean segment_in_V = Standard_True;
792 segment_in_U = ( Abs(U1 - uknots->Value(uknots->Lower())) > EpsU )
793 || ( Abs(U2 - uknots->Value(uknots->Upper())) > EpsU );
794 segment_in_V = ( Abs(V1 - vknots->Value(vknots->Lower())) > EpsV )
795 || ( Abs(V2 - vknots->Value(vknots->Upper())) > EpsV );
796
797 indexU = 0;
798 BSplCLib::LocateParameter(udeg,uknots->Array1(),umults->Array1(),
799 U1,uperiodic,uknots->Lower(),uknots->Upper(),
800 indexU,NewU1);
801 indexU = 0;
802 BSplCLib::LocateParameter(udeg,uknots->Array1(),umults->Array1(),
803 U2,uperiodic,uknots->Lower(),uknots->Upper(),
804 indexU,NewU2);
805 if (segment_in_U) {
806 // inserting the UKnots
807 TColStd_Array1OfReal UKnots(1,2);
808 TColStd_Array1OfInteger UMults(1,2);
809 UKnots( 1) = Min( NewU1, NewU2);
810 UKnots( 2) = Max( NewU1, NewU2);
811 UMults( 1) = UMults( 2) = udeg;
812
813 InsertUKnots( UKnots, UMults, EpsU);
814 }
815
816 indexV = 0;
817 BSplCLib::LocateParameter(vdeg,vknots->Array1(),vmults->Array1(),
818 V1,vperiodic,vknots->Lower(),vknots->Upper(),
819 indexV,NewV1);
820 indexV = 0;
821 BSplCLib::LocateParameter(vdeg,vknots->Array1(),vmults->Array1(),
822 V2,vperiodic,vknots->Lower(),vknots->Upper(),
823 indexV,NewV2);
824 if (segment_in_V) {
825 // Inserting the VKnots
826 TColStd_Array1OfReal VKnots(1,2);
827 TColStd_Array1OfInteger VMults(1,2);
828
829 VKnots( 1) = Min( NewV1, NewV2);
830 VKnots( 2) = Max( NewV1, NewV2);
831 VMults( 1) = VMults( 2) = vdeg;
832 InsertVKnots( VKnots, VMults, EpsV);
833 }
834
835 if (uperiodic && segment_in_U) { // set the origine at NewU1
836 Standard_Integer index = 0;
837 BSplCLib::LocateParameter(udeg,uknots->Array1(),umults->Array1(),
838 U1,uperiodic,uknots->Lower(),uknots->Upper(),
839 index,U);
840 if ( Abs(uknots->Value(index+1)-U) <= EpsU)
841 index++;
842 SetUOrigin(index);
843 SetUNotPeriodic();
844 }
845
846 // compute index1 and index2 to set the new knots and mults
847 Standard_Integer index1U = 0, index2U = 0;
848 Standard_Integer FromU1 = uknots->Lower();
849 Standard_Integer ToU2 = uknots->Upper();
850 BSplCLib::LocateParameter(udeg,uknots->Array1(),umults->Array1(),
851 NewU1,uperiodic,FromU1,ToU2,index1U,U);
852 BSplCLib::LocateParameter(udeg,uknots->Array1(),umults->Array1(),
853 NewU1 + deltaU,uperiodic,FromU1,ToU2,index2U,U);
854 if ( Abs(uknots->Value(index2U+1)-U) <= EpsU)
855 index2U++;
856
857 Standard_Integer nbuknots = index2U - index1U + 1;
858
859 Handle(TColStd_HArray1OfReal)
860 nuknots = new TColStd_HArray1OfReal(1,nbuknots);
861 Handle(TColStd_HArray1OfInteger)
862 numults = new TColStd_HArray1OfInteger(1,nbuknots);
863
864 Standard_Integer i , k = 1;
865 for ( i = index1U; i<= index2U; i++) {
866 nuknots->SetValue(k, uknots->Value(i));
867 numults->SetValue(k, umults->Value(i));
868 k++;
869 }
870 if (segment_in_U) {
871 numults->SetValue( 1, udeg + 1);
872 numults->SetValue(nbuknots, udeg + 1);
873 }
874
875 if (vperiodic&& segment_in_V) { // set the origine at NewV1
876 Standard_Integer index = 0;
877 BSplCLib::LocateParameter(vdeg,vknots->Array1(),vmults->Array1(),
878 V1,vperiodic,vknots->Lower(),vknots->Upper(),
879 index,V);
880 if ( Abs(vknots->Value(index+1)-V) <= EpsV)
881 index++;
882 SetVOrigin(index);
883 SetVNotPeriodic();
884 }
885
886 // compute index1 and index2 to set the new knots and mults
887 Standard_Integer index1V = 0, index2V = 0;
888 Standard_Integer FromV1 = vknots->Lower();
889 Standard_Integer ToV2 = vknots->Upper();
890 BSplCLib::LocateParameter(vdeg,vknots->Array1(),vmults->Array1(),
891 NewV1,vperiodic,FromV1,ToV2,index1V,V);
892 BSplCLib::LocateParameter(vdeg,vknots->Array1(),vmults->Array1(),
893 NewV1 + deltaV,vperiodic,FromV1,ToV2,index2V,V);
894 if ( Abs(vknots->Value(index2V+1)-V) <= EpsV)
895 index2V++;
896
897 Standard_Integer nbvknots = index2V - index1V + 1;
898
899 Handle(TColStd_HArray1OfReal)
900 nvknots = new TColStd_HArray1OfReal(1,nbvknots);
901 Handle(TColStd_HArray1OfInteger)
902 nvmults = new TColStd_HArray1OfInteger(1,nbvknots);
903
904 k = 1;
905 for ( i = index1V; i<= index2V; i++) {
906 nvknots->SetValue(k, vknots->Value(i));
907 nvmults->SetValue(k, vmults->Value(i));
908 k++;
909 }
910 if (segment_in_V) {
911 nvmults->SetValue( 1, vdeg + 1);
912 nvmults->SetValue(nbvknots, vdeg + 1);
913 }
914
915 // compute index1 and index2 to set the new poles and weights
916 Standard_Integer pindex1U
917 = BSplCLib::PoleIndex(udeg,index1U,uperiodic,umults->Array1());
918 Standard_Integer pindex2U
919 = BSplCLib::PoleIndex(udeg,index2U,uperiodic,umults->Array1());
920
921 pindex1U++;
922 pindex2U = Min( pindex2U+1, poles->ColLength());
923
924 Standard_Integer nbupoles = pindex2U - pindex1U + 1;
925
926 // compute index1 and index2 to set the new poles and weights
927 Standard_Integer pindex1V
928 = BSplCLib::PoleIndex(vdeg,index1V,vperiodic,vmults->Array1());
929 Standard_Integer pindex2V
930 = BSplCLib::PoleIndex(vdeg,index2V,vperiodic,vmults->Array1());
931
932 pindex1V++;
933 pindex2V = Min( pindex2V+1, poles->RowLength());
934
935 Standard_Integer nbvpoles = pindex2V - pindex1V + 1;
936
937
938 Handle(TColStd_HArray2OfReal) nweights;
939
940 Handle(TColgp_HArray2OfPnt)
941 npoles = new TColgp_HArray2OfPnt(1,nbupoles,1,nbvpoles);
942
943 k = 1;
944 Standard_Integer j, l;
945 if ( urational || vrational) {
946 nweights = new TColStd_HArray2OfReal( 1,nbupoles,1,nbvpoles);
947 for ( i = pindex1U; i <= pindex2U; i++) {
948 l = 1;
949 for ( j = pindex1V; j <= pindex2V; j++) {
950 npoles->SetValue(k,l, poles->Value(i,j));
951 nweights->SetValue(k,l, weights->Value(i,j));
952 l++;
953 }
954 k++;
955 }
956 }
957 else {
958 for ( i = pindex1U; i <= pindex2U; i++) {
959 l = 1;
960 for ( j = pindex1V; j <= pindex2V; j++) {
961 npoles->SetValue(k,l, poles->Value(i,j));
962 l++;
963 }
964 k++;
965 }
966 }
967
968 uknots = nuknots;
969 umults = numults;
970 vknots = nvknots;
971 vmults = nvmults;
972 poles = npoles;
973 if ( urational || vrational)
974 weights = nweights;
975 else
976 weights = new TColStd_HArray2OfReal (1,poles->ColLength(),
977 1,poles->RowLength(), 1.0);
978
979 maxderivinvok = 0;
980 UpdateUKnots();
981 UpdateVKnots();
982
983}
984
985//=======================================================================
986//function : SetUKnot
987//purpose :
988//=======================================================================
989
990void Geom_BSplineSurface::SetUKnot
991(const Standard_Integer UIndex,
992 const Standard_Real K )
993{
994 if (UIndex < 1 || UIndex > uknots->Length()) Standard_OutOfRange::Raise();
995
996 Standard_Integer NewIndex = UIndex;
997 Standard_Real DU = Abs(Epsilon (K));
998 if (UIndex == 1) {
999 if (K >= uknots->Value (2) - DU) Standard_ConstructionError::Raise();
1000 }
1001 else if (UIndex == uknots->Length()) {
1002 if (K <= uknots->Value (uknots->Length()-1) + DU) {
1003 Standard_ConstructionError::Raise();
1004 }
1005 }
1006 else {
1007 if (K <= uknots->Value (NewIndex-1) + DU ||
1008 K >= uknots->Value (NewIndex+1) - DU ) {
1009 Standard_ConstructionError::Raise();
1010 }
1011 }
1012
1013 if (K != uknots->Value (NewIndex)) {
1014 uknots->SetValue (NewIndex, K);
1015 maxderivinvok = 0;
1016 UpdateUKnots();
1017 }
1018}
1019
1020//=======================================================================
1021//function : SetUKnots
1022//purpose :
1023//=======================================================================
1024
1025void Geom_BSplineSurface::SetUKnots (const TColStd_Array1OfReal& UK) {
1026
1027 Standard_Integer Lower = UK.Lower();
1028 Standard_Integer Upper = UK.Upper();
1029 if (Lower < 1 || Lower > uknots->Length() ||
1030 Upper < 1 || Upper > uknots->Length() ) {
1031 Standard_OutOfRange::Raise();
1032 }
1033 Standard_Real Eps;
1034 if (Lower > 1) {
1035 Eps = Abs (Epsilon (uknots->Value (Lower-1)));
1036 if (Abs (UK (Lower) - uknots->Value (Lower-1)) <= gp::Resolution()) {
1037 Standard_ConstructionError::Raise();
1038 }
1039 }
1040 if (Upper < uknots->Length ()) {
1041 Eps = Abs (Epsilon (uknots->Value (Upper+1)));
1042 if (Abs (UK (Upper) - uknots->Value (Upper+1)) <= gp::Resolution()) {
1043 Standard_ConstructionError::Raise();
1044 }
1045 }
1046 Standard_Real K1 = UK (Lower);
1047 for (Standard_Integer i = Lower; i <= Upper; i++) {
1048 uknots->SetValue (i, UK(i));
1049 if (i != Lower) {
1050 Eps = Abs (Epsilon (K1));
1051 if (Abs (UK(i) - K1) <= gp::Resolution()) {
1052 Standard_ConstructionError::Raise();
1053 }
1054 K1 = UK (i);
1055 }
1056 }
1057
1058 maxderivinvok = 0;
1059 UpdateUKnots();
1060}
1061
1062//=======================================================================
1063//function : SetUKnot
1064//purpose :
1065//=======================================================================
1066
1067void Geom_BSplineSurface::SetUKnot
1068(const Standard_Integer UIndex,
1069 const Standard_Real K,
1070 const Standard_Integer M)
1071{
1072 IncreaseUMultiplicity (UIndex, M);
1073 SetUKnot (UIndex, K);
1074}
1075
1076//=======================================================================
1077//function : SetVKnot
1078//purpose :
1079//=======================================================================
1080
1081void Geom_BSplineSurface::SetVKnot
1082(const Standard_Integer VIndex,
1083 const Standard_Real K)
1084{
1085 if (VIndex < 1 || VIndex > vknots->Length()) Standard_OutOfRange::Raise();
1086 Standard_Integer NewIndex = VIndex + vknots->Lower() - 1;
1087 Standard_Real DV = Abs(Epsilon (K));
1088 if (VIndex == 1) {
1089 if (K >= vknots->Value (2) - DV) {
1090 Standard_ConstructionError::Raise();
1091 }
1092 }
1093 else if (VIndex == vknots->Length()) {
1094 if (K <= vknots->Value (vknots->Length()-1) + DV) {
1095 Standard_ConstructionError::Raise();
1096 }
1097 }
1098 else {
1099 if (K <= vknots->Value (NewIndex-1) + DV ||
1100 K >= vknots->Value (NewIndex+1) - DV ) {
1101 Standard_ConstructionError::Raise();
1102 }
1103 }
1104
1105 maxderivinvok = 0;
1106 UpdateVKnots();
1107}
1108
1109//=======================================================================
1110//function : SetVKnots
1111//purpose :
1112//=======================================================================
1113
1114void Geom_BSplineSurface::SetVKnots (const TColStd_Array1OfReal& VK) {
1115
1116 Standard_Integer Lower = VK.Lower();
1117 Standard_Integer Upper = VK.Upper();
1118 if (Lower < 1 || Lower > vknots->Length() ||
1119 Upper < 1 || Upper > vknots->Length() ) {
1120 Standard_OutOfRange::Raise();
1121 }
1122 Standard_Real Eps;
1123 if (Lower > 1) {
1124 Eps = Abs (Epsilon (vknots->Value (Lower-1)));
1125 if (Abs (VK (Lower) - vknots->Value (Lower-1)) <= gp::Resolution()) {
1126 Standard_ConstructionError::Raise();
1127 }
1128 }
1129 if (Upper < vknots->Length ()) {
1130 Eps = Abs (Epsilon (vknots->Value (Upper+1)));
1131 if (Abs (VK (Upper) - vknots->Value (Upper+1)) <= gp::Resolution()) {
1132 Standard_ConstructionError::Raise();
1133 }
1134 }
1135 Standard_Real K1 = VK (Lower);
1136 for (Standard_Integer i = Lower; i <= Upper; i++) {
1137 vknots->SetValue (i, VK(i));
1138 if (i != Lower) {
1139 Eps = Abs (Epsilon (K1));
1140 if (Abs (VK(i) - K1) <= gp::Resolution()) {
1141 Standard_ConstructionError::Raise();
1142 }
1143 K1 = VK (i);
1144 }
1145 }
1146
1147 maxderivinvok = 0;
1148 UpdateVKnots();
1149}
1150
1151//=======================================================================
1152//function : SetVKnot
1153//purpose :
1154//=======================================================================
1155
1156void Geom_BSplineSurface::SetVKnot
1157(const Standard_Integer VIndex,
1158 const Standard_Real K,
1159 const Standard_Integer M)
1160{
1161 IncreaseVMultiplicity (VIndex, M);
1162 SetVKnot (VIndex, K);
1163}
1164
1165//=======================================================================
1166//function : InsertUKnot
1167//purpose :
1168//=======================================================================
1169
1170void Geom_BSplineSurface::InsertUKnot
1171(const Standard_Real U,
1172 const Standard_Integer M,
1173 const Standard_Real ParametricTolerance,
1174 const Standard_Boolean Add)
1175{
1176 TColStd_Array1OfReal k(1,1);
1177 k(1) = U;
1178 TColStd_Array1OfInteger m(1,1);
1179 m(1) = M;
1180 InsertUKnots(k,m,ParametricTolerance,Add);
1181}
1182
1183//=======================================================================
1184//function : InsertVKnot
1185//purpose :
1186//=======================================================================
1187
1188void Geom_BSplineSurface::InsertVKnot
1189(const Standard_Real V,
1190 const Standard_Integer M,
1191 const Standard_Real ParametricTolerance,
1192 const Standard_Boolean Add)
1193{
1194 TColStd_Array1OfReal k(1,1);
1195 k(1) = V;
1196 TColStd_Array1OfInteger m(1,1);
1197 m(1) = M;
1198 InsertVKnots(k,m,ParametricTolerance,Add);
1199}
1200
1201//=======================================================================
1202//function : IncrementUMultiplicity
1203//purpose :
1204//=======================================================================
1205
1206void Geom_BSplineSurface::IncrementUMultiplicity
1207(const Standard_Integer FromI1,
1208 const Standard_Integer ToI2,
1209 const Standard_Integer Step)
1210{
1211 Handle(TColStd_HArray1OfReal) tk = uknots;
1212 TColStd_Array1OfReal k( (uknots->Array1())(FromI1), FromI1, ToI2);
1213 TColStd_Array1OfInteger m( FromI1, ToI2) ;
1214 m.Init(Step);
1215 InsertUKnots( k, m, Epsilon(1.));
1216}
1217
1218//=======================================================================
1219//function : IncrementVMultiplicity
1220//purpose :
1221//=======================================================================
1222
1223void Geom_BSplineSurface::IncrementVMultiplicity
1224(const Standard_Integer FromI1,
1225 const Standard_Integer ToI2,
1226 const Standard_Integer Step)
1227{
1228 Handle(TColStd_HArray1OfReal) tk = vknots;
1229 TColStd_Array1OfReal k( (vknots->Array1())(FromI1), FromI1, ToI2);
1230
1231 TColStd_Array1OfInteger m( FromI1, ToI2) ;
1232 m.Init(Step);
1233
1234 InsertVKnots( k, m, Epsilon(1.));
1235}
1236
1237//=======================================================================
1238//function : UpdateUKnots
1239//purpose :
1240//=======================================================================
1241
1242void Geom_BSplineSurface::UpdateUKnots()
1243{
1244
1245 Standard_Integer MaxKnotMult = 0;
1246 BSplCLib::KnotAnalysis (udeg, uperiodic,
1247 uknots->Array1(),
1248 umults->Array1(),
1249 uknotSet, MaxKnotMult);
1250
1251 if (uknotSet == GeomAbs_Uniform && !uperiodic) {
1252 ufknots = uknots;
1253 }
1254 else {
1255 ufknots = new TColStd_HArray1OfReal
1256 (1, BSplCLib::KnotSequenceLength(umults->Array1(),udeg,uperiodic));
1257
1258 BSplCLib::KnotSequence (uknots->Array1(),
1259 umults->Array1(),
1260 udeg,uperiodic,
1261 ufknots->ChangeArray1());
1262 }
1263
1264 if (MaxKnotMult == 0) Usmooth = GeomAbs_CN;
1265 else {
1266 switch (udeg - MaxKnotMult) {
1267 case 0 : Usmooth = GeomAbs_C0; break;
1268 case 1 : Usmooth = GeomAbs_C1; break;
1269 case 2 : Usmooth = GeomAbs_C2; break;
1270 case 3 : Usmooth = GeomAbs_C3; break;
1271 default : Usmooth = GeomAbs_C3; break;
1272 }
1273 }
1274
1275 InvalidateCache() ;
1276}
1277
1278//=======================================================================
1279//function : UpdateVKnots
1280//purpose :
1281//=======================================================================
1282
1283void Geom_BSplineSurface::UpdateVKnots()
1284{
1285 Standard_Integer MaxKnotMult = 0;
1286 BSplCLib::KnotAnalysis (vdeg, vperiodic,
1287 vknots->Array1(),
1288 vmults->Array1(),
1289 vknotSet, MaxKnotMult);
1290
1291 if (vknotSet == GeomAbs_Uniform && !vperiodic) {
1292 vfknots = vknots;
1293 }
1294 else {
1295 vfknots = new TColStd_HArray1OfReal
1296 (1, BSplCLib::KnotSequenceLength(vmults->Array1(),vdeg,vperiodic));
1297
1298 BSplCLib::KnotSequence (vknots->Array1(),
1299 vmults->Array1(),
1300 vdeg,vperiodic,
1301 vfknots->ChangeArray1());
1302 }
1303
1304 if (MaxKnotMult == 0) Vsmooth = GeomAbs_CN;
1305 else {
1306 switch (vdeg - MaxKnotMult) {
1307 case 0 : Vsmooth = GeomAbs_C0; break;
1308 case 1 : Vsmooth = GeomAbs_C1; break;
1309 case 2 : Vsmooth = GeomAbs_C2; break;
1310 case 3 : Vsmooth = GeomAbs_C3; break;
1311 default : Vsmooth = GeomAbs_C3; break;
1312 }
1313 }
1314 InvalidateCache() ;
1315}
1316
1317//=======================================================================
1318//function : InvalidateCache
1319//purpose : Invalidates the Cache of the surface
1320//=======================================================================
1321
1322void Geom_BSplineSurface::InvalidateCache()
1323{
1324 validcache = 0 ;
1325}
1326
1327//=======================================================================
1328//function : Normalizes the parameters if the curve is periodic
1329//purpose : that is compute the cache so that it is valid
1330//=======================================================================
1331
1332void Geom_BSplineSurface::PeriodicNormalization
1333(Standard_Real& Uparameter,
1334 Standard_Real& Vparameter) const
1335{
1336 Standard_Real Period, aMaxVal, aMinVal;
1337
1338 if (uperiodic) {
1339 aMaxVal = ufknots->Value(ufknots->Upper() - udeg);
1340 aMinVal = ufknots->Value (udeg + 1);
1341 Standard_Real eps = Abs(Epsilon(Uparameter));
1342 Period = aMaxVal - aMinVal;
1343
1344 if(Period <= eps)
1345 Standard_OutOfRange::Raise("Geom_BSplineSurface::PeriodicNormalization: Uparameter is too great number");
1346
1347 while (Uparameter > aMaxVal) {
1348 Uparameter -= Period ;
1349 }
1350
1351 while (Uparameter < aMinVal) {
1352 Uparameter += Period ;
1353 }
1354 }
1355 if (vperiodic) {
1356 aMaxVal = vfknots->Value(vfknots->Upper() - vdeg);
1357 aMinVal = vfknots->Value (vdeg + 1);
1358 Standard_Real eps = Abs(Epsilon(Vparameter));
1359 Period = aMaxVal - aMinVal;
1360
1361 if(Period <= eps)
1362 Standard_OutOfRange::Raise("Geom_BSplineSurface::PeriodicNormalization: Vparameter is too great number");
1363
1364 while (Vparameter > aMaxVal) {
1365 Vparameter -= Period ;
1366 }
1367 while (Vparameter < aMinVal) {
1368 Vparameter += Period ;
1369 }
1370 }
1371}
1372
1373//=======================================================================
1374//function : ValidateCache
1375//purpose : function that validates the cache of the surface
1376//=======================================================================
1377
1378void Geom_BSplineSurface::ValidateCache(const Standard_Real Uparameter,
1379 const Standard_Real Vparameter)
1380{
1381 Standard_Real NewParameter ;
1382 Standard_Integer LocalIndex = 0 ;
1383 Standard_Integer MinDegree,
1384 MaxDegree ;
1385 //
1386 // check if the degree did not change
1387 //
1388
1389 MinDegree = Min(udeg,vdeg) ;
1390 MaxDegree = Max(udeg,vdeg) ;
1391 if (cachepoles->ColLength() < MaxDegree + 1 ||
1392 cachepoles->RowLength() < MinDegree + 1) {
1393 cachepoles = new TColgp_HArray2OfPnt(1,MaxDegree + 1,
1394 1,MinDegree + 1);
1395 }
1396 //
1397 // Verif + poussee pour les poids
1398 //
1399 if (urational || vrational) {
1400 if (cacheweights.IsNull()) {
1401 cacheweights = new TColStd_HArray2OfReal(1,MaxDegree + 1,
1402 1,MinDegree + 1);
1403 }
1404 else {
1405 if (cacheweights->ColLength() < MaxDegree + 1 ||
1406 cacheweights->RowLength() < MinDegree + 1) {
1407 cacheweights = new TColStd_HArray2OfReal(1,MaxDegree + 1,
1408 1,MinDegree + 1);
1409 }
1410 }
1411 }
1412
1413 BSplCLib::LocateParameter(udeg,
1414 (ufknots->Array1()),
1415 (BSplCLib::NoMults()),
1416 Uparameter,
1417 uperiodic,
1418 LocalIndex,
1419 NewParameter);
1420 ucachespanindex = LocalIndex ;
1421 if (Uparameter == ufknots->Value(LocalIndex + 1)) {
1422
1423 LocalIndex += 1 ;
1424 ucacheparameter = ufknots->Value(LocalIndex) ;
1425 if (LocalIndex == ufknots->Upper() - udeg) {
1426 //
1427 // for the last span if the parameter is outside of
1428 // the domain of the curve than use the last knot
1429 // and normalize with the last span Still set the
1430 // cachespanindex to flatknots->Upper() - deg so that
1431 // the IsCacheValid will know for sure we are extending
1432 // the Bspline
1433 //
1434
1435 ucachespanlenght = ufknots->Value(LocalIndex - 1) - ucacheparameter ;
1436 }
1437 else {
1438 ucachespanlenght = ufknots->Value(LocalIndex + 1) - ucacheparameter ;
1439 }
1440 }
1441 else {
1442 ucacheparameter = ufknots->Value(LocalIndex) ;
1443 ucachespanlenght = ufknots->Value(LocalIndex + 1) - ucacheparameter ;
1444 }
1445
1446 LocalIndex = 0 ;
1447 BSplCLib::LocateParameter(vdeg,
1448 (vfknots->Array1()),
1449 (BSplCLib::NoMults()),
1450 Vparameter,
1451 vperiodic,
1452 LocalIndex,
1453 NewParameter);
1454 vcachespanindex = LocalIndex ;
1455 if (Vparameter == vfknots->Value(LocalIndex + 1)) {
1456 LocalIndex += 1 ;
1457 vcacheparameter = vfknots->Value(LocalIndex) ;
1458 if (LocalIndex == vfknots->Upper() - vdeg) {
1459 //
1460 // for the last span if the parameter is outside of
1461 // the domain of the curve than use the last knot
1462 // and normalize with the last span Still set the
1463 // cachespanindex to flatknots->Upper() - deg so that
1464 // the IsCacheValid will know for sure we are extending
1465 // the Bspline
1466 //
1467
1468 vcachespanlenght = vfknots->Value(LocalIndex - 1) - vcacheparameter ;
1469 }
1470 else {
1471 vcachespanlenght = vfknots->Value(LocalIndex + 1) - vcacheparameter ;
1472 }
1473 }
1474 else {
1475 vcacheparameter = vfknots->Value(LocalIndex) ;
1476 vcachespanlenght = vfknots->Value(LocalIndex + 1) - vcacheparameter ;
1477 }
1478
1479 Standard_Real uparameter_11 = (2*ucacheparameter + ucachespanlenght)/2,
1480 uspanlenght_11 = ucachespanlenght/2,
1481 vparameter_11 = (2*vcacheparameter + vcachespanlenght)/2,
1482 vspanlenght_11 = vcachespanlenght/2 ;
1483 if (urational || vrational) {
1484 BSplSLib::BuildCache(uparameter_11,
1485 vparameter_11,
1486 uspanlenght_11,
1487 vspanlenght_11,
1488 uperiodic,
1489 vperiodic,
1490 udeg,
1491 vdeg,
1492 ucachespanindex,
1493 vcachespanindex,
1494 (ufknots->Array1()),
1495 (vfknots->Array1()),
1496 poles->Array2(),
1497 weights->Array2(),
1498 cachepoles->ChangeArray2(),
1499 cacheweights->ChangeArray2()) ;
1500 }
1501 else {
1502 BSplSLib::BuildCache(uparameter_11,
1503 vparameter_11,
1504 uspanlenght_11,
1505 vspanlenght_11,
1506 uperiodic,
1507 vperiodic,
1508 udeg,
1509 vdeg,
1510 ucachespanindex,
1511 vcachespanindex,
1512 (ufknots->Array1()),
1513 (vfknots->Array1()),
1514 poles->Array2(),
1515 *((TColStd_Array2OfReal*) NULL),
1516 cachepoles->ChangeArray2(),
1517 *((TColStd_Array2OfReal*) NULL)) ;
1518 }
1519 validcache = 1 ;
1520}
1521
1522//=======================================================================
1523//function : IsCacheValid
1524//purpose : function that checks for the validity of the cache of the
1525// surface
1526//=======================================================================
1527Standard_Boolean Geom_BSplineSurface::IsCacheValid
1528(const Standard_Real U,
1529 const Standard_Real V) const
1530{
1531 //Roman Lygin 26.12.08, see comments in Geom_BSplineCurve::IsCacheValid()
1532 Standard_Real aDeltaU = U - ucacheparameter;
1533 Standard_Real aDeltaV = V - vcacheparameter;
1534
1535 return ( validcache &&
1536 (aDeltaU >= 0.0e0) &&
1537 ((aDeltaU < ucachespanlenght) || (ucachespanindex == ufknots->Upper() - udeg)) &&
1538 (aDeltaV >= 0.0e0) &&
1539 ((aDeltaV < vcachespanlenght) || (vcachespanindex == vfknots->Upper() - vdeg)) );
1540}
1541
1542//=======================================================================
1543//function : SetWeight
1544//purpose :
1545//=======================================================================
1546
1547void Geom_BSplineSurface::SetWeight (const Standard_Integer UIndex,
1548 const Standard_Integer VIndex,
1549 const Standard_Real Weight)
1550{
1551 if (Weight <= gp::Resolution()) Standard_ConstructionError::Raise();
1552 TColStd_Array2OfReal & Weights = weights->ChangeArray2();
1553 if (UIndex < 1 || UIndex > Weights.ColLength() ||
1554 VIndex < 1 || VIndex > Weights.RowLength() ) {
1555 Standard_OutOfRange::Raise();
1556 }
1557 Weights (UIndex+Weights.LowerRow()-1, VIndex+Weights.LowerCol()-1) = Weight;
1558 Rational(Weights, urational, vrational);
1559 InvalidateCache();
1560}
1561
1562//=======================================================================
1563//function : SetWeightCol
1564//purpose :
1565//=======================================================================
1566
1567void Geom_BSplineSurface::SetWeightCol
1568(const Standard_Integer VIndex,
1569 const TColStd_Array1OfReal& CPoleWeights)
1570{
1571 TColStd_Array2OfReal & Weights = weights->ChangeArray2();
1572 if (VIndex < 1 || VIndex > Weights.RowLength()) {
1573 Standard_OutOfRange::Raise();
1574 }
1575 if (CPoleWeights.Lower() < 1 ||
1576 CPoleWeights.Lower() > Weights.ColLength() ||
1577 CPoleWeights.Upper() < 1 ||
1578 CPoleWeights.Upper() > Weights.ColLength() ) {
1579 Standard_ConstructionError::Raise();
1580 }
1581 Standard_Integer I = CPoleWeights.Lower();
1582 while (I <= CPoleWeights.Upper()) {
1583 if (CPoleWeights(I) <= gp::Resolution()) {
1584 Standard_ConstructionError::Raise();
1585 }
1586 Weights (I+Weights.LowerRow()-1, VIndex+Weights.LowerCol()-1) =
1587 CPoleWeights (I);
1588 I++;
1589 }
1590 // Verifie si c'est rationnel
1591 Rational(Weights, urational, vrational);
1592
1593 InvalidateCache();
1594}
1595
1596//=======================================================================
1597//function : SetWeightRow
1598//purpose :
1599//=======================================================================
1600
1601void Geom_BSplineSurface::SetWeightRow
1602(const Standard_Integer UIndex,
1603 const TColStd_Array1OfReal& CPoleWeights)
1604{
1605 TColStd_Array2OfReal & Weights = weights->ChangeArray2();
1606 if (UIndex < 1 || UIndex > Weights.ColLength()) {
1607 Standard_OutOfRange::Raise();
1608 }
1609 if (CPoleWeights.Lower() < 1 ||
1610 CPoleWeights.Lower() > Weights.RowLength() ||
1611 CPoleWeights.Upper() < 1 ||
1612 CPoleWeights.Upper() > Weights.RowLength() ) {
1613
1614 Standard_ConstructionError::Raise();
1615 }
1616 Standard_Integer I = CPoleWeights.Lower();
1617
1618 while (I <= CPoleWeights.Upper()) {
1619 if (CPoleWeights(I)<=gp::Resolution()) {
1620 Standard_ConstructionError::Raise();
1621 }
1622 Weights (UIndex+Weights.LowerRow()-1, I+Weights.LowerCol()-1) =
1623 CPoleWeights (I);
1624 I++;
1625 }
1626 // Verifie si c'est rationnel
1627 Rational(Weights, urational, vrational);
1628 InvalidateCache();
1629}
1630