2e7ae3de7d00d8555b684673a386c5013b25cfd2
[occt.git] / src / Convert / Convert_CompBezierCurvesToBSplineCurve.cxx
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::
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
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     // NYI
55   if ( !P1.IsEqual(P2,Precision::Confusion()))
56       cout << "Convert_CompBezierCurvesToBSplineCurve::Addcurve" << endl;;
57   }
58   myDone = Standard_False;
59   Handle(TColgp_HArray1OfPnt) HPoles = 
60     new TColgp_HArray1OfPnt(Poles.Lower(),Poles.Upper());
61   HPoles->ChangeArray1() = Poles;
62   mySequence.Append(HPoles);
63 }
64
65
66 //=======================================================================
67 //function : Degree
68 //purpose  : 
69 //=======================================================================
70
71 Standard_Integer  Convert_CompBezierCurvesToBSplineCurve::Degree() const
72 {
73   return myDegree;
74 }
75
76
77 //=======================================================================
78 //function : NbPoles
79 //purpose  : 
80 //=======================================================================
81
82 Standard_Integer  Convert_CompBezierCurvesToBSplineCurve::NbPoles() const
83 {
84   return CurvePoles.Length();
85 }
86
87
88 //=======================================================================
89 //function : Poles
90 //purpose  : 
91 //=======================================================================
92
93 void  Convert_CompBezierCurvesToBSplineCurve::Poles
94   (TColgp_Array1OfPnt& Poles) const
95 {
96   Standard_Integer i, Lower = Poles.Lower(), Upper = Poles.Upper();
97   Standard_Integer k = 1;
98   for (i = Lower; i <= Upper; i++) {
99     Poles(i) = CurvePoles(k++);
100   }
101 }
102
103
104 //=======================================================================
105 //function : NbKnots
106 //purpose  : 
107 //=======================================================================
108
109 Standard_Integer  Convert_CompBezierCurvesToBSplineCurve::NbKnots() const
110 {
111   return CurveKnots.Length();
112 }
113
114
115 //=======================================================================
116 //function : KnotsAndMults
117 //purpose  : 
118 //=======================================================================
119
120 void  Convert_CompBezierCurvesToBSplineCurve::KnotsAndMults
121   (TColStd_Array1OfReal&    Knots, 
122    TColStd_Array1OfInteger& Mults ) const
123 {
124   Standard_Integer i, LowerK = Knots.Lower(), UpperK = Knots.Upper();
125   Standard_Integer LowerM = Mults.Lower(), UpperM = Mults.Upper();
126   Standard_Integer k = 1;
127   for (i = LowerK; i <= UpperK; i++) {
128     Knots(i) = CurveKnots(k++);
129   }
130   k = 1;
131   for (i = LowerM; i <= UpperM; i++) {
132     Mults(i) = KnotsMultiplicities(k++);
133   }
134 }
135
136
137
138 //=======================================================================
139 //function : Perform
140 //purpose  : 
141 //=======================================================================
142
143 void Convert_CompBezierCurvesToBSplineCurve::Perform() 
144 {
145   myDone = Standard_True;
146   CurvePoles.Clear();
147   CurveKnots.Clear();
148   KnotsMultiplicities.Clear();
149   Standard_Integer LowerI     = 1;
150   Standard_Integer UpperI     = mySequence.Length();
151   Standard_Integer NbrCurv    = UpperI-LowerI+1;
152 //  Standard_Integer NbKnotsSpl = NbrCurv + 1 ;
153   TColStd_Array1OfReal     CurveKnVals         (1,NbrCurv);
154
155   Standard_Integer i;
156   myDegree = 0;
157   for ( i = 1; i <= mySequence.Length(); i++) {
158     myDegree = Max( myDegree, (mySequence(i))->Length() -1);
159   }
160
161   Standard_Real Det=0;
162   gp_Pnt P1, P2, P3;
163   Standard_Integer Deg, Inc, MaxDegree = myDegree;
164   TColgp_Array1OfPnt Points(1, myDegree+1);
165
166   for (i = LowerI ; i <= UpperI ; i++) {
167     // 1- Raise the Bezier curve to the maximum degree.
168     Deg = mySequence(i)->Length()-1;
169     Inc = myDegree - Deg;
170     if ( Inc > 0) {
171       BSplCLib::IncreaseDegree(myDegree, 
172                                mySequence(i)->Array1(), BSplCLib::NoWeights(), 
173                                Points, BSplCLib::NoWeights());
174     }
175     else {
176       Points = mySequence(i)->Array1();
177     }
178
179     // 2- Process the node of junction between 2 Bezier curves.
180     if (i == LowerI) {
181       // Processing of the initial node of the BSpline.
182       for (Standard_Integer j = 1 ; j <= MaxDegree ; j++) {
183         CurvePoles.Append(Points(j));
184       }
185       CurveKnVals(1)         = 1.; // To begin the series.
186       KnotsMultiplicities.Append(MaxDegree+1);
187       Det = 1.;
188     }
189
190
191     if (i != LowerI) {
192       P2 = Points(1);
193       P3 = Points(2);
194       gp_Vec V1(P1, P2), V2(P2, P3);
195
196       // Processing of the tangency between Bezier and the previous.
197       // This allows to guarantee at least a C1 continuity if the tangents are  
198       // coherent.
199       
200       Standard_Real D1 = V1.SquareMagnitude();
201       Standard_Real D2 = V2.SquareMagnitude();
202       if (D1 > gp::Resolution() && D2 > gp::Resolution() && V1.IsParallel(V2, myAngular )) {
203           Standard_Real Lambda = Sqrt(D2/D1);
204           if(CurveKnVals(i-1) * Lambda > 10. * Epsilon(Det)) {
205             KnotsMultiplicities.Append(MaxDegree-1);
206             CurveKnVals(i) = CurveKnVals(i-1) * Lambda;
207             Det += CurveKnVals(i);
208           }
209           else {
210             CurvePoles.Append(Points(1));
211             KnotsMultiplicities.Append(MaxDegree);
212             CurveKnVals(i) = 1.0 ;
213             Det += CurveKnVals(i) ;
214           }
215       }
216       else {
217         CurvePoles.Append(Points(1));
218         KnotsMultiplicities.Append(MaxDegree);
219         CurveKnVals(i) = 1.0 ;
220         Det += CurveKnVals(i) ;
221       }
222
223       // Store the poles.
224       for (Standard_Integer j = 2 ; j <= MaxDegree ; j++) {
225         CurvePoles.Append(Points(j));
226       }
227
228     }
229
230
231     if (i == UpperI) {
232       // Processing of the end node of the BSpline.
233       CurvePoles.Append(Points(MaxDegree+1));
234       KnotsMultiplicities.Append(MaxDegree+1);
235     }
236     P1 = Points(MaxDegree);
237   }
238
239   // Correct nodal values to make them variable within [0.,1.].
240   CurveKnots.Append(0.0);
241 //  cout << "Convert : Det = " << Det << endl;
242   for (i = 2 ; i <= NbrCurv ; i++) {
243     CurveKnots.Append(CurveKnots(i-1) + (CurveKnVals(i-1)/Det));
244   }
245   CurveKnots.Append(1.0);
246 }
247
248