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
26 #include <BSplCLib.hxx>
27 #include <BSplSLib.hxx>
28 #include <Geom_BSplineSurface.hxx>
29 #include <Geom_Curve.hxx>
30 #include <Geom_Geometry.hxx>
31 #include <Geom_UndefinedDerivative.hxx>
34 #include <gp_Trsf.hxx>
36 #include <Precision.hxx>
37 #include <Standard_ConstructionError.hxx>
38 #include <Standard_DimensionError.hxx>
39 #include <Standard_DomainError.hxx>
40 #include <Standard_NoSuchObject.hxx>
41 #include <Standard_NotImplemented.hxx>
42 #include <Standard_OutOfRange.hxx>
43 #include <Standard_RangeError.hxx>
44 #include <Standard_Type.hxx>
46 IMPLEMENT_STANDARD_RTTIEXT(Geom_BSplineSurface,Geom_BoundedSurface)
48 //=======================================================================
49 //function : CheckSurfaceData
50 //purpose : Internal use only.
51 //=======================================================================
52 static void CheckSurfaceData
53 (const TColgp_Array2OfPnt& SPoles,
54 const TColStd_Array1OfReal& SUKnots,
55 const TColStd_Array1OfReal& SVKnots,
56 const TColStd_Array1OfInteger& SUMults,
57 const TColStd_Array1OfInteger& SVMults,
58 const Standard_Integer UDegree,
59 const Standard_Integer VDegree,
60 const Standard_Boolean UPeriodic,
61 const Standard_Boolean VPeriodic)
63 if (UDegree < 1 || UDegree > Geom_BSplineSurface::MaxDegree () ||
64 VDegree < 1 || VDegree > Geom_BSplineSurface::MaxDegree ()) {
65 throw Standard_ConstructionError("Geom_BSplineSurface");
67 if (SPoles.ColLength () < 2 || SPoles.RowLength () < 2) {
68 throw Standard_ConstructionError("Geom_BSplineSurface");
71 if (SUKnots.Length() != SUMults.Length() ||
72 SVKnots.Length() != SVMults.Length()) {
73 throw Standard_ConstructionError("Geom_BSplineSurface");
77 for (i = SUKnots.Lower(); i < SUKnots.Upper(); i++) {
78 if (SUKnots(i+1) - SUKnots(i) <= Epsilon(Abs(SUKnots(i)))) {
79 throw Standard_ConstructionError("Geom_BSplineSurface");
83 for (i = SVKnots.Lower(); i < SVKnots.Upper(); i++) {
84 if (SVKnots(i+1) - SVKnots(i) <= Epsilon(Abs(SVKnots(i)))) {
85 throw Standard_ConstructionError("Geom_BSplineSurface");
89 if (SPoles.ColLength() != BSplCLib::NbPoles(UDegree,UPeriodic,SUMults))
90 throw Standard_ConstructionError("Geom_BSplineSurface");
92 if (SPoles.RowLength() != BSplCLib::NbPoles(VDegree,VPeriodic,SVMults))
93 throw Standard_ConstructionError("Geom_BSplineSurface");
96 //=======================================================================
98 //purpose : Internal use only.
99 //=======================================================================
101 static void Rational(const TColStd_Array2OfReal& Weights,
102 Standard_Boolean& Urational,
103 Standard_Boolean& Vrational)
105 Standard_Integer I,J;
106 J = Weights.LowerCol ();
107 Vrational = Standard_False;
108 while (!Vrational && J <= Weights.UpperCol()) {
109 I = Weights.LowerRow();
110 while (!Vrational && I <= Weights.UpperRow() - 1) {
111 Vrational = (Abs(Weights (I, J) - Weights (I+1, J))
112 > Epsilon (Abs(Weights (I, J))));
118 I = Weights.LowerRow ();
119 Urational = Standard_False;
120 while (!Urational && I <= Weights.UpperRow()) {
121 J = Weights.LowerCol();
122 while (!Urational && J <= Weights.UpperCol() - 1) {
123 Urational = (Abs(Weights (I, J) - Weights (I, J+1))
124 > Epsilon (Abs(Weights (I, J))));
131 //=======================================================================
134 //=======================================================================
136 Handle(Geom_Geometry) Geom_BSplineSurface::Copy () const
138 Handle(Geom_BSplineSurface) S;
139 if (urational || vrational)
140 S = new Geom_BSplineSurface (poles->Array2() , weights->Array2(),
141 uknots->Array1(), vknots->Array1(),
142 umults->Array1(), vmults->Array1(),
144 uperiodic, vperiodic);
146 S = new Geom_BSplineSurface (poles->Array2(),
147 uknots->Array1(), vknots->Array1(),
148 umults->Array1(), vmults->Array1(),
150 uperiodic, vperiodic);
154 //=======================================================================
155 //function : Geom_BSplineSurface
157 //=======================================================================
159 Geom_BSplineSurface::Geom_BSplineSurface
160 (const TColgp_Array2OfPnt& Poles,
161 const TColStd_Array1OfReal& UKnots,
162 const TColStd_Array1OfReal& VKnots,
163 const TColStd_Array1OfInteger& UMults,
164 const TColStd_Array1OfInteger& VMults,
165 const Standard_Integer UDegree,
166 const Standard_Integer VDegree,
167 const Standard_Boolean UPeriodic,
168 const Standard_Boolean VPeriodic
170 urational(Standard_False),
171 vrational(Standard_False),
172 uperiodic(UPeriodic),
173 vperiodic(VPeriodic),
182 CheckSurfaceData(Poles,
186 UPeriodic, VPeriodic);
190 poles = new TColgp_HArray2OfPnt(1,Poles.ColLength(),
191 1,Poles.RowLength());
192 poles->ChangeArray2() = Poles;
194 weights = new TColStd_HArray2OfReal (1,Poles.ColLength(),
195 1,Poles.RowLength(), 1.0);
197 uknots = new TColStd_HArray1OfReal (1,UKnots.Length());
198 uknots->ChangeArray1() = UKnots;
200 umults = new TColStd_HArray1OfInteger (1,UMults.Length());
201 umults->ChangeArray1() = UMults;
203 vknots = new TColStd_HArray1OfReal (1,VKnots.Length());
204 vknots->ChangeArray1() = VKnots;
206 vmults = new TColStd_HArray1OfInteger (1,VMults.Length());
207 vmults->ChangeArray1() = VMults;
213 //=======================================================================
214 //function : Geom_BSplineSurface
216 //=======================================================================
218 Geom_BSplineSurface::Geom_BSplineSurface
219 (const TColgp_Array2OfPnt& Poles,
220 const TColStd_Array2OfReal& Weights,
221 const TColStd_Array1OfReal& UKnots,
222 const TColStd_Array1OfReal& VKnots,
223 const TColStd_Array1OfInteger& UMults,
224 const TColStd_Array1OfInteger& VMults,
225 const Standard_Integer UDegree,
226 const Standard_Integer VDegree,
227 const Standard_Boolean UPeriodic,
228 const Standard_Boolean VPeriodic) :
229 urational(Standard_False),
230 vrational(Standard_False),
231 uperiodic(UPeriodic),
232 vperiodic(VPeriodic),
239 if (Weights.ColLength() != Poles.ColLength())
240 throw Standard_ConstructionError("Geom_BSplineSurface");
242 if (Weights.RowLength() != Poles.RowLength())
243 throw Standard_ConstructionError("Geom_BSplineSurface");
245 Standard_Integer i,j;
246 for (i = Weights.LowerRow(); i <= Weights.UpperRow(); i++) {
247 for (j = Weights.LowerCol(); j <= Weights.UpperCol(); j++) {
248 if (Weights(i,j) <= gp::Resolution())
249 throw Standard_ConstructionError("Geom_BSplineSurface");
253 // check really rational
255 Rational(Weights, urational, vrational);
259 CheckSurfaceData(Poles,
263 UPeriodic, VPeriodic);
267 poles = new TColgp_HArray2OfPnt(1,Poles.ColLength(),
268 1,Poles.RowLength());
269 poles->ChangeArray2() = Poles;
271 weights = new TColStd_HArray2OfReal (1,Poles.ColLength(),
272 1,Poles.RowLength());
273 weights->ChangeArray2() = Weights;
275 uknots = new TColStd_HArray1OfReal (1,UKnots.Length());
276 uknots->ChangeArray1() = UKnots;
278 umults = new TColStd_HArray1OfInteger (1,UMults.Length());
279 umults->ChangeArray1() = UMults;
281 vknots = new TColStd_HArray1OfReal (1,VKnots.Length());
282 vknots->ChangeArray1() = VKnots;
284 vmults = new TColStd_HArray1OfInteger (1,VMults.Length());
285 vmults->ChangeArray1() = VMults;
291 //=======================================================================
292 //function : ExchangeUV
294 //=======================================================================
296 void Geom_BSplineSurface::ExchangeUV ()
298 Standard_Integer LC = poles->LowerCol();
299 Standard_Integer UC = poles->UpperCol();
300 Standard_Integer LR = poles->LowerRow();
301 Standard_Integer UR = poles->UpperRow();
303 Handle(TColgp_HArray2OfPnt) npoles =
304 new TColgp_HArray2OfPnt (LC, UC, LR, UR);
305 Handle(TColStd_HArray2OfReal) nweights =
306 new TColStd_HArray2OfReal (LC, UC, LR, UR);
308 const TColgp_Array2OfPnt & spoles = poles->Array2();
309 const TColStd_Array2OfReal & sweights = weights->Array2();
311 TColgp_Array2OfPnt& snpoles = npoles->ChangeArray2();
312 TColStd_Array2OfReal& snweights = nweights->ChangeArray2();
314 Standard_Integer i, j;
315 for (i = LC; i <= UC; i++) {
316 for (j = LR; j <= UR; j++) {
317 snpoles (i,j) = spoles (j,i);
318 snweights (i,j) = sweights (j,i);
325 Standard_Boolean temp = urational;
326 urational = vrational;
330 uperiodic = vperiodic;
333 Standard_Integer tempdeg = udeg;
338 Handle(TColStd_HArray1OfReal) tempknots = uknots;
342 Handle(TColStd_HArray1OfInteger) tempmults = umults;
350 //=======================================================================
351 //function : IncreaseDegree
353 //=======================================================================
355 void Geom_BSplineSurface::IncreaseDegree (const Standard_Integer UDegree,
356 const Standard_Integer VDegree)
358 if (UDegree != udeg) {
359 if ( UDegree < udeg || UDegree > Geom_BSplineSurface::MaxDegree())
360 throw Standard_ConstructionError();
362 Standard_Integer FromK1 = FirstUKnotIndex();
363 Standard_Integer ToK2 = LastUKnotIndex();
365 Standard_Integer Step = UDegree - udeg;
367 Handle(TColgp_HArray2OfPnt) npoles = new
368 TColgp_HArray2OfPnt( 1, poles->ColLength() + Step * (ToK2 - FromK1),
369 1, poles->RowLength());
371 Standard_Integer nbknots = BSplCLib::IncreaseDegreeCountKnots
372 (udeg,UDegree,uperiodic,umults->Array1());
374 Handle(TColStd_HArray1OfReal) nknots =
375 new TColStd_HArray1OfReal(1,nbknots);
377 Handle(TColStd_HArray1OfInteger) nmults =
378 new TColStd_HArray1OfInteger(1,nbknots);
380 Handle(TColStd_HArray2OfReal) nweights
381 = new TColStd_HArray2OfReal(1,npoles->ColLength(),
382 1,npoles->RowLength(), 1.);
384 if (urational || vrational) {
386 BSplSLib::IncreaseDegree
387 (Standard_True, udeg, UDegree, uperiodic,
388 poles->Array2(),&weights->Array2(),
389 uknots->Array1(),umults->Array1(),
390 npoles->ChangeArray2(),&nweights->ChangeArray2(),
391 nknots->ChangeArray1(),nmults->ChangeArray1());
395 BSplSLib::IncreaseDegree
396 (Standard_True, udeg, UDegree, uperiodic,
397 poles->Array2(),BSplSLib::NoWeights(),
398 uknots->Array1(),umults->Array1(),
399 npoles->ChangeArray2(),BSplSLib::NoWeights(),
400 nknots->ChangeArray1(),nmults->ChangeArray1());
410 if (VDegree != vdeg) {
411 if ( VDegree < vdeg || VDegree > Geom_BSplineSurface::MaxDegree())
412 throw Standard_ConstructionError();
414 Standard_Integer FromK1 = FirstVKnotIndex();
415 Standard_Integer ToK2 = LastVKnotIndex();
417 Standard_Integer Step = VDegree - vdeg;
419 Handle(TColgp_HArray2OfPnt) npoles = new
420 TColgp_HArray2OfPnt( 1, poles->ColLength(),
421 1, poles->RowLength() + Step * (ToK2 - FromK1));
423 Standard_Integer nbknots = BSplCLib::IncreaseDegreeCountKnots
424 (vdeg,VDegree,vperiodic,vmults->Array1());
426 Handle(TColStd_HArray1OfReal) nknots =
427 new TColStd_HArray1OfReal(1,nbknots);
429 Handle(TColStd_HArray1OfInteger) nmults =
430 new TColStd_HArray1OfInteger(1,nbknots);
432 Handle(TColStd_HArray2OfReal) nweights
433 = new TColStd_HArray2OfReal(1,npoles->ColLength(),
434 1,npoles->RowLength(), 1.);
436 if (urational || vrational) {
438 BSplSLib::IncreaseDegree
439 (Standard_False, vdeg, VDegree, vperiodic,
440 poles->Array2(),&weights->Array2(),
441 vknots->Array1(),vmults->Array1(),
442 npoles->ChangeArray2(),&nweights->ChangeArray2(),
443 nknots->ChangeArray1(),nmults->ChangeArray1());
447 BSplSLib::IncreaseDegree
448 (Standard_False, vdeg, VDegree, vperiodic,
449 poles->Array2(),BSplSLib::NoWeights(),
450 vknots->Array1(),vmults->Array1(),
451 npoles->ChangeArray2(),BSplSLib::NoWeights(),
452 nknots->ChangeArray1(),nmults->ChangeArray1());
463 //=======================================================================
464 //function : IncreaseUMultiplicity
466 //=======================================================================
468 void Geom_BSplineSurface::IncreaseUMultiplicity
469 (const Standard_Integer UIndex,
470 const Standard_Integer M)
472 TColStd_Array1OfReal k(1,1);
473 k(1) = uknots->Value(UIndex);
474 TColStd_Array1OfInteger m(1,1);
475 m(1) = M - umults->Value(UIndex);
476 InsertUKnots(k,m,Epsilon(1.),Standard_True);
479 //=======================================================================
480 //function : IncreaseUMultiplicity
482 //=======================================================================
484 void Geom_BSplineSurface::IncreaseUMultiplicity
485 (const Standard_Integer FromI1,
486 const Standard_Integer ToI2,
487 const Standard_Integer M)
489 Handle(TColStd_HArray1OfReal) tk = uknots;
490 TColStd_Array1OfReal k((uknots->Array1())(FromI1),FromI1,ToI2);
491 TColStd_Array1OfInteger m(FromI1, ToI2);
492 for (Standard_Integer i = FromI1; i <= ToI2; i++)
493 m(i) = M - umults->Value(i);
494 InsertUKnots(k,m,Epsilon(1.),Standard_True);
497 //=======================================================================
498 //function : IncreaseVMultiplicity
500 //=======================================================================
502 void Geom_BSplineSurface::IncreaseVMultiplicity
503 (const Standard_Integer VIndex,
504 const Standard_Integer M)
506 TColStd_Array1OfReal k(1,1);
507 k(1) = vknots->Value(VIndex);
508 TColStd_Array1OfInteger m(1,1);
509 m(1) = M - vmults->Value(VIndex);
510 InsertVKnots(k,m,Epsilon(1.),Standard_True);
513 //=======================================================================
514 //function : IncreaseVMultiplicity
516 //=======================================================================
518 void Geom_BSplineSurface::IncreaseVMultiplicity
519 (const Standard_Integer FromI1,
520 const Standard_Integer ToI2,
521 const Standard_Integer M)
523 Handle(TColStd_HArray1OfReal) tk = vknots;
524 TColStd_Array1OfReal k((vknots->Array1())(FromI1),FromI1,ToI2);
525 TColStd_Array1OfInteger m(FromI1,ToI2);
526 for (Standard_Integer i = FromI1; i <= ToI2; i++)
527 m(i) = M - vmults->Value(i);
528 InsertVKnots(k,m,Epsilon(1.),Standard_True);
531 //=======================================================================
534 //=======================================================================
536 void Geom_BSplineSurface::Segment(const Standard_Real U1,
537 const Standard_Real U2,
538 const Standard_Real V1,
539 const Standard_Real V2)
541 if ((U2 < U1) || (V2 < V1))
542 throw Standard_DomainError("Geom_BSplineSurface::Segment");
543 Standard_Real deltaU = Max(Abs(U2),Abs(U1));
544 Standard_Real EpsU = Epsilon(deltaU);
547 Standard_Real aUPeriod = uknots->Last() - uknots->First();
548 if (deltaU - aUPeriod > Precision::PConfusion())
549 throw Standard_DomainError("Geom_BSplineSurface::Segment");
550 if (deltaU > aUPeriod)
554 Standard_Real deltaV = Max(Abs(V2),Abs(V1));
555 Standard_Real EpsV = Epsilon(deltaV);
558 Standard_Real aVPeriod = vknots->Last() - vknots->First();
559 if (deltaV - aVPeriod > Precision::PConfusion())
560 throw Standard_DomainError("Geom_BSplineSurface::Segment");
561 if (deltaV > aVPeriod)
565 Standard_Real NewU1, NewU2, NewV1, NewV2;
567 Standard_Integer indexU, indexV;
569 // inserting the UKnots
570 TColStd_Array1OfReal UKnots(1,2);
571 TColStd_Array1OfInteger UMults(1,2);
574 BSplCLib::LocateParameter(udeg,uknots->Array1(),umults->Array1(),
575 U1,uperiodic,uknots->Lower(),uknots->Upper(),
578 BSplCLib::LocateParameter(udeg,uknots->Array1(),umults->Array1(),
579 U2,uperiodic,uknots->Lower(),uknots->Upper(),
581 UKnots( 1) = Min( NewU1, NewU2);
582 UKnots( 2) = Max( NewU1, NewU2);
583 UMults( 1) = UMults( 2) = udeg;
584 InsertUKnots( UKnots, UMults, EpsU);
586 // Inserting the VKnots
587 TColStd_Array1OfReal VKnots(1,2);
588 TColStd_Array1OfInteger VMults(1,2);
591 BSplCLib::LocateParameter(vdeg,vknots->Array1(),vmults->Array1(),
592 V1,vperiodic,vknots->Lower(),vknots->Upper(),
595 BSplCLib::LocateParameter(vdeg,vknots->Array1(),vmults->Array1(),
596 V2,vperiodic,vknots->Lower(),vknots->Upper(),
598 VKnots( 1) = Min( NewV1, NewV2);
599 VKnots( 2) = Max( NewV1, NewV2);
600 VMults( 1) = VMults( 2) = vdeg;
601 InsertVKnots( VKnots, VMults, EpsV);
604 if (uperiodic) { // set the origine at NewU1
605 Standard_Integer index = 0;
606 BSplCLib::LocateParameter(udeg,uknots->Array1(),umults->Array1(),
607 U1,uperiodic,uknots->Lower(),uknots->Upper(),
609 if ( Abs(uknots->Value(index+1)-U) <= EpsU)
615 // compute index1 and index2 to set the new knots and mults
616 Standard_Integer index1U = 0, index2U = 0;
617 Standard_Integer FromU1 = uknots->Lower();
618 Standard_Integer ToU2 = uknots->Upper();
619 BSplCLib::LocateParameter(udeg,uknots->Array1(),umults->Array1(),
620 NewU1,uperiodic,FromU1,ToU2,index1U,U);
621 BSplCLib::LocateParameter(udeg,uknots->Array1(),umults->Array1(),
622 NewU1 + deltaU,uperiodic,FromU1,ToU2,index2U,U);
623 if ( Abs(uknots->Value(index2U+1)-U) <= EpsU)
626 Standard_Integer nbuknots = index2U - index1U + 1;
628 Handle(TColStd_HArray1OfReal)
629 nuknots = new TColStd_HArray1OfReal(1,nbuknots);
630 Handle(TColStd_HArray1OfInteger)
631 numults = new TColStd_HArray1OfInteger(1,nbuknots);
633 Standard_Integer i , k = 1;
634 for ( i = index1U; i<= index2U; i++) {
635 nuknots->SetValue(k, uknots->Value(i));
636 numults->SetValue(k, umults->Value(i));
639 numults->SetValue( 1, udeg + 1);
640 numults->SetValue(nbuknots, udeg + 1);
643 if (vperiodic) { // set the origine at NewV1
644 Standard_Integer index = 0;
645 BSplCLib::LocateParameter(vdeg,vknots->Array1(),vmults->Array1(),
646 V1,vperiodic,vknots->Lower(),vknots->Upper(),
648 if ( Abs(vknots->Value(index+1)-V) <= EpsV)
654 // compute index1 and index2 to set the new knots and mults
655 Standard_Integer index1V = 0, index2V = 0;
656 Standard_Integer FromV1 = vknots->Lower();
657 Standard_Integer ToV2 = vknots->Upper();
658 BSplCLib::LocateParameter(vdeg,vknots->Array1(),vmults->Array1(),
659 NewV1,vperiodic,FromV1,ToV2,index1V,V);
660 BSplCLib::LocateParameter(vdeg,vknots->Array1(),vmults->Array1(),
661 NewV1 + deltaV,vperiodic,FromV1,ToV2,index2V,V);
662 if ( Abs(vknots->Value(index2V+1)-V) <= EpsV)
665 Standard_Integer nbvknots = index2V - index1V + 1;
667 Handle(TColStd_HArray1OfReal)
668 nvknots = new TColStd_HArray1OfReal(1,nbvknots);
669 Handle(TColStd_HArray1OfInteger)
670 nvmults = new TColStd_HArray1OfInteger(1,nbvknots);
673 for ( i = index1V; i<= index2V; i++) {
674 nvknots->SetValue(k, vknots->Value(i));
675 nvmults->SetValue(k, vmults->Value(i));
678 nvmults->SetValue( 1, vdeg + 1);
679 nvmults->SetValue(nbvknots, vdeg + 1);
682 // compute index1 and index2 to set the new poles and weights
683 Standard_Integer pindex1U
684 = BSplCLib::PoleIndex(udeg,index1U,uperiodic,umults->Array1());
685 Standard_Integer pindex2U
686 = BSplCLib::PoleIndex(udeg,index2U,uperiodic,umults->Array1());
689 pindex2U = Min( pindex2U+1, poles->ColLength());
691 Standard_Integer nbupoles = pindex2U - pindex1U + 1;
693 // compute index1 and index2 to set the new poles and weights
694 Standard_Integer pindex1V
695 = BSplCLib::PoleIndex(vdeg,index1V,vperiodic,vmults->Array1());
696 Standard_Integer pindex2V
697 = BSplCLib::PoleIndex(vdeg,index2V,vperiodic,vmults->Array1());
700 pindex2V = Min( pindex2V+1, poles->RowLength());
702 Standard_Integer nbvpoles = pindex2V - pindex1V + 1;
705 Handle(TColStd_HArray2OfReal) nweights;
707 Handle(TColgp_HArray2OfPnt)
708 npoles = new TColgp_HArray2OfPnt(1,nbupoles,1,nbvpoles);
711 Standard_Integer j, l;
712 if ( urational || vrational) {
713 nweights = new TColStd_HArray2OfReal( 1,nbupoles,1,nbvpoles);
714 for ( i = pindex1U; i <= pindex2U; i++) {
716 for ( j = pindex1V; j <= pindex2V; j++) {
717 npoles->SetValue(k,l, poles->Value(i,j));
718 nweights->SetValue(k,l, weights->Value(i,j));
725 for ( i = pindex1U; i <= pindex2U; i++) {
727 for ( j = pindex1V; j <= pindex2V; j++) {
728 npoles->SetValue(k,l, poles->Value(i,j));
740 if ( urational || vrational)
743 weights = new TColStd_HArray2OfReal (1,poles->ColLength(),
744 1,poles->RowLength(), 1.0);
752 //=======================================================================
753 //function : CheckAndSegment
755 //=======================================================================
757 void Geom_BSplineSurface::CheckAndSegment(const Standard_Real U1,
758 const Standard_Real U2,
759 const Standard_Real V1,
760 const Standard_Real V2)
763 if ((U2 < U1) || (V2 < V1))
764 throw Standard_DomainError("Geom_BSplineSurface::CheckAndSegment");
765 Standard_Real deltaU = Max(Abs(U2),Abs(U1));
766 Standard_Real EpsU = Epsilon(deltaU);
769 Standard_Real aUPeriod = uknots->Last() - uknots->First();
770 if (deltaU - aUPeriod > Precision::PConfusion())
771 throw Standard_DomainError("Geom_BSplineSurface::CheckAndSegment");
772 if (deltaU > aUPeriod)
776 Standard_Real deltaV = Max(Abs(V2),Abs(V1));
777 Standard_Real EpsV = Epsilon(deltaV);
780 Standard_Real aVPeriod = vknots->Last() - vknots->First();
781 if (deltaV - aVPeriod > Precision::PConfusion())
782 throw Standard_DomainError("Geom_BSplineSurface::CheckAndSegment");
783 if (deltaV > aVPeriod)
787 Standard_Real NewU1, NewU2, NewV1, NewV2;
789 Standard_Integer indexU, indexV;
791 Standard_Boolean segment_in_U = Standard_True;
792 Standard_Boolean segment_in_V = Standard_True;
793 segment_in_U = ( Abs(U1 - uknots->Value(uknots->Lower())) > EpsU )
794 || ( Abs(U2 - uknots->Value(uknots->Upper())) > EpsU );
795 segment_in_V = ( Abs(V1 - vknots->Value(vknots->Lower())) > EpsV )
796 || ( Abs(V2 - vknots->Value(vknots->Upper())) > EpsV );
799 BSplCLib::LocateParameter(udeg,uknots->Array1(),umults->Array1(),
800 U1,uperiodic,uknots->Lower(),uknots->Upper(),
803 BSplCLib::LocateParameter(udeg,uknots->Array1(),umults->Array1(),
804 U2,uperiodic,uknots->Lower(),uknots->Upper(),
807 // inserting the UKnots
808 TColStd_Array1OfReal UKnots(1,2);
809 TColStd_Array1OfInteger UMults(1,2);
810 UKnots( 1) = Min( NewU1, NewU2);
811 UKnots( 2) = Max( NewU1, NewU2);
812 UMults( 1) = UMults( 2) = udeg;
814 InsertUKnots( UKnots, UMults, EpsU);
818 BSplCLib::LocateParameter(vdeg,vknots->Array1(),vmults->Array1(),
819 V1,vperiodic,vknots->Lower(),vknots->Upper(),
822 BSplCLib::LocateParameter(vdeg,vknots->Array1(),vmults->Array1(),
823 V2,vperiodic,vknots->Lower(),vknots->Upper(),
826 // Inserting the VKnots
827 TColStd_Array1OfReal VKnots(1,2);
828 TColStd_Array1OfInteger VMults(1,2);
830 VKnots( 1) = Min( NewV1, NewV2);
831 VKnots( 2) = Max( NewV1, NewV2);
832 VMults( 1) = VMults( 2) = vdeg;
833 InsertVKnots( VKnots, VMults, EpsV);
836 if (uperiodic && segment_in_U) { // set the origine at NewU1
837 Standard_Integer index = 0;
838 BSplCLib::LocateParameter(udeg,uknots->Array1(),umults->Array1(),
839 U1,uperiodic,uknots->Lower(),uknots->Upper(),
841 if ( Abs(uknots->Value(index+1)-U) <= EpsU)
847 // compute index1 and index2 to set the new knots and mults
848 Standard_Integer index1U = 0, index2U = 0;
849 Standard_Integer FromU1 = uknots->Lower();
850 Standard_Integer ToU2 = uknots->Upper();
851 BSplCLib::LocateParameter(udeg,uknots->Array1(),umults->Array1(),
852 NewU1,uperiodic,FromU1,ToU2,index1U,U);
853 BSplCLib::LocateParameter(udeg,uknots->Array1(),umults->Array1(),
854 NewU1 + deltaU,uperiodic,FromU1,ToU2,index2U,U);
855 if ( Abs(uknots->Value(index2U+1)-U) <= EpsU)
858 Standard_Integer nbuknots = index2U - index1U + 1;
860 Handle(TColStd_HArray1OfReal)
861 nuknots = new TColStd_HArray1OfReal(1,nbuknots);
862 Handle(TColStd_HArray1OfInteger)
863 numults = new TColStd_HArray1OfInteger(1,nbuknots);
865 Standard_Integer i , k = 1;
866 for ( i = index1U; i<= index2U; i++) {
867 nuknots->SetValue(k, uknots->Value(i));
868 numults->SetValue(k, umults->Value(i));
872 numults->SetValue( 1, udeg + 1);
873 numults->SetValue(nbuknots, udeg + 1);
876 if (vperiodic&& segment_in_V) { // set the origine at NewV1
877 Standard_Integer index = 0;
878 BSplCLib::LocateParameter(vdeg,vknots->Array1(),vmults->Array1(),
879 V1,vperiodic,vknots->Lower(),vknots->Upper(),
881 if ( Abs(vknots->Value(index+1)-V) <= EpsV)
887 // compute index1 and index2 to set the new knots and mults
888 Standard_Integer index1V = 0, index2V = 0;
889 Standard_Integer FromV1 = vknots->Lower();
890 Standard_Integer ToV2 = vknots->Upper();
891 BSplCLib::LocateParameter(vdeg,vknots->Array1(),vmults->Array1(),
892 NewV1,vperiodic,FromV1,ToV2,index1V,V);
893 BSplCLib::LocateParameter(vdeg,vknots->Array1(),vmults->Array1(),
894 NewV1 + deltaV,vperiodic,FromV1,ToV2,index2V,V);
895 if ( Abs(vknots->Value(index2V+1)-V) <= EpsV)
898 Standard_Integer nbvknots = index2V - index1V + 1;
900 Handle(TColStd_HArray1OfReal)
901 nvknots = new TColStd_HArray1OfReal(1,nbvknots);
902 Handle(TColStd_HArray1OfInteger)
903 nvmults = new TColStd_HArray1OfInteger(1,nbvknots);
906 for ( i = index1V; i<= index2V; i++) {
907 nvknots->SetValue(k, vknots->Value(i));
908 nvmults->SetValue(k, vmults->Value(i));
912 nvmults->SetValue( 1, vdeg + 1);
913 nvmults->SetValue(nbvknots, vdeg + 1);
916 // compute index1 and index2 to set the new poles and weights
917 Standard_Integer pindex1U
918 = BSplCLib::PoleIndex(udeg,index1U,uperiodic,umults->Array1());
919 Standard_Integer pindex2U
920 = BSplCLib::PoleIndex(udeg,index2U,uperiodic,umults->Array1());
923 pindex2U = Min( pindex2U+1, poles->ColLength());
925 Standard_Integer nbupoles = pindex2U - pindex1U + 1;
927 // compute index1 and index2 to set the new poles and weights
928 Standard_Integer pindex1V
929 = BSplCLib::PoleIndex(vdeg,index1V,vperiodic,vmults->Array1());
930 Standard_Integer pindex2V
931 = BSplCLib::PoleIndex(vdeg,index2V,vperiodic,vmults->Array1());
934 pindex2V = Min( pindex2V+1, poles->RowLength());
936 Standard_Integer nbvpoles = pindex2V - pindex1V + 1;
939 Handle(TColStd_HArray2OfReal) nweights;
941 Handle(TColgp_HArray2OfPnt)
942 npoles = new TColgp_HArray2OfPnt(1,nbupoles,1,nbvpoles);
945 Standard_Integer j, l;
946 if ( urational || vrational) {
947 nweights = new TColStd_HArray2OfReal( 1,nbupoles,1,nbvpoles);
948 for ( i = pindex1U; i <= pindex2U; i++) {
950 for ( j = pindex1V; j <= pindex2V; j++) {
951 npoles->SetValue(k,l, poles->Value(i,j));
952 nweights->SetValue(k,l, weights->Value(i,j));
959 for ( i = pindex1U; i <= pindex2U; i++) {
961 for ( j = pindex1V; j <= pindex2V; j++) {
962 npoles->SetValue(k,l, poles->Value(i,j));
974 if ( urational || vrational)
977 weights = new TColStd_HArray2OfReal (1,poles->ColLength(),
978 1,poles->RowLength(), 1.0);
986 //=======================================================================
987 //function : SetUKnot
989 //=======================================================================
991 void Geom_BSplineSurface::SetUKnot
992 (const Standard_Integer UIndex,
993 const Standard_Real K )
995 if (UIndex < 1 || UIndex > uknots->Length()) throw Standard_OutOfRange();
997 Standard_Integer NewIndex = UIndex;
998 Standard_Real DU = Abs(Epsilon (K));
1000 if (K >= uknots->Value (2) - DU) throw Standard_ConstructionError();
1002 else if (UIndex == uknots->Length()) {
1003 if (K <= uknots->Value (uknots->Length()-1) + DU) {
1004 throw Standard_ConstructionError();
1008 if (K <= uknots->Value (NewIndex-1) + DU ||
1009 K >= uknots->Value (NewIndex+1) - DU ) {
1010 throw Standard_ConstructionError();
1014 if (K != uknots->Value (NewIndex)) {
1015 uknots->SetValue (NewIndex, K);
1021 //=======================================================================
1022 //function : SetUKnots
1024 //=======================================================================
1026 void Geom_BSplineSurface::SetUKnots (const TColStd_Array1OfReal& UK) {
1028 Standard_Integer Lower = UK.Lower();
1029 Standard_Integer Upper = UK.Upper();
1030 if (Lower < 1 || Lower > uknots->Length() ||
1031 Upper < 1 || Upper > uknots->Length() ) {
1032 throw Standard_OutOfRange();
1035 if (Abs (UK (Lower) - uknots->Value (Lower-1)) <= gp::Resolution()) {
1036 throw Standard_ConstructionError();
1039 if (Upper < uknots->Length ()) {
1040 if (Abs (UK (Upper) - uknots->Value (Upper+1)) <= gp::Resolution()) {
1041 throw Standard_ConstructionError();
1044 Standard_Real K1 = UK (Lower);
1045 for (Standard_Integer i = Lower; i <= Upper; i++) {
1046 uknots->SetValue (i, UK(i));
1048 if (Abs (UK(i) - K1) <= gp::Resolution()) {
1049 throw Standard_ConstructionError();
1059 //=======================================================================
1060 //function : SetUKnot
1062 //=======================================================================
1064 void Geom_BSplineSurface::SetUKnot
1065 (const Standard_Integer UIndex,
1066 const Standard_Real K,
1067 const Standard_Integer M)
1069 IncreaseUMultiplicity (UIndex, M);
1070 SetUKnot (UIndex, K);
1073 //=======================================================================
1074 //function : SetVKnot
1076 //=======================================================================
1078 void Geom_BSplineSurface::SetVKnot
1079 (const Standard_Integer VIndex,
1080 const Standard_Real K)
1082 if (VIndex < 1 || VIndex > vknots->Length()) throw Standard_OutOfRange();
1083 Standard_Integer NewIndex = VIndex + vknots->Lower() - 1;
1084 Standard_Real DV = Abs(Epsilon (K));
1086 if (K >= vknots->Value (2) - DV) {
1087 throw Standard_ConstructionError();
1090 else if (VIndex == vknots->Length()) {
1091 if (K <= vknots->Value (vknots->Length()-1) + DV) {
1092 throw Standard_ConstructionError();
1096 if (K <= vknots->Value (NewIndex-1) + DV ||
1097 K >= vknots->Value (NewIndex+1) - DV ) {
1098 throw Standard_ConstructionError();
1102 if (K != vknots->Value (NewIndex)) {
1103 vknots->SetValue (NewIndex, K);
1109 //=======================================================================
1110 //function : SetVKnots
1112 //=======================================================================
1114 void Geom_BSplineSurface::SetVKnots (const TColStd_Array1OfReal& VK) {
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 throw Standard_OutOfRange();
1123 if (Abs (VK (Lower) - vknots->Value (Lower-1)) <= gp::Resolution()) {
1124 throw Standard_ConstructionError();
1127 if (Upper < vknots->Length ()) {
1128 if (Abs (VK (Upper) - vknots->Value (Upper+1)) <= gp::Resolution()) {
1129 throw Standard_ConstructionError();
1132 Standard_Real K1 = VK (Lower);
1133 for (Standard_Integer i = Lower; i <= Upper; i++) {
1134 vknots->SetValue (i, VK(i));
1136 if (Abs (VK(i) - K1) <= gp::Resolution()) {
1137 throw Standard_ConstructionError();
1147 //=======================================================================
1148 //function : SetVKnot
1150 //=======================================================================
1152 void Geom_BSplineSurface::SetVKnot
1153 (const Standard_Integer VIndex,
1154 const Standard_Real K,
1155 const Standard_Integer M)
1157 IncreaseVMultiplicity (VIndex, M);
1158 SetVKnot (VIndex, K);
1161 //=======================================================================
1162 //function : InsertUKnot
1164 //=======================================================================
1166 void Geom_BSplineSurface::InsertUKnot
1167 (const Standard_Real U,
1168 const Standard_Integer M,
1169 const Standard_Real ParametricTolerance,
1170 const Standard_Boolean Add)
1172 TColStd_Array1OfReal k(1,1);
1174 TColStd_Array1OfInteger m(1,1);
1176 InsertUKnots(k,m,ParametricTolerance,Add);
1179 //=======================================================================
1180 //function : InsertVKnot
1182 //=======================================================================
1184 void Geom_BSplineSurface::InsertVKnot
1185 (const Standard_Real V,
1186 const Standard_Integer M,
1187 const Standard_Real ParametricTolerance,
1188 const Standard_Boolean Add)
1190 TColStd_Array1OfReal k(1,1);
1192 TColStd_Array1OfInteger m(1,1);
1194 InsertVKnots(k,m,ParametricTolerance,Add);
1197 //=======================================================================
1198 //function : IncrementUMultiplicity
1200 //=======================================================================
1202 void Geom_BSplineSurface::IncrementUMultiplicity
1203 (const Standard_Integer FromI1,
1204 const Standard_Integer ToI2,
1205 const Standard_Integer Step)
1207 Handle(TColStd_HArray1OfReal) tk = uknots;
1208 TColStd_Array1OfReal k( (uknots->Array1())(FromI1), FromI1, ToI2);
1209 TColStd_Array1OfInteger m( FromI1, ToI2) ;
1211 InsertUKnots( k, m, Epsilon(1.));
1214 //=======================================================================
1215 //function : IncrementVMultiplicity
1217 //=======================================================================
1219 void Geom_BSplineSurface::IncrementVMultiplicity
1220 (const Standard_Integer FromI1,
1221 const Standard_Integer ToI2,
1222 const Standard_Integer Step)
1224 Handle(TColStd_HArray1OfReal) tk = vknots;
1225 TColStd_Array1OfReal k( (vknots->Array1())(FromI1), FromI1, ToI2);
1227 TColStd_Array1OfInteger m( FromI1, ToI2) ;
1230 InsertVKnots( k, m, Epsilon(1.));
1233 //=======================================================================
1234 //function : UpdateUKnots
1236 //=======================================================================
1238 void Geom_BSplineSurface::UpdateUKnots()
1241 Standard_Integer MaxKnotMult = 0;
1242 BSplCLib::KnotAnalysis (udeg, uperiodic,
1245 uknotSet, MaxKnotMult);
1247 if (uknotSet == GeomAbs_Uniform && !uperiodic) {
1251 ufknots = new TColStd_HArray1OfReal
1252 (1, BSplCLib::KnotSequenceLength(umults->Array1(),udeg,uperiodic));
1254 BSplCLib::KnotSequence (uknots->Array1(),
1257 ufknots->ChangeArray1());
1260 if (MaxKnotMult == 0) Usmooth = GeomAbs_CN;
1262 switch (udeg - MaxKnotMult) {
1263 case 0 : Usmooth = GeomAbs_C0; break;
1264 case 1 : Usmooth = GeomAbs_C1; break;
1265 case 2 : Usmooth = GeomAbs_C2; break;
1266 case 3 : Usmooth = GeomAbs_C3; break;
1267 default : Usmooth = GeomAbs_C3; break;
1272 //=======================================================================
1273 //function : UpdateVKnots
1275 //=======================================================================
1277 void Geom_BSplineSurface::UpdateVKnots()
1279 Standard_Integer MaxKnotMult = 0;
1280 BSplCLib::KnotAnalysis (vdeg, vperiodic,
1283 vknotSet, MaxKnotMult);
1285 if (vknotSet == GeomAbs_Uniform && !vperiodic) {
1289 vfknots = new TColStd_HArray1OfReal
1290 (1, BSplCLib::KnotSequenceLength(vmults->Array1(),vdeg,vperiodic));
1292 BSplCLib::KnotSequence (vknots->Array1(),
1295 vfknots->ChangeArray1());
1298 if (MaxKnotMult == 0) Vsmooth = GeomAbs_CN;
1300 switch (vdeg - MaxKnotMult) {
1301 case 0 : Vsmooth = GeomAbs_C0; break;
1302 case 1 : Vsmooth = GeomAbs_C1; break;
1303 case 2 : Vsmooth = GeomAbs_C2; break;
1304 case 3 : Vsmooth = GeomAbs_C3; break;
1305 default : Vsmooth = GeomAbs_C3; break;
1311 //=======================================================================
1312 //function : Normalizes the parameters if the curve is periodic
1313 //purpose : that is compute the cache so that it is valid
1314 //=======================================================================
1316 void Geom_BSplineSurface::PeriodicNormalization
1317 (Standard_Real& Uparameter,
1318 Standard_Real& Vparameter) const
1320 Standard_Real Period, aMaxVal, aMinVal;
1323 aMaxVal = ufknots->Value(ufknots->Upper() - udeg);
1324 aMinVal = ufknots->Value (udeg + 1);
1325 Standard_Real eps = Abs(Epsilon(Uparameter));
1326 Period = aMaxVal - aMinVal;
1329 throw Standard_OutOfRange("Geom_BSplineSurface::PeriodicNormalization: Uparameter is too great number");
1331 Standard_Boolean isLess, isGreater;
1332 isLess = aMinVal - Uparameter > 0;
1333 isGreater = Uparameter - aMaxVal > 0;
1334 if (isLess || isGreater) {
1335 Standard_Real aDPar, aNbPer;
1336 aDPar = (isLess) ? (aMaxVal - Uparameter) : (aMinVal - Uparameter);
1337 modf(aDPar / Period, &aNbPer);
1338 Uparameter += aNbPer * Period;
1342 aMaxVal = vfknots->Value(vfknots->Upper() - vdeg);
1343 aMinVal = vfknots->Value (vdeg + 1);
1344 Standard_Real eps = Abs(Epsilon(Vparameter));
1345 Period = aMaxVal - aMinVal;
1348 throw Standard_OutOfRange("Geom_BSplineSurface::PeriodicNormalization: Vparameter is too great number");
1350 Standard_Boolean isLess, isGreater;
1351 isLess = aMinVal - Vparameter > 0;
1352 isGreater = Vparameter - aMaxVal > 0;
1353 if (isLess || isGreater) {
1354 Standard_Real aDPar, aNbPer;
1355 aDPar = (isLess) ? (aMaxVal - Vparameter) : (aMinVal - Vparameter);
1356 modf(aDPar / Period, &aNbPer);
1357 Vparameter += aNbPer * Period;
1362 //=======================================================================
1363 //function : SetWeight
1365 //=======================================================================
1367 void Geom_BSplineSurface::SetWeight (const Standard_Integer UIndex,
1368 const Standard_Integer VIndex,
1369 const Standard_Real Weight)
1371 if (Weight <= gp::Resolution()) throw Standard_ConstructionError();
1372 TColStd_Array2OfReal & Weights = weights->ChangeArray2();
1373 if (UIndex < 1 || UIndex > Weights.ColLength() ||
1374 VIndex < 1 || VIndex > Weights.RowLength() ) {
1375 throw Standard_OutOfRange();
1377 Weights (UIndex+Weights.LowerRow()-1, VIndex+Weights.LowerCol()-1) = Weight;
1378 Rational(Weights, urational, vrational);
1381 //=======================================================================
1382 //function : SetWeightCol
1384 //=======================================================================
1386 void Geom_BSplineSurface::SetWeightCol
1387 (const Standard_Integer VIndex,
1388 const TColStd_Array1OfReal& CPoleWeights)
1390 TColStd_Array2OfReal & Weights = weights->ChangeArray2();
1391 if (VIndex < 1 || VIndex > Weights.RowLength()) {
1392 throw Standard_OutOfRange();
1394 if (CPoleWeights.Lower() < 1 ||
1395 CPoleWeights.Lower() > Weights.ColLength() ||
1396 CPoleWeights.Upper() < 1 ||
1397 CPoleWeights.Upper() > Weights.ColLength() ) {
1398 throw Standard_ConstructionError();
1400 Standard_Integer I = CPoleWeights.Lower();
1401 while (I <= CPoleWeights.Upper()) {
1402 if (CPoleWeights(I) <= gp::Resolution()) {
1403 throw Standard_ConstructionError();
1405 Weights (I+Weights.LowerRow()-1, VIndex+Weights.LowerCol()-1) =
1409 // Verifie si c'est rationnel
1410 Rational(Weights, urational, vrational);
1413 //=======================================================================
1414 //function : SetWeightRow
1416 //=======================================================================
1418 void Geom_BSplineSurface::SetWeightRow
1419 (const Standard_Integer UIndex,
1420 const TColStd_Array1OfReal& CPoleWeights)
1422 TColStd_Array2OfReal & Weights = weights->ChangeArray2();
1423 if (UIndex < 1 || UIndex > Weights.ColLength()) {
1424 throw Standard_OutOfRange();
1426 if (CPoleWeights.Lower() < 1 ||
1427 CPoleWeights.Lower() > Weights.RowLength() ||
1428 CPoleWeights.Upper() < 1 ||
1429 CPoleWeights.Upper() > Weights.RowLength() ) {
1431 throw Standard_ConstructionError();
1433 Standard_Integer I = CPoleWeights.Lower();
1435 while (I <= CPoleWeights.Upper()) {
1436 if (CPoleWeights(I)<=gp::Resolution()) {
1437 throw Standard_ConstructionError();
1439 Weights (UIndex+Weights.LowerRow()-1, I+Weights.LowerCol()-1) =
1443 // Verifie si c'est rationnel
1444 Rational(Weights, urational, vrational);