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: invalid degree");
67 if (SPoles.ColLength () < 2 || SPoles.RowLength () < 2) {
68 throw Standard_ConstructionError("Geom_BSplineSurface: at least 2 poles required");
71 if (SUKnots.Length() != SUMults.Length() ||
72 SVKnots.Length() != SVMults.Length()) {
73 throw Standard_ConstructionError("Geom_BSplineSurface: Knot and Mult array size mismatch");
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: UKnots interval values too close");
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: VKnots interval values too close");
89 if (SPoles.ColLength() != BSplCLib::NbPoles(UDegree,UPeriodic,SUMults))
90 throw Standard_ConstructionError("Geom_BSplineSurface: # U Poles and degree mismatch");
92 if (SPoles.RowLength() != BSplCLib::NbPoles(VDegree,VPeriodic,SVMults))
93 throw Standard_ConstructionError("Geom_BSplineSurface: # V Poles and degree mismatch");
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: U Weights and Poles array size mismatch");
242 if (Weights.RowLength() != Poles.RowLength())
243 throw Standard_ConstructionError("Geom_BSplineSurface: V Weights and Poles array size mismatch");
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: Weights values too small");
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("Geom_BSplineSurface::IncreaseDegree: bad U degree value");
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("Geom_BSplineSurface::IncreaseDegree: bad V degree value");
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,
540 const Standard_Real EpsU,
541 const Standard_Real EpsV,
542 const Standard_Boolean SegmentInU,
543 const Standard_Boolean SegmentInV)
545 Standard_Real deltaU = U2 - U1;
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 = V2 - V1;
556 Standard_Real aVPeriod = vknots->Last() - vknots->First();
557 if (deltaV - aVPeriod > Precision::PConfusion())
558 throw Standard_DomainError("Geom_BSplineSurface::Segment");
559 if (deltaV > aVPeriod)
563 Standard_Real NewU1, NewU2, NewV1, NewV2;
565 Standard_Integer indexU, indexV;
568 BSplCLib::LocateParameter(udeg, uknots->Array1(), umults->Array1(),
569 U1, uperiodic, uknots->Lower(), uknots->Upper(),
572 BSplCLib::LocateParameter(udeg, uknots->Array1(), umults->Array1(),
573 U2, uperiodic, uknots->Lower(), uknots->Upper(),
576 // inserting the UKnots
577 TColStd_Array1OfReal UKnots(1, 2);
578 TColStd_Array1OfInteger UMults(1, 2);
579 UKnots(1) = Min(NewU1, NewU2);
580 UKnots(2) = Max(NewU1, NewU2);
581 UMults(1) = UMults(2) = udeg;
583 InsertUKnots(UKnots, UMults, EpsU);
587 BSplCLib::LocateParameter(vdeg, vknots->Array1(), vmults->Array1(),
588 V1, vperiodic, vknots->Lower(), vknots->Upper(),
591 BSplCLib::LocateParameter(vdeg, vknots->Array1(), vmults->Array1(),
592 V2, vperiodic, vknots->Lower(), vknots->Upper(),
595 // Inserting the VKnots
596 TColStd_Array1OfReal VKnots(1, 2);
597 TColStd_Array1OfInteger VMults(1, 2);
599 VKnots(1) = Min(NewV1, NewV2);
600 VKnots(2) = Max(NewV1, NewV2);
601 VMults(1) = VMults(2) = vdeg;
602 InsertVKnots(VKnots, VMults, EpsV);
605 if (uperiodic && SegmentInU) { // set the origine at NewU1
606 Standard_Integer index = 0;
607 BSplCLib::LocateParameter(udeg, uknots->Array1(), umults->Array1(),
608 U1, uperiodic, uknots->Lower(), uknots->Upper(),
610 if (Abs(uknots->Value(index + 1) - U) <= EpsU)
616 // compute index1 and index2 to set the new knots and mults
617 Standard_Integer index1U = 0, index2U = 0;
618 Standard_Integer FromU1 = uknots->Lower();
619 Standard_Integer ToU2 = uknots->Upper();
620 BSplCLib::LocateParameter(udeg, uknots->Array1(), umults->Array1(),
621 NewU1, uperiodic, FromU1, ToU2, index1U, U);
622 BSplCLib::LocateParameter(udeg, uknots->Array1(), umults->Array1(),
623 NewU1 + deltaU, uperiodic, FromU1, ToU2, index2U, U);
624 if (Abs(uknots->Value(index2U + 1) - U) <= EpsU)
627 Standard_Integer nbuknots = index2U - index1U + 1;
629 Handle(TColStd_HArray1OfReal)
630 nuknots = new TColStd_HArray1OfReal(1, nbuknots);
631 Handle(TColStd_HArray1OfInteger)
632 numults = new TColStd_HArray1OfInteger(1, nbuknots);
634 Standard_Integer i, k = 1;
635 for (i = index1U; i <= index2U; i++) {
636 nuknots->SetValue(k, uknots->Value(i));
637 numults->SetValue(k, umults->Value(i));
641 numults->SetValue(1, udeg + 1);
642 numults->SetValue(nbuknots, udeg + 1);
645 if (vperiodic&& SegmentInV) { // set the origine at NewV1
646 Standard_Integer index = 0;
647 BSplCLib::LocateParameter(vdeg, vknots->Array1(), vmults->Array1(),
648 V1, vperiodic, vknots->Lower(), vknots->Upper(),
650 if (Abs(vknots->Value(index + 1) - V) <= EpsV)
656 // compute index1 and index2 to set the new knots and mults
657 Standard_Integer index1V = 0, index2V = 0;
658 Standard_Integer FromV1 = vknots->Lower();
659 Standard_Integer ToV2 = vknots->Upper();
660 BSplCLib::LocateParameter(vdeg, vknots->Array1(), vmults->Array1(),
661 NewV1, vperiodic, FromV1, ToV2, index1V, V);
662 BSplCLib::LocateParameter(vdeg, vknots->Array1(), vmults->Array1(),
663 NewV1 + deltaV, vperiodic, FromV1, ToV2, index2V, V);
664 if (Abs(vknots->Value(index2V + 1) - V) <= EpsV)
667 Standard_Integer nbvknots = index2V - index1V + 1;
669 Handle(TColStd_HArray1OfReal)
670 nvknots = new TColStd_HArray1OfReal(1, nbvknots);
671 Handle(TColStd_HArray1OfInteger)
672 nvmults = new TColStd_HArray1OfInteger(1, nbvknots);
675 for (i = index1V; i <= index2V; i++) {
676 nvknots->SetValue(k, vknots->Value(i));
677 nvmults->SetValue(k, vmults->Value(i));
681 nvmults->SetValue(1, vdeg + 1);
682 nvmults->SetValue(nbvknots, vdeg + 1);
686 // compute index1 and index2 to set the new poles and weights
687 Standard_Integer pindex1U
688 = BSplCLib::PoleIndex(udeg, index1U, uperiodic, umults->Array1());
689 Standard_Integer pindex2U
690 = BSplCLib::PoleIndex(udeg, index2U, uperiodic, umults->Array1());
693 pindex2U = Min(pindex2U + 1, poles->ColLength());
695 Standard_Integer nbupoles = pindex2U - pindex1U + 1;
697 // compute index1 and index2 to set the new poles and weights
698 Standard_Integer pindex1V
699 = BSplCLib::PoleIndex(vdeg, index1V, vperiodic, vmults->Array1());
700 Standard_Integer pindex2V
701 = BSplCLib::PoleIndex(vdeg, index2V, vperiodic, vmults->Array1());
704 pindex2V = Min(pindex2V + 1, poles->RowLength());
706 Standard_Integer nbvpoles = pindex2V - pindex1V + 1;
709 Handle(TColStd_HArray2OfReal) nweights;
711 Handle(TColgp_HArray2OfPnt)
712 npoles = new TColgp_HArray2OfPnt(1, nbupoles, 1, nbvpoles);
714 Standard_Integer j, l;
715 if (urational || vrational) {
716 nweights = new TColStd_HArray2OfReal(1, nbupoles, 1, nbvpoles);
717 for (i = pindex1U; i <= pindex2U; i++) {
719 for (j = pindex1V; j <= pindex2V; j++) {
720 npoles->SetValue(k, l, poles->Value(i, j));
721 nweights->SetValue(k, l, weights->Value(i, j));
728 for (i = pindex1U; i <= pindex2U; i++) {
730 for (j = pindex1V; j <= pindex2V; j++) {
731 npoles->SetValue(k, l, poles->Value(i, j));
743 if (urational || vrational)
746 weights = new TColStd_HArray2OfReal(1, poles->ColLength(),
747 1, poles->RowLength(), 1.0);
754 //=======================================================================
757 //=======================================================================
759 void Geom_BSplineSurface::Segment(const Standard_Real U1,
760 const Standard_Real U2,
761 const Standard_Real V1,
762 const Standard_Real V2,
763 const Standard_Real theUTolerance,
764 const Standard_Real theVTolerance)
766 if ((U2 < U1) || (V2 < V1))
767 throw Standard_DomainError("Geom_BSplineSurface::Segment");
769 Standard_Real aMaxU = Max(Abs(U2), Abs(U1));
770 Standard_Real EpsU = Max(Epsilon(aMaxU), theUTolerance);
772 Standard_Real aMaxV = Max(Abs(V2), Abs(V1));
773 Standard_Real EpsV = Max(Epsilon(aMaxV), theVTolerance);
775 segment(U1, U2, V1, V2, EpsU, EpsV, Standard_True, Standard_True);
778 //=======================================================================
779 //function : CheckAndSegment
781 //=======================================================================
783 void Geom_BSplineSurface::CheckAndSegment(const Standard_Real U1,
784 const Standard_Real U2,
785 const Standard_Real V1,
786 const Standard_Real V2,
787 const Standard_Real theUTolerance,
788 const Standard_Real theVTolerance)
791 if ((U2 < U1) || (V2 < V1))
792 throw Standard_DomainError("Geom_BSplineSurface::CheckAndSegment");
794 Standard_Real aMaxU = Max(Abs(U2), Abs(U1));
795 Standard_Real EpsU = Max(Epsilon(aMaxU), theUTolerance);
797 Standard_Real aMaxV = Max(Abs(V2), Abs(V1));
798 Standard_Real EpsV = Max(Epsilon(aMaxV), theVTolerance);
800 Standard_Boolean segment_in_U = Standard_True;
801 Standard_Boolean segment_in_V = Standard_True;
802 segment_in_U = ( Abs(U1 - uknots->Value(uknots->Lower())) > EpsU )
803 || ( Abs(U2 - uknots->Value(uknots->Upper())) > EpsU );
804 segment_in_V = ( Abs(V1 - vknots->Value(vknots->Lower())) > EpsV )
805 || ( Abs(V2 - vknots->Value(vknots->Upper())) > EpsV );
807 segment(U1, U2, V1, V2, EpsU, EpsV, segment_in_U, segment_in_V);
810 //=======================================================================
811 //function : SetUKnot
813 //=======================================================================
815 void Geom_BSplineSurface::SetUKnot
816 (const Standard_Integer UIndex,
817 const Standard_Real K )
819 if (UIndex < 1 || UIndex > uknots->Length())
820 throw Standard_OutOfRange("Geom_BSplineSurface::SetUKnot: Index and #knots mismatch");
822 Standard_Integer NewIndex = UIndex;
823 Standard_Real DU = Abs(Epsilon (K));
825 if (K >= uknots->Value (2) - DU)
826 throw Standard_ConstructionError("Geom_BSplineSurface::SetUKnot: K out of range");
828 else if (UIndex == uknots->Length()) {
829 if (K <= uknots->Value (uknots->Length()-1) + DU) {
830 throw Standard_ConstructionError("Geom_BSplineSurface::SetUKnot: K out of range");
834 if (K <= uknots->Value (NewIndex-1) + DU ||
835 K >= uknots->Value (NewIndex+1) - DU ) {
836 throw Standard_ConstructionError("Geom_BSplineSurface::SetUKnot: K out of range");
840 if (K != uknots->Value (NewIndex)) {
841 uknots->SetValue (NewIndex, K);
847 //=======================================================================
848 //function : SetUKnots
850 //=======================================================================
852 void Geom_BSplineSurface::SetUKnots (const TColStd_Array1OfReal& UK) {
854 Standard_Integer Lower = UK.Lower();
855 Standard_Integer Upper = UK.Upper();
856 if (Lower < 1 || Lower > uknots->Length() ||
857 Upper < 1 || Upper > uknots->Length() ) {
858 throw Standard_OutOfRange("Geom_BSplineSurface::SetUKnots: invalid array dimension");
861 if (Abs (UK (Lower) - uknots->Value (Lower-1)) <= gp::Resolution()) {
862 throw Standard_ConstructionError("Geom_BSplineSurface::SetUKnots: invalid knot value");
865 if (Upper < uknots->Length ()) {
866 if (Abs (UK (Upper) - uknots->Value (Upper+1)) <= gp::Resolution()) {
867 throw Standard_ConstructionError("Geom_BSplineSurface::SetUKnots: invalid knot value");
870 Standard_Real K1 = UK (Lower);
871 for (Standard_Integer i = Lower; i <= Upper; i++) {
872 uknots->SetValue (i, UK(i));
874 if (Abs (UK(i) - K1) <= gp::Resolution()) {
875 throw Standard_ConstructionError("Geom_BSplineSurface::SetUKnots: invalid knot value");
885 //=======================================================================
886 //function : SetUKnot
888 //=======================================================================
890 void Geom_BSplineSurface::SetUKnot
891 (const Standard_Integer UIndex,
892 const Standard_Real K,
893 const Standard_Integer M)
895 IncreaseUMultiplicity (UIndex, M);
896 SetUKnot (UIndex, K);
899 //=======================================================================
900 //function : SetVKnot
902 //=======================================================================
904 void Geom_BSplineSurface::SetVKnot
905 (const Standard_Integer VIndex,
906 const Standard_Real K)
908 if (VIndex < 1 || VIndex > vknots->Length())
909 throw Standard_OutOfRange("Geom_BSplineSurface::SetVKnot: Index and #knots mismatch");
910 Standard_Integer NewIndex = VIndex + vknots->Lower() - 1;
911 Standard_Real DV = Abs(Epsilon (K));
913 if (K >= vknots->Value (2) - DV) {
914 throw Standard_ConstructionError("Geom_BSplineSurface::SetVKnot: K out of range");
917 else if (VIndex == vknots->Length()) {
918 if (K <= vknots->Value (vknots->Length()-1) + DV) {
919 throw Standard_ConstructionError("Geom_BSplineSurface::SetVKnot: K out of range");
923 if (K <= vknots->Value (NewIndex-1) + DV ||
924 K >= vknots->Value (NewIndex+1) - DV ) {
925 throw Standard_ConstructionError("Geom_BSplineSurface::SetVKnot: K out of range");
929 if (K != vknots->Value (NewIndex)) {
930 vknots->SetValue (NewIndex, K);
936 //=======================================================================
937 //function : SetVKnots
939 //=======================================================================
941 void Geom_BSplineSurface::SetVKnots (const TColStd_Array1OfReal& VK) {
943 Standard_Integer Lower = VK.Lower();
944 Standard_Integer Upper = VK.Upper();
945 if (Lower < 1 || Lower > vknots->Length() ||
946 Upper < 1 || Upper > vknots->Length() ) {
947 throw Standard_OutOfRange("Geom_BSplineSurface::SetVKnots: invalid array dimension");
950 if (Abs (VK (Lower) - vknots->Value (Lower-1)) <= gp::Resolution()) {
951 throw Standard_ConstructionError("Geom_BSplineSurface::SetVKnots: invalid knot value");
954 if (Upper < vknots->Length ()) {
955 if (Abs (VK (Upper) - vknots->Value (Upper+1)) <= gp::Resolution()) {
956 throw Standard_ConstructionError("Geom_BSplineSurface::SetVKnots: invalid knot value");
959 Standard_Real K1 = VK (Lower);
960 for (Standard_Integer i = Lower; i <= Upper; i++) {
961 vknots->SetValue (i, VK(i));
963 if (Abs (VK(i) - K1) <= gp::Resolution()) {
964 throw Standard_ConstructionError("Geom_BSplineSurface::SetVKnots: invalid knot value");
974 //=======================================================================
975 //function : SetVKnot
977 //=======================================================================
979 void Geom_BSplineSurface::SetVKnot
980 (const Standard_Integer VIndex,
981 const Standard_Real K,
982 const Standard_Integer M)
984 IncreaseVMultiplicity (VIndex, M);
985 SetVKnot (VIndex, K);
988 //=======================================================================
989 //function : InsertUKnot
991 //=======================================================================
993 void Geom_BSplineSurface::InsertUKnot
994 (const Standard_Real U,
995 const Standard_Integer M,
996 const Standard_Real ParametricTolerance,
997 const Standard_Boolean Add)
999 TColStd_Array1OfReal k(1,1);
1001 TColStd_Array1OfInteger m(1,1);
1003 InsertUKnots(k,m,ParametricTolerance,Add);
1006 //=======================================================================
1007 //function : InsertVKnot
1009 //=======================================================================
1011 void Geom_BSplineSurface::InsertVKnot
1012 (const Standard_Real V,
1013 const Standard_Integer M,
1014 const Standard_Real ParametricTolerance,
1015 const Standard_Boolean Add)
1017 TColStd_Array1OfReal k(1,1);
1019 TColStd_Array1OfInteger m(1,1);
1021 InsertVKnots(k,m,ParametricTolerance,Add);
1024 //=======================================================================
1025 //function : IncrementUMultiplicity
1027 //=======================================================================
1029 void Geom_BSplineSurface::IncrementUMultiplicity
1030 (const Standard_Integer FromI1,
1031 const Standard_Integer ToI2,
1032 const Standard_Integer Step)
1034 Handle(TColStd_HArray1OfReal) tk = uknots;
1035 TColStd_Array1OfReal k( (uknots->Array1())(FromI1), FromI1, ToI2);
1036 TColStd_Array1OfInteger m( FromI1, ToI2) ;
1038 InsertUKnots( k, m, Epsilon(1.));
1041 //=======================================================================
1042 //function : IncrementVMultiplicity
1044 //=======================================================================
1046 void Geom_BSplineSurface::IncrementVMultiplicity
1047 (const Standard_Integer FromI1,
1048 const Standard_Integer ToI2,
1049 const Standard_Integer Step)
1051 Handle(TColStd_HArray1OfReal) tk = vknots;
1052 TColStd_Array1OfReal k( (vknots->Array1())(FromI1), FromI1, ToI2);
1054 TColStd_Array1OfInteger m( FromI1, ToI2) ;
1057 InsertVKnots( k, m, Epsilon(1.));
1060 //=======================================================================
1061 //function : UpdateUKnots
1063 //=======================================================================
1065 void Geom_BSplineSurface::UpdateUKnots()
1068 Standard_Integer MaxKnotMult = 0;
1069 BSplCLib::KnotAnalysis (udeg, uperiodic,
1072 uknotSet, MaxKnotMult);
1074 if (uknotSet == GeomAbs_Uniform && !uperiodic) {
1078 ufknots = new TColStd_HArray1OfReal
1079 (1, BSplCLib::KnotSequenceLength(umults->Array1(),udeg,uperiodic));
1081 BSplCLib::KnotSequence (uknots->Array1(),
1084 ufknots->ChangeArray1());
1087 if (MaxKnotMult == 0) Usmooth = GeomAbs_CN;
1089 switch (udeg - MaxKnotMult) {
1090 case 0 : Usmooth = GeomAbs_C0; break;
1091 case 1 : Usmooth = GeomAbs_C1; break;
1092 case 2 : Usmooth = GeomAbs_C2; break;
1093 case 3 : Usmooth = GeomAbs_C3; break;
1094 default : Usmooth = GeomAbs_C3; break;
1099 //=======================================================================
1100 //function : UpdateVKnots
1102 //=======================================================================
1104 void Geom_BSplineSurface::UpdateVKnots()
1106 Standard_Integer MaxKnotMult = 0;
1107 BSplCLib::KnotAnalysis (vdeg, vperiodic,
1110 vknotSet, MaxKnotMult);
1112 if (vknotSet == GeomAbs_Uniform && !vperiodic) {
1116 vfknots = new TColStd_HArray1OfReal
1117 (1, BSplCLib::KnotSequenceLength(vmults->Array1(),vdeg,vperiodic));
1119 BSplCLib::KnotSequence (vknots->Array1(),
1122 vfknots->ChangeArray1());
1125 if (MaxKnotMult == 0) Vsmooth = GeomAbs_CN;
1127 switch (vdeg - MaxKnotMult) {
1128 case 0 : Vsmooth = GeomAbs_C0; break;
1129 case 1 : Vsmooth = GeomAbs_C1; break;
1130 case 2 : Vsmooth = GeomAbs_C2; break;
1131 case 3 : Vsmooth = GeomAbs_C3; break;
1132 default : Vsmooth = GeomAbs_C3; break;
1138 //=======================================================================
1139 //function : Normalizes the parameters if the curve is periodic
1140 //purpose : that is compute the cache so that it is valid
1141 //=======================================================================
1143 void Geom_BSplineSurface::PeriodicNormalization
1144 (Standard_Real& Uparameter,
1145 Standard_Real& Vparameter) const
1147 Standard_Real Period, aMaxVal, aMinVal;
1150 aMaxVal = ufknots->Value(ufknots->Upper() - udeg);
1151 aMinVal = ufknots->Value (udeg + 1);
1152 Standard_Real eps = Abs(Epsilon(Uparameter));
1153 Period = aMaxVal - aMinVal;
1156 throw Standard_OutOfRange("Geom_BSplineSurface::PeriodicNormalization: Uparameter is too great number");
1158 Standard_Boolean isLess, isGreater;
1159 isLess = aMinVal - Uparameter > 0;
1160 isGreater = Uparameter - aMaxVal > 0;
1161 if (isLess || isGreater) {
1162 Standard_Real aDPar, aNbPer;
1163 aDPar = (isLess) ? (aMaxVal - Uparameter) : (aMinVal - Uparameter);
1164 modf(aDPar / Period, &aNbPer);
1165 Uparameter += aNbPer * Period;
1169 aMaxVal = vfknots->Value(vfknots->Upper() - vdeg);
1170 aMinVal = vfknots->Value (vdeg + 1);
1171 Standard_Real eps = Abs(Epsilon(Vparameter));
1172 Period = aMaxVal - aMinVal;
1175 throw Standard_OutOfRange("Geom_BSplineSurface::PeriodicNormalization: Vparameter is too great number");
1177 Standard_Boolean isLess, isGreater;
1178 isLess = aMinVal - Vparameter > 0;
1179 isGreater = Vparameter - aMaxVal > 0;
1180 if (isLess || isGreater) {
1181 Standard_Real aDPar, aNbPer;
1182 aDPar = (isLess) ? (aMaxVal - Vparameter) : (aMinVal - Vparameter);
1183 modf(aDPar / Period, &aNbPer);
1184 Vparameter += aNbPer * Period;
1189 //=======================================================================
1190 //function : SetWeight
1192 //=======================================================================
1194 void Geom_BSplineSurface::SetWeight (const Standard_Integer UIndex,
1195 const Standard_Integer VIndex,
1196 const Standard_Real Weight)
1198 if (Weight <= gp::Resolution())
1199 throw Standard_ConstructionError("Geom_BSplineSurface::SetWeight: Weight too small");
1200 TColStd_Array2OfReal & Weights = weights->ChangeArray2();
1201 if (UIndex < 1 || UIndex > Weights.ColLength() ||
1202 VIndex < 1 || VIndex > Weights.RowLength() ) {
1203 throw Standard_OutOfRange("Geom_BSplineSurface::SetWeight: Index and #pole mismatch");
1205 Weights (UIndex+Weights.LowerRow()-1, VIndex+Weights.LowerCol()-1) = Weight;
1206 Rational(Weights, urational, vrational);
1209 //=======================================================================
1210 //function : SetWeightCol
1212 //=======================================================================
1214 void Geom_BSplineSurface::SetWeightCol
1215 (const Standard_Integer VIndex,
1216 const TColStd_Array1OfReal& CPoleWeights)
1218 TColStd_Array2OfReal & Weights = weights->ChangeArray2();
1219 if (VIndex < 1 || VIndex > Weights.RowLength()) {
1220 throw Standard_OutOfRange("Geom_BSplineSurface::SetWeightCol: Index and #pole mismatch");
1222 if (CPoleWeights.Lower() < 1 ||
1223 CPoleWeights.Lower() > Weights.ColLength() ||
1224 CPoleWeights.Upper() < 1 ||
1225 CPoleWeights.Upper() > Weights.ColLength() ) {
1226 throw Standard_ConstructionError("Geom_BSplineSurface::SetWeightCol: invalid array dimension");
1228 Standard_Integer I = CPoleWeights.Lower();
1229 while (I <= CPoleWeights.Upper()) {
1230 if (CPoleWeights(I) <= gp::Resolution()) {
1231 throw Standard_ConstructionError("Geom_BSplineSurface::SetWeightCol: Weight too small");
1233 Weights (I+Weights.LowerRow()-1, VIndex+Weights.LowerCol()-1) =
1237 // Verifie si c'est rationnel
1238 Rational(Weights, urational, vrational);
1241 //=======================================================================
1242 //function : SetWeightRow
1244 //=======================================================================
1246 void Geom_BSplineSurface::SetWeightRow
1247 (const Standard_Integer UIndex,
1248 const TColStd_Array1OfReal& CPoleWeights)
1250 TColStd_Array2OfReal & Weights = weights->ChangeArray2();
1251 if (UIndex < 1 || UIndex > Weights.ColLength()) {
1252 throw Standard_OutOfRange("Geom_BSplineSurface::SetWeightRow: Index and #pole mismatch");
1254 if (CPoleWeights.Lower() < 1 ||
1255 CPoleWeights.Lower() > Weights.RowLength() ||
1256 CPoleWeights.Upper() < 1 ||
1257 CPoleWeights.Upper() > Weights.RowLength() ) {
1259 throw Standard_ConstructionError("Geom_BSplineSurface::SetWeightRow: invalid array dimension");
1261 Standard_Integer I = CPoleWeights.Lower();
1263 while (I <= CPoleWeights.Upper()) {
1264 if (CPoleWeights(I)<=gp::Resolution()) {
1265 throw Standard_ConstructionError("Geom_BSplineSurface::SetWeightRow: Weight too small");
1267 Weights (UIndex+Weights.LowerRow()-1, I+Weights.LowerCol()-1) =
1271 // Verifie si c'est rationnel
1272 Rational(Weights, urational, vrational);