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