0024023: Revamp the OCCT Handle -- downcast (automatic)
[occt.git] / src / GeomFill / GeomFill_Profiler.cxx
CommitLineData
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>
ec357c5c 24#include <Geom_Curve.hxx>
7fd59977 25
93442c6f 26//=======================================================================
27//function : UnifyByInsertingAllKnots
28//purpose :
29//=======================================================================
30void 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//=======================================================================
82void 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}
7fd59977 114
115//=======================================================================
116//function : GeomFill_Profiler
117//purpose :
118//=======================================================================
119
120GeomFill_Profiler::GeomFill_Profiler()
121{
122 myIsDone = Standard_False;
123 myIsPeriodic = Standard_True;
124}
125
126
127//=======================================================================
128
6da30ff1 129GeomFill_Profiler::~GeomFill_Profiler()
130{
131}
7fd59977 132
133
134//=======================================================================
135//function : AddCurve
136//purpose :
137//=======================================================================
138
139void 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)))
c5f3a425 145 theCurve = Handle(Geom_TrimmedCurve)::DownCast (theCurve)->BasisCurve();
7fd59977 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
176void 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 }
7fd59977 223
93442c6f 224 TColGeom_SequenceOfCurve theCurves;
225 for (i = 1; i <= mySequence.Length(); i++)
226 theCurves.Append(Handle(Geom_Curve)::DownCast(mySequence(i)->Copy()));
7fd59977 227
93442c6f 228 UnifyByInsertingAllKnots(theCurves, PTol);
7fd59977 229
93442c6f 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;
7fd59977 237 }
93442c6f 238
239 if (Unified)
240 mySequence = theCurves;
241 else
242 UnifyBySettingMiddleKnots(mySequence);
7fd59977 243
244 myIsDone = Standard_True;
245}
246
247
248//=======================================================================
249//function : Degree
250//purpose :
251//=======================================================================
252
253Standard_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
269Standard_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
285void 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
308void 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
331Standard_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
348void 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