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 <Geom_BezierCurve.hxx>
31 #include <Geom_Geometry.hxx>
34 #include <gp_Trsf.hxx>
38 #include <Precision.hxx>
39 #include <Standard_ConstructionError.hxx>
40 #include <Standard_DimensionError.hxx>
41 #include <Standard_OutOfRange.hxx>
42 #include <Standard_RangeError.hxx>
43 #include <Standard_Type.hxx>
44 #include <TColStd_Array1OfInteger.hxx>
46 //=======================================================================
48 //purpose : check rationality of an array of weights
49 //=======================================================================
50 static Standard_Boolean Rational(const TColStd_Array1OfReal& W)
52 Standard_Integer i, n = W.Length();
53 Standard_Boolean rat = Standard_False;
54 for (i = 1; i < n; i++) {
55 rat = Abs(W(i) - W(i+1)) > gp::Resolution();
61 //=======================================================================
62 //function : Geom_BezierCurve
64 //=======================================================================
66 Geom_BezierCurve::Geom_BezierCurve(const TColgp_Array1OfPnt& Poles)
68 Standard_Integer nbpoles = Poles.Length();
69 if(nbpoles < 2 || nbpoles > (Geom_BezierCurve::MaxDegree() + 1))
70 Standard_ConstructionError::Raise();
72 Handle(TColgp_HArray1OfPnt) npoles =
73 new TColgp_HArray1OfPnt(1,nbpoles);
75 npoles->ChangeArray1() = Poles;
79 Handle(TColStd_HArray1OfReal)());
82 //=======================================================================
83 //function : Geom_BezierCurve
85 //=======================================================================
87 Geom_BezierCurve::Geom_BezierCurve(const TColgp_Array1OfPnt& Poles,
88 const TColStd_Array1OfReal& Weights)
91 Standard_Integer nbpoles = Poles.Length();
92 if(nbpoles < 2 || nbpoles > (Geom_BezierCurve::MaxDegree() + 1))
93 Standard_ConstructionError::Raise();
95 Handle(TColgp_HArray1OfPnt) npoles =
96 new TColgp_HArray1OfPnt(1,nbpoles);
98 npoles->ChangeArray1() = Poles;
103 if (Weights.Length() != nbpoles)
104 Standard_ConstructionError::Raise();
107 for (i = 1; i <= nbpoles; i++) {
108 if (Weights(i) <= gp::Resolution()) {
109 Standard_ConstructionError::Raise();
113 // check really rational
114 Standard_Boolean rat = Rational(Weights);
117 Handle(TColStd_HArray1OfReal) nweights;
119 nweights = new TColStd_HArray1OfReal(1,nbpoles);
120 nweights->ChangeArray1() = Weights;
124 Init(npoles,nweights);
127 //=======================================================================
128 //function : Increase
129 //purpose : increase degree
130 //=======================================================================
132 void Geom_BezierCurve::Increase (const Standard_Integer Deg)
134 if (Deg == Degree()) return;
137 Deg > Geom_BezierCurve::MaxDegree())
138 Standard_ConstructionError::Raise("Geom_BezierCurve::Increase");
140 Handle(TColgp_HArray1OfPnt) npoles =
141 new TColgp_HArray1OfPnt(1,Deg+1);
143 Handle(TColStd_HArray1OfReal) nweights;
145 TColStd_Array1OfReal bidknots(1,2); bidknots(1) = 0.; bidknots(2) = 1.;
146 TColStd_Array1OfInteger bidmults(1,2); bidmults.Init(Degree() + 1);
149 nweights = new TColStd_HArray1OfReal(1,Deg+1);
150 BSplCLib::IncreaseDegree(Degree(), Deg, 0,
154 npoles->ChangeArray1(),
155 &nweights->ChangeArray1(),
159 BSplCLib::IncreaseDegree(Degree(), Deg, 0,
161 BSplCLib::NoWeights(),
163 npoles->ChangeArray1(),
164 BSplCLib::NoWeights(),
168 Init(npoles,nweights);
171 //=======================================================================
172 //function : MaxDegree
174 //=======================================================================
176 Standard_Integer Geom_BezierCurve::MaxDegree ()
178 return BSplCLib::MaxDegree();
181 //=======================================================================
182 //function : InsertPoleAfter
184 //=======================================================================
186 void Geom_BezierCurve::InsertPoleAfter
187 (const Standard_Integer Index,
190 InsertPoleAfter(Index,P,1.);
193 //=======================================================================
194 //function : InsertPoleAfter
196 //=======================================================================
198 void Geom_BezierCurve::InsertPoleAfter
199 (const Standard_Integer Index,
201 const Standard_Real Weight)
203 Standard_Integer nbpoles = NbPoles();
205 if(nbpoles >= Geom_BezierCurve::MaxDegree() ||
206 Weight <= gp::Resolution())
207 Standard_ConstructionError::Raise("Geom_BezierCurve::InsertPoleAfter");
209 if(Index < 0 || Index > nbpoles)
210 Standard_OutOfRange::Raise("Geom_BezierCurve::InsertPoleAfter");
215 Handle(TColgp_HArray1OfPnt) npoles =
216 new TColgp_HArray1OfPnt(1,nbpoles+1);
218 TColgp_Array1OfPnt& newpoles = npoles->ChangeArray1();
219 const TColgp_Array1OfPnt& oldpoles = poles->Array1();
221 for (i = 1; i <= Index; i++)
222 newpoles(i) = oldpoles(i);
224 newpoles(Index+1) = P;
226 for (i = Index+1; i <= nbpoles; i++)
227 newpoles(i+1) = oldpoles(i);
231 Handle(TColStd_HArray1OfReal) nweights;
232 Standard_Boolean rat = IsRational() || Abs(Weight-1.) > gp::Resolution();
235 nweights = new TColStd_HArray1OfReal(1,nbpoles+1);
236 TColStd_Array1OfReal& newweights = nweights->ChangeArray1();
238 for (i = 1; i <= Index; i++)
240 newweights(i) = weights->Value(i);
244 newweights(Index+1) = Weight;
246 for (i = Index+1; i <= nbpoles; i++)
248 newweights(i+1) = weights->Value(i);
250 newweights(i+1) = 1.;
254 Init(npoles,nweights);
257 //=======================================================================
258 //function : InsertPoleBefore
260 //=======================================================================
262 void Geom_BezierCurve::InsertPoleBefore
263 (const Standard_Integer Index,
266 InsertPoleAfter(Index-1,P);
269 //=======================================================================
270 //function : InsertPoleBefore
272 //=======================================================================
274 void Geom_BezierCurve::InsertPoleBefore
275 (const Standard_Integer Index,
277 const Standard_Real Weight)
279 InsertPoleAfter(Index-1,P,Weight);
282 //=======================================================================
283 //function : RemovePole
285 //=======================================================================
287 void Geom_BezierCurve::RemovePole
288 (const Standard_Integer Index)
290 Standard_Integer nbpoles = NbPoles();
293 Standard_ConstructionError::Raise("Geom_BezierCurve::RemovePole");
295 if(Index < 1 || Index > nbpoles)
296 Standard_OutOfRange::Raise("Geom_BezierCurve::RemovePole");
301 Handle(TColgp_HArray1OfPnt) npoles =
302 new TColgp_HArray1OfPnt(1,nbpoles-1);
304 TColgp_Array1OfPnt& newpoles = npoles->ChangeArray1();
305 const TColgp_Array1OfPnt& oldpoles = poles->Array1();
307 for (i = 1; i < Index; i++)
308 newpoles(i) = oldpoles(i);
310 for (i = Index+1; i <= nbpoles; i++)
311 newpoles(i-1) = oldpoles(i);
315 Handle(TColStd_HArray1OfReal) nweights;
318 nweights = new TColStd_HArray1OfReal(1,nbpoles-1);
319 TColStd_Array1OfReal& newweights = nweights->ChangeArray1();
320 const TColStd_Array1OfReal& oldweights = weights->Array1();
322 for (i = 1; i < Index; i++)
323 newweights(i) = oldweights(i);
325 for (i = Index+1; i <= nbpoles; i++)
326 newweights(i-1) = oldweights(i);
329 Init(npoles,nweights);
332 //=======================================================================
335 //=======================================================================
337 void Geom_BezierCurve::Reverse ()
340 Standard_Integer i, nbpoles = NbPoles();
341 TColgp_Array1OfPnt & cpoles = poles->ChangeArray1();
344 for (i = 1; i <= nbpoles / 2; i++) {
346 cpoles(i) = cpoles(nbpoles-i+1);
347 cpoles(nbpoles-i+1) = P;
352 TColStd_Array1OfReal & cweights = weights->ChangeArray1();
354 for (i = 1; i <= nbpoles / 2; i++) {
356 cweights(i) = cweights(nbpoles-i+1);
357 cweights(nbpoles-i+1) = w;
362 //=======================================================================
363 //function : ReversedParameter
365 //=======================================================================
367 Standard_Real Geom_BezierCurve::ReversedParameter(const Standard_Real U) const
372 //=======================================================================
375 //=======================================================================
377 void Geom_BezierCurve::Segment(const Standard_Real U1, const Standard_Real U2)
379 closed = (Abs(Value(U1).Distance (Value(U2))) <= Precision::Confusion());
381 TColStd_Array1OfReal bidflatknots(BSplCLib::FlatBezierKnots(Degree()), 1, 2 * (Degree() + 1));
382 TColgp_HArray1OfPnt coeffs(1, poles->Size());
384 TColStd_Array1OfReal wcoeffs(1, poles->Size());
385 BSplCLib::BuildCache(0.0, 1.0, 0, Degree(), bidflatknots,
386 poles->Array1(), &weights->Array1(), coeffs, &wcoeffs);
387 PLib::Trimming(U1, U2, coeffs, &wcoeffs);
388 PLib::CoefficientsPoles(coeffs, &wcoeffs, poles->ChangeArray1(), &weights->ChangeArray1());
391 BSplCLib::BuildCache(0.0, 1.0, 0, Degree(), bidflatknots,
392 poles->Array1(), BSplCLib::NoWeights(), coeffs, BSplCLib::NoWeights());
393 PLib::Trimming(U1, U2, coeffs, PLib::NoWeights());
394 PLib::CoefficientsPoles(coeffs, PLib::NoWeights(), poles->ChangeArray1(), PLib::NoWeights());
398 //=======================================================================
401 //=======================================================================
403 void Geom_BezierCurve::SetPole (const Standard_Integer Index,
406 if(Index < 1 || Index > NbPoles())
407 Standard_OutOfRange::Raise("Geom_BezierCurve::SetPole");
409 TColgp_Array1OfPnt& cpoles = poles->ChangeArray1();
412 if (Index == 1 || Index == cpoles.Length()) {
413 closed = (cpoles(1).Distance(cpoles(NbPoles())) <= Precision::Confusion());
417 //=======================================================================
420 //=======================================================================
422 void Geom_BezierCurve::SetPole(const Standard_Integer Index,
424 const Standard_Real Weight)
427 SetWeight(Index,Weight);
430 //=======================================================================
431 //function : SetWeight
433 //=======================================================================
435 void Geom_BezierCurve::SetWeight(const Standard_Integer Index,
436 const Standard_Real Weight)
438 Standard_Integer nbpoles = NbPoles();
440 if(Index < 1 || Index > nbpoles)
441 Standard_OutOfRange::Raise("Geom_BezierCurve::SetWeight");
442 if(Weight <= gp::Resolution ())
443 Standard_ConstructionError::Raise("Geom_BezierCurve::SetWeight");
445 // compute new rationality
446 Standard_Boolean wasrat = IsRational();
448 // a weight of 1. does not turn to rational
449 if (Abs(Weight - 1.) <= gp::Resolution()) return;
452 weights = new TColStd_HArray1OfReal(1,nbpoles);
456 TColStd_Array1OfReal & cweights = weights->ChangeArray1();
457 cweights(Index) = Weight;
459 // is it turning into non rational
460 if (wasrat && !Rational(cweights))
464 //=======================================================================
465 //function : IsClosed
467 //=======================================================================
469 Standard_Boolean Geom_BezierCurve::IsClosed () const
474 //=======================================================================
477 //=======================================================================
479 Standard_Boolean Geom_BezierCurve::IsCN (const Standard_Integer ) const
481 return Standard_True;
484 //=======================================================================
485 //function : IsPeriodic
487 //=======================================================================
489 Standard_Boolean Geom_BezierCurve::IsPeriodic () const
491 return Standard_False;
494 //=======================================================================
495 //function : IsRational
497 //=======================================================================
499 Standard_Boolean Geom_BezierCurve::IsRational () const
501 return !weights.IsNull();
504 //=======================================================================
505 //function : Continuity
507 //=======================================================================
509 GeomAbs_Shape Geom_BezierCurve::Continuity () const
514 //=======================================================================
517 //=======================================================================
519 Standard_Integer Geom_BezierCurve::Degree () const
521 return poles->Length()-1;
524 //=======================================================================
527 //=======================================================================
529 void Geom_BezierCurve::D0 (const Standard_Real U, gp_Pnt& P ) const
531 BSplCLib::D0(U, Poles(), Weights(), P);
534 //=======================================================================
537 //=======================================================================
539 void Geom_BezierCurve::D1(const Standard_Real U, gp_Pnt& P, gp_Vec& V1) const
541 BSplCLib::D1(U, Poles(), Weights(), P, V1);
544 //=======================================================================
547 //=======================================================================
549 void Geom_BezierCurve::D2 (const Standard_Real U,
554 BSplCLib::D2(U, Poles(), Weights(), P, V1, V2);
557 //=======================================================================
560 //=======================================================================
562 void Geom_BezierCurve::D3 (const Standard_Real U,
568 BSplCLib::D3(U, Poles(), Weights(), P, V1, V2, V3);
571 //=======================================================================
574 //=======================================================================
576 gp_Vec Geom_BezierCurve::DN (const Standard_Real U,
577 const Standard_Integer N) const
580 Standard_RangeError::Raise("Geom_BezierCurve::DN");
583 TColStd_Array1OfReal bidknots(1,2); bidknots(1) = 0.; bidknots(2) = 1.;
584 TColStd_Array1OfInteger bidmults(1,2); bidmults.Init(Degree() + 1);
587 // BSplCLib::DN(U,N,0,Degree(),0.,
588 BSplCLib::DN(U,N,0,Degree(),Standard_False,
591 bidknots,&bidmults,V);
593 // BSplCLib::DN(U,N,0,Degree(),0.,
594 BSplCLib::DN(U,N,0,Degree(),Standard_False,
596 BSplCLib::NoWeights(),
597 bidknots,&bidmults,V);
601 //=======================================================================
602 //function : StartPoint
604 //=======================================================================
606 gp_Pnt Geom_BezierCurve::StartPoint () const
608 return poles->Value(1);
611 //=======================================================================
612 //function : EndPoint
614 //=======================================================================
616 gp_Pnt Geom_BezierCurve::EndPoint () const
618 return poles->Value (poles->Upper());
621 //=======================================================================
622 //function : FirstParameter
624 //=======================================================================
626 Standard_Real Geom_BezierCurve::FirstParameter () const
631 //=======================================================================
632 //function : LastParameter
634 //=======================================================================
636 Standard_Real Geom_BezierCurve::LastParameter () const
641 //=======================================================================
644 //=======================================================================
646 Standard_Integer Geom_BezierCurve::NbPoles () const
648 return poles->Length();
651 //=======================================================================
654 //=======================================================================
656 gp_Pnt Geom_BezierCurve::Pole (const Standard_Integer Index) const
658 if(Index < 1 || Index > poles->Length())
659 Standard_OutOfRange::Raise("Geom_BezierCurve::Pole");
660 return poles->Value(Index);
663 //=======================================================================
666 //=======================================================================
668 void Geom_BezierCurve::Poles (TColgp_Array1OfPnt& P) const
670 if(P.Length() != poles->Length())
671 Standard_DimensionError::Raise("Geom_BezierCurve::Poles");
676 //=======================================================================
679 //=======================================================================
681 const TColgp_Array1OfPnt& Geom_BezierCurve::Poles() const
683 return poles->Array1();
686 //=======================================================================
689 //=======================================================================
691 Standard_Real Geom_BezierCurve::Weight
692 (const Standard_Integer Index) const
694 if(Index < 1 || Index > poles->Length())
695 Standard_OutOfRange::Raise("Geom_BezierCurve::Weight");
697 return weights->Value(Index);
702 //=======================================================================
705 //=======================================================================
707 void Geom_BezierCurve::Weights
708 (TColStd_Array1OfReal& W) const
711 Standard_Integer nbpoles = NbPoles();
712 if(W.Length() != nbpoles)
713 Standard_DimensionError::Raise("Geom_BezierCurve::Weights");
715 W = weights->Array1();
718 for (i = 1; i <= nbpoles; i++)
723 //=======================================================================
724 //function : Transform
726 //=======================================================================
728 void Geom_BezierCurve::Transform (const gp_Trsf& T)
730 Standard_Integer nbpoles = NbPoles();
731 TColgp_Array1OfPnt & cpoles = poles->ChangeArray1();
733 for (Standard_Integer i = 1; i <= nbpoles; i++)
734 cpoles (i).Transform(T);
737 //=======================================================================
738 //function : Resolution
740 //=======================================================================
742 void Geom_BezierCurve::Resolution(const Standard_Real Tolerance3D,
743 Standard_Real & UTolerance)
746 TColStd_Array1OfReal bidflatknots(BSplCLib::FlatBezierKnots(Degree()),
750 BSplCLib::Resolution(poles->Array1(),
759 BSplCLib::Resolution(poles->Array1(),
760 BSplCLib::NoWeights(),
769 UTolerance = Tolerance3D * maxderivinv;
772 //=======================================================================
775 //=======================================================================
777 Handle(Geom_Geometry) Geom_BezierCurve::Copy() const {
779 Handle(Geom_BezierCurve) C;
781 C = new Geom_BezierCurve (poles->Array1(),weights->Array1());
783 C = new Geom_BezierCurve (poles->Array1());
787 //=======================================================================
790 //=======================================================================
792 void Geom_BezierCurve::Init
793 (const Handle(TColgp_HArray1OfPnt)& Poles,
794 const Handle(TColStd_HArray1OfReal)& Weights)
796 Standard_Integer nbpoles = Poles->Length();
798 const TColgp_Array1OfPnt& cpoles = Poles->Array1();
799 closed = cpoles(1).Distance(cpoles(nbpoles)) <= Precision::Confusion();
802 rational = !Weights.IsNull();