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