0023024: Update headers of OCCT files
[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-2012 OPEN CASCADE SAS
5 //
6 // The content of this file is subject to the Open CASCADE Technology Public
7 // License Version 6.5 (the "License"). You may not use the content of this file
8 // except in compliance with the License. Please obtain a copy of the License
9 // at http://www.opencascade.org and read it completely before using this file.
10 //
11 // The Initial Developer of the Original Code is Open CASCADE S.A.S., having its
12 // main offices at: 1, place des Freres Montgolfier, 78280 Guyancourt, France.
13 //
14 // The Original Code and all software distributed under the License is
15 // distributed on an "AS IS" basis, without warranty of any kind, and the
16 // Initial Developer hereby disclaims all such warranties, including without
17 // limitation, any warranties of merchantability, fitness for a particular
18 // purpose or non-infringement. Please see the License for the specific terms
19 // and conditions governing the rights and limitations under the License.
20
21
22
23 #include <Convert_CompBezierCurvesToBSplineCurve.ixx>
24
25 #include <Precision.hxx>
26 #include <BSplCLib.hxx>
27 #include <PLib.hxx>
28 #include <gp_Pnt.hxx>
29 #include <gp.hxx>
30 #include <gp_Vec.hxx>
31 #include <TColgp_HArray1OfPnt.hxx>
32
33
34 //=======================================================================
35 //function : Convert_CompBezierCurvesToBSplineCurve
36 //purpose  : 
37 //=======================================================================
38
39
40 Convert_CompBezierCurvesToBSplineCurve::
41 Convert_CompBezierCurvesToBSplineCurve(
42                   const Standard_Real AngularTolerance) :
43                   myAngular(AngularTolerance),
44                   myDone(Standard_False)
45 {
46 }
47
48
49 //=======================================================================
50 //function : AddCurve
51 //purpose  : 
52 //=======================================================================
53
54 void  Convert_CompBezierCurvesToBSplineCurve::AddCurve
55   (const TColgp_Array1OfPnt& Poles)
56 {
57   if ( !mySequence.IsEmpty()) {
58     gp_Pnt P1,P2;
59     P1 = mySequence.Last()->Value(mySequence.Last()->Upper());
60     P2 = Poles(Poles.Lower());
61
62     // NYI
63   if ( !P1.IsEqual(P2,Precision::Confusion()))
64       cout << "Convert_CompBezierCurvesToBSplineCurve::Addcurve" << endl;;
65   }
66   myDone = Standard_False;
67   Handle(TColgp_HArray1OfPnt) HPoles = 
68     new TColgp_HArray1OfPnt(Poles.Lower(),Poles.Upper());
69   HPoles->ChangeArray1() = Poles;
70   mySequence.Append(HPoles);
71 }
72
73
74 //=======================================================================
75 //function : Degree
76 //purpose  : 
77 //=======================================================================
78
79 Standard_Integer  Convert_CompBezierCurvesToBSplineCurve::Degree() const
80 {
81   return myDegree;
82 }
83
84
85 //=======================================================================
86 //function : NbPoles
87 //purpose  : 
88 //=======================================================================
89
90 Standard_Integer  Convert_CompBezierCurvesToBSplineCurve::NbPoles() const
91 {
92   return CurvePoles.Length();
93 }
94
95
96 //=======================================================================
97 //function : Poles
98 //purpose  : 
99 //=======================================================================
100
101 void  Convert_CompBezierCurvesToBSplineCurve::Poles
102   (TColgp_Array1OfPnt& Poles) const
103 {
104   Standard_Integer i, Lower = Poles.Lower(), Upper = Poles.Upper();
105   Standard_Integer k = 1;
106   for (i = Lower; i <= Upper; i++) {
107     Poles(i) = CurvePoles(k++);
108   }
109 }
110
111
112 //=======================================================================
113 //function : NbKnots
114 //purpose  : 
115 //=======================================================================
116
117 Standard_Integer  Convert_CompBezierCurvesToBSplineCurve::NbKnots() const
118 {
119   return CurveKnots.Length();
120 }
121
122
123 //=======================================================================
124 //function : KnotsAndMults
125 //purpose  : 
126 //=======================================================================
127
128 void  Convert_CompBezierCurvesToBSplineCurve::KnotsAndMults
129   (TColStd_Array1OfReal&    Knots, 
130    TColStd_Array1OfInteger& Mults ) const
131 {
132   Standard_Integer i, LowerK = Knots.Lower(), UpperK = Knots.Upper();
133   Standard_Integer LowerM = Mults.Lower(), UpperM = Mults.Upper();
134   Standard_Integer k = 1;
135   for (i = LowerK; i <= UpperK; i++) {
136     Knots(i) = CurveKnots(k++);
137   }
138   k = 1;
139   for (i = LowerM; i <= UpperM; i++) {
140     Mults(i) = KnotsMultiplicities(k++);
141   }
142 }
143
144
145
146 //=======================================================================
147 //function : Perform
148 //purpose  : 
149 //=======================================================================
150
151 void Convert_CompBezierCurvesToBSplineCurve::Perform() 
152 {
153   myDone = Standard_True;
154   CurvePoles.Clear();
155   CurveKnots.Clear();
156   KnotsMultiplicities.Clear();
157   Standard_Integer LowerI     = 1;
158   Standard_Integer UpperI     = mySequence.Length();
159   Standard_Integer NbrCurv    = UpperI-LowerI+1;
160 //  Standard_Integer NbKnotsSpl = NbrCurv + 1 ;
161   TColStd_Array1OfReal     CurveKnVals         (1,NbrCurv);
162
163   Standard_Integer i;
164   myDegree = 0;
165   for ( i = 1; i <= mySequence.Length(); i++) {
166     myDegree = Max( myDegree, (mySequence(i))->Length() -1);
167   }
168
169   Standard_Real D1, D2, Lambda, Det=0;
170   gp_Pnt P1, P2, P3;
171   Standard_Integer Deg, Inc, MaxDegree = myDegree;
172   TColgp_Array1OfPnt Points(1, myDegree+1);
173
174   for (i = LowerI ; i <= UpperI ; i++) {
175     // 1- Raise the Bezier curve to the maximum degree.
176     Deg = mySequence(i)->Length()-1;
177     Inc = myDegree - Deg;
178     if ( Inc > 0) {
179       BSplCLib::IncreaseDegree(myDegree, 
180                                mySequence(i)->Array1(), PLib::NoWeights(), 
181                                Points, PLib::NoWeights());
182     }
183     else {
184       Points = mySequence(i)->Array1();
185     }
186
187     // 2- Process the node of junction between 2 Bezier curves.
188     if (i == LowerI) {
189       // Processing of the initial node of the BSpline.
190       for (Standard_Integer j = 1 ; j <= MaxDegree ; j++) {
191         CurvePoles.Append(Points(j));
192       }
193       CurveKnVals(1)         = 1.; // To begin the series.
194       KnotsMultiplicities.Append(MaxDegree+1);
195       Det = 1.;
196     }
197
198
199     if (i != LowerI) {
200       P2 = Points(1);
201       P3 = Points(2);
202       gp_Vec V1(P1, P2), V2(P2, P3);
203       D1 = P1.SquareDistance(P2);
204       D2 = P3.SquareDistance(P2);
205       Lambda = Sqrt(D2/D1);
206 //      cout << "D1, D2, Lambda : " << D1 << " " <<  D2 << " " << Lambda << endl;
207
208       // Processing of the tangency between Bezier and the previous.
209       // This allows to guarantee at least a C1 continuity if the tangents are  
210       // coherent.
211       
212       if (V1.Magnitude() > gp::Resolution() &&
213           V2.Magnitude() > gp::Resolution() &&
214           V1.IsParallel(V2, myAngular )) {
215         if(CurveKnVals(i-1) * Lambda > 10. * Epsilon(Det)) {
216           KnotsMultiplicities.Append(MaxDegree-1);
217           CurveKnVals(i) = CurveKnVals(i-1) * Lambda;
218           Det += CurveKnVals(i);
219         }
220         else {
221           CurvePoles.Append(Points(1));
222           KnotsMultiplicities.Append(MaxDegree);
223           CurveKnVals(i) = 1.0 ;
224           Det += CurveKnVals(i) ;
225         }
226       }
227       else {
228         CurvePoles.Append(Points(1));
229         KnotsMultiplicities.Append(MaxDegree);
230         CurveKnVals(i) = 1.0 ;
231         Det += CurveKnVals(i) ;
232       }
233
234       // Store the poles.
235       for (Standard_Integer j = 2 ; j <= MaxDegree ; j++) {
236         CurvePoles.Append(Points(j));
237       }
238
239     }
240
241
242     if (i == UpperI) {
243       // Processing of the end node of the BSpline.
244       CurvePoles.Append(Points(MaxDegree+1));
245       KnotsMultiplicities.Append(MaxDegree+1);
246     }
247     P1 = Points(MaxDegree);
248   }
249
250   // Correct nodal values to make them variable within [0.,1.].
251   CurveKnots.Append(0.0);
252 //  cout << "Convert : Det = " << Det << endl;
253   for (i = 2 ; i <= NbrCurv ; i++) {
254     CurveKnots.Append(CurveKnots(i-1) + (CurveKnVals(i-1)/Det));
255   }
256   CurveKnots.Append(1.0);
257 }
258
259