0030675: Visualization - remove redundant proxy classes in hierarchy of PrsMgr_Presen...
[occt.git] / src / Geom2dConvert / Geom2dConvert_CompCurveToBSplineCurve.cxx
1 // Created on: 1997-04-29
2 // Created by: Stagiaire Francois DUMONT
3 // Copyright (c) 1997-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 <Geom2d_BoundedCurve.hxx>
19 #include <Geom2d_BSplineCurve.hxx>
20 #include <Geom2dConvert.hxx>
21 #include <Geom2dConvert_CompCurveToBSplineCurve.hxx>
22 #include <gp_Pnt2d.hxx>
23 #include <gp_Vec2d.hxx>
24 #include <Precision.hxx>
25 #include <TColgp_Array1OfPnt2d.hxx>
26 #include <TColStd_Array1OfInteger.hxx>
27 #include <TColStd_Array1OfReal.hxx>
28
29 //=======================================================================
30 //function : constructor
31 //purpose  :
32 //=======================================================================
33 Geom2dConvert_CompCurveToBSplineCurve::Geom2dConvert_CompCurveToBSplineCurve (const Convert_ParameterisationType theParameterisation)
34 : myTol  (Precision::Confusion()),
35   myType (theParameterisation)
36 {
37   //
38 }
39
40 //=======================================================================
41 //function : constructor
42 //purpose  :
43 //=======================================================================
44 Geom2dConvert_CompCurveToBSplineCurve::
45 Geom2dConvert_CompCurveToBSplineCurve(const Handle(Geom2d_BoundedCurve)& BasisCurve, 
46                                       const Convert_ParameterisationType Parameterisation) :
47                                       myTol(Precision::Confusion()),
48                                       myType(Parameterisation)
49 {
50   Handle(Geom2d_BSplineCurve) Bs = 
51       Handle(Geom2d_BSplineCurve)::DownCast(BasisCurve);
52   if (!Bs.IsNull()) { 
53     myCurve =  Handle(Geom2d_BSplineCurve)::DownCast(BasisCurve->Copy()); 
54   }
55   else {
56     myCurve = Geom2dConvert::CurveToBSplineCurve (BasisCurve, myType);
57   }
58 }
59
60 //=======================================================================
61 //function : Add
62 //purpose  :
63 //=======================================================================
64
65 Standard_Boolean Geom2dConvert_CompCurveToBSplineCurve::
66 Add(const Handle(Geom2d_BoundedCurve)& NewCurve,
67     const Standard_Real Tolerance,
68     const Standard_Boolean After)
69 {
70   // conversion
71   Handle(Geom2d_BSplineCurve) Bs = Handle(Geom2d_BSplineCurve)::DownCast (NewCurve);
72   if (!Bs.IsNull())
73   {
74     Bs = Handle(Geom2d_BSplineCurve)::DownCast (NewCurve->Copy());
75   }
76   else
77   {
78     Bs = Geom2dConvert::CurveToBSplineCurve (NewCurve, myType);
79   }
80   if (myCurve.IsNull())
81   {
82     myCurve = Bs;
83     return Standard_True;
84   }
85
86   myTol = Tolerance;
87
88   Standard_Integer LBs = Bs->NbPoles(), LCb = myCurve->NbPoles();
89   
90   // myCurve est elle fermee ?
91   if (myCurve->Pole(LCb).Distance(myCurve->Pole(1)) < myTol){
92     if(After){
93       // Ajout Apres ?
94       Standard_Real d1 = myCurve->Pole(LCb).Distance(Bs->Pole(1));
95       Standard_Real d2 = myCurve->Pole(LCb).Distance(Bs->Pole(LBs));
96       if (d2 < d1) {
97         Bs->Reverse();
98         d1 = d2;
99       }
100       if (d1 < myTol) {
101         Add(myCurve, Bs, Standard_True);
102         return Standard_True;
103       }
104     }
105     else{
106       // Ajout avant ?  
107       Standard_Real d1 = myCurve->Pole(1).Distance(Bs->Pole(1));
108       Standard_Real d2 = myCurve->Pole(1).Distance(Bs->Pole(LBs));
109       if (d1 < d2) {
110         Bs->Reverse();
111         d2 = d1;
112       }
113       if (d2 < myTol) {
114         Add(Bs, myCurve, Standard_False);
115         return Standard_True;
116       }
117     }
118   }
119   // Ajout Apres ?
120   else {
121
122     Standard_Real d1 = myCurve->Pole(LCb).Distance(Bs->Pole(1));
123     Standard_Real d2 = myCurve->Pole(LCb).Distance(Bs->Pole(LBs));
124     if (( d1  < myTol) || ( d2 < myTol)) {
125       if (d2 < d1) {Bs->Reverse();}
126       Add(myCurve, Bs, Standard_True);
127       return Standard_True;
128     }
129   // Ajout avant ?  
130     else { 
131       d1 = myCurve->Pole(1).Distance(Bs->Pole(1));
132       d2 = myCurve->Pole(1).Distance(Bs->Pole(LBs));
133       if ( (d1 < myTol) || (d2 < myTol)) {
134         if (d1 < d2) {Bs->Reverse();}
135         Add(Bs, myCurve, Standard_False );
136         return Standard_True;
137       }
138     }
139   }  
140   return Standard_False;
141 }
142
143 //=======================================================================
144 //function : Add
145 //purpose  :
146 //=======================================================================
147
148 void Geom2dConvert_CompCurveToBSplineCurve::Add( 
149       Handle(Geom2d_BSplineCurve)& FirstCurve, 
150       Handle(Geom2d_BSplineCurve)& SecondCurve,
151       const Standard_Boolean After)
152 {
153 // Harmonisation des degres.
154   Standard_Integer Deg = Max(FirstCurve->Degree(), SecondCurve->Degree());
155   if (FirstCurve->Degree() < Deg) { FirstCurve->IncreaseDegree(Deg); }
156   if (SecondCurve->Degree() < Deg)  { SecondCurve->IncreaseDegree(Deg); }
157
158 // Declarationd
159   Standard_Real L1, L2, U_de_raccord;
160   Standard_Integer ii, jj;
161   Standard_Real  Ratio=1, Ratio1, Ratio2, Delta1, Delta2;
162   Standard_Integer NbP1 = FirstCurve->NbPoles(), NbP2 = SecondCurve->NbPoles();
163   Standard_Integer NbK1 = FirstCurve->NbKnots(), NbK2 = SecondCurve->NbKnots();
164   TColStd_Array1OfReal Noeuds (1, NbK1+NbK2-1);
165   TColgp_Array1OfPnt2d Poles (1, NbP1+ NbP2-1);
166   TColStd_Array1OfReal Poids  (1, NbP1+ NbP2-1);
167   TColStd_Array1OfInteger Mults (1, NbK1+NbK2-1);
168
169   // Ratio de reparametrisation (C1 si possible)
170   L1 = FirstCurve->DN(FirstCurve->LastParameter(), 1).Magnitude();
171   L2 = SecondCurve->DN(SecondCurve->FirstParameter(), 1). Magnitude();
172
173   if ( (L1 > Precision::Confusion()) && (L2 > Precision::Confusion()) ) {
174     Ratio = L1 / L2;
175   }
176   if ( (Ratio < Precision::Confusion()) || (Ratio > 1/Precision::Confusion()) ) {Ratio = 1;}
177
178   if (After) {
179 // On ne bouge pas la premiere courbe
180     Ratio1 = 1;
181     Delta1 = 0;
182     Ratio2 = 1/Ratio;
183     Delta2 = Ratio2*SecondCurve->Knot(1) - FirstCurve->Knot(NbK1);
184     U_de_raccord = FirstCurve->LastParameter();
185   }
186   else {
187 // On ne bouge pas la seconde courbe
188     Ratio1 = Ratio;
189     Delta1 = Ratio1*FirstCurve->Knot(NbK1) - SecondCurve->Knot(1);
190     Ratio2 = 1;
191     Delta2 = 0;
192     U_de_raccord = SecondCurve->FirstParameter();
193   }    
194
195 // Les Noeuds
196
197   for (ii=1; ii<NbK1; ii++) {
198     Noeuds(ii) = Ratio1*FirstCurve->Knot(ii) - Delta1;
199     Mults(ii) = FirstCurve->Multiplicity(ii);
200   }
201   Noeuds(NbK1) = U_de_raccord;
202   Mults(NbK1) = FirstCurve->Degree();
203   for (ii=2, jj=NbK1+1; ii<=NbK2; ii++, jj++) {
204     Noeuds(jj) = Ratio2*SecondCurve->Knot(ii) - Delta2;
205     Mults(jj) = SecondCurve->Multiplicity(ii);
206   } 
207  Ratio = FirstCurve->Weight(NbP1) ;
208  Ratio /=  SecondCurve->Weight(1) ;
209 // Les Poles et Poids
210   for (ii=1;  ii<NbP1; ii++) {
211      Poles(ii) =  FirstCurve->Pole(ii);
212      Poids(ii) =  FirstCurve->Weight(ii);
213    }
214   for (ii=1, jj=NbP1;  ii<=NbP2; ii++, jj++) {
215      Poles(jj) =   SecondCurve->Pole(ii);
216 //
217 // attentiion les poids ne se raccord pas forcement C0
218 // d'ou Ratio
219 //
220      Poids(jj) =   Ratio * SecondCurve->Weight(ii);
221    }
222   
223 // Creation de la BSpline
224   myCurve = new (Geom2d_BSplineCurve) (Poles, Poids, Noeuds, Mults, Deg);
225
226 // Reduction eventuelle de la multiplicite
227   Standard_Boolean Ok = Standard_True;
228   Standard_Integer M = Mults(NbK1);
229   while ( (M>0) && Ok) {
230     M--;
231     Ok = myCurve->RemoveKnot(NbK1, M, myTol);
232   }
233 }
234
235 //=======================================================================
236 //function : BSplineCurve
237 //purpose  :
238 //=======================================================================
239
240 Handle(Geom2d_BSplineCurve) Geom2dConvert_CompCurveToBSplineCurve::BSplineCurve() const 
241 {
242   return myCurve;
243 }
244
245 //=======================================================================
246 //function : Clear
247 //purpose  :
248 //=======================================================================
249
250 void Geom2dConvert_CompCurveToBSplineCurve::Clear()
251 {
252   myCurve.Nullify();
253 }