0023948: Wrong intersection between a surface of revolution and a plane.
[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
25
26 //=======================================================================
27 //function : GeomFill_Profiler
28 //purpose  : 
29 //=======================================================================
30
31 GeomFill_Profiler::GeomFill_Profiler()
32 {
33   myIsDone = Standard_False;
34   myIsPeriodic = Standard_True;
35 }
36
37
38 //=======================================================================
39
40 void GeomFill_Profiler::Delete()
41 {}
42
43
44 //=======================================================================
45 //function : AddCurve
46 //purpose  : 
47 //=======================================================================
48
49 void GeomFill_Profiler::AddCurve(const Handle(Geom_Curve)& Curve)
50 {
51   Handle(Geom_Curve) C;
52   //// modified by jgv, 19.01.05 for OCC7354 ////
53   Handle(Geom_Curve) theCurve = Curve;
54   if (theCurve->IsInstance(STANDARD_TYPE(Geom_TrimmedCurve)))
55     theCurve = (*((Handle(Geom_TrimmedCurve)*)&theCurve))->BasisCurve();
56   if (theCurve->IsKind(STANDARD_TYPE(Geom_Conic)))
57     {
58       GeomConvert_ApproxCurve appr(Curve, Precision::Confusion(), GeomAbs_C1, 16, 14);
59       if (appr.HasResult())
60         C = appr.Curve();
61     }
62   if (C.IsNull())
63     C = GeomConvert::CurveToBSplineCurve(Curve);
64   /*
65   if ( Curve->IsKind(STANDARD_TYPE(Geom_BSplineCurve))) {
66     C = Handle(Geom_Curve)::DownCast(Curve->Copy());
67   }
68   else {
69     C = GeomConvert::CurveToBSplineCurve(Curve,Convert_QuasiAngular);
70   }
71   */
72   ///////////////////////////////////////////////
73
74   mySequence.Append( C);
75
76   if ( myIsPeriodic && !C->IsPeriodic())
77     myIsPeriodic = Standard_False;
78 }
79
80
81 //=======================================================================
82 //function : Perform
83 //purpose  : 
84 //=======================================================================
85
86 void GeomFill_Profiler::Perform(const Standard_Real PTol)
87 {
88   Standard_Integer i;
89 //  Standard_Integer myDegree = 0, myNbPoles = 0;
90   Standard_Integer myDegree = 0;
91   Handle(Geom_BSplineCurve) C;
92   Standard_Real U1, U2, UFirst=0, ULast=0;
93   Standard_Real EcartMax = 0.;
94
95   for ( i = 1; i <= mySequence.Length(); i++) {
96     C = Handle(Geom_BSplineCurve)::DownCast(mySequence(i));
97
98     // si non periodique, il faut deperiodiser toutes les courbes
99     // on les segmente ensuite pour assurer K(1) et K(n) de multiplicite
100     // degre + 1
101
102     U2 = C->Knot(C->LastUKnotIndex());
103     U1 = C->Knot(C->FirstUKnotIndex());
104
105     if ( !myIsPeriodic && C->IsPeriodic()) {
106       C->SetNotPeriodic();
107       C->Segment( U1, U2);
108     }
109
110     // evaluate the max degree
111     myDegree = Max( myDegree, C->Degree());
112     
113     // Calcul de Max ( Ufin - Udeb) sur l ensemble des courbes.
114     if ( ( U2 - U1) > EcartMax) {
115       EcartMax = U2 - U1;
116       UFirst = U1;
117       ULast  = U2;
118     }
119   }
120   
121   // increase the degree of the curves to my degree
122   // reparametrize them in the range U1, U2.
123   for ( i = 1; i <= mySequence.Length(); i++) {
124     C = Handle(Geom_BSplineCurve)::DownCast(mySequence(i));
125
126     C->IncreaseDegree( myDegree);
127
128     TColStd_Array1OfReal Knots(1,C->NbKnots());
129     C->Knots(Knots);
130     BSplCLib::Reparametrize(UFirst,ULast,Knots);
131     C->SetKnots(Knots);
132   }
133   
134   // inserting in the first curve the knot-vector of all the others.
135   C = Handle(Geom_BSplineCurve)::DownCast(mySequence(1));
136
137   for ( i = 2; i <= mySequence.Length(); i++) {
138     Handle(Geom_BSplineCurve) Ci = 
139       Handle(Geom_BSplineCurve)::DownCast(mySequence(i));
140     TColStd_Array1OfReal Ki(1,Ci->NbKnots());
141     Ci->Knots(Ki);
142     TColStd_Array1OfInteger Mi(1,Ci->NbKnots());
143     Ci->Multiplicities(Mi);
144
145     C->InsertKnots( Ki, Mi, PTol, Standard_False);
146   }
147
148   TColStd_Array1OfReal NewKnots(1,C->NbKnots());
149   C->Knots(NewKnots);
150   TColStd_Array1OfInteger NewMults(1,C->NbKnots());
151   C->Multiplicities(NewMults);
152   for ( i = 2; i <= mySequence.Length(); i++) {
153     Handle(Geom_BSplineCurve) Ci = 
154       Handle(Geom_BSplineCurve)::DownCast(mySequence(i));
155     Ci->InsertKnots(NewKnots, NewMults, PTol, Standard_False);
156   }
157
158   // essai : tentative mise des poids sur chaque section a une moyenne 1
159   for ( i = 1; i <= mySequence.Length(); i++) {
160     Handle(Geom_BSplineCurve) Ci = 
161       Handle(Geom_BSplineCurve)::DownCast(mySequence(i));
162     if ( Ci->IsRational() ) {
163       Standard_Integer np = Ci->NbPoles();
164       Standard_Real sigma = 0.;
165       Standard_Integer j;
166       for ( j = 1; j <= np; j++) {
167         sigma += Ci->Weight(j);
168       }
169       sigma /= np;
170       for ( j= 1; j<= np; j++) {
171         Ci->SetWeight(j,Ci->Weight(j) / sigma);
172       }
173     }
174   }
175   // fin de l essai
176
177   myIsDone = Standard_True;
178 }
179
180
181 //=======================================================================
182 //function : Degree
183 //purpose  : 
184 //=======================================================================
185
186 Standard_Integer GeomFill_Profiler::Degree() const 
187 {
188   if ( !myIsDone)
189     StdFail_NotDone::Raise("GeomFill_Profiler::Degree");
190
191   Handle(Geom_BSplineCurve) C = 
192     Handle(Geom_BSplineCurve)::DownCast(mySequence(1));
193   return C->Degree();
194 }
195
196
197 //=======================================================================
198 //function : NbPoles
199 //purpose  : 
200 //=======================================================================
201
202 Standard_Integer GeomFill_Profiler::NbPoles() const 
203 {
204   if ( !myIsDone)
205     StdFail_NotDone::Raise("GeomFill_Profiler::Degree");
206
207   Handle(Geom_BSplineCurve) C = 
208     Handle(Geom_BSplineCurve)::DownCast(mySequence(1));
209   return C->NbPoles();
210 }
211
212
213 //=======================================================================
214 //function : Poles
215 //purpose  : 
216 //=======================================================================
217
218 void GeomFill_Profiler::Poles(const Standard_Integer Index, 
219                                     TColgp_Array1OfPnt& Poles) const 
220 {
221   if ( !myIsDone)
222     StdFail_NotDone::Raise("GeomFill_Profiler::Degree");
223
224   Standard_DomainError_Raise_if( Poles.Length() != NbPoles(),
225                                 "GeomFill_Profiler::Poles");
226   Standard_DomainError_Raise_if( Index < 1 || Index > mySequence.Length(),
227                                 "GeomFill_Profiler::Poles");
228
229   Handle(Geom_BSplineCurve) C = 
230     Handle(Geom_BSplineCurve)::DownCast(mySequence(Index));
231
232   C->Poles(Poles);
233 }
234
235
236 //=======================================================================
237 //function : Weights
238 //purpose  : 
239 //=======================================================================
240
241 void GeomFill_Profiler::Weights(const Standard_Integer      Index, 
242                                       TColStd_Array1OfReal& Weights) const 
243 {
244   if ( !myIsDone)
245     StdFail_NotDone::Raise("GeomFill_Profiler::Degree");
246
247   Standard_DomainError_Raise_if( Weights.Length() != NbPoles(),
248                                 "GeomFill_Profiler::Weights");
249   Standard_DomainError_Raise_if( Index < 1 || Index > mySequence.Length(),
250                                 "GeomFill_Profiler::Weights");
251
252   Handle(Geom_BSplineCurve) C = 
253     Handle(Geom_BSplineCurve)::DownCast(mySequence(Index));
254
255   C->Weights(Weights);
256 }
257
258
259 //=======================================================================
260 //function : NbKnots
261 //purpose  : 
262 //=======================================================================
263
264 Standard_Integer GeomFill_Profiler::NbKnots() const 
265 {
266   if ( !myIsDone)
267     StdFail_NotDone::Raise("GeomFill_Profiler::Degree");
268
269   Handle(Geom_BSplineCurve) C = 
270     Handle(Geom_BSplineCurve)::DownCast(mySequence(1));
271
272   return C->NbKnots();
273 }
274
275
276 //=======================================================================
277 //function : KnotsAndMults
278 //purpose  : 
279 //=======================================================================
280
281 void GeomFill_Profiler::KnotsAndMults(TColStd_Array1OfReal&    Knots, 
282                                       TColStd_Array1OfInteger& Mults ) const 
283 {
284   if ( !myIsDone)
285     StdFail_NotDone::Raise("GeomFill_Profiler::Degree");
286
287 #ifndef No_Exception
288   Standard_Integer n = NbKnots();
289 #endif
290   Standard_DomainError_Raise_if( Knots.Length() != n  || Mults.Length() != n,
291                                 "GeomFill_Profiler::KnotsAndMults");
292
293   Handle(Geom_BSplineCurve) C = 
294     Handle(Geom_BSplineCurve)::DownCast(mySequence(1));
295
296   C->Knots(Knots);
297   C->Multiplicities(Mults);
298 }
299
300