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
6 // This file is part of Open CASCADE Technology software library.
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.
14 // Alternatively, this file may be used under the terms of Open CASCADE
15 // commercial license or contractual agreement.
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>
29 //=======================================================================
30 //function : UnifyByInsertingAllKnots
32 //=======================================================================
33 void UnifyByInsertingAllKnots(TColGeom_SequenceOfCurve& theCurves,
34 const Standard_Real PTol)
36 // inserting in the first curve the knot-vector of all the others.
37 Handle(Geom_BSplineCurve) C = Handle(Geom_BSplineCurve)::DownCast(theCurves(1));
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());
45 TColStd_Array1OfInteger Mi(1,Ci->NbKnots());
46 Ci->Multiplicities(Mi);
48 C->InsertKnots( Ki, Mi, PTol, Standard_False);
51 TColStd_Array1OfReal NewKnots(1,C->NbKnots());
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);
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.;
69 for ( j = 1; j <= np; j++) {
70 sigma += Ci->Weight(j);
73 for ( j= 1; j<= np; j++) {
74 Ci->SetWeight(j,Ci->Weight(j) / sigma);
81 //=======================================================================
82 //function : UnifyBySettingMiddleKnots
84 //=======================================================================
85 void UnifyBySettingMiddleKnots(TColGeom_SequenceOfCurve& theCurves)
87 Standard_Integer i, j;
89 Handle(Geom_BSplineCurve) C = Handle(Geom_BSplineCurve)::DownCast(theCurves(1));
91 Standard_Integer NbKnots = C->NbKnots();
92 Standard_Real ULast = C->Knot(C->LastUKnotIndex());
93 Standard_Real UFirst = C->Knot(C->FirstUKnotIndex());
95 //Set middle values of knots
96 TColStd_Array1OfReal NewKnots(1, NbKnots);
98 NewKnots(NbKnots) = ULast;
99 for (j = 2; j < NbKnots; j++)
101 Standard_Real aMidKnot = 0.;
102 for (i = 1; i <= theCurves.Length(); i++)
104 Handle(Geom_BSplineCurve) Ctemp = Handle(Geom_BSplineCurve)::DownCast(theCurves(i));
105 aMidKnot += Ctemp->Knot(j);
107 aMidKnot /= theCurves.Length();
108 NewKnots(j) = aMidKnot;
111 for (i = 1; i <= theCurves.Length(); i++)
113 Handle(Geom_BSplineCurve) Cres = Handle(Geom_BSplineCurve)::DownCast(theCurves(i));
114 Cres->SetKnots(NewKnots);
118 //=======================================================================
119 //function : GeomFill_Profiler
121 //=======================================================================
123 GeomFill_Profiler::GeomFill_Profiler()
125 myIsDone = Standard_False;
126 myIsPeriodic = Standard_True;
130 //=======================================================================
132 GeomFill_Profiler::~GeomFill_Profiler()
137 //=======================================================================
138 //function : AddCurve
140 //=======================================================================
142 void GeomFill_Profiler::AddCurve(const Handle(Geom_Curve)& Curve)
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)))
151 GeomConvert_ApproxCurve appr(Curve, Precision::Confusion(), GeomAbs_C1, 16, 14);
152 if (appr.HasResult())
156 C = GeomConvert::CurveToBSplineCurve(Curve);
158 if ( Curve->IsKind(STANDARD_TYPE(Geom_BSplineCurve))) {
159 C = Handle(Geom_Curve)::DownCast(Curve->Copy());
162 C = GeomConvert::CurveToBSplineCurve(Curve,Convert_QuasiAngular);
165 ///////////////////////////////////////////////
167 mySequence.Append( C);
169 if ( myIsPeriodic && !C->IsPeriodic())
170 myIsPeriodic = Standard_False;
174 //=======================================================================
177 //=======================================================================
179 void GeomFill_Profiler::Perform(const Standard_Real PTol)
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.;
188 for ( i = 1; i <= mySequence.Length(); i++) {
189 C = Handle(Geom_BSplineCurve)::DownCast(mySequence(i));
191 // si non periodique, il faut deperiodiser toutes les courbes
192 // on les segmente ensuite pour assurer K(1) et K(n) de multiplicite
195 U2 = C->Knot(C->LastUKnotIndex());
196 U1 = C->Knot(C->FirstUKnotIndex());
198 if ( !myIsPeriodic && C->IsPeriodic()) {
203 // evaluate the max degree
204 myDegree = Max( myDegree, C->Degree());
206 // Calcul de Max ( Ufin - Udeb) sur l ensemble des courbes.
207 if ( ( U2 - U1) > EcartMax) {
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));
219 C->IncreaseDegree( myDegree);
221 TColStd_Array1OfReal Knots(1,C->NbKnots());
223 BSplCLib::Reparametrize(UFirst,ULast,Knots);
227 TColGeom_SequenceOfCurve theCurves;
228 for (i = 1; i <= mySequence.Length(); i++)
229 theCurves.Append(Handle(Geom_Curve)::DownCast(mySequence(i)->Copy()));
231 UnifyByInsertingAllKnots(theCurves, PTol);
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)
238 Unified = Standard_False;
243 mySequence = theCurves;
245 UnifyBySettingMiddleKnots(mySequence);
247 myIsDone = Standard_True;
251 //=======================================================================
254 //=======================================================================
256 Standard_Integer GeomFill_Profiler::Degree() const
259 throw StdFail_NotDone("GeomFill_Profiler::Degree");
261 Handle(Geom_BSplineCurve) C =
262 Handle(Geom_BSplineCurve)::DownCast(mySequence(1));
267 //=======================================================================
270 //=======================================================================
272 Standard_Integer GeomFill_Profiler::NbPoles() const
275 throw StdFail_NotDone("GeomFill_Profiler::Degree");
277 Handle(Geom_BSplineCurve) C =
278 Handle(Geom_BSplineCurve)::DownCast(mySequence(1));
283 //=======================================================================
286 //=======================================================================
288 void GeomFill_Profiler::Poles(const Standard_Integer Index,
289 TColgp_Array1OfPnt& Poles) const
292 throw StdFail_NotDone("GeomFill_Profiler::Degree");
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");
299 Handle(Geom_BSplineCurve) C =
300 Handle(Geom_BSplineCurve)::DownCast(mySequence(Index));
306 //=======================================================================
309 //=======================================================================
311 void GeomFill_Profiler::Weights(const Standard_Integer Index,
312 TColStd_Array1OfReal& Weights) const
315 throw StdFail_NotDone("GeomFill_Profiler::Degree");
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");
322 Handle(Geom_BSplineCurve) C =
323 Handle(Geom_BSplineCurve)::DownCast(mySequence(Index));
329 //=======================================================================
332 //=======================================================================
334 Standard_Integer GeomFill_Profiler::NbKnots() const
337 throw StdFail_NotDone("GeomFill_Profiler::Degree");
339 Handle(Geom_BSplineCurve) C =
340 Handle(Geom_BSplineCurve)::DownCast(mySequence(1));
346 //=======================================================================
347 //function : KnotsAndMults
349 //=======================================================================
351 void GeomFill_Profiler::KnotsAndMults(TColStd_Array1OfReal& Knots,
352 TColStd_Array1OfInteger& Mults ) const
355 throw StdFail_NotDone("GeomFill_Profiler::Degree");
358 Standard_Integer n = NbKnots();
360 Standard_DomainError_Raise_if( Knots.Length() != n || Mults.Length() != n,
361 "GeomFill_Profiler::KnotsAndMults");
363 Handle(Geom_BSplineCurve) C =
364 Handle(Geom_BSplineCurve)::DownCast(mySequence(1));
367 C->Multiplicities(Mults);