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 // Passage en classe persistante - 23/01/91
18 // Modif suite a la deuxieme revue de projet toolkit Geometry -23/01/91
20 // Actuellement pour les champs de la courbe le tableau des poles est
21 // declare de 1 a NbPoles et le tableau des poids est declare de 1 a NbPoles
23 // Revised RLE Aug 19 1993
24 // Suppressed Swaps, added Init, removed typedefs
26 #define No_Standard_OutOfRange
27 #define No_Standard_DimensionError
30 #include <BSplCLib.hxx>
31 #include <Geom_BezierCurve.hxx>
32 #include <Geom_Geometry.hxx>
35 #include <gp_Trsf.hxx>
39 #include <Precision.hxx>
40 #include <Standard_ConstructionError.hxx>
41 #include <Standard_DimensionError.hxx>
42 #include <Standard_OutOfRange.hxx>
43 #include <Standard_RangeError.hxx>
44 #include <Standard_Type.hxx>
45 #include <TColStd_Array1OfInteger.hxx>
47 //=======================================================================
49 //purpose : check rationality of an array of weights
50 //=======================================================================
51 static Standard_Boolean Rational(const TColStd_Array1OfReal& W)
53 Standard_Integer i, n = W.Length();
54 Standard_Boolean rat = Standard_False;
55 for (i = 1; i < n; i++) {
56 rat = Abs(W(i) - W(i+1)) > gp::Resolution();
62 //=======================================================================
63 //function : Geom_BezierCurve
65 //=======================================================================
67 Geom_BezierCurve::Geom_BezierCurve(const TColgp_Array1OfPnt& Poles):
68 validcache(0), parametercache(0.), spanlenghtcache(1.)
70 Standard_Integer nbpoles = Poles.Length();
71 if(nbpoles < 2 || nbpoles > (Geom_BezierCurve::MaxDegree() + 1))
72 Standard_ConstructionError::Raise();
74 Handle(TColgp_HArray1OfPnt) npoles =
75 new TColgp_HArray1OfPnt(1,nbpoles);
77 npoles->ChangeArray1() = Poles;
81 Handle(TColStd_HArray1OfReal)());
84 //=======================================================================
85 //function : Geom_BezierCurve
87 //=======================================================================
89 Geom_BezierCurve::Geom_BezierCurve(const TColgp_Array1OfPnt& Poles,
90 const TColStd_Array1OfReal& Weights):
91 validcache(0), parametercache(0.), spanlenghtcache(1.)
94 Standard_Integer nbpoles = Poles.Length();
95 if(nbpoles < 2 || nbpoles > (Geom_BezierCurve::MaxDegree() + 1))
96 Standard_ConstructionError::Raise();
98 Handle(TColgp_HArray1OfPnt) npoles =
99 new TColgp_HArray1OfPnt(1,nbpoles);
101 npoles->ChangeArray1() = Poles;
106 if (Weights.Length() != nbpoles)
107 Standard_ConstructionError::Raise();
110 for (i = 1; i <= nbpoles; i++) {
111 if (Weights(i) <= gp::Resolution()) {
112 Standard_ConstructionError::Raise();
116 // check really rational
117 Standard_Boolean rat = Rational(Weights);
120 Handle(TColStd_HArray1OfReal) nweights;
122 nweights = new TColStd_HArray1OfReal(1,nbpoles);
123 nweights->ChangeArray1() = Weights;
127 Init(npoles,nweights);
130 //=======================================================================
131 //function : Increase
132 //purpose : increase degree
133 //=======================================================================
135 void Geom_BezierCurve::Increase (const Standard_Integer Deg)
137 if (Deg == Degree()) return;
140 Deg > Geom_BezierCurve::MaxDegree())
141 Standard_ConstructionError::Raise("Geom_BezierCurve::Increase");
143 Handle(TColgp_HArray1OfPnt) npoles =
144 new TColgp_HArray1OfPnt(1,Deg+1);
146 Handle(TColStd_HArray1OfReal) nweights;
148 TColStd_Array1OfReal bidknots(1,2); bidknots(1) = 0.; bidknots(2) = 1.;
149 TColStd_Array1OfInteger bidmults(1,2); bidmults.Init(Degree() + 1);
152 nweights = new TColStd_HArray1OfReal(1,Deg+1);
153 BSplCLib::IncreaseDegree(Degree(), Deg, 0,
157 npoles->ChangeArray1(),
158 &nweights->ChangeArray1(),
162 BSplCLib::IncreaseDegree(Degree(), Deg, 0,
164 BSplCLib::NoWeights(),
166 npoles->ChangeArray1(),
167 BSplCLib::NoWeights(),
171 Init(npoles,nweights);
174 //=======================================================================
175 //function : MaxDegree
177 //=======================================================================
179 Standard_Integer Geom_BezierCurve::MaxDegree ()
181 return BSplCLib::MaxDegree();
184 //=======================================================================
185 //function : InsertPoleAfter
187 //=======================================================================
189 void Geom_BezierCurve::InsertPoleAfter
190 (const Standard_Integer Index,
193 InsertPoleAfter(Index,P,1.);
196 //=======================================================================
197 //function : InsertPoleAfter
199 //=======================================================================
201 void Geom_BezierCurve::InsertPoleAfter
202 (const Standard_Integer Index,
204 const Standard_Real Weight)
206 Standard_Integer nbpoles = NbPoles();
208 if(nbpoles >= Geom_BezierCurve::MaxDegree() ||
209 Weight <= gp::Resolution())
210 Standard_ConstructionError::Raise("Geom_BezierCurve::InsertPoleAfter");
212 if(Index < 0 || Index > nbpoles)
213 Standard_OutOfRange::Raise("Geom_BezierCurve::InsertPoleAfter");
218 Handle(TColgp_HArray1OfPnt) npoles =
219 new TColgp_HArray1OfPnt(1,nbpoles+1);
221 TColgp_Array1OfPnt& newpoles = npoles->ChangeArray1();
222 const TColgp_Array1OfPnt& oldpoles = poles->Array1();
224 for (i = 1; i <= Index; i++)
225 newpoles(i) = oldpoles(i);
227 newpoles(Index+1) = P;
229 for (i = Index+1; i <= nbpoles; i++)
230 newpoles(i+1) = oldpoles(i);
234 Handle(TColStd_HArray1OfReal) nweights;
235 Standard_Boolean rat = IsRational() || Abs(Weight-1.) > gp::Resolution();
238 nweights = new TColStd_HArray1OfReal(1,nbpoles+1);
239 TColStd_Array1OfReal& newweights = nweights->ChangeArray1();
241 for (i = 1; i <= Index; i++)
243 newweights(i) = weights->Value(i);
247 newweights(Index+1) = Weight;
249 for (i = Index+1; i <= nbpoles; i++)
251 newweights(i+1) = weights->Value(i);
253 newweights(i+1) = 1.;
257 Init(npoles,nweights);
260 //=======================================================================
261 //function : InsertPoleBefore
263 //=======================================================================
265 void Geom_BezierCurve::InsertPoleBefore
266 (const Standard_Integer Index,
269 InsertPoleAfter(Index-1,P);
272 //=======================================================================
273 //function : InsertPoleBefore
275 //=======================================================================
277 void Geom_BezierCurve::InsertPoleBefore
278 (const Standard_Integer Index,
280 const Standard_Real Weight)
282 InsertPoleAfter(Index-1,P,Weight);
285 //=======================================================================
286 //function : RemovePole
288 //=======================================================================
290 void Geom_BezierCurve::RemovePole
291 (const Standard_Integer Index)
293 Standard_Integer nbpoles = NbPoles();
296 Standard_ConstructionError::Raise("Geom_BezierCurve::RemovePole");
298 if(Index < 1 || Index > nbpoles)
299 Standard_OutOfRange::Raise("Geom_BezierCurve::RemovePole");
304 Handle(TColgp_HArray1OfPnt) npoles =
305 new TColgp_HArray1OfPnt(1,nbpoles-1);
307 TColgp_Array1OfPnt& newpoles = npoles->ChangeArray1();
308 const TColgp_Array1OfPnt& oldpoles = poles->Array1();
310 for (i = 1; i < Index; i++)
311 newpoles(i) = oldpoles(i);
313 for (i = Index+1; i <= nbpoles; i++)
314 newpoles(i-1) = oldpoles(i);
318 Handle(TColStd_HArray1OfReal) nweights;
321 nweights = new TColStd_HArray1OfReal(1,nbpoles-1);
322 TColStd_Array1OfReal& newweights = nweights->ChangeArray1();
323 const TColStd_Array1OfReal& oldweights = weights->Array1();
325 for (i = 1; i < Index; i++)
326 newweights(i) = oldweights(i);
328 for (i = Index+1; i <= nbpoles; i++)
329 newweights(i-1) = oldweights(i);
332 Init(npoles,nweights);
335 //=======================================================================
338 //=======================================================================
340 void Geom_BezierCurve::Reverse ()
343 Standard_Integer i, nbpoles = NbPoles();
344 TColgp_Array1OfPnt & cpoles = poles->ChangeArray1();
347 for (i = 1; i <= nbpoles / 2; i++) {
349 cpoles(i) = cpoles(nbpoles-i+1);
350 cpoles(nbpoles-i+1) = P;
355 TColStd_Array1OfReal & cweights = weights->ChangeArray1();
357 for (i = 1; i <= nbpoles / 2; i++) {
359 cweights(i) = cweights(nbpoles-i+1);
360 cweights(nbpoles-i+1) = w;
364 UpdateCoefficients();
367 //=======================================================================
368 //function : ReversedParameter
370 //=======================================================================
372 Standard_Real Geom_BezierCurve::ReversedParameter(const Standard_Real U) const
377 //=======================================================================
380 //=======================================================================
382 void Geom_BezierCurve::Segment(const Standard_Real U1, const Standard_Real U2)
384 closed = (Abs(Value(U1).Distance (Value(U2))) <= Precision::Confusion());
386 if(!CoefficientsOK(0.)) UpdateCoefficients(0.);
388 PLib::Trimming(U1,U2,coeffs->ChangeArray1(),
389 &wcoeffs->ChangeArray1());
390 PLib::CoefficientsPoles(coeffs->Array1(),
392 poles->ChangeArray1(),
393 &weights->ChangeArray1());
396 PLib::Trimming(U1,U2,coeffs->ChangeArray1(), PLib::NoWeights());
397 PLib::CoefficientsPoles(coeffs->Array1(), PLib::NoWeights(),
398 poles->ChangeArray1(), PLib::NoWeights());
400 UpdateCoefficients();
403 //=======================================================================
406 //=======================================================================
408 void Geom_BezierCurve::SetPole (const Standard_Integer Index,
411 if(Index < 1 || Index > NbPoles())
412 Standard_OutOfRange::Raise("Geom_BezierCurve::SetPole");
414 TColgp_Array1OfPnt& cpoles = poles->ChangeArray1();
417 if (Index == 1 || Index == cpoles.Length()) {
418 closed = (cpoles(1).Distance(cpoles(NbPoles())) <= Precision::Confusion());
420 UpdateCoefficients();
423 //=======================================================================
426 //=======================================================================
428 void Geom_BezierCurve::SetPole(const Standard_Integer Index,
430 const Standard_Real Weight)
433 SetWeight(Index,Weight);
436 //=======================================================================
437 //function : SetWeight
439 //=======================================================================
441 void Geom_BezierCurve::SetWeight(const Standard_Integer Index,
442 const Standard_Real Weight)
444 Standard_Integer nbpoles = NbPoles();
446 if(Index < 1 || Index > nbpoles)
447 Standard_OutOfRange::Raise("Geom_BezierCurve::SetWeight");
448 if(Weight <= gp::Resolution ())
449 Standard_ConstructionError::Raise("Geom_BezierCurve::SetWeight");
451 // compute new rationality
452 Standard_Boolean wasrat = IsRational();
454 // a weight of 1. does not turn to rational
455 if (Abs(Weight - 1.) <= gp::Resolution()) return;
458 weights = new TColStd_HArray1OfReal(1,nbpoles);
459 wcoeffs = new TColStd_HArray1OfReal(1,nbpoles);
463 TColStd_Array1OfReal & cweights = weights->ChangeArray1();
464 cweights(Index) = Weight;
466 // is it turning into non rational
468 if (!Rational(cweights)) {
473 UpdateCoefficients();
476 //=======================================================================
477 //function : IsClosed
479 //=======================================================================
481 Standard_Boolean Geom_BezierCurve::IsClosed () const
486 //=======================================================================
489 //=======================================================================
491 Standard_Boolean Geom_BezierCurve::IsCN (const Standard_Integer ) const
493 return Standard_True;
496 //=======================================================================
497 //function : IsPeriodic
499 //=======================================================================
501 Standard_Boolean Geom_BezierCurve::IsPeriodic () const
503 return Standard_False;
506 //=======================================================================
507 //function : IsRational
509 //=======================================================================
511 Standard_Boolean Geom_BezierCurve::IsRational () const
513 return !weights.IsNull();
516 //=======================================================================
517 //function : Continuity
519 //=======================================================================
521 GeomAbs_Shape Geom_BezierCurve::Continuity () const
526 //=======================================================================
529 //=======================================================================
531 Standard_Integer Geom_BezierCurve::Degree () const
533 return poles->Length()-1;
536 //=======================================================================
539 //=======================================================================
541 void Geom_BezierCurve::D0 (const Standard_Real U, gp_Pnt& P ) const
543 // Idee lumineuse sacrifiee sur l autel des performances.
545 // if(!CoefficientsOK(U))
546 // ((Geom_BezierCurve*)(void*)this)->UpdateCoefficients(U);
548 BSplCLib::CacheD0(U,Degree(),parametercache,spanlenghtcache,
553 BSplCLib::CacheD0(U,Degree(),parametercache,spanlenghtcache,
554 coeffs->Array1(), BSplCLib::NoWeights(), P);
557 //=======================================================================
560 //=======================================================================
562 void Geom_BezierCurve::D1(const Standard_Real U, gp_Pnt& P, gp_Vec& V1) const
564 // Idee lumineuse sacrifiee sur l autel des performances.
566 // if(!CoefficientsOK(U))
567 // ((Geom_BezierCurve*)(void*)this)->UpdateCoefficients(U);
569 BSplCLib::CacheD1(U,Degree(),parametercache,spanlenghtcache,
574 BSplCLib::CacheD1(U,Degree(),parametercache,spanlenghtcache,
576 BSplCLib::NoWeights(),
580 //=======================================================================
583 //=======================================================================
585 void Geom_BezierCurve::D2 (const Standard_Real U,
590 // Idee lumineuse sacrifiee sur l autel des performances.
592 // if(!CoefficientsOK(U))
593 // ((Geom_BezierCurve*)(void*)this)->UpdateCoefficients(U);
595 BSplCLib::CacheD2(U,Degree(),parametercache,spanlenghtcache,
600 BSplCLib::CacheD2(U,Degree(),parametercache,spanlenghtcache,
602 BSplCLib::NoWeights(),
606 //=======================================================================
609 //=======================================================================
611 void Geom_BezierCurve::D3 (const Standard_Real U,
617 if(!CoefficientsOK(U))
618 ((Geom_BezierCurve*)(void*)this)->UpdateCoefficients(U);
620 BSplCLib::CacheD3(U,Degree(),parametercache,spanlenghtcache,
625 BSplCLib::CacheD3(U,Degree(),parametercache,spanlenghtcache,
627 BSplCLib::NoWeights(),
631 //=======================================================================
634 //=======================================================================
636 gp_Vec Geom_BezierCurve::DN (const Standard_Real U,
637 const Standard_Integer N) const
640 Standard_RangeError::Raise("Geom_BezierCurve::DN");
643 TColStd_Array1OfReal bidknots(1,2); bidknots(1) = 0.; bidknots(2) = 1.;
644 TColStd_Array1OfInteger bidmults(1,2); bidmults.Init(Degree() + 1);
647 // BSplCLib::DN(U,N,0,Degree(),0.,
648 BSplCLib::DN(U,N,0,Degree(),Standard_False,
651 bidknots,&bidmults,V);
653 // BSplCLib::DN(U,N,0,Degree(),0.,
654 BSplCLib::DN(U,N,0,Degree(),Standard_False,
656 BSplCLib::NoWeights(),
657 bidknots,&bidmults,V);
661 //=======================================================================
662 //function : StartPoint
664 //=======================================================================
666 gp_Pnt Geom_BezierCurve::StartPoint () const
668 return poles->Value(1);
671 //=======================================================================
672 //function : EndPoint
674 //=======================================================================
676 gp_Pnt Geom_BezierCurve::EndPoint () const
678 return poles->Value (poles->Upper());
681 //=======================================================================
682 //function : FirstParameter
684 //=======================================================================
686 Standard_Real Geom_BezierCurve::FirstParameter () const
691 //=======================================================================
692 //function : LastParameter
694 //=======================================================================
696 Standard_Real Geom_BezierCurve::LastParameter () const
701 //=======================================================================
704 //=======================================================================
706 Standard_Integer Geom_BezierCurve::NbPoles () const
708 return poles->Length();
711 //=======================================================================
714 //=======================================================================
716 gp_Pnt Geom_BezierCurve::Pole (const Standard_Integer Index) const
718 if(Index < 1 || Index > poles->Length())
719 Standard_OutOfRange::Raise("Geom_BezierCurve::Pole");
720 return poles->Value(Index);
723 //=======================================================================
726 //=======================================================================
728 void Geom_BezierCurve::Poles (TColgp_Array1OfPnt& P) const
730 if(P.Length() != poles->Length())
731 Standard_DimensionError::Raise("Geom_BezierCurve::Poles");
735 //=======================================================================
738 //=======================================================================
740 Standard_Real Geom_BezierCurve::Weight
741 (const Standard_Integer Index) const
743 if(Index < 1 || Index > poles->Length())
744 Standard_OutOfRange::Raise("Geom_BezierCurve::Weight");
746 return weights->Value(Index);
751 //=======================================================================
754 //=======================================================================
756 void Geom_BezierCurve::Weights
757 (TColStd_Array1OfReal& W) const
760 Standard_Integer nbpoles = NbPoles();
761 if(W.Length() != nbpoles)
762 Standard_DimensionError::Raise("Geom_BezierCurve::Weights");
764 W = weights->Array1();
767 for (i = 1; i <= nbpoles; i++)
772 //=======================================================================
773 //function : Transform
775 //=======================================================================
777 void Geom_BezierCurve::Transform (const gp_Trsf& T)
779 Standard_Integer nbpoles = NbPoles();
780 TColgp_Array1OfPnt & cpoles = poles->ChangeArray1();
782 for (Standard_Integer i = 1; i <= nbpoles; i++)
783 cpoles (i).Transform(T);
785 UpdateCoefficients();
788 //=======================================================================
789 //function : Resolution
791 //=======================================================================
793 void Geom_BezierCurve::Resolution(const Standard_Real Tolerance3D,
794 Standard_Real & UTolerance)
797 TColStd_Array1OfReal bidflatknots(BSplCLib::FlatBezierKnots(Degree()),
801 BSplCLib::Resolution(poles->Array1(),
810 BSplCLib::Resolution(poles->Array1(),
811 BSplCLib::NoWeights(),
820 UTolerance = Tolerance3D * maxderivinv;
823 //=======================================================================
826 //=======================================================================
828 Handle(Geom_Geometry) Geom_BezierCurve::Copy() const {
830 Handle(Geom_BezierCurve) C;
832 C = new Geom_BezierCurve (poles->Array1(),weights->Array1());
834 C = new Geom_BezierCurve (poles->Array1());
838 //=======================================================================
841 //=======================================================================
843 void Geom_BezierCurve::Init
844 (const Handle(TColgp_HArray1OfPnt)& Poles,
845 const Handle(TColStd_HArray1OfReal)& Weights)
847 Standard_Integer nbpoles = Poles->Length();
849 const TColgp_Array1OfPnt& cpoles = Poles->Array1();
850 closed = cpoles(1).Distance(cpoles(nbpoles)) <= Precision::Confusion();
853 rational = !Weights.IsNull();
857 coeffs = new TColgp_HArray1OfPnt (1,nbpoles);
861 wcoeffs = new TColStd_HArray1OfReal (1, nbpoles, 0.0);
868 UpdateCoefficients();
871 //=======================================================================
872 //function : CoefficientsOK
874 //=======================================================================
876 Standard_Boolean Geom_BezierCurve::CoefficientsOK(const Standard_Real U)const
878 return (validcache && ((parametercache == 0. && U < 1.) ||
879 (parametercache == 1. && U >= 1.)));
882 //=======================================================================
883 //function : UpdateCoefficients
885 //=======================================================================
887 //void Geom_BezierCurve::UpdateCoefficients(const Standard_Real U)
888 void Geom_BezierCurve::UpdateCoefficients(const Standard_Real )
893 // Idee lumineuse sacrifiee sur l autel des performances.
894 // if (U >= 1.) parametercache = 1.;
895 TColStd_Array1OfReal bidflatknots(BSplCLib::FlatBezierKnots(Degree()),
898 BSplCLib::BuildCache(parametercache,spanlenghtcache,0,Degree(),
899 bidflatknots,poles->Array1(),
901 coeffs->ChangeArray1(),
902 &wcoeffs->ChangeArray1());
904 BSplCLib::BuildCache(parametercache,spanlenghtcache,0,Degree(),
905 bidflatknots,poles->Array1(),
906 BSplCLib::NoWeights(),
907 coeffs->ChangeArray1(),
908 BSplCLib::NoWeights());