Warnings on vc14 were eliminated
[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
18 #include <BSplCLib.hxx>
19 #include <Geom_BSplineCurve.hxx>
20 #include <Geom_Conic.hxx>
21 #include <Geom_Curve.hxx>
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>
28
29 //=======================================================================
30 //function : UnifyByInsertingAllKnots
31 //purpose  : 
32 //=======================================================================
33 void UnifyByInsertingAllKnots(TColGeom_SequenceOfCurve& theCurves,
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 //=======================================================================
85 void UnifyBySettingMiddleKnots(TColGeom_SequenceOfCurve& theCurves)
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     {
104       Handle(Geom_BSplineCurve) Ctemp = Handle(Geom_BSplineCurve)::DownCast(theCurves(i));
105       aMidKnot += Ctemp->Knot(j);
106     }
107     aMidKnot /= theCurves.Length();
108     NewKnots(j) = aMidKnot;
109   }
110
111   for (i = 1; i <= theCurves.Length(); i++)
112   {
113     Handle(Geom_BSplineCurve) Cres = Handle(Geom_BSplineCurve)::DownCast(theCurves(i));
114     Cres->SetKnots(NewKnots);
115   }
116 }
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
132 GeomFill_Profiler::~GeomFill_Profiler()
133 {
134 }
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)))
148     theCurve = Handle(Geom_TrimmedCurve)::DownCast (theCurve)->BasisCurve();
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   }
226
227   TColGeom_SequenceOfCurve theCurves;
228   for (i = 1; i <= mySequence.Length(); i++)
229     theCurves.Append(Handle(Geom_Curve)::DownCast(mySequence(i)->Copy()));
230
231   UnifyByInsertingAllKnots(theCurves, PTol);
232
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;
240     }
241   
242   if (Unified)
243     mySequence = theCurves;
244   else
245     UnifyBySettingMiddleKnots(mySequence);
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)
259     throw StdFail_NotDone("GeomFill_Profiler::Degree");
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)
275     throw StdFail_NotDone("GeomFill_Profiler::Degree");
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)
292     throw StdFail_NotDone("GeomFill_Profiler::Degree");
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)
315     throw StdFail_NotDone("GeomFill_Profiler::Degree");
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)
337     throw StdFail_NotDone("GeomFill_Profiler::Degree");
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)
355     throw StdFail_NotDone("GeomFill_Profiler::Degree");
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