1 // Created on: 1993-03-09
3 // Copyright (c) 1993-1999 Matra Datavision
4 // Copyright (c) 1999-2012 OPEN CASCADE SAS
6 // The content of this file is subject to the Open CASCADE Technology Public
7 // License Version 6.5 (the "License"). You may not use the content of this file
8 // except in compliance with the License. Please obtain a copy of the License
9 // at http://www.opencascade.org and read it completely before using this file.
11 // The Initial Developer of the Original Code is Open CASCADE S.A.S., having its
12 // main offices at: 1, place des Freres Montgolfier, 78280 Guyancourt, France.
14 // The Original Code and all software distributed under the License is
15 // distributed on an "AS IS" basis, without warranty of any kind, and the
16 // Initial Developer hereby disclaims all such warranties, including without
17 // limitation, any warranties of merchantability, fitness for a particular
18 // purpose or non-infringement. Please see the License for the specific terms
19 // and conditions governing the rights and limitations under the License.
22 //Avril 1991 : constructeurs + methodes de lecture.
23 //Mai 1991 : revue des specifs + debut de realisation des classes tool =>
24 // implementation des methodes Set et calcul du point courant.
25 //Juillet 1991 : voir egalement File Geom_BSplineCurve_1.cxx
26 //Juin 1992 : mise a plat des valeurs nodales - amelioration des
27 // performances sur calcul du point courant
29 //RLE Aug 1993 Remove Swaps, Remove typedefs, Update BSplCLib
30 // debug periodic, IncreaseDegree
31 // 21-Mar-95 : xab implemented cache
32 // 14-Mar-96 : xab implemented MovePointAndTangent
33 // 13-Oct-96 : pmn Bug dans SetPeriodic (PRO6088) et Segment (PRO6250)
35 #define No_Standard_OutOfRange
37 #include <Geom_BSplineCurve.ixx>
40 #include <BSplCLib.hxx>
41 #include <BSplCLib_KnotDistribution.hxx>
42 #include <BSplCLib_MultDistribution.hxx>
43 #include <Standard_NotImplemented.hxx>
44 #include <Standard_ConstructionError.hxx>
45 #include <Standard_OutOfRange.hxx>
46 #include <Standard_Real.hxx>
48 //=======================================================================
49 //function : CheckCurveData
50 //purpose : Internal use only
51 //=======================================================================
53 static void CheckCurveData
54 (const TColgp_Array1OfPnt& CPoles,
55 const TColStd_Array1OfReal& CKnots,
56 const TColStd_Array1OfInteger& CMults,
57 const Standard_Integer Degree,
58 const Standard_Boolean Periodic)
60 if (Degree < 1 || Degree > Geom_BSplineCurve::MaxDegree()) {
61 Standard_ConstructionError::Raise();
64 if (CPoles.Length() < 2) Standard_ConstructionError::Raise();
65 if (CKnots.Length() != CMults.Length()) Standard_ConstructionError::Raise();
67 for (Standard_Integer I = CKnots.Lower(); I < CKnots.Upper(); I++) {
68 if (CKnots (I+1) - CKnots (I) <= Epsilon (Abs(CKnots (I)))) {
69 Standard_ConstructionError::Raise();
73 if (CPoles.Length() != BSplCLib::NbPoles(Degree,Periodic,CMults))
74 Standard_ConstructionError::Raise();
77 //=======================================================================
78 //function : KnotAnalysis
79 //purpose : Internal use only
80 //=======================================================================
82 static void KnotAnalysis
83 (const Standard_Integer Degree,
84 const Standard_Boolean Periodic,
85 const TColStd_Array1OfReal& CKnots,
86 const TColStd_Array1OfInteger& CMults,
87 GeomAbs_BSplKnotDistribution& KnotForm,
88 Standard_Integer& MaxKnotMult)
90 KnotForm = GeomAbs_NonUniform;
92 BSplCLib_KnotDistribution KSet =
93 BSplCLib::KnotForm (CKnots, 1, CKnots.Length());
96 if (KSet == BSplCLib_Uniform) {
97 BSplCLib_MultDistribution MSet =
98 BSplCLib::MultForm (CMults, 1, CMults.Length());
100 case BSplCLib_NonConstant :
102 case BSplCLib_Constant :
103 if (CKnots.Length() == 2) {
104 KnotForm = GeomAbs_PiecewiseBezier;
107 if (CMults (1) == 1) KnotForm = GeomAbs_Uniform;
110 case BSplCLib_QuasiConstant :
111 if (CMults (1) == Degree + 1) {
112 Standard_Real M = CMults (2);
113 if (M == Degree ) KnotForm = GeomAbs_PiecewiseBezier;
114 else if (M == 1) KnotForm = GeomAbs_QuasiUniform;
120 Standard_Integer FirstKM =
121 Periodic ? CKnots.Lower() : BSplCLib::FirstUKnotIndex (Degree,CMults);
122 Standard_Integer LastKM =
123 Periodic ? CKnots.Upper() : BSplCLib::LastUKnotIndex (Degree,CMults);
125 if (LastKM - FirstKM != 1) {
126 Standard_Integer Multi;
127 for (Standard_Integer i = FirstKM + 1; i < LastKM; i++) {
129 MaxKnotMult = Max (MaxKnotMult, Multi);
134 //=======================================================================
135 //function : Rational
136 //purpose : check rationality of an array of weights
137 //=======================================================================
139 static Standard_Boolean Rational(const TColStd_Array1OfReal& W)
141 Standard_Integer i, n = W.Length();
142 Standard_Boolean rat = Standard_False;
143 for (i = 1; i < n; i++) {
144 rat = Abs(W(i) - W(i+1)) > gp::Resolution();
150 //=======================================================================
153 //=======================================================================
155 Handle(Geom_Geometry) Geom_BSplineCurve::Copy() const
157 Handle(Geom_BSplineCurve) C;
159 C = new Geom_BSplineCurve(poles->Array1(),
165 C = new Geom_BSplineCurve(poles->Array1(),
172 //=======================================================================
173 //function : Geom_BSplineCurve
175 //=======================================================================
177 Geom_BSplineCurve::Geom_BSplineCurve
178 (const TColgp_Array1OfPnt& Poles,
179 const TColStd_Array1OfReal& Knots,
180 const TColStd_Array1OfInteger& Mults,
181 const Standard_Integer Degree,
182 const Standard_Boolean Periodic) :
183 rational(Standard_False),
186 maxderivinvok(Standard_False)
190 CheckCurveData (Poles,
199 poles = new TColgp_HArray1OfPnt(1,Poles.Length());
200 poles->ChangeArray1() = Poles;
203 knots = new TColStd_HArray1OfReal(1,Knots.Length());
204 knots->ChangeArray1() = Knots;
206 mults = new TColStd_HArray1OfInteger(1,Mults.Length());
207 mults->ChangeArray1() = Mults;
210 cachepoles = new TColgp_HArray1OfPnt(1,Degree + 1);
211 parametercache = 0.0e0 ;
212 spanlenghtcache = 0.0e0 ;
217 //=======================================================================
218 //function : Geom_BSplineCurve
220 //=======================================================================
222 Geom_BSplineCurve::Geom_BSplineCurve
223 (const TColgp_Array1OfPnt& Poles,
224 const TColStd_Array1OfReal& Weights,
225 const TColStd_Array1OfReal& Knots,
226 const TColStd_Array1OfInteger& Mults,
227 const Standard_Integer Degree,
228 const Standard_Boolean Periodic,
229 const Standard_Boolean CheckRational) :
230 rational(Standard_True),
233 maxderivinvok(Standard_False)
239 CheckCurveData (Poles,
245 if (Weights.Length() != Poles.Length())
246 Standard_ConstructionError::Raise("Geom_BSplineCurve");
249 for (i = Weights.Lower(); i <= Weights.Upper(); i++) {
250 if (Weights(i) <= gp::Resolution())
251 Standard_ConstructionError::Raise("Geom_BSplineCurve");
254 // check really rational
256 rational = Rational(Weights);
260 poles = new TColgp_HArray1OfPnt(1,Poles.Length());
261 poles->ChangeArray1() = Poles;
262 cachepoles = new TColgp_HArray1OfPnt(1,Degree + 1);
264 weights = new TColStd_HArray1OfReal(1,Weights.Length());
265 weights->ChangeArray1() = Weights;
266 cacheweights = new TColStd_HArray1OfReal(1,Degree + 1);
269 knots = new TColStd_HArray1OfReal(1,Knots.Length());
270 knots->ChangeArray1() = Knots;
272 mults = new TColStd_HArray1OfInteger(1,Mults.Length());
273 mults->ChangeArray1() = Mults;
276 parametercache = 0.0e0 ;
277 spanlenghtcache = 0.0e0 ;
281 //=======================================================================
282 //function : MaxDegree
284 //=======================================================================
286 Standard_Integer Geom_BSplineCurve::MaxDegree ()
288 return BSplCLib::MaxDegree();
291 //=======================================================================
292 //function : IncreaseDegree
294 //=======================================================================
296 void Geom_BSplineCurve::IncreaseDegree (const Standard_Integer Degree)
298 if (Degree == deg) return;
300 if (Degree < deg || Degree > Geom_BSplineCurve::MaxDegree()) {
301 Standard_ConstructionError::Raise();
303 Standard_Integer FromK1 = FirstUKnotIndex ();
304 Standard_Integer ToK2 = LastUKnotIndex ();
306 Standard_Integer Step = Degree - deg;
308 Handle(TColgp_HArray1OfPnt) npoles = new
309 TColgp_HArray1OfPnt(1,poles->Length() + Step * (ToK2-FromK1));
311 Standard_Integer nbknots = BSplCLib::IncreaseDegreeCountKnots
312 (deg,Degree,periodic,mults->Array1());
314 Handle(TColStd_HArray1OfReal) nknots =
315 new TColStd_HArray1OfReal(1,nbknots);
317 Handle(TColStd_HArray1OfInteger) nmults =
318 new TColStd_HArray1OfInteger(1,nbknots);
320 Handle(TColStd_HArray1OfReal) nweights;
324 nweights = new TColStd_HArray1OfReal(1,npoles->Upper());
326 BSplCLib::IncreaseDegree
327 (deg,Degree, periodic,
328 poles->Array1(),weights->Array1(),
329 knots->Array1(),mults->Array1(),
330 npoles->ChangeArray1(),nweights->ChangeArray1(),
331 nknots->ChangeArray1(),nmults->ChangeArray1());
334 BSplCLib::IncreaseDegree
335 (deg,Degree, periodic,
336 poles->Array1(),BSplCLib::NoWeights(),
337 knots->Array1(),mults->Array1(),
338 npoles->ChangeArray1(),
339 *((TColStd_Array1OfReal*) NULL),
340 nknots->ChangeArray1(),nmults->ChangeArray1());
352 //=======================================================================
353 //function : IncreaseMultiplicity
355 //=======================================================================
357 void Geom_BSplineCurve::IncreaseMultiplicity (const Standard_Integer Index,
358 const Standard_Integer M)
360 TColStd_Array1OfReal k(1,1);
361 k(1) = knots->Value(Index);
362 TColStd_Array1OfInteger m(1,1);
363 m(1) = M - mults->Value(Index);
364 InsertKnots(k,m,Epsilon(1.),Standard_True);
367 //=======================================================================
368 //function : IncreaseMultiplicity
370 //=======================================================================
372 void Geom_BSplineCurve::IncreaseMultiplicity (const Standard_Integer I1,
373 const Standard_Integer I2,
374 const Standard_Integer M)
376 Handle(TColStd_HArray1OfReal) tk = knots;
377 TColStd_Array1OfReal k((knots->Array1())(I1),I1,I2);
378 TColStd_Array1OfInteger m(I1,I2);
380 for (i = I1; i <= I2; i++)
381 m(i) = M - mults->Value(i);
382 InsertKnots(k,m,Epsilon(1.),Standard_True);
385 //=======================================================================
386 //function : IncrementMultiplicity
388 //=======================================================================
390 void Geom_BSplineCurve::IncrementMultiplicity
391 (const Standard_Integer I1,
392 const Standard_Integer I2,
393 const Standard_Integer Step)
395 Handle(TColStd_HArray1OfReal) tk = knots;
396 TColStd_Array1OfReal k((knots->Array1())(I1),I1,I2);
397 TColStd_Array1OfInteger m(I1,I2) ;
399 InsertKnots(k,m,Epsilon(1.),Standard_True);
402 //=======================================================================
403 //function : InsertKnot
405 //=======================================================================
407 void Geom_BSplineCurve::InsertKnot
408 (const Standard_Real U,
409 const Standard_Integer M,
410 const Standard_Real ParametricTolerance,
411 const Standard_Boolean Add)
413 TColStd_Array1OfReal k(1,1);
415 TColStd_Array1OfInteger m(1,1);
417 InsertKnots(k,m,ParametricTolerance,Add);
420 //=======================================================================
421 //function : InsertKnots
423 //=======================================================================
425 void Geom_BSplineCurve::InsertKnots(const TColStd_Array1OfReal& Knots,
426 const TColStd_Array1OfInteger& Mults,
427 const Standard_Real Epsilon,
428 const Standard_Boolean Add)
430 // Check and compute new sizes
431 Standard_Integer nbpoles,nbknots;
433 if (!BSplCLib::PrepareInsertKnots(deg,periodic,
434 knots->Array1(),mults->Array1(),
435 Knots,Mults,nbpoles,nbknots,Epsilon,Add))
436 Standard_ConstructionError::Raise("Geom_BSplineCurve::InsertKnots");
438 if (nbpoles == poles->Length()) return;
440 Handle(TColgp_HArray1OfPnt) npoles = new TColgp_HArray1OfPnt(1,nbpoles);
441 Handle(TColStd_HArray1OfReal) nknots = knots;
442 Handle(TColStd_HArray1OfInteger) nmults = mults;
444 if (nbknots != knots->Length()) {
445 nknots = new TColStd_HArray1OfReal(1,nbknots);
446 nmults = new TColStd_HArray1OfInteger(1,nbknots);
450 Handle(TColStd_HArray1OfReal) nweights =
451 new TColStd_HArray1OfReal(1,nbpoles);
452 BSplCLib::InsertKnots(deg,periodic,
453 poles->Array1(), weights->Array1(),
454 knots->Array1(), mults->Array1(),
456 npoles->ChangeArray1(), nweights->ChangeArray1(),
457 nknots->ChangeArray1(), nmults->ChangeArray1(),
462 BSplCLib::InsertKnots(deg,periodic,
463 poles->Array1(), BSplCLib::NoWeights(),
464 knots->Array1(), mults->Array1(),
466 npoles->ChangeArray1(),
467 *((TColStd_Array1OfReal*) NULL),
468 nknots->ChangeArray1(), nmults->ChangeArray1(),
479 //=======================================================================
480 //function : RemoveKnot
482 //=======================================================================
484 Standard_Boolean Geom_BSplineCurve::RemoveKnot(const Standard_Integer Index,
485 const Standard_Integer M,
486 const Standard_Real Tolerance)
488 if (M < 0) return Standard_True;
490 Standard_Integer I1 = FirstUKnotIndex ();
491 Standard_Integer I2 = LastUKnotIndex ();
493 if ( !periodic && (Index <= I1 || Index >= I2) ) {
494 Standard_OutOfRange::Raise();
496 else if ( periodic && (Index < I1 || Index > I2)) {
497 Standard_OutOfRange::Raise();
500 const TColgp_Array1OfPnt & oldpoles = poles->Array1();
502 Standard_Integer step = mults->Value(Index) - M;
503 if (step <= 0) return Standard_True;
505 Handle(TColgp_HArray1OfPnt) npoles =
506 new TColgp_HArray1OfPnt(1,oldpoles.Length()-step);
508 Handle(TColStd_HArray1OfReal) nknots = knots;
509 Handle(TColStd_HArray1OfInteger) nmults = mults;
512 nknots = new TColStd_HArray1OfReal(1,knots->Length()-1);
513 nmults = new TColStd_HArray1OfInteger(1,knots->Length()-1);
517 Handle(TColStd_HArray1OfReal) nweights =
518 new TColStd_HArray1OfReal(1,npoles->Length());
519 if (!BSplCLib::RemoveKnot
520 (Index, M, deg, periodic,
521 poles->Array1(),weights->Array1(),
522 knots->Array1(),mults->Array1(),
523 npoles->ChangeArray1(), nweights->ChangeArray1(),
524 nknots->ChangeArray1(),nmults->ChangeArray1(),
526 return Standard_False;
530 if (!BSplCLib::RemoveKnot
531 (Index, M, deg, periodic,
532 poles->Array1(), BSplCLib::NoWeights(),
533 knots->Array1(),mults->Array1(),
534 npoles->ChangeArray1(),
535 *((TColStd_Array1OfReal*) NULL),
536 nknots->ChangeArray1(),nmults->ChangeArray1(),
538 return Standard_False;
547 return Standard_True;
550 //=======================================================================
553 //=======================================================================
555 void Geom_BSplineCurve::Reverse ()
557 BSplCLib::Reverse(knots->ChangeArray1());
558 BSplCLib::Reverse(mults->ChangeArray1());
559 Standard_Integer last;
561 last = flatknots->Upper() - deg - 1;
563 last = poles->Upper();
564 BSplCLib::Reverse(poles->ChangeArray1(),last);
566 BSplCLib::Reverse(weights->ChangeArray1(),last);
570 //=======================================================================
571 //function : ReversedParameter
573 //=======================================================================
575 Standard_Real Geom_BSplineCurve::ReversedParameter
576 (const Standard_Real U) const
578 return (FirstParameter() + LastParameter() - U);
581 //=======================================================================
584 //=======================================================================
586 void Geom_BSplineCurve::Segment(const Standard_Real U1,
587 const Standard_Real U2)
589 Standard_DomainError_Raise_if ( U2 < U1,
590 "Geom_BSplineCurve::Segment");
592 Standard_Real NewU1, NewU2;
593 Standard_Real U,DU=0,aDDU=0;
594 Standard_Integer index;
595 Standard_Boolean wasPeriodic = periodic;
597 TColStd_Array1OfReal Knots(1,2);
598 TColStd_Array1OfInteger Mults(1,2);
600 // define param ditance to keep (eap, Apr 18 2002, occ311)
602 Standard_Real Period = LastParameter() - FirstParameter();
606 if (DU <= Epsilon(Period))
612 BSplCLib::LocateParameter(deg,knots->Array1(),mults->Array1(),
613 U1,periodic,knots->Lower(),knots->Upper(),
616 BSplCLib::LocateParameter(deg,knots->Array1(),mults->Array1(),
617 U2,periodic,knots->Lower(),knots->Upper(),
621 Standard_Real aNu2 = NewU2;
625 Knots( 1) = Min( NewU1, NewU2);
626 Knots( 2) = Max( NewU1, NewU2);
627 Mults( 1) = Mults( 2) = deg;
629 Standard_Real AbsUMax = Max(Abs(NewU1),Abs(NewU2));
631 // Modified by Sergey KHROMOV - Fri Apr 11 12:15:40 2003 Begin
632 AbsUMax = Max(AbsUMax, Max(Abs(FirstParameter()),Abs(LastParameter())));
633 // Modified by Sergey KHROMOV - Fri Apr 11 12:15:40 2003 End
635 Standard_Real Eps = 100. * Epsilon(AbsUMax);
637 InsertKnots( Knots, Mults, Eps);
639 if (periodic) { // set the origine at NewU1
641 BSplCLib::LocateParameter(deg,knots->Array1(),mults->Array1(),
642 U1,periodic,knots->Lower(),knots->Upper(),
644 // Test si l'insertion est Ok et decalage sinon.
645 if ( Abs(knots->Value(index+1)-U) <= Eps) // <= pour etre homogene a InsertKnots
652 // compute index1 and index2 to set the new knots and mults
653 Standard_Integer index1 = 0, index2 = 0;
654 Standard_Integer FromU1 = knots->Lower();
655 Standard_Integer ToU2 = knots->Upper();
656 BSplCLib::LocateParameter(deg,knots->Array1(),mults->Array1(),
657 NewU1,periodic,FromU1,ToU2,index1,U);
658 if ( Abs(knots->Value(index1+1)-U) <= Eps)
661 BSplCLib::LocateParameter(deg,knots->Array1(),mults->Array1(),
662 NewU2,periodic,FromU1,ToU2,index2,U);
663 if ( Abs(knots->Value(index2+1)-U) <= Eps)
666 Standard_Integer nbknots = index2 - index1 + 1;
668 Handle(TColStd_HArray1OfReal)
669 nknots = new TColStd_HArray1OfReal(1,nbknots);
670 Handle(TColStd_HArray1OfInteger)
671 nmults = new TColStd_HArray1OfInteger(1,nbknots);
673 // to restore changed U1
674 if (DU > 0) // if was periodic
677 Standard_Integer i , k = 1;
678 for ( i = index1; i<= index2; i++) {
679 nknots->SetValue(k, knots->Value(i) - DU);
680 nmults->SetValue(k, mults->Value(i));
683 nmults->SetValue( 1, deg + 1);
684 nmults->SetValue(nbknots, deg + 1);
687 // compute index1 and index2 to set the new poles and weights
688 Standard_Integer pindex1
689 = BSplCLib::PoleIndex(deg,index1,periodic,mults->Array1());
690 Standard_Integer pindex2
691 = BSplCLib::PoleIndex(deg,index2,periodic,mults->Array1());
694 pindex2 = Min( pindex2+1, poles->Length());
696 Standard_Integer nbpoles = pindex2 - pindex1 + 1;
698 Handle(TColStd_HArray1OfReal)
699 nweights = new TColStd_HArray1OfReal(1,nbpoles);
700 Handle(TColgp_HArray1OfPnt)
701 npoles = new TColgp_HArray1OfPnt(1,nbpoles);
705 nweights = new TColStd_HArray1OfReal( 1, nbpoles);
706 for ( i = pindex1; i <= pindex2; i++) {
707 npoles->SetValue(k, poles->Value(i));
708 nweights->SetValue(k, weights->Value(i));
713 for ( i = pindex1; i <= pindex2; i++) {
714 npoles->SetValue(k, poles->Value(i));
721 nknots->ChangeValue(nknots->Lower()) = U1;
723 nknots->ChangeValue(nknots->Upper()) = U1 + aDDU;
738 //=======================================================================
741 //=======================================================================
743 void Geom_BSplineCurve::SetKnot
744 (const Standard_Integer Index,
745 const Standard_Real K)
747 if (Index < 1 || Index > knots->Length()) Standard_OutOfRange::Raise();
748 Standard_Real DK = Abs(Epsilon (K));
750 if (K >= knots->Value(2) - DK) Standard_ConstructionError::Raise();
752 else if (Index == knots->Length()) {
753 if (K <= knots->Value (knots->Length()-1) + DK) {
754 Standard_ConstructionError::Raise();
758 if (K <= knots->Value(Index-1) + DK ||
759 K >= knots->Value(Index+1) - DK ) {
760 Standard_ConstructionError::Raise();
763 if (K != knots->Value (Index)) {
764 knots->SetValue (Index, K);
770 //=======================================================================
771 //function : SetKnots
773 //=======================================================================
775 void Geom_BSplineCurve::SetKnots
776 (const TColStd_Array1OfReal& K)
778 CheckCurveData(poles->Array1(),K,mults->Array1(),deg,periodic);
779 knots->ChangeArray1() = K;
784 //=======================================================================
787 //=======================================================================
789 void Geom_BSplineCurve::SetKnot
790 (const Standard_Integer Index,
791 const Standard_Real K,
792 const Standard_Integer M)
794 IncreaseMultiplicity (Index, M);
798 //=======================================================================
799 //function : SetPeriodic
801 //=======================================================================
803 void Geom_BSplineCurve::SetPeriodic ()
805 Standard_Integer first = FirstUKnotIndex();
806 Standard_Integer last = LastUKnotIndex();
808 Handle(TColStd_HArray1OfReal) tk = knots;
809 TColStd_Array1OfReal cknots((knots->Array1())(first),first,last);
810 knots = new TColStd_HArray1OfReal(1,cknots.Length());
811 knots->ChangeArray1() = cknots;
813 Handle(TColStd_HArray1OfInteger) tm = mults;
814 TColStd_Array1OfInteger cmults((mults->Array1())(first),first,last);
815 cmults(first) = cmults(last) = Min(deg, Max( cmults(first), cmults(last)));
816 mults = new TColStd_HArray1OfInteger(1,cmults.Length());
817 mults->ChangeArray1() = cmults;
819 // compute new number of poles;
820 Standard_Integer nbp = BSplCLib::NbPoles(deg,Standard_True,cmults);
822 Handle(TColgp_HArray1OfPnt) tp = poles;
823 TColgp_Array1OfPnt cpoles((poles->Array1())(1),1,nbp);
824 poles = new TColgp_HArray1OfPnt(1,nbp);
825 poles->ChangeArray1() = cpoles;
828 Handle(TColStd_HArray1OfReal) tw = weights;
829 TColStd_Array1OfReal cweights((weights->Array1())(1),1,nbp);
830 weights = new TColStd_HArray1OfReal(1,nbp);
831 weights->ChangeArray1() = cweights;
834 periodic = Standard_True;
840 //=======================================================================
841 //function : SetOrigin
843 //=======================================================================
845 void Geom_BSplineCurve::SetOrigin(const Standard_Integer Index)
847 Standard_NoSuchObject_Raise_if( !periodic,
848 "Geom_BSplineCurve::SetOrigin");
849 Standard_Integer i,k;
850 Standard_Integer first = FirstUKnotIndex();
851 Standard_Integer last = LastUKnotIndex();
853 Standard_DomainError_Raise_if( (Index < first) || (Index > last),
854 "Geom_BSplineCurve::SetOrigine");
856 Standard_Integer nbknots = knots->Length();
857 Standard_Integer nbpoles = poles->Length();
859 Handle(TColStd_HArray1OfReal) nknots =
860 new TColStd_HArray1OfReal(1,nbknots);
861 TColStd_Array1OfReal& newknots = nknots->ChangeArray1();
863 Handle(TColStd_HArray1OfInteger) nmults =
864 new TColStd_HArray1OfInteger(1,nbknots);
865 TColStd_Array1OfInteger& newmults = nmults->ChangeArray1();
867 // set the knots and mults
868 Standard_Real period = knots->Value(last) - knots->Value(first);
870 for ( i = Index; i <= last ; i++) {
871 newknots(k) = knots->Value(i);
872 newmults(k) = mults->Value(i);
875 for ( i = first+1; i <= Index; i++) {
876 newknots(k) = knots->Value(i) + period;
877 newmults(k) = mults->Value(i);
881 Standard_Integer index = 1;
882 for (i = first+1; i <= Index; i++)
883 index += mults->Value(i);
885 // set the poles and weights
886 Handle(TColgp_HArray1OfPnt) npoles =
887 new TColgp_HArray1OfPnt(1,nbpoles);
888 Handle(TColStd_HArray1OfReal) nweights =
889 new TColStd_HArray1OfReal(1,nbpoles);
890 TColgp_Array1OfPnt & newpoles = npoles->ChangeArray1();
891 TColStd_Array1OfReal & newweights = nweights->ChangeArray1();
892 first = poles->Lower();
893 last = poles->Upper();
896 for ( i = index; i <= last; i++) {
897 newpoles(k) = poles->Value(i);
898 newweights(k) = weights->Value(i);
901 for ( i = first; i < index; i++) {
902 newpoles(k) = poles->Value(i);
903 newweights(k) = weights->Value(i);
909 for ( i = index; i <= last; i++) {
910 newpoles(k) = poles->Value(i);
913 for ( i = first; i < index; i++) {
914 newpoles(k) = poles->Value(i);
928 //=======================================================================
929 //function : SetOrigin
931 //=======================================================================
933 void Geom_BSplineCurve::SetOrigin(const Standard_Real U,
934 const Standard_Real Tol)
936 Standard_NoSuchObject_Raise_if( !periodic,
937 "Geom_BSplineCurve::SetOrigin");
938 //U est il dans la period.
939 Standard_Real uf = FirstParameter(), ul = LastParameter();
940 Standard_Real u = U, period = ul - uf;
941 while (Tol < (uf-u)) u += period;
942 while (Tol > (ul-u)) u -= period;
944 if(Abs(U-u)>Tol) { //On reparametre la courbe
945 Standard_Real delta = U-u;
948 TColStd_Array1OfReal& kn = knots->ChangeArray1();
949 Standard_Integer fk = kn.Lower(), lk = kn.Upper();
950 for(Standard_Integer i = fk; i <= lk; i++){
951 kn.ChangeValue(i) += delta;
955 if(Abs(U-uf)<Tol) return;
957 TColStd_Array1OfReal& kn = knots->ChangeArray1();
958 Standard_Integer fk = kn.Lower(), lk = kn.Upper(),ik=0;
959 Standard_Real delta = RealLast();
960 for(Standard_Integer i = fk; i<= lk; i++){
961 Standard_Real dki = kn.Value(i)-U;
962 if(Abs(dki)<Abs(delta)){
974 //=======================================================================
975 //function : SetNotPeriodic
977 //=======================================================================
979 void Geom_BSplineCurve::SetNotPeriodic ()
982 Standard_Integer NbKnots, NbPoles;
983 BSplCLib::PrepareUnperiodize( deg, mults->Array1(),NbKnots,NbPoles);
985 Handle(TColgp_HArray1OfPnt) npoles
986 = new TColgp_HArray1OfPnt(1,NbPoles);
988 Handle(TColStd_HArray1OfReal) nknots
989 = new TColStd_HArray1OfReal(1,NbKnots);
991 Handle(TColStd_HArray1OfInteger) nmults
992 = new TColStd_HArray1OfInteger(1,NbKnots);
994 Handle(TColStd_HArray1OfReal) nweights;
998 nweights = new TColStd_HArray1OfReal(1,NbPoles);
1000 BSplCLib::Unperiodize
1001 (deg,mults->Array1(),knots->Array1(),poles->Array1(),
1002 weights->Array1(),nmults->ChangeArray1(),
1003 nknots->ChangeArray1(),npoles->ChangeArray1(),
1004 nweights->ChangeArray1());
1009 BSplCLib::Unperiodize
1010 (deg,mults->Array1(),knots->Array1(),poles->Array1(),
1011 BSplCLib::NoWeights(),nmults->ChangeArray1(),
1012 nknots->ChangeArray1(),npoles->ChangeArray1(),
1013 *((TColStd_Array1OfReal*) NULL));
1020 periodic = Standard_False;
1027 //=======================================================================
1028 //function : SetPole
1030 //=======================================================================
1032 void Geom_BSplineCurve::SetPole
1033 (const Standard_Integer Index,
1036 if (Index < 1 || Index > poles->Length()) Standard_OutOfRange::Raise();
1037 poles->SetValue (Index, P);
1042 //=======================================================================
1043 //function : SetPole
1045 //=======================================================================
1047 void Geom_BSplineCurve::SetPole
1048 (const Standard_Integer Index,
1050 const Standard_Real W)
1056 //=======================================================================
1057 //function : SetWeight
1059 //=======================================================================
1061 void Geom_BSplineCurve::SetWeight
1062 (const Standard_Integer Index,
1063 const Standard_Real W)
1065 if (Index < 1 || Index > poles->Length()) Standard_OutOfRange::Raise();
1067 if (W <= gp::Resolution ()) Standard_ConstructionError::Raise();
1070 Standard_Boolean rat = IsRational() || (Abs(W - 1.) > gp::Resolution());
1073 if (rat && !IsRational()) {
1074 weights = new TColStd_HArray1OfReal(1,poles->Length());
1078 weights->SetValue (Index, W);
1081 rat = Rational(weights->Array1());
1082 if (!rat) weights.Nullify();
1085 rational = !weights.IsNull();
1091 //=======================================================================
1092 //function : MovePoint
1094 //=======================================================================
1096 void Geom_BSplineCurve::MovePoint(const Standard_Real U,
1098 const Standard_Integer Index1,
1099 const Standard_Integer Index2,
1100 Standard_Integer& FirstModifiedPole,
1101 Standard_Integer& LastmodifiedPole)
1103 if (Index1 < 1 || Index1 > poles->Length() ||
1104 Index2 < 1 || Index2 > poles->Length() || Index1 > Index2) {
1105 Standard_OutOfRange::Raise();
1107 TColgp_Array1OfPnt npoles(1, poles->Length());
1110 gp_Vec Displ(P0, P);
1111 BSplCLib::MovePoint(U, Displ, Index1, Index2, deg, rational, poles->Array1(),
1112 weights->Array1(), flatknots->Array1(),
1113 FirstModifiedPole, LastmodifiedPole, npoles);
1114 if (FirstModifiedPole) {
1115 poles->ChangeArray1() = npoles;
1121 //=======================================================================
1122 //function : MovePointAndTangent
1124 //=======================================================================
1126 void Geom_BSplineCurve::
1127 MovePointAndTangent(const Standard_Real U,
1129 const gp_Vec& Tangent,
1130 const Standard_Real Tolerance,
1131 const Standard_Integer StartingCondition,
1132 const Standard_Integer EndingCondition,
1133 Standard_Integer& ErrorStatus)
1135 Standard_Integer ii ;
1138 // for the time being do not deal with periodic curves
1142 TColgp_Array1OfPnt new_poles(1, poles->Length());
1146 gp_Vec delta_derivative;
1149 gp_Vec delta(P0, P);
1150 for (ii = 1 ; ii <= 3 ; ii++) {
1151 delta_derivative.SetCoord(ii,
1152 Tangent.Coord(ii)- delta_derivative.Coord(ii)) ;
1154 BSplCLib::MovePointAndTangent(U,
1164 flatknots->Array1(),
1168 poles->ChangeArray1() = new_poles;
1174 //=======================================================================
1175 //function : UpdateKnots
1177 //=======================================================================
1179 void Geom_BSplineCurve::UpdateKnots()
1181 rational = !weights.IsNull();
1183 Standard_Integer MaxKnotMult = 0;
1188 knotSet, MaxKnotMult);
1190 if (knotSet == GeomAbs_Uniform && !periodic) {
1194 flatknots = new TColStd_HArray1OfReal
1195 (1, BSplCLib::KnotSequenceLength(mults->Array1(),deg,periodic));
1197 BSplCLib::KnotSequence (knots->Array1(),
1200 flatknots->ChangeArray1());
1203 if (MaxKnotMult == 0) smooth = GeomAbs_CN;
1205 switch (deg - MaxKnotMult) {
1206 case 0 : smooth = GeomAbs_C0; break;
1207 case 1 : smooth = GeomAbs_C1; break;
1208 case 2 : smooth = GeomAbs_C2; break;
1209 case 3 : smooth = GeomAbs_C3; break;
1210 default : smooth = GeomAbs_C3; break;
1216 //=======================================================================
1217 //function : Invalidate the Cache
1218 //purpose : as the name says
1219 //=======================================================================
1221 void Geom_BSplineCurve::InvalidateCache()
1226 //=======================================================================
1227 //function : check if the Cache is valid
1228 //purpose : as the name says
1229 //=======================================================================
1231 Standard_Boolean Geom_BSplineCurve::IsCacheValid
1232 (const Standard_Real U) const
1234 //Roman Lygin 26.12.08, performance improvements
1235 //1. avoided using NewParameter = (U - parametercache) / spanlenghtcache
1236 //to check against [0, 1), as division is CPU consuming
1237 //2. minimized use of if, as branching is also CPU consuming
1238 Standard_Real aDelta = U - parametercache;
1240 return ( validcache &&
1241 (aDelta >= 0.0e0) &&
1242 ((aDelta < spanlenghtcache) || (spanindexcache == flatknots->Upper() - deg)) );
1245 //=======================================================================
1246 //function : Normalizes the parameters if the curve is periodic
1247 //purpose : that is compute the cache so that it is valid
1248 //=======================================================================
1250 void Geom_BSplineCurve::PeriodicNormalization(Standard_Real& Parameter) const
1252 Standard_Real Period ;
1255 Period = flatknots->Value(flatknots->Upper() - deg) - flatknots->Value (deg + 1) ;
1256 while (Parameter > flatknots->Value(flatknots->Upper()-deg)) {
1257 Parameter -= Period ;
1259 while (Parameter < flatknots->Value((deg + 1))) {
1260 Parameter += Period ;
1265 //=======================================================================
1266 //function : Validate the Cache
1267 //purpose : that is compute the cache so that it is valid
1268 //=======================================================================
1270 void Geom_BSplineCurve::ValidateCache(const Standard_Real Parameter)
1272 Standard_Real NewParameter ;
1273 Standard_Integer LocalIndex = 0 ;
1275 // check if the degree did not change
1277 if (cachepoles->Upper() < deg + 1) {
1278 cachepoles = new TColgp_HArray1OfPnt(1,deg + 1);
1280 cacheweights = new TColStd_HArray1OfReal(1,deg + 1);
1283 BSplCLib::LocateParameter(deg,
1284 (flatknots->Array1()),
1285 (BSplCLib::NoMults()),
1290 spanindexcache = LocalIndex ;
1291 if (Parameter == flatknots->Value(LocalIndex + 1)) {
1294 parametercache = flatknots->Value(LocalIndex) ;
1295 if (LocalIndex == flatknots->Upper() - deg) {
1297 // for the last span if the parameter is outside of
1298 // the domain of the curve than use the last knot
1299 // and normalize with the last span Still set the
1300 // spanindexcache to flatknots->Upper() - deg so that
1301 // the IsCacheValid will know for sure we are extending
1305 spanlenghtcache = flatknots->Value(LocalIndex - 1) - parametercache ;
1308 spanlenghtcache = flatknots->Value(LocalIndex + 1) - parametercache ;
1312 parametercache = flatknots->Value(LocalIndex) ;
1313 spanlenghtcache = flatknots->Value(LocalIndex + 1) - parametercache ;
1317 BSplCLib::BuildCache(parametercache,
1321 (flatknots->Array1()),
1324 cachepoles->ChangeArray1(),
1325 cacheweights->ChangeArray1()) ;
1328 BSplCLib::BuildCache(parametercache,
1332 (flatknots->Array1()),
1334 *((TColStd_Array1OfReal*) NULL),
1335 cachepoles->ChangeArray1(),
1336 *((TColStd_Array1OfReal*) NULL)) ;