1 // Created on: 1993-03-25
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 Geom2d_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, Init methods, Remove typedefs
25 // 14-Mar-96 : xab implemented MovePointAndTangent
27 //SAMTECH Jan 2002 : add text to Raise()
29 #define No_Standard_OutOfRange
32 #include <BSplCLib.hxx>
33 #include <BSplCLib_KnotDistribution.hxx>
34 #include <BSplCLib_MultDistribution.hxx>
35 #include <Geom2d_BSplineCurve.hxx>
36 #include <Geom2d_Geometry.hxx>
37 #include <Geom2d_UndefinedDerivative.hxx>
39 #include <gp_Pnt2d.hxx>
40 #include <gp_Trsf2d.hxx>
41 #include <gp_Vec2d.hxx>
42 #include <Precision.hxx>
43 #include <Standard_ConstructionError.hxx>
44 #include <Standard_DimensionError.hxx>
45 #include <Standard_DomainError.hxx>
46 #include <Standard_NoSuchObject.hxx>
47 #include <Standard_NotImplemented.hxx>
48 #include <Standard_OutOfRange.hxx>
49 #include <Standard_RangeError.hxx>
50 #include <Standard_Type.hxx>
52 IMPLEMENT_STANDARD_RTTIEXT(Geom2d_BSplineCurve,Geom2d_BoundedCurve)
54 //=======================================================================
55 //function : CheckCurveData
56 //purpose : Internal use only
57 //=======================================================================
58 static void CheckCurveData
59 (const TColgp_Array1OfPnt2d& CPoles,
60 const TColStd_Array1OfReal& CKnots,
61 const TColStd_Array1OfInteger& CMults,
62 const Standard_Integer Degree,
63 const Standard_Boolean Periodic)
65 if (Degree < 1 || Degree > Geom2d_BSplineCurve::MaxDegree()) {
66 Standard_ConstructionError::Raise("BSpline curve : invalid degree");
69 if (CPoles.Length() < 2) Standard_ConstructionError::Raise("BSpline curve : at least 2 poles required");
70 if (CKnots.Length() != CMults.Length()) Standard_ConstructionError::Raise("BSpline curve : Knot and Mult array size mismatch");
72 for (Standard_Integer I = CKnots.Lower(); I < CKnots.Upper(); I++) {
73 if (CKnots (I+1) - CKnots (I) <= Epsilon (Abs(CKnots (I)))) {
74 Standard_ConstructionError::Raise("BSpline curve : Knots interval values too close");
78 if (CPoles.Length() != BSplCLib::NbPoles(Degree,Periodic,CMults))
79 Standard_ConstructionError::Raise("BSpline curve : # Poles and degree mismatch");
82 //=======================================================================
84 //purpose : check rationality of an array of weights
85 //=======================================================================
87 static Standard_Boolean Rational(const TColStd_Array1OfReal& W)
89 Standard_Integer i, n = W.Length();
90 Standard_Boolean rat = Standard_False;
91 for (i = 1; i < n; i++) {
92 rat = Abs(W(i) - W(i+1)) > gp::Resolution();
98 //=======================================================================
101 //=======================================================================
103 Handle(Geom2d_Geometry) Geom2d_BSplineCurve::Copy() const
105 Handle(Geom2d_BSplineCurve) C;
107 C = new Geom2d_BSplineCurve(poles->Array1(),
113 C = new Geom2d_BSplineCurve(poles->Array1(),
120 //=======================================================================
121 //function : Geom2d_BSplineCurve
123 //=======================================================================
125 Geom2d_BSplineCurve::Geom2d_BSplineCurve
126 (const TColgp_Array1OfPnt2d& Poles,
127 const TColStd_Array1OfReal& Knots,
128 const TColStd_Array1OfInteger& Mults,
129 const Standard_Integer Degree,
130 const Standard_Boolean Periodic) :
131 rational(Standard_False),
134 maxderivinvok(Standard_False)
138 CheckCurveData(Poles,
146 poles = new TColgp_HArray1OfPnt2d(1,Poles.Length());
147 poles->ChangeArray1() = Poles;
149 knots = new TColStd_HArray1OfReal(1,Knots.Length());
150 knots->ChangeArray1() = Knots;
152 mults = new TColStd_HArray1OfInteger(1,Mults.Length());
153 mults->ChangeArray1() = Mults;
158 //=======================================================================
159 //function : Geom2d_BSplineCurve
161 //=======================================================================
163 Geom2d_BSplineCurve::Geom2d_BSplineCurve
164 (const TColgp_Array1OfPnt2d& Poles,
165 const TColStd_Array1OfReal& Weights,
166 const TColStd_Array1OfReal& Knots,
167 const TColStd_Array1OfInteger& Mults,
168 const Standard_Integer Degree,
169 const Standard_Boolean Periodic) :
170 rational(Standard_True),
173 maxderivinvok(Standard_False)
179 CheckCurveData(Poles,
185 if (Weights.Length() != Poles.Length())
186 Standard_ConstructionError::Raise("Geom2d_BSplineCurve :Weights and Poles array size mismatch");
189 for (i = Weights.Lower(); i <= Weights.Upper(); i++) {
190 if (Weights(i) <= gp::Resolution()) {
191 Standard_ConstructionError::Raise("Geom2d_BSplineCurve: Weights values too small");
195 // check really rational
196 rational = Rational(Weights);
200 poles = new TColgp_HArray1OfPnt2d(1,Poles.Length());
201 poles->ChangeArray1() = Poles;
203 weights = new TColStd_HArray1OfReal(1,Weights.Length());
204 weights->ChangeArray1() = Weights;
207 knots = new TColStd_HArray1OfReal(1,Knots.Length());
208 knots->ChangeArray1() = Knots;
210 mults = new TColStd_HArray1OfInteger(1,Mults.Length());
211 mults->ChangeArray1() = Mults;
216 //=======================================================================
217 //function : MaxDegree
219 //=======================================================================
221 Standard_Integer Geom2d_BSplineCurve::MaxDegree ()
223 return BSplCLib::MaxDegree();
226 //=======================================================================
227 //function : IncreaseDegree
229 //=======================================================================
231 void Geom2d_BSplineCurve::IncreaseDegree
232 (const Standard_Integer Degree)
234 if (Degree == deg) return;
236 if (Degree < deg || Degree > Geom2d_BSplineCurve::MaxDegree()) {
237 Standard_ConstructionError::Raise("BSpline curve : IncreaseDegree : bad degree value");
240 Standard_Integer FromK1 = FirstUKnotIndex ();
241 Standard_Integer ToK2 = LastUKnotIndex ();
243 Standard_Integer Step = Degree - deg;
245 Handle(TColgp_HArray1OfPnt2d) npoles = new
246 TColgp_HArray1OfPnt2d(1,poles->Length() + Step * (ToK2-FromK1));
248 Standard_Integer nbknots = BSplCLib::IncreaseDegreeCountKnots
249 (deg,Degree,periodic,mults->Array1());
251 Handle(TColStd_HArray1OfReal) nknots =
252 new TColStd_HArray1OfReal(1,nbknots);
254 Handle(TColStd_HArray1OfInteger) nmults =
255 new TColStd_HArray1OfInteger(1,nbknots);
257 Handle(TColStd_HArray1OfReal) nweights;
261 nweights = new TColStd_HArray1OfReal(1,npoles->Upper());
263 BSplCLib::IncreaseDegree
264 (deg,Degree, periodic,
265 poles->Array1(),&weights->Array1(),
266 knots->Array1(),mults->Array1(),
267 npoles->ChangeArray1(),&nweights->ChangeArray1(),
268 nknots->ChangeArray1(),nmults->ChangeArray1());
272 BSplCLib::IncreaseDegree
273 (deg,Degree, periodic,
275 BSplCLib::NoWeights(),
276 knots->Array1(),mults->Array1(),
277 npoles->ChangeArray1(),
278 BSplCLib::NoWeights(),
279 nknots->ChangeArray1(),nmults->ChangeArray1());
290 //=======================================================================
291 //function : IncreaseMultiplicity
293 //=======================================================================
295 void Geom2d_BSplineCurve::IncreaseMultiplicity
296 (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 Geom2d_BSplineCurve::IncreaseMultiplicity
312 (const Standard_Integer I1,
313 const Standard_Integer I2,
314 const Standard_Integer M)
316 Handle(TColStd_HArray1OfReal) tk = knots;
317 TColStd_Array1OfReal k((knots->Array1())(I1),I1,I2);
318 TColStd_Array1OfInteger m(I1,I2);
320 for (i = I1; i <= I2; i++)
321 m(i) = M - mults->Value(i);
322 InsertKnots(k,m,Epsilon(1.),Standard_True);
325 //=======================================================================
326 //function : IncrementMultiplicity
328 //=======================================================================
330 void Geom2d_BSplineCurve::IncrementMultiplicity
331 (const Standard_Integer I1,
332 const Standard_Integer I2,
333 const Standard_Integer Step)
335 Handle(TColStd_HArray1OfReal) tk = knots;
336 TColStd_Array1OfReal k((knots->Array1())(I1),I1,I2);
337 TColStd_Array1OfInteger m(I1,I2);
339 InsertKnots(k,m,Epsilon(1.),Standard_True);
342 //=======================================================================
343 //function : InsertKnot
345 //=======================================================================
347 void Geom2d_BSplineCurve::InsertKnot
348 (const Standard_Real U,
349 const Standard_Integer M,
350 const Standard_Real ParametricTolerance)
352 TColStd_Array1OfReal k(1,1);
354 TColStd_Array1OfInteger m(1,1);
356 InsertKnots(k,m,ParametricTolerance);
359 //=======================================================================
360 //function : InsertKnots
362 //=======================================================================
363 void Geom2d_BSplineCurve::InsertKnots(const TColStd_Array1OfReal& Knots,
364 const TColStd_Array1OfInteger& Mults,
365 const Standard_Real Epsilon,
366 const Standard_Boolean Add)
368 // Check and compute new sizes
369 Standard_Integer nbpoles,nbknots;
371 if (!BSplCLib::PrepareInsertKnots(deg,periodic,
372 knots->Array1(),mults->Array1(),
373 Knots,&Mults,nbpoles,nbknots,Epsilon,Add))
374 Standard_ConstructionError::Raise("Geom2d_BSplineCurve::InsertKnots");
376 if (nbpoles == poles->Length()) return;
378 Handle(TColgp_HArray1OfPnt2d) npoles = new TColgp_HArray1OfPnt2d(1,nbpoles);
379 Handle(TColStd_HArray1OfReal) nknots = knots;
380 Handle(TColStd_HArray1OfInteger) nmults = mults;
382 if (nbknots != knots->Length()) {
383 nknots = new TColStd_HArray1OfReal(1,nbknots);
384 nmults = new TColStd_HArray1OfInteger(1,nbknots);
388 Handle(TColStd_HArray1OfReal) nweights =
389 new TColStd_HArray1OfReal(1,nbpoles);
390 BSplCLib::InsertKnots(deg,periodic,
391 poles->Array1(), &weights->Array1(),
392 knots->Array1(), mults->Array1(),
394 npoles->ChangeArray1(), &nweights->ChangeArray1(),
395 nknots->ChangeArray1(), nmults->ChangeArray1(),
400 BSplCLib::InsertKnots(deg,periodic,
402 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 Geom2d_BSplineCurve::RemoveKnot
424 (const Standard_Integer Index,
425 const Standard_Integer M,
426 const Standard_Real Tolerance)
428 if (M < 0) return Standard_True;
430 Standard_Integer I1 = FirstUKnotIndex ();
431 Standard_Integer I2 = LastUKnotIndex ();
433 if (Index < I1 || Index > I2) {
434 Standard_OutOfRange::Raise("BSpline curve : RemoveKnot : index out of range");
437 const TColgp_Array1OfPnt2d & oldpoles = poles->Array1();
439 Standard_Integer step = mults->Value(Index) - M;
440 if (step <= 0) return Standard_True;
442 Handle(TColgp_HArray1OfPnt2d) npoles =
443 new TColgp_HArray1OfPnt2d(1,oldpoles.Length()-step);
445 Handle(TColStd_HArray1OfReal) nknots = knots;
446 Handle(TColStd_HArray1OfInteger) nmults = mults;
449 nknots = new TColStd_HArray1OfReal(1,knots->Length()-1);
450 nmults = new TColStd_HArray1OfInteger(1,knots->Length()-1);
454 Handle(TColStd_HArray1OfReal) nweights =
455 new TColStd_HArray1OfReal(1,npoles->Length());
456 if (!BSplCLib::RemoveKnot
457 (Index, M, deg, periodic,
458 poles->Array1(),&weights->Array1(),
459 knots->Array1(),mults->Array1(),
460 npoles->ChangeArray1(), &nweights->ChangeArray1(),
461 nknots->ChangeArray1(),nmults->ChangeArray1(),
463 return Standard_False;
467 if (!BSplCLib::RemoveKnot
468 (Index, M, deg, periodic,
470 BSplCLib::NoWeights(),
471 knots->Array1(),mults->Array1(),
472 npoles->ChangeArray1(),
473 BSplCLib::NoWeights(),
474 nknots->ChangeArray1(),nmults->ChangeArray1(),
476 return Standard_False;
485 return Standard_True;
488 //=======================================================================
489 //function : InsertPoleAfter
491 //=======================================================================
493 void Geom2d_BSplineCurve::InsertPoleAfter
494 (const Standard_Integer Index,
496 const Standard_Real Weight)
498 if (Index < 0 || Index > poles->Length()) Standard_OutOfRange::Raise("BSpline curve : InsertPoleAfter: Index and #pole mismatch");
500 if (Weight <= gp::Resolution()) Standard_ConstructionError::Raise("BSpline curve : InsertPoleAfter: Weight too small");
502 if (knotSet == GeomAbs_NonUniform || knotSet == GeomAbs_PiecewiseBezier) {
503 Standard_ConstructionError::Raise("BSpline curve : InsertPoleAfter : bad knotSet type");
506 const TColStd_Array1OfReal& cknots = knots->Array1();
507 Standard_Integer nbknots = cknots.Length();
509 Handle(TColStd_HArray1OfReal) nknots =
510 new TColStd_HArray1OfReal(1,nbknots+1);
512 TColStd_Array1OfReal& newknots = nknots->ChangeArray1();
515 for (i = 1; i < nbknots; i++) {
516 newknots (i) = cknots(i);
519 newknots (nbknots+1) = 2 * newknots (nbknots) - newknots(nbknots-1);
521 Handle(TColStd_HArray1OfInteger) nmults =
522 new TColStd_HArray1OfInteger(1,nbknots+1);
524 TColStd_Array1OfInteger& newmults = nmults->ChangeArray1();
525 const TColStd_Array1OfInteger& cmults = mults->Array1();
527 for (i = 2; i <= nbknots; i++) newmults (i) = 1;
528 newmults (1) = cmults(1);
529 newmults (nbknots+1) = cmults(nbknots+1);
531 const TColgp_Array1OfPnt2d& cpoles = poles->Array1();
532 Standard_Integer nbpoles = cpoles.Length();
533 Handle(TColgp_HArray1OfPnt2d) npoles =
534 new TColgp_HArray1OfPnt2d(1, nbpoles+1);
535 TColgp_Array1OfPnt2d& newpoles = npoles->ChangeArray1();
539 for (i = 1; i <= Index; i++)
540 newpoles(i) = cpoles(i);
542 newpoles(Index+1) = P;
544 for (i = Index+1; i <= nbpoles; i++)
545 newpoles(i+1) = cpoles(i);
549 Handle(TColStd_HArray1OfReal) nweights;
550 Standard_Boolean rat = IsRational() || Abs(Weight-1.) > gp::Resolution();
553 nweights = new TColStd_HArray1OfReal(1,nbpoles+1);
554 TColStd_Array1OfReal& newweights = nweights->ChangeArray1();
556 for (i = 1; i <= Index; i++)
558 newweights(i) = weights->Value(i);
562 newweights(Index+1) = Weight;
564 for (i = Index+1; i <= nbpoles; i++)
566 newweights(i+1) = weights->Value(i);
568 newweights(i+1) = 1.;
579 //=======================================================================
580 //function : InsertPoleBefore
582 //=======================================================================
584 void Geom2d_BSplineCurve::InsertPoleBefore
585 (const Standard_Integer Index,
587 const Standard_Real Weight)
589 InsertPoleAfter(Index-1,P,Weight);
592 //=======================================================================
593 //function : RemovePole
595 //=======================================================================
597 void Geom2d_BSplineCurve::RemovePole
598 (const Standard_Integer Index)
600 if (Index < 1 || Index > poles->Length()) Standard_OutOfRange::Raise("BSpline curve :RemovePole : Index and #pole mismatch");
602 if (poles->Length() <= 2) Standard_ConstructionError::Raise("BSpline curve : RemovePole : #pole is already minimum");
604 if (knotSet == GeomAbs_NonUniform || knotSet == GeomAbs_PiecewiseBezier)
605 Standard_ConstructionError::Raise("BSpline curve : RemovePole: bad knotSet type");
608 Handle(TColStd_HArray1OfReal) nknots =
609 new TColStd_HArray1OfReal(1,knots->Length()-1);
610 TColStd_Array1OfReal& newknots = nknots->ChangeArray1();
612 Handle(TColStd_HArray1OfInteger) nmults =
613 new TColStd_HArray1OfInteger(1,mults->Length()-1);
614 TColStd_Array1OfInteger& newmults = nmults->ChangeArray1();
616 for (i = 1; i < newknots.Length(); i++) {
617 newknots (i) = knots->Value (i);
620 newmults(1) = mults->Value(1);
621 newknots(newknots.Upper()) = knots->Value (knots->Upper());
622 newmults(newmults.Upper()) = mults->Value (mults->Upper());
625 Handle(TColgp_HArray1OfPnt2d) npoles =
626 new TColgp_HArray1OfPnt2d(1, poles->Upper()-1);
627 TColgp_Array1OfPnt2d& newpoles = npoles->ChangeArray1();
629 for (i = 1; i < Index; i++)
630 newpoles(i) = poles->Value(i);
631 for (i = Index; i < newpoles.Length(); i++)
632 newpoles(i) = poles->Value(i+1);
634 Handle(TColStd_HArray1OfReal) nweights;
636 nweights = new TColStd_HArray1OfReal(1,newpoles.Length());
637 TColStd_Array1OfReal& newweights = nweights->ChangeArray1();
638 for (i = 1; i < Index; i++)
639 newweights(i) = weights->Value(i);
640 for (i = Index; i < newweights.Length(); i++)
641 newweights(i) = weights->Value(i+1);
651 //=======================================================================
654 //=======================================================================
656 void Geom2d_BSplineCurve::Reverse ()
658 BSplCLib::Reverse(knots->ChangeArray1());
659 BSplCLib::Reverse(mults->ChangeArray1());
660 Standard_Integer last;
662 last = flatknots->Upper() - deg - 1;
664 last = poles->Upper();
665 BSplCLib::Reverse(poles->ChangeArray1(),last);
667 BSplCLib::Reverse(weights->ChangeArray1(),last);
671 //=======================================================================
672 //function : ReversedParameter
674 //=======================================================================
676 Standard_Real Geom2d_BSplineCurve::ReversedParameter( const Standard_Real U) const
678 return (FirstParameter() + LastParameter() - U);
681 //=======================================================================
684 //=======================================================================
685 void Geom2d_BSplineCurve::Segment(const Standard_Real aU1,
686 const Standard_Real aU2)
688 Standard_DomainError_Raise_if ( aU2 < aU1, "Geom2d_BSplineCurve::Segment");
690 Standard_Real AbsUMax = Max(Abs(FirstParameter()),Abs(LastParameter()));
691 Standard_Real Eps = Max (Epsilon(AbsUMax), Precision::PConfusion());
692 Standard_Real NewU1, NewU2;
693 Standard_Real U, DU=0;
694 Standard_Integer i, k, index;
697 // Checking the input bounds aUj (j=1,2).
698 // For the case when aUj==knot(i),
699 // in order to prevent the insertion of a new knot that will be too closed
700 // to the existing knot,
701 // we assign Uj=knot(i)
702 Standard_Integer n1, n2;
703 Standard_Real U1, U2;
709 for (i=n1; i<=n2; ++i) {
711 if (Abs(U-aU1)<=Eps) {
714 else if (Abs(U-aU2)<=Eps) {
718 // Henceforward we use U1, U2 as bounds of the segment
721 TColStd_Array1OfReal Knots(1,2);
722 TColStd_Array1OfInteger Mults(1,2);
724 // define param ditance to keep (eap, Apr 18 2002, occ311)
726 Standard_Real Period = LastParameter() - FirstParameter();
728 while (DU > Period) {
731 if (DU <= Epsilon(Period)) {
737 BSplCLib::LocateParameter(deg,knots->Array1(),mults->Array1(),
738 U1,periodic,knots->Lower(),knots->Upper(),
741 BSplCLib::LocateParameter(deg,knots->Array1(),mults->Array1(),
742 U2,periodic,knots->Lower(),knots->Upper(),
744 Knots(1) = Min( NewU1, NewU2);
745 Knots(2) = Max( NewU1, NewU2);
746 Mults(1) = Mults( 2) = deg;
747 InsertKnots(Knots, Mults, Eps);
749 if (periodic) { // set the origine at NewU1
751 BSplCLib::LocateParameter(deg,knots->Array1(),mults->Array1(),
752 U1,periodic,knots->Lower(),knots->Upper(),
754 // Eps = Epsilon(knots->Value(index+1));
755 if ( Abs(knots->Value(index+1)-U) <= Eps) {
763 // compute index1 and index2 to set the new knots and mults
764 Standard_Integer index1 = 0, index2 = 0;
765 Standard_Integer FromU1 = knots->Lower();
766 Standard_Integer ToU2 = knots->Upper();
767 BSplCLib::LocateParameter(deg,knots->Array1(),mults->Array1(),
768 NewU1,periodic,FromU1,ToU2,index1,U);
769 BSplCLib::LocateParameter(deg,knots->Array1(),mults->Array1(),
770 NewU2,periodic,FromU1,ToU2,index2,U);
771 // Eps = Epsilon(knots->Value(index2+1));
772 if ( Abs(knots->Value(index2+1)-U) <= Eps){
776 Standard_Integer nbknots = index2 - index1 + 1;
778 Handle(TColStd_HArray1OfReal)
779 nknots = new TColStd_HArray1OfReal(1,nbknots);
780 Handle(TColStd_HArray1OfInteger)
781 nmults = new TColStd_HArray1OfInteger(1,nbknots);
783 // to restore changed U1
784 if (DU > 0) {// if was periodic
790 for ( i = index1; i<= index2; i++) {
791 nknots->SetValue(k, knots->Value(i) - DU);
792 nmults->SetValue(k, mults->Value(i));
795 nmults->SetValue( 1, deg + 1);
796 nmults->SetValue(nbknots, deg + 1);
799 // compute index1 and index2 to set the new poles and weights
800 Standard_Integer pindex1
801 = BSplCLib::PoleIndex(deg,index1,periodic,mults->Array1());
802 Standard_Integer pindex2
803 = BSplCLib::PoleIndex(deg,index2,periodic,mults->Array1());
806 pindex2 = Min( pindex2+1, poles->Length());
808 Standard_Integer nbpoles = pindex2 - pindex1 + 1;
810 Handle(TColStd_HArray1OfReal)
811 nweights = new TColStd_HArray1OfReal(1,nbpoles);
812 Handle(TColgp_HArray1OfPnt2d)
813 npoles = new TColgp_HArray1OfPnt2d(1,nbpoles);
817 nweights = new TColStd_HArray1OfReal( 1, nbpoles);
818 for ( i = pindex1; i <= pindex2; i++) {
819 npoles->SetValue(k, poles->Value(i));
820 nweights->SetValue(k, weights->Value(i));
825 for ( i = pindex1; i <= pindex2; i++) {
826 npoles->SetValue(k, poles->Value(i));
840 //=======================================================================
843 //=======================================================================
845 void Geom2d_BSplineCurve::SetKnot
846 (const Standard_Integer Index,
847 const Standard_Real K)
849 if (Index < 1 || Index > knots->Length()) Standard_OutOfRange::Raise("BSpline curve : SetKnot: Index and #pole mismatch");
850 Standard_Real DK = Abs(Epsilon (K));
852 if (K >= knots->Value(2) - DK) Standard_ConstructionError::Raise("BSpline curve :SetKnot :K out of range");
854 else if (Index == knots->Length()) {
855 if (K <= knots->Value (knots->Length()-1) + DK) {
856 Standard_ConstructionError::Raise("BSpline curve : SetKnot : K out of range");
860 if (K <= knots->Value(Index-1) + DK ||
861 K >= knots->Value(Index+1) - DK ) {
862 Standard_ConstructionError::Raise("BSpline curve : SetKnot: K out of range");
865 if (K != knots->Value (Index)) {
866 knots->SetValue (Index, K);
872 //=======================================================================
873 //function : SetKnots
875 //=======================================================================
877 void Geom2d_BSplineCurve::SetKnots
878 (const TColStd_Array1OfReal& K)
880 CheckCurveData(poles->Array1(),K,mults->Array1(),deg,periodic);
881 knots->ChangeArray1() = K;
886 //=======================================================================
889 //=======================================================================
891 void Geom2d_BSplineCurve::SetKnot
892 (const Standard_Integer Index,
893 const Standard_Real K,
894 const Standard_Integer M)
896 IncreaseMultiplicity (Index, M);
900 //=======================================================================
901 //function : SetPeriodic
903 //=======================================================================
905 void Geom2d_BSplineCurve::SetPeriodic ()
907 Standard_Integer first = FirstUKnotIndex();
908 Standard_Integer last = LastUKnotIndex();
910 Handle(TColStd_HArray1OfReal) tk = knots;
911 TColStd_Array1OfReal cknots((knots->Array1())(first),first,last);
912 knots = new TColStd_HArray1OfReal(1,cknots.Length());
913 knots->ChangeArray1() = cknots;
915 Handle(TColStd_HArray1OfInteger) tm = mults;
916 TColStd_Array1OfInteger cmults((mults->Array1())(first),first,last);
917 cmults(first) = cmults(last) = Min(deg, Max( cmults(first), cmults(last)));
918 mults = new TColStd_HArray1OfInteger(1,cmults.Length());
919 mults->ChangeArray1() = cmults;
921 // compute new number of poles;
922 Standard_Integer nbp = BSplCLib::NbPoles(deg,Standard_True,cmults);
924 Handle(TColgp_HArray1OfPnt2d) tp = poles;
925 TColgp_Array1OfPnt2d cpoles((poles->Array1())(1),1,nbp);
926 poles = new TColgp_HArray1OfPnt2d(1,nbp);
927 poles->ChangeArray1() = cpoles;
930 Handle(TColStd_HArray1OfReal) tw = weights;
931 TColStd_Array1OfReal cweights((weights->Array1())(1),1,nbp);
932 weights = new TColStd_HArray1OfReal(1,nbp);
933 weights->ChangeArray1() = cweights;
936 periodic = Standard_True;
942 //=======================================================================
943 //function : SetOrigin
945 //=======================================================================
947 void Geom2d_BSplineCurve::SetOrigin(const Standard_Integer Index)
949 Standard_NoSuchObject_Raise_if( !periodic,
950 "Geom2d_BSplineCurve::SetOrigin");
951 Standard_Integer i,k;
952 Standard_Integer first = FirstUKnotIndex();
953 Standard_Integer last = LastUKnotIndex();
955 Standard_DomainError_Raise_if( (Index < first) || (Index > last),
956 "Geom2d_BSplineCurve::SetOrigine");
958 Standard_Integer nbknots = knots->Length();
959 Standard_Integer nbpoles = poles->Length();
961 Handle(TColStd_HArray1OfReal) nknots =
962 new TColStd_HArray1OfReal(1,nbknots);
963 TColStd_Array1OfReal& newknots = nknots->ChangeArray1();
965 Handle(TColStd_HArray1OfInteger) nmults =
966 new TColStd_HArray1OfInteger(1,nbknots);
967 TColStd_Array1OfInteger& newmults = nmults->ChangeArray1();
969 // set the knots and mults
970 Standard_Real period = knots->Value(last) - knots->Value(first);
972 for ( i = Index; i <= last ; i++) {
973 newknots(k) = knots->Value(i);
974 newmults(k) = mults->Value(i);
977 for ( i = first+1; i <= Index; i++) {
978 newknots(k) = knots->Value(i) + period;
979 newmults(k) = mults->Value(i);
983 Standard_Integer index = 1;
984 for (i = first+1; i <= Index; i++)
985 index += mults->Value(i);
987 // set the poles and weights
988 Handle(TColgp_HArray1OfPnt2d) npoles =
989 new TColgp_HArray1OfPnt2d(1,nbpoles);
990 Handle(TColStd_HArray1OfReal) nweights =
991 new TColStd_HArray1OfReal(1,nbpoles);
992 TColgp_Array1OfPnt2d & newpoles = npoles->ChangeArray1();
993 TColStd_Array1OfReal & newweights = nweights->ChangeArray1();
994 first = poles->Lower();
995 last = poles->Upper();
998 for ( i = index; i <= last; i++) {
999 newpoles(k) = poles->Value(i);
1000 newweights(k) = weights->Value(i);
1003 for ( i = first; i < index; i++) {
1004 newpoles(k) = poles->Value(i);
1005 newweights(k) = weights->Value(i);
1011 for ( i = index; i <= last; i++) {
1012 newpoles(k) = poles->Value(i);
1015 for ( i = first; i < index; i++) {
1016 newpoles(k) = poles->Value(i);
1030 //=======================================================================
1031 //function : SetNotPeriodic
1033 //=======================================================================
1035 void Geom2d_BSplineCurve::SetNotPeriodic ()
1038 Standard_Integer NbKnots, NbPoles;
1039 BSplCLib::PrepareUnperiodize( deg, mults->Array1(),NbKnots,NbPoles);
1041 Handle(TColgp_HArray1OfPnt2d) npoles
1042 = new TColgp_HArray1OfPnt2d(1,NbPoles);
1044 Handle(TColStd_HArray1OfReal) nknots
1045 = new TColStd_HArray1OfReal(1,NbKnots);
1047 Handle(TColStd_HArray1OfInteger) nmults
1048 = new TColStd_HArray1OfInteger(1,NbKnots);
1050 Handle(TColStd_HArray1OfReal) nweights;
1054 nweights = new TColStd_HArray1OfReal(1,NbPoles);
1056 BSplCLib::Unperiodize
1057 (deg,mults->Array1(),knots->Array1(),poles->Array1(),
1058 &weights->Array1(),nmults->ChangeArray1(),
1059 nknots->ChangeArray1(),npoles->ChangeArray1(),
1060 &nweights->ChangeArray1());
1065 BSplCLib::Unperiodize
1066 (deg,mults->Array1(),knots->Array1(),poles->Array1(),
1067 BSplCLib::NoWeights(),nmults->ChangeArray1(),
1068 nknots->ChangeArray1(),npoles->ChangeArray1(),
1069 BSplCLib::NoWeights());
1076 periodic = Standard_False;
1082 //=======================================================================
1083 //function : SetPole
1085 //=======================================================================
1087 void Geom2d_BSplineCurve::SetPole
1088 (const Standard_Integer Index,
1091 if (Index < 1 || Index > poles->Length()) Standard_OutOfRange::Raise("BSpline curve : SetPole : index and #pole mismatch");
1092 poles->SetValue (Index, P);
1096 //=======================================================================
1097 //function : SetPole
1099 //=======================================================================
1101 void Geom2d_BSplineCurve::SetPole
1102 (const Standard_Integer Index,
1104 const Standard_Real W)
1110 //=======================================================================
1111 //function : SetWeight
1113 //=======================================================================
1115 void Geom2d_BSplineCurve::SetWeight
1116 (const Standard_Integer Index,
1117 const Standard_Real W)
1119 if (Index < 1 || Index > poles->Length()) Standard_OutOfRange::Raise("BSpline curve : SetWeight: Index and #pole mismatch");
1121 if (W <= gp::Resolution ()) Standard_ConstructionError::Raise("BSpline curve : SetWeight: Weight too small");
1124 Standard_Boolean rat = IsRational() || (Abs(W - 1.) > gp::Resolution());
1127 if (rat && !IsRational()) {
1128 weights = new TColStd_HArray1OfReal(1,poles->Length());
1132 weights->SetValue (Index, W);
1135 rat = Rational(weights->Array1());
1136 if (!rat) weights.Nullify();
1139 rational = !weights.IsNull();
1145 //=======================================================================
1146 //function : MovePoint
1148 //=======================================================================
1150 void Geom2d_BSplineCurve::MovePoint(const Standard_Real U,
1152 const Standard_Integer Index1,
1153 const Standard_Integer Index2,
1154 Standard_Integer& FirstModifiedPole,
1155 Standard_Integer& LastmodifiedPole)
1157 if (Index1 < 1 || Index1 > poles->Length() ||
1158 Index2 < 1 || Index2 > poles->Length() || Index1 > Index2) {
1159 Standard_OutOfRange::Raise("BSpline curve : MovePoint: Index and #pole mismatch");
1161 TColgp_Array1OfPnt2d npoles(1, poles->Length());
1164 gp_Vec2d Displ(P0, P);
1165 BSplCLib::MovePoint(U, Displ, Index1, Index2, deg, rational, poles->Array1(),
1166 weights->Array1(), flatknots->Array1(),
1167 FirstModifiedPole, LastmodifiedPole, npoles);
1168 if (FirstModifiedPole) {
1169 poles->ChangeArray1() = npoles;
1174 //=======================================================================
1175 //function : MovePointAndTangent
1177 //=======================================================================
1179 void Geom2d_BSplineCurve::
1180 MovePointAndTangent(const Standard_Real U,
1182 const gp_Vec2d& Tangent,
1183 const Standard_Real Tolerance,
1184 const Standard_Integer StartingCondition,
1185 const Standard_Integer EndingCondition,
1186 Standard_Integer& ErrorStatus)
1188 Standard_Integer ii ;
1191 // for the time being do not deal with periodic curves
1195 TColgp_Array1OfPnt2d new_poles(1, poles->Length());
1199 gp_Vec2d delta_derivative;
1202 gp_Vec2d delta(P0, P);
1203 for (ii = 1 ; ii <= 2 ; ii++) {
1204 delta_derivative.SetCoord(ii,
1205 Tangent.Coord(ii)- delta_derivative.Coord(ii)) ;
1207 BSplCLib::MovePointAndTangent(U,
1217 flatknots->Array1(),
1221 poles->ChangeArray1() = new_poles;
1226 //=======================================================================
1227 //function : UpdateKnots
1229 //=======================================================================
1231 void Geom2d_BSplineCurve::UpdateKnots()
1234 rational = !weights.IsNull();
1236 Standard_Integer MaxKnotMult = 0;
1237 BSplCLib::KnotAnalysis (deg,
1241 knotSet, MaxKnotMult);
1243 if (knotSet == GeomAbs_Uniform && !periodic) {
1247 flatknots = new TColStd_HArray1OfReal
1248 (1, BSplCLib::KnotSequenceLength(mults->Array1(),deg,periodic));
1250 BSplCLib::KnotSequence (knots->Array1(),
1253 flatknots->ChangeArray1());
1256 if (MaxKnotMult == 0) smooth = GeomAbs_CN;
1258 switch (deg - MaxKnotMult) {
1259 case 0 : smooth = GeomAbs_C0; break;
1260 case 1 : smooth = GeomAbs_C1; break;
1261 case 2 : smooth = GeomAbs_C2; break;
1262 case 3 : smooth = GeomAbs_C3; break;
1263 default : smooth = GeomAbs_C3; break;
1268 //=======================================================================
1269 //function : Normalizes the parameters if the curve is periodic
1270 //purpose : that is compute the cache so that it is valid
1271 //=======================================================================
1273 void Geom2d_BSplineCurve::PeriodicNormalization(Standard_Real& Parameter) const
1275 Standard_Real Period ;
1278 Period = flatknots->Value(flatknots->Upper() - deg) - flatknots->Value (deg + 1) ;
1279 while (Parameter > flatknots->Value(flatknots->Upper()-deg)) {
1280 Parameter -= Period ;
1282 while (Parameter < flatknots->Value((deg + 1))) {
1283 Parameter += Period ;