1 // Created on: 1993-10-20
2 // Created by: Bruno DUMORTIER
3 // Copyright (c) 1993-1999 Matra Datavision
4 // Copyright (c) 1999-2014 OPEN CASCADE SAS
5 //
6 // This file is part of Open CASCADE Technology software library.
7 //
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.
13 //
14 // Alternatively, this file may be used under the terms of Open CASCADE
15 // commercial license or contractual agreement.
16 
17 
18 #include <BSplCLib.hxx>
19 #include <Convert_CompBezierCurvesToBSplineCurve.hxx>
20 #include <gp.hxx>
21 #include <gp_Pnt.hxx>
22 #include <gp_Vec.hxx>
23 #include <PLib.hxx>
24 #include <Precision.hxx>
25 #include <Standard_ConstructionError.hxx>
26 #include <TColgp_HArray1OfPnt.hxx>
27 
28 //=======================================================================
29 //function : Convert_CompBezierCurvesToBSplineCurve
30 //purpose  :
31 //=======================================================================
32 Convert_CompBezierCurvesToBSplineCurve::
Convert_CompBezierCurvesToBSplineCurve(const Standard_Real AngularTolerance)33 Convert_CompBezierCurvesToBSplineCurve(
34 	          const Standard_Real AngularTolerance) :
35 		  myAngular(AngularTolerance),
36 		  myDone(Standard_False)
37 {
38 }
39 
40 
41 //=======================================================================
42 //function : AddCurve
43 //purpose  :
44 //=======================================================================
45 
AddCurve(const TColgp_Array1OfPnt & Poles)46 void  Convert_CompBezierCurvesToBSplineCurve::AddCurve
47   (const TColgp_Array1OfPnt& Poles)
48 {
49   if ( !mySequence.IsEmpty()) {
50     gp_Pnt P1,P2;
51     P1 = mySequence.Last()->Value(mySequence.Last()->Upper());
52     P2 = Poles(Poles.Lower());
53 
54 #ifdef OCCT_DEBUG
55     if (!P1.IsEqual(P2, Precision::Confusion()))
56       std::cout << "Convert_CompBezierCurvesToBSplineCurve::Addcurve" << std::endl;
57 #endif
58   }
59   myDone = Standard_False;
60   Handle(TColgp_HArray1OfPnt) HPoles =
61     new TColgp_HArray1OfPnt(Poles.Lower(),Poles.Upper());
62   HPoles->ChangeArray1() = Poles;
63   mySequence.Append(HPoles);
64 }
65 
66 
67 //=======================================================================
68 //function : Degree
69 //purpose  :
70 //=======================================================================
71 
Degree() const72 Standard_Integer  Convert_CompBezierCurvesToBSplineCurve::Degree() const
73 {
74   return myDegree;
75 }
76 
77 
78 //=======================================================================
79 //function : NbPoles
80 //purpose  :
81 //=======================================================================
82 
NbPoles() const83 Standard_Integer  Convert_CompBezierCurvesToBSplineCurve::NbPoles() const
84 {
85   return CurvePoles.Length();
86 }
87 
88 
89 //=======================================================================
90 //function : Poles
91 //purpose  :
92 //=======================================================================
93 
Poles(TColgp_Array1OfPnt & Poles) const94 void  Convert_CompBezierCurvesToBSplineCurve::Poles
95   (TColgp_Array1OfPnt& Poles) const
96 {
97   Standard_Integer i, Lower = Poles.Lower(), Upper = Poles.Upper();
98   Standard_Integer k = 1;
99   for (i = Lower; i <= Upper; i++) {
100     Poles(i) = CurvePoles(k++);
101   }
102 }
103 
104 
105 //=======================================================================
106 //function : NbKnots
107 //purpose  :
108 //=======================================================================
109 
NbKnots() const110 Standard_Integer  Convert_CompBezierCurvesToBSplineCurve::NbKnots() const
111 {
112   return CurveKnots.Length();
113 }
114 
115 
116 //=======================================================================
117 //function : KnotsAndMults
118 //purpose  :
119 //=======================================================================
120 
KnotsAndMults(TColStd_Array1OfReal & Knots,TColStd_Array1OfInteger & Mults) const121 void  Convert_CompBezierCurvesToBSplineCurve::KnotsAndMults
122   (TColStd_Array1OfReal&    Knots,
123    TColStd_Array1OfInteger& Mults ) const
124 {
125   Standard_Integer i, LowerK = Knots.Lower(), UpperK = Knots.Upper();
126   Standard_Integer LowerM = Mults.Lower(), UpperM = Mults.Upper();
127   Standard_Integer k = 1;
128   for (i = LowerK; i <= UpperK; i++) {
129     Knots(i) = CurveKnots(k++);
130   }
131   k = 1;
132   for (i = LowerM; i <= UpperM; i++) {
133     Mults(i) = KnotsMultiplicities(k++);
134   }
135 }
136 
137 
138 
139 //=======================================================================
140 //function : Perform
141 //purpose  :
142 //=======================================================================
143 
Perform()144 void Convert_CompBezierCurvesToBSplineCurve::Perform()
145 {
146   myDone = Standard_True;
147   CurvePoles.Clear();
148   CurveKnots.Clear();
149   KnotsMultiplicities.Clear();
150   Standard_Integer LowerI     = 1;
151   Standard_Integer UpperI     = mySequence.Length();
152   Standard_Integer NbrCurv    = UpperI-LowerI+1;
153 //  Standard_Integer NbKnotsSpl = NbrCurv + 1 ;
154   TColStd_Array1OfReal     CurveKnVals         (1,NbrCurv);
155 
156   Standard_Integer i;
157   myDegree = 0;
158   for ( i = 1; i <= mySequence.Length(); i++) {
159     myDegree = Max( myDegree, (mySequence(i))->Length() -1);
160   }
161 
162   Standard_Real Det=0;
163   gp_Pnt P1, P2, P3;
164   Standard_Integer Deg, Inc, MaxDegree = myDegree;
165   TColgp_Array1OfPnt Points(1, myDegree+1);
166 
167   for (i = LowerI ; i <= UpperI ; i++) {
168     // 1- Raise the Bezier curve to the maximum degree.
169     Deg = mySequence(i)->Length()-1;
170     Inc = myDegree - Deg;
171     if ( Inc > 0) {
172       BSplCLib::IncreaseDegree(myDegree,
173 			       mySequence(i)->Array1(), BSplCLib::NoWeights(),
174 			       Points, BSplCLib::NoWeights());
175     }
176     else {
177       Points = mySequence(i)->Array1();
178     }
179 
180     // 2- Process the node of junction between 2 Bezier curves.
181     if (i == LowerI) {
182       // Processing of the initial node of the BSpline.
183       for (Standard_Integer j = 1 ; j <= MaxDegree ; j++) {
184         CurvePoles.Append(Points(j));
185       }
186       CurveKnVals(1)         = 1.; // To begin the series.
187       KnotsMultiplicities.Append(MaxDegree+1);
188       Det = 1.;
189     }
190 
191 
192     if (i != LowerI) {
193       P2 = Points(1);
194       P3 = Points(2);
195       gp_Vec V1(P1, P2), V2(P2, P3);
196 
197       // Processing of the tangency between Bezier and the previous.
198       // This allows to guarantee at least a C1 continuity if the tangents are
199       // coherent.
200 
201       Standard_Real D1 = V1.SquareMagnitude();
202       Standard_Real D2 = V2.SquareMagnitude();
203       if (MaxDegree > 1 && //rln 20.06.99 work-around
204           D1 > gp::Resolution() && D2 > gp::Resolution() && V1.IsParallel(V2, myAngular ))
205       {
206           Standard_Real Lambda = Sqrt(D2/D1);
207           if(CurveKnVals(i-1) * Lambda > 10. * Epsilon(Det)) {
208             KnotsMultiplicities.Append(MaxDegree-1);
209             CurveKnVals(i) = CurveKnVals(i-1) * Lambda;
210           }
211           else {
212             CurvePoles.Append(Points(1));
213             KnotsMultiplicities.Append(MaxDegree);
214             CurveKnVals(i) = 1.0 ;
215           }
216       }
217       else {
218         CurvePoles.Append(Points(1));
219         KnotsMultiplicities.Append(MaxDegree);
220         CurveKnVals(i) = 1.0 ;
221       }
222       Det += CurveKnVals(i);
223 
224       // Store the poles.
225       for (Standard_Integer j = 2 ; j <= MaxDegree ; j++) {
226         CurvePoles.Append(Points(j));
227       }
228 
229     }
230 
231 
232     if (i == UpperI) {
233       // Processing of the end node of the BSpline.
234       CurvePoles.Append(Points(MaxDegree+1));
235       KnotsMultiplicities.Append(MaxDegree+1);
236     }
237     P1 = Points(MaxDegree);
238   }
239 
240   // Correct nodal values to make them variable within [0.,1.].
241   CurveKnots.Append(0.0);
242 //  std::cout << "Convert : Det = " << Det << std::endl;
243   for (i = 2 ; i <= NbrCurv ; i++) {
244     CurveKnots.Append(CurveKnots(i-1) + (CurveKnVals(i-1)/Det));
245   }
246   CurveKnots.Append(1.0);
247 }
248 
249 
250