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