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