Integration of OCCT 6.5.0 from SVN
[occt.git] / src / Convert / Convert_CompBezierCurvesToBSplineCurve.cxx
1 // File:        Convert_CompBezierCurvesToBSplineCurve.cxx
2 // Created:     Wed Oct 20 14:55:08 1993
3 // Author:      Bruno DUMORTIER
4 //              <dub@topsn3>
5 // modified 25/06/1996 PMN : Ajout d'une tolerance Angulaire dans le 
6 //  constructeur pour le test de continuite G1 (1 Radians c'etait trop
7 //  cf BUG PRO4481) 
8
9 #include <Convert_CompBezierCurvesToBSplineCurve.ixx>
10
11 #include <Precision.hxx>
12 #include <BSplCLib.hxx>
13 #include <PLib.hxx>
14 #include <gp_Pnt.hxx>
15 #include <gp.hxx>
16 #include <gp_Vec.hxx>
17 #include <TColgp_HArray1OfPnt.hxx>
18
19
20 //=======================================================================
21 //function : Convert_CompBezierCurvesToBSplineCurve
22 //purpose  : 
23 //=======================================================================
24
25
26 Convert_CompBezierCurvesToBSplineCurve::
27 Convert_CompBezierCurvesToBSplineCurve(
28                   const Standard_Real AngularTolerance) :
29                   myAngular(AngularTolerance),
30                   myDone(Standard_False)
31 {
32 }
33
34
35 //=======================================================================
36 //function : AddCurve
37 //purpose  : 
38 //=======================================================================
39
40 void  Convert_CompBezierCurvesToBSplineCurve::AddCurve
41   (const TColgp_Array1OfPnt& Poles)
42 {
43   if ( !mySequence.IsEmpty()) {
44     gp_Pnt P1,P2;
45     P1 = mySequence.Last()->Value(mySequence.Last()->Upper());
46     P2 = Poles(Poles.Lower());
47
48     // NYI
49   if ( !P1.IsEqual(P2,Precision::Confusion()))
50       cout << "Convert_CompBezierCurvesToBSplineCurve::Addcurve" << endl;;
51   }
52   myDone = Standard_False;
53   Handle(TColgp_HArray1OfPnt) HPoles = 
54     new TColgp_HArray1OfPnt(Poles.Lower(),Poles.Upper());
55   HPoles->ChangeArray1() = Poles;
56   mySequence.Append(HPoles);
57 }
58
59
60 //=======================================================================
61 //function : Degree
62 //purpose  : 
63 //=======================================================================
64
65 Standard_Integer  Convert_CompBezierCurvesToBSplineCurve::Degree() const
66 {
67   return myDegree;
68 }
69
70
71 //=======================================================================
72 //function : NbPoles
73 //purpose  : 
74 //=======================================================================
75
76 Standard_Integer  Convert_CompBezierCurvesToBSplineCurve::NbPoles() const
77 {
78   return CurvePoles.Length();
79 }
80
81
82 //=======================================================================
83 //function : Poles
84 //purpose  : 
85 //=======================================================================
86
87 void  Convert_CompBezierCurvesToBSplineCurve::Poles
88   (TColgp_Array1OfPnt& Poles) const
89 {
90   Standard_Integer i, Lower = Poles.Lower(), Upper = Poles.Upper();
91   Standard_Integer k = 1;
92   for (i = Lower; i <= Upper; i++) {
93     Poles(i) = CurvePoles(k++);
94   }
95 }
96
97
98 //=======================================================================
99 //function : NbKnots
100 //purpose  : 
101 //=======================================================================
102
103 Standard_Integer  Convert_CompBezierCurvesToBSplineCurve::NbKnots() const
104 {
105   return CurveKnots.Length();
106 }
107
108
109 //=======================================================================
110 //function : KnotsAndMults
111 //purpose  : 
112 //=======================================================================
113
114 void  Convert_CompBezierCurvesToBSplineCurve::KnotsAndMults
115   (TColStd_Array1OfReal&    Knots, 
116    TColStd_Array1OfInteger& Mults ) const
117 {
118   Standard_Integer i, LowerK = Knots.Lower(), UpperK = Knots.Upper();
119   Standard_Integer LowerM = Mults.Lower(), UpperM = Mults.Upper();
120   Standard_Integer k = 1;
121   for (i = LowerK; i <= UpperK; i++) {
122     Knots(i) = CurveKnots(k++);
123   }
124   k = 1;
125   for (i = LowerM; i <= UpperM; i++) {
126     Mults(i) = KnotsMultiplicities(k++);
127   }
128 }
129
130
131
132 //=======================================================================
133 //function : Perform
134 //purpose  : 
135 //=======================================================================
136
137 void Convert_CompBezierCurvesToBSplineCurve::Perform() 
138 {
139   myDone = Standard_True;
140   CurvePoles.Clear();
141   CurveKnots.Clear();
142   KnotsMultiplicities.Clear();
143   Standard_Integer LowerI     = 1;
144   Standard_Integer UpperI     = mySequence.Length();
145   Standard_Integer NbrCurv    = UpperI-LowerI+1;
146 //  Standard_Integer NbKnotsSpl = NbrCurv + 1 ;
147   TColStd_Array1OfReal     CurveKnVals         (1,NbrCurv);
148
149   Standard_Integer i;
150   myDegree = 0;
151   for ( i = 1; i <= mySequence.Length(); i++) {
152     myDegree = Max( myDegree, (mySequence(i))->Length() -1);
153   }
154
155   Standard_Real D1, D2, Lambda, Det=0;
156   gp_Pnt P1, P2, P3;
157   Standard_Integer Deg, Inc, MaxDegree = myDegree;
158   TColgp_Array1OfPnt Points(1, myDegree+1);
159
160   for (i = LowerI ; i <= UpperI ; i++) {
161     // 1- Elever la courbe de Bezier au degre maximum.
162     Deg = mySequence(i)->Length()-1;
163     Inc = myDegree - Deg;
164     if ( Inc > 0) {
165       BSplCLib::IncreaseDegree(myDegree, 
166                                mySequence(i)->Array1(), PLib::NoWeights(), 
167                                Points, PLib::NoWeights());
168     }
169     else {
170       Points = mySequence(i)->Array1();
171     }
172
173     // 2- Traiter le noeud de jonction entre 2 courbes de Bezier.
174     if (i == LowerI) {
175       // Traitement du noeud initial de la BSpline.
176       for (Standard_Integer j = 1 ; j <= MaxDegree ; j++) {
177         CurvePoles.Append(Points(j));
178       }
179       CurveKnVals(1)         = 1.; // Pour amorcer la serie.
180       KnotsMultiplicities.Append(MaxDegree+1);
181       Det = 1.;
182     }
183
184
185     if (i != LowerI) {
186       P2 = Points(1);
187       P3 = Points(2);
188       gp_Vec V1(P1, P2), V2(P2, P3);
189       D1 = P1.SquareDistance(P2);
190       D2 = P3.SquareDistance(P2);
191       Lambda = Sqrt(D2/D1);
192 //      cout << "D1, D2, Lambda : " << D1 << " " <<  D2 << " " << Lambda << endl;
193
194       // Traitement de la tangence entre la Bezier et sa precedente.
195       // Ceci permet d''assurer au moins une continuite C1 si 
196       // les tangentes sont coherentes.
197       
198       if (V1.Magnitude() > gp::Resolution() &&
199           V2.Magnitude() > gp::Resolution() &&
200           V1.IsParallel(V2, myAngular )) {
201         if(CurveKnVals(i-1) * Lambda > 10. * Epsilon(Det)) {
202           KnotsMultiplicities.Append(MaxDegree-1);
203           CurveKnVals(i) = CurveKnVals(i-1) * Lambda;
204           Det += CurveKnVals(i);
205         }
206         else {
207           CurvePoles.Append(Points(1));
208           KnotsMultiplicities.Append(MaxDegree);
209           CurveKnVals(i) = 1.0 ;
210           Det += CurveKnVals(i) ;
211         }
212       }
213       else {
214         CurvePoles.Append(Points(1));
215         KnotsMultiplicities.Append(MaxDegree);
216         CurveKnVals(i) = 1.0 ;
217         Det += CurveKnVals(i) ;
218       }
219
220       // Stocker les poles.
221       for (Standard_Integer j = 2 ; j <= MaxDegree ; j++) {
222         CurvePoles.Append(Points(j));
223       }
224
225     }
226
227
228     if (i == UpperI) {
229       // Traitement du noeud terminal de la BSpline.
230       CurvePoles.Append(Points(MaxDegree+1));
231       KnotsMultiplicities.Append(MaxDegree+1);
232     }
233     P1 = Points(MaxDegree);
234   }
235
236   // Corriger les valeurs nodales pour les faire varier dans [0.,1.].
237   CurveKnots.Append(0.0);
238 //  cout << "Convert : Det = " << Det << endl;
239   for (i = 2 ; i <= NbrCurv ; i++) {
240     CurveKnots.Append(CurveKnots(i-1) + (CurveKnVals(i-1)/Det));
241   }
242   CurveKnots.Append(1.0);
243 }
244
245