0024166: Unable to create file with "Save" menu of voxeldemo Qt sample
[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-2012 OPEN CASCADE SAS
5 //
6 // The content of this file is subject to the Open CASCADE Technology Public
7 // License Version 6.5 (the "License"). You may not use the content of this file
8 // except in compliance with the License. Please obtain a copy of the License
9 // at http://www.opencascade.org and read it completely before using this file.
10 //
11 // The Initial Developer of the Original Code is Open CASCADE S.A.S., having its
12 // main offices at: 1, place des Freres Montgolfier, 78280 Guyancourt, France.
13 //
14 // The Original Code and all software distributed under the License is
15 // distributed on an "AS IS" basis, without warranty of any kind, and the
16 // Initial Developer hereby disclaims all such warranties, including without
17 // limitation, any warranties of merchantability, fitness for a particular
18 // purpose or non-infringement. Please see the License for the specific terms
19 // and conditions governing the rights and limitations under the License.
20
21 #include <Geom2dConvert_CompCurveToBSplineCurve.ixx>
22
23 #include <Geom2d_BSplineCurve.hxx>
24 #include <Geom2dConvert.hxx>
25
26 #include <TColStd_Array1OfReal.hxx>
27 #include <TColStd_Array1OfInteger.hxx>
28
29 #include <TColgp_Array1OfPnt2d.hxx>
30 #include <gp_Vec2d.hxx>
31 #include <gp_Pnt2d.hxx>
32 #include <Precision.hxx>
33
34 //=======================================================================
35 //function : constructor
36 //purpose  :
37 //=======================================================================
38 Geom2dConvert_CompCurveToBSplineCurve::Geom2dConvert_CompCurveToBSplineCurve (const Convert_ParameterisationType theParameterisation)
39 : myTol  (Precision::Confusion()),
40   myType (theParameterisation)
41 {
42   //
43 }
44
45 //=======================================================================
46 //function : constructor
47 //purpose  :
48 //=======================================================================
49 Geom2dConvert_CompCurveToBSplineCurve::
50 Geom2dConvert_CompCurveToBSplineCurve(const Handle(Geom2d_BoundedCurve)& BasisCurve, 
51                                       const Convert_ParameterisationType Parameterisation) :
52                                       myTol(Precision::Confusion()),
53                                       myType(Parameterisation)
54 {
55   Handle(Geom2d_BSplineCurve) Bs = 
56       Handle(Geom2d_BSplineCurve)::DownCast(BasisCurve);
57   if (!Bs.IsNull()) { 
58     myCurve =  Handle(Geom2d_BSplineCurve)::DownCast(BasisCurve->Copy()); 
59   }
60   else {
61     myCurve = Geom2dConvert::CurveToBSplineCurve (BasisCurve, myType);
62   }
63 }
64
65 //=======================================================================
66 //function : Add
67 //purpose  :
68 //=======================================================================
69
70 Standard_Boolean Geom2dConvert_CompCurveToBSplineCurve::
71 Add(const Handle(Geom2d_BoundedCurve)& NewCurve,
72     const Standard_Real Tolerance,
73     const Standard_Boolean After)
74 {
75   // conversion
76   Handle(Geom2d_BSplineCurve) Bs = Handle(Geom2d_BSplineCurve)::DownCast (NewCurve);
77   if (!Bs.IsNull())
78   {
79     Bs = Handle(Geom2d_BSplineCurve)::DownCast (NewCurve->Copy());
80   }
81   else
82   {
83     Bs = Geom2dConvert::CurveToBSplineCurve (NewCurve, myType);
84   }
85   if (myCurve.IsNull())
86   {
87     myCurve = Bs;
88     return Standard_True;
89   }
90
91   myTol = Tolerance;
92
93   Standard_Integer LBs = Bs->NbPoles(), LCb = myCurve->NbPoles();
94   
95   // myCurve est elle fermee ?
96   if (myCurve->Pole(LCb).Distance(myCurve->Pole(1))< myTol){
97     if(After){
98       // Ajout Apres ?
99       if (myCurve->Pole(LCb).Distance(Bs->Pole(LBs)) < myTol) {Bs->Reverse();}
100       if (myCurve->Pole(LCb).Distance(Bs->Pole(1)) < myTol) {
101         Add(myCurve, Bs, Standard_True);
102         return Standard_True;
103       }
104     }
105     else{
106       // Ajout avant ?  
107       if (myCurve->Pole(1).Distance(Bs->Pole(1)) < myTol) {Bs->Reverse();}
108       if (myCurve->Pole(1).Distance(Bs->Pole(LBs)) < myTol) {
109         Add(Bs, myCurve, Standard_False);
110         return Standard_True;
111       }
112     }
113   }
114   // Ajout Apres ?
115   else {
116
117     Standard_Real d1 = myCurve->Pole(LCb).Distance(Bs->Pole(1));
118     Standard_Real d2 = myCurve->Pole(LCb).Distance(Bs->Pole(LBs));
119     if (( d1  < myTol) || ( d2 < myTol)) {
120       if (d2 < d1) {Bs->Reverse();}
121       Add(myCurve, Bs, Standard_True);
122       return Standard_True;
123     }
124   // Ajout avant ?  
125     else { 
126       d1 = myCurve->Pole(1).Distance(Bs->Pole(1));
127       d2 = myCurve->Pole(1).Distance(Bs->Pole(LBs));
128       if ( (d1 < myTol) || (d2 < myTol)) {
129         if (d1 < d2) {Bs->Reverse();}
130         Add(Bs, myCurve, Standard_False );
131         return Standard_True;
132       }
133     }
134   }  
135   return Standard_False;
136 }
137
138 //=======================================================================
139 //function : Add
140 //purpose  :
141 //=======================================================================
142
143 void Geom2dConvert_CompCurveToBSplineCurve::Add( 
144       Handle(Geom2d_BSplineCurve)& FirstCurve, 
145       Handle(Geom2d_BSplineCurve)& SecondCurve,
146       const Standard_Boolean After)
147 {
148 // Harmonisation des degres.
149   Standard_Integer Deg = Max(FirstCurve->Degree(), SecondCurve->Degree());
150   if (FirstCurve->Degree() < Deg) { FirstCurve->IncreaseDegree(Deg); }
151   if (SecondCurve->Degree() < Deg)  { SecondCurve->IncreaseDegree(Deg); }
152
153 // Declarationd
154   Standard_Real L1, L2, U_de_raccord;
155   Standard_Integer ii, jj;
156   Standard_Real  Ratio=1, Ratio1, Ratio2, Delta1, Delta2;
157   Standard_Integer NbP1 = FirstCurve->NbPoles(), NbP2 = SecondCurve->NbPoles();
158   Standard_Integer NbK1 = FirstCurve->NbKnots(), NbK2 = SecondCurve->NbKnots();
159   TColStd_Array1OfReal Noeuds (1, NbK1+NbK2-1);
160   TColgp_Array1OfPnt2d Poles (1, NbP1+ NbP2-1);
161   TColStd_Array1OfReal Poids  (1, NbP1+ NbP2-1);
162   TColStd_Array1OfInteger Mults (1, NbK1+NbK2-1);
163
164   // Ratio de reparametrisation (C1 si possible)
165   L1 = FirstCurve->DN(FirstCurve->LastParameter(), 1).Magnitude();
166   L2 = SecondCurve->DN(SecondCurve->FirstParameter(), 1). Magnitude();
167
168   if ( (L1 > Precision::Confusion()) && (L2 > Precision::Confusion()) ) {
169     Ratio = L1 / L2;
170   }
171   if ( (Ratio < Precision::Confusion()) || (Ratio > 1/Precision::Confusion()) ) {Ratio = 1;}
172
173   if (After) {
174 // On ne bouge pas la premiere courbe
175     Ratio1 = 1;
176     Delta1 = 0;
177     Ratio2 = 1/Ratio;
178     Delta2 = Ratio2*SecondCurve->Knot(1) - FirstCurve->Knot(NbK1);
179     U_de_raccord = FirstCurve->LastParameter();
180   }
181   else {
182 // On ne bouge pas la seconde courbe
183     Ratio1 = Ratio;
184     Delta1 = Ratio1*FirstCurve->Knot(NbK1) - SecondCurve->Knot(1);
185     Ratio2 = 1;
186     Delta2 = 0;
187     U_de_raccord = SecondCurve->FirstParameter();
188   }    
189
190 // Les Noeuds
191
192   for (ii=1; ii<NbK1; ii++) {
193     Noeuds(ii) = Ratio1*FirstCurve->Knot(ii) - Delta1;
194     Mults(ii) = FirstCurve->Multiplicity(ii);
195   }
196   Noeuds(NbK1) = U_de_raccord;
197   Mults(NbK1) = FirstCurve->Degree();
198   for (ii=2, jj=NbK1+1; ii<=NbK2; ii++, jj++) {
199     Noeuds(jj) = Ratio2*SecondCurve->Knot(ii) - Delta2;
200     Mults(jj) = SecondCurve->Multiplicity(ii);
201   } 
202  Ratio = FirstCurve->Weight(NbP1) ;
203  Ratio /=  SecondCurve->Weight(1) ;
204 // Les Poles et Poids
205   for (ii=1;  ii<NbP1; ii++) {
206      Poles(ii) =  FirstCurve->Pole(ii);
207      Poids(ii) =  FirstCurve->Weight(ii);
208    }
209   for (ii=1, jj=NbP1;  ii<=NbP2; ii++, jj++) {
210      Poles(jj) =   SecondCurve->Pole(ii);
211 //
212 // attentiion les poids ne se raccord pas forcement C0
213 // d'ou Ratio
214 //
215      Poids(jj) =   Ratio * SecondCurve->Weight(ii);
216    }
217   
218 // Creation de la BSpline
219   myCurve = new (Geom2d_BSplineCurve) (Poles, Poids, Noeuds, Mults, Deg);
220
221 // Reduction eventuelle de la multiplicite
222   Standard_Boolean Ok = Standard_True;
223   Standard_Integer M = Mults(NbK1);
224   while ( (M>0) && Ok) {
225     M--;
226     Ok = myCurve->RemoveKnot(NbK1, M, myTol);
227   }
228 }
229
230 //=======================================================================
231 //function : BSplineCurve
232 //purpose  :
233 //=======================================================================
234
235 Handle(Geom2d_BSplineCurve) Geom2dConvert_CompCurveToBSplineCurve::BSplineCurve() const 
236 {
237   return myCurve;
238 }
239
240 //=======================================================================
241 //function : Clear
242 //purpose  :
243 //=======================================================================
244
245 void Geom2dConvert_CompCurveToBSplineCurve::Clear()
246 {
247   myCurve.Nullify();
248 }