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
33 #include <BSplCLib.hxx>
34 #include <BSplCLib_KnotDistribution.hxx>
35 #include <BSplCLib_MultDistribution.hxx>
37 #include <Geom_BSplineCurve.hxx>
38 #include <Geom_Geometry.hxx>
39 #include <Geom_UndefinedDerivative.hxx>
42 #include <gp_Trsf.hxx>
44 #include <Standard_ConstructionError.hxx>
45 #include <Standard_DimensionError.hxx>
46 #include <Standard_DomainError.hxx>
47 #include <Standard_NoSuchObject.hxx>
48 #include <Standard_NotImplemented.hxx>
49 #include <Standard_OutOfRange.hxx>
50 #include <Standard_RangeError.hxx>
51 #include <Standard_Real.hxx>
52 #include <Standard_Type.hxx>
54 IMPLEMENT_STANDARD_RTTIEXT(Geom_BSplineCurve,Geom_BoundedCurve)
56 //=======================================================================
57 //function : CheckCurveData
58 //purpose : Internal use only
59 //=======================================================================
60 static void CheckCurveData
61 (const TColgp_Array1OfPnt& CPoles,
62 const TColStd_Array1OfReal& CKnots,
63 const TColStd_Array1OfInteger& CMults,
64 const Standard_Integer Degree,
65 const Standard_Boolean Periodic)
67 if (Degree < 1 || Degree > Geom_BSplineCurve::MaxDegree()) {
68 Standard_ConstructionError::Raise();
71 if (CPoles.Length() < 2) Standard_ConstructionError::Raise();
72 if (CKnots.Length() != CMults.Length()) Standard_ConstructionError::Raise();
74 for (Standard_Integer I = CKnots.Lower(); I < CKnots.Upper(); I++) {
75 if (CKnots (I+1) - CKnots (I) <= Epsilon (Abs(CKnots (I)))) {
76 Standard_ConstructionError::Raise();
80 if (CPoles.Length() != BSplCLib::NbPoles(Degree,Periodic,CMults))
81 Standard_ConstructionError::Raise();
84 //=======================================================================
86 //purpose : check rationality of an array of weights
87 //=======================================================================
89 static Standard_Boolean Rational(const TColStd_Array1OfReal& W)
91 Standard_Integer i, n = W.Length();
92 Standard_Boolean rat = Standard_False;
93 for (i = 1; i < n; i++) {
94 rat = Abs(W(i) - W(i+1)) > gp::Resolution();
100 //=======================================================================
103 //=======================================================================
105 Handle(Geom_Geometry) Geom_BSplineCurve::Copy() const
107 Handle(Geom_BSplineCurve) C;
109 C = new Geom_BSplineCurve(poles->Array1(),
115 C = new Geom_BSplineCurve(poles->Array1(),
122 //=======================================================================
123 //function : Geom_BSplineCurve
125 //=======================================================================
127 Geom_BSplineCurve::Geom_BSplineCurve
128 (const TColgp_Array1OfPnt& Poles,
129 const TColStd_Array1OfReal& Knots,
130 const TColStd_Array1OfInteger& Mults,
131 const Standard_Integer Degree,
132 const Standard_Boolean Periodic) :
133 rational(Standard_False),
136 maxderivinvok(Standard_False)
140 CheckCurveData(Poles,
148 poles = new TColgp_HArray1OfPnt(1,Poles.Length());
149 poles->ChangeArray1() = Poles;
152 knots = new TColStd_HArray1OfReal(1,Knots.Length());
153 knots->ChangeArray1() = Knots;
155 mults = new TColStd_HArray1OfInteger(1,Mults.Length());
156 mults->ChangeArray1() = Mults;
161 //=======================================================================
162 //function : Geom_BSplineCurve
164 //=======================================================================
166 Geom_BSplineCurve::Geom_BSplineCurve
167 (const TColgp_Array1OfPnt& Poles,
168 const TColStd_Array1OfReal& Weights,
169 const TColStd_Array1OfReal& Knots,
170 const TColStd_Array1OfInteger& Mults,
171 const Standard_Integer Degree,
172 const Standard_Boolean Periodic,
173 const Standard_Boolean CheckRational) :
174 rational(Standard_True),
177 maxderivinvok(Standard_False)
183 CheckCurveData(Poles,
189 if (Weights.Length() != Poles.Length())
190 Standard_ConstructionError::Raise("Geom_BSplineCurve");
193 for (i = Weights.Lower(); i <= Weights.Upper(); i++) {
194 if (Weights(i) <= gp::Resolution())
195 Standard_ConstructionError::Raise("Geom_BSplineCurve");
198 // check really rational
200 rational = Rational(Weights);
204 poles = new TColgp_HArray1OfPnt(1,Poles.Length());
205 poles->ChangeArray1() = Poles;
207 weights = new TColStd_HArray1OfReal(1,Weights.Length());
208 weights->ChangeArray1() = Weights;
211 knots = new TColStd_HArray1OfReal(1,Knots.Length());
212 knots->ChangeArray1() = Knots;
214 mults = new TColStd_HArray1OfInteger(1,Mults.Length());
215 mults->ChangeArray1() = Mults;
220 //=======================================================================
221 //function : MaxDegree
223 //=======================================================================
225 Standard_Integer Geom_BSplineCurve::MaxDegree ()
227 return BSplCLib::MaxDegree();
230 //=======================================================================
231 //function : IncreaseDegree
233 //=======================================================================
235 void Geom_BSplineCurve::IncreaseDegree (const Standard_Integer Degree)
237 if (Degree == deg) return;
239 if (Degree < deg || Degree > Geom_BSplineCurve::MaxDegree()) {
240 Standard_ConstructionError::Raise();
242 Standard_Integer FromK1 = FirstUKnotIndex ();
243 Standard_Integer ToK2 = LastUKnotIndex ();
245 Standard_Integer Step = Degree - deg;
247 Handle(TColgp_HArray1OfPnt) npoles = new
248 TColgp_HArray1OfPnt(1,poles->Length() + Step * (ToK2-FromK1));
250 Standard_Integer nbknots = BSplCLib::IncreaseDegreeCountKnots
251 (deg,Degree,periodic,mults->Array1());
253 Handle(TColStd_HArray1OfReal) nknots =
254 new TColStd_HArray1OfReal(1,nbknots);
256 Handle(TColStd_HArray1OfInteger) nmults =
257 new TColStd_HArray1OfInteger(1,nbknots);
259 Handle(TColStd_HArray1OfReal) nweights;
263 nweights = new TColStd_HArray1OfReal(1,npoles->Upper());
265 BSplCLib::IncreaseDegree
266 (deg,Degree, periodic,
267 poles->Array1(),&weights->Array1(),
268 knots->Array1(),mults->Array1(),
269 npoles->ChangeArray1(),&nweights->ChangeArray1(),
270 nknots->ChangeArray1(),nmults->ChangeArray1());
273 BSplCLib::IncreaseDegree
274 (deg,Degree, periodic,
275 poles->Array1(),BSplCLib::NoWeights(),
276 knots->Array1(),mults->Array1(),
277 npoles->ChangeArray1(),
278 BSplCLib::NoWeights(),
279 nknots->ChangeArray1(),nmults->ChangeArray1());
291 //=======================================================================
292 //function : IncreaseMultiplicity
294 //=======================================================================
296 void Geom_BSplineCurve::IncreaseMultiplicity (const Standard_Integer Index,
297 const Standard_Integer M)
299 TColStd_Array1OfReal k(1,1);
300 k(1) = knots->Value(Index);
301 TColStd_Array1OfInteger m(1,1);
302 m(1) = M - mults->Value(Index);
303 InsertKnots(k,m,Epsilon(1.),Standard_True);
306 //=======================================================================
307 //function : IncreaseMultiplicity
309 //=======================================================================
311 void Geom_BSplineCurve::IncreaseMultiplicity (const Standard_Integer I1,
312 const Standard_Integer I2,
313 const Standard_Integer M)
315 Handle(TColStd_HArray1OfReal) tk = knots;
316 TColStd_Array1OfReal k((knots->Array1())(I1),I1,I2);
317 TColStd_Array1OfInteger m(I1,I2);
319 for (i = I1; i <= I2; i++)
320 m(i) = M - mults->Value(i);
321 InsertKnots(k,m,Epsilon(1.),Standard_True);
324 //=======================================================================
325 //function : IncrementMultiplicity
327 //=======================================================================
329 void Geom_BSplineCurve::IncrementMultiplicity
330 (const Standard_Integer I1,
331 const Standard_Integer I2,
332 const Standard_Integer Step)
334 Handle(TColStd_HArray1OfReal) tk = knots;
335 TColStd_Array1OfReal k((knots->Array1())(I1),I1,I2);
336 TColStd_Array1OfInteger m(I1,I2) ;
338 InsertKnots(k,m,Epsilon(1.),Standard_True);
341 //=======================================================================
342 //function : InsertKnot
344 //=======================================================================
346 void Geom_BSplineCurve::InsertKnot
347 (const Standard_Real U,
348 const Standard_Integer M,
349 const Standard_Real ParametricTolerance,
350 const Standard_Boolean Add)
352 TColStd_Array1OfReal k(1,1);
354 TColStd_Array1OfInteger m(1,1);
356 InsertKnots(k,m,ParametricTolerance,Add);
359 //=======================================================================
360 //function : InsertKnots
362 //=======================================================================
364 void Geom_BSplineCurve::InsertKnots(const TColStd_Array1OfReal& Knots,
365 const TColStd_Array1OfInteger& Mults,
366 const Standard_Real Epsilon,
367 const Standard_Boolean Add)
369 // Check and compute new sizes
370 Standard_Integer nbpoles,nbknots;
372 if (!BSplCLib::PrepareInsertKnots(deg,periodic,
373 knots->Array1(),mults->Array1(),
374 Knots,&Mults,nbpoles,nbknots,Epsilon,Add))
375 Standard_ConstructionError::Raise("Geom_BSplineCurve::InsertKnots");
377 if (nbpoles == poles->Length()) return;
379 Handle(TColgp_HArray1OfPnt) npoles = new TColgp_HArray1OfPnt(1,nbpoles);
380 Handle(TColStd_HArray1OfReal) nknots = knots;
381 Handle(TColStd_HArray1OfInteger) nmults = mults;
383 if (nbknots != knots->Length()) {
384 nknots = new TColStd_HArray1OfReal(1,nbknots);
385 nmults = new TColStd_HArray1OfInteger(1,nbknots);
389 Handle(TColStd_HArray1OfReal) nweights =
390 new TColStd_HArray1OfReal(1,nbpoles);
391 BSplCLib::InsertKnots(deg,periodic,
392 poles->Array1(), &weights->Array1(),
393 knots->Array1(), mults->Array1(),
395 npoles->ChangeArray1(), &nweights->ChangeArray1(),
396 nknots->ChangeArray1(), nmults->ChangeArray1(),
401 BSplCLib::InsertKnots(deg,periodic,
402 poles->Array1(), BSplCLib::NoWeights(),
403 knots->Array1(), mults->Array1(),
405 npoles->ChangeArray1(),
406 BSplCLib::NoWeights(),
407 nknots->ChangeArray1(), nmults->ChangeArray1(),
418 //=======================================================================
419 //function : RemoveKnot
421 //=======================================================================
423 Standard_Boolean Geom_BSplineCurve::RemoveKnot(const Standard_Integer Index,
424 const Standard_Integer M,
425 const Standard_Real Tolerance)
427 if (M < 0) return Standard_True;
429 Standard_Integer I1 = FirstUKnotIndex ();
430 Standard_Integer I2 = LastUKnotIndex ();
432 if ( !periodic && (Index <= I1 || Index >= I2) ) {
433 Standard_OutOfRange::Raise();
435 else if ( periodic && (Index < I1 || Index > I2)) {
436 Standard_OutOfRange::Raise();
439 const TColgp_Array1OfPnt & oldpoles = poles->Array1();
441 Standard_Integer step = mults->Value(Index) - M;
442 if (step <= 0) return Standard_True;
444 Handle(TColgp_HArray1OfPnt) npoles =
445 new TColgp_HArray1OfPnt(1,oldpoles.Length()-step);
447 Handle(TColStd_HArray1OfReal) nknots = knots;
448 Handle(TColStd_HArray1OfInteger) nmults = mults;
451 nknots = new TColStd_HArray1OfReal(1,knots->Length()-1);
452 nmults = new TColStd_HArray1OfInteger(1,knots->Length()-1);
456 Handle(TColStd_HArray1OfReal) nweights =
457 new TColStd_HArray1OfReal(1,npoles->Length());
458 if (!BSplCLib::RemoveKnot
459 (Index, M, deg, periodic,
460 poles->Array1(),&weights->Array1(),
461 knots->Array1(),mults->Array1(),
462 npoles->ChangeArray1(), &nweights->ChangeArray1(),
463 nknots->ChangeArray1(),nmults->ChangeArray1(),
465 return Standard_False;
469 if (!BSplCLib::RemoveKnot
470 (Index, M, deg, periodic,
471 poles->Array1(), BSplCLib::NoWeights(),
472 knots->Array1(),mults->Array1(),
473 npoles->ChangeArray1(),
474 BSplCLib::NoWeights(),
475 nknots->ChangeArray1(),nmults->ChangeArray1(),
477 return Standard_False;
486 return Standard_True;
489 //=======================================================================
492 //=======================================================================
494 void Geom_BSplineCurve::Reverse ()
496 BSplCLib::Reverse(knots->ChangeArray1());
497 BSplCLib::Reverse(mults->ChangeArray1());
498 Standard_Integer last;
500 last = flatknots->Upper() - deg - 1;
502 last = poles->Upper();
503 BSplCLib::Reverse(poles->ChangeArray1(),last);
505 BSplCLib::Reverse(weights->ChangeArray1(),last);
509 //=======================================================================
510 //function : ReversedParameter
512 //=======================================================================
514 Standard_Real Geom_BSplineCurve::ReversedParameter
515 (const Standard_Real U) const
517 return (FirstParameter() + LastParameter() - U);
520 //=======================================================================
523 //=======================================================================
525 void Geom_BSplineCurve::Segment(const Standard_Real U1,
526 const Standard_Real U2)
528 Standard_DomainError_Raise_if ( U2 < U1,
529 "Geom_BSplineCurve::Segment");
531 Standard_Real NewU1, NewU2;
532 Standard_Real U,DU=0,aDDU=0;
533 Standard_Integer index;
534 Standard_Boolean wasPeriodic = periodic;
536 TColStd_Array1OfReal Knots(1,2);
537 TColStd_Array1OfInteger Mults(1,2);
539 // define param ditance to keep (eap, Apr 18 2002, occ311)
541 Standard_Real Period = LastParameter() - FirstParameter();
545 if (DU <= Epsilon(Period))
551 BSplCLib::LocateParameter(deg,knots->Array1(),mults->Array1(),
552 U1,periodic,knots->Lower(),knots->Upper(),
555 BSplCLib::LocateParameter(deg,knots->Array1(),mults->Array1(),
556 U2,periodic,knots->Lower(),knots->Upper(),
560 Standard_Real aNu2 = NewU2;
564 Knots( 1) = Min( NewU1, NewU2);
565 Knots( 2) = Max( NewU1, NewU2);
566 Mults( 1) = Mults( 2) = deg;
568 Standard_Real AbsUMax = Max(Abs(NewU1),Abs(NewU2));
570 // Modified by Sergey KHROMOV - Fri Apr 11 12:15:40 2003 Begin
571 AbsUMax = Max(AbsUMax, Max(Abs(FirstParameter()),Abs(LastParameter())));
572 // Modified by Sergey KHROMOV - Fri Apr 11 12:15:40 2003 End
574 Standard_Real Eps = 100. * Epsilon(AbsUMax);
576 InsertKnots( Knots, Mults, Eps);
578 if (periodic) { // set the origine at NewU1
580 BSplCLib::LocateParameter(deg,knots->Array1(),mults->Array1(),
581 U1,periodic,knots->Lower(),knots->Upper(),
583 // Test si l'insertion est Ok et decalage sinon.
584 if ( Abs(knots->Value(index+1)-U) <= Eps) // <= pour etre homogene a InsertKnots
591 // compute index1 and index2 to set the new knots and mults
592 Standard_Integer index1 = 0, index2 = 0;
593 Standard_Integer FromU1 = knots->Lower();
594 Standard_Integer ToU2 = knots->Upper();
595 BSplCLib::LocateParameter(deg,knots->Array1(),mults->Array1(),
596 NewU1,periodic,FromU1,ToU2,index1,U);
597 if ( Abs(knots->Value(index1+1)-U) <= Eps)
600 BSplCLib::LocateParameter(deg,knots->Array1(),mults->Array1(),
601 NewU2,periodic,FromU1,ToU2,index2,U);
602 if ( Abs(knots->Value(index2+1)-U) <= Eps || index2 == index1)
605 Standard_Integer nbknots = index2 - index1 + 1;
607 Handle(TColStd_HArray1OfReal)
608 nknots = new TColStd_HArray1OfReal(1,nbknots);
609 Handle(TColStd_HArray1OfInteger)
610 nmults = new TColStd_HArray1OfInteger(1,nbknots);
612 // to restore changed U1
613 if (DU > 0) // if was periodic
616 Standard_Integer i , k = 1;
617 for ( i = index1; i<= index2; i++) {
618 nknots->SetValue(k, knots->Value(i) - DU);
619 nmults->SetValue(k, mults->Value(i));
622 nmults->SetValue( 1, deg + 1);
623 nmults->SetValue(nbknots, deg + 1);
626 // compute index1 and index2 to set the new poles and weights
627 Standard_Integer pindex1
628 = BSplCLib::PoleIndex(deg,index1,periodic,mults->Array1());
629 Standard_Integer pindex2
630 = BSplCLib::PoleIndex(deg,index2,periodic,mults->Array1());
633 pindex2 = Min( pindex2+1, poles->Length());
635 Standard_Integer nbpoles = pindex2 - pindex1 + 1;
637 Handle(TColStd_HArray1OfReal)
638 nweights = new TColStd_HArray1OfReal(1,nbpoles);
639 Handle(TColgp_HArray1OfPnt)
640 npoles = new TColgp_HArray1OfPnt(1,nbpoles);
644 nweights = new TColStd_HArray1OfReal( 1, nbpoles);
645 for ( i = pindex1; i <= pindex2; i++) {
646 npoles->SetValue(k, poles->Value(i));
647 nweights->SetValue(k, weights->Value(i));
652 for ( i = pindex1; i <= pindex2; i++) {
653 npoles->SetValue(k, poles->Value(i));
660 nknots->ChangeValue(nknots->Lower()) = U1;
662 nknots->ChangeValue(nknots->Upper()) = U1 + aDDU;
677 //=======================================================================
680 //=======================================================================
682 void Geom_BSplineCurve::SetKnot
683 (const Standard_Integer Index,
684 const Standard_Real K)
686 if (Index < 1 || Index > knots->Length()) Standard_OutOfRange::Raise();
687 Standard_Real DK = Abs(Epsilon (K));
689 if (K >= knots->Value(2) - DK) Standard_ConstructionError::Raise();
691 else if (Index == knots->Length()) {
692 if (K <= knots->Value (knots->Length()-1) + DK) {
693 Standard_ConstructionError::Raise();
697 if (K <= knots->Value(Index-1) + DK ||
698 K >= knots->Value(Index+1) - DK ) {
699 Standard_ConstructionError::Raise();
702 if (K != knots->Value (Index)) {
703 knots->SetValue (Index, K);
709 //=======================================================================
710 //function : SetKnots
712 //=======================================================================
714 void Geom_BSplineCurve::SetKnots
715 (const TColStd_Array1OfReal& K)
717 CheckCurveData(poles->Array1(),K,mults->Array1(),deg,periodic);
718 knots->ChangeArray1() = K;
723 //=======================================================================
726 //=======================================================================
728 void Geom_BSplineCurve::SetKnot
729 (const Standard_Integer Index,
730 const Standard_Real K,
731 const Standard_Integer M)
733 IncreaseMultiplicity (Index, M);
737 //=======================================================================
738 //function : SetPeriodic
740 //=======================================================================
742 void Geom_BSplineCurve::SetPeriodic ()
744 Standard_Integer first = FirstUKnotIndex();
745 Standard_Integer last = LastUKnotIndex();
747 Handle(TColStd_HArray1OfReal) tk = knots;
748 TColStd_Array1OfReal cknots((knots->Array1())(first),first,last);
749 knots = new TColStd_HArray1OfReal(1,cknots.Length());
750 knots->ChangeArray1() = cknots;
752 Handle(TColStd_HArray1OfInteger) tm = mults;
753 TColStd_Array1OfInteger cmults((mults->Array1())(first),first,last);
754 cmults(first) = cmults(last) = Min(deg, Max( cmults(first), cmults(last)));
755 mults = new TColStd_HArray1OfInteger(1,cmults.Length());
756 mults->ChangeArray1() = cmults;
758 // compute new number of poles;
759 Standard_Integer nbp = BSplCLib::NbPoles(deg,Standard_True,cmults);
761 Handle(TColgp_HArray1OfPnt) tp = poles;
762 TColgp_Array1OfPnt cpoles((poles->Array1())(1),1,nbp);
763 poles = new TColgp_HArray1OfPnt(1,nbp);
764 poles->ChangeArray1() = cpoles;
767 Handle(TColStd_HArray1OfReal) tw = weights;
768 TColStd_Array1OfReal cweights((weights->Array1())(1),1,nbp);
769 weights = new TColStd_HArray1OfReal(1,nbp);
770 weights->ChangeArray1() = cweights;
773 periodic = Standard_True;
779 //=======================================================================
780 //function : SetOrigin
782 //=======================================================================
784 void Geom_BSplineCurve::SetOrigin(const Standard_Integer Index)
786 Standard_NoSuchObject_Raise_if( !periodic,
787 "Geom_BSplineCurve::SetOrigin");
788 Standard_Integer i,k;
789 Standard_Integer first = FirstUKnotIndex();
790 Standard_Integer last = LastUKnotIndex();
792 Standard_DomainError_Raise_if( (Index < first) || (Index > last),
793 "Geom_BSplineCurve::SetOrigine");
795 Standard_Integer nbknots = knots->Length();
796 Standard_Integer nbpoles = poles->Length();
798 Handle(TColStd_HArray1OfReal) nknots =
799 new TColStd_HArray1OfReal(1,nbknots);
800 TColStd_Array1OfReal& newknots = nknots->ChangeArray1();
802 Handle(TColStd_HArray1OfInteger) nmults =
803 new TColStd_HArray1OfInteger(1,nbknots);
804 TColStd_Array1OfInteger& newmults = nmults->ChangeArray1();
806 // set the knots and mults
807 Standard_Real period = knots->Value(last) - knots->Value(first);
809 for ( i = Index; i <= last ; i++) {
810 newknots(k) = knots->Value(i);
811 newmults(k) = mults->Value(i);
814 for ( i = first+1; i <= Index; i++) {
815 newknots(k) = knots->Value(i) + period;
816 newmults(k) = mults->Value(i);
820 Standard_Integer index = 1;
821 for (i = first+1; i <= Index; i++)
822 index += mults->Value(i);
824 // set the poles and weights
825 Handle(TColgp_HArray1OfPnt) npoles =
826 new TColgp_HArray1OfPnt(1,nbpoles);
827 Handle(TColStd_HArray1OfReal) nweights =
828 new TColStd_HArray1OfReal(1,nbpoles);
829 TColgp_Array1OfPnt & newpoles = npoles->ChangeArray1();
830 TColStd_Array1OfReal & newweights = nweights->ChangeArray1();
831 first = poles->Lower();
832 last = poles->Upper();
835 for ( i = index; i <= last; i++) {
836 newpoles(k) = poles->Value(i);
837 newweights(k) = weights->Value(i);
840 for ( i = first; i < index; i++) {
841 newpoles(k) = poles->Value(i);
842 newweights(k) = weights->Value(i);
848 for ( i = index; i <= last; i++) {
849 newpoles(k) = poles->Value(i);
852 for ( i = first; i < index; i++) {
853 newpoles(k) = poles->Value(i);
867 //=======================================================================
868 //function : SetOrigin
870 //=======================================================================
872 void Geom_BSplineCurve::SetOrigin(const Standard_Real U,
873 const Standard_Real Tol)
875 Standard_NoSuchObject_Raise_if( !periodic,
876 "Geom_BSplineCurve::SetOrigin");
877 //U est il dans la period.
878 Standard_Real uf = FirstParameter(), ul = LastParameter();
879 Standard_Real u = U, period = ul - uf;
880 while (Tol < (uf-u)) u += period;
881 while (Tol > (ul-u)) u -= period;
883 if(Abs(U-u)>Tol) { //On reparametre la courbe
884 Standard_Real delta = U-u;
887 TColStd_Array1OfReal& kn = knots->ChangeArray1();
888 Standard_Integer fk = kn.Lower(), lk = kn.Upper();
889 for(Standard_Integer i = fk; i <= lk; i++){
890 kn.ChangeValue(i) += delta;
894 if(Abs(U-uf)<Tol) return;
896 TColStd_Array1OfReal& kn = knots->ChangeArray1();
897 Standard_Integer fk = kn.Lower(), lk = kn.Upper(),ik=0;
898 Standard_Real delta = RealLast();
899 for(Standard_Integer i = fk; i<= lk; i++){
900 Standard_Real dki = kn.Value(i)-U;
901 if(Abs(dki)<Abs(delta)){
913 //=======================================================================
914 //function : SetNotPeriodic
916 //=======================================================================
918 void Geom_BSplineCurve::SetNotPeriodic ()
921 Standard_Integer NbKnots, NbPoles;
922 BSplCLib::PrepareUnperiodize( deg, mults->Array1(),NbKnots,NbPoles);
924 Handle(TColgp_HArray1OfPnt) npoles
925 = new TColgp_HArray1OfPnt(1,NbPoles);
927 Handle(TColStd_HArray1OfReal) nknots
928 = new TColStd_HArray1OfReal(1,NbKnots);
930 Handle(TColStd_HArray1OfInteger) nmults
931 = new TColStd_HArray1OfInteger(1,NbKnots);
933 Handle(TColStd_HArray1OfReal) nweights;
937 nweights = new TColStd_HArray1OfReal(1,NbPoles);
939 BSplCLib::Unperiodize
940 (deg,mults->Array1(),knots->Array1(),poles->Array1(),
941 &weights->Array1(),nmults->ChangeArray1(),
942 nknots->ChangeArray1(),npoles->ChangeArray1(),
943 &nweights->ChangeArray1());
948 BSplCLib::Unperiodize
949 (deg,mults->Array1(),knots->Array1(),poles->Array1(),
950 BSplCLib::NoWeights(),nmults->ChangeArray1(),
951 nknots->ChangeArray1(),npoles->ChangeArray1(),
952 BSplCLib::NoWeights());
959 periodic = Standard_False;
966 //=======================================================================
969 //=======================================================================
971 void Geom_BSplineCurve::SetPole
972 (const Standard_Integer Index,
975 if (Index < 1 || Index > poles->Length()) Standard_OutOfRange::Raise();
976 poles->SetValue (Index, P);
980 //=======================================================================
983 //=======================================================================
985 void Geom_BSplineCurve::SetPole
986 (const Standard_Integer Index,
988 const Standard_Real W)
994 //=======================================================================
995 //function : SetWeight
997 //=======================================================================
999 void Geom_BSplineCurve::SetWeight
1000 (const Standard_Integer Index,
1001 const Standard_Real W)
1003 if (Index < 1 || Index > poles->Length()) Standard_OutOfRange::Raise();
1005 if (W <= gp::Resolution ()) Standard_ConstructionError::Raise();
1008 Standard_Boolean rat = IsRational() || (Abs(W - 1.) > gp::Resolution());
1011 if (rat && !IsRational()) {
1012 weights = new TColStd_HArray1OfReal(1,poles->Length());
1016 weights->SetValue (Index, W);
1019 rat = Rational(weights->Array1());
1020 if (!rat) weights.Nullify();
1023 rational = !weights.IsNull();
1028 //=======================================================================
1029 //function : MovePoint
1031 //=======================================================================
1033 void Geom_BSplineCurve::MovePoint(const Standard_Real U,
1035 const Standard_Integer Index1,
1036 const Standard_Integer Index2,
1037 Standard_Integer& FirstModifiedPole,
1038 Standard_Integer& LastmodifiedPole)
1040 if (Index1 < 1 || Index1 > poles->Length() ||
1041 Index2 < 1 || Index2 > poles->Length() || Index1 > Index2) {
1042 Standard_OutOfRange::Raise();
1044 TColgp_Array1OfPnt npoles(1, poles->Length());
1047 gp_Vec Displ(P0, P);
1048 BSplCLib::MovePoint(U, Displ, Index1, Index2, deg, rational, poles->Array1(),
1049 weights->Array1(), flatknots->Array1(),
1050 FirstModifiedPole, LastmodifiedPole, npoles);
1051 if (FirstModifiedPole) {
1052 poles->ChangeArray1() = npoles;
1057 //=======================================================================
1058 //function : MovePointAndTangent
1060 //=======================================================================
1062 void Geom_BSplineCurve::MovePointAndTangent(const Standard_Real U,
1064 const gp_Vec& Tangent,
1065 const Standard_Real Tolerance,
1066 const Standard_Integer StartingCondition,
1067 const Standard_Integer EndingCondition,
1068 Standard_Integer& ErrorStatus)
1070 Standard_Integer ii ;
1073 // for the time being do not deal with periodic curves
1077 TColgp_Array1OfPnt new_poles(1, poles->Length());
1081 gp_Vec delta_derivative;
1084 gp_Vec delta(P0, P);
1085 for (ii = 1 ; ii <= 3 ; ii++) {
1086 delta_derivative.SetCoord(ii, Tangent.Coord(ii)-delta_derivative.Coord(ii));
1088 BSplCLib::MovePointAndTangent(U,
1098 flatknots->Array1(),
1102 poles->ChangeArray1() = new_poles;
1107 //=======================================================================
1108 //function : UpdateKnots
1110 //=======================================================================
1112 void Geom_BSplineCurve::UpdateKnots()
1114 rational = !weights.IsNull();
1116 Standard_Integer MaxKnotMult = 0;
1117 BSplCLib::KnotAnalysis(deg,
1121 knotSet, MaxKnotMult);
1123 if (knotSet == GeomAbs_Uniform && !periodic) {
1127 flatknots = new TColStd_HArray1OfReal
1128 (1, BSplCLib::KnotSequenceLength(mults->Array1(),deg,periodic));
1130 BSplCLib::KnotSequence(knots->Array1(),
1133 flatknots->ChangeArray1());
1136 if (MaxKnotMult == 0) smooth = GeomAbs_CN;
1138 switch (deg - MaxKnotMult) {
1139 case 0 : smooth = GeomAbs_C0; break;
1140 case 1 : smooth = GeomAbs_C1; break;
1141 case 2 : smooth = GeomAbs_C2; break;
1142 case 3 : smooth = GeomAbs_C3; break;
1143 default : smooth = GeomAbs_C3; break;
1148 //=======================================================================
1149 //function : Normalizes the parameters if the curve is periodic
1150 //purpose : that is compute the cache so that it is valid
1151 //=======================================================================
1153 void Geom_BSplineCurve::PeriodicNormalization(Standard_Real& Parameter) const
1155 Standard_Real Period ;
1158 Period = flatknots->Value(flatknots->Upper() - deg) - flatknots->Value (deg + 1) ;
1159 while (Parameter > flatknots->Value(flatknots->Upper()-deg)) {
1160 Parameter -= Period ;
1162 while (Parameter < flatknots->Value((deg + 1))) {
1163 Parameter += Period ;