b311480e |
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 | |
7fd59977 |
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 | |
b514beda |
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 | } |
7fd59977 |
48 | |
b514beda |
49 | //======================================================================= |
50 | //function : constructor |
51 | //purpose : |
52 | //======================================================================= |
7fd59977 |
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 |
b514beda |
71 | //purpose : |
7fd59977 |
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 | { |
b514beda |
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()); |
7fd59977 |
86 | } |
b514beda |
87 | else |
88 | { |
7fd59977 |
89 | Bs = GeomConvert::CurveToBSplineCurve (NewCurve, myType); |
90 | } |
b514beda |
91 | if (myCurve.IsNull()) |
92 | { |
93 | myCurve = Bs; |
94 | return Standard_True; |
95 | } |
96 | |
97 | Standard_Boolean avant, apres; |
98 | myTol = Tolerance; |
7fd59977 |
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 | |
b514beda |
239 | //======================================================================= |
240 | //function : BSplineCurve |
241 | //purpose : |
242 | //======================================================================= |
7fd59977 |
243 | |
244 | Handle(Geom_BSplineCurve) GeomConvert_CompCurveToBSplineCurve::BSplineCurve() const |
245 | { |
246 | return myCurve; |
247 | } |