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 //Avril 1991 : constructeurs + methodes de lecture.
18 //Mai 1991 : revue des specifs + debut de realisation des classes tool =>
19 // implementation des methodes Set et calcul du point courant.
20 //Juillet 1991 : voir egalement File Geom_BSplineCurve_1.cxx
21 //Juin 1992 : mise a plat des valeurs nodales - amelioration des
22 // performances sur calcul du point courant
24 //RLE Aug 1993 Remove Swaps, Remove typedefs, Update BSplCLib
25 // debug periodic, IncreaseDegree
26 // 21-Mar-95 : xab implemented cache
27 // 14-Mar-96 : xab implemented MovePointAndTangent
28 // 13-Oct-96 : pmn Bug dans SetPeriodic (PRO6088) et Segment (PRO6250)
30 #define No_Standard_OutOfRange
32 #include <Geom_BSplineCurve.ixx>
35 #include <BSplCLib.hxx>
36 #include <BSplCLib_KnotDistribution.hxx>
37 #include <BSplCLib_MultDistribution.hxx>
38 #include <Standard_NotImplemented.hxx>
39 #include <Standard_ConstructionError.hxx>
40 #include <Standard_OutOfRange.hxx>
41 #include <Standard_Real.hxx>
43 //=======================================================================
44 //function : CheckCurveData
45 //purpose : Internal use only
46 //=======================================================================
48 static void CheckCurveData
49 (const TColgp_Array1OfPnt& CPoles,
50 const TColStd_Array1OfReal& CKnots,
51 const TColStd_Array1OfInteger& CMults,
52 const Standard_Integer Degree,
53 const Standard_Boolean Periodic)
55 if (Degree < 1 || Degree > Geom_BSplineCurve::MaxDegree()) {
56 Standard_ConstructionError::Raise();
59 if (CPoles.Length() < 2) Standard_ConstructionError::Raise();
60 if (CKnots.Length() != CMults.Length()) Standard_ConstructionError::Raise();
62 for (Standard_Integer I = CKnots.Lower(); I < CKnots.Upper(); I++) {
63 if (CKnots (I+1) - CKnots (I) <= Epsilon (Abs(CKnots (I)))) {
64 Standard_ConstructionError::Raise();
68 if (CPoles.Length() != BSplCLib::NbPoles(Degree,Periodic,CMults))
69 Standard_ConstructionError::Raise();
72 //=======================================================================
74 //purpose : check rationality of an array of weights
75 //=======================================================================
77 static Standard_Boolean Rational(const TColStd_Array1OfReal& W)
79 Standard_Integer i, n = W.Length();
80 Standard_Boolean rat = Standard_False;
81 for (i = 1; i < n; i++) {
82 rat = Abs(W(i) - W(i+1)) > gp::Resolution();
88 //=======================================================================
91 //=======================================================================
93 Handle(Geom_Geometry) Geom_BSplineCurve::Copy() const
95 Handle(Geom_BSplineCurve) C;
97 C = new Geom_BSplineCurve(poles->Array1(),
103 C = new Geom_BSplineCurve(poles->Array1(),
110 //=======================================================================
111 //function : Geom_BSplineCurve
113 //=======================================================================
115 Geom_BSplineCurve::Geom_BSplineCurve
116 (const TColgp_Array1OfPnt& Poles,
117 const TColStd_Array1OfReal& Knots,
118 const TColStd_Array1OfInteger& Mults,
119 const Standard_Integer Degree,
120 const Standard_Boolean Periodic) :
121 rational(Standard_False),
124 maxderivinvok(Standard_False)
128 CheckCurveData(Poles,
136 poles = new TColgp_HArray1OfPnt(1,Poles.Length());
137 poles->ChangeArray1() = Poles;
140 knots = new TColStd_HArray1OfReal(1,Knots.Length());
141 knots->ChangeArray1() = Knots;
143 mults = new TColStd_HArray1OfInteger(1,Mults.Length());
144 mults->ChangeArray1() = Mults;
149 //=======================================================================
150 //function : Geom_BSplineCurve
152 //=======================================================================
154 Geom_BSplineCurve::Geom_BSplineCurve
155 (const TColgp_Array1OfPnt& Poles,
156 const TColStd_Array1OfReal& Weights,
157 const TColStd_Array1OfReal& Knots,
158 const TColStd_Array1OfInteger& Mults,
159 const Standard_Integer Degree,
160 const Standard_Boolean Periodic,
161 const Standard_Boolean CheckRational) :
162 rational(Standard_True),
165 maxderivinvok(Standard_False)
171 CheckCurveData(Poles,
177 if (Weights.Length() != Poles.Length())
178 Standard_ConstructionError::Raise("Geom_BSplineCurve");
181 for (i = Weights.Lower(); i <= Weights.Upper(); i++) {
182 if (Weights(i) <= gp::Resolution())
183 Standard_ConstructionError::Raise("Geom_BSplineCurve");
186 // check really rational
188 rational = Rational(Weights);
192 poles = new TColgp_HArray1OfPnt(1,Poles.Length());
193 poles->ChangeArray1() = Poles;
195 weights = new TColStd_HArray1OfReal(1,Weights.Length());
196 weights->ChangeArray1() = Weights;
199 knots = new TColStd_HArray1OfReal(1,Knots.Length());
200 knots->ChangeArray1() = Knots;
202 mults = new TColStd_HArray1OfInteger(1,Mults.Length());
203 mults->ChangeArray1() = Mults;
208 //=======================================================================
209 //function : MaxDegree
211 //=======================================================================
213 Standard_Integer Geom_BSplineCurve::MaxDegree ()
215 return BSplCLib::MaxDegree();
218 //=======================================================================
219 //function : IncreaseDegree
221 //=======================================================================
223 void Geom_BSplineCurve::IncreaseDegree (const Standard_Integer Degree)
225 if (Degree == deg) return;
227 if (Degree < deg || Degree > Geom_BSplineCurve::MaxDegree()) {
228 Standard_ConstructionError::Raise();
230 Standard_Integer FromK1 = FirstUKnotIndex ();
231 Standard_Integer ToK2 = LastUKnotIndex ();
233 Standard_Integer Step = Degree - deg;
235 Handle(TColgp_HArray1OfPnt) npoles = new
236 TColgp_HArray1OfPnt(1,poles->Length() + Step * (ToK2-FromK1));
238 Standard_Integer nbknots = BSplCLib::IncreaseDegreeCountKnots
239 (deg,Degree,periodic,mults->Array1());
241 Handle(TColStd_HArray1OfReal) nknots =
242 new TColStd_HArray1OfReal(1,nbknots);
244 Handle(TColStd_HArray1OfInteger) nmults =
245 new TColStd_HArray1OfInteger(1,nbknots);
247 Handle(TColStd_HArray1OfReal) nweights;
251 nweights = new TColStd_HArray1OfReal(1,npoles->Upper());
253 BSplCLib::IncreaseDegree
254 (deg,Degree, periodic,
255 poles->Array1(),weights->Array1(),
256 knots->Array1(),mults->Array1(),
257 npoles->ChangeArray1(),nweights->ChangeArray1(),
258 nknots->ChangeArray1(),nmults->ChangeArray1());
261 BSplCLib::IncreaseDegree
262 (deg,Degree, periodic,
263 poles->Array1(),BSplCLib::NoWeights(),
264 knots->Array1(),mults->Array1(),
265 npoles->ChangeArray1(),
266 *((TColStd_Array1OfReal*) NULL),
267 nknots->ChangeArray1(),nmults->ChangeArray1());
279 //=======================================================================
280 //function : IncreaseMultiplicity
282 //=======================================================================
284 void Geom_BSplineCurve::IncreaseMultiplicity (const Standard_Integer Index,
285 const Standard_Integer M)
287 TColStd_Array1OfReal k(1,1);
288 k(1) = knots->Value(Index);
289 TColStd_Array1OfInteger m(1,1);
290 m(1) = M - mults->Value(Index);
291 InsertKnots(k,m,Epsilon(1.),Standard_True);
294 //=======================================================================
295 //function : IncreaseMultiplicity
297 //=======================================================================
299 void Geom_BSplineCurve::IncreaseMultiplicity (const Standard_Integer I1,
300 const Standard_Integer I2,
301 const Standard_Integer M)
303 Handle(TColStd_HArray1OfReal) tk = knots;
304 TColStd_Array1OfReal k((knots->Array1())(I1),I1,I2);
305 TColStd_Array1OfInteger m(I1,I2);
307 for (i = I1; i <= I2; i++)
308 m(i) = M - mults->Value(i);
309 InsertKnots(k,m,Epsilon(1.),Standard_True);
312 //=======================================================================
313 //function : IncrementMultiplicity
315 //=======================================================================
317 void Geom_BSplineCurve::IncrementMultiplicity
318 (const Standard_Integer I1,
319 const Standard_Integer I2,
320 const Standard_Integer Step)
322 Handle(TColStd_HArray1OfReal) tk = knots;
323 TColStd_Array1OfReal k((knots->Array1())(I1),I1,I2);
324 TColStd_Array1OfInteger m(I1,I2) ;
326 InsertKnots(k,m,Epsilon(1.),Standard_True);
329 //=======================================================================
330 //function : InsertKnot
332 //=======================================================================
334 void Geom_BSplineCurve::InsertKnot
335 (const Standard_Real U,
336 const Standard_Integer M,
337 const Standard_Real ParametricTolerance,
338 const Standard_Boolean Add)
340 TColStd_Array1OfReal k(1,1);
342 TColStd_Array1OfInteger m(1,1);
344 InsertKnots(k,m,ParametricTolerance,Add);
347 //=======================================================================
348 //function : InsertKnots
350 //=======================================================================
352 void Geom_BSplineCurve::InsertKnots(const TColStd_Array1OfReal& Knots,
353 const TColStd_Array1OfInteger& Mults,
354 const Standard_Real Epsilon,
355 const Standard_Boolean Add)
357 // Check and compute new sizes
358 Standard_Integer nbpoles,nbknots;
360 if (!BSplCLib::PrepareInsertKnots(deg,periodic,
361 knots->Array1(),mults->Array1(),
362 Knots,Mults,nbpoles,nbknots,Epsilon,Add))
363 Standard_ConstructionError::Raise("Geom_BSplineCurve::InsertKnots");
365 if (nbpoles == poles->Length()) return;
367 Handle(TColgp_HArray1OfPnt) npoles = new TColgp_HArray1OfPnt(1,nbpoles);
368 Handle(TColStd_HArray1OfReal) nknots = knots;
369 Handle(TColStd_HArray1OfInteger) nmults = mults;
371 if (nbknots != knots->Length()) {
372 nknots = new TColStd_HArray1OfReal(1,nbknots);
373 nmults = new TColStd_HArray1OfInteger(1,nbknots);
377 Handle(TColStd_HArray1OfReal) nweights =
378 new TColStd_HArray1OfReal(1,nbpoles);
379 BSplCLib::InsertKnots(deg,periodic,
380 poles->Array1(), weights->Array1(),
381 knots->Array1(), mults->Array1(),
383 npoles->ChangeArray1(), nweights->ChangeArray1(),
384 nknots->ChangeArray1(), nmults->ChangeArray1(),
389 BSplCLib::InsertKnots(deg,periodic,
390 poles->Array1(), BSplCLib::NoWeights(),
391 knots->Array1(), mults->Array1(),
393 npoles->ChangeArray1(),
394 *((TColStd_Array1OfReal*) NULL),
395 nknots->ChangeArray1(), nmults->ChangeArray1(),
406 //=======================================================================
407 //function : RemoveKnot
409 //=======================================================================
411 Standard_Boolean Geom_BSplineCurve::RemoveKnot(const Standard_Integer Index,
412 const Standard_Integer M,
413 const Standard_Real Tolerance)
415 if (M < 0) return Standard_True;
417 Standard_Integer I1 = FirstUKnotIndex ();
418 Standard_Integer I2 = LastUKnotIndex ();
420 if ( !periodic && (Index <= I1 || Index >= I2) ) {
421 Standard_OutOfRange::Raise();
423 else if ( periodic && (Index < I1 || Index > I2)) {
424 Standard_OutOfRange::Raise();
427 const TColgp_Array1OfPnt & oldpoles = poles->Array1();
429 Standard_Integer step = mults->Value(Index) - M;
430 if (step <= 0) return Standard_True;
432 Handle(TColgp_HArray1OfPnt) npoles =
433 new TColgp_HArray1OfPnt(1,oldpoles.Length()-step);
435 Handle(TColStd_HArray1OfReal) nknots = knots;
436 Handle(TColStd_HArray1OfInteger) nmults = mults;
439 nknots = new TColStd_HArray1OfReal(1,knots->Length()-1);
440 nmults = new TColStd_HArray1OfInteger(1,knots->Length()-1);
444 Handle(TColStd_HArray1OfReal) nweights =
445 new TColStd_HArray1OfReal(1,npoles->Length());
446 if (!BSplCLib::RemoveKnot
447 (Index, M, deg, periodic,
448 poles->Array1(),weights->Array1(),
449 knots->Array1(),mults->Array1(),
450 npoles->ChangeArray1(), nweights->ChangeArray1(),
451 nknots->ChangeArray1(),nmults->ChangeArray1(),
453 return Standard_False;
457 if (!BSplCLib::RemoveKnot
458 (Index, M, deg, periodic,
459 poles->Array1(), BSplCLib::NoWeights(),
460 knots->Array1(),mults->Array1(),
461 npoles->ChangeArray1(),
462 *((TColStd_Array1OfReal*) NULL),
463 nknots->ChangeArray1(),nmults->ChangeArray1(),
465 return Standard_False;
474 return Standard_True;
477 //=======================================================================
480 //=======================================================================
482 void Geom_BSplineCurve::Reverse ()
484 BSplCLib::Reverse(knots->ChangeArray1());
485 BSplCLib::Reverse(mults->ChangeArray1());
486 Standard_Integer last;
488 last = flatknots->Upper() - deg - 1;
490 last = poles->Upper();
491 BSplCLib::Reverse(poles->ChangeArray1(),last);
493 BSplCLib::Reverse(weights->ChangeArray1(),last);
497 //=======================================================================
498 //function : ReversedParameter
500 //=======================================================================
502 Standard_Real Geom_BSplineCurve::ReversedParameter
503 (const Standard_Real U) const
505 return (FirstParameter() + LastParameter() - U);
508 //=======================================================================
511 //=======================================================================
513 void Geom_BSplineCurve::Segment(const Standard_Real U1,
514 const Standard_Real U2)
516 Standard_DomainError_Raise_if ( U2 < U1,
517 "Geom_BSplineCurve::Segment");
519 Standard_Real NewU1, NewU2;
520 Standard_Real U,DU=0,aDDU=0;
521 Standard_Integer index;
522 Standard_Boolean wasPeriodic = periodic;
524 TColStd_Array1OfReal Knots(1,2);
525 TColStd_Array1OfInteger Mults(1,2);
527 // define param ditance to keep (eap, Apr 18 2002, occ311)
529 Standard_Real Period = LastParameter() - FirstParameter();
533 if (DU <= Epsilon(Period))
539 BSplCLib::LocateParameter(deg,knots->Array1(),mults->Array1(),
540 U1,periodic,knots->Lower(),knots->Upper(),
543 BSplCLib::LocateParameter(deg,knots->Array1(),mults->Array1(),
544 U2,periodic,knots->Lower(),knots->Upper(),
548 Standard_Real aNu2 = NewU2;
552 Knots( 1) = Min( NewU1, NewU2);
553 Knots( 2) = Max( NewU1, NewU2);
554 Mults( 1) = Mults( 2) = deg;
556 Standard_Real AbsUMax = Max(Abs(NewU1),Abs(NewU2));
558 // Modified by Sergey KHROMOV - Fri Apr 11 12:15:40 2003 Begin
559 AbsUMax = Max(AbsUMax, Max(Abs(FirstParameter()),Abs(LastParameter())));
560 // Modified by Sergey KHROMOV - Fri Apr 11 12:15:40 2003 End
562 Standard_Real Eps = 100. * Epsilon(AbsUMax);
564 InsertKnots( Knots, Mults, Eps);
566 if (periodic) { // set the origine at NewU1
568 BSplCLib::LocateParameter(deg,knots->Array1(),mults->Array1(),
569 U1,periodic,knots->Lower(),knots->Upper(),
571 // Test si l'insertion est Ok et decalage sinon.
572 if ( Abs(knots->Value(index+1)-U) <= Eps) // <= pour etre homogene a InsertKnots
579 // compute index1 and index2 to set the new knots and mults
580 Standard_Integer index1 = 0, index2 = 0;
581 Standard_Integer FromU1 = knots->Lower();
582 Standard_Integer ToU2 = knots->Upper();
583 BSplCLib::LocateParameter(deg,knots->Array1(),mults->Array1(),
584 NewU1,periodic,FromU1,ToU2,index1,U);
585 if ( Abs(knots->Value(index1+1)-U) <= Eps)
588 BSplCLib::LocateParameter(deg,knots->Array1(),mults->Array1(),
589 NewU2,periodic,FromU1,ToU2,index2,U);
590 if ( Abs(knots->Value(index2+1)-U) <= Eps || index2 == index1)
593 Standard_Integer nbknots = index2 - index1 + 1;
595 Handle(TColStd_HArray1OfReal)
596 nknots = new TColStd_HArray1OfReal(1,nbknots);
597 Handle(TColStd_HArray1OfInteger)
598 nmults = new TColStd_HArray1OfInteger(1,nbknots);
600 // to restore changed U1
601 if (DU > 0) // if was periodic
604 Standard_Integer i , k = 1;
605 for ( i = index1; i<= index2; i++) {
606 nknots->SetValue(k, knots->Value(i) - DU);
607 nmults->SetValue(k, mults->Value(i));
610 nmults->SetValue( 1, deg + 1);
611 nmults->SetValue(nbknots, deg + 1);
614 // compute index1 and index2 to set the new poles and weights
615 Standard_Integer pindex1
616 = BSplCLib::PoleIndex(deg,index1,periodic,mults->Array1());
617 Standard_Integer pindex2
618 = BSplCLib::PoleIndex(deg,index2,periodic,mults->Array1());
621 pindex2 = Min( pindex2+1, poles->Length());
623 Standard_Integer nbpoles = pindex2 - pindex1 + 1;
625 Handle(TColStd_HArray1OfReal)
626 nweights = new TColStd_HArray1OfReal(1,nbpoles);
627 Handle(TColgp_HArray1OfPnt)
628 npoles = new TColgp_HArray1OfPnt(1,nbpoles);
632 nweights = new TColStd_HArray1OfReal( 1, nbpoles);
633 for ( i = pindex1; i <= pindex2; i++) {
634 npoles->SetValue(k, poles->Value(i));
635 nweights->SetValue(k, weights->Value(i));
640 for ( i = pindex1; i <= pindex2; i++) {
641 npoles->SetValue(k, poles->Value(i));
648 nknots->ChangeValue(nknots->Lower()) = U1;
650 nknots->ChangeValue(nknots->Upper()) = U1 + aDDU;
665 //=======================================================================
668 //=======================================================================
670 void Geom_BSplineCurve::SetKnot
671 (const Standard_Integer Index,
672 const Standard_Real K)
674 if (Index < 1 || Index > knots->Length()) Standard_OutOfRange::Raise();
675 Standard_Real DK = Abs(Epsilon (K));
677 if (K >= knots->Value(2) - DK) Standard_ConstructionError::Raise();
679 else if (Index == knots->Length()) {
680 if (K <= knots->Value (knots->Length()-1) + DK) {
681 Standard_ConstructionError::Raise();
685 if (K <= knots->Value(Index-1) + DK ||
686 K >= knots->Value(Index+1) - DK ) {
687 Standard_ConstructionError::Raise();
690 if (K != knots->Value (Index)) {
691 knots->SetValue (Index, K);
697 //=======================================================================
698 //function : SetKnots
700 //=======================================================================
702 void Geom_BSplineCurve::SetKnots
703 (const TColStd_Array1OfReal& K)
705 CheckCurveData(poles->Array1(),K,mults->Array1(),deg,periodic);
706 knots->ChangeArray1() = K;
711 //=======================================================================
714 //=======================================================================
716 void Geom_BSplineCurve::SetKnot
717 (const Standard_Integer Index,
718 const Standard_Real K,
719 const Standard_Integer M)
721 IncreaseMultiplicity (Index, M);
725 //=======================================================================
726 //function : SetPeriodic
728 //=======================================================================
730 void Geom_BSplineCurve::SetPeriodic ()
732 Standard_Integer first = FirstUKnotIndex();
733 Standard_Integer last = LastUKnotIndex();
735 Handle(TColStd_HArray1OfReal) tk = knots;
736 TColStd_Array1OfReal cknots((knots->Array1())(first),first,last);
737 knots = new TColStd_HArray1OfReal(1,cknots.Length());
738 knots->ChangeArray1() = cknots;
740 Handle(TColStd_HArray1OfInteger) tm = mults;
741 TColStd_Array1OfInteger cmults((mults->Array1())(first),first,last);
742 cmults(first) = cmults(last) = Min(deg, Max( cmults(first), cmults(last)));
743 mults = new TColStd_HArray1OfInteger(1,cmults.Length());
744 mults->ChangeArray1() = cmults;
746 // compute new number of poles;
747 Standard_Integer nbp = BSplCLib::NbPoles(deg,Standard_True,cmults);
749 Handle(TColgp_HArray1OfPnt) tp = poles;
750 TColgp_Array1OfPnt cpoles((poles->Array1())(1),1,nbp);
751 poles = new TColgp_HArray1OfPnt(1,nbp);
752 poles->ChangeArray1() = cpoles;
755 Handle(TColStd_HArray1OfReal) tw = weights;
756 TColStd_Array1OfReal cweights((weights->Array1())(1),1,nbp);
757 weights = new TColStd_HArray1OfReal(1,nbp);
758 weights->ChangeArray1() = cweights;
761 periodic = Standard_True;
767 //=======================================================================
768 //function : SetOrigin
770 //=======================================================================
772 void Geom_BSplineCurve::SetOrigin(const Standard_Integer Index)
774 Standard_NoSuchObject_Raise_if( !periodic,
775 "Geom_BSplineCurve::SetOrigin");
776 Standard_Integer i,k;
777 Standard_Integer first = FirstUKnotIndex();
778 Standard_Integer last = LastUKnotIndex();
780 Standard_DomainError_Raise_if( (Index < first) || (Index > last),
781 "Geom_BSplineCurve::SetOrigine");
783 Standard_Integer nbknots = knots->Length();
784 Standard_Integer nbpoles = poles->Length();
786 Handle(TColStd_HArray1OfReal) nknots =
787 new TColStd_HArray1OfReal(1,nbknots);
788 TColStd_Array1OfReal& newknots = nknots->ChangeArray1();
790 Handle(TColStd_HArray1OfInteger) nmults =
791 new TColStd_HArray1OfInteger(1,nbknots);
792 TColStd_Array1OfInteger& newmults = nmults->ChangeArray1();
794 // set the knots and mults
795 Standard_Real period = knots->Value(last) - knots->Value(first);
797 for ( i = Index; i <= last ; i++) {
798 newknots(k) = knots->Value(i);
799 newmults(k) = mults->Value(i);
802 for ( i = first+1; i <= Index; i++) {
803 newknots(k) = knots->Value(i) + period;
804 newmults(k) = mults->Value(i);
808 Standard_Integer index = 1;
809 for (i = first+1; i <= Index; i++)
810 index += mults->Value(i);
812 // set the poles and weights
813 Handle(TColgp_HArray1OfPnt) npoles =
814 new TColgp_HArray1OfPnt(1,nbpoles);
815 Handle(TColStd_HArray1OfReal) nweights =
816 new TColStd_HArray1OfReal(1,nbpoles);
817 TColgp_Array1OfPnt & newpoles = npoles->ChangeArray1();
818 TColStd_Array1OfReal & newweights = nweights->ChangeArray1();
819 first = poles->Lower();
820 last = poles->Upper();
823 for ( i = index; i <= last; i++) {
824 newpoles(k) = poles->Value(i);
825 newweights(k) = weights->Value(i);
828 for ( i = first; i < index; i++) {
829 newpoles(k) = poles->Value(i);
830 newweights(k) = weights->Value(i);
836 for ( i = index; i <= last; i++) {
837 newpoles(k) = poles->Value(i);
840 for ( i = first; i < index; i++) {
841 newpoles(k) = poles->Value(i);
855 //=======================================================================
856 //function : SetOrigin
858 //=======================================================================
860 void Geom_BSplineCurve::SetOrigin(const Standard_Real U,
861 const Standard_Real Tol)
863 Standard_NoSuchObject_Raise_if( !periodic,
864 "Geom_BSplineCurve::SetOrigin");
865 //U est il dans la period.
866 Standard_Real uf = FirstParameter(), ul = LastParameter();
867 Standard_Real u = U, period = ul - uf;
868 while (Tol < (uf-u)) u += period;
869 while (Tol > (ul-u)) u -= period;
871 if(Abs(U-u)>Tol) { //On reparametre la courbe
872 Standard_Real delta = U-u;
875 TColStd_Array1OfReal& kn = knots->ChangeArray1();
876 Standard_Integer fk = kn.Lower(), lk = kn.Upper();
877 for(Standard_Integer i = fk; i <= lk; i++){
878 kn.ChangeValue(i) += delta;
882 if(Abs(U-uf)<Tol) return;
884 TColStd_Array1OfReal& kn = knots->ChangeArray1();
885 Standard_Integer fk = kn.Lower(), lk = kn.Upper(),ik=0;
886 Standard_Real delta = RealLast();
887 for(Standard_Integer i = fk; i<= lk; i++){
888 Standard_Real dki = kn.Value(i)-U;
889 if(Abs(dki)<Abs(delta)){
901 //=======================================================================
902 //function : SetNotPeriodic
904 //=======================================================================
906 void Geom_BSplineCurve::SetNotPeriodic ()
909 Standard_Integer NbKnots, NbPoles;
910 BSplCLib::PrepareUnperiodize( deg, mults->Array1(),NbKnots,NbPoles);
912 Handle(TColgp_HArray1OfPnt) npoles
913 = new TColgp_HArray1OfPnt(1,NbPoles);
915 Handle(TColStd_HArray1OfReal) nknots
916 = new TColStd_HArray1OfReal(1,NbKnots);
918 Handle(TColStd_HArray1OfInteger) nmults
919 = new TColStd_HArray1OfInteger(1,NbKnots);
921 Handle(TColStd_HArray1OfReal) nweights;
925 nweights = new TColStd_HArray1OfReal(1,NbPoles);
927 BSplCLib::Unperiodize
928 (deg,mults->Array1(),knots->Array1(),poles->Array1(),
929 weights->Array1(),nmults->ChangeArray1(),
930 nknots->ChangeArray1(),npoles->ChangeArray1(),
931 nweights->ChangeArray1());
936 BSplCLib::Unperiodize
937 (deg,mults->Array1(),knots->Array1(),poles->Array1(),
938 BSplCLib::NoWeights(),nmults->ChangeArray1(),
939 nknots->ChangeArray1(),npoles->ChangeArray1(),
940 *((TColStd_Array1OfReal*) NULL));
947 periodic = Standard_False;
954 //=======================================================================
957 //=======================================================================
959 void Geom_BSplineCurve::SetPole
960 (const Standard_Integer Index,
963 if (Index < 1 || Index > poles->Length()) Standard_OutOfRange::Raise();
964 poles->SetValue (Index, P);
968 //=======================================================================
971 //=======================================================================
973 void Geom_BSplineCurve::SetPole
974 (const Standard_Integer Index,
976 const Standard_Real W)
982 //=======================================================================
983 //function : SetWeight
985 //=======================================================================
987 void Geom_BSplineCurve::SetWeight
988 (const Standard_Integer Index,
989 const Standard_Real W)
991 if (Index < 1 || Index > poles->Length()) Standard_OutOfRange::Raise();
993 if (W <= gp::Resolution ()) Standard_ConstructionError::Raise();
996 Standard_Boolean rat = IsRational() || (Abs(W - 1.) > gp::Resolution());
999 if (rat && !IsRational()) {
1000 weights = new TColStd_HArray1OfReal(1,poles->Length());
1004 weights->SetValue (Index, W);
1007 rat = Rational(weights->Array1());
1008 if (!rat) weights.Nullify();
1011 rational = !weights.IsNull();
1016 //=======================================================================
1017 //function : MovePoint
1019 //=======================================================================
1021 void Geom_BSplineCurve::MovePoint(const Standard_Real U,
1023 const Standard_Integer Index1,
1024 const Standard_Integer Index2,
1025 Standard_Integer& FirstModifiedPole,
1026 Standard_Integer& LastmodifiedPole)
1028 if (Index1 < 1 || Index1 > poles->Length() ||
1029 Index2 < 1 || Index2 > poles->Length() || Index1 > Index2) {
1030 Standard_OutOfRange::Raise();
1032 TColgp_Array1OfPnt npoles(1, poles->Length());
1035 gp_Vec Displ(P0, P);
1036 BSplCLib::MovePoint(U, Displ, Index1, Index2, deg, rational, poles->Array1(),
1037 weights->Array1(), flatknots->Array1(),
1038 FirstModifiedPole, LastmodifiedPole, npoles);
1039 if (FirstModifiedPole) {
1040 poles->ChangeArray1() = npoles;
1045 //=======================================================================
1046 //function : MovePointAndTangent
1048 //=======================================================================
1050 void Geom_BSplineCurve::MovePointAndTangent(const Standard_Real U,
1052 const gp_Vec& Tangent,
1053 const Standard_Real Tolerance,
1054 const Standard_Integer StartingCondition,
1055 const Standard_Integer EndingCondition,
1056 Standard_Integer& ErrorStatus)
1058 Standard_Integer ii ;
1061 // for the time being do not deal with periodic curves
1065 TColgp_Array1OfPnt new_poles(1, poles->Length());
1069 gp_Vec delta_derivative;
1072 gp_Vec delta(P0, P);
1073 for (ii = 1 ; ii <= 3 ; ii++) {
1074 delta_derivative.SetCoord(ii, Tangent.Coord(ii)-delta_derivative.Coord(ii));
1076 BSplCLib::MovePointAndTangent(U,
1086 flatknots->Array1(),
1090 poles->ChangeArray1() = new_poles;
1095 //=======================================================================
1096 //function : UpdateKnots
1098 //=======================================================================
1100 void Geom_BSplineCurve::UpdateKnots()
1102 rational = !weights.IsNull();
1104 Standard_Integer MaxKnotMult = 0;
1105 BSplCLib::KnotAnalysis(deg,
1109 knotSet, MaxKnotMult);
1111 if (knotSet == GeomAbs_Uniform && !periodic) {
1115 flatknots = new TColStd_HArray1OfReal
1116 (1, BSplCLib::KnotSequenceLength(mults->Array1(),deg,periodic));
1118 BSplCLib::KnotSequence(knots->Array1(),
1121 flatknots->ChangeArray1());
1124 if (MaxKnotMult == 0) smooth = GeomAbs_CN;
1126 switch (deg - MaxKnotMult) {
1127 case 0 : smooth = GeomAbs_C0; break;
1128 case 1 : smooth = GeomAbs_C1; break;
1129 case 2 : smooth = GeomAbs_C2; break;
1130 case 3 : smooth = GeomAbs_C3; break;
1131 default : smooth = GeomAbs_C3; break;
1136 //=======================================================================
1137 //function : Normalizes the parameters if the curve is periodic
1138 //purpose : that is compute the cache so that it is valid
1139 //=======================================================================
1141 void Geom_BSplineCurve::PeriodicNormalization(Standard_Real& Parameter) const
1143 Standard_Real Period ;
1146 Period = flatknots->Value(flatknots->Upper() - deg) - flatknots->Value (deg + 1) ;
1147 while (Parameter > flatknots->Value(flatknots->Upper()-deg)) {
1148 Parameter -= Period ;
1150 while (Parameter < flatknots->Value((deg + 1))) {
1151 Parameter += Period ;