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 //=======================================================================
53 //function : CheckCurveData
54 //purpose : Internal use only
55 //=======================================================================
56 static void CheckCurveData
57 (const TColgp_Array1OfPnt2d& CPoles,
58 const TColStd_Array1OfReal& CKnots,
59 const TColStd_Array1OfInteger& CMults,
60 const Standard_Integer Degree,
61 const Standard_Boolean Periodic)
63 if (Degree < 1 || Degree > Geom2d_BSplineCurve::MaxDegree()) {
64 Standard_ConstructionError::Raise("BSpline curve : invalid degree");
67 if (CPoles.Length() < 2) Standard_ConstructionError::Raise("BSpline curve : at least 2 poles required");
68 if (CKnots.Length() != CMults.Length()) Standard_ConstructionError::Raise("BSpline curve : Knot and Mult array size mismatch");
70 for (Standard_Integer I = CKnots.Lower(); I < CKnots.Upper(); I++) {
71 if (CKnots (I+1) - CKnots (I) <= Epsilon (Abs(CKnots (I)))) {
72 Standard_ConstructionError::Raise("BSpline curve : Knots interval values too close");
76 if (CPoles.Length() != BSplCLib::NbPoles(Degree,Periodic,CMults))
77 Standard_ConstructionError::Raise("BSpline curve : # Poles and degree mismatch");
80 //=======================================================================
82 //purpose : check rationality of an array of weights
83 //=======================================================================
85 static Standard_Boolean Rational(const TColStd_Array1OfReal& W)
87 Standard_Integer i, n = W.Length();
88 Standard_Boolean rat = Standard_False;
89 for (i = 1; i < n; i++) {
90 rat = Abs(W(i) - W(i+1)) > gp::Resolution();
96 //=======================================================================
99 //=======================================================================
101 Handle(Geom2d_Geometry) Geom2d_BSplineCurve::Copy() const
103 Handle(Geom2d_BSplineCurve) C;
105 C = new Geom2d_BSplineCurve(poles->Array1(),
111 C = new Geom2d_BSplineCurve(poles->Array1(),
118 //=======================================================================
119 //function : Geom2d_BSplineCurve
121 //=======================================================================
123 Geom2d_BSplineCurve::Geom2d_BSplineCurve
124 (const TColgp_Array1OfPnt2d& Poles,
125 const TColStd_Array1OfReal& Knots,
126 const TColStd_Array1OfInteger& Mults,
127 const Standard_Integer Degree,
128 const Standard_Boolean Periodic) :
129 rational(Standard_False),
132 maxderivinvok(Standard_False)
136 CheckCurveData(Poles,
144 poles = new TColgp_HArray1OfPnt2d(1,Poles.Length());
145 poles->ChangeArray1() = Poles;
147 knots = new TColStd_HArray1OfReal(1,Knots.Length());
148 knots->ChangeArray1() = Knots;
150 mults = new TColStd_HArray1OfInteger(1,Mults.Length());
151 mults->ChangeArray1() = Mults;
156 //=======================================================================
157 //function : Geom2d_BSplineCurve
159 //=======================================================================
161 Geom2d_BSplineCurve::Geom2d_BSplineCurve
162 (const TColgp_Array1OfPnt2d& Poles,
163 const TColStd_Array1OfReal& Weights,
164 const TColStd_Array1OfReal& Knots,
165 const TColStd_Array1OfInteger& Mults,
166 const Standard_Integer Degree,
167 const Standard_Boolean Periodic) :
168 rational(Standard_True),
171 maxderivinvok(Standard_False)
177 CheckCurveData(Poles,
183 if (Weights.Length() != Poles.Length())
184 Standard_ConstructionError::Raise("Geom2d_BSplineCurve :Weights and Poles array size mismatch");
187 for (i = Weights.Lower(); i <= Weights.Upper(); i++) {
188 if (Weights(i) <= gp::Resolution()) {
189 Standard_ConstructionError::Raise("Geom2d_BSplineCurve: Weights values too small");
193 // check really rational
194 rational = Rational(Weights);
198 poles = new TColgp_HArray1OfPnt2d(1,Poles.Length());
199 poles->ChangeArray1() = Poles;
201 weights = new TColStd_HArray1OfReal(1,Weights.Length());
202 weights->ChangeArray1() = Weights;
205 knots = new TColStd_HArray1OfReal(1,Knots.Length());
206 knots->ChangeArray1() = Knots;
208 mults = new TColStd_HArray1OfInteger(1,Mults.Length());
209 mults->ChangeArray1() = Mults;
214 //=======================================================================
215 //function : MaxDegree
217 //=======================================================================
219 Standard_Integer Geom2d_BSplineCurve::MaxDegree ()
221 return BSplCLib::MaxDegree();
224 //=======================================================================
225 //function : IncreaseDegree
227 //=======================================================================
229 void Geom2d_BSplineCurve::IncreaseDegree
230 (const Standard_Integer Degree)
232 if (Degree == deg) return;
234 if (Degree < deg || Degree > Geom2d_BSplineCurve::MaxDegree()) {
235 Standard_ConstructionError::Raise("BSpline curve : IncreaseDegree : bad degree value");
238 Standard_Integer FromK1 = FirstUKnotIndex ();
239 Standard_Integer ToK2 = LastUKnotIndex ();
241 Standard_Integer Step = Degree - deg;
243 Handle(TColgp_HArray1OfPnt2d) npoles = new
244 TColgp_HArray1OfPnt2d(1,poles->Length() + Step * (ToK2-FromK1));
246 Standard_Integer nbknots = BSplCLib::IncreaseDegreeCountKnots
247 (deg,Degree,periodic,mults->Array1());
249 Handle(TColStd_HArray1OfReal) nknots =
250 new TColStd_HArray1OfReal(1,nbknots);
252 Handle(TColStd_HArray1OfInteger) nmults =
253 new TColStd_HArray1OfInteger(1,nbknots);
255 Handle(TColStd_HArray1OfReal) nweights;
259 nweights = new TColStd_HArray1OfReal(1,npoles->Upper());
261 BSplCLib::IncreaseDegree
262 (deg,Degree, periodic,
263 poles->Array1(),weights->Array1(),
264 knots->Array1(),mults->Array1(),
265 npoles->ChangeArray1(),nweights->ChangeArray1(),
266 nknots->ChangeArray1(),nmults->ChangeArray1());
270 BSplCLib::IncreaseDegree
271 (deg,Degree, periodic,
273 *((TColStd_Array1OfReal*) NULL),
274 knots->Array1(),mults->Array1(),
275 npoles->ChangeArray1(),
276 *((TColStd_Array1OfReal*) NULL),
277 nknots->ChangeArray1(),nmults->ChangeArray1());
288 //=======================================================================
289 //function : IncreaseMultiplicity
291 //=======================================================================
293 void Geom2d_BSplineCurve::IncreaseMultiplicity
294 (const Standard_Integer Index,
295 const Standard_Integer M)
297 TColStd_Array1OfReal k(1,1);
298 k(1) = knots->Value(Index);
299 TColStd_Array1OfInteger m(1,1);
300 m(1) = M - mults->Value(Index);
301 InsertKnots(k,m,Epsilon(1.),Standard_True);
304 //=======================================================================
305 //function : IncreaseMultiplicity
307 //=======================================================================
309 void Geom2d_BSplineCurve::IncreaseMultiplicity
310 (const Standard_Integer I1,
311 const Standard_Integer I2,
312 const Standard_Integer M)
314 Handle(TColStd_HArray1OfReal) tk = knots;
315 TColStd_Array1OfReal k((knots->Array1())(I1),I1,I2);
316 TColStd_Array1OfInteger m(I1,I2);
318 for (i = I1; i <= I2; i++)
319 m(i) = M - mults->Value(i);
320 InsertKnots(k,m,Epsilon(1.),Standard_True);
323 //=======================================================================
324 //function : IncrementMultiplicity
326 //=======================================================================
328 void Geom2d_BSplineCurve::IncrementMultiplicity
329 (const Standard_Integer I1,
330 const Standard_Integer I2,
331 const Standard_Integer Step)
333 Handle(TColStd_HArray1OfReal) tk = knots;
334 TColStd_Array1OfReal k((knots->Array1())(I1),I1,I2);
335 TColStd_Array1OfInteger m(I1,I2);
337 InsertKnots(k,m,Epsilon(1.),Standard_True);
340 //=======================================================================
341 //function : InsertKnot
343 //=======================================================================
345 void Geom2d_BSplineCurve::InsertKnot
346 (const Standard_Real U,
347 const Standard_Integer M,
348 const Standard_Real ParametricTolerance)
350 TColStd_Array1OfReal k(1,1);
352 TColStd_Array1OfInteger m(1,1);
354 InsertKnots(k,m,ParametricTolerance);
357 //=======================================================================
358 //function : InsertKnots
360 //=======================================================================
361 void Geom2d_BSplineCurve::InsertKnots(const TColStd_Array1OfReal& Knots,
362 const TColStd_Array1OfInteger& Mults,
363 const Standard_Real Epsilon,
364 const Standard_Boolean Add)
366 // Check and compute new sizes
367 Standard_Integer nbpoles,nbknots;
369 if (!BSplCLib::PrepareInsertKnots(deg,periodic,
370 knots->Array1(),mults->Array1(),
371 Knots,Mults,nbpoles,nbknots,Epsilon,Add))
372 Standard_ConstructionError::Raise("Geom2d_BSplineCurve::InsertKnots");
374 if (nbpoles == poles->Length()) return;
376 Handle(TColgp_HArray1OfPnt2d) npoles = new TColgp_HArray1OfPnt2d(1,nbpoles);
377 Handle(TColStd_HArray1OfReal) nknots = knots;
378 Handle(TColStd_HArray1OfInteger) nmults = mults;
380 if (nbknots != knots->Length()) {
381 nknots = new TColStd_HArray1OfReal(1,nbknots);
382 nmults = new TColStd_HArray1OfInteger(1,nbknots);
386 Handle(TColStd_HArray1OfReal) nweights =
387 new TColStd_HArray1OfReal(1,nbpoles);
388 BSplCLib::InsertKnots(deg,periodic,
389 poles->Array1(), weights->Array1(),
390 knots->Array1(), mults->Array1(),
392 npoles->ChangeArray1(), nweights->ChangeArray1(),
393 nknots->ChangeArray1(), nmults->ChangeArray1(),
398 BSplCLib::InsertKnots(deg,periodic,
400 *((TColStd_Array1OfReal*) NULL),
401 knots->Array1(), mults->Array1(),
403 npoles->ChangeArray1(),
404 *((TColStd_Array1OfReal*) NULL),
405 nknots->ChangeArray1(), nmults->ChangeArray1(),
416 //=======================================================================
417 //function : RemoveKnot
419 //=======================================================================
421 Standard_Boolean Geom2d_BSplineCurve::RemoveKnot
422 (const Standard_Integer Index,
423 const Standard_Integer M,
424 const Standard_Real Tolerance)
426 if (M < 0) return Standard_True;
428 Standard_Integer I1 = FirstUKnotIndex ();
429 Standard_Integer I2 = LastUKnotIndex ();
431 if (Index < I1 || Index > I2) {
432 Standard_OutOfRange::Raise("BSpline curve : RemoveKnot : index out of range");
435 const TColgp_Array1OfPnt2d & oldpoles = poles->Array1();
437 Standard_Integer step = mults->Value(Index) - M;
438 if (step <= 0) return Standard_True;
440 Handle(TColgp_HArray1OfPnt2d) npoles =
441 new TColgp_HArray1OfPnt2d(1,oldpoles.Length()-step);
443 Handle(TColStd_HArray1OfReal) nknots = knots;
444 Handle(TColStd_HArray1OfInteger) nmults = mults;
447 nknots = new TColStd_HArray1OfReal(1,knots->Length()-1);
448 nmults = new TColStd_HArray1OfInteger(1,knots->Length()-1);
452 Handle(TColStd_HArray1OfReal) nweights =
453 new TColStd_HArray1OfReal(1,npoles->Length());
454 if (!BSplCLib::RemoveKnot
455 (Index, M, deg, periodic,
456 poles->Array1(),weights->Array1(),
457 knots->Array1(),mults->Array1(),
458 npoles->ChangeArray1(), nweights->ChangeArray1(),
459 nknots->ChangeArray1(),nmults->ChangeArray1(),
461 return Standard_False;
465 if (!BSplCLib::RemoveKnot
466 (Index, M, deg, periodic,
468 *((TColStd_Array1OfReal*) NULL),
469 knots->Array1(),mults->Array1(),
470 npoles->ChangeArray1(),
471 *((TColStd_Array1OfReal*) NULL),
472 nknots->ChangeArray1(),nmults->ChangeArray1(),
474 return Standard_False;
483 return Standard_True;
486 //=======================================================================
487 //function : InsertPoleAfter
489 //=======================================================================
491 void Geom2d_BSplineCurve::InsertPoleAfter
492 (const Standard_Integer Index,
494 const Standard_Real Weight)
496 if (Index < 0 || Index > poles->Length()) Standard_OutOfRange::Raise("BSpline curve : InsertPoleAfter: Index and #pole mismatch");
498 if (Weight <= gp::Resolution()) Standard_ConstructionError::Raise("BSpline curve : InsertPoleAfter: Weight too small");
500 if (knotSet == GeomAbs_NonUniform || knotSet == GeomAbs_PiecewiseBezier) {
501 Standard_ConstructionError::Raise("BSpline curve : InsertPoleAfter : bad knotSet type");
504 const TColStd_Array1OfReal& cknots = knots->Array1();
505 Standard_Integer nbknots = cknots.Length();
507 Handle(TColStd_HArray1OfReal) nknots =
508 new TColStd_HArray1OfReal(1,nbknots+1);
510 TColStd_Array1OfReal& newknots = nknots->ChangeArray1();
513 for (i = 1; i < nbknots; i++) {
514 newknots (i) = cknots(i);
517 newknots (nbknots+1) = 2 * newknots (nbknots) - newknots(nbknots-1);
519 Handle(TColStd_HArray1OfInteger) nmults =
520 new TColStd_HArray1OfInteger(1,nbknots+1);
522 TColStd_Array1OfInteger& newmults = nmults->ChangeArray1();
523 const TColStd_Array1OfInteger& cmults = mults->Array1();
525 for (i = 2; i <= nbknots; i++) newmults (i) = 1;
526 newmults (1) = cmults(1);
527 newmults (nbknots+1) = cmults(nbknots+1);
529 const TColgp_Array1OfPnt2d& cpoles = poles->Array1();
530 Standard_Integer nbpoles = cpoles.Length();
531 Handle(TColgp_HArray1OfPnt2d) npoles =
532 new TColgp_HArray1OfPnt2d(1, nbpoles+1);
533 TColgp_Array1OfPnt2d& newpoles = npoles->ChangeArray1();
537 for (i = 1; i <= Index; i++)
538 newpoles(i) = cpoles(i);
540 newpoles(Index+1) = P;
542 for (i = Index+1; i <= nbpoles; i++)
543 newpoles(i+1) = cpoles(i);
547 Handle(TColStd_HArray1OfReal) nweights;
548 Standard_Boolean rat = IsRational() || Abs(Weight-1.) > gp::Resolution();
551 nweights = new TColStd_HArray1OfReal(1,nbpoles+1);
552 TColStd_Array1OfReal& newweights = nweights->ChangeArray1();
554 for (i = 1; i <= Index; i++)
556 newweights(i) = weights->Value(i);
560 newweights(Index+1) = Weight;
562 for (i = Index+1; i <= nbpoles; i++)
564 newweights(i+1) = weights->Value(i);
566 newweights(i+1) = 1.;
577 //=======================================================================
578 //function : InsertPoleBefore
580 //=======================================================================
582 void Geom2d_BSplineCurve::InsertPoleBefore
583 (const Standard_Integer Index,
585 const Standard_Real Weight)
587 InsertPoleAfter(Index-1,P,Weight);
590 //=======================================================================
591 //function : RemovePole
593 //=======================================================================
595 void Geom2d_BSplineCurve::RemovePole
596 (const Standard_Integer Index)
598 if (Index < 1 || Index > poles->Length()) Standard_OutOfRange::Raise("BSpline curve :RemovePole : Index and #pole mismatch");
600 if (poles->Length() <= 2) Standard_ConstructionError::Raise("BSpline curve : RemovePole : #pole is already minimum");
602 if (knotSet == GeomAbs_NonUniform || knotSet == GeomAbs_PiecewiseBezier)
603 Standard_ConstructionError::Raise("BSpline curve : RemovePole: bad knotSet type");
606 Handle(TColStd_HArray1OfReal) nknots =
607 new TColStd_HArray1OfReal(1,knots->Length()-1);
608 TColStd_Array1OfReal& newknots = nknots->ChangeArray1();
610 Handle(TColStd_HArray1OfInteger) nmults =
611 new TColStd_HArray1OfInteger(1,mults->Length()-1);
612 TColStd_Array1OfInteger& newmults = nmults->ChangeArray1();
614 for (i = 1; i < newknots.Length(); i++) {
615 newknots (i) = knots->Value (i);
618 newmults(1) = mults->Value(1);
619 newknots(newknots.Upper()) = knots->Value (knots->Upper());
620 newmults(newmults.Upper()) = mults->Value (mults->Upper());
623 Handle(TColgp_HArray1OfPnt2d) npoles =
624 new TColgp_HArray1OfPnt2d(1, poles->Upper()-1);
625 TColgp_Array1OfPnt2d& newpoles = npoles->ChangeArray1();
627 for (i = 1; i < Index; i++)
628 newpoles(i) = poles->Value(i);
629 for (i = Index; i < newpoles.Length(); i++)
630 newpoles(i) = poles->Value(i+1);
632 Handle(TColStd_HArray1OfReal) nweights;
634 nweights = new TColStd_HArray1OfReal(1,newpoles.Length());
635 TColStd_Array1OfReal& newweights = nweights->ChangeArray1();
636 for (i = 1; i < Index; i++)
637 newweights(i) = weights->Value(i);
638 for (i = Index; i < newweights.Length(); i++)
639 newweights(i) = weights->Value(i+1);
649 //=======================================================================
652 //=======================================================================
654 void Geom2d_BSplineCurve::Reverse ()
656 BSplCLib::Reverse(knots->ChangeArray1());
657 BSplCLib::Reverse(mults->ChangeArray1());
658 Standard_Integer last;
660 last = flatknots->Upper() - deg - 1;
662 last = poles->Upper();
663 BSplCLib::Reverse(poles->ChangeArray1(),last);
665 BSplCLib::Reverse(weights->ChangeArray1(),last);
669 //=======================================================================
670 //function : ReversedParameter
672 //=======================================================================
674 Standard_Real Geom2d_BSplineCurve::ReversedParameter( const Standard_Real U) const
676 return (FirstParameter() + LastParameter() - U);
679 //=======================================================================
682 //=======================================================================
683 void Geom2d_BSplineCurve::Segment(const Standard_Real aU1,
684 const Standard_Real aU2)
686 Standard_DomainError_Raise_if ( aU2 < aU1, "Geom2d_BSplineCurve::Segment");
688 Standard_Real AbsUMax = Max(Abs(FirstParameter()),Abs(LastParameter()));
689 Standard_Real Eps = Max (Epsilon(AbsUMax), Precision::PConfusion());
690 Standard_Real NewU1, NewU2;
691 Standard_Real U, DU=0;
692 Standard_Integer i, k, index;
695 // Checking the input bounds aUj (j=1,2).
696 // For the case when aUj==knot(i),
697 // in order to prevent the insertion of a new knot that will be too closed
698 // to the existing knot,
699 // we assign Uj=knot(i)
700 Standard_Integer n1, n2;
701 Standard_Real U1, U2;
707 for (i=n1; i<=n2; ++i) {
709 if (Abs(U-aU1)<=Eps) {
712 else if (Abs(U-aU2)<=Eps) {
716 // Henceforward we use U1, U2 as bounds of the segment
719 TColStd_Array1OfReal Knots(1,2);
720 TColStd_Array1OfInteger Mults(1,2);
722 // define param ditance to keep (eap, Apr 18 2002, occ311)
724 Standard_Real Period = LastParameter() - FirstParameter();
726 while (DU > Period) {
729 if (DU <= Epsilon(Period)) {
735 BSplCLib::LocateParameter(deg,knots->Array1(),mults->Array1(),
736 U1,periodic,knots->Lower(),knots->Upper(),
739 BSplCLib::LocateParameter(deg,knots->Array1(),mults->Array1(),
740 U2,periodic,knots->Lower(),knots->Upper(),
742 Knots(1) = Min( NewU1, NewU2);
743 Knots(2) = Max( NewU1, NewU2);
744 Mults(1) = Mults( 2) = deg;
745 InsertKnots(Knots, Mults, Eps);
747 if (periodic) { // set the origine at NewU1
749 BSplCLib::LocateParameter(deg,knots->Array1(),mults->Array1(),
750 U1,periodic,knots->Lower(),knots->Upper(),
752 // Eps = Epsilon(knots->Value(index+1));
753 if ( Abs(knots->Value(index+1)-U) <= Eps) {
761 // compute index1 and index2 to set the new knots and mults
762 Standard_Integer index1 = 0, index2 = 0;
763 Standard_Integer FromU1 = knots->Lower();
764 Standard_Integer ToU2 = knots->Upper();
765 BSplCLib::LocateParameter(deg,knots->Array1(),mults->Array1(),
766 NewU1,periodic,FromU1,ToU2,index1,U);
767 BSplCLib::LocateParameter(deg,knots->Array1(),mults->Array1(),
768 NewU2,periodic,FromU1,ToU2,index2,U);
769 // Eps = Epsilon(knots->Value(index2+1));
770 if ( Abs(knots->Value(index2+1)-U) <= Eps){
774 Standard_Integer nbknots = index2 - index1 + 1;
776 Handle(TColStd_HArray1OfReal)
777 nknots = new TColStd_HArray1OfReal(1,nbknots);
778 Handle(TColStd_HArray1OfInteger)
779 nmults = new TColStd_HArray1OfInteger(1,nbknots);
781 // to restore changed U1
782 if (DU > 0) {// if was periodic
788 for ( i = index1; i<= index2; i++) {
789 nknots->SetValue(k, knots->Value(i) - DU);
790 nmults->SetValue(k, mults->Value(i));
793 nmults->SetValue( 1, deg + 1);
794 nmults->SetValue(nbknots, deg + 1);
797 // compute index1 and index2 to set the new poles and weights
798 Standard_Integer pindex1
799 = BSplCLib::PoleIndex(deg,index1,periodic,mults->Array1());
800 Standard_Integer pindex2
801 = BSplCLib::PoleIndex(deg,index2,periodic,mults->Array1());
804 pindex2 = Min( pindex2+1, poles->Length());
806 Standard_Integer nbpoles = pindex2 - pindex1 + 1;
808 Handle(TColStd_HArray1OfReal)
809 nweights = new TColStd_HArray1OfReal(1,nbpoles);
810 Handle(TColgp_HArray1OfPnt2d)
811 npoles = new TColgp_HArray1OfPnt2d(1,nbpoles);
815 nweights = new TColStd_HArray1OfReal( 1, nbpoles);
816 for ( i = pindex1; i <= pindex2; i++) {
817 npoles->SetValue(k, poles->Value(i));
818 nweights->SetValue(k, weights->Value(i));
823 for ( i = pindex1; i <= pindex2; i++) {
824 npoles->SetValue(k, poles->Value(i));
838 //=======================================================================
841 //=======================================================================
843 void Geom2d_BSplineCurve::SetKnot
844 (const Standard_Integer Index,
845 const Standard_Real K)
847 if (Index < 1 || Index > knots->Length()) Standard_OutOfRange::Raise("BSpline curve : SetKnot: Index and #pole mismatch");
848 Standard_Real DK = Abs(Epsilon (K));
850 if (K >= knots->Value(2) - DK) Standard_ConstructionError::Raise("BSpline curve :SetKnot :K out of range");
852 else if (Index == knots->Length()) {
853 if (K <= knots->Value (knots->Length()-1) + DK) {
854 Standard_ConstructionError::Raise("BSpline curve : SetKnot : K out of range");
858 if (K <= knots->Value(Index-1) + DK ||
859 K >= knots->Value(Index+1) - DK ) {
860 Standard_ConstructionError::Raise("BSpline curve : SetKnot: K out of range");
863 if (K != knots->Value (Index)) {
864 knots->SetValue (Index, K);
870 //=======================================================================
871 //function : SetKnots
873 //=======================================================================
875 void Geom2d_BSplineCurve::SetKnots
876 (const TColStd_Array1OfReal& K)
878 CheckCurveData(poles->Array1(),K,mults->Array1(),deg,periodic);
879 knots->ChangeArray1() = K;
884 //=======================================================================
887 //=======================================================================
889 void Geom2d_BSplineCurve::SetKnot
890 (const Standard_Integer Index,
891 const Standard_Real K,
892 const Standard_Integer M)
894 IncreaseMultiplicity (Index, M);
898 //=======================================================================
899 //function : SetPeriodic
901 //=======================================================================
903 void Geom2d_BSplineCurve::SetPeriodic ()
905 Standard_Integer first = FirstUKnotIndex();
906 Standard_Integer last = LastUKnotIndex();
908 Handle(TColStd_HArray1OfReal) tk = knots;
909 TColStd_Array1OfReal cknots((knots->Array1())(first),first,last);
910 knots = new TColStd_HArray1OfReal(1,cknots.Length());
911 knots->ChangeArray1() = cknots;
913 Handle(TColStd_HArray1OfInteger) tm = mults;
914 TColStd_Array1OfInteger cmults((mults->Array1())(first),first,last);
915 cmults(first) = cmults(last) = Min(deg, Max( cmults(first), cmults(last)));
916 mults = new TColStd_HArray1OfInteger(1,cmults.Length());
917 mults->ChangeArray1() = cmults;
919 // compute new number of poles;
920 Standard_Integer nbp = BSplCLib::NbPoles(deg,Standard_True,cmults);
922 Handle(TColgp_HArray1OfPnt2d) tp = poles;
923 TColgp_Array1OfPnt2d cpoles((poles->Array1())(1),1,nbp);
924 poles = new TColgp_HArray1OfPnt2d(1,nbp);
925 poles->ChangeArray1() = cpoles;
928 Handle(TColStd_HArray1OfReal) tw = weights;
929 TColStd_Array1OfReal cweights((weights->Array1())(1),1,nbp);
930 weights = new TColStd_HArray1OfReal(1,nbp);
931 weights->ChangeArray1() = cweights;
934 periodic = Standard_True;
940 //=======================================================================
941 //function : SetOrigin
943 //=======================================================================
945 void Geom2d_BSplineCurve::SetOrigin(const Standard_Integer Index)
947 Standard_NoSuchObject_Raise_if( !periodic,
948 "Geom2d_BSplineCurve::SetOrigin");
949 Standard_Integer i,k;
950 Standard_Integer first = FirstUKnotIndex();
951 Standard_Integer last = LastUKnotIndex();
953 Standard_DomainError_Raise_if( (Index < first) || (Index > last),
954 "Geom2d_BSplineCurve::SetOrigine");
956 Standard_Integer nbknots = knots->Length();
957 Standard_Integer nbpoles = poles->Length();
959 Handle(TColStd_HArray1OfReal) nknots =
960 new TColStd_HArray1OfReal(1,nbknots);
961 TColStd_Array1OfReal& newknots = nknots->ChangeArray1();
963 Handle(TColStd_HArray1OfInteger) nmults =
964 new TColStd_HArray1OfInteger(1,nbknots);
965 TColStd_Array1OfInteger& newmults = nmults->ChangeArray1();
967 // set the knots and mults
968 Standard_Real period = knots->Value(last) - knots->Value(first);
970 for ( i = Index; i <= last ; i++) {
971 newknots(k) = knots->Value(i);
972 newmults(k) = mults->Value(i);
975 for ( i = first+1; i <= Index; i++) {
976 newknots(k) = knots->Value(i) + period;
977 newmults(k) = mults->Value(i);
981 Standard_Integer index = 1;
982 for (i = first+1; i <= Index; i++)
983 index += mults->Value(i);
985 // set the poles and weights
986 Handle(TColgp_HArray1OfPnt2d) npoles =
987 new TColgp_HArray1OfPnt2d(1,nbpoles);
988 Handle(TColStd_HArray1OfReal) nweights =
989 new TColStd_HArray1OfReal(1,nbpoles);
990 TColgp_Array1OfPnt2d & newpoles = npoles->ChangeArray1();
991 TColStd_Array1OfReal & newweights = nweights->ChangeArray1();
992 first = poles->Lower();
993 last = poles->Upper();
996 for ( i = index; i <= last; i++) {
997 newpoles(k) = poles->Value(i);
998 newweights(k) = weights->Value(i);
1001 for ( i = first; i < index; i++) {
1002 newpoles(k) = poles->Value(i);
1003 newweights(k) = weights->Value(i);
1009 for ( i = index; i <= last; i++) {
1010 newpoles(k) = poles->Value(i);
1013 for ( i = first; i < index; i++) {
1014 newpoles(k) = poles->Value(i);
1028 //=======================================================================
1029 //function : SetNotPeriodic
1031 //=======================================================================
1033 void Geom2d_BSplineCurve::SetNotPeriodic ()
1036 Standard_Integer NbKnots, NbPoles;
1037 BSplCLib::PrepareUnperiodize( deg, mults->Array1(),NbKnots,NbPoles);
1039 Handle(TColgp_HArray1OfPnt2d) npoles
1040 = new TColgp_HArray1OfPnt2d(1,NbPoles);
1042 Handle(TColStd_HArray1OfReal) nknots
1043 = new TColStd_HArray1OfReal(1,NbKnots);
1045 Handle(TColStd_HArray1OfInteger) nmults
1046 = new TColStd_HArray1OfInteger(1,NbKnots);
1048 Handle(TColStd_HArray1OfReal) nweights;
1052 nweights = new TColStd_HArray1OfReal(1,NbPoles);
1054 BSplCLib::Unperiodize
1055 (deg,mults->Array1(),knots->Array1(),poles->Array1(),
1056 weights->Array1(),nmults->ChangeArray1(),
1057 nknots->ChangeArray1(),npoles->ChangeArray1(),
1058 nweights->ChangeArray1());
1063 BSplCLib::Unperiodize
1064 (deg,mults->Array1(),knots->Array1(),poles->Array1(),
1065 *((TColStd_Array1OfReal*) NULL),nmults->ChangeArray1(),
1066 nknots->ChangeArray1(),npoles->ChangeArray1(),
1067 *((TColStd_Array1OfReal*) NULL));
1074 periodic = Standard_False;
1080 //=======================================================================
1081 //function : SetPole
1083 //=======================================================================
1085 void Geom2d_BSplineCurve::SetPole
1086 (const Standard_Integer Index,
1089 if (Index < 1 || Index > poles->Length()) Standard_OutOfRange::Raise("BSpline curve : SetPole : index and #pole mismatch");
1090 poles->SetValue (Index, P);
1094 //=======================================================================
1095 //function : SetPole
1097 //=======================================================================
1099 void Geom2d_BSplineCurve::SetPole
1100 (const Standard_Integer Index,
1102 const Standard_Real W)
1108 //=======================================================================
1109 //function : SetWeight
1111 //=======================================================================
1113 void Geom2d_BSplineCurve::SetWeight
1114 (const Standard_Integer Index,
1115 const Standard_Real W)
1117 if (Index < 1 || Index > poles->Length()) Standard_OutOfRange::Raise("BSpline curve : SetWeight: Index and #pole mismatch");
1119 if (W <= gp::Resolution ()) Standard_ConstructionError::Raise("BSpline curve : SetWeight: Weight too small");
1122 Standard_Boolean rat = IsRational() || (Abs(W - 1.) > gp::Resolution());
1125 if (rat && !IsRational()) {
1126 weights = new TColStd_HArray1OfReal(1,poles->Length());
1130 weights->SetValue (Index, W);
1133 rat = Rational(weights->Array1());
1134 if (!rat) weights.Nullify();
1137 rational = !weights.IsNull();
1143 //=======================================================================
1144 //function : MovePoint
1146 //=======================================================================
1148 void Geom2d_BSplineCurve::MovePoint(const Standard_Real U,
1150 const Standard_Integer Index1,
1151 const Standard_Integer Index2,
1152 Standard_Integer& FirstModifiedPole,
1153 Standard_Integer& LastmodifiedPole)
1155 if (Index1 < 1 || Index1 > poles->Length() ||
1156 Index2 < 1 || Index2 > poles->Length() || Index1 > Index2) {
1157 Standard_OutOfRange::Raise("BSpline curve : MovePoint: Index and #pole mismatch");
1159 TColgp_Array1OfPnt2d npoles(1, poles->Length());
1162 gp_Vec2d Displ(P0, P);
1163 BSplCLib::MovePoint(U, Displ, Index1, Index2, deg, rational, poles->Array1(),
1164 weights->Array1(), flatknots->Array1(),
1165 FirstModifiedPole, LastmodifiedPole, npoles);
1166 if (FirstModifiedPole) {
1167 poles->ChangeArray1() = npoles;
1172 //=======================================================================
1173 //function : MovePointAndTangent
1175 //=======================================================================
1177 void Geom2d_BSplineCurve::
1178 MovePointAndTangent(const Standard_Real U,
1180 const gp_Vec2d& Tangent,
1181 const Standard_Real Tolerance,
1182 const Standard_Integer StartingCondition,
1183 const Standard_Integer EndingCondition,
1184 Standard_Integer& ErrorStatus)
1186 Standard_Integer ii ;
1189 // for the time being do not deal with periodic curves
1193 TColgp_Array1OfPnt2d new_poles(1, poles->Length());
1197 gp_Vec2d delta_derivative;
1200 gp_Vec2d delta(P0, P);
1201 for (ii = 1 ; ii <= 2 ; ii++) {
1202 delta_derivative.SetCoord(ii,
1203 Tangent.Coord(ii)- delta_derivative.Coord(ii)) ;
1205 BSplCLib::MovePointAndTangent(U,
1215 flatknots->Array1(),
1219 poles->ChangeArray1() = new_poles;
1224 //=======================================================================
1225 //function : UpdateKnots
1227 //=======================================================================
1229 void Geom2d_BSplineCurve::UpdateKnots()
1232 rational = !weights.IsNull();
1234 Standard_Integer MaxKnotMult = 0;
1235 BSplCLib::KnotAnalysis (deg,
1239 knotSet, MaxKnotMult);
1241 if (knotSet == GeomAbs_Uniform && !periodic) {
1245 flatknots = new TColStd_HArray1OfReal
1246 (1, BSplCLib::KnotSequenceLength(mults->Array1(),deg,periodic));
1248 BSplCLib::KnotSequence (knots->Array1(),
1251 flatknots->ChangeArray1());
1254 if (MaxKnotMult == 0) smooth = GeomAbs_CN;
1256 switch (deg - MaxKnotMult) {
1257 case 0 : smooth = GeomAbs_C0; break;
1258 case 1 : smooth = GeomAbs_C1; break;
1259 case 2 : smooth = GeomAbs_C2; break;
1260 case 3 : smooth = GeomAbs_C3; break;
1261 default : smooth = GeomAbs_C3; break;
1266 //=======================================================================
1267 //function : Normalizes the parameters if the curve is periodic
1268 //purpose : that is compute the cache so that it is valid
1269 //=======================================================================
1271 void Geom2d_BSplineCurve::PeriodicNormalization(Standard_Real& Parameter) const
1273 Standard_Real Period ;
1276 Period = flatknots->Value(flatknots->Upper() - deg) - flatknots->Value (deg + 1) ;
1277 while (Parameter > flatknots->Value(flatknots->Upper()-deg)) {
1278 Parameter -= Period ;
1280 while (Parameter < flatknots->Value((deg + 1))) {
1281 Parameter += Period ;