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 *((TColStd_Array1OfReal*) NULL),
166 npoles->ChangeArray1(),
167 *((TColStd_Array1OfReal*) NULL),
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(),
397 *((TColStd_Array1OfReal*) NULL));
398 PLib::CoefficientsPoles(coeffs->Array1(),
399 *((TColStd_Array1OfReal*) NULL),
400 poles->ChangeArray1(),
401 *((TColStd_Array1OfReal*) NULL));
403 UpdateCoefficients();
406 //=======================================================================
409 //=======================================================================
411 void Geom_BezierCurve::SetPole (const Standard_Integer Index,
414 if(Index < 1 || Index > NbPoles())
415 Standard_OutOfRange::Raise("Geom_BezierCurve::SetPole");
417 TColgp_Array1OfPnt& cpoles = poles->ChangeArray1();
420 if (Index == 1 || Index == cpoles.Length()) {
421 closed = (cpoles(1).Distance(cpoles(NbPoles())) <= Precision::Confusion());
423 UpdateCoefficients();
426 //=======================================================================
429 //=======================================================================
431 void Geom_BezierCurve::SetPole(const Standard_Integer Index,
433 const Standard_Real Weight)
436 SetWeight(Index,Weight);
439 //=======================================================================
440 //function : SetWeight
442 //=======================================================================
444 void Geom_BezierCurve::SetWeight(const Standard_Integer Index,
445 const Standard_Real Weight)
447 Standard_Integer nbpoles = NbPoles();
449 if(Index < 1 || Index > nbpoles)
450 Standard_OutOfRange::Raise("Geom_BezierCurve::SetWeight");
451 if(Weight <= gp::Resolution ())
452 Standard_ConstructionError::Raise("Geom_BezierCurve::SetWeight");
454 // compute new rationality
455 Standard_Boolean wasrat = IsRational();
457 // a weight of 1. does not turn to rational
458 if (Abs(Weight - 1.) <= gp::Resolution()) return;
461 weights = new TColStd_HArray1OfReal(1,nbpoles);
462 wcoeffs = new TColStd_HArray1OfReal(1,nbpoles);
466 TColStd_Array1OfReal & cweights = weights->ChangeArray1();
467 cweights(Index) = Weight;
469 // is it turning into non rational
471 if (!Rational(cweights)) {
476 UpdateCoefficients();
479 //=======================================================================
480 //function : IsClosed
482 //=======================================================================
484 Standard_Boolean Geom_BezierCurve::IsClosed () const
489 //=======================================================================
492 //=======================================================================
494 Standard_Boolean Geom_BezierCurve::IsCN (const Standard_Integer ) const
496 return Standard_True;
499 //=======================================================================
500 //function : IsPeriodic
502 //=======================================================================
504 Standard_Boolean Geom_BezierCurve::IsPeriodic () const
506 return Standard_False;
509 //=======================================================================
510 //function : IsRational
512 //=======================================================================
514 Standard_Boolean Geom_BezierCurve::IsRational () const
516 return !weights.IsNull();
519 //=======================================================================
520 //function : Continuity
522 //=======================================================================
524 GeomAbs_Shape Geom_BezierCurve::Continuity () const
529 //=======================================================================
532 //=======================================================================
534 Standard_Integer Geom_BezierCurve::Degree () const
536 return poles->Length()-1;
539 //=======================================================================
542 //=======================================================================
544 void Geom_BezierCurve::D0 (const Standard_Real U, gp_Pnt& P ) const
546 // Idee lumineuse sacrifiee sur l autel des performances.
548 // if(!CoefficientsOK(U))
549 // ((Geom_BezierCurve*)(void*)this)->UpdateCoefficients(U);
551 BSplCLib::CacheD0(U,Degree(),parametercache,spanlenghtcache,
556 BSplCLib::CacheD0(U,Degree(),parametercache,spanlenghtcache,
558 *((TColStd_Array1OfReal*) NULL),P
562 //=======================================================================
565 //=======================================================================
567 void Geom_BezierCurve::D1(const Standard_Real U, gp_Pnt& P, gp_Vec& V1) const
569 // Idee lumineuse sacrifiee sur l autel des performances.
571 // if(!CoefficientsOK(U))
572 // ((Geom_BezierCurve*)(void*)this)->UpdateCoefficients(U);
574 BSplCLib::CacheD1(U,Degree(),parametercache,spanlenghtcache,
579 BSplCLib::CacheD1(U,Degree(),parametercache,spanlenghtcache,
581 *((TColStd_Array1OfReal*) NULL),
585 //=======================================================================
588 //=======================================================================
590 void Geom_BezierCurve::D2 (const Standard_Real U,
595 // Idee lumineuse sacrifiee sur l autel des performances.
597 // if(!CoefficientsOK(U))
598 // ((Geom_BezierCurve*)(void*)this)->UpdateCoefficients(U);
600 BSplCLib::CacheD2(U,Degree(),parametercache,spanlenghtcache,
605 BSplCLib::CacheD2(U,Degree(),parametercache,spanlenghtcache,
607 *((TColStd_Array1OfReal*) NULL),
611 //=======================================================================
614 //=======================================================================
616 void Geom_BezierCurve::D3 (const Standard_Real U,
622 if(!CoefficientsOK(U))
623 ((Geom_BezierCurve*)(void*)this)->UpdateCoefficients(U);
625 BSplCLib::CacheD3(U,Degree(),parametercache,spanlenghtcache,
630 BSplCLib::CacheD3(U,Degree(),parametercache,spanlenghtcache,
632 *((TColStd_Array1OfReal*) NULL),
636 //=======================================================================
639 //=======================================================================
641 gp_Vec Geom_BezierCurve::DN (const Standard_Real U,
642 const Standard_Integer N) const
645 Standard_RangeError::Raise("Geom_BezierCurve::DN");
648 TColStd_Array1OfReal bidknots(1,2); bidknots(1) = 0.; bidknots(2) = 1.;
649 TColStd_Array1OfInteger bidmults(1,2); bidmults.Init(Degree() + 1);
652 // BSplCLib::DN(U,N,0,Degree(),0.,
653 BSplCLib::DN(U,N,0,Degree(),Standard_False,
656 bidknots,bidmults,V);
658 // BSplCLib::DN(U,N,0,Degree(),0.,
659 BSplCLib::DN(U,N,0,Degree(),Standard_False,
661 *((TColStd_Array1OfReal*) NULL),
662 bidknots,bidmults,V);
666 //=======================================================================
667 //function : StartPoint
669 //=======================================================================
671 gp_Pnt Geom_BezierCurve::StartPoint () const
673 return poles->Value(1);
676 //=======================================================================
677 //function : EndPoint
679 //=======================================================================
681 gp_Pnt Geom_BezierCurve::EndPoint () const
683 return poles->Value (poles->Upper());
686 //=======================================================================
687 //function : FirstParameter
689 //=======================================================================
691 Standard_Real Geom_BezierCurve::FirstParameter () const
696 //=======================================================================
697 //function : LastParameter
699 //=======================================================================
701 Standard_Real Geom_BezierCurve::LastParameter () const
706 //=======================================================================
709 //=======================================================================
711 Standard_Integer Geom_BezierCurve::NbPoles () const
713 return poles->Length();
716 //=======================================================================
719 //=======================================================================
721 gp_Pnt Geom_BezierCurve::Pole (const Standard_Integer Index) const
723 if(Index < 1 || Index > poles->Length())
724 Standard_OutOfRange::Raise("Geom_BezierCurve::Pole");
725 return poles->Value(Index);
728 //=======================================================================
731 //=======================================================================
733 void Geom_BezierCurve::Poles (TColgp_Array1OfPnt& P) const
735 if(P.Length() != poles->Length())
736 Standard_DimensionError::Raise("Geom_BezierCurve::Poles");
740 //=======================================================================
743 //=======================================================================
745 Standard_Real Geom_BezierCurve::Weight
746 (const Standard_Integer Index) const
748 if(Index < 1 || Index > poles->Length())
749 Standard_OutOfRange::Raise("Geom_BezierCurve::Weight");
751 return weights->Value(Index);
756 //=======================================================================
759 //=======================================================================
761 void Geom_BezierCurve::Weights
762 (TColStd_Array1OfReal& W) const
765 Standard_Integer nbpoles = NbPoles();
766 if(W.Length() != nbpoles)
767 Standard_DimensionError::Raise("Geom_BezierCurve::Weights");
769 W = weights->Array1();
772 for (i = 1; i <= nbpoles; i++)
777 //=======================================================================
778 //function : Transform
780 //=======================================================================
782 void Geom_BezierCurve::Transform (const gp_Trsf& T)
784 Standard_Integer nbpoles = NbPoles();
785 TColgp_Array1OfPnt & cpoles = poles->ChangeArray1();
787 for (Standard_Integer i = 1; i <= nbpoles; i++)
788 cpoles (i).Transform(T);
790 UpdateCoefficients();
793 //=======================================================================
794 //function : Resolution
796 //=======================================================================
798 void Geom_BezierCurve::Resolution(const Standard_Real Tolerance3D,
799 Standard_Real & UTolerance)
802 TColStd_Array1OfReal bidflatknots(BSplCLib::FlatBezierKnots(Degree()),
806 BSplCLib::Resolution(poles->Array1(),
815 BSplCLib::Resolution(poles->Array1(),
816 BSplCLib::NoWeights(),
825 UTolerance = Tolerance3D * maxderivinv;
828 //=======================================================================
831 //=======================================================================
833 Handle(Geom_Geometry) Geom_BezierCurve::Copy() const {
835 Handle(Geom_BezierCurve) C;
837 C = new Geom_BezierCurve (poles->Array1(),weights->Array1());
839 C = new Geom_BezierCurve (poles->Array1());
843 //=======================================================================
846 //=======================================================================
848 void Geom_BezierCurve::Init
849 (const Handle(TColgp_HArray1OfPnt)& Poles,
850 const Handle(TColStd_HArray1OfReal)& Weights)
852 Standard_Integer nbpoles = Poles->Length();
854 const TColgp_Array1OfPnt& cpoles = Poles->Array1();
855 closed = cpoles(1).Distance(cpoles(nbpoles)) <= Precision::Confusion();
858 rational = !Weights.IsNull();
862 coeffs = new TColgp_HArray1OfPnt (1,nbpoles);
866 wcoeffs = new TColStd_HArray1OfReal (1, nbpoles, 0.0);
873 UpdateCoefficients();
876 //=======================================================================
877 //function : CoefficientsOK
879 //=======================================================================
881 Standard_Boolean Geom_BezierCurve::CoefficientsOK(const Standard_Real U)const
883 return (validcache && ((parametercache == 0. && U < 1.) ||
884 (parametercache == 1. && U >= 1.)));
887 //=======================================================================
888 //function : UpdateCoefficients
890 //=======================================================================
892 //void Geom_BezierCurve::UpdateCoefficients(const Standard_Real U)
893 void Geom_BezierCurve::UpdateCoefficients(const Standard_Real )
898 // Idee lumineuse sacrifiee sur l autel des performances.
899 // if (U >= 1.) parametercache = 1.;
900 TColStd_Array1OfReal bidflatknots(BSplCLib::FlatBezierKnots(Degree()),
903 BSplCLib::BuildCache(parametercache,spanlenghtcache,0,Degree(),
904 bidflatknots,poles->Array1(),
906 coeffs->ChangeArray1(),
907 wcoeffs->ChangeArray1());
909 BSplCLib::BuildCache(parametercache,spanlenghtcache,0,Degree(),
910 bidflatknots,poles->Array1(),
911 *((TColStd_Array1OfReal*) NULL),
912 coeffs->ChangeArray1(),
913 *((TColStd_Array1OfReal*) NULL));