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 IMPLEMENT_STANDARD_RTTIEXT(Geom_BezierCurve,Geom_BoundedCurve)
48 //=======================================================================
50 //purpose : check rationality of an array of weights
51 //=======================================================================
52 static Standard_Boolean Rational(const TColStd_Array1OfReal& W)
54 Standard_Integer i, n = W.Length();
55 Standard_Boolean rat = Standard_False;
56 for (i = 1; i < n; i++) {
57 rat = Abs(W(i) - W(i+1)) > gp::Resolution();
63 //=======================================================================
64 //function : Geom_BezierCurve
66 //=======================================================================
68 Geom_BezierCurve::Geom_BezierCurve(const TColgp_Array1OfPnt& Poles)
70 Standard_Integer nbpoles = Poles.Length();
71 if(nbpoles < 2 || nbpoles > (Geom_BezierCurve::MaxDegree() + 1))
72 throw Standard_ConstructionError();
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)
93 Standard_Integer nbpoles = Poles.Length();
94 if(nbpoles < 2 || nbpoles > (Geom_BezierCurve::MaxDegree() + 1))
95 throw Standard_ConstructionError();
97 Handle(TColgp_HArray1OfPnt) npoles =
98 new TColgp_HArray1OfPnt(1,nbpoles);
100 npoles->ChangeArray1() = Poles;
105 if (Weights.Length() != nbpoles)
106 throw Standard_ConstructionError();
109 for (i = 1; i <= nbpoles; i++) {
110 if (Weights(i) <= gp::Resolution()) {
111 throw Standard_ConstructionError();
115 // check really rational
116 Standard_Boolean rat = Rational(Weights);
119 Handle(TColStd_HArray1OfReal) nweights;
121 nweights = new TColStd_HArray1OfReal(1,nbpoles);
122 nweights->ChangeArray1() = Weights;
126 Init(npoles,nweights);
129 //=======================================================================
130 //function : Increase
131 //purpose : increase degree
132 //=======================================================================
134 void Geom_BezierCurve::Increase (const Standard_Integer Deg)
136 if (Deg == Degree()) return;
139 Deg > Geom_BezierCurve::MaxDegree())
140 throw Standard_ConstructionError("Geom_BezierCurve::Increase");
142 Handle(TColgp_HArray1OfPnt) npoles =
143 new TColgp_HArray1OfPnt(1,Deg+1);
145 Handle(TColStd_HArray1OfReal) nweights;
147 TColStd_Array1OfReal bidknots(1,2); bidknots(1) = 0.; bidknots(2) = 1.;
148 TColStd_Array1OfInteger bidmults(1,2); bidmults.Init(Degree() + 1);
151 nweights = new TColStd_HArray1OfReal(1,Deg+1);
152 BSplCLib::IncreaseDegree(Degree(), Deg, 0,
156 npoles->ChangeArray1(),
157 &nweights->ChangeArray1(),
161 BSplCLib::IncreaseDegree(Degree(), Deg, 0,
163 BSplCLib::NoWeights(),
165 npoles->ChangeArray1(),
166 BSplCLib::NoWeights(),
170 Init(npoles,nweights);
173 //=======================================================================
174 //function : MaxDegree
176 //=======================================================================
178 Standard_Integer Geom_BezierCurve::MaxDegree ()
180 return BSplCLib::MaxDegree();
183 //=======================================================================
184 //function : InsertPoleAfter
186 //=======================================================================
188 void Geom_BezierCurve::InsertPoleAfter
189 (const Standard_Integer Index,
192 InsertPoleAfter(Index,P,1.);
195 //=======================================================================
196 //function : InsertPoleAfter
198 //=======================================================================
200 void Geom_BezierCurve::InsertPoleAfter
201 (const Standard_Integer Index,
203 const Standard_Real Weight)
205 Standard_Integer nbpoles = NbPoles();
207 if(nbpoles >= Geom_BezierCurve::MaxDegree() ||
208 Weight <= gp::Resolution())
209 throw Standard_ConstructionError("Geom_BezierCurve::InsertPoleAfter");
211 if(Index < 0 || Index > nbpoles)
212 throw Standard_OutOfRange("Geom_BezierCurve::InsertPoleAfter");
217 Handle(TColgp_HArray1OfPnt) npoles =
218 new TColgp_HArray1OfPnt(1,nbpoles+1);
220 TColgp_Array1OfPnt& newpoles = npoles->ChangeArray1();
221 const TColgp_Array1OfPnt& oldpoles = poles->Array1();
223 for (i = 1; i <= Index; i++)
224 newpoles(i) = oldpoles(i);
226 newpoles(Index+1) = P;
228 for (i = Index+1; i <= nbpoles; i++)
229 newpoles(i+1) = oldpoles(i);
233 Handle(TColStd_HArray1OfReal) nweights;
234 Standard_Boolean rat = IsRational() || Abs(Weight-1.) > gp::Resolution();
237 nweights = new TColStd_HArray1OfReal(1,nbpoles+1);
238 TColStd_Array1OfReal& newweights = nweights->ChangeArray1();
240 for (i = 1; i <= Index; i++)
242 newweights(i) = weights->Value(i);
246 newweights(Index+1) = Weight;
248 for (i = Index+1; i <= nbpoles; i++)
250 newweights(i+1) = weights->Value(i);
252 newweights(i+1) = 1.;
256 Init(npoles,nweights);
259 //=======================================================================
260 //function : InsertPoleBefore
262 //=======================================================================
264 void Geom_BezierCurve::InsertPoleBefore
265 (const Standard_Integer Index,
268 InsertPoleAfter(Index-1,P);
271 //=======================================================================
272 //function : InsertPoleBefore
274 //=======================================================================
276 void Geom_BezierCurve::InsertPoleBefore
277 (const Standard_Integer Index,
279 const Standard_Real Weight)
281 InsertPoleAfter(Index-1,P,Weight);
284 //=======================================================================
285 //function : RemovePole
287 //=======================================================================
289 void Geom_BezierCurve::RemovePole
290 (const Standard_Integer Index)
292 Standard_Integer nbpoles = NbPoles();
295 throw Standard_ConstructionError("Geom_BezierCurve::RemovePole");
297 if(Index < 1 || Index > nbpoles)
298 throw Standard_OutOfRange("Geom_BezierCurve::RemovePole");
303 Handle(TColgp_HArray1OfPnt) npoles =
304 new TColgp_HArray1OfPnt(1,nbpoles-1);
306 TColgp_Array1OfPnt& newpoles = npoles->ChangeArray1();
307 const TColgp_Array1OfPnt& oldpoles = poles->Array1();
309 for (i = 1; i < Index; i++)
310 newpoles(i) = oldpoles(i);
312 for (i = Index+1; i <= nbpoles; i++)
313 newpoles(i-1) = oldpoles(i);
317 Handle(TColStd_HArray1OfReal) nweights;
320 nweights = new TColStd_HArray1OfReal(1,nbpoles-1);
321 TColStd_Array1OfReal& newweights = nweights->ChangeArray1();
322 const TColStd_Array1OfReal& oldweights = weights->Array1();
324 for (i = 1; i < Index; i++)
325 newweights(i) = oldweights(i);
327 for (i = Index+1; i <= nbpoles; i++)
328 newweights(i-1) = oldweights(i);
331 Init(npoles,nweights);
334 //=======================================================================
337 //=======================================================================
339 void Geom_BezierCurve::Reverse ()
342 Standard_Integer i, nbpoles = NbPoles();
343 TColgp_Array1OfPnt & cpoles = poles->ChangeArray1();
346 for (i = 1; i <= nbpoles / 2; i++) {
348 cpoles(i) = cpoles(nbpoles-i+1);
349 cpoles(nbpoles-i+1) = P;
354 TColStd_Array1OfReal & cweights = weights->ChangeArray1();
356 for (i = 1; i <= nbpoles / 2; i++) {
358 cweights(i) = cweights(nbpoles-i+1);
359 cweights(nbpoles-i+1) = w;
364 //=======================================================================
365 //function : ReversedParameter
367 //=======================================================================
369 Standard_Real Geom_BezierCurve::ReversedParameter(const Standard_Real U) const
374 //=======================================================================
377 //=======================================================================
379 void Geom_BezierCurve::Segment(const Standard_Real U1, const Standard_Real U2)
381 closed = (Abs(Value(U1).Distance (Value(U2))) <= Precision::Confusion());
383 TColStd_Array1OfReal bidflatknots(BSplCLib::FlatBezierKnots(Degree()), 1, 2 * (Degree() + 1));
384 TColgp_HArray1OfPnt coeffs(1, poles->Size());
386 TColStd_Array1OfReal wcoeffs(1, poles->Size());
387 BSplCLib::BuildCache(0.0, 1.0, 0, Degree(), bidflatknots,
388 poles->Array1(), &weights->Array1(), coeffs, &wcoeffs);
389 PLib::Trimming(U1, U2, coeffs, &wcoeffs);
390 PLib::CoefficientsPoles(coeffs, &wcoeffs, poles->ChangeArray1(), &weights->ChangeArray1());
393 BSplCLib::BuildCache(0.0, 1.0, 0, Degree(), bidflatknots,
394 poles->Array1(), BSplCLib::NoWeights(), coeffs, BSplCLib::NoWeights());
395 PLib::Trimming(U1, U2, coeffs, PLib::NoWeights());
396 PLib::CoefficientsPoles(coeffs, PLib::NoWeights(), poles->ChangeArray1(), PLib::NoWeights());
400 //=======================================================================
403 //=======================================================================
405 void Geom_BezierCurve::SetPole (const Standard_Integer Index,
408 if(Index < 1 || Index > NbPoles())
409 throw Standard_OutOfRange("Geom_BezierCurve::SetPole");
411 TColgp_Array1OfPnt& cpoles = poles->ChangeArray1();
414 if (Index == 1 || Index == cpoles.Length()) {
415 closed = (cpoles(1).Distance(cpoles(NbPoles())) <= Precision::Confusion());
419 //=======================================================================
422 //=======================================================================
424 void Geom_BezierCurve::SetPole(const Standard_Integer Index,
426 const Standard_Real Weight)
429 SetWeight(Index,Weight);
432 //=======================================================================
433 //function : SetWeight
435 //=======================================================================
437 void Geom_BezierCurve::SetWeight(const Standard_Integer Index,
438 const Standard_Real Weight)
440 Standard_Integer nbpoles = NbPoles();
442 if(Index < 1 || Index > nbpoles)
443 throw Standard_OutOfRange("Geom_BezierCurve::SetWeight");
444 if(Weight <= gp::Resolution ())
445 throw Standard_ConstructionError("Geom_BezierCurve::SetWeight");
447 // compute new rationality
448 Standard_Boolean wasrat = IsRational();
450 // a weight of 1. does not turn to rational
451 if (Abs(Weight - 1.) <= gp::Resolution()) return;
454 weights = new TColStd_HArray1OfReal(1,nbpoles);
458 TColStd_Array1OfReal & cweights = weights->ChangeArray1();
459 cweights(Index) = Weight;
461 // is it turning into non rational
462 if (wasrat && !Rational(cweights))
466 //=======================================================================
467 //function : IsClosed
469 //=======================================================================
471 Standard_Boolean Geom_BezierCurve::IsClosed () const
476 //=======================================================================
479 //=======================================================================
481 Standard_Boolean Geom_BezierCurve::IsCN (const Standard_Integer ) const
483 return Standard_True;
486 //=======================================================================
487 //function : IsPeriodic
489 //=======================================================================
491 Standard_Boolean Geom_BezierCurve::IsPeriodic () const
493 return Standard_False;
496 //=======================================================================
497 //function : IsRational
499 //=======================================================================
501 Standard_Boolean Geom_BezierCurve::IsRational () const
503 return !weights.IsNull();
506 //=======================================================================
507 //function : Continuity
509 //=======================================================================
511 GeomAbs_Shape Geom_BezierCurve::Continuity () const
516 //=======================================================================
519 //=======================================================================
521 Standard_Integer Geom_BezierCurve::Degree () const
523 return poles->Length()-1;
526 //=======================================================================
529 //=======================================================================
531 void Geom_BezierCurve::D0 (const Standard_Real U, gp_Pnt& P ) const
533 BSplCLib::D0(U, Poles(), Weights(), P);
536 //=======================================================================
539 //=======================================================================
541 void Geom_BezierCurve::D1(const Standard_Real U, gp_Pnt& P, gp_Vec& V1) const
543 BSplCLib::D1(U, Poles(), Weights(), P, V1);
546 //=======================================================================
549 //=======================================================================
551 void Geom_BezierCurve::D2 (const Standard_Real U,
556 BSplCLib::D2(U, Poles(), Weights(), P, V1, V2);
559 //=======================================================================
562 //=======================================================================
564 void Geom_BezierCurve::D3 (const Standard_Real U,
570 BSplCLib::D3(U, Poles(), Weights(), P, V1, V2, V3);
573 //=======================================================================
576 //=======================================================================
578 gp_Vec Geom_BezierCurve::DN (const Standard_Real U,
579 const Standard_Integer N) const
582 throw Standard_RangeError("Geom_BezierCurve::DN");
585 TColStd_Array1OfReal bidknots(1,2); bidknots(1) = 0.; bidknots(2) = 1.;
586 TColStd_Array1OfInteger bidmults(1,2); bidmults.Init(Degree() + 1);
589 // BSplCLib::DN(U,N,0,Degree(),0.,
590 BSplCLib::DN(U,N,0,Degree(),Standard_False,
593 bidknots,&bidmults,V);
595 // BSplCLib::DN(U,N,0,Degree(),0.,
596 BSplCLib::DN(U,N,0,Degree(),Standard_False,
598 BSplCLib::NoWeights(),
599 bidknots,&bidmults,V);
603 //=======================================================================
604 //function : StartPoint
606 //=======================================================================
608 gp_Pnt Geom_BezierCurve::StartPoint () const
610 return poles->Value(1);
613 //=======================================================================
614 //function : EndPoint
616 //=======================================================================
618 gp_Pnt Geom_BezierCurve::EndPoint () const
620 return poles->Value (poles->Upper());
623 //=======================================================================
624 //function : FirstParameter
626 //=======================================================================
628 Standard_Real Geom_BezierCurve::FirstParameter () const
633 //=======================================================================
634 //function : LastParameter
636 //=======================================================================
638 Standard_Real Geom_BezierCurve::LastParameter () const
643 //=======================================================================
646 //=======================================================================
648 Standard_Integer Geom_BezierCurve::NbPoles () const
650 return poles->Length();
653 //=======================================================================
656 //=======================================================================
658 const gp_Pnt& Geom_BezierCurve::Pole (const Standard_Integer Index) const
660 if(Index < 1 || Index > poles->Length())
661 throw Standard_OutOfRange("Geom_BezierCurve::Pole");
662 return poles->Value(Index);
665 //=======================================================================
668 //=======================================================================
670 void Geom_BezierCurve::Poles (TColgp_Array1OfPnt& P) const
672 if(P.Length() != poles->Length())
673 throw Standard_DimensionError("Geom_BezierCurve::Poles");
678 //=======================================================================
681 //=======================================================================
683 const TColgp_Array1OfPnt& Geom_BezierCurve::Poles() const
685 return poles->Array1();
688 //=======================================================================
691 //=======================================================================
693 Standard_Real Geom_BezierCurve::Weight
694 (const Standard_Integer Index) const
696 if(Index < 1 || Index > poles->Length())
697 throw Standard_OutOfRange("Geom_BezierCurve::Weight");
699 return weights->Value(Index);
704 //=======================================================================
707 //=======================================================================
709 void Geom_BezierCurve::Weights
710 (TColStd_Array1OfReal& W) const
713 Standard_Integer nbpoles = NbPoles();
714 if(W.Length() != nbpoles)
715 throw Standard_DimensionError("Geom_BezierCurve::Weights");
717 W = weights->Array1();
720 for (i = 1; i <= nbpoles; i++)
725 //=======================================================================
726 //function : Transform
728 //=======================================================================
730 void Geom_BezierCurve::Transform (const gp_Trsf& T)
732 Standard_Integer nbpoles = NbPoles();
733 TColgp_Array1OfPnt & cpoles = poles->ChangeArray1();
735 for (Standard_Integer i = 1; i <= nbpoles; i++)
736 cpoles (i).Transform(T);
739 //=======================================================================
740 //function : Resolution
742 //=======================================================================
744 void Geom_BezierCurve::Resolution(const Standard_Real Tolerance3D,
745 Standard_Real & UTolerance)
748 TColStd_Array1OfReal bidflatknots(BSplCLib::FlatBezierKnots(Degree()),
752 BSplCLib::Resolution(poles->Array1(),
761 BSplCLib::Resolution(poles->Array1(),
762 BSplCLib::NoWeights(),
771 UTolerance = Tolerance3D * maxderivinv;
774 //=======================================================================
777 //=======================================================================
779 Handle(Geom_Geometry) Geom_BezierCurve::Copy() const {
781 Handle(Geom_BezierCurve) C;
783 C = new Geom_BezierCurve (poles->Array1(),weights->Array1());
785 C = new Geom_BezierCurve (poles->Array1());
789 //=======================================================================
792 //=======================================================================
794 void Geom_BezierCurve::Init
795 (const Handle(TColgp_HArray1OfPnt)& Poles,
796 const Handle(TColStd_HArray1OfReal)& Weights)
798 Standard_Integer nbpoles = Poles->Length();
800 const TColgp_Array1OfPnt& cpoles = Poles->Array1();
801 closed = cpoles(1).Distance(cpoles(nbpoles)) <= Precision::Confusion();
804 rational = !Weights.IsNull();
815 //=======================================================================
816 //function : DumpJson
818 //=======================================================================
819 void Geom_BezierCurve::DumpJson (Standard_OStream& theOStream, Standard_Integer theDepth) const
821 OCCT_DUMP_TRANSIENT_CLASS_BEGIN (theOStream)
823 OCCT_DUMP_BASE_CLASS (theOStream, theDepth, Geom_BoundedCurve)
825 OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, rational)
826 OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, closed)
828 OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, poles->Size())
829 if (!weights.IsNull())
830 OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, weights->Size())
832 OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, maxderivinv)
833 OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, maxderivinvok)