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