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