1 // Created on: 1993-03-09
3 // Copyright (c) 1993-1999 Matra Datavision
4 // Copyright (c) 1999-2014 OPEN CASCADE SAS
6 // This file is part of Open CASCADE Technology software library.
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.
14 // Alternatively, this file may be used under the terms of Open CASCADE
15 // commercial license or contractual agreement.
17 // 14-Mar-96 : xab portage hp
18 // pmn : 28-Jun-96 Distinction entre la continuite en U et V (bug PRO4625)
19 // pmn : 07-Jan-97 Centralisation des verif rational (PRO6834)
20 // et ajout des InvalideCache() dans les SetWeight*(PRO6833)
21 // RBD : 15-10-98 ; Le cache est maintenant calcule sur [-1,1] (pro15537).
22 // jct : 19-01-99 ; permutation de urational et vrational dans Rational.
23 #define No_Standard_OutOfRange
25 #include <Geom_BSplineSurface.ixx>
28 #include <BSplCLib.hxx>
29 #include <BSplSLib.hxx>
31 #include <Standard_ConstructionError.hxx>
32 #include <Standard_NotImplemented.hxx>
33 #include <Standard_OutOfRange.hxx>
34 #include <Precision.hxx>
36 //=======================================================================
37 //function : CheckSurfaceData
38 //purpose : Internal use only.
39 //=======================================================================
41 static void CheckSurfaceData
42 (const TColgp_Array2OfPnt& SPoles,
43 const TColStd_Array1OfReal& SUKnots,
44 const TColStd_Array1OfReal& SVKnots,
45 const TColStd_Array1OfInteger& SUMults,
46 const TColStd_Array1OfInteger& SVMults,
47 const Standard_Integer UDegree,
48 const Standard_Integer VDegree,
49 const Standard_Boolean UPeriodic,
50 const Standard_Boolean VPeriodic)
52 if (UDegree < 1 || UDegree > Geom_BSplineSurface::MaxDegree () ||
53 VDegree < 1 || VDegree > Geom_BSplineSurface::MaxDegree ()) {
54 Standard_ConstructionError::Raise("Geom_BSplineSurface");
56 if (SPoles.ColLength () < 2 || SPoles.RowLength () < 2) {
57 Standard_ConstructionError::Raise("Geom_BSplineSurface");
60 if (SUKnots.Length() != SUMults.Length() ||
61 SVKnots.Length() != SVMults.Length()) {
62 Standard_ConstructionError::Raise("Geom_BSplineSurface");
66 for (i = SUKnots.Lower(); i < SUKnots.Upper(); i++) {
67 if (SUKnots(i+1) - SUKnots(i) <= Epsilon(Abs(SUKnots(i)))) {
68 Standard_ConstructionError::Raise("Geom_BSplineSurface");
72 for (i = SVKnots.Lower(); i < SVKnots.Upper(); i++) {
73 if (SVKnots(i+1) - SVKnots(i) <= Epsilon(Abs(SVKnots(i)))) {
74 Standard_ConstructionError::Raise("Geom_BSplineSurface");
78 if (SPoles.ColLength() != BSplCLib::NbPoles(UDegree,UPeriodic,SUMults))
79 Standard_ConstructionError::Raise("Geom_BSplineSurface");
81 if (SPoles.RowLength() != BSplCLib::NbPoles(VDegree,VPeriodic,SVMults))
82 Standard_ConstructionError::Raise("Geom_BSplineSurface");
85 //=======================================================================
87 //purpose : Internal use only.
88 //=======================================================================
90 static void Rational(const TColStd_Array2OfReal& Weights,
91 Standard_Boolean& Urational,
92 Standard_Boolean& Vrational)
95 J = Weights.LowerCol ();
96 Vrational = Standard_False;
97 while (!Vrational && J <= Weights.UpperCol()) {
98 I = Weights.LowerRow();
99 while (!Vrational && I <= Weights.UpperRow() - 1) {
100 Vrational = (Abs(Weights (I, J) - Weights (I+1, J))
101 > Epsilon (Abs(Weights (I, J))));
107 I = Weights.LowerRow ();
108 Urational = Standard_False;
109 while (!Urational && I <= Weights.UpperRow()) {
110 J = Weights.LowerCol();
111 while (!Urational && J <= Weights.UpperCol() - 1) {
112 Urational = (Abs(Weights (I, J) - Weights (I, J+1))
113 > Epsilon (Abs(Weights (I, J))));
120 //=======================================================================
123 //=======================================================================
125 Handle(Geom_Geometry) Geom_BSplineSurface::Copy () const
127 Handle(Geom_BSplineSurface) S;
128 if (urational || vrational)
129 S = new Geom_BSplineSurface (poles->Array2() , weights->Array2(),
130 uknots->Array1(), vknots->Array1(),
131 umults->Array1(), vmults->Array1(),
133 uperiodic, vperiodic);
135 S = new Geom_BSplineSurface (poles->Array2(),
136 uknots->Array1(), vknots->Array1(),
137 umults->Array1(), vmults->Array1(),
139 uperiodic, vperiodic);
143 //=======================================================================
144 //function : Geom_BSplineSurface
146 //=======================================================================
148 Geom_BSplineSurface::Geom_BSplineSurface
149 (const TColgp_Array2OfPnt& Poles,
150 const TColStd_Array1OfReal& UKnots,
151 const TColStd_Array1OfReal& VKnots,
152 const TColStd_Array1OfInteger& UMults,
153 const TColStd_Array1OfInteger& VMults,
154 const Standard_Integer UDegree,
155 const Standard_Integer VDegree,
156 const Standard_Boolean UPeriodic,
157 const Standard_Boolean VPeriodic
159 urational(Standard_False),
160 vrational(Standard_False),
161 uperiodic(UPeriodic),
162 vperiodic(VPeriodic),
171 CheckSurfaceData(Poles,
175 UPeriodic, VPeriodic);
179 poles = new TColgp_HArray2OfPnt(1,Poles.ColLength(),
180 1,Poles.RowLength());
181 poles->ChangeArray2() = Poles;
183 weights = new TColStd_HArray2OfReal (1,Poles.ColLength(),
184 1,Poles.RowLength(), 1.0);
186 uknots = new TColStd_HArray1OfReal (1,UKnots.Length());
187 uknots->ChangeArray1() = UKnots;
189 umults = new TColStd_HArray1OfInteger (1,UMults.Length());
190 umults->ChangeArray1() = UMults;
192 vknots = new TColStd_HArray1OfReal (1,VKnots.Length());
193 vknots->ChangeArray1() = VKnots;
195 vmults = new TColStd_HArray1OfInteger (1,VMults.Length());
196 vmults->ChangeArray1() = VMults;
202 //=======================================================================
203 //function : Geom_BSplineSurface
205 //=======================================================================
207 Geom_BSplineSurface::Geom_BSplineSurface
208 (const TColgp_Array2OfPnt& Poles,
209 const TColStd_Array2OfReal& Weights,
210 const TColStd_Array1OfReal& UKnots,
211 const TColStd_Array1OfReal& VKnots,
212 const TColStd_Array1OfInteger& UMults,
213 const TColStd_Array1OfInteger& VMults,
214 const Standard_Integer UDegree,
215 const Standard_Integer VDegree,
216 const Standard_Boolean UPeriodic,
217 const Standard_Boolean VPeriodic) :
218 urational(Standard_False),
219 vrational(Standard_False),
220 uperiodic(UPeriodic),
221 vperiodic(VPeriodic),
228 if (Weights.ColLength() != Poles.ColLength())
229 Standard_ConstructionError::Raise("Geom_BSplineSurface");
231 if (Weights.RowLength() != Poles.RowLength())
232 Standard_ConstructionError::Raise("Geom_BSplineSurface");
234 Standard_Integer i,j;
235 for (i = Weights.LowerRow(); i <= Weights.UpperRow(); i++) {
236 for (j = Weights.LowerCol(); j <= Weights.UpperCol(); j++) {
237 if (Weights(i,j) <= gp::Resolution())
238 Standard_ConstructionError::Raise("Geom_BSplineSurface");
242 // check really rational
244 Rational(Weights, urational, vrational);
248 CheckSurfaceData(Poles,
252 UPeriodic, VPeriodic);
256 poles = new TColgp_HArray2OfPnt(1,Poles.ColLength(),
257 1,Poles.RowLength());
258 poles->ChangeArray2() = Poles;
260 weights = new TColStd_HArray2OfReal (1,Poles.ColLength(),
261 1,Poles.RowLength());
262 weights->ChangeArray2() = Weights;
264 uknots = new TColStd_HArray1OfReal (1,UKnots.Length());
265 uknots->ChangeArray1() = UKnots;
267 umults = new TColStd_HArray1OfInteger (1,UMults.Length());
268 umults->ChangeArray1() = UMults;
270 vknots = new TColStd_HArray1OfReal (1,VKnots.Length());
271 vknots->ChangeArray1() = VKnots;
273 vmults = new TColStd_HArray1OfInteger (1,VMults.Length());
274 vmults->ChangeArray1() = VMults;
280 //=======================================================================
281 //function : ExchangeUV
283 //=======================================================================
285 void Geom_BSplineSurface::ExchangeUV ()
287 Standard_Integer LC = poles->LowerCol();
288 Standard_Integer UC = poles->UpperCol();
289 Standard_Integer LR = poles->LowerRow();
290 Standard_Integer UR = poles->UpperRow();
292 Handle(TColgp_HArray2OfPnt) npoles =
293 new TColgp_HArray2OfPnt (LC, UC, LR, UR);
294 Handle(TColStd_HArray2OfReal) nweights =
295 new TColStd_HArray2OfReal (LC, UC, LR, UR);
297 const TColgp_Array2OfPnt & spoles = poles->Array2();
298 const TColStd_Array2OfReal & sweights = weights->Array2();
300 TColgp_Array2OfPnt& snpoles = npoles->ChangeArray2();
301 TColStd_Array2OfReal& snweights = nweights->ChangeArray2();
303 Standard_Integer i, j;
304 for (i = LC; i <= UC; i++) {
305 for (j = LR; j <= UR; j++) {
306 snpoles (i,j) = spoles (j,i);
307 snweights (i,j) = sweights (j,i);
314 Standard_Boolean temp = urational;
315 urational = vrational;
319 uperiodic = vperiodic;
322 Standard_Integer tempdeg = udeg;
327 Handle(TColStd_HArray1OfReal) tempknots = uknots;
331 Handle(TColStd_HArray1OfInteger) tempmults = umults;
339 //=======================================================================
340 //function : IncreaseDegree
342 //=======================================================================
344 void Geom_BSplineSurface::IncreaseDegree (const Standard_Integer UDegree,
345 const Standard_Integer VDegree)
347 if (UDegree != udeg) {
348 if ( UDegree < udeg || UDegree > Geom_BSplineSurface::MaxDegree())
349 Standard_ConstructionError::Raise();
351 Standard_Integer FromK1 = FirstUKnotIndex();
352 Standard_Integer ToK2 = LastUKnotIndex();
354 Standard_Integer Step = UDegree - udeg;
356 Handle(TColgp_HArray2OfPnt) npoles = new
357 TColgp_HArray2OfPnt( 1, poles->ColLength() + Step * (ToK2 - FromK1),
358 1, poles->RowLength());
360 Standard_Integer nbknots = BSplCLib::IncreaseDegreeCountKnots
361 (udeg,UDegree,uperiodic,umults->Array1());
363 Handle(TColStd_HArray1OfReal) nknots =
364 new TColStd_HArray1OfReal(1,nbknots);
366 Handle(TColStd_HArray1OfInteger) nmults =
367 new TColStd_HArray1OfInteger(1,nbknots);
369 Handle(TColStd_HArray2OfReal) nweights
370 = new TColStd_HArray2OfReal(1,npoles->ColLength(),
371 1,npoles->RowLength(), 1.);
373 if (urational || vrational) {
375 BSplSLib::IncreaseDegree
376 (Standard_True, udeg, UDegree, uperiodic,
377 poles->Array2(),weights->Array2(),
378 uknots->Array1(),umults->Array1(),
379 npoles->ChangeArray2(),nweights->ChangeArray2(),
380 nknots->ChangeArray1(),nmults->ChangeArray1());
384 BSplSLib::IncreaseDegree
385 (Standard_True, udeg, UDegree, uperiodic,
386 poles->Array2(),BSplSLib::NoWeights(),
387 uknots->Array1(),umults->Array1(),
388 npoles->ChangeArray2(),*((TColStd_Array2OfReal*) NULL),
389 nknots->ChangeArray1(),nmults->ChangeArray1());
399 if (VDegree != vdeg) {
400 if ( VDegree < vdeg || VDegree > Geom_BSplineSurface::MaxDegree())
401 Standard_ConstructionError::Raise();
403 Standard_Integer FromK1 = FirstVKnotIndex();
404 Standard_Integer ToK2 = LastVKnotIndex();
406 Standard_Integer Step = VDegree - vdeg;
408 Handle(TColgp_HArray2OfPnt) npoles = new
409 TColgp_HArray2OfPnt( 1, poles->ColLength(),
410 1, poles->RowLength() + Step * (ToK2 - FromK1));
412 Standard_Integer nbknots = BSplCLib::IncreaseDegreeCountKnots
413 (vdeg,VDegree,vperiodic,vmults->Array1());
415 Handle(TColStd_HArray1OfReal) nknots =
416 new TColStd_HArray1OfReal(1,nbknots);
418 Handle(TColStd_HArray1OfInteger) nmults =
419 new TColStd_HArray1OfInteger(1,nbknots);
421 Handle(TColStd_HArray2OfReal) nweights
422 = new TColStd_HArray2OfReal(1,npoles->ColLength(),
423 1,npoles->RowLength(), 1.);
425 if (urational || vrational) {
427 BSplSLib::IncreaseDegree
428 (Standard_False, vdeg, VDegree, vperiodic,
429 poles->Array2(),weights->Array2(),
430 vknots->Array1(),vmults->Array1(),
431 npoles->ChangeArray2(),nweights->ChangeArray2(),
432 nknots->ChangeArray1(),nmults->ChangeArray1());
436 BSplSLib::IncreaseDegree
437 (Standard_False, vdeg, VDegree, vperiodic,
438 poles->Array2(),BSplSLib::NoWeights(),
439 vknots->Array1(),vmults->Array1(),
440 npoles->ChangeArray2(),*((TColStd_Array2OfReal*) NULL),
441 nknots->ChangeArray1(),nmults->ChangeArray1());
452 //=======================================================================
453 //function : IncreaseUMultiplicity
455 //=======================================================================
457 void Geom_BSplineSurface::IncreaseUMultiplicity
458 (const Standard_Integer UIndex,
459 const Standard_Integer M)
461 TColStd_Array1OfReal k(1,1);
462 k(1) = uknots->Value(UIndex);
463 TColStd_Array1OfInteger m(1,1);
464 m(1) = M - umults->Value(UIndex);
465 InsertUKnots(k,m,Epsilon(1.),Standard_True);
468 //=======================================================================
469 //function : IncreaseUMultiplicity
471 //=======================================================================
473 void Geom_BSplineSurface::IncreaseUMultiplicity
474 (const Standard_Integer FromI1,
475 const Standard_Integer ToI2,
476 const Standard_Integer M)
478 Handle(TColStd_HArray1OfReal) tk = uknots;
479 TColStd_Array1OfReal k((uknots->Array1())(FromI1),FromI1,ToI2);
480 TColStd_Array1OfInteger m(FromI1, ToI2);
481 for (Standard_Integer i = FromI1; i <= ToI2; i++)
482 m(i) = M - umults->Value(i);
483 InsertUKnots(k,m,Epsilon(1.),Standard_True);
486 //=======================================================================
487 //function : IncreaseVMultiplicity
489 //=======================================================================
491 void Geom_BSplineSurface::IncreaseVMultiplicity
492 (const Standard_Integer VIndex,
493 const Standard_Integer M)
495 TColStd_Array1OfReal k(1,1);
496 k(1) = vknots->Value(VIndex);
497 TColStd_Array1OfInteger m(1,1);
498 m(1) = M - vmults->Value(VIndex);
499 InsertVKnots(k,m,Epsilon(1.),Standard_True);
502 //=======================================================================
503 //function : IncreaseVMultiplicity
505 //=======================================================================
507 void Geom_BSplineSurface::IncreaseVMultiplicity
508 (const Standard_Integer FromI1,
509 const Standard_Integer ToI2,
510 const Standard_Integer M)
512 Handle(TColStd_HArray1OfReal) tk = vknots;
513 TColStd_Array1OfReal k((vknots->Array1())(FromI1),FromI1,ToI2);
514 TColStd_Array1OfInteger m(FromI1,ToI2);
515 for (Standard_Integer i = FromI1; i <= ToI2; i++)
516 m(i) = M - vmults->Value(i);
517 InsertVKnots(k,m,Epsilon(1.),Standard_True);
520 //=======================================================================
523 //=======================================================================
525 void Geom_BSplineSurface::Segment(const Standard_Real U1,
526 const Standard_Real U2,
527 const Standard_Real V1,
528 const Standard_Real V2)
531 Standard_DomainError_Raise_if ( (U2 < U1) || (V2 < V1),
532 "Geom_BSplineCurve::Segment");
533 Standard_Real deltaU = Max(Abs(U2),Abs(U1));
534 Standard_Real EpsU = Epsilon(deltaU);
537 Standard_Real deltaV = Max(Abs(V2),Abs(V1));
538 Standard_Real EpsV = Epsilon(deltaV);
541 Standard_Real NewU1, NewU2, NewV1, NewV2;
543 Standard_Integer indexU, indexV;
545 // inserting the UKnots
546 TColStd_Array1OfReal UKnots(1,2);
547 TColStd_Array1OfInteger UMults(1,2);
550 BSplCLib::LocateParameter(udeg,uknots->Array1(),umults->Array1(),
551 U1,uperiodic,uknots->Lower(),uknots->Upper(),
554 BSplCLib::LocateParameter(udeg,uknots->Array1(),umults->Array1(),
555 U2,uperiodic,uknots->Lower(),uknots->Upper(),
557 UKnots( 1) = Min( NewU1, NewU2);
558 UKnots( 2) = Max( NewU1, NewU2);
559 UMults( 1) = UMults( 2) = udeg;
560 InsertUKnots( UKnots, UMults, EpsU);
562 // Inserting the VKnots
563 TColStd_Array1OfReal VKnots(1,2);
564 TColStd_Array1OfInteger VMults(1,2);
567 BSplCLib::LocateParameter(vdeg,vknots->Array1(),vmults->Array1(),
568 V1,vperiodic,vknots->Lower(),vknots->Upper(),
571 BSplCLib::LocateParameter(vdeg,vknots->Array1(),vmults->Array1(),
572 V2,vperiodic,vknots->Lower(),vknots->Upper(),
574 VKnots( 1) = Min( NewV1, NewV2);
575 VKnots( 2) = Max( NewV1, NewV2);
576 VMults( 1) = VMults( 2) = vdeg;
577 InsertVKnots( VKnots, VMults, EpsV);
580 if (uperiodic) { // set the origine at NewU1
581 Standard_Integer index = 0;
582 BSplCLib::LocateParameter(udeg,uknots->Array1(),umults->Array1(),
583 U1,uperiodic,uknots->Lower(),uknots->Upper(),
585 if ( Abs(uknots->Value(index+1)-U) <= EpsU)
591 // compute index1 and index2 to set the new knots and mults
592 Standard_Integer index1U = 0, index2U = 0;
593 Standard_Integer FromU1 = uknots->Lower();
594 Standard_Integer ToU2 = uknots->Upper();
595 BSplCLib::LocateParameter(udeg,uknots->Array1(),umults->Array1(),
596 NewU1,uperiodic,FromU1,ToU2,index1U,U);
597 BSplCLib::LocateParameter(udeg,uknots->Array1(),umults->Array1(),
598 NewU1 + deltaU,uperiodic,FromU1,ToU2,index2U,U);
599 if ( Abs(uknots->Value(index2U+1)-U) <= EpsU)
602 Standard_Integer nbuknots = index2U - index1U + 1;
604 Handle(TColStd_HArray1OfReal)
605 nuknots = new TColStd_HArray1OfReal(1,nbuknots);
606 Handle(TColStd_HArray1OfInteger)
607 numults = new TColStd_HArray1OfInteger(1,nbuknots);
609 Standard_Integer i , k = 1;
610 for ( i = index1U; i<= index2U; i++) {
611 nuknots->SetValue(k, uknots->Value(i));
612 numults->SetValue(k, umults->Value(i));
615 numults->SetValue( 1, udeg + 1);
616 numults->SetValue(nbuknots, udeg + 1);
619 if (vperiodic) { // set the origine at NewV1
620 Standard_Integer index = 0;
621 BSplCLib::LocateParameter(vdeg,vknots->Array1(),vmults->Array1(),
622 V1,vperiodic,vknots->Lower(),vknots->Upper(),
624 if ( Abs(vknots->Value(index+1)-V) <= EpsV)
630 // compute index1 and index2 to set the new knots and mults
631 Standard_Integer index1V = 0, index2V = 0;
632 Standard_Integer FromV1 = vknots->Lower();
633 Standard_Integer ToV2 = vknots->Upper();
634 BSplCLib::LocateParameter(vdeg,vknots->Array1(),vmults->Array1(),
635 NewV1,vperiodic,FromV1,ToV2,index1V,V);
636 BSplCLib::LocateParameter(vdeg,vknots->Array1(),vmults->Array1(),
637 NewV1 + deltaV,vperiodic,FromV1,ToV2,index2V,V);
638 if ( Abs(vknots->Value(index2V+1)-V) <= EpsV)
641 Standard_Integer nbvknots = index2V - index1V + 1;
643 Handle(TColStd_HArray1OfReal)
644 nvknots = new TColStd_HArray1OfReal(1,nbvknots);
645 Handle(TColStd_HArray1OfInteger)
646 nvmults = new TColStd_HArray1OfInteger(1,nbvknots);
649 for ( i = index1V; i<= index2V; i++) {
650 nvknots->SetValue(k, vknots->Value(i));
651 nvmults->SetValue(k, vmults->Value(i));
654 nvmults->SetValue( 1, vdeg + 1);
655 nvmults->SetValue(nbvknots, vdeg + 1);
658 // compute index1 and index2 to set the new poles and weights
659 Standard_Integer pindex1U
660 = BSplCLib::PoleIndex(udeg,index1U,uperiodic,umults->Array1());
661 Standard_Integer pindex2U
662 = BSplCLib::PoleIndex(udeg,index2U,uperiodic,umults->Array1());
665 pindex2U = Min( pindex2U+1, poles->ColLength());
667 Standard_Integer nbupoles = pindex2U - pindex1U + 1;
669 // compute index1 and index2 to set the new poles and weights
670 Standard_Integer pindex1V
671 = BSplCLib::PoleIndex(vdeg,index1V,vperiodic,vmults->Array1());
672 Standard_Integer pindex2V
673 = BSplCLib::PoleIndex(vdeg,index2V,vperiodic,vmults->Array1());
676 pindex2V = Min( pindex2V+1, poles->RowLength());
678 Standard_Integer nbvpoles = pindex2V - pindex1V + 1;
681 Handle(TColStd_HArray2OfReal) nweights;
683 Handle(TColgp_HArray2OfPnt)
684 npoles = new TColgp_HArray2OfPnt(1,nbupoles,1,nbvpoles);
687 Standard_Integer j, l;
688 if ( urational || vrational) {
689 nweights = new TColStd_HArray2OfReal( 1,nbupoles,1,nbvpoles);
690 for ( i = pindex1U; i <= pindex2U; i++) {
692 for ( j = pindex1V; j <= pindex2V; j++) {
693 npoles->SetValue(k,l, poles->Value(i,j));
694 nweights->SetValue(k,l, weights->Value(i,j));
701 for ( i = pindex1U; i <= pindex2U; i++) {
703 for ( j = pindex1V; j <= pindex2V; j++) {
704 npoles->SetValue(k,l, poles->Value(i,j));
716 if ( urational || vrational)
719 weights = new TColStd_HArray2OfReal (1,poles->ColLength(),
720 1,poles->RowLength(), 1.0);
728 //=======================================================================
729 //function : CheckAndSegment
731 //=======================================================================
733 void Geom_BSplineSurface::CheckAndSegment(const Standard_Real U1,
734 const Standard_Real U2,
735 const Standard_Real V1,
736 const Standard_Real V2)
739 Standard_DomainError_Raise_if ( (U2 < U1) || (V2 < V1),
740 "Geom_BSplineCurve::Segment");
741 Standard_Real deltaU = Max(Abs(U2),Abs(U1));
742 Standard_Real EpsU = Epsilon(deltaU);
745 Standard_Real deltaV = Max(Abs(V2),Abs(V1));
746 Standard_Real EpsV = Epsilon(deltaV);
749 Standard_Real NewU1, NewU2, NewV1, NewV2;
751 Standard_Integer indexU, indexV;
753 Standard_Boolean segment_in_U = Standard_True;
754 Standard_Boolean segment_in_V = Standard_True;
755 segment_in_U = ( Abs(U1 - uknots->Value(uknots->Lower())) > EpsU )
756 || ( Abs(U2 - uknots->Value(uknots->Upper())) > EpsU );
757 segment_in_V = ( Abs(V1 - vknots->Value(vknots->Lower())) > EpsV )
758 || ( Abs(V2 - vknots->Value(vknots->Upper())) > EpsV );
761 BSplCLib::LocateParameter(udeg,uknots->Array1(),umults->Array1(),
762 U1,uperiodic,uknots->Lower(),uknots->Upper(),
765 BSplCLib::LocateParameter(udeg,uknots->Array1(),umults->Array1(),
766 U2,uperiodic,uknots->Lower(),uknots->Upper(),
769 // inserting the UKnots
770 TColStd_Array1OfReal UKnots(1,2);
771 TColStd_Array1OfInteger UMults(1,2);
772 UKnots( 1) = Min( NewU1, NewU2);
773 UKnots( 2) = Max( NewU1, NewU2);
774 UMults( 1) = UMults( 2) = udeg;
776 InsertUKnots( UKnots, UMults, EpsU);
780 BSplCLib::LocateParameter(vdeg,vknots->Array1(),vmults->Array1(),
781 V1,vperiodic,vknots->Lower(),vknots->Upper(),
784 BSplCLib::LocateParameter(vdeg,vknots->Array1(),vmults->Array1(),
785 V2,vperiodic,vknots->Lower(),vknots->Upper(),
788 // Inserting the VKnots
789 TColStd_Array1OfReal VKnots(1,2);
790 TColStd_Array1OfInteger VMults(1,2);
792 VKnots( 1) = Min( NewV1, NewV2);
793 VKnots( 2) = Max( NewV1, NewV2);
794 VMults( 1) = VMults( 2) = vdeg;
795 InsertVKnots( VKnots, VMults, EpsV);
798 if (uperiodic && segment_in_U) { // set the origine at NewU1
799 Standard_Integer index = 0;
800 BSplCLib::LocateParameter(udeg,uknots->Array1(),umults->Array1(),
801 U1,uperiodic,uknots->Lower(),uknots->Upper(),
803 if ( Abs(uknots->Value(index+1)-U) <= EpsU)
809 // compute index1 and index2 to set the new knots and mults
810 Standard_Integer index1U = 0, index2U = 0;
811 Standard_Integer FromU1 = uknots->Lower();
812 Standard_Integer ToU2 = uknots->Upper();
813 BSplCLib::LocateParameter(udeg,uknots->Array1(),umults->Array1(),
814 NewU1,uperiodic,FromU1,ToU2,index1U,U);
815 BSplCLib::LocateParameter(udeg,uknots->Array1(),umults->Array1(),
816 NewU1 + deltaU,uperiodic,FromU1,ToU2,index2U,U);
817 if ( Abs(uknots->Value(index2U+1)-U) <= EpsU)
820 Standard_Integer nbuknots = index2U - index1U + 1;
822 Handle(TColStd_HArray1OfReal)
823 nuknots = new TColStd_HArray1OfReal(1,nbuknots);
824 Handle(TColStd_HArray1OfInteger)
825 numults = new TColStd_HArray1OfInteger(1,nbuknots);
827 Standard_Integer i , k = 1;
828 for ( i = index1U; i<= index2U; i++) {
829 nuknots->SetValue(k, uknots->Value(i));
830 numults->SetValue(k, umults->Value(i));
834 numults->SetValue( 1, udeg + 1);
835 numults->SetValue(nbuknots, udeg + 1);
838 if (vperiodic&& segment_in_V) { // set the origine at NewV1
839 Standard_Integer index = 0;
840 BSplCLib::LocateParameter(vdeg,vknots->Array1(),vmults->Array1(),
841 V1,vperiodic,vknots->Lower(),vknots->Upper(),
843 if ( Abs(vknots->Value(index+1)-V) <= EpsV)
849 // compute index1 and index2 to set the new knots and mults
850 Standard_Integer index1V = 0, index2V = 0;
851 Standard_Integer FromV1 = vknots->Lower();
852 Standard_Integer ToV2 = vknots->Upper();
853 BSplCLib::LocateParameter(vdeg,vknots->Array1(),vmults->Array1(),
854 NewV1,vperiodic,FromV1,ToV2,index1V,V);
855 BSplCLib::LocateParameter(vdeg,vknots->Array1(),vmults->Array1(),
856 NewV1 + deltaV,vperiodic,FromV1,ToV2,index2V,V);
857 if ( Abs(vknots->Value(index2V+1)-V) <= EpsV)
860 Standard_Integer nbvknots = index2V - index1V + 1;
862 Handle(TColStd_HArray1OfReal)
863 nvknots = new TColStd_HArray1OfReal(1,nbvknots);
864 Handle(TColStd_HArray1OfInteger)
865 nvmults = new TColStd_HArray1OfInteger(1,nbvknots);
868 for ( i = index1V; i<= index2V; i++) {
869 nvknots->SetValue(k, vknots->Value(i));
870 nvmults->SetValue(k, vmults->Value(i));
874 nvmults->SetValue( 1, vdeg + 1);
875 nvmults->SetValue(nbvknots, vdeg + 1);
878 // compute index1 and index2 to set the new poles and weights
879 Standard_Integer pindex1U
880 = BSplCLib::PoleIndex(udeg,index1U,uperiodic,umults->Array1());
881 Standard_Integer pindex2U
882 = BSplCLib::PoleIndex(udeg,index2U,uperiodic,umults->Array1());
885 pindex2U = Min( pindex2U+1, poles->ColLength());
887 Standard_Integer nbupoles = pindex2U - pindex1U + 1;
889 // compute index1 and index2 to set the new poles and weights
890 Standard_Integer pindex1V
891 = BSplCLib::PoleIndex(vdeg,index1V,vperiodic,vmults->Array1());
892 Standard_Integer pindex2V
893 = BSplCLib::PoleIndex(vdeg,index2V,vperiodic,vmults->Array1());
896 pindex2V = Min( pindex2V+1, poles->RowLength());
898 Standard_Integer nbvpoles = pindex2V - pindex1V + 1;
901 Handle(TColStd_HArray2OfReal) nweights;
903 Handle(TColgp_HArray2OfPnt)
904 npoles = new TColgp_HArray2OfPnt(1,nbupoles,1,nbvpoles);
907 Standard_Integer j, l;
908 if ( urational || vrational) {
909 nweights = new TColStd_HArray2OfReal( 1,nbupoles,1,nbvpoles);
910 for ( i = pindex1U; i <= pindex2U; i++) {
912 for ( j = pindex1V; j <= pindex2V; j++) {
913 npoles->SetValue(k,l, poles->Value(i,j));
914 nweights->SetValue(k,l, weights->Value(i,j));
921 for ( i = pindex1U; i <= pindex2U; i++) {
923 for ( j = pindex1V; j <= pindex2V; j++) {
924 npoles->SetValue(k,l, poles->Value(i,j));
936 if ( urational || vrational)
939 weights = new TColStd_HArray2OfReal (1,poles->ColLength(),
940 1,poles->RowLength(), 1.0);
948 //=======================================================================
949 //function : SetUKnot
951 //=======================================================================
953 void Geom_BSplineSurface::SetUKnot
954 (const Standard_Integer UIndex,
955 const Standard_Real K )
957 if (UIndex < 1 || UIndex > uknots->Length()) Standard_OutOfRange::Raise();
959 Standard_Integer NewIndex = UIndex;
960 Standard_Real DU = Abs(Epsilon (K));
962 if (K >= uknots->Value (2) - DU) Standard_ConstructionError::Raise();
964 else if (UIndex == uknots->Length()) {
965 if (K <= uknots->Value (uknots->Length()-1) + DU) {
966 Standard_ConstructionError::Raise();
970 if (K <= uknots->Value (NewIndex-1) + DU ||
971 K >= uknots->Value (NewIndex+1) - DU ) {
972 Standard_ConstructionError::Raise();
976 if (K != uknots->Value (NewIndex)) {
977 uknots->SetValue (NewIndex, K);
983 //=======================================================================
984 //function : SetUKnots
986 //=======================================================================
988 void Geom_BSplineSurface::SetUKnots (const TColStd_Array1OfReal& UK) {
990 Standard_Integer Lower = UK.Lower();
991 Standard_Integer Upper = UK.Upper();
992 if (Lower < 1 || Lower > uknots->Length() ||
993 Upper < 1 || Upper > uknots->Length() ) {
994 Standard_OutOfRange::Raise();
997 if (Abs (UK (Lower) - uknots->Value (Lower-1)) <= gp::Resolution()) {
998 Standard_ConstructionError::Raise();
1001 if (Upper < uknots->Length ()) {
1002 if (Abs (UK (Upper) - uknots->Value (Upper+1)) <= gp::Resolution()) {
1003 Standard_ConstructionError::Raise();
1006 Standard_Real K1 = UK (Lower);
1007 for (Standard_Integer i = Lower; i <= Upper; i++) {
1008 uknots->SetValue (i, UK(i));
1010 if (Abs (UK(i) - K1) <= gp::Resolution()) {
1011 Standard_ConstructionError::Raise();
1021 //=======================================================================
1022 //function : SetUKnot
1024 //=======================================================================
1026 void Geom_BSplineSurface::SetUKnot
1027 (const Standard_Integer UIndex,
1028 const Standard_Real K,
1029 const Standard_Integer M)
1031 IncreaseUMultiplicity (UIndex, M);
1032 SetUKnot (UIndex, K);
1035 //=======================================================================
1036 //function : SetVKnot
1038 //=======================================================================
1040 void Geom_BSplineSurface::SetVKnot
1041 (const Standard_Integer VIndex,
1042 const Standard_Real K)
1044 if (VIndex < 1 || VIndex > vknots->Length()) Standard_OutOfRange::Raise();
1045 Standard_Integer NewIndex = VIndex + vknots->Lower() - 1;
1046 Standard_Real DV = Abs(Epsilon (K));
1048 if (K >= vknots->Value (2) - DV) {
1049 Standard_ConstructionError::Raise();
1052 else if (VIndex == vknots->Length()) {
1053 if (K <= vknots->Value (vknots->Length()-1) + DV) {
1054 Standard_ConstructionError::Raise();
1058 if (K <= vknots->Value (NewIndex-1) + DV ||
1059 K >= vknots->Value (NewIndex+1) - DV ) {
1060 Standard_ConstructionError::Raise();
1068 //=======================================================================
1069 //function : SetVKnots
1071 //=======================================================================
1073 void Geom_BSplineSurface::SetVKnots (const TColStd_Array1OfReal& VK) {
1075 Standard_Integer Lower = VK.Lower();
1076 Standard_Integer Upper = VK.Upper();
1077 if (Lower < 1 || Lower > vknots->Length() ||
1078 Upper < 1 || Upper > vknots->Length() ) {
1079 Standard_OutOfRange::Raise();
1082 if (Abs (VK (Lower) - vknots->Value (Lower-1)) <= gp::Resolution()) {
1083 Standard_ConstructionError::Raise();
1086 if (Upper < vknots->Length ()) {
1087 if (Abs (VK (Upper) - vknots->Value (Upper+1)) <= gp::Resolution()) {
1088 Standard_ConstructionError::Raise();
1091 Standard_Real K1 = VK (Lower);
1092 for (Standard_Integer i = Lower; i <= Upper; i++) {
1093 vknots->SetValue (i, VK(i));
1095 if (Abs (VK(i) - K1) <= gp::Resolution()) {
1096 Standard_ConstructionError::Raise();
1106 //=======================================================================
1107 //function : SetVKnot
1109 //=======================================================================
1111 void Geom_BSplineSurface::SetVKnot
1112 (const Standard_Integer VIndex,
1113 const Standard_Real K,
1114 const Standard_Integer M)
1116 IncreaseVMultiplicity (VIndex, M);
1117 SetVKnot (VIndex, K);
1120 //=======================================================================
1121 //function : InsertUKnot
1123 //=======================================================================
1125 void Geom_BSplineSurface::InsertUKnot
1126 (const Standard_Real U,
1127 const Standard_Integer M,
1128 const Standard_Real ParametricTolerance,
1129 const Standard_Boolean Add)
1131 TColStd_Array1OfReal k(1,1);
1133 TColStd_Array1OfInteger m(1,1);
1135 InsertUKnots(k,m,ParametricTolerance,Add);
1138 //=======================================================================
1139 //function : InsertVKnot
1141 //=======================================================================
1143 void Geom_BSplineSurface::InsertVKnot
1144 (const Standard_Real V,
1145 const Standard_Integer M,
1146 const Standard_Real ParametricTolerance,
1147 const Standard_Boolean Add)
1149 TColStd_Array1OfReal k(1,1);
1151 TColStd_Array1OfInteger m(1,1);
1153 InsertVKnots(k,m,ParametricTolerance,Add);
1156 //=======================================================================
1157 //function : IncrementUMultiplicity
1159 //=======================================================================
1161 void Geom_BSplineSurface::IncrementUMultiplicity
1162 (const Standard_Integer FromI1,
1163 const Standard_Integer ToI2,
1164 const Standard_Integer Step)
1166 Handle(TColStd_HArray1OfReal) tk = uknots;
1167 TColStd_Array1OfReal k( (uknots->Array1())(FromI1), FromI1, ToI2);
1168 TColStd_Array1OfInteger m( FromI1, ToI2) ;
1170 InsertUKnots( k, m, Epsilon(1.));
1173 //=======================================================================
1174 //function : IncrementVMultiplicity
1176 //=======================================================================
1178 void Geom_BSplineSurface::IncrementVMultiplicity
1179 (const Standard_Integer FromI1,
1180 const Standard_Integer ToI2,
1181 const Standard_Integer Step)
1183 Handle(TColStd_HArray1OfReal) tk = vknots;
1184 TColStd_Array1OfReal k( (vknots->Array1())(FromI1), FromI1, ToI2);
1186 TColStd_Array1OfInteger m( FromI1, ToI2) ;
1189 InsertVKnots( k, m, Epsilon(1.));
1192 //=======================================================================
1193 //function : UpdateUKnots
1195 //=======================================================================
1197 void Geom_BSplineSurface::UpdateUKnots()
1200 Standard_Integer MaxKnotMult = 0;
1201 BSplCLib::KnotAnalysis (udeg, uperiodic,
1204 uknotSet, MaxKnotMult);
1206 if (uknotSet == GeomAbs_Uniform && !uperiodic) {
1210 ufknots = new TColStd_HArray1OfReal
1211 (1, BSplCLib::KnotSequenceLength(umults->Array1(),udeg,uperiodic));
1213 BSplCLib::KnotSequence (uknots->Array1(),
1216 ufknots->ChangeArray1());
1219 if (MaxKnotMult == 0) Usmooth = GeomAbs_CN;
1221 switch (udeg - MaxKnotMult) {
1222 case 0 : Usmooth = GeomAbs_C0; break;
1223 case 1 : Usmooth = GeomAbs_C1; break;
1224 case 2 : Usmooth = GeomAbs_C2; break;
1225 case 3 : Usmooth = GeomAbs_C3; break;
1226 default : Usmooth = GeomAbs_C3; break;
1231 //=======================================================================
1232 //function : UpdateVKnots
1234 //=======================================================================
1236 void Geom_BSplineSurface::UpdateVKnots()
1238 Standard_Integer MaxKnotMult = 0;
1239 BSplCLib::KnotAnalysis (vdeg, vperiodic,
1242 vknotSet, MaxKnotMult);
1244 if (vknotSet == GeomAbs_Uniform && !vperiodic) {
1248 vfknots = new TColStd_HArray1OfReal
1249 (1, BSplCLib::KnotSequenceLength(vmults->Array1(),vdeg,vperiodic));
1251 BSplCLib::KnotSequence (vknots->Array1(),
1254 vfknots->ChangeArray1());
1257 if (MaxKnotMult == 0) Vsmooth = GeomAbs_CN;
1259 switch (vdeg - MaxKnotMult) {
1260 case 0 : Vsmooth = GeomAbs_C0; break;
1261 case 1 : Vsmooth = GeomAbs_C1; break;
1262 case 2 : Vsmooth = GeomAbs_C2; break;
1263 case 3 : Vsmooth = GeomAbs_C3; break;
1264 default : Vsmooth = GeomAbs_C3; break;
1270 //=======================================================================
1271 //function : Normalizes the parameters if the curve is periodic
1272 //purpose : that is compute the cache so that it is valid
1273 //=======================================================================
1275 void Geom_BSplineSurface::PeriodicNormalization
1276 (Standard_Real& Uparameter,
1277 Standard_Real& Vparameter) const
1279 Standard_Real Period, aMaxVal, aMinVal;
1282 aMaxVal = ufknots->Value(ufknots->Upper() - udeg);
1283 aMinVal = ufknots->Value (udeg + 1);
1284 Standard_Real eps = Abs(Epsilon(Uparameter));
1285 Period = aMaxVal - aMinVal;
1288 Standard_OutOfRange::Raise("Geom_BSplineSurface::PeriodicNormalization: Uparameter is too great number");
1290 Standard_Boolean isLess, isGreater;
1291 isLess = aMinVal - Uparameter > 0;
1292 isGreater = Uparameter - aMaxVal > 0;
1293 if (isLess || isGreater) {
1294 Standard_Real aDPar, aNbPer;
1295 aDPar = (isLess) ? (aMaxVal - Uparameter) : (aMinVal - Uparameter);
1296 modf(aDPar / Period, &aNbPer);
1297 Uparameter += aNbPer * Period;
1301 aMaxVal = vfknots->Value(vfknots->Upper() - vdeg);
1302 aMinVal = vfknots->Value (vdeg + 1);
1303 Standard_Real eps = Abs(Epsilon(Vparameter));
1304 Period = aMaxVal - aMinVal;
1307 Standard_OutOfRange::Raise("Geom_BSplineSurface::PeriodicNormalization: Vparameter is too great number");
1309 Standard_Boolean isLess, isGreater;
1310 isLess = aMinVal - Vparameter > 0;
1311 isGreater = Vparameter - aMaxVal > 0;
1312 if (isLess || isGreater) {
1313 Standard_Real aDPar, aNbPer;
1314 aDPar = (isLess) ? (aMaxVal - Vparameter) : (aMinVal - Vparameter);
1315 modf(aDPar / Period, &aNbPer);
1316 Vparameter += aNbPer * Period;
1321 //=======================================================================
1322 //function : SetWeight
1324 //=======================================================================
1326 void Geom_BSplineSurface::SetWeight (const Standard_Integer UIndex,
1327 const Standard_Integer VIndex,
1328 const Standard_Real Weight)
1330 if (Weight <= gp::Resolution()) Standard_ConstructionError::Raise();
1331 TColStd_Array2OfReal & Weights = weights->ChangeArray2();
1332 if (UIndex < 1 || UIndex > Weights.ColLength() ||
1333 VIndex < 1 || VIndex > Weights.RowLength() ) {
1334 Standard_OutOfRange::Raise();
1336 Weights (UIndex+Weights.LowerRow()-1, VIndex+Weights.LowerCol()-1) = Weight;
1337 Rational(Weights, urational, vrational);
1340 //=======================================================================
1341 //function : SetWeightCol
1343 //=======================================================================
1345 void Geom_BSplineSurface::SetWeightCol
1346 (const Standard_Integer VIndex,
1347 const TColStd_Array1OfReal& CPoleWeights)
1349 TColStd_Array2OfReal & Weights = weights->ChangeArray2();
1350 if (VIndex < 1 || VIndex > Weights.RowLength()) {
1351 Standard_OutOfRange::Raise();
1353 if (CPoleWeights.Lower() < 1 ||
1354 CPoleWeights.Lower() > Weights.ColLength() ||
1355 CPoleWeights.Upper() < 1 ||
1356 CPoleWeights.Upper() > Weights.ColLength() ) {
1357 Standard_ConstructionError::Raise();
1359 Standard_Integer I = CPoleWeights.Lower();
1360 while (I <= CPoleWeights.Upper()) {
1361 if (CPoleWeights(I) <= gp::Resolution()) {
1362 Standard_ConstructionError::Raise();
1364 Weights (I+Weights.LowerRow()-1, VIndex+Weights.LowerCol()-1) =
1368 // Verifie si c'est rationnel
1369 Rational(Weights, urational, vrational);
1372 //=======================================================================
1373 //function : SetWeightRow
1375 //=======================================================================
1377 void Geom_BSplineSurface::SetWeightRow
1378 (const Standard_Integer UIndex,
1379 const TColStd_Array1OfReal& CPoleWeights)
1381 TColStd_Array2OfReal & Weights = weights->ChangeArray2();
1382 if (UIndex < 1 || UIndex > Weights.ColLength()) {
1383 Standard_OutOfRange::Raise();
1385 if (CPoleWeights.Lower() < 1 ||
1386 CPoleWeights.Lower() > Weights.RowLength() ||
1387 CPoleWeights.Upper() < 1 ||
1388 CPoleWeights.Upper() > Weights.RowLength() ) {
1390 Standard_ConstructionError::Raise();
1392 Standard_Integer I = CPoleWeights.Lower();
1394 while (I <= CPoleWeights.Upper()) {
1395 if (CPoleWeights(I)<=gp::Resolution()) {
1396 Standard_ConstructionError::Raise();
1398 Weights (UIndex+Weights.LowerRow()-1, I+Weights.LowerCol()-1) =
1402 // Verifie si c'est rationnel
1403 Rational(Weights, urational, vrational);