b311480e |
1 | // Created on: 1994-02-17 |
2 | // Created by: Bruno DUMORTIER |
3 | // Copyright (c) 1994-1999 Matra Datavision |
973c2be1 |
4 | // Copyright (c) 1999-2014 OPEN CASCADE SAS |
b311480e |
5 | // |
973c2be1 |
6 | // This file is part of Open CASCADE Technology software library. |
b311480e |
7 | // |
d5f74e42 |
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 |
973c2be1 |
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. |
b311480e |
13 | // |
973c2be1 |
14 | // Alternatively, this file may be used under the terms of Open CASCADE |
15 | // commercial license or contractual agreement. |
7fd59977 |
16 | |
17 | #include <GeomFill_Profiler.ixx> |
18 | #include <GeomConvert.hxx> |
19 | #include <BSplCLib.hxx> |
20 | #include <Geom_BSplineCurve.hxx> |
21 | #include <Geom_TrimmedCurve.hxx> |
22 | #include <Geom_Conic.hxx> |
23 | #include <GeomConvert_ApproxCurve.hxx> |
24 | |
93442c6f |
25 | //======================================================================= |
26 | //function : UnifyByInsertingAllKnots |
27 | //purpose : |
28 | //======================================================================= |
29 | void UnifyByInsertingAllKnots(TColGeom_SequenceOfCurve& theCurves, |
30 | const Standard_Real PTol) |
31 | { |
32 | // inserting in the first curve the knot-vector of all the others. |
33 | Handle(Geom_BSplineCurve) C = Handle(Geom_BSplineCurve)::DownCast(theCurves(1)); |
34 | |
35 | Standard_Integer i; |
36 | for ( i = 2; i <= theCurves.Length(); i++) { |
37 | Handle(Geom_BSplineCurve) Ci = |
38 | Handle(Geom_BSplineCurve)::DownCast(theCurves(i)); |
39 | TColStd_Array1OfReal Ki(1,Ci->NbKnots()); |
40 | Ci->Knots(Ki); |
41 | TColStd_Array1OfInteger Mi(1,Ci->NbKnots()); |
42 | Ci->Multiplicities(Mi); |
43 | |
44 | C->InsertKnots( Ki, Mi, PTol, Standard_False); |
45 | } |
46 | |
47 | TColStd_Array1OfReal NewKnots(1,C->NbKnots()); |
48 | C->Knots(NewKnots); |
49 | TColStd_Array1OfInteger NewMults(1,C->NbKnots()); |
50 | C->Multiplicities(NewMults); |
51 | for ( i = 2; i <= theCurves.Length(); i++) { |
52 | Handle(Geom_BSplineCurve) Ci = |
53 | Handle(Geom_BSplineCurve)::DownCast(theCurves(i)); |
54 | Ci->InsertKnots(NewKnots, NewMults, PTol, Standard_False); |
55 | } |
56 | |
57 | // essai : tentative mise des poids sur chaque section a une moyenne 1 |
58 | for ( i = 1; i <= theCurves.Length(); i++) { |
59 | Handle(Geom_BSplineCurve) Ci = |
60 | Handle(Geom_BSplineCurve)::DownCast(theCurves(i)); |
61 | if ( Ci->IsRational() ) { |
62 | Standard_Integer np = Ci->NbPoles(); |
63 | Standard_Real sigma = 0.; |
64 | Standard_Integer j; |
65 | for ( j = 1; j <= np; j++) { |
66 | sigma += Ci->Weight(j); |
67 | } |
68 | sigma /= np; |
69 | for ( j= 1; j<= np; j++) { |
70 | Ci->SetWeight(j,Ci->Weight(j) / sigma); |
71 | } |
72 | } |
73 | } |
74 | // fin de l essai |
75 | } |
76 | |
77 | //======================================================================= |
78 | //function : UnifyBySettingMiddleKnots |
79 | //purpose : |
80 | //======================================================================= |
81 | void UnifyBySettingMiddleKnots(TColGeom_SequenceOfCurve& theCurves) |
82 | { |
83 | Standard_Integer i, j; |
84 | |
85 | Handle(Geom_BSplineCurve) C = Handle(Geom_BSplineCurve)::DownCast(theCurves(1)); |
86 | |
87 | Standard_Integer NbKnots = C->NbKnots(); |
88 | Standard_Real ULast = C->Knot(C->LastUKnotIndex()); |
89 | Standard_Real UFirst = C->Knot(C->FirstUKnotIndex()); |
90 | |
91 | //Set middle values of knots |
92 | TColStd_Array1OfReal NewKnots(1, NbKnots); |
93 | NewKnots(1) = UFirst; |
94 | NewKnots(NbKnots) = ULast; |
95 | for (j = 2; j < NbKnots; j++) |
96 | { |
97 | Standard_Real aMidKnot = 0.; |
98 | for (i = 1; i <= theCurves.Length(); i++) |
99 | { |
100 | Handle(Geom_BSplineCurve) C = Handle(Geom_BSplineCurve)::DownCast(theCurves(i)); |
101 | aMidKnot += C->Knot(j); |
102 | } |
103 | aMidKnot /= theCurves.Length(); |
104 | NewKnots(j) = aMidKnot; |
105 | } |
106 | |
107 | for (i = 1; i <= theCurves.Length(); i++) |
108 | { |
109 | Handle(Geom_BSplineCurve) C = Handle(Geom_BSplineCurve)::DownCast(theCurves(i)); |
110 | C->SetKnots(NewKnots); |
111 | } |
112 | } |
7fd59977 |
113 | |
114 | //======================================================================= |
115 | //function : GeomFill_Profiler |
116 | //purpose : |
117 | //======================================================================= |
118 | |
119 | GeomFill_Profiler::GeomFill_Profiler() |
120 | { |
121 | myIsDone = Standard_False; |
122 | myIsPeriodic = Standard_True; |
123 | } |
124 | |
125 | |
126 | //======================================================================= |
127 | |
128 | void GeomFill_Profiler::Delete() |
129 | {} |
130 | |
131 | |
132 | //======================================================================= |
133 | //function : AddCurve |
134 | //purpose : |
135 | //======================================================================= |
136 | |
137 | void GeomFill_Profiler::AddCurve(const Handle(Geom_Curve)& Curve) |
138 | { |
139 | Handle(Geom_Curve) C; |
140 | //// modified by jgv, 19.01.05 for OCC7354 //// |
141 | Handle(Geom_Curve) theCurve = Curve; |
142 | if (theCurve->IsInstance(STANDARD_TYPE(Geom_TrimmedCurve))) |
143 | theCurve = (*((Handle(Geom_TrimmedCurve)*)&theCurve))->BasisCurve(); |
144 | if (theCurve->IsKind(STANDARD_TYPE(Geom_Conic))) |
145 | { |
146 | GeomConvert_ApproxCurve appr(Curve, Precision::Confusion(), GeomAbs_C1, 16, 14); |
147 | if (appr.HasResult()) |
148 | C = appr.Curve(); |
149 | } |
150 | if (C.IsNull()) |
151 | C = GeomConvert::CurveToBSplineCurve(Curve); |
152 | /* |
153 | if ( Curve->IsKind(STANDARD_TYPE(Geom_BSplineCurve))) { |
154 | C = Handle(Geom_Curve)::DownCast(Curve->Copy()); |
155 | } |
156 | else { |
157 | C = GeomConvert::CurveToBSplineCurve(Curve,Convert_QuasiAngular); |
158 | } |
159 | */ |
160 | /////////////////////////////////////////////// |
161 | |
162 | mySequence.Append( C); |
163 | |
164 | if ( myIsPeriodic && !C->IsPeriodic()) |
165 | myIsPeriodic = Standard_False; |
166 | } |
167 | |
168 | |
169 | //======================================================================= |
170 | //function : Perform |
171 | //purpose : |
172 | //======================================================================= |
173 | |
174 | void GeomFill_Profiler::Perform(const Standard_Real PTol) |
175 | { |
176 | Standard_Integer i; |
177 | // Standard_Integer myDegree = 0, myNbPoles = 0; |
178 | Standard_Integer myDegree = 0; |
179 | Handle(Geom_BSplineCurve) C; |
180 | Standard_Real U1, U2, UFirst=0, ULast=0; |
181 | Standard_Real EcartMax = 0.; |
182 | |
183 | for ( i = 1; i <= mySequence.Length(); i++) { |
184 | C = Handle(Geom_BSplineCurve)::DownCast(mySequence(i)); |
185 | |
186 | // si non periodique, il faut deperiodiser toutes les courbes |
187 | // on les segmente ensuite pour assurer K(1) et K(n) de multiplicite |
188 | // degre + 1 |
189 | |
190 | U2 = C->Knot(C->LastUKnotIndex()); |
191 | U1 = C->Knot(C->FirstUKnotIndex()); |
192 | |
193 | if ( !myIsPeriodic && C->IsPeriodic()) { |
194 | C->SetNotPeriodic(); |
195 | C->Segment( U1, U2); |
196 | } |
197 | |
198 | // evaluate the max degree |
199 | myDegree = Max( myDegree, C->Degree()); |
200 | |
201 | // Calcul de Max ( Ufin - Udeb) sur l ensemble des courbes. |
202 | if ( ( U2 - U1) > EcartMax) { |
203 | EcartMax = U2 - U1; |
204 | UFirst = U1; |
205 | ULast = U2; |
206 | } |
207 | } |
208 | |
209 | // increase the degree of the curves to my degree |
210 | // reparametrize them in the range U1, U2. |
211 | for ( i = 1; i <= mySequence.Length(); i++) { |
212 | C = Handle(Geom_BSplineCurve)::DownCast(mySequence(i)); |
213 | |
214 | C->IncreaseDegree( myDegree); |
215 | |
216 | TColStd_Array1OfReal Knots(1,C->NbKnots()); |
217 | C->Knots(Knots); |
218 | BSplCLib::Reparametrize(UFirst,ULast,Knots); |
219 | C->SetKnots(Knots); |
220 | } |
7fd59977 |
221 | |
93442c6f |
222 | TColGeom_SequenceOfCurve theCurves; |
223 | for (i = 1; i <= mySequence.Length(); i++) |
224 | theCurves.Append(Handle(Geom_Curve)::DownCast(mySequence(i)->Copy())); |
7fd59977 |
225 | |
93442c6f |
226 | UnifyByInsertingAllKnots(theCurves, PTol); |
7fd59977 |
227 | |
93442c6f |
228 | Standard_Boolean Unified = Standard_True; |
229 | Standard_Integer theNbKnots = (Handle(Geom_BSplineCurve)::DownCast(theCurves(1)))->NbKnots(); |
230 | for (i = 2; i <= theCurves.Length(); i++) |
231 | if ((Handle(Geom_BSplineCurve)::DownCast(theCurves(i)))->NbKnots() != theNbKnots) |
232 | { |
233 | Unified = Standard_False; |
234 | break; |
7fd59977 |
235 | } |
93442c6f |
236 | |
237 | if (Unified) |
238 | mySequence = theCurves; |
239 | else |
240 | UnifyBySettingMiddleKnots(mySequence); |
7fd59977 |
241 | |
242 | myIsDone = Standard_True; |
243 | } |
244 | |
245 | |
246 | //======================================================================= |
247 | //function : Degree |
248 | //purpose : |
249 | //======================================================================= |
250 | |
251 | Standard_Integer GeomFill_Profiler::Degree() const |
252 | { |
253 | if ( !myIsDone) |
254 | StdFail_NotDone::Raise("GeomFill_Profiler::Degree"); |
255 | |
256 | Handle(Geom_BSplineCurve) C = |
257 | Handle(Geom_BSplineCurve)::DownCast(mySequence(1)); |
258 | return C->Degree(); |
259 | } |
260 | |
261 | |
262 | //======================================================================= |
263 | //function : NbPoles |
264 | //purpose : |
265 | //======================================================================= |
266 | |
267 | Standard_Integer GeomFill_Profiler::NbPoles() const |
268 | { |
269 | if ( !myIsDone) |
270 | StdFail_NotDone::Raise("GeomFill_Profiler::Degree"); |
271 | |
272 | Handle(Geom_BSplineCurve) C = |
273 | Handle(Geom_BSplineCurve)::DownCast(mySequence(1)); |
274 | return C->NbPoles(); |
275 | } |
276 | |
277 | |
278 | //======================================================================= |
279 | //function : Poles |
280 | //purpose : |
281 | //======================================================================= |
282 | |
283 | void GeomFill_Profiler::Poles(const Standard_Integer Index, |
284 | TColgp_Array1OfPnt& Poles) const |
285 | { |
286 | if ( !myIsDone) |
287 | StdFail_NotDone::Raise("GeomFill_Profiler::Degree"); |
288 | |
289 | Standard_DomainError_Raise_if( Poles.Length() != NbPoles(), |
290 | "GeomFill_Profiler::Poles"); |
291 | Standard_DomainError_Raise_if( Index < 1 || Index > mySequence.Length(), |
292 | "GeomFill_Profiler::Poles"); |
293 | |
294 | Handle(Geom_BSplineCurve) C = |
295 | Handle(Geom_BSplineCurve)::DownCast(mySequence(Index)); |
296 | |
297 | C->Poles(Poles); |
298 | } |
299 | |
300 | |
301 | //======================================================================= |
302 | //function : Weights |
303 | //purpose : |
304 | //======================================================================= |
305 | |
306 | void GeomFill_Profiler::Weights(const Standard_Integer Index, |
307 | TColStd_Array1OfReal& Weights) const |
308 | { |
309 | if ( !myIsDone) |
310 | StdFail_NotDone::Raise("GeomFill_Profiler::Degree"); |
311 | |
312 | Standard_DomainError_Raise_if( Weights.Length() != NbPoles(), |
313 | "GeomFill_Profiler::Weights"); |
314 | Standard_DomainError_Raise_if( Index < 1 || Index > mySequence.Length(), |
315 | "GeomFill_Profiler::Weights"); |
316 | |
317 | Handle(Geom_BSplineCurve) C = |
318 | Handle(Geom_BSplineCurve)::DownCast(mySequence(Index)); |
319 | |
320 | C->Weights(Weights); |
321 | } |
322 | |
323 | |
324 | //======================================================================= |
325 | //function : NbKnots |
326 | //purpose : |
327 | //======================================================================= |
328 | |
329 | Standard_Integer GeomFill_Profiler::NbKnots() const |
330 | { |
331 | if ( !myIsDone) |
332 | StdFail_NotDone::Raise("GeomFill_Profiler::Degree"); |
333 | |
334 | Handle(Geom_BSplineCurve) C = |
335 | Handle(Geom_BSplineCurve)::DownCast(mySequence(1)); |
336 | |
337 | return C->NbKnots(); |
338 | } |
339 | |
340 | |
341 | //======================================================================= |
342 | //function : KnotsAndMults |
343 | //purpose : |
344 | //======================================================================= |
345 | |
346 | void GeomFill_Profiler::KnotsAndMults(TColStd_Array1OfReal& Knots, |
347 | TColStd_Array1OfInteger& Mults ) const |
348 | { |
349 | if ( !myIsDone) |
350 | StdFail_NotDone::Raise("GeomFill_Profiler::Degree"); |
351 | |
352 | #ifndef No_Exception |
353 | Standard_Integer n = NbKnots(); |
354 | #endif |
355 | Standard_DomainError_Raise_if( Knots.Length() != n || Mults.Length() != n, |
356 | "GeomFill_Profiler::KnotsAndMults"); |
357 | |
358 | Handle(Geom_BSplineCurve) C = |
359 | Handle(Geom_BSplineCurve)::DownCast(mySequence(1)); |
360 | |
361 | C->Knots(Knots); |
362 | C->Multiplicities(Mults); |
363 | } |
364 | |
365 | |