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 //=======================================================================
79 //purpose : check rationality of an array of weights
80 //=======================================================================
82 static Standard_Boolean Rational(const TColStd_Array1OfReal& W)
84 Standard_Integer i, n = W.Length();
85 Standard_Boolean rat = Standard_False;
86 for (i = 1; i < n; i++) {
87 rat = Abs(W(i) - W(i+1)) > gp::Resolution();
93 //=======================================================================
96 //=======================================================================
98 Handle(Geom_Geometry) Geom_BSplineCurve::Copy() const
100 Handle(Geom_BSplineCurve) C;
102 C = new Geom_BSplineCurve(poles->Array1(),
108 C = new Geom_BSplineCurve(poles->Array1(),
115 //=======================================================================
116 //function : Geom_BSplineCurve
118 //=======================================================================
120 Geom_BSplineCurve::Geom_BSplineCurve
121 (const TColgp_Array1OfPnt& Poles,
122 const TColStd_Array1OfReal& Knots,
123 const TColStd_Array1OfInteger& Mults,
124 const Standard_Integer Degree,
125 const Standard_Boolean Periodic) :
126 rational(Standard_False),
129 maxderivinvok(Standard_False)
133 CheckCurveData (Poles,
142 poles = new TColgp_HArray1OfPnt(1,Poles.Length());
143 poles->ChangeArray1() = Poles;
146 knots = new TColStd_HArray1OfReal(1,Knots.Length());
147 knots->ChangeArray1() = Knots;
149 mults = new TColStd_HArray1OfInteger(1,Mults.Length());
150 mults->ChangeArray1() = Mults;
153 cachepoles = new TColgp_HArray1OfPnt(1,Degree + 1);
154 parametercache = 0.0e0 ;
155 spanlenghtcache = 0.0e0 ;
160 //=======================================================================
161 //function : Geom_BSplineCurve
163 //=======================================================================
165 Geom_BSplineCurve::Geom_BSplineCurve
166 (const TColgp_Array1OfPnt& Poles,
167 const TColStd_Array1OfReal& Weights,
168 const TColStd_Array1OfReal& Knots,
169 const TColStd_Array1OfInteger& Mults,
170 const Standard_Integer Degree,
171 const Standard_Boolean Periodic,
172 const Standard_Boolean CheckRational) :
173 rational(Standard_True),
176 maxderivinvok(Standard_False)
182 CheckCurveData (Poles,
188 if (Weights.Length() != Poles.Length())
189 Standard_ConstructionError::Raise("Geom_BSplineCurve");
192 for (i = Weights.Lower(); i <= Weights.Upper(); i++) {
193 if (Weights(i) <= gp::Resolution())
194 Standard_ConstructionError::Raise("Geom_BSplineCurve");
197 // check really rational
199 rational = Rational(Weights);
203 poles = new TColgp_HArray1OfPnt(1,Poles.Length());
204 poles->ChangeArray1() = Poles;
205 cachepoles = new TColgp_HArray1OfPnt(1,Degree + 1);
207 weights = new TColStd_HArray1OfReal(1,Weights.Length());
208 weights->ChangeArray1() = Weights;
209 cacheweights = new TColStd_HArray1OfReal(1,Degree + 1);
212 knots = new TColStd_HArray1OfReal(1,Knots.Length());
213 knots->ChangeArray1() = Knots;
215 mults = new TColStd_HArray1OfInteger(1,Mults.Length());
216 mults->ChangeArray1() = Mults;
219 parametercache = 0.0e0 ;
220 spanlenghtcache = 0.0e0 ;
224 //=======================================================================
225 //function : MaxDegree
227 //=======================================================================
229 Standard_Integer Geom_BSplineCurve::MaxDegree ()
231 return BSplCLib::MaxDegree();
234 //=======================================================================
235 //function : IncreaseDegree
237 //=======================================================================
239 void Geom_BSplineCurve::IncreaseDegree (const Standard_Integer Degree)
241 if (Degree == deg) return;
243 if (Degree < deg || Degree > Geom_BSplineCurve::MaxDegree()) {
244 Standard_ConstructionError::Raise();
246 Standard_Integer FromK1 = FirstUKnotIndex ();
247 Standard_Integer ToK2 = LastUKnotIndex ();
249 Standard_Integer Step = Degree - deg;
251 Handle(TColgp_HArray1OfPnt) npoles = new
252 TColgp_HArray1OfPnt(1,poles->Length() + Step * (ToK2-FromK1));
254 Standard_Integer nbknots = BSplCLib::IncreaseDegreeCountKnots
255 (deg,Degree,periodic,mults->Array1());
257 Handle(TColStd_HArray1OfReal) nknots =
258 new TColStd_HArray1OfReal(1,nbknots);
260 Handle(TColStd_HArray1OfInteger) nmults =
261 new TColStd_HArray1OfInteger(1,nbknots);
263 Handle(TColStd_HArray1OfReal) nweights;
267 nweights = new TColStd_HArray1OfReal(1,npoles->Upper());
269 BSplCLib::IncreaseDegree
270 (deg,Degree, periodic,
271 poles->Array1(),weights->Array1(),
272 knots->Array1(),mults->Array1(),
273 npoles->ChangeArray1(),nweights->ChangeArray1(),
274 nknots->ChangeArray1(),nmults->ChangeArray1());
277 BSplCLib::IncreaseDegree
278 (deg,Degree, periodic,
279 poles->Array1(),BSplCLib::NoWeights(),
280 knots->Array1(),mults->Array1(),
281 npoles->ChangeArray1(),
282 *((TColStd_Array1OfReal*) NULL),
283 nknots->ChangeArray1(),nmults->ChangeArray1());
295 //=======================================================================
296 //function : IncreaseMultiplicity
298 //=======================================================================
300 void Geom_BSplineCurve::IncreaseMultiplicity (const Standard_Integer Index,
301 const Standard_Integer M)
303 TColStd_Array1OfReal k(1,1);
304 k(1) = knots->Value(Index);
305 TColStd_Array1OfInteger m(1,1);
306 m(1) = M - mults->Value(Index);
307 InsertKnots(k,m,Epsilon(1.),Standard_True);
310 //=======================================================================
311 //function : IncreaseMultiplicity
313 //=======================================================================
315 void Geom_BSplineCurve::IncreaseMultiplicity (const Standard_Integer I1,
316 const Standard_Integer I2,
317 const Standard_Integer M)
319 Handle(TColStd_HArray1OfReal) tk = knots;
320 TColStd_Array1OfReal k((knots->Array1())(I1),I1,I2);
321 TColStd_Array1OfInteger m(I1,I2);
323 for (i = I1; i <= I2; i++)
324 m(i) = M - mults->Value(i);
325 InsertKnots(k,m,Epsilon(1.),Standard_True);
328 //=======================================================================
329 //function : IncrementMultiplicity
331 //=======================================================================
333 void Geom_BSplineCurve::IncrementMultiplicity
334 (const Standard_Integer I1,
335 const Standard_Integer I2,
336 const Standard_Integer Step)
338 Handle(TColStd_HArray1OfReal) tk = knots;
339 TColStd_Array1OfReal k((knots->Array1())(I1),I1,I2);
340 TColStd_Array1OfInteger m(I1,I2) ;
342 InsertKnots(k,m,Epsilon(1.),Standard_True);
345 //=======================================================================
346 //function : InsertKnot
348 //=======================================================================
350 void Geom_BSplineCurve::InsertKnot
351 (const Standard_Real U,
352 const Standard_Integer M,
353 const Standard_Real ParametricTolerance,
354 const Standard_Boolean Add)
356 TColStd_Array1OfReal k(1,1);
358 TColStd_Array1OfInteger m(1,1);
360 InsertKnots(k,m,ParametricTolerance,Add);
363 //=======================================================================
364 //function : InsertKnots
366 //=======================================================================
368 void Geom_BSplineCurve::InsertKnots(const TColStd_Array1OfReal& Knots,
369 const TColStd_Array1OfInteger& Mults,
370 const Standard_Real Epsilon,
371 const Standard_Boolean Add)
373 // Check and compute new sizes
374 Standard_Integer nbpoles,nbknots;
376 if (!BSplCLib::PrepareInsertKnots(deg,periodic,
377 knots->Array1(),mults->Array1(),
378 Knots,Mults,nbpoles,nbknots,Epsilon,Add))
379 Standard_ConstructionError::Raise("Geom_BSplineCurve::InsertKnots");
381 if (nbpoles == poles->Length()) return;
383 Handle(TColgp_HArray1OfPnt) npoles = new TColgp_HArray1OfPnt(1,nbpoles);
384 Handle(TColStd_HArray1OfReal) nknots = knots;
385 Handle(TColStd_HArray1OfInteger) nmults = mults;
387 if (nbknots != knots->Length()) {
388 nknots = new TColStd_HArray1OfReal(1,nbknots);
389 nmults = new TColStd_HArray1OfInteger(1,nbknots);
393 Handle(TColStd_HArray1OfReal) nweights =
394 new TColStd_HArray1OfReal(1,nbpoles);
395 BSplCLib::InsertKnots(deg,periodic,
396 poles->Array1(), weights->Array1(),
397 knots->Array1(), mults->Array1(),
399 npoles->ChangeArray1(), nweights->ChangeArray1(),
400 nknots->ChangeArray1(), nmults->ChangeArray1(),
405 BSplCLib::InsertKnots(deg,periodic,
406 poles->Array1(), BSplCLib::NoWeights(),
407 knots->Array1(), mults->Array1(),
409 npoles->ChangeArray1(),
410 *((TColStd_Array1OfReal*) NULL),
411 nknots->ChangeArray1(), nmults->ChangeArray1(),
422 //=======================================================================
423 //function : RemoveKnot
425 //=======================================================================
427 Standard_Boolean Geom_BSplineCurve::RemoveKnot(const Standard_Integer Index,
428 const Standard_Integer M,
429 const Standard_Real Tolerance)
431 if (M < 0) return Standard_True;
433 Standard_Integer I1 = FirstUKnotIndex ();
434 Standard_Integer I2 = LastUKnotIndex ();
436 if ( !periodic && (Index <= I1 || Index >= I2) ) {
437 Standard_OutOfRange::Raise();
439 else if ( periodic && (Index < I1 || Index > I2)) {
440 Standard_OutOfRange::Raise();
443 const TColgp_Array1OfPnt & oldpoles = poles->Array1();
445 Standard_Integer step = mults->Value(Index) - M;
446 if (step <= 0) return Standard_True;
448 Handle(TColgp_HArray1OfPnt) npoles =
449 new TColgp_HArray1OfPnt(1,oldpoles.Length()-step);
451 Handle(TColStd_HArray1OfReal) nknots = knots;
452 Handle(TColStd_HArray1OfInteger) nmults = mults;
455 nknots = new TColStd_HArray1OfReal(1,knots->Length()-1);
456 nmults = new TColStd_HArray1OfInteger(1,knots->Length()-1);
460 Handle(TColStd_HArray1OfReal) nweights =
461 new TColStd_HArray1OfReal(1,npoles->Length());
462 if (!BSplCLib::RemoveKnot
463 (Index, M, deg, periodic,
464 poles->Array1(),weights->Array1(),
465 knots->Array1(),mults->Array1(),
466 npoles->ChangeArray1(), nweights->ChangeArray1(),
467 nknots->ChangeArray1(),nmults->ChangeArray1(),
469 return Standard_False;
473 if (!BSplCLib::RemoveKnot
474 (Index, M, deg, periodic,
475 poles->Array1(), BSplCLib::NoWeights(),
476 knots->Array1(),mults->Array1(),
477 npoles->ChangeArray1(),
478 *((TColStd_Array1OfReal*) NULL),
479 nknots->ChangeArray1(),nmults->ChangeArray1(),
481 return Standard_False;
490 return Standard_True;
493 //=======================================================================
496 //=======================================================================
498 void Geom_BSplineCurve::Reverse ()
500 BSplCLib::Reverse(knots->ChangeArray1());
501 BSplCLib::Reverse(mults->ChangeArray1());
502 Standard_Integer last;
504 last = flatknots->Upper() - deg - 1;
506 last = poles->Upper();
507 BSplCLib::Reverse(poles->ChangeArray1(),last);
509 BSplCLib::Reverse(weights->ChangeArray1(),last);
513 //=======================================================================
514 //function : ReversedParameter
516 //=======================================================================
518 Standard_Real Geom_BSplineCurve::ReversedParameter
519 (const Standard_Real U) const
521 return (FirstParameter() + LastParameter() - U);
524 //=======================================================================
527 //=======================================================================
529 void Geom_BSplineCurve::Segment(const Standard_Real U1,
530 const Standard_Real U2)
532 Standard_DomainError_Raise_if ( U2 < U1,
533 "Geom_BSplineCurve::Segment");
535 Standard_Real NewU1, NewU2;
536 Standard_Real U,DU=0,aDDU=0;
537 Standard_Integer index;
538 Standard_Boolean wasPeriodic = periodic;
540 TColStd_Array1OfReal Knots(1,2);
541 TColStd_Array1OfInteger Mults(1,2);
543 // define param ditance to keep (eap, Apr 18 2002, occ311)
545 Standard_Real Period = LastParameter() - FirstParameter();
549 if (DU <= Epsilon(Period))
555 BSplCLib::LocateParameter(deg,knots->Array1(),mults->Array1(),
556 U1,periodic,knots->Lower(),knots->Upper(),
559 BSplCLib::LocateParameter(deg,knots->Array1(),mults->Array1(),
560 U2,periodic,knots->Lower(),knots->Upper(),
564 Standard_Real aNu2 = NewU2;
568 Knots( 1) = Min( NewU1, NewU2);
569 Knots( 2) = Max( NewU1, NewU2);
570 Mults( 1) = Mults( 2) = deg;
572 Standard_Real AbsUMax = Max(Abs(NewU1),Abs(NewU2));
574 // Modified by Sergey KHROMOV - Fri Apr 11 12:15:40 2003 Begin
575 AbsUMax = Max(AbsUMax, Max(Abs(FirstParameter()),Abs(LastParameter())));
576 // Modified by Sergey KHROMOV - Fri Apr 11 12:15:40 2003 End
578 Standard_Real Eps = 100. * Epsilon(AbsUMax);
580 InsertKnots( Knots, Mults, Eps);
582 if (periodic) { // set the origine at NewU1
584 BSplCLib::LocateParameter(deg,knots->Array1(),mults->Array1(),
585 U1,periodic,knots->Lower(),knots->Upper(),
587 // Test si l'insertion est Ok et decalage sinon.
588 if ( Abs(knots->Value(index+1)-U) <= Eps) // <= pour etre homogene a InsertKnots
595 // compute index1 and index2 to set the new knots and mults
596 Standard_Integer index1 = 0, index2 = 0;
597 Standard_Integer FromU1 = knots->Lower();
598 Standard_Integer ToU2 = knots->Upper();
599 BSplCLib::LocateParameter(deg,knots->Array1(),mults->Array1(),
600 NewU1,periodic,FromU1,ToU2,index1,U);
601 if ( Abs(knots->Value(index1+1)-U) <= Eps)
604 BSplCLib::LocateParameter(deg,knots->Array1(),mults->Array1(),
605 NewU2,periodic,FromU1,ToU2,index2,U);
606 if ( Abs(knots->Value(index2+1)-U) <= Eps)
609 Standard_Integer nbknots = index2 - index1 + 1;
611 Handle(TColStd_HArray1OfReal)
612 nknots = new TColStd_HArray1OfReal(1,nbknots);
613 Handle(TColStd_HArray1OfInteger)
614 nmults = new TColStd_HArray1OfInteger(1,nbknots);
616 // to restore changed U1
617 if (DU > 0) // if was periodic
620 Standard_Integer i , k = 1;
621 for ( i = index1; i<= index2; i++) {
622 nknots->SetValue(k, knots->Value(i) - DU);
623 nmults->SetValue(k, mults->Value(i));
626 nmults->SetValue( 1, deg + 1);
627 nmults->SetValue(nbknots, deg + 1);
630 // compute index1 and index2 to set the new poles and weights
631 Standard_Integer pindex1
632 = BSplCLib::PoleIndex(deg,index1,periodic,mults->Array1());
633 Standard_Integer pindex2
634 = BSplCLib::PoleIndex(deg,index2,periodic,mults->Array1());
637 pindex2 = Min( pindex2+1, poles->Length());
639 Standard_Integer nbpoles = pindex2 - pindex1 + 1;
641 Handle(TColStd_HArray1OfReal)
642 nweights = new TColStd_HArray1OfReal(1,nbpoles);
643 Handle(TColgp_HArray1OfPnt)
644 npoles = new TColgp_HArray1OfPnt(1,nbpoles);
648 nweights = new TColStd_HArray1OfReal( 1, nbpoles);
649 for ( i = pindex1; i <= pindex2; i++) {
650 npoles->SetValue(k, poles->Value(i));
651 nweights->SetValue(k, weights->Value(i));
656 for ( i = pindex1; i <= pindex2; i++) {
657 npoles->SetValue(k, poles->Value(i));
664 nknots->ChangeValue(nknots->Lower()) = U1;
666 nknots->ChangeValue(nknots->Upper()) = U1 + aDDU;
681 //=======================================================================
684 //=======================================================================
686 void Geom_BSplineCurve::SetKnot
687 (const Standard_Integer Index,
688 const Standard_Real K)
690 if (Index < 1 || Index > knots->Length()) Standard_OutOfRange::Raise();
691 Standard_Real DK = Abs(Epsilon (K));
693 if (K >= knots->Value(2) - DK) Standard_ConstructionError::Raise();
695 else if (Index == knots->Length()) {
696 if (K <= knots->Value (knots->Length()-1) + DK) {
697 Standard_ConstructionError::Raise();
701 if (K <= knots->Value(Index-1) + DK ||
702 K >= knots->Value(Index+1) - DK ) {
703 Standard_ConstructionError::Raise();
706 if (K != knots->Value (Index)) {
707 knots->SetValue (Index, K);
713 //=======================================================================
714 //function : SetKnots
716 //=======================================================================
718 void Geom_BSplineCurve::SetKnots
719 (const TColStd_Array1OfReal& K)
721 CheckCurveData(poles->Array1(),K,mults->Array1(),deg,periodic);
722 knots->ChangeArray1() = K;
727 //=======================================================================
730 //=======================================================================
732 void Geom_BSplineCurve::SetKnot
733 (const Standard_Integer Index,
734 const Standard_Real K,
735 const Standard_Integer M)
737 IncreaseMultiplicity (Index, M);
741 //=======================================================================
742 //function : SetPeriodic
744 //=======================================================================
746 void Geom_BSplineCurve::SetPeriodic ()
748 Standard_Integer first = FirstUKnotIndex();
749 Standard_Integer last = LastUKnotIndex();
751 Handle(TColStd_HArray1OfReal) tk = knots;
752 TColStd_Array1OfReal cknots((knots->Array1())(first),first,last);
753 knots = new TColStd_HArray1OfReal(1,cknots.Length());
754 knots->ChangeArray1() = cknots;
756 Handle(TColStd_HArray1OfInteger) tm = mults;
757 TColStd_Array1OfInteger cmults((mults->Array1())(first),first,last);
758 cmults(first) = cmults(last) = Min(deg, Max( cmults(first), cmults(last)));
759 mults = new TColStd_HArray1OfInteger(1,cmults.Length());
760 mults->ChangeArray1() = cmults;
762 // compute new number of poles;
763 Standard_Integer nbp = BSplCLib::NbPoles(deg,Standard_True,cmults);
765 Handle(TColgp_HArray1OfPnt) tp = poles;
766 TColgp_Array1OfPnt cpoles((poles->Array1())(1),1,nbp);
767 poles = new TColgp_HArray1OfPnt(1,nbp);
768 poles->ChangeArray1() = cpoles;
771 Handle(TColStd_HArray1OfReal) tw = weights;
772 TColStd_Array1OfReal cweights((weights->Array1())(1),1,nbp);
773 weights = new TColStd_HArray1OfReal(1,nbp);
774 weights->ChangeArray1() = cweights;
777 periodic = Standard_True;
783 //=======================================================================
784 //function : SetOrigin
786 //=======================================================================
788 void Geom_BSplineCurve::SetOrigin(const Standard_Integer Index)
790 Standard_NoSuchObject_Raise_if( !periodic,
791 "Geom_BSplineCurve::SetOrigin");
792 Standard_Integer i,k;
793 Standard_Integer first = FirstUKnotIndex();
794 Standard_Integer last = LastUKnotIndex();
796 Standard_DomainError_Raise_if( (Index < first) || (Index > last),
797 "Geom_BSplineCurve::SetOrigine");
799 Standard_Integer nbknots = knots->Length();
800 Standard_Integer nbpoles = poles->Length();
802 Handle(TColStd_HArray1OfReal) nknots =
803 new TColStd_HArray1OfReal(1,nbknots);
804 TColStd_Array1OfReal& newknots = nknots->ChangeArray1();
806 Handle(TColStd_HArray1OfInteger) nmults =
807 new TColStd_HArray1OfInteger(1,nbknots);
808 TColStd_Array1OfInteger& newmults = nmults->ChangeArray1();
810 // set the knots and mults
811 Standard_Real period = knots->Value(last) - knots->Value(first);
813 for ( i = Index; i <= last ; i++) {
814 newknots(k) = knots->Value(i);
815 newmults(k) = mults->Value(i);
818 for ( i = first+1; i <= Index; i++) {
819 newknots(k) = knots->Value(i) + period;
820 newmults(k) = mults->Value(i);
824 Standard_Integer index = 1;
825 for (i = first+1; i <= Index; i++)
826 index += mults->Value(i);
828 // set the poles and weights
829 Handle(TColgp_HArray1OfPnt) npoles =
830 new TColgp_HArray1OfPnt(1,nbpoles);
831 Handle(TColStd_HArray1OfReal) nweights =
832 new TColStd_HArray1OfReal(1,nbpoles);
833 TColgp_Array1OfPnt & newpoles = npoles->ChangeArray1();
834 TColStd_Array1OfReal & newweights = nweights->ChangeArray1();
835 first = poles->Lower();
836 last = poles->Upper();
839 for ( i = index; i <= last; i++) {
840 newpoles(k) = poles->Value(i);
841 newweights(k) = weights->Value(i);
844 for ( i = first; i < index; i++) {
845 newpoles(k) = poles->Value(i);
846 newweights(k) = weights->Value(i);
852 for ( i = index; i <= last; i++) {
853 newpoles(k) = poles->Value(i);
856 for ( i = first; i < index; i++) {
857 newpoles(k) = poles->Value(i);
871 //=======================================================================
872 //function : SetOrigin
874 //=======================================================================
876 void Geom_BSplineCurve::SetOrigin(const Standard_Real U,
877 const Standard_Real Tol)
879 Standard_NoSuchObject_Raise_if( !periodic,
880 "Geom_BSplineCurve::SetOrigin");
881 //U est il dans la period.
882 Standard_Real uf = FirstParameter(), ul = LastParameter();
883 Standard_Real u = U, period = ul - uf;
884 while (Tol < (uf-u)) u += period;
885 while (Tol > (ul-u)) u -= period;
887 if(Abs(U-u)>Tol) { //On reparametre la courbe
888 Standard_Real delta = U-u;
891 TColStd_Array1OfReal& kn = knots->ChangeArray1();
892 Standard_Integer fk = kn.Lower(), lk = kn.Upper();
893 for(Standard_Integer i = fk; i <= lk; i++){
894 kn.ChangeValue(i) += delta;
898 if(Abs(U-uf)<Tol) return;
900 TColStd_Array1OfReal& kn = knots->ChangeArray1();
901 Standard_Integer fk = kn.Lower(), lk = kn.Upper(),ik=0;
902 Standard_Real delta = RealLast();
903 for(Standard_Integer i = fk; i<= lk; i++){
904 Standard_Real dki = kn.Value(i)-U;
905 if(Abs(dki)<Abs(delta)){
917 //=======================================================================
918 //function : SetNotPeriodic
920 //=======================================================================
922 void Geom_BSplineCurve::SetNotPeriodic ()
925 Standard_Integer NbKnots, NbPoles;
926 BSplCLib::PrepareUnperiodize( deg, mults->Array1(),NbKnots,NbPoles);
928 Handle(TColgp_HArray1OfPnt) npoles
929 = new TColgp_HArray1OfPnt(1,NbPoles);
931 Handle(TColStd_HArray1OfReal) nknots
932 = new TColStd_HArray1OfReal(1,NbKnots);
934 Handle(TColStd_HArray1OfInteger) nmults
935 = new TColStd_HArray1OfInteger(1,NbKnots);
937 Handle(TColStd_HArray1OfReal) nweights;
941 nweights = new TColStd_HArray1OfReal(1,NbPoles);
943 BSplCLib::Unperiodize
944 (deg,mults->Array1(),knots->Array1(),poles->Array1(),
945 weights->Array1(),nmults->ChangeArray1(),
946 nknots->ChangeArray1(),npoles->ChangeArray1(),
947 nweights->ChangeArray1());
952 BSplCLib::Unperiodize
953 (deg,mults->Array1(),knots->Array1(),poles->Array1(),
954 BSplCLib::NoWeights(),nmults->ChangeArray1(),
955 nknots->ChangeArray1(),npoles->ChangeArray1(),
956 *((TColStd_Array1OfReal*) NULL));
963 periodic = Standard_False;
970 //=======================================================================
973 //=======================================================================
975 void Geom_BSplineCurve::SetPole
976 (const Standard_Integer Index,
979 if (Index < 1 || Index > poles->Length()) Standard_OutOfRange::Raise();
980 poles->SetValue (Index, P);
985 //=======================================================================
988 //=======================================================================
990 void Geom_BSplineCurve::SetPole
991 (const Standard_Integer Index,
993 const Standard_Real W)
999 //=======================================================================
1000 //function : SetWeight
1002 //=======================================================================
1004 void Geom_BSplineCurve::SetWeight
1005 (const Standard_Integer Index,
1006 const Standard_Real W)
1008 if (Index < 1 || Index > poles->Length()) Standard_OutOfRange::Raise();
1010 if (W <= gp::Resolution ()) Standard_ConstructionError::Raise();
1013 Standard_Boolean rat = IsRational() || (Abs(W - 1.) > gp::Resolution());
1016 if (rat && !IsRational()) {
1017 weights = new TColStd_HArray1OfReal(1,poles->Length());
1021 weights->SetValue (Index, W);
1024 rat = Rational(weights->Array1());
1025 if (!rat) weights.Nullify();
1028 rational = !weights.IsNull();
1034 //=======================================================================
1035 //function : MovePoint
1037 //=======================================================================
1039 void Geom_BSplineCurve::MovePoint(const Standard_Real U,
1041 const Standard_Integer Index1,
1042 const Standard_Integer Index2,
1043 Standard_Integer& FirstModifiedPole,
1044 Standard_Integer& LastmodifiedPole)
1046 if (Index1 < 1 || Index1 > poles->Length() ||
1047 Index2 < 1 || Index2 > poles->Length() || Index1 > Index2) {
1048 Standard_OutOfRange::Raise();
1050 TColgp_Array1OfPnt npoles(1, poles->Length());
1053 gp_Vec Displ(P0, P);
1054 BSplCLib::MovePoint(U, Displ, Index1, Index2, deg, rational, poles->Array1(),
1055 weights->Array1(), flatknots->Array1(),
1056 FirstModifiedPole, LastmodifiedPole, npoles);
1057 if (FirstModifiedPole) {
1058 poles->ChangeArray1() = npoles;
1064 //=======================================================================
1065 //function : MovePointAndTangent
1067 //=======================================================================
1069 void Geom_BSplineCurve::
1070 MovePointAndTangent(const Standard_Real U,
1072 const gp_Vec& Tangent,
1073 const Standard_Real Tolerance,
1074 const Standard_Integer StartingCondition,
1075 const Standard_Integer EndingCondition,
1076 Standard_Integer& ErrorStatus)
1078 Standard_Integer ii ;
1081 // for the time being do not deal with periodic curves
1085 TColgp_Array1OfPnt new_poles(1, poles->Length());
1089 gp_Vec delta_derivative;
1092 gp_Vec delta(P0, P);
1093 for (ii = 1 ; ii <= 3 ; ii++) {
1094 delta_derivative.SetCoord(ii,
1095 Tangent.Coord(ii)- delta_derivative.Coord(ii)) ;
1097 BSplCLib::MovePointAndTangent(U,
1107 flatknots->Array1(),
1111 poles->ChangeArray1() = new_poles;
1117 //=======================================================================
1118 //function : UpdateKnots
1120 //=======================================================================
1122 void Geom_BSplineCurve::UpdateKnots()
1124 rational = !weights.IsNull();
1126 Standard_Integer MaxKnotMult = 0;
1127 BSplCLib::KnotAnalysis (deg,
1131 knotSet, MaxKnotMult);
1133 if (knotSet == GeomAbs_Uniform && !periodic) {
1137 flatknots = new TColStd_HArray1OfReal
1138 (1, BSplCLib::KnotSequenceLength(mults->Array1(),deg,periodic));
1140 BSplCLib::KnotSequence (knots->Array1(),
1143 flatknots->ChangeArray1());
1146 if (MaxKnotMult == 0) smooth = GeomAbs_CN;
1148 switch (deg - MaxKnotMult) {
1149 case 0 : smooth = GeomAbs_C0; break;
1150 case 1 : smooth = GeomAbs_C1; break;
1151 case 2 : smooth = GeomAbs_C2; break;
1152 case 3 : smooth = GeomAbs_C3; break;
1153 default : smooth = GeomAbs_C3; break;
1159 //=======================================================================
1160 //function : Invalidate the Cache
1161 //purpose : as the name says
1162 //=======================================================================
1164 void Geom_BSplineCurve::InvalidateCache()
1169 //=======================================================================
1170 //function : check if the Cache is valid
1171 //purpose : as the name says
1172 //=======================================================================
1174 Standard_Boolean Geom_BSplineCurve::IsCacheValid
1175 (const Standard_Real U) const
1177 //Roman Lygin 26.12.08, performance improvements
1178 //1. avoided using NewParameter = (U - parametercache) / spanlenghtcache
1179 //to check against [0, 1), as division is CPU consuming
1180 //2. minimized use of if, as branching is also CPU consuming
1181 Standard_Real aDelta = U - parametercache;
1183 return ( validcache &&
1184 (aDelta >= 0.0e0) &&
1185 ((aDelta < spanlenghtcache) || (spanindexcache == flatknots->Upper() - deg)) );
1188 //=======================================================================
1189 //function : Normalizes the parameters if the curve is periodic
1190 //purpose : that is compute the cache so that it is valid
1191 //=======================================================================
1193 void Geom_BSplineCurve::PeriodicNormalization(Standard_Real& Parameter) const
1195 Standard_Real Period ;
1198 Period = flatknots->Value(flatknots->Upper() - deg) - flatknots->Value (deg + 1) ;
1199 while (Parameter > flatknots->Value(flatknots->Upper()-deg)) {
1200 Parameter -= Period ;
1202 while (Parameter < flatknots->Value((deg + 1))) {
1203 Parameter += Period ;
1208 //=======================================================================
1209 //function : Validate the Cache
1210 //purpose : that is compute the cache so that it is valid
1211 //=======================================================================
1213 void Geom_BSplineCurve::ValidateCache(const Standard_Real Parameter)
1215 Standard_Real NewParameter ;
1216 Standard_Integer LocalIndex = 0 ;
1218 // check if the degree did not change
1220 if (cachepoles->Upper() < deg + 1) {
1221 cachepoles = new TColgp_HArray1OfPnt(1,deg + 1);
1223 cacheweights = new TColStd_HArray1OfReal(1,deg + 1);
1226 BSplCLib::LocateParameter(deg,
1227 (flatknots->Array1()),
1228 (BSplCLib::NoMults()),
1233 spanindexcache = LocalIndex ;
1234 if (Parameter == flatknots->Value(LocalIndex + 1)) {
1237 parametercache = flatknots->Value(LocalIndex) ;
1238 if (LocalIndex == flatknots->Upper() - deg) {
1240 // for the last span if the parameter is outside of
1241 // the domain of the curve than use the last knot
1242 // and normalize with the last span Still set the
1243 // spanindexcache to flatknots->Upper() - deg so that
1244 // the IsCacheValid will know for sure we are extending
1248 spanlenghtcache = flatknots->Value(LocalIndex - 1) - parametercache ;
1251 spanlenghtcache = flatknots->Value(LocalIndex + 1) - parametercache ;
1255 parametercache = flatknots->Value(LocalIndex) ;
1256 spanlenghtcache = flatknots->Value(LocalIndex + 1) - parametercache ;
1260 BSplCLib::BuildCache(parametercache,
1264 (flatknots->Array1()),
1267 cachepoles->ChangeArray1(),
1268 cacheweights->ChangeArray1()) ;
1271 BSplCLib::BuildCache(parametercache,
1275 (flatknots->Array1()),
1277 *((TColStd_Array1OfReal*) NULL),
1278 cachepoles->ChangeArray1(),
1279 *((TColStd_Array1OfReal*) NULL)) ;