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